From 2378cbe36bd5d42611bc62498cd25cb819f9034f Mon Sep 17 00:00:00 2001 From: James Almer Date: Fri, 13 Jan 2023 18:34:26 -0300 Subject: [PATCH 0001/2172] avfilter/vf_showinfo: add support for Ambient Viewing Environment side data Reviewed-by: Stefano Sabatini Signed-off-by: James Almer --- libavfilter/vf_showinfo.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/libavfilter/vf_showinfo.c b/libavfilter/vf_showinfo.c index d5edbd2f0ac..e55625b3382 100644 --- a/libavfilter/vf_showinfo.c +++ b/libavfilter/vf_showinfo.c @@ -42,6 +42,7 @@ #include "libavutil/mastering_display_metadata.h" #include "libavutil/video_enc_params.h" #include "libavutil/detection_bbox.h" +#include "libavutil/ambient_viewing_environment.h" #include "libavutil/uuid.h" #include "avfilter.h" @@ -601,6 +602,17 @@ static void dump_dovi_metadata(AVFilterContext *ctx, const AVFrameSideData *sd) av_log(ctx, AV_LOG_INFO, "source_diagonal=%"PRIu16"; ", color->source_diagonal); } +static void dump_ambient_viewing_environment(AVFilterContext *ctx, const AVFrameSideData *sd) +{ + const AVAmbientViewingEnvironment *ambient_viewing_environment = + (const AVAmbientViewingEnvironment *)sd->data; + + av_log(ctx, AV_LOG_INFO, "ambient_illuminance=%f, ambient_light_x=%f, ambient_light_y=%f", + av_q2d(ambient_viewing_environment->ambient_illuminance), + av_q2d(ambient_viewing_environment->ambient_light_x), + av_q2d(ambient_viewing_environment->ambient_light_y)); +} + static void dump_color_property(AVFilterContext *ctx, AVFrame *frame) { const char *color_range_str = av_color_range_name(frame->color_range); @@ -797,6 +809,9 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *frame) case AV_FRAME_DATA_DOVI_METADATA: dump_dovi_metadata(ctx, sd); break; + case AV_FRAME_DATA_AMBIENT_VIEWING_ENVIRONMENT: + dump_ambient_viewing_environment(ctx, sd); + break; default: if (name) av_log(ctx, AV_LOG_INFO, From e7755b433e913e32bb061f17d5ecfcbcfef995b7 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Wed, 11 Jan 2023 23:05:55 +0100 Subject: [PATCH 0002/2172] avcodec/eatgq: : Check index increments in tgq_decode_block() Fixes: out of array access Fixes: 48567/clusterfuzz-testcase-minimized-ffmpeg_AV_CODEC_ID_EATGQ_fuzzer-6743211456724992 Found-by: continuous fuzzing process https://github.com/google/oss-fuzz/tree/master/projects/ffmpeg Signed-off-by: Michael Niedermayer --- libavcodec/eatgq.c | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/libavcodec/eatgq.c b/libavcodec/eatgq.c index 89e9f20880a..01e1acd4e42 100644 --- a/libavcodec/eatgq.c +++ b/libavcodec/eatgq.c @@ -56,7 +56,7 @@ static av_cold int tgq_decode_init(AVCodecContext *avctx) return 0; } -static void tgq_decode_block(TgqContext *s, int16_t block[64], GetBitContext *gb) +static int tgq_decode_block(TgqContext *s, int16_t block[64], GetBitContext *gb) { const uint8_t *scantable = ff_zigzag_direct; int i, j, value; @@ -64,6 +64,8 @@ static void tgq_decode_block(TgqContext *s, int16_t block[64], GetBitContext *gb for (i = 1; i < 64;) { switch (show_bits(gb, 3)) { case 4: + if (i >= 63) + return AVERROR_INVALIDDATA; block[scantable[i++]] = 0; case 0: block[scantable[i++]] = 0; @@ -73,6 +75,8 @@ static void tgq_decode_block(TgqContext *s, int16_t block[64], GetBitContext *gb case 1: skip_bits(gb, 2); value = get_bits(gb, 6); + if (value > 64 - i) + return AVERROR_INVALIDDATA; for (j = 0; j < value; j++) block[scantable[i++]] = 0; break; @@ -100,6 +104,7 @@ static void tgq_decode_block(TgqContext *s, int16_t block[64], GetBitContext *gb } } block[0] += 128 << 4; + return 0; } static void tgq_idct_put_mb(TgqContext *s, int16_t (*block)[64], AVFrame *frame, @@ -160,8 +165,11 @@ static int tgq_decode_mb(TgqContext *s, GetByteContext *gbyte, if (ret < 0) return ret; - for (i = 0; i < 6; i++) - tgq_decode_block(s, s->block[i], &gb); + for (i = 0; i < 6; i++) { + int ret = tgq_decode_block(s, s->block[i], &gb); + if (ret < 0) + return ret; + } tgq_idct_put_mb(s, s->block, frame, mb_x, mb_y); bytestream2_skip(gbyte, mode); } else { From 1ab0f83b0a243c635d77f8b116646bb7594988d4 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Thu, 12 Jan 2023 21:23:21 +0100 Subject: [PATCH 0003/2172] avcodec/wbmpdec: use remaining size not whole size Fixes: out of array access Fixes: 48567/clusterfuzz-testcase-minimized-ffmpeg_AV_CODEC_ID_WBMP_fuzzer-6652634692190208 Fixes: 48567/clusterfuzz-testcase-minimized-ffmpeg_AV_CODEC_ID_WBMP_fuzzer-6653703453278208 Fixes: 48567/clusterfuzz-testcase-minimized-ffmpeg_AV_CODEC_ID_WBMP_fuzzer-6668020758216704 Fixes: 48567/clusterfuzz-testcase-minimized-ffmpeg_AV_CODEC_ID_WBMP_fuzzer-6684749875249152 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/wbmpdec.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavcodec/wbmpdec.c b/libavcodec/wbmpdec.c index 9638b55b943..8b105bc1352 100644 --- a/libavcodec/wbmpdec.c +++ b/libavcodec/wbmpdec.c @@ -72,7 +72,7 @@ static int wbmp_decode_frame(AVCodecContext *avctx, AVFrame *p, if (p->linesize[0] == (width + 7) / 8) bytestream2_get_buffer(&gb, p->data[0], height * ((width + 7) / 8)); else - readbits(p->data[0], width, height, p->linesize[0], gb.buffer, gb.buffer_end - gb.buffer_start); + readbits(p->data[0], width, height, p->linesize[0], gb.buffer, gb.buffer_end - gb.buffer); p->key_frame = 1; p->pict_type = AV_PICTURE_TYPE_I; From ac7d21284bd3c2b7f7c6d15db450e4c58e93fef8 Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Sun, 8 Jan 2023 13:53:39 +0100 Subject: [PATCH 0004/2172] avfilter: add fractional delay IR source filter --- Changelog | 1 + doc/filters.texi | 27 ++++++ libavfilter/Makefile | 1 + libavfilter/allfilters.c | 1 + libavfilter/asrc_afdelaysrc.c | 173 ++++++++++++++++++++++++++++++++++ libavfilter/version.h | 2 +- 6 files changed, 204 insertions(+), 1 deletion(-) create mode 100644 libavfilter/asrc_afdelaysrc.c diff --git a/Changelog b/Changelog index 179f63c7d53..5c01e8365ed 100644 --- a/Changelog +++ b/Changelog @@ -28,6 +28,7 @@ version : - showcwt multimedia filter - corr video filter - adrc audio filter +- afdelaysrc audio filter version 5.1: diff --git a/doc/filters.texi b/doc/filters.texi index 57088ccc6c4..be70a2396ba 100644 --- a/doc/filters.texi +++ b/doc/filters.texi @@ -7519,6 +7519,33 @@ aevalsrc="0.1*sin(2*PI*(360-2.5/2)*t) | 0.1*sin(2*PI*(360+2.5/2)*t)" @end itemize +@section afdelaysrc + +Generate a fractional delay FIR coefficients. + +The resulting stream can be used with @ref{afir} filter for filtering the audio signal. + +The filter accepts the following options: + +@table @option +@item delay, d +Set the fractional delay. Default is 0. + +@item sample_rate, r +Set the sample rate, default is 44100. + +@item nb_samples, n +Set the number of samples per each frame. Default is 1024. + +@item taps, t +Set the number of filter coefficents in output audio stream. +Default value is 0. + +@item channel_layout, c +Specifies the channel layout, and can be a string representing a channel layout. +The default value of @var{channel_layout} is "stereo". +@end table + @section afirsrc Generate a FIR coefficients using frequency sampling method. diff --git a/libavfilter/Makefile b/libavfilter/Makefile index 5783be281d1..211ff4daaa3 100644 --- a/libavfilter/Makefile +++ b/libavfilter/Makefile @@ -171,6 +171,7 @@ OBJS-$(CONFIG_VOLUME_FILTER) += af_volume.o OBJS-$(CONFIG_VOLUMEDETECT_FILTER) += af_volumedetect.o OBJS-$(CONFIG_AEVALSRC_FILTER) += aeval.o +OBJS-$(CONFIG_AFDELAYSRC_FILTER) += asrc_afdelaysrc.o OBJS-$(CONFIG_AFIRSRC_FILTER) += asrc_afirsrc.o OBJS-$(CONFIG_ANOISESRC_FILTER) += asrc_anoisesrc.o OBJS-$(CONFIG_ANULLSRC_FILTER) += asrc_anullsrc.o diff --git a/libavfilter/allfilters.c b/libavfilter/allfilters.c index 52741b60e4d..1ab3c8319a4 100644 --- a/libavfilter/allfilters.c +++ b/libavfilter/allfilters.c @@ -159,6 +159,7 @@ extern const AVFilter ff_af_volume; extern const AVFilter ff_af_volumedetect; extern const AVFilter ff_asrc_aevalsrc; +extern const AVFilter ff_asrc_afdelaysrc; extern const AVFilter ff_asrc_afirsrc; extern const AVFilter ff_asrc_anoisesrc; extern const AVFilter ff_asrc_anullsrc; diff --git a/libavfilter/asrc_afdelaysrc.c b/libavfilter/asrc_afdelaysrc.c new file mode 100644 index 00000000000..2fc57cee4d2 --- /dev/null +++ b/libavfilter/asrc_afdelaysrc.c @@ -0,0 +1,173 @@ +/* + * Copyright (c) 2023 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 "libavutil/avassert.h" +#include "libavutil/channel_layout.h" +#include "libavutil/opt.h" + +#include "audio.h" +#include "avfilter.h" +#include "filters.h" +#include "internal.h" + +typedef struct AFDelaySrcContext { + const AVClass *class; + + double delay; + int sample_rate; + int nb_samples; + int nb_taps; + AVChannelLayout chlayout; + char *chlayout_str; + + int64_t pts; +} AFDelaySrcContext; + +static av_cold int init(AVFilterContext *ctx) +{ + AFDelaySrcContext *s = ctx->priv; + int ret; + + ret = ff_parse_channel_layout(&s->chlayout, NULL, s->chlayout_str, ctx); + if (ret < 0) + return ret; + + return 0; +} + +static float sincf(float x) +{ + if (x == 0.f) + return 1.f; + return sinf(M_PI * x) / (M_PI * x); +} + +static int activate(AVFilterContext *ctx) +{ + AVFilterLink *outlink = ctx->outputs[0]; + AFDelaySrcContext *s = ctx->priv; + AVFrame *frame = NULL; + int nb_samples; + float *dst; + + if (!ff_outlink_frame_wanted(outlink)) + return FFERROR_NOT_READY; + + nb_samples = FFMIN(s->nb_samples, s->nb_taps - s->pts); + if (nb_samples <= 0) { + ff_outlink_set_status(outlink, AVERROR_EOF, s->pts); + return 0; + } + + if (!(frame = ff_get_audio_buffer(outlink, nb_samples))) + return AVERROR(ENOMEM); + + dst = (float *)frame->extended_data[0]; + for (int n = 0; n < nb_samples; n++) { + float x = s->pts + n; + dst[n] = sincf(x - s->delay) * cosf(M_PI * (x - s->delay) / s->nb_taps) / sincf((x - s->delay) / s->nb_taps); + } + + for (int ch = 1; ch < frame->ch_layout.nb_channels; ch++) + memcpy(frame->extended_data[ch], dst, sizeof(*dst) * nb_samples); + + frame->pts = s->pts; + s->pts += nb_samples; + + return ff_filter_frame(outlink, frame); +} + +static int query_formats(AVFilterContext *ctx) +{ + AFDelaySrcContext *s = ctx->priv; + AVChannelLayout chlayouts[] = { s->chlayout, { 0 } }; + int sample_rates[] = { s->sample_rate, -1 }; + static const enum AVSampleFormat sample_fmts[] = { AV_SAMPLE_FMT_FLTP, + AV_SAMPLE_FMT_NONE }; + int ret = ff_set_common_formats_from_list(ctx, sample_fmts); + if (ret < 0) + return ret; + + ret = ff_set_common_channel_layouts_from_list(ctx, chlayouts); + if (ret < 0) + return ret; + + return ff_set_common_samplerates_from_list(ctx, sample_rates); +} + +static int config_output(AVFilterLink *outlink) +{ + AVFilterContext *ctx = outlink->src; + AFDelaySrcContext *s = ctx->priv; + + outlink->sample_rate = s->sample_rate; + s->pts = 0; + if (s->nb_taps <= 0) + s->nb_taps = s->delay * 8 + 1; + + return 0; +} + +static const AVFilterPad afdelaysrc_outputs[] = { + { + .name = "default", + .type = AVMEDIA_TYPE_AUDIO, + .config_props = config_output, + }, +}; + +static av_cold void uninit(AVFilterContext *ctx) +{ + AFDelaySrcContext *s = ctx->priv; + + av_channel_layout_uninit(&s->chlayout); +} + +#define AF AV_OPT_FLAG_AUDIO_PARAM|AV_OPT_FLAG_FILTERING_PARAM +#define OFFSET(x) offsetof(AFDelaySrcContext, x) + +static const AVOption afdelaysrc_options[] = { + { "delay", "set fractional delay", OFFSET(delay), AV_OPT_TYPE_DOUBLE,{.dbl=0}, 0, INT16_MAX, AF }, + { "d", "set fractional delay", OFFSET(delay), AV_OPT_TYPE_DOUBLE,{.dbl=0}, 0, INT16_MAX, AF }, + { "sample_rate", "set sample rate", OFFSET(sample_rate), AV_OPT_TYPE_INT, {.i64=44100}, 1, INT_MAX, AF }, + { "r", "set sample rate", OFFSET(sample_rate), AV_OPT_TYPE_INT, {.i64=44100}, 1, INT_MAX, AF }, + { "nb_samples", "set the number of samples per requested frame", OFFSET(nb_samples), AV_OPT_TYPE_INT, {.i64=1024}, 1, INT_MAX, AF }, + { "n", "set the number of samples per requested frame", OFFSET(nb_samples), AV_OPT_TYPE_INT, {.i64=1024}, 1, INT_MAX, AF }, + { "taps", "set number of taps for delay filter", OFFSET(nb_taps), AV_OPT_TYPE_INT, {.i64=0}, 0, 32768, AF }, + { "t", "set number of taps for delay filter", OFFSET(nb_taps), AV_OPT_TYPE_INT, {.i64=0}, 0, 32768, AF }, + { "channel_layout", "set channel layout", OFFSET(chlayout_str),AV_OPT_TYPE_STRING,{.str="stereo"},0, 0, AF }, + { "c", "set channel layout", OFFSET(chlayout_str),AV_OPT_TYPE_STRING,{.str="stereo"},0, 0, AF }, + { NULL } +}; + +AVFILTER_DEFINE_CLASS(afdelaysrc); + +const AVFilter ff_asrc_afdelaysrc = { + .name = "afdelaysrc", + .description = NULL_IF_CONFIG_SMALL("Generate a Fractional delay FIR coefficients."), + .priv_size = sizeof(AFDelaySrcContext), + .priv_class = &afdelaysrc_class, + .init = init, + .activate = activate, + .uninit = uninit, + .inputs = NULL, + FILTER_OUTPUTS(afdelaysrc_outputs), + FILTER_QUERY_FUNC(query_formats), +}; diff --git a/libavfilter/version.h b/libavfilter/version.h index 9fabc544b59..a56ba3bb6dd 100644 --- a/libavfilter/version.h +++ b/libavfilter/version.h @@ -31,7 +31,7 @@ #include "version_major.h" -#define LIBAVFILTER_VERSION_MINOR 53 +#define LIBAVFILTER_VERSION_MINOR 54 #define LIBAVFILTER_VERSION_MICRO 100 From 2524d0b33b3e23b23d45c45820601644ba51c7bf Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Thu, 12 Jan 2023 09:56:57 +0100 Subject: [PATCH 0005/2172] avformat/dtshddec: also read trailing padding in samples --- libavformat/dtshddec.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/libavformat/dtshddec.c b/libavformat/dtshddec.c index edd02b4561f..a3dea0668fe 100644 --- a/libavformat/dtshddec.c +++ b/libavformat/dtshddec.c @@ -55,7 +55,7 @@ static int dtshd_read_header(AVFormatContext *s) DTSHDDemuxContext *dtshd = s->priv_data; AVIOContext *pb = s->pb; uint64_t chunk_type, chunk_size; - int64_t duration, data_start; + int64_t duration, orig_nb_samples, data_start; AVStream *st; int ret; char *value; @@ -103,9 +103,12 @@ static int dtshd_read_header(AVFormatContext *s) duration = avio_rb32(pb); // num_frames duration *= avio_rb16(pb); // samples_per_frames st->duration = duration; - avio_skip(pb, 5); + orig_nb_samples = avio_rb32(pb); + orig_nb_samples <<= 8; + orig_nb_samples |= avio_r8(pb); st->codecpar->ch_layout.nb_channels = ff_dca_count_chs_for_mask(avio_rb16(pb)); st->codecpar->initial_padding = avio_rb16(pb); + st->codecpar->trailing_padding = FFMAX(st->duration - orig_nb_samples - st->codecpar->initial_padding, 0); avio_skip(pb, chunk_size - 21); break; case FILEINFO: From 01f46f18dbcdf323ceb4fdff7358cf3ca71366e6 Mon Sep 17 00:00:00 2001 From: Gyan Doshi Date: Sat, 7 Jan 2023 15:10:52 +0530 Subject: [PATCH 0006/2172] avformat/segment: calculate segment durations correctly. segment_time and segment_times are defined as duration specifications, not timestamps, so calculation of segment duration must account for initial timestamp. Fixed. FATE ref for segment-mp4-to-ts changed on account of avoiding premature segment cut at the end of the first segment. --- libavformat/segment.c | 15 +++++++++++++++ tests/ref/fate/segment-mp4-to-ts | 4 ++-- 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/libavformat/segment.c b/libavformat/segment.c index 0e6421ea5d2..80e4bf851c1 100644 --- a/libavformat/segment.c +++ b/libavformat/segment.c @@ -116,6 +116,7 @@ typedef struct SegmentContext { int64_t initial_offset; ///< initial timestamps offset, expressed in microseconds char *reference_stream_specifier; ///< reference stream specifier int reference_stream_index; + int64_t reference_stream_first_pts; ///< initial timestamp, expressed in microseconds int break_non_keyframes; int write_empty; @@ -746,6 +747,8 @@ static int seg_init(AVFormatContext *s) seg->reference_stream_index, av_get_media_type_string(s->streams[seg->reference_stream_index]->codecpar->codec_type)); + seg->reference_stream_first_pts = AV_NOPTS_VALUE; + seg->oformat = av_guess_format(seg->format, s->url, NULL); if (!seg->oformat) @@ -898,6 +901,18 @@ static int seg_write_packet(AVFormatContext *s, AVPacket *pkt) pkt->flags & AV_PKT_FLAG_KEY, pkt->stream_index == seg->reference_stream_index ? seg->frame_count : -1); + if (seg->reference_stream_first_pts == AV_NOPTS_VALUE && + pkt->stream_index == seg->reference_stream_index && + pkt->pts != AV_NOPTS_VALUE) { + seg->reference_stream_first_pts = av_rescale_q(pkt->pts, st->time_base, AV_TIME_BASE_Q); + } + + if (seg->reference_stream_first_pts != AV_NOPTS_VALUE) { + end_pts += (INT64_MAX - end_pts >= seg->reference_stream_first_pts) ? + seg->reference_stream_first_pts : + INT64_MAX - end_pts; + } + if (pkt->pts != AV_NOPTS_VALUE) pkt_pts_avtb = av_rescale_q(pkt->pts, st->time_base, AV_TIME_BASE_Q); diff --git a/tests/ref/fate/segment-mp4-to-ts b/tests/ref/fate/segment-mp4-to-ts index 54fcadb8460..29944162704 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=0x2, S=1, 1 +0, 61200, 61200, 3600, 809, 0x8d948a4e, F=0x0, 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 @@ -71,7 +71,7 @@ 0, 223200, 226800, 3600, 809, 0x84e37fee, F=0x0, S=1, 1 0, 226800, 244800, 3600, 4541, 0xd4e5c0de, F=0x0, S=1, 1 0, 230400, 237600, 3600, 1545, 0x0099fc98, F=0x0, S=1, 1 -0, 234000, 234000, 3600, 929, 0xfd72d049, F=0x0, S=1, 1 +0, 234000, 234000, 3600, 929, 0xfd72d049, F=0x2, S=1, 1 0, 237600, 241200, 3600, 829, 0xcfda9e96, F=0x0, S=1, 1 0, 241200, 259200, 3600, 24220, 0x5ca21d71, S=1, 1 0, 244800, 252000, 3600, 1422, 0xcde6cc34, F=0x0, S=1, 1 From 1f88fb80d5416a23fb164fa0cda4585d9a541d48 Mon Sep 17 00:00:00 2001 From: Haihao Xiang Date: Mon, 9 Jan 2023 16:56:26 +0800 Subject: [PATCH 0007/2172] lavc/qsvenc_jpeg: accept YUYV422 and BGRA in system memory Signed-off-by: Haihao Xiang --- libavcodec/qsvenc_jpeg.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/libavcodec/qsvenc_jpeg.c b/libavcodec/qsvenc_jpeg.c index 2469ef7c9fd..2add12adc90 100644 --- a/libavcodec/qsvenc_jpeg.c +++ b/libavcodec/qsvenc_jpeg.c @@ -89,6 +89,8 @@ const FFCodec ff_mjpeg_qsv_encoder = { .close = qsv_enc_close, .p.capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_HYBRID, .p.pix_fmts = (const enum AVPixelFormat[]){ AV_PIX_FMT_NV12, + AV_PIX_FMT_YUYV422, + AV_PIX_FMT_BGRA, AV_PIX_FMT_QSV, AV_PIX_FMT_NONE }, .p.priv_class = &class, From 24a8e1e126dbe4316df3097c0b4e0b91bb7abb88 Mon Sep 17 00:00:00 2001 From: Haihao Xiang Date: Mon, 9 Jan 2023 15:12:03 +0800 Subject: [PATCH 0008/2172] lavfi/vf_vpp_qsv: add "a", "dar" and "sar" variables Also fix the naming style in enum var_name. This is in preparation for reusing the code for other QSV filters. Signed-off-by: Haihao Xiang --- libavfilter/vf_vpp_qsv.c | 49 ++++++++++++++++++++++++---------------- 1 file changed, 29 insertions(+), 20 deletions(-) diff --git a/libavfilter/vf_vpp_qsv.c b/libavfilter/vf_vpp_qsv.c index 317ae06c122..8d4227f8411 100644 --- a/libavfilter/vf_vpp_qsv.c +++ b/libavfilter/vf_vpp_qsv.c @@ -150,18 +150,22 @@ static const char *const var_names[] = { "ch", "cx", "cy", + "a", "dar", + "sar", NULL }; enum var_name { - VAR_iW, VAR_IN_W, - VAR_iH, VAR_IN_H, - VAR_oW, VAR_OUT_W, VAR_W, - VAR_oH, VAR_OUT_H, VAR_H, - CW, - CH, - CX, - CY, + VAR_IW, VAR_IN_W, + VAR_IH, VAR_IN_H, + VAR_OW, VAR_OUT_W, VAR_W, + VAR_OH, VAR_OUT_H, VAR_H, + VAR_CW, + VAR_CH, + VAR_CX, + VAR_CY, + VAR_A, VAR_DAR, + VAR_SAR, VAR_VARS_NB }; @@ -193,39 +197,44 @@ static int eval_expr(AVFilterContext *ctx) PASS_EXPR(cx_expr, vpp->cx); PASS_EXPR(cy_expr, vpp->cy); - var_values[VAR_iW] = + var_values[VAR_IW] = var_values[VAR_IN_W] = ctx->inputs[0]->w; - var_values[VAR_iH] = + var_values[VAR_IH] = var_values[VAR_IN_H] = ctx->inputs[0]->h; + var_values[VAR_A] = (double)var_values[VAR_IN_W] / var_values[VAR_IN_H]; + var_values[VAR_SAR] = ctx->inputs[0]->sample_aspect_ratio.num ? + (double)ctx->inputs[0]->sample_aspect_ratio.num / ctx->inputs[0]->sample_aspect_ratio.den : 1; + var_values[VAR_DAR] = var_values[VAR_A] * var_values[VAR_SAR]; + /* crop params */ - CALC_EXPR(cw_expr, var_values[CW], vpp->crop_w); - CALC_EXPR(ch_expr, var_values[CH], vpp->crop_h); + CALC_EXPR(cw_expr, var_values[VAR_CW], vpp->crop_w); + CALC_EXPR(ch_expr, var_values[VAR_CH], vpp->crop_h); /* calc again in case cw is relative to ch */ - CALC_EXPR(cw_expr, var_values[CW], vpp->crop_w); + CALC_EXPR(cw_expr, var_values[VAR_CW], vpp->crop_w); CALC_EXPR(w_expr, - var_values[VAR_OUT_W] = var_values[VAR_oW] = var_values[VAR_W], + var_values[VAR_OUT_W] = var_values[VAR_OW] = var_values[VAR_W], vpp->out_width); CALC_EXPR(h_expr, - var_values[VAR_OUT_H] = var_values[VAR_oH] = var_values[VAR_H], + var_values[VAR_OUT_H] = var_values[VAR_OH] = var_values[VAR_H], vpp->out_height); /* calc again in case ow is relative to oh */ CALC_EXPR(w_expr, - var_values[VAR_OUT_W] = var_values[VAR_oW] = var_values[VAR_W], + var_values[VAR_OUT_W] = var_values[VAR_OW] = var_values[VAR_W], vpp->out_width); - CALC_EXPR(cx_expr, var_values[CX], vpp->crop_x); - CALC_EXPR(cy_expr, var_values[CY], vpp->crop_y); + CALC_EXPR(cx_expr, var_values[VAR_CX], vpp->crop_x); + CALC_EXPR(cy_expr, var_values[VAR_CY], vpp->crop_y); /* calc again in case cx is relative to cy */ - CALC_EXPR(cx_expr, var_values[CX], vpp->crop_x); + CALC_EXPR(cx_expr, var_values[VAR_CX], vpp->crop_x); - if ((vpp->crop_w != var_values[VAR_iW]) || (vpp->crop_h != var_values[VAR_iH])) + if ((vpp->crop_w != var_values[VAR_IW]) || (vpp->crop_h != var_values[VAR_IH])) vpp->use_crop = 1; release: From 129530e91707b6451a28580bca147031996993af Mon Sep 17 00:00:00 2001 From: Haihao Xiang Date: Mon, 9 Jan 2023 15:12:04 +0800 Subject: [PATCH 0009/2172] lavfi/vf_vpp_qsv: handle NULL pointer when evaluating an expression This patch provides default value if the expression is NULL. This is in preparation for reusing the code for other QSV filters. Signed-off-by: Haihao Xiang --- libavfilter/vf_vpp_qsv.c | 36 ++++++++++++++++++++---------------- 1 file changed, 20 insertions(+), 16 deletions(-) diff --git a/libavfilter/vf_vpp_qsv.c b/libavfilter/vf_vpp_qsv.c index 8d4227f8411..3a0a395732d 100644 --- a/libavfilter/vf_vpp_qsv.c +++ b/libavfilter/vf_vpp_qsv.c @@ -172,14 +172,19 @@ enum var_name { static int eval_expr(AVFilterContext *ctx) { #define PASS_EXPR(e, s) {\ - ret = av_expr_parse(&e, s, var_names, NULL, NULL, NULL, NULL, 0, ctx); \ - if (ret < 0) {\ - av_log(ctx, AV_LOG_ERROR, "Error when passing '%s'.\n", s);\ - goto release;\ + if (s) {\ + ret = av_expr_parse(&e, s, var_names, NULL, NULL, NULL, NULL, 0, ctx); \ + if (ret < 0) { \ + av_log(ctx, AV_LOG_ERROR, "Error when passing '%s'.\n", s); \ + goto release; \ + } \ }\ } -#define CALC_EXPR(e, v, i) {\ - i = v = av_expr_eval(e, var_values, NULL); \ +#define CALC_EXPR(e, v, i, d) {\ + if (e)\ + i = v = av_expr_eval(e, var_values, NULL); \ + else\ + i = v = d;\ } VPPContext *vpp = ctx->priv; double var_values[VAR_VARS_NB] = { NAN }; @@ -209,30 +214,29 @@ static int eval_expr(AVFilterContext *ctx) var_values[VAR_DAR] = var_values[VAR_A] * var_values[VAR_SAR]; /* crop params */ - CALC_EXPR(cw_expr, var_values[VAR_CW], vpp->crop_w); - CALC_EXPR(ch_expr, var_values[VAR_CH], vpp->crop_h); + CALC_EXPR(cw_expr, var_values[VAR_CW], vpp->crop_w, var_values[VAR_IW]); + CALC_EXPR(ch_expr, var_values[VAR_CH], vpp->crop_h, var_values[VAR_IH]); /* calc again in case cw is relative to ch */ - CALC_EXPR(cw_expr, var_values[VAR_CW], vpp->crop_w); + CALC_EXPR(cw_expr, var_values[VAR_CW], vpp->crop_w, var_values[VAR_IW]); CALC_EXPR(w_expr, var_values[VAR_OUT_W] = var_values[VAR_OW] = var_values[VAR_W], - vpp->out_width); + vpp->out_width, var_values[VAR_CW]); CALC_EXPR(h_expr, var_values[VAR_OUT_H] = var_values[VAR_OH] = var_values[VAR_H], - vpp->out_height); + vpp->out_height, var_values[VAR_CH]); /* calc again in case ow is relative to oh */ CALC_EXPR(w_expr, var_values[VAR_OUT_W] = var_values[VAR_OW] = var_values[VAR_W], - vpp->out_width); + vpp->out_width, var_values[VAR_CW]); - - CALC_EXPR(cx_expr, var_values[VAR_CX], vpp->crop_x); - CALC_EXPR(cy_expr, var_values[VAR_CY], vpp->crop_y); + CALC_EXPR(cx_expr, var_values[VAR_CX], vpp->crop_x, (var_values[VAR_IW] - var_values[VAR_OW]) / 2); + CALC_EXPR(cy_expr, var_values[VAR_CY], vpp->crop_y, (var_values[VAR_IH] - var_values[VAR_OH]) / 2); /* calc again in case cx is relative to cy */ - CALC_EXPR(cx_expr, var_values[VAR_CX], vpp->crop_x); + CALC_EXPR(cx_expr, var_values[VAR_CX], vpp->crop_x, (var_values[VAR_IW] - var_values[VAR_OW]) / 2); if ((vpp->crop_w != var_values[VAR_IW]) || (vpp->crop_h != var_values[VAR_IH])) vpp->use_crop = 1; From eb71c67dcc0990aec9cda9cb39de2a464de4068a Mon Sep 17 00:00:00 2001 From: Haihao Xiang Date: Mon, 9 Jan 2023 15:12:05 +0800 Subject: [PATCH 0010/2172] lavfi/vf_vpp_qsv: allow special values for the output video dimensions Special values are: 0 = original width/height -1 = keep original aspect This is in preparation for reusing the code for other QSV filters. Signed-off-by: Haihao Xiang --- libavfilter/vf_vpp_qsv.c | 47 ++++++++++++++++++++++++++++++++++------ 1 file changed, 40 insertions(+), 7 deletions(-) diff --git a/libavfilter/vf_vpp_qsv.c b/libavfilter/vf_vpp_qsv.c index 3a0a395732d..cf11cd7fdc9 100644 --- a/libavfilter/vf_vpp_qsv.c +++ b/libavfilter/vf_vpp_qsv.c @@ -59,6 +59,11 @@ typedef struct VPPContext{ mfxExtVPPMirroring mirroring_conf; mfxExtVPPScaling scale_conf; + /** + * New dimensions. Special values are: + * 0 = original width/height + * -1 = keep original aspect + */ int out_width; int out_height; /** @@ -127,10 +132,10 @@ static const AVOption options[] = { { "cx", "set the x crop area expression", OFFSET(cx), AV_OPT_TYPE_STRING, { .str = "(in_w-out_w)/2" }, 0, 0, FLAGS }, { "cy", "set the y crop area expression", OFFSET(cy), AV_OPT_TYPE_STRING, { .str = "(in_h-out_h)/2" }, 0, 0, FLAGS }, - { "w", "Output video width", OFFSET(ow), AV_OPT_TYPE_STRING, { .str="cw" }, 0, 255, .flags = FLAGS }, - { "width", "Output video width", OFFSET(ow), AV_OPT_TYPE_STRING, { .str="cw" }, 0, 255, .flags = FLAGS }, - { "h", "Output video height", OFFSET(oh), AV_OPT_TYPE_STRING, { .str="w*ch/cw" }, 0, 255, .flags = FLAGS }, - { "height", "Output video height", OFFSET(oh), AV_OPT_TYPE_STRING, { .str="w*ch/cw" }, 0, 255, .flags = FLAGS }, + { "w", "Output video width(0=input video width, -1=keep input video aspect)", OFFSET(ow), AV_OPT_TYPE_STRING, { .str="cw" }, 0, 255, .flags = FLAGS }, + { "width", "Output video width(0=input video width, -1=keep input video aspect)", OFFSET(ow), AV_OPT_TYPE_STRING, { .str="cw" }, 0, 255, .flags = FLAGS }, + { "h", "Output video height(0=input video height, -1=keep input video aspect)", OFFSET(oh), AV_OPT_TYPE_STRING, { .str="w*ch/cw" }, 0, 255, .flags = FLAGS }, + { "height", "Output video height(0=input video height, -1=keep input video aspect)", 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 }, { "scale_mode", "scale & format conversion 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" }, @@ -276,6 +281,7 @@ static int config_input(AVFilterLink *inlink) AVFilterContext *ctx = inlink->dst; VPPContext *vpp = ctx->priv; int ret; + int64_t ow, oh; if (vpp->framerate.den == 0 || vpp->framerate.num == 0) vpp->framerate = inlink->frame_rate; @@ -289,11 +295,38 @@ static int config_input(AVFilterLink *inlink) return ret; } - if (vpp->out_height == 0 || vpp->out_width == 0) { - vpp->out_width = inlink->w; - vpp->out_height = inlink->h; + ow = vpp->out_width; + oh = vpp->out_height; + + /* sanity check params */ + if (ow < -1 || oh < -1) { + av_log(ctx, AV_LOG_ERROR, "Size values less than -1 are not acceptable.\n"); + return AVERROR(EINVAL); } + if (ow == -1 && oh == -1) + vpp->out_width = vpp->out_height = 0; + + if (!(ow = vpp->out_width)) + ow = inlink->w; + + if (!(oh = vpp->out_height)) + oh = inlink->h; + + if (ow == -1) + ow = av_rescale(oh, inlink->w, inlink->h); + + if (oh == -1) + oh = av_rescale(ow, inlink->h, inlink->w); + + if (ow > INT_MAX || oh > INT_MAX || + (oh * inlink->w) > INT_MAX || + (ow * inlink->h) > INT_MAX) + av_log(ctx, AV_LOG_ERROR, "Rescaled value for width or height is too big.\n"); + + vpp->out_width = ow; + vpp->out_height = oh; + if (vpp->use_crop) { vpp->crop_x = FFMAX(vpp->crop_x, 0); vpp->crop_y = FFMAX(vpp->crop_y, 0); From a1b3e8f2d73b4c0a28189f99bb25d04ff4ef44eb Mon Sep 17 00:00:00 2001 From: Haihao Xiang Date: Mon, 9 Jan 2023 15:12:06 +0800 Subject: [PATCH 0011/2172] lavfi/vf_vpp_qsv: add vpp_preinit callback Set the expected default value for options in this callback, hence we have the right values even if these options are not included in the option arrray. This is in preparation for reusing the code for other QSV filters. Signed-off-by: Haihao Xiang --- libavfilter/vf_vpp_qsv.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/libavfilter/vf_vpp_qsv.c b/libavfilter/vf_vpp_qsv.c index cf11cd7fdc9..2a7b06fa338 100644 --- a/libavfilter/vf_vpp_qsv.c +++ b/libavfilter/vf_vpp_qsv.c @@ -259,6 +259,19 @@ static int eval_expr(AVFilterContext *ctx) return ret; } +static av_cold int vpp_preinit(AVFilterContext *ctx) +{ + VPPContext *vpp = ctx->priv; + /* For AV_OPT_TYPE_STRING options, NULL is handled in other way so + * we needn't set default value here + */ + vpp->saturation = 1.0; + vpp->contrast = 1.0; + vpp->transpose = -1; + + return 0; +} + static av_cold int vpp_init(AVFilterContext *ctx) { VPPContext *vpp = ctx->priv; @@ -683,6 +696,7 @@ const AVFilter ff_vf_vpp_qsv = { .name = "vpp_qsv", .description = NULL_IF_CONFIG_SMALL("Quick Sync Video VPP."), .priv_size = sizeof(VPPContext), + .preinit = vpp_preinit, .init = vpp_init, .uninit = vpp_uninit, FILTER_INPUTS(vpp_inputs), From dc5369144b824ee6d14086b06759b291a8213646 Mon Sep 17 00:00:00 2001 From: Haihao Xiang Date: Mon, 9 Jan 2023 15:12:07 +0800 Subject: [PATCH 0012/2172] lavfi/vf_vpp_qsv: add has_passthrough flag in VPPContext QSV filters may set this flag in preinit callback to turn on / off pass through mode This is in preparation for reusing the code for other QSV filters. E.g. scale_qsv filter doesn't support pass through mode. Signed-off-by: Haihao Xiang --- libavfilter/vf_vpp_qsv.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/libavfilter/vf_vpp_qsv.c b/libavfilter/vf_vpp_qsv.c index 2a7b06fa338..b04307b644d 100644 --- a/libavfilter/vf_vpp_qsv.c +++ b/libavfilter/vf_vpp_qsv.c @@ -102,6 +102,7 @@ typedef struct VPPContext{ int async_depth; int eof; + int has_passthrough; /* apply pass through mode if possible */ } VPPContext; static const AVOption options[] = { @@ -269,6 +270,8 @@ static av_cold int vpp_preinit(AVFilterContext *ctx) vpp->contrast = 1.0; vpp->transpose = -1; + vpp->has_passthrough = 1; + return 0; } @@ -552,7 +555,8 @@ static int config_output(AVFilterLink *outlink) if (vpp->use_frc || vpp->use_crop || vpp->deinterlace || vpp->denoise || vpp->detail || vpp->procamp || vpp->rotate || vpp->hflip || - inlink->w != outlink->w || inlink->h != outlink->h || in_format != vpp->out_format) + inlink->w != outlink->w || inlink->h != outlink->h || in_format != vpp->out_format || + !vpp->has_passthrough) return ff_qsvvpp_create(ctx, &vpp->qsv, ¶m); else { av_log(ctx, AV_LOG_VERBOSE, "qsv vpp pass through mode.\n"); From 6ce23ebaac4f36d0477da18991ef16188e52a2ad Mon Sep 17 00:00:00 2001 From: Haihao Xiang Date: Mon, 9 Jan 2023 15:12:08 +0800 Subject: [PATCH 0013/2172] lavfi/vf_vpp_qsv: check output format string against NULL pointer This is in preparation for reusing the code for other QSV filters. E.g. deinterlacing_qsv may have an option array without format option Signed-off-by: Haihao Xiang --- libavfilter/vf_vpp_qsv.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavfilter/vf_vpp_qsv.c b/libavfilter/vf_vpp_qsv.c index b04307b644d..4aad856a2ed 100644 --- a/libavfilter/vf_vpp_qsv.c +++ b/libavfilter/vf_vpp_qsv.c @@ -279,7 +279,7 @@ static av_cold int vpp_init(AVFilterContext *ctx) { VPPContext *vpp = ctx->priv; - if (!strcmp(vpp->output_format_str, "same")) { + if (!vpp->output_format_str || !strcmp(vpp->output_format_str, "same")) { vpp->out_format = AV_PIX_FMT_NONE; } else { vpp->out_format = av_get_pix_fmt(vpp->output_format_str); From 3763635ef40c59ce02e79efc0f117e1298a775d9 Mon Sep 17 00:00:00 2001 From: Haihao Xiang Date: Mon, 9 Jan 2023 15:12:09 +0800 Subject: [PATCH 0014/2172] lavfi/qsvvpp: set output frame durations Signed-off-by: Haihao Xiang --- libavfilter/qsvvpp.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/libavfilter/qsvvpp.c b/libavfilter/qsvvpp.c index 064b105a177..f074bf9978e 100644 --- a/libavfilter/qsvvpp.c +++ b/libavfilter/qsvvpp.c @@ -503,6 +503,11 @@ static QSVFrame *query_frame(QSVVPPContext *s, AVFilterLink *outlink) return NULL; } + if (outlink->frame_rate.num && outlink->frame_rate.den) + out_frame->frame->duration = av_rescale_q(1, av_inv_q(outlink->frame_rate), outlink->time_base); + else + out_frame->frame->duration = 0; + out_frame->frame->width = outlink->w; out_frame->frame->height = outlink->h; out_frame->surface.Info = s->vpp_param.vpp.Out; From 749154532008e5062ea58c74dff9a94a8e2f020c Mon Sep 17 00:00:00 2001 From: Haihao Xiang Date: Mon, 9 Jan 2023 15:12:10 +0800 Subject: [PATCH 0015/2172] lavfi/qsv: use QSVVPPContext as base context in vf_vpp_qsv/vf_overlay_qsv The same members between QSVVPPContext and VPPContext are removed from VPPContext, and async_depth is moved from QSVVPPParam to QSVVPPContext so that all QSV filters using QSVVPPContext may support async depth. In addition, we may use QSVVPPContext as base context in other QSV filters in the future so that we may re-use functions defined in qsvvpp.c for other QSV filters. This commit shouldn't change the functionality of vpp_qsv / overlay_qsv. Signed-off-by: Haihao Xiang --- libavfilter/qsvvpp.c | 25 ++++++++----------------- libavfilter/qsvvpp.h | 8 ++++---- libavfilter/vf_overlay_qsv.c | 11 +++++------ libavfilter/vf_vpp_qsv.c | 35 ++++++++++++++--------------------- 4 files changed, 31 insertions(+), 48 deletions(-) diff --git a/libavfilter/qsvvpp.c b/libavfilter/qsvvpp.c index f074bf9978e..7e64944f2c6 100644 --- a/libavfilter/qsvvpp.c +++ b/libavfilter/qsvvpp.c @@ -687,15 +687,11 @@ static int init_vpp_session(AVFilterContext *avctx, QSVVPPContext *s) return 0; } -int ff_qsvvpp_create(AVFilterContext *avctx, QSVVPPContext **vpp, QSVVPPParam *param) +int ff_qsvvpp_init(AVFilterContext *avctx, QSVVPPParam *param) { int i; int ret; - QSVVPPContext *s; - - s = av_mallocz(sizeof(*s)); - if (!s) - return AVERROR(ENOMEM); + QSVVPPContext *s = avctx->priv; s->filter_frame = param->filter_frame; if (!s->filter_frame) @@ -767,14 +763,13 @@ int ff_qsvvpp_create(AVFilterContext *avctx, QSVVPPContext **vpp, QSVVPPParam *p s->got_frame = 0; /** keep fifo size at least 1. Even when async_depth is 0, fifo is used. */ - s->async_fifo = av_fifo_alloc2(param->async_depth + 1, sizeof(QSVAsyncFrame), 0); - s->async_depth = param->async_depth; + s->async_fifo = av_fifo_alloc2(s->async_depth + 1, sizeof(QSVAsyncFrame), 0); if (!s->async_fifo) { ret = AVERROR(ENOMEM); goto failed; } - s->vpp_param.AsyncDepth = param->async_depth; + s->vpp_param.AsyncDepth = s->async_depth; if (IS_SYSTEM_MEMORY(s->in_mem_mode)) s->vpp_param.IOPattern |= MFX_IOPATTERN_IN_SYSTEM_MEMORY; @@ -805,25 +800,22 @@ int ff_qsvvpp_create(AVFilterContext *avctx, QSVVPPContext **vpp, QSVVPPParam *p } else if (ret > 0) ff_qsvvpp_print_warning(avctx, ret, "Warning When creating qsvvpp"); - *vpp = s; return 0; failed: - ff_qsvvpp_free(&s); + ff_qsvvpp_close(avctx); return ret; } -int ff_qsvvpp_free(QSVVPPContext **vpp) +int ff_qsvvpp_close(AVFilterContext *avctx) { - QSVVPPContext *s = *vpp; - - if (!s) - return 0; + QSVVPPContext *s = avctx->priv; if (s->session) { MFXVideoVPP_Close(s->session); MFXClose(s->session); + s->session = NULL; } /* release all the resources */ @@ -836,7 +828,6 @@ int ff_qsvvpp_free(QSVVPPContext **vpp) #endif av_freep(&s->frame_infos); av_fifo_freep2(&s->async_fifo); - av_freep(vpp); return 0; } diff --git a/libavfilter/qsvvpp.h b/libavfilter/qsvvpp.h index 6f7c9bfc150..3b321937440 100644 --- a/libavfilter/qsvvpp.h +++ b/libavfilter/qsvvpp.h @@ -53,6 +53,8 @@ typedef struct QSVFrame { } QSVFrame; typedef struct QSVVPPContext { + const AVClass *class; + mfxSession session; int (*filter_frame) (AVFilterLink *outlink, AVFrame *frame); /**< callback */ enum AVPixelFormat out_sw_format; /**< Real output format */ @@ -102,15 +104,13 @@ typedef struct QSVVPPParam { /* Crop information for each input, if needed */ int num_crop; QSVVPPCrop *crop; - - int async_depth; } QSVVPPParam; /* create and initialize the QSV session */ -int ff_qsvvpp_create(AVFilterContext *avctx, QSVVPPContext **vpp, QSVVPPParam *param); +int ff_qsvvpp_init(AVFilterContext *avctx, QSVVPPParam *param); /* release the resources (eg.surfaces) */ -int ff_qsvvpp_free(QSVVPPContext **vpp); +int ff_qsvvpp_close(AVFilterContext *avctx); /* vpp filter frame and call the cb if needed */ int ff_qsvvpp_filter_frame(QSVVPPContext *vpp, AVFilterLink *inlink, AVFrame *frame); diff --git a/libavfilter/vf_overlay_qsv.c b/libavfilter/vf_overlay_qsv.c index 1a2c1b1e96f..5bec7dd414c 100644 --- a/libavfilter/vf_overlay_qsv.c +++ b/libavfilter/vf_overlay_qsv.c @@ -57,10 +57,9 @@ enum var_name { }; typedef struct QSVOverlayContext { - const AVClass *class; + QSVVPPContext qsv; FFFrameSync fs; - QSVVPPContext *qsv; QSVVPPParam qsv_param; mfxExtVPPComposite comp_conf; double var_values[VAR_VARS_NB]; @@ -230,14 +229,14 @@ static int config_overlay_input(AVFilterLink *inlink) static int process_frame(FFFrameSync *fs) { AVFilterContext *ctx = fs->parent; - QSVOverlayContext *s = fs->opaque; + QSVVPPContext *qsv = fs->opaque; AVFrame *frame = NULL; int ret = 0, i; for (i = 0; i < ctx->nb_inputs; i++) { ret = ff_framesync_get_frame(fs, i, &frame, 0); if (ret == 0) - ret = ff_qsvvpp_filter_frame(s->qsv, ctx->inputs[i], frame); + ret = ff_qsvvpp_filter_frame(qsv, ctx->inputs[i], frame); if (ret < 0 && ret != AVERROR(EAGAIN)) break; } @@ -301,7 +300,7 @@ static int config_output(AVFilterLink *outlink) if (ret < 0) return ret; - return ff_qsvvpp_create(ctx, &vpp->qsv, &vpp->qsv_param); + return ff_qsvvpp_init(ctx, &vpp->qsv_param); } /* @@ -350,7 +349,7 @@ static av_cold void overlay_qsv_uninit(AVFilterContext *ctx) { QSVOverlayContext *vpp = ctx->priv; - ff_qsvvpp_free(&vpp->qsv); + ff_qsvvpp_close(ctx); ff_framesync_uninit(&vpp->fs); av_freep(&vpp->comp_conf.InputStream); av_freep(&vpp->qsv_param.ext_buf); diff --git a/libavfilter/vf_vpp_qsv.c b/libavfilter/vf_vpp_qsv.c index 4aad856a2ed..4a1af7146ae 100644 --- a/libavfilter/vf_vpp_qsv.c +++ b/libavfilter/vf_vpp_qsv.c @@ -45,9 +45,7 @@ #define ENH_FILTERS_COUNT (8) typedef struct VPPContext{ - const AVClass *class; - - QSVVPPContext *qsv; + QSVVPPContext qsv; /* Video Enhancement Algorithms */ mfxExtVPPDeinterlacing deinterlace_conf; @@ -100,8 +98,6 @@ typedef struct VPPContext{ char *ow, *oh; char *output_format_str; - int async_depth; - int eof; int has_passthrough; /* apply pass through mode if possible */ } VPPContext; @@ -138,7 +134,7 @@ static const AVOption options[] = { { "h", "Output video height(0=input video height, -1=keep input video aspect)", OFFSET(oh), AV_OPT_TYPE_STRING, { .str="w*ch/cw" }, 0, 255, .flags = FLAGS }, { "height", "Output video height(0=input video height, -1=keep input video aspect)", 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 }, + { "async_depth", "Internal parallelization depth, the higher the value the higher the latency.", OFFSET(qsv.async_depth), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, INT_MAX, .flags = FLAGS }, { "scale_mode", "scale & format conversion 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" }, { "auto", "auto mode", 0, AV_OPT_TYPE_CONST, { .i64 = MFX_SCALING_MODE_DEFAULT}, INT_MIN, INT_MAX, FLAGS, "scale mode"}, { "low_power", "low power mode", 0, AV_OPT_TYPE_CONST, { .i64 = MFX_SCALING_MODE_LOWPOWER}, INT_MIN, INT_MAX, FLAGS, "scale mode"}, @@ -401,7 +397,6 @@ static int config_output(AVFilterLink *outlink) param.filter_frame = NULL; param.num_ext_buf = 0; 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"); @@ -557,8 +552,9 @@ static int config_output(AVFilterLink *outlink) vpp->detail || vpp->procamp || vpp->rotate || vpp->hflip || inlink->w != outlink->w || inlink->h != outlink->h || in_format != vpp->out_format || !vpp->has_passthrough) - return ff_qsvvpp_create(ctx, &vpp->qsv, ¶m); + return ff_qsvvpp_init(ctx, ¶m); else { + /* No MFX session is created in this case */ av_log(ctx, AV_LOG_VERBOSE, "qsv vpp pass through mode.\n"); if (inlink->hw_frames_ctx) outlink->hw_frames_ctx = av_buffer_ref(inlink->hw_frames_ctx); @@ -571,29 +567,27 @@ static int activate(AVFilterContext *ctx) { AVFilterLink *inlink = ctx->inputs[0]; AVFilterLink *outlink = ctx->outputs[0]; - VPPContext *s =ctx->priv; - QSVVPPContext *qsv = s->qsv; + QSVVPPContext *qsv = ctx->priv; AVFrame *in = NULL; int ret, status = 0; int64_t pts = AV_NOPTS_VALUE; FF_FILTER_FORWARD_STATUS_BACK(outlink, inlink); - if (!s->eof) { + if (!qsv->eof) { ret = ff_inlink_consume_frame(inlink, &in); if (ret < 0) return ret; if (ff_inlink_acknowledge_status(inlink, &status, &pts)) { if (status == AVERROR_EOF) { - s->eof = 1; + qsv->eof = 1; } } } - if (qsv) { - if (in || s->eof) { - qsv->eof = s->eof; + if (qsv->session) { + if (in || qsv->eof) { ret = ff_qsvvpp_filter_frame(qsv, inlink, in); av_frame_free(&in); if (ret == AVERROR(EAGAIN)) @@ -601,7 +595,7 @@ static int activate(AVFilterContext *ctx) else if (ret < 0) return ret; - if (s->eof) + if (qsv->eof) goto eof; if (qsv->got_frame) { @@ -610,6 +604,7 @@ static int activate(AVFilterContext *ctx) } } } else { + /* No MFX session is created in pass-through mode */ if (in) { if (in->pts != AV_NOPTS_VALUE) in->pts = av_rescale_q(in->pts, inlink->time_base, outlink->time_base); @@ -618,7 +613,7 @@ static int activate(AVFilterContext *ctx) if (ret < 0) return ret; - if (s->eof) + if (qsv->eof) goto eof; return 0; @@ -626,7 +621,7 @@ static int activate(AVFilterContext *ctx) } not_ready: - if (s->eof) + if (qsv->eof) goto eof; FF_FILTER_FORWARD_WANTED(outlink, inlink); @@ -667,9 +662,7 @@ static int query_formats(AVFilterContext *ctx) static av_cold void vpp_uninit(AVFilterContext *ctx) { - VPPContext *vpp = ctx->priv; - - ff_qsvvpp_free(&vpp->qsv); + ff_qsvvpp_close(ctx); } static const AVClass vpp_class = { From f5f1c1fd6bf892d0aaf7b2ea0c01857ca321319e Mon Sep 17 00:00:00 2001 From: Aman Karmani Date: Mon, 9 Jan 2023 18:40:24 +0000 Subject: [PATCH 0016/2172] avcodec/vaapi_encode_h26x: passthrough A53 CC data as H264/HEVC SEI Signed-off-by: Aman Karmani --- configure | 4 ++-- libavcodec/vaapi_encode_h264.c | 33 +++++++++++++++++++++++++++++++- libavcodec/vaapi_encode_h265.c | 35 +++++++++++++++++++++++++++++++++- 3 files changed, 68 insertions(+), 4 deletions(-) diff --git a/configure b/configure index df69d396692..6e88c32223f 100755 --- a/configure +++ b/configure @@ -3181,7 +3181,7 @@ h264_qsv_decoder_select="h264_mp4toannexb_bsf qsvdec" h264_qsv_encoder_select="atsc_a53 qsvenc" h264_rkmpp_decoder_deps="rkmpp" h264_rkmpp_decoder_select="h264_mp4toannexb_bsf" -h264_vaapi_encoder_select="cbs_h264 vaapi_encode" +h264_vaapi_encoder_select="atsc_a53 cbs_h264 vaapi_encode" h264_v4l2m2m_decoder_deps="v4l2_m2m h264_v4l2_m2m" h264_v4l2m2m_decoder_select="h264_mp4toannexb_bsf" h264_v4l2m2m_encoder_deps="v4l2_m2m h264_v4l2_m2m" @@ -3202,7 +3202,7 @@ hevc_qsv_encoder_select="hevcparse qsvenc" hevc_rkmpp_decoder_deps="rkmpp" hevc_rkmpp_decoder_select="hevc_mp4toannexb_bsf" hevc_vaapi_encoder_deps="VAEncPictureParameterBufferHEVC" -hevc_vaapi_encoder_select="cbs_h265 vaapi_encode" +hevc_vaapi_encoder_select="atsc_a53 cbs_h265 vaapi_encode" hevc_v4l2m2m_decoder_deps="v4l2_m2m hevc_v4l2_m2m" hevc_v4l2m2m_decoder_select="hevc_mp4toannexb_bsf" hevc_v4l2m2m_encoder_deps="v4l2_m2m hevc_v4l2_m2m" diff --git a/libavcodec/vaapi_encode_h264.c b/libavcodec/vaapi_encode_h264.c index dd17be2190a..f15bcc6ea8b 100644 --- a/libavcodec/vaapi_encode_h264.c +++ b/libavcodec/vaapi_encode_h264.c @@ -26,6 +26,7 @@ #include "libavutil/internal.h" #include "libavutil/opt.h" +#include "atsc_a53.h" #include "avcodec.h" #include "cbs.h" #include "cbs_h264.h" @@ -41,6 +42,7 @@ enum { SEI_TIMING = 0x01, SEI_IDENTIFIER = 0x02, SEI_RECOVERY_POINT = 0x04, + SEI_A53_CC = 0x08, }; // Random (version 4) ISO 11578 UUID. @@ -99,6 +101,8 @@ typedef struct VAAPIEncodeH264Context { H264RawSEIRecoveryPoint sei_recovery_point; SEIRawUserDataUnregistered sei_identifier; char *sei_identifier_string; + SEIRawUserDataRegistered sei_a53cc; + void *sei_a53cc_data; int aud_needed; int sei_needed; @@ -249,6 +253,13 @@ static int vaapi_encode_h264_write_extra_header(AVCodecContext *avctx, if (err < 0) goto fail; } + if (priv->sei_needed & SEI_A53_CC) { + err = ff_cbs_sei_add_message(priv->cbc, au, 1, + SEI_TYPE_USER_DATA_REGISTERED_ITU_T_T35, + &priv->sei_a53cc, NULL); + if (err < 0) + goto fail; + } priv->sei_needed = 0; @@ -675,6 +686,22 @@ static int vaapi_encode_h264_init_picture_params(AVCodecContext *avctx, priv->sei_needed |= SEI_RECOVERY_POINT; } + if (priv->sei & SEI_A53_CC) { + int err; + size_t sei_a53cc_len; + av_freep(&priv->sei_a53cc_data); + err = ff_alloc_a53_sei(pic->input_image, 0, &priv->sei_a53cc_data, &sei_a53cc_len); + if (err < 0) + return err; + if (priv->sei_a53cc_data != NULL) { + priv->sei_a53cc.itu_t_t35_country_code = 181; + priv->sei_a53cc.data = (uint8_t *)priv->sei_a53cc_data + 1; + priv->sei_a53cc.data_length = sei_a53cc_len - 1; + + priv->sei_needed |= SEI_A53_CC; + } + } + vpic->CurrPic = (VAPictureH264) { .picture_id = pic->recon_surface, .frame_idx = hpic->frame_num, @@ -1220,6 +1247,7 @@ static av_cold int vaapi_encode_h264_close(AVCodecContext *avctx) ff_cbs_fragment_free(&priv->current_access_unit); ff_cbs_close(&priv->cbc); av_freep(&priv->sei_identifier_string); + av_freep(&priv->sei_a53cc_data); return ff_vaapi_encode_close(avctx); } @@ -1246,7 +1274,7 @@ static const AVOption vaapi_encode_h264_options[] = { { "sei", "Set SEI to include", OFFSET(sei), AV_OPT_TYPE_FLAGS, - { .i64 = SEI_IDENTIFIER | SEI_TIMING | SEI_RECOVERY_POINT }, + { .i64 = SEI_IDENTIFIER | SEI_TIMING | SEI_RECOVERY_POINT | SEI_A53_CC }, 0, INT_MAX, FLAGS, "sei" }, { "identifier", "Include encoder version identifier", 0, AV_OPT_TYPE_CONST, { .i64 = SEI_IDENTIFIER }, @@ -1257,6 +1285,9 @@ static const AVOption vaapi_encode_h264_options[] = { { "recovery_point", "Include recovery points where appropriate", 0, AV_OPT_TYPE_CONST, { .i64 = SEI_RECOVERY_POINT }, INT_MIN, INT_MAX, FLAGS, "sei" }, + { "a53_cc", "Include A/53 caption data", + 0, AV_OPT_TYPE_CONST, { .i64 = SEI_A53_CC }, + INT_MIN, INT_MAX, FLAGS, "sei" }, { "profile", "Set profile (profile_idc and constraint_set*_flag)", OFFSET(profile), AV_OPT_TYPE_INT, diff --git a/libavcodec/vaapi_encode_h265.c b/libavcodec/vaapi_encode_h265.c index 0833053c745..946f2e7640a 100644 --- a/libavcodec/vaapi_encode_h265.c +++ b/libavcodec/vaapi_encode_h265.c @@ -27,6 +27,7 @@ #include "libavutil/opt.h" #include "libavutil/mastering_display_metadata.h" +#include "atsc_a53.h" #include "avcodec.h" #include "cbs.h" #include "cbs_h265.h" @@ -41,6 +42,7 @@ enum { SEI_MASTERING_DISPLAY = 0x08, SEI_CONTENT_LIGHT_LEVEL = 0x10, + SEI_A53_CC = 0x20, }; typedef struct VAAPIEncodeH265Picture { @@ -85,6 +87,8 @@ typedef struct VAAPIEncodeH265Context { SEIRawMasteringDisplayColourVolume sei_mastering_display; SEIRawContentLightLevelInfo sei_content_light_level; + SEIRawUserDataRegistered sei_a53cc; + void *sei_a53cc_data; CodedBitstreamContext *cbc; CodedBitstreamFragment current_access_unit; @@ -227,6 +231,13 @@ static int vaapi_encode_h265_write_extra_header(AVCodecContext *avctx, if (err < 0) goto fail; } + if (priv->sei_needed & SEI_A53_CC) { + err = ff_cbs_sei_add_message(priv->cbc, au, 1, + SEI_TYPE_USER_DATA_REGISTERED_ITU_T_T35, + &priv->sei_a53cc, NULL); + if (err < 0) + goto fail; + } priv->sei_needed = 0; @@ -882,6 +893,22 @@ static int vaapi_encode_h265_init_picture_params(AVCodecContext *avctx, } } + if (priv->sei & SEI_A53_CC) { + int err; + size_t sei_a53cc_len; + av_freep(&priv->sei_a53cc_data); + err = ff_alloc_a53_sei(pic->input_image, 0, &priv->sei_a53cc_data, &sei_a53cc_len); + if (err < 0) + return err; + if (priv->sei_a53cc_data != NULL) { + priv->sei_a53cc.itu_t_t35_country_code = 181; + priv->sei_a53cc.data = (uint8_t *)priv->sei_a53cc_data + 1; + priv->sei_a53cc.data_length = sei_a53cc_len - 1; + + priv->sei_needed |= SEI_A53_CC; + } + } + vpic->decoded_curr_pic = (VAPictureHEVC) { .picture_id = pic->recon_surface, .pic_order_cnt = hpic->pic_order_cnt, @@ -1349,6 +1376,7 @@ static av_cold int vaapi_encode_h265_close(AVCodecContext *avctx) ff_cbs_fragment_free(&priv->current_access_unit); ff_cbs_close(&priv->cbc); + av_freep(&priv->sei_a53cc_data); return ff_vaapi_encode_close(avctx); } @@ -1407,7 +1435,7 @@ static const AVOption vaapi_encode_h265_options[] = { { "sei", "Set SEI to include", OFFSET(sei), AV_OPT_TYPE_FLAGS, - { .i64 = SEI_MASTERING_DISPLAY | SEI_CONTENT_LIGHT_LEVEL }, + { .i64 = SEI_MASTERING_DISPLAY | SEI_CONTENT_LIGHT_LEVEL | SEI_A53_CC }, 0, INT_MAX, FLAGS, "sei" }, { "hdr", "Include HDR metadata for mastering display colour volume " @@ -1415,6 +1443,11 @@ static const AVOption vaapi_encode_h265_options[] = { 0, AV_OPT_TYPE_CONST, { .i64 = SEI_MASTERING_DISPLAY | SEI_CONTENT_LIGHT_LEVEL }, INT_MIN, INT_MAX, FLAGS, "sei" }, + { "a53_cc", + "Include A/53 caption data", + 0, AV_OPT_TYPE_CONST, + { .i64 = SEI_A53_CC }, + INT_MIN, INT_MAX, FLAGS, "sei" }, { "tiles", "Tile columns x rows", OFFSET(common.tile_cols), AV_OPT_TYPE_IMAGE_SIZE, From f1a8d3b0b62355a492ab869b6b695478b4da4544 Mon Sep 17 00:00:00 2001 From: Haihao Xiang Date: Fri, 13 Jan 2023 12:38:30 +0800 Subject: [PATCH 0017/2172] lavfi/vaapi: remove duplicated code Add a ff_ function to handle mulitple pipeline parameters. No functional changes. Signed-off-by: Haihao Xiang --- libavfilter/vaapi_vpp.c | 90 ++++++++++++++++-------- libavfilter/vaapi_vpp.h | 5 ++ libavfilter/vf_overlay_vaapi.c | 122 +++------------------------------ 3 files changed, 77 insertions(+), 140 deletions(-) diff --git a/libavfilter/vaapi_vpp.c b/libavfilter/vaapi_vpp.c index 1610df4c859..a323dab8b8a 100644 --- a/libavfilter/vaapi_vpp.c +++ b/libavfilter/vaapi_vpp.c @@ -588,17 +588,53 @@ int ff_vaapi_vpp_make_param_buffers(AVFilterContext *avctx, return 0; } +static int vaapi_vpp_render_single_pipeline_buffer(AVFilterContext *avctx, + VAProcPipelineParameterBuffer *params, + VABufferID *params_id) +{ + VAAPIVPPContext *ctx = avctx->priv; + VAStatus vas; -int ff_vaapi_vpp_render_picture(AVFilterContext *avctx, - VAProcPipelineParameterBuffer *params, - AVFrame *output_frame) + vas = vaCreateBuffer(ctx->hwctx->display, ctx->va_context, + VAProcPipelineParameterBufferType, + sizeof(*params), 1, params, params_id); + if (vas != VA_STATUS_SUCCESS) { + av_log(avctx, AV_LOG_ERROR, "Failed to create parameter buffer: " + "%d (%s).\n", vas, vaErrorStr(vas)); + *params_id = VA_INVALID_ID; + + return AVERROR(EIO); + } + av_log(avctx, AV_LOG_DEBUG, "Pipeline parameter buffer is %#x.\n", *params_id); + + vas = vaRenderPicture(ctx->hwctx->display, ctx->va_context, params_id, 1); + if (vas != VA_STATUS_SUCCESS) { + av_log(avctx, AV_LOG_ERROR, "Failed to render parameter buffer: " + "%d (%s).\n", vas, vaErrorStr(vas)); + return AVERROR(EIO); + } + + return 0; +} + +int ff_vaapi_vpp_render_pictures(AVFilterContext *avctx, + VAProcPipelineParameterBuffer *params_list, + int cout, + AVFrame *output_frame) { VAAPIVPPContext *ctx = avctx->priv; VASurfaceID output_surface; - VABufferID params_id; + VABufferID *params_ids; VAStatus vas; int err; + params_ids = (VABufferID *)av_malloc_array(cout, sizeof(VABufferID)); + if (!params_ids) + return AVERROR(ENOMEM); + + for (int i = 0; i < cout; i++) + params_ids[i] = VA_INVALID_ID; + output_surface = (VASurfaceID)(uintptr_t)output_frame->data[3]; vas = vaBeginPicture(ctx->hwctx->display, @@ -610,25 +646,10 @@ int ff_vaapi_vpp_render_picture(AVFilterContext *avctx, goto fail; } - vas = vaCreateBuffer(ctx->hwctx->display, ctx->va_context, - VAProcPipelineParameterBufferType, - sizeof(*params), 1, params, ¶ms_id); - if (vas != VA_STATUS_SUCCESS) { - av_log(avctx, AV_LOG_ERROR, "Failed to create parameter buffer: " - "%d (%s).\n", vas, vaErrorStr(vas)); - err = AVERROR(EIO); - goto fail_after_begin; - } - av_log(avctx, AV_LOG_DEBUG, "Pipeline parameter buffer is %#x.\n", - params_id); - - vas = vaRenderPicture(ctx->hwctx->display, ctx->va_context, - ¶ms_id, 1); - if (vas != VA_STATUS_SUCCESS) { - av_log(avctx, AV_LOG_ERROR, "Failed to render parameter buffer: " - "%d (%s).\n", vas, vaErrorStr(vas)); - err = AVERROR(EIO); - goto fail_after_begin; + for (int i = 0; i < cout; i++) { + err = vaapi_vpp_render_single_pipeline_buffer(avctx, ¶ms_list[i], ¶ms_ids[i]); + if (err) + goto fail_after_begin; } vas = vaEndPicture(ctx->hwctx->display, ctx->va_context); @@ -641,14 +662,17 @@ int ff_vaapi_vpp_render_picture(AVFilterContext *avctx, if (CONFIG_VAAPI_1 || ctx->hwctx->driver_quirks & AV_VAAPI_DRIVER_QUIRK_RENDER_PARAM_BUFFERS) { - vas = vaDestroyBuffer(ctx->hwctx->display, params_id); - if (vas != VA_STATUS_SUCCESS) { - av_log(avctx, AV_LOG_ERROR, "Failed to free parameter buffer: " - "%d (%s).\n", vas, vaErrorStr(vas)); - // And ignore. + for (int i = 0; i < cout && params_ids[i] != VA_INVALID_ID; i++) { + vas = vaDestroyBuffer(ctx->hwctx->display, params_ids[i]); + if (vas != VA_STATUS_SUCCESS) { + av_log(avctx, AV_LOG_ERROR, "Failed to free parameter buffer: " + "%d (%s).\n", vas, vaErrorStr(vas)); + // And ignore. + } } } + av_freep(¶ms_ids); return 0; // We want to make sure that if vaBeginPicture has been called, we also @@ -656,13 +680,21 @@ int ff_vaapi_vpp_render_picture(AVFilterContext *avctx, // do something else nasty, but once we're in this failure case there // isn't much else we can do. fail_after_begin: - vaRenderPicture(ctx->hwctx->display, ctx->va_context, ¶ms_id, 1); + vaRenderPicture(ctx->hwctx->display, ctx->va_context, ¶ms_ids[0], 1); fail_after_render: vaEndPicture(ctx->hwctx->display, ctx->va_context); fail: + av_freep(¶ms_ids); return err; } +int ff_vaapi_vpp_render_picture(AVFilterContext *avctx, + VAProcPipelineParameterBuffer *params, + AVFrame *output_frame) +{ + return ff_vaapi_vpp_render_pictures(avctx, params, 1, output_frame); +} + void ff_vaapi_vpp_ctx_init(AVFilterContext *avctx) { int i; diff --git a/libavfilter/vaapi_vpp.h b/libavfilter/vaapi_vpp.h index c3da91717c9..ead07036dce 100644 --- a/libavfilter/vaapi_vpp.h +++ b/libavfilter/vaapi_vpp.h @@ -83,4 +83,9 @@ int ff_vaapi_vpp_render_picture(AVFilterContext *avctx, VAProcPipelineParameterBuffer *params, AVFrame *output_frame); +int ff_vaapi_vpp_render_pictures(AVFilterContext *avctx, + VAProcPipelineParameterBuffer *params_list, + int count, + AVFrame *output_frame); + #endif /* AVFILTER_VAAPI_VPP_H */ diff --git a/libavfilter/vf_overlay_vaapi.c b/libavfilter/vf_overlay_vaapi.c index 307f3cf7fc7..79cf66d0681 100644 --- a/libavfilter/vf_overlay_vaapi.c +++ b/libavfilter/vf_overlay_vaapi.c @@ -159,106 +159,6 @@ static int overlay_vaapi_build_filter_params(AVFilterContext *avctx) return 0; } -static int overlay_vaapi_render_picture(AVFilterContext *avctx, - VAProcPipelineParameterBuffer *params, - VAProcPipelineParameterBuffer *subpic_params, - AVFrame *output_frame) -{ - VAAPIVPPContext *ctx = avctx->priv; - VASurfaceID output_surface; - VABufferID params_id; - VABufferID subpic_params_id; - VAStatus vas; - int err = 0; - - output_surface = (VASurfaceID)(uintptr_t)output_frame->data[3]; - - vas = vaBeginPicture(ctx->hwctx->display, - ctx->va_context, output_surface); - if (vas != VA_STATUS_SUCCESS) { - av_log(avctx, AV_LOG_ERROR, "Failed to attach new picture: " - "%d (%s).\n", vas, vaErrorStr(vas)); - err = AVERROR(EIO); - goto fail; - } - - vas = vaCreateBuffer(ctx->hwctx->display, ctx->va_context, - VAProcPipelineParameterBufferType, - sizeof(*params), 1, params, ¶ms_id); - if (vas != VA_STATUS_SUCCESS) { - av_log(avctx, AV_LOG_ERROR, "Failed to create parameter buffer: " - "%d (%s).\n", vas, vaErrorStr(vas)); - err = AVERROR(EIO); - goto fail_after_begin; - } - av_log(avctx, AV_LOG_DEBUG, "Pipeline parameter buffer is %#x.\n", - params_id); - - - vas = vaRenderPicture(ctx->hwctx->display, ctx->va_context, - ¶ms_id, 1); - if (vas != VA_STATUS_SUCCESS) { - av_log(avctx, AV_LOG_ERROR, "Failed to render parameter buffer: " - "%d (%s).\n", vas, vaErrorStr(vas)); - err = AVERROR(EIO); - goto fail_after_begin; - } - - if (subpic_params) { - vas = vaCreateBuffer(ctx->hwctx->display, ctx->va_context, - VAProcPipelineParameterBufferType, - sizeof(*subpic_params), 1, subpic_params, &subpic_params_id); - if (vas != VA_STATUS_SUCCESS) { - av_log(avctx, AV_LOG_ERROR, "Failed to create parameter buffer: " - "%d (%s).\n", vas, vaErrorStr(vas)); - err = AVERROR(EIO); - goto fail_after_begin; - } - av_log(avctx, AV_LOG_DEBUG, "Pipeline subpic parameter buffer is %#x.\n", - subpic_params_id); - - vas = vaRenderPicture(ctx->hwctx->display, ctx->va_context, - &subpic_params_id, 1); - if (vas != VA_STATUS_SUCCESS) { - av_log(avctx, AV_LOG_ERROR, "Failed to render subpic parameter buffer: " - "%d (%s).\n", vas, vaErrorStr(vas)); - err = AVERROR(EIO); - goto fail_after_begin; - } - } - - vas = vaEndPicture(ctx->hwctx->display, ctx->va_context); - if (vas != VA_STATUS_SUCCESS) { - av_log(avctx, AV_LOG_ERROR, "Failed to start picture processing: " - "%d (%s).\n", vas, vaErrorStr(vas)); - err = AVERROR(EIO); - goto fail_after_render; - } - - if (CONFIG_VAAPI_1 || ctx->hwctx->driver_quirks & - AV_VAAPI_DRIVER_QUIRK_RENDER_PARAM_BUFFERS) { - vas = vaDestroyBuffer(ctx->hwctx->display, params_id); - if (vas != VA_STATUS_SUCCESS) { - av_log(avctx, AV_LOG_ERROR, "Failed to free parameter buffer: " - "%d (%s).\n", vas, vaErrorStr(vas)); - // And ignore. - } - } - - return 0; - - // We want to make sure that if vaBeginPicture has been called, we also - // call vaRenderPicture and vaEndPicture. These calls may well fail or - // do something else nasty, but once we're in this failure case there - // isn't much else we can do. -fail_after_begin: - vaRenderPicture(ctx->hwctx->display, ctx->va_context, ¶ms_id, 1); -fail_after_render: - vaEndPicture(ctx->hwctx->display, ctx->va_context); -fail: - return err; -} - static int overlay_vaapi_blend(FFFrameSync *fs) { AVFilterContext *avctx = fs->parent; @@ -267,7 +167,7 @@ static int overlay_vaapi_blend(FFFrameSync *fs) VAAPIVPPContext *vpp_ctx = avctx->priv; AVFrame *input_main, *input_overlay; AVFrame *output; - VAProcPipelineParameterBuffer params, subpic_params; + VAProcPipelineParameterBuffer params[2]; VABlendState blend_state = { 0 }; /**< Blend State */ VARectangle overlay_region, output_region; int err; @@ -296,7 +196,7 @@ static int overlay_vaapi_blend(FFFrameSync *fs) if (err < 0) goto fail; - err = ff_vaapi_vpp_init_params(avctx, ¶ms, + err = ff_vaapi_vpp_init_params(avctx, ¶ms[0], input_main, output); if (err < 0) goto fail; @@ -308,11 +208,11 @@ static int overlay_vaapi_blend(FFFrameSync *fs) .height = output->height, }; - params.filters = &vpp_ctx->filter_buffers[0]; - params.num_filters = vpp_ctx->nb_filter_buffers; + params[0].filters = &vpp_ctx->filter_buffers[0]; + params[0].num_filters = vpp_ctx->nb_filter_buffers; - params.output_region = &output_region; - params.output_background_color = VAAPI_VPP_BACKGROUND_BLACK; + params[0].output_region = &output_region; + params[0].output_background_color = VAAPI_VPP_BACKGROUND_BLACK; if (input_overlay) { av_log(avctx, AV_LOG_DEBUG, "Filter overlay: %s, %ux%u (%"PRId64").\n", @@ -333,17 +233,17 @@ static int overlay_vaapi_blend(FFFrameSync *fs) "will crop the overlay image according based on the main image.\n"); } - memcpy(&subpic_params, ¶ms, sizeof(subpic_params)); + memcpy(¶ms[1], ¶ms[0], sizeof(params[0])); blend_state.flags = ctx->blend_flags; blend_state.global_alpha = ctx->blend_alpha; - subpic_params.blend_state = &blend_state; + params[1].blend_state = &blend_state; - subpic_params.surface = (VASurfaceID)(uintptr_t)input_overlay->data[3]; - subpic_params.output_region = &overlay_region; + params[1].surface = (VASurfaceID)(uintptr_t)input_overlay->data[3]; + params[1].output_region = &overlay_region; } - err = overlay_vaapi_render_picture(avctx, ¶ms, input_overlay ? &subpic_params : NULL, output); + err = ff_vaapi_vpp_render_pictures(avctx, params, input_overlay ? 2 : 1, output); if (err < 0) goto fail; From faf0afb5d937f480186dc4d3e5afc554e9ad0805 Mon Sep 17 00:00:00 2001 From: Haihao Xiang Date: Fri, 13 Jan 2023 12:38:31 +0800 Subject: [PATCH 0018/2172] lavfi/overlay_vaapi: remove unnecessary code VA-API filter is not required. Signed-off-by: Haihao Xiang --- libavfilter/vf_overlay_vaapi.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/libavfilter/vf_overlay_vaapi.c b/libavfilter/vf_overlay_vaapi.c index 79cf66d0681..16d1e0e2113 100644 --- a/libavfilter/vf_overlay_vaapi.c +++ b/libavfilter/vf_overlay_vaapi.c @@ -208,9 +208,6 @@ static int overlay_vaapi_blend(FFFrameSync *fs) .height = output->height, }; - params[0].filters = &vpp_ctx->filter_buffers[0]; - params[0].num_filters = vpp_ctx->nb_filter_buffers; - params[0].output_region = &output_region; params[0].output_background_color = VAAPI_VPP_BACKGROUND_BLACK; From 4d42d82563d806b5610c0c91497e24ef7f37d4cf Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Fri, 13 Jan 2023 01:01:36 +0100 Subject: [PATCH 0019/2172] avcodec/012v: Order operations for odd size handling Fixes: out of array access Fixes: 48567/clusterfuzz-testcase-minimized-ffmpeg_AV_CODEC_ID_ZERO12V_fuzzer-6714182078955520.fuzz Fixes: 48567/clusterfuzz-testcase-minimized-ffmpeg_AV_CODEC_ID_ZERO12V_fuzzer-6698145212137472.fuzz 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 --- libavcodec/012v.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libavcodec/012v.c b/libavcodec/012v.c index 2d89a86b98b..f0197cd8f90 100644 --- a/libavcodec/012v.c +++ b/libavcodec/012v.c @@ -131,8 +131,8 @@ static int zero12v_decode_frame(AVCodecContext *avctx, AVFrame *pic, u = x/2 + (uint16_t *)(pic->data[1] + line * pic->linesize[1]); v = x/2 + (uint16_t *)(pic->data[2] + line * pic->linesize[2]); memcpy(y, y_temp, sizeof(*y) * (width - x)); - memcpy(u, u_temp, sizeof(*u) * (width - x + 1) / 2); - memcpy(v, v_temp, sizeof(*v) * (width - x + 1) / 2); + memcpy(u, u_temp, sizeof(*u) * ((width - x + 1) / 2)); + memcpy(v, v_temp, sizeof(*v) * ((width - x + 1) / 2)); } line_end += stride; From cc7e984a05b28dcfaaaad95afa061be71b4ba7fc Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Mon, 16 Jan 2023 00:01:13 +0100 Subject: [PATCH 0020/2172] avcodec/scpr3: Check bx Fixes: Out of array access Fixes: 55102/clusterfuzz-testcase-minimized-ffmpeg_AV_CODEC_ID_SCPR_fuzzer-4877396618903552 Found-by: continuous fuzzing process https://github.com/google/oss-fuzz/tree/master/projects/ffmpeg Signed-off-by: Michael Niedermayer --- libavcodec/scpr3.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/libavcodec/scpr3.c b/libavcodec/scpr3.c index d9ea6af1c18..5271717ac79 100644 --- a/libavcodec/scpr3.c +++ b/libavcodec/scpr3.c @@ -1167,6 +1167,9 @@ static int decompress_p3(AVCodecContext *avctx, int run, bx = x * 16 + sx1, by = y * 16 + sy1; uint32_t clr, ptype = 0, r, g, b; + if (bx >= avctx->width) + return AVERROR_INVALIDDATA; + for (; by < y * 16 + sy2 && by < avctx->height;) { ret = decode_value3(s, 5, &s->op_model3[ptype].cntsum, s->op_model3[ptype].freqs[0], From 6a205d244ad0754e671062ed24f596e97e60ee7d Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Tue, 17 Jan 2023 14:33:23 +0100 Subject: [PATCH 0021/2172] avfilter/af_afir: call av_frame_copy_props() --- libavfilter/af_afir.c | 1 + 1 file changed, 1 insertion(+) diff --git a/libavfilter/af_afir.c b/libavfilter/af_afir.c index 11fa5074d01..0fe038972f0 100644 --- a/libavfilter/af_afir.c +++ b/libavfilter/af_afir.c @@ -143,6 +143,7 @@ static int fir_frame(AudioFIRContext *s, AVFrame *in, AVFilterLink *outlink) av_frame_free(&in); return AVERROR(ENOMEM); } + av_frame_copy_props(out, in); out->pts = s->pts = in->pts; s->in = in; From 8885d5dc7a8b06f73fb1b1f8c15c033109c3f013 Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Tue, 17 Jan 2023 14:34:09 +0100 Subject: [PATCH 0022/2172] avfilter/af_surround: call av_frame_copy_props() --- libavfilter/af_surround.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavfilter/af_surround.c b/libavfilter/af_surround.c index 702fdc624a8..925cb6e66c8 100644 --- a/libavfilter/af_surround.c +++ b/libavfilter/af_surround.c @@ -1291,7 +1291,7 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in) FFMIN(outlink->ch_layout.nb_channels, ff_filter_get_nb_threads(ctx))); - out->pts = in->pts; + av_frame_copy_props(out, in); out->nb_samples = in->nb_samples; av_frame_free(&in); From 2cee62295fec51b3452148dc3806e9a59d777e86 Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Tue, 17 Jan 2023 14:43:01 +0100 Subject: [PATCH 0023/2172] avfilter/af_dialoguenhance: call av_frame_copy_props() --- libavfilter/af_dialoguenhance.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavfilter/af_dialoguenhance.c b/libavfilter/af_dialoguenhance.c index ae95f95d681..b613733fafa 100644 --- a/libavfilter/af_dialoguenhance.c +++ b/libavfilter/af_dialoguenhance.c @@ -320,7 +320,7 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in) s->in = in; de_stereo(ctx, out); - out->pts = in->pts; + av_frame_copy_props(out, in); out->nb_samples = in->nb_samples; ret = ff_filter_frame(outlink, out); fail: From 6b8adbfe030d318123874456157270e985fd3078 Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Tue, 17 Jan 2023 14:34:47 +0100 Subject: [PATCH 0024/2172] avfilter/avf_a3dscope,avf_showcwt: set video frame duration --- libavfilter/avf_a3dscope.c | 1 + libavfilter/avf_showcwt.c | 1 + 2 files changed, 2 insertions(+) diff --git a/libavfilter/avf_a3dscope.c b/libavfilter/avf_a3dscope.c index 089c8d8c010..d7fe2dcb751 100644 --- a/libavfilter/avf_a3dscope.c +++ b/libavfilter/avf_a3dscope.c @@ -243,6 +243,7 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in) for (int y = 0; y < outlink->h; y++) memset(out->data[0] + y * out->linesize[0], 0, outlink->w * 4); out->pts = av_rescale_q(in->pts, inlink->time_base, outlink->time_base); + out->duration = 1; projection_matrix(s->fov, half_width / half_height, 0.1f, 1000000.f, s->projection_matrix); view_matrix(s->eye, s->zoom, s->roll, s->pitch, s->yaw, s->view_matrix); diff --git a/libavfilter/avf_showcwt.c b/libavfilter/avf_showcwt.c index 2c7c4473057..ed1bc4c65ae 100644 --- a/libavfilter/avf_showcwt.c +++ b/libavfilter/avf_showcwt.c @@ -869,6 +869,7 @@ static int output_frame(AVFilterContext *ctx) int64_t pts_offset = s->new_frame ? 0LL : av_rescale(s->ihop_index, s->hop_size, s->ihop_size); s->outpicref->pts = av_rescale_q(s->in_pts + pts_offset, inlink->time_base, outlink->time_base); + s->outpicref->duration = 1; } s->ihop_index++; From e6b9191e92b637532fa05362782ffba9b9c931fe Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Wed, 11 Jan 2023 21:30:35 +0100 Subject: [PATCH 0025/2172] avfilter/vf_ciescope: switch to anti-aliased lines --- libavfilter/vf_ciescope.c | 43 +++++++++++++++++++++++++++------------ 1 file changed, 30 insertions(+), 13 deletions(-) diff --git a/libavfilter/vf_ciescope.c b/libavfilter/vf_ciescope.c index a0caaa76e98..81a158b14a3 100644 --- a/libavfilter/vf_ciescope.c +++ b/libavfilter/vf_ciescope.c @@ -1010,27 +1010,44 @@ static void draw_line(uint16_t *const pixels, int linesize, int w, int h, const uint16_t *const rgbcolor) { - int dx = FFABS(x1 - x0), sx = x0 < x1 ? 1 : -1; - int dy = FFABS(y1 - y0), sy = y0 < y1 ? 1 : -1; - int err = (dx > dy ? dx : -dy) / 2, e2; + int sx = x0 < x1 ? 1 : -1, sy = y0 < y1 ? 1 : -1, x2; + int dx = FFABS(x1-x0), dy = FFABS(y1-y0), err = dx * dx + dy * dy; + int e2 = err == 0 ? 1 : 0xffffff / (dx + dy); - for (;;) { - pixels[y0 * linesize + x0 * 4 + 0] = rgbcolor[0]; - pixels[y0 * linesize + x0 * 4 + 1] = rgbcolor[1]; - pixels[y0 * linesize + x0 * 4 + 2] = rgbcolor[2]; - pixels[y0 * linesize + x0 * 4 + 3] = rgbcolor[3]; + dx *= e2; + dy *= e2; + err = dx - dy; - if (x0 == x1 && y0 == y1) - break; + for (;;) { + pixels[y0 * linesize + x0 * 4 + 0] = rgbcolor[0]-(FFABS(err - dx + dy) >> 8); + pixels[y0 * linesize + x0 * 4 + 1] = rgbcolor[1]-(FFABS(err - dx + dy) >> 8); + pixels[y0 * linesize + x0 * 4 + 2] = rgbcolor[2]-(FFABS(err - dx + dy) >> 8); + pixels[y0 * linesize + x0 * 4 + 3] = rgbcolor[3]-(FFABS(err - dx + dy) >> 8); e2 = err; - - if (e2 >-dx) { + x2 = x0; + if (2 * e2 >= -dx) { + if (x0 == x1) + break; + if (e2 + dy < 0xff0000) { + pixels[(y0 + sy) * linesize + x0 * 4 + 0] = rgbcolor[0]-(FFABS(e2 + dy) >> 8); + pixels[(y0 + sy) * linesize + x0 * 4 + 1] = rgbcolor[1]-(FFABS(e2 + dy) >> 8); + pixels[(y0 + sy) * linesize + x0 * 4 + 2] = rgbcolor[2]-(FFABS(e2 + dy) >> 8); + pixels[(y0 + sy) * linesize + x0 * 4 + 3] = rgbcolor[3]-(FFABS(e2 + dy) >> 8); + } err -= dy; x0 += sx; } - if (e2 < dy) { + if (2 * e2 <= dy) { + if (y0 == y1) + break; + if (dx - e2 < 0xff0000) { + pixels[y0 * linesize + (x2 + sx) * 4 + 0] = rgbcolor[0]-(FFABS(dx - e2) >> 8); + pixels[y0 * linesize + (x2 + sx) * 4 + 1] = rgbcolor[1]-(FFABS(dx - e2) >> 8); + pixels[y0 * linesize + (x2 + sx) * 4 + 2] = rgbcolor[2]-(FFABS(dx - e2) >> 8); + pixels[y0 * linesize + (x2 + sx) * 4 + 3] = rgbcolor[3]-(FFABS(dx - e2) >> 8); + } err += dx; y0 += sy; } From d590fbf306a800710065952041885478d5cf0bd3 Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Tue, 17 Jan 2023 10:45:41 +0100 Subject: [PATCH 0026/2172] avfilter/vf_ciescope: fix black-point position --- libavfilter/vf_ciescope.c | 34 ++++++++++++++++------------------ 1 file changed, 16 insertions(+), 18 deletions(-) diff --git a/libavfilter/vf_ciescope.c b/libavfilter/vf_ciescope.c index 81a158b14a3..1af86f202cb 100644 --- a/libavfilter/vf_ciescope.c +++ b/libavfilter/vf_ciescope.c @@ -855,8 +855,6 @@ rgb_to_xy(float rc, *z = m[2][0] * rc + m[2][1] * gc + m[2][2] * bc; scale = *x + *y + *z; - if (scale == 0.f) - scale = 1.f; scale = 1.f / scale; *x = *x * scale; *y = *y * scale; @@ -1270,11 +1268,11 @@ static void filter_rgb48(AVFilterContext *ctx, const uint8_t *ptr, float *cx, float *cy, int x, int y) { CiescopeContext *s = ctx->priv; - const float scale = 1. / 65535.; + const float scale = 1.f / 65535.f; const uint16_t *src = (const uint16_t*)(ptr + linesize * y + x * 6); - float r = src[0] * scale; - float g = src[1] * scale; - float b = src[2] * scale; + float r = (src[0] + 0.01f) * scale; + float g = (src[1] + 0.01f) * scale; + float b = (src[2] + 0.01f) * scale; float cz; rgb_to_xy(r, g, b, cx, cy, &cz, (const float (*)[3])s->m); @@ -1285,11 +1283,11 @@ static void filter_rgba64(AVFilterContext *ctx, const uint8_t *ptr, float *cx, float *cy, int x, int y) { CiescopeContext *s = ctx->priv; - const float scale = 1. / 65535.; + const float scale = 1.f / 65535.f; const uint16_t *src = (const uint16_t*)(ptr + linesize * y + x * 8); - float r = src[0] * scale; - float g = src[1] * scale; - float b = src[2] * scale; + float r = (src[0] + 0.01f) * scale; + float g = (src[1] + 0.01f) * scale; + float b = (src[2] + 0.01f) * scale; float cz; rgb_to_xy(r, g, b, cx, cy, &cz, (const float (*)[3])s->m); @@ -1300,11 +1298,11 @@ static void filter_rgb24(AVFilterContext *ctx, const uint8_t *ptr, float *cx, float *cy, int x, int y) { CiescopeContext *s = ctx->priv; - const float scale = 1. / 255.; + const float scale = 1.f / 255.f; const uint8_t *src = ptr + linesize * y + x * 3; - float r = src[0] * scale; - float g = src[1] * scale; - float b = src[2] * scale; + float r = (src[0] + 0.01f) * scale; + float g = (src[1] + 0.01f) * scale; + float b = (src[2] + 0.01f) * scale; float cz; rgb_to_xy(r, g, b, cx, cy, &cz, (const float (*)[3])s->m); @@ -1315,11 +1313,11 @@ static void filter_rgba(AVFilterContext *ctx, const uint8_t *ptr, float *cx, float *cy, int x, int y) { CiescopeContext *s = ctx->priv; - const float scale = 1. / 255.; + const float scale = 1.f / 255.f; const uint8_t *src = ptr + linesize * y + x * 4; - float r = src[0] * scale; - float g = src[1] * scale; - float b = src[2] * scale; + float r = (src[0] + 0.01f) * scale; + float g = (src[1] + 0.01f) * scale; + float b = (src[2] + 0.01f) * scale; float cz; rgb_to_xy(r, g, b, cx, cy, &cz, (const float (*)[3])s->m); From aa247198439394144d1d8ef33534857389c10e60 Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Tue, 17 Jan 2023 15:35:07 +0100 Subject: [PATCH 0027/2172] avfilter/vsrc_sierpinski: set video frame duration --- libavfilter/vsrc_sierpinski.c | 1 + 1 file changed, 1 insertion(+) diff --git a/libavfilter/vsrc_sierpinski.c b/libavfilter/vsrc_sierpinski.c index 898fb5ae54a..72b28b1bd79 100644 --- a/libavfilter/vsrc_sierpinski.c +++ b/libavfilter/vsrc_sierpinski.c @@ -196,6 +196,7 @@ static int sierpinski_request_frame(AVFilterLink *link) frame->sample_aspect_ratio = (AVRational) {1, 1}; frame->pts = s->pts++; + frame->duration = 1; draw_sierpinski(link->src, frame); From 218278b11dbb9c16bea95f3c8333fc242677a402 Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Tue, 17 Jan 2023 15:36:58 +0100 Subject: [PATCH 0028/2172] avfilter/vsrc_testsrc: set video frame duration --- libavfilter/vsrc_testsrc.c | 1 + 1 file changed, 1 insertion(+) diff --git a/libavfilter/vsrc_testsrc.c b/libavfilter/vsrc_testsrc.c index e7d8d9ea1a0..9760e5fc805 100644 --- a/libavfilter/vsrc_testsrc.c +++ b/libavfilter/vsrc_testsrc.c @@ -183,6 +183,7 @@ static int activate(AVFilterContext *ctx) if (!frame) return AVERROR(ENOMEM); frame->pts = test->pts; + frame->duration = 1; frame->key_frame = 1; frame->interlaced_frame = 0; frame->pict_type = AV_PICTURE_TYPE_I; From 96d4f745482c6003981015fd05d820fab91973a2 Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Tue, 17 Jan 2023 15:39:05 +0100 Subject: [PATCH 0029/2172] avfilter/vsrc_mptestsrc: set video frame duration --- libavfilter/vsrc_mptestsrc.c | 1 + 1 file changed, 1 insertion(+) diff --git a/libavfilter/vsrc_mptestsrc.c b/libavfilter/vsrc_mptestsrc.c index 03073dcf5a3..55b723af004 100644 --- a/libavfilter/vsrc_mptestsrc.c +++ b/libavfilter/vsrc_mptestsrc.c @@ -308,6 +308,7 @@ static int request_frame(AVFilterLink *outlink) if (!picref) return AVERROR(ENOMEM); picref->pts = test->pts++; + picref->duration = 1; // clean image for (i = 0; i < h; i++) From 45910b2504e2e2931357ba4b03272d15c4755d1f Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Tue, 17 Jan 2023 15:40:39 +0100 Subject: [PATCH 0030/2172] avfilter/vsrc_mandelbrot: set video frame duration --- libavfilter/vsrc_mandelbrot.c | 1 + 1 file changed, 1 insertion(+) diff --git a/libavfilter/vsrc_mandelbrot.c b/libavfilter/vsrc_mandelbrot.c index d4d7e2fa492..aa63f9edd1f 100644 --- a/libavfilter/vsrc_mandelbrot.c +++ b/libavfilter/vsrc_mandelbrot.c @@ -395,6 +395,7 @@ static int request_frame(AVFilterLink *link) picref->sample_aspect_ratio = (AVRational) {1, 1}; picref->pts = s->pts++; + picref->duration = 1; draw_mandelbrot(link->src, (uint32_t*)picref->data[0], picref->linesize[0]/4, picref->pts); return ff_filter_frame(link, picref); From e845c3e00a34a43b0ab19fbdc944a69a225b11cf Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Tue, 17 Jan 2023 15:41:36 +0100 Subject: [PATCH 0031/2172] avfilter/vsrc_life: set video frame duration --- libavfilter/vsrc_life.c | 1 + 1 file changed, 1 insertion(+) diff --git a/libavfilter/vsrc_life.c b/libavfilter/vsrc_life.c index d40c38b953e..9f83ca5e189 100644 --- a/libavfilter/vsrc_life.c +++ b/libavfilter/vsrc_life.c @@ -404,6 +404,7 @@ static int request_frame(AVFilterLink *outlink) return AVERROR(ENOMEM); picref->sample_aspect_ratio = (AVRational) {1, 1}; picref->pts = life->pts++; + picref->duration = 1; life->draw(outlink->src, picref); evolve(outlink->src); From 6d2b57fd31742e27d2fc6f6dbf88fa5ecdffcf05 Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Tue, 17 Jan 2023 15:43:13 +0100 Subject: [PATCH 0032/2172] avfilter/vsrc_cellauto: set video frame duration --- libavfilter/vsrc_cellauto.c | 1 + 1 file changed, 1 insertion(+) diff --git a/libavfilter/vsrc_cellauto.c b/libavfilter/vsrc_cellauto.c index 226182daf27..8c682a70523 100644 --- a/libavfilter/vsrc_cellauto.c +++ b/libavfilter/vsrc_cellauto.c @@ -302,6 +302,7 @@ static int request_frame(AVFilterLink *outlink) evolve(outlink->src); picref->pts = s->pts++; + picref->duration = 1; #ifdef DEBUG show_cellauto_row(outlink->src); From 5625f0542de2eebe8255d318f279d8c2f66c7c4d Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Tue, 17 Jan 2023 15:53:52 +0100 Subject: [PATCH 0033/2172] avfilter/af_afftdn: call av_frame_copy_props() --- libavfilter/af_afftdn.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavfilter/af_afftdn.c b/libavfilter/af_afftdn.c index aa30e35d576..de17dc1b2ce 100644 --- a/libavfilter/af_afftdn.c +++ b/libavfilter/af_afftdn.c @@ -1196,7 +1196,7 @@ static int output_frame(AVFilterLink *inlink, AVFrame *in) return AVERROR(ENOMEM); } - out->pts = in->pts; + av_frame_copy_props(out, in); } for (int ch = 0; ch < inlink->ch_layout.nb_channels; ch++) { From 697e0fc06231f54781156c01de1590096db22fba Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Tue, 17 Jan 2023 15:57:25 +0100 Subject: [PATCH 0034/2172] avfilter/af_afftfilt: call av_frame_copy_props() --- libavfilter/af_afftfilt.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavfilter/af_afftfilt.c b/libavfilter/af_afftfilt.c index a65ccc85944..9b09dcaa39f 100644 --- a/libavfilter/af_afftfilt.c +++ b/libavfilter/af_afftfilt.c @@ -345,7 +345,7 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in) goto fail; } - out->pts = in->pts; + av_frame_copy_props(out, in); out->nb_samples = in->nb_samples; for (ch = 0; ch < inlink->ch_layout.nb_channels; ch++) { From 180a7d2d6c0cdc7d5d84195d318e1aef5233dc62 Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Tue, 17 Jan 2023 17:30:13 +0100 Subject: [PATCH 0035/2172] avfilter/af_arnndn: call av_frame_copy_props() --- libavfilter/af_arnndn.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavfilter/af_arnndn.c b/libavfilter/af_arnndn.c index 3ef222bc8e4..1325f3d6d70 100644 --- a/libavfilter/af_arnndn.c +++ b/libavfilter/af_arnndn.c @@ -1436,7 +1436,7 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in) av_frame_free(&in); return AVERROR(ENOMEM); } - out->pts = in->pts; + av_frame_copy_props(out, in); td.in = in; td.out = out; ff_filter_execute(ctx, rnnoise_channels, &td, NULL, From 11b02fc675bc2a4b98001c0f64fbcd45758077d9 Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Tue, 17 Jan 2023 17:43:54 +0100 Subject: [PATCH 0036/2172] avfilter/af_arnndn: unbreak filtering --- libavfilter/af_arnndn.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/libavfilter/af_arnndn.c b/libavfilter/af_arnndn.c index 1325f3d6d70..634f3b972fe 100644 --- a/libavfilter/af_arnndn.c +++ b/libavfilter/af_arnndn.c @@ -373,14 +373,15 @@ static int config_input(AVFilterLink *inlink) for (int i = 0; i < s->channels; i++) { DenoiseState *st = &s->st[i]; + float scale = 1.f; if (!st->tx) - ret = av_tx_init(&st->tx, &st->tx_fn, AV_TX_FLOAT_FFT, 0, WINDOW_SIZE, NULL, 0); + ret = av_tx_init(&st->tx, &st->tx_fn, AV_TX_FLOAT_FFT, 0, WINDOW_SIZE, &scale, 0); if (ret < 0) return ret; if (!st->txi) - ret = av_tx_init(&st->txi, &st->txi_fn, AV_TX_FLOAT_FFT, 1, WINDOW_SIZE, NULL, 0); + ret = av_tx_init(&st->txi, &st->txi_fn, AV_TX_FLOAT_FFT, 1, WINDOW_SIZE, &scale, 0); if (ret < 0) return ret; } @@ -416,7 +417,7 @@ static void forward_transform(DenoiseState *st, AVComplexFloat *out, const float x[i].im = 0; } - st->tx_fn(st->tx, y, x, sizeof(float)); + st->tx_fn(st->tx, y, x, sizeof(AVComplexFloat)); RNN_COPY(out, y, FREQ_SIZE); } @@ -433,7 +434,7 @@ static void inverse_transform(DenoiseState *st, float *out, const AVComplexFloat x[i].im = -x[WINDOW_SIZE - i].im; } - st->txi_fn(st->txi, y, x, sizeof(float)); + st->txi_fn(st->txi, y, x, sizeof(AVComplexFloat)); for (int i = 0; i < WINDOW_SIZE; i++) out[i] = y[i].re / WINDOW_SIZE; From 07485a697552641609df73fd411de1ea964f1ef2 Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Tue, 17 Jan 2023 18:01:02 +0100 Subject: [PATCH 0037/2172] avfilter/vf_scdet: change threshold checking Also allow score to match threshold thus allowing ==0.0 scores. --- libavfilter/vf_scdet.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavfilter/vf_scdet.c b/libavfilter/vf_scdet.c index 1576759c24a..daddc2e6657 100644 --- a/libavfilter/vf_scdet.c +++ b/libavfilter/vf_scdet.c @@ -163,7 +163,7 @@ static int activate(AVFilterContext *ctx) snprintf(buf, sizeof(buf), "%0.3f", s->scene_score); set_meta(s, frame, "lavfi.scd.score", buf); - if (s->scene_score > s->threshold) { + if (s->scene_score >= s->threshold) { av_log(s, AV_LOG_INFO, "lavfi.scd.score: %.3f, lavfi.scd.time: %s\n", s->scene_score, av_ts2timestr(frame->pts, &inlink->time_base)); set_meta(s, frame, "lavfi.scd.time", From 2c3f211b6dacf314f235fc700cd31084049a6886 Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Tue, 17 Jan 2023 18:21:56 +0100 Subject: [PATCH 0038/2172] avfilter/af_virtualbass: call av_frame_copy_props() --- libavfilter/af_virtualbass.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavfilter/af_virtualbass.c b/libavfilter/af_virtualbass.c index 950159096be..76b3f420302 100644 --- a/libavfilter/af_virtualbass.c +++ b/libavfilter/af_virtualbass.c @@ -146,10 +146,10 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in) av_frame_free(&in); return AVERROR(ENOMEM); } + av_frame_copy_props(out, in); vb_stereo(ctx, out, in); - out->pts = in->pts; av_frame_free(&in); return ff_filter_frame(outlink, out); } From a13931843eccb35fe6a594a33e04869173cb94b6 Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Tue, 17 Jan 2023 18:26:41 +0100 Subject: [PATCH 0039/2172] avfilter/avf_abitscope: set output time_base and output frame duration --- libavfilter/avf_abitscope.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/libavfilter/avf_abitscope.c b/libavfilter/avf_abitscope.c index 58e2bdaf616..4fc3c06ecbf 100644 --- a/libavfilter/avf_abitscope.c +++ b/libavfilter/avf_abitscope.c @@ -143,6 +143,7 @@ static int config_output(AVFilterLink *outlink) outlink->h = s->h; outlink->sample_aspect_ratio = (AVRational){1,1}; outlink->frame_rate = s->frame_rate; + outlink->time_base = av_inv_q(outlink->frame_rate); return 0; } @@ -233,7 +234,8 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *insamples) return AVERROR(ENOMEM); } - outpicref->pts = insamples->pts; + outpicref->pts = av_rescale_q(insamples->pts, inlink->time_base, outlink->time_base); + outpicref->duration = 1; outpicref->sample_aspect_ratio = (AVRational){1,1}; switch (insamples->format) { From 04bbf5f70d281f11d1ee94c8ee3a91912d3a6c6a Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Tue, 17 Jan 2023 18:48:09 +0100 Subject: [PATCH 0040/2172] avfilter/vsrc_gradients: set output video frame duration --- libavfilter/vsrc_gradients.c | 1 + 1 file changed, 1 insertion(+) diff --git a/libavfilter/vsrc_gradients.c b/libavfilter/vsrc_gradients.c index c005613d422..3c524b92423 100644 --- a/libavfilter/vsrc_gradients.c +++ b/libavfilter/vsrc_gradients.c @@ -402,6 +402,7 @@ static int activate(AVFilterContext *ctx) frame->pict_type = AV_PICTURE_TYPE_I; frame->sample_aspect_ratio = (AVRational) {1, 1}; frame->pts = s->pts++; + frame->duration = 1; ff_filter_execute(ctx, s->draw_slice, frame, NULL, FFMIN(outlink->h, ff_filter_get_nb_threads(ctx))); From ceb52d47a36f581c32bff7c91f7d1f80b0ae9050 Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Tue, 17 Jan 2023 18:55:52 +0100 Subject: [PATCH 0041/2172] avfilter/avf_showvolume: set output video frame duration --- libavfilter/avf_showvolume.c | 1 + 1 file changed, 1 insertion(+) diff --git a/libavfilter/avf_showvolume.c b/libavfilter/avf_showvolume.c index 952f079a678..24d42d030d4 100644 --- a/libavfilter/avf_showvolume.c +++ b/libavfilter/avf_showvolume.c @@ -339,6 +339,7 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *insamples) clear_picture(s, outlink); } s->out->pts = av_rescale_q(insamples->pts, inlink->time_base, outlink->time_base); + s->out->duration = 1; if ((s->f < 1.) && (s->f > 0.)) { for (j = 0; j < outlink->h; j++) { From 3cc08688e3f41bd49563f61d35f40bbc78c4e369 Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Tue, 17 Jan 2023 22:36:03 +0100 Subject: [PATCH 0042/2172] avfilter/vf_elbg: call av_frame_copy_props() --- libavfilter/vf_elbg.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavfilter/vf_elbg.c b/libavfilter/vf_elbg.c index fc73346ae12..d1166714fc4 100644 --- a/libavfilter/vf_elbg.c +++ b/libavfilter/vf_elbg.c @@ -187,7 +187,7 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *frame) av_frame_free(&frame); return AVERROR(ENOMEM); } - out->pts = frame->pts; + av_frame_copy_props(out, frame); av_frame_free(&frame); pal = (uint32_t *)out->data[1]; p0 = (uint8_t *)out->data[0]; From 6ce51e5ee14492d8f5af10ea500b25c615c0fc31 Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Tue, 17 Jan 2023 22:50:38 +0100 Subject: [PATCH 0043/2172] avfilter/vf_lagfun: call av_frame_copy_props() --- libavfilter/vf_lagfun.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavfilter/vf_lagfun.c b/libavfilter/vf_lagfun.c index 69191ac1d36..352f08512f7 100644 --- a/libavfilter/vf_lagfun.c +++ b/libavfilter/vf_lagfun.c @@ -173,7 +173,7 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in) av_frame_free(&in); return AVERROR(ENOMEM); } - out->pts = in->pts; + av_frame_copy_props(out, in); td.out = out; td.in = in; From c13d95934327ddad4db30f6aee93cd2aa6a26a57 Mon Sep 17 00:00:00 2001 From: OvchinnikovDmitrii Date: Thu, 6 Oct 2022 15:49:59 +0200 Subject: [PATCH 0044/2172] lavc/libvpx: increase thread limit to 64 This change improves the performance and multicore scalability of the vp9 codec for streaming single-pass encoded videos by taking advantage of up to 64 cores in the system. The current thread limit for ffmpeg codecs is 16 (MAX_AUTO_THREADS in pthread_internal.h) due to a limitation in H.264 codec that prevents more than 16 threads being used. Experiments show that increasing the thread limit to 64 for vp9 improves the performance for encoding 4K raw videos for streaming by up to 47% compared to 16 threads, and from 20-30% for 32 threads, with the same quality as measured by the VMAF score. Rationale for this change: Vp9 uses tiling to split the video frame into multiple columns; tiles must be at least 256 pixels wide, so there is a limit to how many tiles can be used. The tiles can be processed in parallel, and more tiles mean more CPU threads can be used. 4K videos can make use of 16 threads, and 8K videos can use 32. Row-mt can double the number of threads so 64 threads can be used. Signed-off-by: James Zern --- libavcodec/libvpx.h | 2 ++ libavcodec/libvpxdec.c | 2 +- libavcodec/libvpxenc.c | 2 +- 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/libavcodec/libvpx.h b/libavcodec/libvpx.h index 0caed8cdcb3..331feb8745a 100644 --- a/libavcodec/libvpx.h +++ b/libavcodec/libvpx.h @@ -25,6 +25,8 @@ #include "codec_internal.h" +#define MAX_VPX_THREADS 64 + void ff_vp9_init_static(FFCodec *codec); #if 0 enum AVPixelFormat ff_vpx_imgfmt_to_pixfmt(vpx_img_fmt_t img); diff --git a/libavcodec/libvpxdec.c b/libavcodec/libvpxdec.c index 9cd2c56cafd..0ae19c3f72a 100644 --- a/libavcodec/libvpxdec.c +++ b/libavcodec/libvpxdec.c @@ -88,7 +88,7 @@ static av_cold int vpx_init(AVCodecContext *avctx, const struct vpx_codec_iface *iface) { struct vpx_codec_dec_cfg deccfg = { - .threads = FFMIN(avctx->thread_count ? avctx->thread_count : av_cpu_count(), 16) + .threads = FFMIN(avctx->thread_count ? avctx->thread_count : av_cpu_count(), MAX_VPX_THREADS) }; av_log(avctx, AV_LOG_INFO, "%s\n", vpx_codec_version_str()); diff --git a/libavcodec/libvpxenc.c b/libavcodec/libvpxenc.c index 9aa5510c280..339d4d81469 100644 --- a/libavcodec/libvpxenc.c +++ b/libavcodec/libvpxenc.c @@ -942,7 +942,7 @@ static av_cold int vpx_init(AVCodecContext *avctx, enccfg.g_timebase.num = avctx->time_base.num; enccfg.g_timebase.den = avctx->time_base.den; enccfg.g_threads = - FFMIN(avctx->thread_count ? avctx->thread_count : av_cpu_count(), 16); + FFMIN(avctx->thread_count ? avctx->thread_count : av_cpu_count(), MAX_VPX_THREADS); enccfg.g_lag_in_frames= ctx->lag_in_frames; if (avctx->flags & AV_CODEC_FLAG_PASS1) From bf23d530d25370819792378d72979a137e6527b9 Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Tue, 17 Jan 2023 23:17:07 +0100 Subject: [PATCH 0045/2172] avfilter/vf_histogram: call av_frame_copy_props() --- libavfilter/vf_histogram.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavfilter/vf_histogram.c b/libavfilter/vf_histogram.c index ced7cda6f44..83477692cd5 100644 --- a/libavfilter/vf_histogram.c +++ b/libavfilter/vf_histogram.c @@ -593,7 +593,7 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in) memset(s->histogram, 0, s->histogram_size * sizeof(unsigned)); } - out->pts = in->pts; + av_frame_copy_props(out, in); av_frame_free(&in); s->x_pos++; if (s->x_pos >= s->width) { From 0b33310cd02aa8e33b2fc1613d13cadb83bb7da8 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Sun, 15 Jan 2023 10:21:36 +0100 Subject: [PATCH 0046/2172] lavc/bitstream: avoid UB in bits_{read,peek}_signed(0) bits_*_signed(0) will currently invoke an undefined shift by 8 * sizeof(int). Add bits_*_signed_nz() that only works for n>0, analogous to bits_read_nz(). Add an explicit check for n=0 in bits_*_signed(). Found-by: James Almer --- libavcodec/bitstream.h | 4 ++++ libavcodec/bitstream_template.h | 36 +++++++++++++++++++++++++++++++-- libavcodec/get_bits.h | 2 +- 3 files changed, 39 insertions(+), 3 deletions(-) diff --git a/libavcodec/bitstream.h b/libavcodec/bitstream.h index ef7d8d55c24..b60f0c296d1 100644 --- a/libavcodec/bitstream.h +++ b/libavcodec/bitstream.h @@ -89,9 +89,11 @@ # define bits_read_63 bits_read_63_le # define bits_read_64 bits_read_64_le # define bits_read_signed bits_read_signed_le +# define bits_read_signed_nz bits_read_signed_nz_le # define bits_peek_nz bits_peek_nz_le # define bits_peek bits_peek_le # define bits_peek_signed bits_peek_signed_le +# define bits_peek_signed_nz bits_peek_signed_nz_le # define bits_skip bits_skip_le # define bits_seek bits_seek_le # define bits_align bits_align_le @@ -115,9 +117,11 @@ # define bits_read_63 bits_read_63_be # define bits_read_64 bits_read_64_be # define bits_read_signed bits_read_signed_be +# define bits_read_signed_nz bits_read_signed_nz_be # define bits_peek_nz bits_peek_nz_be # define bits_peek bits_peek_be # define bits_peek_signed bits_peek_signed_be +# define bits_peek_signed_nz bits_peek_signed_nz_be # define bits_skip bits_skip_be # define bits_seek bits_seek_be # define bits_align bits_align_be diff --git a/libavcodec/bitstream_template.h b/libavcodec/bitstream_template.h index f2c14fc4d37..30bea84add6 100644 --- a/libavcodec/bitstream_template.h +++ b/libavcodec/bitstream_template.h @@ -290,13 +290,29 @@ static inline uint64_t BS_FUNC(read_64)(BSCTX *bc, unsigned int n) return BS_FUNC(read_63)(bc, n); } +/** + * Return n bits from the buffer as a signed integer, n has to be in the 1-32 + * range. May be faster than bits_read_signed() when n is not a compile-time + * constant and is known to be non-zero; + */ +static inline int32_t BS_FUNC(read_signed_nz)(BSCTX *bc, unsigned int n) +{ + av_assert2(n > 0 && n <= 32); + return sign_extend(BS_FUNC(read_nz)(bc, n), n); +} + /** * Return n bits from the buffer as a signed integer. * n has to be in the 0-32 range. */ static inline int32_t BS_FUNC(read_signed)(BSCTX *bc, unsigned int n) { - return sign_extend(BS_FUNC(read)(bc, n), n); + av_assert2(n <= 32); + + if (!n) + return 0; + + return BS_FUNC(read_signed_nz)(bc, n); } /** @@ -327,6 +343,17 @@ static inline uint32_t BS_FUNC(peek)(BSCTX *bc, unsigned int n) return BS_FUNC(peek_nz)(bc, n); } +/** + * Return n bits from the buffer as a signed integer, do not change the buffer + * state. n has to be in the 1-32 range. May be faster than bits_peek_signed() + * when n is not a compile-time constant and is known to be non-zero; + */ +static inline int BS_FUNC(peek_signed_nz)(BSCTX *bc, unsigned int n) +{ + av_assert2(n > 0 && n <= 32); + return sign_extend(BS_FUNC(peek_nz)(bc, n), n); +} + /** * Return n bits from the buffer as a signed integer, * do not change the buffer state. @@ -334,7 +361,12 @@ static inline uint32_t BS_FUNC(peek)(BSCTX *bc, unsigned int n) */ static inline int BS_FUNC(peek_signed)(BSCTX *bc, unsigned int n) { - return sign_extend(BS_FUNC(peek)(bc, n), n); + av_assert2(n <= 32); + + if (!n) + return 0; + + return BS_FUNC(peek_signed_nz)(bc, n); } /** diff --git a/libavcodec/get_bits.h b/libavcodec/get_bits.h index 1aa327a4acb..65dc080ddb3 100644 --- a/libavcodec/get_bits.h +++ b/libavcodec/get_bits.h @@ -85,7 +85,7 @@ typedef BitstreamContext GetBitContext; #define get_bits1 bits_read_bit #define get_bits64 bits_read_64 #define get_xbits bits_read_xbits -#define get_sbits bits_read_signed +#define get_sbits bits_read_signed_nz #define get_sbits_long bits_read_signed #define show_bits bits_peek #define show_bits_long bits_peek From ba36e6ed5213571162c7ef4db6fab3c0c2090212 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Sun, 15 Jan 2023 10:41:21 +0100 Subject: [PATCH 0047/2172] lavc/tests/bitstream: test bits_*_signed_nz and bits_peek_signed* --- libavcodec/tests/bitstream_template.c | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/libavcodec/tests/bitstream_template.c b/libavcodec/tests/bitstream_template.c index 13e92a31c6f..ef59845154d 100644 --- a/libavcodec/tests/bitstream_template.c +++ b/libavcodec/tests/bitstream_template.c @@ -42,6 +42,7 @@ enum Op { OP_READ_63, OP_READ_64, OP_READ_SIGNED, + OP_READ_SIGNED_NZ, OP_APPLY_SIGN, OP_ALIGN, OP_NB, @@ -58,7 +59,7 @@ int main(int argc, char **argv) uint32_t random_seed; uint64_t val, val1; - int32_t sval; + int32_t sval, sval1; unsigned count; /* generate random input, using a given or random seed */ @@ -130,10 +131,26 @@ int main(int argc, char **argv) break; case OP_READ_SIGNED: count = av_lfg_get(&lfg) % FFMIN(33, bits_left(&bc) + 1); + sval1 = bits_peek_signed(&bc, count); sval = bits_read_signed(&bc, count); fprintf(stderr, "%d read_signed %u: %"PRId32"\n", bits_tell(&bc) - count, count, sval); + av_assert0(sval == sval1); + + if (count == 32) put_bits32(&pb, sval); + else put_sbits(&pb, count, sval); + break; + case OP_READ_SIGNED_NZ: + count = av_lfg_get(&lfg) % FFMIN(33, bits_left(&bc) + 1); + count = FFMAX(count, 1); + sval1 = bits_peek_signed_nz(&bc, count); + sval = bits_read_signed_nz(&bc, count); + + fprintf(stderr, "%d read_signed_nz %u: %"PRId32"\n", bits_tell(&bc) - count, count, sval); + + av_assert0(sval == sval1); + if (count == 32) put_bits32(&pb, sval); else put_sbits(&pb, count, sval); break; From 31c15a0880d0f5064d9c84aae23275ee8baddd5c Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Thu, 19 Jan 2023 12:13:38 +0100 Subject: [PATCH 0048/2172] avfilter/vf_dblur: allow radius < 1.0 --- libavfilter/vf_dblur.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavfilter/vf_dblur.c b/libavfilter/vf_dblur.c index 131a3ae30ab..14f8e2e37f5 100644 --- a/libavfilter/vf_dblur.c +++ b/libavfilter/vf_dblur.c @@ -47,7 +47,7 @@ typedef struct DBlurContext { static const AVOption dblur_options[] = { { "angle", "set angle", OFFSET(angle), AV_OPT_TYPE_FLOAT, {.dbl=45}, 0.0, 360, FLAGS }, - { "radius", "set radius", OFFSET(radius), AV_OPT_TYPE_FLOAT, {.dbl=5}, 1, 8192, FLAGS }, + { "radius", "set radius", OFFSET(radius), AV_OPT_TYPE_FLOAT, {.dbl=5}, 0, 8192, FLAGS }, { "planes", "set planes to filter", OFFSET(planes), AV_OPT_TYPE_INT, {.i64=0xF}, 0, 0xF, FLAGS }, { NULL } }; From ab8cde6efa84e547ea07a0c47146091a0066c73c Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Thu, 19 Jan 2023 12:31:00 +0100 Subject: [PATCH 0049/2172] avfilter/vf_dblur: also filter last scanline --- 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 14f8e2e37f5..7dcb873ba8c 100644 --- a/libavfilter/vf_dblur.c +++ b/libavfilter/vf_dblur.c @@ -67,7 +67,7 @@ static int filter_horizontally(AVFilterContext *ctx, int width, int height) float g; if (s->R3 > 0) { - for (int y = 1; y < height - 1; y++) { + for (int y = 1; y < height; y++) { 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; @@ -83,7 +83,7 @@ static int filter_horizontally(AVFilterContext *ctx, int width, int height) } } } else { - for (int y = 1; y < height - 1; y++) { + for (int y = 1; y < height; y++) { 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; From 9d5e66942c5bae578926e29efebec348199798df Mon Sep 17 00:00:00 2001 From: Leo Izen Date: Wed, 18 Jan 2023 09:16:37 -0500 Subject: [PATCH 0050/2172] avcodec/libjxldec: fix gamma22 and gamma28 recognition Gamma 2.2 and Gamma 2.8 are tagged in the file as 0.45455 and 0.35714, respectively (i.e. 1/2.2 and 1/2.8). Trying to identify them as 2.2 and 2.8 instead of these values will cause the transfer function to not properly be recognized. This patch fixes this. --- libavcodec/libjxldec.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libavcodec/libjxldec.c b/libavcodec/libjxldec.c index de48bea4b2c..c85cfa3d690 100644 --- a/libavcodec/libjxldec.c +++ b/libavcodec/libjxldec.c @@ -167,9 +167,9 @@ static enum AVColorTransferCharacteristic libjxl_get_trc(void *avctx, const JxlC case JXL_TRANSFER_FUNCTION_DCI: return AVCOL_TRC_SMPTE428; case JXL_TRANSFER_FUNCTION_HLG: return AVCOL_TRC_ARIB_STD_B67; case JXL_TRANSFER_FUNCTION_GAMMA: - if (jxl_color->gamma > 2.199 && jxl_color->gamma < 2.201) + if (jxl_color->gamma > 0.45355 && jxl_color->gamma < 0.45555) return AVCOL_TRC_GAMMA22; - else if (jxl_color->gamma > 2.799 && jxl_color->gamma < 2.801) + else if (jxl_color->gamma > 0.35614 && jxl_color->gamma < 0.35814) return AVCOL_TRC_GAMMA28; else av_log(avctx, AV_LOG_WARNING, "Unsupported gamma transfer: %f\n", jxl_color->gamma); From c5a545cff864366c22487b47a2e605a06464790e Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Sat, 21 Jan 2023 12:21:44 +0100 Subject: [PATCH 0051/2172] avcodec: add WADY DPCM decoder --- Changelog | 1 + libavcodec/Makefile | 1 + libavcodec/allcodecs.c | 1 + libavcodec/codec_desc.c | 7 +++++++ libavcodec/codec_id.h | 1 + libavcodec/dpcm.c | 45 +++++++++++++++++++++++++++++++++++++++-- libavcodec/utils.c | 1 + libavcodec/version.h | 2 +- 8 files changed, 56 insertions(+), 3 deletions(-) diff --git a/Changelog b/Changelog index 5c01e8365ed..c50ebf99510 100644 --- a/Changelog +++ b/Changelog @@ -29,6 +29,7 @@ version : - corr video filter - adrc audio filter - afdelaysrc audio filter +- WADY DPCM decoder version 5.1: diff --git a/libavcodec/Makefile b/libavcodec/Makefile index 651d3024424..2ad4400a813 100644 --- a/libavcodec/Makefile +++ b/libavcodec/Makefile @@ -774,6 +774,7 @@ OBJS-$(CONFIG_VPLAYER_DECODER) += textdec.o ass.o OBJS-$(CONFIG_VP9_V4L2M2M_DECODER) += v4l2_m2m_dec.o OBJS-$(CONFIG_VQA_DECODER) += vqavideo.o OBJS-$(CONFIG_VQC_DECODER) += vqcdec.o +OBJS-$(CONFIG_WADY_DPCM_DECODER) += dpcm.o OBJS-$(CONFIG_WAVPACK_DECODER) += wavpack.o wavpackdata.o dsd.o OBJS-$(CONFIG_WAVPACK_ENCODER) += wavpackdata.o wavpackenc.o OBJS-$(CONFIG_WBMP_DECODER) += wbmpdec.o diff --git a/libavcodec/allcodecs.c b/libavcodec/allcodecs.c index b009848a44b..46aaa89e99a 100644 --- a/libavcodec/allcodecs.c +++ b/libavcodec/allcodecs.c @@ -628,6 +628,7 @@ extern const FFCodec ff_roq_dpcm_decoder; extern const FFCodec ff_sdx2_dpcm_decoder; extern const FFCodec ff_sol_dpcm_decoder; extern const FFCodec ff_xan_dpcm_decoder; +extern const FFCodec ff_wady_dpcm_decoder; /* ADPCM codecs */ extern const FFCodec ff_adpcm_4xm_decoder; diff --git a/libavcodec/codec_desc.c b/libavcodec/codec_desc.c index 24a0433dbac..2272232ed6a 100644 --- a/libavcodec/codec_desc.c +++ b/libavcodec/codec_desc.c @@ -2619,6 +2619,13 @@ static const AVCodecDescriptor codec_descriptors[] = { .long_name = NULL_IF_CONFIG_SMALL("DPCM Xilam DERF"), .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSY, }, + { + .id = AV_CODEC_ID_WADY_DPCM, + .type = AVMEDIA_TYPE_AUDIO, + .name = "wady_dpcm", + .long_name = NULL_IF_CONFIG_SMALL("DPCM Marble WADY"), + .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSY, + }, /* audio codecs */ { diff --git a/libavcodec/codec_id.h b/libavcodec/codec_id.h index f436a2b624f..5ec3fd4b30d 100644 --- a/libavcodec/codec_id.h +++ b/libavcodec/codec_id.h @@ -430,6 +430,7 @@ enum AVCodecID { AV_CODEC_ID_SDX2_DPCM, AV_CODEC_ID_GREMLIN_DPCM, AV_CODEC_ID_DERF_DPCM, + AV_CODEC_ID_WADY_DPCM, /* audio codecs */ AV_CODEC_ID_MP2 = 0x15000, diff --git a/libavcodec/dpcm.c b/libavcodec/dpcm.c index 2425f84eb9c..2420647bc09 100644 --- a/libavcodec/dpcm.c +++ b/libavcodec/dpcm.c @@ -45,7 +45,8 @@ typedef struct DPCMContext { int16_t array[256]; - int sample[2]; ///< previous sample (for SOL_DPCM) + int sample[2]; ///< previous sample (for SOL_DPCM and WADY_DPCM) + int scale; ///< scale for WADY_DPCM const int8_t *sol_table; ///< delta table for SOL_DPCM } DPCMContext; @@ -126,6 +127,24 @@ static const int16_t sol_table_16[128] = { 0xF00, 0x1000, 0x1400, 0x1800, 0x1C00, 0x2000, 0x3000, 0x4000 }; +static const int16_t wady_table[128] = { + 0, 2, 4, 6, 8, 10, 12, 15, + 18, 21, 24, 28, 32, 36, 40, 44, + 49, 54, 59, 64, 70, 76, 82, 88, + 95, 102, 109, 116, 124, 132, 140, 148, + 160, 170, 180, 190, 200, 210, 220, 230, + 240, 255, 270, 285, 300, 320, 340, 360, + 380, 400, 425, 450, 475, 500, 525, 550, + 580, 610, 650, 700, 750, 800, 900, 1000, + -0, -2, -4, -6, -8, -10, -12, -15, + -18, -21, -24, -28, -32, -36, -40, -44, + -49, -54, -59, -64, -70, -76, -82, -88, + -95, -102,-109,-116,-124,-132,-140,-148, + -160,-170,-180,-190,-200,-210,-220,-230, + -240,-255,-270,-285,-300,-320,-340,-360, + -380,-400,-425,-450,-475,-500,-525,-550, + -580,-610,-650,-700,-750,-800,-900,-1000, +}; static av_cold int dpcm_decode_init(AVCodecContext *avctx) { @@ -139,7 +158,7 @@ static av_cold int dpcm_decode_init(AVCodecContext *avctx) s->sample[0] = s->sample[1] = 0; - switch(avctx->codec->id) { + switch (avctx->codec->id) { case AV_CODEC_ID_ROQ_DPCM: /* initialize square table */ @@ -193,6 +212,10 @@ static av_cold int dpcm_decode_init(AVCodecContext *avctx) } break; + case AV_CODEC_ID_WADY_DPCM: + s->scale = (avctx->extradata && avctx->extradata_size > 0) ? avctx->extradata[0] : 1; + break; + default: break; } @@ -239,6 +262,7 @@ static int dpcm_decode_frame(AVCodecContext *avctx, AVFrame *frame, else out = buf_size; break; + case AV_CODEC_ID_WADY_DPCM: case AV_CODEC_ID_DERF_DPCM: case AV_CODEC_ID_GREMLIN_DPCM: case AV_CODEC_ID_SDX2_DPCM: @@ -401,6 +425,22 @@ static int dpcm_decode_frame(AVCodecContext *avctx, AVFrame *frame, } } break; + + case AV_CODEC_ID_WADY_DPCM: { + int idx = 0; + + while (output_samples < samples_end) { + const uint8_t n = bytestream2_get_byteu(&gb); + + if (n & 0x80) + s->sample[idx] = sign_extend((n & 0x7f) << 9, 16); + else + s->sample[idx] += s->scale * wady_table[n & 0x7f]; + *output_samples++ = av_clip_int16(s->sample[idx]); + idx ^= stereo; + } + } + break; } *got_frame_ptr = 1; @@ -427,3 +467,4 @@ DPCM_DECODER(AV_CODEC_ID_ROQ_DPCM, roq_dpcm, "DPCM id RoQ"); DPCM_DECODER(AV_CODEC_ID_SDX2_DPCM, sdx2_dpcm, "DPCM Squareroot-Delta-Exact"); DPCM_DECODER(AV_CODEC_ID_SOL_DPCM, sol_dpcm, "DPCM Sol"); DPCM_DECODER(AV_CODEC_ID_XAN_DPCM, xan_dpcm, "DPCM Xan"); +DPCM_DECODER(AV_CODEC_ID_WADY_DPCM, wady_dpcm, "DPCM Marble WADY"); diff --git a/libavcodec/utils.c b/libavcodec/utils.c index 2b63a498b9a..27ab92c9ce5 100644 --- a/libavcodec/utils.c +++ b/libavcodec/utils.c @@ -515,6 +515,7 @@ int av_get_exact_bits_per_sample(enum AVCodecID codec_id) case AV_CODEC_ID_PCM_U8: case AV_CODEC_ID_SDX2_DPCM: case AV_CODEC_ID_DERF_DPCM: + case AV_CODEC_ID_WADY_DPCM: return 8; case AV_CODEC_ID_PCM_S16BE: case AV_CODEC_ID_PCM_S16BE_PLANAR: diff --git a/libavcodec/version.h b/libavcodec/version.h index 6b8a1dbb793..dfd3d5d7e57 100644 --- a/libavcodec/version.h +++ b/libavcodec/version.h @@ -29,7 +29,7 @@ #include "version_major.h" -#define LIBAVCODEC_VERSION_MINOR 56 +#define LIBAVCODEC_VERSION_MINOR 57 #define LIBAVCODEC_VERSION_MICRO 100 #define LIBAVCODEC_VERSION_INT AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \ From b8640bfc99d6fe32890a721b4a837bc6672af6f4 Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Sat, 21 Jan 2023 12:05:30 +0100 Subject: [PATCH 0052/2172] avformat: add WADY demuxer --- Changelog | 2 +- libavformat/Makefile | 1 + libavformat/allformats.c | 1 + libavformat/version.h | 2 +- libavformat/wady.c | 87 ++++++++++++++++++++++++++++++++++++++++ 5 files changed, 91 insertions(+), 2 deletions(-) create mode 100644 libavformat/wady.c diff --git a/Changelog b/Changelog index c50ebf99510..9679abce14b 100644 --- a/Changelog +++ b/Changelog @@ -29,7 +29,7 @@ version : - corr video filter - adrc audio filter - afdelaysrc audio filter -- WADY DPCM decoder +- WADY DPCM decoder and demuxer version 5.1: diff --git a/libavformat/Makefile b/libavformat/Makefile index fa71ec12f72..2d11bcd7a33 100644 --- a/libavformat/Makefile +++ b/libavformat/Makefile @@ -597,6 +597,7 @@ OBJS-$(CONFIG_VPLAYER_DEMUXER) += vplayerdec.o subtitles.o OBJS-$(CONFIG_VQF_DEMUXER) += vqf.o OBJS-$(CONFIG_W64_DEMUXER) += wavdec.o w64.o pcm.o OBJS-$(CONFIG_W64_MUXER) += wavenc.o w64.o +OBJS-$(CONFIG_WADY_DEMUXER) += wady.o pcm.o OBJS-$(CONFIG_WAV_DEMUXER) += wavdec.o pcm.o OBJS-$(CONFIG_WAV_MUXER) += wavenc.o OBJS-$(CONFIG_WC3_DEMUXER) += wc3movie.o diff --git a/libavformat/allformats.c b/libavformat/allformats.c index 62262ae9352..bf8afe2078c 100644 --- a/libavformat/allformats.c +++ b/libavformat/allformats.c @@ -479,6 +479,7 @@ extern const AVInputFormat ff_vplayer_demuxer; extern const AVInputFormat ff_vqf_demuxer; extern const AVInputFormat ff_w64_demuxer; extern const AVOutputFormat ff_w64_muxer; +extern const AVInputFormat ff_wady_demuxer; extern const AVInputFormat ff_wav_demuxer; extern const AVOutputFormat ff_wav_muxer; extern const AVInputFormat ff_wc3_demuxer; diff --git a/libavformat/version.h b/libavformat/version.h index f5a7f579b3e..3970ec5cdd6 100644 --- a/libavformat/version.h +++ b/libavformat/version.h @@ -31,7 +31,7 @@ #include "version_major.h" -#define LIBAVFORMAT_VERSION_MINOR 35 +#define LIBAVFORMAT_VERSION_MINOR 36 #define LIBAVFORMAT_VERSION_MICRO 100 #define LIBAVFORMAT_VERSION_INT AV_VERSION_INT(LIBAVFORMAT_VERSION_MAJOR, \ diff --git a/libavformat/wady.c b/libavformat/wady.c new file mode 100644 index 00000000000..bd9b64f5141 --- /dev/null +++ b/libavformat/wady.c @@ -0,0 +1,87 @@ +/* + * WADY demuxer + * Copyright (c) 2023 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 "libavutil/channel_layout.h" +#include "libavutil/intreadwrite.h" +#include "avformat.h" +#include "demux.h" +#include "internal.h" +#include "pcm.h" + +static int wady_probe(const AVProbeData *p) +{ + if (AV_RL32(p->buf) != MKTAG('W','A','D','Y')) + return 0; + if (p->buf[4] != 0 || p->buf[5] == 0 || + AV_RL16(p->buf+6) == 0 || + AV_RL32(p->buf+8) == 0) + return 0; + + return AVPROBE_SCORE_MAX / 3 * 2; +} + +static int wady_read_header(AVFormatContext *s) +{ + AVIOContext *pb = s->pb; + AVCodecParameters *par; + int channels, ret; + AVStream *st; + + avio_skip(pb, 4); + + st = avformat_new_stream(s, NULL); + if (!st) + return AVERROR(ENOMEM); + + avio_skip(pb, 1); + par = st->codecpar; + par->codec_type = AVMEDIA_TYPE_AUDIO; + par->codec_id = AV_CODEC_ID_WADY_DPCM; + par->format = AV_SAMPLE_FMT_S16; + if ((ret = ff_get_extradata(s, par, pb, 1)) < 0) + return ret; + channels = avio_rl16(pb); + if (channels == 0) + return AVERROR_INVALIDDATA; + av_channel_layout_default(&par->ch_layout, channels); + par->sample_rate = avio_rl32(pb); + if (par->sample_rate <= 0) + return AVERROR_INVALIDDATA; + avio_skip(pb, 4); + st->duration = avio_rl32(pb); + par->block_align = channels; + avpriv_set_pts_info(st, 64, 1, par->sample_rate); + + avio_seek(pb, 0x30, SEEK_SET); + + return 0; +} + +const AVInputFormat ff_wady_demuxer = { + .name = "wady", + .long_name = NULL_IF_CONFIG_SMALL("Marble WADY"), + .read_probe = wady_probe, + .read_header = wady_read_header, + .read_packet = ff_pcm_read_packet, + .read_seek = ff_pcm_read_seek, + .flags = AVFMT_GENERIC_INDEX, + .extensions = "way", +}; From 3110e2845636aaab32c426c25790c7ead2878fde Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Sat, 21 Jan 2023 14:07:48 +0100 Subject: [PATCH 0053/2172] avcodec/dpcm: add .flush Otherwise after seek, DC offset for audio samples might be big. --- libavcodec/dpcm.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/libavcodec/dpcm.c b/libavcodec/dpcm.c index 2420647bc09..86cb9134f8f 100644 --- a/libavcodec/dpcm.c +++ b/libavcodec/dpcm.c @@ -448,6 +448,13 @@ static int dpcm_decode_frame(AVCodecContext *avctx, AVFrame *frame, return avpkt->size; } +static void dpcm_flush(AVCodecContext *avctx) +{ + DPCMContext *s = avctx->priv_data; + + s->sample[0] = s->sample[1] = 0; +} + #define DPCM_DECODER(id_, name_, long_name_) \ const FFCodec ff_ ## name_ ## _decoder = { \ .p.name = #name_, \ @@ -457,6 +464,7 @@ const FFCodec ff_ ## name_ ## _decoder = { \ .p.capabilities = AV_CODEC_CAP_DR1, \ .priv_data_size = sizeof(DPCMContext), \ .init = dpcm_decode_init, \ + .flush = dpcm_flush, \ FF_CODEC_DECODE_CB(dpcm_decode_frame), \ } From 69c060bea21d3b4ce63b5fff40d37e98c70ab88f Mon Sep 17 00:00:00 2001 From: Ashyni Date: Thu, 12 Jan 2023 17:36:34 +0100 Subject: [PATCH 0054/2172] avfilter/vf_cropdetect: add ability to change limit at runtime Fixes: https://trac.ffmpeg.org/ticket/9851 Signed-off-by: Ashyni --- doc/filters.texi | 10 ++++ libavfilter/vf_cropdetect.c | 45 +++++++++++++--- tests/ref/fate/filter-metadata-cropdetect | 60 +++++++++++----------- tests/ref/fate/filter-metadata-cropdetect1 | 14 ++--- tests/ref/fate/filter-metadata-cropdetect2 | 14 ++--- 5 files changed, 93 insertions(+), 50 deletions(-) diff --git a/doc/filters.texi b/doc/filters.texi index be70a2396ba..60e4d113a15 100644 --- a/doc/filters.texi +++ b/doc/filters.texi @@ -10587,6 +10587,16 @@ ffmpeg -flags2 +export_mvs -i file.mp4 -vf cropdetect=mode=mvedges,metadata=mode @end example @end itemize +@subsection Commands + +This filter supports the following commands: + +@table @option +@item limit +The command accepts the same syntax of the corresponding option. +If the specified expression is not valid, it is kept at its current value. +@end table + @anchor{cue} @section cue diff --git a/libavfilter/vf_cropdetect.c b/libavfilter/vf_cropdetect.c index 7e985fb2717..724047f864e 100644 --- a/libavfilter/vf_cropdetect.c +++ b/libavfilter/vf_cropdetect.c @@ -39,6 +39,7 @@ typedef struct CropDetectContext { const AVClass *class; int x1, y1, x2, y2; float limit; + float limit_upscaled; int round; int skip; int reset_count; @@ -48,6 +49,7 @@ typedef struct CropDetectContext { int mode; int window_size; int mv_threshold; + int bitdepth; float low, high; uint8_t low_u8, high_u8; uint8_t *filterbuf; @@ -207,8 +209,12 @@ static int config_input(AVFilterLink *inlink) av_image_fill_max_pixsteps(s->max_pixsteps, NULL, desc); + s->bitdepth = desc->comp[0].depth; + if (s->limit < 1.0) - s->limit *= (1 << desc->comp[0].depth) - 1; + s->limit_upscaled = s->limit * ((1 << s->bitdepth) - 1); + else + s->limit_upscaled = s->limit; s->x1 = inlink->w - 1; s->y1 = inlink->h - 1; @@ -243,7 +249,8 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *frame) int w, h, x, y, shrink_by, i; AVDictionary **metadata; int outliers, last_y; - int limit = lrint(s->limit); + int limit_upscaled = lrint(s->limit_upscaled); + char limit_str[22]; const int inw = inlink->w; const int inh = inlink->h; @@ -278,7 +285,7 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *frame) #define FIND(DST, FROM, NOEND, INC, STEP0, STEP1, LEN) \ outliers = 0;\ for (last_y = y = FROM; NOEND; y = y INC) {\ - if (checkline(ctx, frame->data[0] + STEP0 * y, STEP1, LEN, bpp) > limit) {\ + if (checkline(ctx, frame->data[0] + STEP0 * y, STEP1, LEN, bpp) > limit_upscaled) {\ if (++outliers > s->max_outliers) { \ DST = last_y;\ break;\ @@ -423,21 +430,46 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *frame) SET_META("lavfi.cropdetect.x", x); SET_META("lavfi.cropdetect.y", y); + snprintf(limit_str, sizeof(limit_str), "%f", s->limit); + av_dict_set(metadata, "lavfi.cropdetect.limit", limit_str, 0); + av_log(ctx, AV_LOG_INFO, - "x1:%d x2:%d y1:%d y2:%d w:%d h:%d x:%d y:%d pts:%"PRId64" t:%f crop=%d:%d:%d:%d\n", + "x1:%d x2:%d y1:%d y2:%d w:%d h:%d x:%d y:%d pts:%"PRId64" t:%f limit:%f crop=%d:%d:%d:%d\n", s->x1, s->x2, s->y1, s->y2, w, h, x, y, frame->pts, frame->pts == AV_NOPTS_VALUE ? -1 : frame->pts * av_q2d(inlink->time_base), - w, h, x, y); + s->limit, w, h, x, y); } return ff_filter_frame(inlink->dst->outputs[0], frame); } +static int process_command(AVFilterContext *ctx, const char *cmd, const char *args, + char *res, int res_len, int flags) +{ + CropDetectContext *s = ctx->priv; + int ret; + int old_limit = s->limit; + + if ((ret = ff_filter_process_command(ctx, cmd, args, res, res_len, flags)) < 0) + return ret; + + if (old_limit != s->limit) { + if (s->limit < 1.0) + s->limit_upscaled = s->limit * ((1 << s->bitdepth) - 1); + else + s->limit_upscaled = s->limit; + s->frame_nb = s->reset_count; + } + + return 0; +} + #define OFFSET(x) offsetof(CropDetectContext, x) #define FLAGS AV_OPT_FLAG_VIDEO_PARAM|AV_OPT_FLAG_FILTERING_PARAM +#define TFLAGS AV_OPT_FLAG_FILTERING_PARAM | AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_RUNTIME_PARAM static const AVOption cropdetect_options[] = { - { "limit", "Threshold below which the pixel is considered black", OFFSET(limit), AV_OPT_TYPE_FLOAT, { .dbl = 24.0/255 }, 0, 65535, FLAGS }, + { "limit", "Threshold below which the pixel is considered black", OFFSET(limit), AV_OPT_TYPE_FLOAT, { .dbl = 24.0/255 }, 0, 65535, TFLAGS }, { "round", "Value by which the width/height should be divisible", OFFSET(round), AV_OPT_TYPE_INT, { .i64 = 16 }, 0, INT_MAX, FLAGS }, { "reset", "Recalculate the crop area after this many frames", OFFSET(reset_count), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, INT_MAX, FLAGS }, { "skip", "Number of initial frames to skip", OFFSET(skip), AV_OPT_TYPE_INT, { .i64 = 2 }, 0, INT_MAX, FLAGS }, @@ -481,4 +513,5 @@ const AVFilter ff_vf_cropdetect = { FILTER_OUTPUTS(avfilter_vf_cropdetect_outputs), FILTER_PIXFMTS_ARRAY(pix_fmts), .flags = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC | AVFILTER_FLAG_METADATA_ONLY, + .process_command = process_command, }; diff --git a/tests/ref/fate/filter-metadata-cropdetect b/tests/ref/fate/filter-metadata-cropdetect index f3e1865abd1..384ce4dcfef 100644 --- a/tests/ref/fate/filter-metadata-cropdetect +++ b/tests/ref/fate/filter-metadata-cropdetect @@ -1,33 +1,33 @@ pts=0| pts=400 -pts=800|tag:lavfi.cropdetect.x=0|tag:lavfi.cropdetect.x1=0|tag:lavfi.cropdetect.x2=719|tag:lavfi.cropdetect.y1=61|tag:lavfi.cropdetect.y2=424|tag:lavfi.cropdetect.w=720|tag:lavfi.cropdetect.h=352|tag:lavfi.cropdetect.y=68 -pts=1200|tag:lavfi.cropdetect.x=0|tag:lavfi.cropdetect.x1=0|tag:lavfi.cropdetect.x2=719|tag:lavfi.cropdetect.y1=61|tag:lavfi.cropdetect.y2=424|tag:lavfi.cropdetect.w=720|tag:lavfi.cropdetect.h=352|tag:lavfi.cropdetect.y=68 -pts=1600|tag:lavfi.cropdetect.x=0|tag:lavfi.cropdetect.x1=0|tag:lavfi.cropdetect.x2=719|tag:lavfi.cropdetect.y1=61|tag:lavfi.cropdetect.y2=424|tag:lavfi.cropdetect.w=720|tag:lavfi.cropdetect.h=352|tag:lavfi.cropdetect.y=68 -pts=2000|tag:lavfi.cropdetect.x=0|tag:lavfi.cropdetect.x1=0|tag:lavfi.cropdetect.x2=719|tag:lavfi.cropdetect.y1=61|tag:lavfi.cropdetect.y2=424|tag:lavfi.cropdetect.w=720|tag:lavfi.cropdetect.h=352|tag:lavfi.cropdetect.y=68 -pts=2400|tag:lavfi.cropdetect.x=0|tag:lavfi.cropdetect.x1=0|tag:lavfi.cropdetect.x2=719|tag:lavfi.cropdetect.y1=61|tag:lavfi.cropdetect.y2=424|tag:lavfi.cropdetect.w=720|tag:lavfi.cropdetect.h=352|tag:lavfi.cropdetect.y=68 -pts=2800|tag:lavfi.cropdetect.x=0|tag:lavfi.cropdetect.x1=0|tag:lavfi.cropdetect.x2=719|tag:lavfi.cropdetect.y1=61|tag:lavfi.cropdetect.y2=424|tag:lavfi.cropdetect.w=720|tag:lavfi.cropdetect.h=352|tag:lavfi.cropdetect.y=68 -pts=3200|tag:lavfi.cropdetect.x=0|tag:lavfi.cropdetect.x1=0|tag:lavfi.cropdetect.x2=719|tag:lavfi.cropdetect.y1=61|tag:lavfi.cropdetect.y2=424|tag:lavfi.cropdetect.w=720|tag:lavfi.cropdetect.h=352|tag:lavfi.cropdetect.y=68 -pts=3600|tag:lavfi.cropdetect.x=0|tag:lavfi.cropdetect.x1=0|tag:lavfi.cropdetect.x2=719|tag:lavfi.cropdetect.y1=61|tag:lavfi.cropdetect.y2=424|tag:lavfi.cropdetect.w=720|tag:lavfi.cropdetect.h=352|tag:lavfi.cropdetect.y=68 -pts=4000|tag:lavfi.cropdetect.x=0|tag:lavfi.cropdetect.x1=0|tag:lavfi.cropdetect.x2=719|tag:lavfi.cropdetect.y1=61|tag:lavfi.cropdetect.y2=424|tag:lavfi.cropdetect.w=720|tag:lavfi.cropdetect.h=352|tag:lavfi.cropdetect.y=68 -pts=4400|tag:lavfi.cropdetect.x=0|tag:lavfi.cropdetect.x1=0|tag:lavfi.cropdetect.x2=719|tag:lavfi.cropdetect.y1=61|tag:lavfi.cropdetect.y2=424|tag:lavfi.cropdetect.w=720|tag:lavfi.cropdetect.h=352|tag:lavfi.cropdetect.y=68 -pts=4800|tag:lavfi.cropdetect.x=0|tag:lavfi.cropdetect.x1=0|tag:lavfi.cropdetect.x2=719|tag:lavfi.cropdetect.y1=61|tag:lavfi.cropdetect.y2=424|tag:lavfi.cropdetect.w=720|tag:lavfi.cropdetect.h=352|tag:lavfi.cropdetect.y=68 -pts=5200|tag:lavfi.cropdetect.x=0|tag:lavfi.cropdetect.x1=0|tag:lavfi.cropdetect.x2=719|tag:lavfi.cropdetect.y1=61|tag:lavfi.cropdetect.y2=424|tag:lavfi.cropdetect.w=720|tag:lavfi.cropdetect.h=352|tag:lavfi.cropdetect.y=68 -pts=5600|tag:lavfi.cropdetect.x=0|tag:lavfi.cropdetect.x1=0|tag:lavfi.cropdetect.x2=719|tag:lavfi.cropdetect.y1=61|tag:lavfi.cropdetect.y2=424|tag:lavfi.cropdetect.w=720|tag:lavfi.cropdetect.h=352|tag:lavfi.cropdetect.y=68 -pts=6000|tag:lavfi.cropdetect.x=0|tag:lavfi.cropdetect.x1=0|tag:lavfi.cropdetect.x2=719|tag:lavfi.cropdetect.y1=61|tag:lavfi.cropdetect.y2=424|tag:lavfi.cropdetect.w=720|tag:lavfi.cropdetect.h=352|tag:lavfi.cropdetect.y=68 -pts=6400|tag:lavfi.cropdetect.x=0|tag:lavfi.cropdetect.x1=0|tag:lavfi.cropdetect.x2=719|tag:lavfi.cropdetect.y1=61|tag:lavfi.cropdetect.y2=424|tag:lavfi.cropdetect.w=720|tag:lavfi.cropdetect.h=352|tag:lavfi.cropdetect.y=68 -pts=6800|tag:lavfi.cropdetect.x=0|tag:lavfi.cropdetect.x1=0|tag:lavfi.cropdetect.x2=719|tag:lavfi.cropdetect.y1=61|tag:lavfi.cropdetect.y2=424|tag:lavfi.cropdetect.w=720|tag:lavfi.cropdetect.h=352|tag:lavfi.cropdetect.y=68 -pts=7200|tag:lavfi.cropdetect.x=0|tag:lavfi.cropdetect.x1=0|tag:lavfi.cropdetect.x2=719|tag:lavfi.cropdetect.y1=61|tag:lavfi.cropdetect.y2=424|tag:lavfi.cropdetect.w=720|tag:lavfi.cropdetect.h=352|tag:lavfi.cropdetect.y=68 -pts=7600|tag:lavfi.cropdetect.x=0|tag:lavfi.cropdetect.x1=0|tag:lavfi.cropdetect.x2=719|tag:lavfi.cropdetect.y1=61|tag:lavfi.cropdetect.y2=424|tag:lavfi.cropdetect.w=720|tag:lavfi.cropdetect.h=352|tag:lavfi.cropdetect.y=68 -pts=8000|tag:lavfi.cropdetect.x=0|tag:lavfi.cropdetect.x1=0|tag:lavfi.cropdetect.x2=719|tag:lavfi.cropdetect.y1=61|tag:lavfi.cropdetect.y2=424|tag:lavfi.cropdetect.w=720|tag:lavfi.cropdetect.h=352|tag:lavfi.cropdetect.y=68 -pts=8400|tag:lavfi.cropdetect.x=0|tag:lavfi.cropdetect.x1=0|tag:lavfi.cropdetect.x2=719|tag:lavfi.cropdetect.y1=61|tag:lavfi.cropdetect.y2=424|tag:lavfi.cropdetect.w=720|tag:lavfi.cropdetect.h=352|tag:lavfi.cropdetect.y=68 -pts=8800|tag:lavfi.cropdetect.x=0|tag:lavfi.cropdetect.x1=0|tag:lavfi.cropdetect.x2=719|tag:lavfi.cropdetect.y1=61|tag:lavfi.cropdetect.y2=424|tag:lavfi.cropdetect.w=720|tag:lavfi.cropdetect.h=352|tag:lavfi.cropdetect.y=68 -pts=9200|tag:lavfi.cropdetect.x=0|tag:lavfi.cropdetect.x1=0|tag:lavfi.cropdetect.x2=719|tag:lavfi.cropdetect.y1=61|tag:lavfi.cropdetect.y2=424|tag:lavfi.cropdetect.w=720|tag:lavfi.cropdetect.h=352|tag:lavfi.cropdetect.y=68 -pts=9600|tag:lavfi.cropdetect.x=0|tag:lavfi.cropdetect.x1=0|tag:lavfi.cropdetect.x2=719|tag:lavfi.cropdetect.y1=61|tag:lavfi.cropdetect.y2=424|tag:lavfi.cropdetect.w=720|tag:lavfi.cropdetect.h=352|tag:lavfi.cropdetect.y=68 -pts=10000|tag:lavfi.cropdetect.x=0|tag:lavfi.cropdetect.x1=0|tag:lavfi.cropdetect.x2=719|tag:lavfi.cropdetect.y1=61|tag:lavfi.cropdetect.y2=424|tag:lavfi.cropdetect.w=720|tag:lavfi.cropdetect.h=352|tag:lavfi.cropdetect.y=68 -pts=10400|tag:lavfi.cropdetect.x=0|tag:lavfi.cropdetect.x1=0|tag:lavfi.cropdetect.x2=719|tag:lavfi.cropdetect.y1=61|tag:lavfi.cropdetect.y2=424|tag:lavfi.cropdetect.w=720|tag:lavfi.cropdetect.h=352|tag:lavfi.cropdetect.y=68 -pts=10800|tag:lavfi.cropdetect.x=0|tag:lavfi.cropdetect.x1=0|tag:lavfi.cropdetect.x2=719|tag:lavfi.cropdetect.y1=61|tag:lavfi.cropdetect.y2=424|tag:lavfi.cropdetect.w=720|tag:lavfi.cropdetect.h=352|tag:lavfi.cropdetect.y=68 -pts=11200|tag:lavfi.cropdetect.x=0|tag:lavfi.cropdetect.x1=0|tag:lavfi.cropdetect.x2=719|tag:lavfi.cropdetect.y1=61|tag:lavfi.cropdetect.y2=424|tag:lavfi.cropdetect.w=720|tag:lavfi.cropdetect.h=352|tag:lavfi.cropdetect.y=68 -pts=11600|tag:lavfi.cropdetect.x=0|tag:lavfi.cropdetect.x1=0|tag:lavfi.cropdetect.x2=719|tag:lavfi.cropdetect.y1=61|tag:lavfi.cropdetect.y2=424|tag:lavfi.cropdetect.w=720|tag:lavfi.cropdetect.h=352|tag:lavfi.cropdetect.y=68 -pts=12000|tag:lavfi.cropdetect.x=0|tag:lavfi.cropdetect.x1=0|tag:lavfi.cropdetect.x2=719|tag:lavfi.cropdetect.y1=61|tag:lavfi.cropdetect.y2=424|tag:lavfi.cropdetect.w=720|tag:lavfi.cropdetect.h=352|tag:lavfi.cropdetect.y=68 -pts=12400|tag:lavfi.cropdetect.x=0|tag:lavfi.cropdetect.x1=0|tag:lavfi.cropdetect.x2=719|tag:lavfi.cropdetect.y1=61|tag:lavfi.cropdetect.y2=424|tag:lavfi.cropdetect.w=720|tag:lavfi.cropdetect.h=352|tag:lavfi.cropdetect.y=68 +pts=800|tag:lavfi.cropdetect.y=68|tag:lavfi.cropdetect.x1=0|tag:lavfi.cropdetect.x2=719|tag:lavfi.cropdetect.y1=61|tag:lavfi.cropdetect.y2=424|tag:lavfi.cropdetect.w=720|tag:lavfi.cropdetect.h=352|tag:lavfi.cropdetect.x=0|tag:lavfi.cropdetect.limit=0.094118 +pts=1200|tag:lavfi.cropdetect.y=68|tag:lavfi.cropdetect.x1=0|tag:lavfi.cropdetect.x2=719|tag:lavfi.cropdetect.y1=61|tag:lavfi.cropdetect.y2=424|tag:lavfi.cropdetect.w=720|tag:lavfi.cropdetect.h=352|tag:lavfi.cropdetect.x=0|tag:lavfi.cropdetect.limit=0.094118 +pts=1600|tag:lavfi.cropdetect.y=68|tag:lavfi.cropdetect.x1=0|tag:lavfi.cropdetect.x2=719|tag:lavfi.cropdetect.y1=61|tag:lavfi.cropdetect.y2=424|tag:lavfi.cropdetect.w=720|tag:lavfi.cropdetect.h=352|tag:lavfi.cropdetect.x=0|tag:lavfi.cropdetect.limit=0.094118 +pts=2000|tag:lavfi.cropdetect.y=68|tag:lavfi.cropdetect.x1=0|tag:lavfi.cropdetect.x2=719|tag:lavfi.cropdetect.y1=61|tag:lavfi.cropdetect.y2=424|tag:lavfi.cropdetect.w=720|tag:lavfi.cropdetect.h=352|tag:lavfi.cropdetect.x=0|tag:lavfi.cropdetect.limit=0.094118 +pts=2400|tag:lavfi.cropdetect.y=68|tag:lavfi.cropdetect.x1=0|tag:lavfi.cropdetect.x2=719|tag:lavfi.cropdetect.y1=61|tag:lavfi.cropdetect.y2=424|tag:lavfi.cropdetect.w=720|tag:lavfi.cropdetect.h=352|tag:lavfi.cropdetect.x=0|tag:lavfi.cropdetect.limit=0.094118 +pts=2800|tag:lavfi.cropdetect.y=68|tag:lavfi.cropdetect.x1=0|tag:lavfi.cropdetect.x2=719|tag:lavfi.cropdetect.y1=61|tag:lavfi.cropdetect.y2=424|tag:lavfi.cropdetect.w=720|tag:lavfi.cropdetect.h=352|tag:lavfi.cropdetect.x=0|tag:lavfi.cropdetect.limit=0.094118 +pts=3200|tag:lavfi.cropdetect.y=68|tag:lavfi.cropdetect.x1=0|tag:lavfi.cropdetect.x2=719|tag:lavfi.cropdetect.y1=61|tag:lavfi.cropdetect.y2=424|tag:lavfi.cropdetect.w=720|tag:lavfi.cropdetect.h=352|tag:lavfi.cropdetect.x=0|tag:lavfi.cropdetect.limit=0.094118 +pts=3600|tag:lavfi.cropdetect.y=68|tag:lavfi.cropdetect.x1=0|tag:lavfi.cropdetect.x2=719|tag:lavfi.cropdetect.y1=61|tag:lavfi.cropdetect.y2=424|tag:lavfi.cropdetect.w=720|tag:lavfi.cropdetect.h=352|tag:lavfi.cropdetect.x=0|tag:lavfi.cropdetect.limit=0.094118 +pts=4000|tag:lavfi.cropdetect.y=68|tag:lavfi.cropdetect.x1=0|tag:lavfi.cropdetect.x2=719|tag:lavfi.cropdetect.y1=61|tag:lavfi.cropdetect.y2=424|tag:lavfi.cropdetect.w=720|tag:lavfi.cropdetect.h=352|tag:lavfi.cropdetect.x=0|tag:lavfi.cropdetect.limit=0.094118 +pts=4400|tag:lavfi.cropdetect.y=68|tag:lavfi.cropdetect.x1=0|tag:lavfi.cropdetect.x2=719|tag:lavfi.cropdetect.y1=61|tag:lavfi.cropdetect.y2=424|tag:lavfi.cropdetect.w=720|tag:lavfi.cropdetect.h=352|tag:lavfi.cropdetect.x=0|tag:lavfi.cropdetect.limit=0.094118 +pts=4800|tag:lavfi.cropdetect.y=68|tag:lavfi.cropdetect.x1=0|tag:lavfi.cropdetect.x2=719|tag:lavfi.cropdetect.y1=61|tag:lavfi.cropdetect.y2=424|tag:lavfi.cropdetect.w=720|tag:lavfi.cropdetect.h=352|tag:lavfi.cropdetect.x=0|tag:lavfi.cropdetect.limit=0.094118 +pts=5200|tag:lavfi.cropdetect.y=68|tag:lavfi.cropdetect.x1=0|tag:lavfi.cropdetect.x2=719|tag:lavfi.cropdetect.y1=61|tag:lavfi.cropdetect.y2=424|tag:lavfi.cropdetect.w=720|tag:lavfi.cropdetect.h=352|tag:lavfi.cropdetect.x=0|tag:lavfi.cropdetect.limit=0.094118 +pts=5600|tag:lavfi.cropdetect.y=68|tag:lavfi.cropdetect.x1=0|tag:lavfi.cropdetect.x2=719|tag:lavfi.cropdetect.y1=61|tag:lavfi.cropdetect.y2=424|tag:lavfi.cropdetect.w=720|tag:lavfi.cropdetect.h=352|tag:lavfi.cropdetect.x=0|tag:lavfi.cropdetect.limit=0.094118 +pts=6000|tag:lavfi.cropdetect.y=68|tag:lavfi.cropdetect.x1=0|tag:lavfi.cropdetect.x2=719|tag:lavfi.cropdetect.y1=61|tag:lavfi.cropdetect.y2=424|tag:lavfi.cropdetect.w=720|tag:lavfi.cropdetect.h=352|tag:lavfi.cropdetect.x=0|tag:lavfi.cropdetect.limit=0.094118 +pts=6400|tag:lavfi.cropdetect.y=68|tag:lavfi.cropdetect.x1=0|tag:lavfi.cropdetect.x2=719|tag:lavfi.cropdetect.y1=61|tag:lavfi.cropdetect.y2=424|tag:lavfi.cropdetect.w=720|tag:lavfi.cropdetect.h=352|tag:lavfi.cropdetect.x=0|tag:lavfi.cropdetect.limit=0.094118 +pts=6800|tag:lavfi.cropdetect.y=68|tag:lavfi.cropdetect.x1=0|tag:lavfi.cropdetect.x2=719|tag:lavfi.cropdetect.y1=61|tag:lavfi.cropdetect.y2=424|tag:lavfi.cropdetect.w=720|tag:lavfi.cropdetect.h=352|tag:lavfi.cropdetect.x=0|tag:lavfi.cropdetect.limit=0.094118 +pts=7200|tag:lavfi.cropdetect.y=68|tag:lavfi.cropdetect.x1=0|tag:lavfi.cropdetect.x2=719|tag:lavfi.cropdetect.y1=61|tag:lavfi.cropdetect.y2=424|tag:lavfi.cropdetect.w=720|tag:lavfi.cropdetect.h=352|tag:lavfi.cropdetect.x=0|tag:lavfi.cropdetect.limit=0.094118 +pts=7600|tag:lavfi.cropdetect.y=68|tag:lavfi.cropdetect.x1=0|tag:lavfi.cropdetect.x2=719|tag:lavfi.cropdetect.y1=61|tag:lavfi.cropdetect.y2=424|tag:lavfi.cropdetect.w=720|tag:lavfi.cropdetect.h=352|tag:lavfi.cropdetect.x=0|tag:lavfi.cropdetect.limit=0.094118 +pts=8000|tag:lavfi.cropdetect.y=68|tag:lavfi.cropdetect.x1=0|tag:lavfi.cropdetect.x2=719|tag:lavfi.cropdetect.y1=61|tag:lavfi.cropdetect.y2=424|tag:lavfi.cropdetect.w=720|tag:lavfi.cropdetect.h=352|tag:lavfi.cropdetect.x=0|tag:lavfi.cropdetect.limit=0.094118 +pts=8400|tag:lavfi.cropdetect.y=68|tag:lavfi.cropdetect.x1=0|tag:lavfi.cropdetect.x2=719|tag:lavfi.cropdetect.y1=61|tag:lavfi.cropdetect.y2=424|tag:lavfi.cropdetect.w=720|tag:lavfi.cropdetect.h=352|tag:lavfi.cropdetect.x=0|tag:lavfi.cropdetect.limit=0.094118 +pts=8800|tag:lavfi.cropdetect.y=68|tag:lavfi.cropdetect.x1=0|tag:lavfi.cropdetect.x2=719|tag:lavfi.cropdetect.y1=61|tag:lavfi.cropdetect.y2=424|tag:lavfi.cropdetect.w=720|tag:lavfi.cropdetect.h=352|tag:lavfi.cropdetect.x=0|tag:lavfi.cropdetect.limit=0.094118 +pts=9200|tag:lavfi.cropdetect.y=68|tag:lavfi.cropdetect.x1=0|tag:lavfi.cropdetect.x2=719|tag:lavfi.cropdetect.y1=61|tag:lavfi.cropdetect.y2=424|tag:lavfi.cropdetect.w=720|tag:lavfi.cropdetect.h=352|tag:lavfi.cropdetect.x=0|tag:lavfi.cropdetect.limit=0.094118 +pts=9600|tag:lavfi.cropdetect.y=68|tag:lavfi.cropdetect.x1=0|tag:lavfi.cropdetect.x2=719|tag:lavfi.cropdetect.y1=61|tag:lavfi.cropdetect.y2=424|tag:lavfi.cropdetect.w=720|tag:lavfi.cropdetect.h=352|tag:lavfi.cropdetect.x=0|tag:lavfi.cropdetect.limit=0.094118 +pts=10000|tag:lavfi.cropdetect.y=68|tag:lavfi.cropdetect.x1=0|tag:lavfi.cropdetect.x2=719|tag:lavfi.cropdetect.y1=61|tag:lavfi.cropdetect.y2=424|tag:lavfi.cropdetect.w=720|tag:lavfi.cropdetect.h=352|tag:lavfi.cropdetect.x=0|tag:lavfi.cropdetect.limit=0.094118 +pts=10400|tag:lavfi.cropdetect.y=68|tag:lavfi.cropdetect.x1=0|tag:lavfi.cropdetect.x2=719|tag:lavfi.cropdetect.y1=61|tag:lavfi.cropdetect.y2=424|tag:lavfi.cropdetect.w=720|tag:lavfi.cropdetect.h=352|tag:lavfi.cropdetect.x=0|tag:lavfi.cropdetect.limit=0.094118 +pts=10800|tag:lavfi.cropdetect.y=68|tag:lavfi.cropdetect.x1=0|tag:lavfi.cropdetect.x2=719|tag:lavfi.cropdetect.y1=61|tag:lavfi.cropdetect.y2=424|tag:lavfi.cropdetect.w=720|tag:lavfi.cropdetect.h=352|tag:lavfi.cropdetect.x=0|tag:lavfi.cropdetect.limit=0.094118 +pts=11200|tag:lavfi.cropdetect.y=68|tag:lavfi.cropdetect.x1=0|tag:lavfi.cropdetect.x2=719|tag:lavfi.cropdetect.y1=61|tag:lavfi.cropdetect.y2=424|tag:lavfi.cropdetect.w=720|tag:lavfi.cropdetect.h=352|tag:lavfi.cropdetect.x=0|tag:lavfi.cropdetect.limit=0.094118 +pts=11600|tag:lavfi.cropdetect.y=68|tag:lavfi.cropdetect.x1=0|tag:lavfi.cropdetect.x2=719|tag:lavfi.cropdetect.y1=61|tag:lavfi.cropdetect.y2=424|tag:lavfi.cropdetect.w=720|tag:lavfi.cropdetect.h=352|tag:lavfi.cropdetect.x=0|tag:lavfi.cropdetect.limit=0.094118 +pts=12000|tag:lavfi.cropdetect.y=68|tag:lavfi.cropdetect.x1=0|tag:lavfi.cropdetect.x2=719|tag:lavfi.cropdetect.y1=61|tag:lavfi.cropdetect.y2=424|tag:lavfi.cropdetect.w=720|tag:lavfi.cropdetect.h=352|tag:lavfi.cropdetect.x=0|tag:lavfi.cropdetect.limit=0.094118 +pts=12400|tag:lavfi.cropdetect.y=68|tag:lavfi.cropdetect.x1=0|tag:lavfi.cropdetect.x2=719|tag:lavfi.cropdetect.y1=61|tag:lavfi.cropdetect.y2=424|tag:lavfi.cropdetect.w=720|tag:lavfi.cropdetect.h=352|tag:lavfi.cropdetect.x=0|tag:lavfi.cropdetect.limit=0.094118 diff --git a/tests/ref/fate/filter-metadata-cropdetect1 b/tests/ref/fate/filter-metadata-cropdetect1 index 78fbefd85a3..2525a56fc5b 100644 --- a/tests/ref/fate/filter-metadata-cropdetect1 +++ b/tests/ref/fate/filter-metadata-cropdetect1 @@ -2,10 +2,10 @@ pts=0| pts=1001| -pts=2002|tag:lavfi.cropdetect.x=20|tag:lavfi.cropdetect.x1=20|tag:lavfi.cropdetect.x2=851|tag:lavfi.cropdetect.y1=311|tag:lavfi.cropdetect.y2=601|tag:lavfi.cropdetect.w=832|tag:lavfi.cropdetect.h=288|tag:lavfi.cropdetect.y=314| -pts=3003|tag:lavfi.cropdetect.x=22|tag:lavfi.cropdetect.x1=20|tag:lavfi.cropdetect.x2=885|tag:lavfi.cropdetect.y1=311|tag:lavfi.cropdetect.y2=621|tag:lavfi.cropdetect.w=864|tag:lavfi.cropdetect.h=304|tag:lavfi.cropdetect.y=316| -pts=4004|tag:lavfi.cropdetect.x=4|tag:lavfi.cropdetect.x1=0|tag:lavfi.cropdetect.x2=885|tag:lavfi.cropdetect.y1=115|tag:lavfi.cropdetect.y2=621|tag:lavfi.cropdetect.w=880|tag:lavfi.cropdetect.h=496|tag:lavfi.cropdetect.y=122| -pts=5005|tag:lavfi.cropdetect.x=22|tag:lavfi.cropdetect.x1=20|tag:lavfi.cropdetect.x2=885|tag:lavfi.cropdetect.y1=311|tag:lavfi.cropdetect.y2=621|tag:lavfi.cropdetect.w=864|tag:lavfi.cropdetect.h=304|tag:lavfi.cropdetect.y=316| -pts=6006|tag:lavfi.cropdetect.x=4|tag:lavfi.cropdetect.x1=0|tag:lavfi.cropdetect.x2=885|tag:lavfi.cropdetect.y1=115|tag:lavfi.cropdetect.y2=621|tag:lavfi.cropdetect.w=880|tag:lavfi.cropdetect.h=496|tag:lavfi.cropdetect.y=122| -pts=7007|tag:lavfi.cropdetect.x=4|tag:lavfi.cropdetect.x1=0|tag:lavfi.cropdetect.x2=885|tag:lavfi.cropdetect.y1=115|tag:lavfi.cropdetect.y2=621|tag:lavfi.cropdetect.w=880|tag:lavfi.cropdetect.h=496|tag:lavfi.cropdetect.y=122| -pts=8008|tag:lavfi.cropdetect.x=4|tag:lavfi.cropdetect.x1=0|tag:lavfi.cropdetect.x2=885|tag:lavfi.cropdetect.y1=115|tag:lavfi.cropdetect.y2=621|tag:lavfi.cropdetect.w=880|tag:lavfi.cropdetect.h=496|tag:lavfi.cropdetect.y=122| +pts=2002|tag:lavfi.cropdetect.y=314|tag:lavfi.cropdetect.x1=20|tag:lavfi.cropdetect.x2=851|tag:lavfi.cropdetect.y1=311|tag:lavfi.cropdetect.y2=601|tag:lavfi.cropdetect.w=832|tag:lavfi.cropdetect.h=288|tag:lavfi.cropdetect.x=20|tag:lavfi.cropdetect.limit=0.094118| +pts=3003|tag:lavfi.cropdetect.y=316|tag:lavfi.cropdetect.x1=20|tag:lavfi.cropdetect.x2=885|tag:lavfi.cropdetect.y1=311|tag:lavfi.cropdetect.y2=621|tag:lavfi.cropdetect.w=864|tag:lavfi.cropdetect.h=304|tag:lavfi.cropdetect.x=22|tag:lavfi.cropdetect.limit=0.094118| +pts=4004|tag:lavfi.cropdetect.y=122|tag:lavfi.cropdetect.x1=0|tag:lavfi.cropdetect.x2=885|tag:lavfi.cropdetect.y1=115|tag:lavfi.cropdetect.y2=621|tag:lavfi.cropdetect.w=880|tag:lavfi.cropdetect.h=496|tag:lavfi.cropdetect.x=4|tag:lavfi.cropdetect.limit=0.094118| +pts=5005|tag:lavfi.cropdetect.y=316|tag:lavfi.cropdetect.x1=20|tag:lavfi.cropdetect.x2=885|tag:lavfi.cropdetect.y1=311|tag:lavfi.cropdetect.y2=621|tag:lavfi.cropdetect.w=864|tag:lavfi.cropdetect.h=304|tag:lavfi.cropdetect.x=22|tag:lavfi.cropdetect.limit=0.094118| +pts=6006|tag:lavfi.cropdetect.y=122|tag:lavfi.cropdetect.x1=0|tag:lavfi.cropdetect.x2=885|tag:lavfi.cropdetect.y1=115|tag:lavfi.cropdetect.y2=621|tag:lavfi.cropdetect.w=880|tag:lavfi.cropdetect.h=496|tag:lavfi.cropdetect.x=4|tag:lavfi.cropdetect.limit=0.094118| +pts=7007|tag:lavfi.cropdetect.y=122|tag:lavfi.cropdetect.x1=0|tag:lavfi.cropdetect.x2=885|tag:lavfi.cropdetect.y1=115|tag:lavfi.cropdetect.y2=621|tag:lavfi.cropdetect.w=880|tag:lavfi.cropdetect.h=496|tag:lavfi.cropdetect.x=4|tag:lavfi.cropdetect.limit=0.094118| +pts=8008|tag:lavfi.cropdetect.y=122|tag:lavfi.cropdetect.x1=0|tag:lavfi.cropdetect.x2=885|tag:lavfi.cropdetect.y1=115|tag:lavfi.cropdetect.y2=621|tag:lavfi.cropdetect.w=880|tag:lavfi.cropdetect.h=496|tag:lavfi.cropdetect.x=4|tag:lavfi.cropdetect.limit=0.094118| diff --git a/tests/ref/fate/filter-metadata-cropdetect2 b/tests/ref/fate/filter-metadata-cropdetect2 index e58f00770dd..a5383a1aa52 100644 --- a/tests/ref/fate/filter-metadata-cropdetect2 +++ b/tests/ref/fate/filter-metadata-cropdetect2 @@ -3,10 +3,10 @@ pts=0| pts=512| -pts=1024|tag:lavfi.cropdetect.x=22|tag:lavfi.cropdetect.x1=21|tag:lavfi.cropdetect.x2=1221|tag:lavfi.cropdetect.y1=15|tag:lavfi.cropdetect.y2=1116|tag:lavfi.cropdetect.w=1200|tag:lavfi.cropdetect.h=1088|tag:lavfi.cropdetect.y=22| -pts=1536|tag:lavfi.cropdetect.x=24|tag:lavfi.cropdetect.x1=21|tag:lavfi.cropdetect.x2=1257|tag:lavfi.cropdetect.y1=15|tag:lavfi.cropdetect.y2=1116|tag:lavfi.cropdetect.w=1232|tag:lavfi.cropdetect.h=1088|tag:lavfi.cropdetect.y=22| -pts=2048|tag:lavfi.cropdetect.x=22|tag:lavfi.cropdetect.x1=21|tag:lavfi.cropdetect.x2=1221|tag:lavfi.cropdetect.y1=15|tag:lavfi.cropdetect.y2=1116|tag:lavfi.cropdetect.w=1200|tag:lavfi.cropdetect.h=1088|tag:lavfi.cropdetect.y=22| -pts=2560|tag:lavfi.cropdetect.x=22|tag:lavfi.cropdetect.x1=21|tag:lavfi.cropdetect.x2=1221|tag:lavfi.cropdetect.y1=15|tag:lavfi.cropdetect.y2=1116|tag:lavfi.cropdetect.w=1200|tag:lavfi.cropdetect.h=1088|tag:lavfi.cropdetect.y=22| -pts=3072|tag:lavfi.cropdetect.x=28|tag:lavfi.cropdetect.x1=21|tag:lavfi.cropdetect.x2=817|tag:lavfi.cropdetect.y1=15|tag:lavfi.cropdetect.y2=937|tag:lavfi.cropdetect.w=784|tag:lavfi.cropdetect.h=912|tag:lavfi.cropdetect.y=22| -pts=3584|tag:lavfi.cropdetect.x=28|tag:lavfi.cropdetect.x1=21|tag:lavfi.cropdetect.x2=817|tag:lavfi.cropdetect.y1=38|tag:lavfi.cropdetect.y2=937|tag:lavfi.cropdetect.w=784|tag:lavfi.cropdetect.h=896|tag:lavfi.cropdetect.y=40| -pts=4096|tag:lavfi.cropdetect.x=28|tag:lavfi.cropdetect.x1=21|tag:lavfi.cropdetect.x2=817|tag:lavfi.cropdetect.y1=15|tag:lavfi.cropdetect.y2=937|tag:lavfi.cropdetect.w=784|tag:lavfi.cropdetect.h=912|tag:lavfi.cropdetect.y=22| +pts=1024|tag:lavfi.cropdetect.y=22|tag:lavfi.cropdetect.x1=21|tag:lavfi.cropdetect.x2=1221|tag:lavfi.cropdetect.y1=15|tag:lavfi.cropdetect.y2=1116|tag:lavfi.cropdetect.w=1200|tag:lavfi.cropdetect.h=1088|tag:lavfi.cropdetect.x=22|tag:lavfi.cropdetect.limit=0.094118| +pts=1536|tag:lavfi.cropdetect.y=22|tag:lavfi.cropdetect.x1=21|tag:lavfi.cropdetect.x2=1257|tag:lavfi.cropdetect.y1=15|tag:lavfi.cropdetect.y2=1116|tag:lavfi.cropdetect.w=1232|tag:lavfi.cropdetect.h=1088|tag:lavfi.cropdetect.x=24|tag:lavfi.cropdetect.limit=0.094118| +pts=2048|tag:lavfi.cropdetect.y=22|tag:lavfi.cropdetect.x1=21|tag:lavfi.cropdetect.x2=1221|tag:lavfi.cropdetect.y1=15|tag:lavfi.cropdetect.y2=1116|tag:lavfi.cropdetect.w=1200|tag:lavfi.cropdetect.h=1088|tag:lavfi.cropdetect.x=22|tag:lavfi.cropdetect.limit=0.094118| +pts=2560|tag:lavfi.cropdetect.y=22|tag:lavfi.cropdetect.x1=21|tag:lavfi.cropdetect.x2=1221|tag:lavfi.cropdetect.y1=15|tag:lavfi.cropdetect.y2=1116|tag:lavfi.cropdetect.w=1200|tag:lavfi.cropdetect.h=1088|tag:lavfi.cropdetect.x=22|tag:lavfi.cropdetect.limit=0.094118| +pts=3072|tag:lavfi.cropdetect.y=22|tag:lavfi.cropdetect.x1=21|tag:lavfi.cropdetect.x2=817|tag:lavfi.cropdetect.y1=15|tag:lavfi.cropdetect.y2=937|tag:lavfi.cropdetect.w=784|tag:lavfi.cropdetect.h=912|tag:lavfi.cropdetect.x=28|tag:lavfi.cropdetect.limit=0.094118| +pts=3584|tag:lavfi.cropdetect.y=40|tag:lavfi.cropdetect.x1=21|tag:lavfi.cropdetect.x2=817|tag:lavfi.cropdetect.y1=38|tag:lavfi.cropdetect.y2=937|tag:lavfi.cropdetect.w=784|tag:lavfi.cropdetect.h=896|tag:lavfi.cropdetect.x=28|tag:lavfi.cropdetect.limit=0.094118| +pts=4096|tag:lavfi.cropdetect.y=22|tag:lavfi.cropdetect.x1=21|tag:lavfi.cropdetect.x2=817|tag:lavfi.cropdetect.y1=15|tag:lavfi.cropdetect.y2=937|tag:lavfi.cropdetect.w=784|tag:lavfi.cropdetect.h=912|tag:lavfi.cropdetect.x=28|tag:lavfi.cropdetect.limit=0.094118| From 20b96494de5a76fd932d4231d4afde2e5c2c6e59 Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Tue, 24 Jan 2023 22:00:43 +0100 Subject: [PATCH 0055/2172] avfilter/vf_scdet: fix introduced discrepancy with latest change --- libavfilter/vf_scdet.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavfilter/vf_scdet.c b/libavfilter/vf_scdet.c index daddc2e6657..8dcce5ada64 100644 --- a/libavfilter/vf_scdet.c +++ b/libavfilter/vf_scdet.c @@ -170,7 +170,7 @@ static int activate(AVFilterContext *ctx) av_ts2timestr(frame->pts, &inlink->time_base)); } if (s->sc_pass) { - if (s->scene_score > s->threshold) + if (s->scene_score >= s->threshold) return ff_filter_frame(outlink, frame); else { av_frame_free(&frame); From aaa49a7a425ce3dc6ca8edc0e17ed16c98f699a6 Mon Sep 17 00:00:00 2001 From: Mark Thompson Date: Wed, 18 Jan 2023 20:30:50 +0000 Subject: [PATCH 0056/2172] cbs_av1: Remove constraint on MDCV luminance values While desiring min to be less than max feels entirely sensible, unfortunately the standard does not actually have this requirement. --- libavcodec/cbs_av1_syntax_template.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/libavcodec/cbs_av1_syntax_template.c b/libavcodec/cbs_av1_syntax_template.c index d98d3d42dea..e95925a493e 100644 --- a/libavcodec/cbs_av1_syntax_template.c +++ b/libavcodec/cbs_av1_syntax_template.c @@ -1862,11 +1862,8 @@ static int FUNC(metadata_hdr_mdcv)(CodedBitstreamContext *ctx, RWContext *rw, fb(16, white_point_chromaticity_x); fb(16, white_point_chromaticity_y); - fc(32, luminance_max, 1, MAX_UINT_BITS(32)); - // luminance_min must be lower than luminance_max. Convert luminance_max from - // 24.8 fixed point to 18.14 fixed point in order to compare them. - fc(32, luminance_min, 0, FFMIN(((uint64_t)current->luminance_max << 6) - 1, - MAX_UINT_BITS(32))); + fb(32, luminance_max); + fb(32, luminance_min); return 0; } From b6219c91144e665c98ceda9189e5f2bf75232fa8 Mon Sep 17 00:00:00 2001 From: Stefano Sabatini Date: Wed, 13 Jul 2022 01:28:33 +0200 Subject: [PATCH 0057/2172] ffprobe: use pkt->dts to compute interval ts when pts is missing For some samples the pkt->pts is always missing, use the pkt->dts instead. Fix trac issue: http://trac.ffmpeg.org/ticket/4427 --- fftools/ffprobe.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/fftools/ffprobe.c b/fftools/ffprobe.c index b9310a2d251..619ea9a6025 100644 --- a/fftools/ffprobe.c +++ b/fftools/ffprobe.c @@ -2874,9 +2874,10 @@ static int read_interval_packets(WriterContext *w, InputFile *ifile, } if (selected_streams[pkt->stream_index]) { AVRational tb = ifile->streams[pkt->stream_index].st->time_base; + int64_t pts = pkt->pts != AV_NOPTS_VALUE ? pkt->pts : pkt->dts; - if (pkt->pts != AV_NOPTS_VALUE) - *cur_ts = av_rescale_q(pkt->pts, tb, AV_TIME_BASE_Q); + if (pts != AV_NOPTS_VALUE) + *cur_ts = av_rescale_q(pts, tb, AV_TIME_BASE_Q); if (!has_start && *cur_ts != AV_NOPTS_VALUE) { start = *cur_ts; From 843a4467131fd677aacb46b8bbdea898e4fe12d5 Mon Sep 17 00:00:00 2001 From: Stefano Sabatini Date: Sun, 7 Aug 2022 21:24:32 +0200 Subject: [PATCH 0058/2172] ffprobe: fix data hash rendering Print data hash before side data list, fix wrong nesting level of data hash element. In particular, fix trac issue: http://trac.ffmpeg.org/ticket/7217 --- fftools/ffprobe.c | 6 +- tests/ref/fate/flv-demux | 8 +- tests/ref/fate/gapless-mp3-side-data | 12 +- tests/ref/fate/oggopus-demux | 8 +- tests/ref/fate/ts-demux | 72 +- tests/ref/fate/ts-opus-demux | 2048 +++++++++++++------------- tests/ref/fate/ts-small-demux | 292 ++-- 7 files changed, 1223 insertions(+), 1223 deletions(-) diff --git a/fftools/ffprobe.c b/fftools/ffprobe.c index 619ea9a6025..dfa7ff1b241 100644 --- a/fftools/ffprobe.c +++ b/fftools/ffprobe.c @@ -2515,6 +2515,9 @@ static void show_packet(WriterContext *w, InputFile *ifile, AVPacket *pkt, int p else print_str_opt("pos", "N/A"); print_fmt("flags", "%c%c", pkt->flags & AV_PKT_FLAG_KEY ? 'K' : '_', pkt->flags & AV_PKT_FLAG_DISCARD ? 'D' : '_'); + if (do_show_data) + writer_print_data(w, "data", pkt->data, pkt->size); + writer_print_data_hash(w, "data_hash", pkt->data, pkt->size); if (pkt->side_data_elems) { size_t size; @@ -2533,9 +2536,6 @@ static void show_packet(WriterContext *w, InputFile *ifile, AVPacket *pkt, int p SECTION_ID_PACKET_SIDE_DATA); } - if (do_show_data) - writer_print_data(w, "data", pkt->data, pkt->size); - writer_print_data_hash(w, "data_hash", pkt->data, pkt->size); writer_print_section_footer(w); av_bprint_finalize(&pbuf, NULL); diff --git a/tests/ref/fate/flv-demux b/tests/ref/fate/flv-demux index 9282d934af2..07d9ab5ee4a 100644 --- a/tests/ref/fate/flv-demux +++ b/tests/ref/fate/flv-demux @@ -1,7 +1,7 @@ -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 -|data_hash=CRC32:3f2ccc9e +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_|data_hash=CRC32:bbb61b93|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_|data_hash=CRC32:3f2ccc9e|side_data|side_data_type=New Extradata + 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 packet|codec_type=video|stream_index=0|pts=67|pts_time=0.067000|dts=67|dts_time=0.067000|duration=33|duration_time=0.033000|size=14|pos=3560|flags=__|data_hash=CRC32:0b3c3ab4 diff --git a/tests/ref/fate/gapless-mp3-side-data b/tests/ref/fate/gapless-mp3-side-data index b290e66bd1c..edbf91a9d22 100644 --- a/tests/ref/fate/gapless-mp3-side-data +++ b/tests/ref/fate/gapless-mp3-side-data @@ -1,5 +1,5 @@ -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=0|pts_time=0.000000|dts=0|dts_time=0.000000|duration=368640|duration_time=0.026122|size=417|pos=1451|flags=K_|data_hash=CRC32:ae0a5066|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=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 packet|codec_type=audio|stream_index=0|pts=1105920|pts_time=0.078367|dts=1105920|dts_time=0.078367|duration=368640|duration_time=0.026122|size=418|pos=2704|flags=K_|data_hash=CRC32:baec14f8 @@ -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 -|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 -|data_hash=CRC32:3789f3cf +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_|data_hash=CRC32:d5fb5f9c|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=218972160|pts_time=15.516735|dts=218972160|dts_time=15.516735|duration=368640|duration_time=0.026122|size=418|pos=249718|flags=K_|data_hash=CRC32:3789f3cf|side_data|side_data_type=Skip Samples|skip_samples=0|discard_padding=1152|skip_reason=0|discard_reason=0 + 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|initial_padding=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/oggopus-demux b/tests/ref/fate/oggopus-demux index 09de2bf23cd..ad24639bf4c 100644 --- a/tests/ref/fate/oggopus-demux +++ b/tests/ref/fate/oggopus-demux @@ -1,5 +1,5 @@ -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=-356|pts_time=-0.007417|dts=-356|dts_time=-0.007417|duration=960|duration_time=0.020000|size=402|pos=841|flags=K_|data_hash=CRC32:052ff811|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=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 packet|codec_type=audio|stream_index=0|pts=2524|pts_time=0.052583|dts=2524|dts_time=0.052583|duration=960|duration_time=0.020000|size=218|pos=841|flags=K_|data_hash=CRC32:3326bc9f @@ -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 -|data_hash=CRC32:01ca3f8f +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_|data_hash=CRC32:01ca3f8f|side_data|side_data_type=Skip Samples|skip_samples=0|discard_padding=604|skip_reason=0|discard_reason=0 + 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|initial_padding=356|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 39fdc182caa..f221b45c6d5 100644 --- a/tests/ref/fate/ts-demux +++ b/tests/ref/fate/ts-demux @@ -1,43 +1,43 @@ -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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|data_hash=CRC32:25b60d38 +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_|data_hash=CRC32:9bc8b561|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=__|data_hash=CRC32:4f8c97dd|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=__|data_hash=CRC32:27f259db|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=__|data_hash=CRC32:a6588b80|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=__|data_hash=CRC32:33547f9f|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=__|data_hash=CRC32:547f3d4e|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=__|data_hash=CRC32:fb5f4b9e|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=__|data_hash=CRC32:1fb84db4|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=__|data_hash=CRC32:77516f2c|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=__|data_hash=CRC32:7e6594e5|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=__|data_hash=CRC32:31c8b89d|side_data|side_data_type=MPEGTS Stream ID|id=224 + +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_|data_hash=CRC32:25b60d38|side_data|side_data_type=MPEGTS Stream ID|id=189 + 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 -|data_hash=CRC32:34b350c9 +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_|data_hash=CRC32:34b350c9|side_data|side_data_type=MPEGTS Stream ID|id=189 + 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 -|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 -|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 -|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 -|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 -|data_hash=CRC32:3dad674a +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=__|data_hash=CRC32:826f8e8e|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=__|data_hash=CRC32:6b15be8c|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=__|data_hash=CRC32:911b1649|side_data|side_data_type=MPEGTS Stream ID|id=224 + +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_|data_hash=CRC32:d2f2012f|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_|data_hash=CRC32:3dad674a|side_data|side_data_type=MPEGTS Stream ID|id=189 + 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 diff --git a/tests/ref/fate/ts-opus-demux b/tests/ref/fate/ts-opus-demux index 883475058d0..9660ed879aa 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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 +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_|data_hash=CRC32:eec8d060|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_|data_hash=CRC32:c5307335|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_|data_hash=CRC32:6f1c0bfa|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_|data_hash=CRC32:765b2eab|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_|data_hash=CRC32:490463dd|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_|data_hash=CRC32:beef1221|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_|data_hash=CRC32:7814e1fe|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_|data_hash=CRC32:1e28bf7d|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_|data_hash=CRC32:ac39390f|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_|data_hash=CRC32:56129f6c|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_|data_hash=CRC32:444cf0b3|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_|data_hash=CRC32:b26188cc|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_|data_hash=CRC32:550b5ea5|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_|data_hash=CRC32:3b587071|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_|data_hash=CRC32:c655d80f|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_|data_hash=CRC32:4734bf58|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_|data_hash=CRC32:58ddcd0e|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_|data_hash=CRC32:50786001|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_|data_hash=CRC32:4c8c5dc8|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_|data_hash=CRC32:ad3f1eda|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_|data_hash=CRC32:8b7c8437|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_|data_hash=CRC32:c52621e3|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_|data_hash=CRC32:4b34b632|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_|data_hash=CRC32:79f06d2c|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_|data_hash=CRC32:31136ff8|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_|data_hash=CRC32:d6cd17f2|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_|data_hash=CRC32:bd4ada7b|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_|data_hash=CRC32:59132b5d|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_|data_hash=CRC32:6d3ba392|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_|data_hash=CRC32:b9341220|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_|data_hash=CRC32:cd0b0be2|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_|data_hash=CRC32:c0a97918|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_|data_hash=CRC32:b4da2c7e|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_|data_hash=CRC32:aaf0a9b2|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_|data_hash=CRC32:a09994ed|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_|data_hash=CRC32:ded67e51|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_|data_hash=CRC32:17f0a2c0|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_|data_hash=CRC32:92d1d4ad|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_|data_hash=CRC32:3752c787|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_|data_hash=CRC32:ab24f03b|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_|data_hash=CRC32:920e19f5|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_|data_hash=CRC32:951b6d50|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_|data_hash=CRC32:cfc9eb30|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_|data_hash=CRC32:dd66bb72|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_|data_hash=CRC32:67b1c809|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_|data_hash=CRC32:94d441b0|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_|data_hash=CRC32:178471e0|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_|data_hash=CRC32:90e30fb2|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_|data_hash=CRC32:dd4e1d03|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_|data_hash=CRC32:0e059caf|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_|data_hash=CRC32:1981fa52|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_|data_hash=CRC32:6af0ac25|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_|data_hash=CRC32:4ed14497|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_|data_hash=CRC32:b1712b61|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_|data_hash=CRC32:97469bbe|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_|data_hash=CRC32:f2f922fc|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_|data_hash=CRC32:024f521d|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_|data_hash=CRC32:674d82ba|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_|data_hash=CRC32:79409537|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_|data_hash=CRC32:aad393ee|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_|data_hash=CRC32:9e2dee75|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_|data_hash=CRC32:1d8953b4|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_|data_hash=CRC32:3f191e37|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_|data_hash=CRC32:8e05df12|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_|data_hash=CRC32:d3d2e07c|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_|data_hash=CRC32:22e0dee4|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_|data_hash=CRC32:7e1fae18|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_|data_hash=CRC32:213724a0|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_|data_hash=CRC32:f6018f97|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_|data_hash=CRC32:d917e577|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_|data_hash=CRC32:2860d19c|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_|data_hash=CRC32:799e404b|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_|data_hash=CRC32:a4c43eaa|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_|data_hash=CRC32:4aa2d0c3|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_|data_hash=CRC32:b5e19460|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_|data_hash=CRC32:32445f6b|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_|data_hash=CRC32:6f370fec|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_|data_hash=CRC32:43e04e6d|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_|data_hash=CRC32:5ed32f7e|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_|data_hash=CRC32:ead85ef4|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_|data_hash=CRC32:5f283747|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_|data_hash=CRC32:f4aa30a5|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_|data_hash=CRC32:ad09e32c|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_|data_hash=CRC32:57f8004d|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_|data_hash=CRC32:d862a139|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_|data_hash=CRC32:29ebd249|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_|data_hash=CRC32:5af83f3e|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_|data_hash=CRC32:78784213|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_|data_hash=CRC32:cccb4c08|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_|data_hash=CRC32:36520804|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_|data_hash=CRC32:a9235baa|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_|data_hash=CRC32:57ae2eef|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_|data_hash=CRC32:474f3232|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_|data_hash=CRC32:9a51d488|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_|data_hash=CRC32:919bc794|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_|data_hash=CRC32:ed8214ad|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_|data_hash=CRC32:72fcce4c|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_|data_hash=CRC32:2a0143f4|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_|data_hash=CRC32:94f1aae1|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_|data_hash=CRC32:5565737b|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_|data_hash=CRC32:daea61be|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_|data_hash=CRC32:ee704432|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_|data_hash=CRC32:472aa214|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_|data_hash=CRC32:0b046703|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_|data_hash=CRC32:59bf9bd5|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_|data_hash=CRC32:808ee658|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_|data_hash=CRC32:db581c04|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_|data_hash=CRC32:768d8d82|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_|data_hash=CRC32:263c4a83|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_|data_hash=CRC32:4017dc55|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_|data_hash=CRC32:e6b3c398|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_|data_hash=CRC32:37eda28b|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_|data_hash=CRC32:aa3b5d94|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_|data_hash=CRC32:fc87dbf0|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_|data_hash=CRC32:75795b7e|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_|data_hash=CRC32:a8a34bb9|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_|data_hash=CRC32:2ebc4e7b|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_|data_hash=CRC32:53744d32|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_|data_hash=CRC32:d32f77ce|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_|data_hash=CRC32:f582287c|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_|data_hash=CRC32:144b9c4b|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_|data_hash=CRC32:0cca881f|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_|data_hash=CRC32:cddb1237|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_|data_hash=CRC32:10310b68|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_|data_hash=CRC32:dea871f8|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_|data_hash=CRC32:d27e8c99|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_|data_hash=CRC32:3143b0e0|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_|data_hash=CRC32:ebc2c2e6|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_|data_hash=CRC32:dc63972d|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_|data_hash=CRC32:6b141c19|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_|data_hash=CRC32:752ada1e|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_|data_hash=CRC32:36d20d37|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_|data_hash=CRC32:1455dc2e|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_|data_hash=CRC32:c6ffd5fe|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_|data_hash=CRC32:e4c83b97|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_|data_hash=CRC32:ee3f9b5a|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_|data_hash=CRC32:7d0ee8b4|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_|data_hash=CRC32:685b64d8|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_|data_hash=CRC32:ab680b3f|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_|data_hash=CRC32:8485bf04|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_|data_hash=CRC32:60e3ab3b|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_|data_hash=CRC32:cbacc337|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_|data_hash=CRC32:852be5a3|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_|data_hash=CRC32:743f04a8|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_|data_hash=CRC32:0ed88196|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_|data_hash=CRC32:bf13126e|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_|data_hash=CRC32:dd160d29|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_|data_hash=CRC32:65833aa7|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_|data_hash=CRC32:9343d3d2|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_|data_hash=CRC32:7da0cd8d|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_|data_hash=CRC32:8a3298b7|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_|data_hash=CRC32:604d40c4|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_|data_hash=CRC32:ecd7b491|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_|data_hash=CRC32:f8907616|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_|data_hash=CRC32:c6701edc|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_|data_hash=CRC32:ed85bdee|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_|data_hash=CRC32:d9ea8517|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_|data_hash=CRC32:e396092f|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_|data_hash=CRC32:1c628f31|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_|data_hash=CRC32:52183b8f|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_|data_hash=CRC32:bbae2882|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_|data_hash=CRC32:bb5a7486|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_|data_hash=CRC32:ead8306a|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_|data_hash=CRC32:82db1098|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_|data_hash=CRC32:688f5cb6|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_|data_hash=CRC32:fdf34c0b|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_|data_hash=CRC32:802e95d1|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_|data_hash=CRC32:141404b8|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_|data_hash=CRC32:3e39e373|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_|data_hash=CRC32:ce8d8234|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_|data_hash=CRC32:0f3c194d|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_|data_hash=CRC32:3d5d60c4|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_|data_hash=CRC32:f66b2c9f|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_|data_hash=CRC32:44eb2398|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_|data_hash=CRC32:cec1f69c|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_|data_hash=CRC32:57096eb1|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_|data_hash=CRC32:66999a29|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_|data_hash=CRC32:0e598023|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_|data_hash=CRC32:8e728d2b|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_|data_hash=CRC32:7e7549e3|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_|data_hash=CRC32:62f96c18|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_|data_hash=CRC32:48d04b8a|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_|data_hash=CRC32:7937563e|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_|data_hash=CRC32:8e573ad0|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_|data_hash=CRC32:ece4d7e7|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_|data_hash=CRC32:4ca26e7d|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_|data_hash=CRC32:8c347b2d|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_|data_hash=CRC32:b50e55b8|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_|data_hash=CRC32:e2ff539f|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_|data_hash=CRC32:f86e1c5a|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_|data_hash=CRC32:ff858811|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_|data_hash=CRC32:4b0da83e|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_|data_hash=CRC32:605a41a9|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_|data_hash=CRC32:d32c5756|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_|data_hash=CRC32:92c557ef|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_|data_hash=CRC32:c16056ca|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_|data_hash=CRC32:c84a2e99|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_|data_hash=CRC32:d59309d0|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_|data_hash=CRC32:8312e1ba|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_|data_hash=CRC32:12d77a3e|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_|data_hash=CRC32:86b417d4|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_|data_hash=CRC32:a66ed4cf|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_|data_hash=CRC32:b686a5ca|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_|data_hash=CRC32:261ce45b|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_|data_hash=CRC32:cbfbd1bf|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_|data_hash=CRC32:20b5484f|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_|data_hash=CRC32:c4d54099|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_|data_hash=CRC32:cb665fdf|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_|data_hash=CRC32:0271ab1f|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_|data_hash=CRC32:a82f4ab4|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_|data_hash=CRC32:a1e09e3b|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_|data_hash=CRC32:7b297a73|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_|data_hash=CRC32:2165ebef|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_|data_hash=CRC32:b802ae36|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_|data_hash=CRC32:36ca4657|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_|data_hash=CRC32:2fe8a70c|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_|data_hash=CRC32:19c3bc8c|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_|data_hash=CRC32:3b6c08d8|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_|data_hash=CRC32:851471f3|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_|data_hash=CRC32:5d33a166|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_|data_hash=CRC32:d0d1a21b|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_|data_hash=CRC32:c21a3376|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_|data_hash=CRC32:0daaead6|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_|data_hash=CRC32:01c07956|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_|data_hash=CRC32:f5b429c1|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_|data_hash=CRC32:a46831d9|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_|data_hash=CRC32:555d2cb1|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_|data_hash=CRC32:7670785c|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_|data_hash=CRC32:52a244cd|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_|data_hash=CRC32:7ad67c41|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_|data_hash=CRC32:ddc7990b|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_|data_hash=CRC32:8a49bff6|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_|data_hash=CRC32:258dc60a|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_|data_hash=CRC32:2dd6d159|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_|data_hash=CRC32:359ba790|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_|data_hash=CRC32:68cbef69|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_|data_hash=CRC32:cbce1c41|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_|data_hash=CRC32:a9a19b23|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_|data_hash=CRC32:f31b8def|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_|data_hash=CRC32:4dd92879|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_|data_hash=CRC32:7020e4a7|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_|data_hash=CRC32:5f56efad|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_|data_hash=CRC32:4ae7101d|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_|data_hash=CRC32:386c5965|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_|data_hash=CRC32:f2701022|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_|data_hash=CRC32:386bfd07|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_|data_hash=CRC32:080e4345|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_|data_hash=CRC32:4fbaa6b9|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_|data_hash=CRC32:5c879539|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_|data_hash=CRC32:dac40562|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_|data_hash=CRC32:31f989e0|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_|data_hash=CRC32:0149cc11|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_|data_hash=CRC32:1c226514|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_|data_hash=CRC32:991ab49b|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_|data_hash=CRC32:2803c379|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_|data_hash=CRC32:2d95b53b|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_|data_hash=CRC32:2a40955c|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_|data_hash=CRC32:b46687d4|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_|data_hash=CRC32:c4ec89eb|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_|data_hash=CRC32:d53fcf9c|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_|data_hash=CRC32:eb9bfc19|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_|data_hash=CRC32:71e70489|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_|data_hash=CRC32:60a96aca|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_|data_hash=CRC32:ceca878e|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_|data_hash=CRC32:ab40ffe7|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_|data_hash=CRC32:0f8c3162|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_|data_hash=CRC32:af837825|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_|data_hash=CRC32:93a1bea9|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_|data_hash=CRC32:e7289ab0|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_|data_hash=CRC32:4b39626e|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_|data_hash=CRC32:f4bc91d6|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_|data_hash=CRC32:68dd482f|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_|data_hash=CRC32:61ab6014|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_|data_hash=CRC32:232f6af8|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_|data_hash=CRC32:9a4372e9|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_|data_hash=CRC32:f7044435|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_|data_hash=CRC32:2d36f75f|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_|data_hash=CRC32:11858457|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_|data_hash=CRC32:104cc3b1|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_|data_hash=CRC32:8ed3cf9c|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_|data_hash=CRC32:16b50427|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_|data_hash=CRC32:c5c042c3|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_|data_hash=CRC32:722e401f|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_|data_hash=CRC32:831f3604|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_|data_hash=CRC32:7718e73e|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_|data_hash=CRC32:170731a0|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_|data_hash=CRC32:d73c42a8|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_|data_hash=CRC32:854f9a2e|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_|data_hash=CRC32:7d64106d|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_|data_hash=CRC32:02e139fa|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_|data_hash=CRC32:8b5d5f3b|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_|data_hash=CRC32:fa25f507|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_|data_hash=CRC32:ccbf6593|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_|data_hash=CRC32:cea23a52|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_|data_hash=CRC32:3ff8eced|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_|data_hash=CRC32:a5d92bfd|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_|data_hash=CRC32:582c9c2e|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_|data_hash=CRC32:cc23f8d9|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_|data_hash=CRC32:5b9a2c15|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_|data_hash=CRC32:8c48e7c5|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_|data_hash=CRC32:c431b153|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_|data_hash=CRC32:9cfe17d0|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_|data_hash=CRC32:72510fbb|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_|data_hash=CRC32:81830ddd|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_|data_hash=CRC32:43102486|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_|data_hash=CRC32:49018a2e|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_|data_hash=CRC32:3a01967a|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_|data_hash=CRC32:028a7ab9|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_|data_hash=CRC32:012e3f77|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_|data_hash=CRC32:60935688|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_|data_hash=CRC32:1f54722f|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_|data_hash=CRC32:7786349b|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_|data_hash=CRC32:1be2464d|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_|data_hash=CRC32:cf6b28b9|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_|data_hash=CRC32:63fa4ab0|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_|data_hash=CRC32:06a8e324|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_|data_hash=CRC32:c37f55e9|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_|data_hash=CRC32:82f8ac84|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_|data_hash=CRC32:3ed82724|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_|data_hash=CRC32:ed21dfec|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_|data_hash=CRC32:ef20c09c|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_|data_hash=CRC32:5f72438e|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_|data_hash=CRC32:831f56d5|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_|data_hash=CRC32:a3fb153b|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_|data_hash=CRC32:109825ac|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_|data_hash=CRC32:5cb97953|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_|data_hash=CRC32:9aa43658|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_|data_hash=CRC32:0ccad3c6|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_|data_hash=CRC32:ee1e951f|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_|data_hash=CRC32:7e964664|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_|data_hash=CRC32:46489e72|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_|data_hash=CRC32:528f881d|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_|data_hash=CRC32:e776ddf8|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_|data_hash=CRC32:f4d9468d|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_|data_hash=CRC32:0b5bc3e0|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_|data_hash=CRC32:4c6d023d|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_|data_hash=CRC32:29588833|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_|data_hash=CRC32:12f446a5|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_|data_hash=CRC32:39a765b6|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_|data_hash=CRC32:79ab4162|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_|data_hash=CRC32:1c20d61c|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_|data_hash=CRC32:0e5d1ee5|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_|data_hash=CRC32:27c19b26|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_|data_hash=CRC32:8ba8ff4c|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_|data_hash=CRC32:61b51e53|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_|data_hash=CRC32:223fd4b8|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_|data_hash=CRC32:221e6f8a|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_|data_hash=CRC32:623d901e|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_|data_hash=CRC32:584cd53d|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_|data_hash=CRC32:179b3137|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_|data_hash=CRC32:e0e617f2|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_|data_hash=CRC32:560639a0|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_|data_hash=CRC32:a88ea02f|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_|data_hash=CRC32:6a9f391f|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_|data_hash=CRC32:217730ab|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_|data_hash=CRC32:ffa59273|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_|data_hash=CRC32:05a70a45|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_|data_hash=CRC32:1e2e4d40|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_|data_hash=CRC32:695b9d24|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_|data_hash=CRC32:007b90ce|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_|data_hash=CRC32:188da6de|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_|data_hash=CRC32:1046d54c|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_|data_hash=CRC32:aa450d3d|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_|data_hash=CRC32:80bb936b|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_|data_hash=CRC32:47bc2556|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_|data_hash=CRC32:97d4c99c|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_|data_hash=CRC32:37252d43|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_|data_hash=CRC32:76918244|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_|data_hash=CRC32:5ba0d5d3|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_|data_hash=CRC32:5b2b81f0|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_|data_hash=CRC32:161f0b38|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_|data_hash=CRC32:78b4530b|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_|data_hash=CRC32:c0844a4f|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_|data_hash=CRC32:09ef7940|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_|data_hash=CRC32:053ff4c6|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_|data_hash=CRC32:dffb6a19|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_|data_hash=CRC32:95240406|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_|data_hash=CRC32:e2e8f563|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_|data_hash=CRC32:c1c53334|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_|data_hash=CRC32:f122e957|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_|data_hash=CRC32:cd022652|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_|data_hash=CRC32:909c400c|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_|data_hash=CRC32:7340fb8d|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_|data_hash=CRC32:46b59223|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_|data_hash=CRC32:2f1ebb7e|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_|data_hash=CRC32:b56bee4b|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_|data_hash=CRC32:57c778a9|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_|data_hash=CRC32:599b6964|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_|data_hash=CRC32:2351bfa3|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_|data_hash=CRC32:f31f5d14|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_|data_hash=CRC32:c0f7f4b5|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_|data_hash=CRC32:f321de8a|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_|data_hash=CRC32:64e7e790|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_|data_hash=CRC32:d9bef93e|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_|data_hash=CRC32:b08e677b|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_|data_hash=CRC32:cc2d57f3|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_|data_hash=CRC32:920b310d|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_|data_hash=CRC32:7547a71e|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_|data_hash=CRC32:6d0f72a9|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_|data_hash=CRC32:6daae92b|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_|data_hash=CRC32:8bd8704e|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_|data_hash=CRC32:111f49de|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_|data_hash=CRC32:c6e266d5|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_|data_hash=CRC32:b0f5283f|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_|data_hash=CRC32:f70d4475|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_|data_hash=CRC32:371078df|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_|data_hash=CRC32:c2aa814b|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_|data_hash=CRC32:188194bc|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_|data_hash=CRC32:982ba78c|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_|data_hash=CRC32:bf244c73|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_|data_hash=CRC32:8bdf82ed|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_|data_hash=CRC32:acb2d4f3|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_|data_hash=CRC32:1cefab3c|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_|data_hash=CRC32:0bd02594|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_|data_hash=CRC32:cc6fff1d|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_|data_hash=CRC32:cb2fc3d9|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_|data_hash=CRC32:860da403|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_|data_hash=CRC32:14aca2c6|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_|data_hash=CRC32:c5d24ee7|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_|data_hash=CRC32:91680f09|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_|data_hash=CRC32:c6b2948d|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_|data_hash=CRC32:20ff251c|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_|data_hash=CRC32:d9fa6569|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_|data_hash=CRC32:871a83c7|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_|data_hash=CRC32:ad2423ee|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_|data_hash=CRC32:4e9b7b6e|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_|data_hash=CRC32:4aa3582f|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_|data_hash=CRC32:15952f9f|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_|data_hash=CRC32:55db10c7|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_|data_hash=CRC32:1cfff77c|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_|data_hash=CRC32:93bf7a2e|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_|data_hash=CRC32:75577b1c|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_|data_hash=CRC32:fe81112c|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_|data_hash=CRC32:0ddc28c1|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_|data_hash=CRC32:a9dda185|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_|data_hash=CRC32:e10197bd|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_|data_hash=CRC32:f1683c68|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_|data_hash=CRC32:f6eee942|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_|data_hash=CRC32:6ab1ef22|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_|data_hash=CRC32:6920a9e6|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_|data_hash=CRC32:b3ba03c7|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_|data_hash=CRC32:59f04151|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_|data_hash=CRC32:a9300525|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_|data_hash=CRC32:06b28e48|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_|data_hash=CRC32:99640c9a|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_|data_hash=CRC32:264f20e3|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_|data_hash=CRC32:87799aaa|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_|data_hash=CRC32:b2487f0b|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_|data_hash=CRC32:5ff97478|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_|data_hash=CRC32:ee962000|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_|data_hash=CRC32:65a93707|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_|data_hash=CRC32:f365394f|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_|data_hash=CRC32:cc4aa3e5|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_|data_hash=CRC32:a1fd5bac|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_|data_hash=CRC32:1590afda|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_|data_hash=CRC32:3e34e250|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_|data_hash=CRC32:927657b5|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_|data_hash=CRC32:5261b6ab|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_|data_hash=CRC32:645fd792|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_|data_hash=CRC32:240a9cd8|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_|data_hash=CRC32:409c4ee6|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_|data_hash=CRC32:a1e4f6c8|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_|data_hash=CRC32:e405b6d8|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_|data_hash=CRC32:28926870|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_|data_hash=CRC32:991eafa7|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_|data_hash=CRC32:2f2180e4|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_|data_hash=CRC32:c3b931ab|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_|data_hash=CRC32:09c95d1c|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_|data_hash=CRC32:5a90f4d9|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_|data_hash=CRC32:2e1338bd|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_|data_hash=CRC32:db87e979|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_|data_hash=CRC32:d55815d6|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_|data_hash=CRC32:e31e5728|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_|data_hash=CRC32:49e86c3d|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_|data_hash=CRC32:13cefb19|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_|data_hash=CRC32:8d9b7d72|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_|data_hash=CRC32:d55b35fb|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_|data_hash=CRC32:3e10c46a|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_|data_hash=CRC32:924e67eb|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_|data_hash=CRC32:008c6ebb|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_|data_hash=CRC32:96d72d3f|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_|data_hash=CRC32:6f40bb5a|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_|data_hash=CRC32:f6ba1f01|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_|data_hash=CRC32:b610a31e|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_|data_hash=CRC32:64dde46b|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_|data_hash=CRC32:8f794e6c|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_|data_hash=CRC32:65c6284c|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_|data_hash=CRC32:7dead06c|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_|data_hash=CRC32:b0e145b1|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_|data_hash=CRC32:3d2553f6|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_|data_hash=CRC32:e808f1d2|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_|data_hash=CRC32:6b408528|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_|data_hash=CRC32:e51d96e4|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_|data_hash=CRC32:c2df3280|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_|data_hash=CRC32:7bb5a137|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_|data_hash=CRC32:12fcc651|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_|data_hash=CRC32:b402a4c8|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_|data_hash=CRC32:bfe52a16|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_|data_hash=CRC32:09372283|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_|data_hash=CRC32:5a27db5c|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_|data_hash=CRC32:0821b0cd|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_|data_hash=CRC32:91af6b99|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_|data_hash=CRC32:5296a88a|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_|data_hash=CRC32:e75e69d4|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_|data_hash=CRC32:6a5b92cd|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_|data_hash=CRC32:ec30c088|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_|data_hash=CRC32:2c73f2ff|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_|data_hash=CRC32:7f7cb041|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_|data_hash=CRC32:52ef1db9|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_|data_hash=CRC32:fdf0ce4a|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_|data_hash=CRC32:75113c11|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_|data_hash=CRC32:59fc266f|side_data|side_data_type=MPEGTS Stream ID|id=189 + 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|initial_padding=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 3452fad4be7..a0338e08d78 100644 --- a/tests/ref/fate/ts-small-demux +++ b/tests/ref/fate/ts-small-demux @@ -1,149 +1,149 @@ -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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|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 -|data_hash=CRC32:27b943ef +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_|data_hash=CRC32:9c4b744e|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=__|data_hash=CRC32:f5490de8|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=__|data_hash=CRC32:d82fbcc0|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=__|data_hash=CRC32:e062fa20|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=__|data_hash=CRC32:49802a80|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=__|data_hash=CRC32:71cd6c60|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=__|data_hash=CRC32:391aa740|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=__|data_hash=CRC32:0157e1a0|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=__|data_hash=CRC32:10095665|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=__|data_hash=CRC32:28441085|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=__|data_hash=CRC32:6093dba5|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=__|data_hash=CRC32:58de9d45|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=__|data_hash=CRC32:f13c4de5|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=__|data_hash=CRC32:c9710b05|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=__|data_hash=CRC32:81a6c025|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=__|data_hash=CRC32:b9eb86c5|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=__|data_hash=CRC32:a8b53100|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=__|data_hash=CRC32:90f877e0|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=__|data_hash=CRC32:d82fbcc0|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=__|data_hash=CRC32:e062fa20|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=__|data_hash=CRC32:49802a80|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=__|data_hash=CRC32:71cd6c60|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=__|data_hash=CRC32:391aa740|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=__|data_hash=CRC32:0157e1a0|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=__|data_hash=CRC32:10095665|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=__|data_hash=CRC32:28441085|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=__|data_hash=CRC32:6093dba5|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=__|data_hash=CRC32:58de9d45|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=__|data_hash=CRC32:f13c4de5|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=__|data_hash=CRC32:c9710b05|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=__|data_hash=CRC32:81a6c025|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=__|data_hash=CRC32:b9eb86c5|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=__|data_hash=CRC32:a8b53100|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=__|data_hash=CRC32:90f877e0|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=__|data_hash=CRC32:d82fbcc0|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=__|data_hash=CRC32:e062fa20|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=__|data_hash=CRC32:49802a80|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=__|data_hash=CRC32:71cd6c60|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=__|data_hash=CRC32:391aa740|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=__|data_hash=CRC32:0157e1a0|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=__|data_hash=CRC32:10095665|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=__|data_hash=CRC32:28441085|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=__|data_hash=CRC32:6093dba5|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=__|data_hash=CRC32:58de9d45|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=__|data_hash=CRC32:f13c4de5|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=__|data_hash=CRC32:c9710b05|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=__|data_hash=CRC32:81a6c025|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=__|data_hash=CRC32:b9eb86c5|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=__|data_hash=CRC32:a8b53100|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=__|data_hash=CRC32:90f877e0|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=__|data_hash=CRC32:d82fbcc0|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=__|data_hash=CRC32:e062fa20|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=__|data_hash=CRC32:49802a80|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=__|data_hash=CRC32:71cd6c60|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=__|data_hash=CRC32:391aa740|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=__|data_hash=CRC32:0157e1a0|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=__|data_hash=CRC32:10095665|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=__|data_hash=CRC32:28441085|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=__|data_hash=CRC32:6093dba5|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=__|data_hash=CRC32:58de9d45|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=__|data_hash=CRC32:f13c4de5|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=__|data_hash=CRC32:c9710b05|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=__|data_hash=CRC32:81a6c025|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=__|data_hash=CRC32:b9eb86c5|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=__|data_hash=CRC32:a8b53100|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=__|data_hash=CRC32:90f877e0|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=__|data_hash=CRC32:d82fbcc0|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=__|data_hash=CRC32:e062fa20|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=__|data_hash=CRC32:49802a80|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=__|data_hash=CRC32:71cd6c60|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=__|data_hash=CRC32:391aa740|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=__|data_hash=CRC32:cca62b67|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=__|data_hash=CRC32:27b943ef|side_data|side_data_type=MPEGTS Stream ID|id=224 + 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 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 2548c32cc10f256cc0ff90457631ef7ef94070af Mon Sep 17 00:00:00 2001 From: Leo Izen Date: Tue, 17 Jan 2023 11:09:29 -0500 Subject: [PATCH 0059/2172] avcodec/png: use libavutil/csp.h for cHRM chunks The cHRM chunk is descriptive. That is, it describes the primaries that should be used to interpret the pixel data in the PNG file. This is notably different from Mastering Display Metadata, which describes which subset of the presented gamut is relevant. MDM describes a gamut and says colors outside the gamut are not required to be preserved, but it does not actually describe the gamut that the pixel data from the frame resides in. Thus, to decode a cHRM chunk present in a PNG file to Mastering Display Metadata is incorrect. This commit changes this behavior so the cHRM chunk, if present, is decoded to color metadata. For example, if the cHRM chunk describes BT.709 primaries, the resulting AVFrame will be tagged with AVCOL_PRI_BT709, as a description of its pixel data. To do this, it utilizes libavutil/csp.h, which exposes a funcction av_csp_primaries_id_from_desc, to detect which enum value accurately describes the white point and primaries represented by the cHRM chunk. This commit also changes pngenc.c to utilize the libavuitl/csp.h API, since it previously duplicated code contained in that API. Instead, taking advantage of the API that exists makes more sense. pngenc.c does properly utilize the color tags rather than incorrectly using MDM, so that required no change. Signed-off-by: Leo Izen --- libavcodec/pngdec.c | 46 +++++++++++++++++-------------- libavcodec/pngenc.c | 53 +++++++++++------------------------- tests/ref/fate/png-icc | 2 +- tests/ref/fate/png-side-data | 13 +-------- 4 files changed, 44 insertions(+), 70 deletions(-) diff --git a/libavcodec/pngdec.c b/libavcodec/pngdec.c index f1cad26c522..32e7773bcb5 100644 --- a/libavcodec/pngdec.c +++ b/libavcodec/pngdec.c @@ -26,10 +26,12 @@ #include "libavutil/avassert.h" #include "libavutil/bprint.h" #include "libavutil/crc.h" +#include "libavutil/csp.h" #include "libavutil/imgutils.h" #include "libavutil/intreadwrite.h" +#include "libavutil/pixfmt.h" +#include "libavutil/rational.h" #include "libavutil/stereo3d.h" -#include "libavutil/mastering_display_metadata.h" #include "avcodec.h" #include "bytestream.h" @@ -1472,6 +1474,7 @@ static void clear_frame_metadata(PNGDecContext *s) static int output_frame(PNGDecContext *s, AVFrame *f) { + AVCodecContext *avctx = s->avctx; int ret; if (s->iccp_data) { @@ -1483,8 +1486,30 @@ static int output_frame(PNGDecContext *s, AVFrame *f) memcpy(sd->data, s->iccp_data, s->iccp_data_len); av_dict_set(&sd->metadata, "name", s->iccp_name, 0); + } else if (s->have_chrm) { + AVColorPrimariesDesc desc; + enum AVColorPrimaries prim; + desc.wp.x = av_make_q(s->white_point[0], 100000); + desc.wp.y = av_make_q(s->white_point[1], 100000); + desc.prim.r.x = av_make_q(s->display_primaries[0][0], 100000); + desc.prim.r.y = av_make_q(s->display_primaries[0][1], 100000); + desc.prim.g.x = av_make_q(s->display_primaries[1][0], 100000); + desc.prim.g.y = av_make_q(s->display_primaries[1][1], 100000); + desc.prim.b.x = av_make_q(s->display_primaries[2][0], 100000); + desc.prim.b.y = av_make_q(s->display_primaries[2][1], 100000); + prim = av_csp_primaries_id_from_desc(&desc); + if (prim != AVCOL_PRI_UNSPECIFIED) + avctx->color_primaries = f->color_primaries = prim; + else + av_log(avctx, AV_LOG_WARNING, "unknown cHRM primaries\n"); } + /* this chunk overrides gAMA */ + if (s->iccp_data) + av_dict_set(&s->frame_metadata, "gamma", NULL, 0); + + avctx->colorspace = f->colorspace = AVCOL_SPC_RGB; + if (s->stereo_mode >= 0) { AVStereo3D *stereo3d = av_stereo3d_create_side_data(f); if (!stereo3d) { @@ -1496,25 +1521,6 @@ static int output_frame(PNGDecContext *s, AVFrame *f) stereo3d->flags = s->stereo_mode ? 0 : AV_STEREO3D_FLAG_INVERT; } - if (s->have_chrm) { - AVMasteringDisplayMetadata *mdm = av_mastering_display_metadata_create_side_data(f); - if (!mdm) { - ret = AVERROR(ENOMEM); - goto fail; - } - - mdm->white_point[0] = av_make_q(s->white_point[0], 100000); - mdm->white_point[1] = av_make_q(s->white_point[1], 100000); - - /* RGB Primaries */ - for (int i = 0; i < 3; i++) { - mdm->display_primaries[i][0] = av_make_q(s->display_primaries[i][0], 100000); - mdm->display_primaries[i][1] = av_make_q(s->display_primaries[i][1], 100000); - } - - mdm->has_primaries = 1; - } - FFSWAP(AVDictionary*, f->metadata, s->frame_metadata); return 0; diff --git a/libavcodec/pngenc.c b/libavcodec/pngenc.c index ca1a186ca86..4333d5837f0 100644 --- a/libavcodec/pngenc.c +++ b/libavcodec/pngenc.c @@ -29,10 +29,12 @@ #include "zlib_wrapper.h" #include "libavutil/avassert.h" +#include "libavutil/color_utils.h" #include "libavutil/crc.h" +#include "libavutil/csp.h" #include "libavutil/libm.h" #include "libavutil/opt.h" -#include "libavutil/color_utils.h" +#include "libavutil/rational.h" #include "libavutil/stereo3d.h" #include @@ -294,45 +296,22 @@ static int png_write_row(AVCodecContext *avctx, const uint8_t *data, int size) } #define AV_WB32_PNG(buf, n) AV_WB32(buf, lrint((n) * 100000)) +#define AV_WB32_PNG_D(buf, d) AV_WB32_PNG(buf, av_q2d(d)) static int png_get_chrm(enum AVColorPrimaries prim, uint8_t *buf) { - double rx, ry, gx, gy, bx, by, wx = 0.3127, wy = 0.3290; - switch (prim) { - case AVCOL_PRI_BT709: - rx = 0.640; ry = 0.330; - gx = 0.300; gy = 0.600; - bx = 0.150; by = 0.060; - break; - case AVCOL_PRI_BT470M: - rx = 0.670; ry = 0.330; - gx = 0.210; gy = 0.710; - bx = 0.140; by = 0.080; - wx = 0.310; wy = 0.316; - break; - case AVCOL_PRI_BT470BG: - rx = 0.640; ry = 0.330; - gx = 0.290; gy = 0.600; - bx = 0.150; by = 0.060; - break; - case AVCOL_PRI_SMPTE170M: - case AVCOL_PRI_SMPTE240M: - rx = 0.630; ry = 0.340; - gx = 0.310; gy = 0.595; - bx = 0.155; by = 0.070; - break; - case AVCOL_PRI_BT2020: - rx = 0.708; ry = 0.292; - gx = 0.170; gy = 0.797; - bx = 0.131; by = 0.046; - break; - default: - return 0; - } + const AVColorPrimariesDesc *desc = av_csp_primaries_desc_from_id(prim); + if (!desc) + return 0; + + AV_WB32_PNG_D(buf, desc->wp.x); + AV_WB32_PNG_D(buf + 4, desc->wp.y); + AV_WB32_PNG_D(buf + 8, desc->prim.r.x); + AV_WB32_PNG_D(buf + 12, desc->prim.r.y); + AV_WB32_PNG_D(buf + 16, desc->prim.g.x); + AV_WB32_PNG_D(buf + 20, desc->prim.g.y); + AV_WB32_PNG_D(buf + 24, desc->prim.b.x); + AV_WB32_PNG_D(buf + 28, desc->prim.b.y); - AV_WB32_PNG(buf , wx); AV_WB32_PNG(buf + 4 , wy); - AV_WB32_PNG(buf + 8 , rx); AV_WB32_PNG(buf + 12, ry); - AV_WB32_PNG(buf + 16, gx); AV_WB32_PNG(buf + 20, gy); - AV_WB32_PNG(buf + 24, bx); AV_WB32_PNG(buf + 28, by); return 1; } diff --git a/tests/ref/fate/png-icc b/tests/ref/fate/png-icc index 92fa0e526b7..14de5446394 100644 --- a/tests/ref/fate/png-icc +++ b/tests/ref/fate/png-icc @@ -33,7 +33,7 @@ interlaced_frame=0 top_field_first=0 repeat_pict=0 color_range=pc -color_space=unknown +color_space=gbr color_primaries=unknown color_transfer=unknown chroma_location=unspecified diff --git a/tests/ref/fate/png-side-data b/tests/ref/fate/png-side-data index f40f14fea17..a4c16eb3957 100644 --- a/tests/ref/fate/png-side-data +++ b/tests/ref/fate/png-side-data @@ -25,7 +25,7 @@ interlaced_frame=1 top_field_first=0 repeat_pict=0 color_range=pc -color_space=unknown +color_space=gbr color_primaries=unknown color_transfer=unknown chroma_location=unspecified @@ -34,15 +34,4 @@ side_data_type=ICC profile name=Photoshop ICC profile size=3144 [/SIDE_DATA] -[SIDE_DATA] -side_data_type=Mastering display metadata -red_x=63999/100000 -red_y=33001/100000 -green_x=30000/100000 -green_y=60000/100000 -blue_x=15000/100000 -blue_y=5999/100000 -white_point_x=31269/100000 -white_point_y=32899/100000 -[/SIDE_DATA] [/FRAME] From f7bab37c8e66f3c77a5fbb5b5b72c10b0fb4ca5a Mon Sep 17 00:00:00 2001 From: Leo Izen Date: Tue, 17 Jan 2023 12:32:31 -0500 Subject: [PATCH 0060/2172] avcodec/pngdec: support decoding sRGB chunks If an sRGB chunk is present in the PNG file, this commit will cause the png decoder to ignore the cHRM and gAMA chunks and tag the resulting AVFrames with BT.709 primaries, and ISO/IEC 61966-2-1 transfer. If these tags are present in the AVFrame, pngenc.c already writes this chunk, so no change was needed on the encode-side. The PNG spec does not define what happens if sRGB and iCCP are present at the same time, it just recommends that this not happen. As of this patch, the decoder will have the ICC profile take precedence, and it will not tag the pixel data as sRGB. Signed-off-by: Leo Izen --- libavcodec/pngdec.c | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/libavcodec/pngdec.c b/libavcodec/pngdec.c index 32e7773bcb5..1f9ed894de2 100644 --- a/libavcodec/pngdec.c +++ b/libavcodec/pngdec.c @@ -75,6 +75,7 @@ typedef struct PNGDecContext { int have_chrm; uint32_t white_point[2]; uint32_t display_primaries[3][2]; + int have_srgb; enum PNGHeaderState hdr_state; enum PNGImageState pic_state; @@ -1313,6 +1314,11 @@ static int decode_frame_common(AVCodecContext *avctx, PNGDecContext *s, } break; } + case MKTAG('s', 'R', 'G', 'B'): + /* skip rendering intent byte */ + bytestream2_skip(&gb_chunk, 1); + s->have_srgb = 1; + break; case MKTAG('i', 'C', 'C', 'P'): { if ((ret = decode_iccp_chunk(s, &gb_chunk, p)) < 0) goto fail; @@ -1468,6 +1474,7 @@ static void clear_frame_metadata(PNGDecContext *s) s->stereo_mode = -1; s->have_chrm = 0; + s->have_srgb = 0; av_dict_free(&s->frame_metadata); } @@ -1486,6 +1493,9 @@ static int output_frame(PNGDecContext *s, AVFrame *f) memcpy(sd->data, s->iccp_data, s->iccp_data_len); av_dict_set(&sd->metadata, "name", s->iccp_name, 0); + } else if (s->have_srgb) { + avctx->color_primaries = f->color_primaries = AVCOL_PRI_BT709; + avctx->color_trc = f->color_trc = AVCOL_TRC_IEC61966_2_1; } else if (s->have_chrm) { AVColorPrimariesDesc desc; enum AVColorPrimaries prim; @@ -1504,8 +1514,8 @@ static int output_frame(PNGDecContext *s, AVFrame *f) av_log(avctx, AV_LOG_WARNING, "unknown cHRM primaries\n"); } - /* this chunk overrides gAMA */ - if (s->iccp_data) + /* these chunks overrides gAMA */ + if (s->iccp_data || s->have_srgb) av_dict_set(&s->frame_metadata, "gamma", NULL, 0); avctx->colorspace = f->colorspace = AVCOL_SPC_RGB; From 6f79f0971e8ccf6c7a2b8eb1dbc5b64fdd77ca0f Mon Sep 17 00:00:00 2001 From: Leo Izen Date: Tue, 17 Jan 2023 13:38:42 -0500 Subject: [PATCH 0061/2172] avcodec/png: support cICP chunks This commit adds both decode and encode support for cICP chunks, which allow a PNG image's pixel data to be tagged by any of the enum values in H.273, without an ICC profile. Upon decode, if a cICP chunk is present, the PNG decoder will tag output AVFrames with the resulting enum color, and ignore iCCP, sRGB, gAMA, and cHRM chunks, as per the spec. Upon encode, if the color space is known and specified, and it is not sRGB, the PNG encoder will output a cICP chunk containing the color space. If the color space is sRGB, then it will output an sRGB chunk instead of a cICP chunk. If the color space of the input is not unspecified, it will not output a cICP chunk tagging the PNG as unspecified. In either the sRGB case or the non-SRGB case, gAMA and cHRM are still written as fallbacks provided the info is known. Signed-off-by: Leo Izen --- libavcodec/pngdec.c | 35 ++++++++++++++++++++++++++++++++--- libavcodec/pngenc.c | 8 ++++++++ 2 files changed, 40 insertions(+), 3 deletions(-) diff --git a/libavcodec/pngdec.c b/libavcodec/pngdec.c index 1f9ed894de2..0d969decf25 100644 --- a/libavcodec/pngdec.c +++ b/libavcodec/pngdec.c @@ -76,6 +76,10 @@ typedef struct PNGDecContext { uint32_t white_point[2]; uint32_t display_primaries[3][2]; int have_srgb; + int have_cicp; + enum AVColorPrimaries cicp_primaries; + enum AVColorTransferCharacteristic cicp_trc; + enum AVColorRange cicp_range; enum PNGHeaderState hdr_state; enum PNGImageState pic_state; @@ -1314,6 +1318,19 @@ static int decode_frame_common(AVCodecContext *avctx, PNGDecContext *s, } break; } + case MKTAG('c', 'I', 'C', 'P'): + s->cicp_primaries = bytestream2_get_byte(&gb_chunk); + s->cicp_trc = bytestream2_get_byte(&gb_chunk); + if (bytestream2_get_byte(&gb_chunk) != 0) + av_log(avctx, AV_LOG_WARNING, "nonzero cICP matrix\n"); + s->cicp_range = bytestream2_get_byte(&gb_chunk); + if (s->cicp_range != 0 && s->cicp_range != 1) { + av_log(avctx, AV_LOG_ERROR, "invalid cICP range: %d\n", s->cicp_range); + ret = AVERROR_INVALIDDATA; + goto fail; + } + s->have_cicp = 1; + break; case MKTAG('s', 'R', 'G', 'B'): /* skip rendering intent byte */ bytestream2_skip(&gb_chunk, 1); @@ -1475,6 +1492,7 @@ static void clear_frame_metadata(PNGDecContext *s) s->have_chrm = 0; s->have_srgb = 0; + s->have_cicp = 0; av_dict_free(&s->frame_metadata); } @@ -1484,7 +1502,18 @@ static int output_frame(PNGDecContext *s, AVFrame *f) AVCodecContext *avctx = s->avctx; int ret; - if (s->iccp_data) { + if (s->have_cicp) { + if (s->cicp_primaries >= AVCOL_PRI_NB) + av_log(avctx, AV_LOG_WARNING, "unrecognized cICP primaries\n"); + else + avctx->color_primaries = f->color_primaries = s->cicp_primaries; + if (s->cicp_trc >= AVCOL_TRC_NB) + av_log(avctx, AV_LOG_WARNING, "unrecognized cICP transfer\n"); + else + avctx->color_trc = f->color_trc = s->cicp_trc; + avctx->color_range = f->color_range = + s->cicp_range == 0 ? AVCOL_RANGE_MPEG : AVCOL_RANGE_JPEG; + } else if (s->iccp_data) { AVFrameSideData *sd = av_frame_new_side_data(f, AV_FRAME_DATA_ICC_PROFILE, s->iccp_data_len); if (!sd) { ret = AVERROR(ENOMEM); @@ -1514,8 +1543,8 @@ static int output_frame(PNGDecContext *s, AVFrame *f) av_log(avctx, AV_LOG_WARNING, "unknown cHRM primaries\n"); } - /* these chunks overrides gAMA */ - if (s->iccp_data || s->have_srgb) + /* these chunks override gAMA */ + if (s->iccp_data || s->have_srgb || s->have_cicp) av_dict_set(&s->frame_metadata, "gamma", NULL, 0); avctx->colorspace = f->colorspace = AVCOL_SPC_RGB; diff --git a/libavcodec/pngenc.c b/libavcodec/pngenc.c index 4333d5837f0..0ce684342ef 100644 --- a/libavcodec/pngenc.c +++ b/libavcodec/pngenc.c @@ -417,6 +417,14 @@ static int encode_headers(AVCodecContext *avctx, const AVFrame *pict) pict->color_trc == AVCOL_TRC_IEC61966_2_1) { s->buf[0] = 1; /* rendering intent, relative colorimetric by default */ png_write_chunk(&s->bytestream, MKTAG('s', 'R', 'G', 'B'), s->buf, 1); + } else if (pict->color_primaries != AVCOL_PRI_UNSPECIFIED || + pict->color_trc != AVCOL_TRC_UNSPECIFIED) { + /* these values match H.273 so no translation is needed */ + s->buf[0] = pict->color_primaries; + s->buf[1] = pict->color_trc; + s->buf[2] = 0; /* colorspace = RGB */ + s->buf[3] = pict->color_range == AVCOL_RANGE_MPEG ? 0 : 1; + png_write_chunk(&s->bytestream, MKTAG('c', 'I', 'C', 'P'), s->buf, 4); } if (png_get_chrm(pict->color_primaries, s->buf)) From 2c3107c3e9c9a8885fc0860ac471dae2f1054586 Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Wed, 25 Jan 2023 18:46:21 +0100 Subject: [PATCH 0062/2172] avformat/bonk: remove unused variable --- libavformat/bonk.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavformat/bonk.c b/libavformat/bonk.c index 7ce895fa965..bd99c553e70 100644 --- a/libavformat/bonk.c +++ b/libavformat/bonk.c @@ -59,7 +59,7 @@ static int bonk_read_header(AVFormatContext *s) AVStream *st; int ret; - for (int i = 0; !avio_feof(s->pb); i++) { + while (!avio_feof(s->pb)) { const int b = avio_r8(s->pb); if (!b) { uint32_t t; From 1263b0a6ca8f51cebbd21568af31b37235650515 Mon Sep 17 00:00:00 2001 From: Zhao Zhili Date: Wed, 11 Jan 2023 23:33:12 +0800 Subject: [PATCH 0063/2172] avutil/hwcontext_mediacodec: fix backward compatibility AVMediaCodecDeviceContext without surface or native_window is useless, it shouldn't be created at all. Such dummy AVHWDeviceContext is allowed before, and it's used by mpv player. Creating a ANativeWindow automatically breaks such usecases. So disable creating a ANativeWindow by default. It can be enabled via the create_window flag, or by set the AVDictionary of av_hwdevice_ctx_create(). The downside is that ffmpeg -hwaccel mediacodec -i input.mp4 \ -c:a copy -c:v hevc_mediacodec output.mp4 use ByteBuffer mode which isn't as efficient as before. The upside is libavfilter works now, which should be less surprise. To enable create_window on ffmpeg command line, use ffmpeg -hwaccel mediacodec \ -init_hw_device mediacodec=mediacodec,create_window=1 \ -i input.mp4 -c:a copy -c:v hevc_mediacodec output.mp4 Users should know what it is to enable create_window. It should be OK to take sometime to figure out the option. And there are comments inside hwcontext_mediacodec.h to help user figure it out. Signed-off-by: Zhao Zhili --- libavutil/hwcontext_mediacodec.c | 17 +++++++++++++++++ libavutil/hwcontext_mediacodec.h | 16 +++++++++++++++- 2 files changed, 32 insertions(+), 1 deletion(-) diff --git a/libavutil/hwcontext_mediacodec.c b/libavutil/hwcontext_mediacodec.c index bb1779d34df..9ed6a8717ae 100644 --- a/libavutil/hwcontext_mediacodec.c +++ b/libavutil/hwcontext_mediacodec.c @@ -39,11 +39,23 @@ typedef struct MediaCodecDeviceContext { static int mc_device_create(AVHWDeviceContext *ctx, const char *device, AVDictionary *opts, int flags) { + const AVDictionaryEntry *entry = NULL; + MediaCodecDeviceContext *s = ctx->hwctx; + AVMediaCodecDeviceContext *dev = &s->ctx; + if (device && device[0]) { av_log(ctx, AV_LOG_ERROR, "Device selection unsupported.\n"); return AVERROR_UNKNOWN; } + while ((entry = av_dict_iterate(opts, entry))) { + if (!strcmp(entry->key, "create_window")) + dev->create_window = atoi(entry->value); + } + + av_log(ctx, AV_LOG_DEBUG, "%s createPersistentInputSurface\n", + dev->create_window ? "Enable" : "Disable"); + return 0; } @@ -59,6 +71,11 @@ static int mc_device_init(AVHWDeviceContext *ctx) if (dev->native_window) return 0; + // For backward compatibility, don't return error for a dummy + // AVHWDeviceContext without surface or native_window. + if (!dev->create_window) + return 0; + s->libmedia = dlopen("libmediandk.so", RTLD_NOW); if (!s->libmedia) return AVERROR_UNKNOWN; diff --git a/libavutil/hwcontext_mediacodec.h b/libavutil/hwcontext_mediacodec.h index 920e17764fe..fc0263cabce 100644 --- a/libavutil/hwcontext_mediacodec.h +++ b/libavutil/hwcontext_mediacodec.h @@ -36,12 +36,26 @@ typedef struct AVMediaCodecDeviceContext { * Pointer to ANativeWindow. * * It both surface and native_window is NULL, try to create it - * automatically if OS support. + * automatically if create_window is true and OS support + * createPersistentInputSurface. * * It can be used as output surface for decoder and input surface for * encoder. */ void *native_window; + + /** + * Enable createPersistentInputSurface automatically. + * + * Disabled by default. + * + * It can be enabled by setting this flag directly, or by setting + * AVDictionary of av_hwdevice_ctx_create(), with "create_window" as key. + * The second method is useful for ffmpeg cmdline, e.g., we can enable it + * via: + * -init_hw_device mediacodec=mediacodec,create_window=1 + */ + int create_window; } AVMediaCodecDeviceContext; #endif /* AVUTIL_HWCONTEXT_MEDIACODEC_H */ From b8fca1f1f5ece5f3ca9d6db0cb72c1918ba07deb Mon Sep 17 00:00:00 2001 From: Zhao Zhili Date: Fri, 13 Jan 2023 00:23:09 +0800 Subject: [PATCH 0064/2172] avformat/teeproto: setup max_packet_size It's the minimum of all child protocols max_packet_size. Can be used like this: ffmpeg -re -i cctv.mp4 -c copy -f mpegts \ -protocol_whitelist 'tee,file,udp' \ 'tee:out.ts|udp://127.0.0.1:6666?pkt_size=1316' Signed-off-by: Zhao Zhili --- libavformat/teeproto.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/libavformat/teeproto.c b/libavformat/teeproto.c index e532bc7750e..dca97a67414 100644 --- a/libavformat/teeproto.c +++ b/libavformat/teeproto.c @@ -131,6 +131,18 @@ static int tee_open(URLContext *h, const char *filename, int flags) h->is_streamed |= c->child[i].url_context->is_streamed; } + h->max_packet_size = 0; + for (i = 0; i < c->child_count; i++) { + int max = c->child[i].url_context->max_packet_size; + if (!max) + continue; + + if (!h->max_packet_size) + h->max_packet_size = max; + else if (h->max_packet_size > max) + h->max_packet_size = max; + } + return 0; fail: tee_close(h); From 79e9bdf7494b5ff54af1514401a74b1e8c85aa7c Mon Sep 17 00:00:00 2001 From: Zhao Zhili Date: Mon, 9 Jan 2023 20:50:03 +0800 Subject: [PATCH 0065/2172] avcodec/videotoolbox: fix NULL pointer dereference In the code path of av_videotoolbox_default_init/init2(), avctx->internal->hwaccel_priv_data is NULL and passed to decoder_cb.decompressionOutputRefCon. Then it will be dereferenced inside videotoolbox_decoder_callback(). Delay videotoolbox_star() until ff_videotoolbox_common_init() to fix the bug. Signed-off-by: Zhao Zhili --- libavcodec/videotoolbox.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/libavcodec/videotoolbox.c b/libavcodec/videotoolbox.c index 1b1be8ddb41..a18b49007d1 100644 --- a/libavcodec/videotoolbox.c +++ b/libavcodec/videotoolbox.c @@ -1181,9 +1181,8 @@ int ff_videotoolbox_common_init(AVCodecContext *avctx) vtctx->logctx = avctx; - // Old API - do nothing. if (avctx->hwaccel_context) - return 0; + return videotoolbox_start(avctx); if (!avctx->hw_frames_ctx && !avctx->hw_device_ctx) { av_log(avctx, AV_LOG_ERROR, @@ -1404,7 +1403,7 @@ int av_videotoolbox_default_init2(AVCodecContext *avctx, AVVideotoolboxContext * avctx->hwaccel_context = vtctx ?: av_videotoolbox_alloc_context_with_pix_fmt(pix_fmt, full_range); if (!avctx->hwaccel_context) return AVERROR(ENOMEM); - return videotoolbox_start(avctx); + return 0; } void av_videotoolbox_default_free(AVCodecContext *avctx) From ade89bc6defb0c8996088d59ab0c8eb437156da5 Mon Sep 17 00:00:00 2001 From: Zhao Zhili Date: Mon, 9 Jan 2023 20:50:04 +0800 Subject: [PATCH 0066/2172] avcodec/videotoolbox: prefer hw_frames_ctx/hw_device_ctx over hwaccel_context Signed-off-by: Zhao Zhili --- libavcodec/videotoolbox.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libavcodec/videotoolbox.c b/libavcodec/videotoolbox.c index a18b49007d1..acf0c798220 100644 --- a/libavcodec/videotoolbox.c +++ b/libavcodec/videotoolbox.c @@ -1181,7 +1181,8 @@ int ff_videotoolbox_common_init(AVCodecContext *avctx) vtctx->logctx = avctx; - if (avctx->hwaccel_context) + if (!avctx->hw_frames_ctx && !avctx->hw_device_ctx && + avctx->hwaccel_context) return videotoolbox_start(avctx); if (!avctx->hw_frames_ctx && !avctx->hw_device_ctx) { From d6bd980da658453e54af40387633f158e0b125af Mon Sep 17 00:00:00 2001 From: Zhao Zhili Date: Mon, 9 Jan 2023 20:50:06 +0800 Subject: [PATCH 0067/2172] avcodec/videotoolbox: deprecate creating AVVideotoolboxContext by user Signed-off-by: Zhao Zhili --- libavcodec/version_major.h | 1 + libavcodec/videotoolbox.c | 35 ++++++++++++++++++++--------------- libavcodec/videotoolbox.h | 12 ++++++++++++ 3 files changed, 33 insertions(+), 15 deletions(-) diff --git a/libavcodec/version_major.h b/libavcodec/version_major.h index 12f863deb79..2c0443c4c8e 100644 --- a/libavcodec/version_major.h +++ b/libavcodec/version_major.h @@ -52,6 +52,7 @@ #define FF_API_SVTAV1_OPTS (LIBAVCODEC_VERSION_MAJOR < 60) #define FF_API_AYUV_CODECID (LIBAVCODEC_VERSION_MAJOR < 60) #define FF_API_VT_OUTPUT_CALLBACK (LIBAVCODEC_VERSION_MAJOR < 60) +#define FF_API_VT_HWACCEL_CONTEXT (LIBAVCODEC_VERSION_MAJOR < 60) #define FF_API_AVCODEC_CHROMA_POS (LIBAVCODEC_VERSION_MAJOR < 60) #endif /* AVCODEC_VERSION_MAJOR_H */ diff --git a/libavcodec/videotoolbox.c b/libavcodec/videotoolbox.c index acf0c798220..a3d19c4c63d 100644 --- a/libavcodec/videotoolbox.c +++ b/libavcodec/videotoolbox.c @@ -1173,6 +1173,22 @@ static enum AVPixelFormat videotoolbox_best_pixel_format(AVCodecContext *avctx) return AV_PIX_FMT_NV12; } +static AVVideotoolboxContext *av_videotoolbox_alloc_context_with_pix_fmt(enum AVPixelFormat pix_fmt, + bool full_range) +{ + AVVideotoolboxContext *ret = av_mallocz(sizeof(*ret)); + + if (ret) { + OSType cv_pix_fmt_type = av_map_videotoolbox_format_from_pixfmt2(pix_fmt, full_range); + if (cv_pix_fmt_type == 0) { + cv_pix_fmt_type = kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange; + } + ret->cv_pix_fmt_type = cv_pix_fmt_type; + } + + return ret; +} + int ff_videotoolbox_common_init(AVCodecContext *avctx) { VTContext *vtctx = avctx->internal->hwaccel_priv_data; @@ -1191,7 +1207,7 @@ int ff_videotoolbox_common_init(AVCodecContext *avctx) return AVERROR(EINVAL); } - vtctx->vt_ctx = av_videotoolbox_alloc_context(); + vtctx->vt_ctx = av_videotoolbox_alloc_context_with_pix_fmt(AV_PIX_FMT_NONE, false); if (!vtctx->vt_ctx) { err = AVERROR(ENOMEM); goto fail; @@ -1371,22 +1387,9 @@ const AVHWAccel ff_prores_videotoolbox_hwaccel = { .priv_data_size = sizeof(VTContext), }; -static AVVideotoolboxContext *av_videotoolbox_alloc_context_with_pix_fmt(enum AVPixelFormat pix_fmt, - bool full_range) -{ - AVVideotoolboxContext *ret = av_mallocz(sizeof(*ret)); - if (ret) { - OSType cv_pix_fmt_type = av_map_videotoolbox_format_from_pixfmt2(pix_fmt, full_range); - if (cv_pix_fmt_type == 0) { - cv_pix_fmt_type = kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange; - } - ret->cv_pix_fmt_type = cv_pix_fmt_type; - } - - return ret; -} +#if FF_API_VT_HWACCEL_CONTEXT AVVideotoolboxContext *av_videotoolbox_alloc_context(void) { return av_videotoolbox_alloc_context_with_pix_fmt(AV_PIX_FMT_NONE, false); @@ -1413,4 +1416,6 @@ void av_videotoolbox_default_free(AVCodecContext *avctx) videotoolbox_stop(avctx); av_freep(&avctx->hwaccel_context); } +#endif /* FF_API_VT_HWACCEL_CONTEXT */ + #endif /* CONFIG_VIDEOTOOLBOX */ diff --git a/libavcodec/videotoolbox.h b/libavcodec/videotoolbox.h index 25a747a49f3..3cd1d254ffe 100644 --- a/libavcodec/videotoolbox.h +++ b/libavcodec/videotoolbox.h @@ -90,6 +90,8 @@ typedef struct AVVideotoolboxContext { int cm_codec_type; } AVVideotoolboxContext; +#if FF_API_VT_HWACCEL_CONTEXT + /** * Allocate and initialize a Videotoolbox context. * @@ -102,7 +104,9 @@ typedef struct AVVideotoolboxContext { * object and free the Videotoolbox context using av_free(). * * @return the newly allocated context or NULL on failure + * @deprecated Use AVCodecContext.hw_frames_ctx or hw_device_ctx instead. */ +attribute_deprecated AVVideotoolboxContext *av_videotoolbox_alloc_context(void); /** @@ -112,7 +116,9 @@ AVVideotoolboxContext *av_videotoolbox_alloc_context(void); * @param avctx the corresponding codec context * * @return >= 0 on success, a negative AVERROR code on failure + * @deprecated Use AVCodecContext.hw_frames_ctx or hw_device_ctx instead. */ +attribute_deprecated int av_videotoolbox_default_init(AVCodecContext *avctx); /** @@ -123,7 +129,9 @@ int av_videotoolbox_default_init(AVCodecContext *avctx); * @param vtctx the Videotoolbox context to use * * @return >= 0 on success, a negative AVERROR code on failure + * @deprecated Use AVCodecContext.hw_frames_ctx or hw_device_ctx instead. */ +attribute_deprecated int av_videotoolbox_default_init2(AVCodecContext *avctx, AVVideotoolboxContext *vtctx); /** @@ -131,9 +139,13 @@ int av_videotoolbox_default_init2(AVCodecContext *avctx, AVVideotoolboxContext * * av_videotoolbox_default_init(). * * @param avctx the corresponding codec context + * @deprecated Use AVCodecContext.hw_frames_ctx or hw_device_ctx instead. */ +attribute_deprecated void av_videotoolbox_default_free(AVCodecContext *avctx); +#endif /* FF_API_VT_HWACCEL_CONTEXT */ + /** * @} */ From 5146916a9ce2a946c3b9826ccb36c248656d26a6 Mon Sep 17 00:00:00 2001 From: Zhao Zhili Date: Mon, 9 Jan 2023 20:50:07 +0800 Subject: [PATCH 0068/2172] avcodec/videotoolbox: fix documents of AVVideotoolboxContext Since those fields will be overridden by videotoolbox_start(), they should never be set by user, it can trigger memory leaks otherwise. Signed-off-by: Zhao Zhili --- libavcodec/videotoolbox.h | 3 --- 1 file changed, 3 deletions(-) diff --git a/libavcodec/videotoolbox.h b/libavcodec/videotoolbox.h index 3cd1d254ffe..ba5eddbf460 100644 --- a/libavcodec/videotoolbox.h +++ b/libavcodec/videotoolbox.h @@ -57,7 +57,6 @@ typedef struct AVVideotoolboxContext { /** * Videotoolbox decompression session object. - * Created and freed the caller. */ VTDecompressionSessionRef session; @@ -79,13 +78,11 @@ typedef struct AVVideotoolboxContext { /** * CoreMedia Format Description that Videotoolbox will use to create the decompression session. - * Set by the caller. */ CMVideoFormatDescriptionRef cm_fmt_desc; /** * CoreMedia codec type that Videotoolbox will use to create the decompression session. - * Set by the caller. */ int cm_codec_type; } AVVideotoolboxContext; From 9a180f60a98e0f717d627e565dcbea3f8d800127 Mon Sep 17 00:00:00 2001 From: Zhao Zhili Date: Mon, 9 Jan 2023 20:50:08 +0800 Subject: [PATCH 0069/2172] avcodec/videotoolbox: don't use av_ prefix for local function Signed-off-by: Zhao Zhili --- libavcodec/videotoolbox.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/libavcodec/videotoolbox.c b/libavcodec/videotoolbox.c index a3d19c4c63d..e42fea6f325 100644 --- a/libavcodec/videotoolbox.c +++ b/libavcodec/videotoolbox.c @@ -1173,8 +1173,8 @@ static enum AVPixelFormat videotoolbox_best_pixel_format(AVCodecContext *avctx) return AV_PIX_FMT_NV12; } -static AVVideotoolboxContext *av_videotoolbox_alloc_context_with_pix_fmt(enum AVPixelFormat pix_fmt, - bool full_range) +static AVVideotoolboxContext *videotoolbox_alloc_context_with_pix_fmt(enum AVPixelFormat pix_fmt, + bool full_range) { AVVideotoolboxContext *ret = av_mallocz(sizeof(*ret)); @@ -1207,7 +1207,7 @@ int ff_videotoolbox_common_init(AVCodecContext *avctx) return AVERROR(EINVAL); } - vtctx->vt_ctx = av_videotoolbox_alloc_context_with_pix_fmt(AV_PIX_FMT_NONE, false); + vtctx->vt_ctx = videotoolbox_alloc_context_with_pix_fmt(AV_PIX_FMT_NONE, false); if (!vtctx->vt_ctx) { err = AVERROR(ENOMEM); goto fail; @@ -1392,7 +1392,7 @@ const AVHWAccel ff_prores_videotoolbox_hwaccel = { #if FF_API_VT_HWACCEL_CONTEXT AVVideotoolboxContext *av_videotoolbox_alloc_context(void) { - return av_videotoolbox_alloc_context_with_pix_fmt(AV_PIX_FMT_NONE, false); + return videotoolbox_alloc_context_with_pix_fmt(AV_PIX_FMT_NONE, false); } int av_videotoolbox_default_init(AVCodecContext *avctx) @@ -1404,7 +1404,7 @@ int av_videotoolbox_default_init2(AVCodecContext *avctx, AVVideotoolboxContext * { enum AVPixelFormat pix_fmt = videotoolbox_best_pixel_format(avctx); bool full_range = avctx->color_range == AVCOL_RANGE_JPEG; - avctx->hwaccel_context = vtctx ?: av_videotoolbox_alloc_context_with_pix_fmt(pix_fmt, full_range); + avctx->hwaccel_context = vtctx ?: videotoolbox_alloc_context_with_pix_fmt(pix_fmt, full_range); if (!avctx->hwaccel_context) return AVERROR(ENOMEM); return 0; From 7e4ad6e6a854c13f0c8b499a03cf50f21398874d Mon Sep 17 00:00:00 2001 From: Marton Balint Date: Sun, 22 Jan 2023 00:58:22 +0100 Subject: [PATCH 0070/2172] avcodec/mpeg4videoenc: use MpegEncContext->picture_number instead of encode function parameter They should be the same and that is what most encode functions use. Signed-off-by: Marton Balint --- libavcodec/mpeg4videoenc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavcodec/mpeg4videoenc.c b/libavcodec/mpeg4videoenc.c index a2a14afbd08..e327334d59b 100644 --- a/libavcodec/mpeg4videoenc.c +++ b/libavcodec/mpeg4videoenc.c @@ -1065,7 +1065,7 @@ int ff_mpeg4_encode_picture_header(MpegEncContext *s, int picture_number) if (!(s->avctx->flags & AV_CODEC_FLAG_GLOBAL_HEADER)) { if (s->avctx->strict_std_compliance < FF_COMPLIANCE_VERY_STRICT) // HACK, the reference sw is buggy mpeg4_encode_visual_object_header(s); - if (s->avctx->strict_std_compliance < FF_COMPLIANCE_VERY_STRICT || picture_number == 0) // HACK, the reference sw is buggy + if (s->avctx->strict_std_compliance < FF_COMPLIANCE_VERY_STRICT || s->picture_number == 0) // HACK, the reference sw is buggy mpeg4_encode_vol_header(s, 0, 0); } if (!(s->workaround_bugs & FF_BUG_MS)) From 91c29cf9344855bf33bdcd6add2a61a88e468611 Mon Sep 17 00:00:00 2001 From: Marton Balint Date: Sun, 22 Jan 2023 00:59:59 +0100 Subject: [PATCH 0071/2172] avcodec/rv20enc: use MpegEncContext->picture_number instead of encode function parameter They should be the same and that is what most encode functions use. Signed-off-by: Marton Balint --- libavcodec/rv20enc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavcodec/rv20enc.c b/libavcodec/rv20enc.c index a6bacacb48a..00f6c41e775 100644 --- a/libavcodec/rv20enc.c +++ b/libavcodec/rv20enc.c @@ -39,7 +39,7 @@ void ff_rv20_encode_picture_header(MpegEncContext *s, int picture_number){ put_bits(&s->pb, 1, 0); /* unknown bit */ put_bits(&s->pb, 5, s->qscale); - put_sbits(&s->pb, 8, picture_number); //FIXME wrong, but correct is not known + put_sbits(&s->pb, 8, s->picture_number); //FIXME wrong, but correct is not known s->mb_x= s->mb_y= 0; ff_h263_encode_mba(s); From 103617c93c583355474c59599533735d31dc7f9a Mon Sep 17 00:00:00 2001 From: Marton Balint Date: Sun, 22 Jan 2023 01:06:56 +0100 Subject: [PATCH 0072/2172] avcodec/mpegvideo_enc: remove picture_number parameter from encode functions They are unused. Signed-off-by: Marton Balint --- libavcodec/flvenc.c | 2 +- libavcodec/flvenc.h | 2 +- libavcodec/h261enc.c | 2 +- libavcodec/h261enc.h | 2 +- libavcodec/h263enc.h | 2 +- libavcodec/ituh263enc.c | 2 +- libavcodec/mpeg12enc.c | 2 +- libavcodec/mpeg12enc.h | 2 +- libavcodec/mpeg4videoenc.c | 2 +- libavcodec/mpeg4videoenc.h | 2 +- libavcodec/mpegvideo_enc.c | 26 ++++++++++++-------------- libavcodec/msmpeg4enc.c | 2 +- libavcodec/msmpeg4enc.h | 2 +- libavcodec/rv10enc.c | 2 +- libavcodec/rv10enc.h | 4 ++-- libavcodec/rv20enc.c | 2 +- libavcodec/wmv2enc.c | 2 +- libavcodec/wmv2enc.h | 2 +- 18 files changed, 30 insertions(+), 32 deletions(-) diff --git a/libavcodec/flvenc.c b/libavcodec/flvenc.c index b49ca2e0d5b..3329eb0d900 100644 --- a/libavcodec/flvenc.c +++ b/libavcodec/flvenc.c @@ -25,7 +25,7 @@ #include "mpegvideodata.h" #include "mpegvideoenc.h" -void ff_flv_encode_picture_header(MpegEncContext *s, int picture_number) +void ff_flv_encode_picture_header(MpegEncContext *s) { int format; diff --git a/libavcodec/flvenc.h b/libavcodec/flvenc.h index aaa0fcffaba..1ecbb46b17a 100644 --- a/libavcodec/flvenc.h +++ b/libavcodec/flvenc.h @@ -24,7 +24,7 @@ #include "mpegvideo.h" #include "put_bits.h" -void ff_flv_encode_picture_header(MpegEncContext *s, int picture_number); +void ff_flv_encode_picture_header(MpegEncContext *s); void ff_flv2_encode_ac_esc(PutBitContext *pb, int slevel, int level, int run, int last); diff --git a/libavcodec/h261enc.c b/libavcodec/h261enc.c index e8ea357cbbf..9d6c9a055f3 100644 --- a/libavcodec/h261enc.c +++ b/libavcodec/h261enc.c @@ -52,7 +52,7 @@ typedef struct H261EncContext { } format; } H261EncContext; -void ff_h261_encode_picture_header(MpegEncContext *s, int picture_number) +void ff_h261_encode_picture_header(MpegEncContext *s) { H261EncContext *const h = (H261EncContext *)s; int temp_ref; diff --git a/libavcodec/h261enc.h b/libavcodec/h261enc.h index 102e994494d..d8fdcad7aad 100644 --- a/libavcodec/h261enc.h +++ b/libavcodec/h261enc.h @@ -33,7 +33,7 @@ void ff_h261_reorder_mb_index(MpegEncContext *s); void ff_h261_encode_mb(MpegEncContext *s, int16_t block[6][64], int motion_x, int motion_y); -void ff_h261_encode_picture_header(MpegEncContext *s, int picture_number); +void ff_h261_encode_picture_header(MpegEncContext *s); int ff_h261_encode_init(MpegEncContext *s); #endif diff --git a/libavcodec/h263enc.h b/libavcodec/h263enc.h index fff85a18f23..e45475686ec 100644 --- a/libavcodec/h263enc.h +++ b/libavcodec/h263enc.h @@ -25,7 +25,7 @@ #include "mpegvideoenc.h" void ff_h263_encode_init(MpegEncContext *s); -void ff_h263_encode_picture_header(MpegEncContext *s, int picture_number); +void ff_h263_encode_picture_header(MpegEncContext *s); void ff_h263_encode_gob_header(MpegEncContext * s, int mb_line); void ff_h263_encode_mb(MpegEncContext *s, int16_t block[6][64], diff --git a/libavcodec/ituh263enc.c b/libavcodec/ituh263enc.c index 22e5a8368df..b52b9da52c4 100644 --- a/libavcodec/ituh263enc.c +++ b/libavcodec/ituh263enc.c @@ -105,7 +105,7 @@ av_const int ff_h263_aspect_to_info(AVRational aspect){ return FF_ASPECT_EXTENDED; } -void ff_h263_encode_picture_header(MpegEncContext * s, int picture_number) +void ff_h263_encode_picture_header(MpegEncContext * s) { int format, coded_frame_rate, coded_frame_rate_base, i, temp_ref; int best_clock_code=1; diff --git a/libavcodec/mpeg12enc.c b/libavcodec/mpeg12enc.c index 3ad1cd84a16..a6663a158b8 100644 --- a/libavcodec/mpeg12enc.c +++ b/libavcodec/mpeg12enc.c @@ -468,7 +468,7 @@ void ff_mpeg1_encode_slice_header(MpegEncContext *s) put_bits(&s->pb, 1, 0); } -void ff_mpeg1_encode_picture_header(MpegEncContext *s, int picture_number) +void ff_mpeg1_encode_picture_header(MpegEncContext *s) { MPEG12EncContext *const mpeg12 = (MPEG12EncContext*)s; AVFrameSideData *side_data; diff --git a/libavcodec/mpeg12enc.h b/libavcodec/mpeg12enc.h index 0455e5e4e21..0b35af8a307 100644 --- a/libavcodec/mpeg12enc.h +++ b/libavcodec/mpeg12enc.h @@ -26,7 +26,7 @@ #include "mpegvideo.h" -void ff_mpeg1_encode_picture_header(MpegEncContext *s, int picture_number); +void ff_mpeg1_encode_picture_header(MpegEncContext *s); void ff_mpeg1_encode_mb(MpegEncContext *s, int16_t block[8][64], int motion_x, int motion_y); void ff_mpeg1_encode_init(MpegEncContext *s); diff --git a/libavcodec/mpeg4videoenc.c b/libavcodec/mpeg4videoenc.c index e327334d59b..27df9ba0985 100644 --- a/libavcodec/mpeg4videoenc.c +++ b/libavcodec/mpeg4videoenc.c @@ -1056,7 +1056,7 @@ static void mpeg4_encode_vol_header(MpegEncContext *s, } /* write MPEG-4 VOP header */ -int ff_mpeg4_encode_picture_header(MpegEncContext *s, int picture_number) +int ff_mpeg4_encode_picture_header(MpegEncContext *s) { uint64_t time_incr; int64_t time_div, time_mod; diff --git a/libavcodec/mpeg4videoenc.h b/libavcodec/mpeg4videoenc.h index 243cd297a27..f0d5c3d0770 100644 --- a/libavcodec/mpeg4videoenc.h +++ b/libavcodec/mpeg4videoenc.h @@ -32,7 +32,7 @@ void ff_mpeg4_encode_mb(MpegEncContext *s, int16_t block[6][64], int motion_x, int motion_y); void ff_set_mpeg4_time(MpegEncContext *s); -int ff_mpeg4_encode_picture_header(MpegEncContext *s, int picture_number); +int ff_mpeg4_encode_picture_header(MpegEncContext *s); void ff_mpeg4_encode_video_packet_header(MpegEncContext *s); void ff_mpeg4_stuffing(PutBitContext *pbc); diff --git a/libavcodec/mpegvideo_enc.c b/libavcodec/mpegvideo_enc.c index 9b11c5c05a0..bb101612e5a 100644 --- a/libavcodec/mpegvideo_enc.c +++ b/libavcodec/mpegvideo_enc.c @@ -83,7 +83,7 @@ #define QMAT_SHIFT_MMX 16 #define QMAT_SHIFT 21 -static int encode_picture(MpegEncContext *s, int picture_number); +static int encode_picture(MpegEncContext *s); static int dct_quantize_refine(MpegEncContext *s, int16_t *block, int16_t *weight, int16_t *orig, int n, int qscale); static int sse_mb(MpegEncContext *s); static void denoise_dct_c(MpegEncContext *s, int16_t *block); @@ -1795,7 +1795,7 @@ int ff_mpv_encode_picture(AVCodecContext *avctx, AVPacket *pkt, if (ret < 0) return ret; vbv_retry: - ret = encode_picture(s, s->picture_number); + ret = encode_picture(s); if (growing_buffer) { av_assert0(s->pb.buf == avctx->internal->byte_buffer); pkt->data = s->pb.buf; @@ -3556,14 +3556,12 @@ static void set_frame_distances(MpegEncContext * s){ } } -static int encode_picture(MpegEncContext *s, int picture_number) +static int encode_picture(MpegEncContext *s) { int i, ret; int bits; int context_count = s->slice_context_count; - s->picture_number = picture_number; - /* Reset the average MB variance */ s->me.mb_var_sum_temp = s->me.mc_mb_var_sum_temp = 0; @@ -3788,32 +3786,32 @@ static int encode_picture(MpegEncContext *s, int picture_number) break; case FMT_H261: if (CONFIG_H261_ENCODER) - ff_h261_encode_picture_header(s, picture_number); + ff_h261_encode_picture_header(s); break; case FMT_H263: if (CONFIG_WMV2_ENCODER && s->codec_id == AV_CODEC_ID_WMV2) - ff_wmv2_encode_picture_header(s, picture_number); + ff_wmv2_encode_picture_header(s); else if (CONFIG_MSMPEG4ENC && s->msmpeg4_version) - ff_msmpeg4_encode_picture_header(s, picture_number); + ff_msmpeg4_encode_picture_header(s); else if (CONFIG_MPEG4_ENCODER && s->h263_pred) { - ret = ff_mpeg4_encode_picture_header(s, picture_number); + ret = ff_mpeg4_encode_picture_header(s); if (ret < 0) return ret; } else if (CONFIG_RV10_ENCODER && s->codec_id == AV_CODEC_ID_RV10) { - ret = ff_rv10_encode_picture_header(s, picture_number); + ret = ff_rv10_encode_picture_header(s); if (ret < 0) return ret; } else if (CONFIG_RV20_ENCODER && s->codec_id == AV_CODEC_ID_RV20) - ff_rv20_encode_picture_header(s, picture_number); + ff_rv20_encode_picture_header(s); else if (CONFIG_FLV_ENCODER && s->codec_id == AV_CODEC_ID_FLV1) - ff_flv_encode_picture_header(s, picture_number); + ff_flv_encode_picture_header(s); else if (CONFIG_H263_ENCODER) - ff_h263_encode_picture_header(s, picture_number); + ff_h263_encode_picture_header(s); break; case FMT_MPEG1: if (CONFIG_MPEG1VIDEO_ENCODER || CONFIG_MPEG2VIDEO_ENCODER) - ff_mpeg1_encode_picture_header(s, picture_number); + ff_mpeg1_encode_picture_header(s); break; default: av_assert0(0); diff --git a/libavcodec/msmpeg4enc.c b/libavcodec/msmpeg4enc.c index 9b6e5efa0ca..8798b151521 100644 --- a/libavcodec/msmpeg4enc.c +++ b/libavcodec/msmpeg4enc.c @@ -216,7 +216,7 @@ static void find_best_tables(MSMPEG4EncContext *ms) } /* write MSMPEG4 compatible frame header */ -void ff_msmpeg4_encode_picture_header(MpegEncContext * s, int picture_number) +void ff_msmpeg4_encode_picture_header(MpegEncContext * s) { MSMPEG4EncContext *const ms = (MSMPEG4EncContext*)s; diff --git a/libavcodec/msmpeg4enc.h b/libavcodec/msmpeg4enc.h index 602e60112d4..da9a45b5896 100644 --- a/libavcodec/msmpeg4enc.h +++ b/libavcodec/msmpeg4enc.h @@ -34,7 +34,7 @@ typedef struct MSMPEG4EncContext { } MSMPEG4EncContext; void ff_msmpeg4_encode_init(MpegEncContext *s); -void ff_msmpeg4_encode_picture_header(MpegEncContext *s, int picture_number); +void ff_msmpeg4_encode_picture_header(MpegEncContext *s); void ff_msmpeg4_encode_ext_header(MpegEncContext *s); void ff_msmpeg4_encode_mb(MpegEncContext *s, int16_t block[6][64], int motion_x, int motion_y); diff --git a/libavcodec/rv10enc.c b/libavcodec/rv10enc.c index d0704c5a4b7..7f7477ad7bf 100644 --- a/libavcodec/rv10enc.c +++ b/libavcodec/rv10enc.c @@ -31,7 +31,7 @@ #include "put_bits.h" #include "rv10enc.h" -int ff_rv10_encode_picture_header(MpegEncContext *s, int picture_number) +int ff_rv10_encode_picture_header(MpegEncContext *s) { int full_frame= 0; diff --git a/libavcodec/rv10enc.h b/libavcodec/rv10enc.h index 66672f80876..fc3665e8395 100644 --- a/libavcodec/rv10enc.h +++ b/libavcodec/rv10enc.h @@ -23,7 +23,7 @@ #include "mpegvideo.h" -int ff_rv10_encode_picture_header(MpegEncContext *s, int picture_number); -void ff_rv20_encode_picture_header(MpegEncContext *s, int picture_number); +int ff_rv10_encode_picture_header(MpegEncContext *s); +void ff_rv20_encode_picture_header(MpegEncContext *s); #endif /* AVCODEC_RV10ENC_H */ diff --git a/libavcodec/rv20enc.c b/libavcodec/rv20enc.c index 00f6c41e775..b1b88819dba 100644 --- a/libavcodec/rv20enc.c +++ b/libavcodec/rv20enc.c @@ -34,7 +34,7 @@ #include "put_bits.h" #include "rv10enc.h" -void ff_rv20_encode_picture_header(MpegEncContext *s, int picture_number){ +void ff_rv20_encode_picture_header(MpegEncContext *s) { put_bits(&s->pb, 2, s->pict_type); //I 0 vs. 1 ? put_bits(&s->pb, 1, 0); /* unknown bit */ put_bits(&s->pb, 5, s->qscale); diff --git a/libavcodec/wmv2enc.c b/libavcodec/wmv2enc.c index 05f993525db..cdc450060b1 100644 --- a/libavcodec/wmv2enc.c +++ b/libavcodec/wmv2enc.c @@ -93,7 +93,7 @@ static av_cold int wmv2_encode_init(AVCodecContext *avctx) return 0; } -int ff_wmv2_encode_picture_header(MpegEncContext *s, int picture_number) +int ff_wmv2_encode_picture_header(MpegEncContext *s) { WMV2EncContext *const w = (WMV2EncContext *) s; diff --git a/libavcodec/wmv2enc.h b/libavcodec/wmv2enc.h index 3f7f5104a6e..263265acf38 100644 --- a/libavcodec/wmv2enc.h +++ b/libavcodec/wmv2enc.h @@ -23,7 +23,7 @@ #include "mpegvideo.h" -int ff_wmv2_encode_picture_header(MpegEncContext * s, int picture_number); +int ff_wmv2_encode_picture_header(MpegEncContext * s); void ff_wmv2_encode_mb(MpegEncContext * s, int16_t block[6][64], int motion_x, int motion_y); From bdb7338b099c4727df99f8575e0c857f2b4eda3c Mon Sep 17 00:00:00 2001 From: Marton Balint Date: Sun, 22 Jan 2023 01:20:10 +0100 Subject: [PATCH 0073/2172] avcodec/ratecontrol: drop remnants of libxvid rate control Signed-off-by: Marton Balint --- libavcodec/ratecontrol.h | 3 --- 1 file changed, 3 deletions(-) diff --git a/libavcodec/ratecontrol.h b/libavcodec/ratecontrol.h index 2a7aaec644c..4de80fad904 100644 --- a/libavcodec/ratecontrol.h +++ b/libavcodec/ratecontrol.h @@ -80,9 +80,6 @@ typedef struct RateControlContext{ int frame_count[5]; int last_non_b_pict_type; - void *non_lavc_opaque; ///< context for non lavc rc code (for example xvid) - float dry_run_qscale; ///< for xvid rc - int last_picture_number; ///< for xvid rc AVExpr * rc_eq_eval; }RateControlContext; From c0bc804e552bf6b21ae7da9cfeefe7405e380add Mon Sep 17 00:00:00 2001 From: Marton Balint Date: Tue, 24 Jan 2023 00:38:38 +0100 Subject: [PATCH 0074/2172] avcodec/ffv1: use 64-bit frame counter Signed-off-by: Marton Balint --- libavcodec/ffv1.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavcodec/ffv1.h b/libavcodec/ffv1.h index 005f3087840..04869da5c9a 100644 --- a/libavcodec/ffv1.h +++ b/libavcodec/ffv1.h @@ -85,7 +85,7 @@ typedef struct FFV1Context { int chroma_h_shift, chroma_v_shift; int transparency; int flags; - int picture_number; + int64_t picture_number; int key_frame; ThreadFrame picture, last_picture; struct FFV1Context *fsrc; From 6869a80e76f7f597896e60a0feaa7a32b1aa57ae Mon Sep 17 00:00:00 2001 From: Ashyni Date: Fri, 27 Jan 2023 14:46:07 +0100 Subject: [PATCH 0075/2172] avfilter/vf_cropdetect: fix type for old_limit --- libavfilter/vf_cropdetect.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavfilter/vf_cropdetect.c b/libavfilter/vf_cropdetect.c index 724047f864e..588a38fed81 100644 --- a/libavfilter/vf_cropdetect.c +++ b/libavfilter/vf_cropdetect.c @@ -447,8 +447,8 @@ static int process_command(AVFilterContext *ctx, const char *cmd, const char *ar char *res, int res_len, int flags) { CropDetectContext *s = ctx->priv; + float old_limit = s->limit; int ret; - int old_limit = s->limit; if ((ret = ff_filter_process_command(ctx, cmd, args, res, res_len, flags)) < 0) return ret; From 40512dbd968019fb13c7c58004a0cf6cf76d6d0e Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Fri, 20 Jan 2023 13:59:16 +0100 Subject: [PATCH 0076/2172] avfilter/af_adynamicequalizer: add auto option --- doc/filters.texi | 20 ++++++++++++++++++-- libavfilter/af_adynamicequalizer.c | 28 ++++++++++++++++++++++++---- 2 files changed, 42 insertions(+), 6 deletions(-) diff --git a/doc/filters.texi b/doc/filters.texi index 60e4d113a15..4f4d2ea807b 100644 --- a/doc/filters.texi +++ b/doc/filters.texi @@ -1034,11 +1034,27 @@ Default type is @samp{bell}. Set processing direction relative to threshold. @table @samp @item downward -Boost or cut if threshhold is higher than detected volume. +Boost/Cut if threshold is higher/lower than detected volume. @item upward -Boost or cut if threshhold is lower than detected volume. +Boost/Cut if threshold is lower/higher than detected volume. @end table Default direction is @samp{downward}. + +@item auto +Automatically gather threshold from detection filter. By default +is @samp{disabled}. +This option is useful to detect threshold in certain time frame of +input audio stream, in such case option value is changed at runtime. + +Available values are: +@table @samp +@item disabled +Disable using automatically gathered threshold value. +@item off +Stop picking threshold value. +@item on +Start picking threshold value. +@end table @end table @subsection Commands diff --git a/libavfilter/af_adynamicequalizer.c b/libavfilter/af_adynamicequalizer.c index 144a5fcfe8b..0e44922c1e3 100644 --- a/libavfilter/af_adynamicequalizer.c +++ b/libavfilter/af_adynamicequalizer.c @@ -40,6 +40,7 @@ typedef struct AudioDynamicEqualizerContext { double release_coef; int mode; int direction; + int detection; int type; AVFrame *state; @@ -92,7 +93,6 @@ static int filter_channels(AVFilterContext *ctx, void *arg, int jobnr, int nb_jo 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 = s->threshold; const double release = s->release_coef; const double irelease = 1. - release; const double attack = s->attack_coef; @@ -103,6 +103,7 @@ static int filter_channels(AVFilterContext *ctx, void *arg, int jobnr, int nb_jo const double dg = tan(M_PI * dfrequency / sample_rate); const int start = (in->ch_layout.nb_channels * jobnr) / nb_jobs; const int end = (in->ch_layout.nb_channels * (jobnr+1)) / nb_jobs; + const int detection = s->detection; const int direction = s->direction; const int mode = s->mode; const int type = s->type; @@ -124,6 +125,10 @@ static int filter_channels(AVFilterContext *ctx, void *arg, int jobnr, int nb_jo const double *src = (const double *)in->extended_data[ch]; double *dst = (double *)out->extended_data[ch]; double *state = (double *)s->state->extended_data[ch]; + const double threshold = detection == 0 ? state[5] : s->threshold; + + if (detection < 0) + state[5] = threshold; for (int n = 0; n < out->nb_samples; n++) { double detect, gain, v, listen; @@ -133,6 +138,9 @@ static int filter_channels(AVFilterContext *ctx, void *arg, int jobnr, int nb_jo detect = listen = get_svf(src[n], dm, da, state); detect = fabs(detect); + if (detection > 0) + state[5] = fmax(state[5], detect); + if (direction == 0 && mode == 0 && detect < threshold) detect = 1. / av_clipd(1. + makeup + (threshold - detect) * ratio, 1., range); else if (direction == 0 && mode == 1 && detect < threshold) @@ -144,10 +152,18 @@ static int filter_channels(AVFilterContext *ctx, void *arg, int jobnr, int nb_jo else detect = 1.; - if (detect < state[4]) { - detect = iattack * detect + attack * state[4]; + if (direction == 0) { + if (detect > state[4]) { + detect = iattack * detect + attack * state[4]; + } else { + detect = irelease * detect + release * state[4]; + } } else { - detect = irelease * detect + release * state[4]; + if (detect < state[4]) { + detect = iattack * detect + attack * state[4]; + } else { + detect = irelease * detect + release * state[4]; + } } if (state[4] != detect || n == 0) { @@ -270,6 +286,10 @@ static const AVOption adynamicequalizer_options[] = { { "direction", "set direction", OFFSET(direction), AV_OPT_TYPE_INT, {.i64=0}, 0, 1, FLAGS, "direction" }, { "downward", 0, 0, AV_OPT_TYPE_CONST, {.i64=0}, 0, 0, FLAGS, "direction" }, { "upward", 0, 0, AV_OPT_TYPE_CONST, {.i64=1}, 0, 0, FLAGS, "direction" }, + { "auto", "set auto threshold", OFFSET(detection), AV_OPT_TYPE_INT, {.i64=-1}, -1, 1, FLAGS, "auto" }, + { "disabled", 0, 0, AV_OPT_TYPE_CONST, {.i64=-1}, 0, 0, FLAGS, "auto" }, + { "off", 0, 0, AV_OPT_TYPE_CONST, {.i64=0}, 0, 0, FLAGS, "auto" }, + { "on", 0, 0, AV_OPT_TYPE_CONST, {.i64=1}, 0, 0, FLAGS, "auto" }, { NULL } }; From 23d4f9223a81a4d659ad08cad5014f773d9b8b99 Mon Sep 17 00:00:00 2001 From: Dmitrii Ovchinnikov Date: Tue, 20 Dec 2022 16:20:37 +0100 Subject: [PATCH 0077/2172] amfenc: Update the min version to 1.4.28.0 for AMF SDK. Tested-by: Jean-Baptiste Kempf --- configure | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure b/configure index 6e88c32223f..050ebebc651 100755 --- a/configure +++ b/configure @@ -7041,7 +7041,7 @@ fi enabled amf && check_cpp_condition amf "AMF/core/Version.h" \ - "(AMF_VERSION_MAJOR << 48 | AMF_VERSION_MINOR << 32 | AMF_VERSION_RELEASE << 16 | AMF_VERSION_BUILD_NUM) >= 0x0001000400090000" + "(AMF_VERSION_MAJOR << 48 | AMF_VERSION_MINOR << 32 | AMF_VERSION_RELEASE << 16 | AMF_VERSION_BUILD_NUM) >= 0x00010004001c0000" # Funny iconv installations are not unusual, so check it after all flags have been set if enabled libc_iconv; then From 5f0a7a9169e4714255e6b91b085a55ffa4ae6d58 Mon Sep 17 00:00:00 2001 From: Dmitrii Ovchinnikov Date: Tue, 20 Dec 2022 16:20:38 +0100 Subject: [PATCH 0078/2172] libavcodec/amfenc: add AV1 encoding support Tested-by: Jean-Baptiste Kempf --- configure | 1 + libavcodec/Makefile | 1 + libavcodec/allcodecs.c | 1 + libavcodec/amfenc.c | 9 + libavcodec/amfenc.h | 6 + libavcodec/amfenc_av1.c | 361 ++++++++++++++++++++++++++++++++++++++++ 6 files changed, 379 insertions(+) create mode 100644 libavcodec/amfenc_av1.c diff --git a/configure b/configure index 050ebebc651..cb895cf9ac6 100755 --- a/configure +++ b/configure @@ -3257,6 +3257,7 @@ wmv3_crystalhd_decoder_select="crystalhd" av1_qsv_decoder_select="qsvdec" av1_qsv_encoder_select="qsvenc" av1_qsv_encoder_deps="libvpl" +av1_amf_encoder_deps="amf" # parsers aac_parser_select="adts_header mpeg4audio" diff --git a/libavcodec/Makefile b/libavcodec/Makefile index 2ad4400a813..2d9710923d0 100644 --- a/libavcodec/Makefile +++ b/libavcodec/Makefile @@ -163,6 +163,7 @@ OBJS-$(CONFIG_TEXTUREDSP) += texturedsp.o OBJS-$(CONFIG_TEXTUREDSPENC) += texturedspenc.o OBJS-$(CONFIG_TPELDSP) += tpeldsp.o OBJS-$(CONFIG_VAAPI_ENCODE) += vaapi_encode.o +OBJS-$(CONFIG_AV1_AMF_ENCODER) += amfenc_av1.o OBJS-$(CONFIG_VC1DSP) += vc1dsp.o OBJS-$(CONFIG_VIDEODSP) += videodsp.o OBJS-$(CONFIG_VP3DSP) += vp3dsp.o diff --git a/libavcodec/allcodecs.c b/libavcodec/allcodecs.c index 46aaa89e99a..f728c6c82e9 100644 --- a/libavcodec/allcodecs.c +++ b/libavcodec/allcodecs.c @@ -833,6 +833,7 @@ extern const FFCodec ff_av1_mediacodec_decoder; extern const FFCodec ff_av1_nvenc_encoder; extern const FFCodec ff_av1_qsv_decoder; extern const FFCodec ff_av1_qsv_encoder; +extern const FFCodec ff_av1_amf_encoder; extern const FFCodec ff_libopenh264_encoder; extern const FFCodec ff_libopenh264_decoder; extern const FFCodec ff_h264_amf_encoder; diff --git a/libavcodec/amfenc.c b/libavcodec/amfenc.c index a033e1220ed..c487fc48aad 100644 --- a/libavcodec/amfenc.c +++ b/libavcodec/amfenc.c @@ -349,6 +349,9 @@ static int amf_init_encoder(AVCodecContext *avctx) case AV_CODEC_ID_HEVC: codec_id = AMFVideoEncoder_HEVC; break; + case AV_CODEC_ID_AV1 : + codec_id = AMFVideoEncoder_AV1; + break; default: break; } @@ -460,6 +463,11 @@ static int amf_copy_buffer(AVCodecContext *avctx, AVPacket *pkt, AMFBuffer *buff pkt->flags = AV_PKT_FLAG_KEY; } break; + case AV_CODEC_ID_AV1: + buffer->pVtbl->GetProperty(buffer, AMF_VIDEO_ENCODER_AV1_OUTPUT_FRAME_TYPE, &var); + if (var.int64Value == AMF_VIDEO_ENCODER_AV1_OUTPUT_FRAME_TYPE_KEY) { + pkt->flags = AV_PKT_FLAG_KEY; + } default: break; } @@ -681,6 +689,7 @@ int ff_amf_receive_packet(AVCodecContext *avctx, AVPacket *avpkt) case AV_CODEC_ID_HEVC: AMF_ASSIGN_PROPERTY_INT64(res, surface, AMF_VIDEO_ENCODER_HEVC_INSERT_AUD, !!ctx->aud); break; + //case AV_CODEC_ID_AV1 not supported default: break; } diff --git a/libavcodec/amfenc.h b/libavcodec/amfenc.h index 1ab98d2f784..66e06807196 100644 --- a/libavcodec/amfenc.h +++ b/libavcodec/amfenc.h @@ -23,6 +23,7 @@ #include #include +#include #include "libavutil/fifo.h" @@ -116,6 +117,11 @@ typedef struct AmfContext { int min_qp_p; int max_qp_p; int tier; + + // AV1 - specific options + + enum AMF_VIDEO_ENCODER_AV1_ALIGNMENT_MODE_ENUM align; + } AmfContext; extern const AVCodecHWConfigInternal *const ff_amfenc_hw_configs[]; diff --git a/libavcodec/amfenc_av1.c b/libavcodec/amfenc_av1.c new file mode 100644 index 00000000000..8093cb73575 --- /dev/null +++ b/libavcodec/amfenc_av1.c @@ -0,0 +1,361 @@ +/* + * 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/internal.h" +#include "libavutil/opt.h" +#include "amfenc.h" +#include "codec_internal.h" +#include "internal.h" + +#define OFFSET(x) offsetof(AmfContext, x) +#define VE AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_ENCODING_PARAM +static const AVOption options[] = { + { "usage", "Set the encoding usage", OFFSET(usage), AV_OPT_TYPE_INT, {.i64 = AMF_VIDEO_ENCODER_AV1_USAGE_TRANSCODING }, AMF_VIDEO_ENCODER_AV1_USAGE_TRANSCODING, AMF_VIDEO_ENCODER_AV1_USAGE_LOW_LATENCY, VE, "usage" }, + { "transcoding", "", 0, AV_OPT_TYPE_CONST, {.i64 = AMF_VIDEO_ENCODER_AV1_USAGE_TRANSCODING }, 0, 0, VE, "usage" }, + { "lowlatency", "", 0, AV_OPT_TYPE_CONST, {.i64 = AMF_VIDEO_ENCODER_AV1_USAGE_LOW_LATENCY }, 0, 0, VE, "usage" }, + + { "profile", "Set the profile (default main)", OFFSET(profile), AV_OPT_TYPE_INT,{.i64 = AMF_VIDEO_ENCODER_AV1_PROFILE_MAIN }, AMF_VIDEO_ENCODER_AV1_PROFILE_MAIN, AMF_VIDEO_ENCODER_AV1_PROFILE_MAIN, VE, "profile" }, + { "main", "", 0, AV_OPT_TYPE_CONST,{.i64 = AMF_VIDEO_ENCODER_AV1_PROFILE_MAIN }, 0, 0, VE, "profile" }, + + { "level", "Set the encoding level (default auto)", OFFSET(level), AV_OPT_TYPE_INT,{.i64 = 0 }, 0, AMF_VIDEO_ENCODER_AV1_LEVEL_7_3, VE, "level" }, + { "auto", "", 0, AV_OPT_TYPE_CONST, {.i64 = 0 }, 0, 0, VE, "level" }, + { "2.0", "", 0, AV_OPT_TYPE_CONST, {.i64 = AMF_VIDEO_ENCODER_AV1_LEVEL_2_0 }, 0, 0, VE, "level" }, + { "2.1", "", 0, AV_OPT_TYPE_CONST, {.i64 = AMF_VIDEO_ENCODER_AV1_LEVEL_2_1 }, 0, 0, VE, "level" }, + { "2.2", "", 0, AV_OPT_TYPE_CONST, {.i64 = AMF_VIDEO_ENCODER_AV1_LEVEL_2_2 }, 0, 0, VE, "level" }, + { "2.3", "", 0, AV_OPT_TYPE_CONST, {.i64 = AMF_VIDEO_ENCODER_AV1_LEVEL_2_3 }, 0, 0, VE, "level" }, + { "3.0", "", 0, AV_OPT_TYPE_CONST, {.i64 = AMF_VIDEO_ENCODER_AV1_LEVEL_3_0 }, 0, 0, VE, "level" }, + { "3.1", "", 0, AV_OPT_TYPE_CONST, {.i64 = AMF_VIDEO_ENCODER_AV1_LEVEL_3_1 }, 0, 0, VE, "level" }, + { "3.2", "", 0, AV_OPT_TYPE_CONST, {.i64 = AMF_VIDEO_ENCODER_AV1_LEVEL_3_2 }, 0, 0, VE, "level" }, + { "3.3", "", 0, AV_OPT_TYPE_CONST, {.i64 = AMF_VIDEO_ENCODER_AV1_LEVEL_3_3 }, 0, 0, VE, "level" }, + { "4.0", "", 0, AV_OPT_TYPE_CONST, {.i64 = AMF_VIDEO_ENCODER_AV1_LEVEL_4_0 }, 0, 0, VE, "level" }, + { "4.1", "", 0, AV_OPT_TYPE_CONST, {.i64 = AMF_VIDEO_ENCODER_AV1_LEVEL_4_1 }, 0, 0, VE, "level" }, + { "4.2", "", 0, AV_OPT_TYPE_CONST, {.i64 = AMF_VIDEO_ENCODER_AV1_LEVEL_4_2 }, 0, 0, VE, "level" }, + { "4.3", "", 0, AV_OPT_TYPE_CONST, {.i64 = AMF_VIDEO_ENCODER_AV1_LEVEL_4_3 }, 0, 0, VE, "level" }, + { "5.0", "", 0, AV_OPT_TYPE_CONST, {.i64 = AMF_VIDEO_ENCODER_AV1_LEVEL_5_0 }, 0, 0, VE, "level" }, + { "5.1", "", 0, AV_OPT_TYPE_CONST, {.i64 = AMF_VIDEO_ENCODER_AV1_LEVEL_5_1 }, 0, 0, VE, "level" }, + { "5.2", "", 0, AV_OPT_TYPE_CONST, {.i64 = AMF_VIDEO_ENCODER_AV1_LEVEL_5_2 }, 0, 0, VE, "level" }, + { "5.3", "", 0, AV_OPT_TYPE_CONST, {.i64 = AMF_VIDEO_ENCODER_AV1_LEVEL_5_3 }, 0, 0, VE, "level" }, + { "6.0", "", 0, AV_OPT_TYPE_CONST, {.i64 = AMF_VIDEO_ENCODER_AV1_LEVEL_6_0 }, 0, 0, VE, "level" }, + { "6.1", "", 0, AV_OPT_TYPE_CONST, {.i64 = AMF_VIDEO_ENCODER_AV1_LEVEL_6_1 }, 0, 0, VE, "level" }, + { "6.2", "", 0, AV_OPT_TYPE_CONST, {.i64 = AMF_VIDEO_ENCODER_AV1_LEVEL_6_2 }, 0, 0, VE, "level" }, + { "6.3", "", 0, AV_OPT_TYPE_CONST, {.i64 = AMF_VIDEO_ENCODER_AV1_LEVEL_6_3 }, 0, 0, VE, "level" }, + { "7.0", "", 0, AV_OPT_TYPE_CONST, {.i64 = AMF_VIDEO_ENCODER_AV1_LEVEL_7_0 }, 0, 0, VE, "level" }, + { "7.1", "", 0, AV_OPT_TYPE_CONST, {.i64 = AMF_VIDEO_ENCODER_AV1_LEVEL_7_1 }, 0, 0, VE, "level" }, + { "7.2", "", 0, AV_OPT_TYPE_CONST, {.i64 = AMF_VIDEO_ENCODER_AV1_LEVEL_7_2 }, 0, 0, VE, "level" }, + { "7.3", "", 0, AV_OPT_TYPE_CONST, {.i64 = AMF_VIDEO_ENCODER_AV1_LEVEL_7_3 }, 0, 0, VE, "level" }, + + { "quality", "Set the encoding quality", OFFSET(quality), AV_OPT_TYPE_INT, {.i64 = AMF_VIDEO_ENCODER_AV1_QUALITY_PRESET_SPEED }, AMF_VIDEO_ENCODER_AV1_QUALITY_PRESET_HIGH_QUALITY, AMF_VIDEO_ENCODER_AV1_QUALITY_PRESET_SPEED, VE, "quality" }, + { "balanced", "", 0, AV_OPT_TYPE_CONST, {.i64 = AMF_VIDEO_ENCODER_AV1_QUALITY_PRESET_BALANCED }, 0, 0, VE, "quality" }, + { "speed", "", 0, AV_OPT_TYPE_CONST, {.i64 = AMF_VIDEO_ENCODER_AV1_QUALITY_PRESET_SPEED }, 0, 0, VE, "quality" }, + { "quality", "", 0, AV_OPT_TYPE_CONST, {.i64 = AMF_VIDEO_ENCODER_AV1_QUALITY_PRESET_QUALITY }, 0, 0, VE, "quality" }, + { "high_quality", "", 0, AV_OPT_TYPE_CONST, {.i64 = AMF_VIDEO_ENCODER_AV1_QUALITY_PRESET_HIGH_QUALITY }, 0, 0, VE, "quality" }, + + { "rc", "Set the rate control mode", OFFSET(rate_control_mode), AV_OPT_TYPE_INT, {.i64 = AMF_VIDEO_ENCODER_AV1_RATE_CONTROL_METHOD_UNKNOWN }, AMF_VIDEO_ENCODER_AV1_RATE_CONTROL_METHOD_UNKNOWN, AMF_VIDEO_ENCODER_AV1_RATE_CONTROL_METHOD_CBR, VE, "rc" }, + { "cqp", "Constant Quantization Parameter", 0, AV_OPT_TYPE_CONST, {.i64 = AMF_VIDEO_ENCODER_AV1_RATE_CONTROL_METHOD_CONSTANT_QP }, 0, 0, VE, "rc" }, + { "vbr_latency", "Latency Constrained Variable Bitrate", 0, AV_OPT_TYPE_CONST, {.i64 = AMF_VIDEO_ENCODER_AV1_RATE_CONTROL_METHOD_LATENCY_CONSTRAINED_VBR }, 0, 0, VE, "rc" }, + { "vbr_peak", "Peak Contrained Variable Bitrate", 0, AV_OPT_TYPE_CONST, {.i64 = AMF_VIDEO_ENCODER_AV1_RATE_CONTROL_METHOD_PEAK_CONSTRAINED_VBR }, 0, 0, VE, "rc" }, + { "cbr", "Constant Bitrate", 0, AV_OPT_TYPE_CONST, {.i64 = AMF_VIDEO_ENCODER_AV1_RATE_CONTROL_METHOD_CBR }, 0, 0, VE, "rc" }, + + { "header_insertion_mode", "Set header insertion mode", OFFSET(header_insertion_mode), AV_OPT_TYPE_INT,{.i64 = AMF_VIDEO_ENCODER_AV1_HEADER_INSERTION_MODE_NONE }, AMF_VIDEO_ENCODER_AV1_HEADER_INSERTION_MODE_NONE, AMF_VIDEO_ENCODER_AV1_HEADER_INSERTION_MODE_KEY_FRAME_ALIGNED, VE, "hdrmode" }, + { "none", "", 0, AV_OPT_TYPE_CONST, {.i64 = AMF_VIDEO_ENCODER_AV1_HEADER_INSERTION_MODE_NONE }, 0, 0, VE, "hdrmode" }, + { "gop", "", 0, AV_OPT_TYPE_CONST, {.i64 = AMF_VIDEO_ENCODER_AV1_HEADER_INSERTION_MODE_GOP_ALIGNED }, 0, 0, VE, "hdrmode" }, + { "frame", "", 0, AV_OPT_TYPE_CONST, {.i64 = AMF_VIDEO_ENCODER_AV1_HEADER_INSERTION_MODE_KEY_FRAME_ALIGNED }, 0, 0, VE, "hdrmode" }, + + { "preanalysis", "Enable preanalysis", OFFSET(preanalysis), AV_OPT_TYPE_BOOL, {.i64 = 0 }, 0, 1, VE}, + { "enforce_hrd", "Enforce HRD", OFFSET(enforce_hrd), AV_OPT_TYPE_BOOL, {.i64 = 0 }, 0, 1, VE}, + { "filler_data", "Filler Data Enable", OFFSET(filler_data), AV_OPT_TYPE_BOOL, {.i64 = 0 }, 0, 1, VE}, + + // min_qp_i -> min_qp_intra, min_qp_p -> min_qp_inter + { "min_qp_i", "min quantization parameter for I-frame", OFFSET(min_qp_i), AV_OPT_TYPE_INT, {.i64 = -1 }, -1, 255, VE }, + { "max_qp_i", "max quantization parameter for I-frame", OFFSET(max_qp_i), AV_OPT_TYPE_INT, {.i64 = -1 }, -1, 255, VE }, + { "min_qp_p", "min quantization parameter for P-frame", OFFSET(min_qp_p), AV_OPT_TYPE_INT, {.i64 = -1 }, -1, 255, VE }, + { "max_qp_p", "max quantization parameter for P-frame", OFFSET(max_qp_p), AV_OPT_TYPE_INT, {.i64 = -1 }, -1, 255, VE }, + { "qp_p", "quantization parameter for P-frame", OFFSET(qp_p), AV_OPT_TYPE_INT, {.i64 = -1 }, -1, 255, VE }, + { "qp_i", "quantization parameter for I-frame", OFFSET(qp_i), AV_OPT_TYPE_INT, {.i64 = -1 }, -1, 255, VE }, + { "skip_frame", "Rate Control Based Frame Skip", OFFSET(skip_frame), AV_OPT_TYPE_BOOL,{.i64 = 0 }, 0, 1, VE }, + + { "align", "alignment mode", OFFSET(align), AV_OPT_TYPE_INT, {.i64 = AMF_VIDEO_ENCODER_AV1_ALIGNMENT_MODE_NO_RESTRICTIONS }, AMF_VIDEO_ENCODER_AV1_ALIGNMENT_MODE_64X16_ONLY, AMF_VIDEO_ENCODER_AV1_ALIGNMENT_MODE_NO_RESTRICTIONS, VE, "align" }, + { "64x16", "", 0, AV_OPT_TYPE_CONST, {.i64 = AMF_VIDEO_ENCODER_AV1_ALIGNMENT_MODE_64X16_ONLY }, 0, 0, VE, "align" }, + { "1080p", "", 0, AV_OPT_TYPE_CONST, {.i64 = AMF_VIDEO_ENCODER_AV1_ALIGNMENT_MODE_64X16_1080P_CODED_1082 }, 0, 0, VE, "align" }, + { "none", "", 0, AV_OPT_TYPE_CONST, {.i64 = AMF_VIDEO_ENCODER_AV1_ALIGNMENT_MODE_NO_RESTRICTIONS }, 0, 0, VE, "align" }, + + { NULL } + +}; + +static av_cold int amf_encode_init_av1(AVCodecContext* avctx) +{ + int ret = 0; + AMF_RESULT res = AMF_OK; + AmfContext* ctx = avctx->priv_data; + AMFVariantStruct var = { 0 }; + amf_int64 profile = 0; + amf_int64 profile_level = 0; + AMFBuffer* buffer; + AMFGuid guid; + AMFRate framerate; + AMFSize framesize = AMFConstructSize(avctx->width, avctx->height); + + + + if (avctx->framerate.num > 0 && avctx->framerate.den > 0) { + framerate = AMFConstructRate(avctx->framerate.num, avctx->framerate.den); + } + else { + framerate = AMFConstructRate(avctx->time_base.den, avctx->time_base.num * avctx->ticks_per_frame); + } + + if ((ret = ff_amf_encode_init(avctx)) < 0) + return ret; + + // init static parameters + AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_AV1_USAGE, ctx->usage); + + AMF_ASSIGN_PROPERTY_SIZE(res, ctx->encoder, AMF_VIDEO_ENCODER_AV1_FRAMESIZE, framesize); + + AMF_ASSIGN_PROPERTY_RATE(res, ctx->encoder, AMF_VIDEO_ENCODER_AV1_FRAMERATE, framerate); + + switch (avctx->profile) { + case FF_PROFILE_AV1_MAIN: + profile = AMF_VIDEO_ENCODER_AV1_PROFILE_MAIN; + break; + default: + break; + } + if (profile == 0) { + profile = ctx->profile; + } + AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_AV1_PROFILE, profile); + + profile_level = avctx->level; + if (profile_level == FF_LEVEL_UNKNOWN) { + profile_level = ctx->level; + } + if (profile_level != 0) { + AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_AV1_LEVEL, profile_level); + } + AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_AV1_QUALITY_PRESET, ctx->quality); + + // Maximum Reference Frames + if (avctx->refs != -1) { + AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_AV1_MAX_NUM_REFRAMES, avctx->refs); + } + + // Picture control properties + AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_AV1_GOP_SIZE, avctx->gop_size); + + AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_AV1_HEADER_INSERTION_MODE, ctx->header_insertion_mode); + + // Rate control + // autodetect rate control method + if (ctx->rate_control_mode == AMF_VIDEO_ENCODER_AV1_RATE_CONTROL_METHOD_UNKNOWN) { + if (ctx->min_qp_i != -1 || ctx->max_qp_i != -1 || + ctx->min_qp_p != -1 || ctx->max_qp_p != -1 || + ctx->qp_i != -1 || ctx->qp_p != -1) { + ctx->rate_control_mode = AMF_VIDEO_ENCODER_AV1_RATE_CONTROL_METHOD_CONSTANT_QP; + av_log(ctx, AV_LOG_DEBUG, "Rate control turned to CQP\n"); + } + else if (avctx->rc_max_rate > 0) { + ctx->rate_control_mode = AMF_VIDEO_ENCODER_AV1_RATE_CONTROL_METHOD_PEAK_CONSTRAINED_VBR; + av_log(ctx, AV_LOG_DEBUG, "Rate control turned to Peak VBR\n"); + } + else { + ctx->rate_control_mode = AMF_VIDEO_ENCODER_AV1_RATE_CONTROL_METHOD_CBR; + av_log(ctx, AV_LOG_DEBUG, "Rate control turned to CBR\n"); + } + } + + AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_AV1_RATE_CONTROL_METHOD, ctx->rate_control_mode); + if (avctx->rc_buffer_size) { + AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_AV1_VBV_BUFFER_SIZE, avctx->rc_buffer_size); + + if (avctx->rc_initial_buffer_occupancy != 0) { + int amf_buffer_fullness = avctx->rc_initial_buffer_occupancy * 64 / avctx->rc_buffer_size; + if (amf_buffer_fullness > 64) + amf_buffer_fullness = 64; + AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_AV1_INITIAL_VBV_BUFFER_FULLNESS, amf_buffer_fullness); + } + } + + // Pre-Pass, Pre-Analysis, Two-Pass + AMF_ASSIGN_PROPERTY_BOOL(res, ctx->encoder, AMF_VIDEO_ENCODER_AV1_PRE_ANALYSIS_ENABLE, ctx->preanalysis); + + // init dynamic rate control params + if (ctx->max_au_size) + ctx->enforce_hrd = 1; + AMF_ASSIGN_PROPERTY_BOOL(res, ctx->encoder, AMF_VIDEO_ENCODER_AV1_ENFORCE_HRD, ctx->enforce_hrd); + AMF_ASSIGN_PROPERTY_BOOL(res, ctx->encoder, AMF_VIDEO_ENCODER_AV1_FILLER_DATA, ctx->filler_data); + + AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_AV1_TARGET_BITRATE, avctx->bit_rate); + + if (ctx->rate_control_mode == AMF_VIDEO_ENCODER_AV1_RATE_CONTROL_METHOD_CBR) { + AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_AV1_PEAK_BITRATE, avctx->bit_rate); + } + if (avctx->rc_max_rate) { + AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_AV1_PEAK_BITRATE, avctx->rc_max_rate); + } + else if (ctx->rate_control_mode == AMF_VIDEO_ENCODER_AV1_RATE_CONTROL_METHOD_PEAK_CONSTRAINED_VBR) { + av_log(ctx, AV_LOG_WARNING, "rate control mode is PEAK_CONSTRAINED_VBR but rc_max_rate is not set\n"); + } + if (avctx->bit_rate > 0) { + ctx->rate_control_mode = AMF_VIDEO_ENCODER_AV1_RATE_CONTROL_METHOD_CBR; + av_log(ctx, AV_LOG_DEBUG, "Rate control turned to CBR\n"); + } + + switch (ctx->align) + { + case AMF_VIDEO_ENCODER_AV1_ALIGNMENT_MODE_64X16_ONLY: + if (avctx->width / 64 * 64 != avctx->width || avctx->height / 16 * 16 != avctx->height) + { + res = AMF_NOT_SUPPORTED; + av_log(ctx, AV_LOG_ERROR, "Resolution incorrect for alignment mode\n"); + return AVERROR_EXIT; + } + break; + case AMF_VIDEO_ENCODER_AV1_ALIGNMENT_MODE_64X16_1080P_CODED_1082: + if ((avctx->width / 64 * 64 == avctx->width && avctx->height / 16 * 16 == avctx->height) || (avctx->width == 1920 && avctx->height == 1080)) + { + res = AMF_OK; + } + else + { + res = AMF_NOT_SUPPORTED; + av_log(ctx, AV_LOG_ERROR, "Resolution incorrect for alignment mode\n"); + return AVERROR_EXIT; + } + break; + case AMF_VIDEO_ENCODER_AV1_ALIGNMENT_MODE_NO_RESTRICTIONS: + res = AMF_OK; + break; + default: + res = AMF_NOT_SUPPORTED; + av_log(ctx, AV_LOG_ERROR, "Invalid alignment mode\n"); + return AVERROR_EXIT; + } + AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_AV1_ALIGNMENT_MODE, ctx->align); + + + // init encoder + res = ctx->encoder->pVtbl->Init(ctx->encoder, ctx->format, avctx->width, avctx->height); + AMF_RETURN_IF_FALSE(ctx, res == AMF_OK, AVERROR_BUG, "encoder->Init() failed with error %d\n", res); + + // init dynamic picture control params + if (ctx->min_qp_i != -1) { + AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_AV1_MIN_Q_INDEX_INTRA, ctx->min_qp_i); + } + else if (avctx->qmin != -1) { + int qval = avctx->qmin > 255 ? 255 : avctx->qmin; + AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_AV1_MIN_Q_INDEX_INTRA, qval); + } + if (ctx->max_qp_i != -1) { + AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_AV1_MAX_Q_INDEX_INTRA, ctx->max_qp_i); + } + else if (avctx->qmax != -1) { + int qval = avctx->qmax > 255 ? 255 : avctx->qmax; + AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_AV1_MAX_Q_INDEX_INTRA, qval); + } + if (ctx->min_qp_p != -1) { + AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_AV1_MIN_Q_INDEX_INTER, ctx->min_qp_p); + } + else if (avctx->qmin != -1) { + int qval = avctx->qmin > 255 ? 255 : avctx->qmin; + AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_AV1_MIN_Q_INDEX_INTER, qval); + } + if (ctx->max_qp_p != -1) { + AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_AV1_MAX_Q_INDEX_INTER, ctx->max_qp_p); + } + else if (avctx->qmax != -1) { + int qval = avctx->qmax > 255 ? 255 : avctx->qmax; + AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_AV1_MAX_Q_INDEX_INTER, qval); + } + + if (ctx->qp_p != -1) { + AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_AV1_Q_INDEX_INTER, ctx->qp_p); + } + if (ctx->qp_i != -1) { + AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_AV1_Q_INDEX_INTRA, ctx->qp_i); + } + AMF_ASSIGN_PROPERTY_BOOL(res, ctx->encoder, AMF_VIDEO_ENCODER_AV1_RATE_CONTROL_SKIP_FRAME, ctx->skip_frame); + + + // fill extradata + res = AMFVariantInit(&var); + AMF_RETURN_IF_FALSE(ctx, res == AMF_OK, AVERROR_BUG, "AMFVariantInit() failed with error %d\n", res); + + res = ctx->encoder->pVtbl->GetProperty(ctx->encoder, AMF_VIDEO_ENCODER_AV1_EXTRA_DATA, &var); + AMF_RETURN_IF_FALSE(ctx, res == AMF_OK, AVERROR_BUG, "GetProperty(AMF_VIDEO_ENCODER_EXTRADATA) failed with error %d\n", res); + AMF_RETURN_IF_FALSE(ctx, var.pInterface != NULL, AVERROR_BUG, "GetProperty(AMF_VIDEO_ENCODER_EXTRADATA) returned NULL\n"); + + guid = IID_AMFBuffer(); + + res = var.pInterface->pVtbl->QueryInterface(var.pInterface, &guid, (void**)&buffer); // query for buffer interface + if (res != AMF_OK) { + var.pInterface->pVtbl->Release(var.pInterface); + } + AMF_RETURN_IF_FALSE(ctx, res == AMF_OK, AVERROR_BUG, "QueryInterface(IID_AMFBuffer) failed with error %d\n", res); + + avctx->extradata_size = (int)buffer->pVtbl->GetSize(buffer); + avctx->extradata = av_mallocz(avctx->extradata_size + AV_INPUT_BUFFER_PADDING_SIZE); + if (!avctx->extradata) { + buffer->pVtbl->Release(buffer); + var.pInterface->pVtbl->Release(var.pInterface); + return AVERROR(ENOMEM); + } + memcpy(avctx->extradata, buffer->pVtbl->GetNative(buffer), avctx->extradata_size); + + buffer->pVtbl->Release(buffer); + var.pInterface->pVtbl->Release(var.pInterface); + + return 0; +} + +static const FFCodecDefault defaults[] = { + { "refs", "-1" }, + { "aspect", "0" }, + { "b", "2M" }, + { "g", "250" }, + { "qmin", "-1" }, + { "qmax", "-1" }, + { NULL }, +}; + +static const AVClass av1_amf_class = { + .class_name = "av1_amf", + .item_name = av_default_item_name, + .option = options, + .version = LIBAVUTIL_VERSION_INT, +}; + +const FFCodec ff_av1_amf_encoder = { + .p.name = "av1_amf", + CODEC_LONG_NAME("AMD AMF AV1 encoder"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_AV1, + .init = amf_encode_init_av1, + FF_CODEC_RECEIVE_PACKET_CB(ff_amf_receive_packet), + .close = ff_amf_encode_close, + .priv_data_size = sizeof(AmfContext), + .p.priv_class = &av1_amf_class, + .defaults = defaults, + .p.capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_HARDWARE | + AV_CODEC_CAP_DR1, + .caps_internal = FF_CODEC_CAP_INIT_CLEANUP, + .p.pix_fmts = ff_amf_pix_fmts, + .p.wrapper_name = "amf", + .hw_configs = ff_amfenc_hw_configs, +}; From 0c7da969247cc4498dccefc554d7aaf3c00c194f Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Fri, 27 Jan 2023 15:52:31 +0100 Subject: [PATCH 0079/2172] avcodec/wmaprodec: add missing flush call for xma1 --- libavcodec/wmaprodec.c | 1 + 1 file changed, 1 insertion(+) diff --git a/libavcodec/wmaprodec.c b/libavcodec/wmaprodec.c index fbfe75ee33b..7f7357836a2 100644 --- a/libavcodec/wmaprodec.c +++ b/libavcodec/wmaprodec.c @@ -2110,6 +2110,7 @@ const FFCodec ff_xma1_decoder = { .init = xma_decode_init, .close = xma_decode_end, FF_CODEC_DECODE_CB(xma_decode_packet), + .flush = xma_flush, .p.capabilities = AV_CODEC_CAP_SUBFRAMES | AV_CODEC_CAP_DR1 | AV_CODEC_CAP_DELAY, .p.sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_FLTP, AV_SAMPLE_FMT_NONE }, From 01343683fa219587fa282637389d13fde403099d Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Tue, 24 Jan 2023 16:14:25 +0100 Subject: [PATCH 0080/2172] avcodec: add CBD2 DPCM decoder --- Changelog | 1 + libavcodec/Makefile | 1 + libavcodec/allcodecs.c | 1 + libavcodec/codec_desc.c | 7 +++++++ libavcodec/codec_id.h | 1 + libavcodec/dpcm.c | 10 ++++++++++ libavcodec/utils.c | 1 + libavcodec/version.h | 2 +- libavformat/aiff.c | 1 + libavformat/aiffdec.c | 1 + 10 files changed, 25 insertions(+), 1 deletion(-) diff --git a/Changelog b/Changelog index 9679abce14b..ddcbe9eaa14 100644 --- a/Changelog +++ b/Changelog @@ -30,6 +30,7 @@ version : - adrc audio filter - afdelaysrc audio filter - WADY DPCM decoder and demuxer +- CBD2 DPCM decoder version 5.1: diff --git a/libavcodec/Makefile b/libavcodec/Makefile index 2d9710923d0..f0ffd0b961d 100644 --- a/libavcodec/Makefile +++ b/libavcodec/Makefile @@ -278,6 +278,7 @@ OBJS-$(CONFIG_BRENDER_PIX_DECODER) += brenderpix.o OBJS-$(CONFIG_C93_DECODER) += c93.o OBJS-$(CONFIG_CAVS_DECODER) += cavs.o cavsdec.o cavsdsp.o \ cavsdata.o +OBJS-$(CONFIG_CBD2_DECODER) += dpcm.o OBJS-$(CONFIG_CCAPTION_DECODER) += ccaption_dec.o ass.o OBJS-$(CONFIG_CDGRAPHICS_DECODER) += cdgraphics.o OBJS-$(CONFIG_CDTOONS_DECODER) += cdtoons.o diff --git a/libavcodec/allcodecs.c b/libavcodec/allcodecs.c index f728c6c82e9..f30047e17aa 100644 --- a/libavcodec/allcodecs.c +++ b/libavcodec/allcodecs.c @@ -620,6 +620,7 @@ extern const FFCodec ff_pcm_vidc_encoder; extern const FFCodec ff_pcm_vidc_decoder; /* DPCM codecs */ +extern const FFCodec ff_cbd2_dpcm_decoder; extern const FFCodec ff_derf_dpcm_decoder; extern const FFCodec ff_gremlin_dpcm_decoder; extern const FFCodec ff_interplay_dpcm_decoder; diff --git a/libavcodec/codec_desc.c b/libavcodec/codec_desc.c index 2272232ed6a..50f9794e10d 100644 --- a/libavcodec/codec_desc.c +++ b/libavcodec/codec_desc.c @@ -2626,6 +2626,13 @@ static const AVCodecDescriptor codec_descriptors[] = { .long_name = NULL_IF_CONFIG_SMALL("DPCM Marble WADY"), .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSY, }, + { + .id = AV_CODEC_ID_CBD2_DPCM, + .type = AVMEDIA_TYPE_AUDIO, + .name = "cbd2_dpcm", + .long_name = NULL_IF_CONFIG_SMALL("DPCM Cuberoot-Delta-Exact"), + .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSY, + }, /* audio codecs */ { diff --git a/libavcodec/codec_id.h b/libavcodec/codec_id.h index 5ec3fd4b30d..cdf7eb79c39 100644 --- a/libavcodec/codec_id.h +++ b/libavcodec/codec_id.h @@ -431,6 +431,7 @@ enum AVCodecID { AV_CODEC_ID_GREMLIN_DPCM, AV_CODEC_ID_DERF_DPCM, AV_CODEC_ID_WADY_DPCM, + AV_CODEC_ID_CBD2_DPCM, /* audio codecs */ AV_CODEC_ID_MP2 = 0x15000, diff --git a/libavcodec/dpcm.c b/libavcodec/dpcm.c index 86cb9134f8f..6ea9e2c0650 100644 --- a/libavcodec/dpcm.c +++ b/libavcodec/dpcm.c @@ -194,6 +194,13 @@ static av_cold int dpcm_decode_init(AVCodecContext *avctx) } break; + case AV_CODEC_ID_CBD2_DPCM: + for (i = -128; i < 128; i++) { + int16_t cube = (i * i * i) / 64; + s->array[i+128] = cube; + } + break; + case AV_CODEC_ID_GREMLIN_DPCM: { int delta = 0; int code = 64; @@ -265,6 +272,7 @@ static int dpcm_decode_frame(AVCodecContext *avctx, AVFrame *frame, case AV_CODEC_ID_WADY_DPCM: case AV_CODEC_ID_DERF_DPCM: case AV_CODEC_ID_GREMLIN_DPCM: + case AV_CODEC_ID_CBD2_DPCM: case AV_CODEC_ID_SDX2_DPCM: out = buf_size; break; @@ -386,6 +394,7 @@ static int dpcm_decode_frame(AVCodecContext *avctx, AVFrame *frame, } break; + case AV_CODEC_ID_CBD2_DPCM: case AV_CODEC_ID_SDX2_DPCM: while (output_samples < samples_end) { int8_t n = bytestream2_get_byteu(&gb); @@ -468,6 +477,7 @@ const FFCodec ff_ ## name_ ## _decoder = { \ FF_CODEC_DECODE_CB(dpcm_decode_frame), \ } +DPCM_DECODER(AV_CODEC_ID_CBD2_DPCM, cbd2_dpcm, "DPCM Cuberoot-Delta-Exact"); DPCM_DECODER(AV_CODEC_ID_DERF_DPCM, derf_dpcm, "DPCM Xilam DERF"); DPCM_DECODER(AV_CODEC_ID_GREMLIN_DPCM, gremlin_dpcm, "DPCM Gremlin"); DPCM_DECODER(AV_CODEC_ID_INTERPLAY_DPCM, interplay_dpcm, "DPCM Interplay"); diff --git a/libavcodec/utils.c b/libavcodec/utils.c index 27ab92c9ce5..808a7b8f5b3 100644 --- a/libavcodec/utils.c +++ b/libavcodec/utils.c @@ -514,6 +514,7 @@ int av_get_exact_bits_per_sample(enum AVCodecID codec_id) case AV_CODEC_ID_PCM_SGA: case AV_CODEC_ID_PCM_U8: case AV_CODEC_ID_SDX2_DPCM: + case AV_CODEC_ID_CBD2_DPCM: case AV_CODEC_ID_DERF_DPCM: case AV_CODEC_ID_WADY_DPCM: return 8; diff --git a/libavcodec/version.h b/libavcodec/version.h index dfd3d5d7e57..7ac8d2b2fe2 100644 --- a/libavcodec/version.h +++ b/libavcodec/version.h @@ -29,7 +29,7 @@ #include "version_major.h" -#define LIBAVCODEC_VERSION_MINOR 57 +#define LIBAVCODEC_VERSION_MINOR 58 #define LIBAVCODEC_VERSION_MICRO 100 #define LIBAVCODEC_VERSION_INT AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \ diff --git a/libavformat/aiff.c b/libavformat/aiff.c index 0f25b436bd0..1ceac69a702 100644 --- a/libavformat/aiff.c +++ b/libavformat/aiff.c @@ -46,6 +46,7 @@ const AVCodecTag ff_codec_aiff_tags[] = { { AV_CODEC_ID_QDMC, MKTAG('Q','D','M','C') }, { AV_CODEC_ID_QDM2, MKTAG('Q','D','M','2') }, { AV_CODEC_ID_QCELP, MKTAG('Q','c','l','p') }, + { AV_CODEC_ID_CBD2_DPCM, MKTAG('C','B','D','2') }, { AV_CODEC_ID_SDX2_DPCM, MKTAG('S','D','X','2') }, { AV_CODEC_ID_ADPCM_IMA_WS, MKTAG('A','D','P','4') }, { AV_CODEC_ID_NONE, 0 }, diff --git a/libavformat/aiffdec.c b/libavformat/aiffdec.c index 80733e58010..1cde12c1931 100644 --- a/libavformat/aiffdec.c +++ b/libavformat/aiffdec.c @@ -164,6 +164,7 @@ static int get_aiff_header(AVFormatContext *s, int64_t size, case AV_CODEC_ID_ADPCM_IMA_WS: case AV_CODEC_ID_ADPCM_G722: case AV_CODEC_ID_MACE6: + case AV_CODEC_ID_CBD2_DPCM: case AV_CODEC_ID_SDX2_DPCM: par->block_align = 1 * channels; break; From a749e43c86ea4fd217b035538435ba16956a729c Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Wed, 18 Jan 2023 21:23:39 +0100 Subject: [PATCH 0081/2172] avfilter/vf_datascope: call av_frame_copy_props() --- libavfilter/vf_datascope.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavfilter/vf_datascope.c b/libavfilter/vf_datascope.c index 0a605985f1d..d4f441c0ab6 100644 --- a/libavfilter/vf_datascope.c +++ b/libavfilter/vf_datascope.c @@ -322,7 +322,7 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in) av_frame_free(&in); return AVERROR(ENOMEM); } - out->pts = in->pts; + av_frame_copy_props(out, in); ff_fill_rectangle(&s->draw, &s->black, out->data, out->linesize, 0, 0, outlink->w, outlink->h); From 7b78684f9638b5f78766298fc4583c9a4d80d5ad Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Fri, 27 Jan 2023 22:43:59 +0100 Subject: [PATCH 0082/2172] avfilter/vf_random: set output frame duration --- libavfilter/vf_random.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/libavfilter/vf_random.c b/libavfilter/vf_random.c index b3acdd1fcf6..cb4b3d3827d 100644 --- a/libavfilter/vf_random.c +++ b/libavfilter/vf_random.c @@ -37,6 +37,7 @@ typedef struct RandomContext { int nb_frames_filled; AVFrame *frames[MAX_FRAMES]; int64_t pts[MAX_FRAMES]; + int64_t duration[MAX_FRAMES]; int flush_idx; } RandomContext; @@ -74,6 +75,7 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in) if (s->nb_frames_filled < s->nb_frames) { s->frames[s->nb_frames_filled] = in; + s->duration[s->nb_frames_filled] = in->duration; s->pts[s->nb_frames_filled++] = in->pts; return 0; } @@ -82,9 +84,12 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in) out = s->frames[idx]; out->pts = s->pts[0]; + out->duration = s->duration[0]; memmove(&s->pts[0], &s->pts[1], (s->nb_frames - 1) * sizeof(s->pts[0])); + memmove(&s->duration[0], &s->duration[1], (s->nb_frames - 1) * sizeof(s->duration[0])); s->frames[idx] = in; s->pts[s->nb_frames - 1] = in->pts; + s->duration[s->nb_frames - 1] = in->duration; return ff_filter_frame(outlink, out); } @@ -104,6 +109,7 @@ static int request_frame(AVFilterLink *outlink) s->nb_frames--; goto next; } + out->duration = s->duration[s->flush_idx]; out->pts = s->pts[s->flush_idx++]; ret = ff_filter_frame(outlink, out); s->frames[s->nb_frames - 1] = NULL; From 23d0214939aedc77ab60d799cac4847d692358d5 Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Fri, 27 Jan 2023 22:56:13 +0100 Subject: [PATCH 0083/2172] avfilter/vf_tpad: set output frame duration --- libavfilter/vf_tpad.c | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/libavfilter/vf_tpad.c b/libavfilter/vf_tpad.c index c8704781581..f0c065f0c37 100644 --- a/libavfilter/vf_tpad.c +++ b/libavfilter/vf_tpad.c @@ -75,7 +75,7 @@ static int activate(AVFilterContext *ctx) TPadContext *s = ctx->priv; AVFrame *frame = NULL; int ret, status; - int64_t pts; + int64_t duration, pts; FF_FILTER_FORWARD_STATUS_BACK(outlink, inlink); @@ -98,8 +98,10 @@ static int activate(AVFilterContext *ctx) ff_fill_rectangle(&s->draw, &s->color, frame->data, frame->linesize, 0, 0, frame->width, frame->height); + duration = av_rescale_q(1, av_inv_q(outlink->frame_rate), outlink->time_base); frame->pts = s->pts; - s->pts += av_rescale_q(1, av_inv_q(outlink->frame_rate), outlink->time_base); + frame->duration = duration; + s->pts += duration; s->pad_start--; return ff_filter_frame(outlink, frame); } @@ -116,8 +118,10 @@ static int activate(AVFilterContext *ctx) frame = av_frame_clone(s->cache_start); if (!frame) return AVERROR(ENOMEM); + duration = av_rescale_q(1, av_inv_q(outlink->frame_rate), outlink->time_base); frame->pts = s->pts; - s->pts += av_rescale_q(1, av_inv_q(outlink->frame_rate), outlink->time_base); + frame->duration = duration; + s->pts += duration; s->pad_start--; if (s->pad_start == 0) s->cache_start = NULL; @@ -160,8 +164,10 @@ static int activate(AVFilterContext *ctx) if (!frame) return AVERROR(ENOMEM); } + duration = av_rescale_q(1, av_inv_q(outlink->frame_rate), outlink->time_base); frame->pts = s->pts; - s->pts += av_rescale_q(1, av_inv_q(outlink->frame_rate), outlink->time_base); + frame->duration = duration; + s->pts += duration; if (s->pad_stop > 0) s->pad_stop--; return ff_filter_frame(outlink, frame); From d9b07a98539b9d395df5d5e6a1d8ea91210991ee Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Fri, 27 Jan 2023 23:10:24 +0100 Subject: [PATCH 0084/2172] avfilter/vf_ciescope: set output frame duration --- libavfilter/vf_ciescope.c | 1 + 1 file changed, 1 insertion(+) diff --git a/libavfilter/vf_ciescope.c b/libavfilter/vf_ciescope.c index 1af86f202cb..eebb3af2812 100644 --- a/libavfilter/vf_ciescope.c +++ b/libavfilter/vf_ciescope.c @@ -1407,6 +1407,7 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in) return AVERROR(ENOMEM); } out->pts = in->pts; + out->duration = in->duration; if (!s->background) { ret = draw_background(ctx); From ac37b2c2b12bd256c29f92a2feebfa20b08f5f5c Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Fri, 27 Jan 2023 23:52:14 +0100 Subject: [PATCH 0085/2172] avfilter/f_reverse: set output frame duration --- libavfilter/f_reverse.c | 22 +++++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) diff --git a/libavfilter/f_reverse.c b/libavfilter/f_reverse.c index 2c99557c75e..0ab2a3ab293 100644 --- a/libavfilter/f_reverse.c +++ b/libavfilter/f_reverse.c @@ -33,7 +33,9 @@ typedef struct ReverseContext { AVFrame **frames; unsigned int frames_size; unsigned int pts_size; + unsigned int duration_size; int64_t *pts; + int64_t *duration; int flush_idx; int64_t nb_samples; } ReverseContext; @@ -47,12 +49,15 @@ static av_cold int init(AVFilterContext *ctx) if (!s->pts) return AVERROR(ENOMEM); + s->duration = av_fast_realloc(NULL, &s->duration_size, + DEFAULT_LENGTH * sizeof(*(s->duration))); + if (!s->duration) + return AVERROR(ENOMEM); + s->frames = av_fast_realloc(NULL, &s->frames_size, DEFAULT_LENGTH * sizeof(*(s->frames))); - if (!s->frames) { - av_freep(&s->pts); + if (!s->frames) return AVERROR(ENOMEM); - } return 0; } @@ -67,6 +72,7 @@ static av_cold void uninit(AVFilterContext *ctx) } av_freep(&s->pts); + av_freep(&s->duration); av_freep(&s->frames); } @@ -83,6 +89,13 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in) s->pts = ptr; } + if (s->nb_frames + 1 > s->duration_size / sizeof(*(s->duration))) { + ptr = av_fast_realloc(s->duration, &s->duration_size, s->duration_size * 2); + if (!ptr) + return AVERROR(ENOMEM); + s->duration = ptr; + } + if (s->nb_frames + 1 > s->frames_size / sizeof(*(s->frames))) { ptr = av_fast_realloc(s->frames, &s->frames_size, s->frames_size * 2); if (!ptr) @@ -92,6 +105,7 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in) s->frames[s->nb_frames] = in; s->pts[s->nb_frames] = in->pts; + s->duration[s->nb_frames] = in->duration; s->nb_frames++; return 0; @@ -109,6 +123,7 @@ static int request_frame(AVFilterLink *outlink) if (ret == AVERROR_EOF && s->nb_frames > 0) { AVFrame *out = s->frames[s->nb_frames - 1]; + out->duration= s->duration[s->flush_idx]; out->pts = s->pts[s->flush_idx++]; ret = ff_filter_frame(outlink, out); s->frames[s->nb_frames - 1] = NULL; @@ -252,6 +267,7 @@ static int areverse_request_frame(AVFilterLink *outlink) if (ret == AVERROR_EOF && s->nb_frames > 0) { AVFrame *out = s->frames[s->nb_frames - 1]; + out->duration = s->duration[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; From ed519a36908e2009389c7321ed73da36c586930e Mon Sep 17 00:00:00 2001 From: Shannon Chen Date: Fri, 28 Jul 2017 13:19:09 -0700 Subject: [PATCH 0086/2172] lavfi: Add vf_ssim360 filter Customized SSIM for various projections (and stereo formats) of 360 images and videos. Further contributions by: Ashok Mathew Kuruvilla Matthieu Patou Yu-Hui Wu Anton Khirnov Suggested-By: ffmpeg@fb.com Signed-off-by: Anton Khirnov --- Changelog | 1 + libavfilter/Makefile | 1 + libavfilter/allfilters.c | 1 + libavfilter/version.h | 2 +- libavfilter/vf_ssim360.c | 1768 ++++++++++++++++++++++++++++++++++++++ 5 files changed, 1772 insertions(+), 1 deletion(-) create mode 100644 libavfilter/vf_ssim360.c diff --git a/Changelog b/Changelog index ddcbe9eaa14..57bf816105d 100644 --- a/Changelog +++ b/Changelog @@ -31,6 +31,7 @@ version : - afdelaysrc audio filter - WADY DPCM decoder and demuxer - CBD2 DPCM decoder +- ssim360 video filter version 5.1: diff --git a/libavfilter/Makefile b/libavfilter/Makefile index 211ff4daaa3..d4e38bd4e8b 100644 --- a/libavfilter/Makefile +++ b/libavfilter/Makefile @@ -486,6 +486,7 @@ OBJS-$(CONFIG_SPLIT_FILTER) += split.o OBJS-$(CONFIG_SPP_FILTER) += vf_spp.o qp_table.o OBJS-$(CONFIG_SR_FILTER) += vf_sr.o OBJS-$(CONFIG_SSIM_FILTER) += vf_ssim.o framesync.o +OBJS-$(CONFIG_SSIM360_FILTER) += vf_ssim360.o framesync.o OBJS-$(CONFIG_STEREO3D_FILTER) += vf_stereo3d.o OBJS-$(CONFIG_STREAMSELECT_FILTER) += f_streamselect.o framesync.o OBJS-$(CONFIG_SUBTITLES_FILTER) += vf_subtitles.o diff --git a/libavfilter/allfilters.c b/libavfilter/allfilters.c index 1ab3c8319a4..5c86d0789f9 100644 --- a/libavfilter/allfilters.c +++ b/libavfilter/allfilters.c @@ -458,6 +458,7 @@ extern const AVFilter ff_vf_split; extern const AVFilter ff_vf_spp; extern const AVFilter ff_vf_sr; extern const AVFilter ff_vf_ssim; +extern const AVFilter ff_vf_ssim360; extern const AVFilter ff_vf_stereo3d; extern const AVFilter ff_vf_streamselect; extern const AVFilter ff_vf_subtitles; diff --git a/libavfilter/version.h b/libavfilter/version.h index a56ba3bb6dd..09b9954597b 100644 --- a/libavfilter/version.h +++ b/libavfilter/version.h @@ -31,7 +31,7 @@ #include "version_major.h" -#define LIBAVFILTER_VERSION_MINOR 54 +#define LIBAVFILTER_VERSION_MINOR 55 #define LIBAVFILTER_VERSION_MICRO 100 diff --git a/libavfilter/vf_ssim360.c b/libavfilter/vf_ssim360.c new file mode 100644 index 00000000000..0990db0ed52 --- /dev/null +++ b/libavfilter/vf_ssim360.c @@ -0,0 +1,1768 @@ +/** + * Copyright (c) 2015-2021, Facebook, Inc. + * All rights reserved. + * + * 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 + */ + +/* Computes the Structural Similarity Metric between two 360 video streams. + * original SSIM algorithm: + * Z. Wang, A. C. Bovik, H. R. Sheikh and E. P. Simoncelli, + * "Image quality assessment: From error visibility to structural similarity," + * IEEE Transactions on Image Processing, vol. 13, no. 4, pp. 600-612, Apr. 2004. + * + * To improve speed, this implementation uses the standard approximation of + * overlapped 8x8 block sums, rather than the original gaussian weights. + * + * To address warping from 360 projections for videos with same + * projection and resolution, the 8x8 blocks sampled are weighted by + * their location in the image. + * + * To apply SSIM across projections and video sizes, we render the video on to + * a flat "tape" from which the 8x8 are selected and compared. + */ + +/* + * @file + * Caculate the SSIM between two input 360 videos. + */ + +#include + +#include "libavutil/avstring.h" +#include "libavutil/file_open.h" +#include "libavutil/opt.h" +#include "libavutil/pixdesc.h" + +#include "avfilter.h" +#include "drawutils.h" +#include "formats.h" +#include "internal.h" +#include "video.h" +#include "framesync.h" + +#define RIGHT 0 +#define LEFT 1 +#define TOP 2 +#define BOTTOM 3 +#define FRONT 4 +#define BACK 5 + +#define DEFAULT_HEATMAP_W 32 +#define DEFAULT_HEATMAP_H 16 + +#define M_PI_F ((float)M_PI) +#define M_PI_2_F ((float)M_PI_2) +#define M_PI_4_F ((float)M_PI_4) +#define M_SQRT2_F ((float)M_SQRT2) + +#define DEFAULT_EXPANSION_COEF 1.01f + +static const float BARREL_THETA_RANGE = DEFAULT_EXPANSION_COEF * 2.0f * M_PI_F; +static const float BARREL_PHI_RANGE = DEFAULT_EXPANSION_COEF * M_PI_2_F; + +// Use fixed-point with 16 bit precision for fast bilinear math +static const int FIXED_POINT_PRECISION = 16; + +// Use 1MB per channel for the histogram to get 5-digit precise SSIM value +#define SSIM360_HIST_SIZE 131072 + +// The last number is a marker < 0 to mark end of list +static const double PERCENTILE_LIST[] = { + 1.0, 0.9, 0.8, 0.7, 0.6, + 0.5, 0.4, 0.3, 0.2, 0.1, 0, -1 +}; + +typedef enum StereoFormat { + STEREO_FORMAT_TB, + STEREO_FORMAT_LR, + STEREO_FORMAT_MONO, + STEREO_FORMAT_N +} StereoFormat; + +typedef enum Projection { + PROJECTION_CUBEMAP32, + PROJECTION_CUBEMAP23, + PROJECTION_BARREL, + PROJECTION_BARREL_SPLIT, + PROJECTION_EQUIRECT, + PROJECTION_N +} Projection; + +typedef struct Map2D { + int w, h; + double *value; +} Map2D; + +typedef struct HeatmapList { + Map2D map; + struct HeatmapList *next; +} HeatmapList; + +typedef struct SampleParams { + int stride; + int planewidth; + int planeheight; + int x_image_offset; + int y_image_offset; + int x_image_range; + int y_image_range; + int projection; + float expand_coef; +} SampleParams; + +typedef struct BilinearMap { + // Indices to the 4 samples to compute bilinear + int tli; + int tri; + int bli; + int bri; + + // Fixed point factors with which the above 4 sample vector's + // dot product needs to be computed for the final bilinear value + int tlf; + int trf; + int blf; + int brf; +} BilinearMap; + +typedef struct SSIM360Context { + const AVClass *class; + + FFFrameSync fs; + // Stats file configuration + FILE *stats_file; + char *stats_file_str; + + // Component properties + int nb_components; + double coefs[4]; + char comps[4]; + int max; + + // Channel configuration & properties + int compute_chroma; + + int is_rgb; + uint8_t rgba_map[4]; + + // Standard SSIM computation configuration & workspace + uint64_t frame_skip_ratio; + + int *temp; + uint64_t nb_ssim_frames; + uint64_t nb_net_frames; + double ssim360[4], ssim360_total; + double *ssim360_hist[4]; + double ssim360_hist_net[4]; + double ssim360_percentile_sum[4][256]; + + // 360 projection configuration & workspace + int ref_projection; + int main_projection; + int ref_stereo_format; + int main_stereo_format; + float ref_pad; + float main_pad; + int use_tape; + char *heatmap_str; + int default_heatmap_w; + int default_heatmap_h; + + Map2D density; + HeatmapList *heatmaps; + int ref_planewidth[4]; + int ref_planeheight[4]; + int main_planewidth[4]; + int main_planeheight[4]; + int tape_length[4]; + BilinearMap *ref_tape_map[4][2]; + BilinearMap *main_tape_map[4][2]; + float angular_resolution[4][2]; + double (*ssim360_plane)( + uint8_t *main, int main_stride, + uint8_t *ref, int ref_stride, + int width, int height, void *temp, + int max, Map2D density); +} SSIM360Context; + +#define OFFSET(x) offsetof(SSIM360Context, x) +#define FLAGS AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_VIDEO_PARAM + +static const AVOption ssim360_options[] = { + { "stats_file", "Set file where to store per-frame difference information", + OFFSET(stats_file_str), AV_OPT_TYPE_STRING, {.str=NULL}, 0, 0, FLAGS }, + { "f", "Set file where to store per-frame difference information", + OFFSET(stats_file_str), AV_OPT_TYPE_STRING, {.str=NULL}, 0, 0, FLAGS }, + + { "compute_chroma", + "Specifies if non-luma channels must be computed", + OFFSET(compute_chroma), AV_OPT_TYPE_INT, {.i64 = 1}, + 0, 1, .flags = FLAGS }, + + { "frame_skip_ratio", + "Specifies the number of frames to be skipped from evaluation, for every evaluated frame", + OFFSET(frame_skip_ratio), AV_OPT_TYPE_INT, {.i64 = 0}, + 0, 1000000, .flags = FLAGS }, + + { "ref_projection", "projection of the reference video", + OFFSET(ref_projection), AV_OPT_TYPE_INT, {.i64 = PROJECTION_EQUIRECT}, + 0, PROJECTION_N - 1, .flags = FLAGS, "projection" }, + + { "e", "equirectangular", 0, AV_OPT_TYPE_CONST, {.i64 = PROJECTION_EQUIRECT}, 0, 0, FLAGS, "projection" }, + { "equirect", "equirectangular", 0, AV_OPT_TYPE_CONST, {.i64 = PROJECTION_EQUIRECT}, 0, 0, FLAGS, "projection" }, + { "c3x2", "cubemap 3x2", 0, AV_OPT_TYPE_CONST, {.i64 = PROJECTION_CUBEMAP32}, 0, 0, FLAGS, "projection" }, + { "c2x3", "cubemap 2x3", 0, AV_OPT_TYPE_CONST, {.i64 = PROJECTION_CUBEMAP23}, 0, 0, FLAGS, "projection" }, + { "barrel", "barrel facebook's 360 format", 0, AV_OPT_TYPE_CONST, {.i64 = PROJECTION_BARREL}, 0, 0, FLAGS, "projection" }, + { "barrelsplit", "barrel split facebook's 360 format", 0, AV_OPT_TYPE_CONST, {.i64 = PROJECTION_BARREL_SPLIT}, 0, 0, FLAGS, "projection" }, + + { "main_projection", "projection of the main video", + OFFSET(main_projection), AV_OPT_TYPE_INT, {.i64 = PROJECTION_N}, + 0, PROJECTION_N, .flags = FLAGS, "projection" }, + + { "ref_stereo", "stereo format of the reference video", + OFFSET(ref_stereo_format), AV_OPT_TYPE_INT, {.i64 = STEREO_FORMAT_MONO}, + 0, STEREO_FORMAT_N - 1, .flags = FLAGS, "stereo_format" }, + + { "mono", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = STEREO_FORMAT_MONO }, 0, 0, FLAGS, "stereo_format" }, + { "tb", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = STEREO_FORMAT_TB }, 0, 0, FLAGS, "stereo_format" }, + { "lr", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = STEREO_FORMAT_LR }, 0, 0, FLAGS, "stereo_format" }, + + { "main_stereo", "stereo format of main video", + OFFSET(main_stereo_format), AV_OPT_TYPE_INT, {.i64 = STEREO_FORMAT_N}, + 0, STEREO_FORMAT_N, .flags = FLAGS, "stereo_format" }, + + { "ref_pad", + "Expansion (padding) coefficient for each cube face of the reference video", + OFFSET(ref_pad), AV_OPT_TYPE_FLOAT, {.dbl = .0f}, 0, 10, .flags = FLAGS }, + + { "main_pad", + "Expansion (padding) coeffiecient for each cube face of the main video", + OFFSET(main_pad), AV_OPT_TYPE_FLOAT, {.dbl = .0f}, 0, 10, .flags = FLAGS }, + + { "use_tape", + "Specifies if the tape based SSIM 360 algorithm must be used independent of the input video types", + OFFSET(use_tape), AV_OPT_TYPE_INT, {.i64 = 0}, + 0, 1, .flags = FLAGS }, + + { "heatmap_str", + "Heatmap data for view-based evaluation. For heatmap file format, please refer to EntSphericalVideoHeatmapData.", + OFFSET(heatmap_str), AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, .flags = FLAGS }, + + { "default_heatmap_width", + "Default heatmap dimension. Will be used when dimension is not specified in heatmap data.", + OFFSET(default_heatmap_w), AV_OPT_TYPE_INT, {.i64 = 32}, 1, 4096, .flags = FLAGS }, + + { "default_heatmap_height", + "Default heatmap dimension. Will be used when dimension is not specified in heatmap data.", + OFFSET(default_heatmap_h), AV_OPT_TYPE_INT, {.i64 = 16}, 1, 4096, .flags = FLAGS }, + + { NULL } +}; + +FRAMESYNC_DEFINE_CLASS(ssim360, SSIM360Context, fs); + +static void set_meta(AVDictionary **metadata, const char *key, char comp, float d) +{ + char value[128]; + snprintf(value, sizeof(value), "%0.2f", d); + if (comp) { + char key2[128]; + snprintf(key2, sizeof(key2), "%s%c", key, comp); + av_dict_set(metadata, key2, value, 0); + } else { + av_dict_set(metadata, key, value, 0); + } +} + +static void map_uninit(Map2D *map) +{ + av_freep(&map->value); +} + +static int map_init(Map2D *map, int w, int h) +{ + map->value = av_calloc(h * w, sizeof(*map->value)); + if (!map->value) + return AVERROR(ENOMEM); + + map->h = h; + map->w = w; + + return 0; +} + +static void map_list_free(HeatmapList **pl) +{ + HeatmapList *l = *pl; + + while (l) { + HeatmapList *next = l->next; + map_uninit(&l->map); + av_freep(&l); + l = next; + } + + *pl = NULL; +} + +static int map_alloc(HeatmapList **pl, int w, int h) +{ + HeatmapList *l; + int ret; + + l = av_mallocz(sizeof(*l)); + if (!l) + return AVERROR(ENOMEM); + + ret = map_init(&l->map, w, h); + if (ret < 0) { + av_freep(&l); + return ret; + } + + *pl = l; + return 0; +} + +static void +ssim360_4x4xn_16bit(const uint8_t *main8, ptrdiff_t main_stride, + const uint8_t *ref8, ptrdiff_t ref_stride, + int64_t (*sums)[4], int width) +{ + const uint16_t *main16 = (const uint16_t *)main8; + const uint16_t *ref16 = (const uint16_t *)ref8; + + main_stride >>= 1; + ref_stride >>= 1; + + for (int z = 0; z < width; z++) { + uint64_t s1 = 0, s2 = 0, ss = 0, s12 = 0; + + for (int y = 0; y < 4; y++) { + for (int x = 0; x < 4; x++) { + unsigned a = main16[x + y * main_stride]; + unsigned b = ref16[x + y * ref_stride]; + + s1 += a; + s2 += b; + ss += a*a; + ss += b*b; + s12 += a*b; + } + } + + sums[z][0] = s1; + sums[z][1] = s2; + sums[z][2] = ss; + sums[z][3] = s12; + main16 += 4; + ref16 += 4; + } +} + +static void +ssim360_4x4xn_8bit(const uint8_t *main, ptrdiff_t main_stride, + const uint8_t *ref, ptrdiff_t ref_stride, + int (*sums)[4], int width) +{ + for (int z = 0; z < width; z++) { + uint32_t s1 = 0, s2 = 0, ss = 0, s12 = 0; + + for (int y = 0; y < 4; y++) { + for (int x = 0; x < 4; x++) { + int a = main[x + y * main_stride]; + int b = ref[x + y * ref_stride]; + + s1 += a; + s2 += b; + ss += a*a; + ss += b*b; + s12 += a*b; + } + } + + sums[z][0] = s1; + sums[z][1] = s2; + sums[z][2] = ss; + sums[z][3] = s12; + main += 4; + ref += 4; + } +} + +static float ssim360_end1x(int64_t s1, int64_t s2, int64_t ss, int64_t s12, int max) +{ + int64_t ssim_c1 = (int64_t)(.01 * .01 * max * max * 64 + .5); + int64_t ssim_c2 = (int64_t)(.03 * .03 * max * max * 64 * 63 + .5); + + int64_t fs1 = s1; + int64_t fs2 = s2; + int64_t fss = ss; + int64_t fs12 = s12; + int64_t vars = fss * 64 - fs1 * fs1 - fs2 * fs2; + int64_t covar = fs12 * 64 - fs1 * fs2; + + return (float)(2 * fs1 * fs2 + ssim_c1) * (float)(2 * covar + ssim_c2) + / ((float)(fs1 * fs1 + fs2 * fs2 + ssim_c1) * (float)(vars + ssim_c2)); +} + +static float ssim360_end1(int s1, int s2, int ss, int s12) +{ + static const int ssim_c1 = (int)(.01*.01*255*255*64 + .5); + static const int ssim_c2 = (int)(.03*.03*255*255*64*63 + .5); + + int fs1 = s1; + int fs2 = s2; + int fss = ss; + int fs12 = s12; + int vars = fss * 64 - fs1 * fs1 - fs2 * fs2; + int covar = fs12 * 64 - fs1 * fs2; + + return (float)(2 * fs1 * fs2 + ssim_c1) * (float)(2 * covar + ssim_c2) + / ((float)(fs1 * fs1 + fs2 * fs2 + ssim_c1) * (float)(vars + ssim_c2)); +} + +static double +ssim360_endn_16bit(const int64_t (*sum0)[4], const int64_t (*sum1)[4], + int width, int max, + double *density_map, int map_width, double *total_weight) +{ + double ssim360 = 0.0, weight; + + for (int i = 0; i < width; i++) { + weight = density_map ? density_map[(int) ((0.5 + i) / width * map_width)] : 1.0; + ssim360 += weight * ssim360_end1x( + sum0[i][0] + sum0[i + 1][0] + sum1[i][0] + sum1[i + 1][0], + sum0[i][1] + sum0[i + 1][1] + sum1[i][1] + sum1[i + 1][1], + sum0[i][2] + sum0[i + 1][2] + sum1[i][2] + sum1[i + 1][2], + sum0[i][3] + sum0[i + 1][3] + sum1[i][3] + sum1[i + 1][3], + max); + *total_weight += weight; + } + return ssim360; +} + +static double +ssim360_endn_8bit(const int (*sum0)[4], const int (*sum1)[4], int width, + double *density_map, int map_width, double *total_weight) +{ + double ssim360 = 0.0, weight; + + for (int i = 0; i < width; i++) { + weight = density_map ? density_map[(int) ((0.5 + i) / width * map_width)] : 1.0; + ssim360 += weight * ssim360_end1( + sum0[i][0] + sum0[i + 1][0] + sum1[i][0] + sum1[i + 1][0], + sum0[i][1] + sum0[i + 1][1] + sum1[i][1] + sum1[i + 1][1], + sum0[i][2] + sum0[i + 1][2] + sum1[i][2] + sum1[i + 1][2], + sum0[i][3] + sum0[i + 1][3] + sum1[i][3] + sum1[i + 1][3]); + *total_weight += weight; + } + return ssim360; +} + +static double +ssim360_plane_16bit(uint8_t *main, int main_stride, + uint8_t *ref, int ref_stride, + int width, int height, void *temp, + int max, Map2D density) +{ + int z = 0; + double ssim360 = 0.0; + int64_t (*sum0)[4] = temp; + int64_t (*sum1)[4] = sum0 + (width >> 2) + 3; + double total_weight = 0.0; + + width >>= 2; + height >>= 2; + + for (int y = 1; y < height; y++) { + for (; z <= y; z++) { + FFSWAP(void*, sum0, sum1); + ssim360_4x4xn_16bit(&main[4 * z * main_stride], main_stride, + &ref[4 * z * ref_stride], ref_stride, + sum0, width); + } + ssim360 += ssim360_endn_16bit( + (const int64_t (*)[4])sum0, (const int64_t (*)[4])sum1, + width - 1, max, + density.value ? density.value + density.w * ((int) ((z - 1.0) / height * density.h)) : NULL, + density.w, &total_weight); + } + + return (double) (ssim360 / total_weight); +} + +static double +ssim360_plane_8bit(uint8_t *main, int main_stride, + uint8_t *ref, int ref_stride, + int width, int height, void *temp, + int max, Map2D density) +{ + int z = 0; + double ssim360 = 0.0; + int (*sum0)[4] = temp; + int (*sum1)[4] = sum0 + (width >> 2) + 3; + double total_weight = 0.0; + + width >>= 2; + height >>= 2; + + for (int y = 1; y < height; y++) { + for (; z <= y; z++) { + FFSWAP(void*, sum0, sum1); + ssim360_4x4xn_8bit( + &main[4 * z * main_stride], main_stride, + &ref[4 * z * ref_stride], ref_stride, + sum0, width); + } + ssim360 += ssim360_endn_8bit( + (const int (*)[4])sum0, (const int (*)[4])sum1, width - 1, + density.value ? density.value + density.w * ((int) ((z - 1.0) / height * density.h)) : NULL, + density.w, &total_weight); + } + + return (double) (ssim360 / total_weight); +} + +static double ssim360_db(double ssim360, double weight) +{ + return 10 * log10(weight / (weight - ssim360)); +} + +static int get_bilinear_sample(const uint8_t *data, BilinearMap *m, int max_value) +{ + static const int fixed_point_half = 1 << (FIXED_POINT_PRECISION - 1); + static const int inv_byte_mask = (-1) << 8; + + int tl, tr, bl, br, v; + + if (max_value & inv_byte_mask) { + uint16_t *data16 = (uint16_t *)data; + tl = data16[m->tli]; + tr = data16[m->tri]; + bl = data16[m->bli]; + br = data16[m->bri]; + } else { + tl = data[m->tli]; + tr = data[m->tri]; + bl = data[m->bli]; + br = data[m->bri]; + } + + v = m->tlf * tl + + m->trf * tr + + m->blf * bl + + m->brf * br; + + // Round by half, and revert the fixed-point offset + return ((v + fixed_point_half) >> FIXED_POINT_PRECISION) & max_value; +} + +static void +ssim360_4x4x2_tape(const uint8_t *main, BilinearMap *main_maps, + const uint8_t *ref, BilinearMap *ref_maps, + int offset_y, int max_value, int (*sums)[4]) +{ + int offset_x = 0; + + // Two blocks along the width + for (int z = 0; z < 2; z++) { + int s1 = 0, s2 = 0, ss = 0, s12 = 0; + + // 4 pixel block from (offset_x, offset_y) + for (int y = offset_y; y < offset_y + 4; y++) { + int y_stride = y << 3; + for (int x = offset_x; x < offset_x + 4; x++) { + int map_index = x + y_stride; + int a = get_bilinear_sample(main, main_maps + map_index, max_value); + int b = get_bilinear_sample(ref, ref_maps + map_index, max_value); + + s1 += a; + s2 += b; + ss += a*a; + ss += b*b; + s12 += a*b; + } + } + + sums[z][0] = s1; + sums[z][1] = s2; + sums[z][2] = ss; + sums[z][3] = s12; + + offset_x += 4; + } +} + +static float get_radius_between_negative_and_positive_pi(float theta) +{ + int floor_theta_by_2pi, floor_theta_by_pi; + + // Convert theta to range [0, 2*pi] + floor_theta_by_2pi = (int)(theta / (2.0f * M_PI_F)) - (theta < 0.0f); + theta -= 2.0f * M_PI_F * floor_theta_by_2pi; + + // Convert theta to range [-pi, pi] + floor_theta_by_pi = theta / M_PI_F; + theta -= 2.0f * M_PI_F * floor_theta_by_pi; + return FFMIN(M_PI_F, FFMAX(-M_PI_F, theta)); +} + +static float get_heat(HeatmapList *heatmaps, float angular_resoluation, float norm_tape_pos) +{ + float pitch, yaw, norm_pitch, norm_yaw; + int w, h; + + if (!heatmaps) + return 1.0f; + + pitch = asinf(norm_tape_pos*2); + yaw = M_PI_2_F * pitch / angular_resoluation; + yaw = get_radius_between_negative_and_positive_pi(yaw); + + // normalize into [0,1] + norm_pitch = 1.0f - (pitch / M_PI_F + 0.5f); + norm_yaw = yaw / 2.0f / M_PI_F + 0.5f; + + // get heat on map + w = FFMIN(heatmaps->map.w - 1, FFMAX(0, heatmaps->map.w * norm_yaw)); + h = FFMIN(heatmaps->map.h - 1, FFMAX(0, heatmaps->map.h * norm_pitch)); + return heatmaps->map.value[h * heatmaps->map.w + w]; +} + +static double +ssim360_tape(uint8_t *main, BilinearMap *main_maps, + uint8_t *ref, BilinearMap *ref_maps, + int tape_length, int max_value, void *temp, + double *ssim360_hist, double *ssim360_hist_net, + float angular_resolution, HeatmapList *heatmaps) +{ + int horizontal_block_count = 2; + int vertical_block_count = tape_length >> 2; + + int z = 0, y; + // Since the tape will be very long and we need to average over all 8x8 blocks, use double + double ssim360 = 0.0; + double sum_weight = 0.0; + + int (*sum0)[4] = temp; + int (*sum1)[4] = sum0 + horizontal_block_count + 3; + + for (y = 1; y < vertical_block_count; y++) { + int fs1, fs2, fss, fs12, hist_index; + float norm_tape_pos, weight; + double sample_ssim360; + + for (; z <= y; z++) { + FFSWAP(void*, sum0, sum1); + ssim360_4x4x2_tape(main, main_maps, ref, ref_maps, z*4, max_value, sum0); + } + + // Given we have only one 8x8 block, following sums fit within 26 bits even for 10bit videos + fs1 = sum0[0][0] + sum0[1][0] + sum1[0][0] + sum1[1][0]; + fs2 = sum0[0][1] + sum0[1][1] + sum1[0][1] + sum1[1][1]; + fss = sum0[0][2] + sum0[1][2] + sum1[0][2] + sum1[1][2]; + fs12 = sum0[0][3] + sum0[1][3] + sum1[0][3] + sum1[1][3]; + + if (max_value > 255) { + // Since we need high precision to multiply fss / fs12 by 64, use double + double ssim_c1_d = .01*.01*64*max_value*max_value; + double ssim_c2_d = .03*.03*64*63*max_value*max_value; + + double vars = 64. * fss - 1. * fs1 * fs1 - 1. * fs2 * fs2; + double covar = 64. * fs12 - 1.*fs1 * fs2; + sample_ssim360 = (2. * fs1 * fs2 + ssim_c1_d) * (2. * covar + ssim_c2_d) + / ((1. * fs1 * fs1 + 1. * fs2 * fs2 + ssim_c1_d) * (1. * vars + ssim_c2_d)); + } else { + static const int ssim_c1 = (int)(.01*.01*255*255*64 + .5); + static const int ssim_c2 = (int)(.03*.03*255*255*64*63 + .5); + + int vars = fss * 64 - fs1 * fs1 - fs2 * fs2; + int covar = fs12 * 64 - fs1 * fs2; + sample_ssim360 = (double)(2 * fs1 * fs2 + ssim_c1) * (double)(2 * covar + ssim_c2) + / ((double)(fs1 * fs1 + fs2 * fs2 + ssim_c1) * (double)(vars + ssim_c2)); + } + + hist_index = (int)(sample_ssim360 * ((double)SSIM360_HIST_SIZE - .5)); + hist_index = av_clip(hist_index, 0, SSIM360_HIST_SIZE - 1); + + norm_tape_pos = (y - 0.5f) / (vertical_block_count - 1.0f) - 0.5f; + // weight from an input heatmap if available, otherwise weight = 1.0 + weight = get_heat(heatmaps, angular_resolution, norm_tape_pos); + ssim360_hist[hist_index] += weight; + *ssim360_hist_net += weight; + + ssim360 += (sample_ssim360 * weight); + sum_weight += weight; + } + + return ssim360 / sum_weight; +} + +static void compute_bilinear_map(SampleParams *p, BilinearMap *m, float x, float y) +{ + float fixed_point_scale = (float)(1 << FIXED_POINT_PRECISION); + + // All operations in here will fit in the 22 bit mantissa of floating point, + // since the fixed point precision is well under 22 bits + float x_image = av_clipf(x * p->x_image_range, 0, p->x_image_range) + p->x_image_offset; + float y_image = av_clipf(y * p->y_image_range, 0, p->y_image_range) + p->y_image_offset; + + int x_floor = x_image; + int y_floor = y_image; + float x_diff = x_image - x_floor; + float y_diff = y_image - y_floor; + + int x_ceil = x_floor + (x_diff > 1e-6); + int y_ceil = y_floor + (y_diff > 1e-6); + float x_inv_diff = 1.0f - x_diff; + float y_inv_diff = 1.0f - y_diff; + + // Indices of the 4 samples from source frame + m->tli = x_floor + y_floor * p->stride; + m->tri = x_ceil + y_floor * p->stride; + m->bli = x_floor + y_ceil * p->stride; + m->bri = x_ceil + y_ceil * p->stride; + + // Scale to be applied to each of the 4 samples from source frame + m->tlf = x_inv_diff * y_inv_diff * fixed_point_scale; + m->trf = x_diff * y_inv_diff * fixed_point_scale; + m->blf = x_inv_diff * y_diff * fixed_point_scale; + m->brf = x_diff * y_diff * fixed_point_scale; +} + +static void get_equirect_map(float phi, float theta, float *x, float *y) +{ + *x = 0.5f + theta / (2.0f * M_PI_F); + // y increases downwards + *y = 0.5f - phi / M_PI_F; +} + +static void get_barrel_map(float phi, float theta, float *x, float *y) +{ + float abs_phi = FFABS(phi); + + if (abs_phi <= M_PI_4_F) { + // Equirect region + *x = 0.8f * (0.5f + theta / BARREL_THETA_RANGE); + // y increases downwards + *y = 0.5f - phi / BARREL_PHI_RANGE; + } else { + // Radial ratio on a unit circle = cot(abs_phi) / (expansion_cefficient). + // Using cos(abs_phi)/sin(abs_phi) explicitly to avoid division by zero + float radial_ratio = cosf(abs_phi) / (sinf(abs_phi) * DEFAULT_EXPANSION_COEF); + float circle_x = radial_ratio * sinf(theta); + float circle_y = radial_ratio * cosf(theta); + float offset_y = 0.25f; + if (phi < 0) { + // Bottom circle: theta increases clockwise, and front is upward + circle_y *= -1.0f; + offset_y += 0.5f; + } + + *x = 0.8f + 0.1f * (1.0f + circle_x); + *y = offset_y + 0.25f * circle_y; + } +} + +static void get_barrel_split_map(float phi, float theta, float expand_coef, float *x, float *y) +{ + float abs_phi = FFABS(phi); + + // Front Face [-PI/2, PI/2] -> [0,1]. + // Back Face [PI/2, PI] and [-PI, -PI/2] -> [1, 2] + float radian_pi_theta = theta / M_PI_F + 0.5f; + int vFace; + + if (radian_pi_theta < 0.0f) + radian_pi_theta += 2.0f; + + // Front face at top (= 0), back face at bottom (= 1). + vFace = radian_pi_theta >= 1.0f; + + if (abs_phi <= M_PI_4_F) { + // Equirect region + *x = 2.0f / 3.0f * (0.5f + (radian_pi_theta - vFace - 0.5f) / expand_coef); + // y increases downwards + *y = 0.25f + 0.5f * vFace - phi / (M_PI_F * expand_coef); + } else { + // Radial ratio on a unit circle = cot(abs_phi) / (expansion_cefficient). + // Using cos(abs_phi)/sin(abs_phi) explicitly to avoid division by zero + float radial_ratio = cosf(abs_phi) / (sinf(abs_phi) * expand_coef); + float circle_x = radial_ratio * sinf(theta); + float circle_y = radial_ratio * cosf(theta); + float offset_y = 0.25f; + + if (vFace == 1) { + // Back Face: Flip + circle_x *= -1.0f; + circle_y = (circle_y >= 0.0f) ? (1 - circle_y) : (-1 - circle_y); + offset_y += 0.5f; + + // Bottom circle: theta increases clockwise + if (phi < 0) + circle_y *= -1.0f; + } else { + // Front Face + // Bottom circle: theta increases clockwise + if (phi < 0) + circle_y *= -1.0f; + } + + *x = 2.0f / 3.0f + 0.5f / 3.0f * (1.0f + circle_x); + *y = offset_y + 0.25f * circle_y / expand_coef; // y direction of expand_coeff (margin) + } +} + +// Returns cube face, and provided face_x & face_y will range from [0, 1] +static int get_cubemap_face_map(float axis_vec_x, float axis_vec_y, float axis_vec_z, float *face_x, float *face_y) +{ + // To check if phi, theta hits the top / bottom faces, we check the hit point of + // the axis vector on planes y = 1 and y = -1, and see if x & z are within [-1, 1] + + // 0.577 < 1 / sqrt(3), which is less than the smallest sin(phi) falling on top/bottom faces + // This angle check will save computation from unnecessarily checking the top/bottom faces + if (FFABS(axis_vec_y) > 0.577f) { + float x_hit = axis_vec_x / FFABS(axis_vec_y); + float z_hit = axis_vec_z / axis_vec_y; + + if (FFABS(x_hit) <= 1.f && FFABS(z_hit) <= 1.f) { + *face_x = x_hit; + // y increases downwards + *face_y = z_hit; + return axis_vec_y > 0 ? TOP : BOTTOM; + } + } + + // Check for left / right faces + if (FFABS(axis_vec_x) > 0.577f) { + float z_hit = -axis_vec_z / axis_vec_x; + float y_hit = axis_vec_y / FFABS(axis_vec_x); + + if (FFABS(z_hit) <= 1.f && FFABS(y_hit) <= 1.f) { + *face_x = z_hit; + // y increases downwards + *face_y = -y_hit; + return axis_vec_x > 0 ? RIGHT : LEFT; + } + } + + // Front / back faces + *face_x = axis_vec_x / axis_vec_z; + // y increases downwards + *face_y = -axis_vec_y / FFABS(axis_vec_z); + + return axis_vec_z > 0 ? FRONT : BACK; +} + +static void get_cubemap32_map(float phi, float theta, float *x, float *y) +{ + // face_projection_map maps each cube face to an index representing the face on the projection + // The indices 0->5 for cubemap 32 goes as: + // [0, 1, 2] as row 1, left to right + // [3, 4, 5] as row 2, left to right + static const int face_projection_map[] = { + [RIGHT] = 0, [LEFT] = 1, [TOP] = 2, + [BOTTOM] = 3, [FRONT] = 4, [BACK] = 5, + }; + + float axis_vec_x = cosf(phi) * sinf(theta); + float axis_vec_y = sinf(phi); + float axis_vec_z = cosf(phi) * cosf(theta); + float face_x = 0, face_y = 0; + int face_index = get_cubemap_face_map(axis_vec_x, axis_vec_y, axis_vec_z, &face_x, &face_y); + + float x_offset = 1.f / 3.f * (face_projection_map[face_index] % 3); + float y_offset = .5f * (face_projection_map[face_index] / 3); + + *x = x_offset + (face_x / DEFAULT_EXPANSION_COEF + 1.f) / 6.f; + *y = y_offset + (face_y / DEFAULT_EXPANSION_COEF + 1.f) / 4.f; +} + +static void get_rotated_cubemap_map(float phi, float theta, float expand_coef, float *x, float *y) +{ + // face_projection_map maps each cube face to an index representing the face on the projection + // The indices 0->5 for rotated cubemap goes as: + // [0, 1] as row 1, left to right + // [2, 3] as row 2, left to right + // [4, 5] as row 3, left to right + static const int face_projection_map[] = { + [LEFT] = 0, [TOP] = 1, + [FRONT] = 2, [BACK] = 3, + [RIGHT] = 4, [BOTTOM] = 5, + }; + + float axis_yaw_vec_x, axis_yaw_vec_y, axis_yaw_vec_z; + float axis_pitch_vec_z, axis_pitch_vec_y; + float x_offset, y_offset; + float face_x = 0, face_y = 0; + int face_index; + + // Unrotate the cube and fix the face map: + // First undo the 45 degree yaw + theta += M_PI_4_F; + + // Now we are looking at the middle of an edge. So convert to axis vector & undo the pitch + axis_yaw_vec_x = cosf(phi) * sinf(theta); + axis_yaw_vec_y = sinf(phi); + axis_yaw_vec_z = cosf(phi) * cosf(theta); + + // The pitch axis is along +x, and has value of -45 degree. So, only y and z components change + axis_pitch_vec_z = (axis_yaw_vec_z - axis_yaw_vec_y) / M_SQRT2_F; + axis_pitch_vec_y = (axis_yaw_vec_y + axis_yaw_vec_z) / M_SQRT2_F; + + face_index = get_cubemap_face_map(axis_yaw_vec_x, axis_pitch_vec_y, axis_pitch_vec_z, &face_x, &face_y); + + // Correct for the orientation of the axes on the faces + if (face_index == LEFT || face_index == FRONT || face_index == RIGHT) { + // x increases downwards & y increases towards left + float upright_y = face_y; + face_y = face_x; + face_x = -upright_y; + } else if (face_index == TOP || face_index == BOTTOM) { + // turn the face upside-down for top and bottom + face_x *= -1.f; + face_y *= -1.f; + } + + x_offset = .5f * (face_projection_map[face_index] & 1); + y_offset = 1.f / 3.f * (face_projection_map[face_index] >> 1); + + *x = x_offset + (face_x / expand_coef + 1.f) / 4.f; + *y = y_offset + (face_y / expand_coef + 1.f) / 6.f; +} + +static void get_projected_map(float phi, float theta, SampleParams *p, BilinearMap *m) +{ + float x = 0, y = 0; + switch(p->projection) { +// TODO: Calculate for CDS + case PROJECTION_CUBEMAP23: + get_rotated_cubemap_map(phi, theta, p->expand_coef, &x, &y); + break; + case PROJECTION_CUBEMAP32: + get_cubemap32_map(phi, theta, &x, &y); + break; + case PROJECTION_BARREL: + get_barrel_map(phi, theta, &x, &y); + break; + case PROJECTION_BARREL_SPLIT: + get_barrel_split_map(phi, theta, p->expand_coef, &x, &y); + break; + // Assume PROJECTION_EQUIRECT as the default + case PROJECTION_EQUIRECT: + default: + get_equirect_map(phi, theta, &x, &y); + break; + } + compute_bilinear_map(p, m, x, y); +} + +static int tape_supports_projection(int projection) +{ + switch(projection) { + case PROJECTION_CUBEMAP23: + case PROJECTION_CUBEMAP32: + case PROJECTION_BARREL: + case PROJECTION_BARREL_SPLIT: + case PROJECTION_EQUIRECT: + return 1; + default: + return 0; + } +} + +static float get_tape_angular_resolution(int projection, float expand_coef, int image_width, int image_height) +{ + // NOTE: The angular resolution of a projected sphere is defined as + // the maximum possible horizontal angle of a pixel on the equator. + // We apply an intentional bias to the horizon as opposed to the meridian, + // since the view direction of most content is rarely closer to the poles + + switch(projection) { +// TODO: Calculate for CDS + case PROJECTION_CUBEMAP23: + // Approximating atanf(pixel_width / (half_edge_width * sqrt2)) = pixel_width / (half_face_width * sqrt2) + return expand_coef / (M_SQRT2_F * image_width / 4.f); + case PROJECTION_CUBEMAP32: + // Approximating atanf(pixel_width / half_face_width) = pixel_width / half_face_width + return DEFAULT_EXPANSION_COEF / (image_width / 6.f); + case PROJECTION_BARREL: + return FFMAX(BARREL_THETA_RANGE / (0.8f * image_width), BARREL_PHI_RANGE / image_height); + case PROJECTION_BARREL_SPLIT: + return FFMAX((expand_coef * M_PI_F) / (2.0f / 3.0f * image_width), + expand_coef * M_PI_2_F / (image_height / 2.0f)); + // Assume PROJECTION_EQUIRECT as the default + case PROJECTION_EQUIRECT: + default: + return FFMAX(2.0f * M_PI_F / image_width, M_PI_F / image_height); + } +} + +static int +generate_eye_tape_map(SSIM360Context *s, + int plane, int eye, + SampleParams *ref_sample_params, + SampleParams *main_sample_params) +{ + int ref_image_width = ref_sample_params->x_image_range + 1; + int ref_image_height = ref_sample_params->y_image_range + 1; + + float angular_resolution = + get_tape_angular_resolution(s->ref_projection, 1.f + s->ref_pad, + ref_image_width, ref_image_height); + + float conversion_factor = M_PI_2_F / (angular_resolution * angular_resolution); + float start_phi = -M_PI_2_F + 4.0f * angular_resolution; + float start_x = conversion_factor * sinf(start_phi); + float end_phi = M_PI_2_F - 3.0f * angular_resolution; + float end_x = conversion_factor * sinf(end_phi); + float x_range = end_x - start_x; + + // Ensure tape length is a multiple of 4, for full SSIM block coverage + int tape_length = s->tape_length[plane] = ((int)ROUNDED_DIV(x_range, 4)) << 2; + + s->ref_tape_map[plane][eye] = av_malloc_array(tape_length * 8, sizeof(BilinearMap)); + s->main_tape_map[plane][eye] = av_malloc_array(tape_length * 8, sizeof(BilinearMap)); + if (!s->ref_tape_map[plane][eye] || !s->main_tape_map[plane][eye]) + return AVERROR(ENOMEM); + + s->angular_resolution[plane][eye] = angular_resolution; + + // For easy memory access, we navigate the tape lengthwise on y + for (int y_index = 0; y_index < tape_length; y_index ++) { + int y_stride = y_index << 3; + + float x = start_x + x_range * (y_index / (tape_length - 1.0f)); + // phi will be in range [-pi/2, pi/2] + float mid_phi = asinf(x / conversion_factor); + + float theta = mid_phi * M_PI_2_F / angular_resolution; + theta = get_radius_between_negative_and_positive_pi(theta); + + for (int x_index = 0; x_index < 8; x_index ++) { + float phi = mid_phi + angular_resolution * (3.0f - x_index); + int tape_index = y_stride + x_index; + get_projected_map(phi, theta, ref_sample_params, &s->ref_tape_map [plane][eye][tape_index]); + get_projected_map(phi, theta, main_sample_params, &s->main_tape_map[plane][eye][tape_index]); + } + } + + return 0; +} + +static int generate_tape_maps(SSIM360Context *s, AVFrame *main, const AVFrame *ref) +{ + // A tape is a long segment with 8 pixels thickness, with the angular center at the middle (below 4th pixel). + // When it takes a full loop around a sphere, it will overlap the starting point at half the width from above. + int ref_stereo_format = s->ref_stereo_format; + int main_stereo_format = s->main_stereo_format; + int are_both_stereo = (main_stereo_format != STEREO_FORMAT_MONO) && (ref_stereo_format != STEREO_FORMAT_MONO); + int min_eye_count = 1 + are_both_stereo; + int ret; + + for (int i = 0; i < s->nb_components; i ++) { + int ref_width = s->ref_planewidth[i]; + int ref_height = s->ref_planeheight[i]; + int main_width = s->main_planewidth[i]; + int main_height = s->main_planeheight[i]; + + int is_ref_LR = (ref_stereo_format == STEREO_FORMAT_LR); + int is_ref_TB = (ref_stereo_format == STEREO_FORMAT_TB); + int is_main_LR = (main_stereo_format == STEREO_FORMAT_LR); + int is_main_TB = (main_stereo_format == STEREO_FORMAT_TB); + + int ref_image_width = is_ref_LR ? ref_width >> 1 : ref_width; + int ref_image_height = is_ref_TB ? ref_height >> 1 : ref_height; + int main_image_width = is_main_LR ? main_width >> 1 : main_width; + int main_image_height = is_main_TB ? main_height >> 1 : main_height; + + for (int eye = 0; eye < min_eye_count; eye ++) { + SampleParams ref_sample_params = { + .stride = ref->linesize[i], + .planewidth = ref_width, + .planeheight = ref_height, + .x_image_range = ref_image_width - 1, + .y_image_range = ref_image_height - 1, + .x_image_offset = is_ref_LR * eye * ref_image_width, + .y_image_offset = is_ref_TB * eye * ref_image_height, + .projection = s->ref_projection, + .expand_coef = 1.f + s->ref_pad, + }; + + SampleParams main_sample_params = { + .stride = main->linesize[i], + .planewidth = main_width, + .planeheight = main_height, + .x_image_range = main_image_width - 1, + .y_image_range = main_image_height - 1, + .x_image_offset = is_main_LR * eye * main_image_width, + .y_image_offset = is_main_TB * eye * main_image_height, + .projection = s->main_projection, + .expand_coef = 1.f + s->main_pad, + }; + + ret = generate_eye_tape_map(s, i, eye, &ref_sample_params, &main_sample_params); + if (ret < 0) + return ret; + } + } + + return 0; +} + +static int do_ssim360(FFFrameSync *fs) +{ + AVFilterContext *ctx = fs->parent; + SSIM360Context *s = ctx->priv; + AVFrame *master, *ref; + AVDictionary **metadata; + double c[4], ssim360v = 0.0, ssim360p50 = 0.0; + int i, ret; + int need_frame_skip = s->nb_net_frames % (s->frame_skip_ratio + 1); + HeatmapList* h_ptr = NULL; + + ret = ff_framesync_dualinput_get(fs, &master, &ref); + if (ret < 0) + return ret; + + s->nb_net_frames++; + + if (need_frame_skip) + return ff_filter_frame(ctx->outputs[0], master); + + metadata = &master->metadata; + + if (s->use_tape && !s->tape_length[0]) { + ret = generate_tape_maps(s, master, ref); + if (ret < 0) + return ret; + } + + for (i = 0; i < s->nb_components; i++) { + if (s->use_tape) { + c[i] = ssim360_tape(master->data[i], s->main_tape_map[i][0], + ref->data[i], s->ref_tape_map [i][0], + s->tape_length[i], s->max, s->temp, + s->ssim360_hist[i], &s->ssim360_hist_net[i], + s->angular_resolution[i][0], s->heatmaps); + + if (s->ref_tape_map[i][1]) { + c[i] += ssim360_tape(master->data[i], s->main_tape_map[i][1], + ref->data[i], s->ref_tape_map[i][1], + s->tape_length[i], s->max, s->temp, + s->ssim360_hist[i], &s->ssim360_hist_net[i], + s->angular_resolution[i][1], s->heatmaps); + c[i] /= 2.f; + } + } else { + c[i] = s->ssim360_plane(master->data[i], master->linesize[i], + ref->data[i], ref->linesize[i], + s->ref_planewidth[i], s->ref_planeheight[i], + s->temp, s->max, s->density); + } + + s->ssim360[i] += c[i]; + ssim360v += s->coefs[i] * c[i]; + } + + s->nb_ssim_frames++; + if (s->heatmaps) { + map_uninit(&s->heatmaps->map); + h_ptr = s->heatmaps; + s->heatmaps = s->heatmaps->next; + av_freep(&h_ptr); + } + s->ssim360_total += ssim360v; + + // Record percentiles from histogram and attach metadata when using tape + if (s->use_tape) { + int i, p, hist_indices[4]; + double hist_weight[4]; + + for (i = 0; i < s->nb_components; i++) { + hist_indices[i] = SSIM360_HIST_SIZE - 1; + hist_weight[i] = 0; + } + + for (p = 0; PERCENTILE_LIST[p] >= 0.0; p ++) { + for (i = 0; i < s->nb_components; i++) { + double target_weight, ssim360p; + + // Target weight = total number of samples above the specified percentile + target_weight = (1. - PERCENTILE_LIST[p]) * s->ssim360_hist_net[i]; + target_weight = FFMAX(target_weight, 1); + while(hist_indices[i] >= 0 && hist_weight[i] < target_weight) { + hist_weight[i] += s->ssim360_hist[i][hist_indices[i]]; + hist_indices[i] --; + } + + ssim360p = (double)(hist_indices[i] + 1) / (double)(SSIM360_HIST_SIZE - 1); + if (PERCENTILE_LIST[p] == 0.5) + ssim360p50 += s->coefs[i] * ssim360p; + s->ssim360_percentile_sum[i][p] += ssim360p; + } + } + + for (i = 0; i < s->nb_components; i++) { + memset(s->ssim360_hist[i], 0, SSIM360_HIST_SIZE * sizeof(double)); + s->ssim360_hist_net[i] = 0; + } + + for (i = 0; i < s->nb_components; i++) { + int cidx = s->is_rgb ? s->rgba_map[i] : i; + set_meta(metadata, "lavfi.ssim360.", s->comps[i], c[cidx]); + } + + // Use p50 as the aggregated value + set_meta(metadata, "lavfi.ssim360.All", 0, ssim360p50); + set_meta(metadata, "lavfi.ssim360.dB", 0, ssim360_db(ssim360p50, 1.0)); + + if (s->stats_file) { + fprintf(s->stats_file, "n:%"PRId64" ", s->nb_ssim_frames); + + for (i = 0; i < s->nb_components; i++) { + int cidx = s->is_rgb ? s->rgba_map[i] : i; + fprintf(s->stats_file, "%c:%f ", s->comps[i], c[cidx]); + } + + fprintf(s->stats_file, "All:%f (%f)\n", ssim360p50, ssim360_db(ssim360p50, 1.0)); + } + } + + return ff_filter_frame(ctx->outputs[0], master); +} + +static int parse_heatmaps(void *logctx, HeatmapList **proot, + const char *data, int w, int h) +{ + HeatmapList *root = NULL; + HeatmapList **next = &root; + + int ret; + + // skip video id line + data = strchr(data, '\n'); + if (!data) { + av_log(logctx, AV_LOG_ERROR, "Invalid heatmap syntax\n"); + return AVERROR(EINVAL); + } + data++; + + while (*data) { + HeatmapList *cur; + char *line = av_get_token(&data, "\n"); + char *saveptr, *val; + int i; + + if (!line) { + ret = AVERROR(ENOMEM); + goto fail; + } + if (!line) { + av_freep(&line); + break; + } + + // first value is frame id + av_strtok(line, ",", &saveptr); + + ret = map_alloc(next, w, h); + if (ret < 0) + goto line_fail; + + cur = *next; + next = &cur->next; + + i = 0; + while ((val = av_strtok(NULL, ",", &saveptr))) { + if (i >= w * h) { + av_log(logctx, AV_LOG_ERROR, "Too many entries in a heat map\n"); + ret = AVERROR(EINVAL); + goto line_fail; + } + + cur->map.value[i++] = atof(val); + } + +line_fail: + av_freep(&line); + if (ret < 0) + goto fail; + } + + *proot = root; + + return 0; +fail: + map_list_free(&root); + return ret; +} + +static av_cold int init(AVFilterContext *ctx) +{ + SSIM360Context *s = ctx->priv; + int err; + + if (s->stats_file_str) { + if (!strcmp(s->stats_file_str, "-")) { + s->stats_file = stdout; + } else { + s->stats_file = avpriv_fopen_utf8(s->stats_file_str, "w"); + if (!s->stats_file) { + char buf[128]; + + err = AVERROR(errno); + av_strerror(err, buf, sizeof(buf)); + av_log(ctx, AV_LOG_ERROR, "Could not open stats file %s: %s\n", + s->stats_file_str, buf); + return err; + } + } + } + + if (s->use_tape && s->heatmap_str) { + err = parse_heatmaps(ctx, &s->heatmaps, s->heatmap_str, + s->default_heatmap_w, s->default_heatmap_h); + if (err < 0) + return err; + } + + s->fs.on_event = do_ssim360; + return 0; +} + +static int config_input_main(AVFilterLink *inlink) +{ + const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(inlink->format); + AVFilterContext *ctx = inlink->dst; + SSIM360Context *s = ctx->priv; + + s->main_planeheight[0] = inlink->h; + s->main_planeheight[3] = inlink->h; + s->main_planeheight[1] = AV_CEIL_RSHIFT(inlink->h, desc->log2_chroma_h); + s->main_planeheight[2] = AV_CEIL_RSHIFT(inlink->h, desc->log2_chroma_h); + + s->main_planewidth[0] = inlink->w; + s->main_planewidth[3] = inlink->w; + s->main_planewidth[1] = AV_CEIL_RSHIFT(inlink->w, desc->log2_chroma_w); + s->main_planewidth[2] = AV_CEIL_RSHIFT(inlink->w, desc->log2_chroma_w); + + // If main projection is unindentified, assume it is same as reference + if (s->main_projection == PROJECTION_N) + s->main_projection = s->ref_projection; + + // If main stereo format is unindentified, assume it is same as reference + if (s->main_stereo_format == STEREO_FORMAT_N) + s->main_stereo_format = s->ref_stereo_format; + + return 0; +} + +static int generate_density_map(SSIM360Context *s, int w, int h) +{ + double d, r_square, cos_square; + int ow, oh, ret; + + ret = map_init(&s->density, w, h); + if (ret < 0) + return ret; + + switch (s->ref_stereo_format) { + case STEREO_FORMAT_TB: + h >>= 1; + break; + case STEREO_FORMAT_LR: + w >>= 1; + break; + } + + switch (s->ref_projection) { + case PROJECTION_EQUIRECT: + for (int i = 0; i < h; i++) { + d = cos(((0.5 + i) / h - 0.5) * M_PI); + for (int j = 0; j < w; j++) + s->density.value[i * w + j] = d; + } + break; + case PROJECTION_CUBEMAP32: + // for one quater of a face + for (int i = 0; i < h / 4; i++) { + for (int j = 0; j < w / 6; j++) { + // r = normalized distance to the face center + r_square = + (0.5 + i) / (h / 2) * (0.5 + i) / (h / 2) + + (0.5 + j) / (w / 3) * (0.5 + j) / (w / 3); + r_square /= DEFAULT_EXPANSION_COEF * DEFAULT_EXPANSION_COEF; + cos_square = 0.25 / (r_square + 0.25); + d = pow(cos_square, 1.5); + + for (int face = 0; face < 6; face++) { + // center of a face + switch (face) { + case 0: + oh = h / 4; + ow = w / 6; + break; + case 1: + oh = h / 4; + ow = w / 6 + w / 3; + break; + case 2: + oh = h / 4; + ow = w / 6 + 2 * w / 3; + break; + case 3: + oh = h / 4 + h / 2; + ow = w / 6; + break; + case 4: + oh = h / 4 + h / 2; + ow = w / 6 + w / 3; + break; + case 5: + oh = h / 4 + h / 2; + ow = w / 6 + 2 * w / 3; + break; + } + s->density.value[(oh - 1 - i) * w + ow - 1 - j] = d; + s->density.value[(oh - 1 - i) * w + ow + j] = d; + s->density.value[(oh + i) * w + ow - 1 - j] = d; + s->density.value[(oh + i) * w + ow + j] = d; + } + } + } + break; + case PROJECTION_CUBEMAP23: + // for one quater of a face + for (int i = 0; i < h / 6; i++) { + for (int j = 0; j < w / 4; j++) { + // r = normalized distance to the face center + r_square = + (0.5 + i) / (h / 3) * (0.5 + i) / (h / 3) + + (0.5 + j) / (w / 2) * (0.5 + j) / (w / 2); + r_square /= (1.f + s->ref_pad) * (1.f + s->ref_pad); + cos_square = 0.25 / (r_square + 0.25); + d = pow(cos_square, 1.5); + + for (int face = 0; face < 6; face++) { + // center of a face + switch (face) { + case 0: + ow = w / 4; + oh = h / 6; + break; + case 1: + ow = w / 4; + oh = h / 6 + h / 3; + break; + case 2: + ow = w / 4; + oh = h / 6 + 2 * h / 3; + break; + case 3: + ow = w / 4 + w / 2; + oh = h / 6; + break; + case 4: + ow = w / 4 + w / 2; + oh = h / 6 + h / 3; + break; + case 5: + ow = w / 4 + w / 2; + oh = h / 6 + 2 * h / 3; + break; + } + s->density.value[(oh - 1 - i) * w + ow - 1 - j] = d; + s->density.value[(oh - 1 - i) * w + ow + j] = d; + s->density.value[(oh + i) * w + ow - 1 - j] = d; + s->density.value[(oh + i) * w + ow + j] = d; + } + } + } + break; + case PROJECTION_BARREL: + // side face + for (int i = 0; i < h; i++) { + for (int j = 0; j < w * 4 / 5; j++) { + d = cos(((0.5 + i) / h - 0.5) * DEFAULT_EXPANSION_COEF * M_PI_2); + s->density.value[i * w + j] = d * d * d; + } + } + // top and bottom + for (int i = 0; i < h; i++) { + for (int j = w * 4 / 5; j < w; j++) { + double dx = DEFAULT_EXPANSION_COEF * (0.5 + j - w * 0.90) / (w * 0.10); + double dx_squared = dx * dx; + + double top_dy = DEFAULT_EXPANSION_COEF * (0.5 + i - h * 0.25) / (h * 0.25); + double top_dy_squared = top_dy * top_dy; + + double bottom_dy = DEFAULT_EXPANSION_COEF * (0.5 + i - h * 0.75) / (h * 0.25); + double bottom_dy_squared = bottom_dy * bottom_dy; + + // normalized distance to the circle center + r_square = (i < h / 2 ? top_dy_squared : bottom_dy_squared) + dx_squared; + if (r_square > 1.0) + continue; + + cos_square = 1.0 / (r_square + 1.0); + d = pow(cos_square, 1.5); + s->density.value[i * w + j] = d; + } + } + break; + default: + // TODO: SSIM360_v1 + for (int i = 0; i < h; i++) { + for (int j = 0; j < w; j++) + s->density.value[i * w + j] = 0; + } + } + + switch (s->ref_stereo_format) { + case STEREO_FORMAT_TB: + for (int i = 0; i < h; i++) { + for (int j = 0; j < w; j++) + s->density.value[(i + h) * w + j] = s->density.value[i * w + j]; + } + break; + case STEREO_FORMAT_LR: + for (int i = 0; i < h; i++) { + for (int j = 0; j < w; j++) + s->density.value[i * w + j + w] = s->density.value[i * w + j]; + } + } + + return 0; +} + +static int config_input_ref(AVFilterLink *inlink) +{ + const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(inlink->format); + AVFilterContext *ctx = inlink->dst; + SSIM360Context *s = ctx->priv; + int sum = 0; + + s->nb_components = desc->nb_components; + + s->ref_planeheight[0] = inlink->h; + s->ref_planeheight[3] = inlink->h; + s->ref_planeheight[1] = AV_CEIL_RSHIFT(inlink->h, desc->log2_chroma_h); + s->ref_planeheight[2] = AV_CEIL_RSHIFT(inlink->h, desc->log2_chroma_h); + + s->ref_planewidth[0] = inlink->w; + s->ref_planewidth[3] = inlink->w; + s->ref_planewidth[1] = AV_CEIL_RSHIFT(inlink->w, desc->log2_chroma_w); + s->ref_planewidth[2] = AV_CEIL_RSHIFT(inlink->w, desc->log2_chroma_w); + + s->is_rgb = ff_fill_rgba_map(s->rgba_map, inlink->format) >= 0; + s->comps[0] = s->is_rgb ? 'R' : 'Y'; + s->comps[1] = s->is_rgb ? 'G' : 'U'; + s->comps[2] = s->is_rgb ? 'B' : 'V'; + s->comps[3] = 'A'; + + // If chroma computation is disabled, and the format is YUV, skip U & V channels + if (!s->is_rgb && !s->compute_chroma) + s->nb_components = 1; + + s->max = (1 << desc->comp[0].depth) - 1; + + s->ssim360_plane = desc->comp[0].depth > 8 ? ssim360_plane_16bit : ssim360_plane_8bit; + + for (int i = 0; i < s->nb_components; i++) + sum += s->ref_planeheight[i] * s->ref_planewidth[i]; + for (int i = 0; i < s->nb_components; i++) + s->coefs[i] = (double) s->ref_planeheight[i] * s->ref_planewidth[i] / sum; + + return 0; +} + +static int config_output(AVFilterLink *outlink) +{ + AVFilterContext *ctx = outlink->src; + SSIM360Context *s = ctx->priv; + AVFilterLink *mainlink = ctx->inputs[0]; + AVFilterLink *reflink = ctx->inputs[0]; + const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(outlink->format); + int ret; + + // Use tape algorithm if any of frame sizes, projections or stereo format are not equal + if (ctx->inputs[0]->w != ctx->inputs[1]->w || ctx->inputs[0]->h != ctx->inputs[1]->h || + s->ref_projection != s->main_projection || s->ref_stereo_format != s->main_stereo_format) + s->use_tape = 1; + + // Finally, if we have decided to / forced to use tape, check if tape supports both input and output projection + if (s->use_tape && + !(tape_supports_projection(s->main_projection) && + tape_supports_projection(s->ref_projection))) { + av_log(ctx, AV_LOG_ERROR, "Projection is unsupported for the tape based algorithm\n"); + return AVERROR(EINVAL); + } + + if (s->use_tape) { + // s->temp will be allocated for the tape width = 8. The tape is long downwards + s->temp = av_malloc_array((2 * 8 + 12), sizeof(*s->temp)); + if (!s->temp) + return AVERROR(ENOMEM); + + memset(s->ssim360_percentile_sum, 0, sizeof(s->ssim360_percentile_sum)); + + for (int i = 0; i < s->nb_components; i++) { + s->ssim360_hist[i] = av_calloc(SSIM360_HIST_SIZE, sizeof(*s->ssim360_hist)); + if (!s->ssim360_hist[i]) + return AVERROR(ENOMEM); + } + } else { + s->temp = av_malloc_array((2 * reflink->w + 12), sizeof(*s->temp) * (1 + (desc->comp[0].depth > 8))); + if (!s->temp) + return AVERROR(ENOMEM); + + if (!s->density.value) { + ret = generate_density_map(s, reflink->w, reflink->h); + if (ret < 0) + return ret; + } + } + + ret = ff_framesync_init_dualinput(&s->fs, ctx); + if (ret < 0) + return ret; + + outlink->w = mainlink->w; + outlink->h = mainlink->h; + outlink->time_base = mainlink->time_base; + outlink->sample_aspect_ratio = mainlink->sample_aspect_ratio; + outlink->frame_rate = mainlink->frame_rate; + + s->fs.opt_shortest = 1; + s->fs.opt_repeatlast = 1; + + ret = ff_framesync_configure(&s->fs); + if (ret < 0) + return ret; + + return 0; +} + +static int activate(AVFilterContext *ctx) +{ + SSIM360Context *s = ctx->priv; + return ff_framesync_activate(&s->fs); +} + +static av_cold void uninit(AVFilterContext *ctx) +{ + SSIM360Context *s = ctx->priv; + + if (s->nb_ssim_frames > 0) { + char buf[256]; + buf[0] = 0; + // Log average SSIM360 values + for (int i = 0; i < s->nb_components; i++) { + int c = s->is_rgb ? s->rgba_map[i] : i; + av_strlcatf(buf, sizeof(buf), " %c:%f (%f)", s->comps[i], s->ssim360[c] / s->nb_ssim_frames, + ssim360_db(s->ssim360[c], s->nb_ssim_frames)); + } + av_log(ctx, AV_LOG_INFO, "SSIM360%s All:%f (%f)\n", buf, + s->ssim360_total / s->nb_ssim_frames, ssim360_db(s->ssim360_total, s->nb_ssim_frames)); + + // Log percentiles from histogram when using tape + if (s->use_tape) { + for (int p = 0; PERCENTILE_LIST[p] >= 0.0; p++) { + buf[0] = 0; + for (int i = 0; i < s->nb_components; i++) { + int c = s->is_rgb ? s->rgba_map[i] : i; + double ssim360p = s->ssim360_percentile_sum[i][p] / (double)(s->nb_ssim_frames); + av_strlcatf(buf, sizeof(buf), " %c:%f (%f)", s->comps[c], ssim360p, ssim360_db(ssim360p, 1)); + } + av_log(ctx, AV_LOG_INFO, "SSIM360_p%d%s\n", (int)(PERCENTILE_LIST[p] * 100.), buf); + } + } + } + + // free density map + map_uninit(&s->density); + + map_list_free(&s->heatmaps); + + for (int i = 0; i < s->nb_components; i++) { + for (int eye = 0; eye < 2; eye++) { + av_freep(&s->ref_tape_map[i][eye]); + av_freep(&s->main_tape_map[i][eye]); + } + av_freep(&s->ssim360_hist[i]); + } + + ff_framesync_uninit(&s->fs); + + if (s->stats_file && s->stats_file != stdout) + fclose(s->stats_file); + + av_freep(&s->temp); +} + +#define PF(suf) AV_PIX_FMT_YUV420##suf, AV_PIX_FMT_YUV422##suf, AV_PIX_FMT_YUV444##suf, AV_PIX_FMT_GBR##suf +static const enum AVPixelFormat ssim360_pixfmts[] = { + AV_PIX_FMT_GRAY8, + AV_PIX_FMT_YUV420P, AV_PIX_FMT_YUV422P, AV_PIX_FMT_YUV444P, + AV_PIX_FMT_YUV440P, AV_PIX_FMT_YUV411P, AV_PIX_FMT_YUV410P, + AV_PIX_FMT_YUVJ411P, AV_PIX_FMT_YUVJ420P, AV_PIX_FMT_YUVJ422P, + AV_PIX_FMT_YUVJ440P, AV_PIX_FMT_YUVJ444P, + AV_PIX_FMT_GBRP, + PF(P9), PF(P10), PF(P12), PF(P14), PF(P16), + AV_PIX_FMT_NONE +}; +#undef PF + +static const AVFilterPad ssim360_inputs[] = { + { + .name = "main", + .type = AVMEDIA_TYPE_VIDEO, + .config_props = config_input_main, + }, + { + .name = "reference", + .type = AVMEDIA_TYPE_VIDEO, + .config_props = config_input_ref, + }, +}; + +static const AVFilterPad ssim360_outputs[] = { + { + .name = "default", + .type = AVMEDIA_TYPE_VIDEO, + .config_props = config_output, + }, +}; + +AVFilter ff_vf_ssim360 = { + .name = "ssim360", + .description = NULL_IF_CONFIG_SMALL("Calculate the SSIM between two 360 video streams."), + .preinit = ssim360_framesync_preinit, + .init = init, + .uninit = uninit, + .activate = activate, + .priv_size = sizeof(SSIM360Context), + .priv_class = &ssim360_class, + .inputs = ssim360_inputs, + .outputs = ssim360_outputs, + FILTER_INPUTS(ssim360_inputs), + FILTER_OUTPUTS(ssim360_outputs), + FILTER_PIXFMTS_ARRAY(ssim360_pixfmts), +}; From c0cf2c47864bde4db155909e77436008654fef27 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Storsj=C3=B6?= Date: Sat, 28 Jan 2023 18:19:10 +0200 Subject: [PATCH 0087/2172] lavfi/vf_ssim360: Fix compilation with MSVC MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Don't use "static const" for compile time float constants, but use defines. This fixes the following error: src/libavfilter/vf_ssim360.c(549): error C2099: initializer is not a constant Signed-off-by: Martin Storsjö --- libavfilter/vf_ssim360.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/libavfilter/vf_ssim360.c b/libavfilter/vf_ssim360.c index 0990db0ed52..a0bf73da1eb 100644 --- a/libavfilter/vf_ssim360.c +++ b/libavfilter/vf_ssim360.c @@ -72,11 +72,11 @@ #define DEFAULT_EXPANSION_COEF 1.01f -static const float BARREL_THETA_RANGE = DEFAULT_EXPANSION_COEF * 2.0f * M_PI_F; -static const float BARREL_PHI_RANGE = DEFAULT_EXPANSION_COEF * M_PI_2_F; +#define BARREL_THETA_RANGE (DEFAULT_EXPANSION_COEF * 2.0f * M_PI_F) +#define BARREL_PHI_RANGE (DEFAULT_EXPANSION_COEF * M_PI_2_F) // Use fixed-point with 16 bit precision for fast bilinear math -static const int FIXED_POINT_PRECISION = 16; +#define FIXED_POINT_PRECISION 16 // Use 1MB per channel for the histogram to get 5-digit precise SSIM value #define SSIM360_HIST_SIZE 131072 From 54659e329e88083eeb5ce3caa328dbc9319a8372 Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt Date: Sat, 28 Jan 2023 18:01:25 +0100 Subject: [PATCH 0088/2172] avfilter/vf_ssim360: Fix left-shift of negative value Reviewed-by: Anton Khirnov Signed-off-by: Andreas Rheinhardt --- libavfilter/vf_ssim360.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavfilter/vf_ssim360.c b/libavfilter/vf_ssim360.c index a0bf73da1eb..89f51007401 100644 --- a/libavfilter/vf_ssim360.c +++ b/libavfilter/vf_ssim360.c @@ -547,7 +547,7 @@ static double ssim360_db(double ssim360, double weight) static int get_bilinear_sample(const uint8_t *data, BilinearMap *m, int max_value) { static const int fixed_point_half = 1 << (FIXED_POINT_PRECISION - 1); - static const int inv_byte_mask = (-1) << 8; + static const int inv_byte_mask = UINT_MAX << 8; int tl, tr, bl, br, v; From 5fd4d3faf1c28b3154110bf5e98401bf0328189d Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt Date: Sat, 28 Jan 2023 18:02:02 +0100 Subject: [PATCH 0089/2172] avfilter/vf_ssim360: Don't initialize twice The FILTER_INPUTS and FILTER_OUTPUTS macros already set AVFilter.(inputs|outputs); Clang therefore emits a warning for this: "initializer overrides prior initialization of this subobject [-Winitializer-overrides]" Reviewed-by: Anton Khirnov Signed-off-by: Andreas Rheinhardt --- libavfilter/vf_ssim360.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/libavfilter/vf_ssim360.c b/libavfilter/vf_ssim360.c index 89f51007401..35b0819d5fe 100644 --- a/libavfilter/vf_ssim360.c +++ b/libavfilter/vf_ssim360.c @@ -1760,8 +1760,6 @@ AVFilter ff_vf_ssim360 = { .activate = activate, .priv_size = sizeof(SSIM360Context), .priv_class = &ssim360_class, - .inputs = ssim360_inputs, - .outputs = ssim360_outputs, FILTER_INPUTS(ssim360_inputs), FILTER_OUTPUTS(ssim360_outputs), FILTER_PIXFMTS_ARRAY(ssim360_pixfmts), From 35f837710caf9cce3e098dbc2ae42f8b12b19828 Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt Date: Sat, 28 Jan 2023 18:04:09 +0100 Subject: [PATCH 0090/2172] avfilter/vf_ssim360: Constify AVFilter This brings ff_vf_ssim360 in line with its declaration in allfilters.c; this discrepancy is actually undefined behaviour. Reviewed-by: Anton Khirnov Signed-off-by: Andreas Rheinhardt --- libavfilter/vf_ssim360.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavfilter/vf_ssim360.c b/libavfilter/vf_ssim360.c index 35b0819d5fe..3eb8e43bbc8 100644 --- a/libavfilter/vf_ssim360.c +++ b/libavfilter/vf_ssim360.c @@ -1751,7 +1751,7 @@ static const AVFilterPad ssim360_outputs[] = { }, }; -AVFilter ff_vf_ssim360 = { +const AVFilter ff_vf_ssim360 = { .name = "ssim360", .description = NULL_IF_CONFIG_SMALL("Calculate the SSIM between two 360 video streams."), .preinit = ssim360_framesync_preinit, From b95b2c8492fc1b52afd8fbe67b3be3cd518485d6 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Sun, 22 Jan 2023 00:32:44 +0100 Subject: [PATCH 0091/2172] avcodec/utils: use 32pixel alignment for bink bink supports 16x16 blocks in chroma planes thus we need to allocate enough. Fixes: out of array access Fixes: 55026/clusterfuzz-testcase-minimized-ffmpeg_AV_CODEC_ID_BINK_fuzzer-6013915371012096 Reviewed-by: Peter Ross Found-by: continuous fuzzing process https://github.com/google/oss-fuzz/tree/master/projects/ffmpeg Signed-off-by: Michael Niedermayer --- libavcodec/utils.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/libavcodec/utils.c b/libavcodec/utils.c index 808a7b8f5b3..94f7ae6877c 100644 --- a/libavcodec/utils.c +++ b/libavcodec/utils.c @@ -243,6 +243,8 @@ void avcodec_align_dimensions2(AVCodecContext *s, int *width, int *height, case AV_PIX_FMT_GBRAP16BE: w_align = 16; //FIXME assume 16 pixel per macroblock h_align = 16 * 2; // interlaced needs 2 macroblocks height + if (s->codec_id == AV_CODEC_ID_BINKVIDEO) + w_align = 16*2; break; case AV_PIX_FMT_YUV411P: case AV_PIX_FMT_YUVJ411P: From 425b2c4a562878fb58d983f3e5c8b4efba77e40e Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Fri, 25 Nov 2022 14:00:48 +0100 Subject: [PATCH 0092/2172] fftools/ffmpeg: add options for writing encoding stats Similar to -vstats, but more flexible: - works for audio as well as video - frame and/or packet information - user-specifiable format --- Changelog | 1 + doc/ffmpeg.texi | 88 +++++++++++++++ fftools/ffmpeg.c | 63 ++++++++++- fftools/ffmpeg.h | 44 ++++++++ fftools/ffmpeg_mux.c | 8 ++ fftools/ffmpeg_mux_init.c | 224 ++++++++++++++++++++++++++++++++++++++ fftools/ffmpeg_opt.c | 9 ++ 7 files changed, 434 insertions(+), 3 deletions(-) diff --git a/Changelog b/Changelog index 57bf816105d..e07a039ca4e 100644 --- a/Changelog +++ b/Changelog @@ -32,6 +32,7 @@ version : - WADY DPCM decoder and demuxer - CBD2 DPCM decoder - ssim360 video filter +- ffmpeg CLI new options: -enc_stats_pre[_fmt], -enc_stats_post[_fmt] version 5.1: diff --git a/doc/ffmpeg.texi b/doc/ffmpeg.texi index 67b32942563..1c7e65479c3 100644 --- a/doc/ffmpeg.texi +++ b/doc/ffmpeg.texi @@ -2047,6 +2047,94 @@ 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. +@item -enc_stats_pre[:@var{stream_specifier}] @var{path} (@emph{output,per-stream}) +@item -enc_stats_post[:@var{stream_specifier}] @var{path} (@emph{output,per-stream}) +Write per-frame encoding information about the matching streams into the file +given by @var{path}. + +@option{-enc_stats_pre} writes information about raw video or audio frames right +before they are sent for encoding, while @option{-enc_stats_post} writes +information about encoded packets as they are received from the encoder. Every +frame or packet produces one line in the specified file. The format of this line +is controlled by @option{-enc_stats_pre_fmt} / @option{-enc_stats_post_fmt}. + +When stats for multiple streams are written into a single file, the lines +corresponding to different streams will be interleaved. The precise order of +this interleaving is not specified and not guaranteed to remain stable between +different invocations of the program, even with the same options. + +@item -enc_stats_pre_fmt[:@var{stream_specifier}] @var{format_spec} (@emph{output,per-stream}) +@item -enc_stats_post_fmt[:@var{stream_specifier}] @var{format_spec} (@emph{output,per-stream}) +Specify the format for the lines written with @option{-enc_stats_pre} / +@option{-enc_stats_post}. + +@var{format_spec} is a string that may contain directives of the form +@var{@{fmt@}}. @var{format_spec} is backslash-escaped --- use \@{, \@}, and \\ +to write a literal @{, @}, or \, respectively, into the output. + +The directives given with @var{fmt} may be one of the following: +@table @option +@item fidx +Index of the output file. + +@item sidx +Index of the output stream in the file. + +@item n +Frame number. Pre-encoding: number of frames sent to the encoder so far. +Post-encoding: number of packets received from the encoder so far. + +@item tb +Encoder timebase, as a rational number @var{num/den}. Note that this may be +different from the timebase used by the muxer. + +@item pts +Presentation timestamp of the frame or packet, as an integer. Should be +multiplied by the timebase to compute presentation time. + +@item t +Presentation time of the frame or packet, as a decimal number. Equal to +@var{pts} multiplied by @var{tb}. + +@item dts +Decoding timestamp of the packet, as an integer. Should be multiplied by the +timebase to compute presentation time. Post-encoding only. + +@item dt +Decoding time of the frame or packet, as a decimal number. Equal to +@var{dts} multiplied by @var{tb}. + +@item sn +Number of audio samples sent to the encoder so far. Audio and pre-encoding only. + +@item samp +Number of audio samples in the frame. Audio and pre-encoding only. + +@item size +Size of the encoded packet in bytes. Post-encoding only. + +@item br +Current bitrate in bits per second. Post-encoding only. + +@item abr +Average bitrate for the whole stream so far, in bits per second, -1 if it cannot +be determined at this point. Post-encoding only. +@end table + +The default format strings are: +@table @option +@item pre-encoding +@{fidx@} @{sidx@} @{n@} @{t@} +@item post-encoding +@{fidx@} @{sidx@} @{n@} @{t@} +@end table +In the future, new items may be added to the end of the default formatting +strings. Users who depend on the format staying exactly the same, should +prescribe it manually. + +Note that stats for different streams written into the same file may have +different formats. + @end table @section Preset files diff --git a/fftools/ffmpeg.c b/fftools/ffmpeg.c index f722ae76329..e4188c5fc85 100644 --- a/fftools/ffmpeg.c +++ b/fftools/ffmpeg.c @@ -554,6 +554,8 @@ static void ffmpeg_cleanup(int ret) av_err2str(AVERROR(errno))); } av_freep(&vstats_filename); + of_enc_stats_close(); + av_freep(&filter_nbthreads); av_freep(&input_files); @@ -798,6 +800,56 @@ static void update_video_stats(OutputStream *ost, const AVPacket *pkt, int write fprintf(vstats_file, "type= %c\n", av_get_picture_type_char(ost->pict_type)); } +static void enc_stats_write(OutputStream *ost, EncStats *es, + const AVFrame *frame, const AVPacket *pkt) +{ + AVIOContext *io = ost->enc_stats_pre.io; + AVRational tb = ost->enc_ctx->time_base; + int64_t pts = frame ? frame->pts : pkt->pts; + + for (size_t i = 0; i < es->nb_components; i++) { + const EncStatsComponent *c = &es->components[i]; + + switch (c->type) { + case ENC_STATS_LITERAL: avio_write (io, c->str, c->str_len); continue; + case ENC_STATS_FILE_IDX: avio_printf(io, "%d", ost->file_index); continue; + case ENC_STATS_STREAM_IDX: avio_printf(io, "%d", ost->index); continue; + case ENC_STATS_TIMEBASE: avio_printf(io, "%d/%d", tb.num, tb.den); continue; + case ENC_STATS_PTS: avio_printf(io, "%"PRId64, pts); continue; + case ENC_STATS_PTS_TIME: avio_printf(io, "%g", pts * av_q2d(tb)); continue; + } + + if (frame) { + switch (c->type) { + case ENC_STATS_FRAME_NUM: avio_printf(io, "%"PRIu64, ost->frames_encoded); continue; + case ENC_STATS_SAMPLE_NUM: avio_printf(io, "%"PRIu64, ost->samples_encoded); continue; + case ENC_STATS_NB_SAMPLES: avio_printf(io, "%d", frame->nb_samples); continue; + default: av_assert0(0); + } + } else { + switch (c->type) { + case ENC_STATS_DTS: avio_printf(io, "%"PRId64, pkt->dts); continue; + case ENC_STATS_DTS_TIME: avio_printf(io, "%g", pkt->dts * av_q2d(tb)); continue; + case ENC_STATS_PKT_SIZE: avio_printf(io, "%d", pkt->size); continue; + case ENC_STATS_FRAME_NUM: avio_printf(io, "%"PRIu64, ost->packets_encoded); continue; + case ENC_STATS_BITRATE: { + double duration = FFMAX(pkt->duration, 1) * av_q2d(tb); + avio_printf(io, "%g", 8.0 * pkt->size / duration); + continue; + } + case ENC_STATS_AVG_BITRATE: { + double duration = pkt->dts * av_q2d(tb); + avio_printf(io, "%g", duration > 0 ? 8.0 * ost->data_size_enc / duration : -1.); + continue; + } + default: av_assert0(0); + } + } + } + avio_w8(io, '\n'); + avio_flush(io); +} + static int encode_frame(OutputFile *of, OutputStream *ost, AVFrame *frame) { AVCodecContext *enc = ost->enc_ctx; @@ -807,6 +859,9 @@ static int encode_frame(OutputFile *of, OutputStream *ost, AVFrame *frame) int ret; if (frame) { + if (ost->enc_stats_pre.io) + enc_stats_write(ost, &ost->enc_stats_pre, frame, NULL); + ost->frames_encoded++; ost->samples_encoded += frame->nb_samples; @@ -848,6 +903,11 @@ static int encode_frame(OutputFile *of, OutputStream *ost, AVFrame *frame) return ret; } + if (enc->codec_type == AVMEDIA_TYPE_VIDEO) + update_video_stats(ost, pkt, !!vstats_filename); + if (ost->enc_stats_post.io) + enc_stats_write(ost, &ost->enc_stats_post, NULL, pkt); + if (debug_ts) { av_log(NULL, AV_LOG_INFO, "encoder -> type:%s " "pkt_pts:%s pkt_pts_time:%s pkt_dts:%s pkt_dts_time:%s " @@ -872,9 +932,6 @@ static int encode_frame(OutputFile *of, OutputStream *ost, AVFrame *frame) ost->data_size_enc += pkt->size; - if (enc->codec_type == AVMEDIA_TYPE_VIDEO) - update_video_stats(ost, pkt, !!vstats_filename); - ost->packets_encoded++; of_output_packet(of, pkt, ost, 0); diff --git a/fftools/ffmpeg.h b/fftools/ffmpeg.h index 5527dbe49b0..9bda1aa0a17 100644 --- a/fftools/ffmpeg.h +++ b/fftools/ffmpeg.h @@ -252,6 +252,14 @@ typedef struct OptionsContext { int nb_autoscale; SpecifierOpt *bits_per_raw_sample; int nb_bits_per_raw_sample; + SpecifierOpt *enc_stats_pre; + int nb_enc_stats_pre; + SpecifierOpt *enc_stats_post; + int nb_enc_stats_post; + SpecifierOpt *enc_stats_pre_fmt; + int nb_enc_stats_pre_fmt; + SpecifierOpt *enc_stats_post_fmt; + int nb_enc_stats_post_fmt; } OptionsContext; typedef struct InputFilter { @@ -480,6 +488,37 @@ enum forced_keyframes_const { #define ABORT_ON_FLAG_EMPTY_OUTPUT (1 << 0) #define ABORT_ON_FLAG_EMPTY_OUTPUT_STREAM (1 << 1) +enum EncStatsType { + ENC_STATS_LITERAL = 0, + ENC_STATS_FILE_IDX, + ENC_STATS_STREAM_IDX, + ENC_STATS_FRAME_NUM, + ENC_STATS_TIMEBASE, + ENC_STATS_PTS, + ENC_STATS_PTS_TIME, + ENC_STATS_DTS, + ENC_STATS_DTS_TIME, + ENC_STATS_SAMPLE_NUM, + ENC_STATS_NB_SAMPLES, + ENC_STATS_PKT_SIZE, + ENC_STATS_BITRATE, + ENC_STATS_AVG_BITRATE, +}; + +typedef struct EncStatsComponent { + enum EncStatsType type; + + uint8_t *str; + size_t str_len; +} EncStatsComponent; + +typedef struct EncStats { + EncStatsComponent *components; + int nb_components; + + AVIOContext *io; +} EncStats; + extern const char *const forced_keyframes_const_names[]; typedef enum { @@ -625,6 +664,9 @@ typedef struct OutputStream { int sq_idx_encode; int sq_idx_mux; + + EncStats enc_stats_pre; + EncStats enc_stats_post; } OutputStream; typedef struct OutputFile { @@ -749,6 +791,8 @@ int of_write_trailer(OutputFile *of); int of_open(const OptionsContext *o, const char *filename); void of_close(OutputFile **pof); +void of_enc_stats_close(void); + /* * Send a single packet to the output, applying any bitstream filters * associated with the output stream. This may result in any number diff --git a/fftools/ffmpeg_mux.c b/fftools/ffmpeg_mux.c index 20524e5a282..1c85bb697d0 100644 --- a/fftools/ffmpeg_mux.c +++ b/fftools/ffmpeg_mux.c @@ -686,6 +686,14 @@ static void ost_free(OutputStream **post) av_freep(&ost->enc_ctx->stats_in); avcodec_free_context(&ost->enc_ctx); + for (int i = 0; i < ost->enc_stats_pre.nb_components; i++) + av_freep(&ost->enc_stats_pre.components[i].str); + av_freep(&ost->enc_stats_pre.components); + + for (int i = 0; i < ost->enc_stats_post.nb_components; i++) + av_freep(&ost->enc_stats_post.components[i].str); + av_freep(&ost->enc_stats_post.components); + av_freep(post); } diff --git a/fftools/ffmpeg_mux_init.c b/fftools/ffmpeg_mux_init.c index 9eea8639dcf..85258c7f270 100644 --- a/fftools/ffmpeg_mux_init.c +++ b/fftools/ffmpeg_mux_init.c @@ -55,6 +55,10 @@ static const char *const opt_name_copy_initial_nonkeyframes[] = {"copyinkf", NUL static const char *const opt_name_copy_prior_start[] = {"copypriorss", NULL}; static const char *const opt_name_disposition[] = {"disposition", NULL}; static const char *const opt_name_enc_time_bases[] = {"enc_time_base", NULL}; +static const char *const opt_name_enc_stats_pre[] = {"enc_stats_pre", NULL}; +static const char *const opt_name_enc_stats_post[] = {"enc_stats_post", NULL}; +static const char *const opt_name_enc_stats_pre_fmt[] = {"enc_stats_pre_fmt", NULL}; +static const char *const opt_name_enc_stats_post_fmt[] = {"enc_stats_post_fmt", NULL}; static const char *const opt_name_filters[] = {"filter", "af", "vf", NULL}; static const char *const opt_name_filter_scripts[] = {"filter_script", NULL}; static const char *const opt_name_fps_mode[] = {"fps_mode", NULL}; @@ -170,6 +174,201 @@ static int get_preset_file_2(const char *preset_name, const char *codec_name, AV return ret; } +typedef struct EncStatsFile { + char *path; + AVIOContext *io; +} EncStatsFile; + +static EncStatsFile *enc_stats_files; +static int nb_enc_stats_files; + +static int enc_stats_get_file(AVIOContext **io, const char *path) +{ + EncStatsFile *esf; + int ret; + + for (int i = 0; i < nb_enc_stats_files; i++) + if (!strcmp(path, enc_stats_files[i].path)) { + *io = enc_stats_files[i].io; + return 0; + } + + GROW_ARRAY(enc_stats_files, nb_enc_stats_files); + + esf = &enc_stats_files[nb_enc_stats_files - 1]; + + ret = avio_open2(&esf->io, path, AVIO_FLAG_WRITE, &int_cb, NULL); + if (ret < 0) { + av_log(NULL, AV_LOG_ERROR, "Error opening stats file '%s': %s\n", + path, av_err2str(ret)); + return ret; + } + + esf->path = av_strdup(path); + if (!esf->path) + return AVERROR(ENOMEM); + + *io = esf->io; + + return 0; +} + +void of_enc_stats_close(void) +{ + for (int i = 0; i < nb_enc_stats_files; i++) { + av_freep(&enc_stats_files[i].path); + avio_closep(&enc_stats_files[i].io); + } + av_freep(&enc_stats_files); + nb_enc_stats_files = 0; +} + +static int unescape(char **pdst, size_t *dst_len, + const char **pstr, char delim) +{ + const char *str = *pstr; + char *dst; + size_t len, idx; + + *pdst = NULL; + + len = strlen(str); + if (!len) + return 0; + + dst = av_malloc(len + 1); + if (!dst) + return AVERROR(ENOMEM); + + for (idx = 0; *str; idx++, str++) { + if (str[0] == '\\' && str[1]) + str++; + else if (*str == delim) + break; + + dst[idx] = *str; + } + if (!idx) { + av_freep(&dst); + return 0; + } + + dst[idx] = 0; + + *pdst = dst; + *dst_len = idx; + *pstr = str; + + return 0; +} + +static int enc_stats_init(OutputStream *ost, int pre, + const char *path, const char *fmt_spec) +{ + static const struct { + enum EncStatsType type; + const char *str; + int pre_only:1; + int post_only:1; + } fmt_specs[] = { + { ENC_STATS_FILE_IDX, "fidx" }, + { ENC_STATS_STREAM_IDX, "sidx" }, + { ENC_STATS_FRAME_NUM, "n" }, + { ENC_STATS_TIMEBASE, "tb" }, + { ENC_STATS_PTS, "pts" }, + { ENC_STATS_PTS_TIME, "t" }, + { ENC_STATS_DTS, "dts", 0, 1 }, + { ENC_STATS_DTS_TIME, "dt", 0, 1 }, + { ENC_STATS_SAMPLE_NUM, "sn", 1 }, + { ENC_STATS_NB_SAMPLES, "samp", 1 }, + { ENC_STATS_PKT_SIZE, "size", 0, 1 }, + { ENC_STATS_BITRATE, "br", 0, 1 }, + { ENC_STATS_AVG_BITRATE, "abr", 0, 1 }, + }; + EncStats *es = pre ? &ost->enc_stats_pre : &ost->enc_stats_post; + const char *next = fmt_spec; + + int ret; + + while (*next) { + EncStatsComponent *c; + char *val; + size_t val_len; + + // get the sequence up until next opening brace + ret = unescape(&val, &val_len, &next, '{'); + if (ret < 0) + return ret; + + if (val) { + GROW_ARRAY(es->components, es->nb_components); + + c = &es->components[es->nb_components - 1]; + c->type = ENC_STATS_LITERAL; + c->str = val; + c->str_len = val_len; + } + + if (!*next) + break; + next++; + + // get the part inside braces + ret = unescape(&val, &val_len, &next, '}'); + if (ret < 0) + return ret; + + if (!val) { + av_log(NULL, AV_LOG_ERROR, + "Empty formatting directive in: %s\n", fmt_spec); + return AVERROR(EINVAL); + } + + if (!*next) { + av_log(NULL, AV_LOG_ERROR, + "Missing closing brace in: %s\n", fmt_spec); + ret = AVERROR(EINVAL); + goto fail; + } + next++; + + GROW_ARRAY(es->components, es->nb_components); + c = &es->components[es->nb_components - 1]; + + for (size_t i = 0; i < FF_ARRAY_ELEMS(fmt_specs); i++) { + if (!strcmp(val, fmt_specs[i].str)) { + if ((pre && fmt_specs[i].post_only) || (!pre && fmt_specs[i].pre_only)) { + av_log(NULL, AV_LOG_ERROR, + "Format directive '%s' may only be used %s-encoding\n", + val, pre ? "post" : "pre"); + ret = AVERROR(EINVAL); + goto fail; + } + + c->type = fmt_specs[i].type; + break; + } + } + + if (!c->type) { + av_log(NULL, AV_LOG_ERROR, "Invalid format directive: %s\n", val); + ret = AVERROR(EINVAL); + goto fail; + } + +fail: + av_freep(&val); + if (ret < 0) + return ret; + } + + ret = enc_stats_get_file(&es->io, path); + if (ret < 0) + return ret; + + return 0; +} + static OutputStream *new_output_stream(Muxer *mux, const OptionsContext *o, enum AVMediaType type, InputStream *ist) { @@ -230,6 +429,7 @@ static OutputStream *new_output_stream(Muxer *mux, const OptionsContext *o, AVCodecContext *enc = ost->enc_ctx; AVIOContext *s = NULL; char *buf = NULL, *arg = NULL, *preset = NULL; + const char *enc_stats_pre = NULL, *enc_stats_post = NULL; ost->encoder_opts = filter_codec_opts(o->g->codec_opts, enc->codec_id, oc, st, enc->codec); @@ -261,6 +461,30 @@ static OutputStream *new_output_stream(Muxer *mux, const OptionsContext *o, preset, ost->file_index, ost->index); exit_program(1); } + + MATCH_PER_STREAM_OPT(enc_stats_pre, str, enc_stats_pre, oc, st); + if (enc_stats_pre && + (type == AVMEDIA_TYPE_VIDEO || type == AVMEDIA_TYPE_AUDIO)) { + const char *format = "{fidx} {sidx} {n} {t}"; + + MATCH_PER_STREAM_OPT(enc_stats_pre_fmt, str, format, oc, st); + + ret = enc_stats_init(ost, 1, enc_stats_pre, format); + if (ret < 0) + exit_program(1); + } + + MATCH_PER_STREAM_OPT(enc_stats_post, str, enc_stats_post, oc, st); + if (enc_stats_post && + (type == AVMEDIA_TYPE_VIDEO || type == AVMEDIA_TYPE_AUDIO)) { + const char *format = "{fidx} {sidx} {n} {t}"; + + MATCH_PER_STREAM_OPT(enc_stats_post_fmt, str, format, oc, st); + + ret = enc_stats_init(ost, 0, enc_stats_post, format); + if (ret < 0) + exit_program(1); + } } else { ost->encoder_opts = filter_codec_opts(o->g->codec_opts, AV_CODEC_ID_NONE, oc, st, NULL); } diff --git a/fftools/ffmpeg_opt.c b/fftools/ffmpeg_opt.c index 3df02b7d7fa..c81c991d5e7 100644 --- a/fftools/ffmpeg_opt.c +++ b/fftools/ffmpeg_opt.c @@ -1543,6 +1543,15 @@ const OptionDef options[] = { { .off = OFFSET(bits_per_raw_sample) }, "set the number of bits per raw sample", "number" }, + { "enc_stats_pre", HAS_ARG | OPT_SPEC | OPT_EXPERT | OPT_OUTPUT | OPT_STRING, { .off = OFFSET(enc_stats_pre) }, + "write encoding stats before encoding" }, + { "enc_stats_post", HAS_ARG | OPT_SPEC | OPT_EXPERT | OPT_OUTPUT | OPT_STRING, { .off = OFFSET(enc_stats_post) }, + "write encoding stats after encoding" }, + { "enc_stats_pre_fmt", HAS_ARG | OPT_SPEC | OPT_EXPERT | OPT_OUTPUT | OPT_STRING, { .off = OFFSET(enc_stats_pre_fmt) }, + "format of the stats written with -enc_stats_pre" }, + { "enc_stats_post_fmt", HAS_ARG | OPT_SPEC | OPT_EXPERT | OPT_OUTPUT | OPT_STRING, { .off = OFFSET(enc_stats_post_fmt) }, + "format of the stats written with -enc_stats_post" }, + /* video options */ { "vframes", OPT_VIDEO | HAS_ARG | OPT_PERFILE | OPT_OUTPUT, { .func_arg = opt_video_frames }, "set the number of video frames to output", "number" }, From d2c983c213b824fe70a13db1b16c3ced4296ae6f Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Sat, 28 Jan 2023 10:06:20 +0100 Subject: [PATCH 0093/2172] fftools/ffmpeg: add an AVClass to Muxer/OutputFile Use it for logging. This makes log messages related to this output file more consistent. --- fftools/ffmpeg.h | 2 + fftools/ffmpeg_mux.c | 26 +++----- fftools/ffmpeg_mux.h | 3 + fftools/ffmpeg_mux_init.c | 133 +++++++++++++++++++++++--------------- 4 files changed, 96 insertions(+), 68 deletions(-) diff --git a/fftools/ffmpeg.h b/fftools/ffmpeg.h index 9bda1aa0a17..1a235f205f2 100644 --- a/fftools/ffmpeg.h +++ b/fftools/ffmpeg.h @@ -670,6 +670,8 @@ typedef struct OutputStream { } OutputStream; typedef struct OutputFile { + const AVClass *class; + int index; const AVOutputFormat *format; diff --git a/fftools/ffmpeg_mux.c b/fftools/ffmpeg_mux.c index 1c85bb697d0..91be316e0ac 100644 --- a/fftools/ffmpeg_mux.c +++ b/fftools/ffmpeg_mux.c @@ -207,8 +207,7 @@ static void *muxer_thread(void *arg) ret = tq_receive(mux->tq, &stream_idx, pkt); if (stream_idx < 0) { - av_log(NULL, AV_LOG_VERBOSE, - "All streams finished for output file #%d\n", of->index); + av_log(mux, AV_LOG_VERBOSE, "All streams finished\n"); ret = 0; break; } @@ -219,8 +218,7 @@ static void *muxer_thread(void *arg) if (ret == AVERROR_EOF) tq_receive_finish(mux->tq, stream_idx); else if (ret < 0) { - av_log(NULL, AV_LOG_ERROR, - "Error muxing a packet for output file #%d\n", of->index); + av_log(mux, AV_LOG_ERROR, "Error muxing a packet\n"); break; } } @@ -231,7 +229,7 @@ static void *muxer_thread(void *arg) for (unsigned int i = 0; i < mux->fc->nb_streams; i++) tq_receive_finish(mux->tq, i); - av_log(NULL, AV_LOG_VERBOSE, "Terminating muxer thread %d\n", of->index); + av_log(mux, AV_LOG_VERBOSE, "Terminating muxer thread\n"); return (void*)(intptr_t)ret; } @@ -511,10 +509,8 @@ int mux_check_init(Muxer *mux) ret = avformat_write_header(fc, &mux->opts); if (ret < 0) { - av_log(NULL, AV_LOG_ERROR, - "Could not write header for output file #%d " - "(incorrect codec parameters ?): %s\n", - of->index, av_err2str(ret)); + av_log(mux, AV_LOG_ERROR, "Could not write header (incorrect codec " + "parameters ?): %s\n", av_err2str(ret)); return ret; } //assert_avoptions(of->opts); @@ -604,10 +600,9 @@ int of_write_trailer(OutputFile *of) int ret; if (!mux->tq) { - av_log(NULL, AV_LOG_ERROR, - "Nothing was written into output file %d (%s), because " - "at least one of its streams received no packets.\n", - of->index, fc->url); + av_log(mux, AV_LOG_ERROR, + "Nothing was written into output file, because " + "at least one of its streams received no packets.\n"); return AVERROR(EINVAL); } @@ -617,7 +612,7 @@ int of_write_trailer(OutputFile *of) ret = av_write_trailer(fc); if (ret < 0) { - av_log(NULL, AV_LOG_ERROR, "Error writing trailer of %s: %s\n", fc->url, av_err2str(ret)); + av_log(mux, AV_LOG_ERROR, "Error writing trailer: %s\n", av_err2str(ret)); return ret; } @@ -626,8 +621,7 @@ int of_write_trailer(OutputFile *of) if (!(of->format->flags & AVFMT_NOFILE)) { ret = avio_closep(&fc->pb); if (ret < 0) { - av_log(NULL, AV_LOG_ERROR, "Error closing file %s: %s\n", - fc->url, av_err2str(ret)); + av_log(mux, AV_LOG_ERROR, "Error closing file: %s\n", av_err2str(ret)); return ret; } } diff --git a/fftools/ffmpeg_mux.h b/fftools/ffmpeg_mux.h index 6a72b9dc910..8a90cc56c61 100644 --- a/fftools/ffmpeg_mux.h +++ b/fftools/ffmpeg_mux.h @@ -63,6 +63,9 @@ typedef struct MuxStream { typedef struct Muxer { OutputFile of; + // name used for logging + char log_name[32]; + AVFormatContext *fc; pthread_t thread; diff --git a/fftools/ffmpeg_mux_init.c b/fftools/ffmpeg_mux_init.c index 85258c7f270..d0743181999 100644 --- a/fftools/ffmpeg_mux_init.c +++ b/fftools/ffmpeg_mux_init.c @@ -1042,7 +1042,7 @@ static void init_output_filter(OutputFilter *ofilter, const OptionsContext *o, case AVMEDIA_TYPE_VIDEO: ost = new_video_stream(mux, o, NULL); break; case AVMEDIA_TYPE_AUDIO: ost = new_audio_stream(mux, o, NULL); break; default: - av_log(NULL, AV_LOG_FATAL, "Only video and audio filters are supported " + av_log(mux, AV_LOG_FATAL, "Only video and audio filters are supported " "currently.\n"); exit_program(1); } @@ -1247,7 +1247,7 @@ static void map_manual(Muxer *mux, const OptionsContext *o, const StreamMap *map } loop_end: if (!ofilter) { - av_log(NULL, AV_LOG_FATAL, "Output with label '%s' does not exist " + av_log(mux, AV_LOG_FATAL, "Output with label '%s' does not exist " "in any defined filter graph, or was already used elsewhere.\n", map->linklabel); exit_program(1); } @@ -1255,7 +1255,7 @@ static void map_manual(Muxer *mux, const OptionsContext *o, const StreamMap *map } else { ist = input_files[map->file_index]->streams[map->stream_index]; if (ist->user_set_discard == AVDISCARD_ALL) { - av_log(NULL, AV_LOG_FATAL, "Stream #%d:%d is disabled and cannot be mapped.\n", + av_log(mux, AV_LOG_FATAL, "Stream #%d:%d is disabled and cannot be mapped.\n", map->file_index, map->stream_index); exit_program(1); } @@ -1280,11 +1280,11 @@ static void map_manual(Muxer *mux, const OptionsContext *o, const StreamMap *map break; } default: - av_log(NULL, ignore_unknown_streams ? AV_LOG_WARNING : AV_LOG_FATAL, + av_log(mux, ignore_unknown_streams ? AV_LOG_WARNING : AV_LOG_FATAL, "Cannot map stream #%d:%d - unsupported type.\n", map->file_index, map->stream_index); if (!ignore_unknown_streams) { - av_log(NULL, AV_LOG_FATAL, + av_log(mux, AV_LOG_FATAL, "If you want unsupported types ignored instead " "of failing, please use the -ignore_unknown option\n" "If you want them copied, please use -copy_unknown\n"); @@ -1306,18 +1306,18 @@ static void of_add_attachments(Muxer *mux, const OptionsContext *o) int64_t len; if ((err = avio_open2(&pb, o->attachments[i], AVIO_FLAG_READ, &int_cb, NULL)) < 0) { - av_log(NULL, AV_LOG_FATAL, "Could not open attachment file %s.\n", + av_log(mux, AV_LOG_FATAL, "Could not open attachment file %s.\n", o->attachments[i]); exit_program(1); } if ((len = avio_size(pb)) <= 0) { - av_log(NULL, AV_LOG_FATAL, "Could not get size of the attachment %s.\n", + av_log(mux, AV_LOG_FATAL, "Could not get size of the attachment %s.\n", o->attachments[i]); exit_program(1); } if (len > INT_MAX - AV_INPUT_BUFFER_PADDING_SIZE || !(attachment = av_malloc(len + AV_INPUT_BUFFER_PADDING_SIZE))) { - av_log(NULL, AV_LOG_FATAL, "Attachment %s too large.\n", + av_log(mux, AV_LOG_FATAL, "Attachment %s too large.\n", o->attachments[i]); exit_program(1); } @@ -1380,7 +1380,7 @@ static void create_streams(Muxer *mux, const OptionsContext *o) if (!oc->nb_streams && !(oc->oformat->flags & AVFMT_NOSTREAMS)) { av_dump_format(oc, nb_output_files - 1, oc->url, 1); - av_log(NULL, AV_LOG_ERROR, "Output file #%d does not contain any stream\n", nb_output_files - 1); + av_log(mux, AV_LOG_ERROR, "Output file does not contain any stream\n"); exit_program(1); } } @@ -1479,8 +1479,9 @@ static int setup_sync_queues(Muxer *mux, AVFormatContext *oc, int64_t buf_size_u return 0; } -static void of_add_programs(AVFormatContext *oc, const OptionsContext *o) +static void of_add_programs(Muxer *mux, const OptionsContext *o) { + AVFormatContext *oc = mux->fc; /* process manually set programs */ for (int i = 0; i < o->nb_program; i++) { const char *p = o->program[i].u.str; @@ -1525,7 +1526,7 @@ static void of_add_programs(AVFormatContext *oc, const OptionsContext *o) key = av_get_token(&p2, "="); if (!key) { - av_log(NULL, AV_LOG_FATAL, + av_log(mux, AV_LOG_FATAL, "No '=' character in program string %s.\n", p2); exit_program(1); @@ -1541,7 +1542,7 @@ static void of_add_programs(AVFormatContext *oc, const OptionsContext *o) int st_num = strtol(p2, NULL, 0); av_program_add_stream_index(oc, progid, st_num); } else { - av_log(NULL, AV_LOG_FATAL, "Unknown program key %s.\n", key); + av_log(mux, AV_LOG_FATAL, "Unknown program key %s.\n", key); exit_program(1); } av_freep(&to_dealloc); @@ -1557,7 +1558,8 @@ static void of_add_programs(AVFormatContext *oc, const OptionsContext *o) * @param index for type c/p, chapter/program index is written here * @param stream_spec for type s, the stream specifier is written here */ -static void parse_meta_type(const char *arg, char *type, int *index, const char **stream_spec) +static void parse_meta_type(void *logctx, const char *arg, + char *type, int *index, const char **stream_spec) { if (*arg) { *type = *arg; @@ -1566,7 +1568,7 @@ static void parse_meta_type(const char *arg, char *type, int *index, const char break; case 's': if (*(++arg) && *arg != ':') { - av_log(NULL, AV_LOG_FATAL, "Invalid metadata specifier %s.\n", arg); + av_log(logctx, AV_LOG_FATAL, "Invalid metadata specifier %s.\n", arg); exit_program(1); } *stream_spec = *arg == ':' ? arg + 1 : ""; @@ -1577,7 +1579,7 @@ static void parse_meta_type(const char *arg, char *type, int *index, const char *index = strtol(++arg, NULL, 0); break; default: - av_log(NULL, AV_LOG_FATAL, "Invalid metadata type %c.\n", *arg); + av_log(logctx, AV_LOG_FATAL, "Invalid metadata type %c.\n", *arg); exit_program(1); } } else @@ -1595,13 +1597,13 @@ static void of_add_metadata(OutputFile *of, AVFormatContext *oc, val = strchr(o->metadata[i].u.str, '='); if (!val) { - av_log(NULL, AV_LOG_FATAL, "No '=' character in metadata string %s.\n", + av_log(of, AV_LOG_FATAL, "No '=' character in metadata string %s.\n", o->metadata[i].u.str); exit_program(1); } *val++ = 0; - parse_meta_type(o->metadata[i].specifier, &type, &index, &stream_spec); + parse_meta_type(of, o->metadata[i].specifier, &type, &index, &stream_spec); if (type == 's') { for (int j = 0; j < oc->nb_streams; j++) { OutputStream *ost = of->streams[j]; @@ -1636,20 +1638,20 @@ static void of_add_metadata(OutputFile *of, AVFormatContext *oc, break; case 'c': if (index < 0 || index >= oc->nb_chapters) { - av_log(NULL, AV_LOG_FATAL, "Invalid chapter index %d in metadata specifier.\n", index); + av_log(of, AV_LOG_FATAL, "Invalid chapter index %d in metadata specifier.\n", index); exit_program(1); } m = &oc->chapters[index]->metadata; break; case 'p': if (index < 0 || index >= oc->nb_programs) { - av_log(NULL, AV_LOG_FATAL, "Invalid program index %d in metadata specifier.\n", index); + av_log(of, AV_LOG_FATAL, "Invalid program index %d in metadata specifier.\n", index); exit_program(1); } m = &oc->programs[index]->metadata; break; default: - av_log(NULL, AV_LOG_FATAL, "Invalid metadata specifier %s.\n", o->metadata[i].specifier); + av_log(of, AV_LOG_FATAL, "Invalid metadata specifier %s.\n", o->metadata[i].specifier); exit_program(1); } av_dict_set(m, o->metadata[i].u.str, *val ? val : NULL, 0); @@ -1738,11 +1740,12 @@ static int copy_chapters(InputFile *ifile, OutputFile *ofile, AVFormatContext *o return 0; } -static int copy_metadata(const char *outspec, const char *inspec, - AVFormatContext *oc, AVFormatContext *ic, +static int copy_metadata(Muxer *mux, AVFormatContext *ic, + const char *outspec, const char *inspec, int *metadata_global_manual, int *metadata_streams_manual, int *metadata_chapters_manual, const OptionsContext *o) { + AVFormatContext *oc = mux->fc; AVDictionary **meta_in = NULL; AVDictionary **meta_out = NULL; int i, ret = 0; @@ -1750,8 +1753,8 @@ static int copy_metadata(const char *outspec, const char *inspec, const char *istream_spec = NULL, *ostream_spec = NULL; int idx_in = 0, idx_out = 0; - parse_meta_type(inspec, &type_in, &idx_in, &istream_spec); - parse_meta_type(outspec, &type_out, &idx_out, &ostream_spec); + parse_meta_type(mux, inspec, &type_in, &idx_in, &istream_spec); + parse_meta_type(mux, outspec, &type_out, &idx_out, &ostream_spec); if (type_in == 'g' || type_out == 'g') *metadata_global_manual = 1; @@ -1766,7 +1769,7 @@ static int copy_metadata(const char *outspec, const char *inspec, #define METADATA_CHECK_INDEX(index, nb_elems, desc)\ if ((index) < 0 || (index) >= (nb_elems)) {\ - av_log(NULL, AV_LOG_FATAL, "Invalid %s index %d while processing metadata maps.\n",\ + av_log(mux, AV_LOG_FATAL, "Invalid %s index %d while processing metadata maps.\n",\ (desc), (index));\ exit_program(1);\ } @@ -1802,7 +1805,7 @@ static int copy_metadata(const char *outspec, const char *inspec, exit_program(1); } if (!meta_in) { - av_log(NULL, AV_LOG_FATAL, "Stream specifier %s does not match any streams.\n", istream_spec); + av_log(mux, AV_LOG_FATAL, "Stream specifier %s does not match any streams.\n", istream_spec); exit_program(1); } } @@ -1836,12 +1839,13 @@ static void copy_meta(Muxer *mux, const OptionsContext *o) int in_file_index = strtol(o->metadata_map[i].u.str, &p, 0); if (in_file_index >= nb_input_files) { - av_log(NULL, AV_LOG_FATAL, "Invalid input file index %d while processing metadata maps\n", in_file_index); + av_log(mux, AV_LOG_FATAL, "Invalid input file index %d while " + "processing metadata maps\n", in_file_index); exit_program(1); } - copy_metadata(o->metadata_map[i].specifier, *p ? p + 1 : p, oc, - in_file_index >= 0 ? - input_files[in_file_index]->ctx : NULL, + copy_metadata(mux, + in_file_index >= 0 ? input_files[in_file_index]->ctx : NULL, + o->metadata_map[i].specifier, *p ? p + 1 : p, &metadata_global_manual, &metadata_streams_manual, &metadata_chapters_manual, o); } @@ -1857,7 +1861,7 @@ static void copy_meta(Muxer *mux, const OptionsContext *o) break; } } else { - av_log(NULL, AV_LOG_FATAL, "Invalid input file index %d in chapter mapping.\n", + av_log(mux, AV_LOG_FATAL, "Invalid input file index %d in chapter mapping.\n", chapters_input_file); exit_program(1); } @@ -2078,7 +2082,7 @@ static int process_forced_keyframes(Muxer *mux, const OptionsContext *o) return 0; } -static void validate_enc_avopt(const Muxer *mux, const AVDictionary *codec_avopt) +static void validate_enc_avopt(Muxer *mux, const AVDictionary *codec_avopt) { const AVClass *class = avcodec_get_class(); const AVClass *fclass = avformat_get_class(); @@ -2104,10 +2108,8 @@ static void validate_enc_avopt(const Muxer *mux, const AVDictionary *codec_avopt continue; if (!(option->flags & AV_OPT_FLAG_ENCODING_PARAM)) { - av_log(NULL, AV_LOG_ERROR, "Codec AVOption %s (%s) specified for " - "output file #%d (%s) is not an encoding option.\n", e->key, - option->help ? option->help : "", nb_output_files - 1, - mux->fc->url); + av_log(mux, AV_LOG_ERROR, "Codec AVOption %s (%s) is not an " + "encoding option.\n", e->key, option->help ? option->help : ""); exit_program(1); } @@ -2115,16 +2117,41 @@ static void validate_enc_avopt(const Muxer *mux, const AVDictionary *codec_avopt if (!strcmp(e->key, "gop_timecode")) continue; - av_log(NULL, AV_LOG_WARNING, "Codec AVOption %s (%s) specified for " - "output file #%d (%s) has not been used for any stream. The most " - "likely reason is either wrong type (e.g. a video option with " - "no video streams) or that it is a private option of some encoder " - "which was not actually used for any stream.\n", e->key, - option->help ? option->help : "", nb_output_files - 1, mux->fc->url); + av_log(mux, AV_LOG_WARNING, "Codec AVOption %s (%s) has not been used " + "for any stream. The most likely reason is either wrong type " + "(e.g. a video option with no video streams) or that it is a " + "private option of some encoder which was not actually used for " + "any stream.\n", e->key, option->help ? option->help : ""); } av_dict_free(&unused_opts); } +static const char *output_file_item_name(void *obj) +{ + const Muxer *mux = obj; + + return mux->log_name; +} + +static const AVClass output_file_class = { + .class_name = "OutputFile", + .version = LIBAVUTIL_VERSION_INT, + .item_name = output_file_item_name, + .category = AV_CLASS_CATEGORY_MUXER, +}; + +static Muxer *mux_alloc(void) +{ + Muxer *mux = allocate_array_elem(&output_files, sizeof(*mux), &nb_output_files); + + mux->of.class = &output_file_class; + mux->of.index = nb_output_files - 1; + + snprintf(mux->log_name, sizeof(mux->log_name), "out#%d", mux->of.index); + + return mux; +} + int of_open(const OptionsContext *o, const char *filename) { Muxer *mux; @@ -2135,25 +2162,24 @@ int of_open(const OptionsContext *o, const char *filename) int64_t recording_time = o->recording_time; int64_t stop_time = o->stop_time; + mux = mux_alloc(); + of = &mux->of; + if (stop_time != INT64_MAX && recording_time != INT64_MAX) { stop_time = INT64_MAX; - av_log(NULL, AV_LOG_WARNING, "-t and -to cannot be used together; using -t.\n"); + av_log(mux, AV_LOG_WARNING, "-t and -to cannot be used together; using -t.\n"); } if (stop_time != INT64_MAX && recording_time == INT64_MAX) { int64_t start_time = o->start_time == AV_NOPTS_VALUE ? 0 : o->start_time; if (stop_time <= start_time) { - av_log(NULL, AV_LOG_ERROR, "-to value smaller than -ss; aborting.\n"); + av_log(mux, AV_LOG_ERROR, "-to value smaller than -ss; aborting.\n"); exit_program(1); } else { recording_time = stop_time - start_time; } } - mux = allocate_array_elem(&output_files, sizeof(Muxer), &nb_output_files); - of = &mux->of; - - of->index = nb_output_files - 1; of->recording_time = recording_time; of->start_time = o->start_time; of->shortest = o->shortest; @@ -2172,6 +2198,9 @@ int of_open(const OptionsContext *o, const char *filename) } mux->fc = oc; + av_strlcat(mux->log_name, "/", sizeof(mux->log_name)); + av_strlcat(mux->log_name, oc->oformat->name, sizeof(mux->log_name)); + if (strcmp(oc->oformat->name, "rtp")) want_sdp = 0; @@ -2285,12 +2314,12 @@ int of_open(const OptionsContext *o, const char *filename) /* copy metadata and chapters from input files */ copy_meta(mux, o); - of_add_programs(oc, o); + of_add_programs(mux, o); of_add_metadata(of, oc, o); err = set_dispositions(mux, o); if (err < 0) { - av_log(NULL, AV_LOG_FATAL, "Error setting output stream dispositions\n"); + av_log(mux, AV_LOG_FATAL, "Error setting output stream dispositions\n"); exit_program(1); } @@ -2298,13 +2327,13 @@ int of_open(const OptionsContext *o, const char *filename) // must be done after chapters are created err = process_forced_keyframes(mux, o); if (err < 0) { - av_log(NULL, AV_LOG_FATAL, "Error processing forced keyframes\n"); + av_log(mux, AV_LOG_FATAL, "Error processing forced keyframes\n"); exit_program(1); } err = setup_sync_queues(mux, oc, o->shortest_buf_duration * AV_TIME_BASE); if (err < 0) { - av_log(NULL, AV_LOG_FATAL, "Error setting up output sync queues\n"); + av_log(mux, AV_LOG_FATAL, "Error setting up output sync queues\n"); exit_program(1); } From 9b5036fabd41c93cbd623a12893511761827ae98 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Sat, 28 Jan 2023 10:06:20 +0100 Subject: [PATCH 0094/2172] fftools/ffmpeg: add an AVClass to MuxStream/OutputStream Use it for logging. This makes log messages related to this output stream more consistent. --- fftools/ffmpeg.c | 95 ++++++++++++------------ fftools/ffmpeg.h | 5 +- fftools/ffmpeg_demux.c | 10 +-- fftools/ffmpeg_mux.c | 13 ++-- fftools/ffmpeg_mux.h | 3 + fftools/ffmpeg_mux_init.c | 149 ++++++++++++++++++++++---------------- fftools/ffmpeg_opt.c | 9 ++- 7 files changed, 157 insertions(+), 127 deletions(-) diff --git a/fftools/ffmpeg.c b/fftools/ffmpeg.c index e4188c5fc85..9884e0c6c67 100644 --- a/fftools/ffmpeg.c +++ b/fftools/ffmpeg.c @@ -730,8 +730,8 @@ static int init_output_stream_wrapper(OutputStream *ost, AVFrame *frame, ret = init_output_stream(ost, frame, error, sizeof(error)); if (ret < 0) { - av_log(NULL, AV_LOG_ERROR, "Error initializing output stream %d:%d -- %s\n", - ost->file_index, ost->index, error); + av_log(ost, AV_LOG_ERROR, "Error initializing output stream: %s\n", + error); if (fatal) exit_program(1); @@ -866,7 +866,7 @@ static int encode_frame(OutputFile *of, OutputStream *ost, AVFrame *frame) ost->samples_encoded += frame->nb_samples; if (debug_ts) { - av_log(NULL, AV_LOG_INFO, "encoder <- type:%s " + av_log(ost, AV_LOG_INFO, "encoder <- type:%s " "frame_pts:%s frame_pts_time:%s time_base:%d/%d\n", type_desc, av_ts2str(frame->pts), av_ts2timestr(frame->pts, &enc->time_base), @@ -878,7 +878,7 @@ static int encode_frame(OutputFile *of, OutputStream *ost, AVFrame *frame) ret = avcodec_send_frame(enc, frame); if (ret < 0 && !(ret == AVERROR_EOF && !frame)) { - av_log(NULL, AV_LOG_ERROR, "Error submitting %s frame to the encoder\n", + av_log(ost, AV_LOG_ERROR, "Error submitting %s frame to the encoder\n", type_desc); return ret; } @@ -899,7 +899,7 @@ static int encode_frame(OutputFile *of, OutputStream *ost, AVFrame *frame) of_output_packet(of, pkt, ost, 1); return ret; } else if (ret < 0) { - av_log(NULL, AV_LOG_ERROR, "%s encoding failed\n", type_desc); + av_log(ost, AV_LOG_ERROR, "%s encoding failed\n", type_desc); return ret; } @@ -909,7 +909,7 @@ static int encode_frame(OutputFile *of, OutputStream *ost, AVFrame *frame) enc_stats_write(ost, &ost->enc_stats_post, NULL, pkt); if (debug_ts) { - av_log(NULL, AV_LOG_INFO, "encoder -> type:%s " + av_log(ost, AV_LOG_INFO, "encoder -> type:%s " "pkt_pts:%s pkt_pts_time:%s pkt_dts:%s pkt_dts_time:%s " "duration:%s duration_time:%s\n", type_desc, @@ -921,7 +921,7 @@ static int encode_frame(OutputFile *of, OutputStream *ost, AVFrame *frame) av_packet_rescale_ts(pkt, enc->time_base, ost->mux_timebase); if (debug_ts) { - av_log(NULL, AV_LOG_INFO, "encoder -> type:%s " + av_log(ost, AV_LOG_INFO, "encoder -> type:%s " "pkt_pts:%s pkt_pts_time:%s pkt_dts:%s pkt_dts_time:%s " "duration:%s duration_time:%s\n", type_desc, @@ -1023,7 +1023,7 @@ static void do_subtitle_out(OutputFile *of, int64_t pts; if (sub->pts == AV_NOPTS_VALUE) { - av_log(NULL, AV_LOG_ERROR, "Subtitle packets must have a pts\n"); + av_log(ost, AV_LOG_ERROR, "Subtitle packets must have a pts\n"); if (exit_on_error) exit_program(1); return; @@ -1067,7 +1067,7 @@ static void do_subtitle_out(OutputFile *of, if (i == 1) sub->num_rects = save_num_rects; if (subtitle_out_size < 0) { - av_log(NULL, AV_LOG_FATAL, "Subtitle encoding failed\n"); + av_log(ost, AV_LOG_FATAL, "Subtitle encoding failed\n"); exit_program(1); } @@ -1114,9 +1114,9 @@ static void video_sync_process(OutputFile *of, OutputStream *ost, 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); + av_log(ost, AV_LOG_VERBOSE, "Past duration %f too large\n", -delta0); } else - av_log(NULL, AV_LOG_DEBUG, "Clipping frame in rate conversion by %f\n", -delta0); + av_log(ost, AV_LOG_DEBUG, "Clipping frame in rate conversion by %f\n", -delta0); sync_ipts = ost->next_pts; duration += delta0; delta0 = 0; @@ -1125,7 +1125,7 @@ static void video_sync_process(OutputFile *of, OutputStream *ost, switch (ost->vsync_method) { case VSYNC_VSCFR: if (ost->vsync_frame_number == 0 && delta0 >= 0.5) { - av_log(NULL, AV_LOG_DEBUG, "Not duplicating %d initial frames\n", (int)lrintf(delta0)); + av_log(ost, AV_LOG_DEBUG, "Not duplicating %d initial frames\n", (int)lrintf(delta0)); delta = duration; delta0 = 0; ost->next_pts = llrint(sync_ipts); @@ -1160,8 +1160,9 @@ static void video_sync_process(OutputFile *of, OutputStream *ost, } } -static enum AVPictureType forced_kf_apply(KeyframeForceCtx *kf, AVRational tb, - const AVFrame *in_picture, int dup_idx) +static enum AVPictureType forced_kf_apply(void *logctx, KeyframeForceCtx *kf, + AVRational tb, const AVFrame *in_picture, + int dup_idx) { double pts_time; @@ -1206,7 +1207,7 @@ static enum AVPictureType forced_kf_apply(KeyframeForceCtx *kf, AVRational tb, return AV_PICTURE_TYPE_NONE; force_keyframe: - av_log(NULL, AV_LOG_DEBUG, "Forced keyframe at time %f\n", pts_time); + av_log(logctx, AV_LOG_DEBUG, "Forced keyframe at time %f\n", pts_time); return AV_PICTURE_TYPE_I; } @@ -1258,20 +1259,20 @@ static void do_video_out(OutputFile *of, if (nb_frames_prev == 0 && ost->last_dropped) { nb_frames_drop++; - av_log(NULL, AV_LOG_VERBOSE, - "*** dropping frame %"PRId64" from stream %d at ts %"PRId64"\n", - ost->vsync_frame_number, ost->st->index, ost->last_frame->pts); + av_log(ost, AV_LOG_VERBOSE, + "*** dropping frame %"PRId64" at ts %"PRId64"\n", + ost->vsync_frame_number, ost->last_frame->pts); } if (nb_frames > (nb_frames_prev && ost->last_dropped) + (nb_frames > nb_frames_prev)) { if (nb_frames > dts_error_threshold * 30) { - av_log(NULL, AV_LOG_ERROR, "%"PRId64" frame duplication too large, skipping\n", nb_frames - 1); + av_log(ost, AV_LOG_ERROR, "%"PRId64" frame duplication too large, skipping\n", nb_frames - 1); nb_frames_drop++; return; } nb_frames_dup += nb_frames - (nb_frames_prev && ost->last_dropped) - (nb_frames > nb_frames_prev); - av_log(NULL, AV_LOG_VERBOSE, "*** %"PRId64" dup!\n", nb_frames - 1); + av_log(ost, AV_LOG_VERBOSE, "*** %"PRId64" dup!\n", nb_frames - 1); if (nb_frames_dup > dup_warning) { - av_log(NULL, AV_LOG_WARNING, "More than %"PRIu64" frames duplicated\n", dup_warning); + av_log(ost, AV_LOG_WARNING, "More than %"PRIu64" frames duplicated\n", dup_warning); dup_warning *= 10; } } @@ -1296,7 +1297,7 @@ static void do_video_out(OutputFile *of, return; in_picture->quality = enc->global_quality; - in_picture->pict_type = forced_kf_apply(&ost->kf, enc->time_base, in_picture, i); + in_picture->pict_type = forced_kf_apply(ost, &ost->kf, enc->time_base, in_picture, i); ret = submit_encode_frame(of, ost, in_picture); if (ret == AVERROR_EOF) @@ -1764,9 +1765,8 @@ static void flush_encoders(void) if (!ost->initialized) { FilterGraph *fg = ost->filter->graph; - av_log(NULL, AV_LOG_WARNING, - "Finishing stream %d:%d without any data written to it.\n", - ost->file_index, ost->st->index); + av_log(ost, AV_LOG_WARNING, + "Finishing stream without any data written to it.\n"); if (ost->filter && !fg->graph) { int x; @@ -1774,7 +1774,7 @@ static void flush_encoders(void) InputFilter *ifilter = fg->inputs[x]; if (ifilter->format < 0 && ifilter_parameters_from_codecpar(ifilter, ifilter->ist->par) < 0) { - av_log(NULL, AV_LOG_ERROR, "Error copying paramerets from input stream\n"); + av_log(ost, AV_LOG_ERROR, "Error copying paramerets from input stream\n"); exit_program(1); } } @@ -1784,7 +1784,7 @@ static void flush_encoders(void) ret = configure_filtergraph(fg); if (ret < 0) { - av_log(NULL, AV_LOG_ERROR, "Error configuring filter graph\n"); + av_log(ost, AV_LOG_ERROR, "Error configuring filter graph\n"); exit_program(1); } @@ -2671,7 +2671,7 @@ static int init_output_stream_streamcopy(OutputStream *ost) if (ret >= 0) ret = av_opt_set_dict(codec_ctx, &ost->encoder_opts); if (ret < 0) { - av_log(NULL, AV_LOG_FATAL, + av_log(ost, AV_LOG_FATAL, "Error setting up codec context options.\n"); avcodec_free_context(&codec_ctx); return ret; @@ -2680,7 +2680,7 @@ static int init_output_stream_streamcopy(OutputStream *ost) ret = avcodec_parameters_from_context(par, codec_ctx); avcodec_free_context(&codec_ctx); if (ret < 0) { - av_log(NULL, AV_LOG_FATAL, + av_log(ost, AV_LOG_FATAL, "Error getting reference codec parameters.\n"); return ret; } @@ -2762,7 +2762,7 @@ static int init_output_stream_streamcopy(OutputStream *ost) sar = av_mul_q(ost->frame_aspect_ratio, (AVRational){ par->height, par->width }); - av_log(NULL, AV_LOG_WARNING, "Overriding aspect ratio " + av_log(ost, AV_LOG_WARNING, "Overriding aspect ratio " "with stream copy may produce invalid files\n"); } else if (ist->st->sample_aspect_ratio.num) @@ -2819,9 +2819,8 @@ static void init_encoder_time_base(OutputStream *ost, AVRational default_time_ba return; } - av_log(NULL, AV_LOG_WARNING, - "Input stream data for output stream #%d:%d not available, " - "using default time base\n", ost->file_index, ost->index); + av_log(ost, AV_LOG_WARNING, + "Input stream data not available, using default time base\n"); } enc_ctx->time_base = default_time_base; @@ -2846,12 +2845,11 @@ static int init_output_stream_encode(OutputStream *ost, AVFrame *frame) ost->frame_rate = av_buffersink_get_frame_rate(ost->filter->filter); if (!ost->frame_rate.num && !ost->max_frame_rate.num) { ost->frame_rate = (AVRational){25, 1}; - av_log(NULL, AV_LOG_WARNING, + av_log(ost, AV_LOG_WARNING, "No information " "about the input framerate is available. Falling " - "back to a default value of 25fps for output stream #%d:%d. Use the -r option " - "if you want a different framerate.\n", - ost->file_index, ost->index); + "back to a default value of 25fps. Use the -r option " + "if you want a different framerate.\n"); } if (ost->max_frame_rate.num && @@ -2895,9 +2893,9 @@ static int init_output_stream_encode(OutputStream *ost, AVFrame *frame) if ( av_q2d(enc_ctx->time_base) < 0.001 && ost->vsync_method != VSYNC_PASSTHROUGH && (ost->vsync_method == VSYNC_CFR || ost->vsync_method == VSYNC_VSCFR || (ost->vsync_method == VSYNC_AUTO && !(of->format->flags & AVFMT_VARIABLE_FPS)))){ - av_log(NULL, AV_LOG_WARNING, "Frame rate very high for a muxer not efficiently supporting it.\n" - "Please consider specifying a lower framerate, a different muxer or " - "setting vsync/fps_mode to vfr\n"); + av_log(ost, AV_LOG_WARNING, "Frame rate very high for a muxer not efficiently supporting it.\n" + "Please consider specifying a lower framerate, a different muxer or " + "setting vsync/fps_mode to vfr\n"); } enc_ctx->width = av_buffersink_get_w(ost->filter->filter); @@ -2977,7 +2975,7 @@ static int init_output_stream_encode(OutputStream *ost, AVFrame *frame) if (output_descriptor) output_props = output_descriptor->props & (AV_CODEC_PROP_TEXT_SUB | AV_CODEC_PROP_BITMAP_SUB); if (input_props && output_props && input_props != output_props) { - av_log(NULL, AV_LOG_ERROR, + av_log(ost, AV_LOG_ERROR, "Subtitle encoding currently only possible from text to text " "or bitmap to bitmap"); return AVERROR_INVALIDDATA; @@ -3043,12 +3041,12 @@ static int init_output_stream(OutputStream *ost, AVFrame *frame, assert_avoptions(ost->encoder_opts); if (ost->enc_ctx->bit_rate && ost->enc_ctx->bit_rate < 1000 && ost->enc_ctx->codec_id != AV_CODEC_ID_CODEC2 /* don't complain about 700 bit/s modes */) - av_log(NULL, AV_LOG_WARNING, "The bitrate parameter is set too low." - " It takes bits/s as argument, not kbits/s\n"); + av_log(ost, AV_LOG_WARNING, "The bitrate parameter is set too low." + " It takes bits/s as argument, not kbits/s\n"); ret = avcodec_parameters_from_context(ost->st->codecpar, ost->enc_ctx); if (ret < 0) { - av_log(NULL, AV_LOG_FATAL, + av_log(ost, AV_LOG_FATAL, "Error initializing the output stream codec context.\n"); exit_program(1); } @@ -3280,9 +3278,9 @@ static OutputStream *choose_output(void) opts = ost->last_mux_dts == AV_NOPTS_VALUE ? INT64_MIN : ost->last_mux_dts; if (ost->last_mux_dts == AV_NOPTS_VALUE) - av_log(NULL, AV_LOG_DEBUG, - "cur_dts is invalid st:%d (%d) [init:%d i_done:%d finish:%d] (this is harmless if it occurs once at the start per stream)\n", - ost->st->index, ost->st->id, ost->initialized, ost->inputs_done, ost->finished); + av_log(ost, AV_LOG_DEBUG, + "cur_dts is invalid [init:%d i_done:%d finish:%d] (this is harmless if it occurs once at the start per stream)\n", + ost->initialized, ost->inputs_done, ost->finished); } if (!ost->initialized && !ost->inputs_done) @@ -3869,8 +3867,7 @@ static int transcode(void) packets_written = atomic_load(&ost->packets_written); total_packets_written += packets_written; if (!packets_written && (abort_on_flags & ABORT_ON_FLAG_EMPTY_OUTPUT_STREAM)) { - av_log(NULL, AV_LOG_FATAL, "Empty output on stream %d:%d.\n", - ost->file_index, ost->index); + av_log(ost, AV_LOG_FATAL, "Empty output\n"); exit_program(1); } } diff --git a/fftools/ffmpeg.h b/fftools/ffmpeg.h index 1a235f205f2..dddab456f7c 100644 --- a/fftools/ffmpeg.h +++ b/fftools/ffmpeg.h @@ -548,6 +548,8 @@ typedef struct KeyframeForceCtx { } KeyframeForceCtx; typedef struct OutputStream { + const AVClass *class; + int file_index; /* file index */ int index; /* stream index in the output file */ @@ -757,7 +759,8 @@ void assert_avoptions(AVDictionary *m); void assert_file_overwrite(const char *filename); char *file_read(const char *filename); AVDictionary *strip_specifiers(const AVDictionary *dict); -const AVCodec *find_codec_or_die(const char *name, enum AVMediaType type, int encoder); +const AVCodec *find_codec_or_die(void *logctx, const char *name, + enum AVMediaType type, int encoder); int parse_and_set_vsync(const char *arg, int *vsync_var, int file_idx, int st_idx, int is_global); int configure_filtergraph(FilterGraph *fg); diff --git a/fftools/ffmpeg_demux.c b/fftools/ffmpeg_demux.c index 4b5c62b0d59..ffece607201 100644 --- a/fftools/ffmpeg_demux.c +++ b/fftools/ffmpeg_demux.c @@ -503,7 +503,7 @@ static const AVCodec *choose_decoder(const OptionsContext *o, AVFormatContext *s MATCH_PER_STREAM_OPT(codec_names, str, codec_name, s, st); if (codec_name) { - const AVCodec *codec = find_codec_or_die(codec_name, st->codecpar->codec_type, 0); + const AVCodec *codec = find_codec_or_die(NULL, codec_name, st->codecpar->codec_type, 0); st->codecpar->codec_id = codec->id; if (recast_media && st->codecpar->codec_type != codec->type) st->codecpar->codec_type = codec->type; @@ -937,13 +937,13 @@ int ifile_open(const OptionsContext *o, const char *filename) MATCH_PER_TYPE_OPT(codec_names, str, data_codec_name, ic, "d"); if (video_codec_name) - ic->video_codec = find_codec_or_die(video_codec_name , AVMEDIA_TYPE_VIDEO , 0); + ic->video_codec = find_codec_or_die(NULL, video_codec_name , AVMEDIA_TYPE_VIDEO , 0); if (audio_codec_name) - ic->audio_codec = find_codec_or_die(audio_codec_name , AVMEDIA_TYPE_AUDIO , 0); + ic->audio_codec = find_codec_or_die(NULL, audio_codec_name , AVMEDIA_TYPE_AUDIO , 0); if (subtitle_codec_name) - ic->subtitle_codec = find_codec_or_die(subtitle_codec_name, AVMEDIA_TYPE_SUBTITLE, 0); + ic->subtitle_codec = find_codec_or_die(NULL, subtitle_codec_name, AVMEDIA_TYPE_SUBTITLE, 0); if (data_codec_name) - ic->data_codec = find_codec_or_die(data_codec_name , AVMEDIA_TYPE_DATA , 0); + ic->data_codec = find_codec_or_die(NULL, data_codec_name , AVMEDIA_TYPE_DATA , 0); ic->video_codec_id = video_codec_name ? ic->video_codec->id : AV_CODEC_ID_NONE; ic->audio_codec_id = audio_codec_name ? ic->audio_codec->id : AV_CODEC_ID_NONE; diff --git a/fftools/ffmpeg_mux.c b/fftools/ffmpeg_mux.c index 91be316e0ac..5d427b44ea9 100644 --- a/fftools/ffmpeg_mux.c +++ b/fftools/ffmpeg_mux.c @@ -79,7 +79,7 @@ static int write_packet(Muxer *mux, OutputStream *ost, AVPacket *pkt) if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) { if (ost->frame_rate.num && ost->is_cfr) { if (pkt->duration > 0) - av_log(NULL, AV_LOG_WARNING, "Overriding packet duration by frame rate, this should not happen\n"); + av_log(ost, AV_LOG_WARNING, "Overriding packet duration by frame rate, this should not happen\n"); pkt->duration = av_rescale_q(1, av_inv_q(ost->frame_rate), ost->mux_timebase); } @@ -132,7 +132,7 @@ static int write_packet(Muxer *mux, OutputStream *ost, AVPacket *pkt) pkt->stream_index = ost->index; if (debug_ts) { - av_log(NULL, AV_LOG_INFO, "muxer <- type:%s " + av_log(ost, AV_LOG_INFO, "muxer <- type:%s " "pkt_pts:%s pkt_pts_time:%s pkt_dts:%s pkt_dts_time:%s duration:%s duration_time:%s size:%d\n", av_get_media_type_string(st->codecpar->codec_type), av_ts2str(pkt->pts), av_ts2timestr(pkt->pts, &ost->st->time_base), @@ -271,7 +271,7 @@ static int queue_packet(Muxer *mux, OutputStream *ost, AVPacket *pkt) size_t new_size = FFMIN(2 * cur_size, limit); if (new_size <= cur_size) { - av_log(NULL, AV_LOG_ERROR, + av_log(ost, AV_LOG_ERROR, "Too many packets buffered for output stream %d:%d.\n", ost->file_index, ost->st->index); return AVERROR(ENOSPC); @@ -364,8 +364,7 @@ void of_output_packet(OutputFile *of, AVPacket *pkt, OutputStream *ost, int eof) err_msg = "submitting a packet to the muxer"; fail: - av_log(NULL, AV_LOG_ERROR, "Error %s for output stream #%d:%d.\n", - err_msg, ost->file_index, ost->index); + av_log(ost, AV_LOG_ERROR, "Error %s\n", err_msg); if (exit_on_error) exit_program(1); @@ -559,7 +558,7 @@ static int bsf_init(MuxStream *ms) ret = av_bsf_init(ctx); if (ret < 0) { - av_log(NULL, AV_LOG_ERROR, "Error initializing bitstream filter: %s\n", + av_log(ms, AV_LOG_ERROR, "Error initializing bitstream filter: %s\n", ctx->filter->name); return ret; } @@ -640,7 +639,7 @@ static void ost_free(OutputStream **post) if (ost->logfile) { if (fclose(ost->logfile)) - av_log(NULL, AV_LOG_ERROR, + av_log(ms, AV_LOG_ERROR, "Error closing logfile, loss of information possible: %s\n", av_err2str(AVERROR(errno))); ost->logfile = NULL; diff --git a/fftools/ffmpeg_mux.h b/fftools/ffmpeg_mux.h index 8a90cc56c61..1487d86ae10 100644 --- a/fftools/ffmpeg_mux.h +++ b/fftools/ffmpeg_mux.h @@ -37,6 +37,9 @@ typedef struct MuxStream { OutputStream ost; + // name used for logging + char log_name[32]; + /* the packets are buffered here until the muxer is ready to be initialized */ AVFifo *muxing_queue; diff --git a/fftools/ffmpeg_mux_init.c b/fftools/ffmpeg_mux_init.c index d0743181999..35b115f8a63 100644 --- a/fftools/ffmpeg_mux_init.c +++ b/fftools/ffmpeg_mux_init.c @@ -116,15 +116,14 @@ static int choose_encoder(const OptionsContext *o, AVFormatContext *s, NULL, ost->st->codecpar->codec_type); *enc = avcodec_find_encoder(ost->st->codecpar->codec_id); if (!*enc) { - av_log(NULL, AV_LOG_FATAL, "Automatic encoder selection failed for " - "output stream #%d:%d. Default encoder for format %s (codec %s) is " + av_log(ost, AV_LOG_FATAL, "Automatic encoder selection failed " + "Default encoder for format %s (codec %s) is " "probably disabled. Please choose an encoder manually.\n", - ost->file_index, ost->index, s->oformat->name, - avcodec_get_name(ost->st->codecpar->codec_id)); + s->oformat->name, avcodec_get_name(ost->st->codecpar->codec_id)); return AVERROR_ENCODER_NOT_FOUND; } } else if (strcmp(codec_name, "copy")) { - *enc = find_codec_or_die(codec_name, ost->st->codecpar->codec_type, 1); + *enc = find_codec_or_die(ost, codec_name, ost->st->codecpar->codec_type, 1); ost->st->codecpar->codec_id = (*enc)->id; } } @@ -369,6 +368,37 @@ static int enc_stats_init(OutputStream *ost, int pre, return 0; } +static const char *output_stream_item_name(void *obj) +{ + const MuxStream *ms = obj; + + return ms->log_name; +} + +static const AVClass output_stream_class = { + .class_name = "OutputStream", + .version = LIBAVUTIL_VERSION_INT, + .item_name = output_stream_item_name, + .category = AV_CLASS_CATEGORY_MUXER, +}; + +static MuxStream *mux_stream_alloc(Muxer *mux, enum AVMediaType type) +{ + const char *type_str = av_get_media_type_string(type); + MuxStream *ms = allocate_array_elem(&mux->of.streams, sizeof(*ms), + &mux->of.nb_streams); + + ms->ost.file_index = mux->of.index; + ms->ost.index = mux->of.nb_streams - 1; + + ms->ost.class = &output_stream_class; + + snprintf(ms->log_name, sizeof(ms->log_name), "%cost#%d:%d", + type_str ? *type_str : '?', mux->of.index, ms->ost.index); + + return ms; +} + static OutputStream *new_output_stream(Muxer *mux, const OptionsContext *o, enum AVMediaType type, InputStream *ist) { @@ -377,7 +407,7 @@ static OutputStream *new_output_stream(Muxer *mux, const OptionsContext *o, OutputStream *ost; const AVCodec *enc; AVStream *st = avformat_new_stream(oc, NULL); - int idx = oc->nb_streams - 1, ret = 0; + int ret = 0; const char *bsfs = NULL, *time_base = NULL; char *next, *codec_tag = NULL; double qscale = -1; @@ -389,8 +419,7 @@ static OutputStream *new_output_stream(Muxer *mux, const OptionsContext *o, if (oc->nb_streams - 1 < o->nb_streamid_map) st->id = o->streamid_map[oc->nb_streams - 1]; - ms = allocate_array_elem(&mux->of.streams, sizeof(MuxStream), - &mux->of.nb_streams); + ms = mux_stream_alloc(mux, type); ost = &ms->ost; ms->muxing_queue = av_fifo_alloc2(8, sizeof(AVPacket*), 0); @@ -398,16 +427,13 @@ static OutputStream *new_output_stream(Muxer *mux, const OptionsContext *o, report_and_exit(AVERROR(ENOMEM)); ms->last_mux_dts = AV_NOPTS_VALUE; - ost->file_index = nb_output_files - 1; - ost->index = idx; ost->st = st; ost->kf.ref_pts = AV_NOPTS_VALUE; st->codecpar->codec_type = type; ret = choose_encoder(o, oc, ost, &enc); if (ret < 0) { - av_log(NULL, AV_LOG_FATAL, "Error selecting an encoder for stream " - "%d:%d\n", ost->file_index, ost->index); + av_log(ost, AV_LOG_FATAL, "Error selecting an encoder\n"); exit_program(1); } @@ -415,6 +441,11 @@ static OutputStream *new_output_stream(Muxer *mux, const OptionsContext *o, ost->enc_ctx = avcodec_alloc_context3(enc); if (!ost->enc_ctx) report_and_exit(AVERROR(ENOMEM)); + + av_strlcat(ms->log_name, "/", sizeof(ms->log_name)); + av_strlcat(ms->log_name, enc->name, sizeof(ms->log_name)); + } else { + av_strlcat(ms->log_name, "/copy", sizeof(ms->log_name)); } ost->filtered_frame = av_frame_alloc(); @@ -446,7 +477,7 @@ static OutputStream *new_output_stream(Muxer *mux, const OptionsContext *o, if (!buf[0] || buf[0] == '#') continue; if (!(arg = strchr(buf, '='))) { - av_log(NULL, AV_LOG_FATAL, "Invalid line found in the preset file.\n"); + av_log(ost, AV_LOG_FATAL, "Invalid line found in the preset file.\n"); exit_program(1); } *arg++ = 0; @@ -456,9 +487,8 @@ static OutputStream *new_output_stream(Muxer *mux, const OptionsContext *o, avio_closep(&s); } if (ret) { - av_log(NULL, AV_LOG_FATAL, - "Preset %s specified for stream %d:%d, but could not be opened.\n", - preset, ost->file_index, ost->index); + av_log(ost, AV_LOG_FATAL, + "Preset %s specified, but could not be opened.\n", preset); exit_program(1); } @@ -502,7 +532,7 @@ static OutputStream *new_output_stream(Muxer *mux, const OptionsContext *o, AVRational q; if (av_parse_ratio(&q, time_base, INT_MAX, 0, NULL) < 0 || q.num <= 0 || q.den <= 0) { - av_log(NULL, AV_LOG_FATAL, "Invalid time base: %s\n", time_base); + av_log(ost, AV_LOG_FATAL, "Invalid time base: %s\n", time_base); exit_program(1); } st->time_base = q; @@ -513,7 +543,7 @@ static OutputStream *new_output_stream(Muxer *mux, const OptionsContext *o, AVRational q; if (av_parse_ratio(&q, time_base, INT_MAX, 0, NULL) < 0 || q.den <= 0) { - av_log(NULL, AV_LOG_FATAL, "Invalid time base: %s\n", time_base); + av_log(ost, AV_LOG_FATAL, "Invalid time base: %s\n", time_base); exit_program(1); } ost->enc_timebase = q; @@ -524,7 +554,7 @@ static OutputStream *new_output_stream(Muxer *mux, const OptionsContext *o, for (i = 0; inb_max_frames; i++) { char *p = o->max_frames[i].specifier; if (!*p && type != AVMEDIA_TYPE_VIDEO) { - av_log(NULL, AV_LOG_WARNING, "Applying unspecific -frames to non video streams, maybe you meant -vframes ?\n"); + av_log(ost, AV_LOG_WARNING, "Applying unspecific -frames to non video streams, maybe you meant -vframes ?\n"); break; } } @@ -536,7 +566,7 @@ static OutputStream *new_output_stream(Muxer *mux, const OptionsContext *o, if (bsfs && *bsfs) { ret = av_bsf_list_parse_str(bsfs, &ms->bsf_ctx); if (ret < 0) { - av_log(NULL, AV_LOG_ERROR, "Error parsing bitstream filter sequence '%s': %s\n", bsfs, av_err2str(ret)); + av_log(ost, AV_LOG_ERROR, "Error parsing bitstream filter sequence '%s': %s\n", bsfs, av_err2str(ret)); exit_program(1); } } @@ -595,8 +625,7 @@ static char *get_ost_filters(const OptionsContext *o, AVFormatContext *oc, AVStream *st = ost->st; if (ost->filters_script && ost->filters) { - av_log(NULL, AV_LOG_ERROR, "Both -filter and -filter_script set for " - "output stream #%d:%d.\n", nb_output_files, st->index); + av_log(ost, AV_LOG_ERROR, "Both -filter and -filter_script set\n"); exit_program(1); } @@ -610,20 +639,19 @@ static char *get_ost_filters(const OptionsContext *o, AVFormatContext *oc, } static void check_streamcopy_filters(const OptionsContext *o, AVFormatContext *oc, - const OutputStream *ost, enum AVMediaType type) + OutputStream *ost, enum AVMediaType type) { if (ost->filters_script || ost->filters) { - av_log(NULL, AV_LOG_ERROR, - "%s '%s' was defined for %s output stream %d:%d but codec copy was selected.\n" + av_log(ost, AV_LOG_ERROR, + "%s '%s' was defined, but codec copy was selected.\n" "Filtering and streamcopy cannot be used together.\n", ost->filters ? "Filtergraph" : "Filtergraph script", - ost->filters ? ost->filters : ost->filters_script, - av_get_media_type_string(type), ost->file_index, ost->index); + ost->filters ? ost->filters : ost->filters_script); exit_program(1); } } -static void parse_matrix_coeffs(uint16_t *dest, const char *str) +static void parse_matrix_coeffs(void *logctx, uint16_t *dest, const char *str) { int i; const char *p = str; @@ -633,7 +661,8 @@ static void parse_matrix_coeffs(uint16_t *dest, const char *str) break; p = strchr(p, ','); if (!p) { - av_log(NULL, AV_LOG_FATAL, "Syntax error in matrix \"%s\" at coeff %d\n", str, i); + av_log(logctx, AV_LOG_FATAL, + "Syntax error in matrix \"%s\" at coeff %d\n", str, i); exit_program(1); } p++; @@ -652,18 +681,18 @@ static OutputStream *new_video_stream(Muxer *mux, const OptionsContext *o, Input MATCH_PER_STREAM_OPT(frame_rates, str, frame_rate, oc, st); if (frame_rate && av_parse_video_rate(&ost->frame_rate, frame_rate) < 0) { - av_log(NULL, AV_LOG_FATAL, "Invalid framerate value: %s\n", frame_rate); + av_log(ost, AV_LOG_FATAL, "Invalid framerate value: %s\n", frame_rate); exit_program(1); } MATCH_PER_STREAM_OPT(max_frame_rates, str, max_frame_rate, oc, st); if (max_frame_rate && av_parse_video_rate(&ost->max_frame_rate, max_frame_rate) < 0) { - av_log(NULL, AV_LOG_FATAL, "Invalid maximum framerate value: %s\n", max_frame_rate); + av_log(ost, AV_LOG_FATAL, "Invalid maximum framerate value: %s\n", max_frame_rate); exit_program(1); } if (frame_rate && max_frame_rate) { - av_log(NULL, AV_LOG_ERROR, "Only one of -fpsmax and -r can be set for a stream.\n"); + av_log(ost, AV_LOG_ERROR, "Only one of -fpsmax and -r can be set for a stream.\n"); exit_program(1); } @@ -672,7 +701,7 @@ static OutputStream *new_video_stream(Muxer *mux, const OptionsContext *o, Input AVRational q; if (av_parse_ratio(&q, frame_aspect_ratio, 255, 0, NULL) < 0 || q.num <= 0 || q.den <= 0) { - av_log(NULL, AV_LOG_FATAL, "Invalid aspect ratio: %s\n", frame_aspect_ratio); + av_log(ost, AV_LOG_FATAL, "Invalid aspect ratio: %s\n", frame_aspect_ratio); exit_program(1); } ost->frame_aspect_ratio = q; @@ -693,7 +722,7 @@ static OutputStream *new_video_stream(Muxer *mux, const OptionsContext *o, Input MATCH_PER_STREAM_OPT(frame_sizes, str, frame_size, oc, st); if (frame_size && av_parse_video_size(&video_enc->width, &video_enc->height, frame_size) < 0) { - av_log(NULL, AV_LOG_FATAL, "Invalid frame size: %s.\n", frame_size); + av_log(ost, AV_LOG_FATAL, "Invalid frame size: %s.\n", frame_size); exit_program(1); } @@ -704,7 +733,7 @@ static OutputStream *new_video_stream(Muxer *mux, const OptionsContext *o, Input frame_pix_fmt = NULL; } if (frame_pix_fmt && (video_enc->pix_fmt = av_get_pix_fmt(frame_pix_fmt)) == AV_PIX_FMT_NONE) { - av_log(NULL, AV_LOG_FATAL, "Unknown pixel format requested: %s.\n", frame_pix_fmt); + av_log(ost, AV_LOG_FATAL, "Unknown pixel format requested: %s.\n", frame_pix_fmt); exit_program(1); } st->sample_aspect_ratio = video_enc->sample_aspect_ratio; @@ -713,7 +742,7 @@ static OutputStream *new_video_stream(Muxer *mux, const OptionsContext *o, Input if (intra_matrix) { if (!(video_enc->intra_matrix = av_mallocz(sizeof(*video_enc->intra_matrix) * 64))) report_and_exit(AVERROR(ENOMEM)); - parse_matrix_coeffs(video_enc->intra_matrix, intra_matrix); + parse_matrix_coeffs(ost, video_enc->intra_matrix, intra_matrix); } MATCH_PER_STREAM_OPT(chroma_intra_matrices, str, chroma_intra_matrix, oc, st); if (chroma_intra_matrix) { @@ -721,13 +750,13 @@ static OutputStream *new_video_stream(Muxer *mux, const OptionsContext *o, Input if (!p) report_and_exit(AVERROR(ENOMEM)); video_enc->chroma_intra_matrix = p; - parse_matrix_coeffs(p, chroma_intra_matrix); + parse_matrix_coeffs(ost, p, chroma_intra_matrix); } MATCH_PER_STREAM_OPT(inter_matrices, str, inter_matrix, oc, st); if (inter_matrix) { if (!(video_enc->inter_matrix = av_mallocz(sizeof(*video_enc->inter_matrix) * 64))) report_and_exit(AVERROR(ENOMEM)); - parse_matrix_coeffs(video_enc->inter_matrix, inter_matrix); + parse_matrix_coeffs(ost, video_enc->inter_matrix, inter_matrix); } MATCH_PER_STREAM_OPT(rc_overrides, str, p, oc, st); @@ -735,14 +764,14 @@ static OutputStream *new_video_stream(Muxer *mux, const OptionsContext *o, Input int start, end, q; int e = sscanf(p, "%d,%d,%d", &start, &end, &q); if (e != 3) { - av_log(NULL, AV_LOG_FATAL, "error parsing rc_override\n"); + av_log(ost, AV_LOG_FATAL, "error parsing rc_override\n"); exit_program(1); } video_enc->rc_override = av_realloc_array(video_enc->rc_override, i + 1, sizeof(RcOverride)); if (!video_enc->rc_override) { - av_log(NULL, AV_LOG_FATAL, "Could not (re)allocate memory for rc_override.\n"); + av_log(ost, AV_LOG_FATAL, "Could not (re)allocate memory for rc_override.\n"); exit_program(1); } video_enc->rc_override[i].start_frame = start; @@ -762,7 +791,7 @@ static OutputStream *new_video_stream(Muxer *mux, const OptionsContext *o, Input #if FFMPEG_OPT_PSNR if (do_psnr) { - av_log(NULL, AV_LOG_WARNING, "The -psnr option is deprecated, use -flags +psnr\n"); + av_log(ost, AV_LOG_WARNING, "The -psnr option is deprecated, use -flags +psnr\n"); video_enc->flags|= AV_CODEC_FLAG_PSNR; } #endif @@ -805,7 +834,7 @@ static OutputStream *new_video_stream(Muxer *mux, const OptionsContext *o, Input char *logbuffer = file_read(logfilename); if (!logbuffer) { - av_log(NULL, AV_LOG_FATAL, "Error reading log file '%s' for pass-2 encoding\n", + av_log(ost, AV_LOG_FATAL, "Error reading log file '%s' for pass-2 encoding\n", logfilename); exit_program(1); } @@ -814,7 +843,7 @@ static OutputStream *new_video_stream(Muxer *mux, const OptionsContext *o, Input if (video_enc->flags & AV_CODEC_FLAG_PASS1) { f = fopen_utf8(logfilename, "wb"); if (!f) { - av_log(NULL, AV_LOG_FATAL, + av_log(ost, AV_LOG_FATAL, "Cannot write log file '%s' for pass-1 encoding: %s\n", logfilename, strerror(errno)); exit_program(1); @@ -837,7 +866,7 @@ static OutputStream *new_video_stream(Muxer *mux, const OptionsContext *o, Input if ((ost->frame_rate.num || ost->max_frame_rate.num) && !(ost->vsync_method == VSYNC_AUTO || ost->vsync_method == VSYNC_CFR || ost->vsync_method == VSYNC_VSCFR)) { - av_log(NULL, AV_LOG_FATAL, "One of -r/-fpsmax was specified " + av_log(ost, AV_LOG_FATAL, "One of -r/-fpsmax was specified " "together a non-CFR -vsync/-fps_mode. This is contradictory.\n"); exit_program(1); } @@ -915,11 +944,11 @@ static OutputStream *new_audio_stream(Muxer *mux, const OptionsContext *o, Input }) if (!mask) { #endif - av_log(NULL, AV_LOG_FATAL, "Unknown channel layout: %s\n", layout); + av_log(ost, AV_LOG_FATAL, "Unknown channel layout: %s\n", layout); exit_program(1); #if FF_API_OLD_CHANNEL_LAYOUT } - av_log(NULL, AV_LOG_WARNING, "Channel layout '%s' uses a deprecated syntax.\n", + av_log(ost, AV_LOG_WARNING, "Channel layout '%s' uses a deprecated syntax.\n", layout); av_channel_layout_from_mask(&audio_enc->ch_layout, mask); #endif @@ -929,7 +958,7 @@ static OutputStream *new_audio_stream(Muxer *mux, const OptionsContext *o, Input MATCH_PER_STREAM_OPT(sample_fmts, str, sample_fmt, oc, st); if (sample_fmt && (audio_enc->sample_fmt = av_get_sample_fmt(sample_fmt)) == AV_SAMPLE_FMT_NONE) { - av_log(NULL, AV_LOG_FATAL, "Invalid sample format '%s'\n", sample_fmt); + av_log(ost, AV_LOG_FATAL, "Invalid sample format '%s'\n", sample_fmt); exit_program(1); } @@ -953,7 +982,7 @@ static OutputStream *new_audio_stream(Muxer *mux, const OptionsContext *o, Input if (map->channel_idx == -1) { ist = NULL; } else if (!ost->ist) { - av_log(NULL, AV_LOG_FATAL, "Cannot determine input stream for channel mapping %d.%d\n", + av_log(ost, AV_LOG_FATAL, "Cannot determine input stream for channel mapping %d.%d\n", ost->file_index, ost->st->index); continue; } else { @@ -984,7 +1013,7 @@ static OutputStream *new_data_stream(Muxer *mux, const OptionsContext *o, InputS ost = new_output_stream(mux, o, AVMEDIA_TYPE_DATA, ist); if (ost->enc_ctx) { - av_log(NULL, AV_LOG_FATAL, "Data stream encoding not supported yet (only streamcopy)\n"); + av_log(ost, AV_LOG_FATAL, "Data stream encoding not supported yet (only streamcopy)\n"); exit_program(1); } @@ -997,7 +1026,7 @@ static OutputStream *new_unknown_stream(Muxer *mux, const OptionsContext *o, Inp ost = new_output_stream(mux, o, AVMEDIA_TYPE_UNKNOWN, ist); if (ost->enc_ctx) { - av_log(NULL, AV_LOG_FATAL, "Unknown stream encoding not supported yet (only streamcopy)\n"); + av_log(ost, AV_LOG_FATAL, "Unknown stream encoding not supported yet (only streamcopy)\n"); exit_program(1); } @@ -1025,7 +1054,7 @@ static OutputStream *new_subtitle_stream(Muxer *mux, const OptionsContext *o, In MATCH_PER_STREAM_OPT(frame_sizes, str, frame_size, mux->fc, st); if (frame_size && av_parse_video_size(&subtitle_enc->width, &subtitle_enc->height, frame_size) < 0) { - av_log(NULL, AV_LOG_FATAL, "Invalid frame size: %s.\n", frame_size); + av_log(ost, AV_LOG_FATAL, "Invalid frame size: %s.\n", frame_size); exit_program(1); } } @@ -1053,15 +1082,15 @@ static void init_output_filter(OutputFilter *ofilter, const OptionsContext *o, ofilter->format = -1; if (!ost->enc_ctx) { - av_log(NULL, AV_LOG_ERROR, "Streamcopy requested for output stream %d:%d, " - "which is fed from a complex filtergraph. Filtering and streamcopy " - "cannot be used together.\n", ost->file_index, ost->index); + av_log(ost, AV_LOG_ERROR, "Streamcopy requested for output stream fed " + "from a complex filtergraph. Filtering and streamcopy " + "cannot be used together.\n"); exit_program(1); } if (ost->avfilter && (ost->filters || ost->filters_script)) { const char *opt = ost->filters ? "-vf/-af/-filter" : "-filter_script"; - av_log(NULL, AV_LOG_ERROR, + av_log(ost, AV_LOG_ERROR, "%s '%s' was specified through the %s option " "for output stream %d:%d, which is fed from a complex filtergraph.\n" "%s and -filter_complex cannot be used together for the same stream.\n", @@ -1617,7 +1646,7 @@ static void of_add_metadata(OutputFile *of, AVFormatContext *oc, ost->rotate_override_value = theta; } - av_log(NULL, AV_LOG_WARNING, + av_log(ost, AV_LOG_WARNING, "Conversion of a 'rotate' metadata key to a " "proper display matrix rotation is deprecated. " "See -display_rotation for setting rotation " @@ -2059,7 +2088,7 @@ static int process_forced_keyframes(Muxer *mux, const OptionsContext *o) int ret = av_expr_parse(&ost->kf.pexpr, forced_keyframes + 5, forced_keyframes_const_names, NULL, NULL, NULL, NULL, 0, NULL); if (ret < 0) { - av_log(NULL, AV_LOG_ERROR, + av_log(ost, AV_LOG_ERROR, "Invalid force_key_frames expression '%s'\n", forced_keyframes + 5); return ret; } @@ -2237,10 +2266,8 @@ int of_open(const OptionsContext *o, const char *filename) ost->st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) { err = init_simple_filtergraph(ist, ost); if (err < 0) { - av_log(NULL, AV_LOG_ERROR, - "Error initializing a simple filtergraph between streams " - "%d:%d->%d:%d\n", ist->file_index, ist->st->index, - nb_output_files - 1, ost->st->index); + av_log(ost, AV_LOG_ERROR, + "Error initializing a simple filtergraph\n"); exit_program(1); } } diff --git a/fftools/ffmpeg_opt.c b/fftools/ffmpeg_opt.c index c81c991d5e7..c0ae55a3598 100644 --- a/fftools/ffmpeg_opt.c +++ b/fftools/ffmpeg_opt.c @@ -623,7 +623,8 @@ static int opt_recording_timestamp(void *optctx, const char *opt, const char *ar return 0; } -const AVCodec *find_codec_or_die(const char *name, enum AVMediaType type, int encoder) +const AVCodec *find_codec_or_die(void *logctx, const char *name, + enum AVMediaType type, int encoder) { const AVCodecDescriptor *desc; const char *codec_string = encoder ? "encoder" : "decoder"; @@ -637,16 +638,16 @@ const AVCodec *find_codec_or_die(const char *name, enum AVMediaType type, int en codec = encoder ? avcodec_find_encoder(desc->id) : avcodec_find_decoder(desc->id); if (codec) - av_log(NULL, AV_LOG_VERBOSE, "Matched %s '%s' for codec '%s'.\n", + av_log(logctx, AV_LOG_VERBOSE, "Matched %s '%s' for codec '%s'.\n", codec_string, codec->name, desc->name); } if (!codec) { - av_log(NULL, AV_LOG_FATAL, "Unknown %s '%s'\n", codec_string, name); + av_log(logctx, AV_LOG_FATAL, "Unknown %s '%s'\n", codec_string, name); exit_program(1); } if (codec->type != type && !recast_media) { - av_log(NULL, AV_LOG_FATAL, "Invalid %s type '%s'\n", codec_string, name); + av_log(logctx, AV_LOG_FATAL, "Invalid %s type '%s'\n", codec_string, name); exit_program(1); } return codec; From 935964bd418c6695589c99fdd3898cc0b72a7592 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Wed, 25 Jan 2023 14:28:40 +0100 Subject: [PATCH 0095/2172] doc/ffmpeg: drop non-existent -dc option --- doc/ffmpeg.texi | 2 -- 1 file changed, 2 deletions(-) diff --git a/doc/ffmpeg.texi b/doc/ffmpeg.texi index 1c7e65479c3..7f445022a04 100644 --- a/doc/ffmpeg.texi +++ b/doc/ffmpeg.texi @@ -1041,8 +1041,6 @@ version > 1: @code{out= %2d st= %2d frame= %5d q= %2.1f PSNR= %6.2f f_size= %6d s_size= %8.0fkB time= %0.3f br= %7.1fkbits/s avg_br= %7.1fkbits/s} @item -top[:@var{stream_specifier}] @var{n} (@emph{output,per-stream}) top=1/bottom=0/auto=-1 field first -@item -dc @var{precision} -Intra_dc_precision. @item -vtag @var{fourcc/tag} (@emph{output}) Force video tag/fourcc. This is an alias for @code{-tag:v}. @item -qphist (@emph{global}) From 1f9828bb8cf2bcaec95b534b22f30366a56bc92a Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Tue, 10 Jan 2023 15:12:48 +0100 Subject: [PATCH 0096/2172] lavc/avcodec: improve enc/dec API doxy Change return value descriptions into lists of @retval --- libavcodec/avcodec.h | 79 ++++++++++++++++++++++---------------------- 1 file changed, 39 insertions(+), 40 deletions(-) diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h index 0ac581d6604..ad6377e8d89 100644 --- a/libavcodec/avcodec.h +++ b/libavcodec/avcodec.h @@ -2605,17 +2605,17 @@ int avcodec_decode_subtitle2(AVCodecContext *avctx, AVSubtitle *sub, * still has frames buffered, it will return them after sending * a flush packet. * - * @return 0 on success, otherwise negative error code: - * AVERROR(EAGAIN): input is not accepted in the current state - user - * must read output with avcodec_receive_frame() (once - * all output is read, the packet should be resent, and - * the call will not fail with EAGAIN). - * AVERROR_EOF: the decoder has been flushed, and no new packets can - * be sent to it (also returned if more than 1 flush - * packet is sent) - * AVERROR(EINVAL): codec not opened, it is an encoder, or requires flush - * AVERROR(ENOMEM): failed to add packet to internal queue, or similar - * other errors: legitimate decoding errors + * @retval 0 success + * @retval AVERROR(EAGAIN) input is not accepted in the current state - user + * must read output with avcodec_receive_frame() (once + * all output is read, the packet should be resent, + * and the call will not fail with EAGAIN). + * @retval AVERROR_EOF the decoder has been flushed, and no new packets can be + * sent to it (also returned if more than 1 flush + * packet is sent) + * @retval AVERROR(EINVAL) codec not opened, it is an encoder, or requires flush + * @retval AVERROR(ENOMEM) failed to add packet to internal queue, or similar + * @retval "another negative error code" legitimate decoding errors */ int avcodec_send_packet(AVCodecContext *avctx, const AVPacket *avpkt); @@ -2629,18 +2629,17 @@ int avcodec_send_packet(AVCodecContext *avctx, const AVPacket *avpkt); * codec. Note that the function will always call * av_frame_unref(frame) before doing anything else. * - * @return - * 0: success, a frame was returned - * AVERROR(EAGAIN): output is not available in this state - user must try - * to send new input - * AVERROR_EOF: the codec has been fully flushed, and there will be - * no more output frames - * AVERROR(EINVAL): codec not opened, or it is an encoder without - * the AV_CODEC_FLAG_RECON_FRAME flag enabled - * AVERROR_INPUT_CHANGED: current decoded frame has changed parameters - * with respect to first decoded frame. Applicable - * when flag AV_CODEC_FLAG_DROPCHANGED is set. - * other negative values: legitimate decoding errors + * @retval 0 success, a frame was returned + * @retval AVERROR(EAGAIN) output is not available in this state - user must + * try to send new input + * @retval AVERROR_EOF the codec has been fully flushed, and there will be + * no more output frames + * @retval AVERROR(EINVAL) codec not opened, or it is an encoder without the + * AV_CODEC_FLAG_RECON_FRAME flag enabled + * @retval AVERROR_INPUT_CHANGED current decoded frame has changed parameters with + * respect to first decoded frame. Applicable when flag + * AV_CODEC_FLAG_DROPCHANGED is set. + * @retval "other negative error code" legitimate decoding errors */ int avcodec_receive_frame(AVCodecContext *avctx, AVFrame *frame); @@ -2667,16 +2666,16 @@ int avcodec_receive_frame(AVCodecContext *avctx, AVFrame *frame); * If it is not set, frame->nb_samples must be equal to * avctx->frame_size for all frames except the last. * The final frame may be smaller than avctx->frame_size. - * @return 0 on success, otherwise negative error code: - * AVERROR(EAGAIN): input is not accepted in the current state - user - * must read output with avcodec_receive_packet() (once - * all output is read, the packet should be resent, and - * the call will not fail with EAGAIN). - * AVERROR_EOF: the encoder has been flushed, and no new frames can - * be sent to it - * AVERROR(EINVAL): codec not opened, it is a decoder, or requires flush - * AVERROR(ENOMEM): failed to add packet to internal queue, or similar - * other errors: legitimate encoding errors + * @retval 0 success + * @retval AVERROR(EAGAIN) input is not accepted in the current state - user must + * read output with avcodec_receive_packet() (once all + * output is read, the packet should be resent, and the + * call will not fail with EAGAIN). + * @retval AVERROR_EOF the encoder has been flushed, and no new frames can + * be sent to it + * @retval AVERROR(EINVAL) codec not opened, it is a decoder, or requires flush + * @retval AVERROR(ENOMEM) failed to add packet to internal queue, or similar + * @retval "another negative error code" legitimate encoding errors */ int avcodec_send_frame(AVCodecContext *avctx, const AVFrame *frame); @@ -2687,13 +2686,13 @@ int avcodec_send_frame(AVCodecContext *avctx, const AVFrame *frame); * @param avpkt This will be set to a reference-counted packet allocated by the * encoder. Note that the function will always call * av_packet_unref(avpkt) before doing anything else. - * @return 0 on success, otherwise negative error code: - * AVERROR(EAGAIN): output is not available in the current state - user - * must try to send input - * AVERROR_EOF: the encoder has been fully flushed, and there will be - * no more output packets - * AVERROR(EINVAL): codec not opened, or it is a decoder - * other errors: legitimate encoding errors + * @retval 0 success + * @retval AVERROR(EAGAIN) output is not available in the current state - user must + * try to send input + * @retval AVERROR_EOF the encoder has been fully flushed, and there will be no + * more output packets + * @retval AVERROR(EINVAL) codec not opened, or it is a decoder + * @retval "another negative error code" legitimate encoding errors */ int avcodec_receive_packet(AVCodecContext *avctx, AVPacket *avpkt); From e5e29eda5aae8eb5d1d32f647c68c0543db63217 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Tue, 10 Jan 2023 15:13:33 +0100 Subject: [PATCH 0097/2172] lavc/avcodec: improve AV_CODEC_FLAG_RECON_FRAME doxy Do not break a sentence on a period after "i.e.". Link to the definition of AV_CODEC_CAP_ENCODER_RECON_FRAME. --- libavcodec/avcodec.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h index ad6377e8d89..4874b443f93 100644 --- a/libavcodec/avcodec.h +++ b/libavcodec/avcodec.h @@ -232,13 +232,13 @@ typedef struct RcOverride{ */ #define AV_CODEC_FLAG_DROPCHANGED (1 << 5) /** - * Request the encoder to output reconstructed frames, i.e. frames that would be - * produced by decoding the encoded bistream. These frames may be retrieved by - * calling avcodec_receive_frame() immediately after a successful call to + * Request the encoder to output reconstructed frames, i.e.\ frames that would + * be produced by decoding the encoded bistream. These frames may be retrieved + * by calling avcodec_receive_frame() immediately after a successful call to * avcodec_receive_packet(). * * Should only be used with encoders flagged with the - * AV_CODEC_CAP_ENCODER_RECON_FRAME capability. + * @ref AV_CODEC_CAP_ENCODER_RECON_FRAME capability. */ #define AV_CODEC_FLAG_RECON_FRAME (1 << 6) /** From d0c8ca961d7d4a496f212283781ba74623bf8c3f Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Wed, 25 Jan 2023 16:39:01 +0100 Subject: [PATCH 0098/2172] lavc: add a private cap for fake-delay encoders Some encoders (ffv1, flac, adx) are marked with AV_CODEC_CAP_DELAY onky in order to be flushed at the end, otherwise they behave as no-delay encoders. Add a capability to mark these encoders. Use it for setting pts generically. --- libavcodec/adxenc.c | 3 +-- libavcodec/codec_internal.h | 8 ++++++++ libavcodec/encode.c | 6 ++++-- libavcodec/ffv1enc.c | 4 +--- libavcodec/flacenc.c | 7 ++----- libavcodec/tests/avcodec.c | 4 ++++ 6 files changed, 20 insertions(+), 12 deletions(-) diff --git a/libavcodec/adxenc.c b/libavcodec/adxenc.c index 153c91b852f..6e12a58b162 100644 --- a/libavcodec/adxenc.c +++ b/libavcodec/adxenc.c @@ -183,8 +183,6 @@ static int adx_encode_frame(AVCodecContext *avctx, AVPacket *avpkt, dst += BLOCK_SIZE; } - avpkt->pts = frame->pts; - avpkt->duration = frame->nb_samples; *got_packet_ptr = 1; return 0; } @@ -200,4 +198,5 @@ const FFCodec ff_adpcm_adx_encoder = { FF_CODEC_ENCODE_CB(adx_encode_frame), .p.sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_S16, AV_SAMPLE_FMT_NONE }, + .caps_internal = FF_CODEC_CAP_EOF_FLUSH, }; diff --git a/libavcodec/codec_internal.h b/libavcodec/codec_internal.h index e3b77e6deaf..130a7dc3cd7 100644 --- a/libavcodec/codec_internal.h +++ b/libavcodec/codec_internal.h @@ -80,6 +80,14 @@ * Codec supports embedded ICC profiles (AV_FRAME_DATA_ICC_PROFILE). */ #define FF_CODEC_CAP_ICC_PROFILES (1 << 9) +/** + * The encoder has AV_CODEC_CAP_DELAY set, but does not actually have delay - it + * only wants to be flushed at the end to update some context variables (e.g. + * 2pass stats) or produce a trailing packet. Besides that it immediately + * produces exactly one output packet per each input frame, just as no-delay + * encoders do. + */ +#define FF_CODEC_CAP_EOF_FLUSH (1 << 10) /** * FFCodec.codec_tags termination value diff --git a/libavcodec/encode.c b/libavcodec/encode.c index fbe2c97cd62..e0b3e43840f 100644 --- a/libavcodec/encode.c +++ b/libavcodec/encode.c @@ -211,7 +211,8 @@ int ff_encode_encode_cb(AVCodecContext *avctx, AVPacket *avpkt, // set the timestamps for the simple no-delay case // encoders with delay have to set the timestamps themselves - if (!(avctx->codec->capabilities & AV_CODEC_CAP_DELAY)) { + if (!(avctx->codec->capabilities & AV_CODEC_CAP_DELAY) || + (frame && (codec->caps_internal & FF_CODEC_CAP_EOF_FLUSH))) { if (avpkt->pts == AV_NOPTS_VALUE) avpkt->pts = frame->pts; @@ -225,7 +226,8 @@ int ff_encode_encode_cb(AVCodecContext *avctx, AVPacket *avpkt, // dts equals pts unless there is reordering // there can be no reordering if there is no encoder delay if (!(avctx->codec_descriptor->props & AV_CODEC_PROP_REORDER) || - !(avctx->codec->capabilities & AV_CODEC_CAP_DELAY)) + !(avctx->codec->capabilities & AV_CODEC_CAP_DELAY) || + (codec->caps_internal & FF_CODEC_CAP_EOF_FLUSH)) avpkt->dts = avpkt->pts; } else { unref: diff --git a/libavcodec/ffv1enc.c b/libavcodec/ffv1enc.c index 0237ac48ebc..6649ec7e88b 100644 --- a/libavcodec/ffv1enc.c +++ b/libavcodec/ffv1enc.c @@ -1231,8 +1231,6 @@ static int encode_frame(AVCodecContext *avctx, AVPacket *pkt, f->picture_number++; pkt->size = buf_p - pkt->data; - pkt->pts = - pkt->dts = pict->pts; pkt->flags |= AV_PKT_FLAG_KEY * f->key_frame; *got_packet = 1; @@ -1301,5 +1299,5 @@ const FFCodec ff_ffv1_encoder = { }, .p.priv_class = &ffv1_class, - .caps_internal = FF_CODEC_CAP_INIT_CLEANUP, + .caps_internal = FF_CODEC_CAP_INIT_CLEANUP | FF_CODEC_CAP_EOF_FLUSH, }; diff --git a/libavcodec/flacenc.c b/libavcodec/flacenc.c index 8aacc93e283..9a9835dfa6e 100644 --- a/libavcodec/flacenc.c +++ b/libavcodec/flacenc.c @@ -1690,10 +1690,7 @@ static int flac_encode_frame(AVCodecContext *avctx, AVPacket *avpkt, if (out_bytes < s->min_framesize) s->min_framesize = out_bytes; - avpkt->pts = frame->pts; - avpkt->duration = ff_samples_to_time_base(avctx, frame->nb_samples); - - s->next_pts = avpkt->pts + avpkt->duration; + s->next_pts = frame->pts + ff_samples_to_time_base(avctx, frame->nb_samples); av_shrink_packet(avpkt, out_bytes); @@ -1766,5 +1763,5 @@ const FFCodec ff_flac_encoder = { AV_SAMPLE_FMT_S32, AV_SAMPLE_FMT_NONE }, .p.priv_class = &flac_encoder_class, - .caps_internal = FF_CODEC_CAP_INIT_CLEANUP, + .caps_internal = FF_CODEC_CAP_INIT_CLEANUP | FF_CODEC_CAP_EOF_FLUSH, }; diff --git a/libavcodec/tests/avcodec.c b/libavcodec/tests/avcodec.c index 3288a85f64b..4c1730425d7 100644 --- a/libavcodec/tests/avcodec.c +++ b/libavcodec/tests/avcodec.c @@ -158,6 +158,10 @@ int main(void){ if (codec->capabilities & AV_CODEC_CAP_FRAME_THREADS && codec->capabilities & AV_CODEC_CAP_DELAY) ERR("Frame-threaded encoder %s claims to have delay\n"); + + if (codec2->caps_internal & FF_CODEC_CAP_EOF_FLUSH && + !(codec->capabilities & AV_CODEC_CAP_DELAY)) + ERR("EOF_FLUSH encoder %s is not marked as having delay\n"); } else { if ((codec->type == AVMEDIA_TYPE_SUBTITLE) != (codec2->cb_type == FF_CODEC_CB_TYPE_DECODE_SUB)) ERR("Subtitle decoder %s does not implement decode_sub callback\n"); From 5c0348f3d61ce850fa33fe79b5d2bc49f7b52683 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Tue, 12 Jul 2022 11:25:09 +0200 Subject: [PATCH 0099/2172] lavc: add a codec flag for propagating opaque from frames to packets This is intended to be a more convenient replacement for reordered_opaque. Add support for it in the two encoders that offer AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE: libx264 and libx265. Other encoders will be supported in future commits. --- doc/APIchanges | 3 +++ libavcodec/avcodec.h | 26 +++++++++++++++++++++++ libavcodec/encode.c | 7 +++++++ libavcodec/libx264.c | 29 ++++++++++++++++++++++++++ libavcodec/libx265.c | 42 ++++++++++++++++++++++++++++---------- libavcodec/options_table.h | 1 + libavcodec/version.h | 2 +- 7 files changed, 98 insertions(+), 12 deletions(-) diff --git a/doc/APIchanges b/doc/APIchanges index a11acadecd7..148962cb409 100644 --- a/doc/APIchanges +++ b/doc/APIchanges @@ -14,6 +14,9 @@ libavutil: 2021-04-27 API changes, most recent first: +2023-01-xx - xxxxxxxxxx - lavc 59.59.100 - avcodec.h + Add AV_CODEC_FLAG_COPY_OPAQUE. + 2023-01-13 - xxxxxxxxxx - lavu 57.44.100 - ambient_viewing_environment.h frame.h Adds a new structure for holding H.274 Ambient Viewing Environment metadata, AVAmbientViewingEnvironment. diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h index 4874b443f93..832b9d95753 100644 --- a/libavcodec/avcodec.h +++ b/libavcodec/avcodec.h @@ -241,6 +241,32 @@ typedef struct RcOverride{ * @ref AV_CODEC_CAP_ENCODER_RECON_FRAME capability. */ #define AV_CODEC_FLAG_RECON_FRAME (1 << 6) +/** + * Request the encoder to propagate each frame's AVFrame.opaque and + * AVFrame.opaque_ref values to its corresponding output AVPacket. + * + * May only be set on encoders that have the + * @ref AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE capability flag. + * + * @note + * While in typical cases one input frame produces exactly one output packet + * (perhaps after a delay), in general the mapping of frames to packets is + * M-to-N, so + * - Any number of input frames may be associated with any given output packet. + * This includes zero - e.g. some encoders may output packets that carry only + * metadata about the whole stream. + * - A given input frame may be associated with any number of output packets. + * Again this includes zero - e.g. some encoders may drop frames under certain + * conditions. + * . + * This implies that when using this flag, the caller must NOT assume that + * - a given input frame's opaques will necessarily appear on some output packet; + * - every output packet will have some non-NULL opaque value. + * . + * When an output packet contains multiple frames, the opaque values will be + * taken from the first of those. + */ +#define AV_CODEC_FLAG_COPY_OPAQUE (1 << 7) /** * Use internal 2pass ratecontrol in first pass mode. */ diff --git a/libavcodec/encode.c b/libavcodec/encode.c index e0b3e43840f..d6c73dc044f 100644 --- a/libavcodec/encode.c +++ b/libavcodec/encode.c @@ -636,6 +636,13 @@ int ff_encode_preinit(AVCodecContext *avctx) return AVERROR(EINVAL); } + if (avctx->flags & AV_CODEC_FLAG_COPY_OPAQUE && + !(avctx->codec->capabilities & AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE)) { + av_log(avctx, AV_LOG_ERROR, "The copy_opaque flag is set, but the " + "encoder does not support it.\n"); + return AVERROR(EINVAL); + } + switch (avctx->codec_type) { case AVMEDIA_TYPE_VIDEO: ret = encode_preinit_video(avctx); break; case AVMEDIA_TYPE_AUDIO: ret = encode_preinit_audio(avctx); break; diff --git a/libavcodec/libx264.c b/libavcodec/libx264.c index 2bbd9044b68..6d22a1726ec 100644 --- a/libavcodec/libx264.c +++ b/libavcodec/libx264.c @@ -21,6 +21,7 @@ #include "config_components.h" +#include "libavutil/buffer.h" #include "libavutil/eval.h" #include "libavutil/internal.h" #include "libavutil/opt.h" @@ -51,6 +52,9 @@ typedef struct X264Opaque { int64_t reordered_opaque; int64_t wallclock; + + void *frame_opaque; + AVBufferRef *frame_opaque_ref; } X264Opaque; typedef struct X264Context { @@ -133,6 +137,11 @@ static void X264_log(void *p, int level, const char *fmt, va_list args) av_vlog(p, level_map[level], fmt, args); } +static void opaque_uninit(X264Opaque *o) +{ + av_buffer_unref(&o->frame_opaque_ref); + memset(o, 0, sizeof(*o)); +} static int encode_nals(AVCodecContext *ctx, AVPacket *pkt, const x264_nal_t *nals, int nnal) @@ -440,6 +449,15 @@ static int setup_frame(AVCodecContext *ctx, const AVFrame *frame, pic->i_pts = frame->pts; + opaque_uninit(opaque); + + if (ctx->flags & AV_CODEC_FLAG_COPY_OPAQUE) { + opaque->frame_opaque = frame->opaque; + ret = av_buffer_replace(&opaque->frame_opaque_ref, frame->opaque_ref); + if (ret < 0) + goto fail; + } + opaque->reordered_opaque = frame->reordered_opaque; opaque->wallclock = wallclock; if (ctx->export_side_data & AV_CODEC_EXPORT_DATA_PRFT) @@ -594,6 +612,14 @@ static int X264_frame(AVCodecContext *ctx, AVPacket *pkt, const AVFrame *frame, out_opaque < &x4->reordered_opaque[x4->nb_reordered_opaque]) { ctx->reordered_opaque = out_opaque->reordered_opaque; wallclock = out_opaque->wallclock; + + if (ctx->flags & AV_CODEC_FLAG_COPY_OPAQUE) { + pkt->opaque = out_opaque->frame_opaque; + pkt->opaque_ref = out_opaque->frame_opaque_ref; + out_opaque->frame_opaque_ref = NULL; + } + + opaque_uninit(out_opaque); } else { // Unexpected opaque pointer on picture output av_log(ctx, AV_LOG_ERROR, "Unexpected opaque pointer; " @@ -634,6 +660,9 @@ static av_cold int X264_close(AVCodecContext *avctx) X264Context *x4 = avctx->priv_data; av_freep(&x4->sei); + + for (int i = 0; i < x4->nb_reordered_opaque; i++) + opaque_uninit(&x4->reordered_opaque[i]); av_freep(&x4->reordered_opaque); #if X264_BUILD >= 161 diff --git a/libavcodec/libx265.c b/libavcodec/libx265.c index 25de3c669be..a71f1f76d30 100644 --- a/libavcodec/libx265.c +++ b/libavcodec/libx265.c @@ -28,6 +28,7 @@ #include #include "libavutil/avassert.h" +#include "libavutil/buffer.h" #include "libavutil/internal.h" #include "libavutil/common.h" #include "libavutil/opt.h" @@ -43,6 +44,9 @@ typedef struct ReorderedData { int64_t reordered_opaque; + void *frame_opaque; + AVBufferRef *frame_opaque_ref; + int in_use; } ReorderedData; @@ -121,7 +125,7 @@ static int rd_get(libx265Context *ctx) static void rd_release(libx265Context *ctx, int idx) { av_assert0(idx >= 0 && idx < ctx->nb_rd); - + av_buffer_unref(&ctx->rd[idx].frame_opaque_ref); memset(&ctx->rd[idx], 0, sizeof(ctx->rd[idx])); } @@ -132,6 +136,8 @@ static av_cold int libx265_encode_close(AVCodecContext *avctx) ctx->api->param_free(ctx->params); av_freep(&ctx->sei_data); + for (int i = 0; i < ctx->nb_rd; i++) + rd_release(ctx, i); av_freep(&ctx->rd); if (ctx->encoder) @@ -582,6 +588,9 @@ static int libx265_encode_frame(AVCodecContext *avctx, AVPacket *pkt, sei->numPayloads = 0; if (pic) { + ReorderedData *rd; + int rd_idx; + for (i = 0; i < 3; i++) { x265pic.planes[i] = pic->data[i]; x265pic.stride[i] = pic->linesize[i]; @@ -600,21 +609,26 @@ static int libx265_encode_frame(AVCodecContext *avctx, AVPacket *pkt, if (ret < 0) return ret; - if (pic->reordered_opaque) { - ReorderedData *rd; - int rd_idx = rd_get(ctx); + rd_idx = rd_get(ctx); + if (rd_idx < 0) { + free_picture(ctx, &x265pic); + return rd_idx; + } + rd = &ctx->rd[rd_idx]; - if (rd_idx < 0) { + rd->reordered_opaque = pic->reordered_opaque; + if (avctx->flags & AV_CODEC_FLAG_COPY_OPAQUE) { + rd->frame_opaque = pic->opaque; + ret = av_buffer_replace(&rd->frame_opaque_ref, pic->opaque_ref); + if (ret < 0) { + rd_release(ctx, rd_idx); free_picture(ctx, &x265pic); - return rd_idx; + return ret; } - - x265pic.userData = (void*)(intptr_t)(rd_idx + 1); - - rd = &ctx->rd[rd_idx]; - rd->reordered_opaque = pic->reordered_opaque; } + x265pic.userData = (void*)(intptr_t)(rd_idx + 1); + if (ctx->a53_cc) { void *sei_data; size_t sei_size; @@ -742,6 +756,12 @@ static int libx265_encode_frame(AVCodecContext *avctx, AVPacket *pkt, avctx->reordered_opaque = rd->reordered_opaque; + if (avctx->flags & AV_CODEC_FLAG_COPY_OPAQUE) { + pkt->opaque = rd->frame_opaque; + pkt->opaque_ref = rd->frame_opaque_ref; + rd->frame_opaque_ref = NULL; + } + rd_release(ctx, idx); } else avctx->reordered_opaque = 0; diff --git a/libavcodec/options_table.h b/libavcodec/options_table.h index 7924ca61443..4b38c42043d 100644 --- a/libavcodec/options_table.h +++ b/libavcodec/options_table.h @@ -58,6 +58,7 @@ static const AVOption avcodec_options[] = { {"loop", "use loop filter", 0, AV_OPT_TYPE_CONST, {.i64 = AV_CODEC_FLAG_LOOP_FILTER }, INT_MIN, INT_MAX, V|E, "flags"}, {"qscale", "use fixed qscale", 0, AV_OPT_TYPE_CONST, {.i64 = AV_CODEC_FLAG_QSCALE }, INT_MIN, INT_MAX, 0, "flags"}, {"recon_frame", "export reconstructed frames", 0, AV_OPT_TYPE_CONST, {.i64 = AV_CODEC_FLAG_RECON_FRAME}, .unit = "flags"}, +{"copy_opaque", "propagate opaque values", 0, AV_OPT_TYPE_CONST, {.i64 = AV_CODEC_FLAG_COPY_OPAQUE}, .unit = "flags"}, {"pass1", "use internal 2-pass ratecontrol in first pass mode", 0, AV_OPT_TYPE_CONST, {.i64 = AV_CODEC_FLAG_PASS1 }, INT_MIN, INT_MAX, 0, "flags"}, {"pass2", "use internal 2-pass ratecontrol in second pass mode", 0, AV_OPT_TYPE_CONST, {.i64 = AV_CODEC_FLAG_PASS2 }, INT_MIN, INT_MAX, 0, "flags"}, {"gray", "only decode/encode grayscale", 0, AV_OPT_TYPE_CONST, {.i64 = AV_CODEC_FLAG_GRAY }, INT_MIN, INT_MAX, V|E|D, "flags"}, diff --git a/libavcodec/version.h b/libavcodec/version.h index 7ac8d2b2fe2..752adc81f8f 100644 --- a/libavcodec/version.h +++ b/libavcodec/version.h @@ -29,7 +29,7 @@ #include "version_major.h" -#define LIBAVCODEC_VERSION_MINOR 58 +#define LIBAVCODEC_VERSION_MINOR 59 #define LIBAVCODEC_VERSION_MICRO 100 #define LIBAVCODEC_VERSION_INT AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \ From 8d73f3ce56fc90d840c83e8ab3463474d2d38046 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Sun, 27 Nov 2022 13:37:10 +0100 Subject: [PATCH 0100/2172] lavc: support AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE in all no-delay encoders Including fake-delay encoders marked with FF_CODEC_CAP_EOF_FLUSH. --- libavcodec/ac3enc_fixed.c | 2 +- libavcodec/ac3enc_float.c | 2 +- libavcodec/adpcmenc.c | 3 ++- libavcodec/adxenc.c | 3 ++- libavcodec/alacenc.c | 3 ++- libavcodec/aliaspixenc.c | 2 +- libavcodec/aptxenc.c | 4 ++-- libavcodec/asvenc.c | 4 ++-- libavcodec/avuienc.c | 3 ++- libavcodec/bitpacked_enc.c | 3 ++- libavcodec/bmpenc.c | 2 +- libavcodec/cfhdenc.c | 3 ++- libavcodec/cinepakenc.c | 2 +- libavcodec/cljrenc.c | 2 +- libavcodec/cngenc.c | 2 +- libavcodec/dcaenc.c | 3 ++- libavcodec/dfpwmenc.c | 3 ++- libavcodec/dnxhdenc.c | 2 +- libavcodec/dvenc.c | 3 ++- libavcodec/eac3enc.c | 2 +- libavcodec/encode.c | 19 +++++++++++++++++++ libavcodec/encode.h | 6 ++++++ libavcodec/exrenc.c | 3 ++- libavcodec/ffv1enc.c | 3 ++- libavcodec/fitsenc.c | 2 +- libavcodec/flacenc.c | 3 ++- libavcodec/flashsv2enc.c | 2 +- libavcodec/flashsvenc.c | 2 +- libavcodec/flvenc.c | 1 + libavcodec/g722enc.c | 3 ++- libavcodec/g723_1enc.c | 2 +- libavcodec/g726.c | 6 ++++-- libavcodec/gif.c | 2 +- libavcodec/h261enc.c | 1 + libavcodec/hapenc.c | 3 ++- libavcodec/hdrenc.c | 3 ++- libavcodec/huffyuvenc.c | 6 ++++-- libavcodec/ituh263enc.c | 3 ++- libavcodec/j2kenc.c | 2 +- libavcodec/jpeglsenc.c | 3 ++- libavcodec/lclenc.c | 3 ++- libavcodec/libcodec2.c | 3 ++- libavcodec/libgsmenc.c | 4 ++-- libavcodec/libilbc.c | 2 +- libavcodec/libjxlenc.c | 3 ++- libavcodec/libopenh264enc.c | 3 ++- libavcodec/libopenjpegenc.c | 3 ++- libavcodec/libvo-amrwbenc.c | 3 ++- libavcodec/libwebpenc.c | 2 +- libavcodec/libxvid.c | 2 +- libavcodec/ljpegenc.c | 3 ++- libavcodec/magicyuvenc.c | 3 ++- libavcodec/mjpegenc.c | 4 +++- libavcodec/mpegaudioenc_fixed.c | 2 +- libavcodec/mpegaudioenc_float.c | 2 +- libavcodec/msmpeg4enc.c | 3 +++ libavcodec/msvideo1enc.c | 1 + libavcodec/pamenc.c | 2 +- libavcodec/pcm-blurayenc.c | 2 +- libavcodec/pcm-dvdenc.c | 3 ++- libavcodec/pcm.c | 3 ++- libavcodec/pcxenc.c | 2 +- libavcodec/pngenc.c | 3 ++- libavcodec/pnmenc.c | 12 ++++++------ libavcodec/proresenc_anatoliy.c | 6 ++++-- libavcodec/proresenc_kostya.c | 3 ++- libavcodec/qoienc.c | 3 ++- libavcodec/qtrleenc.c | 2 +- libavcodec/r210enc.c | 6 +++--- libavcodec/rawenc.c | 3 ++- libavcodec/roqvideoenc.c | 2 +- libavcodec/rpzaenc.c | 2 +- libavcodec/rv10enc.c | 1 + libavcodec/rv20enc.c | 1 + libavcodec/s302menc.c | 3 ++- libavcodec/sbcenc.c | 3 ++- libavcodec/sgienc.c | 2 +- libavcodec/smcenc.c | 2 +- libavcodec/snowenc.c | 2 +- libavcodec/sonic.c | 6 ++++-- libavcodec/speedhqenc.c | 1 + libavcodec/sunrastenc.c | 2 +- libavcodec/svq1enc.c | 2 +- libavcodec/targaenc.c | 2 +- libavcodec/tiffenc.c | 3 ++- libavcodec/ttaenc.c | 3 ++- libavcodec/utvideoenc.c | 3 ++- libavcodec/v210enc.c | 3 ++- libavcodec/v308enc.c | 2 +- libavcodec/v408enc.c | 4 ++-- libavcodec/v410enc.c | 2 +- libavcodec/vaapi_encode_mjpeg.c | 3 ++- libavcodec/vbnenc.c | 3 ++- libavcodec/vc2enc.c | 3 ++- libavcodec/wavpackenc.c | 3 ++- libavcodec/wbmpenc.c | 3 ++- libavcodec/wmaenc.c | 4 ++-- libavcodec/wmv2enc.c | 1 + libavcodec/wrapped_avframe.c | 1 + libavcodec/xbmenc.c | 2 +- libavcodec/xfaceenc.c | 2 +- libavcodec/xwdenc.c | 2 +- libavcodec/y41penc.c | 2 +- libavcodec/yuv4enc.c | 2 +- libavcodec/zmbvenc.c | 2 +- 105 files changed, 198 insertions(+), 110 deletions(-) diff --git a/libavcodec/ac3enc_fixed.c b/libavcodec/ac3enc_fixed.c index 5a5f1cc2e95..88dfd66b91d 100644 --- a/libavcodec/ac3enc_fixed.c +++ b/libavcodec/ac3enc_fixed.c @@ -112,7 +112,7 @@ const FFCodec ff_ac3_fixed_encoder = { CODEC_LONG_NAME("ATSC A/52A (AC-3)"), .p.type = AVMEDIA_TYPE_AUDIO, .p.id = AV_CODEC_ID_AC3, - .p.capabilities = AV_CODEC_CAP_DR1, + .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE, .priv_data_size = sizeof(AC3EncodeContext), .init = ac3_fixed_encode_init, FF_CODEC_ENCODE_CB(ff_ac3_fixed_encode_frame), diff --git a/libavcodec/ac3enc_float.c b/libavcodec/ac3enc_float.c index 4c4d18ce567..ae351a535e9 100644 --- a/libavcodec/ac3enc_float.c +++ b/libavcodec/ac3enc_float.c @@ -116,7 +116,7 @@ const FFCodec ff_ac3_encoder = { CODEC_LONG_NAME("ATSC A/52A (AC-3)"), .p.type = AVMEDIA_TYPE_AUDIO, .p.id = AV_CODEC_ID_AC3, - .p.capabilities = AV_CODEC_CAP_DR1, + .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE, .priv_data_size = sizeof(AC3EncodeContext), .init = ff_ac3_float_encode_init, FF_CODEC_ENCODE_CB(ff_ac3_float_encode_frame), diff --git a/libavcodec/adpcmenc.c b/libavcodec/adpcmenc.c index 57709b19a10..63afffc58f7 100644 --- a/libavcodec/adpcmenc.c +++ b/libavcodec/adpcmenc.c @@ -1003,7 +1003,8 @@ const FFCodec ff_ ## name_ ## _encoder = { \ .p.id = id_, \ .p.sample_fmts = sample_fmts_, \ .p.ch_layouts = ch_layouts, \ - .p.capabilities = capabilities_ | AV_CODEC_CAP_DR1, \ + .p.capabilities = capabilities_ | AV_CODEC_CAP_DR1 | \ + AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE, \ .p.priv_class = &adpcm_encoder_class, \ .priv_data_size = sizeof(ADPCMEncodeContext), \ .init = adpcm_encode_init, \ diff --git a/libavcodec/adxenc.c b/libavcodec/adxenc.c index 6e12a58b162..796efdab63b 100644 --- a/libavcodec/adxenc.c +++ b/libavcodec/adxenc.c @@ -192,7 +192,8 @@ const FFCodec ff_adpcm_adx_encoder = { CODEC_LONG_NAME("SEGA CRI ADX ADPCM"), .p.type = AVMEDIA_TYPE_AUDIO, .p.id = AV_CODEC_ID_ADPCM_ADX, - .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_DELAY, + .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_DELAY | + AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE, .priv_data_size = sizeof(ADXContext), .init = adx_encode_init, FF_CODEC_ENCODE_CB(adx_encode_frame), diff --git a/libavcodec/alacenc.c b/libavcodec/alacenc.c index 0f685d71d62..9598e5861e5 100644 --- a/libavcodec/alacenc.c +++ b/libavcodec/alacenc.c @@ -653,7 +653,8 @@ const FFCodec ff_alac_encoder = { CODEC_LONG_NAME("ALAC (Apple Lossless Audio Codec)"), .p.type = AVMEDIA_TYPE_AUDIO, .p.id = AV_CODEC_ID_ALAC, - .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_SMALL_LAST_FRAME, + .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_SMALL_LAST_FRAME | + AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE, .priv_data_size = sizeof(AlacEncodeContext), .p.priv_class = &alacenc_class, .init = alac_encode_init, diff --git a/libavcodec/aliaspixenc.c b/libavcodec/aliaspixenc.c index 6593d3f0473..90d2a633193 100644 --- a/libavcodec/aliaspixenc.c +++ b/libavcodec/aliaspixenc.c @@ -106,7 +106,7 @@ const FFCodec ff_alias_pix_encoder = { CODEC_LONG_NAME("Alias/Wavefront PIX image"), .p.type = AVMEDIA_TYPE_VIDEO, .p.id = AV_CODEC_ID_ALIAS_PIX, - .p.capabilities = AV_CODEC_CAP_DR1, + .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE, FF_CODEC_ENCODE_CB(encode_frame), .p.pix_fmts = (const enum AVPixelFormat[]) { AV_PIX_FMT_BGR24, AV_PIX_FMT_GRAY8, AV_PIX_FMT_NONE diff --git a/libavcodec/aptxenc.c b/libavcodec/aptxenc.c index 5fc0378f5dc..6deebaf2cbd 100644 --- a/libavcodec/aptxenc.c +++ b/libavcodec/aptxenc.c @@ -271,7 +271,7 @@ const FFCodec ff_aptx_encoder = { CODEC_LONG_NAME("aptX (Audio Processing Technology for Bluetooth)"), .p.type = AVMEDIA_TYPE_AUDIO, .p.id = AV_CODEC_ID_APTX, - .p.capabilities = AV_CODEC_CAP_DR1, + .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE, .priv_data_size = sizeof(AptXEncContext), .init = aptx_encode_init, FF_CODEC_ENCODE_CB(aptx_encode_frame), @@ -290,7 +290,7 @@ const FFCodec ff_aptx_hd_encoder = { CODEC_LONG_NAME("aptX HD (Audio Processing Technology for Bluetooth)"), .p.type = AVMEDIA_TYPE_AUDIO, .p.id = AV_CODEC_ID_APTX_HD, - .p.capabilities = AV_CODEC_CAP_DR1, + .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE, .priv_data_size = sizeof(AptXEncContext), .init = aptx_encode_init, FF_CODEC_ENCODE_CB(aptx_encode_frame), diff --git a/libavcodec/asvenc.c b/libavcodec/asvenc.c index 9da7cbb986a..4a14bcf8fa2 100644 --- a/libavcodec/asvenc.c +++ b/libavcodec/asvenc.c @@ -362,7 +362,7 @@ const FFCodec ff_asv1_encoder = { CODEC_LONG_NAME("ASUS V1"), .p.type = AVMEDIA_TYPE_VIDEO, .p.id = AV_CODEC_ID_ASV1, - .p.capabilities = AV_CODEC_CAP_DR1, + .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE, .priv_data_size = sizeof(ASVEncContext), .init = encode_init, FF_CODEC_ENCODE_CB(encode_frame), @@ -377,7 +377,7 @@ const FFCodec ff_asv2_encoder = { CODEC_LONG_NAME("ASUS V2"), .p.type = AVMEDIA_TYPE_VIDEO, .p.id = AV_CODEC_ID_ASV2, - .p.capabilities = AV_CODEC_CAP_DR1, + .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE, .priv_data_size = sizeof(ASVEncContext), .init = encode_init, FF_CODEC_ENCODE_CB(encode_frame), diff --git a/libavcodec/avuienc.c b/libavcodec/avuienc.c index 0b82848cb36..8a093d3d193 100644 --- a/libavcodec/avuienc.c +++ b/libavcodec/avuienc.c @@ -96,7 +96,8 @@ const FFCodec ff_avui_encoder = { CODEC_LONG_NAME("Avid Meridien Uncompressed"), .p.type = AVMEDIA_TYPE_VIDEO, .p.id = AV_CODEC_ID_AVUI, - .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_EXPERIMENTAL, + .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_EXPERIMENTAL | + AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE, .p.pix_fmts = (const enum AVPixelFormat[]){ AV_PIX_FMT_UYVY422, AV_PIX_FMT_NONE }, .init = avui_encode_init, FF_CODEC_ENCODE_CB(avui_encode_frame), diff --git a/libavcodec/bitpacked_enc.c b/libavcodec/bitpacked_enc.c index ca4d5c887d6..3c4e11293db 100644 --- a/libavcodec/bitpacked_enc.c +++ b/libavcodec/bitpacked_enc.c @@ -110,7 +110,8 @@ const FFCodec ff_bitpacked_encoder = { .p.type = AVMEDIA_TYPE_VIDEO, .p.id = AV_CODEC_ID_BITPACKED, .priv_data_size = sizeof(struct BitpackedContext), - .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_FRAME_THREADS, + .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_FRAME_THREADS | + AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE, .init = encode_init, FF_CODEC_ENCODE_CB(encode_frame), .p.pix_fmts = (const enum AVPixelFormat[]){ AV_PIX_FMT_YUV422P10, diff --git a/libavcodec/bmpenc.c b/libavcodec/bmpenc.c index abf644bd998..3e3ca324eae 100644 --- a/libavcodec/bmpenc.c +++ b/libavcodec/bmpenc.c @@ -161,7 +161,7 @@ const FFCodec ff_bmp_encoder = { CODEC_LONG_NAME("BMP (Windows and OS/2 bitmap)"), .p.type = AVMEDIA_TYPE_VIDEO, .p.id = AV_CODEC_ID_BMP, - .p.capabilities = AV_CODEC_CAP_DR1, + .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE, .init = bmp_encode_init, FF_CODEC_ENCODE_CB(bmp_encode_frame), .p.pix_fmts = (const enum AVPixelFormat[]){ diff --git a/libavcodec/cfhdenc.c b/libavcodec/cfhdenc.c index 29fb56f25ad..f447438491d 100644 --- a/libavcodec/cfhdenc.c +++ b/libavcodec/cfhdenc.c @@ -859,7 +859,8 @@ const FFCodec ff_cfhd_encoder = { CODEC_LONG_NAME("GoPro CineForm HD"), .p.type = AVMEDIA_TYPE_VIDEO, .p.id = AV_CODEC_ID_CFHD, - .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_FRAME_THREADS, + .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_FRAME_THREADS | + AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE, .priv_data_size = sizeof(CFHDEncContext), .p.priv_class = &cfhd_class, .init = cfhd_encode_init, diff --git a/libavcodec/cinepakenc.c b/libavcodec/cinepakenc.c index c05449e89c8..f15325ad0d0 100644 --- a/libavcodec/cinepakenc.c +++ b/libavcodec/cinepakenc.c @@ -1219,7 +1219,7 @@ const FFCodec ff_cinepak_encoder = { CODEC_LONG_NAME("Cinepak"), .p.type = AVMEDIA_TYPE_VIDEO, .p.id = AV_CODEC_ID_CINEPAK, - .p.capabilities = AV_CODEC_CAP_DR1, + .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE, .priv_data_size = sizeof(CinepakEncContext), .init = cinepak_encode_init, FF_CODEC_ENCODE_CB(cinepak_encode_frame), diff --git a/libavcodec/cljrenc.c b/libavcodec/cljrenc.c index c1f8810a5a1..d6589315205 100644 --- a/libavcodec/cljrenc.c +++ b/libavcodec/cljrenc.c @@ -113,7 +113,7 @@ const FFCodec ff_cljr_encoder = { CODEC_LONG_NAME("Cirrus Logic AccuPak"), .p.type = AVMEDIA_TYPE_VIDEO, .p.id = AV_CODEC_ID_CLJR, - .p.capabilities = AV_CODEC_CAP_DR1, + .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE, .priv_data_size = sizeof(CLJRContext), FF_CODEC_ENCODE_CB(encode_frame), .p.pix_fmts = (const enum AVPixelFormat[]) { AV_PIX_FMT_YUV411P, diff --git a/libavcodec/cngenc.c b/libavcodec/cngenc.c index ff40017f0dc..596d6f8c2ae 100644 --- a/libavcodec/cngenc.c +++ b/libavcodec/cngenc.c @@ -101,7 +101,7 @@ const FFCodec ff_comfortnoise_encoder = { CODEC_LONG_NAME("RFC 3389 comfort noise generator"), .p.type = AVMEDIA_TYPE_AUDIO, .p.id = AV_CODEC_ID_COMFORT_NOISE, - .p.capabilities = AV_CODEC_CAP_DR1, + .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE, .priv_data_size = sizeof(CNGContext), .init = cng_encode_init, FF_CODEC_ENCODE_CB(cng_encode_frame), diff --git a/libavcodec/dcaenc.c b/libavcodec/dcaenc.c index 4cab54ef1be..c731d79381c 100644 --- a/libavcodec/dcaenc.c +++ b/libavcodec/dcaenc.c @@ -1315,7 +1315,8 @@ const FFCodec ff_dca_encoder = { CODEC_LONG_NAME("DCA (DTS Coherent Acoustics)"), .p.type = AVMEDIA_TYPE_AUDIO, .p.id = AV_CODEC_ID_DTS, - .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_EXPERIMENTAL, + .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_EXPERIMENTAL | + AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE, .priv_data_size = sizeof(DCAEncContext), .init = encode_init, .close = encode_close, diff --git a/libavcodec/dfpwmenc.c b/libavcodec/dfpwmenc.c index 7f465a446e4..5318b04a390 100644 --- a/libavcodec/dfpwmenc.c +++ b/libavcodec/dfpwmenc.c @@ -116,5 +116,6 @@ const FFCodec ff_dfpwm_encoder = { .init = dfpwm_enc_init, FF_CODEC_ENCODE_CB(dfpwm_enc_frame), .p.sample_fmts = (const enum AVSampleFormat[]){AV_SAMPLE_FMT_U8, AV_SAMPLE_FMT_NONE}, - .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_VARIABLE_FRAME_SIZE, + .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_VARIABLE_FRAME_SIZE | + AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE, }; diff --git a/libavcodec/dnxhdenc.c b/libavcodec/dnxhdenc.c index b7dc54f86ae..176bf972d81 100644 --- a/libavcodec/dnxhdenc.c +++ b/libavcodec/dnxhdenc.c @@ -1359,7 +1359,7 @@ const FFCodec ff_dnxhd_encoder = { .p.type = AVMEDIA_TYPE_VIDEO, .p.id = AV_CODEC_ID_DNXHD, .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_FRAME_THREADS | - AV_CODEC_CAP_SLICE_THREADS, + AV_CODEC_CAP_SLICE_THREADS | AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE, .priv_data_size = sizeof(DNXHDEncContext), .init = dnxhd_encode_init, FF_CODEC_ENCODE_CB(dnxhd_encode_picture), diff --git a/libavcodec/dvenc.c b/libavcodec/dvenc.c index 4c747ef71ff..8f5fa050b0f 100644 --- a/libavcodec/dvenc.c +++ b/libavcodec/dvenc.c @@ -1239,7 +1239,8 @@ const FFCodec ff_dvvideo_encoder = { .p.type = AVMEDIA_TYPE_VIDEO, .p.id = AV_CODEC_ID_DVVIDEO, .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_FRAME_THREADS | - AV_CODEC_CAP_SLICE_THREADS, + AV_CODEC_CAP_SLICE_THREADS | + AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE, .priv_data_size = sizeof(DVEncContext), .init = dvvideo_encode_init, FF_CODEC_ENCODE_CB(dvvideo_encode_frame), diff --git a/libavcodec/eac3enc.c b/libavcodec/eac3enc.c index 78d4f1399a1..ab9eda261fe 100644 --- a/libavcodec/eac3enc.c +++ b/libavcodec/eac3enc.c @@ -254,7 +254,7 @@ const FFCodec ff_eac3_encoder = { CODEC_LONG_NAME("ATSC A/52 E-AC-3"), .p.type = AVMEDIA_TYPE_AUDIO, .p.id = AV_CODEC_ID_EAC3, - .p.capabilities = AV_CODEC_CAP_DR1, + .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE, .priv_data_size = sizeof(AC3EncodeContext), .init = ff_ac3_float_encode_init, FF_CODEC_ENCODE_CB(ff_ac3_float_encode_frame), diff --git a/libavcodec/encode.c b/libavcodec/encode.c index d6c73dc044f..555bd3ff96b 100644 --- a/libavcodec/encode.c +++ b/libavcodec/encode.c @@ -190,6 +190,21 @@ int ff_encode_get_frame(AVCodecContext *avctx, AVFrame *frame) return 0; } +int ff_encode_reordered_opaque(AVCodecContext *avctx, + AVPacket *pkt, const AVFrame *frame) +{ + avctx->reordered_opaque = frame->reordered_opaque; + + if (avctx->flags & AV_CODEC_FLAG_COPY_OPAQUE) { + int ret = av_buffer_replace(&pkt->opaque_ref, frame->opaque_ref); + if (ret < 0) + return ret; + pkt->opaque = frame->opaque; + } + + return 0; +} + int ff_encode_encode_cb(AVCodecContext *avctx, AVPacket *avpkt, AVFrame *frame, int *got_packet) { @@ -221,6 +236,10 @@ int ff_encode_encode_cb(AVCodecContext *avctx, AVPacket *avpkt, avpkt->duration = ff_samples_to_time_base(avctx, frame->nb_samples); } + + ret = ff_encode_reordered_opaque(avctx, avpkt, frame); + if (ret < 0) + goto unref; } // dts equals pts unless there is reordering diff --git a/libavcodec/encode.h b/libavcodec/encode.h index 81d18d6eadf..26a3304045b 100644 --- a/libavcodec/encode.h +++ b/libavcodec/encode.h @@ -69,6 +69,12 @@ int ff_encode_alloc_frame(AVCodecContext *avctx, AVFrame *frame); */ int ff_alloc_packet(AVCodecContext *avctx, AVPacket *avpkt, int64_t size); +/** + * Propagate user opaque values from the frame to avctx/pkt as needed. + */ +int ff_encode_reordered_opaque(AVCodecContext *avctx, + AVPacket *pkt, const AVFrame *frame); + /* * Perform encoder initialization and validation. * Called when opening the encoder, before the FFCodec.init() call. diff --git a/libavcodec/exrenc.c b/libavcodec/exrenc.c index 10ed8768880..36327f498cb 100644 --- a/libavcodec/exrenc.c +++ b/libavcodec/exrenc.c @@ -547,7 +547,8 @@ const FFCodec ff_exr_encoder = { .p.priv_class = &exr_class, .p.type = AVMEDIA_TYPE_VIDEO, .p.id = AV_CODEC_ID_EXR, - .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_FRAME_THREADS, + .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_FRAME_THREADS | + AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE, .init = encode_init, FF_CODEC_ENCODE_CB(encode_frame), .close = encode_close, diff --git a/libavcodec/ffv1enc.c b/libavcodec/ffv1enc.c index 6649ec7e88b..fb12776cc29 100644 --- a/libavcodec/ffv1enc.c +++ b/libavcodec/ffv1enc.c @@ -1270,7 +1270,8 @@ const FFCodec ff_ffv1_encoder = { .p.type = AVMEDIA_TYPE_VIDEO, .p.id = AV_CODEC_ID_FFV1, .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_DELAY | - AV_CODEC_CAP_SLICE_THREADS, + AV_CODEC_CAP_SLICE_THREADS | + AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE, .priv_data_size = sizeof(FFV1Context), .init = encode_init, FF_CODEC_ENCODE_CB(encode_frame), diff --git a/libavcodec/fitsenc.c b/libavcodec/fitsenc.c index ac910499e58..12952278ac4 100644 --- a/libavcodec/fitsenc.c +++ b/libavcodec/fitsenc.c @@ -114,7 +114,7 @@ const FFCodec ff_fits_encoder = { CODEC_LONG_NAME("Flexible Image Transport System"), .p.type = AVMEDIA_TYPE_VIDEO, .p.id = AV_CODEC_ID_FITS, - .p.capabilities = AV_CODEC_CAP_DR1, + .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE, FF_CODEC_ENCODE_CB(fits_encode_frame), .p.pix_fmts = (const enum AVPixelFormat[]) { AV_PIX_FMT_GBRAP16BE, AV_PIX_FMT_GBRP16BE, diff --git a/libavcodec/flacenc.c b/libavcodec/flacenc.c index 9a9835dfa6e..a449b732353 100644 --- a/libavcodec/flacenc.c +++ b/libavcodec/flacenc.c @@ -1754,7 +1754,8 @@ const FFCodec ff_flac_encoder = { .p.type = AVMEDIA_TYPE_AUDIO, .p.id = AV_CODEC_ID_FLAC, .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_DELAY | - AV_CODEC_CAP_SMALL_LAST_FRAME, + AV_CODEC_CAP_SMALL_LAST_FRAME | + AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE, .priv_data_size = sizeof(FlacEncodeContext), .init = flac_encode_init, FF_CODEC_ENCODE_CB(flac_encode_frame), diff --git a/libavcodec/flashsv2enc.c b/libavcodec/flashsv2enc.c index 668ca6a85ff..46e24a9c1eb 100644 --- a/libavcodec/flashsv2enc.c +++ b/libavcodec/flashsv2enc.c @@ -915,7 +915,7 @@ const FFCodec ff_flashsv2_encoder = { CODEC_LONG_NAME("Flash Screen Video Version 2"), .p.type = AVMEDIA_TYPE_VIDEO, .p.id = AV_CODEC_ID_FLASHSV2, - .p.capabilities = AV_CODEC_CAP_DR1, + .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE, .priv_data_size = sizeof(FlashSV2Context), .init = flashsv2_encode_init, FF_CODEC_ENCODE_CB(flashsv2_encode_frame), diff --git a/libavcodec/flashsvenc.c b/libavcodec/flashsvenc.c index 3a35876d9c5..6192bc25db0 100644 --- a/libavcodec/flashsvenc.c +++ b/libavcodec/flashsvenc.c @@ -251,7 +251,7 @@ const FFCodec ff_flashsv_encoder = { CODEC_LONG_NAME("Flash Screen Video"), .p.type = AVMEDIA_TYPE_VIDEO, .p.id = AV_CODEC_ID_FLASHSV, - .p.capabilities = AV_CODEC_CAP_DR1, + .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE, .priv_data_size = sizeof(FlashSVContext), .init = flashsv_encode_init, FF_CODEC_ENCODE_CB(flashsv_encode_frame), diff --git a/libavcodec/flvenc.c b/libavcodec/flvenc.c index 3329eb0d900..6a96cb0f2f9 100644 --- a/libavcodec/flvenc.c +++ b/libavcodec/flvenc.c @@ -105,4 +105,5 @@ const FFCodec ff_flv_encoder = { .caps_internal = FF_CODEC_CAP_INIT_CLEANUP, .p.pix_fmts = (const enum AVPixelFormat[]) { AV_PIX_FMT_YUV420P, AV_PIX_FMT_NONE}, + .p.capabilities = AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE, }; diff --git a/libavcodec/g722enc.c b/libavcodec/g722enc.c index bc08211b1df..47811cee4d6 100644 --- a/libavcodec/g722enc.c +++ b/libavcodec/g722enc.c @@ -375,7 +375,8 @@ const FFCodec ff_adpcm_g722_encoder = { CODEC_LONG_NAME("G.722 ADPCM"), .p.type = AVMEDIA_TYPE_AUDIO, .p.id = AV_CODEC_ID_ADPCM_G722, - .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_SMALL_LAST_FRAME, + .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_SMALL_LAST_FRAME | + AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE, .priv_data_size = sizeof(G722Context), .init = g722_encode_init, .close = g722_encode_close, diff --git a/libavcodec/g723_1enc.c b/libavcodec/g723_1enc.c index 84660671858..be80153130e 100644 --- a/libavcodec/g723_1enc.c +++ b/libavcodec/g723_1enc.c @@ -1241,7 +1241,7 @@ const FFCodec ff_g723_1_encoder = { CODEC_LONG_NAME("G.723.1"), .p.type = AVMEDIA_TYPE_AUDIO, .p.id = AV_CODEC_ID_G723_1, - .p.capabilities = AV_CODEC_CAP_DR1, + .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE, .priv_data_size = sizeof(G723_1_Context), .init = g723_1_encode_init, FF_CODEC_ENCODE_CB(g723_1_encode_frame), diff --git a/libavcodec/g726.c b/libavcodec/g726.c index 7bbb7f900c8..6c5638760d4 100644 --- a/libavcodec/g726.c +++ b/libavcodec/g726.c @@ -405,7 +405,8 @@ const FFCodec ff_adpcm_g726_encoder = { CODEC_LONG_NAME("G.726 ADPCM"), .p.type = AVMEDIA_TYPE_AUDIO, .p.id = AV_CODEC_ID_ADPCM_G726, - .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_SMALL_LAST_FRAME, + .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_SMALL_LAST_FRAME | + AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE, .priv_data_size = sizeof(G726Context), .init = g726_encode_init, FF_CODEC_ENCODE_CB(g726_encode_frame), @@ -422,7 +423,8 @@ const FFCodec ff_adpcm_g726le_encoder = { CODEC_LONG_NAME("G.726 little endian ADPCM (\"right-justified\")"), .p.type = AVMEDIA_TYPE_AUDIO, .p.id = AV_CODEC_ID_ADPCM_G726LE, - .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_SMALL_LAST_FRAME, + .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_SMALL_LAST_FRAME | + AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE, .priv_data_size = sizeof(G726Context), .init = g726_encode_init, FF_CODEC_ENCODE_CB(g726_encode_frame), diff --git a/libavcodec/gif.c b/libavcodec/gif.c index 7e717d8220d..e17ead0f823 100644 --- a/libavcodec/gif.c +++ b/libavcodec/gif.c @@ -553,7 +553,7 @@ const FFCodec ff_gif_encoder = { CODEC_LONG_NAME("GIF (Graphics Interchange Format)"), .p.type = AVMEDIA_TYPE_VIDEO, .p.id = AV_CODEC_ID_GIF, - .p.capabilities = AV_CODEC_CAP_DR1, + .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE, .priv_data_size = sizeof(GIFContext), .init = gif_encode_init, FF_CODEC_ENCODE_CB(gif_encode_frame), diff --git a/libavcodec/h261enc.c b/libavcodec/h261enc.c index 9d6c9a055f3..438ebb63d91 100644 --- a/libavcodec/h261enc.c +++ b/libavcodec/h261enc.c @@ -413,4 +413,5 @@ const FFCodec ff_h261_encoder = { .caps_internal = FF_CODEC_CAP_INIT_CLEANUP, .p.pix_fmts = (const enum AVPixelFormat[]) { AV_PIX_FMT_YUV420P, AV_PIX_FMT_NONE }, + .p.capabilities = AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE, }; diff --git a/libavcodec/hapenc.c b/libavcodec/hapenc.c index a890dc64926..7de7358e3d9 100644 --- a/libavcodec/hapenc.c +++ b/libavcodec/hapenc.c @@ -351,7 +351,8 @@ const FFCodec ff_hap_encoder = { CODEC_LONG_NAME("Vidvox Hap"), .p.type = AVMEDIA_TYPE_VIDEO, .p.id = AV_CODEC_ID_HAP, - .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_SLICE_THREADS, + .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_SLICE_THREADS | + AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE, .priv_data_size = sizeof(HapContext), .p.priv_class = &hapenc_class, .init = hap_init, diff --git a/libavcodec/hdrenc.c b/libavcodec/hdrenc.c index d8c3111c93f..40d283ee610 100644 --- a/libavcodec/hdrenc.c +++ b/libavcodec/hdrenc.c @@ -177,7 +177,8 @@ const FFCodec ff_hdr_encoder = { .priv_data_size = sizeof(HDREncContext), .p.type = AVMEDIA_TYPE_VIDEO, .p.id = AV_CODEC_ID_RADIANCE_HDR, - .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_FRAME_THREADS, + .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_FRAME_THREADS | + AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE, .init = hdr_encode_init, FF_CODEC_ENCODE_CB(hdr_encode_frame), .close = hdr_encode_close, diff --git a/libavcodec/huffyuvenc.c b/libavcodec/huffyuvenc.c index db274e37ad5..72d6246ebe0 100644 --- a/libavcodec/huffyuvenc.c +++ b/libavcodec/huffyuvenc.c @@ -1082,7 +1082,8 @@ const FFCodec ff_huffyuv_encoder = { CODEC_LONG_NAME("Huffyuv / HuffYUV"), .p.type = AVMEDIA_TYPE_VIDEO, .p.id = AV_CODEC_ID_HUFFYUV, - .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_FRAME_THREADS, + .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_FRAME_THREADS | + AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE, .priv_data_size = sizeof(HYuvEncContext), .init = encode_init, FF_CODEC_ENCODE_CB(encode_frame), @@ -1101,7 +1102,8 @@ const FFCodec ff_ffvhuff_encoder = { CODEC_LONG_NAME("Huffyuv FFmpeg variant"), .p.type = AVMEDIA_TYPE_VIDEO, .p.id = AV_CODEC_ID_FFVHUFF, - .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_FRAME_THREADS, + .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_FRAME_THREADS | + AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE, .priv_data_size = sizeof(HYuvEncContext), .init = encode_init, FF_CODEC_ENCODE_CB(encode_frame), diff --git a/libavcodec/ituh263enc.c b/libavcodec/ituh263enc.c index b52b9da52c4..c30ecad4382 100644 --- a/libavcodec/ituh263enc.c +++ b/libavcodec/ituh263enc.c @@ -903,6 +903,7 @@ const FFCodec ff_h263_encoder = { .p.id = AV_CODEC_ID_H263, .p.pix_fmts = (const enum AVPixelFormat[]){AV_PIX_FMT_YUV420P, AV_PIX_FMT_NONE}, .p.priv_class = &h263_class, + .p.capabilities = AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE, .caps_internal = FF_CODEC_CAP_INIT_CLEANUP, .priv_data_size = sizeof(MpegEncContext), .init = ff_mpv_encode_init, @@ -933,7 +934,7 @@ const FFCodec ff_h263p_encoder = { .p.id = AV_CODEC_ID_H263P, .p.pix_fmts = (const enum AVPixelFormat[]){ AV_PIX_FMT_YUV420P, AV_PIX_FMT_NONE }, .p.priv_class = &h263p_class, - .p.capabilities = AV_CODEC_CAP_SLICE_THREADS, + .p.capabilities = AV_CODEC_CAP_SLICE_THREADS | AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE, .caps_internal = FF_CODEC_CAP_INIT_CLEANUP, .priv_data_size = sizeof(MpegEncContext), .init = ff_mpv_encode_init, diff --git a/libavcodec/j2kenc.c b/libavcodec/j2kenc.c index e883d5deb79..6406f90ac2c 100644 --- a/libavcodec/j2kenc.c +++ b/libavcodec/j2kenc.c @@ -1835,7 +1835,7 @@ const FFCodec ff_jpeg2000_encoder = { CODEC_LONG_NAME("JPEG 2000"), .p.type = AVMEDIA_TYPE_VIDEO, .p.id = AV_CODEC_ID_JPEG2000, - .p.capabilities = AV_CODEC_CAP_DR1, + .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE, .priv_data_size = sizeof(Jpeg2000EncoderContext), .init = j2kenc_init, FF_CODEC_ENCODE_CB(encode_frame), diff --git a/libavcodec/jpeglsenc.c b/libavcodec/jpeglsenc.c index 5ee39ac2d63..53394102df3 100644 --- a/libavcodec/jpeglsenc.c +++ b/libavcodec/jpeglsenc.c @@ -476,7 +476,8 @@ const FFCodec ff_jpegls_encoder = { CODEC_LONG_NAME("JPEG-LS"), .p.type = AVMEDIA_TYPE_VIDEO, .p.id = AV_CODEC_ID_JPEGLS, - .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_FRAME_THREADS, + .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_FRAME_THREADS | + AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE, .priv_data_size = sizeof(JPEGLSContext), .p.priv_class = &jpegls_class, .init = encode_jpegls_init, diff --git a/libavcodec/lclenc.c b/libavcodec/lclenc.c index 2c9add52159..dd5eed9d63c 100644 --- a/libavcodec/lclenc.c +++ b/libavcodec/lclenc.c @@ -156,7 +156,8 @@ const FFCodec ff_zlib_encoder = { CODEC_LONG_NAME("LCL (LossLess Codec Library) ZLIB"), .p.type = AVMEDIA_TYPE_VIDEO, .p.id = AV_CODEC_ID_ZLIB, - .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_FRAME_THREADS, + .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_FRAME_THREADS | + AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE, .priv_data_size = sizeof(LclEncContext), .init = encode_init, FF_CODEC_ENCODE_CB(encode_frame), diff --git a/libavcodec/libcodec2.c b/libavcodec/libcodec2.c index 5728d915c23..83f68e85c79 100644 --- a/libavcodec/libcodec2.c +++ b/libavcodec/libcodec2.c @@ -197,7 +197,8 @@ const FFCodec ff_libcodec2_encoder = { CODEC_LONG_NAME("codec2 encoder using libcodec2"), .p.type = AVMEDIA_TYPE_AUDIO, .p.id = AV_CODEC_ID_CODEC2, - .p.capabilities = AV_CODEC_CAP_DR1, + .p.capabilities = AV_CODEC_CAP_DR1 | + AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE, .p.supported_samplerates = (const int[]){ 8000, 0 }, .p.sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_S16, AV_SAMPLE_FMT_NONE }, .p.ch_layouts = (const AVChannelLayout[]) { AV_CHANNEL_LAYOUT_MONO, { 0 } }, diff --git a/libavcodec/libgsmenc.c b/libavcodec/libgsmenc.c index bd3b1420aab..640954491a7 100644 --- a/libavcodec/libgsmenc.c +++ b/libavcodec/libgsmenc.c @@ -122,7 +122,7 @@ const FFCodec ff_libgsm_encoder = { CODEC_LONG_NAME("libgsm GSM"), .p.type = AVMEDIA_TYPE_AUDIO, .p.id = AV_CODEC_ID_GSM, - .p.capabilities = AV_CODEC_CAP_DR1, + .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE, .init = libgsm_encode_init, FF_CODEC_ENCODE_CB(libgsm_encode_frame), .close = libgsm_encode_close, @@ -141,7 +141,7 @@ const FFCodec ff_libgsm_ms_encoder = { CODEC_LONG_NAME("libgsm GSM Microsoft variant"), .p.type = AVMEDIA_TYPE_AUDIO, .p.id = AV_CODEC_ID_GSM_MS, - .p.capabilities = AV_CODEC_CAP_DR1, + .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE, .init = libgsm_encode_init, FF_CODEC_ENCODE_CB(libgsm_encode_frame), .close = libgsm_encode_close, diff --git a/libavcodec/libilbc.c b/libavcodec/libilbc.c index 9ef6e16bc54..9ca90bf0c66 100644 --- a/libavcodec/libilbc.c +++ b/libavcodec/libilbc.c @@ -205,7 +205,7 @@ const FFCodec ff_libilbc_encoder = { CODEC_LONG_NAME("iLBC (Internet Low Bitrate Codec)"), .p.type = AVMEDIA_TYPE_AUDIO, .p.id = AV_CODEC_ID_ILBC, - .p.capabilities = AV_CODEC_CAP_DR1, + .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE, .caps_internal = FF_CODEC_CAP_NOT_INIT_THREADSAFE, .priv_data_size = sizeof(ILBCEncContext), .init = ilbc_encode_init, diff --git a/libavcodec/libjxlenc.c b/libavcodec/libjxlenc.c index 0793ed251b0..06581b268d2 100644 --- a/libavcodec/libjxlenc.c +++ b/libavcodec/libjxlenc.c @@ -467,7 +467,8 @@ const FFCodec ff_libjxl_encoder = { .init = libjxl_encode_init, FF_CODEC_ENCODE_CB(libjxl_encode_frame), .close = libjxl_encode_close, - .p.capabilities = AV_CODEC_CAP_OTHER_THREADS, + .p.capabilities = AV_CODEC_CAP_OTHER_THREADS | + AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE, .caps_internal = FF_CODEC_CAP_NOT_INIT_THREADSAFE | FF_CODEC_CAP_AUTO_THREADS | FF_CODEC_CAP_INIT_CLEANUP | FF_CODEC_CAP_ICC_PROFILES, diff --git a/libavcodec/libopenh264enc.c b/libavcodec/libopenh264enc.c index bbd69695682..6934fd481ce 100644 --- a/libavcodec/libopenh264enc.c +++ b/libavcodec/libopenh264enc.c @@ -456,7 +456,8 @@ const FFCodec ff_libopenh264_encoder = { CODEC_LONG_NAME("OpenH264 H.264 / AVC / MPEG-4 AVC / MPEG-4 part 10"), .p.type = AVMEDIA_TYPE_VIDEO, .p.id = AV_CODEC_ID_H264, - .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_OTHER_THREADS, + .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_OTHER_THREADS | + AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE, .priv_data_size = sizeof(SVCContext), .init = svc_encode_init, FF_CODEC_ENCODE_CB(svc_encode_frame), diff --git a/libavcodec/libopenjpegenc.c b/libavcodec/libopenjpegenc.c index 6f77780391f..009c7a43774 100644 --- a/libavcodec/libopenjpegenc.c +++ b/libavcodec/libopenjpegenc.c @@ -763,7 +763,8 @@ const FFCodec ff_libopenjpeg_encoder = { .priv_data_size = sizeof(LibOpenJPEGContext), .init = libopenjpeg_encode_init, FF_CODEC_ENCODE_CB(libopenjpeg_encode_frame), - .p.capabilities = AV_CODEC_CAP_FRAME_THREADS, + .p.capabilities = AV_CODEC_CAP_FRAME_THREADS | + AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE, .p.pix_fmts = (const enum AVPixelFormat[]) { AV_PIX_FMT_RGB24, AV_PIX_FMT_RGBA, AV_PIX_FMT_RGB48, AV_PIX_FMT_RGBA64, AV_PIX_FMT_GBR24P, diff --git a/libavcodec/libvo-amrwbenc.c b/libavcodec/libvo-amrwbenc.c index 76a6b69994c..02b8941a6d2 100644 --- a/libavcodec/libvo-amrwbenc.c +++ b/libavcodec/libvo-amrwbenc.c @@ -144,7 +144,8 @@ const FFCodec ff_libvo_amrwbenc_encoder = { CODEC_LONG_NAME("Android VisualOn AMR-WB (Adaptive Multi-Rate Wide-Band)"), .p.type = AVMEDIA_TYPE_AUDIO, .p.id = AV_CODEC_ID_AMR_WB, - .p.capabilities = AV_CODEC_CAP_DR1, + .p.capabilities = AV_CODEC_CAP_DR1 | + AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE, .p.priv_class = &amrwb_class, .p.wrapper_name = "libvo_amrwbenc", .caps_internal = FF_CODEC_CAP_NOT_INIT_THREADSAFE, diff --git a/libavcodec/libwebpenc.c b/libavcodec/libwebpenc.c index ee5795f0418..d6edd866037 100644 --- a/libavcodec/libwebpenc.c +++ b/libavcodec/libwebpenc.c @@ -92,7 +92,7 @@ const FFCodec ff_libwebp_encoder = { CODEC_LONG_NAME("libwebp WebP image"), .p.type = AVMEDIA_TYPE_VIDEO, .p.id = AV_CODEC_ID_WEBP, - .p.capabilities = AV_CODEC_CAP_DR1, + .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE, .p.pix_fmts = ff_libwebpenc_pix_fmts, .p.priv_class = &ff_libwebpenc_class, .p.wrapper_name = "libwebp", diff --git a/libavcodec/libxvid.c b/libavcodec/libxvid.c index 4e04b3c0989..aba875b6b85 100644 --- a/libavcodec/libxvid.c +++ b/libavcodec/libxvid.c @@ -902,7 +902,7 @@ const FFCodec ff_libxvid_encoder = { CODEC_LONG_NAME("libxvidcore MPEG-4 part 2"), .p.type = AVMEDIA_TYPE_VIDEO, .p.id = AV_CODEC_ID_MPEG4, - .p.capabilities = AV_CODEC_CAP_DR1, + .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE, .priv_data_size = sizeof(struct xvid_context), .init = xvid_encode_init, FF_CODEC_ENCODE_CB(xvid_encode_frame), diff --git a/libavcodec/ljpegenc.c b/libavcodec/ljpegenc.c index 81c52a7c784..aa62beac71e 100644 --- a/libavcodec/ljpegenc.c +++ b/libavcodec/ljpegenc.c @@ -316,7 +316,8 @@ const FFCodec ff_ljpeg_encoder = { CODEC_LONG_NAME("Lossless JPEG"), .p.type = AVMEDIA_TYPE_VIDEO, .p.id = AV_CODEC_ID_LJPEG, - .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_FRAME_THREADS, + .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_FRAME_THREADS | + AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE, .priv_data_size = sizeof(LJpegEncContext), .p.priv_class = &ljpeg_class, .init = ljpeg_encode_init, diff --git a/libavcodec/magicyuvenc.c b/libavcodec/magicyuvenc.c index 7f9ff72834f..9e41c1b0fe7 100644 --- a/libavcodec/magicyuvenc.c +++ b/libavcodec/magicyuvenc.c @@ -569,7 +569,8 @@ const FFCodec ff_magicyuv_encoder = { CODEC_LONG_NAME("MagicYUV video"), .p.type = AVMEDIA_TYPE_VIDEO, .p.id = AV_CODEC_ID_MAGICYUV, - .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_FRAME_THREADS, + .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_FRAME_THREADS | + AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE, .priv_data_size = sizeof(MagicYUVContext), .p.priv_class = &magicyuv_class, .init = magy_encode_init, diff --git a/libavcodec/mjpegenc.c b/libavcodec/mjpegenc.c index eafe7130e2c..508772987f3 100644 --- a/libavcodec/mjpegenc.c +++ b/libavcodec/mjpegenc.c @@ -651,7 +651,8 @@ const FFCodec ff_mjpeg_encoder = { .init = ff_mpv_encode_init, FF_CODEC_ENCODE_CB(ff_mpv_encode_picture), .close = mjpeg_encode_close, - .p.capabilities = AV_CODEC_CAP_SLICE_THREADS | AV_CODEC_CAP_FRAME_THREADS, + .p.capabilities = AV_CODEC_CAP_SLICE_THREADS | AV_CODEC_CAP_FRAME_THREADS | + AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE, .caps_internal = FF_CODEC_CAP_INIT_CLEANUP | FF_CODEC_CAP_ICC_PROFILES, .p.pix_fmts = (const enum AVPixelFormat[]) { AV_PIX_FMT_YUVJ420P, AV_PIX_FMT_YUVJ422P, AV_PIX_FMT_YUVJ444P, @@ -685,5 +686,6 @@ const FFCodec ff_amv_encoder = { AV_PIX_FMT_YUVJ420P, AV_PIX_FMT_NONE }, .p.priv_class = &amv_class, + .p.capabilities = AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE, }; #endif diff --git a/libavcodec/mpegaudioenc_fixed.c b/libavcodec/mpegaudioenc_fixed.c index afbffe766bb..a523b5d5338 100644 --- a/libavcodec/mpegaudioenc_fixed.c +++ b/libavcodec/mpegaudioenc_fixed.c @@ -28,7 +28,7 @@ const FFCodec ff_mp2fixed_encoder = { CODEC_LONG_NAME("MP2 fixed point (MPEG audio layer 2)"), .p.type = AVMEDIA_TYPE_AUDIO, .p.id = AV_CODEC_ID_MP2, - .p.capabilities = AV_CODEC_CAP_DR1, + .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE, .priv_data_size = sizeof(MpegAudioContext), .init = MPA_encode_init, FF_CODEC_ENCODE_CB(MPA_encode_frame), diff --git a/libavcodec/mpegaudioenc_float.c b/libavcodec/mpegaudioenc_float.c index 212709c2916..6a13d095738 100644 --- a/libavcodec/mpegaudioenc_float.c +++ b/libavcodec/mpegaudioenc_float.c @@ -29,7 +29,7 @@ const FFCodec ff_mp2_encoder = { CODEC_LONG_NAME("MP2 (MPEG audio layer 2)"), .p.type = AVMEDIA_TYPE_AUDIO, .p.id = AV_CODEC_ID_MP2, - .p.capabilities = AV_CODEC_CAP_DR1, + .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE, .priv_data_size = sizeof(MpegAudioContext), .init = MPA_encode_init, FF_CODEC_ENCODE_CB(MPA_encode_frame), diff --git a/libavcodec/msmpeg4enc.c b/libavcodec/msmpeg4enc.c index 8798b151521..54121438a0c 100644 --- a/libavcodec/msmpeg4enc.c +++ b/libavcodec/msmpeg4enc.c @@ -684,6 +684,7 @@ const FFCodec ff_msmpeg4v2_encoder = { .p.id = AV_CODEC_ID_MSMPEG4V2, .p.pix_fmts = (const enum AVPixelFormat[]){ AV_PIX_FMT_YUV420P, AV_PIX_FMT_NONE }, .p.priv_class = &ff_mpv_enc_class, + .p.capabilities = AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE, .caps_internal = FF_CODEC_CAP_INIT_CLEANUP, .priv_data_size = sizeof(MSMPEG4EncContext), .init = ff_mpv_encode_init, @@ -698,6 +699,7 @@ const FFCodec ff_msmpeg4v3_encoder = { .p.id = AV_CODEC_ID_MSMPEG4V3, .p.pix_fmts = (const enum AVPixelFormat[]){ AV_PIX_FMT_YUV420P, AV_PIX_FMT_NONE }, .p.priv_class = &ff_mpv_enc_class, + .p.capabilities = AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE, .caps_internal = FF_CODEC_CAP_INIT_CLEANUP, .priv_data_size = sizeof(MSMPEG4EncContext), .init = ff_mpv_encode_init, @@ -712,6 +714,7 @@ const FFCodec ff_wmv1_encoder = { .p.id = AV_CODEC_ID_WMV1, .p.pix_fmts = (const enum AVPixelFormat[]){ AV_PIX_FMT_YUV420P, AV_PIX_FMT_NONE }, .p.priv_class = &ff_mpv_enc_class, + .p.capabilities = AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE, .caps_internal = FF_CODEC_CAP_INIT_CLEANUP, .priv_data_size = sizeof(MSMPEG4EncContext), .init = ff_mpv_encode_init, diff --git a/libavcodec/msvideo1enc.c b/libavcodec/msvideo1enc.c index a349b42ca0d..36cfd39a854 100644 --- a/libavcodec/msvideo1enc.c +++ b/libavcodec/msvideo1enc.c @@ -307,6 +307,7 @@ const FFCodec ff_msvideo1_encoder = { CODEC_LONG_NAME("Microsoft Video-1"), .p.type = AVMEDIA_TYPE_VIDEO, .p.id = AV_CODEC_ID_MSVIDEO1, + .p.capabilities = AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE, .priv_data_size = sizeof(Msvideo1EncContext), .init = encode_init, FF_CODEC_ENCODE_CB(encode_frame), diff --git a/libavcodec/pamenc.c b/libavcodec/pamenc.c index 7d01e89f742..45ec29ccb38 100644 --- a/libavcodec/pamenc.c +++ b/libavcodec/pamenc.c @@ -133,7 +133,7 @@ const FFCodec ff_pam_encoder = { CODEC_LONG_NAME("PAM (Portable AnyMap) image"), .p.type = AVMEDIA_TYPE_VIDEO, .p.id = AV_CODEC_ID_PAM, - .p.capabilities = AV_CODEC_CAP_DR1, + .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE, FF_CODEC_ENCODE_CB(pam_encode_frame), .p.pix_fmts = (const enum AVPixelFormat[]){ AV_PIX_FMT_RGB24, AV_PIX_FMT_RGBA, diff --git a/libavcodec/pcm-blurayenc.c b/libavcodec/pcm-blurayenc.c index 62e86e722f3..bfbfa91d7ac 100644 --- a/libavcodec/pcm-blurayenc.c +++ b/libavcodec/pcm-blurayenc.c @@ -304,5 +304,5 @@ const FFCodec ff_pcm_bluray_encoder = { { 0 } }, .p.sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_S16, AV_SAMPLE_FMT_S32, AV_SAMPLE_FMT_NONE }, - .p.capabilities = AV_CODEC_CAP_DR1, + .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE, }; diff --git a/libavcodec/pcm-dvdenc.c b/libavcodec/pcm-dvdenc.c index 011d0a2f00e..a2e5cbdc2e9 100644 --- a/libavcodec/pcm-dvdenc.c +++ b/libavcodec/pcm-dvdenc.c @@ -176,7 +176,8 @@ const FFCodec ff_pcm_dvd_encoder = { CODEC_LONG_NAME("PCM signed 16|20|24-bit big-endian for DVD media"), .p.type = AVMEDIA_TYPE_AUDIO, .p.id = AV_CODEC_ID_PCM_DVD, - .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_SMALL_LAST_FRAME, + .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_SMALL_LAST_FRAME | + AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE, .priv_data_size = sizeof(PCMDVDContext), .init = pcm_dvd_encode_init, FF_CODEC_ENCODE_CB(pcm_dvd_encode_frame), diff --git a/libavcodec/pcm.c b/libavcodec/pcm.c index ee36a364c8d..23955ba2ddf 100644 --- a/libavcodec/pcm.c +++ b/libavcodec/pcm.c @@ -553,7 +553,8 @@ const FFCodec ff_ ## name_ ## _encoder = { \ CODEC_LONG_NAME(long_name_), \ .p.type = AVMEDIA_TYPE_AUDIO, \ .p.id = AV_CODEC_ID_ ## id_, \ - .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_VARIABLE_FRAME_SIZE, \ + .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_VARIABLE_FRAME_SIZE | \ + AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE, \ .init = pcm_encode_init, \ FF_CODEC_ENCODE_CB(pcm_encode_frame), \ .p.sample_fmts = (const enum AVSampleFormat[]){ sample_fmt_, \ diff --git a/libavcodec/pcxenc.c b/libavcodec/pcxenc.c index 509158ba0f2..cf9b41b752b 100644 --- a/libavcodec/pcxenc.c +++ b/libavcodec/pcxenc.c @@ -197,7 +197,7 @@ const FFCodec ff_pcx_encoder = { CODEC_LONG_NAME("PC Paintbrush PCX image"), .p.type = AVMEDIA_TYPE_VIDEO, .p.id = AV_CODEC_ID_PCX, - .p.capabilities = AV_CODEC_CAP_DR1, + .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE, FF_CODEC_ENCODE_CB(pcx_encode_frame), .p.pix_fmts = (const enum AVPixelFormat[]){ AV_PIX_FMT_RGB24, diff --git a/libavcodec/pngenc.c b/libavcodec/pngenc.c index 0ce684342ef..5166698b8a2 100644 --- a/libavcodec/pngenc.c +++ b/libavcodec/pngenc.c @@ -1183,7 +1183,8 @@ const FFCodec ff_png_encoder = { CODEC_LONG_NAME("PNG (Portable Network Graphics) image"), .p.type = AVMEDIA_TYPE_VIDEO, .p.id = AV_CODEC_ID_PNG, - .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_FRAME_THREADS, + .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_FRAME_THREADS | + AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE, .priv_data_size = sizeof(PNGEncContext), .init = png_enc_init, .close = png_enc_close, diff --git a/libavcodec/pnmenc.c b/libavcodec/pnmenc.c index 4bdd2e032f3..9e1b11382b1 100644 --- a/libavcodec/pnmenc.c +++ b/libavcodec/pnmenc.c @@ -229,7 +229,7 @@ const FFCodec ff_pgm_encoder = { CODEC_LONG_NAME("PGM (Portable GrayMap) image"), .p.type = AVMEDIA_TYPE_VIDEO, .p.id = AV_CODEC_ID_PGM, - .p.capabilities = AV_CODEC_CAP_DR1, + .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE, FF_CODEC_ENCODE_CB(pnm_encode_frame), .p.pix_fmts = (const enum AVPixelFormat[]){ AV_PIX_FMT_GRAY8, AV_PIX_FMT_GRAY16BE, AV_PIX_FMT_NONE @@ -243,7 +243,7 @@ const FFCodec ff_pgmyuv_encoder = { CODEC_LONG_NAME("PGMYUV (Portable GrayMap YUV) image"), .p.type = AVMEDIA_TYPE_VIDEO, .p.id = AV_CODEC_ID_PGMYUV, - .p.capabilities = AV_CODEC_CAP_DR1, + .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE, FF_CODEC_ENCODE_CB(pnm_encode_frame), .p.pix_fmts = (const enum AVPixelFormat[]){ AV_PIX_FMT_YUV420P, AV_PIX_FMT_YUV420P16BE, AV_PIX_FMT_NONE @@ -257,7 +257,7 @@ const FFCodec ff_ppm_encoder = { CODEC_LONG_NAME("PPM (Portable PixelMap) image"), .p.type = AVMEDIA_TYPE_VIDEO, .p.id = AV_CODEC_ID_PPM, - .p.capabilities = AV_CODEC_CAP_DR1, + .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE, FF_CODEC_ENCODE_CB(pnm_encode_frame), .p.pix_fmts = (const enum AVPixelFormat[]){ AV_PIX_FMT_RGB24, AV_PIX_FMT_RGB48BE, AV_PIX_FMT_NONE @@ -271,7 +271,7 @@ const FFCodec ff_pbm_encoder = { CODEC_LONG_NAME("PBM (Portable BitMap) image"), .p.type = AVMEDIA_TYPE_VIDEO, .p.id = AV_CODEC_ID_PBM, - .p.capabilities = AV_CODEC_CAP_DR1, + .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE, FF_CODEC_ENCODE_CB(pnm_encode_frame), .p.pix_fmts = (const enum AVPixelFormat[]){ AV_PIX_FMT_MONOWHITE, AV_PIX_FMT_NONE }, @@ -284,7 +284,7 @@ const FFCodec ff_pfm_encoder = { CODEC_LONG_NAME("PFM (Portable FloatMap) image"), .p.type = AVMEDIA_TYPE_VIDEO, .p.id = AV_CODEC_ID_PFM, - .p.capabilities = AV_CODEC_CAP_DR1, + .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE, FF_CODEC_ENCODE_CB(pnm_encode_frame), .p.pix_fmts = (const enum AVPixelFormat[]){ AV_PIX_FMT_GBRPF32LE, AV_PIX_FMT_GRAYF32LE, @@ -309,7 +309,7 @@ const FFCodec ff_phm_encoder = { CODEC_LONG_NAME("PHM (Portable HalfFloatMap) image"), .p.type = AVMEDIA_TYPE_VIDEO, .p.id = AV_CODEC_ID_PHM, - .p.capabilities = AV_CODEC_CAP_DR1, + .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE, .priv_data_size = sizeof(PHMEncContext), .init = phm_enc_init, FF_CODEC_ENCODE_CB(pnm_encode_frame), diff --git a/libavcodec/proresenc_anatoliy.c b/libavcodec/proresenc_anatoliy.c index bd1b70cc5dc..09196c7aa11 100644 --- a/libavcodec/proresenc_anatoliy.c +++ b/libavcodec/proresenc_anatoliy.c @@ -944,7 +944,8 @@ const FFCodec ff_prores_aw_encoder = { CODEC_LONG_NAME("Apple ProRes"), .p.type = AVMEDIA_TYPE_VIDEO, .p.id = AV_CODEC_ID_PRORES, - .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_FRAME_THREADS, + .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_FRAME_THREADS | + AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE, .p.pix_fmts = pix_fmts, .priv_data_size = sizeof(ProresContext), .init = prores_encode_init, @@ -960,7 +961,8 @@ const FFCodec ff_prores_encoder = { CODEC_LONG_NAME("Apple ProRes"), .p.type = AVMEDIA_TYPE_VIDEO, .p.id = AV_CODEC_ID_PRORES, - .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_FRAME_THREADS, + .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_FRAME_THREADS | + AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE, .p.pix_fmts = pix_fmts, .priv_data_size = sizeof(ProresContext), .init = prores_encode_init, diff --git a/libavcodec/proresenc_kostya.c b/libavcodec/proresenc_kostya.c index 5b38437d0aa..1940e0378a0 100644 --- a/libavcodec/proresenc_kostya.c +++ b/libavcodec/proresenc_kostya.c @@ -1428,7 +1428,8 @@ const FFCodec ff_prores_ks_encoder = { .init = encode_init, .close = encode_close, FF_CODEC_ENCODE_CB(encode_frame), - .p.capabilities = AV_CODEC_CAP_SLICE_THREADS | AV_CODEC_CAP_FRAME_THREADS, + .p.capabilities = AV_CODEC_CAP_SLICE_THREADS | AV_CODEC_CAP_FRAME_THREADS | + AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE, .p.pix_fmts = (const enum AVPixelFormat[]) { AV_PIX_FMT_YUV422P10, AV_PIX_FMT_YUV444P10, AV_PIX_FMT_YUVA444P10, AV_PIX_FMT_NONE diff --git a/libavcodec/qoienc.c b/libavcodec/qoienc.c index 6d574e0da9e..b9efdc2fa52 100644 --- a/libavcodec/qoienc.c +++ b/libavcodec/qoienc.c @@ -131,7 +131,8 @@ const FFCodec ff_qoi_encoder = { CODEC_LONG_NAME("QOI (Quite OK Image format) image"), .p.type = AVMEDIA_TYPE_VIDEO, .p.id = AV_CODEC_ID_QOI, - .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_FRAME_THREADS, + .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_FRAME_THREADS | + AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE, FF_CODEC_ENCODE_CB(qoi_encode_frame), .p.pix_fmts = (const enum AVPixelFormat[]){ AV_PIX_FMT_RGBA, AV_PIX_FMT_RGB24, diff --git a/libavcodec/qtrleenc.c b/libavcodec/qtrleenc.c index 855494d3df8..3d51fcf8434 100644 --- a/libavcodec/qtrleenc.c +++ b/libavcodec/qtrleenc.c @@ -404,7 +404,7 @@ const FFCodec ff_qtrle_encoder = { CODEC_LONG_NAME("QuickTime Animation (RLE) video"), .p.type = AVMEDIA_TYPE_VIDEO, .p.id = AV_CODEC_ID_QTRLE, - .p.capabilities = AV_CODEC_CAP_DR1, + .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE, .priv_data_size = sizeof(QtrleEncContext), .init = qtrle_encode_init, FF_CODEC_ENCODE_CB(qtrle_encode_frame), diff --git a/libavcodec/r210enc.c b/libavcodec/r210enc.c index d87f42ce4a8..91e34528741 100644 --- a/libavcodec/r210enc.c +++ b/libavcodec/r210enc.c @@ -96,7 +96,7 @@ const FFCodec ff_r210_encoder = { CODEC_LONG_NAME("Uncompressed RGB 10-bit"), .p.type = AVMEDIA_TYPE_VIDEO, .p.id = AV_CODEC_ID_R210, - .p.capabilities = AV_CODEC_CAP_DR1, + .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE, .init = encode_init, FF_CODEC_ENCODE_CB(encode_frame), .p.pix_fmts = pix_fmt, @@ -108,7 +108,7 @@ const FFCodec ff_r10k_encoder = { CODEC_LONG_NAME("AJA Kona 10-bit RGB Codec"), .p.type = AVMEDIA_TYPE_VIDEO, .p.id = AV_CODEC_ID_R10K, - .p.capabilities = AV_CODEC_CAP_DR1, + .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE, .init = encode_init, FF_CODEC_ENCODE_CB(encode_frame), .p.pix_fmts = pix_fmt, @@ -120,7 +120,7 @@ const FFCodec ff_avrp_encoder = { CODEC_LONG_NAME("Avid 1:1 10-bit RGB Packer"), .p.type = AVMEDIA_TYPE_VIDEO, .p.id = AV_CODEC_ID_AVRP, - .p.capabilities = AV_CODEC_CAP_DR1, + .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE, .init = encode_init, FF_CODEC_ENCODE_CB(encode_frame), .p.pix_fmts = pix_fmt, diff --git a/libavcodec/rawenc.c b/libavcodec/rawenc.c index c2643e6d803..8c577006d92 100644 --- a/libavcodec/rawenc.c +++ b/libavcodec/rawenc.c @@ -86,7 +86,8 @@ const FFCodec ff_rawvideo_encoder = { CODEC_LONG_NAME("raw video"), .p.type = AVMEDIA_TYPE_VIDEO, .p.id = AV_CODEC_ID_RAWVIDEO, - .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_FRAME_THREADS, + .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_FRAME_THREADS | + AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE, .init = raw_encode_init, FF_CODEC_ENCODE_CB(raw_encode), }; diff --git a/libavcodec/roqvideoenc.c b/libavcodec/roqvideoenc.c index 273686a1476..c25aa39b735 100644 --- a/libavcodec/roqvideoenc.c +++ b/libavcodec/roqvideoenc.c @@ -1122,7 +1122,7 @@ const FFCodec ff_roq_encoder = { CODEC_LONG_NAME("id RoQ video"), .p.type = AVMEDIA_TYPE_VIDEO, .p.id = AV_CODEC_ID_ROQ, - .p.capabilities = AV_CODEC_CAP_DR1, + .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE, .priv_data_size = sizeof(RoqEncContext), .init = roq_encode_init, FF_CODEC_ENCODE_CB(roq_encode_frame), diff --git a/libavcodec/rpzaenc.c b/libavcodec/rpzaenc.c index 1ea579d2d38..da9500e4242 100644 --- a/libavcodec/rpzaenc.c +++ b/libavcodec/rpzaenc.c @@ -873,7 +873,7 @@ const FFCodec ff_rpza_encoder = { CODEC_LONG_NAME("QuickTime video (RPZA)"), .p.type = AVMEDIA_TYPE_VIDEO, .p.id = AV_CODEC_ID_RPZA, - .p.capabilities = AV_CODEC_CAP_DR1, + .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE, .priv_data_size = sizeof(RpzaContext), .p.priv_class = &rpza_class, .init = rpza_encode_init, diff --git a/libavcodec/rv10enc.c b/libavcodec/rv10enc.c index 7f7477ad7bf..8a405b86867 100644 --- a/libavcodec/rv10enc.c +++ b/libavcodec/rv10enc.c @@ -71,6 +71,7 @@ const FFCodec ff_rv10_encoder = { .p.type = AVMEDIA_TYPE_VIDEO, .p.id = AV_CODEC_ID_RV10, .p.priv_class = &ff_mpv_enc_class, + .p.capabilities = AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE, .priv_data_size = sizeof(MpegEncContext), .init = ff_mpv_encode_init, FF_CODEC_ENCODE_CB(ff_mpv_encode_picture), diff --git a/libavcodec/rv20enc.c b/libavcodec/rv20enc.c index b1b88819dba..dc26877d5e6 100644 --- a/libavcodec/rv20enc.c +++ b/libavcodec/rv20enc.c @@ -68,6 +68,7 @@ const FFCodec ff_rv20_encoder = { .p.type = AVMEDIA_TYPE_VIDEO, .p.id = AV_CODEC_ID_RV20, .p.priv_class = &ff_mpv_enc_class, + .p.capabilities = AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE, .priv_data_size = sizeof(MpegEncContext), .init = ff_mpv_encode_init, FF_CODEC_ENCODE_CB(ff_mpv_encode_picture), diff --git a/libavcodec/s302menc.c b/libavcodec/s302menc.c index 3bd657f9458..4b8996f9ac8 100644 --- a/libavcodec/s302menc.c +++ b/libavcodec/s302menc.c @@ -176,7 +176,8 @@ const FFCodec ff_s302m_encoder = { .p.type = AVMEDIA_TYPE_AUDIO, .p.id = AV_CODEC_ID_S302M, .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_EXPERIMENTAL | - AV_CODEC_CAP_VARIABLE_FRAME_SIZE, + AV_CODEC_CAP_VARIABLE_FRAME_SIZE | + AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE, .priv_data_size = sizeof(S302MEncContext), .init = s302m_encode_init, FF_CODEC_ENCODE_CB(s302m_encode2_frame), diff --git a/libavcodec/sbcenc.c b/libavcodec/sbcenc.c index 721c97e1ea3..fccb0e3ea3f 100644 --- a/libavcodec/sbcenc.c +++ b/libavcodec/sbcenc.c @@ -348,7 +348,8 @@ const FFCodec ff_sbc_encoder = { CODEC_LONG_NAME("SBC (low-complexity subband codec)"), .p.type = AVMEDIA_TYPE_AUDIO, .p.id = AV_CODEC_ID_SBC, - .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_SMALL_LAST_FRAME, + .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_SMALL_LAST_FRAME | + AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE, .priv_data_size = sizeof(SBCEncContext), .init = sbc_encode_init, FF_CODEC_ENCODE_CB(sbc_encode_frame), diff --git a/libavcodec/sgienc.c b/libavcodec/sgienc.c index 901e0a74f94..5bbb72c03a6 100644 --- a/libavcodec/sgienc.c +++ b/libavcodec/sgienc.c @@ -275,7 +275,7 @@ const FFCodec ff_sgi_encoder = { CODEC_LONG_NAME("SGI image"), .p.type = AVMEDIA_TYPE_VIDEO, .p.id = AV_CODEC_ID_SGI, - .p.capabilities = AV_CODEC_CAP_DR1, + .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE, .priv_data_size = sizeof(SgiContext), .p.priv_class = &sgi_class, .init = encode_init, diff --git a/libavcodec/smcenc.c b/libavcodec/smcenc.c index e3ea7e5e9f4..3e8b5afcf67 100644 --- a/libavcodec/smcenc.c +++ b/libavcodec/smcenc.c @@ -595,7 +595,7 @@ const FFCodec ff_smc_encoder = { CODEC_LONG_NAME("QuickTime Graphics (SMC)"), .p.type = AVMEDIA_TYPE_VIDEO, .p.id = AV_CODEC_ID_SMC, - .p.capabilities = AV_CODEC_CAP_DR1, + .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE, .priv_data_size = sizeof(SMCContext), .init = smc_encode_init, FF_CODEC_ENCODE_CB(smc_encode_frame), diff --git a/libavcodec/snowenc.c b/libavcodec/snowenc.c index 7fad95b69a8..749c8067d2d 100644 --- a/libavcodec/snowenc.c +++ b/libavcodec/snowenc.c @@ -1935,7 +1935,7 @@ const FFCodec ff_snow_encoder = { CODEC_LONG_NAME("Snow"), .p.type = AVMEDIA_TYPE_VIDEO, .p.id = AV_CODEC_ID_SNOW, - .p.capabilities = AV_CODEC_CAP_DR1, + .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE, .priv_data_size = sizeof(SnowContext), .init = encode_init, FF_CODEC_ENCODE_CB(encode_frame), diff --git a/libavcodec/sonic.c b/libavcodec/sonic.c index 77bdb418a7e..62e6193ac63 100644 --- a/libavcodec/sonic.c +++ b/libavcodec/sonic.c @@ -1096,7 +1096,8 @@ const FFCodec ff_sonic_encoder = { CODEC_LONG_NAME("Sonic"), .p.type = AVMEDIA_TYPE_AUDIO, .p.id = AV_CODEC_ID_SONIC, - .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_EXPERIMENTAL, + .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_EXPERIMENTAL | + AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE, .priv_data_size = sizeof(SonicContext), .init = sonic_encode_init, FF_CODEC_ENCODE_CB(sonic_encode_frame), @@ -1112,7 +1113,8 @@ const FFCodec ff_sonic_ls_encoder = { CODEC_LONG_NAME("Sonic lossless"), .p.type = AVMEDIA_TYPE_AUDIO, .p.id = AV_CODEC_ID_SONIC_LS, - .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_EXPERIMENTAL, + .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_EXPERIMENTAL | + AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE, .priv_data_size = sizeof(SonicContext), .init = sonic_encode_init, FF_CODEC_ENCODE_CB(sonic_encode_frame), diff --git a/libavcodec/speedhqenc.c b/libavcodec/speedhqenc.c index 7269e345d37..5b4ff4c139e 100644 --- a/libavcodec/speedhqenc.c +++ b/libavcodec/speedhqenc.c @@ -288,6 +288,7 @@ const FFCodec ff_speedhq_encoder = { .p.type = AVMEDIA_TYPE_VIDEO, .p.id = AV_CODEC_ID_SPEEDHQ, .p.priv_class = &ff_mpv_enc_class, + .p.capabilities = AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE, .priv_data_size = sizeof(SpeedHQEncContext), .init = ff_mpv_encode_init, FF_CODEC_ENCODE_CB(ff_mpv_encode_picture), diff --git a/libavcodec/sunrastenc.c b/libavcodec/sunrastenc.c index 9b82f9921a3..b2d57f7235d 100644 --- a/libavcodec/sunrastenc.c +++ b/libavcodec/sunrastenc.c @@ -213,7 +213,7 @@ const FFCodec ff_sunrast_encoder = { CODEC_LONG_NAME("Sun Rasterfile image"), .p.type = AVMEDIA_TYPE_VIDEO, .p.id = AV_CODEC_ID_SUNRAST, - .p.capabilities = AV_CODEC_CAP_DR1, + .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE, .priv_data_size = sizeof(SUNRASTContext), .init = sunrast_encode_init, FF_CODEC_ENCODE_CB(sunrast_encode_frame), diff --git a/libavcodec/svq1enc.c b/libavcodec/svq1enc.c index 8f09e634a59..e3ea0c1e474 100644 --- a/libavcodec/svq1enc.c +++ b/libavcodec/svq1enc.c @@ -752,7 +752,7 @@ const FFCodec ff_svq1_encoder = { CODEC_LONG_NAME("Sorenson Vector Quantizer 1 / Sorenson Video 1 / SVQ1"), .p.type = AVMEDIA_TYPE_VIDEO, .p.id = AV_CODEC_ID_SVQ1, - .p.capabilities = AV_CODEC_CAP_DR1, + .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE, .priv_data_size = sizeof(SVQ1EncContext), .p.priv_class = &svq1enc_class, .init = svq1_encode_init, diff --git a/libavcodec/targaenc.c b/libavcodec/targaenc.c index bb3cb931878..d9c500b97de 100644 --- a/libavcodec/targaenc.c +++ b/libavcodec/targaenc.c @@ -207,7 +207,7 @@ const FFCodec ff_targa_encoder = { CODEC_LONG_NAME("Truevision Targa image"), .p.type = AVMEDIA_TYPE_VIDEO, .p.id = AV_CODEC_ID_TARGA, - .p.capabilities = AV_CODEC_CAP_DR1, + .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE, .priv_data_size = sizeof(TargaContext), .p.priv_class = &targa_class, .init = targa_encode_init, diff --git a/libavcodec/tiffenc.c b/libavcodec/tiffenc.c index 6dfbdaeb409..06d7dcc99d8 100644 --- a/libavcodec/tiffenc.c +++ b/libavcodec/tiffenc.c @@ -574,7 +574,8 @@ const FFCodec ff_tiff_encoder = { CODEC_LONG_NAME("TIFF image"), .p.type = AVMEDIA_TYPE_VIDEO, .p.id = AV_CODEC_ID_TIFF, - .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_FRAME_THREADS, + .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_FRAME_THREADS | + AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE, .priv_data_size = sizeof(TiffEncoderContext), .init = encode_init, .close = encode_close, diff --git a/libavcodec/ttaenc.c b/libavcodec/ttaenc.c index d41d2e6fa58..db79c38b43f 100644 --- a/libavcodec/ttaenc.c +++ b/libavcodec/ttaenc.c @@ -204,7 +204,8 @@ const FFCodec ff_tta_encoder = { CODEC_LONG_NAME("TTA (True Audio)"), .p.type = AVMEDIA_TYPE_AUDIO, .p.id = AV_CODEC_ID_TTA, - .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_SMALL_LAST_FRAME, + .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_SMALL_LAST_FRAME | + AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE, .priv_data_size = sizeof(TTAEncContext), .init = tta_encode_init, .close = tta_encode_close, diff --git a/libavcodec/utvideoenc.c b/libavcodec/utvideoenc.c index d4388da8ba1..6e87bbc2b6c 100644 --- a/libavcodec/utvideoenc.c +++ b/libavcodec/utvideoenc.c @@ -648,7 +648,8 @@ const FFCodec ff_utvideo_encoder = { CODEC_LONG_NAME("Ut Video"), .p.type = AVMEDIA_TYPE_VIDEO, .p.id = AV_CODEC_ID_UTVIDEO, - .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_FRAME_THREADS, + .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_FRAME_THREADS | + AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE, .priv_data_size = sizeof(UtvideoContext), .p.priv_class = &utvideo_class, .init = utvideo_encode_init, diff --git a/libavcodec/v210enc.c b/libavcodec/v210enc.c index abbbf4ff9db..2a30ed77da3 100644 --- a/libavcodec/v210enc.c +++ b/libavcodec/v210enc.c @@ -112,7 +112,8 @@ const FFCodec ff_v210_encoder = { CODEC_LONG_NAME("Uncompressed 4:2:2 10-bit"), .p.type = AVMEDIA_TYPE_VIDEO, .p.id = AV_CODEC_ID_V210, - .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_FRAME_THREADS, + .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_FRAME_THREADS | + AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE, .priv_data_size = sizeof(V210EncContext), .init = encode_init, FF_CODEC_ENCODE_CB(encode_frame), diff --git a/libavcodec/v308enc.c b/libavcodec/v308enc.c index 78e33c0a8ab..68f9c3310b8 100644 --- a/libavcodec/v308enc.c +++ b/libavcodec/v308enc.c @@ -75,7 +75,7 @@ const FFCodec ff_v308_encoder = { CODEC_LONG_NAME("Uncompressed packed 4:4:4"), .p.type = AVMEDIA_TYPE_VIDEO, .p.id = AV_CODEC_ID_V308, - .p.capabilities = AV_CODEC_CAP_DR1, + .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE, .init = v308_encode_init, FF_CODEC_ENCODE_CB(v308_encode_frame), .p.pix_fmts = (const enum AVPixelFormat[]){ AV_PIX_FMT_YUV444P, AV_PIX_FMT_NONE }, diff --git a/libavcodec/v408enc.c b/libavcodec/v408enc.c index 514f41be4e3..1faac7cc363 100644 --- a/libavcodec/v408enc.c +++ b/libavcodec/v408enc.c @@ -94,7 +94,7 @@ const FFCodec ff_ayuv_encoder = { CODEC_LONG_NAME("Uncompressed packed MS 4:4:4:4"), .p.type = AVMEDIA_TYPE_VIDEO, .p.id = AV_CODEC_ID_AYUV, - .p.capabilities = AV_CODEC_CAP_DR1, + .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE, .init = v408_encode_init, FF_CODEC_ENCODE_CB(v408_encode_frame), .p.pix_fmts = pix_fmt, @@ -107,7 +107,7 @@ const FFCodec ff_v408_encoder = { CODEC_LONG_NAME("Uncompressed packed QT 4:4:4:4"), .p.type = AVMEDIA_TYPE_VIDEO, .p.id = AV_CODEC_ID_V408, - .p.capabilities = AV_CODEC_CAP_DR1, + .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE, .init = v408_encode_init, FF_CODEC_ENCODE_CB(v408_encode_frame), .p.pix_fmts = pix_fmt, diff --git a/libavcodec/v410enc.c b/libavcodec/v410enc.c index bad13c371ae..89ee3a72786 100644 --- a/libavcodec/v410enc.c +++ b/libavcodec/v410enc.c @@ -79,7 +79,7 @@ const FFCodec ff_v410_encoder = { CODEC_LONG_NAME("Uncompressed 4:4:4 10-bit"), .p.type = AVMEDIA_TYPE_VIDEO, .p.id = AV_CODEC_ID_V410, - .p.capabilities = AV_CODEC_CAP_DR1, + .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE, .init = v410_encode_init, FF_CODEC_ENCODE_CB(v410_encode_frame), .p.pix_fmts = (const enum AVPixelFormat[]){ AV_PIX_FMT_YUV444P10, AV_PIX_FMT_NONE }, diff --git a/libavcodec/vaapi_encode_mjpeg.c b/libavcodec/vaapi_encode_mjpeg.c index 5ef93cd102f..cb7588b94ba 100644 --- a/libavcodec/vaapi_encode_mjpeg.c +++ b/libavcodec/vaapi_encode_mjpeg.c @@ -574,7 +574,8 @@ const FFCodec ff_mjpeg_vaapi_encoder = { FF_CODEC_RECEIVE_PACKET_CB(&ff_vaapi_encode_receive_packet), .close = &vaapi_encode_mjpeg_close, .p.priv_class = &vaapi_encode_mjpeg_class, - .p.capabilities = AV_CODEC_CAP_HARDWARE | AV_CODEC_CAP_DR1, + .p.capabilities = AV_CODEC_CAP_HARDWARE | AV_CODEC_CAP_DR1 | + AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE, .caps_internal = FF_CODEC_CAP_NOT_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP, .defaults = vaapi_encode_mjpeg_defaults, diff --git a/libavcodec/vbnenc.c b/libavcodec/vbnenc.c index 45101382a3f..7ce91863d7f 100644 --- a/libavcodec/vbnenc.c +++ b/libavcodec/vbnenc.c @@ -153,7 +153,8 @@ const FFCodec ff_vbn_encoder = { CODEC_LONG_NAME("Vizrt Binary Image"), .p.type = AVMEDIA_TYPE_VIDEO, .p.id = AV_CODEC_ID_VBN, - .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_SLICE_THREADS, + .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_SLICE_THREADS | + AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE, .p.priv_class = &vbnenc_class, .init = vbn_init, FF_CODEC_ENCODE_CB(vbn_encode), diff --git a/libavcodec/vc2enc.c b/libavcodec/vc2enc.c index 82d11462aaa..d978c67a3b0 100644 --- a/libavcodec/vc2enc.c +++ b/libavcodec/vc2enc.c @@ -1228,7 +1228,8 @@ const FFCodec ff_vc2_encoder = { CODEC_LONG_NAME("SMPTE VC-2"), .p.type = AVMEDIA_TYPE_VIDEO, .p.id = AV_CODEC_ID_DIRAC, - .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_SLICE_THREADS, + .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_SLICE_THREADS | + AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE, .caps_internal = FF_CODEC_CAP_INIT_CLEANUP, .priv_data_size = sizeof(VC2EncContext), .init = vc2_encode_init, diff --git a/libavcodec/wavpackenc.c b/libavcodec/wavpackenc.c index bdb536382f2..3d2d45360de 100644 --- a/libavcodec/wavpackenc.c +++ b/libavcodec/wavpackenc.c @@ -2963,7 +2963,8 @@ const FFCodec ff_wavpack_encoder = { CODEC_LONG_NAME("WavPack"), .p.type = AVMEDIA_TYPE_AUDIO, .p.id = AV_CODEC_ID_WAVPACK, - .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_SMALL_LAST_FRAME, + .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_SMALL_LAST_FRAME | + AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE, .priv_data_size = sizeof(WavPackEncodeContext), .p.priv_class = &wavpack_encoder_class, .init = wavpack_encode_init, diff --git a/libavcodec/wbmpenc.c b/libavcodec/wbmpenc.c index 25fac746fc4..abb66b4ca97 100644 --- a/libavcodec/wbmpenc.c +++ b/libavcodec/wbmpenc.c @@ -80,7 +80,8 @@ const FFCodec ff_wbmp_encoder = { CODEC_LONG_NAME("WBMP (Wireless Application Protocol Bitmap) image"), .p.type = AVMEDIA_TYPE_VIDEO, .p.id = AV_CODEC_ID_WBMP, - .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_FRAME_THREADS, + .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_FRAME_THREADS | + AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE, FF_CODEC_ENCODE_CB(wbmp_encode_frame), .p.pix_fmts = (const enum AVPixelFormat[]){ AV_PIX_FMT_MONOBLACK, diff --git a/libavcodec/wmaenc.c b/libavcodec/wmaenc.c index 2c647af13bd..80ff696be66 100644 --- a/libavcodec/wmaenc.c +++ b/libavcodec/wmaenc.c @@ -440,7 +440,7 @@ const FFCodec ff_wmav1_encoder = { CODEC_LONG_NAME("Windows Media Audio 1"), .p.type = AVMEDIA_TYPE_AUDIO, .p.id = AV_CODEC_ID_WMAV1, - .p.capabilities = AV_CODEC_CAP_DR1, + .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE, .priv_data_size = sizeof(WMACodecContext), .init = encode_init, FF_CODEC_ENCODE_CB(encode_superframe), @@ -456,7 +456,7 @@ const FFCodec ff_wmav2_encoder = { CODEC_LONG_NAME("Windows Media Audio 2"), .p.type = AVMEDIA_TYPE_AUDIO, .p.id = AV_CODEC_ID_WMAV2, - .p.capabilities = AV_CODEC_CAP_DR1, + .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE, .priv_data_size = sizeof(WMACodecContext), .init = encode_init, FF_CODEC_ENCODE_CB(encode_superframe), diff --git a/libavcodec/wmv2enc.c b/libavcodec/wmv2enc.c index cdc450060b1..8eb56444a31 100644 --- a/libavcodec/wmv2enc.c +++ b/libavcodec/wmv2enc.c @@ -242,6 +242,7 @@ const FFCodec ff_wmv2_encoder = { .p.type = AVMEDIA_TYPE_VIDEO, .p.id = AV_CODEC_ID_WMV2, .p.priv_class = &ff_mpv_enc_class, + .p.capabilities = AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE, .priv_data_size = sizeof(WMV2EncContext), .init = wmv2_encode_init, FF_CODEC_ENCODE_CB(ff_mpv_encode_picture), diff --git a/libavcodec/wrapped_avframe.c b/libavcodec/wrapped_avframe.c index c9579848e6a..0278ea42ba0 100644 --- a/libavcodec/wrapped_avframe.c +++ b/libavcodec/wrapped_avframe.c @@ -109,6 +109,7 @@ const FFCodec ff_wrapped_avframe_encoder = { CODEC_LONG_NAME("AVFrame to AVPacket passthrough"), .p.type = AVMEDIA_TYPE_VIDEO, .p.id = AV_CODEC_ID_WRAPPED_AVFRAME, + .p.capabilities = AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE, FF_CODEC_ENCODE_CB(wrapped_avframe_encode), }; diff --git a/libavcodec/xbmenc.c b/libavcodec/xbmenc.c index 664c6599bff..cd8b73afa3e 100644 --- a/libavcodec/xbmenc.c +++ b/libavcodec/xbmenc.c @@ -82,7 +82,7 @@ const FFCodec ff_xbm_encoder = { CODEC_LONG_NAME("XBM (X BitMap) image"), .p.type = AVMEDIA_TYPE_VIDEO, .p.id = AV_CODEC_ID_XBM, - .p.capabilities = AV_CODEC_CAP_DR1, + .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE, FF_CODEC_ENCODE_CB(xbm_encode_frame), .p.pix_fmts = (const enum AVPixelFormat[]) { AV_PIX_FMT_MONOWHITE, AV_PIX_FMT_NONE }, diff --git a/libavcodec/xfaceenc.c b/libavcodec/xfaceenc.c index 7125f1f085c..4998d42ea50 100644 --- a/libavcodec/xfaceenc.c +++ b/libavcodec/xfaceenc.c @@ -216,7 +216,7 @@ const FFCodec ff_xface_encoder = { CODEC_LONG_NAME("X-face image"), .p.type = AVMEDIA_TYPE_VIDEO, .p.id = AV_CODEC_ID_XFACE, - .p.capabilities = AV_CODEC_CAP_DR1, + .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE, .p.pix_fmts = (const enum AVPixelFormat[]) { AV_PIX_FMT_MONOWHITE, AV_PIX_FMT_NONE }, .priv_data_size = sizeof(XFaceContext), FF_CODEC_ENCODE_CB(xface_encode_frame), diff --git a/libavcodec/xwdenc.c b/libavcodec/xwdenc.c index 6c588f3acca..08554d86323 100644 --- a/libavcodec/xwdenc.c +++ b/libavcodec/xwdenc.c @@ -216,7 +216,7 @@ const FFCodec ff_xwd_encoder = { CODEC_LONG_NAME("XWD (X Window Dump) image"), .p.type = AVMEDIA_TYPE_VIDEO, .p.id = AV_CODEC_ID_XWD, - .p.capabilities = AV_CODEC_CAP_DR1, + .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE, FF_CODEC_ENCODE_CB(xwd_encode_frame), .p.pix_fmts = (const enum AVPixelFormat[]) { AV_PIX_FMT_BGRA, AV_PIX_FMT_RGBA, diff --git a/libavcodec/y41penc.c b/libavcodec/y41penc.c index d3ef88c2ce2..e86769da66b 100644 --- a/libavcodec/y41penc.c +++ b/libavcodec/y41penc.c @@ -82,7 +82,7 @@ const FFCodec ff_y41p_encoder = { CODEC_LONG_NAME("Uncompressed YUV 4:1:1 12-bit"), .p.type = AVMEDIA_TYPE_VIDEO, .p.id = AV_CODEC_ID_Y41P, - .p.capabilities = AV_CODEC_CAP_DR1, + .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE, .init = y41p_encode_init, FF_CODEC_ENCODE_CB(y41p_encode_frame), .p.pix_fmts = (const enum AVPixelFormat[]) { AV_PIX_FMT_YUV411P, diff --git a/libavcodec/yuv4enc.c b/libavcodec/yuv4enc.c index 27e786dd545..8123260d5db 100644 --- a/libavcodec/yuv4enc.c +++ b/libavcodec/yuv4enc.c @@ -64,7 +64,7 @@ const FFCodec ff_yuv4_encoder = { CODEC_LONG_NAME("Uncompressed packed 4:2:0"), .p.type = AVMEDIA_TYPE_VIDEO, .p.id = AV_CODEC_ID_YUV4, - .p.capabilities = AV_CODEC_CAP_DR1, + .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE, .p.pix_fmts = (const enum AVPixelFormat[]){ AV_PIX_FMT_YUV420P, AV_PIX_FMT_NONE }, FF_CODEC_ENCODE_CB(yuv4_encode_frame), }; diff --git a/libavcodec/zmbvenc.c b/libavcodec/zmbvenc.c index c12f783d5ad..d20330568d9 100644 --- a/libavcodec/zmbvenc.c +++ b/libavcodec/zmbvenc.c @@ -416,7 +416,7 @@ const FFCodec ff_zmbv_encoder = { CODEC_LONG_NAME("Zip Motion Blocks Video"), .p.type = AVMEDIA_TYPE_VIDEO, .p.id = AV_CODEC_ID_ZMBV, - .p.capabilities = AV_CODEC_CAP_DR1, + .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE, .priv_data_size = sizeof(ZmbvEncContext), .init = encode_init, FF_CODEC_ENCODE_CB(encode_frame), From a1a80f2e64f31755be74d8cc7afb1aafe000c29a Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Tue, 12 Jul 2022 11:25:09 +0200 Subject: [PATCH 0101/2172] lavc/encode: pass through frame durations to encoded packets The generic code can only handle the no-delay case. Encoders with delay need to be handled individually, which will be done in the following commits. --- doc/APIchanges | 4 ++-- libavcodec/avcodec.h | 7 +++++++ libavcodec/encode.c | 14 ++++++++++++-- libavcodec/options_table.h | 1 + 4 files changed, 22 insertions(+), 4 deletions(-) diff --git a/doc/APIchanges b/doc/APIchanges index 148962cb409..bc52a079644 100644 --- a/doc/APIchanges +++ b/doc/APIchanges @@ -14,8 +14,8 @@ libavutil: 2021-04-27 API changes, most recent first: -2023-01-xx - xxxxxxxxxx - lavc 59.59.100 - avcodec.h - Add AV_CODEC_FLAG_COPY_OPAQUE. +2023-01-29 - xxxxxxxxxx - lavc 59.59.100 - avcodec.h + Add AV_CODEC_FLAG_COPY_OPAQUE and AV_CODEC_FLAG_FRAME_DURATION. 2023-01-13 - xxxxxxxxxx - lavu 57.44.100 - ambient_viewing_environment.h frame.h Adds a new structure for holding H.274 Ambient Viewing Environment metadata, diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h index 832b9d95753..90b437ccbe2 100644 --- a/libavcodec/avcodec.h +++ b/libavcodec/avcodec.h @@ -267,6 +267,13 @@ typedef struct RcOverride{ * taken from the first of those. */ #define AV_CODEC_FLAG_COPY_OPAQUE (1 << 7) +/** + * Signal to the encoder that the values of AVFrame.duration are valid and + * should be used (typically for transferring them to output packets). + * + * If this flag is not set, frame durations are ignored. + */ +#define AV_CODEC_FLAG_FRAME_DURATION (1 << 8) /** * Use internal 2pass ratecontrol in first pass mode. */ diff --git a/libavcodec/encode.c b/libavcodec/encode.c index 555bd3ff96b..c92beaf8e1f 100644 --- a/libavcodec/encode.c +++ b/libavcodec/encode.c @@ -231,10 +231,13 @@ int ff_encode_encode_cb(AVCodecContext *avctx, AVPacket *avpkt, if (avpkt->pts == AV_NOPTS_VALUE) avpkt->pts = frame->pts; - if (avctx->codec->type == AVMEDIA_TYPE_AUDIO) { - if (!avpkt->duration) + if (!avpkt->duration) { + if (frame->duration) + avpkt->duration = frame->duration; + else if (avctx->codec->type == AVMEDIA_TYPE_AUDIO) { avpkt->duration = ff_samples_to_time_base(avctx, frame->nb_samples); + } } ret = ff_encode_reordered_opaque(avctx, avpkt, frame); @@ -463,6 +466,13 @@ FF_ENABLE_DEPRECATION_WARNINGS return ret; } + // unset frame duration unless AV_CODEC_FLAG_FRAME_DURATION is set, + // since otherwise we cannot be sure that whatever value it has is in the + // right timebase, so we would produce an incorrect value, which is worse + // than none at all + if (!(avctx->flags & AV_CODEC_FLAG_FRAME_DURATION)) + dst->duration = 0; + return 0; } diff --git a/libavcodec/options_table.h b/libavcodec/options_table.h index 4b38c42043d..322ec7a1566 100644 --- a/libavcodec/options_table.h +++ b/libavcodec/options_table.h @@ -59,6 +59,7 @@ static const AVOption avcodec_options[] = { {"qscale", "use fixed qscale", 0, AV_OPT_TYPE_CONST, {.i64 = AV_CODEC_FLAG_QSCALE }, INT_MIN, INT_MAX, 0, "flags"}, {"recon_frame", "export reconstructed frames", 0, AV_OPT_TYPE_CONST, {.i64 = AV_CODEC_FLAG_RECON_FRAME}, .unit = "flags"}, {"copy_opaque", "propagate opaque values", 0, AV_OPT_TYPE_CONST, {.i64 = AV_CODEC_FLAG_COPY_OPAQUE}, .unit = "flags"}, +{"frame_duration", "use frame durations", 0, AV_OPT_TYPE_CONST, {.i64 = AV_CODEC_FLAG_FRAME_DURATION}, .unit = "flags"}, {"pass1", "use internal 2-pass ratecontrol in first pass mode", 0, AV_OPT_TYPE_CONST, {.i64 = AV_CODEC_FLAG_PASS1 }, INT_MIN, INT_MAX, 0, "flags"}, {"pass2", "use internal 2-pass ratecontrol in second pass mode", 0, AV_OPT_TYPE_CONST, {.i64 = AV_CODEC_FLAG_PASS2 }, INT_MIN, INT_MAX, 0, "flags"}, {"gray", "only decode/encode grayscale", 0, AV_OPT_TYPE_CONST, {.i64 = AV_CODEC_FLAG_GRAY }, INT_MIN, INT_MAX, V|E|D, "flags"}, From 1b25eb65cd71906abdc87a260338f0611a793c85 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Tue, 12 Jul 2022 11:25:09 +0200 Subject: [PATCH 0102/2172] lavc/librav1e: handle frame durations and AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE --- libavcodec/librav1e.c | 61 +++++++++++++++++++++++++++++++++++++------ 1 file changed, 53 insertions(+), 8 deletions(-) diff --git a/libavcodec/librav1e.c b/libavcodec/librav1e.c index 3481b7637d6..00d69328fb7 100644 --- a/libavcodec/librav1e.c +++ b/libavcodec/librav1e.c @@ -22,6 +22,7 @@ #include +#include "libavutil/buffer.h" #include "libavutil/internal.h" #include "libavutil/avassert.h" #include "libavutil/base64.h" @@ -53,6 +54,15 @@ typedef struct librav1eContext { int tile_cols; } librav1eContext; +typedef struct FrameData { + int64_t pts; + int64_t duration; + int64_t reordered_opaque; + + void *frame_opaque; + AVBufferRef *frame_opaque_ref; +} FrameData; + static inline RaPixelRange range_map(enum AVPixelFormat pix_fmt, enum AVColorRange range) { switch (pix_fmt) { @@ -419,11 +429,23 @@ static av_cold int librav1e_encode_init(AVCodecContext *avctx) return ret; } +static void frame_data_free(void *data) +{ + FrameData *fd = data; + + if (!fd) + return; + + av_buffer_unref(&fd->frame_opaque_ref); + av_free(data); +} + static int librav1e_receive_packet(AVCodecContext *avctx, AVPacket *pkt) { librav1eContext *ctx = avctx->priv_data; RaFrame *rframe = ctx->rframe; RaPacket *rpkt = NULL; + FrameData *fd; int ret; if (!rframe) { @@ -436,18 +458,30 @@ static int librav1e_receive_packet(AVCodecContext *avctx, AVPacket *pkt) if (frame->buf[0]) { const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(frame->format); - int64_t *pts = av_malloc(sizeof(int64_t)); - if (!pts) { + fd = av_mallocz(sizeof(*fd)); + if (!fd) { av_log(avctx, AV_LOG_ERROR, "Could not allocate PTS buffer.\n"); return AVERROR(ENOMEM); } - *pts = frame->pts; + fd->pts = frame->pts; + fd->duration = frame->duration; + fd->reordered_opaque = frame->reordered_opaque; + + if (avctx->flags & AV_CODEC_FLAG_COPY_OPAQUE) { + fd->frame_opaque = frame->opaque; + ret = av_buffer_replace(&fd->frame_opaque_ref, frame->opaque_ref); + if (ret < 0) { + frame_data_free(fd); + av_frame_unref(frame); + return ret; + } + } rframe = rav1e_frame_new(ctx->ctx); if (!rframe) { av_log(avctx, AV_LOG_ERROR, "Could not allocate new rav1e frame.\n"); av_frame_unref(frame); - av_freep(&pts); + frame_data_free(fd); return AVERROR(ENOMEM); } @@ -459,7 +493,7 @@ static int librav1e_receive_packet(AVCodecContext *avctx, AVPacket *pkt) frame->linesize[i], bytes); } av_frame_unref(frame); - rav1e_frame_set_opaque(rframe, pts, av_free); + rav1e_frame_set_opaque(rframe, fd, frame_data_free); } } @@ -535,8 +569,18 @@ static int librav1e_receive_packet(AVCodecContext *avctx, AVPacket *pkt) if (rpkt->frame_type == RA_FRAME_TYPE_KEY) pkt->flags |= AV_PKT_FLAG_KEY; - pkt->pts = pkt->dts = *((int64_t *) rpkt->opaque); - av_free(rpkt->opaque); + fd = rpkt->opaque; + pkt->pts = pkt->dts = fd->pts; + pkt->duration = fd->duration; + avctx->reordered_opaque = fd->reordered_opaque; + + if (avctx->flags & AV_CODEC_FLAG_COPY_OPAQUE) { + pkt->opaque = fd->frame_opaque; + pkt->opaque_ref = fd->frame_opaque_ref; + fd->frame_opaque_ref = NULL; + } + + frame_data_free(fd); if (avctx->flags & AV_CODEC_FLAG_RECON_FRAME) { AVCodecInternal *avci = avctx->internal; @@ -626,7 +670,8 @@ const FFCodec ff_librav1e_encoder = { .defaults = librav1e_defaults, .p.pix_fmts = librav1e_pix_fmts, .p.capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_OTHER_THREADS | - AV_CODEC_CAP_DR1 | AV_CODEC_CAP_ENCODER_RECON_FRAME, + AV_CODEC_CAP_DR1 | AV_CODEC_CAP_ENCODER_RECON_FRAME | + AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE, .caps_internal = FF_CODEC_CAP_NOT_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP | FF_CODEC_CAP_AUTO_THREADS, .p.wrapper_name = "librav1e", From 35538097038fd1e36577306d3165f38c8fa02466 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Tue, 12 Jul 2022 11:25:09 +0200 Subject: [PATCH 0103/2172] lavc/nvenc: handle frame durations and AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE --- libavcodec/nvenc.c | 102 ++++++++++++++++++++++++++++++++-------- libavcodec/nvenc.h | 2 +- libavcodec/nvenc_av1.c | 3 +- libavcodec/nvenc_h264.c | 3 +- libavcodec/nvenc_hevc.c | 3 +- 5 files changed, 89 insertions(+), 24 deletions(-) diff --git a/libavcodec/nvenc.c b/libavcodec/nvenc.c index f6df7cb6ac1..ab42dc9690f 100644 --- a/libavcodec/nvenc.c +++ b/libavcodec/nvenc.c @@ -28,6 +28,7 @@ #include "av1.h" #endif +#include "libavutil/buffer.h" #include "libavutil/hwcontext_cuda.h" #include "libavutil/hwcontext.h" #include "libavutil/cuda_check.h" @@ -162,6 +163,23 @@ static int nvenc_print_error(AVCodecContext *avctx, NVENCSTATUS err, return ret; } +typedef struct FrameData { + int64_t pts; + int64_t duration; + int64_t reordered_opaque; + + void *frame_opaque; + AVBufferRef *frame_opaque_ref; +} FrameData; + +static void reorder_queue_flush(AVFifo *queue) +{ + FrameData fd; + + while (av_fifo_read(queue, &fd, 1) >= 0) + av_buffer_unref(&fd.frame_opaque_ref); +} + typedef struct GUIDTuple { const GUID guid; int flags; @@ -1748,8 +1766,8 @@ static av_cold int nvenc_setup_surfaces(AVCodecContext *avctx) if (!ctx->surfaces) return AVERROR(ENOMEM); - ctx->timestamp_list = av_fifo_alloc2(ctx->nb_surfaces, sizeof(int64_t), 0); - if (!ctx->timestamp_list) + ctx->reorder_queue = av_fifo_alloc2(ctx->nb_surfaces, sizeof(FrameData), 0); + if (!ctx->reorder_queue) return AVERROR(ENOMEM); ctx->unused_surface_queue = av_fifo_alloc2(ctx->nb_surfaces, sizeof(NvencSurface*), 0); @@ -1833,7 +1851,8 @@ av_cold int ff_nvenc_encode_close(AVCodecContext *avctx) p_nvenc->nvEncEncodePicture(ctx->nvencoder, ¶ms); } - av_fifo_freep2(&ctx->timestamp_list); + reorder_queue_flush(ctx->reorder_queue); + av_fifo_freep2(&ctx->reorder_queue); av_fifo_freep2(&ctx->output_surface_ready_queue); av_fifo_freep2(&ctx->output_surface_queue); av_fifo_freep2(&ctx->unused_surface_queue); @@ -2177,18 +2196,45 @@ static void nvenc_codec_specific_pic_params(AVCodecContext *avctx, } } -static inline void timestamp_queue_enqueue(AVFifo *queue, int64_t timestamp) +static void reorder_queue_enqueue(AVFifo *queue, const AVCodecContext *avctx, + const AVFrame *frame, AVBufferRef **opaque_ref) { - av_fifo_write(queue, ×tamp, 1); + FrameData fd; + + fd.pts = frame->pts; + fd.duration = frame->duration; + fd.reordered_opaque = frame->reordered_opaque; + fd.frame_opaque = frame->opaque; + fd.frame_opaque_ref = *opaque_ref; + + *opaque_ref = NULL; + + av_fifo_write(queue, &fd, 1); } -static inline int64_t timestamp_queue_dequeue(AVFifo *queue) +static int64_t reorder_queue_dequeue(AVFifo *queue, AVCodecContext *avctx, + AVPacket *pkt) { - int64_t timestamp = AV_NOPTS_VALUE; + FrameData fd; + // The following call might fail if the queue is empty. - av_fifo_read(queue, ×tamp, 1); + if (av_fifo_read(queue, &fd, 1) < 0) + return AV_NOPTS_VALUE; + + if (pkt) { + avctx->reordered_opaque = fd.reordered_opaque; + pkt->duration = fd.duration; + + if (avctx->flags & AV_CODEC_FLAG_COPY_OPAQUE) { + pkt->opaque = fd.frame_opaque; + pkt->opaque_ref = fd.frame_opaque_ref; + fd.frame_opaque_ref = NULL; + } + } + + av_buffer_unref(&fd.frame_opaque_ref); - return timestamp; + return fd.pts; } static int nvenc_set_timestamp(AVCodecContext *avctx, @@ -2196,12 +2242,14 @@ static int nvenc_set_timestamp(AVCodecContext *avctx, AVPacket *pkt) { NvencContext *ctx = avctx->priv_data; + int64_t dts; pkt->pts = params->outputTimeStamp; + dts = reorder_queue_dequeue(ctx->reorder_queue, avctx, pkt); + if (avctx->codec_descriptor->props & AV_CODEC_PROP_REORDER) { - pkt->dts = timestamp_queue_dequeue(ctx->timestamp_list); - pkt->dts -= FFMAX(ctx->encode_config.frameIntervalP - 1, 0) * FFMAX(avctx->ticks_per_frame, 1); + pkt->dts = dts - FFMAX(ctx->encode_config.frameIntervalP - 1, 0) * FFMAX(avctx->ticks_per_frame, 1); } else { pkt->dts = pkt->pts; } @@ -2298,7 +2346,7 @@ static int process_output_surface(AVCodecContext *avctx, AVPacket *pkt, NvencSur return 0; error: - timestamp_queue_dequeue(ctx->timestamp_list); + reorder_queue_dequeue(ctx->reorder_queue, avctx, NULL); error2: return res; @@ -2528,6 +2576,8 @@ static int nvenc_send_frame(AVCodecContext *avctx, const AVFrame *frame) int sei_count = 0; int i; + AVBufferRef *opaque_ref = NULL; + NvencContext *ctx = avctx->priv_data; NvencDynLoadFunctions *dl_fn = &ctx->nvenc_dload_funcs; NV_ENCODE_API_FUNCTION_LIST *p_nvenc = &dl_fn->nvenc_funcs; @@ -2595,9 +2645,17 @@ static int nvenc_send_frame(AVCodecContext *avctx, const AVFrame *frame) pic_params.encodePicFlags = NV_ENC_PIC_FLAG_EOS; } + // make a reference for enqueing in the reorder queue here, + // so that reorder_queue_enqueue() cannot fail + if (frame && frame->opaque_ref && avctx->flags & AV_CODEC_FLAG_COPY_OPAQUE) { + opaque_ref = av_buffer_ref(frame->opaque_ref); + if (!opaque_ref) + return AVERROR(ENOMEM); + } + res = nvenc_push_context(avctx); if (res < 0) - return res; + goto opaque_ref_fail; nv_status = p_nvenc->nvEncEncodePicture(ctx->nvencoder, &pic_params); @@ -2606,17 +2664,17 @@ static int nvenc_send_frame(AVCodecContext *avctx, const AVFrame *frame) res = nvenc_pop_context(avctx); if (res < 0) - return res; + goto opaque_ref_fail; if (nv_status != NV_ENC_SUCCESS && - nv_status != NV_ENC_ERR_NEED_MORE_INPUT) - return nvenc_print_error(avctx, nv_status, "EncodePicture failed!"); + nv_status != NV_ENC_ERR_NEED_MORE_INPUT) { + res = nvenc_print_error(avctx, nv_status, "EncodePicture failed!"); + goto opaque_ref_fail; + } if (frame && frame->buf[0]) { av_fifo_write(ctx->output_surface_queue, &in_surf, 1); - - if (avctx->codec_descriptor->props & AV_CODEC_PROP_REORDER) - timestamp_queue_enqueue(ctx->timestamp_list, frame->pts); + reorder_queue_enqueue(ctx->reorder_queue, avctx, frame, &opaque_ref); } /* all the pending buffers are now ready for output */ @@ -2626,6 +2684,10 @@ static int nvenc_send_frame(AVCodecContext *avctx, const AVFrame *frame) } return 0; + +opaque_ref_fail: + av_buffer_unref(&opaque_ref); + return res; } int ff_nvenc_receive_packet(AVCodecContext *avctx, AVPacket *pkt) @@ -2684,5 +2746,5 @@ av_cold void ff_nvenc_encode_flush(AVCodecContext *avctx) NvencContext *ctx = avctx->priv_data; nvenc_send_frame(avctx, NULL); - av_fifo_reset2(ctx->timestamp_list); + reorder_queue_flush(ctx->reorder_queue); } diff --git a/libavcodec/nvenc.h b/libavcodec/nvenc.h index 05a7ac48b17..411c83aa943 100644 --- a/libavcodec/nvenc.h +++ b/libavcodec/nvenc.h @@ -171,7 +171,7 @@ typedef struct NvencContext AVFifo *unused_surface_queue; AVFifo *output_surface_queue; AVFifo *output_surface_ready_queue; - AVFifo *timestamp_list; + AVFifo *reorder_queue; NV_ENC_SEI_PAYLOAD *sei_data; int sei_data_size; diff --git a/libavcodec/nvenc_av1.c b/libavcodec/nvenc_av1.c index 2ed99d948b6..2b349c7b61f 100644 --- a/libavcodec/nvenc_av1.c +++ b/libavcodec/nvenc_av1.c @@ -181,7 +181,8 @@ const FFCodec ff_av1_nvenc_encoder = { .defaults = defaults, .p.pix_fmts = ff_nvenc_pix_fmts, .p.capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_HARDWARE | - AV_CODEC_CAP_ENCODER_FLUSH | AV_CODEC_CAP_DR1, + AV_CODEC_CAP_ENCODER_FLUSH | AV_CODEC_CAP_DR1 | + AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE, .caps_internal = FF_CODEC_CAP_NOT_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP, .p.wrapper_name = "nvenc", diff --git a/libavcodec/nvenc_h264.c b/libavcodec/nvenc_h264.c index a69358b03b8..5dc2961c3bc 100644 --- a/libavcodec/nvenc_h264.c +++ b/libavcodec/nvenc_h264.c @@ -232,7 +232,8 @@ const FFCodec ff_h264_nvenc_encoder = { .p.priv_class = &h264_nvenc_class, .defaults = defaults, .p.capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_HARDWARE | - AV_CODEC_CAP_ENCODER_FLUSH | AV_CODEC_CAP_DR1, + AV_CODEC_CAP_ENCODER_FLUSH | AV_CODEC_CAP_DR1 | + AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE, .caps_internal = FF_CODEC_CAP_NOT_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP, .p.pix_fmts = ff_nvenc_pix_fmts, diff --git a/libavcodec/nvenc_hevc.c b/libavcodec/nvenc_hevc.c index 5ad423444a5..1362a927c8e 100644 --- a/libavcodec/nvenc_hevc.c +++ b/libavcodec/nvenc_hevc.c @@ -214,7 +214,8 @@ const FFCodec ff_hevc_nvenc_encoder = { .defaults = defaults, .p.pix_fmts = ff_nvenc_pix_fmts, .p.capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_HARDWARE | - AV_CODEC_CAP_ENCODER_FLUSH | AV_CODEC_CAP_DR1, + AV_CODEC_CAP_ENCODER_FLUSH | AV_CODEC_CAP_DR1 | + AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE, .caps_internal = FF_CODEC_CAP_NOT_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP, .p.wrapper_name = "nvenc", From bbbafab0ee8b5ac15150d3b6c8129d7dbcbe6603 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Tue, 12 Jul 2022 14:37:15 +0200 Subject: [PATCH 0104/2172] lavc/pngenc: handle frame durations and AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE --- libavcodec/pngenc.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/libavcodec/pngenc.c b/libavcodec/pngenc.c index 5166698b8a2..535a46b5077 100644 --- a/libavcodec/pngenc.c +++ b/libavcodec/pngenc.c @@ -964,6 +964,11 @@ static int encode_apng(AVCodecContext *avctx, AVPacket *pkt, memcpy(pkt->data, s->last_frame_packet, s->last_frame_packet_size); pkt->pts = pkt->dts = s->last_frame->pts; + pkt->duration = s->last_frame->duration; + + ret = ff_encode_reordered_opaque(avctx, pkt, s->last_frame); + if (ret < 0) + return ret; } if (pict) { @@ -1206,7 +1211,8 @@ const FFCodec ff_apng_encoder = { CODEC_LONG_NAME("APNG (Animated Portable Network Graphics) image"), .p.type = AVMEDIA_TYPE_VIDEO, .p.id = AV_CODEC_ID_APNG, - .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_DELAY, + .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_DELAY | + AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE, .priv_data_size = sizeof(PNGEncContext), .init = png_enc_init, .close = png_enc_close, From b7f0c8889e022c6fbfd9703664f8af05d9a48258 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Tue, 12 Jul 2022 14:45:59 +0200 Subject: [PATCH 0105/2172] lavc/pngenc: stop setting dts unnecessarily for APNG APNG is not marked as supporting reordering, so dts will be set from pts by the generic code. --- libavcodec/pngenc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavcodec/pngenc.c b/libavcodec/pngenc.c index 535a46b5077..2393161c3b9 100644 --- a/libavcodec/pngenc.c +++ b/libavcodec/pngenc.c @@ -963,7 +963,7 @@ static int encode_apng(AVCodecContext *avctx, AVPacket *pkt, return ret; memcpy(pkt->data, s->last_frame_packet, s->last_frame_packet_size); - pkt->pts = pkt->dts = s->last_frame->pts; + pkt->pts = s->last_frame->pts; pkt->duration = s->last_frame->duration; ret = ff_encode_reordered_opaque(avctx, pkt, s->last_frame); From 2bb20e98ba74ca629fd63d7b1fc3154ea1f3caa5 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Tue, 12 Jul 2022 14:37:15 +0200 Subject: [PATCH 0106/2172] lavc/libtheoraenc: handle frame durations and AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE --- libavcodec/libtheoraenc.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/libavcodec/libtheoraenc.c b/libavcodec/libtheoraenc.c index da16c6372e2..73295e22b9c 100644 --- a/libavcodec/libtheoraenc.c +++ b/libavcodec/libtheoraenc.c @@ -347,6 +347,12 @@ static int encode_frame(AVCodecContext* avc_context, AVPacket *pkt, // HACK: assumes no encoder delay, this is true until libtheora becomes // multithreaded (which will be disabled unless explicitly requested) pkt->pts = pkt->dts = frame->pts; + pkt->duration = frame->duration; + + ret = ff_encode_reordered_opaque(avc_context, pkt, frame); + if (ret < 0) + return ret; + if (!(o_packet.granulepos & h->keyframe_mask)) pkt->flags |= AV_PKT_FLAG_KEY; *got_packet = 1; @@ -373,7 +379,9 @@ const FFCodec ff_libtheora_encoder = { .p.type = AVMEDIA_TYPE_VIDEO, .p.id = AV_CODEC_ID_THEORA, .p.capabilities = AV_CODEC_CAP_DR1 | - AV_CODEC_CAP_DELAY /* for statsfile summary */, + /* for statsfile summary */ + AV_CODEC_CAP_DELAY | + AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE, .caps_internal = FF_CODEC_CAP_NOT_INIT_THREADSAFE, .priv_data_size = sizeof(TheoraContext), .init = encode_init, From 8a60a9c74c7bfc2772a67d13401a395fe01d5677 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Tue, 12 Jul 2022 14:45:59 +0200 Subject: [PATCH 0107/2172] lavc/libtheoraenc: stop setting dts unnecessarily Theora is not marked as supporting reordering, so dts will be set from pts by the generic code. --- libavcodec/libtheoraenc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavcodec/libtheoraenc.c b/libavcodec/libtheoraenc.c index 73295e22b9c..06eeaae0063 100644 --- a/libavcodec/libtheoraenc.c +++ b/libavcodec/libtheoraenc.c @@ -346,7 +346,7 @@ static int encode_frame(AVCodecContext* avc_context, AVPacket *pkt, // HACK: assumes no encoder delay, this is true until libtheora becomes // multithreaded (which will be disabled unless explicitly requested) - pkt->pts = pkt->dts = frame->pts; + pkt->pts = frame->pts; pkt->duration = frame->duration; ret = ff_encode_reordered_opaque(avc_context, pkt, frame); From c44a3dba9eaebc200c2cf9e4cb30c20c2ebd4562 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Wed, 4 Jan 2023 17:27:07 +0100 Subject: [PATCH 0108/2172] lavc/mpegvideo_enc: handle frame durations and AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE For delay-capable encoders, i.e. mpeg12 and mpeg4video. Generic code in encode.c already handles this for all other mpegvideo encoders. --- libavcodec/mpeg12enc.c | 6 ++++-- libavcodec/mpeg4videoenc.c | 3 ++- libavcodec/mpegvideo_enc.c | 9 +++++++++ 3 files changed, 15 insertions(+), 3 deletions(-) diff --git a/libavcodec/mpeg12enc.c b/libavcodec/mpeg12enc.c index a6663a158b8..b5951e43070 100644 --- a/libavcodec/mpeg12enc.c +++ b/libavcodec/mpeg12enc.c @@ -1246,7 +1246,8 @@ const FFCodec ff_mpeg1video_encoder = { .p.supported_framerates = ff_mpeg12_frame_rate_tab + 1, .p.pix_fmts = (const enum AVPixelFormat[]) { AV_PIX_FMT_YUV420P, AV_PIX_FMT_NONE }, - .p.capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_SLICE_THREADS, + .p.capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_SLICE_THREADS | + AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE, .caps_internal = FF_CODEC_CAP_INIT_CLEANUP, .p.priv_class = &mpeg1_class, }; @@ -1264,7 +1265,8 @@ const FFCodec ff_mpeg2video_encoder = { .p.pix_fmts = (const enum AVPixelFormat[]) { AV_PIX_FMT_YUV420P, AV_PIX_FMT_YUV422P, AV_PIX_FMT_NONE }, - .p.capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_SLICE_THREADS, + .p.capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_SLICE_THREADS | + AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE, .caps_internal = FF_CODEC_CAP_INIT_CLEANUP, .p.priv_class = &mpeg2_class, }; diff --git a/libavcodec/mpeg4videoenc.c b/libavcodec/mpeg4videoenc.c index 27df9ba0985..c3e9ebea452 100644 --- a/libavcodec/mpeg4videoenc.c +++ b/libavcodec/mpeg4videoenc.c @@ -1403,7 +1403,8 @@ const FFCodec ff_mpeg4_encoder = { FF_CODEC_ENCODE_CB(ff_mpv_encode_picture), .close = ff_mpv_encode_end, .p.pix_fmts = (const enum AVPixelFormat[]) { AV_PIX_FMT_YUV420P, AV_PIX_FMT_NONE }, - .p.capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_SLICE_THREADS, + .p.capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_SLICE_THREADS | + AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE, .caps_internal = FF_CODEC_CAP_INIT_CLEANUP, .p.priv_class = &mpeg4enc_class, }; diff --git a/libavcodec/mpegvideo_enc.c b/libavcodec/mpegvideo_enc.c index bb101612e5a..0e6a4c4ec54 100644 --- a/libavcodec/mpegvideo_enc.c +++ b/libavcodec/mpegvideo_enc.c @@ -1952,6 +1952,7 @@ int ff_mpv_encode_picture(AVCodecContext *avctx, AVPacket *pkt, s->total_bits += s->frame_bits; pkt->pts = s->current_picture.f->pts; + pkt->duration = s->current_picture.f->duration; if (!s->low_delay && s->pict_type != AV_PICTURE_TYPE_B) { if (!s->current_picture.f->coded_picture_number) pkt->dts = pkt->pts - s->dts_delta; @@ -1960,6 +1961,14 @@ int ff_mpv_encode_picture(AVCodecContext *avctx, AVPacket *pkt, s->reordered_pts = pkt->pts; } else pkt->dts = pkt->pts; + + // the no-delay case is handled in generic code + if (avctx->codec->capabilities & AV_CODEC_CAP_DELAY) { + ret = ff_encode_reordered_opaque(avctx, pkt, s->current_picture.f); + if (ret < 0) + return ret; + } + if (s->current_picture.f->key_frame) pkt->flags |= AV_PKT_FLAG_KEY; if (s->mb_info) From fbdba9a1a69fe4df413d9e9df1b11db522946e75 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Wed, 4 Jan 2023 18:11:19 +0100 Subject: [PATCH 0109/2172] lavc/vaapi_encode*: handle frame durations and AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE Except for the mjpeg_vaapi encoder, which is already handled generically. --- libavcodec/vaapi_encode.c | 8 ++++++++ libavcodec/vaapi_encode_h264.c | 2 +- libavcodec/vaapi_encode_h265.c | 2 +- libavcodec/vaapi_encode_mpeg2.c | 2 +- libavcodec/vaapi_encode_vp8.c | 2 +- libavcodec/vaapi_encode_vp9.c | 2 +- 6 files changed, 13 insertions(+), 5 deletions(-) diff --git a/libavcodec/vaapi_encode.c b/libavcodec/vaapi_encode.c index 9a58661b51a..6787b90e8d6 100644 --- a/libavcodec/vaapi_encode.c +++ b/libavcodec/vaapi_encode.c @@ -695,6 +695,7 @@ static int vaapi_encode_output(AVCodecContext *avctx, pkt->flags |= AV_PKT_FLAG_KEY; pkt->pts = pic->pts; + pkt->duration = pic->input_image->duration; vas = vaUnmapBuffer(ctx->hwctx->display, pic->output_buffer); if (vas != VA_STATUS_SUCCESS) { @@ -704,6 +705,13 @@ static int vaapi_encode_output(AVCodecContext *avctx, goto fail; } + // for no-delay encoders this is handled in generic codec + if (avctx->codec->capabilities & AV_CODEC_CAP_DELAY) { + err = ff_encode_reordered_opaque(avctx, pkt, pic->input_image); + if (err < 0) + goto fail; + } + av_buffer_unref(&pic->output_buffer_ref); pic->output_buffer = VA_INVALID_ID; diff --git a/libavcodec/vaapi_encode_h264.c b/libavcodec/vaapi_encode_h264.c index f15bcc6ea8b..0fe39056660 100644 --- a/libavcodec/vaapi_encode_h264.c +++ b/libavcodec/vaapi_encode_h264.c @@ -1361,7 +1361,7 @@ const FFCodec ff_h264_vaapi_encoder = { .close = &vaapi_encode_h264_close, .p.priv_class = &vaapi_encode_h264_class, .p.capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_HARDWARE | - AV_CODEC_CAP_DR1, + AV_CODEC_CAP_DR1 | AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE, .caps_internal = FF_CODEC_CAP_NOT_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP, .defaults = vaapi_encode_h264_defaults, diff --git a/libavcodec/vaapi_encode_h265.c b/libavcodec/vaapi_encode_h265.c index 946f2e7640a..aa7e532f9a4 100644 --- a/libavcodec/vaapi_encode_h265.c +++ b/libavcodec/vaapi_encode_h265.c @@ -1487,7 +1487,7 @@ const FFCodec ff_hevc_vaapi_encoder = { .close = &vaapi_encode_h265_close, .p.priv_class = &vaapi_encode_h265_class, .p.capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_HARDWARE | - AV_CODEC_CAP_DR1, + AV_CODEC_CAP_DR1 | AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE, .caps_internal = FF_CODEC_CAP_NOT_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP, .defaults = vaapi_encode_h265_defaults, diff --git a/libavcodec/vaapi_encode_mpeg2.c b/libavcodec/vaapi_encode_mpeg2.c index 38e1d83f682..9261d19a831 100644 --- a/libavcodec/vaapi_encode_mpeg2.c +++ b/libavcodec/vaapi_encode_mpeg2.c @@ -698,7 +698,7 @@ const FFCodec ff_mpeg2_vaapi_encoder = { .close = &vaapi_encode_mpeg2_close, .p.priv_class = &vaapi_encode_mpeg2_class, .p.capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_HARDWARE | - AV_CODEC_CAP_DR1, + AV_CODEC_CAP_DR1 | AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE, .caps_internal = FF_CODEC_CAP_NOT_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP, .defaults = vaapi_encode_mpeg2_defaults, diff --git a/libavcodec/vaapi_encode_vp8.c b/libavcodec/vaapi_encode_vp8.c index 93e543d7984..ae6a8d313ca 100644 --- a/libavcodec/vaapi_encode_vp8.c +++ b/libavcodec/vaapi_encode_vp8.c @@ -253,7 +253,7 @@ const FFCodec ff_vp8_vaapi_encoder = { .close = &ff_vaapi_encode_close, .p.priv_class = &vaapi_encode_vp8_class, .p.capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_HARDWARE | - AV_CODEC_CAP_DR1, + AV_CODEC_CAP_DR1 | AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE, .caps_internal = FF_CODEC_CAP_NOT_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP, .defaults = vaapi_encode_vp8_defaults, diff --git a/libavcodec/vaapi_encode_vp9.c b/libavcodec/vaapi_encode_vp9.c index b4c5588730a..af1353cea80 100644 --- a/libavcodec/vaapi_encode_vp9.c +++ b/libavcodec/vaapi_encode_vp9.c @@ -308,7 +308,7 @@ const FFCodec ff_vp9_vaapi_encoder = { .close = &ff_vaapi_encode_close, .p.priv_class = &vaapi_encode_vp9_class, .p.capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_HARDWARE | - AV_CODEC_CAP_DR1, + AV_CODEC_CAP_DR1 | AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE, .caps_internal = FF_CODEC_CAP_NOT_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP, .defaults = vaapi_encode_vp9_defaults, From 476ec7787030b58a5ddb4226d5d5bdba1801c207 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Tue, 10 Jan 2023 13:31:22 +0100 Subject: [PATCH 0110/2172] lavc/libwebpenc_animencoder: stop setting dts unnecessarily WebP does not have reordering, so dts=pts is set by the generic code. --- libavcodec/libwebpenc_animencoder.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavcodec/libwebpenc_animencoder.c b/libavcodec/libwebpenc_animencoder.c index 0f2c190c8cb..977f880d6cd 100644 --- a/libavcodec/libwebpenc_animencoder.c +++ b/libavcodec/libwebpenc_animencoder.c @@ -77,7 +77,7 @@ static int libwebp_anim_encode_frame(AVCodecContext *avctx, AVPacket *pkt, memcpy(pkt->data, assembled_data.bytes, assembled_data.size); WebPDataClear(&assembled_data); s->done = 1; - pkt->pts = pkt->dts = s->first_frame_pts; + pkt->pts = s->first_frame_pts; *got_packet = 1; return 0; } else { From 782127d876f52400e61f78536ae759c2f3775528 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Tue, 10 Jan 2023 13:31:22 +0100 Subject: [PATCH 0111/2172] lavc/libwebpenc_animencoder: handle frame durations and AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE --- libavcodec/libwebpenc_animencoder.c | 39 +++++++++++++++++++++++++++-- 1 file changed, 37 insertions(+), 2 deletions(-) diff --git a/libavcodec/libwebpenc_animencoder.c b/libavcodec/libwebpenc_animencoder.c index 977f880d6cd..440cae1de55 100644 --- a/libavcodec/libwebpenc_animencoder.c +++ b/libavcodec/libwebpenc_animencoder.c @@ -24,6 +24,8 @@ * WebP encoder using libwebp (WebPAnimEncoder API) */ +#include "libavutil/buffer.h" + #include "config.h" #include "codec_internal.h" #include "encode.h" @@ -35,6 +37,12 @@ typedef struct LibWebPAnimContext { LibWebPContextCommon cc; WebPAnimEncoder *enc; // the main AnimEncoder object int64_t first_frame_pts; // pts of the first encoded frame. + int64_t end_pts; // pts + duration of the last frame + + int64_t reordered_opaque; + void *first_frame_opaque; + AVBufferRef *first_frame_opaque_ref; + int done; // If true, we have assembled the bitstream already } LibWebPAnimContext; @@ -78,6 +86,17 @@ static int libwebp_anim_encode_frame(AVCodecContext *avctx, AVPacket *pkt, WebPDataClear(&assembled_data); s->done = 1; pkt->pts = s->first_frame_pts; + + if (pkt->pts != AV_NOPTS_VALUE && s->end_pts > pkt->pts) + pkt->duration = s->end_pts - pkt->pts; + + avctx->reordered_opaque = s->reordered_opaque; + if (avctx->flags & AV_CODEC_FLAG_COPY_OPAQUE) { + pkt->opaque = s->first_frame_opaque; + pkt->opaque_ref = s->first_frame_opaque_ref; + s->first_frame_opaque_ref = NULL; + } + *got_packet = 1; return 0; } else { @@ -107,8 +126,21 @@ static int libwebp_anim_encode_frame(AVCodecContext *avctx, AVPacket *pkt, goto end; } - if (!avctx->frame_number) + if (!avctx->frame_number) { s->first_frame_pts = frame->pts; + s->reordered_opaque = frame->reordered_opaque; + + if (avctx->flags & AV_CODEC_FLAG_COPY_OPAQUE) { + s->first_frame_opaque = frame->opaque; + ret = av_buffer_replace(&s->first_frame_opaque_ref, frame->opaque_ref); + if (ret < 0) + goto end; + } + } + + if (frame->pts != AV_NOPTS_VALUE) + s->end_pts = frame->pts + frame->duration; + ret = 0; *got_packet = 0; @@ -126,6 +158,8 @@ static int libwebp_anim_encode_close(AVCodecContext *avctx) av_frame_free(&s->cc.ref); WebPAnimEncoderDelete(s->enc); + av_buffer_unref(&s->first_frame_opaque_ref); + return 0; } @@ -134,7 +168,8 @@ const FFCodec ff_libwebp_anim_encoder = { CODEC_LONG_NAME("libwebp WebP image"), .p.type = AVMEDIA_TYPE_VIDEO, .p.id = AV_CODEC_ID_WEBP, - .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_DELAY, + .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_DELAY | + AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE, .p.pix_fmts = ff_libwebpenc_pix_fmts, .p.priv_class = &ff_libwebpenc_class, .p.wrapper_name = "libwebp", From a172b33ebf19f91fcb9daf854af56af2e5fbbada Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Tue, 12 Jul 2022 14:37:15 +0200 Subject: [PATCH 0112/2172] lavc/libx264: pass through frame durations to encoded packets --- libavcodec/libx264.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/libavcodec/libx264.c b/libavcodec/libx264.c index 6d22a1726ec..2742fb11a06 100644 --- a/libavcodec/libx264.c +++ b/libavcodec/libx264.c @@ -52,6 +52,7 @@ typedef struct X264Opaque { int64_t reordered_opaque; int64_t wallclock; + int64_t duration; void *frame_opaque; AVBufferRef *frame_opaque_ref; @@ -459,6 +460,7 @@ static int setup_frame(AVCodecContext *ctx, const AVFrame *frame, } opaque->reordered_opaque = frame->reordered_opaque; + opaque->duration = frame->duration; opaque->wallclock = wallclock; if (ctx->export_side_data & AV_CODEC_EXPORT_DATA_PRFT) opaque->wallclock = av_gettime(); @@ -612,6 +614,7 @@ static int X264_frame(AVCodecContext *ctx, AVPacket *pkt, const AVFrame *frame, out_opaque < &x4->reordered_opaque[x4->nb_reordered_opaque]) { ctx->reordered_opaque = out_opaque->reordered_opaque; wallclock = out_opaque->wallclock; + pkt->duration = out_opaque->duration; if (ctx->flags & AV_CODEC_FLAG_COPY_OPAQUE) { pkt->opaque = out_opaque->frame_opaque; From d87055107d80dac898e5b2f58711e1958cbd8eb2 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Tue, 12 Jul 2022 14:37:15 +0200 Subject: [PATCH 0113/2172] lavc/libx265: pass through frame durations to encoded packets --- libavcodec/libx265.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/libavcodec/libx265.c b/libavcodec/libx265.c index a71f1f76d30..6fc189f1b5d 100644 --- a/libavcodec/libx265.c +++ b/libavcodec/libx265.c @@ -43,6 +43,7 @@ typedef struct ReorderedData { int64_t reordered_opaque; + int64_t duration; void *frame_opaque; AVBufferRef *frame_opaque_ref; @@ -616,6 +617,7 @@ static int libx265_encode_frame(AVCodecContext *avctx, AVPacket *pkt, } rd = &ctx->rd[rd_idx]; + rd->duration = pic->duration; rd->reordered_opaque = pic->reordered_opaque; if (avctx->flags & AV_CODEC_FLAG_COPY_OPAQUE) { rd->frame_opaque = pic->opaque; @@ -755,6 +757,7 @@ static int libx265_encode_frame(AVCodecContext *avctx, AVPacket *pkt, ReorderedData *rd = &ctx->rd[idx]; avctx->reordered_opaque = rd->reordered_opaque; + pkt->duration = rd->duration; if (avctx->flags & AV_CODEC_FLAG_COPY_OPAQUE) { pkt->opaque = rd->frame_opaque; From 7cf161abe5fecf817f2212363181adc4fe3ca32b Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Tue, 12 Jul 2022 14:37:15 +0200 Subject: [PATCH 0114/2172] lavc/libaomenc: pass through frame durations to encoded packets --- libavcodec/libaomenc.c | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/libavcodec/libaomenc.c b/libavcodec/libaomenc.c index bd576fdd3aa..0b88102c775 100644 --- a/libavcodec/libaomenc.c +++ b/libavcodec/libaomenc.c @@ -23,6 +23,8 @@ * AV1 encoder support via libaom */ +#include + #define AOM_DISABLE_CTRL_TYPECHECKS 1 #include #include @@ -1094,6 +1096,7 @@ static int storeframe(AVCodecContext *avctx, struct FrameListData *cx_frame, } memcpy(pkt->data, cx_frame->buf, pkt->size); pkt->pts = pkt->dts = cx_frame->pts; + pkt->duration = cx_frame->duration; if (!!(cx_frame->flags & AOM_FRAME_IS_KEY)) { pkt->flags |= AV_PKT_FLAG_KEY; @@ -1275,6 +1278,7 @@ static int aom_encode(AVCodecContext *avctx, AVPacket *pkt, AOMContext *ctx = avctx->priv_data; struct aom_image *rawimg = NULL; int64_t timestamp = 0; + unsigned long duration = 0; int res, coded_size; aom_enc_frame_flags_t flags = 0; @@ -1287,6 +1291,13 @@ static int aom_encode(AVCodecContext *avctx, AVPacket *pkt, rawimg->stride[AOM_PLANE_U] = frame->linesize[1]; rawimg->stride[AOM_PLANE_V] = frame->linesize[2]; timestamp = frame->pts; + + if (frame->duration > ULONG_MAX) { + av_log(avctx, AV_LOG_WARNING, + "Frame duration too large: %"PRId64"\n", frame->duration); + } else + duration = frame->duration ? frame->duration : avctx->ticks_per_frame; + switch (frame->color_range) { case AVCOL_RANGE_MPEG: rawimg->range = AOM_CR_STUDIO_RANGE; @@ -1300,8 +1311,7 @@ static int aom_encode(AVCodecContext *avctx, AVPacket *pkt, flags |= AOM_EFLAG_FORCE_KF; } - res = aom_codec_encode(&ctx->encoder, rawimg, timestamp, - avctx->ticks_per_frame, flags); + res = aom_codec_encode(&ctx->encoder, rawimg, timestamp, duration, flags); if (res != AOM_CODEC_OK) { log_encoder_error(avctx, "Error encoding frame"); return AVERROR_INVALIDDATA; From 65c0b169611853195046f885227a8824e6e0b63a Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Sun, 29 Jan 2023 13:08:15 +0100 Subject: [PATCH 0115/2172] avcodec/ftr: use more portable return error code --- libavcodec/ftr.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavcodec/ftr.c b/libavcodec/ftr.c index 277b9be5b88..74a2c10b5c8 100644 --- a/libavcodec/ftr.c +++ b/libavcodec/ftr.c @@ -37,7 +37,7 @@ static av_cold int ftr_init(AVCodecContext *avctx) if (avctx->ch_layout.nb_channels > 64 || avctx->ch_layout.nb_channels <= 0) - return AVERROR(ENOTSUP); + return AVERROR(EINVAL); s->packet = av_packet_alloc(); if (!s->packet) From 757218564dd50b462fab4cb6aa225d7bbdb2f94c Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Sun, 29 Jan 2023 13:10:20 +0100 Subject: [PATCH 0116/2172] avcodec/dvdsubenc: remove duplicated ; --- libavcodec/dvdsubenc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavcodec/dvdsubenc.c b/libavcodec/dvdsubenc.c index 0874aaa02dd..d272b576757 100644 --- a/libavcodec/dvdsubenc.c +++ b/libavcodec/dvdsubenc.c @@ -379,7 +379,7 @@ static int encode_dvd_subtitles(AVCodecContext *avctx, if (x2 > avctx->width || y2 > avctx->height) { av_log(avctx, AV_LOG_ERROR, "canvas_size(%d:%d) is too small(%d:%d) for render\n", avctx->width, avctx->height, x2, y2); - ret = AVERROR(EINVAL);; + ret = AVERROR(EINVAL); goto fail; } *q++ = 0x05; From 6aff3c5e434f91dee9f88541ad2ea73e03bbc583 Mon Sep 17 00:00:00 2001 From: Marton Balint Date: Wed, 28 Dec 2022 02:36:57 +0100 Subject: [PATCH 0117/2172] avformat/mxfdec: check index entry array size Signed-off-by: Marton Balint --- libavformat/mxfdec.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/libavformat/mxfdec.c b/libavformat/mxfdec.c index fa58854fcde..d843802f28b 100644 --- a/libavformat/mxfdec.c +++ b/libavformat/mxfdec.c @@ -1198,11 +1198,15 @@ static int mxf_read_essence_container_data(void *arg, AVIOContext *pb, int tag, static int mxf_read_index_entry_array(AVIOContext *pb, MXFIndexTableSegment *segment) { int i, length; + uint32_t nb_index_entries; if (segment->temporal_offset_entries) return AVERROR_INVALIDDATA; - segment->nb_index_entries = avio_rb32(pb); + nb_index_entries = avio_rb32(pb); + if (nb_index_entries > INT_MAX) + return AVERROR_INVALIDDATA; + segment->nb_index_entries = nb_index_entries; length = avio_rb32(pb); if(segment->nb_index_entries && length < 11) From 41dfa629d752145d73e56023a361ce487a3d4e8f Mon Sep 17 00:00:00 2001 From: Marton Balint Date: Wed, 28 Dec 2022 03:43:34 +0100 Subject: [PATCH 0118/2172] avformat/mxfdec: support Avid files with an extra index entry Signed-off-by: Marton Balint --- libavformat/mxfdec.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/libavformat/mxfdec.c b/libavformat/mxfdec.c index d843802f28b..efd0b9521cb 100644 --- a/libavformat/mxfdec.c +++ b/libavformat/mxfdec.c @@ -1991,11 +1991,11 @@ static int mxf_compute_ptses_fake_index(MXFContext *mxf, MXFIndexTable *index_ta int index_delta = 1; int n = s->nb_index_entries; - if (s->nb_index_entries == 2 * s->index_duration + 1) { + if (s->nb_index_entries == 2 * s->index_duration + 1) index_delta = 2; /* Avid index */ - /* ignore the last entry - it's the size of the essence container */ + if (s->nb_index_entries == index_delta * s->index_duration + 1) + /* ignore the last entry - it's the size of the essence container in Avid */ n--; - } for (j = 0; j < n; j += index_delta, x++) { int offset = s->temporal_offset_entries[j] / index_delta; From af606c232a9ecd30c69e7754547eb0dd232bc29d Mon Sep 17 00:00:00 2001 From: Marton Balint Date: Wed, 28 Dec 2022 03:20:11 +0100 Subject: [PATCH 0119/2172] avformat/mxfdec: check number of index table entires more strictly Let's ignore the index table if the number of index entries does not match the index duration (or the special AVID index entry counts). Fixes: OOM Fixes: 50551/clusterfuzz-testcase-minimized-ffmpeg_dem_MXF_fuzzer-6607795234930688 Found-by: continuous fuzzing process https://github.com/google/oss-fuzz/tree/master/projects/ffmpeg Signed-off-by: Marton Balint --- libavformat/mxfdec.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/libavformat/mxfdec.c b/libavformat/mxfdec.c index efd0b9521cb..45306172076 100644 --- a/libavformat/mxfdec.c +++ b/libavformat/mxfdec.c @@ -1937,6 +1937,14 @@ static int mxf_compute_ptses_fake_index(MXFContext *mxf, MXFIndexTable *index_ta return 0; } + if (s->nb_index_entries != s->index_duration && + s->nb_index_entries != s->index_duration + 1 && /* Avid index */ + s->nb_index_entries != s->index_duration * 2 + 1) { + index_table->nb_ptses = 0; + av_log(mxf->fc, AV_LOG_ERROR, "ignoring IndexSID %d, duration does not match nb_index_entries\n", s->index_sid); + return 0; + } + index_table->nb_ptses += s->index_duration; } From 4e3b6270c6e12537a26cc3c1f1032175fe823eb4 Mon Sep 17 00:00:00 2001 From: David Rosca Date: Tue, 17 Jan 2023 12:17:58 +0100 Subject: [PATCH 0120/2172] vaapi_encode_h264: Only set pic_order_cnt_type to 0 with B-frames v3: pic_order_cnt steps by 2 --- libavcodec/vaapi_encode_h264.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/libavcodec/vaapi_encode_h264.c b/libavcodec/vaapi_encode_h264.c index 0fe39056660..645f6a978db 100644 --- a/libavcodec/vaapi_encode_h264.c +++ b/libavcodec/vaapi_encode_h264.c @@ -361,8 +361,10 @@ static int vaapi_encode_h264_init_sequence_params(AVCodecContext *avctx) sps->chroma_format_idc = 1; sps->log2_max_frame_num_minus4 = 4; - sps->pic_order_cnt_type = 0; - sps->log2_max_pic_order_cnt_lsb_minus4 = 4; + sps->pic_order_cnt_type = ctx->max_b_depth ? 0 : 2; + if (sps->pic_order_cnt_type == 0) { + sps->log2_max_pic_order_cnt_lsb_minus4 = 4; + } sps->max_num_ref_frames = priv->dpb_frames; @@ -643,6 +645,10 @@ static int vaapi_encode_h264_init_picture_params(AVCodecContext *avctx, } } hpic->pic_order_cnt = pic->display_order - hpic->last_idr_frame; + if (priv->raw_sps.pic_order_cnt_type == 2) { + hpic->pic_order_cnt *= 2; + } + hpic->dpb_delay = pic->display_order - pic->encode_order + ctx->max_b_depth; hpic->cpb_delay = pic->encode_order - hpic->last_idr_frame; From aecfec6f80fd8be68e050a97935589beeae588fa Mon Sep 17 00:00:00 2001 From: Haihao Xiang Date: Thu, 19 Jan 2023 16:30:06 +0800 Subject: [PATCH 0121/2172] avfilter: add VA-API variants of the stack filters Include hstack_vaapi, vstack_vaapi and xstack_vaapi. They may accept input streams with different sizes. libva2 (VA-API 1.0+) is required. Example: $ ffmpeg -hwaccel vaapi -hwaccel_output_format vaapi -i input.h265 -filter_complex "[0:v][0:v]hstack_vaapi" -c:v h264_vaapi out.h264 $ ffmpeg \ -hwaccel vaapi -hwaccel_output_format vaapi -i input.h264 \ -hwaccel vaapi -hwaccel_output_format vaapi -i input.h264 \ -hwaccel vaapi -hwaccel_output_format vaapi -i input.h264 \ -hwaccel vaapi -hwaccel_output_format vaapi -i input.h264 \ -filter_complex "[0:v][1:v][2:v][3:v]xstack_vaapi=inputs=4:fill=0x000000:layout=0_0_1920x1080|w0_0_1920x1080|0_h0_1920x1080|w0_h0_1920x1080" \ -c:v hevc_vaapi out.h265 Signed-off-by: Haihao Xiang --- Changelog | 1 + configure | 3 + doc/filters.texi | 81 +++++ libavfilter/Makefile | 3 + libavfilter/allfilters.c | 3 + libavfilter/version.h | 2 +- libavfilter/vf_stack_vaapi.c | 574 +++++++++++++++++++++++++++++++++++ 7 files changed, 666 insertions(+), 1 deletion(-) create mode 100644 libavfilter/vf_stack_vaapi.c diff --git a/Changelog b/Changelog index e07a039ca4e..a0f1ad7211a 100644 --- a/Changelog +++ b/Changelog @@ -33,6 +33,7 @@ version : - CBD2 DPCM decoder - ssim360 video filter - ffmpeg CLI new options: -enc_stats_pre[_fmt], -enc_stats_post[_fmt] +- hstack_vaapi, vstack_vaapi and xstack_vaapi filters version 5.1: diff --git a/configure b/configure index cb895cf9ac6..8190e978a8a 100755 --- a/configure +++ b/configure @@ -3766,6 +3766,9 @@ 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" +hstack_vaapi_filter_deps="vaapi_1" +vstack_vaapi_filter_deps="vaapi_1" +xstack_vaapi_filter_deps="vaapi_1" # examples avio_list_dir_deps="avformat avutil" diff --git a/doc/filters.texi b/doc/filters.texi index 4f4d2ea807b..3a54c68f3e7 100644 --- a/doc/filters.texi +++ b/doc/filters.texi @@ -14941,6 +14941,7 @@ Set the scaling dimension: @code{2} for @code{hq2x}, @code{3} for Default is @code{3}. @end table +@anchor{hstack} @section hstack Stack input videos horizontally. @@ -24392,6 +24393,7 @@ Example: ffmpeg -i ref.mpg -vf vmafmotion -f null - @end example +@anchor{vstack} @section vstack Stack input videos vertically. @@ -24873,6 +24875,7 @@ minimum values, and @code{1} maximum values. This filter supports all above options as @ref{commands}, excluding option @code{inputs}. +@anchor{xstack} @section xstack Stack video inputs into custom layout. @@ -26689,6 +26692,84 @@ tonemap_vaapi=format=p010:t=bt2020-10 @end example @end itemize +@section hstack_vaapi +Stack input videos horizontally. + +This is the VA-API variant of the @ref{hstack} filter, each input stream may +have different height, this filter will scale down/up each input stream while +keeping the orignal aspect. + +It accepts the following options: + +@table @option +@item inputs +See @ref{hstack}. + +@item shortest +See @ref{hstack}. + +@item height +Set height of output. If set to 0, this filter will set height of output to +height of the first input stream. Default value is 0. +@end table + +@section vstack_vaapi +Stack input videos vertically. + +This is the VA-API variant of the @ref{vstack} filter, each input stream may +have different width, this filter will scale down/up each input stream while +keeping the orignal aspect. + +It accepts the following options: + +@table @option +@item inputs +See @ref{vstack}. + +@item shortest +See @ref{vstack}. + +@item width +Set width of output. If set to 0, this filter will set width of output to +width of the first input stream. Default value is 0. +@end table + +@section xstack_vaapi +Stack video inputs into custom layout. + +This is the VA-API variant of the @ref{xstack} filter, each input stream may +have different size, this filter will scale down/up each input stream to the +given output size, or the size of the first input stream. + +It accepts the following options: + +@table @option +@item inputs +See @ref{xstack}. + +@item shortest +See @ref{xstack}. + +@item layout +See @ref{xstack}. +Moreover, this permits the user to supply output size for each input stream. +@example +xstack_vaapi=inputs=4:layout=0_0_1920x1080|0_h0_1920x1080|w0_0_1920x1080|w0_h0_1920x1080 +@end example + +@item grid +See @ref{xstack}. + +@item grid_tile_size +Set output size for each input stream when @option{grid} is set. If this option +is not set, this filter will set output size by default to the size of the +first input stream. For the syntax of this option, check the +@ref{video size syntax,,"Video size" section in the ffmpeg-utils manual,ffmpeg-utils}. + +@item fill +See @ref{xstack}. +@end table + @c man end VAAPI VIDEO FILTERS @chapter Video Sources diff --git a/libavfilter/Makefile b/libavfilter/Makefile index d4e38bd4e8b..a0059c69e6a 100644 --- a/libavfilter/Makefile +++ b/libavfilter/Makefile @@ -558,6 +558,9 @@ OBJS-$(CONFIG_YAEPBLUR_FILTER) += vf_yaepblur.o OBJS-$(CONFIG_ZMQ_FILTER) += f_zmq.o OBJS-$(CONFIG_ZOOMPAN_FILTER) += vf_zoompan.o OBJS-$(CONFIG_ZSCALE_FILTER) += vf_zscale.o +OBJS-$(CONFIG_HSTACK_VAAPI_FILTER) += vf_stack_vaapi.o framesync.o vaapi_vpp.o +OBJS-$(CONFIG_VSTACK_VAAPI_FILTER) += vf_stack_vaapi.o framesync.o vaapi_vpp.o +OBJS-$(CONFIG_XSTACK_VAAPI_FILTER) += vf_stack_vaapi.o framesync.o vaapi_vpp.o OBJS-$(CONFIG_ALLRGB_FILTER) += vsrc_testsrc.o OBJS-$(CONFIG_ALLYUV_FILTER) += vsrc_testsrc.o diff --git a/libavfilter/allfilters.c b/libavfilter/allfilters.c index 5c86d0789f9..9cdcca48534 100644 --- a/libavfilter/allfilters.c +++ b/libavfilter/allfilters.c @@ -523,6 +523,9 @@ extern const AVFilter ff_vf_yaepblur; extern const AVFilter ff_vf_zmq; extern const AVFilter ff_vf_zoompan; extern const AVFilter ff_vf_zscale; +extern const AVFilter ff_vf_hstack_vaapi; +extern const AVFilter ff_vf_vstack_vaapi; +extern const AVFilter ff_vf_xstack_vaapi; extern const AVFilter ff_vsrc_allrgb; extern const AVFilter ff_vsrc_allyuv; diff --git a/libavfilter/version.h b/libavfilter/version.h index 09b9954597b..057ab634157 100644 --- a/libavfilter/version.h +++ b/libavfilter/version.h @@ -31,7 +31,7 @@ #include "version_major.h" -#define LIBAVFILTER_VERSION_MINOR 55 +#define LIBAVFILTER_VERSION_MINOR 56 #define LIBAVFILTER_VERSION_MICRO 100 diff --git a/libavfilter/vf_stack_vaapi.c b/libavfilter/vf_stack_vaapi.c new file mode 100644 index 00000000000..403fbb19eb1 --- /dev/null +++ b/libavfilter/vf_stack_vaapi.c @@ -0,0 +1,574 @@ +/* + * 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 + * Hardware accelerated hstack, vstack and xstack filters based on VA-API + */ + +#include "config_components.h" + +#include "libavutil/opt.h" +#include "libavutil/common.h" +#include "libavutil/pixdesc.h" +#include "libavutil/eval.h" +#include "libavutil/hwcontext.h" +#include "libavutil/avstring.h" +#include "libavutil/avassert.h" +#include "libavutil/imgutils.h" +#include "libavutil/mathematics.h" +#include "libavutil/parseutils.h" +#include "libavutil/mem.h" + +#include "internal.h" +#include "filters.h" +#include "formats.h" +#include "video.h" +#include "framesync.h" +#include "vaapi_vpp.h" + +#define OFFSET(x) offsetof(StackVAAPIContext, x) +#define FLAGS (AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_FILTERING_PARAM) + +enum { + STACK_VAAPI_H = 0, + STACK_VAAPI_V = 1, + STACK_VAAPI_X = 2 +}; + +typedef struct StackVAAPIContext { + VAAPIVPPContext vppctx; /**< must be the first field */ + + FFFrameSync fs; + int mode; + VARectangle *rects; + uint8_t fillcolor[4]; + int fillcolor_enable; + + /* Options */ + int nb_inputs; + int shortest; + int tile_width; + int tile_height; + int nb_grid_columns; + int nb_grid_rows; + char *layout; + char *fillcolor_str; +} StackVAAPIContext; + +static int process_frame(FFFrameSync *fs) +{ + AVFilterContext *avctx = fs->parent; + AVFilterLink *outlink = avctx->outputs[0]; + StackVAAPIContext *sctx = fs->opaque; + VAAPIVPPContext *vppctx = fs->opaque; + AVFrame *oframe, *iframe; + VAProcPipelineParameterBuffer *params = NULL; + VARectangle *irect = NULL; + int ret = 0; + + if (vppctx->va_context == VA_INVALID_ID) + return AVERROR(EINVAL); + + oframe = ff_get_video_buffer(outlink, outlink->w, outlink->h); + if (!oframe) + return AVERROR(ENOMEM); + + irect = av_calloc(avctx->nb_inputs, sizeof(*irect)); + params = av_calloc(avctx->nb_inputs, sizeof(*params)); + if (!irect || !params) { + ret = AVERROR(ENOMEM); + goto fail; + } + + for (int i = 0; i < avctx->nb_inputs; i++) { + ret = ff_framesync_get_frame(fs, i, &iframe, 0); + if (ret) + goto fail; + + if (i == 0) { + ret = av_frame_copy_props(oframe, iframe); + if (ret < 0) + goto fail; + } + + ret = ff_vaapi_vpp_init_params(avctx, ¶ms[i], iframe, oframe); + if (ret) + goto fail; + + av_log(avctx, AV_LOG_DEBUG, "stack input %d: %s, %ux%u (%"PRId64").\n", + i, av_get_pix_fmt_name(iframe->format), + iframe->width, iframe->height, iframe->pts); + irect[i].x = 0; + irect[i].y = 0; + irect[i].width = iframe->width; + irect[i].height = iframe->height; + params[i].surface_region = &irect[i]; + params[i].surface = (VASurfaceID)(uintptr_t)iframe->data[3]; + params[i].output_region = &sctx->rects[i]; + + if (sctx->fillcolor_enable) + params[i].output_background_color = (sctx->fillcolor[3] << 24 | + sctx->fillcolor[0] << 16 | + sctx->fillcolor[1] << 8 | + sctx->fillcolor[2]); + } + + oframe->pts = av_rescale_q(sctx->fs.pts, sctx->fs.time_base, outlink->time_base); + oframe->sample_aspect_ratio = outlink->sample_aspect_ratio; + + ret = ff_vaapi_vpp_render_pictures(avctx, params, avctx->nb_inputs, oframe); + if (ret) + goto fail; + + av_freep(&irect); + av_freep(¶ms); + return ff_filter_frame(outlink, oframe); + +fail: + av_freep(&irect); + av_freep(¶ms); + av_frame_free(&oframe); + return ret; +} + +static int init_framesync(AVFilterContext *avctx) +{ + StackVAAPIContext *sctx = avctx->priv; + int ret; + + ret = ff_framesync_init(&sctx->fs, avctx, avctx->nb_inputs); + if (ret < 0) + return ret; + + sctx->fs.on_event = process_frame; + sctx->fs.opaque = sctx; + + for (int i = 0; i < sctx->nb_inputs; i++) { + FFFrameSyncIn *in = &sctx->fs.in[i]; + + in->before = EXT_STOP; + in->after = sctx->shortest ? EXT_STOP : EXT_INFINITY; + in->sync = 1; + in->time_base = avctx->inputs[i]->time_base; + } + + return ff_framesync_configure(&sctx->fs); +} + +#define SET_INPUT_REGION(rect, rx, ry, rw, rh) do { \ + rect->x = rx; \ + rect->y = ry; \ + rect->width = rw; \ + rect->height = rh; \ + } while (0) + +static int config_output(AVFilterLink *outlink) +{ + AVFilterContext *avctx = outlink->src; + StackVAAPIContext *sctx = avctx->priv; + VAAPIVPPContext *vppctx = avctx->priv; + AVFilterLink *inlink0 = avctx->inputs[0]; + AVHWFramesContext *hwfc0 = NULL; + int width, height, ret; + + if (inlink0->format != AV_PIX_FMT_VAAPI || !inlink0->hw_frames_ctx || !inlink0->hw_frames_ctx->data) { + av_log(avctx, AV_LOG_ERROR, "Software pixel format is not supported.\n"); + return AVERROR(EINVAL); + } + + hwfc0 = (AVHWFramesContext *)inlink0->hw_frames_ctx->data; + + for (int i = 1; i < sctx->nb_inputs; i++) { + AVFilterLink *inlink = avctx->inputs[i]; + AVHWFramesContext *hwfc = NULL; + + if (inlink->format != AV_PIX_FMT_VAAPI || !inlink->hw_frames_ctx || !inlink->hw_frames_ctx->data) { + av_log(avctx, AV_LOG_ERROR, "Software pixel format is not supported.\n"); + return AVERROR(EINVAL); + } + + hwfc = (AVHWFramesContext *)inlink->hw_frames_ctx->data; + + if (hwfc0->sw_format != hwfc->sw_format) { + av_log(avctx, AV_LOG_ERROR, "All inputs should have the same underlying software pixel format.\n"); + return AVERROR(EINVAL); + } + + if (hwfc0->device_ctx != hwfc->device_ctx) { + av_log(avctx, AV_LOG_ERROR, "All inputs should have the same underlying vaapi devices.\n"); + return AVERROR(EINVAL); + } + } + + ff_vaapi_vpp_config_input(inlink0); + vppctx->output_format = hwfc0->sw_format; + + if (sctx->mode == STACK_VAAPI_H) { + height = sctx->tile_height; + width = 0; + + if (!height) + height = inlink0->h; + + for (int i = 0; i < sctx->nb_inputs; i++) { + AVFilterLink *inlink = avctx->inputs[i]; + VARectangle *rect = &sctx->rects[i]; + + SET_INPUT_REGION(rect, width, 0, av_rescale(height, inlink->w, inlink->h), height); + width += av_rescale(height, inlink->w, inlink->h); + } + } else if (sctx->mode == STACK_VAAPI_V) { + height = 0; + width = sctx->tile_width; + + if (!width) + width = inlink0->w; + + for (int i = 0; i < sctx->nb_inputs; i++) { + AVFilterLink *inlink = avctx->inputs[i]; + VARectangle *rect = &sctx->rects[i]; + + SET_INPUT_REGION(rect, 0, height, width, av_rescale(width, inlink->h, inlink->w)); + height += av_rescale(width, inlink->h, inlink->w); + } + } else if (sctx->nb_grid_rows && sctx->nb_grid_columns) { + int xpos = 0, ypos = 0; + int ow, oh, k = 0; + + ow = sctx->tile_width; + oh = sctx->tile_height; + + if (!ow || !oh) { + ow = avctx->inputs[0]->w; + oh = avctx->inputs[0]->h; + } + + for (int i = 0; i < sctx->nb_grid_columns; i++) { + ypos = 0; + + for (int j = 0; j < sctx->nb_grid_rows; j++) { + VARectangle *rect = &sctx->rects[k++]; + + SET_INPUT_REGION(rect, xpos, ypos, ow, oh); + ypos += oh; + } + + xpos += ow; + } + + width = ow * sctx->nb_grid_columns; + height = oh * sctx->nb_grid_rows; + } else { + char *arg, *p = sctx->layout, *saveptr = NULL; + char *arg2, *p2, *saveptr2 = NULL; + char *arg3, *p3, *saveptr3 = NULL; + int xpos, ypos, size; + int ow, oh; + + width = avctx->inputs[0]->w; + height = avctx->inputs[0]->h; + + for (int i = 0; i < sctx->nb_inputs; i++) { + AVFilterLink *inlink = avctx->inputs[i]; + VARectangle *rect = &sctx->rects[i]; + + ow = inlink->w; + oh = inlink->h; + + if (!(arg = av_strtok(p, "|", &saveptr))) + return AVERROR(EINVAL); + + p = NULL; + p2 = arg; + xpos = ypos = 0; + + for (int j = 0; j < 3; j++) { + if (!(arg2 = av_strtok(p2, "_", &saveptr2))) { + if (j == 2) + break; + else + return AVERROR(EINVAL); + } + + p2 = NULL; + p3 = arg2; + + if (j == 2) { + if ((ret = av_parse_video_size(&ow, &oh, p3)) < 0) { + av_log(avctx, AV_LOG_ERROR, "Invalid size '%s'\n", p3); + return ret; + } + + break; + } + + while ((arg3 = av_strtok(p3, "+", &saveptr3))) { + p3 = NULL; + if (sscanf(arg3, "w%d", &size) == 1) { + if (size == i || size < 0 || size >= sctx->nb_inputs) + return AVERROR(EINVAL); + + if (!j) + xpos += sctx->rects[size].width; + else + ypos += sctx->rects[size].width; + } else if (sscanf(arg3, "h%d", &size) == 1) { + if (size == i || size < 0 || size >= sctx->nb_inputs) + return AVERROR(EINVAL); + + if (!j) + xpos += sctx->rects[size].height; + else + ypos += sctx->rects[size].height; + } else if (sscanf(arg3, "%d", &size) == 1) { + if (size < 0) + return AVERROR(EINVAL); + + if (!j) + xpos += size; + else + ypos += size; + } else { + return AVERROR(EINVAL); + } + } + } + + SET_INPUT_REGION(rect, xpos, ypos, ow, oh); + width = FFMAX(width, xpos + ow); + height = FFMAX(height, ypos + oh); + } + + } + + outlink->w = width; + outlink->h = height; + outlink->frame_rate = inlink0->frame_rate; + outlink->sample_aspect_ratio = inlink0->sample_aspect_ratio; + + for (int i = 1; i < sctx->nb_inputs; i++) { + AVFilterLink *inlink = avctx->inputs[i]; + if (outlink->frame_rate.num != inlink->frame_rate.num || + outlink->frame_rate.den != inlink->frame_rate.den) { + av_log(avctx, AV_LOG_VERBOSE, + "Video inputs have different frame rates, output will be VFR\n"); + outlink->frame_rate = av_make_q(1, 0); + break; + } + } + + ret = init_framesync(avctx); + if (ret < 0) + return ret; + + outlink->time_base = sctx->fs.time_base; + + vppctx->output_width = width; + vppctx->output_height = height; + + return ff_vaapi_vpp_config_output(outlink); +} + +static int vaapi_stack_init(AVFilterContext *avctx) +{ + StackVAAPIContext *sctx = avctx->priv; + VAAPIVPPContext *vppctx = avctx->priv; + int ret; + + if (!strcmp(avctx->filter->name, "hstack_vaapi")) + sctx->mode = STACK_VAAPI_H; + else if (!strcmp(avctx->filter->name, "vstack_vaapi")) + sctx->mode = STACK_VAAPI_V; + else { + int is_grid; + + av_assert0(strcmp(avctx->filter->name, "xstack_vaapi") == 0); + sctx->mode = STACK_VAAPI_X; + is_grid = sctx->nb_grid_rows && sctx->nb_grid_columns; + + if (sctx->layout && is_grid) { + av_log(avctx, AV_LOG_ERROR, "Both layout and grid were specified. Only one is allowed.\n"); + return AVERROR(EINVAL); + } + + if (!sctx->layout && !is_grid) { + if (sctx->nb_inputs == 2) { + sctx->nb_grid_rows = 1; + sctx->nb_grid_columns = 2; + is_grid = 1; + } else { + av_log(avctx, AV_LOG_ERROR, "No layout or grid specified.\n"); + return AVERROR(EINVAL); + } + } + + if (is_grid) + sctx->nb_inputs = sctx->nb_grid_rows * sctx->nb_grid_columns; + + if (strcmp(sctx->fillcolor_str, "none") && + av_parse_color(sctx->fillcolor, sctx->fillcolor_str, -1, avctx) >= 0) { + sctx->fillcolor_enable = 1; + } else { + sctx->fillcolor_enable = 0; + } + } + + for (int i = 0; i < sctx->nb_inputs; i++) { + AVFilterPad pad = { 0 }; + + pad.type = AVMEDIA_TYPE_VIDEO; + pad.name = av_asprintf("input%d", i); + + if (!pad.name) + return AVERROR(ENOMEM); + + if ((ret = ff_append_inpad_free_name(avctx, &pad)) < 0) + return ret; + } + + /* stack region */ + sctx->rects = av_calloc(sctx->nb_inputs, sizeof(*sctx->rects)); + if (!sctx->rects) + return AVERROR(ENOMEM); + + ff_vaapi_vpp_ctx_init(avctx); + vppctx->output_format = AV_PIX_FMT_NONE; + + return 0; +} + +static av_cold void vaapi_stack_uninit(AVFilterContext *avctx) +{ + StackVAAPIContext *sctx = avctx->priv; + + ff_framesync_uninit(&sctx->fs); + av_freep(&sctx->rects); +} + +static int vaapi_stack_activate(AVFilterContext *avctx) +{ + StackVAAPIContext *sctx = avctx->priv; + return ff_framesync_activate(&sctx->fs); +} + +static int vaapi_stack_query_formats(AVFilterContext *avctx) +{ + static const enum AVPixelFormat pixel_formats[] = { + AV_PIX_FMT_VAAPI, + AV_PIX_FMT_NONE, + }; + + return ff_set_common_formats_from_list(avctx, pixel_formats); +} + +static const AVFilterPad vaapi_stack_outputs[] = { + { + .name = "default", + .type = AVMEDIA_TYPE_VIDEO, + .config_props = config_output, + }, +}; + +#define STACK_COMMON_OPTS \ + { "inputs", "Set number of inputs", OFFSET(nb_inputs), AV_OPT_TYPE_INT, { .i64 = 2 }, 2, UINT16_MAX, .flags = FLAGS }, \ + { "shortest", "Force termination when the shortest input terminates", OFFSET(shortest), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, FLAGS }, + +#if CONFIG_HSTACK_VAAPI_FILTER + +static const AVOption hstack_vaapi_options[] = { + STACK_COMMON_OPTS + + { "height", "Set output height (0 to use the height of input 0)", OFFSET(tile_height), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, UINT16_MAX, FLAGS }, + { NULL } +}; + +AVFILTER_DEFINE_CLASS(hstack_vaapi); + +const AVFilter ff_vf_hstack_vaapi = { + .name = "hstack_vaapi", + .description = NULL_IF_CONFIG_SMALL("VA-API hstack."), + .priv_size = sizeof(StackVAAPIContext), + .priv_class = &hstack_vaapi_class, + .init = vaapi_stack_init, + .uninit = vaapi_stack_uninit, + .activate = vaapi_stack_activate, + FILTER_QUERY_FUNC(vaapi_stack_query_formats), + FILTER_OUTPUTS(vaapi_stack_outputs), + .flags_internal = FF_FILTER_FLAG_HWFRAME_AWARE, + .flags = AVFILTER_FLAG_DYNAMIC_INPUTS, +}; + +#endif + +#if CONFIG_VSTACK_VAAPI_FILTER + +static const AVOption vstack_vaapi_options[] = { + STACK_COMMON_OPTS + + { "width", "Set output width (0 to use the width of input 0)", OFFSET(tile_width), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, UINT16_MAX, FLAGS }, + { NULL } +}; + +AVFILTER_DEFINE_CLASS(vstack_vaapi); + +const AVFilter ff_vf_vstack_vaapi = { + .name = "vstack_vaapi", + .description = NULL_IF_CONFIG_SMALL("VA-API vstack."), + .priv_size = sizeof(StackVAAPIContext), + .priv_class = &vstack_vaapi_class, + .init = vaapi_stack_init, + .uninit = vaapi_stack_uninit, + .activate = vaapi_stack_activate, + FILTER_QUERY_FUNC(vaapi_stack_query_formats), + FILTER_OUTPUTS(vaapi_stack_outputs), + .flags_internal = FF_FILTER_FLAG_HWFRAME_AWARE, + .flags = AVFILTER_FLAG_DYNAMIC_INPUTS, +}; + +#endif + +#if CONFIG_XSTACK_VAAPI_FILTER + +static const AVOption xstack_vaapi_options[] = { + STACK_COMMON_OPTS + + { "layout", "Set custom layout", OFFSET(layout), AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, .flags = FLAGS }, + { "grid", "set fixed size grid layout", OFFSET(nb_grid_columns), AV_OPT_TYPE_IMAGE_SIZE, {.str = NULL}, 0, 0, .flags = FLAGS }, + { "grid_tile_size", "set tile size in grid layout", OFFSET(tile_width), AV_OPT_TYPE_IMAGE_SIZE, {.str = NULL}, 0, 0, .flags = FLAGS }, + { "fill", "Set the color for unused pixels", OFFSET(fillcolor_str), AV_OPT_TYPE_STRING, {.str = "none"}, .flags = FLAGS }, + { NULL } +}; + +AVFILTER_DEFINE_CLASS(xstack_vaapi); + +const AVFilter ff_vf_xstack_vaapi = { + .name = "xstack_vaapi", + .description = NULL_IF_CONFIG_SMALL("VA-API xstack."), + .priv_size = sizeof(StackVAAPIContext), + .priv_class = &xstack_vaapi_class, + .init = vaapi_stack_init, + .uninit = vaapi_stack_uninit, + .activate = vaapi_stack_activate, + FILTER_OUTPUTS(vaapi_stack_outputs), + FILTER_QUERY_FUNC(vaapi_stack_query_formats), + .flags_internal = FF_FILTER_FLAG_HWFRAME_AWARE, + .flags = AVFILTER_FLAG_DYNAMIC_INPUTS, +}; + +#endif From 500282941655558e2440afe163f0268dc5ac61bf Mon Sep 17 00:00:00 2001 From: galinart Date: Mon, 5 Dec 2022 20:18:21 +0000 Subject: [PATCH 0122/2172] libavcodec/qsvenc: enable Hyper Encode Hyper Encode uses Intel integrated and discrete graphics on one system to accelerate encoding of a single video stream. Depending on the selected parameters and codecs, performance gain on AlderLake iGPU + ARC Gfx up to 1.6x. More information: https://www.intel.co.uk/content/www/uk/en/architecture-and-technology/adaptix/deep-link.html Developer guide: https://github.com/oneapi-src/oneVPL-intel-gpu/blob/main/doc/HyperEncode_FeatureDeveloperGuide.md Hyper Encode is supported only on Windows and requires D3D11 and oneVPL. To enable Hyper Encode need to specify: -Hyper Encode mode (-dual_gfx on or dual_gfx adaptive) -Encoder: h264_qsv or hevc_qsv -BRC: VBR, CQP or ICQ -Lowpower mode (-low_power 1) -Closed GOP for AVC or strict GOP for HEVC -idr_interval = 0 used by default Depending on the encoding parameters, the following parameters may need to be adjusted: -g recommended >= 30 for better performance -async_depth recommended >= 30 for better performance -extra_hw_frames recommended equal to async_depth value -bf recommended = 0 for better performance In the cases with fast encoding (-preset veryfast) there may be no performance gain due to the fact that the decode is slower than the encode. Command line examples: ffmpeg.exe -init_hw_device qsv:hw,child_device_type=d3d11va,child_device=0 -v verbose -y -hwaccel qsv -extra_hw_frames 60 -async_depth 60 -c:v h264_qsv -i bbb_sunflower_2160p_60fps_normal.mp4 -async_depth 60 -c:v h264_qsv -preset medium -g 60 -low_power 1 -bf 0 -dual_gfx on output.h265 Signed-off-by: galinart --- libavcodec/qsvenc.c | 91 +++++++++++++++++++++++++++++++++++++++- libavcodec/qsvenc.h | 19 ++++++++- libavcodec/qsvenc_h264.c | 3 ++ libavcodec/qsvenc_hevc.c | 3 ++ 4 files changed, 112 insertions(+), 4 deletions(-) diff --git a/libavcodec/qsvenc.c b/libavcodec/qsvenc.c index 93f1862a4b2..2f0e94a9148 100644 --- a/libavcodec/qsvenc.c +++ b/libavcodec/qsvenc.c @@ -169,6 +169,8 @@ do { \ } \ } while (0) \ +#define MFX_IMPL_VIA_MASK(impl) (0x0f00 & (impl)) + static const char *print_ratecontrol(mfxU16 rc_mode) { int i; @@ -197,6 +199,10 @@ static void dump_video_param(AVCodecContext *avctx, QSVEncContext *q, mfxExtCodingOption2 *co2 = NULL; mfxExtCodingOption3 *co3 = NULL; mfxExtHEVCTiles *exthevctiles = NULL; +#if QSV_HAVE_HE + mfxExtHyperModeParam *exthypermodeparam = NULL; +#endif + const char *tmp_str = NULL; if (q->co2_idx > 0) @@ -208,6 +214,11 @@ static void dump_video_param(AVCodecContext *avctx, QSVEncContext *q, if (q->exthevctiles_idx > 0) exthevctiles = (mfxExtHEVCTiles *)coding_opts[q->exthevctiles_idx]; +#if QSV_HAVE_HE + if (q->exthypermodeparam_idx > 0) + exthypermodeparam = (mfxExtHyperModeParam *)coding_opts[q->exthypermodeparam_idx]; +#endif + av_log(avctx, AV_LOG_VERBOSE, "profile: %s; level: %"PRIu16"\n", print_profile(avctx->codec_id, info->CodecProfile), info->CodecLevel); @@ -373,6 +384,21 @@ static void dump_video_param(AVCodecContext *avctx, QSVEncContext *q, av_log(avctx, AV_LOG_VERBOSE, "NumTileColumns: %"PRIu16"; NumTileRows: %"PRIu16"\n", exthevctiles->NumTileColumns, exthevctiles->NumTileRows); } + +#if QSV_HAVE_HE + if (exthypermodeparam) { + av_log(avctx, AV_LOG_VERBOSE, "HyperEncode: "); + + if (exthypermodeparam->Mode == MFX_HYPERMODE_OFF) + av_log(avctx, AV_LOG_VERBOSE, "OFF"); + if (exthypermodeparam->Mode == MFX_HYPERMODE_ON) + av_log(avctx, AV_LOG_VERBOSE, "ON"); + if (exthypermodeparam->Mode == MFX_HYPERMODE_ADAPTIVE) + av_log(avctx, AV_LOG_VERBOSE, "Adaptive"); + + av_log(avctx, AV_LOG_VERBOSE, "\n"); + } +#endif } static void dump_video_vp9_param(AVCodecContext *avctx, QSVEncContext *q, @@ -1168,6 +1194,54 @@ static int init_video_param(AVCodecContext *avctx, QSVEncContext *q) q->extparam_internal[q->nb_extparam_internal++] = (mfxExtBuffer *)&q->extvsi; } +#if QSV_HAVE_HE + if (q->dual_gfx) { + if (QSV_RUNTIME_VERSION_ATLEAST(q->ver, 2, 4)) { + mfxIMPL impl; + MFXQueryIMPL(q->session, &impl); + + if (MFX_IMPL_VIA_MASK(impl) != MFX_IMPL_VIA_D3D11) { + av_log(avctx, AV_LOG_ERROR, "Dual GFX mode requires D3D11VA \n"); + return AVERROR_UNKNOWN; + } + if (q->param.mfx.LowPower != MFX_CODINGOPTION_ON) { + av_log(avctx, AV_LOG_ERROR, "Dual GFX mode supports only low-power encoding mode \n"); + return AVERROR_UNKNOWN; + } + if (q->param.mfx.CodecId != MFX_CODEC_AVC && q->param.mfx.CodecId != MFX_CODEC_HEVC) { + av_log(avctx, AV_LOG_ERROR, "Not supported encoder for dual GFX mode. " + "Supported: h264_qsv and hevc_qsv \n"); + return AVERROR_UNKNOWN; + } + if (q->param.mfx.RateControlMethod != MFX_RATECONTROL_VBR && + q->param.mfx.RateControlMethod != MFX_RATECONTROL_CQP && + q->param.mfx.RateControlMethod != MFX_RATECONTROL_ICQ) { + av_log(avctx, AV_LOG_WARNING, "Not supported BRC for dual GFX mode. " + "Supported: VBR, CQP and ICQ \n"); + } + if ((q->param.mfx.CodecId == MFX_CODEC_AVC && q->param.mfx.IdrInterval != 0) || + (q->param.mfx.CodecId == MFX_CODEC_HEVC && q->param.mfx.IdrInterval != 1)) { + av_log(avctx, AV_LOG_WARNING, "Dual GFX mode requires closed GOP for AVC and strict GOP for HEVC, -idr_interval 0 \n"); + } + if (q->param.mfx.GopPicSize < 30) { + av_log(avctx, AV_LOG_WARNING, "For better performance in dual GFX mode GopPicSize must be >= 30 \n"); + } + if (q->param.AsyncDepth < 30) { + av_log(avctx, AV_LOG_WARNING, "For better performance in dual GFX mode AsyncDepth must be >= 30 \n"); + } + + q->exthypermodeparam.Header.BufferId = MFX_EXTBUFF_HYPER_MODE_PARAM; + q->exthypermodeparam.Header.BufferSz = sizeof(q->exthypermodeparam); + q->exthypermodeparam.Mode = q->dual_gfx; + q->extparam_internal[q->nb_extparam_internal++] = (mfxExtBuffer *)&q->exthypermodeparam; + } else { + av_log(avctx, AV_LOG_ERROR, + "This version of runtime doesn't support Hyper Encode\n"); + return AVERROR_UNKNOWN; + } + } +#endif + if (!check_enc_param(avctx,q)) { av_log(avctx, AV_LOG_ERROR, "some encoding parameters are not supported by the QSV " @@ -1342,12 +1416,19 @@ static int qsv_retrieve_enc_params(AVCodecContext *avctx, QSVEncContext *q) .Header.BufferSz = sizeof(hevc_tile_buf), }; - mfxExtBuffer *ext_buffers[6]; +#if QSV_HAVE_HE + mfxExtHyperModeParam hyper_mode_param_buf = { + .Header.BufferId = MFX_EXTBUFF_HYPER_MODE_PARAM, + .Header.BufferSz = sizeof(hyper_mode_param_buf), + }; +#endif + + mfxExtBuffer *ext_buffers[6 + QSV_HAVE_HE]; int need_pps = avctx->codec_id != AV_CODEC_ID_MPEG2VIDEO; int ret, ext_buf_num = 0, extradata_offset = 0; - q->co2_idx = q->co3_idx = q->exthevctiles_idx = -1; + q->co2_idx = q->co3_idx = q->exthevctiles_idx = q->exthypermodeparam_idx = -1; ext_buffers[ext_buf_num++] = (mfxExtBuffer*)&extradata; ext_buffers[ext_buf_num++] = (mfxExtBuffer*)&co; @@ -1369,6 +1450,12 @@ static int qsv_retrieve_enc_params(AVCodecContext *avctx, QSVEncContext *q) q->exthevctiles_idx = ext_buf_num; ext_buffers[ext_buf_num++] = (mfxExtBuffer*)&hevc_tile_buf; } +#if QSV_HAVE_HE + if (q->dual_gfx && QSV_RUNTIME_VERSION_ATLEAST(q->ver, 2, 4)) { + q->exthypermodeparam_idx = ext_buf_num; + ext_buffers[ext_buf_num++] = (mfxExtBuffer*)&hyper_mode_param_buf; + } +#endif q->param.ExtParam = ext_buffers; q->param.NumExtParam = ext_buf_num; diff --git a/libavcodec/qsvenc.h b/libavcodec/qsvenc.h index a7bbb3797e3..4a6fa2caedc 100644 --- a/libavcodec/qsvenc.h +++ b/libavcodec/qsvenc.h @@ -45,10 +45,12 @@ #define QSV_HAVE_AVBR 1 #define QSV_HAVE_VCM 1 #define QSV_HAVE_MF 0 +#define QSV_HAVE_HE QSV_VERSION_ATLEAST(2, 4) #else #define QSV_HAVE_AVBR 0 #define QSV_HAVE_VCM 0 #define QSV_HAVE_MF !QSV_ONEVPL +#define QSV_HAVE_HE 0 #endif #define QSV_COMMON_OPTS \ @@ -64,6 +66,14 @@ { "forced_idr", "Forcing I frames as IDR frames", OFFSET(qsv.forced_idr), AV_OPT_TYPE_BOOL,{ .i64 = 0 }, 0, 1, VE }, \ { "low_power", "enable low power mode(experimental: many limitations by mfx version, BRC modes, etc.)", OFFSET(qsv.low_power), AV_OPT_TYPE_BOOL, { .i64 = -1}, -1, 1, VE}, +#if QSV_HAVE_HE +#define QSV_HE_OPTIONS \ +{ "dual_gfx", "Prefer processing on both iGfx and dGfx simultaneously", OFFSET(qsv.dual_gfx), AV_OPT_TYPE_INT, { .i64 = MFX_HYPERMODE_OFF }, MFX_HYPERMODE_OFF, MFX_HYPERMODE_ADAPTIVE, VE, "dual_gfx" }, \ +{ "off", "Disable HyperEncode mode", 0, AV_OPT_TYPE_CONST, { .i64 = MFX_HYPERMODE_OFF }, INT_MIN, INT_MAX, VE, "dual_gfx" }, \ +{ "on", "Enable HyperEncode mode and return error if incompatible parameters during initialization", 0, AV_OPT_TYPE_CONST, { .i64 = MFX_HYPERMODE_ON }, INT_MIN, INT_MAX, VE, "dual_gfx" }, \ +{ "adaptive", "Enable HyperEncode mode or fallback to single GPU if incompatible parameters during initialization", 0, AV_OPT_TYPE_CONST, { .i64 = MFX_HYPERMODE_ADAPTIVE }, INT_MIN, INT_MAX, VE, "dual_gfx" }, +#endif + #define QSV_OPTION_RDO \ { "rdo", "Enable rate distortion optimization", OFFSET(qsv.rdo), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, 1, VE }, @@ -171,7 +181,9 @@ typedef struct QSVEncContext { mfxExtAV1TileParam extav1tileparam; mfxExtAV1BitstreamParam extav1bsparam; #endif - +#if QSV_HAVE_HE + mfxExtHyperModeParam exthypermodeparam; +#endif #if QSV_HAVE_OPAQUE mfxExtOpaqueSurfaceAlloc opaque_alloc; mfxFrameSurface1 **opaque_surfaces; @@ -180,7 +192,7 @@ typedef struct QSVEncContext { mfxExtVideoSignalInfo extvsi; - mfxExtBuffer *extparam_internal[5 + (QSV_HAVE_MF * 2) + QSV_HAVE_EXT_AV1_PARAM * 2]; + mfxExtBuffer *extparam_internal[5 + (QSV_HAVE_MF * 2) + (QSV_HAVE_EXT_AV1_PARAM * 2) + QSV_HAVE_HE]; int nb_extparam_internal; mfxExtBuffer **extparam; @@ -255,6 +267,7 @@ typedef struct QSVEncContext { int co2_idx; int co3_idx; int exthevctiles_idx; + int exthypermodeparam_idx; int vp9_idx; int max_qp_i; @@ -299,6 +312,8 @@ typedef struct QSVEncContext { // This is used for SEI Timing reset int old_pic_timing_sei; int skip_frame; + // This is used for Hyper Encode + int dual_gfx; } QSVEncContext; int ff_qsv_enc_init(AVCodecContext *avctx, QSVEncContext *q); diff --git a/libavcodec/qsvenc_h264.c b/libavcodec/qsvenc_h264.c index bbdedc3335f..071a9a79e96 100644 --- a/libavcodec/qsvenc_h264.c +++ b/libavcodec/qsvenc_h264.c @@ -117,6 +117,9 @@ static const AVOption options[] = { QSV_OPTION_SCENARIO QSV_OPTION_AVBR QSV_OPTION_SKIP_FRAME +#if QSV_HAVE_HE + QSV_HE_OPTIONS +#endif { "cavlc", "Enable CAVLC", OFFSET(qsv.cavlc), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, VE }, #if QSV_HAVE_VCM diff --git a/libavcodec/qsvenc_hevc.c b/libavcodec/qsvenc_hevc.c index e042263bf51..5e23ca9647c 100644 --- a/libavcodec/qsvenc_hevc.c +++ b/libavcodec/qsvenc_hevc.c @@ -318,6 +318,9 @@ static const AVOption options[] = { QSV_OPTION_SCENARIO QSV_OPTION_AVBR QSV_OPTION_SKIP_FRAME +#if QSV_HAVE_HE + QSV_HE_OPTIONS +#endif { "idr_interval", "Distance (in I-frames) between IDR frames", OFFSET(qsv.idr_interval), AV_OPT_TYPE_INT, { .i64 = 0 }, -1, INT_MAX, VE, "idr_interval" }, { "begin_only", "Output an IDR-frame only at the beginning of the stream", 0, AV_OPT_TYPE_CONST, { .i64 = -1 }, 0, 0, VE, "idr_interval" }, From d66312cf278f0b2db4d4410dd6a99bb4d1f30919 Mon Sep 17 00:00:00 2001 From: Haihao Xiang Date: Tue, 17 Jan 2023 14:20:25 +0800 Subject: [PATCH 0123/2172] lavfi/scale_qsv: simplify scale_qsv filter Use QSVVPPContext as a base context of QSVScaleContext, hence we may re-use functions defined for QSVVPPContext to manage MFX session for scale_qsv filter. In addition, system memory has been taken into account in QSVVVPPContext, we may add support for non-QSV pixel formats in the future. Signed-off-by: Haihao Xiang --- configure | 1 + libavfilter/vf_scale_qsv.c | 441 +++---------------------------------- 2 files changed, 35 insertions(+), 407 deletions(-) diff --git a/configure b/configure index 8190e978a8a..47790d10f57 100755 --- a/configure +++ b/configure @@ -3722,6 +3722,7 @@ sab_filter_deps="gpl swscale" scale2ref_filter_deps="swscale" scale_filter_deps="swscale" scale_qsv_filter_deps="libmfx" +scale_qsv_filter_select="qsvvpp" scdet_filter_select="scene_sad" select_filter_select="scene_sad" sharpness_vaapi_filter_deps="vaapi" diff --git a/libavfilter/vf_scale_qsv.c b/libavfilter/vf_scale_qsv.c index a89a3ba6e6d..8eb8bc9ec1e 100644 --- a/libavfilter/vf_scale_qsv.c +++ b/libavfilter/vf_scale_qsv.c @@ -66,35 +66,11 @@ enum var_name { #define MFX_IMPL_VIA_MASK(impl) (0x0f00 & (impl)) typedef struct QSVScaleContext { - const AVClass *class; - - /* a clone of the main session, used internally for scaling */ - mfxSession session; - - mfxMemId *mem_ids_in; - int nb_mem_ids_in; - - mfxMemId *mem_ids_out; - int nb_mem_ids_out; - - mfxFrameSurface1 **surface_ptrs_in; - int nb_surface_ptrs_in; - - mfxFrameSurface1 **surface_ptrs_out; - int nb_surface_ptrs_out; - -#if QSV_HAVE_OPAQUE - mfxExtOpaqueSurfaceAlloc opaque_alloc; -#endif + QSVVPPContext qsv; mfxExtVPPScaling scale_conf; int mode; - mfxExtBuffer *ext_buffers[2]; - int num_ext_buf; - - int shift_width, shift_height; - /** * New dimensions. Special values are: * 0 = original width/height @@ -131,338 +107,21 @@ static av_cold int qsvscale_init(AVFilterContext *ctx) static av_cold void qsvscale_uninit(AVFilterContext *ctx) { - QSVScaleContext *s = ctx->priv; - - if (s->session) { - MFXClose(s->session); - s->session = NULL; - } - - av_freep(&s->mem_ids_in); - av_freep(&s->mem_ids_out); - s->nb_mem_ids_in = 0; - s->nb_mem_ids_out = 0; - - av_freep(&s->surface_ptrs_in); - av_freep(&s->surface_ptrs_out); - s->nb_surface_ptrs_in = 0; - s->nb_surface_ptrs_out = 0; -} - -static int init_out_pool(AVFilterContext *ctx, - int out_width, int out_height) -{ - QSVScaleContext *s = ctx->priv; - AVFilterLink *outlink = ctx->outputs[0]; - - AVHWFramesContext *in_frames_ctx; - AVHWFramesContext *out_frames_ctx; - AVQSVFramesContext *in_frames_hwctx; - AVQSVFramesContext *out_frames_hwctx; - enum AVPixelFormat in_format; - enum AVPixelFormat out_format; - int i, ret; - - /* check that we have a hw context */ - if (!ctx->inputs[0]->hw_frames_ctx) { - av_log(ctx, AV_LOG_ERROR, "No hw context provided on input\n"); - return AVERROR(EINVAL); - } - in_frames_ctx = (AVHWFramesContext*)ctx->inputs[0]->hw_frames_ctx->data; - in_frames_hwctx = in_frames_ctx->hwctx; - - in_format = in_frames_ctx->sw_format; - out_format = (s->format == AV_PIX_FMT_NONE) ? in_format : s->format; - - outlink->hw_frames_ctx = av_hwframe_ctx_alloc(in_frames_ctx->device_ref); - if (!outlink->hw_frames_ctx) - return AVERROR(ENOMEM); - out_frames_ctx = (AVHWFramesContext*)outlink->hw_frames_ctx->data; - out_frames_hwctx = out_frames_ctx->hwctx; - - out_frames_ctx->format = AV_PIX_FMT_QSV; - out_frames_ctx->width = FFALIGN(out_width, 16); - out_frames_ctx->height = FFALIGN(out_height, 16); - out_frames_ctx->sw_format = out_format; - out_frames_ctx->initial_pool_size = 4; - - out_frames_hwctx->frame_type = in_frames_hwctx->frame_type | MFX_MEMTYPE_FROM_VPPOUT; - - ret = ff_filter_init_hw_frames(ctx, outlink, 32); - if (ret < 0) - return ret; - - ret = av_hwframe_ctx_init(outlink->hw_frames_ctx); - if (ret < 0) - return ret; - - for (i = 0; i < out_frames_hwctx->nb_surfaces; i++) { - mfxFrameInfo *info = &out_frames_hwctx->surfaces[i].Info; - info->CropW = out_width; - info->CropH = out_height; - } - - return 0; -} - -static mfxStatus frame_alloc(mfxHDL pthis, mfxFrameAllocRequest *req, - mfxFrameAllocResponse *resp) -{ - AVFilterContext *ctx = pthis; - QSVScaleContext *s = ctx->priv; - - if (!(req->Type & MFX_MEMTYPE_VIDEO_MEMORY_PROCESSOR_TARGET) || - !(req->Type & (MFX_MEMTYPE_FROM_VPPIN | MFX_MEMTYPE_FROM_VPPOUT)) || - !(req->Type & MFX_MEMTYPE_EXTERNAL_FRAME)) - return MFX_ERR_UNSUPPORTED; - - if (req->Type & MFX_MEMTYPE_FROM_VPPIN) { - resp->mids = s->mem_ids_in; - resp->NumFrameActual = s->nb_mem_ids_in; - } else { - resp->mids = s->mem_ids_out; - resp->NumFrameActual = s->nb_mem_ids_out; - } - - return MFX_ERR_NONE; -} - -static mfxStatus frame_free(mfxHDL pthis, mfxFrameAllocResponse *resp) -{ - return MFX_ERR_NONE; -} - -static mfxStatus frame_lock(mfxHDL pthis, mfxMemId mid, mfxFrameData *ptr) -{ - return MFX_ERR_UNSUPPORTED; -} - -static mfxStatus frame_unlock(mfxHDL pthis, mfxMemId mid, mfxFrameData *ptr) -{ - return MFX_ERR_UNSUPPORTED; -} - -static mfxStatus frame_get_hdl(mfxHDL pthis, mfxMemId mid, mfxHDL *hdl) -{ - mfxHDLPair *pair_dst = (mfxHDLPair*)hdl; - mfxHDLPair *pair_src = (mfxHDLPair*)mid; - - pair_dst->first = pair_src->first; - - if (pair_src->second != (mfxMemId)MFX_INFINITE) - pair_dst->second = pair_src->second; - return MFX_ERR_NONE; -} - -static int init_out_session(AVFilterContext *ctx) -{ - - QSVScaleContext *s = ctx->priv; - AVHWFramesContext *in_frames_ctx = (AVHWFramesContext*)ctx->inputs[0]->hw_frames_ctx->data; - AVHWFramesContext *out_frames_ctx = (AVHWFramesContext*)ctx->outputs[0]->hw_frames_ctx->data; - AVQSVFramesContext *in_frames_hwctx = in_frames_ctx->hwctx; - AVQSVFramesContext *out_frames_hwctx = out_frames_ctx->hwctx; - AVQSVDeviceContext *device_hwctx = in_frames_ctx->device_ctx->hwctx; - - int opaque = 0; - - mfxHDL handle = NULL; - mfxHandleType handle_type; - mfxVersion ver; - mfxIMPL impl; - mfxVideoParam par; - mfxStatus err; - int i, ret; - -#if QSV_HAVE_OPAQUE - opaque = !!(in_frames_hwctx->frame_type & MFX_MEMTYPE_OPAQUE_FRAME); -#endif - s->num_ext_buf = 0; - - /* extract the properties of the "master" session given to us */ - err = MFXQueryIMPL(device_hwctx->session, &impl); - if (err == MFX_ERR_NONE) - err = MFXQueryVersion(device_hwctx->session, &ver); - if (err != MFX_ERR_NONE) { - av_log(ctx, AV_LOG_ERROR, "Error querying the session attributes\n"); - return AVERROR_UNKNOWN; - } - - if (MFX_IMPL_VIA_VAAPI == MFX_IMPL_VIA_MASK(impl)) { - handle_type = MFX_HANDLE_VA_DISPLAY; - } else if (MFX_IMPL_VIA_D3D11 == MFX_IMPL_VIA_MASK(impl)) { - handle_type = MFX_HANDLE_D3D11_DEVICE; - } else if (MFX_IMPL_VIA_D3D9 == MFX_IMPL_VIA_MASK(impl)) { - handle_type = MFX_HANDLE_D3D9_DEVICE_MANAGER; - } else { - av_log(ctx, AV_LOG_ERROR, "Error unsupported handle type\n"); - return AVERROR_UNKNOWN; - } - - err = MFXVideoCORE_GetHandle(device_hwctx->session, handle_type, &handle); - if (err < 0) - return ff_qsvvpp_print_error(ctx, err, "Error getting the session handle"); - else if (err > 0) { - ff_qsvvpp_print_warning(ctx, err, "Warning in getting the session handle"); - return AVERROR_UNKNOWN; - } - - /* create a "slave" session with those same properties, to be used for - * actual scaling */ - ret = ff_qsvvpp_create_mfx_session(ctx, device_hwctx->loader, impl, &ver, - &s->session); - if (ret) - return ret; - - if (handle) { - err = MFXVideoCORE_SetHandle(s->session, handle_type, handle); - if (err != MFX_ERR_NONE) - return AVERROR_UNKNOWN; - } - - if (QSV_RUNTIME_VERSION_ATLEAST(ver, 1, 25)) { - err = MFXJoinSession(device_hwctx->session, s->session); - if (err != MFX_ERR_NONE) - return AVERROR_UNKNOWN; - } - - memset(&par, 0, sizeof(par)); - - if (!opaque) { - mfxFrameAllocator frame_allocator = { - .pthis = ctx, - .Alloc = frame_alloc, - .Lock = frame_lock, - .Unlock = frame_unlock, - .GetHDL = frame_get_hdl, - .Free = frame_free, - }; - - s->mem_ids_in = av_calloc(in_frames_hwctx->nb_surfaces, - sizeof(*s->mem_ids_in)); - if (!s->mem_ids_in) - return AVERROR(ENOMEM); - for (i = 0; i < in_frames_hwctx->nb_surfaces; i++) - s->mem_ids_in[i] = in_frames_hwctx->surfaces[i].Data.MemId; - s->nb_mem_ids_in = in_frames_hwctx->nb_surfaces; - - s->mem_ids_out = av_calloc(out_frames_hwctx->nb_surfaces, - sizeof(*s->mem_ids_out)); - if (!s->mem_ids_out) - return AVERROR(ENOMEM); - for (i = 0; i < out_frames_hwctx->nb_surfaces; i++) - s->mem_ids_out[i] = out_frames_hwctx->surfaces[i].Data.MemId; - s->nb_mem_ids_out = out_frames_hwctx->nb_surfaces; - - err = MFXVideoCORE_SetFrameAllocator(s->session, &frame_allocator); - if (err != MFX_ERR_NONE) - return AVERROR_UNKNOWN; - - par.IOPattern = MFX_IOPATTERN_IN_VIDEO_MEMORY | MFX_IOPATTERN_OUT_VIDEO_MEMORY; - } -#if QSV_HAVE_OPAQUE - else { - s->surface_ptrs_in = av_calloc(in_frames_hwctx->nb_surfaces, - sizeof(*s->surface_ptrs_in)); - if (!s->surface_ptrs_in) - return AVERROR(ENOMEM); - for (i = 0; i < in_frames_hwctx->nb_surfaces; i++) - s->surface_ptrs_in[i] = in_frames_hwctx->surfaces + i; - s->nb_surface_ptrs_in = in_frames_hwctx->nb_surfaces; - - s->surface_ptrs_out = av_calloc(out_frames_hwctx->nb_surfaces, - sizeof(*s->surface_ptrs_out)); - if (!s->surface_ptrs_out) - return AVERROR(ENOMEM); - for (i = 0; i < out_frames_hwctx->nb_surfaces; i++) - s->surface_ptrs_out[i] = out_frames_hwctx->surfaces + i; - s->nb_surface_ptrs_out = out_frames_hwctx->nb_surfaces; - - s->opaque_alloc.In.Surfaces = s->surface_ptrs_in; - s->opaque_alloc.In.NumSurface = s->nb_surface_ptrs_in; - s->opaque_alloc.In.Type = in_frames_hwctx->frame_type; - - s->opaque_alloc.Out.Surfaces = s->surface_ptrs_out; - s->opaque_alloc.Out.NumSurface = s->nb_surface_ptrs_out; - s->opaque_alloc.Out.Type = out_frames_hwctx->frame_type; - - s->opaque_alloc.Header.BufferId = MFX_EXTBUFF_OPAQUE_SURFACE_ALLOCATION; - s->opaque_alloc.Header.BufferSz = sizeof(s->opaque_alloc); - - s->ext_buffers[s->num_ext_buf++] = (mfxExtBuffer*)&s->opaque_alloc; - - par.IOPattern = MFX_IOPATTERN_IN_OPAQUE_MEMORY | MFX_IOPATTERN_OUT_OPAQUE_MEMORY; - } -#endif - - memset(&s->scale_conf, 0, sizeof(mfxExtVPPScaling)); - s->scale_conf.Header.BufferId = MFX_EXTBUFF_VPP_SCALING; - s->scale_conf.Header.BufferSz = sizeof(mfxExtVPPScaling); - s->scale_conf.ScalingMode = s->mode; - s->ext_buffers[s->num_ext_buf++] = (mfxExtBuffer*)&s->scale_conf; - av_log(ctx, AV_LOG_VERBOSE, "Scaling mode: %d\n", s->mode); - - par.ExtParam = s->ext_buffers; - par.NumExtParam = s->num_ext_buf; - - par.AsyncDepth = 1; // TODO async - - par.vpp.In = in_frames_hwctx->surfaces[0].Info; - par.vpp.Out = out_frames_hwctx->surfaces[0].Info; - - /* Apparently VPP requires the frame rate to be set to some value, otherwise - * init will fail (probably for the framerate conversion filter). Since we - * are only doing scaling here, we just invent an arbitrary - * value */ - par.vpp.In.FrameRateExtN = 25; - par.vpp.In.FrameRateExtD = 1; - par.vpp.Out.FrameRateExtN = 25; - par.vpp.Out.FrameRateExtD = 1; - - /* Print input memory mode */ - ff_qsvvpp_print_iopattern(ctx, par.IOPattern & 0x0F, "VPP"); - /* Print output memory mode */ - ff_qsvvpp_print_iopattern(ctx, par.IOPattern & 0xF0, "VPP"); - err = MFXVideoVPP_Init(s->session, &par); - if (err < 0) - return ff_qsvvpp_print_error(ctx, err, - "Error opening the VPP for scaling"); - else if (err > 0) { - ff_qsvvpp_print_warning(ctx, err, - "Warning in VPP initialization"); - return AVERROR_UNKNOWN; - } - - return 0; -} - -static int init_scale_session(AVFilterContext *ctx, int in_width, int in_height, - int out_width, int out_height) -{ - int ret; - - qsvscale_uninit(ctx); - - ret = init_out_pool(ctx, out_width, out_height); - if (ret < 0) - return ret; - - ret = init_out_session(ctx); - if (ret < 0) - return ret; - - return 0; + ff_qsvvpp_close(ctx); } static int qsvscale_config_props(AVFilterLink *outlink) { AVFilterContext *ctx = outlink->src; AVFilterLink *inlink = outlink->src->inputs[0]; - QSVScaleContext *s = ctx->priv; + QSVScaleContext *s = ctx->priv; + QSVVPPParam param = { NULL }; + mfxExtBuffer *ext_buf[1]; int64_t w, h; double var_values[VARS_NB], res; char *expr; int ret; + enum AVPixelFormat in_format; var_values[VAR_IN_W] = var_values[VAR_IW] = inlink->w; var_values[VAR_IN_H] = var_values[VAR_IH] = inlink->h; @@ -518,7 +177,30 @@ static int qsvscale_config_props(AVFilterLink *outlink) outlink->w = w; outlink->h = h; - ret = init_scale_session(ctx, inlink->w, inlink->h, w, h); + if (inlink->format == AV_PIX_FMT_QSV) { + if (!inlink->hw_frames_ctx || !inlink->hw_frames_ctx->data) + return AVERROR(EINVAL); + else + in_format = ((AVHWFramesContext*)inlink->hw_frames_ctx->data)->sw_format; + } else + in_format = inlink->format; + + if (s->format == AV_PIX_FMT_NONE) + s->format = in_format; + + outlink->frame_rate = inlink->frame_rate; + outlink->time_base = av_inv_q(inlink->frame_rate); + param.out_sw_format = s->format; + + param.ext_buf = ext_buf; + memset(&s->scale_conf, 0, sizeof(mfxExtVPPScaling)); + s->scale_conf.Header.BufferId = MFX_EXTBUFF_VPP_SCALING; + s->scale_conf.Header.BufferSz = sizeof(mfxExtVPPScaling); + s->scale_conf.ScalingMode = s->mode; + param.ext_buf[param.num_ext_buf++] = (mfxExtBuffer*)&s->scale_conf; + av_log(ctx, AV_LOG_VERBOSE, "Scaling mode: %d\n", s->mode); + + ret = ff_qsvvpp_init(ctx, ¶m); if (ret < 0) return ret; @@ -542,67 +224,12 @@ static int qsvscale_config_props(AVFilterLink *outlink) static int qsvscale_filter_frame(AVFilterLink *link, AVFrame *in) { - AVFilterContext *ctx = link->dst; - QSVScaleContext *s = ctx->priv; - AVFilterLink *outlink = ctx->outputs[0]; - - mfxSyncPoint sync = NULL; - mfxStatus err; - - AVFrame *out = NULL; - int ret = 0; - - out = ff_get_video_buffer(outlink, outlink->w, outlink->h); - if (!out) { - ret = AVERROR(ENOMEM); - goto fail; - } + int ret = 0; + AVFilterContext *ctx = link->dst; + QSVVPPContext *qsv = ctx->priv; - do { - err = MFXVideoVPP_RunFrameVPPAsync(s->session, - (mfxFrameSurface1*)in->data[3], - (mfxFrameSurface1*)out->data[3], - NULL, &sync); - if (err == MFX_WRN_DEVICE_BUSY) - av_usleep(1); - } while (err == MFX_WRN_DEVICE_BUSY); - - if (err < 0) { - ret = ff_qsvvpp_print_error(ctx, err, "Error during scaling"); - goto fail; - } - - if (!sync) { - av_log(ctx, AV_LOG_ERROR, "No sync during scaling\n"); - ret = AVERROR_UNKNOWN; - goto fail; - } - - do { - err = MFXVideoCORE_SyncOperation(s->session, sync, 1000); - } while (err == MFX_WRN_IN_EXECUTION); - if (err < 0) { - ret = ff_qsvvpp_print_error(ctx, err, "Error synchronizing the operation"); - goto fail; - } - - ret = av_frame_copy_props(out, in); - if (ret < 0) - goto fail; - - out->width = outlink->w; - out->height = outlink->h; - - av_reduce(&out->sample_aspect_ratio.num, &out->sample_aspect_ratio.den, - (int64_t)in->sample_aspect_ratio.num * outlink->h * link->w, - (int64_t)in->sample_aspect_ratio.den * outlink->w * link->h, - INT_MAX); - - av_frame_free(&in); - return ff_filter_frame(outlink, out); -fail: + ret = ff_qsvvpp_filter_frame(qsv, link, in); av_frame_free(&in); - av_frame_free(&out); return ret; } From 9c09fb232b6863181ac1fe70647f9cbccb053d88 Mon Sep 17 00:00:00 2001 From: Haihao Xiang Date: Tue, 17 Jan 2023 14:20:26 +0800 Subject: [PATCH 0124/2172] lavfi/scale_qsv: re-use VPPContext for scale_qsv filter QSVScaleContext and VPPContext have the same base context, and all features in scale_qsv are implemented in vpp_qsv filter, so scale_qsv can be taken as a special case of vpp_qsv filter, and we may use VPPContext with a different option array, preinit callback and supported pixel formats to implement scale_qsv then remove QSVScaleContext Signed-off-by: Haihao Xiang --- libavfilter/Makefile | 2 +- libavfilter/vf_scale_qsv.c | 290 ------------------------------------- libavfilter/vf_vpp_qsv.c | 186 ++++++++++++++++-------- 3 files changed, 124 insertions(+), 354 deletions(-) delete mode 100644 libavfilter/vf_scale_qsv.c diff --git a/libavfilter/Makefile b/libavfilter/Makefile index a0059c69e6a..b45dcd00fc1 100644 --- a/libavfilter/Makefile +++ b/libavfilter/Makefile @@ -446,7 +446,7 @@ OBJS-$(CONFIG_SCALE_FILTER) += vf_scale.o scale_eval.o OBJS-$(CONFIG_SCALE_CUDA_FILTER) += vf_scale_cuda.o scale_eval.o \ vf_scale_cuda.ptx.o cuda/load_helper.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_QSV_FILTER) += vf_vpp_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 vulkan_filter.o OBJS-$(CONFIG_SCALE2REF_FILTER) += vf_scale.o scale_eval.o diff --git a/libavfilter/vf_scale_qsv.c b/libavfilter/vf_scale_qsv.c deleted file mode 100644 index 8eb8bc9ec1e..00000000000 --- a/libavfilter/vf_scale_qsv.c +++ /dev/null @@ -1,290 +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 - */ - -/** - * @file - * scale video filter - QSV - */ - -#include - -#include -#include - -#include "libavutil/avstring.h" -#include "libavutil/common.h" -#include "libavutil/eval.h" -#include "libavutil/hwcontext.h" -#include "libavutil/hwcontext_qsv.h" -#include "libavutil/internal.h" -#include "libavutil/mathematics.h" -#include "libavutil/opt.h" -#include "libavutil/pixdesc.h" -#include "libavutil/time.h" -#include "libavfilter/qsvvpp.h" - -#include "avfilter.h" -#include "formats.h" -#include "internal.h" -#include "video.h" - -static const char *const var_names[] = { - "in_w", "iw", - "in_h", "ih", - "out_w", "ow", - "out_h", "oh", - "a", "dar", - "sar", - 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_DAR, - VAR_SAR, - VARS_NB -}; - -#define MFX_IMPL_VIA_MASK(impl) (0x0f00 & (impl)) - -typedef struct QSVScaleContext { - QSVVPPContext qsv; - - mfxExtVPPScaling scale_conf; - int mode; - - /** - * New dimensions. Special values are: - * 0 = original width/height - * -1 = keep original aspect - */ - int w, h; - - /** - * Output sw format. AV_PIX_FMT_NONE for no conversion. - */ - enum AVPixelFormat format; - - char *w_expr; ///< width expression string - char *h_expr; ///< height expression string - char *format_str; -} QSVScaleContext; - -static av_cold int qsvscale_init(AVFilterContext *ctx) -{ - QSVScaleContext *s = ctx->priv; - - if (!strcmp(s->format_str, "same")) { - s->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); - return AVERROR(EINVAL); - } - } - - return 0; -} - -static av_cold void qsvscale_uninit(AVFilterContext *ctx) -{ - ff_qsvvpp_close(ctx); -} - -static int qsvscale_config_props(AVFilterLink *outlink) -{ - AVFilterContext *ctx = outlink->src; - AVFilterLink *inlink = outlink->src->inputs[0]; - QSVScaleContext *s = ctx->priv; - QSVVPPParam param = { NULL }; - mfxExtBuffer *ext_buf[1]; - int64_t w, h; - double var_values[VARS_NB], res; - char *expr; - int ret; - enum AVPixelFormat in_format; - - var_values[VAR_IN_W] = var_values[VAR_IW] = inlink->w; - var_values[VAR_IN_H] = var_values[VAR_IH] = inlink->h; - var_values[VAR_OUT_W] = var_values[VAR_OW] = NAN; - var_values[VAR_OUT_H] = var_values[VAR_OH] = NAN; - var_values[VAR_A] = (double) inlink->w / inlink->h; - var_values[VAR_SAR] = inlink->sample_aspect_ratio.num ? - (double) inlink->sample_aspect_ratio.num / inlink->sample_aspect_ratio.den : 1; - var_values[VAR_DAR] = var_values[VAR_A] * var_values[VAR_SAR]; - - /* evaluate width and height */ - av_expr_parse_and_eval(&res, (expr = s->w_expr), - var_names, var_values, - NULL, NULL, NULL, NULL, NULL, 0, ctx); - s->w = var_values[VAR_OUT_W] = var_values[VAR_OW] = res; - if ((ret = av_expr_parse_and_eval(&res, (expr = s->h_expr), - var_names, var_values, - NULL, NULL, NULL, NULL, NULL, 0, ctx)) < 0) - goto fail; - s->h = var_values[VAR_OUT_H] = var_values[VAR_OH] = res; - /* evaluate again the width, as it may depend on the output height */ - if ((ret = av_expr_parse_and_eval(&res, (expr = s->w_expr), - var_names, var_values, - NULL, NULL, NULL, NULL, NULL, 0, ctx)) < 0) - goto fail; - s->w = res; - - w = s->w; - h = s->h; - - /* sanity check params */ - if (w < -1 || h < -1) { - av_log(ctx, AV_LOG_ERROR, "Size values less than -1 are not acceptable.\n"); - return AVERROR(EINVAL); - } - if (w == -1 && h == -1) - s->w = s->h = 0; - - if (!(w = s->w)) - w = inlink->w; - if (!(h = s->h)) - h = inlink->h; - if (w == -1) - w = av_rescale(h, inlink->w, inlink->h); - if (h == -1) - h = av_rescale(w, inlink->h, inlink->w); - - if (w > INT_MAX || h > INT_MAX || - (h * inlink->w) > INT_MAX || - (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; - - if (inlink->format == AV_PIX_FMT_QSV) { - if (!inlink->hw_frames_ctx || !inlink->hw_frames_ctx->data) - return AVERROR(EINVAL); - else - in_format = ((AVHWFramesContext*)inlink->hw_frames_ctx->data)->sw_format; - } else - in_format = inlink->format; - - if (s->format == AV_PIX_FMT_NONE) - s->format = in_format; - - outlink->frame_rate = inlink->frame_rate; - outlink->time_base = av_inv_q(inlink->frame_rate); - param.out_sw_format = s->format; - - param.ext_buf = ext_buf; - memset(&s->scale_conf, 0, sizeof(mfxExtVPPScaling)); - s->scale_conf.Header.BufferId = MFX_EXTBUFF_VPP_SCALING; - s->scale_conf.Header.BufferSz = sizeof(mfxExtVPPScaling); - s->scale_conf.ScalingMode = s->mode; - param.ext_buf[param.num_ext_buf++] = (mfxExtBuffer*)&s->scale_conf; - av_log(ctx, AV_LOG_VERBOSE, "Scaling mode: %d\n", s->mode); - - ret = ff_qsvvpp_init(ctx, ¶m); - if (ret < 0) - return ret; - - av_log(ctx, AV_LOG_VERBOSE, "w:%d h:%d -> w:%d h:%d\n", - inlink->w, inlink->h, outlink->w, outlink->h); - - if (inlink->sample_aspect_ratio.num) - outlink->sample_aspect_ratio = av_mul_q((AVRational){outlink->h*inlink->w, - outlink->w*inlink->h}, - inlink->sample_aspect_ratio); - else - outlink->sample_aspect_ratio = inlink->sample_aspect_ratio; - - return 0; - -fail: - av_log(ctx, AV_LOG_ERROR, - "Error when evaluating the expression '%s'\n", expr); - return ret; -} - -static int qsvscale_filter_frame(AVFilterLink *link, AVFrame *in) -{ - int ret = 0; - AVFilterContext *ctx = link->dst; - QSVVPPContext *qsv = ctx->priv; - - ret = ff_qsvvpp_filter_frame(qsv, link, in); - av_frame_free(&in); - return ret; -} - -#define OFFSET(x) offsetof(QSVScaleContext, x) -#define FLAGS AV_OPT_FLAG_VIDEO_PARAM|AV_OPT_FLAG_FILTERING_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 }, - { "format", "Output pixel format", OFFSET(format_str), AV_OPT_TYPE_STRING, { .str = "same" }, .flags = FLAGS }, - - { "mode", "set scaling mode", OFFSET(mode), AV_OPT_TYPE_INT, { .i64 = MFX_SCALING_MODE_DEFAULT}, MFX_SCALING_MODE_DEFAULT, MFX_SCALING_MODE_QUALITY, FLAGS, "mode"}, - { "low_power", "low power mode", 0, AV_OPT_TYPE_CONST, { .i64 = MFX_SCALING_MODE_LOWPOWER}, INT_MIN, INT_MAX, FLAGS, "mode"}, - { "hq", "high quality mode", 0, AV_OPT_TYPE_CONST, { .i64 = MFX_SCALING_MODE_QUALITY}, INT_MIN, INT_MAX, FLAGS, "mode"}, - - { NULL }, -}; - -static const AVClass qsvscale_class = { - .class_name = "scale_qsv", - .item_name = av_default_item_name, - .option = options, - .version = LIBAVUTIL_VERSION_INT, -}; - -static const AVFilterPad qsvscale_inputs[] = { - { - .name = "default", - .type = AVMEDIA_TYPE_VIDEO, - .filter_frame = qsvscale_filter_frame, - .get_buffer.video = ff_qsvvpp_get_video_buffer, - }, -}; - -static const AVFilterPad qsvscale_outputs[] = { - { - .name = "default", - .type = AVMEDIA_TYPE_VIDEO, - .config_props = qsvscale_config_props, - }, -}; - -const AVFilter ff_vf_scale_qsv = { - .name = "scale_qsv", - .description = NULL_IF_CONFIG_SMALL("QuickSync video scaling and format conversion"), - - .init = qsvscale_init, - .uninit = qsvscale_uninit, - - .priv_size = sizeof(QSVScaleContext), - .priv_class = &qsvscale_class, - - FILTER_INPUTS(qsvscale_inputs), - FILTER_OUTPUTS(qsvscale_outputs), - - FILTER_SINGLE_PIXFMT(AV_PIX_FMT_QSV), - - .flags_internal = FF_FILTER_FLAG_HWFRAME_AWARE, -}; diff --git a/libavfilter/vf_vpp_qsv.c b/libavfilter/vf_vpp_qsv.c index 4a1af7146ae..34732bb2c93 100644 --- a/libavfilter/vf_vpp_qsv.c +++ b/libavfilter/vf_vpp_qsv.c @@ -23,6 +23,8 @@ #include +#include "config_components.h" + #include "libavutil/opt.h" #include "libavutil/eval.h" #include "libavutil/hwcontext.h" @@ -101,48 +103,6 @@ typedef struct VPPContext{ int has_passthrough; /* apply pass through mode if possible */ } VPPContext; -static const AVOption options[] = { - { "deinterlace", "deinterlace mode: 0=off, 1=bob, 2=advanced", OFFSET(deinterlace), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, MFX_DEINTERLACING_ADVANCED, .flags = FLAGS, "deinterlace" }, - { "bob", "Bob deinterlace mode.", 0, AV_OPT_TYPE_CONST, { .i64 = MFX_DEINTERLACING_BOB }, .flags = FLAGS, "deinterlace" }, - { "advanced", "Advanced deinterlace mode. ", 0, AV_OPT_TYPE_CONST, { .i64 = MFX_DEINTERLACING_ADVANCED }, .flags = FLAGS, "deinterlace" }, - - { "denoise", "denoise level [0, 100]", OFFSET(denoise), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 100, .flags = FLAGS }, - { "detail", "enhancement level [0, 100]", OFFSET(detail), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 100, .flags = FLAGS }, - { "framerate", "output framerate", OFFSET(framerate), AV_OPT_TYPE_RATIONAL, { .dbl = 0.0 },0, DBL_MAX, .flags = FLAGS }, - { "procamp", "Enable ProcAmp", OFFSET(procamp), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 1, .flags = FLAGS}, - { "hue", "ProcAmp hue", OFFSET(hue), AV_OPT_TYPE_FLOAT, { .dbl = 0.0 }, -180.0, 180.0, .flags = FLAGS}, - { "saturation", "ProcAmp saturation", OFFSET(saturation), AV_OPT_TYPE_FLOAT, { .dbl = 1.0 }, 0.0, 10.0, .flags = FLAGS}, - { "contrast", "ProcAmp contrast", OFFSET(contrast), AV_OPT_TYPE_FLOAT, { .dbl = 1.0 }, 0.0, 10.0, .flags = FLAGS}, - { "brightness", "ProcAmp brightness", OFFSET(brightness), AV_OPT_TYPE_FLOAT, { .dbl = 0.0 }, -100.0, 100.0, .flags = FLAGS}, - - { "transpose", "set transpose direction", OFFSET(transpose), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, 6, FLAGS, "transpose"}, - { "cclock_hflip", "rotate counter-clockwise with horizontal flip", 0, AV_OPT_TYPE_CONST, { .i64 = TRANSPOSE_CCLOCK_FLIP }, .flags=FLAGS, .unit = "transpose" }, - { "clock", "rotate clockwise", 0, AV_OPT_TYPE_CONST, { .i64 = TRANSPOSE_CLOCK }, .flags=FLAGS, .unit = "transpose" }, - { "cclock", "rotate counter-clockwise", 0, AV_OPT_TYPE_CONST, { .i64 = TRANSPOSE_CCLOCK }, .flags=FLAGS, .unit = "transpose" }, - { "clock_hflip", "rotate clockwise with horizontal flip", 0, AV_OPT_TYPE_CONST, { .i64 = TRANSPOSE_CLOCK_FLIP }, .flags=FLAGS, .unit = "transpose" }, - { "reversal", "rotate by half-turn", 0, AV_OPT_TYPE_CONST, { .i64 = TRANSPOSE_REVERSAL }, .flags=FLAGS, .unit = "transpose" }, - { "hflip", "flip horizontally", 0, AV_OPT_TYPE_CONST, { .i64 = TRANSPOSE_HFLIP }, .flags=FLAGS, .unit = "transpose" }, - { "vflip", "flip vertically", 0, AV_OPT_TYPE_CONST, { .i64 = TRANSPOSE_VFLIP }, .flags=FLAGS, .unit = "transpose" }, - - { "cw", "set the width crop area expression", OFFSET(cw), AV_OPT_TYPE_STRING, { .str = "iw" }, 0, 0, FLAGS }, - { "ch", "set the height crop area expression", OFFSET(ch), AV_OPT_TYPE_STRING, { .str = "ih" }, 0, 0, FLAGS }, - { "cx", "set the x crop area expression", OFFSET(cx), AV_OPT_TYPE_STRING, { .str = "(in_w-out_w)/2" }, 0, 0, FLAGS }, - { "cy", "set the y crop area expression", OFFSET(cy), AV_OPT_TYPE_STRING, { .str = "(in_h-out_h)/2" }, 0, 0, FLAGS }, - - { "w", "Output video width(0=input video width, -1=keep input video aspect)", OFFSET(ow), AV_OPT_TYPE_STRING, { .str="cw" }, 0, 255, .flags = FLAGS }, - { "width", "Output video width(0=input video width, -1=keep input video aspect)", OFFSET(ow), AV_OPT_TYPE_STRING, { .str="cw" }, 0, 255, .flags = FLAGS }, - { "h", "Output video height(0=input video height, -1=keep input video aspect)", OFFSET(oh), AV_OPT_TYPE_STRING, { .str="w*ch/cw" }, 0, 255, .flags = FLAGS }, - { "height", "Output video height(0=input video height, -1=keep input video aspect)", 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(qsv.async_depth), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, INT_MAX, .flags = FLAGS }, - { "scale_mode", "scale & format conversion 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" }, - { "auto", "auto mode", 0, AV_OPT_TYPE_CONST, { .i64 = MFX_SCALING_MODE_DEFAULT}, INT_MIN, INT_MAX, FLAGS, "scale mode"}, - { "low_power", "low power mode", 0, AV_OPT_TYPE_CONST, { .i64 = MFX_SCALING_MODE_LOWPOWER}, INT_MIN, INT_MAX, FLAGS, "scale mode"}, - { "hq", "high quality mode", 0, AV_OPT_TYPE_CONST, { .i64 = MFX_SCALING_MODE_QUALITY}, INT_MIN, INT_MAX, FLAGS, "scale mode"}, - - { NULL } -}; - static const char *const var_names[] = { "iw", "in_w", "ih", "in_h", @@ -633,6 +593,30 @@ static int activate(AVFilterContext *ctx) return 0; } +static av_cold void vpp_uninit(AVFilterContext *ctx) +{ + ff_qsvvpp_close(ctx); +} + +static const AVFilterPad vpp_inputs[] = { + { + .name = "default", + .type = AVMEDIA_TYPE_VIDEO, + .config_props = config_input, + .get_buffer.video = ff_qsvvpp_get_video_buffer, + }, +}; + +static const AVFilterPad vpp_outputs[] = { + { + .name = "default", + .type = AVMEDIA_TYPE_VIDEO, + .config_props = config_output, + }, +}; + +#if CONFIG_VPP_QSV_FILTER + static int query_formats(AVFilterContext *ctx) { int ret; @@ -660,10 +644,47 @@ static int query_formats(AVFilterContext *ctx) &ctx->outputs[0]->incfg.formats); } -static av_cold void vpp_uninit(AVFilterContext *ctx) -{ - ff_qsvvpp_close(ctx); -} +static const AVOption options[] = { + { "deinterlace", "deinterlace mode: 0=off, 1=bob, 2=advanced", OFFSET(deinterlace), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, MFX_DEINTERLACING_ADVANCED, .flags = FLAGS, "deinterlace" }, + { "bob", "Bob deinterlace mode.", 0, AV_OPT_TYPE_CONST, { .i64 = MFX_DEINTERLACING_BOB }, .flags = FLAGS, "deinterlace" }, + { "advanced", "Advanced deinterlace mode. ", 0, AV_OPT_TYPE_CONST, { .i64 = MFX_DEINTERLACING_ADVANCED }, .flags = FLAGS, "deinterlace" }, + + { "denoise", "denoise level [0, 100]", OFFSET(denoise), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 100, .flags = FLAGS }, + { "detail", "enhancement level [0, 100]", OFFSET(detail), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 100, .flags = FLAGS }, + { "framerate", "output framerate", OFFSET(framerate), AV_OPT_TYPE_RATIONAL, { .dbl = 0.0 },0, DBL_MAX, .flags = FLAGS }, + { "procamp", "Enable ProcAmp", OFFSET(procamp), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 1, .flags = FLAGS}, + { "hue", "ProcAmp hue", OFFSET(hue), AV_OPT_TYPE_FLOAT, { .dbl = 0.0 }, -180.0, 180.0, .flags = FLAGS}, + { "saturation", "ProcAmp saturation", OFFSET(saturation), AV_OPT_TYPE_FLOAT, { .dbl = 1.0 }, 0.0, 10.0, .flags = FLAGS}, + { "contrast", "ProcAmp contrast", OFFSET(contrast), AV_OPT_TYPE_FLOAT, { .dbl = 1.0 }, 0.0, 10.0, .flags = FLAGS}, + { "brightness", "ProcAmp brightness", OFFSET(brightness), AV_OPT_TYPE_FLOAT, { .dbl = 0.0 }, -100.0, 100.0, .flags = FLAGS}, + + { "transpose", "set transpose direction", OFFSET(transpose), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, 6, FLAGS, "transpose"}, + { "cclock_hflip", "rotate counter-clockwise with horizontal flip", 0, AV_OPT_TYPE_CONST, { .i64 = TRANSPOSE_CCLOCK_FLIP }, .flags=FLAGS, .unit = "transpose" }, + { "clock", "rotate clockwise", 0, AV_OPT_TYPE_CONST, { .i64 = TRANSPOSE_CLOCK }, .flags=FLAGS, .unit = "transpose" }, + { "cclock", "rotate counter-clockwise", 0, AV_OPT_TYPE_CONST, { .i64 = TRANSPOSE_CCLOCK }, .flags=FLAGS, .unit = "transpose" }, + { "clock_hflip", "rotate clockwise with horizontal flip", 0, AV_OPT_TYPE_CONST, { .i64 = TRANSPOSE_CLOCK_FLIP }, .flags=FLAGS, .unit = "transpose" }, + { "reversal", "rotate by half-turn", 0, AV_OPT_TYPE_CONST, { .i64 = TRANSPOSE_REVERSAL }, .flags=FLAGS, .unit = "transpose" }, + { "hflip", "flip horizontally", 0, AV_OPT_TYPE_CONST, { .i64 = TRANSPOSE_HFLIP }, .flags=FLAGS, .unit = "transpose" }, + { "vflip", "flip vertically", 0, AV_OPT_TYPE_CONST, { .i64 = TRANSPOSE_VFLIP }, .flags=FLAGS, .unit = "transpose" }, + + { "cw", "set the width crop area expression", OFFSET(cw), AV_OPT_TYPE_STRING, { .str = "iw" }, 0, 0, FLAGS }, + { "ch", "set the height crop area expression", OFFSET(ch), AV_OPT_TYPE_STRING, { .str = "ih" }, 0, 0, FLAGS }, + { "cx", "set the x crop area expression", OFFSET(cx), AV_OPT_TYPE_STRING, { .str = "(in_w-out_w)/2" }, 0, 0, FLAGS }, + { "cy", "set the y crop area expression", OFFSET(cy), AV_OPT_TYPE_STRING, { .str = "(in_h-out_h)/2" }, 0, 0, FLAGS }, + + { "w", "Output video width(0=input video width, -1=keep input video aspect)", OFFSET(ow), AV_OPT_TYPE_STRING, { .str="cw" }, 0, 255, .flags = FLAGS }, + { "width", "Output video width(0=input video width, -1=keep input video aspect)", OFFSET(ow), AV_OPT_TYPE_STRING, { .str="cw" }, 0, 255, .flags = FLAGS }, + { "h", "Output video height(0=input video height, -1=keep input video aspect)", OFFSET(oh), AV_OPT_TYPE_STRING, { .str="w*ch/cw" }, 0, 255, .flags = FLAGS }, + { "height", "Output video height(0=input video height, -1=keep input video aspect)", 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(qsv.async_depth), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, INT_MAX, .flags = FLAGS }, + { "scale_mode", "scale & format conversion 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" }, + { "auto", "auto mode", 0, AV_OPT_TYPE_CONST, { .i64 = MFX_SCALING_MODE_DEFAULT}, INT_MIN, INT_MAX, FLAGS, "scale mode"}, + { "low_power", "low power mode", 0, AV_OPT_TYPE_CONST, { .i64 = MFX_SCALING_MODE_LOWPOWER}, INT_MIN, INT_MAX, FLAGS, "scale mode"}, + { "hq", "high quality mode", 0, AV_OPT_TYPE_CONST, { .i64 = MFX_SCALING_MODE_QUALITY}, INT_MIN, INT_MAX, FLAGS, "scale mode"}, + + { NULL } +}; static const AVClass vpp_class = { .class_name = "vpp_qsv", @@ -672,23 +693,6 @@ static const AVClass vpp_class = { .version = LIBAVUTIL_VERSION_INT, }; -static const AVFilterPad vpp_inputs[] = { - { - .name = "default", - .type = AVMEDIA_TYPE_VIDEO, - .config_props = config_input, - .get_buffer.video = ff_qsvvpp_get_video_buffer, - }, -}; - -static const AVFilterPad vpp_outputs[] = { - { - .name = "default", - .type = AVMEDIA_TYPE_VIDEO, - .config_props = config_output, - }, -}; - const AVFilter ff_vf_vpp_qsv = { .name = "vpp_qsv", .description = NULL_IF_CONFIG_SMALL("Quick Sync Video VPP."), @@ -703,3 +707,59 @@ const AVFilter ff_vf_vpp_qsv = { .priv_class = &vpp_class, .flags_internal = FF_FILTER_FLAG_HWFRAME_AWARE, }; + +#endif + +#if CONFIG_SCALE_QSV_FILTER + +static const AVOption qsvscale_options[] = { + { "w", "Output video width(0=input video width, -1=keep input video aspect)", OFFSET(ow), AV_OPT_TYPE_STRING, { .str = "iw" }, .flags = FLAGS }, + { "h", "Output video height(0=input video height, -1=keep input video aspect)", OFFSET(oh), AV_OPT_TYPE_STRING, { .str = "ih" }, .flags = FLAGS }, + { "format", "Output pixel format", OFFSET(output_format_str), AV_OPT_TYPE_STRING, { .str = "same" }, .flags = FLAGS }, + + { "mode", "set scaling mode", OFFSET(scale_mode), AV_OPT_TYPE_INT, { .i64 = MFX_SCALING_MODE_DEFAULT}, MFX_SCALING_MODE_DEFAULT, MFX_SCALING_MODE_QUALITY, FLAGS, "mode"}, + { "low_power", "low power mode", 0, AV_OPT_TYPE_CONST, { .i64 = MFX_SCALING_MODE_LOWPOWER}, INT_MIN, INT_MAX, FLAGS, "mode"}, + { "hq", "high quality mode", 0, AV_OPT_TYPE_CONST, { .i64 = MFX_SCALING_MODE_QUALITY}, INT_MIN, INT_MAX, FLAGS, "mode"}, + + { NULL }, +}; + +static av_cold int qsvscale_preinit(AVFilterContext *ctx) +{ + VPPContext *vpp = ctx->priv; + + vpp_preinit(ctx); + vpp->has_passthrough = 0; + + return 0; +} + +static const AVClass qsvscale_class = { + .class_name = "scale_qsv", + .item_name = av_default_item_name, + .option = qsvscale_options, + .version = LIBAVUTIL_VERSION_INT, +}; + +const AVFilter ff_vf_scale_qsv = { + .name = "scale_qsv", + .description = NULL_IF_CONFIG_SMALL("Quick Sync Video scaling and format conversion"), + + .preinit = qsvscale_preinit, + .init = vpp_init, + .uninit = vpp_uninit, + + .priv_size = sizeof(VPPContext), + .priv_class = &qsvscale_class, + + FILTER_INPUTS(vpp_inputs), + FILTER_OUTPUTS(vpp_outputs), + + FILTER_SINGLE_PIXFMT(AV_PIX_FMT_QSV), + + .activate = activate, + + .flags_internal = FF_FILTER_FLAG_HWFRAME_AWARE, +}; + +#endif From 2d202985b79630cd5056c4e32f8f77f22bf1067c Mon Sep 17 00:00:00 2001 From: Haihao Xiang Date: Tue, 17 Jan 2023 14:20:27 +0800 Subject: [PATCH 0125/2172] lavfi/vpp_qsv: factor out the code for filter definition Signed-off-by: Haihao Xiang --- libavfilter/vf_vpp_qsv.c | 126 ++++++++++++++++----------------------- 1 file changed, 51 insertions(+), 75 deletions(-) diff --git a/libavfilter/vf_vpp_qsv.c b/libavfilter/vf_vpp_qsv.c index 34732bb2c93..34e530e244e 100644 --- a/libavfilter/vf_vpp_qsv.c +++ b/libavfilter/vf_vpp_qsv.c @@ -615,36 +615,31 @@ static const AVFilterPad vpp_outputs[] = { }, }; -#if CONFIG_VPP_QSV_FILTER - -static int query_formats(AVFilterContext *ctx) -{ - int ret; - static const enum AVPixelFormat in_pix_fmts[] = { - AV_PIX_FMT_YUV420P, - AV_PIX_FMT_NV12, - AV_PIX_FMT_YUYV422, - AV_PIX_FMT_RGB32, - AV_PIX_FMT_P010, - AV_PIX_FMT_QSV, - AV_PIX_FMT_NONE - }; - static const enum AVPixelFormat out_pix_fmts[] = { - AV_PIX_FMT_NV12, - AV_PIX_FMT_P010, - AV_PIX_FMT_QSV, - AV_PIX_FMT_NONE - }; +#define DEFINE_QSV_FILTER(x, sn, ln, fmts) \ +static const AVClass x##_class = { \ + .class_name = #sn "_qsv", \ + .item_name = av_default_item_name, \ + .option = x##_options, \ + .version = LIBAVUTIL_VERSION_INT, \ +}; \ +const AVFilter ff_vf_##sn##_qsv = { \ + .name = #sn "_qsv", \ + .description = NULL_IF_CONFIG_SMALL("Quick Sync Video " #ln), \ + .preinit = x##_preinit, \ + .init = vpp_init, \ + .uninit = vpp_uninit, \ + .priv_size = sizeof(VPPContext), \ + .priv_class = &x##_class, \ + FILTER_INPUTS(vpp_inputs), \ + FILTER_OUTPUTS(vpp_outputs), \ + fmts, \ + .activate = activate, \ + .flags_internal = FF_FILTER_FLAG_HWFRAME_AWARE, \ +}; - ret = ff_formats_ref(ff_make_format_list(in_pix_fmts), - &ctx->inputs[0]->outcfg.formats); - if (ret < 0) - return ret; - return ff_formats_ref(ff_make_format_list(out_pix_fmts), - &ctx->outputs[0]->incfg.formats); -} +#if CONFIG_VPP_QSV_FILTER -static const AVOption options[] = { +static const AVOption vpp_options[] = { { "deinterlace", "deinterlace mode: 0=off, 1=bob, 2=advanced", OFFSET(deinterlace), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, MFX_DEINTERLACING_ADVANCED, .flags = FLAGS, "deinterlace" }, { "bob", "Bob deinterlace mode.", 0, AV_OPT_TYPE_CONST, { .i64 = MFX_DEINTERLACING_BOB }, .flags = FLAGS, "deinterlace" }, { "advanced", "Advanced deinterlace mode. ", 0, AV_OPT_TYPE_CONST, { .i64 = MFX_DEINTERLACING_ADVANCED }, .flags = FLAGS, "deinterlace" }, @@ -686,27 +681,34 @@ static const AVOption options[] = { { NULL } }; -static const AVClass vpp_class = { - .class_name = "vpp_qsv", - .item_name = av_default_item_name, - .option = options, - .version = LIBAVUTIL_VERSION_INT, -}; +static int vpp_query_formats(AVFilterContext *ctx) +{ + int ret; + static const enum AVPixelFormat in_pix_fmts[] = { + AV_PIX_FMT_YUV420P, + AV_PIX_FMT_NV12, + AV_PIX_FMT_YUYV422, + AV_PIX_FMT_RGB32, + AV_PIX_FMT_P010, + AV_PIX_FMT_QSV, + AV_PIX_FMT_NONE + }; + static const enum AVPixelFormat out_pix_fmts[] = { + AV_PIX_FMT_NV12, + AV_PIX_FMT_P010, + AV_PIX_FMT_QSV, + AV_PIX_FMT_NONE + }; -const AVFilter ff_vf_vpp_qsv = { - .name = "vpp_qsv", - .description = NULL_IF_CONFIG_SMALL("Quick Sync Video VPP."), - .priv_size = sizeof(VPPContext), - .preinit = vpp_preinit, - .init = vpp_init, - .uninit = vpp_uninit, - FILTER_INPUTS(vpp_inputs), - FILTER_OUTPUTS(vpp_outputs), - FILTER_QUERY_FUNC(query_formats), - .activate = activate, - .priv_class = &vpp_class, - .flags_internal = FF_FILTER_FLAG_HWFRAME_AWARE, -}; + ret = ff_formats_ref(ff_make_format_list(in_pix_fmts), + &ctx->inputs[0]->outcfg.formats); + if (ret < 0) + return ret; + return ff_formats_ref(ff_make_format_list(out_pix_fmts), + &ctx->outputs[0]->incfg.formats); +} + +DEFINE_QSV_FILTER(vpp, vpp, "VPP", FILTER_QUERY_FUNC(vpp_query_formats)); #endif @@ -734,32 +736,6 @@ static av_cold int qsvscale_preinit(AVFilterContext *ctx) return 0; } -static const AVClass qsvscale_class = { - .class_name = "scale_qsv", - .item_name = av_default_item_name, - .option = qsvscale_options, - .version = LIBAVUTIL_VERSION_INT, -}; - -const AVFilter ff_vf_scale_qsv = { - .name = "scale_qsv", - .description = NULL_IF_CONFIG_SMALL("Quick Sync Video scaling and format conversion"), - - .preinit = qsvscale_preinit, - .init = vpp_init, - .uninit = vpp_uninit, - - .priv_size = sizeof(VPPContext), - .priv_class = &qsvscale_class, - - FILTER_INPUTS(vpp_inputs), - FILTER_OUTPUTS(vpp_outputs), - - FILTER_SINGLE_PIXFMT(AV_PIX_FMT_QSV), - - .activate = activate, - - .flags_internal = FF_FILTER_FLAG_HWFRAME_AWARE, -}; +DEFINE_QSV_FILTER(qsvscale, scale, "scaling and format conversion", FILTER_SINGLE_PIXFMT(AV_PIX_FMT_QSV)); #endif From 5508e04c7b710616e33407ac2b3f8d616cb745f0 Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Mon, 30 Jan 2023 17:01:26 +0100 Subject: [PATCH 0126/2172] avfilter/vf_colorlevels: add support for gbrpf32 format --- libavfilter/vf_colorlevels.c | 118 ++++++++++++++++++++++++++--------- 1 file changed, 90 insertions(+), 28 deletions(-) diff --git a/libavfilter/vf_colorlevels.c b/libavfilter/vf_colorlevels.c index 76adfbd8c8d..44ae6cffbf2 100644 --- a/libavfilter/vf_colorlevels.c +++ b/libavfilter/vf_colorlevels.c @@ -97,11 +97,13 @@ typedef struct ThreadData { int h; + float fimin[4]; + float fomin[4]; int imin[4]; int omin[4]; } ThreadData; -#define DO_COMMON(type, clip, preserve, planar) \ +#define DO_COMMON(type, ptype, clip, preserve, planar) \ const ThreadData *td = arg; \ const int linesize = s->linesize; \ const int step = s->step; \ @@ -118,14 +120,14 @@ typedef struct ThreadData { type *dst_g = (type *)(td->dstrow[G]) + src_linesize * slice_start; \ type *dst_b = (type *)(td->dstrow[B]) + src_linesize * slice_start; \ type *dst_a = (type *)(td->dstrow[A]) + src_linesize * slice_start; \ - const int imin_r = td->imin[R]; \ - const int imin_g = td->imin[G]; \ - const int imin_b = td->imin[B]; \ - const int imin_a = td->imin[A]; \ - const int omin_r = td->omin[R]; \ - const int omin_g = td->omin[G]; \ - const int omin_b = td->omin[B]; \ - const int omin_a = td->omin[A]; \ + const ptype imin_r = s->depth == 32 ? td->fimin[R] : td->imin[R]; \ + const ptype imin_g = s->depth == 32 ? td->fimin[G] : td->imin[G]; \ + const ptype imin_b = s->depth == 32 ? td->fimin[B] : td->imin[B]; \ + const ptype imin_a = s->depth == 32 ? td->fimin[A] : td->imin[A]; \ + const ptype omin_r = s->depth == 32 ? td->fomin[R] : td->omin[R]; \ + const ptype omin_g = s->depth == 32 ? td->fomin[G] : td->omin[G]; \ + const ptype omin_b = s->depth == 32 ? td->fomin[B] : td->omin[B]; \ + const ptype omin_a = s->depth == 32 ? td->fomin[A] : td->omin[A]; \ const float coeff_r = td->coeff[R]; \ const float coeff_g = td->coeff[G]; \ const float coeff_b = td->coeff[B]; \ @@ -133,12 +135,12 @@ typedef struct ThreadData { \ for (int y = slice_start; y < slice_end; y++) { \ for (int x = 0; x < linesize; x += step) { \ - int ir, ig, ib, or, og, ob; \ + ptype ir, ig, ib, or, og, ob; \ ir = src_r[x]; \ ig = src_g[x]; \ ib = src_b[x]; \ if (preserve) { \ - float ratio, icolor, ocolor, max = s->max; \ + float ratio, icolor, ocolor, max = s->depth==32 ? 1.f : s->max; \ \ or = (ir - imin_r) * coeff_r + omin_r; \ og = (ig - imin_g) * coeff_g + omin_g; \ @@ -180,39 +182,40 @@ typedef struct ThreadData { #define CLIP8(x, depth) av_clip_uint8(x) #define CLIP16(x, depth) av_clip_uint16(x) +#define NOCLIP(x, depth) (x) static int colorlevels_slice_8(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) { ColorLevelsContext *s = ctx->priv; - DO_COMMON(uint8_t, CLIP8, 0, 0) + DO_COMMON(uint8_t, int, CLIP8, 0, 0) return 0; } static int colorlevels_slice_16(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) { ColorLevelsContext *s = ctx->priv;\ - DO_COMMON(uint16_t, CLIP16, 0, 0) + DO_COMMON(uint16_t, int, CLIP16, 0, 0) return 0; } static int colorlevels_preserve_slice_8(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) { ColorLevelsContext *s = ctx->priv; - DO_COMMON(uint8_t, CLIP8, 1, 0) + DO_COMMON(uint8_t, int, CLIP8, 1, 0) return 0; } static int colorlevels_preserve_slice_16(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) { ColorLevelsContext *s = ctx->priv; - DO_COMMON(uint16_t, CLIP16, 1, 0) + DO_COMMON(uint16_t, int, CLIP16, 1, 0) return 0; } static int colorlevels_slice_8_planar(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) { ColorLevelsContext *s = ctx->priv; - DO_COMMON(uint8_t, CLIP8, 0, 1) + DO_COMMON(uint8_t, int, CLIP8, 0, 1) return 0; } @@ -220,7 +223,7 @@ static int colorlevels_slice_9_planar(AVFilterContext *ctx, void *arg, int jobnr { ColorLevelsContext *s = ctx->priv; const int depth = 9; - DO_COMMON(uint16_t, av_clip_uintp2, 0, 1) + DO_COMMON(uint16_t, int, av_clip_uintp2, 0, 1) return 0; } @@ -228,7 +231,7 @@ static int colorlevels_slice_10_planar(AVFilterContext *ctx, void *arg, int jobn { ColorLevelsContext *s = ctx->priv; const int depth = 10; - DO_COMMON(uint16_t, av_clip_uintp2, 0, 1) + DO_COMMON(uint16_t, int, av_clip_uintp2, 0, 1) return 0; } @@ -236,7 +239,7 @@ static int colorlevels_slice_12_planar(AVFilterContext *ctx, void *arg, int jobn { ColorLevelsContext *s = ctx->priv; const int depth = 12; - DO_COMMON(uint16_t, av_clip_uintp2, 0, 1) + DO_COMMON(uint16_t, int, av_clip_uintp2, 0, 1) return 0; } @@ -244,21 +247,28 @@ static int colorlevels_slice_14_planar(AVFilterContext *ctx, void *arg, int jobn { ColorLevelsContext *s = ctx->priv; const int depth = 14; - DO_COMMON(uint16_t, av_clip_uintp2, 0, 1) + DO_COMMON(uint16_t, int, av_clip_uintp2, 0, 1) return 0; } static int colorlevels_slice_16_planar(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) { ColorLevelsContext *s = ctx->priv; - DO_COMMON(uint16_t, CLIP16, 0, 1) + DO_COMMON(uint16_t, int, CLIP16, 0, 1) + return 0; +} + +static int colorlevels_slice_32_planar(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) +{ + ColorLevelsContext *s = ctx->priv; + DO_COMMON(float, float, NOCLIP, 0, 1) return 0; } static int colorlevels_preserve_slice_8_planar(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) { ColorLevelsContext *s = ctx->priv; - DO_COMMON(uint8_t, CLIP8, 1, 1) + DO_COMMON(uint8_t, int, CLIP8, 1, 1) return 0; } @@ -266,7 +276,7 @@ static int colorlevels_preserve_slice_9_planar(AVFilterContext *ctx, void *arg, { ColorLevelsContext *s = ctx->priv; const int depth = 9; - DO_COMMON(uint16_t, av_clip_uintp2, 1, 1) + DO_COMMON(uint16_t, int, av_clip_uintp2, 1, 1) return 0; } @@ -274,7 +284,7 @@ static int colorlevels_preserve_slice_10_planar(AVFilterContext *ctx, void *arg, { ColorLevelsContext *s = ctx->priv; const int depth = 10; - DO_COMMON(uint16_t, av_clip_uintp2, 1, 1) + DO_COMMON(uint16_t, int, av_clip_uintp2, 1, 1) return 0; } @@ -282,7 +292,7 @@ static int colorlevels_preserve_slice_12_planar(AVFilterContext *ctx, void *arg, { ColorLevelsContext *s = ctx->priv; const int depth = 12; - DO_COMMON(uint16_t, av_clip_uintp2, 1, 1) + DO_COMMON(uint16_t, int, av_clip_uintp2, 1, 1) return 0; } @@ -290,14 +300,21 @@ static int colorlevels_preserve_slice_14_planar(AVFilterContext *ctx, void *arg, { ColorLevelsContext *s = ctx->priv; const int depth = 14; - DO_COMMON(uint16_t, av_clip_uintp2, 1, 1) + DO_COMMON(uint16_t, int, av_clip_uintp2, 1, 1) return 0; } static int colorlevels_preserve_slice_16_planar(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) { ColorLevelsContext *s = ctx->priv; - DO_COMMON(uint16_t, CLIP16, 1, 1) + DO_COMMON(uint16_t, int, CLIP16, 1, 1) + return 0; +} + +static int colorlevels_preserve_slice_32_planar(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) +{ + ColorLevelsContext *s = ctx->priv; + DO_COMMON(float, float, NOCLIP, 1, 1) return 0; } @@ -349,6 +366,10 @@ static int config_input(AVFilterLink *inlink) s->colorlevels_slice[0] = colorlevels_slice_16_planar; s->colorlevels_slice[1] = colorlevels_preserve_slice_16_planar; break; + case 32: + s->colorlevels_slice[0] = colorlevels_slice_32_planar; + s->colorlevels_slice[1] = colorlevels_preserve_slice_32_planar; + break; } } @@ -479,6 +500,46 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in) td.omin[i] = omin; } break; + case 4: + for (int i = 0; i < s->nb_comp; i++) { + Range *r = &s->range[i]; + const uint8_t offset = s->rgba_map[i]; + const uint8_t *srcrow = in->data[0]; + float imin = r->in_min; + float imax = r->in_max; + float omin = r->out_min; + float omax = r->out_max; + float coeff; + + if (imin < 0.f) { + imin = 1.f; + for (int y = 0; y < inlink->h; y++) { + const float *src = (const float *)srcrow; + + for (int x = 0; x < s->linesize; x += step) + imin = fminf(imin, src[x + offset]); + srcrow += in->linesize[0]; + } + } + if (imax < 0.f) { + srcrow = in->data[0]; + imax = 0.f; + for (int y = 0; y < inlink->h; y++) { + const float *src = (const float *)srcrow; + + for (int x = 0; x < s->linesize; x += step) + imax = fmaxf(imax, src[x + offset]); + srcrow += in->linesize[0]; + } + } + + coeff = (omax - omin) / (double)(imax - imin); + + td.coeff[i] = coeff; + td.fimin[i] = imin; + td.fomin[i] = omin; + } + break; } ff_filter_execute(ctx, s->colorlevels_slice[s->preserve_color > 0], &td, NULL, @@ -524,7 +585,8 @@ const AVFilter ff_vf_colorlevels = { AV_PIX_FMT_GBRP10, AV_PIX_FMT_GBRAP10, AV_PIX_FMT_GBRP12, AV_PIX_FMT_GBRAP12, AV_PIX_FMT_GBRP14, - AV_PIX_FMT_GBRP16, AV_PIX_FMT_GBRAP16), + AV_PIX_FMT_GBRP16, AV_PIX_FMT_GBRAP16, + AV_PIX_FMT_GBRPF32, AV_PIX_FMT_GBRAPF32), .flags = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC | AVFILTER_FLAG_SLICE_THREADS, .process_command = ff_filter_process_command, }; From 9bfdd8524e4d3657be4057798bd4f015322827b2 Mon Sep 17 00:00:00 2001 From: Niklas Haas Date: Mon, 30 Jan 2023 20:34:55 +0100 Subject: [PATCH 0127/2172] avfilter/vf_libplacebo: suppress cast warning This warning was introduced when ee65039 removed the cast. --- libavfilter/vf_libplacebo.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/libavfilter/vf_libplacebo.c b/libavfilter/vf_libplacebo.c index d3c62d12a42..12abca4cc7f 100644 --- a/libavfilter/vf_libplacebo.c +++ b/libavfilter/vf_libplacebo.c @@ -262,8 +262,7 @@ static int init_vulkan(AVFilterContext *avctx) return AVERROR(EINVAL); } - avhwctx = avctx->hw_device_ctx->data; - + avhwctx = (AVHWDeviceContext *) avctx->hw_device_ctx->data; if (avhwctx->type != AV_HWDEVICE_TYPE_VULKAN) { av_log(s, AV_LOG_ERROR, "Expected vulkan hwdevice for vf_libplacebo, got %s.\n", av_hwdevice_get_type_name(avhwctx->type)); From 280e6e93fc96afbbb73f1987eb3d603f8949ea30 Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Wed, 25 Jan 2023 19:31:44 +0100 Subject: [PATCH 0128/2172] avcodec: add ADPCM XMD decoder --- Changelog | 1 + libavcodec/Makefile | 1 + libavcodec/adpcm.c | 44 +++++++++++++++++++++++++++++++++++++++++ libavcodec/allcodecs.c | 1 + libavcodec/codec_desc.c | 7 +++++++ libavcodec/codec_id.h | 1 + libavcodec/utils.c | 3 +++ libavcodec/version.h | 2 +- 8 files changed, 59 insertions(+), 1 deletion(-) diff --git a/Changelog b/Changelog index a0f1ad7211a..a0ba25257de 100644 --- a/Changelog +++ b/Changelog @@ -34,6 +34,7 @@ version : - ssim360 video filter - ffmpeg CLI new options: -enc_stats_pre[_fmt], -enc_stats_post[_fmt] - hstack_vaapi, vstack_vaapi and xstack_vaapi filters +- XMD ADPCM decoder version 5.1: diff --git a/libavcodec/Makefile b/libavcodec/Makefile index f0ffd0b961d..629933d85cc 100644 --- a/libavcodec/Makefile +++ b/libavcodec/Makefile @@ -959,6 +959,7 @@ OBJS-$(CONFIG_ADPCM_THP_DECODER) += adpcm.o adpcm_data.o OBJS-$(CONFIG_ADPCM_THP_LE_DECODER) += adpcm.o adpcm_data.o OBJS-$(CONFIG_ADPCM_VIMA_DECODER) += vima.o adpcm_data.o OBJS-$(CONFIG_ADPCM_XA_DECODER) += adpcm.o adpcm_data.o +OBJS-$(CONFIG_ADPCM_XMD_DECODER) += adpcm.o adpcm_data.o OBJS-$(CONFIG_ADPCM_YAMAHA_DECODER) += adpcm.o adpcm_data.o OBJS-$(CONFIG_ADPCM_YAMAHA_ENCODER) += adpcmenc.o adpcm_data.o OBJS-$(CONFIG_ADPCM_ZORK_DECODER) += adpcm.o adpcm_data.o diff --git a/libavcodec/adpcm.c b/libavcodec/adpcm.c index 841538b1389..451696932d1 100644 --- a/libavcodec/adpcm.c +++ b/libavcodec/adpcm.c @@ -324,6 +324,7 @@ static av_cold int adpcm_decode_init(AVCodecContext * avctx) case AV_CODEC_ID_ADPCM_IMA_WAV: case AV_CODEC_ID_ADPCM_4XM: case AV_CODEC_ID_ADPCM_XA: + case AV_CODEC_ID_ADPCM_XMD: case AV_CODEC_ID_ADPCM_EA_R1: case AV_CODEC_ID_ADPCM_EA_R2: case AV_CODEC_ID_ADPCM_EA_R3: @@ -1043,6 +1044,9 @@ static int get_nb_samples(AVCodecContext *avctx, GetByteContext *gb, case AV_CODEC_ID_ADPCM_XA: nb_samples = (buf_size / 128) * 224 / ch; break; + case AV_CODEC_ID_ADPCM_XMD: + nb_samples = buf_size / (21 * ch) * 32; + break; case AV_CODEC_ID_ADPCM_DTK: case AV_CODEC_ID_ADPCM_PSX: nb_samples = buf_size / (16 * ch) * 28; @@ -1553,6 +1557,45 @@ static int adpcm_decode_frame(AVCodecContext *avctx, AVFrame *frame, } bytestream2_seek(&gb, 0, SEEK_END); ) /* End of CASE */ + CASE(ADPCM_XMD, + int bytes_remaining, block = 0; + while (bytestream2_get_bytes_left(&gb) >= 21 * channels) { + for (int channel = 0; channel < channels; channel++) { + int16_t *out = samples_p[channel] + block * 32; + int16_t history[2]; + uint16_t scale; + + history[1] = sign_extend(bytestream2_get_le16(&gb), 16); + history[0] = sign_extend(bytestream2_get_le16(&gb), 16); + scale = bytestream2_get_le16(&gb); + + out[0] = history[1]; + out[1] = history[0]; + + for (int n = 0; n < 15; n++) { + unsigned byte = bytestream2_get_byte(&gb); + int32_t nibble[2]; + + nibble[0] = sign_extend(byte & 15, 4); + nibble[1] = sign_extend(byte >> 4, 4); + + out[2+n*2] = (nibble[0]*(scale<<14) + (history[0]*29336) - (history[1]*13136)) >> 14; + history[1] = history[0]; + history[0] = out[2+n*2]; + + out[2+n*2+1] = (nibble[1]*(scale<<14) + (history[0]*29336) - (history[1]*13136)) >> 14; + history[1] = history[0]; + history[0] = out[2+n*2+1]; + } + } + + block++; + } + bytes_remaining = bytestream2_get_bytes_left(&gb); + if (bytes_remaining > 0) { + bytestream2_skip(&gb, bytes_remaining); + } + ) /* End of CASE */ CASE(ADPCM_XA, int16_t *out0 = samples_p[0]; int16_t *out1 = samples_p[1]; @@ -2350,5 +2393,6 @@ ADPCM_DECODER(ADPCM_SWF, sample_fmts_s16, adpcm_swf, "ADPCM Sho ADPCM_DECODER(ADPCM_THP_LE, sample_fmts_s16p, adpcm_thp_le, "ADPCM Nintendo THP (little-endian)") ADPCM_DECODER(ADPCM_THP, sample_fmts_s16p, adpcm_thp, "ADPCM Nintendo THP") ADPCM_DECODER(ADPCM_XA, sample_fmts_s16p, adpcm_xa, "ADPCM CDROM XA") +ADPCM_DECODER(ADPCM_XMD, sample_fmts_s16p, adpcm_xmd, "ADPCM Konami XMD") ADPCM_DECODER(ADPCM_YAMAHA, sample_fmts_s16, adpcm_yamaha, "ADPCM Yamaha") ADPCM_DECODER(ADPCM_ZORK, sample_fmts_s16, adpcm_zork, "ADPCM Zork") diff --git a/libavcodec/allcodecs.c b/libavcodec/allcodecs.c index f30047e17aa..0deaea65b36 100644 --- a/libavcodec/allcodecs.c +++ b/libavcodec/allcodecs.c @@ -695,6 +695,7 @@ extern const FFCodec ff_adpcm_thp_decoder; extern const FFCodec ff_adpcm_thp_le_decoder; extern const FFCodec ff_adpcm_vima_decoder; extern const FFCodec ff_adpcm_xa_decoder; +extern const FFCodec ff_adpcm_xmd_decoder; extern const FFCodec ff_adpcm_yamaha_encoder; extern const FFCodec ff_adpcm_yamaha_decoder; extern const FFCodec ff_adpcm_zork_decoder; diff --git a/libavcodec/codec_desc.c b/libavcodec/codec_desc.c index 50f9794e10d..fbb6604f769 100644 --- a/libavcodec/codec_desc.c +++ b/libavcodec/codec_desc.c @@ -2536,6 +2536,13 @@ static const AVCodecDescriptor codec_descriptors[] = { .long_name = NULL_IF_CONFIG_SMALL("ADPCM IMA Acorn Replay"), .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSY, }, + { + .id = AV_CODEC_ID_ADPCM_XMD, + .type = AVMEDIA_TYPE_AUDIO, + .name = "adpcm_xmd", + .long_name = NULL_IF_CONFIG_SMALL("ADPCM Konami XMD"), + .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSY, + }, /* AMR */ { diff --git a/libavcodec/codec_id.h b/libavcodec/codec_id.h index cdf7eb79c39..3e84098f354 100644 --- a/libavcodec/codec_id.h +++ b/libavcodec/codec_id.h @@ -413,6 +413,7 @@ enum AVCodecID { AV_CODEC_ID_ADPCM_IMA_CUNNING, AV_CODEC_ID_ADPCM_IMA_MOFLEX, AV_CODEC_ID_ADPCM_IMA_ACORN, + AV_CODEC_ID_ADPCM_XMD, /* AMR */ AV_CODEC_ID_AMR_NB = 0x12000, diff --git a/libavcodec/utils.c b/libavcodec/utils.c index 94f7ae6877c..18a433b1af0 100644 --- a/libavcodec/utils.c +++ b/libavcodec/utils.c @@ -769,6 +769,9 @@ static int get_audio_frame_duration(enum AVCodecID id, int sr, int ch, int ba, case AV_CODEC_ID_ADPCM_MTAF: tmp = blocks * (ba - 16LL) * 2 / ch; break; + case AV_CODEC_ID_ADPCM_XMD: + tmp = blocks * 32; + break; } if (tmp) { if (tmp != (int)tmp) diff --git a/libavcodec/version.h b/libavcodec/version.h index 752adc81f8f..2ed4ef5547f 100644 --- a/libavcodec/version.h +++ b/libavcodec/version.h @@ -29,7 +29,7 @@ #include "version_major.h" -#define LIBAVCODEC_VERSION_MINOR 59 +#define LIBAVCODEC_VERSION_MINOR 60 #define LIBAVCODEC_VERSION_MICRO 100 #define LIBAVCODEC_VERSION_INT AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \ From fa42575ffa30f226f6fda89cb192f315319f8575 Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Wed, 25 Jan 2023 19:16:03 +0100 Subject: [PATCH 0129/2172] avformat: add XMD demuxer --- Changelog | 2 +- libavformat/Makefile | 1 + libavformat/allformats.c | 1 + libavformat/version.h | 2 +- libavformat/xmd.c | 80 ++++++++++++++++++++++++++++++++++++++++ 5 files changed, 84 insertions(+), 2 deletions(-) create mode 100644 libavformat/xmd.c diff --git a/Changelog b/Changelog index a0ba25257de..aa0dad13a17 100644 --- a/Changelog +++ b/Changelog @@ -34,7 +34,7 @@ version : - ssim360 video filter - ffmpeg CLI new options: -enc_stats_pre[_fmt], -enc_stats_post[_fmt] - hstack_vaapi, vstack_vaapi and xstack_vaapi filters -- XMD ADPCM decoder +- XMD ADPCM decoder and demuxer version 5.1: diff --git a/libavformat/Makefile b/libavformat/Makefile index 2d11bcd7a33..0bb9e8c19af 100644 --- a/libavformat/Makefile +++ b/libavformat/Makefile @@ -621,6 +621,7 @@ OBJS-$(CONFIG_WVE_DEMUXER) += wvedec.o pcm.o OBJS-$(CONFIG_WV_MUXER) += wvenc.o wv.o apetag.o img2.o OBJS-$(CONFIG_XA_DEMUXER) += xa.o OBJS-$(CONFIG_XBIN_DEMUXER) += bintext.o sauce.o +OBJS-$(CONFIG_XMD_DEMUXER) += xmd.o pcm.o OBJS-$(CONFIG_XMV_DEMUXER) += xmv.o OBJS-$(CONFIG_XVAG_DEMUXER) += xvag.o OBJS-$(CONFIG_XWMA_DEMUXER) += xwma.o diff --git a/libavformat/allformats.c b/libavformat/allformats.c index bf8afe2078c..2d31956fd57 100644 --- a/libavformat/allformats.c +++ b/libavformat/allformats.c @@ -501,6 +501,7 @@ extern const AVInputFormat ff_wv_demuxer; extern const AVOutputFormat ff_wv_muxer; extern const AVInputFormat ff_xa_demuxer; extern const AVInputFormat ff_xbin_demuxer; +extern const AVInputFormat ff_xmd_demuxer; extern const AVInputFormat ff_xmv_demuxer; extern const AVInputFormat ff_xvag_demuxer; extern const AVInputFormat ff_xwma_demuxer; diff --git a/libavformat/version.h b/libavformat/version.h index 3970ec5cdd6..789859fbe29 100644 --- a/libavformat/version.h +++ b/libavformat/version.h @@ -31,7 +31,7 @@ #include "version_major.h" -#define LIBAVFORMAT_VERSION_MINOR 36 +#define LIBAVFORMAT_VERSION_MINOR 37 #define LIBAVFORMAT_VERSION_MICRO 100 #define LIBAVFORMAT_VERSION_INT AV_VERSION_INT(LIBAVFORMAT_VERSION_MAJOR, \ diff --git a/libavformat/xmd.c b/libavformat/xmd.c new file mode 100644 index 00000000000..f9c8138d72a --- /dev/null +++ b/libavformat/xmd.c @@ -0,0 +1,80 @@ +/* + * XMD demuxer + * Copyright (c) 2023 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 "libavutil/channel_layout.h" +#include "libavutil/intreadwrite.h" +#include "avformat.h" +#include "demux.h" +#include "internal.h" +#include "pcm.h" + +static int xmd_probe(const AVProbeData *p) +{ + if ((AV_RL32(p->buf) & 0xFFFFFF) != MKTAG('x','m','d',0)) + return 0; + if (p->buf[3] == 0 || p->buf[3] > 2 || + AV_RL16(p->buf+4) == 0 || + AV_RL32(p->buf+6) == 0) + return 0; + + return AVPROBE_SCORE_MAX / 3; +} + +static int xmd_read_header(AVFormatContext *s) +{ + AVIOContext *pb = s->pb; + AVCodecParameters *par; + int channels; + AVStream *st; + + avio_skip(pb, 3); + + st = avformat_new_stream(s, NULL); + if (!st) + return AVERROR(ENOMEM); + + par = st->codecpar; + par->codec_type = AVMEDIA_TYPE_AUDIO; + par->codec_id = AV_CODEC_ID_ADPCM_XMD; + channels = avio_r8(pb); + if (channels == 0) + return AVERROR_INVALIDDATA; + av_channel_layout_default(&par->ch_layout, channels); + par->sample_rate = avio_rl16(pb); + if (par->sample_rate <= 0) + return AVERROR_INVALIDDATA; + par->block_align = 21 * channels; + st->duration = (avio_rl32(pb) / par->block_align) * 32LL; + avpriv_set_pts_info(st, 64, 1, par->sample_rate); + avio_skip(pb, 7); + + return 0; +} + +const AVInputFormat ff_xmd_demuxer = { + .name = "xmd", + .long_name = NULL_IF_CONFIG_SMALL("Konami XMD"), + .read_probe = xmd_probe, + .read_header = xmd_read_header, + .read_packet = ff_pcm_read_packet, + .flags = AVFMT_GENERIC_INDEX, + .extensions = "xmd", +}; From 229f3259f80d824c7e7bb3bd5935ae4bc75d5374 Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Mon, 30 Jan 2023 21:34:04 +0100 Subject: [PATCH 0130/2172] doc/general_contents: sync with available decoders and demuxers --- doc/general_contents.texi | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/doc/general_contents.texi b/doc/general_contents.texi index 8399fcb6b7b..87e180c9799 100644 --- a/doc/general_contents.texi +++ b/doc/general_contents.texi @@ -534,6 +534,8 @@ library: @item Metal Gear Solid: The Twin Snakes @tab @tab X @item Megalux Frame @tab @tab X @tab Used by Megalux Ultimate Paint +@item MobiClip MODS @tab @tab X +@item MobiClip MOFLEX @tab @tab X @item Mobotix .mxg @tab @tab X @item Monkey's Audio @tab @tab X @item Motion Pixels MVI @tab @tab X @@ -665,6 +667,7 @@ library: @item SBG @tab @tab X @item SDP @tab @tab X @item SER @tab @tab X +@item Digital Pictures SGA @tab @tab X @item Sega FILM/CPK @tab X @tab X @tab Used in many Sega Saturn console games. @item Silicon Graphics Movie @tab @tab X @@ -702,6 +705,7 @@ library: @item Vivo @tab @tab X @item VPK @tab @tab X @tab Audio format used in Sony PS games. +@item Marble WADY @tab @tab X @item WAV @tab X @tab X @item WavPack @tab X @tab X @item WebM @tab X @tab X @@ -714,6 +718,7 @@ library: @tab Multimedia format used in Westwood Studios games. @item Wideband Single-bit Data (WSD) @tab @tab X @item WVE @tab @tab X +@item Konami XMD @tab @tab X @item XMV @tab @tab X @tab Microsoft video container used in Xbox games. @item XVAG @tab @tab X @@ -763,6 +768,7 @@ following image formats are supported: @item JPEG-LS @tab X @tab X @item LJPEG @tab X @tab @tab Lossless JPEG +@item Media 100 @tab @tab X @item MSP @tab @tab X @tab Microsoft Paint image @item PAM @tab X @tab X @@ -1159,6 +1165,7 @@ following image formats are supported: @item ADPCM IMA Electronic Arts SEAD @tab @tab X @item ADPCM IMA Funcom @tab @tab X @item ADPCM IMA High Voltage Software ALP @tab X @tab X +@item ADPCM IMA Mobiclip MOFLEX @tab @tab X @item ADPCM IMA QuickTime @tab X @tab X @item ADPCM IMA Simon & Schuster Interactive @tab X @tab X @item ADPCM IMA Ubisoft APM @tab X @tab X @@ -1188,6 +1195,7 @@ following image formats are supported: @item ADPCM Sound Blaster Pro 4-bit @tab @tab X @item ADPCM VIMA @tab @tab X @tab Used in LucasArts SMUSH animations. +@item ADPCM Konami XMD @tab @tab X @item ADPCM Westwood Studios IMA @tab X @tab X @tab Used in Westwood Studios games like Command and Conquer. @item ADPCM Yamaha @tab X @tab X @@ -1225,9 +1233,12 @@ following image formats are supported: @item DCA (DTS Coherent Acoustics) @tab X @tab X @tab supported extensions: XCh, XXCH, X96, XBR, XLL, LBR (partially) @item Dolby E @tab @tab X +@item DPCM Cuberoot-Delta-Exact @tab @tab X + @tab Used in few games. @item DPCM Gremlin @tab @tab X @item DPCM id RoQ @tab X @tab X @tab Used in Quake III, Jedi Knight 2 and other computer games. +@item DPCM Marble WADY @tab @tab X @item DPCM Interplay @tab @tab X @tab Used in various Interplay computer games. @item DPCM Squareroot-Delta-Exact @tab @tab X @@ -1273,6 +1284,7 @@ following image formats are supported: @item MP3 (MPEG audio layer 3) @tab E @tab IX @tab encoding supported through external library LAME, ADU MP3 and MP3onMP4 also supported @item MPEG-4 Audio Lossless Coding (ALS) @tab @tab X +@item MobiClip FastAudio @tab @tab X @item Musepack SV7 @tab @tab X @item Musepack SV8 @tab @tab X @item Nellymoser Asao @tab X @tab X @@ -1307,6 +1319,7 @@ following image formats are supported: @item PCM unsigned 24-bit little-endian @tab X @tab X @item PCM unsigned 32-bit big-endian @tab X @tab X @item PCM unsigned 32-bit little-endian @tab X @tab X +@item PCM SGA @tab @tab X @item QCELP / PureVoice @tab @tab X @item QDesign Music Codec 1 @tab @tab X @item QDesign Music Codec 2 @tab @tab X From e3a99041b80e915efc021f93eef1c3fddf41199c Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Fri, 27 Jan 2023 18:41:40 +0100 Subject: [PATCH 0131/2172] lavc: add null codecs They discard all input without ever returning any output. Useful for development. --- libavcodec/Makefile | 4 ++ libavcodec/allcodecs.c | 6 +++ libavcodec/codec_desc.c | 12 +++++ libavcodec/codec_id.h | 10 +++++ libavcodec/null.c | 97 +++++++++++++++++++++++++++++++++++++++++ 5 files changed, 129 insertions(+) create mode 100644 libavcodec/null.c diff --git a/libavcodec/Makefile b/libavcodec/Makefile index 629933d85cc..304c2bc2e3a 100644 --- a/libavcodec/Makefile +++ b/libavcodec/Makefile @@ -219,6 +219,8 @@ OBJS-$(CONFIG_AMRWB_DECODER) += amrwbdec.o celp_filters.o \ acelp_pitch_delay.o OBJS-$(CONFIG_AMV_ENCODER) += mjpegenc.o mjpegenc_common.o OBJS-$(CONFIG_ANM_DECODER) += anm.o +OBJS-$(CONFIG_ANULL_DECODER) += null.o +OBJS-$(CONFIG_ANULL_ENCODER) += null.o OBJS-$(CONFIG_ANSI_DECODER) += ansi.o cga_data.o OBJS-$(CONFIG_APAC_DECODER) += apac.o OBJS-$(CONFIG_APE_DECODER) += apedec.o @@ -747,6 +749,8 @@ OBJS-$(CONFIG_VCR1_DECODER) += vcr1.o OBJS-$(CONFIG_VMDAUDIO_DECODER) += vmdaudio.o OBJS-$(CONFIG_VMDVIDEO_DECODER) += vmdvideo.o OBJS-$(CONFIG_VMNC_DECODER) += vmnc.o +OBJS-$(CONFIG_VNULL_DECODER) += null.o +OBJS-$(CONFIG_VNULL_ENCODER) += null.o OBJS-$(CONFIG_VORBIS_DECODER) += vorbisdec.o vorbisdsp.o vorbis.o \ vorbis_data.o OBJS-$(CONFIG_VORBIS_ENCODER) += vorbisenc.o vorbis.o \ diff --git a/libavcodec/allcodecs.c b/libavcodec/allcodecs.c index 0deaea65b36..ff82423a88c 100644 --- a/libavcodec/allcodecs.c +++ b/libavcodec/allcodecs.c @@ -884,6 +884,12 @@ extern const FFCodec ff_vp9_qsv_decoder; extern const FFCodec ff_vp9_vaapi_encoder; extern const FFCodec ff_vp9_qsv_encoder; +// null codecs +extern const FFCodec ff_vnull_decoder; +extern const FFCodec ff_vnull_encoder; +extern const FFCodec ff_anull_decoder; +extern const FFCodec ff_anull_encoder; + // The iterate API is not usable with ossfuzz due to the excessive size of binaries created #if CONFIG_OSSFUZZ const FFCodec * codec_list[] = { diff --git a/libavcodec/codec_desc.c b/libavcodec/codec_desc.c index fbb6604f769..8ab228d8464 100644 --- a/libavcodec/codec_desc.c +++ b/libavcodec/codec_desc.c @@ -3625,6 +3625,18 @@ static const AVCodecDescriptor codec_descriptors[] = { .long_name = NULL_IF_CONFIG_SMALL("AVFrame to AVPacket passthrough"), .props = AV_CODEC_PROP_LOSSLESS, }, + { + .id = AV_CODEC_ID_VNULL, + .type = AVMEDIA_TYPE_VIDEO, + .name = "vnull", + .long_name = NULL_IF_CONFIG_SMALL("Null video codec"), + }, + { + .id = AV_CODEC_ID_ANULL, + .type = AVMEDIA_TYPE_AUDIO, + .name = "anull", + .long_name = NULL_IF_CONFIG_SMALL("Null audio codec"), + }, }; static int descriptor_compare(const void *key, const void *member) diff --git a/libavcodec/codec_id.h b/libavcodec/codec_id.h index 3e84098f354..0c574c96193 100644 --- a/libavcodec/codec_id.h +++ b/libavcodec/codec_id.h @@ -590,6 +590,16 @@ enum AVCodecID { * stream (only used by libavformat) */ AV_CODEC_ID_FFMETADATA = 0x21000, ///< Dummy codec for streams containing only metadata information. AV_CODEC_ID_WRAPPED_AVFRAME = 0x21001, ///< Passthrough codec, AVFrames wrapped in AVPacket + /** + * Dummy null video codec, useful mainly for development and debugging. + * Null encoder/decoder discard all input and never return any output. + */ + AV_CODEC_ID_VNULL, + /** + * Dummy null audio codec, useful mainly for development and debugging. + * Null encoder/decoder discard all input and never return any output. + */ + AV_CODEC_ID_ANULL, }; /** diff --git a/libavcodec/null.c b/libavcodec/null.c new file mode 100644 index 00000000000..d8e334437c7 --- /dev/null +++ b/libavcodec/null.c @@ -0,0 +1,97 @@ +/* + * Null codecs + * + * 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_components.h" + +#include "codec_internal.h" +#include "decode.h" +#include "encode.h" + +#if CONFIG_VNULL_DECODER || CONFIG_ANULL_DECODER +static int null_decode(AVCodecContext *avctx, AVFrame *frame, + int *got_frame, AVPacket *avpkt) +{ + *got_frame = 0; + return avpkt->size; +} + +#if CONFIG_VNULL_DECODER +const FFCodec ff_vnull_decoder = { + .p.name = "vnull", + CODEC_LONG_NAME("null video"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_VNULL, + .p.capabilities = AV_CODEC_CAP_DR1, + FF_CODEC_DECODE_CB(null_decode), +}; +#endif + +#if CONFIG_ANULL_DECODER +const FFCodec ff_anull_decoder = { + .p.name = "anull", + CODEC_LONG_NAME("null audio"), + .p.type = AVMEDIA_TYPE_AUDIO, + .p.id = AV_CODEC_ID_ANULL, + .p.capabilities = AV_CODEC_CAP_DR1, + FF_CODEC_DECODE_CB(null_decode), +}; +#endif + +#endif + +#if CONFIG_VNULL_ENCODER || CONFIG_ANULL_ENCODER +static int null_encode(AVCodecContext *avctx, AVPacket *pkt, + const AVFrame *frame, int *got_packet) +{ + *got_packet = 0; + return 0; +} + +#if CONFIG_VNULL_ENCODER +const FFCodec ff_vnull_encoder = { + .p.name = "vnull", + CODEC_LONG_NAME("null video"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_VNULL, + FF_CODEC_ENCODE_CB(null_encode), +}; +#endif + +#if CONFIG_ANULL_ENCODER +const FFCodec ff_anull_encoder = { + .p.name = "anull", + CODEC_LONG_NAME("null audio"), + .p.type = AVMEDIA_TYPE_AUDIO, + .p.id = AV_CODEC_ID_ANULL, + .p.capabilities = AV_CODEC_CAP_VARIABLE_FRAME_SIZE, + .p.sample_fmts = (const enum AVSampleFormat[]){ + AV_SAMPLE_FMT_U8, AV_SAMPLE_FMT_U8P, + AV_SAMPLE_FMT_S16, AV_SAMPLE_FMT_S16P, + AV_SAMPLE_FMT_S32, AV_SAMPLE_FMT_S32P, + AV_SAMPLE_FMT_S64, AV_SAMPLE_FMT_S64P, + AV_SAMPLE_FMT_FLT, AV_SAMPLE_FMT_FLTP, + AV_SAMPLE_FMT_DBL, AV_SAMPLE_FMT_DBLP, + AV_SAMPLE_FMT_NONE, + }, + FF_CODEC_ENCODE_CB(null_encode), +}; +#endif + +#endif From 5c36f4ef8410008d508b9ca348441903a15a6f7c Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Sun, 29 Jan 2023 22:13:33 +0100 Subject: [PATCH 0132/2172] lavu/opt: use AV_DICT_MULTIKEY in av_opt_set_dict2() If the dictionary provided on input contains multiple entries for an option (relevant for flags modifying the previous value with '+' or '-') and the option is not found in the target object, only the last entry would be returned to the caller. Pass AV_DICT_MULTIKEY to av_dict_set() to make sure all such entries are returned. --- libavutil/opt.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavutil/opt.c b/libavutil/opt.c index 0a909a8b22e..0908751752e 100644 --- a/libavutil/opt.c +++ b/libavutil/opt.c @@ -1752,7 +1752,7 @@ int av_opt_set_dict2(void *obj, AVDictionary **options, int search_flags) while ((t = av_dict_iterate(*options, t))) { ret = av_opt_set(obj, t->key, t->value, search_flags); if (ret == AVERROR_OPTION_NOT_FOUND) - ret = av_dict_set(&tmp, t->key, t->value, 0); + ret = av_dict_set(&tmp, t->key, t->value, AV_DICT_MULTIKEY); if (ret < 0) { av_log(obj, AV_LOG_ERROR, "Error setting option %s to value %s.\n", t->key, t->value); av_dict_free(&tmp); From 61afbc23766f1567857551eb7b2da5f8aab97c4c Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Sun, 29 Jan 2023 22:26:20 +0100 Subject: [PATCH 0133/2172] fftools/ffmpeg: use correct IO context for -enc_stats_post --- fftools/ffmpeg.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fftools/ffmpeg.c b/fftools/ffmpeg.c index 9884e0c6c67..3ad432ff54b 100644 --- a/fftools/ffmpeg.c +++ b/fftools/ffmpeg.c @@ -803,7 +803,7 @@ static void update_video_stats(OutputStream *ost, const AVPacket *pkt, int write static void enc_stats_write(OutputStream *ost, EncStats *es, const AVFrame *frame, const AVPacket *pkt) { - AVIOContext *io = ost->enc_stats_pre.io; + AVIOContext *io = es->io; AVRational tb = ost->enc_ctx->time_base; int64_t pts = frame ? frame->pts : pkt->pts; From 806ecace91d5b5e7c0f10b69746a57fd0d8a51f9 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Fri, 27 Jan 2023 12:19:16 +0100 Subject: [PATCH 0134/2172] fftools/ffmpeg: support input frame params in encoding stats --- doc/ffmpeg.texi | 17 ++++++++++++ fftools/ffmpeg.c | 54 ++++++++++++++++++++++++++++++++++++--- fftools/ffmpeg.h | 6 +++++ fftools/ffmpeg_mux_init.c | 21 +++++++++++++-- 4 files changed, 92 insertions(+), 6 deletions(-) diff --git a/doc/ffmpeg.texi b/doc/ffmpeg.texi index 7f445022a04..81e04f69834 100644 --- a/doc/ffmpeg.texi +++ b/doc/ffmpeg.texi @@ -2082,18 +2082,35 @@ Index of the output stream in the file. Frame number. Pre-encoding: number of frames sent to the encoder so far. Post-encoding: number of packets received from the encoder so far. +@item ni +Input frame number. Index of the input frame (i.e. output by a decoder) that +corresponds to this output frame or packet. -1 if unavailable. + @item tb Encoder timebase, as a rational number @var{num/den}. Note that this may be different from the timebase used by the muxer. +@item tbi +Timebase for @var{ptsi}, as a rational number @var{num/den}. Available when +@var{ptsi} is available, @var{0/1} otherwise. + @item pts Presentation timestamp of the frame or packet, as an integer. Should be multiplied by the timebase to compute presentation time. +@item ptsi +Presentation timestamp of the input frame (see @var{ni}), as an integer. Should +be multiplied by @var{tbi} to compute presentation time. Printed as +(2^63 - 1 = 9223372036854775807) when not available. + @item t Presentation time of the frame or packet, as a decimal number. Equal to @var{pts} multiplied by @var{tb}. +@item ti +Presentation time of the input frame (see @var{ni}), as a decimal number. Equal +to @var{ptsi} multiplied by @var{tbi}. Printed as inf when not available. + @item dts Decoding timestamp of the packet, as an integer. Should be multiplied by the timebase to compute presentation time. Post-encoding only. diff --git a/fftools/ffmpeg.c b/fftools/ffmpeg.c index 3ad432ff54b..92fd61f3158 100644 --- a/fftools/ffmpeg.c +++ b/fftools/ffmpeg.c @@ -113,6 +113,13 @@ const int program_birth_year = 2000; static FILE *vstats_file; +// optionally attached as opaque_ref to decoded AVFrames +typedef struct FrameData { + uint64_t idx; + int64_t pts; + AVRational tb; +} FrameData; + typedef struct BenchmarkTimeStamps { int64_t real_usec; int64_t user_usec; @@ -807,6 +814,17 @@ static void enc_stats_write(OutputStream *ost, EncStats *es, AVRational tb = ost->enc_ctx->time_base; int64_t pts = frame ? frame->pts : pkt->pts; + AVRational tbi = (AVRational){ 0, 1}; + int64_t ptsi = INT64_MAX; + + const FrameData *fd; + + if ((frame && frame->opaque_ref) || (pkt && pkt->opaque_ref)) { + fd = (const FrameData*)(frame ? frame->opaque_ref->data : pkt->opaque_ref->data); + tbi = fd->tb; + ptsi = fd->pts; + } + for (size_t i = 0; i < es->nb_components; i++) { const EncStatsComponent *c = &es->components[i]; @@ -815,8 +833,13 @@ static void enc_stats_write(OutputStream *ost, EncStats *es, case ENC_STATS_FILE_IDX: avio_printf(io, "%d", ost->file_index); continue; case ENC_STATS_STREAM_IDX: avio_printf(io, "%d", ost->index); continue; case ENC_STATS_TIMEBASE: avio_printf(io, "%d/%d", tb.num, tb.den); continue; + case ENC_STATS_TIMEBASE_IN: avio_printf(io, "%d/%d", tbi.num, tbi.den); continue; case ENC_STATS_PTS: avio_printf(io, "%"PRId64, pts); continue; + case ENC_STATS_PTS_IN: avio_printf(io, "%"PRId64, ptsi); continue; case ENC_STATS_PTS_TIME: avio_printf(io, "%g", pts * av_q2d(tb)); continue; + case ENC_STATS_PTS_TIME_IN: avio_printf(io, "%g", ptsi == INT64_MAX ? + INFINITY : ptsi * av_q2d(tbi)); continue; + case ENC_STATS_FRAME_NUM_IN: avio_printf(io, "%"PRIu64, fd ? fd->idx : -1); continue; } if (frame) { @@ -2034,7 +2057,8 @@ static int ifilter_send_eof(InputFilter *ifilter, int64_t pts) // There is the following difference: if you got a frame, you must call // it again with pkt=NULL. pkt==NULL is treated differently from pkt->size==0 // (pkt==NULL means get more output, pkt->size==0 is a flush/drain packet) -static int decode(AVCodecContext *avctx, AVFrame *frame, int *got_frame, AVPacket *pkt) +static int decode(InputStream *ist, AVCodecContext *avctx, + AVFrame *frame, int *got_frame, AVPacket *pkt) { int ret; @@ -2051,8 +2075,24 @@ static int decode(AVCodecContext *avctx, AVFrame *frame, int *got_frame, AVPacke ret = avcodec_receive_frame(avctx, frame); if (ret < 0 && ret != AVERROR(EAGAIN)) return ret; - if (ret >= 0) + if (ret >= 0) { + if (ist->want_frame_data) { + FrameData *fd; + + av_assert0(!frame->opaque_ref); + frame->opaque_ref = av_buffer_allocz(sizeof(*fd)); + if (!frame->opaque_ref) { + av_frame_unref(frame); + return AVERROR(ENOMEM); + } + fd = (FrameData*)frame->opaque_ref->data; + fd->pts = frame->pts; + fd->tb = avctx->pkt_timebase; + fd->idx = avctx->frame_number - 1; + } + *got_frame = 1; + } return 0; } @@ -2084,7 +2124,7 @@ static int decode_audio(InputStream *ist, AVPacket *pkt, int *got_output, AVRational decoded_frame_tb; update_benchmark(NULL); - ret = decode(avctx, decoded_frame, got_output, pkt); + ret = decode(ist, avctx, decoded_frame, got_output, pkt); update_benchmark("decode_audio %d.%d", ist->file_index, ist->st->index); if (ret < 0) *decode_failed = 1; @@ -2163,7 +2203,7 @@ static int decode_video(InputStream *ist, AVPacket *pkt, int *got_output, int64_ } update_benchmark(NULL); - ret = decode(ist->dec_ctx, decoded_frame, got_output, pkt); + ret = decode(ist, ist->dec_ctx, decoded_frame, got_output, pkt); update_benchmark("decode_video %d.%d", ist->file_index, ist->st->index); if (ret < 0) *decode_failed = 1; @@ -3017,6 +3057,12 @@ static int init_output_stream(OutputStream *ost, AVFrame *frame, if (!av_dict_get(ost->encoder_opts, "threads", NULL, 0)) av_dict_set(&ost->encoder_opts, "threads", "auto", 0); + if (codec->capabilities & AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE) { + ret = av_dict_set(&ost->encoder_opts, "flags", "+copy_opaque", AV_DICT_MULTIKEY); + if (ret < 0) + return ret; + } + ret = hw_device_setup_for_encode(ost); if (ret < 0) { snprintf(error, error_len, "Device setup failed for " diff --git a/fftools/ffmpeg.h b/fftools/ffmpeg.h index dddab456f7c..8c976af97ad 100644 --- a/fftools/ffmpeg.h +++ b/fftools/ffmpeg.h @@ -335,6 +335,8 @@ typedef struct InputStream { #define DECODING_FOR_OST 1 #define DECODING_FOR_FILTER 2 int processing_needed; /* non zero if the packets must be processed */ + // should attach FrameData as opaque_ref after decoding + int want_frame_data; /** * Codec parameters - to be used by the decoding/streamcopy code. @@ -493,9 +495,13 @@ enum EncStatsType { ENC_STATS_FILE_IDX, ENC_STATS_STREAM_IDX, ENC_STATS_FRAME_NUM, + ENC_STATS_FRAME_NUM_IN, ENC_STATS_TIMEBASE, + ENC_STATS_TIMEBASE_IN, ENC_STATS_PTS, ENC_STATS_PTS_TIME, + ENC_STATS_PTS_IN, + ENC_STATS_PTS_TIME_IN, ENC_STATS_DTS, ENC_STATS_DTS_TIME, ENC_STATS_SAMPLE_NUM, diff --git a/fftools/ffmpeg_mux_init.c b/fftools/ffmpeg_mux_init.c index 35b115f8a63..f8ccf4a3e9b 100644 --- a/fftools/ffmpeg_mux_init.c +++ b/fftools/ffmpeg_mux_init.c @@ -269,13 +269,18 @@ static int enc_stats_init(OutputStream *ost, int pre, const char *str; int pre_only:1; int post_only:1; + int need_input_data:1; } fmt_specs[] = { { ENC_STATS_FILE_IDX, "fidx" }, { ENC_STATS_STREAM_IDX, "sidx" }, { ENC_STATS_FRAME_NUM, "n" }, + { ENC_STATS_FRAME_NUM_IN, "ni", 0, 0, 1 }, { ENC_STATS_TIMEBASE, "tb" }, + { ENC_STATS_TIMEBASE_IN, "tbi", 0, 0, 1 }, { ENC_STATS_PTS, "pts" }, { ENC_STATS_PTS_TIME, "t" }, + { ENC_STATS_PTS_IN, "ptsi", 0, 0, 1 }, + { ENC_STATS_PTS_TIME_IN, "ti", 0, 0, 1 }, { ENC_STATS_DTS, "dts", 0, 1 }, { ENC_STATS_DTS_TIME, "dt", 0, 1 }, { ENC_STATS_SAMPLE_NUM, "sn", 1 }, @@ -345,6 +350,18 @@ static int enc_stats_init(OutputStream *ost, int pre, } c->type = fmt_specs[i].type; + + if (fmt_specs[i].need_input_data) { + if (ost->ist) + ost->ist->want_frame_data = 1; + else { + av_log(ost, AV_LOG_WARNING, + "Format directive '%s' is unavailable, because " + "this output stream has no associated input stream\n", + val); + } + } + break; } } @@ -428,6 +445,7 @@ static OutputStream *new_output_stream(Muxer *mux, const OptionsContext *o, ms->last_mux_dts = AV_NOPTS_VALUE; ost->st = st; + ost->ist = ist; ost->kf.ref_pts = AV_NOPTS_VALUE; st->codecpar->codec_type = type; @@ -605,8 +623,7 @@ static OutputStream *new_output_stream(Muxer *mux, const OptionsContext *o, if (ost->enc_ctx && av_get_exact_bits_per_sample(ost->enc_ctx->codec_id) == 24) av_dict_set(&ost->swr_opts, "output_sample_bits", "24", 0); - if (ist) { - ost->ist = ist; + if (ost->ist) { ost->ist->discard = 0; ost->ist->st->discard = ost->ist->user_set_discard; } From 01f58f36465a13db069641cca47fa9777f03b875 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Storsj=C3=B6?= Date: Mon, 16 Jan 2023 00:20:24 +0200 Subject: [PATCH 0135/2172] lavu/video_enc_params: Avoid relying on an undefined C construct MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The construct of using offsetof on a (potentially anonymous) struct defined within the offsetof expression, while supported by all current compilers, has been declared explicitly undefined by the C standards committee [1]. Clang recently got a change to identify this as an issue [2]; initially it was treated as a hard error, but it was soon after softened into a warning under the -Wgnu-offsetof-extensions option (not enabled automatically as part of -Wall though). Nevertheless - in this particular case, it's trivial to fix the code not to rely on the construct that the standards committee has explicitly called out as undefined. [1] https://www.open-std.org/jtc1/sc22/wg14/www/docs/n2350.htm [2] https://reviews.llvm.org/D133574 Signed-off-by: Martin Storsjö --- libavutil/video_enc_params.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/libavutil/video_enc_params.c b/libavutil/video_enc_params.c index 54bfed0ed97..33592dc1284 100644 --- a/libavutil/video_enc_params.c +++ b/libavutil/video_enc_params.c @@ -27,11 +27,11 @@ AVVideoEncParams *av_video_enc_params_alloc(enum AVVideoEncParamsType type, unsigned int nb_blocks, size_t *out_size) { - const size_t blocks_offset = offsetof( - struct { - AVVideoEncParams p; - AVVideoBlockParams b; - }, b); + struct TestStruct { + AVVideoEncParams p; + AVVideoBlockParams b; + }; + const size_t blocks_offset = offsetof(struct TestStruct, b); size_t size = blocks_offset; AVVideoEncParams *par; From 431f6260ac6408fdccfe06dd5276084b17c3557f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Storsj=C3=B6?= Date: Tue, 17 Jan 2023 10:56:54 +0200 Subject: [PATCH 0136/2172] mov: Reduce the verbosity of the warning about fragmented MP4 vs advanced edit lists MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Only warn if the advanced_editlist option is enabled (it is enabled by default though) so we don't print one warning for each track, and demote the warning to AV_LOG_LEVEL_VERBOSE; this message does get generated whenever parsing a fragmented MP4 file, regardless of whether the file actually uses multiple edits or not. Later when parsing the mov structures, the demuxer does warn if the file did contain multiple edits which would require the advanced_editlist option enabled for decoding correctly. Adjust the warning message for the case when the file seemed like it actually would have needed handling of advanced edit lists, to reflect the fact that it doesn't help to try set the option as it has been automatically disabled. Signed-off-by: Martin Storsjö --- libavformat/isom.h | 1 + libavformat/mov.c | 20 ++++++++++++++------ 2 files changed, 15 insertions(+), 6 deletions(-) diff --git a/libavformat/isom.h b/libavformat/isom.h index 64fb7065d59..5107b4eb748 100644 --- a/libavformat/isom.h +++ b/libavformat/isom.h @@ -286,6 +286,7 @@ typedef struct MOVContext { int use_absolute_path; int ignore_editlist; int advanced_editlist; + int advanced_editlist_autodisabled; int ignore_chapters; int seek_individually; int64_t next_root_atom; ///< offset of the next root atom diff --git a/libavformat/mov.c b/libavformat/mov.c index e0b7df28153..6ab43b00c6b 100644 --- a/libavformat/mov.c +++ b/libavformat/mov.c @@ -4063,10 +4063,15 @@ static void mov_build_index(MOVContext *mov, AVStream *st) } } - if (multiple_edits && !mov->advanced_editlist) - av_log(mov->fc, AV_LOG_WARNING, "multiple edit list entries, " - "Use -advanced_editlist to correctly decode otherwise " - "a/v desync might occur\n"); + if (multiple_edits && !mov->advanced_editlist) { + if (mov->advanced_editlist_autodisabled) + av_log(mov->fc, AV_LOG_WARNING, "multiple edit list entries, " + "not supported in fragmented MP4 files\n"); + else + av_log(mov->fc, AV_LOG_WARNING, "multiple edit list entries, " + "Use -advanced_editlist to correctly decode otherwise " + "a/v desync might occur\n"); + } /* adjust first dts according to edit list */ if ((empty_duration || start_time) && mov->time_scale > 0) { @@ -4507,10 +4512,13 @@ static int mov_read_trak(MOVContext *c, AVIOContext *pb, MOVAtom atom) * It cannot be used with use_mfra_for = {pts,dts} either, as the index * is not complete, but filled in as more trun atoms are read, as well. */ - if (!sc->stts_count || c->use_mfra_for != FF_MOV_FLAG_MFRA_AUTO) { - av_log(c->fc, AV_LOG_WARNING, "advanced_editlist does not work with fragmented " + if (!sc->stts_count || c->use_mfra_for != FF_MOV_FLAG_MFRA_AUTO && + c->advanced_editlist) { + + av_log(c->fc, AV_LOG_VERBOSE, "advanced_editlist does not work with fragmented " "MP4. disabling.\n"); c->advanced_editlist = 0; + c->advanced_editlist_autodisabled = 1; } mov_build_index(c, st); From 669ff26bc283c39334e7df3a81fd0db0088a7442 Mon Sep 17 00:00:00 2001 From: Cameron Gutman Date: Fri, 20 Jan 2023 19:20:30 -0600 Subject: [PATCH 0137/2172] avcodec/mfenc: fix double-free on init failure MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit mfenc sets FF_CODEC_CAP_INIT_CLEANUP, so calling mf_close() on failure inside mf_init() results in a double-free. Signed-off-by: Cameron Gutman Signed-off-by: Martin Storsjö --- libavcodec/mfenc.c | 1 - 1 file changed, 1 deletion(-) diff --git a/libavcodec/mfenc.c b/libavcodec/mfenc.c index 36a6d8482d1..f3415df10b0 100644 --- a/libavcodec/mfenc.c +++ b/libavcodec/mfenc.c @@ -1214,7 +1214,6 @@ static int mf_init(AVCodecContext *avctx) return 0; } } - mf_close(avctx); return ret; } From fb823161a8e3dfc864a7bd83a9b968f4912c5b1d Mon Sep 17 00:00:00 2001 From: Leo Izen Date: Fri, 27 Jan 2023 06:47:15 -0500 Subject: [PATCH 0138/2172] avcodec/libjxl: respect AVCodecContext->bits_per_raw_sample libjxl only accepts 16-bit buffers with its API, but it can accept 9-bit to 15-bit input via a 16-bit buffer, provided the flag is set declaring the buffer to be of the respective significant depth. Likewise, it can only provide pixel data on decode as a 16-bit buffer (if higher than 8) but does provide the metadata tagging the actual bit depth. This commit causes libjxlenc.c and libjxldec.c to respect this metadata and tag/read it accordingly from AVCodecContext->bits_per_raw_sample. Signed-off-by: Leo Izen --- libavcodec/libjxldec.c | 17 +++++++++++++---- libavcodec/libjxlenc.c | 10 +++++++++- 2 files changed, 22 insertions(+), 5 deletions(-) diff --git a/libavcodec/libjxldec.c b/libavcodec/libjxldec.c index c85cfa3d690..abe08eb4001 100644 --- a/libavcodec/libjxldec.c +++ b/libavcodec/libjxldec.c @@ -47,6 +47,7 @@ typedef struct LibJxlDecodeContext { JxlDecoder *decoder; JxlBasicInfo basic_info; JxlPixelFormat jxl_pixfmt; + JxlBitDepth jxl_bit_depth; JxlDecoderStatus events; AVBufferRef *iccp; } LibJxlDecodeContext; @@ -93,10 +94,14 @@ static av_cold int libjxl_decode_init(AVCodecContext *avctx) return libjxl_init_jxl_decoder(avctx); } -static enum AVPixelFormat libjxl_get_pix_fmt(void *avctx, const JxlBasicInfo *basic_info, JxlPixelFormat *format) +static enum AVPixelFormat libjxl_get_pix_fmt(AVCodecContext *avctx, const JxlBasicInfo *basic_info, + JxlPixelFormat *format, JxlBitDepth *depth) { format->endianness = JXL_NATIVE_ENDIAN; format->num_channels = basic_info->num_color_channels + (basic_info->alpha_bits > 0); + depth->bits_per_sample = avctx->bits_per_raw_sample = basic_info->bits_per_sample; + depth->type = JXL_BIT_DEPTH_FROM_PIXEL_FORMAT; + depth->exponent_bits_per_sample = basic_info->exponent_bits_per_sample; /* Gray */ if (basic_info->num_color_channels == 1) { if (basic_info->bits_per_sample <= 8) { @@ -119,10 +124,10 @@ static enum AVPixelFormat libjxl_get_pix_fmt(void *avctx, const JxlBasicInfo *ba format->data_type = JXL_TYPE_UINT8; return basic_info->alpha_bits ? AV_PIX_FMT_RGBA : AV_PIX_FMT_RGB24; } - if (basic_info->bits_per_sample > 16) - av_log(avctx, AV_LOG_WARNING, "Downsampling larger integer to 16-bit via libjxl\n"); if (basic_info->exponent_bits_per_sample) av_log(avctx, AV_LOG_WARNING, "Downsampling float to 16-bit integer via libjxl\n"); + else if (basic_info->bits_per_sample > 16) + av_log(avctx, AV_LOG_WARNING, "Downsampling larger integer to 16-bit via libjxl\n"); format->data_type = JXL_TYPE_UINT16; return basic_info->alpha_bits ? AV_PIX_FMT_RGBA64 : AV_PIX_FMT_RGB48; } @@ -367,7 +372,7 @@ static int libjxl_decode_frame(AVCodecContext *avctx, AVFrame *frame, int *got_f av_log(avctx, AV_LOG_ERROR, "Bad libjxl basic info event\n"); return AVERROR_EXTERNAL; } - avctx->pix_fmt = libjxl_get_pix_fmt(avctx, &ctx->basic_info, &ctx->jxl_pixfmt); + avctx->pix_fmt = libjxl_get_pix_fmt(avctx, &ctx->basic_info, &ctx->jxl_pixfmt, &ctx->jxl_bit_depth); if (avctx->pix_fmt == AV_PIX_FMT_NONE) { av_log(avctx, AV_LOG_ERROR, "Bad libjxl pixel format\n"); return AVERROR_EXTERNAL; @@ -390,6 +395,10 @@ static int libjxl_decode_frame(AVCodecContext *avctx, AVFrame *frame, int *got_f av_log(avctx, AV_LOG_ERROR, "Bad libjxl dec need image out buffer event\n"); return AVERROR_EXTERNAL; } + if (JxlDecoderSetImageOutBitDepth(ctx->decoder, &ctx->jxl_bit_depth) != JXL_DEC_SUCCESS) { + av_log(avctx, AV_LOG_ERROR, "Error setting output bit depth\n"); + return AVERROR_EXTERNAL; + } continue; case JXL_DEC_FULL_IMAGE: /* full image is one frame, even if animated */ diff --git a/libavcodec/libjxlenc.c b/libavcodec/libjxlenc.c index 06581b268d2..c51024f1806 100644 --- a/libavcodec/libjxlenc.c +++ b/libavcodec/libjxlenc.c @@ -250,6 +250,7 @@ static int libjxl_encode_frame(AVCodecContext *avctx, AVPacket *pkt, const AVFra JxlBasicInfo info; JxlColorEncoding jxl_color; JxlPixelFormat jxl_fmt; + JxlBitDepth jxl_bit_depth; JxlEncoderStatus jret; int ret; size_t available = ctx->buffer_size; @@ -269,17 +270,22 @@ static int libjxl_encode_frame(AVCodecContext *avctx, AVPacket *pkt, const AVFra info.ysize = frame->height; info.num_extra_channels = (jxl_fmt.num_channels + 1) % 2; info.num_color_channels = jxl_fmt.num_channels - info.num_extra_channels; - info.bits_per_sample = av_get_bits_per_pixel(pix_desc) / jxl_fmt.num_channels; + jxl_bit_depth.bits_per_sample = av_get_bits_per_pixel(pix_desc) / jxl_fmt.num_channels; + info.bits_per_sample = avctx->bits_per_raw_sample > 0 && !(pix_desc->flags & AV_PIX_FMT_FLAG_FLOAT) + ? avctx->bits_per_raw_sample : jxl_bit_depth.bits_per_sample; info.alpha_bits = (info.num_extra_channels > 0) * info.bits_per_sample; if (pix_desc->flags & AV_PIX_FMT_FLAG_FLOAT) { info.exponent_bits_per_sample = info.bits_per_sample > 16 ? 8 : 5; info.alpha_exponent_bits = info.alpha_bits ? info.exponent_bits_per_sample : 0; jxl_fmt.data_type = info.bits_per_sample > 16 ? JXL_TYPE_FLOAT : JXL_TYPE_FLOAT16; + jxl_bit_depth.exponent_bits_per_sample = info.exponent_bits_per_sample; } else { info.exponent_bits_per_sample = 0; info.alpha_exponent_bits = 0; jxl_fmt.data_type = info.bits_per_sample <= 8 ? JXL_TYPE_UINT8 : JXL_TYPE_UINT16; + jxl_bit_depth.exponent_bits_per_sample = 0; } + jxl_bit_depth.type = JXL_BIT_DEPTH_FROM_PIXEL_FORMAT; /* JPEG XL format itself does not support limited range */ if (avctx->color_range == AVCOL_RANGE_MPEG || @@ -356,6 +362,8 @@ static int libjxl_encode_frame(AVCodecContext *avctx, AVPacket *pkt, const AVFra av_log(avctx, AV_LOG_WARNING, "Could not set ICC Profile\n"); if (JxlEncoderSetColorEncoding(ctx->encoder, &jxl_color) != JXL_ENC_SUCCESS) av_log(avctx, AV_LOG_WARNING, "Failed to set JxlColorEncoding\n"); + if (JxlEncoderSetFrameBitDepth(ctx->options, &jxl_bit_depth) != JXL_ENC_SUCCESS) + av_log(avctx, AV_LOG_WARNING, "Failed to set JxlBitDepth\n"); /* depending on basic info, level 10 might * be required instead of level 5 */ From 00994e8be185d259fbb8346f45f09bcea4e7f750 Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Tue, 31 Jan 2023 10:18:17 +0100 Subject: [PATCH 0139/2172] avcodec: add media100_to_mjpegb bitstream filter and use it --- Changelog | 1 + configure | 1 + libavcodec/Makefile | 3 +- libavcodec/bitstream_filters.c | 1 + libavcodec/media100.c | 224 ---------------------------- libavcodec/media100_to_mjpegb_bsf.c | 168 +++++++++++++++++++++ libavcodec/mjpegbdec.c | 15 ++ libavcodec/version.h | 2 +- 8 files changed, 189 insertions(+), 226 deletions(-) delete mode 100644 libavcodec/media100.c create mode 100644 libavcodec/media100_to_mjpegb_bsf.c diff --git a/Changelog b/Changelog index aa0dad13a17..c3ca10a3bb2 100644 --- a/Changelog +++ b/Changelog @@ -35,6 +35,7 @@ version : - ffmpeg CLI new options: -enc_stats_pre[_fmt], -enc_stats_post[_fmt] - hstack_vaapi, vstack_vaapi and xstack_vaapi filters - XMD ADPCM decoder and demuxer +- media100 to mjpegb bsf version 5.1: diff --git a/configure b/configure index 47790d10f57..9d78a244a3a 100755 --- a/configure +++ b/configure @@ -2850,6 +2850,7 @@ lscr_decoder_select="inflate_wrapper" magicyuv_decoder_select="llviddsp" magicyuv_encoder_select="llvidencdsp" mdec_decoder_select="blockdsp bswapdsp idctdsp" +media100_decoder_select="media100_to_mjpegb_bsf mjpegb_decoder" metasound_decoder_select="lsp sinewin" mimic_decoder_select="blockdsp bswapdsp hpeldsp idctdsp" mjpeg_decoder_select="blockdsp hpeldsp exif idctdsp jpegtables" diff --git a/libavcodec/Makefile b/libavcodec/Makefile index 304c2bc2e3a..1fb963f8208 100644 --- a/libavcodec/Makefile +++ b/libavcodec/Makefile @@ -485,7 +485,7 @@ OBJS-$(CONFIG_MACE6_DECODER) += mace.o OBJS-$(CONFIG_MAGICYUV_DECODER) += magicyuv.o OBJS-$(CONFIG_MAGICYUV_ENCODER) += magicyuvenc.o OBJS-$(CONFIG_MDEC_DECODER) += mdec.o mpeg12.o mpeg12data.o -OBJS-$(CONFIG_MEDIA100_DECODER) += media100.o +OBJS-$(CONFIG_MEDIA100_DECODER) += mjpegbdec.o OBJS-$(CONFIG_METASOUND_DECODER) += metasound.o twinvq.o OBJS-$(CONFIG_MICRODVD_DECODER) += microdvddec.o ass.o OBJS-$(CONFIG_MIMIC_DECODER) += mimic.o @@ -1220,6 +1220,7 @@ OBJS-$(CONFIG_HEVC_METADATA_BSF) += h265_metadata_bsf.o h265_profile_le h2645data.o OBJS-$(CONFIG_HEVC_MP4TOANNEXB_BSF) += hevc_mp4toannexb_bsf.o OBJS-$(CONFIG_IMX_DUMP_HEADER_BSF) += imx_dump_header_bsf.o +OBJS-$(CONFIG_MEDIA100_TO_MJPEGB_BSF) += media100_to_mjpegb_bsf.o OBJS-$(CONFIG_MJPEG2JPEG_BSF) += mjpeg2jpeg_bsf.o OBJS-$(CONFIG_MJPEGA_DUMP_HEADER_BSF) += mjpega_dump_header_bsf.o OBJS-$(CONFIG_MPEG4_UNPACK_BFRAMES_BSF) += mpeg4_unpack_bframes_bsf.o diff --git a/libavcodec/bitstream_filters.c b/libavcodec/bitstream_filters.c index a3bebefe5f9..e8216819cae 100644 --- a/libavcodec/bitstream_filters.c +++ b/libavcodec/bitstream_filters.c @@ -43,6 +43,7 @@ extern const FFBitStreamFilter ff_hapqa_extract_bsf; extern const FFBitStreamFilter ff_hevc_metadata_bsf; extern const FFBitStreamFilter ff_hevc_mp4toannexb_bsf; extern const FFBitStreamFilter ff_imx_dump_header_bsf; +extern const FFBitStreamFilter ff_media100_to_mjpegb_bsf; extern const FFBitStreamFilter ff_mjpeg2jpeg_bsf; extern const FFBitStreamFilter ff_mjpega_dump_header_bsf; extern const FFBitStreamFilter ff_mp3_header_decompress_bsf; diff --git a/libavcodec/media100.c b/libavcodec/media100.c deleted file mode 100644 index fdfce2cac1b..00000000000 --- a/libavcodec/media100.c +++ /dev/null @@ -1,224 +0,0 @@ -/* - * Media 100 decoder - * Copyright (c) 2022 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 - */ - -/** - * @file - * Media 100 decoder. - */ - -#include - -#include "libavutil/intreadwrite.h" -#include "avcodec.h" -#include "bytestream.h" -#include "codec_internal.h" - -typedef struct Media100Context { - AVCodecContext *avctx; // wrapper context for mjpegb - AVPacket *pkt; -} Media100Context; - -static av_cold int media100_decode_init(AVCodecContext *avctx) -{ - Media100Context *ctx = avctx->priv_data; - const AVCodec *codec; - int ret; - - codec = avcodec_find_decoder(AV_CODEC_ID_MJPEGB); - if (!codec) - return AVERROR_BUG; - ctx->avctx = avcodec_alloc_context3(codec); - if (!ctx->avctx) - return AVERROR(ENOMEM); - ctx->avctx->thread_count = 1; - ctx->avctx->flags = avctx->flags; - ctx->avctx->flags2 = avctx->flags2; - ctx->avctx->width = ctx->avctx->coded_width = avctx->width; - ctx->avctx->height = ctx->avctx->coded_height = avctx->height; - - ret = avcodec_open2(ctx->avctx, codec, NULL); - if (ret < 0) - return ret; - - ctx->pkt = av_packet_alloc(); - if (!ctx->pkt) - return AVERROR(ENOMEM); - - return 0; -} - -static int media100_decode_frame(AVCodecContext *avctx, - AVFrame *frame, int *got_frame, - AVPacket *avpkt) -{ - Media100Context *ctx = avctx->priv_data; - unsigned second_field_offset = 0; - unsigned next_field = 0; - unsigned dht_offset[2]; - unsigned dqt_offset[2]; - unsigned sod_offset[2]; - unsigned sof_offset[2]; - unsigned sos_offset[2]; - unsigned field = 0; - GetByteContext gb; - PutByteContext pb; - AVPacket *pkt; - int ret; - - if (avpkt->size + 1024 > ctx->pkt->size) { - ret = av_grow_packet(ctx->pkt, avpkt->size + 1024 - ctx->pkt->size); - if (ret < 0) - return ret; - } - - ret = av_packet_make_writable(ctx->pkt); - if (ret < 0) - return ret; - - bytestream2_init(&gb, avpkt->data, avpkt->size); - bytestream2_init_writer(&pb, ctx->pkt->data, ctx->pkt->size); - -second_field: - bytestream2_put_be32(&pb, 0); - bytestream2_put_be32(&pb, AV_RB32("mjpg")); - bytestream2_put_be32(&pb, 0); - bytestream2_put_be32(&pb, 0); - for (int i = 0; i < 6; i++) - bytestream2_put_be32(&pb, 0); - - sof_offset[field] = bytestream2_tell_p(&pb); - bytestream2_put_be16(&pb, 17); - bytestream2_put_byte(&pb, 8); - bytestream2_put_be16(&pb, avctx->height / 2); - bytestream2_put_be16(&pb, avctx->width); - bytestream2_put_byte(&pb, 3); - bytestream2_put_byte(&pb, 1); - bytestream2_put_byte(&pb, 0x21); - bytestream2_put_byte(&pb, 0); - bytestream2_put_byte(&pb, 2); - bytestream2_put_byte(&pb, 0x11); - bytestream2_put_byte(&pb, 1); - bytestream2_put_byte(&pb, 3); - bytestream2_put_byte(&pb, 0x11); - bytestream2_put_byte(&pb, 1); - - sos_offset[field] = bytestream2_tell_p(&pb); - bytestream2_put_be16(&pb, 12); - bytestream2_put_byte(&pb, 3); - bytestream2_put_byte(&pb, 1); - bytestream2_put_byte(&pb, 0); - bytestream2_put_byte(&pb, 2); - bytestream2_put_byte(&pb, 0x11); - bytestream2_put_byte(&pb, 3); - bytestream2_put_byte(&pb, 0x11); - bytestream2_put_byte(&pb, 0); - bytestream2_put_byte(&pb, 0); - bytestream2_put_byte(&pb, 0); - - dqt_offset[field] = bytestream2_tell_p(&pb); - bytestream2_put_be16(&pb, 132); - bytestream2_put_byte(&pb, 0); - bytestream2_skip(&gb, 4); - for (int i = 0; i < 64; i++) - bytestream2_put_byte(&pb, bytestream2_get_be32(&gb)); - bytestream2_put_byte(&pb, 1); - for (int i = 0; i < 64; i++) - bytestream2_put_byte(&pb, bytestream2_get_be32(&gb)); - - dht_offset[field] = 0; - sod_offset[field] = bytestream2_tell_p(&pb); - - for (int i = bytestream2_tell(&gb) + 8; next_field == 0 && i < avpkt->size - 4; i++) { - if (AV_RB32(avpkt->data + i) == 0x00000001) { - next_field = i; - break; - } - } - - bytestream2_skip(&gb, 8); - bytestream2_copy_buffer(&pb, &gb, next_field - bytestream2_tell(&gb)); - bytestream2_put_be64(&pb, 0); - - if (field == 0) { - field = 1; - second_field_offset = bytestream2_tell_p(&pb); - next_field = avpkt->size; - goto second_field; - } - - pkt = ctx->pkt; - - AV_WB32(pkt->data + 8, second_field_offset); - AV_WB32(pkt->data + 12, second_field_offset); - AV_WB32(pkt->data + 16, second_field_offset); - AV_WB32(pkt->data + 20, dqt_offset[0]); - AV_WB32(pkt->data + 24, dht_offset[0]); - AV_WB32(pkt->data + 28, sof_offset[0]); - AV_WB32(pkt->data + 32, sos_offset[0]); - AV_WB32(pkt->data + 36, sod_offset[0]); - - AV_WB32(pkt->data + second_field_offset + 8, bytestream2_tell_p(&pb) - second_field_offset); - AV_WB32(pkt->data + second_field_offset + 12, bytestream2_tell_p(&pb) - second_field_offset); - AV_WB32(pkt->data + second_field_offset + 16, 0); - AV_WB32(pkt->data + second_field_offset + 20, dqt_offset[1] - second_field_offset); - AV_WB32(pkt->data + second_field_offset + 24, dht_offset[1]); - AV_WB32(pkt->data + second_field_offset + 28, sof_offset[1] - second_field_offset); - AV_WB32(pkt->data + second_field_offset + 32, sos_offset[1] - second_field_offset); - AV_WB32(pkt->data + second_field_offset + 36, sod_offset[1] - second_field_offset); - - pkt->size = bytestream2_tell_p(&pb); - - ret = avcodec_send_packet(ctx->avctx, pkt); - if (ret < 0) { - av_log(avctx, AV_LOG_ERROR, "Error submitting a packet for decoding\n"); - return ret; - } - - ret = avcodec_receive_frame(ctx->avctx, frame); - if (ret < 0) - return ret; - - *got_frame = 1; - - return avpkt->size; -} - -static av_cold int media100_decode_end(AVCodecContext *avctx) -{ - Media100Context *ctx = avctx->priv_data; - - avcodec_free_context(&ctx->avctx); - av_packet_free(&ctx->pkt); - - return 0; -} - -const FFCodec ff_media100_decoder = { - .p.name = "media100", - CODEC_LONG_NAME("Media 100"), - .p.type = AVMEDIA_TYPE_VIDEO, - .p.id = AV_CODEC_ID_MEDIA100, - .priv_data_size = sizeof(Media100Context), - .init = media100_decode_init, - .close = media100_decode_end, - FF_CODEC_DECODE_CB(media100_decode_frame), - .caps_internal = FF_CODEC_CAP_INIT_CLEANUP, -}; diff --git a/libavcodec/media100_to_mjpegb_bsf.c b/libavcodec/media100_to_mjpegb_bsf.c new file mode 100644 index 00000000000..6e117ae20fb --- /dev/null +++ b/libavcodec/media100_to_mjpegb_bsf.c @@ -0,0 +1,168 @@ +/* + * Media 100 to MJPEGB bitstream filter + * Copyright (c) 2023 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 + */ + +/** + * @file + * Media 100 to MJPEGB bitstream filter. + */ + +#include "libavutil/intreadwrite.h" +#include "bsf.h" +#include "bsf_internal.h" +#include "bytestream.h" + +static av_cold int init(AVBSFContext *ctx) +{ + ctx->par_out->codec_id = AV_CODEC_ID_MJPEGB; + return 0; +} + +static int filter(AVBSFContext *ctx, AVPacket *out) +{ + unsigned second_field_offset = 0; + unsigned next_field = 0; + unsigned dht_offset[2]; + unsigned dqt_offset[2]; + unsigned sod_offset[2]; + unsigned sof_offset[2]; + unsigned sos_offset[2]; + unsigned field = 0; + GetByteContext gb; + PutByteContext pb; + AVPacket *in; + int ret; + + ret = ff_bsf_get_packet(ctx, &in); + if (ret < 0) + return ret; + + ret = av_new_packet(out, in->size + 1024); + if (ret < 0) + goto fail; + + bytestream2_init(&gb, in->data, in->size); + bytestream2_init_writer(&pb, out->data, out->size); + +second_field: + bytestream2_put_be32(&pb, 0); + bytestream2_put_be32(&pb, AV_RB32("mjpg")); + bytestream2_put_be32(&pb, 0); + bytestream2_put_be32(&pb, 0); + for (int i = 0; i < 6; i++) + bytestream2_put_be32(&pb, 0); + + sof_offset[field] = bytestream2_tell_p(&pb); + bytestream2_put_be16(&pb, 17); + bytestream2_put_byte(&pb, 8); + bytestream2_put_be16(&pb, ctx->par_in->height / 2); + bytestream2_put_be16(&pb, ctx->par_in->width); + bytestream2_put_byte(&pb, 3); + bytestream2_put_byte(&pb, 1); + bytestream2_put_byte(&pb, 0x21); + bytestream2_put_byte(&pb, 0); + bytestream2_put_byte(&pb, 2); + bytestream2_put_byte(&pb, 0x11); + bytestream2_put_byte(&pb, 1); + bytestream2_put_byte(&pb, 3); + bytestream2_put_byte(&pb, 0x11); + bytestream2_put_byte(&pb, 1); + + sos_offset[field] = bytestream2_tell_p(&pb); + bytestream2_put_be16(&pb, 12); + bytestream2_put_byte(&pb, 3); + bytestream2_put_byte(&pb, 1); + bytestream2_put_byte(&pb, 0); + bytestream2_put_byte(&pb, 2); + bytestream2_put_byte(&pb, 0x11); + bytestream2_put_byte(&pb, 3); + bytestream2_put_byte(&pb, 0x11); + bytestream2_put_byte(&pb, 0); + bytestream2_put_byte(&pb, 0); + bytestream2_put_byte(&pb, 0); + + dqt_offset[field] = bytestream2_tell_p(&pb); + bytestream2_put_be16(&pb, 132); + bytestream2_put_byte(&pb, 0); + bytestream2_skip(&gb, 4); + for (int i = 0; i < 64; i++) + bytestream2_put_byte(&pb, bytestream2_get_be32(&gb)); + bytestream2_put_byte(&pb, 1); + for (int i = 0; i < 64; i++) + bytestream2_put_byte(&pb, bytestream2_get_be32(&gb)); + + dht_offset[field] = 0; + sod_offset[field] = bytestream2_tell_p(&pb); + + for (int i = bytestream2_tell(&gb) + 8; next_field == 0 && i < in->size - 4; i++) { + if (AV_RB32(in->data + i) == 0x00000001) { + next_field = i; + break; + } + } + + bytestream2_skip(&gb, 8); + bytestream2_copy_buffer(&pb, &gb, next_field - bytestream2_tell(&gb)); + bytestream2_put_be64(&pb, 0); + + if (field == 0) { + field = 1; + second_field_offset = bytestream2_tell_p(&pb); + next_field = in->size; + goto second_field; + } + + AV_WB32(out->data + 8, second_field_offset); + AV_WB32(out->data + 12, second_field_offset); + AV_WB32(out->data + 16, second_field_offset); + AV_WB32(out->data + 20, dqt_offset[0]); + AV_WB32(out->data + 24, dht_offset[0]); + AV_WB32(out->data + 28, sof_offset[0]); + AV_WB32(out->data + 32, sos_offset[0]); + AV_WB32(out->data + 36, sod_offset[0]); + + AV_WB32(out->data + second_field_offset + 8, bytestream2_tell_p(&pb) - second_field_offset); + AV_WB32(out->data + second_field_offset + 12, bytestream2_tell_p(&pb) - second_field_offset); + AV_WB32(out->data + second_field_offset + 16, 0); + AV_WB32(out->data + second_field_offset + 20, dqt_offset[1] - second_field_offset); + AV_WB32(out->data + second_field_offset + 24, dht_offset[1]); + AV_WB32(out->data + second_field_offset + 28, sof_offset[1] - second_field_offset); + AV_WB32(out->data + second_field_offset + 32, sos_offset[1] - second_field_offset); + AV_WB32(out->data + second_field_offset + 36, sod_offset[1] - second_field_offset); + + out->size = bytestream2_tell_p(&pb); + + ret = av_packet_copy_props(out, in); + if (ret < 0) + goto fail; + +fail: + if (ret < 0) + av_packet_unref(out); + av_packet_free(&in); + return ret; +} + +const FFBitStreamFilter ff_media100_to_mjpegb_bsf = { + .p.name = "media100_to_mjpegb", + .p.codec_ids = (const enum AVCodecID []){ AV_CODEC_ID_MEDIA100, AV_CODEC_ID_NONE }, + .init = init, + .filter = filter, +}; diff --git a/libavcodec/mjpegbdec.c b/libavcodec/mjpegbdec.c index 6d422e7a29d..4db1d9a89d7 100644 --- a/libavcodec/mjpegbdec.c +++ b/libavcodec/mjpegbdec.c @@ -168,3 +168,18 @@ const FFCodec ff_mjpegb_decoder = { .p.max_lowres = 3, .caps_internal = FF_CODEC_CAP_INIT_CLEANUP, }; + +const FFCodec ff_media100_decoder = { + .p.name = "media100", + CODEC_LONG_NAME("Media 100"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_MEDIA100, + .priv_data_size = sizeof(MJpegDecodeContext), + .init = ff_mjpeg_decode_init, + .close = ff_mjpeg_decode_end, + FF_CODEC_DECODE_CB(mjpegb_decode_frame), + .p.capabilities = AV_CODEC_CAP_DR1, + .p.max_lowres = 3, + .caps_internal = FF_CODEC_CAP_INIT_CLEANUP, + .bsfs = "media100_to_mjpegb", +}; diff --git a/libavcodec/version.h b/libavcodec/version.h index 2ed4ef5547f..499c6bb175b 100644 --- a/libavcodec/version.h +++ b/libavcodec/version.h @@ -29,7 +29,7 @@ #include "version_major.h" -#define LIBAVCODEC_VERSION_MINOR 60 +#define LIBAVCODEC_VERSION_MINOR 61 #define LIBAVCODEC_VERSION_MICRO 100 #define LIBAVCODEC_VERSION_INT AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \ From fc9a3b584da3cf3fc1f00036be2eaf5dff903ccf Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Mon, 30 Jan 2023 19:35:36 +0100 Subject: [PATCH 0140/2172] avcodec/mlpdec: parse and use substream info bits --- libavcodec/mlp_parse.c | 6 +++++- libavcodec/mlp_parse.h | 3 +++ libavcodec/mlpdec.c | 15 ++++++++++++++- 3 files changed, 22 insertions(+), 2 deletions(-) diff --git a/libavcodec/mlp_parse.c b/libavcodec/mlp_parse.c index 45715352c28..924c731439d 100644 --- a/libavcodec/mlp_parse.c +++ b/libavcodec/mlp_parse.c @@ -159,7 +159,11 @@ int ff_mlp_read_major_sync(void *log, MLPHeaderInfo *mh, GetBitContext *gb) mh->num_substreams = get_bits(gb, 4); - skip_bits_long(gb, 4 + (header_size - 17) * 8); + skip_bits(gb, 2); + mh->extended_substream_info = get_bits(gb, 2); + mh->substream_info = get_bits(gb, 8); + + skip_bits_long(gb, (header_size - 18) * 8); return 0; } diff --git a/libavcodec/mlp_parse.h b/libavcodec/mlp_parse.h index f0d7b41c119..fa6e3d52dcc 100644 --- a/libavcodec/mlp_parse.h +++ b/libavcodec/mlp_parse.h @@ -58,6 +58,9 @@ typedef struct MLPHeaderInfo int peak_bitrate; ///< Peak bitrate for VBR, actual bitrate (==peak) for CBR int num_substreams; ///< Number of substreams within stream + + int extended_substream_info; ///< Which substream of substreams carry 16-channel presentation + int substream_info; ///< Which substream of substreams carry 2/6/8-channel presentation } MLPHeaderInfo; static const uint8_t thd_chancount[13] = { diff --git a/libavcodec/mlpdec.c b/libavcodec/mlpdec.c index 5b14a3b03ba..0ee1f0982c6 100644 --- a/libavcodec/mlpdec.c +++ b/libavcodec/mlpdec.c @@ -153,6 +153,12 @@ typedef struct MLPDecodeContext { /// Number of substreams contained within this stream. uint8_t num_substreams; + /// Which substream of substreams carry 16-channel presentation + uint8_t extended_substream_info; + + /// Which substream of substreams carry 2/6/8-channel presentation + uint8_t substream_info; + /// Index of the last substream to decode - further substreams are skipped. uint8_t max_decoded_substream; @@ -384,6 +390,7 @@ static int read_major_sync(MLPDecodeContext *m, GetBitContext *gb) m->access_unit_size_pow2 = mh.access_unit_size_pow2; m->num_substreams = mh.num_substreams; + m->substream_info = mh.substream_info; /* limit to decoding 3 substreams, as the 4th is used by Dolby Atmos for non-audio data */ m->max_decoded_substream = FFMIN(m->num_substreams - 1, 2); @@ -1286,7 +1293,13 @@ static int read_access_unit(AVCodecContext *avctx, AVFrame *frame, if (!s->restart_seen) goto next_substr; - if (substr > 0 && substr < m->max_decoded_substream && + if (((avctx->ch_layout.nb_channels == 6 && + ((m->substream_info >> 2) & 0x3) != 0x3) || + (avctx->ch_layout.nb_channels == 8 && + ((m->substream_info >> 4) & 0x7) != 0x7 && + ((m->substream_info >> 4) & 0x7) != 0x6 && + ((m->substream_info >> 4) & 0x7) != 0x3)) && + substr > 0 && substr < m->max_decoded_substream && (s->min_channel <= m->substream[substr - 1].max_channel)) { av_log(avctx, AV_LOG_DEBUG, "Previous substream(%d) channels overlaps current substream(%d) channels, skipping.\n", From bbe95f7353a972f28a48be8da883549f02c59e4b Mon Sep 17 00:00:00 2001 From: Lynne Date: Wed, 1 Feb 2023 02:26:20 +0100 Subject: [PATCH 0141/2172] x86: replace explicit REP_RETs with RETs From x86inc: > On AMD cpus <=K10, an ordinary ret is slow if it immediately follows either > a branch or a branch target. So switch to a 2-byte form of ret in that case. > We can automatically detect "follows a branch", but not a branch target. > (SSSE3 is a sufficient condition to know that your cpu doesn't have this problem.) x86inc can automatically determine whether to use REP_RET rather than REP in most of these cases, so impact is minimal. Additionally, a few REP_RETs were used unnecessary, despite the return being nowhere near a branch. The only CPUs affected were AMD K10s, made between 2007 and 2011, 16 years ago and 12 years ago, respectively. In the future, everyone involved with x86inc should consider dropping REP_RETs altogether. --- libavcodec/x86/aacpsdsp.asm | 10 ++++----- libavcodec/x86/ac3dsp.asm | 6 +++--- libavcodec/x86/alacdsp.asm | 4 ++-- libavcodec/x86/audiodsp.asm | 2 +- libavcodec/x86/dirac_dwt.asm | 14 ++++++------- libavcodec/x86/fft.asm | 8 +++---- libavcodec/x86/flacdsp.asm | 8 +++---- libavcodec/x86/h264_chromamc.asm | 18 ++++++++-------- libavcodec/x86/h264_chromamc_10bit.asm | 10 ++++----- libavcodec/x86/h264_deblock_10bit.asm | 6 +++--- libavcodec/x86/h264_idct.asm | 10 ++++----- libavcodec/x86/h264_idct_10bit.asm | 8 +++---- libavcodec/x86/h264_intrapred.asm | 24 ++++++++++----------- libavcodec/x86/h264_intrapred_10bit.asm | 16 +++++++------- libavcodec/x86/h264_qpel_10bit.asm | 2 +- libavcodec/x86/h264_qpel_8bit.asm | 26 +++++++++++------------ libavcodec/x86/h264_weight.asm | 12 +++++------ libavcodec/x86/h264_weight_10bit.asm | 12 +++++------ libavcodec/x86/hevc_sao.asm | 2 +- libavcodec/x86/hevc_sao_10bit.asm | 2 +- libavcodec/x86/hpeldsp.asm | 20 +++++++++--------- libavcodec/x86/hpeldsp_vp3.asm | 4 ++-- libavcodec/x86/huffyuvdsp.asm | 2 +- libavcodec/x86/jpeg2000dsp.asm | 4 ++-- libavcodec/x86/lossless_videodsp.asm | 2 +- libavcodec/x86/lossless_videoencdsp.asm | 2 +- libavcodec/x86/me_cmp.asm | 2 +- libavcodec/x86/pngdsp.asm | 2 +- libavcodec/x86/qpel.asm | 6 +++--- libavcodec/x86/qpeldsp.asm | 12 +++++------ libavcodec/x86/rv34dsp.asm | 2 +- libavcodec/x86/rv40dsp.asm | 10 ++++----- libavcodec/x86/sbrdsp.asm | 12 +++++------ libavcodec/x86/takdsp.asm | 8 +++---- libavcodec/x86/utvideodsp.asm | 4 ++-- libavcodec/x86/v210.asm | 2 +- libavcodec/x86/vc1dsp_mc.asm | 2 +- libavcodec/x86/videodsp.asm | 2 +- libavcodec/x86/vp8dsp.asm | 28 ++++++++++++------------- libavfilter/x86/af_volume.asm | 6 +++--- libavfilter/x86/avf_showcqt.asm | 4 ++-- libavfilter/x86/scene_sad.asm | 2 +- libavfilter/x86/vf_blend.asm | 2 +- libavfilter/x86/vf_framerate.asm | 2 +- libavfilter/x86/vf_gradfun.asm | 6 +++--- libavfilter/x86/vf_hqdn3d.asm | 2 +- libavfilter/x86/vf_interlace.asm | 6 +++--- libavfilter/x86/vf_maskedmerge.asm | 2 +- libavfilter/x86/vf_stereo3d.asm | 2 +- libavfilter/x86/vf_w3fdif.asm | 10 ++++----- libavutil/x86/float_dsp.asm | 18 ++++++++-------- libavutil/x86/lls.asm | 4 ++-- libswresample/x86/audio_convert.asm | 12 +++++------ libswresample/x86/rematrix.asm | 8 +++---- libswscale/x86/input.asm | 14 ++++++------- libswscale/x86/output.asm | 10 ++++----- libswscale/x86/scale.asm | 2 +- libswscale/x86/scale_avx2.asm | 2 +- libswscale/x86/yuv2yuvX.asm | 2 +- libswscale/x86/yuv_2_rgb.asm | 2 +- tests/checkasm/x86/checkasm.asm | 2 +- 61 files changed, 223 insertions(+), 223 deletions(-) diff --git a/libavcodec/x86/aacpsdsp.asm b/libavcodec/x86/aacpsdsp.asm index 105e1af5c56..cc496d4df86 100644 --- a/libavcodec/x86/aacpsdsp.asm +++ b/libavcodec/x86/aacpsdsp.asm @@ -49,7 +49,7 @@ align 16 add dstq, mmsize add nq, mmsize*2 jl .loop - REP_RET + RET %endmacro INIT_XMM sse @@ -83,7 +83,7 @@ align 16 add src2q, mmsize add nq, mmsize*2 jl .loop - REP_RET + RET ;*********************************************************************** ;void ff_ps_stereo_interpolate_sse3(float (*l)[2], float (*r)[2], @@ -116,7 +116,7 @@ align 16 movhps [rq+nq], m2 add nq, 8 jl .loop - REP_RET + RET ;*************************************************************************** ;void ps_stereo_interpolate_ipdopd_sse3(float (*l)[2], float (*r)[2], @@ -164,7 +164,7 @@ align 16 movhps [rq+nq], m2 add nq, 8 jl .loop - REP_RET + RET ;********************************************************** ;void ps_hybrid_analysis_ileave_sse(float out[2][38][64], @@ -484,7 +484,7 @@ align 16 add outq, strideq add nq, 64 jl .loop - REP_RET + RET %endmacro INIT_XMM sse diff --git a/libavcodec/x86/ac3dsp.asm b/libavcodec/x86/ac3dsp.asm index c11a94ca931..a95d359d952 100644 --- a/libavcodec/x86/ac3dsp.asm +++ b/libavcodec/x86/ac3dsp.asm @@ -60,7 +60,7 @@ cglobal ac3_exponent_min, 3, 4, 2, exp, reuse_blks, expn, offset sub expnq, mmsize jg .nextexp .end: - REP_RET + RET %endmacro %define LOOP_ALIGN ALIGN 16 @@ -126,7 +126,7 @@ cglobal float_to_fixed24, 3, 3, 9, dst, src, len sub lenq, 16 %endif ja .loop - REP_RET + RET ;------------------------------------------------------------------------------ ; int ff_ac3_compute_mantissa_size(uint16_t mant_cnt[6][16]) @@ -220,7 +220,7 @@ cglobal ac3_extract_exponents, 3, 3, 4, exp, coef, len add lenq, 4 jl .loop - REP_RET + RET %endmacro %if HAVE_SSE2_EXTERNAL diff --git a/libavcodec/x86/alacdsp.asm b/libavcodec/x86/alacdsp.asm index bb2069f7858..1cfd302de2a 100644 --- a/libavcodec/x86/alacdsp.asm +++ b/libavcodec/x86/alacdsp.asm @@ -100,7 +100,7 @@ align 16 add lenq, mmsize*2 jl .loop - REP_RET + RET %if ARCH_X86_64 cglobal alac_append_extra_bits_mono, 2, 5, 3, buf, exbuf, exbits, ch, len @@ -130,4 +130,4 @@ align 16 add lenq, mmsize*2 jl .loop - REP_RET + RET diff --git a/libavcodec/x86/audiodsp.asm b/libavcodec/x86/audiodsp.asm index f64077cb13a..cf5baa9415d 100644 --- a/libavcodec/x86/audiodsp.asm +++ b/libavcodec/x86/audiodsp.asm @@ -123,7 +123,7 @@ cglobal vector_clip_int32%5, 5,5,%1, dst, src, min, max, len add dstq, mmsize*4*(%2+%3) sub lend, mmsize*(%2+%3) jg .loop - REP_RET + RET %endmacro INIT_XMM sse2 diff --git a/libavcodec/x86/dirac_dwt.asm b/libavcodec/x86/dirac_dwt.asm index 6c8b3c0d889..1f3b238aee5 100644 --- a/libavcodec/x86/dirac_dwt.asm +++ b/libavcodec/x86/dirac_dwt.asm @@ -75,7 +75,7 @@ cglobal vertical_compose53iL0_%1, 4,4,1, b0, b1, b2, width COMPOSE_53iL0 m0, m1, [b2q+2*widthq], m2 mova [b1q+2*widthq], m0 jg .loop - REP_RET + RET ; void vertical_compose_dirac53iH0(IDWTELEM *b0, IDWTELEM *b1, IDWTELEM *b2, ; int width) @@ -93,7 +93,7 @@ cglobal vertical_compose_dirac53iH0_%1, 4,4,1, b0, b1, b2, width paddw m0, [b1q+2*widthq] mova [b1q+2*widthq], m0 jg .loop - REP_RET + RET ; void vertical_compose_dd97iH0(IDWTELEM *b0, IDWTELEM *b1, IDWTELEM *b2, ; IDWTELEM *b3, IDWTELEM *b4, int width) @@ -110,7 +110,7 @@ cglobal vertical_compose_dd97iH0_%1, 6,6,5, b0, b1, b2, b3, b4, width COMPOSE_DD97iH0 [b2q+2*widthq], [b3q+2*widthq], [b4q+2*widthq] mova [b2q+2*widthq], m1 jg .loop - REP_RET + RET ; void vertical_compose_dd137iL0(IDWTELEM *b0, IDWTELEM *b1, IDWTELEM *b2, ; IDWTELEM *b3, IDWTELEM *b4, int width) @@ -139,7 +139,7 @@ cglobal vertical_compose_dd137iL0_%1, 6,6,6, b0, b1, b2, b3, b4, width psubw m5, m1 mova [b2q+2*widthq], m5 jg .loop - REP_RET + RET ; void vertical_compose_haar(IDWTELEM *b0, IDWTELEM *b1, int width) cglobal vertical_compose_haar_%1, 3,4,3, b0, b1, width @@ -159,7 +159,7 @@ cglobal vertical_compose_haar_%1, 3,4,3, b0, b1, width paddw m2, m0 mova [b1q+2*widthq], m2 jg .loop - REP_RET + RET %endmacro ; extend the left and right edges of the tmp array by %1 and %2 respectively @@ -225,7 +225,7 @@ cglobal horizontal_compose_haar%2i_%1, 3,6,4, b, tmp, w, x, w2, b_w2 cmp xq, w2q jl .highpass_loop .end: - REP_RET + RET %endmacro @@ -290,7 +290,7 @@ cglobal horizontal_compose_dd97i_ssse3, 3,6,8, b, tmp, w, x, w2, b_w2 cmp xd, w2d jl .highpass_loop .end: - REP_RET + RET INIT_XMM diff --git a/libavcodec/x86/fft.asm b/libavcodec/x86/fft.asm index a44596e5655..34c3fc9a0f5 100644 --- a/libavcodec/x86/fft.asm +++ b/libavcodec/x86/fft.asm @@ -475,7 +475,7 @@ cglobal fft_calc, 2,5,8 mov r0, r1 mov r1, r3 FFT_DISPATCH _interleave %+ SUFFIX, r1 - REP_RET + RET %endif @@ -510,7 +510,7 @@ cglobal fft_calc, 2,5,8 add r2, mmsize*2 jl .loop .end: - REP_RET + RET cglobal fft_permute, 2,7,1 mov r4, [r0 + FFTContext.revtab] @@ -543,7 +543,7 @@ cglobal fft_permute, 2,7,1 movaps [r1 + r2 + 16], xmm1 add r2, 32 jl .loopcopy - REP_RET + RET INIT_XMM sse cglobal imdct_calc, 3,5,3 @@ -583,7 +583,7 @@ cglobal imdct_calc, 3,5,3 sub r3, mmsize add r2, mmsize jl .loop - REP_RET + RET %ifdef PIC %define SECTION_REL - $$ diff --git a/libavcodec/x86/flacdsp.asm b/libavcodec/x86/flacdsp.asm index 6d755f49728..44416e4dfde 100644 --- a/libavcodec/x86/flacdsp.asm +++ b/libavcodec/x86/flacdsp.asm @@ -79,7 +79,7 @@ ALIGN 16 movd [decodedq+4], m1 jg .loop_sample .ret: - REP_RET + RET %endmacro %if HAVE_XOP_EXTERNAL @@ -133,7 +133,7 @@ align 16 mova [outq + lenq], m%2 add lenq, 16 jl .loop - REP_RET + RET %endmacro INIT_XMM sse2 @@ -177,7 +177,7 @@ align 16 add outq, mmsize*2 sub lend, mmsize/4 jg .loop - REP_RET + RET %endmacro INIT_XMM sse2 @@ -302,7 +302,7 @@ align 16 add outq, mmsize*REPCOUNT sub lend, mmsize/4 jg .loop - REP_RET + RET %endmacro INIT_XMM ssse3 diff --git a/libavcodec/x86/h264_chromamc.asm b/libavcodec/x86/h264_chromamc.asm index a5c53034a2b..e70bc492b2d 100644 --- a/libavcodec/x86/h264_chromamc.asm +++ b/libavcodec/x86/h264_chromamc.asm @@ -112,7 +112,7 @@ cglobal %1_%2_chroma_mc8%3, 6, 7 + extra_regs, 0 jne .at_least_one_non_zero ; mx == 0 AND my == 0 - no filter needed mv0_pixels_mc8 - REP_RET + RET .at_least_one_non_zero: %ifidn %2, rv40 @@ -192,7 +192,7 @@ cglobal %1_%2_chroma_mc8%3, 6, 7 + extra_regs, 0 add r1, r2 dec r3d jne .next1drow - REP_RET + RET .both_non_zero: ; general case, bilinear movd m4, r4d ; x @@ -365,7 +365,7 @@ cglobal %1_%2_chroma_mc4, 6, 6 + extra_regs, 0 add r0, r2 sub r3d, 2 jnz .next2rows - REP_RET + RET %endmacro %macro chroma_mc2_mmx_func 2 @@ -407,7 +407,7 @@ cglobal %1_%2_chroma_mc2, 6, 7, 0 add r0, r2 sub r3d, 1 jnz .nextrow - REP_RET + RET %endmacro %define rnd_1d_h264 pw_4 @@ -453,7 +453,7 @@ cglobal %1_%2_chroma_mc8%3, 6, 7, 8 jne .at_least_one_non_zero ; mx == 0 AND my == 0 - no filter needed mv0_pixels_mc8 - REP_RET + RET .at_least_one_non_zero: test r5d, r5d @@ -514,7 +514,7 @@ cglobal %1_%2_chroma_mc8%3, 6, 7, 8 sub r3d, 2 lea r0, [r0+r2*2] jg .next2rows - REP_RET + RET .my_is_zero: mov r5d, r4d @@ -551,7 +551,7 @@ cglobal %1_%2_chroma_mc8%3, 6, 7, 8 lea r0, [r0+r2*2] lea r1, [r1+r2*2] jg .next2xrows - REP_RET + RET .mx_is_zero: mov r4d, r5d @@ -588,7 +588,7 @@ cglobal %1_%2_chroma_mc8%3, 6, 7, 8 sub r3d, 2 lea r0, [r0+r2*2] jg .next2yrows - REP_RET + RET %endmacro %macro chroma_mc4_ssse3_func 2 @@ -638,7 +638,7 @@ cglobal %1_%2_chroma_mc4, 6, 7, 0 sub r3d, 2 lea r0, [r0+r2*2] jg .next2rows - REP_RET + RET %endmacro %define CHROMAMC_AVG NOTHING diff --git a/libavcodec/x86/h264_chromamc_10bit.asm b/libavcodec/x86/h264_chromamc_10bit.asm index fdc4f407c7a..d4f92c90c72 100644 --- a/libavcodec/x86/h264_chromamc_10bit.asm +++ b/libavcodec/x86/h264_chromamc_10bit.asm @@ -67,7 +67,7 @@ cglobal %1_h264_chroma_mc8_10, 6,7,8 jne .at_least_one_non_zero ; mx == 0 AND my == 0 - no filter needed MV0_PIXELS_MC8 - REP_RET + RET .at_least_one_non_zero: mov r6d, 2 @@ -102,7 +102,7 @@ cglobal %1_h264_chroma_mc8_10, 6,7,8 add r1, r2 dec r3d jne .next1drow - REP_RET + RET .xy_interpolation: ; general case, bilinear movd m4, r4m ; x @@ -144,7 +144,7 @@ cglobal %1_h264_chroma_mc8_10, 6,7,8 add r0, r2 dec r3d jne .next2drow - REP_RET + RET %endmacro ;----------------------------------------------------------------------------- @@ -194,7 +194,7 @@ cglobal %1_h264_chroma_mc4_10, 6,6,7 MC4_OP m6, m0 sub r3d, 2 jnz .next2rows - REP_RET + RET %endmacro ;----------------------------------------------------------------------------- @@ -234,7 +234,7 @@ cglobal %1_h264_chroma_mc2_10, 6,7 add r0, r2 dec r3d jnz .nextrow - REP_RET + RET %endmacro %macro NOTHING 2-3 diff --git a/libavcodec/x86/h264_deblock_10bit.asm b/libavcodec/x86/h264_deblock_10bit.asm index 23971b5cb51..033f2f4d550 100644 --- a/libavcodec/x86/h264_deblock_10bit.asm +++ b/libavcodec/x86/h264_deblock_10bit.asm @@ -372,7 +372,7 @@ cglobal deblock_v_luma_10, 5,5,15 add r4, 2 dec r3 jg .loop - REP_RET + RET cglobal deblock_h_luma_10, 5,7,15 shl r2d, 2 @@ -411,7 +411,7 @@ cglobal deblock_h_luma_10, 5,7,15 lea r5, [r5+r1*8] dec r6 jg .loop - REP_RET + RET %endmacro INIT_XMM sse2 @@ -648,7 +648,7 @@ cglobal deblock_v_luma_intra_10, 4,7,16 add r4, mmsize dec r6 jg .loop - REP_RET + RET ;----------------------------------------------------------------------------- ; void ff_deblock_h_luma_intra_10(uint16_t *pix, int stride, int alpha, diff --git a/libavcodec/x86/h264_idct.asm b/libavcodec/x86/h264_idct.asm index 9b5920d3b02..1f86e51d82d 100644 --- a/libavcodec/x86/h264_idct.asm +++ b/libavcodec/x86/h264_idct.asm @@ -354,7 +354,7 @@ INIT_MMX cpuname add r2, 128 cmp r5, 16 jl .nextblock - REP_RET + RET .no_dc: INIT_XMM cpuname mov dst2d, dword [r1+r5*4] @@ -368,7 +368,7 @@ INIT_XMM cpuname add r2, 128 cmp r5, 16 jl .nextblock - REP_RET + RET INIT_MMX mmx h264_idct_add8_mmx_plane: @@ -508,7 +508,7 @@ cglobal h264_idct_add16_8, 5, 5 + ARCH_X86_64, 8 add16_sse2_cycle 5, 0x24 add16_sse2_cycle 6, 0x1e add16_sse2_cycle 7, 0x26 -REP_RET +RET %macro add16intra_sse2_cycle 2 movzx r0, word [r4+%2] @@ -555,7 +555,7 @@ cglobal h264_idct_add16intra_8, 5, 7 + ARCH_X86_64, 8 add16intra_sse2_cycle 5, 0x24 add16intra_sse2_cycle 6, 0x1e add16intra_sse2_cycle 7, 0x26 -REP_RET +RET %macro add8_sse2_cycle 2 movzx r0, word [r4+%2] @@ -610,7 +610,7 @@ cglobal h264_idct_add8_8, 5, 7 + ARCH_X86_64, 8 %endif add8_sse2_cycle 2, 0x5c add8_sse2_cycle 3, 0x64 -REP_RET +RET ;void ff_h264_luma_dc_dequant_idct_mmx(int16_t *output, int16_t *input, int qmul) diff --git a/libavcodec/x86/h264_idct_10bit.asm b/libavcodec/x86/h264_idct_10bit.asm index 9fd05abb2b7..b990db7121e 100644 --- a/libavcodec/x86/h264_idct_10bit.asm +++ b/libavcodec/x86/h264_idct_10bit.asm @@ -155,7 +155,7 @@ cglobal h264_idct_add16_10, 5,6 ADD16_OP 13, 7+3*8 ADD16_OP 14, 6+4*8 ADD16_OP 15, 7+4*8 - REP_RET + RET %endmacro INIT_XMM sse2 @@ -292,7 +292,7 @@ cglobal h264_idct_add16intra_10,5,7,8 ADD16_OP_INTRA 10, 4+4*8 ADD16_OP_INTRA 12, 6+3*8 ADD16_OP_INTRA 14, 6+4*8 - REP_RET + RET AC 8 AC 10 AC 12 @@ -335,7 +335,7 @@ cglobal h264_idct_add8_10,5,8,7 %endif ADD16_OP_INTRA 32, 4+11*8 ADD16_OP_INTRA 34, 4+12*8 - REP_RET + RET AC 16 AC 18 AC 32 @@ -384,7 +384,7 @@ cglobal h264_idct_add8_422_10, 5, 8, 7 ADD16_OP_INTRA 34, 4+12*8 ADD16_OP_INTRA 40, 4+13*8 ; i+4 ADD16_OP_INTRA 42, 4+14*8 ; i+4 -REP_RET +RET AC 16 AC 18 AC 24 ; i+4 diff --git a/libavcodec/x86/h264_intrapred.asm b/libavcodec/x86/h264_intrapred.asm index 31840a14720..8a38ba2bb5d 100644 --- a/libavcodec/x86/h264_intrapred.asm +++ b/libavcodec/x86/h264_intrapred.asm @@ -62,7 +62,7 @@ cglobal pred16x16_vertical_8, 2,3 lea r0, [r0+r1*2] dec r2 jg .loop - REP_RET + RET ;----------------------------------------------------------------------------- ; void ff_pred16x16_horizontal_8(uint8_t *src, ptrdiff_t stride) @@ -95,7 +95,7 @@ cglobal pred16x16_horizontal_8, 2,3 lea r0, [r0+r1*2] dec r2 jg .loop - REP_RET + RET %endmacro INIT_MMX mmxext @@ -146,7 +146,7 @@ cglobal pred16x16_dc_8, 2,7 lea r4, [r4+r1*2] dec r3d jg .loop - REP_RET + RET %endmacro INIT_XMM sse2 @@ -192,7 +192,7 @@ cglobal pred16x16_tm_vp8_8, 2,6,6 lea r0, [r0+r1*2] dec r5d jg .loop - REP_RET + RET %if HAVE_AVX2_EXTERNAL INIT_YMM avx2 @@ -228,7 +228,7 @@ cglobal pred16x16_tm_vp8_8, 2, 4, 5, dst, stride, stride3, iteration lea dstq, [dstq+strideq*4] dec iterationd jg .loop - REP_RET + RET %endif ;----------------------------------------------------------------------------- @@ -427,7 +427,7 @@ cglobal pred16x16_plane_%1_8, 2,9,7 lea r0, [r0+r2*2] dec r4 jg .loop - REP_RET + RET %endmacro INIT_XMM sse2 @@ -556,7 +556,7 @@ ALIGN 16 lea r0, [r0+r2*2] dec r4 jg .loop - REP_RET + RET %endmacro INIT_XMM sse2 @@ -599,7 +599,7 @@ cglobal pred8x8_horizontal_8, 2,3 lea r0, [r0+r1*2] dec r2 jg .loop - REP_RET + RET %endmacro INIT_MMX mmxext @@ -737,7 +737,7 @@ cglobal pred8x8_dc_rv40_8, 2,7 lea r4, [r4+r1*2] dec r3d jg .loop - REP_RET + RET ;----------------------------------------------------------------------------- ; void ff_pred8x8_tm_vp8_8(uint8_t *src, ptrdiff_t stride) @@ -770,7 +770,7 @@ cglobal pred8x8_tm_vp8_8, 2,6,4 lea r0, [r0+r1*2] dec r5d jg .loop - REP_RET + RET INIT_XMM ssse3 cglobal pred8x8_tm_vp8_8, 2,3,6 @@ -797,7 +797,7 @@ cglobal pred8x8_tm_vp8_8, 2,3,6 lea r0, [r0+r1*2] dec r2d jg .loop - REP_RET + RET ; dest, left, right, src, tmp ; output: %1 = (t[n-1] + t[n]*2 + t[n+1] + 2) >> 2 @@ -1802,7 +1802,7 @@ cglobal pred4x4_tm_vp8_8, 3,6 lea r0, [r0+r2*2] dec r5d jg .loop - REP_RET + RET INIT_XMM ssse3 cglobal pred4x4_tm_vp8_8, 3,3 diff --git a/libavcodec/x86/h264_intrapred_10bit.asm b/libavcodec/x86/h264_intrapred_10bit.asm index c4645d434ee..2f30807332a 100644 --- a/libavcodec/x86/h264_intrapred_10bit.asm +++ b/libavcodec/x86/h264_intrapred_10bit.asm @@ -327,7 +327,7 @@ cglobal pred8x8_horizontal_10, 2, 3 lea r0, [r0+r1*2] dec r2d jg .loop - REP_RET + RET ;----------------------------------------------------------------------------- ; void ff_predict_8x8_dc_10(pixel *src, ptrdiff_t stride) @@ -481,7 +481,7 @@ cglobal pred8x8_plane_10, 2, 7, 7 add r0, r1 dec r2d jg .loop - REP_RET + RET ;----------------------------------------------------------------------------- @@ -994,7 +994,7 @@ cglobal pred16x16_vertical_10, 2, 3 lea r0, [r0+r1*2] dec r2d jg .loop - REP_RET + RET ;----------------------------------------------------------------------------- ; void ff_pred16x16_horizontal_10(pixel *src, ptrdiff_t stride) @@ -1012,7 +1012,7 @@ cglobal pred16x16_horizontal_10, 2, 3 lea r0, [r0+r1*2] dec r2d jg .vloop - REP_RET + RET ;----------------------------------------------------------------------------- ; void ff_pred16x16_dc_10(pixel *src, ptrdiff_t stride) @@ -1048,7 +1048,7 @@ cglobal pred16x16_dc_10, 2, 6 lea r5, [r5+r1*2] dec r3d jg .loop - REP_RET + RET ;----------------------------------------------------------------------------- ; void ff_pred16x16_top_dc_10(pixel *src, ptrdiff_t stride) @@ -1070,7 +1070,7 @@ cglobal pred16x16_top_dc_10, 2, 3 lea r0, [r0+r1*2] dec r2d jg .loop - REP_RET + RET ;----------------------------------------------------------------------------- ; void ff_pred16x16_left_dc_10(pixel *src, ptrdiff_t stride) @@ -1101,7 +1101,7 @@ cglobal pred16x16_left_dc_10, 2, 6 lea r5, [r5+r1*2] dec r3d jg .loop - REP_RET + RET ;----------------------------------------------------------------------------- ; void ff_pred16x16_128_dc_10(pixel *src, ptrdiff_t stride) @@ -1116,4 +1116,4 @@ cglobal pred16x16_128_dc_10, 2,3 lea r0, [r0+r1*2] dec r2d jg .loop - REP_RET + RET diff --git a/libavcodec/x86/h264_qpel_10bit.asm b/libavcodec/x86/h264_qpel_10bit.asm index c862cb22269..80483b15ba7 100644 --- a/libavcodec/x86/h264_qpel_10bit.asm +++ b/libavcodec/x86/h264_qpel_10bit.asm @@ -211,7 +211,7 @@ cglobal %1_h264_qpel16_mc00_10, 3,4 lea r1, [r1+r2*2] dec r3d jg .loop - REP_RET + RET %endmacro %define OP_MOV mova diff --git a/libavcodec/x86/h264_qpel_8bit.asm b/libavcodec/x86/h264_qpel_8bit.asm index 6269b3cf4f5..4e64329991e 100644 --- a/libavcodec/x86/h264_qpel_8bit.asm +++ b/libavcodec/x86/h264_qpel_8bit.asm @@ -89,7 +89,7 @@ cglobal %1_h264_qpel4_h_lowpass, 4,5 ; dst, src, dstStride, srcStride add r1, r3 dec r4d jg .loop - REP_RET + RET %endmacro INIT_MMX mmxext @@ -149,7 +149,7 @@ cglobal %1_h264_qpel8_h_lowpass, 4,5 ; dst, src, dstStride, srcStride add r1, r3 dec r4d jg .loop - REP_RET + RET %endmacro INIT_MMX mmxext @@ -192,7 +192,7 @@ cglobal %1_h264_qpel8_h_lowpass, 4,5,8 ; dst, src, dstStride, srcStride add r0, r2 dec r4d jne .loop - REP_RET + RET %endmacro INIT_XMM ssse3 @@ -239,7 +239,7 @@ cglobal %1_h264_qpel4_h_lowpass_l2, 5,6 ; dst, src, src2, dstStride, srcStride add r2, r4 dec r5d jg .loop - REP_RET + RET %endmacro INIT_MMX mmxext @@ -303,7 +303,7 @@ cglobal %1_h264_qpel8_h_lowpass_l2, 5,6 ; dst, src, src2, dstStride, srcStride add r2, r4 dec r5d jg .loop - REP_RET + RET %endmacro INIT_MMX mmxext @@ -350,7 +350,7 @@ cglobal %1_h264_qpel8_h_lowpass_l2, 5,6,8 ; dst, src, src2, dstStride, src2Strid add r2, r4 dec r5d jg .loop - REP_RET + RET %endmacro INIT_XMM ssse3 @@ -458,7 +458,7 @@ cglobal %1_h264_qpel8or16_v_lowpass_op, 5,5,8 ; dst, src, dstStride, srcStride, FILT_V %1 FILT_V %1 .end: - REP_RET + RET %endmacro INIT_XMM sse2 @@ -531,7 +531,7 @@ cglobal %1_h264_qpel4_hv_lowpass_h, 3,4 ; tmp, dst, dstStride add r1, r2 dec r3d jnz .loop - REP_RET + RET %endmacro INIT_MMX mmxext @@ -574,7 +574,7 @@ cglobal %1_h264_qpel8or16_hv1_lowpass_op, 4,4,8 ; src, tmp, srcStride, size FILT_HV 14*48 FILT_HV 15*48 .end: - REP_RET + RET %endmacro INIT_XMM sse2 @@ -619,7 +619,7 @@ cglobal %1_h264_qpel8or16_hv2_lowpass_op, 5,5 ; dst, tmp, dstStride, unused, h add r0, r2 dec r4d jne .loop - REP_RET + RET %endmacro INIT_MMX mmxext @@ -710,7 +710,7 @@ cglobal %1_h264_qpel8or16_hv2_lowpass, 5,5,8 ; dst, tmp, dstStride, tmpStride, s dec r4d jne .op16 .done: - REP_RET + RET %endmacro INIT_XMM ssse3 @@ -776,7 +776,7 @@ cglobal %1_pixels8_l2_shift5, 6, 6 ; dst, src16, src8, dstStride, src8Stride, h lea r0, [r0+2*r3] sub r5d, 2 jne .loop - REP_RET + RET %endmacro INIT_MMX mmxext @@ -845,7 +845,7 @@ cglobal %1_h264_qpel16_h_lowpass_l2, 5, 6, 16 ; dst, src, src2, dstStride, src2S add r2, r4 dec r5d jg .loop - REP_RET + RET %endmacro INIT_XMM ssse3 diff --git a/libavcodec/x86/h264_weight.asm b/libavcodec/x86/h264_weight.asm index 6076e64ae05..66353d1a9c1 100644 --- a/libavcodec/x86/h264_weight.asm +++ b/libavcodec/x86/h264_weight.asm @@ -79,7 +79,7 @@ cglobal h264_weight_%1, 6, 6, %2 add r0, r1 dec r2d jnz .nextrow - REP_RET + RET %endmacro INIT_XMM sse2 @@ -102,7 +102,7 @@ cglobal h264_weight_%1, 6, 6, %2 add r0, r3 dec r2d jnz .nextrow - REP_RET + RET %endmacro INIT_MMX mmxext @@ -196,7 +196,7 @@ cglobal h264_biweight_%1, 7, 8, %2 add r1, r2 dec r3d jnz .nextrow - REP_RET + RET %endmacro INIT_XMM sse2 @@ -223,7 +223,7 @@ cglobal h264_biweight_%1, 7, 8, %2 add r1, r4 dec r3d jnz .nextrow - REP_RET + RET %endmacro INIT_MMX mmxext @@ -258,7 +258,7 @@ cglobal h264_biweight_16, 7, 8, 8 add r1, r2 dec r3d jnz .nextrow - REP_RET + RET INIT_XMM ssse3 cglobal h264_biweight_8, 7, 8, 8 @@ -281,4 +281,4 @@ cglobal h264_biweight_8, 7, 8, 8 add r1, r4 dec r3d jnz .nextrow - REP_RET + RET diff --git a/libavcodec/x86/h264_weight_10bit.asm b/libavcodec/x86/h264_weight_10bit.asm index f924e558544..356871bc62d 100644 --- a/libavcodec/x86/h264_weight_10bit.asm +++ b/libavcodec/x86/h264_weight_10bit.asm @@ -101,7 +101,7 @@ cglobal h264_weight_16_10 add r0, r1 dec r2d jnz .nextrow - REP_RET + RET %endmacro INIT_XMM sse2 @@ -120,7 +120,7 @@ cglobal h264_weight_8_10 add r0, r1 dec r2d jnz .nextrow - REP_RET + RET %endmacro INIT_XMM sse2 @@ -142,7 +142,7 @@ cglobal h264_weight_4_10 add r0, r3 dec r2d jnz .nextrow - REP_RET + RET %endmacro INIT_XMM sse2 @@ -234,7 +234,7 @@ cglobal h264_biweight_16_10 add r1, r2 dec r3d jnz .nextrow - REP_RET + RET %endmacro INIT_XMM sse2 @@ -253,7 +253,7 @@ cglobal h264_biweight_8_10 add r1, r2 dec r3d jnz .nextrow - REP_RET + RET %endmacro INIT_XMM sse2 @@ -275,7 +275,7 @@ cglobal h264_biweight_4_10 add r1, r4 dec r3d jnz .nextrow - REP_RET + RET %endmacro INIT_XMM sse2 diff --git a/libavcodec/x86/hevc_sao.asm b/libavcodec/x86/hevc_sao.asm index 2eb8924da81..8abb16150d0 100644 --- a/libavcodec/x86/hevc_sao.asm +++ b/libavcodec/x86/hevc_sao.asm @@ -166,7 +166,7 @@ INIT_YMM cpuname add srcq, srcstrideq ; src += srcstride dec heightd ; cmp height jnz .loop ; height loop - REP_RET + RET %endmacro diff --git a/libavcodec/x86/hevc_sao_10bit.asm b/libavcodec/x86/hevc_sao_10bit.asm index 38005740e50..0daa9c645cd 100644 --- a/libavcodec/x86/hevc_sao_10bit.asm +++ b/libavcodec/x86/hevc_sao_10bit.asm @@ -145,7 +145,7 @@ align 16 add srcq, srcstrideq dec heightd jg .loop - REP_RET + RET %endmacro %macro HEVC_SAO_BAND_FILTER_FUNCS 0 diff --git a/libavcodec/x86/hpeldsp.asm b/libavcodec/x86/hpeldsp.asm index b3a270a173b..7a2b7135d80 100644 --- a/libavcodec/x86/hpeldsp.asm +++ b/libavcodec/x86/hpeldsp.asm @@ -78,7 +78,7 @@ cglobal put_pixels8_x2, 4,5 add r0, r4 sub r3d, 4 jne .loop - REP_RET + RET %endmacro INIT_MMX mmxext @@ -120,7 +120,7 @@ cglobal put_pixels16_x2, 4,5 add r0, r4 sub r3d, 4 jne .loop - REP_RET + RET %endmacro INIT_MMX mmxext @@ -162,7 +162,7 @@ cglobal put_no_rnd_pixels8_x2, 4,5 add r0, r4 sub r3d, 4 jne .loop - REP_RET + RET ; void ff_put_pixels8_y2(uint8_t *block, const uint8_t *pixels, ptrdiff_t line_size, int h) @@ -194,7 +194,7 @@ cglobal put_pixels8_y2, 4,5 add r0, r4 sub r3d, 4 jne .loop - REP_RET + RET %endmacro INIT_MMX mmxext @@ -232,7 +232,7 @@ cglobal put_no_rnd_pixels8_y2, 4,5 add r0, r4 sub r3d, 4 jne .loop - REP_RET + RET ; void ff_avg_pixels8_x2(uint8_t *block, const uint8_t *pixels, ptrdiff_t line_size, int h) @@ -280,7 +280,7 @@ cglobal avg_pixels8_x2, 4,5 add r0, r4 sub r3d, 4 jne .loop - REP_RET + RET %endmacro INIT_MMX mmxext @@ -323,7 +323,7 @@ cglobal avg_pixels8_y2, 4,5 add r0, r4 sub r3d, 4 jne .loop - REP_RET + RET %endmacro INIT_MMX mmxext @@ -370,7 +370,7 @@ cglobal avg_approx_pixels8_xy2, 4,5 add r0, r4 sub r3d, 4 jne .loop - REP_RET + RET ; void ff_avg_pixels16_xy2(uint8_t *block, const uint8_t *pixels, ptrdiff_t line_size, int h) @@ -448,7 +448,7 @@ cglobal %1_pixels8_xy2, 4,5 add r4, r2 sub r3d, 2 jnz .loop - REP_RET + RET %endmacro INIT_MMX mmxext @@ -514,7 +514,7 @@ cglobal %1_pixels8_xy2, 4,5 add r4, r2 sub r3d, 2 jnz .loop - REP_RET + RET %endmacro INIT_MMX ssse3 diff --git a/libavcodec/x86/hpeldsp_vp3.asm b/libavcodec/x86/hpeldsp_vp3.asm index 88ca8e8e0af..e580133e454 100644 --- a/libavcodec/x86/hpeldsp_vp3.asm +++ b/libavcodec/x86/hpeldsp_vp3.asm @@ -60,7 +60,7 @@ cglobal put_no_rnd_pixels8_x2_exact, 4,5 lea r0, [r0+r2*4] sub r3d, 4 jg .loop - REP_RET + RET ; void ff_put_no_rnd_pixels8_y2_exact(uint8_t *block, const uint8_t *pixels, ptrdiff_t line_size, int h) @@ -96,4 +96,4 @@ cglobal put_no_rnd_pixels8_y2_exact, 4,5 lea r0, [r0+r2*4] sub r3d, 4 jg .loop - REP_RET + RET diff --git a/libavcodec/x86/huffyuvdsp.asm b/libavcodec/x86/huffyuvdsp.asm index c5c40e991b2..c1b375f4791 100644 --- a/libavcodec/x86/huffyuvdsp.asm +++ b/libavcodec/x86/huffyuvdsp.asm @@ -74,7 +74,7 @@ cglobal add_hfyu_left_pred_bgr32, 4,4,3, dst, src, w, left jl .loop movd m0, [dstq-4] movd [leftq], m0 - REP_RET + RET ; void add_hfyu_median_prediction_mmxext(uint8_t *dst, const uint8_t *top, const uint8_t *diff, int mask, int w, int *left, int *left_top) diff --git a/libavcodec/x86/jpeg2000dsp.asm b/libavcodec/x86/jpeg2000dsp.asm index 61dfdd4f71b..c61cc707844 100644 --- a/libavcodec/x86/jpeg2000dsp.asm +++ b/libavcodec/x86/jpeg2000dsp.asm @@ -113,7 +113,7 @@ align 16 movaps [src1q+csizeq], m5 add csizeq, mmsize jl .loop - REP_RET + RET %endmacro INIT_XMM sse @@ -153,7 +153,7 @@ align 16 mova [src0q+csizeq], m2 add csizeq, mmsize jl .loop - REP_RET + RET %endmacro INIT_XMM sse2 diff --git a/libavcodec/x86/lossless_videodsp.asm b/libavcodec/x86/lossless_videodsp.asm index eb1b80506ee..7159aafe678 100644 --- a/libavcodec/x86/lossless_videodsp.asm +++ b/libavcodec/x86/lossless_videodsp.asm @@ -229,7 +229,7 @@ cglobal add_bytes, 3,4,2, dst, src, w, size inc wq jl .3 .end: - REP_RET + RET %endmacro INIT_XMM sse2 diff --git a/libavcodec/x86/lossless_videoencdsp.asm b/libavcodec/x86/lossless_videoencdsp.asm index c579891d6ac..8ccaea91393 100644 --- a/libavcodec/x86/lossless_videoencdsp.asm +++ b/libavcodec/x86/lossless_videoencdsp.asm @@ -110,7 +110,7 @@ cglobal diff_bytes, 4,5,2, dst, src1, src2, w inc wq jl .loop_gpr_%1%2 .end_%1%2: - REP_RET + RET %endmacro INIT_XMM sse2 diff --git a/libavcodec/x86/me_cmp.asm b/libavcodec/x86/me_cmp.asm index eb036ee4bc0..923eb8078b4 100644 --- a/libavcodec/x86/me_cmp.asm +++ b/libavcodec/x86/me_cmp.asm @@ -458,7 +458,7 @@ cglobal hf_noise%1, 3,3,0, pix1, lsize, h psrlq m6, 32 paddd m0, m6 movd eax, m0 ; eax = result of hf_noise8; - REP_RET ; return eax; + RET ; return eax; %endmacro INIT_MMX mmx diff --git a/libavcodec/x86/pngdsp.asm b/libavcodec/x86/pngdsp.asm index 7bc43c79a0d..efaf652cd4a 100644 --- a/libavcodec/x86/pngdsp.asm +++ b/libavcodec/x86/pngdsp.asm @@ -75,7 +75,7 @@ cglobal add_bytes_l2, 4, 6, 2, dst, src1, src2, wa, w, i .end_s: cmp iq, wq jl .loop_s - REP_RET + RET %macro ADD_PAETH_PRED_FN 1 cglobal add_png_paeth_prediction, 5, 7, %1, dst, src, top, w, bpp, end, cntr diff --git a/libavcodec/x86/qpel.asm b/libavcodec/x86/qpel.asm index 4e72d5084ff..481251314a7 100644 --- a/libavcodec/x86/qpel.asm +++ b/libavcodec/x86/qpel.asm @@ -81,7 +81,7 @@ cglobal %1_pixels4_l2, 6,6 add r2, 16 sub r5d, 4 jne .loop - REP_RET + RET %endmacro INIT_MMX mmxext @@ -125,7 +125,7 @@ cglobal %1_pixels8_l2, 6,6 add r2, 32 sub r5d, 4 jne .loop - REP_RET + RET %endmacro INIT_MMX mmxext @@ -171,7 +171,7 @@ cglobal %1_pixels16_l2, 6,6 add r2, 32 sub r5d, 2 jne .loop - REP_RET + RET %endmacro INIT_MMX mmxext diff --git a/libavcodec/x86/qpeldsp.asm b/libavcodec/x86/qpeldsp.asm index 3a6a6506544..30d26a5acc5 100644 --- a/libavcodec/x86/qpeldsp.asm +++ b/libavcodec/x86/qpeldsp.asm @@ -92,7 +92,7 @@ cglobal put_no_rnd_pixels8_l2, 6,6 add r2, 32 sub r5d, 4 jne .loop - REP_RET + RET %endmacro INIT_MMX mmxext @@ -161,7 +161,7 @@ cglobal put_no_rnd_pixels16_l2, 6,6 add r2, 32 sub r5d, 2 jne .loop - REP_RET + RET %endmacro INIT_MMX mmxext @@ -274,7 +274,7 @@ cglobal %1_mpeg4_qpel16_h_lowpass, 5, 5, 0, 16 add r0, r2 dec r4d jne .loop - REP_RET + RET %endmacro %macro PUT_OP 2-3 @@ -357,7 +357,7 @@ cglobal %1_mpeg4_qpel8_h_lowpass, 5, 5, 0, 8 add r0, r2 dec r4d jne .loop - REP_RET + RET %endmacro INIT_MMX mmxext @@ -466,7 +466,7 @@ cglobal %1_mpeg4_qpel16_v_lowpass, 4, 6, 0, 544 add r0, r1 dec r4d jne .loopv - REP_RET + RET %endmacro %macro PUT_OPH 2-3 @@ -543,7 +543,7 @@ cglobal %1_mpeg4_qpel8_v_lowpass, 4, 6, 0, 288 add r0, r1 dec r4d jne .loopv - REP_RET + RET %endmacro INIT_MMX mmxext diff --git a/libavcodec/x86/rv34dsp.asm b/libavcodec/x86/rv34dsp.asm index 0a3d99c53f2..f29bfd715c7 100644 --- a/libavcodec/x86/rv34dsp.asm +++ b/libavcodec/x86/rv34dsp.asm @@ -54,7 +54,7 @@ cglobal rv34_idct_dc_noround, 1, 2, 0 movq [r0+ 8], m0 movq [r0+16], m0 movq [r0+24], m0 - REP_RET + RET ; Load coeffs and perform row transform ; Output: coeffs in mm[0467], rounder in mm5 diff --git a/libavcodec/x86/rv40dsp.asm b/libavcodec/x86/rv40dsp.asm index f2ce236d441..e02ad2c63f1 100644 --- a/libavcodec/x86/rv40dsp.asm +++ b/libavcodec/x86/rv40dsp.asm @@ -170,7 +170,7 @@ cglobal %1_rv40_qpel_v, 6,6+npicregs,12, dst, dststride, src, srcstride, height, add srcq, srcstrideq dec heightd ; next row jg .nextrow - REP_RET + RET %endmacro %macro FILTER_H 1 @@ -227,7 +227,7 @@ cglobal %1_rv40_qpel_h, 6, 6+npicregs, 12, dst, dststride, src, srcstride, heigh add srcq, srcstrideq dec heightd ; next row jg .nextrow - REP_RET + RET %endmacro INIT_XMM sse2 @@ -280,7 +280,7 @@ cglobal %1_rv40_qpel_v, 6,6+npicregs,8, dst, dststride, src, srcstride, height, add srcq, srcstrideq dec heightd ; next row jg .nextrow - REP_RET + RET cglobal %1_rv40_qpel_h, 6,6+npicregs,8, dst, dststride, src, srcstride, height, mx, picreg %ifdef PIC @@ -313,7 +313,7 @@ cglobal %1_rv40_qpel_h, 6,6+npicregs,8, dst, dststride, src, srcstride, height, add srcq, srcstrideq dec heightd ; next row jg .nextrow - REP_RET + RET %endmacro INIT_XMM ssse3 @@ -464,7 +464,7 @@ cglobal rv40_weight_func_%1_%2, 6, 7, 8 .loop: MAIN_LOOP %2, RND jnz .loop - REP_RET + RET %endmacro INIT_XMM sse2 diff --git a/libavcodec/x86/sbrdsp.asm b/libavcodec/x86/sbrdsp.asm index 87dcdc43ce1..d02f70d7043 100644 --- a/libavcodec/x86/sbrdsp.asm +++ b/libavcodec/x86/sbrdsp.asm @@ -208,7 +208,7 @@ cglobal sbr_sum64x5, 1,2,4,z add zq, 32 cmp zq, r1q jne .loop - REP_RET + RET INIT_XMM sse cglobal sbr_qmf_post_shuffle, 2,3,4,W,z @@ -227,7 +227,7 @@ cglobal sbr_qmf_post_shuffle, 2,3,4,W,z add zq, 16 cmp zq, r2q jl .loop - REP_RET + RET INIT_XMM sse cglobal sbr_neg_odd_64, 1,2,4,z @@ -248,7 +248,7 @@ cglobal sbr_neg_odd_64, 1,2,4,z add zq, 64 cmp zq, r1q jne .loop - REP_RET + RET ; void ff_sbr_qmf_deint_bfly_sse2(float *v, const float *src0, const float *src1) INIT_XMM sse2 @@ -276,7 +276,7 @@ cglobal sbr_qmf_deint_bfly, 3,5,8, v,src0,src1,vrev,c add vrevq, 2*mmsize sub cq, 2*mmsize jge .loop - REP_RET + RET INIT_XMM sse2 cglobal sbr_qmf_pre_shuffle, 1,4,6,z @@ -306,7 +306,7 @@ cglobal sbr_qmf_pre_shuffle, 1,4,6,z jge .loop movq m2, [zq] movq [r2q], m2 - REP_RET + RET %ifdef PIC %define NREGS 1 @@ -432,7 +432,7 @@ cglobal sbr_qmf_deint_neg, 2,4,4,v,src,vrev,c sub vq, mmsize add cq, mmsize jl .loop - REP_RET + RET %macro SBR_AUTOCORRELATE 0 cglobal sbr_autocorrelate, 2,3,8,32, x, phi, cnt diff --git a/libavcodec/x86/takdsp.asm b/libavcodec/x86/takdsp.asm index 5f3ded3ea2d..be8e1ab5533 100644 --- a/libavcodec/x86/takdsp.asm +++ b/libavcodec/x86/takdsp.asm @@ -43,7 +43,7 @@ cglobal tak_decorrelate_ls, 3, 3, 2, p1, p2, length mova [p2q+lengthq+mmsize*1], m1 add lengthq, mmsize*2 jl .loop - REP_RET + RET cglobal tak_decorrelate_sr, 3, 3, 2, p1, p2, length shl lengthd, 2 @@ -60,7 +60,7 @@ cglobal tak_decorrelate_sr, 3, 3, 2, p1, p2, length mova [p1q+lengthq+mmsize*1], m1 add lengthq, mmsize*2 jl .loop - REP_RET + RET cglobal tak_decorrelate_sm, 3, 3, 6, p1, p2, length shl lengthd, 2 @@ -87,7 +87,7 @@ cglobal tak_decorrelate_sm, 3, 3, 6, p1, p2, length mova [p2q+lengthq+mmsize], m4 add lengthq, mmsize*2 jl .loop - REP_RET + RET INIT_XMM sse4 cglobal tak_decorrelate_sf, 3, 3, 5, p1, p2, length, dshift, dfactor @@ -113,4 +113,4 @@ cglobal tak_decorrelate_sf, 3, 3, 5, p1, p2, length, dshift, dfactor mova [p1q+lengthq], m1 add lengthq, mmsize jl .loop - REP_RET + RET diff --git a/libavcodec/x86/utvideodsp.asm b/libavcodec/x86/utvideodsp.asm index b799c44b640..9d54deeb32b 100644 --- a/libavcodec/x86/utvideodsp.asm +++ b/libavcodec/x86/utvideodsp.asm @@ -69,7 +69,7 @@ DEFINE_ARGS src_r, src_g, src_b, linesize_r, linesize_g, linesize_b, x add src_bq, linesize_bq sub hd, 1 jg .nextrow - REP_RET + RET %endmacro INIT_XMM sse2 @@ -125,7 +125,7 @@ DEFINE_ARGS src_r, src_g, src_b, linesize_r, linesize_g, linesize_b, x add src_bq, linesize_bq sub hd, 1 jg .nextrow - REP_RET + RET %endmacro INIT_XMM sse2 diff --git a/libavcodec/x86/v210.asm b/libavcodec/x86/v210.asm index f247737ed03..8ae592205f9 100644 --- a/libavcodec/x86/v210.asm +++ b/libavcodec/x86/v210.asm @@ -116,7 +116,7 @@ cglobal v210_planar_unpack_%1, 5, 5, 6 + 2 * cpuflag(avx2), src, y, u, v, w add wq, (mmsize*3)/8 jl .loop - REP_RET + RET %endmacro INIT_XMM ssse3 diff --git a/libavcodec/x86/vc1dsp_mc.asm b/libavcodec/x86/vc1dsp_mc.asm index 0e6d87dd8b5..c1b3ed1bc3b 100644 --- a/libavcodec/x86/vc1dsp_mc.asm +++ b/libavcodec/x86/vc1dsp_mc.asm @@ -139,7 +139,7 @@ cglobal vc1_put_ver_16b_shift2, 4,7,0, dst, src, stride add dstq, 8 dec i jnz .loop - REP_RET + RET %undef rnd %undef shift %undef stride_neg2 diff --git a/libavcodec/x86/videodsp.asm b/libavcodec/x86/videodsp.asm index b19a8300c54..3cc07878d3b 100644 --- a/libavcodec/x86/videodsp.asm +++ b/libavcodec/x86/videodsp.asm @@ -433,4 +433,4 @@ cglobal prefetch, 3, 3, 0, buf, stride, h add bufq, strideq dec hd jg .loop - REP_RET + RET diff --git a/libavcodec/x86/vp8dsp.asm b/libavcodec/x86/vp8dsp.asm index 33d488bf6f2..6ac5a7721bf 100644 --- a/libavcodec/x86/vp8dsp.asm +++ b/libavcodec/x86/vp8dsp.asm @@ -200,7 +200,7 @@ cglobal put_vp8_epel%1_h6, 6, 6 + npicregs, 8, dst, dststride, src, srcstride, h add srcq, srcstrideq dec heightd ; next row jg .nextrow - REP_RET + RET cglobal put_vp8_epel%1_h4, 6, 6 + npicregs, 7, dst, dststride, src, srcstride, height, mx, picreg shl mxd, 4 @@ -230,7 +230,7 @@ cglobal put_vp8_epel%1_h4, 6, 6 + npicregs, 7, dst, dststride, src, srcstride, h add srcq, srcstrideq dec heightd ; next row jg .nextrow - REP_RET + RET cglobal put_vp8_epel%1_v4, 7, 7, 8, dst, dststride, src, srcstride, height, picreg, my shl myd, 4 @@ -268,7 +268,7 @@ cglobal put_vp8_epel%1_v4, 7, 7, 8, dst, dststride, src, srcstride, height, picr add srcq, srcstrideq dec heightd ; next row jg .nextrow - REP_RET + RET cglobal put_vp8_epel%1_v6, 7, 7, 8, dst, dststride, src, srcstride, height, picreg, my lea myd, [myq*3] @@ -314,7 +314,7 @@ cglobal put_vp8_epel%1_v6, 7, 7, 8, dst, dststride, src, srcstride, height, picr add srcq, srcstrideq dec heightd ; next row jg .nextrow - REP_RET + RET %endmacro INIT_MMX ssse3 @@ -368,7 +368,7 @@ cglobal put_vp8_epel4_h4, 6, 6 + npicregs, 0, dst, dststride, src, srcstride, he add srcq, srcstrideq dec heightd ; next row jg .nextrow - REP_RET + RET ; 4x4 block, H-only 6-tap filter INIT_MMX mmxext @@ -426,7 +426,7 @@ cglobal put_vp8_epel4_h6, 6, 6 + npicregs, 0, dst, dststride, src, srcstride, he add srcq, srcstrideq dec heightd ; next row jg .nextrow - REP_RET + RET INIT_XMM sse2 cglobal put_vp8_epel8_h4, 6, 6 + npicregs, 10, dst, dststride, src, srcstride, height, mx, picreg @@ -474,7 +474,7 @@ cglobal put_vp8_epel8_h4, 6, 6 + npicregs, 10, dst, dststride, src, srcstride, h add srcq, srcstrideq dec heightd ; next row jg .nextrow - REP_RET + RET INIT_XMM sse2 cglobal put_vp8_epel8_h6, 6, 6 + npicregs, 14, dst, dststride, src, srcstride, height, mx, picreg @@ -537,7 +537,7 @@ cglobal put_vp8_epel8_h6, 6, 6 + npicregs, 14, dst, dststride, src, srcstride, h add srcq, srcstrideq dec heightd ; next row jg .nextrow - REP_RET + RET %macro FILTER_V 1 ; 4x4 block, V-only 4-tap filter @@ -590,7 +590,7 @@ cglobal put_vp8_epel%1_v4, 7, 7, 8, dst, dststride, src, srcstride, height, picr add srcq, srcstrideq dec heightd ; next row jg .nextrow - REP_RET + RET ; 4x4 block, V-only 6-tap filter @@ -655,7 +655,7 @@ cglobal put_vp8_epel%1_v6, 7, 7, 8, dst, dststride, src, srcstride, height, picr add srcq, srcstrideq dec heightd ; next row jg .nextrow - REP_RET + RET %endmacro INIT_MMX mmxext @@ -738,7 +738,7 @@ cglobal put_vp8_bilinear%1_v, 7, 7, 7, dst, dststride, src, srcstride, height, p lea srcq, [srcq+srcstrideq*2] sub heightd, 2 jg .nextrow - REP_RET + RET %if cpuflag(ssse3) cglobal put_vp8_bilinear%1_h, 6, 6 + npicregs, 5, dst, dststride, src, srcstride, height, mx, picreg @@ -815,7 +815,7 @@ cglobal put_vp8_bilinear%1_h, 6, 6 + npicregs, 7, dst, dststride, src, srcstride lea srcq, [srcq+srcstrideq*2] sub heightd, 2 jg .nextrow - REP_RET + RET %endmacro INIT_MMX mmxext @@ -838,7 +838,7 @@ cglobal put_vp8_pixels8, 5, 5, 0, dst, dststride, src, srcstride, height lea dstq, [dstq+dststrideq*2] sub heightd, 2 jg .nextrow - REP_RET + RET INIT_XMM sse cglobal put_vp8_pixels16, 5, 5, 2, dst, dststride, src, srcstride, height @@ -851,7 +851,7 @@ cglobal put_vp8_pixels16, 5, 5, 2, dst, dststride, src, srcstride, height lea dstq, [dstq+dststrideq*2] sub heightd, 2 jg .nextrow - REP_RET + RET ;----------------------------------------------------------------------------- ; void ff_vp8_idct_dc_add_(uint8_t *dst, int16_t block[16], ptrdiff_t stride); diff --git a/libavfilter/x86/af_volume.asm b/libavfilter/x86/af_volume.asm index 723ab1f8fb6..35a00784a2d 100644 --- a/libavfilter/x86/af_volume.asm +++ b/libavfilter/x86/af_volume.asm @@ -56,7 +56,7 @@ cglobal scale_samples_s16, 4,4,4, dst, src, len, volume mova [dstq+lenq], m3 sub lenq, mmsize jge .loop - REP_RET + RET ;------------------------------------------------------------------------------ ; void ff_scale_samples_s32(uint8_t *dst, const uint8_t *src, int len, @@ -93,7 +93,7 @@ cglobal scale_samples_s32, 4,4,4, dst, src, len, volume %endif sub lenq, mmsize jge .loop - REP_RET + RET %endmacro INIT_XMM sse2 @@ -137,4 +137,4 @@ cglobal scale_samples_s32, 4,4,8, dst, src, len, volume mova [dstq+lenq], m0 sub lenq, mmsize jge .loop - REP_RET + RET diff --git a/libavfilter/x86/avf_showcqt.asm b/libavfilter/x86/avf_showcqt.asm index 63e58408cda..16af0de9b0e 100644 --- a/libavfilter/x86/avf_showcqt.asm +++ b/libavfilter/x86/avf_showcqt.asm @@ -127,7 +127,7 @@ cglobal showcqt_cqt_calc, 5, 10, 12, dst, src, coeffs, len, fft_len, x, coeffs_v lea dstq, [dstq + 16] lea coeffsq, [coeffsq + 2*Coeffs.sizeof] jnz .loop_k - REP_RET + RET align 16 .check_loop_a: cmp xd, [coeffsq + Coeffs.len] @@ -170,7 +170,7 @@ cglobal showcqt_cqt_calc, 4, 7, 8, dst, src, coeffs, len, x, coeffs_val, i lea dstq, [dstq + 8] lea coeffsq, [coeffsq + Coeffs.sizeof] jnz .loop_k - REP_RET + RET %endif ; ARCH_X86_64 %endmacro ; DECLARE_CQT_CALC diff --git a/libavfilter/x86/scene_sad.asm b/libavfilter/x86/scene_sad.asm index d38d71ccca1..bf7236b3a3b 100644 --- a/libavfilter/x86/scene_sad.asm +++ b/libavfilter/x86/scene_sad.asm @@ -53,7 +53,7 @@ cglobal scene_sad, 6, 7, 2, src1, stride1, src2, stride2, width, end, x mov r0q, r6mp movu [r0q], m1 ; sum -REP_RET +RET %endmacro diff --git a/libavfilter/x86/vf_blend.asm b/libavfilter/x86/vf_blend.asm index 277b100e4d5..362020ec959 100644 --- a/libavfilter/x86/vf_blend.asm +++ b/libavfilter/x86/vf_blend.asm @@ -63,7 +63,7 @@ cglobal blend_%1, 5, 7, %2, top, top_linesize, bottom, bottom_linesize, dst, end add dstq, dst_linesizeq sub endd, 1 jg .nextrow -REP_RET +RET %endmacro %macro BLEND_SIMPLE 2-3 0 diff --git a/libavfilter/x86/vf_framerate.asm b/libavfilter/x86/vf_framerate.asm index 7a30c870bd5..b5505b4ff8c 100644 --- a/libavfilter/x86/vf_framerate.asm +++ b/libavfilter/x86/vf_framerate.asm @@ -84,7 +84,7 @@ cglobal blend_frames%1, 5, 7, 5, src1, src1_linesize, src2, src2_linesize, dst, add dstq, dst_linesizeq sub endd, 1 jg .nextrow -REP_RET +RET %endmacro diff --git a/libavfilter/x86/vf_gradfun.asm b/libavfilter/x86/vf_gradfun.asm index 3581f89fe88..d106d521008 100644 --- a/libavfilter/x86/vf_gradfun.asm +++ b/libavfilter/x86/vf_gradfun.asm @@ -64,7 +64,7 @@ cglobal gradfun_filter_line, 6, 6 add r0, 4 jl .loop .end: - REP_RET + RET INIT_XMM ssse3 cglobal gradfun_filter_line, 6, 6, 8 @@ -78,7 +78,7 @@ cglobal gradfun_filter_line, 6, 6, 8 FILTER_LINE m4 add r0, 8 jl .loop - REP_RET + RET %macro BLUR_LINE 1 cglobal gradfun_blur_line_%1, 6, 6, 8 @@ -102,7 +102,7 @@ cglobal gradfun_blur_line_%1, 6, 6, 8 mova [r3+r0], m0 add r0, 16 jl .loop - REP_RET + RET %endmacro INIT_XMM sse2 diff --git a/libavfilter/x86/vf_hqdn3d.asm b/libavfilter/x86/vf_hqdn3d.asm index e3b1bdca53b..2c0ca455718 100644 --- a/libavfilter/x86/vf_hqdn3d.asm +++ b/libavfilter/x86/vf_hqdn3d.asm @@ -97,7 +97,7 @@ ALIGN 16 inc xq jl .loop je .loop2 - REP_RET + RET %endmacro ; HQDN3D_ROW HQDN3D_ROW 8 diff --git a/libavfilter/x86/vf_interlace.asm b/libavfilter/x86/vf_interlace.asm index f4a405c7543..c28f9fbe3e5 100644 --- a/libavfilter/x86/vf_interlace.asm +++ b/libavfilter/x86/vf_interlace.asm @@ -73,7 +73,7 @@ SECTION .text jl .loop .end: - REP_RET + RET %endmacro %macro LOWPASS_LINE 0 @@ -146,7 +146,7 @@ cglobal lowpass_line_complex, 5, 5, 8, dst, h, src, mref, pref add srcq, mmsize sub hd, mmsize jg .loop -REP_RET +RET cglobal lowpass_line_complex_12, 5, 5, 8, 16, dst, h, src, mref, pref, clip_max movd m7, DWORD clip_maxm @@ -208,7 +208,7 @@ cglobal lowpass_line_complex_12, 5, 5, 8, 16, dst, h, src, mref, pref, clip_max add srcq, 2*mmsize sub hd, mmsize jg .loop -REP_RET +RET %endmacro INIT_XMM sse2 diff --git a/libavfilter/x86/vf_maskedmerge.asm b/libavfilter/x86/vf_maskedmerge.asm index 10282990874..d9bd4688fd1 100644 --- a/libavfilter/x86/vf_maskedmerge.asm +++ b/libavfilter/x86/vf_maskedmerge.asm @@ -81,4 +81,4 @@ cglobal maskedmerge8, 5, 7, 8, bsrc, osrc, msrc, dst, blinesize, w, x add dstq, dlinesizeq sub hd, 1 jg .nextrow -REP_RET +RET diff --git a/libavfilter/x86/vf_stereo3d.asm b/libavfilter/x86/vf_stereo3d.asm index a057e495f18..b6a293b18e2 100644 --- a/libavfilter/x86/vf_stereo3d.asm +++ b/libavfilter/x86/vf_stereo3d.asm @@ -213,4 +213,4 @@ cglobal anaglyph, 3, 6, 8, 2*9*mmsize, dst, lsrc, rsrc, dst_linesize, o, cnt add rsrcq, r_linesizeq sub heightd, 1 jg .nextrow -REP_RET +RET diff --git a/libavfilter/x86/vf_w3fdif.asm b/libavfilter/x86/vf_w3fdif.asm index 52628c38d79..3010469f97f 100644 --- a/libavfilter/x86/vf_w3fdif.asm +++ b/libavfilter/x86/vf_w3fdif.asm @@ -38,7 +38,7 @@ cglobal w3fdif_scale, 3, 3, 2, 0, out_pixel, work_pixel, linesize add work_pixelq, mmsize*2 sub linesized, mmsize/2 jg .loop -REP_RET +RET cglobal w3fdif_simple_low, 4, 5, 6, 0, work_line, in_lines_cur0, coef, linesize, offset movd m1, [coefq] @@ -63,7 +63,7 @@ cglobal w3fdif_simple_low, 4, 5, 6, 0, work_line, in_lines_cur0, coef, linesize, add offsetq, mmsize/2 sub linesized, mmsize/2 jg .loop -REP_RET +RET cglobal w3fdif_complex_low, 4, 7, 8, 0, work_line, in_lines_cur0, coef, linesize movq m0, [coefq] @@ -99,7 +99,7 @@ cglobal w3fdif_complex_low, 4, 7, 8, 0, work_line, in_lines_cur0, coef, linesize add offsetq, mmsize/2 sub linesized, mmsize/2 jg .loop -REP_RET +RET %if ARCH_X86_64 cglobal w3fdif_simple_high, 5, 9, 8, 0, work_line, in_lines_cur0, in_lines_adj0, coef, linesize @@ -179,7 +179,7 @@ cglobal w3fdif_simple_high, 4, 7, 8, 0, work_line, in_lines_cur0, in_lines_adj0, add offsetq, mmsize/2 sub linesized, mmsize/2 jg .loop -REP_RET +RET %if ARCH_X86_64 @@ -254,6 +254,6 @@ cglobal w3fdif_complex_high, 5, 13, 10, 0, work_line, in_lines_cur0, in_lines_ad add offsetq, mmsize/2 sub linesized, mmsize/2 jg .loop -REP_RET +RET %endif diff --git a/libavutil/x86/float_dsp.asm b/libavutil/x86/float_dsp.asm index ff608f5f5a8..e84ba525668 100644 --- a/libavutil/x86/float_dsp.asm +++ b/libavutil/x86/float_dsp.asm @@ -48,7 +48,7 @@ ALIGN 16 sub lenq, 64 jge .loop - REP_RET + RET %endmacro INIT_XMM sse @@ -141,7 +141,7 @@ cglobal vector_fmac_scalar, 4,4,5, dst, src, mul, len %endif ; mmsize sub lenq, 64 jge .loop - REP_RET + RET %endmacro INIT_XMM sse @@ -178,7 +178,7 @@ cglobal vector_fmul_scalar, 4,4,3, dst, src, mul, len mova [dstq+lenq], m1 sub lenq, mmsize jge .loop - REP_RET + RET %endmacro INIT_XMM sse @@ -233,7 +233,7 @@ cglobal vector_dmac_scalar, 4,4,5, dst, src, mul, len movaps [dstq+lenq+3*mmsize], m4 sub lenq, mmsize*4 jge .loop - REP_RET + RET %endmacro INIT_XMM sse2 @@ -280,7 +280,7 @@ cglobal vector_dmul_scalar, 4,4,3, dst, src, mul, len movaps [dstq+lenq+mmsize], m2 sub lenq, 2*mmsize jge .loop - REP_RET + RET %endmacro INIT_XMM sse2 @@ -323,7 +323,7 @@ cglobal vector_fmul_window, 5, 6, 6, dst, src0, src1, win, len, len1 sub len1q, mmsize add lenq, mmsize jl .loop - REP_RET + RET ;----------------------------------------------------------------------------- ; vector_fmul_add(float *dst, const float *src0, const float *src1, @@ -352,7 +352,7 @@ ALIGN 16 sub lenq, 2*mmsize jge .loop - REP_RET + RET %endmacro INIT_XMM sse @@ -401,7 +401,7 @@ ALIGN 16 add src1q, 2*mmsize sub lenq, 2*mmsize jge .loop - REP_RET + RET %endmacro INIT_XMM sse @@ -585,4 +585,4 @@ cglobal butterflies_float, 3,3,3, src0, src1, len mova [src0q + lenq], m0 add lenq, mmsize jl .loop - REP_RET + RET diff --git a/libavutil/x86/lls.asm b/libavutil/x86/lls.asm index d2526d1ff48..e8141e6c4ff 100644 --- a/libavutil/x86/lls.asm +++ b/libavutil/x86/lls.asm @@ -123,7 +123,7 @@ cglobal update_lls, 2,5,8, ctx, var, i, j, covar2 test id, id jle .loop2x1 .ret: - REP_RET + RET %macro UPDATE_LLS 0 cglobal update_lls, 3,6,8, ctx, var, count, i, j, count2 @@ -240,7 +240,7 @@ cglobal update_lls, 3,6,8, ctx, var, count, i, j, count2 cmp id, countd jle .loop2x1 .ret: - REP_RET + RET %endmacro ; UPDATE_LLS %if HAVE_AVX_EXTERNAL diff --git a/libswresample/x86/audio_convert.asm b/libswresample/x86/audio_convert.asm index d6d6a814957..ad65008e230 100644 --- a/libswresample/x86/audio_convert.asm +++ b/libswresample/x86/audio_convert.asm @@ -85,7 +85,7 @@ pack_2ch_%2_to_%1_u_int %+ SUFFIX: add lenq, 2*mmsize/(2<<%4) %endif jl .next - REP_RET + RET %endmacro %macro UNPACK_2CH 5-7 @@ -157,7 +157,7 @@ unpack_2ch_%2_to_%1_u_int %+ SUFFIX: add lenq, mmsize/(1<<%4) %endif jl .next - REP_RET + RET %endmacro %macro CONV 5-7 @@ -198,7 +198,7 @@ cglobal %2_to_%1_%3, 3, 3, 6, dst, src, len emms RET %else - REP_RET + RET %endif %endmacro @@ -301,7 +301,7 @@ pack_6ch_%2_to_%1_u_int %+ SUFFIX: emms RET %else - REP_RET + RET %endif %endmacro @@ -375,7 +375,7 @@ unpack_6ch_%2_to_%1_u_int %+ SUFFIX: add dstq, mmsize sub lend, mmsize/4 jg .loop - REP_RET + RET %endmacro %define PACK_8CH_GPRS (10 * ARCH_X86_64) + ((6 + HAVE_ALIGNED_STACK) * ARCH_X86_32) @@ -525,7 +525,7 @@ pack_8ch_%2_to_%1_u_int %+ SUFFIX: %endif sub lend, mmsize/4 jg .loop - REP_RET + RET %endmacro %macro INT16_TO_INT32_N 6 diff --git a/libswresample/x86/rematrix.asm b/libswresample/x86/rematrix.asm index 968010701e8..e2b2a863179 100644 --- a/libswresample/x86/rematrix.asm +++ b/libswresample/x86/rematrix.asm @@ -68,7 +68,7 @@ mix_2_1_float_u_int %+ SUFFIX: mov%1 [outq + lenq + mmsize], m2 add lenq, mmsize*2 jl .next - REP_RET + RET %endmacro %macro MIX1_FLT 1 @@ -100,7 +100,7 @@ mix_1_1_float_u_int %+ SUFFIX: mov%1 [outq + lenq + mmsize], m1 add lenq, mmsize*2 jl .next - REP_RET + RET %endmacro %macro MIX1_INT16 1 @@ -152,7 +152,7 @@ mix_1_1_int16_u_int %+ SUFFIX: emms RET %else - REP_RET + RET %endif %endmacro @@ -218,7 +218,7 @@ mix_2_1_int16_u_int %+ SUFFIX: emms RET %else - REP_RET + RET %endif %endmacro diff --git a/libswscale/x86/input.asm b/libswscale/x86/input.asm index 6de6733faa5..a197183f1f7 100644 --- a/libswscale/x86/input.asm +++ b/libswscale/x86/input.asm @@ -207,7 +207,7 @@ cglobal %2 %+ 24ToY, 6, 6, %1, dst, src, u1, u2, w, table mova [dstq+wq], m0 add wq, mmsize jl .loop - REP_RET + RET %endif ; ARCH_X86_64 && %0 == 3 %endmacro @@ -313,7 +313,7 @@ cglobal %2 %+ 24ToUV, 7, 7, %1, dstU, dstV, u1, src, u2, w, table mova [dstVq+wq], m2 add wq, mmsize jl .loop - REP_RET + RET %endif ; ARCH_X86_64 && %0 == 3 %endmacro @@ -394,7 +394,7 @@ cglobal %2%3%4%5 %+ ToY, 6, 6, %1, dst, src, u1, u2, w, table add wq, 2 jl .loop2 .end: - REP_RET + RET %endif ; %0 == 3 %endmacro @@ -491,7 +491,7 @@ cglobal %2%3%4%5 %+ ToUV, 7, 7, %1, dstU, dstV, u1, src, u2, w, table add wq, 2 jl .loop2 .end: - REP_RET + RET %endif ; ARCH_X86_64 && %0 == 3 %endmacro @@ -543,7 +543,7 @@ RGB32_FUNCS 8, 12 mova [dstq+wq], m0 add wq, mmsize jl .loop_%1 - REP_RET + RET %endmacro ; %1 = nr. of XMM registers @@ -599,7 +599,7 @@ cglobal %2ToY, 5, 5, %1, dst, unused0, unused1, src, w movhps [dstVq+wq], m1 add wq, mmsize / 2 jl .loop_%1 - REP_RET + RET %endmacro ; %1 = nr. of XMM registers @@ -657,7 +657,7 @@ cglobal %2ToUV, 4, 5, %1, dstU, dstV, unused, src, w %endif ; nv12/21 add wq, mmsize jl .loop_%1 - REP_RET + RET %endmacro ; %1 = nr. of XMM registers diff --git a/libswscale/x86/output.asm b/libswscale/x86/output.asm index f943a275347..95ec2fa8850 100644 --- a/libswscale/x86/output.asm +++ b/libswscale/x86/output.asm @@ -297,7 +297,7 @@ cglobal yuv2planeX_%1, %3, 8, %2, filter, fltsize, src, dst, w, dither, offset test dstq, 15 jnz .unaligned yuv2planeX_mainloop %1, a - REP_RET + RET .unaligned: yuv2planeX_mainloop %1, u %endif ; mmsize == 8/16 @@ -307,10 +307,10 @@ cglobal yuv2planeX_%1, %3, 8, %2, filter, fltsize, src, dst, w, dither, offset ADD rsp, pad RET %else ; x86-64 - REP_RET + RET %endif ; x86-32/64 %else ; %1 == 9/10/16 - REP_RET + RET %endif ; %1 == 8/9/10/16 %endmacro @@ -433,10 +433,10 @@ cglobal yuv2plane1_%1, %3, %3, %2, src, dst, w, dither, offset test dstq, 15 jnz .unaligned yuv2plane1_mainloop %1, a - REP_RET + RET .unaligned: yuv2plane1_mainloop %1, u - REP_RET + RET %endmacro INIT_XMM sse2 diff --git a/libswscale/x86/scale.asm b/libswscale/x86/scale.asm index c62ae3dcc27..2e14c8c0232 100644 --- a/libswscale/x86/scale.asm +++ b/libswscale/x86/scale.asm @@ -357,7 +357,7 @@ cglobal hscale%1to%2_%4, %5, 10, %6, pos0, dst, w, srcmem, filter, fltpos, fltsi add wq, 2 %endif ; %3 ==/!= X jl .loop - REP_RET + RET %endmacro ; SCALE_FUNCS source_width, intermediate_nbits, n_xmm diff --git a/libswscale/x86/scale_avx2.asm b/libswscale/x86/scale_avx2.asm index 37095e596ad..179895666a7 100644 --- a/libswscale/x86/scale_avx2.asm +++ b/libswscale/x86/scale_avx2.asm @@ -144,7 +144,7 @@ cglobal hscale8to15_%1, 7, 9, 16, pos0, dst, w, srcmem, filter, fltpos, fltsize, cmp countq, wq jl .tail_loop .end: -REP_RET +RET %endmacro %if ARCH_X86_64 diff --git a/libswscale/x86/yuv2yuvX.asm b/libswscale/x86/yuv2yuvX.asm index d5b03495fda..369c850674d 100644 --- a/libswscale/x86/yuv2yuvX.asm +++ b/libswscale/x86/yuv2yuvX.asm @@ -121,7 +121,7 @@ cglobal yuv2yuvX, 7, 7, 8, filter, filterSize, src, dest, dstW, dither, offset mov filterSizeq, filterq cmp offsetq, dstWq jb .outerloop - REP_RET + RET %endmacro INIT_MMX mmxext diff --git a/libswscale/x86/yuv_2_rgb.asm b/libswscale/x86/yuv_2_rgb.asm index c5fa3ee690e..e3470fd9ad4 100644 --- a/libswscale/x86/yuv_2_rgb.asm +++ b/libswscale/x86/yuv_2_rgb.asm @@ -354,7 +354,7 @@ add imageq, 8 * depth * time_num add indexq, 4 * time_num js .loop0 -REP_RET +RET %endmacro diff --git a/tests/checkasm/x86/checkasm.asm b/tests/checkasm/x86/checkasm.asm index 683aae80e36..ab11bcba649 100644 --- a/tests/checkasm/x86/checkasm.asm +++ b/tests/checkasm/x86/checkasm.asm @@ -234,7 +234,7 @@ cglobal checked_call%1, 1,7 .emms_ok: %endif add esp, max_args*4 - REP_RET + RET %endmacro %endif ; ARCH_X86_64 From 35871c26d25fd9735a26848af7d9d65684990e6c Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Mon, 30 Jan 2023 19:53:22 +0100 Subject: [PATCH 0142/2172] tools/target_dec_fuzzer: Adjust threshold for BONK The decoder is quite slow with max n taps Fixes: Timeout Fixes: 54063/clusterfuzz-testcase-minimized-ffmpeg_AV_CODEC_ID_BONK_fuzzer-5087362407596032 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 a20345db5c6..127d534c9de 100644 --- a/tools/target_dec_fuzzer.c +++ b/tools/target_dec_fuzzer.c @@ -215,6 +215,7 @@ int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { case AV_CODEC_ID_ARGO: maxpixels /= 1024; break; case AV_CODEC_ID_BETHSOFTVID: maxpixels /= 8192; break; case AV_CODEC_ID_BINKVIDEO: maxpixels /= 32; break; + case AV_CODEC_ID_BONK: maxsamples /= 1<<20; break; case AV_CODEC_ID_CDTOONS: maxpixels /= 1024; break; case AV_CODEC_ID_CFHD: maxpixels /= 16384; break; case AV_CODEC_ID_CINEPAK: maxpixels /= 128; break; From ad95d9c855db3e78e6495ea52e5fd2e089320d74 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Mon, 30 Jan 2023 23:08:14 +0100 Subject: [PATCH 0143/2172] avformat/lafdec: Check if all data was read Fixes: OOM Fixes: 54572/clusterfuzz-testcase-minimized-ffmpeg_dem_LAF_fuzzer-4974038870523904 Found-by: continuous fuzzing process https://github.com/google/oss-fuzz/tree/master/projects/ffmpeg Signed-off-by: Michael Niedermayer --- libavformat/lafdec.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libavformat/lafdec.c b/libavformat/lafdec.c index d02b479c4d1..a1775e1b698 100644 --- a/libavformat/lafdec.c +++ b/libavformat/lafdec.c @@ -21,6 +21,7 @@ #include "libavutil/intreadwrite.h" #include "avformat.h" +#include "avio_internal.h" #include "internal.h" #define MAX_STREAMS 4096 @@ -205,7 +206,7 @@ static int laf_read_packet(AVFormatContext *ctx, AVPacket *pkt) s->nb_stored = st_count; if (!st_count) return AVERROR_INVALIDDATA; - ret = avio_read(pb, s->data, st_count * st->codecpar->sample_rate * bpp); + ret = ffio_read_size(pb, s->data, st_count * st->codecpar->sample_rate * bpp); if (ret < 0) return ret; } From f4b4e16641184b2414e5822c49fa5f6f9a57f2fb Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Mon, 30 Jan 2023 23:18:49 +0100 Subject: [PATCH 0144/2172] libavformat/lafdec: free data Fixes: memleak Signed-off-by: Michael Niedermayer --- libavformat/lafdec.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/libavformat/lafdec.c b/libavformat/lafdec.c index a1775e1b698..d6ef8415a95 100644 --- a/libavformat/lafdec.c +++ b/libavformat/lafdec.c @@ -252,6 +252,15 @@ static int laf_read_packet(AVFormatContext *ctx, AVPacket *pkt) return 0; } +static int laf_read_close(AVFormatContext *ctx) +{ + LAFContext *s = ctx->priv_data; + + av_freep(&s->data); + + return 0; +} + static int laf_read_seek(AVFormatContext *ctx, int stream_index, int64_t timestamp, int flags) { @@ -269,7 +278,9 @@ const AVInputFormat ff_laf_demuxer = { .read_probe = laf_probe, .read_header = laf_read_header, .read_packet = laf_read_packet, + .read_close = laf_read_close, .read_seek = laf_read_seek, .extensions = "laf", .flags = AVFMT_GENERIC_INDEX, + .flags_internal = FF_FMT_INIT_CLEANUP, }; From 7d49fef8b426041e22fde77771b435d9411241a0 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Tue, 31 Jan 2023 14:14:47 +0100 Subject: [PATCH 0145/2172] lavc/vaapi_encode: fix propagating durations and opaques input_image is freed by the time the output packet is constructed, so we need to store copies in VAAPIEncodePicture. --- libavcodec/vaapi_encode.c | 22 +++++++++++++++++----- libavcodec/vaapi_encode.h | 4 ++++ 2 files changed, 21 insertions(+), 5 deletions(-) diff --git a/libavcodec/vaapi_encode.c b/libavcodec/vaapi_encode.c index 6787b90e8d6..bfca315a7ad 100644 --- a/libavcodec/vaapi_encode.c +++ b/libavcodec/vaapi_encode.c @@ -695,7 +695,7 @@ static int vaapi_encode_output(AVCodecContext *avctx, pkt->flags |= AV_PKT_FLAG_KEY; pkt->pts = pic->pts; - pkt->duration = pic->input_image->duration; + pkt->duration = pic->duration; vas = vaUnmapBuffer(ctx->hwctx->display, pic->output_buffer); if (vas != VA_STATUS_SUCCESS) { @@ -706,10 +706,11 @@ static int vaapi_encode_output(AVCodecContext *avctx, } // for no-delay encoders this is handled in generic codec - if (avctx->codec->capabilities & AV_CODEC_CAP_DELAY) { - err = ff_encode_reordered_opaque(avctx, pkt, pic->input_image); - if (err < 0) - goto fail; + if (avctx->codec->capabilities & AV_CODEC_CAP_DELAY && + avctx->flags & AV_CODEC_FLAG_COPY_OPAQUE) { + pkt->opaque = pic->opaque; + pkt->opaque_ref = pic->opaque_ref; + pic->opaque_ref = NULL; } av_buffer_unref(&pic->output_buffer_ref); @@ -785,6 +786,8 @@ static int vaapi_encode_free(AVCodecContext *avctx, av_frame_free(&pic->input_image); av_frame_free(&pic->recon_image); + av_buffer_unref(&pic->opaque_ref); + av_freep(&pic->param_buffers); av_freep(&pic->slices); // Output buffer should already be destroyed. @@ -1152,6 +1155,15 @@ static int vaapi_encode_send_frame(AVCodecContext *avctx, AVFrame *frame) pic->input_surface = (VASurfaceID)(uintptr_t)frame->data[3]; pic->pts = frame->pts; + pic->duration = frame->duration; + + if (avctx->flags & AV_CODEC_FLAG_COPY_OPAQUE) { + err = av_buffer_replace(&pic->opaque_ref, frame->opaque_ref); + if (err < 0) + goto fail; + + pic->opaque = frame->opaque; + } av_frame_move_ref(pic->input_image, frame); diff --git a/libavcodec/vaapi_encode.h b/libavcodec/vaapi_encode.h index 359f954ffff..a1e639f56b0 100644 --- a/libavcodec/vaapi_encode.h +++ b/libavcodec/vaapi_encode.h @@ -75,8 +75,12 @@ typedef struct VAAPIEncodePicture { int64_t display_order; int64_t encode_order; int64_t pts; + int64_t duration; int force_idr; + void *opaque; + AVBufferRef *opaque_ref; + #if VA_CHECK_VERSION(1, 0, 0) // ROI regions. VAEncROI *roi; From 077e63496581edf02e503e7d99dbc4e1a5670246 Mon Sep 17 00:00:00 2001 From: Haihao Xiang Date: Mon, 30 Jan 2023 09:37:17 +0800 Subject: [PATCH 0146/2172] lavfi/vpp_qsv: add rate option This is used to control the output at frame rate or field rate when deinterlace is expected and framerate is not specified. Signed-off-by: Haihao Xiang --- libavfilter/vf_vpp_qsv.c | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/libavfilter/vf_vpp_qsv.c b/libavfilter/vf_vpp_qsv.c index 34e530e244e..aac0a234c30 100644 --- a/libavfilter/vf_vpp_qsv.c +++ b/libavfilter/vf_vpp_qsv.c @@ -101,6 +101,7 @@ typedef struct VPPContext{ char *output_format_str; int has_passthrough; /* apply pass through mode if possible */ + int field_rate; /* Generate output at frame rate or field rate for deinterlace mode, 0: frame, 1: field */ } VPPContext; static const char *const var_names[] = { @@ -255,9 +256,14 @@ static int config_input(AVFilterLink *inlink) int ret; int64_t ow, oh; - if (vpp->framerate.den == 0 || vpp->framerate.num == 0) + if (vpp->framerate.den == 0 || vpp->framerate.num == 0) { vpp->framerate = inlink->frame_rate; + if (vpp->deinterlace && vpp->field_rate) + vpp->framerate = av_mul_q(inlink->frame_rate, + (AVRational){ 2, 1 }); + } + if (av_cmp_q(vpp->framerate, inlink->frame_rate)) vpp->use_frc = 1; @@ -352,7 +358,7 @@ static int config_output(AVFilterLink *outlink) outlink->w = vpp->out_width; outlink->h = vpp->out_height; outlink->frame_rate = vpp->framerate; - outlink->time_base = inlink->time_base; + outlink->time_base = av_inv_q(vpp->framerate); param.filter_frame = NULL; param.num_ext_buf = 0; @@ -678,6 +684,13 @@ static const AVOption vpp_options[] = { { "low_power", "low power mode", 0, AV_OPT_TYPE_CONST, { .i64 = MFX_SCALING_MODE_LOWPOWER}, INT_MIN, INT_MAX, FLAGS, "scale mode"}, { "hq", "high quality mode", 0, AV_OPT_TYPE_CONST, { .i64 = MFX_SCALING_MODE_QUALITY}, INT_MIN, INT_MAX, FLAGS, "scale mode"}, + { "rate", "Generate output at frame rate or field rate, available only for deinterlace mode", + OFFSET(field_rate), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 1, FLAGS, "rate" }, + { "frame", "Output at frame rate (one frame of output for each field-pair)", + 0, AV_OPT_TYPE_CONST, { .i64 = 0 }, 0, 0, FLAGS, "rate" }, + { "field", "Output at field rate (one frame of output for each field)", + 0, AV_OPT_TYPE_CONST, { .i64 = 1 }, 0, 0, FLAGS, "rate" }, + { NULL } }; From a48c95d3c9c404c9139f7fc4eb7ae8bdf6fe0eaa Mon Sep 17 00:00:00 2001 From: Haihao Xiang Date: Mon, 30 Jan 2023 09:37:18 +0800 Subject: [PATCH 0147/2172] lavfi/deinterlace_qsv: simplify deinterlace_qsv filter Like what we did for scale_qsv filter, we use QSVVPPContext as a base context to manage MFX session for deinterlace_qsv filter. Signed-off-by: Haihao Xiang --- configure | 1 + libavfilter/vf_deinterlace_qsv.c | 505 ++----------------------------- 2 files changed, 31 insertions(+), 475 deletions(-) diff --git a/configure b/configure index 9d78a244a3a..c726076da1a 100755 --- a/configure +++ b/configure @@ -3649,6 +3649,7 @@ coreimagesrc_filter_extralibs="-framework OpenGL" cover_rect_filter_deps="avcodec avformat gpl" cropdetect_filter_deps="gpl" deinterlace_qsv_filter_deps="libmfx" +deinterlace_qsv_filter_select="qsvvpp" deinterlace_vaapi_filter_deps="vaapi" delogo_filter_deps="gpl" denoise_vaapi_filter_deps="vaapi" diff --git a/libavfilter/vf_deinterlace_qsv.c b/libavfilter/vf_deinterlace_qsv.c index 6c94923f02f..8173386780a 100644 --- a/libavfilter/vf_deinterlace_qsv.c +++ b/libavfilter/vf_deinterlace_qsv.c @@ -44,36 +44,10 @@ #define MFX_IMPL_VIA_MASK(impl) (0x0f00 & (impl)) -enum { - QSVDEINT_MORE_OUTPUT = 1, - QSVDEINT_MORE_INPUT, -}; - typedef struct QSVDeintContext { - const AVClass *class; - - AVBufferRef *hw_frames_ctx; - /* a clone of the main session, used internally for deinterlacing */ - mfxSession session; - - mfxMemId *mem_ids; - int nb_mem_ids; - - mfxFrameSurface1 **surface_ptrs; - int nb_surface_ptrs; - -#if QSV_HAVE_OPAQUE - mfxExtOpaqueSurfaceAlloc opaque_alloc; -#endif - mfxExtVPPDeinterlacing deint_conf; - mfxExtBuffer *ext_buffers[2]; - int num_ext_buffers; - - QSVFrame *work_frames; + QSVVPPContext qsv; - int64_t last_pts; - - int eof; + mfxExtVPPDeinterlacing deint_conf; /* option for Deinterlacing algorithm to be used */ int mode; @@ -81,476 +55,57 @@ typedef struct QSVDeintContext { static av_cold void qsvdeint_uninit(AVFilterContext *ctx) { - QSVDeintContext *s = ctx->priv; - QSVFrame *cur; - - if (s->session) { - MFXClose(s->session); - s->session = NULL; - } - av_buffer_unref(&s->hw_frames_ctx); - - cur = s->work_frames; - while (cur) { - s->work_frames = cur->next; - av_frame_free(&cur->frame); - av_freep(&cur); - cur = s->work_frames; - } - - av_freep(&s->mem_ids); - s->nb_mem_ids = 0; - - av_freep(&s->surface_ptrs); - s->nb_surface_ptrs = 0; -} - -static mfxStatus frame_alloc(mfxHDL pthis, mfxFrameAllocRequest *req, - mfxFrameAllocResponse *resp) -{ - AVFilterContext *ctx = pthis; - QSVDeintContext *s = ctx->priv; - - if (!(req->Type & MFX_MEMTYPE_VIDEO_MEMORY_PROCESSOR_TARGET) || - !(req->Type & (MFX_MEMTYPE_FROM_VPPIN | MFX_MEMTYPE_FROM_VPPOUT)) || - !(req->Type & MFX_MEMTYPE_EXTERNAL_FRAME)) - return MFX_ERR_UNSUPPORTED; - - resp->mids = s->mem_ids; - resp->NumFrameActual = s->nb_mem_ids; - - return MFX_ERR_NONE; -} - -static mfxStatus frame_free(mfxHDL pthis, mfxFrameAllocResponse *resp) -{ - return MFX_ERR_NONE; -} - -static mfxStatus frame_lock(mfxHDL pthis, mfxMemId mid, mfxFrameData *ptr) -{ - return MFX_ERR_UNSUPPORTED; -} - -static mfxStatus frame_unlock(mfxHDL pthis, mfxMemId mid, mfxFrameData *ptr) -{ - return MFX_ERR_UNSUPPORTED; -} - -static mfxStatus frame_get_hdl(mfxHDL pthis, mfxMemId mid, mfxHDL *hdl) -{ - mfxHDLPair *pair_dst = (mfxHDLPair*)hdl; - mfxHDLPair *pair_src = (mfxHDLPair*)mid; - - pair_dst->first = pair_src->first; - - if (pair_src->second != (mfxMemId)MFX_INFINITE) - pair_dst->second = pair_src->second; - return MFX_ERR_NONE; -} - -static int init_out_session(AVFilterContext *ctx) -{ - - QSVDeintContext *s = ctx->priv; - AVHWFramesContext *hw_frames_ctx = (AVHWFramesContext*)s->hw_frames_ctx->data; - AVQSVFramesContext *hw_frames_hwctx = hw_frames_ctx->hwctx; - AVQSVDeviceContext *device_hwctx = hw_frames_ctx->device_ctx->hwctx; - int opaque = 0; - mfxHDL handle = NULL; - mfxHandleType handle_type; - mfxVersion ver; - mfxIMPL impl; - mfxVideoParam par; - mfxStatus err; - int i, ret; - -#if QSV_HAVE_OPAQUE - opaque = !!(hw_frames_hwctx->frame_type & MFX_MEMTYPE_OPAQUE_FRAME); -#endif - /* extract the properties of the "master" session given to us */ - err = MFXQueryIMPL(device_hwctx->session, &impl); - if (err == MFX_ERR_NONE) - err = MFXQueryVersion(device_hwctx->session, &ver); - if (err != MFX_ERR_NONE) { - av_log(ctx, AV_LOG_ERROR, "Error querying the session attributes\n"); - return AVERROR_UNKNOWN; - } - - if (MFX_IMPL_VIA_VAAPI == MFX_IMPL_VIA_MASK(impl)) { - handle_type = MFX_HANDLE_VA_DISPLAY; - } else if (MFX_IMPL_VIA_D3D11 == MFX_IMPL_VIA_MASK(impl)) { - handle_type = MFX_HANDLE_D3D11_DEVICE; - } else if (MFX_IMPL_VIA_D3D9 == MFX_IMPL_VIA_MASK(impl)) { - handle_type = MFX_HANDLE_D3D9_DEVICE_MANAGER; - } else { - av_log(ctx, AV_LOG_ERROR, "Error unsupported handle type\n"); - return AVERROR_UNKNOWN; - } - - err = MFXVideoCORE_GetHandle(device_hwctx->session, handle_type, &handle); - if (err < 0) - return ff_qsvvpp_print_error(ctx, err, "Error getting the session handle"); - else if (err > 0) { - ff_qsvvpp_print_warning(ctx, err, "Warning in getting the session handle"); - return AVERROR_UNKNOWN; - } - - /* create a "slave" session with those same properties, to be used for - * actual deinterlacing */ - ret = ff_qsvvpp_create_mfx_session(ctx, device_hwctx->loader, impl, &ver, - &s->session); - if (ret) - return ret; - - if (handle) { - err = MFXVideoCORE_SetHandle(s->session, handle_type, handle); - if (err != MFX_ERR_NONE) - return AVERROR_UNKNOWN; - } - - if (QSV_RUNTIME_VERSION_ATLEAST(ver, 1, 25)) { - err = MFXJoinSession(device_hwctx->session, s->session); - if (err != MFX_ERR_NONE) - return AVERROR_UNKNOWN; - } - - memset(&par, 0, sizeof(par)); - - s->deint_conf.Header.BufferId = MFX_EXTBUFF_VPP_DEINTERLACING; - s->deint_conf.Header.BufferSz = sizeof(s->deint_conf); - s->deint_conf.Mode = s->mode; - - s->ext_buffers[s->num_ext_buffers++] = (mfxExtBuffer *)&s->deint_conf; - - if (!opaque) { - mfxFrameAllocator frame_allocator = { - .pthis = ctx, - .Alloc = frame_alloc, - .Lock = frame_lock, - .Unlock = frame_unlock, - .GetHDL = frame_get_hdl, - .Free = frame_free, - }; - - s->mem_ids = av_calloc(hw_frames_hwctx->nb_surfaces, - sizeof(*s->mem_ids)); - if (!s->mem_ids) - return AVERROR(ENOMEM); - for (i = 0; i < hw_frames_hwctx->nb_surfaces; i++) - s->mem_ids[i] = hw_frames_hwctx->surfaces[i].Data.MemId; - s->nb_mem_ids = hw_frames_hwctx->nb_surfaces; - - err = MFXVideoCORE_SetFrameAllocator(s->session, &frame_allocator); - if (err != MFX_ERR_NONE) - return AVERROR_UNKNOWN; - - par.IOPattern = MFX_IOPATTERN_IN_VIDEO_MEMORY | MFX_IOPATTERN_OUT_VIDEO_MEMORY; - } -#if QSV_HAVE_OPAQUE - else { - s->surface_ptrs = av_calloc(hw_frames_hwctx->nb_surfaces, - sizeof(*s->surface_ptrs)); - - if (!s->surface_ptrs) - return AVERROR(ENOMEM); - for (i = 0; i < hw_frames_hwctx->nb_surfaces; i++) - s->surface_ptrs[i] = hw_frames_hwctx->surfaces + i; - s->nb_surface_ptrs = hw_frames_hwctx->nb_surfaces; - - s->opaque_alloc.In.Surfaces = s->surface_ptrs; - s->opaque_alloc.In.NumSurface = s->nb_surface_ptrs; - s->opaque_alloc.In.Type = hw_frames_hwctx->frame_type; - - s->opaque_alloc.Out = s->opaque_alloc.In; - - s->opaque_alloc.Header.BufferId = MFX_EXTBUFF_OPAQUE_SURFACE_ALLOCATION; - s->opaque_alloc.Header.BufferSz = sizeof(s->opaque_alloc); - - s->ext_buffers[s->num_ext_buffers++] = (mfxExtBuffer *)&s->opaque_alloc; - - par.IOPattern = MFX_IOPATTERN_IN_OPAQUE_MEMORY | MFX_IOPATTERN_OUT_OPAQUE_MEMORY; - } -#endif - - par.ExtParam = s->ext_buffers; - par.NumExtParam = s->num_ext_buffers; - - par.AsyncDepth = 1; // TODO async - - par.vpp.In = hw_frames_hwctx->surfaces[0].Info; - - par.vpp.In.CropW = ctx->inputs[0]->w; - par.vpp.In.CropH = ctx->inputs[0]->h; - - if (ctx->inputs[0]->frame_rate.num) { - par.vpp.In.FrameRateExtN = ctx->inputs[0]->frame_rate.num; - par.vpp.In.FrameRateExtD = ctx->inputs[0]->frame_rate.den; - } else { - par.vpp.In.FrameRateExtN = ctx->inputs[0]->time_base.num; - par.vpp.In.FrameRateExtD = ctx->inputs[0]->time_base.den; - } - - par.vpp.Out = par.vpp.In; - - if (ctx->outputs[0]->frame_rate.num) { - par.vpp.Out.FrameRateExtN = ctx->outputs[0]->frame_rate.num; - par.vpp.Out.FrameRateExtD = ctx->outputs[0]->frame_rate.den; - } else { - par.vpp.Out.FrameRateExtN = ctx->outputs[0]->time_base.num; - par.vpp.Out.FrameRateExtD = ctx->outputs[0]->time_base.den; - } - - /* Print input memory mode */ - ff_qsvvpp_print_iopattern(ctx, par.IOPattern & 0x0F, "VPP"); - /* Print output memory mode */ - ff_qsvvpp_print_iopattern(ctx, par.IOPattern & 0xF0, "VPP"); - err = MFXVideoVPP_Init(s->session, &par); - if (err < 0) - return ff_qsvvpp_print_error(ctx, err, - "Error opening the VPP for deinterlacing"); - else if (err > 0) { - ff_qsvvpp_print_warning(ctx, err, - "Warning in VPP initialization"); - return AVERROR_UNKNOWN; - } - - return 0; + ff_qsvvpp_close(ctx); } static int qsvdeint_config_props(AVFilterLink *outlink) { AVFilterContext *ctx = outlink->src; AVFilterLink *inlink = ctx->inputs[0]; - QSVDeintContext *s = ctx->priv; - int ret; + QSVDeintContext *s = ctx->priv; + QSVVPPParam param = { NULL }; + mfxExtBuffer *ext_buf[1]; + enum AVPixelFormat in_format; qsvdeint_uninit(ctx); - s->last_pts = AV_NOPTS_VALUE; + outlink->w = inlink->w; + outlink->h = inlink->h; outlink->frame_rate = av_mul_q(inlink->frame_rate, (AVRational){ 2, 1 }); outlink->time_base = av_mul_q(inlink->time_base, (AVRational){ 1, 2 }); - /* check that we have a hw context */ - if (!inlink->hw_frames_ctx) { - av_log(ctx, AV_LOG_ERROR, "No hw context provided on input\n"); - return AVERROR(EINVAL); - } - - s->hw_frames_ctx = av_buffer_ref(inlink->hw_frames_ctx); - if (!s->hw_frames_ctx) - return AVERROR(ENOMEM); - - av_buffer_unref(&outlink->hw_frames_ctx); - outlink->hw_frames_ctx = av_buffer_ref(inlink->hw_frames_ctx); - if (!outlink->hw_frames_ctx) { - qsvdeint_uninit(ctx); - return AVERROR(ENOMEM); - } - - ret = init_out_session(ctx); - if (ret < 0) - return ret; - - - return 0; -} - -static void clear_unused_frames(QSVDeintContext *s) -{ - QSVFrame *cur = s->work_frames; - while (cur) { - if (!cur->surface.Data.Locked) { - av_frame_free(&cur->frame); - cur->queued = 0; - } - cur = cur->next; - } -} - -static int get_free_frame(QSVDeintContext *s, QSVFrame **f) -{ - QSVFrame *frame, **last; - - clear_unused_frames(s); - - frame = s->work_frames; - last = &s->work_frames; - while (frame) { - if (!frame->queued) { - *f = frame; - return 0; - } - - last = &frame->next; - frame = frame->next; - } - - frame = av_mallocz(sizeof(*frame)); - if (!frame) - return AVERROR(ENOMEM); - *last = frame; - *f = frame; - - return 0; -} - -static int submit_frame(AVFilterContext *ctx, AVFrame *frame, - mfxFrameSurface1 **surface) -{ - QSVDeintContext *s = ctx->priv; - QSVFrame *qf; - int ret; - - ret = get_free_frame(s, &qf); - if (ret < 0) - return ret; - - qf->frame = frame; - - qf->surface = *(mfxFrameSurface1*)qf->frame->data[3]; - - qf->surface.Data.Locked = 0; - qf->surface.Info.CropW = qf->frame->width; - qf->surface.Info.CropH = qf->frame->height; - - qf->surface.Info.PicStruct = !qf->frame->interlaced_frame ? MFX_PICSTRUCT_PROGRESSIVE : - (qf->frame->top_field_first ? MFX_PICSTRUCT_FIELD_TFF : - MFX_PICSTRUCT_FIELD_BFF); - if (qf->frame->repeat_pict == 1) { - qf->surface.Info.PicStruct |= MFX_PICSTRUCT_FIELD_REPEATED; - qf->surface.Info.PicStruct |= qf->frame->top_field_first ? MFX_PICSTRUCT_FIELD_TFF : - MFX_PICSTRUCT_FIELD_BFF; - } else if (qf->frame->repeat_pict == 2) - qf->surface.Info.PicStruct |= MFX_PICSTRUCT_FRAME_DOUBLING; - else if (qf->frame->repeat_pict == 4) - qf->surface.Info.PicStruct |= MFX_PICSTRUCT_FRAME_TRIPLING; - - if (ctx->inputs[0]->frame_rate.num) { - qf->surface.Info.FrameRateExtN = ctx->inputs[0]->frame_rate.num; - qf->surface.Info.FrameRateExtD = ctx->inputs[0]->frame_rate.den; - } else { - qf->surface.Info.FrameRateExtN = ctx->inputs[0]->time_base.num; - qf->surface.Info.FrameRateExtD = ctx->inputs[0]->time_base.den; - } - - qf->surface.Data.TimeStamp = av_rescale_q(qf->frame->pts, - ctx->inputs[0]->time_base, - (AVRational){1, 90000}); - - *surface = &qf->surface; - qf->queued = 1; - - return 0; -} - -static int process_frame(AVFilterContext *ctx, const AVFrame *in, - mfxFrameSurface1 *surf_in) -{ - QSVDeintContext *s = ctx->priv; - AVFilterLink *inlink = ctx->inputs[0]; - AVFilterLink *outlink = ctx->outputs[0]; - - AVFrame *out; - mfxFrameSurface1 *surf_out; - mfxSyncPoint sync = NULL; - mfxStatus err; - int ret, again = 0; + if (inlink->format == AV_PIX_FMT_QSV) { + if (!inlink->hw_frames_ctx || !inlink->hw_frames_ctx->data) + return AVERROR(EINVAL); + else + in_format = ((AVHWFramesContext*)inlink->hw_frames_ctx->data)->sw_format; + } else + in_format = inlink->format; - out = ff_get_video_buffer(outlink, outlink->w, outlink->h); - if (!out) { - ret = AVERROR(ENOMEM); - goto fail; - } + param.out_sw_format = in_format; + param.ext_buf = ext_buf; - surf_out = (mfxFrameSurface1*)out->data[3]; - surf_out->Info.CropW = outlink->w; - surf_out->Info.CropH = outlink->h; - surf_out->Info.PicStruct = MFX_PICSTRUCT_PROGRESSIVE; + memset(&s->deint_conf, 0, sizeof(mfxExtVPPDeinterlacing)); + s->deint_conf.Header.BufferId = MFX_EXTBUFF_VPP_DEINTERLACING; + s->deint_conf.Header.BufferSz = sizeof(s->deint_conf); + s->deint_conf.Mode = s->mode; + param.ext_buf[param.num_ext_buf++] = (mfxExtBuffer*)&s->deint_conf; - do { - err = MFXVideoVPP_RunFrameVPPAsync(s->session, surf_in, surf_out, - NULL, &sync); - if (err == MFX_WRN_DEVICE_BUSY) - av_usleep(1); - } while (err == MFX_WRN_DEVICE_BUSY); - - if (err == MFX_ERR_MORE_DATA) { - av_frame_free(&out); - return QSVDEINT_MORE_INPUT; - } - - if (err < 0 && err != MFX_ERR_MORE_SURFACE) { - ret = ff_qsvvpp_print_error(ctx, err, "Error during deinterlacing"); - goto fail; - } - - if (!sync) { - av_log(ctx, AV_LOG_ERROR, "No sync during deinterlacing\n"); - ret = AVERROR_UNKNOWN; - goto fail; - } - if (err == MFX_ERR_MORE_SURFACE) - again = 1; - - do { - err = MFXVideoCORE_SyncOperation(s->session, sync, 1000); - } while (err == MFX_WRN_IN_EXECUTION); - if (err < 0) { - ret = ff_qsvvpp_print_error(ctx, err, "Error synchronizing the operation"); - goto fail; - } - - ret = av_frame_copy_props(out, in); - if (ret < 0) - goto fail; - - out->width = outlink->w; - out->height = outlink->h; - out->interlaced_frame = 0; - - out->pts = av_rescale_q(out->pts, inlink->time_base, outlink->time_base); - if (out->pts == s->last_pts) - out->pts++; - s->last_pts = out->pts; - - if (outlink->frame_rate.num && outlink->frame_rate.den) - out->duration = av_rescale_q(1, av_inv_q(outlink->frame_rate), outlink->time_base); - else - out->duration = 0; - - ret = ff_filter_frame(outlink, out); - if (ret < 0) - return ret; - - return again ? QSVDEINT_MORE_OUTPUT : 0; -fail: - av_frame_free(&out); - return ret; + return ff_qsvvpp_init(ctx, ¶m); } static int qsvdeint_filter_frame(AVFilterLink *link, AVFrame *in) { - AVFilterContext *ctx = link->dst; + AVFilterContext *ctx = link->dst; + QSVVPPContext *qsv = ctx->priv; + int ret = 0; - mfxFrameSurface1 *surf_in; - int ret; + ret = ff_qsvvpp_filter_frame(qsv, link, in); + av_frame_free(&in); - ret = submit_frame(ctx, in, &surf_in); - if (ret < 0) { - av_frame_free(&in); - return ret; - } - - do { - ret = process_frame(ctx, in, surf_in); - if (ret < 0) - return ret; - } while (ret == QSVDEINT_MORE_OUTPUT); - - return 0; + return ret; } static int qsvdeint_request_frame(AVFilterLink *outlink) From b92028346c35dad837dd1160930435d88bd838b5 Mon Sep 17 00:00:00 2001 From: Haihao Xiang Date: Mon, 30 Jan 2023 09:37:19 +0800 Subject: [PATCH 0148/2172] lavfi/deinterlace_qsv: re-use VPPContext for deinterlace_qsv filter QSVDeintContext and VPPContext have the same base context, and all features in deinterlace_qsv are implemented in vpp_qsv filter, so deinterlace_qsv can be taken as a special case of vpp_qsv filter, and we may use VPPContext with a different option array, preinit callback and support pixel formats to implement deinterlace_qsv, then remove QSVDeintContext. Signed-off-by: Haihao Xiang --- libavfilter/Makefile | 2 +- libavfilter/vf_deinterlace_qsv.c | 166 ------------------------------- libavfilter/vf_vpp_qsv.c | 25 +++++ 3 files changed, 26 insertions(+), 167 deletions(-) delete mode 100644 libavfilter/vf_deinterlace_qsv.c diff --git a/libavfilter/Makefile b/libavfilter/Makefile index b45dcd00fc1..0173b11870f 100644 --- a/libavfilter/Makefile +++ b/libavfilter/Makefile @@ -260,7 +260,7 @@ OBJS-$(CONFIG_DECONVOLVE_FILTER) += vf_convolve.o framesync.o OBJS-$(CONFIG_DEDOT_FILTER) += vf_dedot.o OBJS-$(CONFIG_DEFLATE_FILTER) += vf_neighbor.o OBJS-$(CONFIG_DEFLICKER_FILTER) += vf_deflicker.o -OBJS-$(CONFIG_DEINTERLACE_QSV_FILTER) += vf_deinterlace_qsv.o +OBJS-$(CONFIG_DEINTERLACE_QSV_FILTER) += vf_vpp_qsv.o OBJS-$(CONFIG_DEINTERLACE_VAAPI_FILTER) += vf_deinterlace_vaapi.o vaapi_vpp.o OBJS-$(CONFIG_DEJUDDER_FILTER) += vf_dejudder.o OBJS-$(CONFIG_DELOGO_FILTER) += vf_delogo.o diff --git a/libavfilter/vf_deinterlace_qsv.c b/libavfilter/vf_deinterlace_qsv.c deleted file mode 100644 index 8173386780a..00000000000 --- a/libavfilter/vf_deinterlace_qsv.c +++ /dev/null @@ -1,166 +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 - */ - -/** - * @file - * deinterlace video filter - QSV - */ - -#include - -#include -#include - -#include "libavutil/avstring.h" -#include "libavutil/common.h" -#include "libavutil/hwcontext.h" -#include "libavutil/hwcontext_qsv.h" -#include "libavutil/internal.h" -#include "libavutil/mathematics.h" -#include "libavutil/opt.h" -#include "libavutil/pixdesc.h" -#include "libavutil/time.h" -#include "libavfilter/qsvvpp.h" - -#include "avfilter.h" -#include "formats.h" -#include "internal.h" -#include "video.h" - -#define MFX_IMPL_VIA_MASK(impl) (0x0f00 & (impl)) - -typedef struct QSVDeintContext { - QSVVPPContext qsv; - - mfxExtVPPDeinterlacing deint_conf; - - /* option for Deinterlacing algorithm to be used */ - int mode; -} QSVDeintContext; - -static av_cold void qsvdeint_uninit(AVFilterContext *ctx) -{ - ff_qsvvpp_close(ctx); -} - -static int qsvdeint_config_props(AVFilterLink *outlink) -{ - AVFilterContext *ctx = outlink->src; - AVFilterLink *inlink = ctx->inputs[0]; - QSVDeintContext *s = ctx->priv; - QSVVPPParam param = { NULL }; - mfxExtBuffer *ext_buf[1]; - enum AVPixelFormat in_format; - - qsvdeint_uninit(ctx); - - outlink->w = inlink->w; - outlink->h = inlink->h; - outlink->frame_rate = av_mul_q(inlink->frame_rate, - (AVRational){ 2, 1 }); - outlink->time_base = av_mul_q(inlink->time_base, - (AVRational){ 1, 2 }); - - if (inlink->format == AV_PIX_FMT_QSV) { - if (!inlink->hw_frames_ctx || !inlink->hw_frames_ctx->data) - return AVERROR(EINVAL); - else - in_format = ((AVHWFramesContext*)inlink->hw_frames_ctx->data)->sw_format; - } else - in_format = inlink->format; - - param.out_sw_format = in_format; - param.ext_buf = ext_buf; - - memset(&s->deint_conf, 0, sizeof(mfxExtVPPDeinterlacing)); - s->deint_conf.Header.BufferId = MFX_EXTBUFF_VPP_DEINTERLACING; - s->deint_conf.Header.BufferSz = sizeof(s->deint_conf); - s->deint_conf.Mode = s->mode; - param.ext_buf[param.num_ext_buf++] = (mfxExtBuffer*)&s->deint_conf; - - return ff_qsvvpp_init(ctx, ¶m); -} - -static int qsvdeint_filter_frame(AVFilterLink *link, AVFrame *in) -{ - AVFilterContext *ctx = link->dst; - QSVVPPContext *qsv = ctx->priv; - int ret = 0; - - ret = ff_qsvvpp_filter_frame(qsv, link, in); - av_frame_free(&in); - - return ret; -} - -static int qsvdeint_request_frame(AVFilterLink *outlink) -{ - AVFilterContext *ctx = outlink->src; - - return ff_request_frame(ctx->inputs[0]); -} - -#define OFFSET(x) offsetof(QSVDeintContext, x) -#define FLAGS AV_OPT_FLAG_VIDEO_PARAM|AV_OPT_FLAG_FILTERING_PARAM -static const AVOption options[] = { - { "mode", "set deinterlace mode", OFFSET(mode), AV_OPT_TYPE_INT, {.i64 = MFX_DEINTERLACING_ADVANCED}, MFX_DEINTERLACING_BOB, MFX_DEINTERLACING_ADVANCED, FLAGS, "mode"}, - { "bob", "bob algorithm", 0, AV_OPT_TYPE_CONST, {.i64 = MFX_DEINTERLACING_BOB}, MFX_DEINTERLACING_BOB, MFX_DEINTERLACING_ADVANCED, FLAGS, "mode"}, - { "advanced", "Motion adaptive algorithm", 0, AV_OPT_TYPE_CONST, {.i64 = MFX_DEINTERLACING_ADVANCED}, MFX_DEINTERLACING_BOB, MFX_DEINTERLACING_ADVANCED, FLAGS, "mode"}, - { NULL }, -}; - -static const AVClass qsvdeint_class = { - .class_name = "deinterlace_qsv", - .item_name = av_default_item_name, - .option = options, - .version = LIBAVUTIL_VERSION_INT, -}; - -static const AVFilterPad qsvdeint_inputs[] = { - { - .name = "default", - .type = AVMEDIA_TYPE_VIDEO, - .filter_frame = qsvdeint_filter_frame, - .get_buffer.video = ff_qsvvpp_get_video_buffer, - }, -}; - -static const AVFilterPad qsvdeint_outputs[] = { - { - .name = "default", - .type = AVMEDIA_TYPE_VIDEO, - .config_props = qsvdeint_config_props, - .request_frame = qsvdeint_request_frame, - }, -}; - -const AVFilter ff_vf_deinterlace_qsv = { - .name = "deinterlace_qsv", - .description = NULL_IF_CONFIG_SMALL("QuickSync video deinterlacing"), - - .uninit = qsvdeint_uninit, - - .priv_size = sizeof(QSVDeintContext), - .priv_class = &qsvdeint_class, - - FILTER_INPUTS(qsvdeint_inputs), - FILTER_OUTPUTS(qsvdeint_outputs), - FILTER_SINGLE_PIXFMT(AV_PIX_FMT_QSV), - - .flags_internal = FF_FILTER_FLAG_HWFRAME_AWARE, -}; diff --git a/libavfilter/vf_vpp_qsv.c b/libavfilter/vf_vpp_qsv.c index aac0a234c30..010b69943ac 100644 --- a/libavfilter/vf_vpp_qsv.c +++ b/libavfilter/vf_vpp_qsv.c @@ -752,3 +752,28 @@ static av_cold int qsvscale_preinit(AVFilterContext *ctx) DEFINE_QSV_FILTER(qsvscale, scale, "scaling and format conversion", FILTER_SINGLE_PIXFMT(AV_PIX_FMT_QSV)); #endif + +#if CONFIG_DEINTERLACE_QSV_FILTER + +static const AVOption qsvdeint_options[] = { + { "mode", "set deinterlace mode", OFFSET(deinterlace), AV_OPT_TYPE_INT, {.i64 = MFX_DEINTERLACING_ADVANCED}, MFX_DEINTERLACING_BOB, MFX_DEINTERLACING_ADVANCED, FLAGS, "mode"}, + { "bob", "bob algorithm", 0, AV_OPT_TYPE_CONST, {.i64 = MFX_DEINTERLACING_BOB}, MFX_DEINTERLACING_BOB, MFX_DEINTERLACING_ADVANCED, FLAGS, "mode"}, + { "advanced", "Motion adaptive algorithm", 0, AV_OPT_TYPE_CONST, {.i64 = MFX_DEINTERLACING_ADVANCED}, MFX_DEINTERLACING_BOB, MFX_DEINTERLACING_ADVANCED, FLAGS, "mode"}, + + { NULL }, +}; + +static av_cold int qsvdeint_preinit(AVFilterContext *ctx) +{ + VPPContext *vpp = ctx->priv; + + vpp_preinit(ctx); + vpp->has_passthrough = 0; + vpp->field_rate = 1; + + return 0; +} + +DEFINE_QSV_FILTER(qsvdeint, deinterlace, "deinterlacing", FILTER_SINGLE_PIXFMT(AV_PIX_FMT_QSV)) + +#endif From fcc50674ded2d70b44be32be0331c7d925aa53dc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Ekstr=C3=B6m?= Date: Mon, 13 Dec 2021 18:30:37 +0200 Subject: [PATCH 0149/2172] ffmpeg: refactor post-decoding steps for subtitles into a function MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This enables us to later call this when generating additional subtitles for splitting purposes. Co-authored-by: Andrzej Nadachowski Signed-off-by: Jan Ekström --- fftools/ffmpeg.c | 49 +++++++++++++++++++++++++++--------------------- 1 file changed, 28 insertions(+), 21 deletions(-) diff --git a/fftools/ffmpeg.c b/fftools/ffmpeg.c index 92fd61f3158..ba045b454c3 100644 --- a/fftools/ffmpeg.c +++ b/fftools/ffmpeg.c @@ -2296,27 +2296,15 @@ static int decode_video(InputStream *ist, AVPacket *pkt, int *got_output, int64_ return err < 0 ? err : ret; } -static int transcode_subtitles(InputStream *ist, AVPacket *pkt, int *got_output, - int *decode_failed) +static int process_subtitle(InputStream *ist, AVSubtitle *subtitle, int *got_output) { - AVSubtitle subtitle; + int ret = 0; int free_sub = 1; - int ret = avcodec_decode_subtitle2(ist->dec_ctx, - &subtitle, got_output, pkt); - - check_decode_result(NULL, got_output, ret); - - if (ret < 0 || !*got_output) { - *decode_failed = 1; - if (!pkt->size) - sub2video_flush(ist); - return ret; - } if (ist->fix_sub_duration) { int end = 1; if (ist->prev_sub.got_output) { - end = av_rescale(subtitle.pts - ist->prev_sub.subtitle.pts, + end = av_rescale(subtitle->pts - ist->prev_sub.subtitle.pts, 1000, AV_TIME_BASE); if (end < ist->prev_sub.subtitle.end_display_time) { av_log(NULL, AV_LOG_DEBUG, @@ -2328,7 +2316,7 @@ static int transcode_subtitles(InputStream *ist, AVPacket *pkt, int *got_output, } FFSWAP(int, *got_output, ist->prev_sub.got_output); FFSWAP(int, ret, ist->prev_sub.ret); - FFSWAP(AVSubtitle, subtitle, ist->prev_sub.subtitle); + FFSWAP(AVSubtitle, *subtitle, ist->prev_sub.subtitle); if (end <= 0) goto out; } @@ -2337,20 +2325,20 @@ static int transcode_subtitles(InputStream *ist, AVPacket *pkt, int *got_output, return ret; if (ist->sub2video.frame) { - sub2video_update(ist, INT64_MIN, &subtitle); + sub2video_update(ist, INT64_MIN, subtitle); } else if (ist->nb_filters) { if (!ist->sub2video.sub_queue) ist->sub2video.sub_queue = av_fifo_alloc2(8, sizeof(AVSubtitle), AV_FIFO_FLAG_AUTO_GROW); if (!ist->sub2video.sub_queue) report_and_exit(AVERROR(ENOMEM)); - ret = av_fifo_write(ist->sub2video.sub_queue, &subtitle, 1); + ret = av_fifo_write(ist->sub2video.sub_queue, subtitle, 1); if (ret < 0) exit_program(1); free_sub = 0; } - if (!subtitle.num_rects) + if (!subtitle->num_rects) goto out; ist->frames_decoded++; @@ -2360,15 +2348,34 @@ static int transcode_subtitles(InputStream *ist, AVPacket *pkt, int *got_output, || ost->enc_ctx->codec_type != AVMEDIA_TYPE_SUBTITLE) continue; - do_subtitle_out(output_files[ost->file_index], ost, &subtitle); + do_subtitle_out(output_files[ost->file_index], ost, subtitle); } out: if (free_sub) - avsubtitle_free(&subtitle); + avsubtitle_free(subtitle); return ret; } +static int transcode_subtitles(InputStream *ist, AVPacket *pkt, int *got_output, + int *decode_failed) +{ + AVSubtitle subtitle; + int ret = avcodec_decode_subtitle2(ist->dec_ctx, + &subtitle, got_output, pkt); + + check_decode_result(NULL, got_output, ret); + + if (ret < 0 || !*got_output) { + *decode_failed = 1; + if (!pkt->size) + sub2video_flush(ist); + return ret; + } + + return process_subtitle(ist, &subtitle, got_output); +} + static int send_filter_eof(InputStream *ist) { int i, ret; From 746d27455b00f6baca2a1e4ab206cd40bf187598 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Ekstr=C3=B6m?= Date: Fri, 5 Aug 2022 10:50:57 +0300 Subject: [PATCH 0150/2172] ffmpeg: move decoded frame counter from after post-processing to decode MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This way we can call process_subtitles without causing the decoded frame counter to get bumped. Additionally, this now takes into mention all of the decoded subtitle frames without fix_sub_duration latency/buffering, or filtering out decoded reset/end subtitles without any rendered rectangles, which matches the original intent in 4754345027eb85cfa51aeb88beec68d7b036c11e . Signed-off-by: Jan Ekström --- fftools/ffmpeg.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/fftools/ffmpeg.c b/fftools/ffmpeg.c index ba045b454c3..e0a02260f5f 100644 --- a/fftools/ffmpeg.c +++ b/fftools/ffmpeg.c @@ -2341,8 +2341,6 @@ static int process_subtitle(InputStream *ist, AVSubtitle *subtitle, int *got_out if (!subtitle->num_rects) goto out; - ist->frames_decoded++; - for (OutputStream *ost = ost_iter(NULL); ost; ost = ost_iter(ost)) { if (!check_output_constraints(ist, ost) || !ost->enc_ctx || ost->enc_ctx->codec_type != AVMEDIA_TYPE_SUBTITLE) @@ -2373,6 +2371,8 @@ static int transcode_subtitles(InputStream *ist, AVPacket *pkt, int *got_output, return ret; } + ist->frames_decoded++; + return process_subtitle(ist, &subtitle, got_output); } From 9a820ec8b1e2323b70a1cebd204bf459bf7daa1a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Ekstr=C3=B6m?= Date: Fri, 22 Jul 2022 13:57:54 +0300 Subject: [PATCH 0151/2172] ffmpeg: add video heartbeat capability to fix_sub_duration MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Splits the currently handled subtitle at random access point packets that can be configured to follow a specific output stream. Currently only subtitle streams which are directly mapped into the same output in which the heartbeat stream resides are affected. This way the subtitle - which is known to be shown at this time can be split and passed to muxer before its full duration is yet known. This is also a drawback, as this essentially outputs multiple subtitles from a single input subtitle that continues over multiple random access points. Thus this feature should not be utilized in cases where subtitle output latency does not matter. Co-authored-by: Andrzej Nadachowski Co-authored-by: Bernard Boulay Signed-off-by: Jan Ekström --- Changelog | 1 + doc/ffmpeg.texi | 16 ++ fftools/ffmpeg.c | 148 ++++++++++++++++++ fftools/ffmpeg.h | 8 + fftools/ffmpeg_mux_init.c | 4 + fftools/ffmpeg_opt.c | 5 + tests/fate/ffmpeg.mak | 15 ++ .../fate/ffmpeg-fix_sub_duration_heartbeat | 48 ++++++ 8 files changed, 245 insertions(+) create mode 100644 tests/ref/fate/ffmpeg-fix_sub_duration_heartbeat diff --git a/Changelog b/Changelog index c3ca10a3bb2..cdbe43eac1b 100644 --- a/Changelog +++ b/Changelog @@ -36,6 +36,7 @@ version : - hstack_vaapi, vstack_vaapi and xstack_vaapi filters - XMD ADPCM decoder and demuxer - media100 to mjpegb bsf +- ffmpeg CLI new option: -fix_sub_duration_heartbeat version 5.1: diff --git a/doc/ffmpeg.texi b/doc/ffmpeg.texi index 81e04f69834..592c4b4393d 100644 --- a/doc/ffmpeg.texi +++ b/doc/ffmpeg.texi @@ -1342,6 +1342,22 @@ List all hardware acceleration components enabled in this build of ffmpeg. Actual runtime availability depends on the hardware and its suitable driver being installed. +@item -fix_sub_duration_heartbeat[:@var{stream_specifier}] +Set a specific output video stream as the heartbeat stream according to which +to split and push through currently in-progress subtitle upon receipt of a +random access packet. + +This lowers the latency of subtitles for which the end packet or the following +subtitle has not yet been received. As a drawback, this will most likely lead +to duplication of subtitle events in order to cover the full duration, so +when dealing with use cases where latency of when the subtitle event is passed +on to output is not relevant this option should not be utilized. + +Requires @option{-fix_sub_duration} to be set for the relevant input subtitle +stream for this to have any effect, as well as for the input subtitle stream +having to be directly mapped to the same output in which the heartbeat stream +resides. + @end table @section Audio Options diff --git a/fftools/ffmpeg.c b/fftools/ffmpeg.c index e0a02260f5f..743bc0c6b67 100644 --- a/fftools/ffmpeg.c +++ b/fftools/ffmpeg.c @@ -126,6 +126,7 @@ typedef struct BenchmarkTimeStamps { int64_t sys_usec; } BenchmarkTimeStamps; +static int trigger_fix_sub_duration_heartbeat(OutputStream *ost, const AVPacket *pkt); static BenchmarkTimeStamps get_benchmark_time_stamps(void); static int64_t getmaxrss(void); static int ifilter_has_all_input_formats(FilterGraph *fg); @@ -953,6 +954,13 @@ static int encode_frame(OutputFile *of, OutputStream *ost, AVFrame *frame) av_ts2str(pkt->duration), av_ts2timestr(pkt->duration, &enc->time_base)); } + if ((ret = trigger_fix_sub_duration_heartbeat(ost, pkt)) < 0) { + av_log(NULL, AV_LOG_ERROR, + "Subtitle heartbeat logic failed in %s! (%s)\n", + __func__, av_err2str(ret)); + exit_program(1); + } + ost->data_size_enc += pkt->size; ost->packets_encoded++; @@ -1912,6 +1920,16 @@ 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); + { + int ret = trigger_fix_sub_duration_heartbeat(ost, pkt); + if (ret < 0) { + av_log(NULL, AV_LOG_ERROR, + "Subtitle heartbeat logic failed in %s! (%s)\n", + __func__, av_err2str(ret)); + exit_program(1); + } + } + of_output_packet(of, opkt, ost, 0); ost->streamcopy_started = 1; @@ -2355,6 +2373,136 @@ static int process_subtitle(InputStream *ist, AVSubtitle *subtitle, int *got_out return ret; } +static int copy_av_subtitle(AVSubtitle *dst, AVSubtitle *src) +{ + int ret = AVERROR_BUG; + AVSubtitle tmp = { + .format = src->format, + .start_display_time = src->start_display_time, + .end_display_time = src->end_display_time, + .num_rects = 0, + .rects = NULL, + .pts = src->pts + }; + + if (!src->num_rects) + goto success; + + if (!(tmp.rects = av_calloc(src->num_rects, sizeof(*tmp.rects)))) + return AVERROR(ENOMEM); + + for (int i = 0; i < src->num_rects; i++) { + AVSubtitleRect *src_rect = src->rects[i]; + AVSubtitleRect *dst_rect; + + if (!(dst_rect = tmp.rects[i] = av_mallocz(sizeof(*tmp.rects[0])))) { + ret = AVERROR(ENOMEM); + goto cleanup; + } + + tmp.num_rects++; + + dst_rect->type = src_rect->type; + dst_rect->flags = src_rect->flags; + + dst_rect->x = src_rect->x; + dst_rect->y = src_rect->y; + dst_rect->w = src_rect->w; + dst_rect->h = src_rect->h; + dst_rect->nb_colors = src_rect->nb_colors; + + if (src_rect->text) + if (!(dst_rect->text = av_strdup(src_rect->text))) { + ret = AVERROR(ENOMEM); + goto cleanup; + } + + if (src_rect->ass) + if (!(dst_rect->ass = av_strdup(src_rect->ass))) { + ret = AVERROR(ENOMEM); + goto cleanup; + } + + for (int j = 0; j < 4; j++) { + // SUBTITLE_BITMAP images are special in the sense that they + // are like PAL8 images. first pointer to data, second to + // palette. This makes the size calculation match this. + size_t buf_size = src_rect->type == SUBTITLE_BITMAP && j == 1 ? + AVPALETTE_SIZE : + src_rect->h * src_rect->linesize[j]; + + if (!src_rect->data[j]) + continue; + + if (!(dst_rect->data[j] = av_memdup(src_rect->data[j], buf_size))) { + ret = AVERROR(ENOMEM); + goto cleanup; + } + dst_rect->linesize[j] = src_rect->linesize[j]; + } + } + +success: + *dst = tmp; + + return 0; + +cleanup: + avsubtitle_free(&tmp); + + return ret; +} + +static int fix_sub_duration_heartbeat(InputStream *ist, int64_t signal_pts) +{ + int ret = AVERROR_BUG; + int got_output = 1; + AVSubtitle *prev_subtitle = &ist->prev_sub.subtitle; + AVSubtitle subtitle; + + if (!ist->fix_sub_duration || !prev_subtitle->num_rects || + signal_pts <= prev_subtitle->pts) + return 0; + + if ((ret = copy_av_subtitle(&subtitle, prev_subtitle)) < 0) + return ret; + + subtitle.pts = signal_pts; + + return process_subtitle(ist, &subtitle, &got_output); +} + +static int trigger_fix_sub_duration_heartbeat(OutputStream *ost, const AVPacket *pkt) +{ + OutputFile *of = output_files[ost->file_index]; + int64_t signal_pts = av_rescale_q(pkt->pts, ost->mux_timebase, + AV_TIME_BASE_Q); + + if (!ost->fix_sub_duration_heartbeat || !(pkt->flags & AV_PKT_FLAG_KEY)) + // we are only interested in heartbeats on streams configured, and + // only on random access points. + return 0; + + for (int i = 0; i < of->nb_streams; i++) { + OutputStream *iter_ost = of->streams[i]; + InputStream *ist = iter_ost->ist; + int ret = AVERROR_BUG; + + if (iter_ost == ost || !ist || !ist->decoding_needed || + ist->dec_ctx->codec_type != AVMEDIA_TYPE_SUBTITLE) + // We wish to skip the stream that causes the heartbeat, + // output streams without an input stream, streams not decoded + // (as fix_sub_duration is only done for decoded subtitles) as + // well as non-subtitle streams. + continue; + + if ((ret = fix_sub_duration_heartbeat(ist, signal_pts)) < 0) + return ret; + } + + return 0; +} + static int transcode_subtitles(InputStream *ist, AVPacket *pkt, int *got_output, int *decode_failed) { diff --git a/fftools/ffmpeg.h b/fftools/ffmpeg.h index 8c976af97ad..933312dba78 100644 --- a/fftools/ffmpeg.h +++ b/fftools/ffmpeg.h @@ -224,6 +224,8 @@ typedef struct OptionsContext { int nb_reinit_filters; SpecifierOpt *fix_sub_duration; int nb_fix_sub_duration; + SpecifierOpt *fix_sub_duration_heartbeat; + int nb_fix_sub_duration_heartbeat; SpecifierOpt *canvas_sizes; int nb_canvas_sizes; SpecifierOpt *pass; @@ -675,6 +677,12 @@ typedef struct OutputStream { EncStats enc_stats_pre; EncStats enc_stats_post; + + /* + * bool on whether this stream should be utilized for splitting + * subtitles utilizing fix_sub_duration at random access points. + */ + unsigned int fix_sub_duration_heartbeat; } OutputStream; typedef struct OutputFile { diff --git a/fftools/ffmpeg_mux_init.c b/fftools/ffmpeg_mux_init.c index f8ccf4a3e9b..834cdbcc9f2 100644 --- a/fftools/ffmpeg_mux_init.c +++ b/fftools/ffmpeg_mux_init.c @@ -61,6 +61,7 @@ static const char *const opt_name_enc_stats_pre_fmt[] = {"enc_stats_pre_ static const char *const opt_name_enc_stats_post_fmt[] = {"enc_stats_post_fmt", NULL}; static const char *const opt_name_filters[] = {"filter", "af", "vf", NULL}; static const char *const opt_name_filter_scripts[] = {"filter_script", NULL}; +static const char *const opt_name_fix_sub_duration_heartbeat[] = {"fix_sub_duration_heartbeat", NULL}; static const char *const opt_name_fps_mode[] = {"fps_mode", NULL}; static const char *const opt_name_force_fps[] = {"force_fps", NULL}; static const char *const opt_name_forced_key_frames[] = {"forced_key_frames", NULL}; @@ -614,6 +615,9 @@ static OutputStream *new_output_stream(Muxer *mux, const OptionsContext *o, MATCH_PER_STREAM_OPT(bits_per_raw_sample, i, ost->bits_per_raw_sample, oc, st); + MATCH_PER_STREAM_OPT(fix_sub_duration_heartbeat, i, ost->fix_sub_duration_heartbeat, + oc, st); + if (oc->oformat->flags & AVFMT_GLOBALHEADER && ost->enc_ctx) ost->enc_ctx->flags |= AV_CODEC_FLAG_GLOBAL_HEADER; diff --git a/fftools/ffmpeg_opt.c b/fftools/ffmpeg_opt.c index c0ae55a3598..204be38c94d 100644 --- a/fftools/ffmpeg_opt.c +++ b/fftools/ffmpeg_opt.c @@ -1658,6 +1658,11 @@ const OptionDef options[] = { { "autoscale", HAS_ARG | OPT_BOOL | OPT_SPEC | OPT_EXPERT | OPT_OUTPUT, { .off = OFFSET(autoscale) }, "automatically insert a scale filter at the end of the filter graph" }, + { "fix_sub_duration_heartbeat", OPT_VIDEO | OPT_BOOL | OPT_EXPERT | + OPT_SPEC | OPT_OUTPUT, { .off = OFFSET(fix_sub_duration_heartbeat) }, + "set this video output stream to be a heartbeat stream for " + "fix_sub_duration, according to which subtitles should be split at " + "random access points" }, /* audio options */ { "aframes", OPT_AUDIO | HAS_ARG | OPT_PERFILE | OPT_OUTPUT, { .func_arg = opt_audio_frames }, diff --git a/tests/fate/ffmpeg.mak b/tests/fate/ffmpeg.mak index d87639c5961..0f33c2a0ed7 100644 --- a/tests/fate/ffmpeg.mak +++ b/tests/fate/ffmpeg.mak @@ -117,6 +117,21 @@ fate-ffmpeg-fix_sub_duration: CMD = fmtstdout srt -fix_sub_duration \ -real_time 1 -f lavfi \ -i "movie=$(TARGET_SAMPLES)/sub/Closedcaption_rollup.m2v[out0+subcc]" +# Basic test for fix_sub_duration_heartbeat, which causes a buffered subtitle +# to be pushed out when a video keyframe is received from an encoder. +FATE_SAMPLES_FFMPEG-$(call FILTERDEMDECENCMUX, MOVIE, MPEGVIDEO, \ + MPEG2VIDEO, SUBRIP, SRT, LAVFI_INDEV \ + MPEGVIDEO_PARSER CCAPTION_DECODER \ + MPEG2VIDEO_ENCODER NULL_MUXER PIPE_PROTOCOL) \ + += fate-ffmpeg-fix_sub_duration_heartbeat +fate-ffmpeg-fix_sub_duration_heartbeat: CMD = fmtstdout srt -fix_sub_duration \ + -real_time 1 -f lavfi \ + -i "movie=$(TARGET_SAMPLES)/sub/Closedcaption_rollup.m2v[out0+subcc]" \ + -map 0:v -map 0:s -fix_sub_duration_heartbeat:v:0 \ + -c:v mpeg2video -b:v 2M -g 30 -sc_threshold 1000000000 \ + -c:s srt \ + -f null - + FATE_STREAMCOPY-$(call REMUX, MP4 MOV, EAC3_DEMUXER) += fate-copy-trac3074 fate-copy-trac3074: CMD = transcode eac3 $(TARGET_SAMPLES)/eac3/csi_miami_stereo_128_spx.eac3\ mp4 "-codec copy -map 0" "-codec copy" diff --git a/tests/ref/fate/ffmpeg-fix_sub_duration_heartbeat b/tests/ref/fate/ffmpeg-fix_sub_duration_heartbeat new file mode 100644 index 00000000000..957a4109215 --- /dev/null +++ b/tests/ref/fate/ffmpeg-fix_sub_duration_heartbeat @@ -0,0 +1,48 @@ +1 +00:00:00,968 --> 00:00:01,001 +{\an7}( + +2 +00:00:01,001 --> 00:00:01,168 +{\an7}( + +3 +00:00:01,168 --> 00:00:01,368 +{\an7}( inaudibl + +4 +00:00:01,368 --> 00:00:01,568 +{\an7}( inaudible radio chat + +5 +00:00:01,568 --> 00:00:02,002 +{\an7}( inaudible radio chatter ) + +6 +00:00:02,002 --> 00:00:03,003 +{\an7}( inaudible radio chatter ) + +7 +00:00:03,003 --> 00:00:03,103 +{\an7}( inaudible radio chatter ) + +8 +00:00:03,103 --> 00:00:03,303 +{\an7}( inaudible radio chatter ) +>> + +9 +00:00:03,303 --> 00:00:03,503 +{\an7}( inaudible radio chatter ) +>> Safety rema + +10 +00:00:03,504 --> 00:00:03,704 +{\an7}( inaudible radio chatter ) +>> Safety remains our numb + +11 +00:00:03,704 --> 00:00:04,004 +{\an7}( inaudible radio chatter ) +>> Safety remains our number one + From 651da919153e385f0769238c091109c06a142ca6 Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Sat, 21 Jan 2023 19:25:41 +0100 Subject: [PATCH 0152/2172] avcodec: add WavArc decoder --- Changelog | 1 + doc/general_contents.texi | 1 + libavcodec/Makefile | 1 + libavcodec/allcodecs.c | 1 + libavcodec/codec_desc.c | 7 + libavcodec/codec_id.h | 1 + libavcodec/version.h | 2 +- libavcodec/wavarc.c | 460 ++++++++++++++++++++++++++++++++++++++ 8 files changed, 473 insertions(+), 1 deletion(-) create mode 100644 libavcodec/wavarc.c diff --git a/Changelog b/Changelog index cdbe43eac1b..2d2206e1ba9 100644 --- a/Changelog +++ b/Changelog @@ -37,6 +37,7 @@ version : - XMD ADPCM decoder and demuxer - media100 to mjpegb bsf - ffmpeg CLI new option: -fix_sub_duration_heartbeat +- WavArc decoder version 5.1: diff --git a/doc/general_contents.texi b/doc/general_contents.texi index 87e180c9799..84df3432cf3 100644 --- a/doc/general_contents.texi +++ b/doc/general_contents.texi @@ -1356,6 +1356,7 @@ following image formats are supported: @item Vorbis @tab E @tab X @tab A native but very primitive encoder exists. @item Voxware MetaSound @tab @tab X +@item Waveform Archiver @tab @tab X @item WavPack @tab X @tab X @item Westwood Audio (SND1) @tab @tab X @item Windows Media Audio 1 @tab X @tab X diff --git a/libavcodec/Makefile b/libavcodec/Makefile index 1fb963f8208..4971832ff41 100644 --- a/libavcodec/Makefile +++ b/libavcodec/Makefile @@ -781,6 +781,7 @@ OBJS-$(CONFIG_VP9_V4L2M2M_DECODER) += v4l2_m2m_dec.o OBJS-$(CONFIG_VQA_DECODER) += vqavideo.o OBJS-$(CONFIG_VQC_DECODER) += vqcdec.o OBJS-$(CONFIG_WADY_DPCM_DECODER) += dpcm.o +OBJS-$(CONFIG_WAVARC_DECODER) += wavarc.o OBJS-$(CONFIG_WAVPACK_DECODER) += wavpack.o wavpackdata.o dsd.o OBJS-$(CONFIG_WAVPACK_ENCODER) += wavpackdata.o wavpackenc.o OBJS-$(CONFIG_WBMP_DECODER) += wbmpdec.o diff --git a/libavcodec/allcodecs.c b/libavcodec/allcodecs.c index ff82423a88c..b80b6983e90 100644 --- a/libavcodec/allcodecs.c +++ b/libavcodec/allcodecs.c @@ -538,6 +538,7 @@ extern const FFCodec ff_twinvq_decoder; extern const FFCodec ff_vmdaudio_decoder; extern const FFCodec ff_vorbis_encoder; extern const FFCodec ff_vorbis_decoder; +extern const FFCodec ff_wavarc_decoder; extern const FFCodec ff_wavpack_encoder; extern const FFCodec ff_wavpack_decoder; extern const FFCodec ff_wmalossless_decoder; diff --git a/libavcodec/codec_desc.c b/libavcodec/codec_desc.c index 8ab228d8464..57d0f982116 100644 --- a/libavcodec/codec_desc.c +++ b/libavcodec/codec_desc.c @@ -3353,6 +3353,13 @@ static const AVCodecDescriptor codec_descriptors[] = { .long_name = NULL_IF_CONFIG_SMALL("FTR Voice"), .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSY, }, + { + .id = AV_CODEC_ID_WAVARC, + .type = AVMEDIA_TYPE_AUDIO, + .name = "wavarc", + .long_name = NULL_IF_CONFIG_SMALL("Waveform Archiver"), + .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSLESS, + }, /* subtitle codecs */ { diff --git a/libavcodec/codec_id.h b/libavcodec/codec_id.h index 0c574c96193..ad1131b464d 100644 --- a/libavcodec/codec_id.h +++ b/libavcodec/codec_id.h @@ -536,6 +536,7 @@ enum AVCodecID { AV_CODEC_ID_MISC4, AV_CODEC_ID_APAC, AV_CODEC_ID_FTR, + AV_CODEC_ID_WAVARC, /* subtitle codecs */ AV_CODEC_ID_FIRST_SUBTITLE = 0x17000, ///< A dummy ID pointing at the start of subtitle codecs. diff --git a/libavcodec/version.h b/libavcodec/version.h index 499c6bb175b..310c80eeef6 100644 --- a/libavcodec/version.h +++ b/libavcodec/version.h @@ -29,7 +29,7 @@ #include "version_major.h" -#define LIBAVCODEC_VERSION_MINOR 61 +#define LIBAVCODEC_VERSION_MINOR 62 #define LIBAVCODEC_VERSION_MICRO 100 #define LIBAVCODEC_VERSION_INT AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \ diff --git a/libavcodec/wavarc.c b/libavcodec/wavarc.c new file mode 100644 index 00000000000..898c3c20554 --- /dev/null +++ b/libavcodec/wavarc.c @@ -0,0 +1,460 @@ +/* + * WavArc audio decoder + * Copyright (c) 2023 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 "libavutil/internal.h" +#include "libavutil/intreadwrite.h" +#include "avcodec.h" +#include "codec_internal.h" +#include "decode.h" +#include "get_bits.h" +#include "bytestream.h" +#include "mathops.h" +#include "unary.h" + +typedef struct WavArcContext { + GetBitContext gb; + + int shift; + int nb_samples; + int offset; + + int eof; + int skip; + uint8_t *bitstream; + int64_t max_framesize; + int bitstream_size; + int bitstream_index; + + int pred[2][70]; + int filter[2][70]; + int samples[2][640]; +} WavArcContext; + +static av_cold int wavarc_init(AVCodecContext *avctx) +{ + WavArcContext *s = avctx->priv_data; + + if (avctx->extradata_size < 44) + return AVERROR_INVALIDDATA; + if (AV_RL32(avctx->extradata + 16) != MKTAG('R','I','F','F')) + return AVERROR_INVALIDDATA; + if (AV_RL32(avctx->extradata + 24) != MKTAG('W','A','V','E')) + return AVERROR_INVALIDDATA; + if (AV_RL32(avctx->extradata + 28) != MKTAG('f','m','t',' ')) + return AVERROR_INVALIDDATA; + if (AV_RL16(avctx->extradata + 38) != 1 && + AV_RL16(avctx->extradata + 38) != 2) + return AVERROR_INVALIDDATA; + + av_channel_layout_uninit(&avctx->ch_layout); + av_channel_layout_default(&avctx->ch_layout, AV_RL16(avctx->extradata + 38)); + avctx->sample_rate = AV_RL32(avctx->extradata + 40); + + switch (avctx->extradata[36]) { + case 0: avctx->sample_fmt = AV_SAMPLE_FMT_U8P; break; + case 1: avctx->sample_fmt = AV_SAMPLE_FMT_S16P; break; + } + + s->shift = 0; + switch (avctx->codec_tag) { + case MKTAG('1','D','I','F'): + s->nb_samples = 256; + s->offset = 4; + break; + case MKTAG('2','S','L','P'): + case MKTAG('3','N','L','P'): + case MKTAG('4','A','L','P'): + s->nb_samples = 570; + s->offset = 70; + break; + default: + return AVERROR_INVALIDDATA; + } + + s->max_framesize = s->nb_samples * 16; + s->bitstream = av_calloc(s->max_framesize, sizeof(*s->bitstream)); + if (!s->bitstream) + return AVERROR(ENOMEM); + + return 0; +} + +static unsigned get_urice(GetBitContext *gb, int k) +{ + unsigned x = get_unary(gb, 1, get_bits_left(gb)); + unsigned y = get_bits_long(gb, k); + unsigned z = (x << k) | y; + + return z; +} + +static int get_srice(GetBitContext *gb, int k) +{ + unsigned z = get_urice(gb, k); + + return (z & 1) ? ~((int)(z >> 1)) : z >> 1; +} + +static void do_stereo(WavArcContext *s, int ch, int correlated, int len) +{ + const int nb_samples = s->nb_samples; + const int shift = s->shift; + + if (ch == 0) { + if (correlated) { + for (int n = 0; n < len; n++) { + s->samples[0][n] = s->samples[0][nb_samples + n] >> shift; + s->samples[1][n] = s->pred[1][n] >> shift; + } + } else { + for (int n = 0; n < len; n++) { + s->samples[0][n] = s->samples[0][nb_samples + n] >> shift; + s->samples[1][n] = s->pred[0][n] >> shift; + } + } + } else { + if (correlated) { + for (int n = 0; n < nb_samples; n++) + s->samples[1][n + len] += s->samples[0][n + len]; + } + for (int n = 0; n < len; n++) { + s->pred[0][n] = s->samples[1][nb_samples + n]; + s->pred[1][n] = s->pred[0][n] - s->samples[0][nb_samples + n]; + } + } +} + +static int decode_1dif(AVCodecContext *avctx, + WavArcContext *s, GetBitContext *gb) +{ + int ch, finished, fill, correlated; + + ch = 0; + finished = 0; + while (!finished) { + int *samples = s->samples[ch]; + int k, block_type; + + if (get_bits_left(gb) <= 0) + return AVERROR_INVALIDDATA; + + block_type = get_urice(gb, 1); + if (block_type < 4 && block_type >= 0) { + k = 1 + (avctx->sample_fmt == AV_SAMPLE_FMT_S16P); + k = get_urice(gb, k) + 1; + } + + switch (block_type) { + case 8: + s->eof = 1; + return AVERROR_EOF; + case 7: + s->nb_samples = get_bits(gb, 8); + continue; + case 6: + s->shift = get_urice(gb, 2); + continue; + case 5: + if (avctx->sample_fmt == AV_SAMPLE_FMT_U8P) { + fill = (int8_t)get_bits(gb, 8); + fill -= 0x80; + } else { + fill = (int16_t)get_bits(gb, 16); + fill -= 0x8000; + } + + for (int n = 0; n < s->nb_samples; n++) + samples[n + 4] = fill; + finished = 1; + break; + case 4: + for (int n = 0; n < s->nb_samples; n++) + samples[n + 4] = 0; + finished = 1; + break; + case 3: + for (int n = 0; n < s->nb_samples; n++) + samples[n + 4] = get_srice(gb, k) + (samples[n + 3] - samples[n + 2]) * 3 + + samples[n + 1]; + finished = 1; + break; + case 2: + for (int n = 0; n < s->nb_samples; n++) + samples[n + 4] = get_srice(gb, k) + (samples[n + 3] * 2 - samples[n + 2]); + finished = 1; + break; + case 1: + for (int n = 0; n < s->nb_samples; n++) + samples[n + 4] = get_srice(gb, k) + samples[n + 3]; + finished = 1; + break; + case 0: + for (int n = 0; n < s->nb_samples; n++) + samples[n + 4] = get_srice(gb, k); + finished = 1; + break; + default: + return AVERROR_INVALIDDATA; + } + + if (finished == 1 && avctx->ch_layout.nb_channels == 2) { + if (ch == 0) + correlated = get_bits1(gb); + finished = ch != 0; + do_stereo(s, ch, correlated, 4); + ch = 1; + } + } + + if (avctx->ch_layout.nb_channels == 1) { + for (int n = 0; n < 4; n++) + s->samples[0][n] = s->samples[0][s->nb_samples + n] >> s->shift; + } + + return 0; +} + +static int decode_2slp(AVCodecContext *avctx, + WavArcContext *s, GetBitContext *gb) +{ + int ch, finished, fill, correlated, order; + + ch = 0; + finished = 0; + while (!finished) { + int *samples = s->samples[ch]; + int k, block_type; + + if (get_bits_left(gb) <= 0) + return AVERROR_INVALIDDATA; + + block_type = get_urice(gb, 1); + if (block_type < 5 && block_type >= 0) { + k = 1 + (avctx->sample_fmt == AV_SAMPLE_FMT_S16P); + k = get_urice(gb, k) + 1; + } + + switch (block_type) { + case 9: + s->eof = 1; + return AVERROR_EOF; + case 8: + s->nb_samples = get_urice(gb, 8); + continue; + case 7: + s->shift = get_urice(gb, 2); + continue; + case 6: + if (avctx->sample_fmt == AV_SAMPLE_FMT_U8P) { + fill = (int8_t)get_bits(gb, 8); + fill -= 0x80; + } else { + fill = (int16_t)get_bits(gb, 16); + fill -= 0x8000; + } + + for (int n = 0; n < s->nb_samples; n++) + samples[n + 70] = fill; + finished = 1; + break; + case 5: + for (int n = 0; n < s->nb_samples; n++) + samples[n + 70] = 0; + finished = 1; + break; + case 4: + for (int n = 0; n < s->nb_samples; n++) + samples[n + 70] = get_srice(gb, k) + (samples[n + 69] - samples[n + 68]) * 3 + + samples[n + 67]; + finished = 1; + break; + case 3: + for (int n = 0; n < s->nb_samples; n++) + samples[n + 70] = get_srice(gb, k) + (samples[n + 69] * 2 - samples[n + 68]); + finished = 1; + break; + case 2: + for (int n = 0; n < s->nb_samples; n++) + samples[n + 70] = get_srice(gb, k); + finished = 1; + break; + case 1: + for (int n = 0; n < s->nb_samples; n++) + samples[n + 70] = get_srice(gb, k) + samples[n + 69]; + finished = 1; + break; + case 0: + order = get_urice(gb, 2); + for (int o = 0; o < order; o++) + s->filter[ch][o] = get_srice(gb, 2); + for (int n = 0; n < s->nb_samples; n++) { + int sum = 15; + + for (int o = 0; o < order; o++) + sum += s->filter[ch][o] * samples[n + 70 - o - 1]; + + samples[n + 70] = get_srice(gb, k) + (sum >> 4); + } + finished = 1; + break; + default: + return AVERROR_INVALIDDATA; + } + + if (finished == 1 && avctx->ch_layout.nb_channels == 2) { + if (ch == 0) + correlated = get_bits1(gb); + finished = ch != 0; + do_stereo(s, ch, correlated, 70); + ch = 1; + } + } + + if (avctx->ch_layout.nb_channels == 1) { + for (int n = 0; n < 70; n++) + s->samples[0][n] = s->samples[0][s->nb_samples + n] >> s->shift; + } + + return 0; +} + +static int wavarc_decode(AVCodecContext *avctx, AVFrame *frame, + int *got_frame_ptr, AVPacket *pkt) +{ + WavArcContext *s = avctx->priv_data; + GetBitContext *gb = &s->gb; + int buf_size, input_buf_size; + const uint8_t *buf; + int ret, n; + + if ((!pkt->size && !s->bitstream_size) || s->nb_samples == 0 || s->eof) { + *got_frame_ptr = 0; + return pkt->size; + } + + buf_size = FFMIN(pkt->size, s->max_framesize - s->bitstream_size); + input_buf_size = buf_size; + if (s->bitstream_index + s->bitstream_size + buf_size + AV_INPUT_BUFFER_PADDING_SIZE > s->max_framesize) { + memmove(s->bitstream, &s->bitstream[s->bitstream_index], s->bitstream_size); + s->bitstream_index = 0; + } + if (pkt->data) + memcpy(&s->bitstream[s->bitstream_index + s->bitstream_size], pkt->data, buf_size); + buf = &s->bitstream[s->bitstream_index]; + buf_size += s->bitstream_size; + s->bitstream_size = buf_size; + if (buf_size < s->max_framesize && pkt->data) { + *got_frame_ptr = 0; + return input_buf_size; + } + + if ((ret = init_get_bits8(gb, buf, buf_size)) < 0) + return ret; + skip_bits(gb, s->skip); + + switch (avctx->codec_tag) { + case MKTAG('1','D','I','F'): + ret = decode_1dif(avctx, s, gb); + break; + case MKTAG('2','S','L','P'): + case MKTAG('3','N','L','P'): + case MKTAG('4','A','L','P'): + ret = decode_2slp(avctx, s, gb); + break; + default: + ret = AVERROR_INVALIDDATA; + } + + if (ret < 0) + goto fail; + + s->skip = get_bits_count(gb) - 8 * (get_bits_count(gb) / 8); + n = get_bits_count(gb) / 8; + + if (n > buf_size) { +fail: + s->bitstream_size = 0; + s->bitstream_index = 0; + return ret; + } + + frame->nb_samples = s->nb_samples; + if ((ret = ff_get_buffer(avctx, frame, 0)) < 0) + return ret; + + switch (avctx->sample_fmt) { + case AV_SAMPLE_FMT_U8P: + for (int ch = 0; ch < avctx->ch_layout.nb_channels; ch++) { + uint8_t *dst = (uint8_t *)frame->extended_data[ch]; + const int *src = s->samples[ch] + s->offset; + + for (int n = 0; n < frame->nb_samples; n++) + dst[n] = src[n] * (1 << s->shift); + } + break; + case AV_SAMPLE_FMT_S16P: + for (int ch = 0; ch < avctx->ch_layout.nb_channels; ch++) { + int16_t *dst = (int16_t *)frame->extended_data[ch]; + const int *src = s->samples[ch] + s->offset; + + for (int n = 0; n < frame->nb_samples; n++) + dst[n] = src[n] * (1 << s->shift); + } + break; + } + + *got_frame_ptr = 1; + + if (s->bitstream_size) { + s->bitstream_index += n; + s->bitstream_size -= n; + return input_buf_size; + } + + return n; +} + +static av_cold int wavarc_close(AVCodecContext *avctx) +{ + WavArcContext *s = avctx->priv_data; + + av_freep(&s->bitstream); + s->bitstream_size = 0; + + return 0; +} + +const FFCodec ff_wavarc_decoder = { + .p.name = "wavarc", + CODEC_LONG_NAME("Waveform Archiver"), + .p.type = AVMEDIA_TYPE_AUDIO, + .p.id = AV_CODEC_ID_WAVARC, + .priv_data_size = sizeof(WavArcContext), + .init = wavarc_init, + FF_CODEC_DECODE_CB(wavarc_decode), + .close = wavarc_close, + .p.capabilities = AV_CODEC_CAP_DR1 | + AV_CODEC_CAP_SUBFRAMES | + AV_CODEC_CAP_DELAY, + .p.sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_U8P, + AV_SAMPLE_FMT_S16P, + AV_SAMPLE_FMT_NONE }, +}; From 4e3e70c19dc6257a97c0cac5dabb3fc9846aa76f Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Sat, 21 Jan 2023 19:17:38 +0100 Subject: [PATCH 0153/2172] avformat: add WavArc demuxer --- Changelog | 2 +- doc/general_contents.texi | 1 + libavformat/Makefile | 1 + libavformat/allformats.c | 1 + libavformat/version.h | 2 +- libavformat/wavarc.c | 126 ++++++++++++++++++++++++++++++++++++++ 6 files changed, 131 insertions(+), 2 deletions(-) create mode 100644 libavformat/wavarc.c diff --git a/Changelog b/Changelog index 2d2206e1ba9..7c3bd7f80cb 100644 --- a/Changelog +++ b/Changelog @@ -37,7 +37,7 @@ version : - XMD ADPCM decoder and demuxer - media100 to mjpegb bsf - ffmpeg CLI new option: -fix_sub_duration_heartbeat -- WavArc decoder +- WavArc decoder and demuxer version 5.1: diff --git a/doc/general_contents.texi b/doc/general_contents.texi index 84df3432cf3..33f3c18c7a4 100644 --- a/doc/general_contents.texi +++ b/doc/general_contents.texi @@ -707,6 +707,7 @@ library: @tab Audio format used in Sony PS games. @item Marble WADY @tab @tab X @item WAV @tab X @tab X +@item Waveform Archiver @tab @tab X @item WavPack @tab X @tab X @item WebM @tab X @tab X @item Windows Televison (WTV) @tab X @tab X diff --git a/libavformat/Makefile b/libavformat/Makefile index 0bb9e8c19af..d68b78ce340 100644 --- a/libavformat/Makefile +++ b/libavformat/Makefile @@ -598,6 +598,7 @@ OBJS-$(CONFIG_VQF_DEMUXER) += vqf.o OBJS-$(CONFIG_W64_DEMUXER) += wavdec.o w64.o pcm.o OBJS-$(CONFIG_W64_MUXER) += wavenc.o w64.o OBJS-$(CONFIG_WADY_DEMUXER) += wady.o pcm.o +OBJS-$(CONFIG_WAVARC_DEMUXER) += wavarc.o rawdec.o OBJS-$(CONFIG_WAV_DEMUXER) += wavdec.o pcm.o OBJS-$(CONFIG_WAV_MUXER) += wavenc.o OBJS-$(CONFIG_WC3_DEMUXER) += wc3movie.o diff --git a/libavformat/allformats.c b/libavformat/allformats.c index 2d31956fd57..b5a3d909bd9 100644 --- a/libavformat/allformats.c +++ b/libavformat/allformats.c @@ -480,6 +480,7 @@ extern const AVInputFormat ff_vqf_demuxer; extern const AVInputFormat ff_w64_demuxer; extern const AVOutputFormat ff_w64_muxer; extern const AVInputFormat ff_wady_demuxer; +extern const AVInputFormat ff_wavarc_demuxer; extern const AVInputFormat ff_wav_demuxer; extern const AVOutputFormat ff_wav_muxer; extern const AVInputFormat ff_wc3_demuxer; diff --git a/libavformat/version.h b/libavformat/version.h index 789859fbe29..134cdb2b899 100644 --- a/libavformat/version.h +++ b/libavformat/version.h @@ -31,7 +31,7 @@ #include "version_major.h" -#define LIBAVFORMAT_VERSION_MINOR 37 +#define LIBAVFORMAT_VERSION_MINOR 38 #define LIBAVFORMAT_VERSION_MICRO 100 #define LIBAVFORMAT_VERSION_INT AV_VERSION_INT(LIBAVFORMAT_VERSION_MAJOR, \ diff --git a/libavformat/wavarc.c b/libavformat/wavarc.c new file mode 100644 index 00000000000..41ee817a1ea --- /dev/null +++ b/libavformat/wavarc.c @@ -0,0 +1,126 @@ +/* + * WavArc demuxer + * Copyright (c) 2023 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 "libavutil/channel_layout.h" +#include "libavutil/intreadwrite.h" +#include "avformat.h" +#include "demux.h" +#include "internal.h" +#include "rawdec.h" + +static int wavarc_probe(const AVProbeData *p) +{ + int len = p->buf[0]; + uint32_t id; + + if (len == 0 || len + 6 >= p->buf_size) + return 0; + + if (p->buf[len + 1] != 0) + return 0; + + id = AV_RL32(p->buf + len + 2); + if (id != MKTAG('1','D','I','F') && + id != MKTAG('2','S','L','P') && + id != MKTAG('3','N','L','P') && + id != MKTAG('4','A','L','P') && + id != MKTAG('5','E','L','P')) + return 0; + + return AVPROBE_SCORE_MAX / 3 * 2; +} + +static int wavarc_read_header(AVFormatContext *s) +{ + AVIOContext *pb = s->pb; + AVCodecParameters *par; + int filename_len, fmt_len, ret; + uint8_t data[36]; + AVStream *st; + uint32_t id; + + filename_len = avio_r8(pb); + if (filename_len == 0) + return AVERROR_INVALIDDATA; + avio_skip(pb, filename_len); + if (avio_r8(pb)) + return AVERROR_INVALIDDATA; + id = avio_rl32(pb); + if (avio_read(pb, data, sizeof(data)) != sizeof(data)) + return AVERROR(EIO); + fmt_len = AV_RL32(data + 32); + if (fmt_len < 12) + return AVERROR_INVALIDDATA; + + st = avformat_new_stream(s, NULL); + if (!st) + return AVERROR(ENOMEM); + par = st->codecpar; + + ret = ff_alloc_extradata(par, fmt_len + sizeof(data)); + if (ret < 0) + return ret; + memcpy(par->extradata, data, sizeof(data)); + avio_read(pb, par->extradata + sizeof(data), fmt_len); + + par->codec_type = AVMEDIA_TYPE_AUDIO; + par->codec_id = AV_CODEC_ID_WAVARC; + par->codec_tag = id; + + do { + id = avio_rl32(pb); + if (id != MKTAG('d','a','t','a')) + avio_skip(pb, avio_rl32(pb)); + } while (id != MKTAG('d','a','t','a')); + avio_skip(pb, 4); + + if (AV_RL32(par->extradata + 16) != MKTAG('R','I','F','F')) + return AVERROR_INVALIDDATA; + if (AV_RL32(par->extradata + 24) != MKTAG('W','A','V','E')) + return AVERROR_INVALIDDATA; + if (AV_RL32(par->extradata + 28) != MKTAG('f','m','t',' ')) + return AVERROR_INVALIDDATA; + + av_channel_layout_default(&par->ch_layout, AV_RL16(par->extradata + 38)); + par->sample_rate = AV_RL32(par->extradata + 40); + avpriv_set_pts_info(st, 64, 1, par->sample_rate); + st->start_time = 0; + + switch (par->extradata[36]) { + case 0: par->format = AV_SAMPLE_FMT_U8P; break; + case 1: par->format = AV_SAMPLE_FMT_S16P; break; + } + + return 0; +} + +const AVInputFormat ff_wavarc_demuxer = { + .name = "wavarc", + .long_name = NULL_IF_CONFIG_SMALL("Waveform Archiver"), + .read_probe = wavarc_probe, + .read_packet = ff_raw_read_partial_packet, + .flags = AVFMT_NOBINSEARCH | AVFMT_NOGENSEARCH | AVFMT_NO_BYTE_SEEK | AVFMT_NOTIMESTAMPS, + .read_header = wavarc_read_header, + .extensions = "wa", + .raw_codec_id = AV_CODEC_ID_WAVARC, + .priv_data_size = sizeof(FFRawDemuxerContext), + .priv_class = &ff_raw_demuxer_class, +}; From 332a4d798d5c0bc3de809f6db22e99ae428d2776 Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Sat, 4 Feb 2023 08:52:42 +0100 Subject: [PATCH 0154/2172] avformat/lafdec: error out on partial packet header read --- libavformat/lafdec.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/libavformat/lafdec.c b/libavformat/lafdec.c index d6ef8415a95..d63d76d74f9 100644 --- a/libavformat/lafdec.c +++ b/libavformat/lafdec.c @@ -185,7 +185,9 @@ static int laf_read_packet(AVFormatContext *ctx, AVPacket *pkt) if (s->index >= ctx->nb_streams) { int cur_st = 0, st_count = 0, st_index = 0; - avio_read(pb, s->header, s->header_len); + ret = ffio_read_size(pb, s->header, s->header_len); + if (ret < 0) + return ret; for (int i = 0; i < s->header_len; i++) { uint8_t val = s->header[i]; From 4b922218e9ee581b9d41e73f38e132b94f79deb5 Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Sat, 4 Feb 2023 08:55:22 +0100 Subject: [PATCH 0155/2172] avformat/lafdec: check for not supported bpp --- libavformat/lafdec.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/libavformat/lafdec.c b/libavformat/lafdec.c index d63d76d74f9..59a59dcfe9c 100644 --- a/libavformat/lafdec.c +++ b/libavformat/lafdec.c @@ -132,6 +132,8 @@ static int laf_read_header(AVFormatContext *ctx) codec_id = AV_CODEC_ID_PCM_S24LE; bpp = 3; break; + default: + return AVERROR_INVALIDDATA; } s->index = 0; From 82da22066c0818b606812d479674929a229386e2 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Tue, 31 Jan 2023 13:11:20 +0100 Subject: [PATCH 0156/2172] lavc: deprecate CrystalHD decoders The hardware is old and not relevant today. The decoders also have many special quirks and are effectively unmaintained. --- Changelog | 1 + MAINTAINERS | 2 -- configure | 4 +++- libavcodec/crystalhd.c | 4 ++++ libavcodec/version_major.h | 3 +++ 5 files changed, 11 insertions(+), 3 deletions(-) diff --git a/Changelog b/Changelog index 7c3bd7f80cb..df9cd69da2d 100644 --- a/Changelog +++ b/Changelog @@ -38,6 +38,7 @@ version : - media100 to mjpegb bsf - ffmpeg CLI new option: -fix_sub_duration_heartbeat - WavArc decoder and demuxer +- CrystalHD decoders deprecated version 5.1: diff --git a/MAINTAINERS b/MAINTAINERS index 48e2ec4fd4d..f87d43fce5c 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -151,7 +151,6 @@ Codecs: ccaption_dec.c Anshul Maheshwari, Aman Gupta cljr Alex Beregszaszi cpia.c Stephan Hilb - crystalhd.c Philip Langdale cscd.c Reimar Doeffinger cuviddec.c Timo Rothenpieler dca* foo86 @@ -265,7 +264,6 @@ Codecs: xwd* Paul B Mahol Hardware acceleration: - crystalhd.c Philip Langdale dxva2* Hendrik Leppkes, Laurent Aimar, Steve Lhomme d3d11va* Steve Lhomme mediacodec* Matthieu Bouron, Aman Gupta diff --git a/configure b/configure index c726076da1a..d67855c7299 100755 --- a/configure +++ b/configure @@ -7001,7 +7001,9 @@ enabled vdpau && enabled vdpau && check_lib vdpau_x11 "vdpau/vdpau.h vdpau/vdpau_x11.h" vdp_device_create_x11 -lvdpau -lX11 -enabled crystalhd && check_lib crystalhd "stdint.h libcrystalhd/libcrystalhd_if.h" DtsCrystalHDVersion -lcrystalhd +enabled crystalhd && check_lib crystalhd "stdint.h libcrystalhd/libcrystalhd_if.h" DtsCrystalHDVersion -lcrystalhd && \ + warn "CrystalHD support is deprecated and will be removed, please contact the developers if you are interested" \ + "in maintaining it." if enabled vulkan; then check_pkg_config_header_only vulkan "vulkan >= 1.2.189" "vulkan/vulkan.h" "defined VK_VERSION_1_2" || diff --git a/libavcodec/crystalhd.c b/libavcodec/crystalhd.c index 8673a491d42..688cdffbcb5 100644 --- a/libavcodec/crystalhd.c +++ b/libavcodec/crystalhd.c @@ -329,6 +329,10 @@ static av_cold int init(AVCodecContext *avctx) av_log(avctx, AV_LOG_VERBOSE, "CrystalHD Init for %s\n", avctx->codec->name); + av_log(avctx, AV_LOG_WARNING, "CrystalHD support is deprecated and will " + "be removed. Please contact the developers if you are interested in " + "maintaining it.\n"); + avctx->pix_fmt = AV_PIX_FMT_YUYV422; /* Initialize the library */ diff --git a/libavcodec/version_major.h b/libavcodec/version_major.h index 2c0443c4c8e..f38566f62c2 100644 --- a/libavcodec/version_major.h +++ b/libavcodec/version_major.h @@ -55,4 +55,7 @@ #define FF_API_VT_HWACCEL_CONTEXT (LIBAVCODEC_VERSION_MAJOR < 60) #define FF_API_AVCODEC_CHROMA_POS (LIBAVCODEC_VERSION_MAJOR < 60) +// reminder to remove CrystalHD decoders on next major bump +#define FF_CODEC_CRYSTAL_HD (LIBAVCODEC_VERSION_MAJOR < 61) + #endif /* AVCODEC_VERSION_MAJOR_H */ From d02340b9e3e72f401cddbeb3bcc3cb584902b886 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Tue, 31 Jan 2023 11:07:50 +0100 Subject: [PATCH 0157/2172] lavc/decode: allow using AV_CODEC_FLAG_COPY_OPAQUE for decoding Use it to propagate AVPacket.opaque[_ref] to corresponding AVFrame fields. This is a more convenient alternative to reordered_opaque. --- doc/APIchanges | 3 +++ libavcodec/avcodec.h | 9 +++++++++ libavcodec/decode.c | 12 ++++++++++-- libavcodec/decode.h | 3 ++- libavcodec/libdav1d.c | 31 +++++++++++++++++++++++-------- libavcodec/version.h | 2 +- 6 files changed, 48 insertions(+), 12 deletions(-) diff --git a/doc/APIchanges b/doc/APIchanges index bc52a079644..6baf914760d 100644 --- a/doc/APIchanges +++ b/doc/APIchanges @@ -14,6 +14,9 @@ libavutil: 2021-04-27 API changes, most recent first: +2023-0x-xx - xxxxxxxxxx - lavc 59.63.100 + Allow AV_CODEC_FLAG_COPY_OPAQUE to be used with decoders. + 2023-01-29 - xxxxxxxxxx - lavc 59.59.100 - avcodec.h Add AV_CODEC_FLAG_COPY_OPAQUE and AV_CODEC_FLAG_FRAME_DURATION. diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h index 90b437ccbe2..eba9ea73d71 100644 --- a/libavcodec/avcodec.h +++ b/libavcodec/avcodec.h @@ -242,9 +242,15 @@ typedef struct RcOverride{ */ #define AV_CODEC_FLAG_RECON_FRAME (1 << 6) /** + * @par decoding + * Request the decoder to propagate each packets AVPacket.opaque and + * AVPacket.opaque_ref to its corresponding output AVFrame. + * + * @par encoding: * Request the encoder to propagate each frame's AVFrame.opaque and * AVFrame.opaque_ref values to its corresponding output AVPacket. * + * @par * May only be set on encoders that have the * @ref AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE capability flag. * @@ -265,6 +271,9 @@ typedef struct RcOverride{ * . * When an output packet contains multiple frames, the opaque values will be * taken from the first of those. + * + * @note + * The converse holds for decoders, with frames and packets switched. */ #define AV_CODEC_FLAG_COPY_OPAQUE (1 << 7) /** diff --git a/libavcodec/decode.c b/libavcodec/decode.c index 0abc88737b2..17b398e9334 100644 --- a/libavcodec/decode.c +++ b/libavcodec/decode.c @@ -1291,7 +1291,8 @@ static int add_metadata_from_side_data(const AVPacket *avpkt, AVFrame *frame) return av_packet_unpack_dictionary(side_metadata, size, frame_md); } -int ff_decode_frame_props_from_pkt(AVFrame *frame, const AVPacket *pkt) +int ff_decode_frame_props_from_pkt(const AVCodecContext *avctx, + AVFrame *frame, const AVPacket *pkt) { static const struct { enum AVPacketSideDataType packet; @@ -1336,6 +1337,13 @@ int ff_decode_frame_props_from_pkt(AVFrame *frame, const AVPacket *pkt) frame->flags = (frame->flags & ~AV_FRAME_FLAG_DISCARD); } + if (avctx->flags & AV_CODEC_FLAG_COPY_OPAQUE) { + int ret = av_buffer_replace(&frame->opaque_ref, pkt->opaque_ref); + if (ret < 0) + return ret; + frame->opaque = pkt->opaque; + } + return 0; } @@ -1344,7 +1352,7 @@ int ff_decode_frame_props(AVCodecContext *avctx, AVFrame *frame) const AVPacket *pkt = avctx->internal->last_pkt_props; if (!(ffcodec(avctx->codec)->caps_internal & FF_CODEC_CAP_SETS_FRAME_PROPS)) { - int ret = ff_decode_frame_props_from_pkt(frame, pkt); + int ret = ff_decode_frame_props_from_pkt(avctx, frame, pkt); if (ret < 0) return ret; frame->pkt_size = (int)(intptr_t)pkt->opaque; diff --git a/libavcodec/decode.h b/libavcodec/decode.h index 906122b4a73..8430ffbd664 100644 --- a/libavcodec/decode.h +++ b/libavcodec/decode.h @@ -72,7 +72,8 @@ int ff_decode_get_packet(AVCodecContext *avctx, AVPacket *pkt); /** * Set various frame properties from the provided packet. */ -int ff_decode_frame_props_from_pkt(AVFrame *frame, const AVPacket *pkt); +int ff_decode_frame_props_from_pkt(const AVCodecContext *avctx, + AVFrame *frame, const AVPacket *pkt); /** * Set various frame properties from the codec context / packet data. diff --git a/libavcodec/libdav1d.c b/libavcodec/libdav1d.c index b43af03732a..f7d75f94392 100644 --- a/libavcodec/libdav1d.c +++ b/libavcodec/libdav1d.c @@ -288,6 +288,11 @@ static void libdav1d_flush(AVCodecContext *c) dav1d_flush(dav1d->c); } +typedef struct OpaqueData { + void *pkt_orig_opaque; + int64_t reordered_opaque; +} OpaqueData; + static void libdav1d_data_free(const uint8_t *data, void *opaque) { AVBufferRef *buf = opaque; @@ -307,6 +312,7 @@ static int libdav1d_receive_frame(AVCodecContext *c, AVFrame *frame) Dav1dData *data = &dav1d->data; Dav1dPicture pic = { 0 }, *p = &pic; AVPacket *pkt; + OpaqueData *od = NULL; #if FF_DAV1D_VERSION_AT_LEAST(5,1) enum Dav1dEventFlags event_flags = 0; #endif @@ -333,17 +339,19 @@ static int libdav1d_receive_frame(AVCodecContext *c, AVFrame *frame) } pkt->buf = NULL; - pkt->opaque = NULL; - if (c->reordered_opaque != AV_NOPTS_VALUE) { - pkt->opaque = av_memdup(&c->reordered_opaque, - sizeof(c->reordered_opaque)); - if (!pkt->opaque) { + if (c->reordered_opaque != AV_NOPTS_VALUE || + (pkt->opaque && (c->flags & AV_CODEC_FLAG_COPY_OPAQUE))) { + od = av_mallocz(sizeof(*od)); + if (!od) { av_packet_free(&pkt); dav1d_data_unref(data); return AVERROR(ENOMEM); } + od->pkt_orig_opaque = pkt->opaque; + od->reordered_opaque = c->reordered_opaque; } + pkt->opaque = od; res = dav1d_data_wrap_user_data(data, (const uint8_t *)pkt, libdav1d_user_data_free, pkt); @@ -423,13 +431,20 @@ static int libdav1d_receive_frame(AVCodecContext *c, AVFrame *frame) ff_set_sar(c, frame->sample_aspect_ratio); pkt = (AVPacket *)p->m.user_data.data; - if (pkt->opaque) - memcpy(&frame->reordered_opaque, pkt->opaque, sizeof(frame->reordered_opaque)); + od = pkt->opaque; + if (od && od->reordered_opaque != AV_NOPTS_VALUE) + frame->reordered_opaque = od->reordered_opaque; else frame->reordered_opaque = AV_NOPTS_VALUE; + // restore the original user opaque value for + // ff_decode_frame_props_from_pkt() + pkt->opaque = od ? od->pkt_orig_opaque : NULL; + av_freep(&od); + // match timestamps and packet size - res = ff_decode_frame_props_from_pkt(frame, pkt); + res = ff_decode_frame_props_from_pkt(c, frame, pkt); + pkt->opaque = NULL; if (res < 0) goto fail; diff --git a/libavcodec/version.h b/libavcodec/version.h index 310c80eeef6..a80dc4776d6 100644 --- a/libavcodec/version.h +++ b/libavcodec/version.h @@ -29,7 +29,7 @@ #include "version_major.h" -#define LIBAVCODEC_VERSION_MINOR 62 +#define LIBAVCODEC_VERSION_MINOR 63 #define LIBAVCODEC_VERSION_MICRO 100 #define LIBAVCODEC_VERSION_INT AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \ From bdc76f467f5caaa15b3bd11cbe6c52cc8f2f45b1 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Tue, 31 Jan 2023 12:27:28 +0100 Subject: [PATCH 0158/2172] lavu/frame: deprecate reordered_opaque It is only used in libavcodec, where it's been superseded by AV_CODEC_CAP_COPY_OPAQUE. --- libavcodec/avcodec.h | 5 +++++ libavcodec/codec.h | 6 +++--- libavcodec/decode.c | 4 ++++ libavcodec/encode.c | 4 ++++ libavcodec/libdav1d.c | 15 ++++++++++++++- libavcodec/librav1e.c | 10 ++++++++++ libavcodec/libwebpenc_animencoder.c | 10 ++++++++++ libavcodec/libx264.c | 14 ++++++++++++++ libavcodec/libx265.c | 17 ++++++++++++++++- libavcodec/nvenc.c | 10 ++++++++++ libavcodec/options.c | 4 ++++ libavcodec/pthread_frame.c | 4 ++++ libavutil/frame.c | 4 ++++ libavutil/frame.h | 5 +++++ libavutil/version.h | 1 + 15 files changed, 108 insertions(+), 5 deletions(-) diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h index eba9ea73d71..755e543fac0 100644 --- a/libavcodec/avcodec.h +++ b/libavcodec/avcodec.h @@ -1392,6 +1392,7 @@ typedef struct AVCodecContext { */ int err_recognition; +#if FF_API_REORDERED_OPAQUE /** * opaque 64-bit number (generally a PTS) that will be reordered and * output in AVFrame.reordered_opaque @@ -1400,8 +1401,12 @@ typedef struct AVCodecContext { * supported by encoders with the * AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE capability. * - decoding: Set by user. + * + * @deprecated Use AV_CODEC_FLAG_COPY_OPAQUE instead */ + attribute_deprecated int64_t reordered_opaque; +#endif /** * Hardware accelerator in use diff --git a/libavcodec/codec.h b/libavcodec/codec.h index 77a1a3f5a29..67f9120b447 100644 --- a/libavcodec/codec.h +++ b/libavcodec/codec.h @@ -169,9 +169,9 @@ #define AV_CODEC_CAP_HYBRID (1 << 19) /** - * This codec takes the reordered_opaque field from input AVFrames - * and returns it in the corresponding field in AVCodecContext after - * encoding. + * This encoder can reorder user opaque values from input AVFrames and return + * them with corresponding output packets. + * @see AV_CODEC_FLAG_COPY_OPAQUE */ #define AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE (1 << 20) diff --git a/libavcodec/decode.c b/libavcodec/decode.c index 17b398e9334..03ae27ecdf9 100644 --- a/libavcodec/decode.c +++ b/libavcodec/decode.c @@ -1357,7 +1357,11 @@ int ff_decode_frame_props(AVCodecContext *avctx, AVFrame *frame) return ret; frame->pkt_size = (int)(intptr_t)pkt->opaque; } +#if FF_API_REORDERED_OPAQUE +FF_DISABLE_DEPRECATION_WARNINGS frame->reordered_opaque = avctx->reordered_opaque; +FF_ENABLE_DEPRECATION_WARNINGS +#endif if (frame->color_primaries == AVCOL_PRI_UNSPECIFIED) frame->color_primaries = avctx->color_primaries; diff --git a/libavcodec/encode.c b/libavcodec/encode.c index c92beaf8e1f..b0a9625ca92 100644 --- a/libavcodec/encode.c +++ b/libavcodec/encode.c @@ -193,7 +193,11 @@ int ff_encode_get_frame(AVCodecContext *avctx, AVFrame *frame) int ff_encode_reordered_opaque(AVCodecContext *avctx, AVPacket *pkt, const AVFrame *frame) { +#if FF_API_REORDERED_OPAQUE +FF_DISABLE_DEPRECATION_WARNINGS avctx->reordered_opaque = frame->reordered_opaque; +FF_ENABLE_DEPRECATION_WARNINGS +#endif if (avctx->flags & AV_CODEC_FLAG_COPY_OPAQUE) { int ret = av_buffer_replace(&pkt->opaque_ref, frame->opaque_ref); diff --git a/libavcodec/libdav1d.c b/libavcodec/libdav1d.c index f7d75f94392..2488a709c72 100644 --- a/libavcodec/libdav1d.c +++ b/libavcodec/libdav1d.c @@ -290,7 +290,9 @@ static void libdav1d_flush(AVCodecContext *c) typedef struct OpaqueData { void *pkt_orig_opaque; +#if FF_API_REORDERED_OPAQUE int64_t reordered_opaque; +#endif } OpaqueData; static void libdav1d_data_free(const uint8_t *data, void *opaque) { @@ -340,7 +342,11 @@ static int libdav1d_receive_frame(AVCodecContext *c, AVFrame *frame) pkt->buf = NULL; - if (c->reordered_opaque != AV_NOPTS_VALUE || +FF_DISABLE_DEPRECATION_WARNINGS + if ( +#if FF_API_REORDERED_OPAQUE + c->reordered_opaque != AV_NOPTS_VALUE || +#endif (pkt->opaque && (c->flags & AV_CODEC_FLAG_COPY_OPAQUE))) { od = av_mallocz(sizeof(*od)); if (!od) { @@ -349,7 +355,10 @@ static int libdav1d_receive_frame(AVCodecContext *c, AVFrame *frame) return AVERROR(ENOMEM); } od->pkt_orig_opaque = pkt->opaque; +#if FF_API_REORDERED_OPAQUE od->reordered_opaque = c->reordered_opaque; +#endif +FF_ENABLE_DEPRECATION_WARNINGS } pkt->opaque = od; @@ -432,10 +441,14 @@ static int libdav1d_receive_frame(AVCodecContext *c, AVFrame *frame) pkt = (AVPacket *)p->m.user_data.data; od = pkt->opaque; +#if FF_API_REORDERED_OPAQUE +FF_DISABLE_DEPRECATION_WARNINGS if (od && od->reordered_opaque != AV_NOPTS_VALUE) frame->reordered_opaque = od->reordered_opaque; else frame->reordered_opaque = AV_NOPTS_VALUE; +FF_ENABLE_DEPRECATION_WARNINGS +#endif // restore the original user opaque value for // ff_decode_frame_props_from_pkt() diff --git a/libavcodec/librav1e.c b/libavcodec/librav1e.c index 00d69328fb7..08affabe3e0 100644 --- a/libavcodec/librav1e.c +++ b/libavcodec/librav1e.c @@ -57,7 +57,9 @@ typedef struct librav1eContext { typedef struct FrameData { int64_t pts; int64_t duration; +#if FF_API_REORDERED_OPAQUE int64_t reordered_opaque; +#endif void *frame_opaque; AVBufferRef *frame_opaque_ref; @@ -465,7 +467,11 @@ static int librav1e_receive_packet(AVCodecContext *avctx, AVPacket *pkt) } fd->pts = frame->pts; fd->duration = frame->duration; +#if FF_API_REORDERED_OPAQUE +FF_DISABLE_DEPRECATION_WARNINGS fd->reordered_opaque = frame->reordered_opaque; +FF_ENABLE_DEPRECATION_WARNINGS +#endif if (avctx->flags & AV_CODEC_FLAG_COPY_OPAQUE) { fd->frame_opaque = frame->opaque; @@ -572,7 +578,11 @@ static int librav1e_receive_packet(AVCodecContext *avctx, AVPacket *pkt) fd = rpkt->opaque; pkt->pts = pkt->dts = fd->pts; pkt->duration = fd->duration; +#if FF_API_REORDERED_OPAQUE +FF_DISABLE_DEPRECATION_WARNINGS avctx->reordered_opaque = fd->reordered_opaque; +FF_ENABLE_DEPRECATION_WARNINGS +#endif if (avctx->flags & AV_CODEC_FLAG_COPY_OPAQUE) { pkt->opaque = fd->frame_opaque; diff --git a/libavcodec/libwebpenc_animencoder.c b/libavcodec/libwebpenc_animencoder.c index 440cae1de55..72d704f490f 100644 --- a/libavcodec/libwebpenc_animencoder.c +++ b/libavcodec/libwebpenc_animencoder.c @@ -39,7 +39,9 @@ typedef struct LibWebPAnimContext { int64_t first_frame_pts; // pts of the first encoded frame. int64_t end_pts; // pts + duration of the last frame +#if FF_API_REORDERED_OPAQUE int64_t reordered_opaque; +#endif void *first_frame_opaque; AVBufferRef *first_frame_opaque_ref; @@ -90,7 +92,11 @@ static int libwebp_anim_encode_frame(AVCodecContext *avctx, AVPacket *pkt, if (pkt->pts != AV_NOPTS_VALUE && s->end_pts > pkt->pts) pkt->duration = s->end_pts - pkt->pts; +#if FF_API_REORDERED_OPAQUE +FF_DISABLE_DEPRECATION_WARNINGS avctx->reordered_opaque = s->reordered_opaque; +FF_ENABLE_DEPRECATION_WARNINGS +#endif if (avctx->flags & AV_CODEC_FLAG_COPY_OPAQUE) { pkt->opaque = s->first_frame_opaque; pkt->opaque_ref = s->first_frame_opaque_ref; @@ -128,7 +134,11 @@ static int libwebp_anim_encode_frame(AVCodecContext *avctx, AVPacket *pkt, if (!avctx->frame_number) { s->first_frame_pts = frame->pts; +#if FF_API_REORDERED_OPAQUE +FF_DISABLE_DEPRECATION_WARNINGS s->reordered_opaque = frame->reordered_opaque; +FF_ENABLE_DEPRECATION_WARNINGS +#endif if (avctx->flags & AV_CODEC_FLAG_COPY_OPAQUE) { s->first_frame_opaque = frame->opaque; diff --git a/libavcodec/libx264.c b/libavcodec/libx264.c index 2742fb11a06..f65ac5dacc2 100644 --- a/libavcodec/libx264.c +++ b/libavcodec/libx264.c @@ -50,7 +50,9 @@ #define MB_SIZE 16 typedef struct X264Opaque { +#if FF_API_REORDERED_OPAQUE int64_t reordered_opaque; +#endif int64_t wallclock; int64_t duration; @@ -459,7 +461,11 @@ static int setup_frame(AVCodecContext *ctx, const AVFrame *frame, goto fail; } +#if FF_API_REORDERED_OPAQUE +FF_DISABLE_DEPRECATION_WARNINGS opaque->reordered_opaque = frame->reordered_opaque; +FF_ENABLE_DEPRECATION_WARNINGS +#endif opaque->duration = frame->duration; opaque->wallclock = wallclock; if (ctx->export_side_data & AV_CODEC_EXPORT_DATA_PRFT) @@ -612,7 +618,11 @@ static int X264_frame(AVCodecContext *ctx, AVPacket *pkt, const AVFrame *frame, out_opaque = pic_out.opaque; if (out_opaque >= x4->reordered_opaque && out_opaque < &x4->reordered_opaque[x4->nb_reordered_opaque]) { +#if FF_API_REORDERED_OPAQUE +FF_DISABLE_DEPRECATION_WARNINGS ctx->reordered_opaque = out_opaque->reordered_opaque; +FF_ENABLE_DEPRECATION_WARNINGS +#endif wallclock = out_opaque->wallclock; pkt->duration = out_opaque->duration; @@ -627,7 +637,11 @@ static int X264_frame(AVCodecContext *ctx, AVPacket *pkt, const AVFrame *frame, // Unexpected opaque pointer on picture output av_log(ctx, AV_LOG_ERROR, "Unexpected opaque pointer; " "this is a bug, please report it.\n"); +#if FF_API_REORDERED_OPAQUE +FF_DISABLE_DEPRECATION_WARNINGS ctx->reordered_opaque = 0; +FF_ENABLE_DEPRECATION_WARNINGS +#endif } switch (pic_out.i_type) { diff --git a/libavcodec/libx265.c b/libavcodec/libx265.c index 6fc189f1b5d..6a2600c5e7e 100644 --- a/libavcodec/libx265.c +++ b/libavcodec/libx265.c @@ -42,7 +42,9 @@ #include "sei.h" typedef struct ReorderedData { +#if FF_API_REORDERED_OPAQUE int64_t reordered_opaque; +#endif int64_t duration; void *frame_opaque; @@ -618,7 +620,11 @@ static int libx265_encode_frame(AVCodecContext *avctx, AVPacket *pkt, rd = &ctx->rd[rd_idx]; rd->duration = pic->duration; +#if FF_API_REORDERED_OPAQUE +FF_DISABLE_DEPRECATION_WARNINGS rd->reordered_opaque = pic->reordered_opaque; +FF_ENABLE_DEPRECATION_WARNINGS +#endif if (avctx->flags & AV_CODEC_FLAG_COPY_OPAQUE) { rd->frame_opaque = pic->opaque; ret = av_buffer_replace(&rd->frame_opaque_ref, pic->opaque_ref); @@ -756,7 +762,11 @@ static int libx265_encode_frame(AVCodecContext *avctx, AVPacket *pkt, int idx = (int)(intptr_t)x265pic_out.userData - 1; ReorderedData *rd = &ctx->rd[idx]; +#if FF_API_REORDERED_OPAQUE +FF_DISABLE_DEPRECATION_WARNINGS avctx->reordered_opaque = rd->reordered_opaque; +FF_ENABLE_DEPRECATION_WARNINGS +#endif pkt->duration = rd->duration; if (avctx->flags & AV_CODEC_FLAG_COPY_OPAQUE) { @@ -766,8 +776,13 @@ static int libx265_encode_frame(AVCodecContext *avctx, AVPacket *pkt, } rd_release(ctx, idx); - } else + } +#if FF_API_REORDERED_OPAQUE + else +FF_DISABLE_DEPRECATION_WARNINGS avctx->reordered_opaque = 0; +FF_ENABLE_DEPRECATION_WARNINGS +#endif *got_packet = 1; return 0; diff --git a/libavcodec/nvenc.c b/libavcodec/nvenc.c index ab42dc9690f..8a284540422 100644 --- a/libavcodec/nvenc.c +++ b/libavcodec/nvenc.c @@ -166,7 +166,9 @@ static int nvenc_print_error(AVCodecContext *avctx, NVENCSTATUS err, typedef struct FrameData { int64_t pts; int64_t duration; +#if FF_API_REORDERED_OPAQUE int64_t reordered_opaque; +#endif void *frame_opaque; AVBufferRef *frame_opaque_ref; @@ -2203,7 +2205,11 @@ static void reorder_queue_enqueue(AVFifo *queue, const AVCodecContext *avctx, fd.pts = frame->pts; fd.duration = frame->duration; +#if FF_API_REORDERED_OPAQUE +FF_DISABLE_DEPRECATION_WARNINGS fd.reordered_opaque = frame->reordered_opaque; +FF_ENABLE_DEPRECATION_WARNINGS +#endif fd.frame_opaque = frame->opaque; fd.frame_opaque_ref = *opaque_ref; @@ -2222,7 +2228,11 @@ static int64_t reorder_queue_dequeue(AVFifo *queue, AVCodecContext *avctx, return AV_NOPTS_VALUE; if (pkt) { +#if FF_API_REORDERED_OPAQUE +FF_DISABLE_DEPRECATION_WARNINGS avctx->reordered_opaque = fd.reordered_opaque; +FF_ENABLE_DEPRECATION_WARNINGS +#endif pkt->duration = fd.duration; if (avctx->flags & AV_CODEC_FLAG_COPY_OPAQUE) { diff --git a/libavcodec/options.c b/libavcodec/options.c index 2e05d29e1ee..9090c94e9c4 100644 --- a/libavcodec/options.c +++ b/libavcodec/options.c @@ -124,7 +124,11 @@ static int init_context_defaults(AVCodecContext *s, const AVCodec *codec) s->sw_pix_fmt = AV_PIX_FMT_NONE; s->sample_fmt = AV_SAMPLE_FMT_NONE; +#if FF_API_REORDERED_OPAQUE +FF_DISABLE_DEPRECATION_WARNINGS s->reordered_opaque = AV_NOPTS_VALUE; +FF_ENABLE_DEPRECATION_WARNINGS +#endif if(codec && codec2->priv_data_size){ s->priv_data = av_mallocz(codec2->priv_data_size); if (!s->priv_data) diff --git a/libavcodec/pthread_frame.c b/libavcodec/pthread_frame.c index 62a0b18a8ac..ae8d051acd7 100644 --- a/libavcodec/pthread_frame.c +++ b/libavcodec/pthread_frame.c @@ -390,7 +390,11 @@ static int update_context_from_user(AVCodecContext *dst, AVCodecContext *src) dst->skip_frame = src->skip_frame; dst->frame_number = src->frame_number; +#if FF_API_REORDERED_OPAQUE +FF_DISABLE_DEPRECATION_WARNINGS dst->reordered_opaque = src->reordered_opaque; +FF_ENABLE_DEPRECATION_WARNINGS +#endif #if FF_API_THREAD_SAFE_CALLBACKS FF_DISABLE_DEPRECATION_WARNINGS dst->thread_safe_callbacks = src->thread_safe_callbacks; diff --git a/libavutil/frame.c b/libavutil/frame.c index fa9b11aa543..2d81de8b0d2 100644 --- a/libavutil/frame.c +++ b/libavutil/frame.c @@ -304,7 +304,11 @@ FF_DISABLE_DEPRECATION_WARNINGS FF_ENABLE_DEPRECATION_WARNINGS #endif dst->time_base = src->time_base; +#if FF_API_REORDERED_OPAQUE +FF_DISABLE_DEPRECATION_WARNINGS dst->reordered_opaque = src->reordered_opaque; +FF_ENABLE_DEPRECATION_WARNINGS +#endif dst->quality = src->quality; dst->best_effort_timestamp = src->best_effort_timestamp; dst->coded_picture_number = src->coded_picture_number; diff --git a/libavutil/frame.h b/libavutil/frame.h index bbe909ee2da..911af515f47 100644 --- a/libavutil/frame.h +++ b/libavutil/frame.h @@ -491,6 +491,7 @@ typedef struct AVFrame { */ int palette_has_changed; +#if FF_API_REORDERED_OPAQUE /** * reordered opaque 64 bits (generally an integer or a double precision float * PTS but can be anything). @@ -498,8 +499,12 @@ typedef struct AVFrame { * that time, * the decoder reorders values as needed and sets AVFrame.reordered_opaque * to exactly one of the values provided by the user through AVCodecContext.reordered_opaque + * + * @deprecated Use AV_CODEC_FLAG_COPY_OPAQUE instead */ + attribute_deprecated int64_t reordered_opaque; +#endif /** * Sample rate of the audio data. diff --git a/libavutil/version.h b/libavutil/version.h index 60f96af5df8..43daf8cd5ad 100644 --- a/libavutil/version.h +++ b/libavutil/version.h @@ -115,6 +115,7 @@ #define FF_API_OLD_CHANNEL_LAYOUT (LIBAVUTIL_VERSION_MAJOR < 58) #define FF_API_AV_FOPEN_UTF8 (LIBAVUTIL_VERSION_MAJOR < 58) #define FF_API_PKT_DURATION (LIBAVUTIL_VERSION_MAJOR < 58) +#define FF_API_REORDERED_OPAQUE (LIBAVUTIL_VERSION_MAJOR < 59) /** * @} From d7c2da1f8d14672ff0768305b87cf118ad320469 Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Mon, 6 Feb 2023 16:32:38 +0100 Subject: [PATCH 0159/2172] avcodec/wavarc: check that nb_samples is valid --- libavcodec/wavarc.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/libavcodec/wavarc.c b/libavcodec/wavarc.c index 898c3c20554..caab08cb246 100644 --- a/libavcodec/wavarc.c +++ b/libavcodec/wavarc.c @@ -258,6 +258,10 @@ static int decode_2slp(AVCodecContext *avctx, return AVERROR_EOF; case 8: s->nb_samples = get_urice(gb, 8); + if (s->nb_samples > 570) { + s->nb_samples = 570; + return AVERROR_INVALIDDATA; + } continue; case 7: s->shift = get_urice(gb, 2); From 64b242d03078630bbe7570d0775d3a68f166306c Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Mon, 6 Feb 2023 18:07:35 +0100 Subject: [PATCH 0160/2172] avcodec/wavarc: fix 8bit decoding --- libavcodec/wavarc.c | 8 ++++---- libavformat/wavarc.c | 7 +------ 2 files changed, 5 insertions(+), 10 deletions(-) diff --git a/libavcodec/wavarc.c b/libavcodec/wavarc.c index caab08cb246..b18a88000b5 100644 --- a/libavcodec/wavarc.c +++ b/libavcodec/wavarc.c @@ -68,9 +68,9 @@ static av_cold int wavarc_init(AVCodecContext *avctx) av_channel_layout_default(&avctx->ch_layout, AV_RL16(avctx->extradata + 38)); avctx->sample_rate = AV_RL32(avctx->extradata + 40); - switch (avctx->extradata[36]) { - case 0: avctx->sample_fmt = AV_SAMPLE_FMT_U8P; break; - case 1: avctx->sample_fmt = AV_SAMPLE_FMT_S16P; break; + switch (AV_RL16(avctx->extradata + 38)) { + case 1: avctx->sample_fmt = AV_SAMPLE_FMT_U8P; break; + case 2: avctx->sample_fmt = AV_SAMPLE_FMT_S16P; break; } s->shift = 0; @@ -411,7 +411,7 @@ static int wavarc_decode(AVCodecContext *avctx, AVFrame *frame, const int *src = s->samples[ch] + s->offset; for (int n = 0; n < frame->nb_samples; n++) - dst[n] = src[n] * (1 << s->shift); + dst[n] = src[n] * (1 << s->shift) + 0x80U; } break; case AV_SAMPLE_FMT_S16P: diff --git a/libavformat/wavarc.c b/libavformat/wavarc.c index 41ee817a1ea..13e56026a7f 100644 --- a/libavformat/wavarc.c +++ b/libavformat/wavarc.c @@ -89,7 +89,7 @@ static int wavarc_read_header(AVFormatContext *s) id = avio_rl32(pb); if (id != MKTAG('d','a','t','a')) avio_skip(pb, avio_rl32(pb)); - } while (id != MKTAG('d','a','t','a')); + } while (id != MKTAG('d','a','t','a') && !avio_feof(pb)); avio_skip(pb, 4); if (AV_RL32(par->extradata + 16) != MKTAG('R','I','F','F')) @@ -104,11 +104,6 @@ static int wavarc_read_header(AVFormatContext *s) avpriv_set_pts_info(st, 64, 1, par->sample_rate); st->start_time = 0; - switch (par->extradata[36]) { - case 0: par->format = AV_SAMPLE_FMT_U8P; break; - case 1: par->format = AV_SAMPLE_FMT_S16P; break; - } - return 0; } From c5aeb8f4db5529cdb5248bbb7154adf6f0c8faf3 Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Mon, 6 Feb 2023 18:26:01 +0100 Subject: [PATCH 0161/2172] avcodec/wavarc: really fix bits per sample detection --- libavcodec/wavarc.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/libavcodec/wavarc.c b/libavcodec/wavarc.c index b18a88000b5..20371b53de6 100644 --- a/libavcodec/wavarc.c +++ b/libavcodec/wavarc.c @@ -52,7 +52,7 @@ static av_cold int wavarc_init(AVCodecContext *avctx) { WavArcContext *s = avctx->priv_data; - if (avctx->extradata_size < 44) + if (avctx->extradata_size < 52) return AVERROR_INVALIDDATA; if (AV_RL32(avctx->extradata + 16) != MKTAG('R','I','F','F')) return AVERROR_INVALIDDATA; @@ -68,9 +68,9 @@ static av_cold int wavarc_init(AVCodecContext *avctx) av_channel_layout_default(&avctx->ch_layout, AV_RL16(avctx->extradata + 38)); avctx->sample_rate = AV_RL32(avctx->extradata + 40); - switch (AV_RL16(avctx->extradata + 38)) { - case 1: avctx->sample_fmt = AV_SAMPLE_FMT_U8P; break; - case 2: avctx->sample_fmt = AV_SAMPLE_FMT_S16P; break; + switch (AV_RL16(avctx->extradata + 50)) { + case 8: avctx->sample_fmt = AV_SAMPLE_FMT_U8P; break; + case 16: avctx->sample_fmt = AV_SAMPLE_FMT_S16P; break; } s->shift = 0; From 000934830620c03be55644e054f9ffaaadac2a0a Mon Sep 17 00:00:00 2001 From: Leo Izen Date: Sat, 4 Feb 2023 16:29:15 -0500 Subject: [PATCH 0162/2172] avcodec/libjxl: add #ifdef guards for libjxl >= 0.8.0 features Since many distributions ship libjxl 0.7.0 still, we'd still prefer to compile against that, but don't want to lose the features that require libjxl 0.8.0 or greater. For this reason I've added preprocessor #ifdef guards around the features that aren't necessarily in libjxl 0.7.0. Signed-off-by: Leo Izen --- libavcodec/libjxl.h | 12 ++++++++++++ libavcodec/libjxldec.c | 19 +++++++++++++------ libavcodec/libjxlenc.c | 18 ++++++++++++++---- 3 files changed, 39 insertions(+), 10 deletions(-) diff --git a/libavcodec/libjxl.h b/libavcodec/libjxl.h index 5387c438fd0..e305b6e7588 100644 --- a/libavcodec/libjxl.h +++ b/libavcodec/libjxl.h @@ -27,8 +27,20 @@ #ifndef AVCODEC_LIBJXL_H #define AVCODEC_LIBJXL_H +#include #include +/* + * libjxl version 0.7.0 and earlier doesn't contain these macros at all + * so to detect version 0.7.0 versus 0.8.0 we need to define them ourselves + */ +#ifndef JPEGXL_COMPUTE_NUMERIC_VERSION + #define JPEGXL_COMPUTE_NUMERIC_VERSION(major,minor,patch) ((major<<24) | (minor<<16) | (patch<<8) | 0) +#endif +#ifndef JPEGXL_NUMERIC_VERSION + #define JPEGXL_NUMERIC_VERSION JPEGXL_COMPUTE_NUMERIC_VERSION(0, 7, 0) +#endif + /** * Transform threadcount in ffmpeg to one used by libjxl. * diff --git a/libavcodec/libjxldec.c b/libavcodec/libjxldec.c index abe08eb4001..045a1535f93 100644 --- a/libavcodec/libjxldec.c +++ b/libavcodec/libjxldec.c @@ -47,7 +47,9 @@ typedef struct LibJxlDecodeContext { JxlDecoder *decoder; JxlBasicInfo basic_info; JxlPixelFormat jxl_pixfmt; +#if JPEGXL_NUMERIC_VERSION >= JPEGXL_COMPUTE_NUMERIC_VERSION(0, 8, 0) JxlBitDepth jxl_bit_depth; +#endif JxlDecoderStatus events; AVBufferRef *iccp; } LibJxlDecodeContext; @@ -94,14 +96,17 @@ static av_cold int libjxl_decode_init(AVCodecContext *avctx) return libjxl_init_jxl_decoder(avctx); } -static enum AVPixelFormat libjxl_get_pix_fmt(AVCodecContext *avctx, const JxlBasicInfo *basic_info, - JxlPixelFormat *format, JxlBitDepth *depth) +static enum AVPixelFormat libjxl_get_pix_fmt(AVCodecContext *avctx, LibJxlDecodeContext *ctx) { + const JxlBasicInfo *basic_info = &ctx->basic_info; + JxlPixelFormat *format = &ctx->jxl_pixfmt; format->endianness = JXL_NATIVE_ENDIAN; format->num_channels = basic_info->num_color_channels + (basic_info->alpha_bits > 0); - depth->bits_per_sample = avctx->bits_per_raw_sample = basic_info->bits_per_sample; - depth->type = JXL_BIT_DEPTH_FROM_PIXEL_FORMAT; - depth->exponent_bits_per_sample = basic_info->exponent_bits_per_sample; +#if JPEGXL_NUMERIC_VERSION >= JPEGXL_COMPUTE_NUMERIC_VERSION(0, 8, 0) + ctx->jxl_bit_depth.bits_per_sample = avctx->bits_per_raw_sample = basic_info->bits_per_sample; + ctx->jxl_bit_depth.type = JXL_BIT_DEPTH_FROM_PIXEL_FORMAT; + ctx->jxl_bit_depth.exponent_bits_per_sample = basic_info->exponent_bits_per_sample; +#endif /* Gray */ if (basic_info->num_color_channels == 1) { if (basic_info->bits_per_sample <= 8) { @@ -372,7 +377,7 @@ static int libjxl_decode_frame(AVCodecContext *avctx, AVFrame *frame, int *got_f av_log(avctx, AV_LOG_ERROR, "Bad libjxl basic info event\n"); return AVERROR_EXTERNAL; } - avctx->pix_fmt = libjxl_get_pix_fmt(avctx, &ctx->basic_info, &ctx->jxl_pixfmt, &ctx->jxl_bit_depth); + avctx->pix_fmt = libjxl_get_pix_fmt(avctx, ctx); if (avctx->pix_fmt == AV_PIX_FMT_NONE) { av_log(avctx, AV_LOG_ERROR, "Bad libjxl pixel format\n"); return AVERROR_EXTERNAL; @@ -395,10 +400,12 @@ static int libjxl_decode_frame(AVCodecContext *avctx, AVFrame *frame, int *got_f av_log(avctx, AV_LOG_ERROR, "Bad libjxl dec need image out buffer event\n"); return AVERROR_EXTERNAL; } +#if JPEGXL_NUMERIC_VERSION >= JPEGXL_COMPUTE_NUMERIC_VERSION(0, 8, 0) if (JxlDecoderSetImageOutBitDepth(ctx->decoder, &ctx->jxl_bit_depth) != JXL_DEC_SUCCESS) { av_log(avctx, AV_LOG_ERROR, "Error setting output bit depth\n"); return AVERROR_EXTERNAL; } +#endif continue; case JXL_DEC_FULL_IMAGE: /* full image is one frame, even if animated */ diff --git a/libavcodec/libjxlenc.c b/libavcodec/libjxlenc.c index c51024f1806..897452f5750 100644 --- a/libavcodec/libjxlenc.c +++ b/libavcodec/libjxlenc.c @@ -250,7 +250,10 @@ static int libjxl_encode_frame(AVCodecContext *avctx, AVPacket *pkt, const AVFra JxlBasicInfo info; JxlColorEncoding jxl_color; JxlPixelFormat jxl_fmt; + int bits_per_sample; +#if JPEGXL_NUMERIC_VERSION >= JPEGXL_COMPUTE_NUMERIC_VERSION(0, 8, 0) JxlBitDepth jxl_bit_depth; +#endif JxlEncoderStatus jret; int ret; size_t available = ctx->buffer_size; @@ -270,22 +273,26 @@ static int libjxl_encode_frame(AVCodecContext *avctx, AVPacket *pkt, const AVFra info.ysize = frame->height; info.num_extra_channels = (jxl_fmt.num_channels + 1) % 2; info.num_color_channels = jxl_fmt.num_channels - info.num_extra_channels; - jxl_bit_depth.bits_per_sample = av_get_bits_per_pixel(pix_desc) / jxl_fmt.num_channels; + bits_per_sample = av_get_bits_per_pixel(pix_desc) / jxl_fmt.num_channels; info.bits_per_sample = avctx->bits_per_raw_sample > 0 && !(pix_desc->flags & AV_PIX_FMT_FLAG_FLOAT) - ? avctx->bits_per_raw_sample : jxl_bit_depth.bits_per_sample; + ? avctx->bits_per_raw_sample : bits_per_sample; info.alpha_bits = (info.num_extra_channels > 0) * info.bits_per_sample; if (pix_desc->flags & AV_PIX_FMT_FLAG_FLOAT) { info.exponent_bits_per_sample = info.bits_per_sample > 16 ? 8 : 5; info.alpha_exponent_bits = info.alpha_bits ? info.exponent_bits_per_sample : 0; jxl_fmt.data_type = info.bits_per_sample > 16 ? JXL_TYPE_FLOAT : JXL_TYPE_FLOAT16; - jxl_bit_depth.exponent_bits_per_sample = info.exponent_bits_per_sample; } else { info.exponent_bits_per_sample = 0; info.alpha_exponent_bits = 0; jxl_fmt.data_type = info.bits_per_sample <= 8 ? JXL_TYPE_UINT8 : JXL_TYPE_UINT16; - jxl_bit_depth.exponent_bits_per_sample = 0; } + +#if JPEGXL_NUMERIC_VERSION >= JPEGXL_COMPUTE_NUMERIC_VERSION(0, 8, 0) + jxl_bit_depth.bits_per_sample = bits_per_sample; jxl_bit_depth.type = JXL_BIT_DEPTH_FROM_PIXEL_FORMAT; + jxl_bit_depth.exponent_bits_per_sample = pix_desc->flags & AV_PIX_FMT_FLAG_FLOAT ? + info.exponent_bits_per_sample : 0; +#endif /* JPEG XL format itself does not support limited range */ if (avctx->color_range == AVCOL_RANGE_MPEG || @@ -362,8 +369,11 @@ static int libjxl_encode_frame(AVCodecContext *avctx, AVPacket *pkt, const AVFra av_log(avctx, AV_LOG_WARNING, "Could not set ICC Profile\n"); if (JxlEncoderSetColorEncoding(ctx->encoder, &jxl_color) != JXL_ENC_SUCCESS) av_log(avctx, AV_LOG_WARNING, "Failed to set JxlColorEncoding\n"); + +#if JPEGXL_NUMERIC_VERSION >= JPEGXL_COMPUTE_NUMERIC_VERSION(0, 8, 0) if (JxlEncoderSetFrameBitDepth(ctx->options, &jxl_bit_depth) != JXL_ENC_SUCCESS) av_log(avctx, AV_LOG_WARNING, "Failed to set JxlBitDepth\n"); +#endif /* depending on basic info, level 10 might * be required instead of level 5 */ From 3b3a321fed016665b602e50de993f96fa59ece30 Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Mon, 6 Feb 2023 20:28:01 +0100 Subject: [PATCH 0163/2172] avcodec/wavarc: remove invalid shifts --- libavcodec/wavarc.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libavcodec/wavarc.c b/libavcodec/wavarc.c index 20371b53de6..956c52bfe90 100644 --- a/libavcodec/wavarc.c +++ b/libavcodec/wavarc.c @@ -226,7 +226,7 @@ static int decode_1dif(AVCodecContext *avctx, if (avctx->ch_layout.nb_channels == 1) { for (int n = 0; n < 4; n++) - s->samples[0][n] = s->samples[0][s->nb_samples + n] >> s->shift; + s->samples[0][n] = s->samples[0][s->nb_samples + n]; } return 0; @@ -334,7 +334,7 @@ static int decode_2slp(AVCodecContext *avctx, if (avctx->ch_layout.nb_channels == 1) { for (int n = 0; n < 70; n++) - s->samples[0][n] = s->samples[0][s->nb_samples + n] >> s->shift; + s->samples[0][n] = s->samples[0][s->nb_samples + n]; } return 0; From f1355ec9f6125ff8eb644e5beb3e3ccd6e35da28 Mon Sep 17 00:00:00 2001 From: Haihao Xiang Date: Thu, 10 Mar 2022 14:34:22 +0800 Subject: [PATCH 0164/2172] lavu/hwcontext_qsv: add support for UYVY The SDK supports UYVY from version 1.17, and VPP may support UYVY input on Linux [1] $ ffmpeg -loglevel verbose -init_hw_device qsv=intel -f lavfi -i \ yuvtestsrc -vf \ "format=uyvy422,hwupload=extra_hw_frames=32,vpp_qsv=format=nv12" \ -f null - [1] https://github.com/Intel-Media-SDK/MediaSDK/blob/master/doc/samples/readme-vpp_linux.md Signed-off-by: Haihao Xiang --- libavutil/hwcontext_qsv.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/libavutil/hwcontext_qsv.c b/libavutil/hwcontext_qsv.c index ec0f72b329e..42851d4fd5d 100644 --- a/libavutil/hwcontext_qsv.c +++ b/libavutil/hwcontext_qsv.c @@ -118,6 +118,8 @@ static const struct { #if CONFIG_VAAPI { AV_PIX_FMT_YUYV422, MFX_FOURCC_YUY2, 0 }, + { AV_PIX_FMT_UYVY422, + MFX_FOURCC_UYVY, 0 }, { AV_PIX_FMT_Y210, MFX_FOURCC_Y210, 1 }, // VUYX is used for VAAPI child device, @@ -1556,6 +1558,11 @@ static int map_frame_to_surface(const AVFrame *frame, mfxFrameSurface1 *surface) // use the value from the frame. surface->Data.A = frame->data[0] + 6; break; + case AV_PIX_FMT_UYVY422: + surface->Data.Y = frame->data[0] + 1; + surface->Data.U = frame->data[0]; + surface->Data.V = frame->data[0] + 2; + break; #endif default: return MFX_ERR_UNSUPPORTED; From 36016c55967622a1475e5ec9cade39543921915c Mon Sep 17 00:00:00 2001 From: Haihao Xiang Date: Thu, 10 Mar 2022 14:39:06 +0800 Subject: [PATCH 0165/2172] lavfi/vf_vpp_qsv: support UYVY in system memory It only works on Linux $ ffmpeg -loglevel verbose -init_hw_device qsv=intel -f lavfi -i \ yuvtestsrc -vf "format=uyvy422,vpp_qsv=format=nv12" -f null - Signed-off-by: Haihao Xiang --- libavfilter/qsvvpp.c | 9 +++++++++ libavfilter/vf_vpp_qsv.c | 3 +++ 2 files changed, 12 insertions(+) diff --git a/libavfilter/qsvvpp.c b/libavfilter/qsvvpp.c index 7e64944f2c6..e181e7b5846 100644 --- a/libavfilter/qsvvpp.c +++ b/libavfilter/qsvvpp.c @@ -247,6 +247,10 @@ static int pix_fmt_to_mfx_fourcc(int format) return MFX_FOURCC_RGB4; case AV_PIX_FMT_P010: return MFX_FOURCC_P010; +#if CONFIG_VAAPI + case AV_PIX_FMT_UYVY422: + return MFX_FOURCC_UYVY; +#endif } return MFX_FOURCC_NV12; @@ -276,6 +280,11 @@ static int map_frame_to_surface(AVFrame *frame, mfxFrameSurface1 *surface) surface->Data.R = frame->data[0] + 2; surface->Data.A = frame->data[0] + 3; break; + case AV_PIX_FMT_UYVY422: + surface->Data.Y = frame->data[0] + 1; + surface->Data.U = frame->data[0]; + surface->Data.V = frame->data[0] + 2; + break; default: return MFX_ERR_UNSUPPORTED; } diff --git a/libavfilter/vf_vpp_qsv.c b/libavfilter/vf_vpp_qsv.c index 010b69943ac..65484fa091f 100644 --- a/libavfilter/vf_vpp_qsv.c +++ b/libavfilter/vf_vpp_qsv.c @@ -703,6 +703,9 @@ static int vpp_query_formats(AVFilterContext *ctx) AV_PIX_FMT_YUYV422, AV_PIX_FMT_RGB32, AV_PIX_FMT_P010, +#if CONFIG_VAAPI + AV_PIX_FMT_UYVY422, +#endif AV_PIX_FMT_QSV, AV_PIX_FMT_NONE }; From 58d6426870ed10e5eeed98418dc3b7b2d4efe2c6 Mon Sep 17 00:00:00 2001 From: Haihao Xiang Date: Thu, 28 Jul 2022 11:16:08 +0800 Subject: [PATCH 0166/2172] lavfi/vf_vpp_qsv: add support for new scaling modes The new modes work on new platforms and are avaialable only for oneVPL. Signed-off-by: Haihao Xiang --- libavfilter/vf_vpp_qsv.c | 31 ++++++++++++++++++++++++++++--- 1 file changed, 28 insertions(+), 3 deletions(-) diff --git a/libavfilter/vf_vpp_qsv.c b/libavfilter/vf_vpp_qsv.c index 65484fa091f..ac77f7bb4ba 100644 --- a/libavfilter/vf_vpp_qsv.c +++ b/libavfilter/vf_vpp_qsv.c @@ -504,8 +504,15 @@ static int config_output(AVFilterLink *outlink) if (inlink->w != outlink->w || inlink->h != outlink->h || in_format != vpp->out_format) { if (QSV_RUNTIME_VERSION_ATLEAST(mfx_version, 1, 19)) { + int mode = vpp->scale_mode; + +#if QSV_ONEVPL + if (mode > 2) + mode = MFX_SCALING_MODE_VENDOR + mode - 2; +#endif + INIT_MFX_EXTBUF(scale_conf, MFX_EXTBUFF_VPP_SCALING); - SET_MFX_PARAM_FIELD(scale_conf, ScalingMode, vpp->scale_mode); + SET_MFX_PARAM_FIELD(scale_conf, ScalingMode, mode); } else av_log(ctx, AV_LOG_WARNING, "The QSV VPP Scale & format conversion " "option is not supported with this MSDK version.\n"); @@ -679,10 +686,19 @@ static const AVOption vpp_options[] = { { "height", "Output video height(0=input video height, -1=keep input video aspect)", 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(qsv.async_depth), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, INT_MAX, .flags = FLAGS }, - { "scale_mode", "scale & format conversion 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" }, +#if QSV_ONEVPL + { "scale_mode", "scaling & format conversion mode (mode compute(3), vd(4) and ve(5) are only available on some platforms)", OFFSET(scale_mode), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 5, .flags = FLAGS, "scale mode" }, +#else + { "scale_mode", "scaling & format conversion mode", 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 { "auto", "auto mode", 0, AV_OPT_TYPE_CONST, { .i64 = MFX_SCALING_MODE_DEFAULT}, INT_MIN, INT_MAX, FLAGS, "scale mode"}, { "low_power", "low power mode", 0, AV_OPT_TYPE_CONST, { .i64 = MFX_SCALING_MODE_LOWPOWER}, INT_MIN, INT_MAX, FLAGS, "scale mode"}, { "hq", "high quality mode", 0, AV_OPT_TYPE_CONST, { .i64 = MFX_SCALING_MODE_QUALITY}, INT_MIN, INT_MAX, FLAGS, "scale mode"}, +#if QSV_ONEVPL + { "compute", "compute", 0, AV_OPT_TYPE_CONST, { .i64 = 3}, INT_MIN, INT_MAX, FLAGS, "scale mode"}, + { "vd", "vd", 0, AV_OPT_TYPE_CONST, { .i64 = 4}, INT_MIN, INT_MAX, FLAGS, "scale mode"}, + { "ve", "ve", 0, AV_OPT_TYPE_CONST, { .i64 = 5}, INT_MIN, INT_MAX, FLAGS, "scale mode"}, +#endif { "rate", "Generate output at frame rate or field rate, available only for deinterlace mode", OFFSET(field_rate), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 1, FLAGS, "rate" }, @@ -735,9 +751,18 @@ static const AVOption qsvscale_options[] = { { "h", "Output video height(0=input video height, -1=keep input video aspect)", OFFSET(oh), AV_OPT_TYPE_STRING, { .str = "ih" }, .flags = FLAGS }, { "format", "Output pixel format", OFFSET(output_format_str), AV_OPT_TYPE_STRING, { .str = "same" }, .flags = FLAGS }, - { "mode", "set scaling mode", OFFSET(scale_mode), AV_OPT_TYPE_INT, { .i64 = MFX_SCALING_MODE_DEFAULT}, MFX_SCALING_MODE_DEFAULT, MFX_SCALING_MODE_QUALITY, FLAGS, "mode"}, +#if QSV_ONEVPL + { "mode", "scaling & format conversion mode (mode compute(3), vd(4) and ve(5) are only available on some platforms)", OFFSET(scale_mode), AV_OPT_TYPE_INT, { .i64 = 0}, 0, 5, FLAGS, "mode"}, +#else + { "mode", "scaling & format conversion mode", OFFSET(scale_mode), AV_OPT_TYPE_INT, { .i64 = MFX_SCALING_MODE_DEFAULT}, MFX_SCALING_MODE_DEFAULT, MFX_SCALING_MODE_QUALITY, FLAGS, "mode"}, +#endif { "low_power", "low power mode", 0, AV_OPT_TYPE_CONST, { .i64 = MFX_SCALING_MODE_LOWPOWER}, INT_MIN, INT_MAX, FLAGS, "mode"}, { "hq", "high quality mode", 0, AV_OPT_TYPE_CONST, { .i64 = MFX_SCALING_MODE_QUALITY}, INT_MIN, INT_MAX, FLAGS, "mode"}, +#if QSV_ONEVPL + { "compute", "compute", 0, AV_OPT_TYPE_CONST, { .i64 = 3}, INT_MIN, INT_MAX, FLAGS, "mode"}, + { "vd", "vd", 0, AV_OPT_TYPE_CONST, { .i64 = 4}, INT_MIN, INT_MAX, FLAGS, "mode"}, + { "ve", "ve", 0, AV_OPT_TYPE_CONST, { .i64 = 5}, INT_MIN, INT_MAX, FLAGS, "mode"}, +#endif { NULL }, }; From 62dfa546886d55109f0ba0afb1c13e59157e524c Mon Sep 17 00:00:00 2001 From: Niklas Haas Date: Tue, 7 Feb 2023 15:09:18 +0100 Subject: [PATCH 0167/2172] avfilter/vf_libplacebo: fix format query We need to construct the output format list separatedly from the input format list, because we need to adhere to two extra requirements: 1. Big-endian output formats are always unsupported (runtime error) 2. Combining 'vulkan' with an explicit out_format that is not supported by the vulkan frame allocation code is illegal and will crash (abort) As a free side benefit, this rewrite fixes a possible memory leak in the `fail` path that was present in the old code. Signed-off-by: Niklas Haas --- libavfilter/vf_libplacebo.c | 52 +++++++++++++++++++++++++------------ 1 file changed, 35 insertions(+), 17 deletions(-) diff --git a/libavfilter/vf_libplacebo.c b/libavfilter/vf_libplacebo.c index 12abca4cc7f..5b310771072 100644 --- a/libavfilter/vf_libplacebo.c +++ b/libavfilter/vf_libplacebo.c @@ -547,10 +547,10 @@ static int filter_frame(AVFilterLink *link, AVFrame *in) static int libplacebo_query_format(AVFilterContext *ctx) { - int err = 0; + int err; LibplaceboContext *s = ctx->priv; const AVPixFmtDescriptor *desc = NULL; - AVFilterFormats *formats = NULL; + AVFilterFormats *infmts = NULL, *outfmts = NULL; RET(init_vulkan(ctx)); @@ -564,29 +564,47 @@ static int libplacebo_query_format(AVFilterContext *ctx) continue; #endif - if (pl_test_pixfmt(s->gpu, pixfmt)) { - if ((err = ff_add_format(&formats, pixfmt)) < 0) - return err; + if (!pl_test_pixfmt(s->gpu, pixfmt)) + continue; + + RET(ff_add_format(&infmts, pixfmt)); + + /* Filter for supported output pixel formats */ + if (desc->flags & AV_PIX_FMT_FLAG_BE) + continue; /* BE formats are not supported by pl_download_avframe */ + + /* Mask based on user specified format */ + if (s->out_format != AV_PIX_FMT_NONE) { + if (pixfmt == AV_PIX_FMT_VULKAN && av_vkfmt_from_pixfmt(s->out_format)) { + /* OK */ + } else if (pixfmt == s->out_format) { + /* OK */ + } else { + continue; /* Not OK */ + } } - } - RET(ff_formats_ref(formats, &ctx->inputs[0]->outcfg.formats)); + RET(ff_add_format(&outfmts, pixfmt)); + } - if (s->out_format != AV_PIX_FMT_NONE) { - /* Support only requested format, and hwaccel (vulkan) */ - const enum AVPixelFormat out_fmts[] = { - s->out_format, AV_PIX_FMT_VULKAN, AV_PIX_FMT_NONE, - }; - RET(ff_formats_ref(ff_make_format_list(out_fmts), - &ctx->outputs[0]->incfg.formats)); - } else { - /* Support all formats */ - RET(ff_formats_ref(formats, &ctx->outputs[0]->incfg.formats)); + if (!infmts || !outfmts) { + if (s->out_format) { + av_log(s, AV_LOG_ERROR, "Invalid output format '%s'!\n", + av_get_pix_fmt_name(s->out_format)); + } + err = AVERROR(EINVAL); + goto fail; } + RET(ff_formats_ref(infmts, &ctx->inputs[0]->outcfg.formats)); + RET(ff_formats_ref(outfmts, &ctx->outputs[0]->incfg.formats)); return 0; fail: + if (infmts && !infmts->refcount) + ff_formats_unref(&infmts); + if (outfmts && !outfmts->refcount) + ff_formats_unref(&outfmts); return err; } From 5dba4b217c548524a93e306a3635d963ddd81c42 Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Tue, 7 Feb 2023 16:26:14 +0100 Subject: [PATCH 0168/2172] avcodec/wavarc: properly handle invalid data --- libavcodec/wavarc.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/libavcodec/wavarc.c b/libavcodec/wavarc.c index 956c52bfe90..6e0e66dcd81 100644 --- a/libavcodec/wavarc.c +++ b/libavcodec/wavarc.c @@ -371,7 +371,7 @@ static int wavarc_decode(AVCodecContext *avctx, AVFrame *frame, } if ((ret = init_get_bits8(gb, buf, buf_size)) < 0) - return ret; + goto fail; skip_bits(gb, s->skip); switch (avctx->codec_tag) { @@ -397,12 +397,14 @@ static int wavarc_decode(AVCodecContext *avctx, AVFrame *frame, fail: s->bitstream_size = 0; s->bitstream_index = 0; - return ret; + if (ret == AVERROR_EOF) + return 0; + return AVERROR_INVALIDDATA; } frame->nb_samples = s->nb_samples; if ((ret = ff_get_buffer(avctx, frame, 0)) < 0) - return ret; + goto fail; switch (avctx->sample_fmt) { case AV_SAMPLE_FMT_U8P: From 0c7af7b95484167c89ec0cb1bd6a862ecaf70e36 Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Tue, 7 Feb 2023 16:26:40 +0100 Subject: [PATCH 0169/2172] avcodec/bonk: properly handle some other errors --- libavcodec/bonk.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libavcodec/bonk.c b/libavcodec/bonk.c index 061cc69a584..5f510e49103 100644 --- a/libavcodec/bonk.c +++ b/libavcodec/bonk.c @@ -330,10 +330,10 @@ static int bonk_decode(AVCodecContext *avctx, AVFrame *frame, frame->nb_samples = FFMIN(s->samples_per_packet * s->down_sampling, s->nb_samples); if ((ret = ff_get_buffer(avctx, frame, 0)) < 0) - return ret; + goto fail; if ((ret = init_get_bits8(gb, buf, buf_size)) < 0) - return ret; + goto fail; skip_bits(gb, s->skip); if ((ret = intlist_read(s, s->k, s->n_taps, 0)) < 0) From df4ab69cfa4583c5cd48ed57f4349c773673233a Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Tue, 7 Feb 2023 16:54:54 +0100 Subject: [PATCH 0170/2172] avcodec/wavarc: add support for 0CPY --- libavcodec/wavarc.c | 32 ++++++++++++++++++++++++++++++-- libavformat/wavarc.c | 3 ++- 2 files changed, 32 insertions(+), 3 deletions(-) diff --git a/libavcodec/wavarc.c b/libavcodec/wavarc.c index 6e0e66dcd81..2d6a58ffb04 100644 --- a/libavcodec/wavarc.c +++ b/libavcodec/wavarc.c @@ -35,6 +35,8 @@ typedef struct WavArcContext { int shift; int nb_samples; int offset; + int align; + int add; int eof; int skip; @@ -68,22 +70,32 @@ static av_cold int wavarc_init(AVCodecContext *avctx) av_channel_layout_default(&avctx->ch_layout, AV_RL16(avctx->extradata + 38)); avctx->sample_rate = AV_RL32(avctx->extradata + 40); + s->align = avctx->ch_layout.nb_channels; + switch (AV_RL16(avctx->extradata + 50)) { case 8: avctx->sample_fmt = AV_SAMPLE_FMT_U8P; break; - case 16: avctx->sample_fmt = AV_SAMPLE_FMT_S16P; break; + case 16: s->align *= 2; + avctx->sample_fmt = AV_SAMPLE_FMT_S16P; break; } s->shift = 0; switch (avctx->codec_tag) { + case MKTAG('0','C','P','Y'): + s->nb_samples = 640; + s->offset = 0; + s->add = 0; + break; case MKTAG('1','D','I','F'): s->nb_samples = 256; s->offset = 4; + s->add = 0x80; break; case MKTAG('2','S','L','P'): case MKTAG('3','N','L','P'): case MKTAG('4','A','L','P'): s->nb_samples = 570; s->offset = 70; + s->add = 0x80; break; default: return AVERROR_INVALIDDATA; @@ -142,6 +154,19 @@ static void do_stereo(WavArcContext *s, int ch, int correlated, int len) } } +static int decode_0cpy(AVCodecContext *avctx, + WavArcContext *s, GetBitContext *gb) +{ + int bits = s->align * 8; + s->nb_samples = FFMIN(640, get_bits_left(gb) / bits); + + for (int n = 0; n < s->nb_samples; n++) { + for (int ch = 0; ch < avctx->ch_layout.nb_channels; ch++) + s->samples[ch][n] = get_bits(gb, bits); + } + return 0; +} + static int decode_1dif(AVCodecContext *avctx, WavArcContext *s, GetBitContext *gb) { @@ -375,6 +400,9 @@ static int wavarc_decode(AVCodecContext *avctx, AVFrame *frame, skip_bits(gb, s->skip); switch (avctx->codec_tag) { + case MKTAG('0','C','P','Y'): + ret = decode_0cpy(avctx, s, gb); + break; case MKTAG('1','D','I','F'): ret = decode_1dif(avctx, s, gb); break; @@ -413,7 +441,7 @@ static int wavarc_decode(AVCodecContext *avctx, AVFrame *frame, const int *src = s->samples[ch] + s->offset; for (int n = 0; n < frame->nb_samples; n++) - dst[n] = src[n] * (1 << s->shift) + 0x80U; + dst[n] = src[n] * (1 << s->shift) + s->add; } break; case AV_SAMPLE_FMT_S16P: diff --git a/libavformat/wavarc.c b/libavformat/wavarc.c index 13e56026a7f..7b38995af9b 100644 --- a/libavformat/wavarc.c +++ b/libavformat/wavarc.c @@ -38,7 +38,8 @@ static int wavarc_probe(const AVProbeData *p) return 0; id = AV_RL32(p->buf + len + 2); - if (id != MKTAG('1','D','I','F') && + if (id != MKTAG('0','C','P','Y') && + id != MKTAG('1','D','I','F') && id != MKTAG('2','S','L','P') && id != MKTAG('3','N','L','P') && id != MKTAG('4','A','L','P') && From 93a9ee7afd7bf2e019490117f1bada30724a0200 Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Sat, 4 Feb 2023 21:46:15 +0100 Subject: [PATCH 0171/2172] avfilter/af_pan: fix regression introduced with switch to new channel layout API Fixes #10168 --- libavfilter/af_pan.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/libavfilter/af_pan.c b/libavfilter/af_pan.c index 067f6468053..80c194b066f 100644 --- a/libavfilter/af_pan.c +++ b/libavfilter/af_pan.c @@ -313,7 +313,9 @@ static int config_props(AVFilterLink *link) pan->channel_map[i] = ch_id; } - av_opt_set_int(pan->swr, "uch", pan->nb_output_channels, 0); + av_opt_set_chlayout(pan->swr, "ichl", &link->ch_layout, 0); + av_opt_set_chlayout(pan->swr, "ochl", &pan->out_channel_layout, 0); + av_opt_set_int(pan->swr, "uch", link->ch_layout.nb_channels, 0); swr_set_channel_mapping(pan->swr, pan->channel_map); } else { // renormalize @@ -333,6 +335,8 @@ static int config_props(AVFilterLink *link) for (j = 0; j < link->ch_layout.nb_channels; j++) pan->gain[i][j] /= t; } + av_opt_set_chlayout(pan->swr, "ichl", &link->ch_layout, 0); + av_opt_set_chlayout(pan->swr, "ochl", &pan->out_channel_layout, 0); swr_set_matrix(pan->swr, pan->gain[0], pan->gain[1] - pan->gain[0]); } From c56f5be6782014fee165d361de1f548eaac7a272 Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Tue, 7 Feb 2023 20:56:32 +0100 Subject: [PATCH 0172/2172] avcodec/wavarc: fix 16bit 0CPY mode --- libavcodec/wavarc.c | 25 ++++++++++++++++--------- 1 file changed, 16 insertions(+), 9 deletions(-) diff --git a/libavcodec/wavarc.c b/libavcodec/wavarc.c index 2d6a58ffb04..b626daa66eb 100644 --- a/libavcodec/wavarc.c +++ b/libavcodec/wavarc.c @@ -36,7 +36,6 @@ typedef struct WavArcContext { int nb_samples; int offset; int align; - int add; int eof; int skip; @@ -83,19 +82,16 @@ static av_cold int wavarc_init(AVCodecContext *avctx) case MKTAG('0','C','P','Y'): s->nb_samples = 640; s->offset = 0; - s->add = 0; break; case MKTAG('1','D','I','F'): s->nb_samples = 256; s->offset = 4; - s->add = 0x80; break; case MKTAG('2','S','L','P'): case MKTAG('3','N','L','P'): case MKTAG('4','A','L','P'): s->nb_samples = 570; s->offset = 70; - s->add = 0x80; break; default: return AVERROR_INVALIDDATA; @@ -157,12 +153,23 @@ static void do_stereo(WavArcContext *s, int ch, int correlated, int len) static int decode_0cpy(AVCodecContext *avctx, WavArcContext *s, GetBitContext *gb) { - int bits = s->align * 8; + const int bits = s->align * 8; + s->nb_samples = FFMIN(640, get_bits_left(gb) / bits); - for (int n = 0; n < s->nb_samples; n++) { - for (int ch = 0; ch < avctx->ch_layout.nb_channels; ch++) - s->samples[ch][n] = get_bits(gb, bits); + switch (avctx->sample_fmt) { + case AV_SAMPLE_FMT_U8P: + for (int n = 0; n < s->nb_samples; n++) { + for (int ch = 0; ch < avctx->ch_layout.nb_channels; ch++) + s->samples[ch][n] = get_bits(gb, 8) - 0x80; + } + break; + case AV_SAMPLE_FMT_S16P: + for (int n = 0; n < s->nb_samples; n++) { + for (int ch = 0; ch < avctx->ch_layout.nb_channels; ch++) + s->samples[ch][n] = sign_extend(av_bswap16(get_bits(gb, 16)), 16); + } + break; } return 0; } @@ -441,7 +448,7 @@ static int wavarc_decode(AVCodecContext *avctx, AVFrame *frame, const int *src = s->samples[ch] + s->offset; for (int n = 0; n < frame->nb_samples; n++) - dst[n] = src[n] * (1 << s->shift) + s->add; + dst[n] = src[n] * (1 << s->shift) + 0x80U; } break; case AV_SAMPLE_FMT_S16P: From 5cf0bc42362ce54afa84103ab5e3ca28e695110f Mon Sep 17 00:00:00 2001 From: Leo Izen Date: Wed, 1 Feb 2023 12:04:30 -0500 Subject: [PATCH 0173/2172] avcodec/pngenc: avoid writing cICP when inappropriate We parse the fallback cHRM on decode and correctly determine that we have BT.709 primaries, but unknown TRC. This causes us to write cICP where we shouldn't. Primaries without transfer can be handled entirely by cHRM, so we should only write cICP if we actually know the transfer function. Additionally, we should avoid writing cICP if there's an ICC profile because the spec says decoders must prioritize cICP over the ICC profile. Signed-off-by: Leo Izen --- libavcodec/pngenc.c | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/libavcodec/pngenc.c b/libavcodec/pngenc.c index 2393161c3b9..81b95c143dc 100644 --- a/libavcodec/pngenc.c +++ b/libavcodec/pngenc.c @@ -412,14 +412,25 @@ static int encode_headers(AVCodecContext *avctx, const AVFrame *pict) } } + side_data = av_frame_get_side_data(pict, AV_FRAME_DATA_ICC_PROFILE); + if ((ret = png_write_iccp(s, side_data))) + return ret; + /* write colorspace information */ if (pict->color_primaries == AVCOL_PRI_BT709 && pict->color_trc == AVCOL_TRC_IEC61966_2_1) { s->buf[0] = 1; /* rendering intent, relative colorimetric by default */ png_write_chunk(&s->bytestream, MKTAG('s', 'R', 'G', 'B'), s->buf, 1); - } else if (pict->color_primaries != AVCOL_PRI_UNSPECIFIED || - pict->color_trc != AVCOL_TRC_UNSPECIFIED) { - /* these values match H.273 so no translation is needed */ + } else if (pict->color_trc != AVCOL_TRC_UNSPECIFIED && !side_data) { + /* + * Avoid writing cICP if the transfer is unknown. Known primaries + * with unknown transfer can be handled by cHRM. + * + * We also avoid writing cICP if an ICC Profile is present, because + * the standard requires that cICP overrides iCCP. + * + * These values match H.273 so no translation is needed. + */ s->buf[0] = pict->color_primaries; s->buf[1] = pict->color_trc; s->buf[2] = 0; /* colorspace = RGB */ @@ -432,10 +443,6 @@ static int encode_headers(AVCodecContext *avctx, const AVFrame *pict) if (png_get_gama(pict->color_trc, s->buf)) png_write_chunk(&s->bytestream, MKTAG('g', 'A', 'M', 'A'), s->buf, 4); - side_data = av_frame_get_side_data(pict, AV_FRAME_DATA_ICC_PROFILE); - if ((ret = png_write_iccp(s, side_data))) - return ret; - /* put the palette if needed, must be after colorspace information */ if (s->color_type == PNG_COLOR_TYPE_PALETTE) { int has_alpha, alpha, i; From a678b0c252473831c346d21f9412679ef789bf91 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomas=20H=C3=A4rdin?= Date: Tue, 31 Jan 2023 16:33:21 +0100 Subject: [PATCH 0174/2172] sws/utils.c: Do not uselessly call initFilter() when unscaling --- libswscale/utils.c | 62 +++++++++++++++++++++++----------------------- 1 file changed, 31 insertions(+), 31 deletions(-) diff --git a/libswscale/utils.c b/libswscale/utils.c index 90734f66ef4..925c536bf17 100644 --- a/libswscale/utils.c +++ b/libswscale/utils.c @@ -1701,6 +1701,37 @@ static av_cold int sws_init_single_context(SwsContext *c, SwsFilter *srcFilter, } } + /* alpha blend special case, note this has been split via cascaded contexts if its scaled */ + if (unscaled && !usesHFilter && !usesVFilter && + c->alphablend != SWS_ALPHA_BLEND_NONE && + isALPHA(srcFormat) && + (c->srcRange == c->dstRange || isAnyRGB(dstFormat)) && + alphaless_fmt(srcFormat) == dstFormat + ) { + c->convert_unscaled = ff_sws_alphablendaway; + + if (flags & SWS_PRINT_INFO) + av_log(c, AV_LOG_INFO, + "using alpha blendaway %s -> %s special converter\n", + av_get_pix_fmt_name(srcFormat), av_get_pix_fmt_name(dstFormat)); + return 0; + } + + /* unscaled special cases */ + if (unscaled && !usesHFilter && !usesVFilter && + (c->srcRange == c->dstRange || isAnyRGB(dstFormat) || + isFloat(srcFormat) || isFloat(dstFormat))){ + ff_get_unscaled_swscale(c); + + if (c->convert_unscaled) { + if (flags & SWS_PRINT_INFO) + av_log(c, AV_LOG_INFO, + "using unscaled %s -> %s special converter\n", + av_get_pix_fmt_name(srcFormat), av_get_pix_fmt_name(dstFormat)); + return 0; + } + } + #if HAVE_MMAP && HAVE_MPROTECT && defined(MAP_ANONYMOUS) #define USE_MMAP 1 #else @@ -1905,37 +1936,6 @@ static av_cold int sws_init_single_context(SwsContext *c, SwsFilter *srcFilter, c->chrXInc, c->chrYInc); } - /* alpha blend special case, note this has been split via cascaded contexts if its scaled */ - if (unscaled && !usesHFilter && !usesVFilter && - c->alphablend != SWS_ALPHA_BLEND_NONE && - isALPHA(srcFormat) && - (c->srcRange == c->dstRange || isAnyRGB(dstFormat)) && - alphaless_fmt(srcFormat) == dstFormat - ) { - c->convert_unscaled = ff_sws_alphablendaway; - - if (flags & SWS_PRINT_INFO) - av_log(c, AV_LOG_INFO, - "using alpha blendaway %s -> %s special converter\n", - av_get_pix_fmt_name(srcFormat), av_get_pix_fmt_name(dstFormat)); - return 0; - } - - /* unscaled special cases */ - if (unscaled && !usesHFilter && !usesVFilter && - (c->srcRange == c->dstRange || isAnyRGB(dstFormat) || - isFloat(srcFormat) || isFloat(dstFormat))){ - ff_get_unscaled_swscale(c); - - if (c->convert_unscaled) { - if (flags & SWS_PRINT_INFO) - av_log(c, AV_LOG_INFO, - "using unscaled %s -> %s special converter\n", - av_get_pix_fmt_name(srcFormat), av_get_pix_fmt_name(dstFormat)); - return 0; - } - } - ff_sws_init_scale(c); return ff_init_filters(c); From 068ad0490874e6fe23b30507f09a1ff587886c81 Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Wed, 8 Feb 2023 18:47:45 +0100 Subject: [PATCH 0175/2172] avfilter/af_compensationdelay: simplify frame allocation --- libavfilter/af_compensationdelay.c | 18 +++--------------- 1 file changed, 3 insertions(+), 15 deletions(-) diff --git a/libavfilter/af_compensationdelay.c b/libavfilter/af_compensationdelay.c index c59ebdca91c..754e02e3ee6 100644 --- a/libavfilter/af_compensationdelay.c +++ b/libavfilter/af_compensationdelay.c @@ -68,7 +68,6 @@ static int config_input(AVFilterLink *inlink) AVFilterContext *ctx = inlink->dst; CompensationDelayContext *s = ctx->priv; unsigned min_size, new_size = 1; - int ret; s->delay = (s->distance_m * 100. + s->distance_cm * 1. + s->distance_mm * .1) * COMP_DELAY_SOUND_FRONT_DELAY(s->temp) * inlink->sample_rate; @@ -77,23 +76,12 @@ static int config_input(AVFilterLink *inlink) while (new_size < min_size) new_size <<= 1; - s->delay_frame = av_frame_alloc(); + s->buf_size = new_size; + s->delay_frame = ff_get_audio_buffer(inlink, s->buf_size); if (!s->delay_frame) return AVERROR(ENOMEM); - s->buf_size = new_size; - s->delay_frame->format = inlink->format; - s->delay_frame->nb_samples = new_size; -#if FF_API_OLD_CHANNEL_LAYOUT -FF_DISABLE_DEPRECATION_WARNINGS - s->delay_frame->channel_layout = inlink->channel_layout; - s->delay_frame->channels = inlink->ch_layout.nb_channels; -FF_ENABLE_DEPRECATION_WARNINGS -#endif - if ((ret = av_channel_layout_copy(&s->delay_frame->ch_layout, &inlink->ch_layout)) < 0) - return ret; - - return av_frame_get_buffer(s->delay_frame, 0); + return 0; } static int filter_frame(AVFilterLink *inlink, AVFrame *in) From 7e1d474021898251dd4b3e56c0d153eafd440f7c Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Wed, 8 Feb 2023 18:54:16 +0100 Subject: [PATCH 0176/2172] avfilter/af_compand: simplify frame allocation --- libavfilter/af_compand.c | 22 ++-------------------- 1 file changed, 2 insertions(+), 20 deletions(-) diff --git a/libavfilter/af_compand.c b/libavfilter/af_compand.c index ba90d21cede..3e799c3b15e 100644 --- a/libavfilter/af_compand.c +++ b/libavfilter/af_compand.c @@ -306,8 +306,6 @@ static int config_output(AVFilterLink *outlink) int nb_attacks, nb_decays, nb_points; int new_nb_items, num; int i; - int err; - count_items(s->attacks, &nb_attacks); count_items(s->decays, &nb_decays); @@ -495,25 +493,9 @@ static int config_output(AVFilterLink *outlink) return 0; } - s->delay_frame = av_frame_alloc(); - if (!s->delay_frame) { - uninit(ctx); + s->delay_frame = ff_get_audio_buffer(outlink, s->delay_samples); + if (!s->delay_frame) return AVERROR(ENOMEM); - } - - s->delay_frame->format = outlink->format; - s->delay_frame->nb_samples = s->delay_samples; -#if FF_API_OLD_CHANNEL_LAYOUT -FF_DISABLE_DEPRECATION_WARNINGS - s->delay_frame->channel_layout = outlink->channel_layout; -FF_ENABLE_DEPRECATION_WARNINGS -#endif - if ((err = av_channel_layout_copy(&s->delay_frame->ch_layout, &outlink->ch_layout)) < 0) - return err; - - err = av_frame_get_buffer(s->delay_frame, 0); - if (err) - return err; s->compand = compand_delay; return 0; From d09254a658365b89fc4430e88e18fef04de432be Mon Sep 17 00:00:00 2001 From: gnattu Date: Thu, 20 Oct 2022 20:11:38 +0800 Subject: [PATCH 0177/2172] avformat/hls: Add option to retry failed segments for hls Current HLS implementation simply skip a failed segment to catch up the stream, but this is not optimal for some use cases like livestream recording. Add an option to retry a failed segment to ensure the output file is a complete stream. Signed-off-by: gnattu Reviewed-by: Steven Liu --- doc/demuxers.texi | 4 ++++ libavformat/hls.c | 15 ++++++++++++++- 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/doc/demuxers.texi b/doc/demuxers.texi index f07f3f53181..3c81024f038 100644 --- a/doc/demuxers.texi +++ b/doc/demuxers.texi @@ -419,6 +419,10 @@ Use HTTP partial requests for downloading HTTP segments. @item seg_format_options Set options for the demuxer of media segments using a list of key=value pairs separated by @code{:}. + +@item seg_max_retry +Maximum number of times to reload a segment on error, useful when segment skip on network error is not desired. +Default value is 0. @end table @section image2 diff --git a/libavformat/hls.c b/libavformat/hls.c index 926d053939c..8a96a37ff9b 100644 --- a/libavformat/hls.c +++ b/libavformat/hls.c @@ -225,6 +225,7 @@ typedef struct HLSContext { int http_persistent; int http_multiple; int http_seekable; + int seg_max_retry; AVIOContext *playlist_pb; HLSCryptoContext crypto_ctx; } HLSContext; @@ -1472,6 +1473,7 @@ static int read_data(void *opaque, uint8_t *buf, int buf_size) int ret; int just_opened = 0; int reload_count = 0; + int segment_retries = 0; struct segment *seg; restart: @@ -1563,9 +1565,18 @@ static int read_data(void *opaque, uint8_t *buf, int buf_size) av_log(v->parent, AV_LOG_WARNING, "Failed to open segment %"PRId64" of playlist %d\n", v->cur_seq_no, v->index); - v->cur_seq_no += 1; + if (segment_retries >= c->seg_max_retry) { + av_log(v->parent, AV_LOG_WARNING, "Segment %"PRId64" of playlist %d failed too many times, skipping\n", + v->cur_seq_no, + v->index); + v->cur_seq_no++; + segment_retries = 0; + } else { + segment_retries++; + } goto reload; } + segment_retries = 0; just_opened = 1; } @@ -2549,6 +2560,8 @@ static const AVOption hls_options[] = { OFFSET(http_seekable), AV_OPT_TYPE_BOOL, { .i64 = -1}, -1, 1, FLAGS}, {"seg_format_options", "Set options for segment demuxer", OFFSET(seg_format_opts), AV_OPT_TYPE_DICT, {.str = NULL}, 0, 0, FLAGS}, + {"seg_max_retry", "Maximum number of times to reload a segment on error.", + OFFSET(seg_max_retry), AV_OPT_TYPE_INT, {.i64 = 0}, 0, INT_MAX, FLAGS}, {NULL} }; From 159b028df58f480605b678109088e1b2ba8fdc71 Mon Sep 17 00:00:00 2001 From: Gyan Doshi Date: Sun, 29 Jan 2023 16:52:04 +0530 Subject: [PATCH 0178/2172] avcodec/h264_metadata_bsf: remove AUDs at any position Some files, likely due to faulty packetization or muxing, can have AUDs at other positions besides the head unit of a packet. Remove these too. --- libavcodec/h264_metadata_bsf.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/libavcodec/h264_metadata_bsf.c b/libavcodec/h264_metadata_bsf.c index d318bf0ceec..b9cfeaba946 100644 --- a/libavcodec/h264_metadata_bsf.c +++ b/libavcodec/h264_metadata_bsf.c @@ -469,12 +469,13 @@ static int h264_metadata_update_fragment(AVBSFContext *bsf, AVPacket *pkt, H264MetadataContext *ctx = bsf->priv_data; int err, i, has_sps, seek_point; - // If an AUD is present, it must be the first NAL unit. - if (au->nb_units && au->units[0].type == H264_NAL_AUD) { - if (ctx->aud == BSF_ELEMENT_REMOVE) - ff_cbs_delete_unit(au, 0); - } else { - if (pkt && ctx->aud == BSF_ELEMENT_INSERT) { + if (ctx->aud == BSF_ELEMENT_REMOVE) { + for (i = au->nb_units - 1; i >= 0; i--) { + if (au->units[i].type == H264_NAL_AUD) + ff_cbs_delete_unit(au, i); + } + } else if (ctx->aud == BSF_ELEMENT_INSERT) { + if (pkt) { err = h264_metadata_insert_aud(bsf, au); if (err < 0) return err; From 63a348659b28ef481112ff063f33176d679de5e5 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Tue, 7 Feb 2023 09:01:40 +0100 Subject: [PATCH 0179/2172] configure: make flite depend on threads The filter calls pthreads functions unconditionally. --- configure | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure b/configure index d67855c7299..12184c7f26b 100755 --- a/configure +++ b/configure @@ -3667,7 +3667,7 @@ eq_filter_deps="gpl" erosion_opencl_filter_deps="opencl" find_rect_filter_deps="avcodec avformat gpl" flip_vulkan_filter_deps="vulkan spirv_compiler" -flite_filter_deps="libflite" +flite_filter_deps="libflite threads" framerate_filter_select="scene_sad" freezedetect_filter_select="scene_sad" frei0r_deps_any="libdl LoadLibrary" From 18cd65998bfe9651b1bd9496bba9f641c77920cd Mon Sep 17 00:00:00 2001 From: rcombs Date: Tue, 10 Jan 2023 19:55:32 -0600 Subject: [PATCH 0180/2172] ffprobe: report the corrupt flag on packets Signed-off-by: Anton Khirnov --- fftools/ffprobe.c | 5 +- .../ref/fate/concat-demuxer-extended-lavf-mxf | 2 +- .../fate/concat-demuxer-extended-lavf-mxf_d10 | 2 +- .../ref/fate/concat-demuxer-simple1-lavf-mxf | 202 +-- .../fate/concat-demuxer-simple1-lavf-mxf_d10 | 140 +- tests/ref/fate/concat-demuxer-simple2-lavf-ts | 298 ++-- tests/ref/fate/ffprobe_compact | 28 +- tests/ref/fate/ffprobe_csv | 28 +- tests/ref/fate/ffprobe_default | 28 +- tests/ref/fate/ffprobe_flat | 28 +- tests/ref/fate/ffprobe_ini | 28 +- tests/ref/fate/ffprobe_json | 28 +- tests/ref/fate/ffprobe_xml | 28 +- tests/ref/fate/ffprobe_xsd | 28 +- tests/ref/fate/flcl1905 | 34 +- tests/ref/fate/flv-demux | 1206 ++++++++--------- tests/ref/fate/gapless-mp3-side-data | 1190 ++++++++-------- tests/ref/fate/gaplessenc-itunes-to-ipod-aac | 30 +- tests/ref/fate/gaplessenc-pcm-to-mov-aac | 30 +- tests/ref/fate/gaplessinfo-itunes1 | 30 +- tests/ref/fate/gaplessinfo-itunes2 | 30 +- ...hapqa-extract-nosnappy-to-hapalphaonly-mov | 2 +- .../fate/hapqa-extract-nosnappy-to-hapq-mov | 2 +- tests/ref/fate/matroska-encoding-delay | 10 +- tests/ref/fate/matroska-ogg-opus-remux | 6 +- tests/ref/fate/matroska-opus-remux | 6 +- tests/ref/fate/mov-aac-2048-priming | 434 +++--- tests/ref/fate/mov-init-nonkeyframe | 240 ++-- tests/ref/fate/mov-mp4-extended-atom | 2 +- tests/ref/fate/mov-mp4-ttml-dfxp | 2 +- tests/ref/fate/mov-mp4-ttml-stpp | 2 +- tests/ref/fate/mov-zombie | 132 +- tests/ref/fate/oggopus-demux | 82 +- tests/ref/fate/ts-demux | 50 +- tests/ref/fate/ts-opus-demux | 1024 +++++++------- tests/ref/fate/ts-small-demux | 148 +- 36 files changed, 2783 insertions(+), 2782 deletions(-) diff --git a/fftools/ffprobe.c b/fftools/ffprobe.c index dfa7ff1b241..db5e4ecdf1f 100644 --- a/fftools/ffprobe.c +++ b/fftools/ffprobe.c @@ -2513,8 +2513,9 @@ static void show_packet(WriterContext *w, InputFile *ifile, AVPacket *pkt, int p print_val("size", pkt->size, unit_byte_str); if (pkt->pos != -1) print_fmt ("pos", "%"PRId64, pkt->pos); else print_str_opt("pos", "N/A"); - print_fmt("flags", "%c%c", pkt->flags & AV_PKT_FLAG_KEY ? 'K' : '_', - pkt->flags & AV_PKT_FLAG_DISCARD ? 'D' : '_'); + print_fmt("flags", "%c%c%c", pkt->flags & AV_PKT_FLAG_KEY ? 'K' : '_', + pkt->flags & AV_PKT_FLAG_DISCARD ? 'D' : '_', + pkt->flags & AV_PKT_FLAG_CORRUPT ? 'C' : '_'); if (do_show_data) writer_print_data(w, "data", pkt->data, pkt->size); writer_print_data_hash(w, "data_hash", pkt->data, pkt->size); diff --git a/tests/ref/fate/concat-demuxer-extended-lavf-mxf b/tests/ref/fate/concat-demuxer-extended-lavf-mxf index 3d448ca0cc1..ebdd77c57c3 100644 --- a/tests/ref/fate/concat-demuxer-extended-lavf-mxf +++ b/tests/ref/fate/concat-demuxer-extended-lavf-mxf @@ -1 +1 @@ -05a65d350a18869abeac626ff49c1f4a *tests/data/fate/concat-demuxer-extended-lavf-mxf.ffprobe +239286d6a802d8629bec9ab0d2b37d41 *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 bd24104bd59..66fafd3e060 100644 --- a/tests/ref/fate/concat-demuxer-extended-lavf-mxf_d10 +++ b/tests/ref/fate/concat-demuxer-extended-lavf-mxf_d10 @@ -1 +1 @@ -8c222118f9d0e41581a5bec66e20fbe8 *tests/data/fate/concat-demuxer-extended-lavf-mxf_d10.ffprobe +9583eaa1d52e977c75da2ab3f14225c8 *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 fbe553d6de2..19fea1e71d1 100644 --- a/tests/ref/fate/concat-demuxer-simple1-lavf-mxf +++ b/tests/ref/fate/concat-demuxer-simple1-lavf-mxf @@ -1,103 +1,103 @@ -video|0|0|0.000000|-1|-0.040000|1|0.040000|24801|7168|K_ -audio|1|0|0.000000|0|0.000000|1920|0.040000|3840|32256|K_ -video|0|3|0.120000|0|0.000000|1|0.040000|16743|36864|__ -audio|1|1920|0.040000|1920|0.040000|1920|0.040000|3840|53760|K_ -video|0|1|0.040000|1|0.040000|1|0.040000|13812|58368|__ -audio|1|3840|0.080000|3840|0.080000|1920|0.040000|3840|72704|K_ -video|0|2|0.080000|2|0.080000|1|0.040000|13607|77312|__ -audio|1|5760|0.120000|5760|0.120000|1920|0.040000|3840|91136|K_ -video|0|6|0.240000|3|0.120000|1|0.040000|16158|95744|__ -audio|1|7680|0.160000|7680|0.160000|1920|0.040000|3840|112128|K_ -video|0|4|0.160000|4|0.160000|1|0.040000|13943|116736|__ -audio|1|9600|0.200000|9600|0.200000|1920|0.040000|3840|131072|K_ -video|0|5|0.200000|5|0.200000|1|0.040000|11223|135680|__ -audio|1|11520|0.240000|11520|0.240000|1920|0.040000|3840|146944|K_ -video|0|9|0.360000|6|0.240000|1|0.040000|20298|151552|__ -audio|1|13440|0.280000|13440|0.280000|1920|0.040000|3840|172032|K_ -video|0|7|0.280000|7|0.280000|1|0.040000|13341|176640|__ -audio|1|15360|0.320000|15360|0.320000|1920|0.040000|3840|190464|K_ -video|0|8|0.320000|8|0.320000|1|0.040000|12362|195072|__ -audio|1|17280|0.360000|17280|0.360000|1920|0.040000|3840|207872|K_ -video|0|12|0.480000|9|0.360000|1|0.040000|24786|212480|K_ -audio|1|19200|0.400000|19200|0.400000|1920|0.040000|3840|237568|K_ -video|0|10|0.400000|10|0.400000|1|0.040000|13377|242176|__ -audio|1|21120|0.440000|21120|0.440000|1920|0.040000|3840|256000|K_ -video|0|11|0.440000|11|0.440000|1|0.040000|15624|260608|__ -audio|1|23040|0.480000|23040|0.480000|1920|0.040000|3840|276480|K_ -video|0|15|0.600000|12|0.480000|1|0.040000|22597|281088|__ -audio|1|24960|0.520000|24960|0.520000|1920|0.040000|3840|304128|K_ -video|0|13|0.520000|13|0.520000|1|0.040000|15028|308736|__ -audio|1|26880|0.560000|26880|0.560000|1920|0.040000|3840|324096|K_ -video|0|14|0.560000|14|0.560000|1|0.040000|14014|328704|__ -audio|1|28800|0.600000|28800|0.600000|1920|0.040000|3840|343040|K_ -video|0|18|0.720000|15|0.600000|1|0.040000|20731|347648|__ -audio|1|30720|0.640000|30720|0.640000|1920|0.040000|3840|368640|K_ -video|0|16|0.640000|16|0.640000|1|0.040000|11946|373248|__ -audio|1|32640|0.680000|32640|0.680000|1920|0.040000|3840|385536|K_ -video|0|17|0.680000|17|0.680000|1|0.040000|14464|390144|__ -audio|1|34560|0.720000|34560|0.720000|1920|0.040000|3840|404992|K_ -video|0|21|0.840000|18|0.720000|1|0.040000|16189|409600|__ -audio|1|36480|0.760000|36480|0.760000|1920|0.040000|3840|425984|K_ -video|0|19|0.760000|19|0.760000|1|0.040000|10524|430592|__ -audio|1|38400|0.800000|38400|0.800000|1920|0.040000|3840|441344|K_ -video|0|20|0.800000|20|0.800000|1|0.040000|10599|445952|__ -audio|1|40320|0.840000|40320|0.840000|1920|0.040000|3840|456704|K_ -video|0|24|0.960000|21|0.840000|1|0.040000|24711|461312|K_ -audio|1|42240|0.880000|42240|0.880000|1920|0.040000|3840|486400|K_ -video|0|22|0.880000|22|0.880000|1|0.040000|10840|491008|__ -audio|1|44160|0.920000|44160|0.920000|1920|0.040000|3840|502272|K_ -video|0|23|0.920000|23|0.920000|1|0.040000|13350|506880|__ -audio|1|46080|0.960000|46080|0.960000|1920|0.040000|3840|520704|K_ -video|0|17|0.680000|14|0.560000|1|0.040000|24786|212480|K_ -audio|1|28800|0.600000|28800|0.600000|1920|0.040000|3840|237568|K_ -video|0|15|0.600000|15|0.600000|1|0.040000|13377|242176|__ -audio|1|30720|0.640000|30720|0.640000|1920|0.040000|3840|256000|K_ -video|0|16|0.640000|16|0.640000|1|0.040000|15624|260608|__ -audio|1|32640|0.680000|32640|0.680000|1920|0.040000|3840|276480|K_ -video|0|20|0.800000|17|0.680000|1|0.040000|22597|281088|__ -audio|1|34560|0.720000|34560|0.720000|1920|0.040000|3840|304128|K_ -video|0|18|0.720000|18|0.720000|1|0.040000|15028|308736|__ -audio|1|36480|0.760000|36480|0.760000|1920|0.040000|3840|324096|K_ -video|0|19|0.760000|19|0.760000|1|0.040000|14014|328704|__ -audio|1|38400|0.800000|38400|0.800000|1920|0.040000|3840|343040|K_ -video|0|23|0.920000|20|0.800000|1|0.040000|20731|347648|__ -audio|1|40320|0.840000|40320|0.840000|1920|0.040000|3840|368640|K_ -video|0|21|0.840000|21|0.840000|1|0.040000|11946|373248|__ -audio|1|42240|0.880000|42240|0.880000|1920|0.040000|3840|385536|K_ -video|0|22|0.880000|22|0.880000|1|0.040000|14464|390144|__ -audio|1|44160|0.920000|44160|0.920000|1920|0.040000|3840|404992|K_ -video|0|26|1.040000|23|0.920000|1|0.040000|16189|409600|__ -audio|1|46080|0.960000|46080|0.960000|1920|0.040000|3840|425984|K_ -video|0|24|0.960000|24|0.960000|1|0.040000|10524|430592|__ -audio|1|48000|1.000000|48000|1.000000|1920|0.040000|3840|441344|K_ -video|0|25|1.000000|25|1.000000|1|0.040000|10599|445952|__ -audio|1|49920|1.040000|49920|1.040000|1920|0.040000|3840|456704|K_ -video|0|29|1.160000|26|1.040000|1|0.040000|24711|461312|K_ -audio|1|51840|1.080000|51840|1.080000|1920|0.040000|3840|486400|K_ -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 +video|0|0|0.000000|-1|-0.040000|1|0.040000|24801|7168|K__ +audio|1|0|0.000000|0|0.000000|1920|0.040000|3840|32256|K__ +video|0|3|0.120000|0|0.000000|1|0.040000|16743|36864|___ +audio|1|1920|0.040000|1920|0.040000|1920|0.040000|3840|53760|K__ +video|0|1|0.040000|1|0.040000|1|0.040000|13812|58368|___ +audio|1|3840|0.080000|3840|0.080000|1920|0.040000|3840|72704|K__ +video|0|2|0.080000|2|0.080000|1|0.040000|13607|77312|___ +audio|1|5760|0.120000|5760|0.120000|1920|0.040000|3840|91136|K__ +video|0|6|0.240000|3|0.120000|1|0.040000|16158|95744|___ +audio|1|7680|0.160000|7680|0.160000|1920|0.040000|3840|112128|K__ +video|0|4|0.160000|4|0.160000|1|0.040000|13943|116736|___ +audio|1|9600|0.200000|9600|0.200000|1920|0.040000|3840|131072|K__ +video|0|5|0.200000|5|0.200000|1|0.040000|11223|135680|___ +audio|1|11520|0.240000|11520|0.240000|1920|0.040000|3840|146944|K__ +video|0|9|0.360000|6|0.240000|1|0.040000|20298|151552|___ +audio|1|13440|0.280000|13440|0.280000|1920|0.040000|3840|172032|K__ +video|0|7|0.280000|7|0.280000|1|0.040000|13341|176640|___ +audio|1|15360|0.320000|15360|0.320000|1920|0.040000|3840|190464|K__ +video|0|8|0.320000|8|0.320000|1|0.040000|12362|195072|___ +audio|1|17280|0.360000|17280|0.360000|1920|0.040000|3840|207872|K__ +video|0|12|0.480000|9|0.360000|1|0.040000|24786|212480|K__ +audio|1|19200|0.400000|19200|0.400000|1920|0.040000|3840|237568|K__ +video|0|10|0.400000|10|0.400000|1|0.040000|13377|242176|___ +audio|1|21120|0.440000|21120|0.440000|1920|0.040000|3840|256000|K__ +video|0|11|0.440000|11|0.440000|1|0.040000|15624|260608|___ +audio|1|23040|0.480000|23040|0.480000|1920|0.040000|3840|276480|K__ +video|0|15|0.600000|12|0.480000|1|0.040000|22597|281088|___ +audio|1|24960|0.520000|24960|0.520000|1920|0.040000|3840|304128|K__ +video|0|13|0.520000|13|0.520000|1|0.040000|15028|308736|___ +audio|1|26880|0.560000|26880|0.560000|1920|0.040000|3840|324096|K__ +video|0|14|0.560000|14|0.560000|1|0.040000|14014|328704|___ +audio|1|28800|0.600000|28800|0.600000|1920|0.040000|3840|343040|K__ +video|0|18|0.720000|15|0.600000|1|0.040000|20731|347648|___ +audio|1|30720|0.640000|30720|0.640000|1920|0.040000|3840|368640|K__ +video|0|16|0.640000|16|0.640000|1|0.040000|11946|373248|___ +audio|1|32640|0.680000|32640|0.680000|1920|0.040000|3840|385536|K__ +video|0|17|0.680000|17|0.680000|1|0.040000|14464|390144|___ +audio|1|34560|0.720000|34560|0.720000|1920|0.040000|3840|404992|K__ +video|0|21|0.840000|18|0.720000|1|0.040000|16189|409600|___ +audio|1|36480|0.760000|36480|0.760000|1920|0.040000|3840|425984|K__ +video|0|19|0.760000|19|0.760000|1|0.040000|10524|430592|___ +audio|1|38400|0.800000|38400|0.800000|1920|0.040000|3840|441344|K__ +video|0|20|0.800000|20|0.800000|1|0.040000|10599|445952|___ +audio|1|40320|0.840000|40320|0.840000|1920|0.040000|3840|456704|K__ +video|0|24|0.960000|21|0.840000|1|0.040000|24711|461312|K__ +audio|1|42240|0.880000|42240|0.880000|1920|0.040000|3840|486400|K__ +video|0|22|0.880000|22|0.880000|1|0.040000|10840|491008|___ +audio|1|44160|0.920000|44160|0.920000|1920|0.040000|3840|502272|K__ +video|0|23|0.920000|23|0.920000|1|0.040000|13350|506880|___ +audio|1|46080|0.960000|46080|0.960000|1920|0.040000|3840|520704|K__ +video|0|17|0.680000|14|0.560000|1|0.040000|24786|212480|K__ +audio|1|28800|0.600000|28800|0.600000|1920|0.040000|3840|237568|K__ +video|0|15|0.600000|15|0.600000|1|0.040000|13377|242176|___ +audio|1|30720|0.640000|30720|0.640000|1920|0.040000|3840|256000|K__ +video|0|16|0.640000|16|0.640000|1|0.040000|15624|260608|___ +audio|1|32640|0.680000|32640|0.680000|1920|0.040000|3840|276480|K__ +video|0|20|0.800000|17|0.680000|1|0.040000|22597|281088|___ +audio|1|34560|0.720000|34560|0.720000|1920|0.040000|3840|304128|K__ +video|0|18|0.720000|18|0.720000|1|0.040000|15028|308736|___ +audio|1|36480|0.760000|36480|0.760000|1920|0.040000|3840|324096|K__ +video|0|19|0.760000|19|0.760000|1|0.040000|14014|328704|___ +audio|1|38400|0.800000|38400|0.800000|1920|0.040000|3840|343040|K__ +video|0|23|0.920000|20|0.800000|1|0.040000|20731|347648|___ +audio|1|40320|0.840000|40320|0.840000|1920|0.040000|3840|368640|K__ +video|0|21|0.840000|21|0.840000|1|0.040000|11946|373248|___ +audio|1|42240|0.880000|42240|0.880000|1920|0.040000|3840|385536|K__ +video|0|22|0.880000|22|0.880000|1|0.040000|14464|390144|___ +audio|1|44160|0.920000|44160|0.920000|1920|0.040000|3840|404992|K__ +video|0|26|1.040000|23|0.920000|1|0.040000|16189|409600|___ +audio|1|46080|0.960000|46080|0.960000|1920|0.040000|3840|425984|K__ +video|0|24|0.960000|24|0.960000|1|0.040000|10524|430592|___ +audio|1|48000|1.000000|48000|1.000000|1920|0.040000|3840|441344|K__ +video|0|25|1.000000|25|1.000000|1|0.040000|10599|445952|___ +audio|1|49920|1.040000|49920|1.040000|1920|0.040000|3840|456704|K__ +video|0|29|1.160000|26|1.040000|1|0.040000|24711|461312|K__ +audio|1|51840|1.080000|51840|1.080000|1920|0.040000|3840|486400|K__ +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 1|pcm_s16le|unknown|audio|[0][0][0][0]|0x0000|s16|48000|1|unknown|16|0|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 3127ca7fbc1..98b922cc7f3 100644 --- a/tests/ref/fate/concat-demuxer-simple1-lavf-mxf_d10 +++ b/tests/ref/fate/concat-demuxer-simple1-lavf-mxf_d10 @@ -1,72 +1,72 @@ -video|0|0|0.000000|0|0.000000|1|0.040000|150000|7168|K_ -audio|1|0|0.000000|0|0.000000|1920|0.040000|7680|157696|K_ -video|0|1|0.040000|1|0.040000|1|0.040000|150000|220160|K_ -audio|1|1920|0.040000|1920|0.040000|1920|0.040000|7680|370688|K_ -video|0|2|0.080000|2|0.080000|1|0.040000|150000|433152|K_ -audio|1|3840|0.080000|3840|0.080000|1920|0.040000|7680|583680|K_ -video|0|3|0.120000|3|0.120000|1|0.040000|150000|646144|K_ -audio|1|5760|0.120000|5760|0.120000|1920|0.040000|7680|796672|K_ -video|0|4|0.160000|4|0.160000|1|0.040000|150000|859136|K_ -audio|1|7680|0.160000|7680|0.160000|1920|0.040000|7680|1009664|K_ -video|0|5|0.200000|5|0.200000|1|0.040000|150000|1072128|K_ -audio|1|9600|0.200000|9600|0.200000|1920|0.040000|7680|1222656|K_ -video|0|6|0.240000|6|0.240000|1|0.040000|150000|1285120|K_ -audio|1|11520|0.240000|11520|0.240000|1920|0.040000|7680|1435648|K_ -video|0|7|0.280000|7|0.280000|1|0.040000|150000|1498112|K_ -audio|1|13440|0.280000|13440|0.280000|1920|0.040000|7680|1648640|K_ -video|0|8|0.320000|8|0.320000|1|0.040000|150000|1711104|K_ -audio|1|15360|0.320000|15360|0.320000|1920|0.040000|7680|1861632|K_ -video|0|9|0.360000|9|0.360000|1|0.040000|150000|1924096|K_ -audio|1|17280|0.360000|17280|0.360000|1920|0.040000|7680|2074624|K_ -video|0|10|0.400000|10|0.400000|1|0.040000|150000|2137088|K_ -audio|1|19200|0.400000|19200|0.400000|1920|0.040000|7680|2287616|K_ -video|0|11|0.440000|11|0.440000|1|0.040000|150000|2350080|K_ -audio|1|21120|0.440000|21120|0.440000|1920|0.040000|7680|2500608|K_ -video|0|12|0.480000|12|0.480000|1|0.040000|150000|2563072|K_ -audio|1|23040|0.480000|23040|0.480000|1920|0.040000|7680|2713600|K_ -video|0|13|0.520000|13|0.520000|1|0.040000|150000|2776064|K_ -audio|1|24960|0.520000|24960|0.520000|1920|0.040000|7680|2926592|K_ -video|0|14|0.560000|14|0.560000|1|0.040000|150000|2989056|K_ -audio|1|26880|0.560000|26880|0.560000|1920|0.040000|7680|3139584|K_ -video|0|15|0.600000|15|0.600000|1|0.040000|150000|3202048|K_ -audio|1|28800|0.600000|28800|0.600000|1920|0.040000|7680|3352576|K_ -video|0|16|0.640000|16|0.640000|1|0.040000|150000|3415040|K_ -audio|1|30720|0.640000|30720|0.640000|1920|0.040000|7680|3565568|K_ -video|0|17|0.680000|17|0.680000|1|0.040000|150000|3628032|K_ -audio|1|32640|0.680000|32640|0.680000|1920|0.040000|7680|3778560|K_ -video|0|18|0.720000|18|0.720000|1|0.040000|150000|3841024|K_ -audio|1|34560|0.720000|34560|0.720000|1920|0.040000|7680|3991552|K_ -video|0|19|0.760000|19|0.760000|1|0.040000|150000|4054016|K_ -audio|1|36480|0.760000|36480|0.760000|1920|0.040000|7680|4204544|K_ -video|0|20|0.800000|20|0.800000|1|0.040000|150000|4267008|K_ -audio|1|38400|0.800000|38400|0.800000|1920|0.040000|7680|4417536|K_ -video|0|21|0.840000|21|0.840000|1|0.040000|150000|4480000|K_ -audio|1|40320|0.840000|40320|0.840000|1920|0.040000|7680|4630528|K_ -video|0|22|0.880000|22|0.880000|1|0.040000|150000|4692992|K_ -audio|1|42240|0.880000|42240|0.880000|1920|0.040000|7680|4843520|K_ -video|0|23|0.920000|23|0.920000|1|0.040000|150000|4905984|K_ -audio|1|44160|0.920000|44160|0.920000|1920|0.040000|7680|5056512|K_ -video|0|24|0.960000|24|0.960000|1|0.040000|150000|5118976|K_ -audio|1|46080|0.960000|46080|0.960000|1920|0.040000|7680|5269504|K_ -video|0|25|1.000000|25|1.000000|1|0.040000|150000|4267008|K_ -audio|1|48000|1.000000|48000|1.000000|1920|0.040000|7680|4417536|K_ -video|0|26|1.040000|26|1.040000|1|0.040000|150000|4480000|K_ -audio|1|49920|1.040000|49920|1.040000|1920|0.040000|7680|4630528|K_ -video|0|27|1.080000|27|1.080000|1|0.040000|150000|4692992|K_ -audio|1|51840|1.080000|51840|1.080000|1920|0.040000|7680|4843520|K_ -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 +video|0|0|0.000000|0|0.000000|1|0.040000|150000|7168|K__ +audio|1|0|0.000000|0|0.000000|1920|0.040000|7680|157696|K__ +video|0|1|0.040000|1|0.040000|1|0.040000|150000|220160|K__ +audio|1|1920|0.040000|1920|0.040000|1920|0.040000|7680|370688|K__ +video|0|2|0.080000|2|0.080000|1|0.040000|150000|433152|K__ +audio|1|3840|0.080000|3840|0.080000|1920|0.040000|7680|583680|K__ +video|0|3|0.120000|3|0.120000|1|0.040000|150000|646144|K__ +audio|1|5760|0.120000|5760|0.120000|1920|0.040000|7680|796672|K__ +video|0|4|0.160000|4|0.160000|1|0.040000|150000|859136|K__ +audio|1|7680|0.160000|7680|0.160000|1920|0.040000|7680|1009664|K__ +video|0|5|0.200000|5|0.200000|1|0.040000|150000|1072128|K__ +audio|1|9600|0.200000|9600|0.200000|1920|0.040000|7680|1222656|K__ +video|0|6|0.240000|6|0.240000|1|0.040000|150000|1285120|K__ +audio|1|11520|0.240000|11520|0.240000|1920|0.040000|7680|1435648|K__ +video|0|7|0.280000|7|0.280000|1|0.040000|150000|1498112|K__ +audio|1|13440|0.280000|13440|0.280000|1920|0.040000|7680|1648640|K__ +video|0|8|0.320000|8|0.320000|1|0.040000|150000|1711104|K__ +audio|1|15360|0.320000|15360|0.320000|1920|0.040000|7680|1861632|K__ +video|0|9|0.360000|9|0.360000|1|0.040000|150000|1924096|K__ +audio|1|17280|0.360000|17280|0.360000|1920|0.040000|7680|2074624|K__ +video|0|10|0.400000|10|0.400000|1|0.040000|150000|2137088|K__ +audio|1|19200|0.400000|19200|0.400000|1920|0.040000|7680|2287616|K__ +video|0|11|0.440000|11|0.440000|1|0.040000|150000|2350080|K__ +audio|1|21120|0.440000|21120|0.440000|1920|0.040000|7680|2500608|K__ +video|0|12|0.480000|12|0.480000|1|0.040000|150000|2563072|K__ +audio|1|23040|0.480000|23040|0.480000|1920|0.040000|7680|2713600|K__ +video|0|13|0.520000|13|0.520000|1|0.040000|150000|2776064|K__ +audio|1|24960|0.520000|24960|0.520000|1920|0.040000|7680|2926592|K__ +video|0|14|0.560000|14|0.560000|1|0.040000|150000|2989056|K__ +audio|1|26880|0.560000|26880|0.560000|1920|0.040000|7680|3139584|K__ +video|0|15|0.600000|15|0.600000|1|0.040000|150000|3202048|K__ +audio|1|28800|0.600000|28800|0.600000|1920|0.040000|7680|3352576|K__ +video|0|16|0.640000|16|0.640000|1|0.040000|150000|3415040|K__ +audio|1|30720|0.640000|30720|0.640000|1920|0.040000|7680|3565568|K__ +video|0|17|0.680000|17|0.680000|1|0.040000|150000|3628032|K__ +audio|1|32640|0.680000|32640|0.680000|1920|0.040000|7680|3778560|K__ +video|0|18|0.720000|18|0.720000|1|0.040000|150000|3841024|K__ +audio|1|34560|0.720000|34560|0.720000|1920|0.040000|7680|3991552|K__ +video|0|19|0.760000|19|0.760000|1|0.040000|150000|4054016|K__ +audio|1|36480|0.760000|36480|0.760000|1920|0.040000|7680|4204544|K__ +video|0|20|0.800000|20|0.800000|1|0.040000|150000|4267008|K__ +audio|1|38400|0.800000|38400|0.800000|1920|0.040000|7680|4417536|K__ +video|0|21|0.840000|21|0.840000|1|0.040000|150000|4480000|K__ +audio|1|40320|0.840000|40320|0.840000|1920|0.040000|7680|4630528|K__ +video|0|22|0.880000|22|0.880000|1|0.040000|150000|4692992|K__ +audio|1|42240|0.880000|42240|0.880000|1920|0.040000|7680|4843520|K__ +video|0|23|0.920000|23|0.920000|1|0.040000|150000|4905984|K__ +audio|1|44160|0.920000|44160|0.920000|1920|0.040000|7680|5056512|K__ +video|0|24|0.960000|24|0.960000|1|0.040000|150000|5118976|K__ +audio|1|46080|0.960000|46080|0.960000|1920|0.040000|7680|5269504|K__ +video|0|25|1.000000|25|1.000000|1|0.040000|150000|4267008|K__ +audio|1|48000|1.000000|48000|1.000000|1920|0.040000|7680|4417536|K__ +video|0|26|1.040000|26|1.040000|1|0.040000|150000|4480000|K__ +audio|1|49920|1.040000|49920|1.040000|1920|0.040000|7680|4630528|K__ +video|0|27|1.080000|27|1.080000|1|0.040000|150000|4692992|K__ +audio|1|51840|1.080000|51840|1.080000|1920|0.040000|7680|4843520|K__ +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 1|pcm_s16le|unknown|audio|[0][0][0][0]|0x0000|s16|48000|2|unknown|16|0|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 92e6829425e..2ce63506d28 100644 --- a/tests/ref/fate/concat-demuxer-simple2-lavf-ts +++ b/tests/ref/fate/concat-demuxer-simple2-lavf-ts @@ -1,215 +1,215 @@ -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_ -audio|0|7053|0.078367|7053|0.078367|2351|0.026122|209|N/A|K_ -audio|0|9404|0.104489|9404|0.104489|2351|0.026122|209|N/A|K_ -audio|0|11755|0.130611|11755|0.130611|2351|0.026122|209|N/A|K_ -audio|0|14106|0.156733|14106|0.156733|2351|0.026122|209|N/A|K_ -audio|0|16457|0.182856|16457|0.182856|2351|0.026122|209|N/A|K_ -audio|0|18808|0.208978|18808|0.208978|2351|0.026122|209|N/A|K_ -audio|0|21159|0.235100|21159|0.235100|2351|0.026122|209|N/A|K_ -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 +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__ +audio|0|7053|0.078367|7053|0.078367|2351|0.026122|209|N/A|K__ +audio|0|9404|0.104489|9404|0.104489|2351|0.026122|209|N/A|K__ +audio|0|11755|0.130611|11755|0.130611|2351|0.026122|209|N/A|K__ +audio|0|14106|0.156733|14106|0.156733|2351|0.026122|209|N/A|K__ +audio|0|16457|0.182856|16457|0.182856|2351|0.026122|209|N/A|K__ +audio|0|18808|0.208978|18808|0.208978|2351|0.026122|209|N/A|K__ +audio|0|21159|0.235100|21159|0.235100|2351|0.026122|209|N/A|K__ +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|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_ -audio|0|39968|0.444089|39968|0.444089|2351|0.026122|209|N/A|K_ -audio|0|42319|0.470211|42319|0.470211|2351|0.026122|209|N/A|K_ -audio|0|44670|0.496333|44670|0.496333|2351|0.026122|209|N/A|K_ -audio|0|47021|0.522456|47021|0.522456|2351|0.026122|209|N/A|K_ -audio|0|49372|0.548578|49372|0.548578|2351|0.026122|209|N/A|K_ -audio|0|51723|0.574700|51723|0.574700|2351|0.026122|209|N/A|K_ -audio|0|54074|0.600822|54074|0.600822|2351|0.026122|209|N/A|K_ -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 +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__ +audio|0|39968|0.444089|39968|0.444089|2351|0.026122|209|N/A|K__ +audio|0|42319|0.470211|42319|0.470211|2351|0.026122|209|N/A|K__ +audio|0|44670|0.496333|44670|0.496333|2351|0.026122|209|N/A|K__ +audio|0|47021|0.522456|47021|0.522456|2351|0.026122|209|N/A|K__ +audio|0|49372|0.548578|49372|0.548578|2351|0.026122|209|N/A|K__ +audio|0|51723|0.574700|51723|0.574700|2351|0.026122|209|N/A|K__ +audio|0|54074|0.600822|54074|0.600822|2351|0.026122|209|N/A|K__ +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|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_ -audio|0|72882|0.809800|72882|0.809800|2351|0.026122|209|N/A|K_ -audio|0|75233|0.835922|75233|0.835922|2351|0.026122|209|N/A|K_ -audio|0|77584|0.862044|77584|0.862044|2351|0.026122|209|N/A|K_ -audio|0|79935|0.888167|79935|0.888167|2351|0.026122|209|N/A|K_ -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 +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__ +audio|0|72882|0.809800|72882|0.809800|2351|0.026122|209|N/A|K__ +audio|0|75233|0.835922|75233|0.835922|2351|0.026122|209|N/A|K__ +audio|0|77584|0.862044|77584|0.862044|2351|0.026122|209|N/A|K__ +audio|0|79935|0.888167|79935|0.888167|2351|0.026122|209|N/A|K__ +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|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|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|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_ -audio|0|98035|1.089278|98035|1.089278|2351|0.026122|209|N/A|K_ -audio|0|100386|1.115400|100386|1.115400|2351|0.026122|209|N/A|K_ -audio|0|102737|1.141522|102737|1.141522|2351|0.026122|209|N/A|K_ -audio|0|105088|1.167644|105088|1.167644|2351|0.026122|209|N/A|K_ -audio|0|107439|1.193767|107439|1.193767|2351|0.026122|209|N/A|K_ -audio|0|109790|1.219889|109790|1.219889|2351|0.026122|209|N/A|K_ -audio|0|112141|1.246011|112141|1.246011|2351|0.026122|209|N/A|K_ -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 +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__ +audio|0|98035|1.089278|98035|1.089278|2351|0.026122|209|N/A|K__ +audio|0|100386|1.115400|100386|1.115400|2351|0.026122|209|N/A|K__ +audio|0|102737|1.141522|102737|1.141522|2351|0.026122|209|N/A|K__ +audio|0|105088|1.167644|105088|1.167644|2351|0.026122|209|N/A|K__ +audio|0|107439|1.193767|107439|1.193767|2351|0.026122|209|N/A|K__ +audio|0|109790|1.219889|109790|1.219889|2351|0.026122|209|N/A|K__ +audio|0|112141|1.246011|112141|1.246011|2351|0.026122|209|N/A|K__ +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|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_ -audio|0|130950|1.455000|130950|1.455000|2351|0.026122|209|N/A|K_ -audio|0|133301|1.481122|133301|1.481122|2351|0.026122|209|N/A|K_ -audio|0|135652|1.507244|135652|1.507244|2351|0.026122|209|N/A|K_ -audio|0|138003|1.533367|138003|1.533367|2351|0.026122|209|N/A|K_ -audio|0|140354|1.559489|140354|1.559489|2351|0.026122|209|N/A|K_ -audio|0|142705|1.585611|142705|1.585611|2351|0.026122|209|N/A|K_ -audio|0|145056|1.611733|145056|1.611733|2351|0.026122|209|N/A|K_ -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 +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__ +audio|0|130950|1.455000|130950|1.455000|2351|0.026122|209|N/A|K__ +audio|0|133301|1.481122|133301|1.481122|2351|0.026122|209|N/A|K__ +audio|0|135652|1.507244|135652|1.507244|2351|0.026122|209|N/A|K__ +audio|0|138003|1.533367|138003|1.533367|2351|0.026122|209|N/A|K__ +audio|0|140354|1.559489|140354|1.559489|2351|0.026122|209|N/A|K__ +audio|0|142705|1.585611|142705|1.585611|2351|0.026122|209|N/A|K__ +audio|0|145056|1.611733|145056|1.611733|2351|0.026122|209|N/A|K__ +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|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_ -audio|0|163864|1.820711|163864|1.820711|2351|0.026122|209|N/A|K_ -audio|0|166215|1.846833|166215|1.846833|2351|0.026122|209|N/A|K_ -audio|0|168566|1.872956|168566|1.872956|2351|0.026122|209|N/A|K_ -audio|0|170917|1.899078|170917|1.899078|2351|0.026122|209|N/A|K_ -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 +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__ +audio|0|163864|1.820711|163864|1.820711|2351|0.026122|209|N/A|K__ +audio|0|166215|1.846833|166215|1.846833|2351|0.026122|209|N/A|K__ +audio|0|168566|1.872956|168566|1.872956|2351|0.026122|209|N/A|K__ +audio|0|170917|1.899078|170917|1.899078|2351|0.026122|209|N/A|K__ +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|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|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|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_ -audio|0|139482|1.549800|139482|1.549800|2351|0.026122|209|N/A|K_ -audio|0|141833|1.575922|141833|1.575922|2351|0.026122|209|N/A|K_ -audio|0|144184|1.602044|144184|1.602044|2351|0.026122|209|N/A|K_ -audio|0|146535|1.628167|146535|1.628167|2351|0.026122|209|N/A|K_ -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 +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__ +audio|0|139482|1.549800|139482|1.549800|2351|0.026122|209|N/A|K__ +audio|0|141833|1.575922|141833|1.575922|2351|0.026122|209|N/A|K__ +audio|0|144184|1.602044|144184|1.602044|2351|0.026122|209|N/A|K__ +audio|0|146535|1.628167|146535|1.628167|2351|0.026122|209|N/A|K__ +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|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|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|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|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 diff --git a/tests/ref/fate/ffprobe_compact b/tests/ref/fate/ffprobe_compact index 8286f5d9734..f00a4485614 100644 --- a/tests/ref/fate/ffprobe_compact +++ b/tests/ref/fate/ffprobe_compact @@ -1,30 +1,30 @@ -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_ +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|duration=1024|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_ +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|duration=2048|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_ +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|duration=2048|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_ +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|duration=1024|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_ +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|duration=2048|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_ +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|duration=2048|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_ +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|duration=1024|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_ +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|duration=1024|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_ +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|duration=2048|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_ +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|duration=2048|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_ +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|duration=1024|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_ +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|duration=393|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_ +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|duration=2048|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_ +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|duration=2048|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|initial_padding=0|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=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 diff --git a/tests/ref/fate/ffprobe_csv b/tests/ref/fate/ffprobe_csv index d8aa2f93434..2ec2836c263 100644 --- a/tests/ref/fate/ffprobe_csv +++ b/tests/ref/fate/ffprobe_csv @@ -1,30 +1,30 @@ -packet,audio,0,0,0.000000,0,0.000000,1024,0.023220,2048,669,K_ +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,1024,0.023220,669,2048,s16,1024,1,unknown -packet,video,1,0,0.000000,0,0.000000,2048,0.040000,230400,2744,K_ +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,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_ +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,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_ +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,1024,0.023220,263170,2048,s16,1024,1,unknown -packet,video,1,2048,0.040000,2048,0.040000,2048,0.040000,230400,265248,K_ +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,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_ +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,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_ +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,1024,0.023220,525677,2048,s16,1024,1,unknown -packet,audio,0,3072,0.069660,3072,0.069660,1024,0.023220,2048,527748,K_ +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,1024,0.023220,527748,2048,s16,1024,1,unknown -packet,video,1,4096,0.080000,4096,0.080000,2048,0.040000,230400,529826,K_ +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,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_ +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,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_ +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,1024,0.023220,790255,2048,s16,1024,1,unknown -packet,audio,0,5120,0.116100,5120,0.116100,393,0.008912,786,792326,K_ +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,393,0.008912,792326,786,s16,393,1,unknown -packet,video,1,6144,0.120000,6144,0.120000,2048,0.040000,230400,793142,K_ +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,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_ +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,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,0,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,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 diff --git a/tests/ref/fate/ffprobe_default b/tests/ref/fate/ffprobe_default index 7f7b2702fe7..f8c18a1e504 100644 --- a/tests/ref/fate/ffprobe_default +++ b/tests/ref/fate/ffprobe_default @@ -9,7 +9,7 @@ duration=1024 duration_time=0.023220 size=2048 pos=669 -flags=K_ +flags=K__ [/PACKET] [FRAME] media_type=audio @@ -43,7 +43,7 @@ duration=2048 duration_time=0.040000 size=230400 pos=2744 -flags=K_ +flags=K__ [/PACKET] [FRAME] media_type=video @@ -88,7 +88,7 @@ duration=2048 duration_time=0.040000 size=30000 pos=233165 -flags=K_ +flags=K__ [/PACKET] [FRAME] media_type=video @@ -133,7 +133,7 @@ duration=1024 duration_time=0.023220 size=2048 pos=263170 -flags=K_ +flags=K__ [/PACKET] [FRAME] media_type=audio @@ -167,7 +167,7 @@ duration=2048 duration_time=0.040000 size=230400 pos=265248 -flags=K_ +flags=K__ [/PACKET] [FRAME] media_type=video @@ -212,7 +212,7 @@ duration=2048 duration_time=0.040000 size=30000 pos=495672 -flags=K_ +flags=K__ [/PACKET] [FRAME] media_type=video @@ -257,7 +257,7 @@ duration=1024 duration_time=0.023220 size=2048 pos=525677 -flags=K_ +flags=K__ [/PACKET] [FRAME] media_type=audio @@ -291,7 +291,7 @@ duration=1024 duration_time=0.023220 size=2048 pos=527748 -flags=K_ +flags=K__ [/PACKET] [FRAME] media_type=audio @@ -325,7 +325,7 @@ duration=2048 duration_time=0.040000 size=230400 pos=529826 -flags=K_ +flags=K__ [/PACKET] [FRAME] media_type=video @@ -370,7 +370,7 @@ duration=2048 duration_time=0.040000 size=30000 pos=760250 -flags=K_ +flags=K__ [/PACKET] [FRAME] media_type=video @@ -415,7 +415,7 @@ duration=1024 duration_time=0.023220 size=2048 pos=790255 -flags=K_ +flags=K__ [/PACKET] [FRAME] media_type=audio @@ -449,7 +449,7 @@ duration=393 duration_time=0.008912 size=786 pos=792326 -flags=K_ +flags=K__ [/PACKET] [FRAME] media_type=audio @@ -483,7 +483,7 @@ duration=2048 duration_time=0.040000 size=230400 pos=793142 -flags=K_ +flags=K__ [/PACKET] [FRAME] media_type=video @@ -528,7 +528,7 @@ duration=2048 duration_time=0.040000 size=30000 pos=1023566 -flags=K_ +flags=K__ [/PACKET] [FRAME] media_type=video diff --git a/tests/ref/fate/ffprobe_flat b/tests/ref/fate/ffprobe_flat index c2f08f6658b..ee4373408f0 100644 --- a/tests/ref/fate/ffprobe_flat +++ b/tests/ref/fate/ffprobe_flat @@ -8,7 +8,7 @@ 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="669" -packets_and_frames.packet.0.flags="K_" +packets_and_frames.packet.0.flags="K__" packets_and_frames.frame.0.media_type="audio" packets_and_frames.frame.0.stream_index=0 packets_and_frames.frame.0.key_frame=1 @@ -38,7 +38,7 @@ 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="2744" -packets_and_frames.packet.1.flags="K_" +packets_and_frames.packet.1.flags="K__" packets_and_frames.frame.1.media_type="video" packets_and_frames.frame.1.stream_index=1 packets_and_frames.frame.1.key_frame=1 @@ -79,7 +79,7 @@ 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="233165" -packets_and_frames.packet.2.flags="K_" +packets_and_frames.packet.2.flags="K__" packets_and_frames.frame.2.media_type="video" packets_and_frames.frame.2.stream_index=2 packets_and_frames.frame.2.key_frame=1 @@ -120,7 +120,7 @@ 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="263170" -packets_and_frames.packet.3.flags="K_" +packets_and_frames.packet.3.flags="K__" packets_and_frames.frame.3.media_type="audio" packets_and_frames.frame.3.stream_index=0 packets_and_frames.frame.3.key_frame=1 @@ -150,7 +150,7 @@ 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="265248" -packets_and_frames.packet.4.flags="K_" +packets_and_frames.packet.4.flags="K__" packets_and_frames.frame.4.media_type="video" packets_and_frames.frame.4.stream_index=1 packets_and_frames.frame.4.key_frame=1 @@ -191,7 +191,7 @@ 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="495672" -packets_and_frames.packet.5.flags="K_" +packets_and_frames.packet.5.flags="K__" packets_and_frames.frame.5.media_type="video" packets_and_frames.frame.5.stream_index=2 packets_and_frames.frame.5.key_frame=1 @@ -232,7 +232,7 @@ 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="525677" -packets_and_frames.packet.6.flags="K_" +packets_and_frames.packet.6.flags="K__" packets_and_frames.frame.6.media_type="audio" packets_and_frames.frame.6.stream_index=0 packets_and_frames.frame.6.key_frame=1 @@ -262,7 +262,7 @@ 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="527748" -packets_and_frames.packet.7.flags="K_" +packets_and_frames.packet.7.flags="K__" packets_and_frames.frame.7.media_type="audio" packets_and_frames.frame.7.stream_index=0 packets_and_frames.frame.7.key_frame=1 @@ -292,7 +292,7 @@ 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="529826" -packets_and_frames.packet.8.flags="K_" +packets_and_frames.packet.8.flags="K__" packets_and_frames.frame.8.media_type="video" packets_and_frames.frame.8.stream_index=1 packets_and_frames.frame.8.key_frame=1 @@ -333,7 +333,7 @@ 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="760250" -packets_and_frames.packet.9.flags="K_" +packets_and_frames.packet.9.flags="K__" packets_and_frames.frame.9.media_type="video" packets_and_frames.frame.9.stream_index=2 packets_and_frames.frame.9.key_frame=1 @@ -374,7 +374,7 @@ 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="790255" -packets_and_frames.packet.10.flags="K_" +packets_and_frames.packet.10.flags="K__" packets_and_frames.frame.10.media_type="audio" packets_and_frames.frame.10.stream_index=0 packets_and_frames.frame.10.key_frame=1 @@ -404,7 +404,7 @@ 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="792326" -packets_and_frames.packet.11.flags="K_" +packets_and_frames.packet.11.flags="K__" packets_and_frames.frame.11.media_type="audio" packets_and_frames.frame.11.stream_index=0 packets_and_frames.frame.11.key_frame=1 @@ -434,7 +434,7 @@ 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="793142" -packets_and_frames.packet.12.flags="K_" +packets_and_frames.packet.12.flags="K__" packets_and_frames.frame.12.media_type="video" packets_and_frames.frame.12.stream_index=1 packets_and_frames.frame.12.key_frame=1 @@ -475,7 +475,7 @@ 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="1023566" -packets_and_frames.packet.13.flags="K_" +packets_and_frames.packet.13.flags="K__" packets_and_frames.frame.13.media_type="video" packets_and_frames.frame.13.stream_index=2 packets_and_frames.frame.13.key_frame=1 diff --git a/tests/ref/fate/ffprobe_ini b/tests/ref/fate/ffprobe_ini index bf9efd880ed..77a12eaa135 100644 --- a/tests/ref/fate/ffprobe_ini +++ b/tests/ref/fate/ffprobe_ini @@ -11,7 +11,7 @@ duration=1024 duration_time=0.023220 size=2048 pos=669 -flags=K_ +flags=K__ [packets_and_frames.frame.0] media_type=audio @@ -45,7 +45,7 @@ duration=2048 duration_time=0.040000 size=230400 pos=2744 -flags=K_ +flags=K__ [packets_and_frames.frame.1] media_type=video @@ -90,7 +90,7 @@ duration=2048 duration_time=0.040000 size=30000 pos=233165 -flags=K_ +flags=K__ [packets_and_frames.frame.2] media_type=video @@ -135,7 +135,7 @@ duration=1024 duration_time=0.023220 size=2048 pos=263170 -flags=K_ +flags=K__ [packets_and_frames.frame.3] media_type=audio @@ -169,7 +169,7 @@ duration=2048 duration_time=0.040000 size=230400 pos=265248 -flags=K_ +flags=K__ [packets_and_frames.frame.4] media_type=video @@ -214,7 +214,7 @@ duration=2048 duration_time=0.040000 size=30000 pos=495672 -flags=K_ +flags=K__ [packets_and_frames.frame.5] media_type=video @@ -259,7 +259,7 @@ duration=1024 duration_time=0.023220 size=2048 pos=525677 -flags=K_ +flags=K__ [packets_and_frames.frame.6] media_type=audio @@ -293,7 +293,7 @@ duration=1024 duration_time=0.023220 size=2048 pos=527748 -flags=K_ +flags=K__ [packets_and_frames.frame.7] media_type=audio @@ -327,7 +327,7 @@ duration=2048 duration_time=0.040000 size=230400 pos=529826 -flags=K_ +flags=K__ [packets_and_frames.frame.8] media_type=video @@ -372,7 +372,7 @@ duration=2048 duration_time=0.040000 size=30000 pos=760250 -flags=K_ +flags=K__ [packets_and_frames.frame.9] media_type=video @@ -417,7 +417,7 @@ duration=1024 duration_time=0.023220 size=2048 pos=790255 -flags=K_ +flags=K__ [packets_and_frames.frame.10] media_type=audio @@ -451,7 +451,7 @@ duration=393 duration_time=0.008912 size=786 pos=792326 -flags=K_ +flags=K__ [packets_and_frames.frame.11] media_type=audio @@ -485,7 +485,7 @@ duration=2048 duration_time=0.040000 size=230400 pos=793142 -flags=K_ +flags=K__ [packets_and_frames.frame.12] media_type=video @@ -530,7 +530,7 @@ duration=2048 duration_time=0.040000 size=30000 pos=1023566 -flags=K_ +flags=K__ [packets_and_frames.frame.13] media_type=video diff --git a/tests/ref/fate/ffprobe_json b/tests/ref/fate/ffprobe_json index eb63664cbaf..89e89e4a7a1 100644 --- a/tests/ref/fate/ffprobe_json +++ b/tests/ref/fate/ffprobe_json @@ -12,7 +12,7 @@ "duration_time": "0.023220", "size": "2048", "pos": "669", - "flags": "K_" + "flags": "K__" }, { "type": "frame", @@ -47,7 +47,7 @@ "duration_time": "0.040000", "size": "230400", "pos": "2744", - "flags": "K_" + "flags": "K__" }, { "type": "frame", @@ -89,7 +89,7 @@ "duration_time": "0.040000", "size": "30000", "pos": "233165", - "flags": "K_" + "flags": "K__" }, { "type": "frame", @@ -131,7 +131,7 @@ "duration_time": "0.023220", "size": "2048", "pos": "263170", - "flags": "K_" + "flags": "K__" }, { "type": "frame", @@ -166,7 +166,7 @@ "duration_time": "0.040000", "size": "230400", "pos": "265248", - "flags": "K_" + "flags": "K__" }, { "type": "frame", @@ -208,7 +208,7 @@ "duration_time": "0.040000", "size": "30000", "pos": "495672", - "flags": "K_" + "flags": "K__" }, { "type": "frame", @@ -250,7 +250,7 @@ "duration_time": "0.023220", "size": "2048", "pos": "525677", - "flags": "K_" + "flags": "K__" }, { "type": "frame", @@ -285,7 +285,7 @@ "duration_time": "0.023220", "size": "2048", "pos": "527748", - "flags": "K_" + "flags": "K__" }, { "type": "frame", @@ -320,7 +320,7 @@ "duration_time": "0.040000", "size": "230400", "pos": "529826", - "flags": "K_" + "flags": "K__" }, { "type": "frame", @@ -362,7 +362,7 @@ "duration_time": "0.040000", "size": "30000", "pos": "760250", - "flags": "K_" + "flags": "K__" }, { "type": "frame", @@ -404,7 +404,7 @@ "duration_time": "0.023220", "size": "2048", "pos": "790255", - "flags": "K_" + "flags": "K__" }, { "type": "frame", @@ -439,7 +439,7 @@ "duration_time": "0.008912", "size": "786", "pos": "792326", - "flags": "K_" + "flags": "K__" }, { "type": "frame", @@ -474,7 +474,7 @@ "duration_time": "0.040000", "size": "230400", "pos": "793142", - "flags": "K_" + "flags": "K__" }, { "type": "frame", @@ -516,7 +516,7 @@ "duration_time": "0.040000", "size": "30000", "pos": "1023566", - "flags": "K_" + "flags": "K__" }, { "type": "frame", diff --git a/tests/ref/fate/ffprobe_xml b/tests/ref/fate/ffprobe_xml index 707033f830e..bd0db8746fb 100644 --- a/tests/ref/fate/ffprobe_xml +++ b/tests/ref/fate/ffprobe_xml @@ -1,33 +1,33 @@ - + - + - + - + - + - + - + - + - + - + - + - + - + - + diff --git a/tests/ref/fate/ffprobe_xsd b/tests/ref/fate/ffprobe_xsd index 412fd9a180a..f05813bc4d0 100644 --- a/tests/ref/fate/ffprobe_xsd +++ b/tests/ref/fate/ffprobe_xsd @@ -1,33 +1,33 @@ - + - + - + - + - + - + - + - + - + - + - + - + - + - + diff --git a/tests/ref/fate/flcl1905 b/tests/ref/fate/flcl1905 index 679896e33d5..666b2600e43 100644 --- a/tests/ref/fate/flcl1905 +++ b/tests/ref/fate/flcl1905 @@ -1,4 +1,4 @@ -packet|codec_type=audio|stream_index=0|pts=0|pts_time=0.000000|dts=0|dts_time=0.000000|duration=22528|duration_time=0.510839|size=4092|pos=56|flags=K_ +packet|codec_type=audio|stream_index=0|pts=0|pts_time=0.000000|dts=0|dts_time=0.000000|duration=22528|duration_time=0.510839|size=4092|pos=56|flags=K__ frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=56|pkt_size=3348|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=56|pkt_size=2976|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=56|pkt_size=2604|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown @@ -8,7 +8,7 @@ frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=56|pkt_size=1116|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=56|pkt_size=744|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=56|pkt_size=372|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown -packet|codec_type=audio|stream_index=0|pts=22528|pts_time=0.510839|dts=22528|dts_time=0.510839|duration=22528|duration_time=0.510839|size=4092|pos=4148|flags=K_ +packet|codec_type=audio|stream_index=0|pts=22528|pts_time=0.510839|dts=22528|dts_time=0.510839|duration=22528|duration_time=0.510839|size=4092|pos=4148|flags=K__ frame|media_type=audio|stream_index=0|key_frame=1|pts=22528|pts_time=0.510839|pkt_dts=22528|pkt_dts_time=0.510839|best_effort_timestamp=22528|best_effort_timestamp_time=0.510839|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=4148|pkt_size=4092|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=4148|pkt_size=3720|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=4148|pkt_size=3348|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown @@ -20,7 +20,7 @@ frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=4148|pkt_size=1116|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=4148|pkt_size=744|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=4148|pkt_size=372|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown -packet|codec_type=audio|stream_index=0|pts=45056|pts_time=1.021678|dts=45056|dts_time=1.021678|duration=22528|duration_time=0.510839|size=4092|pos=8240|flags=K_ +packet|codec_type=audio|stream_index=0|pts=45056|pts_time=1.021678|dts=45056|dts_time=1.021678|duration=22528|duration_time=0.510839|size=4092|pos=8240|flags=K__ frame|media_type=audio|stream_index=0|key_frame=1|pts=45056|pts_time=1.021678|pkt_dts=45056|pkt_dts_time=1.021678|best_effort_timestamp=45056|best_effort_timestamp_time=1.021678|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=8240|pkt_size=4092|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=8240|pkt_size=3720|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=8240|pkt_size=3348|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown @@ -32,7 +32,7 @@ frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=8240|pkt_size=1116|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=8240|pkt_size=744|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=8240|pkt_size=372|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown -packet|codec_type=audio|stream_index=0|pts=67584|pts_time=1.532517|dts=67584|dts_time=1.532517|duration=22528|duration_time=0.510839|size=4092|pos=12332|flags=K_ +packet|codec_type=audio|stream_index=0|pts=67584|pts_time=1.532517|dts=67584|dts_time=1.532517|duration=22528|duration_time=0.510839|size=4092|pos=12332|flags=K__ frame|media_type=audio|stream_index=0|key_frame=1|pts=67584|pts_time=1.532517|pkt_dts=67584|pkt_dts_time=1.532517|best_effort_timestamp=67584|best_effort_timestamp_time=1.532517|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=12332|pkt_size=4092|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=12332|pkt_size=3720|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=12332|pkt_size=3348|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown @@ -44,7 +44,7 @@ frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=12332|pkt_size=1116|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=12332|pkt_size=744|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=12332|pkt_size=372|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown -packet|codec_type=audio|stream_index=0|pts=90112|pts_time=2.043356|dts=90112|dts_time=2.043356|duration=22528|duration_time=0.510839|size=4092|pos=16424|flags=K_ +packet|codec_type=audio|stream_index=0|pts=90112|pts_time=2.043356|dts=90112|dts_time=2.043356|duration=22528|duration_time=0.510839|size=4092|pos=16424|flags=K__ frame|media_type=audio|stream_index=0|key_frame=1|pts=90112|pts_time=2.043356|pkt_dts=90112|pkt_dts_time=2.043356|best_effort_timestamp=90112|best_effort_timestamp_time=2.043356|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=16424|pkt_size=4092|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=16424|pkt_size=3720|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=16424|pkt_size=3348|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown @@ -56,7 +56,7 @@ frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=16424|pkt_size=1116|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=16424|pkt_size=744|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=16424|pkt_size=372|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown -packet|codec_type=audio|stream_index=0|pts=112640|pts_time=2.554195|dts=112640|dts_time=2.554195|duration=22528|duration_time=0.510839|size=4092|pos=20516|flags=K_ +packet|codec_type=audio|stream_index=0|pts=112640|pts_time=2.554195|dts=112640|dts_time=2.554195|duration=22528|duration_time=0.510839|size=4092|pos=20516|flags=K__ frame|media_type=audio|stream_index=0|key_frame=1|pts=112640|pts_time=2.554195|pkt_dts=112640|pkt_dts_time=2.554195|best_effort_timestamp=112640|best_effort_timestamp_time=2.554195|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=20516|pkt_size=4092|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=20516|pkt_size=3720|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=20516|pkt_size=3348|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown @@ -68,7 +68,7 @@ frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=20516|pkt_size=1116|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=20516|pkt_size=744|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=20516|pkt_size=372|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown -packet|codec_type=audio|stream_index=0|pts=135168|pts_time=3.065034|dts=135168|dts_time=3.065034|duration=22528|duration_time=0.510839|size=4092|pos=24608|flags=K_ +packet|codec_type=audio|stream_index=0|pts=135168|pts_time=3.065034|dts=135168|dts_time=3.065034|duration=22528|duration_time=0.510839|size=4092|pos=24608|flags=K__ frame|media_type=audio|stream_index=0|key_frame=1|pts=135168|pts_time=3.065034|pkt_dts=135168|pkt_dts_time=3.065034|best_effort_timestamp=135168|best_effort_timestamp_time=3.065034|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=24608|pkt_size=4092|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=24608|pkt_size=3720|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=24608|pkt_size=3348|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown @@ -80,7 +80,7 @@ frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=24608|pkt_size=1116|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=24608|pkt_size=744|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=24608|pkt_size=372|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown -packet|codec_type=audio|stream_index=0|pts=157696|pts_time=3.575873|dts=157696|dts_time=3.575873|duration=22528|duration_time=0.510839|size=4092|pos=28700|flags=K_ +packet|codec_type=audio|stream_index=0|pts=157696|pts_time=3.575873|dts=157696|dts_time=3.575873|duration=22528|duration_time=0.510839|size=4092|pos=28700|flags=K__ frame|media_type=audio|stream_index=0|key_frame=1|pts=157696|pts_time=3.575873|pkt_dts=157696|pkt_dts_time=3.575873|best_effort_timestamp=157696|best_effort_timestamp_time=3.575873|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=28700|pkt_size=4092|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=28700|pkt_size=3720|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=28700|pkt_size=3348|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown @@ -92,7 +92,7 @@ frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=28700|pkt_size=1116|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=28700|pkt_size=744|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=28700|pkt_size=372|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown -packet|codec_type=audio|stream_index=0|pts=180224|pts_time=4.086712|dts=180224|dts_time=4.086712|duration=22528|duration_time=0.510839|size=4092|pos=32792|flags=K_ +packet|codec_type=audio|stream_index=0|pts=180224|pts_time=4.086712|dts=180224|dts_time=4.086712|duration=22528|duration_time=0.510839|size=4092|pos=32792|flags=K__ frame|media_type=audio|stream_index=0|key_frame=1|pts=180224|pts_time=4.086712|pkt_dts=180224|pkt_dts_time=4.086712|best_effort_timestamp=180224|best_effort_timestamp_time=4.086712|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=32792|pkt_size=4092|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=32792|pkt_size=3720|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=32792|pkt_size=3348|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown @@ -104,7 +104,7 @@ frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=32792|pkt_size=1116|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=32792|pkt_size=744|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=32792|pkt_size=372|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown -packet|codec_type=audio|stream_index=0|pts=202752|pts_time=4.597551|dts=202752|dts_time=4.597551|duration=22528|duration_time=0.510839|size=4092|pos=36884|flags=K_ +packet|codec_type=audio|stream_index=0|pts=202752|pts_time=4.597551|dts=202752|dts_time=4.597551|duration=22528|duration_time=0.510839|size=4092|pos=36884|flags=K__ frame|media_type=audio|stream_index=0|key_frame=1|pts=202752|pts_time=4.597551|pkt_dts=202752|pkt_dts_time=4.597551|best_effort_timestamp=202752|best_effort_timestamp_time=4.597551|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=36884|pkt_size=4092|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=36884|pkt_size=3720|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=36884|pkt_size=3348|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown @@ -116,7 +116,7 @@ frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=36884|pkt_size=1116|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=36884|pkt_size=744|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=36884|pkt_size=372|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown -packet|codec_type=audio|stream_index=0|pts=225280|pts_time=5.108390|dts=225280|dts_time=5.108390|duration=22528|duration_time=0.510839|size=4092|pos=40976|flags=K_ +packet|codec_type=audio|stream_index=0|pts=225280|pts_time=5.108390|dts=225280|dts_time=5.108390|duration=22528|duration_time=0.510839|size=4092|pos=40976|flags=K__ frame|media_type=audio|stream_index=0|key_frame=1|pts=225280|pts_time=5.108390|pkt_dts=225280|pkt_dts_time=5.108390|best_effort_timestamp=225280|best_effort_timestamp_time=5.108390|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=40976|pkt_size=4092|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=40976|pkt_size=3720|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=40976|pkt_size=3348|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown @@ -128,7 +128,7 @@ frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=40976|pkt_size=1116|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=40976|pkt_size=744|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=40976|pkt_size=372|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown -packet|codec_type=audio|stream_index=0|pts=247808|pts_time=5.619229|dts=247808|dts_time=5.619229|duration=22528|duration_time=0.510839|size=4092|pos=45068|flags=K_ +packet|codec_type=audio|stream_index=0|pts=247808|pts_time=5.619229|dts=247808|dts_time=5.619229|duration=22528|duration_time=0.510839|size=4092|pos=45068|flags=K__ frame|media_type=audio|stream_index=0|key_frame=1|pts=247808|pts_time=5.619229|pkt_dts=247808|pkt_dts_time=5.619229|best_effort_timestamp=247808|best_effort_timestamp_time=5.619229|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=45068|pkt_size=4092|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=45068|pkt_size=3720|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=45068|pkt_size=3348|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown @@ -140,7 +140,7 @@ frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=45068|pkt_size=1116|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=45068|pkt_size=744|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=45068|pkt_size=372|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown -packet|codec_type=audio|stream_index=0|pts=270336|pts_time=6.130068|dts=270336|dts_time=6.130068|duration=22528|duration_time=0.510839|size=4092|pos=49160|flags=K_ +packet|codec_type=audio|stream_index=0|pts=270336|pts_time=6.130068|dts=270336|dts_time=6.130068|duration=22528|duration_time=0.510839|size=4092|pos=49160|flags=K__ frame|media_type=audio|stream_index=0|key_frame=1|pts=270336|pts_time=6.130068|pkt_dts=270336|pkt_dts_time=6.130068|best_effort_timestamp=270336|best_effort_timestamp_time=6.130068|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=49160|pkt_size=4092|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=49160|pkt_size=3720|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=49160|pkt_size=3348|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown @@ -152,7 +152,7 @@ frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=49160|pkt_size=1116|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=49160|pkt_size=744|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=49160|pkt_size=372|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown -packet|codec_type=audio|stream_index=0|pts=292864|pts_time=6.640907|dts=292864|dts_time=6.640907|duration=22528|duration_time=0.510839|size=4092|pos=53252|flags=K_ +packet|codec_type=audio|stream_index=0|pts=292864|pts_time=6.640907|dts=292864|dts_time=6.640907|duration=22528|duration_time=0.510839|size=4092|pos=53252|flags=K__ frame|media_type=audio|stream_index=0|key_frame=1|pts=292864|pts_time=6.640907|pkt_dts=292864|pkt_dts_time=6.640907|best_effort_timestamp=292864|best_effort_timestamp_time=6.640907|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=53252|pkt_size=4092|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=53252|pkt_size=3720|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=53252|pkt_size=3348|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown @@ -164,7 +164,7 @@ frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=53252|pkt_size=1116|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=53252|pkt_size=744|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=53252|pkt_size=372|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown -packet|codec_type=audio|stream_index=0|pts=315392|pts_time=7.151746|dts=315392|dts_time=7.151746|duration=22528|duration_time=0.510839|size=4092|pos=57344|flags=K_ +packet|codec_type=audio|stream_index=0|pts=315392|pts_time=7.151746|dts=315392|dts_time=7.151746|duration=22528|duration_time=0.510839|size=4092|pos=57344|flags=K__ frame|media_type=audio|stream_index=0|key_frame=1|pts=315392|pts_time=7.151746|pkt_dts=315392|pkt_dts_time=7.151746|best_effort_timestamp=315392|best_effort_timestamp_time=7.151746|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=57344|pkt_size=4092|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=57344|pkt_size=3720|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=57344|pkt_size=3348|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown @@ -176,7 +176,7 @@ frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=57344|pkt_size=1116|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=57344|pkt_size=744|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=57344|pkt_size=372|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown -packet|codec_type=audio|stream_index=0|pts=337920|pts_time=7.662585|dts=337920|dts_time=7.662585|duration=22528|duration_time=0.510839|size=4092|pos=61436|flags=K_ +packet|codec_type=audio|stream_index=0|pts=337920|pts_time=7.662585|dts=337920|dts_time=7.662585|duration=22528|duration_time=0.510839|size=4092|pos=61436|flags=K__ frame|media_type=audio|stream_index=0|key_frame=1|pts=337920|pts_time=7.662585|pkt_dts=337920|pkt_dts_time=7.662585|best_effort_timestamp=337920|best_effort_timestamp_time=7.662585|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=61436|pkt_size=4092|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=61436|pkt_size=3720|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=61436|pkt_size=3348|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown @@ -188,5 +188,5 @@ frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=61436|pkt_size=1116|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=61436|pkt_size=744|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=61436|pkt_size=372|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown -packet|codec_type=audio|stream_index=0|pts=360448|pts_time=8.173424|dts=360448|dts_time=8.173424|duration=44|duration_time=0.000998|size=8|pos=65528|flags=K_ +packet|codec_type=audio|stream_index=0|pts=360448|pts_time=8.173424|dts=360448|dts_time=8.173424|duration=44|duration_time=0.000998|size=8|pos=65528|flags=K_C frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=44|pkt_duration_time=0.000998|duration=44|duration_time=0.000998|pkt_pos=65528|pkt_size=8|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown diff --git a/tests/ref/fate/flv-demux b/tests/ref/fate/flv-demux index 07d9ab5ee4a..2e9610fb4a5 100644 --- a/tests/ref/fate/flv-demux +++ b/tests/ref/fate/flv-demux @@ -1,608 +1,608 @@ -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_|data_hash=CRC32:bbb61b93|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__|data_hash=CRC32:bbb61b93|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_|data_hash=CRC32:3f2ccc9e|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__|data_hash=CRC32:3f2ccc9e|side_data|side_data_type=New Extradata -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 -packet|codec_type=video|stream_index=0|pts=67|pts_time=0.067000|dts=67|dts_time=0.067000|duration=33|duration_time=0.033000|size=14|pos=3560|flags=__|data_hash=CRC32:0b3c3ab4 -packet|codec_type=audio|stream_index=1|pts=93|pts_time=0.093000|dts=93|dts_time=0.093000|duration=46|duration_time=0.046000|size=9|pos=3594|flags=K_|data_hash=CRC32:42c079c5 -packet|codec_type=video|stream_index=0|pts=100|pts_time=0.100000|dts=100|dts_time=0.100000|duration=33|duration_time=0.033000|size=14|pos=3620|flags=__|data_hash=CRC32:280ad88b -packet|codec_type=video|stream_index=0|pts=133|pts_time=0.133000|dts=133|dts_time=0.133000|duration=33|duration_time=0.033000|size=117|pos=3654|flags=__|data_hash=CRC32:376f2497 -packet|codec_type=audio|stream_index=1|pts=139|pts_time=0.139000|dts=139|dts_time=0.139000|duration=46|duration_time=0.046000|size=89|pos=3791|flags=K_|data_hash=CRC32:548db44a -packet|codec_type=video|stream_index=0|pts=167|pts_time=0.167000|dts=167|dts_time=0.167000|duration=33|duration_time=0.033000|size=14|pos=3897|flags=__|data_hash=CRC32:0811a146 -packet|codec_type=audio|stream_index=1|pts=186|pts_time=0.186000|dts=186|dts_time=0.186000|duration=46|duration_time=0.046000|size=155|pos=3931|flags=K_|data_hash=CRC32:a7111723 -packet|codec_type=video|stream_index=0|pts=200|pts_time=0.200000|dts=200|dts_time=0.200000|duration=33|duration_time=0.033000|size=14|pos=4103|flags=__|data_hash=CRC32:3bfeef21 -packet|codec_type=audio|stream_index=1|pts=232|pts_time=0.232000|dts=232|dts_time=0.232000|duration=46|duration_time=0.046000|size=281|pos=4137|flags=K_|data_hash=CRC32:27f537aa -packet|codec_type=video|stream_index=0|pts=234|pts_time=0.234000|dts=234|dts_time=0.234000|duration=33|duration_time=0.033000|size=117|pos=4435|flags=__|data_hash=CRC32:2bc5eba8 -packet|codec_type=video|stream_index=0|pts=267|pts_time=0.267000|dts=267|dts_time=0.267000|duration=33|duration_time=0.033000|size=14|pos=4572|flags=__|data_hash=CRC32:0033671d -packet|codec_type=audio|stream_index=1|pts=279|pts_time=0.279000|dts=279|dts_time=0.279000|duration=46|duration_time=0.046000|size=548|pos=4606|flags=K_|data_hash=CRC32:7ab3c7cb -packet|codec_type=video|stream_index=0|pts=300|pts_time=0.300000|dts=300|dts_time=0.300000|duration=33|duration_time=0.033000|size=14|pos=5171|flags=__|data_hash=CRC32:dfb4f951 -packet|codec_type=audio|stream_index=1|pts=325|pts_time=0.325000|dts=325|dts_time=0.325000|duration=46|duration_time=0.046000|size=472|pos=5205|flags=K_|data_hash=CRC32:d10a7849 -packet|codec_type=video|stream_index=0|pts=334|pts_time=0.334000|dts=334|dts_time=0.334000|duration=33|duration_time=0.033000|size=117|pos=5694|flags=__|data_hash=CRC32:97814fc1 -packet|codec_type=video|stream_index=0|pts=367|pts_time=0.367000|dts=367|dts_time=0.367000|duration=33|duration_time=0.033000|size=14|pos=5831|flags=__|data_hash=CRC32:3c206b65 -packet|codec_type=audio|stream_index=1|pts=372|pts_time=0.372000|dts=372|dts_time=0.372000|duration=46|duration_time=0.046000|size=489|pos=5865|flags=K_|data_hash=CRC32:4d3f1f03 -packet|codec_type=video|stream_index=0|pts=400|pts_time=0.400000|dts=400|dts_time=0.400000|duration=33|duration_time=0.033000|size=14|pos=6371|flags=__|data_hash=CRC32:0fcf2502 -packet|codec_type=audio|stream_index=1|pts=418|pts_time=0.418000|dts=418|dts_time=0.418000|duration=46|duration_time=0.046000|size=357|pos=6405|flags=K_|data_hash=CRC32:eccea9c1 -packet|codec_type=video|stream_index=0|pts=434|pts_time=0.434000|dts=434|dts_time=0.434000|duration=33|duration_time=0.033000|size=207|pos=6779|flags=__|data_hash=CRC32:86bab8df -packet|codec_type=audio|stream_index=1|pts=464|pts_time=0.464000|dts=464|dts_time=0.464000|duration=46|duration_time=0.046000|size=262|pos=7006|flags=K_|data_hash=CRC32:50b0e3b7 -packet|codec_type=video|stream_index=0|pts=467|pts_time=0.467000|dts=467|dts_time=0.467000|duration=33|duration_time=0.033000|size=14|pos=7285|flags=__|data_hash=CRC32:8704a589 -packet|codec_type=video|stream_index=0|pts=501|pts_time=0.501000|dts=501|dts_time=0.501000|duration=33|duration_time=0.033000|size=14|pos=7319|flags=__|data_hash=CRC32:d3357720 -packet|codec_type=audio|stream_index=1|pts=511|pts_time=0.511000|dts=511|dts_time=0.511000|duration=46|duration_time=0.046000|size=294|pos=7353|flags=K_|data_hash=CRC32:805a1f22 -packet|codec_type=video|stream_index=0|pts=534|pts_time=0.534000|dts=534|dts_time=0.534000|duration=33|duration_time=0.033000|size=179|pos=7664|flags=__|data_hash=CRC32:5b61c9b6 -packet|codec_type=audio|stream_index=1|pts=557|pts_time=0.557000|dts=557|dts_time=0.557000|duration=46|duration_time=0.046000|size=204|pos=7863|flags=K_|data_hash=CRC32:7f4a9c90 -packet|codec_type=video|stream_index=0|pts=567|pts_time=0.567000|dts=567|dts_time=0.567000|duration=33|duration_time=0.033000|size=14|pos=8084|flags=__|data_hash=CRC32:44067395 -packet|codec_type=video|stream_index=0|pts=601|pts_time=0.601000|dts=601|dts_time=0.601000|duration=33|duration_time=0.033000|size=14|pos=8118|flags=__|data_hash=CRC32:00ee0d64 -packet|codec_type=audio|stream_index=1|pts=604|pts_time=0.604000|dts=604|dts_time=0.604000|duration=46|duration_time=0.046000|size=275|pos=8152|flags=K_|data_hash=CRC32:d04e94cd -packet|codec_type=video|stream_index=0|pts=634|pts_time=0.634000|dts=634|dts_time=0.634000|duration=33|duration_time=0.033000|size=32|pos=8444|flags=__|data_hash=CRC32:41c4e3cb -packet|codec_type=audio|stream_index=1|pts=650|pts_time=0.650000|dts=650|dts_time=0.650000|duration=46|duration_time=0.046000|size=309|pos=8496|flags=K_|data_hash=CRC32:c3b4718d -packet|codec_type=video|stream_index=0|pts=667|pts_time=0.667000|dts=667|dts_time=0.667000|duration=33|duration_time=0.033000|size=30|pos=8822|flags=__|data_hash=CRC32:9894f2b3 -packet|codec_type=audio|stream_index=1|pts=697|pts_time=0.697000|dts=697|dts_time=0.697000|duration=46|duration_time=0.046000|size=280|pos=8872|flags=K_|data_hash=CRC32:683aa168 -packet|codec_type=video|stream_index=0|pts=701|pts_time=0.701000|dts=701|dts_time=0.701000|duration=33|duration_time=0.033000|size=16|pos=9169|flags=__|data_hash=CRC32:33031360 -packet|codec_type=video|stream_index=0|pts=734|pts_time=0.734000|dts=734|dts_time=0.734000|duration=33|duration_time=0.033000|size=33|pos=9205|flags=__|data_hash=CRC32:4cb9408b -packet|codec_type=audio|stream_index=1|pts=743|pts_time=0.743000|dts=743|dts_time=0.743000|duration=46|duration_time=0.046000|size=106|pos=9258|flags=K_|data_hash=CRC32:d3693544 -packet|codec_type=video|stream_index=0|pts=767|pts_time=0.767000|dts=767|dts_time=0.767000|duration=33|duration_time=0.033000|size=16|pos=9381|flags=__|data_hash=CRC32:ebca8d2b -packet|codec_type=audio|stream_index=1|pts=789|pts_time=0.789000|dts=789|dts_time=0.789000|duration=46|duration_time=0.046000|size=133|pos=9417|flags=K_|data_hash=CRC32:848dc228 -packet|codec_type=video|stream_index=0|pts=801|pts_time=0.801000|dts=801|dts_time=0.801000|duration=33|duration_time=0.033000|size=16|pos=9567|flags=__|data_hash=CRC32:9d238d80 -packet|codec_type=video|stream_index=0|pts=834|pts_time=0.834000|dts=834|dts_time=0.834000|duration=33|duration_time=0.033000|size=22|pos=9603|flags=__|data_hash=CRC32:d606882e -packet|codec_type=audio|stream_index=1|pts=836|pts_time=0.836000|dts=836|dts_time=0.836000|duration=46|duration_time=0.046000|size=380|pos=9645|flags=K_|data_hash=CRC32:70b58912 -packet|codec_type=video|stream_index=0|pts=868|pts_time=0.868000|dts=868|dts_time=0.868000|duration=33|duration_time=0.033000|size=14|pos=10042|flags=__|data_hash=CRC32:39d914b1 -packet|codec_type=audio|stream_index=1|pts=882|pts_time=0.882000|dts=882|dts_time=0.882000|duration=46|duration_time=0.046000|size=378|pos=10076|flags=K_|data_hash=CRC32:7eaf35cb -packet|codec_type=video|stream_index=0|pts=901|pts_time=0.901000|dts=901|dts_time=0.901000|duration=33|duration_time=0.033000|size=14|pos=10471|flags=__|data_hash=CRC32:1aeff68e -packet|codec_type=audio|stream_index=1|pts=929|pts_time=0.929000|dts=929|dts_time=0.929000|duration=46|duration_time=0.046000|size=108|pos=10505|flags=K_|data_hash=CRC32:8bf2b703 -packet|codec_type=video|stream_index=0|pts=934|pts_time=0.934000|dts=934|dts_time=0.934000|duration=33|duration_time=0.033000|size=55|pos=10630|flags=__|data_hash=CRC32:26064135 -packet|codec_type=video|stream_index=0|pts=968|pts_time=0.968000|dts=968|dts_time=0.968000|duration=33|duration_time=0.033000|size=14|pos=10705|flags=__|data_hash=CRC32:abb369c4 -packet|codec_type=audio|stream_index=1|pts=975|pts_time=0.975000|dts=975|dts_time=0.975000|duration=46|duration_time=0.046000|size=279|pos=10739|flags=K_|data_hash=CRC32:6bff85a8 -packet|codec_type=video|stream_index=0|pts=1001|pts_time=1.001000|dts=1001|dts_time=1.001000|duration=33|duration_time=0.033000|size=14|pos=11035|flags=__|data_hash=CRC32:1af77344 -packet|codec_type=audio|stream_index=1|pts=1022|pts_time=1.022000|dts=1022|dts_time=1.022000|duration=46|duration_time=0.046000|size=134|pos=11069|flags=K_|data_hash=CRC32:349e2a8c -packet|codec_type=video|stream_index=0|pts=1034|pts_time=1.034000|dts=1034|dts_time=1.034000|duration=33|duration_time=0.033000|size=58|pos=11220|flags=__|data_hash=CRC32:8b2e7991 -packet|codec_type=audio|stream_index=1|pts=1068|pts_time=1.068000|dts=1068|dts_time=1.068000|duration=46|duration_time=0.046000|size=162|pos=11298|flags=K_|data_hash=CRC32:f64effd2 -packet|codec_type=video|stream_index=0|pts=1068|pts_time=1.068000|dts=1068|dts_time=1.068000|duration=33|duration_time=0.033000|size=39|pos=11477|flags=__|data_hash=CRC32:0ae377c8 -packet|codec_type=video|stream_index=0|pts=1101|pts_time=1.101000|dts=1101|dts_time=1.101000|duration=33|duration_time=0.033000|size=48|pos=11536|flags=__|data_hash=CRC32:1bc6d22d -packet|codec_type=audio|stream_index=1|pts=1115|pts_time=1.115000|dts=1115|dts_time=1.115000|duration=46|duration_time=0.046000|size=46|pos=11604|flags=K_|data_hash=CRC32:3dfbc696 -packet|codec_type=video|stream_index=0|pts=1134|pts_time=1.134000|dts=1134|dts_time=1.134000|duration=33|duration_time=0.033000|size=319|pos=11667|flags=__|data_hash=CRC32:39d9a172 -packet|codec_type=audio|stream_index=1|pts=1161|pts_time=1.161000|dts=1161|dts_time=1.161000|duration=46|duration_time=0.046000|size=150|pos=12006|flags=K_|data_hash=CRC32:eec82a0f -packet|codec_type=video|stream_index=0|pts=1168|pts_time=1.168000|dts=1168|dts_time=1.168000|duration=33|duration_time=0.033000|size=204|pos=12173|flags=__|data_hash=CRC32:96683004 -packet|codec_type=video|stream_index=0|pts=1201|pts_time=1.201000|dts=1201|dts_time=1.201000|duration=33|duration_time=0.033000|size=240|pos=12397|flags=__|data_hash=CRC32:65f1defa -packet|codec_type=audio|stream_index=1|pts=1207|pts_time=1.207000|dts=1207|dts_time=1.207000|duration=46|duration_time=0.046000|size=427|pos=12657|flags=K_|data_hash=CRC32:e8361847 -packet|codec_type=video|stream_index=0|pts=1235|pts_time=1.235000|dts=1235|dts_time=1.235000|duration=33|duration_time=0.033000|size=305|pos=13101|flags=__|data_hash=CRC32:12e13d9c -packet|codec_type=audio|stream_index=1|pts=1254|pts_time=1.254000|dts=1254|dts_time=1.254000|duration=46|duration_time=0.046000|size=616|pos=13426|flags=K_|data_hash=CRC32:65e6a966 -packet|codec_type=video|stream_index=0|pts=1268|pts_time=1.268000|dts=1268|dts_time=1.268000|duration=33|duration_time=0.033000|size=217|pos=14059|flags=__|data_hash=CRC32:741596bf -packet|codec_type=audio|stream_index=1|pts=1300|pts_time=1.300000|dts=1300|dts_time=1.300000|duration=46|duration_time=0.046000|size=736|pos=14296|flags=K_|data_hash=CRC32:bf178137 -packet|codec_type=video|stream_index=0|pts=1301|pts_time=1.301000|dts=1301|dts_time=1.301000|duration=33|duration_time=0.033000|size=236|pos=15049|flags=__|data_hash=CRC32:e857a41f -packet|codec_type=video|stream_index=0|pts=1335|pts_time=1.335000|dts=1335|dts_time=1.335000|duration=33|duration_time=0.033000|size=222|pos=15305|flags=__|data_hash=CRC32:02e5c508 -packet|codec_type=audio|stream_index=1|pts=1347|pts_time=1.347000|dts=1347|dts_time=1.347000|duration=46|duration_time=0.046000|size=708|pos=15547|flags=K_|data_hash=CRC32:cd4df572 -packet|codec_type=video|stream_index=0|pts=1368|pts_time=1.368000|dts=1368|dts_time=1.368000|duration=33|duration_time=0.033000|size=1295|pos=16272|flags=K_|data_hash=CRC32:65d347c4 -packet|codec_type=audio|stream_index=1|pts=1393|pts_time=1.393000|dts=1393|dts_time=1.393000|duration=46|duration_time=0.046000|size=717|pos=17587|flags=K_|data_hash=CRC32:72de4551 -packet|codec_type=video|stream_index=0|pts=1401|pts_time=1.401000|dts=1401|dts_time=1.401000|duration=33|duration_time=0.033000|size=653|pos=18321|flags=__|data_hash=CRC32:b9f01826 -packet|codec_type=video|stream_index=0|pts=1435|pts_time=1.435000|dts=1435|dts_time=1.435000|duration=33|duration_time=0.033000|size=335|pos=18994|flags=__|data_hash=CRC32:9e2e9463 -packet|codec_type=audio|stream_index=1|pts=1440|pts_time=1.440000|dts=1440|dts_time=1.440000|duration=46|duration_time=0.046000|size=730|pos=19349|flags=K_|data_hash=CRC32:8f424fb7 -packet|codec_type=video|stream_index=0|pts=1468|pts_time=1.468000|dts=1468|dts_time=1.468000|duration=33|duration_time=0.033000|size=765|pos=20096|flags=__|data_hash=CRC32:09b3b571 -packet|codec_type=audio|stream_index=1|pts=1486|pts_time=1.486000|dts=1486|dts_time=1.486000|duration=46|duration_time=0.046000|size=756|pos=20881|flags=K_|data_hash=CRC32:4921e8da -packet|codec_type=video|stream_index=0|pts=1502|pts_time=1.502000|dts=1502|dts_time=1.502000|duration=33|duration_time=0.033000|size=213|pos=21654|flags=__|data_hash=CRC32:c7c9280a -packet|codec_type=audio|stream_index=1|pts=1533|pts_time=1.533000|dts=1533|dts_time=1.533000|duration=46|duration_time=0.046000|size=664|pos=21887|flags=K_|data_hash=CRC32:e093637e -packet|codec_type=video|stream_index=0|pts=1535|pts_time=1.535000|dts=1535|dts_time=1.535000|duration=33|duration_time=0.033000|size=464|pos=22568|flags=__|data_hash=CRC32:e555cff4 -packet|codec_type=video|stream_index=0|pts=1568|pts_time=1.568000|dts=1568|dts_time=1.568000|duration=33|duration_time=0.033000|size=561|pos=23052|flags=__|data_hash=CRC32:5e5d560b -packet|codec_type=audio|stream_index=1|pts=1579|pts_time=1.579000|dts=1579|dts_time=1.579000|duration=46|duration_time=0.046000|size=751|pos=23633|flags=K_|data_hash=CRC32:7d228f8d -packet|codec_type=video|stream_index=0|pts=1602|pts_time=1.602000|dts=1602|dts_time=1.602000|duration=33|duration_time=0.033000|size=876|pos=24401|flags=__|data_hash=CRC32:e92ee634 -packet|codec_type=audio|stream_index=1|pts=1625|pts_time=1.625000|dts=1625|dts_time=1.625000|duration=46|duration_time=0.046000|size=780|pos=25297|flags=K_|data_hash=CRC32:9b9cba9e -packet|codec_type=video|stream_index=0|pts=1635|pts_time=1.635000|dts=1635|dts_time=1.635000|duration=33|duration_time=0.033000|size=473|pos=26094|flags=__|data_hash=CRC32:4797e66e -packet|codec_type=video|stream_index=0|pts=1668|pts_time=1.668000|dts=1668|dts_time=1.668000|duration=33|duration_time=0.033000|size=272|pos=26587|flags=__|data_hash=CRC32:86c1281c -packet|codec_type=audio|stream_index=1|pts=1672|pts_time=1.672000|dts=1672|dts_time=1.672000|duration=46|duration_time=0.046000|size=404|pos=26879|flags=K_|data_hash=CRC32:89d51769 -packet|codec_type=video|stream_index=0|pts=1702|pts_time=1.702000|dts=1702|dts_time=1.702000|duration=33|duration_time=0.033000|size=281|pos=27300|flags=__|data_hash=CRC32:b5f22b1a -packet|codec_type=audio|stream_index=1|pts=1718|pts_time=1.718000|dts=1718|dts_time=1.718000|duration=46|duration_time=0.046000|size=326|pos=27601|flags=K_|data_hash=CRC32:3723e2b7 -packet|codec_type=video|stream_index=0|pts=1735|pts_time=1.735000|dts=1735|dts_time=1.735000|duration=33|duration_time=0.033000|size=315|pos=27944|flags=__|data_hash=CRC32:322931af -packet|codec_type=audio|stream_index=1|pts=1765|pts_time=1.765000|dts=1765|dts_time=1.765000|duration=46|duration_time=0.046000|size=77|pos=28279|flags=K_|data_hash=CRC32:181325ba -packet|codec_type=video|stream_index=0|pts=1768|pts_time=1.768000|dts=1768|dts_time=1.768000|duration=33|duration_time=0.033000|size=653|pos=28373|flags=__|data_hash=CRC32:53cc49de -packet|codec_type=video|stream_index=0|pts=1802|pts_time=1.802000|dts=1802|dts_time=1.802000|duration=33|duration_time=0.033000|size=228|pos=29046|flags=__|data_hash=CRC32:bb222de5 -packet|codec_type=audio|stream_index=1|pts=1811|pts_time=1.811000|dts=1811|dts_time=1.811000|duration=46|duration_time=0.046000|size=132|pos=29294|flags=K_|data_hash=CRC32:1bef55db -packet|codec_type=video|stream_index=0|pts=1835|pts_time=1.835000|dts=1835|dts_time=1.835000|duration=33|duration_time=0.033000|size=265|pos=29443|flags=__|data_hash=CRC32:d4f0d444 -packet|codec_type=audio|stream_index=1|pts=1858|pts_time=1.858000|dts=1858|dts_time=1.858000|duration=46|duration_time=0.046000|size=266|pos=29728|flags=K_|data_hash=CRC32:126ec6c3 -packet|codec_type=video|stream_index=0|pts=1869|pts_time=1.869000|dts=1869|dts_time=1.869000|duration=33|duration_time=0.033000|size=362|pos=30011|flags=__|data_hash=CRC32:a3399859 -packet|codec_type=video|stream_index=0|pts=1902|pts_time=1.902000|dts=1902|dts_time=1.902000|duration=33|duration_time=0.033000|size=362|pos=30393|flags=__|data_hash=CRC32:b4462dfc -packet|codec_type=audio|stream_index=1|pts=1904|pts_time=1.904000|dts=1904|dts_time=1.904000|duration=46|duration_time=0.046000|size=297|pos=30775|flags=K_|data_hash=CRC32:8a286293 -packet|codec_type=video|stream_index=0|pts=1935|pts_time=1.935000|dts=1935|dts_time=1.935000|duration=33|duration_time=0.033000|size=297|pos=31089|flags=__|data_hash=CRC32:ead314f3 -packet|codec_type=audio|stream_index=1|pts=1950|pts_time=1.950000|dts=1950|dts_time=1.950000|duration=46|duration_time=0.046000|size=9|pos=31406|flags=K_|data_hash=CRC32:3395d413 -packet|codec_type=video|stream_index=0|pts=1969|pts_time=1.969000|dts=1969|dts_time=1.969000|duration=33|duration_time=0.033000|size=395|pos=31432|flags=__|data_hash=CRC32:2d27c345 -packet|codec_type=audio|stream_index=1|pts=1997|pts_time=1.997000|dts=1997|dts_time=1.997000|duration=46|duration_time=0.046000|size=9|pos=31847|flags=K_|data_hash=CRC32:6b5dbb28 -packet|codec_type=video|stream_index=0|pts=2002|pts_time=2.002000|dts=2002|dts_time=2.002000|duration=33|duration_time=0.033000|size=149|pos=31873|flags=__|data_hash=CRC32:cbf3938c -packet|codec_type=video|stream_index=0|pts=2035|pts_time=2.035000|dts=2035|dts_time=2.035000|duration=33|duration_time=0.033000|size=141|pos=32042|flags=__|data_hash=CRC32:8b92a9de -packet|codec_type=audio|stream_index=1|pts=2043|pts_time=2.043000|dts=2043|dts_time=2.043000|duration=46|duration_time=0.046000|size=9|pos=32203|flags=K_|data_hash=CRC32:bbb61b93 -packet|codec_type=video|stream_index=0|pts=2069|pts_time=2.069000|dts=2069|dts_time=2.069000|duration=33|duration_time=0.033000|size=317|pos=32229|flags=__|data_hash=CRC32:5362eed3 -packet|codec_type=audio|stream_index=1|pts=2090|pts_time=2.090000|dts=2090|dts_time=2.090000|duration=46|duration_time=0.046000|size=9|pos=32566|flags=K_|data_hash=CRC32:bbb61b93 -packet|codec_type=video|stream_index=0|pts=2102|pts_time=2.102000|dts=2102|dts_time=2.102000|duration=33|duration_time=0.033000|size=170|pos=32592|flags=__|data_hash=CRC32:867c837a -packet|codec_type=video|stream_index=0|pts=2135|pts_time=2.135000|dts=2135|dts_time=2.135000|duration=33|duration_time=0.033000|size=443|pos=32782|flags=__|data_hash=CRC32:5bc93901 -packet|codec_type=audio|stream_index=1|pts=2136|pts_time=2.136000|dts=2136|dts_time=2.136000|duration=46|duration_time=0.046000|size=9|pos=33245|flags=K_|data_hash=CRC32:bbb61b93 -packet|codec_type=video|stream_index=0|pts=2169|pts_time=2.169000|dts=2169|dts_time=2.169000|duration=33|duration_time=0.033000|size=224|pos=33271|flags=__|data_hash=CRC32:8eddf111 -packet|codec_type=audio|stream_index=1|pts=2183|pts_time=2.183000|dts=2183|dts_time=2.183000|duration=46|duration_time=0.046000|size=9|pos=33515|flags=K_|data_hash=CRC32:bbb61b93 -packet|codec_type=video|stream_index=0|pts=2202|pts_time=2.202000|dts=2202|dts_time=2.202000|duration=33|duration_time=0.033000|size=472|pos=33541|flags=__|data_hash=CRC32:abe7ea6c -packet|codec_type=audio|stream_index=1|pts=2229|pts_time=2.229000|dts=2229|dts_time=2.229000|duration=46|duration_time=0.046000|size=9|pos=34033|flags=K_|data_hash=CRC32:bbb61b93 -packet|codec_type=video|stream_index=0|pts=2236|pts_time=2.236000|dts=2236|dts_time=2.236000|duration=33|duration_time=0.033000|size=188|pos=34059|flags=__|data_hash=CRC32:73b69b1a -packet|codec_type=video|stream_index=0|pts=2269|pts_time=2.269000|dts=2269|dts_time=2.269000|duration=33|duration_time=0.033000|size=302|pos=34267|flags=__|data_hash=CRC32:81ba5025 -packet|codec_type=audio|stream_index=1|pts=2276|pts_time=2.276000|dts=2276|dts_time=2.276000|duration=46|duration_time=0.046000|size=9|pos=34589|flags=K_|data_hash=CRC32:bbb61b93 -packet|codec_type=video|stream_index=0|pts=2302|pts_time=2.302000|dts=2302|dts_time=2.302000|duration=33|duration_time=0.033000|size=125|pos=34615|flags=__|data_hash=CRC32:16e31418 -packet|codec_type=audio|stream_index=1|pts=2322|pts_time=2.322000|dts=2322|dts_time=2.322000|duration=46|duration_time=0.046000|size=9|pos=34760|flags=K_|data_hash=CRC32:bbb61b93 -packet|codec_type=video|stream_index=0|pts=2336|pts_time=2.336000|dts=2336|dts_time=2.336000|duration=33|duration_time=0.033000|size=810|pos=34786|flags=__|data_hash=CRC32:409d7bc5 -packet|codec_type=audio|stream_index=1|pts=2368|pts_time=2.368000|dts=2368|dts_time=2.368000|duration=46|duration_time=0.046000|size=304|pos=35616|flags=K_|data_hash=CRC32:d7355e6f -packet|codec_type=video|stream_index=0|pts=2369|pts_time=2.369000|dts=2369|dts_time=2.369000|duration=33|duration_time=0.033000|size=158|pos=35937|flags=__|data_hash=CRC32:bb167cd2 -packet|codec_type=video|stream_index=0|pts=2402|pts_time=2.402000|dts=2402|dts_time=2.402000|duration=33|duration_time=0.033000|size=561|pos=36115|flags=__|data_hash=CRC32:582133cb -packet|codec_type=audio|stream_index=1|pts=2415|pts_time=2.415000|dts=2415|dts_time=2.415000|duration=46|duration_time=0.046000|size=683|pos=36696|flags=K_|data_hash=CRC32:0e95a3a0 -packet|codec_type=video|stream_index=0|pts=2436|pts_time=2.436000|dts=2436|dts_time=2.436000|duration=33|duration_time=0.033000|size=383|pos=37396|flags=__|data_hash=CRC32:a2c19b0b -packet|codec_type=audio|stream_index=1|pts=2461|pts_time=2.461000|dts=2461|dts_time=2.461000|duration=46|duration_time=0.046000|size=681|pos=37799|flags=K_|data_hash=CRC32:326a32e5 -packet|codec_type=video|stream_index=0|pts=2469|pts_time=2.469000|dts=2469|dts_time=2.469000|duration=33|duration_time=0.033000|size=218|pos=38497|flags=__|data_hash=CRC32:bda38cdd -packet|codec_type=video|stream_index=0|pts=2503|pts_time=2.503000|dts=2503|dts_time=2.503000|duration=33|duration_time=0.033000|size=270|pos=38735|flags=__|data_hash=CRC32:18a59365 -packet|codec_type=audio|stream_index=1|pts=2508|pts_time=2.508000|dts=2508|dts_time=2.508000|duration=46|duration_time=0.046000|size=663|pos=39025|flags=K_|data_hash=CRC32:04b4fe14 -packet|codec_type=video|stream_index=0|pts=2536|pts_time=2.536000|dts=2536|dts_time=2.536000|duration=33|duration_time=0.033000|size=182|pos=39705|flags=__|data_hash=CRC32:3f9da83b -packet|codec_type=audio|stream_index=1|pts=2554|pts_time=2.554000|dts=2554|dts_time=2.554000|duration=46|duration_time=0.046000|size=671|pos=39907|flags=K_|data_hash=CRC32:b8c62ab4 -packet|codec_type=video|stream_index=0|pts=2569|pts_time=2.569000|dts=2569|dts_time=2.569000|duration=33|duration_time=0.033000|size=1063|pos=40595|flags=K_|data_hash=CRC32:89a9f14f -packet|codec_type=audio|stream_index=1|pts=2601|pts_time=2.601000|dts=2601|dts_time=2.601000|duration=46|duration_time=0.046000|size=682|pos=41678|flags=K_|data_hash=CRC32:e95e8d23 -packet|codec_type=video|stream_index=0|pts=2603|pts_time=2.603000|dts=2603|dts_time=2.603000|duration=33|duration_time=0.033000|size=3687|pos=42377|flags=__|data_hash=CRC32:e9d6144b -packet|codec_type=video|stream_index=0|pts=2636|pts_time=2.636000|dts=2636|dts_time=2.636000|duration=33|duration_time=0.033000|size=280|pos=46084|flags=__|data_hash=CRC32:520c7765 -packet|codec_type=audio|stream_index=1|pts=2647|pts_time=2.647000|dts=2647|dts_time=2.647000|duration=46|duration_time=0.046000|size=698|pos=46384|flags=K_|data_hash=CRC32:0631a240 -packet|codec_type=video|stream_index=0|pts=2669|pts_time=2.669000|dts=2669|dts_time=2.669000|duration=33|duration_time=0.033000|size=475|pos=47099|flags=__|data_hash=CRC32:e1a7746b -packet|codec_type=audio|stream_index=1|pts=2694|pts_time=2.694000|dts=2694|dts_time=2.694000|duration=46|duration_time=0.046000|size=697|pos=47594|flags=K_|data_hash=CRC32:0e9feb04 -packet|codec_type=video|stream_index=0|pts=2703|pts_time=2.703000|dts=2703|dts_time=2.703000|duration=33|duration_time=0.033000|size=488|pos=48308|flags=__|data_hash=CRC32:ba916d5f -packet|codec_type=video|stream_index=0|pts=2736|pts_time=2.736000|dts=2736|dts_time=2.736000|duration=33|duration_time=0.033000|size=532|pos=48816|flags=__|data_hash=CRC32:bb384278 -packet|codec_type=audio|stream_index=1|pts=2740|pts_time=2.740000|dts=2740|dts_time=2.740000|duration=46|duration_time=0.046000|size=674|pos=49368|flags=K_|data_hash=CRC32:9859c9fe -packet|codec_type=video|stream_index=0|pts=2769|pts_time=2.769000|dts=2769|dts_time=2.769000|duration=33|duration_time=0.033000|size=590|pos=50059|flags=__|data_hash=CRC32:55a84515 -packet|codec_type=audio|stream_index=1|pts=2786|pts_time=2.786000|dts=2786|dts_time=2.786000|duration=46|duration_time=0.046000|size=651|pos=50669|flags=K_|data_hash=CRC32:642d943c -packet|codec_type=video|stream_index=0|pts=2803|pts_time=2.803000|dts=2803|dts_time=2.803000|duration=33|duration_time=0.033000|size=683|pos=51337|flags=__|data_hash=CRC32:ed48440d -packet|codec_type=audio|stream_index=1|pts=2833|pts_time=2.833000|dts=2833|dts_time=2.833000|duration=46|duration_time=0.046000|size=672|pos=52040|flags=K_|data_hash=CRC32:f2af0db0 -packet|codec_type=video|stream_index=0|pts=2836|pts_time=2.836000|dts=2836|dts_time=2.836000|duration=33|duration_time=0.033000|size=836|pos=52729|flags=__|data_hash=CRC32:d99a6f79 -packet|codec_type=video|stream_index=0|pts=2870|pts_time=2.870000|dts=2870|dts_time=2.870000|duration=33|duration_time=0.033000|size=676|pos=53585|flags=__|data_hash=CRC32:ed426283 -packet|codec_type=audio|stream_index=1|pts=2879|pts_time=2.879000|dts=2879|dts_time=2.879000|duration=46|duration_time=0.046000|size=665|pos=54281|flags=K_|data_hash=CRC32:d6e66995 -packet|codec_type=video|stream_index=0|pts=2903|pts_time=2.903000|dts=2903|dts_time=2.903000|duration=33|duration_time=0.033000|size=731|pos=54963|flags=__|data_hash=CRC32:9df509dc -packet|codec_type=audio|stream_index=1|pts=2926|pts_time=2.926000|dts=2926|dts_time=2.926000|duration=46|duration_time=0.046000|size=734|pos=55714|flags=K_|data_hash=CRC32:2e13e9fe -packet|codec_type=video|stream_index=0|pts=2936|pts_time=2.936000|dts=2936|dts_time=2.936000|duration=33|duration_time=0.033000|size=839|pos=56465|flags=__|data_hash=CRC32:dc12a67f -packet|codec_type=video|stream_index=0|pts=2970|pts_time=2.970000|dts=2970|dts_time=2.970000|duration=33|duration_time=0.033000|size=787|pos=57324|flags=__|data_hash=CRC32:db72a014 -packet|codec_type=audio|stream_index=1|pts=2972|pts_time=2.972000|dts=2972|dts_time=2.972000|duration=46|duration_time=0.046000|size=732|pos=58131|flags=K_|data_hash=CRC32:9cfb9b77 -packet|codec_type=video|stream_index=0|pts=3003|pts_time=3.003000|dts=3003|dts_time=3.003000|duration=33|duration_time=0.033000|size=1039|pos=58880|flags=__|data_hash=CRC32:bf96f792 -packet|codec_type=audio|stream_index=1|pts=3019|pts_time=3.019000|dts=3019|dts_time=3.019000|duration=46|duration_time=0.046000|size=742|pos=59939|flags=K_|data_hash=CRC32:51cb6568 -packet|codec_type=video|stream_index=0|pts=3036|pts_time=3.036000|dts=3036|dts_time=3.036000|duration=33|duration_time=0.033000|size=851|pos=60698|flags=__|data_hash=CRC32:45237f01 -packet|codec_type=audio|stream_index=1|pts=3065|pts_time=3.065000|dts=3065|dts_time=3.065000|duration=46|duration_time=0.046000|size=748|pos=61569|flags=K_|data_hash=CRC32:5c676c58 -packet|codec_type=video|stream_index=0|pts=3070|pts_time=3.070000|dts=3070|dts_time=3.070000|duration=33|duration_time=0.033000|size=928|pos=62334|flags=__|data_hash=CRC32:cef81f2c -packet|codec_type=video|stream_index=0|pts=3103|pts_time=3.103000|dts=3103|dts_time=3.103000|duration=33|duration_time=0.033000|size=840|pos=63282|flags=__|data_hash=CRC32:7ae6a4a0 -packet|codec_type=audio|stream_index=1|pts=3111|pts_time=3.111000|dts=3111|dts_time=3.111000|duration=46|duration_time=0.046000|size=671|pos=64142|flags=K_|data_hash=CRC32:c4c27684 -packet|codec_type=video|stream_index=0|pts=3136|pts_time=3.136000|dts=3136|dts_time=3.136000|duration=33|duration_time=0.033000|size=889|pos=64830|flags=__|data_hash=CRC32:70b13ba7 -packet|codec_type=audio|stream_index=1|pts=3158|pts_time=3.158000|dts=3158|dts_time=3.158000|duration=46|duration_time=0.046000|size=645|pos=65739|flags=K_|data_hash=CRC32:1b7b9a99 -packet|codec_type=video|stream_index=0|pts=3170|pts_time=3.170000|dts=3170|dts_time=3.170000|duration=33|duration_time=0.033000|size=789|pos=66401|flags=__|data_hash=CRC32:6ffae70e -packet|codec_type=video|stream_index=0|pts=3203|pts_time=3.203000|dts=3203|dts_time=3.203000|duration=33|duration_time=0.033000|size=1037|pos=67210|flags=__|data_hash=CRC32:acb72f8a -packet|codec_type=audio|stream_index=1|pts=3204|pts_time=3.204000|dts=3204|dts_time=3.204000|duration=46|duration_time=0.046000|size=724|pos=68267|flags=K_|data_hash=CRC32:feb7c4f3 -packet|codec_type=video|stream_index=0|pts=3237|pts_time=3.237000|dts=3237|dts_time=3.237000|duration=33|duration_time=0.033000|size=1201|pos=69008|flags=__|data_hash=CRC32:0ac77ab1 -packet|codec_type=audio|stream_index=1|pts=3251|pts_time=3.251000|dts=3251|dts_time=3.251000|duration=46|duration_time=0.046000|size=757|pos=70229|flags=K_|data_hash=CRC32:28d27dd5 -packet|codec_type=video|stream_index=0|pts=3270|pts_time=3.270000|dts=3270|dts_time=3.270000|duration=33|duration_time=0.033000|size=934|pos=71003|flags=__|data_hash=CRC32:dd16f432 -packet|codec_type=audio|stream_index=1|pts=3297|pts_time=3.297000|dts=3297|dts_time=3.297000|duration=46|duration_time=0.046000|size=710|pos=71957|flags=K_|data_hash=CRC32:fb16456d -packet|codec_type=video|stream_index=0|pts=3303|pts_time=3.303000|dts=3303|dts_time=3.303000|duration=33|duration_time=0.033000|size=1028|pos=72684|flags=__|data_hash=CRC32:d4cf8920 -packet|codec_type=video|stream_index=0|pts=3337|pts_time=3.337000|dts=3337|dts_time=3.337000|duration=33|duration_time=0.033000|size=1007|pos=73732|flags=__|data_hash=CRC32:4dfc2133 -packet|codec_type=audio|stream_index=1|pts=3344|pts_time=3.344000|dts=3344|dts_time=3.344000|duration=46|duration_time=0.046000|size=705|pos=74759|flags=K_|data_hash=CRC32:249bd165 -packet|codec_type=video|stream_index=0|pts=3370|pts_time=3.370000|dts=3370|dts_time=3.370000|duration=33|duration_time=0.033000|size=944|pos=75481|flags=__|data_hash=CRC32:cf0ee6e5 -packet|codec_type=audio|stream_index=1|pts=3390|pts_time=3.390000|dts=3390|dts_time=3.390000|duration=46|duration_time=0.046000|size=693|pos=76445|flags=K_|data_hash=CRC32:907c82d7 -packet|codec_type=video|stream_index=0|pts=3403|pts_time=3.403000|dts=3403|dts_time=3.403000|duration=33|duration_time=0.033000|size=1121|pos=77155|flags=__|data_hash=CRC32:f4a2ef4d -packet|codec_type=audio|stream_index=1|pts=3437|pts_time=3.437000|dts=3437|dts_time=3.437000|duration=46|duration_time=0.046000|size=683|pos=78296|flags=K_|data_hash=CRC32:25f0e52b -packet|codec_type=video|stream_index=0|pts=3437|pts_time=3.437000|dts=3437|dts_time=3.437000|duration=33|duration_time=0.033000|size=1321|pos=78996|flags=__|data_hash=CRC32:890f59cd -packet|codec_type=video|stream_index=0|pts=3470|pts_time=3.470000|dts=3470|dts_time=3.470000|duration=33|duration_time=0.033000|size=1229|pos=80337|flags=__|data_hash=CRC32:7c53b1c5 -packet|codec_type=audio|stream_index=1|pts=3483|pts_time=3.483000|dts=3483|dts_time=3.483000|duration=46|duration_time=0.046000|size=668|pos=81586|flags=K_|data_hash=CRC32:c848f398 -packet|codec_type=video|stream_index=0|pts=3504|pts_time=3.504000|dts=3504|dts_time=3.504000|duration=33|duration_time=0.033000|size=1166|pos=82271|flags=__|data_hash=CRC32:237539fc -packet|codec_type=audio|stream_index=1|pts=3529|pts_time=3.529000|dts=3529|dts_time=3.529000|duration=46|duration_time=0.046000|size=624|pos=83457|flags=K_|data_hash=CRC32:5d81d294 -packet|codec_type=video|stream_index=0|pts=3537|pts_time=3.537000|dts=3537|dts_time=3.537000|duration=33|duration_time=0.033000|size=1055|pos=84098|flags=__|data_hash=CRC32:2d22b0e9 -packet|codec_type=video|stream_index=0|pts=3570|pts_time=3.570000|dts=3570|dts_time=3.570000|duration=33|duration_time=0.033000|size=947|pos=85173|flags=__|data_hash=CRC32:1003bc18 -packet|codec_type=audio|stream_index=1|pts=3576|pts_time=3.576000|dts=3576|dts_time=3.576000|duration=46|duration_time=0.046000|size=570|pos=86140|flags=K_|data_hash=CRC32:41da9b98 -packet|codec_type=video|stream_index=0|pts=3604|pts_time=3.604000|dts=3604|dts_time=3.604000|duration=33|duration_time=0.033000|size=1117|pos=86727|flags=__|data_hash=CRC32:ea91a8bf -packet|codec_type=audio|stream_index=1|pts=3622|pts_time=3.622000|dts=3622|dts_time=3.622000|duration=46|duration_time=0.046000|size=579|pos=87864|flags=K_|data_hash=CRC32:b1e12639 -packet|codec_type=video|stream_index=0|pts=3637|pts_time=3.637000|dts=3637|dts_time=3.637000|duration=33|duration_time=0.033000|size=1397|pos=88460|flags=__|data_hash=CRC32:f2bdfea7 -packet|codec_type=audio|stream_index=1|pts=3669|pts_time=3.669000|dts=3669|dts_time=3.669000|duration=46|duration_time=0.046000|size=558|pos=89877|flags=K_|data_hash=CRC32:095b218c -packet|codec_type=video|stream_index=0|pts=3670|pts_time=3.670000|dts=3670|dts_time=3.670000|duration=33|duration_time=0.033000|size=1097|pos=90452|flags=__|data_hash=CRC32:be8cf516 -packet|codec_type=video|stream_index=0|pts=3704|pts_time=3.704000|dts=3704|dts_time=3.704000|duration=33|duration_time=0.033000|size=1207|pos=91569|flags=__|data_hash=CRC32:176a8fe9 -packet|codec_type=audio|stream_index=1|pts=3715|pts_time=3.715000|dts=3715|dts_time=3.715000|duration=46|duration_time=0.046000|size=510|pos=92796|flags=K_|data_hash=CRC32:8cea9dca -packet|codec_type=video|stream_index=0|pts=3737|pts_time=3.737000|dts=3737|dts_time=3.737000|duration=33|duration_time=0.033000|size=1109|pos=93323|flags=__|data_hash=CRC32:615bab01 -packet|codec_type=audio|stream_index=1|pts=3762|pts_time=3.762000|dts=3762|dts_time=3.762000|duration=46|duration_time=0.046000|size=518|pos=94452|flags=K_|data_hash=CRC32:600293cc -packet|codec_type=video|stream_index=0|pts=3770|pts_time=3.770000|dts=3770|dts_time=3.770000|duration=33|duration_time=0.033000|size=994|pos=94987|flags=__|data_hash=CRC32:db090b40 -packet|codec_type=video|stream_index=0|pts=3804|pts_time=3.804000|dts=3804|dts_time=3.804000|duration=33|duration_time=0.033000|size=1144|pos=96001|flags=__|data_hash=CRC32:4966c524 -packet|codec_type=audio|stream_index=1|pts=3808|pts_time=3.808000|dts=3808|dts_time=3.808000|duration=46|duration_time=0.046000|size=481|pos=97165|flags=K_|data_hash=CRC32:e53ca4a3 -packet|codec_type=video|stream_index=0|pts=3837|pts_time=3.837000|dts=3837|dts_time=3.837000|duration=33|duration_time=0.033000|size=1409|pos=97663|flags=__|data_hash=CRC32:5561cdad -packet|codec_type=audio|stream_index=1|pts=3855|pts_time=3.855000|dts=3855|dts_time=3.855000|duration=46|duration_time=0.046000|size=443|pos=99092|flags=K_|data_hash=CRC32:14937ac1 -packet|codec_type=video|stream_index=0|pts=3871|pts_time=3.871000|dts=3871|dts_time=3.871000|duration=33|duration_time=0.033000|size=1205|pos=99552|flags=__|data_hash=CRC32:93f9dbe0 -packet|codec_type=audio|stream_index=1|pts=3901|pts_time=3.901000|dts=3901|dts_time=3.901000|duration=46|duration_time=0.046000|size=413|pos=100777|flags=K_|data_hash=CRC32:4fea79a1 -packet|codec_type=video|stream_index=0|pts=3904|pts_time=3.904000|dts=3904|dts_time=3.904000|duration=33|duration_time=0.033000|size=1159|pos=101207|flags=__|data_hash=CRC32:8a7dd1ca -packet|codec_type=video|stream_index=0|pts=3937|pts_time=3.937000|dts=3937|dts_time=3.937000|duration=33|duration_time=0.033000|size=1207|pos=102386|flags=__|data_hash=CRC32:9c351265 -packet|codec_type=audio|stream_index=1|pts=3947|pts_time=3.947000|dts=3947|dts_time=3.947000|duration=46|duration_time=0.046000|size=398|pos=103613|flags=K_|data_hash=CRC32:0777a82b -packet|codec_type=video|stream_index=0|pts=3971|pts_time=3.971000|dts=3971|dts_time=3.971000|duration=33|duration_time=0.033000|size=1084|pos=104028|flags=__|data_hash=CRC32:3b4222c7 -packet|codec_type=audio|stream_index=1|pts=3994|pts_time=3.994000|dts=3994|dts_time=3.994000|duration=46|duration_time=0.046000|size=377|pos=105132|flags=K_|data_hash=CRC32:8662b58a -packet|codec_type=video|stream_index=0|pts=4004|pts_time=4.004000|dts=4004|dts_time=4.004000|duration=33|duration_time=0.033000|size=1539|pos=105526|flags=__|data_hash=CRC32:cf253620 -packet|codec_type=video|stream_index=0|pts=4037|pts_time=4.037000|dts=4037|dts_time=4.037000|duration=33|duration_time=0.033000|size=1409|pos=107085|flags=__|data_hash=CRC32:01f30787 -packet|codec_type=audio|stream_index=1|pts=4040|pts_time=4.040000|dts=4040|dts_time=4.040000|duration=46|duration_time=0.046000|size=364|pos=108514|flags=K_|data_hash=CRC32:f73e6c88 -packet|codec_type=video|stream_index=0|pts=4071|pts_time=4.071000|dts=4071|dts_time=4.071000|duration=33|duration_time=0.033000|size=1275|pos=108895|flags=__|data_hash=CRC32:d7c1cfe1 -packet|codec_type=audio|stream_index=1|pts=4087|pts_time=4.087000|dts=4087|dts_time=4.087000|duration=46|duration_time=0.046000|size=374|pos=110190|flags=K_|data_hash=CRC32:c41f57c7 -packet|codec_type=video|stream_index=0|pts=4104|pts_time=4.104000|dts=4104|dts_time=4.104000|duration=33|duration_time=0.033000|size=1317|pos=110581|flags=__|data_hash=CRC32:685138ef -packet|codec_type=audio|stream_index=1|pts=4133|pts_time=4.133000|dts=4133|dts_time=4.133000|duration=46|duration_time=0.046000|size=355|pos=111918|flags=K_|data_hash=CRC32:7a5e82a8 -packet|codec_type=video|stream_index=0|pts=4137|pts_time=4.137000|dts=4137|dts_time=4.137000|duration=33|duration_time=0.033000|size=1146|pos=112290|flags=__|data_hash=CRC32:48ce008d -packet|codec_type=video|stream_index=0|pts=4171|pts_time=4.171000|dts=4171|dts_time=4.171000|duration=33|duration_time=0.033000|size=1166|pos=113456|flags=__|data_hash=CRC32:f12da76b -packet|codec_type=audio|stream_index=1|pts=4180|pts_time=4.180000|dts=4180|dts_time=4.180000|duration=46|duration_time=0.046000|size=341|pos=114642|flags=K_|data_hash=CRC32:ea126e98 -packet|codec_type=video|stream_index=0|pts=4204|pts_time=4.204000|dts=4204|dts_time=4.204000|duration=33|duration_time=0.033000|size=1272|pos=115000|flags=__|data_hash=CRC32:31e617c7 -packet|codec_type=audio|stream_index=1|pts=4226|pts_time=4.226000|dts=4226|dts_time=4.226000|duration=46|duration_time=0.046000|size=364|pos=116292|flags=K_|data_hash=CRC32:6d84c4a8 -packet|codec_type=video|stream_index=0|pts=4238|pts_time=4.238000|dts=4238|dts_time=4.238000|duration=33|duration_time=0.033000|size=1550|pos=116673|flags=__|data_hash=CRC32:50d17465 -packet|codec_type=video|stream_index=0|pts=4271|pts_time=4.271000|dts=4271|dts_time=4.271000|duration=33|duration_time=0.033000|size=1353|pos=118243|flags=__|data_hash=CRC32:af8d072c -packet|codec_type=audio|stream_index=1|pts=4272|pts_time=4.272000|dts=4272|dts_time=4.272000|duration=46|duration_time=0.046000|size=350|pos=119616|flags=K_|data_hash=CRC32:c27e7ecc -packet|codec_type=video|stream_index=0|pts=4304|pts_time=4.304000|dts=4304|dts_time=4.304000|duration=33|duration_time=0.033000|size=1251|pos=119983|flags=__|data_hash=CRC32:271dcd86 -packet|codec_type=audio|stream_index=1|pts=4319|pts_time=4.319000|dts=4319|dts_time=4.319000|duration=46|duration_time=0.046000|size=356|pos=121254|flags=K_|data_hash=CRC32:6d111a73 -packet|codec_type=video|stream_index=0|pts=4338|pts_time=4.338000|dts=4338|dts_time=4.338000|duration=33|duration_time=0.033000|size=1339|pos=121627|flags=__|data_hash=CRC32:01aa658e -packet|codec_type=audio|stream_index=1|pts=4365|pts_time=4.365000|dts=4365|dts_time=4.365000|duration=46|duration_time=0.046000|size=365|pos=122986|flags=K_|data_hash=CRC32:e24aa34c -packet|codec_type=video|stream_index=0|pts=4371|pts_time=4.371000|dts=4371|dts_time=4.371000|duration=33|duration_time=0.033000|size=1216|pos=123368|flags=__|data_hash=CRC32:bee7821f -packet|codec_type=video|stream_index=0|pts=4404|pts_time=4.404000|dts=4404|dts_time=4.404000|duration=33|duration_time=0.033000|size=1222|pos=124604|flags=__|data_hash=CRC32:2bd2754e -packet|codec_type=audio|stream_index=1|pts=4412|pts_time=4.412000|dts=4412|dts_time=4.412000|duration=46|duration_time=0.046000|size=352|pos=125846|flags=K_|data_hash=CRC32:fc970370 -packet|codec_type=video|stream_index=0|pts=4438|pts_time=4.438000|dts=4438|dts_time=4.438000|duration=33|duration_time=0.033000|size=1665|pos=126215|flags=__|data_hash=CRC32:a08b2e57 -packet|codec_type=audio|stream_index=1|pts=4458|pts_time=4.458000|dts=4458|dts_time=4.458000|duration=46|duration_time=0.046000|size=374|pos=127900|flags=K_|data_hash=CRC32:fa07f96b -packet|codec_type=video|stream_index=0|pts=4471|pts_time=4.471000|dts=4471|dts_time=4.471000|duration=33|duration_time=0.033000|size=1372|pos=128291|flags=__|data_hash=CRC32:7ba310fc -packet|codec_type=audio|stream_index=1|pts=4505|pts_time=4.505000|dts=4505|dts_time=4.505000|duration=46|duration_time=0.046000|size=375|pos=129683|flags=K_|data_hash=CRC32:912ec2a1 -packet|codec_type=video|stream_index=0|pts=4505|pts_time=4.505000|dts=4505|dts_time=4.505000|duration=33|duration_time=0.033000|size=1611|pos=130075|flags=__|data_hash=CRC32:894697a0 -packet|codec_type=video|stream_index=0|pts=4538|pts_time=4.538000|dts=4538|dts_time=4.538000|duration=33|duration_time=0.033000|size=7010|pos=131706|flags=K_|data_hash=CRC32:e74f1b93 -packet|codec_type=audio|stream_index=1|pts=4551|pts_time=4.551000|dts=4551|dts_time=4.551000|duration=46|duration_time=0.046000|size=375|pos=138736|flags=K_|data_hash=CRC32:9049bbe0 -packet|codec_type=video|stream_index=0|pts=4571|pts_time=4.571000|dts=4571|dts_time=4.571000|duration=33|duration_time=0.033000|size=549|pos=139128|flags=__|data_hash=CRC32:bea67fa5 -packet|codec_type=audio|stream_index=1|pts=4598|pts_time=4.598000|dts=4598|dts_time=4.598000|duration=46|duration_time=0.046000|size=376|pos=139697|flags=K_|data_hash=CRC32:cf9362b3 -packet|codec_type=video|stream_index=0|pts=4605|pts_time=4.605000|dts=4605|dts_time=4.605000|duration=33|duration_time=0.033000|size=1021|pos=140090|flags=__|data_hash=CRC32:93ace02c -packet|codec_type=video|stream_index=0|pts=4638|pts_time=4.638000|dts=4638|dts_time=4.638000|duration=33|duration_time=0.033000|size=1281|pos=141131|flags=__|data_hash=CRC32:24070179 -packet|codec_type=audio|stream_index=1|pts=4644|pts_time=4.644000|dts=4644|dts_time=4.644000|duration=46|duration_time=0.046000|size=372|pos=142432|flags=K_|data_hash=CRC32:f7372f4c -packet|codec_type=video|stream_index=0|pts=4671|pts_time=4.671000|dts=4671|dts_time=4.671000|duration=33|duration_time=0.033000|size=1267|pos=142821|flags=__|data_hash=CRC32:7cfd6aa6 -packet|codec_type=audio|stream_index=1|pts=4690|pts_time=4.690000|dts=4690|dts_time=4.690000|duration=46|duration_time=0.046000|size=371|pos=144108|flags=K_|data_hash=CRC32:b244704d -packet|codec_type=video|stream_index=0|pts=4705|pts_time=4.705000|dts=4705|dts_time=4.705000|duration=33|duration_time=0.033000|size=1140|pos=144496|flags=__|data_hash=CRC32:eccfa0f7 -packet|codec_type=audio|stream_index=1|pts=4737|pts_time=4.737000|dts=4737|dts_time=4.737000|duration=46|duration_time=0.046000|size=365|pos=145656|flags=K_|data_hash=CRC32:834bb209 -packet|codec_type=video|stream_index=0|pts=4738|pts_time=4.738000|dts=4738|dts_time=4.738000|duration=33|duration_time=0.033000|size=1289|pos=146038|flags=__|data_hash=CRC32:4669d638 -packet|codec_type=video|stream_index=0|pts=4771|pts_time=4.771000|dts=4771|dts_time=4.771000|duration=33|duration_time=0.033000|size=1127|pos=147347|flags=__|data_hash=CRC32:e52c7abd -packet|codec_type=audio|stream_index=1|pts=4783|pts_time=4.783000|dts=4783|dts_time=4.783000|duration=46|duration_time=0.046000|size=385|pos=148494|flags=K_|data_hash=CRC32:e61dc477 -packet|codec_type=video|stream_index=0|pts=4805|pts_time=4.805000|dts=4805|dts_time=4.805000|duration=33|duration_time=0.033000|size=1196|pos=148896|flags=__|data_hash=CRC32:5a318942 -packet|codec_type=audio|stream_index=1|pts=4830|pts_time=4.830000|dts=4830|dts_time=4.830000|duration=46|duration_time=0.046000|size=362|pos=150112|flags=K_|data_hash=CRC32:8fee051a -packet|codec_type=video|stream_index=0|pts=4838|pts_time=4.838000|dts=4838|dts_time=4.838000|duration=33|duration_time=0.033000|size=1520|pos=150491|flags=__|data_hash=CRC32:2418eb0f -packet|codec_type=video|stream_index=0|pts=4872|pts_time=4.872000|dts=4872|dts_time=4.872000|duration=33|duration_time=0.033000|size=1370|pos=152031|flags=__|data_hash=CRC32:79ca0732 -packet|codec_type=audio|stream_index=1|pts=4876|pts_time=4.876000|dts=4876|dts_time=4.876000|duration=46|duration_time=0.046000|size=370|pos=153421|flags=K_|data_hash=CRC32:1720582c -packet|codec_type=video|stream_index=0|pts=4905|pts_time=4.905000|dts=4905|dts_time=4.905000|duration=33|duration_time=0.033000|size=1232|pos=153808|flags=__|data_hash=CRC32:32295018 -packet|codec_type=audio|stream_index=1|pts=4923|pts_time=4.923000|dts=4923|dts_time=4.923000|duration=46|duration_time=0.046000|size=369|pos=155060|flags=K_|data_hash=CRC32:6b668e5b -packet|codec_type=video|stream_index=0|pts=4938|pts_time=4.938000|dts=4938|dts_time=4.938000|duration=33|duration_time=0.033000|size=1159|pos=155446|flags=__|data_hash=CRC32:45fc12f2 -packet|codec_type=audio|stream_index=1|pts=4969|pts_time=4.969000|dts=4969|dts_time=4.969000|duration=46|duration_time=0.046000|size=341|pos=156625|flags=K_|data_hash=CRC32:4d4741d6 -packet|codec_type=video|stream_index=0|pts=4972|pts_time=4.972000|dts=4972|dts_time=4.972000|duration=33|duration_time=0.033000|size=1183|pos=156983|flags=__|data_hash=CRC32:10f40093 -packet|codec_type=video|stream_index=0|pts=5005|pts_time=5.005000|dts=5005|dts_time=5.005000|duration=33|duration_time=0.033000|size=1469|pos=158186|flags=__|data_hash=CRC32:43a4815e -packet|codec_type=audio|stream_index=1|pts=5016|pts_time=5.016000|dts=5016|dts_time=5.016000|duration=46|duration_time=0.046000|size=351|pos=159675|flags=K_|data_hash=CRC32:82bf6546 -packet|codec_type=video|stream_index=0|pts=5038|pts_time=5.038000|dts=5038|dts_time=5.038000|duration=33|duration_time=0.033000|size=1468|pos=160043|flags=__|data_hash=CRC32:e8c78f03 -packet|codec_type=audio|stream_index=1|pts=5062|pts_time=5.062000|dts=5062|dts_time=5.062000|duration=46|duration_time=0.046000|size=365|pos=161531|flags=K_|data_hash=CRC32:1299be30 -packet|codec_type=video|stream_index=0|pts=5072|pts_time=5.072000|dts=5072|dts_time=5.072000|duration=33|duration_time=0.033000|size=1355|pos=161913|flags=__|data_hash=CRC32:044621ed -packet|codec_type=video|stream_index=0|pts=5105|pts_time=5.105000|dts=5105|dts_time=5.105000|duration=33|duration_time=0.033000|size=1303|pos=163288|flags=__|data_hash=CRC32:3403397b -packet|codec_type=audio|stream_index=1|pts=5108|pts_time=5.108000|dts=5108|dts_time=5.108000|duration=46|duration_time=0.046000|size=358|pos=164611|flags=K_|data_hash=CRC32:ee1a432d -packet|codec_type=video|stream_index=0|pts=5138|pts_time=5.138000|dts=5138|dts_time=5.138000|duration=33|duration_time=0.033000|size=1316|pos=164986|flags=__|data_hash=CRC32:7021310e -packet|codec_type=audio|stream_index=1|pts=5155|pts_time=5.155000|dts=5155|dts_time=5.155000|duration=46|duration_time=0.046000|size=373|pos=166322|flags=K_|data_hash=CRC32:f25887f4 -packet|codec_type=video|stream_index=0|pts=5172|pts_time=5.172000|dts=5172|dts_time=5.172000|duration=33|duration_time=0.033000|size=1196|pos=166712|flags=__|data_hash=CRC32:d8492897 -packet|codec_type=audio|stream_index=1|pts=5201|pts_time=5.201000|dts=5201|dts_time=5.201000|duration=46|duration_time=0.046000|size=367|pos=167928|flags=K_|data_hash=CRC32:c30e6c9f -packet|codec_type=video|stream_index=0|pts=5205|pts_time=5.205000|dts=5205|dts_time=5.205000|duration=33|duration_time=0.033000|size=1283|pos=168312|flags=__|data_hash=CRC32:c9058bba -packet|codec_type=video|stream_index=0|pts=5239|pts_time=5.239000|dts=5239|dts_time=5.239000|duration=33|duration_time=0.033000|size=1489|pos=169615|flags=__|data_hash=CRC32:0e5dadc6 -packet|codec_type=audio|stream_index=1|pts=5248|pts_time=5.248000|dts=5248|dts_time=5.248000|duration=46|duration_time=0.046000|size=364|pos=171124|flags=K_|data_hash=CRC32:74db7811 -packet|codec_type=video|stream_index=0|pts=5272|pts_time=5.272000|dts=5272|dts_time=5.272000|duration=33|duration_time=0.033000|size=1507|pos=171505|flags=__|data_hash=CRC32:1e37a39f -packet|codec_type=audio|stream_index=1|pts=5294|pts_time=5.294000|dts=5294|dts_time=5.294000|duration=46|duration_time=0.046000|size=346|pos=173032|flags=K_|data_hash=CRC32:3386dd10 -packet|codec_type=video|stream_index=0|pts=5305|pts_time=5.305000|dts=5305|dts_time=5.305000|duration=33|duration_time=0.033000|size=1237|pos=173395|flags=__|data_hash=CRC32:d8f772ae -packet|codec_type=video|stream_index=0|pts=5339|pts_time=5.339000|dts=5339|dts_time=5.339000|duration=33|duration_time=0.033000|size=1217|pos=174652|flags=__|data_hash=CRC32:7caabc71 -packet|codec_type=audio|stream_index=1|pts=5341|pts_time=5.341000|dts=5341|dts_time=5.341000|duration=46|duration_time=0.046000|size=362|pos=175889|flags=K_|data_hash=CRC32:b4975396 -packet|codec_type=video|stream_index=0|pts=5372|pts_time=5.372000|dts=5372|dts_time=5.372000|duration=33|duration_time=0.033000|size=1224|pos=176268|flags=__|data_hash=CRC32:fbca6068 -packet|codec_type=audio|stream_index=1|pts=5387|pts_time=5.387000|dts=5387|dts_time=5.387000|duration=46|duration_time=0.046000|size=360|pos=177512|flags=K_|data_hash=CRC32:f639adaf -packet|codec_type=video|stream_index=0|pts=5405|pts_time=5.405000|dts=5405|dts_time=5.405000|duration=33|duration_time=0.033000|size=1554|pos=177889|flags=__|data_hash=CRC32:f9e211de -packet|codec_type=audio|stream_index=1|pts=5433|pts_time=5.433000|dts=5433|dts_time=5.433000|duration=46|duration_time=0.046000|size=356|pos=179463|flags=K_|data_hash=CRC32:ef458996 -packet|codec_type=video|stream_index=0|pts=5439|pts_time=5.439000|dts=5439|dts_time=5.439000|duration=33|duration_time=0.033000|size=1465|pos=179836|flags=__|data_hash=CRC32:cb5d725a -packet|codec_type=video|stream_index=0|pts=5472|pts_time=5.472000|dts=5472|dts_time=5.472000|duration=33|duration_time=0.033000|size=1862|pos=181321|flags=__|data_hash=CRC32:a9acf274 -packet|codec_type=audio|stream_index=1|pts=5480|pts_time=5.480000|dts=5480|dts_time=5.480000|duration=46|duration_time=0.046000|size=364|pos=183203|flags=K_|data_hash=CRC32:6d92ed19 -packet|codec_type=video|stream_index=0|pts=5506|pts_time=5.506000|dts=5506|dts_time=5.506000|duration=33|duration_time=0.033000|size=1604|pos=183584|flags=__|data_hash=CRC32:19bfeabc -packet|codec_type=audio|stream_index=1|pts=5526|pts_time=5.526000|dts=5526|dts_time=5.526000|duration=46|duration_time=0.046000|size=365|pos=185208|flags=K_|data_hash=CRC32:f257469d -packet|codec_type=video|stream_index=0|pts=5539|pts_time=5.539000|dts=5539|dts_time=5.539000|duration=33|duration_time=0.033000|size=1541|pos=185590|flags=__|data_hash=CRC32:642b27dd -packet|codec_type=video|stream_index=0|pts=5572|pts_time=5.572000|dts=5572|dts_time=5.572000|duration=33|duration_time=0.033000|size=1534|pos=187151|flags=__|data_hash=CRC32:67693383 -packet|codec_type=audio|stream_index=1|pts=5573|pts_time=5.573000|dts=5573|dts_time=5.573000|duration=46|duration_time=0.046000|size=357|pos=188705|flags=K_|data_hash=CRC32:52e0f7ac -packet|codec_type=video|stream_index=0|pts=5606|pts_time=5.606000|dts=5606|dts_time=5.606000|duration=33|duration_time=0.033000|size=1336|pos=189079|flags=__|data_hash=CRC32:904a4734 -packet|codec_type=audio|stream_index=1|pts=5619|pts_time=5.619000|dts=5619|dts_time=5.619000|duration=46|duration_time=0.046000|size=367|pos=190435|flags=K_|data_hash=CRC32:dae9d0bd -packet|codec_type=video|stream_index=0|pts=5639|pts_time=5.639000|dts=5639|dts_time=5.639000|duration=33|duration_time=0.033000|size=1761|pos=190819|flags=__|data_hash=CRC32:93496a5c -packet|codec_type=audio|stream_index=1|pts=5666|pts_time=5.666000|dts=5666|dts_time=5.666000|duration=46|duration_time=0.046000|size=361|pos=192600|flags=K_|data_hash=CRC32:86968dd2 -packet|codec_type=video|stream_index=0|pts=5672|pts_time=5.672000|dts=5672|dts_time=5.672000|duration=33|duration_time=0.033000|size=1722|pos=192978|flags=__|data_hash=CRC32:feec28c7 -packet|codec_type=video|stream_index=0|pts=5706|pts_time=5.706000|dts=5706|dts_time=5.706000|duration=33|duration_time=0.033000|size=1442|pos=194720|flags=__|data_hash=CRC32:620e5c0e -packet|codec_type=audio|stream_index=1|pts=5712|pts_time=5.712000|dts=5712|dts_time=5.712000|duration=46|duration_time=0.046000|size=367|pos=196182|flags=K_|data_hash=CRC32:17f30b04 -packet|codec_type=video|stream_index=0|pts=5739|pts_time=5.739000|dts=5739|dts_time=5.739000|duration=33|duration_time=0.033000|size=1313|pos=196566|flags=__|data_hash=CRC32:6bee8c20 -packet|codec_type=audio|stream_index=1|pts=5759|pts_time=5.759000|dts=5759|dts_time=5.759000|duration=46|duration_time=0.046000|size=375|pos=197899|flags=K_|data_hash=CRC32:4eda4c7c -packet|codec_type=video|stream_index=0|pts=5772|pts_time=5.772000|dts=5772|dts_time=5.772000|duration=33|duration_time=0.033000|size=1436|pos=198291|flags=__|data_hash=CRC32:fd8ac68a -packet|codec_type=audio|stream_index=1|pts=5805|pts_time=5.805000|dts=5805|dts_time=5.805000|duration=46|duration_time=0.046000|size=357|pos=199747|flags=K_|data_hash=CRC32:3551e83a -packet|codec_type=video|stream_index=0|pts=5806|pts_time=5.806000|dts=5806|dts_time=5.806000|duration=33|duration_time=0.033000|size=1689|pos=200121|flags=__|data_hash=CRC32:e09613d4 -packet|codec_type=video|stream_index=0|pts=5839|pts_time=5.839000|dts=5839|dts_time=5.839000|duration=33|duration_time=0.033000|size=1472|pos=201830|flags=__|data_hash=CRC32:9467baaf -packet|codec_type=audio|stream_index=1|pts=5851|pts_time=5.851000|dts=5851|dts_time=5.851000|duration=46|duration_time=0.046000|size=379|pos=203322|flags=K_|data_hash=CRC32:de123d0a -packet|codec_type=video|stream_index=0|pts=5873|pts_time=5.873000|dts=5873|dts_time=5.873000|duration=33|duration_time=0.033000|size=1730|pos=203718|flags=__|data_hash=CRC32:2b6400ba -packet|codec_type=audio|stream_index=1|pts=5898|pts_time=5.898000|dts=5898|dts_time=5.898000|duration=46|duration_time=0.046000|size=361|pos=205468|flags=K_|data_hash=CRC32:02a5f979 -packet|codec_type=video|stream_index=0|pts=5906|pts_time=5.906000|dts=5906|dts_time=5.906000|duration=33|duration_time=0.033000|size=1555|pos=205846|flags=__|data_hash=CRC32:31d5ba1a -packet|codec_type=video|stream_index=0|pts=5939|pts_time=5.939000|dts=5939|dts_time=5.939000|duration=33|duration_time=0.033000|size=1486|pos=207421|flags=__|data_hash=CRC32:8d0829d2 -packet|codec_type=audio|stream_index=1|pts=5944|pts_time=5.944000|dts=5944|dts_time=5.944000|duration=46|duration_time=0.046000|size=350|pos=208927|flags=K_|data_hash=CRC32:8759b7f4 -packet|codec_type=video|stream_index=0|pts=5973|pts_time=5.973000|dts=5973|dts_time=5.973000|duration=33|duration_time=0.033000|size=1311|pos=209294|flags=__|data_hash=CRC32:bc92ded4 -packet|codec_type=audio|stream_index=1|pts=5991|pts_time=5.991000|dts=5991|dts_time=5.991000|duration=46|duration_time=0.046000|size=339|pos=210625|flags=K_|data_hash=CRC32:1aeda6e0 -packet|codec_type=video|stream_index=0|pts=6006|pts_time=6.006000|dts=6006|dts_time=6.006000|duration=33|duration_time=0.033000|size=1700|pos=210981|flags=__|data_hash=CRC32:6352f8f3 -packet|codec_type=audio|stream_index=1|pts=6037|pts_time=6.037000|dts=6037|dts_time=6.037000|duration=46|duration_time=0.046000|size=336|pos=212701|flags=K_|data_hash=CRC32:2df5ef30 -packet|codec_type=video|stream_index=0|pts=6039|pts_time=6.039000|dts=6039|dts_time=6.039000|duration=33|duration_time=0.033000|size=1647|pos=213054|flags=__|data_hash=CRC32:931d3120 -packet|codec_type=video|stream_index=0|pts=6073|pts_time=6.073000|dts=6073|dts_time=6.073000|duration=33|duration_time=0.033000|size=1663|pos=214721|flags=__|data_hash=CRC32:3191d8b9 -packet|codec_type=audio|stream_index=1|pts=6084|pts_time=6.084000|dts=6084|dts_time=6.084000|duration=46|duration_time=0.046000|size=331|pos=216404|flags=K_|data_hash=CRC32:81610328 -packet|codec_type=video|stream_index=0|pts=6106|pts_time=6.106000|dts=6106|dts_time=6.106000|duration=33|duration_time=0.033000|size=1512|pos=216752|flags=__|data_hash=CRC32:975cd742 -packet|codec_type=audio|stream_index=1|pts=6130|pts_time=6.130000|dts=6130|dts_time=6.130000|duration=46|duration_time=0.046000|size=335|pos=218284|flags=K_|data_hash=CRC32:7a0eaa18 -packet|codec_type=video|stream_index=0|pts=6139|pts_time=6.139000|dts=6139|dts_time=6.139000|duration=33|duration_time=0.033000|size=1370|pos=218636|flags=__|data_hash=CRC32:66567f2e -packet|codec_type=video|stream_index=0|pts=6173|pts_time=6.173000|dts=6173|dts_time=6.173000|duration=33|duration_time=0.033000|size=1440|pos=220026|flags=__|data_hash=CRC32:4bfade47 -packet|codec_type=audio|stream_index=1|pts=6177|pts_time=6.177000|dts=6177|dts_time=6.177000|duration=46|duration_time=0.046000|size=323|pos=221486|flags=K_|data_hash=CRC32:3799307f -packet|codec_type=video|stream_index=0|pts=6206|pts_time=6.206000|dts=6206|dts_time=6.206000|duration=33|duration_time=0.033000|size=1574|pos=221826|flags=__|data_hash=CRC32:a489fa6f -packet|codec_type=audio|stream_index=1|pts=6223|pts_time=6.223000|dts=6223|dts_time=6.223000|duration=46|duration_time=0.046000|size=333|pos=223420|flags=K_|data_hash=CRC32:c8363968 -packet|codec_type=video|stream_index=0|pts=6240|pts_time=6.240000|dts=6240|dts_time=6.240000|duration=33|duration_time=0.033000|size=1328|pos=223770|flags=__|data_hash=CRC32:1fea5aac -packet|codec_type=audio|stream_index=1|pts=6269|pts_time=6.269000|dts=6269|dts_time=6.269000|duration=46|duration_time=0.046000|size=335|pos=225118|flags=K_|data_hash=CRC32:b9425c66 -packet|codec_type=video|stream_index=0|pts=6273|pts_time=6.273000|dts=6273|dts_time=6.273000|duration=33|duration_time=0.033000|size=1802|pos=225470|flags=__|data_hash=CRC32:dcf03b48 -packet|codec_type=video|stream_index=0|pts=6306|pts_time=6.306000|dts=6306|dts_time=6.306000|duration=33|duration_time=0.033000|size=1619|pos=227292|flags=__|data_hash=CRC32:fe0b0001 -packet|codec_type=audio|stream_index=1|pts=6316|pts_time=6.316000|dts=6316|dts_time=6.316000|duration=46|duration_time=0.046000|size=334|pos=228931|flags=K_|data_hash=CRC32:ec0fe921 -packet|codec_type=video|stream_index=0|pts=6340|pts_time=6.340000|dts=6340|dts_time=6.340000|duration=33|duration_time=0.033000|size=1471|pos=229282|flags=__|data_hash=CRC32:d30c0223 -packet|codec_type=audio|stream_index=1|pts=6362|pts_time=6.362000|dts=6362|dts_time=6.362000|duration=46|duration_time=0.046000|size=342|pos=230773|flags=K_|data_hash=CRC32:f18fb26f -packet|codec_type=video|stream_index=0|pts=6373|pts_time=6.373000|dts=6373|dts_time=6.373000|duration=33|duration_time=0.033000|size=1226|pos=231132|flags=__|data_hash=CRC32:7336c586 -packet|codec_type=video|stream_index=0|pts=6406|pts_time=6.406000|dts=6406|dts_time=6.406000|duration=33|duration_time=0.033000|size=1485|pos=232378|flags=__|data_hash=CRC32:6f6eae16 -packet|codec_type=audio|stream_index=1|pts=6409|pts_time=6.409000|dts=6409|dts_time=6.409000|duration=46|duration_time=0.046000|size=358|pos=233883|flags=K_|data_hash=CRC32:ef6dc063 -packet|codec_type=video|stream_index=0|pts=6440|pts_time=6.440000|dts=6440|dts_time=6.440000|duration=33|duration_time=0.033000|size=1786|pos=234258|flags=__|data_hash=CRC32:0d06af0a -packet|codec_type=audio|stream_index=1|pts=6455|pts_time=6.455000|dts=6455|dts_time=6.455000|duration=46|duration_time=0.046000|size=360|pos=236064|flags=K_|data_hash=CRC32:21588c84 -packet|codec_type=video|stream_index=0|pts=6473|pts_time=6.473000|dts=6473|dts_time=6.473000|duration=33|duration_time=0.033000|size=1345|pos=236441|flags=__|data_hash=CRC32:be3a88c3 -packet|codec_type=audio|stream_index=1|pts=6502|pts_time=6.502000|dts=6502|dts_time=6.502000|duration=46|duration_time=0.046000|size=357|pos=237806|flags=K_|data_hash=CRC32:2b9aa0fa -packet|codec_type=video|stream_index=0|pts=6507|pts_time=6.507000|dts=6507|dts_time=6.507000|duration=33|duration_time=0.033000|size=8275|pos=238180|flags=K_|data_hash=CRC32:a7db122a -packet|codec_type=video|stream_index=0|pts=6540|pts_time=6.540000|dts=6540|dts_time=6.540000|duration=33|duration_time=0.033000|size=698|pos=246475|flags=__|data_hash=CRC32:333944af -packet|codec_type=audio|stream_index=1|pts=6548|pts_time=6.548000|dts=6548|dts_time=6.548000|duration=46|duration_time=0.046000|size=336|pos=247193|flags=K_|data_hash=CRC32:57dbe1a1 -packet|codec_type=video|stream_index=0|pts=6573|pts_time=6.573000|dts=6573|dts_time=6.573000|duration=33|duration_time=0.033000|size=1298|pos=247546|flags=__|data_hash=CRC32:e4a95b13 -packet|codec_type=audio|stream_index=1|pts=6594|pts_time=6.594000|dts=6594|dts_time=6.594000|duration=46|duration_time=0.046000|size=343|pos=248864|flags=K_|data_hash=CRC32:ed44ae94 -packet|codec_type=video|stream_index=0|pts=6607|pts_time=6.607000|dts=6607|dts_time=6.607000|duration=33|duration_time=0.033000|size=1454|pos=249224|flags=__|data_hash=CRC32:40218f22 -packet|codec_type=video|stream_index=0|pts=6640|pts_time=6.640000|dts=6640|dts_time=6.640000|duration=33|duration_time=0.033000|size=1352|pos=250698|flags=__|data_hash=CRC32:06fd2643 -packet|codec_type=audio|stream_index=1|pts=6641|pts_time=6.641000|dts=6641|dts_time=6.641000|duration=46|duration_time=0.046000|size=324|pos=252070|flags=K_|data_hash=CRC32:0a20b257 -packet|codec_type=video|stream_index=0|pts=6673|pts_time=6.673000|dts=6673|dts_time=6.673000|duration=33|duration_time=0.033000|size=1609|pos=252411|flags=__|data_hash=CRC32:73d71cca -packet|codec_type=audio|stream_index=1|pts=6687|pts_time=6.687000|dts=6687|dts_time=6.687000|duration=46|duration_time=0.046000|size=322|pos=254040|flags=K_|data_hash=CRC32:32957adb -packet|codec_type=video|stream_index=0|pts=6707|pts_time=6.707000|dts=6707|dts_time=6.707000|duration=33|duration_time=0.033000|size=1476|pos=254379|flags=__|data_hash=CRC32:226c92f5 -packet|codec_type=audio|stream_index=1|pts=6734|pts_time=6.734000|dts=6734|dts_time=6.734000|duration=46|duration_time=0.046000|size=328|pos=255875|flags=K_|data_hash=CRC32:f2deeca5 -packet|codec_type=video|stream_index=0|pts=6740|pts_time=6.740000|dts=6740|dts_time=6.740000|duration=33|duration_time=0.033000|size=1391|pos=256220|flags=__|data_hash=CRC32:9a20a6cc -packet|codec_type=video|stream_index=0|pts=6773|pts_time=6.773000|dts=6773|dts_time=6.773000|duration=33|duration_time=0.033000|size=1203|pos=257631|flags=__|data_hash=CRC32:694b79e2 -packet|codec_type=audio|stream_index=1|pts=6780|pts_time=6.780000|dts=6780|dts_time=6.780000|duration=46|duration_time=0.046000|size=332|pos=258854|flags=K_|data_hash=CRC32:69c10e24 -packet|codec_type=video|stream_index=0|pts=6807|pts_time=6.807000|dts=6807|dts_time=6.807000|duration=33|duration_time=0.033000|size=1489|pos=259203|flags=__|data_hash=CRC32:72a4b942 -packet|codec_type=audio|stream_index=1|pts=6827|pts_time=6.827000|dts=6827|dts_time=6.827000|duration=46|duration_time=0.046000|size=343|pos=260712|flags=K_|data_hash=CRC32:59e5debb -packet|codec_type=video|stream_index=0|pts=6840|pts_time=6.840000|dts=6840|dts_time=6.840000|duration=33|duration_time=0.033000|size=1655|pos=261072|flags=__|data_hash=CRC32:d23af0f0 -packet|codec_type=audio|stream_index=1|pts=6873|pts_time=6.873000|dts=6873|dts_time=6.873000|duration=46|duration_time=0.046000|size=343|pos=262747|flags=K_|data_hash=CRC32:3a753534 -packet|codec_type=video|stream_index=0|pts=6874|pts_time=6.874000|dts=6874|dts_time=6.874000|duration=33|duration_time=0.033000|size=1363|pos=263107|flags=__|data_hash=CRC32:a3c3183f -packet|codec_type=video|stream_index=0|pts=6907|pts_time=6.907000|dts=6907|dts_time=6.907000|duration=33|duration_time=0.033000|size=1492|pos=264490|flags=__|data_hash=CRC32:2efa7752 -packet|codec_type=audio|stream_index=1|pts=6920|pts_time=6.920000|dts=6920|dts_time=6.920000|duration=46|duration_time=0.046000|size=327|pos=266002|flags=K_|data_hash=CRC32:0c6cfc20 -packet|codec_type=video|stream_index=0|pts=6940|pts_time=6.940000|dts=6940|dts_time=6.940000|duration=33|duration_time=0.033000|size=1397|pos=266346|flags=__|data_hash=CRC32:f4cff2aa -packet|codec_type=audio|stream_index=1|pts=6966|pts_time=6.966000|dts=6966|dts_time=6.966000|duration=46|duration_time=0.046000|size=326|pos=267763|flags=K_|data_hash=CRC32:0287694a -packet|codec_type=video|stream_index=0|pts=6974|pts_time=6.974000|dts=6974|dts_time=6.974000|duration=33|duration_time=0.033000|size=1251|pos=268106|flags=__|data_hash=CRC32:24f376e2 -packet|codec_type=video|stream_index=0|pts=7007|pts_time=7.007000|dts=7007|dts_time=7.007000|duration=33|duration_time=0.033000|size=1586|pos=269377|flags=__|data_hash=CRC32:6894eed6 -packet|codec_type=audio|stream_index=1|pts=7012|pts_time=7.012000|dts=7012|dts_time=7.012000|duration=46|duration_time=0.046000|size=324|pos=270983|flags=K_|data_hash=CRC32:7131ae4e -packet|codec_type=video|stream_index=0|pts=7040|pts_time=7.040000|dts=7040|dts_time=7.040000|duration=33|duration_time=0.033000|size=1333|pos=271324|flags=__|data_hash=CRC32:c70a7aad -packet|codec_type=audio|stream_index=1|pts=7059|pts_time=7.059000|dts=7059|dts_time=7.059000|duration=46|duration_time=0.046000|size=312|pos=272677|flags=K_|data_hash=CRC32:19e4ee3f -packet|codec_type=video|stream_index=0|pts=7074|pts_time=7.074000|dts=7074|dts_time=7.074000|duration=33|duration_time=0.033000|size=2723|pos=273006|flags=__|data_hash=CRC32:a6013df5 -packet|codec_type=audio|stream_index=1|pts=7105|pts_time=7.105000|dts=7105|dts_time=7.105000|duration=46|duration_time=0.046000|size=308|pos=275749|flags=K_|data_hash=CRC32:c90c6296 -packet|codec_type=video|stream_index=0|pts=7107|pts_time=7.107000|dts=7107|dts_time=7.107000|duration=33|duration_time=0.033000|size=632|pos=276074|flags=__|data_hash=CRC32:24dd0b1b -packet|codec_type=video|stream_index=0|pts=7140|pts_time=7.140000|dts=7140|dts_time=7.140000|duration=33|duration_time=0.033000|size=444|pos=276726|flags=__|data_hash=CRC32:f0104674 -packet|codec_type=audio|stream_index=1|pts=7152|pts_time=7.152000|dts=7152|dts_time=7.152000|duration=46|duration_time=0.046000|size=308|pos=277190|flags=K_|data_hash=CRC32:801d3efb -packet|codec_type=video|stream_index=0|pts=7174|pts_time=7.174000|dts=7174|dts_time=7.174000|duration=33|duration_time=0.033000|size=1013|pos=277515|flags=__|data_hash=CRC32:50fd7439 -packet|codec_type=audio|stream_index=1|pts=7198|pts_time=7.198000|dts=7198|dts_time=7.198000|duration=46|duration_time=0.046000|size=318|pos=278548|flags=K_|data_hash=CRC32:da27ff29 -packet|codec_type=video|stream_index=0|pts=7207|pts_time=7.207000|dts=7207|dts_time=7.207000|duration=33|duration_time=0.033000|size=1357|pos=278883|flags=__|data_hash=CRC32:147764fe -packet|codec_type=video|stream_index=0|pts=7241|pts_time=7.241000|dts=7241|dts_time=7.241000|duration=33|duration_time=0.033000|size=1586|pos=280260|flags=__|data_hash=CRC32:6ba61f38 -packet|codec_type=audio|stream_index=1|pts=7245|pts_time=7.245000|dts=7245|dts_time=7.245000|duration=46|duration_time=0.046000|size=331|pos=281866|flags=K_|data_hash=CRC32:ff54d1a1 -packet|codec_type=video|stream_index=0|pts=7274|pts_time=7.274000|dts=7274|dts_time=7.274000|duration=33|duration_time=0.033000|size=2514|pos=282214|flags=__|data_hash=CRC32:ee50c38f -packet|codec_type=audio|stream_index=1|pts=7291|pts_time=7.291000|dts=7291|dts_time=7.291000|duration=46|duration_time=0.046000|size=329|pos=284748|flags=K_|data_hash=CRC32:af348626 -packet|codec_type=video|stream_index=0|pts=7307|pts_time=7.307000|dts=7307|dts_time=7.307000|duration=33|duration_time=0.033000|size=450|pos=285094|flags=__|data_hash=CRC32:4c566b91 -packet|codec_type=audio|stream_index=1|pts=7338|pts_time=7.338000|dts=7338|dts_time=7.338000|duration=46|duration_time=0.046000|size=333|pos=285564|flags=K_|data_hash=CRC32:561118f2 -packet|codec_type=video|stream_index=0|pts=7341|pts_time=7.341000|dts=7341|dts_time=7.341000|duration=33|duration_time=0.033000|size=423|pos=285914|flags=__|data_hash=CRC32:799d9d42 -packet|codec_type=video|stream_index=0|pts=7374|pts_time=7.374000|dts=7374|dts_time=7.374000|duration=33|duration_time=0.033000|size=1161|pos=286357|flags=__|data_hash=CRC32:f37f1ffc -packet|codec_type=audio|stream_index=1|pts=7384|pts_time=7.384000|dts=7384|dts_time=7.384000|duration=46|duration_time=0.046000|size=314|pos=287538|flags=K_|data_hash=CRC32:ab18160b -packet|codec_type=video|stream_index=0|pts=7407|pts_time=7.407000|dts=7407|dts_time=7.407000|duration=33|duration_time=0.033000|size=1366|pos=287869|flags=__|data_hash=CRC32:6484b277 -packet|codec_type=audio|stream_index=1|pts=7430|pts_time=7.430000|dts=7430|dts_time=7.430000|duration=46|duration_time=0.046000|size=304|pos=289255|flags=K_|data_hash=CRC32:823aa6c6 -packet|codec_type=video|stream_index=0|pts=7441|pts_time=7.441000|dts=7441|dts_time=7.441000|duration=33|duration_time=0.033000|size=1325|pos=289576|flags=__|data_hash=CRC32:6eb411da -packet|codec_type=video|stream_index=0|pts=7474|pts_time=7.474000|dts=7474|dts_time=7.474000|duration=33|duration_time=0.033000|size=2687|pos=290921|flags=__|data_hash=CRC32:dc8f2e68 -packet|codec_type=audio|stream_index=1|pts=7477|pts_time=7.477000|dts=7477|dts_time=7.477000|duration=46|duration_time=0.046000|size=299|pos=293628|flags=K_|data_hash=CRC32:92c86961 -packet|codec_type=video|stream_index=0|pts=7508|pts_time=7.508000|dts=7508|dts_time=7.508000|duration=33|duration_time=0.033000|size=678|pos=293944|flags=__|data_hash=CRC32:bbd3fb62 -packet|codec_type=audio|stream_index=1|pts=7523|pts_time=7.523000|dts=7523|dts_time=7.523000|duration=46|duration_time=0.046000|size=311|pos=294642|flags=K_|data_hash=CRC32:8f7e6535 -packet|codec_type=video|stream_index=0|pts=7541|pts_time=7.541000|dts=7541|dts_time=7.541000|duration=33|duration_time=0.033000|size=491|pos=294970|flags=__|data_hash=CRC32:44e5e238 -packet|codec_type=audio|stream_index=1|pts=7570|pts_time=7.570000|dts=7570|dts_time=7.570000|duration=46|duration_time=0.046000|size=323|pos=295481|flags=K_|data_hash=CRC32:4572a6b6 -packet|codec_type=video|stream_index=0|pts=7574|pts_time=7.574000|dts=7574|dts_time=7.574000|duration=33|duration_time=0.033000|size=1056|pos=295821|flags=__|data_hash=CRC32:59790f4a -packet|codec_type=video|stream_index=0|pts=7608|pts_time=7.608000|dts=7608|dts_time=7.608000|duration=33|duration_time=0.033000|size=1549|pos=296897|flags=__|data_hash=CRC32:ede372d1 -packet|codec_type=audio|stream_index=1|pts=7616|pts_time=7.616000|dts=7616|dts_time=7.616000|duration=46|duration_time=0.046000|size=317|pos=298466|flags=K_|data_hash=CRC32:217926a5 -packet|codec_type=video|stream_index=0|pts=7641|pts_time=7.641000|dts=7641|dts_time=7.641000|duration=33|duration_time=0.033000|size=2502|pos=298800|flags=__|data_hash=CRC32:b4c753cb -packet|codec_type=audio|stream_index=1|pts=7663|pts_time=7.663000|dts=7663|dts_time=7.663000|duration=46|duration_time=0.046000|size=322|pos=301322|flags=K_|data_hash=CRC32:66da2414 -packet|codec_type=video|stream_index=0|pts=7674|pts_time=7.674000|dts=7674|dts_time=7.674000|duration=33|duration_time=0.033000|size=539|pos=301661|flags=__|data_hash=CRC32:957ce92c -packet|codec_type=video|stream_index=0|pts=7708|pts_time=7.708000|dts=7708|dts_time=7.708000|duration=33|duration_time=0.033000|size=594|pos=302220|flags=__|data_hash=CRC32:01178bad -packet|codec_type=audio|stream_index=1|pts=7709|pts_time=7.709000|dts=7709|dts_time=7.709000|duration=46|duration_time=0.046000|size=329|pos=302834|flags=K_|data_hash=CRC32:8570ef58 -packet|codec_type=video|stream_index=0|pts=7741|pts_time=7.741000|dts=7741|dts_time=7.741000|duration=33|duration_time=0.033000|size=1254|pos=303180|flags=__|data_hash=CRC32:7b42fdb2 -packet|codec_type=audio|stream_index=1|pts=7755|pts_time=7.755000|dts=7755|dts_time=7.755000|duration=46|duration_time=0.046000|size=342|pos=304454|flags=K_|data_hash=CRC32:866b46d1 -packet|codec_type=video|stream_index=0|pts=7774|pts_time=7.774000|dts=7774|dts_time=7.774000|duration=33|duration_time=0.033000|size=1341|pos=304813|flags=__|data_hash=CRC32:76ee5810 -packet|codec_type=audio|stream_index=1|pts=7802|pts_time=7.802000|dts=7802|dts_time=7.802000|duration=46|duration_time=0.046000|size=331|pos=306174|flags=K_|data_hash=CRC32:e836a9c7 -packet|codec_type=video|stream_index=0|pts=7808|pts_time=7.808000|dts=7808|dts_time=7.808000|duration=33|duration_time=0.033000|size=1358|pos=306522|flags=__|data_hash=CRC32:935430a2 -packet|codec_type=video|stream_index=0|pts=7841|pts_time=7.841000|dts=7841|dts_time=7.841000|duration=33|duration_time=0.033000|size=2336|pos=307900|flags=__|data_hash=CRC32:3ed5a208 -packet|codec_type=audio|stream_index=1|pts=7848|pts_time=7.848000|dts=7848|dts_time=7.848000|duration=46|duration_time=0.046000|size=343|pos=310256|flags=K_|data_hash=CRC32:eb15e72d -packet|codec_type=video|stream_index=0|pts=7875|pts_time=7.875000|dts=7875|dts_time=7.875000|duration=33|duration_time=0.033000|size=339|pos=310616|flags=__|data_hash=CRC32:10d2e236 -packet|codec_type=audio|stream_index=1|pts=7895|pts_time=7.895000|dts=7895|dts_time=7.895000|duration=46|duration_time=0.046000|size=327|pos=310975|flags=K_|data_hash=CRC32:fa82f874 -packet|codec_type=video|stream_index=0|pts=7908|pts_time=7.908000|dts=7908|dts_time=7.908000|duration=33|duration_time=0.033000|size=2159|pos=311319|flags=__|data_hash=CRC32:d84ad78a -packet|codec_type=audio|stream_index=1|pts=7941|pts_time=7.941000|dts=7941|dts_time=7.941000|duration=46|duration_time=0.046000|size=317|pos=313498|flags=K_|data_hash=CRC32:2f9ae86b -packet|codec_type=video|stream_index=0|pts=7941|pts_time=7.941000|dts=7941|dts_time=7.941000|duration=33|duration_time=0.033000|size=390|pos=313832|flags=__|data_hash=CRC32:d5f6e16d -packet|codec_type=video|stream_index=0|pts=7975|pts_time=7.975000|dts=7975|dts_time=7.975000|duration=33|duration_time=0.033000|size=479|pos=314242|flags=__|data_hash=CRC32:62ef0b83 -packet|codec_type=audio|stream_index=1|pts=7988|pts_time=7.988000|dts=7988|dts_time=7.988000|duration=46|duration_time=0.046000|size=313|pos=314741|flags=K_|data_hash=CRC32:de3136c8 -packet|codec_type=video|stream_index=0|pts=8008|pts_time=8.008000|dts=8008|dts_time=8.008000|duration=33|duration_time=0.033000|size=2157|pos=315071|flags=__|data_hash=CRC32:0cef0137 -packet|codec_type=audio|stream_index=1|pts=8034|pts_time=8.034000|dts=8034|dts_time=8.034000|duration=46|duration_time=0.046000|size=312|pos=317248|flags=K_|data_hash=CRC32:4abd9c07 -packet|codec_type=video|stream_index=0|pts=8041|pts_time=8.041000|dts=8041|dts_time=8.041000|duration=33|duration_time=0.033000|size=429|pos=317577|flags=__|data_hash=CRC32:87ebdeb2 -packet|codec_type=video|stream_index=0|pts=8075|pts_time=8.075000|dts=8075|dts_time=8.075000|duration=33|duration_time=0.033000|size=1953|pos=318026|flags=__|data_hash=CRC32:02a64621 -packet|codec_type=audio|stream_index=1|pts=8081|pts_time=8.081000|dts=8081|dts_time=8.081000|duration=46|duration_time=0.046000|size=318|pos=319999|flags=K_|data_hash=CRC32:f22024a9 -packet|codec_type=video|stream_index=0|pts=8108|pts_time=8.108000|dts=8108|dts_time=8.108000|duration=33|duration_time=0.033000|size=379|pos=320334|flags=__|data_hash=CRC32:b62cddd2 -packet|codec_type=audio|stream_index=1|pts=8127|pts_time=8.127000|dts=8127|dts_time=8.127000|duration=46|duration_time=0.046000|size=325|pos=320733|flags=K_|data_hash=CRC32:64fd8299 -packet|codec_type=video|stream_index=0|pts=8141|pts_time=8.141000|dts=8141|dts_time=8.141000|duration=33|duration_time=0.033000|size=1817|pos=321075|flags=__|data_hash=CRC32:c8592216 -packet|codec_type=audio|stream_index=1|pts=8173|pts_time=8.173000|dts=8173|dts_time=8.173000|duration=46|duration_time=0.046000|size=317|pos=322912|flags=K_|data_hash=CRC32:4691c3cf -packet|codec_type=video|stream_index=0|pts=8175|pts_time=8.175000|dts=8175|dts_time=8.175000|duration=33|duration_time=0.033000|size=372|pos=323246|flags=__|data_hash=CRC32:97c375b0 -packet|codec_type=video|stream_index=0|pts=8208|pts_time=8.208000|dts=8208|dts_time=8.208000|duration=33|duration_time=0.033000|size=1664|pos=323638|flags=__|data_hash=CRC32:ca3e11a7 -packet|codec_type=audio|stream_index=1|pts=8220|pts_time=8.220000|dts=8220|dts_time=8.220000|duration=46|duration_time=0.046000|size=308|pos=325322|flags=K_|data_hash=CRC32:09626471 -packet|codec_type=video|stream_index=0|pts=8242|pts_time=8.242000|dts=8242|dts_time=8.242000|duration=33|duration_time=0.033000|size=340|pos=325647|flags=__|data_hash=CRC32:a779f4f7 -packet|codec_type=audio|stream_index=1|pts=8266|pts_time=8.266000|dts=8266|dts_time=8.266000|duration=46|duration_time=0.046000|size=309|pos=326007|flags=K_|data_hash=CRC32:728889b5 -packet|codec_type=video|stream_index=0|pts=8275|pts_time=8.275000|dts=8275|dts_time=8.275000|duration=33|duration_time=0.033000|size=1955|pos=326333|flags=__|data_hash=CRC32:695aa624 -packet|codec_type=video|stream_index=0|pts=8308|pts_time=8.308000|dts=8308|dts_time=8.308000|duration=33|duration_time=0.033000|size=485|pos=328308|flags=__|data_hash=CRC32:51973647 -packet|codec_type=audio|stream_index=1|pts=8313|pts_time=8.313000|dts=8313|dts_time=8.313000|duration=46|duration_time=0.046000|size=315|pos=328813|flags=K_|data_hash=CRC32:c3488703 -packet|codec_type=video|stream_index=0|pts=8342|pts_time=8.342000|dts=8342|dts_time=8.342000|duration=33|duration_time=0.033000|size=1705|pos=329145|flags=__|data_hash=CRC32:5837d8d2 -packet|codec_type=audio|stream_index=1|pts=8359|pts_time=8.359000|dts=8359|dts_time=8.359000|duration=46|duration_time=0.046000|size=340|pos=330870|flags=K_|data_hash=CRC32:9e35fdd6 -packet|codec_type=video|stream_index=0|pts=8375|pts_time=8.375000|dts=8375|dts_time=8.375000|duration=33|duration_time=0.033000|size=411|pos=331227|flags=__|data_hash=CRC32:0f50eec7 -packet|codec_type=audio|stream_index=1|pts=8406|pts_time=8.406000|dts=8406|dts_time=8.406000|duration=46|duration_time=0.046000|size=326|pos=331658|flags=K_|data_hash=CRC32:719bf8ae -packet|codec_type=video|stream_index=0|pts=8408|pts_time=8.408000|dts=8408|dts_time=8.408000|duration=33|duration_time=0.033000|size=1818|pos=332001|flags=__|data_hash=CRC32:a33c3a86 -packet|codec_type=video|stream_index=0|pts=8442|pts_time=8.442000|dts=8442|dts_time=8.442000|duration=33|duration_time=0.033000|size=304|pos=333839|flags=__|data_hash=CRC32:e192b5c4 -packet|codec_type=audio|stream_index=1|pts=8452|pts_time=8.452000|dts=8452|dts_time=8.452000|duration=46|duration_time=0.046000|size=333|pos=334163|flags=K_|data_hash=CRC32:e927cbe1 -packet|codec_type=video|stream_index=0|pts=8475|pts_time=8.475000|dts=8475|dts_time=8.475000|duration=33|duration_time=0.033000|size=6302|pos=334513|flags=K_|data_hash=CRC32:2290178c -packet|codec_type=audio|stream_index=1|pts=8499|pts_time=8.499000|dts=8499|dts_time=8.499000|duration=46|duration_time=0.046000|size=340|pos=340835|flags=K_|data_hash=CRC32:2dfd7ad8 -packet|codec_type=video|stream_index=0|pts=8509|pts_time=8.509000|dts=8509|dts_time=8.509000|duration=33|duration_time=0.033000|size=1498|pos=341192|flags=__|data_hash=CRC32:e0611ee8 -packet|codec_type=video|stream_index=0|pts=8542|pts_time=8.542000|dts=8542|dts_time=8.542000|duration=33|duration_time=0.033000|size=434|pos=342710|flags=__|data_hash=CRC32:ffb5d9c5 -packet|codec_type=audio|stream_index=1|pts=8545|pts_time=8.545000|dts=8545|dts_time=8.545000|duration=46|duration_time=0.046000|size=338|pos=343164|flags=K_|data_hash=CRC32:954e8263 -packet|codec_type=video|stream_index=0|pts=8575|pts_time=8.575000|dts=8575|dts_time=8.575000|duration=33|duration_time=0.033000|size=1643|pos=343519|flags=__|data_hash=CRC32:c4e8ba5f -packet|codec_type=audio|stream_index=1|pts=8591|pts_time=8.591000|dts=8591|dts_time=8.591000|duration=46|duration_time=0.046000|size=357|pos=345182|flags=K_|data_hash=CRC32:944e4fde -packet|codec_type=video|stream_index=0|pts=8609|pts_time=8.609000|dts=8609|dts_time=8.609000|duration=33|duration_time=0.033000|size=213|pos=345556|flags=__|data_hash=CRC32:6b32090f -packet|codec_type=audio|stream_index=1|pts=8638|pts_time=8.638000|dts=8638|dts_time=8.638000|duration=46|duration_time=0.046000|size=340|pos=345789|flags=K_|data_hash=CRC32:edd08354 -packet|codec_type=video|stream_index=0|pts=8642|pts_time=8.642000|dts=8642|dts_time=8.642000|duration=33|duration_time=0.033000|size=1820|pos=346146|flags=__|data_hash=CRC32:e814434f -packet|codec_type=video|stream_index=0|pts=8675|pts_time=8.675000|dts=8675|dts_time=8.675000|duration=33|duration_time=0.033000|size=264|pos=347986|flags=__|data_hash=CRC32:c47e7364 -packet|codec_type=audio|stream_index=1|pts=8684|pts_time=8.684000|dts=8684|dts_time=8.684000|duration=46|duration_time=0.046000|size=335|pos=348270|flags=K_|data_hash=CRC32:6a3050c7 -packet|codec_type=video|stream_index=0|pts=8709|pts_time=8.709000|dts=8709|dts_time=8.709000|duration=33|duration_time=0.033000|size=1461|pos=348622|flags=__|data_hash=CRC32:9bf7c586 -packet|codec_type=audio|stream_index=1|pts=8731|pts_time=8.731000|dts=8731|dts_time=8.731000|duration=46|duration_time=0.046000|size=322|pos=350103|flags=K_|data_hash=CRC32:f8744c32 -packet|codec_type=video|stream_index=0|pts=8742|pts_time=8.742000|dts=8742|dts_time=8.742000|duration=33|duration_time=0.033000|size=239|pos=350442|flags=__|data_hash=CRC32:7549da5a -packet|codec_type=video|stream_index=0|pts=8775|pts_time=8.775000|dts=8775|dts_time=8.775000|duration=33|duration_time=0.033000|size=1581|pos=350701|flags=__|data_hash=CRC32:2d4be1b6 -packet|codec_type=audio|stream_index=1|pts=8777|pts_time=8.777000|dts=8777|dts_time=8.777000|duration=46|duration_time=0.046000|size=318|pos=352302|flags=K_|data_hash=CRC32:e85d4c2c -packet|codec_type=video|stream_index=0|pts=8809|pts_time=8.809000|dts=8809|dts_time=8.809000|duration=33|duration_time=0.033000|size=212|pos=352637|flags=__|data_hash=CRC32:5b804b23 -packet|codec_type=audio|stream_index=1|pts=8824|pts_time=8.824000|dts=8824|dts_time=8.824000|duration=46|duration_time=0.046000|size=326|pos=352869|flags=K_|data_hash=CRC32:a2b69ebf -packet|codec_type=video|stream_index=0|pts=8842|pts_time=8.842000|dts=8842|dts_time=8.842000|duration=33|duration_time=0.033000|size=1351|pos=353212|flags=__|data_hash=CRC32:5f901255 -packet|codec_type=audio|stream_index=1|pts=8870|pts_time=8.870000|dts=8870|dts_time=8.870000|duration=46|duration_time=0.046000|size=341|pos=354583|flags=K_|data_hash=CRC32:f928467f -packet|codec_type=video|stream_index=0|pts=8876|pts_time=8.876000|dts=8876|dts_time=8.876000|duration=33|duration_time=0.033000|size=448|pos=354941|flags=__|data_hash=CRC32:ab757d3b -packet|codec_type=video|stream_index=0|pts=8909|pts_time=8.909000|dts=8909|dts_time=8.909000|duration=33|duration_time=0.033000|size=1403|pos=355409|flags=__|data_hash=CRC32:b01c66f4 -packet|codec_type=audio|stream_index=1|pts=8916|pts_time=8.916000|dts=8916|dts_time=8.916000|duration=46|duration_time=0.046000|size=319|pos=356832|flags=K_|data_hash=CRC32:0926072d -packet|codec_type=video|stream_index=0|pts=8942|pts_time=8.942000|dts=8942|dts_time=8.942000|duration=33|duration_time=0.033000|size=491|pos=357168|flags=__|data_hash=CRC32:0367ac76 -packet|codec_type=audio|stream_index=1|pts=8963|pts_time=8.963000|dts=8963|dts_time=8.963000|duration=46|duration_time=0.046000|size=303|pos=357679|flags=K_|data_hash=CRC32:d41fe125 -packet|codec_type=video|stream_index=0|pts=8976|pts_time=8.976000|dts=8976|dts_time=8.976000|duration=33|duration_time=0.033000|size=1606|pos=357999|flags=__|data_hash=CRC32:662f0120 -packet|codec_type=audio|stream_index=1|pts=9009|pts_time=9.009000|dts=9009|dts_time=9.009000|duration=46|duration_time=0.046000|size=291|pos=359625|flags=K_|data_hash=CRC32:f90846c9 -packet|codec_type=video|stream_index=0|pts=9009|pts_time=9.009000|dts=9009|dts_time=9.009000|duration=33|duration_time=0.033000|size=304|pos=359933|flags=__|data_hash=CRC32:18968792 -packet|codec_type=video|stream_index=0|pts=9042|pts_time=9.042000|dts=9042|dts_time=9.042000|duration=33|duration_time=0.033000|size=1537|pos=360257|flags=__|data_hash=CRC32:5469d062 -packet|codec_type=audio|stream_index=1|pts=9056|pts_time=9.056000|dts=9056|dts_time=9.056000|duration=46|duration_time=0.046000|size=307|pos=361814|flags=K_|data_hash=CRC32:ef8ffe20 -packet|codec_type=video|stream_index=0|pts=9076|pts_time=9.076000|dts=9076|dts_time=9.076000|duration=33|duration_time=0.033000|size=342|pos=362138|flags=__|data_hash=CRC32:dd1d6dbb -packet|codec_type=audio|stream_index=1|pts=9102|pts_time=9.102000|dts=9102|dts_time=9.102000|duration=46|duration_time=0.046000|size=335|pos=362500|flags=K_|data_hash=CRC32:ccc6f929 -packet|codec_type=video|stream_index=0|pts=9109|pts_time=9.109000|dts=9109|dts_time=9.109000|duration=33|duration_time=0.033000|size=1405|pos=362852|flags=__|data_hash=CRC32:6558f9bb -packet|codec_type=video|stream_index=0|pts=9142|pts_time=9.142000|dts=9142|dts_time=9.142000|duration=33|duration_time=0.033000|size=351|pos=364277|flags=__|data_hash=CRC32:867aaa58 -packet|codec_type=audio|stream_index=1|pts=9149|pts_time=9.149000|dts=9149|dts_time=9.149000|duration=46|duration_time=0.046000|size=348|pos=364648|flags=K_|data_hash=CRC32:d0911535 -packet|codec_type=video|stream_index=0|pts=9176|pts_time=9.176000|dts=9176|dts_time=9.176000|duration=33|duration_time=0.033000|size=1451|pos=365013|flags=__|data_hash=CRC32:8c786cd9 -packet|codec_type=audio|stream_index=1|pts=9195|pts_time=9.195000|dts=9195|dts_time=9.195000|duration=46|duration_time=0.046000|size=346|pos=366484|flags=K_|data_hash=CRC32:4d6976df -packet|codec_type=video|stream_index=0|pts=9209|pts_time=9.209000|dts=9209|dts_time=9.209000|duration=33|duration_time=0.033000|size=490|pos=366847|flags=__|data_hash=CRC32:d80d8605 -packet|codec_type=audio|stream_index=1|pts=9242|pts_time=9.242000|dts=9242|dts_time=9.242000|duration=46|duration_time=0.046000|size=333|pos=367357|flags=K_|data_hash=CRC32:dac6e6f2 -packet|codec_type=video|stream_index=0|pts=9243|pts_time=9.243000|dts=9243|dts_time=9.243000|duration=33|duration_time=0.033000|size=1524|pos=367707|flags=__|data_hash=CRC32:c3d07b7a -packet|codec_type=video|stream_index=0|pts=9276|pts_time=9.276000|dts=9276|dts_time=9.276000|duration=33|duration_time=0.033000|size=556|pos=369251|flags=__|data_hash=CRC32:3cb8f0fa -packet|codec_type=audio|stream_index=1|pts=9288|pts_time=9.288000|dts=9288|dts_time=9.288000|duration=46|duration_time=0.046000|size=338|pos=369827|flags=K_|data_hash=CRC32:2eade044 -packet|codec_type=video|stream_index=0|pts=9309|pts_time=9.309000|dts=9309|dts_time=9.309000|duration=33|duration_time=0.033000|size=1414|pos=370182|flags=__|data_hash=CRC32:e4c49a5e -packet|codec_type=audio|stream_index=1|pts=9334|pts_time=9.334000|dts=9334|dts_time=9.334000|duration=46|duration_time=0.046000|size=328|pos=371616|flags=K_|data_hash=CRC32:2a757134 -packet|codec_type=video|stream_index=0|pts=9343|pts_time=9.343000|dts=9343|dts_time=9.343000|duration=33|duration_time=0.033000|size=808|pos=371961|flags=__|data_hash=CRC32:9ec00704 -packet|codec_type=video|stream_index=0|pts=9376|pts_time=9.376000|dts=9376|dts_time=9.376000|duration=33|duration_time=0.033000|size=871|pos=372789|flags=__|data_hash=CRC32:67e02ddd -packet|codec_type=audio|stream_index=1|pts=9381|pts_time=9.381000|dts=9381|dts_time=9.381000|duration=46|duration_time=0.046000|size=334|pos=373680|flags=K_|data_hash=CRC32:3d50fa76 -packet|codec_type=video|stream_index=0|pts=9409|pts_time=9.409000|dts=9409|dts_time=9.409000|duration=33|duration_time=0.033000|size=562|pos=374031|flags=__|data_hash=CRC32:b4925536 -packet|codec_type=audio|stream_index=1|pts=9427|pts_time=9.427000|dts=9427|dts_time=9.427000|duration=46|duration_time=0.046000|size=364|pos=374613|flags=K_|data_hash=CRC32:d936a611 -packet|codec_type=video|stream_index=0|pts=9443|pts_time=9.443000|dts=9443|dts_time=9.443000|duration=33|duration_time=0.033000|size=711|pos=374994|flags=__|data_hash=CRC32:8842cf6e -packet|codec_type=audio|stream_index=1|pts=9474|pts_time=9.474000|dts=9474|dts_time=9.474000|duration=46|duration_time=0.046000|size=350|pos=375725|flags=K_|data_hash=CRC32:004fc6a5 -packet|codec_type=video|stream_index=0|pts=9476|pts_time=9.476000|dts=9476|dts_time=9.476000|duration=33|duration_time=0.033000|size=1209|pos=376092|flags=__|data_hash=CRC32:89e0866a -packet|codec_type=video|stream_index=0|pts=9510|pts_time=9.510000|dts=9510|dts_time=9.510000|duration=33|duration_time=0.033000|size=483|pos=377321|flags=__|data_hash=CRC32:952b1a6f -packet|codec_type=audio|stream_index=1|pts=9520|pts_time=9.520000|dts=9520|dts_time=9.520000|duration=46|duration_time=0.046000|size=348|pos=377824|flags=K_|data_hash=CRC32:314e7eb1 -packet|codec_type=video|stream_index=0|pts=9543|pts_time=9.543000|dts=9543|dts_time=9.543000|duration=33|duration_time=0.033000|size=422|pos=378189|flags=__|data_hash=CRC32:97ea1adf -packet|codec_type=audio|stream_index=1|pts=9567|pts_time=9.567000|dts=9567|dts_time=9.567000|duration=46|duration_time=0.046000|size=354|pos=378631|flags=K_|data_hash=CRC32:4eb4dd74 -packet|codec_type=video|stream_index=0|pts=9576|pts_time=9.576000|dts=9576|dts_time=9.576000|duration=33|duration_time=0.033000|size=533|pos=379002|flags=__|data_hash=CRC32:32282d12 -packet|codec_type=video|stream_index=0|pts=9610|pts_time=9.610000|dts=9610|dts_time=9.610000|duration=33|duration_time=0.033000|size=490|pos=379555|flags=__|data_hash=CRC32:df09aad5 -packet|codec_type=audio|stream_index=1|pts=9613|pts_time=9.613000|dts=9613|dts_time=9.613000|duration=46|duration_time=0.046000|size=358|pos=380065|flags=K_|data_hash=CRC32:032aac0d -packet|codec_type=video|stream_index=0|pts=9643|pts_time=9.643000|dts=9643|dts_time=9.643000|duration=33|duration_time=0.033000|size=972|pos=380440|flags=__|data_hash=CRC32:dfe239a5 -packet|codec_type=audio|stream_index=1|pts=9660|pts_time=9.660000|dts=9660|dts_time=9.660000|duration=46|duration_time=0.046000|size=361|pos=381432|flags=K_|data_hash=CRC32:c758edef -packet|codec_type=video|stream_index=0|pts=9676|pts_time=9.676000|dts=9676|dts_time=9.676000|duration=33|duration_time=0.033000|size=370|pos=381810|flags=__|data_hash=CRC32:18bf63af -packet|codec_type=audio|stream_index=1|pts=9706|pts_time=9.706000|dts=9706|dts_time=9.706000|duration=46|duration_time=0.046000|size=354|pos=382200|flags=K_|data_hash=CRC32:1b23fac4 -packet|codec_type=video|stream_index=0|pts=9710|pts_time=9.710000|dts=9710|dts_time=9.710000|duration=33|duration_time=0.033000|size=348|pos=382571|flags=__|data_hash=CRC32:b6ecb8fe -packet|codec_type=video|stream_index=0|pts=9743|pts_time=9.743000|dts=9743|dts_time=9.743000|duration=33|duration_time=0.033000|size=449|pos=382939|flags=__|data_hash=CRC32:99ec4250 -packet|codec_type=audio|stream_index=1|pts=9752|pts_time=9.752000|dts=9752|dts_time=9.752000|duration=46|duration_time=0.046000|size=369|pos=383408|flags=K_|data_hash=CRC32:25045152 -packet|codec_type=video|stream_index=0|pts=9776|pts_time=9.776000|dts=9776|dts_time=9.776000|duration=33|duration_time=0.033000|size=447|pos=383794|flags=__|data_hash=CRC32:53378d54 -packet|codec_type=audio|stream_index=1|pts=9799|pts_time=9.799000|dts=9799|dts_time=9.799000|duration=46|duration_time=0.046000|size=359|pos=384261|flags=K_|data_hash=CRC32:387d406d -packet|codec_type=video|stream_index=0|pts=9810|pts_time=9.810000|dts=9810|dts_time=9.810000|duration=33|duration_time=0.033000|size=414|pos=384637|flags=__|data_hash=CRC32:ab76fa07 -packet|codec_type=video|stream_index=0|pts=9843|pts_time=9.843000|dts=9843|dts_time=9.843000|duration=33|duration_time=0.033000|size=467|pos=385071|flags=__|data_hash=CRC32:e0d0f23c -packet|codec_type=audio|stream_index=1|pts=9845|pts_time=9.845000|dts=9845|dts_time=9.845000|duration=46|duration_time=0.046000|size=348|pos=385558|flags=K_|data_hash=CRC32:13f83e98 -packet|codec_type=video|stream_index=0|pts=9877|pts_time=9.877000|dts=9877|dts_time=9.877000|duration=33|duration_time=0.033000|size=890|pos=385923|flags=__|data_hash=CRC32:ef8759d9 -packet|codec_type=audio|stream_index=1|pts=9892|pts_time=9.892000|dts=9892|dts_time=9.892000|duration=46|duration_time=0.046000|size=346|pos=386833|flags=K_|data_hash=CRC32:4c0da0e0 -packet|codec_type=video|stream_index=0|pts=9910|pts_time=9.910000|dts=9910|dts_time=9.910000|duration=33|duration_time=0.033000|size=387|pos=387196|flags=__|data_hash=CRC32:9e2b0fa2 -packet|codec_type=audio|stream_index=1|pts=9938|pts_time=9.938000|dts=9938|dts_time=9.938000|duration=46|duration_time=0.046000|size=350|pos=387603|flags=K_|data_hash=CRC32:7b52e49d -packet|codec_type=video|stream_index=0|pts=9943|pts_time=9.943000|dts=9943|dts_time=9.943000|duration=33|duration_time=0.033000|size=351|pos=387970|flags=__|data_hash=CRC32:d1874a20 -packet|codec_type=video|stream_index=0|pts=9977|pts_time=9.977000|dts=9977|dts_time=9.977000|duration=33|duration_time=0.033000|size=720|pos=388341|flags=__|data_hash=CRC32:1dbb852e -packet|codec_type=audio|stream_index=1|pts=9985|pts_time=9.985000|dts=9985|dts_time=9.985000|duration=46|duration_time=0.046000|size=359|pos=389081|flags=K_|data_hash=CRC32:6efd45ba -packet|codec_type=video|stream_index=0|pts=10010|pts_time=10.010000|dts=10010|dts_time=10.010000|duration=33|duration_time=0.033000|size=855|pos=389457|flags=__|data_hash=CRC32:9266ff7a -packet|codec_type=audio|stream_index=1|pts=10031|pts_time=10.031000|dts=10031|dts_time=10.031000|duration=46|duration_time=0.046000|size=355|pos=390332|flags=K_|data_hash=CRC32:58c387cc -packet|codec_type=video|stream_index=0|pts=10043|pts_time=10.043000|dts=10043|dts_time=10.043000|duration=33|duration_time=0.033000|size=742|pos=390704|flags=__|data_hash=CRC32:b48053b8 -packet|codec_type=audio|stream_index=1|pts=10077|pts_time=10.077000|dts=10077|dts_time=10.077000|duration=46|duration_time=0.046000|size=320|pos=391466|flags=K_|data_hash=CRC32:115fa28d -packet|codec_type=video|stream_index=0|pts=10077|pts_time=10.077000|dts=10077|dts_time=10.077000|duration=33|duration_time=0.033000|size=835|pos=391803|flags=__|data_hash=CRC32:5e06bb03 -packet|codec_type=video|stream_index=0|pts=10110|pts_time=10.110000|dts=10110|dts_time=10.110000|duration=33|duration_time=0.033000|size=1610|pos=392658|flags=__|data_hash=CRC32:fafab2d1 -packet|codec_type=audio|stream_index=1|pts=10124|pts_time=10.124000|dts=10124|dts_time=10.124000|duration=46|duration_time=0.046000|size=348|pos=394288|flags=K_|data_hash=CRC32:92d59397 -packet|codec_type=video|stream_index=0|pts=10143|pts_time=10.143000|dts=10143|dts_time=10.143000|duration=33|duration_time=0.033000|size=637|pos=394653|flags=__|data_hash=CRC32:6e59b37f -packet|codec_type=audio|stream_index=1|pts=10170|pts_time=10.170000|dts=10170|dts_time=10.170000|duration=46|duration_time=0.046000|size=370|pos=395310|flags=K_|data_hash=CRC32:3ea66fa9 -packet|codec_type=video|stream_index=0|pts=10177|pts_time=10.177000|dts=10177|dts_time=10.177000|duration=33|duration_time=0.033000|size=614|pos=395697|flags=__|data_hash=CRC32:4f7f5e8e -packet|codec_type=video|stream_index=0|pts=10210|pts_time=10.210000|dts=10210|dts_time=10.210000|duration=33|duration_time=0.033000|size=1143|pos=396331|flags=__|data_hash=CRC32:d877789c -packet|codec_type=audio|stream_index=1|pts=10217|pts_time=10.217000|dts=10217|dts_time=10.217000|duration=46|duration_time=0.046000|size=353|pos=397494|flags=K_|data_hash=CRC32:22050bd1 -packet|codec_type=video|stream_index=0|pts=10244|pts_time=10.244000|dts=10244|dts_time=10.244000|duration=33|duration_time=0.033000|size=1262|pos=397864|flags=__|data_hash=CRC32:6d88aa4f -packet|codec_type=audio|stream_index=1|pts=10263|pts_time=10.263000|dts=10263|dts_time=10.263000|duration=46|duration_time=0.046000|size=367|pos=399146|flags=K_|data_hash=CRC32:077e57a2 -packet|codec_type=video|stream_index=0|pts=10277|pts_time=10.277000|dts=10277|dts_time=10.277000|duration=33|duration_time=0.033000|size=1618|pos=399530|flags=__|data_hash=CRC32:175e29a2 -packet|codec_type=audio|stream_index=1|pts=10310|pts_time=10.310000|dts=10310|dts_time=10.310000|duration=46|duration_time=0.046000|size=350|pos=401168|flags=K_|data_hash=CRC32:346c722e -packet|codec_type=video|stream_index=0|pts=10310|pts_time=10.310000|dts=10310|dts_time=10.310000|duration=33|duration_time=0.033000|size=2345|pos=401535|flags=__|data_hash=CRC32:ccf488bd -packet|codec_type=video|stream_index=0|pts=10344|pts_time=10.344000|dts=10344|dts_time=10.344000|duration=33|duration_time=0.033000|size=1029|pos=403900|flags=__|data_hash=CRC32:4b3a69da -packet|codec_type=audio|stream_index=1|pts=10356|pts_time=10.356000|dts=10356|dts_time=10.356000|duration=46|duration_time=0.046000|size=353|pos=404949|flags=K_|data_hash=CRC32:de07f5ea -packet|codec_type=video|stream_index=0|pts=10377|pts_time=10.377000|dts=10377|dts_time=10.377000|duration=33|duration_time=0.033000|size=932|pos=405319|flags=__|data_hash=CRC32:dfb7b52c -packet|codec_type=audio|stream_index=1|pts=10403|pts_time=10.403000|dts=10403|dts_time=10.403000|duration=46|duration_time=0.046000|size=336|pos=406271|flags=K_|data_hash=CRC32:2dbed9ee -packet|codec_type=video|stream_index=0|pts=10410|pts_time=10.410000|dts=10410|dts_time=10.410000|duration=33|duration_time=0.033000|size=1688|pos=406624|flags=__|data_hash=CRC32:6fc6be0f -packet|codec_type=video|stream_index=0|pts=10444|pts_time=10.444000|dts=10444|dts_time=10.444000|duration=33|duration_time=0.033000|size=4159|pos=408332|flags=K_|data_hash=CRC32:6988ae22 -packet|codec_type=audio|stream_index=1|pts=10449|pts_time=10.449000|dts=10449|dts_time=10.449000|duration=46|duration_time=0.046000|size=334|pos=412511|flags=K_|data_hash=CRC32:7b903b6f -packet|codec_type=video|stream_index=0|pts=10477|pts_time=10.477000|dts=10477|dts_time=10.477000|duration=33|duration_time=0.033000|size=2039|pos=412862|flags=__|data_hash=CRC32:c0cf0abd -packet|codec_type=audio|stream_index=1|pts=10495|pts_time=10.495000|dts=10495|dts_time=10.495000|duration=46|duration_time=0.046000|size=358|pos=414921|flags=K_|data_hash=CRC32:2e46c79f -packet|codec_type=video|stream_index=0|pts=10511|pts_time=10.511000|dts=10511|dts_time=10.511000|duration=33|duration_time=0.033000|size=614|pos=415296|flags=__|data_hash=CRC32:682066fb -packet|codec_type=audio|stream_index=1|pts=10542|pts_time=10.542000|dts=10542|dts_time=10.542000|duration=46|duration_time=0.046000|size=344|pos=415930|flags=K_|data_hash=CRC32:037d4b43 -packet|codec_type=video|stream_index=0|pts=10544|pts_time=10.544000|dts=10544|dts_time=10.544000|duration=33|duration_time=0.033000|size=1749|pos=416291|flags=__|data_hash=CRC32:09ab2b77 -packet|codec_type=video|stream_index=0|pts=10577|pts_time=10.577000|dts=10577|dts_time=10.577000|duration=33|duration_time=0.033000|size=2609|pos=418060|flags=__|data_hash=CRC32:3630dc54 -packet|codec_type=audio|stream_index=1|pts=10588|pts_time=10.588000|dts=10588|dts_time=10.588000|duration=46|duration_time=0.046000|size=344|pos=420689|flags=K_|data_hash=CRC32:73dfce6a -packet|codec_type=video|stream_index=0|pts=10611|pts_time=10.611000|dts=10611|dts_time=10.611000|duration=33|duration_time=0.033000|size=689|pos=421050|flags=__|data_hash=CRC32:6700928b -packet|codec_type=audio|stream_index=1|pts=10635|pts_time=10.635000|dts=10635|dts_time=10.635000|duration=46|duration_time=0.046000|size=356|pos=421759|flags=K_|data_hash=CRC32:5596b779 -packet|codec_type=video|stream_index=0|pts=10644|pts_time=10.644000|dts=10644|dts_time=10.644000|duration=33|duration_time=0.033000|size=2259|pos=422132|flags=__|data_hash=CRC32:264fcb3f -packet|codec_type=video|stream_index=0|pts=10677|pts_time=10.677000|dts=10677|dts_time=10.677000|duration=33|duration_time=0.033000|size=2494|pos=424411|flags=__|data_hash=CRC32:67753c81 -packet|codec_type=audio|stream_index=1|pts=10681|pts_time=10.681000|dts=10681|dts_time=10.681000|duration=46|duration_time=0.046000|size=354|pos=426925|flags=K_|data_hash=CRC32:3d7b1c0d -packet|codec_type=video|stream_index=0|pts=10711|pts_time=10.711000|dts=10711|dts_time=10.711000|duration=33|duration_time=0.033000|size=2457|pos=427296|flags=__|data_hash=CRC32:f02a3205 -packet|codec_type=audio|stream_index=1|pts=10728|pts_time=10.728000|dts=10728|dts_time=10.728000|duration=46|duration_time=0.046000|size=330|pos=429773|flags=K_|data_hash=CRC32:f9310cfe -packet|codec_type=video|stream_index=0|pts=10744|pts_time=10.744000|dts=10744|dts_time=10.744000|duration=33|duration_time=0.033000|size=2476|pos=430120|flags=__|data_hash=CRC32:eac06b3e -packet|codec_type=audio|stream_index=1|pts=10774|pts_time=10.774000|dts=10774|dts_time=10.774000|duration=46|duration_time=0.046000|size=328|pos=432616|flags=K_|data_hash=CRC32:9618f3ab -packet|codec_type=video|stream_index=0|pts=10777|pts_time=10.777000|dts=10777|dts_time=10.777000|duration=33|duration_time=0.033000|size=2560|pos=432961|flags=__|data_hash=CRC32:4c277ba1 -packet|codec_type=video|stream_index=0|pts=10811|pts_time=10.811000|dts=10811|dts_time=10.811000|duration=33|duration_time=0.033000|size=2679|pos=435541|flags=__|data_hash=CRC32:e070caf2 -packet|codec_type=audio|stream_index=1|pts=10820|pts_time=10.820000|dts=10820|dts_time=10.820000|duration=46|duration_time=0.046000|size=351|pos=438240|flags=K_|data_hash=CRC32:19bb5b6c -packet|codec_type=video|stream_index=0|pts=10844|pts_time=10.844000|dts=10844|dts_time=10.844000|duration=33|duration_time=0.033000|size=2795|pos=438608|flags=__|data_hash=CRC32:6642234c -packet|codec_type=audio|stream_index=1|pts=10867|pts_time=10.867000|dts=10867|dts_time=10.867000|duration=46|duration_time=0.046000|size=364|pos=441423|flags=K_|data_hash=CRC32:4dbd8e39 -packet|codec_type=video|stream_index=0|pts=10878|pts_time=10.878000|dts=10878|dts_time=10.878000|duration=33|duration_time=0.033000|size=2927|pos=441804|flags=__|data_hash=CRC32:0c7d6e1b -packet|codec_type=video|stream_index=0|pts=10911|pts_time=10.911000|dts=10911|dts_time=10.911000|duration=33|duration_time=0.033000|size=2437|pos=444751|flags=__|data_hash=CRC32:29100f02 -packet|codec_type=audio|stream_index=1|pts=10913|pts_time=10.913000|dts=10913|dts_time=10.913000|duration=46|duration_time=0.046000|size=365|pos=447208|flags=K_|data_hash=CRC32:f4732e1d -packet|codec_type=video|stream_index=0|pts=10944|pts_time=10.944000|dts=10944|dts_time=10.944000|duration=33|duration_time=0.033000|size=2663|pos=447590|flags=__|data_hash=CRC32:42a7b089 -packet|codec_type=audio|stream_index=1|pts=10960|pts_time=10.960000|dts=10960|dts_time=10.960000|duration=46|duration_time=0.046000|size=341|pos=450273|flags=K_|data_hash=CRC32:270d8e2f -packet|codec_type=video|stream_index=0|pts=10978|pts_time=10.978000|dts=10978|dts_time=10.978000|duration=33|duration_time=0.033000|size=2688|pos=450631|flags=__|data_hash=CRC32:e6b1e69d -packet|codec_type=audio|stream_index=1|pts=11006|pts_time=11.006000|dts=11006|dts_time=11.006000|duration=46|duration_time=0.046000|size=330|pos=453339|flags=K_|data_hash=CRC32:ffedf602 -packet|codec_type=video|stream_index=0|pts=11011|pts_time=11.011000|dts=11011|dts_time=11.011000|duration=33|duration_time=0.033000|size=2727|pos=453686|flags=__|data_hash=CRC32:0e15158e -packet|codec_type=video|stream_index=0|pts=11044|pts_time=11.044000|dts=11044|dts_time=11.044000|duration=33|duration_time=0.033000|size=2747|pos=456433|flags=__|data_hash=CRC32:5456aa57 -packet|codec_type=audio|stream_index=1|pts=11053|pts_time=11.053000|dts=11053|dts_time=11.053000|duration=46|duration_time=0.046000|size=358|pos=459200|flags=K_|data_hash=CRC32:cac56902 -packet|codec_type=video|stream_index=0|pts=11078|pts_time=11.078000|dts=11078|dts_time=11.078000|duration=33|duration_time=0.033000|size=3602|pos=459575|flags=__|data_hash=CRC32:a332e21c -packet|codec_type=audio|stream_index=1|pts=11099|pts_time=11.099000|dts=11099|dts_time=11.099000|duration=46|duration_time=0.046000|size=367|pos=463197|flags=K_|data_hash=CRC32:6e7f4f1d -packet|codec_type=video|stream_index=0|pts=11111|pts_time=11.111000|dts=11111|dts_time=11.111000|duration=33|duration_time=0.033000|size=1334|pos=463581|flags=__|data_hash=CRC32:5c4e2f6d -packet|codec_type=video|stream_index=0|pts=11144|pts_time=11.144000|dts=11144|dts_time=11.144000|duration=33|duration_time=0.033000|size=2562|pos=464935|flags=__|data_hash=CRC32:ebc7e2ca -packet|codec_type=audio|stream_index=1|pts=11146|pts_time=11.146000|dts=11146|dts_time=11.146000|duration=46|duration_time=0.046000|size=353|pos=467517|flags=K_|data_hash=CRC32:cfe498a5 -packet|codec_type=video|stream_index=0|pts=11178|pts_time=11.178000|dts=11178|dts_time=11.178000|duration=33|duration_time=0.033000|size=2917|pos=467887|flags=__|data_hash=CRC32:77f836e3 -packet|codec_type=audio|stream_index=1|pts=11192|pts_time=11.192000|dts=11192|dts_time=11.192000|duration=46|duration_time=0.046000|size=336|pos=470824|flags=K_|data_hash=CRC32:9ee13031 -packet|codec_type=video|stream_index=0|pts=11211|pts_time=11.211000|dts=11211|dts_time=11.211000|duration=33|duration_time=0.033000|size=2788|pos=471177|flags=__|data_hash=CRC32:79aa2cce -packet|codec_type=audio|stream_index=1|pts=11238|pts_time=11.238000|dts=11238|dts_time=11.238000|duration=46|duration_time=0.046000|size=329|pos=473985|flags=K_|data_hash=CRC32:86c3f096 -packet|codec_type=video|stream_index=0|pts=11245|pts_time=11.245000|dts=11245|dts_time=11.245000|duration=33|duration_time=0.033000|size=2876|pos=474331|flags=__|data_hash=CRC32:f71a01f7 -packet|codec_type=video|stream_index=0|pts=11278|pts_time=11.278000|dts=11278|dts_time=11.278000|duration=33|duration_time=0.033000|size=2782|pos=477227|flags=__|data_hash=CRC32:66c68a76 -packet|codec_type=audio|stream_index=1|pts=11285|pts_time=11.285000|dts=11285|dts_time=11.285000|duration=46|duration_time=0.046000|size=323|pos=480029|flags=K_|data_hash=CRC32:1e715e07 -packet|codec_type=video|stream_index=0|pts=11311|pts_time=11.311000|dts=11311|dts_time=11.311000|duration=33|duration_time=0.033000|size=2393|pos=480369|flags=__|data_hash=CRC32:ca824913 -packet|codec_type=audio|stream_index=1|pts=11331|pts_time=11.331000|dts=11331|dts_time=11.331000|duration=46|duration_time=0.046000|size=328|pos=482782|flags=K_|data_hash=CRC32:57b8fe27 -packet|codec_type=video|stream_index=0|pts=11345|pts_time=11.345000|dts=11345|dts_time=11.345000|duration=33|duration_time=0.033000|size=2773|pos=483127|flags=__|data_hash=CRC32:6bc9c9d7 -packet|codec_type=audio|stream_index=1|pts=11378|pts_time=11.378000|dts=11378|dts_time=11.378000|duration=46|duration_time=0.046000|size=345|pos=485920|flags=K_|data_hash=CRC32:95f244d4 -packet|codec_type=video|stream_index=0|pts=11378|pts_time=11.378000|dts=11378|dts_time=11.378000|duration=33|duration_time=0.033000|size=2972|pos=486282|flags=__|data_hash=CRC32:9fdef1d9 -packet|codec_type=video|stream_index=0|pts=11411|pts_time=11.411000|dts=11411|dts_time=11.411000|duration=33|duration_time=0.033000|size=3480|pos=489274|flags=__|data_hash=CRC32:977f9784 -packet|codec_type=audio|stream_index=1|pts=11424|pts_time=11.424000|dts=11424|dts_time=11.424000|duration=46|duration_time=0.046000|size=345|pos=492774|flags=K_|data_hash=CRC32:9c69a0dc -packet|codec_type=video|stream_index=0|pts=11445|pts_time=11.445000|dts=11445|dts_time=11.445000|duration=33|duration_time=0.033000|size=1078|pos=493136|flags=__|data_hash=CRC32:4a479a66 -packet|codec_type=audio|stream_index=1|pts=11471|pts_time=11.471000|dts=11471|dts_time=11.471000|duration=46|duration_time=0.046000|size=349|pos=494234|flags=K_|data_hash=CRC32:0fcb70ef -packet|codec_type=video|stream_index=0|pts=11478|pts_time=11.478000|dts=11478|dts_time=11.478000|duration=33|duration_time=0.033000|size=3385|pos=494600|flags=__|data_hash=CRC32:f1d76112 -packet|codec_type=video|stream_index=0|pts=11512|pts_time=11.512000|dts=11512|dts_time=11.512000|duration=33|duration_time=0.033000|size=1408|pos=498005|flags=__|data_hash=CRC32:12165420 -packet|codec_type=audio|stream_index=1|pts=11517|pts_time=11.517000|dts=11517|dts_time=11.517000|duration=46|duration_time=0.046000|size=340|pos=499433|flags=K_|data_hash=CRC32:e867c459 -packet|codec_type=video|stream_index=0|pts=11545|pts_time=11.545000|dts=11545|dts_time=11.545000|duration=33|duration_time=0.033000|size=2543|pos=499790|flags=__|data_hash=CRC32:d3803831 -packet|codec_type=audio|stream_index=1|pts=11564|pts_time=11.564000|dts=11564|dts_time=11.564000|duration=46|duration_time=0.046000|size=352|pos=502353|flags=K_|data_hash=CRC32:029632be -packet|codec_type=video|stream_index=0|pts=11578|pts_time=11.578000|dts=11578|dts_time=11.578000|duration=33|duration_time=0.033000|size=3609|pos=502722|flags=__|data_hash=CRC32:ebd09926 -packet|codec_type=audio|stream_index=1|pts=11610|pts_time=11.610000|dts=11610|dts_time=11.610000|duration=46|duration_time=0.046000|size=345|pos=506351|flags=K_|data_hash=CRC32:8374b7c9 -packet|codec_type=video|stream_index=0|pts=11612|pts_time=11.612000|dts=11612|dts_time=11.612000|duration=33|duration_time=0.033000|size=1078|pos=506713|flags=__|data_hash=CRC32:96db1ff7 -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 +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 +packet|codec_type=video|stream_index=0|pts=67|pts_time=0.067000|dts=67|dts_time=0.067000|duration=33|duration_time=0.033000|size=14|pos=3560|flags=___|data_hash=CRC32:0b3c3ab4 +packet|codec_type=audio|stream_index=1|pts=93|pts_time=0.093000|dts=93|dts_time=0.093000|duration=46|duration_time=0.046000|size=9|pos=3594|flags=K__|data_hash=CRC32:42c079c5 +packet|codec_type=video|stream_index=0|pts=100|pts_time=0.100000|dts=100|dts_time=0.100000|duration=33|duration_time=0.033000|size=14|pos=3620|flags=___|data_hash=CRC32:280ad88b +packet|codec_type=video|stream_index=0|pts=133|pts_time=0.133000|dts=133|dts_time=0.133000|duration=33|duration_time=0.033000|size=117|pos=3654|flags=___|data_hash=CRC32:376f2497 +packet|codec_type=audio|stream_index=1|pts=139|pts_time=0.139000|dts=139|dts_time=0.139000|duration=46|duration_time=0.046000|size=89|pos=3791|flags=K__|data_hash=CRC32:548db44a +packet|codec_type=video|stream_index=0|pts=167|pts_time=0.167000|dts=167|dts_time=0.167000|duration=33|duration_time=0.033000|size=14|pos=3897|flags=___|data_hash=CRC32:0811a146 +packet|codec_type=audio|stream_index=1|pts=186|pts_time=0.186000|dts=186|dts_time=0.186000|duration=46|duration_time=0.046000|size=155|pos=3931|flags=K__|data_hash=CRC32:a7111723 +packet|codec_type=video|stream_index=0|pts=200|pts_time=0.200000|dts=200|dts_time=0.200000|duration=33|duration_time=0.033000|size=14|pos=4103|flags=___|data_hash=CRC32:3bfeef21 +packet|codec_type=audio|stream_index=1|pts=232|pts_time=0.232000|dts=232|dts_time=0.232000|duration=46|duration_time=0.046000|size=281|pos=4137|flags=K__|data_hash=CRC32:27f537aa +packet|codec_type=video|stream_index=0|pts=234|pts_time=0.234000|dts=234|dts_time=0.234000|duration=33|duration_time=0.033000|size=117|pos=4435|flags=___|data_hash=CRC32:2bc5eba8 +packet|codec_type=video|stream_index=0|pts=267|pts_time=0.267000|dts=267|dts_time=0.267000|duration=33|duration_time=0.033000|size=14|pos=4572|flags=___|data_hash=CRC32:0033671d +packet|codec_type=audio|stream_index=1|pts=279|pts_time=0.279000|dts=279|dts_time=0.279000|duration=46|duration_time=0.046000|size=548|pos=4606|flags=K__|data_hash=CRC32:7ab3c7cb +packet|codec_type=video|stream_index=0|pts=300|pts_time=0.300000|dts=300|dts_time=0.300000|duration=33|duration_time=0.033000|size=14|pos=5171|flags=___|data_hash=CRC32:dfb4f951 +packet|codec_type=audio|stream_index=1|pts=325|pts_time=0.325000|dts=325|dts_time=0.325000|duration=46|duration_time=0.046000|size=472|pos=5205|flags=K__|data_hash=CRC32:d10a7849 +packet|codec_type=video|stream_index=0|pts=334|pts_time=0.334000|dts=334|dts_time=0.334000|duration=33|duration_time=0.033000|size=117|pos=5694|flags=___|data_hash=CRC32:97814fc1 +packet|codec_type=video|stream_index=0|pts=367|pts_time=0.367000|dts=367|dts_time=0.367000|duration=33|duration_time=0.033000|size=14|pos=5831|flags=___|data_hash=CRC32:3c206b65 +packet|codec_type=audio|stream_index=1|pts=372|pts_time=0.372000|dts=372|dts_time=0.372000|duration=46|duration_time=0.046000|size=489|pos=5865|flags=K__|data_hash=CRC32:4d3f1f03 +packet|codec_type=video|stream_index=0|pts=400|pts_time=0.400000|dts=400|dts_time=0.400000|duration=33|duration_time=0.033000|size=14|pos=6371|flags=___|data_hash=CRC32:0fcf2502 +packet|codec_type=audio|stream_index=1|pts=418|pts_time=0.418000|dts=418|dts_time=0.418000|duration=46|duration_time=0.046000|size=357|pos=6405|flags=K__|data_hash=CRC32:eccea9c1 +packet|codec_type=video|stream_index=0|pts=434|pts_time=0.434000|dts=434|dts_time=0.434000|duration=33|duration_time=0.033000|size=207|pos=6779|flags=___|data_hash=CRC32:86bab8df +packet|codec_type=audio|stream_index=1|pts=464|pts_time=0.464000|dts=464|dts_time=0.464000|duration=46|duration_time=0.046000|size=262|pos=7006|flags=K__|data_hash=CRC32:50b0e3b7 +packet|codec_type=video|stream_index=0|pts=467|pts_time=0.467000|dts=467|dts_time=0.467000|duration=33|duration_time=0.033000|size=14|pos=7285|flags=___|data_hash=CRC32:8704a589 +packet|codec_type=video|stream_index=0|pts=501|pts_time=0.501000|dts=501|dts_time=0.501000|duration=33|duration_time=0.033000|size=14|pos=7319|flags=___|data_hash=CRC32:d3357720 +packet|codec_type=audio|stream_index=1|pts=511|pts_time=0.511000|dts=511|dts_time=0.511000|duration=46|duration_time=0.046000|size=294|pos=7353|flags=K__|data_hash=CRC32:805a1f22 +packet|codec_type=video|stream_index=0|pts=534|pts_time=0.534000|dts=534|dts_time=0.534000|duration=33|duration_time=0.033000|size=179|pos=7664|flags=___|data_hash=CRC32:5b61c9b6 +packet|codec_type=audio|stream_index=1|pts=557|pts_time=0.557000|dts=557|dts_time=0.557000|duration=46|duration_time=0.046000|size=204|pos=7863|flags=K__|data_hash=CRC32:7f4a9c90 +packet|codec_type=video|stream_index=0|pts=567|pts_time=0.567000|dts=567|dts_time=0.567000|duration=33|duration_time=0.033000|size=14|pos=8084|flags=___|data_hash=CRC32:44067395 +packet|codec_type=video|stream_index=0|pts=601|pts_time=0.601000|dts=601|dts_time=0.601000|duration=33|duration_time=0.033000|size=14|pos=8118|flags=___|data_hash=CRC32:00ee0d64 +packet|codec_type=audio|stream_index=1|pts=604|pts_time=0.604000|dts=604|dts_time=0.604000|duration=46|duration_time=0.046000|size=275|pos=8152|flags=K__|data_hash=CRC32:d04e94cd +packet|codec_type=video|stream_index=0|pts=634|pts_time=0.634000|dts=634|dts_time=0.634000|duration=33|duration_time=0.033000|size=32|pos=8444|flags=___|data_hash=CRC32:41c4e3cb +packet|codec_type=audio|stream_index=1|pts=650|pts_time=0.650000|dts=650|dts_time=0.650000|duration=46|duration_time=0.046000|size=309|pos=8496|flags=K__|data_hash=CRC32:c3b4718d +packet|codec_type=video|stream_index=0|pts=667|pts_time=0.667000|dts=667|dts_time=0.667000|duration=33|duration_time=0.033000|size=30|pos=8822|flags=___|data_hash=CRC32:9894f2b3 +packet|codec_type=audio|stream_index=1|pts=697|pts_time=0.697000|dts=697|dts_time=0.697000|duration=46|duration_time=0.046000|size=280|pos=8872|flags=K__|data_hash=CRC32:683aa168 +packet|codec_type=video|stream_index=0|pts=701|pts_time=0.701000|dts=701|dts_time=0.701000|duration=33|duration_time=0.033000|size=16|pos=9169|flags=___|data_hash=CRC32:33031360 +packet|codec_type=video|stream_index=0|pts=734|pts_time=0.734000|dts=734|dts_time=0.734000|duration=33|duration_time=0.033000|size=33|pos=9205|flags=___|data_hash=CRC32:4cb9408b +packet|codec_type=audio|stream_index=1|pts=743|pts_time=0.743000|dts=743|dts_time=0.743000|duration=46|duration_time=0.046000|size=106|pos=9258|flags=K__|data_hash=CRC32:d3693544 +packet|codec_type=video|stream_index=0|pts=767|pts_time=0.767000|dts=767|dts_time=0.767000|duration=33|duration_time=0.033000|size=16|pos=9381|flags=___|data_hash=CRC32:ebca8d2b +packet|codec_type=audio|stream_index=1|pts=789|pts_time=0.789000|dts=789|dts_time=0.789000|duration=46|duration_time=0.046000|size=133|pos=9417|flags=K__|data_hash=CRC32:848dc228 +packet|codec_type=video|stream_index=0|pts=801|pts_time=0.801000|dts=801|dts_time=0.801000|duration=33|duration_time=0.033000|size=16|pos=9567|flags=___|data_hash=CRC32:9d238d80 +packet|codec_type=video|stream_index=0|pts=834|pts_time=0.834000|dts=834|dts_time=0.834000|duration=33|duration_time=0.033000|size=22|pos=9603|flags=___|data_hash=CRC32:d606882e +packet|codec_type=audio|stream_index=1|pts=836|pts_time=0.836000|dts=836|dts_time=0.836000|duration=46|duration_time=0.046000|size=380|pos=9645|flags=K__|data_hash=CRC32:70b58912 +packet|codec_type=video|stream_index=0|pts=868|pts_time=0.868000|dts=868|dts_time=0.868000|duration=33|duration_time=0.033000|size=14|pos=10042|flags=___|data_hash=CRC32:39d914b1 +packet|codec_type=audio|stream_index=1|pts=882|pts_time=0.882000|dts=882|dts_time=0.882000|duration=46|duration_time=0.046000|size=378|pos=10076|flags=K__|data_hash=CRC32:7eaf35cb +packet|codec_type=video|stream_index=0|pts=901|pts_time=0.901000|dts=901|dts_time=0.901000|duration=33|duration_time=0.033000|size=14|pos=10471|flags=___|data_hash=CRC32:1aeff68e +packet|codec_type=audio|stream_index=1|pts=929|pts_time=0.929000|dts=929|dts_time=0.929000|duration=46|duration_time=0.046000|size=108|pos=10505|flags=K__|data_hash=CRC32:8bf2b703 +packet|codec_type=video|stream_index=0|pts=934|pts_time=0.934000|dts=934|dts_time=0.934000|duration=33|duration_time=0.033000|size=55|pos=10630|flags=___|data_hash=CRC32:26064135 +packet|codec_type=video|stream_index=0|pts=968|pts_time=0.968000|dts=968|dts_time=0.968000|duration=33|duration_time=0.033000|size=14|pos=10705|flags=___|data_hash=CRC32:abb369c4 +packet|codec_type=audio|stream_index=1|pts=975|pts_time=0.975000|dts=975|dts_time=0.975000|duration=46|duration_time=0.046000|size=279|pos=10739|flags=K__|data_hash=CRC32:6bff85a8 +packet|codec_type=video|stream_index=0|pts=1001|pts_time=1.001000|dts=1001|dts_time=1.001000|duration=33|duration_time=0.033000|size=14|pos=11035|flags=___|data_hash=CRC32:1af77344 +packet|codec_type=audio|stream_index=1|pts=1022|pts_time=1.022000|dts=1022|dts_time=1.022000|duration=46|duration_time=0.046000|size=134|pos=11069|flags=K__|data_hash=CRC32:349e2a8c +packet|codec_type=video|stream_index=0|pts=1034|pts_time=1.034000|dts=1034|dts_time=1.034000|duration=33|duration_time=0.033000|size=58|pos=11220|flags=___|data_hash=CRC32:8b2e7991 +packet|codec_type=audio|stream_index=1|pts=1068|pts_time=1.068000|dts=1068|dts_time=1.068000|duration=46|duration_time=0.046000|size=162|pos=11298|flags=K__|data_hash=CRC32:f64effd2 +packet|codec_type=video|stream_index=0|pts=1068|pts_time=1.068000|dts=1068|dts_time=1.068000|duration=33|duration_time=0.033000|size=39|pos=11477|flags=___|data_hash=CRC32:0ae377c8 +packet|codec_type=video|stream_index=0|pts=1101|pts_time=1.101000|dts=1101|dts_time=1.101000|duration=33|duration_time=0.033000|size=48|pos=11536|flags=___|data_hash=CRC32:1bc6d22d +packet|codec_type=audio|stream_index=1|pts=1115|pts_time=1.115000|dts=1115|dts_time=1.115000|duration=46|duration_time=0.046000|size=46|pos=11604|flags=K__|data_hash=CRC32:3dfbc696 +packet|codec_type=video|stream_index=0|pts=1134|pts_time=1.134000|dts=1134|dts_time=1.134000|duration=33|duration_time=0.033000|size=319|pos=11667|flags=___|data_hash=CRC32:39d9a172 +packet|codec_type=audio|stream_index=1|pts=1161|pts_time=1.161000|dts=1161|dts_time=1.161000|duration=46|duration_time=0.046000|size=150|pos=12006|flags=K__|data_hash=CRC32:eec82a0f +packet|codec_type=video|stream_index=0|pts=1168|pts_time=1.168000|dts=1168|dts_time=1.168000|duration=33|duration_time=0.033000|size=204|pos=12173|flags=___|data_hash=CRC32:96683004 +packet|codec_type=video|stream_index=0|pts=1201|pts_time=1.201000|dts=1201|dts_time=1.201000|duration=33|duration_time=0.033000|size=240|pos=12397|flags=___|data_hash=CRC32:65f1defa +packet|codec_type=audio|stream_index=1|pts=1207|pts_time=1.207000|dts=1207|dts_time=1.207000|duration=46|duration_time=0.046000|size=427|pos=12657|flags=K__|data_hash=CRC32:e8361847 +packet|codec_type=video|stream_index=0|pts=1235|pts_time=1.235000|dts=1235|dts_time=1.235000|duration=33|duration_time=0.033000|size=305|pos=13101|flags=___|data_hash=CRC32:12e13d9c +packet|codec_type=audio|stream_index=1|pts=1254|pts_time=1.254000|dts=1254|dts_time=1.254000|duration=46|duration_time=0.046000|size=616|pos=13426|flags=K__|data_hash=CRC32:65e6a966 +packet|codec_type=video|stream_index=0|pts=1268|pts_time=1.268000|dts=1268|dts_time=1.268000|duration=33|duration_time=0.033000|size=217|pos=14059|flags=___|data_hash=CRC32:741596bf +packet|codec_type=audio|stream_index=1|pts=1300|pts_time=1.300000|dts=1300|dts_time=1.300000|duration=46|duration_time=0.046000|size=736|pos=14296|flags=K__|data_hash=CRC32:bf178137 +packet|codec_type=video|stream_index=0|pts=1301|pts_time=1.301000|dts=1301|dts_time=1.301000|duration=33|duration_time=0.033000|size=236|pos=15049|flags=___|data_hash=CRC32:e857a41f +packet|codec_type=video|stream_index=0|pts=1335|pts_time=1.335000|dts=1335|dts_time=1.335000|duration=33|duration_time=0.033000|size=222|pos=15305|flags=___|data_hash=CRC32:02e5c508 +packet|codec_type=audio|stream_index=1|pts=1347|pts_time=1.347000|dts=1347|dts_time=1.347000|duration=46|duration_time=0.046000|size=708|pos=15547|flags=K__|data_hash=CRC32:cd4df572 +packet|codec_type=video|stream_index=0|pts=1368|pts_time=1.368000|dts=1368|dts_time=1.368000|duration=33|duration_time=0.033000|size=1295|pos=16272|flags=K__|data_hash=CRC32:65d347c4 +packet|codec_type=audio|stream_index=1|pts=1393|pts_time=1.393000|dts=1393|dts_time=1.393000|duration=46|duration_time=0.046000|size=717|pos=17587|flags=K__|data_hash=CRC32:72de4551 +packet|codec_type=video|stream_index=0|pts=1401|pts_time=1.401000|dts=1401|dts_time=1.401000|duration=33|duration_time=0.033000|size=653|pos=18321|flags=___|data_hash=CRC32:b9f01826 +packet|codec_type=video|stream_index=0|pts=1435|pts_time=1.435000|dts=1435|dts_time=1.435000|duration=33|duration_time=0.033000|size=335|pos=18994|flags=___|data_hash=CRC32:9e2e9463 +packet|codec_type=audio|stream_index=1|pts=1440|pts_time=1.440000|dts=1440|dts_time=1.440000|duration=46|duration_time=0.046000|size=730|pos=19349|flags=K__|data_hash=CRC32:8f424fb7 +packet|codec_type=video|stream_index=0|pts=1468|pts_time=1.468000|dts=1468|dts_time=1.468000|duration=33|duration_time=0.033000|size=765|pos=20096|flags=___|data_hash=CRC32:09b3b571 +packet|codec_type=audio|stream_index=1|pts=1486|pts_time=1.486000|dts=1486|dts_time=1.486000|duration=46|duration_time=0.046000|size=756|pos=20881|flags=K__|data_hash=CRC32:4921e8da +packet|codec_type=video|stream_index=0|pts=1502|pts_time=1.502000|dts=1502|dts_time=1.502000|duration=33|duration_time=0.033000|size=213|pos=21654|flags=___|data_hash=CRC32:c7c9280a +packet|codec_type=audio|stream_index=1|pts=1533|pts_time=1.533000|dts=1533|dts_time=1.533000|duration=46|duration_time=0.046000|size=664|pos=21887|flags=K__|data_hash=CRC32:e093637e +packet|codec_type=video|stream_index=0|pts=1535|pts_time=1.535000|dts=1535|dts_time=1.535000|duration=33|duration_time=0.033000|size=464|pos=22568|flags=___|data_hash=CRC32:e555cff4 +packet|codec_type=video|stream_index=0|pts=1568|pts_time=1.568000|dts=1568|dts_time=1.568000|duration=33|duration_time=0.033000|size=561|pos=23052|flags=___|data_hash=CRC32:5e5d560b +packet|codec_type=audio|stream_index=1|pts=1579|pts_time=1.579000|dts=1579|dts_time=1.579000|duration=46|duration_time=0.046000|size=751|pos=23633|flags=K__|data_hash=CRC32:7d228f8d +packet|codec_type=video|stream_index=0|pts=1602|pts_time=1.602000|dts=1602|dts_time=1.602000|duration=33|duration_time=0.033000|size=876|pos=24401|flags=___|data_hash=CRC32:e92ee634 +packet|codec_type=audio|stream_index=1|pts=1625|pts_time=1.625000|dts=1625|dts_time=1.625000|duration=46|duration_time=0.046000|size=780|pos=25297|flags=K__|data_hash=CRC32:9b9cba9e +packet|codec_type=video|stream_index=0|pts=1635|pts_time=1.635000|dts=1635|dts_time=1.635000|duration=33|duration_time=0.033000|size=473|pos=26094|flags=___|data_hash=CRC32:4797e66e +packet|codec_type=video|stream_index=0|pts=1668|pts_time=1.668000|dts=1668|dts_time=1.668000|duration=33|duration_time=0.033000|size=272|pos=26587|flags=___|data_hash=CRC32:86c1281c +packet|codec_type=audio|stream_index=1|pts=1672|pts_time=1.672000|dts=1672|dts_time=1.672000|duration=46|duration_time=0.046000|size=404|pos=26879|flags=K__|data_hash=CRC32:89d51769 +packet|codec_type=video|stream_index=0|pts=1702|pts_time=1.702000|dts=1702|dts_time=1.702000|duration=33|duration_time=0.033000|size=281|pos=27300|flags=___|data_hash=CRC32:b5f22b1a +packet|codec_type=audio|stream_index=1|pts=1718|pts_time=1.718000|dts=1718|dts_time=1.718000|duration=46|duration_time=0.046000|size=326|pos=27601|flags=K__|data_hash=CRC32:3723e2b7 +packet|codec_type=video|stream_index=0|pts=1735|pts_time=1.735000|dts=1735|dts_time=1.735000|duration=33|duration_time=0.033000|size=315|pos=27944|flags=___|data_hash=CRC32:322931af +packet|codec_type=audio|stream_index=1|pts=1765|pts_time=1.765000|dts=1765|dts_time=1.765000|duration=46|duration_time=0.046000|size=77|pos=28279|flags=K__|data_hash=CRC32:181325ba +packet|codec_type=video|stream_index=0|pts=1768|pts_time=1.768000|dts=1768|dts_time=1.768000|duration=33|duration_time=0.033000|size=653|pos=28373|flags=___|data_hash=CRC32:53cc49de +packet|codec_type=video|stream_index=0|pts=1802|pts_time=1.802000|dts=1802|dts_time=1.802000|duration=33|duration_time=0.033000|size=228|pos=29046|flags=___|data_hash=CRC32:bb222de5 +packet|codec_type=audio|stream_index=1|pts=1811|pts_time=1.811000|dts=1811|dts_time=1.811000|duration=46|duration_time=0.046000|size=132|pos=29294|flags=K__|data_hash=CRC32:1bef55db +packet|codec_type=video|stream_index=0|pts=1835|pts_time=1.835000|dts=1835|dts_time=1.835000|duration=33|duration_time=0.033000|size=265|pos=29443|flags=___|data_hash=CRC32:d4f0d444 +packet|codec_type=audio|stream_index=1|pts=1858|pts_time=1.858000|dts=1858|dts_time=1.858000|duration=46|duration_time=0.046000|size=266|pos=29728|flags=K__|data_hash=CRC32:126ec6c3 +packet|codec_type=video|stream_index=0|pts=1869|pts_time=1.869000|dts=1869|dts_time=1.869000|duration=33|duration_time=0.033000|size=362|pos=30011|flags=___|data_hash=CRC32:a3399859 +packet|codec_type=video|stream_index=0|pts=1902|pts_time=1.902000|dts=1902|dts_time=1.902000|duration=33|duration_time=0.033000|size=362|pos=30393|flags=___|data_hash=CRC32:b4462dfc +packet|codec_type=audio|stream_index=1|pts=1904|pts_time=1.904000|dts=1904|dts_time=1.904000|duration=46|duration_time=0.046000|size=297|pos=30775|flags=K__|data_hash=CRC32:8a286293 +packet|codec_type=video|stream_index=0|pts=1935|pts_time=1.935000|dts=1935|dts_time=1.935000|duration=33|duration_time=0.033000|size=297|pos=31089|flags=___|data_hash=CRC32:ead314f3 +packet|codec_type=audio|stream_index=1|pts=1950|pts_time=1.950000|dts=1950|dts_time=1.950000|duration=46|duration_time=0.046000|size=9|pos=31406|flags=K__|data_hash=CRC32:3395d413 +packet|codec_type=video|stream_index=0|pts=1969|pts_time=1.969000|dts=1969|dts_time=1.969000|duration=33|duration_time=0.033000|size=395|pos=31432|flags=___|data_hash=CRC32:2d27c345 +packet|codec_type=audio|stream_index=1|pts=1997|pts_time=1.997000|dts=1997|dts_time=1.997000|duration=46|duration_time=0.046000|size=9|pos=31847|flags=K__|data_hash=CRC32:6b5dbb28 +packet|codec_type=video|stream_index=0|pts=2002|pts_time=2.002000|dts=2002|dts_time=2.002000|duration=33|duration_time=0.033000|size=149|pos=31873|flags=___|data_hash=CRC32:cbf3938c +packet|codec_type=video|stream_index=0|pts=2035|pts_time=2.035000|dts=2035|dts_time=2.035000|duration=33|duration_time=0.033000|size=141|pos=32042|flags=___|data_hash=CRC32:8b92a9de +packet|codec_type=audio|stream_index=1|pts=2043|pts_time=2.043000|dts=2043|dts_time=2.043000|duration=46|duration_time=0.046000|size=9|pos=32203|flags=K__|data_hash=CRC32:bbb61b93 +packet|codec_type=video|stream_index=0|pts=2069|pts_time=2.069000|dts=2069|dts_time=2.069000|duration=33|duration_time=0.033000|size=317|pos=32229|flags=___|data_hash=CRC32:5362eed3 +packet|codec_type=audio|stream_index=1|pts=2090|pts_time=2.090000|dts=2090|dts_time=2.090000|duration=46|duration_time=0.046000|size=9|pos=32566|flags=K__|data_hash=CRC32:bbb61b93 +packet|codec_type=video|stream_index=0|pts=2102|pts_time=2.102000|dts=2102|dts_time=2.102000|duration=33|duration_time=0.033000|size=170|pos=32592|flags=___|data_hash=CRC32:867c837a +packet|codec_type=video|stream_index=0|pts=2135|pts_time=2.135000|dts=2135|dts_time=2.135000|duration=33|duration_time=0.033000|size=443|pos=32782|flags=___|data_hash=CRC32:5bc93901 +packet|codec_type=audio|stream_index=1|pts=2136|pts_time=2.136000|dts=2136|dts_time=2.136000|duration=46|duration_time=0.046000|size=9|pos=33245|flags=K__|data_hash=CRC32:bbb61b93 +packet|codec_type=video|stream_index=0|pts=2169|pts_time=2.169000|dts=2169|dts_time=2.169000|duration=33|duration_time=0.033000|size=224|pos=33271|flags=___|data_hash=CRC32:8eddf111 +packet|codec_type=audio|stream_index=1|pts=2183|pts_time=2.183000|dts=2183|dts_time=2.183000|duration=46|duration_time=0.046000|size=9|pos=33515|flags=K__|data_hash=CRC32:bbb61b93 +packet|codec_type=video|stream_index=0|pts=2202|pts_time=2.202000|dts=2202|dts_time=2.202000|duration=33|duration_time=0.033000|size=472|pos=33541|flags=___|data_hash=CRC32:abe7ea6c +packet|codec_type=audio|stream_index=1|pts=2229|pts_time=2.229000|dts=2229|dts_time=2.229000|duration=46|duration_time=0.046000|size=9|pos=34033|flags=K__|data_hash=CRC32:bbb61b93 +packet|codec_type=video|stream_index=0|pts=2236|pts_time=2.236000|dts=2236|dts_time=2.236000|duration=33|duration_time=0.033000|size=188|pos=34059|flags=___|data_hash=CRC32:73b69b1a +packet|codec_type=video|stream_index=0|pts=2269|pts_time=2.269000|dts=2269|dts_time=2.269000|duration=33|duration_time=0.033000|size=302|pos=34267|flags=___|data_hash=CRC32:81ba5025 +packet|codec_type=audio|stream_index=1|pts=2276|pts_time=2.276000|dts=2276|dts_time=2.276000|duration=46|duration_time=0.046000|size=9|pos=34589|flags=K__|data_hash=CRC32:bbb61b93 +packet|codec_type=video|stream_index=0|pts=2302|pts_time=2.302000|dts=2302|dts_time=2.302000|duration=33|duration_time=0.033000|size=125|pos=34615|flags=___|data_hash=CRC32:16e31418 +packet|codec_type=audio|stream_index=1|pts=2322|pts_time=2.322000|dts=2322|dts_time=2.322000|duration=46|duration_time=0.046000|size=9|pos=34760|flags=K__|data_hash=CRC32:bbb61b93 +packet|codec_type=video|stream_index=0|pts=2336|pts_time=2.336000|dts=2336|dts_time=2.336000|duration=33|duration_time=0.033000|size=810|pos=34786|flags=___|data_hash=CRC32:409d7bc5 +packet|codec_type=audio|stream_index=1|pts=2368|pts_time=2.368000|dts=2368|dts_time=2.368000|duration=46|duration_time=0.046000|size=304|pos=35616|flags=K__|data_hash=CRC32:d7355e6f +packet|codec_type=video|stream_index=0|pts=2369|pts_time=2.369000|dts=2369|dts_time=2.369000|duration=33|duration_time=0.033000|size=158|pos=35937|flags=___|data_hash=CRC32:bb167cd2 +packet|codec_type=video|stream_index=0|pts=2402|pts_time=2.402000|dts=2402|dts_time=2.402000|duration=33|duration_time=0.033000|size=561|pos=36115|flags=___|data_hash=CRC32:582133cb +packet|codec_type=audio|stream_index=1|pts=2415|pts_time=2.415000|dts=2415|dts_time=2.415000|duration=46|duration_time=0.046000|size=683|pos=36696|flags=K__|data_hash=CRC32:0e95a3a0 +packet|codec_type=video|stream_index=0|pts=2436|pts_time=2.436000|dts=2436|dts_time=2.436000|duration=33|duration_time=0.033000|size=383|pos=37396|flags=___|data_hash=CRC32:a2c19b0b +packet|codec_type=audio|stream_index=1|pts=2461|pts_time=2.461000|dts=2461|dts_time=2.461000|duration=46|duration_time=0.046000|size=681|pos=37799|flags=K__|data_hash=CRC32:326a32e5 +packet|codec_type=video|stream_index=0|pts=2469|pts_time=2.469000|dts=2469|dts_time=2.469000|duration=33|duration_time=0.033000|size=218|pos=38497|flags=___|data_hash=CRC32:bda38cdd +packet|codec_type=video|stream_index=0|pts=2503|pts_time=2.503000|dts=2503|dts_time=2.503000|duration=33|duration_time=0.033000|size=270|pos=38735|flags=___|data_hash=CRC32:18a59365 +packet|codec_type=audio|stream_index=1|pts=2508|pts_time=2.508000|dts=2508|dts_time=2.508000|duration=46|duration_time=0.046000|size=663|pos=39025|flags=K__|data_hash=CRC32:04b4fe14 +packet|codec_type=video|stream_index=0|pts=2536|pts_time=2.536000|dts=2536|dts_time=2.536000|duration=33|duration_time=0.033000|size=182|pos=39705|flags=___|data_hash=CRC32:3f9da83b +packet|codec_type=audio|stream_index=1|pts=2554|pts_time=2.554000|dts=2554|dts_time=2.554000|duration=46|duration_time=0.046000|size=671|pos=39907|flags=K__|data_hash=CRC32:b8c62ab4 +packet|codec_type=video|stream_index=0|pts=2569|pts_time=2.569000|dts=2569|dts_time=2.569000|duration=33|duration_time=0.033000|size=1063|pos=40595|flags=K__|data_hash=CRC32:89a9f14f +packet|codec_type=audio|stream_index=1|pts=2601|pts_time=2.601000|dts=2601|dts_time=2.601000|duration=46|duration_time=0.046000|size=682|pos=41678|flags=K__|data_hash=CRC32:e95e8d23 +packet|codec_type=video|stream_index=0|pts=2603|pts_time=2.603000|dts=2603|dts_time=2.603000|duration=33|duration_time=0.033000|size=3687|pos=42377|flags=___|data_hash=CRC32:e9d6144b +packet|codec_type=video|stream_index=0|pts=2636|pts_time=2.636000|dts=2636|dts_time=2.636000|duration=33|duration_time=0.033000|size=280|pos=46084|flags=___|data_hash=CRC32:520c7765 +packet|codec_type=audio|stream_index=1|pts=2647|pts_time=2.647000|dts=2647|dts_time=2.647000|duration=46|duration_time=0.046000|size=698|pos=46384|flags=K__|data_hash=CRC32:0631a240 +packet|codec_type=video|stream_index=0|pts=2669|pts_time=2.669000|dts=2669|dts_time=2.669000|duration=33|duration_time=0.033000|size=475|pos=47099|flags=___|data_hash=CRC32:e1a7746b +packet|codec_type=audio|stream_index=1|pts=2694|pts_time=2.694000|dts=2694|dts_time=2.694000|duration=46|duration_time=0.046000|size=697|pos=47594|flags=K__|data_hash=CRC32:0e9feb04 +packet|codec_type=video|stream_index=0|pts=2703|pts_time=2.703000|dts=2703|dts_time=2.703000|duration=33|duration_time=0.033000|size=488|pos=48308|flags=___|data_hash=CRC32:ba916d5f +packet|codec_type=video|stream_index=0|pts=2736|pts_time=2.736000|dts=2736|dts_time=2.736000|duration=33|duration_time=0.033000|size=532|pos=48816|flags=___|data_hash=CRC32:bb384278 +packet|codec_type=audio|stream_index=1|pts=2740|pts_time=2.740000|dts=2740|dts_time=2.740000|duration=46|duration_time=0.046000|size=674|pos=49368|flags=K__|data_hash=CRC32:9859c9fe +packet|codec_type=video|stream_index=0|pts=2769|pts_time=2.769000|dts=2769|dts_time=2.769000|duration=33|duration_time=0.033000|size=590|pos=50059|flags=___|data_hash=CRC32:55a84515 +packet|codec_type=audio|stream_index=1|pts=2786|pts_time=2.786000|dts=2786|dts_time=2.786000|duration=46|duration_time=0.046000|size=651|pos=50669|flags=K__|data_hash=CRC32:642d943c +packet|codec_type=video|stream_index=0|pts=2803|pts_time=2.803000|dts=2803|dts_time=2.803000|duration=33|duration_time=0.033000|size=683|pos=51337|flags=___|data_hash=CRC32:ed48440d +packet|codec_type=audio|stream_index=1|pts=2833|pts_time=2.833000|dts=2833|dts_time=2.833000|duration=46|duration_time=0.046000|size=672|pos=52040|flags=K__|data_hash=CRC32:f2af0db0 +packet|codec_type=video|stream_index=0|pts=2836|pts_time=2.836000|dts=2836|dts_time=2.836000|duration=33|duration_time=0.033000|size=836|pos=52729|flags=___|data_hash=CRC32:d99a6f79 +packet|codec_type=video|stream_index=0|pts=2870|pts_time=2.870000|dts=2870|dts_time=2.870000|duration=33|duration_time=0.033000|size=676|pos=53585|flags=___|data_hash=CRC32:ed426283 +packet|codec_type=audio|stream_index=1|pts=2879|pts_time=2.879000|dts=2879|dts_time=2.879000|duration=46|duration_time=0.046000|size=665|pos=54281|flags=K__|data_hash=CRC32:d6e66995 +packet|codec_type=video|stream_index=0|pts=2903|pts_time=2.903000|dts=2903|dts_time=2.903000|duration=33|duration_time=0.033000|size=731|pos=54963|flags=___|data_hash=CRC32:9df509dc +packet|codec_type=audio|stream_index=1|pts=2926|pts_time=2.926000|dts=2926|dts_time=2.926000|duration=46|duration_time=0.046000|size=734|pos=55714|flags=K__|data_hash=CRC32:2e13e9fe +packet|codec_type=video|stream_index=0|pts=2936|pts_time=2.936000|dts=2936|dts_time=2.936000|duration=33|duration_time=0.033000|size=839|pos=56465|flags=___|data_hash=CRC32:dc12a67f +packet|codec_type=video|stream_index=0|pts=2970|pts_time=2.970000|dts=2970|dts_time=2.970000|duration=33|duration_time=0.033000|size=787|pos=57324|flags=___|data_hash=CRC32:db72a014 +packet|codec_type=audio|stream_index=1|pts=2972|pts_time=2.972000|dts=2972|dts_time=2.972000|duration=46|duration_time=0.046000|size=732|pos=58131|flags=K__|data_hash=CRC32:9cfb9b77 +packet|codec_type=video|stream_index=0|pts=3003|pts_time=3.003000|dts=3003|dts_time=3.003000|duration=33|duration_time=0.033000|size=1039|pos=58880|flags=___|data_hash=CRC32:bf96f792 +packet|codec_type=audio|stream_index=1|pts=3019|pts_time=3.019000|dts=3019|dts_time=3.019000|duration=46|duration_time=0.046000|size=742|pos=59939|flags=K__|data_hash=CRC32:51cb6568 +packet|codec_type=video|stream_index=0|pts=3036|pts_time=3.036000|dts=3036|dts_time=3.036000|duration=33|duration_time=0.033000|size=851|pos=60698|flags=___|data_hash=CRC32:45237f01 +packet|codec_type=audio|stream_index=1|pts=3065|pts_time=3.065000|dts=3065|dts_time=3.065000|duration=46|duration_time=0.046000|size=748|pos=61569|flags=K__|data_hash=CRC32:5c676c58 +packet|codec_type=video|stream_index=0|pts=3070|pts_time=3.070000|dts=3070|dts_time=3.070000|duration=33|duration_time=0.033000|size=928|pos=62334|flags=___|data_hash=CRC32:cef81f2c +packet|codec_type=video|stream_index=0|pts=3103|pts_time=3.103000|dts=3103|dts_time=3.103000|duration=33|duration_time=0.033000|size=840|pos=63282|flags=___|data_hash=CRC32:7ae6a4a0 +packet|codec_type=audio|stream_index=1|pts=3111|pts_time=3.111000|dts=3111|dts_time=3.111000|duration=46|duration_time=0.046000|size=671|pos=64142|flags=K__|data_hash=CRC32:c4c27684 +packet|codec_type=video|stream_index=0|pts=3136|pts_time=3.136000|dts=3136|dts_time=3.136000|duration=33|duration_time=0.033000|size=889|pos=64830|flags=___|data_hash=CRC32:70b13ba7 +packet|codec_type=audio|stream_index=1|pts=3158|pts_time=3.158000|dts=3158|dts_time=3.158000|duration=46|duration_time=0.046000|size=645|pos=65739|flags=K__|data_hash=CRC32:1b7b9a99 +packet|codec_type=video|stream_index=0|pts=3170|pts_time=3.170000|dts=3170|dts_time=3.170000|duration=33|duration_time=0.033000|size=789|pos=66401|flags=___|data_hash=CRC32:6ffae70e +packet|codec_type=video|stream_index=0|pts=3203|pts_time=3.203000|dts=3203|dts_time=3.203000|duration=33|duration_time=0.033000|size=1037|pos=67210|flags=___|data_hash=CRC32:acb72f8a +packet|codec_type=audio|stream_index=1|pts=3204|pts_time=3.204000|dts=3204|dts_time=3.204000|duration=46|duration_time=0.046000|size=724|pos=68267|flags=K__|data_hash=CRC32:feb7c4f3 +packet|codec_type=video|stream_index=0|pts=3237|pts_time=3.237000|dts=3237|dts_time=3.237000|duration=33|duration_time=0.033000|size=1201|pos=69008|flags=___|data_hash=CRC32:0ac77ab1 +packet|codec_type=audio|stream_index=1|pts=3251|pts_time=3.251000|dts=3251|dts_time=3.251000|duration=46|duration_time=0.046000|size=757|pos=70229|flags=K__|data_hash=CRC32:28d27dd5 +packet|codec_type=video|stream_index=0|pts=3270|pts_time=3.270000|dts=3270|dts_time=3.270000|duration=33|duration_time=0.033000|size=934|pos=71003|flags=___|data_hash=CRC32:dd16f432 +packet|codec_type=audio|stream_index=1|pts=3297|pts_time=3.297000|dts=3297|dts_time=3.297000|duration=46|duration_time=0.046000|size=710|pos=71957|flags=K__|data_hash=CRC32:fb16456d +packet|codec_type=video|stream_index=0|pts=3303|pts_time=3.303000|dts=3303|dts_time=3.303000|duration=33|duration_time=0.033000|size=1028|pos=72684|flags=___|data_hash=CRC32:d4cf8920 +packet|codec_type=video|stream_index=0|pts=3337|pts_time=3.337000|dts=3337|dts_time=3.337000|duration=33|duration_time=0.033000|size=1007|pos=73732|flags=___|data_hash=CRC32:4dfc2133 +packet|codec_type=audio|stream_index=1|pts=3344|pts_time=3.344000|dts=3344|dts_time=3.344000|duration=46|duration_time=0.046000|size=705|pos=74759|flags=K__|data_hash=CRC32:249bd165 +packet|codec_type=video|stream_index=0|pts=3370|pts_time=3.370000|dts=3370|dts_time=3.370000|duration=33|duration_time=0.033000|size=944|pos=75481|flags=___|data_hash=CRC32:cf0ee6e5 +packet|codec_type=audio|stream_index=1|pts=3390|pts_time=3.390000|dts=3390|dts_time=3.390000|duration=46|duration_time=0.046000|size=693|pos=76445|flags=K__|data_hash=CRC32:907c82d7 +packet|codec_type=video|stream_index=0|pts=3403|pts_time=3.403000|dts=3403|dts_time=3.403000|duration=33|duration_time=0.033000|size=1121|pos=77155|flags=___|data_hash=CRC32:f4a2ef4d +packet|codec_type=audio|stream_index=1|pts=3437|pts_time=3.437000|dts=3437|dts_time=3.437000|duration=46|duration_time=0.046000|size=683|pos=78296|flags=K__|data_hash=CRC32:25f0e52b +packet|codec_type=video|stream_index=0|pts=3437|pts_time=3.437000|dts=3437|dts_time=3.437000|duration=33|duration_time=0.033000|size=1321|pos=78996|flags=___|data_hash=CRC32:890f59cd +packet|codec_type=video|stream_index=0|pts=3470|pts_time=3.470000|dts=3470|dts_time=3.470000|duration=33|duration_time=0.033000|size=1229|pos=80337|flags=___|data_hash=CRC32:7c53b1c5 +packet|codec_type=audio|stream_index=1|pts=3483|pts_time=3.483000|dts=3483|dts_time=3.483000|duration=46|duration_time=0.046000|size=668|pos=81586|flags=K__|data_hash=CRC32:c848f398 +packet|codec_type=video|stream_index=0|pts=3504|pts_time=3.504000|dts=3504|dts_time=3.504000|duration=33|duration_time=0.033000|size=1166|pos=82271|flags=___|data_hash=CRC32:237539fc +packet|codec_type=audio|stream_index=1|pts=3529|pts_time=3.529000|dts=3529|dts_time=3.529000|duration=46|duration_time=0.046000|size=624|pos=83457|flags=K__|data_hash=CRC32:5d81d294 +packet|codec_type=video|stream_index=0|pts=3537|pts_time=3.537000|dts=3537|dts_time=3.537000|duration=33|duration_time=0.033000|size=1055|pos=84098|flags=___|data_hash=CRC32:2d22b0e9 +packet|codec_type=video|stream_index=0|pts=3570|pts_time=3.570000|dts=3570|dts_time=3.570000|duration=33|duration_time=0.033000|size=947|pos=85173|flags=___|data_hash=CRC32:1003bc18 +packet|codec_type=audio|stream_index=1|pts=3576|pts_time=3.576000|dts=3576|dts_time=3.576000|duration=46|duration_time=0.046000|size=570|pos=86140|flags=K__|data_hash=CRC32:41da9b98 +packet|codec_type=video|stream_index=0|pts=3604|pts_time=3.604000|dts=3604|dts_time=3.604000|duration=33|duration_time=0.033000|size=1117|pos=86727|flags=___|data_hash=CRC32:ea91a8bf +packet|codec_type=audio|stream_index=1|pts=3622|pts_time=3.622000|dts=3622|dts_time=3.622000|duration=46|duration_time=0.046000|size=579|pos=87864|flags=K__|data_hash=CRC32:b1e12639 +packet|codec_type=video|stream_index=0|pts=3637|pts_time=3.637000|dts=3637|dts_time=3.637000|duration=33|duration_time=0.033000|size=1397|pos=88460|flags=___|data_hash=CRC32:f2bdfea7 +packet|codec_type=audio|stream_index=1|pts=3669|pts_time=3.669000|dts=3669|dts_time=3.669000|duration=46|duration_time=0.046000|size=558|pos=89877|flags=K__|data_hash=CRC32:095b218c +packet|codec_type=video|stream_index=0|pts=3670|pts_time=3.670000|dts=3670|dts_time=3.670000|duration=33|duration_time=0.033000|size=1097|pos=90452|flags=___|data_hash=CRC32:be8cf516 +packet|codec_type=video|stream_index=0|pts=3704|pts_time=3.704000|dts=3704|dts_time=3.704000|duration=33|duration_time=0.033000|size=1207|pos=91569|flags=___|data_hash=CRC32:176a8fe9 +packet|codec_type=audio|stream_index=1|pts=3715|pts_time=3.715000|dts=3715|dts_time=3.715000|duration=46|duration_time=0.046000|size=510|pos=92796|flags=K__|data_hash=CRC32:8cea9dca +packet|codec_type=video|stream_index=0|pts=3737|pts_time=3.737000|dts=3737|dts_time=3.737000|duration=33|duration_time=0.033000|size=1109|pos=93323|flags=___|data_hash=CRC32:615bab01 +packet|codec_type=audio|stream_index=1|pts=3762|pts_time=3.762000|dts=3762|dts_time=3.762000|duration=46|duration_time=0.046000|size=518|pos=94452|flags=K__|data_hash=CRC32:600293cc +packet|codec_type=video|stream_index=0|pts=3770|pts_time=3.770000|dts=3770|dts_time=3.770000|duration=33|duration_time=0.033000|size=994|pos=94987|flags=___|data_hash=CRC32:db090b40 +packet|codec_type=video|stream_index=0|pts=3804|pts_time=3.804000|dts=3804|dts_time=3.804000|duration=33|duration_time=0.033000|size=1144|pos=96001|flags=___|data_hash=CRC32:4966c524 +packet|codec_type=audio|stream_index=1|pts=3808|pts_time=3.808000|dts=3808|dts_time=3.808000|duration=46|duration_time=0.046000|size=481|pos=97165|flags=K__|data_hash=CRC32:e53ca4a3 +packet|codec_type=video|stream_index=0|pts=3837|pts_time=3.837000|dts=3837|dts_time=3.837000|duration=33|duration_time=0.033000|size=1409|pos=97663|flags=___|data_hash=CRC32:5561cdad +packet|codec_type=audio|stream_index=1|pts=3855|pts_time=3.855000|dts=3855|dts_time=3.855000|duration=46|duration_time=0.046000|size=443|pos=99092|flags=K__|data_hash=CRC32:14937ac1 +packet|codec_type=video|stream_index=0|pts=3871|pts_time=3.871000|dts=3871|dts_time=3.871000|duration=33|duration_time=0.033000|size=1205|pos=99552|flags=___|data_hash=CRC32:93f9dbe0 +packet|codec_type=audio|stream_index=1|pts=3901|pts_time=3.901000|dts=3901|dts_time=3.901000|duration=46|duration_time=0.046000|size=413|pos=100777|flags=K__|data_hash=CRC32:4fea79a1 +packet|codec_type=video|stream_index=0|pts=3904|pts_time=3.904000|dts=3904|dts_time=3.904000|duration=33|duration_time=0.033000|size=1159|pos=101207|flags=___|data_hash=CRC32:8a7dd1ca +packet|codec_type=video|stream_index=0|pts=3937|pts_time=3.937000|dts=3937|dts_time=3.937000|duration=33|duration_time=0.033000|size=1207|pos=102386|flags=___|data_hash=CRC32:9c351265 +packet|codec_type=audio|stream_index=1|pts=3947|pts_time=3.947000|dts=3947|dts_time=3.947000|duration=46|duration_time=0.046000|size=398|pos=103613|flags=K__|data_hash=CRC32:0777a82b +packet|codec_type=video|stream_index=0|pts=3971|pts_time=3.971000|dts=3971|dts_time=3.971000|duration=33|duration_time=0.033000|size=1084|pos=104028|flags=___|data_hash=CRC32:3b4222c7 +packet|codec_type=audio|stream_index=1|pts=3994|pts_time=3.994000|dts=3994|dts_time=3.994000|duration=46|duration_time=0.046000|size=377|pos=105132|flags=K__|data_hash=CRC32:8662b58a +packet|codec_type=video|stream_index=0|pts=4004|pts_time=4.004000|dts=4004|dts_time=4.004000|duration=33|duration_time=0.033000|size=1539|pos=105526|flags=___|data_hash=CRC32:cf253620 +packet|codec_type=video|stream_index=0|pts=4037|pts_time=4.037000|dts=4037|dts_time=4.037000|duration=33|duration_time=0.033000|size=1409|pos=107085|flags=___|data_hash=CRC32:01f30787 +packet|codec_type=audio|stream_index=1|pts=4040|pts_time=4.040000|dts=4040|dts_time=4.040000|duration=46|duration_time=0.046000|size=364|pos=108514|flags=K__|data_hash=CRC32:f73e6c88 +packet|codec_type=video|stream_index=0|pts=4071|pts_time=4.071000|dts=4071|dts_time=4.071000|duration=33|duration_time=0.033000|size=1275|pos=108895|flags=___|data_hash=CRC32:d7c1cfe1 +packet|codec_type=audio|stream_index=1|pts=4087|pts_time=4.087000|dts=4087|dts_time=4.087000|duration=46|duration_time=0.046000|size=374|pos=110190|flags=K__|data_hash=CRC32:c41f57c7 +packet|codec_type=video|stream_index=0|pts=4104|pts_time=4.104000|dts=4104|dts_time=4.104000|duration=33|duration_time=0.033000|size=1317|pos=110581|flags=___|data_hash=CRC32:685138ef +packet|codec_type=audio|stream_index=1|pts=4133|pts_time=4.133000|dts=4133|dts_time=4.133000|duration=46|duration_time=0.046000|size=355|pos=111918|flags=K__|data_hash=CRC32:7a5e82a8 +packet|codec_type=video|stream_index=0|pts=4137|pts_time=4.137000|dts=4137|dts_time=4.137000|duration=33|duration_time=0.033000|size=1146|pos=112290|flags=___|data_hash=CRC32:48ce008d +packet|codec_type=video|stream_index=0|pts=4171|pts_time=4.171000|dts=4171|dts_time=4.171000|duration=33|duration_time=0.033000|size=1166|pos=113456|flags=___|data_hash=CRC32:f12da76b +packet|codec_type=audio|stream_index=1|pts=4180|pts_time=4.180000|dts=4180|dts_time=4.180000|duration=46|duration_time=0.046000|size=341|pos=114642|flags=K__|data_hash=CRC32:ea126e98 +packet|codec_type=video|stream_index=0|pts=4204|pts_time=4.204000|dts=4204|dts_time=4.204000|duration=33|duration_time=0.033000|size=1272|pos=115000|flags=___|data_hash=CRC32:31e617c7 +packet|codec_type=audio|stream_index=1|pts=4226|pts_time=4.226000|dts=4226|dts_time=4.226000|duration=46|duration_time=0.046000|size=364|pos=116292|flags=K__|data_hash=CRC32:6d84c4a8 +packet|codec_type=video|stream_index=0|pts=4238|pts_time=4.238000|dts=4238|dts_time=4.238000|duration=33|duration_time=0.033000|size=1550|pos=116673|flags=___|data_hash=CRC32:50d17465 +packet|codec_type=video|stream_index=0|pts=4271|pts_time=4.271000|dts=4271|dts_time=4.271000|duration=33|duration_time=0.033000|size=1353|pos=118243|flags=___|data_hash=CRC32:af8d072c +packet|codec_type=audio|stream_index=1|pts=4272|pts_time=4.272000|dts=4272|dts_time=4.272000|duration=46|duration_time=0.046000|size=350|pos=119616|flags=K__|data_hash=CRC32:c27e7ecc +packet|codec_type=video|stream_index=0|pts=4304|pts_time=4.304000|dts=4304|dts_time=4.304000|duration=33|duration_time=0.033000|size=1251|pos=119983|flags=___|data_hash=CRC32:271dcd86 +packet|codec_type=audio|stream_index=1|pts=4319|pts_time=4.319000|dts=4319|dts_time=4.319000|duration=46|duration_time=0.046000|size=356|pos=121254|flags=K__|data_hash=CRC32:6d111a73 +packet|codec_type=video|stream_index=0|pts=4338|pts_time=4.338000|dts=4338|dts_time=4.338000|duration=33|duration_time=0.033000|size=1339|pos=121627|flags=___|data_hash=CRC32:01aa658e +packet|codec_type=audio|stream_index=1|pts=4365|pts_time=4.365000|dts=4365|dts_time=4.365000|duration=46|duration_time=0.046000|size=365|pos=122986|flags=K__|data_hash=CRC32:e24aa34c +packet|codec_type=video|stream_index=0|pts=4371|pts_time=4.371000|dts=4371|dts_time=4.371000|duration=33|duration_time=0.033000|size=1216|pos=123368|flags=___|data_hash=CRC32:bee7821f +packet|codec_type=video|stream_index=0|pts=4404|pts_time=4.404000|dts=4404|dts_time=4.404000|duration=33|duration_time=0.033000|size=1222|pos=124604|flags=___|data_hash=CRC32:2bd2754e +packet|codec_type=audio|stream_index=1|pts=4412|pts_time=4.412000|dts=4412|dts_time=4.412000|duration=46|duration_time=0.046000|size=352|pos=125846|flags=K__|data_hash=CRC32:fc970370 +packet|codec_type=video|stream_index=0|pts=4438|pts_time=4.438000|dts=4438|dts_time=4.438000|duration=33|duration_time=0.033000|size=1665|pos=126215|flags=___|data_hash=CRC32:a08b2e57 +packet|codec_type=audio|stream_index=1|pts=4458|pts_time=4.458000|dts=4458|dts_time=4.458000|duration=46|duration_time=0.046000|size=374|pos=127900|flags=K__|data_hash=CRC32:fa07f96b +packet|codec_type=video|stream_index=0|pts=4471|pts_time=4.471000|dts=4471|dts_time=4.471000|duration=33|duration_time=0.033000|size=1372|pos=128291|flags=___|data_hash=CRC32:7ba310fc +packet|codec_type=audio|stream_index=1|pts=4505|pts_time=4.505000|dts=4505|dts_time=4.505000|duration=46|duration_time=0.046000|size=375|pos=129683|flags=K__|data_hash=CRC32:912ec2a1 +packet|codec_type=video|stream_index=0|pts=4505|pts_time=4.505000|dts=4505|dts_time=4.505000|duration=33|duration_time=0.033000|size=1611|pos=130075|flags=___|data_hash=CRC32:894697a0 +packet|codec_type=video|stream_index=0|pts=4538|pts_time=4.538000|dts=4538|dts_time=4.538000|duration=33|duration_time=0.033000|size=7010|pos=131706|flags=K__|data_hash=CRC32:e74f1b93 +packet|codec_type=audio|stream_index=1|pts=4551|pts_time=4.551000|dts=4551|dts_time=4.551000|duration=46|duration_time=0.046000|size=375|pos=138736|flags=K__|data_hash=CRC32:9049bbe0 +packet|codec_type=video|stream_index=0|pts=4571|pts_time=4.571000|dts=4571|dts_time=4.571000|duration=33|duration_time=0.033000|size=549|pos=139128|flags=___|data_hash=CRC32:bea67fa5 +packet|codec_type=audio|stream_index=1|pts=4598|pts_time=4.598000|dts=4598|dts_time=4.598000|duration=46|duration_time=0.046000|size=376|pos=139697|flags=K__|data_hash=CRC32:cf9362b3 +packet|codec_type=video|stream_index=0|pts=4605|pts_time=4.605000|dts=4605|dts_time=4.605000|duration=33|duration_time=0.033000|size=1021|pos=140090|flags=___|data_hash=CRC32:93ace02c +packet|codec_type=video|stream_index=0|pts=4638|pts_time=4.638000|dts=4638|dts_time=4.638000|duration=33|duration_time=0.033000|size=1281|pos=141131|flags=___|data_hash=CRC32:24070179 +packet|codec_type=audio|stream_index=1|pts=4644|pts_time=4.644000|dts=4644|dts_time=4.644000|duration=46|duration_time=0.046000|size=372|pos=142432|flags=K__|data_hash=CRC32:f7372f4c +packet|codec_type=video|stream_index=0|pts=4671|pts_time=4.671000|dts=4671|dts_time=4.671000|duration=33|duration_time=0.033000|size=1267|pos=142821|flags=___|data_hash=CRC32:7cfd6aa6 +packet|codec_type=audio|stream_index=1|pts=4690|pts_time=4.690000|dts=4690|dts_time=4.690000|duration=46|duration_time=0.046000|size=371|pos=144108|flags=K__|data_hash=CRC32:b244704d +packet|codec_type=video|stream_index=0|pts=4705|pts_time=4.705000|dts=4705|dts_time=4.705000|duration=33|duration_time=0.033000|size=1140|pos=144496|flags=___|data_hash=CRC32:eccfa0f7 +packet|codec_type=audio|stream_index=1|pts=4737|pts_time=4.737000|dts=4737|dts_time=4.737000|duration=46|duration_time=0.046000|size=365|pos=145656|flags=K__|data_hash=CRC32:834bb209 +packet|codec_type=video|stream_index=0|pts=4738|pts_time=4.738000|dts=4738|dts_time=4.738000|duration=33|duration_time=0.033000|size=1289|pos=146038|flags=___|data_hash=CRC32:4669d638 +packet|codec_type=video|stream_index=0|pts=4771|pts_time=4.771000|dts=4771|dts_time=4.771000|duration=33|duration_time=0.033000|size=1127|pos=147347|flags=___|data_hash=CRC32:e52c7abd +packet|codec_type=audio|stream_index=1|pts=4783|pts_time=4.783000|dts=4783|dts_time=4.783000|duration=46|duration_time=0.046000|size=385|pos=148494|flags=K__|data_hash=CRC32:e61dc477 +packet|codec_type=video|stream_index=0|pts=4805|pts_time=4.805000|dts=4805|dts_time=4.805000|duration=33|duration_time=0.033000|size=1196|pos=148896|flags=___|data_hash=CRC32:5a318942 +packet|codec_type=audio|stream_index=1|pts=4830|pts_time=4.830000|dts=4830|dts_time=4.830000|duration=46|duration_time=0.046000|size=362|pos=150112|flags=K__|data_hash=CRC32:8fee051a +packet|codec_type=video|stream_index=0|pts=4838|pts_time=4.838000|dts=4838|dts_time=4.838000|duration=33|duration_time=0.033000|size=1520|pos=150491|flags=___|data_hash=CRC32:2418eb0f +packet|codec_type=video|stream_index=0|pts=4872|pts_time=4.872000|dts=4872|dts_time=4.872000|duration=33|duration_time=0.033000|size=1370|pos=152031|flags=___|data_hash=CRC32:79ca0732 +packet|codec_type=audio|stream_index=1|pts=4876|pts_time=4.876000|dts=4876|dts_time=4.876000|duration=46|duration_time=0.046000|size=370|pos=153421|flags=K__|data_hash=CRC32:1720582c +packet|codec_type=video|stream_index=0|pts=4905|pts_time=4.905000|dts=4905|dts_time=4.905000|duration=33|duration_time=0.033000|size=1232|pos=153808|flags=___|data_hash=CRC32:32295018 +packet|codec_type=audio|stream_index=1|pts=4923|pts_time=4.923000|dts=4923|dts_time=4.923000|duration=46|duration_time=0.046000|size=369|pos=155060|flags=K__|data_hash=CRC32:6b668e5b +packet|codec_type=video|stream_index=0|pts=4938|pts_time=4.938000|dts=4938|dts_time=4.938000|duration=33|duration_time=0.033000|size=1159|pos=155446|flags=___|data_hash=CRC32:45fc12f2 +packet|codec_type=audio|stream_index=1|pts=4969|pts_time=4.969000|dts=4969|dts_time=4.969000|duration=46|duration_time=0.046000|size=341|pos=156625|flags=K__|data_hash=CRC32:4d4741d6 +packet|codec_type=video|stream_index=0|pts=4972|pts_time=4.972000|dts=4972|dts_time=4.972000|duration=33|duration_time=0.033000|size=1183|pos=156983|flags=___|data_hash=CRC32:10f40093 +packet|codec_type=video|stream_index=0|pts=5005|pts_time=5.005000|dts=5005|dts_time=5.005000|duration=33|duration_time=0.033000|size=1469|pos=158186|flags=___|data_hash=CRC32:43a4815e +packet|codec_type=audio|stream_index=1|pts=5016|pts_time=5.016000|dts=5016|dts_time=5.016000|duration=46|duration_time=0.046000|size=351|pos=159675|flags=K__|data_hash=CRC32:82bf6546 +packet|codec_type=video|stream_index=0|pts=5038|pts_time=5.038000|dts=5038|dts_time=5.038000|duration=33|duration_time=0.033000|size=1468|pos=160043|flags=___|data_hash=CRC32:e8c78f03 +packet|codec_type=audio|stream_index=1|pts=5062|pts_time=5.062000|dts=5062|dts_time=5.062000|duration=46|duration_time=0.046000|size=365|pos=161531|flags=K__|data_hash=CRC32:1299be30 +packet|codec_type=video|stream_index=0|pts=5072|pts_time=5.072000|dts=5072|dts_time=5.072000|duration=33|duration_time=0.033000|size=1355|pos=161913|flags=___|data_hash=CRC32:044621ed +packet|codec_type=video|stream_index=0|pts=5105|pts_time=5.105000|dts=5105|dts_time=5.105000|duration=33|duration_time=0.033000|size=1303|pos=163288|flags=___|data_hash=CRC32:3403397b +packet|codec_type=audio|stream_index=1|pts=5108|pts_time=5.108000|dts=5108|dts_time=5.108000|duration=46|duration_time=0.046000|size=358|pos=164611|flags=K__|data_hash=CRC32:ee1a432d +packet|codec_type=video|stream_index=0|pts=5138|pts_time=5.138000|dts=5138|dts_time=5.138000|duration=33|duration_time=0.033000|size=1316|pos=164986|flags=___|data_hash=CRC32:7021310e +packet|codec_type=audio|stream_index=1|pts=5155|pts_time=5.155000|dts=5155|dts_time=5.155000|duration=46|duration_time=0.046000|size=373|pos=166322|flags=K__|data_hash=CRC32:f25887f4 +packet|codec_type=video|stream_index=0|pts=5172|pts_time=5.172000|dts=5172|dts_time=5.172000|duration=33|duration_time=0.033000|size=1196|pos=166712|flags=___|data_hash=CRC32:d8492897 +packet|codec_type=audio|stream_index=1|pts=5201|pts_time=5.201000|dts=5201|dts_time=5.201000|duration=46|duration_time=0.046000|size=367|pos=167928|flags=K__|data_hash=CRC32:c30e6c9f +packet|codec_type=video|stream_index=0|pts=5205|pts_time=5.205000|dts=5205|dts_time=5.205000|duration=33|duration_time=0.033000|size=1283|pos=168312|flags=___|data_hash=CRC32:c9058bba +packet|codec_type=video|stream_index=0|pts=5239|pts_time=5.239000|dts=5239|dts_time=5.239000|duration=33|duration_time=0.033000|size=1489|pos=169615|flags=___|data_hash=CRC32:0e5dadc6 +packet|codec_type=audio|stream_index=1|pts=5248|pts_time=5.248000|dts=5248|dts_time=5.248000|duration=46|duration_time=0.046000|size=364|pos=171124|flags=K__|data_hash=CRC32:74db7811 +packet|codec_type=video|stream_index=0|pts=5272|pts_time=5.272000|dts=5272|dts_time=5.272000|duration=33|duration_time=0.033000|size=1507|pos=171505|flags=___|data_hash=CRC32:1e37a39f +packet|codec_type=audio|stream_index=1|pts=5294|pts_time=5.294000|dts=5294|dts_time=5.294000|duration=46|duration_time=0.046000|size=346|pos=173032|flags=K__|data_hash=CRC32:3386dd10 +packet|codec_type=video|stream_index=0|pts=5305|pts_time=5.305000|dts=5305|dts_time=5.305000|duration=33|duration_time=0.033000|size=1237|pos=173395|flags=___|data_hash=CRC32:d8f772ae +packet|codec_type=video|stream_index=0|pts=5339|pts_time=5.339000|dts=5339|dts_time=5.339000|duration=33|duration_time=0.033000|size=1217|pos=174652|flags=___|data_hash=CRC32:7caabc71 +packet|codec_type=audio|stream_index=1|pts=5341|pts_time=5.341000|dts=5341|dts_time=5.341000|duration=46|duration_time=0.046000|size=362|pos=175889|flags=K__|data_hash=CRC32:b4975396 +packet|codec_type=video|stream_index=0|pts=5372|pts_time=5.372000|dts=5372|dts_time=5.372000|duration=33|duration_time=0.033000|size=1224|pos=176268|flags=___|data_hash=CRC32:fbca6068 +packet|codec_type=audio|stream_index=1|pts=5387|pts_time=5.387000|dts=5387|dts_time=5.387000|duration=46|duration_time=0.046000|size=360|pos=177512|flags=K__|data_hash=CRC32:f639adaf +packet|codec_type=video|stream_index=0|pts=5405|pts_time=5.405000|dts=5405|dts_time=5.405000|duration=33|duration_time=0.033000|size=1554|pos=177889|flags=___|data_hash=CRC32:f9e211de +packet|codec_type=audio|stream_index=1|pts=5433|pts_time=5.433000|dts=5433|dts_time=5.433000|duration=46|duration_time=0.046000|size=356|pos=179463|flags=K__|data_hash=CRC32:ef458996 +packet|codec_type=video|stream_index=0|pts=5439|pts_time=5.439000|dts=5439|dts_time=5.439000|duration=33|duration_time=0.033000|size=1465|pos=179836|flags=___|data_hash=CRC32:cb5d725a +packet|codec_type=video|stream_index=0|pts=5472|pts_time=5.472000|dts=5472|dts_time=5.472000|duration=33|duration_time=0.033000|size=1862|pos=181321|flags=___|data_hash=CRC32:a9acf274 +packet|codec_type=audio|stream_index=1|pts=5480|pts_time=5.480000|dts=5480|dts_time=5.480000|duration=46|duration_time=0.046000|size=364|pos=183203|flags=K__|data_hash=CRC32:6d92ed19 +packet|codec_type=video|stream_index=0|pts=5506|pts_time=5.506000|dts=5506|dts_time=5.506000|duration=33|duration_time=0.033000|size=1604|pos=183584|flags=___|data_hash=CRC32:19bfeabc +packet|codec_type=audio|stream_index=1|pts=5526|pts_time=5.526000|dts=5526|dts_time=5.526000|duration=46|duration_time=0.046000|size=365|pos=185208|flags=K__|data_hash=CRC32:f257469d +packet|codec_type=video|stream_index=0|pts=5539|pts_time=5.539000|dts=5539|dts_time=5.539000|duration=33|duration_time=0.033000|size=1541|pos=185590|flags=___|data_hash=CRC32:642b27dd +packet|codec_type=video|stream_index=0|pts=5572|pts_time=5.572000|dts=5572|dts_time=5.572000|duration=33|duration_time=0.033000|size=1534|pos=187151|flags=___|data_hash=CRC32:67693383 +packet|codec_type=audio|stream_index=1|pts=5573|pts_time=5.573000|dts=5573|dts_time=5.573000|duration=46|duration_time=0.046000|size=357|pos=188705|flags=K__|data_hash=CRC32:52e0f7ac +packet|codec_type=video|stream_index=0|pts=5606|pts_time=5.606000|dts=5606|dts_time=5.606000|duration=33|duration_time=0.033000|size=1336|pos=189079|flags=___|data_hash=CRC32:904a4734 +packet|codec_type=audio|stream_index=1|pts=5619|pts_time=5.619000|dts=5619|dts_time=5.619000|duration=46|duration_time=0.046000|size=367|pos=190435|flags=K__|data_hash=CRC32:dae9d0bd +packet|codec_type=video|stream_index=0|pts=5639|pts_time=5.639000|dts=5639|dts_time=5.639000|duration=33|duration_time=0.033000|size=1761|pos=190819|flags=___|data_hash=CRC32:93496a5c +packet|codec_type=audio|stream_index=1|pts=5666|pts_time=5.666000|dts=5666|dts_time=5.666000|duration=46|duration_time=0.046000|size=361|pos=192600|flags=K__|data_hash=CRC32:86968dd2 +packet|codec_type=video|stream_index=0|pts=5672|pts_time=5.672000|dts=5672|dts_time=5.672000|duration=33|duration_time=0.033000|size=1722|pos=192978|flags=___|data_hash=CRC32:feec28c7 +packet|codec_type=video|stream_index=0|pts=5706|pts_time=5.706000|dts=5706|dts_time=5.706000|duration=33|duration_time=0.033000|size=1442|pos=194720|flags=___|data_hash=CRC32:620e5c0e +packet|codec_type=audio|stream_index=1|pts=5712|pts_time=5.712000|dts=5712|dts_time=5.712000|duration=46|duration_time=0.046000|size=367|pos=196182|flags=K__|data_hash=CRC32:17f30b04 +packet|codec_type=video|stream_index=0|pts=5739|pts_time=5.739000|dts=5739|dts_time=5.739000|duration=33|duration_time=0.033000|size=1313|pos=196566|flags=___|data_hash=CRC32:6bee8c20 +packet|codec_type=audio|stream_index=1|pts=5759|pts_time=5.759000|dts=5759|dts_time=5.759000|duration=46|duration_time=0.046000|size=375|pos=197899|flags=K__|data_hash=CRC32:4eda4c7c +packet|codec_type=video|stream_index=0|pts=5772|pts_time=5.772000|dts=5772|dts_time=5.772000|duration=33|duration_time=0.033000|size=1436|pos=198291|flags=___|data_hash=CRC32:fd8ac68a +packet|codec_type=audio|stream_index=1|pts=5805|pts_time=5.805000|dts=5805|dts_time=5.805000|duration=46|duration_time=0.046000|size=357|pos=199747|flags=K__|data_hash=CRC32:3551e83a +packet|codec_type=video|stream_index=0|pts=5806|pts_time=5.806000|dts=5806|dts_time=5.806000|duration=33|duration_time=0.033000|size=1689|pos=200121|flags=___|data_hash=CRC32:e09613d4 +packet|codec_type=video|stream_index=0|pts=5839|pts_time=5.839000|dts=5839|dts_time=5.839000|duration=33|duration_time=0.033000|size=1472|pos=201830|flags=___|data_hash=CRC32:9467baaf +packet|codec_type=audio|stream_index=1|pts=5851|pts_time=5.851000|dts=5851|dts_time=5.851000|duration=46|duration_time=0.046000|size=379|pos=203322|flags=K__|data_hash=CRC32:de123d0a +packet|codec_type=video|stream_index=0|pts=5873|pts_time=5.873000|dts=5873|dts_time=5.873000|duration=33|duration_time=0.033000|size=1730|pos=203718|flags=___|data_hash=CRC32:2b6400ba +packet|codec_type=audio|stream_index=1|pts=5898|pts_time=5.898000|dts=5898|dts_time=5.898000|duration=46|duration_time=0.046000|size=361|pos=205468|flags=K__|data_hash=CRC32:02a5f979 +packet|codec_type=video|stream_index=0|pts=5906|pts_time=5.906000|dts=5906|dts_time=5.906000|duration=33|duration_time=0.033000|size=1555|pos=205846|flags=___|data_hash=CRC32:31d5ba1a +packet|codec_type=video|stream_index=0|pts=5939|pts_time=5.939000|dts=5939|dts_time=5.939000|duration=33|duration_time=0.033000|size=1486|pos=207421|flags=___|data_hash=CRC32:8d0829d2 +packet|codec_type=audio|stream_index=1|pts=5944|pts_time=5.944000|dts=5944|dts_time=5.944000|duration=46|duration_time=0.046000|size=350|pos=208927|flags=K__|data_hash=CRC32:8759b7f4 +packet|codec_type=video|stream_index=0|pts=5973|pts_time=5.973000|dts=5973|dts_time=5.973000|duration=33|duration_time=0.033000|size=1311|pos=209294|flags=___|data_hash=CRC32:bc92ded4 +packet|codec_type=audio|stream_index=1|pts=5991|pts_time=5.991000|dts=5991|dts_time=5.991000|duration=46|duration_time=0.046000|size=339|pos=210625|flags=K__|data_hash=CRC32:1aeda6e0 +packet|codec_type=video|stream_index=0|pts=6006|pts_time=6.006000|dts=6006|dts_time=6.006000|duration=33|duration_time=0.033000|size=1700|pos=210981|flags=___|data_hash=CRC32:6352f8f3 +packet|codec_type=audio|stream_index=1|pts=6037|pts_time=6.037000|dts=6037|dts_time=6.037000|duration=46|duration_time=0.046000|size=336|pos=212701|flags=K__|data_hash=CRC32:2df5ef30 +packet|codec_type=video|stream_index=0|pts=6039|pts_time=6.039000|dts=6039|dts_time=6.039000|duration=33|duration_time=0.033000|size=1647|pos=213054|flags=___|data_hash=CRC32:931d3120 +packet|codec_type=video|stream_index=0|pts=6073|pts_time=6.073000|dts=6073|dts_time=6.073000|duration=33|duration_time=0.033000|size=1663|pos=214721|flags=___|data_hash=CRC32:3191d8b9 +packet|codec_type=audio|stream_index=1|pts=6084|pts_time=6.084000|dts=6084|dts_time=6.084000|duration=46|duration_time=0.046000|size=331|pos=216404|flags=K__|data_hash=CRC32:81610328 +packet|codec_type=video|stream_index=0|pts=6106|pts_time=6.106000|dts=6106|dts_time=6.106000|duration=33|duration_time=0.033000|size=1512|pos=216752|flags=___|data_hash=CRC32:975cd742 +packet|codec_type=audio|stream_index=1|pts=6130|pts_time=6.130000|dts=6130|dts_time=6.130000|duration=46|duration_time=0.046000|size=335|pos=218284|flags=K__|data_hash=CRC32:7a0eaa18 +packet|codec_type=video|stream_index=0|pts=6139|pts_time=6.139000|dts=6139|dts_time=6.139000|duration=33|duration_time=0.033000|size=1370|pos=218636|flags=___|data_hash=CRC32:66567f2e +packet|codec_type=video|stream_index=0|pts=6173|pts_time=6.173000|dts=6173|dts_time=6.173000|duration=33|duration_time=0.033000|size=1440|pos=220026|flags=___|data_hash=CRC32:4bfade47 +packet|codec_type=audio|stream_index=1|pts=6177|pts_time=6.177000|dts=6177|dts_time=6.177000|duration=46|duration_time=0.046000|size=323|pos=221486|flags=K__|data_hash=CRC32:3799307f +packet|codec_type=video|stream_index=0|pts=6206|pts_time=6.206000|dts=6206|dts_time=6.206000|duration=33|duration_time=0.033000|size=1574|pos=221826|flags=___|data_hash=CRC32:a489fa6f +packet|codec_type=audio|stream_index=1|pts=6223|pts_time=6.223000|dts=6223|dts_time=6.223000|duration=46|duration_time=0.046000|size=333|pos=223420|flags=K__|data_hash=CRC32:c8363968 +packet|codec_type=video|stream_index=0|pts=6240|pts_time=6.240000|dts=6240|dts_time=6.240000|duration=33|duration_time=0.033000|size=1328|pos=223770|flags=___|data_hash=CRC32:1fea5aac +packet|codec_type=audio|stream_index=1|pts=6269|pts_time=6.269000|dts=6269|dts_time=6.269000|duration=46|duration_time=0.046000|size=335|pos=225118|flags=K__|data_hash=CRC32:b9425c66 +packet|codec_type=video|stream_index=0|pts=6273|pts_time=6.273000|dts=6273|dts_time=6.273000|duration=33|duration_time=0.033000|size=1802|pos=225470|flags=___|data_hash=CRC32:dcf03b48 +packet|codec_type=video|stream_index=0|pts=6306|pts_time=6.306000|dts=6306|dts_time=6.306000|duration=33|duration_time=0.033000|size=1619|pos=227292|flags=___|data_hash=CRC32:fe0b0001 +packet|codec_type=audio|stream_index=1|pts=6316|pts_time=6.316000|dts=6316|dts_time=6.316000|duration=46|duration_time=0.046000|size=334|pos=228931|flags=K__|data_hash=CRC32:ec0fe921 +packet|codec_type=video|stream_index=0|pts=6340|pts_time=6.340000|dts=6340|dts_time=6.340000|duration=33|duration_time=0.033000|size=1471|pos=229282|flags=___|data_hash=CRC32:d30c0223 +packet|codec_type=audio|stream_index=1|pts=6362|pts_time=6.362000|dts=6362|dts_time=6.362000|duration=46|duration_time=0.046000|size=342|pos=230773|flags=K__|data_hash=CRC32:f18fb26f +packet|codec_type=video|stream_index=0|pts=6373|pts_time=6.373000|dts=6373|dts_time=6.373000|duration=33|duration_time=0.033000|size=1226|pos=231132|flags=___|data_hash=CRC32:7336c586 +packet|codec_type=video|stream_index=0|pts=6406|pts_time=6.406000|dts=6406|dts_time=6.406000|duration=33|duration_time=0.033000|size=1485|pos=232378|flags=___|data_hash=CRC32:6f6eae16 +packet|codec_type=audio|stream_index=1|pts=6409|pts_time=6.409000|dts=6409|dts_time=6.409000|duration=46|duration_time=0.046000|size=358|pos=233883|flags=K__|data_hash=CRC32:ef6dc063 +packet|codec_type=video|stream_index=0|pts=6440|pts_time=6.440000|dts=6440|dts_time=6.440000|duration=33|duration_time=0.033000|size=1786|pos=234258|flags=___|data_hash=CRC32:0d06af0a +packet|codec_type=audio|stream_index=1|pts=6455|pts_time=6.455000|dts=6455|dts_time=6.455000|duration=46|duration_time=0.046000|size=360|pos=236064|flags=K__|data_hash=CRC32:21588c84 +packet|codec_type=video|stream_index=0|pts=6473|pts_time=6.473000|dts=6473|dts_time=6.473000|duration=33|duration_time=0.033000|size=1345|pos=236441|flags=___|data_hash=CRC32:be3a88c3 +packet|codec_type=audio|stream_index=1|pts=6502|pts_time=6.502000|dts=6502|dts_time=6.502000|duration=46|duration_time=0.046000|size=357|pos=237806|flags=K__|data_hash=CRC32:2b9aa0fa +packet|codec_type=video|stream_index=0|pts=6507|pts_time=6.507000|dts=6507|dts_time=6.507000|duration=33|duration_time=0.033000|size=8275|pos=238180|flags=K__|data_hash=CRC32:a7db122a +packet|codec_type=video|stream_index=0|pts=6540|pts_time=6.540000|dts=6540|dts_time=6.540000|duration=33|duration_time=0.033000|size=698|pos=246475|flags=___|data_hash=CRC32:333944af +packet|codec_type=audio|stream_index=1|pts=6548|pts_time=6.548000|dts=6548|dts_time=6.548000|duration=46|duration_time=0.046000|size=336|pos=247193|flags=K__|data_hash=CRC32:57dbe1a1 +packet|codec_type=video|stream_index=0|pts=6573|pts_time=6.573000|dts=6573|dts_time=6.573000|duration=33|duration_time=0.033000|size=1298|pos=247546|flags=___|data_hash=CRC32:e4a95b13 +packet|codec_type=audio|stream_index=1|pts=6594|pts_time=6.594000|dts=6594|dts_time=6.594000|duration=46|duration_time=0.046000|size=343|pos=248864|flags=K__|data_hash=CRC32:ed44ae94 +packet|codec_type=video|stream_index=0|pts=6607|pts_time=6.607000|dts=6607|dts_time=6.607000|duration=33|duration_time=0.033000|size=1454|pos=249224|flags=___|data_hash=CRC32:40218f22 +packet|codec_type=video|stream_index=0|pts=6640|pts_time=6.640000|dts=6640|dts_time=6.640000|duration=33|duration_time=0.033000|size=1352|pos=250698|flags=___|data_hash=CRC32:06fd2643 +packet|codec_type=audio|stream_index=1|pts=6641|pts_time=6.641000|dts=6641|dts_time=6.641000|duration=46|duration_time=0.046000|size=324|pos=252070|flags=K__|data_hash=CRC32:0a20b257 +packet|codec_type=video|stream_index=0|pts=6673|pts_time=6.673000|dts=6673|dts_time=6.673000|duration=33|duration_time=0.033000|size=1609|pos=252411|flags=___|data_hash=CRC32:73d71cca +packet|codec_type=audio|stream_index=1|pts=6687|pts_time=6.687000|dts=6687|dts_time=6.687000|duration=46|duration_time=0.046000|size=322|pos=254040|flags=K__|data_hash=CRC32:32957adb +packet|codec_type=video|stream_index=0|pts=6707|pts_time=6.707000|dts=6707|dts_time=6.707000|duration=33|duration_time=0.033000|size=1476|pos=254379|flags=___|data_hash=CRC32:226c92f5 +packet|codec_type=audio|stream_index=1|pts=6734|pts_time=6.734000|dts=6734|dts_time=6.734000|duration=46|duration_time=0.046000|size=328|pos=255875|flags=K__|data_hash=CRC32:f2deeca5 +packet|codec_type=video|stream_index=0|pts=6740|pts_time=6.740000|dts=6740|dts_time=6.740000|duration=33|duration_time=0.033000|size=1391|pos=256220|flags=___|data_hash=CRC32:9a20a6cc +packet|codec_type=video|stream_index=0|pts=6773|pts_time=6.773000|dts=6773|dts_time=6.773000|duration=33|duration_time=0.033000|size=1203|pos=257631|flags=___|data_hash=CRC32:694b79e2 +packet|codec_type=audio|stream_index=1|pts=6780|pts_time=6.780000|dts=6780|dts_time=6.780000|duration=46|duration_time=0.046000|size=332|pos=258854|flags=K__|data_hash=CRC32:69c10e24 +packet|codec_type=video|stream_index=0|pts=6807|pts_time=6.807000|dts=6807|dts_time=6.807000|duration=33|duration_time=0.033000|size=1489|pos=259203|flags=___|data_hash=CRC32:72a4b942 +packet|codec_type=audio|stream_index=1|pts=6827|pts_time=6.827000|dts=6827|dts_time=6.827000|duration=46|duration_time=0.046000|size=343|pos=260712|flags=K__|data_hash=CRC32:59e5debb +packet|codec_type=video|stream_index=0|pts=6840|pts_time=6.840000|dts=6840|dts_time=6.840000|duration=33|duration_time=0.033000|size=1655|pos=261072|flags=___|data_hash=CRC32:d23af0f0 +packet|codec_type=audio|stream_index=1|pts=6873|pts_time=6.873000|dts=6873|dts_time=6.873000|duration=46|duration_time=0.046000|size=343|pos=262747|flags=K__|data_hash=CRC32:3a753534 +packet|codec_type=video|stream_index=0|pts=6874|pts_time=6.874000|dts=6874|dts_time=6.874000|duration=33|duration_time=0.033000|size=1363|pos=263107|flags=___|data_hash=CRC32:a3c3183f +packet|codec_type=video|stream_index=0|pts=6907|pts_time=6.907000|dts=6907|dts_time=6.907000|duration=33|duration_time=0.033000|size=1492|pos=264490|flags=___|data_hash=CRC32:2efa7752 +packet|codec_type=audio|stream_index=1|pts=6920|pts_time=6.920000|dts=6920|dts_time=6.920000|duration=46|duration_time=0.046000|size=327|pos=266002|flags=K__|data_hash=CRC32:0c6cfc20 +packet|codec_type=video|stream_index=0|pts=6940|pts_time=6.940000|dts=6940|dts_time=6.940000|duration=33|duration_time=0.033000|size=1397|pos=266346|flags=___|data_hash=CRC32:f4cff2aa +packet|codec_type=audio|stream_index=1|pts=6966|pts_time=6.966000|dts=6966|dts_time=6.966000|duration=46|duration_time=0.046000|size=326|pos=267763|flags=K__|data_hash=CRC32:0287694a +packet|codec_type=video|stream_index=0|pts=6974|pts_time=6.974000|dts=6974|dts_time=6.974000|duration=33|duration_time=0.033000|size=1251|pos=268106|flags=___|data_hash=CRC32:24f376e2 +packet|codec_type=video|stream_index=0|pts=7007|pts_time=7.007000|dts=7007|dts_time=7.007000|duration=33|duration_time=0.033000|size=1586|pos=269377|flags=___|data_hash=CRC32:6894eed6 +packet|codec_type=audio|stream_index=1|pts=7012|pts_time=7.012000|dts=7012|dts_time=7.012000|duration=46|duration_time=0.046000|size=324|pos=270983|flags=K__|data_hash=CRC32:7131ae4e +packet|codec_type=video|stream_index=0|pts=7040|pts_time=7.040000|dts=7040|dts_time=7.040000|duration=33|duration_time=0.033000|size=1333|pos=271324|flags=___|data_hash=CRC32:c70a7aad +packet|codec_type=audio|stream_index=1|pts=7059|pts_time=7.059000|dts=7059|dts_time=7.059000|duration=46|duration_time=0.046000|size=312|pos=272677|flags=K__|data_hash=CRC32:19e4ee3f +packet|codec_type=video|stream_index=0|pts=7074|pts_time=7.074000|dts=7074|dts_time=7.074000|duration=33|duration_time=0.033000|size=2723|pos=273006|flags=___|data_hash=CRC32:a6013df5 +packet|codec_type=audio|stream_index=1|pts=7105|pts_time=7.105000|dts=7105|dts_time=7.105000|duration=46|duration_time=0.046000|size=308|pos=275749|flags=K__|data_hash=CRC32:c90c6296 +packet|codec_type=video|stream_index=0|pts=7107|pts_time=7.107000|dts=7107|dts_time=7.107000|duration=33|duration_time=0.033000|size=632|pos=276074|flags=___|data_hash=CRC32:24dd0b1b +packet|codec_type=video|stream_index=0|pts=7140|pts_time=7.140000|dts=7140|dts_time=7.140000|duration=33|duration_time=0.033000|size=444|pos=276726|flags=___|data_hash=CRC32:f0104674 +packet|codec_type=audio|stream_index=1|pts=7152|pts_time=7.152000|dts=7152|dts_time=7.152000|duration=46|duration_time=0.046000|size=308|pos=277190|flags=K__|data_hash=CRC32:801d3efb +packet|codec_type=video|stream_index=0|pts=7174|pts_time=7.174000|dts=7174|dts_time=7.174000|duration=33|duration_time=0.033000|size=1013|pos=277515|flags=___|data_hash=CRC32:50fd7439 +packet|codec_type=audio|stream_index=1|pts=7198|pts_time=7.198000|dts=7198|dts_time=7.198000|duration=46|duration_time=0.046000|size=318|pos=278548|flags=K__|data_hash=CRC32:da27ff29 +packet|codec_type=video|stream_index=0|pts=7207|pts_time=7.207000|dts=7207|dts_time=7.207000|duration=33|duration_time=0.033000|size=1357|pos=278883|flags=___|data_hash=CRC32:147764fe +packet|codec_type=video|stream_index=0|pts=7241|pts_time=7.241000|dts=7241|dts_time=7.241000|duration=33|duration_time=0.033000|size=1586|pos=280260|flags=___|data_hash=CRC32:6ba61f38 +packet|codec_type=audio|stream_index=1|pts=7245|pts_time=7.245000|dts=7245|dts_time=7.245000|duration=46|duration_time=0.046000|size=331|pos=281866|flags=K__|data_hash=CRC32:ff54d1a1 +packet|codec_type=video|stream_index=0|pts=7274|pts_time=7.274000|dts=7274|dts_time=7.274000|duration=33|duration_time=0.033000|size=2514|pos=282214|flags=___|data_hash=CRC32:ee50c38f +packet|codec_type=audio|stream_index=1|pts=7291|pts_time=7.291000|dts=7291|dts_time=7.291000|duration=46|duration_time=0.046000|size=329|pos=284748|flags=K__|data_hash=CRC32:af348626 +packet|codec_type=video|stream_index=0|pts=7307|pts_time=7.307000|dts=7307|dts_time=7.307000|duration=33|duration_time=0.033000|size=450|pos=285094|flags=___|data_hash=CRC32:4c566b91 +packet|codec_type=audio|stream_index=1|pts=7338|pts_time=7.338000|dts=7338|dts_time=7.338000|duration=46|duration_time=0.046000|size=333|pos=285564|flags=K__|data_hash=CRC32:561118f2 +packet|codec_type=video|stream_index=0|pts=7341|pts_time=7.341000|dts=7341|dts_time=7.341000|duration=33|duration_time=0.033000|size=423|pos=285914|flags=___|data_hash=CRC32:799d9d42 +packet|codec_type=video|stream_index=0|pts=7374|pts_time=7.374000|dts=7374|dts_time=7.374000|duration=33|duration_time=0.033000|size=1161|pos=286357|flags=___|data_hash=CRC32:f37f1ffc +packet|codec_type=audio|stream_index=1|pts=7384|pts_time=7.384000|dts=7384|dts_time=7.384000|duration=46|duration_time=0.046000|size=314|pos=287538|flags=K__|data_hash=CRC32:ab18160b +packet|codec_type=video|stream_index=0|pts=7407|pts_time=7.407000|dts=7407|dts_time=7.407000|duration=33|duration_time=0.033000|size=1366|pos=287869|flags=___|data_hash=CRC32:6484b277 +packet|codec_type=audio|stream_index=1|pts=7430|pts_time=7.430000|dts=7430|dts_time=7.430000|duration=46|duration_time=0.046000|size=304|pos=289255|flags=K__|data_hash=CRC32:823aa6c6 +packet|codec_type=video|stream_index=0|pts=7441|pts_time=7.441000|dts=7441|dts_time=7.441000|duration=33|duration_time=0.033000|size=1325|pos=289576|flags=___|data_hash=CRC32:6eb411da +packet|codec_type=video|stream_index=0|pts=7474|pts_time=7.474000|dts=7474|dts_time=7.474000|duration=33|duration_time=0.033000|size=2687|pos=290921|flags=___|data_hash=CRC32:dc8f2e68 +packet|codec_type=audio|stream_index=1|pts=7477|pts_time=7.477000|dts=7477|dts_time=7.477000|duration=46|duration_time=0.046000|size=299|pos=293628|flags=K__|data_hash=CRC32:92c86961 +packet|codec_type=video|stream_index=0|pts=7508|pts_time=7.508000|dts=7508|dts_time=7.508000|duration=33|duration_time=0.033000|size=678|pos=293944|flags=___|data_hash=CRC32:bbd3fb62 +packet|codec_type=audio|stream_index=1|pts=7523|pts_time=7.523000|dts=7523|dts_time=7.523000|duration=46|duration_time=0.046000|size=311|pos=294642|flags=K__|data_hash=CRC32:8f7e6535 +packet|codec_type=video|stream_index=0|pts=7541|pts_time=7.541000|dts=7541|dts_time=7.541000|duration=33|duration_time=0.033000|size=491|pos=294970|flags=___|data_hash=CRC32:44e5e238 +packet|codec_type=audio|stream_index=1|pts=7570|pts_time=7.570000|dts=7570|dts_time=7.570000|duration=46|duration_time=0.046000|size=323|pos=295481|flags=K__|data_hash=CRC32:4572a6b6 +packet|codec_type=video|stream_index=0|pts=7574|pts_time=7.574000|dts=7574|dts_time=7.574000|duration=33|duration_time=0.033000|size=1056|pos=295821|flags=___|data_hash=CRC32:59790f4a +packet|codec_type=video|stream_index=0|pts=7608|pts_time=7.608000|dts=7608|dts_time=7.608000|duration=33|duration_time=0.033000|size=1549|pos=296897|flags=___|data_hash=CRC32:ede372d1 +packet|codec_type=audio|stream_index=1|pts=7616|pts_time=7.616000|dts=7616|dts_time=7.616000|duration=46|duration_time=0.046000|size=317|pos=298466|flags=K__|data_hash=CRC32:217926a5 +packet|codec_type=video|stream_index=0|pts=7641|pts_time=7.641000|dts=7641|dts_time=7.641000|duration=33|duration_time=0.033000|size=2502|pos=298800|flags=___|data_hash=CRC32:b4c753cb +packet|codec_type=audio|stream_index=1|pts=7663|pts_time=7.663000|dts=7663|dts_time=7.663000|duration=46|duration_time=0.046000|size=322|pos=301322|flags=K__|data_hash=CRC32:66da2414 +packet|codec_type=video|stream_index=0|pts=7674|pts_time=7.674000|dts=7674|dts_time=7.674000|duration=33|duration_time=0.033000|size=539|pos=301661|flags=___|data_hash=CRC32:957ce92c +packet|codec_type=video|stream_index=0|pts=7708|pts_time=7.708000|dts=7708|dts_time=7.708000|duration=33|duration_time=0.033000|size=594|pos=302220|flags=___|data_hash=CRC32:01178bad +packet|codec_type=audio|stream_index=1|pts=7709|pts_time=7.709000|dts=7709|dts_time=7.709000|duration=46|duration_time=0.046000|size=329|pos=302834|flags=K__|data_hash=CRC32:8570ef58 +packet|codec_type=video|stream_index=0|pts=7741|pts_time=7.741000|dts=7741|dts_time=7.741000|duration=33|duration_time=0.033000|size=1254|pos=303180|flags=___|data_hash=CRC32:7b42fdb2 +packet|codec_type=audio|stream_index=1|pts=7755|pts_time=7.755000|dts=7755|dts_time=7.755000|duration=46|duration_time=0.046000|size=342|pos=304454|flags=K__|data_hash=CRC32:866b46d1 +packet|codec_type=video|stream_index=0|pts=7774|pts_time=7.774000|dts=7774|dts_time=7.774000|duration=33|duration_time=0.033000|size=1341|pos=304813|flags=___|data_hash=CRC32:76ee5810 +packet|codec_type=audio|stream_index=1|pts=7802|pts_time=7.802000|dts=7802|dts_time=7.802000|duration=46|duration_time=0.046000|size=331|pos=306174|flags=K__|data_hash=CRC32:e836a9c7 +packet|codec_type=video|stream_index=0|pts=7808|pts_time=7.808000|dts=7808|dts_time=7.808000|duration=33|duration_time=0.033000|size=1358|pos=306522|flags=___|data_hash=CRC32:935430a2 +packet|codec_type=video|stream_index=0|pts=7841|pts_time=7.841000|dts=7841|dts_time=7.841000|duration=33|duration_time=0.033000|size=2336|pos=307900|flags=___|data_hash=CRC32:3ed5a208 +packet|codec_type=audio|stream_index=1|pts=7848|pts_time=7.848000|dts=7848|dts_time=7.848000|duration=46|duration_time=0.046000|size=343|pos=310256|flags=K__|data_hash=CRC32:eb15e72d +packet|codec_type=video|stream_index=0|pts=7875|pts_time=7.875000|dts=7875|dts_time=7.875000|duration=33|duration_time=0.033000|size=339|pos=310616|flags=___|data_hash=CRC32:10d2e236 +packet|codec_type=audio|stream_index=1|pts=7895|pts_time=7.895000|dts=7895|dts_time=7.895000|duration=46|duration_time=0.046000|size=327|pos=310975|flags=K__|data_hash=CRC32:fa82f874 +packet|codec_type=video|stream_index=0|pts=7908|pts_time=7.908000|dts=7908|dts_time=7.908000|duration=33|duration_time=0.033000|size=2159|pos=311319|flags=___|data_hash=CRC32:d84ad78a +packet|codec_type=audio|stream_index=1|pts=7941|pts_time=7.941000|dts=7941|dts_time=7.941000|duration=46|duration_time=0.046000|size=317|pos=313498|flags=K__|data_hash=CRC32:2f9ae86b +packet|codec_type=video|stream_index=0|pts=7941|pts_time=7.941000|dts=7941|dts_time=7.941000|duration=33|duration_time=0.033000|size=390|pos=313832|flags=___|data_hash=CRC32:d5f6e16d +packet|codec_type=video|stream_index=0|pts=7975|pts_time=7.975000|dts=7975|dts_time=7.975000|duration=33|duration_time=0.033000|size=479|pos=314242|flags=___|data_hash=CRC32:62ef0b83 +packet|codec_type=audio|stream_index=1|pts=7988|pts_time=7.988000|dts=7988|dts_time=7.988000|duration=46|duration_time=0.046000|size=313|pos=314741|flags=K__|data_hash=CRC32:de3136c8 +packet|codec_type=video|stream_index=0|pts=8008|pts_time=8.008000|dts=8008|dts_time=8.008000|duration=33|duration_time=0.033000|size=2157|pos=315071|flags=___|data_hash=CRC32:0cef0137 +packet|codec_type=audio|stream_index=1|pts=8034|pts_time=8.034000|dts=8034|dts_time=8.034000|duration=46|duration_time=0.046000|size=312|pos=317248|flags=K__|data_hash=CRC32:4abd9c07 +packet|codec_type=video|stream_index=0|pts=8041|pts_time=8.041000|dts=8041|dts_time=8.041000|duration=33|duration_time=0.033000|size=429|pos=317577|flags=___|data_hash=CRC32:87ebdeb2 +packet|codec_type=video|stream_index=0|pts=8075|pts_time=8.075000|dts=8075|dts_time=8.075000|duration=33|duration_time=0.033000|size=1953|pos=318026|flags=___|data_hash=CRC32:02a64621 +packet|codec_type=audio|stream_index=1|pts=8081|pts_time=8.081000|dts=8081|dts_time=8.081000|duration=46|duration_time=0.046000|size=318|pos=319999|flags=K__|data_hash=CRC32:f22024a9 +packet|codec_type=video|stream_index=0|pts=8108|pts_time=8.108000|dts=8108|dts_time=8.108000|duration=33|duration_time=0.033000|size=379|pos=320334|flags=___|data_hash=CRC32:b62cddd2 +packet|codec_type=audio|stream_index=1|pts=8127|pts_time=8.127000|dts=8127|dts_time=8.127000|duration=46|duration_time=0.046000|size=325|pos=320733|flags=K__|data_hash=CRC32:64fd8299 +packet|codec_type=video|stream_index=0|pts=8141|pts_time=8.141000|dts=8141|dts_time=8.141000|duration=33|duration_time=0.033000|size=1817|pos=321075|flags=___|data_hash=CRC32:c8592216 +packet|codec_type=audio|stream_index=1|pts=8173|pts_time=8.173000|dts=8173|dts_time=8.173000|duration=46|duration_time=0.046000|size=317|pos=322912|flags=K__|data_hash=CRC32:4691c3cf +packet|codec_type=video|stream_index=0|pts=8175|pts_time=8.175000|dts=8175|dts_time=8.175000|duration=33|duration_time=0.033000|size=372|pos=323246|flags=___|data_hash=CRC32:97c375b0 +packet|codec_type=video|stream_index=0|pts=8208|pts_time=8.208000|dts=8208|dts_time=8.208000|duration=33|duration_time=0.033000|size=1664|pos=323638|flags=___|data_hash=CRC32:ca3e11a7 +packet|codec_type=audio|stream_index=1|pts=8220|pts_time=8.220000|dts=8220|dts_time=8.220000|duration=46|duration_time=0.046000|size=308|pos=325322|flags=K__|data_hash=CRC32:09626471 +packet|codec_type=video|stream_index=0|pts=8242|pts_time=8.242000|dts=8242|dts_time=8.242000|duration=33|duration_time=0.033000|size=340|pos=325647|flags=___|data_hash=CRC32:a779f4f7 +packet|codec_type=audio|stream_index=1|pts=8266|pts_time=8.266000|dts=8266|dts_time=8.266000|duration=46|duration_time=0.046000|size=309|pos=326007|flags=K__|data_hash=CRC32:728889b5 +packet|codec_type=video|stream_index=0|pts=8275|pts_time=8.275000|dts=8275|dts_time=8.275000|duration=33|duration_time=0.033000|size=1955|pos=326333|flags=___|data_hash=CRC32:695aa624 +packet|codec_type=video|stream_index=0|pts=8308|pts_time=8.308000|dts=8308|dts_time=8.308000|duration=33|duration_time=0.033000|size=485|pos=328308|flags=___|data_hash=CRC32:51973647 +packet|codec_type=audio|stream_index=1|pts=8313|pts_time=8.313000|dts=8313|dts_time=8.313000|duration=46|duration_time=0.046000|size=315|pos=328813|flags=K__|data_hash=CRC32:c3488703 +packet|codec_type=video|stream_index=0|pts=8342|pts_time=8.342000|dts=8342|dts_time=8.342000|duration=33|duration_time=0.033000|size=1705|pos=329145|flags=___|data_hash=CRC32:5837d8d2 +packet|codec_type=audio|stream_index=1|pts=8359|pts_time=8.359000|dts=8359|dts_time=8.359000|duration=46|duration_time=0.046000|size=340|pos=330870|flags=K__|data_hash=CRC32:9e35fdd6 +packet|codec_type=video|stream_index=0|pts=8375|pts_time=8.375000|dts=8375|dts_time=8.375000|duration=33|duration_time=0.033000|size=411|pos=331227|flags=___|data_hash=CRC32:0f50eec7 +packet|codec_type=audio|stream_index=1|pts=8406|pts_time=8.406000|dts=8406|dts_time=8.406000|duration=46|duration_time=0.046000|size=326|pos=331658|flags=K__|data_hash=CRC32:719bf8ae +packet|codec_type=video|stream_index=0|pts=8408|pts_time=8.408000|dts=8408|dts_time=8.408000|duration=33|duration_time=0.033000|size=1818|pos=332001|flags=___|data_hash=CRC32:a33c3a86 +packet|codec_type=video|stream_index=0|pts=8442|pts_time=8.442000|dts=8442|dts_time=8.442000|duration=33|duration_time=0.033000|size=304|pos=333839|flags=___|data_hash=CRC32:e192b5c4 +packet|codec_type=audio|stream_index=1|pts=8452|pts_time=8.452000|dts=8452|dts_time=8.452000|duration=46|duration_time=0.046000|size=333|pos=334163|flags=K__|data_hash=CRC32:e927cbe1 +packet|codec_type=video|stream_index=0|pts=8475|pts_time=8.475000|dts=8475|dts_time=8.475000|duration=33|duration_time=0.033000|size=6302|pos=334513|flags=K__|data_hash=CRC32:2290178c +packet|codec_type=audio|stream_index=1|pts=8499|pts_time=8.499000|dts=8499|dts_time=8.499000|duration=46|duration_time=0.046000|size=340|pos=340835|flags=K__|data_hash=CRC32:2dfd7ad8 +packet|codec_type=video|stream_index=0|pts=8509|pts_time=8.509000|dts=8509|dts_time=8.509000|duration=33|duration_time=0.033000|size=1498|pos=341192|flags=___|data_hash=CRC32:e0611ee8 +packet|codec_type=video|stream_index=0|pts=8542|pts_time=8.542000|dts=8542|dts_time=8.542000|duration=33|duration_time=0.033000|size=434|pos=342710|flags=___|data_hash=CRC32:ffb5d9c5 +packet|codec_type=audio|stream_index=1|pts=8545|pts_time=8.545000|dts=8545|dts_time=8.545000|duration=46|duration_time=0.046000|size=338|pos=343164|flags=K__|data_hash=CRC32:954e8263 +packet|codec_type=video|stream_index=0|pts=8575|pts_time=8.575000|dts=8575|dts_time=8.575000|duration=33|duration_time=0.033000|size=1643|pos=343519|flags=___|data_hash=CRC32:c4e8ba5f +packet|codec_type=audio|stream_index=1|pts=8591|pts_time=8.591000|dts=8591|dts_time=8.591000|duration=46|duration_time=0.046000|size=357|pos=345182|flags=K__|data_hash=CRC32:944e4fde +packet|codec_type=video|stream_index=0|pts=8609|pts_time=8.609000|dts=8609|dts_time=8.609000|duration=33|duration_time=0.033000|size=213|pos=345556|flags=___|data_hash=CRC32:6b32090f +packet|codec_type=audio|stream_index=1|pts=8638|pts_time=8.638000|dts=8638|dts_time=8.638000|duration=46|duration_time=0.046000|size=340|pos=345789|flags=K__|data_hash=CRC32:edd08354 +packet|codec_type=video|stream_index=0|pts=8642|pts_time=8.642000|dts=8642|dts_time=8.642000|duration=33|duration_time=0.033000|size=1820|pos=346146|flags=___|data_hash=CRC32:e814434f +packet|codec_type=video|stream_index=0|pts=8675|pts_time=8.675000|dts=8675|dts_time=8.675000|duration=33|duration_time=0.033000|size=264|pos=347986|flags=___|data_hash=CRC32:c47e7364 +packet|codec_type=audio|stream_index=1|pts=8684|pts_time=8.684000|dts=8684|dts_time=8.684000|duration=46|duration_time=0.046000|size=335|pos=348270|flags=K__|data_hash=CRC32:6a3050c7 +packet|codec_type=video|stream_index=0|pts=8709|pts_time=8.709000|dts=8709|dts_time=8.709000|duration=33|duration_time=0.033000|size=1461|pos=348622|flags=___|data_hash=CRC32:9bf7c586 +packet|codec_type=audio|stream_index=1|pts=8731|pts_time=8.731000|dts=8731|dts_time=8.731000|duration=46|duration_time=0.046000|size=322|pos=350103|flags=K__|data_hash=CRC32:f8744c32 +packet|codec_type=video|stream_index=0|pts=8742|pts_time=8.742000|dts=8742|dts_time=8.742000|duration=33|duration_time=0.033000|size=239|pos=350442|flags=___|data_hash=CRC32:7549da5a +packet|codec_type=video|stream_index=0|pts=8775|pts_time=8.775000|dts=8775|dts_time=8.775000|duration=33|duration_time=0.033000|size=1581|pos=350701|flags=___|data_hash=CRC32:2d4be1b6 +packet|codec_type=audio|stream_index=1|pts=8777|pts_time=8.777000|dts=8777|dts_time=8.777000|duration=46|duration_time=0.046000|size=318|pos=352302|flags=K__|data_hash=CRC32:e85d4c2c +packet|codec_type=video|stream_index=0|pts=8809|pts_time=8.809000|dts=8809|dts_time=8.809000|duration=33|duration_time=0.033000|size=212|pos=352637|flags=___|data_hash=CRC32:5b804b23 +packet|codec_type=audio|stream_index=1|pts=8824|pts_time=8.824000|dts=8824|dts_time=8.824000|duration=46|duration_time=0.046000|size=326|pos=352869|flags=K__|data_hash=CRC32:a2b69ebf +packet|codec_type=video|stream_index=0|pts=8842|pts_time=8.842000|dts=8842|dts_time=8.842000|duration=33|duration_time=0.033000|size=1351|pos=353212|flags=___|data_hash=CRC32:5f901255 +packet|codec_type=audio|stream_index=1|pts=8870|pts_time=8.870000|dts=8870|dts_time=8.870000|duration=46|duration_time=0.046000|size=341|pos=354583|flags=K__|data_hash=CRC32:f928467f +packet|codec_type=video|stream_index=0|pts=8876|pts_time=8.876000|dts=8876|dts_time=8.876000|duration=33|duration_time=0.033000|size=448|pos=354941|flags=___|data_hash=CRC32:ab757d3b +packet|codec_type=video|stream_index=0|pts=8909|pts_time=8.909000|dts=8909|dts_time=8.909000|duration=33|duration_time=0.033000|size=1403|pos=355409|flags=___|data_hash=CRC32:b01c66f4 +packet|codec_type=audio|stream_index=1|pts=8916|pts_time=8.916000|dts=8916|dts_time=8.916000|duration=46|duration_time=0.046000|size=319|pos=356832|flags=K__|data_hash=CRC32:0926072d +packet|codec_type=video|stream_index=0|pts=8942|pts_time=8.942000|dts=8942|dts_time=8.942000|duration=33|duration_time=0.033000|size=491|pos=357168|flags=___|data_hash=CRC32:0367ac76 +packet|codec_type=audio|stream_index=1|pts=8963|pts_time=8.963000|dts=8963|dts_time=8.963000|duration=46|duration_time=0.046000|size=303|pos=357679|flags=K__|data_hash=CRC32:d41fe125 +packet|codec_type=video|stream_index=0|pts=8976|pts_time=8.976000|dts=8976|dts_time=8.976000|duration=33|duration_time=0.033000|size=1606|pos=357999|flags=___|data_hash=CRC32:662f0120 +packet|codec_type=audio|stream_index=1|pts=9009|pts_time=9.009000|dts=9009|dts_time=9.009000|duration=46|duration_time=0.046000|size=291|pos=359625|flags=K__|data_hash=CRC32:f90846c9 +packet|codec_type=video|stream_index=0|pts=9009|pts_time=9.009000|dts=9009|dts_time=9.009000|duration=33|duration_time=0.033000|size=304|pos=359933|flags=___|data_hash=CRC32:18968792 +packet|codec_type=video|stream_index=0|pts=9042|pts_time=9.042000|dts=9042|dts_time=9.042000|duration=33|duration_time=0.033000|size=1537|pos=360257|flags=___|data_hash=CRC32:5469d062 +packet|codec_type=audio|stream_index=1|pts=9056|pts_time=9.056000|dts=9056|dts_time=9.056000|duration=46|duration_time=0.046000|size=307|pos=361814|flags=K__|data_hash=CRC32:ef8ffe20 +packet|codec_type=video|stream_index=0|pts=9076|pts_time=9.076000|dts=9076|dts_time=9.076000|duration=33|duration_time=0.033000|size=342|pos=362138|flags=___|data_hash=CRC32:dd1d6dbb +packet|codec_type=audio|stream_index=1|pts=9102|pts_time=9.102000|dts=9102|dts_time=9.102000|duration=46|duration_time=0.046000|size=335|pos=362500|flags=K__|data_hash=CRC32:ccc6f929 +packet|codec_type=video|stream_index=0|pts=9109|pts_time=9.109000|dts=9109|dts_time=9.109000|duration=33|duration_time=0.033000|size=1405|pos=362852|flags=___|data_hash=CRC32:6558f9bb +packet|codec_type=video|stream_index=0|pts=9142|pts_time=9.142000|dts=9142|dts_time=9.142000|duration=33|duration_time=0.033000|size=351|pos=364277|flags=___|data_hash=CRC32:867aaa58 +packet|codec_type=audio|stream_index=1|pts=9149|pts_time=9.149000|dts=9149|dts_time=9.149000|duration=46|duration_time=0.046000|size=348|pos=364648|flags=K__|data_hash=CRC32:d0911535 +packet|codec_type=video|stream_index=0|pts=9176|pts_time=9.176000|dts=9176|dts_time=9.176000|duration=33|duration_time=0.033000|size=1451|pos=365013|flags=___|data_hash=CRC32:8c786cd9 +packet|codec_type=audio|stream_index=1|pts=9195|pts_time=9.195000|dts=9195|dts_time=9.195000|duration=46|duration_time=0.046000|size=346|pos=366484|flags=K__|data_hash=CRC32:4d6976df +packet|codec_type=video|stream_index=0|pts=9209|pts_time=9.209000|dts=9209|dts_time=9.209000|duration=33|duration_time=0.033000|size=490|pos=366847|flags=___|data_hash=CRC32:d80d8605 +packet|codec_type=audio|stream_index=1|pts=9242|pts_time=9.242000|dts=9242|dts_time=9.242000|duration=46|duration_time=0.046000|size=333|pos=367357|flags=K__|data_hash=CRC32:dac6e6f2 +packet|codec_type=video|stream_index=0|pts=9243|pts_time=9.243000|dts=9243|dts_time=9.243000|duration=33|duration_time=0.033000|size=1524|pos=367707|flags=___|data_hash=CRC32:c3d07b7a +packet|codec_type=video|stream_index=0|pts=9276|pts_time=9.276000|dts=9276|dts_time=9.276000|duration=33|duration_time=0.033000|size=556|pos=369251|flags=___|data_hash=CRC32:3cb8f0fa +packet|codec_type=audio|stream_index=1|pts=9288|pts_time=9.288000|dts=9288|dts_time=9.288000|duration=46|duration_time=0.046000|size=338|pos=369827|flags=K__|data_hash=CRC32:2eade044 +packet|codec_type=video|stream_index=0|pts=9309|pts_time=9.309000|dts=9309|dts_time=9.309000|duration=33|duration_time=0.033000|size=1414|pos=370182|flags=___|data_hash=CRC32:e4c49a5e +packet|codec_type=audio|stream_index=1|pts=9334|pts_time=9.334000|dts=9334|dts_time=9.334000|duration=46|duration_time=0.046000|size=328|pos=371616|flags=K__|data_hash=CRC32:2a757134 +packet|codec_type=video|stream_index=0|pts=9343|pts_time=9.343000|dts=9343|dts_time=9.343000|duration=33|duration_time=0.033000|size=808|pos=371961|flags=___|data_hash=CRC32:9ec00704 +packet|codec_type=video|stream_index=0|pts=9376|pts_time=9.376000|dts=9376|dts_time=9.376000|duration=33|duration_time=0.033000|size=871|pos=372789|flags=___|data_hash=CRC32:67e02ddd +packet|codec_type=audio|stream_index=1|pts=9381|pts_time=9.381000|dts=9381|dts_time=9.381000|duration=46|duration_time=0.046000|size=334|pos=373680|flags=K__|data_hash=CRC32:3d50fa76 +packet|codec_type=video|stream_index=0|pts=9409|pts_time=9.409000|dts=9409|dts_time=9.409000|duration=33|duration_time=0.033000|size=562|pos=374031|flags=___|data_hash=CRC32:b4925536 +packet|codec_type=audio|stream_index=1|pts=9427|pts_time=9.427000|dts=9427|dts_time=9.427000|duration=46|duration_time=0.046000|size=364|pos=374613|flags=K__|data_hash=CRC32:d936a611 +packet|codec_type=video|stream_index=0|pts=9443|pts_time=9.443000|dts=9443|dts_time=9.443000|duration=33|duration_time=0.033000|size=711|pos=374994|flags=___|data_hash=CRC32:8842cf6e +packet|codec_type=audio|stream_index=1|pts=9474|pts_time=9.474000|dts=9474|dts_time=9.474000|duration=46|duration_time=0.046000|size=350|pos=375725|flags=K__|data_hash=CRC32:004fc6a5 +packet|codec_type=video|stream_index=0|pts=9476|pts_time=9.476000|dts=9476|dts_time=9.476000|duration=33|duration_time=0.033000|size=1209|pos=376092|flags=___|data_hash=CRC32:89e0866a +packet|codec_type=video|stream_index=0|pts=9510|pts_time=9.510000|dts=9510|dts_time=9.510000|duration=33|duration_time=0.033000|size=483|pos=377321|flags=___|data_hash=CRC32:952b1a6f +packet|codec_type=audio|stream_index=1|pts=9520|pts_time=9.520000|dts=9520|dts_time=9.520000|duration=46|duration_time=0.046000|size=348|pos=377824|flags=K__|data_hash=CRC32:314e7eb1 +packet|codec_type=video|stream_index=0|pts=9543|pts_time=9.543000|dts=9543|dts_time=9.543000|duration=33|duration_time=0.033000|size=422|pos=378189|flags=___|data_hash=CRC32:97ea1adf +packet|codec_type=audio|stream_index=1|pts=9567|pts_time=9.567000|dts=9567|dts_time=9.567000|duration=46|duration_time=0.046000|size=354|pos=378631|flags=K__|data_hash=CRC32:4eb4dd74 +packet|codec_type=video|stream_index=0|pts=9576|pts_time=9.576000|dts=9576|dts_time=9.576000|duration=33|duration_time=0.033000|size=533|pos=379002|flags=___|data_hash=CRC32:32282d12 +packet|codec_type=video|stream_index=0|pts=9610|pts_time=9.610000|dts=9610|dts_time=9.610000|duration=33|duration_time=0.033000|size=490|pos=379555|flags=___|data_hash=CRC32:df09aad5 +packet|codec_type=audio|stream_index=1|pts=9613|pts_time=9.613000|dts=9613|dts_time=9.613000|duration=46|duration_time=0.046000|size=358|pos=380065|flags=K__|data_hash=CRC32:032aac0d +packet|codec_type=video|stream_index=0|pts=9643|pts_time=9.643000|dts=9643|dts_time=9.643000|duration=33|duration_time=0.033000|size=972|pos=380440|flags=___|data_hash=CRC32:dfe239a5 +packet|codec_type=audio|stream_index=1|pts=9660|pts_time=9.660000|dts=9660|dts_time=9.660000|duration=46|duration_time=0.046000|size=361|pos=381432|flags=K__|data_hash=CRC32:c758edef +packet|codec_type=video|stream_index=0|pts=9676|pts_time=9.676000|dts=9676|dts_time=9.676000|duration=33|duration_time=0.033000|size=370|pos=381810|flags=___|data_hash=CRC32:18bf63af +packet|codec_type=audio|stream_index=1|pts=9706|pts_time=9.706000|dts=9706|dts_time=9.706000|duration=46|duration_time=0.046000|size=354|pos=382200|flags=K__|data_hash=CRC32:1b23fac4 +packet|codec_type=video|stream_index=0|pts=9710|pts_time=9.710000|dts=9710|dts_time=9.710000|duration=33|duration_time=0.033000|size=348|pos=382571|flags=___|data_hash=CRC32:b6ecb8fe +packet|codec_type=video|stream_index=0|pts=9743|pts_time=9.743000|dts=9743|dts_time=9.743000|duration=33|duration_time=0.033000|size=449|pos=382939|flags=___|data_hash=CRC32:99ec4250 +packet|codec_type=audio|stream_index=1|pts=9752|pts_time=9.752000|dts=9752|dts_time=9.752000|duration=46|duration_time=0.046000|size=369|pos=383408|flags=K__|data_hash=CRC32:25045152 +packet|codec_type=video|stream_index=0|pts=9776|pts_time=9.776000|dts=9776|dts_time=9.776000|duration=33|duration_time=0.033000|size=447|pos=383794|flags=___|data_hash=CRC32:53378d54 +packet|codec_type=audio|stream_index=1|pts=9799|pts_time=9.799000|dts=9799|dts_time=9.799000|duration=46|duration_time=0.046000|size=359|pos=384261|flags=K__|data_hash=CRC32:387d406d +packet|codec_type=video|stream_index=0|pts=9810|pts_time=9.810000|dts=9810|dts_time=9.810000|duration=33|duration_time=0.033000|size=414|pos=384637|flags=___|data_hash=CRC32:ab76fa07 +packet|codec_type=video|stream_index=0|pts=9843|pts_time=9.843000|dts=9843|dts_time=9.843000|duration=33|duration_time=0.033000|size=467|pos=385071|flags=___|data_hash=CRC32:e0d0f23c +packet|codec_type=audio|stream_index=1|pts=9845|pts_time=9.845000|dts=9845|dts_time=9.845000|duration=46|duration_time=0.046000|size=348|pos=385558|flags=K__|data_hash=CRC32:13f83e98 +packet|codec_type=video|stream_index=0|pts=9877|pts_time=9.877000|dts=9877|dts_time=9.877000|duration=33|duration_time=0.033000|size=890|pos=385923|flags=___|data_hash=CRC32:ef8759d9 +packet|codec_type=audio|stream_index=1|pts=9892|pts_time=9.892000|dts=9892|dts_time=9.892000|duration=46|duration_time=0.046000|size=346|pos=386833|flags=K__|data_hash=CRC32:4c0da0e0 +packet|codec_type=video|stream_index=0|pts=9910|pts_time=9.910000|dts=9910|dts_time=9.910000|duration=33|duration_time=0.033000|size=387|pos=387196|flags=___|data_hash=CRC32:9e2b0fa2 +packet|codec_type=audio|stream_index=1|pts=9938|pts_time=9.938000|dts=9938|dts_time=9.938000|duration=46|duration_time=0.046000|size=350|pos=387603|flags=K__|data_hash=CRC32:7b52e49d +packet|codec_type=video|stream_index=0|pts=9943|pts_time=9.943000|dts=9943|dts_time=9.943000|duration=33|duration_time=0.033000|size=351|pos=387970|flags=___|data_hash=CRC32:d1874a20 +packet|codec_type=video|stream_index=0|pts=9977|pts_time=9.977000|dts=9977|dts_time=9.977000|duration=33|duration_time=0.033000|size=720|pos=388341|flags=___|data_hash=CRC32:1dbb852e +packet|codec_type=audio|stream_index=1|pts=9985|pts_time=9.985000|dts=9985|dts_time=9.985000|duration=46|duration_time=0.046000|size=359|pos=389081|flags=K__|data_hash=CRC32:6efd45ba +packet|codec_type=video|stream_index=0|pts=10010|pts_time=10.010000|dts=10010|dts_time=10.010000|duration=33|duration_time=0.033000|size=855|pos=389457|flags=___|data_hash=CRC32:9266ff7a +packet|codec_type=audio|stream_index=1|pts=10031|pts_time=10.031000|dts=10031|dts_time=10.031000|duration=46|duration_time=0.046000|size=355|pos=390332|flags=K__|data_hash=CRC32:58c387cc +packet|codec_type=video|stream_index=0|pts=10043|pts_time=10.043000|dts=10043|dts_time=10.043000|duration=33|duration_time=0.033000|size=742|pos=390704|flags=___|data_hash=CRC32:b48053b8 +packet|codec_type=audio|stream_index=1|pts=10077|pts_time=10.077000|dts=10077|dts_time=10.077000|duration=46|duration_time=0.046000|size=320|pos=391466|flags=K__|data_hash=CRC32:115fa28d +packet|codec_type=video|stream_index=0|pts=10077|pts_time=10.077000|dts=10077|dts_time=10.077000|duration=33|duration_time=0.033000|size=835|pos=391803|flags=___|data_hash=CRC32:5e06bb03 +packet|codec_type=video|stream_index=0|pts=10110|pts_time=10.110000|dts=10110|dts_time=10.110000|duration=33|duration_time=0.033000|size=1610|pos=392658|flags=___|data_hash=CRC32:fafab2d1 +packet|codec_type=audio|stream_index=1|pts=10124|pts_time=10.124000|dts=10124|dts_time=10.124000|duration=46|duration_time=0.046000|size=348|pos=394288|flags=K__|data_hash=CRC32:92d59397 +packet|codec_type=video|stream_index=0|pts=10143|pts_time=10.143000|dts=10143|dts_time=10.143000|duration=33|duration_time=0.033000|size=637|pos=394653|flags=___|data_hash=CRC32:6e59b37f +packet|codec_type=audio|stream_index=1|pts=10170|pts_time=10.170000|dts=10170|dts_time=10.170000|duration=46|duration_time=0.046000|size=370|pos=395310|flags=K__|data_hash=CRC32:3ea66fa9 +packet|codec_type=video|stream_index=0|pts=10177|pts_time=10.177000|dts=10177|dts_time=10.177000|duration=33|duration_time=0.033000|size=614|pos=395697|flags=___|data_hash=CRC32:4f7f5e8e +packet|codec_type=video|stream_index=0|pts=10210|pts_time=10.210000|dts=10210|dts_time=10.210000|duration=33|duration_time=0.033000|size=1143|pos=396331|flags=___|data_hash=CRC32:d877789c +packet|codec_type=audio|stream_index=1|pts=10217|pts_time=10.217000|dts=10217|dts_time=10.217000|duration=46|duration_time=0.046000|size=353|pos=397494|flags=K__|data_hash=CRC32:22050bd1 +packet|codec_type=video|stream_index=0|pts=10244|pts_time=10.244000|dts=10244|dts_time=10.244000|duration=33|duration_time=0.033000|size=1262|pos=397864|flags=___|data_hash=CRC32:6d88aa4f +packet|codec_type=audio|stream_index=1|pts=10263|pts_time=10.263000|dts=10263|dts_time=10.263000|duration=46|duration_time=0.046000|size=367|pos=399146|flags=K__|data_hash=CRC32:077e57a2 +packet|codec_type=video|stream_index=0|pts=10277|pts_time=10.277000|dts=10277|dts_time=10.277000|duration=33|duration_time=0.033000|size=1618|pos=399530|flags=___|data_hash=CRC32:175e29a2 +packet|codec_type=audio|stream_index=1|pts=10310|pts_time=10.310000|dts=10310|dts_time=10.310000|duration=46|duration_time=0.046000|size=350|pos=401168|flags=K__|data_hash=CRC32:346c722e +packet|codec_type=video|stream_index=0|pts=10310|pts_time=10.310000|dts=10310|dts_time=10.310000|duration=33|duration_time=0.033000|size=2345|pos=401535|flags=___|data_hash=CRC32:ccf488bd +packet|codec_type=video|stream_index=0|pts=10344|pts_time=10.344000|dts=10344|dts_time=10.344000|duration=33|duration_time=0.033000|size=1029|pos=403900|flags=___|data_hash=CRC32:4b3a69da +packet|codec_type=audio|stream_index=1|pts=10356|pts_time=10.356000|dts=10356|dts_time=10.356000|duration=46|duration_time=0.046000|size=353|pos=404949|flags=K__|data_hash=CRC32:de07f5ea +packet|codec_type=video|stream_index=0|pts=10377|pts_time=10.377000|dts=10377|dts_time=10.377000|duration=33|duration_time=0.033000|size=932|pos=405319|flags=___|data_hash=CRC32:dfb7b52c +packet|codec_type=audio|stream_index=1|pts=10403|pts_time=10.403000|dts=10403|dts_time=10.403000|duration=46|duration_time=0.046000|size=336|pos=406271|flags=K__|data_hash=CRC32:2dbed9ee +packet|codec_type=video|stream_index=0|pts=10410|pts_time=10.410000|dts=10410|dts_time=10.410000|duration=33|duration_time=0.033000|size=1688|pos=406624|flags=___|data_hash=CRC32:6fc6be0f +packet|codec_type=video|stream_index=0|pts=10444|pts_time=10.444000|dts=10444|dts_time=10.444000|duration=33|duration_time=0.033000|size=4159|pos=408332|flags=K__|data_hash=CRC32:6988ae22 +packet|codec_type=audio|stream_index=1|pts=10449|pts_time=10.449000|dts=10449|dts_time=10.449000|duration=46|duration_time=0.046000|size=334|pos=412511|flags=K__|data_hash=CRC32:7b903b6f +packet|codec_type=video|stream_index=0|pts=10477|pts_time=10.477000|dts=10477|dts_time=10.477000|duration=33|duration_time=0.033000|size=2039|pos=412862|flags=___|data_hash=CRC32:c0cf0abd +packet|codec_type=audio|stream_index=1|pts=10495|pts_time=10.495000|dts=10495|dts_time=10.495000|duration=46|duration_time=0.046000|size=358|pos=414921|flags=K__|data_hash=CRC32:2e46c79f +packet|codec_type=video|stream_index=0|pts=10511|pts_time=10.511000|dts=10511|dts_time=10.511000|duration=33|duration_time=0.033000|size=614|pos=415296|flags=___|data_hash=CRC32:682066fb +packet|codec_type=audio|stream_index=1|pts=10542|pts_time=10.542000|dts=10542|dts_time=10.542000|duration=46|duration_time=0.046000|size=344|pos=415930|flags=K__|data_hash=CRC32:037d4b43 +packet|codec_type=video|stream_index=0|pts=10544|pts_time=10.544000|dts=10544|dts_time=10.544000|duration=33|duration_time=0.033000|size=1749|pos=416291|flags=___|data_hash=CRC32:09ab2b77 +packet|codec_type=video|stream_index=0|pts=10577|pts_time=10.577000|dts=10577|dts_time=10.577000|duration=33|duration_time=0.033000|size=2609|pos=418060|flags=___|data_hash=CRC32:3630dc54 +packet|codec_type=audio|stream_index=1|pts=10588|pts_time=10.588000|dts=10588|dts_time=10.588000|duration=46|duration_time=0.046000|size=344|pos=420689|flags=K__|data_hash=CRC32:73dfce6a +packet|codec_type=video|stream_index=0|pts=10611|pts_time=10.611000|dts=10611|dts_time=10.611000|duration=33|duration_time=0.033000|size=689|pos=421050|flags=___|data_hash=CRC32:6700928b +packet|codec_type=audio|stream_index=1|pts=10635|pts_time=10.635000|dts=10635|dts_time=10.635000|duration=46|duration_time=0.046000|size=356|pos=421759|flags=K__|data_hash=CRC32:5596b779 +packet|codec_type=video|stream_index=0|pts=10644|pts_time=10.644000|dts=10644|dts_time=10.644000|duration=33|duration_time=0.033000|size=2259|pos=422132|flags=___|data_hash=CRC32:264fcb3f +packet|codec_type=video|stream_index=0|pts=10677|pts_time=10.677000|dts=10677|dts_time=10.677000|duration=33|duration_time=0.033000|size=2494|pos=424411|flags=___|data_hash=CRC32:67753c81 +packet|codec_type=audio|stream_index=1|pts=10681|pts_time=10.681000|dts=10681|dts_time=10.681000|duration=46|duration_time=0.046000|size=354|pos=426925|flags=K__|data_hash=CRC32:3d7b1c0d +packet|codec_type=video|stream_index=0|pts=10711|pts_time=10.711000|dts=10711|dts_time=10.711000|duration=33|duration_time=0.033000|size=2457|pos=427296|flags=___|data_hash=CRC32:f02a3205 +packet|codec_type=audio|stream_index=1|pts=10728|pts_time=10.728000|dts=10728|dts_time=10.728000|duration=46|duration_time=0.046000|size=330|pos=429773|flags=K__|data_hash=CRC32:f9310cfe +packet|codec_type=video|stream_index=0|pts=10744|pts_time=10.744000|dts=10744|dts_time=10.744000|duration=33|duration_time=0.033000|size=2476|pos=430120|flags=___|data_hash=CRC32:eac06b3e +packet|codec_type=audio|stream_index=1|pts=10774|pts_time=10.774000|dts=10774|dts_time=10.774000|duration=46|duration_time=0.046000|size=328|pos=432616|flags=K__|data_hash=CRC32:9618f3ab +packet|codec_type=video|stream_index=0|pts=10777|pts_time=10.777000|dts=10777|dts_time=10.777000|duration=33|duration_time=0.033000|size=2560|pos=432961|flags=___|data_hash=CRC32:4c277ba1 +packet|codec_type=video|stream_index=0|pts=10811|pts_time=10.811000|dts=10811|dts_time=10.811000|duration=33|duration_time=0.033000|size=2679|pos=435541|flags=___|data_hash=CRC32:e070caf2 +packet|codec_type=audio|stream_index=1|pts=10820|pts_time=10.820000|dts=10820|dts_time=10.820000|duration=46|duration_time=0.046000|size=351|pos=438240|flags=K__|data_hash=CRC32:19bb5b6c +packet|codec_type=video|stream_index=0|pts=10844|pts_time=10.844000|dts=10844|dts_time=10.844000|duration=33|duration_time=0.033000|size=2795|pos=438608|flags=___|data_hash=CRC32:6642234c +packet|codec_type=audio|stream_index=1|pts=10867|pts_time=10.867000|dts=10867|dts_time=10.867000|duration=46|duration_time=0.046000|size=364|pos=441423|flags=K__|data_hash=CRC32:4dbd8e39 +packet|codec_type=video|stream_index=0|pts=10878|pts_time=10.878000|dts=10878|dts_time=10.878000|duration=33|duration_time=0.033000|size=2927|pos=441804|flags=___|data_hash=CRC32:0c7d6e1b +packet|codec_type=video|stream_index=0|pts=10911|pts_time=10.911000|dts=10911|dts_time=10.911000|duration=33|duration_time=0.033000|size=2437|pos=444751|flags=___|data_hash=CRC32:29100f02 +packet|codec_type=audio|stream_index=1|pts=10913|pts_time=10.913000|dts=10913|dts_time=10.913000|duration=46|duration_time=0.046000|size=365|pos=447208|flags=K__|data_hash=CRC32:f4732e1d +packet|codec_type=video|stream_index=0|pts=10944|pts_time=10.944000|dts=10944|dts_time=10.944000|duration=33|duration_time=0.033000|size=2663|pos=447590|flags=___|data_hash=CRC32:42a7b089 +packet|codec_type=audio|stream_index=1|pts=10960|pts_time=10.960000|dts=10960|dts_time=10.960000|duration=46|duration_time=0.046000|size=341|pos=450273|flags=K__|data_hash=CRC32:270d8e2f +packet|codec_type=video|stream_index=0|pts=10978|pts_time=10.978000|dts=10978|dts_time=10.978000|duration=33|duration_time=0.033000|size=2688|pos=450631|flags=___|data_hash=CRC32:e6b1e69d +packet|codec_type=audio|stream_index=1|pts=11006|pts_time=11.006000|dts=11006|dts_time=11.006000|duration=46|duration_time=0.046000|size=330|pos=453339|flags=K__|data_hash=CRC32:ffedf602 +packet|codec_type=video|stream_index=0|pts=11011|pts_time=11.011000|dts=11011|dts_time=11.011000|duration=33|duration_time=0.033000|size=2727|pos=453686|flags=___|data_hash=CRC32:0e15158e +packet|codec_type=video|stream_index=0|pts=11044|pts_time=11.044000|dts=11044|dts_time=11.044000|duration=33|duration_time=0.033000|size=2747|pos=456433|flags=___|data_hash=CRC32:5456aa57 +packet|codec_type=audio|stream_index=1|pts=11053|pts_time=11.053000|dts=11053|dts_time=11.053000|duration=46|duration_time=0.046000|size=358|pos=459200|flags=K__|data_hash=CRC32:cac56902 +packet|codec_type=video|stream_index=0|pts=11078|pts_time=11.078000|dts=11078|dts_time=11.078000|duration=33|duration_time=0.033000|size=3602|pos=459575|flags=___|data_hash=CRC32:a332e21c +packet|codec_type=audio|stream_index=1|pts=11099|pts_time=11.099000|dts=11099|dts_time=11.099000|duration=46|duration_time=0.046000|size=367|pos=463197|flags=K__|data_hash=CRC32:6e7f4f1d +packet|codec_type=video|stream_index=0|pts=11111|pts_time=11.111000|dts=11111|dts_time=11.111000|duration=33|duration_time=0.033000|size=1334|pos=463581|flags=___|data_hash=CRC32:5c4e2f6d +packet|codec_type=video|stream_index=0|pts=11144|pts_time=11.144000|dts=11144|dts_time=11.144000|duration=33|duration_time=0.033000|size=2562|pos=464935|flags=___|data_hash=CRC32:ebc7e2ca +packet|codec_type=audio|stream_index=1|pts=11146|pts_time=11.146000|dts=11146|dts_time=11.146000|duration=46|duration_time=0.046000|size=353|pos=467517|flags=K__|data_hash=CRC32:cfe498a5 +packet|codec_type=video|stream_index=0|pts=11178|pts_time=11.178000|dts=11178|dts_time=11.178000|duration=33|duration_time=0.033000|size=2917|pos=467887|flags=___|data_hash=CRC32:77f836e3 +packet|codec_type=audio|stream_index=1|pts=11192|pts_time=11.192000|dts=11192|dts_time=11.192000|duration=46|duration_time=0.046000|size=336|pos=470824|flags=K__|data_hash=CRC32:9ee13031 +packet|codec_type=video|stream_index=0|pts=11211|pts_time=11.211000|dts=11211|dts_time=11.211000|duration=33|duration_time=0.033000|size=2788|pos=471177|flags=___|data_hash=CRC32:79aa2cce +packet|codec_type=audio|stream_index=1|pts=11238|pts_time=11.238000|dts=11238|dts_time=11.238000|duration=46|duration_time=0.046000|size=329|pos=473985|flags=K__|data_hash=CRC32:86c3f096 +packet|codec_type=video|stream_index=0|pts=11245|pts_time=11.245000|dts=11245|dts_time=11.245000|duration=33|duration_time=0.033000|size=2876|pos=474331|flags=___|data_hash=CRC32:f71a01f7 +packet|codec_type=video|stream_index=0|pts=11278|pts_time=11.278000|dts=11278|dts_time=11.278000|duration=33|duration_time=0.033000|size=2782|pos=477227|flags=___|data_hash=CRC32:66c68a76 +packet|codec_type=audio|stream_index=1|pts=11285|pts_time=11.285000|dts=11285|dts_time=11.285000|duration=46|duration_time=0.046000|size=323|pos=480029|flags=K__|data_hash=CRC32:1e715e07 +packet|codec_type=video|stream_index=0|pts=11311|pts_time=11.311000|dts=11311|dts_time=11.311000|duration=33|duration_time=0.033000|size=2393|pos=480369|flags=___|data_hash=CRC32:ca824913 +packet|codec_type=audio|stream_index=1|pts=11331|pts_time=11.331000|dts=11331|dts_time=11.331000|duration=46|duration_time=0.046000|size=328|pos=482782|flags=K__|data_hash=CRC32:57b8fe27 +packet|codec_type=video|stream_index=0|pts=11345|pts_time=11.345000|dts=11345|dts_time=11.345000|duration=33|duration_time=0.033000|size=2773|pos=483127|flags=___|data_hash=CRC32:6bc9c9d7 +packet|codec_type=audio|stream_index=1|pts=11378|pts_time=11.378000|dts=11378|dts_time=11.378000|duration=46|duration_time=0.046000|size=345|pos=485920|flags=K__|data_hash=CRC32:95f244d4 +packet|codec_type=video|stream_index=0|pts=11378|pts_time=11.378000|dts=11378|dts_time=11.378000|duration=33|duration_time=0.033000|size=2972|pos=486282|flags=___|data_hash=CRC32:9fdef1d9 +packet|codec_type=video|stream_index=0|pts=11411|pts_time=11.411000|dts=11411|dts_time=11.411000|duration=33|duration_time=0.033000|size=3480|pos=489274|flags=___|data_hash=CRC32:977f9784 +packet|codec_type=audio|stream_index=1|pts=11424|pts_time=11.424000|dts=11424|dts_time=11.424000|duration=46|duration_time=0.046000|size=345|pos=492774|flags=K__|data_hash=CRC32:9c69a0dc +packet|codec_type=video|stream_index=0|pts=11445|pts_time=11.445000|dts=11445|dts_time=11.445000|duration=33|duration_time=0.033000|size=1078|pos=493136|flags=___|data_hash=CRC32:4a479a66 +packet|codec_type=audio|stream_index=1|pts=11471|pts_time=11.471000|dts=11471|dts_time=11.471000|duration=46|duration_time=0.046000|size=349|pos=494234|flags=K__|data_hash=CRC32:0fcb70ef +packet|codec_type=video|stream_index=0|pts=11478|pts_time=11.478000|dts=11478|dts_time=11.478000|duration=33|duration_time=0.033000|size=3385|pos=494600|flags=___|data_hash=CRC32:f1d76112 +packet|codec_type=video|stream_index=0|pts=11512|pts_time=11.512000|dts=11512|dts_time=11.512000|duration=33|duration_time=0.033000|size=1408|pos=498005|flags=___|data_hash=CRC32:12165420 +packet|codec_type=audio|stream_index=1|pts=11517|pts_time=11.517000|dts=11517|dts_time=11.517000|duration=46|duration_time=0.046000|size=340|pos=499433|flags=K__|data_hash=CRC32:e867c459 +packet|codec_type=video|stream_index=0|pts=11545|pts_time=11.545000|dts=11545|dts_time=11.545000|duration=33|duration_time=0.033000|size=2543|pos=499790|flags=___|data_hash=CRC32:d3803831 +packet|codec_type=audio|stream_index=1|pts=11564|pts_time=11.564000|dts=11564|dts_time=11.564000|duration=46|duration_time=0.046000|size=352|pos=502353|flags=K__|data_hash=CRC32:029632be +packet|codec_type=video|stream_index=0|pts=11578|pts_time=11.578000|dts=11578|dts_time=11.578000|duration=33|duration_time=0.033000|size=3609|pos=502722|flags=___|data_hash=CRC32:ebd09926 +packet|codec_type=audio|stream_index=1|pts=11610|pts_time=11.610000|dts=11610|dts_time=11.610000|duration=46|duration_time=0.046000|size=345|pos=506351|flags=K__|data_hash=CRC32:8374b7c9 +packet|codec_type=video|stream_index=0|pts=11612|pts_time=11.612000|dts=11612|dts_time=11.612000|duration=33|duration_time=0.033000|size=1078|pos=506713|flags=___|data_hash=CRC32:96db1ff7 +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=__C|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_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|initial_padding=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/gapless-mp3-side-data b/tests/ref/fate/gapless-mp3-side-data index edbf91a9d22..caf42068dc4 100644 --- a/tests/ref/fate/gapless-mp3-side-data +++ b/tests/ref/fate/gapless-mp3-side-data @@ -1,600 +1,600 @@ -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_|data_hash=CRC32:ae0a5066|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__|data_hash=CRC32:ae0a5066|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=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 -packet|codec_type=audio|stream_index=0|pts=1105920|pts_time=0.078367|dts=1105920|dts_time=0.078367|duration=368640|duration_time=0.026122|size=418|pos=2704|flags=K_|data_hash=CRC32:baec14f8 -packet|codec_type=audio|stream_index=0|pts=1474560|pts_time=0.104490|dts=1474560|dts_time=0.104490|duration=368640|duration_time=0.026122|size=418|pos=3122|flags=K_|data_hash=CRC32:9916a4cf -packet|codec_type=audio|stream_index=0|pts=1843200|pts_time=0.130612|dts=1843200|dts_time=0.130612|duration=368640|duration_time=0.026122|size=418|pos=3540|flags=K_|data_hash=CRC32:a5897354 -packet|codec_type=audio|stream_index=0|pts=2211840|pts_time=0.156735|dts=2211840|dts_time=0.156735|duration=368640|duration_time=0.026122|size=418|pos=3958|flags=K_|data_hash=CRC32:3b3bd4e1 -packet|codec_type=audio|stream_index=0|pts=2580480|pts_time=0.182857|dts=2580480|dts_time=0.182857|duration=368640|duration_time=0.026122|size=418|pos=4376|flags=K_|data_hash=CRC32:5a319d96 -packet|codec_type=audio|stream_index=0|pts=2949120|pts_time=0.208980|dts=2949120|dts_time=0.208980|duration=368640|duration_time=0.026122|size=418|pos=4794|flags=K_|data_hash=CRC32:c62a20be -packet|codec_type=audio|stream_index=0|pts=3317760|pts_time=0.235102|dts=3317760|dts_time=0.235102|duration=368640|duration_time=0.026122|size=418|pos=5212|flags=K_|data_hash=CRC32:233edc53 -packet|codec_type=audio|stream_index=0|pts=3686400|pts_time=0.261224|dts=3686400|dts_time=0.261224|duration=368640|duration_time=0.026122|size=418|pos=5630|flags=K_|data_hash=CRC32:62ff9ae2 -packet|codec_type=audio|stream_index=0|pts=4055040|pts_time=0.287347|dts=4055040|dts_time=0.287347|duration=368640|duration_time=0.026122|size=418|pos=6048|flags=K_|data_hash=CRC32:de77ed5e -packet|codec_type=audio|stream_index=0|pts=4423680|pts_time=0.313469|dts=4423680|dts_time=0.313469|duration=368640|duration_time=0.026122|size=418|pos=6466|flags=K_|data_hash=CRC32:1ea533a1 -packet|codec_type=audio|stream_index=0|pts=4792320|pts_time=0.339592|dts=4792320|dts_time=0.339592|duration=368640|duration_time=0.026122|size=418|pos=6884|flags=K_|data_hash=CRC32:b5b48e4b -packet|codec_type=audio|stream_index=0|pts=5160960|pts_time=0.365714|dts=5160960|dts_time=0.365714|duration=368640|duration_time=0.026122|size=418|pos=7302|flags=K_|data_hash=CRC32:afdcd44b -packet|codec_type=audio|stream_index=0|pts=5529600|pts_time=0.391837|dts=5529600|dts_time=0.391837|duration=368640|duration_time=0.026122|size=418|pos=7720|flags=K_|data_hash=CRC32:10038cf1 -packet|codec_type=audio|stream_index=0|pts=5898240|pts_time=0.417959|dts=5898240|dts_time=0.417959|duration=368640|duration_time=0.026122|size=418|pos=8138|flags=K_|data_hash=CRC32:0d72e0e3 -packet|codec_type=audio|stream_index=0|pts=6266880|pts_time=0.444082|dts=6266880|dts_time=0.444082|duration=368640|duration_time=0.026122|size=418|pos=8556|flags=K_|data_hash=CRC32:7919c1eb -packet|codec_type=audio|stream_index=0|pts=6635520|pts_time=0.470204|dts=6635520|dts_time=0.470204|duration=368640|duration_time=0.026122|size=418|pos=8974|flags=K_|data_hash=CRC32:95549eee -packet|codec_type=audio|stream_index=0|pts=7004160|pts_time=0.496327|dts=7004160|dts_time=0.496327|duration=368640|duration_time=0.026122|size=418|pos=9392|flags=K_|data_hash=CRC32:d8d5c005 -packet|codec_type=audio|stream_index=0|pts=7372800|pts_time=0.522449|dts=7372800|dts_time=0.522449|duration=368640|duration_time=0.026122|size=418|pos=9810|flags=K_|data_hash=CRC32:09a9254b -packet|codec_type=audio|stream_index=0|pts=7741440|pts_time=0.548571|dts=7741440|dts_time=0.548571|duration=368640|duration_time=0.026122|size=418|pos=10228|flags=K_|data_hash=CRC32:29cc7956 -packet|codec_type=audio|stream_index=0|pts=8110080|pts_time=0.574694|dts=8110080|dts_time=0.574694|duration=368640|duration_time=0.026122|size=418|pos=10646|flags=K_|data_hash=CRC32:cb439791 -packet|codec_type=audio|stream_index=0|pts=8478720|pts_time=0.600816|dts=8478720|dts_time=0.600816|duration=368640|duration_time=0.026122|size=418|pos=11064|flags=K_|data_hash=CRC32:7784025b -packet|codec_type=audio|stream_index=0|pts=8847360|pts_time=0.626939|dts=8847360|dts_time=0.626939|duration=368640|duration_time=0.026122|size=418|pos=11482|flags=K_|data_hash=CRC32:ad6d75d3 -packet|codec_type=audio|stream_index=0|pts=9216000|pts_time=0.653061|dts=9216000|dts_time=0.653061|duration=368640|duration_time=0.026122|size=417|pos=11900|flags=K_|data_hash=CRC32:081e0b41 -packet|codec_type=audio|stream_index=0|pts=9584640|pts_time=0.679184|dts=9584640|dts_time=0.679184|duration=368640|duration_time=0.026122|size=418|pos=12317|flags=K_|data_hash=CRC32:3c8c1e54 -packet|codec_type=audio|stream_index=0|pts=9953280|pts_time=0.705306|dts=9953280|dts_time=0.705306|duration=368640|duration_time=0.026122|size=418|pos=12735|flags=K_|data_hash=CRC32:58dea5a2 -packet|codec_type=audio|stream_index=0|pts=10321920|pts_time=0.731429|dts=10321920|dts_time=0.731429|duration=368640|duration_time=0.026122|size=418|pos=13153|flags=K_|data_hash=CRC32:d56daa18 -packet|codec_type=audio|stream_index=0|pts=10690560|pts_time=0.757551|dts=10690560|dts_time=0.757551|duration=368640|duration_time=0.026122|size=418|pos=13571|flags=K_|data_hash=CRC32:ab2b2c48 -packet|codec_type=audio|stream_index=0|pts=11059200|pts_time=0.783673|dts=11059200|dts_time=0.783673|duration=368640|duration_time=0.026122|size=418|pos=13989|flags=K_|data_hash=CRC32:52467934 -packet|codec_type=audio|stream_index=0|pts=11427840|pts_time=0.809796|dts=11427840|dts_time=0.809796|duration=368640|duration_time=0.026122|size=418|pos=14407|flags=K_|data_hash=CRC32:2e8e22fc -packet|codec_type=audio|stream_index=0|pts=11796480|pts_time=0.835918|dts=11796480|dts_time=0.835918|duration=368640|duration_time=0.026122|size=418|pos=14825|flags=K_|data_hash=CRC32:2432d9df -packet|codec_type=audio|stream_index=0|pts=12165120|pts_time=0.862041|dts=12165120|dts_time=0.862041|duration=368640|duration_time=0.026122|size=418|pos=15243|flags=K_|data_hash=CRC32:623666e1 -packet|codec_type=audio|stream_index=0|pts=12533760|pts_time=0.888163|dts=12533760|dts_time=0.888163|duration=368640|duration_time=0.026122|size=418|pos=15661|flags=K_|data_hash=CRC32:7efdc60c -packet|codec_type=audio|stream_index=0|pts=12902400|pts_time=0.914286|dts=12902400|dts_time=0.914286|duration=368640|duration_time=0.026122|size=418|pos=16079|flags=K_|data_hash=CRC32:22e96068 -packet|codec_type=audio|stream_index=0|pts=13271040|pts_time=0.940408|dts=13271040|dts_time=0.940408|duration=368640|duration_time=0.026122|size=418|pos=16497|flags=K_|data_hash=CRC32:544c1b78 -packet|codec_type=audio|stream_index=0|pts=13639680|pts_time=0.966531|dts=13639680|dts_time=0.966531|duration=368640|duration_time=0.026122|size=418|pos=16915|flags=K_|data_hash=CRC32:e9413152 -packet|codec_type=audio|stream_index=0|pts=14008320|pts_time=0.992653|dts=14008320|dts_time=0.992653|duration=368640|duration_time=0.026122|size=418|pos=17333|flags=K_|data_hash=CRC32:f1737ca4 -packet|codec_type=audio|stream_index=0|pts=14376960|pts_time=1.018776|dts=14376960|dts_time=1.018776|duration=368640|duration_time=0.026122|size=418|pos=17751|flags=K_|data_hash=CRC32:31f7139f -packet|codec_type=audio|stream_index=0|pts=14745600|pts_time=1.044898|dts=14745600|dts_time=1.044898|duration=368640|duration_time=0.026122|size=418|pos=18169|flags=K_|data_hash=CRC32:f330de95 -packet|codec_type=audio|stream_index=0|pts=15114240|pts_time=1.071020|dts=15114240|dts_time=1.071020|duration=368640|duration_time=0.026122|size=418|pos=18587|flags=K_|data_hash=CRC32:6ea0d79f -packet|codec_type=audio|stream_index=0|pts=15482880|pts_time=1.097143|dts=15482880|dts_time=1.097143|duration=368640|duration_time=0.026122|size=418|pos=19005|flags=K_|data_hash=CRC32:cd141c49 -packet|codec_type=audio|stream_index=0|pts=15851520|pts_time=1.123265|dts=15851520|dts_time=1.123265|duration=368640|duration_time=0.026122|size=418|pos=19423|flags=K_|data_hash=CRC32:45c367a6 -packet|codec_type=audio|stream_index=0|pts=16220160|pts_time=1.149388|dts=16220160|dts_time=1.149388|duration=368640|duration_time=0.026122|size=418|pos=19841|flags=K_|data_hash=CRC32:cd89cd56 -packet|codec_type=audio|stream_index=0|pts=16588800|pts_time=1.175510|dts=16588800|dts_time=1.175510|duration=368640|duration_time=0.026122|size=418|pos=20259|flags=K_|data_hash=CRC32:a293ff84 -packet|codec_type=audio|stream_index=0|pts=16957440|pts_time=1.201633|dts=16957440|dts_time=1.201633|duration=368640|duration_time=0.026122|size=418|pos=20677|flags=K_|data_hash=CRC32:a3c6725e -packet|codec_type=audio|stream_index=0|pts=17326080|pts_time=1.227755|dts=17326080|dts_time=1.227755|duration=368640|duration_time=0.026122|size=418|pos=21095|flags=K_|data_hash=CRC32:be091252 -packet|codec_type=audio|stream_index=0|pts=17694720|pts_time=1.253878|dts=17694720|dts_time=1.253878|duration=368640|duration_time=0.026122|size=418|pos=21513|flags=K_|data_hash=CRC32:a5135f75 -packet|codec_type=audio|stream_index=0|pts=18063360|pts_time=1.280000|dts=18063360|dts_time=1.280000|duration=368640|duration_time=0.026122|size=417|pos=21931|flags=K_|data_hash=CRC32:8225dd66 -packet|codec_type=audio|stream_index=0|pts=18432000|pts_time=1.306122|dts=18432000|dts_time=1.306122|duration=368640|duration_time=0.026122|size=418|pos=22348|flags=K_|data_hash=CRC32:7b1db59c -packet|codec_type=audio|stream_index=0|pts=18800640|pts_time=1.332245|dts=18800640|dts_time=1.332245|duration=368640|duration_time=0.026122|size=418|pos=22766|flags=K_|data_hash=CRC32:e5897689 -packet|codec_type=audio|stream_index=0|pts=19169280|pts_time=1.358367|dts=19169280|dts_time=1.358367|duration=368640|duration_time=0.026122|size=418|pos=23184|flags=K_|data_hash=CRC32:94929aa7 -packet|codec_type=audio|stream_index=0|pts=19537920|pts_time=1.384490|dts=19537920|dts_time=1.384490|duration=368640|duration_time=0.026122|size=418|pos=23602|flags=K_|data_hash=CRC32:65697a12 -packet|codec_type=audio|stream_index=0|pts=19906560|pts_time=1.410612|dts=19906560|dts_time=1.410612|duration=368640|duration_time=0.026122|size=418|pos=24020|flags=K_|data_hash=CRC32:18f69ad3 -packet|codec_type=audio|stream_index=0|pts=20275200|pts_time=1.436735|dts=20275200|dts_time=1.436735|duration=368640|duration_time=0.026122|size=418|pos=24438|flags=K_|data_hash=CRC32:47ab41f0 -packet|codec_type=audio|stream_index=0|pts=20643840|pts_time=1.462857|dts=20643840|dts_time=1.462857|duration=368640|duration_time=0.026122|size=418|pos=24856|flags=K_|data_hash=CRC32:75879cf2 -packet|codec_type=audio|stream_index=0|pts=21012480|pts_time=1.488980|dts=21012480|dts_time=1.488980|duration=368640|duration_time=0.026122|size=418|pos=25274|flags=K_|data_hash=CRC32:d43c0882 -packet|codec_type=audio|stream_index=0|pts=21381120|pts_time=1.515102|dts=21381120|dts_time=1.515102|duration=368640|duration_time=0.026122|size=418|pos=25692|flags=K_|data_hash=CRC32:3b9a22da -packet|codec_type=audio|stream_index=0|pts=21749760|pts_time=1.541224|dts=21749760|dts_time=1.541224|duration=368640|duration_time=0.026122|size=418|pos=26110|flags=K_|data_hash=CRC32:ec698fec -packet|codec_type=audio|stream_index=0|pts=22118400|pts_time=1.567347|dts=22118400|dts_time=1.567347|duration=368640|duration_time=0.026122|size=418|pos=26528|flags=K_|data_hash=CRC32:ca99d2c0 -packet|codec_type=audio|stream_index=0|pts=22487040|pts_time=1.593469|dts=22487040|dts_time=1.593469|duration=368640|duration_time=0.026122|size=418|pos=26946|flags=K_|data_hash=CRC32:fa370e06 -packet|codec_type=audio|stream_index=0|pts=22855680|pts_time=1.619592|dts=22855680|dts_time=1.619592|duration=368640|duration_time=0.026122|size=418|pos=27364|flags=K_|data_hash=CRC32:9522fdd4 -packet|codec_type=audio|stream_index=0|pts=23224320|pts_time=1.645714|dts=23224320|dts_time=1.645714|duration=368640|duration_time=0.026122|size=418|pos=27782|flags=K_|data_hash=CRC32:d6bd9ba4 -packet|codec_type=audio|stream_index=0|pts=23592960|pts_time=1.671837|dts=23592960|dts_time=1.671837|duration=368640|duration_time=0.026122|size=418|pos=28200|flags=K_|data_hash=CRC32:f4689266 -packet|codec_type=audio|stream_index=0|pts=23961600|pts_time=1.697959|dts=23961600|dts_time=1.697959|duration=368640|duration_time=0.026122|size=418|pos=28618|flags=K_|data_hash=CRC32:ea1aaa66 -packet|codec_type=audio|stream_index=0|pts=24330240|pts_time=1.724082|dts=24330240|dts_time=1.724082|duration=368640|duration_time=0.026122|size=418|pos=29036|flags=K_|data_hash=CRC32:fb547f37 -packet|codec_type=audio|stream_index=0|pts=24698880|pts_time=1.750204|dts=24698880|dts_time=1.750204|duration=368640|duration_time=0.026122|size=418|pos=29454|flags=K_|data_hash=CRC32:78f84f3f -packet|codec_type=audio|stream_index=0|pts=25067520|pts_time=1.776327|dts=25067520|dts_time=1.776327|duration=368640|duration_time=0.026122|size=418|pos=29872|flags=K_|data_hash=CRC32:db07bf11 -packet|codec_type=audio|stream_index=0|pts=25436160|pts_time=1.802449|dts=25436160|dts_time=1.802449|duration=368640|duration_time=0.026122|size=418|pos=30290|flags=K_|data_hash=CRC32:77bb035b -packet|codec_type=audio|stream_index=0|pts=25804800|pts_time=1.828571|dts=25804800|dts_time=1.828571|duration=368640|duration_time=0.026122|size=418|pos=30708|flags=K_|data_hash=CRC32:23378de7 -packet|codec_type=audio|stream_index=0|pts=26173440|pts_time=1.854694|dts=26173440|dts_time=1.854694|duration=368640|duration_time=0.026122|size=418|pos=31126|flags=K_|data_hash=CRC32:17e3e719 -packet|codec_type=audio|stream_index=0|pts=26542080|pts_time=1.880816|dts=26542080|dts_time=1.880816|duration=368640|duration_time=0.026122|size=418|pos=31544|flags=K_|data_hash=CRC32:b33797de -packet|codec_type=audio|stream_index=0|pts=26910720|pts_time=1.906939|dts=26910720|dts_time=1.906939|duration=368640|duration_time=0.026122|size=418|pos=31962|flags=K_|data_hash=CRC32:d585f179 -packet|codec_type=audio|stream_index=0|pts=27279360|pts_time=1.933061|dts=27279360|dts_time=1.933061|duration=368640|duration_time=0.026122|size=417|pos=32380|flags=K_|data_hash=CRC32:469f8f74 -packet|codec_type=audio|stream_index=0|pts=27648000|pts_time=1.959184|dts=27648000|dts_time=1.959184|duration=368640|duration_time=0.026122|size=418|pos=32797|flags=K_|data_hash=CRC32:fd53cf2f -packet|codec_type=audio|stream_index=0|pts=28016640|pts_time=1.985306|dts=28016640|dts_time=1.985306|duration=368640|duration_time=0.026122|size=418|pos=33215|flags=K_|data_hash=CRC32:5a37e9ae -packet|codec_type=audio|stream_index=0|pts=28385280|pts_time=2.011429|dts=28385280|dts_time=2.011429|duration=368640|duration_time=0.026122|size=418|pos=33633|flags=K_|data_hash=CRC32:123bf9d4 -packet|codec_type=audio|stream_index=0|pts=28753920|pts_time=2.037551|dts=28753920|dts_time=2.037551|duration=368640|duration_time=0.026122|size=418|pos=34051|flags=K_|data_hash=CRC32:a3d4074d -packet|codec_type=audio|stream_index=0|pts=29122560|pts_time=2.063673|dts=29122560|dts_time=2.063673|duration=368640|duration_time=0.026122|size=418|pos=34469|flags=K_|data_hash=CRC32:d79d5351 -packet|codec_type=audio|stream_index=0|pts=29491200|pts_time=2.089796|dts=29491200|dts_time=2.089796|duration=368640|duration_time=0.026122|size=418|pos=34887|flags=K_|data_hash=CRC32:d9a54e49 -packet|codec_type=audio|stream_index=0|pts=29859840|pts_time=2.115918|dts=29859840|dts_time=2.115918|duration=368640|duration_time=0.026122|size=418|pos=35305|flags=K_|data_hash=CRC32:e3f6826f -packet|codec_type=audio|stream_index=0|pts=30228480|pts_time=2.142041|dts=30228480|dts_time=2.142041|duration=368640|duration_time=0.026122|size=418|pos=35723|flags=K_|data_hash=CRC32:2ab209b1 -packet|codec_type=audio|stream_index=0|pts=30597120|pts_time=2.168163|dts=30597120|dts_time=2.168163|duration=368640|duration_time=0.026122|size=418|pos=36141|flags=K_|data_hash=CRC32:bec119c0 -packet|codec_type=audio|stream_index=0|pts=30965760|pts_time=2.194286|dts=30965760|dts_time=2.194286|duration=368640|duration_time=0.026122|size=418|pos=36559|flags=K_|data_hash=CRC32:5e3e13bf -packet|codec_type=audio|stream_index=0|pts=31334400|pts_time=2.220408|dts=31334400|dts_time=2.220408|duration=368640|duration_time=0.026122|size=418|pos=36977|flags=K_|data_hash=CRC32:b725b85c -packet|codec_type=audio|stream_index=0|pts=31703040|pts_time=2.246531|dts=31703040|dts_time=2.246531|duration=368640|duration_time=0.026122|size=418|pos=37395|flags=K_|data_hash=CRC32:e650f974 -packet|codec_type=audio|stream_index=0|pts=32071680|pts_time=2.272653|dts=32071680|dts_time=2.272653|duration=368640|duration_time=0.026122|size=418|pos=37813|flags=K_|data_hash=CRC32:6edc5628 -packet|codec_type=audio|stream_index=0|pts=32440320|pts_time=2.298776|dts=32440320|dts_time=2.298776|duration=368640|duration_time=0.026122|size=418|pos=38231|flags=K_|data_hash=CRC32:37adc162 -packet|codec_type=audio|stream_index=0|pts=32808960|pts_time=2.324898|dts=32808960|dts_time=2.324898|duration=368640|duration_time=0.026122|size=418|pos=38649|flags=K_|data_hash=CRC32:a4b7042e -packet|codec_type=audio|stream_index=0|pts=33177600|pts_time=2.351020|dts=33177600|dts_time=2.351020|duration=368640|duration_time=0.026122|size=418|pos=39067|flags=K_|data_hash=CRC32:c0e98589 -packet|codec_type=audio|stream_index=0|pts=33546240|pts_time=2.377143|dts=33546240|dts_time=2.377143|duration=368640|duration_time=0.026122|size=418|pos=39485|flags=K_|data_hash=CRC32:480fd334 -packet|codec_type=audio|stream_index=0|pts=33914880|pts_time=2.403265|dts=33914880|dts_time=2.403265|duration=368640|duration_time=0.026122|size=418|pos=39903|flags=K_|data_hash=CRC32:4e5d606f -packet|codec_type=audio|stream_index=0|pts=34283520|pts_time=2.429388|dts=34283520|dts_time=2.429388|duration=368640|duration_time=0.026122|size=418|pos=40321|flags=K_|data_hash=CRC32:2d18c337 -packet|codec_type=audio|stream_index=0|pts=34652160|pts_time=2.455510|dts=34652160|dts_time=2.455510|duration=368640|duration_time=0.026122|size=418|pos=40739|flags=K_|data_hash=CRC32:288170f4 -packet|codec_type=audio|stream_index=0|pts=35020800|pts_time=2.481633|dts=35020800|dts_time=2.481633|duration=368640|duration_time=0.026122|size=418|pos=41157|flags=K_|data_hash=CRC32:ce5f7aa9 -packet|codec_type=audio|stream_index=0|pts=35389440|pts_time=2.507755|dts=35389440|dts_time=2.507755|duration=368640|duration_time=0.026122|size=418|pos=41575|flags=K_|data_hash=CRC32:1f0a8297 -packet|codec_type=audio|stream_index=0|pts=35758080|pts_time=2.533878|dts=35758080|dts_time=2.533878|duration=368640|duration_time=0.026122|size=418|pos=41993|flags=K_|data_hash=CRC32:4a8b9b61 -packet|codec_type=audio|stream_index=0|pts=36126720|pts_time=2.560000|dts=36126720|dts_time=2.560000|duration=368640|duration_time=0.026122|size=417|pos=42411|flags=K_|data_hash=CRC32:e3a90971 -packet|codec_type=audio|stream_index=0|pts=36495360|pts_time=2.586122|dts=36495360|dts_time=2.586122|duration=368640|duration_time=0.026122|size=418|pos=42828|flags=K_|data_hash=CRC32:f254c3ce -packet|codec_type=audio|stream_index=0|pts=36864000|pts_time=2.612245|dts=36864000|dts_time=2.612245|duration=368640|duration_time=0.026122|size=418|pos=43246|flags=K_|data_hash=CRC32:1867a5a7 -packet|codec_type=audio|stream_index=0|pts=37232640|pts_time=2.638367|dts=37232640|dts_time=2.638367|duration=368640|duration_time=0.026122|size=418|pos=43664|flags=K_|data_hash=CRC32:0d4fd9de -packet|codec_type=audio|stream_index=0|pts=37601280|pts_time=2.664490|dts=37601280|dts_time=2.664490|duration=368640|duration_time=0.026122|size=418|pos=44082|flags=K_|data_hash=CRC32:878c4022 -packet|codec_type=audio|stream_index=0|pts=37969920|pts_time=2.690612|dts=37969920|dts_time=2.690612|duration=368640|duration_time=0.026122|size=418|pos=44500|flags=K_|data_hash=CRC32:d0b5ed85 -packet|codec_type=audio|stream_index=0|pts=38338560|pts_time=2.716735|dts=38338560|dts_time=2.716735|duration=368640|duration_time=0.026122|size=418|pos=44918|flags=K_|data_hash=CRC32:d93b8cae -packet|codec_type=audio|stream_index=0|pts=38707200|pts_time=2.742857|dts=38707200|dts_time=2.742857|duration=368640|duration_time=0.026122|size=418|pos=45336|flags=K_|data_hash=CRC32:33070649 -packet|codec_type=audio|stream_index=0|pts=39075840|pts_time=2.768980|dts=39075840|dts_time=2.768980|duration=368640|duration_time=0.026122|size=418|pos=45754|flags=K_|data_hash=CRC32:2f74cc7e -packet|codec_type=audio|stream_index=0|pts=39444480|pts_time=2.795102|dts=39444480|dts_time=2.795102|duration=368640|duration_time=0.026122|size=418|pos=46172|flags=K_|data_hash=CRC32:3c7146bc -packet|codec_type=audio|stream_index=0|pts=39813120|pts_time=2.821224|dts=39813120|dts_time=2.821224|duration=368640|duration_time=0.026122|size=418|pos=46590|flags=K_|data_hash=CRC32:62967471 -packet|codec_type=audio|stream_index=0|pts=40181760|pts_time=2.847347|dts=40181760|dts_time=2.847347|duration=368640|duration_time=0.026122|size=418|pos=47008|flags=K_|data_hash=CRC32:efd4b940 -packet|codec_type=audio|stream_index=0|pts=40550400|pts_time=2.873469|dts=40550400|dts_time=2.873469|duration=368640|duration_time=0.026122|size=418|pos=47426|flags=K_|data_hash=CRC32:45338c17 -packet|codec_type=audio|stream_index=0|pts=40919040|pts_time=2.899592|dts=40919040|dts_time=2.899592|duration=368640|duration_time=0.026122|size=418|pos=47844|flags=K_|data_hash=CRC32:0806e97f -packet|codec_type=audio|stream_index=0|pts=41287680|pts_time=2.925714|dts=41287680|dts_time=2.925714|duration=368640|duration_time=0.026122|size=418|pos=48262|flags=K_|data_hash=CRC32:7fa8c136 -packet|codec_type=audio|stream_index=0|pts=41656320|pts_time=2.951837|dts=41656320|dts_time=2.951837|duration=368640|duration_time=0.026122|size=418|pos=48680|flags=K_|data_hash=CRC32:78d7f3e3 -packet|codec_type=audio|stream_index=0|pts=42024960|pts_time=2.977959|dts=42024960|dts_time=2.977959|duration=368640|duration_time=0.026122|size=418|pos=49098|flags=K_|data_hash=CRC32:eb7f4484 -packet|codec_type=audio|stream_index=0|pts=42393600|pts_time=3.004082|dts=42393600|dts_time=3.004082|duration=368640|duration_time=0.026122|size=418|pos=49516|flags=K_|data_hash=CRC32:a2a3f48d -packet|codec_type=audio|stream_index=0|pts=42762240|pts_time=3.030204|dts=42762240|dts_time=3.030204|duration=368640|duration_time=0.026122|size=418|pos=49934|flags=K_|data_hash=CRC32:c478db4a -packet|codec_type=audio|stream_index=0|pts=43130880|pts_time=3.056327|dts=43130880|dts_time=3.056327|duration=368640|duration_time=0.026122|size=418|pos=50352|flags=K_|data_hash=CRC32:e40731af -packet|codec_type=audio|stream_index=0|pts=43499520|pts_time=3.082449|dts=43499520|dts_time=3.082449|duration=368640|duration_time=0.026122|size=418|pos=50770|flags=K_|data_hash=CRC32:74603e95 -packet|codec_type=audio|stream_index=0|pts=43868160|pts_time=3.108571|dts=43868160|dts_time=3.108571|duration=368640|duration_time=0.026122|size=418|pos=51188|flags=K_|data_hash=CRC32:6486340f -packet|codec_type=audio|stream_index=0|pts=44236800|pts_time=3.134694|dts=44236800|dts_time=3.134694|duration=368640|duration_time=0.026122|size=418|pos=51606|flags=K_|data_hash=CRC32:8cda2b23 -packet|codec_type=audio|stream_index=0|pts=44605440|pts_time=3.160816|dts=44605440|dts_time=3.160816|duration=368640|duration_time=0.026122|size=418|pos=52024|flags=K_|data_hash=CRC32:b0bd790d -packet|codec_type=audio|stream_index=0|pts=44974080|pts_time=3.186939|dts=44974080|dts_time=3.186939|duration=368640|duration_time=0.026122|size=418|pos=52442|flags=K_|data_hash=CRC32:5ae7824d -packet|codec_type=audio|stream_index=0|pts=45342720|pts_time=3.213061|dts=45342720|dts_time=3.213061|duration=368640|duration_time=0.026122|size=417|pos=52860|flags=K_|data_hash=CRC32:8ef12cf9 -packet|codec_type=audio|stream_index=0|pts=45711360|pts_time=3.239184|dts=45711360|dts_time=3.239184|duration=368640|duration_time=0.026122|size=418|pos=53277|flags=K_|data_hash=CRC32:7426d3d8 -packet|codec_type=audio|stream_index=0|pts=46080000|pts_time=3.265306|dts=46080000|dts_time=3.265306|duration=368640|duration_time=0.026122|size=418|pos=53695|flags=K_|data_hash=CRC32:87ddbc34 -packet|codec_type=audio|stream_index=0|pts=46448640|pts_time=3.291429|dts=46448640|dts_time=3.291429|duration=368640|duration_time=0.026122|size=418|pos=54113|flags=K_|data_hash=CRC32:18375ee3 -packet|codec_type=audio|stream_index=0|pts=46817280|pts_time=3.317551|dts=46817280|dts_time=3.317551|duration=368640|duration_time=0.026122|size=418|pos=54531|flags=K_|data_hash=CRC32:1b28b358 -packet|codec_type=audio|stream_index=0|pts=47185920|pts_time=3.343673|dts=47185920|dts_time=3.343673|duration=368640|duration_time=0.026122|size=418|pos=54949|flags=K_|data_hash=CRC32:576d401d -packet|codec_type=audio|stream_index=0|pts=47554560|pts_time=3.369796|dts=47554560|dts_time=3.369796|duration=368640|duration_time=0.026122|size=418|pos=55367|flags=K_|data_hash=CRC32:db2ab4fc -packet|codec_type=audio|stream_index=0|pts=47923200|pts_time=3.395918|dts=47923200|dts_time=3.395918|duration=368640|duration_time=0.026122|size=418|pos=55785|flags=K_|data_hash=CRC32:78ca7f79 -packet|codec_type=audio|stream_index=0|pts=48291840|pts_time=3.422041|dts=48291840|dts_time=3.422041|duration=368640|duration_time=0.026122|size=418|pos=56203|flags=K_|data_hash=CRC32:a35e5abd -packet|codec_type=audio|stream_index=0|pts=48660480|pts_time=3.448163|dts=48660480|dts_time=3.448163|duration=368640|duration_time=0.026122|size=418|pos=56621|flags=K_|data_hash=CRC32:682643d6 -packet|codec_type=audio|stream_index=0|pts=49029120|pts_time=3.474286|dts=49029120|dts_time=3.474286|duration=368640|duration_time=0.026122|size=418|pos=57039|flags=K_|data_hash=CRC32:e676c49e -packet|codec_type=audio|stream_index=0|pts=49397760|pts_time=3.500408|dts=49397760|dts_time=3.500408|duration=368640|duration_time=0.026122|size=418|pos=57457|flags=K_|data_hash=CRC32:b41299c0 -packet|codec_type=audio|stream_index=0|pts=49766400|pts_time=3.526531|dts=49766400|dts_time=3.526531|duration=368640|duration_time=0.026122|size=418|pos=57875|flags=K_|data_hash=CRC32:19a7a028 -packet|codec_type=audio|stream_index=0|pts=50135040|pts_time=3.552653|dts=50135040|dts_time=3.552653|duration=368640|duration_time=0.026122|size=418|pos=58293|flags=K_|data_hash=CRC32:e1d92031 -packet|codec_type=audio|stream_index=0|pts=50503680|pts_time=3.578776|dts=50503680|dts_time=3.578776|duration=368640|duration_time=0.026122|size=418|pos=58711|flags=K_|data_hash=CRC32:6fb22e33 -packet|codec_type=audio|stream_index=0|pts=50872320|pts_time=3.604898|dts=50872320|dts_time=3.604898|duration=368640|duration_time=0.026122|size=418|pos=59129|flags=K_|data_hash=CRC32:10096a70 -packet|codec_type=audio|stream_index=0|pts=51240960|pts_time=3.631020|dts=51240960|dts_time=3.631020|duration=368640|duration_time=0.026122|size=418|pos=59547|flags=K_|data_hash=CRC32:57c4a982 -packet|codec_type=audio|stream_index=0|pts=51609600|pts_time=3.657143|dts=51609600|dts_time=3.657143|duration=368640|duration_time=0.026122|size=418|pos=59965|flags=K_|data_hash=CRC32:a705d327 -packet|codec_type=audio|stream_index=0|pts=51978240|pts_time=3.683265|dts=51978240|dts_time=3.683265|duration=368640|duration_time=0.026122|size=418|pos=60383|flags=K_|data_hash=CRC32:7c2beb09 -packet|codec_type=audio|stream_index=0|pts=52346880|pts_time=3.709388|dts=52346880|dts_time=3.709388|duration=368640|duration_time=0.026122|size=418|pos=60801|flags=K_|data_hash=CRC32:7b3d1a15 -packet|codec_type=audio|stream_index=0|pts=52715520|pts_time=3.735510|dts=52715520|dts_time=3.735510|duration=368640|duration_time=0.026122|size=418|pos=61219|flags=K_|data_hash=CRC32:f99045c1 -packet|codec_type=audio|stream_index=0|pts=53084160|pts_time=3.761633|dts=53084160|dts_time=3.761633|duration=368640|duration_time=0.026122|size=418|pos=61637|flags=K_|data_hash=CRC32:dd02d72d -packet|codec_type=audio|stream_index=0|pts=53452800|pts_time=3.787755|dts=53452800|dts_time=3.787755|duration=368640|duration_time=0.026122|size=418|pos=62055|flags=K_|data_hash=CRC32:0606b50a -packet|codec_type=audio|stream_index=0|pts=53821440|pts_time=3.813878|dts=53821440|dts_time=3.813878|duration=368640|duration_time=0.026122|size=418|pos=62473|flags=K_|data_hash=CRC32:bd5ce543 -packet|codec_type=audio|stream_index=0|pts=54190080|pts_time=3.840000|dts=54190080|dts_time=3.840000|duration=368640|duration_time=0.026122|size=417|pos=62891|flags=K_|data_hash=CRC32:feabd4b3 -packet|codec_type=audio|stream_index=0|pts=54558720|pts_time=3.866122|dts=54558720|dts_time=3.866122|duration=368640|duration_time=0.026122|size=418|pos=63308|flags=K_|data_hash=CRC32:0d89c582 -packet|codec_type=audio|stream_index=0|pts=54927360|pts_time=3.892245|dts=54927360|dts_time=3.892245|duration=368640|duration_time=0.026122|size=418|pos=63726|flags=K_|data_hash=CRC32:88664f54 -packet|codec_type=audio|stream_index=0|pts=55296000|pts_time=3.918367|dts=55296000|dts_time=3.918367|duration=368640|duration_time=0.026122|size=418|pos=64144|flags=K_|data_hash=CRC32:f94cac9a -packet|codec_type=audio|stream_index=0|pts=55664640|pts_time=3.944490|dts=55664640|dts_time=3.944490|duration=368640|duration_time=0.026122|size=418|pos=64562|flags=K_|data_hash=CRC32:317dc642 -packet|codec_type=audio|stream_index=0|pts=56033280|pts_time=3.970612|dts=56033280|dts_time=3.970612|duration=368640|duration_time=0.026122|size=418|pos=64980|flags=K_|data_hash=CRC32:478887cd -packet|codec_type=audio|stream_index=0|pts=56401920|pts_time=3.996735|dts=56401920|dts_time=3.996735|duration=368640|duration_time=0.026122|size=418|pos=65398|flags=K_|data_hash=CRC32:4f8ce9d9 -packet|codec_type=audio|stream_index=0|pts=56770560|pts_time=4.022857|dts=56770560|dts_time=4.022857|duration=368640|duration_time=0.026122|size=418|pos=65816|flags=K_|data_hash=CRC32:a2af903e -packet|codec_type=audio|stream_index=0|pts=57139200|pts_time=4.048980|dts=57139200|dts_time=4.048980|duration=368640|duration_time=0.026122|size=418|pos=66234|flags=K_|data_hash=CRC32:43fd701a -packet|codec_type=audio|stream_index=0|pts=57507840|pts_time=4.075102|dts=57507840|dts_time=4.075102|duration=368640|duration_time=0.026122|size=418|pos=66652|flags=K_|data_hash=CRC32:1b823ca6 -packet|codec_type=audio|stream_index=0|pts=57876480|pts_time=4.101224|dts=57876480|dts_time=4.101224|duration=368640|duration_time=0.026122|size=418|pos=67070|flags=K_|data_hash=CRC32:bb5fc2a0 -packet|codec_type=audio|stream_index=0|pts=58245120|pts_time=4.127347|dts=58245120|dts_time=4.127347|duration=368640|duration_time=0.026122|size=418|pos=67488|flags=K_|data_hash=CRC32:9597c685 -packet|codec_type=audio|stream_index=0|pts=58613760|pts_time=4.153469|dts=58613760|dts_time=4.153469|duration=368640|duration_time=0.026122|size=418|pos=67906|flags=K_|data_hash=CRC32:1800cbc7 -packet|codec_type=audio|stream_index=0|pts=58982400|pts_time=4.179592|dts=58982400|dts_time=4.179592|duration=368640|duration_time=0.026122|size=418|pos=68324|flags=K_|data_hash=CRC32:93d29987 -packet|codec_type=audio|stream_index=0|pts=59351040|pts_time=4.205714|dts=59351040|dts_time=4.205714|duration=368640|duration_time=0.026122|size=418|pos=68742|flags=K_|data_hash=CRC32:101eaf05 -packet|codec_type=audio|stream_index=0|pts=59719680|pts_time=4.231837|dts=59719680|dts_time=4.231837|duration=368640|duration_time=0.026122|size=418|pos=69160|flags=K_|data_hash=CRC32:3098d5d0 -packet|codec_type=audio|stream_index=0|pts=60088320|pts_time=4.257959|dts=60088320|dts_time=4.257959|duration=368640|duration_time=0.026122|size=418|pos=69578|flags=K_|data_hash=CRC32:a0435280 -packet|codec_type=audio|stream_index=0|pts=60456960|pts_time=4.284082|dts=60456960|dts_time=4.284082|duration=368640|duration_time=0.026122|size=418|pos=69996|flags=K_|data_hash=CRC32:a583c03b -packet|codec_type=audio|stream_index=0|pts=60825600|pts_time=4.310204|dts=60825600|dts_time=4.310204|duration=368640|duration_time=0.026122|size=418|pos=70414|flags=K_|data_hash=CRC32:11122d17 -packet|codec_type=audio|stream_index=0|pts=61194240|pts_time=4.336327|dts=61194240|dts_time=4.336327|duration=368640|duration_time=0.026122|size=418|pos=70832|flags=K_|data_hash=CRC32:3f3070b1 -packet|codec_type=audio|stream_index=0|pts=61562880|pts_time=4.362449|dts=61562880|dts_time=4.362449|duration=368640|duration_time=0.026122|size=418|pos=71250|flags=K_|data_hash=CRC32:7fcf2489 -packet|codec_type=audio|stream_index=0|pts=61931520|pts_time=4.388571|dts=61931520|dts_time=4.388571|duration=368640|duration_time=0.026122|size=418|pos=71668|flags=K_|data_hash=CRC32:112b3e44 -packet|codec_type=audio|stream_index=0|pts=62300160|pts_time=4.414694|dts=62300160|dts_time=4.414694|duration=368640|duration_time=0.026122|size=418|pos=72086|flags=K_|data_hash=CRC32:5033b587 -packet|codec_type=audio|stream_index=0|pts=62668800|pts_time=4.440816|dts=62668800|dts_time=4.440816|duration=368640|duration_time=0.026122|size=418|pos=72504|flags=K_|data_hash=CRC32:9cb52ea5 -packet|codec_type=audio|stream_index=0|pts=63037440|pts_time=4.466939|dts=63037440|dts_time=4.466939|duration=368640|duration_time=0.026122|size=418|pos=72922|flags=K_|data_hash=CRC32:5630d818 -packet|codec_type=audio|stream_index=0|pts=63406080|pts_time=4.493061|dts=63406080|dts_time=4.493061|duration=368640|duration_time=0.026122|size=417|pos=73340|flags=K_|data_hash=CRC32:328534f2 -packet|codec_type=audio|stream_index=0|pts=63774720|pts_time=4.519184|dts=63774720|dts_time=4.519184|duration=368640|duration_time=0.026122|size=418|pos=73757|flags=K_|data_hash=CRC32:6d57605f -packet|codec_type=audio|stream_index=0|pts=64143360|pts_time=4.545306|dts=64143360|dts_time=4.545306|duration=368640|duration_time=0.026122|size=418|pos=74175|flags=K_|data_hash=CRC32:e79fd1bb -packet|codec_type=audio|stream_index=0|pts=64512000|pts_time=4.571429|dts=64512000|dts_time=4.571429|duration=368640|duration_time=0.026122|size=418|pos=74593|flags=K_|data_hash=CRC32:b61e5e9a -packet|codec_type=audio|stream_index=0|pts=64880640|pts_time=4.597551|dts=64880640|dts_time=4.597551|duration=368640|duration_time=0.026122|size=418|pos=75011|flags=K_|data_hash=CRC32:71bc8fe3 -packet|codec_type=audio|stream_index=0|pts=65249280|pts_time=4.623673|dts=65249280|dts_time=4.623673|duration=368640|duration_time=0.026122|size=418|pos=75429|flags=K_|data_hash=CRC32:72e21ec5 -packet|codec_type=audio|stream_index=0|pts=65617920|pts_time=4.649796|dts=65617920|dts_time=4.649796|duration=368640|duration_time=0.026122|size=418|pos=75847|flags=K_|data_hash=CRC32:f93673ad -packet|codec_type=audio|stream_index=0|pts=65986560|pts_time=4.675918|dts=65986560|dts_time=4.675918|duration=368640|duration_time=0.026122|size=418|pos=76265|flags=K_|data_hash=CRC32:93dffd2d -packet|codec_type=audio|stream_index=0|pts=66355200|pts_time=4.702041|dts=66355200|dts_time=4.702041|duration=368640|duration_time=0.026122|size=418|pos=76683|flags=K_|data_hash=CRC32:b4160eef -packet|codec_type=audio|stream_index=0|pts=66723840|pts_time=4.728163|dts=66723840|dts_time=4.728163|duration=368640|duration_time=0.026122|size=418|pos=77101|flags=K_|data_hash=CRC32:4685fb67 -packet|codec_type=audio|stream_index=0|pts=67092480|pts_time=4.754286|dts=67092480|dts_time=4.754286|duration=368640|duration_time=0.026122|size=418|pos=77519|flags=K_|data_hash=CRC32:b9c9f49c -packet|codec_type=audio|stream_index=0|pts=67461120|pts_time=4.780408|dts=67461120|dts_time=4.780408|duration=368640|duration_time=0.026122|size=418|pos=77937|flags=K_|data_hash=CRC32:97eecd83 -packet|codec_type=audio|stream_index=0|pts=67829760|pts_time=4.806531|dts=67829760|dts_time=4.806531|duration=368640|duration_time=0.026122|size=418|pos=78355|flags=K_|data_hash=CRC32:c5a4d76c -packet|codec_type=audio|stream_index=0|pts=68198400|pts_time=4.832653|dts=68198400|dts_time=4.832653|duration=368640|duration_time=0.026122|size=418|pos=78773|flags=K_|data_hash=CRC32:e693a3e4 -packet|codec_type=audio|stream_index=0|pts=68567040|pts_time=4.858776|dts=68567040|dts_time=4.858776|duration=368640|duration_time=0.026122|size=418|pos=79191|flags=K_|data_hash=CRC32:0596d099 -packet|codec_type=audio|stream_index=0|pts=68935680|pts_time=4.884898|dts=68935680|dts_time=4.884898|duration=368640|duration_time=0.026122|size=418|pos=79609|flags=K_|data_hash=CRC32:cb1ece5e -packet|codec_type=audio|stream_index=0|pts=69304320|pts_time=4.911020|dts=69304320|dts_time=4.911020|duration=368640|duration_time=0.026122|size=418|pos=80027|flags=K_|data_hash=CRC32:04f13287 -packet|codec_type=audio|stream_index=0|pts=69672960|pts_time=4.937143|dts=69672960|dts_time=4.937143|duration=368640|duration_time=0.026122|size=418|pos=80445|flags=K_|data_hash=CRC32:b7288a06 -packet|codec_type=audio|stream_index=0|pts=70041600|pts_time=4.963265|dts=70041600|dts_time=4.963265|duration=368640|duration_time=0.026122|size=418|pos=80863|flags=K_|data_hash=CRC32:da40d80d -packet|codec_type=audio|stream_index=0|pts=70410240|pts_time=4.989388|dts=70410240|dts_time=4.989388|duration=368640|duration_time=0.026122|size=418|pos=81281|flags=K_|data_hash=CRC32:248c54a6 -packet|codec_type=audio|stream_index=0|pts=70778880|pts_time=5.015510|dts=70778880|dts_time=5.015510|duration=368640|duration_time=0.026122|size=418|pos=81699|flags=K_|data_hash=CRC32:c8a6a9a2 -packet|codec_type=audio|stream_index=0|pts=71147520|pts_time=5.041633|dts=71147520|dts_time=5.041633|duration=368640|duration_time=0.026122|size=418|pos=82117|flags=K_|data_hash=CRC32:f2e498bb -packet|codec_type=audio|stream_index=0|pts=71516160|pts_time=5.067755|dts=71516160|dts_time=5.067755|duration=368640|duration_time=0.026122|size=418|pos=82535|flags=K_|data_hash=CRC32:88ae4f13 -packet|codec_type=audio|stream_index=0|pts=71884800|pts_time=5.093878|dts=71884800|dts_time=5.093878|duration=368640|duration_time=0.026122|size=418|pos=82953|flags=K_|data_hash=CRC32:671833ea -packet|codec_type=audio|stream_index=0|pts=72253440|pts_time=5.120000|dts=72253440|dts_time=5.120000|duration=368640|duration_time=0.026122|size=417|pos=83371|flags=K_|data_hash=CRC32:e9300bb8 -packet|codec_type=audio|stream_index=0|pts=72622080|pts_time=5.146122|dts=72622080|dts_time=5.146122|duration=368640|duration_time=0.026122|size=418|pos=83788|flags=K_|data_hash=CRC32:f24ddb8f -packet|codec_type=audio|stream_index=0|pts=72990720|pts_time=5.172245|dts=72990720|dts_time=5.172245|duration=368640|duration_time=0.026122|size=418|pos=84206|flags=K_|data_hash=CRC32:70f61a2c -packet|codec_type=audio|stream_index=0|pts=73359360|pts_time=5.198367|dts=73359360|dts_time=5.198367|duration=368640|duration_time=0.026122|size=418|pos=84624|flags=K_|data_hash=CRC32:73dd76f4 -packet|codec_type=audio|stream_index=0|pts=73728000|pts_time=5.224490|dts=73728000|dts_time=5.224490|duration=368640|duration_time=0.026122|size=418|pos=85042|flags=K_|data_hash=CRC32:0e0502bc -packet|codec_type=audio|stream_index=0|pts=74096640|pts_time=5.250612|dts=74096640|dts_time=5.250612|duration=368640|duration_time=0.026122|size=418|pos=85460|flags=K_|data_hash=CRC32:f014154f -packet|codec_type=audio|stream_index=0|pts=74465280|pts_time=5.276735|dts=74465280|dts_time=5.276735|duration=368640|duration_time=0.026122|size=418|pos=85878|flags=K_|data_hash=CRC32:c937e40d -packet|codec_type=audio|stream_index=0|pts=74833920|pts_time=5.302857|dts=74833920|dts_time=5.302857|duration=368640|duration_time=0.026122|size=418|pos=86296|flags=K_|data_hash=CRC32:4803689b -packet|codec_type=audio|stream_index=0|pts=75202560|pts_time=5.328980|dts=75202560|dts_time=5.328980|duration=368640|duration_time=0.026122|size=418|pos=86714|flags=K_|data_hash=CRC32:22fa34c9 -packet|codec_type=audio|stream_index=0|pts=75571200|pts_time=5.355102|dts=75571200|dts_time=5.355102|duration=368640|duration_time=0.026122|size=418|pos=87132|flags=K_|data_hash=CRC32:178ca70b -packet|codec_type=audio|stream_index=0|pts=75939840|pts_time=5.381224|dts=75939840|dts_time=5.381224|duration=368640|duration_time=0.026122|size=418|pos=87550|flags=K_|data_hash=CRC32:608d220e -packet|codec_type=audio|stream_index=0|pts=76308480|pts_time=5.407347|dts=76308480|dts_time=5.407347|duration=368640|duration_time=0.026122|size=418|pos=87968|flags=K_|data_hash=CRC32:6156090c -packet|codec_type=audio|stream_index=0|pts=76677120|pts_time=5.433469|dts=76677120|dts_time=5.433469|duration=368640|duration_time=0.026122|size=418|pos=88386|flags=K_|data_hash=CRC32:0e137f5c -packet|codec_type=audio|stream_index=0|pts=77045760|pts_time=5.459592|dts=77045760|dts_time=5.459592|duration=368640|duration_time=0.026122|size=418|pos=88804|flags=K_|data_hash=CRC32:1a82efb3 -packet|codec_type=audio|stream_index=0|pts=77414400|pts_time=5.485714|dts=77414400|dts_time=5.485714|duration=368640|duration_time=0.026122|size=418|pos=89222|flags=K_|data_hash=CRC32:6dfaa92a -packet|codec_type=audio|stream_index=0|pts=77783040|pts_time=5.511837|dts=77783040|dts_time=5.511837|duration=368640|duration_time=0.026122|size=418|pos=89640|flags=K_|data_hash=CRC32:0ff57235 -packet|codec_type=audio|stream_index=0|pts=78151680|pts_time=5.537959|dts=78151680|dts_time=5.537959|duration=368640|duration_time=0.026122|size=418|pos=90058|flags=K_|data_hash=CRC32:af6aad5b -packet|codec_type=audio|stream_index=0|pts=78520320|pts_time=5.564082|dts=78520320|dts_time=5.564082|duration=368640|duration_time=0.026122|size=418|pos=90476|flags=K_|data_hash=CRC32:3edc87af -packet|codec_type=audio|stream_index=0|pts=78888960|pts_time=5.590204|dts=78888960|dts_time=5.590204|duration=368640|duration_time=0.026122|size=418|pos=90894|flags=K_|data_hash=CRC32:4e45d2f9 -packet|codec_type=audio|stream_index=0|pts=79257600|pts_time=5.616327|dts=79257600|dts_time=5.616327|duration=368640|duration_time=0.026122|size=418|pos=91312|flags=K_|data_hash=CRC32:3e3d4490 -packet|codec_type=audio|stream_index=0|pts=79626240|pts_time=5.642449|dts=79626240|dts_time=5.642449|duration=368640|duration_time=0.026122|size=418|pos=91730|flags=K_|data_hash=CRC32:ce361a9e -packet|codec_type=audio|stream_index=0|pts=79994880|pts_time=5.668571|dts=79994880|dts_time=5.668571|duration=368640|duration_time=0.026122|size=418|pos=92148|flags=K_|data_hash=CRC32:4b4b5560 -packet|codec_type=audio|stream_index=0|pts=80363520|pts_time=5.694694|dts=80363520|dts_time=5.694694|duration=368640|duration_time=0.026122|size=418|pos=92566|flags=K_|data_hash=CRC32:15778e7b -packet|codec_type=audio|stream_index=0|pts=80732160|pts_time=5.720816|dts=80732160|dts_time=5.720816|duration=368640|duration_time=0.026122|size=418|pos=92984|flags=K_|data_hash=CRC32:6ada6d94 -packet|codec_type=audio|stream_index=0|pts=81100800|pts_time=5.746939|dts=81100800|dts_time=5.746939|duration=368640|duration_time=0.026122|size=418|pos=93402|flags=K_|data_hash=CRC32:3a8d9e78 -packet|codec_type=audio|stream_index=0|pts=81469440|pts_time=5.773061|dts=81469440|dts_time=5.773061|duration=368640|duration_time=0.026122|size=417|pos=93820|flags=K_|data_hash=CRC32:71ba89fd -packet|codec_type=audio|stream_index=0|pts=81838080|pts_time=5.799184|dts=81838080|dts_time=5.799184|duration=368640|duration_time=0.026122|size=418|pos=94237|flags=K_|data_hash=CRC32:16867b8c -packet|codec_type=audio|stream_index=0|pts=82206720|pts_time=5.825306|dts=82206720|dts_time=5.825306|duration=368640|duration_time=0.026122|size=418|pos=94655|flags=K_|data_hash=CRC32:cd7e042c -packet|codec_type=audio|stream_index=0|pts=82575360|pts_time=5.851429|dts=82575360|dts_time=5.851429|duration=368640|duration_time=0.026122|size=418|pos=95073|flags=K_|data_hash=CRC32:d9777ff5 -packet|codec_type=audio|stream_index=0|pts=82944000|pts_time=5.877551|dts=82944000|dts_time=5.877551|duration=368640|duration_time=0.026122|size=418|pos=95491|flags=K_|data_hash=CRC32:015776b6 -packet|codec_type=audio|stream_index=0|pts=83312640|pts_time=5.903673|dts=83312640|dts_time=5.903673|duration=368640|duration_time=0.026122|size=418|pos=95909|flags=K_|data_hash=CRC32:16dbd1ba -packet|codec_type=audio|stream_index=0|pts=83681280|pts_time=5.929796|dts=83681280|dts_time=5.929796|duration=368640|duration_time=0.026122|size=418|pos=96327|flags=K_|data_hash=CRC32:34156e2e -packet|codec_type=audio|stream_index=0|pts=84049920|pts_time=5.955918|dts=84049920|dts_time=5.955918|duration=368640|duration_time=0.026122|size=418|pos=96745|flags=K_|data_hash=CRC32:7ba39adb -packet|codec_type=audio|stream_index=0|pts=84418560|pts_time=5.982041|dts=84418560|dts_time=5.982041|duration=368640|duration_time=0.026122|size=418|pos=97163|flags=K_|data_hash=CRC32:315662c5 -packet|codec_type=audio|stream_index=0|pts=84787200|pts_time=6.008163|dts=84787200|dts_time=6.008163|duration=368640|duration_time=0.026122|size=418|pos=97581|flags=K_|data_hash=CRC32:1d6c6500 -packet|codec_type=audio|stream_index=0|pts=85155840|pts_time=6.034286|dts=85155840|dts_time=6.034286|duration=368640|duration_time=0.026122|size=418|pos=97999|flags=K_|data_hash=CRC32:bc14dad3 -packet|codec_type=audio|stream_index=0|pts=85524480|pts_time=6.060408|dts=85524480|dts_time=6.060408|duration=368640|duration_time=0.026122|size=418|pos=98417|flags=K_|data_hash=CRC32:7719dddd -packet|codec_type=audio|stream_index=0|pts=85893120|pts_time=6.086531|dts=85893120|dts_time=6.086531|duration=368640|duration_time=0.026122|size=418|pos=98835|flags=K_|data_hash=CRC32:132ad1b8 -packet|codec_type=audio|stream_index=0|pts=86261760|pts_time=6.112653|dts=86261760|dts_time=6.112653|duration=368640|duration_time=0.026122|size=418|pos=99253|flags=K_|data_hash=CRC32:2867c127 -packet|codec_type=audio|stream_index=0|pts=86630400|pts_time=6.138776|dts=86630400|dts_time=6.138776|duration=368640|duration_time=0.026122|size=418|pos=99671|flags=K_|data_hash=CRC32:5af3ae3d -packet|codec_type=audio|stream_index=0|pts=86999040|pts_time=6.164898|dts=86999040|dts_time=6.164898|duration=368640|duration_time=0.026122|size=418|pos=100089|flags=K_|data_hash=CRC32:16d31800 -packet|codec_type=audio|stream_index=0|pts=87367680|pts_time=6.191020|dts=87367680|dts_time=6.191020|duration=368640|duration_time=0.026122|size=418|pos=100507|flags=K_|data_hash=CRC32:93a607e1 -packet|codec_type=audio|stream_index=0|pts=87736320|pts_time=6.217143|dts=87736320|dts_time=6.217143|duration=368640|duration_time=0.026122|size=418|pos=100925|flags=K_|data_hash=CRC32:db20f488 -packet|codec_type=audio|stream_index=0|pts=88104960|pts_time=6.243265|dts=88104960|dts_time=6.243265|duration=368640|duration_time=0.026122|size=418|pos=101343|flags=K_|data_hash=CRC32:8f3d4379 -packet|codec_type=audio|stream_index=0|pts=88473600|pts_time=6.269388|dts=88473600|dts_time=6.269388|duration=368640|duration_time=0.026122|size=418|pos=101761|flags=K_|data_hash=CRC32:837d0ec9 -packet|codec_type=audio|stream_index=0|pts=88842240|pts_time=6.295510|dts=88842240|dts_time=6.295510|duration=368640|duration_time=0.026122|size=418|pos=102179|flags=K_|data_hash=CRC32:22a48a51 -packet|codec_type=audio|stream_index=0|pts=89210880|pts_time=6.321633|dts=89210880|dts_time=6.321633|duration=368640|duration_time=0.026122|size=418|pos=102597|flags=K_|data_hash=CRC32:bca25918 -packet|codec_type=audio|stream_index=0|pts=89579520|pts_time=6.347755|dts=89579520|dts_time=6.347755|duration=368640|duration_time=0.026122|size=418|pos=103015|flags=K_|data_hash=CRC32:3db99977 -packet|codec_type=audio|stream_index=0|pts=89948160|pts_time=6.373878|dts=89948160|dts_time=6.373878|duration=368640|duration_time=0.026122|size=418|pos=103433|flags=K_|data_hash=CRC32:faa243b6 -packet|codec_type=audio|stream_index=0|pts=90316800|pts_time=6.400000|dts=90316800|dts_time=6.400000|duration=368640|duration_time=0.026122|size=417|pos=103851|flags=K_|data_hash=CRC32:f725a63e -packet|codec_type=audio|stream_index=0|pts=90685440|pts_time=6.426122|dts=90685440|dts_time=6.426122|duration=368640|duration_time=0.026122|size=418|pos=104268|flags=K_|data_hash=CRC32:76cf3f35 -packet|codec_type=audio|stream_index=0|pts=91054080|pts_time=6.452245|dts=91054080|dts_time=6.452245|duration=368640|duration_time=0.026122|size=418|pos=104686|flags=K_|data_hash=CRC32:2fa3029d -packet|codec_type=audio|stream_index=0|pts=91422720|pts_time=6.478367|dts=91422720|dts_time=6.478367|duration=368640|duration_time=0.026122|size=418|pos=105104|flags=K_|data_hash=CRC32:4a8deeec -packet|codec_type=audio|stream_index=0|pts=91791360|pts_time=6.504490|dts=91791360|dts_time=6.504490|duration=368640|duration_time=0.026122|size=418|pos=105522|flags=K_|data_hash=CRC32:6bb7f1f6 -packet|codec_type=audio|stream_index=0|pts=92160000|pts_time=6.530612|dts=92160000|dts_time=6.530612|duration=368640|duration_time=0.026122|size=418|pos=105940|flags=K_|data_hash=CRC32:e16d50d2 -packet|codec_type=audio|stream_index=0|pts=92528640|pts_time=6.556735|dts=92528640|dts_time=6.556735|duration=368640|duration_time=0.026122|size=418|pos=106358|flags=K_|data_hash=CRC32:b5347035 -packet|codec_type=audio|stream_index=0|pts=92897280|pts_time=6.582857|dts=92897280|dts_time=6.582857|duration=368640|duration_time=0.026122|size=418|pos=106776|flags=K_|data_hash=CRC32:7854e0d2 -packet|codec_type=audio|stream_index=0|pts=93265920|pts_time=6.608980|dts=93265920|dts_time=6.608980|duration=368640|duration_time=0.026122|size=418|pos=107194|flags=K_|data_hash=CRC32:695b58a9 -packet|codec_type=audio|stream_index=0|pts=93634560|pts_time=6.635102|dts=93634560|dts_time=6.635102|duration=368640|duration_time=0.026122|size=418|pos=107612|flags=K_|data_hash=CRC32:edf1b673 -packet|codec_type=audio|stream_index=0|pts=94003200|pts_time=6.661224|dts=94003200|dts_time=6.661224|duration=368640|duration_time=0.026122|size=418|pos=108030|flags=K_|data_hash=CRC32:46324bbb -packet|codec_type=audio|stream_index=0|pts=94371840|pts_time=6.687347|dts=94371840|dts_time=6.687347|duration=368640|duration_time=0.026122|size=418|pos=108448|flags=K_|data_hash=CRC32:e4f2bb26 -packet|codec_type=audio|stream_index=0|pts=94740480|pts_time=6.713469|dts=94740480|dts_time=6.713469|duration=368640|duration_time=0.026122|size=418|pos=108866|flags=K_|data_hash=CRC32:5db12b9c -packet|codec_type=audio|stream_index=0|pts=95109120|pts_time=6.739592|dts=95109120|dts_time=6.739592|duration=368640|duration_time=0.026122|size=418|pos=109284|flags=K_|data_hash=CRC32:36183b69 -packet|codec_type=audio|stream_index=0|pts=95477760|pts_time=6.765714|dts=95477760|dts_time=6.765714|duration=368640|duration_time=0.026122|size=418|pos=109702|flags=K_|data_hash=CRC32:baa2604d -packet|codec_type=audio|stream_index=0|pts=95846400|pts_time=6.791837|dts=95846400|dts_time=6.791837|duration=368640|duration_time=0.026122|size=418|pos=110120|flags=K_|data_hash=CRC32:5ed1c59a -packet|codec_type=audio|stream_index=0|pts=96215040|pts_time=6.817959|dts=96215040|dts_time=6.817959|duration=368640|duration_time=0.026122|size=418|pos=110538|flags=K_|data_hash=CRC32:dc54d5cd -packet|codec_type=audio|stream_index=0|pts=96583680|pts_time=6.844082|dts=96583680|dts_time=6.844082|duration=368640|duration_time=0.026122|size=418|pos=110956|flags=K_|data_hash=CRC32:0fbfd9a0 -packet|codec_type=audio|stream_index=0|pts=96952320|pts_time=6.870204|dts=96952320|dts_time=6.870204|duration=368640|duration_time=0.026122|size=418|pos=111374|flags=K_|data_hash=CRC32:bf3e1f53 -packet|codec_type=audio|stream_index=0|pts=97320960|pts_time=6.896327|dts=97320960|dts_time=6.896327|duration=368640|duration_time=0.026122|size=418|pos=111792|flags=K_|data_hash=CRC32:4ef81515 -packet|codec_type=audio|stream_index=0|pts=97689600|pts_time=6.922449|dts=97689600|dts_time=6.922449|duration=368640|duration_time=0.026122|size=418|pos=112210|flags=K_|data_hash=CRC32:576a9545 -packet|codec_type=audio|stream_index=0|pts=98058240|pts_time=6.948571|dts=98058240|dts_time=6.948571|duration=368640|duration_time=0.026122|size=418|pos=112628|flags=K_|data_hash=CRC32:522a71d5 -packet|codec_type=audio|stream_index=0|pts=98426880|pts_time=6.974694|dts=98426880|dts_time=6.974694|duration=368640|duration_time=0.026122|size=418|pos=113046|flags=K_|data_hash=CRC32:b15d9d3b -packet|codec_type=audio|stream_index=0|pts=98795520|pts_time=7.000816|dts=98795520|dts_time=7.000816|duration=368640|duration_time=0.026122|size=418|pos=113464|flags=K_|data_hash=CRC32:fd9937b8 -packet|codec_type=audio|stream_index=0|pts=99164160|pts_time=7.026939|dts=99164160|dts_time=7.026939|duration=368640|duration_time=0.026122|size=418|pos=113882|flags=K_|data_hash=CRC32:b9331702 -packet|codec_type=audio|stream_index=0|pts=99532800|pts_time=7.053061|dts=99532800|dts_time=7.053061|duration=368640|duration_time=0.026122|size=417|pos=114300|flags=K_|data_hash=CRC32:0e805c6d -packet|codec_type=audio|stream_index=0|pts=99901440|pts_time=7.079184|dts=99901440|dts_time=7.079184|duration=368640|duration_time=0.026122|size=418|pos=114717|flags=K_|data_hash=CRC32:b6f589c8 -packet|codec_type=audio|stream_index=0|pts=100270080|pts_time=7.105306|dts=100270080|dts_time=7.105306|duration=368640|duration_time=0.026122|size=418|pos=115135|flags=K_|data_hash=CRC32:87cfee38 -packet|codec_type=audio|stream_index=0|pts=100638720|pts_time=7.131429|dts=100638720|dts_time=7.131429|duration=368640|duration_time=0.026122|size=418|pos=115553|flags=K_|data_hash=CRC32:d90d4ebe -packet|codec_type=audio|stream_index=0|pts=101007360|pts_time=7.157551|dts=101007360|dts_time=7.157551|duration=368640|duration_time=0.026122|size=418|pos=115971|flags=K_|data_hash=CRC32:cf571193 -packet|codec_type=audio|stream_index=0|pts=101376000|pts_time=7.183673|dts=101376000|dts_time=7.183673|duration=368640|duration_time=0.026122|size=418|pos=116389|flags=K_|data_hash=CRC32:30d3b2d7 -packet|codec_type=audio|stream_index=0|pts=101744640|pts_time=7.209796|dts=101744640|dts_time=7.209796|duration=368640|duration_time=0.026122|size=418|pos=116807|flags=K_|data_hash=CRC32:94eff902 -packet|codec_type=audio|stream_index=0|pts=102113280|pts_time=7.235918|dts=102113280|dts_time=7.235918|duration=368640|duration_time=0.026122|size=418|pos=117225|flags=K_|data_hash=CRC32:6ed46b0c -packet|codec_type=audio|stream_index=0|pts=102481920|pts_time=7.262041|dts=102481920|dts_time=7.262041|duration=368640|duration_time=0.026122|size=418|pos=117643|flags=K_|data_hash=CRC32:ae9574bf -packet|codec_type=audio|stream_index=0|pts=102850560|pts_time=7.288163|dts=102850560|dts_time=7.288163|duration=368640|duration_time=0.026122|size=418|pos=118061|flags=K_|data_hash=CRC32:216621bb -packet|codec_type=audio|stream_index=0|pts=103219200|pts_time=7.314286|dts=103219200|dts_time=7.314286|duration=368640|duration_time=0.026122|size=418|pos=118479|flags=K_|data_hash=CRC32:be692b5a -packet|codec_type=audio|stream_index=0|pts=103587840|pts_time=7.340408|dts=103587840|dts_time=7.340408|duration=368640|duration_time=0.026122|size=418|pos=118897|flags=K_|data_hash=CRC32:76b6814a -packet|codec_type=audio|stream_index=0|pts=103956480|pts_time=7.366531|dts=103956480|dts_time=7.366531|duration=368640|duration_time=0.026122|size=418|pos=119315|flags=K_|data_hash=CRC32:60ac1531 -packet|codec_type=audio|stream_index=0|pts=104325120|pts_time=7.392653|dts=104325120|dts_time=7.392653|duration=368640|duration_time=0.026122|size=418|pos=119733|flags=K_|data_hash=CRC32:d9ac3b87 -packet|codec_type=audio|stream_index=0|pts=104693760|pts_time=7.418776|dts=104693760|dts_time=7.418776|duration=368640|duration_time=0.026122|size=418|pos=120151|flags=K_|data_hash=CRC32:6187bef7 -packet|codec_type=audio|stream_index=0|pts=105062400|pts_time=7.444898|dts=105062400|dts_time=7.444898|duration=368640|duration_time=0.026122|size=418|pos=120569|flags=K_|data_hash=CRC32:abb11d4e -packet|codec_type=audio|stream_index=0|pts=105431040|pts_time=7.471020|dts=105431040|dts_time=7.471020|duration=368640|duration_time=0.026122|size=418|pos=120987|flags=K_|data_hash=CRC32:21ff16ed -packet|codec_type=audio|stream_index=0|pts=105799680|pts_time=7.497143|dts=105799680|dts_time=7.497143|duration=368640|duration_time=0.026122|size=418|pos=121405|flags=K_|data_hash=CRC32:8b9d33e3 -packet|codec_type=audio|stream_index=0|pts=106168320|pts_time=7.523265|dts=106168320|dts_time=7.523265|duration=368640|duration_time=0.026122|size=418|pos=121823|flags=K_|data_hash=CRC32:9fdfecc3 -packet|codec_type=audio|stream_index=0|pts=106536960|pts_time=7.549388|dts=106536960|dts_time=7.549388|duration=368640|duration_time=0.026122|size=418|pos=122241|flags=K_|data_hash=CRC32:09b2eb8c -packet|codec_type=audio|stream_index=0|pts=106905600|pts_time=7.575510|dts=106905600|dts_time=7.575510|duration=368640|duration_time=0.026122|size=418|pos=122659|flags=K_|data_hash=CRC32:1157b18a -packet|codec_type=audio|stream_index=0|pts=107274240|pts_time=7.601633|dts=107274240|dts_time=7.601633|duration=368640|duration_time=0.026122|size=418|pos=123077|flags=K_|data_hash=CRC32:16d63271 -packet|codec_type=audio|stream_index=0|pts=107642880|pts_time=7.627755|dts=107642880|dts_time=7.627755|duration=368640|duration_time=0.026122|size=418|pos=123495|flags=K_|data_hash=CRC32:ff8cd868 -packet|codec_type=audio|stream_index=0|pts=108011520|pts_time=7.653878|dts=108011520|dts_time=7.653878|duration=368640|duration_time=0.026122|size=418|pos=123913|flags=K_|data_hash=CRC32:dcd4b34b -packet|codec_type=audio|stream_index=0|pts=108380160|pts_time=7.680000|dts=108380160|dts_time=7.680000|duration=368640|duration_time=0.026122|size=417|pos=124331|flags=K_|data_hash=CRC32:511a97cc -packet|codec_type=audio|stream_index=0|pts=108748800|pts_time=7.706122|dts=108748800|dts_time=7.706122|duration=368640|duration_time=0.026122|size=418|pos=124748|flags=K_|data_hash=CRC32:12f0449c -packet|codec_type=audio|stream_index=0|pts=109117440|pts_time=7.732245|dts=109117440|dts_time=7.732245|duration=368640|duration_time=0.026122|size=418|pos=125166|flags=K_|data_hash=CRC32:5af6bfcc -packet|codec_type=audio|stream_index=0|pts=109486080|pts_time=7.758367|dts=109486080|dts_time=7.758367|duration=368640|duration_time=0.026122|size=418|pos=125584|flags=K_|data_hash=CRC32:1cfa7e91 -packet|codec_type=audio|stream_index=0|pts=109854720|pts_time=7.784490|dts=109854720|dts_time=7.784490|duration=368640|duration_time=0.026122|size=418|pos=126002|flags=K_|data_hash=CRC32:d87857f2 -packet|codec_type=audio|stream_index=0|pts=110223360|pts_time=7.810612|dts=110223360|dts_time=7.810612|duration=368640|duration_time=0.026122|size=418|pos=126420|flags=K_|data_hash=CRC32:37cd9f06 -packet|codec_type=audio|stream_index=0|pts=110592000|pts_time=7.836735|dts=110592000|dts_time=7.836735|duration=368640|duration_time=0.026122|size=418|pos=126838|flags=K_|data_hash=CRC32:a3df2bf0 -packet|codec_type=audio|stream_index=0|pts=110960640|pts_time=7.862857|dts=110960640|dts_time=7.862857|duration=368640|duration_time=0.026122|size=418|pos=127256|flags=K_|data_hash=CRC32:814fa056 -packet|codec_type=audio|stream_index=0|pts=111329280|pts_time=7.888980|dts=111329280|dts_time=7.888980|duration=368640|duration_time=0.026122|size=418|pos=127674|flags=K_|data_hash=CRC32:6c87eadd -packet|codec_type=audio|stream_index=0|pts=111697920|pts_time=7.915102|dts=111697920|dts_time=7.915102|duration=368640|duration_time=0.026122|size=418|pos=128092|flags=K_|data_hash=CRC32:3b1623b4 -packet|codec_type=audio|stream_index=0|pts=112066560|pts_time=7.941224|dts=112066560|dts_time=7.941224|duration=368640|duration_time=0.026122|size=418|pos=128510|flags=K_|data_hash=CRC32:2282971a -packet|codec_type=audio|stream_index=0|pts=112435200|pts_time=7.967347|dts=112435200|dts_time=7.967347|duration=368640|duration_time=0.026122|size=418|pos=128928|flags=K_|data_hash=CRC32:e4c2f907 -packet|codec_type=audio|stream_index=0|pts=112803840|pts_time=7.993469|dts=112803840|dts_time=7.993469|duration=368640|duration_time=0.026122|size=418|pos=129346|flags=K_|data_hash=CRC32:0d494e7c -packet|codec_type=audio|stream_index=0|pts=113172480|pts_time=8.019592|dts=113172480|dts_time=8.019592|duration=368640|duration_time=0.026122|size=418|pos=129764|flags=K_|data_hash=CRC32:73683d3b -packet|codec_type=audio|stream_index=0|pts=113541120|pts_time=8.045714|dts=113541120|dts_time=8.045714|duration=368640|duration_time=0.026122|size=418|pos=130182|flags=K_|data_hash=CRC32:6a80ad3a -packet|codec_type=audio|stream_index=0|pts=113909760|pts_time=8.071837|dts=113909760|dts_time=8.071837|duration=368640|duration_time=0.026122|size=418|pos=130600|flags=K_|data_hash=CRC32:6d1ad253 -packet|codec_type=audio|stream_index=0|pts=114278400|pts_time=8.097959|dts=114278400|dts_time=8.097959|duration=368640|duration_time=0.026122|size=418|pos=131018|flags=K_|data_hash=CRC32:08fbdf2b -packet|codec_type=audio|stream_index=0|pts=114647040|pts_time=8.124082|dts=114647040|dts_time=8.124082|duration=368640|duration_time=0.026122|size=418|pos=131436|flags=K_|data_hash=CRC32:53280306 -packet|codec_type=audio|stream_index=0|pts=115015680|pts_time=8.150204|dts=115015680|dts_time=8.150204|duration=368640|duration_time=0.026122|size=418|pos=131854|flags=K_|data_hash=CRC32:0c8ac4d8 -packet|codec_type=audio|stream_index=0|pts=115384320|pts_time=8.176327|dts=115384320|dts_time=8.176327|duration=368640|duration_time=0.026122|size=418|pos=132272|flags=K_|data_hash=CRC32:b1d42b95 -packet|codec_type=audio|stream_index=0|pts=115752960|pts_time=8.202449|dts=115752960|dts_time=8.202449|duration=368640|duration_time=0.026122|size=418|pos=132690|flags=K_|data_hash=CRC32:e79c13f3 -packet|codec_type=audio|stream_index=0|pts=116121600|pts_time=8.228571|dts=116121600|dts_time=8.228571|duration=368640|duration_time=0.026122|size=418|pos=133108|flags=K_|data_hash=CRC32:b7a6b904 -packet|codec_type=audio|stream_index=0|pts=116490240|pts_time=8.254694|dts=116490240|dts_time=8.254694|duration=368640|duration_time=0.026122|size=418|pos=133526|flags=K_|data_hash=CRC32:e7437fe1 -packet|codec_type=audio|stream_index=0|pts=116858880|pts_time=8.280816|dts=116858880|dts_time=8.280816|duration=368640|duration_time=0.026122|size=418|pos=133944|flags=K_|data_hash=CRC32:ec10c2f1 -packet|codec_type=audio|stream_index=0|pts=117227520|pts_time=8.306939|dts=117227520|dts_time=8.306939|duration=368640|duration_time=0.026122|size=418|pos=134362|flags=K_|data_hash=CRC32:c85afe11 -packet|codec_type=audio|stream_index=0|pts=117596160|pts_time=8.333061|dts=117596160|dts_time=8.333061|duration=368640|duration_time=0.026122|size=417|pos=134780|flags=K_|data_hash=CRC32:86d78485 -packet|codec_type=audio|stream_index=0|pts=117964800|pts_time=8.359184|dts=117964800|dts_time=8.359184|duration=368640|duration_time=0.026122|size=418|pos=135197|flags=K_|data_hash=CRC32:38a01640 -packet|codec_type=audio|stream_index=0|pts=118333440|pts_time=8.385306|dts=118333440|dts_time=8.385306|duration=368640|duration_time=0.026122|size=418|pos=135615|flags=K_|data_hash=CRC32:fa047a2a -packet|codec_type=audio|stream_index=0|pts=118702080|pts_time=8.411429|dts=118702080|dts_time=8.411429|duration=368640|duration_time=0.026122|size=418|pos=136033|flags=K_|data_hash=CRC32:be363336 -packet|codec_type=audio|stream_index=0|pts=119070720|pts_time=8.437551|dts=119070720|dts_time=8.437551|duration=368640|duration_time=0.026122|size=418|pos=136451|flags=K_|data_hash=CRC32:107b9a48 -packet|codec_type=audio|stream_index=0|pts=119439360|pts_time=8.463673|dts=119439360|dts_time=8.463673|duration=368640|duration_time=0.026122|size=418|pos=136869|flags=K_|data_hash=CRC32:ec2d29b4 -packet|codec_type=audio|stream_index=0|pts=119808000|pts_time=8.489796|dts=119808000|dts_time=8.489796|duration=368640|duration_time=0.026122|size=418|pos=137287|flags=K_|data_hash=CRC32:5b4e1cd2 -packet|codec_type=audio|stream_index=0|pts=120176640|pts_time=8.515918|dts=120176640|dts_time=8.515918|duration=368640|duration_time=0.026122|size=418|pos=137705|flags=K_|data_hash=CRC32:3fdd2053 -packet|codec_type=audio|stream_index=0|pts=120545280|pts_time=8.542041|dts=120545280|dts_time=8.542041|duration=368640|duration_time=0.026122|size=418|pos=138123|flags=K_|data_hash=CRC32:a6205b07 -packet|codec_type=audio|stream_index=0|pts=120913920|pts_time=8.568163|dts=120913920|dts_time=8.568163|duration=368640|duration_time=0.026122|size=418|pos=138541|flags=K_|data_hash=CRC32:25820a59 -packet|codec_type=audio|stream_index=0|pts=121282560|pts_time=8.594286|dts=121282560|dts_time=8.594286|duration=368640|duration_time=0.026122|size=418|pos=138959|flags=K_|data_hash=CRC32:d7e4d24a -packet|codec_type=audio|stream_index=0|pts=121651200|pts_time=8.620408|dts=121651200|dts_time=8.620408|duration=368640|duration_time=0.026122|size=418|pos=139377|flags=K_|data_hash=CRC32:372d6c45 -packet|codec_type=audio|stream_index=0|pts=122019840|pts_time=8.646531|dts=122019840|dts_time=8.646531|duration=368640|duration_time=0.026122|size=418|pos=139795|flags=K_|data_hash=CRC32:b3d2534b -packet|codec_type=audio|stream_index=0|pts=122388480|pts_time=8.672653|dts=122388480|dts_time=8.672653|duration=368640|duration_time=0.026122|size=418|pos=140213|flags=K_|data_hash=CRC32:ec06331a -packet|codec_type=audio|stream_index=0|pts=122757120|pts_time=8.698776|dts=122757120|dts_time=8.698776|duration=368640|duration_time=0.026122|size=418|pos=140631|flags=K_|data_hash=CRC32:c1d73495 -packet|codec_type=audio|stream_index=0|pts=123125760|pts_time=8.724898|dts=123125760|dts_time=8.724898|duration=368640|duration_time=0.026122|size=418|pos=141049|flags=K_|data_hash=CRC32:cd3b07b4 -packet|codec_type=audio|stream_index=0|pts=123494400|pts_time=8.751020|dts=123494400|dts_time=8.751020|duration=368640|duration_time=0.026122|size=418|pos=141467|flags=K_|data_hash=CRC32:89d52d58 -packet|codec_type=audio|stream_index=0|pts=123863040|pts_time=8.777143|dts=123863040|dts_time=8.777143|duration=368640|duration_time=0.026122|size=418|pos=141885|flags=K_|data_hash=CRC32:4f6f794b -packet|codec_type=audio|stream_index=0|pts=124231680|pts_time=8.803265|dts=124231680|dts_time=8.803265|duration=368640|duration_time=0.026122|size=418|pos=142303|flags=K_|data_hash=CRC32:fffede19 -packet|codec_type=audio|stream_index=0|pts=124600320|pts_time=8.829388|dts=124600320|dts_time=8.829388|duration=368640|duration_time=0.026122|size=418|pos=142721|flags=K_|data_hash=CRC32:2567e5ee -packet|codec_type=audio|stream_index=0|pts=124968960|pts_time=8.855510|dts=124968960|dts_time=8.855510|duration=368640|duration_time=0.026122|size=418|pos=143139|flags=K_|data_hash=CRC32:e5a1e8c9 -packet|codec_type=audio|stream_index=0|pts=125337600|pts_time=8.881633|dts=125337600|dts_time=8.881633|duration=368640|duration_time=0.026122|size=418|pos=143557|flags=K_|data_hash=CRC32:90a53524 -packet|codec_type=audio|stream_index=0|pts=125706240|pts_time=8.907755|dts=125706240|dts_time=8.907755|duration=368640|duration_time=0.026122|size=418|pos=143975|flags=K_|data_hash=CRC32:dab534ad -packet|codec_type=audio|stream_index=0|pts=126074880|pts_time=8.933878|dts=126074880|dts_time=8.933878|duration=368640|duration_time=0.026122|size=418|pos=144393|flags=K_|data_hash=CRC32:80e2d601 -packet|codec_type=audio|stream_index=0|pts=126443520|pts_time=8.960000|dts=126443520|dts_time=8.960000|duration=368640|duration_time=0.026122|size=417|pos=144811|flags=K_|data_hash=CRC32:9e58315a -packet|codec_type=audio|stream_index=0|pts=126812160|pts_time=8.986122|dts=126812160|dts_time=8.986122|duration=368640|duration_time=0.026122|size=418|pos=145228|flags=K_|data_hash=CRC32:caf2a992 -packet|codec_type=audio|stream_index=0|pts=127180800|pts_time=9.012245|dts=127180800|dts_time=9.012245|duration=368640|duration_time=0.026122|size=418|pos=145646|flags=K_|data_hash=CRC32:b4416c55 -packet|codec_type=audio|stream_index=0|pts=127549440|pts_time=9.038367|dts=127549440|dts_time=9.038367|duration=368640|duration_time=0.026122|size=418|pos=146064|flags=K_|data_hash=CRC32:cf540122 -packet|codec_type=audio|stream_index=0|pts=127918080|pts_time=9.064490|dts=127918080|dts_time=9.064490|duration=368640|duration_time=0.026122|size=418|pos=146482|flags=K_|data_hash=CRC32:d2271324 -packet|codec_type=audio|stream_index=0|pts=128286720|pts_time=9.090612|dts=128286720|dts_time=9.090612|duration=368640|duration_time=0.026122|size=418|pos=146900|flags=K_|data_hash=CRC32:8d46cedb -packet|codec_type=audio|stream_index=0|pts=128655360|pts_time=9.116735|dts=128655360|dts_time=9.116735|duration=368640|duration_time=0.026122|size=418|pos=147318|flags=K_|data_hash=CRC32:98360373 -packet|codec_type=audio|stream_index=0|pts=129024000|pts_time=9.142857|dts=129024000|dts_time=9.142857|duration=368640|duration_time=0.026122|size=418|pos=147736|flags=K_|data_hash=CRC32:16a4d10e -packet|codec_type=audio|stream_index=0|pts=129392640|pts_time=9.168980|dts=129392640|dts_time=9.168980|duration=368640|duration_time=0.026122|size=418|pos=148154|flags=K_|data_hash=CRC32:96039cf1 -packet|codec_type=audio|stream_index=0|pts=129761280|pts_time=9.195102|dts=129761280|dts_time=9.195102|duration=368640|duration_time=0.026122|size=418|pos=148572|flags=K_|data_hash=CRC32:810c60a7 -packet|codec_type=audio|stream_index=0|pts=130129920|pts_time=9.221224|dts=130129920|dts_time=9.221224|duration=368640|duration_time=0.026122|size=418|pos=148990|flags=K_|data_hash=CRC32:965ad421 -packet|codec_type=audio|stream_index=0|pts=130498560|pts_time=9.247347|dts=130498560|dts_time=9.247347|duration=368640|duration_time=0.026122|size=418|pos=149408|flags=K_|data_hash=CRC32:ee0de130 -packet|codec_type=audio|stream_index=0|pts=130867200|pts_time=9.273469|dts=130867200|dts_time=9.273469|duration=368640|duration_time=0.026122|size=418|pos=149826|flags=K_|data_hash=CRC32:0b2e2883 -packet|codec_type=audio|stream_index=0|pts=131235840|pts_time=9.299592|dts=131235840|dts_time=9.299592|duration=368640|duration_time=0.026122|size=418|pos=150244|flags=K_|data_hash=CRC32:3f610265 -packet|codec_type=audio|stream_index=0|pts=131604480|pts_time=9.325714|dts=131604480|dts_time=9.325714|duration=368640|duration_time=0.026122|size=418|pos=150662|flags=K_|data_hash=CRC32:26cf9721 -packet|codec_type=audio|stream_index=0|pts=131973120|pts_time=9.351837|dts=131973120|dts_time=9.351837|duration=368640|duration_time=0.026122|size=418|pos=151080|flags=K_|data_hash=CRC32:eab74fb9 -packet|codec_type=audio|stream_index=0|pts=132341760|pts_time=9.377959|dts=132341760|dts_time=9.377959|duration=368640|duration_time=0.026122|size=418|pos=151498|flags=K_|data_hash=CRC32:60dea12f -packet|codec_type=audio|stream_index=0|pts=132710400|pts_time=9.404082|dts=132710400|dts_time=9.404082|duration=368640|duration_time=0.026122|size=418|pos=151916|flags=K_|data_hash=CRC32:54d23243 -packet|codec_type=audio|stream_index=0|pts=133079040|pts_time=9.430204|dts=133079040|dts_time=9.430204|duration=368640|duration_time=0.026122|size=418|pos=152334|flags=K_|data_hash=CRC32:6d507594 -packet|codec_type=audio|stream_index=0|pts=133447680|pts_time=9.456327|dts=133447680|dts_time=9.456327|duration=368640|duration_time=0.026122|size=418|pos=152752|flags=K_|data_hash=CRC32:a31b92c2 -packet|codec_type=audio|stream_index=0|pts=133816320|pts_time=9.482449|dts=133816320|dts_time=9.482449|duration=368640|duration_time=0.026122|size=418|pos=153170|flags=K_|data_hash=CRC32:04f064bd -packet|codec_type=audio|stream_index=0|pts=134184960|pts_time=9.508571|dts=134184960|dts_time=9.508571|duration=368640|duration_time=0.026122|size=418|pos=153588|flags=K_|data_hash=CRC32:234c71a8 -packet|codec_type=audio|stream_index=0|pts=134553600|pts_time=9.534694|dts=134553600|dts_time=9.534694|duration=368640|duration_time=0.026122|size=418|pos=154006|flags=K_|data_hash=CRC32:18fabbb7 -packet|codec_type=audio|stream_index=0|pts=134922240|pts_time=9.560816|dts=134922240|dts_time=9.560816|duration=368640|duration_time=0.026122|size=418|pos=154424|flags=K_|data_hash=CRC32:e372f113 -packet|codec_type=audio|stream_index=0|pts=135290880|pts_time=9.586939|dts=135290880|dts_time=9.586939|duration=368640|duration_time=0.026122|size=418|pos=154842|flags=K_|data_hash=CRC32:10352242 -packet|codec_type=audio|stream_index=0|pts=135659520|pts_time=9.613061|dts=135659520|dts_time=9.613061|duration=368640|duration_time=0.026122|size=417|pos=155260|flags=K_|data_hash=CRC32:571e601d -packet|codec_type=audio|stream_index=0|pts=136028160|pts_time=9.639184|dts=136028160|dts_time=9.639184|duration=368640|duration_time=0.026122|size=418|pos=155677|flags=K_|data_hash=CRC32:974376f0 -packet|codec_type=audio|stream_index=0|pts=136396800|pts_time=9.665306|dts=136396800|dts_time=9.665306|duration=368640|duration_time=0.026122|size=418|pos=156095|flags=K_|data_hash=CRC32:9893202f -packet|codec_type=audio|stream_index=0|pts=136765440|pts_time=9.691429|dts=136765440|dts_time=9.691429|duration=368640|duration_time=0.026122|size=418|pos=156513|flags=K_|data_hash=CRC32:57c930c0 -packet|codec_type=audio|stream_index=0|pts=137134080|pts_time=9.717551|dts=137134080|dts_time=9.717551|duration=368640|duration_time=0.026122|size=418|pos=156931|flags=K_|data_hash=CRC32:a8fc9e47 -packet|codec_type=audio|stream_index=0|pts=137502720|pts_time=9.743673|dts=137502720|dts_time=9.743673|duration=368640|duration_time=0.026122|size=418|pos=157349|flags=K_|data_hash=CRC32:a06f74d4 -packet|codec_type=audio|stream_index=0|pts=137871360|pts_time=9.769796|dts=137871360|dts_time=9.769796|duration=368640|duration_time=0.026122|size=418|pos=157767|flags=K_|data_hash=CRC32:adf88905 -packet|codec_type=audio|stream_index=0|pts=138240000|pts_time=9.795918|dts=138240000|dts_time=9.795918|duration=368640|duration_time=0.026122|size=418|pos=158185|flags=K_|data_hash=CRC32:8d415d99 -packet|codec_type=audio|stream_index=0|pts=138608640|pts_time=9.822041|dts=138608640|dts_time=9.822041|duration=368640|duration_time=0.026122|size=418|pos=158603|flags=K_|data_hash=CRC32:5df4c659 -packet|codec_type=audio|stream_index=0|pts=138977280|pts_time=9.848163|dts=138977280|dts_time=9.848163|duration=368640|duration_time=0.026122|size=418|pos=159021|flags=K_|data_hash=CRC32:c0aba593 -packet|codec_type=audio|stream_index=0|pts=139345920|pts_time=9.874286|dts=139345920|dts_time=9.874286|duration=368640|duration_time=0.026122|size=418|pos=159439|flags=K_|data_hash=CRC32:3d5f2342 -packet|codec_type=audio|stream_index=0|pts=139714560|pts_time=9.900408|dts=139714560|dts_time=9.900408|duration=368640|duration_time=0.026122|size=418|pos=159857|flags=K_|data_hash=CRC32:6835ff9d -packet|codec_type=audio|stream_index=0|pts=140083200|pts_time=9.926531|dts=140083200|dts_time=9.926531|duration=368640|duration_time=0.026122|size=418|pos=160275|flags=K_|data_hash=CRC32:de3061f3 -packet|codec_type=audio|stream_index=0|pts=140451840|pts_time=9.952653|dts=140451840|dts_time=9.952653|duration=368640|duration_time=0.026122|size=418|pos=160693|flags=K_|data_hash=CRC32:e28378d6 -packet|codec_type=audio|stream_index=0|pts=140820480|pts_time=9.978776|dts=140820480|dts_time=9.978776|duration=368640|duration_time=0.026122|size=418|pos=161111|flags=K_|data_hash=CRC32:1eabe555 -packet|codec_type=audio|stream_index=0|pts=141189120|pts_time=10.004898|dts=141189120|dts_time=10.004898|duration=368640|duration_time=0.026122|size=418|pos=161529|flags=K_|data_hash=CRC32:2bad508d -packet|codec_type=audio|stream_index=0|pts=141557760|pts_time=10.031020|dts=141557760|dts_time=10.031020|duration=368640|duration_time=0.026122|size=418|pos=161947|flags=K_|data_hash=CRC32:37fba9de -packet|codec_type=audio|stream_index=0|pts=141926400|pts_time=10.057143|dts=141926400|dts_time=10.057143|duration=368640|duration_time=0.026122|size=418|pos=162365|flags=K_|data_hash=CRC32:3244ecea -packet|codec_type=audio|stream_index=0|pts=142295040|pts_time=10.083265|dts=142295040|dts_time=10.083265|duration=368640|duration_time=0.026122|size=418|pos=162783|flags=K_|data_hash=CRC32:685781af -packet|codec_type=audio|stream_index=0|pts=142663680|pts_time=10.109388|dts=142663680|dts_time=10.109388|duration=368640|duration_time=0.026122|size=418|pos=163201|flags=K_|data_hash=CRC32:12d9eb56 -packet|codec_type=audio|stream_index=0|pts=143032320|pts_time=10.135510|dts=143032320|dts_time=10.135510|duration=368640|duration_time=0.026122|size=418|pos=163619|flags=K_|data_hash=CRC32:40f01793 -packet|codec_type=audio|stream_index=0|pts=143400960|pts_time=10.161633|dts=143400960|dts_time=10.161633|duration=368640|duration_time=0.026122|size=418|pos=164037|flags=K_|data_hash=CRC32:46a6b913 -packet|codec_type=audio|stream_index=0|pts=143769600|pts_time=10.187755|dts=143769600|dts_time=10.187755|duration=368640|duration_time=0.026122|size=418|pos=164455|flags=K_|data_hash=CRC32:a0923bf5 -packet|codec_type=audio|stream_index=0|pts=144138240|pts_time=10.213878|dts=144138240|dts_time=10.213878|duration=368640|duration_time=0.026122|size=418|pos=164873|flags=K_|data_hash=CRC32:85b32138 -packet|codec_type=audio|stream_index=0|pts=144506880|pts_time=10.240000|dts=144506880|dts_time=10.240000|duration=368640|duration_time=0.026122|size=417|pos=165291|flags=K_|data_hash=CRC32:6b70633a -packet|codec_type=audio|stream_index=0|pts=144875520|pts_time=10.266122|dts=144875520|dts_time=10.266122|duration=368640|duration_time=0.026122|size=418|pos=165708|flags=K_|data_hash=CRC32:bb86f9a2 -packet|codec_type=audio|stream_index=0|pts=145244160|pts_time=10.292245|dts=145244160|dts_time=10.292245|duration=368640|duration_time=0.026122|size=418|pos=166126|flags=K_|data_hash=CRC32:cae5a723 -packet|codec_type=audio|stream_index=0|pts=145612800|pts_time=10.318367|dts=145612800|dts_time=10.318367|duration=368640|duration_time=0.026122|size=418|pos=166544|flags=K_|data_hash=CRC32:86376f16 -packet|codec_type=audio|stream_index=0|pts=145981440|pts_time=10.344490|dts=145981440|dts_time=10.344490|duration=368640|duration_time=0.026122|size=418|pos=166962|flags=K_|data_hash=CRC32:02a40485 -packet|codec_type=audio|stream_index=0|pts=146350080|pts_time=10.370612|dts=146350080|dts_time=10.370612|duration=368640|duration_time=0.026122|size=418|pos=167380|flags=K_|data_hash=CRC32:36b3012d -packet|codec_type=audio|stream_index=0|pts=146718720|pts_time=10.396735|dts=146718720|dts_time=10.396735|duration=368640|duration_time=0.026122|size=418|pos=167798|flags=K_|data_hash=CRC32:5ee19ccd -packet|codec_type=audio|stream_index=0|pts=147087360|pts_time=10.422857|dts=147087360|dts_time=10.422857|duration=368640|duration_time=0.026122|size=418|pos=168216|flags=K_|data_hash=CRC32:c0152565 -packet|codec_type=audio|stream_index=0|pts=147456000|pts_time=10.448980|dts=147456000|dts_time=10.448980|duration=368640|duration_time=0.026122|size=418|pos=168634|flags=K_|data_hash=CRC32:19e503a0 -packet|codec_type=audio|stream_index=0|pts=147824640|pts_time=10.475102|dts=147824640|dts_time=10.475102|duration=368640|duration_time=0.026122|size=418|pos=169052|flags=K_|data_hash=CRC32:61cec178 -packet|codec_type=audio|stream_index=0|pts=148193280|pts_time=10.501224|dts=148193280|dts_time=10.501224|duration=368640|duration_time=0.026122|size=418|pos=169470|flags=K_|data_hash=CRC32:14781bf1 -packet|codec_type=audio|stream_index=0|pts=148561920|pts_time=10.527347|dts=148561920|dts_time=10.527347|duration=368640|duration_time=0.026122|size=418|pos=169888|flags=K_|data_hash=CRC32:a981e92c -packet|codec_type=audio|stream_index=0|pts=148930560|pts_time=10.553469|dts=148930560|dts_time=10.553469|duration=368640|duration_time=0.026122|size=418|pos=170306|flags=K_|data_hash=CRC32:771754a1 -packet|codec_type=audio|stream_index=0|pts=149299200|pts_time=10.579592|dts=149299200|dts_time=10.579592|duration=368640|duration_time=0.026122|size=418|pos=170724|flags=K_|data_hash=CRC32:d553fa66 -packet|codec_type=audio|stream_index=0|pts=149667840|pts_time=10.605714|dts=149667840|dts_time=10.605714|duration=368640|duration_time=0.026122|size=418|pos=171142|flags=K_|data_hash=CRC32:92289185 -packet|codec_type=audio|stream_index=0|pts=150036480|pts_time=10.631837|dts=150036480|dts_time=10.631837|duration=368640|duration_time=0.026122|size=418|pos=171560|flags=K_|data_hash=CRC32:f9c61381 -packet|codec_type=audio|stream_index=0|pts=150405120|pts_time=10.657959|dts=150405120|dts_time=10.657959|duration=368640|duration_time=0.026122|size=418|pos=171978|flags=K_|data_hash=CRC32:d68bf882 -packet|codec_type=audio|stream_index=0|pts=150773760|pts_time=10.684082|dts=150773760|dts_time=10.684082|duration=368640|duration_time=0.026122|size=418|pos=172396|flags=K_|data_hash=CRC32:a5155dee -packet|codec_type=audio|stream_index=0|pts=151142400|pts_time=10.710204|dts=151142400|dts_time=10.710204|duration=368640|duration_time=0.026122|size=418|pos=172814|flags=K_|data_hash=CRC32:98527928 -packet|codec_type=audio|stream_index=0|pts=151511040|pts_time=10.736327|dts=151511040|dts_time=10.736327|duration=368640|duration_time=0.026122|size=418|pos=173232|flags=K_|data_hash=CRC32:b4540586 -packet|codec_type=audio|stream_index=0|pts=151879680|pts_time=10.762449|dts=151879680|dts_time=10.762449|duration=368640|duration_time=0.026122|size=418|pos=173650|flags=K_|data_hash=CRC32:8ca5872b -packet|codec_type=audio|stream_index=0|pts=152248320|pts_time=10.788571|dts=152248320|dts_time=10.788571|duration=368640|duration_time=0.026122|size=418|pos=174068|flags=K_|data_hash=CRC32:b48241ad -packet|codec_type=audio|stream_index=0|pts=152616960|pts_time=10.814694|dts=152616960|dts_time=10.814694|duration=368640|duration_time=0.026122|size=418|pos=174486|flags=K_|data_hash=CRC32:87b45640 -packet|codec_type=audio|stream_index=0|pts=152985600|pts_time=10.840816|dts=152985600|dts_time=10.840816|duration=368640|duration_time=0.026122|size=418|pos=174904|flags=K_|data_hash=CRC32:7e4a7a0c -packet|codec_type=audio|stream_index=0|pts=153354240|pts_time=10.866939|dts=153354240|dts_time=10.866939|duration=368640|duration_time=0.026122|size=418|pos=175322|flags=K_|data_hash=CRC32:6027ce87 -packet|codec_type=audio|stream_index=0|pts=153722880|pts_time=10.893061|dts=153722880|dts_time=10.893061|duration=368640|duration_time=0.026122|size=417|pos=175740|flags=K_|data_hash=CRC32:0d68984f -packet|codec_type=audio|stream_index=0|pts=154091520|pts_time=10.919184|dts=154091520|dts_time=10.919184|duration=368640|duration_time=0.026122|size=418|pos=176157|flags=K_|data_hash=CRC32:614d8028 -packet|codec_type=audio|stream_index=0|pts=154460160|pts_time=10.945306|dts=154460160|dts_time=10.945306|duration=368640|duration_time=0.026122|size=418|pos=176575|flags=K_|data_hash=CRC32:14d0b66c -packet|codec_type=audio|stream_index=0|pts=154828800|pts_time=10.971429|dts=154828800|dts_time=10.971429|duration=368640|duration_time=0.026122|size=418|pos=176993|flags=K_|data_hash=CRC32:6a25430d -packet|codec_type=audio|stream_index=0|pts=155197440|pts_time=10.997551|dts=155197440|dts_time=10.997551|duration=368640|duration_time=0.026122|size=418|pos=177411|flags=K_|data_hash=CRC32:cb4a5803 -packet|codec_type=audio|stream_index=0|pts=155566080|pts_time=11.023673|dts=155566080|dts_time=11.023673|duration=368640|duration_time=0.026122|size=418|pos=177829|flags=K_|data_hash=CRC32:04d55594 -packet|codec_type=audio|stream_index=0|pts=155934720|pts_time=11.049796|dts=155934720|dts_time=11.049796|duration=368640|duration_time=0.026122|size=418|pos=178247|flags=K_|data_hash=CRC32:8c6be356 -packet|codec_type=audio|stream_index=0|pts=156303360|pts_time=11.075918|dts=156303360|dts_time=11.075918|duration=368640|duration_time=0.026122|size=418|pos=178665|flags=K_|data_hash=CRC32:cb291119 -packet|codec_type=audio|stream_index=0|pts=156672000|pts_time=11.102041|dts=156672000|dts_time=11.102041|duration=368640|duration_time=0.026122|size=418|pos=179083|flags=K_|data_hash=CRC32:eb228350 -packet|codec_type=audio|stream_index=0|pts=157040640|pts_time=11.128163|dts=157040640|dts_time=11.128163|duration=368640|duration_time=0.026122|size=418|pos=179501|flags=K_|data_hash=CRC32:c5337a0b -packet|codec_type=audio|stream_index=0|pts=157409280|pts_time=11.154286|dts=157409280|dts_time=11.154286|duration=368640|duration_time=0.026122|size=418|pos=179919|flags=K_|data_hash=CRC32:4cba189e -packet|codec_type=audio|stream_index=0|pts=157777920|pts_time=11.180408|dts=157777920|dts_time=11.180408|duration=368640|duration_time=0.026122|size=418|pos=180337|flags=K_|data_hash=CRC32:0418a931 -packet|codec_type=audio|stream_index=0|pts=158146560|pts_time=11.206531|dts=158146560|dts_time=11.206531|duration=368640|duration_time=0.026122|size=418|pos=180755|flags=K_|data_hash=CRC32:3d44908c -packet|codec_type=audio|stream_index=0|pts=158515200|pts_time=11.232653|dts=158515200|dts_time=11.232653|duration=368640|duration_time=0.026122|size=418|pos=181173|flags=K_|data_hash=CRC32:ed6d7efb -packet|codec_type=audio|stream_index=0|pts=158883840|pts_time=11.258776|dts=158883840|dts_time=11.258776|duration=368640|duration_time=0.026122|size=418|pos=181591|flags=K_|data_hash=CRC32:18ca7c0c -packet|codec_type=audio|stream_index=0|pts=159252480|pts_time=11.284898|dts=159252480|dts_time=11.284898|duration=368640|duration_time=0.026122|size=418|pos=182009|flags=K_|data_hash=CRC32:af52b87e -packet|codec_type=audio|stream_index=0|pts=159621120|pts_time=11.311020|dts=159621120|dts_time=11.311020|duration=368640|duration_time=0.026122|size=418|pos=182427|flags=K_|data_hash=CRC32:bc425aed -packet|codec_type=audio|stream_index=0|pts=159989760|pts_time=11.337143|dts=159989760|dts_time=11.337143|duration=368640|duration_time=0.026122|size=418|pos=182845|flags=K_|data_hash=CRC32:c3d28318 -packet|codec_type=audio|stream_index=0|pts=160358400|pts_time=11.363265|dts=160358400|dts_time=11.363265|duration=368640|duration_time=0.026122|size=418|pos=183263|flags=K_|data_hash=CRC32:e58a6767 -packet|codec_type=audio|stream_index=0|pts=160727040|pts_time=11.389388|dts=160727040|dts_time=11.389388|duration=368640|duration_time=0.026122|size=418|pos=183681|flags=K_|data_hash=CRC32:1ec96cd7 -packet|codec_type=audio|stream_index=0|pts=161095680|pts_time=11.415510|dts=161095680|dts_time=11.415510|duration=368640|duration_time=0.026122|size=418|pos=184099|flags=K_|data_hash=CRC32:f06e5745 -packet|codec_type=audio|stream_index=0|pts=161464320|pts_time=11.441633|dts=161464320|dts_time=11.441633|duration=368640|duration_time=0.026122|size=418|pos=184517|flags=K_|data_hash=CRC32:64601c5b -packet|codec_type=audio|stream_index=0|pts=161832960|pts_time=11.467755|dts=161832960|dts_time=11.467755|duration=368640|duration_time=0.026122|size=418|pos=184935|flags=K_|data_hash=CRC32:d9c27a78 -packet|codec_type=audio|stream_index=0|pts=162201600|pts_time=11.493878|dts=162201600|dts_time=11.493878|duration=368640|duration_time=0.026122|size=418|pos=185353|flags=K_|data_hash=CRC32:dbbff040 -packet|codec_type=audio|stream_index=0|pts=162570240|pts_time=11.520000|dts=162570240|dts_time=11.520000|duration=368640|duration_time=0.026122|size=417|pos=185771|flags=K_|data_hash=CRC32:c9f6c5a9 -packet|codec_type=audio|stream_index=0|pts=162938880|pts_time=11.546122|dts=162938880|dts_time=11.546122|duration=368640|duration_time=0.026122|size=418|pos=186188|flags=K_|data_hash=CRC32:ca280dd5 -packet|codec_type=audio|stream_index=0|pts=163307520|pts_time=11.572245|dts=163307520|dts_time=11.572245|duration=368640|duration_time=0.026122|size=418|pos=186606|flags=K_|data_hash=CRC32:3388d5a6 -packet|codec_type=audio|stream_index=0|pts=163676160|pts_time=11.598367|dts=163676160|dts_time=11.598367|duration=368640|duration_time=0.026122|size=418|pos=187024|flags=K_|data_hash=CRC32:3605bd56 -packet|codec_type=audio|stream_index=0|pts=164044800|pts_time=11.624490|dts=164044800|dts_time=11.624490|duration=368640|duration_time=0.026122|size=418|pos=187442|flags=K_|data_hash=CRC32:4a62eb9d -packet|codec_type=audio|stream_index=0|pts=164413440|pts_time=11.650612|dts=164413440|dts_time=11.650612|duration=368640|duration_time=0.026122|size=418|pos=187860|flags=K_|data_hash=CRC32:17d2c66e -packet|codec_type=audio|stream_index=0|pts=164782080|pts_time=11.676735|dts=164782080|dts_time=11.676735|duration=368640|duration_time=0.026122|size=418|pos=188278|flags=K_|data_hash=CRC32:ef7e72b5 -packet|codec_type=audio|stream_index=0|pts=165150720|pts_time=11.702857|dts=165150720|dts_time=11.702857|duration=368640|duration_time=0.026122|size=418|pos=188696|flags=K_|data_hash=CRC32:f7422408 -packet|codec_type=audio|stream_index=0|pts=165519360|pts_time=11.728980|dts=165519360|dts_time=11.728980|duration=368640|duration_time=0.026122|size=418|pos=189114|flags=K_|data_hash=CRC32:01512d42 -packet|codec_type=audio|stream_index=0|pts=165888000|pts_time=11.755102|dts=165888000|dts_time=11.755102|duration=368640|duration_time=0.026122|size=418|pos=189532|flags=K_|data_hash=CRC32:ec4ae9e0 -packet|codec_type=audio|stream_index=0|pts=166256640|pts_time=11.781224|dts=166256640|dts_time=11.781224|duration=368640|duration_time=0.026122|size=418|pos=189950|flags=K_|data_hash=CRC32:7f2ce39f -packet|codec_type=audio|stream_index=0|pts=166625280|pts_time=11.807347|dts=166625280|dts_time=11.807347|duration=368640|duration_time=0.026122|size=418|pos=190368|flags=K_|data_hash=CRC32:3abb4dc0 -packet|codec_type=audio|stream_index=0|pts=166993920|pts_time=11.833469|dts=166993920|dts_time=11.833469|duration=368640|duration_time=0.026122|size=418|pos=190786|flags=K_|data_hash=CRC32:06fdee7a -packet|codec_type=audio|stream_index=0|pts=167362560|pts_time=11.859592|dts=167362560|dts_time=11.859592|duration=368640|duration_time=0.026122|size=418|pos=191204|flags=K_|data_hash=CRC32:bfaed869 -packet|codec_type=audio|stream_index=0|pts=167731200|pts_time=11.885714|dts=167731200|dts_time=11.885714|duration=368640|duration_time=0.026122|size=418|pos=191622|flags=K_|data_hash=CRC32:a6762b1a -packet|codec_type=audio|stream_index=0|pts=168099840|pts_time=11.911837|dts=168099840|dts_time=11.911837|duration=368640|duration_time=0.026122|size=418|pos=192040|flags=K_|data_hash=CRC32:156bf7e4 -packet|codec_type=audio|stream_index=0|pts=168468480|pts_time=11.937959|dts=168468480|dts_time=11.937959|duration=368640|duration_time=0.026122|size=418|pos=192458|flags=K_|data_hash=CRC32:4cfaf03d -packet|codec_type=audio|stream_index=0|pts=168837120|pts_time=11.964082|dts=168837120|dts_time=11.964082|duration=368640|duration_time=0.026122|size=418|pos=192876|flags=K_|data_hash=CRC32:24cadb2b -packet|codec_type=audio|stream_index=0|pts=169205760|pts_time=11.990204|dts=169205760|dts_time=11.990204|duration=368640|duration_time=0.026122|size=418|pos=193294|flags=K_|data_hash=CRC32:9bba25cb -packet|codec_type=audio|stream_index=0|pts=169574400|pts_time=12.016327|dts=169574400|dts_time=12.016327|duration=368640|duration_time=0.026122|size=418|pos=193712|flags=K_|data_hash=CRC32:a6192bb5 -packet|codec_type=audio|stream_index=0|pts=169943040|pts_time=12.042449|dts=169943040|dts_time=12.042449|duration=368640|duration_time=0.026122|size=418|pos=194130|flags=K_|data_hash=CRC32:c06a11b2 -packet|codec_type=audio|stream_index=0|pts=170311680|pts_time=12.068571|dts=170311680|dts_time=12.068571|duration=368640|duration_time=0.026122|size=418|pos=194548|flags=K_|data_hash=CRC32:cd083930 -packet|codec_type=audio|stream_index=0|pts=170680320|pts_time=12.094694|dts=170680320|dts_time=12.094694|duration=368640|duration_time=0.026122|size=418|pos=194966|flags=K_|data_hash=CRC32:02e92b19 -packet|codec_type=audio|stream_index=0|pts=171048960|pts_time=12.120816|dts=171048960|dts_time=12.120816|duration=368640|duration_time=0.026122|size=418|pos=195384|flags=K_|data_hash=CRC32:4c63b84e -packet|codec_type=audio|stream_index=0|pts=171417600|pts_time=12.146939|dts=171417600|dts_time=12.146939|duration=368640|duration_time=0.026122|size=418|pos=195802|flags=K_|data_hash=CRC32:8e93e537 -packet|codec_type=audio|stream_index=0|pts=171786240|pts_time=12.173061|dts=171786240|dts_time=12.173061|duration=368640|duration_time=0.026122|size=417|pos=196220|flags=K_|data_hash=CRC32:9a9da365 -packet|codec_type=audio|stream_index=0|pts=172154880|pts_time=12.199184|dts=172154880|dts_time=12.199184|duration=368640|duration_time=0.026122|size=418|pos=196637|flags=K_|data_hash=CRC32:3d6cfb68 -packet|codec_type=audio|stream_index=0|pts=172523520|pts_time=12.225306|dts=172523520|dts_time=12.225306|duration=368640|duration_time=0.026122|size=418|pos=197055|flags=K_|data_hash=CRC32:82a3d445 -packet|codec_type=audio|stream_index=0|pts=172892160|pts_time=12.251429|dts=172892160|dts_time=12.251429|duration=368640|duration_time=0.026122|size=418|pos=197473|flags=K_|data_hash=CRC32:186d2c93 -packet|codec_type=audio|stream_index=0|pts=173260800|pts_time=12.277551|dts=173260800|dts_time=12.277551|duration=368640|duration_time=0.026122|size=418|pos=197891|flags=K_|data_hash=CRC32:d7836980 -packet|codec_type=audio|stream_index=0|pts=173629440|pts_time=12.303673|dts=173629440|dts_time=12.303673|duration=368640|duration_time=0.026122|size=418|pos=198309|flags=K_|data_hash=CRC32:7660396f -packet|codec_type=audio|stream_index=0|pts=173998080|pts_time=12.329796|dts=173998080|dts_time=12.329796|duration=368640|duration_time=0.026122|size=418|pos=198727|flags=K_|data_hash=CRC32:382b6366 -packet|codec_type=audio|stream_index=0|pts=174366720|pts_time=12.355918|dts=174366720|dts_time=12.355918|duration=368640|duration_time=0.026122|size=418|pos=199145|flags=K_|data_hash=CRC32:e85af773 -packet|codec_type=audio|stream_index=0|pts=174735360|pts_time=12.382041|dts=174735360|dts_time=12.382041|duration=368640|duration_time=0.026122|size=418|pos=199563|flags=K_|data_hash=CRC32:90dce600 -packet|codec_type=audio|stream_index=0|pts=175104000|pts_time=12.408163|dts=175104000|dts_time=12.408163|duration=368640|duration_time=0.026122|size=418|pos=199981|flags=K_|data_hash=CRC32:51048306 -packet|codec_type=audio|stream_index=0|pts=175472640|pts_time=12.434286|dts=175472640|dts_time=12.434286|duration=368640|duration_time=0.026122|size=418|pos=200399|flags=K_|data_hash=CRC32:8fc72574 -packet|codec_type=audio|stream_index=0|pts=175841280|pts_time=12.460408|dts=175841280|dts_time=12.460408|duration=368640|duration_time=0.026122|size=418|pos=200817|flags=K_|data_hash=CRC32:0c2fdbc9 -packet|codec_type=audio|stream_index=0|pts=176209920|pts_time=12.486531|dts=176209920|dts_time=12.486531|duration=368640|duration_time=0.026122|size=418|pos=201235|flags=K_|data_hash=CRC32:c624821f -packet|codec_type=audio|stream_index=0|pts=176578560|pts_time=12.512653|dts=176578560|dts_time=12.512653|duration=368640|duration_time=0.026122|size=418|pos=201653|flags=K_|data_hash=CRC32:122a97b1 -packet|codec_type=audio|stream_index=0|pts=176947200|pts_time=12.538776|dts=176947200|dts_time=12.538776|duration=368640|duration_time=0.026122|size=418|pos=202071|flags=K_|data_hash=CRC32:70034867 -packet|codec_type=audio|stream_index=0|pts=177315840|pts_time=12.564898|dts=177315840|dts_time=12.564898|duration=368640|duration_time=0.026122|size=418|pos=202489|flags=K_|data_hash=CRC32:23f7ff55 -packet|codec_type=audio|stream_index=0|pts=177684480|pts_time=12.591020|dts=177684480|dts_time=12.591020|duration=368640|duration_time=0.026122|size=418|pos=202907|flags=K_|data_hash=CRC32:30502042 -packet|codec_type=audio|stream_index=0|pts=178053120|pts_time=12.617143|dts=178053120|dts_time=12.617143|duration=368640|duration_time=0.026122|size=418|pos=203325|flags=K_|data_hash=CRC32:c4fc3556 -packet|codec_type=audio|stream_index=0|pts=178421760|pts_time=12.643265|dts=178421760|dts_time=12.643265|duration=368640|duration_time=0.026122|size=418|pos=203743|flags=K_|data_hash=CRC32:93e85444 -packet|codec_type=audio|stream_index=0|pts=178790400|pts_time=12.669388|dts=178790400|dts_time=12.669388|duration=368640|duration_time=0.026122|size=418|pos=204161|flags=K_|data_hash=CRC32:7cd8422c -packet|codec_type=audio|stream_index=0|pts=179159040|pts_time=12.695510|dts=179159040|dts_time=12.695510|duration=368640|duration_time=0.026122|size=418|pos=204579|flags=K_|data_hash=CRC32:b4f0ac22 -packet|codec_type=audio|stream_index=0|pts=179527680|pts_time=12.721633|dts=179527680|dts_time=12.721633|duration=368640|duration_time=0.026122|size=418|pos=204997|flags=K_|data_hash=CRC32:767c9538 -packet|codec_type=audio|stream_index=0|pts=179896320|pts_time=12.747755|dts=179896320|dts_time=12.747755|duration=368640|duration_time=0.026122|size=418|pos=205415|flags=K_|data_hash=CRC32:dc526929 -packet|codec_type=audio|stream_index=0|pts=180264960|pts_time=12.773878|dts=180264960|dts_time=12.773878|duration=368640|duration_time=0.026122|size=418|pos=205833|flags=K_|data_hash=CRC32:8b581282 -packet|codec_type=audio|stream_index=0|pts=180633600|pts_time=12.800000|dts=180633600|dts_time=12.800000|duration=368640|duration_time=0.026122|size=417|pos=206251|flags=K_|data_hash=CRC32:3c289703 -packet|codec_type=audio|stream_index=0|pts=181002240|pts_time=12.826122|dts=181002240|dts_time=12.826122|duration=368640|duration_time=0.026122|size=418|pos=206668|flags=K_|data_hash=CRC32:97ad0eb3 -packet|codec_type=audio|stream_index=0|pts=181370880|pts_time=12.852245|dts=181370880|dts_time=12.852245|duration=368640|duration_time=0.026122|size=418|pos=207086|flags=K_|data_hash=CRC32:faf9c1b5 -packet|codec_type=audio|stream_index=0|pts=181739520|pts_time=12.878367|dts=181739520|dts_time=12.878367|duration=368640|duration_time=0.026122|size=418|pos=207504|flags=K_|data_hash=CRC32:8f7c216a -packet|codec_type=audio|stream_index=0|pts=182108160|pts_time=12.904490|dts=182108160|dts_time=12.904490|duration=368640|duration_time=0.026122|size=418|pos=207922|flags=K_|data_hash=CRC32:2cb8f508 -packet|codec_type=audio|stream_index=0|pts=182476800|pts_time=12.930612|dts=182476800|dts_time=12.930612|duration=368640|duration_time=0.026122|size=418|pos=208340|flags=K_|data_hash=CRC32:0e9ca434 -packet|codec_type=audio|stream_index=0|pts=182845440|pts_time=12.956735|dts=182845440|dts_time=12.956735|duration=368640|duration_time=0.026122|size=418|pos=208758|flags=K_|data_hash=CRC32:ce807881 -packet|codec_type=audio|stream_index=0|pts=183214080|pts_time=12.982857|dts=183214080|dts_time=12.982857|duration=368640|duration_time=0.026122|size=418|pos=209176|flags=K_|data_hash=CRC32:0f2d056d -packet|codec_type=audio|stream_index=0|pts=183582720|pts_time=13.008980|dts=183582720|dts_time=13.008980|duration=368640|duration_time=0.026122|size=418|pos=209594|flags=K_|data_hash=CRC32:34f82e70 -packet|codec_type=audio|stream_index=0|pts=183951360|pts_time=13.035102|dts=183951360|dts_time=13.035102|duration=368640|duration_time=0.026122|size=418|pos=210012|flags=K_|data_hash=CRC32:93986f39 -packet|codec_type=audio|stream_index=0|pts=184320000|pts_time=13.061224|dts=184320000|dts_time=13.061224|duration=368640|duration_time=0.026122|size=418|pos=210430|flags=K_|data_hash=CRC32:057d018c -packet|codec_type=audio|stream_index=0|pts=184688640|pts_time=13.087347|dts=184688640|dts_time=13.087347|duration=368640|duration_time=0.026122|size=418|pos=210848|flags=K_|data_hash=CRC32:20288d86 -packet|codec_type=audio|stream_index=0|pts=185057280|pts_time=13.113469|dts=185057280|dts_time=13.113469|duration=368640|duration_time=0.026122|size=418|pos=211266|flags=K_|data_hash=CRC32:2054d963 -packet|codec_type=audio|stream_index=0|pts=185425920|pts_time=13.139592|dts=185425920|dts_time=13.139592|duration=368640|duration_time=0.026122|size=418|pos=211684|flags=K_|data_hash=CRC32:51451bd5 -packet|codec_type=audio|stream_index=0|pts=185794560|pts_time=13.165714|dts=185794560|dts_time=13.165714|duration=368640|duration_time=0.026122|size=418|pos=212102|flags=K_|data_hash=CRC32:40180197 -packet|codec_type=audio|stream_index=0|pts=186163200|pts_time=13.191837|dts=186163200|dts_time=13.191837|duration=368640|duration_time=0.026122|size=418|pos=212520|flags=K_|data_hash=CRC32:66cdd080 -packet|codec_type=audio|stream_index=0|pts=186531840|pts_time=13.217959|dts=186531840|dts_time=13.217959|duration=368640|duration_time=0.026122|size=418|pos=212938|flags=K_|data_hash=CRC32:03eb571f -packet|codec_type=audio|stream_index=0|pts=186900480|pts_time=13.244082|dts=186900480|dts_time=13.244082|duration=368640|duration_time=0.026122|size=418|pos=213356|flags=K_|data_hash=CRC32:88515140 -packet|codec_type=audio|stream_index=0|pts=187269120|pts_time=13.270204|dts=187269120|dts_time=13.270204|duration=368640|duration_time=0.026122|size=418|pos=213774|flags=K_|data_hash=CRC32:b82428b6 -packet|codec_type=audio|stream_index=0|pts=187637760|pts_time=13.296327|dts=187637760|dts_time=13.296327|duration=368640|duration_time=0.026122|size=418|pos=214192|flags=K_|data_hash=CRC32:43d07d2b -packet|codec_type=audio|stream_index=0|pts=188006400|pts_time=13.322449|dts=188006400|dts_time=13.322449|duration=368640|duration_time=0.026122|size=418|pos=214610|flags=K_|data_hash=CRC32:458c2504 -packet|codec_type=audio|stream_index=0|pts=188375040|pts_time=13.348571|dts=188375040|dts_time=13.348571|duration=368640|duration_time=0.026122|size=418|pos=215028|flags=K_|data_hash=CRC32:efa75088 -packet|codec_type=audio|stream_index=0|pts=188743680|pts_time=13.374694|dts=188743680|dts_time=13.374694|duration=368640|duration_time=0.026122|size=418|pos=215446|flags=K_|data_hash=CRC32:781209a4 -packet|codec_type=audio|stream_index=0|pts=189112320|pts_time=13.400816|dts=189112320|dts_time=13.400816|duration=368640|duration_time=0.026122|size=418|pos=215864|flags=K_|data_hash=CRC32:c09324be -packet|codec_type=audio|stream_index=0|pts=189480960|pts_time=13.426939|dts=189480960|dts_time=13.426939|duration=368640|duration_time=0.026122|size=418|pos=216282|flags=K_|data_hash=CRC32:b4b9932d -packet|codec_type=audio|stream_index=0|pts=189849600|pts_time=13.453061|dts=189849600|dts_time=13.453061|duration=368640|duration_time=0.026122|size=417|pos=216700|flags=K_|data_hash=CRC32:da830315 -packet|codec_type=audio|stream_index=0|pts=190218240|pts_time=13.479184|dts=190218240|dts_time=13.479184|duration=368640|duration_time=0.026122|size=418|pos=217117|flags=K_|data_hash=CRC32:66202e4f -packet|codec_type=audio|stream_index=0|pts=190586880|pts_time=13.505306|dts=190586880|dts_time=13.505306|duration=368640|duration_time=0.026122|size=418|pos=217535|flags=K_|data_hash=CRC32:2e237c5c -packet|codec_type=audio|stream_index=0|pts=190955520|pts_time=13.531429|dts=190955520|dts_time=13.531429|duration=368640|duration_time=0.026122|size=418|pos=217953|flags=K_|data_hash=CRC32:5764d408 -packet|codec_type=audio|stream_index=0|pts=191324160|pts_time=13.557551|dts=191324160|dts_time=13.557551|duration=368640|duration_time=0.026122|size=418|pos=218371|flags=K_|data_hash=CRC32:35c3a585 -packet|codec_type=audio|stream_index=0|pts=191692800|pts_time=13.583673|dts=191692800|dts_time=13.583673|duration=368640|duration_time=0.026122|size=418|pos=218789|flags=K_|data_hash=CRC32:78fe7986 -packet|codec_type=audio|stream_index=0|pts=192061440|pts_time=13.609796|dts=192061440|dts_time=13.609796|duration=368640|duration_time=0.026122|size=418|pos=219207|flags=K_|data_hash=CRC32:9f375cbe -packet|codec_type=audio|stream_index=0|pts=192430080|pts_time=13.635918|dts=192430080|dts_time=13.635918|duration=368640|duration_time=0.026122|size=418|pos=219625|flags=K_|data_hash=CRC32:491852fd -packet|codec_type=audio|stream_index=0|pts=192798720|pts_time=13.662041|dts=192798720|dts_time=13.662041|duration=368640|duration_time=0.026122|size=418|pos=220043|flags=K_|data_hash=CRC32:4f831db2 -packet|codec_type=audio|stream_index=0|pts=193167360|pts_time=13.688163|dts=193167360|dts_time=13.688163|duration=368640|duration_time=0.026122|size=418|pos=220461|flags=K_|data_hash=CRC32:030e4b07 -packet|codec_type=audio|stream_index=0|pts=193536000|pts_time=13.714286|dts=193536000|dts_time=13.714286|duration=368640|duration_time=0.026122|size=418|pos=220879|flags=K_|data_hash=CRC32:098ea741 -packet|codec_type=audio|stream_index=0|pts=193904640|pts_time=13.740408|dts=193904640|dts_time=13.740408|duration=368640|duration_time=0.026122|size=418|pos=221297|flags=K_|data_hash=CRC32:7ad88654 -packet|codec_type=audio|stream_index=0|pts=194273280|pts_time=13.766531|dts=194273280|dts_time=13.766531|duration=368640|duration_time=0.026122|size=418|pos=221715|flags=K_|data_hash=CRC32:d88ccfac -packet|codec_type=audio|stream_index=0|pts=194641920|pts_time=13.792653|dts=194641920|dts_time=13.792653|duration=368640|duration_time=0.026122|size=418|pos=222133|flags=K_|data_hash=CRC32:f22666d1 -packet|codec_type=audio|stream_index=0|pts=195010560|pts_time=13.818776|dts=195010560|dts_time=13.818776|duration=368640|duration_time=0.026122|size=418|pos=222551|flags=K_|data_hash=CRC32:d249bf1c -packet|codec_type=audio|stream_index=0|pts=195379200|pts_time=13.844898|dts=195379200|dts_time=13.844898|duration=368640|duration_time=0.026122|size=418|pos=222969|flags=K_|data_hash=CRC32:98e88198 -packet|codec_type=audio|stream_index=0|pts=195747840|pts_time=13.871020|dts=195747840|dts_time=13.871020|duration=368640|duration_time=0.026122|size=418|pos=223387|flags=K_|data_hash=CRC32:8a9fc4b4 -packet|codec_type=audio|stream_index=0|pts=196116480|pts_time=13.897143|dts=196116480|dts_time=13.897143|duration=368640|duration_time=0.026122|size=418|pos=223805|flags=K_|data_hash=CRC32:e0835e74 -packet|codec_type=audio|stream_index=0|pts=196485120|pts_time=13.923265|dts=196485120|dts_time=13.923265|duration=368640|duration_time=0.026122|size=418|pos=224223|flags=K_|data_hash=CRC32:08c1071f -packet|codec_type=audio|stream_index=0|pts=196853760|pts_time=13.949388|dts=196853760|dts_time=13.949388|duration=368640|duration_time=0.026122|size=418|pos=224641|flags=K_|data_hash=CRC32:ca5a3aaa -packet|codec_type=audio|stream_index=0|pts=197222400|pts_time=13.975510|dts=197222400|dts_time=13.975510|duration=368640|duration_time=0.026122|size=418|pos=225059|flags=K_|data_hash=CRC32:f789d2b3 -packet|codec_type=audio|stream_index=0|pts=197591040|pts_time=14.001633|dts=197591040|dts_time=14.001633|duration=368640|duration_time=0.026122|size=418|pos=225477|flags=K_|data_hash=CRC32:7bc285ed -packet|codec_type=audio|stream_index=0|pts=197959680|pts_time=14.027755|dts=197959680|dts_time=14.027755|duration=368640|duration_time=0.026122|size=418|pos=225895|flags=K_|data_hash=CRC32:6061a821 -packet|codec_type=audio|stream_index=0|pts=198328320|pts_time=14.053878|dts=198328320|dts_time=14.053878|duration=368640|duration_time=0.026122|size=418|pos=226313|flags=K_|data_hash=CRC32:14367df4 -packet|codec_type=audio|stream_index=0|pts=198696960|pts_time=14.080000|dts=198696960|dts_time=14.080000|duration=368640|duration_time=0.026122|size=417|pos=226731|flags=K_|data_hash=CRC32:f3140a6b -packet|codec_type=audio|stream_index=0|pts=199065600|pts_time=14.106122|dts=199065600|dts_time=14.106122|duration=368640|duration_time=0.026122|size=418|pos=227148|flags=K_|data_hash=CRC32:ebf07925 -packet|codec_type=audio|stream_index=0|pts=199434240|pts_time=14.132245|dts=199434240|dts_time=14.132245|duration=368640|duration_time=0.026122|size=418|pos=227566|flags=K_|data_hash=CRC32:4f8cde59 -packet|codec_type=audio|stream_index=0|pts=199802880|pts_time=14.158367|dts=199802880|dts_time=14.158367|duration=368640|duration_time=0.026122|size=418|pos=227984|flags=K_|data_hash=CRC32:4467b601 -packet|codec_type=audio|stream_index=0|pts=200171520|pts_time=14.184490|dts=200171520|dts_time=14.184490|duration=368640|duration_time=0.026122|size=418|pos=228402|flags=K_|data_hash=CRC32:f6ae7ed4 -packet|codec_type=audio|stream_index=0|pts=200540160|pts_time=14.210612|dts=200540160|dts_time=14.210612|duration=368640|duration_time=0.026122|size=418|pos=228820|flags=K_|data_hash=CRC32:5cb30836 -packet|codec_type=audio|stream_index=0|pts=200908800|pts_time=14.236735|dts=200908800|dts_time=14.236735|duration=368640|duration_time=0.026122|size=418|pos=229238|flags=K_|data_hash=CRC32:21b70421 -packet|codec_type=audio|stream_index=0|pts=201277440|pts_time=14.262857|dts=201277440|dts_time=14.262857|duration=368640|duration_time=0.026122|size=418|pos=229656|flags=K_|data_hash=CRC32:3bcafdd7 -packet|codec_type=audio|stream_index=0|pts=201646080|pts_time=14.288980|dts=201646080|dts_time=14.288980|duration=368640|duration_time=0.026122|size=418|pos=230074|flags=K_|data_hash=CRC32:76edd678 -packet|codec_type=audio|stream_index=0|pts=202014720|pts_time=14.315102|dts=202014720|dts_time=14.315102|duration=368640|duration_time=0.026122|size=418|pos=230492|flags=K_|data_hash=CRC32:0999fa0b -packet|codec_type=audio|stream_index=0|pts=202383360|pts_time=14.341224|dts=202383360|dts_time=14.341224|duration=368640|duration_time=0.026122|size=418|pos=230910|flags=K_|data_hash=CRC32:227a3da5 -packet|codec_type=audio|stream_index=0|pts=202752000|pts_time=14.367347|dts=202752000|dts_time=14.367347|duration=368640|duration_time=0.026122|size=418|pos=231328|flags=K_|data_hash=CRC32:0068cd57 -packet|codec_type=audio|stream_index=0|pts=203120640|pts_time=14.393469|dts=203120640|dts_time=14.393469|duration=368640|duration_time=0.026122|size=418|pos=231746|flags=K_|data_hash=CRC32:70f8a1dc -packet|codec_type=audio|stream_index=0|pts=203489280|pts_time=14.419592|dts=203489280|dts_time=14.419592|duration=368640|duration_time=0.026122|size=418|pos=232164|flags=K_|data_hash=CRC32:c19072eb -packet|codec_type=audio|stream_index=0|pts=203857920|pts_time=14.445714|dts=203857920|dts_time=14.445714|duration=368640|duration_time=0.026122|size=418|pos=232582|flags=K_|data_hash=CRC32:f0461d09 -packet|codec_type=audio|stream_index=0|pts=204226560|pts_time=14.471837|dts=204226560|dts_time=14.471837|duration=368640|duration_time=0.026122|size=418|pos=233000|flags=K_|data_hash=CRC32:c8fa8555 -packet|codec_type=audio|stream_index=0|pts=204595200|pts_time=14.497959|dts=204595200|dts_time=14.497959|duration=368640|duration_time=0.026122|size=418|pos=233418|flags=K_|data_hash=CRC32:901f5bfb -packet|codec_type=audio|stream_index=0|pts=204963840|pts_time=14.524082|dts=204963840|dts_time=14.524082|duration=368640|duration_time=0.026122|size=418|pos=233836|flags=K_|data_hash=CRC32:91d0ab8c -packet|codec_type=audio|stream_index=0|pts=205332480|pts_time=14.550204|dts=205332480|dts_time=14.550204|duration=368640|duration_time=0.026122|size=418|pos=234254|flags=K_|data_hash=CRC32:3516c575 -packet|codec_type=audio|stream_index=0|pts=205701120|pts_time=14.576327|dts=205701120|dts_time=14.576327|duration=368640|duration_time=0.026122|size=418|pos=234672|flags=K_|data_hash=CRC32:b32cd4ed -packet|codec_type=audio|stream_index=0|pts=206069760|pts_time=14.602449|dts=206069760|dts_time=14.602449|duration=368640|duration_time=0.026122|size=418|pos=235090|flags=K_|data_hash=CRC32:bcd22861 -packet|codec_type=audio|stream_index=0|pts=206438400|pts_time=14.628571|dts=206438400|dts_time=14.628571|duration=368640|duration_time=0.026122|size=418|pos=235508|flags=K_|data_hash=CRC32:a7d0b124 -packet|codec_type=audio|stream_index=0|pts=206807040|pts_time=14.654694|dts=206807040|dts_time=14.654694|duration=368640|duration_time=0.026122|size=418|pos=235926|flags=K_|data_hash=CRC32:3fed01ec -packet|codec_type=audio|stream_index=0|pts=207175680|pts_time=14.680816|dts=207175680|dts_time=14.680816|duration=368640|duration_time=0.026122|size=418|pos=236344|flags=K_|data_hash=CRC32:ff85606f -packet|codec_type=audio|stream_index=0|pts=207544320|pts_time=14.706939|dts=207544320|dts_time=14.706939|duration=368640|duration_time=0.026122|size=418|pos=236762|flags=K_|data_hash=CRC32:a62312cb -packet|codec_type=audio|stream_index=0|pts=207912960|pts_time=14.733061|dts=207912960|dts_time=14.733061|duration=368640|duration_time=0.026122|size=417|pos=237180|flags=K_|data_hash=CRC32:4b910380 -packet|codec_type=audio|stream_index=0|pts=208281600|pts_time=14.759184|dts=208281600|dts_time=14.759184|duration=368640|duration_time=0.026122|size=418|pos=237597|flags=K_|data_hash=CRC32:4f97177f -packet|codec_type=audio|stream_index=0|pts=208650240|pts_time=14.785306|dts=208650240|dts_time=14.785306|duration=368640|duration_time=0.026122|size=418|pos=238015|flags=K_|data_hash=CRC32:f919570c -packet|codec_type=audio|stream_index=0|pts=209018880|pts_time=14.811429|dts=209018880|dts_time=14.811429|duration=368640|duration_time=0.026122|size=418|pos=238433|flags=K_|data_hash=CRC32:74ca87ce -packet|codec_type=audio|stream_index=0|pts=209387520|pts_time=14.837551|dts=209387520|dts_time=14.837551|duration=368640|duration_time=0.026122|size=418|pos=238851|flags=K_|data_hash=CRC32:5fb510e2 -packet|codec_type=audio|stream_index=0|pts=209756160|pts_time=14.863673|dts=209756160|dts_time=14.863673|duration=368640|duration_time=0.026122|size=418|pos=239269|flags=K_|data_hash=CRC32:c01c76b9 -packet|codec_type=audio|stream_index=0|pts=210124800|pts_time=14.889796|dts=210124800|dts_time=14.889796|duration=368640|duration_time=0.026122|size=418|pos=239687|flags=K_|data_hash=CRC32:fb39fca0 -packet|codec_type=audio|stream_index=0|pts=210493440|pts_time=14.915918|dts=210493440|dts_time=14.915918|duration=368640|duration_time=0.026122|size=418|pos=240105|flags=K_|data_hash=CRC32:9b334424 -packet|codec_type=audio|stream_index=0|pts=210862080|pts_time=14.942041|dts=210862080|dts_time=14.942041|duration=368640|duration_time=0.026122|size=418|pos=240523|flags=K_|data_hash=CRC32:8b9fd924 -packet|codec_type=audio|stream_index=0|pts=211230720|pts_time=14.968163|dts=211230720|dts_time=14.968163|duration=368640|duration_time=0.026122|size=418|pos=240941|flags=K_|data_hash=CRC32:e81832b1 -packet|codec_type=audio|stream_index=0|pts=211599360|pts_time=14.994286|dts=211599360|dts_time=14.994286|duration=368640|duration_time=0.026122|size=418|pos=241359|flags=K_|data_hash=CRC32:cef4dc50 -packet|codec_type=audio|stream_index=0|pts=211968000|pts_time=15.020408|dts=211968000|dts_time=15.020408|duration=368640|duration_time=0.026122|size=418|pos=241777|flags=K_|data_hash=CRC32:4948aebf -packet|codec_type=audio|stream_index=0|pts=212336640|pts_time=15.046531|dts=212336640|dts_time=15.046531|duration=368640|duration_time=0.026122|size=418|pos=242195|flags=K_|data_hash=CRC32:eb2c924e -packet|codec_type=audio|stream_index=0|pts=212705280|pts_time=15.072653|dts=212705280|dts_time=15.072653|duration=368640|duration_time=0.026122|size=418|pos=242613|flags=K_|data_hash=CRC32:851f8690 -packet|codec_type=audio|stream_index=0|pts=213073920|pts_time=15.098776|dts=213073920|dts_time=15.098776|duration=368640|duration_time=0.026122|size=418|pos=243031|flags=K_|data_hash=CRC32:4c0e608d -packet|codec_type=audio|stream_index=0|pts=213442560|pts_time=15.124898|dts=213442560|dts_time=15.124898|duration=368640|duration_time=0.026122|size=418|pos=243449|flags=K_|data_hash=CRC32:37f43818 -packet|codec_type=audio|stream_index=0|pts=213811200|pts_time=15.151020|dts=213811200|dts_time=15.151020|duration=368640|duration_time=0.026122|size=418|pos=243867|flags=K_|data_hash=CRC32:8f88252e -packet|codec_type=audio|stream_index=0|pts=214179840|pts_time=15.177143|dts=214179840|dts_time=15.177143|duration=368640|duration_time=0.026122|size=418|pos=244285|flags=K_|data_hash=CRC32:95f6b13d -packet|codec_type=audio|stream_index=0|pts=214548480|pts_time=15.203265|dts=214548480|dts_time=15.203265|duration=368640|duration_time=0.026122|size=418|pos=244703|flags=K_|data_hash=CRC32:32dde92f -packet|codec_type=audio|stream_index=0|pts=214917120|pts_time=15.229388|dts=214917120|dts_time=15.229388|duration=368640|duration_time=0.026122|size=418|pos=245121|flags=K_|data_hash=CRC32:0d034c77 -packet|codec_type=audio|stream_index=0|pts=215285760|pts_time=15.255510|dts=215285760|dts_time=15.255510|duration=368640|duration_time=0.026122|size=418|pos=245539|flags=K_|data_hash=CRC32:4cbf0548 -packet|codec_type=audio|stream_index=0|pts=215654400|pts_time=15.281633|dts=215654400|dts_time=15.281633|duration=368640|duration_time=0.026122|size=418|pos=245957|flags=K_|data_hash=CRC32:599d8f8f -packet|codec_type=audio|stream_index=0|pts=216023040|pts_time=15.307755|dts=216023040|dts_time=15.307755|duration=368640|duration_time=0.026122|size=418|pos=246375|flags=K_|data_hash=CRC32:da07f929 -packet|codec_type=audio|stream_index=0|pts=216391680|pts_time=15.333878|dts=216391680|dts_time=15.333878|duration=368640|duration_time=0.026122|size=418|pos=246793|flags=K_|data_hash=CRC32:294af00d -packet|codec_type=audio|stream_index=0|pts=216760320|pts_time=15.360000|dts=216760320|dts_time=15.360000|duration=368640|duration_time=0.026122|size=417|pos=247211|flags=K_|data_hash=CRC32:14a8bd71 -packet|codec_type=audio|stream_index=0|pts=217128960|pts_time=15.386122|dts=217128960|dts_time=15.386122|duration=368640|duration_time=0.026122|size=418|pos=247628|flags=K_|data_hash=CRC32:10afdcd0 -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_|data_hash=CRC32:d5fb5f9c|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=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 +packet|codec_type=audio|stream_index=0|pts=1105920|pts_time=0.078367|dts=1105920|dts_time=0.078367|duration=368640|duration_time=0.026122|size=418|pos=2704|flags=K__|data_hash=CRC32:baec14f8 +packet|codec_type=audio|stream_index=0|pts=1474560|pts_time=0.104490|dts=1474560|dts_time=0.104490|duration=368640|duration_time=0.026122|size=418|pos=3122|flags=K__|data_hash=CRC32:9916a4cf +packet|codec_type=audio|stream_index=0|pts=1843200|pts_time=0.130612|dts=1843200|dts_time=0.130612|duration=368640|duration_time=0.026122|size=418|pos=3540|flags=K__|data_hash=CRC32:a5897354 +packet|codec_type=audio|stream_index=0|pts=2211840|pts_time=0.156735|dts=2211840|dts_time=0.156735|duration=368640|duration_time=0.026122|size=418|pos=3958|flags=K__|data_hash=CRC32:3b3bd4e1 +packet|codec_type=audio|stream_index=0|pts=2580480|pts_time=0.182857|dts=2580480|dts_time=0.182857|duration=368640|duration_time=0.026122|size=418|pos=4376|flags=K__|data_hash=CRC32:5a319d96 +packet|codec_type=audio|stream_index=0|pts=2949120|pts_time=0.208980|dts=2949120|dts_time=0.208980|duration=368640|duration_time=0.026122|size=418|pos=4794|flags=K__|data_hash=CRC32:c62a20be +packet|codec_type=audio|stream_index=0|pts=3317760|pts_time=0.235102|dts=3317760|dts_time=0.235102|duration=368640|duration_time=0.026122|size=418|pos=5212|flags=K__|data_hash=CRC32:233edc53 +packet|codec_type=audio|stream_index=0|pts=3686400|pts_time=0.261224|dts=3686400|dts_time=0.261224|duration=368640|duration_time=0.026122|size=418|pos=5630|flags=K__|data_hash=CRC32:62ff9ae2 +packet|codec_type=audio|stream_index=0|pts=4055040|pts_time=0.287347|dts=4055040|dts_time=0.287347|duration=368640|duration_time=0.026122|size=418|pos=6048|flags=K__|data_hash=CRC32:de77ed5e +packet|codec_type=audio|stream_index=0|pts=4423680|pts_time=0.313469|dts=4423680|dts_time=0.313469|duration=368640|duration_time=0.026122|size=418|pos=6466|flags=K__|data_hash=CRC32:1ea533a1 +packet|codec_type=audio|stream_index=0|pts=4792320|pts_time=0.339592|dts=4792320|dts_time=0.339592|duration=368640|duration_time=0.026122|size=418|pos=6884|flags=K__|data_hash=CRC32:b5b48e4b +packet|codec_type=audio|stream_index=0|pts=5160960|pts_time=0.365714|dts=5160960|dts_time=0.365714|duration=368640|duration_time=0.026122|size=418|pos=7302|flags=K__|data_hash=CRC32:afdcd44b +packet|codec_type=audio|stream_index=0|pts=5529600|pts_time=0.391837|dts=5529600|dts_time=0.391837|duration=368640|duration_time=0.026122|size=418|pos=7720|flags=K__|data_hash=CRC32:10038cf1 +packet|codec_type=audio|stream_index=0|pts=5898240|pts_time=0.417959|dts=5898240|dts_time=0.417959|duration=368640|duration_time=0.026122|size=418|pos=8138|flags=K__|data_hash=CRC32:0d72e0e3 +packet|codec_type=audio|stream_index=0|pts=6266880|pts_time=0.444082|dts=6266880|dts_time=0.444082|duration=368640|duration_time=0.026122|size=418|pos=8556|flags=K__|data_hash=CRC32:7919c1eb +packet|codec_type=audio|stream_index=0|pts=6635520|pts_time=0.470204|dts=6635520|dts_time=0.470204|duration=368640|duration_time=0.026122|size=418|pos=8974|flags=K__|data_hash=CRC32:95549eee +packet|codec_type=audio|stream_index=0|pts=7004160|pts_time=0.496327|dts=7004160|dts_time=0.496327|duration=368640|duration_time=0.026122|size=418|pos=9392|flags=K__|data_hash=CRC32:d8d5c005 +packet|codec_type=audio|stream_index=0|pts=7372800|pts_time=0.522449|dts=7372800|dts_time=0.522449|duration=368640|duration_time=0.026122|size=418|pos=9810|flags=K__|data_hash=CRC32:09a9254b +packet|codec_type=audio|stream_index=0|pts=7741440|pts_time=0.548571|dts=7741440|dts_time=0.548571|duration=368640|duration_time=0.026122|size=418|pos=10228|flags=K__|data_hash=CRC32:29cc7956 +packet|codec_type=audio|stream_index=0|pts=8110080|pts_time=0.574694|dts=8110080|dts_time=0.574694|duration=368640|duration_time=0.026122|size=418|pos=10646|flags=K__|data_hash=CRC32:cb439791 +packet|codec_type=audio|stream_index=0|pts=8478720|pts_time=0.600816|dts=8478720|dts_time=0.600816|duration=368640|duration_time=0.026122|size=418|pos=11064|flags=K__|data_hash=CRC32:7784025b +packet|codec_type=audio|stream_index=0|pts=8847360|pts_time=0.626939|dts=8847360|dts_time=0.626939|duration=368640|duration_time=0.026122|size=418|pos=11482|flags=K__|data_hash=CRC32:ad6d75d3 +packet|codec_type=audio|stream_index=0|pts=9216000|pts_time=0.653061|dts=9216000|dts_time=0.653061|duration=368640|duration_time=0.026122|size=417|pos=11900|flags=K__|data_hash=CRC32:081e0b41 +packet|codec_type=audio|stream_index=0|pts=9584640|pts_time=0.679184|dts=9584640|dts_time=0.679184|duration=368640|duration_time=0.026122|size=418|pos=12317|flags=K__|data_hash=CRC32:3c8c1e54 +packet|codec_type=audio|stream_index=0|pts=9953280|pts_time=0.705306|dts=9953280|dts_time=0.705306|duration=368640|duration_time=0.026122|size=418|pos=12735|flags=K__|data_hash=CRC32:58dea5a2 +packet|codec_type=audio|stream_index=0|pts=10321920|pts_time=0.731429|dts=10321920|dts_time=0.731429|duration=368640|duration_time=0.026122|size=418|pos=13153|flags=K__|data_hash=CRC32:d56daa18 +packet|codec_type=audio|stream_index=0|pts=10690560|pts_time=0.757551|dts=10690560|dts_time=0.757551|duration=368640|duration_time=0.026122|size=418|pos=13571|flags=K__|data_hash=CRC32:ab2b2c48 +packet|codec_type=audio|stream_index=0|pts=11059200|pts_time=0.783673|dts=11059200|dts_time=0.783673|duration=368640|duration_time=0.026122|size=418|pos=13989|flags=K__|data_hash=CRC32:52467934 +packet|codec_type=audio|stream_index=0|pts=11427840|pts_time=0.809796|dts=11427840|dts_time=0.809796|duration=368640|duration_time=0.026122|size=418|pos=14407|flags=K__|data_hash=CRC32:2e8e22fc +packet|codec_type=audio|stream_index=0|pts=11796480|pts_time=0.835918|dts=11796480|dts_time=0.835918|duration=368640|duration_time=0.026122|size=418|pos=14825|flags=K__|data_hash=CRC32:2432d9df +packet|codec_type=audio|stream_index=0|pts=12165120|pts_time=0.862041|dts=12165120|dts_time=0.862041|duration=368640|duration_time=0.026122|size=418|pos=15243|flags=K__|data_hash=CRC32:623666e1 +packet|codec_type=audio|stream_index=0|pts=12533760|pts_time=0.888163|dts=12533760|dts_time=0.888163|duration=368640|duration_time=0.026122|size=418|pos=15661|flags=K__|data_hash=CRC32:7efdc60c +packet|codec_type=audio|stream_index=0|pts=12902400|pts_time=0.914286|dts=12902400|dts_time=0.914286|duration=368640|duration_time=0.026122|size=418|pos=16079|flags=K__|data_hash=CRC32:22e96068 +packet|codec_type=audio|stream_index=0|pts=13271040|pts_time=0.940408|dts=13271040|dts_time=0.940408|duration=368640|duration_time=0.026122|size=418|pos=16497|flags=K__|data_hash=CRC32:544c1b78 +packet|codec_type=audio|stream_index=0|pts=13639680|pts_time=0.966531|dts=13639680|dts_time=0.966531|duration=368640|duration_time=0.026122|size=418|pos=16915|flags=K__|data_hash=CRC32:e9413152 +packet|codec_type=audio|stream_index=0|pts=14008320|pts_time=0.992653|dts=14008320|dts_time=0.992653|duration=368640|duration_time=0.026122|size=418|pos=17333|flags=K__|data_hash=CRC32:f1737ca4 +packet|codec_type=audio|stream_index=0|pts=14376960|pts_time=1.018776|dts=14376960|dts_time=1.018776|duration=368640|duration_time=0.026122|size=418|pos=17751|flags=K__|data_hash=CRC32:31f7139f +packet|codec_type=audio|stream_index=0|pts=14745600|pts_time=1.044898|dts=14745600|dts_time=1.044898|duration=368640|duration_time=0.026122|size=418|pos=18169|flags=K__|data_hash=CRC32:f330de95 +packet|codec_type=audio|stream_index=0|pts=15114240|pts_time=1.071020|dts=15114240|dts_time=1.071020|duration=368640|duration_time=0.026122|size=418|pos=18587|flags=K__|data_hash=CRC32:6ea0d79f +packet|codec_type=audio|stream_index=0|pts=15482880|pts_time=1.097143|dts=15482880|dts_time=1.097143|duration=368640|duration_time=0.026122|size=418|pos=19005|flags=K__|data_hash=CRC32:cd141c49 +packet|codec_type=audio|stream_index=0|pts=15851520|pts_time=1.123265|dts=15851520|dts_time=1.123265|duration=368640|duration_time=0.026122|size=418|pos=19423|flags=K__|data_hash=CRC32:45c367a6 +packet|codec_type=audio|stream_index=0|pts=16220160|pts_time=1.149388|dts=16220160|dts_time=1.149388|duration=368640|duration_time=0.026122|size=418|pos=19841|flags=K__|data_hash=CRC32:cd89cd56 +packet|codec_type=audio|stream_index=0|pts=16588800|pts_time=1.175510|dts=16588800|dts_time=1.175510|duration=368640|duration_time=0.026122|size=418|pos=20259|flags=K__|data_hash=CRC32:a293ff84 +packet|codec_type=audio|stream_index=0|pts=16957440|pts_time=1.201633|dts=16957440|dts_time=1.201633|duration=368640|duration_time=0.026122|size=418|pos=20677|flags=K__|data_hash=CRC32:a3c6725e +packet|codec_type=audio|stream_index=0|pts=17326080|pts_time=1.227755|dts=17326080|dts_time=1.227755|duration=368640|duration_time=0.026122|size=418|pos=21095|flags=K__|data_hash=CRC32:be091252 +packet|codec_type=audio|stream_index=0|pts=17694720|pts_time=1.253878|dts=17694720|dts_time=1.253878|duration=368640|duration_time=0.026122|size=418|pos=21513|flags=K__|data_hash=CRC32:a5135f75 +packet|codec_type=audio|stream_index=0|pts=18063360|pts_time=1.280000|dts=18063360|dts_time=1.280000|duration=368640|duration_time=0.026122|size=417|pos=21931|flags=K__|data_hash=CRC32:8225dd66 +packet|codec_type=audio|stream_index=0|pts=18432000|pts_time=1.306122|dts=18432000|dts_time=1.306122|duration=368640|duration_time=0.026122|size=418|pos=22348|flags=K__|data_hash=CRC32:7b1db59c +packet|codec_type=audio|stream_index=0|pts=18800640|pts_time=1.332245|dts=18800640|dts_time=1.332245|duration=368640|duration_time=0.026122|size=418|pos=22766|flags=K__|data_hash=CRC32:e5897689 +packet|codec_type=audio|stream_index=0|pts=19169280|pts_time=1.358367|dts=19169280|dts_time=1.358367|duration=368640|duration_time=0.026122|size=418|pos=23184|flags=K__|data_hash=CRC32:94929aa7 +packet|codec_type=audio|stream_index=0|pts=19537920|pts_time=1.384490|dts=19537920|dts_time=1.384490|duration=368640|duration_time=0.026122|size=418|pos=23602|flags=K__|data_hash=CRC32:65697a12 +packet|codec_type=audio|stream_index=0|pts=19906560|pts_time=1.410612|dts=19906560|dts_time=1.410612|duration=368640|duration_time=0.026122|size=418|pos=24020|flags=K__|data_hash=CRC32:18f69ad3 +packet|codec_type=audio|stream_index=0|pts=20275200|pts_time=1.436735|dts=20275200|dts_time=1.436735|duration=368640|duration_time=0.026122|size=418|pos=24438|flags=K__|data_hash=CRC32:47ab41f0 +packet|codec_type=audio|stream_index=0|pts=20643840|pts_time=1.462857|dts=20643840|dts_time=1.462857|duration=368640|duration_time=0.026122|size=418|pos=24856|flags=K__|data_hash=CRC32:75879cf2 +packet|codec_type=audio|stream_index=0|pts=21012480|pts_time=1.488980|dts=21012480|dts_time=1.488980|duration=368640|duration_time=0.026122|size=418|pos=25274|flags=K__|data_hash=CRC32:d43c0882 +packet|codec_type=audio|stream_index=0|pts=21381120|pts_time=1.515102|dts=21381120|dts_time=1.515102|duration=368640|duration_time=0.026122|size=418|pos=25692|flags=K__|data_hash=CRC32:3b9a22da +packet|codec_type=audio|stream_index=0|pts=21749760|pts_time=1.541224|dts=21749760|dts_time=1.541224|duration=368640|duration_time=0.026122|size=418|pos=26110|flags=K__|data_hash=CRC32:ec698fec +packet|codec_type=audio|stream_index=0|pts=22118400|pts_time=1.567347|dts=22118400|dts_time=1.567347|duration=368640|duration_time=0.026122|size=418|pos=26528|flags=K__|data_hash=CRC32:ca99d2c0 +packet|codec_type=audio|stream_index=0|pts=22487040|pts_time=1.593469|dts=22487040|dts_time=1.593469|duration=368640|duration_time=0.026122|size=418|pos=26946|flags=K__|data_hash=CRC32:fa370e06 +packet|codec_type=audio|stream_index=0|pts=22855680|pts_time=1.619592|dts=22855680|dts_time=1.619592|duration=368640|duration_time=0.026122|size=418|pos=27364|flags=K__|data_hash=CRC32:9522fdd4 +packet|codec_type=audio|stream_index=0|pts=23224320|pts_time=1.645714|dts=23224320|dts_time=1.645714|duration=368640|duration_time=0.026122|size=418|pos=27782|flags=K__|data_hash=CRC32:d6bd9ba4 +packet|codec_type=audio|stream_index=0|pts=23592960|pts_time=1.671837|dts=23592960|dts_time=1.671837|duration=368640|duration_time=0.026122|size=418|pos=28200|flags=K__|data_hash=CRC32:f4689266 +packet|codec_type=audio|stream_index=0|pts=23961600|pts_time=1.697959|dts=23961600|dts_time=1.697959|duration=368640|duration_time=0.026122|size=418|pos=28618|flags=K__|data_hash=CRC32:ea1aaa66 +packet|codec_type=audio|stream_index=0|pts=24330240|pts_time=1.724082|dts=24330240|dts_time=1.724082|duration=368640|duration_time=0.026122|size=418|pos=29036|flags=K__|data_hash=CRC32:fb547f37 +packet|codec_type=audio|stream_index=0|pts=24698880|pts_time=1.750204|dts=24698880|dts_time=1.750204|duration=368640|duration_time=0.026122|size=418|pos=29454|flags=K__|data_hash=CRC32:78f84f3f +packet|codec_type=audio|stream_index=0|pts=25067520|pts_time=1.776327|dts=25067520|dts_time=1.776327|duration=368640|duration_time=0.026122|size=418|pos=29872|flags=K__|data_hash=CRC32:db07bf11 +packet|codec_type=audio|stream_index=0|pts=25436160|pts_time=1.802449|dts=25436160|dts_time=1.802449|duration=368640|duration_time=0.026122|size=418|pos=30290|flags=K__|data_hash=CRC32:77bb035b +packet|codec_type=audio|stream_index=0|pts=25804800|pts_time=1.828571|dts=25804800|dts_time=1.828571|duration=368640|duration_time=0.026122|size=418|pos=30708|flags=K__|data_hash=CRC32:23378de7 +packet|codec_type=audio|stream_index=0|pts=26173440|pts_time=1.854694|dts=26173440|dts_time=1.854694|duration=368640|duration_time=0.026122|size=418|pos=31126|flags=K__|data_hash=CRC32:17e3e719 +packet|codec_type=audio|stream_index=0|pts=26542080|pts_time=1.880816|dts=26542080|dts_time=1.880816|duration=368640|duration_time=0.026122|size=418|pos=31544|flags=K__|data_hash=CRC32:b33797de +packet|codec_type=audio|stream_index=0|pts=26910720|pts_time=1.906939|dts=26910720|dts_time=1.906939|duration=368640|duration_time=0.026122|size=418|pos=31962|flags=K__|data_hash=CRC32:d585f179 +packet|codec_type=audio|stream_index=0|pts=27279360|pts_time=1.933061|dts=27279360|dts_time=1.933061|duration=368640|duration_time=0.026122|size=417|pos=32380|flags=K__|data_hash=CRC32:469f8f74 +packet|codec_type=audio|stream_index=0|pts=27648000|pts_time=1.959184|dts=27648000|dts_time=1.959184|duration=368640|duration_time=0.026122|size=418|pos=32797|flags=K__|data_hash=CRC32:fd53cf2f +packet|codec_type=audio|stream_index=0|pts=28016640|pts_time=1.985306|dts=28016640|dts_time=1.985306|duration=368640|duration_time=0.026122|size=418|pos=33215|flags=K__|data_hash=CRC32:5a37e9ae +packet|codec_type=audio|stream_index=0|pts=28385280|pts_time=2.011429|dts=28385280|dts_time=2.011429|duration=368640|duration_time=0.026122|size=418|pos=33633|flags=K__|data_hash=CRC32:123bf9d4 +packet|codec_type=audio|stream_index=0|pts=28753920|pts_time=2.037551|dts=28753920|dts_time=2.037551|duration=368640|duration_time=0.026122|size=418|pos=34051|flags=K__|data_hash=CRC32:a3d4074d +packet|codec_type=audio|stream_index=0|pts=29122560|pts_time=2.063673|dts=29122560|dts_time=2.063673|duration=368640|duration_time=0.026122|size=418|pos=34469|flags=K__|data_hash=CRC32:d79d5351 +packet|codec_type=audio|stream_index=0|pts=29491200|pts_time=2.089796|dts=29491200|dts_time=2.089796|duration=368640|duration_time=0.026122|size=418|pos=34887|flags=K__|data_hash=CRC32:d9a54e49 +packet|codec_type=audio|stream_index=0|pts=29859840|pts_time=2.115918|dts=29859840|dts_time=2.115918|duration=368640|duration_time=0.026122|size=418|pos=35305|flags=K__|data_hash=CRC32:e3f6826f +packet|codec_type=audio|stream_index=0|pts=30228480|pts_time=2.142041|dts=30228480|dts_time=2.142041|duration=368640|duration_time=0.026122|size=418|pos=35723|flags=K__|data_hash=CRC32:2ab209b1 +packet|codec_type=audio|stream_index=0|pts=30597120|pts_time=2.168163|dts=30597120|dts_time=2.168163|duration=368640|duration_time=0.026122|size=418|pos=36141|flags=K__|data_hash=CRC32:bec119c0 +packet|codec_type=audio|stream_index=0|pts=30965760|pts_time=2.194286|dts=30965760|dts_time=2.194286|duration=368640|duration_time=0.026122|size=418|pos=36559|flags=K__|data_hash=CRC32:5e3e13bf +packet|codec_type=audio|stream_index=0|pts=31334400|pts_time=2.220408|dts=31334400|dts_time=2.220408|duration=368640|duration_time=0.026122|size=418|pos=36977|flags=K__|data_hash=CRC32:b725b85c +packet|codec_type=audio|stream_index=0|pts=31703040|pts_time=2.246531|dts=31703040|dts_time=2.246531|duration=368640|duration_time=0.026122|size=418|pos=37395|flags=K__|data_hash=CRC32:e650f974 +packet|codec_type=audio|stream_index=0|pts=32071680|pts_time=2.272653|dts=32071680|dts_time=2.272653|duration=368640|duration_time=0.026122|size=418|pos=37813|flags=K__|data_hash=CRC32:6edc5628 +packet|codec_type=audio|stream_index=0|pts=32440320|pts_time=2.298776|dts=32440320|dts_time=2.298776|duration=368640|duration_time=0.026122|size=418|pos=38231|flags=K__|data_hash=CRC32:37adc162 +packet|codec_type=audio|stream_index=0|pts=32808960|pts_time=2.324898|dts=32808960|dts_time=2.324898|duration=368640|duration_time=0.026122|size=418|pos=38649|flags=K__|data_hash=CRC32:a4b7042e +packet|codec_type=audio|stream_index=0|pts=33177600|pts_time=2.351020|dts=33177600|dts_time=2.351020|duration=368640|duration_time=0.026122|size=418|pos=39067|flags=K__|data_hash=CRC32:c0e98589 +packet|codec_type=audio|stream_index=0|pts=33546240|pts_time=2.377143|dts=33546240|dts_time=2.377143|duration=368640|duration_time=0.026122|size=418|pos=39485|flags=K__|data_hash=CRC32:480fd334 +packet|codec_type=audio|stream_index=0|pts=33914880|pts_time=2.403265|dts=33914880|dts_time=2.403265|duration=368640|duration_time=0.026122|size=418|pos=39903|flags=K__|data_hash=CRC32:4e5d606f +packet|codec_type=audio|stream_index=0|pts=34283520|pts_time=2.429388|dts=34283520|dts_time=2.429388|duration=368640|duration_time=0.026122|size=418|pos=40321|flags=K__|data_hash=CRC32:2d18c337 +packet|codec_type=audio|stream_index=0|pts=34652160|pts_time=2.455510|dts=34652160|dts_time=2.455510|duration=368640|duration_time=0.026122|size=418|pos=40739|flags=K__|data_hash=CRC32:288170f4 +packet|codec_type=audio|stream_index=0|pts=35020800|pts_time=2.481633|dts=35020800|dts_time=2.481633|duration=368640|duration_time=0.026122|size=418|pos=41157|flags=K__|data_hash=CRC32:ce5f7aa9 +packet|codec_type=audio|stream_index=0|pts=35389440|pts_time=2.507755|dts=35389440|dts_time=2.507755|duration=368640|duration_time=0.026122|size=418|pos=41575|flags=K__|data_hash=CRC32:1f0a8297 +packet|codec_type=audio|stream_index=0|pts=35758080|pts_time=2.533878|dts=35758080|dts_time=2.533878|duration=368640|duration_time=0.026122|size=418|pos=41993|flags=K__|data_hash=CRC32:4a8b9b61 +packet|codec_type=audio|stream_index=0|pts=36126720|pts_time=2.560000|dts=36126720|dts_time=2.560000|duration=368640|duration_time=0.026122|size=417|pos=42411|flags=K__|data_hash=CRC32:e3a90971 +packet|codec_type=audio|stream_index=0|pts=36495360|pts_time=2.586122|dts=36495360|dts_time=2.586122|duration=368640|duration_time=0.026122|size=418|pos=42828|flags=K__|data_hash=CRC32:f254c3ce +packet|codec_type=audio|stream_index=0|pts=36864000|pts_time=2.612245|dts=36864000|dts_time=2.612245|duration=368640|duration_time=0.026122|size=418|pos=43246|flags=K__|data_hash=CRC32:1867a5a7 +packet|codec_type=audio|stream_index=0|pts=37232640|pts_time=2.638367|dts=37232640|dts_time=2.638367|duration=368640|duration_time=0.026122|size=418|pos=43664|flags=K__|data_hash=CRC32:0d4fd9de +packet|codec_type=audio|stream_index=0|pts=37601280|pts_time=2.664490|dts=37601280|dts_time=2.664490|duration=368640|duration_time=0.026122|size=418|pos=44082|flags=K__|data_hash=CRC32:878c4022 +packet|codec_type=audio|stream_index=0|pts=37969920|pts_time=2.690612|dts=37969920|dts_time=2.690612|duration=368640|duration_time=0.026122|size=418|pos=44500|flags=K__|data_hash=CRC32:d0b5ed85 +packet|codec_type=audio|stream_index=0|pts=38338560|pts_time=2.716735|dts=38338560|dts_time=2.716735|duration=368640|duration_time=0.026122|size=418|pos=44918|flags=K__|data_hash=CRC32:d93b8cae +packet|codec_type=audio|stream_index=0|pts=38707200|pts_time=2.742857|dts=38707200|dts_time=2.742857|duration=368640|duration_time=0.026122|size=418|pos=45336|flags=K__|data_hash=CRC32:33070649 +packet|codec_type=audio|stream_index=0|pts=39075840|pts_time=2.768980|dts=39075840|dts_time=2.768980|duration=368640|duration_time=0.026122|size=418|pos=45754|flags=K__|data_hash=CRC32:2f74cc7e +packet|codec_type=audio|stream_index=0|pts=39444480|pts_time=2.795102|dts=39444480|dts_time=2.795102|duration=368640|duration_time=0.026122|size=418|pos=46172|flags=K__|data_hash=CRC32:3c7146bc +packet|codec_type=audio|stream_index=0|pts=39813120|pts_time=2.821224|dts=39813120|dts_time=2.821224|duration=368640|duration_time=0.026122|size=418|pos=46590|flags=K__|data_hash=CRC32:62967471 +packet|codec_type=audio|stream_index=0|pts=40181760|pts_time=2.847347|dts=40181760|dts_time=2.847347|duration=368640|duration_time=0.026122|size=418|pos=47008|flags=K__|data_hash=CRC32:efd4b940 +packet|codec_type=audio|stream_index=0|pts=40550400|pts_time=2.873469|dts=40550400|dts_time=2.873469|duration=368640|duration_time=0.026122|size=418|pos=47426|flags=K__|data_hash=CRC32:45338c17 +packet|codec_type=audio|stream_index=0|pts=40919040|pts_time=2.899592|dts=40919040|dts_time=2.899592|duration=368640|duration_time=0.026122|size=418|pos=47844|flags=K__|data_hash=CRC32:0806e97f +packet|codec_type=audio|stream_index=0|pts=41287680|pts_time=2.925714|dts=41287680|dts_time=2.925714|duration=368640|duration_time=0.026122|size=418|pos=48262|flags=K__|data_hash=CRC32:7fa8c136 +packet|codec_type=audio|stream_index=0|pts=41656320|pts_time=2.951837|dts=41656320|dts_time=2.951837|duration=368640|duration_time=0.026122|size=418|pos=48680|flags=K__|data_hash=CRC32:78d7f3e3 +packet|codec_type=audio|stream_index=0|pts=42024960|pts_time=2.977959|dts=42024960|dts_time=2.977959|duration=368640|duration_time=0.026122|size=418|pos=49098|flags=K__|data_hash=CRC32:eb7f4484 +packet|codec_type=audio|stream_index=0|pts=42393600|pts_time=3.004082|dts=42393600|dts_time=3.004082|duration=368640|duration_time=0.026122|size=418|pos=49516|flags=K__|data_hash=CRC32:a2a3f48d +packet|codec_type=audio|stream_index=0|pts=42762240|pts_time=3.030204|dts=42762240|dts_time=3.030204|duration=368640|duration_time=0.026122|size=418|pos=49934|flags=K__|data_hash=CRC32:c478db4a +packet|codec_type=audio|stream_index=0|pts=43130880|pts_time=3.056327|dts=43130880|dts_time=3.056327|duration=368640|duration_time=0.026122|size=418|pos=50352|flags=K__|data_hash=CRC32:e40731af +packet|codec_type=audio|stream_index=0|pts=43499520|pts_time=3.082449|dts=43499520|dts_time=3.082449|duration=368640|duration_time=0.026122|size=418|pos=50770|flags=K__|data_hash=CRC32:74603e95 +packet|codec_type=audio|stream_index=0|pts=43868160|pts_time=3.108571|dts=43868160|dts_time=3.108571|duration=368640|duration_time=0.026122|size=418|pos=51188|flags=K__|data_hash=CRC32:6486340f +packet|codec_type=audio|stream_index=0|pts=44236800|pts_time=3.134694|dts=44236800|dts_time=3.134694|duration=368640|duration_time=0.026122|size=418|pos=51606|flags=K__|data_hash=CRC32:8cda2b23 +packet|codec_type=audio|stream_index=0|pts=44605440|pts_time=3.160816|dts=44605440|dts_time=3.160816|duration=368640|duration_time=0.026122|size=418|pos=52024|flags=K__|data_hash=CRC32:b0bd790d +packet|codec_type=audio|stream_index=0|pts=44974080|pts_time=3.186939|dts=44974080|dts_time=3.186939|duration=368640|duration_time=0.026122|size=418|pos=52442|flags=K__|data_hash=CRC32:5ae7824d +packet|codec_type=audio|stream_index=0|pts=45342720|pts_time=3.213061|dts=45342720|dts_time=3.213061|duration=368640|duration_time=0.026122|size=417|pos=52860|flags=K__|data_hash=CRC32:8ef12cf9 +packet|codec_type=audio|stream_index=0|pts=45711360|pts_time=3.239184|dts=45711360|dts_time=3.239184|duration=368640|duration_time=0.026122|size=418|pos=53277|flags=K__|data_hash=CRC32:7426d3d8 +packet|codec_type=audio|stream_index=0|pts=46080000|pts_time=3.265306|dts=46080000|dts_time=3.265306|duration=368640|duration_time=0.026122|size=418|pos=53695|flags=K__|data_hash=CRC32:87ddbc34 +packet|codec_type=audio|stream_index=0|pts=46448640|pts_time=3.291429|dts=46448640|dts_time=3.291429|duration=368640|duration_time=0.026122|size=418|pos=54113|flags=K__|data_hash=CRC32:18375ee3 +packet|codec_type=audio|stream_index=0|pts=46817280|pts_time=3.317551|dts=46817280|dts_time=3.317551|duration=368640|duration_time=0.026122|size=418|pos=54531|flags=K__|data_hash=CRC32:1b28b358 +packet|codec_type=audio|stream_index=0|pts=47185920|pts_time=3.343673|dts=47185920|dts_time=3.343673|duration=368640|duration_time=0.026122|size=418|pos=54949|flags=K__|data_hash=CRC32:576d401d +packet|codec_type=audio|stream_index=0|pts=47554560|pts_time=3.369796|dts=47554560|dts_time=3.369796|duration=368640|duration_time=0.026122|size=418|pos=55367|flags=K__|data_hash=CRC32:db2ab4fc +packet|codec_type=audio|stream_index=0|pts=47923200|pts_time=3.395918|dts=47923200|dts_time=3.395918|duration=368640|duration_time=0.026122|size=418|pos=55785|flags=K__|data_hash=CRC32:78ca7f79 +packet|codec_type=audio|stream_index=0|pts=48291840|pts_time=3.422041|dts=48291840|dts_time=3.422041|duration=368640|duration_time=0.026122|size=418|pos=56203|flags=K__|data_hash=CRC32:a35e5abd +packet|codec_type=audio|stream_index=0|pts=48660480|pts_time=3.448163|dts=48660480|dts_time=3.448163|duration=368640|duration_time=0.026122|size=418|pos=56621|flags=K__|data_hash=CRC32:682643d6 +packet|codec_type=audio|stream_index=0|pts=49029120|pts_time=3.474286|dts=49029120|dts_time=3.474286|duration=368640|duration_time=0.026122|size=418|pos=57039|flags=K__|data_hash=CRC32:e676c49e +packet|codec_type=audio|stream_index=0|pts=49397760|pts_time=3.500408|dts=49397760|dts_time=3.500408|duration=368640|duration_time=0.026122|size=418|pos=57457|flags=K__|data_hash=CRC32:b41299c0 +packet|codec_type=audio|stream_index=0|pts=49766400|pts_time=3.526531|dts=49766400|dts_time=3.526531|duration=368640|duration_time=0.026122|size=418|pos=57875|flags=K__|data_hash=CRC32:19a7a028 +packet|codec_type=audio|stream_index=0|pts=50135040|pts_time=3.552653|dts=50135040|dts_time=3.552653|duration=368640|duration_time=0.026122|size=418|pos=58293|flags=K__|data_hash=CRC32:e1d92031 +packet|codec_type=audio|stream_index=0|pts=50503680|pts_time=3.578776|dts=50503680|dts_time=3.578776|duration=368640|duration_time=0.026122|size=418|pos=58711|flags=K__|data_hash=CRC32:6fb22e33 +packet|codec_type=audio|stream_index=0|pts=50872320|pts_time=3.604898|dts=50872320|dts_time=3.604898|duration=368640|duration_time=0.026122|size=418|pos=59129|flags=K__|data_hash=CRC32:10096a70 +packet|codec_type=audio|stream_index=0|pts=51240960|pts_time=3.631020|dts=51240960|dts_time=3.631020|duration=368640|duration_time=0.026122|size=418|pos=59547|flags=K__|data_hash=CRC32:57c4a982 +packet|codec_type=audio|stream_index=0|pts=51609600|pts_time=3.657143|dts=51609600|dts_time=3.657143|duration=368640|duration_time=0.026122|size=418|pos=59965|flags=K__|data_hash=CRC32:a705d327 +packet|codec_type=audio|stream_index=0|pts=51978240|pts_time=3.683265|dts=51978240|dts_time=3.683265|duration=368640|duration_time=0.026122|size=418|pos=60383|flags=K__|data_hash=CRC32:7c2beb09 +packet|codec_type=audio|stream_index=0|pts=52346880|pts_time=3.709388|dts=52346880|dts_time=3.709388|duration=368640|duration_time=0.026122|size=418|pos=60801|flags=K__|data_hash=CRC32:7b3d1a15 +packet|codec_type=audio|stream_index=0|pts=52715520|pts_time=3.735510|dts=52715520|dts_time=3.735510|duration=368640|duration_time=0.026122|size=418|pos=61219|flags=K__|data_hash=CRC32:f99045c1 +packet|codec_type=audio|stream_index=0|pts=53084160|pts_time=3.761633|dts=53084160|dts_time=3.761633|duration=368640|duration_time=0.026122|size=418|pos=61637|flags=K__|data_hash=CRC32:dd02d72d +packet|codec_type=audio|stream_index=0|pts=53452800|pts_time=3.787755|dts=53452800|dts_time=3.787755|duration=368640|duration_time=0.026122|size=418|pos=62055|flags=K__|data_hash=CRC32:0606b50a +packet|codec_type=audio|stream_index=0|pts=53821440|pts_time=3.813878|dts=53821440|dts_time=3.813878|duration=368640|duration_time=0.026122|size=418|pos=62473|flags=K__|data_hash=CRC32:bd5ce543 +packet|codec_type=audio|stream_index=0|pts=54190080|pts_time=3.840000|dts=54190080|dts_time=3.840000|duration=368640|duration_time=0.026122|size=417|pos=62891|flags=K__|data_hash=CRC32:feabd4b3 +packet|codec_type=audio|stream_index=0|pts=54558720|pts_time=3.866122|dts=54558720|dts_time=3.866122|duration=368640|duration_time=0.026122|size=418|pos=63308|flags=K__|data_hash=CRC32:0d89c582 +packet|codec_type=audio|stream_index=0|pts=54927360|pts_time=3.892245|dts=54927360|dts_time=3.892245|duration=368640|duration_time=0.026122|size=418|pos=63726|flags=K__|data_hash=CRC32:88664f54 +packet|codec_type=audio|stream_index=0|pts=55296000|pts_time=3.918367|dts=55296000|dts_time=3.918367|duration=368640|duration_time=0.026122|size=418|pos=64144|flags=K__|data_hash=CRC32:f94cac9a +packet|codec_type=audio|stream_index=0|pts=55664640|pts_time=3.944490|dts=55664640|dts_time=3.944490|duration=368640|duration_time=0.026122|size=418|pos=64562|flags=K__|data_hash=CRC32:317dc642 +packet|codec_type=audio|stream_index=0|pts=56033280|pts_time=3.970612|dts=56033280|dts_time=3.970612|duration=368640|duration_time=0.026122|size=418|pos=64980|flags=K__|data_hash=CRC32:478887cd +packet|codec_type=audio|stream_index=0|pts=56401920|pts_time=3.996735|dts=56401920|dts_time=3.996735|duration=368640|duration_time=0.026122|size=418|pos=65398|flags=K__|data_hash=CRC32:4f8ce9d9 +packet|codec_type=audio|stream_index=0|pts=56770560|pts_time=4.022857|dts=56770560|dts_time=4.022857|duration=368640|duration_time=0.026122|size=418|pos=65816|flags=K__|data_hash=CRC32:a2af903e +packet|codec_type=audio|stream_index=0|pts=57139200|pts_time=4.048980|dts=57139200|dts_time=4.048980|duration=368640|duration_time=0.026122|size=418|pos=66234|flags=K__|data_hash=CRC32:43fd701a +packet|codec_type=audio|stream_index=0|pts=57507840|pts_time=4.075102|dts=57507840|dts_time=4.075102|duration=368640|duration_time=0.026122|size=418|pos=66652|flags=K__|data_hash=CRC32:1b823ca6 +packet|codec_type=audio|stream_index=0|pts=57876480|pts_time=4.101224|dts=57876480|dts_time=4.101224|duration=368640|duration_time=0.026122|size=418|pos=67070|flags=K__|data_hash=CRC32:bb5fc2a0 +packet|codec_type=audio|stream_index=0|pts=58245120|pts_time=4.127347|dts=58245120|dts_time=4.127347|duration=368640|duration_time=0.026122|size=418|pos=67488|flags=K__|data_hash=CRC32:9597c685 +packet|codec_type=audio|stream_index=0|pts=58613760|pts_time=4.153469|dts=58613760|dts_time=4.153469|duration=368640|duration_time=0.026122|size=418|pos=67906|flags=K__|data_hash=CRC32:1800cbc7 +packet|codec_type=audio|stream_index=0|pts=58982400|pts_time=4.179592|dts=58982400|dts_time=4.179592|duration=368640|duration_time=0.026122|size=418|pos=68324|flags=K__|data_hash=CRC32:93d29987 +packet|codec_type=audio|stream_index=0|pts=59351040|pts_time=4.205714|dts=59351040|dts_time=4.205714|duration=368640|duration_time=0.026122|size=418|pos=68742|flags=K__|data_hash=CRC32:101eaf05 +packet|codec_type=audio|stream_index=0|pts=59719680|pts_time=4.231837|dts=59719680|dts_time=4.231837|duration=368640|duration_time=0.026122|size=418|pos=69160|flags=K__|data_hash=CRC32:3098d5d0 +packet|codec_type=audio|stream_index=0|pts=60088320|pts_time=4.257959|dts=60088320|dts_time=4.257959|duration=368640|duration_time=0.026122|size=418|pos=69578|flags=K__|data_hash=CRC32:a0435280 +packet|codec_type=audio|stream_index=0|pts=60456960|pts_time=4.284082|dts=60456960|dts_time=4.284082|duration=368640|duration_time=0.026122|size=418|pos=69996|flags=K__|data_hash=CRC32:a583c03b +packet|codec_type=audio|stream_index=0|pts=60825600|pts_time=4.310204|dts=60825600|dts_time=4.310204|duration=368640|duration_time=0.026122|size=418|pos=70414|flags=K__|data_hash=CRC32:11122d17 +packet|codec_type=audio|stream_index=0|pts=61194240|pts_time=4.336327|dts=61194240|dts_time=4.336327|duration=368640|duration_time=0.026122|size=418|pos=70832|flags=K__|data_hash=CRC32:3f3070b1 +packet|codec_type=audio|stream_index=0|pts=61562880|pts_time=4.362449|dts=61562880|dts_time=4.362449|duration=368640|duration_time=0.026122|size=418|pos=71250|flags=K__|data_hash=CRC32:7fcf2489 +packet|codec_type=audio|stream_index=0|pts=61931520|pts_time=4.388571|dts=61931520|dts_time=4.388571|duration=368640|duration_time=0.026122|size=418|pos=71668|flags=K__|data_hash=CRC32:112b3e44 +packet|codec_type=audio|stream_index=0|pts=62300160|pts_time=4.414694|dts=62300160|dts_time=4.414694|duration=368640|duration_time=0.026122|size=418|pos=72086|flags=K__|data_hash=CRC32:5033b587 +packet|codec_type=audio|stream_index=0|pts=62668800|pts_time=4.440816|dts=62668800|dts_time=4.440816|duration=368640|duration_time=0.026122|size=418|pos=72504|flags=K__|data_hash=CRC32:9cb52ea5 +packet|codec_type=audio|stream_index=0|pts=63037440|pts_time=4.466939|dts=63037440|dts_time=4.466939|duration=368640|duration_time=0.026122|size=418|pos=72922|flags=K__|data_hash=CRC32:5630d818 +packet|codec_type=audio|stream_index=0|pts=63406080|pts_time=4.493061|dts=63406080|dts_time=4.493061|duration=368640|duration_time=0.026122|size=417|pos=73340|flags=K__|data_hash=CRC32:328534f2 +packet|codec_type=audio|stream_index=0|pts=63774720|pts_time=4.519184|dts=63774720|dts_time=4.519184|duration=368640|duration_time=0.026122|size=418|pos=73757|flags=K__|data_hash=CRC32:6d57605f +packet|codec_type=audio|stream_index=0|pts=64143360|pts_time=4.545306|dts=64143360|dts_time=4.545306|duration=368640|duration_time=0.026122|size=418|pos=74175|flags=K__|data_hash=CRC32:e79fd1bb +packet|codec_type=audio|stream_index=0|pts=64512000|pts_time=4.571429|dts=64512000|dts_time=4.571429|duration=368640|duration_time=0.026122|size=418|pos=74593|flags=K__|data_hash=CRC32:b61e5e9a +packet|codec_type=audio|stream_index=0|pts=64880640|pts_time=4.597551|dts=64880640|dts_time=4.597551|duration=368640|duration_time=0.026122|size=418|pos=75011|flags=K__|data_hash=CRC32:71bc8fe3 +packet|codec_type=audio|stream_index=0|pts=65249280|pts_time=4.623673|dts=65249280|dts_time=4.623673|duration=368640|duration_time=0.026122|size=418|pos=75429|flags=K__|data_hash=CRC32:72e21ec5 +packet|codec_type=audio|stream_index=0|pts=65617920|pts_time=4.649796|dts=65617920|dts_time=4.649796|duration=368640|duration_time=0.026122|size=418|pos=75847|flags=K__|data_hash=CRC32:f93673ad +packet|codec_type=audio|stream_index=0|pts=65986560|pts_time=4.675918|dts=65986560|dts_time=4.675918|duration=368640|duration_time=0.026122|size=418|pos=76265|flags=K__|data_hash=CRC32:93dffd2d +packet|codec_type=audio|stream_index=0|pts=66355200|pts_time=4.702041|dts=66355200|dts_time=4.702041|duration=368640|duration_time=0.026122|size=418|pos=76683|flags=K__|data_hash=CRC32:b4160eef +packet|codec_type=audio|stream_index=0|pts=66723840|pts_time=4.728163|dts=66723840|dts_time=4.728163|duration=368640|duration_time=0.026122|size=418|pos=77101|flags=K__|data_hash=CRC32:4685fb67 +packet|codec_type=audio|stream_index=0|pts=67092480|pts_time=4.754286|dts=67092480|dts_time=4.754286|duration=368640|duration_time=0.026122|size=418|pos=77519|flags=K__|data_hash=CRC32:b9c9f49c +packet|codec_type=audio|stream_index=0|pts=67461120|pts_time=4.780408|dts=67461120|dts_time=4.780408|duration=368640|duration_time=0.026122|size=418|pos=77937|flags=K__|data_hash=CRC32:97eecd83 +packet|codec_type=audio|stream_index=0|pts=67829760|pts_time=4.806531|dts=67829760|dts_time=4.806531|duration=368640|duration_time=0.026122|size=418|pos=78355|flags=K__|data_hash=CRC32:c5a4d76c +packet|codec_type=audio|stream_index=0|pts=68198400|pts_time=4.832653|dts=68198400|dts_time=4.832653|duration=368640|duration_time=0.026122|size=418|pos=78773|flags=K__|data_hash=CRC32:e693a3e4 +packet|codec_type=audio|stream_index=0|pts=68567040|pts_time=4.858776|dts=68567040|dts_time=4.858776|duration=368640|duration_time=0.026122|size=418|pos=79191|flags=K__|data_hash=CRC32:0596d099 +packet|codec_type=audio|stream_index=0|pts=68935680|pts_time=4.884898|dts=68935680|dts_time=4.884898|duration=368640|duration_time=0.026122|size=418|pos=79609|flags=K__|data_hash=CRC32:cb1ece5e +packet|codec_type=audio|stream_index=0|pts=69304320|pts_time=4.911020|dts=69304320|dts_time=4.911020|duration=368640|duration_time=0.026122|size=418|pos=80027|flags=K__|data_hash=CRC32:04f13287 +packet|codec_type=audio|stream_index=0|pts=69672960|pts_time=4.937143|dts=69672960|dts_time=4.937143|duration=368640|duration_time=0.026122|size=418|pos=80445|flags=K__|data_hash=CRC32:b7288a06 +packet|codec_type=audio|stream_index=0|pts=70041600|pts_time=4.963265|dts=70041600|dts_time=4.963265|duration=368640|duration_time=0.026122|size=418|pos=80863|flags=K__|data_hash=CRC32:da40d80d +packet|codec_type=audio|stream_index=0|pts=70410240|pts_time=4.989388|dts=70410240|dts_time=4.989388|duration=368640|duration_time=0.026122|size=418|pos=81281|flags=K__|data_hash=CRC32:248c54a6 +packet|codec_type=audio|stream_index=0|pts=70778880|pts_time=5.015510|dts=70778880|dts_time=5.015510|duration=368640|duration_time=0.026122|size=418|pos=81699|flags=K__|data_hash=CRC32:c8a6a9a2 +packet|codec_type=audio|stream_index=0|pts=71147520|pts_time=5.041633|dts=71147520|dts_time=5.041633|duration=368640|duration_time=0.026122|size=418|pos=82117|flags=K__|data_hash=CRC32:f2e498bb +packet|codec_type=audio|stream_index=0|pts=71516160|pts_time=5.067755|dts=71516160|dts_time=5.067755|duration=368640|duration_time=0.026122|size=418|pos=82535|flags=K__|data_hash=CRC32:88ae4f13 +packet|codec_type=audio|stream_index=0|pts=71884800|pts_time=5.093878|dts=71884800|dts_time=5.093878|duration=368640|duration_time=0.026122|size=418|pos=82953|flags=K__|data_hash=CRC32:671833ea +packet|codec_type=audio|stream_index=0|pts=72253440|pts_time=5.120000|dts=72253440|dts_time=5.120000|duration=368640|duration_time=0.026122|size=417|pos=83371|flags=K__|data_hash=CRC32:e9300bb8 +packet|codec_type=audio|stream_index=0|pts=72622080|pts_time=5.146122|dts=72622080|dts_time=5.146122|duration=368640|duration_time=0.026122|size=418|pos=83788|flags=K__|data_hash=CRC32:f24ddb8f +packet|codec_type=audio|stream_index=0|pts=72990720|pts_time=5.172245|dts=72990720|dts_time=5.172245|duration=368640|duration_time=0.026122|size=418|pos=84206|flags=K__|data_hash=CRC32:70f61a2c +packet|codec_type=audio|stream_index=0|pts=73359360|pts_time=5.198367|dts=73359360|dts_time=5.198367|duration=368640|duration_time=0.026122|size=418|pos=84624|flags=K__|data_hash=CRC32:73dd76f4 +packet|codec_type=audio|stream_index=0|pts=73728000|pts_time=5.224490|dts=73728000|dts_time=5.224490|duration=368640|duration_time=0.026122|size=418|pos=85042|flags=K__|data_hash=CRC32:0e0502bc +packet|codec_type=audio|stream_index=0|pts=74096640|pts_time=5.250612|dts=74096640|dts_time=5.250612|duration=368640|duration_time=0.026122|size=418|pos=85460|flags=K__|data_hash=CRC32:f014154f +packet|codec_type=audio|stream_index=0|pts=74465280|pts_time=5.276735|dts=74465280|dts_time=5.276735|duration=368640|duration_time=0.026122|size=418|pos=85878|flags=K__|data_hash=CRC32:c937e40d +packet|codec_type=audio|stream_index=0|pts=74833920|pts_time=5.302857|dts=74833920|dts_time=5.302857|duration=368640|duration_time=0.026122|size=418|pos=86296|flags=K__|data_hash=CRC32:4803689b +packet|codec_type=audio|stream_index=0|pts=75202560|pts_time=5.328980|dts=75202560|dts_time=5.328980|duration=368640|duration_time=0.026122|size=418|pos=86714|flags=K__|data_hash=CRC32:22fa34c9 +packet|codec_type=audio|stream_index=0|pts=75571200|pts_time=5.355102|dts=75571200|dts_time=5.355102|duration=368640|duration_time=0.026122|size=418|pos=87132|flags=K__|data_hash=CRC32:178ca70b +packet|codec_type=audio|stream_index=0|pts=75939840|pts_time=5.381224|dts=75939840|dts_time=5.381224|duration=368640|duration_time=0.026122|size=418|pos=87550|flags=K__|data_hash=CRC32:608d220e +packet|codec_type=audio|stream_index=0|pts=76308480|pts_time=5.407347|dts=76308480|dts_time=5.407347|duration=368640|duration_time=0.026122|size=418|pos=87968|flags=K__|data_hash=CRC32:6156090c +packet|codec_type=audio|stream_index=0|pts=76677120|pts_time=5.433469|dts=76677120|dts_time=5.433469|duration=368640|duration_time=0.026122|size=418|pos=88386|flags=K__|data_hash=CRC32:0e137f5c +packet|codec_type=audio|stream_index=0|pts=77045760|pts_time=5.459592|dts=77045760|dts_time=5.459592|duration=368640|duration_time=0.026122|size=418|pos=88804|flags=K__|data_hash=CRC32:1a82efb3 +packet|codec_type=audio|stream_index=0|pts=77414400|pts_time=5.485714|dts=77414400|dts_time=5.485714|duration=368640|duration_time=0.026122|size=418|pos=89222|flags=K__|data_hash=CRC32:6dfaa92a +packet|codec_type=audio|stream_index=0|pts=77783040|pts_time=5.511837|dts=77783040|dts_time=5.511837|duration=368640|duration_time=0.026122|size=418|pos=89640|flags=K__|data_hash=CRC32:0ff57235 +packet|codec_type=audio|stream_index=0|pts=78151680|pts_time=5.537959|dts=78151680|dts_time=5.537959|duration=368640|duration_time=0.026122|size=418|pos=90058|flags=K__|data_hash=CRC32:af6aad5b +packet|codec_type=audio|stream_index=0|pts=78520320|pts_time=5.564082|dts=78520320|dts_time=5.564082|duration=368640|duration_time=0.026122|size=418|pos=90476|flags=K__|data_hash=CRC32:3edc87af +packet|codec_type=audio|stream_index=0|pts=78888960|pts_time=5.590204|dts=78888960|dts_time=5.590204|duration=368640|duration_time=0.026122|size=418|pos=90894|flags=K__|data_hash=CRC32:4e45d2f9 +packet|codec_type=audio|stream_index=0|pts=79257600|pts_time=5.616327|dts=79257600|dts_time=5.616327|duration=368640|duration_time=0.026122|size=418|pos=91312|flags=K__|data_hash=CRC32:3e3d4490 +packet|codec_type=audio|stream_index=0|pts=79626240|pts_time=5.642449|dts=79626240|dts_time=5.642449|duration=368640|duration_time=0.026122|size=418|pos=91730|flags=K__|data_hash=CRC32:ce361a9e +packet|codec_type=audio|stream_index=0|pts=79994880|pts_time=5.668571|dts=79994880|dts_time=5.668571|duration=368640|duration_time=0.026122|size=418|pos=92148|flags=K__|data_hash=CRC32:4b4b5560 +packet|codec_type=audio|stream_index=0|pts=80363520|pts_time=5.694694|dts=80363520|dts_time=5.694694|duration=368640|duration_time=0.026122|size=418|pos=92566|flags=K__|data_hash=CRC32:15778e7b +packet|codec_type=audio|stream_index=0|pts=80732160|pts_time=5.720816|dts=80732160|dts_time=5.720816|duration=368640|duration_time=0.026122|size=418|pos=92984|flags=K__|data_hash=CRC32:6ada6d94 +packet|codec_type=audio|stream_index=0|pts=81100800|pts_time=5.746939|dts=81100800|dts_time=5.746939|duration=368640|duration_time=0.026122|size=418|pos=93402|flags=K__|data_hash=CRC32:3a8d9e78 +packet|codec_type=audio|stream_index=0|pts=81469440|pts_time=5.773061|dts=81469440|dts_time=5.773061|duration=368640|duration_time=0.026122|size=417|pos=93820|flags=K__|data_hash=CRC32:71ba89fd +packet|codec_type=audio|stream_index=0|pts=81838080|pts_time=5.799184|dts=81838080|dts_time=5.799184|duration=368640|duration_time=0.026122|size=418|pos=94237|flags=K__|data_hash=CRC32:16867b8c +packet|codec_type=audio|stream_index=0|pts=82206720|pts_time=5.825306|dts=82206720|dts_time=5.825306|duration=368640|duration_time=0.026122|size=418|pos=94655|flags=K__|data_hash=CRC32:cd7e042c +packet|codec_type=audio|stream_index=0|pts=82575360|pts_time=5.851429|dts=82575360|dts_time=5.851429|duration=368640|duration_time=0.026122|size=418|pos=95073|flags=K__|data_hash=CRC32:d9777ff5 +packet|codec_type=audio|stream_index=0|pts=82944000|pts_time=5.877551|dts=82944000|dts_time=5.877551|duration=368640|duration_time=0.026122|size=418|pos=95491|flags=K__|data_hash=CRC32:015776b6 +packet|codec_type=audio|stream_index=0|pts=83312640|pts_time=5.903673|dts=83312640|dts_time=5.903673|duration=368640|duration_time=0.026122|size=418|pos=95909|flags=K__|data_hash=CRC32:16dbd1ba +packet|codec_type=audio|stream_index=0|pts=83681280|pts_time=5.929796|dts=83681280|dts_time=5.929796|duration=368640|duration_time=0.026122|size=418|pos=96327|flags=K__|data_hash=CRC32:34156e2e +packet|codec_type=audio|stream_index=0|pts=84049920|pts_time=5.955918|dts=84049920|dts_time=5.955918|duration=368640|duration_time=0.026122|size=418|pos=96745|flags=K__|data_hash=CRC32:7ba39adb +packet|codec_type=audio|stream_index=0|pts=84418560|pts_time=5.982041|dts=84418560|dts_time=5.982041|duration=368640|duration_time=0.026122|size=418|pos=97163|flags=K__|data_hash=CRC32:315662c5 +packet|codec_type=audio|stream_index=0|pts=84787200|pts_time=6.008163|dts=84787200|dts_time=6.008163|duration=368640|duration_time=0.026122|size=418|pos=97581|flags=K__|data_hash=CRC32:1d6c6500 +packet|codec_type=audio|stream_index=0|pts=85155840|pts_time=6.034286|dts=85155840|dts_time=6.034286|duration=368640|duration_time=0.026122|size=418|pos=97999|flags=K__|data_hash=CRC32:bc14dad3 +packet|codec_type=audio|stream_index=0|pts=85524480|pts_time=6.060408|dts=85524480|dts_time=6.060408|duration=368640|duration_time=0.026122|size=418|pos=98417|flags=K__|data_hash=CRC32:7719dddd +packet|codec_type=audio|stream_index=0|pts=85893120|pts_time=6.086531|dts=85893120|dts_time=6.086531|duration=368640|duration_time=0.026122|size=418|pos=98835|flags=K__|data_hash=CRC32:132ad1b8 +packet|codec_type=audio|stream_index=0|pts=86261760|pts_time=6.112653|dts=86261760|dts_time=6.112653|duration=368640|duration_time=0.026122|size=418|pos=99253|flags=K__|data_hash=CRC32:2867c127 +packet|codec_type=audio|stream_index=0|pts=86630400|pts_time=6.138776|dts=86630400|dts_time=6.138776|duration=368640|duration_time=0.026122|size=418|pos=99671|flags=K__|data_hash=CRC32:5af3ae3d +packet|codec_type=audio|stream_index=0|pts=86999040|pts_time=6.164898|dts=86999040|dts_time=6.164898|duration=368640|duration_time=0.026122|size=418|pos=100089|flags=K__|data_hash=CRC32:16d31800 +packet|codec_type=audio|stream_index=0|pts=87367680|pts_time=6.191020|dts=87367680|dts_time=6.191020|duration=368640|duration_time=0.026122|size=418|pos=100507|flags=K__|data_hash=CRC32:93a607e1 +packet|codec_type=audio|stream_index=0|pts=87736320|pts_time=6.217143|dts=87736320|dts_time=6.217143|duration=368640|duration_time=0.026122|size=418|pos=100925|flags=K__|data_hash=CRC32:db20f488 +packet|codec_type=audio|stream_index=0|pts=88104960|pts_time=6.243265|dts=88104960|dts_time=6.243265|duration=368640|duration_time=0.026122|size=418|pos=101343|flags=K__|data_hash=CRC32:8f3d4379 +packet|codec_type=audio|stream_index=0|pts=88473600|pts_time=6.269388|dts=88473600|dts_time=6.269388|duration=368640|duration_time=0.026122|size=418|pos=101761|flags=K__|data_hash=CRC32:837d0ec9 +packet|codec_type=audio|stream_index=0|pts=88842240|pts_time=6.295510|dts=88842240|dts_time=6.295510|duration=368640|duration_time=0.026122|size=418|pos=102179|flags=K__|data_hash=CRC32:22a48a51 +packet|codec_type=audio|stream_index=0|pts=89210880|pts_time=6.321633|dts=89210880|dts_time=6.321633|duration=368640|duration_time=0.026122|size=418|pos=102597|flags=K__|data_hash=CRC32:bca25918 +packet|codec_type=audio|stream_index=0|pts=89579520|pts_time=6.347755|dts=89579520|dts_time=6.347755|duration=368640|duration_time=0.026122|size=418|pos=103015|flags=K__|data_hash=CRC32:3db99977 +packet|codec_type=audio|stream_index=0|pts=89948160|pts_time=6.373878|dts=89948160|dts_time=6.373878|duration=368640|duration_time=0.026122|size=418|pos=103433|flags=K__|data_hash=CRC32:faa243b6 +packet|codec_type=audio|stream_index=0|pts=90316800|pts_time=6.400000|dts=90316800|dts_time=6.400000|duration=368640|duration_time=0.026122|size=417|pos=103851|flags=K__|data_hash=CRC32:f725a63e +packet|codec_type=audio|stream_index=0|pts=90685440|pts_time=6.426122|dts=90685440|dts_time=6.426122|duration=368640|duration_time=0.026122|size=418|pos=104268|flags=K__|data_hash=CRC32:76cf3f35 +packet|codec_type=audio|stream_index=0|pts=91054080|pts_time=6.452245|dts=91054080|dts_time=6.452245|duration=368640|duration_time=0.026122|size=418|pos=104686|flags=K__|data_hash=CRC32:2fa3029d +packet|codec_type=audio|stream_index=0|pts=91422720|pts_time=6.478367|dts=91422720|dts_time=6.478367|duration=368640|duration_time=0.026122|size=418|pos=105104|flags=K__|data_hash=CRC32:4a8deeec +packet|codec_type=audio|stream_index=0|pts=91791360|pts_time=6.504490|dts=91791360|dts_time=6.504490|duration=368640|duration_time=0.026122|size=418|pos=105522|flags=K__|data_hash=CRC32:6bb7f1f6 +packet|codec_type=audio|stream_index=0|pts=92160000|pts_time=6.530612|dts=92160000|dts_time=6.530612|duration=368640|duration_time=0.026122|size=418|pos=105940|flags=K__|data_hash=CRC32:e16d50d2 +packet|codec_type=audio|stream_index=0|pts=92528640|pts_time=6.556735|dts=92528640|dts_time=6.556735|duration=368640|duration_time=0.026122|size=418|pos=106358|flags=K__|data_hash=CRC32:b5347035 +packet|codec_type=audio|stream_index=0|pts=92897280|pts_time=6.582857|dts=92897280|dts_time=6.582857|duration=368640|duration_time=0.026122|size=418|pos=106776|flags=K__|data_hash=CRC32:7854e0d2 +packet|codec_type=audio|stream_index=0|pts=93265920|pts_time=6.608980|dts=93265920|dts_time=6.608980|duration=368640|duration_time=0.026122|size=418|pos=107194|flags=K__|data_hash=CRC32:695b58a9 +packet|codec_type=audio|stream_index=0|pts=93634560|pts_time=6.635102|dts=93634560|dts_time=6.635102|duration=368640|duration_time=0.026122|size=418|pos=107612|flags=K__|data_hash=CRC32:edf1b673 +packet|codec_type=audio|stream_index=0|pts=94003200|pts_time=6.661224|dts=94003200|dts_time=6.661224|duration=368640|duration_time=0.026122|size=418|pos=108030|flags=K__|data_hash=CRC32:46324bbb +packet|codec_type=audio|stream_index=0|pts=94371840|pts_time=6.687347|dts=94371840|dts_time=6.687347|duration=368640|duration_time=0.026122|size=418|pos=108448|flags=K__|data_hash=CRC32:e4f2bb26 +packet|codec_type=audio|stream_index=0|pts=94740480|pts_time=6.713469|dts=94740480|dts_time=6.713469|duration=368640|duration_time=0.026122|size=418|pos=108866|flags=K__|data_hash=CRC32:5db12b9c +packet|codec_type=audio|stream_index=0|pts=95109120|pts_time=6.739592|dts=95109120|dts_time=6.739592|duration=368640|duration_time=0.026122|size=418|pos=109284|flags=K__|data_hash=CRC32:36183b69 +packet|codec_type=audio|stream_index=0|pts=95477760|pts_time=6.765714|dts=95477760|dts_time=6.765714|duration=368640|duration_time=0.026122|size=418|pos=109702|flags=K__|data_hash=CRC32:baa2604d +packet|codec_type=audio|stream_index=0|pts=95846400|pts_time=6.791837|dts=95846400|dts_time=6.791837|duration=368640|duration_time=0.026122|size=418|pos=110120|flags=K__|data_hash=CRC32:5ed1c59a +packet|codec_type=audio|stream_index=0|pts=96215040|pts_time=6.817959|dts=96215040|dts_time=6.817959|duration=368640|duration_time=0.026122|size=418|pos=110538|flags=K__|data_hash=CRC32:dc54d5cd +packet|codec_type=audio|stream_index=0|pts=96583680|pts_time=6.844082|dts=96583680|dts_time=6.844082|duration=368640|duration_time=0.026122|size=418|pos=110956|flags=K__|data_hash=CRC32:0fbfd9a0 +packet|codec_type=audio|stream_index=0|pts=96952320|pts_time=6.870204|dts=96952320|dts_time=6.870204|duration=368640|duration_time=0.026122|size=418|pos=111374|flags=K__|data_hash=CRC32:bf3e1f53 +packet|codec_type=audio|stream_index=0|pts=97320960|pts_time=6.896327|dts=97320960|dts_time=6.896327|duration=368640|duration_time=0.026122|size=418|pos=111792|flags=K__|data_hash=CRC32:4ef81515 +packet|codec_type=audio|stream_index=0|pts=97689600|pts_time=6.922449|dts=97689600|dts_time=6.922449|duration=368640|duration_time=0.026122|size=418|pos=112210|flags=K__|data_hash=CRC32:576a9545 +packet|codec_type=audio|stream_index=0|pts=98058240|pts_time=6.948571|dts=98058240|dts_time=6.948571|duration=368640|duration_time=0.026122|size=418|pos=112628|flags=K__|data_hash=CRC32:522a71d5 +packet|codec_type=audio|stream_index=0|pts=98426880|pts_time=6.974694|dts=98426880|dts_time=6.974694|duration=368640|duration_time=0.026122|size=418|pos=113046|flags=K__|data_hash=CRC32:b15d9d3b +packet|codec_type=audio|stream_index=0|pts=98795520|pts_time=7.000816|dts=98795520|dts_time=7.000816|duration=368640|duration_time=0.026122|size=418|pos=113464|flags=K__|data_hash=CRC32:fd9937b8 +packet|codec_type=audio|stream_index=0|pts=99164160|pts_time=7.026939|dts=99164160|dts_time=7.026939|duration=368640|duration_time=0.026122|size=418|pos=113882|flags=K__|data_hash=CRC32:b9331702 +packet|codec_type=audio|stream_index=0|pts=99532800|pts_time=7.053061|dts=99532800|dts_time=7.053061|duration=368640|duration_time=0.026122|size=417|pos=114300|flags=K__|data_hash=CRC32:0e805c6d +packet|codec_type=audio|stream_index=0|pts=99901440|pts_time=7.079184|dts=99901440|dts_time=7.079184|duration=368640|duration_time=0.026122|size=418|pos=114717|flags=K__|data_hash=CRC32:b6f589c8 +packet|codec_type=audio|stream_index=0|pts=100270080|pts_time=7.105306|dts=100270080|dts_time=7.105306|duration=368640|duration_time=0.026122|size=418|pos=115135|flags=K__|data_hash=CRC32:87cfee38 +packet|codec_type=audio|stream_index=0|pts=100638720|pts_time=7.131429|dts=100638720|dts_time=7.131429|duration=368640|duration_time=0.026122|size=418|pos=115553|flags=K__|data_hash=CRC32:d90d4ebe +packet|codec_type=audio|stream_index=0|pts=101007360|pts_time=7.157551|dts=101007360|dts_time=7.157551|duration=368640|duration_time=0.026122|size=418|pos=115971|flags=K__|data_hash=CRC32:cf571193 +packet|codec_type=audio|stream_index=0|pts=101376000|pts_time=7.183673|dts=101376000|dts_time=7.183673|duration=368640|duration_time=0.026122|size=418|pos=116389|flags=K__|data_hash=CRC32:30d3b2d7 +packet|codec_type=audio|stream_index=0|pts=101744640|pts_time=7.209796|dts=101744640|dts_time=7.209796|duration=368640|duration_time=0.026122|size=418|pos=116807|flags=K__|data_hash=CRC32:94eff902 +packet|codec_type=audio|stream_index=0|pts=102113280|pts_time=7.235918|dts=102113280|dts_time=7.235918|duration=368640|duration_time=0.026122|size=418|pos=117225|flags=K__|data_hash=CRC32:6ed46b0c +packet|codec_type=audio|stream_index=0|pts=102481920|pts_time=7.262041|dts=102481920|dts_time=7.262041|duration=368640|duration_time=0.026122|size=418|pos=117643|flags=K__|data_hash=CRC32:ae9574bf +packet|codec_type=audio|stream_index=0|pts=102850560|pts_time=7.288163|dts=102850560|dts_time=7.288163|duration=368640|duration_time=0.026122|size=418|pos=118061|flags=K__|data_hash=CRC32:216621bb +packet|codec_type=audio|stream_index=0|pts=103219200|pts_time=7.314286|dts=103219200|dts_time=7.314286|duration=368640|duration_time=0.026122|size=418|pos=118479|flags=K__|data_hash=CRC32:be692b5a +packet|codec_type=audio|stream_index=0|pts=103587840|pts_time=7.340408|dts=103587840|dts_time=7.340408|duration=368640|duration_time=0.026122|size=418|pos=118897|flags=K__|data_hash=CRC32:76b6814a +packet|codec_type=audio|stream_index=0|pts=103956480|pts_time=7.366531|dts=103956480|dts_time=7.366531|duration=368640|duration_time=0.026122|size=418|pos=119315|flags=K__|data_hash=CRC32:60ac1531 +packet|codec_type=audio|stream_index=0|pts=104325120|pts_time=7.392653|dts=104325120|dts_time=7.392653|duration=368640|duration_time=0.026122|size=418|pos=119733|flags=K__|data_hash=CRC32:d9ac3b87 +packet|codec_type=audio|stream_index=0|pts=104693760|pts_time=7.418776|dts=104693760|dts_time=7.418776|duration=368640|duration_time=0.026122|size=418|pos=120151|flags=K__|data_hash=CRC32:6187bef7 +packet|codec_type=audio|stream_index=0|pts=105062400|pts_time=7.444898|dts=105062400|dts_time=7.444898|duration=368640|duration_time=0.026122|size=418|pos=120569|flags=K__|data_hash=CRC32:abb11d4e +packet|codec_type=audio|stream_index=0|pts=105431040|pts_time=7.471020|dts=105431040|dts_time=7.471020|duration=368640|duration_time=0.026122|size=418|pos=120987|flags=K__|data_hash=CRC32:21ff16ed +packet|codec_type=audio|stream_index=0|pts=105799680|pts_time=7.497143|dts=105799680|dts_time=7.497143|duration=368640|duration_time=0.026122|size=418|pos=121405|flags=K__|data_hash=CRC32:8b9d33e3 +packet|codec_type=audio|stream_index=0|pts=106168320|pts_time=7.523265|dts=106168320|dts_time=7.523265|duration=368640|duration_time=0.026122|size=418|pos=121823|flags=K__|data_hash=CRC32:9fdfecc3 +packet|codec_type=audio|stream_index=0|pts=106536960|pts_time=7.549388|dts=106536960|dts_time=7.549388|duration=368640|duration_time=0.026122|size=418|pos=122241|flags=K__|data_hash=CRC32:09b2eb8c +packet|codec_type=audio|stream_index=0|pts=106905600|pts_time=7.575510|dts=106905600|dts_time=7.575510|duration=368640|duration_time=0.026122|size=418|pos=122659|flags=K__|data_hash=CRC32:1157b18a +packet|codec_type=audio|stream_index=0|pts=107274240|pts_time=7.601633|dts=107274240|dts_time=7.601633|duration=368640|duration_time=0.026122|size=418|pos=123077|flags=K__|data_hash=CRC32:16d63271 +packet|codec_type=audio|stream_index=0|pts=107642880|pts_time=7.627755|dts=107642880|dts_time=7.627755|duration=368640|duration_time=0.026122|size=418|pos=123495|flags=K__|data_hash=CRC32:ff8cd868 +packet|codec_type=audio|stream_index=0|pts=108011520|pts_time=7.653878|dts=108011520|dts_time=7.653878|duration=368640|duration_time=0.026122|size=418|pos=123913|flags=K__|data_hash=CRC32:dcd4b34b +packet|codec_type=audio|stream_index=0|pts=108380160|pts_time=7.680000|dts=108380160|dts_time=7.680000|duration=368640|duration_time=0.026122|size=417|pos=124331|flags=K__|data_hash=CRC32:511a97cc +packet|codec_type=audio|stream_index=0|pts=108748800|pts_time=7.706122|dts=108748800|dts_time=7.706122|duration=368640|duration_time=0.026122|size=418|pos=124748|flags=K__|data_hash=CRC32:12f0449c +packet|codec_type=audio|stream_index=0|pts=109117440|pts_time=7.732245|dts=109117440|dts_time=7.732245|duration=368640|duration_time=0.026122|size=418|pos=125166|flags=K__|data_hash=CRC32:5af6bfcc +packet|codec_type=audio|stream_index=0|pts=109486080|pts_time=7.758367|dts=109486080|dts_time=7.758367|duration=368640|duration_time=0.026122|size=418|pos=125584|flags=K__|data_hash=CRC32:1cfa7e91 +packet|codec_type=audio|stream_index=0|pts=109854720|pts_time=7.784490|dts=109854720|dts_time=7.784490|duration=368640|duration_time=0.026122|size=418|pos=126002|flags=K__|data_hash=CRC32:d87857f2 +packet|codec_type=audio|stream_index=0|pts=110223360|pts_time=7.810612|dts=110223360|dts_time=7.810612|duration=368640|duration_time=0.026122|size=418|pos=126420|flags=K__|data_hash=CRC32:37cd9f06 +packet|codec_type=audio|stream_index=0|pts=110592000|pts_time=7.836735|dts=110592000|dts_time=7.836735|duration=368640|duration_time=0.026122|size=418|pos=126838|flags=K__|data_hash=CRC32:a3df2bf0 +packet|codec_type=audio|stream_index=0|pts=110960640|pts_time=7.862857|dts=110960640|dts_time=7.862857|duration=368640|duration_time=0.026122|size=418|pos=127256|flags=K__|data_hash=CRC32:814fa056 +packet|codec_type=audio|stream_index=0|pts=111329280|pts_time=7.888980|dts=111329280|dts_time=7.888980|duration=368640|duration_time=0.026122|size=418|pos=127674|flags=K__|data_hash=CRC32:6c87eadd +packet|codec_type=audio|stream_index=0|pts=111697920|pts_time=7.915102|dts=111697920|dts_time=7.915102|duration=368640|duration_time=0.026122|size=418|pos=128092|flags=K__|data_hash=CRC32:3b1623b4 +packet|codec_type=audio|stream_index=0|pts=112066560|pts_time=7.941224|dts=112066560|dts_time=7.941224|duration=368640|duration_time=0.026122|size=418|pos=128510|flags=K__|data_hash=CRC32:2282971a +packet|codec_type=audio|stream_index=0|pts=112435200|pts_time=7.967347|dts=112435200|dts_time=7.967347|duration=368640|duration_time=0.026122|size=418|pos=128928|flags=K__|data_hash=CRC32:e4c2f907 +packet|codec_type=audio|stream_index=0|pts=112803840|pts_time=7.993469|dts=112803840|dts_time=7.993469|duration=368640|duration_time=0.026122|size=418|pos=129346|flags=K__|data_hash=CRC32:0d494e7c +packet|codec_type=audio|stream_index=0|pts=113172480|pts_time=8.019592|dts=113172480|dts_time=8.019592|duration=368640|duration_time=0.026122|size=418|pos=129764|flags=K__|data_hash=CRC32:73683d3b +packet|codec_type=audio|stream_index=0|pts=113541120|pts_time=8.045714|dts=113541120|dts_time=8.045714|duration=368640|duration_time=0.026122|size=418|pos=130182|flags=K__|data_hash=CRC32:6a80ad3a +packet|codec_type=audio|stream_index=0|pts=113909760|pts_time=8.071837|dts=113909760|dts_time=8.071837|duration=368640|duration_time=0.026122|size=418|pos=130600|flags=K__|data_hash=CRC32:6d1ad253 +packet|codec_type=audio|stream_index=0|pts=114278400|pts_time=8.097959|dts=114278400|dts_time=8.097959|duration=368640|duration_time=0.026122|size=418|pos=131018|flags=K__|data_hash=CRC32:08fbdf2b +packet|codec_type=audio|stream_index=0|pts=114647040|pts_time=8.124082|dts=114647040|dts_time=8.124082|duration=368640|duration_time=0.026122|size=418|pos=131436|flags=K__|data_hash=CRC32:53280306 +packet|codec_type=audio|stream_index=0|pts=115015680|pts_time=8.150204|dts=115015680|dts_time=8.150204|duration=368640|duration_time=0.026122|size=418|pos=131854|flags=K__|data_hash=CRC32:0c8ac4d8 +packet|codec_type=audio|stream_index=0|pts=115384320|pts_time=8.176327|dts=115384320|dts_time=8.176327|duration=368640|duration_time=0.026122|size=418|pos=132272|flags=K__|data_hash=CRC32:b1d42b95 +packet|codec_type=audio|stream_index=0|pts=115752960|pts_time=8.202449|dts=115752960|dts_time=8.202449|duration=368640|duration_time=0.026122|size=418|pos=132690|flags=K__|data_hash=CRC32:e79c13f3 +packet|codec_type=audio|stream_index=0|pts=116121600|pts_time=8.228571|dts=116121600|dts_time=8.228571|duration=368640|duration_time=0.026122|size=418|pos=133108|flags=K__|data_hash=CRC32:b7a6b904 +packet|codec_type=audio|stream_index=0|pts=116490240|pts_time=8.254694|dts=116490240|dts_time=8.254694|duration=368640|duration_time=0.026122|size=418|pos=133526|flags=K__|data_hash=CRC32:e7437fe1 +packet|codec_type=audio|stream_index=0|pts=116858880|pts_time=8.280816|dts=116858880|dts_time=8.280816|duration=368640|duration_time=0.026122|size=418|pos=133944|flags=K__|data_hash=CRC32:ec10c2f1 +packet|codec_type=audio|stream_index=0|pts=117227520|pts_time=8.306939|dts=117227520|dts_time=8.306939|duration=368640|duration_time=0.026122|size=418|pos=134362|flags=K__|data_hash=CRC32:c85afe11 +packet|codec_type=audio|stream_index=0|pts=117596160|pts_time=8.333061|dts=117596160|dts_time=8.333061|duration=368640|duration_time=0.026122|size=417|pos=134780|flags=K__|data_hash=CRC32:86d78485 +packet|codec_type=audio|stream_index=0|pts=117964800|pts_time=8.359184|dts=117964800|dts_time=8.359184|duration=368640|duration_time=0.026122|size=418|pos=135197|flags=K__|data_hash=CRC32:38a01640 +packet|codec_type=audio|stream_index=0|pts=118333440|pts_time=8.385306|dts=118333440|dts_time=8.385306|duration=368640|duration_time=0.026122|size=418|pos=135615|flags=K__|data_hash=CRC32:fa047a2a +packet|codec_type=audio|stream_index=0|pts=118702080|pts_time=8.411429|dts=118702080|dts_time=8.411429|duration=368640|duration_time=0.026122|size=418|pos=136033|flags=K__|data_hash=CRC32:be363336 +packet|codec_type=audio|stream_index=0|pts=119070720|pts_time=8.437551|dts=119070720|dts_time=8.437551|duration=368640|duration_time=0.026122|size=418|pos=136451|flags=K__|data_hash=CRC32:107b9a48 +packet|codec_type=audio|stream_index=0|pts=119439360|pts_time=8.463673|dts=119439360|dts_time=8.463673|duration=368640|duration_time=0.026122|size=418|pos=136869|flags=K__|data_hash=CRC32:ec2d29b4 +packet|codec_type=audio|stream_index=0|pts=119808000|pts_time=8.489796|dts=119808000|dts_time=8.489796|duration=368640|duration_time=0.026122|size=418|pos=137287|flags=K__|data_hash=CRC32:5b4e1cd2 +packet|codec_type=audio|stream_index=0|pts=120176640|pts_time=8.515918|dts=120176640|dts_time=8.515918|duration=368640|duration_time=0.026122|size=418|pos=137705|flags=K__|data_hash=CRC32:3fdd2053 +packet|codec_type=audio|stream_index=0|pts=120545280|pts_time=8.542041|dts=120545280|dts_time=8.542041|duration=368640|duration_time=0.026122|size=418|pos=138123|flags=K__|data_hash=CRC32:a6205b07 +packet|codec_type=audio|stream_index=0|pts=120913920|pts_time=8.568163|dts=120913920|dts_time=8.568163|duration=368640|duration_time=0.026122|size=418|pos=138541|flags=K__|data_hash=CRC32:25820a59 +packet|codec_type=audio|stream_index=0|pts=121282560|pts_time=8.594286|dts=121282560|dts_time=8.594286|duration=368640|duration_time=0.026122|size=418|pos=138959|flags=K__|data_hash=CRC32:d7e4d24a +packet|codec_type=audio|stream_index=0|pts=121651200|pts_time=8.620408|dts=121651200|dts_time=8.620408|duration=368640|duration_time=0.026122|size=418|pos=139377|flags=K__|data_hash=CRC32:372d6c45 +packet|codec_type=audio|stream_index=0|pts=122019840|pts_time=8.646531|dts=122019840|dts_time=8.646531|duration=368640|duration_time=0.026122|size=418|pos=139795|flags=K__|data_hash=CRC32:b3d2534b +packet|codec_type=audio|stream_index=0|pts=122388480|pts_time=8.672653|dts=122388480|dts_time=8.672653|duration=368640|duration_time=0.026122|size=418|pos=140213|flags=K__|data_hash=CRC32:ec06331a +packet|codec_type=audio|stream_index=0|pts=122757120|pts_time=8.698776|dts=122757120|dts_time=8.698776|duration=368640|duration_time=0.026122|size=418|pos=140631|flags=K__|data_hash=CRC32:c1d73495 +packet|codec_type=audio|stream_index=0|pts=123125760|pts_time=8.724898|dts=123125760|dts_time=8.724898|duration=368640|duration_time=0.026122|size=418|pos=141049|flags=K__|data_hash=CRC32:cd3b07b4 +packet|codec_type=audio|stream_index=0|pts=123494400|pts_time=8.751020|dts=123494400|dts_time=8.751020|duration=368640|duration_time=0.026122|size=418|pos=141467|flags=K__|data_hash=CRC32:89d52d58 +packet|codec_type=audio|stream_index=0|pts=123863040|pts_time=8.777143|dts=123863040|dts_time=8.777143|duration=368640|duration_time=0.026122|size=418|pos=141885|flags=K__|data_hash=CRC32:4f6f794b +packet|codec_type=audio|stream_index=0|pts=124231680|pts_time=8.803265|dts=124231680|dts_time=8.803265|duration=368640|duration_time=0.026122|size=418|pos=142303|flags=K__|data_hash=CRC32:fffede19 +packet|codec_type=audio|stream_index=0|pts=124600320|pts_time=8.829388|dts=124600320|dts_time=8.829388|duration=368640|duration_time=0.026122|size=418|pos=142721|flags=K__|data_hash=CRC32:2567e5ee +packet|codec_type=audio|stream_index=0|pts=124968960|pts_time=8.855510|dts=124968960|dts_time=8.855510|duration=368640|duration_time=0.026122|size=418|pos=143139|flags=K__|data_hash=CRC32:e5a1e8c9 +packet|codec_type=audio|stream_index=0|pts=125337600|pts_time=8.881633|dts=125337600|dts_time=8.881633|duration=368640|duration_time=0.026122|size=418|pos=143557|flags=K__|data_hash=CRC32:90a53524 +packet|codec_type=audio|stream_index=0|pts=125706240|pts_time=8.907755|dts=125706240|dts_time=8.907755|duration=368640|duration_time=0.026122|size=418|pos=143975|flags=K__|data_hash=CRC32:dab534ad +packet|codec_type=audio|stream_index=0|pts=126074880|pts_time=8.933878|dts=126074880|dts_time=8.933878|duration=368640|duration_time=0.026122|size=418|pos=144393|flags=K__|data_hash=CRC32:80e2d601 +packet|codec_type=audio|stream_index=0|pts=126443520|pts_time=8.960000|dts=126443520|dts_time=8.960000|duration=368640|duration_time=0.026122|size=417|pos=144811|flags=K__|data_hash=CRC32:9e58315a +packet|codec_type=audio|stream_index=0|pts=126812160|pts_time=8.986122|dts=126812160|dts_time=8.986122|duration=368640|duration_time=0.026122|size=418|pos=145228|flags=K__|data_hash=CRC32:caf2a992 +packet|codec_type=audio|stream_index=0|pts=127180800|pts_time=9.012245|dts=127180800|dts_time=9.012245|duration=368640|duration_time=0.026122|size=418|pos=145646|flags=K__|data_hash=CRC32:b4416c55 +packet|codec_type=audio|stream_index=0|pts=127549440|pts_time=9.038367|dts=127549440|dts_time=9.038367|duration=368640|duration_time=0.026122|size=418|pos=146064|flags=K__|data_hash=CRC32:cf540122 +packet|codec_type=audio|stream_index=0|pts=127918080|pts_time=9.064490|dts=127918080|dts_time=9.064490|duration=368640|duration_time=0.026122|size=418|pos=146482|flags=K__|data_hash=CRC32:d2271324 +packet|codec_type=audio|stream_index=0|pts=128286720|pts_time=9.090612|dts=128286720|dts_time=9.090612|duration=368640|duration_time=0.026122|size=418|pos=146900|flags=K__|data_hash=CRC32:8d46cedb +packet|codec_type=audio|stream_index=0|pts=128655360|pts_time=9.116735|dts=128655360|dts_time=9.116735|duration=368640|duration_time=0.026122|size=418|pos=147318|flags=K__|data_hash=CRC32:98360373 +packet|codec_type=audio|stream_index=0|pts=129024000|pts_time=9.142857|dts=129024000|dts_time=9.142857|duration=368640|duration_time=0.026122|size=418|pos=147736|flags=K__|data_hash=CRC32:16a4d10e +packet|codec_type=audio|stream_index=0|pts=129392640|pts_time=9.168980|dts=129392640|dts_time=9.168980|duration=368640|duration_time=0.026122|size=418|pos=148154|flags=K__|data_hash=CRC32:96039cf1 +packet|codec_type=audio|stream_index=0|pts=129761280|pts_time=9.195102|dts=129761280|dts_time=9.195102|duration=368640|duration_time=0.026122|size=418|pos=148572|flags=K__|data_hash=CRC32:810c60a7 +packet|codec_type=audio|stream_index=0|pts=130129920|pts_time=9.221224|dts=130129920|dts_time=9.221224|duration=368640|duration_time=0.026122|size=418|pos=148990|flags=K__|data_hash=CRC32:965ad421 +packet|codec_type=audio|stream_index=0|pts=130498560|pts_time=9.247347|dts=130498560|dts_time=9.247347|duration=368640|duration_time=0.026122|size=418|pos=149408|flags=K__|data_hash=CRC32:ee0de130 +packet|codec_type=audio|stream_index=0|pts=130867200|pts_time=9.273469|dts=130867200|dts_time=9.273469|duration=368640|duration_time=0.026122|size=418|pos=149826|flags=K__|data_hash=CRC32:0b2e2883 +packet|codec_type=audio|stream_index=0|pts=131235840|pts_time=9.299592|dts=131235840|dts_time=9.299592|duration=368640|duration_time=0.026122|size=418|pos=150244|flags=K__|data_hash=CRC32:3f610265 +packet|codec_type=audio|stream_index=0|pts=131604480|pts_time=9.325714|dts=131604480|dts_time=9.325714|duration=368640|duration_time=0.026122|size=418|pos=150662|flags=K__|data_hash=CRC32:26cf9721 +packet|codec_type=audio|stream_index=0|pts=131973120|pts_time=9.351837|dts=131973120|dts_time=9.351837|duration=368640|duration_time=0.026122|size=418|pos=151080|flags=K__|data_hash=CRC32:eab74fb9 +packet|codec_type=audio|stream_index=0|pts=132341760|pts_time=9.377959|dts=132341760|dts_time=9.377959|duration=368640|duration_time=0.026122|size=418|pos=151498|flags=K__|data_hash=CRC32:60dea12f +packet|codec_type=audio|stream_index=0|pts=132710400|pts_time=9.404082|dts=132710400|dts_time=9.404082|duration=368640|duration_time=0.026122|size=418|pos=151916|flags=K__|data_hash=CRC32:54d23243 +packet|codec_type=audio|stream_index=0|pts=133079040|pts_time=9.430204|dts=133079040|dts_time=9.430204|duration=368640|duration_time=0.026122|size=418|pos=152334|flags=K__|data_hash=CRC32:6d507594 +packet|codec_type=audio|stream_index=0|pts=133447680|pts_time=9.456327|dts=133447680|dts_time=9.456327|duration=368640|duration_time=0.026122|size=418|pos=152752|flags=K__|data_hash=CRC32:a31b92c2 +packet|codec_type=audio|stream_index=0|pts=133816320|pts_time=9.482449|dts=133816320|dts_time=9.482449|duration=368640|duration_time=0.026122|size=418|pos=153170|flags=K__|data_hash=CRC32:04f064bd +packet|codec_type=audio|stream_index=0|pts=134184960|pts_time=9.508571|dts=134184960|dts_time=9.508571|duration=368640|duration_time=0.026122|size=418|pos=153588|flags=K__|data_hash=CRC32:234c71a8 +packet|codec_type=audio|stream_index=0|pts=134553600|pts_time=9.534694|dts=134553600|dts_time=9.534694|duration=368640|duration_time=0.026122|size=418|pos=154006|flags=K__|data_hash=CRC32:18fabbb7 +packet|codec_type=audio|stream_index=0|pts=134922240|pts_time=9.560816|dts=134922240|dts_time=9.560816|duration=368640|duration_time=0.026122|size=418|pos=154424|flags=K__|data_hash=CRC32:e372f113 +packet|codec_type=audio|stream_index=0|pts=135290880|pts_time=9.586939|dts=135290880|dts_time=9.586939|duration=368640|duration_time=0.026122|size=418|pos=154842|flags=K__|data_hash=CRC32:10352242 +packet|codec_type=audio|stream_index=0|pts=135659520|pts_time=9.613061|dts=135659520|dts_time=9.613061|duration=368640|duration_time=0.026122|size=417|pos=155260|flags=K__|data_hash=CRC32:571e601d +packet|codec_type=audio|stream_index=0|pts=136028160|pts_time=9.639184|dts=136028160|dts_time=9.639184|duration=368640|duration_time=0.026122|size=418|pos=155677|flags=K__|data_hash=CRC32:974376f0 +packet|codec_type=audio|stream_index=0|pts=136396800|pts_time=9.665306|dts=136396800|dts_time=9.665306|duration=368640|duration_time=0.026122|size=418|pos=156095|flags=K__|data_hash=CRC32:9893202f +packet|codec_type=audio|stream_index=0|pts=136765440|pts_time=9.691429|dts=136765440|dts_time=9.691429|duration=368640|duration_time=0.026122|size=418|pos=156513|flags=K__|data_hash=CRC32:57c930c0 +packet|codec_type=audio|stream_index=0|pts=137134080|pts_time=9.717551|dts=137134080|dts_time=9.717551|duration=368640|duration_time=0.026122|size=418|pos=156931|flags=K__|data_hash=CRC32:a8fc9e47 +packet|codec_type=audio|stream_index=0|pts=137502720|pts_time=9.743673|dts=137502720|dts_time=9.743673|duration=368640|duration_time=0.026122|size=418|pos=157349|flags=K__|data_hash=CRC32:a06f74d4 +packet|codec_type=audio|stream_index=0|pts=137871360|pts_time=9.769796|dts=137871360|dts_time=9.769796|duration=368640|duration_time=0.026122|size=418|pos=157767|flags=K__|data_hash=CRC32:adf88905 +packet|codec_type=audio|stream_index=0|pts=138240000|pts_time=9.795918|dts=138240000|dts_time=9.795918|duration=368640|duration_time=0.026122|size=418|pos=158185|flags=K__|data_hash=CRC32:8d415d99 +packet|codec_type=audio|stream_index=0|pts=138608640|pts_time=9.822041|dts=138608640|dts_time=9.822041|duration=368640|duration_time=0.026122|size=418|pos=158603|flags=K__|data_hash=CRC32:5df4c659 +packet|codec_type=audio|stream_index=0|pts=138977280|pts_time=9.848163|dts=138977280|dts_time=9.848163|duration=368640|duration_time=0.026122|size=418|pos=159021|flags=K__|data_hash=CRC32:c0aba593 +packet|codec_type=audio|stream_index=0|pts=139345920|pts_time=9.874286|dts=139345920|dts_time=9.874286|duration=368640|duration_time=0.026122|size=418|pos=159439|flags=K__|data_hash=CRC32:3d5f2342 +packet|codec_type=audio|stream_index=0|pts=139714560|pts_time=9.900408|dts=139714560|dts_time=9.900408|duration=368640|duration_time=0.026122|size=418|pos=159857|flags=K__|data_hash=CRC32:6835ff9d +packet|codec_type=audio|stream_index=0|pts=140083200|pts_time=9.926531|dts=140083200|dts_time=9.926531|duration=368640|duration_time=0.026122|size=418|pos=160275|flags=K__|data_hash=CRC32:de3061f3 +packet|codec_type=audio|stream_index=0|pts=140451840|pts_time=9.952653|dts=140451840|dts_time=9.952653|duration=368640|duration_time=0.026122|size=418|pos=160693|flags=K__|data_hash=CRC32:e28378d6 +packet|codec_type=audio|stream_index=0|pts=140820480|pts_time=9.978776|dts=140820480|dts_time=9.978776|duration=368640|duration_time=0.026122|size=418|pos=161111|flags=K__|data_hash=CRC32:1eabe555 +packet|codec_type=audio|stream_index=0|pts=141189120|pts_time=10.004898|dts=141189120|dts_time=10.004898|duration=368640|duration_time=0.026122|size=418|pos=161529|flags=K__|data_hash=CRC32:2bad508d +packet|codec_type=audio|stream_index=0|pts=141557760|pts_time=10.031020|dts=141557760|dts_time=10.031020|duration=368640|duration_time=0.026122|size=418|pos=161947|flags=K__|data_hash=CRC32:37fba9de +packet|codec_type=audio|stream_index=0|pts=141926400|pts_time=10.057143|dts=141926400|dts_time=10.057143|duration=368640|duration_time=0.026122|size=418|pos=162365|flags=K__|data_hash=CRC32:3244ecea +packet|codec_type=audio|stream_index=0|pts=142295040|pts_time=10.083265|dts=142295040|dts_time=10.083265|duration=368640|duration_time=0.026122|size=418|pos=162783|flags=K__|data_hash=CRC32:685781af +packet|codec_type=audio|stream_index=0|pts=142663680|pts_time=10.109388|dts=142663680|dts_time=10.109388|duration=368640|duration_time=0.026122|size=418|pos=163201|flags=K__|data_hash=CRC32:12d9eb56 +packet|codec_type=audio|stream_index=0|pts=143032320|pts_time=10.135510|dts=143032320|dts_time=10.135510|duration=368640|duration_time=0.026122|size=418|pos=163619|flags=K__|data_hash=CRC32:40f01793 +packet|codec_type=audio|stream_index=0|pts=143400960|pts_time=10.161633|dts=143400960|dts_time=10.161633|duration=368640|duration_time=0.026122|size=418|pos=164037|flags=K__|data_hash=CRC32:46a6b913 +packet|codec_type=audio|stream_index=0|pts=143769600|pts_time=10.187755|dts=143769600|dts_time=10.187755|duration=368640|duration_time=0.026122|size=418|pos=164455|flags=K__|data_hash=CRC32:a0923bf5 +packet|codec_type=audio|stream_index=0|pts=144138240|pts_time=10.213878|dts=144138240|dts_time=10.213878|duration=368640|duration_time=0.026122|size=418|pos=164873|flags=K__|data_hash=CRC32:85b32138 +packet|codec_type=audio|stream_index=0|pts=144506880|pts_time=10.240000|dts=144506880|dts_time=10.240000|duration=368640|duration_time=0.026122|size=417|pos=165291|flags=K__|data_hash=CRC32:6b70633a +packet|codec_type=audio|stream_index=0|pts=144875520|pts_time=10.266122|dts=144875520|dts_time=10.266122|duration=368640|duration_time=0.026122|size=418|pos=165708|flags=K__|data_hash=CRC32:bb86f9a2 +packet|codec_type=audio|stream_index=0|pts=145244160|pts_time=10.292245|dts=145244160|dts_time=10.292245|duration=368640|duration_time=0.026122|size=418|pos=166126|flags=K__|data_hash=CRC32:cae5a723 +packet|codec_type=audio|stream_index=0|pts=145612800|pts_time=10.318367|dts=145612800|dts_time=10.318367|duration=368640|duration_time=0.026122|size=418|pos=166544|flags=K__|data_hash=CRC32:86376f16 +packet|codec_type=audio|stream_index=0|pts=145981440|pts_time=10.344490|dts=145981440|dts_time=10.344490|duration=368640|duration_time=0.026122|size=418|pos=166962|flags=K__|data_hash=CRC32:02a40485 +packet|codec_type=audio|stream_index=0|pts=146350080|pts_time=10.370612|dts=146350080|dts_time=10.370612|duration=368640|duration_time=0.026122|size=418|pos=167380|flags=K__|data_hash=CRC32:36b3012d +packet|codec_type=audio|stream_index=0|pts=146718720|pts_time=10.396735|dts=146718720|dts_time=10.396735|duration=368640|duration_time=0.026122|size=418|pos=167798|flags=K__|data_hash=CRC32:5ee19ccd +packet|codec_type=audio|stream_index=0|pts=147087360|pts_time=10.422857|dts=147087360|dts_time=10.422857|duration=368640|duration_time=0.026122|size=418|pos=168216|flags=K__|data_hash=CRC32:c0152565 +packet|codec_type=audio|stream_index=0|pts=147456000|pts_time=10.448980|dts=147456000|dts_time=10.448980|duration=368640|duration_time=0.026122|size=418|pos=168634|flags=K__|data_hash=CRC32:19e503a0 +packet|codec_type=audio|stream_index=0|pts=147824640|pts_time=10.475102|dts=147824640|dts_time=10.475102|duration=368640|duration_time=0.026122|size=418|pos=169052|flags=K__|data_hash=CRC32:61cec178 +packet|codec_type=audio|stream_index=0|pts=148193280|pts_time=10.501224|dts=148193280|dts_time=10.501224|duration=368640|duration_time=0.026122|size=418|pos=169470|flags=K__|data_hash=CRC32:14781bf1 +packet|codec_type=audio|stream_index=0|pts=148561920|pts_time=10.527347|dts=148561920|dts_time=10.527347|duration=368640|duration_time=0.026122|size=418|pos=169888|flags=K__|data_hash=CRC32:a981e92c +packet|codec_type=audio|stream_index=0|pts=148930560|pts_time=10.553469|dts=148930560|dts_time=10.553469|duration=368640|duration_time=0.026122|size=418|pos=170306|flags=K__|data_hash=CRC32:771754a1 +packet|codec_type=audio|stream_index=0|pts=149299200|pts_time=10.579592|dts=149299200|dts_time=10.579592|duration=368640|duration_time=0.026122|size=418|pos=170724|flags=K__|data_hash=CRC32:d553fa66 +packet|codec_type=audio|stream_index=0|pts=149667840|pts_time=10.605714|dts=149667840|dts_time=10.605714|duration=368640|duration_time=0.026122|size=418|pos=171142|flags=K__|data_hash=CRC32:92289185 +packet|codec_type=audio|stream_index=0|pts=150036480|pts_time=10.631837|dts=150036480|dts_time=10.631837|duration=368640|duration_time=0.026122|size=418|pos=171560|flags=K__|data_hash=CRC32:f9c61381 +packet|codec_type=audio|stream_index=0|pts=150405120|pts_time=10.657959|dts=150405120|dts_time=10.657959|duration=368640|duration_time=0.026122|size=418|pos=171978|flags=K__|data_hash=CRC32:d68bf882 +packet|codec_type=audio|stream_index=0|pts=150773760|pts_time=10.684082|dts=150773760|dts_time=10.684082|duration=368640|duration_time=0.026122|size=418|pos=172396|flags=K__|data_hash=CRC32:a5155dee +packet|codec_type=audio|stream_index=0|pts=151142400|pts_time=10.710204|dts=151142400|dts_time=10.710204|duration=368640|duration_time=0.026122|size=418|pos=172814|flags=K__|data_hash=CRC32:98527928 +packet|codec_type=audio|stream_index=0|pts=151511040|pts_time=10.736327|dts=151511040|dts_time=10.736327|duration=368640|duration_time=0.026122|size=418|pos=173232|flags=K__|data_hash=CRC32:b4540586 +packet|codec_type=audio|stream_index=0|pts=151879680|pts_time=10.762449|dts=151879680|dts_time=10.762449|duration=368640|duration_time=0.026122|size=418|pos=173650|flags=K__|data_hash=CRC32:8ca5872b +packet|codec_type=audio|stream_index=0|pts=152248320|pts_time=10.788571|dts=152248320|dts_time=10.788571|duration=368640|duration_time=0.026122|size=418|pos=174068|flags=K__|data_hash=CRC32:b48241ad +packet|codec_type=audio|stream_index=0|pts=152616960|pts_time=10.814694|dts=152616960|dts_time=10.814694|duration=368640|duration_time=0.026122|size=418|pos=174486|flags=K__|data_hash=CRC32:87b45640 +packet|codec_type=audio|stream_index=0|pts=152985600|pts_time=10.840816|dts=152985600|dts_time=10.840816|duration=368640|duration_time=0.026122|size=418|pos=174904|flags=K__|data_hash=CRC32:7e4a7a0c +packet|codec_type=audio|stream_index=0|pts=153354240|pts_time=10.866939|dts=153354240|dts_time=10.866939|duration=368640|duration_time=0.026122|size=418|pos=175322|flags=K__|data_hash=CRC32:6027ce87 +packet|codec_type=audio|stream_index=0|pts=153722880|pts_time=10.893061|dts=153722880|dts_time=10.893061|duration=368640|duration_time=0.026122|size=417|pos=175740|flags=K__|data_hash=CRC32:0d68984f +packet|codec_type=audio|stream_index=0|pts=154091520|pts_time=10.919184|dts=154091520|dts_time=10.919184|duration=368640|duration_time=0.026122|size=418|pos=176157|flags=K__|data_hash=CRC32:614d8028 +packet|codec_type=audio|stream_index=0|pts=154460160|pts_time=10.945306|dts=154460160|dts_time=10.945306|duration=368640|duration_time=0.026122|size=418|pos=176575|flags=K__|data_hash=CRC32:14d0b66c +packet|codec_type=audio|stream_index=0|pts=154828800|pts_time=10.971429|dts=154828800|dts_time=10.971429|duration=368640|duration_time=0.026122|size=418|pos=176993|flags=K__|data_hash=CRC32:6a25430d +packet|codec_type=audio|stream_index=0|pts=155197440|pts_time=10.997551|dts=155197440|dts_time=10.997551|duration=368640|duration_time=0.026122|size=418|pos=177411|flags=K__|data_hash=CRC32:cb4a5803 +packet|codec_type=audio|stream_index=0|pts=155566080|pts_time=11.023673|dts=155566080|dts_time=11.023673|duration=368640|duration_time=0.026122|size=418|pos=177829|flags=K__|data_hash=CRC32:04d55594 +packet|codec_type=audio|stream_index=0|pts=155934720|pts_time=11.049796|dts=155934720|dts_time=11.049796|duration=368640|duration_time=0.026122|size=418|pos=178247|flags=K__|data_hash=CRC32:8c6be356 +packet|codec_type=audio|stream_index=0|pts=156303360|pts_time=11.075918|dts=156303360|dts_time=11.075918|duration=368640|duration_time=0.026122|size=418|pos=178665|flags=K__|data_hash=CRC32:cb291119 +packet|codec_type=audio|stream_index=0|pts=156672000|pts_time=11.102041|dts=156672000|dts_time=11.102041|duration=368640|duration_time=0.026122|size=418|pos=179083|flags=K__|data_hash=CRC32:eb228350 +packet|codec_type=audio|stream_index=0|pts=157040640|pts_time=11.128163|dts=157040640|dts_time=11.128163|duration=368640|duration_time=0.026122|size=418|pos=179501|flags=K__|data_hash=CRC32:c5337a0b +packet|codec_type=audio|stream_index=0|pts=157409280|pts_time=11.154286|dts=157409280|dts_time=11.154286|duration=368640|duration_time=0.026122|size=418|pos=179919|flags=K__|data_hash=CRC32:4cba189e +packet|codec_type=audio|stream_index=0|pts=157777920|pts_time=11.180408|dts=157777920|dts_time=11.180408|duration=368640|duration_time=0.026122|size=418|pos=180337|flags=K__|data_hash=CRC32:0418a931 +packet|codec_type=audio|stream_index=0|pts=158146560|pts_time=11.206531|dts=158146560|dts_time=11.206531|duration=368640|duration_time=0.026122|size=418|pos=180755|flags=K__|data_hash=CRC32:3d44908c +packet|codec_type=audio|stream_index=0|pts=158515200|pts_time=11.232653|dts=158515200|dts_time=11.232653|duration=368640|duration_time=0.026122|size=418|pos=181173|flags=K__|data_hash=CRC32:ed6d7efb +packet|codec_type=audio|stream_index=0|pts=158883840|pts_time=11.258776|dts=158883840|dts_time=11.258776|duration=368640|duration_time=0.026122|size=418|pos=181591|flags=K__|data_hash=CRC32:18ca7c0c +packet|codec_type=audio|stream_index=0|pts=159252480|pts_time=11.284898|dts=159252480|dts_time=11.284898|duration=368640|duration_time=0.026122|size=418|pos=182009|flags=K__|data_hash=CRC32:af52b87e +packet|codec_type=audio|stream_index=0|pts=159621120|pts_time=11.311020|dts=159621120|dts_time=11.311020|duration=368640|duration_time=0.026122|size=418|pos=182427|flags=K__|data_hash=CRC32:bc425aed +packet|codec_type=audio|stream_index=0|pts=159989760|pts_time=11.337143|dts=159989760|dts_time=11.337143|duration=368640|duration_time=0.026122|size=418|pos=182845|flags=K__|data_hash=CRC32:c3d28318 +packet|codec_type=audio|stream_index=0|pts=160358400|pts_time=11.363265|dts=160358400|dts_time=11.363265|duration=368640|duration_time=0.026122|size=418|pos=183263|flags=K__|data_hash=CRC32:e58a6767 +packet|codec_type=audio|stream_index=0|pts=160727040|pts_time=11.389388|dts=160727040|dts_time=11.389388|duration=368640|duration_time=0.026122|size=418|pos=183681|flags=K__|data_hash=CRC32:1ec96cd7 +packet|codec_type=audio|stream_index=0|pts=161095680|pts_time=11.415510|dts=161095680|dts_time=11.415510|duration=368640|duration_time=0.026122|size=418|pos=184099|flags=K__|data_hash=CRC32:f06e5745 +packet|codec_type=audio|stream_index=0|pts=161464320|pts_time=11.441633|dts=161464320|dts_time=11.441633|duration=368640|duration_time=0.026122|size=418|pos=184517|flags=K__|data_hash=CRC32:64601c5b +packet|codec_type=audio|stream_index=0|pts=161832960|pts_time=11.467755|dts=161832960|dts_time=11.467755|duration=368640|duration_time=0.026122|size=418|pos=184935|flags=K__|data_hash=CRC32:d9c27a78 +packet|codec_type=audio|stream_index=0|pts=162201600|pts_time=11.493878|dts=162201600|dts_time=11.493878|duration=368640|duration_time=0.026122|size=418|pos=185353|flags=K__|data_hash=CRC32:dbbff040 +packet|codec_type=audio|stream_index=0|pts=162570240|pts_time=11.520000|dts=162570240|dts_time=11.520000|duration=368640|duration_time=0.026122|size=417|pos=185771|flags=K__|data_hash=CRC32:c9f6c5a9 +packet|codec_type=audio|stream_index=0|pts=162938880|pts_time=11.546122|dts=162938880|dts_time=11.546122|duration=368640|duration_time=0.026122|size=418|pos=186188|flags=K__|data_hash=CRC32:ca280dd5 +packet|codec_type=audio|stream_index=0|pts=163307520|pts_time=11.572245|dts=163307520|dts_time=11.572245|duration=368640|duration_time=0.026122|size=418|pos=186606|flags=K__|data_hash=CRC32:3388d5a6 +packet|codec_type=audio|stream_index=0|pts=163676160|pts_time=11.598367|dts=163676160|dts_time=11.598367|duration=368640|duration_time=0.026122|size=418|pos=187024|flags=K__|data_hash=CRC32:3605bd56 +packet|codec_type=audio|stream_index=0|pts=164044800|pts_time=11.624490|dts=164044800|dts_time=11.624490|duration=368640|duration_time=0.026122|size=418|pos=187442|flags=K__|data_hash=CRC32:4a62eb9d +packet|codec_type=audio|stream_index=0|pts=164413440|pts_time=11.650612|dts=164413440|dts_time=11.650612|duration=368640|duration_time=0.026122|size=418|pos=187860|flags=K__|data_hash=CRC32:17d2c66e +packet|codec_type=audio|stream_index=0|pts=164782080|pts_time=11.676735|dts=164782080|dts_time=11.676735|duration=368640|duration_time=0.026122|size=418|pos=188278|flags=K__|data_hash=CRC32:ef7e72b5 +packet|codec_type=audio|stream_index=0|pts=165150720|pts_time=11.702857|dts=165150720|dts_time=11.702857|duration=368640|duration_time=0.026122|size=418|pos=188696|flags=K__|data_hash=CRC32:f7422408 +packet|codec_type=audio|stream_index=0|pts=165519360|pts_time=11.728980|dts=165519360|dts_time=11.728980|duration=368640|duration_time=0.026122|size=418|pos=189114|flags=K__|data_hash=CRC32:01512d42 +packet|codec_type=audio|stream_index=0|pts=165888000|pts_time=11.755102|dts=165888000|dts_time=11.755102|duration=368640|duration_time=0.026122|size=418|pos=189532|flags=K__|data_hash=CRC32:ec4ae9e0 +packet|codec_type=audio|stream_index=0|pts=166256640|pts_time=11.781224|dts=166256640|dts_time=11.781224|duration=368640|duration_time=0.026122|size=418|pos=189950|flags=K__|data_hash=CRC32:7f2ce39f +packet|codec_type=audio|stream_index=0|pts=166625280|pts_time=11.807347|dts=166625280|dts_time=11.807347|duration=368640|duration_time=0.026122|size=418|pos=190368|flags=K__|data_hash=CRC32:3abb4dc0 +packet|codec_type=audio|stream_index=0|pts=166993920|pts_time=11.833469|dts=166993920|dts_time=11.833469|duration=368640|duration_time=0.026122|size=418|pos=190786|flags=K__|data_hash=CRC32:06fdee7a +packet|codec_type=audio|stream_index=0|pts=167362560|pts_time=11.859592|dts=167362560|dts_time=11.859592|duration=368640|duration_time=0.026122|size=418|pos=191204|flags=K__|data_hash=CRC32:bfaed869 +packet|codec_type=audio|stream_index=0|pts=167731200|pts_time=11.885714|dts=167731200|dts_time=11.885714|duration=368640|duration_time=0.026122|size=418|pos=191622|flags=K__|data_hash=CRC32:a6762b1a +packet|codec_type=audio|stream_index=0|pts=168099840|pts_time=11.911837|dts=168099840|dts_time=11.911837|duration=368640|duration_time=0.026122|size=418|pos=192040|flags=K__|data_hash=CRC32:156bf7e4 +packet|codec_type=audio|stream_index=0|pts=168468480|pts_time=11.937959|dts=168468480|dts_time=11.937959|duration=368640|duration_time=0.026122|size=418|pos=192458|flags=K__|data_hash=CRC32:4cfaf03d +packet|codec_type=audio|stream_index=0|pts=168837120|pts_time=11.964082|dts=168837120|dts_time=11.964082|duration=368640|duration_time=0.026122|size=418|pos=192876|flags=K__|data_hash=CRC32:24cadb2b +packet|codec_type=audio|stream_index=0|pts=169205760|pts_time=11.990204|dts=169205760|dts_time=11.990204|duration=368640|duration_time=0.026122|size=418|pos=193294|flags=K__|data_hash=CRC32:9bba25cb +packet|codec_type=audio|stream_index=0|pts=169574400|pts_time=12.016327|dts=169574400|dts_time=12.016327|duration=368640|duration_time=0.026122|size=418|pos=193712|flags=K__|data_hash=CRC32:a6192bb5 +packet|codec_type=audio|stream_index=0|pts=169943040|pts_time=12.042449|dts=169943040|dts_time=12.042449|duration=368640|duration_time=0.026122|size=418|pos=194130|flags=K__|data_hash=CRC32:c06a11b2 +packet|codec_type=audio|stream_index=0|pts=170311680|pts_time=12.068571|dts=170311680|dts_time=12.068571|duration=368640|duration_time=0.026122|size=418|pos=194548|flags=K__|data_hash=CRC32:cd083930 +packet|codec_type=audio|stream_index=0|pts=170680320|pts_time=12.094694|dts=170680320|dts_time=12.094694|duration=368640|duration_time=0.026122|size=418|pos=194966|flags=K__|data_hash=CRC32:02e92b19 +packet|codec_type=audio|stream_index=0|pts=171048960|pts_time=12.120816|dts=171048960|dts_time=12.120816|duration=368640|duration_time=0.026122|size=418|pos=195384|flags=K__|data_hash=CRC32:4c63b84e +packet|codec_type=audio|stream_index=0|pts=171417600|pts_time=12.146939|dts=171417600|dts_time=12.146939|duration=368640|duration_time=0.026122|size=418|pos=195802|flags=K__|data_hash=CRC32:8e93e537 +packet|codec_type=audio|stream_index=0|pts=171786240|pts_time=12.173061|dts=171786240|dts_time=12.173061|duration=368640|duration_time=0.026122|size=417|pos=196220|flags=K__|data_hash=CRC32:9a9da365 +packet|codec_type=audio|stream_index=0|pts=172154880|pts_time=12.199184|dts=172154880|dts_time=12.199184|duration=368640|duration_time=0.026122|size=418|pos=196637|flags=K__|data_hash=CRC32:3d6cfb68 +packet|codec_type=audio|stream_index=0|pts=172523520|pts_time=12.225306|dts=172523520|dts_time=12.225306|duration=368640|duration_time=0.026122|size=418|pos=197055|flags=K__|data_hash=CRC32:82a3d445 +packet|codec_type=audio|stream_index=0|pts=172892160|pts_time=12.251429|dts=172892160|dts_time=12.251429|duration=368640|duration_time=0.026122|size=418|pos=197473|flags=K__|data_hash=CRC32:186d2c93 +packet|codec_type=audio|stream_index=0|pts=173260800|pts_time=12.277551|dts=173260800|dts_time=12.277551|duration=368640|duration_time=0.026122|size=418|pos=197891|flags=K__|data_hash=CRC32:d7836980 +packet|codec_type=audio|stream_index=0|pts=173629440|pts_time=12.303673|dts=173629440|dts_time=12.303673|duration=368640|duration_time=0.026122|size=418|pos=198309|flags=K__|data_hash=CRC32:7660396f +packet|codec_type=audio|stream_index=0|pts=173998080|pts_time=12.329796|dts=173998080|dts_time=12.329796|duration=368640|duration_time=0.026122|size=418|pos=198727|flags=K__|data_hash=CRC32:382b6366 +packet|codec_type=audio|stream_index=0|pts=174366720|pts_time=12.355918|dts=174366720|dts_time=12.355918|duration=368640|duration_time=0.026122|size=418|pos=199145|flags=K__|data_hash=CRC32:e85af773 +packet|codec_type=audio|stream_index=0|pts=174735360|pts_time=12.382041|dts=174735360|dts_time=12.382041|duration=368640|duration_time=0.026122|size=418|pos=199563|flags=K__|data_hash=CRC32:90dce600 +packet|codec_type=audio|stream_index=0|pts=175104000|pts_time=12.408163|dts=175104000|dts_time=12.408163|duration=368640|duration_time=0.026122|size=418|pos=199981|flags=K__|data_hash=CRC32:51048306 +packet|codec_type=audio|stream_index=0|pts=175472640|pts_time=12.434286|dts=175472640|dts_time=12.434286|duration=368640|duration_time=0.026122|size=418|pos=200399|flags=K__|data_hash=CRC32:8fc72574 +packet|codec_type=audio|stream_index=0|pts=175841280|pts_time=12.460408|dts=175841280|dts_time=12.460408|duration=368640|duration_time=0.026122|size=418|pos=200817|flags=K__|data_hash=CRC32:0c2fdbc9 +packet|codec_type=audio|stream_index=0|pts=176209920|pts_time=12.486531|dts=176209920|dts_time=12.486531|duration=368640|duration_time=0.026122|size=418|pos=201235|flags=K__|data_hash=CRC32:c624821f +packet|codec_type=audio|stream_index=0|pts=176578560|pts_time=12.512653|dts=176578560|dts_time=12.512653|duration=368640|duration_time=0.026122|size=418|pos=201653|flags=K__|data_hash=CRC32:122a97b1 +packet|codec_type=audio|stream_index=0|pts=176947200|pts_time=12.538776|dts=176947200|dts_time=12.538776|duration=368640|duration_time=0.026122|size=418|pos=202071|flags=K__|data_hash=CRC32:70034867 +packet|codec_type=audio|stream_index=0|pts=177315840|pts_time=12.564898|dts=177315840|dts_time=12.564898|duration=368640|duration_time=0.026122|size=418|pos=202489|flags=K__|data_hash=CRC32:23f7ff55 +packet|codec_type=audio|stream_index=0|pts=177684480|pts_time=12.591020|dts=177684480|dts_time=12.591020|duration=368640|duration_time=0.026122|size=418|pos=202907|flags=K__|data_hash=CRC32:30502042 +packet|codec_type=audio|stream_index=0|pts=178053120|pts_time=12.617143|dts=178053120|dts_time=12.617143|duration=368640|duration_time=0.026122|size=418|pos=203325|flags=K__|data_hash=CRC32:c4fc3556 +packet|codec_type=audio|stream_index=0|pts=178421760|pts_time=12.643265|dts=178421760|dts_time=12.643265|duration=368640|duration_time=0.026122|size=418|pos=203743|flags=K__|data_hash=CRC32:93e85444 +packet|codec_type=audio|stream_index=0|pts=178790400|pts_time=12.669388|dts=178790400|dts_time=12.669388|duration=368640|duration_time=0.026122|size=418|pos=204161|flags=K__|data_hash=CRC32:7cd8422c +packet|codec_type=audio|stream_index=0|pts=179159040|pts_time=12.695510|dts=179159040|dts_time=12.695510|duration=368640|duration_time=0.026122|size=418|pos=204579|flags=K__|data_hash=CRC32:b4f0ac22 +packet|codec_type=audio|stream_index=0|pts=179527680|pts_time=12.721633|dts=179527680|dts_time=12.721633|duration=368640|duration_time=0.026122|size=418|pos=204997|flags=K__|data_hash=CRC32:767c9538 +packet|codec_type=audio|stream_index=0|pts=179896320|pts_time=12.747755|dts=179896320|dts_time=12.747755|duration=368640|duration_time=0.026122|size=418|pos=205415|flags=K__|data_hash=CRC32:dc526929 +packet|codec_type=audio|stream_index=0|pts=180264960|pts_time=12.773878|dts=180264960|dts_time=12.773878|duration=368640|duration_time=0.026122|size=418|pos=205833|flags=K__|data_hash=CRC32:8b581282 +packet|codec_type=audio|stream_index=0|pts=180633600|pts_time=12.800000|dts=180633600|dts_time=12.800000|duration=368640|duration_time=0.026122|size=417|pos=206251|flags=K__|data_hash=CRC32:3c289703 +packet|codec_type=audio|stream_index=0|pts=181002240|pts_time=12.826122|dts=181002240|dts_time=12.826122|duration=368640|duration_time=0.026122|size=418|pos=206668|flags=K__|data_hash=CRC32:97ad0eb3 +packet|codec_type=audio|stream_index=0|pts=181370880|pts_time=12.852245|dts=181370880|dts_time=12.852245|duration=368640|duration_time=0.026122|size=418|pos=207086|flags=K__|data_hash=CRC32:faf9c1b5 +packet|codec_type=audio|stream_index=0|pts=181739520|pts_time=12.878367|dts=181739520|dts_time=12.878367|duration=368640|duration_time=0.026122|size=418|pos=207504|flags=K__|data_hash=CRC32:8f7c216a +packet|codec_type=audio|stream_index=0|pts=182108160|pts_time=12.904490|dts=182108160|dts_time=12.904490|duration=368640|duration_time=0.026122|size=418|pos=207922|flags=K__|data_hash=CRC32:2cb8f508 +packet|codec_type=audio|stream_index=0|pts=182476800|pts_time=12.930612|dts=182476800|dts_time=12.930612|duration=368640|duration_time=0.026122|size=418|pos=208340|flags=K__|data_hash=CRC32:0e9ca434 +packet|codec_type=audio|stream_index=0|pts=182845440|pts_time=12.956735|dts=182845440|dts_time=12.956735|duration=368640|duration_time=0.026122|size=418|pos=208758|flags=K__|data_hash=CRC32:ce807881 +packet|codec_type=audio|stream_index=0|pts=183214080|pts_time=12.982857|dts=183214080|dts_time=12.982857|duration=368640|duration_time=0.026122|size=418|pos=209176|flags=K__|data_hash=CRC32:0f2d056d +packet|codec_type=audio|stream_index=0|pts=183582720|pts_time=13.008980|dts=183582720|dts_time=13.008980|duration=368640|duration_time=0.026122|size=418|pos=209594|flags=K__|data_hash=CRC32:34f82e70 +packet|codec_type=audio|stream_index=0|pts=183951360|pts_time=13.035102|dts=183951360|dts_time=13.035102|duration=368640|duration_time=0.026122|size=418|pos=210012|flags=K__|data_hash=CRC32:93986f39 +packet|codec_type=audio|stream_index=0|pts=184320000|pts_time=13.061224|dts=184320000|dts_time=13.061224|duration=368640|duration_time=0.026122|size=418|pos=210430|flags=K__|data_hash=CRC32:057d018c +packet|codec_type=audio|stream_index=0|pts=184688640|pts_time=13.087347|dts=184688640|dts_time=13.087347|duration=368640|duration_time=0.026122|size=418|pos=210848|flags=K__|data_hash=CRC32:20288d86 +packet|codec_type=audio|stream_index=0|pts=185057280|pts_time=13.113469|dts=185057280|dts_time=13.113469|duration=368640|duration_time=0.026122|size=418|pos=211266|flags=K__|data_hash=CRC32:2054d963 +packet|codec_type=audio|stream_index=0|pts=185425920|pts_time=13.139592|dts=185425920|dts_time=13.139592|duration=368640|duration_time=0.026122|size=418|pos=211684|flags=K__|data_hash=CRC32:51451bd5 +packet|codec_type=audio|stream_index=0|pts=185794560|pts_time=13.165714|dts=185794560|dts_time=13.165714|duration=368640|duration_time=0.026122|size=418|pos=212102|flags=K__|data_hash=CRC32:40180197 +packet|codec_type=audio|stream_index=0|pts=186163200|pts_time=13.191837|dts=186163200|dts_time=13.191837|duration=368640|duration_time=0.026122|size=418|pos=212520|flags=K__|data_hash=CRC32:66cdd080 +packet|codec_type=audio|stream_index=0|pts=186531840|pts_time=13.217959|dts=186531840|dts_time=13.217959|duration=368640|duration_time=0.026122|size=418|pos=212938|flags=K__|data_hash=CRC32:03eb571f +packet|codec_type=audio|stream_index=0|pts=186900480|pts_time=13.244082|dts=186900480|dts_time=13.244082|duration=368640|duration_time=0.026122|size=418|pos=213356|flags=K__|data_hash=CRC32:88515140 +packet|codec_type=audio|stream_index=0|pts=187269120|pts_time=13.270204|dts=187269120|dts_time=13.270204|duration=368640|duration_time=0.026122|size=418|pos=213774|flags=K__|data_hash=CRC32:b82428b6 +packet|codec_type=audio|stream_index=0|pts=187637760|pts_time=13.296327|dts=187637760|dts_time=13.296327|duration=368640|duration_time=0.026122|size=418|pos=214192|flags=K__|data_hash=CRC32:43d07d2b +packet|codec_type=audio|stream_index=0|pts=188006400|pts_time=13.322449|dts=188006400|dts_time=13.322449|duration=368640|duration_time=0.026122|size=418|pos=214610|flags=K__|data_hash=CRC32:458c2504 +packet|codec_type=audio|stream_index=0|pts=188375040|pts_time=13.348571|dts=188375040|dts_time=13.348571|duration=368640|duration_time=0.026122|size=418|pos=215028|flags=K__|data_hash=CRC32:efa75088 +packet|codec_type=audio|stream_index=0|pts=188743680|pts_time=13.374694|dts=188743680|dts_time=13.374694|duration=368640|duration_time=0.026122|size=418|pos=215446|flags=K__|data_hash=CRC32:781209a4 +packet|codec_type=audio|stream_index=0|pts=189112320|pts_time=13.400816|dts=189112320|dts_time=13.400816|duration=368640|duration_time=0.026122|size=418|pos=215864|flags=K__|data_hash=CRC32:c09324be +packet|codec_type=audio|stream_index=0|pts=189480960|pts_time=13.426939|dts=189480960|dts_time=13.426939|duration=368640|duration_time=0.026122|size=418|pos=216282|flags=K__|data_hash=CRC32:b4b9932d +packet|codec_type=audio|stream_index=0|pts=189849600|pts_time=13.453061|dts=189849600|dts_time=13.453061|duration=368640|duration_time=0.026122|size=417|pos=216700|flags=K__|data_hash=CRC32:da830315 +packet|codec_type=audio|stream_index=0|pts=190218240|pts_time=13.479184|dts=190218240|dts_time=13.479184|duration=368640|duration_time=0.026122|size=418|pos=217117|flags=K__|data_hash=CRC32:66202e4f +packet|codec_type=audio|stream_index=0|pts=190586880|pts_time=13.505306|dts=190586880|dts_time=13.505306|duration=368640|duration_time=0.026122|size=418|pos=217535|flags=K__|data_hash=CRC32:2e237c5c +packet|codec_type=audio|stream_index=0|pts=190955520|pts_time=13.531429|dts=190955520|dts_time=13.531429|duration=368640|duration_time=0.026122|size=418|pos=217953|flags=K__|data_hash=CRC32:5764d408 +packet|codec_type=audio|stream_index=0|pts=191324160|pts_time=13.557551|dts=191324160|dts_time=13.557551|duration=368640|duration_time=0.026122|size=418|pos=218371|flags=K__|data_hash=CRC32:35c3a585 +packet|codec_type=audio|stream_index=0|pts=191692800|pts_time=13.583673|dts=191692800|dts_time=13.583673|duration=368640|duration_time=0.026122|size=418|pos=218789|flags=K__|data_hash=CRC32:78fe7986 +packet|codec_type=audio|stream_index=0|pts=192061440|pts_time=13.609796|dts=192061440|dts_time=13.609796|duration=368640|duration_time=0.026122|size=418|pos=219207|flags=K__|data_hash=CRC32:9f375cbe +packet|codec_type=audio|stream_index=0|pts=192430080|pts_time=13.635918|dts=192430080|dts_time=13.635918|duration=368640|duration_time=0.026122|size=418|pos=219625|flags=K__|data_hash=CRC32:491852fd +packet|codec_type=audio|stream_index=0|pts=192798720|pts_time=13.662041|dts=192798720|dts_time=13.662041|duration=368640|duration_time=0.026122|size=418|pos=220043|flags=K__|data_hash=CRC32:4f831db2 +packet|codec_type=audio|stream_index=0|pts=193167360|pts_time=13.688163|dts=193167360|dts_time=13.688163|duration=368640|duration_time=0.026122|size=418|pos=220461|flags=K__|data_hash=CRC32:030e4b07 +packet|codec_type=audio|stream_index=0|pts=193536000|pts_time=13.714286|dts=193536000|dts_time=13.714286|duration=368640|duration_time=0.026122|size=418|pos=220879|flags=K__|data_hash=CRC32:098ea741 +packet|codec_type=audio|stream_index=0|pts=193904640|pts_time=13.740408|dts=193904640|dts_time=13.740408|duration=368640|duration_time=0.026122|size=418|pos=221297|flags=K__|data_hash=CRC32:7ad88654 +packet|codec_type=audio|stream_index=0|pts=194273280|pts_time=13.766531|dts=194273280|dts_time=13.766531|duration=368640|duration_time=0.026122|size=418|pos=221715|flags=K__|data_hash=CRC32:d88ccfac +packet|codec_type=audio|stream_index=0|pts=194641920|pts_time=13.792653|dts=194641920|dts_time=13.792653|duration=368640|duration_time=0.026122|size=418|pos=222133|flags=K__|data_hash=CRC32:f22666d1 +packet|codec_type=audio|stream_index=0|pts=195010560|pts_time=13.818776|dts=195010560|dts_time=13.818776|duration=368640|duration_time=0.026122|size=418|pos=222551|flags=K__|data_hash=CRC32:d249bf1c +packet|codec_type=audio|stream_index=0|pts=195379200|pts_time=13.844898|dts=195379200|dts_time=13.844898|duration=368640|duration_time=0.026122|size=418|pos=222969|flags=K__|data_hash=CRC32:98e88198 +packet|codec_type=audio|stream_index=0|pts=195747840|pts_time=13.871020|dts=195747840|dts_time=13.871020|duration=368640|duration_time=0.026122|size=418|pos=223387|flags=K__|data_hash=CRC32:8a9fc4b4 +packet|codec_type=audio|stream_index=0|pts=196116480|pts_time=13.897143|dts=196116480|dts_time=13.897143|duration=368640|duration_time=0.026122|size=418|pos=223805|flags=K__|data_hash=CRC32:e0835e74 +packet|codec_type=audio|stream_index=0|pts=196485120|pts_time=13.923265|dts=196485120|dts_time=13.923265|duration=368640|duration_time=0.026122|size=418|pos=224223|flags=K__|data_hash=CRC32:08c1071f +packet|codec_type=audio|stream_index=0|pts=196853760|pts_time=13.949388|dts=196853760|dts_time=13.949388|duration=368640|duration_time=0.026122|size=418|pos=224641|flags=K__|data_hash=CRC32:ca5a3aaa +packet|codec_type=audio|stream_index=0|pts=197222400|pts_time=13.975510|dts=197222400|dts_time=13.975510|duration=368640|duration_time=0.026122|size=418|pos=225059|flags=K__|data_hash=CRC32:f789d2b3 +packet|codec_type=audio|stream_index=0|pts=197591040|pts_time=14.001633|dts=197591040|dts_time=14.001633|duration=368640|duration_time=0.026122|size=418|pos=225477|flags=K__|data_hash=CRC32:7bc285ed +packet|codec_type=audio|stream_index=0|pts=197959680|pts_time=14.027755|dts=197959680|dts_time=14.027755|duration=368640|duration_time=0.026122|size=418|pos=225895|flags=K__|data_hash=CRC32:6061a821 +packet|codec_type=audio|stream_index=0|pts=198328320|pts_time=14.053878|dts=198328320|dts_time=14.053878|duration=368640|duration_time=0.026122|size=418|pos=226313|flags=K__|data_hash=CRC32:14367df4 +packet|codec_type=audio|stream_index=0|pts=198696960|pts_time=14.080000|dts=198696960|dts_time=14.080000|duration=368640|duration_time=0.026122|size=417|pos=226731|flags=K__|data_hash=CRC32:f3140a6b +packet|codec_type=audio|stream_index=0|pts=199065600|pts_time=14.106122|dts=199065600|dts_time=14.106122|duration=368640|duration_time=0.026122|size=418|pos=227148|flags=K__|data_hash=CRC32:ebf07925 +packet|codec_type=audio|stream_index=0|pts=199434240|pts_time=14.132245|dts=199434240|dts_time=14.132245|duration=368640|duration_time=0.026122|size=418|pos=227566|flags=K__|data_hash=CRC32:4f8cde59 +packet|codec_type=audio|stream_index=0|pts=199802880|pts_time=14.158367|dts=199802880|dts_time=14.158367|duration=368640|duration_time=0.026122|size=418|pos=227984|flags=K__|data_hash=CRC32:4467b601 +packet|codec_type=audio|stream_index=0|pts=200171520|pts_time=14.184490|dts=200171520|dts_time=14.184490|duration=368640|duration_time=0.026122|size=418|pos=228402|flags=K__|data_hash=CRC32:f6ae7ed4 +packet|codec_type=audio|stream_index=0|pts=200540160|pts_time=14.210612|dts=200540160|dts_time=14.210612|duration=368640|duration_time=0.026122|size=418|pos=228820|flags=K__|data_hash=CRC32:5cb30836 +packet|codec_type=audio|stream_index=0|pts=200908800|pts_time=14.236735|dts=200908800|dts_time=14.236735|duration=368640|duration_time=0.026122|size=418|pos=229238|flags=K__|data_hash=CRC32:21b70421 +packet|codec_type=audio|stream_index=0|pts=201277440|pts_time=14.262857|dts=201277440|dts_time=14.262857|duration=368640|duration_time=0.026122|size=418|pos=229656|flags=K__|data_hash=CRC32:3bcafdd7 +packet|codec_type=audio|stream_index=0|pts=201646080|pts_time=14.288980|dts=201646080|dts_time=14.288980|duration=368640|duration_time=0.026122|size=418|pos=230074|flags=K__|data_hash=CRC32:76edd678 +packet|codec_type=audio|stream_index=0|pts=202014720|pts_time=14.315102|dts=202014720|dts_time=14.315102|duration=368640|duration_time=0.026122|size=418|pos=230492|flags=K__|data_hash=CRC32:0999fa0b +packet|codec_type=audio|stream_index=0|pts=202383360|pts_time=14.341224|dts=202383360|dts_time=14.341224|duration=368640|duration_time=0.026122|size=418|pos=230910|flags=K__|data_hash=CRC32:227a3da5 +packet|codec_type=audio|stream_index=0|pts=202752000|pts_time=14.367347|dts=202752000|dts_time=14.367347|duration=368640|duration_time=0.026122|size=418|pos=231328|flags=K__|data_hash=CRC32:0068cd57 +packet|codec_type=audio|stream_index=0|pts=203120640|pts_time=14.393469|dts=203120640|dts_time=14.393469|duration=368640|duration_time=0.026122|size=418|pos=231746|flags=K__|data_hash=CRC32:70f8a1dc +packet|codec_type=audio|stream_index=0|pts=203489280|pts_time=14.419592|dts=203489280|dts_time=14.419592|duration=368640|duration_time=0.026122|size=418|pos=232164|flags=K__|data_hash=CRC32:c19072eb +packet|codec_type=audio|stream_index=0|pts=203857920|pts_time=14.445714|dts=203857920|dts_time=14.445714|duration=368640|duration_time=0.026122|size=418|pos=232582|flags=K__|data_hash=CRC32:f0461d09 +packet|codec_type=audio|stream_index=0|pts=204226560|pts_time=14.471837|dts=204226560|dts_time=14.471837|duration=368640|duration_time=0.026122|size=418|pos=233000|flags=K__|data_hash=CRC32:c8fa8555 +packet|codec_type=audio|stream_index=0|pts=204595200|pts_time=14.497959|dts=204595200|dts_time=14.497959|duration=368640|duration_time=0.026122|size=418|pos=233418|flags=K__|data_hash=CRC32:901f5bfb +packet|codec_type=audio|stream_index=0|pts=204963840|pts_time=14.524082|dts=204963840|dts_time=14.524082|duration=368640|duration_time=0.026122|size=418|pos=233836|flags=K__|data_hash=CRC32:91d0ab8c +packet|codec_type=audio|stream_index=0|pts=205332480|pts_time=14.550204|dts=205332480|dts_time=14.550204|duration=368640|duration_time=0.026122|size=418|pos=234254|flags=K__|data_hash=CRC32:3516c575 +packet|codec_type=audio|stream_index=0|pts=205701120|pts_time=14.576327|dts=205701120|dts_time=14.576327|duration=368640|duration_time=0.026122|size=418|pos=234672|flags=K__|data_hash=CRC32:b32cd4ed +packet|codec_type=audio|stream_index=0|pts=206069760|pts_time=14.602449|dts=206069760|dts_time=14.602449|duration=368640|duration_time=0.026122|size=418|pos=235090|flags=K__|data_hash=CRC32:bcd22861 +packet|codec_type=audio|stream_index=0|pts=206438400|pts_time=14.628571|dts=206438400|dts_time=14.628571|duration=368640|duration_time=0.026122|size=418|pos=235508|flags=K__|data_hash=CRC32:a7d0b124 +packet|codec_type=audio|stream_index=0|pts=206807040|pts_time=14.654694|dts=206807040|dts_time=14.654694|duration=368640|duration_time=0.026122|size=418|pos=235926|flags=K__|data_hash=CRC32:3fed01ec +packet|codec_type=audio|stream_index=0|pts=207175680|pts_time=14.680816|dts=207175680|dts_time=14.680816|duration=368640|duration_time=0.026122|size=418|pos=236344|flags=K__|data_hash=CRC32:ff85606f +packet|codec_type=audio|stream_index=0|pts=207544320|pts_time=14.706939|dts=207544320|dts_time=14.706939|duration=368640|duration_time=0.026122|size=418|pos=236762|flags=K__|data_hash=CRC32:a62312cb +packet|codec_type=audio|stream_index=0|pts=207912960|pts_time=14.733061|dts=207912960|dts_time=14.733061|duration=368640|duration_time=0.026122|size=417|pos=237180|flags=K__|data_hash=CRC32:4b910380 +packet|codec_type=audio|stream_index=0|pts=208281600|pts_time=14.759184|dts=208281600|dts_time=14.759184|duration=368640|duration_time=0.026122|size=418|pos=237597|flags=K__|data_hash=CRC32:4f97177f +packet|codec_type=audio|stream_index=0|pts=208650240|pts_time=14.785306|dts=208650240|dts_time=14.785306|duration=368640|duration_time=0.026122|size=418|pos=238015|flags=K__|data_hash=CRC32:f919570c +packet|codec_type=audio|stream_index=0|pts=209018880|pts_time=14.811429|dts=209018880|dts_time=14.811429|duration=368640|duration_time=0.026122|size=418|pos=238433|flags=K__|data_hash=CRC32:74ca87ce +packet|codec_type=audio|stream_index=0|pts=209387520|pts_time=14.837551|dts=209387520|dts_time=14.837551|duration=368640|duration_time=0.026122|size=418|pos=238851|flags=K__|data_hash=CRC32:5fb510e2 +packet|codec_type=audio|stream_index=0|pts=209756160|pts_time=14.863673|dts=209756160|dts_time=14.863673|duration=368640|duration_time=0.026122|size=418|pos=239269|flags=K__|data_hash=CRC32:c01c76b9 +packet|codec_type=audio|stream_index=0|pts=210124800|pts_time=14.889796|dts=210124800|dts_time=14.889796|duration=368640|duration_time=0.026122|size=418|pos=239687|flags=K__|data_hash=CRC32:fb39fca0 +packet|codec_type=audio|stream_index=0|pts=210493440|pts_time=14.915918|dts=210493440|dts_time=14.915918|duration=368640|duration_time=0.026122|size=418|pos=240105|flags=K__|data_hash=CRC32:9b334424 +packet|codec_type=audio|stream_index=0|pts=210862080|pts_time=14.942041|dts=210862080|dts_time=14.942041|duration=368640|duration_time=0.026122|size=418|pos=240523|flags=K__|data_hash=CRC32:8b9fd924 +packet|codec_type=audio|stream_index=0|pts=211230720|pts_time=14.968163|dts=211230720|dts_time=14.968163|duration=368640|duration_time=0.026122|size=418|pos=240941|flags=K__|data_hash=CRC32:e81832b1 +packet|codec_type=audio|stream_index=0|pts=211599360|pts_time=14.994286|dts=211599360|dts_time=14.994286|duration=368640|duration_time=0.026122|size=418|pos=241359|flags=K__|data_hash=CRC32:cef4dc50 +packet|codec_type=audio|stream_index=0|pts=211968000|pts_time=15.020408|dts=211968000|dts_time=15.020408|duration=368640|duration_time=0.026122|size=418|pos=241777|flags=K__|data_hash=CRC32:4948aebf +packet|codec_type=audio|stream_index=0|pts=212336640|pts_time=15.046531|dts=212336640|dts_time=15.046531|duration=368640|duration_time=0.026122|size=418|pos=242195|flags=K__|data_hash=CRC32:eb2c924e +packet|codec_type=audio|stream_index=0|pts=212705280|pts_time=15.072653|dts=212705280|dts_time=15.072653|duration=368640|duration_time=0.026122|size=418|pos=242613|flags=K__|data_hash=CRC32:851f8690 +packet|codec_type=audio|stream_index=0|pts=213073920|pts_time=15.098776|dts=213073920|dts_time=15.098776|duration=368640|duration_time=0.026122|size=418|pos=243031|flags=K__|data_hash=CRC32:4c0e608d +packet|codec_type=audio|stream_index=0|pts=213442560|pts_time=15.124898|dts=213442560|dts_time=15.124898|duration=368640|duration_time=0.026122|size=418|pos=243449|flags=K__|data_hash=CRC32:37f43818 +packet|codec_type=audio|stream_index=0|pts=213811200|pts_time=15.151020|dts=213811200|dts_time=15.151020|duration=368640|duration_time=0.026122|size=418|pos=243867|flags=K__|data_hash=CRC32:8f88252e +packet|codec_type=audio|stream_index=0|pts=214179840|pts_time=15.177143|dts=214179840|dts_time=15.177143|duration=368640|duration_time=0.026122|size=418|pos=244285|flags=K__|data_hash=CRC32:95f6b13d +packet|codec_type=audio|stream_index=0|pts=214548480|pts_time=15.203265|dts=214548480|dts_time=15.203265|duration=368640|duration_time=0.026122|size=418|pos=244703|flags=K__|data_hash=CRC32:32dde92f +packet|codec_type=audio|stream_index=0|pts=214917120|pts_time=15.229388|dts=214917120|dts_time=15.229388|duration=368640|duration_time=0.026122|size=418|pos=245121|flags=K__|data_hash=CRC32:0d034c77 +packet|codec_type=audio|stream_index=0|pts=215285760|pts_time=15.255510|dts=215285760|dts_time=15.255510|duration=368640|duration_time=0.026122|size=418|pos=245539|flags=K__|data_hash=CRC32:4cbf0548 +packet|codec_type=audio|stream_index=0|pts=215654400|pts_time=15.281633|dts=215654400|dts_time=15.281633|duration=368640|duration_time=0.026122|size=418|pos=245957|flags=K__|data_hash=CRC32:599d8f8f +packet|codec_type=audio|stream_index=0|pts=216023040|pts_time=15.307755|dts=216023040|dts_time=15.307755|duration=368640|duration_time=0.026122|size=418|pos=246375|flags=K__|data_hash=CRC32:da07f929 +packet|codec_type=audio|stream_index=0|pts=216391680|pts_time=15.333878|dts=216391680|dts_time=15.333878|duration=368640|duration_time=0.026122|size=418|pos=246793|flags=K__|data_hash=CRC32:294af00d +packet|codec_type=audio|stream_index=0|pts=216760320|pts_time=15.360000|dts=216760320|dts_time=15.360000|duration=368640|duration_time=0.026122|size=417|pos=247211|flags=K__|data_hash=CRC32:14a8bd71 +packet|codec_type=audio|stream_index=0|pts=217128960|pts_time=15.386122|dts=217128960|dts_time=15.386122|duration=368640|duration_time=0.026122|size=418|pos=247628|flags=K__|data_hash=CRC32:10afdcd0 +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__|data_hash=CRC32:d5fb5f9c|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=218972160|pts_time=15.516735|dts=218972160|dts_time=15.516735|duration=368640|duration_time=0.026122|size=418|pos=249718|flags=K_|data_hash=CRC32:3789f3cf|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__|data_hash=CRC32:3789f3cf|side_data|side_data_type=Skip Samples|skip_samples=0|discard_padding=1152|skip_reason=0|discard_reason=0 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|initial_padding=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 1f89e9af85f..7dd2c8308eb 100644 --- a/tests/ref/fate/gaplessenc-itunes-to-ipod-aac +++ b/tests/ref/fate/gaplessenc-itunes-to-ipod-aac @@ -7,22 +7,22 @@ duration_ts=103326 start_time=0.000000 duration=2.342993 [/FORMAT] -packet|pts=-1024|dts=-1024|duration=1024|flags=KD|side_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_ -packet|pts=2048|dts=2048|duration=1024|flags=K_ -packet|pts=3072|dts=3072|duration=1024|flags=K_ -packet|pts=4096|dts=4096|duration=1024|flags=K_ -packet|pts=5120|dts=5120|duration=1024|flags=K_ -packet|pts=95232|dts=95232|duration=1024|flags=K_ -packet|pts=96256|dts=96256|duration=1024|flags=K_ -packet|pts=97280|dts=97280|duration=1024|flags=K_ -packet|pts=98304|dts=98304|duration=1024|flags=K_ -packet|pts=99328|dts=99328|duration=1024|flags=K_ -packet|pts=100352|dts=100352|duration=1024|flags=K_ -packet|pts=101376|dts=101376|duration=1024|flags=K_ -packet|pts=102400|dts=102400|duration=926|flags=K_ +packet|pts=0|dts=0|duration=1024|flags=K__ +packet|pts=1024|dts=1024|duration=1024|flags=K__ +packet|pts=2048|dts=2048|duration=1024|flags=K__ +packet|pts=3072|dts=3072|duration=1024|flags=K__ +packet|pts=4096|dts=4096|duration=1024|flags=K__ +packet|pts=5120|dts=5120|duration=1024|flags=K__ +packet|pts=95232|dts=95232|duration=1024|flags=K__ +packet|pts=96256|dts=96256|duration=1024|flags=K__ +packet|pts=97280|dts=97280|duration=1024|flags=K__ +packet|pts=98304|dts=98304|duration=1024|flags=K__ +packet|pts=99328|dts=99328|duration=1024|flags=K__ +packet|pts=100352|dts=100352|duration=1024|flags=K__ +packet|pts=101376|dts=101376|duration=1024|flags=K__ +packet|pts=102400|dts=102400|duration=926|flags=K__ stream|nb_read_packets=102 frame|pts=0|pkt_dts=0|best_effort_timestamp=0|pkt_duration=1024|nb_samples=1024 frame|pts=1024|pkt_dts=1024|best_effort_timestamp=1024|pkt_duration=1024|nb_samples=1024 diff --git a/tests/ref/fate/gaplessenc-pcm-to-mov-aac b/tests/ref/fate/gaplessenc-pcm-to-mov-aac index 82bed6f936d..e5f343e42f7 100644 --- a/tests/ref/fate/gaplessenc-pcm-to-mov-aac +++ b/tests/ref/fate/gaplessenc-pcm-to-mov-aac @@ -7,22 +7,22 @@ duration_ts=529200 start_time=0.000000 duration=12.000000 [/FORMAT] -packet|pts=-1024|dts=-1024|duration=1024|flags=KD|side_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_ -packet|pts=2048|dts=2048|duration=1024|flags=K_ -packet|pts=3072|dts=3072|duration=1024|flags=K_ -packet|pts=4096|dts=4096|duration=1024|flags=K_ -packet|pts=5120|dts=5120|duration=1024|flags=K_ -packet|pts=521216|dts=521216|duration=1024|flags=K_ -packet|pts=522240|dts=522240|duration=1024|flags=K_ -packet|pts=523264|dts=523264|duration=1024|flags=K_ -packet|pts=524288|dts=524288|duration=1024|flags=K_ -packet|pts=525312|dts=525312|duration=1024|flags=K_ -packet|pts=526336|dts=526336|duration=1024|flags=K_ -packet|pts=527360|dts=527360|duration=1024|flags=K_ -packet|pts=528384|dts=528384|duration=816|flags=K_ +packet|pts=0|dts=0|duration=1024|flags=K__ +packet|pts=1024|dts=1024|duration=1024|flags=K__ +packet|pts=2048|dts=2048|duration=1024|flags=K__ +packet|pts=3072|dts=3072|duration=1024|flags=K__ +packet|pts=4096|dts=4096|duration=1024|flags=K__ +packet|pts=5120|dts=5120|duration=1024|flags=K__ +packet|pts=521216|dts=521216|duration=1024|flags=K__ +packet|pts=522240|dts=522240|duration=1024|flags=K__ +packet|pts=523264|dts=523264|duration=1024|flags=K__ +packet|pts=524288|dts=524288|duration=1024|flags=K__ +packet|pts=525312|dts=525312|duration=1024|flags=K__ +packet|pts=526336|dts=526336|duration=1024|flags=K__ +packet|pts=527360|dts=527360|duration=1024|flags=K__ +packet|pts=528384|dts=528384|duration=816|flags=K__ stream|nb_read_packets=518 frame|pts=0|pkt_dts=0|best_effort_timestamp=0|pkt_duration=1024|nb_samples=1024 frame|pts=1024|pkt_dts=1024|best_effort_timestamp=1024|pkt_duration=1024|nb_samples=1024 diff --git a/tests/ref/fate/gaplessinfo-itunes1 b/tests/ref/fate/gaplessinfo-itunes1 index 841bdb31d01..94034d05a3d 100644 --- a/tests/ref/fate/gaplessinfo-itunes1 +++ b/tests/ref/fate/gaplessinfo-itunes1 @@ -7,22 +7,22 @@ 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_ -packet|pts=3072|dts=3072|duration=1024|flags=K_ -packet|pts=4096|dts=4096|duration=1024|flags=K_ -packet|pts=5120|dts=5120|duration=1024|flags=K_ -packet|pts=6144|dts=6144|duration=1024|flags=K_ -packet|pts=1286144|dts=1286144|duration=1024|flags=K_ -packet|pts=1287168|dts=1287168|duration=1024|flags=K_ -packet|pts=1288192|dts=1288192|duration=1024|flags=K_ -packet|pts=1289216|dts=1289216|duration=1024|flags=K_ -packet|pts=1290240|dts=1290240|duration=1024|flags=K_ -packet|pts=1291264|dts=1291264|duration=1024|flags=K_ -packet|pts=1292288|dts=1292288|duration=1024|flags=K_ -packet|pts=1293312|dts=1293312|duration=1024|flags=K_ +packet|pts=1024|dts=1024|duration=1024|flags=K__ +packet|pts=2048|dts=2048|duration=1024|flags=K__ +packet|pts=3072|dts=3072|duration=1024|flags=K__ +packet|pts=4096|dts=4096|duration=1024|flags=K__ +packet|pts=5120|dts=5120|duration=1024|flags=K__ +packet|pts=6144|dts=6144|duration=1024|flags=K__ +packet|pts=1286144|dts=1286144|duration=1024|flags=K__ +packet|pts=1287168|dts=1287168|duration=1024|flags=K__ +packet|pts=1288192|dts=1288192|duration=1024|flags=K__ +packet|pts=1289216|dts=1289216|duration=1024|flags=K__ +packet|pts=1290240|dts=1290240|duration=1024|flags=K__ +packet|pts=1291264|dts=1291264|duration=1024|flags=K__ +packet|pts=1292288|dts=1292288|duration=1024|flags=K__ +packet|pts=1293312|dts=1293312|duration=1024|flags=K__ stream|nb_read_packets=1264 frame|pts=2112|pkt_dts=2112|best_effort_timestamp=2112|pkt_duration=960|nb_samples=960 frame|pts=3072|pkt_dts=3072|best_effort_timestamp=3072|pkt_duration=1024|nb_samples=1024 diff --git a/tests/ref/fate/gaplessinfo-itunes2 b/tests/ref/fate/gaplessinfo-itunes2 index 3184a5ea59c..eae245dec2e 100644 --- a/tests/ref/fate/gaplessinfo-itunes2 +++ b/tests/ref/fate/gaplessinfo-itunes2 @@ -7,22 +7,22 @@ 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_ -packet|pts=3072|dts=3072|duration=1024|flags=K_ -packet|pts=4096|dts=4096|duration=1024|flags=K_ -packet|pts=5120|dts=5120|duration=1024|flags=K_ -packet|pts=6144|dts=6144|duration=1024|flags=K_ -packet|pts=97280|dts=97280|duration=1024|flags=K_ -packet|pts=98304|dts=98304|duration=1024|flags=K_ -packet|pts=99328|dts=99328|duration=1024|flags=K_ -packet|pts=100352|dts=100352|duration=1024|flags=K_ -packet|pts=101376|dts=101376|duration=1024|flags=K_ -packet|pts=102400|dts=102400|duration=1024|flags=K_ -packet|pts=103424|dts=103424|duration=1024|flags=K_ -packet|pts=104448|dts=104448|duration=1024|flags=K_ +packet|pts=1024|dts=1024|duration=1024|flags=K__ +packet|pts=2048|dts=2048|duration=1024|flags=K__ +packet|pts=3072|dts=3072|duration=1024|flags=K__ +packet|pts=4096|dts=4096|duration=1024|flags=K__ +packet|pts=5120|dts=5120|duration=1024|flags=K__ +packet|pts=6144|dts=6144|duration=1024|flags=K__ +packet|pts=97280|dts=97280|duration=1024|flags=K__ +packet|pts=98304|dts=98304|duration=1024|flags=K__ +packet|pts=99328|dts=99328|duration=1024|flags=K__ +packet|pts=100352|dts=100352|duration=1024|flags=K__ +packet|pts=101376|dts=101376|duration=1024|flags=K__ +packet|pts=102400|dts=102400|duration=1024|flags=K__ +packet|pts=103424|dts=103424|duration=1024|flags=K__ +packet|pts=104448|dts=104448|duration=1024|flags=K__ stream|nb_read_packets=103 frame|pts=2112|pkt_dts=2112|best_effort_timestamp=2112|pkt_duration=960|nb_samples=960 frame|pts=3072|pkt_dts=3072|best_effort_timestamp=3072|pkt_duration=1024|nb_samples=1024 diff --git a/tests/ref/fate/hapqa-extract-nosnappy-to-hapalphaonly-mov b/tests/ref/fate/hapqa-extract-nosnappy-to-hapalphaonly-mov index 72c89339255..d79f764fd7b 100644 --- a/tests/ref/fate/hapqa-extract-nosnappy-to-hapalphaonly-mov +++ b/tests/ref/fate/hapqa-extract-nosnappy-to-hapalphaonly-mov @@ -9,7 +9,7 @@ duration=512 duration_time=0.040000 size=4612 pos=36 -flags=K_ +flags=K__ data_hash=adler32:ed83c166 [/PACKET] [STREAM] diff --git a/tests/ref/fate/hapqa-extract-nosnappy-to-hapq-mov b/tests/ref/fate/hapqa-extract-nosnappy-to-hapq-mov index 449910bef6e..c71fa04ac8b 100644 --- a/tests/ref/fate/hapqa-extract-nosnappy-to-hapq-mov +++ b/tests/ref/fate/hapqa-extract-nosnappy-to-hapq-mov @@ -9,7 +9,7 @@ duration=512 duration_time=0.040000 size=9220 pos=36 -flags=K_ +flags=K__ data_hash=adler32:b3ccc147 [/PACKET] [STREAM] diff --git a/tests/ref/fate/matroska-encoding-delay b/tests/ref/fate/matroska-encoding-delay index 8dd3bf59e2a..e6cf4790f52 100644 --- a/tests/ref/fate/matroska-encoding-delay +++ b/tests/ref/fate/matroska-encoding-delay @@ -33,7 +33,7 @@ duration=24 duration_time=0.024000 size=1152 pos=1238 -flags=K_ +flags=K__ [/PACKET] [PACKET] codec_type=video @@ -46,7 +46,7 @@ duration=40 duration_time=0.040000 size=237628 pos=2398 -flags=K_ +flags=K__ [/PACKET] [PACKET] codec_type=audio @@ -59,7 +59,7 @@ duration=24 duration_time=0.024000 size=1152 pos=240033 -flags=K_ +flags=K__ [/PACKET] [PACKET] codec_type=audio @@ -72,7 +72,7 @@ duration=24 duration_time=0.024000 size=1152 pos=241208 -flags=K_ +flags=K__ [/PACKET] [PACKET] codec_type=video @@ -85,7 +85,7 @@ duration=40 duration_time=0.040000 size=238066 pos=242368 -flags=K_ +flags=K__ [/PACKET] [STREAM] codec_name=mpeg2video diff --git a/tests/ref/fate/matroska-ogg-opus-remux b/tests/ref/fate/matroska-ogg-opus-remux index 1fa776ef011..473b9ff00c9 100644 --- a/tests/ref/fate/matroska-ogg-opus-remux +++ b/tests/ref/fate/matroska-ogg-opus-remux @@ -58,7 +58,7 @@ duration=20 duration_time=0.020000 size=402 pos=540 -flags=K_ +flags=K__ [/PACKET] [PACKET] codec_type=audio @@ -71,7 +71,7 @@ duration=20 duration_time=0.020000 size=216 pos=949 -flags=K_ +flags=K__ [/PACKET] [PACKET] codec_type=audio @@ -84,7 +84,7 @@ duration=20 duration_time=0.020000 size=215 pos=1172 -flags=K_ +flags=K__ [/PACKET] [STREAM] codec_name=opus diff --git a/tests/ref/fate/matroska-opus-remux b/tests/ref/fate/matroska-opus-remux index 61afeaa7514..8ebc80ee360 100644 --- a/tests/ref/fate/matroska-opus-remux +++ b/tests/ref/fate/matroska-opus-remux @@ -69,7 +69,7 @@ duration=20 duration_time=0.020000 size=320 pos=496 -flags=K_ +flags=K__ [/PACKET] [PACKET] codec_type=audio @@ -82,7 +82,7 @@ duration=20 duration_time=0.020000 size=159 pos=823 -flags=K_ +flags=K__ [/PACKET] [PACKET] codec_type=audio @@ -95,7 +95,7 @@ duration=20 duration_time=0.020000 size=148 pos=989 -flags=K_ +flags=K__ [/PACKET] [STREAM] codec_name=opus diff --git a/tests/ref/fate/mov-aac-2048-priming b/tests/ref/fate/mov-aac-2048-priming index 071c3627f33..de202605bc3 100644 --- a/tests/ref/fate/mov-aac-2048-priming +++ b/tests/ref/fate/mov-aac-2048-priming @@ -1,218 +1,218 @@ -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=-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_ -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=186|pos=698|flags=K_ -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=222|pos=884|flags=K_ -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=186|pos=1106|flags=K_ -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=206|pos=1292|flags=K_ -packet|codec_type=audio|stream_index=0|pts=5120|pts_time=0.116100|dts=5120|dts_time=0.116100|duration=1024|duration_time=0.023220|size=199|pos=1498|flags=K_ -packet|codec_type=audio|stream_index=0|pts=6144|pts_time=0.139320|dts=6144|dts_time=0.139320|duration=1024|duration_time=0.023220|size=236|pos=1697|flags=K_ -packet|codec_type=audio|stream_index=0|pts=7168|pts_time=0.162540|dts=7168|dts_time=0.162540|duration=1024|duration_time=0.023220|size=208|pos=1933|flags=K_ -packet|codec_type=audio|stream_index=0|pts=8192|pts_time=0.185760|dts=8192|dts_time=0.185760|duration=1024|duration_time=0.023220|size=238|pos=2141|flags=K_ -packet|codec_type=audio|stream_index=0|pts=9216|pts_time=0.208980|dts=9216|dts_time=0.208980|duration=1024|duration_time=0.023220|size=222|pos=2379|flags=K_ -packet|codec_type=audio|stream_index=0|pts=10240|pts_time=0.232200|dts=10240|dts_time=0.232200|duration=1024|duration_time=0.023220|size=211|pos=2601|flags=K_ -packet|codec_type=audio|stream_index=0|pts=11264|pts_time=0.255420|dts=11264|dts_time=0.255420|duration=1024|duration_time=0.023220|size=153|pos=2812|flags=K_ -packet|codec_type=audio|stream_index=0|pts=12288|pts_time=0.278639|dts=12288|dts_time=0.278639|duration=1024|duration_time=0.023220|size=191|pos=2965|flags=K_ -packet|codec_type=audio|stream_index=0|pts=13312|pts_time=0.301859|dts=13312|dts_time=0.301859|duration=1024|duration_time=0.023220|size=208|pos=3156|flags=K_ -packet|codec_type=audio|stream_index=0|pts=14336|pts_time=0.325079|dts=14336|dts_time=0.325079|duration=1024|duration_time=0.023220|size=188|pos=3364|flags=K_ -packet|codec_type=audio|stream_index=0|pts=15360|pts_time=0.348299|dts=15360|dts_time=0.348299|duration=1024|duration_time=0.023220|size=170|pos=3552|flags=K_ -packet|codec_type=audio|stream_index=0|pts=16384|pts_time=0.371519|dts=16384|dts_time=0.371519|duration=1024|duration_time=0.023220|size=221|pos=3722|flags=K_ -packet|codec_type=audio|stream_index=0|pts=17408|pts_time=0.394739|dts=17408|dts_time=0.394739|duration=1024|duration_time=0.023220|size=247|pos=3943|flags=K_ -packet|codec_type=audio|stream_index=0|pts=18432|pts_time=0.417959|dts=18432|dts_time=0.417959|duration=1024|duration_time=0.023220|size=202|pos=4190|flags=K_ -packet|codec_type=audio|stream_index=0|pts=19456|pts_time=0.441179|dts=19456|dts_time=0.441179|duration=1024|duration_time=0.023220|size=186|pos=4392|flags=K_ -packet|codec_type=audio|stream_index=0|pts=20480|pts_time=0.464399|dts=20480|dts_time=0.464399|duration=1024|duration_time=0.023220|size=196|pos=4578|flags=K_ -packet|codec_type=audio|stream_index=0|pts=21504|pts_time=0.487619|dts=21504|dts_time=0.487619|duration=1024|duration_time=0.023220|size=200|pos=4774|flags=K_ -packet|codec_type=audio|stream_index=0|pts=22528|pts_time=0.510839|dts=22528|dts_time=0.510839|duration=1024|duration_time=0.023220|size=170|pos=4974|flags=K_ -packet|codec_type=audio|stream_index=0|pts=23552|pts_time=0.534059|dts=23552|dts_time=0.534059|duration=1024|duration_time=0.023220|size=172|pos=5144|flags=K_ -packet|codec_type=audio|stream_index=0|pts=24576|pts_time=0.557279|dts=24576|dts_time=0.557279|duration=1024|duration_time=0.023220|size=206|pos=5316|flags=K_ -packet|codec_type=audio|stream_index=0|pts=25600|pts_time=0.580499|dts=25600|dts_time=0.580499|duration=1024|duration_time=0.023220|size=208|pos=5522|flags=K_ -packet|codec_type=audio|stream_index=0|pts=26624|pts_time=0.603719|dts=26624|dts_time=0.603719|duration=1024|duration_time=0.023220|size=217|pos=5730|flags=K_ -packet|codec_type=audio|stream_index=0|pts=27648|pts_time=0.626939|dts=27648|dts_time=0.626939|duration=1024|duration_time=0.023220|size=252|pos=5947|flags=K_ -packet|codec_type=audio|stream_index=0|pts=28672|pts_time=0.650159|dts=28672|dts_time=0.650159|duration=1024|duration_time=0.023220|size=171|pos=6199|flags=K_ -packet|codec_type=audio|stream_index=0|pts=29696|pts_time=0.673379|dts=29696|dts_time=0.673379|duration=1024|duration_time=0.023220|size=206|pos=6370|flags=K_ -packet|codec_type=audio|stream_index=0|pts=30720|pts_time=0.696599|dts=30720|dts_time=0.696599|duration=1024|duration_time=0.023220|size=237|pos=6576|flags=K_ -packet|codec_type=audio|stream_index=0|pts=31744|pts_time=0.719819|dts=31744|dts_time=0.719819|duration=1024|duration_time=0.023220|size=210|pos=6813|flags=K_ -packet|codec_type=audio|stream_index=0|pts=32768|pts_time=0.743039|dts=32768|dts_time=0.743039|duration=1024|duration_time=0.023220|size=166|pos=7023|flags=K_ -packet|codec_type=audio|stream_index=0|pts=33792|pts_time=0.766259|dts=33792|dts_time=0.766259|duration=1024|duration_time=0.023220|size=166|pos=7189|flags=K_ -packet|codec_type=audio|stream_index=0|pts=34816|pts_time=0.789478|dts=34816|dts_time=0.789478|duration=1024|duration_time=0.023220|size=177|pos=7355|flags=K_ -packet|codec_type=audio|stream_index=0|pts=35840|pts_time=0.812698|dts=35840|dts_time=0.812698|duration=1024|duration_time=0.023220|size=188|pos=7532|flags=K_ -packet|codec_type=audio|stream_index=0|pts=36864|pts_time=0.835918|dts=36864|dts_time=0.835918|duration=1024|duration_time=0.023220|size=193|pos=7720|flags=K_ -packet|codec_type=audio|stream_index=0|pts=37888|pts_time=0.859138|dts=37888|dts_time=0.859138|duration=1024|duration_time=0.023220|size=195|pos=7913|flags=K_ -packet|codec_type=audio|stream_index=0|pts=38912|pts_time=0.882358|dts=38912|dts_time=0.882358|duration=1024|duration_time=0.023220|size=211|pos=8108|flags=K_ -packet|codec_type=audio|stream_index=0|pts=39936|pts_time=0.905578|dts=39936|dts_time=0.905578|duration=1024|duration_time=0.023220|size=249|pos=8319|flags=K_ -packet|codec_type=audio|stream_index=0|pts=40960|pts_time=0.928798|dts=40960|dts_time=0.928798|duration=1024|duration_time=0.023220|size=223|pos=8568|flags=K_ -packet|codec_type=audio|stream_index=0|pts=41984|pts_time=0.952018|dts=41984|dts_time=0.952018|duration=1024|duration_time=0.023220|size=230|pos=8791|flags=K_ -packet|codec_type=audio|stream_index=0|pts=43008|pts_time=0.975238|dts=43008|dts_time=0.975238|duration=1024|duration_time=0.023220|size=203|pos=9021|flags=K_ -packet|codec_type=audio|stream_index=0|pts=44032|pts_time=0.998458|dts=44032|dts_time=0.998458|duration=1024|duration_time=0.023220|size=180|pos=9224|flags=K_ -packet|codec_type=audio|stream_index=0|pts=45056|pts_time=1.021678|dts=45056|dts_time=1.021678|duration=1024|duration_time=0.023220|size=172|pos=9404|flags=K_ -packet|codec_type=audio|stream_index=0|pts=46080|pts_time=1.044898|dts=46080|dts_time=1.044898|duration=1024|duration_time=0.023220|size=240|pos=9576|flags=K_ -packet|codec_type=audio|stream_index=0|pts=47104|pts_time=1.068118|dts=47104|dts_time=1.068118|duration=1024|duration_time=0.023220|size=179|pos=9816|flags=K_ -packet|codec_type=audio|stream_index=0|pts=48128|pts_time=1.091338|dts=48128|dts_time=1.091338|duration=1024|duration_time=0.023220|size=191|pos=9995|flags=K_ -packet|codec_type=audio|stream_index=0|pts=49152|pts_time=1.114558|dts=49152|dts_time=1.114558|duration=1024|duration_time=0.023220|size=184|pos=10186|flags=K_ -packet|codec_type=audio|stream_index=0|pts=50176|pts_time=1.137778|dts=50176|dts_time=1.137778|duration=1024|duration_time=0.023220|size=214|pos=10370|flags=K_ -packet|codec_type=audio|stream_index=0|pts=51200|pts_time=1.160998|dts=51200|dts_time=1.160998|duration=1024|duration_time=0.023220|size=194|pos=10584|flags=K_ -packet|codec_type=audio|stream_index=0|pts=52224|pts_time=1.184218|dts=52224|dts_time=1.184218|duration=1024|duration_time=0.023220|size=235|pos=10778|flags=K_ -packet|codec_type=audio|stream_index=0|pts=53248|pts_time=1.207438|dts=53248|dts_time=1.207438|duration=1024|duration_time=0.023220|size=195|pos=11013|flags=K_ -packet|codec_type=audio|stream_index=0|pts=54272|pts_time=1.230658|dts=54272|dts_time=1.230658|duration=1024|duration_time=0.023220|size=220|pos=11208|flags=K_ -packet|codec_type=audio|stream_index=0|pts=55296|pts_time=1.253878|dts=55296|dts_time=1.253878|duration=1024|duration_time=0.023220|size=187|pos=11428|flags=K_ -packet|codec_type=audio|stream_index=0|pts=56320|pts_time=1.277098|dts=56320|dts_time=1.277098|duration=1024|duration_time=0.023220|size=238|pos=11615|flags=K_ -packet|codec_type=audio|stream_index=0|pts=57344|pts_time=1.300317|dts=57344|dts_time=1.300317|duration=1024|duration_time=0.023220|size=175|pos=11853|flags=K_ -packet|codec_type=audio|stream_index=0|pts=58368|pts_time=1.323537|dts=58368|dts_time=1.323537|duration=1024|duration_time=0.023220|size=178|pos=12028|flags=K_ -packet|codec_type=audio|stream_index=0|pts=59392|pts_time=1.346757|dts=59392|dts_time=1.346757|duration=1024|duration_time=0.023220|size=219|pos=12206|flags=K_ -packet|codec_type=audio|stream_index=0|pts=60416|pts_time=1.369977|dts=60416|dts_time=1.369977|duration=1024|duration_time=0.023220|size=179|pos=12425|flags=K_ -packet|codec_type=audio|stream_index=0|pts=61440|pts_time=1.393197|dts=61440|dts_time=1.393197|duration=1024|duration_time=0.023220|size=193|pos=12604|flags=K_ -packet|codec_type=audio|stream_index=0|pts=62464|pts_time=1.416417|dts=62464|dts_time=1.416417|duration=1024|duration_time=0.023220|size=200|pos=12797|flags=K_ -packet|codec_type=audio|stream_index=0|pts=63488|pts_time=1.439637|dts=63488|dts_time=1.439637|duration=1024|duration_time=0.023220|size=218|pos=12997|flags=K_ -packet|codec_type=audio|stream_index=0|pts=64512|pts_time=1.462857|dts=64512|dts_time=1.462857|duration=1024|duration_time=0.023220|size=215|pos=13215|flags=K_ -packet|codec_type=audio|stream_index=0|pts=65536|pts_time=1.486077|dts=65536|dts_time=1.486077|duration=1024|duration_time=0.023220|size=209|pos=13430|flags=K_ -packet|codec_type=audio|stream_index=0|pts=66560|pts_time=1.509297|dts=66560|dts_time=1.509297|duration=1024|duration_time=0.023220|size=171|pos=13639|flags=K_ -packet|codec_type=audio|stream_index=0|pts=67584|pts_time=1.532517|dts=67584|dts_time=1.532517|duration=1024|duration_time=0.023220|size=179|pos=13810|flags=K_ -packet|codec_type=audio|stream_index=0|pts=68608|pts_time=1.555737|dts=68608|dts_time=1.555737|duration=1024|duration_time=0.023220|size=185|pos=13989|flags=K_ -packet|codec_type=audio|stream_index=0|pts=69632|pts_time=1.578957|dts=69632|dts_time=1.578957|duration=1024|duration_time=0.023220|size=225|pos=14174|flags=K_ -packet|codec_type=audio|stream_index=0|pts=70656|pts_time=1.602177|dts=70656|dts_time=1.602177|duration=1024|duration_time=0.023220|size=221|pos=14399|flags=K_ -packet|codec_type=audio|stream_index=0|pts=71680|pts_time=1.625397|dts=71680|dts_time=1.625397|duration=1024|duration_time=0.023220|size=201|pos=14620|flags=K_ -packet|codec_type=audio|stream_index=0|pts=72704|pts_time=1.648617|dts=72704|dts_time=1.648617|duration=1024|duration_time=0.023220|size=206|pos=14821|flags=K_ -packet|codec_type=audio|stream_index=0|pts=73728|pts_time=1.671837|dts=73728|dts_time=1.671837|duration=1024|duration_time=0.023220|size=182|pos=15027|flags=K_ -packet|codec_type=audio|stream_index=0|pts=74752|pts_time=1.695057|dts=74752|dts_time=1.695057|duration=1024|duration_time=0.023220|size=176|pos=15209|flags=K_ -packet|codec_type=audio|stream_index=0|pts=75776|pts_time=1.718277|dts=75776|dts_time=1.718277|duration=1024|duration_time=0.023220|size=233|pos=15385|flags=K_ -packet|codec_type=audio|stream_index=0|pts=76800|pts_time=1.741497|dts=76800|dts_time=1.741497|duration=1024|duration_time=0.023220|size=199|pos=15618|flags=K_ -packet|codec_type=audio|stream_index=0|pts=77824|pts_time=1.764717|dts=77824|dts_time=1.764717|duration=1024|duration_time=0.023220|size=220|pos=15817|flags=K_ -packet|codec_type=audio|stream_index=0|pts=78848|pts_time=1.787937|dts=78848|dts_time=1.787937|duration=1024|duration_time=0.023220|size=190|pos=16037|flags=K_ -packet|codec_type=audio|stream_index=0|pts=79872|pts_time=1.811156|dts=79872|dts_time=1.811156|duration=1024|duration_time=0.023220|size=210|pos=16227|flags=K_ -packet|codec_type=audio|stream_index=0|pts=80896|pts_time=1.834376|dts=80896|dts_time=1.834376|duration=1024|duration_time=0.023220|size=204|pos=16437|flags=K_ -packet|codec_type=audio|stream_index=0|pts=81920|pts_time=1.857596|dts=81920|dts_time=1.857596|duration=1024|duration_time=0.023220|size=171|pos=16641|flags=K_ -packet|codec_type=audio|stream_index=0|pts=82944|pts_time=1.880816|dts=82944|dts_time=1.880816|duration=1024|duration_time=0.023220|size=167|pos=16812|flags=K_ -packet|codec_type=audio|stream_index=0|pts=83968|pts_time=1.904036|dts=83968|dts_time=1.904036|duration=1024|duration_time=0.023220|size=200|pos=16979|flags=K_ -packet|codec_type=audio|stream_index=0|pts=84992|pts_time=1.927256|dts=84992|dts_time=1.927256|duration=1024|duration_time=0.023220|size=254|pos=17179|flags=K_ -packet|codec_type=audio|stream_index=0|pts=86016|pts_time=1.950476|dts=86016|dts_time=1.950476|duration=1024|duration_time=0.023220|size=205|pos=17433|flags=K_ -packet|codec_type=audio|stream_index=0|pts=87040|pts_time=1.973696|dts=87040|dts_time=1.973696|duration=1024|duration_time=0.023220|size=196|pos=17638|flags=K_ -packet|codec_type=audio|stream_index=0|pts=88064|pts_time=1.996916|dts=88064|dts_time=1.996916|duration=1024|duration_time=0.023220|size=190|pos=17834|flags=K_ -packet|codec_type=audio|stream_index=0|pts=89088|pts_time=2.020136|dts=89088|dts_time=2.020136|duration=1024|duration_time=0.023220|size=197|pos=18024|flags=K_ -packet|codec_type=audio|stream_index=0|pts=90112|pts_time=2.043356|dts=90112|dts_time=2.043356|duration=1024|duration_time=0.023220|size=186|pos=18221|flags=K_ -packet|codec_type=audio|stream_index=0|pts=91136|pts_time=2.066576|dts=91136|dts_time=2.066576|duration=1024|duration_time=0.023220|size=194|pos=18407|flags=K_ -packet|codec_type=audio|stream_index=0|pts=92160|pts_time=2.089796|dts=92160|dts_time=2.089796|duration=1024|duration_time=0.023220|size=227|pos=18601|flags=K_ -packet|codec_type=audio|stream_index=0|pts=93184|pts_time=2.113016|dts=93184|dts_time=2.113016|duration=1024|duration_time=0.023220|size=195|pos=18828|flags=K_ -packet|codec_type=audio|stream_index=0|pts=94208|pts_time=2.136236|dts=94208|dts_time=2.136236|duration=1024|duration_time=0.023220|size=228|pos=19023|flags=K_ -packet|codec_type=audio|stream_index=0|pts=95232|pts_time=2.159456|dts=95232|dts_time=2.159456|duration=1024|duration_time=0.023220|size=196|pos=19251|flags=K_ -packet|codec_type=audio|stream_index=0|pts=96256|pts_time=2.182676|dts=96256|dts_time=2.182676|duration=1024|duration_time=0.023220|size=197|pos=19447|flags=K_ -packet|codec_type=audio|stream_index=0|pts=97280|pts_time=2.205896|dts=97280|dts_time=2.205896|duration=1024|duration_time=0.023220|size=186|pos=19644|flags=K_ -packet|codec_type=audio|stream_index=0|pts=98304|pts_time=2.229116|dts=98304|dts_time=2.229116|duration=1024|duration_time=0.023220|size=191|pos=19830|flags=K_ -packet|codec_type=audio|stream_index=0|pts=99328|pts_time=2.252336|dts=99328|dts_time=2.252336|duration=1024|duration_time=0.023220|size=215|pos=20021|flags=K_ -packet|codec_type=audio|stream_index=0|pts=100352|pts_time=2.275556|dts=100352|dts_time=2.275556|duration=1024|duration_time=0.023220|size=203|pos=20236|flags=K_ -packet|codec_type=audio|stream_index=0|pts=101376|pts_time=2.298776|dts=101376|dts_time=2.298776|duration=1024|duration_time=0.023220|size=205|pos=20439|flags=K_ -packet|codec_type=audio|stream_index=0|pts=102400|pts_time=2.321995|dts=102400|dts_time=2.321995|duration=1024|duration_time=0.023220|size=205|pos=20644|flags=K_ -packet|codec_type=audio|stream_index=0|pts=103424|pts_time=2.345215|dts=103424|dts_time=2.345215|duration=1024|duration_time=0.023220|size=213|pos=20849|flags=K_ -packet|codec_type=audio|stream_index=0|pts=104448|pts_time=2.368435|dts=104448|dts_time=2.368435|duration=1024|duration_time=0.023220|size=198|pos=21062|flags=K_ -packet|codec_type=audio|stream_index=0|pts=105472|pts_time=2.391655|dts=105472|dts_time=2.391655|duration=1024|duration_time=0.023220|size=178|pos=21260|flags=K_ -packet|codec_type=audio|stream_index=0|pts=106496|pts_time=2.414875|dts=106496|dts_time=2.414875|duration=1024|duration_time=0.023220|size=195|pos=21438|flags=K_ -packet|codec_type=audio|stream_index=0|pts=107520|pts_time=2.438095|dts=107520|dts_time=2.438095|duration=1024|duration_time=0.023220|size=227|pos=21633|flags=K_ -packet|codec_type=audio|stream_index=0|pts=108544|pts_time=2.461315|dts=108544|dts_time=2.461315|duration=1024|duration_time=0.023220|size=185|pos=21860|flags=K_ -packet|codec_type=audio|stream_index=0|pts=109568|pts_time=2.484535|dts=109568|dts_time=2.484535|duration=1024|duration_time=0.023220|size=206|pos=22045|flags=K_ -packet|codec_type=audio|stream_index=0|pts=110592|pts_time=2.507755|dts=110592|dts_time=2.507755|duration=1024|duration_time=0.023220|size=183|pos=22251|flags=K_ -packet|codec_type=audio|stream_index=0|pts=111616|pts_time=2.530975|dts=111616|dts_time=2.530975|duration=1024|duration_time=0.023220|size=208|pos=22434|flags=K_ -packet|codec_type=audio|stream_index=0|pts=112640|pts_time=2.554195|dts=112640|dts_time=2.554195|duration=1024|duration_time=0.023220|size=204|pos=22642|flags=K_ -packet|codec_type=audio|stream_index=0|pts=113664|pts_time=2.577415|dts=113664|dts_time=2.577415|duration=1024|duration_time=0.023220|size=192|pos=22846|flags=K_ -packet|codec_type=audio|stream_index=0|pts=114688|pts_time=2.600635|dts=114688|dts_time=2.600635|duration=1024|duration_time=0.023220|size=190|pos=23038|flags=K_ -packet|codec_type=audio|stream_index=0|pts=115712|pts_time=2.623855|dts=115712|dts_time=2.623855|duration=1024|duration_time=0.023220|size=199|pos=23228|flags=K_ -packet|codec_type=audio|stream_index=0|pts=116736|pts_time=2.647075|dts=116736|dts_time=2.647075|duration=1024|duration_time=0.023220|size=229|pos=23427|flags=K_ -packet|codec_type=audio|stream_index=0|pts=117760|pts_time=2.670295|dts=117760|dts_time=2.670295|duration=1024|duration_time=0.023220|size=208|pos=23656|flags=K_ -packet|codec_type=audio|stream_index=0|pts=118784|pts_time=2.693515|dts=118784|dts_time=2.693515|duration=1024|duration_time=0.023220|size=195|pos=23864|flags=K_ -packet|codec_type=audio|stream_index=0|pts=119808|pts_time=2.716735|dts=119808|dts_time=2.716735|duration=1024|duration_time=0.023220|size=190|pos=24059|flags=K_ -packet|codec_type=audio|stream_index=0|pts=120832|pts_time=2.739955|dts=120832|dts_time=2.739955|duration=1024|duration_time=0.023220|size=190|pos=24249|flags=K_ -packet|codec_type=audio|stream_index=0|pts=121856|pts_time=2.763175|dts=121856|dts_time=2.763175|duration=1024|duration_time=0.023220|size=192|pos=24439|flags=K_ -packet|codec_type=audio|stream_index=0|pts=122880|pts_time=2.786395|dts=122880|dts_time=2.786395|duration=1024|duration_time=0.023220|size=226|pos=24631|flags=K_ -packet|codec_type=audio|stream_index=0|pts=123904|pts_time=2.809615|dts=123904|dts_time=2.809615|duration=1024|duration_time=0.023220|size=195|pos=24857|flags=K_ -packet|codec_type=audio|stream_index=0|pts=124928|pts_time=2.832834|dts=124928|dts_time=2.832834|duration=1024|duration_time=0.023220|size=230|pos=25052|flags=K_ -packet|codec_type=audio|stream_index=0|pts=125952|pts_time=2.856054|dts=125952|dts_time=2.856054|duration=1024|duration_time=0.023220|size=198|pos=25282|flags=K_ -packet|codec_type=audio|stream_index=0|pts=126976|pts_time=2.879274|dts=126976|dts_time=2.879274|duration=1024|duration_time=0.023220|size=183|pos=25480|flags=K_ -packet|codec_type=audio|stream_index=0|pts=128000|pts_time=2.902494|dts=128000|dts_time=2.902494|duration=1024|duration_time=0.023220|size=199|pos=25663|flags=K_ -packet|codec_type=audio|stream_index=0|pts=129024|pts_time=2.925714|dts=129024|dts_time=2.925714|duration=1024|duration_time=0.023220|size=196|pos=25862|flags=K_ -packet|codec_type=audio|stream_index=0|pts=130048|pts_time=2.948934|dts=130048|dts_time=2.948934|duration=1024|duration_time=0.023220|size=186|pos=26058|flags=K_ -packet|codec_type=audio|stream_index=0|pts=131072|pts_time=2.972154|dts=131072|dts_time=2.972154|duration=1024|duration_time=0.023220|size=200|pos=26244|flags=K_ -packet|codec_type=audio|stream_index=0|pts=132096|pts_time=2.995374|dts=132096|dts_time=2.995374|duration=1024|duration_time=0.023220|size=210|pos=26444|flags=K_ -packet|codec_type=audio|stream_index=0|pts=133120|pts_time=3.018594|dts=133120|dts_time=3.018594|duration=1024|duration_time=0.023220|size=196|pos=26654|flags=K_ -packet|codec_type=audio|stream_index=0|pts=134144|pts_time=3.041814|dts=134144|dts_time=3.041814|duration=1024|duration_time=0.023220|size=214|pos=26850|flags=K_ -packet|codec_type=audio|stream_index=0|pts=135168|pts_time=3.065034|dts=135168|dts_time=3.065034|duration=1024|duration_time=0.023220|size=185|pos=27064|flags=K_ -packet|codec_type=audio|stream_index=0|pts=136192|pts_time=3.088254|dts=136192|dts_time=3.088254|duration=1024|duration_time=0.023220|size=198|pos=27249|flags=K_ -packet|codec_type=audio|stream_index=0|pts=137216|pts_time=3.111474|dts=137216|dts_time=3.111474|duration=1024|duration_time=0.023220|size=200|pos=27447|flags=K_ -packet|codec_type=audio|stream_index=0|pts=138240|pts_time=3.134694|dts=138240|dts_time=3.134694|duration=1024|duration_time=0.023220|size=208|pos=27647|flags=K_ -packet|codec_type=audio|stream_index=0|pts=139264|pts_time=3.157914|dts=139264|dts_time=3.157914|duration=1024|duration_time=0.023220|size=212|pos=27855|flags=K_ -packet|codec_type=audio|stream_index=0|pts=140288|pts_time=3.181134|dts=140288|dts_time=3.181134|duration=1024|duration_time=0.023220|size=208|pos=28067|flags=K_ -packet|codec_type=audio|stream_index=0|pts=141312|pts_time=3.204354|dts=141312|dts_time=3.204354|duration=1024|duration_time=0.023220|size=192|pos=28275|flags=K_ -packet|codec_type=audio|stream_index=0|pts=142336|pts_time=3.227574|dts=142336|dts_time=3.227574|duration=1024|duration_time=0.023220|size=192|pos=28467|flags=K_ -packet|codec_type=audio|stream_index=0|pts=143360|pts_time=3.250794|dts=143360|dts_time=3.250794|duration=1024|duration_time=0.023220|size=211|pos=28659|flags=K_ -packet|codec_type=audio|stream_index=0|pts=144384|pts_time=3.274014|dts=144384|dts_time=3.274014|duration=1024|duration_time=0.023220|size=195|pos=28870|flags=K_ -packet|codec_type=audio|stream_index=0|pts=145408|pts_time=3.297234|dts=145408|dts_time=3.297234|duration=1024|duration_time=0.023220|size=208|pos=29065|flags=K_ -packet|codec_type=audio|stream_index=0|pts=146432|pts_time=3.320454|dts=146432|dts_time=3.320454|duration=1024|duration_time=0.023220|size=195|pos=29273|flags=K_ -packet|codec_type=audio|stream_index=0|pts=147456|pts_time=3.343673|dts=147456|dts_time=3.343673|duration=1024|duration_time=0.023220|size=204|pos=29468|flags=K_ -packet|codec_type=audio|stream_index=0|pts=148480|pts_time=3.366893|dts=148480|dts_time=3.366893|duration=1024|duration_time=0.023220|size=209|pos=29672|flags=K_ -packet|codec_type=audio|stream_index=0|pts=149504|pts_time=3.390113|dts=149504|dts_time=3.390113|duration=1024|duration_time=0.023220|size=195|pos=29881|flags=K_ -packet|codec_type=audio|stream_index=0|pts=150528|pts_time=3.413333|dts=150528|dts_time=3.413333|duration=1024|duration_time=0.023220|size=191|pos=30076|flags=K_ -packet|codec_type=audio|stream_index=0|pts=151552|pts_time=3.436553|dts=151552|dts_time=3.436553|duration=1024|duration_time=0.023220|size=210|pos=30267|flags=K_ -packet|codec_type=audio|stream_index=0|pts=152576|pts_time=3.459773|dts=152576|dts_time=3.459773|duration=1024|duration_time=0.023220|size=209|pos=30477|flags=K_ -packet|codec_type=audio|stream_index=0|pts=153600|pts_time=3.482993|dts=153600|dts_time=3.482993|duration=1024|duration_time=0.023220|size=175|pos=30686|flags=K_ -packet|codec_type=audio|stream_index=0|pts=154624|pts_time=3.506213|dts=154624|dts_time=3.506213|duration=1024|duration_time=0.023220|size=244|pos=30861|flags=K_ -packet|codec_type=audio|stream_index=0|pts=155648|pts_time=3.529433|dts=155648|dts_time=3.529433|duration=1024|duration_time=0.023220|size=177|pos=31105|flags=K_ -packet|codec_type=audio|stream_index=0|pts=156672|pts_time=3.552653|dts=156672|dts_time=3.552653|duration=1024|duration_time=0.023220|size=217|pos=31282|flags=K_ -packet|codec_type=audio|stream_index=0|pts=157696|pts_time=3.575873|dts=157696|dts_time=3.575873|duration=1024|duration_time=0.023220|size=182|pos=31499|flags=K_ -packet|codec_type=audio|stream_index=0|pts=158720|pts_time=3.599093|dts=158720|dts_time=3.599093|duration=1024|duration_time=0.023220|size=181|pos=31681|flags=K_ -packet|codec_type=audio|stream_index=0|pts=159744|pts_time=3.622313|dts=159744|dts_time=3.622313|duration=1024|duration_time=0.023220|size=203|pos=31862|flags=K_ -packet|codec_type=audio|stream_index=0|pts=160768|pts_time=3.645533|dts=160768|dts_time=3.645533|duration=1024|duration_time=0.023220|size=198|pos=32065|flags=K_ -packet|codec_type=audio|stream_index=0|pts=161792|pts_time=3.668753|dts=161792|dts_time=3.668753|duration=1024|duration_time=0.023220|size=217|pos=32263|flags=K_ -packet|codec_type=audio|stream_index=0|pts=162816|pts_time=3.691973|dts=162816|dts_time=3.691973|duration=1024|duration_time=0.023220|size=195|pos=32480|flags=K_ -packet|codec_type=audio|stream_index=0|pts=163840|pts_time=3.715193|dts=163840|dts_time=3.715193|duration=1024|duration_time=0.023220|size=198|pos=32675|flags=K_ -packet|codec_type=audio|stream_index=0|pts=164864|pts_time=3.738413|dts=164864|dts_time=3.738413|duration=1024|duration_time=0.023220|size=202|pos=32873|flags=K_ -packet|codec_type=audio|stream_index=0|pts=165888|pts_time=3.761633|dts=165888|dts_time=3.761633|duration=1024|duration_time=0.023220|size=185|pos=33075|flags=K_ -packet|codec_type=audio|stream_index=0|pts=166912|pts_time=3.784853|dts=166912|dts_time=3.784853|duration=1024|duration_time=0.023220|size=196|pos=33260|flags=K_ -packet|codec_type=audio|stream_index=0|pts=167936|pts_time=3.808073|dts=167936|dts_time=3.808073|duration=1024|duration_time=0.023220|size=226|pos=33456|flags=K_ -packet|codec_type=audio|stream_index=0|pts=168960|pts_time=3.831293|dts=168960|dts_time=3.831293|duration=1024|duration_time=0.023220|size=187|pos=33682|flags=K_ -packet|codec_type=audio|stream_index=0|pts=169984|pts_time=3.854512|dts=169984|dts_time=3.854512|duration=1024|duration_time=0.023220|size=193|pos=33869|flags=K_ -packet|codec_type=audio|stream_index=0|pts=171008|pts_time=3.877732|dts=171008|dts_time=3.877732|duration=1024|duration_time=0.023220|size=218|pos=34062|flags=K_ -packet|codec_type=audio|stream_index=0|pts=172032|pts_time=3.900952|dts=172032|dts_time=3.900952|duration=1024|duration_time=0.023220|size=200|pos=34280|flags=K_ -packet|codec_type=audio|stream_index=0|pts=173056|pts_time=3.924172|dts=173056|dts_time=3.924172|duration=1024|duration_time=0.023220|size=200|pos=34480|flags=K_ -packet|codec_type=audio|stream_index=0|pts=174080|pts_time=3.947392|dts=174080|dts_time=3.947392|duration=1024|duration_time=0.023220|size=198|pos=34680|flags=K_ -packet|codec_type=audio|stream_index=0|pts=175104|pts_time=3.970612|dts=175104|dts_time=3.970612|duration=1024|duration_time=0.023220|size=200|pos=34878|flags=K_ -packet|codec_type=audio|stream_index=0|pts=176128|pts_time=3.993832|dts=176128|dts_time=3.993832|duration=1024|duration_time=0.023220|size=197|pos=35078|flags=K_ -packet|codec_type=audio|stream_index=0|pts=177152|pts_time=4.017052|dts=177152|dts_time=4.017052|duration=1024|duration_time=0.023220|size=209|pos=35275|flags=K_ -packet|codec_type=audio|stream_index=0|pts=178176|pts_time=4.040272|dts=178176|dts_time=4.040272|duration=1024|duration_time=0.023220|size=205|pos=35484|flags=K_ -packet|codec_type=audio|stream_index=0|pts=179200|pts_time=4.063492|dts=179200|dts_time=4.063492|duration=1024|duration_time=0.023220|size=199|pos=35689|flags=K_ -packet|codec_type=audio|stream_index=0|pts=180224|pts_time=4.086712|dts=180224|dts_time=4.086712|duration=1024|duration_time=0.023220|size=192|pos=35888|flags=K_ -packet|codec_type=audio|stream_index=0|pts=181248|pts_time=4.109932|dts=181248|dts_time=4.109932|duration=1024|duration_time=0.023220|size=201|pos=36080|flags=K_ -packet|codec_type=audio|stream_index=0|pts=182272|pts_time=4.133152|dts=182272|dts_time=4.133152|duration=1024|duration_time=0.023220|size=200|pos=36281|flags=K_ -packet|codec_type=audio|stream_index=0|pts=183296|pts_time=4.156372|dts=183296|dts_time=4.156372|duration=1024|duration_time=0.023220|size=202|pos=36481|flags=K_ -packet|codec_type=audio|stream_index=0|pts=184320|pts_time=4.179592|dts=184320|dts_time=4.179592|duration=1024|duration_time=0.023220|size=196|pos=36683|flags=K_ -packet|codec_type=audio|stream_index=0|pts=185344|pts_time=4.202812|dts=185344|dts_time=4.202812|duration=1024|duration_time=0.023220|size=200|pos=36879|flags=K_ -packet|codec_type=audio|stream_index=0|pts=186368|pts_time=4.226032|dts=186368|dts_time=4.226032|duration=1024|duration_time=0.023220|size=209|pos=37079|flags=K_ -packet|codec_type=audio|stream_index=0|pts=187392|pts_time=4.249252|dts=187392|dts_time=4.249252|duration=1024|duration_time=0.023220|size=201|pos=37288|flags=K_ -packet|codec_type=audio|stream_index=0|pts=188416|pts_time=4.272472|dts=188416|dts_time=4.272472|duration=1024|duration_time=0.023220|size=201|pos=37489|flags=K_ -packet|codec_type=audio|stream_index=0|pts=189440|pts_time=4.295692|dts=189440|dts_time=4.295692|duration=1024|duration_time=0.023220|size=201|pos=37690|flags=K_ -packet|codec_type=audio|stream_index=0|pts=190464|pts_time=4.318912|dts=190464|dts_time=4.318912|duration=1024|duration_time=0.023220|size=199|pos=37891|flags=K_ -packet|codec_type=audio|stream_index=0|pts=191488|pts_time=4.342132|dts=191488|dts_time=4.342132|duration=1024|duration_time=0.023220|size=198|pos=38090|flags=K_ -packet|codec_type=audio|stream_index=0|pts=192512|pts_time=4.365351|dts=192512|dts_time=4.365351|duration=1024|duration_time=0.023220|size=205|pos=38288|flags=K_ -packet|codec_type=audio|stream_index=0|pts=193536|pts_time=4.388571|dts=193536|dts_time=4.388571|duration=1024|duration_time=0.023220|size=190|pos=38493|flags=K_ -packet|codec_type=audio|stream_index=0|pts=194560|pts_time=4.411791|dts=194560|dts_time=4.411791|duration=1024|duration_time=0.023220|size=207|pos=38683|flags=K_ -packet|codec_type=audio|stream_index=0|pts=195584|pts_time=4.435011|dts=195584|dts_time=4.435011|duration=1024|duration_time=0.023220|size=204|pos=38890|flags=K_ -packet|codec_type=audio|stream_index=0|pts=196608|pts_time=4.458231|dts=196608|dts_time=4.458231|duration=1024|duration_time=0.023220|size=192|pos=39094|flags=K_ -packet|codec_type=audio|stream_index=0|pts=197632|pts_time=4.481451|dts=197632|dts_time=4.481451|duration=1024|duration_time=0.023220|size=211|pos=39286|flags=K_ -packet|codec_type=audio|stream_index=0|pts=198656|pts_time=4.504671|dts=198656|dts_time=4.504671|duration=1024|duration_time=0.023220|size=195|pos=39497|flags=K_ -packet|codec_type=audio|stream_index=0|pts=199680|pts_time=4.527891|dts=199680|dts_time=4.527891|duration=1024|duration_time=0.023220|size=214|pos=39692|flags=K_ -packet|codec_type=audio|stream_index=0|pts=200704|pts_time=4.551111|dts=200704|dts_time=4.551111|duration=1024|duration_time=0.023220|size=195|pos=39906|flags=K_ -packet|codec_type=audio|stream_index=0|pts=201728|pts_time=4.574331|dts=201728|dts_time=4.574331|duration=1024|duration_time=0.023220|size=199|pos=40101|flags=K_ -packet|codec_type=audio|stream_index=0|pts=202752|pts_time=4.597551|dts=202752|dts_time=4.597551|duration=1024|duration_time=0.023220|size=183|pos=40300|flags=K_ -packet|codec_type=audio|stream_index=0|pts=203776|pts_time=4.620771|dts=203776|dts_time=4.620771|duration=1024|duration_time=0.023220|size=211|pos=40483|flags=K_ -packet|codec_type=audio|stream_index=0|pts=204800|pts_time=4.643991|dts=204800|dts_time=4.643991|duration=1024|duration_time=0.023220|size=200|pos=40694|flags=K_ -packet|codec_type=audio|stream_index=0|pts=205824|pts_time=4.667211|dts=205824|dts_time=4.667211|duration=1024|duration_time=0.023220|size=199|pos=40894|flags=K_ -packet|codec_type=audio|stream_index=0|pts=206848|pts_time=4.690431|dts=206848|dts_time=4.690431|duration=1024|duration_time=0.023220|size=213|pos=41093|flags=K_ -packet|codec_type=audio|stream_index=0|pts=207872|pts_time=4.713651|dts=207872|dts_time=4.713651|duration=1024|duration_time=0.023220|size=191|pos=41306|flags=K_ -packet|codec_type=audio|stream_index=0|pts=208896|pts_time=4.736871|dts=208896|dts_time=4.736871|duration=1024|duration_time=0.023220|size=211|pos=41497|flags=K_ -packet|codec_type=audio|stream_index=0|pts=209920|pts_time=4.760091|dts=209920|dts_time=4.760091|duration=1024|duration_time=0.023220|size=198|pos=41708|flags=K_ -packet|codec_type=audio|stream_index=0|pts=210944|pts_time=4.783311|dts=210944|dts_time=4.783311|duration=1024|duration_time=0.023220|size=203|pos=41906|flags=K_ -packet|codec_type=audio|stream_index=0|pts=211968|pts_time=4.806531|dts=211968|dts_time=4.806531|duration=1024|duration_time=0.023220|size=196|pos=42109|flags=K_ -packet|codec_type=audio|stream_index=0|pts=212992|pts_time=4.829751|dts=212992|dts_time=4.829751|duration=1024|duration_time=0.023220|size=197|pos=42305|flags=K_ -packet|codec_type=audio|stream_index=0|pts=214016|pts_time=4.852971|dts=214016|dts_time=4.852971|duration=1024|duration_time=0.023220|size=190|pos=42502|flags=K_ -packet|codec_type=audio|stream_index=0|pts=215040|pts_time=4.876190|dts=215040|dts_time=4.876190|duration=1024|duration_time=0.023220|size=208|pos=42692|flags=K_ -packet|codec_type=audio|stream_index=0|pts=216064|pts_time=4.899410|dts=216064|dts_time=4.899410|duration=1024|duration_time=0.023220|size=203|pos=42900|flags=K_ -packet|codec_type=audio|stream_index=0|pts=217088|pts_time=4.922630|dts=217088|dts_time=4.922630|duration=1024|duration_time=0.023220|size=198|pos=43103|flags=K_ -packet|codec_type=audio|stream_index=0|pts=218112|pts_time=4.945850|dts=218112|dts_time=4.945850|duration=1024|duration_time=0.023220|size=284|pos=43301|flags=K_ -packet|codec_type=audio|stream_index=0|pts=219136|pts_time=4.969070|dts=219136|dts_time=4.969070|duration=1364|duration_time=0.030930|size=5|pos=43585|flags=K_ +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__ +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=186|pos=698|flags=K__ +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=222|pos=884|flags=K__ +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=186|pos=1106|flags=K__ +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=206|pos=1292|flags=K__ +packet|codec_type=audio|stream_index=0|pts=5120|pts_time=0.116100|dts=5120|dts_time=0.116100|duration=1024|duration_time=0.023220|size=199|pos=1498|flags=K__ +packet|codec_type=audio|stream_index=0|pts=6144|pts_time=0.139320|dts=6144|dts_time=0.139320|duration=1024|duration_time=0.023220|size=236|pos=1697|flags=K__ +packet|codec_type=audio|stream_index=0|pts=7168|pts_time=0.162540|dts=7168|dts_time=0.162540|duration=1024|duration_time=0.023220|size=208|pos=1933|flags=K__ +packet|codec_type=audio|stream_index=0|pts=8192|pts_time=0.185760|dts=8192|dts_time=0.185760|duration=1024|duration_time=0.023220|size=238|pos=2141|flags=K__ +packet|codec_type=audio|stream_index=0|pts=9216|pts_time=0.208980|dts=9216|dts_time=0.208980|duration=1024|duration_time=0.023220|size=222|pos=2379|flags=K__ +packet|codec_type=audio|stream_index=0|pts=10240|pts_time=0.232200|dts=10240|dts_time=0.232200|duration=1024|duration_time=0.023220|size=211|pos=2601|flags=K__ +packet|codec_type=audio|stream_index=0|pts=11264|pts_time=0.255420|dts=11264|dts_time=0.255420|duration=1024|duration_time=0.023220|size=153|pos=2812|flags=K__ +packet|codec_type=audio|stream_index=0|pts=12288|pts_time=0.278639|dts=12288|dts_time=0.278639|duration=1024|duration_time=0.023220|size=191|pos=2965|flags=K__ +packet|codec_type=audio|stream_index=0|pts=13312|pts_time=0.301859|dts=13312|dts_time=0.301859|duration=1024|duration_time=0.023220|size=208|pos=3156|flags=K__ +packet|codec_type=audio|stream_index=0|pts=14336|pts_time=0.325079|dts=14336|dts_time=0.325079|duration=1024|duration_time=0.023220|size=188|pos=3364|flags=K__ +packet|codec_type=audio|stream_index=0|pts=15360|pts_time=0.348299|dts=15360|dts_time=0.348299|duration=1024|duration_time=0.023220|size=170|pos=3552|flags=K__ +packet|codec_type=audio|stream_index=0|pts=16384|pts_time=0.371519|dts=16384|dts_time=0.371519|duration=1024|duration_time=0.023220|size=221|pos=3722|flags=K__ +packet|codec_type=audio|stream_index=0|pts=17408|pts_time=0.394739|dts=17408|dts_time=0.394739|duration=1024|duration_time=0.023220|size=247|pos=3943|flags=K__ +packet|codec_type=audio|stream_index=0|pts=18432|pts_time=0.417959|dts=18432|dts_time=0.417959|duration=1024|duration_time=0.023220|size=202|pos=4190|flags=K__ +packet|codec_type=audio|stream_index=0|pts=19456|pts_time=0.441179|dts=19456|dts_time=0.441179|duration=1024|duration_time=0.023220|size=186|pos=4392|flags=K__ +packet|codec_type=audio|stream_index=0|pts=20480|pts_time=0.464399|dts=20480|dts_time=0.464399|duration=1024|duration_time=0.023220|size=196|pos=4578|flags=K__ +packet|codec_type=audio|stream_index=0|pts=21504|pts_time=0.487619|dts=21504|dts_time=0.487619|duration=1024|duration_time=0.023220|size=200|pos=4774|flags=K__ +packet|codec_type=audio|stream_index=0|pts=22528|pts_time=0.510839|dts=22528|dts_time=0.510839|duration=1024|duration_time=0.023220|size=170|pos=4974|flags=K__ +packet|codec_type=audio|stream_index=0|pts=23552|pts_time=0.534059|dts=23552|dts_time=0.534059|duration=1024|duration_time=0.023220|size=172|pos=5144|flags=K__ +packet|codec_type=audio|stream_index=0|pts=24576|pts_time=0.557279|dts=24576|dts_time=0.557279|duration=1024|duration_time=0.023220|size=206|pos=5316|flags=K__ +packet|codec_type=audio|stream_index=0|pts=25600|pts_time=0.580499|dts=25600|dts_time=0.580499|duration=1024|duration_time=0.023220|size=208|pos=5522|flags=K__ +packet|codec_type=audio|stream_index=0|pts=26624|pts_time=0.603719|dts=26624|dts_time=0.603719|duration=1024|duration_time=0.023220|size=217|pos=5730|flags=K__ +packet|codec_type=audio|stream_index=0|pts=27648|pts_time=0.626939|dts=27648|dts_time=0.626939|duration=1024|duration_time=0.023220|size=252|pos=5947|flags=K__ +packet|codec_type=audio|stream_index=0|pts=28672|pts_time=0.650159|dts=28672|dts_time=0.650159|duration=1024|duration_time=0.023220|size=171|pos=6199|flags=K__ +packet|codec_type=audio|stream_index=0|pts=29696|pts_time=0.673379|dts=29696|dts_time=0.673379|duration=1024|duration_time=0.023220|size=206|pos=6370|flags=K__ +packet|codec_type=audio|stream_index=0|pts=30720|pts_time=0.696599|dts=30720|dts_time=0.696599|duration=1024|duration_time=0.023220|size=237|pos=6576|flags=K__ +packet|codec_type=audio|stream_index=0|pts=31744|pts_time=0.719819|dts=31744|dts_time=0.719819|duration=1024|duration_time=0.023220|size=210|pos=6813|flags=K__ +packet|codec_type=audio|stream_index=0|pts=32768|pts_time=0.743039|dts=32768|dts_time=0.743039|duration=1024|duration_time=0.023220|size=166|pos=7023|flags=K__ +packet|codec_type=audio|stream_index=0|pts=33792|pts_time=0.766259|dts=33792|dts_time=0.766259|duration=1024|duration_time=0.023220|size=166|pos=7189|flags=K__ +packet|codec_type=audio|stream_index=0|pts=34816|pts_time=0.789478|dts=34816|dts_time=0.789478|duration=1024|duration_time=0.023220|size=177|pos=7355|flags=K__ +packet|codec_type=audio|stream_index=0|pts=35840|pts_time=0.812698|dts=35840|dts_time=0.812698|duration=1024|duration_time=0.023220|size=188|pos=7532|flags=K__ +packet|codec_type=audio|stream_index=0|pts=36864|pts_time=0.835918|dts=36864|dts_time=0.835918|duration=1024|duration_time=0.023220|size=193|pos=7720|flags=K__ +packet|codec_type=audio|stream_index=0|pts=37888|pts_time=0.859138|dts=37888|dts_time=0.859138|duration=1024|duration_time=0.023220|size=195|pos=7913|flags=K__ +packet|codec_type=audio|stream_index=0|pts=38912|pts_time=0.882358|dts=38912|dts_time=0.882358|duration=1024|duration_time=0.023220|size=211|pos=8108|flags=K__ +packet|codec_type=audio|stream_index=0|pts=39936|pts_time=0.905578|dts=39936|dts_time=0.905578|duration=1024|duration_time=0.023220|size=249|pos=8319|flags=K__ +packet|codec_type=audio|stream_index=0|pts=40960|pts_time=0.928798|dts=40960|dts_time=0.928798|duration=1024|duration_time=0.023220|size=223|pos=8568|flags=K__ +packet|codec_type=audio|stream_index=0|pts=41984|pts_time=0.952018|dts=41984|dts_time=0.952018|duration=1024|duration_time=0.023220|size=230|pos=8791|flags=K__ +packet|codec_type=audio|stream_index=0|pts=43008|pts_time=0.975238|dts=43008|dts_time=0.975238|duration=1024|duration_time=0.023220|size=203|pos=9021|flags=K__ +packet|codec_type=audio|stream_index=0|pts=44032|pts_time=0.998458|dts=44032|dts_time=0.998458|duration=1024|duration_time=0.023220|size=180|pos=9224|flags=K__ +packet|codec_type=audio|stream_index=0|pts=45056|pts_time=1.021678|dts=45056|dts_time=1.021678|duration=1024|duration_time=0.023220|size=172|pos=9404|flags=K__ +packet|codec_type=audio|stream_index=0|pts=46080|pts_time=1.044898|dts=46080|dts_time=1.044898|duration=1024|duration_time=0.023220|size=240|pos=9576|flags=K__ +packet|codec_type=audio|stream_index=0|pts=47104|pts_time=1.068118|dts=47104|dts_time=1.068118|duration=1024|duration_time=0.023220|size=179|pos=9816|flags=K__ +packet|codec_type=audio|stream_index=0|pts=48128|pts_time=1.091338|dts=48128|dts_time=1.091338|duration=1024|duration_time=0.023220|size=191|pos=9995|flags=K__ +packet|codec_type=audio|stream_index=0|pts=49152|pts_time=1.114558|dts=49152|dts_time=1.114558|duration=1024|duration_time=0.023220|size=184|pos=10186|flags=K__ +packet|codec_type=audio|stream_index=0|pts=50176|pts_time=1.137778|dts=50176|dts_time=1.137778|duration=1024|duration_time=0.023220|size=214|pos=10370|flags=K__ +packet|codec_type=audio|stream_index=0|pts=51200|pts_time=1.160998|dts=51200|dts_time=1.160998|duration=1024|duration_time=0.023220|size=194|pos=10584|flags=K__ +packet|codec_type=audio|stream_index=0|pts=52224|pts_time=1.184218|dts=52224|dts_time=1.184218|duration=1024|duration_time=0.023220|size=235|pos=10778|flags=K__ +packet|codec_type=audio|stream_index=0|pts=53248|pts_time=1.207438|dts=53248|dts_time=1.207438|duration=1024|duration_time=0.023220|size=195|pos=11013|flags=K__ +packet|codec_type=audio|stream_index=0|pts=54272|pts_time=1.230658|dts=54272|dts_time=1.230658|duration=1024|duration_time=0.023220|size=220|pos=11208|flags=K__ +packet|codec_type=audio|stream_index=0|pts=55296|pts_time=1.253878|dts=55296|dts_time=1.253878|duration=1024|duration_time=0.023220|size=187|pos=11428|flags=K__ +packet|codec_type=audio|stream_index=0|pts=56320|pts_time=1.277098|dts=56320|dts_time=1.277098|duration=1024|duration_time=0.023220|size=238|pos=11615|flags=K__ +packet|codec_type=audio|stream_index=0|pts=57344|pts_time=1.300317|dts=57344|dts_time=1.300317|duration=1024|duration_time=0.023220|size=175|pos=11853|flags=K__ +packet|codec_type=audio|stream_index=0|pts=58368|pts_time=1.323537|dts=58368|dts_time=1.323537|duration=1024|duration_time=0.023220|size=178|pos=12028|flags=K__ +packet|codec_type=audio|stream_index=0|pts=59392|pts_time=1.346757|dts=59392|dts_time=1.346757|duration=1024|duration_time=0.023220|size=219|pos=12206|flags=K__ +packet|codec_type=audio|stream_index=0|pts=60416|pts_time=1.369977|dts=60416|dts_time=1.369977|duration=1024|duration_time=0.023220|size=179|pos=12425|flags=K__ +packet|codec_type=audio|stream_index=0|pts=61440|pts_time=1.393197|dts=61440|dts_time=1.393197|duration=1024|duration_time=0.023220|size=193|pos=12604|flags=K__ +packet|codec_type=audio|stream_index=0|pts=62464|pts_time=1.416417|dts=62464|dts_time=1.416417|duration=1024|duration_time=0.023220|size=200|pos=12797|flags=K__ +packet|codec_type=audio|stream_index=0|pts=63488|pts_time=1.439637|dts=63488|dts_time=1.439637|duration=1024|duration_time=0.023220|size=218|pos=12997|flags=K__ +packet|codec_type=audio|stream_index=0|pts=64512|pts_time=1.462857|dts=64512|dts_time=1.462857|duration=1024|duration_time=0.023220|size=215|pos=13215|flags=K__ +packet|codec_type=audio|stream_index=0|pts=65536|pts_time=1.486077|dts=65536|dts_time=1.486077|duration=1024|duration_time=0.023220|size=209|pos=13430|flags=K__ +packet|codec_type=audio|stream_index=0|pts=66560|pts_time=1.509297|dts=66560|dts_time=1.509297|duration=1024|duration_time=0.023220|size=171|pos=13639|flags=K__ +packet|codec_type=audio|stream_index=0|pts=67584|pts_time=1.532517|dts=67584|dts_time=1.532517|duration=1024|duration_time=0.023220|size=179|pos=13810|flags=K__ +packet|codec_type=audio|stream_index=0|pts=68608|pts_time=1.555737|dts=68608|dts_time=1.555737|duration=1024|duration_time=0.023220|size=185|pos=13989|flags=K__ +packet|codec_type=audio|stream_index=0|pts=69632|pts_time=1.578957|dts=69632|dts_time=1.578957|duration=1024|duration_time=0.023220|size=225|pos=14174|flags=K__ +packet|codec_type=audio|stream_index=0|pts=70656|pts_time=1.602177|dts=70656|dts_time=1.602177|duration=1024|duration_time=0.023220|size=221|pos=14399|flags=K__ +packet|codec_type=audio|stream_index=0|pts=71680|pts_time=1.625397|dts=71680|dts_time=1.625397|duration=1024|duration_time=0.023220|size=201|pos=14620|flags=K__ +packet|codec_type=audio|stream_index=0|pts=72704|pts_time=1.648617|dts=72704|dts_time=1.648617|duration=1024|duration_time=0.023220|size=206|pos=14821|flags=K__ +packet|codec_type=audio|stream_index=0|pts=73728|pts_time=1.671837|dts=73728|dts_time=1.671837|duration=1024|duration_time=0.023220|size=182|pos=15027|flags=K__ +packet|codec_type=audio|stream_index=0|pts=74752|pts_time=1.695057|dts=74752|dts_time=1.695057|duration=1024|duration_time=0.023220|size=176|pos=15209|flags=K__ +packet|codec_type=audio|stream_index=0|pts=75776|pts_time=1.718277|dts=75776|dts_time=1.718277|duration=1024|duration_time=0.023220|size=233|pos=15385|flags=K__ +packet|codec_type=audio|stream_index=0|pts=76800|pts_time=1.741497|dts=76800|dts_time=1.741497|duration=1024|duration_time=0.023220|size=199|pos=15618|flags=K__ +packet|codec_type=audio|stream_index=0|pts=77824|pts_time=1.764717|dts=77824|dts_time=1.764717|duration=1024|duration_time=0.023220|size=220|pos=15817|flags=K__ +packet|codec_type=audio|stream_index=0|pts=78848|pts_time=1.787937|dts=78848|dts_time=1.787937|duration=1024|duration_time=0.023220|size=190|pos=16037|flags=K__ +packet|codec_type=audio|stream_index=0|pts=79872|pts_time=1.811156|dts=79872|dts_time=1.811156|duration=1024|duration_time=0.023220|size=210|pos=16227|flags=K__ +packet|codec_type=audio|stream_index=0|pts=80896|pts_time=1.834376|dts=80896|dts_time=1.834376|duration=1024|duration_time=0.023220|size=204|pos=16437|flags=K__ +packet|codec_type=audio|stream_index=0|pts=81920|pts_time=1.857596|dts=81920|dts_time=1.857596|duration=1024|duration_time=0.023220|size=171|pos=16641|flags=K__ +packet|codec_type=audio|stream_index=0|pts=82944|pts_time=1.880816|dts=82944|dts_time=1.880816|duration=1024|duration_time=0.023220|size=167|pos=16812|flags=K__ +packet|codec_type=audio|stream_index=0|pts=83968|pts_time=1.904036|dts=83968|dts_time=1.904036|duration=1024|duration_time=0.023220|size=200|pos=16979|flags=K__ +packet|codec_type=audio|stream_index=0|pts=84992|pts_time=1.927256|dts=84992|dts_time=1.927256|duration=1024|duration_time=0.023220|size=254|pos=17179|flags=K__ +packet|codec_type=audio|stream_index=0|pts=86016|pts_time=1.950476|dts=86016|dts_time=1.950476|duration=1024|duration_time=0.023220|size=205|pos=17433|flags=K__ +packet|codec_type=audio|stream_index=0|pts=87040|pts_time=1.973696|dts=87040|dts_time=1.973696|duration=1024|duration_time=0.023220|size=196|pos=17638|flags=K__ +packet|codec_type=audio|stream_index=0|pts=88064|pts_time=1.996916|dts=88064|dts_time=1.996916|duration=1024|duration_time=0.023220|size=190|pos=17834|flags=K__ +packet|codec_type=audio|stream_index=0|pts=89088|pts_time=2.020136|dts=89088|dts_time=2.020136|duration=1024|duration_time=0.023220|size=197|pos=18024|flags=K__ +packet|codec_type=audio|stream_index=0|pts=90112|pts_time=2.043356|dts=90112|dts_time=2.043356|duration=1024|duration_time=0.023220|size=186|pos=18221|flags=K__ +packet|codec_type=audio|stream_index=0|pts=91136|pts_time=2.066576|dts=91136|dts_time=2.066576|duration=1024|duration_time=0.023220|size=194|pos=18407|flags=K__ +packet|codec_type=audio|stream_index=0|pts=92160|pts_time=2.089796|dts=92160|dts_time=2.089796|duration=1024|duration_time=0.023220|size=227|pos=18601|flags=K__ +packet|codec_type=audio|stream_index=0|pts=93184|pts_time=2.113016|dts=93184|dts_time=2.113016|duration=1024|duration_time=0.023220|size=195|pos=18828|flags=K__ +packet|codec_type=audio|stream_index=0|pts=94208|pts_time=2.136236|dts=94208|dts_time=2.136236|duration=1024|duration_time=0.023220|size=228|pos=19023|flags=K__ +packet|codec_type=audio|stream_index=0|pts=95232|pts_time=2.159456|dts=95232|dts_time=2.159456|duration=1024|duration_time=0.023220|size=196|pos=19251|flags=K__ +packet|codec_type=audio|stream_index=0|pts=96256|pts_time=2.182676|dts=96256|dts_time=2.182676|duration=1024|duration_time=0.023220|size=197|pos=19447|flags=K__ +packet|codec_type=audio|stream_index=0|pts=97280|pts_time=2.205896|dts=97280|dts_time=2.205896|duration=1024|duration_time=0.023220|size=186|pos=19644|flags=K__ +packet|codec_type=audio|stream_index=0|pts=98304|pts_time=2.229116|dts=98304|dts_time=2.229116|duration=1024|duration_time=0.023220|size=191|pos=19830|flags=K__ +packet|codec_type=audio|stream_index=0|pts=99328|pts_time=2.252336|dts=99328|dts_time=2.252336|duration=1024|duration_time=0.023220|size=215|pos=20021|flags=K__ +packet|codec_type=audio|stream_index=0|pts=100352|pts_time=2.275556|dts=100352|dts_time=2.275556|duration=1024|duration_time=0.023220|size=203|pos=20236|flags=K__ +packet|codec_type=audio|stream_index=0|pts=101376|pts_time=2.298776|dts=101376|dts_time=2.298776|duration=1024|duration_time=0.023220|size=205|pos=20439|flags=K__ +packet|codec_type=audio|stream_index=0|pts=102400|pts_time=2.321995|dts=102400|dts_time=2.321995|duration=1024|duration_time=0.023220|size=205|pos=20644|flags=K__ +packet|codec_type=audio|stream_index=0|pts=103424|pts_time=2.345215|dts=103424|dts_time=2.345215|duration=1024|duration_time=0.023220|size=213|pos=20849|flags=K__ +packet|codec_type=audio|stream_index=0|pts=104448|pts_time=2.368435|dts=104448|dts_time=2.368435|duration=1024|duration_time=0.023220|size=198|pos=21062|flags=K__ +packet|codec_type=audio|stream_index=0|pts=105472|pts_time=2.391655|dts=105472|dts_time=2.391655|duration=1024|duration_time=0.023220|size=178|pos=21260|flags=K__ +packet|codec_type=audio|stream_index=0|pts=106496|pts_time=2.414875|dts=106496|dts_time=2.414875|duration=1024|duration_time=0.023220|size=195|pos=21438|flags=K__ +packet|codec_type=audio|stream_index=0|pts=107520|pts_time=2.438095|dts=107520|dts_time=2.438095|duration=1024|duration_time=0.023220|size=227|pos=21633|flags=K__ +packet|codec_type=audio|stream_index=0|pts=108544|pts_time=2.461315|dts=108544|dts_time=2.461315|duration=1024|duration_time=0.023220|size=185|pos=21860|flags=K__ +packet|codec_type=audio|stream_index=0|pts=109568|pts_time=2.484535|dts=109568|dts_time=2.484535|duration=1024|duration_time=0.023220|size=206|pos=22045|flags=K__ +packet|codec_type=audio|stream_index=0|pts=110592|pts_time=2.507755|dts=110592|dts_time=2.507755|duration=1024|duration_time=0.023220|size=183|pos=22251|flags=K__ +packet|codec_type=audio|stream_index=0|pts=111616|pts_time=2.530975|dts=111616|dts_time=2.530975|duration=1024|duration_time=0.023220|size=208|pos=22434|flags=K__ +packet|codec_type=audio|stream_index=0|pts=112640|pts_time=2.554195|dts=112640|dts_time=2.554195|duration=1024|duration_time=0.023220|size=204|pos=22642|flags=K__ +packet|codec_type=audio|stream_index=0|pts=113664|pts_time=2.577415|dts=113664|dts_time=2.577415|duration=1024|duration_time=0.023220|size=192|pos=22846|flags=K__ +packet|codec_type=audio|stream_index=0|pts=114688|pts_time=2.600635|dts=114688|dts_time=2.600635|duration=1024|duration_time=0.023220|size=190|pos=23038|flags=K__ +packet|codec_type=audio|stream_index=0|pts=115712|pts_time=2.623855|dts=115712|dts_time=2.623855|duration=1024|duration_time=0.023220|size=199|pos=23228|flags=K__ +packet|codec_type=audio|stream_index=0|pts=116736|pts_time=2.647075|dts=116736|dts_time=2.647075|duration=1024|duration_time=0.023220|size=229|pos=23427|flags=K__ +packet|codec_type=audio|stream_index=0|pts=117760|pts_time=2.670295|dts=117760|dts_time=2.670295|duration=1024|duration_time=0.023220|size=208|pos=23656|flags=K__ +packet|codec_type=audio|stream_index=0|pts=118784|pts_time=2.693515|dts=118784|dts_time=2.693515|duration=1024|duration_time=0.023220|size=195|pos=23864|flags=K__ +packet|codec_type=audio|stream_index=0|pts=119808|pts_time=2.716735|dts=119808|dts_time=2.716735|duration=1024|duration_time=0.023220|size=190|pos=24059|flags=K__ +packet|codec_type=audio|stream_index=0|pts=120832|pts_time=2.739955|dts=120832|dts_time=2.739955|duration=1024|duration_time=0.023220|size=190|pos=24249|flags=K__ +packet|codec_type=audio|stream_index=0|pts=121856|pts_time=2.763175|dts=121856|dts_time=2.763175|duration=1024|duration_time=0.023220|size=192|pos=24439|flags=K__ +packet|codec_type=audio|stream_index=0|pts=122880|pts_time=2.786395|dts=122880|dts_time=2.786395|duration=1024|duration_time=0.023220|size=226|pos=24631|flags=K__ +packet|codec_type=audio|stream_index=0|pts=123904|pts_time=2.809615|dts=123904|dts_time=2.809615|duration=1024|duration_time=0.023220|size=195|pos=24857|flags=K__ +packet|codec_type=audio|stream_index=0|pts=124928|pts_time=2.832834|dts=124928|dts_time=2.832834|duration=1024|duration_time=0.023220|size=230|pos=25052|flags=K__ +packet|codec_type=audio|stream_index=0|pts=125952|pts_time=2.856054|dts=125952|dts_time=2.856054|duration=1024|duration_time=0.023220|size=198|pos=25282|flags=K__ +packet|codec_type=audio|stream_index=0|pts=126976|pts_time=2.879274|dts=126976|dts_time=2.879274|duration=1024|duration_time=0.023220|size=183|pos=25480|flags=K__ +packet|codec_type=audio|stream_index=0|pts=128000|pts_time=2.902494|dts=128000|dts_time=2.902494|duration=1024|duration_time=0.023220|size=199|pos=25663|flags=K__ +packet|codec_type=audio|stream_index=0|pts=129024|pts_time=2.925714|dts=129024|dts_time=2.925714|duration=1024|duration_time=0.023220|size=196|pos=25862|flags=K__ +packet|codec_type=audio|stream_index=0|pts=130048|pts_time=2.948934|dts=130048|dts_time=2.948934|duration=1024|duration_time=0.023220|size=186|pos=26058|flags=K__ +packet|codec_type=audio|stream_index=0|pts=131072|pts_time=2.972154|dts=131072|dts_time=2.972154|duration=1024|duration_time=0.023220|size=200|pos=26244|flags=K__ +packet|codec_type=audio|stream_index=0|pts=132096|pts_time=2.995374|dts=132096|dts_time=2.995374|duration=1024|duration_time=0.023220|size=210|pos=26444|flags=K__ +packet|codec_type=audio|stream_index=0|pts=133120|pts_time=3.018594|dts=133120|dts_time=3.018594|duration=1024|duration_time=0.023220|size=196|pos=26654|flags=K__ +packet|codec_type=audio|stream_index=0|pts=134144|pts_time=3.041814|dts=134144|dts_time=3.041814|duration=1024|duration_time=0.023220|size=214|pos=26850|flags=K__ +packet|codec_type=audio|stream_index=0|pts=135168|pts_time=3.065034|dts=135168|dts_time=3.065034|duration=1024|duration_time=0.023220|size=185|pos=27064|flags=K__ +packet|codec_type=audio|stream_index=0|pts=136192|pts_time=3.088254|dts=136192|dts_time=3.088254|duration=1024|duration_time=0.023220|size=198|pos=27249|flags=K__ +packet|codec_type=audio|stream_index=0|pts=137216|pts_time=3.111474|dts=137216|dts_time=3.111474|duration=1024|duration_time=0.023220|size=200|pos=27447|flags=K__ +packet|codec_type=audio|stream_index=0|pts=138240|pts_time=3.134694|dts=138240|dts_time=3.134694|duration=1024|duration_time=0.023220|size=208|pos=27647|flags=K__ +packet|codec_type=audio|stream_index=0|pts=139264|pts_time=3.157914|dts=139264|dts_time=3.157914|duration=1024|duration_time=0.023220|size=212|pos=27855|flags=K__ +packet|codec_type=audio|stream_index=0|pts=140288|pts_time=3.181134|dts=140288|dts_time=3.181134|duration=1024|duration_time=0.023220|size=208|pos=28067|flags=K__ +packet|codec_type=audio|stream_index=0|pts=141312|pts_time=3.204354|dts=141312|dts_time=3.204354|duration=1024|duration_time=0.023220|size=192|pos=28275|flags=K__ +packet|codec_type=audio|stream_index=0|pts=142336|pts_time=3.227574|dts=142336|dts_time=3.227574|duration=1024|duration_time=0.023220|size=192|pos=28467|flags=K__ +packet|codec_type=audio|stream_index=0|pts=143360|pts_time=3.250794|dts=143360|dts_time=3.250794|duration=1024|duration_time=0.023220|size=211|pos=28659|flags=K__ +packet|codec_type=audio|stream_index=0|pts=144384|pts_time=3.274014|dts=144384|dts_time=3.274014|duration=1024|duration_time=0.023220|size=195|pos=28870|flags=K__ +packet|codec_type=audio|stream_index=0|pts=145408|pts_time=3.297234|dts=145408|dts_time=3.297234|duration=1024|duration_time=0.023220|size=208|pos=29065|flags=K__ +packet|codec_type=audio|stream_index=0|pts=146432|pts_time=3.320454|dts=146432|dts_time=3.320454|duration=1024|duration_time=0.023220|size=195|pos=29273|flags=K__ +packet|codec_type=audio|stream_index=0|pts=147456|pts_time=3.343673|dts=147456|dts_time=3.343673|duration=1024|duration_time=0.023220|size=204|pos=29468|flags=K__ +packet|codec_type=audio|stream_index=0|pts=148480|pts_time=3.366893|dts=148480|dts_time=3.366893|duration=1024|duration_time=0.023220|size=209|pos=29672|flags=K__ +packet|codec_type=audio|stream_index=0|pts=149504|pts_time=3.390113|dts=149504|dts_time=3.390113|duration=1024|duration_time=0.023220|size=195|pos=29881|flags=K__ +packet|codec_type=audio|stream_index=0|pts=150528|pts_time=3.413333|dts=150528|dts_time=3.413333|duration=1024|duration_time=0.023220|size=191|pos=30076|flags=K__ +packet|codec_type=audio|stream_index=0|pts=151552|pts_time=3.436553|dts=151552|dts_time=3.436553|duration=1024|duration_time=0.023220|size=210|pos=30267|flags=K__ +packet|codec_type=audio|stream_index=0|pts=152576|pts_time=3.459773|dts=152576|dts_time=3.459773|duration=1024|duration_time=0.023220|size=209|pos=30477|flags=K__ +packet|codec_type=audio|stream_index=0|pts=153600|pts_time=3.482993|dts=153600|dts_time=3.482993|duration=1024|duration_time=0.023220|size=175|pos=30686|flags=K__ +packet|codec_type=audio|stream_index=0|pts=154624|pts_time=3.506213|dts=154624|dts_time=3.506213|duration=1024|duration_time=0.023220|size=244|pos=30861|flags=K__ +packet|codec_type=audio|stream_index=0|pts=155648|pts_time=3.529433|dts=155648|dts_time=3.529433|duration=1024|duration_time=0.023220|size=177|pos=31105|flags=K__ +packet|codec_type=audio|stream_index=0|pts=156672|pts_time=3.552653|dts=156672|dts_time=3.552653|duration=1024|duration_time=0.023220|size=217|pos=31282|flags=K__ +packet|codec_type=audio|stream_index=0|pts=157696|pts_time=3.575873|dts=157696|dts_time=3.575873|duration=1024|duration_time=0.023220|size=182|pos=31499|flags=K__ +packet|codec_type=audio|stream_index=0|pts=158720|pts_time=3.599093|dts=158720|dts_time=3.599093|duration=1024|duration_time=0.023220|size=181|pos=31681|flags=K__ +packet|codec_type=audio|stream_index=0|pts=159744|pts_time=3.622313|dts=159744|dts_time=3.622313|duration=1024|duration_time=0.023220|size=203|pos=31862|flags=K__ +packet|codec_type=audio|stream_index=0|pts=160768|pts_time=3.645533|dts=160768|dts_time=3.645533|duration=1024|duration_time=0.023220|size=198|pos=32065|flags=K__ +packet|codec_type=audio|stream_index=0|pts=161792|pts_time=3.668753|dts=161792|dts_time=3.668753|duration=1024|duration_time=0.023220|size=217|pos=32263|flags=K__ +packet|codec_type=audio|stream_index=0|pts=162816|pts_time=3.691973|dts=162816|dts_time=3.691973|duration=1024|duration_time=0.023220|size=195|pos=32480|flags=K__ +packet|codec_type=audio|stream_index=0|pts=163840|pts_time=3.715193|dts=163840|dts_time=3.715193|duration=1024|duration_time=0.023220|size=198|pos=32675|flags=K__ +packet|codec_type=audio|stream_index=0|pts=164864|pts_time=3.738413|dts=164864|dts_time=3.738413|duration=1024|duration_time=0.023220|size=202|pos=32873|flags=K__ +packet|codec_type=audio|stream_index=0|pts=165888|pts_time=3.761633|dts=165888|dts_time=3.761633|duration=1024|duration_time=0.023220|size=185|pos=33075|flags=K__ +packet|codec_type=audio|stream_index=0|pts=166912|pts_time=3.784853|dts=166912|dts_time=3.784853|duration=1024|duration_time=0.023220|size=196|pos=33260|flags=K__ +packet|codec_type=audio|stream_index=0|pts=167936|pts_time=3.808073|dts=167936|dts_time=3.808073|duration=1024|duration_time=0.023220|size=226|pos=33456|flags=K__ +packet|codec_type=audio|stream_index=0|pts=168960|pts_time=3.831293|dts=168960|dts_time=3.831293|duration=1024|duration_time=0.023220|size=187|pos=33682|flags=K__ +packet|codec_type=audio|stream_index=0|pts=169984|pts_time=3.854512|dts=169984|dts_time=3.854512|duration=1024|duration_time=0.023220|size=193|pos=33869|flags=K__ +packet|codec_type=audio|stream_index=0|pts=171008|pts_time=3.877732|dts=171008|dts_time=3.877732|duration=1024|duration_time=0.023220|size=218|pos=34062|flags=K__ +packet|codec_type=audio|stream_index=0|pts=172032|pts_time=3.900952|dts=172032|dts_time=3.900952|duration=1024|duration_time=0.023220|size=200|pos=34280|flags=K__ +packet|codec_type=audio|stream_index=0|pts=173056|pts_time=3.924172|dts=173056|dts_time=3.924172|duration=1024|duration_time=0.023220|size=200|pos=34480|flags=K__ +packet|codec_type=audio|stream_index=0|pts=174080|pts_time=3.947392|dts=174080|dts_time=3.947392|duration=1024|duration_time=0.023220|size=198|pos=34680|flags=K__ +packet|codec_type=audio|stream_index=0|pts=175104|pts_time=3.970612|dts=175104|dts_time=3.970612|duration=1024|duration_time=0.023220|size=200|pos=34878|flags=K__ +packet|codec_type=audio|stream_index=0|pts=176128|pts_time=3.993832|dts=176128|dts_time=3.993832|duration=1024|duration_time=0.023220|size=197|pos=35078|flags=K__ +packet|codec_type=audio|stream_index=0|pts=177152|pts_time=4.017052|dts=177152|dts_time=4.017052|duration=1024|duration_time=0.023220|size=209|pos=35275|flags=K__ +packet|codec_type=audio|stream_index=0|pts=178176|pts_time=4.040272|dts=178176|dts_time=4.040272|duration=1024|duration_time=0.023220|size=205|pos=35484|flags=K__ +packet|codec_type=audio|stream_index=0|pts=179200|pts_time=4.063492|dts=179200|dts_time=4.063492|duration=1024|duration_time=0.023220|size=199|pos=35689|flags=K__ +packet|codec_type=audio|stream_index=0|pts=180224|pts_time=4.086712|dts=180224|dts_time=4.086712|duration=1024|duration_time=0.023220|size=192|pos=35888|flags=K__ +packet|codec_type=audio|stream_index=0|pts=181248|pts_time=4.109932|dts=181248|dts_time=4.109932|duration=1024|duration_time=0.023220|size=201|pos=36080|flags=K__ +packet|codec_type=audio|stream_index=0|pts=182272|pts_time=4.133152|dts=182272|dts_time=4.133152|duration=1024|duration_time=0.023220|size=200|pos=36281|flags=K__ +packet|codec_type=audio|stream_index=0|pts=183296|pts_time=4.156372|dts=183296|dts_time=4.156372|duration=1024|duration_time=0.023220|size=202|pos=36481|flags=K__ +packet|codec_type=audio|stream_index=0|pts=184320|pts_time=4.179592|dts=184320|dts_time=4.179592|duration=1024|duration_time=0.023220|size=196|pos=36683|flags=K__ +packet|codec_type=audio|stream_index=0|pts=185344|pts_time=4.202812|dts=185344|dts_time=4.202812|duration=1024|duration_time=0.023220|size=200|pos=36879|flags=K__ +packet|codec_type=audio|stream_index=0|pts=186368|pts_time=4.226032|dts=186368|dts_time=4.226032|duration=1024|duration_time=0.023220|size=209|pos=37079|flags=K__ +packet|codec_type=audio|stream_index=0|pts=187392|pts_time=4.249252|dts=187392|dts_time=4.249252|duration=1024|duration_time=0.023220|size=201|pos=37288|flags=K__ +packet|codec_type=audio|stream_index=0|pts=188416|pts_time=4.272472|dts=188416|dts_time=4.272472|duration=1024|duration_time=0.023220|size=201|pos=37489|flags=K__ +packet|codec_type=audio|stream_index=0|pts=189440|pts_time=4.295692|dts=189440|dts_time=4.295692|duration=1024|duration_time=0.023220|size=201|pos=37690|flags=K__ +packet|codec_type=audio|stream_index=0|pts=190464|pts_time=4.318912|dts=190464|dts_time=4.318912|duration=1024|duration_time=0.023220|size=199|pos=37891|flags=K__ +packet|codec_type=audio|stream_index=0|pts=191488|pts_time=4.342132|dts=191488|dts_time=4.342132|duration=1024|duration_time=0.023220|size=198|pos=38090|flags=K__ +packet|codec_type=audio|stream_index=0|pts=192512|pts_time=4.365351|dts=192512|dts_time=4.365351|duration=1024|duration_time=0.023220|size=205|pos=38288|flags=K__ +packet|codec_type=audio|stream_index=0|pts=193536|pts_time=4.388571|dts=193536|dts_time=4.388571|duration=1024|duration_time=0.023220|size=190|pos=38493|flags=K__ +packet|codec_type=audio|stream_index=0|pts=194560|pts_time=4.411791|dts=194560|dts_time=4.411791|duration=1024|duration_time=0.023220|size=207|pos=38683|flags=K__ +packet|codec_type=audio|stream_index=0|pts=195584|pts_time=4.435011|dts=195584|dts_time=4.435011|duration=1024|duration_time=0.023220|size=204|pos=38890|flags=K__ +packet|codec_type=audio|stream_index=0|pts=196608|pts_time=4.458231|dts=196608|dts_time=4.458231|duration=1024|duration_time=0.023220|size=192|pos=39094|flags=K__ +packet|codec_type=audio|stream_index=0|pts=197632|pts_time=4.481451|dts=197632|dts_time=4.481451|duration=1024|duration_time=0.023220|size=211|pos=39286|flags=K__ +packet|codec_type=audio|stream_index=0|pts=198656|pts_time=4.504671|dts=198656|dts_time=4.504671|duration=1024|duration_time=0.023220|size=195|pos=39497|flags=K__ +packet|codec_type=audio|stream_index=0|pts=199680|pts_time=4.527891|dts=199680|dts_time=4.527891|duration=1024|duration_time=0.023220|size=214|pos=39692|flags=K__ +packet|codec_type=audio|stream_index=0|pts=200704|pts_time=4.551111|dts=200704|dts_time=4.551111|duration=1024|duration_time=0.023220|size=195|pos=39906|flags=K__ +packet|codec_type=audio|stream_index=0|pts=201728|pts_time=4.574331|dts=201728|dts_time=4.574331|duration=1024|duration_time=0.023220|size=199|pos=40101|flags=K__ +packet|codec_type=audio|stream_index=0|pts=202752|pts_time=4.597551|dts=202752|dts_time=4.597551|duration=1024|duration_time=0.023220|size=183|pos=40300|flags=K__ +packet|codec_type=audio|stream_index=0|pts=203776|pts_time=4.620771|dts=203776|dts_time=4.620771|duration=1024|duration_time=0.023220|size=211|pos=40483|flags=K__ +packet|codec_type=audio|stream_index=0|pts=204800|pts_time=4.643991|dts=204800|dts_time=4.643991|duration=1024|duration_time=0.023220|size=200|pos=40694|flags=K__ +packet|codec_type=audio|stream_index=0|pts=205824|pts_time=4.667211|dts=205824|dts_time=4.667211|duration=1024|duration_time=0.023220|size=199|pos=40894|flags=K__ +packet|codec_type=audio|stream_index=0|pts=206848|pts_time=4.690431|dts=206848|dts_time=4.690431|duration=1024|duration_time=0.023220|size=213|pos=41093|flags=K__ +packet|codec_type=audio|stream_index=0|pts=207872|pts_time=4.713651|dts=207872|dts_time=4.713651|duration=1024|duration_time=0.023220|size=191|pos=41306|flags=K__ +packet|codec_type=audio|stream_index=0|pts=208896|pts_time=4.736871|dts=208896|dts_time=4.736871|duration=1024|duration_time=0.023220|size=211|pos=41497|flags=K__ +packet|codec_type=audio|stream_index=0|pts=209920|pts_time=4.760091|dts=209920|dts_time=4.760091|duration=1024|duration_time=0.023220|size=198|pos=41708|flags=K__ +packet|codec_type=audio|stream_index=0|pts=210944|pts_time=4.783311|dts=210944|dts_time=4.783311|duration=1024|duration_time=0.023220|size=203|pos=41906|flags=K__ +packet|codec_type=audio|stream_index=0|pts=211968|pts_time=4.806531|dts=211968|dts_time=4.806531|duration=1024|duration_time=0.023220|size=196|pos=42109|flags=K__ +packet|codec_type=audio|stream_index=0|pts=212992|pts_time=4.829751|dts=212992|dts_time=4.829751|duration=1024|duration_time=0.023220|size=197|pos=42305|flags=K__ +packet|codec_type=audio|stream_index=0|pts=214016|pts_time=4.852971|dts=214016|dts_time=4.852971|duration=1024|duration_time=0.023220|size=190|pos=42502|flags=K__ +packet|codec_type=audio|stream_index=0|pts=215040|pts_time=4.876190|dts=215040|dts_time=4.876190|duration=1024|duration_time=0.023220|size=208|pos=42692|flags=K__ +packet|codec_type=audio|stream_index=0|pts=216064|pts_time=4.899410|dts=216064|dts_time=4.899410|duration=1024|duration_time=0.023220|size=203|pos=42900|flags=K__ +packet|codec_type=audio|stream_index=0|pts=217088|pts_time=4.922630|dts=217088|dts_time=4.922630|duration=1024|duration_time=0.023220|size=198|pos=43103|flags=K__ +packet|codec_type=audio|stream_index=0|pts=218112|pts_time=4.945850|dts=218112|dts_time=4.945850|duration=1024|duration_time=0.023220|size=284|pos=43301|flags=K__ +packet|codec_type=audio|stream_index=0|pts=219136|pts_time=4.969070|dts=219136|dts_time=4.969070|duration=1364|duration_time=0.030930|size=5|pos=43585|flags=K__ diff --git a/tests/ref/fate/mov-init-nonkeyframe b/tests/ref/fate/mov-init-nonkeyframe index 438f3973f90..2a1c2df6a7d 100644 --- a/tests/ref/fate/mov-init-nonkeyframe +++ b/tests/ref/fate/mov-init-nonkeyframe @@ -1,120 +1,120 @@ -packet|codec_type=video|stream_index=0|pts=0|pts_time=0.000000|dts=0|dts_time=0.000000|duration=1001|duration_time=0.033367|size=599|pos=48|flags=__ -packet|codec_type=video|stream_index=0|pts=2002|pts_time=0.066733|dts=1001|dts_time=0.033367|duration=1001|duration_time=0.033367|size=2944|pos=1674|flags=__ -packet|codec_type=video|stream_index=0|pts=7007|pts_time=0.233567|dts=2002|dts_time=0.066733|duration=1001|duration_time=0.033367|size=21987|pos=5335|flags=__ -packet|codec_type=video|stream_index=0|pts=5005|pts_time=0.166833|dts=3003|dts_time=0.100100|duration=1001|duration_time=0.033367|size=4145|pos=28605|flags=__ -packet|codec_type=video|stream_index=0|pts=4004|pts_time=0.133467|dts=4004|dts_time=0.133467|duration=1001|duration_time=0.033367|size=3093|pos=33425|flags=__ -packet|codec_type=video|stream_index=0|pts=6006|pts_time=0.200200|dts=5005|dts_time=0.166833|duration=1001|duration_time=0.033367|size=572|pos=37769|flags=__ -packet|codec_type=video|stream_index=0|pts=11011|pts_time=0.367033|dts=6006|dts_time=0.200200|duration=1001|duration_time=0.033367|size=21599|pos=38999|flags=__ -packet|codec_type=video|stream_index=0|pts=9009|pts_time=0.300300|dts=7007|dts_time=0.233567|duration=1001|duration_time=0.033367|size=6287|pos=61922|flags=__ -packet|codec_type=video|stream_index=0|pts=8008|pts_time=0.266933|dts=8008|dts_time=0.266933|duration=1001|duration_time=0.033367|size=2720|pos=68909|flags=__ -packet|codec_type=video|stream_index=0|pts=10010|pts_time=0.333667|dts=9009|dts_time=0.300300|duration=1001|duration_time=0.033367|size=2715|pos=72301|flags=__ -packet|codec_type=video|stream_index=0|pts=15015|pts_time=0.500500|dts=10010|dts_time=0.333667|duration=1001|duration_time=0.033367|size=20221|pos=76433|flags=__ -packet|codec_type=video|stream_index=0|pts=13013|pts_time=0.433767|dts=11011|dts_time=0.367033|duration=1001|duration_time=0.033367|size=9505|pos=97381|flags=__ -packet|codec_type=video|stream_index=0|pts=12012|pts_time=0.400400|dts=12012|dts_time=0.400400|duration=1001|duration_time=0.033367|size=522|pos=108391|flags=__ -packet|codec_type=video|stream_index=0|pts=14014|pts_time=0.467133|dts=13013|dts_time=0.433767|duration=1001|duration_time=0.033367|size=2360|pos=109683|flags=__ -packet|codec_type=video|stream_index=0|pts=17017|pts_time=0.567233|dts=14014|dts_time=0.467133|duration=1001|duration_time=0.033367|size=22156|pos=113572|flags=__ -packet|codec_type=video|stream_index=0|pts=16016|pts_time=0.533867|dts=15015|dts_time=0.500500|duration=1001|duration_time=0.033367|size=1801|pos=136496|flags=__ -packet|codec_type=video|stream_index=0|pts=21021|pts_time=0.700700|dts=16016|dts_time=0.533867|duration=1001|duration_time=0.033367|size=20181|pos=139074|flags=__ -packet|codec_type=video|stream_index=0|pts=19019|pts_time=0.633967|dts=17017|dts_time=0.567233|duration=1001|duration_time=0.033367|size=3608|pos=160959|flags=__ -packet|codec_type=video|stream_index=0|pts=18018|pts_time=0.600600|dts=18018|dts_time=0.600600|duration=1001|duration_time=0.033367|size=368|pos=165305|flags=__ -packet|codec_type=video|stream_index=0|pts=20020|pts_time=0.667333|dts=19019|dts_time=0.633967|duration=1001|duration_time=0.033367|size=2989|pos=167054|flags=__ -packet|codec_type=video|stream_index=0|pts=25025|pts_time=0.834167|dts=20020|dts_time=0.667333|duration=1001|duration_time=0.033367|size=24475|pos=170801|flags=__ -packet|codec_type=video|stream_index=0|pts=23023|pts_time=0.767433|dts=21021|dts_time=0.700700|duration=1001|duration_time=0.033367|size=10682|pos=196732|flags=__ -packet|codec_type=video|stream_index=0|pts=22022|pts_time=0.734067|dts=22022|dts_time=0.734067|duration=1001|duration_time=0.033367|size=3198|pos=208151|flags=__ -packet|codec_type=video|stream_index=0|pts=24024|pts_time=0.800800|dts=23023|dts_time=0.767433|duration=1001|duration_time=0.033367|size=479|pos=212958|flags=__ -packet|codec_type=video|stream_index=0|pts=29029|pts_time=0.967633|dts=24024|dts_time=0.800800|duration=1001|duration_time=0.033367|size=21240|pos=214384|flags=__ -packet|codec_type=video|stream_index=0|pts=27027|pts_time=0.900900|dts=25025|dts_time=0.834167|duration=1001|duration_time=0.033367|size=4409|pos=236946|flags=__ -packet|codec_type=video|stream_index=0|pts=26026|pts_time=0.867533|dts=26026|dts_time=0.867533|duration=1001|duration_time=0.033367|size=3106|pos=242647|flags=__ -packet|codec_type=video|stream_index=0|pts=28028|pts_time=0.934267|dts=27027|dts_time=0.900900|duration=1001|duration_time=0.033367|size=453|pos=246428|flags=__ -packet|codec_type=video|stream_index=0|pts=33033|pts_time=1.101100|dts=28028|dts_time=0.934267|duration=1001|duration_time=0.033367|size=20668|pos=248308|flags=__ -packet|codec_type=video|stream_index=0|pts=31031|pts_time=1.034367|dts=29029|dts_time=0.967633|duration=1001|duration_time=0.033367|size=6668|pos=269708|flags=__ -packet|codec_type=video|stream_index=0|pts=30030|pts_time=1.001000|dts=30030|dts_time=1.001000|duration=1001|duration_time=0.033367|size=3027|pos=277789|flags=__ -packet|codec_type=video|stream_index=0|pts=32032|pts_time=1.067733|dts=31031|dts_time=1.034367|duration=1001|duration_time=0.033367|size=2884|pos=281613|flags=__ -packet|codec_type=video|stream_index=0|pts=37037|pts_time=1.234567|dts=32032|dts_time=1.067733|duration=1001|duration_time=0.033367|size=21313|pos=285261|flags=__ -packet|codec_type=video|stream_index=0|pts=35035|pts_time=1.167833|dts=33033|dts_time=1.101100|duration=1001|duration_time=0.033367|size=9890|pos=308303|flags=__ -packet|codec_type=video|stream_index=0|pts=34034|pts_time=1.134467|dts=34034|dts_time=1.134467|duration=1001|duration_time=0.033367|size=501|pos=318919|flags=__ -packet|codec_type=video|stream_index=0|pts=36036|pts_time=1.201200|dts=35035|dts_time=1.167833|duration=1001|duration_time=0.033367|size=3123|pos=320824|flags=__ -packet|codec_type=video|stream_index=0|pts=39039|pts_time=1.301300|dts=36036|dts_time=1.201200|duration=1001|duration_time=0.033367|size=21768|pos=324664|flags=__ -packet|codec_type=video|stream_index=0|pts=38038|pts_time=1.267933|dts=37037|dts_time=1.234567|duration=1001|duration_time=0.033367|size=2664|pos=347922|flags=__ -packet|codec_type=video|stream_index=0|pts=43043|pts_time=1.434767|dts=38038|dts_time=1.267933|duration=1001|duration_time=0.033367|size=19144|pos=351354|flags=__ -packet|codec_type=video|stream_index=0|pts=41041|pts_time=1.368033|dts=39039|dts_time=1.301300|duration=1001|duration_time=0.033367|size=4118|pos=371991|flags=__ -packet|codec_type=video|stream_index=0|pts=40040|pts_time=1.334667|dts=40040|dts_time=1.334667|duration=1001|duration_time=0.033367|size=423|pos=376899|flags=__ -packet|codec_type=video|stream_index=0|pts=42042|pts_time=1.401400|dts=41041|dts_time=1.368033|duration=1001|duration_time=0.033367|size=2785|pos=378037|flags=__ -packet|codec_type=video|stream_index=0|pts=45045|pts_time=1.501500|dts=42042|dts_time=1.401400|duration=1001|duration_time=0.033367|size=24489|pos=382144|flags=__ -packet|codec_type=video|stream_index=0|pts=44044|pts_time=1.468133|dts=43043|dts_time=1.434767|duration=1001|duration_time=0.033367|size=2984|pos=407344|flags=__ -packet|codec_type=video|stream_index=0|pts=49049|pts_time=1.634967|dts=44044|dts_time=1.468133|duration=1001|duration_time=0.033367|size=19174|pos=411791|flags=__ -packet|codec_type=video|stream_index=0|pts=47047|pts_time=1.568233|dts=45045|dts_time=1.501500|duration=1001|duration_time=0.033367|size=4905|pos=431740|flags=__ -packet|codec_type=video|stream_index=0|pts=46046|pts_time=1.534867|dts=46046|dts_time=1.534867|duration=1001|duration_time=0.033367|size=412|pos=438183|flags=__ -packet|codec_type=video|stream_index=0|pts=48048|pts_time=1.601600|dts=47047|dts_time=1.568233|duration=1001|duration_time=0.033367|size=3215|pos=439373|flags=__ -packet|codec_type=video|stream_index=0|pts=51051|pts_time=1.701700|dts=48048|dts_time=1.601600|duration=1001|duration_time=0.033367|size=21572|pos=443371|flags=__ -packet|codec_type=video|stream_index=0|pts=50050|pts_time=1.668333|dts=49049|dts_time=1.634967|duration=1001|duration_time=0.033367|size=2644|pos=466486|flags=__ -packet|codec_type=video|stream_index=0|pts=55055|pts_time=1.835167|dts=50050|dts_time=1.668333|duration=1001|duration_time=0.033367|size=19417|pos=470462|flags=__ -packet|codec_type=video|stream_index=0|pts=53053|pts_time=1.768433|dts=51051|dts_time=1.701700|duration=1001|duration_time=0.033367|size=3685|pos=491335|flags=__ -packet|codec_type=video|stream_index=0|pts=52052|pts_time=1.735067|dts=52052|dts_time=1.735067|duration=1001|duration_time=0.033367|size=355|pos=495771|flags=__ -packet|codec_type=video|stream_index=0|pts=54054|pts_time=1.801800|dts=53053|dts_time=1.768433|duration=1001|duration_time=0.033367|size=3021|pos=497714|flags=__ -packet|codec_type=video|stream_index=0|pts=59059|pts_time=1.968633|dts=54054|dts_time=1.801800|duration=1001|duration_time=0.033367|size=21464|pos=501431|flags=__ -packet|codec_type=video|stream_index=0|pts=57057|pts_time=1.901900|dts=55055|dts_time=1.835167|duration=1001|duration_time=0.033367|size=9340|pos=524392|flags=__ -packet|codec_type=video|stream_index=0|pts=56056|pts_time=1.868533|dts=56056|dts_time=1.868533|duration=1001|duration_time=0.033367|size=406|pos=534504|flags=__ -packet|codec_type=video|stream_index=0|pts=58058|pts_time=1.935267|dts=57057|dts_time=1.901900|duration=1001|duration_time=0.033367|size=3277|pos=535694|flags=__ -packet|codec_type=video|stream_index=0|pts=63063|pts_time=2.102100|dts=58058|dts_time=1.935267|duration=1001|duration_time=0.033367|size=21388|pos=541090|flags=__ -packet|codec_type=video|stream_index=0|pts=61061|pts_time=2.035367|dts=59059|dts_time=1.968633|duration=1001|duration_time=0.033367|size=4466|pos=563132|flags=__ -packet|codec_type=video|stream_index=0|pts=60060|pts_time=2.002000|dts=60060|dts_time=2.002000|duration=1001|duration_time=0.033367|size=3467|pos=569245|flags=__ -packet|codec_type=video|stream_index=0|pts=62062|pts_time=2.068733|dts=61061|dts_time=2.035367|duration=1001|duration_time=0.033367|size=499|pos=573478|flags=__ -packet|codec_type=video|stream_index=0|pts=67067|pts_time=2.235567|dts=62062|dts_time=2.068733|duration=1001|duration_time=0.033367|size=25972|pos=575469|flags=__ -packet|codec_type=video|stream_index=0|pts=65065|pts_time=2.168833|dts=63063|dts_time=2.102100|duration=1001|duration_time=0.033367|size=6643|pos=602163|flags=__ -packet|codec_type=video|stream_index=0|pts=64064|pts_time=2.135467|dts=64064|dts_time=2.135467|duration=1001|duration_time=0.033367|size=3069|pos=609558|flags=__ -packet|codec_type=video|stream_index=0|pts=66066|pts_time=2.202200|dts=65065|dts_time=2.168833|duration=1001|duration_time=0.033367|size=3049|pos=614133|flags=__ -packet|codec_type=video|stream_index=0|pts=68068|pts_time=2.268933|dts=66066|dts_time=2.202200|duration=1001|duration_time=0.033367|size=4559|pos=618551|flags=__ -packet|codec_type=video|stream_index=0|pts=72072|pts_time=2.402400|dts=67067|dts_time=2.235567|duration=1001|duration_time=0.033367|size=21251|pos=624621|flags=__ -packet|codec_type=video|stream_index=0|pts=70070|pts_time=2.335667|dts=68068|dts_time=2.268933|duration=1001|duration_time=0.033367|size=7108|pos=646657|flags=__ -packet|codec_type=video|stream_index=0|pts=69069|pts_time=2.302300|dts=69069|dts_time=2.302300|duration=1001|duration_time=0.033367|size=3250|pos=655299|flags=__ -packet|codec_type=video|stream_index=0|pts=71071|pts_time=2.369033|dts=70070|dts_time=2.335667|duration=1001|duration_time=0.033367|size=3365|pos=659310|flags=__ -packet|codec_type=video|stream_index=0|pts=73073|pts_time=2.435767|dts=71071|dts_time=2.369033|duration=1001|duration_time=0.033367|size=24803|pos=664201|flags=__ -packet|codec_type=video|stream_index=0|pts=77077|pts_time=2.569233|dts=72072|dts_time=2.402400|duration=1001|duration_time=0.033367|size=22185|pos=689763|flags=__ -packet|codec_type=video|stream_index=0|pts=75075|pts_time=2.502500|dts=73073|dts_time=2.435767|duration=1001|duration_time=0.033367|size=5088|pos=712679|flags=__ -packet|codec_type=video|stream_index=0|pts=74074|pts_time=2.469133|dts=74074|dts_time=2.469133|duration=1001|duration_time=0.033367|size=537|pos=719128|flags=__ -packet|codec_type=video|stream_index=0|pts=76076|pts_time=2.535867|dts=75075|dts_time=2.502500|duration=1001|duration_time=0.033367|size=3765|pos=720413|flags=__ -packet|codec_type=video|stream_index=0|pts=81081|pts_time=2.702700|dts=76076|dts_time=2.535867|duration=1001|duration_time=0.033367|size=20654|pos=725583|flags=__ -packet|codec_type=video|stream_index=0|pts=79079|pts_time=2.635967|dts=77077|dts_time=2.569233|duration=1001|duration_time=0.033367|size=10202|pos=746999|flags=__ -packet|codec_type=video|stream_index=0|pts=78078|pts_time=2.602600|dts=78078|dts_time=2.602600|duration=1001|duration_time=0.033367|size=3970|pos=758705|flags=__ -packet|codec_type=video|stream_index=0|pts=80080|pts_time=2.669333|dts=79079|dts_time=2.635967|duration=1001|duration_time=0.033367|size=421|pos=763442|flags=__ -packet|codec_type=video|stream_index=0|pts=84084|pts_time=2.802800|dts=80080|dts_time=2.669333|duration=1001|duration_time=0.033367|size=25685|pos=764653|flags=__ -packet|codec_type=video|stream_index=0|pts=82082|pts_time=2.736067|dts=81081|dts_time=2.702700|duration=1001|duration_time=0.033367|size=4077|pos=791911|flags=__ -packet|codec_type=video|stream_index=0|pts=83083|pts_time=2.769433|dts=82082|dts_time=2.736067|duration=1001|duration_time=0.033367|size=3049|pos=796780|flags=__ -packet|codec_type=video|stream_index=0|pts=88088|pts_time=2.936267|dts=83083|dts_time=2.769433|duration=1001|duration_time=0.033367|size=8924|pos=801473|flags=__ -packet|codec_type=video|stream_index=0|pts=86086|pts_time=2.869533|dts=84084|dts_time=2.802800|duration=1001|duration_time=0.033367|size=2512|pos=811078|flags=__ -packet|codec_type=video|stream_index=0|pts=85085|pts_time=2.836167|dts=85085|dts_time=2.836167|duration=1001|duration_time=0.033367|size=163|pos=815033|flags=__ -packet|codec_type=video|stream_index=0|pts=87087|pts_time=2.902900|dts=86086|dts_time=2.869533|duration=1001|duration_time=0.033367|size=1734|pos=815934|flags=__ -packet|codec_type=video|stream_index=0|pts=90090|pts_time=3.003000|dts=87087|dts_time=2.902900|duration=1001|duration_time=0.033367|size=11505|pos=819088|flags=__ -packet|codec_type=video|stream_index=0|pts=89089|pts_time=2.969633|dts=88088|dts_time=2.936267|duration=1001|duration_time=0.033367|size=1431|pos=831367|flags=__ -packet|codec_type=video|stream_index=0|pts=92092|pts_time=3.069733|dts=89089|dts_time=2.969633|duration=1001|duration_time=0.033367|size=5269|pos=833580|flags=__ -packet|codec_type=video|stream_index=0|pts=91091|pts_time=3.036367|dts=90090|dts_time=3.003000|duration=1001|duration_time=0.033367|size=199|pos=840352|flags=__ -packet|codec_type=video|stream_index=0|pts=93093|pts_time=3.103100|dts=91091|dts_time=3.036367|duration=1001|duration_time=0.033367|size=85650|pos=841722|flags=K_ -packet|codec_type=video|stream_index=0|pts=95095|pts_time=3.169833|dts=92092|dts_time=3.069733|duration=1001|duration_time=0.033367|size=13261|pos=928747|flags=__ -packet|codec_type=video|stream_index=0|pts=94094|pts_time=3.136467|dts=93093|dts_time=3.103100|duration=1001|duration_time=0.033367|size=1667|pos=942741|flags=__ -packet|codec_type=video|stream_index=0|pts=99099|pts_time=3.303300|dts=94094|dts_time=3.136467|duration=1001|duration_time=0.033367|size=20143|pos=945841|flags=__ -packet|codec_type=video|stream_index=0|pts=97097|pts_time=3.236567|dts=95095|dts_time=3.169833|duration=1001|duration_time=0.033367|size=2484|pos=966681|flags=__ -packet|codec_type=video|stream_index=0|pts=96096|pts_time=3.203200|dts=96096|dts_time=3.203200|duration=1001|duration_time=0.033367|size=278|pos=969887|flags=__ -packet|codec_type=video|stream_index=0|pts=98098|pts_time=3.269933|dts=97097|dts_time=3.236567|duration=1001|duration_time=0.033367|size=1539|pos=971696|flags=__ -packet|codec_type=video|stream_index=0|pts=101101|pts_time=3.370033|dts=98098|dts_time=3.269933|duration=1001|duration_time=0.033367|size=20270|pos=974088|flags=__ -packet|codec_type=video|stream_index=0|pts=100100|pts_time=3.336667|dts=99099|dts_time=3.303300|duration=1001|duration_time=0.033367|size=1754|pos=995975|flags=__ -packet|codec_type=video|stream_index=0|pts=105105|pts_time=3.503500|dts=100100|dts_time=3.336667|duration=1001|duration_time=0.033367|size=19154|pos=998420|flags=__ -packet|codec_type=video|stream_index=0|pts=103103|pts_time=3.436767|dts=101101|dts_time=3.370033|duration=1001|duration_time=0.033367|size=3359|pos=1019010|flags=__ -packet|codec_type=video|stream_index=0|pts=102102|pts_time=3.403400|dts=102102|dts_time=3.403400|duration=1001|duration_time=0.033367|size=287|pos=1023138|flags=__ -packet|codec_type=video|stream_index=0|pts=104104|pts_time=3.470133|dts=103103|dts_time=3.436767|duration=1001|duration_time=0.033367|size=2111|pos=1024928|flags=__ -packet|codec_type=video|stream_index=0|pts=109109|pts_time=3.636967|dts=104104|dts_time=3.470133|duration=1001|duration_time=0.033367|size=17178|pos=1027833|flags=__ -packet|codec_type=video|stream_index=0|pts=107107|pts_time=3.570233|dts=105105|dts_time=3.503500|duration=1001|duration_time=0.033367|size=7205|pos=1045716|flags=__ -packet|codec_type=video|stream_index=0|pts=106106|pts_time=3.536867|dts=106106|dts_time=3.536867|duration=1001|duration_time=0.033367|size=2209|pos=1054354|flags=__ -packet|codec_type=video|stream_index=0|pts=108108|pts_time=3.603600|dts=107107|dts_time=3.570233|duration=1001|duration_time=0.033367|size=359|pos=1057226|flags=__ -packet|codec_type=video|stream_index=0|pts=113113|pts_time=3.770433|dts=108108|dts_time=3.603600|duration=1001|duration_time=0.033367|size=18469|pos=1059024|flags=__ -packet|codec_type=video|stream_index=0|pts=111111|pts_time=3.703700|dts=109109|dts_time=3.636967|duration=1001|duration_time=0.033367|size=3314|pos=1078213|flags=__ -packet|codec_type=video|stream_index=0|pts=110110|pts_time=3.670333|dts=110110|dts_time=3.670333|duration=1001|duration_time=0.033367|size=2556|pos=1083059|flags=__ -packet|codec_type=video|stream_index=0|pts=112112|pts_time=3.737067|dts=111111|dts_time=3.703700|duration=1001|duration_time=0.033367|size=437|pos=1086388|flags=__ -packet|codec_type=video|stream_index=0|pts=117117|pts_time=3.903900|dts=112112|dts_time=3.737067|duration=1001|duration_time=0.033367|size=19707|pos=1087610|flags=__ -packet|codec_type=video|stream_index=0|pts=115115|pts_time=3.837167|dts=113113|dts_time=3.770433|duration=1001|duration_time=0.033367|size=5917|pos=1108845|flags=__ -packet|codec_type=video|stream_index=0|pts=114114|pts_time=3.803800|dts=114114|dts_time=3.803800|duration=1001|duration_time=0.033367|size=2613|pos=1115495|flags=__ -packet|codec_type=video|stream_index=0|pts=116116|pts_time=3.870533|dts=115115|dts_time=3.837167|duration=1001|duration_time=0.033367|size=2672|pos=1119530|flags=__ -packet|codec_type=video|stream_index=0|pts=121121|pts_time=4.037367|dts=116116|dts_time=3.870533|duration=1001|duration_time=0.033367|size=19091|pos=1122970|flags=_D -packet|codec_type=video|stream_index=0|pts=119119|pts_time=3.970633|dts=117117|dts_time=3.903900|duration=1001|duration_time=0.033367|size=9244|pos=1143585|flags=__ -packet|codec_type=video|stream_index=0|pts=118118|pts_time=3.937267|dts=118118|dts_time=3.937267|duration=1001|duration_time=0.033367|size=284|pos=1153587|flags=__ -packet|codec_type=video|stream_index=0|pts=120120|pts_time=4.004000|dts=119119|dts_time=3.970633|duration=1001|duration_time=0.033367|size=2381|pos=1155393|flags=_D +packet|codec_type=video|stream_index=0|pts=0|pts_time=0.000000|dts=0|dts_time=0.000000|duration=1001|duration_time=0.033367|size=599|pos=48|flags=___ +packet|codec_type=video|stream_index=0|pts=2002|pts_time=0.066733|dts=1001|dts_time=0.033367|duration=1001|duration_time=0.033367|size=2944|pos=1674|flags=___ +packet|codec_type=video|stream_index=0|pts=7007|pts_time=0.233567|dts=2002|dts_time=0.066733|duration=1001|duration_time=0.033367|size=21987|pos=5335|flags=___ +packet|codec_type=video|stream_index=0|pts=5005|pts_time=0.166833|dts=3003|dts_time=0.100100|duration=1001|duration_time=0.033367|size=4145|pos=28605|flags=___ +packet|codec_type=video|stream_index=0|pts=4004|pts_time=0.133467|dts=4004|dts_time=0.133467|duration=1001|duration_time=0.033367|size=3093|pos=33425|flags=___ +packet|codec_type=video|stream_index=0|pts=6006|pts_time=0.200200|dts=5005|dts_time=0.166833|duration=1001|duration_time=0.033367|size=572|pos=37769|flags=___ +packet|codec_type=video|stream_index=0|pts=11011|pts_time=0.367033|dts=6006|dts_time=0.200200|duration=1001|duration_time=0.033367|size=21599|pos=38999|flags=___ +packet|codec_type=video|stream_index=0|pts=9009|pts_time=0.300300|dts=7007|dts_time=0.233567|duration=1001|duration_time=0.033367|size=6287|pos=61922|flags=___ +packet|codec_type=video|stream_index=0|pts=8008|pts_time=0.266933|dts=8008|dts_time=0.266933|duration=1001|duration_time=0.033367|size=2720|pos=68909|flags=___ +packet|codec_type=video|stream_index=0|pts=10010|pts_time=0.333667|dts=9009|dts_time=0.300300|duration=1001|duration_time=0.033367|size=2715|pos=72301|flags=___ +packet|codec_type=video|stream_index=0|pts=15015|pts_time=0.500500|dts=10010|dts_time=0.333667|duration=1001|duration_time=0.033367|size=20221|pos=76433|flags=___ +packet|codec_type=video|stream_index=0|pts=13013|pts_time=0.433767|dts=11011|dts_time=0.367033|duration=1001|duration_time=0.033367|size=9505|pos=97381|flags=___ +packet|codec_type=video|stream_index=0|pts=12012|pts_time=0.400400|dts=12012|dts_time=0.400400|duration=1001|duration_time=0.033367|size=522|pos=108391|flags=___ +packet|codec_type=video|stream_index=0|pts=14014|pts_time=0.467133|dts=13013|dts_time=0.433767|duration=1001|duration_time=0.033367|size=2360|pos=109683|flags=___ +packet|codec_type=video|stream_index=0|pts=17017|pts_time=0.567233|dts=14014|dts_time=0.467133|duration=1001|duration_time=0.033367|size=22156|pos=113572|flags=___ +packet|codec_type=video|stream_index=0|pts=16016|pts_time=0.533867|dts=15015|dts_time=0.500500|duration=1001|duration_time=0.033367|size=1801|pos=136496|flags=___ +packet|codec_type=video|stream_index=0|pts=21021|pts_time=0.700700|dts=16016|dts_time=0.533867|duration=1001|duration_time=0.033367|size=20181|pos=139074|flags=___ +packet|codec_type=video|stream_index=0|pts=19019|pts_time=0.633967|dts=17017|dts_time=0.567233|duration=1001|duration_time=0.033367|size=3608|pos=160959|flags=___ +packet|codec_type=video|stream_index=0|pts=18018|pts_time=0.600600|dts=18018|dts_time=0.600600|duration=1001|duration_time=0.033367|size=368|pos=165305|flags=___ +packet|codec_type=video|stream_index=0|pts=20020|pts_time=0.667333|dts=19019|dts_time=0.633967|duration=1001|duration_time=0.033367|size=2989|pos=167054|flags=___ +packet|codec_type=video|stream_index=0|pts=25025|pts_time=0.834167|dts=20020|dts_time=0.667333|duration=1001|duration_time=0.033367|size=24475|pos=170801|flags=___ +packet|codec_type=video|stream_index=0|pts=23023|pts_time=0.767433|dts=21021|dts_time=0.700700|duration=1001|duration_time=0.033367|size=10682|pos=196732|flags=___ +packet|codec_type=video|stream_index=0|pts=22022|pts_time=0.734067|dts=22022|dts_time=0.734067|duration=1001|duration_time=0.033367|size=3198|pos=208151|flags=___ +packet|codec_type=video|stream_index=0|pts=24024|pts_time=0.800800|dts=23023|dts_time=0.767433|duration=1001|duration_time=0.033367|size=479|pos=212958|flags=___ +packet|codec_type=video|stream_index=0|pts=29029|pts_time=0.967633|dts=24024|dts_time=0.800800|duration=1001|duration_time=0.033367|size=21240|pos=214384|flags=___ +packet|codec_type=video|stream_index=0|pts=27027|pts_time=0.900900|dts=25025|dts_time=0.834167|duration=1001|duration_time=0.033367|size=4409|pos=236946|flags=___ +packet|codec_type=video|stream_index=0|pts=26026|pts_time=0.867533|dts=26026|dts_time=0.867533|duration=1001|duration_time=0.033367|size=3106|pos=242647|flags=___ +packet|codec_type=video|stream_index=0|pts=28028|pts_time=0.934267|dts=27027|dts_time=0.900900|duration=1001|duration_time=0.033367|size=453|pos=246428|flags=___ +packet|codec_type=video|stream_index=0|pts=33033|pts_time=1.101100|dts=28028|dts_time=0.934267|duration=1001|duration_time=0.033367|size=20668|pos=248308|flags=___ +packet|codec_type=video|stream_index=0|pts=31031|pts_time=1.034367|dts=29029|dts_time=0.967633|duration=1001|duration_time=0.033367|size=6668|pos=269708|flags=___ +packet|codec_type=video|stream_index=0|pts=30030|pts_time=1.001000|dts=30030|dts_time=1.001000|duration=1001|duration_time=0.033367|size=3027|pos=277789|flags=___ +packet|codec_type=video|stream_index=0|pts=32032|pts_time=1.067733|dts=31031|dts_time=1.034367|duration=1001|duration_time=0.033367|size=2884|pos=281613|flags=___ +packet|codec_type=video|stream_index=0|pts=37037|pts_time=1.234567|dts=32032|dts_time=1.067733|duration=1001|duration_time=0.033367|size=21313|pos=285261|flags=___ +packet|codec_type=video|stream_index=0|pts=35035|pts_time=1.167833|dts=33033|dts_time=1.101100|duration=1001|duration_time=0.033367|size=9890|pos=308303|flags=___ +packet|codec_type=video|stream_index=0|pts=34034|pts_time=1.134467|dts=34034|dts_time=1.134467|duration=1001|duration_time=0.033367|size=501|pos=318919|flags=___ +packet|codec_type=video|stream_index=0|pts=36036|pts_time=1.201200|dts=35035|dts_time=1.167833|duration=1001|duration_time=0.033367|size=3123|pos=320824|flags=___ +packet|codec_type=video|stream_index=0|pts=39039|pts_time=1.301300|dts=36036|dts_time=1.201200|duration=1001|duration_time=0.033367|size=21768|pos=324664|flags=___ +packet|codec_type=video|stream_index=0|pts=38038|pts_time=1.267933|dts=37037|dts_time=1.234567|duration=1001|duration_time=0.033367|size=2664|pos=347922|flags=___ +packet|codec_type=video|stream_index=0|pts=43043|pts_time=1.434767|dts=38038|dts_time=1.267933|duration=1001|duration_time=0.033367|size=19144|pos=351354|flags=___ +packet|codec_type=video|stream_index=0|pts=41041|pts_time=1.368033|dts=39039|dts_time=1.301300|duration=1001|duration_time=0.033367|size=4118|pos=371991|flags=___ +packet|codec_type=video|stream_index=0|pts=40040|pts_time=1.334667|dts=40040|dts_time=1.334667|duration=1001|duration_time=0.033367|size=423|pos=376899|flags=___ +packet|codec_type=video|stream_index=0|pts=42042|pts_time=1.401400|dts=41041|dts_time=1.368033|duration=1001|duration_time=0.033367|size=2785|pos=378037|flags=___ +packet|codec_type=video|stream_index=0|pts=45045|pts_time=1.501500|dts=42042|dts_time=1.401400|duration=1001|duration_time=0.033367|size=24489|pos=382144|flags=___ +packet|codec_type=video|stream_index=0|pts=44044|pts_time=1.468133|dts=43043|dts_time=1.434767|duration=1001|duration_time=0.033367|size=2984|pos=407344|flags=___ +packet|codec_type=video|stream_index=0|pts=49049|pts_time=1.634967|dts=44044|dts_time=1.468133|duration=1001|duration_time=0.033367|size=19174|pos=411791|flags=___ +packet|codec_type=video|stream_index=0|pts=47047|pts_time=1.568233|dts=45045|dts_time=1.501500|duration=1001|duration_time=0.033367|size=4905|pos=431740|flags=___ +packet|codec_type=video|stream_index=0|pts=46046|pts_time=1.534867|dts=46046|dts_time=1.534867|duration=1001|duration_time=0.033367|size=412|pos=438183|flags=___ +packet|codec_type=video|stream_index=0|pts=48048|pts_time=1.601600|dts=47047|dts_time=1.568233|duration=1001|duration_time=0.033367|size=3215|pos=439373|flags=___ +packet|codec_type=video|stream_index=0|pts=51051|pts_time=1.701700|dts=48048|dts_time=1.601600|duration=1001|duration_time=0.033367|size=21572|pos=443371|flags=___ +packet|codec_type=video|stream_index=0|pts=50050|pts_time=1.668333|dts=49049|dts_time=1.634967|duration=1001|duration_time=0.033367|size=2644|pos=466486|flags=___ +packet|codec_type=video|stream_index=0|pts=55055|pts_time=1.835167|dts=50050|dts_time=1.668333|duration=1001|duration_time=0.033367|size=19417|pos=470462|flags=___ +packet|codec_type=video|stream_index=0|pts=53053|pts_time=1.768433|dts=51051|dts_time=1.701700|duration=1001|duration_time=0.033367|size=3685|pos=491335|flags=___ +packet|codec_type=video|stream_index=0|pts=52052|pts_time=1.735067|dts=52052|dts_time=1.735067|duration=1001|duration_time=0.033367|size=355|pos=495771|flags=___ +packet|codec_type=video|stream_index=0|pts=54054|pts_time=1.801800|dts=53053|dts_time=1.768433|duration=1001|duration_time=0.033367|size=3021|pos=497714|flags=___ +packet|codec_type=video|stream_index=0|pts=59059|pts_time=1.968633|dts=54054|dts_time=1.801800|duration=1001|duration_time=0.033367|size=21464|pos=501431|flags=___ +packet|codec_type=video|stream_index=0|pts=57057|pts_time=1.901900|dts=55055|dts_time=1.835167|duration=1001|duration_time=0.033367|size=9340|pos=524392|flags=___ +packet|codec_type=video|stream_index=0|pts=56056|pts_time=1.868533|dts=56056|dts_time=1.868533|duration=1001|duration_time=0.033367|size=406|pos=534504|flags=___ +packet|codec_type=video|stream_index=0|pts=58058|pts_time=1.935267|dts=57057|dts_time=1.901900|duration=1001|duration_time=0.033367|size=3277|pos=535694|flags=___ +packet|codec_type=video|stream_index=0|pts=63063|pts_time=2.102100|dts=58058|dts_time=1.935267|duration=1001|duration_time=0.033367|size=21388|pos=541090|flags=___ +packet|codec_type=video|stream_index=0|pts=61061|pts_time=2.035367|dts=59059|dts_time=1.968633|duration=1001|duration_time=0.033367|size=4466|pos=563132|flags=___ +packet|codec_type=video|stream_index=0|pts=60060|pts_time=2.002000|dts=60060|dts_time=2.002000|duration=1001|duration_time=0.033367|size=3467|pos=569245|flags=___ +packet|codec_type=video|stream_index=0|pts=62062|pts_time=2.068733|dts=61061|dts_time=2.035367|duration=1001|duration_time=0.033367|size=499|pos=573478|flags=___ +packet|codec_type=video|stream_index=0|pts=67067|pts_time=2.235567|dts=62062|dts_time=2.068733|duration=1001|duration_time=0.033367|size=25972|pos=575469|flags=___ +packet|codec_type=video|stream_index=0|pts=65065|pts_time=2.168833|dts=63063|dts_time=2.102100|duration=1001|duration_time=0.033367|size=6643|pos=602163|flags=___ +packet|codec_type=video|stream_index=0|pts=64064|pts_time=2.135467|dts=64064|dts_time=2.135467|duration=1001|duration_time=0.033367|size=3069|pos=609558|flags=___ +packet|codec_type=video|stream_index=0|pts=66066|pts_time=2.202200|dts=65065|dts_time=2.168833|duration=1001|duration_time=0.033367|size=3049|pos=614133|flags=___ +packet|codec_type=video|stream_index=0|pts=68068|pts_time=2.268933|dts=66066|dts_time=2.202200|duration=1001|duration_time=0.033367|size=4559|pos=618551|flags=___ +packet|codec_type=video|stream_index=0|pts=72072|pts_time=2.402400|dts=67067|dts_time=2.235567|duration=1001|duration_time=0.033367|size=21251|pos=624621|flags=___ +packet|codec_type=video|stream_index=0|pts=70070|pts_time=2.335667|dts=68068|dts_time=2.268933|duration=1001|duration_time=0.033367|size=7108|pos=646657|flags=___ +packet|codec_type=video|stream_index=0|pts=69069|pts_time=2.302300|dts=69069|dts_time=2.302300|duration=1001|duration_time=0.033367|size=3250|pos=655299|flags=___ +packet|codec_type=video|stream_index=0|pts=71071|pts_time=2.369033|dts=70070|dts_time=2.335667|duration=1001|duration_time=0.033367|size=3365|pos=659310|flags=___ +packet|codec_type=video|stream_index=0|pts=73073|pts_time=2.435767|dts=71071|dts_time=2.369033|duration=1001|duration_time=0.033367|size=24803|pos=664201|flags=___ +packet|codec_type=video|stream_index=0|pts=77077|pts_time=2.569233|dts=72072|dts_time=2.402400|duration=1001|duration_time=0.033367|size=22185|pos=689763|flags=___ +packet|codec_type=video|stream_index=0|pts=75075|pts_time=2.502500|dts=73073|dts_time=2.435767|duration=1001|duration_time=0.033367|size=5088|pos=712679|flags=___ +packet|codec_type=video|stream_index=0|pts=74074|pts_time=2.469133|dts=74074|dts_time=2.469133|duration=1001|duration_time=0.033367|size=537|pos=719128|flags=___ +packet|codec_type=video|stream_index=0|pts=76076|pts_time=2.535867|dts=75075|dts_time=2.502500|duration=1001|duration_time=0.033367|size=3765|pos=720413|flags=___ +packet|codec_type=video|stream_index=0|pts=81081|pts_time=2.702700|dts=76076|dts_time=2.535867|duration=1001|duration_time=0.033367|size=20654|pos=725583|flags=___ +packet|codec_type=video|stream_index=0|pts=79079|pts_time=2.635967|dts=77077|dts_time=2.569233|duration=1001|duration_time=0.033367|size=10202|pos=746999|flags=___ +packet|codec_type=video|stream_index=0|pts=78078|pts_time=2.602600|dts=78078|dts_time=2.602600|duration=1001|duration_time=0.033367|size=3970|pos=758705|flags=___ +packet|codec_type=video|stream_index=0|pts=80080|pts_time=2.669333|dts=79079|dts_time=2.635967|duration=1001|duration_time=0.033367|size=421|pos=763442|flags=___ +packet|codec_type=video|stream_index=0|pts=84084|pts_time=2.802800|dts=80080|dts_time=2.669333|duration=1001|duration_time=0.033367|size=25685|pos=764653|flags=___ +packet|codec_type=video|stream_index=0|pts=82082|pts_time=2.736067|dts=81081|dts_time=2.702700|duration=1001|duration_time=0.033367|size=4077|pos=791911|flags=___ +packet|codec_type=video|stream_index=0|pts=83083|pts_time=2.769433|dts=82082|dts_time=2.736067|duration=1001|duration_time=0.033367|size=3049|pos=796780|flags=___ +packet|codec_type=video|stream_index=0|pts=88088|pts_time=2.936267|dts=83083|dts_time=2.769433|duration=1001|duration_time=0.033367|size=8924|pos=801473|flags=___ +packet|codec_type=video|stream_index=0|pts=86086|pts_time=2.869533|dts=84084|dts_time=2.802800|duration=1001|duration_time=0.033367|size=2512|pos=811078|flags=___ +packet|codec_type=video|stream_index=0|pts=85085|pts_time=2.836167|dts=85085|dts_time=2.836167|duration=1001|duration_time=0.033367|size=163|pos=815033|flags=___ +packet|codec_type=video|stream_index=0|pts=87087|pts_time=2.902900|dts=86086|dts_time=2.869533|duration=1001|duration_time=0.033367|size=1734|pos=815934|flags=___ +packet|codec_type=video|stream_index=0|pts=90090|pts_time=3.003000|dts=87087|dts_time=2.902900|duration=1001|duration_time=0.033367|size=11505|pos=819088|flags=___ +packet|codec_type=video|stream_index=0|pts=89089|pts_time=2.969633|dts=88088|dts_time=2.936267|duration=1001|duration_time=0.033367|size=1431|pos=831367|flags=___ +packet|codec_type=video|stream_index=0|pts=92092|pts_time=3.069733|dts=89089|dts_time=2.969633|duration=1001|duration_time=0.033367|size=5269|pos=833580|flags=___ +packet|codec_type=video|stream_index=0|pts=91091|pts_time=3.036367|dts=90090|dts_time=3.003000|duration=1001|duration_time=0.033367|size=199|pos=840352|flags=___ +packet|codec_type=video|stream_index=0|pts=93093|pts_time=3.103100|dts=91091|dts_time=3.036367|duration=1001|duration_time=0.033367|size=85650|pos=841722|flags=K__ +packet|codec_type=video|stream_index=0|pts=95095|pts_time=3.169833|dts=92092|dts_time=3.069733|duration=1001|duration_time=0.033367|size=13261|pos=928747|flags=___ +packet|codec_type=video|stream_index=0|pts=94094|pts_time=3.136467|dts=93093|dts_time=3.103100|duration=1001|duration_time=0.033367|size=1667|pos=942741|flags=___ +packet|codec_type=video|stream_index=0|pts=99099|pts_time=3.303300|dts=94094|dts_time=3.136467|duration=1001|duration_time=0.033367|size=20143|pos=945841|flags=___ +packet|codec_type=video|stream_index=0|pts=97097|pts_time=3.236567|dts=95095|dts_time=3.169833|duration=1001|duration_time=0.033367|size=2484|pos=966681|flags=___ +packet|codec_type=video|stream_index=0|pts=96096|pts_time=3.203200|dts=96096|dts_time=3.203200|duration=1001|duration_time=0.033367|size=278|pos=969887|flags=___ +packet|codec_type=video|stream_index=0|pts=98098|pts_time=3.269933|dts=97097|dts_time=3.236567|duration=1001|duration_time=0.033367|size=1539|pos=971696|flags=___ +packet|codec_type=video|stream_index=0|pts=101101|pts_time=3.370033|dts=98098|dts_time=3.269933|duration=1001|duration_time=0.033367|size=20270|pos=974088|flags=___ +packet|codec_type=video|stream_index=0|pts=100100|pts_time=3.336667|dts=99099|dts_time=3.303300|duration=1001|duration_time=0.033367|size=1754|pos=995975|flags=___ +packet|codec_type=video|stream_index=0|pts=105105|pts_time=3.503500|dts=100100|dts_time=3.336667|duration=1001|duration_time=0.033367|size=19154|pos=998420|flags=___ +packet|codec_type=video|stream_index=0|pts=103103|pts_time=3.436767|dts=101101|dts_time=3.370033|duration=1001|duration_time=0.033367|size=3359|pos=1019010|flags=___ +packet|codec_type=video|stream_index=0|pts=102102|pts_time=3.403400|dts=102102|dts_time=3.403400|duration=1001|duration_time=0.033367|size=287|pos=1023138|flags=___ +packet|codec_type=video|stream_index=0|pts=104104|pts_time=3.470133|dts=103103|dts_time=3.436767|duration=1001|duration_time=0.033367|size=2111|pos=1024928|flags=___ +packet|codec_type=video|stream_index=0|pts=109109|pts_time=3.636967|dts=104104|dts_time=3.470133|duration=1001|duration_time=0.033367|size=17178|pos=1027833|flags=___ +packet|codec_type=video|stream_index=0|pts=107107|pts_time=3.570233|dts=105105|dts_time=3.503500|duration=1001|duration_time=0.033367|size=7205|pos=1045716|flags=___ +packet|codec_type=video|stream_index=0|pts=106106|pts_time=3.536867|dts=106106|dts_time=3.536867|duration=1001|duration_time=0.033367|size=2209|pos=1054354|flags=___ +packet|codec_type=video|stream_index=0|pts=108108|pts_time=3.603600|dts=107107|dts_time=3.570233|duration=1001|duration_time=0.033367|size=359|pos=1057226|flags=___ +packet|codec_type=video|stream_index=0|pts=113113|pts_time=3.770433|dts=108108|dts_time=3.603600|duration=1001|duration_time=0.033367|size=18469|pos=1059024|flags=___ +packet|codec_type=video|stream_index=0|pts=111111|pts_time=3.703700|dts=109109|dts_time=3.636967|duration=1001|duration_time=0.033367|size=3314|pos=1078213|flags=___ +packet|codec_type=video|stream_index=0|pts=110110|pts_time=3.670333|dts=110110|dts_time=3.670333|duration=1001|duration_time=0.033367|size=2556|pos=1083059|flags=___ +packet|codec_type=video|stream_index=0|pts=112112|pts_time=3.737067|dts=111111|dts_time=3.703700|duration=1001|duration_time=0.033367|size=437|pos=1086388|flags=___ +packet|codec_type=video|stream_index=0|pts=117117|pts_time=3.903900|dts=112112|dts_time=3.737067|duration=1001|duration_time=0.033367|size=19707|pos=1087610|flags=___ +packet|codec_type=video|stream_index=0|pts=115115|pts_time=3.837167|dts=113113|dts_time=3.770433|duration=1001|duration_time=0.033367|size=5917|pos=1108845|flags=___ +packet|codec_type=video|stream_index=0|pts=114114|pts_time=3.803800|dts=114114|dts_time=3.803800|duration=1001|duration_time=0.033367|size=2613|pos=1115495|flags=___ +packet|codec_type=video|stream_index=0|pts=116116|pts_time=3.870533|dts=115115|dts_time=3.837167|duration=1001|duration_time=0.033367|size=2672|pos=1119530|flags=___ +packet|codec_type=video|stream_index=0|pts=121121|pts_time=4.037367|dts=116116|dts_time=3.870533|duration=1001|duration_time=0.033367|size=19091|pos=1122970|flags=_D_ +packet|codec_type=video|stream_index=0|pts=119119|pts_time=3.970633|dts=117117|dts_time=3.903900|duration=1001|duration_time=0.033367|size=9244|pos=1143585|flags=___ +packet|codec_type=video|stream_index=0|pts=118118|pts_time=3.937267|dts=118118|dts_time=3.937267|duration=1001|duration_time=0.033367|size=284|pos=1153587|flags=___ +packet|codec_type=video|stream_index=0|pts=120120|pts_time=4.004000|dts=119119|dts_time=3.970633|duration=1001|duration_time=0.033367|size=2381|pos=1155393|flags=_D_ diff --git a/tests/ref/fate/mov-mp4-extended-atom b/tests/ref/fate/mov-mp4-extended-atom index 9d01abb2f5f..18d42b2a2b2 100644 --- a/tests/ref/fate/mov-mp4-extended-atom +++ b/tests/ref/fate/mov-mp4-extended-atom @@ -1 +1 @@ -packet|codec_type=video|stream_index=0|pts=0|pts_time=0.000000|dts=0|dts_time=0.000000|duration=1001|duration_time=0.033367|size=14798|pos=16|flags=K_ +packet|codec_type=video|stream_index=0|pts=0|pts_time=0.000000|dts=0|dts_time=0.000000|duration=1001|duration_time=0.033367|size=14798|pos=16|flags=K__ diff --git a/tests/ref/fate/mov-mp4-ttml-dfxp b/tests/ref/fate/mov-mp4-ttml-dfxp index e24b5d618bd..15f4f9b69bd 100644 --- a/tests/ref/fate/mov-mp4-ttml-dfxp +++ b/tests/ref/fate/mov-mp4-ttml-dfxp @@ -17,7 +17,7 @@ "duration_time": "68.500000", "size": "7866", "pos": "44", - "flags": "K_" + "flags": "K__" } ], "programs": [ diff --git a/tests/ref/fate/mov-mp4-ttml-stpp b/tests/ref/fate/mov-mp4-ttml-stpp index 77bd23b7bf5..7726cd332e2 100644 --- a/tests/ref/fate/mov-mp4-ttml-stpp +++ b/tests/ref/fate/mov-mp4-ttml-stpp @@ -17,7 +17,7 @@ cbd2c7ff864a663b0d893deac5a0caec *tests/data/fate/mov-mp4-ttml-stpp.mp4 "duration_time": "68.500000", "size": "7866", "pos": "44", - "flags": "K_" + "flags": "K__" } ], "programs": [ diff --git a/tests/ref/fate/mov-zombie b/tests/ref/fate/mov-zombie index a0195651c7c..49730a2e889 100644 --- a/tests/ref/fate/mov-zombie +++ b/tests/ref/fate/mov-zombie @@ -1,197 +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=__ +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|duration=3003|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=__ +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|duration=3003|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=__ +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|duration=3003|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=__ +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|duration=3003|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=__ +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|duration=3003|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=__ +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|duration=3003|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=__ +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|duration=3003|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=__ +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|duration=3003|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=__ +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|duration=3003|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=__ +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|duration=3003|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=__ +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|duration=3003|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=__ +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|duration=3003|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=__ +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|duration=3003|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=__ +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|duration=3003|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=__ +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|duration=3003|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=__ +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|duration=3003|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=__ +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|duration=3003|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=__ +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|duration=3003|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=__ +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|duration=3003|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=__ +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|duration=3003|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=__ +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|duration=3003|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=__ +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|duration=3003|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=__ +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|duration=3003|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_ +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|duration=3003|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=__ +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|duration=3003|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=__ +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|duration=3003|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=__ +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|duration=3003|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=__ +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|duration=3003|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=__ +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|duration=3003|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=__ +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|duration=3003|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=__ +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|duration=3003|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=__ +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|duration=3003|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=__ +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|duration=3003|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=__ +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|duration=3003|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=__ +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|duration=3003|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=__ +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|duration=3003|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=__ +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|duration=3003|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=__ +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|duration=3003|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=__ +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|duration=3003|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=__ +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|duration=3003|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=__ +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|duration=3003|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=__ +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|duration=3003|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=__ +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|duration=3003|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=__ +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|duration=3003|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=__ +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|duration=3003|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=__ +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|duration=3003|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=__ +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|duration=3003|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_ +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|duration=3003|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=__ +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|duration=3003|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=__ +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|duration=3003|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=__ +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|duration=3003|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=__ +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|duration=3003|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=__ +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|duration=3003|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=__ +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|duration=3003|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=__ +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|duration=3003|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=__ +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|duration=3003|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=__ +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|duration=3003|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=__ +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|duration=3003|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=__ +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|duration=3003|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=__ +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|duration=3003|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=__ +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|duration=3003|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=__ +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|duration=3003|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=__ +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|duration=3003|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=__ +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|duration=3003|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=__ +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=__C 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|duration=3003|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 diff --git a/tests/ref/fate/oggopus-demux b/tests/ref/fate/oggopus-demux index ad24639bf4c..54bccb38853 100644 --- a/tests/ref/fate/oggopus-demux +++ b/tests/ref/fate/oggopus-demux @@ -1,45 +1,45 @@ -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_|data_hash=CRC32:052ff811|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__|data_hash=CRC32:052ff811|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=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 -packet|codec_type=audio|stream_index=0|pts=2524|pts_time=0.052583|dts=2524|dts_time=0.052583|duration=960|duration_time=0.020000|size=218|pos=841|flags=K_|data_hash=CRC32:3326bc9f -packet|codec_type=audio|stream_index=0|pts=3484|pts_time=0.072583|dts=3484|dts_time=0.072583|duration=960|duration_time=0.020000|size=218|pos=841|flags=K_|data_hash=CRC32:e341a3da -packet|codec_type=audio|stream_index=0|pts=4444|pts_time=0.092583|dts=4444|dts_time=0.092583|duration=960|duration_time=0.020000|size=194|pos=841|flags=K_|data_hash=CRC32:59dcb3fb -packet|codec_type=audio|stream_index=0|pts=5404|pts_time=0.112583|dts=5404|dts_time=0.112583|duration=960|duration_time=0.020000|size=216|pos=841|flags=K_|data_hash=CRC32:7b5566f5 -packet|codec_type=audio|stream_index=0|pts=6364|pts_time=0.132583|dts=6364|dts_time=0.132583|duration=960|duration_time=0.020000|size=218|pos=841|flags=K_|data_hash=CRC32:e95e91d1 -packet|codec_type=audio|stream_index=0|pts=7324|pts_time=0.152583|dts=7324|dts_time=0.152583|duration=960|duration_time=0.020000|size=218|pos=841|flags=K_|data_hash=CRC32:4e2a2dcd -packet|codec_type=audio|stream_index=0|pts=8284|pts_time=0.172583|dts=8284|dts_time=0.172583|duration=960|duration_time=0.020000|size=219|pos=841|flags=K_|data_hash=CRC32:8d3e1e9c -packet|codec_type=audio|stream_index=0|pts=9244|pts_time=0.192583|dts=9244|dts_time=0.192583|duration=960|duration_time=0.020000|size=218|pos=841|flags=K_|data_hash=CRC32:0cf422f3 -packet|codec_type=audio|stream_index=0|pts=10204|pts_time=0.212583|dts=10204|dts_time=0.212583|duration=960|duration_time=0.020000|size=217|pos=841|flags=K_|data_hash=CRC32:e683509f -packet|codec_type=audio|stream_index=0|pts=11164|pts_time=0.232583|dts=11164|dts_time=0.232583|duration=960|duration_time=0.020000|size=218|pos=841|flags=K_|data_hash=CRC32:53c28210 -packet|codec_type=audio|stream_index=0|pts=12124|pts_time=0.252583|dts=12124|dts_time=0.252583|duration=960|duration_time=0.020000|size=222|pos=841|flags=K_|data_hash=CRC32:1e7778cb -packet|codec_type=audio|stream_index=0|pts=13084|pts_time=0.272583|dts=13084|dts_time=0.272583|duration=960|duration_time=0.020000|size=218|pos=841|flags=K_|data_hash=CRC32:ea403207 -packet|codec_type=audio|stream_index=0|pts=14044|pts_time=0.292583|dts=14044|dts_time=0.292583|duration=960|duration_time=0.020000|size=217|pos=841|flags=K_|data_hash=CRC32:9a8e4930 -packet|codec_type=audio|stream_index=0|pts=15004|pts_time=0.312583|dts=15004|dts_time=0.312583|duration=960|duration_time=0.020000|size=210|pos=841|flags=K_|data_hash=CRC32:afbec644 -packet|codec_type=audio|stream_index=0|pts=15964|pts_time=0.332583|dts=15964|dts_time=0.332583|duration=960|duration_time=0.020000|size=216|pos=841|flags=K_|data_hash=CRC32:0f8f7901 -packet|codec_type=audio|stream_index=0|pts=16924|pts_time=0.352583|dts=16924|dts_time=0.352583|duration=960|duration_time=0.020000|size=203|pos=841|flags=K_|data_hash=CRC32:e8c6eb24 -packet|codec_type=audio|stream_index=0|pts=17884|pts_time=0.372583|dts=17884|dts_time=0.372583|duration=960|duration_time=0.020000|size=209|pos=841|flags=K_|data_hash=CRC32:5fdfb02e -packet|codec_type=audio|stream_index=0|pts=18844|pts_time=0.392583|dts=18844|dts_time=0.392583|duration=960|duration_time=0.020000|size=217|pos=841|flags=K_|data_hash=CRC32:a72182be -packet|codec_type=audio|stream_index=0|pts=19804|pts_time=0.412583|dts=19804|dts_time=0.412583|duration=960|duration_time=0.020000|size=218|pos=841|flags=K_|data_hash=CRC32:ede6d275 -packet|codec_type=audio|stream_index=0|pts=20764|pts_time=0.432583|dts=20764|dts_time=0.432583|duration=960|duration_time=0.020000|size=219|pos=841|flags=K_|data_hash=CRC32:b9d28f17 -packet|codec_type=audio|stream_index=0|pts=21724|pts_time=0.452583|dts=21724|dts_time=0.452583|duration=960|duration_time=0.020000|size=217|pos=841|flags=K_|data_hash=CRC32:e0307b65 -packet|codec_type=audio|stream_index=0|pts=22684|pts_time=0.472583|dts=22684|dts_time=0.472583|duration=960|duration_time=0.020000|size=220|pos=841|flags=K_|data_hash=CRC32:dca81c5d -packet|codec_type=audio|stream_index=0|pts=23644|pts_time=0.492583|dts=23644|dts_time=0.492583|duration=960|duration_time=0.020000|size=364|pos=841|flags=K_|data_hash=CRC32:46844268 -packet|codec_type=audio|stream_index=0|pts=24604|pts_time=0.512583|dts=24604|dts_time=0.512583|duration=960|duration_time=0.020000|size=221|pos=841|flags=K_|data_hash=CRC32:bcac731f -packet|codec_type=audio|stream_index=0|pts=25564|pts_time=0.532583|dts=25564|dts_time=0.532583|duration=960|duration_time=0.020000|size=215|pos=841|flags=K_|data_hash=CRC32:cf6f9041 -packet|codec_type=audio|stream_index=0|pts=26524|pts_time=0.552583|dts=26524|dts_time=0.552583|duration=960|duration_time=0.020000|size=215|pos=841|flags=K_|data_hash=CRC32:903fc52d -packet|codec_type=audio|stream_index=0|pts=27484|pts_time=0.572583|dts=27484|dts_time=0.572583|duration=960|duration_time=0.020000|size=218|pos=841|flags=K_|data_hash=CRC32:2d204bcc -packet|codec_type=audio|stream_index=0|pts=28444|pts_time=0.592583|dts=28444|dts_time=0.592583|duration=960|duration_time=0.020000|size=216|pos=841|flags=K_|data_hash=CRC32:8fa7b453 -packet|codec_type=audio|stream_index=0|pts=29404|pts_time=0.612583|dts=29404|dts_time=0.612583|duration=960|duration_time=0.020000|size=216|pos=841|flags=K_|data_hash=CRC32:8fefaa27 -packet|codec_type=audio|stream_index=0|pts=30364|pts_time=0.632583|dts=30364|dts_time=0.632583|duration=960|duration_time=0.020000|size=216|pos=841|flags=K_|data_hash=CRC32:dc96ebe2 -packet|codec_type=audio|stream_index=0|pts=31324|pts_time=0.652583|dts=31324|dts_time=0.652583|duration=960|duration_time=0.020000|size=215|pos=841|flags=K_|data_hash=CRC32:47e4da62 -packet|codec_type=audio|stream_index=0|pts=32284|pts_time=0.672583|dts=32284|dts_time=0.672583|duration=960|duration_time=0.020000|size=219|pos=841|flags=K_|data_hash=CRC32:b822d69d -packet|codec_type=audio|stream_index=0|pts=33244|pts_time=0.692583|dts=33244|dts_time=0.692583|duration=960|duration_time=0.020000|size=220|pos=841|flags=K_|data_hash=CRC32:c7f5cf20 -packet|codec_type=audio|stream_index=0|pts=34204|pts_time=0.712583|dts=34204|dts_time=0.712583|duration=960|duration_time=0.020000|size=218|pos=841|flags=K_|data_hash=CRC32:f9fed5d8 -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_|data_hash=CRC32:01ca3f8f|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=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 +packet|codec_type=audio|stream_index=0|pts=2524|pts_time=0.052583|dts=2524|dts_time=0.052583|duration=960|duration_time=0.020000|size=218|pos=841|flags=K__|data_hash=CRC32:3326bc9f +packet|codec_type=audio|stream_index=0|pts=3484|pts_time=0.072583|dts=3484|dts_time=0.072583|duration=960|duration_time=0.020000|size=218|pos=841|flags=K__|data_hash=CRC32:e341a3da +packet|codec_type=audio|stream_index=0|pts=4444|pts_time=0.092583|dts=4444|dts_time=0.092583|duration=960|duration_time=0.020000|size=194|pos=841|flags=K__|data_hash=CRC32:59dcb3fb +packet|codec_type=audio|stream_index=0|pts=5404|pts_time=0.112583|dts=5404|dts_time=0.112583|duration=960|duration_time=0.020000|size=216|pos=841|flags=K__|data_hash=CRC32:7b5566f5 +packet|codec_type=audio|stream_index=0|pts=6364|pts_time=0.132583|dts=6364|dts_time=0.132583|duration=960|duration_time=0.020000|size=218|pos=841|flags=K__|data_hash=CRC32:e95e91d1 +packet|codec_type=audio|stream_index=0|pts=7324|pts_time=0.152583|dts=7324|dts_time=0.152583|duration=960|duration_time=0.020000|size=218|pos=841|flags=K__|data_hash=CRC32:4e2a2dcd +packet|codec_type=audio|stream_index=0|pts=8284|pts_time=0.172583|dts=8284|dts_time=0.172583|duration=960|duration_time=0.020000|size=219|pos=841|flags=K__|data_hash=CRC32:8d3e1e9c +packet|codec_type=audio|stream_index=0|pts=9244|pts_time=0.192583|dts=9244|dts_time=0.192583|duration=960|duration_time=0.020000|size=218|pos=841|flags=K__|data_hash=CRC32:0cf422f3 +packet|codec_type=audio|stream_index=0|pts=10204|pts_time=0.212583|dts=10204|dts_time=0.212583|duration=960|duration_time=0.020000|size=217|pos=841|flags=K__|data_hash=CRC32:e683509f +packet|codec_type=audio|stream_index=0|pts=11164|pts_time=0.232583|dts=11164|dts_time=0.232583|duration=960|duration_time=0.020000|size=218|pos=841|flags=K__|data_hash=CRC32:53c28210 +packet|codec_type=audio|stream_index=0|pts=12124|pts_time=0.252583|dts=12124|dts_time=0.252583|duration=960|duration_time=0.020000|size=222|pos=841|flags=K__|data_hash=CRC32:1e7778cb +packet|codec_type=audio|stream_index=0|pts=13084|pts_time=0.272583|dts=13084|dts_time=0.272583|duration=960|duration_time=0.020000|size=218|pos=841|flags=K__|data_hash=CRC32:ea403207 +packet|codec_type=audio|stream_index=0|pts=14044|pts_time=0.292583|dts=14044|dts_time=0.292583|duration=960|duration_time=0.020000|size=217|pos=841|flags=K__|data_hash=CRC32:9a8e4930 +packet|codec_type=audio|stream_index=0|pts=15004|pts_time=0.312583|dts=15004|dts_time=0.312583|duration=960|duration_time=0.020000|size=210|pos=841|flags=K__|data_hash=CRC32:afbec644 +packet|codec_type=audio|stream_index=0|pts=15964|pts_time=0.332583|dts=15964|dts_time=0.332583|duration=960|duration_time=0.020000|size=216|pos=841|flags=K__|data_hash=CRC32:0f8f7901 +packet|codec_type=audio|stream_index=0|pts=16924|pts_time=0.352583|dts=16924|dts_time=0.352583|duration=960|duration_time=0.020000|size=203|pos=841|flags=K__|data_hash=CRC32:e8c6eb24 +packet|codec_type=audio|stream_index=0|pts=17884|pts_time=0.372583|dts=17884|dts_time=0.372583|duration=960|duration_time=0.020000|size=209|pos=841|flags=K__|data_hash=CRC32:5fdfb02e +packet|codec_type=audio|stream_index=0|pts=18844|pts_time=0.392583|dts=18844|dts_time=0.392583|duration=960|duration_time=0.020000|size=217|pos=841|flags=K__|data_hash=CRC32:a72182be +packet|codec_type=audio|stream_index=0|pts=19804|pts_time=0.412583|dts=19804|dts_time=0.412583|duration=960|duration_time=0.020000|size=218|pos=841|flags=K__|data_hash=CRC32:ede6d275 +packet|codec_type=audio|stream_index=0|pts=20764|pts_time=0.432583|dts=20764|dts_time=0.432583|duration=960|duration_time=0.020000|size=219|pos=841|flags=K__|data_hash=CRC32:b9d28f17 +packet|codec_type=audio|stream_index=0|pts=21724|pts_time=0.452583|dts=21724|dts_time=0.452583|duration=960|duration_time=0.020000|size=217|pos=841|flags=K__|data_hash=CRC32:e0307b65 +packet|codec_type=audio|stream_index=0|pts=22684|pts_time=0.472583|dts=22684|dts_time=0.472583|duration=960|duration_time=0.020000|size=220|pos=841|flags=K__|data_hash=CRC32:dca81c5d +packet|codec_type=audio|stream_index=0|pts=23644|pts_time=0.492583|dts=23644|dts_time=0.492583|duration=960|duration_time=0.020000|size=364|pos=841|flags=K__|data_hash=CRC32:46844268 +packet|codec_type=audio|stream_index=0|pts=24604|pts_time=0.512583|dts=24604|dts_time=0.512583|duration=960|duration_time=0.020000|size=221|pos=841|flags=K__|data_hash=CRC32:bcac731f +packet|codec_type=audio|stream_index=0|pts=25564|pts_time=0.532583|dts=25564|dts_time=0.532583|duration=960|duration_time=0.020000|size=215|pos=841|flags=K__|data_hash=CRC32:cf6f9041 +packet|codec_type=audio|stream_index=0|pts=26524|pts_time=0.552583|dts=26524|dts_time=0.552583|duration=960|duration_time=0.020000|size=215|pos=841|flags=K__|data_hash=CRC32:903fc52d +packet|codec_type=audio|stream_index=0|pts=27484|pts_time=0.572583|dts=27484|dts_time=0.572583|duration=960|duration_time=0.020000|size=218|pos=841|flags=K__|data_hash=CRC32:2d204bcc +packet|codec_type=audio|stream_index=0|pts=28444|pts_time=0.592583|dts=28444|dts_time=0.592583|duration=960|duration_time=0.020000|size=216|pos=841|flags=K__|data_hash=CRC32:8fa7b453 +packet|codec_type=audio|stream_index=0|pts=29404|pts_time=0.612583|dts=29404|dts_time=0.612583|duration=960|duration_time=0.020000|size=216|pos=841|flags=K__|data_hash=CRC32:8fefaa27 +packet|codec_type=audio|stream_index=0|pts=30364|pts_time=0.632583|dts=30364|dts_time=0.632583|duration=960|duration_time=0.020000|size=216|pos=841|flags=K__|data_hash=CRC32:dc96ebe2 +packet|codec_type=audio|stream_index=0|pts=31324|pts_time=0.652583|dts=31324|dts_time=0.652583|duration=960|duration_time=0.020000|size=215|pos=841|flags=K__|data_hash=CRC32:47e4da62 +packet|codec_type=audio|stream_index=0|pts=32284|pts_time=0.672583|dts=32284|dts_time=0.672583|duration=960|duration_time=0.020000|size=219|pos=841|flags=K__|data_hash=CRC32:b822d69d +packet|codec_type=audio|stream_index=0|pts=33244|pts_time=0.692583|dts=33244|dts_time=0.692583|duration=960|duration_time=0.020000|size=220|pos=841|flags=K__|data_hash=CRC32:c7f5cf20 +packet|codec_type=audio|stream_index=0|pts=34204|pts_time=0.712583|dts=34204|dts_time=0.712583|duration=960|duration_time=0.020000|size=218|pos=841|flags=K__|data_hash=CRC32:f9fed5d8 +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__|data_hash=CRC32:01ca3f8f|side_data|side_data_type=Skip Samples|skip_samples=0|discard_padding=604|skip_reason=0|discard_reason=0 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|initial_padding=356|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 f221b45c6d5..08326766646 100644 --- a/tests/ref/fate/ts-demux +++ b/tests/ref/fate/ts-demux @@ -1,46 +1,46 @@ -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_|data_hash=CRC32:9bc8b561|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__|data_hash=CRC32:9bc8b561|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=__|data_hash=CRC32:4f8c97dd|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=___|data_hash=CRC32:4f8c97dd|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=__|data_hash=CRC32:27f259db|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=___|data_hash=CRC32:27f259db|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=__|data_hash=CRC32:a6588b80|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=___|data_hash=CRC32:a6588b80|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=__|data_hash=CRC32:33547f9f|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=___|data_hash=CRC32:33547f9f|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=__|data_hash=CRC32:547f3d4e|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=___|data_hash=CRC32:547f3d4e|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=__|data_hash=CRC32:fb5f4b9e|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=___|data_hash=CRC32:fb5f4b9e|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=__|data_hash=CRC32:1fb84db4|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=___|data_hash=CRC32:1fb84db4|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=__|data_hash=CRC32:77516f2c|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=___|data_hash=CRC32:77516f2c|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=__|data_hash=CRC32:7e6594e5|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=___|data_hash=CRC32:7e6594e5|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=__|data_hash=CRC32:31c8b89d|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=___|data_hash=CRC32:31c8b89d|side_data|side_data_type=MPEGTS Stream ID|id=224 -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_|data_hash=CRC32:25b60d38|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__|data_hash=CRC32:25b60d38|side_data|side_data_type=MPEGTS Stream ID|id=189 -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_|data_hash=CRC32:34b350c9|side_data|side_data_type=MPEGTS Stream ID|id=189 +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__|data_hash=CRC32:34b350c9|side_data|side_data_type=MPEGTS Stream ID|id=189 -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=__|data_hash=CRC32:826f8e8e|side_data|side_data_type=MPEGTS Stream ID|id=224 +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=___|data_hash=CRC32:826f8e8e|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=__|data_hash=CRC32:6b15be8c|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=___|data_hash=CRC32:6b15be8c|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=__|data_hash=CRC32:911b1649|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=___|data_hash=CRC32:911b1649|side_data|side_data_type=MPEGTS Stream ID|id=224 -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_|data_hash=CRC32:d2f2012f|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_C|data_hash=CRC32:d2f2012f|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_|data_hash=CRC32:3dad674a|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_C|data_hash=CRC32:3dad674a|side_data|side_data_type=MPEGTS Stream ID|id=189 -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 +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=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|initial_padding=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|initial_padding=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 9660ed879aa..1d3e647f3c9 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_|data_hash=CRC32:eec8d060|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__|data_hash=CRC32:eec8d060|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_|data_hash=CRC32:c5307335|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__|data_hash=CRC32:c5307335|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_|data_hash=CRC32:6f1c0bfa|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__|data_hash=CRC32:6f1c0bfa|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_|data_hash=CRC32:765b2eab|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__|data_hash=CRC32:765b2eab|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_|data_hash=CRC32:490463dd|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__|data_hash=CRC32:490463dd|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_|data_hash=CRC32:beef1221|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__|data_hash=CRC32:beef1221|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_|data_hash=CRC32:7814e1fe|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__|data_hash=CRC32:7814e1fe|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_|data_hash=CRC32:1e28bf7d|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__|data_hash=CRC32:1e28bf7d|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_|data_hash=CRC32:ac39390f|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__|data_hash=CRC32:ac39390f|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_|data_hash=CRC32:56129f6c|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__|data_hash=CRC32:56129f6c|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_|data_hash=CRC32:444cf0b3|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__|data_hash=CRC32:444cf0b3|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_|data_hash=CRC32:b26188cc|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__|data_hash=CRC32:b26188cc|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_|data_hash=CRC32:550b5ea5|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__|data_hash=CRC32:550b5ea5|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_|data_hash=CRC32:3b587071|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__|data_hash=CRC32:3b587071|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_|data_hash=CRC32:c655d80f|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__|data_hash=CRC32:c655d80f|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_|data_hash=CRC32:4734bf58|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__|data_hash=CRC32:4734bf58|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_|data_hash=CRC32:58ddcd0e|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__|data_hash=CRC32:58ddcd0e|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_|data_hash=CRC32:50786001|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__|data_hash=CRC32:50786001|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_|data_hash=CRC32:4c8c5dc8|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__|data_hash=CRC32:4c8c5dc8|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_|data_hash=CRC32:ad3f1eda|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__|data_hash=CRC32:ad3f1eda|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_|data_hash=CRC32:8b7c8437|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__|data_hash=CRC32:8b7c8437|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_|data_hash=CRC32:c52621e3|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__|data_hash=CRC32:c52621e3|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_|data_hash=CRC32:4b34b632|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__|data_hash=CRC32:4b34b632|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_|data_hash=CRC32:79f06d2c|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__|data_hash=CRC32:79f06d2c|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_|data_hash=CRC32:31136ff8|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__|data_hash=CRC32:31136ff8|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_|data_hash=CRC32:d6cd17f2|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__|data_hash=CRC32:d6cd17f2|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_|data_hash=CRC32:bd4ada7b|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__|data_hash=CRC32:bd4ada7b|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_|data_hash=CRC32:59132b5d|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__|data_hash=CRC32:59132b5d|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_|data_hash=CRC32:6d3ba392|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__|data_hash=CRC32:6d3ba392|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_|data_hash=CRC32:b9341220|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__|data_hash=CRC32:b9341220|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_|data_hash=CRC32:cd0b0be2|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__|data_hash=CRC32:cd0b0be2|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_|data_hash=CRC32:c0a97918|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__|data_hash=CRC32:c0a97918|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_|data_hash=CRC32:b4da2c7e|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__|data_hash=CRC32:b4da2c7e|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_|data_hash=CRC32:aaf0a9b2|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__|data_hash=CRC32:aaf0a9b2|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_|data_hash=CRC32:a09994ed|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__|data_hash=CRC32:a09994ed|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_|data_hash=CRC32:ded67e51|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__|data_hash=CRC32:ded67e51|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_|data_hash=CRC32:17f0a2c0|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__|data_hash=CRC32:17f0a2c0|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_|data_hash=CRC32:92d1d4ad|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__|data_hash=CRC32:92d1d4ad|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_|data_hash=CRC32:3752c787|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__|data_hash=CRC32:3752c787|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_|data_hash=CRC32:ab24f03b|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__|data_hash=CRC32:ab24f03b|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_|data_hash=CRC32:920e19f5|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__|data_hash=CRC32:920e19f5|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_|data_hash=CRC32:951b6d50|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__|data_hash=CRC32:951b6d50|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_|data_hash=CRC32:cfc9eb30|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__|data_hash=CRC32:cfc9eb30|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_|data_hash=CRC32:dd66bb72|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__|data_hash=CRC32:dd66bb72|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_|data_hash=CRC32:67b1c809|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__|data_hash=CRC32:67b1c809|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_|data_hash=CRC32:94d441b0|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__|data_hash=CRC32:94d441b0|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_|data_hash=CRC32:178471e0|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__|data_hash=CRC32:178471e0|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_|data_hash=CRC32:90e30fb2|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__|data_hash=CRC32:90e30fb2|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_|data_hash=CRC32:dd4e1d03|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__|data_hash=CRC32:dd4e1d03|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_|data_hash=CRC32:0e059caf|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__|data_hash=CRC32:0e059caf|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_|data_hash=CRC32:1981fa52|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__|data_hash=CRC32:1981fa52|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_|data_hash=CRC32:6af0ac25|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__|data_hash=CRC32:6af0ac25|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_|data_hash=CRC32:4ed14497|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__|data_hash=CRC32:4ed14497|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_|data_hash=CRC32:b1712b61|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__|data_hash=CRC32:b1712b61|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_|data_hash=CRC32:97469bbe|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__|data_hash=CRC32:97469bbe|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_|data_hash=CRC32:f2f922fc|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__|data_hash=CRC32:f2f922fc|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_|data_hash=CRC32:024f521d|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__|data_hash=CRC32:024f521d|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_|data_hash=CRC32:674d82ba|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__|data_hash=CRC32:674d82ba|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_|data_hash=CRC32:79409537|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__|data_hash=CRC32:79409537|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_|data_hash=CRC32:aad393ee|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__|data_hash=CRC32:aad393ee|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_|data_hash=CRC32:9e2dee75|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__|data_hash=CRC32:9e2dee75|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_|data_hash=CRC32:1d8953b4|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__|data_hash=CRC32:1d8953b4|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_|data_hash=CRC32:3f191e37|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__|data_hash=CRC32:3f191e37|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_|data_hash=CRC32:8e05df12|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__|data_hash=CRC32:8e05df12|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_|data_hash=CRC32:d3d2e07c|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__|data_hash=CRC32:d3d2e07c|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_|data_hash=CRC32:22e0dee4|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__|data_hash=CRC32:22e0dee4|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_|data_hash=CRC32:7e1fae18|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__|data_hash=CRC32:7e1fae18|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_|data_hash=CRC32:213724a0|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__|data_hash=CRC32:213724a0|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_|data_hash=CRC32:f6018f97|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__|data_hash=CRC32:f6018f97|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_|data_hash=CRC32:d917e577|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__|data_hash=CRC32:d917e577|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_|data_hash=CRC32:2860d19c|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__|data_hash=CRC32:2860d19c|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_|data_hash=CRC32:799e404b|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__|data_hash=CRC32:799e404b|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_|data_hash=CRC32:a4c43eaa|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__|data_hash=CRC32:a4c43eaa|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_|data_hash=CRC32:4aa2d0c3|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__|data_hash=CRC32:4aa2d0c3|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_|data_hash=CRC32:b5e19460|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__|data_hash=CRC32:b5e19460|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_|data_hash=CRC32:32445f6b|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__|data_hash=CRC32:32445f6b|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_|data_hash=CRC32:6f370fec|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__|data_hash=CRC32:6f370fec|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_|data_hash=CRC32:43e04e6d|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__|data_hash=CRC32:43e04e6d|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_|data_hash=CRC32:5ed32f7e|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__|data_hash=CRC32:5ed32f7e|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_|data_hash=CRC32:ead85ef4|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__|data_hash=CRC32:ead85ef4|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_|data_hash=CRC32:5f283747|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__|data_hash=CRC32:5f283747|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_|data_hash=CRC32:f4aa30a5|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__|data_hash=CRC32:f4aa30a5|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_|data_hash=CRC32:ad09e32c|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__|data_hash=CRC32:ad09e32c|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_|data_hash=CRC32:57f8004d|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__|data_hash=CRC32:57f8004d|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_|data_hash=CRC32:d862a139|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__|data_hash=CRC32:d862a139|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_|data_hash=CRC32:29ebd249|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__|data_hash=CRC32:29ebd249|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_|data_hash=CRC32:5af83f3e|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__|data_hash=CRC32:5af83f3e|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_|data_hash=CRC32:78784213|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__|data_hash=CRC32:78784213|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_|data_hash=CRC32:cccb4c08|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__|data_hash=CRC32:cccb4c08|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_|data_hash=CRC32:36520804|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__|data_hash=CRC32:36520804|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_|data_hash=CRC32:a9235baa|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__|data_hash=CRC32:a9235baa|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_|data_hash=CRC32:57ae2eef|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__|data_hash=CRC32:57ae2eef|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_|data_hash=CRC32:474f3232|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__|data_hash=CRC32:474f3232|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_|data_hash=CRC32:9a51d488|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__|data_hash=CRC32:9a51d488|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_|data_hash=CRC32:919bc794|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__|data_hash=CRC32:919bc794|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_|data_hash=CRC32:ed8214ad|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__|data_hash=CRC32:ed8214ad|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_|data_hash=CRC32:72fcce4c|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__|data_hash=CRC32:72fcce4c|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_|data_hash=CRC32:2a0143f4|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__|data_hash=CRC32:2a0143f4|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_|data_hash=CRC32:94f1aae1|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__|data_hash=CRC32:94f1aae1|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_|data_hash=CRC32:5565737b|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__|data_hash=CRC32:5565737b|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_|data_hash=CRC32:daea61be|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__|data_hash=CRC32:daea61be|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_|data_hash=CRC32:ee704432|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__|data_hash=CRC32:ee704432|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_|data_hash=CRC32:472aa214|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__|data_hash=CRC32:472aa214|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_|data_hash=CRC32:0b046703|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__|data_hash=CRC32:0b046703|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_|data_hash=CRC32:59bf9bd5|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__|data_hash=CRC32:59bf9bd5|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_|data_hash=CRC32:808ee658|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__|data_hash=CRC32:808ee658|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_|data_hash=CRC32:db581c04|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__|data_hash=CRC32:db581c04|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_|data_hash=CRC32:768d8d82|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__|data_hash=CRC32:768d8d82|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_|data_hash=CRC32:263c4a83|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__|data_hash=CRC32:263c4a83|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_|data_hash=CRC32:4017dc55|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__|data_hash=CRC32:4017dc55|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_|data_hash=CRC32:e6b3c398|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__|data_hash=CRC32:e6b3c398|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_|data_hash=CRC32:37eda28b|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__|data_hash=CRC32:37eda28b|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_|data_hash=CRC32:aa3b5d94|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__|data_hash=CRC32:aa3b5d94|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_|data_hash=CRC32:fc87dbf0|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__|data_hash=CRC32:fc87dbf0|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_|data_hash=CRC32:75795b7e|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__|data_hash=CRC32:75795b7e|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_|data_hash=CRC32:a8a34bb9|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__|data_hash=CRC32:a8a34bb9|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_|data_hash=CRC32:2ebc4e7b|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__|data_hash=CRC32:2ebc4e7b|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_|data_hash=CRC32:53744d32|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__|data_hash=CRC32:53744d32|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_|data_hash=CRC32:d32f77ce|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__|data_hash=CRC32:d32f77ce|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_|data_hash=CRC32:f582287c|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__|data_hash=CRC32:f582287c|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_|data_hash=CRC32:144b9c4b|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__|data_hash=CRC32:144b9c4b|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_|data_hash=CRC32:0cca881f|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__|data_hash=CRC32:0cca881f|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_|data_hash=CRC32:cddb1237|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__|data_hash=CRC32:cddb1237|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_|data_hash=CRC32:10310b68|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__|data_hash=CRC32:10310b68|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_|data_hash=CRC32:dea871f8|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__|data_hash=CRC32:dea871f8|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_|data_hash=CRC32:d27e8c99|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__|data_hash=CRC32:d27e8c99|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_|data_hash=CRC32:3143b0e0|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__|data_hash=CRC32:3143b0e0|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_|data_hash=CRC32:ebc2c2e6|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__|data_hash=CRC32:ebc2c2e6|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_|data_hash=CRC32:dc63972d|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__|data_hash=CRC32:dc63972d|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_|data_hash=CRC32:6b141c19|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__|data_hash=CRC32:6b141c19|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_|data_hash=CRC32:752ada1e|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__|data_hash=CRC32:752ada1e|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_|data_hash=CRC32:36d20d37|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__|data_hash=CRC32:36d20d37|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_|data_hash=CRC32:1455dc2e|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__|data_hash=CRC32:1455dc2e|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_|data_hash=CRC32:c6ffd5fe|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__|data_hash=CRC32:c6ffd5fe|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_|data_hash=CRC32:e4c83b97|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__|data_hash=CRC32:e4c83b97|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_|data_hash=CRC32:ee3f9b5a|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__|data_hash=CRC32:ee3f9b5a|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_|data_hash=CRC32:7d0ee8b4|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__|data_hash=CRC32:7d0ee8b4|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_|data_hash=CRC32:685b64d8|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__|data_hash=CRC32:685b64d8|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_|data_hash=CRC32:ab680b3f|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__|data_hash=CRC32:ab680b3f|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_|data_hash=CRC32:8485bf04|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__|data_hash=CRC32:8485bf04|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_|data_hash=CRC32:60e3ab3b|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__|data_hash=CRC32:60e3ab3b|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_|data_hash=CRC32:cbacc337|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__|data_hash=CRC32:cbacc337|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_|data_hash=CRC32:852be5a3|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__|data_hash=CRC32:852be5a3|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_|data_hash=CRC32:743f04a8|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__|data_hash=CRC32:743f04a8|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_|data_hash=CRC32:0ed88196|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__|data_hash=CRC32:0ed88196|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_|data_hash=CRC32:bf13126e|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__|data_hash=CRC32:bf13126e|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_|data_hash=CRC32:dd160d29|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__|data_hash=CRC32:dd160d29|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_|data_hash=CRC32:65833aa7|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__|data_hash=CRC32:65833aa7|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_|data_hash=CRC32:9343d3d2|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__|data_hash=CRC32:9343d3d2|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_|data_hash=CRC32:7da0cd8d|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__|data_hash=CRC32:7da0cd8d|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_|data_hash=CRC32:8a3298b7|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__|data_hash=CRC32:8a3298b7|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_|data_hash=CRC32:604d40c4|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__|data_hash=CRC32:604d40c4|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_|data_hash=CRC32:ecd7b491|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__|data_hash=CRC32:ecd7b491|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_|data_hash=CRC32:f8907616|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__|data_hash=CRC32:f8907616|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_|data_hash=CRC32:c6701edc|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__|data_hash=CRC32:c6701edc|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_|data_hash=CRC32:ed85bdee|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__|data_hash=CRC32:ed85bdee|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_|data_hash=CRC32:d9ea8517|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__|data_hash=CRC32:d9ea8517|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_|data_hash=CRC32:e396092f|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__|data_hash=CRC32:e396092f|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_|data_hash=CRC32:1c628f31|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__|data_hash=CRC32:1c628f31|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_|data_hash=CRC32:52183b8f|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__|data_hash=CRC32:52183b8f|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_|data_hash=CRC32:bbae2882|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__|data_hash=CRC32:bbae2882|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_|data_hash=CRC32:bb5a7486|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__|data_hash=CRC32:bb5a7486|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_|data_hash=CRC32:ead8306a|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__|data_hash=CRC32:ead8306a|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_|data_hash=CRC32:82db1098|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__|data_hash=CRC32:82db1098|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_|data_hash=CRC32:688f5cb6|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__|data_hash=CRC32:688f5cb6|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_|data_hash=CRC32:fdf34c0b|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__|data_hash=CRC32:fdf34c0b|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_|data_hash=CRC32:802e95d1|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__|data_hash=CRC32:802e95d1|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_|data_hash=CRC32:141404b8|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__|data_hash=CRC32:141404b8|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_|data_hash=CRC32:3e39e373|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__|data_hash=CRC32:3e39e373|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_|data_hash=CRC32:ce8d8234|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__|data_hash=CRC32:ce8d8234|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_|data_hash=CRC32:0f3c194d|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__|data_hash=CRC32:0f3c194d|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_|data_hash=CRC32:3d5d60c4|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__|data_hash=CRC32:3d5d60c4|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_|data_hash=CRC32:f66b2c9f|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__|data_hash=CRC32:f66b2c9f|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_|data_hash=CRC32:44eb2398|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__|data_hash=CRC32:44eb2398|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_|data_hash=CRC32:cec1f69c|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__|data_hash=CRC32:cec1f69c|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_|data_hash=CRC32:57096eb1|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__|data_hash=CRC32:57096eb1|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_|data_hash=CRC32:66999a29|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__|data_hash=CRC32:66999a29|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_|data_hash=CRC32:0e598023|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__|data_hash=CRC32:0e598023|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_|data_hash=CRC32:8e728d2b|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__|data_hash=CRC32:8e728d2b|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_|data_hash=CRC32:7e7549e3|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__|data_hash=CRC32:7e7549e3|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_|data_hash=CRC32:62f96c18|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__|data_hash=CRC32:62f96c18|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_|data_hash=CRC32:48d04b8a|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__|data_hash=CRC32:48d04b8a|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_|data_hash=CRC32:7937563e|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__|data_hash=CRC32:7937563e|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_|data_hash=CRC32:8e573ad0|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__|data_hash=CRC32:8e573ad0|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_|data_hash=CRC32:ece4d7e7|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__|data_hash=CRC32:ece4d7e7|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_|data_hash=CRC32:4ca26e7d|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__|data_hash=CRC32:4ca26e7d|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_|data_hash=CRC32:8c347b2d|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__|data_hash=CRC32:8c347b2d|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_|data_hash=CRC32:b50e55b8|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__|data_hash=CRC32:b50e55b8|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_|data_hash=CRC32:e2ff539f|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__|data_hash=CRC32:e2ff539f|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_|data_hash=CRC32:f86e1c5a|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__|data_hash=CRC32:f86e1c5a|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_|data_hash=CRC32:ff858811|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__|data_hash=CRC32:ff858811|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_|data_hash=CRC32:4b0da83e|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__|data_hash=CRC32:4b0da83e|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_|data_hash=CRC32:605a41a9|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__|data_hash=CRC32:605a41a9|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_|data_hash=CRC32:d32c5756|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__|data_hash=CRC32:d32c5756|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_|data_hash=CRC32:92c557ef|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__|data_hash=CRC32:92c557ef|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_|data_hash=CRC32:c16056ca|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__|data_hash=CRC32:c16056ca|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_|data_hash=CRC32:c84a2e99|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__|data_hash=CRC32:c84a2e99|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_|data_hash=CRC32:d59309d0|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__|data_hash=CRC32:d59309d0|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_|data_hash=CRC32:8312e1ba|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__|data_hash=CRC32:8312e1ba|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_|data_hash=CRC32:12d77a3e|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__|data_hash=CRC32:12d77a3e|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_|data_hash=CRC32:86b417d4|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__|data_hash=CRC32:86b417d4|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_|data_hash=CRC32:a66ed4cf|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__|data_hash=CRC32:a66ed4cf|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_|data_hash=CRC32:b686a5ca|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__|data_hash=CRC32:b686a5ca|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_|data_hash=CRC32:261ce45b|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__|data_hash=CRC32:261ce45b|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_|data_hash=CRC32:cbfbd1bf|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__|data_hash=CRC32:cbfbd1bf|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_|data_hash=CRC32:20b5484f|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__|data_hash=CRC32:20b5484f|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_|data_hash=CRC32:c4d54099|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__|data_hash=CRC32:c4d54099|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_|data_hash=CRC32:cb665fdf|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__|data_hash=CRC32:cb665fdf|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_|data_hash=CRC32:0271ab1f|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__|data_hash=CRC32:0271ab1f|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_|data_hash=CRC32:a82f4ab4|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__|data_hash=CRC32:a82f4ab4|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_|data_hash=CRC32:a1e09e3b|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__|data_hash=CRC32:a1e09e3b|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_|data_hash=CRC32:7b297a73|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__|data_hash=CRC32:7b297a73|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_|data_hash=CRC32:2165ebef|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__|data_hash=CRC32:2165ebef|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_|data_hash=CRC32:b802ae36|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__|data_hash=CRC32:b802ae36|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_|data_hash=CRC32:36ca4657|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__|data_hash=CRC32:36ca4657|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_|data_hash=CRC32:2fe8a70c|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__|data_hash=CRC32:2fe8a70c|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_|data_hash=CRC32:19c3bc8c|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__|data_hash=CRC32:19c3bc8c|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_|data_hash=CRC32:3b6c08d8|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__|data_hash=CRC32:3b6c08d8|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_|data_hash=CRC32:851471f3|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__|data_hash=CRC32:851471f3|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_|data_hash=CRC32:5d33a166|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__|data_hash=CRC32:5d33a166|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_|data_hash=CRC32:d0d1a21b|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__|data_hash=CRC32:d0d1a21b|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_|data_hash=CRC32:c21a3376|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__|data_hash=CRC32:c21a3376|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_|data_hash=CRC32:0daaead6|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__|data_hash=CRC32:0daaead6|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_|data_hash=CRC32:01c07956|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__|data_hash=CRC32:01c07956|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_|data_hash=CRC32:f5b429c1|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__|data_hash=CRC32:f5b429c1|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_|data_hash=CRC32:a46831d9|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__|data_hash=CRC32:a46831d9|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_|data_hash=CRC32:555d2cb1|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__|data_hash=CRC32:555d2cb1|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_|data_hash=CRC32:7670785c|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__|data_hash=CRC32:7670785c|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_|data_hash=CRC32:52a244cd|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__|data_hash=CRC32:52a244cd|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_|data_hash=CRC32:7ad67c41|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__|data_hash=CRC32:7ad67c41|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_|data_hash=CRC32:ddc7990b|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__|data_hash=CRC32:ddc7990b|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_|data_hash=CRC32:8a49bff6|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__|data_hash=CRC32:8a49bff6|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_|data_hash=CRC32:258dc60a|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__|data_hash=CRC32:258dc60a|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_|data_hash=CRC32:2dd6d159|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__|data_hash=CRC32:2dd6d159|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_|data_hash=CRC32:359ba790|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__|data_hash=CRC32:359ba790|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_|data_hash=CRC32:68cbef69|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__|data_hash=CRC32:68cbef69|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_|data_hash=CRC32:cbce1c41|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__|data_hash=CRC32:cbce1c41|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_|data_hash=CRC32:a9a19b23|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__|data_hash=CRC32:a9a19b23|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_|data_hash=CRC32:f31b8def|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__|data_hash=CRC32:f31b8def|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_|data_hash=CRC32:4dd92879|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__|data_hash=CRC32:4dd92879|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_|data_hash=CRC32:7020e4a7|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__|data_hash=CRC32:7020e4a7|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_|data_hash=CRC32:5f56efad|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__|data_hash=CRC32:5f56efad|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_|data_hash=CRC32:4ae7101d|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__|data_hash=CRC32:4ae7101d|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_|data_hash=CRC32:386c5965|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__|data_hash=CRC32:386c5965|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_|data_hash=CRC32:f2701022|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__|data_hash=CRC32:f2701022|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_|data_hash=CRC32:386bfd07|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__|data_hash=CRC32:386bfd07|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_|data_hash=CRC32:080e4345|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__|data_hash=CRC32:080e4345|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_|data_hash=CRC32:4fbaa6b9|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__|data_hash=CRC32:4fbaa6b9|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_|data_hash=CRC32:5c879539|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__|data_hash=CRC32:5c879539|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_|data_hash=CRC32:dac40562|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__|data_hash=CRC32:dac40562|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_|data_hash=CRC32:31f989e0|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__|data_hash=CRC32:31f989e0|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_|data_hash=CRC32:0149cc11|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__|data_hash=CRC32:0149cc11|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_|data_hash=CRC32:1c226514|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__|data_hash=CRC32:1c226514|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_|data_hash=CRC32:991ab49b|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__|data_hash=CRC32:991ab49b|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_|data_hash=CRC32:2803c379|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__|data_hash=CRC32:2803c379|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_|data_hash=CRC32:2d95b53b|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__|data_hash=CRC32:2d95b53b|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_|data_hash=CRC32:2a40955c|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__|data_hash=CRC32:2a40955c|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_|data_hash=CRC32:b46687d4|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__|data_hash=CRC32:b46687d4|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_|data_hash=CRC32:c4ec89eb|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__|data_hash=CRC32:c4ec89eb|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_|data_hash=CRC32:d53fcf9c|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__|data_hash=CRC32:d53fcf9c|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_|data_hash=CRC32:eb9bfc19|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__|data_hash=CRC32:eb9bfc19|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_|data_hash=CRC32:71e70489|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__|data_hash=CRC32:71e70489|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_|data_hash=CRC32:60a96aca|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__|data_hash=CRC32:60a96aca|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_|data_hash=CRC32:ceca878e|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__|data_hash=CRC32:ceca878e|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_|data_hash=CRC32:ab40ffe7|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__|data_hash=CRC32:ab40ffe7|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_|data_hash=CRC32:0f8c3162|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__|data_hash=CRC32:0f8c3162|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_|data_hash=CRC32:af837825|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__|data_hash=CRC32:af837825|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_|data_hash=CRC32:93a1bea9|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__|data_hash=CRC32:93a1bea9|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_|data_hash=CRC32:e7289ab0|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__|data_hash=CRC32:e7289ab0|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_|data_hash=CRC32:4b39626e|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__|data_hash=CRC32:4b39626e|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_|data_hash=CRC32:f4bc91d6|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__|data_hash=CRC32:f4bc91d6|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_|data_hash=CRC32:68dd482f|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__|data_hash=CRC32:68dd482f|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_|data_hash=CRC32:61ab6014|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__|data_hash=CRC32:61ab6014|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_|data_hash=CRC32:232f6af8|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__|data_hash=CRC32:232f6af8|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_|data_hash=CRC32:9a4372e9|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__|data_hash=CRC32:9a4372e9|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_|data_hash=CRC32:f7044435|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__|data_hash=CRC32:f7044435|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_|data_hash=CRC32:2d36f75f|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__|data_hash=CRC32:2d36f75f|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_|data_hash=CRC32:11858457|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__|data_hash=CRC32:11858457|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_|data_hash=CRC32:104cc3b1|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__|data_hash=CRC32:104cc3b1|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_|data_hash=CRC32:8ed3cf9c|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__|data_hash=CRC32:8ed3cf9c|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_|data_hash=CRC32:16b50427|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__|data_hash=CRC32:16b50427|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_|data_hash=CRC32:c5c042c3|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__|data_hash=CRC32:c5c042c3|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_|data_hash=CRC32:722e401f|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__|data_hash=CRC32:722e401f|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_|data_hash=CRC32:831f3604|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__|data_hash=CRC32:831f3604|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_|data_hash=CRC32:7718e73e|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__|data_hash=CRC32:7718e73e|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_|data_hash=CRC32:170731a0|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__|data_hash=CRC32:170731a0|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_|data_hash=CRC32:d73c42a8|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__|data_hash=CRC32:d73c42a8|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_|data_hash=CRC32:854f9a2e|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__|data_hash=CRC32:854f9a2e|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_|data_hash=CRC32:7d64106d|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__|data_hash=CRC32:7d64106d|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_|data_hash=CRC32:02e139fa|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__|data_hash=CRC32:02e139fa|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_|data_hash=CRC32:8b5d5f3b|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__|data_hash=CRC32:8b5d5f3b|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_|data_hash=CRC32:fa25f507|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__|data_hash=CRC32:fa25f507|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_|data_hash=CRC32:ccbf6593|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__|data_hash=CRC32:ccbf6593|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_|data_hash=CRC32:cea23a52|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__|data_hash=CRC32:cea23a52|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_|data_hash=CRC32:3ff8eced|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__|data_hash=CRC32:3ff8eced|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_|data_hash=CRC32:a5d92bfd|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__|data_hash=CRC32:a5d92bfd|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_|data_hash=CRC32:582c9c2e|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__|data_hash=CRC32:582c9c2e|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_|data_hash=CRC32:cc23f8d9|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__|data_hash=CRC32:cc23f8d9|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_|data_hash=CRC32:5b9a2c15|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__|data_hash=CRC32:5b9a2c15|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_|data_hash=CRC32:8c48e7c5|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__|data_hash=CRC32:8c48e7c5|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_|data_hash=CRC32:c431b153|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__|data_hash=CRC32:c431b153|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_|data_hash=CRC32:9cfe17d0|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__|data_hash=CRC32:9cfe17d0|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_|data_hash=CRC32:72510fbb|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__|data_hash=CRC32:72510fbb|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_|data_hash=CRC32:81830ddd|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__|data_hash=CRC32:81830ddd|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_|data_hash=CRC32:43102486|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__|data_hash=CRC32:43102486|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_|data_hash=CRC32:49018a2e|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__|data_hash=CRC32:49018a2e|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_|data_hash=CRC32:3a01967a|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__|data_hash=CRC32:3a01967a|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_|data_hash=CRC32:028a7ab9|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__|data_hash=CRC32:028a7ab9|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_|data_hash=CRC32:012e3f77|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__|data_hash=CRC32:012e3f77|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_|data_hash=CRC32:60935688|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__|data_hash=CRC32:60935688|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_|data_hash=CRC32:1f54722f|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__|data_hash=CRC32:1f54722f|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_|data_hash=CRC32:7786349b|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__|data_hash=CRC32:7786349b|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_|data_hash=CRC32:1be2464d|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__|data_hash=CRC32:1be2464d|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_|data_hash=CRC32:cf6b28b9|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__|data_hash=CRC32:cf6b28b9|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_|data_hash=CRC32:63fa4ab0|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__|data_hash=CRC32:63fa4ab0|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_|data_hash=CRC32:06a8e324|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__|data_hash=CRC32:06a8e324|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_|data_hash=CRC32:c37f55e9|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__|data_hash=CRC32:c37f55e9|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_|data_hash=CRC32:82f8ac84|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__|data_hash=CRC32:82f8ac84|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_|data_hash=CRC32:3ed82724|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__|data_hash=CRC32:3ed82724|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_|data_hash=CRC32:ed21dfec|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__|data_hash=CRC32:ed21dfec|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_|data_hash=CRC32:ef20c09c|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__|data_hash=CRC32:ef20c09c|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_|data_hash=CRC32:5f72438e|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__|data_hash=CRC32:5f72438e|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_|data_hash=CRC32:831f56d5|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__|data_hash=CRC32:831f56d5|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_|data_hash=CRC32:a3fb153b|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__|data_hash=CRC32:a3fb153b|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_|data_hash=CRC32:109825ac|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__|data_hash=CRC32:109825ac|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_|data_hash=CRC32:5cb97953|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__|data_hash=CRC32:5cb97953|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_|data_hash=CRC32:9aa43658|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__|data_hash=CRC32:9aa43658|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_|data_hash=CRC32:0ccad3c6|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__|data_hash=CRC32:0ccad3c6|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_|data_hash=CRC32:ee1e951f|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__|data_hash=CRC32:ee1e951f|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_|data_hash=CRC32:7e964664|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__|data_hash=CRC32:7e964664|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_|data_hash=CRC32:46489e72|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__|data_hash=CRC32:46489e72|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_|data_hash=CRC32:528f881d|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__|data_hash=CRC32:528f881d|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_|data_hash=CRC32:e776ddf8|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__|data_hash=CRC32:e776ddf8|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_|data_hash=CRC32:f4d9468d|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__|data_hash=CRC32:f4d9468d|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_|data_hash=CRC32:0b5bc3e0|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__|data_hash=CRC32:0b5bc3e0|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_|data_hash=CRC32:4c6d023d|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__|data_hash=CRC32:4c6d023d|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_|data_hash=CRC32:29588833|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__|data_hash=CRC32:29588833|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_|data_hash=CRC32:12f446a5|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__|data_hash=CRC32:12f446a5|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_|data_hash=CRC32:39a765b6|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__|data_hash=CRC32:39a765b6|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_|data_hash=CRC32:79ab4162|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__|data_hash=CRC32:79ab4162|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_|data_hash=CRC32:1c20d61c|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__|data_hash=CRC32:1c20d61c|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_|data_hash=CRC32:0e5d1ee5|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__|data_hash=CRC32:0e5d1ee5|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_|data_hash=CRC32:27c19b26|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__|data_hash=CRC32:27c19b26|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_|data_hash=CRC32:8ba8ff4c|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__|data_hash=CRC32:8ba8ff4c|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_|data_hash=CRC32:61b51e53|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__|data_hash=CRC32:61b51e53|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_|data_hash=CRC32:223fd4b8|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__|data_hash=CRC32:223fd4b8|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_|data_hash=CRC32:221e6f8a|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__|data_hash=CRC32:221e6f8a|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_|data_hash=CRC32:623d901e|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__|data_hash=CRC32:623d901e|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_|data_hash=CRC32:584cd53d|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__|data_hash=CRC32:584cd53d|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_|data_hash=CRC32:179b3137|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__|data_hash=CRC32:179b3137|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_|data_hash=CRC32:e0e617f2|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__|data_hash=CRC32:e0e617f2|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_|data_hash=CRC32:560639a0|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__|data_hash=CRC32:560639a0|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_|data_hash=CRC32:a88ea02f|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__|data_hash=CRC32:a88ea02f|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_|data_hash=CRC32:6a9f391f|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__|data_hash=CRC32:6a9f391f|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_|data_hash=CRC32:217730ab|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__|data_hash=CRC32:217730ab|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_|data_hash=CRC32:ffa59273|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__|data_hash=CRC32:ffa59273|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_|data_hash=CRC32:05a70a45|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__|data_hash=CRC32:05a70a45|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_|data_hash=CRC32:1e2e4d40|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__|data_hash=CRC32:1e2e4d40|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_|data_hash=CRC32:695b9d24|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__|data_hash=CRC32:695b9d24|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_|data_hash=CRC32:007b90ce|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__|data_hash=CRC32:007b90ce|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_|data_hash=CRC32:188da6de|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__|data_hash=CRC32:188da6de|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_|data_hash=CRC32:1046d54c|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__|data_hash=CRC32:1046d54c|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_|data_hash=CRC32:aa450d3d|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__|data_hash=CRC32:aa450d3d|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_|data_hash=CRC32:80bb936b|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__|data_hash=CRC32:80bb936b|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_|data_hash=CRC32:47bc2556|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__|data_hash=CRC32:47bc2556|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_|data_hash=CRC32:97d4c99c|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__|data_hash=CRC32:97d4c99c|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_|data_hash=CRC32:37252d43|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__|data_hash=CRC32:37252d43|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_|data_hash=CRC32:76918244|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__|data_hash=CRC32:76918244|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_|data_hash=CRC32:5ba0d5d3|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__|data_hash=CRC32:5ba0d5d3|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_|data_hash=CRC32:5b2b81f0|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__|data_hash=CRC32:5b2b81f0|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_|data_hash=CRC32:161f0b38|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__|data_hash=CRC32:161f0b38|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_|data_hash=CRC32:78b4530b|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__|data_hash=CRC32:78b4530b|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_|data_hash=CRC32:c0844a4f|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__|data_hash=CRC32:c0844a4f|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_|data_hash=CRC32:09ef7940|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__|data_hash=CRC32:09ef7940|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_|data_hash=CRC32:053ff4c6|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__|data_hash=CRC32:053ff4c6|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_|data_hash=CRC32:dffb6a19|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__|data_hash=CRC32:dffb6a19|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_|data_hash=CRC32:95240406|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__|data_hash=CRC32:95240406|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_|data_hash=CRC32:e2e8f563|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__|data_hash=CRC32:e2e8f563|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_|data_hash=CRC32:c1c53334|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__|data_hash=CRC32:c1c53334|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_|data_hash=CRC32:f122e957|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__|data_hash=CRC32:f122e957|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_|data_hash=CRC32:cd022652|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__|data_hash=CRC32:cd022652|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_|data_hash=CRC32:909c400c|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__|data_hash=CRC32:909c400c|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_|data_hash=CRC32:7340fb8d|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__|data_hash=CRC32:7340fb8d|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_|data_hash=CRC32:46b59223|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__|data_hash=CRC32:46b59223|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_|data_hash=CRC32:2f1ebb7e|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__|data_hash=CRC32:2f1ebb7e|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_|data_hash=CRC32:b56bee4b|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__|data_hash=CRC32:b56bee4b|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_|data_hash=CRC32:57c778a9|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__|data_hash=CRC32:57c778a9|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_|data_hash=CRC32:599b6964|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__|data_hash=CRC32:599b6964|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_|data_hash=CRC32:2351bfa3|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__|data_hash=CRC32:2351bfa3|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_|data_hash=CRC32:f31f5d14|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__|data_hash=CRC32:f31f5d14|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_|data_hash=CRC32:c0f7f4b5|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__|data_hash=CRC32:c0f7f4b5|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_|data_hash=CRC32:f321de8a|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__|data_hash=CRC32:f321de8a|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_|data_hash=CRC32:64e7e790|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__|data_hash=CRC32:64e7e790|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_|data_hash=CRC32:d9bef93e|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__|data_hash=CRC32:d9bef93e|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_|data_hash=CRC32:b08e677b|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__|data_hash=CRC32:b08e677b|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_|data_hash=CRC32:cc2d57f3|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__|data_hash=CRC32:cc2d57f3|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_|data_hash=CRC32:920b310d|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__|data_hash=CRC32:920b310d|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_|data_hash=CRC32:7547a71e|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__|data_hash=CRC32:7547a71e|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_|data_hash=CRC32:6d0f72a9|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__|data_hash=CRC32:6d0f72a9|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_|data_hash=CRC32:6daae92b|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__|data_hash=CRC32:6daae92b|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_|data_hash=CRC32:8bd8704e|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__|data_hash=CRC32:8bd8704e|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_|data_hash=CRC32:111f49de|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__|data_hash=CRC32:111f49de|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_|data_hash=CRC32:c6e266d5|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__|data_hash=CRC32:c6e266d5|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_|data_hash=CRC32:b0f5283f|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__|data_hash=CRC32:b0f5283f|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_|data_hash=CRC32:f70d4475|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__|data_hash=CRC32:f70d4475|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_|data_hash=CRC32:371078df|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__|data_hash=CRC32:371078df|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_|data_hash=CRC32:c2aa814b|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__|data_hash=CRC32:c2aa814b|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_|data_hash=CRC32:188194bc|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__|data_hash=CRC32:188194bc|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_|data_hash=CRC32:982ba78c|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__|data_hash=CRC32:982ba78c|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_|data_hash=CRC32:bf244c73|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__|data_hash=CRC32:bf244c73|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_|data_hash=CRC32:8bdf82ed|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__|data_hash=CRC32:8bdf82ed|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_|data_hash=CRC32:acb2d4f3|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__|data_hash=CRC32:acb2d4f3|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_|data_hash=CRC32:1cefab3c|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__|data_hash=CRC32:1cefab3c|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_|data_hash=CRC32:0bd02594|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__|data_hash=CRC32:0bd02594|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_|data_hash=CRC32:cc6fff1d|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__|data_hash=CRC32:cc6fff1d|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_|data_hash=CRC32:cb2fc3d9|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__|data_hash=CRC32:cb2fc3d9|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_|data_hash=CRC32:860da403|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__|data_hash=CRC32:860da403|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_|data_hash=CRC32:14aca2c6|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__|data_hash=CRC32:14aca2c6|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_|data_hash=CRC32:c5d24ee7|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__|data_hash=CRC32:c5d24ee7|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_|data_hash=CRC32:91680f09|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__|data_hash=CRC32:91680f09|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_|data_hash=CRC32:c6b2948d|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__|data_hash=CRC32:c6b2948d|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_|data_hash=CRC32:20ff251c|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__|data_hash=CRC32:20ff251c|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_|data_hash=CRC32:d9fa6569|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__|data_hash=CRC32:d9fa6569|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_|data_hash=CRC32:871a83c7|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__|data_hash=CRC32:871a83c7|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_|data_hash=CRC32:ad2423ee|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__|data_hash=CRC32:ad2423ee|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_|data_hash=CRC32:4e9b7b6e|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__|data_hash=CRC32:4e9b7b6e|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_|data_hash=CRC32:4aa3582f|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__|data_hash=CRC32:4aa3582f|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_|data_hash=CRC32:15952f9f|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__|data_hash=CRC32:15952f9f|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_|data_hash=CRC32:55db10c7|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__|data_hash=CRC32:55db10c7|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_|data_hash=CRC32:1cfff77c|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__|data_hash=CRC32:1cfff77c|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_|data_hash=CRC32:93bf7a2e|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__|data_hash=CRC32:93bf7a2e|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_|data_hash=CRC32:75577b1c|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__|data_hash=CRC32:75577b1c|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_|data_hash=CRC32:fe81112c|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__|data_hash=CRC32:fe81112c|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_|data_hash=CRC32:0ddc28c1|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__|data_hash=CRC32:0ddc28c1|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_|data_hash=CRC32:a9dda185|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__|data_hash=CRC32:a9dda185|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_|data_hash=CRC32:e10197bd|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__|data_hash=CRC32:e10197bd|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_|data_hash=CRC32:f1683c68|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__|data_hash=CRC32:f1683c68|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_|data_hash=CRC32:f6eee942|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__|data_hash=CRC32:f6eee942|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_|data_hash=CRC32:6ab1ef22|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__|data_hash=CRC32:6ab1ef22|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_|data_hash=CRC32:6920a9e6|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__|data_hash=CRC32:6920a9e6|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_|data_hash=CRC32:b3ba03c7|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__|data_hash=CRC32:b3ba03c7|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_|data_hash=CRC32:59f04151|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__|data_hash=CRC32:59f04151|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_|data_hash=CRC32:a9300525|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__|data_hash=CRC32:a9300525|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_|data_hash=CRC32:06b28e48|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__|data_hash=CRC32:06b28e48|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_|data_hash=CRC32:99640c9a|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__|data_hash=CRC32:99640c9a|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_|data_hash=CRC32:264f20e3|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__|data_hash=CRC32:264f20e3|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_|data_hash=CRC32:87799aaa|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__|data_hash=CRC32:87799aaa|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_|data_hash=CRC32:b2487f0b|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__|data_hash=CRC32:b2487f0b|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_|data_hash=CRC32:5ff97478|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__|data_hash=CRC32:5ff97478|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_|data_hash=CRC32:ee962000|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__|data_hash=CRC32:ee962000|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_|data_hash=CRC32:65a93707|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__|data_hash=CRC32:65a93707|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_|data_hash=CRC32:f365394f|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__|data_hash=CRC32:f365394f|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_|data_hash=CRC32:cc4aa3e5|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__|data_hash=CRC32:cc4aa3e5|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_|data_hash=CRC32:a1fd5bac|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__|data_hash=CRC32:a1fd5bac|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_|data_hash=CRC32:1590afda|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__|data_hash=CRC32:1590afda|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_|data_hash=CRC32:3e34e250|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__|data_hash=CRC32:3e34e250|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_|data_hash=CRC32:927657b5|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__|data_hash=CRC32:927657b5|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_|data_hash=CRC32:5261b6ab|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__|data_hash=CRC32:5261b6ab|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_|data_hash=CRC32:645fd792|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__|data_hash=CRC32:645fd792|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_|data_hash=CRC32:240a9cd8|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__|data_hash=CRC32:240a9cd8|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_|data_hash=CRC32:409c4ee6|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__|data_hash=CRC32:409c4ee6|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_|data_hash=CRC32:a1e4f6c8|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__|data_hash=CRC32:a1e4f6c8|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_|data_hash=CRC32:e405b6d8|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__|data_hash=CRC32:e405b6d8|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_|data_hash=CRC32:28926870|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__|data_hash=CRC32:28926870|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_|data_hash=CRC32:991eafa7|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__|data_hash=CRC32:991eafa7|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_|data_hash=CRC32:2f2180e4|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__|data_hash=CRC32:2f2180e4|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_|data_hash=CRC32:c3b931ab|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__|data_hash=CRC32:c3b931ab|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_|data_hash=CRC32:09c95d1c|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__|data_hash=CRC32:09c95d1c|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_|data_hash=CRC32:5a90f4d9|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__|data_hash=CRC32:5a90f4d9|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_|data_hash=CRC32:2e1338bd|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__|data_hash=CRC32:2e1338bd|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_|data_hash=CRC32:db87e979|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__|data_hash=CRC32:db87e979|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_|data_hash=CRC32:d55815d6|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__|data_hash=CRC32:d55815d6|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_|data_hash=CRC32:e31e5728|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__|data_hash=CRC32:e31e5728|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_|data_hash=CRC32:49e86c3d|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__|data_hash=CRC32:49e86c3d|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_|data_hash=CRC32:13cefb19|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__|data_hash=CRC32:13cefb19|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_|data_hash=CRC32:8d9b7d72|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__|data_hash=CRC32:8d9b7d72|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_|data_hash=CRC32:d55b35fb|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__|data_hash=CRC32:d55b35fb|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_|data_hash=CRC32:3e10c46a|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__|data_hash=CRC32:3e10c46a|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_|data_hash=CRC32:924e67eb|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__|data_hash=CRC32:924e67eb|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_|data_hash=CRC32:008c6ebb|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__|data_hash=CRC32:008c6ebb|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_|data_hash=CRC32:96d72d3f|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__|data_hash=CRC32:96d72d3f|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_|data_hash=CRC32:6f40bb5a|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__|data_hash=CRC32:6f40bb5a|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_|data_hash=CRC32:f6ba1f01|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__|data_hash=CRC32:f6ba1f01|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_|data_hash=CRC32:b610a31e|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__|data_hash=CRC32:b610a31e|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_|data_hash=CRC32:64dde46b|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__|data_hash=CRC32:64dde46b|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_|data_hash=CRC32:8f794e6c|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__|data_hash=CRC32:8f794e6c|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_|data_hash=CRC32:65c6284c|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__|data_hash=CRC32:65c6284c|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_|data_hash=CRC32:7dead06c|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__|data_hash=CRC32:7dead06c|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_|data_hash=CRC32:b0e145b1|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__|data_hash=CRC32:b0e145b1|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_|data_hash=CRC32:3d2553f6|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__|data_hash=CRC32:3d2553f6|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_|data_hash=CRC32:e808f1d2|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__|data_hash=CRC32:e808f1d2|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_|data_hash=CRC32:6b408528|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__|data_hash=CRC32:6b408528|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_|data_hash=CRC32:e51d96e4|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__|data_hash=CRC32:e51d96e4|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_|data_hash=CRC32:c2df3280|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__|data_hash=CRC32:c2df3280|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_|data_hash=CRC32:7bb5a137|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__|data_hash=CRC32:7bb5a137|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_|data_hash=CRC32:12fcc651|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__|data_hash=CRC32:12fcc651|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_|data_hash=CRC32:b402a4c8|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__|data_hash=CRC32:b402a4c8|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_|data_hash=CRC32:bfe52a16|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__|data_hash=CRC32:bfe52a16|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_|data_hash=CRC32:09372283|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__|data_hash=CRC32:09372283|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_|data_hash=CRC32:5a27db5c|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__|data_hash=CRC32:5a27db5c|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_|data_hash=CRC32:0821b0cd|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__|data_hash=CRC32:0821b0cd|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_|data_hash=CRC32:91af6b99|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__|data_hash=CRC32:91af6b99|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_|data_hash=CRC32:5296a88a|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__|data_hash=CRC32:5296a88a|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_|data_hash=CRC32:e75e69d4|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__|data_hash=CRC32:e75e69d4|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_|data_hash=CRC32:6a5b92cd|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__|data_hash=CRC32:6a5b92cd|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_|data_hash=CRC32:ec30c088|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__|data_hash=CRC32:ec30c088|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_|data_hash=CRC32:2c73f2ff|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__|data_hash=CRC32:2c73f2ff|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_|data_hash=CRC32:7f7cb041|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__|data_hash=CRC32:7f7cb041|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_|data_hash=CRC32:52ef1db9|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__|data_hash=CRC32:52ef1db9|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_|data_hash=CRC32:fdf0ce4a|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__|data_hash=CRC32:fdf0ce4a|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_|data_hash=CRC32:75113c11|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__|data_hash=CRC32:75113c11|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_|data_hash=CRC32:59fc266f|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__|data_hash=CRC32:59fc266f|side_data|side_data_type=MPEGTS Stream ID|id=189 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|initial_padding=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 a0338e08d78..0b12cdde42b 100644 --- a/tests/ref/fate/ts-small-demux +++ b/tests/ref/fate/ts-small-demux @@ -1,149 +1,149 @@ -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_|data_hash=CRC32:9c4b744e|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__|data_hash=CRC32:9c4b744e|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=__|data_hash=CRC32:f5490de8|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=___|data_hash=CRC32:f5490de8|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=__|data_hash=CRC32:d82fbcc0|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=___|data_hash=CRC32:d82fbcc0|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=__|data_hash=CRC32:e062fa20|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=___|data_hash=CRC32:e062fa20|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=__|data_hash=CRC32:49802a80|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=___|data_hash=CRC32:49802a80|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=__|data_hash=CRC32:71cd6c60|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=___|data_hash=CRC32:71cd6c60|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=__|data_hash=CRC32:391aa740|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=___|data_hash=CRC32:391aa740|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=__|data_hash=CRC32:0157e1a0|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=___|data_hash=CRC32:0157e1a0|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=__|data_hash=CRC32:10095665|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=___|data_hash=CRC32:10095665|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=__|data_hash=CRC32:28441085|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=___|data_hash=CRC32:28441085|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=__|data_hash=CRC32:6093dba5|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=___|data_hash=CRC32:6093dba5|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=__|data_hash=CRC32:58de9d45|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=___|data_hash=CRC32:58de9d45|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=__|data_hash=CRC32:f13c4de5|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=___|data_hash=CRC32:f13c4de5|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=__|data_hash=CRC32:c9710b05|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=___|data_hash=CRC32:c9710b05|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=__|data_hash=CRC32:81a6c025|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=___|data_hash=CRC32:81a6c025|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=__|data_hash=CRC32:b9eb86c5|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=___|data_hash=CRC32:b9eb86c5|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=__|data_hash=CRC32:a8b53100|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=___|data_hash=CRC32:a8b53100|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=__|data_hash=CRC32:90f877e0|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=___|data_hash=CRC32:90f877e0|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=__|data_hash=CRC32:d82fbcc0|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=___|data_hash=CRC32:d82fbcc0|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=__|data_hash=CRC32:e062fa20|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=___|data_hash=CRC32:e062fa20|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=__|data_hash=CRC32:49802a80|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=___|data_hash=CRC32:49802a80|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=__|data_hash=CRC32:71cd6c60|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=___|data_hash=CRC32:71cd6c60|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=__|data_hash=CRC32:391aa740|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=___|data_hash=CRC32:391aa740|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=__|data_hash=CRC32:0157e1a0|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=___|data_hash=CRC32:0157e1a0|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=__|data_hash=CRC32:10095665|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=___|data_hash=CRC32:10095665|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=__|data_hash=CRC32:28441085|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=___|data_hash=CRC32:28441085|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=__|data_hash=CRC32:6093dba5|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=___|data_hash=CRC32:6093dba5|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=__|data_hash=CRC32:58de9d45|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=___|data_hash=CRC32:58de9d45|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=__|data_hash=CRC32:f13c4de5|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=___|data_hash=CRC32:f13c4de5|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=__|data_hash=CRC32:c9710b05|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=___|data_hash=CRC32:c9710b05|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=__|data_hash=CRC32:81a6c025|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=___|data_hash=CRC32:81a6c025|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=__|data_hash=CRC32:b9eb86c5|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=___|data_hash=CRC32:b9eb86c5|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=__|data_hash=CRC32:a8b53100|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=___|data_hash=CRC32:a8b53100|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=__|data_hash=CRC32:90f877e0|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=___|data_hash=CRC32:90f877e0|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=__|data_hash=CRC32:d82fbcc0|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=___|data_hash=CRC32:d82fbcc0|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=__|data_hash=CRC32:e062fa20|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=___|data_hash=CRC32:e062fa20|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=__|data_hash=CRC32:49802a80|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=___|data_hash=CRC32:49802a80|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=__|data_hash=CRC32:71cd6c60|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=___|data_hash=CRC32:71cd6c60|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=__|data_hash=CRC32:391aa740|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=___|data_hash=CRC32:391aa740|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=__|data_hash=CRC32:0157e1a0|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=___|data_hash=CRC32:0157e1a0|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=__|data_hash=CRC32:10095665|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=___|data_hash=CRC32:10095665|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=__|data_hash=CRC32:28441085|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=___|data_hash=CRC32:28441085|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=__|data_hash=CRC32:6093dba5|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=___|data_hash=CRC32:6093dba5|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=__|data_hash=CRC32:58de9d45|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=___|data_hash=CRC32:58de9d45|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=__|data_hash=CRC32:f13c4de5|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=___|data_hash=CRC32:f13c4de5|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=__|data_hash=CRC32:c9710b05|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=___|data_hash=CRC32:c9710b05|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=__|data_hash=CRC32:81a6c025|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=___|data_hash=CRC32:81a6c025|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=__|data_hash=CRC32:b9eb86c5|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=___|data_hash=CRC32:b9eb86c5|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=__|data_hash=CRC32:a8b53100|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=___|data_hash=CRC32:a8b53100|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=__|data_hash=CRC32:90f877e0|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=___|data_hash=CRC32:90f877e0|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=__|data_hash=CRC32:d82fbcc0|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=___|data_hash=CRC32:d82fbcc0|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=__|data_hash=CRC32:e062fa20|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=___|data_hash=CRC32:e062fa20|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=__|data_hash=CRC32:49802a80|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=___|data_hash=CRC32:49802a80|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=__|data_hash=CRC32:71cd6c60|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=___|data_hash=CRC32:71cd6c60|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=__|data_hash=CRC32:391aa740|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=___|data_hash=CRC32:391aa740|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=__|data_hash=CRC32:0157e1a0|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=___|data_hash=CRC32:0157e1a0|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=__|data_hash=CRC32:10095665|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=___|data_hash=CRC32:10095665|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=__|data_hash=CRC32:28441085|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=___|data_hash=CRC32:28441085|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=__|data_hash=CRC32:6093dba5|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=___|data_hash=CRC32:6093dba5|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=__|data_hash=CRC32:58de9d45|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=___|data_hash=CRC32:58de9d45|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=__|data_hash=CRC32:f13c4de5|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=___|data_hash=CRC32:f13c4de5|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=__|data_hash=CRC32:c9710b05|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=___|data_hash=CRC32:c9710b05|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=__|data_hash=CRC32:81a6c025|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=___|data_hash=CRC32:81a6c025|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=__|data_hash=CRC32:b9eb86c5|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=___|data_hash=CRC32:b9eb86c5|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=__|data_hash=CRC32:a8b53100|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=___|data_hash=CRC32:a8b53100|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=__|data_hash=CRC32:90f877e0|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=___|data_hash=CRC32:90f877e0|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=__|data_hash=CRC32:d82fbcc0|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=___|data_hash=CRC32:d82fbcc0|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=__|data_hash=CRC32:e062fa20|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=___|data_hash=CRC32:e062fa20|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=__|data_hash=CRC32:49802a80|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=___|data_hash=CRC32:49802a80|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=__|data_hash=CRC32:71cd6c60|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=___|data_hash=CRC32:71cd6c60|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=__|data_hash=CRC32:391aa740|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=___|data_hash=CRC32:391aa740|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=__|data_hash=CRC32:cca62b67|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=___|data_hash=CRC32:cca62b67|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=__|data_hash=CRC32:27b943ef|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=___|data_hash=CRC32:27b943ef|side_data|side_data_type=MPEGTS Stream ID|id=224 -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 +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 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 25f31929b6ede49194ca9231560323829d4da67a Mon Sep 17 00:00:00 2001 From: Marth64 Date: Mon, 6 Feb 2023 12:12:15 -0600 Subject: [PATCH 0181/2172] ffmpeg_opt: move help text for -ab/-b:a to audio category Since at least 4.4.3, -ab/-b:a help text was in the video section of ffmpeg -h, but these are audio options. Signed-off-by: Marth64 Signed-off-by: Anton Khirnov --- fftools/ffmpeg_opt.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/fftools/ffmpeg_opt.c b/fftools/ffmpeg_opt.c index 204be38c94d..799dcf071eb 100644 --- a/fftools/ffmpeg_opt.c +++ b/fftools/ffmpeg_opt.c @@ -1637,8 +1637,6 @@ const OptionDef options[] = { { "force_key_frames", OPT_VIDEO | OPT_STRING | HAS_ARG | OPT_EXPERT | OPT_SPEC | OPT_OUTPUT, { .off = OFFSET(forced_key_frames) }, "force key frames at specified timestamps", "timestamps" }, - { "ab", OPT_VIDEO | HAS_ARG | OPT_PERFILE | OPT_OUTPUT, { .func_arg = opt_bitrate }, - "audio bitrate (please use -b:a)", "bitrate" }, { "b", OPT_VIDEO | HAS_ARG | OPT_PERFILE | OPT_OUTPUT, { .func_arg = opt_bitrate }, "video bitrate (please use -b:v)", "bitrate" }, { "hwaccel", OPT_VIDEO | OPT_STRING | HAS_ARG | OPT_EXPERT | @@ -1680,6 +1678,8 @@ const OptionDef options[] = { { "acodec", OPT_AUDIO | HAS_ARG | OPT_PERFILE | OPT_INPUT | OPT_OUTPUT, { .func_arg = opt_audio_codec }, "force audio codec ('copy' to copy stream)", "codec" }, + { "ab", OPT_AUDIO | HAS_ARG | OPT_PERFILE | OPT_OUTPUT, { .func_arg = opt_bitrate }, + "audio bitrate (please use -b:a)", "bitrate" }, { "atag", OPT_AUDIO | HAS_ARG | OPT_EXPERT | OPT_PERFILE | OPT_OUTPUT, { .func_arg = opt_old2new }, "force audio tag/fourcc", "fourcc/tag" }, From 458ae405ef2eca38e1d16ea3b494830cc686d678 Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Thu, 9 Feb 2023 13:40:00 +0100 Subject: [PATCH 0182/2172] Revert "avfilter/af_pan: fix regression introduced with switch to new channel layout API" This reverts commit 93a9ee7afd7bf2e019490117f1bada30724a0200. Was not fixing real problem, issue is probably outside of pan filter. --- libavfilter/af_pan.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/libavfilter/af_pan.c b/libavfilter/af_pan.c index 80c194b066f..067f6468053 100644 --- a/libavfilter/af_pan.c +++ b/libavfilter/af_pan.c @@ -313,9 +313,7 @@ static int config_props(AVFilterLink *link) pan->channel_map[i] = ch_id; } - av_opt_set_chlayout(pan->swr, "ichl", &link->ch_layout, 0); - av_opt_set_chlayout(pan->swr, "ochl", &pan->out_channel_layout, 0); - av_opt_set_int(pan->swr, "uch", link->ch_layout.nb_channels, 0); + av_opt_set_int(pan->swr, "uch", pan->nb_output_channels, 0); swr_set_channel_mapping(pan->swr, pan->channel_map); } else { // renormalize @@ -335,8 +333,6 @@ static int config_props(AVFilterLink *link) for (j = 0; j < link->ch_layout.nb_channels; j++) pan->gain[i][j] /= t; } - av_opt_set_chlayout(pan->swr, "ichl", &link->ch_layout, 0); - av_opt_set_chlayout(pan->swr, "ochl", &pan->out_channel_layout, 0); swr_set_matrix(pan->swr, pan->gain[0], pan->gain[1] - pan->gain[0]); } From 6d4f3ae116eaa6552434c9c73eb8d84f7be07c91 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Mon, 6 Feb 2023 13:12:05 +0100 Subject: [PATCH 0183/2172] fftools/ffmpeg: store output packet timebases in the packet Useful to keep track of what timebase the packet's timestamps are in. --- fftools/ffmpeg.c | 33 ++++++++++++++++++++------------- fftools/ffmpeg_mux.c | 7 ++++--- 2 files changed, 24 insertions(+), 16 deletions(-) diff --git a/fftools/ffmpeg.c b/fftools/ffmpeg.c index 743bc0c6b67..32e0c3febdb 100644 --- a/fftools/ffmpeg.c +++ b/fftools/ffmpeg.c @@ -797,7 +797,7 @@ static void update_video_stats(OutputStream *ost, const AVPacket *pkt, int write fprintf(vstats_file,"f_size= %6d ", pkt->size); /* compute pts value */ - ti1 = pkt->dts * av_q2d(ost->mux_timebase); + ti1 = pkt->dts * av_q2d(pkt->time_base); if (ti1 < 0.01) ti1 = 0.01; @@ -812,7 +812,7 @@ static void enc_stats_write(OutputStream *ost, EncStats *es, const AVFrame *frame, const AVPacket *pkt) { AVIOContext *io = es->io; - AVRational tb = ost->enc_ctx->time_base; + AVRational tb = frame ? frame->time_base : pkt->time_base; int64_t pts = frame ? frame->pts : pkt->pts; AVRational tbi = (AVRational){ 0, 1}; @@ -912,6 +912,8 @@ static int encode_frame(OutputFile *of, OutputStream *ost, AVFrame *frame) update_benchmark("%s_%s %d.%d", action, type_desc, ost->file_index, ost->index); + pkt->time_base = enc->time_base; + /* if two pass, output log on success and EOF */ if ((ret >= 0 || ret == AVERROR_EOF) && ost->logfile && enc->stats_out) fprintf(ost->logfile, "%s", enc->stats_out); @@ -942,7 +944,8 @@ static int encode_frame(OutputFile *of, OutputStream *ost, AVFrame *frame) av_ts2str(pkt->duration), av_ts2timestr(pkt->duration, &enc->time_base)); } - av_packet_rescale_ts(pkt, enc->time_base, ost->mux_timebase); + av_packet_rescale_ts(pkt, pkt->time_base, ost->mux_timebase); + pkt->time_base = ost->mux_timebase; if (debug_ts) { av_log(ost, AV_LOG_INFO, "encoder -> type:%s " @@ -1103,17 +1106,19 @@ static void do_subtitle_out(OutputFile *of, } av_shrink_packet(pkt, subtitle_out_size); - pkt->pts = av_rescale_q(sub->pts, AV_TIME_BASE_Q, ost->mux_timebase); - pkt->duration = av_rescale_q(sub->end_display_time, (AVRational){ 1, 1000 }, ost->mux_timebase); + pkt->time_base = ost->mux_timebase; + pkt->pts = av_rescale_q(sub->pts, AV_TIME_BASE_Q, pkt->time_base); + pkt->duration = av_rescale_q(sub->end_display_time, (AVRational){ 1, 1000 }, pkt->time_base); if (enc->codec_id == AV_CODEC_ID_DVB_SUBTITLE) { /* XXX: the pts correction is handled here. Maybe handling it in the codec would be better */ if (i == 0) - pkt->pts += av_rescale_q(sub->start_display_time, (AVRational){ 1, 1000 }, ost->mux_timebase); + pkt->pts += av_rescale_q(sub->start_display_time, (AVRational){ 1, 1000 }, pkt->time_base); else - pkt->pts += av_rescale_q(sub->end_display_time, (AVRational){ 1, 1000 }, ost->mux_timebase); + pkt->pts += av_rescale_q(sub->end_display_time, (AVRational){ 1, 1000 }, pkt->time_base); } pkt->dts = pkt->pts; + of_output_packet(of, pkt, ost, 0); } } @@ -1900,25 +1905,27 @@ static void do_streamcopy(InputStream *ist, OutputStream *ost, const AVPacket *p if (av_packet_ref(opkt, pkt) < 0) exit_program(1); + opkt->time_base = ost->mux_timebase; + if (pkt->pts != AV_NOPTS_VALUE) - opkt->pts = av_rescale_q(pkt->pts, ist->st->time_base, ost->mux_timebase) - ost_tb_start_time; + opkt->pts = av_rescale_q(pkt->pts, ist->st->time_base, opkt->time_base) - ost_tb_start_time; if (pkt->dts == AV_NOPTS_VALUE) { - opkt->dts = av_rescale_q(ist->dts, AV_TIME_BASE_Q, ost->mux_timebase); + opkt->dts = av_rescale_q(ist->dts, AV_TIME_BASE_Q, opkt->time_base); } else if (ost->st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) { int duration = av_get_audio_frame_duration2(ist->par, pkt->size); if(!duration) duration = ist->par->frame_size; opkt->dts = av_rescale_delta(ist->st->time_base, pkt->dts, (AVRational){1, ist->par->sample_rate}, duration, - &ist->filter_in_rescale_delta_last, ost->mux_timebase); + &ist->filter_in_rescale_delta_last, opkt->time_base); /* dts will be set immediately afterwards to what pts is now */ opkt->pts = opkt->dts - ost_tb_start_time; } else - opkt->dts = av_rescale_q(pkt->dts, ist->st->time_base, ost->mux_timebase); + opkt->dts = av_rescale_q(pkt->dts, ist->st->time_base, opkt->time_base); opkt->dts -= ost_tb_start_time; - opkt->duration = av_rescale_q(pkt->duration, ist->st->time_base, ost->mux_timebase); + opkt->duration = av_rescale_q(pkt->duration, ist->st->time_base, opkt->time_base); { int ret = trigger_fix_sub_duration_heartbeat(ost, pkt); @@ -2475,7 +2482,7 @@ static int fix_sub_duration_heartbeat(InputStream *ist, int64_t signal_pts) static int trigger_fix_sub_duration_heartbeat(OutputStream *ost, const AVPacket *pkt) { OutputFile *of = output_files[ost->file_index]; - int64_t signal_pts = av_rescale_q(pkt->pts, ost->mux_timebase, + int64_t signal_pts = av_rescale_q(pkt->pts, pkt->time_base, AV_TIME_BASE_Q); if (!ost->fix_sub_duration_heartbeat || !(pkt->flags & AV_PKT_FLAG_KEY)) diff --git a/fftools/ffmpeg_mux.c b/fftools/ffmpeg_mux.c index 5d427b44ea9..30764e22d14 100644 --- a/fftools/ffmpeg_mux.c +++ b/fftools/ffmpeg_mux.c @@ -81,11 +81,12 @@ static int write_packet(Muxer *mux, OutputStream *ost, AVPacket *pkt) if (pkt->duration > 0) av_log(ost, AV_LOG_WARNING, "Overriding packet duration by frame rate, this should not happen\n"); pkt->duration = av_rescale_q(1, av_inv_q(ost->frame_rate), - ost->mux_timebase); + pkt->time_base); } } - av_packet_rescale_ts(pkt, ost->mux_timebase, ost->st->time_base); + av_packet_rescale_ts(pkt, pkt->time_base, ost->st->time_base); + pkt->time_base = ost->st->time_base; if (!(s->oformat->flags & AVFMT_NOTIMESTAMPS)) { if (pkt->dts != AV_NOPTS_VALUE && @@ -325,7 +326,7 @@ void of_output_packet(OutputFile *of, AVPacket *pkt, OutputStream *ost, int eof) int ret = 0; if (!eof && pkt->dts != AV_NOPTS_VALUE) - ost->last_mux_dts = av_rescale_q(pkt->dts, ost->mux_timebase, AV_TIME_BASE_Q); + ost->last_mux_dts = av_rescale_q(pkt->dts, pkt->time_base, AV_TIME_BASE_Q); /* apply the output bitstream filters */ if (ms->bsf_ctx) { From 42a0dd6e7e3bc343d65a5499bd1373ad15160ab7 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Mon, 6 Feb 2023 13:14:53 +0100 Subject: [PATCH 0184/2172] fftools/ffmpeg: add an option for writing pre-muxing stats Analogous to -enc_stats*, but happens right before muxing. Useful because bitstream filters and the sync queue can modify packets after encoding and before muxing. Also has access to the muxing timebase. --- Changelog | 3 ++- doc/ffmpeg.texi | 13 +++++++++---- fftools/ffmpeg.c | 14 ++++++++------ fftools/ffmpeg.h | 8 ++++++++ fftools/ffmpeg_mux.c | 10 +++++++++- fftools/ffmpeg_mux.h | 2 ++ fftools/ffmpeg_mux_init.c | 23 ++++++++++++++++++----- fftools/ffmpeg_opt.c | 4 ++++ 8 files changed, 60 insertions(+), 17 deletions(-) diff --git a/Changelog b/Changelog index df9cd69da2d..bd9fe9922d4 100644 --- a/Changelog +++ b/Changelog @@ -32,7 +32,8 @@ version : - WADY DPCM decoder and demuxer - CBD2 DPCM decoder - ssim360 video filter -- ffmpeg CLI new options: -enc_stats_pre[_fmt], -enc_stats_post[_fmt] +- ffmpeg CLI new options: -enc_stats_pre[_fmt], -enc_stats_post[_fmt], + -stats_mux_pre[_fmt] - hstack_vaapi, vstack_vaapi and xstack_vaapi filters - XMD ADPCM decoder and demuxer - media100 to mjpegb bsf diff --git a/doc/ffmpeg.texi b/doc/ffmpeg.texi index 592c4b4393d..076956d1283 100644 --- a/doc/ffmpeg.texi +++ b/doc/ffmpeg.texi @@ -2063,14 +2063,17 @@ or invalid output files. @item -enc_stats_pre[:@var{stream_specifier}] @var{path} (@emph{output,per-stream}) @item -enc_stats_post[:@var{stream_specifier}] @var{path} (@emph{output,per-stream}) +@item -stats_mux_pre[:@var{stream_specifier}] @var{path} (@emph{output,per-stream}) Write per-frame encoding information about the matching streams into the file given by @var{path}. @option{-enc_stats_pre} writes information about raw video or audio frames right before they are sent for encoding, while @option{-enc_stats_post} writes -information about encoded packets as they are received from the encoder. Every -frame or packet produces one line in the specified file. The format of this line -is controlled by @option{-enc_stats_pre_fmt} / @option{-enc_stats_post_fmt}. +information about encoded packets as they are received from the encoder. +@option{-stats_mux_pre} writes information about packets just as they are about to +be sent to the muxer. Every frame or packet produces one line in the specified +file. The format of this line is controlled by @option{-enc_stats_pre_fmt} / +@option{-enc_stats_post_fmt} / @option{-stats_mux_pre_fmt}. When stats for multiple streams are written into a single file, the lines corresponding to different streams will be interleaved. The precise order of @@ -2079,8 +2082,9 @@ different invocations of the program, even with the same options. @item -enc_stats_pre_fmt[:@var{stream_specifier}] @var{format_spec} (@emph{output,per-stream}) @item -enc_stats_post_fmt[:@var{stream_specifier}] @var{format_spec} (@emph{output,per-stream}) +@item -stats_mux_pre_fmt[:@var{stream_specifier}] @var{format_spec} (@emph{output,per-stream}) Specify the format for the lines written with @option{-enc_stats_pre} / -@option{-enc_stats_post}. +@option{-enc_stats_post} / @option{-stats_mux_pre}. @var{format_spec} is a string that may contain directives of the form @var{@{fmt@}}. @var{format_spec} is backslash-escaped --- use \@{, \@}, and \\ @@ -2097,6 +2101,7 @@ Index of the output stream in the file. @item n Frame number. Pre-encoding: number of frames sent to the encoder so far. Post-encoding: number of packets received from the encoder so far. +Muxing: number of packets submitted to the muxer for this stream so far. @item ni Input frame number. Index of the input frame (i.e. output by a decoder) that diff --git a/fftools/ffmpeg.c b/fftools/ffmpeg.c index 32e0c3febdb..aac393c7141 100644 --- a/fftools/ffmpeg.c +++ b/fftools/ffmpeg.c @@ -808,8 +808,9 @@ static void update_video_stats(OutputStream *ost, const AVPacket *pkt, int write fprintf(vstats_file, "type= %c\n", av_get_picture_type_char(ost->pict_type)); } -static void enc_stats_write(OutputStream *ost, EncStats *es, - const AVFrame *frame, const AVPacket *pkt) +void enc_stats_write(OutputStream *ost, EncStats *es, + const AVFrame *frame, const AVPacket *pkt, + uint64_t frame_num) { AVIOContext *io = es->io; AVRational tb = frame ? frame->time_base : pkt->time_base; @@ -840,12 +841,12 @@ static void enc_stats_write(OutputStream *ost, EncStats *es, case ENC_STATS_PTS_TIME: avio_printf(io, "%g", pts * av_q2d(tb)); continue; case ENC_STATS_PTS_TIME_IN: avio_printf(io, "%g", ptsi == INT64_MAX ? INFINITY : ptsi * av_q2d(tbi)); continue; + case ENC_STATS_FRAME_NUM: avio_printf(io, "%"PRIu64, frame_num); continue; case ENC_STATS_FRAME_NUM_IN: avio_printf(io, "%"PRIu64, fd ? fd->idx : -1); continue; } if (frame) { switch (c->type) { - case ENC_STATS_FRAME_NUM: avio_printf(io, "%"PRIu64, ost->frames_encoded); continue; case ENC_STATS_SAMPLE_NUM: avio_printf(io, "%"PRIu64, ost->samples_encoded); continue; case ENC_STATS_NB_SAMPLES: avio_printf(io, "%d", frame->nb_samples); continue; default: av_assert0(0); @@ -855,7 +856,6 @@ static void enc_stats_write(OutputStream *ost, EncStats *es, case ENC_STATS_DTS: avio_printf(io, "%"PRId64, pkt->dts); continue; case ENC_STATS_DTS_TIME: avio_printf(io, "%g", pkt->dts * av_q2d(tb)); continue; case ENC_STATS_PKT_SIZE: avio_printf(io, "%d", pkt->size); continue; - case ENC_STATS_FRAME_NUM: avio_printf(io, "%"PRIu64, ost->packets_encoded); continue; case ENC_STATS_BITRATE: { double duration = FFMAX(pkt->duration, 1) * av_q2d(tb); avio_printf(io, "%g", 8.0 * pkt->size / duration); @@ -884,7 +884,8 @@ static int encode_frame(OutputFile *of, OutputStream *ost, AVFrame *frame) if (frame) { if (ost->enc_stats_pre.io) - enc_stats_write(ost, &ost->enc_stats_pre, frame, NULL); + enc_stats_write(ost, &ost->enc_stats_pre, frame, NULL, + ost->frames_encoded); ost->frames_encoded++; ost->samples_encoded += frame->nb_samples; @@ -932,7 +933,8 @@ static int encode_frame(OutputFile *of, OutputStream *ost, AVFrame *frame) if (enc->codec_type == AVMEDIA_TYPE_VIDEO) update_video_stats(ost, pkt, !!vstats_filename); if (ost->enc_stats_post.io) - enc_stats_write(ost, &ost->enc_stats_post, NULL, pkt); + enc_stats_write(ost, &ost->enc_stats_post, NULL, pkt, + ost->packets_encoded); if (debug_ts) { av_log(ost, AV_LOG_INFO, "encoder -> type:%s " diff --git a/fftools/ffmpeg.h b/fftools/ffmpeg.h index 933312dba78..f1412f6446b 100644 --- a/fftools/ffmpeg.h +++ b/fftools/ffmpeg.h @@ -258,10 +258,14 @@ typedef struct OptionsContext { int nb_enc_stats_pre; SpecifierOpt *enc_stats_post; int nb_enc_stats_post; + SpecifierOpt *mux_stats; + int nb_mux_stats; SpecifierOpt *enc_stats_pre_fmt; int nb_enc_stats_pre_fmt; SpecifierOpt *enc_stats_post_fmt; int nb_enc_stats_post_fmt; + SpecifierOpt *mux_stats_fmt; + int nb_mux_stats_fmt; } OptionsContext; typedef struct InputFilter { @@ -789,6 +793,10 @@ int ifilter_parameters_from_frame(InputFilter *ifilter, const AVFrame *frame); int ffmpeg_parse_options(int argc, char **argv); +void enc_stats_write(OutputStream *ost, EncStats *es, + const AVFrame *frame, const AVPacket *pkt, + uint64_t frame_num); + HWDevice *hw_device_get_by_name(const char *name); int hw_device_init_from_string(const char *arg, HWDevice **dev); void hw_device_free_all(void); diff --git a/fftools/ffmpeg_mux.c b/fftools/ffmpeg_mux.c index 30764e22d14..dffc1410c85 100644 --- a/fftools/ffmpeg_mux.c +++ b/fftools/ffmpeg_mux.c @@ -64,6 +64,7 @@ static int write_packet(Muxer *mux, OutputStream *ost, AVPacket *pkt) AVFormatContext *s = mux->fc; AVStream *st = ost->st; int64_t fs; + uint64_t frame_num; int ret; fs = filesize(s->pb); @@ -128,7 +129,7 @@ static int write_packet(Muxer *mux, OutputStream *ost, AVPacket *pkt) ms->last_mux_dts = pkt->dts; ost->data_size_mux += pkt->size; - atomic_fetch_add(&ost->packets_written, 1); + frame_num = atomic_fetch_add(&ost->packets_written, 1); pkt->stream_index = ost->index; @@ -143,6 +144,9 @@ static int write_packet(Muxer *mux, OutputStream *ost, AVPacket *pkt) ); } + if (ms->stats.io) + enc_stats_write(ost, &ms->stats, NULL, pkt, frame_num); + ret = av_interleaved_write_frame(s, pkt); if (ret < 0) { print_error("av_interleaved_write_frame()", ret); @@ -688,6 +692,10 @@ static void ost_free(OutputStream **post) av_freep(&ost->enc_stats_post.components[i].str); av_freep(&ost->enc_stats_post.components); + for (int i = 0; i < ms->stats.nb_components; i++) + av_freep(&ms->stats.components[i].str); + av_freep(&ms->stats.components); + av_freep(post); } diff --git a/fftools/ffmpeg_mux.h b/fftools/ffmpeg_mux.h index 1487d86ae10..c76dc2e5246 100644 --- a/fftools/ffmpeg_mux.h +++ b/fftools/ffmpeg_mux.h @@ -45,6 +45,8 @@ typedef struct MuxStream { AVBSFContext *bsf_ctx; + EncStats stats; + int64_t max_frames; /* diff --git a/fftools/ffmpeg_mux_init.c b/fftools/ffmpeg_mux_init.c index 834cdbcc9f2..f4ef83f6af1 100644 --- a/fftools/ffmpeg_mux_init.c +++ b/fftools/ffmpeg_mux_init.c @@ -57,8 +57,10 @@ static const char *const opt_name_disposition[] = {"disposition", static const char *const opt_name_enc_time_bases[] = {"enc_time_base", NULL}; static const char *const opt_name_enc_stats_pre[] = {"enc_stats_pre", NULL}; static const char *const opt_name_enc_stats_post[] = {"enc_stats_post", NULL}; +static const char *const opt_name_mux_stats[] = {"mux_stats", NULL}; static const char *const opt_name_enc_stats_pre_fmt[] = {"enc_stats_pre_fmt", NULL}; static const char *const opt_name_enc_stats_post_fmt[] = {"enc_stats_post_fmt", NULL}; +static const char *const opt_name_mux_stats_fmt[] = {"mux_stats_fmt", NULL}; static const char *const opt_name_filters[] = {"filter", "af", "vf", NULL}; static const char *const opt_name_filter_scripts[] = {"filter_script", NULL}; static const char *const opt_name_fix_sub_duration_heartbeat[] = {"fix_sub_duration_heartbeat", NULL}; @@ -262,7 +264,7 @@ static int unescape(char **pdst, size_t *dst_len, return 0; } -static int enc_stats_init(OutputStream *ost, int pre, +static int enc_stats_init(OutputStream *ost, EncStats *es, int pre, const char *path, const char *fmt_spec) { static const struct { @@ -290,7 +292,6 @@ static int enc_stats_init(OutputStream *ost, int pre, { ENC_STATS_BITRATE, "br", 0, 1 }, { ENC_STATS_AVG_BITRATE, "abr", 0, 1 }, }; - EncStats *es = pre ? &ost->enc_stats_pre : &ost->enc_stats_post; const char *next = fmt_spec; int ret; @@ -479,7 +480,7 @@ static OutputStream *new_output_stream(Muxer *mux, const OptionsContext *o, AVCodecContext *enc = ost->enc_ctx; AVIOContext *s = NULL; char *buf = NULL, *arg = NULL, *preset = NULL; - const char *enc_stats_pre = NULL, *enc_stats_post = NULL; + const char *enc_stats_pre = NULL, *enc_stats_post = NULL, *mux_stats = NULL; ost->encoder_opts = filter_codec_opts(o->g->codec_opts, enc->codec_id, oc, st, enc->codec); @@ -518,7 +519,7 @@ static OutputStream *new_output_stream(Muxer *mux, const OptionsContext *o, MATCH_PER_STREAM_OPT(enc_stats_pre_fmt, str, format, oc, st); - ret = enc_stats_init(ost, 1, enc_stats_pre, format); + ret = enc_stats_init(ost, &ost->enc_stats_pre, 1, enc_stats_pre, format); if (ret < 0) exit_program(1); } @@ -530,7 +531,19 @@ static OutputStream *new_output_stream(Muxer *mux, const OptionsContext *o, MATCH_PER_STREAM_OPT(enc_stats_post_fmt, str, format, oc, st); - ret = enc_stats_init(ost, 0, enc_stats_post, format); + ret = enc_stats_init(ost, &ost->enc_stats_post, 0, enc_stats_post, format); + if (ret < 0) + exit_program(1); + } + + MATCH_PER_STREAM_OPT(mux_stats, str, mux_stats, oc, st); + if (mux_stats && + (type == AVMEDIA_TYPE_VIDEO || type == AVMEDIA_TYPE_AUDIO)) { + const char *format = "{fidx} {sidx} {n} {t}"; + + MATCH_PER_STREAM_OPT(mux_stats_fmt, str, format, oc, st); + + ret = enc_stats_init(ost, &ms->stats, 0, mux_stats, format); if (ret < 0) exit_program(1); } diff --git a/fftools/ffmpeg_opt.c b/fftools/ffmpeg_opt.c index 799dcf071eb..ed7ee6ab7d1 100644 --- a/fftools/ffmpeg_opt.c +++ b/fftools/ffmpeg_opt.c @@ -1548,10 +1548,14 @@ const OptionDef options[] = { "write encoding stats before encoding" }, { "enc_stats_post", HAS_ARG | OPT_SPEC | OPT_EXPERT | OPT_OUTPUT | OPT_STRING, { .off = OFFSET(enc_stats_post) }, "write encoding stats after encoding" }, + { "stats_mux_pre", HAS_ARG | OPT_SPEC | OPT_EXPERT | OPT_OUTPUT | OPT_STRING, { .off = OFFSET(mux_stats) }, + "write packets stats before muxing" }, { "enc_stats_pre_fmt", HAS_ARG | OPT_SPEC | OPT_EXPERT | OPT_OUTPUT | OPT_STRING, { .off = OFFSET(enc_stats_pre_fmt) }, "format of the stats written with -enc_stats_pre" }, { "enc_stats_post_fmt", HAS_ARG | OPT_SPEC | OPT_EXPERT | OPT_OUTPUT | OPT_STRING, { .off = OFFSET(enc_stats_post_fmt) }, "format of the stats written with -enc_stats_post" }, + { "stats_mux_pre_fmt", HAS_ARG | OPT_SPEC | OPT_EXPERT | OPT_OUTPUT | OPT_STRING, { .off = OFFSET(mux_stats_fmt) }, + "format of the stats written with -stats_mux_pre" }, /* video options */ { "vframes", OPT_VIDEO | HAS_ARG | OPT_PERFILE | OPT_OUTPUT, { .func_arg = opt_video_frames }, From 145f6b22231b84e59cc26a350b6c2a6237b2113d Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt Date: Fri, 27 Jan 2023 15:05:56 +0100 Subject: [PATCH 0185/2172] avformat/avformat: Remove AVOutputFormat.data_codec No AVOutputFormat has this set. Signed-off-by: Andreas Rheinhardt Signed-off-by: Anton Khirnov --- libavformat/avformat.h | 1 - libavformat/format.c | 2 -- libavformat/mux_utils.c | 3 +-- 3 files changed, 1 insertion(+), 5 deletions(-) diff --git a/libavformat/avformat.h b/libavformat/avformat.h index 1d97d56ac58..53bbc0063f0 100644 --- a/libavformat/avformat.h +++ b/libavformat/avformat.h @@ -614,7 +614,6 @@ typedef struct AVOutputFormat { * @see avdevice_list_devices() for more details. */ int (*get_device_list)(struct AVFormatContext *s, struct AVDeviceInfoList *device_list); - enum AVCodecID data_codec; /**< default data codec */ /** * Initialize format. May allocate data here, and set any AVFormatContext or * AVStream parameters that need to be set before packets are sent. diff --git a/libavformat/format.c b/libavformat/format.c index 4b1f3c2986e..76f25ab5a67 100644 --- a/libavformat/format.c +++ b/libavformat/format.c @@ -111,8 +111,6 @@ enum AVCodecID av_guess_codec(const AVOutputFormat *fmt, const char *short_name, return fmt->audio_codec; else if (type == AVMEDIA_TYPE_SUBTITLE) return fmt->subtitle_codec; - else if (type == AVMEDIA_TYPE_DATA) - return fmt->data_codec; else return AV_CODEC_ID_NONE; } diff --git a/libavformat/mux_utils.c b/libavformat/mux_utils.c index 764c834fa2c..55e58ae9d68 100644 --- a/libavformat/mux_utils.c +++ b/libavformat/mux_utils.c @@ -51,8 +51,7 @@ int avformat_query_codec(const AVOutputFormat *ofmt, enum AVCodecID codec_id, return !!av_codec_get_tag2(ofmt->codec_tag, codec_id, &codec_tag); else if (codec_id == ofmt->video_codec || codec_id == ofmt->audio_codec || - codec_id == ofmt->subtitle_codec || - codec_id == ofmt->data_codec) + codec_id == ofmt->subtitle_codec) return 1; } return AVERROR_PATCHWELCOME; From 0281e28c3763765be1bff448bb735bbefca4c7d6 Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt Date: Fri, 27 Jan 2023 15:05:57 +0100 Subject: [PATCH 0186/2172] avformat/avformat: Move codecpar up in AVStream It is the most commonly used field and moving it to the start e.g. allows to encode the offset in a pointer+offset addressing mode on one byte on x86. Signed-off-by: Andreas Rheinhardt Signed-off-by: Anton Khirnov --- libavformat/avformat.h | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/libavformat/avformat.h b/libavformat/avformat.h index 53bbc0063f0..a69ee1c575c 100644 --- a/libavformat/avformat.h +++ b/libavformat/avformat.h @@ -962,6 +962,17 @@ typedef struct AVStream { */ int id; + /** + * Codec parameters associated with this stream. Allocated and freed by + * libavformat in avformat_new_stream() and avformat_free_context() + * respectively. + * + * - demuxing: filled by libavformat on stream creation or in + * avformat_find_stream_info() + * - muxing: filled by the caller before avformat_write_header() + */ + AVCodecParameters *codecpar; + void *priv_data; /** @@ -1097,17 +1108,6 @@ typedef struct AVStream { */ AVRational r_frame_rate; - /** - * Codec parameters associated with this stream. Allocated and freed by - * libavformat in avformat_new_stream() and avformat_free_context() - * respectively. - * - * - demuxing: filled by libavformat on stream creation or in - * avformat_find_stream_info() - * - muxing: filled by the caller before avformat_write_header() - */ - AVCodecParameters *codecpar; - /** * Number of bits in timestamps. Used for wrapping control. * From 868a31b42dc0fb62f63e704138f083d48f40d68c Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt Date: Fri, 27 Jan 2023 15:05:58 +0100 Subject: [PATCH 0187/2172] avcodec: Make avcodec_decode_subtitle2 accept a const AVPacket* Signed-off-by: Andreas Rheinhardt Signed-off-by: Anton Khirnov --- doc/APIchanges | 3 +++ fftools/ffmpeg.c | 4 ++-- fftools/ffprobe.c | 2 +- libavcodec/avcodec.h | 3 +-- libavcodec/decode.c | 9 ++++----- tools/target_dec_fuzzer.c | 4 ++-- 6 files changed, 13 insertions(+), 12 deletions(-) diff --git a/doc/APIchanges b/doc/APIchanges index 6baf914760d..c4b9dc114b8 100644 --- a/doc/APIchanges +++ b/doc/APIchanges @@ -14,6 +14,9 @@ libavutil: 2021-04-27 API changes, most recent first: +2023-02-xx - xxxxxxxxxx - lavc 60.0.100 - avcodec.h + avcodec_decode_subtitle2() now accepts const AVPacket*. + 2023-0x-xx - xxxxxxxxxx - lavc 59.63.100 Allow AV_CODEC_FLAG_COPY_OPAQUE to be used with decoders. diff --git a/fftools/ffmpeg.c b/fftools/ffmpeg.c index aac393c7141..a9c84f507c4 100644 --- a/fftools/ffmpeg.c +++ b/fftools/ffmpeg.c @@ -2512,8 +2512,8 @@ static int trigger_fix_sub_duration_heartbeat(OutputStream *ost, const AVPacket return 0; } -static int transcode_subtitles(InputStream *ist, AVPacket *pkt, int *got_output, - int *decode_failed) +static int transcode_subtitles(InputStream *ist, const AVPacket *pkt, + int *got_output, int *decode_failed) { AVSubtitle subtitle; int ret = avcodec_decode_subtitle2(ist->dec_ctx, diff --git a/fftools/ffprobe.c b/fftools/ffprobe.c index db5e4ecdf1f..06013fd6faf 100644 --- a/fftools/ffprobe.c +++ b/fftools/ffprobe.c @@ -2734,7 +2734,7 @@ static void show_frame(WriterContext *w, AVFrame *frame, AVStream *stream, static av_always_inline int process_frame(WriterContext *w, InputFile *ifile, - AVFrame *frame, AVPacket *pkt, + AVFrame *frame, const AVPacket *pkt, int *packet_new) { AVFormatContext *fmt_ctx = ifile->fmt_ctx; diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h index 755e543fac0..e8333a94f16 100644 --- a/libavcodec/avcodec.h +++ b/libavcodec/avcodec.h @@ -2615,8 +2615,7 @@ enum AVChromaLocation avcodec_chroma_pos_to_enum(int xpos, int ypos); * @param[in] avpkt The input AVPacket containing the input buffer. */ int avcodec_decode_subtitle2(AVCodecContext *avctx, AVSubtitle *sub, - int *got_sub_ptr, - AVPacket *avpkt); + int *got_sub_ptr, const AVPacket *avpkt); /** * Supply raw packet data as input to a decoder. diff --git a/libavcodec/decode.c b/libavcodec/decode.c index 03ae27ecdf9..78bf3ba547b 100644 --- a/libavcodec/decode.c +++ b/libavcodec/decode.c @@ -780,8 +780,8 @@ static void get_subtitle_defaults(AVSubtitle *sub) } #define UTF8_MAX_BYTES 4 /* 5 and 6 bytes sequences should not be used */ -static int recode_subtitle(AVCodecContext *avctx, AVPacket **outpkt, - AVPacket *inpkt, AVPacket *buf_pkt) +static int recode_subtitle(AVCodecContext *avctx, const AVPacket **outpkt, + const AVPacket *inpkt, AVPacket *buf_pkt) { #if CONFIG_ICONV iconv_t cd = (iconv_t)-1; @@ -861,8 +861,7 @@ static int utf8_check(const uint8_t *str) } int avcodec_decode_subtitle2(AVCodecContext *avctx, AVSubtitle *sub, - int *got_sub_ptr, - AVPacket *avpkt) + int *got_sub_ptr, const AVPacket *avpkt) { int ret = 0; @@ -882,7 +881,7 @@ int avcodec_decode_subtitle2(AVCodecContext *avctx, AVSubtitle *sub, if ((avctx->codec->capabilities & AV_CODEC_CAP_DELAY) || avpkt->size) { AVCodecInternal *avci = avctx->internal; - AVPacket *pkt; + const AVPacket *pkt; ret = recode_subtitle(avctx, &pkt, avpkt, avci->buffer_pkt); if (ret < 0) diff --git a/tools/target_dec_fuzzer.c b/tools/target_dec_fuzzer.c index 127d534c9de..a9472eebe61 100644 --- a/tools/target_dec_fuzzer.c +++ b/tools/target_dec_fuzzer.c @@ -81,8 +81,8 @@ static const FFCodec *AVCodecInitialize(enum AVCodecID codec_id) return ffcodec(res); } -static int subtitle_handler(AVCodecContext *avctx, void *frame, - int *got_sub_ptr, AVPacket *avpkt) +static int subtitle_handler(AVCodecContext *avctx, AVFrame *unused, + int *got_sub_ptr, const AVPacket *avpkt) { AVSubtitle sub; int ret = avcodec_decode_subtitle2(avctx, &sub, got_sub_ptr, avpkt); From f23ae839fc184c4492e10f371cde5c1b55e51522 Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt Date: Fri, 27 Jan 2023 15:05:59 +0100 Subject: [PATCH 0188/2172] avformat/demux: Avoid stack packet when decoding frame Possible now that avcodec_decode_subtitle2() accepts a const AVPacket*. Signed-off-by: Andreas Rheinhardt Signed-off-by: Anton Khirnov --- libavformat/demux.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/libavformat/demux.c b/libavformat/demux.c index 2dfd82a63ca..ba2991750bc 100644 --- a/libavformat/demux.c +++ b/libavformat/demux.c @@ -1984,7 +1984,7 @@ static int has_codec_parameters(const AVStream *st, const char **errmsg_ptr) /* returns 1 or 0 if or if not decoded data was returned, or a negative error */ static int try_decode_frame(AVFormatContext *s, AVStream *st, - const AVPacket *avpkt, AVDictionary **options) + const AVPacket *pkt, AVDictionary **options) { FFStream *const sti = ffstream(st); AVCodecContext *const avctx = sti->avctx; @@ -1992,9 +1992,9 @@ static int try_decode_frame(AVFormatContext *s, AVStream *st, int got_picture = 1, ret = 0; AVFrame *frame = av_frame_alloc(); AVSubtitle subtitle; - AVPacket pkt = *avpkt; int do_skip_frame = 0; enum AVDiscard skip_frame; + int pkt_to_send = pkt->size > 0; if (!frame) return AVERROR(ENOMEM); @@ -2043,7 +2043,7 @@ static int try_decode_frame(AVFormatContext *s, AVStream *st, avctx->skip_frame = AVDISCARD_ALL; } - while ((pkt.size > 0 || (!pkt.data && got_picture)) && + while ((pkt_to_send || (!pkt->data && got_picture)) && ret >= 0 && (!has_codec_parameters(st, NULL) || !has_decode_delay_been_guessed(st) || (!sti->codec_info_nb_frames && @@ -2051,11 +2051,11 @@ static int try_decode_frame(AVFormatContext *s, AVStream *st, got_picture = 0; if (avctx->codec_type == AVMEDIA_TYPE_VIDEO || avctx->codec_type == AVMEDIA_TYPE_AUDIO) { - ret = avcodec_send_packet(avctx, &pkt); + ret = avcodec_send_packet(avctx, pkt); if (ret < 0 && ret != AVERROR(EAGAIN) && ret != AVERROR_EOF) break; if (ret >= 0) - pkt.size = 0; + pkt_to_send = 0; ret = avcodec_receive_frame(avctx, frame); if (ret >= 0) got_picture = 1; @@ -2063,11 +2063,11 @@ static int try_decode_frame(AVFormatContext *s, AVStream *st, ret = 0; } else if (avctx->codec_type == AVMEDIA_TYPE_SUBTITLE) { ret = avcodec_decode_subtitle2(avctx, &subtitle, - &got_picture, &pkt); + &got_picture, pkt); if (got_picture) avsubtitle_free(&subtitle); if (ret >= 0) - pkt.size = 0; + pkt_to_send = 0; } if (ret >= 0) { if (got_picture) From 59c9dc82f450638a3068deeb1db5c56f6d155752 Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt Date: Fri, 27 Jan 2023 15:06:00 +0100 Subject: [PATCH 0189/2172] avformat/avformat: Move AVOutputFormat internals out of public header This commit does for AVOutputFormat what commit 20f972701806be20a77f808db332d9489343bb78 did for AVCodec: It adds a new type FFOutputFormat, moves all the internals of AVOutputFormat to it and adds a now reduced AVOutputFormat as first member. This does not affect/improve extensibility of both public or private fields for muxers (it is still a mess due to lavd). Signed-off-by: Andreas Rheinhardt Signed-off-by: Anton Khirnov --- configure | 8 +- libavdevice/alldevices.c | 31 +- libavdevice/alsa_enc.c | 14 +- libavdevice/audiotoolbox.m | 15 +- libavdevice/avdevice.c | 9 +- libavdevice/caca.c | 15 +- libavdevice/decklink_enc_c.c | 17 +- libavdevice/fbdev_enc.c | 15 +- libavdevice/opengl_enc.c | 14 +- libavdevice/oss_enc.c | 15 +- libavdevice/pulse_audio_enc.c | 14 +- libavdevice/sdl2.c | 15 +- libavdevice/sndio_enc.c | 15 +- libavdevice/v4l2enc.c | 15 +- libavdevice/xv.c | 14 +- libavformat/a64.c | 11 +- libavformat/adtsenc.c | 19 +- libavformat/aiffenc.c | 19 +- libavformat/allformats.c | 363 +++++++++++------------ libavformat/alp.c | 15 +- libavformat/amr.c | 17 +- libavformat/amvenc.c | 15 +- libavformat/apm.c | 13 +- libavformat/apngenc.c | 19 +- libavformat/argo_asf.c | 15 +- libavformat/argo_cvg.c | 15 +- libavformat/asfenc.c | 40 +-- libavformat/assenc.c | 17 +- libavformat/astenc.c | 17 +- libavformat/au.c | 19 +- libavformat/avformat.c | 5 +- libavformat/avformat.h | 109 ------- libavformat/avienc.c | 19 +- libavformat/bit.c | 15 +- libavformat/cafenc.c | 16 +- libavformat/chromaprint.c | 13 +- libavformat/codec2.c | 15 +- libavformat/crcenc.c | 13 +- libavformat/dashenc.c | 20 +- libavformat/daudenc.c | 15 +- libavformat/dvenc.c | 12 +- libavformat/ffmetaenc.c | 11 +- libavformat/fifo.c | 10 +- libavformat/fifo_test.c | 11 +- libavformat/filmstripenc.c | 13 +- libavformat/fitsenc.c | 13 +- libavformat/flacenc.c | 19 +- libavformat/flvenc.c | 20 +- libavformat/framecrcenc.c | 13 +- libavformat/gif.c | 19 +- libavformat/gxfenc.c | 12 +- libavformat/hashenc.c | 71 ++--- libavformat/hdsenc.c | 14 +- libavformat/hlsenc.c | 18 +- libavformat/icoenc.c | 17 +- libavformat/idroqenc.c | 13 +- libavformat/ilbc.c | 15 +- libavformat/img2enc.c | 25 +- libavformat/internal.h | 3 +- libavformat/ircamenc.c | 15 +- libavformat/ivfenc.c | 14 +- libavformat/jacosubenc.c | 15 +- libavformat/kvag.c | 13 +- libavformat/latmenc.c | 18 +- libavformat/lrcenc.c | 14 +- libavformat/matroskaenc.c | 62 ++-- libavformat/microdvdenc.c | 15 +- libavformat/mkvtimestamp_v2.c | 11 +- libavformat/mmf.c | 15 +- libavformat/movenc.c | 170 +++++------ libavformat/mp3enc.c | 19 +- libavformat/mpegenc.c | 99 +++---- libavformat/mpegtsenc.c | 18 +- libavformat/mpjpeg.c | 19 +- libavformat/mux.c | 77 ++--- libavformat/mux.h | 113 +++++++ libavformat/mux_utils.c | 4 +- libavformat/mxfenc.c | 120 ++++---- libavformat/nullenc.c | 12 +- libavformat/nutenc.c | 20 +- libavformat/oggenc.c | 85 +++--- libavformat/omaenc.c | 17 +- libavformat/pcmenc.c | 15 +- libavformat/rawenc.c | 486 +++++++++++++++---------------- libavformat/rmenc.c | 17 +- libavformat/rsoenc.c | 17 +- libavformat/rtpenc.c | 15 +- libavformat/rtpenc_mpegts.c | 13 +- libavformat/rtspenc.c | 14 +- libavformat/sapenc.c | 12 +- libavformat/sccenc.c | 13 +- libavformat/segafilmenc.c | 12 +- libavformat/segment.c | 29 +- libavformat/smjpegenc.c | 14 +- libavformat/smoothstreamingenc.c | 14 +- libavformat/soxenc.c | 15 +- libavformat/spdifenc.c | 17 +- libavformat/srtenc.c | 15 +- libavformat/supenc.c | 15 +- libavformat/swfenc.c | 31 +- libavformat/tee.c | 10 +- libavformat/ttaenc.c | 15 +- libavformat/ttmlenc.c | 15 +- libavformat/uncodedframecrcenc.c | 14 +- libavformat/vc1testenc.c | 13 +- libavformat/vocenc.c | 19 +- libavformat/wavenc.c | 37 +-- libavformat/webm_chunk.c | 14 +- libavformat/webmdashenc.c | 13 +- libavformat/webpenc.c | 15 +- libavformat/webvttenc.c | 15 +- libavformat/westwood_audenc.c | 13 +- libavformat/wtvenc.c | 14 +- libavformat/wvenc.c | 17 +- libavformat/yuv4mpegenc.c | 13 +- 115 files changed, 1731 insertions(+), 1644 deletions(-) diff --git a/configure b/configure index 12184c7f26b..d38613309dd 100755 --- a/configure +++ b/configure @@ -4010,9 +4010,9 @@ find_filters_extern(){ } FILTER_LIST=$(find_filters_extern libavfilter/allfilters.c) -OUTDEV_LIST=$(find_things_extern muxer AVOutputFormat libavdevice/alldevices.c outdev) +OUTDEV_LIST=$(find_things_extern muxer FFOutputFormat libavdevice/alldevices.c outdev) INDEV_LIST=$(find_things_extern demuxer AVInputFormat libavdevice/alldevices.c indev) -MUXER_LIST=$(find_things_extern muxer AVOutputFormat libavformat/allformats.c) +MUXER_LIST=$(find_things_extern muxer FFOutputFormat libavformat/allformats.c) DEMUXER_LIST=$(find_things_extern demuxer AVInputFormat libavformat/allformats.c) ENCODER_LIST=$(find_things_extern encoder FFCodec libavcodec/allcodecs.c) DECODER_LIST=$(find_things_extern decoder FFCodec libavcodec/allcodecs.c) @@ -7960,9 +7960,9 @@ print_enabled_components libavcodec/codec_list.c FFCodec codec_list $CODEC_LIST print_enabled_components libavcodec/parser_list.c AVCodecParser parser_list $PARSER_LIST print_enabled_components libavcodec/bsf_list.c FFBitStreamFilter bitstream_filters $BSF_LIST print_enabled_components libavformat/demuxer_list.c AVInputFormat demuxer_list $DEMUXER_LIST -print_enabled_components libavformat/muxer_list.c AVOutputFormat muxer_list $MUXER_LIST +print_enabled_components libavformat/muxer_list.c FFOutputFormat muxer_list $MUXER_LIST print_enabled_components libavdevice/indev_list.c AVInputFormat indev_list $INDEV_LIST -print_enabled_components libavdevice/outdev_list.c AVOutputFormat outdev_list $OUTDEV_LIST +print_enabled_components libavdevice/outdev_list.c FFOutputFormat outdev_list $OUTDEV_LIST print_enabled_components libavformat/protocol_list.c URLProtocol url_protocols $PROTOCOL_LIST # Settings for pkg-config files diff --git a/libavdevice/alldevices.c b/libavdevice/alldevices.c index 22323a0a44a..8a90fcb5d78 100644 --- a/libavdevice/alldevices.c +++ b/libavdevice/alldevices.c @@ -19,40 +19,41 @@ */ #include "libavformat/internal.h" +#include "libavformat/mux.h" #include "avdevice.h" /* devices */ extern const AVInputFormat ff_alsa_demuxer; -extern const AVOutputFormat ff_alsa_muxer; +extern const FFOutputFormat ff_alsa_muxer; extern const AVInputFormat ff_android_camera_demuxer; -extern const AVOutputFormat ff_audiotoolbox_muxer; +extern const FFOutputFormat ff_audiotoolbox_muxer; extern const AVInputFormat ff_avfoundation_demuxer; extern const AVInputFormat ff_bktr_demuxer; -extern const AVOutputFormat ff_caca_muxer; +extern const FFOutputFormat ff_caca_muxer; extern const AVInputFormat ff_decklink_demuxer; -extern const AVOutputFormat ff_decklink_muxer; +extern const FFOutputFormat ff_decklink_muxer; extern const AVInputFormat ff_dshow_demuxer; extern const AVInputFormat ff_fbdev_demuxer; -extern const AVOutputFormat ff_fbdev_muxer; +extern const FFOutputFormat ff_fbdev_muxer; extern const AVInputFormat ff_gdigrab_demuxer; extern const AVInputFormat ff_iec61883_demuxer; extern const AVInputFormat ff_jack_demuxer; extern const AVInputFormat ff_kmsgrab_demuxer; extern const AVInputFormat ff_lavfi_demuxer; extern const AVInputFormat ff_openal_demuxer; -extern const AVOutputFormat ff_opengl_muxer; +extern const FFOutputFormat ff_opengl_muxer; extern const AVInputFormat ff_oss_demuxer; -extern const AVOutputFormat ff_oss_muxer; +extern const FFOutputFormat ff_oss_muxer; extern const AVInputFormat ff_pulse_demuxer; -extern const AVOutputFormat ff_pulse_muxer; -extern const AVOutputFormat ff_sdl2_muxer; +extern const FFOutputFormat ff_pulse_muxer; +extern const FFOutputFormat ff_sdl2_muxer; extern const AVInputFormat ff_sndio_demuxer; -extern const AVOutputFormat ff_sndio_muxer; +extern const FFOutputFormat ff_sndio_muxer; extern const AVInputFormat ff_v4l2_demuxer; -extern const AVOutputFormat ff_v4l2_muxer; +extern const FFOutputFormat ff_v4l2_muxer; extern const AVInputFormat ff_vfwcap_demuxer; extern const AVInputFormat ff_xcbgrab_demuxer; -extern const AVOutputFormat ff_xv_muxer; +extern const FFOutputFormat ff_xv_muxer; /* external libraries */ extern const AVInputFormat ff_libcdio_demuxer; @@ -97,12 +98,12 @@ static const void *next_output(const AVOutputFormat *prev, AVClassCategory c2) const AVClass *pc; const AVClassCategory c1 = AV_CLASS_CATEGORY_DEVICE_OUTPUT; AVClassCategory category = AV_CLASS_CATEGORY_NA; - const AVOutputFormat *fmt = NULL; + const FFOutputFormat *fmt = NULL; int i = 0; while (prev && (fmt = outdev_list[i])) { i++; - if (prev == fmt) + if (prev == &fmt->p) break; } @@ -110,7 +111,7 @@ static const void *next_output(const AVOutputFormat *prev, AVClassCategory c2) fmt = outdev_list[i++]; if (!fmt) break; - pc = fmt->priv_class; + pc = fmt->p.priv_class; if (!pc) continue; category = pc->category; diff --git a/libavdevice/alsa_enc.c b/libavdevice/alsa_enc.c index e461829d03b..62a20c7ba48 100644 --- a/libavdevice/alsa_enc.c +++ b/libavdevice/alsa_enc.c @@ -165,18 +165,18 @@ static const AVClass alsa_muxer_class = { .category = AV_CLASS_CATEGORY_DEVICE_AUDIO_OUTPUT, }; -const AVOutputFormat ff_alsa_muxer = { - .name = "alsa", - .long_name = NULL_IF_CONFIG_SMALL("ALSA audio output"), +const FFOutputFormat ff_alsa_muxer = { + .p.name = "alsa", + .p.long_name = NULL_IF_CONFIG_SMALL("ALSA audio output"), .priv_data_size = sizeof(AlsaData), - .audio_codec = DEFAULT_CODEC_ID, - .video_codec = AV_CODEC_ID_NONE, + .p.audio_codec = DEFAULT_CODEC_ID, + .p.video_codec = AV_CODEC_ID_NONE, .write_header = audio_write_header, .write_packet = audio_write_packet, .write_trailer = ff_alsa_close, .write_uncoded_frame = audio_write_frame, .get_device_list = audio_get_device_list, .get_output_timestamp = audio_get_output_timestamp, - .flags = AVFMT_NOFILE, - .priv_class = &alsa_muxer_class, + .p.flags = AVFMT_NOFILE, + .p.priv_class = &alsa_muxer_class, }; diff --git a/libavdevice/audiotoolbox.m b/libavdevice/audiotoolbox.m index 27a1fd4a78c..aa49e2c992a 100644 --- a/libavdevice/audiotoolbox.m +++ b/libavdevice/audiotoolbox.m @@ -30,6 +30,7 @@ #include "libavutil/opt.h" #include "libavformat/internal.h" +#include "libavformat/mux.h" #include "libavutil/internal.h" #include "avdevice.h" @@ -294,15 +295,15 @@ static av_cold int at_write_trailer(AVFormatContext *avctx) .category = AV_CLASS_CATEGORY_DEVICE_AUDIO_OUTPUT, }; -const AVOutputFormat ff_audiotoolbox_muxer = { - .name = "audiotoolbox", - .long_name = NULL_IF_CONFIG_SMALL("AudioToolbox output device"), +const FFOutputFormat ff_audiotoolbox_muxer = { + .p.name = "audiotoolbox", + .p.long_name = NULL_IF_CONFIG_SMALL("AudioToolbox output device"), .priv_data_size = sizeof(ATContext), - .audio_codec = AV_NE(AV_CODEC_ID_PCM_S16BE, AV_CODEC_ID_PCM_S16LE), - .video_codec = AV_CODEC_ID_NONE, + .p.audio_codec = AV_NE(AV_CODEC_ID_PCM_S16BE, AV_CODEC_ID_PCM_S16LE), + .p.video_codec = AV_CODEC_ID_NONE, .write_header = at_write_header, .write_packet = at_write_packet, .write_trailer = at_write_trailer, - .flags = AVFMT_NOFILE, - .priv_class = &at_class, + .p.flags = AVFMT_NOFILE, + .p.priv_class = &at_class, }; diff --git a/libavdevice/avdevice.c b/libavdevice/avdevice.c index 58996404b3b..b47f89c4bf2 100644 --- a/libavdevice/avdevice.c +++ b/libavdevice/avdevice.c @@ -19,6 +19,7 @@ #include "libavutil/avassert.h" #include "avdevice.h" #include "internal.h" +#include "libavformat/mux.h" #if FF_API_DEVICE_CAPABILITIES const AVOption av_device_capabilities[] = { @@ -29,9 +30,9 @@ const AVOption av_device_capabilities[] = { int avdevice_app_to_dev_control_message(struct AVFormatContext *s, enum AVAppToDevMessageType type, void *data, size_t data_size) { - if (!s->oformat || !s->oformat->control_message) + if (!s->oformat || !ffofmt(s->oformat)->control_message) return AVERROR(ENOSYS); - return s->oformat->control_message(s, type, data, data_size); + return ffofmt(s->oformat)->control_message(s, type, data, data_size); } int avdevice_dev_to_app_control_message(struct AVFormatContext *s, enum AVDevToAppMessageType type, @@ -61,7 +62,7 @@ int avdevice_list_devices(AVFormatContext *s, AVDeviceInfoList **device_list) av_assert0(s); av_assert0(device_list); av_assert0(s->oformat || s->iformat); - if ((s->oformat && !s->oformat->get_device_list) || + if ((s->oformat && !ffofmt(s->oformat)->get_device_list) || (s->iformat && !s->iformat->get_device_list)) { *device_list = NULL; return AVERROR(ENOSYS); @@ -72,7 +73,7 @@ int avdevice_list_devices(AVFormatContext *s, AVDeviceInfoList **device_list) /* no default device by default */ (*device_list)->default_device = -1; if (s->oformat) - ret = s->oformat->get_device_list(s, *device_list); + ret = ffofmt(s->oformat)->get_device_list(s, *device_list); else ret = s->iformat->get_device_list(s, *device_list); if (ret < 0) { diff --git a/libavdevice/caca.c b/libavdevice/caca.c index 5536fd036ed..6af1649137e 100644 --- a/libavdevice/caca.c +++ b/libavdevice/caca.c @@ -21,6 +21,7 @@ #include #include "libavutil/opt.h" #include "libavutil/pixdesc.h" +#include "libavformat/mux.h" #include "avdevice.h" typedef struct CACAContext { @@ -220,15 +221,15 @@ static const AVClass caca_class = { .category = AV_CLASS_CATEGORY_DEVICE_VIDEO_OUTPUT, }; -const AVOutputFormat ff_caca_muxer = { - .name = "caca", - .long_name = NULL_IF_CONFIG_SMALL("caca (color ASCII art) output device"), +const FFOutputFormat ff_caca_muxer = { + .p.name = "caca", + .p.long_name = NULL_IF_CONFIG_SMALL("caca (color ASCII art) output device"), .priv_data_size = sizeof(CACAContext), - .audio_codec = AV_CODEC_ID_NONE, - .video_codec = AV_CODEC_ID_RAWVIDEO, + .p.audio_codec = AV_CODEC_ID_NONE, + .p.video_codec = AV_CODEC_ID_RAWVIDEO, .write_header = caca_write_header, .write_packet = caca_write_packet, .deinit = caca_deinit, - .flags = AVFMT_NOFILE, - .priv_class = &caca_class, + .p.flags = AVFMT_NOFILE, + .p.priv_class = &caca_class, }; diff --git a/libavdevice/decklink_enc_c.c b/libavdevice/decklink_enc_c.c index 990fbb81684..f7e315057fc 100644 --- a/libavdevice/decklink_enc_c.c +++ b/libavdevice/decklink_enc_c.c @@ -20,6 +20,7 @@ */ #include "libavformat/avformat.h" +#include "libavformat/mux.h" #include "libavutil/opt.h" #include "decklink_common_c.h" @@ -71,15 +72,15 @@ static const AVClass decklink_muxer_class = { .category = AV_CLASS_CATEGORY_DEVICE_VIDEO_OUTPUT, }; -const AVOutputFormat ff_decklink_muxer = { - .name = "decklink", - .long_name = NULL_IF_CONFIG_SMALL("Blackmagic DeckLink output"), - .audio_codec = AV_CODEC_ID_PCM_S16LE, - .video_codec = AV_CODEC_ID_WRAPPED_AVFRAME, - .subtitle_codec = AV_CODEC_ID_NONE, - .flags = AVFMT_NOFILE, +const FFOutputFormat ff_decklink_muxer = { + .p.name = "decklink", + .p.long_name = NULL_IF_CONFIG_SMALL("Blackmagic DeckLink output"), + .p.audio_codec = AV_CODEC_ID_PCM_S16LE, + .p.video_codec = AV_CODEC_ID_WRAPPED_AVFRAME, + .p.subtitle_codec = AV_CODEC_ID_NONE, + .p.flags = AVFMT_NOFILE, + .p.priv_class = &decklink_muxer_class, .get_device_list = ff_decklink_list_output_devices, - .priv_class = &decklink_muxer_class, .priv_data_size = sizeof(struct decklink_cctx), .write_header = ff_decklink_write_header, .write_packet = ff_decklink_write_packet, diff --git a/libavdevice/fbdev_enc.c b/libavdevice/fbdev_enc.c index 77233880e7d..7f3e8e5935f 100644 --- a/libavdevice/fbdev_enc.c +++ b/libavdevice/fbdev_enc.c @@ -28,6 +28,7 @@ #include "libavutil/log.h" #include "libavutil/opt.h" #include "libavformat/avformat.h" +#include "libavformat/mux.h" #include "fbdev_common.h" #include "avdevice.h" @@ -206,16 +207,16 @@ static const AVClass fbdev_class = { .category = AV_CLASS_CATEGORY_DEVICE_VIDEO_OUTPUT, }; -const AVOutputFormat ff_fbdev_muxer = { - .name = "fbdev", - .long_name = NULL_IF_CONFIG_SMALL("Linux framebuffer"), +const FFOutputFormat ff_fbdev_muxer = { + .p.name = "fbdev", + .p.long_name = NULL_IF_CONFIG_SMALL("Linux framebuffer"), .priv_data_size = sizeof(FBDevContext), - .audio_codec = AV_CODEC_ID_NONE, - .video_codec = AV_CODEC_ID_RAWVIDEO, + .p.audio_codec = AV_CODEC_ID_NONE, + .p.video_codec = AV_CODEC_ID_RAWVIDEO, .write_header = fbdev_write_header, .write_packet = fbdev_write_packet, .write_trailer = fbdev_write_trailer, .get_device_list = fbdev_get_device_list, - .flags = AVFMT_NOFILE | AVFMT_VARIABLE_FPS | AVFMT_NOTIMESTAMPS, - .priv_class = &fbdev_class, + .p.flags = AVFMT_NOFILE | AVFMT_VARIABLE_FPS | AVFMT_NOTIMESTAMPS, + .p.priv_class = &fbdev_class, }; diff --git a/libavdevice/opengl_enc.c b/libavdevice/opengl_enc.c index b2140c80be5..06750bbba1e 100644 --- a/libavdevice/opengl_enc.c +++ b/libavdevice/opengl_enc.c @@ -1292,17 +1292,17 @@ static const AVClass opengl_class = { .category = AV_CLASS_CATEGORY_DEVICE_VIDEO_OUTPUT, }; -const AVOutputFormat ff_opengl_muxer = { - .name = "opengl", - .long_name = NULL_IF_CONFIG_SMALL("OpenGL output"), +const FFOutputFormat ff_opengl_muxer = { + .p.name = "opengl", + .p.long_name = NULL_IF_CONFIG_SMALL("OpenGL output"), + .p.audio_codec = AV_CODEC_ID_NONE, + .p.video_codec = AV_CODEC_ID_WRAPPED_AVFRAME, + .p.flags = AVFMT_NOFILE | AVFMT_VARIABLE_FPS | AVFMT_NOTIMESTAMPS, + .p.priv_class = &opengl_class, .priv_data_size = sizeof(OpenGLContext), - .audio_codec = AV_CODEC_ID_NONE, - .video_codec = AV_CODEC_ID_WRAPPED_AVFRAME, .write_header = opengl_write_header, .write_packet = opengl_write_packet, .write_uncoded_frame = opengl_write_frame, .write_trailer = opengl_write_trailer, .control_message = opengl_control_message, - .flags = AVFMT_NOFILE | AVFMT_VARIABLE_FPS | AVFMT_NOTIMESTAMPS, - .priv_class = &opengl_class, }; diff --git a/libavdevice/oss_enc.c b/libavdevice/oss_enc.c index 704f434c53a..c125e6c0e9f 100644 --- a/libavdevice/oss_enc.c +++ b/libavdevice/oss_enc.c @@ -32,6 +32,7 @@ #include "avdevice.h" #include "libavformat/internal.h" +#include "libavformat/mux.h" #include "oss.h" @@ -94,18 +95,18 @@ static const AVClass oss_muxer_class = { .category = AV_CLASS_CATEGORY_DEVICE_AUDIO_OUTPUT, }; -const AVOutputFormat ff_oss_muxer = { - .name = "oss", - .long_name = NULL_IF_CONFIG_SMALL("OSS (Open Sound System) playback"), +const FFOutputFormat ff_oss_muxer = { + .p.name = "oss", + .p.long_name = NULL_IF_CONFIG_SMALL("OSS (Open Sound System) playback"), .priv_data_size = sizeof(OSSAudioData), /* XXX: we make the assumption that the soundcard accepts this format */ /* XXX: find better solution with "preinit" method, needed also in other formats */ - .audio_codec = AV_NE(AV_CODEC_ID_PCM_S16BE, AV_CODEC_ID_PCM_S16LE), - .video_codec = AV_CODEC_ID_NONE, + .p.audio_codec = AV_NE(AV_CODEC_ID_PCM_S16BE, AV_CODEC_ID_PCM_S16LE), + .p.video_codec = AV_CODEC_ID_NONE, .write_header = audio_write_header, .write_packet = audio_write_packet, .write_trailer = audio_write_trailer, - .flags = AVFMT_NOFILE, - .priv_class = &oss_muxer_class, + .p.flags = AVFMT_NOFILE, + .p.priv_class = &oss_muxer_class, }; diff --git a/libavdevice/pulse_audio_enc.c b/libavdevice/pulse_audio_enc.c index 038401c680c..3d8323233f7 100644 --- a/libavdevice/pulse_audio_enc.c +++ b/libavdevice/pulse_audio_enc.c @@ -788,12 +788,12 @@ static const AVClass pulse_muxer_class = { .category = AV_CLASS_CATEGORY_DEVICE_AUDIO_OUTPUT, }; -const AVOutputFormat ff_pulse_muxer = { - .name = "pulse", - .long_name = NULL_IF_CONFIG_SMALL("Pulse audio output"), +const FFOutputFormat ff_pulse_muxer = { + .p.name = "pulse", + .p.long_name = NULL_IF_CONFIG_SMALL("Pulse audio output"), .priv_data_size = sizeof(PulseData), - .audio_codec = AV_NE(AV_CODEC_ID_PCM_S16BE, AV_CODEC_ID_PCM_S16LE), - .video_codec = AV_CODEC_ID_NONE, + .p.audio_codec = AV_NE(AV_CODEC_ID_PCM_S16BE, AV_CODEC_ID_PCM_S16LE), + .p.video_codec = AV_CODEC_ID_NONE, .write_header = pulse_write_header, .write_packet = pulse_write_packet, .write_uncoded_frame = pulse_write_frame, @@ -801,6 +801,6 @@ const AVOutputFormat ff_pulse_muxer = { .get_output_timestamp = pulse_get_output_timestamp, .get_device_list = pulse_get_device_list, .control_message = pulse_control_message, - .flags = AVFMT_NOFILE | AVFMT_ALLOW_FLUSH, - .priv_class = &pulse_muxer_class, + .p.flags = AVFMT_NOFILE | AVFMT_ALLOW_FLUSH, + .p.priv_class = &pulse_muxer_class, }; diff --git a/libavdevice/sdl2.c b/libavdevice/sdl2.c index a9023153f13..342a253dc09 100644 --- a/libavdevice/sdl2.c +++ b/libavdevice/sdl2.c @@ -33,6 +33,7 @@ #include "libavutil/pixdesc.h" #include "libavutil/time.h" #include "avdevice.h" +#include "libavformat/mux.h" typedef struct { AVClass *class; @@ -355,15 +356,15 @@ static const AVClass sdl2_class = { .category = AV_CLASS_CATEGORY_DEVICE_VIDEO_OUTPUT, }; -const AVOutputFormat ff_sdl2_muxer = { - .name = "sdl,sdl2", - .long_name = NULL_IF_CONFIG_SMALL("SDL2 output device"), +const FFOutputFormat ff_sdl2_muxer = { + .p.name = "sdl,sdl2", + .p.long_name = NULL_IF_CONFIG_SMALL("SDL2 output device"), .priv_data_size = sizeof(SDLContext), - .audio_codec = AV_CODEC_ID_NONE, - .video_codec = AV_CODEC_ID_RAWVIDEO, + .p.audio_codec = AV_CODEC_ID_NONE, + .p.video_codec = AV_CODEC_ID_RAWVIDEO, .write_header = sdl2_write_header, .write_packet = sdl2_write_packet, .write_trailer = sdl2_write_trailer, - .flags = AVFMT_NOFILE | AVFMT_VARIABLE_FPS | AVFMT_NOTIMESTAMPS, - .priv_class = &sdl2_class, + .p.flags = AVFMT_NOFILE | AVFMT_VARIABLE_FPS | AVFMT_NOTIMESTAMPS, + .p.priv_class = &sdl2_class, }; diff --git a/libavdevice/sndio_enc.c b/libavdevice/sndio_enc.c index 0cf58fdc6ab..578e287a41f 100644 --- a/libavdevice/sndio_enc.c +++ b/libavdevice/sndio_enc.c @@ -24,6 +24,7 @@ #include "libavutil/internal.h" +#include "libavformat/mux.h" #include "libavdevice/avdevice.h" #include "libavdevice/sndio.h" @@ -86,18 +87,18 @@ static const AVClass sndio_muxer_class = { .category = AV_CLASS_CATEGORY_DEVICE_AUDIO_OUTPUT, }; -const AVOutputFormat ff_sndio_muxer = { - .name = "sndio", - .long_name = NULL_IF_CONFIG_SMALL("sndio audio playback"), +const FFOutputFormat ff_sndio_muxer = { + .p.name = "sndio", + .p.long_name = NULL_IF_CONFIG_SMALL("sndio audio playback"), .priv_data_size = sizeof(SndioData), /* XXX: we make the assumption that the soundcard accepts this format */ /* XXX: find better solution with "preinit" method, needed also in other formats */ - .audio_codec = AV_NE(AV_CODEC_ID_PCM_S16BE, AV_CODEC_ID_PCM_S16LE), - .video_codec = AV_CODEC_ID_NONE, + .p.audio_codec = AV_NE(AV_CODEC_ID_PCM_S16BE, AV_CODEC_ID_PCM_S16LE), + .p.video_codec = AV_CODEC_ID_NONE, .write_header = audio_write_header, .write_packet = audio_write_packet, .write_trailer = audio_write_trailer, - .flags = AVFMT_NOFILE, - .priv_class = &sndio_muxer_class, + .p.flags = AVFMT_NOFILE, + .p.priv_class = &sndio_muxer_class, }; diff --git a/libavdevice/v4l2enc.c b/libavdevice/v4l2enc.c index b1006461b7a..8e8f911996c 100644 --- a/libavdevice/v4l2enc.c +++ b/libavdevice/v4l2enc.c @@ -21,6 +21,7 @@ #include "libavutil/imgutils.h" #include "libavutil/pixdesc.h" #include "libavformat/avformat.h" +#include "libavformat/mux.h" #include "v4l2-common.h" typedef struct { @@ -111,15 +112,15 @@ static const AVClass v4l2_class = { .category = AV_CLASS_CATEGORY_DEVICE_VIDEO_OUTPUT, }; -const AVOutputFormat ff_v4l2_muxer = { - .name = "video4linux2,v4l2", - .long_name = NULL_IF_CONFIG_SMALL("Video4Linux2 output device"), +const FFOutputFormat ff_v4l2_muxer = { + .p.name = "video4linux2,v4l2", + .p.long_name = NULL_IF_CONFIG_SMALL("Video4Linux2 output device"), .priv_data_size = sizeof(V4L2Context), - .audio_codec = AV_CODEC_ID_NONE, - .video_codec = AV_CODEC_ID_RAWVIDEO, + .p.audio_codec = AV_CODEC_ID_NONE, + .p.video_codec = AV_CODEC_ID_RAWVIDEO, .write_header = write_header, .write_packet = write_packet, .write_trailer = write_trailer, - .flags = AVFMT_NOFILE, - .priv_class = &v4l2_class, + .p.flags = AVFMT_NOFILE, + .p.priv_class = &v4l2_class, }; diff --git a/libavdevice/xv.c b/libavdevice/xv.c index 348c289beae..441f8541218 100644 --- a/libavdevice/xv.c +++ b/libavdevice/xv.c @@ -376,17 +376,17 @@ static const AVClass xv_class = { .category = AV_CLASS_CATEGORY_DEVICE_VIDEO_OUTPUT, }; -const AVOutputFormat ff_xv_muxer = { - .name = "xv", - .long_name = NULL_IF_CONFIG_SMALL("XV (XVideo) output device"), +const FFOutputFormat ff_xv_muxer = { + .p.name = "xv", + .p.long_name = NULL_IF_CONFIG_SMALL("XV (XVideo) output device"), + .p.audio_codec = AV_CODEC_ID_NONE, + .p.video_codec = AV_CODEC_ID_WRAPPED_AVFRAME, + .p.flags = AVFMT_NOFILE | AVFMT_VARIABLE_FPS | AVFMT_NOTIMESTAMPS, + .p.priv_class = &xv_class, .priv_data_size = sizeof(XVContext), - .audio_codec = AV_CODEC_ID_NONE, - .video_codec = AV_CODEC_ID_WRAPPED_AVFRAME, .write_header = xv_write_header, .write_packet = xv_write_packet, .write_uncoded_frame = xv_write_frame, .write_trailer = xv_write_trailer, .control_message = xv_control_message, - .flags = AVFMT_NOFILE | AVFMT_VARIABLE_FPS | AVFMT_NOTIMESTAMPS, - .priv_class = &xv_class, }; diff --git a/libavformat/a64.c b/libavformat/a64.c index a66f2542b7e..23b20fc8b79 100644 --- a/libavformat/a64.c +++ b/libavformat/a64.c @@ -23,6 +23,7 @@ #include "libavcodec/codec_id.h" #include "libavcodec/codec_par.h" #include "avformat.h" +#include "mux.h" #include "rawenc.h" static int a64_write_header(AVFormatContext *s) @@ -59,11 +60,11 @@ static int a64_write_header(AVFormatContext *s) return 0; } -const AVOutputFormat ff_a64_muxer = { - .name = "a64", - .long_name = NULL_IF_CONFIG_SMALL("a64 - video for Commodore 64"), - .extensions = "a64, A64", - .video_codec = AV_CODEC_ID_A64_MULTI, +const FFOutputFormat ff_a64_muxer = { + .p.name = "a64", + .p.long_name = NULL_IF_CONFIG_SMALL("a64 - video for Commodore 64"), + .p.extensions = "a64, A64", + .p.video_codec = AV_CODEC_ID_A64_MULTI, .write_header = a64_write_header, .write_packet = ff_raw_write_packet, }; diff --git a/libavformat/adtsenc.c b/libavformat/adtsenc.c index 5f2461cc6c6..b5e9640544b 100644 --- a/libavformat/adtsenc.c +++ b/libavformat/adtsenc.c @@ -31,6 +31,7 @@ #include "avformat.h" #include "apetag.h" #include "id3v2.h" +#include "mux.h" #define ADTS_HEADER_SIZE 7 @@ -232,18 +233,18 @@ static const AVClass adts_muxer_class = { .version = LIBAVUTIL_VERSION_INT, }; -const AVOutputFormat ff_adts_muxer = { - .name = "adts", - .long_name = NULL_IF_CONFIG_SMALL("ADTS AAC (Advanced Audio Coding)"), - .mime_type = "audio/aac", - .extensions = "aac,adts", +const FFOutputFormat ff_adts_muxer = { + .p.name = "adts", + .p.long_name = NULL_IF_CONFIG_SMALL("ADTS AAC (Advanced Audio Coding)"), + .p.mime_type = "audio/aac", + .p.extensions = "aac,adts", .priv_data_size = sizeof(ADTSContext), - .audio_codec = AV_CODEC_ID_AAC, - .video_codec = AV_CODEC_ID_NONE, + .p.audio_codec = AV_CODEC_ID_AAC, + .p.video_codec = AV_CODEC_ID_NONE, .init = adts_init, .write_header = adts_write_header, .write_packet = adts_write_packet, .write_trailer = adts_write_trailer, - .priv_class = &adts_muxer_class, - .flags = AVFMT_NOTIMESTAMPS, + .p.priv_class = &adts_muxer_class, + .p.flags = AVFMT_NOTIMESTAMPS, }; diff --git a/libavformat/aiffenc.c b/libavformat/aiffenc.c index bdaf5c2c3e4..11a5b18d573 100644 --- a/libavformat/aiffenc.c +++ b/libavformat/aiffenc.c @@ -30,6 +30,7 @@ #include "avio_internal.h" #include "isom.h" #include "id3v2.h" +#include "mux.h" typedef struct AIFFOutputContext { const AVClass *class; @@ -284,18 +285,18 @@ static const AVClass aiff_muxer_class = { .version = LIBAVUTIL_VERSION_INT, }; -const AVOutputFormat ff_aiff_muxer = { - .name = "aiff", - .long_name = NULL_IF_CONFIG_SMALL("Audio IFF"), - .mime_type = "audio/aiff", - .extensions = "aif,aiff,afc,aifc", +const FFOutputFormat ff_aiff_muxer = { + .p.name = "aiff", + .p.long_name = NULL_IF_CONFIG_SMALL("Audio IFF"), + .p.mime_type = "audio/aiff", + .p.extensions = "aif,aiff,afc,aifc", .priv_data_size = sizeof(AIFFOutputContext), - .audio_codec = AV_CODEC_ID_PCM_S16BE, - .video_codec = AV_CODEC_ID_PNG, + .p.audio_codec = AV_CODEC_ID_PCM_S16BE, + .p.video_codec = AV_CODEC_ID_PNG, .write_header = aiff_write_header, .write_packet = aiff_write_packet, .write_trailer = aiff_write_trailer, .deinit = aiff_deinit, - .codec_tag = ff_aiff_codec_tags_list, - .priv_class = &aiff_muxer_class, + .p.codec_tag = ff_aiff_codec_tags_list, + .p.priv_class = &aiff_muxer_class, }; diff --git a/libavformat/allformats.c b/libavformat/allformats.c index b5a3d909bd9..365d7f34282 100644 --- a/libavformat/allformats.c +++ b/libavformat/allformats.c @@ -25,82 +25,83 @@ #include "libavformat/internal.h" #include "avformat.h" +#include "mux.h" /* (de)muxers */ -extern const AVOutputFormat ff_a64_muxer; +extern const FFOutputFormat ff_a64_muxer; extern const AVInputFormat ff_aa_demuxer; extern const AVInputFormat ff_aac_demuxer; extern const AVInputFormat ff_aax_demuxer; extern const AVInputFormat ff_ac3_demuxer; -extern const AVOutputFormat ff_ac3_muxer; +extern const FFOutputFormat ff_ac3_muxer; extern const AVInputFormat ff_ace_demuxer; extern const AVInputFormat ff_acm_demuxer; extern const AVInputFormat ff_act_demuxer; extern const AVInputFormat ff_adf_demuxer; extern const AVInputFormat ff_adp_demuxer; extern const AVInputFormat ff_ads_demuxer; -extern const AVOutputFormat ff_adts_muxer; +extern const FFOutputFormat ff_adts_muxer; extern const AVInputFormat ff_adx_demuxer; -extern const AVOutputFormat ff_adx_muxer; +extern const FFOutputFormat ff_adx_muxer; extern const AVInputFormat ff_aea_demuxer; extern const AVInputFormat ff_afc_demuxer; extern const AVInputFormat ff_aiff_demuxer; -extern const AVOutputFormat ff_aiff_muxer; +extern const FFOutputFormat ff_aiff_muxer; extern const AVInputFormat ff_aix_demuxer; extern const AVInputFormat ff_alp_demuxer; -extern const AVOutputFormat ff_alp_muxer; +extern const FFOutputFormat ff_alp_muxer; extern const AVInputFormat ff_amr_demuxer; -extern const AVOutputFormat ff_amr_muxer; +extern const FFOutputFormat ff_amr_muxer; extern const AVInputFormat ff_amrnb_demuxer; extern const AVInputFormat ff_amrwb_demuxer; -extern const AVOutputFormat ff_amv_muxer; +extern const FFOutputFormat ff_amv_muxer; extern const AVInputFormat ff_anm_demuxer; extern const AVInputFormat ff_apac_demuxer; extern const AVInputFormat ff_apc_demuxer; extern const AVInputFormat ff_ape_demuxer; extern const AVInputFormat ff_apm_demuxer; -extern const AVOutputFormat ff_apm_muxer; +extern const FFOutputFormat ff_apm_muxer; extern const AVInputFormat ff_apng_demuxer; -extern const AVOutputFormat ff_apng_muxer; +extern const FFOutputFormat ff_apng_muxer; extern const AVInputFormat ff_aptx_demuxer; -extern const AVOutputFormat ff_aptx_muxer; +extern const FFOutputFormat ff_aptx_muxer; extern const AVInputFormat ff_aptx_hd_demuxer; -extern const AVOutputFormat ff_aptx_hd_muxer; +extern const FFOutputFormat ff_aptx_hd_muxer; extern const AVInputFormat ff_aqtitle_demuxer; extern const AVInputFormat ff_argo_asf_demuxer; -extern const AVOutputFormat ff_argo_asf_muxer; +extern const FFOutputFormat ff_argo_asf_muxer; extern const AVInputFormat ff_argo_brp_demuxer; extern const AVInputFormat ff_argo_cvg_demuxer; -extern const AVOutputFormat ff_argo_cvg_muxer; +extern const FFOutputFormat ff_argo_cvg_muxer; extern const AVInputFormat ff_asf_demuxer; -extern const AVOutputFormat ff_asf_muxer; +extern const FFOutputFormat ff_asf_muxer; extern const AVInputFormat ff_asf_o_demuxer; extern const AVInputFormat ff_ass_demuxer; -extern const AVOutputFormat ff_ass_muxer; +extern const FFOutputFormat ff_ass_muxer; extern const AVInputFormat ff_ast_demuxer; -extern const AVOutputFormat ff_ast_muxer; -extern const AVOutputFormat ff_asf_stream_muxer; +extern const FFOutputFormat ff_ast_muxer; +extern const FFOutputFormat ff_asf_stream_muxer; extern const AVInputFormat ff_au_demuxer; -extern const AVOutputFormat ff_au_muxer; +extern const FFOutputFormat ff_au_muxer; extern const AVInputFormat ff_av1_demuxer; extern const AVInputFormat ff_avi_demuxer; -extern const AVOutputFormat ff_avi_muxer; -extern const AVOutputFormat ff_avif_muxer; +extern const FFOutputFormat ff_avi_muxer; +extern const FFOutputFormat ff_avif_muxer; extern const AVInputFormat ff_avisynth_demuxer; -extern const AVOutputFormat ff_avm2_muxer; +extern const FFOutputFormat ff_avm2_muxer; extern const AVInputFormat ff_avr_demuxer; extern const AVInputFormat ff_avs_demuxer; extern const AVInputFormat ff_avs2_demuxer; -extern const AVOutputFormat ff_avs2_muxer; +extern const FFOutputFormat ff_avs2_muxer; extern const AVInputFormat ff_avs3_demuxer; -extern const AVOutputFormat ff_avs3_muxer; +extern const FFOutputFormat ff_avs3_muxer; extern const AVInputFormat ff_bethsoftvid_demuxer; extern const AVInputFormat ff_bfi_demuxer; extern const AVInputFormat ff_bintext_demuxer; 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 FFOutputFormat ff_bit_muxer; extern const AVInputFormat ff_bitpacked_demuxer; extern const AVInputFormat ff_bmv_demuxer; extern const AVInputFormat ff_bfstm_demuxer; @@ -109,190 +110,190 @@ extern const AVInputFormat ff_boa_demuxer; extern const AVInputFormat ff_bonk_demuxer; extern const AVInputFormat ff_c93_demuxer; extern const AVInputFormat ff_caf_demuxer; -extern const AVOutputFormat ff_caf_muxer; +extern const FFOutputFormat ff_caf_muxer; extern const AVInputFormat ff_cavsvideo_demuxer; -extern const AVOutputFormat ff_cavsvideo_muxer; +extern const FFOutputFormat ff_cavsvideo_muxer; extern const AVInputFormat ff_cdg_demuxer; extern const AVInputFormat ff_cdxl_demuxer; extern const AVInputFormat ff_cine_demuxer; extern const AVInputFormat ff_codec2_demuxer; -extern const AVOutputFormat ff_codec2_muxer; +extern const FFOutputFormat ff_codec2_muxer; extern const AVInputFormat ff_codec2raw_demuxer; -extern const AVOutputFormat ff_codec2raw_muxer; +extern const FFOutputFormat ff_codec2raw_muxer; extern const AVInputFormat ff_concat_demuxer; -extern const AVOutputFormat ff_crc_muxer; +extern const FFOutputFormat ff_crc_muxer; extern const AVInputFormat ff_dash_demuxer; -extern const AVOutputFormat ff_dash_muxer; +extern const FFOutputFormat ff_dash_muxer; extern const AVInputFormat ff_data_demuxer; -extern const AVOutputFormat ff_data_muxer; +extern const FFOutputFormat ff_data_muxer; extern const AVInputFormat ff_daud_demuxer; -extern const AVOutputFormat ff_daud_muxer; +extern const FFOutputFormat ff_daud_muxer; extern const AVInputFormat ff_dcstr_demuxer; extern const AVInputFormat ff_derf_demuxer; extern const AVInputFormat ff_dfa_demuxer; extern const AVInputFormat ff_dfpwm_demuxer; -extern const AVOutputFormat ff_dfpwm_muxer; +extern const FFOutputFormat ff_dfpwm_muxer; extern const AVInputFormat ff_dhav_demuxer; extern const AVInputFormat ff_dirac_demuxer; -extern const AVOutputFormat ff_dirac_muxer; +extern const FFOutputFormat ff_dirac_muxer; extern const AVInputFormat ff_dnxhd_demuxer; -extern const AVOutputFormat ff_dnxhd_muxer; +extern const FFOutputFormat ff_dnxhd_muxer; extern const AVInputFormat ff_dsf_demuxer; extern const AVInputFormat ff_dsicin_demuxer; extern const AVInputFormat ff_dss_demuxer; extern const AVInputFormat ff_dts_demuxer; -extern const AVOutputFormat ff_dts_muxer; +extern const FFOutputFormat ff_dts_muxer; extern const AVInputFormat ff_dtshd_demuxer; extern const AVInputFormat ff_dv_demuxer; -extern const AVOutputFormat ff_dv_muxer; +extern const FFOutputFormat ff_dv_muxer; extern const AVInputFormat ff_dvbsub_demuxer; extern const AVInputFormat ff_dvbtxt_demuxer; extern const AVInputFormat ff_dxa_demuxer; extern const AVInputFormat ff_ea_demuxer; extern const AVInputFormat ff_ea_cdata_demuxer; extern const AVInputFormat ff_eac3_demuxer; -extern const AVOutputFormat ff_eac3_muxer; +extern const FFOutputFormat ff_eac3_muxer; extern const AVInputFormat ff_epaf_demuxer; -extern const AVOutputFormat ff_f4v_muxer; +extern const FFOutputFormat ff_f4v_muxer; extern const AVInputFormat ff_ffmetadata_demuxer; -extern const AVOutputFormat ff_ffmetadata_muxer; -extern const AVOutputFormat ff_fifo_muxer; -extern const AVOutputFormat ff_fifo_test_muxer; +extern const FFOutputFormat ff_ffmetadata_muxer; +extern const FFOutputFormat ff_fifo_muxer; +extern const FFOutputFormat ff_fifo_test_muxer; extern const AVInputFormat ff_filmstrip_demuxer; -extern const AVOutputFormat ff_filmstrip_muxer; +extern const FFOutputFormat ff_filmstrip_muxer; extern const AVInputFormat ff_fits_demuxer; -extern const AVOutputFormat ff_fits_muxer; +extern const FFOutputFormat ff_fits_muxer; extern const AVInputFormat ff_flac_demuxer; -extern const AVOutputFormat ff_flac_muxer; +extern const FFOutputFormat ff_flac_muxer; extern const AVInputFormat ff_flic_demuxer; extern const AVInputFormat ff_flv_demuxer; -extern const AVOutputFormat ff_flv_muxer; +extern const FFOutputFormat ff_flv_muxer; extern const AVInputFormat ff_live_flv_demuxer; extern const AVInputFormat ff_fourxm_demuxer; -extern const AVOutputFormat ff_framecrc_muxer; -extern const AVOutputFormat ff_framehash_muxer; -extern const AVOutputFormat ff_framemd5_muxer; +extern const FFOutputFormat ff_framecrc_muxer; +extern const FFOutputFormat ff_framehash_muxer; +extern const FFOutputFormat ff_framemd5_muxer; extern const AVInputFormat ff_frm_demuxer; extern const AVInputFormat ff_fsb_demuxer; extern const AVInputFormat ff_fwse_demuxer; extern const AVInputFormat ff_g722_demuxer; -extern const AVOutputFormat ff_g722_muxer; +extern const FFOutputFormat ff_g722_muxer; extern const AVInputFormat ff_g723_1_demuxer; -extern const AVOutputFormat ff_g723_1_muxer; +extern const FFOutputFormat ff_g723_1_muxer; extern const AVInputFormat ff_g726_demuxer; -extern const AVOutputFormat ff_g726_muxer; +extern const FFOutputFormat ff_g726_muxer; extern const AVInputFormat ff_g726le_demuxer; -extern const AVOutputFormat ff_g726le_muxer; +extern const FFOutputFormat ff_g726le_muxer; extern const AVInputFormat ff_g729_demuxer; extern const AVInputFormat ff_gdv_demuxer; extern const AVInputFormat ff_genh_demuxer; extern const AVInputFormat ff_gif_demuxer; -extern const AVOutputFormat ff_gif_muxer; +extern const FFOutputFormat ff_gif_muxer; extern const AVInputFormat ff_gsm_demuxer; -extern const AVOutputFormat ff_gsm_muxer; +extern const FFOutputFormat ff_gsm_muxer; extern const AVInputFormat ff_gxf_demuxer; -extern const AVOutputFormat ff_gxf_muxer; +extern const FFOutputFormat ff_gxf_muxer; extern const AVInputFormat ff_h261_demuxer; -extern const AVOutputFormat ff_h261_muxer; +extern const FFOutputFormat ff_h261_muxer; extern const AVInputFormat ff_h263_demuxer; -extern const AVOutputFormat ff_h263_muxer; +extern const FFOutputFormat ff_h263_muxer; extern const AVInputFormat ff_h264_demuxer; -extern const AVOutputFormat ff_h264_muxer; -extern const AVOutputFormat ff_hash_muxer; +extern const FFOutputFormat ff_h264_muxer; +extern const FFOutputFormat ff_hash_muxer; extern const AVInputFormat ff_hca_demuxer; extern const AVInputFormat ff_hcom_demuxer; -extern const AVOutputFormat ff_hds_muxer; +extern const FFOutputFormat ff_hds_muxer; extern const AVInputFormat ff_hevc_demuxer; -extern const AVOutputFormat ff_hevc_muxer; +extern const FFOutputFormat ff_hevc_muxer; extern const AVInputFormat ff_hls_demuxer; -extern const AVOutputFormat ff_hls_muxer; +extern const FFOutputFormat ff_hls_muxer; extern const AVInputFormat ff_hnm_demuxer; extern const AVInputFormat ff_ico_demuxer; -extern const AVOutputFormat ff_ico_muxer; +extern const FFOutputFormat ff_ico_muxer; extern const AVInputFormat ff_idcin_demuxer; extern const AVInputFormat ff_idf_demuxer; extern const AVInputFormat ff_iff_demuxer; extern const AVInputFormat ff_ifv_demuxer; extern const AVInputFormat ff_ilbc_demuxer; -extern const AVOutputFormat ff_ilbc_muxer; +extern const FFOutputFormat ff_ilbc_muxer; extern const AVInputFormat ff_image2_demuxer; -extern const AVOutputFormat ff_image2_muxer; +extern const FFOutputFormat ff_image2_muxer; extern const AVInputFormat ff_image2pipe_demuxer; -extern const AVOutputFormat ff_image2pipe_muxer; +extern const FFOutputFormat 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; +extern const FFOutputFormat ff_ipod_muxer; extern const AVInputFormat ff_ipu_demuxer; extern const AVInputFormat ff_ircam_demuxer; -extern const AVOutputFormat ff_ircam_muxer; -extern const AVOutputFormat ff_ismv_muxer; +extern const FFOutputFormat ff_ircam_muxer; +extern const FFOutputFormat ff_ismv_muxer; extern const AVInputFormat ff_iss_demuxer; extern const AVInputFormat ff_iv8_demuxer; extern const AVInputFormat ff_ivf_demuxer; -extern const AVOutputFormat ff_ivf_muxer; +extern const FFOutputFormat ff_ivf_muxer; extern const AVInputFormat ff_ivr_demuxer; extern const AVInputFormat ff_jacosub_demuxer; -extern const AVOutputFormat ff_jacosub_muxer; +extern const FFOutputFormat ff_jacosub_muxer; extern const AVInputFormat ff_jv_demuxer; extern const AVInputFormat ff_kux_demuxer; extern const AVInputFormat ff_kvag_demuxer; -extern const AVOutputFormat ff_kvag_muxer; +extern const FFOutputFormat ff_kvag_muxer; extern const AVInputFormat ff_laf_demuxer; -extern const AVOutputFormat ff_latm_muxer; +extern const FFOutputFormat ff_latm_muxer; extern const AVInputFormat ff_lmlm4_demuxer; extern const AVInputFormat ff_loas_demuxer; extern const AVInputFormat ff_luodat_demuxer; extern const AVInputFormat ff_lrc_demuxer; -extern const AVOutputFormat ff_lrc_muxer; +extern const FFOutputFormat ff_lrc_muxer; extern const AVInputFormat ff_lvf_demuxer; extern const AVInputFormat ff_lxf_demuxer; extern const AVInputFormat ff_m4v_demuxer; -extern const AVOutputFormat ff_m4v_muxer; +extern const FFOutputFormat ff_m4v_muxer; extern const AVInputFormat ff_mca_demuxer; extern const AVInputFormat ff_mcc_demuxer; -extern const AVOutputFormat ff_md5_muxer; +extern const FFOutputFormat ff_md5_muxer; extern const AVInputFormat ff_matroska_demuxer; -extern const AVOutputFormat ff_matroska_muxer; -extern const AVOutputFormat ff_matroska_audio_muxer; +extern const FFOutputFormat ff_matroska_muxer; +extern const FFOutputFormat ff_matroska_audio_muxer; extern const AVInputFormat ff_mgsts_demuxer; extern const AVInputFormat ff_microdvd_demuxer; -extern const AVOutputFormat ff_microdvd_muxer; +extern const FFOutputFormat ff_microdvd_muxer; extern const AVInputFormat ff_mjpeg_demuxer; -extern const AVOutputFormat ff_mjpeg_muxer; +extern const FFOutputFormat ff_mjpeg_muxer; extern const AVInputFormat ff_mjpeg_2000_demuxer; extern const AVInputFormat ff_mlp_demuxer; -extern const AVOutputFormat ff_mlp_muxer; +extern const FFOutputFormat ff_mlp_muxer; extern const AVInputFormat ff_mlv_demuxer; extern const AVInputFormat ff_mm_demuxer; extern const AVInputFormat ff_mmf_demuxer; -extern const AVOutputFormat ff_mmf_muxer; +extern const FFOutputFormat ff_mmf_muxer; extern const AVInputFormat ff_mods_demuxer; extern const AVInputFormat ff_moflex_demuxer; extern const AVInputFormat ff_mov_demuxer; -extern const AVOutputFormat ff_mov_muxer; -extern const AVOutputFormat ff_mp2_muxer; +extern const FFOutputFormat ff_mov_muxer; +extern const FFOutputFormat ff_mp2_muxer; extern const AVInputFormat ff_mp3_demuxer; -extern const AVOutputFormat ff_mp3_muxer; -extern const AVOutputFormat ff_mp4_muxer; +extern const FFOutputFormat ff_mp3_muxer; +extern const FFOutputFormat ff_mp4_muxer; extern const AVInputFormat ff_mpc_demuxer; extern const AVInputFormat ff_mpc8_demuxer; -extern const AVOutputFormat ff_mpeg1system_muxer; -extern const AVOutputFormat ff_mpeg1vcd_muxer; -extern const AVOutputFormat ff_mpeg1video_muxer; -extern const AVOutputFormat ff_mpeg2dvd_muxer; -extern const AVOutputFormat ff_mpeg2svcd_muxer; -extern const AVOutputFormat ff_mpeg2video_muxer; -extern const AVOutputFormat ff_mpeg2vob_muxer; +extern const FFOutputFormat ff_mpeg1system_muxer; +extern const FFOutputFormat ff_mpeg1vcd_muxer; +extern const FFOutputFormat ff_mpeg1video_muxer; +extern const FFOutputFormat ff_mpeg2dvd_muxer; +extern const FFOutputFormat ff_mpeg2svcd_muxer; +extern const FFOutputFormat ff_mpeg2video_muxer; +extern const FFOutputFormat ff_mpeg2vob_muxer; extern const AVInputFormat ff_mpegps_demuxer; extern const AVInputFormat ff_mpegts_demuxer; -extern const AVOutputFormat ff_mpegts_muxer; +extern const FFOutputFormat ff_mpegts_muxer; extern const AVInputFormat ff_mpegtsraw_demuxer; extern const AVInputFormat ff_mpegvideo_demuxer; extern const AVInputFormat ff_mpjpeg_demuxer; -extern const AVOutputFormat ff_mpjpeg_muxer; +extern const FFOutputFormat ff_mpjpeg_muxer; extern const AVInputFormat ff_mpl2_demuxer; extern const AVInputFormat ff_mpsub_demuxer; extern const AVInputFormat ff_msf_demuxer; @@ -304,114 +305,114 @@ extern const AVInputFormat ff_musx_demuxer; extern const AVInputFormat ff_mv_demuxer; extern const AVInputFormat ff_mvi_demuxer; extern const AVInputFormat ff_mxf_demuxer; -extern const AVOutputFormat ff_mxf_muxer; -extern const AVOutputFormat ff_mxf_d10_muxer; -extern const AVOutputFormat ff_mxf_opatom_muxer; +extern const FFOutputFormat ff_mxf_muxer; +extern const FFOutputFormat ff_mxf_d10_muxer; +extern const FFOutputFormat ff_mxf_opatom_muxer; extern const AVInputFormat ff_mxg_demuxer; extern const AVInputFormat ff_nc_demuxer; extern const AVInputFormat ff_nistsphere_demuxer; extern const AVInputFormat ff_nsp_demuxer; extern const AVInputFormat ff_nsv_demuxer; -extern const AVOutputFormat ff_null_muxer; +extern const FFOutputFormat ff_null_muxer; extern const AVInputFormat ff_nut_demuxer; -extern const AVOutputFormat ff_nut_muxer; +extern const FFOutputFormat ff_nut_muxer; extern const AVInputFormat ff_nuv_demuxer; extern const AVInputFormat ff_obu_demuxer; -extern const AVOutputFormat ff_obu_muxer; -extern const AVOutputFormat ff_oga_muxer; +extern const FFOutputFormat ff_obu_muxer; +extern const FFOutputFormat ff_oga_muxer; extern const AVInputFormat ff_ogg_demuxer; -extern const AVOutputFormat ff_ogg_muxer; -extern const AVOutputFormat ff_ogv_muxer; +extern const FFOutputFormat ff_ogg_muxer; +extern const FFOutputFormat ff_ogv_muxer; extern const AVInputFormat ff_oma_demuxer; -extern const AVOutputFormat ff_oma_muxer; -extern const AVOutputFormat ff_opus_muxer; +extern const FFOutputFormat ff_oma_muxer; +extern const FFOutputFormat ff_opus_muxer; extern const AVInputFormat ff_paf_demuxer; extern const AVInputFormat ff_pcm_alaw_demuxer; -extern const AVOutputFormat ff_pcm_alaw_muxer; +extern const FFOutputFormat ff_pcm_alaw_muxer; extern const AVInputFormat ff_pcm_mulaw_demuxer; -extern const AVOutputFormat ff_pcm_mulaw_muxer; +extern const FFOutputFormat ff_pcm_mulaw_muxer; extern const AVInputFormat ff_pcm_vidc_demuxer; -extern const AVOutputFormat ff_pcm_vidc_muxer; +extern const FFOutputFormat ff_pcm_vidc_muxer; extern const AVInputFormat ff_pcm_f64be_demuxer; -extern const AVOutputFormat ff_pcm_f64be_muxer; +extern const FFOutputFormat ff_pcm_f64be_muxer; extern const AVInputFormat ff_pcm_f64le_demuxer; -extern const AVOutputFormat ff_pcm_f64le_muxer; +extern const FFOutputFormat ff_pcm_f64le_muxer; extern const AVInputFormat ff_pcm_f32be_demuxer; -extern const AVOutputFormat ff_pcm_f32be_muxer; +extern const FFOutputFormat ff_pcm_f32be_muxer; extern const AVInputFormat ff_pcm_f32le_demuxer; -extern const AVOutputFormat ff_pcm_f32le_muxer; +extern const FFOutputFormat ff_pcm_f32le_muxer; extern const AVInputFormat ff_pcm_s32be_demuxer; -extern const AVOutputFormat ff_pcm_s32be_muxer; +extern const FFOutputFormat ff_pcm_s32be_muxer; extern const AVInputFormat ff_pcm_s32le_demuxer; -extern const AVOutputFormat ff_pcm_s32le_muxer; +extern const FFOutputFormat ff_pcm_s32le_muxer; extern const AVInputFormat ff_pcm_s24be_demuxer; -extern const AVOutputFormat ff_pcm_s24be_muxer; +extern const FFOutputFormat ff_pcm_s24be_muxer; extern const AVInputFormat ff_pcm_s24le_demuxer; -extern const AVOutputFormat ff_pcm_s24le_muxer; +extern const FFOutputFormat ff_pcm_s24le_muxer; extern const AVInputFormat ff_pcm_s16be_demuxer; -extern const AVOutputFormat ff_pcm_s16be_muxer; +extern const FFOutputFormat ff_pcm_s16be_muxer; extern const AVInputFormat ff_pcm_s16le_demuxer; -extern const AVOutputFormat ff_pcm_s16le_muxer; +extern const FFOutputFormat ff_pcm_s16le_muxer; extern const AVInputFormat ff_pcm_s8_demuxer; -extern const AVOutputFormat ff_pcm_s8_muxer; +extern const FFOutputFormat ff_pcm_s8_muxer; extern const AVInputFormat ff_pcm_u32be_demuxer; -extern const AVOutputFormat ff_pcm_u32be_muxer; +extern const FFOutputFormat ff_pcm_u32be_muxer; extern const AVInputFormat ff_pcm_u32le_demuxer; -extern const AVOutputFormat ff_pcm_u32le_muxer; +extern const FFOutputFormat ff_pcm_u32le_muxer; extern const AVInputFormat ff_pcm_u24be_demuxer; -extern const AVOutputFormat ff_pcm_u24be_muxer; +extern const FFOutputFormat ff_pcm_u24be_muxer; extern const AVInputFormat ff_pcm_u24le_demuxer; -extern const AVOutputFormat ff_pcm_u24le_muxer; +extern const FFOutputFormat ff_pcm_u24le_muxer; extern const AVInputFormat ff_pcm_u16be_demuxer; -extern const AVOutputFormat ff_pcm_u16be_muxer; +extern const FFOutputFormat ff_pcm_u16be_muxer; extern const AVInputFormat ff_pcm_u16le_demuxer; -extern const AVOutputFormat ff_pcm_u16le_muxer; +extern const FFOutputFormat ff_pcm_u16le_muxer; extern const AVInputFormat ff_pcm_u8_demuxer; -extern const AVOutputFormat ff_pcm_u8_muxer; +extern const FFOutputFormat ff_pcm_u8_muxer; extern const AVInputFormat ff_pjs_demuxer; extern const AVInputFormat ff_pmp_demuxer; extern const AVInputFormat ff_pp_bnk_demuxer; -extern const AVOutputFormat ff_psp_muxer; +extern const FFOutputFormat ff_psp_muxer; extern const AVInputFormat ff_pva_demuxer; extern const AVInputFormat ff_pvf_demuxer; extern const AVInputFormat ff_qcp_demuxer; extern const AVInputFormat ff_r3d_demuxer; extern const AVInputFormat ff_rawvideo_demuxer; -extern const AVOutputFormat ff_rawvideo_muxer; +extern const FFOutputFormat ff_rawvideo_muxer; extern const AVInputFormat ff_realtext_demuxer; extern const AVInputFormat ff_redspark_demuxer; extern const AVInputFormat ff_rl2_demuxer; extern const AVInputFormat ff_rm_demuxer; -extern const AVOutputFormat ff_rm_muxer; +extern const FFOutputFormat ff_rm_muxer; extern const AVInputFormat ff_roq_demuxer; -extern const AVOutputFormat ff_roq_muxer; +extern const FFOutputFormat ff_roq_muxer; extern const AVInputFormat ff_rpl_demuxer; extern const AVInputFormat ff_rsd_demuxer; extern const AVInputFormat ff_rso_demuxer; -extern const AVOutputFormat ff_rso_muxer; +extern const FFOutputFormat ff_rso_muxer; extern const AVInputFormat ff_rtp_demuxer; -extern const AVOutputFormat ff_rtp_muxer; -extern const AVOutputFormat ff_rtp_mpegts_muxer; +extern const FFOutputFormat ff_rtp_muxer; +extern const FFOutputFormat ff_rtp_mpegts_muxer; extern const AVInputFormat ff_rtsp_demuxer; -extern const AVOutputFormat ff_rtsp_muxer; +extern const FFOutputFormat ff_rtsp_muxer; extern const AVInputFormat ff_s337m_demuxer; extern const AVInputFormat ff_sami_demuxer; extern const AVInputFormat ff_sap_demuxer; -extern const AVOutputFormat ff_sap_muxer; +extern const FFOutputFormat ff_sap_muxer; extern const AVInputFormat ff_sbc_demuxer; -extern const AVOutputFormat ff_sbc_muxer; +extern const FFOutputFormat ff_sbc_muxer; extern const AVInputFormat ff_sbg_demuxer; extern const AVInputFormat ff_scc_demuxer; -extern const AVOutputFormat ff_scc_muxer; +extern const FFOutputFormat 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; extern const AVInputFormat ff_sdx_demuxer; extern const AVInputFormat ff_segafilm_demuxer; -extern const AVOutputFormat ff_segafilm_muxer; -extern const AVOutputFormat ff_segment_muxer; -extern const AVOutputFormat ff_stream_segment_muxer; +extern const FFOutputFormat ff_segafilm_muxer; +extern const FFOutputFormat ff_segment_muxer; +extern const FFOutputFormat ff_stream_segment_muxer; extern const AVInputFormat ff_ser_demuxer; extern const AVInputFormat ff_sga_demuxer; extern const AVInputFormat ff_shorten_demuxer; @@ -420,86 +421,86 @@ extern const AVInputFormat ff_simbiosis_imx_demuxer; extern const AVInputFormat ff_sln_demuxer; extern const AVInputFormat ff_smacker_demuxer; extern const AVInputFormat ff_smjpeg_demuxer; -extern const AVOutputFormat ff_smjpeg_muxer; -extern const AVOutputFormat ff_smoothstreaming_muxer; +extern const FFOutputFormat ff_smjpeg_muxer; +extern const FFOutputFormat ff_smoothstreaming_muxer; extern const AVInputFormat ff_smush_demuxer; extern const AVInputFormat ff_sol_demuxer; extern const AVInputFormat ff_sox_demuxer; -extern const AVOutputFormat ff_sox_muxer; -extern const AVOutputFormat ff_spx_muxer; +extern const FFOutputFormat ff_sox_muxer; +extern const FFOutputFormat ff_spx_muxer; extern const AVInputFormat ff_spdif_demuxer; -extern const AVOutputFormat ff_spdif_muxer; +extern const FFOutputFormat ff_spdif_muxer; extern const AVInputFormat ff_srt_demuxer; -extern const AVOutputFormat ff_srt_muxer; +extern const FFOutputFormat ff_srt_muxer; extern const AVInputFormat ff_str_demuxer; extern const AVInputFormat ff_stl_demuxer; -extern const AVOutputFormat ff_streamhash_muxer; +extern const FFOutputFormat ff_streamhash_muxer; extern const AVInputFormat ff_subviewer1_demuxer; extern const AVInputFormat ff_subviewer_demuxer; extern const AVInputFormat ff_sup_demuxer; -extern const AVOutputFormat ff_sup_muxer; +extern const FFOutputFormat ff_sup_muxer; extern const AVInputFormat ff_svag_demuxer; extern const AVInputFormat ff_svs_demuxer; extern const AVInputFormat ff_swf_demuxer; -extern const AVOutputFormat ff_swf_muxer; +extern const FFOutputFormat ff_swf_muxer; extern const AVInputFormat ff_tak_demuxer; -extern const AVOutputFormat ff_tee_muxer; +extern const FFOutputFormat ff_tee_muxer; extern const AVInputFormat ff_tedcaptions_demuxer; -extern const AVOutputFormat ff_tg2_muxer; -extern const AVOutputFormat ff_tgp_muxer; +extern const FFOutputFormat ff_tg2_muxer; +extern const FFOutputFormat ff_tgp_muxer; extern const AVInputFormat ff_thp_demuxer; extern const AVInputFormat ff_threedostr_demuxer; extern const AVInputFormat ff_tiertexseq_demuxer; -extern const AVOutputFormat ff_mkvtimestamp_v2_muxer; +extern const FFOutputFormat ff_mkvtimestamp_v2_muxer; extern const AVInputFormat ff_tmv_demuxer; extern const AVInputFormat ff_truehd_demuxer; -extern const AVOutputFormat ff_truehd_muxer; +extern const FFOutputFormat ff_truehd_muxer; extern const AVInputFormat ff_tta_demuxer; -extern const AVOutputFormat ff_tta_muxer; -extern const AVOutputFormat ff_ttml_muxer; +extern const FFOutputFormat ff_tta_muxer; +extern const FFOutputFormat ff_ttml_muxer; extern const AVInputFormat ff_txd_demuxer; extern const AVInputFormat ff_tty_demuxer; extern const AVInputFormat ff_ty_demuxer; -extern const AVOutputFormat ff_uncodedframecrc_muxer; +extern const FFOutputFormat ff_uncodedframecrc_muxer; extern const AVInputFormat ff_v210_demuxer; extern const AVInputFormat ff_v210x_demuxer; extern const AVInputFormat ff_vag_demuxer; extern const AVInputFormat ff_vc1_demuxer; -extern const AVOutputFormat ff_vc1_muxer; +extern const FFOutputFormat ff_vc1_muxer; extern const AVInputFormat ff_vc1t_demuxer; -extern const AVOutputFormat ff_vc1t_muxer; +extern const FFOutputFormat ff_vc1t_muxer; extern const AVInputFormat ff_vividas_demuxer; extern const AVInputFormat ff_vivo_demuxer; extern const AVInputFormat ff_vmd_demuxer; extern const AVInputFormat ff_vobsub_demuxer; extern const AVInputFormat ff_voc_demuxer; -extern const AVOutputFormat ff_voc_muxer; +extern const FFOutputFormat ff_voc_muxer; extern const AVInputFormat ff_vpk_demuxer; extern const AVInputFormat ff_vplayer_demuxer; extern const AVInputFormat ff_vqf_demuxer; extern const AVInputFormat ff_w64_demuxer; -extern const AVOutputFormat ff_w64_muxer; +extern const FFOutputFormat ff_w64_muxer; extern const AVInputFormat ff_wady_demuxer; extern const AVInputFormat ff_wavarc_demuxer; extern const AVInputFormat ff_wav_demuxer; -extern const AVOutputFormat ff_wav_muxer; +extern const FFOutputFormat ff_wav_muxer; extern const AVInputFormat ff_wc3_demuxer; -extern const AVOutputFormat ff_webm_muxer; +extern const FFOutputFormat ff_webm_muxer; extern const AVInputFormat ff_webm_dash_manifest_demuxer; -extern const AVOutputFormat ff_webm_dash_manifest_muxer; -extern const AVOutputFormat ff_webm_chunk_muxer; -extern const AVOutputFormat ff_webp_muxer; +extern const FFOutputFormat ff_webm_dash_manifest_muxer; +extern const FFOutputFormat ff_webm_chunk_muxer; +extern const FFOutputFormat ff_webp_muxer; extern const AVInputFormat ff_webvtt_demuxer; -extern const AVOutputFormat ff_webvtt_muxer; +extern const FFOutputFormat ff_webvtt_muxer; extern const AVInputFormat ff_wsaud_demuxer; -extern const AVOutputFormat ff_wsaud_muxer; +extern const FFOutputFormat ff_wsaud_muxer; extern const AVInputFormat ff_wsd_demuxer; extern const AVInputFormat ff_wsvqa_demuxer; extern const AVInputFormat ff_wtv_demuxer; -extern const AVOutputFormat ff_wtv_muxer; +extern const FFOutputFormat ff_wtv_muxer; extern const AVInputFormat ff_wve_demuxer; extern const AVInputFormat ff_wv_demuxer; -extern const AVOutputFormat ff_wv_muxer; +extern const FFOutputFormat ff_wv_muxer; extern const AVInputFormat ff_xa_demuxer; extern const AVInputFormat ff_xbin_demuxer; extern const AVInputFormat ff_xmd_demuxer; @@ -508,7 +509,7 @@ extern const AVInputFormat ff_xvag_demuxer; extern const AVInputFormat ff_xwma_demuxer; extern const AVInputFormat ff_yop_demuxer; extern const AVInputFormat ff_yuv4mpegpipe_demuxer; -extern const AVOutputFormat ff_yuv4mpegpipe_muxer; +extern const FFOutputFormat ff_yuv4mpegpipe_muxer; /* image demuxers */ extern const AVInputFormat ff_image_bmp_pipe_demuxer; extern const AVInputFormat ff_image_cri_pipe_demuxer; @@ -548,7 +549,7 @@ extern const AVInputFormat ff_image_xpm_pipe_demuxer; extern const AVInputFormat ff_image_xwd_pipe_demuxer; /* external libraries */ -extern const AVOutputFormat ff_chromaprint_muxer; +extern const FFOutputFormat ff_chromaprint_muxer; extern const AVInputFormat ff_libgme_demuxer; extern const AVInputFormat ff_libmodplug_demuxer; extern const AVInputFormat ff_libopenmpt_demuxer; @@ -564,19 +565,21 @@ const AVOutputFormat *av_muxer_iterate(void **opaque) { static const uintptr_t size = sizeof(muxer_list)/sizeof(muxer_list[0]) - 1; uintptr_t i = (uintptr_t)*opaque; - const AVOutputFormat *f = NULL; + const FFOutputFormat *f = NULL; uintptr_t tmp; if (i < size) { f = muxer_list[i]; } else if (tmp = atomic_load_explicit(&outdev_list_intptr, memory_order_relaxed)) { - const AVOutputFormat *const *outdev_list = (const AVOutputFormat *const *)tmp; + const FFOutputFormat *const *outdev_list = (const FFOutputFormat *const *)tmp; f = outdev_list[i - size]; } - if (f) + if (f) { *opaque = (void*)(i + 1); - return f; + return &f->p; + } + return NULL; } const AVInputFormat *av_demuxer_iterate(void **opaque) @@ -598,7 +601,7 @@ const AVInputFormat *av_demuxer_iterate(void **opaque) return f; } -void avpriv_register_devices(const AVOutputFormat * const o[], const AVInputFormat * const i[]) +void avpriv_register_devices(const FFOutputFormat * const o[], const AVInputFormat * const i[]) { atomic_store_explicit(&outdev_list_intptr, (uintptr_t)o, memory_order_relaxed); atomic_store_explicit(&indev_list_intptr, (uintptr_t)i, memory_order_relaxed); diff --git a/libavformat/alp.c b/libavformat/alp.c index 40e4890a387..8c6066a59c6 100644 --- a/libavformat/alp.c +++ b/libavformat/alp.c @@ -25,6 +25,7 @@ #include "libavutil/channel_layout.h" #include "avformat.h" #include "internal.h" +#include "mux.h" #include "rawenc.h" #include "libavutil/intreadwrite.h" #include "libavutil/internal.h" @@ -290,16 +291,16 @@ static const AVClass alp_muxer_class = { .version = LIBAVUTIL_VERSION_INT }; -const AVOutputFormat ff_alp_muxer = { - .name = "alp", - .long_name = NULL_IF_CONFIG_SMALL("LEGO Racers ALP"), - .extensions = "tun,pcm", - .audio_codec = AV_CODEC_ID_ADPCM_IMA_ALP, - .video_codec = AV_CODEC_ID_NONE, +const FFOutputFormat ff_alp_muxer = { + .p.name = "alp", + .p.long_name = NULL_IF_CONFIG_SMALL("LEGO Racers ALP"), + .p.extensions = "tun,pcm", + .p.audio_codec = AV_CODEC_ID_ADPCM_IMA_ALP, + .p.video_codec = AV_CODEC_ID_NONE, + .p.priv_class = &alp_muxer_class, .init = alp_write_init, .write_header = alp_write_header, .write_packet = ff_raw_write_packet, - .priv_class = &alp_muxer_class, .priv_data_size = sizeof(ALPMuxContext) }; #endif diff --git a/libavformat/amr.c b/libavformat/amr.c index 88f07ce0bac..b6615d8295c 100644 --- a/libavformat/amr.c +++ b/libavformat/amr.c @@ -30,6 +30,7 @@ Write and read amr data according to RFC3267, http://www.ietf.org/rfc/rfc3267.tx #include "avformat.h" #include "avio_internal.h" #include "internal.h" +#include "mux.h" #include "rawdec.h" #include "rawenc.h" @@ -266,15 +267,15 @@ const AVInputFormat ff_amrwb_demuxer = { #endif #if CONFIG_AMR_MUXER -const AVOutputFormat ff_amr_muxer = { - .name = "amr", - .long_name = NULL_IF_CONFIG_SMALL("3GPP AMR"), - .mime_type = "audio/amr", - .extensions = "amr", - .audio_codec = AV_CODEC_ID_AMR_NB, - .video_codec = AV_CODEC_ID_NONE, +const FFOutputFormat ff_amr_muxer = { + .p.name = "amr", + .p.long_name = NULL_IF_CONFIG_SMALL("3GPP AMR"), + .p.mime_type = "audio/amr", + .p.extensions = "amr", + .p.audio_codec = AV_CODEC_ID_AMR_NB, + .p.video_codec = AV_CODEC_ID_NONE, + .p.flags = AVFMT_NOTIMESTAMPS, .write_header = amr_write_header, .write_packet = ff_raw_write_packet, - .flags = AVFMT_NOTIMESTAMPS, }; #endif diff --git a/libavformat/amvenc.c b/libavformat/amvenc.c index 28d4879b19e..e1b1ffd42e2 100644 --- a/libavformat/amvenc.c +++ b/libavformat/amvenc.c @@ -20,6 +20,7 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include "avformat.h" +#include "mux.h" #include "riff.h" #include "internal.h" #include "avio_internal.h" @@ -401,14 +402,14 @@ static int amv_write_trailer(AVFormatContext *s) return 0; } -const AVOutputFormat ff_amv_muxer = { - .name = "amv", - .long_name = NULL_IF_CONFIG_SMALL("AMV"), - .mime_type = "video/amv", - .extensions = "amv", +const FFOutputFormat ff_amv_muxer = { + .p.name = "amv", + .p.long_name = NULL_IF_CONFIG_SMALL("AMV"), + .p.mime_type = "video/amv", + .p.extensions = "amv", .priv_data_size = sizeof(AMVContext), - .audio_codec = AV_CODEC_ID_ADPCM_IMA_AMV, - .video_codec = AV_CODEC_ID_AMV, + .p.audio_codec = AV_CODEC_ID_ADPCM_IMA_AMV, + .p.video_codec = AV_CODEC_ID_AMV, .init = amv_init, .deinit = amv_deinit, .write_header = amv_write_header, diff --git a/libavformat/apm.c b/libavformat/apm.c index a3ddc08e83b..ccb8e22437e 100644 --- a/libavformat/apm.c +++ b/libavformat/apm.c @@ -24,6 +24,7 @@ #include "avformat.h" #include "internal.h" +#include "mux.h" #include "rawenc.h" #include "libavutil/channel_layout.h" #include "libavutil/internal.h" @@ -303,12 +304,12 @@ static int apm_write_trailer(AVFormatContext *s) return 0; } -const AVOutputFormat ff_apm_muxer = { - .name = "apm", - .long_name = NULL_IF_CONFIG_SMALL("Ubisoft Rayman 2 APM"), - .extensions = "apm", - .audio_codec = AV_CODEC_ID_ADPCM_IMA_APM, - .video_codec = AV_CODEC_ID_NONE, +const FFOutputFormat ff_apm_muxer = { + .p.name = "apm", + .p.long_name = NULL_IF_CONFIG_SMALL("Ubisoft Rayman 2 APM"), + .p.extensions = "apm", + .p.audio_codec = AV_CODEC_ID_ADPCM_IMA_APM, + .p.video_codec = AV_CODEC_ID_NONE, .init = apm_write_init, .write_header = apm_write_header, .write_packet = ff_raw_write_packet, diff --git a/libavformat/apngenc.c b/libavformat/apngenc.c index cddb148d50b..a0af916f141 100644 --- a/libavformat/apngenc.c +++ b/libavformat/apngenc.c @@ -22,6 +22,7 @@ */ #include "avformat.h" +#include "mux.h" #include "libavutil/avassert.h" #include "libavutil/crc.h" #include "libavutil/intreadwrite.h" @@ -306,18 +307,18 @@ static const AVClass apng_muxer_class = { .option = options, }; -const AVOutputFormat ff_apng_muxer = { - .name = "apng", - .long_name = NULL_IF_CONFIG_SMALL("Animated Portable Network Graphics"), - .mime_type = "image/png", - .extensions = "apng", +const FFOutputFormat ff_apng_muxer = { + .p.name = "apng", + .p.long_name = NULL_IF_CONFIG_SMALL("Animated Portable Network Graphics"), + .p.mime_type = "image/png", + .p.extensions = "apng", .priv_data_size = sizeof(APNGMuxContext), - .audio_codec = AV_CODEC_ID_NONE, - .video_codec = AV_CODEC_ID_APNG, + .p.audio_codec = AV_CODEC_ID_NONE, + .p.video_codec = AV_CODEC_ID_APNG, .write_header = apng_write_header, .write_packet = apng_write_packet, .write_trailer = apng_write_trailer, .deinit = apng_deinit, - .priv_class = &apng_muxer_class, - .flags = AVFMT_VARIABLE_FPS, + .p.priv_class = &apng_muxer_class, + .p.flags = AVFMT_VARIABLE_FPS, }; diff --git a/libavformat/argo_asf.c b/libavformat/argo_asf.c index 39a60a0dde4..5f38b68b6ac 100644 --- a/libavformat/argo_asf.c +++ b/libavformat/argo_asf.c @@ -25,6 +25,7 @@ #include "libavutil/avstring.h" #include "avformat.h" #include "internal.h" +#include "mux.h" #include "libavutil/channel_layout.h" #include "libavutil/intreadwrite.h" #include "libavutil/avassert.h" @@ -470,20 +471,20 @@ static const AVClass argo_asf_muxer_class = { .version = LIBAVUTIL_VERSION_INT }; -const AVOutputFormat ff_argo_asf_muxer = { - .name = "argo_asf", - .long_name = NULL_IF_CONFIG_SMALL("Argonaut Games ASF"), +const FFOutputFormat ff_argo_asf_muxer = { + .p.name = "argo_asf", + .p.long_name = NULL_IF_CONFIG_SMALL("Argonaut Games ASF"), /* * NB: Can't do this as it conflicts with the actual ASF format. - * .extensions = "asf", + * .p.extensions = "asf", */ - .audio_codec = AV_CODEC_ID_ADPCM_ARGO, - .video_codec = AV_CODEC_ID_NONE, + .p.audio_codec = AV_CODEC_ID_ADPCM_ARGO, + .p.video_codec = AV_CODEC_ID_NONE, + .p.priv_class = &argo_asf_muxer_class, .init = argo_asf_write_init, .write_header = argo_asf_write_header, .write_packet = argo_asf_write_packet, .write_trailer = argo_asf_write_trailer, - .priv_class = &argo_asf_muxer_class, .priv_data_size = sizeof(ArgoASFMuxContext) }; #endif diff --git a/libavformat/argo_cvg.c b/libavformat/argo_cvg.c index aedc7c4a329..2c74200b7d8 100644 --- a/libavformat/argo_cvg.c +++ b/libavformat/argo_cvg.c @@ -26,6 +26,7 @@ #include "libavutil/channel_layout.h" #include "avformat.h" #include "internal.h" +#include "mux.h" #include "libavutil/opt.h" #include "libavutil/intreadwrite.h" @@ -400,17 +401,17 @@ static const AVClass argo_cvg_muxer_class = { .version = LIBAVUTIL_VERSION_INT }; -const AVOutputFormat ff_argo_cvg_muxer = { - .name = "argo_cvg", - .long_name = NULL_IF_CONFIG_SMALL("Argonaut Games CVG"), - .extensions = "cvg", - .audio_codec = AV_CODEC_ID_ADPCM_PSX, - .video_codec = AV_CODEC_ID_NONE, +const FFOutputFormat ff_argo_cvg_muxer = { + .p.name = "argo_cvg", + .p.long_name = NULL_IF_CONFIG_SMALL("Argonaut Games CVG"), + .p.extensions = "cvg", + .p.audio_codec = AV_CODEC_ID_ADPCM_PSX, + .p.video_codec = AV_CODEC_ID_NONE, + .p.priv_class = &argo_cvg_muxer_class, .init = argo_cvg_write_init, .write_header = argo_cvg_write_header, .write_packet = argo_cvg_write_packet, .write_trailer = argo_cvg_write_trailer, - .priv_class = &argo_cvg_muxer_class, .priv_data_size = sizeof(ArgoCVGMuxContext), }; #endif diff --git a/libavformat/asfenc.c b/libavformat/asfenc.c index 47240fc0a80..244c7e7a271 100644 --- a/libavformat/asfenc.c +++ b/libavformat/asfenc.c @@ -1129,39 +1129,39 @@ static const AVClass asf_muxer_class = { }; #if CONFIG_ASF_MUXER -const AVOutputFormat ff_asf_muxer = { - .name = "asf", - .long_name = NULL_IF_CONFIG_SMALL("ASF (Advanced / Active Streaming Format)"), - .mime_type = "video/x-ms-asf", - .extensions = "asf,wmv,wma", +const FFOutputFormat ff_asf_muxer = { + .p.name = "asf", + .p.long_name = NULL_IF_CONFIG_SMALL("ASF (Advanced / Active Streaming Format)"), + .p.mime_type = "video/x-ms-asf", + .p.extensions = "asf,wmv,wma", + .p.audio_codec = AV_CODEC_ID_WMAV2, + .p.video_codec = AV_CODEC_ID_MSMPEG4V3, + .p.flags = AVFMT_GLOBALHEADER, + .p.codec_tag = asf_codec_tags, + .p.priv_class = &asf_muxer_class, .priv_data_size = sizeof(ASFContext), - .audio_codec = AV_CODEC_ID_WMAV2, - .video_codec = AV_CODEC_ID_MSMPEG4V3, .write_header = asf_write_header, .write_packet = asf_write_packet, .write_trailer = asf_write_trailer, - .flags = AVFMT_GLOBALHEADER, - .codec_tag = asf_codec_tags, - .priv_class = &asf_muxer_class, .deinit = asf_deinit, }; #endif /* CONFIG_ASF_MUXER */ #if CONFIG_ASF_STREAM_MUXER -const AVOutputFormat ff_asf_stream_muxer = { - .name = "asf_stream", - .long_name = NULL_IF_CONFIG_SMALL("ASF (Advanced / Active Streaming Format)"), - .mime_type = "video/x-ms-asf", - .extensions = "asf,wmv,wma", +const FFOutputFormat ff_asf_stream_muxer = { + .p.name = "asf_stream", + .p.long_name = NULL_IF_CONFIG_SMALL("ASF (Advanced / Active Streaming Format)"), + .p.mime_type = "video/x-ms-asf", + .p.extensions = "asf,wmv,wma", .priv_data_size = sizeof(ASFContext), - .audio_codec = AV_CODEC_ID_WMAV2, - .video_codec = AV_CODEC_ID_MSMPEG4V3, + .p.audio_codec = AV_CODEC_ID_WMAV2, + .p.video_codec = AV_CODEC_ID_MSMPEG4V3, .write_header = asf_write_stream_header, .write_packet = asf_write_packet, .write_trailer = asf_write_trailer, - .flags = AVFMT_GLOBALHEADER, - .codec_tag = asf_codec_tags, - .priv_class = &asf_muxer_class, + .p.flags = AVFMT_GLOBALHEADER, + .p.codec_tag = asf_codec_tags, + .p.priv_class = &asf_muxer_class, .deinit = asf_deinit, }; #endif /* CONFIG_ASF_STREAM_MUXER */ diff --git a/libavformat/assenc.c b/libavformat/assenc.c index 1600f0a02b2..85a1e533715 100644 --- a/libavformat/assenc.c +++ b/libavformat/assenc.c @@ -22,6 +22,7 @@ #include "libavutil/avstring.h" #include "avformat.h" #include "internal.h" +#include "mux.h" #include "libavutil/opt.h" @@ -226,16 +227,16 @@ static const AVClass ass_class = { .version = LIBAVUTIL_VERSION_INT, }; -const AVOutputFormat ff_ass_muxer = { - .name = "ass", - .long_name = NULL_IF_CONFIG_SMALL("SSA (SubStation Alpha) subtitle"), - .mime_type = "text/x-ass", - .extensions = "ass,ssa", +const FFOutputFormat ff_ass_muxer = { + .p.name = "ass", + .p.long_name = NULL_IF_CONFIG_SMALL("SSA (SubStation Alpha) subtitle"), + .p.mime_type = "text/x-ass", + .p.extensions = "ass,ssa", + .p.subtitle_codec = AV_CODEC_ID_ASS, + .p.flags = AVFMT_GLOBALHEADER | AVFMT_NOTIMESTAMPS | AVFMT_TS_NONSTRICT, + .p.priv_class = &ass_class, .priv_data_size = sizeof(ASSContext), - .subtitle_codec = AV_CODEC_ID_ASS, .write_header = write_header, .write_packet = write_packet, .write_trailer = write_trailer, - .flags = AVFMT_GLOBALHEADER | AVFMT_NOTIMESTAMPS | AVFMT_TS_NONSTRICT, - .priv_class = &ass_class, }; diff --git a/libavformat/astenc.c b/libavformat/astenc.c index b29cfc4aaf0..9dd388040f9 100644 --- a/libavformat/astenc.c +++ b/libavformat/astenc.c @@ -23,6 +23,7 @@ #include "avio_internal.h" #include "internal.h" #include "ast.h" +#include "mux.h" #include "libavutil/mathematics.h" #include "libavutil/opt.h" @@ -194,16 +195,16 @@ static const AVClass ast_muxer_class = { .version = LIBAVUTIL_VERSION_INT, }; -const AVOutputFormat ff_ast_muxer = { - .name = "ast", - .long_name = NULL_IF_CONFIG_SMALL("AST (Audio Stream)"), - .extensions = "ast", +const FFOutputFormat ff_ast_muxer = { + .p.name = "ast", + .p.long_name = NULL_IF_CONFIG_SMALL("AST (Audio Stream)"), + .p.extensions = "ast", .priv_data_size = sizeof(ASTMuxContext), - .audio_codec = AV_CODEC_ID_PCM_S16BE_PLANAR, - .video_codec = AV_CODEC_ID_NONE, + .p.audio_codec = AV_CODEC_ID_PCM_S16BE_PLANAR, + .p.video_codec = AV_CODEC_ID_NONE, .write_header = ast_write_header, .write_packet = ast_write_packet, .write_trailer = ast_write_trailer, - .priv_class = &ast_muxer_class, - .codec_tag = ff_ast_codec_tags_list, + .p.priv_class = &ast_muxer_class, + .p.codec_tag = ff_ast_codec_tags_list, }; diff --git a/libavformat/au.c b/libavformat/au.c index f7c47d53331..3bf21502584 100644 --- a/libavformat/au.c +++ b/libavformat/au.c @@ -33,6 +33,7 @@ #include "avformat.h" #include "internal.h" #include "avio_internal.h" +#include "mux.h" #include "pcm.h" #include "libavutil/avassert.h" @@ -331,19 +332,19 @@ static int au_write_trailer(AVFormatContext *s) return 0; } -const AVOutputFormat ff_au_muxer = { - .name = "au", - .long_name = NULL_IF_CONFIG_SMALL("Sun AU"), - .mime_type = "audio/basic", - .extensions = "au", +const FFOutputFormat ff_au_muxer = { + .p.name = "au", + .p.long_name = NULL_IF_CONFIG_SMALL("Sun AU"), + .p.mime_type = "audio/basic", + .p.extensions = "au", + .p.codec_tag = au_codec_tags, + .p.audio_codec = AV_CODEC_ID_PCM_S16BE, + .p.video_codec = AV_CODEC_ID_NONE, + .p.flags = AVFMT_NOTIMESTAMPS, .priv_data_size = sizeof(AUContext), - .audio_codec = AV_CODEC_ID_PCM_S16BE, - .video_codec = AV_CODEC_ID_NONE, .write_header = au_write_header, .write_packet = ff_raw_write_packet, .write_trailer = au_write_trailer, - .codec_tag = au_codec_tags, - .flags = AVFMT_NOTIMESTAMPS, }; #endif /* CONFIG_AU_MUXER */ diff --git a/libavformat/avformat.c b/libavformat/avformat.c index 19c72194714..88ff46a5744 100644 --- a/libavformat/avformat.c +++ b/libavformat/avformat.c @@ -35,6 +35,7 @@ #include "avformat.h" #include "avio.h" #include "demux.h" +#include "mux.h" #include "internal.h" void ff_free_stream(AVStream **pst) @@ -100,8 +101,8 @@ void avformat_free_context(AVFormatContext *s) return; si = ffformatcontext(s); - if (s->oformat && s->oformat->deinit && si->initialized) - s->oformat->deinit(s); + if (s->oformat && ffofmt(s->oformat)->deinit && si->initialized) + ffofmt(s->oformat)->deinit(s); av_opt_free(s); if (s->iformat && s->iformat->priv_class && s->priv_data) diff --git a/libavformat/avformat.h b/libavformat/avformat.h index a69ee1c575c..49e50a5120a 100644 --- a/libavformat/avformat.h +++ b/libavformat/avformat.h @@ -328,10 +328,8 @@ #endif struct AVFormatContext; -struct AVStream; struct AVDeviceInfoList; -struct AVDeviceCapabilitiesQuery; /** * @defgroup metadata_api Public Metadata API @@ -536,113 +534,6 @@ typedef struct AVOutputFormat { const AVClass *priv_class; ///< AVClass for the private context - - /***************************************************************** - * No fields below this line are part of the public API. They - * may not be used outside of libavformat and can be changed and - * removed at will. - * New public fields should be added right above. - ***************************************************************** - */ - /** - * size of private data so that it can be allocated in the wrapper - */ - int priv_data_size; - - /** - * Internal flags. See FF_FMT_FLAG_* in internal.h. - */ - int flags_internal; - - int (*write_header)(struct AVFormatContext *); - /** - * Write a packet. If AVFMT_ALLOW_FLUSH is set in flags, - * pkt can be NULL in order to flush data buffered in the muxer. - * When flushing, return 0 if there still is more data to flush, - * or 1 if everything was flushed and there is no more buffered - * data. - */ - int (*write_packet)(struct AVFormatContext *, AVPacket *pkt); - int (*write_trailer)(struct AVFormatContext *); - /** - * A format-specific function for interleavement. - * If unset, packets will be interleaved by dts. - * - * @param s An AVFormatContext for output. pkt will be added to - * resp. taken from its packet buffer. - * @param[in,out] pkt A packet to be interleaved if has_packet is set; - * also used to return packets. If no packet is returned - * (e.g. on error), pkt is blank on return. - * @param flush 1 if no further packets are available as input and - * all remaining packets should be output. - * @param has_packet If set, pkt contains a packet to be interleaved - * on input; otherwise pkt is blank on input. - * @return 1 if a packet was output, 0 if no packet could be output, - * < 0 if an error occurred - */ - int (*interleave_packet)(struct AVFormatContext *s, AVPacket *pkt, - int flush, int has_packet); - /** - * Test if the given codec can be stored in this container. - * - * @return 1 if the codec is supported, 0 if it is not. - * A negative number if unknown. - * MKTAG('A', 'P', 'I', 'C') if the codec is only supported as AV_DISPOSITION_ATTACHED_PIC - */ - int (*query_codec)(enum AVCodecID id, int std_compliance); - - void (*get_output_timestamp)(struct AVFormatContext *s, int stream, - int64_t *dts, int64_t *wall); - /** - * Allows sending messages from application to device. - */ - int (*control_message)(struct AVFormatContext *s, int type, - void *data, size_t data_size); - - /** - * Write an uncoded AVFrame. - * - * See av_write_uncoded_frame() for details. - * - * The library will free *frame afterwards, but the muxer can prevent it - * by setting the pointer to NULL. - */ - int (*write_uncoded_frame)(struct AVFormatContext *, int stream_index, - AVFrame **frame, unsigned flags); - /** - * Returns device list with it properties. - * @see avdevice_list_devices() for more details. - */ - int (*get_device_list)(struct AVFormatContext *s, struct AVDeviceInfoList *device_list); - /** - * Initialize format. May allocate data here, and set any AVFormatContext or - * AVStream parameters that need to be set before packets are sent. - * This method must not write output. - * - * Return 0 if streams were fully configured, 1 if not, negative AVERROR on failure - * - * Any allocations made here must be freed in deinit(). - */ - int (*init)(struct AVFormatContext *); - /** - * Deinitialize format. If present, this is called whenever the muxer is being - * destroyed, regardless of whether or not the header has been written. - * - * If a trailer is being written, this is called after write_trailer(). - * - * This is called if init() fails as well. - */ - void (*deinit)(struct AVFormatContext *); - /** - * 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 *s, struct AVStream *st, - const AVPacket *pkt); } AVOutputFormat; /** * @} diff --git a/libavformat/avienc.c b/libavformat/avienc.c index 14115b3e2b8..a61e5c31095 100644 --- a/libavformat/avienc.c +++ b/libavformat/avienc.c @@ -28,6 +28,7 @@ #include "config_components.h" #include "riff.h" #include "mpegts.h" +#include "mux.h" #include "rawutils.h" #include "libavformat/avlanguage.h" #include "libavutil/avstring.h" @@ -1003,19 +1004,19 @@ static const AVClass avi_muxer_class = { .version = LIBAVUTIL_VERSION_INT, }; -const AVOutputFormat ff_avi_muxer = { - .name = "avi", - .long_name = NULL_IF_CONFIG_SMALL("AVI (Audio Video Interleaved)"), - .mime_type = "video/x-msvideo", - .extensions = "avi", +const FFOutputFormat ff_avi_muxer = { + .p.name = "avi", + .p.long_name = NULL_IF_CONFIG_SMALL("AVI (Audio Video Interleaved)"), + .p.mime_type = "video/x-msvideo", + .p.extensions = "avi", .priv_data_size = sizeof(AVIContext), - .audio_codec = CONFIG_LIBMP3LAME ? AV_CODEC_ID_MP3 : AV_CODEC_ID_AC3, - .video_codec = AV_CODEC_ID_MPEG4, + .p.audio_codec = CONFIG_LIBMP3LAME ? AV_CODEC_ID_MP3 : AV_CODEC_ID_AC3, + .p.video_codec = AV_CODEC_ID_MPEG4, .init = avi_init, .deinit = avi_deinit, .write_header = avi_write_header, .write_packet = avi_write_packet, .write_trailer = avi_write_trailer, - .codec_tag = ff_riff_codec_tags_list, - .priv_class = &avi_muxer_class, + .p.codec_tag = ff_riff_codec_tags_list, + .p.priv_class = &avi_muxer_class, }; diff --git a/libavformat/bit.c b/libavformat/bit.c index 9efb4ac0708..c3b9cf4d3dc 100644 --- a/libavformat/bit.c +++ b/libavformat/bit.c @@ -23,6 +23,7 @@ #include "avformat.h" #include "internal.h" +#include "mux.h" #include "libavcodec/get_bits.h" #include "libavcodec/put_bits.h" @@ -158,13 +159,13 @@ static int write_packet(AVFormatContext *s, AVPacket *pkt) return 0; } -const AVOutputFormat ff_bit_muxer = { - .name = "bit", - .long_name = NULL_IF_CONFIG_SMALL("G.729 BIT file format"), - .mime_type = "audio/bit", - .extensions = "bit", - .audio_codec = AV_CODEC_ID_G729, - .video_codec = AV_CODEC_ID_NONE, +const FFOutputFormat ff_bit_muxer = { + .p.name = "bit", + .p.long_name = NULL_IF_CONFIG_SMALL("G.729 BIT file format"), + .p.mime_type = "audio/bit", + .p.extensions = "bit", + .p.audio_codec = AV_CODEC_ID_G729, + .p.video_codec = AV_CODEC_ID_NONE, .write_header = write_header, .write_packet = write_packet, }; diff --git a/libavformat/cafenc.c b/libavformat/cafenc.c index b8317cd5edc..67be59806c0 100644 --- a/libavformat/cafenc.c +++ b/libavformat/cafenc.c @@ -276,16 +276,16 @@ static int caf_write_trailer(AVFormatContext *s) return 0; } -const AVOutputFormat ff_caf_muxer = { - .name = "caf", - .long_name = NULL_IF_CONFIG_SMALL("Apple CAF (Core Audio Format)"), - .mime_type = "audio/x-caf", - .extensions = "caf", +const FFOutputFormat ff_caf_muxer = { + .p.name = "caf", + .p.long_name = NULL_IF_CONFIG_SMALL("Apple CAF (Core Audio Format)"), + .p.mime_type = "audio/x-caf", + .p.extensions = "caf", .priv_data_size = sizeof(CAFContext), - .audio_codec = AV_CODEC_ID_PCM_S16BE, - .video_codec = AV_CODEC_ID_NONE, + .p.audio_codec = AV_CODEC_ID_PCM_S16BE, + .p.video_codec = AV_CODEC_ID_NONE, .write_header = caf_write_header, .write_packet = caf_write_packet, .write_trailer = caf_write_trailer, - .codec_tag = ff_caf_codec_tags_list, + .p.codec_tag = ff_caf_codec_tags_list, }; diff --git a/libavformat/chromaprint.c b/libavformat/chromaprint.c index 3953a5ced30..9e5fd780c1e 100644 --- a/libavformat/chromaprint.c +++ b/libavformat/chromaprint.c @@ -21,6 +21,7 @@ #include "avformat.h" #include "internal.h" +#include "mux.h" #include "libavutil/opt.h" #include @@ -176,15 +177,15 @@ static const AVClass chromaprint_class = { .version = LIBAVUTIL_VERSION_INT, }; -const AVOutputFormat ff_chromaprint_muxer = { - .name = "chromaprint", - .long_name = NULL_IF_CONFIG_SMALL("Chromaprint"), +const FFOutputFormat ff_chromaprint_muxer = { + .p.name = "chromaprint", + .p.long_name = NULL_IF_CONFIG_SMALL("Chromaprint"), .priv_data_size = sizeof(ChromaprintMuxContext), - .audio_codec = AV_NE(AV_CODEC_ID_PCM_S16BE, AV_CODEC_ID_PCM_S16LE), + .p.audio_codec = AV_NE(AV_CODEC_ID_PCM_S16BE, AV_CODEC_ID_PCM_S16LE), .write_header = write_header, .write_packet = write_packet, .write_trailer = write_trailer, .deinit = deinit, - .flags = AVFMT_NOTIMESTAMPS, - .priv_class = &chromaprint_class, + .p.flags = AVFMT_NOTIMESTAMPS, + .p.priv_class = &chromaprint_class, }; diff --git a/libavformat/codec2.c b/libavformat/codec2.c index 400c5acbdb6..f0f7b892533 100644 --- a/libavformat/codec2.c +++ b/libavformat/codec2.c @@ -28,6 +28,7 @@ #include "avio_internal.h" #include "avformat.h" #include "internal.h" +#include "mux.h" #include "rawenc.h" #include "pcm.h" @@ -309,16 +310,16 @@ const AVInputFormat ff_codec2_demuxer = { #endif #if CONFIG_CODEC2_MUXER -const AVOutputFormat ff_codec2_muxer = { - .name = "codec2", - .long_name = NULL_IF_CONFIG_SMALL("codec2 .c2 muxer"), +const FFOutputFormat ff_codec2_muxer = { + .p.name = "codec2", + .p.long_name = NULL_IF_CONFIG_SMALL("codec2 .c2 muxer"), + .p.extensions = "c2", + .p.audio_codec = AV_CODEC_ID_CODEC2, + .p.video_codec = AV_CODEC_ID_NONE, + .p.flags = AVFMT_NOTIMESTAMPS, .priv_data_size = sizeof(Codec2Context), - .extensions = "c2", - .audio_codec = AV_CODEC_ID_CODEC2, - .video_codec = AV_CODEC_ID_NONE, .write_header = codec2_write_header, .write_packet = ff_raw_write_packet, - .flags = AVFMT_NOTIMESTAMPS, }; #endif diff --git a/libavformat/crcenc.c b/libavformat/crcenc.c index 9f40dd4ec0d..1779bdd91c0 100644 --- a/libavformat/crcenc.c +++ b/libavformat/crcenc.c @@ -23,6 +23,7 @@ #include "libavutil/adler32.h" #include "avformat.h" +#include "mux.h" typedef struct CRCState { uint32_t crcval; @@ -54,14 +55,14 @@ static int crc_write_trailer(struct AVFormatContext *s) return 0; } -const AVOutputFormat ff_crc_muxer = { - .name = "crc", - .long_name = NULL_IF_CONFIG_SMALL("CRC testing"), +const FFOutputFormat ff_crc_muxer = { + .p.name = "crc", + .p.long_name = NULL_IF_CONFIG_SMALL("CRC testing"), .priv_data_size = sizeof(CRCState), - .audio_codec = AV_CODEC_ID_PCM_S16LE, - .video_codec = AV_CODEC_ID_RAWVIDEO, + .p.audio_codec = AV_CODEC_ID_PCM_S16LE, + .p.video_codec = AV_CODEC_ID_RAWVIDEO, .init = crc_init, .write_packet = crc_write_packet, .write_trailer = crc_write_trailer, - .flags = AVFMT_NOTIMESTAMPS, + .p.flags = AVFMT_NOTIMESTAMPS, }; diff --git a/libavformat/dashenc.c b/libavformat/dashenc.c index 8e725a0d3fb..52865eacb51 100644 --- a/libavformat/dashenc.c +++ b/libavformat/dashenc.c @@ -2346,10 +2346,10 @@ static int dash_check_bitstream(AVFormatContext *s, AVStream *st, DASHContext *c = s->priv_data; OutputStream *os = &c->streams[st->index]; AVFormatContext *oc = os->ctx; - if (oc->oformat->check_bitstream) { + if (ffofmt(oc->oformat)->check_bitstream) { AVStream *const ost = oc->streams[0]; int ret; - ret = oc->oformat->check_bitstream(oc, ost, avpkt); + ret = ffofmt(oc->oformat)->check_bitstream(oc, ost, avpkt); if (ret == 1) { FFStream *const sti = ffstream(st); FFStream *const osti = ffstream(ost); @@ -2419,19 +2419,19 @@ static const AVClass dash_class = { .version = LIBAVUTIL_VERSION_INT, }; -const AVOutputFormat ff_dash_muxer = { - .name = "dash", - .long_name = NULL_IF_CONFIG_SMALL("DASH Muxer"), - .extensions = "mpd", +const FFOutputFormat ff_dash_muxer = { + .p.name = "dash", + .p.long_name = NULL_IF_CONFIG_SMALL("DASH Muxer"), + .p.extensions = "mpd", + .p.audio_codec = AV_CODEC_ID_AAC, + .p.video_codec = AV_CODEC_ID_H264, + .p.flags = AVFMT_GLOBALHEADER | AVFMT_NOFILE | AVFMT_TS_NEGATIVE, + .p.priv_class = &dash_class, .priv_data_size = sizeof(DASHContext), - .audio_codec = AV_CODEC_ID_AAC, - .video_codec = AV_CODEC_ID_H264, - .flags = AVFMT_GLOBALHEADER | AVFMT_NOFILE | AVFMT_TS_NEGATIVE, .init = dash_init, .write_header = dash_write_header, .write_packet = dash_write_packet, .write_trailer = dash_write_trailer, .deinit = dash_free, .check_bitstream = dash_check_bitstream, - .priv_class = &dash_class, }; diff --git a/libavformat/daudenc.c b/libavformat/daudenc.c index 2e252449e92..2d84b16650e 100644 --- a/libavformat/daudenc.c +++ b/libavformat/daudenc.c @@ -20,6 +20,7 @@ */ #include "avformat.h" +#include "mux.h" static int daud_init(struct AVFormatContext *s) { @@ -42,13 +43,13 @@ static int daud_write_packet(struct AVFormatContext *s, AVPacket *pkt) return 0; } -const AVOutputFormat ff_daud_muxer = { - .name = "daud", - .long_name = NULL_IF_CONFIG_SMALL("D-Cinema audio"), - .extensions = "302", - .audio_codec = AV_CODEC_ID_PCM_S24DAUD, - .video_codec = AV_CODEC_ID_NONE, +const FFOutputFormat ff_daud_muxer = { + .p.name = "daud", + .p.long_name = NULL_IF_CONFIG_SMALL("D-Cinema audio"), + .p.extensions = "302", + .p.audio_codec = AV_CODEC_ID_PCM_S24DAUD, + .p.video_codec = AV_CODEC_ID_NONE, + .p.flags = AVFMT_NOTIMESTAMPS, .init = daud_init, .write_packet = daud_write_packet, - .flags = AVFMT_NOTIMESTAMPS, }; diff --git a/libavformat/dvenc.c b/libavformat/dvenc.c index 11947aa4934..29d2dc47acf 100644 --- a/libavformat/dvenc.c +++ b/libavformat/dvenc.c @@ -442,13 +442,13 @@ static void dv_deinit(AVFormatContext *s) av_fifo_freep2(&c->audio_data[i]); } -const AVOutputFormat ff_dv_muxer = { - .name = "dv", - .long_name = NULL_IF_CONFIG_SMALL("DV (Digital Video)"), - .extensions = "dv", +const FFOutputFormat ff_dv_muxer = { + .p.name = "dv", + .p.long_name = NULL_IF_CONFIG_SMALL("DV (Digital Video)"), + .p.extensions = "dv", .priv_data_size = sizeof(DVMuxContext), - .audio_codec = AV_CODEC_ID_PCM_S16LE, - .video_codec = AV_CODEC_ID_DVVIDEO, + .p.audio_codec = AV_CODEC_ID_PCM_S16LE, + .p.video_codec = AV_CODEC_ID_DVVIDEO, .write_header = dv_write_header, .write_packet = dv_write_packet, .deinit = dv_deinit, diff --git a/libavformat/ffmetaenc.c b/libavformat/ffmetaenc.c index f27ac1ac502..ef076407b5d 100644 --- a/libavformat/ffmetaenc.c +++ b/libavformat/ffmetaenc.c @@ -23,6 +23,7 @@ #include "avformat.h" #include "ffmeta.h" +#include "mux.h" #include "libavutil/dict.h" @@ -87,12 +88,12 @@ static int write_packet(AVFormatContext *s, AVPacket *pkt) return 0; } -const AVOutputFormat ff_ffmetadata_muxer = { - .name = "ffmetadata", - .long_name = NULL_IF_CONFIG_SMALL("FFmpeg metadata in text"), - .extensions = "ffmeta", +const FFOutputFormat ff_ffmetadata_muxer = { + .p.name = "ffmetadata", + .p.long_name = NULL_IF_CONFIG_SMALL("FFmpeg metadata in text"), + .p.extensions = "ffmeta", .write_header = write_header, .write_packet = write_packet, .write_trailer = write_trailer, - .flags = AVFMT_NOTIMESTAMPS | AVFMT_NOSTREAMS, + .p.flags = AVFMT_NOTIMESTAMPS | AVFMT_NOSTREAMS, }; diff --git a/libavformat/fifo.c b/libavformat/fifo.c index c125a97b0dd..ebadeef645d 100644 --- a/libavformat/fifo.c +++ b/libavformat/fifo.c @@ -707,15 +707,15 @@ static const AVClass fifo_muxer_class = { .version = LIBAVUTIL_VERSION_INT, }; -const AVOutputFormat ff_fifo_muxer = { - .name = "fifo", - .long_name = NULL_IF_CONFIG_SMALL("FIFO queue pseudo-muxer"), +const FFOutputFormat ff_fifo_muxer = { + .p.name = "fifo", + .p.long_name = NULL_IF_CONFIG_SMALL("FIFO queue pseudo-muxer"), + .p.priv_class = &fifo_muxer_class, + .p.flags = AVFMT_NOFILE | AVFMT_ALLOW_FLUSH | AVFMT_TS_NEGATIVE, .priv_data_size = sizeof(FifoContext), .init = fifo_init, .write_header = fifo_write_header, .write_packet = fifo_write_packet, .write_trailer = fifo_write_trailer, .deinit = fifo_deinit, - .priv_class = &fifo_muxer_class, - .flags = AVFMT_NOFILE | AVFMT_ALLOW_FLUSH | AVFMT_TS_NEGATIVE, }; diff --git a/libavformat/fifo_test.c b/libavformat/fifo_test.c index 80c0c846129..0f12d88b0fd 100644 --- a/libavformat/fifo_test.c +++ b/libavformat/fifo_test.c @@ -25,6 +25,7 @@ #include "libavutil/time.h" #include "avformat.h" +#include "mux.h" #include "url.h" /* Implementation of mock muxer to simulate real muxer failures */ @@ -137,15 +138,15 @@ static const AVClass failing_muxer_class = { .version = LIBAVUTIL_VERSION_INT, }; -const AVOutputFormat ff_fifo_test_muxer = { - .name = "fifo_test", - .long_name = NULL_IF_CONFIG_SMALL("Fifo test muxer"), +const FFOutputFormat ff_fifo_test_muxer = { + .p.name = "fifo_test", + .p.long_name = NULL_IF_CONFIG_SMALL("Fifo test muxer"), .priv_data_size = sizeof(FailingMuxerContext), .write_header = failing_write_header, .write_packet = failing_write_packet, .write_trailer = failing_write_trailer, .deinit = failing_deinit, - .priv_class = &failing_muxer_class, - .flags = AVFMT_NOFILE | AVFMT_ALLOW_FLUSH, + .p.priv_class = &failing_muxer_class, + .p.flags = AVFMT_NOFILE | AVFMT_ALLOW_FLUSH, }; diff --git a/libavformat/filmstripenc.c b/libavformat/filmstripenc.c index ebb7294175f..9033dba6925 100644 --- a/libavformat/filmstripenc.c +++ b/libavformat/filmstripenc.c @@ -27,6 +27,7 @@ #include "libavutil/intreadwrite.h" #include "avformat.h" #include "avio_internal.h" +#include "mux.h" #include "rawenc.h" #define RAND_TAG MKBETAG('R','a','n','d') @@ -59,12 +60,12 @@ static int write_trailer(AVFormatContext *s) return 0; } -const AVOutputFormat ff_filmstrip_muxer = { - .name = "filmstrip", - .long_name = NULL_IF_CONFIG_SMALL("Adobe Filmstrip"), - .extensions = "flm", - .audio_codec = AV_CODEC_ID_NONE, - .video_codec = AV_CODEC_ID_RAWVIDEO, +const FFOutputFormat ff_filmstrip_muxer = { + .p.name = "filmstrip", + .p.long_name = NULL_IF_CONFIG_SMALL("Adobe Filmstrip"), + .p.extensions = "flm", + .p.audio_codec = AV_CODEC_ID_NONE, + .p.video_codec = AV_CODEC_ID_RAWVIDEO, .write_header = write_header, .write_packet = ff_raw_write_packet, .write_trailer = write_trailer, diff --git a/libavformat/fitsenc.c b/libavformat/fitsenc.c index 37ee10bb139..1df7e2bcf2b 100644 --- a/libavformat/fitsenc.c +++ b/libavformat/fitsenc.c @@ -26,6 +26,7 @@ #include "avio_internal.h" #include "internal.h" +#include "mux.h" typedef struct FITSContext { int first_image; @@ -191,13 +192,13 @@ static int fits_write_packet(AVFormatContext *s, AVPacket *pkt) return 0; } -const AVOutputFormat ff_fits_muxer = { - .name = "fits", - .long_name = NULL_IF_CONFIG_SMALL("Flexible Image Transport System"), - .extensions = "fits", +const FFOutputFormat ff_fits_muxer = { + .p.name = "fits", + .p.long_name = NULL_IF_CONFIG_SMALL("Flexible Image Transport System"), + .p.extensions = "fits", + .p.audio_codec = AV_CODEC_ID_NONE, + .p.video_codec = AV_CODEC_ID_FITS, .priv_data_size = sizeof(FITSContext), - .audio_codec = AV_CODEC_ID_NONE, - .video_codec = AV_CODEC_ID_FITS, .write_header = fits_write_header, .write_packet = fits_write_packet, }; diff --git a/libavformat/flacenc.c b/libavformat/flacenc.c index d7930f4a6e2..a8beec7750b 100644 --- a/libavformat/flacenc.c +++ b/libavformat/flacenc.c @@ -30,6 +30,7 @@ #include "flacenc.h" #include "id3v2.h" #include "internal.h" +#include "mux.h" #include "version.h" #include "vorbiscomment.h" @@ -413,19 +414,19 @@ static const AVClass flac_muxer_class = { .version = LIBAVUTIL_VERSION_INT, }; -const AVOutputFormat ff_flac_muxer = { - .name = "flac", - .long_name = NULL_IF_CONFIG_SMALL("raw FLAC"), +const FFOutputFormat ff_flac_muxer = { + .p.name = "flac", + .p.long_name = NULL_IF_CONFIG_SMALL("raw FLAC"), .priv_data_size = sizeof(FlacMuxerContext), - .mime_type = "audio/x-flac", - .extensions = "flac", - .audio_codec = AV_CODEC_ID_FLAC, - .video_codec = AV_CODEC_ID_PNG, + .p.mime_type = "audio/x-flac", + .p.extensions = "flac", + .p.audio_codec = AV_CODEC_ID_FLAC, + .p.video_codec = AV_CODEC_ID_PNG, .init = flac_init, .write_header = flac_write_header, .write_packet = flac_write_packet, .write_trailer = flac_write_trailer, .deinit = flac_deinit, - .flags = AVFMT_NOTIMESTAMPS, - .priv_class = &flac_muxer_class, + .p.flags = AVFMT_NOTIMESTAMPS, + .p.priv_class = &flac_muxer_class, }; diff --git a/libavformat/flvenc.c b/libavformat/flvenc.c index 128ae8ebc0e..81d9b6100da 100644 --- a/libavformat/flvenc.c +++ b/libavformat/flvenc.c @@ -1060,24 +1060,24 @@ static const AVClass flv_muxer_class = { .version = LIBAVUTIL_VERSION_INT, }; -const AVOutputFormat ff_flv_muxer = { - .name = "flv", - .long_name = NULL_IF_CONFIG_SMALL("FLV (Flash Video)"), - .mime_type = "video/x-flv", - .extensions = "flv", +const FFOutputFormat ff_flv_muxer = { + .p.name = "flv", + .p.long_name = NULL_IF_CONFIG_SMALL("FLV (Flash Video)"), + .p.mime_type = "video/x-flv", + .p.extensions = "flv", .priv_data_size = sizeof(FLVContext), - .audio_codec = CONFIG_LIBMP3LAME ? AV_CODEC_ID_MP3 : AV_CODEC_ID_ADPCM_SWF, - .video_codec = AV_CODEC_ID_FLV1, + .p.audio_codec = CONFIG_LIBMP3LAME ? AV_CODEC_ID_MP3 : AV_CODEC_ID_ADPCM_SWF, + .p.video_codec = AV_CODEC_ID_FLV1, .init = flv_init, .write_header = flv_write_header, .write_packet = flv_write_packet, .write_trailer = flv_write_trailer, .deinit = flv_deinit, .check_bitstream= flv_check_bitstream, - .codec_tag = (const AVCodecTag* const []) { + .p.codec_tag = (const AVCodecTag* const []) { flv_video_codec_ids, flv_audio_codec_ids, 0 }, - .flags = AVFMT_GLOBALHEADER | AVFMT_VARIABLE_FPS | + .p.flags = AVFMT_GLOBALHEADER | AVFMT_VARIABLE_FPS | AVFMT_TS_NONSTRICT, - .priv_class = &flv_muxer_class, + .p.priv_class = &flv_muxer_class, }; diff --git a/libavformat/framecrcenc.c b/libavformat/framecrcenc.c index ab79903e318..ce306a6c498 100644 --- a/libavformat/framecrcenc.c +++ b/libavformat/framecrcenc.c @@ -30,6 +30,7 @@ #include "avformat.h" #include "internal.h" +#include "mux.h" static int framecrc_write_header(struct AVFormatContext *s) { @@ -69,13 +70,13 @@ static int framecrc_write_packet(struct AVFormatContext *s, AVPacket *pkt) return 0; } -const AVOutputFormat ff_framecrc_muxer = { - .name = "framecrc", - .long_name = NULL_IF_CONFIG_SMALL("framecrc testing"), - .audio_codec = AV_CODEC_ID_PCM_S16LE, - .video_codec = AV_CODEC_ID_RAWVIDEO, +const FFOutputFormat ff_framecrc_muxer = { + .p.name = "framecrc", + .p.long_name = NULL_IF_CONFIG_SMALL("framecrc testing"), + .p.audio_codec = AV_CODEC_ID_PCM_S16LE, + .p.video_codec = AV_CODEC_ID_RAWVIDEO, .write_header = framecrc_write_header, .write_packet = framecrc_write_packet, - .flags = AVFMT_VARIABLE_FPS | AVFMT_TS_NONSTRICT | + .p.flags = AVFMT_VARIABLE_FPS | AVFMT_TS_NONSTRICT | AVFMT_TS_NEGATIVE, }; diff --git a/libavformat/gif.c b/libavformat/gif.c index b52ff4dd395..bfa7deb598c 100644 --- a/libavformat/gif.c +++ b/libavformat/gif.c @@ -23,6 +23,7 @@ #include "avformat.h" #include "internal.h" +#include "mux.h" #include "libavutil/imgutils.h" #include "libavutil/log.h" #include "libavutil/opt.h" @@ -202,17 +203,17 @@ static const AVClass gif_muxer_class = { .option = options, }; -const AVOutputFormat ff_gif_muxer = { - .name = "gif", - .long_name = NULL_IF_CONFIG_SMALL("CompuServe Graphics Interchange Format (GIF)"), - .mime_type = "image/gif", - .extensions = "gif", +const FFOutputFormat ff_gif_muxer = { + .p.name = "gif", + .p.long_name = NULL_IF_CONFIG_SMALL("CompuServe Graphics Interchange Format (GIF)"), + .p.mime_type = "image/gif", + .p.extensions = "gif", .priv_data_size = sizeof(GIFContext), - .audio_codec = AV_CODEC_ID_NONE, - .video_codec = AV_CODEC_ID_GIF, + .p.audio_codec = AV_CODEC_ID_NONE, + .p.video_codec = AV_CODEC_ID_GIF, .write_header = gif_write_header, .write_packet = gif_write_packet, .write_trailer = gif_write_trailer, - .priv_class = &gif_muxer_class, - .flags = AVFMT_VARIABLE_FPS, + .p.priv_class = &gif_muxer_class, + .p.flags = AVFMT_VARIABLE_FPS, }; diff --git a/libavformat/gxfenc.c b/libavformat/gxfenc.c index 0f971c039a4..74959247229 100644 --- a/libavformat/gxfenc.c +++ b/libavformat/gxfenc.c @@ -1009,13 +1009,13 @@ static int gxf_interleave_packet(AVFormatContext *s, AVPacket *pkt, return ff_interleave_packet_per_dts(s, pkt, flush, 0); } -const AVOutputFormat ff_gxf_muxer = { - .name = "gxf", - .long_name = NULL_IF_CONFIG_SMALL("GXF (General eXchange Format)"), - .extensions = "gxf", +const FFOutputFormat ff_gxf_muxer = { + .p.name = "gxf", + .p.long_name = NULL_IF_CONFIG_SMALL("GXF (General eXchange Format)"), + .p.extensions = "gxf", .priv_data_size = sizeof(GXFContext), - .audio_codec = AV_CODEC_ID_PCM_S16LE, - .video_codec = AV_CODEC_ID_MPEG2VIDEO, + .p.audio_codec = AV_CODEC_ID_PCM_S16LE, + .p.video_codec = AV_CODEC_ID_MPEG2VIDEO, .write_header = gxf_write_header, .write_packet = gxf_write_packet, .write_trailer = gxf_write_trailer, diff --git a/libavformat/hashenc.c b/libavformat/hashenc.c index 1aaba0b306e..17ee2f7e9fb 100644 --- a/libavformat/hashenc.c +++ b/libavformat/hashenc.c @@ -27,6 +27,7 @@ #include "libavutil/opt.h" #include "avformat.h" #include "internal.h" +#include "mux.h" struct HashContext { const AVClass *avclass; @@ -172,19 +173,19 @@ static void hash_free(struct AVFormatContext *s) } #if CONFIG_HASH_MUXER -const AVOutputFormat ff_hash_muxer = { - .name = "hash", - .long_name = NULL_IF_CONFIG_SMALL("Hash testing"), +const FFOutputFormat ff_hash_muxer = { + .p.name = "hash", + .p.long_name = NULL_IF_CONFIG_SMALL("Hash testing"), .priv_data_size = sizeof(struct HashContext), - .audio_codec = AV_CODEC_ID_PCM_S16LE, - .video_codec = AV_CODEC_ID_RAWVIDEO, + .p.audio_codec = AV_CODEC_ID_PCM_S16LE, + .p.video_codec = AV_CODEC_ID_RAWVIDEO, .init = hash_init, .write_packet = hash_write_packet, .write_trailer = hash_write_trailer, .deinit = hash_free, - .flags = AVFMT_VARIABLE_FPS | AVFMT_TS_NONSTRICT | + .p.flags = AVFMT_VARIABLE_FPS | AVFMT_TS_NONSTRICT | AVFMT_TS_NEGATIVE, - .priv_class = &hash_streamhashenc_class, + .p.priv_class = &hash_streamhashenc_class, }; #endif @@ -196,36 +197,36 @@ static const AVClass md5enc_class = { .version = LIBAVUTIL_VERSION_INT, }; -const AVOutputFormat ff_md5_muxer = { - .name = "md5", - .long_name = NULL_IF_CONFIG_SMALL("MD5 testing"), +const FFOutputFormat ff_md5_muxer = { + .p.name = "md5", + .p.long_name = NULL_IF_CONFIG_SMALL("MD5 testing"), .priv_data_size = sizeof(struct HashContext), - .audio_codec = AV_CODEC_ID_PCM_S16LE, - .video_codec = AV_CODEC_ID_RAWVIDEO, + .p.audio_codec = AV_CODEC_ID_PCM_S16LE, + .p.video_codec = AV_CODEC_ID_RAWVIDEO, .init = hash_init, .write_packet = hash_write_packet, .write_trailer = hash_write_trailer, .deinit = hash_free, - .flags = AVFMT_VARIABLE_FPS | AVFMT_TS_NONSTRICT | + .p.flags = AVFMT_VARIABLE_FPS | AVFMT_TS_NONSTRICT | AVFMT_TS_NEGATIVE, - .priv_class = &md5enc_class, + .p.priv_class = &md5enc_class, }; #endif #if CONFIG_STREAMHASH_MUXER -const AVOutputFormat ff_streamhash_muxer = { - .name = "streamhash", - .long_name = NULL_IF_CONFIG_SMALL("Per-stream hash testing"), +const FFOutputFormat ff_streamhash_muxer = { + .p.name = "streamhash", + .p.long_name = NULL_IF_CONFIG_SMALL("Per-stream hash testing"), .priv_data_size = sizeof(struct HashContext), - .audio_codec = AV_CODEC_ID_PCM_S16LE, - .video_codec = AV_CODEC_ID_RAWVIDEO, + .p.audio_codec = AV_CODEC_ID_PCM_S16LE, + .p.video_codec = AV_CODEC_ID_RAWVIDEO, .init = streamhash_init, .write_packet = hash_write_packet, .write_trailer = hash_write_trailer, .deinit = hash_free, - .flags = AVFMT_VARIABLE_FPS | AVFMT_TS_NONSTRICT | + .p.flags = AVFMT_VARIABLE_FPS | AVFMT_TS_NONSTRICT | AVFMT_TS_NEGATIVE, - .priv_class = &hash_streamhashenc_class, + .p.priv_class = &hash_streamhashenc_class, }; #endif @@ -324,19 +325,19 @@ static const AVClass framehash_class = { .version = LIBAVUTIL_VERSION_INT, }; -const AVOutputFormat ff_framehash_muxer = { - .name = "framehash", - .long_name = NULL_IF_CONFIG_SMALL("Per-frame hash testing"), +const FFOutputFormat ff_framehash_muxer = { + .p.name = "framehash", + .p.long_name = NULL_IF_CONFIG_SMALL("Per-frame hash testing"), .priv_data_size = sizeof(struct HashContext), - .audio_codec = AV_CODEC_ID_PCM_S16LE, - .video_codec = AV_CODEC_ID_RAWVIDEO, + .p.audio_codec = AV_CODEC_ID_PCM_S16LE, + .p.video_codec = AV_CODEC_ID_RAWVIDEO, .init = framehash_init, .write_header = framehash_write_header, .write_packet = framehash_write_packet, .deinit = hash_free, - .flags = AVFMT_VARIABLE_FPS | AVFMT_TS_NONSTRICT | + .p.flags = AVFMT_VARIABLE_FPS | AVFMT_TS_NONSTRICT | AVFMT_TS_NEGATIVE, - .priv_class = &framehash_class, + .p.priv_class = &framehash_class, }; #endif @@ -348,18 +349,18 @@ static const AVClass framemd5_class = { .version = LIBAVUTIL_VERSION_INT, }; -const AVOutputFormat ff_framemd5_muxer = { - .name = "framemd5", - .long_name = NULL_IF_CONFIG_SMALL("Per-frame MD5 testing"), +const FFOutputFormat ff_framemd5_muxer = { + .p.name = "framemd5", + .p.long_name = NULL_IF_CONFIG_SMALL("Per-frame MD5 testing"), .priv_data_size = sizeof(struct HashContext), - .audio_codec = AV_CODEC_ID_PCM_S16LE, - .video_codec = AV_CODEC_ID_RAWVIDEO, + .p.audio_codec = AV_CODEC_ID_PCM_S16LE, + .p.video_codec = AV_CODEC_ID_RAWVIDEO, .init = framehash_init, .write_header = framehash_write_header, .write_packet = framehash_write_packet, .deinit = hash_free, - .flags = AVFMT_VARIABLE_FPS | AVFMT_TS_NONSTRICT | + .p.flags = AVFMT_VARIABLE_FPS | AVFMT_TS_NONSTRICT | AVFMT_TS_NEGATIVE, - .priv_class = &framemd5_class, + .p.priv_class = &framemd5_class, }; #endif diff --git a/libavformat/hdsenc.c b/libavformat/hdsenc.c index a8f340ac460..080a873ee8a 100644 --- a/libavformat/hdsenc.c +++ b/libavformat/hdsenc.c @@ -564,16 +564,16 @@ static const AVClass hds_class = { .version = LIBAVUTIL_VERSION_INT, }; -const AVOutputFormat ff_hds_muxer = { - .name = "hds", - .long_name = NULL_IF_CONFIG_SMALL("HDS Muxer"), +const FFOutputFormat ff_hds_muxer = { + .p.name = "hds", + .p.long_name = NULL_IF_CONFIG_SMALL("HDS Muxer"), + .p.audio_codec = AV_CODEC_ID_AAC, + .p.video_codec = AV_CODEC_ID_H264, + .p.flags = AVFMT_GLOBALHEADER | AVFMT_NOFILE, + .p.priv_class = &hds_class, .priv_data_size = sizeof(HDSContext), - .audio_codec = AV_CODEC_ID_AAC, - .video_codec = AV_CODEC_ID_H264, - .flags = AVFMT_GLOBALHEADER | AVFMT_NOFILE, .write_header = hds_write_header, .write_packet = hds_write_packet, .write_trailer = hds_write_trailer, .deinit = hds_free, - .priv_class = &hds_class, }; diff --git a/libavformat/hlsenc.c b/libavformat/hlsenc.c index 39df9becc7a..adf06ec7643 100644 --- a/libavformat/hlsenc.c +++ b/libavformat/hlsenc.c @@ -3183,19 +3183,19 @@ static const AVClass hls_class = { }; -const AVOutputFormat ff_hls_muxer = { - .name = "hls", - .long_name = NULL_IF_CONFIG_SMALL("Apple HTTP Live Streaming"), - .extensions = "m3u8", +const FFOutputFormat ff_hls_muxer = { + .p.name = "hls", + .p.long_name = NULL_IF_CONFIG_SMALL("Apple HTTP Live Streaming"), + .p.extensions = "m3u8", + .p.audio_codec = AV_CODEC_ID_AAC, + .p.video_codec = AV_CODEC_ID_H264, + .p.subtitle_codec = AV_CODEC_ID_WEBVTT, + .p.flags = AVFMT_NOFILE | AVFMT_GLOBALHEADER | AVFMT_ALLOW_FLUSH | AVFMT_NODIMENSIONS, + .p.priv_class = &hls_class, .priv_data_size = sizeof(HLSContext), - .audio_codec = AV_CODEC_ID_AAC, - .video_codec = AV_CODEC_ID_H264, - .subtitle_codec = AV_CODEC_ID_WEBVTT, - .flags = AVFMT_NOFILE | AVFMT_GLOBALHEADER | AVFMT_ALLOW_FLUSH | AVFMT_NODIMENSIONS, .init = hls_init, .write_header = hls_write_header, .write_packet = hls_write_packet, .write_trailer = hls_write_trailer, .deinit = hls_deinit, - .priv_class = &hls_class, }; diff --git a/libavformat/icoenc.c b/libavformat/icoenc.c index d684f677072..caa3ba4965a 100644 --- a/libavformat/icoenc.c +++ b/libavformat/icoenc.c @@ -31,6 +31,7 @@ #include "avformat.h" #include "avio_internal.h" +#include "mux.h" typedef struct { int offset; @@ -193,17 +194,17 @@ static void ico_deinit(AVFormatContext *s) av_freep(&ico->images); } -const AVOutputFormat ff_ico_muxer = { - .name = "ico", - .long_name = NULL_IF_CONFIG_SMALL("Microsoft Windows ICO"), +const FFOutputFormat ff_ico_muxer = { + .p.name = "ico", + .p.long_name = NULL_IF_CONFIG_SMALL("Microsoft Windows ICO"), .priv_data_size = sizeof(IcoMuxContext), - .mime_type = "image/vnd.microsoft.icon", - .extensions = "ico", - .audio_codec = AV_CODEC_ID_NONE, - .video_codec = AV_CODEC_ID_BMP, + .p.mime_type = "image/vnd.microsoft.icon", + .p.extensions = "ico", + .p.audio_codec = AV_CODEC_ID_NONE, + .p.video_codec = AV_CODEC_ID_BMP, .write_header = ico_write_header, .write_packet = ico_write_packet, .write_trailer = ico_write_trailer, .deinit = ico_deinit, - .flags = AVFMT_NOTIMESTAMPS, + .p.flags = AVFMT_NOTIMESTAMPS, }; diff --git a/libavformat/idroqenc.c b/libavformat/idroqenc.c index 57dd7f024ef..9baf9ad1b1b 100644 --- a/libavformat/idroqenc.c +++ b/libavformat/idroqenc.c @@ -20,6 +20,7 @@ */ #include "avformat.h" +#include "mux.h" #include "rawenc.h" @@ -59,12 +60,12 @@ static int roq_write_header(struct AVFormatContext *s) return 0; } -const AVOutputFormat ff_roq_muxer = { - .name = "roq", - .long_name = NULL_IF_CONFIG_SMALL("raw id RoQ"), - .extensions = "roq", - .audio_codec = AV_CODEC_ID_ROQ_DPCM, - .video_codec = AV_CODEC_ID_ROQ, +const FFOutputFormat ff_roq_muxer = { + .p.name = "roq", + .p.long_name = NULL_IF_CONFIG_SMALL("raw id RoQ"), + .p.extensions = "roq", + .p.audio_codec = AV_CODEC_ID_ROQ_DPCM, + .p.video_codec = AV_CODEC_ID_ROQ, .write_header = roq_write_header, .write_packet = ff_raw_write_packet, }; diff --git a/libavformat/ilbc.c b/libavformat/ilbc.c index 26336ef2ac3..6b5bb33b620 100644 --- a/libavformat/ilbc.c +++ b/libavformat/ilbc.c @@ -23,6 +23,7 @@ #include "avformat.h" #include "internal.h" +#include "mux.h" #include "rawenc.h" static const char mode20_header[] = "#!iLBC20\n"; @@ -120,14 +121,14 @@ const AVInputFormat ff_ilbc_demuxer = { }; #if CONFIG_ILBC_MUXER -const AVOutputFormat ff_ilbc_muxer = { - .name = "ilbc", - .long_name = NULL_IF_CONFIG_SMALL("iLBC storage"), - .mime_type = "audio/iLBC", - .extensions = "lbc", - .audio_codec = AV_CODEC_ID_ILBC, +const FFOutputFormat ff_ilbc_muxer = { + .p.name = "ilbc", + .p.long_name = NULL_IF_CONFIG_SMALL("iLBC storage"), + .p.mime_type = "audio/iLBC", + .p.extensions = "lbc", + .p.audio_codec = AV_CODEC_ID_ILBC, + .p.flags = AVFMT_NOTIMESTAMPS, .write_header = ilbc_write_header, .write_packet = ff_raw_write_packet, - .flags = AVFMT_NOTIMESTAMPS, }; #endif diff --git a/libavformat/img2enc.c b/libavformat/img2enc.c index c05f37e22b3..9b8ec06cea1 100644 --- a/libavformat/img2enc.c +++ b/libavformat/img2enc.c @@ -33,6 +33,7 @@ #include "avio_internal.h" #include "internal.h" #include "img2.h" +#include "mux.h" typedef struct VideoMuxData { const AVClass *class; /**< Class for private options. */ @@ -268,30 +269,30 @@ static const AVClass img2mux_class = { .version = LIBAVUTIL_VERSION_INT, }; -const AVOutputFormat ff_image2_muxer = { - .name = "image2", - .long_name = NULL_IF_CONFIG_SMALL("image2 sequence"), - .extensions = "bmp,dpx,exr,jls,jpeg,jpg,jxl,ljpg,pam,pbm,pcx,pfm,pgm,pgmyuv,phm," +const FFOutputFormat ff_image2_muxer = { + .p.name = "image2", + .p.long_name = NULL_IF_CONFIG_SMALL("image2 sequence"), + .p.extensions = "bmp,dpx,exr,jls,jpeg,jpg,jxl,ljpg,pam,pbm,pcx,pfm,pgm,pgmyuv,phm," "png,ppm,sgi,tga,tif,tiff,jp2,j2c,j2k,xwd,sun,ras,rs,im1,im8," "im24,sunras,vbn,xbm,xface,pix,y,avif,qoi,hdr,wbmp", .priv_data_size = sizeof(VideoMuxData), - .video_codec = AV_CODEC_ID_MJPEG, + .p.video_codec = AV_CODEC_ID_MJPEG, .write_header = write_header, .write_packet = write_packet, .query_codec = query_codec, - .flags = AVFMT_NOTIMESTAMPS | AVFMT_NODIMENSIONS | AVFMT_NOFILE, - .priv_class = &img2mux_class, + .p.flags = AVFMT_NOTIMESTAMPS | AVFMT_NODIMENSIONS | AVFMT_NOFILE, + .p.priv_class = &img2mux_class, }; #endif #if CONFIG_IMAGE2PIPE_MUXER -const AVOutputFormat ff_image2pipe_muxer = { - .name = "image2pipe", - .long_name = NULL_IF_CONFIG_SMALL("piped image2 sequence"), +const FFOutputFormat ff_image2pipe_muxer = { + .p.name = "image2pipe", + .p.long_name = NULL_IF_CONFIG_SMALL("piped image2 sequence"), .priv_data_size = sizeof(VideoMuxData), - .video_codec = AV_CODEC_ID_MJPEG, + .p.video_codec = AV_CODEC_ID_MJPEG, .write_header = write_header, .write_packet = write_packet_pipe, .query_codec = query_codec, - .flags = AVFMT_NOTIMESTAMPS | AVFMT_NODIMENSIONS + .p.flags = AVFMT_NOTIMESTAMPS | AVFMT_NODIMENSIONS }; #endif diff --git a/libavformat/internal.h b/libavformat/internal.h index ce837fefc76..f575064e8fb 100644 --- a/libavformat/internal.h +++ b/libavformat/internal.h @@ -705,6 +705,7 @@ int ff_unlock_avformat(void); */ void ff_format_set_url(AVFormatContext *s, char *url); -void avpriv_register_devices(const AVOutputFormat * const o[], const AVInputFormat * const i[]); +struct FFOutputFormat; +void avpriv_register_devices(const struct FFOutputFormat * const o[], const AVInputFormat * const i[]); #endif /* AVFORMAT_INTERNAL_H */ diff --git a/libavformat/ircamenc.c b/libavformat/ircamenc.c index df1494b2b8d..ceeab2b305b 100644 --- a/libavformat/ircamenc.c +++ b/libavformat/ircamenc.c @@ -23,6 +23,7 @@ #include "avformat.h" #include "avio_internal.h" #include "internal.h" +#include "mux.h" #include "rawenc.h" #include "ircam.h" @@ -50,13 +51,13 @@ static int ircam_write_header(AVFormatContext *s) return 0; } -const AVOutputFormat ff_ircam_muxer = { - .name = "ircam", - .extensions = "sf,ircam", - .long_name = NULL_IF_CONFIG_SMALL("Berkeley/IRCAM/CARL Sound Format"), - .audio_codec = AV_CODEC_ID_PCM_S16LE, - .video_codec = AV_CODEC_ID_NONE, +const FFOutputFormat ff_ircam_muxer = { + .p.name = "ircam", + .p.extensions = "sf,ircam", + .p.long_name = NULL_IF_CONFIG_SMALL("Berkeley/IRCAM/CARL Sound Format"), + .p.audio_codec = AV_CODEC_ID_PCM_S16LE, + .p.video_codec = AV_CODEC_ID_NONE, .write_header = ircam_write_header, .write_packet = ff_raw_write_packet, - .codec_tag = (const AVCodecTag *const []){ ff_codec_ircam_le_tags, 0 }, + .p.codec_tag = (const AVCodecTag *const []){ ff_codec_ircam_le_tags, 0 }, }; diff --git a/libavformat/ivfenc.c b/libavformat/ivfenc.c index ed5ec90ce94..47b4efbcd10 100644 --- a/libavformat/ivfenc.c +++ b/libavformat/ivfenc.c @@ -122,16 +122,16 @@ static const AVCodecTag codec_ivf_tags[] = { { AV_CODEC_ID_NONE, 0 } }; -const AVOutputFormat ff_ivf_muxer = { +const FFOutputFormat ff_ivf_muxer = { + .p.name = "ivf", + .p.long_name = NULL_IF_CONFIG_SMALL("On2 IVF"), + .p.extensions = "ivf", + .p.audio_codec = AV_CODEC_ID_NONE, + .p.video_codec = AV_CODEC_ID_VP8, + .p.codec_tag = (const AVCodecTag* const []){ codec_ivf_tags, 0 }, .priv_data_size = sizeof(IVFEncContext), - .name = "ivf", - .long_name = NULL_IF_CONFIG_SMALL("On2 IVF"), - .extensions = "ivf", - .audio_codec = AV_CODEC_ID_NONE, - .video_codec = AV_CODEC_ID_VP8, .init = ivf_init, .write_header = ivf_write_header, .write_packet = ivf_write_packet, .write_trailer = ivf_write_trailer, - .codec_tag = (const AVCodecTag* const []){ codec_ivf_tags, 0 }, }; diff --git a/libavformat/jacosubenc.c b/libavformat/jacosubenc.c index f0548bb2820..fa0f9fdaa2a 100644 --- a/libavformat/jacosubenc.c +++ b/libavformat/jacosubenc.c @@ -17,6 +17,7 @@ */ #include "avformat.h" +#include "mux.h" #include "rawenc.h" static int jacosub_write_header(AVFormatContext *s) @@ -29,13 +30,13 @@ static int jacosub_write_header(AVFormatContext *s) return 0; } -const AVOutputFormat ff_jacosub_muxer = { - .name = "jacosub", - .long_name = NULL_IF_CONFIG_SMALL("JACOsub subtitle format"), - .mime_type = "text/x-jacosub", - .extensions = "jss,js", +const FFOutputFormat ff_jacosub_muxer = { + .p.name = "jacosub", + .p.long_name = NULL_IF_CONFIG_SMALL("JACOsub subtitle format"), + .p.mime_type = "text/x-jacosub", + .p.extensions = "jss,js", + .p.flags = AVFMT_TS_NONSTRICT, + .p.subtitle_codec = AV_CODEC_ID_JACOSUB, .write_header = jacosub_write_header, .write_packet = ff_raw_write_packet, - .flags = AVFMT_TS_NONSTRICT, - .subtitle_codec = AV_CODEC_ID_JACOSUB, }; diff --git a/libavformat/kvag.c b/libavformat/kvag.c index 7c3816ab828..9487e7dd0eb 100644 --- a/libavformat/kvag.c +++ b/libavformat/kvag.c @@ -26,6 +26,7 @@ #include "avformat.h" #include "avio_internal.h" #include "internal.h" +#include "mux.h" #include "rawenc.h" #include "libavutil/intreadwrite.h" @@ -188,12 +189,12 @@ static int kvag_write_trailer(AVFormatContext *s) return 0; } -const AVOutputFormat ff_kvag_muxer = { - .name = "kvag", - .long_name = NULL_IF_CONFIG_SMALL("Simon & Schuster Interactive VAG"), - .extensions = "vag", - .audio_codec = AV_CODEC_ID_ADPCM_IMA_SSI, - .video_codec = AV_CODEC_ID_NONE, +const FFOutputFormat ff_kvag_muxer = { + .p.name = "kvag", + .p.long_name = NULL_IF_CONFIG_SMALL("Simon & Schuster Interactive VAG"), + .p.extensions = "vag", + .p.audio_codec = AV_CODEC_ID_ADPCM_IMA_SSI, + .p.video_codec = AV_CODEC_ID_NONE, .init = kvag_write_init, .write_header = kvag_write_header, .write_packet = ff_raw_write_packet, diff --git a/libavformat/latmenc.c b/libavformat/latmenc.c index 6fd36d1484f..8eec632c546 100644 --- a/libavformat/latmenc.c +++ b/libavformat/latmenc.c @@ -260,17 +260,17 @@ static int latm_check_bitstream(AVFormatContext *s, AVStream *st, return ret; } -const AVOutputFormat ff_latm_muxer = { - .name = "latm", - .long_name = NULL_IF_CONFIG_SMALL("LOAS/LATM"), - .mime_type = "audio/MP4A-LATM", - .extensions = "latm,loas", +const FFOutputFormat ff_latm_muxer = { + .p.name = "latm", + .p.long_name = NULL_IF_CONFIG_SMALL("LOAS/LATM"), + .p.mime_type = "audio/MP4A-LATM", + .p.extensions = "latm,loas", .priv_data_size = sizeof(LATMContext), - .audio_codec = AV_CODEC_ID_AAC, - .video_codec = AV_CODEC_ID_NONE, + .p.audio_codec = AV_CODEC_ID_AAC, + .p.video_codec = AV_CODEC_ID_NONE, .write_header = latm_write_header, .write_packet = latm_write_packet, - .priv_class = &latm_muxer_class, + .p.priv_class = &latm_muxer_class, .check_bitstream= latm_check_bitstream, - .flags = AVFMT_NOTIMESTAMPS, + .p.flags = AVFMT_NOTIMESTAMPS, }; diff --git a/libavformat/lrcenc.c b/libavformat/lrcenc.c index 2d6ca33e380..d66be9a8faa 100644 --- a/libavformat/lrcenc.c +++ b/libavformat/lrcenc.c @@ -125,14 +125,14 @@ static int lrc_write_packet(AVFormatContext *s, AVPacket *pkt) return 0; } -const AVOutputFormat ff_lrc_muxer = { - .name = "lrc", - .long_name = NULL_IF_CONFIG_SMALL("LRC lyrics"), - .extensions = "lrc", +const FFOutputFormat ff_lrc_muxer = { + .p.name = "lrc", + .p.long_name = NULL_IF_CONFIG_SMALL("LRC lyrics"), + .p.extensions = "lrc", + .p.flags = AVFMT_VARIABLE_FPS | AVFMT_GLOBALHEADER | + AVFMT_TS_NEGATIVE | AVFMT_TS_NONSTRICT, + .p.subtitle_codec = AV_CODEC_ID_SUBRIP, .priv_data_size = 0, .write_header = lrc_write_header, .write_packet = lrc_write_packet, - .flags = AVFMT_VARIABLE_FPS | AVFMT_GLOBALHEADER | - AVFMT_TS_NEGATIVE | AVFMT_TS_NONSTRICT, - .subtitle_codec = AV_CODEC_ID_SUBRIP }; diff --git a/libavformat/matroskaenc.c b/libavformat/matroskaenc.c index 2deb4284e84..113541bd9a2 100644 --- a/libavformat/matroskaenc.c +++ b/libavformat/matroskaenc.c @@ -3321,31 +3321,31 @@ static int mkv_query_codec(enum AVCodecID codec_id, int std_compliance) return 0; } -const AVOutputFormat ff_matroska_muxer = { - .name = "matroska", - .long_name = NULL_IF_CONFIG_SMALL("Matroska"), - .mime_type = "video/x-matroska", - .extensions = "mkv", +const FFOutputFormat ff_matroska_muxer = { + .p.name = "matroska", + .p.long_name = NULL_IF_CONFIG_SMALL("Matroska"), + .p.mime_type = "video/x-matroska", + .p.extensions = "mkv", .priv_data_size = sizeof(MatroskaMuxContext), - .audio_codec = CONFIG_LIBVORBIS_ENCODER ? + .p.audio_codec = CONFIG_LIBVORBIS_ENCODER ? AV_CODEC_ID_VORBIS : AV_CODEC_ID_AC3, - .video_codec = CONFIG_LIBX264_ENCODER ? + .p.video_codec = CONFIG_LIBX264_ENCODER ? AV_CODEC_ID_H264 : AV_CODEC_ID_MPEG4, .init = mkv_init, .deinit = mkv_deinit, .write_header = mkv_write_header, .write_packet = mkv_write_flush_packet, .write_trailer = mkv_write_trailer, - .flags = AVFMT_GLOBALHEADER | AVFMT_VARIABLE_FPS | + .p.flags = AVFMT_GLOBALHEADER | AVFMT_VARIABLE_FPS | AVFMT_TS_NONSTRICT | AVFMT_ALLOW_FLUSH, - .codec_tag = (const AVCodecTag* const []){ + .p.codec_tag = (const AVCodecTag* const []){ ff_codec_bmp_tags, ff_codec_wav_tags, additional_audio_tags, additional_video_tags, additional_subtitle_tags, 0 }, - .subtitle_codec = AV_CODEC_ID_ASS, + .p.subtitle_codec = AV_CODEC_ID_ASS, .query_codec = mkv_query_codec, .check_bitstream = mkv_check_bitstream, - .priv_class = &matroska_webm_class, + .p.priv_class = &matroska_webm_class, }; #endif @@ -3359,15 +3359,15 @@ static int webm_query_codec(enum AVCodecID codec_id, int std_compliance) return 0; } -const AVOutputFormat ff_webm_muxer = { - .name = "webm", - .long_name = NULL_IF_CONFIG_SMALL("WebM"), - .mime_type = "video/webm", - .extensions = "webm", +const FFOutputFormat ff_webm_muxer = { + .p.name = "webm", + .p.long_name = NULL_IF_CONFIG_SMALL("WebM"), + .p.mime_type = "video/webm", + .p.extensions = "webm", .priv_data_size = sizeof(MatroskaMuxContext), - .audio_codec = CONFIG_LIBOPUS_ENCODER ? AV_CODEC_ID_OPUS : AV_CODEC_ID_VORBIS, - .video_codec = CONFIG_LIBVPX_VP9_ENCODER? AV_CODEC_ID_VP9 : AV_CODEC_ID_VP8, - .subtitle_codec = AV_CODEC_ID_WEBVTT, + .p.audio_codec = CONFIG_LIBOPUS_ENCODER ? AV_CODEC_ID_OPUS : AV_CODEC_ID_VORBIS, + .p.video_codec = CONFIG_LIBVPX_VP9_ENCODER? AV_CODEC_ID_VP9 : AV_CODEC_ID_VP8, + .p.subtitle_codec = AV_CODEC_ID_WEBVTT, .init = mkv_init, .deinit = mkv_deinit, .write_header = mkv_write_header, @@ -3375,33 +3375,33 @@ const AVOutputFormat ff_webm_muxer = { .write_trailer = mkv_write_trailer, .query_codec = webm_query_codec, .check_bitstream = mkv_check_bitstream, - .flags = AVFMT_GLOBALHEADER | AVFMT_VARIABLE_FPS | + .p.flags = AVFMT_GLOBALHEADER | AVFMT_VARIABLE_FPS | AVFMT_TS_NONSTRICT | AVFMT_ALLOW_FLUSH, - .priv_class = &matroska_webm_class, + .p.priv_class = &matroska_webm_class, }; #endif #if CONFIG_MATROSKA_AUDIO_MUXER -const AVOutputFormat ff_matroska_audio_muxer = { - .name = "matroska", - .long_name = NULL_IF_CONFIG_SMALL("Matroska Audio"), - .mime_type = "audio/x-matroska", - .extensions = "mka", +const FFOutputFormat ff_matroska_audio_muxer = { + .p.name = "matroska", + .p.long_name = NULL_IF_CONFIG_SMALL("Matroska Audio"), + .p.mime_type = "audio/x-matroska", + .p.extensions = "mka", .priv_data_size = sizeof(MatroskaMuxContext), - .audio_codec = CONFIG_LIBVORBIS_ENCODER ? + .p.audio_codec = CONFIG_LIBVORBIS_ENCODER ? AV_CODEC_ID_VORBIS : AV_CODEC_ID_AC3, - .video_codec = AV_CODEC_ID_NONE, + .p.video_codec = AV_CODEC_ID_NONE, .init = mkv_init, .deinit = mkv_deinit, .write_header = mkv_write_header, .write_packet = mkv_write_flush_packet, .write_trailer = mkv_write_trailer, .check_bitstream = mkv_check_bitstream, - .flags = AVFMT_GLOBALHEADER | AVFMT_TS_NONSTRICT | + .p.flags = AVFMT_GLOBALHEADER | AVFMT_TS_NONSTRICT | AVFMT_ALLOW_FLUSH, - .codec_tag = (const AVCodecTag* const []){ + .p.codec_tag = (const AVCodecTag* const []){ ff_codec_wav_tags, additional_audio_tags, 0 }, - .priv_class = &matroska_webm_class, + .p.priv_class = &matroska_webm_class, }; #endif diff --git a/libavformat/microdvdenc.c b/libavformat/microdvdenc.c index 4db5e701619..950309981bb 100644 --- a/libavformat/microdvdenc.c +++ b/libavformat/microdvdenc.c @@ -22,6 +22,7 @@ #include #include "avformat.h" #include "internal.h" +#include "mux.h" static int microdvd_write_header(struct AVFormatContext *s) { @@ -55,13 +56,13 @@ static int microdvd_write_packet(AVFormatContext *avf, AVPacket *pkt) return 0; } -const AVOutputFormat ff_microdvd_muxer = { - .name = "microdvd", - .long_name = NULL_IF_CONFIG_SMALL("MicroDVD subtitle format"), - .mime_type = "text/x-microdvd", - .extensions = "sub", +const FFOutputFormat ff_microdvd_muxer = { + .p.name = "microdvd", + .p.long_name = NULL_IF_CONFIG_SMALL("MicroDVD subtitle format"), + .p.mime_type = "text/x-microdvd", + .p.extensions = "sub", + .p.flags = AVFMT_NOTIMESTAMPS, + .p.subtitle_codec = AV_CODEC_ID_MICRODVD, .write_header = microdvd_write_header, .write_packet = microdvd_write_packet, - .flags = AVFMT_NOTIMESTAMPS, - .subtitle_codec = AV_CODEC_ID_MICRODVD, }; diff --git a/libavformat/mkvtimestamp_v2.c b/libavformat/mkvtimestamp_v2.c index 27c7d7a68be..dde431ab7d0 100644 --- a/libavformat/mkvtimestamp_v2.c +++ b/libavformat/mkvtimestamp_v2.c @@ -21,6 +21,7 @@ #include "avformat.h" #include "internal.h" +#include "mux.h" static int write_header(AVFormatContext *s) { @@ -40,11 +41,11 @@ static int write_packet(AVFormatContext *s, AVPacket *pkt) return 0; } -const AVOutputFormat ff_mkvtimestamp_v2_muxer = { - .name = "mkvtimestamp_v2", - .long_name = NULL_IF_CONFIG_SMALL("extract pts as timecode v2 format, as defined by mkvtoolnix"), - .audio_codec = AV_CODEC_ID_NONE, - .video_codec = AV_CODEC_ID_RAWVIDEO, +const FFOutputFormat ff_mkvtimestamp_v2_muxer = { + .p.name = "mkvtimestamp_v2", + .p.long_name = NULL_IF_CONFIG_SMALL("extract pts as timecode v2 format, as defined by mkvtoolnix"), + .p.audio_codec = AV_CODEC_ID_NONE, + .p.video_codec = AV_CODEC_ID_RAWVIDEO, .write_header = write_header, .write_packet = write_packet, }; diff --git a/libavformat/mmf.c b/libavformat/mmf.c index 3f20d5bc0b7..5cac4381f45 100644 --- a/libavformat/mmf.c +++ b/libavformat/mmf.c @@ -25,6 +25,7 @@ #include "avformat.h" #include "avio_internal.h" #include "internal.h" +#include "mux.h" #include "pcm.h" #include "rawenc.h" #include "riff.h" @@ -309,14 +310,14 @@ const AVInputFormat ff_mmf_demuxer = { #endif #if CONFIG_MMF_MUXER -const AVOutputFormat ff_mmf_muxer = { - .name = "mmf", - .long_name = NULL_IF_CONFIG_SMALL("Yamaha SMAF"), - .mime_type = "application/vnd.smaf", - .extensions = "mmf", +const FFOutputFormat ff_mmf_muxer = { + .p.name = "mmf", + .p.long_name = NULL_IF_CONFIG_SMALL("Yamaha SMAF"), + .p.mime_type = "application/vnd.smaf", + .p.extensions = "mmf", .priv_data_size = sizeof(MMFContext), - .audio_codec = AV_CODEC_ID_ADPCM_YAMAHA, - .video_codec = AV_CODEC_ID_NONE, + .p.audio_codec = AV_CODEC_ID_ADPCM_YAMAHA, + .p.video_codec = AV_CODEC_ID_NONE, .write_header = mmf_write_header, .write_packet = ff_raw_write_packet, .write_trailer = mmf_write_trailer, diff --git a/libavformat/movenc.c b/libavformat/movenc.c index 8d31317838b..87ee7a921f0 100644 --- a/libavformat/movenc.c +++ b/libavformat/movenc.c @@ -7805,182 +7805,182 @@ static const AVClass mov_avif_muxer_class = { #endif #if CONFIG_MOV_MUXER -const AVOutputFormat ff_mov_muxer = { - .name = "mov", - .long_name = NULL_IF_CONFIG_SMALL("QuickTime / MOV"), - .extensions = "mov", +const FFOutputFormat ff_mov_muxer = { + .p.name = "mov", + .p.long_name = NULL_IF_CONFIG_SMALL("QuickTime / MOV"), + .p.extensions = "mov", .priv_data_size = sizeof(MOVMuxContext), - .audio_codec = AV_CODEC_ID_AAC, - .video_codec = CONFIG_LIBX264_ENCODER ? + .p.audio_codec = AV_CODEC_ID_AAC, + .p.video_codec = CONFIG_LIBX264_ENCODER ? AV_CODEC_ID_H264 : AV_CODEC_ID_MPEG4, .init = mov_init, .write_header = mov_write_header, .write_packet = mov_write_packet, .write_trailer = mov_write_trailer, .deinit = mov_free, - .flags = AVFMT_GLOBALHEADER | AVFMT_ALLOW_FLUSH | AVFMT_TS_NEGATIVE, - .codec_tag = (const AVCodecTag* const []){ + .p.flags = AVFMT_GLOBALHEADER | AVFMT_ALLOW_FLUSH | AVFMT_TS_NEGATIVE, + .p.codec_tag = (const AVCodecTag* const []){ ff_codec_movvideo_tags, ff_codec_movaudio_tags, ff_codec_movsubtitle_tags, 0 }, .check_bitstream = mov_check_bitstream, - .priv_class = &mov_isobmff_muxer_class, + .p.priv_class = &mov_isobmff_muxer_class, }; #endif #if CONFIG_TGP_MUXER -const AVOutputFormat ff_tgp_muxer = { - .name = "3gp", - .long_name = NULL_IF_CONFIG_SMALL("3GP (3GPP file format)"), - .extensions = "3gp", +const FFOutputFormat ff_tgp_muxer = { + .p.name = "3gp", + .p.long_name = NULL_IF_CONFIG_SMALL("3GP (3GPP file format)"), + .p.extensions = "3gp", .priv_data_size = sizeof(MOVMuxContext), - .audio_codec = AV_CODEC_ID_AMR_NB, - .video_codec = AV_CODEC_ID_H263, + .p.audio_codec = AV_CODEC_ID_AMR_NB, + .p.video_codec = AV_CODEC_ID_H263, .init = mov_init, .write_header = mov_write_header, .write_packet = mov_write_packet, .write_trailer = mov_write_trailer, .deinit = mov_free, - .flags = AVFMT_GLOBALHEADER | AVFMT_ALLOW_FLUSH | AVFMT_TS_NEGATIVE, - .codec_tag = codec_3gp_tags_list, + .p.flags = AVFMT_GLOBALHEADER | AVFMT_ALLOW_FLUSH | AVFMT_TS_NEGATIVE, + .p.codec_tag = codec_3gp_tags_list, .check_bitstream = mov_check_bitstream, - .priv_class = &mov_isobmff_muxer_class, + .p.priv_class = &mov_isobmff_muxer_class, }; #endif #if CONFIG_MP4_MUXER -const AVOutputFormat ff_mp4_muxer = { - .name = "mp4", - .long_name = NULL_IF_CONFIG_SMALL("MP4 (MPEG-4 Part 14)"), - .mime_type = "video/mp4", - .extensions = "mp4", +const FFOutputFormat ff_mp4_muxer = { + .p.name = "mp4", + .p.long_name = NULL_IF_CONFIG_SMALL("MP4 (MPEG-4 Part 14)"), + .p.mime_type = "video/mp4", + .p.extensions = "mp4", .priv_data_size = sizeof(MOVMuxContext), - .audio_codec = AV_CODEC_ID_AAC, - .video_codec = CONFIG_LIBX264_ENCODER ? + .p.audio_codec = AV_CODEC_ID_AAC, + .p.video_codec = CONFIG_LIBX264_ENCODER ? AV_CODEC_ID_H264 : AV_CODEC_ID_MPEG4, .init = mov_init, .write_header = mov_write_header, .write_packet = mov_write_packet, .write_trailer = mov_write_trailer, .deinit = mov_free, - .flags = AVFMT_GLOBALHEADER | AVFMT_ALLOW_FLUSH | AVFMT_TS_NEGATIVE, - .codec_tag = mp4_codec_tags_list, + .p.flags = AVFMT_GLOBALHEADER | AVFMT_ALLOW_FLUSH | AVFMT_TS_NEGATIVE, + .p.codec_tag = mp4_codec_tags_list, .check_bitstream = mov_check_bitstream, - .priv_class = &mov_isobmff_muxer_class, + .p.priv_class = &mov_isobmff_muxer_class, }; #endif #if CONFIG_PSP_MUXER -const AVOutputFormat ff_psp_muxer = { - .name = "psp", - .long_name = NULL_IF_CONFIG_SMALL("PSP MP4 (MPEG-4 Part 14)"), - .extensions = "mp4,psp", +const FFOutputFormat ff_psp_muxer = { + .p.name = "psp", + .p.long_name = NULL_IF_CONFIG_SMALL("PSP MP4 (MPEG-4 Part 14)"), + .p.extensions = "mp4,psp", .priv_data_size = sizeof(MOVMuxContext), - .audio_codec = AV_CODEC_ID_AAC, - .video_codec = CONFIG_LIBX264_ENCODER ? + .p.audio_codec = AV_CODEC_ID_AAC, + .p.video_codec = CONFIG_LIBX264_ENCODER ? AV_CODEC_ID_H264 : AV_CODEC_ID_MPEG4, .init = mov_init, .write_header = mov_write_header, .write_packet = mov_write_packet, .write_trailer = mov_write_trailer, .deinit = mov_free, - .flags = AVFMT_GLOBALHEADER | AVFMT_ALLOW_FLUSH | AVFMT_TS_NEGATIVE, - .codec_tag = mp4_codec_tags_list, + .p.flags = AVFMT_GLOBALHEADER | AVFMT_ALLOW_FLUSH | AVFMT_TS_NEGATIVE, + .p.codec_tag = mp4_codec_tags_list, .check_bitstream = mov_check_bitstream, - .priv_class = &mov_isobmff_muxer_class, + .p.priv_class = &mov_isobmff_muxer_class, }; #endif #if CONFIG_TG2_MUXER -const AVOutputFormat ff_tg2_muxer = { - .name = "3g2", - .long_name = NULL_IF_CONFIG_SMALL("3GP2 (3GPP2 file format)"), - .extensions = "3g2", +const FFOutputFormat ff_tg2_muxer = { + .p.name = "3g2", + .p.long_name = NULL_IF_CONFIG_SMALL("3GP2 (3GPP2 file format)"), + .p.extensions = "3g2", .priv_data_size = sizeof(MOVMuxContext), - .audio_codec = AV_CODEC_ID_AMR_NB, - .video_codec = AV_CODEC_ID_H263, + .p.audio_codec = AV_CODEC_ID_AMR_NB, + .p.video_codec = AV_CODEC_ID_H263, .init = mov_init, .write_header = mov_write_header, .write_packet = mov_write_packet, .write_trailer = mov_write_trailer, .deinit = mov_free, - .flags = AVFMT_GLOBALHEADER | AVFMT_ALLOW_FLUSH | AVFMT_TS_NEGATIVE, - .codec_tag = codec_3gp_tags_list, + .p.flags = AVFMT_GLOBALHEADER | AVFMT_ALLOW_FLUSH | AVFMT_TS_NEGATIVE, + .p.codec_tag = codec_3gp_tags_list, .check_bitstream = mov_check_bitstream, - .priv_class = &mov_isobmff_muxer_class, + .p.priv_class = &mov_isobmff_muxer_class, }; #endif #if CONFIG_IPOD_MUXER -const AVOutputFormat ff_ipod_muxer = { - .name = "ipod", - .long_name = NULL_IF_CONFIG_SMALL("iPod H.264 MP4 (MPEG-4 Part 14)"), - .mime_type = "video/mp4", - .extensions = "m4v,m4a,m4b", +const FFOutputFormat ff_ipod_muxer = { + .p.name = "ipod", + .p.long_name = NULL_IF_CONFIG_SMALL("iPod H.264 MP4 (MPEG-4 Part 14)"), + .p.mime_type = "video/mp4", + .p.extensions = "m4v,m4a,m4b", .priv_data_size = sizeof(MOVMuxContext), - .audio_codec = AV_CODEC_ID_AAC, - .video_codec = AV_CODEC_ID_H264, + .p.audio_codec = AV_CODEC_ID_AAC, + .p.video_codec = AV_CODEC_ID_H264, .init = mov_init, .write_header = mov_write_header, .write_packet = mov_write_packet, .write_trailer = mov_write_trailer, .deinit = mov_free, - .flags = AVFMT_GLOBALHEADER | AVFMT_ALLOW_FLUSH | AVFMT_TS_NEGATIVE, - .codec_tag = (const AVCodecTag* const []){ codec_ipod_tags, 0 }, + .p.flags = AVFMT_GLOBALHEADER | AVFMT_ALLOW_FLUSH | AVFMT_TS_NEGATIVE, + .p.codec_tag = (const AVCodecTag* const []){ codec_ipod_tags, 0 }, .check_bitstream = mov_check_bitstream, - .priv_class = &mov_isobmff_muxer_class, + .p.priv_class = &mov_isobmff_muxer_class, }; #endif #if CONFIG_ISMV_MUXER -const AVOutputFormat ff_ismv_muxer = { - .name = "ismv", - .long_name = NULL_IF_CONFIG_SMALL("ISMV/ISMA (Smooth Streaming)"), - .mime_type = "video/mp4", - .extensions = "ismv,isma", +const FFOutputFormat ff_ismv_muxer = { + .p.name = "ismv", + .p.long_name = NULL_IF_CONFIG_SMALL("ISMV/ISMA (Smooth Streaming)"), + .p.mime_type = "video/mp4", + .p.extensions = "ismv,isma", .priv_data_size = sizeof(MOVMuxContext), - .audio_codec = AV_CODEC_ID_AAC, - .video_codec = AV_CODEC_ID_H264, + .p.audio_codec = AV_CODEC_ID_AAC, + .p.video_codec = AV_CODEC_ID_H264, .init = mov_init, .write_header = mov_write_header, .write_packet = mov_write_packet, .write_trailer = mov_write_trailer, .deinit = mov_free, - .flags = AVFMT_GLOBALHEADER | AVFMT_ALLOW_FLUSH | AVFMT_TS_NEGATIVE, - .codec_tag = (const AVCodecTag* const []){ + .p.flags = AVFMT_GLOBALHEADER | AVFMT_ALLOW_FLUSH | AVFMT_TS_NEGATIVE, + .p.codec_tag = (const AVCodecTag* const []){ codec_mp4_tags, codec_ism_tags, 0 }, .check_bitstream = mov_check_bitstream, - .priv_class = &mov_isobmff_muxer_class, + .p.priv_class = &mov_isobmff_muxer_class, }; #endif #if CONFIG_F4V_MUXER -const AVOutputFormat ff_f4v_muxer = { - .name = "f4v", - .long_name = NULL_IF_CONFIG_SMALL("F4V Adobe Flash Video"), - .mime_type = "application/f4v", - .extensions = "f4v", +const FFOutputFormat ff_f4v_muxer = { + .p.name = "f4v", + .p.long_name = NULL_IF_CONFIG_SMALL("F4V Adobe Flash Video"), + .p.mime_type = "application/f4v", + .p.extensions = "f4v", .priv_data_size = sizeof(MOVMuxContext), - .audio_codec = AV_CODEC_ID_AAC, - .video_codec = AV_CODEC_ID_H264, + .p.audio_codec = AV_CODEC_ID_AAC, + .p.video_codec = AV_CODEC_ID_H264, .init = mov_init, .write_header = mov_write_header, .write_packet = mov_write_packet, .write_trailer = mov_write_trailer, .deinit = mov_free, - .flags = AVFMT_GLOBALHEADER | AVFMT_ALLOW_FLUSH, - .codec_tag = (const AVCodecTag* const []){ codec_f4v_tags, 0 }, + .p.flags = AVFMT_GLOBALHEADER | AVFMT_ALLOW_FLUSH, + .p.codec_tag = (const AVCodecTag* const []){ codec_f4v_tags, 0 }, .check_bitstream = mov_check_bitstream, - .priv_class = &mov_isobmff_muxer_class, + .p.priv_class = &mov_isobmff_muxer_class, }; #endif #if CONFIG_AVIF_MUXER -const AVOutputFormat ff_avif_muxer = { - .name = "avif", - .long_name = NULL_IF_CONFIG_SMALL("AVIF"), - .mime_type = "image/avif", - .extensions = "avif", +const FFOutputFormat ff_avif_muxer = { + .p.name = "avif", + .p.long_name = NULL_IF_CONFIG_SMALL("AVIF"), + .p.mime_type = "image/avif", + .p.extensions = "avif", .priv_data_size = sizeof(MOVMuxContext), - .video_codec = AV_CODEC_ID_AV1, + .p.video_codec = AV_CODEC_ID_AV1, .init = mov_init, .write_header = mov_write_header, .write_packet = mov_write_packet, .write_trailer = avif_write_trailer, .deinit = mov_free, - .flags = AVFMT_GLOBALHEADER | AVFMT_ALLOW_FLUSH, - .codec_tag = codec_avif_tags_list, - .priv_class = &mov_avif_muxer_class, + .p.flags = AVFMT_GLOBALHEADER | AVFMT_ALLOW_FLUSH, + .p.codec_tag = codec_avif_tags_list, + .p.priv_class = &mov_avif_muxer_class, }; #endif diff --git a/libavformat/mp3enc.c b/libavformat/mp3enc.c index 91874fa14ef..5e81f72a59a 100644 --- a/libavformat/mp3enc.c +++ b/libavformat/mp3enc.c @@ -23,6 +23,7 @@ #include "avio_internal.h" #include "id3v1.h" #include "id3v2.h" +#include "mux.h" #include "rawenc.h" #include "libavutil/avstring.h" #include "libavcodec/mpegaudio.h" @@ -636,20 +637,20 @@ static void mp3_deinit(struct AVFormatContext *s) av_freep(&mp3->xing_frame); } -const AVOutputFormat ff_mp3_muxer = { - .name = "mp3", - .long_name = NULL_IF_CONFIG_SMALL("MP3 (MPEG audio layer 3)"), - .mime_type = "audio/mpeg", - .extensions = "mp3", +const FFOutputFormat ff_mp3_muxer = { + .p.name = "mp3", + .p.long_name = NULL_IF_CONFIG_SMALL("MP3 (MPEG audio layer 3)"), + .p.mime_type = "audio/mpeg", + .p.extensions = "mp3", .priv_data_size = sizeof(MP3Context), - .audio_codec = AV_CODEC_ID_MP3, - .video_codec = AV_CODEC_ID_PNG, + .p.audio_codec = AV_CODEC_ID_MP3, + .p.video_codec = AV_CODEC_ID_PNG, .init = mp3_init, .write_header = mp3_write_header, .write_packet = mp3_write_packet, .write_trailer = mp3_write_trailer, .deinit = mp3_deinit, .query_codec = query_codec, - .flags = AVFMT_NOTIMESTAMPS, - .priv_class = &mp3_muxer_class, + .p.flags = AVFMT_NOTIMESTAMPS, + .p.priv_class = &mp3_muxer_class, }; diff --git a/libavformat/mpegenc.c b/libavformat/mpegenc.c index 3ab4bd3f9b2..c06e3082963 100644 --- a/libavformat/mpegenc.c +++ b/libavformat/mpegenc.c @@ -35,6 +35,7 @@ #include "avio_internal.h" #include "internal.h" #include "mpeg.h" +#include "mux.h" #define MAX_PAYLOAD_SIZE 4096 @@ -86,10 +87,10 @@ typedef struct MpegMuxContext { int preload; } MpegMuxContext; -extern const AVOutputFormat ff_mpeg1vcd_muxer; -extern const AVOutputFormat ff_mpeg2dvd_muxer; -extern const AVOutputFormat ff_mpeg2svcd_muxer; -extern const AVOutputFormat ff_mpeg2vob_muxer; +extern const FFOutputFormat ff_mpeg1vcd_muxer; +extern const FFOutputFormat ff_mpeg2dvd_muxer; +extern const FFOutputFormat ff_mpeg2svcd_muxer; +extern const FFOutputFormat ff_mpeg2vob_muxer; static int put_pack_header(AVFormatContext *ctx, uint8_t *buf, int64_t timestamp) @@ -307,12 +308,12 @@ static av_cold int mpeg_mux_init(AVFormatContext *ctx) int video_bitrate; s->packet_number = 0; - s->is_vcd = (CONFIG_MPEG1VCD_MUXER && ctx->oformat == &ff_mpeg1vcd_muxer); - s->is_svcd = (CONFIG_MPEG2SVCD_MUXER && ctx->oformat == &ff_mpeg2svcd_muxer); - s->is_mpeg2 = ((CONFIG_MPEG2VOB_MUXER && ctx->oformat == &ff_mpeg2vob_muxer) || - (CONFIG_MPEG2DVD_MUXER && ctx->oformat == &ff_mpeg2dvd_muxer) || - (CONFIG_MPEG2SVCD_MUXER && ctx->oformat == &ff_mpeg2svcd_muxer)); - s->is_dvd = (CONFIG_MPEG2DVD_MUXER && ctx->oformat == &ff_mpeg2dvd_muxer); + s->is_vcd = (CONFIG_MPEG1VCD_MUXER && ctx->oformat == &ff_mpeg1vcd_muxer.p); + s->is_svcd = (CONFIG_MPEG2SVCD_MUXER && ctx->oformat == &ff_mpeg2svcd_muxer.p); + s->is_mpeg2 = ((CONFIG_MPEG2VOB_MUXER && ctx->oformat == &ff_mpeg2vob_muxer.p) || + (CONFIG_MPEG2DVD_MUXER && ctx->oformat == &ff_mpeg2dvd_muxer.p) || + (CONFIG_MPEG2SVCD_MUXER && ctx->oformat == &ff_mpeg2svcd_muxer.p)); + s->is_dvd = (CONFIG_MPEG2DVD_MUXER && ctx->oformat == &ff_mpeg2dvd_muxer.p); if (ctx->packet_size) { if (ctx->packet_size < 20 || ctx->packet_size > (1 << 23) + 10) { @@ -1293,87 +1294,87 @@ static const AVClass mpeg_class = { }; #if CONFIG_MPEG1SYSTEM_MUXER -const AVOutputFormat ff_mpeg1system_muxer = { - .name = "mpeg", - .long_name = NULL_IF_CONFIG_SMALL("MPEG-1 Systems / MPEG program stream"), - .mime_type = "video/mpeg", - .extensions = "mpg,mpeg", +const FFOutputFormat ff_mpeg1system_muxer = { + .p.name = "mpeg", + .p.long_name = NULL_IF_CONFIG_SMALL("MPEG-1 Systems / MPEG program stream"), + .p.mime_type = "video/mpeg", + .p.extensions = "mpg,mpeg", .priv_data_size = sizeof(MpegMuxContext), - .audio_codec = AV_CODEC_ID_MP2, - .video_codec = AV_CODEC_ID_MPEG1VIDEO, + .p.audio_codec = AV_CODEC_ID_MP2, + .p.video_codec = AV_CODEC_ID_MPEG1VIDEO, .write_header = mpeg_mux_init, .write_packet = mpeg_mux_write_packet, .write_trailer = mpeg_mux_end, .deinit = mpeg_mux_deinit, - .priv_class = &mpeg_class, + .p.priv_class = &mpeg_class, }; #endif #if CONFIG_MPEG1VCD_MUXER -const AVOutputFormat ff_mpeg1vcd_muxer = { - .name = "vcd", - .long_name = NULL_IF_CONFIG_SMALL("MPEG-1 Systems / MPEG program stream (VCD)"), - .mime_type = "video/mpeg", +const FFOutputFormat ff_mpeg1vcd_muxer = { + .p.name = "vcd", + .p.long_name = NULL_IF_CONFIG_SMALL("MPEG-1 Systems / MPEG program stream (VCD)"), + .p.mime_type = "video/mpeg", .priv_data_size = sizeof(MpegMuxContext), - .audio_codec = AV_CODEC_ID_MP2, - .video_codec = AV_CODEC_ID_MPEG1VIDEO, + .p.audio_codec = AV_CODEC_ID_MP2, + .p.video_codec = AV_CODEC_ID_MPEG1VIDEO, .write_header = mpeg_mux_init, .write_packet = mpeg_mux_write_packet, .write_trailer = mpeg_mux_end, .deinit = mpeg_mux_deinit, - .priv_class = &mpeg_class, + .p.priv_class = &mpeg_class, }; #endif #if CONFIG_MPEG2VOB_MUXER -const AVOutputFormat ff_mpeg2vob_muxer = { - .name = "vob", - .long_name = NULL_IF_CONFIG_SMALL("MPEG-2 PS (VOB)"), - .mime_type = "video/mpeg", - .extensions = "vob", +const FFOutputFormat ff_mpeg2vob_muxer = { + .p.name = "vob", + .p.long_name = NULL_IF_CONFIG_SMALL("MPEG-2 PS (VOB)"), + .p.mime_type = "video/mpeg", + .p.extensions = "vob", .priv_data_size = sizeof(MpegMuxContext), - .audio_codec = AV_CODEC_ID_MP2, - .video_codec = AV_CODEC_ID_MPEG2VIDEO, + .p.audio_codec = AV_CODEC_ID_MP2, + .p.video_codec = AV_CODEC_ID_MPEG2VIDEO, .write_header = mpeg_mux_init, .write_packet = mpeg_mux_write_packet, .write_trailer = mpeg_mux_end, .deinit = mpeg_mux_deinit, - .priv_class = &mpeg_class, + .p.priv_class = &mpeg_class, }; #endif /* Same as mpeg2vob_mux except that the pack size is 2324 */ #if CONFIG_MPEG2SVCD_MUXER -const AVOutputFormat ff_mpeg2svcd_muxer = { - .name = "svcd", - .long_name = NULL_IF_CONFIG_SMALL("MPEG-2 PS (SVCD)"), - .mime_type = "video/mpeg", - .extensions = "vob", +const FFOutputFormat ff_mpeg2svcd_muxer = { + .p.name = "svcd", + .p.long_name = NULL_IF_CONFIG_SMALL("MPEG-2 PS (SVCD)"), + .p.mime_type = "video/mpeg", + .p.extensions = "vob", .priv_data_size = sizeof(MpegMuxContext), - .audio_codec = AV_CODEC_ID_MP2, - .video_codec = AV_CODEC_ID_MPEG2VIDEO, + .p.audio_codec = AV_CODEC_ID_MP2, + .p.video_codec = AV_CODEC_ID_MPEG2VIDEO, .write_header = mpeg_mux_init, .write_packet = mpeg_mux_write_packet, .write_trailer = mpeg_mux_end, .deinit = mpeg_mux_deinit, - .priv_class = &mpeg_class, + .p.priv_class = &mpeg_class, }; #endif /* Same as mpeg2vob_mux except the 'is_dvd' flag is set to produce NAV pkts */ #if CONFIG_MPEG2DVD_MUXER -const AVOutputFormat ff_mpeg2dvd_muxer = { - .name = "dvd", - .long_name = NULL_IF_CONFIG_SMALL("MPEG-2 PS (DVD VOB)"), - .mime_type = "video/mpeg", - .extensions = "dvd", +const FFOutputFormat ff_mpeg2dvd_muxer = { + .p.name = "dvd", + .p.long_name = NULL_IF_CONFIG_SMALL("MPEG-2 PS (DVD VOB)"), + .p.mime_type = "video/mpeg", + .p.extensions = "dvd", .priv_data_size = sizeof(MpegMuxContext), - .audio_codec = AV_CODEC_ID_MP2, - .video_codec = AV_CODEC_ID_MPEG2VIDEO, + .p.audio_codec = AV_CODEC_ID_MP2, + .p.video_codec = AV_CODEC_ID_MPEG2VIDEO, .write_header = mpeg_mux_init, .write_packet = mpeg_mux_write_packet, .write_trailer = mpeg_mux_end, .deinit = mpeg_mux_deinit, - .priv_class = &mpeg_class, + .p.priv_class = &mpeg_class, }; #endif diff --git a/libavformat/mpegtsenc.c b/libavformat/mpegtsenc.c index 48d39e6a7da..00ad426086f 100644 --- a/libavformat/mpegtsenc.c +++ b/libavformat/mpegtsenc.c @@ -2308,19 +2308,19 @@ static const AVClass mpegts_muxer_class = { .version = LIBAVUTIL_VERSION_INT, }; -const AVOutputFormat ff_mpegts_muxer = { - .name = "mpegts", - .long_name = NULL_IF_CONFIG_SMALL("MPEG-TS (MPEG-2 Transport Stream)"), - .mime_type = "video/MP2T", - .extensions = "ts,m2t,m2ts,mts", +const FFOutputFormat ff_mpegts_muxer = { + .p.name = "mpegts", + .p.long_name = NULL_IF_CONFIG_SMALL("MPEG-TS (MPEG-2 Transport Stream)"), + .p.mime_type = "video/MP2T", + .p.extensions = "ts,m2t,m2ts,mts", .priv_data_size = sizeof(MpegTSWrite), - .audio_codec = AV_CODEC_ID_MP2, - .video_codec = AV_CODEC_ID_MPEG2VIDEO, + .p.audio_codec = AV_CODEC_ID_MP2, + .p.video_codec = AV_CODEC_ID_MPEG2VIDEO, .init = mpegts_init, .write_packet = mpegts_write_packet, .write_trailer = mpegts_write_end, .deinit = mpegts_deinit, .check_bitstream = mpegts_check_bitstream, - .flags = AVFMT_ALLOW_FLUSH | AVFMT_VARIABLE_FPS | AVFMT_NODIMENSIONS, - .priv_class = &mpegts_muxer_class, + .p.flags = AVFMT_ALLOW_FLUSH | AVFMT_VARIABLE_FPS | AVFMT_NODIMENSIONS, + .p.priv_class = &mpegts_muxer_class, }; diff --git a/libavformat/mpjpeg.c b/libavformat/mpjpeg.c index c5e5d1e2864..81ace8e9ee1 100644 --- a/libavformat/mpjpeg.c +++ b/libavformat/mpjpeg.c @@ -20,6 +20,7 @@ */ #include "libavutil/opt.h" #include "avformat.h" +#include "mux.h" /* Multipart JPEG */ @@ -61,16 +62,16 @@ static const AVClass mpjpeg_muxer_class = { .version = LIBAVUTIL_VERSION_INT, }; -const AVOutputFormat ff_mpjpeg_muxer = { - .name = "mpjpeg", - .long_name = NULL_IF_CONFIG_SMALL("MIME multipart JPEG"), - .mime_type = "multipart/x-mixed-replace;boundary=" BOUNDARY_TAG, - .extensions = "mjpg", +const FFOutputFormat ff_mpjpeg_muxer = { + .p.name = "mpjpeg", + .p.long_name = NULL_IF_CONFIG_SMALL("MIME multipart JPEG"), + .p.mime_type = "multipart/x-mixed-replace;boundary=" BOUNDARY_TAG, + .p.extensions = "mjpg", .priv_data_size = sizeof(MPJPEGContext), - .audio_codec = AV_CODEC_ID_NONE, - .video_codec = AV_CODEC_ID_MJPEG, + .p.audio_codec = AV_CODEC_ID_NONE, + .p.video_codec = AV_CODEC_ID_MJPEG, .write_header = mpjpeg_write_header, .write_packet = mpjpeg_write_packet, - .flags = AVFMT_NOTIMESTAMPS, - .priv_class = &mpjpeg_muxer_class, + .p.flags = AVFMT_NOTIMESTAMPS, + .p.priv_class = &mpjpeg_muxer_class, }; diff --git a/libavformat/mux.c b/libavformat/mux.c index b2b5be63b44..04de05ec178 100644 --- a/libavformat/mux.c +++ b/libavformat/mux.c @@ -118,8 +118,8 @@ int avformat_alloc_output_context2(AVFormatContext **avctx, const AVOutputFormat } s->oformat = oformat; - if (s->oformat->priv_data_size > 0) { - s->priv_data = av_mallocz(s->oformat->priv_data_size); + if (ffofmt(s->oformat)->priv_data_size > 0) { + s->priv_data = av_mallocz(ffofmt(s->oformat)->priv_data_size); if (!s->priv_data) goto nomem; if (s->oformat->priv_class) { @@ -182,7 +182,7 @@ static int init_muxer(AVFormatContext *s, AVDictionary **options) { FFFormatContext *const si = ffformatcontext(s); AVDictionary *tmp = NULL; - const AVOutputFormat *of = s->oformat; + const FFOutputFormat *of = ffofmt(s->oformat); AVDictionaryEntry *e; int ret = 0; @@ -201,7 +201,7 @@ static int init_muxer(AVFormatContext *s, AVDictionary **options) } // some sanity checks - if (s->nb_streams == 0 && !(of->flags & AVFMT_NOSTREAMS)) { + if (s->nb_streams == 0 && !(of->p.flags & AVFMT_NOSTREAMS)) { av_log(s, AV_LOG_ERROR, "No streams to mux were specified\n"); ret = AVERROR(EINVAL); goto fail; @@ -251,7 +251,7 @@ FF_ENABLE_DEPRECATION_WARNINGS break; case AVMEDIA_TYPE_VIDEO: if ((par->width <= 0 || par->height <= 0) && - !(of->flags & AVFMT_NODIMENSIONS)) { + !(of->p.flags & AVFMT_NODIMENSIONS)) { av_log(s, AV_LOG_ERROR, "dimensions not set\n"); ret = AVERROR(EINVAL); goto fail; @@ -281,11 +281,11 @@ FF_ENABLE_DEPRECATION_WARNINGS sti->is_intra_only = ff_is_intra_only(par->codec_id); - if (of->codec_tag) { + if (of->p.codec_tag) { if ( par->codec_tag && par->codec_id == AV_CODEC_ID_RAWVIDEO - && ( av_codec_get_tag(of->codec_tag, par->codec_id) == 0 - || av_codec_get_tag(of->codec_tag, par->codec_id) == MKTAG('r', 'a', 'w', ' ')) + && ( av_codec_get_tag(of->p.codec_tag, par->codec_id) == 0 + || av_codec_get_tag(of->p.codec_tag, par->codec_id) == MKTAG('r', 'a', 'w', ' ')) && !validate_codec_tag(s, st)) { // the current rawvideo encoding system ends up setting // the wrong codec_tag for avi/mov, we override it here @@ -301,7 +301,7 @@ FF_ENABLE_DEPRECATION_WARNINGS goto fail; } } else - par->codec_tag = av_codec_get_tag(of->codec_tag, par->codec_id); + par->codec_tag = av_codec_get_tag(of->p.codec_tag, par->codec_id); } if (par->codec_type != AVMEDIA_TYPE_ATTACHMENT) @@ -319,8 +319,8 @@ FF_ENABLE_DEPRECATION_WARNINGS ret = AVERROR(ENOMEM); goto fail; } - if (of->priv_class) { - *(const AVClass **)s->priv_data = of->priv_class; + if (of->p.priv_class) { + *(const AVClass **)s->priv_data = of->p.priv_class; av_opt_set_defaults(s->priv_data); if ((ret = av_opt_set_dict2(s->priv_data, &tmp, AV_OPT_SEARCH_CHILDREN)) < 0) goto fail; @@ -343,10 +343,10 @@ FF_ENABLE_DEPRECATION_WARNINGS *options = tmp; } - if (s->oformat->init) { - if ((ret = s->oformat->init(s)) < 0) { - if (s->oformat->deinit) - s->oformat->deinit(s); + if (of->init) { + if ((ret = of->init(s)) < 0) { + if (of->deinit) + of->deinit(s); return ret; } return ret == 0; @@ -420,8 +420,9 @@ static void flush_if_needed(AVFormatContext *s) static void deinit_muxer(AVFormatContext *s) { FFFormatContext *const si = ffformatcontext(s); - if (s->oformat && s->oformat->deinit && si->initialized) - s->oformat->deinit(s); + const FFOutputFormat *const of = ffofmt(s->oformat); + if (of && of->deinit && si->initialized) + of->deinit(s); si->initialized = si->streams_initialized = 0; } @@ -437,7 +438,7 @@ int avformat_init_output(AVFormatContext *s, AVDictionary **options) si->initialized = 1; si->streams_initialized = ret; - if (s->oformat->init && ret) { + if (ffofmt(s->oformat)->init && ret) { if ((ret = init_pts(s)) < 0) return ret; @@ -460,8 +461,8 @@ int avformat_write_header(AVFormatContext *s, AVDictionary **options) if (!(s->oformat->flags & AVFMT_NOFILE) && s->pb) avio_write_marker(s->pb, AV_NOPTS_VALUE, AVIO_DATA_MARKER_HEADER); - if (s->oformat->write_header) { - ret = s->oformat->write_header(s); + if (ffofmt(s->oformat)->write_header) { + ret = ffofmt(s->oformat)->write_header(s); if (ret >= 0 && s->pb && s->pb->error < 0) ret = s->pb->error; if (ret < 0) @@ -724,9 +725,9 @@ static int write_packet(AVFormatContext *s, AVPacket *pkt) if ((pkt->flags & AV_PKT_FLAG_UNCODED_FRAME)) { AVFrame **frame = (AVFrame **)pkt->data; av_assert0(pkt->size == sizeof(*frame)); - ret = s->oformat->write_uncoded_frame(s, pkt->stream_index, frame, 0); + ret = ffofmt(s->oformat)->write_uncoded_frame(s, pkt->stream_index, frame, 0); } else { - ret = s->oformat->write_packet(s, pkt); + ret = ffofmt(s->oformat)->write_packet(s, pkt); } if (s->pb && ret >= 0) { @@ -1078,9 +1079,9 @@ static int check_bitstream(AVFormatContext *s, FFStream *sti, AVPacket *pkt) if (!(s->flags & AVFMT_FLAG_AUTO_BSF)) return 1; - if (s->oformat->check_bitstream) { + if (ffofmt(s->oformat)->check_bitstream) { if (!sti->bitstream_checked) { - if ((ret = s->oformat->check_bitstream(s, &sti->pub, pkt)) < 0) + if ((ret = ffofmt(s->oformat)->check_bitstream(s, &sti->pub, pkt)) < 0) return ret; else if (ret == 1) sti->bitstream_checked = 1; @@ -1198,7 +1199,7 @@ int av_write_frame(AVFormatContext *s, AVPacket *in) if (!in) { if (s->oformat->flags & AVFMT_ALLOW_FLUSH) { - ret = s->oformat->write_packet(s, NULL); + ret = ffofmt(s->oformat)->write_packet(s, NULL); flush_if_needed(s); if (ret >= 0 && s->pb && s->pb->error < 0) ret = s->pb->error; @@ -1273,14 +1274,12 @@ int av_write_trailer(AVFormatContext *s) if (ret >= 0) ret = ret1; - if (s->oformat->write_trailer) { + if (ffofmt(s->oformat)->write_trailer) { if (!(s->oformat->flags & AVFMT_NOFILE) && s->pb) avio_write_marker(s->pb, AV_NOPTS_VALUE, AVIO_DATA_MARKER_TRAILER); - if (ret >= 0) { - ret = s->oformat->write_trailer(s); - } else { - s->oformat->write_trailer(s); - } + ret1 = ffofmt(s->oformat)->write_trailer(s); + if (ret >= 0) + ret = ret1; } deinit_muxer(s); @@ -1303,9 +1302,10 @@ int av_write_trailer(AVFormatContext *s) int av_get_output_timestamp(struct AVFormatContext *s, int stream, int64_t *dts, int64_t *wall) { - if (!s->oformat || !s->oformat->get_output_timestamp) + const FFOutputFormat *const of = ffofmt(s->oformat); + if (!of || !of->get_output_timestamp) return AVERROR(ENOSYS); - s->oformat->get_output_timestamp(s, stream, dts, wall); + of->get_output_timestamp(s, stream, dts, wall); return 0; } @@ -1395,7 +1395,7 @@ static int write_uncoded_frame_internal(AVFormatContext *s, int stream_index, AVPacket *pkt = si->parse_pkt; av_assert0(s->oformat); - if (!s->oformat->write_uncoded_frame) { + if (!ffofmt(s->oformat)->write_uncoded_frame) { av_frame_free(&frame); return AVERROR(ENOSYS); } @@ -1452,9 +1452,10 @@ int av_interleaved_write_uncoded_frame(AVFormatContext *s, int stream_index, int av_write_uncoded_frame_query(AVFormatContext *s, int stream_index) { - av_assert0(s->oformat); - if (!s->oformat->write_uncoded_frame) + const FFOutputFormat *const of = ffofmt(s->oformat); + av_assert0(of); + if (!of->write_uncoded_frame) return AVERROR(ENOSYS); - return s->oformat->write_uncoded_frame(s, stream_index, NULL, - AV_WRITE_UNCODED_FRAME_QUERY); + return of->write_uncoded_frame(s, stream_index, NULL, + AV_WRITE_UNCODED_FRAME_QUERY); } diff --git a/libavformat/mux.h b/libavformat/mux.h index 1bfcaf795fd..c2de45400c2 100644 --- a/libavformat/mux.h +++ b/libavformat/mux.h @@ -25,6 +25,119 @@ #include "libavcodec/packet.h" #include "avformat.h" +struct AVDeviceInfoList; + +typedef struct FFOutputFormat { + /** + * The public AVOutputFormat. See avformat.h for it. + */ + AVOutputFormat p; + /** + * size of private data so that it can be allocated in the wrapper + */ + int priv_data_size; + + /** + * Internal flags. See FF_FMT_FLAG_* in internal.h. + */ + int flags_internal; + + int (*write_header)(AVFormatContext *); + /** + * Write a packet. If AVFMT_ALLOW_FLUSH is set in flags, + * pkt can be NULL in order to flush data buffered in the muxer. + * When flushing, return 0 if there still is more data to flush, + * or 1 if everything was flushed and there is no more buffered + * data. + */ + int (*write_packet)(AVFormatContext *, AVPacket *pkt); + int (*write_trailer)(AVFormatContext *); + /** + * A format-specific function for interleavement. + * If unset, packets will be interleaved by dts. + * + * @param s An AVFormatContext for output. pkt will be added to + * resp. taken from its packet buffer. + * @param[in,out] pkt A packet to be interleaved if has_packet is set; + * also used to return packets. If no packet is returned + * (e.g. on error), pkt is blank on return. + * @param flush 1 if no further packets are available as input and + * all remaining packets should be output. + * @param has_packet If set, pkt contains a packet to be interleaved + * on input; otherwise pkt is blank on input. + * @return 1 if a packet was output, 0 if no packet could be output, + * < 0 if an error occurred + */ + int (*interleave_packet)(AVFormatContext *s, AVPacket *pkt, + int flush, int has_packet); + /** + * Test if the given codec can be stored in this container. + * + * @return 1 if the codec is supported, 0 if it is not. + * A negative number if unknown. + * MKTAG('A', 'P', 'I', 'C') if the codec is only supported as AV_DISPOSITION_ATTACHED_PIC + */ + int (*query_codec)(enum AVCodecID id, int std_compliance); + + void (*get_output_timestamp)(AVFormatContext *s, int stream, + int64_t *dts, int64_t *wall); + /** + * Allows sending messages from application to device. + */ + int (*control_message)(AVFormatContext *s, int type, + void *data, size_t data_size); + + /** + * Write an uncoded AVFrame. + * + * See av_write_uncoded_frame() for details. + * + * The library will free *frame afterwards, but the muxer can prevent it + * by setting the pointer to NULL. + */ + int (*write_uncoded_frame)(AVFormatContext *, int stream_index, + AVFrame **frame, unsigned flags); + /** + * Returns device list with it properties. + * @see avdevice_list_devices() for more details. + */ + int (*get_device_list)(AVFormatContext *s, struct AVDeviceInfoList *device_list); + /** + * Initialize format. May allocate data here, and set any AVFormatContext or + * AVStream parameters that need to be set before packets are sent. + * This method must not write output. + * + * Return 0 if streams were fully configured, 1 if not, negative AVERROR on failure + * + * Any allocations made here must be freed in deinit(). + */ + int (*init)(AVFormatContext *); + /** + * Deinitialize format. If present, this is called whenever the muxer is being + * destroyed, regardless of whether or not the header has been written. + * + * If a trailer is being written, this is called after write_trailer(). + * + * This is called if init() fails as well. + */ + void (*deinit)(AVFormatContext *); + /** + * 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)(AVFormatContext *s, AVStream *st, + const AVPacket *pkt); +} FFOutputFormat; + +static inline const FFOutputFormat *ffofmt(const AVOutputFormat *fmt) +{ + return (const FFOutputFormat*)fmt; +} + /** * Add packet to an AVFormatContext's packet_buffer list, determining its * interleaved position using compare() function argument. diff --git a/libavformat/mux_utils.c b/libavformat/mux_utils.c index 55e58ae9d68..3e63b8039af 100644 --- a/libavformat/mux_utils.c +++ b/libavformat/mux_utils.c @@ -45,8 +45,8 @@ int avformat_query_codec(const AVOutputFormat *ofmt, enum AVCodecID codec_id, { if (ofmt) { unsigned int codec_tag; - if (ofmt->query_codec) - return ofmt->query_codec(codec_id, std_compliance); + if (ffofmt(ofmt)->query_codec) + return ffofmt(ofmt)->query_codec(codec_id, std_compliance); else if (ofmt->codec_tag) return !!av_codec_get_tag2(ofmt->codec_tag, codec_id, &codec_tag); else if (codec_id == ofmt->video_codec || diff --git a/libavformat/mxfenc.c b/libavformat/mxfenc.c index 58c551c83c3..a29d678098c 100644 --- a/libavformat/mxfenc.c +++ b/libavformat/mxfenc.c @@ -61,8 +61,11 @@ #include "config.h" #include "version.h" -extern const AVOutputFormat ff_mxf_d10_muxer; -extern const AVOutputFormat ff_mxf_opatom_muxer; +extern const FFOutputFormat ff_mxf_d10_muxer; +extern const FFOutputFormat ff_mxf_opatom_muxer; + +#define IS_D10(s) ((s)->oformat == &ff_mxf_d10_muxer.p) +#define IS_OPATOM(s) ((s)->oformat == &ff_mxf_opatom_muxer.p) #define EDIT_UNITS_PER_BODY 250 #define KAG_SIZE 512 @@ -667,7 +670,7 @@ static void mxf_write_preface(AVFormatContext *s) // operational pattern mxf_write_local_tag(s, 16, 0x3B09); - if (s->oformat == &ff_mxf_opatom_muxer) + if (IS_OPATOM(s)) avio_write(pb, opatom_ul, 16); else avio_write(pb, op1a_ul, 16); @@ -765,7 +768,7 @@ static void mxf_write_identification(AVFormatContext *s) AVDictionaryEntry *product_entry = av_dict_get(s->metadata, "product_name", NULL, 0); AVDictionaryEntry *version_entry = av_dict_get(s->metadata, "product_version", NULL, 0); const char *company = com_entry ? com_entry->value : "FFmpeg"; - const char *product = product_entry ? product_entry->value : s->oformat != &ff_mxf_opatom_muxer ? "OP1a Muxer" : "OPAtom Muxer"; + const char *product = product_entry ? product_entry->value : !IS_OPATOM(s) ? "OP1a Muxer" : "OPAtom Muxer"; const char *platform = s->flags & AVFMT_FLAG_BITEXACT ? "Lavf" : PLATFORM_IDENT; const char *version = version_entry ? version_entry->value : s->flags & AVFMT_FLAG_BITEXACT ? "0.0.0" : @@ -866,7 +869,7 @@ static void mxf_write_track(AVFormatContext *s, AVStream *st, MXFPackage *packag // write edit rate mxf_write_local_tag(s, 8, 0x4B01); - if (st == mxf->timecode_track && s->oformat == &ff_mxf_opatom_muxer) { + if (st == mxf->timecode_track && IS_OPATOM(s)) { avio_wb32(pb, mxf->tc.rate.num); avio_wb32(pb, mxf->tc.rate.den); } else { @@ -902,7 +905,7 @@ static void mxf_write_common_fields(AVFormatContext *s, AVStream *st) // write duration mxf_write_local_tag(s, 8, 0x0202); - if (st != mxf->timecode_track && s->oformat == &ff_mxf_opatom_muxer && st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) { + if (st != mxf->timecode_track && IS_OPATOM(s) && st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) { avio_wb64(pb, mxf->body_offset / mxf->edit_unit_byte_count); } else { avio_wb64(pb, mxf->duration); @@ -1066,7 +1069,7 @@ static int64_t mxf_write_generic_desc(AVFormatContext *s, AVStream *st, const UI avio_wb32(pb, st->index+2); mxf_write_local_tag(s, 8, 0x3001); - if (s->oformat == &ff_mxf_d10_muxer) { + if (IS_D10(s)) { avio_wb32(pb, mxf->time_base.den); avio_wb32(pb, mxf->time_base.num); } else { @@ -1138,7 +1141,7 @@ static int64_t mxf_write_cdci_common(AVFormatContext *s, AVStream *st, const UID mxf_write_local_tag(s, 4, 0x3202); avio_wb32(pb, stored_height>>sc->interlaced); - if (s->oformat == &ff_mxf_d10_muxer) { + if (IS_D10(s)) { //Stored F2 Offset mxf_write_local_tag(s, 4, 0x3216); avio_wb32(pb, 0); @@ -1435,7 +1438,7 @@ static int64_t mxf_write_generic_sound_common(AVFormatContext *s, AVStream *st, int show_warnings = !mxf->footer_partition_offset; int64_t pos = mxf_write_generic_desc(s, st, key); - if (s->oformat == &ff_mxf_opatom_muxer) { + if (IS_OPATOM(s)) { mxf_write_local_tag(s, 8, 0x3002); avio_wb64(pb, mxf->body_offset / mxf->edit_unit_byte_count); } @@ -1449,19 +1452,19 @@ static int64_t mxf_write_generic_sound_common(AVFormatContext *s, AVStream *st, avio_wb32(pb, st->codecpar->sample_rate); avio_wb32(pb, 1); - if (s->oformat == &ff_mxf_d10_muxer) { + if (IS_D10(s)) { mxf_write_local_tag(s, 1, 0x3D04); avio_w8(pb, 0); } mxf_write_local_tag(s, 4, 0x3D07); if (mxf->channel_count == -1) { - if (show_warnings && (s->oformat == &ff_mxf_d10_muxer) && + if (show_warnings && IS_D10(s) && (st->codecpar->ch_layout.nb_channels != 4) && (st->codecpar->ch_layout.nb_channels != 8)) av_log(s, AV_LOG_WARNING, "the number of audio channels shall be 4 or 8 : the output will not comply to MXF D-10 specs, use -d10_channelcount to fix this\n"); avio_wb32(pb, st->codecpar->ch_layout.nb_channels); - } else if (s->oformat == &ff_mxf_d10_muxer) { + } else if (IS_D10(s)) { if (show_warnings && (mxf->channel_count < st->codecpar->ch_layout.nb_channels)) av_log(s, AV_LOG_WARNING, "d10_channelcount < actual number of audio channels : some channels will be discarded\n"); if (show_warnings && (mxf->channel_count != 4) && (mxf->channel_count != 8)) @@ -1961,7 +1964,7 @@ static int mxf_write_partition(AVFormatContext *s, int bodysid, avio_wb32(pb, index_byte_count ? indexsid : 0); // indexSID // BodyOffset - if (bodysid && mxf->edit_units_count && mxf->body_partitions_count && s->oformat != &ff_mxf_opatom_muxer) + if (bodysid && mxf->edit_units_count && mxf->body_partitions_count && !IS_OPATOM(s)) avio_wb64(pb, mxf->body_offset); else avio_wb64(pb, 0); @@ -1969,7 +1972,7 @@ static int mxf_write_partition(AVFormatContext *s, int bodysid, avio_wb32(pb, bodysid); // bodySID // operational pattern - if (s->oformat == &ff_mxf_opatom_muxer) + if (IS_OPATOM(s)) avio_write(pb, opatom_ul, 16); else avio_write(pb, op1a_ul, 16); @@ -2436,7 +2439,7 @@ static int mxf_parse_mpeg2_frame(AVFormatContext *s, AVStream *st, } } } - if (s->oformat != &ff_mxf_d10_muxer) { + if (!IS_D10(s)) { const UID *codec_ul = mxf_get_mpeg2_codec_ul(st->codecpar); if (!codec_ul) return 0; @@ -2533,7 +2536,7 @@ static int mxf_init(AVFormatContext *s) uint8_t present[FF_ARRAY_ELEMS(mxf_essence_container_uls)] = {0}; int64_t timestamp = 0; - if (s->oformat == &ff_mxf_opatom_muxer && s->nb_streams !=1) { + if (IS_OPATOM(s) && s->nb_streams != 1) { av_log(s, AV_LOG_ERROR, "there must be exactly one stream for mxf opatom\n"); return -1; } @@ -2549,7 +2552,7 @@ static int mxf_init(AVFormatContext *s) st->priv_data = sc; sc->index = -1; - if (((i == 0) ^ (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO)) && s->oformat != &ff_mxf_opatom_muxer) { + if (((i == 0) ^ (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO)) && !IS_OPATOM(s)) { av_log(s, AV_LOG_ERROR, "there must be exactly one video stream and it must be the first one\n"); return -1; } @@ -2593,12 +2596,12 @@ static int mxf_init(AVFormatContext *s) sc->video_bit_rate = st->codecpar->bit_rate; - if (s->oformat == &ff_mxf_d10_muxer || + if (IS_D10(s) || st->codecpar->codec_id == AV_CODEC_ID_DNXHD || st->codecpar->codec_id == AV_CODEC_ID_DVVIDEO) mxf->cbr_index = 1; - if (s->oformat == &ff_mxf_d10_muxer) { + if (IS_D10(s)) { int ntsc = mxf->time_base.den != 25; int ul_index; @@ -2636,7 +2639,7 @@ static int mxf_init(AVFormatContext *s) return -1; } avpriv_set_pts_info(st, 64, 1, st->codecpar->sample_rate); - if (s->oformat == &ff_mxf_d10_muxer) { + if (IS_D10(s)) { if (st->index != 1) { av_log(s, AV_LOG_ERROR, "MXF D-10 only support one audio track\n"); return -1; @@ -2648,7 +2651,7 @@ static int mxf_init(AVFormatContext *s) sc->index = INDEX_D10_AUDIO; sc->container_ul = ((MXFStreamContext*)s->streams[0]->priv_data)->container_ul; sc->frame_size = 4 + 8 * av_rescale_rnd(st->codecpar->sample_rate, mxf->time_base.num, mxf->time_base.den, AV_ROUND_UP) * 4; - } else if (s->oformat == &ff_mxf_opatom_muxer) { + } else if (IS_OPATOM(s)) { AVRational tbc = av_inv_q(mxf->audio_edit_rate); if (st->codecpar->codec_id != AV_CODEC_ID_PCM_S16LE && @@ -2707,7 +2710,7 @@ 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) { + if (IS_OPATOM(s) && 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 @@ -2720,7 +2723,7 @@ static int mxf_init(AVFormatContext *s) present[sc->index]++; } - if (s->oformat == &ff_mxf_d10_muxer || s->oformat == &ff_mxf_opatom_muxer) { + if (IS_D10(s) || IS_OPATOM(s)) { mxf->essence_container_count = 1; } @@ -2889,7 +2892,7 @@ static void mxf_compute_edit_unit_byte_count(AVFormatContext *s) MXFContext *mxf = s->priv_data; int i; - if (s->oformat == &ff_mxf_opatom_muxer) { + if (IS_OPATOM(s)) { MXFStreamContext *sc = s->streams[0]->priv_data; mxf->edit_unit_byte_count = sc->frame_size; return; @@ -2915,7 +2918,7 @@ static int mxf_write_packet(AVFormatContext *s, AVPacket *pkt) int err; if (!mxf->header_written && pkt->stream_index != 0 && - s->oformat != &ff_mxf_opatom_muxer) { + !IS_OPATOM(s)) { av_log(s, AV_LOG_ERROR, "Received non-video packet before " "header has been written\n"); return AVERROR_INVALIDDATA; @@ -2967,7 +2970,7 @@ static int mxf_write_packet(AVFormatContext *s, AVPacket *pkt) mxf_compute_edit_unit_byte_count(s); } - if (s->oformat == &ff_mxf_opatom_muxer) + if (IS_OPATOM(s)) return mxf_write_opatom_packet(s, pkt, &ie); if (!mxf->header_written) { @@ -3015,8 +3018,7 @@ static int mxf_write_packet(AVFormatContext *s, AVPacket *pkt) mxf_write_klv_fill(s); avio_write(pb, sc->track_essence_element_key, 16); // write key - if (s->oformat == &ff_mxf_d10_muxer && - st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) { + if (IS_D10(s) && st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) { mxf_write_d10_audio_packet(s, st, pkt); } else { klv_encode_ber4_length(pb, pkt->size); // write length @@ -3037,7 +3039,7 @@ static void mxf_write_random_index_pack(AVFormatContext *s) avio_write(pb, ff_mxf_random_index_pack_key, 16); klv_encode_ber_length(pb, 28 + 12LL*mxf->body_partitions_count); - if (mxf->edit_unit_byte_count && s->oformat != &ff_mxf_opatom_muxer) + if (mxf->edit_unit_byte_count && !IS_OPATOM(s)) avio_wb32(pb, 1); // BodySID of header partition else avio_wb32(pb, 0); @@ -3061,7 +3063,7 @@ static int mxf_write_footer(AVFormatContext *s) int i, err; if (!mxf->header_written || - (s->oformat == &ff_mxf_opatom_muxer && !mxf->body_partition_offset)) { + (IS_OPATOM(s) && !mxf->body_partition_offset)) { /* reason could be invalid options/not supported codec/out of memory */ return AVERROR_UNKNOWN; } @@ -3070,7 +3072,7 @@ static int mxf_write_footer(AVFormatContext *s) mxf_write_klv_fill(s); mxf->footer_partition_offset = avio_tell(pb); - if (mxf->edit_unit_byte_count && s->oformat != &ff_mxf_opatom_muxer) { // no need to repeat index + if (mxf->edit_unit_byte_count && !IS_OPATOM(s)) { // no need to repeat index if ((err = mxf_write_partition(s, 0, 0, footer_partition_key, 0)) < 0) return err; } else { @@ -3084,7 +3086,7 @@ static int mxf_write_footer(AVFormatContext *s) mxf_write_random_index_pack(s); if (s->pb->seekable & AVIO_SEEKABLE_NORMAL) { - if (s->oformat == &ff_mxf_opatom_muxer) { + if (IS_OPATOM(s)) { /* rewrite body partition to update lengths */ avio_seek(pb, mxf->body_partition_offset[0], SEEK_SET); if ((err = mxf_write_opatom_body_partition(s)) < 0) @@ -3092,7 +3094,7 @@ static int mxf_write_footer(AVFormatContext *s) } avio_seek(pb, 0, SEEK_SET); - if (mxf->edit_unit_byte_count && s->oformat != &ff_mxf_opatom_muxer) { + if (mxf->edit_unit_byte_count && !IS_OPATOM(s)) { if ((err = mxf_write_partition(s, 1, 2, header_closed_partition_key, 1)) < 0) return err; mxf_write_klv_fill(s); @@ -3260,52 +3262,52 @@ static const AVClass mxf_opatom_muxer_class = { .version = LIBAVUTIL_VERSION_INT, }; -const AVOutputFormat ff_mxf_muxer = { - .name = "mxf", - .long_name = NULL_IF_CONFIG_SMALL("MXF (Material eXchange Format)"), - .mime_type = "application/mxf", - .extensions = "mxf", +const FFOutputFormat ff_mxf_muxer = { + .p.name = "mxf", + .p.long_name = NULL_IF_CONFIG_SMALL("MXF (Material eXchange Format)"), + .p.mime_type = "application/mxf", + .p.extensions = "mxf", .priv_data_size = sizeof(MXFContext), - .audio_codec = AV_CODEC_ID_PCM_S16LE, - .video_codec = AV_CODEC_ID_MPEG2VIDEO, + .p.audio_codec = AV_CODEC_ID_PCM_S16LE, + .p.video_codec = AV_CODEC_ID_MPEG2VIDEO, .init = mxf_init, .write_packet = mxf_write_packet, .write_trailer = mxf_write_footer, .deinit = mxf_deinit, - .flags = AVFMT_NOTIMESTAMPS, + .p.flags = AVFMT_NOTIMESTAMPS, .interleave_packet = mxf_interleave, - .priv_class = &mxf_muxer_class, + .p.priv_class = &mxf_muxer_class, }; -const AVOutputFormat ff_mxf_d10_muxer = { - .name = "mxf_d10", - .long_name = NULL_IF_CONFIG_SMALL("MXF (Material eXchange Format) D-10 Mapping"), - .mime_type = "application/mxf", +const FFOutputFormat ff_mxf_d10_muxer = { + .p.name = "mxf_d10", + .p.long_name = NULL_IF_CONFIG_SMALL("MXF (Material eXchange Format) D-10 Mapping"), + .p.mime_type = "application/mxf", .priv_data_size = sizeof(MXFContext), - .audio_codec = AV_CODEC_ID_PCM_S16LE, - .video_codec = AV_CODEC_ID_MPEG2VIDEO, + .p.audio_codec = AV_CODEC_ID_PCM_S16LE, + .p.video_codec = AV_CODEC_ID_MPEG2VIDEO, .init = mxf_init, .write_packet = mxf_write_packet, .write_trailer = mxf_write_footer, .deinit = mxf_deinit, - .flags = AVFMT_NOTIMESTAMPS, + .p.flags = AVFMT_NOTIMESTAMPS, .interleave_packet = mxf_interleave, - .priv_class = &mxf_d10_muxer_class, + .p.priv_class = &mxf_d10_muxer_class, }; -const AVOutputFormat ff_mxf_opatom_muxer = { - .name = "mxf_opatom", - .long_name = NULL_IF_CONFIG_SMALL("MXF (Material eXchange Format) Operational Pattern Atom"), - .mime_type = "application/mxf", - .extensions = "mxf", +const FFOutputFormat ff_mxf_opatom_muxer = { + .p.name = "mxf_opatom", + .p.long_name = NULL_IF_CONFIG_SMALL("MXF (Material eXchange Format) Operational Pattern Atom"), + .p.mime_type = "application/mxf", + .p.extensions = "mxf", .priv_data_size = sizeof(MXFContext), - .audio_codec = AV_CODEC_ID_PCM_S16LE, - .video_codec = AV_CODEC_ID_DNXHD, + .p.audio_codec = AV_CODEC_ID_PCM_S16LE, + .p.video_codec = AV_CODEC_ID_DNXHD, .init = mxf_init, .write_packet = mxf_write_packet, .write_trailer = mxf_write_footer, .deinit = mxf_deinit, - .flags = AVFMT_NOTIMESTAMPS, + .p.flags = AVFMT_NOTIMESTAMPS, .interleave_packet = mxf_interleave, - .priv_class = &mxf_opatom_muxer_class, + .p.priv_class = &mxf_opatom_muxer_class, }; diff --git a/libavformat/nullenc.c b/libavformat/nullenc.c index 3deca5a7eda..60bde2a0690 100644 --- a/libavformat/nullenc.c +++ b/libavformat/nullenc.c @@ -27,12 +27,12 @@ static int null_write_packet(struct AVFormatContext *s, AVPacket *pkt) return 0; } -const AVOutputFormat ff_null_muxer = { - .name = "null", - .long_name = NULL_IF_CONFIG_SMALL("raw null video"), - .audio_codec = AV_NE(AV_CODEC_ID_PCM_S16BE, AV_CODEC_ID_PCM_S16LE), - .video_codec = AV_CODEC_ID_WRAPPED_AVFRAME, +const FFOutputFormat ff_null_muxer = { + .p.name = "null", + .p.long_name = NULL_IF_CONFIG_SMALL("raw null video"), + .p.audio_codec = AV_NE(AV_CODEC_ID_PCM_S16BE, AV_CODEC_ID_PCM_S16LE), + .p.video_codec = AV_CODEC_ID_WRAPPED_AVFRAME, .write_packet = null_write_packet, - .flags = AVFMT_VARIABLE_FPS | AVFMT_NOFILE | AVFMT_NOTIMESTAMPS, + .p.flags = AVFMT_VARIABLE_FPS | AVFMT_NOFILE | AVFMT_NOTIMESTAMPS, .interleave_packet = ff_interleave_packet_passthrough, }; diff --git a/libavformat/nutenc.c b/libavformat/nutenc.c index ff81ee34aa0..a5198c7ca9f 100644 --- a/libavformat/nutenc.c +++ b/libavformat/nutenc.c @@ -1253,20 +1253,20 @@ static const AVClass class = { .version = LIBAVUTIL_VERSION_INT, }; -const AVOutputFormat ff_nut_muxer = { - .name = "nut", - .long_name = NULL_IF_CONFIG_SMALL("NUT"), - .mime_type = "video/x-nut", - .extensions = "nut", +const FFOutputFormat ff_nut_muxer = { + .p.name = "nut", + .p.long_name = NULL_IF_CONFIG_SMALL("NUT"), + .p.mime_type = "video/x-nut", + .p.extensions = "nut", .priv_data_size = sizeof(NUTContext), - .audio_codec = CONFIG_LIBVORBIS ? AV_CODEC_ID_VORBIS : + .p.audio_codec = CONFIG_LIBVORBIS ? AV_CODEC_ID_VORBIS : CONFIG_LIBMP3LAME ? AV_CODEC_ID_MP3 : AV_CODEC_ID_MP2, - .video_codec = AV_CODEC_ID_MPEG4, + .p.video_codec = AV_CODEC_ID_MPEG4, .write_header = nut_write_header, .write_packet = nut_write_packet, .write_trailer = nut_write_trailer, .deinit = nut_write_deinit, - .flags = AVFMT_GLOBALHEADER | AVFMT_VARIABLE_FPS, - .codec_tag = ff_nut_codec_tags, - .priv_class = &class, + .p.flags = AVFMT_GLOBALHEADER | AVFMT_VARIABLE_FPS, + .p.codec_tag = ff_nut_codec_tags, + .p.priv_class = &class, }; diff --git a/libavformat/oggenc.c b/libavformat/oggenc.c index 458b2a9bdc4..2e582d0754c 100644 --- a/libavformat/oggenc.c +++ b/libavformat/oggenc.c @@ -33,6 +33,7 @@ #include "avformat.h" #include "avio_internal.h" #include "internal.h" +#include "mux.h" #include "version.h" #include "vorbiscomment.h" @@ -746,11 +747,11 @@ static void ogg_free(AVFormatContext *s) } #if CONFIG_OGG_MUXER -const AVOutputFormat ff_ogg_muxer = { - .name = "ogg", - .long_name = NULL_IF_CONFIG_SMALL("Ogg"), - .mime_type = "application/ogg", - .extensions = "ogg" +const FFOutputFormat ff_ogg_muxer = { + .p.name = "ogg", + .p.long_name = NULL_IF_CONFIG_SMALL("Ogg"), + .p.mime_type = "application/ogg", + .p.extensions = "ogg" #if !CONFIG_OGV_MUXER ",ogv" #endif @@ -762,90 +763,90 @@ const AVOutputFormat ff_ogg_muxer = { #endif , .priv_data_size = sizeof(OGGContext), - .audio_codec = CONFIG_LIBVORBIS_ENCODER ? + .p.audio_codec = CONFIG_LIBVORBIS_ENCODER ? AV_CODEC_ID_VORBIS : AV_CODEC_ID_FLAC, - .video_codec = AV_CODEC_ID_THEORA, + .p.video_codec = AV_CODEC_ID_THEORA, .init = ogg_init, .write_header = ogg_write_header, .write_packet = ogg_write_packet, .write_trailer = ogg_write_trailer, .deinit = ogg_free, - .flags = AVFMT_TS_NEGATIVE | AVFMT_TS_NONSTRICT | AVFMT_ALLOW_FLUSH, - .priv_class = &ogg_muxer_class, + .p.flags = AVFMT_TS_NEGATIVE | AVFMT_TS_NONSTRICT | AVFMT_ALLOW_FLUSH, + .p.priv_class = &ogg_muxer_class, }; #endif #if CONFIG_OGA_MUXER -const AVOutputFormat ff_oga_muxer = { - .name = "oga", - .long_name = NULL_IF_CONFIG_SMALL("Ogg Audio"), - .mime_type = "audio/ogg", - .extensions = "oga", +const FFOutputFormat ff_oga_muxer = { + .p.name = "oga", + .p.long_name = NULL_IF_CONFIG_SMALL("Ogg Audio"), + .p.mime_type = "audio/ogg", + .p.extensions = "oga", .priv_data_size = sizeof(OGGContext), - .audio_codec = AV_CODEC_ID_FLAC, + .p.audio_codec = AV_CODEC_ID_FLAC, .init = ogg_init, .write_header = ogg_write_header, .write_packet = ogg_write_packet, .write_trailer = ogg_write_trailer, .deinit = ogg_free, - .flags = AVFMT_TS_NEGATIVE | AVFMT_ALLOW_FLUSH, - .priv_class = &ogg_muxer_class, + .p.flags = AVFMT_TS_NEGATIVE | AVFMT_ALLOW_FLUSH, + .p.priv_class = &ogg_muxer_class, }; #endif #if CONFIG_OGV_MUXER -const AVOutputFormat ff_ogv_muxer = { - .name = "ogv", - .long_name = NULL_IF_CONFIG_SMALL("Ogg Video"), - .mime_type = "video/ogg", - .extensions = "ogv", +const FFOutputFormat ff_ogv_muxer = { + .p.name = "ogv", + .p.long_name = NULL_IF_CONFIG_SMALL("Ogg Video"), + .p.mime_type = "video/ogg", + .p.extensions = "ogv", .priv_data_size = sizeof(OGGContext), - .audio_codec = CONFIG_LIBVORBIS_ENCODER ? + .p.audio_codec = CONFIG_LIBVORBIS_ENCODER ? AV_CODEC_ID_VORBIS : AV_CODEC_ID_FLAC, - .video_codec = CONFIG_LIBTHEORA_ENCODER ? + .p.video_codec = CONFIG_LIBTHEORA_ENCODER ? AV_CODEC_ID_THEORA : AV_CODEC_ID_VP8, .init = ogg_init, .write_header = ogg_write_header, .write_packet = ogg_write_packet, .write_trailer = ogg_write_trailer, .deinit = ogg_free, - .flags = AVFMT_TS_NEGATIVE | AVFMT_TS_NONSTRICT | AVFMT_ALLOW_FLUSH, - .priv_class = &ogg_muxer_class, + .p.flags = AVFMT_TS_NEGATIVE | AVFMT_TS_NONSTRICT | AVFMT_ALLOW_FLUSH, + .p.priv_class = &ogg_muxer_class, }; #endif #if CONFIG_SPX_MUXER -const AVOutputFormat ff_spx_muxer = { - .name = "spx", - .long_name = NULL_IF_CONFIG_SMALL("Ogg Speex"), - .mime_type = "audio/ogg", - .extensions = "spx", +const FFOutputFormat ff_spx_muxer = { + .p.name = "spx", + .p.long_name = NULL_IF_CONFIG_SMALL("Ogg Speex"), + .p.mime_type = "audio/ogg", + .p.extensions = "spx", .priv_data_size = sizeof(OGGContext), - .audio_codec = AV_CODEC_ID_SPEEX, + .p.audio_codec = AV_CODEC_ID_SPEEX, .init = ogg_init, .write_header = ogg_write_header, .write_packet = ogg_write_packet, .write_trailer = ogg_write_trailer, .deinit = ogg_free, - .flags = AVFMT_TS_NEGATIVE | AVFMT_ALLOW_FLUSH, - .priv_class = &ogg_muxer_class, + .p.flags = AVFMT_TS_NEGATIVE | AVFMT_ALLOW_FLUSH, + .p.priv_class = &ogg_muxer_class, }; #endif #if CONFIG_OPUS_MUXER -const AVOutputFormat ff_opus_muxer = { - .name = "opus", - .long_name = NULL_IF_CONFIG_SMALL("Ogg Opus"), - .mime_type = "audio/ogg", - .extensions = "opus", +const FFOutputFormat ff_opus_muxer = { + .p.name = "opus", + .p.long_name = NULL_IF_CONFIG_SMALL("Ogg Opus"), + .p.mime_type = "audio/ogg", + .p.extensions = "opus", .priv_data_size = sizeof(OGGContext), - .audio_codec = AV_CODEC_ID_OPUS, + .p.audio_codec = AV_CODEC_ID_OPUS, .init = ogg_init, .write_header = ogg_write_header, .write_packet = ogg_write_packet, .write_trailer = ogg_write_trailer, .deinit = ogg_free, - .flags = AVFMT_TS_NEGATIVE | AVFMT_ALLOW_FLUSH, - .priv_class = &ogg_muxer_class, + .p.flags = AVFMT_TS_NEGATIVE | AVFMT_ALLOW_FLUSH, + .p.priv_class = &ogg_muxer_class, }; #endif diff --git a/libavformat/omaenc.c b/libavformat/omaenc.c index 246f5195fb9..6d0b47465d1 100644 --- a/libavformat/omaenc.c +++ b/libavformat/omaenc.c @@ -24,6 +24,7 @@ #include "avio_internal.h" #include "id3v2.h" #include "internal.h" +#include "mux.h" #include "oma.h" #include "rawenc.h" @@ -91,14 +92,14 @@ static av_cold int oma_write_header(AVFormatContext *s) return 0; } -const AVOutputFormat ff_oma_muxer = { - .name = "oma", - .long_name = NULL_IF_CONFIG_SMALL("Sony OpenMG audio"), - .mime_type = "audio/x-oma", - .extensions = "oma", - .audio_codec = AV_CODEC_ID_ATRAC3, +const FFOutputFormat ff_oma_muxer = { + .p.name = "oma", + .p.long_name = NULL_IF_CONFIG_SMALL("Sony OpenMG audio"), + .p.mime_type = "audio/x-oma", + .p.extensions = "oma", + .p.audio_codec = AV_CODEC_ID_ATRAC3, .write_header = oma_write_header, .write_packet = ff_raw_write_packet, - .codec_tag = ff_oma_codec_tags_list, - .flags = AVFMT_NOTIMESTAMPS, + .p.codec_tag = ff_oma_codec_tags_list, + .p.flags = AVFMT_NOTIMESTAMPS, }; diff --git a/libavformat/pcmenc.c b/libavformat/pcmenc.c index 0cf497989af..7f716443081 100644 --- a/libavformat/pcmenc.c +++ b/libavformat/pcmenc.c @@ -22,18 +22,19 @@ #include "config_components.h" #include "avformat.h" +#include "mux.h" #include "rawenc.h" #define PCMDEF_0(name_, long_name_, ext, codec) #define PCMDEF_1(name_, long_name_, ext, codec) \ -const AVOutputFormat ff_pcm_ ## name_ ## _muxer = { \ - .name = #name_, \ - .long_name = NULL_IF_CONFIG_SMALL(long_name_), \ - .extensions = ext, \ - .audio_codec = codec, \ - .video_codec = AV_CODEC_ID_NONE, \ +const FFOutputFormat ff_pcm_ ## name_ ## _muxer = { \ + .p.name = #name_, \ + .p.long_name = NULL_IF_CONFIG_SMALL(long_name_), \ + .p.extensions = ext, \ + .p.audio_codec = codec, \ + .p.video_codec = AV_CODEC_ID_NONE, \ + .p.flags = AVFMT_NOTIMESTAMPS, \ .write_packet = ff_raw_write_packet, \ - .flags = AVFMT_NOTIMESTAMPS, \ }; #define PCMDEF_2(name, long_name, ext, codec, enabled) \ PCMDEF_ ## enabled(name, long_name, ext, codec) diff --git a/libavformat/rawenc.c b/libavformat/rawenc.c index 267fce252d1..78fadda9679 100644 --- a/libavformat/rawenc.c +++ b/libavformat/rawenc.c @@ -59,16 +59,16 @@ static int force_one_stream(AVFormatContext *s) /* Note: Do not forget to add new entries to the Makefile as well. */ #if CONFIG_AC3_MUXER -const AVOutputFormat ff_ac3_muxer = { - .name = "ac3", - .long_name = NULL_IF_CONFIG_SMALL("raw AC-3"), - .mime_type = "audio/x-ac3", - .extensions = "ac3", - .audio_codec = AV_CODEC_ID_AC3, - .video_codec = AV_CODEC_ID_NONE, +const FFOutputFormat ff_ac3_muxer = { + .p.name = "ac3", + .p.long_name = NULL_IF_CONFIG_SMALL("raw AC-3"), + .p.mime_type = "audio/x-ac3", + .p.extensions = "ac3", + .p.audio_codec = AV_CODEC_ID_AC3, + .p.video_codec = AV_CODEC_ID_NONE, .init = force_one_stream, .write_packet = ff_raw_write_packet, - .flags = AVFMT_NOTIMESTAMPS, + .p.flags = AVFMT_NOTIMESTAMPS, }; #endif @@ -92,266 +92,266 @@ static int adx_write_trailer(AVFormatContext *s) return 0; } -const AVOutputFormat ff_adx_muxer = { - .name = "adx", - .long_name = NULL_IF_CONFIG_SMALL("CRI ADX"), - .extensions = "adx", - .audio_codec = AV_CODEC_ID_ADPCM_ADX, - .video_codec = AV_CODEC_ID_NONE, +const FFOutputFormat ff_adx_muxer = { + .p.name = "adx", + .p.long_name = NULL_IF_CONFIG_SMALL("CRI ADX"), + .p.extensions = "adx", + .p.audio_codec = AV_CODEC_ID_ADPCM_ADX, + .p.video_codec = AV_CODEC_ID_NONE, .init = force_one_stream, .write_packet = ff_raw_write_packet, .write_trailer = adx_write_trailer, - .flags = AVFMT_NOTIMESTAMPS, + .p.flags = AVFMT_NOTIMESTAMPS, }; #endif #if CONFIG_APTX_MUXER -const AVOutputFormat ff_aptx_muxer = { - .name = "aptx", - .long_name = NULL_IF_CONFIG_SMALL("raw aptX (Audio Processing Technology for Bluetooth)"), - .extensions = "aptx", - .audio_codec = AV_CODEC_ID_APTX, - .video_codec = AV_CODEC_ID_NONE, +const FFOutputFormat ff_aptx_muxer = { + .p.name = "aptx", + .p.long_name = NULL_IF_CONFIG_SMALL("raw aptX (Audio Processing Technology for Bluetooth)"), + .p.extensions = "aptx", + .p.audio_codec = AV_CODEC_ID_APTX, + .p.video_codec = AV_CODEC_ID_NONE, .init = force_one_stream, .write_packet = ff_raw_write_packet, - .flags = AVFMT_NOTIMESTAMPS, + .p.flags = AVFMT_NOTIMESTAMPS, }; #endif #if CONFIG_APTX_HD_MUXER -const AVOutputFormat ff_aptx_hd_muxer = { - .name = "aptx_hd", - .long_name = NULL_IF_CONFIG_SMALL("raw aptX HD (Audio Processing Technology for Bluetooth)"), - .extensions = "aptxhd", - .audio_codec = AV_CODEC_ID_APTX_HD, - .video_codec = AV_CODEC_ID_NONE, +const FFOutputFormat ff_aptx_hd_muxer = { + .p.name = "aptx_hd", + .p.long_name = NULL_IF_CONFIG_SMALL("raw aptX HD (Audio Processing Technology for Bluetooth)"), + .p.extensions = "aptxhd", + .p.audio_codec = AV_CODEC_ID_APTX_HD, + .p.video_codec = AV_CODEC_ID_NONE, .init = force_one_stream, .write_packet = ff_raw_write_packet, - .flags = AVFMT_NOTIMESTAMPS, + .p.flags = AVFMT_NOTIMESTAMPS, }; #endif #if CONFIG_AVS2_MUXER -const AVOutputFormat ff_avs2_muxer = { - .name = "avs2", - .long_name = NULL_IF_CONFIG_SMALL("raw AVS2-P2/IEEE1857.4 video"), - .extensions = "avs,avs2", - .audio_codec = AV_CODEC_ID_NONE, - .video_codec = AV_CODEC_ID_AVS2, +const FFOutputFormat ff_avs2_muxer = { + .p.name = "avs2", + .p.long_name = NULL_IF_CONFIG_SMALL("raw AVS2-P2/IEEE1857.4 video"), + .p.extensions = "avs,avs2", + .p.audio_codec = AV_CODEC_ID_NONE, + .p.video_codec = AV_CODEC_ID_AVS2, .init = force_one_stream, .write_packet = ff_raw_write_packet, - .flags = AVFMT_NOTIMESTAMPS, + .p.flags = AVFMT_NOTIMESTAMPS, }; #endif #if CONFIG_AVS3_MUXER -const AVOutputFormat ff_avs3_muxer = { - .name = "avs3", - .long_name = NULL_IF_CONFIG_SMALL("AVS3-P2/IEEE1857.10"), - .extensions = "avs3", - .audio_codec = AV_CODEC_ID_NONE, - .video_codec = AV_CODEC_ID_AVS3, +const FFOutputFormat ff_avs3_muxer = { + .p.name = "avs3", + .p.long_name = NULL_IF_CONFIG_SMALL("AVS3-P2/IEEE1857.10"), + .p.extensions = "avs3", + .p.audio_codec = AV_CODEC_ID_NONE, + .p.video_codec = AV_CODEC_ID_AVS3, .init = force_one_stream, .write_packet = ff_raw_write_packet, - .flags = AVFMT_NOTIMESTAMPS, + .p.flags = AVFMT_NOTIMESTAMPS, }; #endif #if CONFIG_CAVSVIDEO_MUXER -const AVOutputFormat ff_cavsvideo_muxer = { - .name = "cavsvideo", - .long_name = NULL_IF_CONFIG_SMALL("raw Chinese AVS (Audio Video Standard) video"), - .extensions = "cavs", - .audio_codec = AV_CODEC_ID_NONE, - .video_codec = AV_CODEC_ID_CAVS, +const FFOutputFormat ff_cavsvideo_muxer = { + .p.name = "cavsvideo", + .p.long_name = NULL_IF_CONFIG_SMALL("raw Chinese AVS (Audio Video Standard) video"), + .p.extensions = "cavs", + .p.audio_codec = AV_CODEC_ID_NONE, + .p.video_codec = AV_CODEC_ID_CAVS, .init = force_one_stream, .write_packet = ff_raw_write_packet, - .flags = AVFMT_NOTIMESTAMPS, + .p.flags = AVFMT_NOTIMESTAMPS, }; #endif #if CONFIG_CODEC2RAW_MUXER -const AVOutputFormat ff_codec2raw_muxer = { - .name = "codec2raw", - .long_name = NULL_IF_CONFIG_SMALL("raw codec2 muxer"), - .audio_codec = AV_CODEC_ID_CODEC2, - .video_codec = AV_CODEC_ID_NONE, +const FFOutputFormat ff_codec2raw_muxer = { + .p.name = "codec2raw", + .p.long_name = NULL_IF_CONFIG_SMALL("raw codec2 muxer"), + .p.audio_codec = AV_CODEC_ID_CODEC2, + .p.video_codec = AV_CODEC_ID_NONE, .init = force_one_stream, .write_packet = ff_raw_write_packet, - .flags = AVFMT_NOTIMESTAMPS, + .p.flags = AVFMT_NOTIMESTAMPS, }; #endif #if CONFIG_DATA_MUXER -const AVOutputFormat ff_data_muxer = { - .name = "data", - .long_name = NULL_IF_CONFIG_SMALL("raw data"), +const FFOutputFormat ff_data_muxer = { + .p.name = "data", + .p.long_name = NULL_IF_CONFIG_SMALL("raw data"), .init = force_one_stream, .write_packet = ff_raw_write_packet, - .flags = AVFMT_NOTIMESTAMPS, + .p.flags = AVFMT_NOTIMESTAMPS, }; #endif #if CONFIG_DFPWM_MUXER -const AVOutputFormat ff_dfpwm_muxer = { - .name = "dfpwm", - .long_name = NULL_IF_CONFIG_SMALL("raw DFPWM1a"), - .extensions = "dfpwm", - .audio_codec = AV_CODEC_ID_DFPWM, - .video_codec = AV_CODEC_ID_NONE, +const FFOutputFormat ff_dfpwm_muxer = { + .p.name = "dfpwm", + .p.long_name = NULL_IF_CONFIG_SMALL("raw DFPWM1a"), + .p.extensions = "dfpwm", + .p.audio_codec = AV_CODEC_ID_DFPWM, + .p.video_codec = AV_CODEC_ID_NONE, .init = force_one_stream, .write_packet = ff_raw_write_packet, - .flags = AVFMT_NOTIMESTAMPS, + .p.flags = AVFMT_NOTIMESTAMPS, }; #endif #if CONFIG_DIRAC_MUXER -const AVOutputFormat ff_dirac_muxer = { - .name = "dirac", - .long_name = NULL_IF_CONFIG_SMALL("raw Dirac"), - .extensions = "drc,vc2", - .audio_codec = AV_CODEC_ID_NONE, - .video_codec = AV_CODEC_ID_DIRAC, +const FFOutputFormat ff_dirac_muxer = { + .p.name = "dirac", + .p.long_name = NULL_IF_CONFIG_SMALL("raw Dirac"), + .p.extensions = "drc,vc2", + .p.audio_codec = AV_CODEC_ID_NONE, + .p.video_codec = AV_CODEC_ID_DIRAC, .init = force_one_stream, .write_packet = ff_raw_write_packet, - .flags = AVFMT_NOTIMESTAMPS, + .p.flags = AVFMT_NOTIMESTAMPS, }; #endif #if CONFIG_DNXHD_MUXER -const AVOutputFormat ff_dnxhd_muxer = { - .name = "dnxhd", - .long_name = NULL_IF_CONFIG_SMALL("raw DNxHD (SMPTE VC-3)"), - .extensions = "dnxhd,dnxhr", - .audio_codec = AV_CODEC_ID_NONE, - .video_codec = AV_CODEC_ID_DNXHD, +const FFOutputFormat ff_dnxhd_muxer = { + .p.name = "dnxhd", + .p.long_name = NULL_IF_CONFIG_SMALL("raw DNxHD (SMPTE VC-3)"), + .p.extensions = "dnxhd,dnxhr", + .p.audio_codec = AV_CODEC_ID_NONE, + .p.video_codec = AV_CODEC_ID_DNXHD, .init = force_one_stream, .write_packet = ff_raw_write_packet, - .flags = AVFMT_NOTIMESTAMPS, + .p.flags = AVFMT_NOTIMESTAMPS, }; #endif #if CONFIG_DTS_MUXER -const AVOutputFormat ff_dts_muxer = { - .name = "dts", - .long_name = NULL_IF_CONFIG_SMALL("raw DTS"), - .mime_type = "audio/x-dca", - .extensions = "dts", - .audio_codec = AV_CODEC_ID_DTS, - .video_codec = AV_CODEC_ID_NONE, +const FFOutputFormat ff_dts_muxer = { + .p.name = "dts", + .p.long_name = NULL_IF_CONFIG_SMALL("raw DTS"), + .p.mime_type = "audio/x-dca", + .p.extensions = "dts", + .p.audio_codec = AV_CODEC_ID_DTS, + .p.video_codec = AV_CODEC_ID_NONE, .init = force_one_stream, .write_packet = ff_raw_write_packet, - .flags = AVFMT_NOTIMESTAMPS, + .p.flags = AVFMT_NOTIMESTAMPS, }; #endif #if CONFIG_EAC3_MUXER -const AVOutputFormat ff_eac3_muxer = { - .name = "eac3", - .long_name = NULL_IF_CONFIG_SMALL("raw E-AC-3"), - .mime_type = "audio/x-eac3", - .extensions = "eac3,ec3", - .audio_codec = AV_CODEC_ID_EAC3, - .video_codec = AV_CODEC_ID_NONE, +const FFOutputFormat ff_eac3_muxer = { + .p.name = "eac3", + .p.long_name = NULL_IF_CONFIG_SMALL("raw E-AC-3"), + .p.mime_type = "audio/x-eac3", + .p.extensions = "eac3,ec3", + .p.audio_codec = AV_CODEC_ID_EAC3, + .p.video_codec = AV_CODEC_ID_NONE, .init = force_one_stream, .write_packet = ff_raw_write_packet, - .flags = AVFMT_NOTIMESTAMPS, + .p.flags = AVFMT_NOTIMESTAMPS, }; #endif #if CONFIG_G722_MUXER -const AVOutputFormat ff_g722_muxer = { - .name = "g722", - .long_name = NULL_IF_CONFIG_SMALL("raw G.722"), - .mime_type = "audio/G722", - .extensions = "g722", - .audio_codec = AV_CODEC_ID_ADPCM_G722, - .video_codec = AV_CODEC_ID_NONE, +const FFOutputFormat ff_g722_muxer = { + .p.name = "g722", + .p.long_name = NULL_IF_CONFIG_SMALL("raw G.722"), + .p.mime_type = "audio/G722", + .p.extensions = "g722", + .p.audio_codec = AV_CODEC_ID_ADPCM_G722, + .p.video_codec = AV_CODEC_ID_NONE, .init = force_one_stream, .write_packet = ff_raw_write_packet, - .flags = AVFMT_NOTIMESTAMPS, + .p.flags = AVFMT_NOTIMESTAMPS, }; #endif #if CONFIG_G723_1_MUXER -const AVOutputFormat ff_g723_1_muxer = { - .name = "g723_1", - .long_name = NULL_IF_CONFIG_SMALL("raw G.723.1"), - .mime_type = "audio/g723", - .extensions = "tco,rco", - .audio_codec = AV_CODEC_ID_G723_1, - .video_codec = AV_CODEC_ID_NONE, +const FFOutputFormat ff_g723_1_muxer = { + .p.name = "g723_1", + .p.long_name = NULL_IF_CONFIG_SMALL("raw G.723.1"), + .p.mime_type = "audio/g723", + .p.extensions = "tco,rco", + .p.audio_codec = AV_CODEC_ID_G723_1, + .p.video_codec = AV_CODEC_ID_NONE, .init = force_one_stream, .write_packet = ff_raw_write_packet, - .flags = AVFMT_NOTIMESTAMPS, + .p.flags = AVFMT_NOTIMESTAMPS, }; #endif #if CONFIG_G726_MUXER -const AVOutputFormat ff_g726_muxer = { - .name = "g726", - .long_name = NULL_IF_CONFIG_SMALL("raw big-endian G.726 (\"left-justified\")"), - .audio_codec = AV_CODEC_ID_ADPCM_G726, - .video_codec = AV_CODEC_ID_NONE, +const FFOutputFormat ff_g726_muxer = { + .p.name = "g726", + .p.long_name = NULL_IF_CONFIG_SMALL("raw big-endian G.726 (\"left-justified\")"), + .p.audio_codec = AV_CODEC_ID_ADPCM_G726, + .p.video_codec = AV_CODEC_ID_NONE, .init = force_one_stream, .write_packet = ff_raw_write_packet, - .flags = AVFMT_NOTIMESTAMPS, + .p.flags = AVFMT_NOTIMESTAMPS, }; #endif #if CONFIG_G726LE_MUXER -const AVOutputFormat ff_g726le_muxer = { - .name = "g726le", - .long_name = NULL_IF_CONFIG_SMALL("raw little-endian G.726 (\"right-justified\")"), - .audio_codec = AV_CODEC_ID_ADPCM_G726LE, - .video_codec = AV_CODEC_ID_NONE, +const FFOutputFormat ff_g726le_muxer = { + .p.name = "g726le", + .p.long_name = NULL_IF_CONFIG_SMALL("raw little-endian G.726 (\"right-justified\")"), + .p.audio_codec = AV_CODEC_ID_ADPCM_G726LE, + .p.video_codec = AV_CODEC_ID_NONE, .init = force_one_stream, .write_packet = ff_raw_write_packet, - .flags = AVFMT_NOTIMESTAMPS, + .p.flags = AVFMT_NOTIMESTAMPS, }; #endif #if CONFIG_GSM_MUXER -const AVOutputFormat ff_gsm_muxer = { - .name = "gsm", - .long_name = NULL_IF_CONFIG_SMALL("raw GSM"), - .mime_type = "audio/x-gsm", - .extensions = "gsm", - .audio_codec = AV_CODEC_ID_GSM, - .video_codec = AV_CODEC_ID_NONE, +const FFOutputFormat ff_gsm_muxer = { + .p.name = "gsm", + .p.long_name = NULL_IF_CONFIG_SMALL("raw GSM"), + .p.mime_type = "audio/x-gsm", + .p.extensions = "gsm", + .p.audio_codec = AV_CODEC_ID_GSM, + .p.video_codec = AV_CODEC_ID_NONE, .init = force_one_stream, .write_packet = ff_raw_write_packet, - .flags = AVFMT_NOTIMESTAMPS, + .p.flags = AVFMT_NOTIMESTAMPS, }; #endif #if CONFIG_H261_MUXER -const AVOutputFormat ff_h261_muxer = { - .name = "h261", - .long_name = NULL_IF_CONFIG_SMALL("raw H.261"), - .mime_type = "video/x-h261", - .extensions = "h261", - .audio_codec = AV_CODEC_ID_NONE, - .video_codec = AV_CODEC_ID_H261, +const FFOutputFormat ff_h261_muxer = { + .p.name = "h261", + .p.long_name = NULL_IF_CONFIG_SMALL("raw H.261"), + .p.mime_type = "video/x-h261", + .p.extensions = "h261", + .p.audio_codec = AV_CODEC_ID_NONE, + .p.video_codec = AV_CODEC_ID_H261, .init = force_one_stream, .write_packet = ff_raw_write_packet, - .flags = AVFMT_NOTIMESTAMPS, + .p.flags = AVFMT_NOTIMESTAMPS, }; #endif #if CONFIG_H263_MUXER -const AVOutputFormat ff_h263_muxer = { - .name = "h263", - .long_name = NULL_IF_CONFIG_SMALL("raw H.263"), - .mime_type = "video/x-h263", - .extensions = "h263", - .audio_codec = AV_CODEC_ID_NONE, - .video_codec = AV_CODEC_ID_H263, +const FFOutputFormat ff_h263_muxer = { + .p.name = "h263", + .p.long_name = NULL_IF_CONFIG_SMALL("raw H.263"), + .p.mime_type = "video/x-h263", + .p.extensions = "h263", + .p.audio_codec = AV_CODEC_ID_NONE, + .p.video_codec = AV_CODEC_ID_H263, .init = force_one_stream, .write_packet = ff_raw_write_packet, - .flags = AVFMT_NOTIMESTAMPS, + .p.flags = AVFMT_NOTIMESTAMPS, }; #endif @@ -365,16 +365,16 @@ static int h264_check_bitstream(AVFormatContext *s, AVStream *st, return 1; } -const AVOutputFormat ff_h264_muxer = { - .name = "h264", - .long_name = NULL_IF_CONFIG_SMALL("raw H.264 video"), - .extensions = "h264,264", - .audio_codec = AV_CODEC_ID_NONE, - .video_codec = AV_CODEC_ID_H264, +const FFOutputFormat ff_h264_muxer = { + .p.name = "h264", + .p.long_name = NULL_IF_CONFIG_SMALL("raw H.264 video"), + .p.extensions = "h264,264", + .p.audio_codec = AV_CODEC_ID_NONE, + .p.video_codec = AV_CODEC_ID_H264, .init = force_one_stream, .write_packet = ff_raw_write_packet, .check_bitstream = h264_check_bitstream, - .flags = AVFMT_NOTIMESTAMPS, + .p.flags = AVFMT_NOTIMESTAMPS, }; #endif @@ -388,97 +388,97 @@ static int hevc_check_bitstream(AVFormatContext *s, AVStream *st, return 1; } -const AVOutputFormat ff_hevc_muxer = { - .name = "hevc", - .long_name = NULL_IF_CONFIG_SMALL("raw HEVC video"), - .extensions = "hevc,h265,265", - .audio_codec = AV_CODEC_ID_NONE, - .video_codec = AV_CODEC_ID_HEVC, +const FFOutputFormat ff_hevc_muxer = { + .p.name = "hevc", + .p.long_name = NULL_IF_CONFIG_SMALL("raw HEVC video"), + .p.extensions = "hevc,h265,265", + .p.audio_codec = AV_CODEC_ID_NONE, + .p.video_codec = AV_CODEC_ID_HEVC, .init = force_one_stream, .write_packet = ff_raw_write_packet, .check_bitstream = hevc_check_bitstream, - .flags = AVFMT_NOTIMESTAMPS, + .p.flags = AVFMT_NOTIMESTAMPS, }; #endif #if CONFIG_M4V_MUXER -const AVOutputFormat ff_m4v_muxer = { - .name = "m4v", - .long_name = NULL_IF_CONFIG_SMALL("raw MPEG-4 video"), - .extensions = "m4v", - .audio_codec = AV_CODEC_ID_NONE, - .video_codec = AV_CODEC_ID_MPEG4, +const FFOutputFormat ff_m4v_muxer = { + .p.name = "m4v", + .p.long_name = NULL_IF_CONFIG_SMALL("raw MPEG-4 video"), + .p.extensions = "m4v", + .p.audio_codec = AV_CODEC_ID_NONE, + .p.video_codec = AV_CODEC_ID_MPEG4, .init = force_one_stream, .write_packet = ff_raw_write_packet, - .flags = AVFMT_NOTIMESTAMPS, + .p.flags = AVFMT_NOTIMESTAMPS, }; #endif #if CONFIG_MJPEG_MUXER -const AVOutputFormat ff_mjpeg_muxer = { - .name = "mjpeg", - .long_name = NULL_IF_CONFIG_SMALL("raw MJPEG video"), - .mime_type = "video/x-mjpeg", - .extensions = "mjpg,mjpeg", - .audio_codec = AV_CODEC_ID_NONE, - .video_codec = AV_CODEC_ID_MJPEG, +const FFOutputFormat ff_mjpeg_muxer = { + .p.name = "mjpeg", + .p.long_name = NULL_IF_CONFIG_SMALL("raw MJPEG video"), + .p.mime_type = "video/x-mjpeg", + .p.extensions = "mjpg,mjpeg", + .p.audio_codec = AV_CODEC_ID_NONE, + .p.video_codec = AV_CODEC_ID_MJPEG, .init = force_one_stream, .write_packet = ff_raw_write_packet, - .flags = AVFMT_NOTIMESTAMPS, + .p.flags = AVFMT_NOTIMESTAMPS, }; #endif #if CONFIG_MLP_MUXER -const AVOutputFormat ff_mlp_muxer = { - .name = "mlp", - .long_name = NULL_IF_CONFIG_SMALL("raw MLP"), - .extensions = "mlp", - .audio_codec = AV_CODEC_ID_MLP, - .video_codec = AV_CODEC_ID_NONE, +const FFOutputFormat ff_mlp_muxer = { + .p.name = "mlp", + .p.long_name = NULL_IF_CONFIG_SMALL("raw MLP"), + .p.extensions = "mlp", + .p.audio_codec = AV_CODEC_ID_MLP, + .p.video_codec = AV_CODEC_ID_NONE, .init = force_one_stream, .write_packet = ff_raw_write_packet, - .flags = AVFMT_NOTIMESTAMPS, + .p.flags = AVFMT_NOTIMESTAMPS, }; #endif #if CONFIG_MP2_MUXER -const AVOutputFormat ff_mp2_muxer = { - .name = "mp2", - .long_name = NULL_IF_CONFIG_SMALL("MP2 (MPEG audio layer 2)"), - .mime_type = "audio/mpeg", - .extensions = "mp2,m2a,mpa", - .audio_codec = AV_CODEC_ID_MP2, - .video_codec = AV_CODEC_ID_NONE, +const FFOutputFormat ff_mp2_muxer = { + .p.name = "mp2", + .p.long_name = NULL_IF_CONFIG_SMALL("MP2 (MPEG audio layer 2)"), + .p.mime_type = "audio/mpeg", + .p.extensions = "mp2,m2a,mpa", + .p.audio_codec = AV_CODEC_ID_MP2, + .p.video_codec = AV_CODEC_ID_NONE, .init = force_one_stream, .write_packet = ff_raw_write_packet, - .flags = AVFMT_NOTIMESTAMPS, + .p.flags = AVFMT_NOTIMESTAMPS, }; #endif #if CONFIG_MPEG1VIDEO_MUXER -const AVOutputFormat ff_mpeg1video_muxer = { - .name = "mpeg1video", - .long_name = NULL_IF_CONFIG_SMALL("raw MPEG-1 video"), - .mime_type = "video/mpeg", - .extensions = "mpg,mpeg,m1v", - .audio_codec = AV_CODEC_ID_NONE, - .video_codec = AV_CODEC_ID_MPEG1VIDEO, +const FFOutputFormat ff_mpeg1video_muxer = { + .p.name = "mpeg1video", + .p.long_name = NULL_IF_CONFIG_SMALL("raw MPEG-1 video"), + .p.mime_type = "video/mpeg", + .p.extensions = "mpg,mpeg,m1v", + .p.audio_codec = AV_CODEC_ID_NONE, + .p.video_codec = AV_CODEC_ID_MPEG1VIDEO, .init = force_one_stream, .write_packet = ff_raw_write_packet, - .flags = AVFMT_NOTIMESTAMPS, + .p.flags = AVFMT_NOTIMESTAMPS, }; #endif #if CONFIG_MPEG2VIDEO_MUXER -const AVOutputFormat ff_mpeg2video_muxer = { - .name = "mpeg2video", - .long_name = NULL_IF_CONFIG_SMALL("raw MPEG-2 video"), - .extensions = "m2v", - .audio_codec = AV_CODEC_ID_NONE, - .video_codec = AV_CODEC_ID_MPEG2VIDEO, +const FFOutputFormat ff_mpeg2video_muxer = { + .p.name = "mpeg2video", + .p.long_name = NULL_IF_CONFIG_SMALL("raw MPEG-2 video"), + .p.extensions = "m2v", + .p.audio_codec = AV_CODEC_ID_NONE, + .p.video_codec = AV_CODEC_ID_MPEG2VIDEO, .init = force_one_stream, .write_packet = ff_raw_write_packet, - .flags = AVFMT_NOTIMESTAMPS, + .p.flags = AVFMT_NOTIMESTAMPS, }; #endif @@ -489,66 +489,66 @@ static int obu_check_bitstream(AVFormatContext *s, AVStream *st, return ff_stream_add_bitstream_filter(st, "av1_metadata", "td=insert"); } -const AVOutputFormat ff_obu_muxer = { - .name = "obu", - .long_name = NULL_IF_CONFIG_SMALL("AV1 low overhead OBU"), - .extensions = "obu", - .audio_codec = AV_CODEC_ID_NONE, - .video_codec = AV_CODEC_ID_AV1, +const FFOutputFormat ff_obu_muxer = { + .p.name = "obu", + .p.long_name = NULL_IF_CONFIG_SMALL("AV1 low overhead OBU"), + .p.extensions = "obu", + .p.audio_codec = AV_CODEC_ID_NONE, + .p.video_codec = AV_CODEC_ID_AV1, .init = force_one_stream, .write_packet = ff_raw_write_packet, .check_bitstream = obu_check_bitstream, - .flags = AVFMT_NOTIMESTAMPS, + .p.flags = AVFMT_NOTIMESTAMPS, }; #endif #if CONFIG_RAWVIDEO_MUXER -const AVOutputFormat ff_rawvideo_muxer = { - .name = "rawvideo", - .long_name = NULL_IF_CONFIG_SMALL("raw video"), - .extensions = "yuv,rgb", - .audio_codec = AV_CODEC_ID_NONE, - .video_codec = AV_CODEC_ID_RAWVIDEO, +const FFOutputFormat ff_rawvideo_muxer = { + .p.name = "rawvideo", + .p.long_name = NULL_IF_CONFIG_SMALL("raw video"), + .p.extensions = "yuv,rgb", + .p.audio_codec = AV_CODEC_ID_NONE, + .p.video_codec = AV_CODEC_ID_RAWVIDEO, .write_packet = ff_raw_write_packet, - .flags = AVFMT_NOTIMESTAMPS, + .p.flags = AVFMT_NOTIMESTAMPS, }; #endif #if CONFIG_SBC_MUXER -const AVOutputFormat ff_sbc_muxer = { - .name = "sbc", - .long_name = NULL_IF_CONFIG_SMALL("raw SBC"), - .mime_type = "audio/x-sbc", - .extensions = "sbc,msbc", - .audio_codec = AV_CODEC_ID_SBC, +const FFOutputFormat ff_sbc_muxer = { + .p.name = "sbc", + .p.long_name = NULL_IF_CONFIG_SMALL("raw SBC"), + .p.mime_type = "audio/x-sbc", + .p.extensions = "sbc,msbc", + .p.audio_codec = AV_CODEC_ID_SBC, .init = force_one_stream, .write_packet = ff_raw_write_packet, - .flags = AVFMT_NOTIMESTAMPS, + .p.flags = AVFMT_NOTIMESTAMPS, }; #endif #if CONFIG_TRUEHD_MUXER -const AVOutputFormat ff_truehd_muxer = { - .name = "truehd", - .long_name = NULL_IF_CONFIG_SMALL("raw TrueHD"), - .extensions = "thd", - .audio_codec = AV_CODEC_ID_TRUEHD, - .video_codec = AV_CODEC_ID_NONE, +const FFOutputFormat ff_truehd_muxer = { + .p.name = "truehd", + .p.long_name = NULL_IF_CONFIG_SMALL("raw TrueHD"), + .p.extensions = "thd", + .p.audio_codec = AV_CODEC_ID_TRUEHD, + .p.video_codec = AV_CODEC_ID_NONE, .init = force_one_stream, .write_packet = ff_raw_write_packet, - .flags = AVFMT_NOTIMESTAMPS, + .p.flags = AVFMT_NOTIMESTAMPS, }; #endif #if CONFIG_VC1_MUXER -const AVOutputFormat ff_vc1_muxer = { - .name = "vc1", - .long_name = NULL_IF_CONFIG_SMALL("raw VC-1 video"), - .extensions = "vc1", - .audio_codec = AV_CODEC_ID_NONE, - .video_codec = AV_CODEC_ID_VC1, +const FFOutputFormat ff_vc1_muxer = { + .p.name = "vc1", + .p.long_name = NULL_IF_CONFIG_SMALL("raw VC-1 video"), + .p.extensions = "vc1", + .p.audio_codec = AV_CODEC_ID_NONE, + .p.video_codec = AV_CODEC_ID_VC1, .init = force_one_stream, .write_packet = ff_raw_write_packet, - .flags = AVFMT_NOTIMESTAMPS, + .p.flags = AVFMT_NOTIMESTAMPS, }; #endif diff --git a/libavformat/rmenc.c b/libavformat/rmenc.c index 1fba092b888..0d001224cb6 100644 --- a/libavformat/rmenc.c +++ b/libavformat/rmenc.c @@ -20,6 +20,7 @@ */ #include "avformat.h" #include "avio_internal.h" +#include "mux.h" #include "rm.h" #include "libavutil/dict.h" @@ -465,16 +466,16 @@ static int rm_write_trailer(AVFormatContext *s) } -const AVOutputFormat ff_rm_muxer = { - .name = "rm", - .long_name = NULL_IF_CONFIG_SMALL("RealMedia"), - .mime_type = "application/vnd.rn-realmedia", - .extensions = "rm,ra", +const FFOutputFormat ff_rm_muxer = { + .p.name = "rm", + .p.long_name = NULL_IF_CONFIG_SMALL("RealMedia"), + .p.mime_type = "application/vnd.rn-realmedia", + .p.extensions = "rm,ra", .priv_data_size = sizeof(RMMuxContext), - .audio_codec = AV_CODEC_ID_AC3, - .video_codec = AV_CODEC_ID_RV10, + .p.audio_codec = AV_CODEC_ID_AC3, + .p.video_codec = AV_CODEC_ID_RV10, .write_header = rm_write_header, .write_packet = rm_write_packet, .write_trailer = rm_write_trailer, - .codec_tag = (const AVCodecTag* const []){ ff_rm_codec_tags, 0 }, + .p.codec_tag = (const AVCodecTag* const []){ ff_rm_codec_tags, 0 }, }; diff --git a/libavformat/rsoenc.c b/libavformat/rsoenc.c index 858b53f6c6b..fe22e22812a 100644 --- a/libavformat/rsoenc.c +++ b/libavformat/rsoenc.c @@ -22,6 +22,7 @@ #include "avformat.h" #include "internal.h" +#include "mux.h" #include "rawenc.h" #include "riff.h" #include "rso.h" @@ -91,15 +92,15 @@ static int rso_write_trailer(AVFormatContext *s) return 0; } -const AVOutputFormat ff_rso_muxer = { - .name = "rso", - .long_name = NULL_IF_CONFIG_SMALL("Lego Mindstorms RSO"), - .extensions = "rso", - .audio_codec = AV_CODEC_ID_PCM_U8, - .video_codec = AV_CODEC_ID_NONE, +const FFOutputFormat ff_rso_muxer = { + .p.name = "rso", + .p.long_name = NULL_IF_CONFIG_SMALL("Lego Mindstorms RSO"), + .p.extensions = "rso", + .p.audio_codec = AV_CODEC_ID_PCM_U8, + .p.video_codec = AV_CODEC_ID_NONE, .write_header = rso_write_header, .write_packet = ff_raw_write_packet, .write_trailer = rso_write_trailer, - .codec_tag = ff_rso_codec_tags_list, - .flags = AVFMT_NOTIMESTAMPS, + .p.codec_tag = ff_rso_codec_tags_list, + .p.flags = AVFMT_NOTIMESTAMPS, }; diff --git a/libavformat/rtpenc.c b/libavformat/rtpenc.c index ce629a80954..a8d296a1542 100644 --- a/libavformat/rtpenc.c +++ b/libavformat/rtpenc.c @@ -22,6 +22,7 @@ #include "avformat.h" #include "mpegts.h" #include "internal.h" +#include "mux.h" #include "libavutil/mathematics.h" #include "libavutil/random_seed.h" #include "libavutil/opt.h" @@ -659,15 +660,15 @@ static int rtp_write_trailer(AVFormatContext *s1) return 0; } -const AVOutputFormat ff_rtp_muxer = { - .name = "rtp", - .long_name = NULL_IF_CONFIG_SMALL("RTP output"), +const FFOutputFormat ff_rtp_muxer = { + .p.name = "rtp", + .p.long_name = NULL_IF_CONFIG_SMALL("RTP output"), .priv_data_size = sizeof(RTPMuxContext), - .audio_codec = AV_CODEC_ID_PCM_MULAW, - .video_codec = AV_CODEC_ID_MPEG4, + .p.audio_codec = AV_CODEC_ID_PCM_MULAW, + .p.video_codec = AV_CODEC_ID_MPEG4, .write_header = rtp_write_header, .write_packet = rtp_write_packet, .write_trailer = rtp_write_trailer, - .priv_class = &rtp_muxer_class, - .flags = AVFMT_TS_NONSTRICT, + .p.priv_class = &rtp_muxer_class, + .p.flags = AVFMT_TS_NONSTRICT, }; diff --git a/libavformat/rtpenc_mpegts.c b/libavformat/rtpenc_mpegts.c index fdc759c1793..0d6403a0484 100644 --- a/libavformat/rtpenc_mpegts.c +++ b/libavformat/rtpenc_mpegts.c @@ -23,6 +23,7 @@ #include "libavutil/opt.h" #include "avformat.h" #include "avio_internal.h" +#include "mux.h" typedef struct MuxChain { const AVClass *class; @@ -187,14 +188,14 @@ static const AVClass rtp_mpegts_class = { .version = LIBAVUTIL_VERSION_INT, }; -const AVOutputFormat ff_rtp_mpegts_muxer = { - .name = "rtp_mpegts", - .long_name = NULL_IF_CONFIG_SMALL("RTP/mpegts output format"), +const FFOutputFormat ff_rtp_mpegts_muxer = { + .p.name = "rtp_mpegts", + .p.long_name = NULL_IF_CONFIG_SMALL("RTP/mpegts output format"), .priv_data_size = sizeof(MuxChain), - .audio_codec = AV_CODEC_ID_AAC, - .video_codec = AV_CODEC_ID_MPEG4, + .p.audio_codec = AV_CODEC_ID_AAC, + .p.video_codec = AV_CODEC_ID_MPEG4, .write_header = rtp_mpegts_write_header, .write_packet = rtp_mpegts_write_packet, .write_trailer = rtp_mpegts_write_close, - .priv_class = &rtp_mpegts_class, + .p.priv_class = &rtp_mpegts_class, }; diff --git a/libavformat/rtspenc.c b/libavformat/rtspenc.c index 21b204381b3..3d444ccbfd8 100644 --- a/libavformat/rtspenc.c +++ b/libavformat/rtspenc.c @@ -244,15 +244,15 @@ static int rtsp_write_close(AVFormatContext *s) return 0; } -const AVOutputFormat ff_rtsp_muxer = { - .name = "rtsp", - .long_name = NULL_IF_CONFIG_SMALL("RTSP output"), +const FFOutputFormat ff_rtsp_muxer = { + .p.name = "rtsp", + .p.long_name = NULL_IF_CONFIG_SMALL("RTSP output"), .priv_data_size = sizeof(RTSPState), - .audio_codec = AV_CODEC_ID_AAC, - .video_codec = AV_CODEC_ID_MPEG4, + .p.audio_codec = AV_CODEC_ID_AAC, + .p.video_codec = AV_CODEC_ID_MPEG4, .write_header = rtsp_write_header, .write_packet = rtsp_write_packet, .write_trailer = rtsp_write_close, - .flags = AVFMT_NOFILE | AVFMT_GLOBALHEADER, - .priv_class = &rtsp_muxer_class, + .p.flags = AVFMT_NOFILE | AVFMT_GLOBALHEADER, + .p.priv_class = &rtsp_muxer_class, }; diff --git a/libavformat/sapenc.c b/libavformat/sapenc.c index 8eb9d3b92a7..28839b837ff 100644 --- a/libavformat/sapenc.c +++ b/libavformat/sapenc.c @@ -268,14 +268,14 @@ static int sap_write_packet(AVFormatContext *s, AVPacket *pkt) return ff_write_chained(rtpctx, 0, pkt, s, 0); } -const AVOutputFormat ff_sap_muxer = { - .name = "sap", - .long_name = NULL_IF_CONFIG_SMALL("SAP output"), +const FFOutputFormat ff_sap_muxer = { + .p.name = "sap", + .p.long_name = NULL_IF_CONFIG_SMALL("SAP output"), .priv_data_size = sizeof(struct SAPState), - .audio_codec = AV_CODEC_ID_AAC, - .video_codec = AV_CODEC_ID_MPEG4, + .p.audio_codec = AV_CODEC_ID_AAC, + .p.video_codec = AV_CODEC_ID_MPEG4, .write_header = sap_write_header, .write_packet = sap_write_packet, .write_trailer = sap_write_close, - .flags = AVFMT_NOFILE | AVFMT_GLOBALHEADER, + .p.flags = AVFMT_NOFILE | AVFMT_GLOBALHEADER, }; diff --git a/libavformat/sccenc.c b/libavformat/sccenc.c index 2b924ba6e77..ea7865ecf22 100644 --- a/libavformat/sccenc.c +++ b/libavformat/sccenc.c @@ -21,6 +21,7 @@ #include "avformat.h" #include "internal.h" +#include "mux.h" #include "libavutil/log.h" #include "libavutil/intreadwrite.h" @@ -111,13 +112,13 @@ static int scc_write_packet(AVFormatContext *avf, AVPacket *pkt) return 0; } -const AVOutputFormat ff_scc_muxer = { - .name = "scc", - .long_name = NULL_IF_CONFIG_SMALL("Scenarist Closed Captions"), - .extensions = "scc", +const FFOutputFormat ff_scc_muxer = { + .p.name = "scc", + .p.long_name = NULL_IF_CONFIG_SMALL("Scenarist Closed Captions"), + .p.extensions = "scc", + .p.flags = AVFMT_GLOBALHEADER | AVFMT_VARIABLE_FPS | AVFMT_TS_NONSTRICT, + .p.subtitle_codec = AV_CODEC_ID_EIA_608, .priv_data_size = sizeof(SCCContext), .write_header = scc_write_header, .write_packet = scc_write_packet, - .flags = AVFMT_GLOBALHEADER | AVFMT_VARIABLE_FPS | AVFMT_TS_NONSTRICT, - .subtitle_codec = AV_CODEC_ID_EIA_608, }; diff --git a/libavformat/segafilmenc.c b/libavformat/segafilmenc.c index 42d56fccd61..ba06dc655d0 100644 --- a/libavformat/segafilmenc.c +++ b/libavformat/segafilmenc.c @@ -280,13 +280,13 @@ static void film_deinit(AVFormatContext *format_context) ffio_free_dyn_buf(&film->header); } -const AVOutputFormat ff_segafilm_muxer = { - .name = "film_cpk", - .long_name = NULL_IF_CONFIG_SMALL("Sega FILM / CPK"), - .extensions = "cpk", +const FFOutputFormat ff_segafilm_muxer = { + .p.name = "film_cpk", + .p.long_name = NULL_IF_CONFIG_SMALL("Sega FILM / CPK"), + .p.extensions = "cpk", .priv_data_size = sizeof(FILMOutputContext), - .audio_codec = AV_CODEC_ID_PCM_S16BE_PLANAR, - .video_codec = AV_CODEC_ID_CINEPAK, + .p.audio_codec = AV_CODEC_ID_PCM_S16BE_PLANAR, + .p.video_codec = AV_CODEC_ID_CINEPAK, .init = film_init, .write_trailer = film_write_header, .write_packet = film_write_packet, diff --git a/libavformat/segment.c b/libavformat/segment.c index 80e4bf851c1..eb629b342ce 100644 --- a/libavformat/segment.c +++ b/libavformat/segment.c @@ -976,7 +976,8 @@ static int seg_write_packet(AVFormatContext *s, AVPacket *pkt) av_ts2str(pkt->dts), av_ts2timestr(pkt->dts, &st->time_base)); ret = ff_write_chained(seg->avf, pkt->stream_index, pkt, s, - seg->initial_offset || seg->reset_timestamps || seg->avf->oformat->interleave_packet); + seg->initial_offset || seg->reset_timestamps || + ffofmt(seg->avf->oformat)->interleave_packet); fail: /* Use st->index here as the packet returned from ff_write_chained() @@ -1016,9 +1017,9 @@ static int seg_check_bitstream(AVFormatContext *s, AVStream *st, { SegmentContext *seg = s->priv_data; AVFormatContext *oc = seg->avf; - if (oc->oformat->check_bitstream) { + if (ffofmt(oc->oformat)->check_bitstream) { AVStream *const ost = oc->streams[st->index]; - int ret = oc->oformat->check_bitstream(oc, ost, pkt); + int ret = ffofmt(oc->oformat)->check_bitstream(oc, ost, pkt); if (ret == 1) { FFStream *const sti = ffstream(st); FFStream *const osti = ffstream(ost); @@ -1085,33 +1086,33 @@ static const AVClass seg_class = { }; #if CONFIG_SEGMENT_MUXER -const AVOutputFormat ff_segment_muxer = { - .name = "segment", - .long_name = NULL_IF_CONFIG_SMALL("segment"), +const FFOutputFormat ff_segment_muxer = { + .p.name = "segment", + .p.long_name = NULL_IF_CONFIG_SMALL("segment"), + .p.flags = AVFMT_NOFILE|AVFMT_GLOBALHEADER, + .p.priv_class = &seg_class, .priv_data_size = sizeof(SegmentContext), - .flags = AVFMT_NOFILE|AVFMT_GLOBALHEADER, .init = seg_init, .write_header = seg_write_header, .write_packet = seg_write_packet, .write_trailer = seg_write_trailer, .deinit = seg_free, .check_bitstream = seg_check_bitstream, - .priv_class = &seg_class, }; #endif #if CONFIG_STREAM_SEGMENT_MUXER -const AVOutputFormat ff_stream_segment_muxer = { - .name = "stream_segment,ssegment", - .long_name = NULL_IF_CONFIG_SMALL("streaming segment muxer"), - .priv_data_size = sizeof(SegmentContext), - .flags = AVFMT_NOFILE, +const FFOutputFormat ff_stream_segment_muxer = { + .p.name = "stream_segment,ssegment", + .p.long_name = NULL_IF_CONFIG_SMALL("streaming segment muxer"), + .p.flags = AVFMT_NOFILE, + .p.priv_class = &seg_class, + .priv_data_size = sizeof(SegmentContext), .init = seg_init, .write_header = seg_write_header, .write_packet = seg_write_packet, .write_trailer = seg_write_trailer, .deinit = seg_free, .check_bitstream = seg_check_bitstream, - .priv_class = &seg_class, }; #endif diff --git a/libavformat/smjpegenc.c b/libavformat/smjpegenc.c index edba08cf9b7..56907c96f7a 100644 --- a/libavformat/smjpegenc.c +++ b/libavformat/smjpegenc.c @@ -133,15 +133,15 @@ static int smjpeg_write_trailer(AVFormatContext *s) return 0; } -const AVOutputFormat ff_smjpeg_muxer = { - .name = "smjpeg", - .long_name = NULL_IF_CONFIG_SMALL("Loki SDL MJPEG"), +const FFOutputFormat ff_smjpeg_muxer = { + .p.name = "smjpeg", + .p.long_name = NULL_IF_CONFIG_SMALL("Loki SDL MJPEG"), .priv_data_size = sizeof(SMJPEGMuxContext), - .audio_codec = AV_CODEC_ID_PCM_S16LE, - .video_codec = AV_CODEC_ID_MJPEG, + .p.audio_codec = AV_CODEC_ID_PCM_S16LE, + .p.video_codec = AV_CODEC_ID_MJPEG, .write_header = smjpeg_write_header, .write_packet = smjpeg_write_packet, .write_trailer = smjpeg_write_trailer, - .flags = AVFMT_GLOBALHEADER | AVFMT_TS_NONSTRICT, - .codec_tag = (const AVCodecTag *const []){ ff_codec_smjpeg_video_tags, ff_codec_smjpeg_audio_tags, 0 }, + .p.flags = AVFMT_GLOBALHEADER | AVFMT_TS_NONSTRICT, + .p.codec_tag = (const AVCodecTag *const []){ ff_codec_smjpeg_video_tags, ff_codec_smjpeg_audio_tags, 0 }, }; diff --git a/libavformat/smoothstreamingenc.c b/libavformat/smoothstreamingenc.c index ade6d5723b2..66e6313934a 100644 --- a/libavformat/smoothstreamingenc.c +++ b/libavformat/smoothstreamingenc.c @@ -637,16 +637,16 @@ static const AVClass ism_class = { }; -const AVOutputFormat ff_smoothstreaming_muxer = { - .name = "smoothstreaming", - .long_name = NULL_IF_CONFIG_SMALL("Smooth Streaming Muxer"), +const FFOutputFormat ff_smoothstreaming_muxer = { + .p.name = "smoothstreaming", + .p.long_name = NULL_IF_CONFIG_SMALL("Smooth Streaming Muxer"), + .p.audio_codec = AV_CODEC_ID_AAC, + .p.video_codec = AV_CODEC_ID_H264, + .p.flags = AVFMT_GLOBALHEADER | AVFMT_NOFILE, + .p.priv_class = &ism_class, .priv_data_size = sizeof(SmoothStreamingContext), - .audio_codec = AV_CODEC_ID_AAC, - .video_codec = AV_CODEC_ID_H264, - .flags = AVFMT_GLOBALHEADER | AVFMT_NOFILE, .write_header = ism_write_header, .write_packet = ism_write_packet, .write_trailer = ism_write_trailer, .deinit = ism_free, - .priv_class = &ism_class, }; diff --git a/libavformat/soxenc.c b/libavformat/soxenc.c index ac01f97df5c..062b4a3fae2 100644 --- a/libavformat/soxenc.c +++ b/libavformat/soxenc.c @@ -34,6 +34,7 @@ #include "libavutil/dict.h" #include "avformat.h" #include "avio_internal.h" +#include "mux.h" #include "rawenc.h" #include "sox.h" @@ -104,15 +105,15 @@ static int sox_write_trailer(AVFormatContext *s) return 0; } -const AVOutputFormat ff_sox_muxer = { - .name = "sox", - .long_name = NULL_IF_CONFIG_SMALL("SoX native"), - .extensions = "sox", +const FFOutputFormat ff_sox_muxer = { + .p.name = "sox", + .p.long_name = NULL_IF_CONFIG_SMALL("SoX native"), + .p.extensions = "sox", .priv_data_size = sizeof(SoXContext), - .audio_codec = AV_CODEC_ID_PCM_S32LE, - .video_codec = AV_CODEC_ID_NONE, + .p.audio_codec = AV_CODEC_ID_PCM_S32LE, + .p.video_codec = AV_CODEC_ID_NONE, .write_header = sox_write_header, .write_packet = ff_raw_write_packet, .write_trailer = sox_write_trailer, - .flags = AVFMT_NOTIMESTAMPS, + .p.flags = AVFMT_NOTIMESTAMPS, }; diff --git a/libavformat/spdifenc.c b/libavformat/spdifenc.c index 2861f828b42..ca386746268 100644 --- a/libavformat/spdifenc.c +++ b/libavformat/spdifenc.c @@ -48,6 +48,7 @@ #include "avformat.h" #include "avio_internal.h" +#include "mux.h" #include "spdif.h" #include "libavcodec/ac3defs.h" #include "libavcodec/adts_parser.h" @@ -673,16 +674,16 @@ static int spdif_write_packet(struct AVFormatContext *s, AVPacket *pkt) return 0; } -const AVOutputFormat ff_spdif_muxer = { - .name = "spdif", - .long_name = NULL_IF_CONFIG_SMALL("IEC 61937 (used on S/PDIF - IEC958)"), - .extensions = "spdif", +const FFOutputFormat ff_spdif_muxer = { + .p.name = "spdif", + .p.long_name = NULL_IF_CONFIG_SMALL("IEC 61937 (used on S/PDIF - IEC958)"), + .p.extensions = "spdif", .priv_data_size = sizeof(IEC61937Context), - .audio_codec = AV_CODEC_ID_AC3, - .video_codec = AV_CODEC_ID_NONE, + .p.audio_codec = AV_CODEC_ID_AC3, + .p.video_codec = AV_CODEC_ID_NONE, .write_header = spdif_write_header, .write_packet = spdif_write_packet, .deinit = spdif_deinit, - .flags = AVFMT_NOTIMESTAMPS, - .priv_class = &spdif_class, + .p.flags = AVFMT_NOTIMESTAMPS, + .p.priv_class = &spdif_class, }; diff --git a/libavformat/srtenc.c b/libavformat/srtenc.c index 7f6171edd34..30dc59e0f8d 100644 --- a/libavformat/srtenc.c +++ b/libavformat/srtenc.c @@ -21,6 +21,7 @@ #include "avformat.h" #include "internal.h" +#include "mux.h" #include "libavutil/log.h" #include "libavutil/intreadwrite.h" @@ -96,14 +97,14 @@ static int srt_write_packet(AVFormatContext *avf, AVPacket *pkt) return 0; } -const AVOutputFormat ff_srt_muxer = { - .name = "srt", - .long_name = NULL_IF_CONFIG_SMALL("SubRip subtitle"), - .mime_type = "application/x-subrip", - .extensions = "srt", +const FFOutputFormat ff_srt_muxer = { + .p.name = "srt", + .p.long_name = NULL_IF_CONFIG_SMALL("SubRip subtitle"), + .p.mime_type = "application/x-subrip", + .p.extensions = "srt", + .p.flags = AVFMT_VARIABLE_FPS | AVFMT_TS_NONSTRICT, + .p.subtitle_codec = AV_CODEC_ID_SUBRIP, .priv_data_size = sizeof(SRTContext), .write_header = srt_write_header, .write_packet = srt_write_packet, - .flags = AVFMT_VARIABLE_FPS | AVFMT_TS_NONSTRICT, - .subtitle_codec = AV_CODEC_ID_SUBRIP, }; diff --git a/libavformat/supenc.c b/libavformat/supenc.c index c45d8a5321b..4af92fefa2e 100644 --- a/libavformat/supenc.c +++ b/libavformat/supenc.c @@ -21,6 +21,7 @@ #include "avformat.h" #include "internal.h" +#include "mux.h" #include "libavutil/intreadwrite.h" #define SUP_PGS_MAGIC 0x5047 /* "PG", big endian */ @@ -84,13 +85,13 @@ static int sup_write_header(AVFormatContext *s) return 0; } -const AVOutputFormat ff_sup_muxer = { - .name = "sup", - .long_name = NULL_IF_CONFIG_SMALL("raw HDMV Presentation Graphic Stream subtitles"), - .extensions = "sup", - .mime_type = "application/x-pgs", - .subtitle_codec = AV_CODEC_ID_HDMV_PGS_SUBTITLE, +const FFOutputFormat ff_sup_muxer = { + .p.name = "sup", + .p.long_name = NULL_IF_CONFIG_SMALL("raw HDMV Presentation Graphic Stream subtitles"), + .p.extensions = "sup", + .p.mime_type = "application/x-pgs", + .p.subtitle_codec = AV_CODEC_ID_HDMV_PGS_SUBTITLE, + .p.flags = AVFMT_VARIABLE_FPS | AVFMT_TS_NONSTRICT, .write_header = sup_write_header, .write_packet = sup_write_packet, - .flags = AVFMT_VARIABLE_FPS | AVFMT_TS_NONSTRICT, }; diff --git a/libavformat/swfenc.c b/libavformat/swfenc.c index 75b892087fe..f9ac69539b4 100644 --- a/libavformat/swfenc.c +++ b/libavformat/swfenc.c @@ -27,6 +27,7 @@ #include "libavutil/fifo.h" #include "avformat.h" #include "flv.h" +#include "mux.h" #include "swf.h" #define AUDIO_FIFO_SIZE 65536 @@ -547,33 +548,33 @@ static void swf_deinit(AVFormatContext *s) } #if CONFIG_SWF_MUXER -const AVOutputFormat ff_swf_muxer = { - .name = "swf", - .long_name = NULL_IF_CONFIG_SMALL("SWF (ShockWave Flash)"), - .mime_type = "application/x-shockwave-flash", - .extensions = "swf", +const FFOutputFormat ff_swf_muxer = { + .p.name = "swf", + .p.long_name = NULL_IF_CONFIG_SMALL("SWF (ShockWave Flash)"), + .p.mime_type = "application/x-shockwave-flash", + .p.extensions = "swf", .priv_data_size = sizeof(SWFEncContext), - .audio_codec = AV_CODEC_ID_MP3, - .video_codec = AV_CODEC_ID_FLV1, + .p.audio_codec = AV_CODEC_ID_MP3, + .p.video_codec = AV_CODEC_ID_FLV1, .write_header = swf_write_header, .write_packet = swf_write_packet, .write_trailer = swf_write_trailer, .deinit = swf_deinit, - .flags = AVFMT_TS_NONSTRICT, + .p.flags = AVFMT_TS_NONSTRICT, }; #endif #if CONFIG_AVM2_MUXER -const AVOutputFormat ff_avm2_muxer = { - .name = "avm2", - .long_name = NULL_IF_CONFIG_SMALL("SWF (ShockWave Flash) (AVM2)"), - .mime_type = "application/x-shockwave-flash", +const FFOutputFormat ff_avm2_muxer = { + .p.name = "avm2", + .p.long_name = NULL_IF_CONFIG_SMALL("SWF (ShockWave Flash) (AVM2)"), + .p.mime_type = "application/x-shockwave-flash", .priv_data_size = sizeof(SWFEncContext), - .audio_codec = AV_CODEC_ID_MP3, - .video_codec = AV_CODEC_ID_FLV1, + .p.audio_codec = AV_CODEC_ID_MP3, + .p.video_codec = AV_CODEC_ID_FLV1, .write_header = swf_write_header, .write_packet = swf_write_packet, .write_trailer = swf_write_trailer, .deinit = swf_deinit, - .flags = AVFMT_TS_NONSTRICT, + .p.flags = AVFMT_TS_NONSTRICT, }; #endif diff --git a/libavformat/tee.c b/libavformat/tee.c index dd408dd096c..960b2ea574b 100644 --- a/libavformat/tee.c +++ b/libavformat/tee.c @@ -602,13 +602,13 @@ static int tee_write_packet(AVFormatContext *avf, AVPacket *pkt) return ret_all; } -const AVOutputFormat ff_tee_muxer = { - .name = "tee", - .long_name = NULL_IF_CONFIG_SMALL("Multiple muxer tee"), +const FFOutputFormat ff_tee_muxer = { + .p.name = "tee", + .p.long_name = NULL_IF_CONFIG_SMALL("Multiple muxer tee"), .priv_data_size = sizeof(TeeContext), .write_header = tee_write_header, .write_trailer = tee_write_trailer, .write_packet = tee_write_packet, - .priv_class = &tee_muxer_class, - .flags = AVFMT_NOFILE | AVFMT_ALLOW_FLUSH | AVFMT_TS_NEGATIVE, + .p.priv_class = &tee_muxer_class, + .p.flags = AVFMT_NOFILE | AVFMT_ALLOW_FLUSH | AVFMT_TS_NEGATIVE, }; diff --git a/libavformat/ttaenc.c b/libavformat/ttaenc.c index 1938582bb3a..c7f7e065dc1 100644 --- a/libavformat/ttaenc.c +++ b/libavformat/ttaenc.c @@ -27,6 +27,7 @@ #include "avformat.h" #include "avio_internal.h" #include "internal.h" +#include "mux.h" typedef struct TTAMuxContext { AVIOContext *seek_table; @@ -165,14 +166,14 @@ static void tta_deinit(AVFormatContext *s) avpriv_packet_list_free(&tta->queue); } -const AVOutputFormat ff_tta_muxer = { - .name = "tta", - .long_name = NULL_IF_CONFIG_SMALL("TTA (True Audio)"), - .mime_type = "audio/x-tta", - .extensions = "tta", +const FFOutputFormat ff_tta_muxer = { + .p.name = "tta", + .p.long_name = NULL_IF_CONFIG_SMALL("TTA (True Audio)"), + .p.mime_type = "audio/x-tta", + .p.extensions = "tta", .priv_data_size = sizeof(TTAMuxContext), - .audio_codec = AV_CODEC_ID_TTA, - .video_codec = AV_CODEC_ID_NONE, + .p.audio_codec = AV_CODEC_ID_TTA, + .p.video_codec = AV_CODEC_ID_NONE, .init = tta_init, .deinit = tta_deinit, .write_header = tta_write_header, diff --git a/libavformat/ttmlenc.c b/libavformat/ttmlenc.c index fc8069f7b56..212994be503 100644 --- a/libavformat/ttmlenc.c +++ b/libavformat/ttmlenc.c @@ -30,6 +30,7 @@ #include "libavutil/avstring.h" #include "avformat.h" #include "internal.h" +#include "mux.h" #include "ttmlenc.h" #include "libavcodec/ttmlenc.h" #include "libavutil/internal.h" @@ -215,15 +216,15 @@ static int ttml_write_trailer(AVFormatContext *ctx) return 0; } -const AVOutputFormat ff_ttml_muxer = { - .name = "ttml", - .long_name = NULL_IF_CONFIG_SMALL("TTML subtitle"), - .extensions = "ttml", - .mime_type = "text/ttml", +const FFOutputFormat ff_ttml_muxer = { + .p.name = "ttml", + .p.long_name = NULL_IF_CONFIG_SMALL("TTML subtitle"), + .p.extensions = "ttml", + .p.mime_type = "text/ttml", .priv_data_size = sizeof(TTMLMuxContext), - .flags = AVFMT_GLOBALHEADER | AVFMT_VARIABLE_FPS | + .p.flags = AVFMT_GLOBALHEADER | AVFMT_VARIABLE_FPS | AVFMT_TS_NONSTRICT, - .subtitle_codec = AV_CODEC_ID_TTML, + .p.subtitle_codec = AV_CODEC_ID_TTML, .write_header = ttml_write_header, .write_packet = ttml_write_packet, .write_trailer = ttml_write_trailer, diff --git a/libavformat/uncodedframecrcenc.c b/libavformat/uncodedframecrcenc.c index 99990616d32..4c37ef6e5b2 100644 --- a/libavformat/uncodedframecrcenc.c +++ b/libavformat/uncodedframecrcenc.c @@ -165,14 +165,14 @@ static int write_packet(struct AVFormatContext *s, AVPacket *pkt) return AVERROR(ENOSYS); } -const AVOutputFormat ff_uncodedframecrc_muxer = { - .name = "uncodedframecrc", - .long_name = NULL_IF_CONFIG_SMALL("uncoded framecrc testing"), - .audio_codec = AV_CODEC_ID_PCM_S16LE, - .video_codec = AV_CODEC_ID_RAWVIDEO, +const FFOutputFormat ff_uncodedframecrc_muxer = { + .p.name = "uncodedframecrc", + .p.long_name = NULL_IF_CONFIG_SMALL("uncoded framecrc testing"), + .p.audio_codec = AV_CODEC_ID_PCM_S16LE, + .p.video_codec = AV_CODEC_ID_RAWVIDEO, + .p.flags = AVFMT_VARIABLE_FPS | AVFMT_TS_NONSTRICT | + AVFMT_TS_NEGATIVE, .write_header = write_header, .write_packet = write_packet, .write_uncoded_frame = write_frame, - .flags = AVFMT_VARIABLE_FPS | AVFMT_TS_NONSTRICT | - AVFMT_TS_NEGATIVE, }; diff --git a/libavformat/vc1testenc.c b/libavformat/vc1testenc.c index 4bc95026f56..89b916deeb1 100644 --- a/libavformat/vc1testenc.c +++ b/libavformat/vc1testenc.c @@ -20,6 +20,7 @@ */ #include "avformat.h" #include "internal.h" +#include "mux.h" typedef struct RCVContext { int frames; @@ -80,13 +81,13 @@ static int vc1test_write_trailer(AVFormatContext *s) return 0; } -const AVOutputFormat ff_vc1t_muxer = { - .name = "vc1test", - .long_name = NULL_IF_CONFIG_SMALL("VC-1 test bitstream"), - .extensions = "rcv", +const FFOutputFormat ff_vc1t_muxer = { + .p.name = "vc1test", + .p.long_name = NULL_IF_CONFIG_SMALL("VC-1 test bitstream"), + .p.extensions = "rcv", .priv_data_size = sizeof(RCVContext), - .audio_codec = AV_CODEC_ID_NONE, - .video_codec = AV_CODEC_ID_WMV3, + .p.audio_codec = AV_CODEC_ID_NONE, + .p.video_codec = AV_CODEC_ID_WMV3, .write_header = vc1test_write_header, .write_packet = vc1test_write_packet, .write_trailer = vc1test_write_trailer, diff --git a/libavformat/vocenc.c b/libavformat/vocenc.c index 59c2bbba7b5..8739a177157 100644 --- a/libavformat/vocenc.c +++ b/libavformat/vocenc.c @@ -21,6 +21,7 @@ #include "voc.h" #include "internal.h" +#include "mux.h" typedef struct voc_enc_context { @@ -96,17 +97,17 @@ static int voc_write_trailer(AVFormatContext *s) return 0; } -const AVOutputFormat ff_voc_muxer = { - .name = "voc", - .long_name = NULL_IF_CONFIG_SMALL("Creative Voice"), - .mime_type = "audio/x-voc", - .extensions = "voc", +const FFOutputFormat ff_voc_muxer = { + .p.name = "voc", + .p.long_name = NULL_IF_CONFIG_SMALL("Creative Voice"), + .p.mime_type = "audio/x-voc", + .p.extensions = "voc", .priv_data_size = sizeof(VocEncContext), - .audio_codec = AV_CODEC_ID_PCM_S16LE, - .video_codec = AV_CODEC_ID_NONE, + .p.audio_codec = AV_CODEC_ID_PCM_S16LE, + .p.video_codec = AV_CODEC_ID_NONE, .write_header = voc_write_header, .write_packet = voc_write_packet, .write_trailer = voc_write_trailer, - .codec_tag = ff_voc_codec_tags_list, - .flags = AVFMT_NOTIMESTAMPS, + .p.codec_tag = ff_voc_codec_tags_list, + .p.flags = AVFMT_NOTIMESTAMPS, }; diff --git a/libavformat/wavenc.c b/libavformat/wavenc.c index 3531a8f909d..c12c0909349 100644 --- a/libavformat/wavenc.c +++ b/libavformat/wavenc.c @@ -46,6 +46,7 @@ #include "avio.h" #include "avio_internal.h" #include "internal.h" +#include "mux.h" #include "riff.h" #define RF64_AUTO (-1) @@ -506,21 +507,21 @@ static const AVClass wav_muxer_class = { .version = LIBAVUTIL_VERSION_INT, }; -const AVOutputFormat ff_wav_muxer = { - .name = "wav", - .long_name = NULL_IF_CONFIG_SMALL("WAV / WAVE (Waveform Audio)"), - .mime_type = "audio/x-wav", - .extensions = "wav", +const FFOutputFormat ff_wav_muxer = { + .p.name = "wav", + .p.long_name = NULL_IF_CONFIG_SMALL("WAV / WAVE (Waveform Audio)"), + .p.mime_type = "audio/x-wav", + .p.extensions = "wav", .priv_data_size = sizeof(WAVMuxContext), - .audio_codec = AV_CODEC_ID_PCM_S16LE, - .video_codec = AV_CODEC_ID_NONE, + .p.audio_codec = AV_CODEC_ID_PCM_S16LE, + .p.video_codec = AV_CODEC_ID_NONE, .write_header = wav_write_header, .write_packet = wav_write_packet, .write_trailer = wav_write_trailer, .deinit = wav_deinit, - .flags = AVFMT_TS_NONSTRICT, - .codec_tag = ff_wav_codec_tags_list, - .priv_class = &wav_muxer_class, + .p.flags = AVFMT_TS_NONSTRICT, + .p.codec_tag = ff_wav_codec_tags_list, + .p.priv_class = &wav_muxer_class, }; #endif /* CONFIG_WAV_MUXER */ @@ -615,18 +616,18 @@ static int w64_write_trailer(AVFormatContext *s) return 0; } -const AVOutputFormat ff_w64_muxer = { - .name = "w64", - .long_name = NULL_IF_CONFIG_SMALL("Sony Wave64"), - .extensions = "w64", +const FFOutputFormat ff_w64_muxer = { + .p.name = "w64", + .p.long_name = NULL_IF_CONFIG_SMALL("Sony Wave64"), + .p.extensions = "w64", .priv_data_size = sizeof(WAVMuxContext), - .audio_codec = AV_CODEC_ID_PCM_S16LE, - .video_codec = AV_CODEC_ID_NONE, + .p.audio_codec = AV_CODEC_ID_PCM_S16LE, + .p.video_codec = AV_CODEC_ID_NONE, .init = w64_init, .write_header = w64_write_header, .write_packet = wav_write_packet, .write_trailer = w64_write_trailer, - .flags = AVFMT_TS_NONSTRICT, - .codec_tag = ff_wav_codec_tags_list, + .p.flags = AVFMT_TS_NONSTRICT, + .p.codec_tag = ff_wav_codec_tags_list, }; #endif /* CONFIG_W64_MUXER */ diff --git a/libavformat/webm_chunk.c b/libavformat/webm_chunk.c index 916ed0cbaba..494a83f5078 100644 --- a/libavformat/webm_chunk.c +++ b/libavformat/webm_chunk.c @@ -292,18 +292,18 @@ static const AVClass webm_chunk_class = { .version = LIBAVUTIL_VERSION_INT, }; -const AVOutputFormat ff_webm_chunk_muxer = { - .name = "webm_chunk", - .long_name = NULL_IF_CONFIG_SMALL("WebM Chunk Muxer"), - .mime_type = "video/webm", - .extensions = "chk", - .flags = AVFMT_NOFILE | AVFMT_GLOBALHEADER | AVFMT_NEEDNUMBER | +const FFOutputFormat ff_webm_chunk_muxer = { + .p.name = "webm_chunk", + .p.long_name = NULL_IF_CONFIG_SMALL("WebM Chunk Muxer"), + .p.mime_type = "video/webm", + .p.extensions = "chk", + .p.flags = AVFMT_NOFILE | AVFMT_GLOBALHEADER | AVFMT_NEEDNUMBER | AVFMT_TS_NONSTRICT, + .p.priv_class = &webm_chunk_class, .priv_data_size = sizeof(WebMChunkContext), .init = webm_chunk_init, .write_header = webm_chunk_write_header, .write_packet = webm_chunk_write_packet, .write_trailer = webm_chunk_write_trailer, .deinit = webm_chunk_deinit, - .priv_class = &webm_chunk_class, }; diff --git a/libavformat/webmdashenc.c b/libavformat/webmdashenc.c index f8f2274556d..0d6c4a2072e 100644 --- a/libavformat/webmdashenc.c +++ b/libavformat/webmdashenc.c @@ -32,6 +32,7 @@ #include "avformat.h" #include "matroska.h" +#include "mux.h" #include "libavutil/avstring.h" #include "libavutil/dict.h" @@ -540,13 +541,13 @@ static const AVClass webm_dash_class = { .version = LIBAVUTIL_VERSION_INT, }; -const AVOutputFormat ff_webm_dash_manifest_muxer = { - .name = "webm_dash_manifest", - .long_name = NULL_IF_CONFIG_SMALL("WebM DASH Manifest"), - .mime_type = "application/xml", - .extensions = "xml", +const FFOutputFormat ff_webm_dash_manifest_muxer = { + .p.name = "webm_dash_manifest", + .p.long_name = NULL_IF_CONFIG_SMALL("WebM DASH Manifest"), + .p.mime_type = "application/xml", + .p.extensions = "xml", .priv_data_size = sizeof(WebMDashMuxContext), .write_header = webm_dash_manifest_write_header, .write_packet = webm_dash_manifest_write_packet, - .priv_class = &webm_dash_class, + .p.priv_class = &webm_dash_class, }; diff --git a/libavformat/webpenc.c b/libavformat/webpenc.c index 8a5c29201a8..b3f5bdc9b57 100644 --- a/libavformat/webpenc.c +++ b/libavformat/webpenc.c @@ -23,6 +23,7 @@ #include "libavutil/opt.h" #include "avformat.h" #include "internal.h" +#include "mux.h" typedef struct WebpContext{ AVClass *class; @@ -208,15 +209,15 @@ static const AVClass webp_muxer_class = { .version = LIBAVUTIL_VERSION_INT, .option = options, }; -const AVOutputFormat ff_webp_muxer = { - .name = "webp", - .long_name = NULL_IF_CONFIG_SMALL("WebP"), - .extensions = "webp", +const FFOutputFormat ff_webp_muxer = { + .p.name = "webp", + .p.long_name = NULL_IF_CONFIG_SMALL("WebP"), + .p.extensions = "webp", .priv_data_size = sizeof(WebpContext), - .video_codec = AV_CODEC_ID_WEBP, + .p.video_codec = AV_CODEC_ID_WEBP, .init = webp_init, .write_packet = webp_write_packet, .write_trailer = webp_write_trailer, - .priv_class = &webp_muxer_class, - .flags = AVFMT_VARIABLE_FPS, + .p.priv_class = &webp_muxer_class, + .p.flags = AVFMT_VARIABLE_FPS, }; diff --git a/libavformat/webvttenc.c b/libavformat/webvttenc.c index fcff80c4bf3..13370453251 100644 --- a/libavformat/webvttenc.c +++ b/libavformat/webvttenc.c @@ -26,6 +26,7 @@ #include "avformat.h" #include "internal.h" +#include "mux.h" static void webvtt_write_time(AVIOContext *pb, int64_t millisec) { @@ -102,13 +103,13 @@ static int webvtt_write_packet(AVFormatContext *ctx, AVPacket *pkt) return 0; } -const AVOutputFormat ff_webvtt_muxer = { - .name = "webvtt", - .long_name = NULL_IF_CONFIG_SMALL("WebVTT subtitle"), - .extensions = "vtt", - .mime_type = "text/vtt", - .flags = AVFMT_VARIABLE_FPS | AVFMT_TS_NONSTRICT, - .subtitle_codec = AV_CODEC_ID_WEBVTT, +const FFOutputFormat ff_webvtt_muxer = { + .p.name = "webvtt", + .p.long_name = NULL_IF_CONFIG_SMALL("WebVTT subtitle"), + .p.extensions = "vtt", + .p.mime_type = "text/vtt", + .p.flags = AVFMT_VARIABLE_FPS | AVFMT_TS_NONSTRICT, + .p.subtitle_codec = AV_CODEC_ID_WEBVTT, .write_header = webvtt_write_header, .write_packet = webvtt_write_packet, }; diff --git a/libavformat/westwood_audenc.c b/libavformat/westwood_audenc.c index a2401eff5a7..84a871e4782 100644 --- a/libavformat/westwood_audenc.c +++ b/libavformat/westwood_audenc.c @@ -31,6 +31,7 @@ #include "avformat.h" #include "avio_internal.h" #include "internal.h" +#include "mux.h" #include #define AUD_CHUNK_SIGNATURE 0x0000DEAF @@ -125,13 +126,13 @@ static int wsaud_write_trailer(AVFormatContext *ctx) return 0; } -const AVOutputFormat ff_wsaud_muxer = { - .name = "wsaud", - .long_name = NULL_IF_CONFIG_SMALL("Westwood Studios audio"), - .extensions = "aud", +const FFOutputFormat ff_wsaud_muxer = { + .p.name = "wsaud", + .p.long_name = NULL_IF_CONFIG_SMALL("Westwood Studios audio"), + .p.extensions = "aud", .priv_data_size = sizeof(AUDMuxContext), - .audio_codec = AV_CODEC_ID_ADPCM_IMA_WS, - .video_codec = AV_CODEC_ID_NONE, + .p.audio_codec = AV_CODEC_ID_ADPCM_IMA_WS, + .p.video_codec = AV_CODEC_ID_NONE, .init = wsaud_write_init, .write_header = wsaud_write_header, .write_packet = wsaud_write_packet, diff --git a/libavformat/wtvenc.c b/libavformat/wtvenc.c index 62dca62b062..c0e56216467 100644 --- a/libavformat/wtvenc.c +++ b/libavformat/wtvenc.c @@ -829,15 +829,15 @@ static int write_trailer(AVFormatContext *s) return 0; } -const AVOutputFormat ff_wtv_muxer = { - .name = "wtv", - .long_name = NULL_IF_CONFIG_SMALL("Windows Television (WTV)"), - .extensions = "wtv", +const FFOutputFormat ff_wtv_muxer = { + .p.name = "wtv", + .p.long_name = NULL_IF_CONFIG_SMALL("Windows Television (WTV)"), + .p.extensions = "wtv", .priv_data_size = sizeof(WtvContext), - .audio_codec = AV_CODEC_ID_AC3, - .video_codec = AV_CODEC_ID_MPEG2VIDEO, + .p.audio_codec = AV_CODEC_ID_AC3, + .p.video_codec = AV_CODEC_ID_MPEG2VIDEO, .write_header = write_header, .write_packet = write_packet, .write_trailer = write_trailer, - .codec_tag = ff_riff_codec_tags_list, + .p.codec_tag = ff_riff_codec_tags_list, }; diff --git a/libavformat/wvenc.c b/libavformat/wvenc.c index 0dca2f7996c..9d9190f2527 100644 --- a/libavformat/wvenc.c +++ b/libavformat/wvenc.c @@ -24,6 +24,7 @@ #include "apetag.h" #include "avformat.h" +#include "mux.h" #include "wv.h" typedef struct WvMuxContext { @@ -76,16 +77,16 @@ static av_cold int wv_write_trailer(AVFormatContext *ctx) return 0; } -const AVOutputFormat ff_wv_muxer = { - .name = "wv", - .long_name = NULL_IF_CONFIG_SMALL("raw WavPack"), - .mime_type = "audio/x-wavpack", - .extensions = "wv", +const FFOutputFormat ff_wv_muxer = { + .p.name = "wv", + .p.long_name = NULL_IF_CONFIG_SMALL("raw WavPack"), + .p.mime_type = "audio/x-wavpack", + .p.extensions = "wv", .priv_data_size = sizeof(WvMuxContext), - .audio_codec = AV_CODEC_ID_WAVPACK, - .video_codec = AV_CODEC_ID_NONE, + .p.audio_codec = AV_CODEC_ID_WAVPACK, + .p.video_codec = AV_CODEC_ID_NONE, .init = wv_init, .write_packet = wv_write_packet, .write_trailer = wv_write_trailer, - .flags = AVFMT_NOTIMESTAMPS, + .p.flags = AVFMT_NOTIMESTAMPS, }; diff --git a/libavformat/yuv4mpegenc.c b/libavformat/yuv4mpegenc.c index fca0ee31207..fc6b08e0cd4 100644 --- a/libavformat/yuv4mpegenc.c +++ b/libavformat/yuv4mpegenc.c @@ -22,6 +22,7 @@ #include "libavutil/pixdesc.h" #include "avformat.h" #include "internal.h" +#include "mux.h" #include "yuv4mpeg.h" static int yuv4_write_header(AVFormatContext *s) @@ -282,12 +283,12 @@ static int yuv4_init(AVFormatContext *s) return 0; } -const AVOutputFormat ff_yuv4mpegpipe_muxer = { - .name = "yuv4mpegpipe", - .long_name = NULL_IF_CONFIG_SMALL("YUV4MPEG pipe"), - .extensions = "y4m", - .audio_codec = AV_CODEC_ID_NONE, - .video_codec = AV_CODEC_ID_WRAPPED_AVFRAME, +const FFOutputFormat ff_yuv4mpegpipe_muxer = { + .p.name = "yuv4mpegpipe", + .p.long_name = NULL_IF_CONFIG_SMALL("YUV4MPEG pipe"), + .p.extensions = "y4m", + .p.audio_codec = AV_CODEC_ID_NONE, + .p.video_codec = AV_CODEC_ID_WRAPPED_AVFRAME, .init = yuv4_init, .write_header = yuv4_write_header, .write_packet = yuv4_write_packet, From f843460eb790d37e444e5946628f228421916537 Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt Date: Fri, 27 Jan 2023 15:05:55 +0100 Subject: [PATCH 0190/2172] avcodec/avcodec: Remove AV_CODEC_FLAG2_DROP_FRAME_TIMECODE It has been deprecated in 94d68a41fabb55dd8c7e59b88fe4a28a637d1e5f and can't be set via AVOptions. The only codecs that use it (the MPEG-1/2 encoders) have private options for this. So remove it. Signed-off-by: Andreas Rheinhardt Signed-off-by: Anton Khirnov --- libavcodec/avcodec.h | 5 ----- libavcodec/mpeg12enc.c | 1 - 2 files changed, 6 deletions(-) diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h index e8333a94f16..3884e52de93 100644 --- a/libavcodec/avcodec.h +++ b/libavcodec/avcodec.h @@ -352,11 +352,6 @@ typedef struct RcOverride{ */ #define AV_CODEC_FLAG2_LOCAL_HEADER (1 << 3) -/** - * timecode is in drop frame format. DEPRECATED!!!! - */ -#define AV_CODEC_FLAG2_DROP_FRAME_TIMECODE (1 << 13) - /** * Input bitstream might be truncated at a packet boundaries * instead of only at frame boundaries. diff --git a/libavcodec/mpeg12enc.c b/libavcodec/mpeg12enc.c index b5951e43070..26cf33a3c68 100644 --- a/libavcodec/mpeg12enc.c +++ b/libavcodec/mpeg12enc.c @@ -249,7 +249,6 @@ static av_cold int encode_init(AVCodecContext *avctx) } } - 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 && mpeg12->frame_rate_index != 4) { From cb7de655899f8a18d2361942a309a425d4486895 Mon Sep 17 00:00:00 2001 From: James Almer Date: Mon, 9 Jan 2023 10:38:43 -0300 Subject: [PATCH 0191/2172] avcodec: remove FF_API_OPENH264_SLICE_MODE Signed-off-by: James Almer --- libavcodec/libopenh264enc.c | 16 ---------------- libavcodec/version_major.h | 1 - 2 files changed, 17 deletions(-) diff --git a/libavcodec/libopenh264enc.c b/libavcodec/libopenh264enc.c index 6934fd481ce..4dd15b0afe5 100644 --- a/libavcodec/libopenh264enc.c +++ b/libavcodec/libopenh264enc.c @@ -63,22 +63,6 @@ typedef struct SVCContext { #define VE AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_ENCODING_PARAM #define DEPRECATED AV_OPT_FLAG_DEPRECATED static const AVOption options[] = { -#if FF_API_OPENH264_SLICE_MODE -#if OPENH264_VER_AT_LEAST(1, 6) - { "slice_mode", "set slice mode, use slices/max_nal_size", OFFSET(slice_mode), AV_OPT_TYPE_INT, { .i64 = SM_FIXEDSLCNUM_SLICE }, SM_SINGLE_SLICE, SM_RESERVED, VE|DEPRECATED, "slice_mode" }, -#else - { "slice_mode", "set slice mode, use slices/max_nal_size", OFFSET(slice_mode), AV_OPT_TYPE_INT, { .i64 = SM_AUTO_SLICE }, SM_SINGLE_SLICE, SM_RESERVED, VE|DEPRECATED, "slice_mode" }, -#endif - { "fixed", "a fixed number of slices", 0, AV_OPT_TYPE_CONST, { .i64 = SM_FIXEDSLCNUM_SLICE }, 0, 0, VE, "slice_mode" }, -#if OPENH264_VER_AT_LEAST(1, 6) - { "dyn", "Size limited (compatibility name)", 0, AV_OPT_TYPE_CONST, { .i64 = SM_SIZELIMITED_SLICE }, 0, 0, VE, "slice_mode" }, - { "sizelimited", "Size limited", 0, AV_OPT_TYPE_CONST, { .i64 = SM_SIZELIMITED_SLICE }, 0, 0, VE, "slice_mode" }, -#else - { "rowmb", "one slice per row of macroblocks", 0, AV_OPT_TYPE_CONST, { .i64 = SM_ROWMB_SLICE }, 0, 0, VE, "slice_mode" }, - { "auto", "automatic number of slices according to number of threads", 0, AV_OPT_TYPE_CONST, { .i64 = SM_AUTO_SLICE }, 0, 0, VE, "slice_mode" }, - { "dyn", "Dynamic slicing", 0, AV_OPT_TYPE_CONST, { .i64 = SM_DYN_SLICE }, 0, 0, VE, "slice_mode" }, -#endif -#endif { "loopfilter", "enable loop filter", OFFSET(loopfilter), AV_OPT_TYPE_INT, { .i64 = 1 }, 0, 1, VE }, { "profile", "set profile restrictions", OFFSET(profile), AV_OPT_TYPE_INT, { .i64 = FF_PROFILE_UNKNOWN }, FF_PROFILE_UNKNOWN, 0xffff, VE, "profile" }, #define PROFILE(name, value) name, NULL, 0, AV_OPT_TYPE_CONST, { .i64 = value }, 0, 0, VE, "profile" diff --git a/libavcodec/version_major.h b/libavcodec/version_major.h index f38566f62c2..535d10e7ecf 100644 --- a/libavcodec/version_major.h +++ b/libavcodec/version_major.h @@ -37,7 +37,6 @@ * at once through the bump. This improves the git bisect-ability of the change. */ -#define FF_API_OPENH264_SLICE_MODE (LIBAVCODEC_VERSION_MAJOR < 60) #define FF_API_OPENH264_CABAC (LIBAVCODEC_VERSION_MAJOR < 60) #define FF_API_UNUSED_CODEC_CAPS (LIBAVCODEC_VERSION_MAJOR < 60) #define FF_API_THREAD_SAFE_CALLBACKS (LIBAVCODEC_VERSION_MAJOR < 60) From 86806347d853b1b4297f5bf6ff6996d35afac5fc Mon Sep 17 00:00:00 2001 From: James Almer Date: Mon, 9 Jan 2023 10:39:16 -0300 Subject: [PATCH 0192/2172] avcodec: remove FF_API_OPENH264_CABAC Signed-off-by: James Almer --- libavcodec/libopenh264enc.c | 6 ------ libavcodec/version_major.h | 1 - 2 files changed, 7 deletions(-) diff --git a/libavcodec/libopenh264enc.c b/libavcodec/libopenh264enc.c index 4dd15b0afe5..8b4755f5ba4 100644 --- a/libavcodec/libopenh264enc.c +++ b/libavcodec/libopenh264enc.c @@ -50,9 +50,6 @@ typedef struct SVCContext { int max_nal_size; int skip_frames; int skipped; -#if FF_API_OPENH264_CABAC - int cabac; // deprecated -#endif int coder; // rate control mode @@ -72,9 +69,6 @@ static const AVOption options[] = { #undef PROFILE { "max_nal_size", "set maximum NAL size in bytes", OFFSET(max_nal_size), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, INT_MAX, VE }, { "allow_skip_frames", "allow skipping frames to hit the target bitrate", OFFSET(skip_frames), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, VE }, -#if FF_API_OPENH264_CABAC - { "cabac", "Enable cabac(deprecated, use coder)", OFFSET(cabac), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 1, VE|DEPRECATED }, -#endif { "coder", "Coder type", OFFSET(coder), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, 1, VE, "coder" }, { "default", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = -1 }, INT_MIN, INT_MAX, VE, "coder" }, { "cavlc", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = 0 }, INT_MIN, INT_MAX, VE, "coder" }, diff --git a/libavcodec/version_major.h b/libavcodec/version_major.h index 535d10e7ecf..06e82facbc9 100644 --- a/libavcodec/version_major.h +++ b/libavcodec/version_major.h @@ -37,7 +37,6 @@ * at once through the bump. This improves the git bisect-ability of the change. */ -#define FF_API_OPENH264_CABAC (LIBAVCODEC_VERSION_MAJOR < 60) #define FF_API_UNUSED_CODEC_CAPS (LIBAVCODEC_VERSION_MAJOR < 60) #define FF_API_THREAD_SAFE_CALLBACKS (LIBAVCODEC_VERSION_MAJOR < 60) #define FF_API_DEBUG_MV (LIBAVCODEC_VERSION_MAJOR < 60) From 2f9cd8861797df5b4d2e36143dfa8268b65cfd38 Mon Sep 17 00:00:00 2001 From: James Almer Date: Mon, 9 Jan 2023 10:40:00 -0300 Subject: [PATCH 0193/2172] avcodec: remove FF_API_UNUSED_CODEC_CAPS Signed-off-by: James Almer --- libavcodec/codec.h | 11 ----------- libavcodec/version_major.h | 1 - 2 files changed, 12 deletions(-) diff --git a/libavcodec/codec.h b/libavcodec/codec.h index 67f9120b447..336a785e188 100644 --- a/libavcodec/codec.h +++ b/libavcodec/codec.h @@ -143,17 +143,6 @@ */ #define AV_CODEC_CAP_AVOID_PROBING (1 << 17) -#if FF_API_UNUSED_CODEC_CAPS -/** - * Deprecated and unused. Use AVCodecDescriptor.props instead - */ -#define AV_CODEC_CAP_INTRA_ONLY 0x40000000 -/** - * Deprecated and unused. Use AVCodecDescriptor.props instead - */ -#define AV_CODEC_CAP_LOSSLESS 0x80000000 -#endif - /** * Codec is backed by a hardware implementation. Typically used to * identify a non-hwaccel hardware decoder. For information about hwaccels, use diff --git a/libavcodec/version_major.h b/libavcodec/version_major.h index 06e82facbc9..269b1f4eaa9 100644 --- a/libavcodec/version_major.h +++ b/libavcodec/version_major.h @@ -37,7 +37,6 @@ * at once through the bump. This improves the git bisect-ability of the change. */ -#define FF_API_UNUSED_CODEC_CAPS (LIBAVCODEC_VERSION_MAJOR < 60) #define FF_API_THREAD_SAFE_CALLBACKS (LIBAVCODEC_VERSION_MAJOR < 60) #define FF_API_DEBUG_MV (LIBAVCODEC_VERSION_MAJOR < 60) #define FF_API_GET_FRAME_CLASS (LIBAVCODEC_VERSION_MAJOR < 60) From e0786a8eeb9e7c8feb057e83f284491f0a87e463 Mon Sep 17 00:00:00 2001 From: James Almer Date: Mon, 23 Jan 2023 19:05:02 -0300 Subject: [PATCH 0194/2172] avcodec: remove FF_API_THREAD_SAFE_CALLBACKS Signed-off-by: James Almer Signed-off-by: Anton Khirnov --- fftools/ffmpeg.c | 5 - libavcodec/avcodec.h | 21 --- libavcodec/decode.c | 13 -- libavcodec/encode.c | 7 +- libavcodec/frame_thread_encoder.c | 20 --- libavcodec/pthread_frame.c | 237 +----------------------------- libavcodec/thread.h | 12 -- libavcodec/utils.c | 5 - libavcodec/version_major.h | 1 - 9 files changed, 6 insertions(+), 315 deletions(-) diff --git a/fftools/ffmpeg.c b/fftools/ffmpeg.c index a9c84f507c4..064ec6d4b3f 100644 --- a/fftools/ffmpeg.c +++ b/fftools/ffmpeg.c @@ -2804,11 +2804,6 @@ static int init_input_stream(InputStream *ist, char *error, int error_len) ist->dec_ctx->opaque = ist; ist->dec_ctx->get_format = get_format; -#if LIBAVCODEC_VERSION_MAJOR < 60 - AV_NOWARN_DEPRECATED({ - ist->dec_ctx->thread_safe_callbacks = 1; - }) -#endif if (ist->dec_ctx->codec_id == AV_CODEC_ID_DVB_SUBTITLE && (ist->decoding_needed & DECODING_FOR_OST)) { diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h index 3884e52de93..22d7f506494 100644 --- a/libavcodec/avcodec.h +++ b/libavcodec/avcodec.h @@ -1526,27 +1526,6 @@ typedef struct AVCodecContext { */ int active_thread_type; -#if FF_API_THREAD_SAFE_CALLBACKS - /** - * Set by the client if its custom get_buffer() callback can be called - * synchronously from another thread, which allows faster multithreaded decoding. - * draw_horiz_band() will be called from other threads regardless of this setting. - * Ignored if the default get_buffer() is used. - * - encoding: Set by user. - * - decoding: Set by user. - * - * @deprecated the custom get_buffer2() callback should always be - * thread-safe. Thread-unsafe get_buffer2() implementations will be - * invalid starting with LIBAVCODEC_VERSION_MAJOR=60; in other words, - * libavcodec will behave as if this field was always set to 1. - * Callers that want to be forward compatible with future libavcodec - * versions should wrap access to this field in - * `#if LIBAVCODEC_VERSION_MAJOR < 60` - */ - attribute_deprecated - int thread_safe_callbacks; -#endif - /** * The codec may call this to execute several independent things. * It will return only after finishing all tasks. diff --git a/libavcodec/decode.c b/libavcodec/decode.c index 78bf3ba547b..34e67a649bf 100644 --- a/libavcodec/decode.c +++ b/libavcodec/decode.c @@ -1604,19 +1604,6 @@ int ff_decode_preinit(AVCodecContext *avctx) * free the already allocated subtitle_header before overwriting it */ av_freep(&avctx->subtitle_header); -#if FF_API_THREAD_SAFE_CALLBACKS -FF_DISABLE_DEPRECATION_WARNINGS - if ((avctx->thread_type & FF_THREAD_FRAME) && - avctx->get_buffer2 != avcodec_default_get_buffer2 && - !avctx->thread_safe_callbacks) { - av_log(avctx, AV_LOG_WARNING, "Requested frame threading with a " - "custom get_buffer2() implementation which is not marked as " - "thread safe. This is not supported anymore, make your " - "callback thread-safe.\n"); - } -FF_ENABLE_DEPRECATION_WARNINGS -#endif - if (avctx->codec->max_lowres < avctx->lowres || avctx->lowres < 0) { av_log(avctx, AV_LOG_WARNING, "The maximum value for lowres supported by the decoder is %d\n", avctx->codec->max_lowres); diff --git a/libavcodec/encode.c b/libavcodec/encode.c index b0a9625ca92..6499d962cac 100644 --- a/libavcodec/encode.c +++ b/libavcodec/encode.c @@ -259,10 +259,9 @@ int ff_encode_encode_cb(AVCodecContext *avctx, AVPacket *avpkt, unref: av_packet_unref(avpkt); } -#if !FF_API_THREAD_SAFE_CALLBACKS + if (frame) av_frame_unref(frame); -#endif return ret; } @@ -303,10 +302,6 @@ static int encode_simple_internal(AVCodecContext *avctx, AVPacket *avpkt) ret = ff_thread_video_encode_frame(avctx, avpkt, frame, &got_packet); else { ret = ff_encode_encode_cb(avctx, avpkt, frame, &got_packet); -#if FF_API_THREAD_SAFE_CALLBACKS - if (frame) - av_frame_unref(frame); -#endif } if (avci->draining && !got_packet) diff --git a/libavcodec/frame_thread_encoder.c b/libavcodec/frame_thread_encoder.c index 35775ae823e..62d9580ad4c 100644 --- a/libavcodec/frame_thread_encoder.c +++ b/libavcodec/frame_thread_encoder.c @@ -48,9 +48,6 @@ typedef struct{ typedef struct{ AVCodecContext *parent_avctx; -#if FF_API_THREAD_SAFE_CALLBACKS - pthread_mutex_t buffer_mutex; -#endif pthread_mutex_t task_fifo_mutex; /* Used to guard (next_)task_index */ pthread_cond_t task_fifo_cond; @@ -70,15 +67,9 @@ typedef struct{ } ThreadContext; #define OFF(member) offsetof(ThreadContext, member) -#if FF_API_THREAD_SAFE_CALLBACKS -DEFINE_OFFSET_ARRAY(ThreadContext, thread_ctx, pthread_init_cnt, - (OFF(buffer_mutex), OFF(task_fifo_mutex), OFF(finished_task_mutex)), - (OFF(task_fifo_cond), OFF(finished_task_cond))); -#else DEFINE_OFFSET_ARRAY(ThreadContext, thread_ctx, pthread_init_cnt, (OFF(task_fifo_mutex), OFF(finished_task_mutex)), (OFF(task_fifo_cond), OFF(finished_task_cond))); -#endif #undef OFF static void * attribute_align_arg worker(void *v){ @@ -112,11 +103,6 @@ static void * attribute_align_arg worker(void *v){ pkt = task->outdata; ret = ff_encode_encode_cb(avctx, pkt, frame, &task->got_packet); -#if FF_API_THREAD_SAFE_CALLBACKS - pthread_mutex_lock(&c->buffer_mutex); - av_frame_unref(frame); - pthread_mutex_unlock(&c->buffer_mutex); -#endif pthread_mutex_lock(&c->finished_task_mutex); task->return_code = ret; task->finished = 1; @@ -124,13 +110,7 @@ static void * attribute_align_arg worker(void *v){ pthread_mutex_unlock(&c->finished_task_mutex); } end: -#if FF_API_THREAD_SAFE_CALLBACKS - pthread_mutex_lock(&c->buffer_mutex); -#endif avcodec_close(avctx); -#if FF_API_THREAD_SAFE_CALLBACKS - pthread_mutex_unlock(&c->buffer_mutex); -#endif av_freep(&avctx); return NULL; } diff --git a/libavcodec/pthread_frame.c b/libavcodec/pthread_frame.c index ae8d051acd7..71edd6b3ecd 100644 --- a/libavcodec/pthread_frame.c +++ b/libavcodec/pthread_frame.c @@ -99,22 +99,6 @@ typedef struct PerThreadContext { atomic_int state; -#if FF_API_THREAD_SAFE_CALLBACKS - /** - * Array of frames passed to ff_thread_release_buffer(). - * Frames are released after all threads referencing them are finished. - */ - AVFrame **released_buffers; - int num_released_buffers; - int released_buffers_allocated; - - AVFrame *requested_frame; ///< AVFrame the codec passed to get_buffer() - int requested_flags; ///< flags passed to get_buffer() for requested_frame - - const enum AVPixelFormat *available_formats; ///< Format array for get_format() - enum AVPixelFormat result_format; ///< get_format() result -#endif - int die; ///< Set when the thread should exit. int hwaccel_serializing; @@ -156,11 +140,6 @@ typedef struct FrameThreadContext { void *stash_hwaccel_priv; } FrameThreadContext; -#if FF_API_THREAD_SAFE_CALLBACKS -#define THREAD_SAFE_CALLBACKS(avctx) \ -((avctx)->thread_safe_callbacks || (avctx)->get_buffer2 == avcodec_default_get_buffer2) -#endif - static void async_lock(FrameThreadContext *fctx) { pthread_mutex_lock(&fctx->async_mutex); @@ -212,14 +191,8 @@ static attribute_align_arg void *frame_worker_thread(void *arg) if (p->die) break; -FF_DISABLE_DEPRECATION_WARNINGS - if (!codec->update_thread_context -#if FF_API_THREAD_SAFE_CALLBACKS - && THREAD_SAFE_CALLBACKS(avctx) -#endif - ) + if (!codec->update_thread_context) ff_thread_finish_setup(avctx); -FF_ENABLE_DEPRECATION_WARNINGS /* If a decoder supports hwaccel, then it must call ff_get_format(). * Since that call must happen before ff_thread_finish_setup(), the @@ -394,11 +367,6 @@ static int update_context_from_user(AVCodecContext *dst, AVCodecContext *src) FF_DISABLE_DEPRECATION_WARNINGS dst->reordered_opaque = src->reordered_opaque; FF_ENABLE_DEPRECATION_WARNINGS -#endif -#if FF_API_THREAD_SAFE_CALLBACKS -FF_DISABLE_DEPRECATION_WARNINGS - dst->thread_safe_callbacks = src->thread_safe_callbacks; -FF_ENABLE_DEPRECATION_WARNINGS #endif if (src->slice_count && src->slice_offset) { @@ -421,29 +389,6 @@ FF_ENABLE_DEPRECATION_WARNINGS return 0; } -#if FF_API_THREAD_SAFE_CALLBACKS -/// Releases the buffers that this decoding thread was the last user of. -static void release_delayed_buffers(PerThreadContext *p) -{ - FrameThreadContext *fctx = p->parent; - - while (p->num_released_buffers > 0) { - AVFrame *f; - - pthread_mutex_lock(&fctx->buffer_mutex); - - // fix extended data in case the caller screwed it up - av_assert0(p->avctx->codec_type == AVMEDIA_TYPE_VIDEO || - p->avctx->codec_type == AVMEDIA_TYPE_AUDIO); - f = p->released_buffers[--p->num_released_buffers]; - f->extended_data = f->data; - av_frame_unref(f); - - pthread_mutex_unlock(&fctx->buffer_mutex); - } -} -#endif - static int submit_packet(PerThreadContext *p, AVCodecContext *user_avctx, AVPacket *avpkt) { @@ -466,10 +411,6 @@ static int submit_packet(PerThreadContext *p, AVCodecContext *user_avctx, (p->avctx->debug & FF_DEBUG_THREADS) != 0, memory_order_relaxed); -#if FF_API_THREAD_SAFE_CALLBACKS - release_delayed_buffers(p); -#endif - if (prev_thread) { int err; if (atomic_load(&prev_thread->state) == STATE_SETTING_UP) { @@ -504,44 +445,6 @@ static int submit_packet(PerThreadContext *p, AVCodecContext *user_avctx, pthread_cond_signal(&p->input_cond); pthread_mutex_unlock(&p->mutex); -#if FF_API_THREAD_SAFE_CALLBACKS -FF_DISABLE_DEPRECATION_WARNINGS - /* - * If the client doesn't have a thread-safe get_buffer(), - * then decoding threads call back to the main thread, - * and it calls back to the client here. - */ - - if (!p->avctx->thread_safe_callbacks && ( - p->avctx->get_format != avcodec_default_get_format || - p->avctx->get_buffer2 != avcodec_default_get_buffer2)) { - while (atomic_load(&p->state) != STATE_SETUP_FINISHED && atomic_load(&p->state) != STATE_INPUT_READY) { - int call_done = 1; - pthread_mutex_lock(&p->progress_mutex); - while (atomic_load(&p->state) == STATE_SETTING_UP) - pthread_cond_wait(&p->progress_cond, &p->progress_mutex); - - switch (atomic_load_explicit(&p->state, memory_order_acquire)) { - case STATE_GET_BUFFER: - p->result = ff_get_buffer(p->avctx, p->requested_frame, p->requested_flags); - break; - case STATE_GET_FORMAT: - p->result_format = ff_get_format(p->avctx, p->available_formats); - break; - default: - call_done = 0; - break; - } - if (call_done) { - atomic_store(&p->state, STATE_SETTING_UP); - pthread_cond_signal(&p->progress_cond); - } - pthread_mutex_unlock(&p->progress_mutex); - } - } -FF_ENABLE_DEPRECATION_WARNINGS -#endif - fctx->prev_thread = p; fctx->next_decoding++; @@ -772,12 +675,6 @@ void ff_frame_thread_free(AVCodecContext *avctx, int thread_count) if (codec->close && p->thread_init != UNINITIALIZED) codec->close(ctx); -#if FF_API_THREAD_SAFE_CALLBACKS - release_delayed_buffers(p); - for (int j = 0; j < p->released_buffers_allocated; j++) - av_frame_free(&p->released_buffers[j]); - av_freep(&p->released_buffers); -#endif if (ctx->priv_data) { if (codec->p.priv_class) av_opt_free(ctx->priv_data); @@ -975,10 +872,6 @@ void ff_thread_flush(AVCodecContext *avctx) av_frame_unref(p->frame); p->result = 0; -#if FF_API_THREAD_SAFE_CALLBACKS - release_delayed_buffers(p); -#endif - if (ffcodec(avctx->codec)->flush) ffcodec(avctx->codec)->flush(p->avctx); } @@ -987,16 +880,12 @@ void ff_thread_flush(AVCodecContext *avctx) int ff_thread_can_start_frame(AVCodecContext *avctx) { PerThreadContext *p = avctx->internal->thread_ctx; -FF_DISABLE_DEPRECATION_WARNINGS + if ((avctx->active_thread_type&FF_THREAD_FRAME) && atomic_load(&p->state) != STATE_SETTING_UP && - (ffcodec(avctx->codec)->update_thread_context -#if FF_API_THREAD_SAFE_CALLBACKS - || !THREAD_SAFE_CALLBACKS(avctx) -#endif - )) { + ffcodec(avctx->codec)->update_thread_context) { return 0; } -FF_ENABLE_DEPRECATION_WARNINGS + return 1; } @@ -1011,80 +900,20 @@ static int thread_get_buffer_internal(AVCodecContext *avctx, AVFrame *f, int fla p = avctx->internal->thread_ctx; FF_DISABLE_DEPRECATION_WARNINGS if (atomic_load(&p->state) != STATE_SETTING_UP && - (ffcodec(avctx->codec)->update_thread_context -#if FF_API_THREAD_SAFE_CALLBACKS - || !THREAD_SAFE_CALLBACKS(avctx) -#endif - )) { + ffcodec(avctx->codec)->update_thread_context) { FF_ENABLE_DEPRECATION_WARNINGS av_log(avctx, AV_LOG_ERROR, "get_buffer() cannot be called after ff_thread_finish_setup()\n"); return -1; } pthread_mutex_lock(&p->parent->buffer_mutex); -#if !FF_API_THREAD_SAFE_CALLBACKS err = ff_get_buffer(avctx, f, flags); -#else -FF_DISABLE_DEPRECATION_WARNINGS - if (THREAD_SAFE_CALLBACKS(avctx)) { - err = ff_get_buffer(avctx, f, flags); - } else { - pthread_mutex_lock(&p->progress_mutex); - p->requested_frame = f; - p->requested_flags = flags; - atomic_store_explicit(&p->state, STATE_GET_BUFFER, memory_order_release); - pthread_cond_broadcast(&p->progress_cond); - - while (atomic_load(&p->state) != STATE_SETTING_UP) - pthread_cond_wait(&p->progress_cond, &p->progress_mutex); - - err = p->result; - - pthread_mutex_unlock(&p->progress_mutex); - - } - if (!THREAD_SAFE_CALLBACKS(avctx) && !ffcodec(avctx->codec)->update_thread_context) - ff_thread_finish_setup(avctx); -FF_ENABLE_DEPRECATION_WARNINGS -#endif pthread_mutex_unlock(&p->parent->buffer_mutex); return err; } -#if FF_API_THREAD_SAFE_CALLBACKS -FF_DISABLE_DEPRECATION_WARNINGS -enum AVPixelFormat ff_thread_get_format(AVCodecContext *avctx, const enum AVPixelFormat *fmt) -{ - enum AVPixelFormat res; - PerThreadContext *p; - if (!(avctx->active_thread_type & FF_THREAD_FRAME) || avctx->thread_safe_callbacks || - avctx->get_format == avcodec_default_get_format) - return ff_get_format(avctx, fmt); - - p = avctx->internal->thread_ctx; - if (atomic_load(&p->state) != STATE_SETTING_UP) { - av_log(avctx, AV_LOG_ERROR, "get_format() cannot be called after ff_thread_finish_setup()\n"); - return -1; - } - pthread_mutex_lock(&p->progress_mutex); - p->available_formats = fmt; - atomic_store(&p->state, STATE_GET_FORMAT); - pthread_cond_broadcast(&p->progress_cond); - - while (atomic_load(&p->state) != STATE_SETTING_UP) - pthread_cond_wait(&p->progress_cond, &p->progress_mutex); - - res = p->result_format; - - pthread_mutex_unlock(&p->progress_mutex); - - return res; -} -FF_ENABLE_DEPRECATION_WARNINGS -#endif - int ff_thread_get_buffer(AVCodecContext *avctx, AVFrame *f, int flags) { int ret = thread_get_buffer_internal(avctx, f, flags); @@ -1126,69 +955,13 @@ int ff_thread_get_ext_buffer(AVCodecContext *avctx, ThreadFrame *f, int flags) void ff_thread_release_buffer(AVCodecContext *avctx, AVFrame *f) { -#if FF_API_THREAD_SAFE_CALLBACKS -FF_DISABLE_DEPRECATION_WARNINGS - PerThreadContext *p; - FrameThreadContext *fctx; - AVFrame *dst; - int ret = 0; - int can_direct_free = !(avctx->active_thread_type & FF_THREAD_FRAME) || - THREAD_SAFE_CALLBACKS(avctx); -FF_ENABLE_DEPRECATION_WARNINGS -#endif - if (!f) return; if (avctx->debug & FF_DEBUG_BUFFERS) av_log(avctx, AV_LOG_DEBUG, "thread_release_buffer called on pic %p\n", f); -#if !FF_API_THREAD_SAFE_CALLBACKS av_frame_unref(f); -#else - // when the frame buffers are not allocated, just reset it to clean state - if (can_direct_free || !f->buf[0]) { - av_frame_unref(f); - return; - } - - p = avctx->internal->thread_ctx; - fctx = p->parent; - pthread_mutex_lock(&fctx->buffer_mutex); - - if (p->num_released_buffers == p->released_buffers_allocated) { - AVFrame **tmp = av_realloc_array(p->released_buffers, p->released_buffers_allocated + 1, - sizeof(*p->released_buffers)); - if (tmp) { - tmp[p->released_buffers_allocated] = av_frame_alloc(); - p->released_buffers = tmp; - } - - if (!tmp || !tmp[p->released_buffers_allocated]) { - ret = AVERROR(ENOMEM); - goto fail; - } - p->released_buffers_allocated++; - } - - dst = p->released_buffers[p->num_released_buffers]; - av_frame_move_ref(dst, f); - - p->num_released_buffers++; - -fail: - pthread_mutex_unlock(&fctx->buffer_mutex); - - // make sure the frame is clean even if we fail to free it - // this leaks, but it is better than crashing - if (ret < 0) { - av_log(avctx, AV_LOG_ERROR, "Could not queue a frame for freeing, this will leak\n"); - memset(f->buf, 0, sizeof(f->buf)); - if (f->extended_buf) - memset(f->extended_buf, 0, f->nb_extended_buf * sizeof(*f->extended_buf)); - av_frame_unref(f); - } -#endif } void ff_thread_release_ext_buffer(AVCodecContext *avctx, ThreadFrame *f) diff --git a/libavcodec/thread.h b/libavcodec/thread.h index d5673f25eaf..88a14cfeb12 100644 --- a/libavcodec/thread.h +++ b/libavcodec/thread.h @@ -62,19 +62,7 @@ int ff_thread_decode_frame(AVCodecContext *avctx, AVFrame *picture, */ void ff_thread_finish_setup(AVCodecContext *avctx); -#if FF_API_THREAD_SAFE_CALLBACKS -/** - * Wrapper around get_format() for frame-multithreaded codecs. - * Call this function instead of avctx->get_format(). - * Cannot be called after the codec has called ff_thread_finish_setup(). - * - * @param avctx The current context. - * @param fmt The list of available formats. - */ -enum AVPixelFormat ff_thread_get_format(AVCodecContext *avctx, const enum AVPixelFormat *fmt); -#else #define ff_thread_get_format ff_get_format -#endif /** * Wrapper around get_buffer() for frame-multithreaded codecs. diff --git a/libavcodec/utils.c b/libavcodec/utils.c index 18a433b1af0..3b58c8a2edd 100644 --- a/libavcodec/utils.c +++ b/libavcodec/utils.c @@ -913,11 +913,6 @@ int ff_thread_ref_frame(ThreadFrame *dst, const ThreadFrame *src) #if !HAVE_THREADS -enum AVPixelFormat ff_thread_get_format(AVCodecContext *avctx, const enum AVPixelFormat *fmt) -{ - return ff_get_format(avctx, fmt); -} - int ff_thread_get_buffer(AVCodecContext *avctx, AVFrame *f, int flags) { return ff_get_buffer(avctx, f, flags); diff --git a/libavcodec/version_major.h b/libavcodec/version_major.h index 269b1f4eaa9..852f4a9cab9 100644 --- a/libavcodec/version_major.h +++ b/libavcodec/version_major.h @@ -37,7 +37,6 @@ * at once through the bump. This improves the git bisect-ability of the change. */ -#define FF_API_THREAD_SAFE_CALLBACKS (LIBAVCODEC_VERSION_MAJOR < 60) #define FF_API_DEBUG_MV (LIBAVCODEC_VERSION_MAJOR < 60) #define FF_API_GET_FRAME_CLASS (LIBAVCODEC_VERSION_MAJOR < 60) #define FF_API_AUTO_THREADS (LIBAVCODEC_VERSION_MAJOR < 60) From 0b3152779d99712d8c54add32bad1703f0087178 Mon Sep 17 00:00:00 2001 From: James Almer Date: Mon, 9 Jan 2023 11:06:53 -0300 Subject: [PATCH 0195/2172] avcodec: remove FF_API_DEBUG_MV Signed-off-by: James Almer --- libavcodec/avcodec.h | 11 ----------- libavcodec/version_major.h | 1 - 2 files changed, 12 deletions(-) diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h index 22d7f506494..f1475fa32ec 100644 --- a/libavcodec/avcodec.h +++ b/libavcodec/avcodec.h @@ -1826,17 +1826,6 @@ typedef struct AVCodecContext { */ int seek_preroll; -#if FF_API_DEBUG_MV - /** - * @deprecated unused - */ - attribute_deprecated - int debug_mv; -#define FF_DEBUG_VIS_MV_P_FOR 0x00000001 //visualize forward predicted MVs of P frames -#define FF_DEBUG_VIS_MV_B_FOR 0x00000002 //visualize forward predicted MVs of B frames -#define FF_DEBUG_VIS_MV_B_BACK 0x00000004 //visualize backward predicted MVs of B frames -#endif - /** * custom intra quantization matrix * - encoding: Set by user, can be NULL. diff --git a/libavcodec/version_major.h b/libavcodec/version_major.h index 852f4a9cab9..f0e347c4828 100644 --- a/libavcodec/version_major.h +++ b/libavcodec/version_major.h @@ -37,7 +37,6 @@ * at once through the bump. This improves the git bisect-ability of the change. */ -#define FF_API_DEBUG_MV (LIBAVCODEC_VERSION_MAJOR < 60) #define FF_API_GET_FRAME_CLASS (LIBAVCODEC_VERSION_MAJOR < 60) #define FF_API_AUTO_THREADS (LIBAVCODEC_VERSION_MAJOR < 60) #define FF_API_INIT_PACKET (LIBAVCODEC_VERSION_MAJOR < 60) From 63258b6f7cc5275a35fa7896321327959309c3da Mon Sep 17 00:00:00 2001 From: James Almer Date: Mon, 9 Jan 2023 11:08:14 -0300 Subject: [PATCH 0196/2172] avcodec: remove FF_API_GET_FRAME_CLASS Signed-off-by: James Almer --- libavcodec/avcodec.h | 8 -------- libavcodec/options.c | 33 --------------------------------- libavcodec/version_major.h | 1 - 3 files changed, 42 deletions(-) diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h index f1475fa32ec..cc7a8faa6a5 100644 --- a/libavcodec/avcodec.h +++ b/libavcodec/avcodec.h @@ -2384,14 +2384,6 @@ void avcodec_free_context(AVCodecContext **avctx); */ const AVClass *avcodec_get_class(void); -#if FF_API_GET_FRAME_CLASS -/** - * @deprecated This function should not be used. - */ -attribute_deprecated -const AVClass *avcodec_get_frame_class(void); -#endif - /** * Get the AVClass for AVSubtitleRect. It can be used in combination with * AV_OPT_SEARCH_FAKE_OBJ for examining options. diff --git a/libavcodec/options.c b/libavcodec/options.c index 9090c94e9c4..a9b35ee1c34 100644 --- a/libavcodec/options.c +++ b/libavcodec/options.c @@ -189,39 +189,6 @@ const AVClass *avcodec_get_class(void) return &av_codec_context_class; } -#if FF_API_GET_FRAME_CLASS -FF_DISABLE_DEPRECATION_WARNINGS -#define FOFFSET(x) offsetof(AVFrame,x) - -static const AVOption frame_options[]={ -{"best_effort_timestamp", "", FOFFSET(best_effort_timestamp), AV_OPT_TYPE_INT64, {.i64 = AV_NOPTS_VALUE }, INT64_MIN, INT64_MAX, 0}, -{"pkt_pos", "", FOFFSET(pkt_pos), AV_OPT_TYPE_INT64, {.i64 = -1 }, INT64_MIN, INT64_MAX, 0}, -{"pkt_size", "", FOFFSET(pkt_size), AV_OPT_TYPE_INT64, {.i64 = -1 }, INT64_MIN, INT64_MAX, 0}, -{"sample_aspect_ratio", "", FOFFSET(sample_aspect_ratio), AV_OPT_TYPE_RATIONAL, {.dbl = 0 }, 0, INT_MAX, 0}, -{"width", "", FOFFSET(width), AV_OPT_TYPE_INT, {.i64 = 0 }, 0, INT_MAX, 0}, -{"height", "", FOFFSET(height), AV_OPT_TYPE_INT, {.i64 = 0 }, 0, INT_MAX, 0}, -{"format", "", FOFFSET(format), AV_OPT_TYPE_INT, {.i64 = -1 }, 0, INT_MAX, 0}, -#if FF_API_OLD_CHANNEL_LAYOUT -{"channel_layout", "", FOFFSET(channel_layout), AV_OPT_TYPE_INT64, {.i64 = 0 }, 0, INT64_MAX, 0}, -#endif -{"sample_rate", "", FOFFSET(sample_rate), AV_OPT_TYPE_INT, {.i64 = 0 }, 0, INT_MAX, 0}, -{NULL}, -}; - -static const AVClass av_frame_class = { - .class_name = "AVFrame", - .item_name = NULL, - .option = frame_options, - .version = LIBAVUTIL_VERSION_INT, -}; - -const AVClass *avcodec_get_frame_class(void) -{ - return &av_frame_class; -} -FF_ENABLE_DEPRECATION_WARNINGS -#endif - #define SROFFSET(x) offsetof(AVSubtitleRect,x) static const AVOption subtitle_rect_options[]={ diff --git a/libavcodec/version_major.h b/libavcodec/version_major.h index f0e347c4828..d65fe867dfa 100644 --- a/libavcodec/version_major.h +++ b/libavcodec/version_major.h @@ -37,7 +37,6 @@ * at once through the bump. This improves the git bisect-ability of the change. */ -#define FF_API_GET_FRAME_CLASS (LIBAVCODEC_VERSION_MAJOR < 60) #define FF_API_AUTO_THREADS (LIBAVCODEC_VERSION_MAJOR < 60) #define FF_API_INIT_PACKET (LIBAVCODEC_VERSION_MAJOR < 60) #define FF_API_AVCTX_TIMEBASE (LIBAVCODEC_VERSION_MAJOR < 60) From 10c9a0874cb361336237557391d306d26d43f137 Mon Sep 17 00:00:00 2001 From: James Almer Date: Mon, 9 Jan 2023 11:09:09 -0300 Subject: [PATCH 0197/2172] avcodec: remove FF_API_AUTO_THREADS Signed-off-by: James Almer --- libavcodec/codec.h | 3 --- libavcodec/version_major.h | 1 - 2 files changed, 4 deletions(-) diff --git a/libavcodec/codec.h b/libavcodec/codec.h index 336a785e188..e1ebb0943e5 100644 --- a/libavcodec/codec.h +++ b/libavcodec/codec.h @@ -125,9 +125,6 @@ * multithreading-capable external libraries. */ #define AV_CODEC_CAP_OTHER_THREADS (1 << 15) -#if FF_API_AUTO_THREADS -#define AV_CODEC_CAP_AUTO_THREADS AV_CODEC_CAP_OTHER_THREADS -#endif /** * Audio encoder supports receiving a different number of samples in each call. */ diff --git a/libavcodec/version_major.h b/libavcodec/version_major.h index d65fe867dfa..84560bcabaa 100644 --- a/libavcodec/version_major.h +++ b/libavcodec/version_major.h @@ -37,7 +37,6 @@ * at once through the bump. This improves the git bisect-ability of the change. */ -#define FF_API_AUTO_THREADS (LIBAVCODEC_VERSION_MAJOR < 60) #define FF_API_INIT_PACKET (LIBAVCODEC_VERSION_MAJOR < 60) #define FF_API_AVCTX_TIMEBASE (LIBAVCODEC_VERSION_MAJOR < 60) #define FF_API_FLAG_TRUNCATED (LIBAVCODEC_VERSION_MAJOR < 60) From 5f9e848e686a3c0795939809712b260af5c1adb8 Mon Sep 17 00:00:00 2001 From: James Almer Date: Wed, 4 Jan 2023 13:13:19 -0300 Subject: [PATCH 0198/2172] avcodec: remove FF_API_AVCTX_TIMEBASE Signed-off-by: James Almer --- libavcodec/av1_parser.c | 3 --- libavcodec/avcodec.c | 5 ----- libavcodec/avcodec.h | 3 +-- libavcodec/avs2_parser.c | 4 ++-- libavcodec/avs3_parser.c | 4 ++-- libavcodec/cpia.c | 8 ------- libavcodec/decode.c | 5 ----- libavcodec/h264_parser.c | 7 +++--- libavcodec/h264dec.c | 6 ----- libavcodec/mjpegdec.c | 2 +- libavcodec/mpeg4video_parser.c | 4 ++-- libavcodec/mpeg4videodec.c | 3 --- libavcodec/mpegvideo_parser.c | 5 ----- libavcodec/vc1_parser.c | 2 -- libavcodec/version_major.h | 1 - libavformat/avformat.c | 33 ++++++++++++++++----------- libavformat/demux.c | 41 +++++++++++++++++++--------------- 17 files changed, 55 insertions(+), 81 deletions(-) diff --git a/libavcodec/av1_parser.c b/libavcodec/av1_parser.c index e57e382757e..14dae92fe9f 100644 --- a/libavcodec/av1_parser.c +++ b/libavcodec/av1_parser.c @@ -168,9 +168,6 @@ static int av1_parser_parse(AVCodecParserContext *ctx, timing->num_units_in_display_tick, timing->time_scale, INT_MAX); } - if (avctx->framerate.num) - avctx->time_base = av_inv_q(av_mul_q(avctx->framerate, (AVRational){avctx->ticks_per_frame, 1})); - end: ff_cbs_fragment_reset(td); diff --git a/libavcodec/avcodec.c b/libavcodec/avcodec.c index efa76d2740a..00a58518071 100644 --- a/libavcodec/avcodec.c +++ b/libavcodec/avcodec.c @@ -349,11 +349,6 @@ FF_ENABLE_DEPRECATION_WARNINGS ret = AVERROR(EINVAL); goto free_and_end; } - -#if FF_API_AVCTX_TIMEBASE - if (avctx->framerate.num > 0 && avctx->framerate.den > 0) - avctx->time_base = av_inv_q(av_mul_q(avctx->framerate, (AVRational){avctx->ticks_per_frame, 1})); -#endif } if (codec->priv_class) av_assert0(*(const AVClass **)avctx->priv_data == codec->priv_class); diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h index cc7a8faa6a5..c83e03a08f4 100644 --- a/libavcodec/avcodec.h +++ b/libavcodec/avcodec.h @@ -552,8 +552,7 @@ typedef struct AVCodecContext { * (fixed_vop_rate == 0 implies that it is different from the framerate) * * - encoding: MUST be set by user. - * - decoding: the use of this field for decoding is deprecated. - * Use framerate instead. + * - decoding: unused. */ AVRational time_base; diff --git a/libavcodec/avs2_parser.c b/libavcodec/avs2_parser.c index 0350517493a..200134f91db 100644 --- a/libavcodec/avs2_parser.c +++ b/libavcodec/avs2_parser.c @@ -112,9 +112,9 @@ static void parse_avs2_seq_header(AVCodecParserContext *s, const uint8_t *buf, s->height = height; s->coded_width = FFALIGN(width, 8); s->coded_height = FFALIGN(height, 8); - avctx->framerate.num = avctx->time_base.den = + avctx->framerate.num = ff_avs2_frame_rate_tab[frame_rate_code].num; - avctx->framerate.den = avctx->time_base.num = + avctx->framerate.den = ff_avs2_frame_rate_tab[frame_rate_code].den; avctx->has_b_frames = FFMAX(avctx->has_b_frames, !low_delay); diff --git a/libavcodec/avs3_parser.c b/libavcodec/avs3_parser.c index a9fd879e9de..a819b5783d6 100644 --- a/libavcodec/avs3_parser.c +++ b/libavcodec/avs3_parser.c @@ -117,8 +117,8 @@ static void parse_avs3_nal_units(AVCodecParserContext *s, const uint8_t *buf, low_delay = get_bits(&gb, 1); avctx->has_b_frames = FFMAX(avctx->has_b_frames, !low_delay); - avctx->framerate.num = avctx->time_base.den = ff_avs3_frame_rate_tab[ratecode].num; - avctx->framerate.den = avctx->time_base.num = ff_avs3_frame_rate_tab[ratecode].den; + avctx->framerate.num = ff_avs3_frame_rate_tab[ratecode].num; + avctx->framerate.den = ff_avs3_frame_rate_tab[ratecode].den; s->width = s->coded_width = avctx->width; s->height = s->coded_height = avctx->height; diff --git a/libavcodec/cpia.c b/libavcodec/cpia.c index 99362e73f07..bfd270dae2b 100644 --- a/libavcodec/cpia.c +++ b/libavcodec/cpia.c @@ -198,14 +198,6 @@ static av_cold int cpia_decode_init(AVCodecContext *avctx) // output pixel format avctx->pix_fmt = AV_PIX_FMT_YUV420P; - /* The default timebase set by the v4l2 demuxer leads to probing which is buggy. - * Set some reasonable time_base to skip this. - */ - if (avctx->time_base.num == 1 && avctx->time_base.den == 1000000) { - avctx->time_base.num = 1; - avctx->time_base.den = 60; - } - s->frame = av_frame_alloc(); if (!s->frame) return AVERROR(ENOMEM); diff --git a/libavcodec/decode.c b/libavcodec/decode.c index 34e67a649bf..aba20859df0 100644 --- a/libavcodec/decode.c +++ b/libavcodec/decode.c @@ -434,11 +434,6 @@ FF_ENABLE_DEPRECATION_WARNINGS #endif ret = pkt->size; -#if FF_API_AVCTX_TIMEBASE - if (avctx->framerate.num > 0 && avctx->framerate.den > 0) - avctx->time_base = av_inv_q(av_mul_q(avctx->framerate, (AVRational){avctx->ticks_per_frame, 1})); -#endif - /* do not stop draining when actual_got_frame != 0 or ret < 0 */ /* got_frame == 0 but actual_got_frame != 0 when frame is discarded */ if (avci->draining && !actual_got_frame) { diff --git a/libavcodec/h264_parser.c b/libavcodec/h264_parser.c index 3ed23fb9cae..46134a1c483 100644 --- a/libavcodec/h264_parser.c +++ b/libavcodec/h264_parser.c @@ -593,6 +593,7 @@ static int h264_parse(AVCodecParserContext *s, { H264ParseContext *p = s->priv_data; ParseContext *pc = &p->pc; + AVRational time_base = { 0, 1 }; int next; if (!p->got_first) { @@ -624,7 +625,7 @@ static int h264_parse(AVCodecParserContext *s, parse_nal_units(s, avctx, buf, buf_size); if (avctx->framerate.num) - avctx->time_base = av_inv_q(av_mul_q(avctx->framerate, (AVRational){avctx->ticks_per_frame, 1})); + time_base = av_inv_q(av_mul_q(avctx->framerate, (AVRational){avctx->ticks_per_frame, 1})); if (p->sei.picture_timing.cpb_removal_delay >= 0) { s->dts_sync_point = p->sei.buffering_period.present; s->dts_ref_dts_delta = p->sei.picture_timing.cpb_removal_delay; @@ -640,9 +641,9 @@ static int h264_parse(AVCodecParserContext *s, } if (s->dts_sync_point >= 0) { - int64_t den = avctx->time_base.den * (int64_t)avctx->pkt_timebase.num; + int64_t den = time_base.den * (int64_t)avctx->pkt_timebase.num; if (den > 0) { - int64_t num = avctx->time_base.num * (int64_t)avctx->pkt_timebase.den; + int64_t num = time_base.num * (int64_t)avctx->pkt_timebase.den; if (s->dts != AV_NOPTS_VALUE) { // got DTS from the stream, update reference timestamp p->reference_dts = s->dts - av_rescale(s->dts_ref_dts_delta, num, den); diff --git a/libavcodec/h264dec.c b/libavcodec/h264dec.c index 9f7b3782e84..2d691731c5d 100644 --- a/libavcodec/h264dec.c +++ b/libavcodec/h264dec.c @@ -382,12 +382,6 @@ static av_cold int h264_decode_init(AVCodecContext *avctx) return AVERROR_UNKNOWN; } - if (avctx->ticks_per_frame == 1) { - if(h->avctx->time_base.den < INT_MAX/2) { - h->avctx->time_base.den *= 2; - } else - h->avctx->time_base.num /= 2; - } avctx->ticks_per_frame = 2; if (!avctx->internal->is_copy) { diff --git a/libavcodec/mjpegdec.c b/libavcodec/mjpegdec.c index f33911e1a86..b2be55af4af 100644 --- a/libavcodec/mjpegdec.c +++ b/libavcodec/mjpegdec.c @@ -436,7 +436,7 @@ int ff_mjpeg_decode_sof(MJpegDecodeContext *s) /* test interlaced mode */ if (s->first_picture && - (s->multiscope != 2 || s->avctx->time_base.den >= 25 * s->avctx->time_base.num) && + (s->multiscope != 2 || s->avctx->pkt_timebase.den >= 25 * s->avctx->pkt_timebase.num) && s->orig_height != 0 && s->height < ((s->orig_height * 3) / 4)) { s->interlaced = 1; diff --git a/libavcodec/mpeg4video_parser.c b/libavcodec/mpeg4video_parser.c index e32a93d2964..3beb5f6dae0 100644 --- a/libavcodec/mpeg4video_parser.c +++ b/libavcodec/mpeg4video_parser.c @@ -114,11 +114,11 @@ static int mpeg4_decode_header(AVCodecParserContext *s1, AVCodecContext *avctx, if (ret < 0) return ret; } - if((s1->flags & PARSER_FLAG_USE_CODEC_TS) && s->avctx->time_base.den>0 && ret>=0){ + if((s1->flags & PARSER_FLAG_USE_CODEC_TS) && s->avctx->framerate.num>0 && ret>=0){ av_assert1(s1->pts == AV_NOPTS_VALUE); av_assert1(s1->dts == AV_NOPTS_VALUE); - s1->pts = av_rescale_q(s->time, (AVRational){1, s->avctx->time_base.den}, (AVRational){1, 1200000}); + s1->pts = av_rescale_q(s->time, (AVRational){1, s->avctx->framerate.num}, (AVRational){1, 1200000}); } s1->pict_type = s->pict_type; diff --git a/libavcodec/mpeg4videodec.c b/libavcodec/mpeg4videodec.c index 0a100d2064e..f96b6a31171 100644 --- a/libavcodec/mpeg4videodec.c +++ b/libavcodec/mpeg4videodec.c @@ -2648,8 +2648,6 @@ static int decode_vol_header(Mpeg4DecContext *ctx, GetBitContext *gb) else s->avctx->framerate.den = 1; - s->avctx->time_base = av_inv_q(av_mul_q(s->avctx->framerate, (AVRational){s->avctx->ticks_per_frame, 1})); - ctx->t_frame = 0; if (ctx->shape != BIN_ONLY_SHAPE) { @@ -3145,7 +3143,6 @@ static int decode_vop_header(Mpeg4DecContext *ctx, GetBitContext *gb, "time_increment_bits set to %d bits, based on bitstream analysis\n", ctx->time_increment_bits); if (s->avctx->framerate.num && 4*s->avctx->framerate.num < 1<time_increment_bits) { s->avctx->framerate.num = 1<time_increment_bits; - s->avctx->time_base = av_inv_q(av_mul_q(s->avctx->framerate, (AVRational){s->avctx->ticks_per_frame, 1})); } } diff --git a/libavcodec/mpegvideo_parser.c b/libavcodec/mpegvideo_parser.c index ac6efb69091..57bc1f706cc 100644 --- a/libavcodec/mpegvideo_parser.c +++ b/libavcodec/mpegvideo_parser.c @@ -241,11 +241,6 @@ static void mpegvideo_extract_headers(AVCodecParserContext *s, s->coded_width = FFALIGN(pc->width, 16); s->coded_height = FFALIGN(pc->height, 16); } - -#if FF_API_AVCTX_TIMEBASE - if (avctx->framerate.num) - avctx->time_base = av_inv_q(av_mul_q(avctx->framerate, (AVRational){avctx->ticks_per_frame, 1})); -#endif } static int mpegvideo_parse(AVCodecParserContext *s, diff --git a/libavcodec/vc1_parser.c b/libavcodec/vc1_parser.c index a459a2aa7d7..4167215fb11 100644 --- a/libavcodec/vc1_parser.c +++ b/libavcodec/vc1_parser.c @@ -112,8 +112,6 @@ static void vc1_extract_header(AVCodecParserContext *s, AVCodecContext *avctx, break; } - if (avctx->framerate.num) - avctx->time_base = av_inv_q(av_mul_q(avctx->framerate, (AVRational){avctx->ticks_per_frame, 1})); s->format = vpc->v.chromaformat == 1 ? AV_PIX_FMT_YUV420P : AV_PIX_FMT_NONE; if (avctx->width && avctx->height) { diff --git a/libavcodec/version_major.h b/libavcodec/version_major.h index 84560bcabaa..573cd855edb 100644 --- a/libavcodec/version_major.h +++ b/libavcodec/version_major.h @@ -38,7 +38,6 @@ */ #define FF_API_INIT_PACKET (LIBAVCODEC_VERSION_MAJOR < 60) -#define FF_API_AVCTX_TIMEBASE (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_IDCT_NONE (LIBAVCODEC_VERSION_MAJOR < 60) diff --git a/libavformat/avformat.c b/libavformat/avformat.c index 88ff46a5744..fe7b068f4a2 100644 --- a/libavformat/avformat.c +++ b/libavformat/avformat.c @@ -703,6 +703,10 @@ int avformat_transfer_internal_stream_timing_info(const AVOutputFormat *ofmt, { const AVCodecContext *const dec_ctx = cffstream(ist)->avctx; AVCodecContext *const enc_ctx = ffstream(ost)->avctx; + AVRational dec_ctx_tb = dec_ctx->framerate.num ? av_inv_q(av_mul_q(dec_ctx->framerate, + (AVRational){dec_ctx->ticks_per_frame, 1})) + : (ist->codecpar->codec_type == AVMEDIA_TYPE_AUDIO ? (AVRational){0, 1} + : ist->time_base); enc_ctx->time_base = ist->time_base; /* @@ -715,38 +719,41 @@ int avformat_transfer_internal_stream_timing_info(const AVOutputFormat *ofmt, if (copy_tb == AVFMT_TBCF_AUTO && ist->r_frame_rate.num && av_q2d(ist->r_frame_rate) >= av_q2d(ist->avg_frame_rate) && 0.5/av_q2d(ist->r_frame_rate) > av_q2d(ist->time_base) - && 0.5/av_q2d(ist->r_frame_rate) > av_q2d(dec_ctx->time_base) - && av_q2d(ist->time_base) < 1.0/500 && av_q2d(dec_ctx->time_base) < 1.0/500 + && 0.5/av_q2d(ist->r_frame_rate) > av_q2d(dec_ctx_tb) + && av_q2d(ist->time_base) < 1.0/500 && av_q2d(dec_ctx_tb) < 1.0/500 || copy_tb == AVFMT_TBCF_R_FRAMERATE) { enc_ctx->time_base.num = ist->r_frame_rate.den; enc_ctx->time_base.den = 2*ist->r_frame_rate.num; enc_ctx->ticks_per_frame = 2; } else #endif - if (copy_tb == AVFMT_TBCF_AUTO && av_q2d(dec_ctx->time_base)*dec_ctx->ticks_per_frame > 2*av_q2d(ist->time_base) + if (copy_tb == AVFMT_TBCF_AUTO && dec_ctx->framerate.num && + av_q2d(av_inv_q(dec_ctx->framerate)) > 2*av_q2d(ist->time_base) && av_q2d(ist->time_base) < 1.0/500 - || copy_tb == AVFMT_TBCF_DECODER) { - enc_ctx->time_base = dec_ctx->time_base; + || (copy_tb == AVFMT_TBCF_DECODER && + (dec_ctx->framerate.num || ist->codecpar->codec_type == AVMEDIA_TYPE_AUDIO))) { + enc_ctx->time_base = dec_ctx_tb; enc_ctx->time_base.num *= dec_ctx->ticks_per_frame; enc_ctx->time_base.den *= 2; enc_ctx->ticks_per_frame = 2; } } else if (!(ofmt->flags & AVFMT_VARIABLE_FPS) && !av_match_name(ofmt->name, "mov,mp4,3gp,3g2,psp,ipod,ismv,f4v")) { - if (copy_tb == AVFMT_TBCF_AUTO && dec_ctx->time_base.den - && av_q2d(dec_ctx->time_base)*dec_ctx->ticks_per_frame > av_q2d(ist->time_base) + if (copy_tb == AVFMT_TBCF_AUTO && dec_ctx->framerate.num + && av_q2d(av_inv_q(dec_ctx->framerate)) > av_q2d(ist->time_base) && av_q2d(ist->time_base) < 1.0/500 - || copy_tb == AVFMT_TBCF_DECODER) { - enc_ctx->time_base = dec_ctx->time_base; + || (copy_tb == AVFMT_TBCF_DECODER && + (dec_ctx->framerate.num || ist->codecpar->codec_type == AVMEDIA_TYPE_AUDIO))) { + enc_ctx->time_base = dec_ctx_tb; enc_ctx->time_base.num *= dec_ctx->ticks_per_frame; } } if ((enc_ctx->codec_tag == AV_RL32("tmcd") || ost->codecpar->codec_tag == AV_RL32("tmcd")) - && dec_ctx->time_base.num < dec_ctx->time_base.den - && dec_ctx->time_base.num > 0 - && 121LL*dec_ctx->time_base.num > dec_ctx->time_base.den) { - enc_ctx->time_base = dec_ctx->time_base; + && dec_ctx_tb.num < dec_ctx_tb.den + && dec_ctx_tb.num > 0 + && 121LL*dec_ctx_tb.num > dec_ctx_tb.den) { + enc_ctx->time_base = dec_ctx_tb; } av_reduce(&enc_ctx->time_base.num, &enc_ctx->time_base.den, diff --git a/libavformat/demux.c b/libavformat/demux.c index ba2991750bc..b19ab86d08d 100644 --- a/libavformat/demux.c +++ b/libavformat/demux.c @@ -2156,10 +2156,19 @@ static int get_std_framerate(int i) * Old DivX and Xvid often have nonsense timebases like 1fps or 2fps. * MPEG-2 commonly misuses field repeat flags to store different framerates. * And there are "variable" fps files this needs to detect as well. */ -static int tb_unreliable(AVCodecContext *c) +static int tb_unreliable(AVFormatContext *ic, AVStream *st) { - if (c->time_base.den >= 101LL * c->time_base.num || - c->time_base.den < 5LL * c->time_base.num || + FFStream *const sti = ffstream(st); + AVCodecContext *c = sti->avctx; + AVRational time_base = c->framerate.num ? av_inv_q(av_mul_q(c->framerate, + (AVRational){c->ticks_per_frame, 1})) + /* NOHEADER check added to not break existing behavior */ + : (((ic->ctx_flags & AVFMTCTX_NOHEADER) || + st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) ? (AVRational){0, 1} + : st->time_base); + + if (time_base.den >= 101LL * time_base.num || + time_base.den < 5LL * time_base.num || // c->codec_tag == AV_RL32("DIVX") || // c->codec_tag == AV_RL32("XVID") || c->codec_tag == AV_RL32("mp4v") || @@ -2243,11 +2252,11 @@ void ff_rfps_calculate(AVFormatContext *ic) // the check for tb_unreliable() is not completely correct, since this is not about handling // an unreliable/inexact time base, but a time base that is finer than necessary, as e.g. // ipmovie.c produces. - if (tb_unreliable(sti->avctx) && sti->info->duration_count > 15 && sti->info->duration_gcd > FFMAX(1, st->time_base.den/(500LL*st->time_base.num)) && !st->r_frame_rate.num && + if (tb_unreliable(ic, st) && sti->info->duration_count > 15 && sti->info->duration_gcd > FFMAX(1, st->time_base.den/(500LL*st->time_base.num)) && !st->r_frame_rate.num && sti->info->duration_gcd < INT64_MAX / st->time_base.num) av_reduce(&st->r_frame_rate.num, &st->r_frame_rate.den, st->time_base.den, st->time_base.num * sti->info->duration_gcd, INT_MAX); if (sti->info->duration_count > 1 && !st->r_frame_rate.num - && tb_unreliable(sti->avctx)) { + && tb_unreliable(ic, st)) { int num = 0; double best_error = 0.01; AVRational ref_rate = st->r_frame_rate.num ? st->r_frame_rate : av_inv_q(st->time_base); @@ -2459,14 +2468,6 @@ int avformat_find_stream_info(AVFormatContext *ic, AVDictionary **options) FFStream *const sti = ffstream(st); AVCodecContext *const avctx = sti->avctx; - if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO || - st->codecpar->codec_type == AVMEDIA_TYPE_SUBTITLE) { -/* if (!st->time_base.num) - st->time_base = */ - if (!avctx->time_base.num) - avctx->time_base = st->time_base; - } - /* check if the caller has overridden the codec id */ // only for the split stuff if (!sti->parser && !(ic->flags & AVFMT_FLAG_NOPARSE) && sti->request_probe <= 0) { @@ -2544,7 +2545,7 @@ int avformat_find_stream_info(AVFormatContext *ic, AVDictionary **options) * the correct fps. */ if (av_q2d(st->time_base) > 0.0005) fps_analyze_framecount *= 2; - if (!tb_unreliable(sti->avctx)) + if (!tb_unreliable(ic, st)) fps_analyze_framecount = 0; if (ic->fps_probe_size >= 0) fps_analyze_framecount = ic->fps_probe_size; @@ -2857,12 +2858,16 @@ int avformat_find_stream_info(AVFormatContext *ic, AVDictionary **options) av_reduce(&st->avg_frame_rate.num, &st->avg_frame_rate.den, best_fps, 12 * 1001, INT_MAX); } - if (!st->r_frame_rate.num) { - if ( avctx->time_base.den * (int64_t) st->time_base.num - <= avctx->time_base.num * (uint64_t)avctx->ticks_per_frame * st->time_base.den) { + AVRational time_base = avctx->framerate.num ? av_inv_q(av_mul_q(avctx->framerate, + (AVRational){avctx->ticks_per_frame, 1})) + /* NOHEADER check added to not break existing behavior */ + : ((ic->ctx_flags & AVFMTCTX_NOHEADER) ? (AVRational){0, 1} + : st->time_base); + if ( time_base.den * (int64_t) st->time_base.num + <= time_base.num * (uint64_t)avctx->ticks_per_frame * st->time_base.den) { av_reduce(&st->r_frame_rate.num, &st->r_frame_rate.den, - avctx->time_base.den, (int64_t)avctx->time_base.num * avctx->ticks_per_frame, INT_MAX); + time_base.den, (int64_t)time_base.num * avctx->ticks_per_frame, INT_MAX); } else { st->r_frame_rate.num = st->time_base.den; st->r_frame_rate.den = st->time_base.num; From 3ceffe783965767e62d59e8e68ecd265c98460ec Mon Sep 17 00:00:00 2001 From: James Almer Date: Mon, 9 Jan 2023 11:22:39 -0300 Subject: [PATCH 0199/2172] avcodec: remove FF_API_FLAG_TRUNCATED Signed-off-by: James Almer --- libavcodec/avcodec.h | 9 ----- libavcodec/codec.h | 6 ---- libavcodec/decode.c | 4 --- libavcodec/h263_parser.c | 11 ------ libavcodec/h263_parser.h | 29 --------------- libavcodec/h263dec.c | 42 ---------------------- libavcodec/mpeg12.c | 66 ---------------------------------- libavcodec/mpeg12.h | 9 ----- libavcodec/mpeg12dec.c | 31 ---------------- libavcodec/mpeg4video_parser.c | 12 ------- libavcodec/mpeg4video_parser.h | 34 ------------------ libavcodec/mpeg4videodec.c | 3 -- libavcodec/mpegvideo.c | 9 ----- libavcodec/mpegvideo.h | 7 ---- libavcodec/mpegvideo_dec.c | 8 ----- libavcodec/mpegvideo_parser.c | 7 +--- libavcodec/options_table.h | 3 -- libavcodec/pthread.c | 3 -- libavcodec/version_major.h | 1 - 19 files changed, 1 insertion(+), 293 deletions(-) delete mode 100644 libavcodec/h263_parser.h delete mode 100644 libavcodec/mpeg4video_parser.h diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h index c83e03a08f4..a3cf38a865e 100644 --- a/libavcodec/avcodec.h +++ b/libavcodec/avcodec.h @@ -303,15 +303,6 @@ typedef struct RcOverride{ * error[?] variables will be set during encoding. */ #define AV_CODEC_FLAG_PSNR (1 << 15) -#if FF_API_FLAG_TRUNCATED -/** - * Input bitstream might be truncated at a random location - * instead of only at frame boundaries. - * - * @deprecated use codec parsers for packetizing input - */ -#define AV_CODEC_FLAG_TRUNCATED (1 << 16) -#endif /** * Use interlaced DCT. */ diff --git a/libavcodec/codec.h b/libavcodec/codec.h index e1ebb0943e5..3b1995bcfef 100644 --- a/libavcodec/codec.h +++ b/libavcodec/codec.h @@ -50,12 +50,6 @@ * avcodec_default_get_buffer2 or avcodec_default_get_encode_buffer. */ #define AV_CODEC_CAP_DR1 (1 << 1) -#if FF_API_FLAG_TRUNCATED -/** - * @deprecated Use parsers to always send proper frames. - */ -#define AV_CODEC_CAP_TRUNCATED (1 << 3) -#endif /** * Encoder or decoder requires flushing with NULL input at the end in order to * give the complete and correct output. diff --git a/libavcodec/decode.c b/libavcodec/decode.c index aba20859df0..93ecd36c2bf 100644 --- a/libavcodec/decode.c +++ b/libavcodec/decode.c @@ -427,11 +427,7 @@ FF_ENABLE_DEPRECATION_WARNINGS if (!got_frame) av_frame_unref(frame); -#if FF_API_FLAG_TRUNCATED - if (ret >= 0 && avctx->codec->type == AVMEDIA_TYPE_VIDEO && !(avctx->flags & AV_CODEC_FLAG_TRUNCATED)) -#else if (ret >= 0 && avctx->codec->type == AVMEDIA_TYPE_VIDEO) -#endif ret = pkt->size; /* do not stop draining when actual_got_frame != 0 or ret < 0 */ diff --git a/libavcodec/h263_parser.c b/libavcodec/h263_parser.c index 7a742caa80b..f70a7911777 100644 --- a/libavcodec/h263_parser.c +++ b/libavcodec/h263_parser.c @@ -25,16 +25,9 @@ */ #include "parser.h" -#if FF_API_FLAG_TRUNCATED -/* Nuke this header when removing FF_API_FLAG_TRUNCATED */ -#include "h263_parser.h" - -int ff_h263_find_frame_end(ParseContext *pc, const uint8_t *buf, int buf_size){ -#else static int h263_find_frame_end(ParseContext *pc, const uint8_t *buf, int buf_size) { -#endif int vop_found, i; uint32_t state; @@ -80,11 +73,7 @@ static int h263_parse(AVCodecParserContext *s, if (s->flags & PARSER_FLAG_COMPLETE_FRAMES) { next = buf_size; } else { -#if FF_API_FLAG_TRUNCATED - next= ff_h263_find_frame_end(pc, buf, buf_size); -#else next = h263_find_frame_end(pc, buf, buf_size); -#endif if (ff_combine_frame(pc, next, &buf, &buf_size) < 0) { *poutbuf = NULL; diff --git a/libavcodec/h263_parser.h b/libavcodec/h263_parser.h deleted file mode 100644 index 565a222bc1e..00000000000 --- a/libavcodec/h263_parser.h +++ /dev/null @@ -1,29 +0,0 @@ -/* - * H.263 parser - * 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_H263_PARSER_H -#define AVCODEC_H263_PARSER_H - -#include "parser.h" - -int ff_h263_find_frame_end(ParseContext *pc, const uint8_t *buf, int buf_size); - -#endif /* AVCODEC_H263_PARSER_H */ diff --git a/libavcodec/h263dec.c b/libavcodec/h263dec.c index 0a2d7487a83..f4e7048a5f2 100644 --- a/libavcodec/h263dec.c +++ b/libavcodec/h263dec.c @@ -36,17 +36,11 @@ #include "flvdec.h" #include "h263.h" #include "h263dec.h" -#if FF_API_FLAG_TRUNCATED -#include "h263_parser.h" -#endif #include "hwconfig.h" #include "mpeg_er.h" #include "mpeg4video.h" #include "mpeg4videodec.h" #include "mpeg4videodefs.h" -#if FF_API_FLAG_TRUNCATED -#include "mpeg4video_parser.h" -#endif #include "mpegutils.h" #include "mpegvideo.h" #include "mpegvideodec.h" @@ -163,14 +157,6 @@ static int get_consumed_bytes(MpegEncContext *s, int buf_size) /* We would have to scan through the whole buf to handle the weird * reordering ... */ return buf_size; -#if FF_API_FLAG_TRUNCATED - } else if (s->avctx->flags & AV_CODEC_FLAG_TRUNCATED) { - pos -= s->parse_context.last_index; - // padding is not really read so this might be -1 - if (pos < 0) - pos = 0; - return pos; -#endif } else { // avoid infinite loops (maybe not needed...) if (pos == 0) @@ -448,28 +434,6 @@ int ff_h263_decode_frame(AVCodecContext *avctx, AVFrame *pict, return 0; } -#if FF_API_FLAG_TRUNCATED - if (s->avctx->flags & AV_CODEC_FLAG_TRUNCATED) { - int next; - - if (CONFIG_MPEG4_DECODER && s->codec_id == AV_CODEC_ID_MPEG4) { - next = ff_mpeg4_find_frame_end(&s->parse_context, buf, buf_size); - } else if (CONFIG_H263_DECODER && s->codec_id == AV_CODEC_ID_H263) { - next = ff_h263_find_frame_end(&s->parse_context, buf, buf_size); - } else if (CONFIG_H263P_DECODER && s->codec_id == AV_CODEC_ID_H263P) { - next = ff_h263_find_frame_end(&s->parse_context, buf, buf_size); - } else { - av_log(s->avctx, AV_LOG_ERROR, - "this codec does not support truncated bitstreams\n"); - return AVERROR(ENOSYS); - } - - if (ff_combine_frame(&s->parse_context, next, (const uint8_t **)&buf, - &buf_size) < 0) - return buf_size; - } -#endif - retry: if (s->divx_packed && s->bitstream_buffer_size) { int i; @@ -749,9 +713,6 @@ const FFCodec ff_h263_decoder = { .close = ff_h263_decode_end, FF_CODEC_DECODE_CB(ff_h263_decode_frame), .p.capabilities = AV_CODEC_CAP_DRAW_HORIZ_BAND | AV_CODEC_CAP_DR1 | -#if FF_API_FLAG_TRUNCATED - AV_CODEC_CAP_TRUNCATED | -#endif AV_CODEC_CAP_DELAY, .caps_internal = FF_CODEC_CAP_SKIP_FRAME_FILL_PARAM, .flush = ff_mpeg_flush, @@ -770,9 +731,6 @@ const FFCodec ff_h263p_decoder = { .close = ff_h263_decode_end, FF_CODEC_DECODE_CB(ff_h263_decode_frame), .p.capabilities = AV_CODEC_CAP_DRAW_HORIZ_BAND | AV_CODEC_CAP_DR1 | -#if FF_API_FLAG_TRUNCATED - AV_CODEC_CAP_TRUNCATED | -#endif AV_CODEC_CAP_DELAY, .caps_internal = FF_CODEC_CAP_SKIP_FRAME_FILL_PARAM, .flush = ff_mpeg_flush, diff --git a/libavcodec/mpeg12.c b/libavcodec/mpeg12.c index 5d5f39388f9..a256d45c85b 100644 --- a/libavcodec/mpeg12.c +++ b/libavcodec/mpeg12.c @@ -167,72 +167,6 @@ av_cold void ff_mpeg12_init_vlcs(void) ff_thread_once(&init_static_once, mpeg12_init_vlcs); } -#if FF_API_FLAG_TRUNCATED -/** - * Find the end of the current frame in the bitstream. - * @return the position of the first byte of the next frame, or -1 - */ -int ff_mpeg1_find_frame_end(ParseContext *pc, const uint8_t *buf, int buf_size, AVCodecParserContext *s) -{ - int i; - uint32_t state = pc->state; - - /* EOF considered as end of frame */ - if (buf_size == 0) - return 0; - -/* - 0 frame start -> 1/4 - 1 first_SEQEXT -> 0/2 - 2 first field start -> 3/0 - 3 second_SEQEXT -> 2/0 - 4 searching end -*/ - - for (i = 0; i < buf_size; i++) { - av_assert1(pc->frame_start_found >= 0 && pc->frame_start_found <= 4); - if (pc->frame_start_found & 1) { - if (state == EXT_START_CODE && (buf[i] & 0xF0) != 0x80) - pc->frame_start_found--; - else if (state == EXT_START_CODE + 2) { - if ((buf[i] & 3) == 3) - pc->frame_start_found = 0; - else - pc->frame_start_found = (pc->frame_start_found + 1) & 3; - } - state++; - } else { - i = avpriv_find_start_code(buf + i, buf + buf_size, &state) - buf - 1; - if (pc->frame_start_found == 0 && state >= SLICE_MIN_START_CODE && state <= SLICE_MAX_START_CODE) { - i++; - pc->frame_start_found = 4; - } - if (state == SEQ_END_CODE) { - pc->frame_start_found = 0; - pc->state=-1; - return i+1; - } - if (pc->frame_start_found == 2 && state == SEQ_START_CODE) - pc->frame_start_found = 0; - if (pc->frame_start_found < 4 && state == EXT_START_CODE) - pc->frame_start_found++; - if (pc->frame_start_found == 4 && (state & 0xFFFFFF00) == 0x100) { - if (state < SLICE_MIN_START_CODE || state > SLICE_MAX_START_CODE) { - pc->frame_start_found = 0; - pc->state = -1; - return i - 3; - } - } - if (pc->frame_start_found == 0 && s && state == PICTURE_START_CODE) { - ff_fetch_timestamp(s, i - 3, 1, i > 3); - } - } - } - pc->state = state; - return END_NOT_FOUND; -} -#endif - #define MAX_INDEX (64 - 1) int ff_mpeg1_decode_block_intra(GetBitContext *gb, diff --git a/libavcodec/mpeg12.h b/libavcodec/mpeg12.h index 4e2e67eae18..86dd627e954 100644 --- a/libavcodec/mpeg12.h +++ b/libavcodec/mpeg12.h @@ -34,15 +34,6 @@ #define EXT_START_CODE 0x000001b5 #define USER_START_CODE 0x000001b2 -#include "version_major.h" -#if FF_API_FLAG_TRUNCATED -#include - -struct ParseContext; -struct AVCodecParserContext; -int ff_mpeg1_find_frame_end(struct ParseContext *pc, const uint8_t *buf, int buf_size, struct AVCodecParserContext *s); -#endif - void ff_mpeg12_find_best_frame_rate(AVRational frame_rate, int *code, int *ext_n, int *ext_d, int nonstandard); diff --git a/libavcodec/mpeg12dec.c b/libavcodec/mpeg12dec.c index 9999926f55d..457d985265d 100644 --- a/libavcodec/mpeg12dec.c +++ b/libavcodec/mpeg12dec.c @@ -1239,14 +1239,7 @@ static int mpeg_decode_postinit(AVCodecContext *avctx) (s1->save_progressive_seq != s->progressive_sequence && FFALIGN(s->height, 16) != FFALIGN(s->height, 32)) || 0) { if (s1->mpeg_enc_ctx_allocated) { -#if FF_API_FLAG_TRUNCATED - ParseContext pc = s->parse_context; - s->parse_context.buffer = 0; ff_mpv_common_end(s); - s->parse_context = pc; -#else - ff_mpv_common_end(s); -#endif s1->mpeg_enc_ctx_allocated = 0; } @@ -2482,11 +2475,7 @@ static int decode_chunks(AVCodecContext *avctx, AVFrame *picture, if (avctx->err_recognition & AV_EF_EXPLODE && s2->er.error_count) return AVERROR_INVALIDDATA; -#if FF_API_FLAG_TRUNCATED - return FFMAX(0, buf_ptr - buf - s2->parse_context.last_index); -#else return FFMAX(0, buf_ptr - buf); -#endif } input_size = buf_end - buf_ptr; @@ -2799,17 +2788,6 @@ static int mpeg_decode_frame(AVCodecContext *avctx, AVFrame *picture, return buf_size; } -#if FF_API_FLAG_TRUNCATED - if (s2->avctx->flags & AV_CODEC_FLAG_TRUNCATED) { - int next = ff_mpeg1_find_frame_end(&s2->parse_context, buf, - buf_size, NULL); - - if (ff_combine_frame(&s2->parse_context, next, - (const uint8_t **) &buf, &buf_size) < 0) - return buf_size; - } -#endif - if (s->mpeg_enc_ctx_allocated == 0 && ( s2->codec_tag == AV_RL32("VCR2") || s2->codec_tag == AV_RL32("BW10") )) @@ -2886,9 +2864,6 @@ const FFCodec ff_mpeg1video_decoder = { .close = mpeg_decode_end, FF_CODEC_DECODE_CB(mpeg_decode_frame), .p.capabilities = AV_CODEC_CAP_DRAW_HORIZ_BAND | AV_CODEC_CAP_DR1 | -#if FF_API_FLAG_TRUNCATED - AV_CODEC_CAP_TRUNCATED | -#endif AV_CODEC_CAP_DELAY | AV_CODEC_CAP_SLICE_THREADS, .caps_internal = FF_CODEC_CAP_SKIP_FRAME_FILL_PARAM, .flush = flush, @@ -2918,9 +2893,6 @@ const FFCodec ff_mpeg2video_decoder = { .close = mpeg_decode_end, FF_CODEC_DECODE_CB(mpeg_decode_frame), .p.capabilities = AV_CODEC_CAP_DRAW_HORIZ_BAND | AV_CODEC_CAP_DR1 | -#if FF_API_FLAG_TRUNCATED - AV_CODEC_CAP_TRUNCATED | -#endif AV_CODEC_CAP_DELAY | AV_CODEC_CAP_SLICE_THREADS, .caps_internal = FF_CODEC_CAP_SKIP_FRAME_FILL_PARAM, .flush = flush, @@ -2963,9 +2935,6 @@ const FFCodec ff_mpegvideo_decoder = { .close = mpeg_decode_end, FF_CODEC_DECODE_CB(mpeg_decode_frame), .p.capabilities = AV_CODEC_CAP_DRAW_HORIZ_BAND | AV_CODEC_CAP_DR1 | -#if FF_API_FLAG_TRUNCATED - AV_CODEC_CAP_TRUNCATED | -#endif AV_CODEC_CAP_DELAY | AV_CODEC_CAP_SLICE_THREADS, .caps_internal = FF_CODEC_CAP_SKIP_FRAME_FILL_PARAM, .flush = flush, diff --git a/libavcodec/mpeg4video_parser.c b/libavcodec/mpeg4video_parser.c index 3beb5f6dae0..28353aa146b 100644 --- a/libavcodec/mpeg4video_parser.c +++ b/libavcodec/mpeg4video_parser.c @@ -27,10 +27,6 @@ #include "mpegvideo.h" #include "mpeg4videodec.h" #include "mpeg4videodefs.h" -#if FF_API_FLAG_TRUNCATED -/* Nuke this header when removing FF_API_FLAG_TRUNCATED */ -#include "mpeg4video_parser.h" -#endif struct Mp4vParseContext { ParseContext pc; @@ -38,15 +34,11 @@ struct Mp4vParseContext { int first_picture; }; -#if FF_API_FLAG_TRUNCATED -int ff_mpeg4_find_frame_end(ParseContext *pc, const uint8_t *buf, int buf_size) -#else /** * Find the end of the current frame in the bitstream. * @return the position of the first byte of the next frame, or -1 */ static int mpeg4_find_frame_end(ParseContext *pc, const uint8_t *buf, int buf_size) -#endif { int vop_found, i; uint32_t state; @@ -148,11 +140,7 @@ static int mpeg4video_parse(AVCodecParserContext *s, if (s->flags & PARSER_FLAG_COMPLETE_FRAMES) { next = buf_size; } else { -#if FF_API_FLAG_TRUNCATED - next = ff_mpeg4_find_frame_end(pc, buf, buf_size); -#else next = mpeg4_find_frame_end(pc, buf, buf_size); -#endif if (ff_combine_frame(pc, next, &buf, &buf_size) < 0) { *poutbuf = NULL; diff --git a/libavcodec/mpeg4video_parser.h b/libavcodec/mpeg4video_parser.h deleted file mode 100644 index 8008e693b43..00000000000 --- a/libavcodec/mpeg4video_parser.h +++ /dev/null @@ -1,34 +0,0 @@ -/* - * MPEG-4 video parser prototypes - * Copyright (c) 2003 Fabrice Bellard - * Copyright (c) 2003 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_MPEG4VIDEO_PARSER_H -#define AVCODEC_MPEG4VIDEO_PARSER_H - -#include "parser.h" - -/** - * Find the end of the current frame in the bitstream. - * @return the position of the first byte of the next frame, or -1 - */ -int ff_mpeg4_find_frame_end(ParseContext *pc, const uint8_t *buf, int buf_size); - -#endif /* AVCODEC_MPEG4VIDEO_PARSER_H */ diff --git a/libavcodec/mpeg4videodec.c b/libavcodec/mpeg4videodec.c index f96b6a31171..d456e5dd113 100644 --- a/libavcodec/mpeg4videodec.c +++ b/libavcodec/mpeg4videodec.c @@ -3859,9 +3859,6 @@ const FFCodec ff_mpeg4_decoder = { .close = ff_h263_decode_end, FF_CODEC_DECODE_CB(ff_h263_decode_frame), .p.capabilities = AV_CODEC_CAP_DRAW_HORIZ_BAND | AV_CODEC_CAP_DR1 | -#if FF_API_FLAG_TRUNCATED - AV_CODEC_CAP_TRUNCATED | -#endif AV_CODEC_CAP_DELAY | AV_CODEC_CAP_FRAME_THREADS, .caps_internal = FF_CODEC_CAP_SKIP_FRAME_FILL_PARAM | FF_CODEC_CAP_ALLOCATE_PROGRESS, diff --git a/libavcodec/mpegvideo.c b/libavcodec/mpegvideo.c index 836869c1d92..fc73abab9cd 100644 --- a/libavcodec/mpegvideo.c +++ b/libavcodec/mpegvideo.c @@ -738,10 +738,6 @@ av_cold int ff_mpv_common_init(MpegEncContext *s) nb_slices = max_slices; } -#if FF_API_FLAG_TRUNCATED - s->parse_context.state = -1; -#endif - s->context_initialized = 1; memset(s->thread_context, 0, sizeof(s->thread_context)); s->thread_context[0] = s; @@ -791,11 +787,6 @@ void ff_mpv_common_end(MpegEncContext *s) if (s->slice_context_count > 1) s->slice_context_count = 1; -#if FF_API_FLAG_TRUNCATED - av_freep(&s->parse_context.buffer); - s->parse_context.buffer_size = 0; -#endif - av_freep(&s->bitstream_buffer); s->allocated_bitstream_buffer_size = 0; diff --git a/libavcodec/mpegvideo.h b/libavcodec/mpegvideo.h index 42275953b9e..55828e61027 100644 --- a/libavcodec/mpegvideo.h +++ b/libavcodec/mpegvideo.h @@ -44,9 +44,6 @@ #include "pixblockdsp.h" #include "put_bits.h" #include "ratecontrol.h" -#if FF_API_FLAG_TRUNCATED -#include "parser.h" -#endif #include "mpegutils.h" #include "qpeldsp.h" #include "videodsp.h" @@ -353,10 +350,6 @@ typedef struct MpegEncContext { 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) -#if FF_API_FLAG_TRUNCATED - ParseContext parse_context; -#endif - /* H.263 specific */ int gob_index; int obmc; ///< overlapped block motion compensation diff --git a/libavcodec/mpegvideo_dec.c b/libavcodec/mpegvideo_dec.c index 12c7144ffb1..7a0c51e53d1 100644 --- a/libavcodec/mpegvideo_dec.c +++ b/libavcodec/mpegvideo_dec.c @@ -554,14 +554,6 @@ void ff_mpeg_flush(AVCodecContext *avctx) 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; } diff --git a/libavcodec/mpegvideo_parser.c b/libavcodec/mpegvideo_parser.c index 57bc1f706cc..8e7e88ff25e 100644 --- a/libavcodec/mpegvideo_parser.c +++ b/libavcodec/mpegvideo_parser.c @@ -20,6 +20,7 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#include "libavutil/avassert.h" #include "decode.h" #include "parser.h" #include "mpeg12.h" @@ -33,7 +34,6 @@ struct MpvParseContext { int width, height; }; -#if !FF_API_FLAG_TRUNCATED /** * Find the end of the current frame in the bitstream. * @return the position of the first byte of the next frame, or -1 @@ -98,7 +98,6 @@ static int mpeg1_find_frame_end(ParseContext *pc, const uint8_t *buf, pc->state = state; return END_NOT_FOUND; } -#endif static void mpegvideo_extract_headers(AVCodecParserContext *s, AVCodecContext *avctx, @@ -255,11 +254,7 @@ static int mpegvideo_parse(AVCodecParserContext *s, if(s->flags & PARSER_FLAG_COMPLETE_FRAMES){ next= buf_size; }else{ -#if FF_API_FLAG_TRUNCATED - next= ff_mpeg1_find_frame_end(pc, buf, buf_size, s); -#else next = mpeg1_find_frame_end(pc, buf, buf_size, s); -#endif if (ff_combine_frame(pc, next, &buf, &buf_size) < 0) { *poutbuf = NULL; diff --git a/libavcodec/options_table.h b/libavcodec/options_table.h index 322ec7a1566..52ecc25cf9b 100644 --- a/libavcodec/options_table.h +++ b/libavcodec/options_table.h @@ -64,9 +64,6 @@ static const AVOption avcodec_options[] = { {"pass2", "use internal 2-pass ratecontrol in second pass mode", 0, AV_OPT_TYPE_CONST, {.i64 = AV_CODEC_FLAG_PASS2 }, INT_MIN, INT_MAX, 0, "flags"}, {"gray", "only decode/encode grayscale", 0, AV_OPT_TYPE_CONST, {.i64 = AV_CODEC_FLAG_GRAY }, INT_MIN, INT_MAX, V|E|D, "flags"}, {"psnr", "error[?] variables will be set during encoding", 0, AV_OPT_TYPE_CONST, {.i64 = AV_CODEC_FLAG_PSNR }, INT_MIN, INT_MAX, V|E, "flags"}, -#if FF_API_FLAG_TRUNCATED -{"truncated", "(Deprecated, use parsers instead.) Input bitstream might be randomly truncated", 0, AV_OPT_TYPE_CONST, {.i64 = AV_CODEC_FLAG_TRUNCATED }, INT_MIN, INT_MAX, V|D | AV_OPT_FLAG_DEPRECATED, "flags"}, -#endif {"ildct", "use interlaced DCT", 0, AV_OPT_TYPE_CONST, {.i64 = AV_CODEC_FLAG_INTERLACED_DCT }, INT_MIN, INT_MAX, V|E, "flags"}, {"low_delay", "force low delay", 0, AV_OPT_TYPE_CONST, {.i64 = AV_CODEC_FLAG_LOW_DELAY }, INT_MIN, INT_MAX, V|D|E, "flags"}, {"global_header", "place global headers in extradata instead of every keyframe", 0, AV_OPT_TYPE_CONST, {.i64 = AV_CODEC_FLAG_GLOBAL_HEADER }, INT_MIN, INT_MAX, V|A|E, "flags"}, diff --git a/libavcodec/pthread.c b/libavcodec/pthread.c index 60ba87dac48..ca84b81391d 100644 --- a/libavcodec/pthread.c +++ b/libavcodec/pthread.c @@ -48,9 +48,6 @@ static void validate_thread_parameters(AVCodecContext *avctx) { int frame_threading_supported = (avctx->codec->capabilities & AV_CODEC_CAP_FRAME_THREADS) -#if FF_API_FLAG_TRUNCATED - && !(avctx->flags & AV_CODEC_FLAG_TRUNCATED) -#endif && !(avctx->flags & AV_CODEC_FLAG_LOW_DELAY) && !(avctx->flags2 & AV_CODEC_FLAG2_CHUNKS); if (avctx->thread_count == 1) { diff --git a/libavcodec/version_major.h b/libavcodec/version_major.h index 573cd855edb..96536732d97 100644 --- a/libavcodec/version_major.h +++ b/libavcodec/version_major.h @@ -38,7 +38,6 @@ */ #define FF_API_INIT_PACKET (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_IDCT_NONE (LIBAVCODEC_VERSION_MAJOR < 60) #define FF_API_SVTAV1_OPTS (LIBAVCODEC_VERSION_MAJOR < 60) From 1ba8b6d9dcf5541107b627cf634a4dc2b0cd3d1a Mon Sep 17 00:00:00 2001 From: James Almer Date: Mon, 9 Jan 2023 11:25:21 -0300 Subject: [PATCH 0200/2172] avcodec: remove FF_API_SUB_TEXT_FORMAT Signed-off-by: James Almer --- libavcodec/avcodec.h | 9 --------- libavcodec/options_table.h | 4 ---- libavcodec/version_major.h | 1 - 3 files changed, 14 deletions(-) diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h index a3cf38a865e..17416791a63 100644 --- a/libavcodec/avcodec.h +++ b/libavcodec/avcodec.h @@ -1882,15 +1882,6 @@ typedef struct AVCodecContext { */ AVBufferRef *hw_frames_ctx; -#if FF_API_SUB_TEXT_FORMAT - /** - * @deprecated unused - */ - attribute_deprecated - int sub_text_format; -#define FF_SUB_TEXT_FMT_ASS 0 -#endif - /** * Audio only. The amount of padding (in samples) appended by the encoder to * the end of the audio. I.e. this number of decoded samples must be diff --git a/libavcodec/options_table.h b/libavcodec/options_table.h index 52ecc25cf9b..bcd6f381917 100644 --- a/libavcodec/options_table.h +++ b/libavcodec/options_table.h @@ -376,10 +376,6 @@ static const AVOption avcodec_options[] = { {"auto", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = FF_SUB_CHARENC_MODE_AUTOMATIC}, INT_MIN, INT_MAX, S|D, "sub_charenc_mode"}, {"pre_decoder", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = FF_SUB_CHARENC_MODE_PRE_DECODER}, INT_MIN, INT_MAX, S|D, "sub_charenc_mode"}, {"ignore", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = FF_SUB_CHARENC_MODE_IGNORE}, INT_MIN, INT_MAX, S|D, "sub_charenc_mode"}, -#if FF_API_SUB_TEXT_FORMAT -{"sub_text_format", "Deprecated, does nothing", OFFSET(sub_text_format), AV_OPT_TYPE_INT, {.i64 = FF_SUB_TEXT_FMT_ASS}, 0, 1, S|D | AV_OPT_FLAG_DEPRECATED, "sub_text_format"}, -{"ass", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = FF_SUB_TEXT_FMT_ASS}, INT_MIN, INT_MAX, S|D, "sub_text_format"}, -#endif {"apply_cropping", NULL, OFFSET(apply_cropping), AV_OPT_TYPE_BOOL, { .i64 = 1 }, 0, 1, V | D }, {"skip_alpha", "Skip processing alpha", OFFSET(skip_alpha), AV_OPT_TYPE_BOOL, {.i64 = 0 }, 0, 1, V|D }, {"field_order", "Field order", OFFSET(field_order), AV_OPT_TYPE_INT, {.i64 = AV_FIELD_UNKNOWN }, 0, 5, V|D|E, "field_order" }, diff --git a/libavcodec/version_major.h b/libavcodec/version_major.h index 96536732d97..46739ad1e40 100644 --- a/libavcodec/version_major.h +++ b/libavcodec/version_major.h @@ -38,7 +38,6 @@ */ #define FF_API_INIT_PACKET (LIBAVCODEC_VERSION_MAJOR < 60) -#define FF_API_SUB_TEXT_FORMAT (LIBAVCODEC_VERSION_MAJOR < 60) #define FF_API_IDCT_NONE (LIBAVCODEC_VERSION_MAJOR < 60) #define FF_API_SVTAV1_OPTS (LIBAVCODEC_VERSION_MAJOR < 60) #define FF_API_AYUV_CODECID (LIBAVCODEC_VERSION_MAJOR < 60) From add33e370d241d947209c914de1bf062fe44d58e Mon Sep 17 00:00:00 2001 From: James Almer Date: Wed, 11 Jan 2023 10:27:14 -0300 Subject: [PATCH 0201/2172] avformat: remove FF_API_LAVF_PRIV_OPT Signed-off-by: James Almer --- libavformat/avformat.h | 3 --- libavformat/version_major.h | 1 - 2 files changed, 4 deletions(-) diff --git a/libavformat/avformat.h b/libavformat/avformat.h index 49e50a5120a..ac40e197f62 100644 --- a/libavformat/avformat.h +++ b/libavformat/avformat.h @@ -1242,9 +1242,6 @@ typedef struct AVFormatContext { */ #define AVFMT_FLAG_BITEXACT 0x0400 #define AVFMT_FLAG_SORT_DTS 0x10000 ///< try to interleave outputted packets by dts (using this flag can slow demuxing down) -#if FF_API_LAVF_PRIV_OPT -#define AVFMT_FLAG_PRIV_OPT 0x20000 ///< Enable use of private options by delaying codec open (deprecated, does nothing) -#endif #define AVFMT_FLAG_FAST_SEEK 0x80000 ///< Enable fast, but inaccurate seeks for some formats #define AVFMT_FLAG_SHORTEST 0x100000 ///< Stop muxing when the shortest stream stops. #define AVFMT_FLAG_AUTO_BSF 0x200000 ///< Add bitstream filters as requested by the muxer diff --git a/libavformat/version_major.h b/libavformat/version_major.h index 86af3ee4a5a..abc1699685a 100644 --- a/libavformat/version_major.h +++ b/libavformat/version_major.h @@ -41,7 +41,6 @@ * at once through the bump. This improves the git bisect-ability of the change. * */ -#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) From 9b8a398930df6606f6314b07c66605f44a8cb0eb Mon Sep 17 00:00:00 2001 From: James Almer Date: Wed, 11 Jan 2023 10:28:22 -0300 Subject: [PATCH 0202/2172] avformat: remove FF_API_AVIOCONTEXT_WRITTEN Signed-off-by: James Almer --- libavformat/avio.h | 10 ---------- libavformat/aviobuf.c | 10 ---------- libavformat/version_major.h | 1 - 3 files changed, 21 deletions(-) diff --git a/libavformat/avio.h b/libavformat/avio.h index 4bf6b1fbdaa..5f13e0622d3 100644 --- a/libavformat/avio.h +++ b/libavformat/avio.h @@ -295,16 +295,6 @@ typedef struct AVIOContext { */ int ignore_boundary_point; -#if FF_API_AVIOCONTEXT_WRITTEN - /** - * @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; -#endif - /** * Maximum reached position before a backward seek in the write buffer, * used keeping track of already written data for a later flush. diff --git a/libavformat/aviobuf.c b/libavformat/aviobuf.c index 257535a9642..4ad734a3c3e 100644 --- a/libavformat/aviobuf.c +++ b/libavformat/aviobuf.c @@ -125,11 +125,6 @@ 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( @@ -174,11 +169,6 @@ static void writeout(AVIOContext *s, const uint8_t *data, int len) 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_major.h b/libavformat/version_major.h index abc1699685a..044af1ebf6f 100644 --- a/libavformat/version_major.h +++ b/libavformat/version_major.h @@ -42,7 +42,6 @@ * */ #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) #define FF_API_GET_END_PTS (LIBAVFORMAT_VERSION_MAJOR < 60) From 1f86fc1c5ede2be519a618e5b22fd11a268021fc Mon Sep 17 00:00:00 2001 From: James Almer Date: Wed, 11 Jan 2023 10:28:49 -0300 Subject: [PATCH 0203/2172] avformat: remove FF_HLS_TS_OPTIONS Signed-off-by: James Almer --- libavformat/hlsenc.c | 3 --- libavformat/version_major.h | 1 - 2 files changed, 4 deletions(-) diff --git a/libavformat/hlsenc.c b/libavformat/hlsenc.c index adf06ec7643..dcc363b42e3 100644 --- a/libavformat/hlsenc.c +++ b/libavformat/hlsenc.c @@ -3116,9 +3116,6 @@ 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}, -#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_major.h b/libavformat/version_major.h index 044af1ebf6f..057d1ac0fb0 100644 --- a/libavformat/version_major.h +++ b/libavformat/version_major.h @@ -42,7 +42,6 @@ * */ #define FF_API_COMPUTE_PKT_FIELDS2 (LIBAVFORMAT_VERSION_MAJOR < 60) -#define FF_HLS_TS_OPTIONS (LIBAVFORMAT_VERSION_MAJOR < 60) #define FF_API_AVSTREAM_CLASS (LIBAVFORMAT_VERSION_MAJOR > 59) #define FF_API_GET_END_PTS (LIBAVFORMAT_VERSION_MAJOR < 60) #define FF_API_AVIODIRCONTEXT (LIBAVFORMAT_VERSION_MAJOR < 60) From 6d6ae3595b74106ad8f59800f26b96ab3dfb297e Mon Sep 17 00:00:00 2001 From: James Almer Date: Wed, 11 Jan 2023 10:31:11 -0300 Subject: [PATCH 0204/2172] avformat: remove FF_API_AVSTREAM_CLASS Signed-off-by: James Almer --- fftools/ffmpeg_mux_init.c | 11 ----------- libavformat/avformat.h | 2 -- libavformat/options.c | 3 --- libavformat/version_major.h | 1 - 4 files changed, 17 deletions(-) diff --git a/fftools/ffmpeg_mux_init.c b/fftools/ffmpeg_mux_init.c index f4ef83f6af1..b3cc502fddc 100644 --- a/fftools/ffmpeg_mux_init.c +++ b/fftools/ffmpeg_mux_init.c @@ -2000,18 +2000,7 @@ static int set_dispositions(Muxer *mux, const OptionsContext *o) if (!disp) continue; -#if LIBAVFORMAT_VERSION_MAJOR >= 60 ret = av_opt_set(ost->st, "disposition", disp, 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, disp, &ost->st->disposition); - } -#endif - if (ret < 0) goto finish; } diff --git a/libavformat/avformat.h b/libavformat/avformat.h index ac40e197f62..b986aacc785 100644 --- a/libavformat/avformat.h +++ b/libavformat/avformat.h @@ -838,12 +838,10 @@ const char *av_disposition_to_string(int disposition); * 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 */ /** diff --git a/libavformat/options.c b/libavformat/options.c index 0079a06d9a5..c7681122cd7 100644 --- a/libavformat/options.c +++ b/libavformat/options.c @@ -257,10 +257,7 @@ 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_major.h b/libavformat/version_major.h index 057d1ac0fb0..1db8e7600eb 100644 --- a/libavformat/version_major.h +++ b/libavformat/version_major.h @@ -42,7 +42,6 @@ * */ #define FF_API_COMPUTE_PKT_FIELDS2 (LIBAVFORMAT_VERSION_MAJOR < 60) -#define FF_API_AVSTREAM_CLASS (LIBAVFORMAT_VERSION_MAJOR > 59) #define FF_API_GET_END_PTS (LIBAVFORMAT_VERSION_MAJOR < 60) #define FF_API_AVIODIRCONTEXT (LIBAVFORMAT_VERSION_MAJOR < 60) From a9e77b42e348f6da8f6f2d98e9fbb64fc5addfdc Mon Sep 17 00:00:00 2001 From: James Almer Date: Wed, 11 Jan 2023 10:33:03 -0300 Subject: [PATCH 0205/2172] avfilter: remove FF_API_SWS_PARAM_OPTION Signed-off-by: James Almer --- libavfilter/buffersrc.c | 11 ----------- libavfilter/version_major.h | 1 - 2 files changed, 12 deletions(-) diff --git a/libavfilter/buffersrc.c b/libavfilter/buffersrc.c index ae8bba19b07..ba17450b937 100644 --- a/libavfilter/buffersrc.c +++ b/libavfilter/buffersrc.c @@ -50,9 +50,6 @@ typedef struct BufferSourceContext { int w, h; enum AVPixelFormat pix_fmt; AVRational pixel_aspect; -#if FF_API_SWS_PARAM_OPTION - char *sws_param; -#endif AVBufferRef *hw_frames_ctx; @@ -287,11 +284,6 @@ static av_cold int init_video(AVFilterContext *ctx) c->time_base.num, c->time_base.den, c->frame_rate.num, c->frame_rate.den, c->pixel_aspect.num, c->pixel_aspect.den); -#if FF_API_SWS_PARAM_OPTION - if (c->sws_param) - av_log(ctx, AV_LOG_WARNING, "sws_param option is deprecated and ignored\n"); -#endif - return 0; } @@ -313,9 +305,6 @@ static const AVOption buffer_options[] = { { "pixel_aspect", "sample aspect ratio", OFFSET(pixel_aspect), AV_OPT_TYPE_RATIONAL, { .dbl = 0 }, 0, DBL_MAX, V }, { "time_base", NULL, OFFSET(time_base), AV_OPT_TYPE_RATIONAL, { .dbl = 0 }, 0, DBL_MAX, V }, { "frame_rate", NULL, OFFSET(frame_rate), AV_OPT_TYPE_RATIONAL, { .dbl = 0 }, 0, DBL_MAX, V }, -#if FF_API_SWS_PARAM_OPTION - { "sws_param", NULL, OFFSET(sws_param), AV_OPT_TYPE_STRING, .flags = V }, -#endif { NULL }, }; diff --git a/libavfilter/version_major.h b/libavfilter/version_major.h index de0cf6e9793..655e3d119d2 100644 --- a/libavfilter/version_major.h +++ b/libavfilter/version_major.h @@ -35,7 +35,6 @@ * the public API and may change, break or disappear at any time. */ -#define FF_API_SWS_PARAM_OPTION (LIBAVFILTER_VERSION_MAJOR < 9) #define FF_API_BUFFERSINK_ALLOC (LIBAVFILTER_VERSION_MAJOR < 9) #define FF_API_PAD_COUNT (LIBAVFILTER_VERSION_MAJOR < 9) From 863822bfaf5374fc8c8cabbf171141621c50e037 Mon Sep 17 00:00:00 2001 From: James Almer Date: Wed, 11 Jan 2023 10:33:48 -0300 Subject: [PATCH 0206/2172] avfilter: remove FF_API_BUFFERSINK_ALLOC Signed-off-by: James Almer --- libavfilter/buffersink.c | 22 ---------------------- libavfilter/buffersink.h | 36 ------------------------------------ libavfilter/version_major.h | 1 - 3 files changed, 59 deletions(-) diff --git a/libavfilter/buffersink.c b/libavfilter/buffersink.c index e269cf72d1b..306c283f775 100644 --- a/libavfilter/buffersink.c +++ b/libavfilter/buffersink.c @@ -154,28 +154,6 @@ int attribute_align_arg av_buffersink_get_samples(AVFilterContext *ctx, return get_frame_internal(ctx, frame, 0, nb_samples); } -#if FF_API_BUFFERSINK_ALLOC -AVBufferSinkParams *av_buffersink_params_alloc(void) -{ - static const int pixel_fmts[] = { AV_PIX_FMT_NONE }; - AVBufferSinkParams *params = av_malloc(sizeof(AVBufferSinkParams)); - if (!params) - return NULL; - - params->pixel_fmts = pixel_fmts; - return params; -} - -AVABufferSinkParams *av_abuffersink_params_alloc(void) -{ - AVABufferSinkParams *params = av_mallocz(sizeof(AVABufferSinkParams)); - - if (!params) - return NULL; - return params; -} -#endif - static av_cold int common_init(AVFilterContext *ctx) { BufferSinkContext *buf = ctx->priv; diff --git a/libavfilter/buffersink.h b/libavfilter/buffersink.h index 01e7c747d8e..64e08de53ee 100644 --- a/libavfilter/buffersink.h +++ b/libavfilter/buffersink.h @@ -94,42 +94,6 @@ int av_buffersink_get_frame_flags(AVFilterContext *ctx, AVFrame *frame, int flag */ #define AV_BUFFERSINK_FLAG_NO_REQUEST 2 -#if FF_API_BUFFERSINK_ALLOC -/** - * Deprecated and unused struct to use for initializing a buffersink context. - */ -typedef struct AVBufferSinkParams { - const enum AVPixelFormat *pixel_fmts; ///< list of allowed pixel formats, terminated by AV_PIX_FMT_NONE -} AVBufferSinkParams; - -/** - * Create an AVBufferSinkParams structure. - * - * Must be freed with av_free(). - */ -attribute_deprecated -AVBufferSinkParams *av_buffersink_params_alloc(void); - -/** - * Deprecated and unused struct to use for initializing an abuffersink context. - */ -typedef struct AVABufferSinkParams { - const enum AVSampleFormat *sample_fmts; ///< list of allowed sample formats, terminated by AV_SAMPLE_FMT_NONE - const int64_t *channel_layouts; ///< list of allowed channel layouts, terminated by -1 - const int *channel_counts; ///< list of allowed channel counts, terminated by -1 - int all_channel_counts; ///< if not 0, accept any channel count or layout - int *sample_rates; ///< list of allowed sample rates, terminated by -1 -} AVABufferSinkParams; - -/** - * Create an AVABufferSinkParams structure. - * - * Must be freed with av_free(). - */ -attribute_deprecated -AVABufferSinkParams *av_abuffersink_params_alloc(void); -#endif - /** * Set the frame size for an audio buffer sink. * diff --git a/libavfilter/version_major.h b/libavfilter/version_major.h index 655e3d119d2..5a8bf4eda21 100644 --- a/libavfilter/version_major.h +++ b/libavfilter/version_major.h @@ -35,7 +35,6 @@ * the public API and may change, break or disappear at any time. */ -#define FF_API_BUFFERSINK_ALLOC (LIBAVFILTER_VERSION_MAJOR < 9) #define FF_API_PAD_COUNT (LIBAVFILTER_VERSION_MAJOR < 9) #endif /* AVFILTER_VERSION_MAJOR_H */ From 8bc0d3132082c0d87f40e41867042ce7a383cf56 Mon Sep 17 00:00:00 2001 From: James Almer Date: Wed, 11 Jan 2023 10:34:25 -0300 Subject: [PATCH 0207/2172] avfilter: remove FF_API_PAD_COUNT Signed-off-by: James Almer --- libavfilter/avfilter.c | 21 --------------------- libavfilter/avfilter.h | 10 ---------- libavfilter/version_major.h | 2 -- 3 files changed, 33 deletions(-) diff --git a/libavfilter/avfilter.c b/libavfilter/avfilter.c index c2ecdffa6f5..ed363351add 100644 --- a/libavfilter/avfilter.c +++ b/libavfilter/avfilter.c @@ -560,27 +560,6 @@ int avfilter_process_command(AVFilterContext *filter, const char *cmd, const cha return AVERROR(ENOSYS); } -#if FF_API_PAD_COUNT -int avfilter_pad_count(const AVFilterPad *pads) -{ - const AVFilter *filter; - void *opaque = NULL; - - if (!pads) - return 0; - - while (filter = av_filter_iterate(&opaque)) { - if (pads == filter->inputs) - return filter->nb_inputs; - if (pads == filter->outputs) - return filter->nb_outputs; - } - - av_assert0(!"AVFilterPad list not from a filter"); - return AVERROR_BUG; -} -#endif - unsigned avfilter_filter_pad_count(const AVFilter *filter, int is_output) { return is_output ? filter->nb_outputs : filter->nb_inputs; diff --git a/libavfilter/avfilter.h b/libavfilter/avfilter.h index c2ec7a4b5fc..333eeb31c3d 100644 --- a/libavfilter/avfilter.h +++ b/libavfilter/avfilter.h @@ -76,16 +76,6 @@ typedef struct AVFilterPad AVFilterPad; typedef struct AVFilterFormats AVFilterFormats; typedef struct AVFilterChannelLayouts AVFilterChannelLayouts; -#if FF_API_PAD_COUNT -/** - * Get the number of elements in an AVFilter's inputs or outputs array. - * - * @deprecated Use avfilter_filter_pad_count() instead. - */ -attribute_deprecated -int avfilter_pad_count(const AVFilterPad *pads); -#endif - /** * Get the name of an AVFilterPad. * diff --git a/libavfilter/version_major.h b/libavfilter/version_major.h index 5a8bf4eda21..cb2238ffdd0 100644 --- a/libavfilter/version_major.h +++ b/libavfilter/version_major.h @@ -35,6 +35,4 @@ * the public API and may change, break or disappear at any time. */ -#define FF_API_PAD_COUNT (LIBAVFILTER_VERSION_MAJOR < 9) - #endif /* AVFILTER_VERSION_MAJOR_H */ From 4fcd6c82cf45160880be35e6c097708323d9d93f Mon Sep 17 00:00:00 2001 From: James Almer Date: Wed, 11 Jan 2023 10:35:51 -0300 Subject: [PATCH 0208/2172] avdevice: remove FF_API_DEVICE_CAPABILITIES Signed-off-by: James Almer --- libavdevice/avdevice.c | 19 ------ libavdevice/avdevice.h | 130 ------------------------------------ libavdevice/version_major.h | 1 - 3 files changed, 150 deletions(-) diff --git a/libavdevice/avdevice.c b/libavdevice/avdevice.c index b47f89c4bf2..38110ddfdb2 100644 --- a/libavdevice/avdevice.c +++ b/libavdevice/avdevice.c @@ -21,12 +21,6 @@ #include "internal.h" #include "libavformat/mux.h" -#if FF_API_DEVICE_CAPABILITIES -const AVOption av_device_capabilities[] = { - { NULL } -}; -#endif - int avdevice_app_to_dev_control_message(struct AVFormatContext *s, enum AVAppToDevMessageType type, void *data, size_t data_size) { @@ -43,19 +37,6 @@ int avdevice_dev_to_app_control_message(struct AVFormatContext *s, enum AVDevToA return s->control_message_cb(s, type, data, data_size); } -#if FF_API_DEVICE_CAPABILITIES -int avdevice_capabilities_create(AVDeviceCapabilitiesQuery **caps, AVFormatContext *s, - AVDictionary **device_options) -{ - return AVERROR(ENOSYS); -} - -void avdevice_capabilities_free(AVDeviceCapabilitiesQuery **caps, AVFormatContext *s) -{ - return; -} -#endif - int avdevice_list_devices(AVFormatContext *s, AVDeviceInfoList **device_list) { int ret; diff --git a/libavdevice/avdevice.h b/libavdevice/avdevice.h index 185593053f7..887fd5e3c80 100644 --- a/libavdevice/avdevice.h +++ b/libavdevice/avdevice.h @@ -327,136 +327,6 @@ int avdevice_dev_to_app_control_message(struct AVFormatContext *s, enum AVDevToAppMessageType type, void *data, size_t data_size); -#if FF_API_DEVICE_CAPABILITIES -/** - * Following API allows user to probe device capabilities (supported codecs, - * pixel formats, sample formats, resolutions, channel counts, etc). - * It is build on top op AVOption API. - * Queried capabilities make it possible to set up converters of video or audio - * parameters that fit to the device. - * - * List of capabilities that can be queried: - * - Capabilities valid for both audio and video devices: - * - codec: supported audio/video codecs. - * type: AV_OPT_TYPE_INT (AVCodecID value) - * - Capabilities valid for audio devices: - * - sample_format: supported sample formats. - * type: AV_OPT_TYPE_INT (AVSampleFormat value) - * - sample_rate: supported sample rates. - * type: AV_OPT_TYPE_INT - * - channels: supported number of channels. - * type: AV_OPT_TYPE_INT - * - channel_layout: supported channel layouts. - * type: AV_OPT_TYPE_INT64 - * - Capabilities valid for video devices: - * - pixel_format: supported pixel formats. - * type: AV_OPT_TYPE_INT (AVPixelFormat value) - * - window_size: supported window sizes (describes size of the window size presented to the user). - * type: AV_OPT_TYPE_IMAGE_SIZE - * - frame_size: supported frame sizes (describes size of provided video frames). - * type: AV_OPT_TYPE_IMAGE_SIZE - * - fps: supported fps values - * type: AV_OPT_TYPE_RATIONAL - * - * Value of the capability may be set by user using av_opt_set() function - * and AVDeviceCapabilitiesQuery object. Following queries will - * limit results to the values matching already set capabilities. - * For example, setting a codec may impact number of formats or fps values - * returned during next query. Setting invalid value may limit results to zero. - * - * Example of the usage basing on opengl output device: - * - * @code - * AVFormatContext *oc = NULL; - * AVDeviceCapabilitiesQuery *caps = NULL; - * AVOptionRanges *ranges; - * int ret; - * - * if ((ret = avformat_alloc_output_context2(&oc, NULL, "opengl", NULL)) < 0) - * goto fail; - * if (avdevice_capabilities_create(&caps, oc, NULL) < 0) - * goto fail; - * - * //query codecs - * if (av_opt_query_ranges(&ranges, caps, "codec", AV_OPT_MULTI_COMPONENT_RANGE)) < 0) - * goto fail; - * //pick codec here and set it - * av_opt_set(caps, "codec", AV_CODEC_ID_RAWVIDEO, 0); - * - * //query format - * if (av_opt_query_ranges(&ranges, caps, "pixel_format", AV_OPT_MULTI_COMPONENT_RANGE)) < 0) - * goto fail; - * //pick format here and set it - * av_opt_set(caps, "pixel_format", AV_PIX_FMT_YUV420P, 0); - * - * //query and set more capabilities - * - * fail: - * //clean up code - * avdevice_capabilities_free(&query, oc); - * avformat_free_context(oc); - * @endcode - */ - -/** - * Structure describes device capabilities. - * - * It is used by devices in conjunction with av_device_capabilities AVOption table - * to implement capabilities probing API based on AVOption API. Should not be used directly. - */ -typedef struct AVDeviceCapabilitiesQuery { - const AVClass *av_class; - AVFormatContext *device_context; - enum AVCodecID codec; - enum AVSampleFormat sample_format; - enum AVPixelFormat pixel_format; - int sample_rate; - int channels; - int64_t channel_layout; - int window_width; - int window_height; - int frame_width; - int frame_height; - AVRational fps; -} AVDeviceCapabilitiesQuery; - -/** - * AVOption table used by devices to implement device capabilities API. Should not be used by a user. - */ -attribute_deprecated -extern const AVOption av_device_capabilities[]; - -/** - * Initialize capabilities probing API based on AVOption API. - * - * avdevice_capabilities_free() must be called when query capabilities API is - * not used anymore. - * - * @param[out] caps Device capabilities data. Pointer to a NULL pointer must be passed. - * @param s Context of the device. - * @param device_options An AVDictionary filled with device-private options. - * On return this parameter will be destroyed and replaced with a dict - * containing options that were not found. May be NULL. - * The same options must be passed later to avformat_write_header() for output - * devices or avformat_open_input() for input devices, or at any other place - * that affects device-private options. - * - * @return >= 0 on success, negative otherwise. - */ -attribute_deprecated -int avdevice_capabilities_create(AVDeviceCapabilitiesQuery **caps, AVFormatContext *s, - AVDictionary **device_options); - -/** - * Free resources created by avdevice_capabilities_create() - * - * @param caps Device capabilities data to be freed. - * @param s Context of the device. - */ -attribute_deprecated -void avdevice_capabilities_free(AVDeviceCapabilitiesQuery **caps, AVFormatContext *s); -#endif - /** * Structure describes basic parameters of the device. */ diff --git a/libavdevice/version_major.h b/libavdevice/version_major.h index d255ff6992d..571257f31d7 100644 --- a/libavdevice/version_major.h +++ b/libavdevice/version_major.h @@ -32,6 +32,5 @@ * 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. */ -#define FF_API_DEVICE_CAPABILITIES (LIBAVDEVICE_VERSION_MAJOR < 60) #endif /* AVDEVICE_VERSION_MAJOR_H */ From 30e1e7e0f324d7bf66b3b8583a3e49fd3cd101b2 Mon Sep 17 00:00:00 2001 From: James Almer Date: Wed, 11 Jan 2023 10:37:58 -0300 Subject: [PATCH 0209/2172] avutil: remove FF_API_D2STR Signed-off-by: James Almer --- libavutil/avstring.c | 10 ---------- libavutil/avstring.h | 9 --------- libavutil/tests/avstring.c | 16 ---------------- libavutil/version.h | 1 - 4 files changed, 36 deletions(-) diff --git a/libavutil/avstring.c b/libavutil/avstring.c index 5ddbe9219e8..e460b5be7f3 100644 --- a/libavutil/avstring.c +++ b/libavutil/avstring.c @@ -139,16 +139,6 @@ char *av_asprintf(const char *fmt, ...) return p; } -#if FF_API_D2STR -char *av_d2str(double d) -{ - char *str = av_malloc(16); - if (str) - snprintf(str, 16, "%f", d); - return str; -} -#endif - #define WHITESPACES " \n\t\r" char *av_get_token(const char **buf, const char *term) diff --git a/libavutil/avstring.h b/libavutil/avstring.h index 74aa4cd0e4e..e2602637630 100644 --- a/libavutil/avstring.h +++ b/libavutil/avstring.h @@ -157,15 +157,6 @@ static inline size_t av_strnlen(const char *s, size_t len) */ char *av_asprintf(const char *fmt, ...) av_printf_format(1, 2); -#if FF_API_D2STR -/** - * Convert a number to an av_malloced string. - * @deprecated use av_asprintf() with "%f" or a more specific format - */ -attribute_deprecated -char *av_d2str(double d); -#endif - /** * Unescape the given string until a non escaped terminating char, * and return the token corresponding to the unescaped string. diff --git a/libavutil/tests/avstring.c b/libavutil/tests/avstring.c index 37a2cf18334..bc0bde358d5 100644 --- a/libavutil/tests/avstring.c +++ b/libavutil/tests/avstring.c @@ -109,21 +109,5 @@ int main(void) TEST_STRIREPLACE(haystack, needle [2], "Education consists mainly in what we have instead."); TEST_STRIREPLACE(haystack, needle [1], "Education consists mainly in what we have instead"); -#if FF_API_D2STR -FF_DISABLE_DEPRECATION_WARNINGS - /*Testing av_d2str()*/ - #define TEST_D2STR(value, expected) \ - if((ptr = av_d2str(value)) == NULL){ \ - printf("error, received null pointer!\n"); \ - } else { \ - if(strcmp(ptr, expected) != 0) \ - printf( "expected: %s, received: %s\n", expected, ptr); \ - av_free(ptr); \ - } - TEST_D2STR(0 , "0.000000"); - TEST_D2STR(-1.2333234, "-1.233323"); - TEST_D2STR(-1.2333237, "-1.233324"); -FF_ENABLE_DEPRECATION_WARNINGS -#endif return 0; } diff --git a/libavutil/version.h b/libavutil/version.h index 43daf8cd5ad..bd5d7afe9d0 100644 --- a/libavutil/version.h +++ b/libavutil/version.h @@ -105,7 +105,6 @@ * @{ */ -#define FF_API_D2STR (LIBAVUTIL_VERSION_MAJOR < 58) #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) From 21814a70db08999efee49531c67f62e2678a62f4 Mon Sep 17 00:00:00 2001 From: James Almer Date: Wed, 11 Jan 2023 10:46:41 -0300 Subject: [PATCH 0210/2172] avutil: remove FF_API_DECLARE_ALIGNED Signed-off-by: James Almer --- libavcodec/qdmc.c | 1 + libavutil/mem.h | 80 ---------------------------------------- libavutil/mem_internal.h | 2 - libavutil/version.h | 1 - 4 files changed, 1 insertion(+), 83 deletions(-) diff --git a/libavcodec/qdmc.c b/libavcodec/qdmc.c index 4b582dc3491..081c4dd46f0 100644 --- a/libavcodec/qdmc.c +++ b/libavcodec/qdmc.c @@ -25,6 +25,7 @@ #define BITSTREAM_READER_LE #include "libavutil/channel_layout.h" +#include "libavutil/mem_internal.h" #include "libavutil/thread.h" #include "libavutil/tx.h" diff --git a/libavutil/mem.h b/libavutil/mem.h index c9c4fcf1ff0..b093b3b5cb0 100644 --- a/libavutil/mem.h +++ b/libavutil/mem.h @@ -51,86 +51,6 @@ * @{ */ -#if FF_API_DECLARE_ALIGNED -/** - * - * @defgroup lavu_mem_macros Alignment Macros - * Helper macros for declaring aligned variables. - * @{ - */ - -/** - * @def DECLARE_ALIGNED(n,t,v) - * Declare a variable that is aligned in memory. - * - * @code{.c} - * DECLARE_ALIGNED(16, uint16_t, aligned_int) = 42; - * DECLARE_ALIGNED(32, uint8_t, aligned_array)[128]; - * - * // The default-alignment equivalent would be - * uint16_t aligned_int = 42; - * uint8_t aligned_array[128]; - * @endcode - * - * @param n Minimum alignment in bytes - * @param t Type of the variable (or array element) - * @param v Name of the variable - */ - -/** - * @def DECLARE_ASM_ALIGNED(n,t,v) - * Declare an aligned variable appropriate for use in inline assembly code. - * - * @code{.c} - * DECLARE_ASM_ALIGNED(16, uint64_t, pw_08) = UINT64_C(0x0008000800080008); - * @endcode - * - * @param n Minimum alignment in bytes - * @param t Type of the variable (or array element) - * @param v Name of the variable - */ - -/** - * @def DECLARE_ASM_CONST(n,t,v) - * Declare a static constant aligned variable appropriate for use in inline - * assembly code. - * - * @code{.c} - * DECLARE_ASM_CONST(16, uint64_t, pw_08) = UINT64_C(0x0008000800080008); - * @endcode - * - * @param n Minimum alignment in bytes - * @param t Type of the variable (or array element) - * @param v Name of the variable - */ - -#if defined(__INTEL_COMPILER) && __INTEL_COMPILER < 1110 || defined(__SUNPRO_C) - #define DECLARE_ALIGNED(n,t,v) t __attribute__ ((aligned (n))) v - #define DECLARE_ASM_ALIGNED(n,t,v) t __attribute__ ((aligned (n))) v - #define DECLARE_ASM_CONST(n,t,v) const t __attribute__ ((aligned (n))) v -#elif defined(__DJGPP__) - #define DECLARE_ALIGNED(n,t,v) t __attribute__ ((aligned (FFMIN(n, 16)))) v - #define DECLARE_ASM_ALIGNED(n,t,v) t av_used __attribute__ ((aligned (FFMIN(n, 16)))) v - #define DECLARE_ASM_CONST(n,t,v) static const t av_used __attribute__ ((aligned (FFMIN(n, 16)))) v -#elif defined(__GNUC__) || defined(__clang__) - #define DECLARE_ALIGNED(n,t,v) t __attribute__ ((aligned (n))) v - #define DECLARE_ASM_ALIGNED(n,t,v) t av_used __attribute__ ((aligned (n))) v - #define DECLARE_ASM_CONST(n,t,v) static const t av_used __attribute__ ((aligned (n))) v -#elif defined(_MSC_VER) - #define DECLARE_ALIGNED(n,t,v) __declspec(align(n)) t v - #define DECLARE_ASM_ALIGNED(n,t,v) __declspec(align(n)) t v - #define DECLARE_ASM_CONST(n,t,v) __declspec(align(n)) static const t v -#else - #define DECLARE_ALIGNED(n,t,v) t v - #define DECLARE_ASM_ALIGNED(n,t,v) t v - #define DECLARE_ASM_CONST(n,t,v) static const t v -#endif - -/** - * @} - */ -#endif - /** * @defgroup lavu_mem_attrs Function Attributes * Function attributes applicable to memory handling functions. diff --git a/libavutil/mem_internal.h b/libavutil/mem_internal.h index 955e31a6981..2448c606f19 100644 --- a/libavutil/mem_internal.h +++ b/libavutil/mem_internal.h @@ -30,7 +30,6 @@ #include "mem.h" #include "version.h" -#if !FF_API_DECLARE_ALIGNED /** * @def DECLARE_ALIGNED(n,t,v) * Declare a variable that is aligned in memory. @@ -97,7 +96,6 @@ #define DECLARE_ASM_ALIGNED(n,t,v) t v #define DECLARE_ASM_CONST(n,t,v) static const t v #endif -#endif // Some broken preprocessors need a second expansion // to be forced to tokenize __VA_ARGS__ diff --git a/libavutil/version.h b/libavutil/version.h index bd5d7afe9d0..2e646fd6379 100644 --- a/libavutil/version.h +++ b/libavutil/version.h @@ -105,7 +105,6 @@ * @{ */ -#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) From 16c4e8f9c106c1e4f4e50a06b7ed0350928775b8 Mon Sep 17 00:00:00 2001 From: James Almer Date: Wed, 11 Jan 2023 10:48:27 -0300 Subject: [PATCH 0211/2172] avutil: remove FF_API_COLORSPACE_NAME Signed-off-by: James Almer --- libavutil/frame.c | 17 ----------------- libavutil/frame.h | 9 --------- libavutil/version.h | 1 - 3 files changed, 27 deletions(-) diff --git a/libavutil/frame.c b/libavutil/frame.c index 2d81de8b0d2..4d89c75dc88 100644 --- a/libavutil/frame.c +++ b/libavutil/frame.c @@ -35,23 +35,6 @@ av_get_channel_layout_nb_channels((frame)->channel_layout)) #endif -#if FF_API_COLORSPACE_NAME -const char *av_get_colorspace_name(enum AVColorSpace val) -{ - static const char * const name[] = { - [AVCOL_SPC_RGB] = "GBR", - [AVCOL_SPC_BT709] = "bt709", - [AVCOL_SPC_FCC] = "fcc", - [AVCOL_SPC_BT470BG] = "bt470bg", - [AVCOL_SPC_SMPTE170M] = "smpte170m", - [AVCOL_SPC_SMPTE240M] = "smpte240m", - [AVCOL_SPC_YCOCG] = "YCgCo", - }; - if ((unsigned)val >= FF_ARRAY_ELEMS(name)) - return NULL; - return name[val]; -} -#endif static void get_frame_defaults(AVFrame *frame) { memset(frame, 0, sizeof(*frame)); diff --git a/libavutil/frame.h b/libavutil/frame.h index 911af515f47..e5c92a0ca81 100644 --- a/libavutil/frame.h +++ b/libavutil/frame.h @@ -725,15 +725,6 @@ typedef struct AVFrame { } AVFrame; -#if FF_API_COLORSPACE_NAME -/** - * Get the name of a colorspace. - * @return a static string identifying the colorspace; can be NULL. - * @deprecated use av_color_space_name() - */ -attribute_deprecated -const char *av_get_colorspace_name(enum AVColorSpace val); -#endif /** * Allocate an AVFrame and set its fields to default values. The resulting * struct must be freed using av_frame_free(). diff --git a/libavutil/version.h b/libavutil/version.h index 2e646fd6379..a635d6d7a32 100644 --- a/libavutil/version.h +++ b/libavutil/version.h @@ -105,7 +105,6 @@ * @{ */ -#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) #define FF_API_FIFO_OLD_API (LIBAVUTIL_VERSION_MAJOR < 58) From dc1b8135e096e4a41c1d606f8ca5795053136ad7 Mon Sep 17 00:00:00 2001 From: James Almer Date: Wed, 11 Jan 2023 10:50:01 -0300 Subject: [PATCH 0212/2172] avutil: remove FF_API_AV_MALLOCZ_ARRAY Signed-off-by: James Almer --- libavutil/mem.c | 10 ---------- libavutil/mem.h | 8 -------- libavutil/version.h | 1 - 3 files changed, 19 deletions(-) diff --git a/libavutil/mem.c b/libavutil/mem.c index 18aff5291f0..36b8940a0cf 100644 --- a/libavutil/mem.c +++ b/libavutil/mem.c @@ -212,16 +212,6 @@ void *av_malloc_array(size_t nmemb, size_t size) return av_malloc(result); } -#if FF_API_AV_MALLOCZ_ARRAY -void *av_mallocz_array(size_t nmemb, size_t size) -{ - size_t result; - if (size_mult(nmemb, size, &result) < 0) - return NULL; - return av_mallocz(result); -} -#endif - void *av_realloc_array(void *ptr, size_t nmemb, size_t size) { size_t result; diff --git a/libavutil/mem.h b/libavutil/mem.h index b093b3b5cb0..62b4ca6e50e 100644 --- a/libavutil/mem.h +++ b/libavutil/mem.h @@ -159,14 +159,6 @@ av_alloc_size(1, 2) void *av_malloc_array(size_t nmemb, size_t size); */ void *av_calloc(size_t nmemb, size_t size) av_malloc_attrib av_alloc_size(1, 2); -#if FF_API_AV_MALLOCZ_ARRAY -/** - * @deprecated use av_calloc() - */ -attribute_deprecated -void *av_mallocz_array(size_t nmemb, size_t size) av_malloc_attrib av_alloc_size(1, 2); -#endif - /** * Allocate, reallocate, or free a block of memory. * diff --git a/libavutil/version.h b/libavutil/version.h index a635d6d7a32..40dc9f241ff 100644 --- a/libavutil/version.h +++ b/libavutil/version.h @@ -105,7 +105,6 @@ * @{ */ -#define FF_API_AV_MALLOCZ_ARRAY (LIBAVUTIL_VERSION_MAJOR < 58) #define FF_API_FIFO_PEEK2 (LIBAVUTIL_VERSION_MAJOR < 58) #define FF_API_FIFO_OLD_API (LIBAVUTIL_VERSION_MAJOR < 58) #define FF_API_XVMC (LIBAVUTIL_VERSION_MAJOR < 58) From 719a93f4e40b202c5b74b58bcff85395a3edd0c7 Mon Sep 17 00:00:00 2001 From: Leo Izen Date: Mon, 30 Jan 2023 11:50:10 -0500 Subject: [PATCH 0213/2172] avutil/{color_utils, csp}: merge color_utils into csp and expose API libavutil/color_utils contains some avpriv_ symbols that map enum AVTransferCharacteristic values to gamma-curve approximations and to the actual transfer functions to invert them (i.e. -> linear). There's two issues with this: (1) avpriv is evil and should be avoided whenever possible (2) libavutil/csp.h exposes a public API for handling color that already handles primaries and matricies I don't see any reason this API has to be private, so this commit takes the functionality from avutil/color_utils and merges it into avutil/csp with an exposed av_ API rather than the previous avpriv_ API. Every reference to the previous API has been updated to point to the new one. color_utils.h has been deleted as well. This should not break any applications as it only contained avpriv_ symbols in the first place, so nothing in that header could be referenced by other applications. Signed-off-by: Leo Izen Signed-off-by: Anton Khirnov --- doc/APIchanges | 4 + libavcodec/exr.c | 8 +- libavcodec/fflcms2.c | 1 - libavcodec/pngenc.c | 3 +- libavformat/movenc.c | 7 +- libavutil/Makefile | 1 - libavutil/color_utils.c | 234 ---------------------------------- libavutil/color_utils.h | 56 -------- libavutil/csp.c | 172 +++++++++++++++++++++++++ libavutil/csp.h | 39 ++++++ libavutil/tests/color_utils.c | 4 +- 11 files changed, 225 insertions(+), 304 deletions(-) delete mode 100644 libavutil/color_utils.c delete mode 100644 libavutil/color_utils.h diff --git a/doc/APIchanges b/doc/APIchanges index c4b9dc114b8..f38bc0baeac 100644 --- a/doc/APIchanges +++ b/doc/APIchanges @@ -14,6 +14,10 @@ libavutil: 2021-04-27 API changes, most recent first: +2023-02-xx - xxxxxxxxxx - lavu 58.0.100 - csp.h + Add av_csp_approximate_trc_gamma() and av_csp_trc_func_from_id(). + Add av_csp_trc_function. + 2023-02-xx - xxxxxxxxxx - lavc 60.0.100 - avcodec.h avcodec_decode_subtitle2() now accepts const AVPacket*. diff --git a/libavcodec/exr.c b/libavcodec/exr.c index 6a0af96ce4f..2f1766c17bf 100644 --- a/libavcodec/exr.c +++ b/libavcodec/exr.c @@ -36,11 +36,11 @@ #include "libavutil/avassert.h" #include "libavutil/common.h" +#include "libavutil/csp.h" #include "libavutil/imgutils.h" #include "libavutil/intfloat.h" #include "libavutil/avstring.h" #include "libavutil/opt.h" -#include "libavutil/color_utils.h" #include "libavutil/half2float.h" #include "avcodec.h" @@ -1189,7 +1189,7 @@ static int decode_block(AVCodecContext *avctx, void *tdata, int i, x, buf_size = s->buf_size; int c, rgb_channel_count; float one_gamma = 1.0f / s->gamma; - avpriv_trc_function trc_func = avpriv_get_trc_function_from_trc(s->apply_trc_type); + av_csp_trc_function trc_func = av_csp_trc_func_from_id(s->apply_trc_type); int ret; line_offset = AV_RL64(s->gb.buffer + jobnr * 8); @@ -2215,7 +2215,7 @@ static av_cold int decode_init(AVCodecContext *avctx) uint32_t i; union av_intfloat32 t; float one_gamma = 1.0f / s->gamma; - avpriv_trc_function trc_func = NULL; + av_csp_trc_function trc_func = NULL; ff_init_half2float_tables(&s->h2f_tables); @@ -2227,7 +2227,7 @@ static av_cold int decode_init(AVCodecContext *avctx) ff_bswapdsp_init(&s->bbdsp); #endif - trc_func = avpriv_get_trc_function_from_trc(s->apply_trc_type); + trc_func = av_csp_trc_func_from_id(s->apply_trc_type); if (trc_func) { for (i = 0; i < 65536; ++i) { t.i = half2float(i, &s->h2f_tables); diff --git a/libavcodec/fflcms2.c b/libavcodec/fflcms2.c index fd370fb310f..5443f178bc9 100644 --- a/libavcodec/fflcms2.c +++ b/libavcodec/fflcms2.c @@ -17,7 +17,6 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include "libavutil/color_utils.h" #include "libavutil/csp.h" #include "fflcms2.h" diff --git a/libavcodec/pngenc.c b/libavcodec/pngenc.c index 81b95c143dc..43bf2039fff 100644 --- a/libavcodec/pngenc.c +++ b/libavcodec/pngenc.c @@ -29,7 +29,6 @@ #include "zlib_wrapper.h" #include "libavutil/avassert.h" -#include "libavutil/color_utils.h" #include "libavutil/crc.h" #include "libavutil/csp.h" #include "libavutil/libm.h" @@ -317,7 +316,7 @@ static int png_get_chrm(enum AVColorPrimaries prim, uint8_t *buf) static int png_get_gama(enum AVColorTransferCharacteristic trc, uint8_t *buf) { - double gamma = avpriv_get_gamma_from_trc(trc); + double gamma = av_csp_approximate_trc_gamma(trc); if (gamma <= 1e-6) return 0; diff --git a/libavformat/movenc.c b/libavformat/movenc.c index 87ee7a921f0..aca8b9d5853 100644 --- a/libavformat/movenc.c +++ b/libavformat/movenc.c @@ -47,6 +47,7 @@ #include "internal.h" #include "libavutil/avstring.h" #include "libavutil/channel_layout.h" +#include "libavutil/csp.h" #include "libavutil/intfloat.h" #include "libavutil/mathematics.h" #include "libavutil/libm.h" @@ -56,7 +57,6 @@ #include "libavutil/stereo3d.h" #include "libavutil/timecode.h" #include "libavutil/dovi_meta.h" -#include "libavutil/color_utils.h" #include "libavutil/uuid.h" #include "hevc.h" #include "rtpenc.h" @@ -2011,9 +2011,8 @@ static int mov_write_pasp_tag(AVIOContext *pb, MOVTrack *track) static int mov_write_gama_tag(AVFormatContext *s, AVIOContext *pb, MOVTrack *track, double gamma) { uint32_t gama = 0; - if (gamma <= 0.0) { - gamma = avpriv_get_gamma_from_trc(track->par->color_trc); - } + if (gamma <= 0.0) + gamma = av_csp_approximate_trc_gamma(track->par->color_trc); av_log(s, AV_LOG_DEBUG, "gamma value %g\n", gamma); if (gamma > 1e-6) { diff --git a/libavutil/Makefile b/libavutil/Makefile index 29b06665f50..dc9012f9a83 100644 --- a/libavutil/Makefile +++ b/libavutil/Makefile @@ -114,7 +114,6 @@ OBJS = adler32.o \ cast5.o \ camellia.o \ channel_layout.o \ - color_utils.o \ cpu.o \ crc.o \ csp.o \ diff --git a/libavutil/color_utils.c b/libavutil/color_utils.c deleted file mode 100644 index 5e221fb7983..00000000000 --- a/libavutil/color_utils.c +++ /dev/null @@ -1,234 +0,0 @@ -/* - * Copyright (c) 2015 Kevin Wheatley - * - * 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/color_utils.h" -#include "libavutil/pixfmt.h" - -double avpriv_get_gamma_from_trc(enum AVColorTransferCharacteristic trc) -{ - double gamma; - switch (trc) { - case AVCOL_TRC_BT709: - case AVCOL_TRC_SMPTE170M: - case AVCOL_TRC_SMPTE240M: - case AVCOL_TRC_BT1361_ECG: - case AVCOL_TRC_BT2020_10: - case AVCOL_TRC_BT2020_12: - /* these share a segmented TRC, but gamma 1.961 is a close - approximation, and also more correct for decoding content */ - gamma = 1.961; - break; - case AVCOL_TRC_GAMMA22: - case AVCOL_TRC_IEC61966_2_1: - gamma = 2.2; - break; - case AVCOL_TRC_GAMMA28: - gamma = 2.8; - break; - case AVCOL_TRC_LINEAR: - gamma = 1.0; - break; - default: - gamma = 0.0; // Unknown value representation - } - return gamma; -} - -#define BT709_alpha 1.099296826809442 -#define BT709_beta 0.018053968510807 - -static double avpriv_trc_bt709(double Lc) -{ - const double a = BT709_alpha; - const double b = BT709_beta; - - return (0.0 > Lc) ? 0.0 - : ( b > Lc) ? 4.500 * Lc - : a * pow(Lc, 0.45) - (a - 1.0); -} - -static double avpriv_trc_gamma22(double Lc) -{ - return (0.0 > Lc) ? 0.0 : pow(Lc, 1.0/ 2.2); -} - -static double avpriv_trc_gamma28(double Lc) -{ - return (0.0 > Lc) ? 0.0 : pow(Lc, 1.0/ 2.8); -} - -static double avpriv_trc_smpte240M(double Lc) -{ - const double a = 1.1115; - const double b = 0.0228; - - return (0.0 > Lc) ? 0.0 - : ( b > Lc) ? 4.000 * Lc - : a * pow(Lc, 0.45) - (a - 1.0); -} - -static double avpriv_trc_linear(double Lc) -{ - return Lc; -} - -static double avpriv_trc_log(double Lc) -{ - return (0.01 > Lc) ? 0.0 : 1.0 + log10(Lc) / 2.0; -} - -static double avpriv_trc_log_sqrt(double Lc) -{ - // sqrt(10) / 1000 - return (0.00316227766 > Lc) ? 0.0 : 1.0 + log10(Lc) / 2.5; -} - -static double avpriv_trc_iec61966_2_4(double Lc) -{ - const double a = BT709_alpha; - const double b = BT709_beta; - - return (-b >= Lc) ? -a * pow(-Lc, 0.45) + (a - 1.0) - : ( b > Lc) ? 4.500 * Lc - : a * pow( Lc, 0.45) - (a - 1.0); -} - -static double avpriv_trc_bt1361(double Lc) -{ - const double a = BT709_alpha; - const double b = BT709_beta; - - return (-0.0045 >= Lc) ? -(a * pow(-4.0 * Lc, 0.45) + (a - 1.0)) / 4.0 - : ( b > Lc) ? 4.500 * Lc - : a * pow( Lc, 0.45) - (a - 1.0); -} - -static double avpriv_trc_iec61966_2_1(double Lc) -{ - const double a = 1.055; - const double b = 0.0031308; - - return (0.0 > Lc) ? 0.0 - : ( b > Lc) ? 12.92 * Lc - : a * pow(Lc, 1.0 / 2.4) - (a - 1.0); -} - -static double avpriv_trc_smpte_st2084(double Lc) -{ - const double c1 = 3424.0 / 4096.0; // c3-c2 + 1 - const double c2 = 32.0 * 2413.0 / 4096.0; - const double c3 = 32.0 * 2392.0 / 4096.0; - const double m = 128.0 * 2523.0 / 4096.0; - const double n = 0.25 * 2610.0 / 4096.0; - const double L = Lc / 10000.0; - const double Ln = pow(L, n); - - return (0.0 > Lc) ? 0.0 - : pow((c1 + c2 * Ln) / (1.0 + c3 * Ln), m); - -} - -static double avpriv_trc_smpte_st428_1(double Lc) -{ - return (0.0 > Lc) ? 0.0 - : pow(48.0 * Lc / 52.37, 1.0 / 2.6); -} - - -static double avpriv_trc_arib_std_b67(double Lc) { - // The function uses the definition from HEVC, which assumes that the peak - // white is input level = 1. (this is equivalent to scaling E = Lc * 12 and - // using the definition from the ARIB STD-B67 spec) - const double a = 0.17883277; - const double b = 0.28466892; - const double c = 0.55991073; - return (0.0 > Lc) ? 0.0 : - (Lc <= 1.0 / 12.0 ? sqrt(3.0 * Lc) : a * log(12.0 * Lc - b) + c); -} - -avpriv_trc_function avpriv_get_trc_function_from_trc(enum AVColorTransferCharacteristic trc) -{ - avpriv_trc_function func = NULL; - switch (trc) { - case AVCOL_TRC_BT709: - case AVCOL_TRC_SMPTE170M: - case AVCOL_TRC_BT2020_10: - case AVCOL_TRC_BT2020_12: - func = avpriv_trc_bt709; - break; - - case AVCOL_TRC_GAMMA22: - func = avpriv_trc_gamma22; - break; - case AVCOL_TRC_GAMMA28: - func = avpriv_trc_gamma28; - break; - - case AVCOL_TRC_SMPTE240M: - func = avpriv_trc_smpte240M; - break; - - case AVCOL_TRC_LINEAR: - func = avpriv_trc_linear; - break; - - case AVCOL_TRC_LOG: - func = avpriv_trc_log; - break; - - case AVCOL_TRC_LOG_SQRT: - func = avpriv_trc_log_sqrt; - break; - - case AVCOL_TRC_IEC61966_2_4: - func = avpriv_trc_iec61966_2_4; - break; - - case AVCOL_TRC_BT1361_ECG: - func = avpriv_trc_bt1361; - break; - - case AVCOL_TRC_IEC61966_2_1: - func = avpriv_trc_iec61966_2_1; - break; - - case AVCOL_TRC_SMPTEST2084: - func = avpriv_trc_smpte_st2084; - break; - - case AVCOL_TRC_SMPTEST428_1: - func = avpriv_trc_smpte_st428_1; - break; - - case AVCOL_TRC_ARIB_STD_B67: - func = avpriv_trc_arib_std_b67; - break; - - case AVCOL_TRC_RESERVED0: - case AVCOL_TRC_UNSPECIFIED: - case AVCOL_TRC_RESERVED: - default: - break; - } - return func; -} diff --git a/libavutil/color_utils.h b/libavutil/color_utils.h deleted file mode 100644 index 9529006452c..00000000000 --- a/libavutil/color_utils.h +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Copyright (c) 2015 Kevin Wheatley - * - * 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_COLOR_UTILS_H -#define AVUTIL_COLOR_UTILS_H - - -#include "libavutil/pixfmt.h" - -/** - * Determine a suitable 'gamma' value to match the supplied - * AVColorTransferCharacteristic. - * - * See Apple Technical Note TN2257 (https://developer.apple.com/library/mac/technotes/tn2257/_index.html) - * - * @return Will return an approximation to the simple gamma function matching - * the supplied Transfer Characteristic, Will return 0.0 for any - * we cannot reasonably match against. - */ -double avpriv_get_gamma_from_trc(enum AVColorTransferCharacteristic trc); - - -typedef double (*avpriv_trc_function)(double); - -/** - * Determine the function needed to apply the given - * AVColorTransferCharacteristic to linear input. - * - * The function returned should expect a nominal domain and range of [0.0-1.0] - * values outside of this range maybe valid depending on the chosen - * characteristic function. - * - * @return Will return pointer to the function matching the - * supplied Transfer Characteristic. If unspecified will - * return NULL: - */ -avpriv_trc_function avpriv_get_trc_function_from_trc(enum AVColorTransferCharacteristic trc); - -#endif diff --git a/libavutil/csp.c b/libavutil/csp.c index 98fc83c1da0..7ef822c60bc 100644 --- a/libavutil/csp.c +++ b/libavutil/csp.c @@ -1,5 +1,8 @@ /* + * Copyright (c) 2015 Kevin Wheatley * Copyright (c) 2016 Ronald S. Bultje + * Copyright (c) 2023 Leo Izen + * * This file is part of FFmpeg. * * FFmpeg is free software; you can redistribute it and/or @@ -21,9 +24,11 @@ * @file Colorspace functions for libavutil * @author Ronald S. Bultje * @author Leo Izen + * @author Kevin Wheatley */ #include +#include #include "attributes.h" #include "csp.h" @@ -126,3 +131,170 @@ enum AVColorPrimaries av_csp_primaries_id_from_desc(const AVColorPrimariesDesc * return AVCOL_PRI_UNSPECIFIED; } + +static const double approximate_gamma[AVCOL_TRC_NB] = { + [AVCOL_TRC_BT709] = 1.961, + [AVCOL_TRC_SMPTE170M] = 1.961, + [AVCOL_TRC_SMPTE240M] = 1.961, + [AVCOL_TRC_BT1361_ECG] = 1.961, + [AVCOL_TRC_BT2020_10] = 1.961, + [AVCOL_TRC_BT2020_12] = 1.961, + [AVCOL_TRC_GAMMA22] = 2.2, + [AVCOL_TRC_IEC61966_2_1] = 2.2, + [AVCOL_TRC_GAMMA28] = 2.8, + [AVCOL_TRC_LINEAR] = 1.0, + [AVCOL_TRC_SMPTE428] = 2.6, +}; + +double av_csp_approximate_trc_gamma(enum AVColorTransferCharacteristic trc) +{ + double gamma; + if (trc >= AVCOL_TRC_NB) + return 0.0; + gamma = approximate_gamma[trc]; + if (gamma > 0) + return gamma; + return 0.0; +} + +#define BT709_alpha 1.099296826809442 +#define BT709_beta 0.018053968510807 + +static double trc_bt709(double Lc) +{ + const double a = BT709_alpha; + const double b = BT709_beta; + + return (0.0 > Lc) ? 0.0 + : ( b > Lc) ? 4.500 * Lc + : a * pow(Lc, 0.45) - (a - 1.0); +} + +static double trc_gamma22(double Lc) +{ + return (0.0 > Lc) ? 0.0 : pow(Lc, 1.0/ 2.2); +} + +static double trc_gamma28(double Lc) +{ + return (0.0 > Lc) ? 0.0 : pow(Lc, 1.0/ 2.8); +} + +static double trc_smpte240M(double Lc) +{ + const double a = 1.1115; + const double b = 0.0228; + + return (0.0 > Lc) ? 0.0 + : ( b > Lc) ? 4.000 * Lc + : a * pow(Lc, 0.45) - (a - 1.0); +} + +static double trc_linear(double Lc) +{ + return Lc; +} + +static double trc_log(double Lc) +{ + return (0.01 > Lc) ? 0.0 : 1.0 + log10(Lc) / 2.0; +} + +static double trc_log_sqrt(double Lc) +{ + // sqrt(10) / 1000 + return (0.00316227766 > Lc) ? 0.0 : 1.0 + log10(Lc) / 2.5; +} + +static double trc_iec61966_2_4(double Lc) +{ + const double a = BT709_alpha; + const double b = BT709_beta; + + return (-b >= Lc) ? -a * pow(-Lc, 0.45) + (a - 1.0) + : ( b > Lc) ? 4.500 * Lc + : a * pow( Lc, 0.45) - (a - 1.0); +} + +static double trc_bt1361(double Lc) +{ + const double a = BT709_alpha; + const double b = BT709_beta; + + return (-0.0045 >= Lc) ? -(a * pow(-4.0 * Lc, 0.45) + (a - 1.0)) / 4.0 + : ( b > Lc) ? 4.500 * Lc + : a * pow( Lc, 0.45) - (a - 1.0); +} + +static double trc_iec61966_2_1(double Lc) +{ + const double a = 1.055; + const double b = 0.0031308; + + return (0.0 > Lc) ? 0.0 + : ( b > Lc) ? 12.92 * Lc + : a * pow(Lc, 1.0 / 2.4) - (a - 1.0); +} + +static double trc_smpte_st2084(double Lc) +{ + const double c1 = 3424.0 / 4096.0; // c3-c2 + 1 + const double c2 = 32.0 * 2413.0 / 4096.0; + const double c3 = 32.0 * 2392.0 / 4096.0; + const double m = 128.0 * 2523.0 / 4096.0; + const double n = 0.25 * 2610.0 / 4096.0; + const double L = Lc / 10000.0; + const double Ln = pow(L, n); + + return (0.0 > Lc) ? 0.0 + : pow((c1 + c2 * Ln) / (1.0 + c3 * Ln), m); + +} + +static double trc_smpte_st428_1(double Lc) +{ + return (0.0 > Lc) ? 0.0 + : pow(48.0 * Lc / 52.37, 1.0 / 2.6); +} + + +static double trc_arib_std_b67(double Lc) { + // The function uses the definition from HEVC, which assumes that the peak + // white is input level = 1. (this is equivalent to scaling E = Lc * 12 and + // using the definition from the ARIB STD-B67 spec) + const double a = 0.17883277; + const double b = 0.28466892; + const double c = 0.55991073; + return (0.0 > Lc) ? 0.0 : + (Lc <= 1.0 / 12.0 ? sqrt(3.0 * Lc) : a * log(12.0 * Lc - b) + c); +} + +static const av_csp_trc_function trc_funcs[AVCOL_TRC_NB] = { + [AVCOL_TRC_BT709] = trc_bt709, + [AVCOL_TRC_GAMMA22] = trc_gamma22, + [AVCOL_TRC_GAMMA28] = trc_gamma28, + [AVCOL_TRC_SMPTE170M] = trc_bt709, + [AVCOL_TRC_SMPTE240M] = trc_smpte240M, + [AVCOL_TRC_LINEAR] = trc_linear, + [AVCOL_TRC_LOG] = trc_log, + [AVCOL_TRC_LOG_SQRT] = trc_log_sqrt, + [AVCOL_TRC_IEC61966_2_4] = trc_iec61966_2_4, + [AVCOL_TRC_BT1361_ECG] = trc_bt1361, + [AVCOL_TRC_IEC61966_2_1] = trc_iec61966_2_1, + [AVCOL_TRC_BT2020_10] = trc_bt709, + [AVCOL_TRC_BT2020_12] = trc_bt709, + [AVCOL_TRC_SMPTE2084] = trc_smpte_st2084, + [AVCOL_TRC_SMPTE428] = trc_smpte_st428_1, + [AVCOL_TRC_ARIB_STD_B67] = trc_arib_std_b67, +}; + +av_csp_trc_function av_csp_trc_func_from_id(enum AVColorTransferCharacteristic trc) +{ + av_csp_trc_function func; + if (trc >= AVCOL_TRC_NB) + return NULL; + func = trc_funcs[trc]; + if (!func) + return NULL; + return func; +} diff --git a/libavutil/csp.h b/libavutil/csp.h index 18ef208adf3..73bce52bc0c 100644 --- a/libavutil/csp.h +++ b/libavutil/csp.h @@ -1,5 +1,8 @@ /* + * Copyright (c) 2015 Kevin Wheatley * Copyright (c) 2016 Ronald S. Bultje + * Copyright (c) 2023 Leo Izen + * * This file is part of FFmpeg. * * FFmpeg is free software; you can redistribute it and/or @@ -29,6 +32,7 @@ * @ingroup lavu_math_csp * @author Ronald S. Bultje * @author Leo Izen + * @author Kevin Wheatley */ /** @@ -76,6 +80,12 @@ typedef struct AVColorPrimariesDesc { AVPrimaryCoefficients prim; } AVColorPrimariesDesc; +/** + * Function pointer representing a double -> double transfer function that performs + * an EOTF transfer inversion. This function outputs linear light. + */ +typedef double (*av_csp_trc_function)(double); + /** * Retrieves the Luma coefficients necessary to construct a conversion matrix * from an enum constant describing the colorspace. @@ -104,6 +114,35 @@ const AVColorPrimariesDesc *av_csp_primaries_desc_from_id(enum AVColorPrimaries */ enum AVColorPrimaries av_csp_primaries_id_from_desc(const AVColorPrimariesDesc *prm); +/** + * Determine a suitable 'gamma' value to match the supplied + * AVColorTransferCharacteristic. + * + * See Apple Technical Note TN2257 (https://developer.apple.com/library/mac/technotes/tn2257/_index.html) + * + * This function returns the gamma exponent for the OETF. For example, sRGB is approximated + * by gamma 2.2, not by gamma 0.45455. + * + * @return Will return an approximation to the simple gamma function matching + * the supplied Transfer Characteristic, Will return 0.0 for any + * we cannot reasonably match against. + */ +double av_csp_approximate_trc_gamma(enum AVColorTransferCharacteristic trc); + +/** + * Determine the function needed to apply the given + * AVColorTransferCharacteristic to linear input. + * + * The function returned should expect a nominal domain and range of [0.0-1.0] + * values outside of this range maybe valid depending on the chosen + * characteristic function. + * + * @return Will return pointer to the function matching the + * supplied Transfer Characteristic. If unspecified will + * return NULL: + */ +av_csp_trc_function av_csp_trc_func_from_id(enum AVColorTransferCharacteristic trc); + /** * @} */ diff --git a/libavutil/tests/color_utils.c b/libavutil/tests/color_utils.c index 4bdc550330e..95fb3c1d560 100644 --- a/libavutil/tests/color_utils.c +++ b/libavutil/tests/color_utils.c @@ -19,7 +19,7 @@ */ #include -#include "libavutil/color_utils.c" +#include "libavutil/csp.h" #include "libavutil/macros.h" int main(int argc, char *argv[]) @@ -32,7 +32,7 @@ int main(int argc, char *argv[]) }; for(i = 0; i < AVCOL_TRC_NB; i++) { - avpriv_trc_function func = avpriv_get_trc_function_from_trc(i); + av_csp_trc_function func = av_csp_trc_func_from_id(i); for(j = 0; j < FF_ARRAY_ELEMS(test_data); j++) { if(func != NULL) { double result = func(test_data[j]); From 0a95e4af998e2ff096331ee338a4d6caf490394c Mon Sep 17 00:00:00 2001 From: James Almer Date: Thu, 12 Jan 2023 08:53:51 -0300 Subject: [PATCH 0214/2172] avutil/version: postpone the remaining API deprecations They are too recent. Signed-off-by: James Almer --- fftools/ffprobe.c | 2 +- libavutil/version.h | 12 ++++++------ 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/fftools/ffprobe.c b/fftools/ffprobe.c index 06013fd6faf..f5ac5c1554d 100644 --- a/fftools/ffprobe.c +++ b/fftools/ffprobe.c @@ -2589,7 +2589,7 @@ static void show_frame(WriterContext *w, AVFrame *frame, AVStream *stream, print_time("pkt_dts_time", frame->pkt_dts, &stream->time_base); print_ts ("best_effort_timestamp", frame->best_effort_timestamp); print_time("best_effort_timestamp_time", frame->best_effort_timestamp, &stream->time_base); -#if LIBAVUTIL_VERSION_MAJOR < 58 +#if LIBAVUTIL_VERSION_MAJOR < 59 AV_NOWARN_DEPRECATED( print_duration_ts ("pkt_duration", frame->pkt_duration); print_duration_time("pkt_duration_time", frame->pkt_duration, &stream->time_base); diff --git a/libavutil/version.h b/libavutil/version.h index 40dc9f241ff..c20627c47a0 100644 --- a/libavutil/version.h +++ b/libavutil/version.h @@ -105,12 +105,12 @@ * @{ */ -#define FF_API_FIFO_PEEK2 (LIBAVUTIL_VERSION_MAJOR < 58) -#define FF_API_FIFO_OLD_API (LIBAVUTIL_VERSION_MAJOR < 58) -#define FF_API_XVMC (LIBAVUTIL_VERSION_MAJOR < 58) -#define FF_API_OLD_CHANNEL_LAYOUT (LIBAVUTIL_VERSION_MAJOR < 58) -#define FF_API_AV_FOPEN_UTF8 (LIBAVUTIL_VERSION_MAJOR < 58) -#define FF_API_PKT_DURATION (LIBAVUTIL_VERSION_MAJOR < 58) +#define FF_API_FIFO_PEEK2 (LIBAVUTIL_VERSION_MAJOR < 59) +#define FF_API_FIFO_OLD_API (LIBAVUTIL_VERSION_MAJOR < 59) +#define FF_API_XVMC (LIBAVUTIL_VERSION_MAJOR < 59) +#define FF_API_OLD_CHANNEL_LAYOUT (LIBAVUTIL_VERSION_MAJOR < 59) +#define FF_API_AV_FOPEN_UTF8 (LIBAVUTIL_VERSION_MAJOR < 59) +#define FF_API_PKT_DURATION (LIBAVUTIL_VERSION_MAJOR < 59) #define FF_API_REORDERED_OPAQUE (LIBAVUTIL_VERSION_MAJOR < 59) /** From 1135ad0f26305b534fc7ad7239a942c35b2165c6 Mon Sep 17 00:00:00 2001 From: James Almer Date: Thu, 12 Jan 2023 08:55:01 -0300 Subject: [PATCH 0215/2172] avcodec/version: postpone the remaining API deprecations They are either too recent, or still need work like FF_API_INIT_PACKET. Signed-off-by: James Almer --- libavcodec/version_major.h | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/libavcodec/version_major.h b/libavcodec/version_major.h index 46739ad1e40..2dd39234f10 100644 --- a/libavcodec/version_major.h +++ b/libavcodec/version_major.h @@ -37,13 +37,13 @@ * at once through the bump. This improves the git bisect-ability of the change. */ -#define FF_API_INIT_PACKET (LIBAVCODEC_VERSION_MAJOR < 60) -#define FF_API_IDCT_NONE (LIBAVCODEC_VERSION_MAJOR < 60) -#define FF_API_SVTAV1_OPTS (LIBAVCODEC_VERSION_MAJOR < 60) -#define FF_API_AYUV_CODECID (LIBAVCODEC_VERSION_MAJOR < 60) -#define FF_API_VT_OUTPUT_CALLBACK (LIBAVCODEC_VERSION_MAJOR < 60) -#define FF_API_VT_HWACCEL_CONTEXT (LIBAVCODEC_VERSION_MAJOR < 60) -#define FF_API_AVCODEC_CHROMA_POS (LIBAVCODEC_VERSION_MAJOR < 60) +#define FF_API_INIT_PACKET (LIBAVCODEC_VERSION_MAJOR < 61) +#define FF_API_IDCT_NONE (LIBAVCODEC_VERSION_MAJOR < 61) +#define FF_API_SVTAV1_OPTS (LIBAVCODEC_VERSION_MAJOR < 61) +#define FF_API_AYUV_CODECID (LIBAVCODEC_VERSION_MAJOR < 61) +#define FF_API_VT_OUTPUT_CALLBACK (LIBAVCODEC_VERSION_MAJOR < 61) +#define FF_API_AVCODEC_CHROMA_POS (LIBAVCODEC_VERSION_MAJOR < 61) +#define FF_API_VT_HWACCEL_CONTEXT (LIBAVCODEC_VERSION_MAJOR < 61) // reminder to remove CrystalHD decoders on next major bump #define FF_CODEC_CRYSTAL_HD (LIBAVCODEC_VERSION_MAJOR < 61) From c52b1c283e30c0985cf062248eb1dd8fb0485966 Mon Sep 17 00:00:00 2001 From: James Almer Date: Thu, 12 Jan 2023 08:55:32 -0300 Subject: [PATCH 0216/2172] avformat/version: postpone the remaining API deprecations They are either too recent, or still need work like FF_API_COMPUTE_PKT_FIELDS2. Signed-off-by: James Almer --- libavformat/version_major.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/libavformat/version_major.h b/libavformat/version_major.h index 1db8e7600eb..b11f8113838 100644 --- a/libavformat/version_major.h +++ b/libavformat/version_major.h @@ -41,9 +41,9 @@ * at once through the bump. This improves the git bisect-ability of the change. * */ -#define FF_API_COMPUTE_PKT_FIELDS2 (LIBAVFORMAT_VERSION_MAJOR < 60) -#define FF_API_GET_END_PTS (LIBAVFORMAT_VERSION_MAJOR < 60) -#define FF_API_AVIODIRCONTEXT (LIBAVFORMAT_VERSION_MAJOR < 60) +#define FF_API_COMPUTE_PKT_FIELDS2 (LIBAVFORMAT_VERSION_MAJOR < 61) +#define FF_API_GET_END_PTS (LIBAVFORMAT_VERSION_MAJOR < 61) +#define FF_API_AVIODIRCONTEXT (LIBAVFORMAT_VERSION_MAJOR < 61) #define FF_API_R_FRAME_RATE 1 From 5bad4856035ca5ed571e9d7d9b1d503a5c9ef0a5 Mon Sep 17 00:00:00 2001 From: James Almer Date: Thu, 12 Jan 2023 09:20:34 -0300 Subject: [PATCH 0217/2172] Bump major versions of all libraries Signed-off-by: James Almer --- doc/APIchanges | 14 +------------- libavcodec/version.h | 2 +- libavcodec/version_major.h | 2 +- libavdevice/version.h | 4 ++-- libavdevice/version_major.h | 2 +- libavfilter/version.h | 2 +- libavfilter/version_major.h | 2 +- libavformat/version.h | 2 +- libavformat/version_major.h | 2 +- libavutil/version.h | 4 ++-- libpostproc/version.h | 2 +- libpostproc/version_major.h | 2 +- libswscale/version.h | 4 ++-- libswscale/version_major.h | 2 +- 14 files changed, 17 insertions(+), 29 deletions(-) diff --git a/doc/APIchanges b/doc/APIchanges index f38bc0baeac..810b8c07468 100644 --- a/doc/APIchanges +++ b/doc/APIchanges @@ -1,16 +1,4 @@ -Never assume the API of libav* to be stable unless at least 1 month has passed -since the last major version increase or the API was added. - -The last version increases were: -libavcodec: 2021-04-27 -libavdevice: 2021-04-27 -libavfilter: 2021-04-27 -libavformat: 2021-04-27 -libpostproc: 2021-04-27 -libswresample: 2021-04-27 -libswscale: 2021-04-27 -libavutil: 2021-04-27 - +The last version increases of all libraries were on 2023-02-09 API changes, most recent first: diff --git a/libavcodec/version.h b/libavcodec/version.h index a80dc4776d6..8c3d476003e 100644 --- a/libavcodec/version.h +++ b/libavcodec/version.h @@ -29,7 +29,7 @@ #include "version_major.h" -#define LIBAVCODEC_VERSION_MINOR 63 +#define LIBAVCODEC_VERSION_MINOR 0 #define LIBAVCODEC_VERSION_MICRO 100 #define LIBAVCODEC_VERSION_INT AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \ diff --git a/libavcodec/version_major.h b/libavcodec/version_major.h index 2dd39234f10..ae7cba45f31 100644 --- a/libavcodec/version_major.h +++ b/libavcodec/version_major.h @@ -25,7 +25,7 @@ * Libavcodec version macros. */ -#define LIBAVCODEC_VERSION_MAJOR 59 +#define LIBAVCODEC_VERSION_MAJOR 60 /** * FF_API_* defines may be placed below to indicate public API that will be diff --git a/libavdevice/version.h b/libavdevice/version.h index 3e654fff892..25befdead12 100644 --- a/libavdevice/version.h +++ b/libavdevice/version.h @@ -29,8 +29,8 @@ #include "version_major.h" -#define LIBAVDEVICE_VERSION_MINOR 8 -#define LIBAVDEVICE_VERSION_MICRO 101 +#define LIBAVDEVICE_VERSION_MINOR 0 +#define LIBAVDEVICE_VERSION_MICRO 100 #define LIBAVDEVICE_VERSION_INT AV_VERSION_INT(LIBAVDEVICE_VERSION_MAJOR, \ LIBAVDEVICE_VERSION_MINOR, \ diff --git a/libavdevice/version_major.h b/libavdevice/version_major.h index 571257f31d7..b884fd42246 100644 --- a/libavdevice/version_major.h +++ b/libavdevice/version_major.h @@ -25,7 +25,7 @@ * Libavdevice version macros */ -#define LIBAVDEVICE_VERSION_MAJOR 59 +#define LIBAVDEVICE_VERSION_MAJOR 60 /** * FF_API_* defines may be placed below to indicate public API that will be diff --git a/libavfilter/version.h b/libavfilter/version.h index 057ab634157..d5a6bc143a9 100644 --- a/libavfilter/version.h +++ b/libavfilter/version.h @@ -31,7 +31,7 @@ #include "version_major.h" -#define LIBAVFILTER_VERSION_MINOR 56 +#define LIBAVFILTER_VERSION_MINOR 0 #define LIBAVFILTER_VERSION_MICRO 100 diff --git a/libavfilter/version_major.h b/libavfilter/version_major.h index cb2238ffdd0..899dfdb27db 100644 --- a/libavfilter/version_major.h +++ b/libavfilter/version_major.h @@ -27,7 +27,7 @@ * Libavfilter version macros */ -#define LIBAVFILTER_VERSION_MAJOR 8 +#define LIBAVFILTER_VERSION_MAJOR 9 /** * FF_API_* defines may be placed below to indicate public API that will be diff --git a/libavformat/version.h b/libavformat/version.h index 134cdb2b899..752aac16f7b 100644 --- a/libavformat/version.h +++ b/libavformat/version.h @@ -31,7 +31,7 @@ #include "version_major.h" -#define LIBAVFORMAT_VERSION_MINOR 38 +#define LIBAVFORMAT_VERSION_MINOR 0 #define LIBAVFORMAT_VERSION_MICRO 100 #define LIBAVFORMAT_VERSION_INT AV_VERSION_INT(LIBAVFORMAT_VERSION_MAJOR, \ diff --git a/libavformat/version_major.h b/libavformat/version_major.h index b11f8113838..9ccf40bdc17 100644 --- a/libavformat/version_major.h +++ b/libavformat/version_major.h @@ -29,7 +29,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_MAJOR 60 /** * FF_API_* defines may be placed below to indicate public API that will be diff --git a/libavutil/version.h b/libavutil/version.h index c20627c47a0..3ad38110c1a 100644 --- a/libavutil/version.h +++ b/libavutil/version.h @@ -78,8 +78,8 @@ * @{ */ -#define LIBAVUTIL_VERSION_MAJOR 57 -#define LIBAVUTIL_VERSION_MINOR 44 +#define LIBAVUTIL_VERSION_MAJOR 58 +#define LIBAVUTIL_VERSION_MINOR 0 #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 c258957d4d0..bcbdd210c4f 100644 --- a/libpostproc/version.h +++ b/libpostproc/version.h @@ -30,7 +30,7 @@ #include "version_major.h" -#define LIBPOSTPROC_VERSION_MINOR 7 +#define LIBPOSTPROC_VERSION_MINOR 0 #define LIBPOSTPROC_VERSION_MICRO 100 #define LIBPOSTPROC_VERSION_INT AV_VERSION_INT(LIBPOSTPROC_VERSION_MAJOR, \ diff --git a/libpostproc/version_major.h b/libpostproc/version_major.h index 7afc4dbb72f..771e17a9e7c 100644 --- a/libpostproc/version_major.h +++ b/libpostproc/version_major.h @@ -26,6 +26,6 @@ * Libpostproc version macros */ -#define LIBPOSTPROC_VERSION_MAJOR 56 +#define LIBPOSTPROC_VERSION_MAJOR 57 #endif /* POSTPROC_VERSION_MAJOR_H */ diff --git a/libswscale/version.h b/libswscale/version.h index 9bb3b171a73..148efd83eb5 100644 --- a/libswscale/version.h +++ b/libswscale/version.h @@ -28,8 +28,8 @@ #include "version_major.h" -#define LIBSWSCALE_VERSION_MINOR 8 -#define LIBSWSCALE_VERSION_MICRO 112 +#define LIBSWSCALE_VERSION_MINOR 0 +#define LIBSWSCALE_VERSION_MICRO 100 #define LIBSWSCALE_VERSION_INT AV_VERSION_INT(LIBSWSCALE_VERSION_MAJOR, \ LIBSWSCALE_VERSION_MINOR, \ diff --git a/libswscale/version_major.h b/libswscale/version_major.h index 2f8418780cd..88577a2b42a 100644 --- a/libswscale/version_major.h +++ b/libswscale/version_major.h @@ -24,7 +24,7 @@ * swscale version macros */ -#define LIBSWSCALE_VERSION_MAJOR 6 +#define LIBSWSCALE_VERSION_MAJOR 7 /** * FF_API_* defines may be placed below to indicate public API that will be From 8ed1d6b5e409c2a92a6920b42caff5ea89b66dfb Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Thu, 9 Feb 2023 11:32:19 +0100 Subject: [PATCH 0218/2172] avformat/wavarc: demux only data chunk content --- libavformat/Makefile | 2 +- libavformat/wavarc.c | 30 +++++++++++++++++++++++++----- 2 files changed, 26 insertions(+), 6 deletions(-) diff --git a/libavformat/Makefile b/libavformat/Makefile index d68b78ce340..5d219afc062 100644 --- a/libavformat/Makefile +++ b/libavformat/Makefile @@ -598,7 +598,7 @@ OBJS-$(CONFIG_VQF_DEMUXER) += vqf.o OBJS-$(CONFIG_W64_DEMUXER) += wavdec.o w64.o pcm.o OBJS-$(CONFIG_W64_MUXER) += wavenc.o w64.o OBJS-$(CONFIG_WADY_DEMUXER) += wady.o pcm.o -OBJS-$(CONFIG_WAVARC_DEMUXER) += wavarc.o rawdec.o +OBJS-$(CONFIG_WAVARC_DEMUXER) += wavarc.o OBJS-$(CONFIG_WAV_DEMUXER) += wavdec.o pcm.o OBJS-$(CONFIG_WAV_MUXER) += wavenc.o OBJS-$(CONFIG_WC3_DEMUXER) += wc3movie.o diff --git a/libavformat/wavarc.c b/libavformat/wavarc.c index 7b38995af9b..208b7237160 100644 --- a/libavformat/wavarc.c +++ b/libavformat/wavarc.c @@ -24,7 +24,10 @@ #include "avformat.h" #include "demux.h" #include "internal.h" -#include "rawdec.h" + +typedef struct WavArcContext { + int64_t data_end; +} WavArcContext; static int wavarc_probe(const AVProbeData *p) { @@ -51,6 +54,7 @@ static int wavarc_probe(const AVProbeData *p) static int wavarc_read_header(AVFormatContext *s) { + WavArcContext *w = s->priv_data; AVIOContext *pb = s->pb; AVCodecParameters *par; int filename_len, fmt_len, ret; @@ -91,7 +95,8 @@ static int wavarc_read_header(AVFormatContext *s) if (id != MKTAG('d','a','t','a')) avio_skip(pb, avio_rl32(pb)); } while (id != MKTAG('d','a','t','a') && !avio_feof(pb)); - avio_skip(pb, 4); + w->data_end = avio_rl32(pb); + w->data_end += avio_tell(pb); if (AV_RL32(par->extradata + 16) != MKTAG('R','I','F','F')) return AVERROR_INVALIDDATA; @@ -108,15 +113,30 @@ static int wavarc_read_header(AVFormatContext *s) return 0; } +static int wavarc_read_packet(AVFormatContext *s, AVPacket *pkt) +{ + WavArcContext *w = s->priv_data; + AVIOContext *pb = s->pb; + int64_t size, left = w->data_end - avio_tell(pb); + int ret; + + size = FFMIN(left, 1024); + if (size <= 0) + return AVERROR_EOF; + + ret = av_get_packet(pb, pkt, size); + pkt->stream_index = 0; + return ret; +} + const AVInputFormat ff_wavarc_demuxer = { .name = "wavarc", .long_name = NULL_IF_CONFIG_SMALL("Waveform Archiver"), + .priv_data_size = sizeof(WavArcContext), .read_probe = wavarc_probe, - .read_packet = ff_raw_read_partial_packet, + .read_packet = wavarc_read_packet, .flags = AVFMT_NOBINSEARCH | AVFMT_NOGENSEARCH | AVFMT_NO_BYTE_SEEK | AVFMT_NOTIMESTAMPS, .read_header = wavarc_read_header, .extensions = "wa", .raw_codec_id = AV_CODEC_ID_WAVARC, - .priv_data_size = sizeof(FFRawDemuxerContext), - .priv_class = &ff_raw_demuxer_class, }; From b40856c905712da6d38b70766a4eb833dcc34839 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Thu, 9 Feb 2023 16:51:30 +0100 Subject: [PATCH 0219/2172] fftools/ffmpeg_mux: distinguish between sync queue and muxer EOF Individual streams should be terminated in the former case, the whole muxing process in the latter. Reported-by: Gyan Doshi --- fftools/ffmpeg_mux.c | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/fftools/ffmpeg_mux.c b/fftools/ffmpeg_mux.c index dffc1410c85..cf580519495 100644 --- a/fftools/ffmpeg_mux.c +++ b/fftools/ffmpeg_mux.c @@ -159,14 +159,18 @@ static int write_packet(Muxer *mux, OutputStream *ost, AVPacket *pkt) return ret; } -static int sync_queue_process(Muxer *mux, OutputStream *ost, AVPacket *pkt) +static int sync_queue_process(Muxer *mux, OutputStream *ost, AVPacket *pkt, int *stream_eof) { OutputFile *of = &mux->of; if (ost->sq_idx_mux >= 0) { int ret = sq_send(mux->sq_mux, ost->sq_idx_mux, SQPKT(pkt)); - if (ret < 0) + if (ret < 0) { + if (ret == AVERROR_EOF) + *stream_eof = 1; + return ret; + } while (1) { ret = sq_receive(mux->sq_mux, -1, SQPKT(mux->sq_pkt)); @@ -208,7 +212,7 @@ static void *muxer_thread(void *arg) while (1) { OutputStream *ost; - int stream_idx; + int stream_idx, stream_eof = 0; ret = tq_receive(mux->tq, &stream_idx, pkt); if (stream_idx < 0) { @@ -218,9 +222,9 @@ static void *muxer_thread(void *arg) } ost = of->streams[stream_idx]; - ret = sync_queue_process(mux, ost, ret < 0 ? NULL : pkt); + ret = sync_queue_process(mux, ost, ret < 0 ? NULL : pkt, &stream_eof); av_packet_unref(pkt); - if (ret == AVERROR_EOF) + if (ret == AVERROR_EOF && stream_eof) tq_receive_finish(mux->tq, stream_idx); else if (ret < 0) { av_log(mux, AV_LOG_ERROR, "Error muxing a packet\n"); From 2c4dcbd66be6427b8c91afbff63a77fbce5123b7 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Thu, 9 Feb 2023 15:12:03 +0100 Subject: [PATCH 0220/2172] fftools/ffmpeg: rename -enc_stats* to -stats_enc* This is consistent with -stats_mux* As the options were added very recently, this should not break any users. --- Changelog | 2 +- doc/ffmpeg.texi | 20 ++++++++++---------- fftools/ffmpeg_opt.c | 12 ++++++------ 3 files changed, 17 insertions(+), 17 deletions(-) diff --git a/Changelog b/Changelog index bd9fe9922d4..11dfd7ef730 100644 --- a/Changelog +++ b/Changelog @@ -32,7 +32,7 @@ version : - WADY DPCM decoder and demuxer - CBD2 DPCM decoder - ssim360 video filter -- ffmpeg CLI new options: -enc_stats_pre[_fmt], -enc_stats_post[_fmt], +- ffmpeg CLI new options: -stats_enc_pre[_fmt], -stats_enc_post[_fmt], -stats_mux_pre[_fmt] - hstack_vaapi, vstack_vaapi and xstack_vaapi filters - XMD ADPCM decoder and demuxer diff --git a/doc/ffmpeg.texi b/doc/ffmpeg.texi index 076956d1283..d9d4b75567c 100644 --- a/doc/ffmpeg.texi +++ b/doc/ffmpeg.texi @@ -2061,30 +2061,30 @@ 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. -@item -enc_stats_pre[:@var{stream_specifier}] @var{path} (@emph{output,per-stream}) -@item -enc_stats_post[:@var{stream_specifier}] @var{path} (@emph{output,per-stream}) +@item -stats_enc_pre[:@var{stream_specifier}] @var{path} (@emph{output,per-stream}) +@item -stats_enc_post[:@var{stream_specifier}] @var{path} (@emph{output,per-stream}) @item -stats_mux_pre[:@var{stream_specifier}] @var{path} (@emph{output,per-stream}) Write per-frame encoding information about the matching streams into the file given by @var{path}. -@option{-enc_stats_pre} writes information about raw video or audio frames right -before they are sent for encoding, while @option{-enc_stats_post} writes +@option{-stats_enc_pre} writes information about raw video or audio frames right +before they are sent for encoding, while @option{-stats_enc_post} writes information about encoded packets as they are received from the encoder. @option{-stats_mux_pre} writes information about packets just as they are about to be sent to the muxer. Every frame or packet produces one line in the specified -file. The format of this line is controlled by @option{-enc_stats_pre_fmt} / -@option{-enc_stats_post_fmt} / @option{-stats_mux_pre_fmt}. +file. The format of this line is controlled by @option{-stats_enc_pre_fmt} / +@option{-stats_enc_post_fmt} / @option{-stats_mux_pre_fmt}. When stats for multiple streams are written into a single file, the lines corresponding to different streams will be interleaved. The precise order of this interleaving is not specified and not guaranteed to remain stable between different invocations of the program, even with the same options. -@item -enc_stats_pre_fmt[:@var{stream_specifier}] @var{format_spec} (@emph{output,per-stream}) -@item -enc_stats_post_fmt[:@var{stream_specifier}] @var{format_spec} (@emph{output,per-stream}) +@item -stats_enc_pre_fmt[:@var{stream_specifier}] @var{format_spec} (@emph{output,per-stream}) +@item -stats_enc_post_fmt[:@var{stream_specifier}] @var{format_spec} (@emph{output,per-stream}) @item -stats_mux_pre_fmt[:@var{stream_specifier}] @var{format_spec} (@emph{output,per-stream}) -Specify the format for the lines written with @option{-enc_stats_pre} / -@option{-enc_stats_post} / @option{-stats_mux_pre}. +Specify the format for the lines written with @option{-stats_enc_pre} / +@option{-stats_enc_post} / @option{-stats_mux_pre}. @var{format_spec} is a string that may contain directives of the form @var{@{fmt@}}. @var{format_spec} is backslash-escaped --- use \@{, \@}, and \\ diff --git a/fftools/ffmpeg_opt.c b/fftools/ffmpeg_opt.c index ed7ee6ab7d1..055275d8139 100644 --- a/fftools/ffmpeg_opt.c +++ b/fftools/ffmpeg_opt.c @@ -1544,16 +1544,16 @@ const OptionDef options[] = { { .off = OFFSET(bits_per_raw_sample) }, "set the number of bits per raw sample", "number" }, - { "enc_stats_pre", HAS_ARG | OPT_SPEC | OPT_EXPERT | OPT_OUTPUT | OPT_STRING, { .off = OFFSET(enc_stats_pre) }, + { "stats_enc_pre", HAS_ARG | OPT_SPEC | OPT_EXPERT | OPT_OUTPUT | OPT_STRING, { .off = OFFSET(enc_stats_pre) }, "write encoding stats before encoding" }, - { "enc_stats_post", HAS_ARG | OPT_SPEC | OPT_EXPERT | OPT_OUTPUT | OPT_STRING, { .off = OFFSET(enc_stats_post) }, + { "stats_enc_post", HAS_ARG | OPT_SPEC | OPT_EXPERT | OPT_OUTPUT | OPT_STRING, { .off = OFFSET(enc_stats_post) }, "write encoding stats after encoding" }, { "stats_mux_pre", HAS_ARG | OPT_SPEC | OPT_EXPERT | OPT_OUTPUT | OPT_STRING, { .off = OFFSET(mux_stats) }, "write packets stats before muxing" }, - { "enc_stats_pre_fmt", HAS_ARG | OPT_SPEC | OPT_EXPERT | OPT_OUTPUT | OPT_STRING, { .off = OFFSET(enc_stats_pre_fmt) }, - "format of the stats written with -enc_stats_pre" }, - { "enc_stats_post_fmt", HAS_ARG | OPT_SPEC | OPT_EXPERT | OPT_OUTPUT | OPT_STRING, { .off = OFFSET(enc_stats_post_fmt) }, - "format of the stats written with -enc_stats_post" }, + { "stats_enc_pre_fmt", HAS_ARG | OPT_SPEC | OPT_EXPERT | OPT_OUTPUT | OPT_STRING, { .off = OFFSET(enc_stats_pre_fmt) }, + "format of the stats written with -stats_enc_pre" }, + { "stats_enc_post_fmt", HAS_ARG | OPT_SPEC | OPT_EXPERT | OPT_OUTPUT | OPT_STRING, { .off = OFFSET(enc_stats_post_fmt) }, + "format of the stats written with -stats_enc_post" }, { "stats_mux_pre_fmt", HAS_ARG | OPT_SPEC | OPT_EXPERT | OPT_OUTPUT | OPT_STRING, { .off = OFFSET(mux_stats_fmt) }, "format of the stats written with -stats_mux_pre" }, From acd87d41f29bce3283798c10dccf6b00090b0d2d Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Thu, 19 Jan 2023 00:25:36 +0100 Subject: [PATCH 0221/2172] avfilter/vf_exposure: reduce copy operations --- libavfilter/vf_exposure.c | 62 +++++++++++++++++++++++++++++++-------- 1 file changed, 49 insertions(+), 13 deletions(-) diff --git a/libavfilter/vf_exposure.c b/libavfilter/vf_exposure.c index bbe951967be..ff2f1565341 100644 --- a/libavfilter/vf_exposure.c +++ b/libavfilter/vf_exposure.c @@ -38,43 +38,80 @@ typedef struct ExposureContext { int jobnr, int nb_jobs); } ExposureContext; +typedef struct ThreadData { + AVFrame *out, *in; +} ThreadData; + static int exposure_slice(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) { ExposureContext *s = ctx->priv; - AVFrame *frame = arg; - const int width = frame->width; - const int height = frame->height; + ThreadData *td = arg; + const int width = td->out->width; + const int height = td->out->height; const int slice_start = (height * jobnr) / nb_jobs; const int slice_end = (height * (jobnr + 1)) / nb_jobs; const float black = s->black; const float scale = s->scale; for (int p = 0; p < 3; p++) { - const int linesize = frame->linesize[p] / 4; - float *ptr = (float *)frame->data[p] + slice_start * linesize; + const int slinesize = td->in->linesize[p] / 4; + const int dlinesize = td->out->linesize[p] / 4; + const float *src = (const float *)td->in->data[p] + slice_start * slinesize; + float *ptr = (float *)td->out->data[p] + slice_start * dlinesize; for (int y = slice_start; y < slice_end; y++) { for (int x = 0; x < width; x++) - ptr[x] = (ptr[x] - black) * scale; + ptr[x] = (src[x] - black) * scale; + + ptr += dlinesize; + src += slinesize; + } + } - ptr += linesize; + if (td->in->data[3] && td->in->linesize[3] && td->in != td->out) { + const int slinesize = td->in->linesize[3] / 4; + const int dlinesize = td->out->linesize[3] / 4; + const float *src = (const float *)td->in->data[3] + slice_start * slinesize; + float *ptr = (float *)td->out->data[3] + slice_start * dlinesize; + for (int y = slice_start; y < slice_end; y++) { + memcpy(ptr, src, width * sizeof(*ptr)); + ptr += dlinesize; + src += slinesize; } } return 0; } -static int filter_frame(AVFilterLink *inlink, AVFrame *frame) +static int filter_frame(AVFilterLink *inlink, AVFrame *in) { AVFilterContext *ctx = inlink->dst; + AVFilterLink *outlink = ctx->outputs[0]; ExposureContext *s = ctx->priv; float diff = fabsf(exp2f(-s->exposure) - s->black); + 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); + } diff = diff > 0.f ? diff : 1.f / 1024.f; s->scale = 1.f / diff; - ff_filter_execute(ctx, s->do_slice, frame, NULL, - FFMIN(frame->height, ff_filter_get_nb_threads(ctx))); - - return ff_filter_frame(ctx->outputs[0], frame); + td.out = out; + td.in = in; + ff_filter_execute(ctx, s->do_slice, &td, NULL, + FFMIN(out->height, ff_filter_get_nb_threads(ctx))); + + if (out != in) + av_frame_free(&in); + return ff_filter_frame(outlink, out); } static av_cold int config_input(AVFilterLink *inlink) @@ -91,7 +128,6 @@ static const AVFilterPad exposure_inputs[] = { { .name = "default", .type = AVMEDIA_TYPE_VIDEO, - .flags = AVFILTERPAD_FLAG_NEEDS_WRITABLE, .filter_frame = filter_frame, .config_props = config_input, }, From 725328672a28d9591d2cf7564401742b12478a7e Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Thu, 19 Jan 2023 10:04:15 +0100 Subject: [PATCH 0222/2172] avfilter/vf_vibrance: reduce copy operations --- libavfilter/vf_vibrance.c | 117 +++++++++++++++++++++++++++++++------- 1 file changed, 96 insertions(+), 21 deletions(-) diff --git a/libavfilter/vf_vibrance.c b/libavfilter/vf_vibrance.c index 81ae63902cb..329b37bdc62 100644 --- a/libavfilter/vf_vibrance.c +++ b/libavfilter/vf_vibrance.c @@ -29,6 +29,7 @@ #define R 0 #define G 1 #define B 2 +#define A 3 typedef struct VibranceContext { const AVClass *class; @@ -51,10 +52,16 @@ static inline float lerpf(float v0, float v1, float f) return v0 + (v1 - v0) * f; } +typedef struct ThreadData { + AVFrame *out, *in; +} ThreadData; + static int vibrance_slice8(AVFilterContext *avctx, void *arg, int jobnr, int nb_jobs) { VibranceContext *s = avctx->priv; - AVFrame *frame = arg; + ThreadData *td = arg; + AVFrame *frame = td->out; + AVFrame *in = td->in; const int width = frame->width; const int height = frame->height; const float scale = 1.f / 255.f; @@ -74,15 +81,25 @@ static int vibrance_slice8(AVFilterContext *avctx, void *arg, int jobnr, int nb_ const int glinesize = frame->linesize[0]; const int blinesize = frame->linesize[1]; const int rlinesize = frame->linesize[2]; + const int alinesize = frame->linesize[3]; + const int gslinesize = in->linesize[0]; + const int bslinesize = in->linesize[1]; + const int rslinesize = in->linesize[2]; + const int aslinesize = in->linesize[3]; + const uint8_t *gsrc = in->data[0] + slice_start * glinesize; + const uint8_t *bsrc = in->data[1] + slice_start * blinesize; + const uint8_t *rsrc = in->data[2] + slice_start * rlinesize; uint8_t *gptr = frame->data[0] + slice_start * glinesize; uint8_t *bptr = frame->data[1] + slice_start * blinesize; uint8_t *rptr = frame->data[2] + slice_start * rlinesize; + const uint8_t *asrc = in->data[3]; + uint8_t *aptr = frame->data[3]; for (int y = slice_start; y < slice_end; y++) { for (int x = 0; x < width; x++) { - float g = gptr[x] * scale; - float b = bptr[x] * scale; - float r = rptr[x] * scale; + float g = gsrc[x] * scale; + float b = bsrc[x] * scale; + float r = rsrc[x] * scale; float max_color = FFMAX3(r, g, b); float min_color = FFMIN3(r, g, b); float color_saturation = max_color - min_color; @@ -100,6 +117,12 @@ static int vibrance_slice8(AVFilterContext *avctx, void *arg, int jobnr, int nb_ rptr[x] = av_clip_uint8(r * 255.f); } + if (aptr && alinesize && frame != in) + memcpy(aptr + alinesize * y, asrc + aslinesize * y, width); + + gsrc += gslinesize; + bsrc += bslinesize; + rsrc += rslinesize; gptr += glinesize; bptr += blinesize; rptr += rlinesize; @@ -111,7 +134,9 @@ static int vibrance_slice8(AVFilterContext *avctx, void *arg, int jobnr, int nb_ static int vibrance_slice16(AVFilterContext *avctx, void *arg, int jobnr, int nb_jobs) { VibranceContext *s = avctx->priv; - AVFrame *frame = arg; + ThreadData *td = arg; + AVFrame *frame = td->out; + AVFrame *in = td->in; const int depth = s->depth; const float max = (1 << depth) - 1; const float scale = 1.f / max; @@ -130,18 +155,28 @@ static int vibrance_slice16(AVFilterContext *avctx, void *arg, int jobnr, int nb const float srintensity = alternate * FFSIGN(rintensity); const int slice_start = (height * jobnr) / nb_jobs; const int slice_end = (height * (jobnr + 1)) / nb_jobs; + const int gslinesize = in->linesize[0] / 2; + const int bslinesize = in->linesize[1] / 2; + const int rslinesize = in->linesize[2] / 2; + const int aslinesize = in->linesize[3] / 2; const int glinesize = frame->linesize[0] / 2; const int blinesize = frame->linesize[1] / 2; const int rlinesize = frame->linesize[2] / 2; + const int alinesize = frame->linesize[3] / 2; + const uint16_t *gsrc = (const uint16_t *)in->data[0] + slice_start * gslinesize; + const uint16_t *bsrc = (const uint16_t *)in->data[1] + slice_start * bslinesize; + const uint16_t *rsrc = (const uint16_t *)in->data[2] + slice_start * rslinesize; uint16_t *gptr = (uint16_t *)frame->data[0] + slice_start * glinesize; uint16_t *bptr = (uint16_t *)frame->data[1] + slice_start * blinesize; uint16_t *rptr = (uint16_t *)frame->data[2] + slice_start * rlinesize; + const uint16_t *asrc = (const uint16_t *)in->data[3]; + uint16_t *aptr = (uint16_t *)frame->data[3]; for (int y = slice_start; y < slice_end; y++) { for (int x = 0; x < width; x++) { - float g = gptr[x] * scale; - float b = bptr[x] * scale; - float r = rptr[x] * scale; + float g = gsrc[x] * scale; + float b = bsrc[x] * scale; + float r = rsrc[x] * scale; float max_color = FFMAX3(r, g, b); float min_color = FFMIN3(r, g, b); float color_saturation = max_color - min_color; @@ -159,6 +194,12 @@ static int vibrance_slice16(AVFilterContext *avctx, void *arg, int jobnr, int nb rptr[x] = av_clip_uintp2_c(r * max, depth); } + if (aptr && alinesize && frame != in) + memcpy(aptr + alinesize * y, asrc + aslinesize * y, width * 2); + + gsrc += gslinesize; + bsrc += bslinesize; + rsrc += rslinesize; gptr += glinesize; bptr += blinesize; rptr += rlinesize; @@ -170,7 +211,9 @@ static int vibrance_slice16(AVFilterContext *avctx, void *arg, int jobnr, int nb static int vibrance_slice8p(AVFilterContext *avctx, void *arg, int jobnr, int nb_jobs) { VibranceContext *s = avctx->priv; - AVFrame *frame = arg; + ThreadData *td = arg; + AVFrame *frame = td->out; + AVFrame *in = td->in; const int step = s->step; const int width = frame->width; const int height = frame->height; @@ -181,6 +224,7 @@ static int vibrance_slice8p(AVFilterContext *avctx, void *arg, int jobnr, int nb const uint8_t roffset = s->rgba_map[R]; const uint8_t goffset = s->rgba_map[G]; const uint8_t boffset = s->rgba_map[B]; + const uint8_t aoffset = s->rgba_map[A]; const float intensity = s->intensity; const float alternate = s->alternate ? 1.f : -1.f; const float gintensity = intensity * s->balance[0]; @@ -192,13 +236,15 @@ static int vibrance_slice8p(AVFilterContext *avctx, void *arg, int jobnr, int nb const int slice_start = (height * jobnr) / nb_jobs; const int slice_end = (height * (jobnr + 1)) / nb_jobs; const int linesize = frame->linesize[0]; + const int slinesize = in->linesize[0]; + const uint8_t *src = in->data[0] + slice_start * slinesize; uint8_t *ptr = frame->data[0] + slice_start * linesize; for (int y = slice_start; y < slice_end; y++) { for (int x = 0; x < width; x++) { - float g = ptr[x * step + goffset] * scale; - float b = ptr[x * step + boffset] * scale; - float r = ptr[x * step + roffset] * scale; + float g = src[x * step + goffset] * scale; + float b = src[x * step + boffset] * scale; + float r = src[x * step + roffset] * scale; float max_color = FFMAX3(r, g, b); float min_color = FFMIN3(r, g, b); float color_saturation = max_color - min_color; @@ -214,9 +260,13 @@ static int vibrance_slice8p(AVFilterContext *avctx, void *arg, int jobnr, int nb ptr[x * step + goffset] = av_clip_uint8(g * 255.f); ptr[x * step + boffset] = av_clip_uint8(b * 255.f); ptr[x * step + roffset] = av_clip_uint8(r * 255.f); + + if (frame != in) + ptr[x * step + aoffset] = src[x * step + aoffset]; } ptr += linesize; + src += slinesize; } return 0; @@ -225,7 +275,9 @@ static int vibrance_slice8p(AVFilterContext *avctx, void *arg, int jobnr, int nb static int vibrance_slice16p(AVFilterContext *avctx, void *arg, int jobnr, int nb_jobs) { VibranceContext *s = avctx->priv; - AVFrame *frame = arg; + ThreadData *td = arg; + AVFrame *frame = td->out; + AVFrame *in = td->in; const int step = s->step; const int depth = s->depth; const float max = (1 << depth) - 1; @@ -236,6 +288,7 @@ static int vibrance_slice16p(AVFilterContext *avctx, void *arg, int jobnr, int n const uint8_t roffset = s->rgba_map[R]; const uint8_t goffset = s->rgba_map[G]; const uint8_t boffset = s->rgba_map[B]; + const uint8_t aoffset = s->rgba_map[A]; const int width = frame->width; const int height = frame->height; const float intensity = s->intensity; @@ -249,13 +302,15 @@ static int vibrance_slice16p(AVFilterContext *avctx, void *arg, int jobnr, int n const int slice_start = (height * jobnr) / nb_jobs; const int slice_end = (height * (jobnr + 1)) / nb_jobs; const int linesize = frame->linesize[0] / 2; + const int slinesize = in->linesize[0] / 2; + const uint16_t *src = (const uint16_t *)in->data[0] + slice_start * slinesize; uint16_t *ptr = (uint16_t *)frame->data[0] + slice_start * linesize; for (int y = slice_start; y < slice_end; y++) { for (int x = 0; x < width; x++) { - float g = ptr[x * step + goffset] * scale; - float b = ptr[x * step + boffset] * scale; - float r = ptr[x * step + roffset] * scale; + float g = src[x * step + goffset] * scale; + float b = src[x * step + boffset] * scale; + float r = src[x * step + roffset] * scale; float max_color = FFMAX3(r, g, b); float min_color = FFMIN3(r, g, b); float color_saturation = max_color - min_color; @@ -271,25 +326,46 @@ static int vibrance_slice16p(AVFilterContext *avctx, void *arg, int jobnr, int n ptr[x * step + goffset] = av_clip_uintp2_c(g * max, depth); ptr[x * step + boffset] = av_clip_uintp2_c(b * max, depth); ptr[x * step + roffset] = av_clip_uintp2_c(r * max, depth); + if (frame != in) + ptr[x * step + aoffset] = src[x * step + aoffset]; } ptr += linesize; + src += slinesize; } return 0; } -static int filter_frame(AVFilterLink *link, AVFrame *frame) +static int filter_frame(AVFilterLink *link, AVFrame *in) { AVFilterContext *avctx = link->dst; + AVFilterLink *outlink = avctx->outputs[0]; VibranceContext *s = avctx->priv; + ThreadData td; + AVFrame *out; int res; - if (res = ff_filter_execute(avctx, s->do_slice, frame, NULL, - FFMIN(frame->height, ff_filter_get_nb_threads(avctx)))) + 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; + if (res = ff_filter_execute(avctx, s->do_slice, &td, NULL, + FFMIN(out->height, ff_filter_get_nb_threads(avctx)))) return res; - return ff_filter_frame(avctx->outputs[0], frame); + if (out != in) + av_frame_free(&in); + return ff_filter_frame(outlink, out); } static const enum AVPixelFormat pixel_fmts[] = { @@ -335,7 +411,6 @@ static const AVFilterPad vibrance_inputs[] = { { .name = "default", .type = AVMEDIA_TYPE_VIDEO, - .flags = AVFILTERPAD_FLAG_NEEDS_WRITABLE, .filter_frame = filter_frame, .config_props = config_input, }, From 385ec464245e0d0754e897256cf4535143de8463 Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Fri, 27 Jan 2023 17:00:36 +0100 Subject: [PATCH 0223/2172] avformat: add SDNS demuxer --- Changelog | 1 + doc/general_contents.texi | 1 + libavformat/Makefile | 1 + libavformat/allformats.c | 1 + libavformat/sdns.c | 96 +++++++++++++++++++++++++++++++++++++++ libavformat/version.h | 2 +- 6 files changed, 101 insertions(+), 1 deletion(-) create mode 100644 libavformat/sdns.c diff --git a/Changelog b/Changelog index 11dfd7ef730..543eaf7fb75 100644 --- a/Changelog +++ b/Changelog @@ -40,6 +40,7 @@ version : - ffmpeg CLI new option: -fix_sub_duration_heartbeat - WavArc decoder and demuxer - CrystalHD decoders deprecated +- SDNS demuxer version 5.1: diff --git a/doc/general_contents.texi b/doc/general_contents.texi index 33f3c18c7a4..f39628de9a5 100644 --- a/doc/general_contents.texi +++ b/doc/general_contents.texi @@ -665,6 +665,7 @@ library: @item Sample Dump eXchange @tab @tab X @item SAP @tab X @tab X @item SBG @tab @tab X +@item SDNS @tab @tab X @item SDP @tab @tab X @item SER @tab @tab X @item Digital Pictures SGA @tab @tab X diff --git a/libavformat/Makefile b/libavformat/Makefile index 5d219afc062..471e014b220 100644 --- a/libavformat/Makefile +++ b/libavformat/Makefile @@ -523,6 +523,7 @@ OBJS-$(CONFIG_SBG_DEMUXER) += sbgdec.o OBJS-$(CONFIG_SCC_DEMUXER) += sccdec.o subtitles.o OBJS-$(CONFIG_SCC_MUXER) += sccenc.o OBJS-$(CONFIG_SCD_DEMUXER) += scd.o +OBJS-$(CONFIG_SDNS_DEMUXER) += sdns.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 365d7f34282..8393dd34c7d 100644 --- a/libavformat/allformats.c +++ b/libavformat/allformats.c @@ -405,6 +405,7 @@ extern const AVInputFormat ff_sbg_demuxer; extern const AVInputFormat ff_scc_demuxer; extern const FFOutputFormat ff_scc_muxer; extern const AVInputFormat ff_scd_demuxer; +extern const AVInputFormat ff_sdns_demuxer; extern const AVInputFormat ff_sdp_demuxer; extern const AVInputFormat ff_sdr2_demuxer; extern const AVInputFormat ff_sds_demuxer; diff --git a/libavformat/sdns.c b/libavformat/sdns.c new file mode 100644 index 00000000000..f00c6bcc49f --- /dev/null +++ b/libavformat/sdns.c @@ -0,0 +1,96 @@ +/* + * SDNS demuxer + * Copyright (c) 2023 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 "libavutil/channel_layout.h" +#include "libavutil/intreadwrite.h" +#include "avformat.h" +#include "demux.h" +#include "internal.h" + +static int sdns_probe(const AVProbeData *p) +{ + if (AV_RL32(p->buf) != MKTAG('S','D','N','S')) + return 0; + if (AV_RB32(p->buf + 8) <= 0) + return 0; + if (AV_RB32(p->buf + 12) <= 0 || + AV_RB32(p->buf + 12) > 128) + return 0; + return AVPROBE_SCORE_MAX / 3; +} + +static int sdns_read_header(AVFormatContext *s) +{ + AVIOContext *pb = s->pb; + AVCodecParameters *par; + int channels, ret; + AVStream *st; + + avio_skip(pb, 8); + + st = avformat_new_stream(s, NULL); + if (!st) + return AVERROR(ENOMEM); + + par = st->codecpar; + par->codec_type = AVMEDIA_TYPE_AUDIO; + par->codec_id = AV_CODEC_ID_XMA1; + par->sample_rate = avio_rb32(pb); + channels = avio_rb32(pb); + if (channels <= 0 || channels > 128) + return AVERROR_INVALIDDATA; + av_channel_layout_default(&par->ch_layout, channels); + if (par->sample_rate <= 0) + return AVERROR_INVALIDDATA; + par->block_align = 2048; + if ((ret = ff_alloc_extradata(par, 8 + 20 * ((channels + 1) / 2))) < 0) + return ret; + memset(par->extradata, 0, 28); + par->extradata[4] = (channels + 1) / 2; + for (int i = 0; i < par->extradata[4]; i++) + par->extradata[8 + 20 * i + 17] = FFMIN(2, channels - i * 2); + avpriv_set_pts_info(st, 64, 1, par->sample_rate); + avio_seek(pb, 0x1000, SEEK_SET); + + return 0; +} + +static int sdns_read_packet(AVFormatContext *s, AVPacket *pkt) +{ + int ret; + + if (avio_feof(s->pb)) + return AVERROR_EOF; + ret = av_get_packet(s->pb, pkt, 2048); + pkt->stream_index = 0; + + return ret; +} + +const AVInputFormat ff_sdns_demuxer = { + .name = "sdns", + .long_name = NULL_IF_CONFIG_SMALL("Xbox SDNS"), + .read_probe = sdns_probe, + .read_header = sdns_read_header, + .read_packet = sdns_read_packet, + .flags = AVFMT_GENERIC_INDEX, + .extensions = "sdns", +}; diff --git a/libavformat/version.h b/libavformat/version.h index 752aac16f7b..a7c80dc5647 100644 --- a/libavformat/version.h +++ b/libavformat/version.h @@ -31,7 +31,7 @@ #include "version_major.h" -#define LIBAVFORMAT_VERSION_MINOR 0 +#define LIBAVFORMAT_VERSION_MINOR 1 #define LIBAVFORMAT_VERSION_MICRO 100 #define LIBAVFORMAT_VERSION_INT AV_VERSION_INT(LIBAVFORMAT_VERSION_MAJOR, \ From 27315dc3459431b6ae158db8d27c0d58307c48b9 Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Sat, 11 Feb 2023 16:48:11 +0100 Subject: [PATCH 0224/2172] avcodec/tta: fix regression with new channel layout switch --- libavcodec/tta.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libavcodec/tta.c b/libavcodec/tta.c index e63d08bb441..3e89571f16d 100644 --- a/libavcodec/tta.c +++ b/libavcodec/tta.c @@ -160,7 +160,8 @@ static av_cold int tta_decode_init(AVCodecContext * avctx) av_channel_layout_uninit(&avctx->ch_layout); if (s->channels > 1 && s->channels < 9) { av_channel_layout_from_mask(&avctx->ch_layout, tta_channel_layouts[s->channels-2]); - } else { + } + if (avctx->ch_layout.nb_channels == 0) { avctx->ch_layout.order = AV_CHANNEL_ORDER_UNSPEC; avctx->ch_layout.nb_channels = s->channels; } From abfe8456a2948f085a8ff88715bd2e0a9afc5a1d Mon Sep 17 00:00:00 2001 From: Stefano Sabatini Date: Mon, 16 Jan 2023 01:56:56 +0100 Subject: [PATCH 0225/2172] lavfi/astats: sort measures keys by name --- libavfilter/af_astats.c | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/libavfilter/af_astats.c b/libavfilter/af_astats.c index 8755ab87520..f3f2bd743b5 100644 --- a/libavfilter/af_astats.c +++ b/libavfilter/af_astats.c @@ -119,31 +119,31 @@ static const AVOption astats_options[] = { { "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" }, + { "Bit_depth" , "", 0, AV_OPT_TYPE_CONST, {.i64=MEASURE_BIT_DEPTH }, 0, 0, FLAGS, "measure" }, + { "Crest_factor" , "", 0, AV_OPT_TYPE_CONST, {.i64=MEASURE_CREST_FACTOR }, 0, 0, FLAGS, "measure" }, { "DC_offset" , "", 0, AV_OPT_TYPE_CONST, {.i64=MEASURE_DC_OFFSET }, 0, 0, FLAGS, "measure" }, - { "Min_level" , "", 0, AV_OPT_TYPE_CONST, {.i64=MEASURE_MIN_LEVEL }, 0, 0, FLAGS, "measure" }, - { "Max_level" , "", 0, AV_OPT_TYPE_CONST, {.i64=MEASURE_MAX_LEVEL }, 0, 0, FLAGS, "measure" }, - { "Min_difference" , "", 0, AV_OPT_TYPE_CONST, {.i64=MEASURE_MIN_DIFFERENCE }, 0, 0, FLAGS, "measure" }, + { "Dynamic_range" , "", 0, AV_OPT_TYPE_CONST, {.i64=MEASURE_DYNAMIC_RANGE }, 0, 0, FLAGS, "measure" }, + { "Entropy" , "", 0, AV_OPT_TYPE_CONST, {.i64=MEASURE_ENTROPY }, 0, 0, FLAGS, "measure" }, + { "Flat_factor" , "", 0, AV_OPT_TYPE_CONST, {.i64=MEASURE_FLAT_FACTOR }, 0, 0, FLAGS, "measure" }, { "Max_difference" , "", 0, AV_OPT_TYPE_CONST, {.i64=MEASURE_MAX_DIFFERENCE }, 0, 0, FLAGS, "measure" }, + { "Max_level" , "", 0, AV_OPT_TYPE_CONST, {.i64=MEASURE_MAX_LEVEL }, 0, 0, FLAGS, "measure" }, { "Mean_difference" , "", 0, AV_OPT_TYPE_CONST, {.i64=MEASURE_MEAN_DIFFERENCE }, 0, 0, FLAGS, "measure" }, - { "RMS_difference" , "", 0, AV_OPT_TYPE_CONST, {.i64=MEASURE_RMS_DIFFERENCE }, 0, 0, FLAGS, "measure" }, + { "Min_difference" , "", 0, AV_OPT_TYPE_CONST, {.i64=MEASURE_MIN_DIFFERENCE }, 0, 0, FLAGS, "measure" }, + { "Min_level" , "", 0, AV_OPT_TYPE_CONST, {.i64=MEASURE_MIN_LEVEL }, 0, 0, FLAGS, "measure" }, + { "Noise_floor" , "", 0, AV_OPT_TYPE_CONST, {.i64=MEASURE_NOISE_FLOOR }, 0, 0, FLAGS, "measure" }, + { "Noise_floor_count" , "", 0, AV_OPT_TYPE_CONST, {.i64=MEASURE_NOISE_FLOOR_COUNT }, 0, 0, FLAGS, "measure" }, + { "Number_of_Infs" , "", 0, AV_OPT_TYPE_CONST, {.i64=MEASURE_NUMBER_OF_INFS }, 0, 0, FLAGS, "measure" }, + { "Number_of_NaNs" , "", 0, AV_OPT_TYPE_CONST, {.i64=MEASURE_NUMBER_OF_NANS }, 0, 0, FLAGS, "measure" }, + { "Number_of_denormals" , "", 0, AV_OPT_TYPE_CONST, {.i64=MEASURE_NUMBER_OF_DENORMALS }, 0, 0, FLAGS, "measure" }, + { "Number_of_samples" , "", 0, AV_OPT_TYPE_CONST, {.i64=MEASURE_NUMBER_OF_SAMPLES }, 0, 0, FLAGS, "measure" }, + { "Peak_count" , "", 0, AV_OPT_TYPE_CONST, {.i64=MEASURE_PEAK_COUNT }, 0, 0, FLAGS, "measure" }, { "Peak_level" , "", 0, AV_OPT_TYPE_CONST, {.i64=MEASURE_PEAK_LEVEL }, 0, 0, FLAGS, "measure" }, + { "RMS_difference" , "", 0, AV_OPT_TYPE_CONST, {.i64=MEASURE_RMS_DIFFERENCE }, 0, 0, FLAGS, "measure" }, { "RMS_level" , "", 0, AV_OPT_TYPE_CONST, {.i64=MEASURE_RMS_LEVEL }, 0, 0, FLAGS, "measure" }, { "RMS_peak" , "", 0, AV_OPT_TYPE_CONST, {.i64=MEASURE_RMS_PEAK }, 0, 0, FLAGS, "measure" }, { "RMS_trough" , "", 0, AV_OPT_TYPE_CONST, {.i64=MEASURE_RMS_TROUGH }, 0, 0, FLAGS, "measure" }, - { "Crest_factor" , "", 0, AV_OPT_TYPE_CONST, {.i64=MEASURE_CREST_FACTOR }, 0, 0, FLAGS, "measure" }, - { "Flat_factor" , "", 0, AV_OPT_TYPE_CONST, {.i64=MEASURE_FLAT_FACTOR }, 0, 0, FLAGS, "measure" }, - { "Peak_count" , "", 0, AV_OPT_TYPE_CONST, {.i64=MEASURE_PEAK_COUNT }, 0, 0, FLAGS, "measure" }, - { "Bit_depth" , "", 0, AV_OPT_TYPE_CONST, {.i64=MEASURE_BIT_DEPTH }, 0, 0, FLAGS, "measure" }, - { "Dynamic_range" , "", 0, AV_OPT_TYPE_CONST, {.i64=MEASURE_DYNAMIC_RANGE }, 0, 0, FLAGS, "measure" }, { "Zero_crossings" , "", 0, AV_OPT_TYPE_CONST, {.i64=MEASURE_ZERO_CROSSINGS }, 0, 0, FLAGS, "measure" }, { "Zero_crossings_rate" , "", 0, AV_OPT_TYPE_CONST, {.i64=MEASURE_ZERO_CROSSINGS_RATE }, 0, 0, FLAGS, "measure" }, - { "Noise_floor" , "", 0, AV_OPT_TYPE_CONST, {.i64=MEASURE_NOISE_FLOOR }, 0, 0, FLAGS, "measure" }, - { "Noise_floor_count" , "", 0, AV_OPT_TYPE_CONST, {.i64=MEASURE_NOISE_FLOOR_COUNT }, 0, 0, FLAGS, "measure" }, - { "Entropy" , "", 0, AV_OPT_TYPE_CONST, {.i64=MEASURE_ENTROPY }, 0, 0, FLAGS, "measure" }, - { "Number_of_samples" , "", 0, AV_OPT_TYPE_CONST, {.i64=MEASURE_NUMBER_OF_SAMPLES }, 0, 0, FLAGS, "measure" }, - { "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", "Select the parameters which are measured overall", OFFSET(measure_overall), AV_OPT_TYPE_FLAGS, {.i64=MEASURE_ALL}, 0, UINT_MAX, FLAGS, "measure" }, { NULL } }; From 2a3a36e2796a8b2ec294b1d9aa08c17e380bc2cb Mon Sep 17 00:00:00 2001 From: Stefano Sabatini Date: Mon, 16 Jan 2023 01:58:15 +0100 Subject: [PATCH 0226/2172] doc/filters/astats: sort measure entries, add missing ones Also apply minor consistency and formatting fixes. Fix trac issue: http://trac.ffmpeg.org/ticket/8397 --- doc/filters.texi | 211 ++++++++++++++++++++++++++--------------------- 1 file changed, 115 insertions(+), 96 deletions(-) diff --git a/doc/filters.texi b/doc/filters.texi index 3a54c68f3e7..4d1eae73a6d 100644 --- a/doc/filters.texi +++ b/doc/filters.texi @@ -3183,62 +3183,61 @@ where @code{X} is channel number starting from 1 or string @code{Overall}. Defau disabled. Available keys for each channel are: -DC_offset -Min_level -Max_level -Min_difference -Max_difference -Mean_difference -RMS_difference -Peak_level -RMS_peak -RMS_trough -Crest_factor -Flat_factor -Peak_count -Noise_floor -Noise_floor_count -Entropy -Bit_depth -Dynamic_range -Zero_crossings -Zero_crossings_rate -Number_of_NaNs -Number_of_Infs -Number_of_denormals - -and for Overall: -DC_offset -Min_level -Max_level -Min_difference -Max_difference -Mean_difference -RMS_difference -Peak_level -RMS_level -RMS_peak -RMS_trough -Flat_factor -Peak_count -Noise_floor -Noise_floor_count -Entropy -Bit_depth -Number_of_samples -Number_of_NaNs -Number_of_Infs -Number_of_denormals - -For example full key look like this @code{lavfi.astats.1.DC_offset} or -this @code{lavfi.astats.Overall.Peak_count}. - -For description what each key means read below. +@var{Bit_depth} +@var{Crest_factor} +@var{DC_offset} +@var{Dynamic_range} +@var{Entropy} +@var{Flat_factor} +@var{Max_difference} +@var{Max_level} +@var{Mean_difference} +@var{Min_difference} +@var{Min_level} +@var{Noise_floor} +@var{Noise_floor_count} +@var{Number_of_Infs} +@var{Number_of_NaNs} +@var{Number_of_denormals} +@var{Peak_count} +@var{Peak_level} +@var{RMS_difference} +@var{RMS_peak} +@var{RMS_trough} +@var{Zero_crossings} +@var{Zero_crossings_rate} + +and for @code{Overall}: +@var{Bit_depth} +@var{DC_offset} +@var{Entropy} +@var{Flat_factor} +@var{Max_difference} +@var{Max_level} +@var{Mean_difference} +@var{Min_difference} +@var{Min_level} +@var{Noise_floor} +@var{Noise_floor_count} +@var{Number_of_Infs} +@var{Number_of_NaNs} +@var{Number_of_denormals} +@var{Number_of_samples} +@var{Peak_count} +@var{Peak_level} +@var{RMS_difference} +@var{RMS_level} +@var{RMS_peak} +@var{RMS_trough} + +For example, a full key looks like @code{lavfi.astats.1.DC_offset} or +@code{lavfi.astats.Overall.Peak_count}. + +Read below for the description of the keys. @item reset Set the number of frames over which cumulative stats are calculated before -being reset -Default is disabled. +being reset. Default is disabled. @item measure_perchannel Select the parameters which are measured per channel. The metadata keys can @@ -3252,71 +3251,91 @@ be used as flags, default is @option{all} which measures everything. @end table -A description of each shown parameter follows: +A description of the measure keys follow: @table @option -@item DC offset -Mean amplitude displacement from zero. +@item none +no measures -@item Min level -Minimal sample level. +@item all +all measures -@item Max level -Maximal sample level. +@item Bit_depth +overall bit depth of audio, i.e. number of bits used for each sample -@item Min difference -Minimal difference between two consecutive samples. +@item Crest_factor +standard ratio of peak to RMS level (note: not in dB) -@item Max difference -Maximal difference between two consecutive samples. +@item DC_offset +mean amplitude displacement from zero -@item Mean difference -Mean difference between two consecutive samples. -The average of each difference between two consecutive samples. +@item Dynamic_range +measured dynamic range of audio in dB -@item RMS difference -Root Mean Square difference between two consecutive samples. +@item Entropy +entropy measured across whole audio, entropy of value near 1.0 is typically measured for white noise -@item Peak level dB -@item RMS level dB -Standard peak and RMS level measured in dBFS. +@item Flat_factor +flatness (i.e. consecutive samples with the same value) of the signal at its peak levels +(i.e. either @var{Min_level} or @var{Max_level}) -@item RMS peak dB -@item RMS trough dB -Peak and trough values for RMS level measured over a short window. +@item Max_difference +maximal difference between two consecutive samples -@item Crest factor -Standard ratio of peak to RMS level (note: not in dB). +@item Max_level +maximal sample level -@item Flat factor -Flatness (i.e. consecutive samples with the same value) of the signal at its peak levels -(i.e. either @var{Min level} or @var{Max level}). +@item Mean_difference +mean difference between two consecutive samples, i.e. the average of each difference between two consecutive samples -@item Peak count -Number of occasions (not the number of samples) that the signal attained either -@var{Min level} or @var{Max level}. +@item Min_difference +minimal difference between two consecutive samples -@item Noise floor dB -Minimum local peak measured in dBFS over a short window. +@item Min_level +minimal sample level -@item Noise floor count -Number of occasions (not the number of samples) that the signal attained -@var{Noise floor}. +@item Noise_floor +minimum local peak measured in dBFS over a short window -@item Entropy -Entropy measured across whole audio. Entropy of value near 1.0 is typically measured for white noise. +@item Noise_floor_count +number of occasions (not the number of samples) that the signal attained +@var{Noise floor} + +@item Number_of_Infs +number of samples with an infinite value + +@item Number_of_NaNs +number of samples with a NaN (not a number) value + +@item Number_of_denormals +number of samples with a subnormal value + +@item Number_of_samples +number of samples + +@item Peak_count +number of occasions (not the number of samples) that the signal attained either +@var{Min_level} or @var{Max_level} + +@item Peak_level +standard peak level measured in dBFS + +@item RMS_difference +Root Mean Square difference between two consecutive samples -@item Bit depth -Overall bit depth of audio. Number of bits used for each sample. +@item RMS_level +standard RMS level measured in dBFS -@item Dynamic range -Measured dynamic range of audio in dB. +@item RMS_peak +@item RMS_trough +peak and trough values for RMS level measured over a short window, +measured in dBFS. @item Zero crossings -Number of points where the waveform crosses the zero level axis. +number of points where the waveform crosses the zero level axis @item Zero crossings rate -Rate of Zero crossings and number of audio samples. +rate of Zero crossings and number of audio samples @end table @section asubboost From f0a415c7eb47d4a71c93948f564d91d812070f6a Mon Sep 17 00:00:00 2001 From: Stefano Sabatini Date: Sun, 15 Jan 2023 03:06:39 +0100 Subject: [PATCH 0227/2172] examples: rename avio_reading to avio_read_callback Adopt general scheme VERB_OBJECT. --- configure | 4 ++-- doc/examples/Makefile | 2 +- doc/examples/Makefile.example | 2 +- doc/examples/{avio_reading.c => avio_read_callback.c} | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) rename doc/examples/{avio_reading.c => avio_read_callback.c} (99%) diff --git a/configure b/configure index d38613309dd..7e2fdc2bea3 100755 --- a/configure +++ b/configure @@ -1711,7 +1711,7 @@ COMPONENT_LIST=" EXAMPLE_LIST=" avio_list_dir_example - avio_reading_example + avio_read_callback_example decode_audio_example decode_video_example demuxing_decoding_example @@ -3775,7 +3775,7 @@ xstack_vaapi_filter_deps="vaapi_1" # examples avio_list_dir_deps="avformat avutil" -avio_reading_deps="avformat avcodec avutil" +avio_read_callback_deps="avformat avcodec avutil" decode_audio_example_deps="avcodec avutil" decode_video_example_deps="avcodec avutil" demuxing_decoding_example_deps="avcodec avformat avutil" diff --git a/doc/examples/Makefile b/doc/examples/Makefile index f937fbefda5..a651f5877a9 100644 --- a/doc/examples/Makefile +++ b/doc/examples/Makefile @@ -1,5 +1,5 @@ EXAMPLES-$(CONFIG_AVIO_LIST_DIR_EXAMPLE) += avio_list_dir -EXAMPLES-$(CONFIG_AVIO_READING_EXAMPLE) += avio_reading +EXAMPLES-$(CONFIG_AVIO_READ_CALLBACK_EXAMPLE) += avio_read_callback EXAMPLES-$(CONFIG_DECODE_AUDIO_EXAMPLE) += decode_audio EXAMPLES-$(CONFIG_DECODE_VIDEO_EXAMPLE) += decode_video EXAMPLES-$(CONFIG_DEMUXING_DECODING_EXAMPLE) += demuxing_decoding diff --git a/doc/examples/Makefile.example b/doc/examples/Makefile.example index a232d97f987..bcb485e3061 100644 --- a/doc/examples/Makefile.example +++ b/doc/examples/Makefile.example @@ -12,7 +12,7 @@ CFLAGS := $(shell pkg-config --cflags $(FFMPEG_LIBS)) $(CFLAGS) LDLIBS := $(shell pkg-config --libs $(FFMPEG_LIBS)) $(LDLIBS) EXAMPLES= avio_list_dir \ - avio_reading \ + avio_read_callback \ decode_audio \ decode_video \ demuxing_decoding \ diff --git a/doc/examples/avio_reading.c b/doc/examples/avio_read_callback.c similarity index 99% rename from doc/examples/avio_reading.c rename to doc/examples/avio_read_callback.c index 36ee02afa54..e57a66bdec8 100644 --- a/doc/examples/avio_reading.c +++ b/doc/examples/avio_read_callback.c @@ -26,7 +26,7 @@ * * Make libavformat demuxer access media content through a custom * AVIOContext read callback. - * @example avio_reading.c + * @example avio_read_callback.c */ #include From 7f5630a89983ac4f156ad643c0c8c42400e8102b Mon Sep 17 00:00:00 2001 From: Stefano Sabatini Date: Sun, 15 Jan 2023 03:13:01 +0100 Subject: [PATCH 0228/2172] examples: rename demuxing_decoding to demux_decode Follow general scheme VERB_OBJECT. --- configure | 4 ++-- doc/examples/Makefile | 2 +- doc/examples/Makefile.example | 2 +- doc/examples/{demuxing_decoding.c => demux_decode.c} | 4 ++-- 4 files changed, 6 insertions(+), 6 deletions(-) rename doc/examples/{demuxing_decoding.c => demux_decode.c} (99%) diff --git a/configure b/configure index 7e2fdc2bea3..543d6958737 100755 --- a/configure +++ b/configure @@ -1714,7 +1714,7 @@ EXAMPLE_LIST=" avio_read_callback_example decode_audio_example decode_video_example - demuxing_decoding_example + demux_decode_example encode_audio_example encode_video_example extract_mvs_example @@ -3778,7 +3778,7 @@ avio_list_dir_deps="avformat avutil" avio_read_callback_deps="avformat avcodec avutil" decode_audio_example_deps="avcodec avutil" decode_video_example_deps="avcodec avutil" -demuxing_decoding_example_deps="avcodec avformat avutil" +demux_decode_example_deps="avcodec avformat avutil" encode_audio_example_deps="avcodec avutil" encode_video_example_deps="avcodec avutil" extract_mvs_example_deps="avcodec avformat avutil" diff --git a/doc/examples/Makefile b/doc/examples/Makefile index a651f5877a9..adfcdb6aa38 100644 --- a/doc/examples/Makefile +++ b/doc/examples/Makefile @@ -2,7 +2,7 @@ EXAMPLES-$(CONFIG_AVIO_LIST_DIR_EXAMPLE) += avio_list_dir EXAMPLES-$(CONFIG_AVIO_READ_CALLBACK_EXAMPLE) += avio_read_callback EXAMPLES-$(CONFIG_DECODE_AUDIO_EXAMPLE) += decode_audio EXAMPLES-$(CONFIG_DECODE_VIDEO_EXAMPLE) += decode_video -EXAMPLES-$(CONFIG_DEMUXING_DECODING_EXAMPLE) += demuxing_decoding +EXAMPLES-$(CONFIG_DEMUX_DECODE_EXAMPLE) += demux_decode EXAMPLES-$(CONFIG_ENCODE_AUDIO_EXAMPLE) += encode_audio EXAMPLES-$(CONFIG_ENCODE_VIDEO_EXAMPLE) += encode_video EXAMPLES-$(CONFIG_EXTRACT_MVS_EXAMPLE) += extract_mvs diff --git a/doc/examples/Makefile.example b/doc/examples/Makefile.example index bcb485e3061..33af323c6f0 100644 --- a/doc/examples/Makefile.example +++ b/doc/examples/Makefile.example @@ -15,7 +15,7 @@ EXAMPLES= avio_list_dir \ avio_read_callback \ decode_audio \ decode_video \ - demuxing_decoding \ + demux_decode \ encode_audio \ encode_video \ extract_mvs \ diff --git a/doc/examples/demuxing_decoding.c b/doc/examples/demux_decode.c similarity index 99% rename from doc/examples/demuxing_decoding.c rename to doc/examples/demux_decode.c index 999a78db0d6..a2ca53b26be 100644 --- a/doc/examples/demuxing_decoding.c +++ b/doc/examples/demux_decode.c @@ -22,11 +22,11 @@ /** * @file - * Demuxing and decoding example. + * libavformat and libavcodec API example to demux and decode. * * Show how to use the libavformat and libavcodec API to demux and * decode audio and video data. - * @example demuxing_decoding.c + * @example demux_decode.c */ #include From 3367bd56d140bdad70784fb5ab6e8d964498e064 Mon Sep 17 00:00:00 2001 From: Stefano Sabatini Date: Sun, 15 Jan 2023 12:26:30 +0100 Subject: [PATCH 0229/2172] examples: rename filtering_audio to decode_filter_audio --- configure | 4 ++-- doc/examples/Makefile | 2 +- doc/examples/Makefile.example | 2 +- doc/examples/{filtering_audio.c => decode_filter_audio.c} | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) rename doc/examples/{filtering_audio.c => decode_filter_audio.c} (99%) diff --git a/configure b/configure index 543d6958737..357fb01f688 100755 --- a/configure +++ b/configure @@ -1713,13 +1713,13 @@ EXAMPLE_LIST=" avio_list_dir_example avio_read_callback_example decode_audio_example + decode_filter_audio_example decode_video_example demux_decode_example encode_audio_example encode_video_example extract_mvs_example filter_audio_example - filtering_audio_example filtering_video_example http_multiclient_example hw_decode_example @@ -3777,13 +3777,13 @@ xstack_vaapi_filter_deps="vaapi_1" avio_list_dir_deps="avformat avutil" avio_read_callback_deps="avformat avcodec avutil" decode_audio_example_deps="avcodec avutil" +decode_filter_audio_example_deps="avfilter avcodec avformat avutil" decode_video_example_deps="avcodec avutil" demux_decode_example_deps="avcodec avformat avutil" encode_audio_example_deps="avcodec avutil" encode_video_example_deps="avcodec avutil" extract_mvs_example_deps="avcodec avformat avutil" filter_audio_example_deps="avfilter avutil" -filtering_audio_example_deps="avfilter avcodec avformat avutil" filtering_video_example_deps="avfilter avcodec avformat avutil" http_multiclient_example_deps="avformat avutil fork" hw_decode_example_deps="avcodec avformat avutil" diff --git a/doc/examples/Makefile b/doc/examples/Makefile index adfcdb6aa38..2e97605d5e1 100644 --- a/doc/examples/Makefile +++ b/doc/examples/Makefile @@ -1,13 +1,13 @@ EXAMPLES-$(CONFIG_AVIO_LIST_DIR_EXAMPLE) += avio_list_dir EXAMPLES-$(CONFIG_AVIO_READ_CALLBACK_EXAMPLE) += avio_read_callback EXAMPLES-$(CONFIG_DECODE_AUDIO_EXAMPLE) += decode_audio +EXAMPLES-$(CONFIG_DECODE_FILTER_AUDIO_EXAMPLE) += decode_filter_audio EXAMPLES-$(CONFIG_DECODE_VIDEO_EXAMPLE) += decode_video EXAMPLES-$(CONFIG_DEMUX_DECODE_EXAMPLE) += demux_decode EXAMPLES-$(CONFIG_ENCODE_AUDIO_EXAMPLE) += encode_audio EXAMPLES-$(CONFIG_ENCODE_VIDEO_EXAMPLE) += encode_video EXAMPLES-$(CONFIG_EXTRACT_MVS_EXAMPLE) += extract_mvs EXAMPLES-$(CONFIG_FILTER_AUDIO_EXAMPLE) += filter_audio -EXAMPLES-$(CONFIG_FILTERING_AUDIO_EXAMPLE) += filtering_audio EXAMPLES-$(CONFIG_FILTERING_VIDEO_EXAMPLE) += filtering_video EXAMPLES-$(CONFIG_HTTP_MULTICLIENT_EXAMPLE) += http_multiclient EXAMPLES-$(CONFIG_HW_DECODE_EXAMPLE) += hw_decode diff --git a/doc/examples/Makefile.example b/doc/examples/Makefile.example index 33af323c6f0..e720dc2008d 100644 --- a/doc/examples/Makefile.example +++ b/doc/examples/Makefile.example @@ -14,13 +14,13 @@ LDLIBS := $(shell pkg-config --libs $(FFMPEG_LIBS)) $(LDLIBS) EXAMPLES= avio_list_dir \ avio_read_callback \ decode_audio \ + decode_filter_audio \ decode_video \ demux_decode \ encode_audio \ encode_video \ extract_mvs \ filtering_video \ - filtering_audio \ http_multiclient \ hw_decode \ metadata \ diff --git a/doc/examples/filtering_audio.c b/doc/examples/decode_filter_audio.c similarity index 99% rename from doc/examples/filtering_audio.c rename to doc/examples/decode_filter_audio.c index 51fc47be2a9..607237bf111 100644 --- a/doc/examples/filtering_audio.c +++ b/doc/examples/decode_filter_audio.c @@ -25,7 +25,7 @@ /** * @file * API example for audio decoding and filtering - * @example filtering_audio.c + * @example decode_filter_audio.c */ #include From 1ae619e8ee1d4ae9d16820df75b8dd9dcbedd8cd Mon Sep 17 00:00:00 2001 From: Stefano Sabatini Date: Sun, 15 Jan 2023 12:33:11 +0100 Subject: [PATCH 0230/2172] examples: rename filtering_video to decode_filter_video --- configure | 4 ++-- doc/examples/Makefile | 2 +- doc/examples/Makefile.example | 2 +- doc/examples/{filtering_video.c => decode_filter_video.c} | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) rename doc/examples/{filtering_video.c => decode_filter_video.c} (99%) diff --git a/configure b/configure index 357fb01f688..62b0c196fae 100755 --- a/configure +++ b/configure @@ -1714,13 +1714,13 @@ EXAMPLE_LIST=" avio_read_callback_example decode_audio_example decode_filter_audio_example + decode_filter_video_example decode_video_example demux_decode_example encode_audio_example encode_video_example extract_mvs_example filter_audio_example - filtering_video_example http_multiclient_example hw_decode_example metadata_example @@ -3778,13 +3778,13 @@ avio_list_dir_deps="avformat avutil" avio_read_callback_deps="avformat avcodec avutil" decode_audio_example_deps="avcodec avutil" decode_filter_audio_example_deps="avfilter avcodec avformat avutil" +decode_filter_video_example_deps="avfilter avcodec avformat avutil" decode_video_example_deps="avcodec avutil" demux_decode_example_deps="avcodec avformat avutil" encode_audio_example_deps="avcodec avutil" encode_video_example_deps="avcodec avutil" extract_mvs_example_deps="avcodec avformat avutil" filter_audio_example_deps="avfilter avutil" -filtering_video_example_deps="avfilter avcodec avformat avutil" http_multiclient_example_deps="avformat avutil fork" hw_decode_example_deps="avcodec avformat avutil" metadata_example_deps="avformat avutil" diff --git a/doc/examples/Makefile b/doc/examples/Makefile index 2e97605d5e1..ba3a3b712a4 100644 --- a/doc/examples/Makefile +++ b/doc/examples/Makefile @@ -2,13 +2,13 @@ EXAMPLES-$(CONFIG_AVIO_LIST_DIR_EXAMPLE) += avio_list_dir EXAMPLES-$(CONFIG_AVIO_READ_CALLBACK_EXAMPLE) += avio_read_callback EXAMPLES-$(CONFIG_DECODE_AUDIO_EXAMPLE) += decode_audio EXAMPLES-$(CONFIG_DECODE_FILTER_AUDIO_EXAMPLE) += decode_filter_audio +EXAMPLES-$(CONFIG_DECODE_FILTER_VIDEO_EXAMPLE) += decode_filter_video EXAMPLES-$(CONFIG_DECODE_VIDEO_EXAMPLE) += decode_video EXAMPLES-$(CONFIG_DEMUX_DECODE_EXAMPLE) += demux_decode EXAMPLES-$(CONFIG_ENCODE_AUDIO_EXAMPLE) += encode_audio EXAMPLES-$(CONFIG_ENCODE_VIDEO_EXAMPLE) += encode_video EXAMPLES-$(CONFIG_EXTRACT_MVS_EXAMPLE) += extract_mvs EXAMPLES-$(CONFIG_FILTER_AUDIO_EXAMPLE) += filter_audio -EXAMPLES-$(CONFIG_FILTERING_VIDEO_EXAMPLE) += filtering_video EXAMPLES-$(CONFIG_HTTP_MULTICLIENT_EXAMPLE) += http_multiclient EXAMPLES-$(CONFIG_HW_DECODE_EXAMPLE) += hw_decode EXAMPLES-$(CONFIG_METADATA_EXAMPLE) += metadata diff --git a/doc/examples/Makefile.example b/doc/examples/Makefile.example index e720dc2008d..3383bb61fef 100644 --- a/doc/examples/Makefile.example +++ b/doc/examples/Makefile.example @@ -15,12 +15,12 @@ EXAMPLES= avio_list_dir \ avio_read_callback \ decode_audio \ decode_filter_audio \ + decode_filter_video \ decode_video \ demux_decode \ encode_audio \ encode_video \ extract_mvs \ - filtering_video \ http_multiclient \ hw_decode \ metadata \ diff --git a/doc/examples/filtering_video.c b/doc/examples/decode_filter_video.c similarity index 99% rename from doc/examples/filtering_video.c rename to doc/examples/decode_filter_video.c index 7b3e16c40c0..454c19222f2 100644 --- a/doc/examples/filtering_video.c +++ b/doc/examples/decode_filter_video.c @@ -24,7 +24,7 @@ /** * @file * API example for decoding and filtering - * @example filtering_video.c + * @example decode_filter_video.c */ #define _XOPEN_SOURCE 600 /* for usleep */ From 2e4694707e619ddb736489cc32ace997c6788930 Mon Sep 17 00:00:00 2001 From: Stefano Sabatini Date: Sun, 15 Jan 2023 12:44:04 +0100 Subject: [PATCH 0231/2172] examples: rename http_multiclient to avio_http_serve_files --- configure | 4 ++-- doc/examples/Makefile | 2 +- doc/examples/Makefile.example | 5 +++-- doc/examples/{http_multiclient.c => avio_http_serve_files.c} | 2 +- 4 files changed, 7 insertions(+), 6 deletions(-) rename doc/examples/{http_multiclient.c => avio_http_serve_files.c} (99%) diff --git a/configure b/configure index 62b0c196fae..b695c77c585 100755 --- a/configure +++ b/configure @@ -1710,6 +1710,7 @@ COMPONENT_LIST=" " EXAMPLE_LIST=" + avio_http_serve_files_example avio_list_dir_example avio_read_callback_example decode_audio_example @@ -1721,7 +1722,6 @@ EXAMPLE_LIST=" encode_video_example extract_mvs_example filter_audio_example - http_multiclient_example hw_decode_example metadata_example muxing_example @@ -3774,6 +3774,7 @@ vstack_vaapi_filter_deps="vaapi_1" xstack_vaapi_filter_deps="vaapi_1" # examples +avio_http_serve_files_deps="avformat avutil fork" avio_list_dir_deps="avformat avutil" avio_read_callback_deps="avformat avcodec avutil" decode_audio_example_deps="avcodec avutil" @@ -3785,7 +3786,6 @@ encode_audio_example_deps="avcodec avutil" encode_video_example_deps="avcodec avutil" extract_mvs_example_deps="avcodec avformat avutil" filter_audio_example_deps="avfilter avutil" -http_multiclient_example_deps="avformat avutil fork" hw_decode_example_deps="avcodec avformat avutil" metadata_example_deps="avformat avutil" muxing_example_deps="avcodec avformat avutil swscale" diff --git a/doc/examples/Makefile b/doc/examples/Makefile index ba3a3b712a4..f640a5e6360 100644 --- a/doc/examples/Makefile +++ b/doc/examples/Makefile @@ -1,3 +1,4 @@ +EXAMPLES-$(CONFIG_AVIO_HTTP_SERVE_FILES) += avio_http_serve_files EXAMPLES-$(CONFIG_AVIO_LIST_DIR_EXAMPLE) += avio_list_dir EXAMPLES-$(CONFIG_AVIO_READ_CALLBACK_EXAMPLE) += avio_read_callback EXAMPLES-$(CONFIG_DECODE_AUDIO_EXAMPLE) += decode_audio @@ -9,7 +10,6 @@ EXAMPLES-$(CONFIG_ENCODE_AUDIO_EXAMPLE) += encode_audio EXAMPLES-$(CONFIG_ENCODE_VIDEO_EXAMPLE) += encode_video EXAMPLES-$(CONFIG_EXTRACT_MVS_EXAMPLE) += extract_mvs EXAMPLES-$(CONFIG_FILTER_AUDIO_EXAMPLE) += filter_audio -EXAMPLES-$(CONFIG_HTTP_MULTICLIENT_EXAMPLE) += http_multiclient EXAMPLES-$(CONFIG_HW_DECODE_EXAMPLE) += hw_decode EXAMPLES-$(CONFIG_METADATA_EXAMPLE) += metadata EXAMPLES-$(CONFIG_MUXING_EXAMPLE) += muxing diff --git a/doc/examples/Makefile.example b/doc/examples/Makefile.example index 3383bb61fef..9e725715a59 100644 --- a/doc/examples/Makefile.example +++ b/doc/examples/Makefile.example @@ -11,7 +11,9 @@ CFLAGS += -Wall -g CFLAGS := $(shell pkg-config --cflags $(FFMPEG_LIBS)) $(CFLAGS) LDLIBS := $(shell pkg-config --libs $(FFMPEG_LIBS)) $(LDLIBS) -EXAMPLES= avio_list_dir \ +EXAMPLES=\ + avio_http_serve_files \ + avio_list_dir \ avio_read_callback \ decode_audio \ decode_filter_audio \ @@ -21,7 +23,6 @@ EXAMPLES= avio_list_dir \ encode_audio \ encode_video \ extract_mvs \ - http_multiclient \ hw_decode \ metadata \ muxing \ diff --git a/doc/examples/http_multiclient.c b/doc/examples/avio_http_serve_files.c similarity index 99% rename from doc/examples/http_multiclient.c rename to doc/examples/avio_http_serve_files.c index 831e89c60a4..d6a1d146f34 100644 --- a/doc/examples/http_multiclient.c +++ b/doc/examples/avio_http_serve_files.c @@ -24,7 +24,7 @@ * @file * libavformat multi-client network API usage example. * - * @example http_multiclient.c + * @example avio_http_serve_files.c * This example will serve a file without decoding or demuxing it over http. * Multiple clients can connect and will receive the same file. */ From 7a53ae931d3cac6f78993ba5480efd684a835cbc Mon Sep 17 00:00:00 2001 From: Stefano Sabatini Date: Sun, 15 Jan 2023 12:49:32 +0100 Subject: [PATCH 0232/2172] examples: rename metadata to show_metadata --- configure | 4 ++-- doc/examples/Makefile | 2 +- doc/examples/Makefile.example | 2 +- doc/examples/{metadata.c => show_metadata.c} | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) rename doc/examples/{metadata.c => show_metadata.c} (98%) diff --git a/configure b/configure index b695c77c585..6d4e1842418 100755 --- a/configure +++ b/configure @@ -1723,12 +1723,12 @@ EXAMPLE_LIST=" extract_mvs_example filter_audio_example hw_decode_example - metadata_example muxing_example qsvdec_example remuxing_example resampling_audio_example scaling_video_example + show_metadata_example transcode_aac_example transcoding_example vaapi_encode_example @@ -3787,12 +3787,12 @@ encode_video_example_deps="avcodec avutil" extract_mvs_example_deps="avcodec avformat avutil" filter_audio_example_deps="avfilter avutil" hw_decode_example_deps="avcodec avformat avutil" -metadata_example_deps="avformat avutil" muxing_example_deps="avcodec avformat avutil swscale" qsvdec_example_deps="avcodec avutil libmfx h264_qsv_decoder" remuxing_example_deps="avcodec avformat avutil" resampling_audio_example_deps="avutil swresample" scaling_video_example_deps="avutil swscale" +show_metadata_example_deps="avformat avutil" transcode_aac_example_deps="avcodec avformat swresample" transcoding_example_deps="avfilter avcodec avformat avutil" vaapi_encode_example_deps="avcodec avutil h264_vaapi_encoder" diff --git a/doc/examples/Makefile b/doc/examples/Makefile index f640a5e6360..44a56dd84d7 100644 --- a/doc/examples/Makefile +++ b/doc/examples/Makefile @@ -11,12 +11,12 @@ EXAMPLES-$(CONFIG_ENCODE_VIDEO_EXAMPLE) += encode_video EXAMPLES-$(CONFIG_EXTRACT_MVS_EXAMPLE) += extract_mvs EXAMPLES-$(CONFIG_FILTER_AUDIO_EXAMPLE) += filter_audio EXAMPLES-$(CONFIG_HW_DECODE_EXAMPLE) += hw_decode -EXAMPLES-$(CONFIG_METADATA_EXAMPLE) += metadata EXAMPLES-$(CONFIG_MUXING_EXAMPLE) += muxing EXAMPLES-$(CONFIG_QSVDEC_EXAMPLE) += qsvdec EXAMPLES-$(CONFIG_REMUXING_EXAMPLE) += remuxing EXAMPLES-$(CONFIG_RESAMPLING_AUDIO_EXAMPLE) += resampling_audio EXAMPLES-$(CONFIG_SCALING_VIDEO_EXAMPLE) += scaling_video +EXAMPLES-$(CONFIG_SHOW_METADATA_EXAMPLE) += show_metadata EXAMPLES-$(CONFIG_TRANSCODE_AAC_EXAMPLE) += transcode_aac EXAMPLES-$(CONFIG_TRANSCODING_EXAMPLE) += transcoding EXAMPLES-$(CONFIG_VAAPI_ENCODE_EXAMPLE) += vaapi_encode diff --git a/doc/examples/Makefile.example b/doc/examples/Makefile.example index 9e725715a59..db09ceddd11 100644 --- a/doc/examples/Makefile.example +++ b/doc/examples/Makefile.example @@ -24,11 +24,11 @@ EXAMPLES=\ encode_video \ extract_mvs \ hw_decode \ - metadata \ muxing \ remuxing \ resampling_audio \ scaling_video \ + show_metadata \ transcode_aac \ transcoding \ diff --git a/doc/examples/metadata.c b/doc/examples/show_metadata.c similarity index 98% rename from doc/examples/metadata.c rename to doc/examples/show_metadata.c index 734b12df165..f7f07bf598b 100644 --- a/doc/examples/metadata.c +++ b/doc/examples/show_metadata.c @@ -23,7 +23,7 @@ /** * @file * Shows how the metadata API can be used in application programs. - * @example metadata.c + * @example show_metadata.c */ #include From eac4324bfbe452f0292b48b2f1dc37b5052ec0be Mon Sep 17 00:00:00 2001 From: Stefano Sabatini Date: Sun, 15 Jan 2023 12:53:31 +0100 Subject: [PATCH 0233/2172] examples: rename muxing to mux --- configure | 4 ++-- doc/examples/Makefile | 2 +- doc/examples/Makefile.example | 2 +- doc/examples/encode_video.c | 2 +- doc/examples/{muxing.c => mux.c} | 2 +- 5 files changed, 6 insertions(+), 6 deletions(-) rename doc/examples/{muxing.c => mux.c} (99%) diff --git a/configure b/configure index 6d4e1842418..71c92e1e6d8 100755 --- a/configure +++ b/configure @@ -1723,7 +1723,7 @@ EXAMPLE_LIST=" extract_mvs_example filter_audio_example hw_decode_example - muxing_example + mux_example qsvdec_example remuxing_example resampling_audio_example @@ -3787,7 +3787,7 @@ encode_video_example_deps="avcodec avutil" extract_mvs_example_deps="avcodec avformat avutil" filter_audio_example_deps="avfilter avutil" hw_decode_example_deps="avcodec avformat avutil" -muxing_example_deps="avcodec avformat avutil swscale" +mux_example_deps="avcodec avformat avutil swscale" qsvdec_example_deps="avcodec avutil libmfx h264_qsv_decoder" remuxing_example_deps="avcodec avformat avutil" resampling_audio_example_deps="avutil swresample" diff --git a/doc/examples/Makefile b/doc/examples/Makefile index 44a56dd84d7..c91d26e4a00 100644 --- a/doc/examples/Makefile +++ b/doc/examples/Makefile @@ -11,7 +11,7 @@ EXAMPLES-$(CONFIG_ENCODE_VIDEO_EXAMPLE) += encode_video EXAMPLES-$(CONFIG_EXTRACT_MVS_EXAMPLE) += extract_mvs EXAMPLES-$(CONFIG_FILTER_AUDIO_EXAMPLE) += filter_audio EXAMPLES-$(CONFIG_HW_DECODE_EXAMPLE) += hw_decode -EXAMPLES-$(CONFIG_MUXING_EXAMPLE) += muxing +EXAMPLES-$(CONFIG_MUX_EXAMPLE) += mux EXAMPLES-$(CONFIG_QSVDEC_EXAMPLE) += qsvdec EXAMPLES-$(CONFIG_REMUXING_EXAMPLE) += remuxing EXAMPLES-$(CONFIG_RESAMPLING_AUDIO_EXAMPLE) += resampling_audio diff --git a/doc/examples/Makefile.example b/doc/examples/Makefile.example index db09ceddd11..920c7a2362f 100644 --- a/doc/examples/Makefile.example +++ b/doc/examples/Makefile.example @@ -24,7 +24,7 @@ EXAMPLES=\ encode_video \ extract_mvs \ hw_decode \ - muxing \ + mux \ remuxing \ resampling_audio \ scaling_video \ diff --git a/doc/examples/encode_video.c b/doc/examples/encode_video.c index 939ed68324e..6c3a3f5684f 100644 --- a/doc/examples/encode_video.c +++ b/doc/examples/encode_video.c @@ -202,7 +202,7 @@ int main(int argc, char **argv) It makes only sense because this tiny examples writes packets directly. This is called "elementary stream" and only works for some codecs. To create a valid file, you usually need to write packets - into a proper file format or protocol; see muxing.c. + into a proper file format or protocol; see mux.c. */ if (codec->id == AV_CODEC_ID_MPEG1VIDEO || codec->id == AV_CODEC_ID_MPEG2VIDEO) fwrite(endcode, 1, sizeof(endcode), f); diff --git a/doc/examples/muxing.c b/doc/examples/mux.c similarity index 99% rename from doc/examples/muxing.c rename to doc/examples/mux.c index cd997d5431d..e3062c5003a 100644 --- a/doc/examples/muxing.c +++ b/doc/examples/mux.c @@ -26,7 +26,7 @@ * * Output a media file in any supported libavformat format. The default * codecs are used. - * @example muxing.c + * @example mux.c */ #include From ab2ec8ef015c0516c9d6824ef47195adc6c2a40b Mon Sep 17 00:00:00 2001 From: Stefano Sabatini Date: Sun, 15 Jan 2023 12:56:54 +0100 Subject: [PATCH 0234/2172] examples: rename qsvdec to qsv_decode --- configure | 4 ++-- doc/examples/Makefile | 2 +- doc/examples/{qsvdec.c => qsv_decode.c} | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) rename doc/examples/{qsvdec.c => qsv_decode.c} (99%) diff --git a/configure b/configure index 71c92e1e6d8..e72d253e644 100755 --- a/configure +++ b/configure @@ -1724,7 +1724,7 @@ EXAMPLE_LIST=" filter_audio_example hw_decode_example mux_example - qsvdec_example + qsv_decode_example remuxing_example resampling_audio_example scaling_video_example @@ -3788,7 +3788,7 @@ extract_mvs_example_deps="avcodec avformat avutil" filter_audio_example_deps="avfilter avutil" hw_decode_example_deps="avcodec avformat avutil" mux_example_deps="avcodec avformat avutil swscale" -qsvdec_example_deps="avcodec avutil libmfx h264_qsv_decoder" +qsv_decode_example_deps="avcodec avutil libmfx h264_qsv_decoder" remuxing_example_deps="avcodec avformat avutil" resampling_audio_example_deps="avutil swresample" scaling_video_example_deps="avutil swscale" diff --git a/doc/examples/Makefile b/doc/examples/Makefile index c91d26e4a00..9342fae7443 100644 --- a/doc/examples/Makefile +++ b/doc/examples/Makefile @@ -12,7 +12,7 @@ EXAMPLES-$(CONFIG_EXTRACT_MVS_EXAMPLE) += extract_mvs EXAMPLES-$(CONFIG_FILTER_AUDIO_EXAMPLE) += filter_audio EXAMPLES-$(CONFIG_HW_DECODE_EXAMPLE) += hw_decode EXAMPLES-$(CONFIG_MUX_EXAMPLE) += mux -EXAMPLES-$(CONFIG_QSVDEC_EXAMPLE) += qsvdec +EXAMPLES-$(CONFIG_QSV_DECODE_EXAMPLE) += qsv_decode EXAMPLES-$(CONFIG_REMUXING_EXAMPLE) += remuxing EXAMPLES-$(CONFIG_RESAMPLING_AUDIO_EXAMPLE) += resampling_audio EXAMPLES-$(CONFIG_SCALING_VIDEO_EXAMPLE) += scaling_video diff --git a/doc/examples/qsvdec.c b/doc/examples/qsv_decode.c similarity index 99% rename from doc/examples/qsvdec.c rename to doc/examples/qsv_decode.c index b662ae91c3c..0cdef4466c8 100644 --- a/doc/examples/qsvdec.c +++ b/doc/examples/qsv_decode.c @@ -24,7 +24,7 @@ * @file * Intel QSV-accelerated H.264 decoding example. * - * @example qsvdec.c + * @example qsv_decode.c * This example shows how to do QSV-accelerated H.264 decoding with output * frames in the GPU video surfaces. */ From 0a69ca656b7178c260f68d50d07b2e16a073050c Mon Sep 17 00:00:00 2001 From: Stefano Sabatini Date: Sun, 15 Jan 2023 13:03:47 +0100 Subject: [PATCH 0235/2172] examples: rename remuxing to remux --- configure | 4 ++-- doc/examples/Makefile | 2 +- doc/examples/Makefile.example | 2 +- doc/examples/{remuxing.c => remux.c} | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) rename doc/examples/{remuxing.c => remux.c} (99%) diff --git a/configure b/configure index e72d253e644..229880f6359 100755 --- a/configure +++ b/configure @@ -1725,7 +1725,7 @@ EXAMPLE_LIST=" hw_decode_example mux_example qsv_decode_example - remuxing_example + remux_example resampling_audio_example scaling_video_example show_metadata_example @@ -3789,7 +3789,7 @@ filter_audio_example_deps="avfilter avutil" hw_decode_example_deps="avcodec avformat avutil" mux_example_deps="avcodec avformat avutil swscale" qsv_decode_example_deps="avcodec avutil libmfx h264_qsv_decoder" -remuxing_example_deps="avcodec avformat avutil" +remux_example_deps="avcodec avformat avutil" resampling_audio_example_deps="avutil swresample" scaling_video_example_deps="avutil swscale" show_metadata_example_deps="avformat avutil" diff --git a/doc/examples/Makefile b/doc/examples/Makefile index 9342fae7443..8cc9d4e80e1 100644 --- a/doc/examples/Makefile +++ b/doc/examples/Makefile @@ -13,7 +13,7 @@ EXAMPLES-$(CONFIG_FILTER_AUDIO_EXAMPLE) += filter_audio EXAMPLES-$(CONFIG_HW_DECODE_EXAMPLE) += hw_decode EXAMPLES-$(CONFIG_MUX_EXAMPLE) += mux EXAMPLES-$(CONFIG_QSV_DECODE_EXAMPLE) += qsv_decode -EXAMPLES-$(CONFIG_REMUXING_EXAMPLE) += remuxing +EXAMPLES-$(CONFIG_REMUX_EXAMPLE) += remux EXAMPLES-$(CONFIG_RESAMPLING_AUDIO_EXAMPLE) += resampling_audio EXAMPLES-$(CONFIG_SCALING_VIDEO_EXAMPLE) += scaling_video EXAMPLES-$(CONFIG_SHOW_METADATA_EXAMPLE) += show_metadata diff --git a/doc/examples/Makefile.example b/doc/examples/Makefile.example index 920c7a2362f..ff30f9a3da7 100644 --- a/doc/examples/Makefile.example +++ b/doc/examples/Makefile.example @@ -25,7 +25,7 @@ EXAMPLES=\ extract_mvs \ hw_decode \ mux \ - remuxing \ + remux \ resampling_audio \ scaling_video \ show_metadata \ diff --git a/doc/examples/remuxing.c b/doc/examples/remux.c similarity index 99% rename from doc/examples/remuxing.c rename to doc/examples/remux.c index 2657f9dc669..8855199c603 100644 --- a/doc/examples/remuxing.c +++ b/doc/examples/remux.c @@ -25,7 +25,7 @@ * libavformat/libavcodec demuxing and muxing API example. * * Remux streams from one container format to another. - * @example remuxing.c + * @example remux.c */ #include From cd8211527efbb9cad19db1c0d033da0749836e43 Mon Sep 17 00:00:00 2001 From: Stefano Sabatini Date: Sun, 15 Jan 2023 16:43:06 +0100 Subject: [PATCH 0236/2172] examples: rename resampling audio to resample_audio --- configure | 4 ++-- doc/examples/Makefile | 2 +- doc/examples/Makefile.example | 2 +- doc/examples/{resampling_audio.c => resample_audio.c} | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) rename doc/examples/{resampling_audio.c => resample_audio.c} (99%) diff --git a/configure b/configure index 229880f6359..6862c96a7c8 100755 --- a/configure +++ b/configure @@ -1726,7 +1726,7 @@ EXAMPLE_LIST=" mux_example qsv_decode_example remux_example - resampling_audio_example + resample_audio_example scaling_video_example show_metadata_example transcode_aac_example @@ -3790,7 +3790,7 @@ hw_decode_example_deps="avcodec avformat avutil" mux_example_deps="avcodec avformat avutil swscale" qsv_decode_example_deps="avcodec avutil libmfx h264_qsv_decoder" remux_example_deps="avcodec avformat avutil" -resampling_audio_example_deps="avutil swresample" +resample_audio_example_deps="avutil swresample" scaling_video_example_deps="avutil swscale" show_metadata_example_deps="avformat avutil" transcode_aac_example_deps="avcodec avformat swresample" diff --git a/doc/examples/Makefile b/doc/examples/Makefile index 8cc9d4e80e1..4ea0d95ca10 100644 --- a/doc/examples/Makefile +++ b/doc/examples/Makefile @@ -14,7 +14,7 @@ EXAMPLES-$(CONFIG_HW_DECODE_EXAMPLE) += hw_decode EXAMPLES-$(CONFIG_MUX_EXAMPLE) += mux EXAMPLES-$(CONFIG_QSV_DECODE_EXAMPLE) += qsv_decode EXAMPLES-$(CONFIG_REMUX_EXAMPLE) += remux -EXAMPLES-$(CONFIG_RESAMPLING_AUDIO_EXAMPLE) += resampling_audio +EXAMPLES-$(CONFIG_RESAMPLE_AUDIO_EXAMPLE) += resample_audio EXAMPLES-$(CONFIG_SCALING_VIDEO_EXAMPLE) += scaling_video EXAMPLES-$(CONFIG_SHOW_METADATA_EXAMPLE) += show_metadata EXAMPLES-$(CONFIG_TRANSCODE_AAC_EXAMPLE) += transcode_aac diff --git a/doc/examples/Makefile.example b/doc/examples/Makefile.example index ff30f9a3da7..f632c0e490c 100644 --- a/doc/examples/Makefile.example +++ b/doc/examples/Makefile.example @@ -26,7 +26,7 @@ EXAMPLES=\ hw_decode \ mux \ remux \ - resampling_audio \ + resample_audio \ scaling_video \ show_metadata \ transcode_aac \ diff --git a/doc/examples/resampling_audio.c b/doc/examples/resample_audio.c similarity index 99% rename from doc/examples/resampling_audio.c rename to doc/examples/resample_audio.c index 9f1521a5a5f..890d30c934c 100644 --- a/doc/examples/resampling_audio.c +++ b/doc/examples/resample_audio.c @@ -21,7 +21,7 @@ */ /** - * @example resampling_audio.c + * @example resample_audio.c * libswresample API use example. */ From 3856f82ef9e70d6989ad2830ea7166e0a7508869 Mon Sep 17 00:00:00 2001 From: Stefano Sabatini Date: Sun, 15 Jan 2023 16:44:25 +0100 Subject: [PATCH 0237/2172] examples: rename scaling_video to scale_video --- configure | 4 ++-- doc/examples/Makefile | 2 +- doc/examples/Makefile.example | 2 +- doc/examples/{scaling_video.c => scale_video.c} | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) rename doc/examples/{scaling_video.c => scale_video.c} (99%) diff --git a/configure b/configure index 6862c96a7c8..8b746d4abfa 100755 --- a/configure +++ b/configure @@ -1727,7 +1727,7 @@ EXAMPLE_LIST=" qsv_decode_example remux_example resample_audio_example - scaling_video_example + scale_video_example show_metadata_example transcode_aac_example transcoding_example @@ -3791,7 +3791,7 @@ mux_example_deps="avcodec avformat avutil swscale" qsv_decode_example_deps="avcodec avutil libmfx h264_qsv_decoder" remux_example_deps="avcodec avformat avutil" resample_audio_example_deps="avutil swresample" -scaling_video_example_deps="avutil swscale" +scale_video_example_deps="avutil swscale" show_metadata_example_deps="avformat avutil" transcode_aac_example_deps="avcodec avformat swresample" transcoding_example_deps="avfilter avcodec avformat avutil" diff --git a/doc/examples/Makefile b/doc/examples/Makefile index 4ea0d95ca10..a42bcd44652 100644 --- a/doc/examples/Makefile +++ b/doc/examples/Makefile @@ -15,7 +15,7 @@ EXAMPLES-$(CONFIG_MUX_EXAMPLE) += mux EXAMPLES-$(CONFIG_QSV_DECODE_EXAMPLE) += qsv_decode EXAMPLES-$(CONFIG_REMUX_EXAMPLE) += remux EXAMPLES-$(CONFIG_RESAMPLE_AUDIO_EXAMPLE) += resample_audio -EXAMPLES-$(CONFIG_SCALING_VIDEO_EXAMPLE) += scaling_video +EXAMPLES-$(CONFIG_SCALE_VIDEO_EXAMPLE) += scale_video EXAMPLES-$(CONFIG_SHOW_METADATA_EXAMPLE) += show_metadata EXAMPLES-$(CONFIG_TRANSCODE_AAC_EXAMPLE) += transcode_aac EXAMPLES-$(CONFIG_TRANSCODING_EXAMPLE) += transcoding diff --git a/doc/examples/Makefile.example b/doc/examples/Makefile.example index f632c0e490c..da7a947830d 100644 --- a/doc/examples/Makefile.example +++ b/doc/examples/Makefile.example @@ -27,7 +27,7 @@ EXAMPLES=\ mux \ remux \ resample_audio \ - scaling_video \ + scale_video \ show_metadata \ transcode_aac \ transcoding \ diff --git a/doc/examples/scaling_video.c b/doc/examples/scale_video.c similarity index 99% rename from doc/examples/scaling_video.c rename to doc/examples/scale_video.c index 587f3abe4f1..27cd00996d9 100644 --- a/doc/examples/scaling_video.c +++ b/doc/examples/scale_video.c @@ -23,7 +23,7 @@ /** * @file * libswscale API use example. - * @example scaling_video.c + * @example scale_video.c */ #include From 3d4dc6aa778e60073f608d379139b46051da2302 Mon Sep 17 00:00:00 2001 From: Stefano Sabatini Date: Sun, 15 Jan 2023 13:11:09 +0100 Subject: [PATCH 0238/2172] examples: rename transcoding to transcode --- configure | 4 ++-- doc/examples/Makefile | 2 +- doc/examples/Makefile.example | 2 +- doc/examples/{transcoding.c => transcode.c} | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) rename doc/examples/{transcoding.c => transcode.c} (99%) diff --git a/configure b/configure index 8b746d4abfa..932805ccf3c 100755 --- a/configure +++ b/configure @@ -1730,7 +1730,7 @@ EXAMPLE_LIST=" scale_video_example show_metadata_example transcode_aac_example - transcoding_example + transcode_example vaapi_encode_example vaapi_transcode_example qsv_transcode_example @@ -3794,7 +3794,7 @@ resample_audio_example_deps="avutil swresample" scale_video_example_deps="avutil swscale" show_metadata_example_deps="avformat avutil" transcode_aac_example_deps="avcodec avformat swresample" -transcoding_example_deps="avfilter avcodec avformat avutil" +transcode_example_deps="avfilter avcodec avformat avutil" vaapi_encode_example_deps="avcodec avutil h264_vaapi_encoder" vaapi_transcode_example_deps="avcodec avformat avutil h264_vaapi_encoder" qsv_transcode_example_deps="avcodec avformat avutil h264_qsv_encoder" diff --git a/doc/examples/Makefile b/doc/examples/Makefile index a42bcd44652..4efed6b11d8 100644 --- a/doc/examples/Makefile +++ b/doc/examples/Makefile @@ -18,7 +18,7 @@ EXAMPLES-$(CONFIG_RESAMPLE_AUDIO_EXAMPLE) += resample_audio EXAMPLES-$(CONFIG_SCALE_VIDEO_EXAMPLE) += scale_video EXAMPLES-$(CONFIG_SHOW_METADATA_EXAMPLE) += show_metadata EXAMPLES-$(CONFIG_TRANSCODE_AAC_EXAMPLE) += transcode_aac -EXAMPLES-$(CONFIG_TRANSCODING_EXAMPLE) += transcoding +EXAMPLES-$(CONFIG_TRANSCODE_EXAMPLE) += transcode EXAMPLES-$(CONFIG_VAAPI_ENCODE_EXAMPLE) += vaapi_encode EXAMPLES-$(CONFIG_VAAPI_TRANSCODE_EXAMPLE) += vaapi_transcode EXAMPLES-$(CONFIG_QSV_TRANSCODE_EXAMPLE) += qsv_transcode diff --git a/doc/examples/Makefile.example b/doc/examples/Makefile.example index da7a947830d..730d7e1a9ae 100644 --- a/doc/examples/Makefile.example +++ b/doc/examples/Makefile.example @@ -30,7 +30,7 @@ EXAMPLES=\ scale_video \ show_metadata \ transcode_aac \ - transcoding \ + transcode \ OBJS=$(addsuffix .o,$(EXAMPLES)) diff --git a/doc/examples/transcoding.c b/doc/examples/transcode.c similarity index 99% rename from doc/examples/transcoding.c rename to doc/examples/transcode.c index 013f89fc7d2..b0f4fb0399b 100644 --- a/doc/examples/transcoding.c +++ b/doc/examples/transcode.c @@ -25,7 +25,7 @@ /** * @file * API example for demuxing, decoding, filtering, encoding and muxing - * @example transcoding.c + * @example transcode.c */ #include From 34ff361921ef3698d18626a7b7e1e9a48821c69a Mon Sep 17 00:00:00 2001 From: Stefano Sabatini Date: Sun, 15 Jan 2023 02:57:14 +0100 Subject: [PATCH 0239/2172] examples: apply doxy entries consistency fixes Use consistent format for the @file field and file description. --- doc/examples/avio_http_serve_files.c | 9 ++++----- doc/examples/avio_list_dir.c | 7 +++++++ doc/examples/avio_read_callback.c | 5 ++--- doc/examples/decode_audio.c | 7 ++++--- doc/examples/decode_filter_audio.c | 6 ++++-- doc/examples/decode_video.c | 7 ++++--- doc/examples/demux_decode.c | 10 +++++----- doc/examples/encode_audio.c | 6 +++--- doc/examples/encode_video.c | 6 +++--- doc/examples/extract_mvs.c | 8 ++++++++ doc/examples/filter_audio.c | 10 ++++------ doc/examples/hw_decode.c | 9 ++++----- doc/examples/mux.c | 9 ++++----- doc/examples/qsv_decode.c | 9 ++++----- doc/examples/qsv_transcode.c | 12 +++++------- doc/examples/remux.c | 8 ++++---- doc/examples/resample_audio.c | 6 +++++- doc/examples/scale_video.c | 5 +++-- doc/examples/show_metadata.c | 5 +++-- doc/examples/transcode.c | 6 ++++-- doc/examples/transcode_aac.c | 9 ++++----- doc/examples/vaapi_encode.c | 11 ++++------- doc/examples/vaapi_transcode.c | 9 +++------ 23 files changed, 95 insertions(+), 84 deletions(-) diff --git a/doc/examples/avio_http_serve_files.c b/doc/examples/avio_http_serve_files.c index d6a1d146f34..2aae3870c2d 100644 --- a/doc/examples/avio_http_serve_files.c +++ b/doc/examples/avio_http_serve_files.c @@ -21,12 +21,11 @@ */ /** - * @file - * libavformat multi-client network API usage example. - * + * @file libavformat multi-client network API usage example * @example avio_http_serve_files.c - * This example will serve a file without decoding or demuxing it over http. - * Multiple clients can connect and will receive the same file. + * + * Serve a file without decoding or demuxing it over the HTTP protocol. Multiple + * clients can connect and will receive the same file. */ #include diff --git a/doc/examples/avio_list_dir.c b/doc/examples/avio_list_dir.c index 3073baaefa9..bb19debad31 100644 --- a/doc/examples/avio_list_dir.c +++ b/doc/examples/avio_list_dir.c @@ -20,6 +20,13 @@ * THE SOFTWARE. */ +/** + * @file libavformat AVIOContext list directory API usage example + * @example avio_list_dir.c + * + * Show how to list directories through the libavformat AVIOContext API. + */ + #include #include #include diff --git a/doc/examples/avio_read_callback.c b/doc/examples/avio_read_callback.c index e57a66bdec8..4cf81ad72ee 100644 --- a/doc/examples/avio_read_callback.c +++ b/doc/examples/avio_read_callback.c @@ -21,12 +21,11 @@ */ /** - * @file - * libavformat AVIOContext API example. + * @file libavformat AVIOContext read callback API usage example + * @example avio_read_callback.c * * Make libavformat demuxer access media content through a custom * AVIOContext read callback. - * @example avio_read_callback.c */ #include diff --git a/doc/examples/decode_audio.c b/doc/examples/decode_audio.c index 49ad22cba63..bcb3d87a695 100644 --- a/doc/examples/decode_audio.c +++ b/doc/examples/decode_audio.c @@ -21,10 +21,11 @@ */ /** - * @file - * audio decoding with libavcodec API example - * + * @file libavcodec audio decoding API usage example * @example decode_audio.c + * + * Decode data from an MP2 input file and generate a raw audio file to + * be played with ffplay. */ #include diff --git a/doc/examples/decode_filter_audio.c b/doc/examples/decode_filter_audio.c index 607237bf111..2046419819a 100644 --- a/doc/examples/decode_filter_audio.c +++ b/doc/examples/decode_filter_audio.c @@ -23,9 +23,11 @@ */ /** - * @file - * API example for audio decoding and filtering + * @file audio decoding and filtering usage example * @example decode_filter_audio.c + * + * Demux, decode and filter audio input file, generate a raw audio + * file to be played with ffplay. */ #include diff --git a/doc/examples/decode_video.c b/doc/examples/decode_video.c index 7238e381039..81ec4b50e28 100644 --- a/doc/examples/decode_video.c +++ b/doc/examples/decode_video.c @@ -21,10 +21,11 @@ */ /** - * @file - * video decoding with libavcodec API example + * @file libavcodec video decoding API usage example + * @example decode_video.c * * - * @example decode_video.c + * Read from an MPEG1 video file, decode frames, and generate PGM images as + * output. */ #include diff --git a/doc/examples/demux_decode.c b/doc/examples/demux_decode.c index a2ca53b26be..ebef7a61142 100644 --- a/doc/examples/demux_decode.c +++ b/doc/examples/demux_decode.c @@ -21,12 +21,12 @@ */ /** - * @file - * libavformat and libavcodec API example to demux and decode. - * - * Show how to use the libavformat and libavcodec API to demux and - * decode audio and video data. + * @file libavformat and libavcodec demuxing and decoding API usage example * @example demux_decode.c + * + * Show how to use the libavformat and libavcodec API to demux and decode audio + * and video data. Write the output as raw audio and input files to be played by + * ffplay. */ #include diff --git a/doc/examples/encode_audio.c b/doc/examples/encode_audio.c index 9a1792b7250..bb16683d946 100644 --- a/doc/examples/encode_audio.c +++ b/doc/examples/encode_audio.c @@ -21,10 +21,10 @@ */ /** - * @file - * audio encoding with libavcodec API example. - * + * @file libavcodec encoding audio API usage examples * @example encode_audio.c + * + * Generate a synthetic audio signal and encode it to an output MP2 file. */ #include diff --git a/doc/examples/encode_video.c b/doc/examples/encode_video.c index 6c3a3f5684f..4fae146f2e9 100644 --- a/doc/examples/encode_video.c +++ b/doc/examples/encode_video.c @@ -21,10 +21,10 @@ */ /** - * @file - * video encoding with libavcodec API example - * + * @file libavcodec encoding video API usage example * @example encode_video.c + * + * Generate synthetic video data and encode it to an output file. */ #include diff --git a/doc/examples/extract_mvs.c b/doc/examples/extract_mvs.c index b80ba26bb7c..5603064d723 100644 --- a/doc/examples/extract_mvs.c +++ b/doc/examples/extract_mvs.c @@ -21,6 +21,14 @@ * THE SOFTWARE. */ +/** + * @file libavcodec motion vectors extraction API usage example + * @example extract_mvs.c + * + * Read from input file, decode video stream and print a motion vectors + * representation to stdout. + */ + #include #include #include diff --git a/doc/examples/filter_audio.c b/doc/examples/filter_audio.c index f53e52562b8..9e4039b9000 100644 --- a/doc/examples/filter_audio.c +++ b/doc/examples/filter_audio.c @@ -19,13 +19,11 @@ */ /** - * @file - * libavfilter API usage example. - * + * @file libavfilter audio filtering API usage example * @example filter_audio.c - * This example will generate a sine wave audio, - * pass it through a simple filter chain, and then compute the MD5 checksum of - * the output data. + * + * This example will generate a sine wave audio, pass it through a simple filter + * chain, and then compute the MD5 checksum of the output data. * * The filter chain it uses is: * (input) -> abuffer -> volume -> aformat -> abuffersink -> (output) diff --git a/doc/examples/hw_decode.c b/doc/examples/hw_decode.c index 0d23f451e69..6a4a4fb83d5 100644 --- a/doc/examples/hw_decode.c +++ b/doc/examples/hw_decode.c @@ -24,12 +24,11 @@ */ /** - * @file - * HW-Accelerated decoding example. - * + * @file HW-accelerated decoding API usage.example * @example hw_decode.c - * This example shows how to do HW-accelerated decoding with output - * frames from the HW video surfaces. + * + * Perform HW-accelerated decoding with output frames from HW video + * surfaces. */ #include diff --git a/doc/examples/mux.c b/doc/examples/mux.c index e3062c5003a..d1f682e1968 100644 --- a/doc/examples/mux.c +++ b/doc/examples/mux.c @@ -21,12 +21,11 @@ */ /** - * @file - * libavformat API example. - * - * Output a media file in any supported libavformat format. The default - * codecs are used. + * @file libavformat muxing API usage example * @example mux.c + * + * Generate a synthetic audio and video signal and mux them to a media file in + * any supported libavformat format. The default codecs are used. */ #include diff --git a/doc/examples/qsv_decode.c b/doc/examples/qsv_decode.c index 0cdef4466c8..cc2662d5bdd 100644 --- a/doc/examples/qsv_decode.c +++ b/doc/examples/qsv_decode.c @@ -21,12 +21,11 @@ */ /** - * @file - * Intel QSV-accelerated H.264 decoding example. - * + * @file Intel QSV-accelerated H.264 decoding API usage example * @example qsv_decode.c - * This example shows how to do QSV-accelerated H.264 decoding with output - * frames in the GPU video surfaces. + * + * Perform QSV-accelerated H.264 decoding with output frames in the + * GPU video surfaces, write the decoded frames to an output file. */ #include "config.h" diff --git a/doc/examples/qsv_transcode.c b/doc/examples/qsv_transcode.c index 9b37bbea9fa..7ea3ef5674b 100644 --- a/doc/examples/qsv_transcode.c +++ b/doc/examples/qsv_transcode.c @@ -1,6 +1,4 @@ /* - * Quick Sync Video (video transcoding) transcode sample - * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights @@ -21,12 +19,12 @@ */ /** - * @file - * Intel QSV-accelerated transcoding example. - * + * @file Intel QSV-accelerated video transcoding API usage example * @example qsv_transcode.c - * This example shows how to do QSV-accelerated transcoding and how to - * dynamically change encoder's option. + * + * Perform QSV-accelerated transcoding and show to dynamically change + * encoder's options. + * * Usage: qsv_transcode input_stream codec output_stream initial option * { frame_number new_option } * e.g: - qsv_transcode input.mp4 h264_qsv output_h264.mp4 "g 60" diff --git a/doc/examples/remux.c b/doc/examples/remux.c index 8855199c603..ecf30489f13 100644 --- a/doc/examples/remux.c +++ b/doc/examples/remux.c @@ -21,11 +21,11 @@ */ /** - * @file - * libavformat/libavcodec demuxing and muxing API example. - * - * Remux streams from one container format to another. + * @file libavformat/libavcodec demuxing and muxing API usage example * @example remux.c + * + * Remux streams from one container format to another. Data is copied from the + * input to the output without transcoding. */ #include diff --git a/doc/examples/resample_audio.c b/doc/examples/resample_audio.c index 890d30c934c..db9b4e5e087 100644 --- a/doc/examples/resample_audio.c +++ b/doc/examples/resample_audio.c @@ -21,8 +21,12 @@ */ /** + * @file audio resampling API usage example * @example resample_audio.c - * libswresample API use example. + * + * Generate a synthetic audio signal, and Use libswresample API to perform audio + * resampling. The output is written to a raw audio file to be played with + * ffplay. */ #include diff --git a/doc/examples/scale_video.c b/doc/examples/scale_video.c index 27cd00996d9..cb4da4a5767 100644 --- a/doc/examples/scale_video.c +++ b/doc/examples/scale_video.c @@ -21,9 +21,10 @@ */ /** - * @file - * libswscale API use example. + * @file libswscale API usage example * @example scale_video.c + * + * Generate a synthetic video signal and use libswscale to perform rescaling. */ #include diff --git a/doc/examples/show_metadata.c b/doc/examples/show_metadata.c index f7f07bf598b..abe3cc0cae3 100644 --- a/doc/examples/show_metadata.c +++ b/doc/examples/show_metadata.c @@ -21,9 +21,10 @@ */ /** - * @file - * Shows how the metadata API can be used in application programs. + * @file libavformat metadata extraction API usage example * @example show_metadata.c + * + * Show metadata from an input file. */ #include diff --git a/doc/examples/transcode.c b/doc/examples/transcode.c index b0f4fb0399b..805a028ed73 100644 --- a/doc/examples/transcode.c +++ b/doc/examples/transcode.c @@ -23,9 +23,11 @@ */ /** - * @file - * API example for demuxing, decoding, filtering, encoding and muxing + * @file demuxing, decoding, filtering, encoding and muxing API usage example * @example transcode.c + * + * Convert input to output file, applying some hard-coded filter-graph on both + * audio and video streams. */ #include diff --git a/doc/examples/transcode_aac.c b/doc/examples/transcode_aac.c index 2d4f9a59d37..bb5681a7c0a 100644 --- a/doc/examples/transcode_aac.c +++ b/doc/examples/transcode_aac.c @@ -19,12 +19,11 @@ */ /** - * @file - * Simple audio converter - * + * @file audio transcoding to MPEG/AAC API usage example * @example transcode_aac.c - * Convert an input audio file to AAC in an MP4 container using FFmpeg. - * Formats other than MP4 are supported based on the output file extension. + * + * Convert an input audio file to AAC in an MP4 container. Formats other than + * MP4 are supported based on the output file extension. * @author Andreas Unterweger (dustsigns@gmail.com) */ diff --git a/doc/examples/vaapi_encode.c b/doc/examples/vaapi_encode.c index e232fa579a1..d5f472f6dd8 100644 --- a/doc/examples/vaapi_encode.c +++ b/doc/examples/vaapi_encode.c @@ -1,6 +1,4 @@ /* - * Video Acceleration API (video encoding) encode sample - * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights @@ -21,13 +19,12 @@ */ /** - * @file - * Intel VAAPI-accelerated encoding example. - * + * @file Intel VAAPI-accelerated encoding API usage example * @example vaapi_encode.c - * This example shows how to do VAAPI-accelerated encoding. now only support NV12 - * raw file, usage like: vaapi_encode 1920 1080 input.yuv output.h264 * + * Perform VAAPI-accelerated encoding. Read input from an NV12 raw + * file, and write the H.264 encoded data to an output raw file. + * Usage: vaapi_encode 1920 1080 input.yuv output.h264 */ #include diff --git a/doc/examples/vaapi_transcode.c b/doc/examples/vaapi_transcode.c index a174bb643a7..8367cb30404 100644 --- a/doc/examples/vaapi_transcode.c +++ b/doc/examples/vaapi_transcode.c @@ -1,6 +1,4 @@ /* - * Video Acceleration API (video transcoding) transcode sample - * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights @@ -21,11 +19,10 @@ */ /** - * @file - * Intel VAAPI-accelerated transcoding example. - * + * @file Intel VAAPI-accelerated transcoding API usage example * @example vaapi_transcode.c - * This example shows how to do VAAPI-accelerated transcoding. + * + * Perform VAAPI-accelerated transcoding. * Usage: vaapi_transcode input_stream codec output_stream * e.g: - vaapi_transcode input.mp4 h264_vaapi output_h264.mp4 * - vaapi_transcode input.mp4 vp9_vaapi output_vp9.ivf From 051e1ed1e27e012045a66fd43428a685843f24b6 Mon Sep 17 00:00:00 2001 From: Stefano Sabatini Date: Sun, 15 Jan 2023 16:48:30 +0100 Subject: [PATCH 0240/2172] examples/Makefile.example: add note about missing entries --- doc/examples/Makefile.example | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/doc/examples/Makefile.example b/doc/examples/Makefile.example index 730d7e1a9ae..01712f42d94 100644 --- a/doc/examples/Makefile.example +++ b/doc/examples/Makefile.example @@ -11,6 +11,12 @@ CFLAGS += -Wall -g CFLAGS := $(shell pkg-config --cflags $(FFMPEG_LIBS)) $(CFLAGS) LDLIBS := $(shell pkg-config --libs $(FFMPEG_LIBS)) $(LDLIBS) +# missing the following targets, since they need special options in the FFmpeg build: +# qsv_decode +# qsv_transcode +# vaapi_encode +# vaapi_transcode + EXAMPLES=\ avio_http_serve_files \ avio_list_dir \ @@ -30,7 +36,7 @@ EXAMPLES=\ scale_video \ show_metadata \ transcode_aac \ - transcode \ + transcode OBJS=$(addsuffix .o,$(EXAMPLES)) From e3bbf5c17dad2005fea862fe5e882525f986592e Mon Sep 17 00:00:00 2001 From: Stefano Sabatini Date: Sat, 11 Feb 2023 18:05:29 +0100 Subject: [PATCH 0241/2172] doc/examples: fix make command, reference Makefile.example Fix regression since b25d6290c67e193. --- doc/examples/README | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/doc/examples/README b/doc/examples/README index c1ce619d350..6cb4b6e17a2 100644 --- a/doc/examples/README +++ b/doc/examples/README @@ -7,8 +7,10 @@ that you have them installed and working on your system. Method 1: build the installed examples in a generic read/write user directory -Copy to a read/write user directory and just use "make", it will link -to the libraries on your system, assuming the PKG_CONFIG_PATH is +Copy to a read/write user directory and run: +make -f Makefile.example + +It will link to the libraries on your system, assuming the PKG_CONFIG_PATH is correctly configured. Method 2: build the examples in-tree @@ -20,4 +22,4 @@ examples using "make examplesclean" If you want to try the dedicated Makefile examples (to emulate the first method), go into doc/examples and run a command such as -PKG_CONFIG_PATH=pc-uninstalled make. +PKG_CONFIG_PATH=pc-uninstalled make -f Makefile.example From b8c08021568fb8926d240279739738754c4f763c Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Tue, 31 Jan 2023 21:03:38 +0100 Subject: [PATCH 0242/2172] avcodec: add RKA decoder --- Changelog | 1 + doc/general_contents.texi | 1 + libavcodec/Makefile | 1 + libavcodec/allcodecs.c | 1 + libavcodec/codec_desc.c | 7 + libavcodec/codec_id.h | 1 + libavcodec/rka.c | 944 ++++++++++++++++++++++++++++++++++++++ libavcodec/version.h | 2 +- 8 files changed, 957 insertions(+), 1 deletion(-) create mode 100644 libavcodec/rka.c diff --git a/Changelog b/Changelog index 543eaf7fb75..b70835a7fea 100644 --- a/Changelog +++ b/Changelog @@ -41,6 +41,7 @@ version : - WavArc decoder and demuxer - CrystalHD decoders deprecated - SDNS demuxer +- RKA decoder version 5.1: diff --git a/doc/general_contents.texi b/doc/general_contents.texi index f39628de9a5..2f9ef1544de 100644 --- a/doc/general_contents.texi +++ b/doc/general_contents.texi @@ -1334,6 +1334,7 @@ following image formats are supported: @tab Real low bitrate AC-3 codec @item RealAudio Lossless @tab @tab X @item RealAudio SIPR / ACELP.NET @tab @tab X +@item RK Audio (RKA) @tab @tab X @item SBC (low-complexity subband codec) @tab X @tab X @tab Used in Bluetooth A2DP @item Shorten @tab @tab X diff --git a/libavcodec/Makefile b/libavcodec/Makefile index 4971832ff41..389253f5d08 100644 --- a/libavcodec/Makefile +++ b/libavcodec/Makefile @@ -631,6 +631,7 @@ OBJS-$(CONFIG_RASC_DECODER) += rasc.o OBJS-$(CONFIG_RAWVIDEO_DECODER) += rawdec.o OBJS-$(CONFIG_RAWVIDEO_ENCODER) += rawenc.o OBJS-$(CONFIG_REALTEXT_DECODER) += realtextdec.o ass.o +OBJS-$(CONFIG_RKA_DECODER) += rka.o OBJS-$(CONFIG_RL2_DECODER) += rl2.o OBJS-$(CONFIG_ROQ_DECODER) += roqvideodec.o roqvideo.o OBJS-$(CONFIG_ROQ_ENCODER) += roqvideoenc.o roqvideo.o elbg.o diff --git a/libavcodec/allcodecs.c b/libavcodec/allcodecs.c index b80b6983e90..e593ad19afc 100644 --- a/libavcodec/allcodecs.c +++ b/libavcodec/allcodecs.c @@ -287,6 +287,7 @@ extern const FFCodec ff_r210_decoder; extern const FFCodec ff_rasc_decoder; extern const FFCodec ff_rawvideo_encoder; extern const FFCodec ff_rawvideo_decoder; +extern const FFCodec ff_rka_decoder; extern const FFCodec ff_rl2_decoder; extern const FFCodec ff_roq_encoder; extern const FFCodec ff_roq_decoder; diff --git a/libavcodec/codec_desc.c b/libavcodec/codec_desc.c index 57d0f982116..199f62df15b 100644 --- a/libavcodec/codec_desc.c +++ b/libavcodec/codec_desc.c @@ -3360,6 +3360,13 @@ static const AVCodecDescriptor codec_descriptors[] = { .long_name = NULL_IF_CONFIG_SMALL("Waveform Archiver"), .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSLESS, }, + { + .id = AV_CODEC_ID_RKA, + .type = AVMEDIA_TYPE_AUDIO, + .name = "rka", + .long_name = NULL_IF_CONFIG_SMALL("RKA (RK Audio)"), + .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSY | AV_CODEC_PROP_LOSSLESS, + }, /* subtitle codecs */ { diff --git a/libavcodec/codec_id.h b/libavcodec/codec_id.h index ad1131b464d..89a4a0cb893 100644 --- a/libavcodec/codec_id.h +++ b/libavcodec/codec_id.h @@ -537,6 +537,7 @@ enum AVCodecID { AV_CODEC_ID_APAC, AV_CODEC_ID_FTR, AV_CODEC_ID_WAVARC, + AV_CODEC_ID_RKA, /* subtitle codecs */ AV_CODEC_ID_FIRST_SUBTITLE = 0x17000, ///< A dummy ID pointing at the start of subtitle codecs. diff --git a/libavcodec/rka.c b/libavcodec/rka.c new file mode 100644 index 00000000000..6eba3dd9211 --- /dev/null +++ b/libavcodec/rka.c @@ -0,0 +1,944 @@ +/* + * RKA decoder + * Copyright (c) 2023 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 "libavutil/channel_layout.h" +#include "libavutil/intreadwrite.h" + +#include "avcodec.h" +#include "codec_internal.h" +#include "bytestream.h" +#include "decode.h" + +typedef struct ACoder { + GetByteContext gb; + uint32_t low, high; + uint32_t value; +} ACoder; + +typedef struct FiltCoeffs { + int32_t coeffs[257]; + unsigned size; +} FiltCoeffs; + +typedef struct Model64 { + uint32_t zero[2]; + uint32_t sign[2]; + unsigned size; + int bits; + + uint16_t val4[65]; + uint16_t val1[65]; +} Model64; + +typedef struct AdaptiveModel { + int last; + int total; + int buf_size; + int16_t sum; + uint16_t aprob0; + uint16_t aprob1; + uint16_t *prob[2]; +} AdaptiveModel; + +typedef struct ChContext { + int cmode; + int cmode2; + int last_nb_decoded; + unsigned srate_pad; + unsigned pos_idx; + + AdaptiveModel *filt_size; + AdaptiveModel *filt_bits; + + int *bprob0; + int *bprob1; + + AdaptiveModel position; + AdaptiveModel fshift; + AdaptiveModel nb_segments; + AdaptiveModel coeff_bits[11]; + + Model64 mdl64[4][11]; + + int32_t buf0[12001]; + int32_t buf1[12001]; +} ChContext; + +typedef struct RKAContext { + AVClass *class; + + ACoder ac; + ChContext ch[2]; + + int bps; + int align; + int channels; + int frame_samples; + int last_nb_samples; + uint32_t total_nb_samples; + uint32_t samples_left; + + int bprob0[257]; + int bprob1[257]; + + AdaptiveModel filt_size; + AdaptiveModel filt_bits; +} RKAContext; + +static int adaptive_model_init(AdaptiveModel *am, int buf_size) +{ + am->buf_size = buf_size; + am->sum = 2000; + am->aprob0 = 0; + am->aprob1 = 0; + am->total = 0; + + if (!am->prob[0]) + am->prob[0] = av_malloc_array(buf_size + 5, sizeof(*am->prob[0])); + if (!am->prob[1]) + am->prob[1] = av_malloc_array(buf_size + 5, sizeof(*am->prob[1])); + + if (!am->prob[0] || !am->prob[1]) + return AVERROR(ENOMEM); + memset(am->prob[0], 0, (buf_size + 5) * sizeof(*am->prob[0])); + memset(am->prob[1], 0, (buf_size + 5) * sizeof(*am->prob[1])); + return 0; +} + +static void adaptive_model_free(AdaptiveModel *am) +{ + av_freep(&am->prob[0]); + av_freep(&am->prob[1]); +} + +static av_cold int rka_decode_init(AVCodecContext *avctx) +{ + RKAContext *s = avctx->priv_data; + int cmode; + + if (avctx->extradata_size < 16) + return AVERROR_INVALIDDATA; + + s->bps = avctx->bits_per_raw_sample = avctx->extradata[13]; + + switch (s->bps) { + case 8: + avctx->sample_fmt = AV_SAMPLE_FMT_U8P; + break; + case 16: + avctx->sample_fmt = AV_SAMPLE_FMT_S16P; + break; + default: + return AVERROR_INVALIDDATA; + } + + s->channels = avctx->ch_layout.nb_channels; + if (s->channels < 1 || s->channels > 2) + return AVERROR_INVALIDDATA; + + s->align = (s->channels * (avctx->bits_per_raw_sample >> 3)); + s->samples_left = s->total_nb_samples = (AV_RL32(avctx->extradata + 4)) / s->align; + s->frame_samples = 131072 / s->align; + s->last_nb_samples = s->total_nb_samples % s->frame_samples; + + cmode = avctx->extradata[14] & 0xf; + if ((avctx->extradata[15] & 4) != 0) + cmode = -cmode; + + s->ch[0].cmode = s->ch[1].cmode = cmode; + s->ch[0].cmode2 = -s->ch[0].cmode; + s->ch[1].cmode2 = -s->ch[1].cmode; + av_log(avctx, AV_LOG_DEBUG, "cmode: %d\n", cmode); + + return 0; +} + +static void model64_init(Model64 *m, unsigned bits) +{ + unsigned x; + + m->bits = bits; + m->size = 64; + m->zero[0] = 1; + + x = (1 << (bits >> 1)) + 3; + x = FFMIN(x, 20); + + m->zero[1] = x; + m->sign[0] = 1; + m->sign[1] = 1; + + for (int i = 0; i < FF_ARRAY_ELEMS(m->val4); i++) { + m->val4[i] = 4; + m->val1[i] = 1; + } +} + +static int chctx_init(RKAContext *s, ChContext *c, + int sample_rate, int bps) +{ + int ret; + + memset(c->buf0, 0, sizeof(c->buf0)); + memset(c->buf1, 0, sizeof(c->buf1)); + + c->filt_size = &s->filt_size; + c->filt_bits = &s->filt_bits; + + c->bprob0 = s->bprob0; + c->bprob1 = s->bprob1; + + c->srate_pad = (sample_rate << 13) / 44100 & 0xFFFFFFFCU; + c->pos_idx = 1; + + for (int i = 0; i < FF_ARRAY_ELEMS(s->bprob0); i++) + c->bprob0[i] = c->bprob1[i] = 1; + + for (int i = 0; i < 11; i++) { + ret = adaptive_model_init(&c->coeff_bits[i], 32); + if (ret < 0) + return ret; + + model64_init(&c->mdl64[0][i], i); + model64_init(&c->mdl64[1][i], i); + model64_init(&c->mdl64[2][i], i+1); + model64_init(&c->mdl64[3][i], i+1); + } + + ret = adaptive_model_init(c->filt_size, 256); + if (ret < 0) + return ret; + ret = adaptive_model_init(c->filt_bits, 16); + if (ret < 0) + return ret; + ret = adaptive_model_init(&c->position, 16); + if (ret < 0) + return ret; + ret = adaptive_model_init(&c->nb_segments, 8); + if (ret < 0) + return ret; + return adaptive_model_init(&c->fshift, 32); +} + +static void init_acoder(ACoder *ac) +{ + ac->low = 0x0; + ac->high = 0xffffffff; + ac->value = bytestream2_get_be32(&ac->gb); +} + +static int ac_decode_bool(ACoder *ac, int freq1, int freq2) +{ + unsigned help, add, high; + int value, low; + + low = ac->low; + help = ac->high / (unsigned)(freq2 + freq1); + value = ac->value; + add = freq1 * help; + ac->high = help; + + if (value - low >= add) { + ac->low = low = add + low; + ac->high = high = freq2 * help; + while (1) { + if ((low ^ (high + low)) > 0xFFFFFF) { + if (high > 0xFFFF) + return 1; + ac->high = (uint16_t)-(int16_t)low; + } + + if (bytestream2_get_bytes_left(&ac->gb) <= 0) + break; + ac->value = bytestream2_get_byteu(&ac->gb) | (ac->value << 8); + ac->high = high = ac->high << 8; + ac->low = low = ac->low << 8; + } + return -1; + } + + ac->high = add; + while (1) { + if ((low ^ (add + low)) > 0xFFFFFF) { + if (add > 0xFFFF) + return 0; + ac->high = (uint16_t)-(int16_t)low; + } + + if (bytestream2_get_bytes_left(&ac->gb) <= 0) + break; + ac->value = bytestream2_get_byteu(&ac->gb) | (ac->value << 8); + ac->high = add = ac->high << 8; + ac->low = low = ac->low << 8; + } + return -1; +} + +static int decode_bool(ACoder *ac, ChContext *c, int idx) +{ + int x, b; + + x = c->bprob0[idx]; + if (x + c->bprob1[idx] > 4096) { + c->bprob0[idx] = (x >> 1) + 1; + c->bprob1[idx] = (c->bprob1[idx] >> 1) + 1; + } + + b = ac_decode_bool(ac, c->bprob0[idx], c->bprob1[idx]); + if (b == 1) { + c->bprob1[idx]++; + } else if (b == 0) { + c->bprob0[idx]++; + } + + return b; +} + +static int ac_get_freq(ACoder *ac, unsigned freq, int *result) +{ + uint32_t new_high; + + if (freq == 0) + return -1; + + new_high = ac->high / freq; + ac->high = new_high; + + if (new_high == 0) + return -1; + + *result = (ac->value - ac->low) / new_high; + + return 0; +} + +static int ac_update(ACoder *ac, int freq, int mul) +{ + uint32_t low, high; + + low = ac->low = ac->high * freq + ac->low; + high = ac->high = ac->high * mul; + + while (1) { + if (((high + low) ^ low) > 0xffffff) { + if (high > 0xffff) + return 0; + ac->high = (-(int16_t)low) & 0xffff; + } + + if (bytestream2_get_bytes_left(&ac->gb) <= 0) + break; + + ac->value = (ac->value << 8) | bytestream2_get_byteu(&ac->gb); + low = ac->low = ac->low << 8; + high = ac->high = ac->high << 8; + } + + return -1; +} + +static void amdl_update_prob(AdaptiveModel *am, int val, int diff) +{ + am->aprob0 += diff; + if (val <= 0) { + am->prob[0][0] += diff; + } else { + do { + am->prob[0][val] += diff; + val += (val & -val); + } while (val < am->buf_size); + } +} + +static void update_ch_subobj(AdaptiveModel *am) +{ + int idx2, idx = am->buf_size - 1; + + if (idx >= 0) { + do { + uint16_t *prob = am->prob[0]; + int diff, prob_idx = prob[idx]; + + idx2 = idx - 1; + if (idx > 0) { + int idx3 = idx - 1; + + if ((idx2 & idx) != idx2) { + do { + prob_idx -= prob[idx3]; + idx3 &= idx3 - 1; + } while ((idx2 & idx) != idx3); + } + } + + diff = ((prob_idx > 0) - prob_idx) >> 1; + amdl_update_prob(am, idx, diff); + idx--; + } while (idx2 >= 0); + } + + if (am->sum < 8000) + am->sum += 200; + + am->aprob1 = (am->aprob1 + 1) >> 1; +} + +static int amdl_decode_int(AdaptiveModel *am, ACoder *ac, unsigned *dst, unsigned size) +{ + unsigned freq, size2; + int val, mul, j; + + size = FFMIN(size, am->buf_size - 1); + + if (am->aprob0 >= am->sum) + update_ch_subobj(am); + + if (am->aprob1 && (am->total == am->buf_size || + ac_decode_bool(ac, am->aprob0, am->aprob1) == 0)) { + if (am->total <= 1) { + dst[0] = am->last; + amdl_update_prob(am, dst[0], 1); + return 0; + } + if (size == am->buf_size - 1) { + freq = am->aprob0; + } else { + freq = am->prob[0][0]; + for (int j = size; j > 0; j &= (j - 1) ) + freq += am->prob[0][j]; + } + ac_get_freq(ac, freq, &freq); + size2 = am->buf_size >> 1; + val = am->prob[0][0]; + if (freq >= val) { + int sum = 0; + for (j = freq - val; size2; size2 >>= 1) { + unsigned v = am->prob[0][size2 + sum]; + if (j >= v) { + sum += size2; + j -= v; + } + } + freq = freq - j; + val = sum + 1; + } else { + freq = 0; + val = 0; + } + dst[0] = val; + mul = am->prob[0][val]; + if (val > 0) { + for (int k = val - 1; (val & (val - 1)) != k; k &= k - 1) + mul -= am->prob[0][k]; + } + ac_update(ac, freq, mul); + amdl_update_prob(am, dst[0], 1); + return 0; + } + am->aprob1++; + if (size == am->buf_size - 1) { + ac_get_freq(ac, am->buf_size - am->total, &val); + } else { + freq = 1; + for (dst[0] = 0; dst[0] < size; dst[0]++) { + if (!am->prob[1][dst[0]]) + freq++; + } + ac_get_freq(ac, freq, &val); + } + freq = 0; + dst[0] = 0; + if (val > 0 && am->buf_size > 0) { + for (dst[0] = 0; dst[0] < size & freq < val; dst[0]++) { + if (!am->prob[1][dst[0]]) + freq++; + } + } + if (am->prob[1][dst[0]]) { + do { + val = dst[0]++; + } while (val + 1 < am->buf_size && am->prob[1][val + 1]); + } + ac_update(ac, freq, 1); + am->prob[1][dst[0]]++; + am->total++; + amdl_update_prob(am, dst[0], 1); + am->last = dst[0]; + + return 0; +} + +static int decode_filt_coeffs(RKAContext *s, ChContext *ctx, ACoder *ac, FiltCoeffs *dst) +{ + unsigned val, bits; + int idx = 0; + + if (amdl_decode_int(ctx->filt_size, ac, &dst->size, 256) < 0) + return -1; + + if (dst->size == 0) + return 0; + + if (amdl_decode_int(ctx->filt_bits, ac, &bits, 10) < 0) + return -1; + + do { + if (((idx == 8) || (idx == 20)) && (0 < bits)) + bits--; + + if (bits > 10) + return -1; + + if (amdl_decode_int(&ctx->coeff_bits[bits], ac, &val, 31) < 0) + return -1; + + if (val == 31) { + ac_get_freq(ac, 65536, &val); + ac_update(ac, val, 1); + } + + if (val == 0) { + dst->coeffs[idx++] = 0; + } else { + unsigned freq = 0; + int sign; + + if (bits > 0) { + ac_get_freq(ac, 1 << bits, &freq); + ac_update(ac, freq, 1); + } + dst->coeffs[idx] = freq + 1 + ((val - 1U) << bits); + sign = decode_bool(ac, ctx, idx); + if (sign < 0) + return -1; + if (sign == 1) + dst->coeffs[idx] = -dst->coeffs[idx]; + idx++; + } + } while (idx < dst->size); + + return 0; +} + +static int ac_dec_bit(ACoder *ac) +{ + uint32_t high, low; + + low = ac->low; + ac->high = high = ac->high >> 1; + if (ac->value - low < high) { + do { + if (((high + low) ^ low) > 0xffffff) { + if (high > 0xffff) + return 0; + ac->high = (-(int16_t)low) & 0xffff; + } + + if (bytestream2_get_bytes_left(&ac->gb) <= 0) + break; + + ac->value = (ac->value << 8) | bytestream2_get_byteu(&ac->gb); + ac->high = high = ac->high << 8; + ac->low = low = ac->low << 8; + } while (1); + + return -1; + } + ac->low = low = low + high; + do { + if (((high + low) ^ low) > 0xffffff) { + if (high > 0xffff) + return 1; + ac->high = (-(int16_t)low) & 0xffff; + } + + if (bytestream2_get_bytes_left(&ac->gb) <= 0) + break; + + ac->value = (ac->value << 8) | bytestream2_get_byteu(&ac->gb); + ac->high = high = ac->high << 8; + ac->low = low = ac->low << 8; + } while (1); + + return -1; +} + +static int mdl64_decode(ACoder *ac, Model64 *ctx, int *dst) +{ + int sign, idx, bits; + unsigned val = 0; + + if (ctx->zero[0] + ctx->zero[1] > 4000) { + ctx->zero[0] = (ctx->zero[0] >> 1) + 1; + ctx->zero[1] = (ctx->zero[1] >> 1) + 1; + } + if (ctx->sign[0] + ctx->sign[1] > 4000) { + ctx->sign[0] = (ctx->sign[0] >> 1) + 1; + ctx->sign[1] = (ctx->sign[1] >> 1) + 1; + } + sign = ac_decode_bool(ac, ctx->zero[0], ctx->zero[1]); + if (sign == 0) { + ctx->zero[0] += 2; + dst[0] = 0; + return 0; + } else if (sign < 0) + return -1; + + ctx->zero[1] += 2; + sign = ac_decode_bool(ac, ctx->sign[0], ctx->sign[1]); + if (sign < 0) + return -1; + ctx->sign[sign]++; + bits = ctx->bits; + if (bits > 0) { + if (bits < 13) { + ac_get_freq(ac, 1 << bits, &val); + ac_update(ac, val, 1); + } else { + ac_get_freq(ac, 1 << (bits / 2), &val); + ac_update(ac, val, 1); + ac_get_freq(ac, 1 << (ctx->bits - (bits / 2)), &bits); + ac_update(ac, val, 1); + val = val + (bits << (bits / 2)); + } + } + bits = ctx->size; + idx = 0; + if (bits >= 0) { + do { + uint16_t *val4 = ctx->val4; + int b; + + if (val4[idx] + ctx->val1[idx] > 2000U) { + val4[idx] = (val4[idx] >> 1) + 1; + ctx->val1[idx] = (ctx->val1[idx] >> 1) + 1; + } + b = ac_decode_bool(ac, ctx->val4[idx], ctx->val1[idx]); + if (b == 1) { + ctx->val1[idx] += 4; + break; + } else if (b < 0) { + return -1; + } + ctx->val4[idx] += 4; + idx++; + } while (idx <= ctx->size); + bits = ctx->size; + if (idx <= bits) { + dst[0] = val + 1 + (idx << ctx->bits); + if (sign) + dst[0] = -dst[0]; + return 0; + } + } + bits = bits + 1; + while (ac_dec_bit(ac) == 0) + bits = bits + 64; + ac_get_freq(ac, 64, &idx); + ac_update(ac, idx, 1); + idx += bits; + bits = val + 1 + (idx << ctx->bits); + dst[0] = bits; + if (sign) + dst[0] = -dst[0]; + + return 0; +} + +static const uint8_t tab[] = { 0, 3, 3, 2, 2, 1, 1, 1, 1 }; + +static int decode_filter(RKAContext *s, ChContext *ctx, ACoder *ac, int off, unsigned size) +{ + FiltCoeffs filt; + Model64 *mdl64; + int m = 0, split, val, last_val = 0, ret; + unsigned idx = 3, bits = 0; + + if (ctx->cmode == 0) { + if (amdl_decode_int(&ctx->fshift, ac, &bits, 15) < 0) + return -1; + bits &= 31U; + } + + ret = decode_filt_coeffs(s, ctx, ac, &filt); + if (ret < 0) + return ret; + + if (size < 512) + split = size / 2; + else + split = size >> 4; + + if (size <= 0) + return 0; + + for (int x = 0; x < size;) { + if (amdl_decode_int(&ctx->position, ac, &idx, 10) < 0) + return -1; + + idx = (ctx->pos_idx + idx) % 11; + ctx->pos_idx = idx; + + for (int y = 0; y < split; y++, off++) { + int midx, shift = idx, *src, sum = 16; + + midx = FFABS(last_val) >> shift; + if (midx >= 15) { + mdl64 = &ctx->mdl64[3][idx]; + } else if (midx >= 7) { + mdl64 = &ctx->mdl64[2][idx]; + } else if (midx >= 4) { + mdl64 = &ctx->mdl64[1][idx]; + } else { + mdl64 = &ctx->mdl64[0][idx]; + } + ret = mdl64_decode(ac, mdl64, &val); + if (ret < 0) + return -1; + last_val = val; + src = &ctx->buf1[off + -1]; + for (int i = 0; i < filt.size && i < 15; i++) + sum += filt.coeffs[i] * src[-i]; + sum = sum * 2; + for (int i = 15; i < filt.size; i++) + sum += filt.coeffs[i] * src[-i]; + sum = sum >> 6; + if (ctx->cmode == 0) { + if (bits == 0) { + ctx->buf1[off] = sum + val; + } else { + ctx->buf1[off] = (val + (sum >> bits) * (1U << bits)) + + (((1U << bits) - 1U) & ctx->buf1[off + -1]); + } + ctx->buf0[off] = ctx->buf1[off] + ctx->buf0[off + -1]; + } else { + val = val * (1 << ctx->cmode & 0x1f); + sum += ctx->buf0[off + -1] + val; + switch (s->bps) { + case 16: sum = av_clip_int16(sum); break; + case 8: sum = av_clip_int8(sum); break; + } + ctx->buf1[off] = sum - ctx->buf0[off + -1]; + ctx->buf0[off] = sum; + m += FFABS(ctx->buf1[off]); + } + } + if (ctx->cmode2 != 0) { + int sum = 0; + for (int i = (m << 6) / split; i > 0; i = i >> 1) + sum++; + sum = sum - (ctx->cmode2 + 7); + ctx->cmode = FFMAX(sum, tab[ctx->cmode2]); + } + + x += split; + } + + return 0; +} + +static int decode_samples(AVCodecContext *avctx, ACoder *ac, ChContext *ctx, int offset) +{ + RKAContext *s = avctx->priv_data; + int segment_size, offset2, mode, ret; + + ret = amdl_decode_int(&ctx->nb_segments, ac, &mode, 5); + if (ret < 0) + return ret; + + if (mode == 5) { + ret = ac_get_freq(ac, ctx->srate_pad >> 2, &segment_size); + if (ret < 0) + return ret; + ac_update(ac, segment_size, 1); + segment_size *= 4; + decode_filter(s, ctx, ac, offset, segment_size); + } else { + segment_size = ctx->srate_pad; + + if (mode) { + if (mode > 2) { + decode_filter(s, ctx, ac, offset, segment_size / 4); + offset2 = segment_size / 4 + offset; + decode_filter(s, ctx, ac, offset2, segment_size / 4); + offset2 = segment_size / 4 + offset2; + } else { + decode_filter(s, ctx, ac, offset, segment_size / 2); + offset2 = segment_size / 2 + offset; + } + if (mode & 1) { + decode_filter(s, ctx, ac, offset2, segment_size / 2); + } else { + decode_filter(s, ctx, ac, offset2, segment_size / 4); + decode_filter(s, ctx, ac, segment_size / 4 + offset2, segment_size / 4); + } + } else { + decode_filter(s, ctx, ac, offset, ctx->srate_pad); + } + } + + return segment_size; +} + +static int decode_ch_samples(AVCodecContext *avctx, ChContext *c) +{ + RKAContext *s = avctx->priv_data; + ACoder *ac = &s->ac; + int nb_decoded = 0; + + if (bytestream2_get_bytes_left(&ac->gb) <= 0) + return 0; + + memmove(c->buf0, &c->buf0[c->last_nb_decoded], 2560 * sizeof(*c->buf0)); + memmove(c->buf1, &c->buf1[c->last_nb_decoded], 2560 * sizeof(*c->buf1)); + + nb_decoded = decode_samples(avctx, ac, c, 2560); + if (nb_decoded < 0) + return nb_decoded; + c->last_nb_decoded = nb_decoded; + + return nb_decoded; +} + +static int rka_decode_frame(AVCodecContext *avctx, AVFrame *frame, + int *got_frame_ptr, AVPacket *avpkt) +{ + RKAContext *s = avctx->priv_data; + ACoder *ac = &s->ac; + int ret; + + bytestream2_init(&ac->gb, avpkt->data, avpkt->size); + init_acoder(ac); + + for (int ch = 0; ch < s->channels; ch++) { + ret = chctx_init(s, &s->ch[ch], avctx->sample_rate, + avctx->bits_per_raw_sample); + if (ret < 0) + return ret; + } + + frame->nb_samples = s->frame_samples; + if ((ret = ff_get_buffer(avctx, frame, 0)) < 0) + return ret; + + if (s->channels == 2) { + int16_t *l16 = (int16_t *)frame->extended_data[0]; + int16_t *r16 = (int16_t *)frame->extended_data[1]; + + switch (avctx->sample_fmt) { + case AV_SAMPLE_FMT_S16P: + for (int n = 0; n < frame->nb_samples;) { + ret = decode_ch_samples(avctx, &s->ch[0]); + if (ret == 0) { + frame->nb_samples = n; + break; + } + if (ret < 0 || n + ret > frame->nb_samples) + return AVERROR_INVALIDDATA; + + ret = decode_ch_samples(avctx, &s->ch[1]); + if (ret == 0) { + frame->nb_samples = n; + break; + } + if (ret < 0 || n + ret > frame->nb_samples) + return AVERROR_INVALIDDATA; + + for (int i = 0; i < ret; i++) { + int l = s->ch[0].buf0[2560 + i]; + int r = s->ch[1].buf0[2560 + i]; + + l16[n + i] = (l * 2 + r + 1) >> 1; + r16[n + i] = (l * 2 - r + 1) >> 1; + } + + n += ret; + } + break; + default: + return AVERROR_INVALIDDATA; + } + } else { + int16_t *m16 = (int16_t *)frame->data[0]; + + switch (avctx->sample_fmt) { + case AV_SAMPLE_FMT_S16P: + for (int n = 0; n < frame->nb_samples;) { + ret = decode_ch_samples(avctx, &s->ch[0]); + if (ret == 0) { + frame->nb_samples = n; + break; + } + if (ret < 0 || n + ret > frame->nb_samples) + return AVERROR_INVALIDDATA; + + for (int i = 0; i < ret; i++) { + int m = s->ch[0].buf0[2560 + i]; + + m16[n + i] = m; + } + + n += ret; + } + break; + default: + return AVERROR_INVALIDDATA; + } + } + + *got_frame_ptr = 1; + + return avpkt->size; +} + +static av_cold int rka_decode_close(AVCodecContext *avctx) +{ + RKAContext *s = avctx->priv_data; + + for (int ch = 0; ch < 2; ch++) { + ChContext *c = &s->ch[ch]; + + for (int i = 0; i < 11; i++) + adaptive_model_free(&c->coeff_bits[i]); + + adaptive_model_free(&c->position); + adaptive_model_free(&c->nb_segments); + adaptive_model_free(&c->fshift); + } + + adaptive_model_free(&s->filt_size); + adaptive_model_free(&s->filt_bits); + + return 0; +} + +const FFCodec ff_rka_decoder = { + .p.name = "rka", + CODEC_LONG_NAME("RKA (RK Audio"), + .p.type = AVMEDIA_TYPE_AUDIO, + .p.id = AV_CODEC_ID_RKA, + .priv_data_size = sizeof(RKAContext), + .init = rka_decode_init, + .close = rka_decode_close, + FF_CODEC_DECODE_CB(rka_decode_frame), + .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_CHANNEL_CONF, + .caps_internal = FF_CODEC_CAP_INIT_CLEANUP, +}; diff --git a/libavcodec/version.h b/libavcodec/version.h index 8c3d476003e..59570094574 100644 --- a/libavcodec/version.h +++ b/libavcodec/version.h @@ -29,7 +29,7 @@ #include "version_major.h" -#define LIBAVCODEC_VERSION_MINOR 0 +#define LIBAVCODEC_VERSION_MINOR 1 #define LIBAVCODEC_VERSION_MICRO 100 #define LIBAVCODEC_VERSION_INT AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \ From a13210ab398c83ecd5eba96c3fe0d93827ea80e1 Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Tue, 31 Jan 2023 19:27:09 +0100 Subject: [PATCH 0243/2172] avformat: add RKA demuxer --- Changelog | 2 +- doc/general_contents.texi | 1 + libavformat/Makefile | 1 + libavformat/allformats.c | 1 + libavformat/rka.c | 173 ++++++++++++++++++++++++++++++++++++++ libavformat/version.h | 2 +- 6 files changed, 178 insertions(+), 2 deletions(-) create mode 100644 libavformat/rka.c diff --git a/Changelog b/Changelog index b70835a7fea..cfe2b8a770e 100644 --- a/Changelog +++ b/Changelog @@ -41,7 +41,7 @@ version : - WavArc decoder and demuxer - CrystalHD decoders deprecated - SDNS demuxer -- RKA decoder +- RKA decoder and demuxer version 5.1: diff --git a/doc/general_contents.texi b/doc/general_contents.texi index 2f9ef1544de..2eeebd847da 100644 --- a/doc/general_contents.texi +++ b/doc/general_contents.texi @@ -579,6 +579,7 @@ library: @item Ogg @tab X @tab X @item Playstation Portable PMP @tab @tab X @item Portable Voice Format @tab @tab X +@item RK Audio (RKA) @tab @tab X @item TechnoTrend PVA @tab @tab X @tab Used by TechnoTrend DVB PCI boards. @item QCP @tab @tab X diff --git a/libavformat/Makefile b/libavformat/Makefile index 471e014b220..47bbbbfb2a9 100644 --- a/libavformat/Makefile +++ b/libavformat/Makefile @@ -482,6 +482,7 @@ OBJS-$(CONFIG_RAWVIDEO_DEMUXER) += rawvideodec.o OBJS-$(CONFIG_RAWVIDEO_MUXER) += rawenc.o OBJS-$(CONFIG_REALTEXT_DEMUXER) += realtextdec.o subtitles.o OBJS-$(CONFIG_REDSPARK_DEMUXER) += redspark.o +OBJS-$(CONFIG_RKA_DEMUXER) += rka.o apetag.o img2.o OBJS-$(CONFIG_RL2_DEMUXER) += rl2.o OBJS-$(CONFIG_RM_DEMUXER) += rmdec.o rm.o rmsipr.o OBJS-$(CONFIG_RM_MUXER) += rmenc.o rm.o diff --git a/libavformat/allformats.c b/libavformat/allformats.c index 8393dd34c7d..cb5b69e9cd6 100644 --- a/libavformat/allformats.c +++ b/libavformat/allformats.c @@ -381,6 +381,7 @@ extern const AVInputFormat ff_rawvideo_demuxer; extern const FFOutputFormat ff_rawvideo_muxer; extern const AVInputFormat ff_realtext_demuxer; extern const AVInputFormat ff_redspark_demuxer; +extern const AVInputFormat ff_rka_demuxer; extern const AVInputFormat ff_rl2_demuxer; extern const AVInputFormat ff_rm_demuxer; extern const FFOutputFormat ff_rm_muxer; diff --git a/libavformat/rka.c b/libavformat/rka.c new file mode 100644 index 00000000000..c1e64ebcb31 --- /dev/null +++ b/libavformat/rka.c @@ -0,0 +1,173 @@ +/* + * RKA demuxer + * Copyright (c) 2023 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 "libavutil/dict.h" +#include "libavutil/intreadwrite.h" + +#include "apetag.h" +#include "avformat.h" +#include "avio_internal.h" +#include "demux.h" +#include "internal.h" + +typedef struct RKAContext { + int total_frames, currentframe; + int frame_size; + int last_frame_size; +} RKAContext; + +static int rka_probe(const AVProbeData *p) +{ + if (AV_RL32(&p->buf[0]) == MKTAG('R', 'K', 'A', '7') && + AV_RL32(&p->buf[4]) > 0 && + AV_RL32(&p->buf[8]) > 0 && + p->buf[12] > 0 && + p->buf[12] <= 2 && + (p->buf[13] == 8 || p->buf[13] == 16) && + p->buf[15] & 2 != 0) + return AVPROBE_SCORE_EXTENSION + 30; + return 0; +} + +static int rka_read_header(AVFormatContext *s) +{ + int64_t nb_samples, size_offset; + RKAContext *c = s->priv_data; + int channels, bps, samplerate; + AVCodecParameters *par; + int64_t framepos; + AVStream *st; + int ret; + + st = avformat_new_stream(s, NULL); + if (!st) + return AVERROR(ENOMEM); + + par = st->codecpar; + ret = ff_get_extradata(s, par, s->pb, 16); + if (ret < 0) + return ret; + + nb_samples = AV_RL32(par->extradata + 4); + samplerate = AV_RL32(par->extradata + 8); + channels = par->extradata[12]; + if (channels == 0) + return AVERROR_INVALIDDATA; + bps = par->extradata[13]; + if (bps == 0) + return AVERROR_INVALIDDATA; + size_offset = avio_rl32(s->pb); + framepos = avio_tell(s->pb); + c->frame_size = 131072; + + avpriv_set_pts_info(st, 64, 1, samplerate); + st->start_time = 0; + + avio_seek(s->pb, size_offset, SEEK_SET); + c->total_frames = (nb_samples + c->frame_size - 1) / c->frame_size; + c->last_frame_size = nb_samples % c->frame_size; + + for (int i = 0; i < c->total_frames; i++) { + int r, end = 0; + int64_t size; + + if (avio_feof(s->pb)) + break; + + size = avio_rl24(s->pb); + if (size == 0) { + end = 1; + size = size_offset - framepos; + if (size <= 0) + break; + } + + if ((r = av_add_index_entry(st, framepos, (i * 131072LL) / (channels * (bps >> 3)), + size, 0, AVINDEX_KEYFRAME)) < 0) + return r; + framepos += size; + + if (end) + break; + } + + par->codec_type = AVMEDIA_TYPE_AUDIO; + par->codec_id = AV_CODEC_ID_RKA; + par->ch_layout.nb_channels = channels; + par->sample_rate = samplerate; + par->bits_per_raw_sample = bps; + st->duration = nb_samples / (channels * (bps >> 3)); + + if (s->pb->seekable & AVIO_SEEKABLE_NORMAL) + ff_ape_parse_tag(s); + + avio_seek(s->pb, 20, SEEK_SET); + + return 0; +} + +static int rka_read_packet(AVFormatContext *s, AVPacket *pkt) +{ + RKAContext *c = s->priv_data; + AVStream *st = s->streams[0]; + FFStream *const sti = ffstream(st); + int size, ret; + + if (avio_feof(s->pb)) + return AVERROR_EOF; + + if (c->currentframe >= sti->nb_index_entries) + return AVERROR_EOF; + + size = sti->index_entries[c->currentframe].size; + + ret = av_get_packet(s->pb, pkt, size); + pkt->dts = sti->index_entries[c->currentframe++].timestamp; + pkt->duration = c->currentframe == c->total_frames ? c->last_frame_size : + 131072; + return ret; +} + +static int rka_read_seek(AVFormatContext *s, int stream_index, int64_t timestamp, int flags) +{ + RKAContext *c = s->priv_data; + AVStream *st = s->streams[stream_index]; + int index = av_index_search_timestamp(st, timestamp, flags); + if (index < 0) + return -1; + if (avio_seek(s->pb, ffstream(st)->index_entries[index].pos, SEEK_SET) < 0) + return -1; + + c->currentframe = index; + + return 0; +} + +const AVInputFormat ff_rka_demuxer = { + .name = "rka", + .long_name = NULL_IF_CONFIG_SMALL("RKA (RK Audio)"), + .priv_data_size = sizeof(RKAContext), + .read_probe = rka_probe, + .read_header = rka_read_header, + .read_packet = rka_read_packet, + .read_seek = rka_read_seek, + .extensions = "rka", +}; diff --git a/libavformat/version.h b/libavformat/version.h index a7c80dc5647..904e7f06aa6 100644 --- a/libavformat/version.h +++ b/libavformat/version.h @@ -31,7 +31,7 @@ #include "version_major.h" -#define LIBAVFORMAT_VERSION_MINOR 1 +#define LIBAVFORMAT_VERSION_MINOR 2 #define LIBAVFORMAT_VERSION_MICRO 100 #define LIBAVFORMAT_VERSION_INT AV_VERSION_INT(LIBAVFORMAT_VERSION_MAJOR, \ From 2b4273072dbb1dde2ab4bbbd30b3cef4042fc4fb Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Sat, 11 Feb 2023 22:56:10 +0100 Subject: [PATCH 0244/2172] avcodec/roqaudioenc: unbreak mono encoding --- libavcodec/roqaudioenc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavcodec/roqaudioenc.c b/libavcodec/roqaudioenc.c index f0254adc700..81dccd09b58 100644 --- a/libavcodec/roqaudioenc.c +++ b/libavcodec/roqaudioenc.c @@ -174,7 +174,7 @@ static int roq_dpcm_encode_frame(AVCodecContext *avctx, AVPacket *avpkt, /* Write the actual samples */ for (i = 0; i < data_size; i++) - *out++ = dpcm_predict(&context->lastSample[i & 1], *in++); + *out++ = dpcm_predict(&context->lastSample[(i & 1) & stereo], *in++); avpkt->pts = context->input_frames <= 7 ? context->first_pts : frame->pts; avpkt->duration = data_size / channels; From 926059dbf36c00807720a9160a43b4fa13f0d6ae Mon Sep 17 00:00:00 2001 From: "J. Dekker" Date: Wed, 16 Feb 2022 02:49:29 +0100 Subject: [PATCH 0245/2172] tools: add general_assembly.pl This script generates the current general assembly voters according to the criteria of '20 commits in the last 36 months'. Signed-off-by: J. Dekker Signed-off-by: Anton Khirnov --- doc/dev_community/community.md | 3 +++ tools/general_assembly.pl | 40 ++++++++++++++++++++++++++++++++++ 2 files changed, 43 insertions(+) create mode 100644 tools/general_assembly.pl diff --git a/doc/dev_community/community.md b/doc/dev_community/community.md index 21e08e20e3b..516ca5c05e7 100644 --- a/doc/dev_community/community.md +++ b/doc/dev_community/community.md @@ -25,6 +25,9 @@ proposal by a member of the General Assembly. They are part of the GA for two years, after which they need a confirmation by the GA. +A script to generate the current members of the general assembly (minus members +voted in) can be found in `tools/general_assembly.pl`. + ## Voting Voting is done using a ranked voting system, currently running on https://vote.ffmpeg.org/ . diff --git a/tools/general_assembly.pl b/tools/general_assembly.pl new file mode 100644 index 00000000000..898a6262efd --- /dev/null +++ b/tools/general_assembly.pl @@ -0,0 +1,40 @@ +#!/usr/bin/env perl + +use warnings; +use strict; + +use POSIX qw(strftime); +use Encode qw(decode); +use Data::Dumper; + +sub trim { my $s = shift; $s =~ s/^\s+|\s+$//g; return $s }; + +my @shortlog = split /\n/, decode('UTF-8', `git log --pretty=format:"%aN <%aE>" --since="last 36 months" | sort | uniq -c | sort -r`, Encode::FB_CROAK); +my %assembly = (); + +foreach my $line (@shortlog) { + my ($count, $name, $email) = $line =~ m/^ *(\d+) *(.*?) <(.*?)>/; + if ($count < 20) { + next; + } + + $name = trim $name; + if ($count < 50) { + my $true = 0; + my @commits = split /(^|\n)commit [a-z0-9]{40}(\n|$)/, decode('UTF-8', `git log --name-only --use-mailmap --author="$email" --since="last 36 months"`, Encode::FB_CROAK); + foreach my $commit (@commits) { + $true++; # if ($commit =~ /\n[\w\/]+\.(c|h|S|asm|texi)/); + } + + if ($true < 20) { + next; + } + } + + $assembly{$name} = $email; +} + +printf("# %s %s", strftime("%Y-%m-%d", localtime), decode('UTF-8', `git rev-parse HEAD`, Encode::FB_CROAK)); +foreach my $email (sort values %assembly) { + printf("%s\n", $email); +} From 80cf509e7315bd77aad4a0cce8dd15a85e6e6ed4 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Mon, 16 Jan 2023 15:54:54 +0100 Subject: [PATCH 0246/2172] lavfi/avfilter: export process_options() Also, replace an AVFilterContext argument with a logging context+private class, as those are the only things needed in this function. Will be useful in future commits. --- libavfilter/avfilter.c | 20 ++++++++++---------- libavfilter/internal.h | 13 +++++++++++++ 2 files changed, 23 insertions(+), 10 deletions(-) diff --git a/libavfilter/avfilter.c b/libavfilter/avfilter.c index ed363351add..2f9f962f299 100644 --- a/libavfilter/avfilter.c +++ b/libavfilter/avfilter.c @@ -776,8 +776,8 @@ int ff_filter_get_nb_threads(AVFilterContext *ctx) return ctx->graph->nb_threads; } -static int process_options(AVFilterContext *ctx, AVDictionary **options, - const char *args) +int ff_filter_opt_parse(void *logctx, const AVClass *priv_class, + AVDictionary **options, const char *args) { const AVOption *o = NULL; int ret; @@ -791,8 +791,8 @@ static int process_options(AVFilterContext *ctx, AVDictionary **options, while (*args) { const char *shorthand = NULL; - if (ctx->filter->priv_class) - o = av_opt_next(ctx->priv, o); + if (priv_class) + o = av_opt_next(&priv_class, o); if (o) { if (o->type == AV_OPT_TYPE_CONST || o->offset == offset) continue; @@ -805,9 +805,9 @@ static int process_options(AVFilterContext *ctx, AVDictionary **options, &parsed_key, &value); if (ret < 0) { if (ret == AVERROR(EINVAL)) - av_log(ctx, AV_LOG_ERROR, "No option name near '%s'\n", args); + av_log(logctx, AV_LOG_ERROR, "No option name near '%s'\n", args); else - av_log(ctx, AV_LOG_ERROR, "Unable to parse '%s': %s\n", args, + av_log(logctx, AV_LOG_ERROR, "Unable to parse '%s': %s\n", args, av_err2str(ret)); return ret; } @@ -817,13 +817,13 @@ static int process_options(AVFilterContext *ctx, AVDictionary **options, key = parsed_key; /* discard all remaining shorthand */ - if (ctx->filter->priv_class) - while ((o = av_opt_next(ctx->priv, o))); + if (priv_class) + while ((o = av_opt_next(&priv_class, o))); } else { key = shorthand; } - av_log(ctx, AV_LOG_DEBUG, "Setting '%s' to value '%s'\n", key, value); + av_log(logctx, AV_LOG_DEBUG, "Setting '%s' to value '%s'\n", key, value); av_dict_set(options, key, value, AV_DICT_MULTIKEY); @@ -887,7 +887,7 @@ int avfilter_init_str(AVFilterContext *filter, const char *args) int ret = 0; if (args && *args) { - ret = process_options(filter, &options, args); + ret = ff_filter_opt_parse(filter, filter->filter->priv_class, &options, args); if (ret < 0) goto fail; } diff --git a/libavfilter/internal.h b/libavfilter/internal.h index aaf2c6c584c..2ec41917f7d 100644 --- a/libavfilter/internal.h +++ b/libavfilter/internal.h @@ -405,4 +405,17 @@ int ff_filter_process_command(AVFilterContext *ctx, const char *cmd, int ff_filter_init_hw_frames(AVFilterContext *avctx, AVFilterLink *link, int default_pool_size); +/** + * Parse filter options into a dictionary. + * + * @param logctx context for logging + * @param priv_class a filter's private class for shorthand options or NULL + * @param options dictionary to store parsed options in + * @param args options string to parse + * + * @return a non-negative number on success, a negative error code on failure + */ +int ff_filter_opt_parse(void *logctx, const AVClass *priv_class, + AVDictionary **options, const char *args); + #endif /* AVFILTER_INTERNAL_H */ From 4310b66b985e5d8f4463639c007d876e4439e7a9 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Tue, 17 Jan 2023 10:51:57 +0100 Subject: [PATCH 0247/2172] lavfi/avfilter: track whether a filter has been initialized Refuse to link uninitialized filters or initialize a filter twice. --- libavfilter/avfilter.c | 12 ++++++++++++ libavfilter/internal.h | 4 ++++ 2 files changed, 16 insertions(+) diff --git a/libavfilter/avfilter.c b/libavfilter/avfilter.c index 2f9f962f299..ec83b691bf8 100644 --- a/libavfilter/avfilter.c +++ b/libavfilter/avfilter.c @@ -158,6 +158,11 @@ int avfilter_link(AVFilterContext *src, unsigned srcpad, src->outputs[srcpad] || dst->inputs[dstpad]) return AVERROR(EINVAL); + if (!src->internal->initialized || !dst->internal->initialized) { + av_log(src, AV_LOG_ERROR, "Filters must be initialized before linking.\n"); + return AVERROR(EINVAL); + } + if (src->output_pads[srcpad].type != dst->input_pads[dstpad].type) { av_log(src, AV_LOG_ERROR, "Media type mismatch between the '%s' filter output pad %d (%s) and the '%s' filter input pad %d (%s)\n", @@ -851,6 +856,11 @@ int avfilter_init_dict(AVFilterContext *ctx, AVDictionary **options) { int ret = 0; + if (ctx->internal->initialized) { + av_log(ctx, AV_LOG_ERROR, "Filter already initialized\n"); + return AVERROR(EINVAL); + } + ret = av_opt_set_dict2(ctx, options, AV_OPT_SEARCH_CHILDREN); if (ret < 0) { av_log(ctx, AV_LOG_ERROR, "Error applying generic filter options.\n"); @@ -877,6 +887,8 @@ int avfilter_init_dict(AVFilterContext *ctx, AVDictionary **options) return ret; } + ctx->internal->initialized = 1; + return 0; } diff --git a/libavfilter/internal.h b/libavfilter/internal.h index 2ec41917f7d..8b232a8d8f9 100644 --- a/libavfilter/internal.h +++ b/libavfilter/internal.h @@ -137,6 +137,10 @@ struct AVFilterGraphInternal { struct AVFilterInternal { avfilter_execute_func *execute; + + // 1 when avfilter_init_*() was successfully called on this filter + // 0 otherwise + int initialized; }; static av_always_inline int ff_filter_execute(AVFilterContext *ctx, avfilter_action_func *func, From d1b9a3ddb4a342f4449c8f92b4238249f82533e8 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Mon, 16 Jan 2023 16:12:49 +0100 Subject: [PATCH 0248/2172] lavfi: add a new filtergraph parsing API Callers currently have two ways of adding filters to a graph - they can either - create, initialize, and link them manually - use one of the avfilter_graph_parse*() functions, which take a (typically end-user-written) string, split it into individual filter definitions+options, then create filters, apply options, initialize filters, and finally link them - all based on information from this string. A major problem with the second approach is that it performs many actions as a single atomic unit, leaving the caller no space to intervene in between. Such intervention would be useful e.g. to - modify filter options; - supply hardware device contexts; both of which typically must be done before the filter is initialized. Callers who need such intervention are then forced to invent their own filtergraph parsing, which is clearly suboptimal. This commit aims to address this problem by adding a new modular filtergraph parsing API. It adds a new avfilter_graph_segment_parse() function to parse a string filtergraph description into an intermediate tree-like representation (AVFilterGraphSegment and its children). This intermediate form may then be applied step by step using further new avfilter_graph_segment*() functions, with user intervention possible between each step. --- doc/APIchanges | 15 + libavfilter/avfilter.h | 311 +++++++++++++++++ libavfilter/graphparser.c | 679 +++++++++++++++++++++++++++++++++++++- libavfilter/version.h | 2 +- 4 files changed, 999 insertions(+), 8 deletions(-) diff --git a/doc/APIchanges b/doc/APIchanges index 810b8c07468..2c4723c6695 100644 --- a/doc/APIchanges +++ b/doc/APIchanges @@ -2,6 +2,21 @@ The last version increases of all libraries were on 2023-02-09 API changes, most recent first: +2023-02-12 - xxxxxxxxxx - lavfi 9.1.100 - avfilter.h + Add filtergraph segment parsing API. + New structs: + - AVFilterGraphSegment + - AVFilterChain + - AVFilterParams + - AVFilterPadParams + New functions: + - avfilter_graph_segment_parse() + - avfilter_graph_segment_create_filters() + - avfilter_graph_segment_apply_opts() + - avfilter_graph_segment_init() + - avfilter_graph_segment_link() + - avfilter_graph_segment_apply() + 2023-02-xx - xxxxxxxxxx - lavu 58.0.100 - csp.h Add av_csp_approximate_trc_gamma() and av_csp_trc_func_from_id(). Add av_csp_trc_function. diff --git a/libavfilter/avfilter.h b/libavfilter/avfilter.h index 333eeb31c3d..d0d45844681 100644 --- a/libavfilter/avfilter.h +++ b/libavfilter/avfilter.h @@ -1108,6 +1108,317 @@ int avfilter_graph_parse2(AVFilterGraph *graph, const char *filters, AVFilterInOut **inputs, AVFilterInOut **outputs); +/** + * Parameters of a filter's input or output pad. + * + * Created as a child of AVFilterParams by avfilter_graph_segment_parse(). + * Freed in avfilter_graph_segment_free(). + */ +typedef struct AVFilterPadParams { + /** + * An av_malloc()'ed string containing the pad label. + * + * May be av_free()'d and set to NULL by the caller, in which case this pad + * will be treated as unlabeled for linking. + * May also be replaced by another av_malloc()'ed string. + */ + char *label; +} AVFilterPadParams; + +/** + * Parameters describing a filter to be created in a filtergraph. + * + * Created as a child of AVFilterGraphSegment by avfilter_graph_segment_parse(). + * Freed in avfilter_graph_segment_free(). + */ +typedef struct AVFilterParams { + /** + * The filter context. + * + * Created by avfilter_graph_segment_create_filters() based on + * AVFilterParams.filter_name and instance_name. + * + * Callers may also create the filter context manually, then they should + * av_free() filter_name and set it to NULL. Such AVFilterParams instances + * are then skipped by avfilter_graph_segment_create_filters(). + */ + AVFilterContext *filter; + + /** + * Name of the AVFilter to be used. + * + * An av_malloc()'ed string, set by avfilter_graph_segment_parse(). Will be + * passed to avfilter_get_by_name() by + * avfilter_graph_segment_create_filters(). + * + * Callers may av_free() this string and replace it with another one or + * NULL. If the caller creates the filter instance manually, this string + * MUST be set to NULL. + * + * When both AVFilterParams.filter an AVFilterParams.filter_name are NULL, + * this AVFilterParams instance is skipped by avfilter_graph_segment_*() + * functions. + */ + char *filter_name; + /** + * Name to be used for this filter instance. + * + * An av_malloc()'ed string, may be set by avfilter_graph_segment_parse() or + * left NULL. The caller may av_free() this string and replace with another + * one or NULL. + * + * Will be used by avfilter_graph_segment_create_filters() - passed as the + * third argument to avfilter_graph_alloc_filter(), then freed and set to + * NULL. + */ + char *instance_name; + + /** + * Options to be apllied to the filter. + * + * Filled by avfilter_graph_segment_parse(). Afterwards may be freely + * modified by the caller. + * + * Will be applied to the filter by avfilter_graph_segment_apply_opts() + * with an equivalent of av_opt_set_dict2(filter, &opts, AV_OPT_SEARCH_CHILDREN), + * i.e. any unapplied options will be left in this dictionary. + */ + AVDictionary *opts; + + AVFilterPadParams **inputs; + unsigned nb_inputs; + + AVFilterPadParams **outputs; + unsigned nb_outputs; +} AVFilterParams; + +/** + * A filterchain is a list of filter specifications. + * + * Created as a child of AVFilterGraphSegment by avfilter_graph_segment_parse(). + * Freed in avfilter_graph_segment_free(). + */ +typedef struct AVFilterChain { + AVFilterParams **filters; + size_t nb_filters; +} AVFilterChain; + +/** + * A parsed representation of a filtergraph segment. + * + * A filtergraph segment is conceptually a list of filterchains, with some + * supplementary information (e.g. format conversion flags). + * + * Created by avfilter_graph_segment_parse(). Must be freed with + * avfilter_graph_segment_free(). + */ +typedef struct AVFilterGraphSegment { + /** + * The filtergraph this segment is associated with. + * Set by avfilter_graph_segment_parse(). + */ + AVFilterGraph *graph; + + /** + * A list of filter chain contained in this segment. + * Set in avfilter_graph_segment_parse(). + */ + AVFilterChain **chains; + size_t nb_chains; + + /** + * A string containing a colon-separated list of key=value options applied + * to all scale filters in this segment. + * + * May be set by avfilter_graph_segment_parse(). + * The caller may free this string with av_free() and replace it with a + * different av_malloc()'ed string. + */ + char *scale_sws_opts; +} AVFilterGraphSegment; + +/** + * Parse a textual filtergraph description into an intermediate form. + * + * This intermediate representation is intended to be modified by the caller as + * described in the documentation of AVFilterGraphSegment and its children, and + * then applied to the graph either manually or with other + * avfilter_graph_segment_*() functions. See the documentation for + * avfilter_graph_segment_apply() for the canonical way to apply + * AVFilterGraphSegment. + * + * @param graph Filter graph the parsed segment is associated with. Will only be + * used for logging and similar auxiliary purposes. The graph will + * not be actually modified by this function - the parsing results + * are instead stored in seg for further processing. + * @param graph_str a string describing the filtergraph segment + * @param flags reserved for future use, caller must set to 0 for now + * @param seg A pointer to the newly-created AVFilterGraphSegment is written + * here on success. The graph segment is owned by the caller and must + * be freed with avfilter_graph_segment_free() before graph itself is + * freed. + * + * @retval "non-negative number" success + * @retval "negative error code" failure + */ +int avfilter_graph_segment_parse(AVFilterGraph *graph, const char *graph_str, + int flags, AVFilterGraphSegment **seg); + +/** + * Create filters specified in a graph segment. + * + * Walk through the creation-pending AVFilterParams in the segment and create + * new filter instances for them. + * Creation-pending params are those where AVFilterParams.filter_name is + * non-NULL (and hence AVFilterParams.filter is NULL). All other AVFilterParams + * instances are ignored. + * + * For any filter created by this function, the corresponding + * AVFilterParams.filter is set to the newly-created filter context, + * AVFilterParams.filter_name and AVFilterParams.instance_name are freed and set + * to NULL. + * + * @param seg the filtergraph segment to process + * @param flags reserved for future use, caller must set to 0 for now + * + * @retval "non-negative number" Success, all creation-pending filters were + * successfully created + * @retval AVERROR_FILTER_NOT_FOUND some filter's name did not correspond to a + * known filter + * @retval "another negative error code" other failures + * + * @note Calling this function multiple times is safe, as it is idempotent. + */ +int avfilter_graph_segment_create_filters(AVFilterGraphSegment *seg, int flags); + +/** + * Apply parsed options to filter instances in a graph segment. + * + * Walk through all filter instances in the graph segment that have option + * dictionaries associated with them and apply those options with + * av_opt_set_dict2(..., AV_OPT_SEARCH_CHILDREN). AVFilterParams.opts is + * replaced by the dictionary output by av_opt_set_dict2(), which should be + * empty (NULL) if all options were successfully applied. + * + * If any options could not be found, this function will continue processing all + * other filters and finally return AVERROR_OPTION_NOT_FOUND (unless another + * error happens). The calling program may then deal with unapplied options as + * it wishes. + * + * Any creation-pending filters (see avfilter_graph_segment_create_filters()) + * present in the segment will cause this function to fail. AVFilterParams with + * no associated filter context are simply skipped. + * + * @param seg the filtergraph segment to process + * @param flags reserved for future use, caller must set to 0 for now + * + * @retval "non-negative number" Success, all options were successfully applied. + * @retval AVERROR_OPTION_NOT_FOUND some options were not found in a filter + * @retval "another negative error code" other failures + * + * @note Calling this function multiple times is safe, as it is idempotent. + */ +int avfilter_graph_segment_apply_opts(AVFilterGraphSegment *seg, int flags); + +/** + * Initialize all filter instances in a graph segment. + * + * Walk through all filter instances in the graph segment and call + * avfilter_init_dict(..., NULL) on those that have not been initialized yet. + * + * Any creation-pending filters (see avfilter_graph_segment_create_filters()) + * present in the segment will cause this function to fail. AVFilterParams with + * no associated filter context or whose filter context is already initialized, + * are simply skipped. + * + * @param seg the filtergraph segment to process + * @param flags reserved for future use, caller must set to 0 for now + * + * @retval "non-negative number" Success, all filter instances were successfully + * initialized + * @retval "negative error code" failure + * + * @note Calling this function multiple times is safe, as it is idempotent. + */ +int avfilter_graph_segment_init(AVFilterGraphSegment *seg, int flags); + +/** + * Link filters in a graph segment. + * + * Walk through all filter instances in the graph segment and try to link all + * unlinked input and output pads. Any creation-pending filters (see + * avfilter_graph_segment_create_filters()) present in the segment will cause + * this function to fail. Disabled filters and already linked pads are skipped. + * + * Every filter output pad that has a corresponding AVFilterPadParams with a + * non-NULL label is + * - linked to the input with the matching label, if one exists; + * - exported in the outputs linked list otherwise, with the label preserved. + * Unlabeled outputs are + * - linked to the first unlinked unlabeled input in the next non-disabled + * filter in the chain, if one exists + * - exported in the ouputs linked list otherwise, with NULL label + * + * Similarly, unlinked input pads are exported in the inputs linked list. + * + * @param seg the filtergraph segment to process + * @param flags reserved for future use, caller must set to 0 for now + * @param[out] inputs a linked list of all free (unlinked) inputs of the + * filters in this graph segment will be returned here. It + * is to be freed by the caller using avfilter_inout_free(). + * @param[out] outputs a linked list of all free (unlinked) outputs of the + * filters in this graph segment will be returned here. It + * is to be freed by the caller using avfilter_inout_free(). + * + * @retval "non-negative number" success + * @retval "negative error code" failure + * + * @note Calling this function multiple times is safe, as it is idempotent. + */ +int avfilter_graph_segment_link(AVFilterGraphSegment *seg, int flags, + AVFilterInOut **inputs, + AVFilterInOut **outputs); + +/** + * Apply all filter/link descriptions from a graph segment to the associated filtergraph. + * + * This functions is currently equivalent to calling the following in sequence: + * - avfilter_graph_segment_create_filters(); + * - avfilter_graph_segment_apply_opts(); + * - avfilter_graph_segment_init(); + * - avfilter_graph_segment_link(); + * failing if any of them fails. This list may be extended in the future. + * + * Since the above functions are idempotent, the caller may call some of them + * manually, then do some custom processing on the filtergraph, then call this + * function to do the rest. + * + * @param seg the filtergraph segment to process + * @param flags reserved for future use, caller must set to 0 for now + * @param[out] inputs passed to avfilter_graph_segment_link() + * @param[out] outputs passed to avfilter_graph_segment_link() + * + * @retval "non-negative number" success + * @retval "negative error code" failure + * + * @note Calling this function multiple times is safe, as it is idempotent. + */ +int avfilter_graph_segment_apply(AVFilterGraphSegment *seg, int flags, + AVFilterInOut **inputs, + AVFilterInOut **outputs); + +/** + * Free the provided AVFilterGraphSegment and everything associated with it. + * + * @param seg double pointer to the AVFilterGraphSegment to be freed. NULL will + * be written to this pointer on exit from this function. + * + * @note + * The filter contexts (AVFilterParams.filter) are owned by AVFilterGraph rather + * than AVFilterGraphSegment, so they are not freed. + */ +void avfilter_graph_segment_free(AVFilterGraphSegment **seg); + /** * Send a command to one or more filter instances. * diff --git a/libavfilter/graphparser.c b/libavfilter/graphparser.c index 0759c39014e..84d86a64413 100644 --- a/libavfilter/graphparser.c +++ b/libavfilter/graphparser.c @@ -24,10 +24,12 @@ #include #include "libavutil/avstring.h" +#include "libavutil/dict.h" #include "libavutil/mem.h" #include "libavutil/opt.h" #include "avfilter.h" +#include "internal.h" #define WHITESPACES " \n\t\r" @@ -386,7 +388,7 @@ static int parse_outputs(const char **buf, AVFilterInOut **curr_inputs, return pad; } -static int parse_sws_flags(const char **buf, AVFilterGraph *graph) +static int parse_sws_flags(const char **buf, char **dst, void *log_ctx) { char *p = strchr(*buf, ';'); @@ -394,16 +396,16 @@ static int parse_sws_flags(const char **buf, AVFilterGraph *graph) return 0; if (!p) { - av_log(graph, AV_LOG_ERROR, "sws_flags not terminated with ';'.\n"); + av_log(log_ctx, AV_LOG_ERROR, "sws_flags not terminated with ';'.\n"); return AVERROR(EINVAL); } *buf += 4; // keep the 'flags=' part - av_freep(&graph->scale_sws_opts); - if (!(graph->scale_sws_opts = av_mallocz(p - *buf + 1))) + av_freep(dst); + if (!(*dst = av_mallocz(p - *buf + 1))) return AVERROR(ENOMEM); - av_strlcpy(graph->scale_sws_opts, *buf, p - *buf + 1); + av_strlcpy(*dst, *buf, p - *buf + 1); *buf = p + 1; return 0; @@ -420,7 +422,7 @@ int avfilter_graph_parse2(AVFilterGraph *graph, const char *filters, filters += strspn(filters, WHITESPACES); - if ((ret = parse_sws_flags(&filters, graph)) < 0) + if ((ret = parse_sws_flags(&filters, &graph->scale_sws_opts, graph)) < 0) goto end; do { @@ -551,7 +553,7 @@ int avfilter_graph_parse_ptr(AVFilterGraph *graph, const char *filters, AVFilterInOut *open_inputs = open_inputs_ptr ? *open_inputs_ptr : NULL; AVFilterInOut *open_outputs = open_outputs_ptr ? *open_outputs_ptr : NULL; - if ((ret = parse_sws_flags(&filters, graph)) < 0) + if ((ret = parse_sws_flags(&filters, &graph->scale_sws_opts, graph)) < 0) goto end; do { @@ -623,3 +625,666 @@ int avfilter_graph_parse_ptr(AVFilterGraph *graph, const char *filters, } return ret; } + +static void pad_params_free(AVFilterPadParams **pfpp) +{ + AVFilterPadParams *fpp = *pfpp; + + if (!fpp) + return; + + av_freep(&fpp->label); + + av_freep(pfpp); +} + +static void filter_params_free(AVFilterParams **pp) +{ + AVFilterParams *p = *pp; + + if (!p) + return; + + for (unsigned i = 0; i < p->nb_inputs; i++) + pad_params_free(&p->inputs[i]); + av_freep(&p->inputs); + + for (unsigned i = 0; i < p->nb_outputs; i++) + pad_params_free(&p->outputs[i]); + av_freep(&p->outputs); + + av_dict_free(&p->opts); + + av_freep(&p->filter_name); + av_freep(&p->instance_name); + + av_freep(pp); +} + +static void chain_free(AVFilterChain **pch) +{ + AVFilterChain *ch = *pch; + + if (!ch) + return; + + for (size_t i = 0; i < ch->nb_filters; i++) + filter_params_free(&ch->filters[i]); + av_freep(&ch->filters); + + av_freep(pch); +} + +void avfilter_graph_segment_free(AVFilterGraphSegment **pseg) +{ + AVFilterGraphSegment *seg = *pseg; + + if (!seg) + return; + + for (size_t i = 0; i < seg->nb_chains; i++) + chain_free(&seg->chains[i]); + av_freep(&seg->chains); + + av_freep(&seg->scale_sws_opts); + + av_freep(pseg); +} + +static int linklabels_parse(void *logctx, const char **linklabels, + AVFilterPadParams ***res, unsigned *nb_res) +{ + AVFilterPadParams **pp = NULL; + int nb = 0; + int ret; + + while (**linklabels == '[') { + char *label; + AVFilterPadParams *par; + + label = parse_link_name(linklabels, logctx); + if (!label) { + ret = AVERROR(EINVAL); + goto fail; + } + + par = av_mallocz(sizeof(*par)); + if (!par) { + av_freep(&label); + ret = AVERROR(ENOMEM); + goto fail; + } + + par->label = label; + + ret = av_dynarray_add_nofree(&pp, &nb, par); + if (ret < 0) { + pad_params_free(&par); + goto fail; + } + + *linklabels += strspn(*linklabels, WHITESPACES); + } + + *res = pp; + *nb_res = nb; + + return 0; +fail: + for (unsigned i = 0; i < nb; i++) + pad_params_free(&pp[i]); + av_freep(&pp); + return ret; +} + +static int filter_parse(void *logctx, const char **filter, + AVFilterParams **pp) +{ + AVFilterParams *p; + char *inst_name; + int ret; + + p = av_mallocz(sizeof(*p)); + if (!p) + return AVERROR(ENOMEM); + + ret = linklabels_parse(logctx, filter, &p->inputs, &p->nb_inputs); + if (ret < 0) + goto fail; + + p->filter_name = av_get_token(filter, "=,;["); + if (!p->filter_name) { + ret = AVERROR(ENOMEM); + goto fail; + } + + inst_name = strchr(p->filter_name, '@'); + if (inst_name) { + *inst_name++ = 0; + p->instance_name = av_strdup(inst_name); + if (!p->instance_name) { + ret = AVERROR(ENOMEM); + goto fail; + } + } + + if (**filter == '=') { + const AVFilter *f = avfilter_get_by_name(p->filter_name); + char *opts; + + (*filter)++; + + opts = av_get_token(filter, "[],;"); + if (!opts) { + ret = AVERROR(ENOMEM); + goto fail; + } + + ret = ff_filter_opt_parse(logctx, f ? f->priv_class : NULL, + &p->opts, opts); + av_freep(&opts); + if (ret < 0) + goto fail; + } + + ret = linklabels_parse(logctx, filter, &p->outputs, &p->nb_outputs); + if (ret < 0) + goto fail; + + *filter += strspn(*filter, WHITESPACES); + + *pp = p; + return 0; +fail: + av_log(logctx, AV_LOG_ERROR, + "Error parsing a filter description around: %s\n", *filter); + filter_params_free(&p); + return ret; +} + +static int chain_parse(void *logctx, const char **pchain, + AVFilterChain **pch) +{ + const char *chain = *pchain; + AVFilterChain *ch; + int ret, nb_filters = 0; + + *pch = NULL; + + ch = av_mallocz(sizeof(*ch)); + if (!ch) + return AVERROR(ENOMEM); + + while (*chain) { + AVFilterParams *p; + char chr; + + ret = filter_parse(logctx, &chain, &p); + if (ret < 0) + goto fail; + + ret = av_dynarray_add_nofree(&ch->filters, &nb_filters, p); + if (ret < 0) { + filter_params_free(&p); + goto fail; + } + ch->nb_filters = nb_filters; + + // a filter ends with one of: , ; end-of-string + chr = *chain; + if (chr && chr != ',' && chr != ';') { + av_log(logctx, AV_LOG_ERROR, + "Trailing garbage after a filter: %s\n", chain); + ret = AVERROR(EINVAL); + goto fail; + } + + if (chr) { + chain++; + chain += strspn(chain, WHITESPACES); + + if (chr == ';') + break; + } + } + + *pchain = chain; + *pch = ch; + + return 0; +fail: + av_log(logctx, AV_LOG_ERROR, + "Error parsing filterchain '%s' around: %s\n", *pchain, chain); + chain_free(&ch); + return ret; +} + +int avfilter_graph_segment_parse(AVFilterGraph *graph, const char *graph_str, + int flags, AVFilterGraphSegment **pseg) +{ + AVFilterGraphSegment *seg; + int ret, nb_chains = 0; + + *pseg = NULL; + + if (flags) + return AVERROR(ENOSYS); + + seg = av_mallocz(sizeof(*seg)); + if (!seg) + return AVERROR(ENOMEM); + + seg->graph = graph; + + graph_str += strspn(graph_str, WHITESPACES); + + ret = parse_sws_flags(&graph_str, &seg->scale_sws_opts, &graph); + if (ret < 0) + goto fail; + + graph_str += strspn(graph_str, WHITESPACES); + + while (*graph_str) { + AVFilterChain *ch; + + ret = chain_parse(graph, &graph_str, &ch); + if (ret < 0) + goto fail; + + ret = av_dynarray_add_nofree(&seg->chains, &nb_chains, ch); + if (ret < 0) { + chain_free(&ch); + goto fail; + } + seg->nb_chains = nb_chains; + + graph_str += strspn(graph_str, WHITESPACES); + } + + if (!seg->nb_chains) { + av_log(graph, AV_LOG_ERROR, "No filters specified in the graph description\n"); + ret = AVERROR(EINVAL); + goto fail; + } + + *pseg = seg; + + return 0; +fail: + avfilter_graph_segment_free(&seg); + return ret; +} + +int avfilter_graph_segment_create_filters(AVFilterGraphSegment *seg, int flags) +{ + size_t idx = 0; + + if (flags) + return AVERROR(ENOSYS); + + if (seg->scale_sws_opts) { + av_freep(&seg->graph->scale_sws_opts); + seg->graph->scale_sws_opts = av_strdup(seg->scale_sws_opts); + if (!seg->graph->scale_sws_opts) + return AVERROR(ENOMEM); + } + + for (size_t i = 0; i < seg->nb_chains; i++) { + AVFilterChain *ch = seg->chains[i]; + + for (size_t j = 0; j < ch->nb_filters; j++) { + AVFilterParams *p = ch->filters[j]; + const AVFilter *f = avfilter_get_by_name(p->filter_name); + char inst_name[30], *name = p->instance_name ? p->instance_name : + inst_name; + + // skip already processed filters + if (p->filter || !p->filter_name) + continue; + + if (!f) { + av_log(seg->graph, AV_LOG_ERROR, + "No such filter: '%s'\n", p->filter_name); + return AVERROR_FILTER_NOT_FOUND; + } + + if (!p->instance_name) + snprintf(inst_name, sizeof(inst_name), "Parsed_%s_%zu", f->name, idx); + + p->filter = avfilter_graph_alloc_filter(seg->graph, f, name); + if (!p->filter) + return AVERROR(ENOMEM); + + if (!strcmp(f->name, "scale") && seg->graph->scale_sws_opts) { + int ret = av_set_options_string(p->filter, seg->graph->scale_sws_opts, + "=", ":"); + if (ret < 0) { + avfilter_free(p->filter); + p->filter = NULL; + return ret; + } + } + + av_freep(&p->filter_name); + av_freep(&p->instance_name); + + idx++; + } + } + + return 0; +} + +static int fail_creation_pending(AVFilterGraphSegment *seg, const char *fn, + const char *func) +{ + av_log(seg->graph, AV_LOG_ERROR, + "A creation-pending filter '%s' present in the segment. All filters " + "must be created or disabled before calling %s().\n", fn, func); + return AVERROR(EINVAL); +} + +int avfilter_graph_segment_apply_opts(AVFilterGraphSegment *seg, int flags) +{ + int ret, leftover_opts = 0; + + if (flags) + return AVERROR(ENOSYS); + + for (size_t i = 0; i < seg->nb_chains; i++) { + AVFilterChain *ch = seg->chains[i]; + + for (size_t j = 0; j < ch->nb_filters; j++) { + AVFilterParams *p = ch->filters[j]; + + if (p->filter_name) + return fail_creation_pending(seg, p->filter_name, __func__); + if (!p->filter || !p->opts) + continue; + + ret = av_opt_set_dict2(p->filter, &p->opts, AV_OPT_SEARCH_CHILDREN); + if (ret < 0) + return ret; + + if (av_dict_count(p->opts)) + leftover_opts = 1; + } + } + + return leftover_opts ? AVERROR_OPTION_NOT_FOUND : 0; +} + +int avfilter_graph_segment_init(AVFilterGraphSegment *seg, int flags) +{ + if (flags) + return AVERROR(ENOSYS); + + for (size_t i = 0; i < seg->nb_chains; i++) { + AVFilterChain *ch = seg->chains[i]; + + for (size_t j = 0; j < ch->nb_filters; j++) { + AVFilterParams *p = ch->filters[j]; + int ret; + + if (p->filter_name) + return fail_creation_pending(seg, p->filter_name, __func__); + if (!p->filter || p->filter->internal->initialized) + continue; + + ret = avfilter_init_dict(p->filter, NULL); + if (ret < 0) + return ret; + } + } + + return 0; +} + +static unsigned +find_linklabel(AVFilterGraphSegment *seg, const char *label, + int output, size_t idx_chain, size_t idx_filter, + AVFilterParams **pp) +{ + for (; idx_chain < seg->nb_chains; idx_chain++) { + AVFilterChain *ch = seg->chains[idx_chain]; + + for (; idx_filter < ch->nb_filters; idx_filter++) { + AVFilterParams *p = ch->filters[idx_filter]; + AVFilterPadParams **io = output ? p->outputs : p->inputs; + unsigned nb_io = output ? p->nb_outputs : p->nb_inputs; + AVFilterLink **l; + unsigned nb_l; + + if (!p->filter) + continue; + + l = output ? p->filter->outputs : p->filter->inputs; + nb_l = output ? p->filter->nb_outputs : p->filter->nb_inputs; + + for (unsigned i = 0; i < FFMIN(nb_io, nb_l); i++) + if (!l[i] && io[i]->label && !strcmp(io[i]->label, label)) { + *pp = p; + return i; + } + } + + idx_filter = 0; + } + + *pp = NULL; + return 0; +} + +static int inout_add(AVFilterInOut **inouts, AVFilterContext *f, unsigned pad_idx, + const char *label) +{ + AVFilterInOut *io = av_mallocz(sizeof(*io)); + + if (!io) + return AVERROR(ENOMEM); + + io->filter_ctx = f; + io->pad_idx = pad_idx; + + if (label) { + io->name = av_strdup(label); + if (!io->name) { + avfilter_inout_free(&io); + return AVERROR(ENOMEM); + } + } + + append_inout(inouts, &io); + + return 0; +} + +static int link_inputs(AVFilterGraphSegment *seg, size_t idx_chain, + size_t idx_filter, AVFilterInOut **inputs) +{ + AVFilterChain *ch = seg->chains[idx_chain]; + AVFilterParams *p = ch->filters[idx_filter]; + AVFilterContext *f = p->filter; + + int ret; + + if (f->nb_inputs < p->nb_inputs) { + av_log(seg->graph, AV_LOG_ERROR, + "More input link labels specified for filter '%s' than " + "it has inputs: %u > %d\n", f->filter->name, + p->nb_inputs, f->nb_inputs); + return AVERROR(EINVAL); + } + + for (unsigned in = 0; in < f->nb_inputs; in++) { + const char *label = (in < p->nb_inputs) ? p->inputs[in]->label : NULL; + + // skip already linked inputs + if (f->inputs[in]) + continue; + + if (label) { + AVFilterParams *po = NULL; + unsigned idx = find_linklabel(seg, label, 1, idx_chain, idx_filter, &po); + + if (po) { + ret = avfilter_link(po->filter, idx, f, in); + if (ret < 0) + return ret; + + continue; + } + } + + ret = inout_add(inputs, f, in, label); + if (ret < 0) + return ret; + } + + return 0; +} + +static int link_outputs(AVFilterGraphSegment *seg, size_t idx_chain, + size_t idx_filter, AVFilterInOut **outputs) +{ + AVFilterChain *ch = seg->chains[idx_chain]; + AVFilterParams *p = ch->filters[idx_filter]; + AVFilterContext *f = p->filter; + + int ret; + + if (f->nb_outputs < p->nb_outputs) { + av_log(seg->graph, AV_LOG_ERROR, + "More output link labels specified for filter '%s' than " + "it has outputs: %u > %d\n", f->filter->name, + p->nb_outputs, f->nb_outputs); + return AVERROR(EINVAL); + } + for (unsigned out = 0; out < f->nb_outputs; out++) { + char *label = (out < p->nb_outputs) ? p->outputs[out]->label : NULL; + + // skip already linked outputs + if (f->outputs[out]) + continue; + + if (label) { + AVFilterParams *po = NULL; + unsigned idx = find_linklabel(seg, label, 0, idx_chain, idx_filter, &po); + + if (po) { + ret = avfilter_link(f, out, po->filter, idx); + if (ret < 0) + return ret; + + continue; + } + } + + // if this output is unlabeled, try linking it to an unlabeled + // input in the next non-disabled filter in the chain + for (size_t i = idx_filter + 1; i < ch->nb_filters && !label; i++) { + AVFilterParams *p_next = ch->filters[i]; + + if (!p_next->filter) + continue; + + for (unsigned in = 0; in < p_next->filter->nb_inputs; in++) { + if (!p_next->filter->inputs[in] && + (in >= p_next->nb_inputs || !p_next->inputs[in]->label)) { + ret = avfilter_link(f, out, p_next->filter, in); + if (ret < 0) + return ret; + + goto cont; + } + } + break; + } + + ret = inout_add(outputs, f, out, label); + if (ret < 0) + return ret; + +cont:; + } + + return 0; +} + +int avfilter_graph_segment_link(AVFilterGraphSegment *seg, int flags, + AVFilterInOut **inputs, + AVFilterInOut **outputs) +{ + int ret; + + *inputs = NULL; + *outputs = NULL; + + if (flags) + return AVERROR(ENOSYS); + + for (size_t idx_chain = 0; idx_chain < seg->nb_chains; idx_chain++) { + AVFilterChain *ch = seg->chains[idx_chain]; + + for (size_t idx_filter = 0; idx_filter < ch->nb_filters; idx_filter++) { + AVFilterParams *p = ch->filters[idx_filter]; + + if (p->filter_name) { + ret = fail_creation_pending(seg, p->filter_name, __func__); + goto fail; + } + + if (!p->filter) + continue; + + ret = link_inputs(seg, idx_chain, idx_filter, inputs); + if (ret < 0) + goto fail; + + ret = link_outputs(seg, idx_chain, idx_filter, outputs); + if (ret < 0) + goto fail; + } + } + return 0; +fail: + avfilter_inout_free(inputs); + avfilter_inout_free(outputs); + return ret; +} + +int avfilter_graph_segment_apply(AVFilterGraphSegment *seg, int flags, + AVFilterInOut **inputs, + AVFilterInOut **outputs) +{ + int ret; + + if (flags) + return AVERROR(ENOSYS); + + ret = avfilter_graph_segment_create_filters(seg, 0); + if (ret < 0) { + av_log(seg->graph, AV_LOG_ERROR, "Error creating filters\n"); + return ret; + } + + ret = avfilter_graph_segment_apply_opts(seg, 0); + if (ret < 0) { + av_log(seg->graph, AV_LOG_ERROR, "Error applying filter options\n"); + return ret; + } + + ret = avfilter_graph_segment_init(seg, 0); + if (ret < 0) { + av_log(seg->graph, AV_LOG_ERROR, "Error initializing filters\n"); + return ret; + } + + ret = avfilter_graph_segment_link(seg, 0, inputs, outputs); + if (ret < 0) { + av_log(seg->graph, AV_LOG_ERROR, "Error linking filters\n"); + return ret; + } + + return 0; +} diff --git a/libavfilter/version.h b/libavfilter/version.h index d5a6bc143a9..1e884d9b44c 100644 --- a/libavfilter/version.h +++ b/libavfilter/version.h @@ -31,7 +31,7 @@ #include "version_major.h" -#define LIBAVFILTER_VERSION_MINOR 0 +#define LIBAVFILTER_VERSION_MINOR 1 #define LIBAVFILTER_VERSION_MICRO 100 From f17051eaae278c6683492c037e5a1658ace64bec Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Fri, 20 Jan 2023 20:13:45 +0100 Subject: [PATCH 0249/2172] lavfi/graphparser: reimplement avfilter_graph_parse* using new API --- libavfilter/graphparser.c | 537 +++++++++----------------------------- 1 file changed, 126 insertions(+), 411 deletions(-) diff --git a/libavfilter/graphparser.c b/libavfilter/graphparser.c index 84d86a64413..8e12416ccb6 100644 --- a/libavfilter/graphparser.c +++ b/libavfilter/graphparser.c @@ -33,26 +33,6 @@ #define WHITESPACES " \n\t\r" -/** - * Link two filters together. - * - * @see avfilter_link() - */ -static int link_filter(AVFilterContext *src, int srcpad, - AVFilterContext *dst, int dstpad, - void *log_ctx) -{ - int ret; - if ((ret = avfilter_link(src, srcpad, dst, dstpad))) { - av_log(log_ctx, AV_LOG_ERROR, - "Cannot create the link %s:%d -> %s:%d\n", - src->filter->name, srcpad, dst->filter->name, dstpad); - return ret; - } - - return 0; -} - /** * Parse the name of a link, which has the format "[linkname]". * @@ -87,119 +67,6 @@ static char *parse_link_name(const char **buf, void *log_ctx) return name; } -/** - * Create an instance of a filter, initialize and insert it in the - * filtergraph in *ctx. - * - * @param filt_ctx put here a filter context in case of successful creation and configuration, NULL otherwise. - * @param ctx the filtergraph context - * @param index an index which is supposed to be unique for each filter instance added to the filtergraph - * @param name the name of the filter to create, can be filter name or filter_name\@id as instance name - * @param args the arguments provided to the filter during its initialization - * @param log_ctx the log context to use - * @return >= 0 in case of success, a negative AVERROR code otherwise - */ -static int create_filter(AVFilterContext **filt_ctx, AVFilterGraph *ctx, int index, - const char *name, const char *args, void *log_ctx) -{ - const AVFilter *filt; - char name2[30]; - const char *inst_name = NULL, *filt_name = NULL; - int ret, k; - - av_strlcpy(name2, name, sizeof(name2)); - - for (k = 0; name2[k]; k++) { - if (name2[k] == '@' && name[k+1]) { - name2[k] = 0; - inst_name = name; - filt_name = name2; - break; - } - } - - if (!inst_name) { - snprintf(name2, sizeof(name2), "Parsed_%s_%d", name, index); - inst_name = name2; - filt_name = name; - } - - filt = avfilter_get_by_name(filt_name); - - if (!filt) { - av_log(log_ctx, AV_LOG_ERROR, - "No such filter: '%s'\n", filt_name); - return AVERROR(EINVAL); - } - - *filt_ctx = avfilter_graph_alloc_filter(ctx, filt, inst_name); - if (!*filt_ctx) { - av_log(log_ctx, AV_LOG_ERROR, - "Error creating filter '%s'\n", filt_name); - return AVERROR(ENOMEM); - } - - if (!strcmp(filt_name, "scale") && ctx->scale_sws_opts) { - ret = av_set_options_string(*filt_ctx, ctx->scale_sws_opts, "=", ":"); - if (ret < 0) - return ret; - } - - ret = avfilter_init_str(*filt_ctx, args); - if (ret < 0) { - av_log(log_ctx, AV_LOG_ERROR, - "Error initializing filter '%s'", filt_name); - if (args) - av_log(log_ctx, AV_LOG_ERROR, " with args '%s'", args); - av_log(log_ctx, AV_LOG_ERROR, "\n"); - avfilter_free(*filt_ctx); - *filt_ctx = NULL; - } - - return ret; -} - -/** - * Parse a string of the form FILTER_NAME[=PARAMS], and create a - * corresponding filter instance which is added to graph with - * create_filter(). - * - * @param filt_ctx Pointer that is set to the created and configured filter - * context on success, set to NULL on failure. - * @param filt_ctx put here a pointer to the created filter context on - * success, NULL otherwise - * @param buf pointer to the buffer to parse, *buf will be updated to - * point to the char next after the parsed string - * @param index an index which is assigned to the created filter - * instance, and which is supposed to be unique for each filter - * instance added to the filtergraph - * @return >= 0 in case of success, a negative AVERROR code otherwise - */ -static int parse_filter(AVFilterContext **filt_ctx, const char **buf, AVFilterGraph *graph, - int index, void *log_ctx) -{ - char *opts = NULL; - char *name = av_get_token(buf, "=,;["); - int ret; - - if (!name) - return AVERROR(ENOMEM); - - if (**buf == '=') { - (*buf)++; - opts = av_get_token(buf, "[],;"); - if (!opts) { - av_free(name); - return AVERROR(ENOMEM); - } - } - - ret = create_filter(filt_ctx, graph, index, name, opts, log_ctx); - av_free(name); - av_free(opts); - return ret; -} - AVFilterInOut *avfilter_inout_alloc(void) { return av_mallocz(sizeof(AVFilterInOut)); @@ -232,12 +99,6 @@ static AVFilterInOut *extract_inout(const char *label, AVFilterInOut **links) return ret; } -static void insert_inout(AVFilterInOut **inouts, AVFilterInOut *element) -{ - element->next = *inouts; - *inouts = element; -} - static void append_inout(AVFilterInOut **inouts, AVFilterInOut **element) { while (*inouts && (*inouts)->next) @@ -250,144 +111,6 @@ static void append_inout(AVFilterInOut **inouts, AVFilterInOut **element) *element = NULL; } -static int link_filter_inouts(AVFilterContext *filt_ctx, - AVFilterInOut **curr_inputs, - AVFilterInOut **open_inputs, void *log_ctx) -{ - int pad, ret; - - for (pad = 0; pad < filt_ctx->nb_inputs; pad++) { - AVFilterInOut *p = *curr_inputs; - - if (p) { - *curr_inputs = (*curr_inputs)->next; - p->next = NULL; - } else if (!(p = av_mallocz(sizeof(*p)))) - return AVERROR(ENOMEM); - - if (p->filter_ctx) { - ret = link_filter(p->filter_ctx, p->pad_idx, filt_ctx, pad, log_ctx); - av_freep(&p->name); - av_freep(&p); - if (ret < 0) - return ret; - } else { - p->filter_ctx = filt_ctx; - p->pad_idx = pad; - append_inout(open_inputs, &p); - } - } - - if (*curr_inputs) { - av_log(log_ctx, AV_LOG_ERROR, - "Too many inputs specified for the \"%s\" filter.\n", - filt_ctx->filter->name); - return AVERROR(EINVAL); - } - - pad = filt_ctx->nb_outputs; - while (pad--) { - AVFilterInOut *currlinkn = av_mallocz(sizeof(AVFilterInOut)); - if (!currlinkn) - return AVERROR(ENOMEM); - currlinkn->filter_ctx = filt_ctx; - currlinkn->pad_idx = pad; - insert_inout(curr_inputs, currlinkn); - } - - return 0; -} - -static int parse_inputs(const char **buf, AVFilterInOut **curr_inputs, - AVFilterInOut **open_outputs, void *log_ctx) -{ - AVFilterInOut *parsed_inputs = NULL; - int pad = 0; - - while (**buf == '[') { - char *name = parse_link_name(buf, log_ctx); - AVFilterInOut *match; - - if (!name) { - avfilter_inout_free(&parsed_inputs); - return AVERROR(EINVAL); - } - - /* First check if the label is not in the open_outputs list */ - match = extract_inout(name, open_outputs); - - if (match) { - av_free(name); - } else { - /* Not in the list, so add it as an input */ - if (!(match = av_mallocz(sizeof(AVFilterInOut)))) { - avfilter_inout_free(&parsed_inputs); - av_free(name); - return AVERROR(ENOMEM); - } - match->name = name; - match->pad_idx = pad; - } - - append_inout(&parsed_inputs, &match); - - *buf += strspn(*buf, WHITESPACES); - pad++; - } - - append_inout(&parsed_inputs, curr_inputs); - *curr_inputs = parsed_inputs; - - return pad; -} - -static int parse_outputs(const char **buf, AVFilterInOut **curr_inputs, - AVFilterInOut **open_inputs, - AVFilterInOut **open_outputs, void *log_ctx) -{ - int ret, pad = 0; - - while (**buf == '[') { - char *name = parse_link_name(buf, log_ctx); - AVFilterInOut *match; - - AVFilterInOut *input = *curr_inputs; - - if (!name) - return AVERROR(EINVAL); - - if (!input) { - av_log(log_ctx, AV_LOG_ERROR, - "No output pad can be associated to link label '%s'.\n", name); - av_free(name); - return AVERROR(EINVAL); - } - *curr_inputs = (*curr_inputs)->next; - - /* First check if the label is not in the open_inputs list */ - match = extract_inout(name, open_inputs); - - if (match) { - ret = link_filter(input->filter_ctx, input->pad_idx, - match->filter_ctx, match->pad_idx, log_ctx); - av_freep(&match->name); - av_freep(&name); - av_freep(&match); - av_freep(&input); - if (ret < 0) - return ret; - } else { - /* Not in the list, so add the first input as an open_output */ - input->name = name; - insert_inout(open_outputs, input); - } - *buf += strspn(*buf, WHITESPACES); - pad++; - } - - return pad; -} - static int parse_sws_flags(const char **buf, char **dst, void *log_ctx) { char *p = strchr(*buf, ';'); @@ -415,66 +138,24 @@ int avfilter_graph_parse2(AVFilterGraph *graph, const char *filters, AVFilterInOut **inputs, AVFilterInOut **outputs) { - int index = 0, ret = 0; - char chr = 0; - - AVFilterInOut *curr_inputs = NULL, *open_inputs = NULL, *open_outputs = NULL; - - filters += strspn(filters, WHITESPACES); - - if ((ret = parse_sws_flags(&filters, &graph->scale_sws_opts, graph)) < 0) - goto end; - - do { - AVFilterContext *filter; - filters += strspn(filters, WHITESPACES); - - if ((ret = parse_inputs(&filters, &curr_inputs, &open_outputs, graph)) < 0) - goto end; - if ((ret = parse_filter(&filter, &filters, graph, index, graph)) < 0) - goto end; - - - if ((ret = link_filter_inouts(filter, &curr_inputs, &open_inputs, graph)) < 0) - goto end; - - if ((ret = parse_outputs(&filters, &curr_inputs, &open_inputs, &open_outputs, - graph)) < 0) - goto end; - - filters += strspn(filters, WHITESPACES); - chr = *filters++; + AVFilterGraphSegment *seg; + int ret; - if (chr == ';' && curr_inputs) - append_inout(&open_outputs, &curr_inputs); - index++; - } while (chr == ',' || chr == ';'); + ret = avfilter_graph_segment_parse(graph, filters, 0, &seg); + if (ret < 0) + return ret; - if (chr) { - av_log(graph, AV_LOG_ERROR, - "Unable to parse graph description substring: \"%s\"\n", - filters - 1); - ret = AVERROR(EINVAL); + ret = avfilter_graph_segment_apply(seg, 0, inputs, outputs); + avfilter_graph_segment_free(&seg); + if (ret < 0) goto end; - } - - append_inout(&open_outputs, &curr_inputs); - - *inputs = open_inputs; - *outputs = open_outputs; return 0; end: while (graph->nb_filters) avfilter_free(graph->filters[0]); av_freep(&graph->filters); - avfilter_inout_free(&open_inputs); - avfilter_inout_free(&open_outputs); - avfilter_inout_free(&curr_inputs); - - *inputs = NULL; - *outputs = NULL; return ret; } @@ -542,90 +223,6 @@ int avfilter_graph_parse(AVFilterGraph *graph, const char *filters, return ret; } -int avfilter_graph_parse_ptr(AVFilterGraph *graph, const char *filters, - AVFilterInOut **open_inputs_ptr, AVFilterInOut **open_outputs_ptr, - void *log_ctx) -{ - int index = 0, ret = 0; - char chr = 0; - - AVFilterInOut *curr_inputs = NULL; - AVFilterInOut *open_inputs = open_inputs_ptr ? *open_inputs_ptr : NULL; - AVFilterInOut *open_outputs = open_outputs_ptr ? *open_outputs_ptr : NULL; - - if ((ret = parse_sws_flags(&filters, &graph->scale_sws_opts, graph)) < 0) - goto end; - - do { - AVFilterContext *filter; - const char *filterchain = filters; - filters += strspn(filters, WHITESPACES); - - if ((ret = parse_inputs(&filters, &curr_inputs, &open_outputs, log_ctx)) < 0) - goto end; - - if ((ret = parse_filter(&filter, &filters, graph, index, log_ctx)) < 0) - goto end; - - if (filter->nb_inputs == 1 && !curr_inputs && !index) { - /* First input pad, assume it is "[in]" if not specified */ - const char *tmp = "[in]"; - if ((ret = parse_inputs(&tmp, &curr_inputs, &open_outputs, log_ctx)) < 0) - goto end; - } - - if ((ret = link_filter_inouts(filter, &curr_inputs, &open_inputs, log_ctx)) < 0) - goto end; - - if ((ret = parse_outputs(&filters, &curr_inputs, &open_inputs, &open_outputs, - log_ctx)) < 0) - goto end; - - filters += strspn(filters, WHITESPACES); - chr = *filters++; - - if (chr == ';' && curr_inputs) { - av_log(log_ctx, AV_LOG_ERROR, - "Invalid filterchain containing an unlabelled output pad: \"%s\"\n", - filterchain); - ret = AVERROR(EINVAL); - goto end; - } - index++; - } while (chr == ',' || chr == ';'); - - if (chr) { - av_log(log_ctx, AV_LOG_ERROR, - "Unable to parse graph description substring: \"%s\"\n", - filters - 1); - ret = AVERROR(EINVAL); - goto end; - } - - if (curr_inputs) { - /* Last output pad, assume it is "[out]" if not specified */ - const char *tmp = "[out]"; - if ((ret = parse_outputs(&tmp, &curr_inputs, &open_inputs, &open_outputs, - log_ctx)) < 0) - goto end; - } - -end: - /* clear open_in/outputs only if not passed as parameters */ - if (open_inputs_ptr) *open_inputs_ptr = open_inputs; - else avfilter_inout_free(&open_inputs); - if (open_outputs_ptr) *open_outputs_ptr = open_outputs; - else avfilter_inout_free(&open_outputs); - avfilter_inout_free(&curr_inputs); - - if (ret < 0) { - while (graph->nb_filters) - avfilter_free(graph->filters[0]); - av_freep(&graph->filters); - } - return ret; -} - static void pad_params_free(AVFilterPadParams **pfpp) { AVFilterPadParams *fpp = *pfpp; @@ -1288,3 +885,121 @@ int avfilter_graph_segment_apply(AVFilterGraphSegment *seg, int flags, return 0; } + +int avfilter_graph_parse_ptr(AVFilterGraph *graph, const char *filters, + AVFilterInOut **open_inputs_ptr, AVFilterInOut **open_outputs_ptr, + void *log_ctx) +{ + AVFilterInOut *user_inputs = open_inputs_ptr ? *open_inputs_ptr : NULL; + AVFilterInOut *user_outputs = open_outputs_ptr ? *open_outputs_ptr : NULL; + + AVFilterInOut *inputs = NULL, *outputs = NULL; + AVFilterGraphSegment *seg = NULL; + AVFilterChain *ch; + AVFilterParams *p; + int ret; + + ret = avfilter_graph_segment_parse(graph, filters, 0, &seg); + if (ret < 0) + goto end; + + ret = avfilter_graph_segment_create_filters(seg, 0); + if (ret < 0) + goto end; + + ret = avfilter_graph_segment_apply_opts(seg, 0); + if (ret < 0) + goto end; + + ret = avfilter_graph_segment_init(seg, 0); + if (ret < 0) + goto end; + + /* First input pad, assume it is "[in]" if not specified */ + p = seg->chains[0]->filters[0]; + if (p->filter->nb_inputs == 1 && !p->inputs) { + const char *tmp = "[in]"; + + ret = linklabels_parse(graph, &tmp, &p->inputs, &p->nb_inputs); + if (ret < 0) + goto end; + } + + /* Last output pad, assume it is "[out]" if not specified */ + ch = seg->chains[seg->nb_chains - 1]; + p = ch->filters[ch->nb_filters - 1]; + if (p->filter->nb_outputs == 1 && !p->outputs) { + const char *tmp = "[out]"; + + ret = linklabels_parse(graph, &tmp, &p->outputs, &p->nb_outputs); + if (ret < 0) + goto end; + } + + ret = avfilter_graph_segment_apply(seg, 0, &inputs, &outputs); + avfilter_graph_segment_free(&seg); + if (ret < 0) + goto end; + + // process user-supplied inputs/outputs + while (inputs) { + AVFilterInOut *cur, *match = NULL; + + cur = inputs; + inputs = cur->next; + cur->next = NULL; + + if (cur->name) + match = extract_inout(cur->name, &user_outputs); + + if (match) { + ret = avfilter_link(match->filter_ctx, match->pad_idx, + cur->filter_ctx, cur->pad_idx); + avfilter_inout_free(&match); + avfilter_inout_free(&cur); + if (ret < 0) + goto end; + } else + append_inout(&user_inputs, &cur); + } + while (outputs) { + AVFilterInOut *cur, *match = NULL; + + cur = outputs; + outputs = cur->next; + cur->next = NULL; + + if (cur->name) + match = extract_inout(cur->name, &user_inputs); + + if (match) { + ret = avfilter_link(cur->filter_ctx, cur->pad_idx, + match->filter_ctx, match->pad_idx); + avfilter_inout_free(&match); + avfilter_inout_free(&cur); + if (ret < 0) + goto end; + } else + append_inout(&user_outputs, &cur); + } + +end: + avfilter_graph_segment_free(&seg); + + if (ret < 0) { + while (graph->nb_filters) + avfilter_free(graph->filters[0]); + av_freep(&graph->filters); + } + + /* clear open_in/outputs only if not passed as parameters */ + if (open_inputs_ptr) *open_inputs_ptr = user_inputs; + else avfilter_inout_free(&user_inputs); + if (open_outputs_ptr) *open_outputs_ptr = user_outputs; + else avfilter_inout_free(&user_outputs); + + avfilter_inout_free(&inputs); + avfilter_inout_free(&outputs); + + return ret; +} From 78f46065d861eb8487124e92ab46a459426eb89c Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Thu, 19 Jan 2023 13:54:44 +0100 Subject: [PATCH 0250/2172] fftools/ffmpeg: add special syntax for loading filter options from files Many filters accept user-provided data that is cumbersome to provide as text strings - e.g. binary files or very long text. For that reason such filters typically provide a option whose value is the path from which the filter loads the actual data. However, filters doing their own IO internally is a layering violation that the callers may not expect, and is thus best avoided. With the recently introduced graph segment parsing API, loading option values from files can now be handled by the caller. This commit makes use of the new API in ffmpeg CLI. Any option name in the filtergraph syntax can now be prefixed with a slash '/'. This will cause ffmpeg to interpret the value as the path to load the actual value from. --- Changelog | 2 + doc/filters.texi | 11 +++ fftools/ffmpeg_filter.c | 154 +++++++++++++++++++++++++++++++++++++++- 3 files changed, 165 insertions(+), 2 deletions(-) diff --git a/Changelog b/Changelog index cfe2b8a770e..d15acbe6782 100644 --- a/Changelog +++ b/Changelog @@ -42,6 +42,8 @@ version : - CrystalHD decoders deprecated - SDNS demuxer - RKA decoder and demuxer +- filtergraph syntax in ffmpeg CLI now supports passing file contents + as option values, by prefixing option name with '/' version 5.1: diff --git a/doc/filters.texi b/doc/filters.texi index 4d1eae73a6d..a4e235d2afc 100644 --- a/doc/filters.texi +++ b/doc/filters.texi @@ -171,6 +171,17 @@ within the quoted text; otherwise the argument string is considered terminated when the next special character (belonging to the set @samp{[]=;,}) is encountered. +A special syntax implemented in the @command{ffmpeg} CLI tool allows loading +option values from files. This is done be prepending a slash '/' to the option +name, then the supplied value is interpreted as a path from which the actual +value is loaded. E.g. +@example +ffmpeg -i -vf drawtext=/text=/tmp/some_text +@end example +will load the text to be drawn from @file{/tmp/some_text}. API users wishing to +implement a similar feature should use the @code{avfilter_graph_segment_*()} +functions together with custom IO code. + The name and arguments of the filter are optionally preceded and followed by a list of link labels. A link label allows one to name a link and associate it to a filter output diff --git a/fftools/ffmpeg_filter.c b/fftools/ffmpeg_filter.c index 7eb656dbe5f..1f5bbf6c4d1 100644 --- a/fftools/ffmpeg_filter.c +++ b/fftools/ffmpeg_filter.c @@ -314,6 +314,156 @@ static void init_input_filter(FilterGraph *fg, AVFilterInOut *in) ist->filters[ist->nb_filters - 1] = ifilter; } +static int read_binary(const char *path, uint8_t **data, int *len) +{ + AVIOContext *io = NULL; + int64_t fsize; + int ret; + + *data = NULL; + *len = 0; + + ret = avio_open2(&io, path, AVIO_FLAG_READ, &int_cb, NULL); + if (ret < 0) { + av_log(NULL, AV_LOG_ERROR, "Cannot open file '%s': %s\n", + path, av_err2str(ret)); + return ret; + } + + fsize = avio_size(io); + if (fsize < 0 || fsize > INT_MAX) { + av_log(NULL, AV_LOG_ERROR, "Cannot obtain size of file %s\n", path); + ret = AVERROR(EIO); + goto fail; + } + + *data = av_malloc(fsize); + if (!*data) { + ret = AVERROR(ENOMEM); + goto fail; + } + + ret = avio_read(io, *data, fsize); + if (ret != fsize) { + av_log(NULL, AV_LOG_ERROR, "Error reading file %s\n", path); + ret = ret < 0 ? ret : AVERROR(EIO); + goto fail; + } + + *len = fsize; + + return 0; +fail: + avio_close(io); + av_freep(data); + *len = 0; + return ret; +} + +static int filter_opt_apply(AVFilterContext *f, const char *key, const char *val) +{ + const AVOption *o; + int ret; + + ret = av_opt_set(f, key, val, AV_OPT_SEARCH_CHILDREN); + if (ret >= 0) + return 0; + + if (ret == AVERROR_OPTION_NOT_FOUND && key[0] == '/') + o = av_opt_find(f, key + 1, NULL, 0, AV_OPT_SEARCH_CHILDREN); + if (!o) + goto err_apply; + + // key is a valid option name prefixed with '/' + // interpret value as a path from which to load the actual option value + key++; + + if (o->type == AV_OPT_TYPE_BINARY) { + uint8_t *data; + int len; + + ret = read_binary(val, &data, &len); + if (ret < 0) + goto err_load; + + ret = av_opt_set_bin(f, key, data, len, AV_OPT_SEARCH_CHILDREN); + av_freep(&data); + } else { + char *data = file_read(val); + if (!data) { + ret = AVERROR(EIO); + goto err_load; + } + + ret = av_opt_set(f, key, data, AV_OPT_SEARCH_CHILDREN); + av_freep(&data); + } + if (ret < 0) + goto err_apply; + + return 0; + +err_apply: + av_log(NULL, AV_LOG_ERROR, + "Error applying option '%s' to filter '%s': %s\n", + key, f->filter->name, av_err2str(ret)); + return ret; +err_load: + av_log(NULL, AV_LOG_ERROR, + "Error loading value for option '%s' from file '%s'\n", + key, val); + return ret; +} + +static int graph_opts_apply(AVFilterGraphSegment *seg) +{ + for (size_t i = 0; i < seg->nb_chains; i++) { + AVFilterChain *ch = seg->chains[i]; + + for (size_t j = 0; j < ch->nb_filters; j++) { + AVFilterParams *p = ch->filters[j]; + const AVDictionaryEntry *e = NULL; + + av_assert0(p->filter); + + while ((e = av_dict_iterate(p->opts, e))) { + int ret = filter_opt_apply(p->filter, e->key, e->value); + if (ret < 0) + return ret; + } + + av_dict_free(&p->opts); + } + } + + return 0; +} + +static int graph_parse(AVFilterGraph *graph, const char *desc, + AVFilterInOut **inputs, AVFilterInOut **outputs) +{ + AVFilterGraphSegment *seg; + int ret; + + ret = avfilter_graph_segment_parse(graph, desc, 0, &seg); + if (ret < 0) + return ret; + + ret = avfilter_graph_segment_create_filters(seg, 0); + if (ret < 0) + goto fail; + + ret = graph_opts_apply(seg); + if (ret < 0) + goto fail; + + ret = avfilter_graph_segment_apply(seg, 0, inputs, outputs); + +fail: + avfilter_graph_segment_free(&seg); + return ret; +} + int init_complex_filtergraph(FilterGraph *fg) { AVFilterInOut *inputs, *outputs, *cur; @@ -327,7 +477,7 @@ int init_complex_filtergraph(FilterGraph *fg) return AVERROR(ENOMEM); graph->nb_threads = 1; - ret = avfilter_graph_parse2(graph, fg->graph_desc, &inputs, &outputs); + ret = graph_parse(graph, fg->graph_desc, &inputs, &outputs); if (ret < 0) goto fail; @@ -1004,7 +1154,7 @@ int configure_filtergraph(FilterGraph *fg) fg->graph->nb_threads = filter_complex_nbthreads; } - if ((ret = avfilter_graph_parse2(fg->graph, graph_desc, &inputs, &outputs)) < 0) + if ((ret = graph_parse(fg->graph, graph_desc, &inputs, &outputs)) < 0) goto fail; ret = hw_device_setup_for_filter(fg); From e506ea3ce1de0c782b2b833398240c8e19a02bb4 Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Mon, 6 Feb 2023 14:57:50 +0100 Subject: [PATCH 0251/2172] avfilter: use ff_inlink_make_frame_writable() --- libavfilter/avf_abitscope.c | 11 +++++-- libavfilter/avf_ahistogram.c | 9 ++++-- libavfilter/avf_aphasemeter.c | 9 ++++-- libavfilter/avf_avectorscope.c | 7 ++++- libavfilter/avf_showspectrum.c | 5 +++- libavfilter/avf_showvolume.c | 8 +++-- libavfilter/f_ebur128.c | 12 ++++++-- libavfilter/f_perms.c | 4 ++- libavfilter/framesync.c | 2 +- libavfilter/vf_cover_rect.c | 9 ++++-- libavfilter/vf_dedot.c | 2 +- libavfilter/vf_floodfill.c | 5 +++- libavfilter/vf_lensfun.c | 8 ++++- libavfilter/vf_overlay_cuda.c | 3 +- libavfilter/vf_paletteuse.c | 2 +- libavfilter/vf_photosensitivity.c | 3 +- libavfilter/vf_repeatfields.c | 49 +++++++++++++++++++++---------- libavfilter/vf_signalstats.c | 27 ++++++++++++++--- libavfilter/vf_telecine.c | 13 ++++++-- libavfilter/vf_vidstabdetect.c | 12 ++++++-- 20 files changed, 152 insertions(+), 48 deletions(-) diff --git a/libavfilter/avf_abitscope.c b/libavfilter/avf_abitscope.c index 4fc3c06ecbf..782d57e03a5 100644 --- a/libavfilter/avf_abitscope.c +++ b/libavfilter/avf_abitscope.c @@ -213,6 +213,7 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *insamples) AVFilterLink *outlink = ctx->outputs[0]; AudioBitScopeContext *s = ctx->priv; AVFrame *outpicref; + int ret; if (s->mode == 0 || !s->outpicref) { outpicref = ff_get_video_buffer(outlink, outlink->w, outlink->h); @@ -228,10 +229,16 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *insamples) } if (s->mode == 1) { - av_frame_make_writable(s->outpicref); + ret = ff_inlink_make_frame_writable(outlink, &s->outpicref); + if (ret < 0) { + av_frame_free(&insamples); + return ret; + } outpicref = av_frame_clone(s->outpicref); - if (!outpicref) + if (!outpicref) { + av_frame_free(&insamples); return AVERROR(ENOMEM); + } } outpicref->pts = av_rescale_q(insamples->pts, inlink->time_base, outlink->time_base); diff --git a/libavfilter/avf_ahistogram.c b/libavfilter/avf_ahistogram.c index c45493730dc..06490192a57 100644 --- a/libavfilter/avf_ahistogram.c +++ b/libavfilter/avf_ahistogram.c @@ -209,7 +209,7 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in) AudioHistogramContext *s = ctx->priv; const int H = s->histogram_h; const int w = s->w; - int c, y, n, p, bin; + int c, y, n, p, bin, ret; uint64_t acmax = 1; AVFrame *clone; @@ -229,7 +229,12 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in) } } - av_frame_make_writable(s->out); + ret = ff_inlink_make_frame_writable(outlink, &s->out); + if (ret < 0) { + av_frame_free(&in); + return ret; + } + if (s->dmode == SEPARATE) { for (y = 0; y < w; y++) { s->combine_buffer[3 * y ] = 0; diff --git a/libavfilter/avf_aphasemeter.c b/libavfilter/avf_aphasemeter.c index 0f7692982ca..bf9f922639b 100644 --- a/libavfilter/avf_aphasemeter.c +++ b/libavfilter/avf_aphasemeter.c @@ -29,6 +29,7 @@ #include "libavutil/parseutils.h" #include "libavutil/timestamp.h" #include "avfilter.h" +#include "filters.h" #include "formats.h" #include "audio.h" #include "video.h" @@ -246,7 +247,7 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in) float fphase = 0; AVFrame *out; uint8_t *dst; - int i; + int i, ret; int mono_measurement; int out_phase_measurement; float tolerance = 1.0f - s->tolerance; @@ -265,8 +266,12 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in) for (i = 0; i < outlink->h; i++) memset(out->data[0] + i * out->linesize[0], 0, outlink->w * 4); } else if (s->do_video) { + ret = ff_inlink_make_frame_writable(outlink, &s->out); + if (ret < 0) { + av_frame_free(&in); + return ret; + } out = s->out; - av_frame_make_writable(s->out); for (i = outlink->h - 1; i >= 10; i--) memmove(out->data[0] + (i ) * out->linesize[0], out->data[0] + (i-1) * out->linesize[0], diff --git a/libavfilter/avf_avectorscope.c b/libavfilter/avf_avectorscope.c index 3927d80b428..6e45fd95755 100644 --- a/libavfilter/avf_avectorscope.c +++ b/libavfilter/avf_avectorscope.c @@ -297,6 +297,7 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *insamples) unsigned x, y; unsigned prev_x = s->prev_x, prev_y = s->prev_y; double zoom = s->zoom; + int ret; if (!s->outpicref || s->outpicref->width != outlink->w || s->outpicref->height != outlink->h) { @@ -314,7 +315,11 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *insamples) s->outpicref->pts = av_rescale_q(insamples->pts, inlink->time_base, outlink->time_base); s->outpicref->duration = 1; - av_frame_make_writable(s->outpicref); + ret = ff_inlink_make_frame_writable(outlink, &s->outpicref); + if (ret < 0) { + av_frame_free(&insamples); + return ret; + } ff_filter_execute(ctx, fade, NULL, NULL, FFMIN(outlink->h, ff_filter_get_nb_threads(ctx))); if (zoom < 1) { diff --git a/libavfilter/avf_showspectrum.c b/libavfilter/avf_showspectrum.c index 24a424a34a0..4ce964706fa 100644 --- a/libavfilter/avf_showspectrum.c +++ b/libavfilter/avf_showspectrum.c @@ -1441,7 +1441,10 @@ static int plot_spectrum_column(AVFilterLink *inlink, AVFrame *insamples) } } - av_frame_make_writable(s->outpicref); + ret = ff_inlink_make_frame_writable(outlink, &s->outpicref); + if (ret < 0) + return ret; + outpicref = s->outpicref; /* copy to output */ if (s->orientation == VERTICAL) { if (s->sliding == SCROLL) { diff --git a/libavfilter/avf_showvolume.c b/libavfilter/avf_showvolume.c index 24d42d030d4..fa64d5237ae 100644 --- a/libavfilter/avf_showvolume.c +++ b/libavfilter/avf_showvolume.c @@ -324,7 +324,7 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *insamples) AVFilterLink *outlink = ctx->outputs[0]; ShowVolumeContext *s = ctx->priv; const int step = s->step; - int c, j, k, max_draw; + int c, j, k, max_draw, ret; char channel_name[64]; AVFrame *out; @@ -434,7 +434,11 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *insamples) out = av_frame_clone(s->out); if (!out) return AVERROR(ENOMEM); - av_frame_make_writable(out); + ret = ff_inlink_make_frame_writable(outlink, &out); + if (ret < 0) { + av_frame_free(&out); + return ret; + } /* draw volume level */ for (c = 0; c < inlink->ch_layout.nb_channels && s->h >= 8 && s->draw_volume; c++) { diff --git a/libavfilter/f_ebur128.c b/libavfilter/f_ebur128.c index 8afab37fdb4..38e7e0b2954 100644 --- a/libavfilter/f_ebur128.c +++ b/libavfilter/f_ebur128.c @@ -618,13 +618,13 @@ static int gate_update(struct integrator *integ, double power, static int filter_frame(AVFilterLink *inlink, AVFrame *insamples) { - int i, ch, idx_insample; + int i, ch, idx_insample, ret; AVFilterContext *ctx = inlink->dst; EBUR128Context *ebur128 = ctx->priv; const int nb_channels = ebur128->nb_channels; const int nb_samples = insamples->nb_samples; const double *samples = (double *)insamples->data[0]; - AVFrame *pic = ebur128->outpicref; + AVFrame *pic; #if CONFIG_SWRESAMPLE if (ebur128->peak_mode & PEAK_MODE_TRUE_PEAKS && ebur128->idx_insample == 0) { @@ -821,7 +821,13 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *insamples) y_loudness_lu_graph = lu_to_y(ebur128, loudness_3000 - ebur128->target); y_loudness_lu_gauge = lu_to_y(ebur128, gauge_value); - av_frame_make_writable(pic); + ret = ff_inlink_make_frame_writable(outlink, &ebur128->outpicref); + if (ret < 0) { + av_frame_free(&insamples); + ebur128->insamples = NULL; + return ret; + } + pic = ebur128->outpicref; /* draw the graph using the short-term loudness */ p = pic->data[0] + ebur128->graph.y*pic->linesize[0] + ebur128->graph.x*3; for (y = 0; y < ebur128->graph.h; y++) { diff --git a/libavfilter/f_perms.c b/libavfilter/f_perms.c index e26a15fd066..021652cfe81 100644 --- a/libavfilter/f_perms.c +++ b/libavfilter/f_perms.c @@ -24,6 +24,7 @@ #include "libavutil/opt.h" #include "libavutil/random_seed.h" #include "audio.h" +#include "filters.h" #include "video.h" enum mode { @@ -96,8 +97,9 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *frame) in_perm == out_perm ? " (no-op)" : ""); if (in_perm == RO && out_perm == RW) { - if ((ret = av_frame_make_writable(frame)) < 0) + if ((ret = ff_inlink_make_frame_writable(inlink, &frame)) < 0) return ret; + out = frame; } else if (in_perm == RW && out_perm == RO) { out = av_frame_clone(frame); if (!out) diff --git a/libavfilter/framesync.c b/libavfilter/framesync.c index ee91e4cf681..c748262ba6a 100644 --- a/libavfilter/framesync.c +++ b/libavfilter/framesync.c @@ -288,7 +288,7 @@ int ff_framesync_get_frame(FFFrameSync *fs, unsigned in, AVFrame **rframe, if (need_copy) { if (!(frame = av_frame_clone(frame))) return AVERROR(ENOMEM); - if ((ret = av_frame_make_writable(frame)) < 0) { + if ((ret = ff_inlink_make_frame_writable(fs->parent->inputs[in], &frame) < 0)) { av_frame_free(&frame); return ret; } diff --git a/libavfilter/vf_cover_rect.c b/libavfilter/vf_cover_rect.c index 01c9f2abbb6..642747a3516 100644 --- a/libavfilter/vf_cover_rect.c +++ b/libavfilter/vf_cover_rect.c @@ -24,6 +24,7 @@ #include "libavutil/imgutils.h" #include "libavutil/opt.h" +#include "filters.h" #include "internal.h" #include "lavfutils.h" @@ -125,7 +126,7 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in) AVFilterContext *ctx = inlink->dst; CoverContext *cover = ctx->priv; AVDictionaryEntry *ex, *ey, *ew, *eh; - int x = -1, y = -1, w = -1, h = -1; + int ret, x = -1, y = -1, w = -1, h = -1; char *xendptr = NULL, *yendptr = NULL, *wendptr = NULL, *hendptr = NULL; ex = av_dict_get(in->metadata, "lavfi.rect.x", NULL, AV_DICT_MATCH_CASE); @@ -170,7 +171,11 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in) x = av_clip(x, 0, in->width - w); y = av_clip(y, 0, in->height - h); - av_frame_make_writable(in); + ret = ff_inlink_make_frame_writable(inlink, &in); + if (ret < 0) { + av_frame_free(&in); + return ret; + } if (cover->mode == MODE_BLUR) { blur (cover, in, x, y); diff --git a/libavfilter/vf_dedot.c b/libavfilter/vf_dedot.c index a0638f45b40..6ca47c262a0 100644 --- a/libavfilter/vf_dedot.c +++ b/libavfilter/vf_dedot.c @@ -289,7 +289,7 @@ static int activate(AVFilterContext *ctx) s->frames[4]) { out = av_frame_clone(s->frames[2]); if (out && !ctx->is_disabled) { - ret = av_frame_make_writable(out); + ret = ff_inlink_make_frame_writable(inlink, &out); if (ret >= 0) { if (s->m & 1) ff_filter_execute(ctx, s->dedotcrawl, out, NULL, diff --git a/libavfilter/vf_floodfill.c b/libavfilter/vf_floodfill.c index da747c9f9f1..212255a784d 100644 --- a/libavfilter/vf_floodfill.c +++ b/libavfilter/vf_floodfill.c @@ -22,6 +22,7 @@ #include "libavutil/imgutils.h" #include "libavutil/intreadwrite.h" #include "avfilter.h" +#include "filters.h" #include "formats.h" #include "internal.h" #include "video.h" @@ -315,8 +316,10 @@ static int filter_frame(AVFilterLink *link, AVFrame *frame) s->front++; } - if (ret = av_frame_make_writable(frame)) + if (ret = ff_inlink_make_frame_writable(link, &frame)) { + av_frame_free(&frame); return ret; + } while (s->front > s->back) { int x, y; diff --git a/libavfilter/vf_lensfun.c b/libavfilter/vf_lensfun.c index 35c522a723d..f544af773e5 100644 --- a/libavfilter/vf_lensfun.c +++ b/libavfilter/vf_lensfun.c @@ -32,6 +32,7 @@ #include "libavutil/opt.h" #include "libswscale/swscale.h" #include "avfilter.h" +#include "filters.h" #include "formats.h" #include "internal.h" #include "video.h" @@ -443,9 +444,14 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in) AVFrame *out; VignettingThreadData vignetting_thread_data; DistortionCorrectionThreadData distortion_correction_thread_data; + int ret; if (lensfun->mode & VIGNETTING) { - av_frame_make_writable(in); + ret = ff_inlink_make_frame_writable(inlink, &in); + if (ret < 0) { + av_frame_free(&in); + return ret; + } vignetting_thread_data = (VignettingThreadData) { .width = inlink->w, diff --git a/libavfilter/vf_overlay_cuda.c b/libavfilter/vf_overlay_cuda.c index 68c00405fb8..b2cbb9c625d 100644 --- a/libavfilter/vf_overlay_cuda.c +++ b/libavfilter/vf_overlay_cuda.c @@ -32,6 +32,7 @@ #include "libavutil/eval.h" #include "avfilter.h" +#include "filters.h" #include "framesync.h" #include "internal.h" @@ -252,7 +253,7 @@ static int overlay_cuda_blend(FFFrameSync *fs) if (!input_overlay) return ff_filter_frame(outlink, input_main); - ret = av_frame_make_writable(input_main); + ret = ff_inlink_make_frame_writable(inlink, &input_main); if (ret < 0) { av_frame_free(&input_main); return ret; diff --git a/libavfilter/vf_paletteuse.c b/libavfilter/vf_paletteuse.c index 944ff5c74d3..5fa7a605cef 100644 --- a/libavfilter/vf_paletteuse.c +++ b/libavfilter/vf_paletteuse.c @@ -783,7 +783,7 @@ static int apply_palette(AVFilterLink *inlink, AVFrame *in, AVFrame **outf) av_frame_unref(s->last_out); if ((ret = av_frame_ref(s->last_in, in)) < 0 || (ret = av_frame_ref(s->last_out, out)) < 0 || - (ret = av_frame_make_writable(s->last_in)) < 0) { + (ret = ff_inlink_make_frame_writable(inlink, &s->last_in)) < 0) { av_frame_free(&out); *outf = NULL; return ret; diff --git a/libavfilter/vf_photosensitivity.c b/libavfilter/vf_photosensitivity.c index 1bb984cc93e..e05d4d02621 100644 --- a/libavfilter/vf_photosensitivity.c +++ b/libavfilter/vf_photosensitivity.c @@ -25,6 +25,7 @@ #include "libavutil/pixdesc.h" #include "avfilter.h" +#include "filters.h" #include "formats.h" #include "internal.h" #include "video.h" @@ -243,7 +244,7 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in) /* just duplicate the frame */ s->history[s->history_pos] = 0; /* frame was duplicated, thus, delta is zero */ } else { - res = av_frame_make_writable(s->last_frame_av); + res = ff_inlink_make_frame_writable(inlink, &s->last_frame_av); if (res) { av_frame_free(&in); return res; diff --git a/libavfilter/vf_repeatfields.c b/libavfilter/vf_repeatfields.c index 9c02c61631d..4d31f3b4f50 100644 --- a/libavfilter/vf_repeatfields.c +++ b/libavfilter/vf_repeatfields.c @@ -20,6 +20,7 @@ #include "libavutil/imgutils.h" #include "avfilter.h" +#include "filters.h" #include "internal.h" typedef struct RepeatFieldsContext { @@ -75,23 +76,23 @@ static void update_pts(AVFilterLink *link, AVFrame *f, int64_t pts, int fields) f->pts = AV_NOPTS_VALUE; } -static int filter_frame(AVFilterLink *inlink, AVFrame *in) { +static int filter_frame(AVFilterLink *inlink, AVFrame *in) +{ AVFilterContext *ctx = inlink->dst; AVFilterLink *outlink = inlink->dst->outputs[0]; RepeatFieldsContext *s = ctx->priv; - AVFrame *out; int ret, i; int state = s->state; if (!s->frame) { s->frame = av_frame_clone(in); - if (!s->frame) + if (!s->frame) { + av_frame_free(&in); return AVERROR(ENOMEM); + } s->frame->pts = AV_NOPTS_VALUE; } - out = s->frame; - if ((state == 0 && !in->top_field_first) || (state == 1 && in->top_field_first)) { av_log(ctx, AV_LOG_WARNING, "Unexpected field flags: " @@ -104,16 +105,22 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in) { AVFrame *new; new = av_frame_clone(in); - if (!new) + if (!new) { + av_frame_free(&in); return AVERROR(ENOMEM); + } ret = ff_filter_frame(outlink, new); if (in->repeat_pict) { - av_frame_make_writable(out); - update_pts(outlink, out, in->pts, 2); + ret = ff_inlink_make_frame_writable(inlink, &s->frame); + if (ret < 0) { + av_frame_free(&in); + return ret; + } + update_pts(outlink, s->frame, in->pts, 2); for (i = 0; i < s->nb_planes; i++) { - av_image_copy_plane(out->data[i], out->linesize[i] * 2, + av_image_copy_plane(s->frame->data[i], s->frame->linesize[i] * 2, in->data[i], in->linesize[i] * 2, s->linesize[i], s->planeheight[i] / 2); } @@ -121,28 +128,38 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in) { } } else { for (i = 0; i < s->nb_planes; i++) { - av_frame_make_writable(out); - av_image_copy_plane(out->data[i] + out->linesize[i], out->linesize[i] * 2, + ret = ff_inlink_make_frame_writable(inlink, &s->frame); + if (ret < 0) { + av_frame_free(&in); + return ret; + } + av_image_copy_plane(s->frame->data[i] + s->frame->linesize[i], s->frame->linesize[i] * 2, in->data[i] + in->linesize[i], in->linesize[i] * 2, s->linesize[i], s->planeheight[i] / 2); } - ret = ff_filter_frame(outlink, av_frame_clone(out)); + ret = ff_filter_frame(outlink, av_frame_clone(s->frame)); if (in->repeat_pict) { AVFrame *new; new = av_frame_clone(in); - if (!new) + if (!new) { + av_frame_free(&in); return AVERROR(ENOMEM); + } ret = ff_filter_frame(outlink, new); state = 0; } else { - av_frame_make_writable(out); - update_pts(outlink, out, in->pts, 1); + ret = ff_inlink_make_frame_writable(inlink, &s->frame); + if (ret < 0) { + av_frame_free(&in); + return ret; + } + update_pts(outlink, s->frame, in->pts, 1); for (i = 0; i < s->nb_planes; i++) { - av_image_copy_plane(out->data[i], out->linesize[i] * 2, + av_image_copy_plane(s->frame->data[i], s->frame->linesize[i] * 2, in->data[i], in->linesize[i] * 2, s->linesize[i], s->planeheight[i] / 2); } diff --git a/libavfilter/vf_signalstats.c b/libavfilter/vf_signalstats.c index e6f84be9baa..b4d10292960 100644 --- a/libavfilter/vf_signalstats.c +++ b/libavfilter/vf_signalstats.c @@ -23,6 +23,7 @@ #include "libavutil/intreadwrite.h" #include "libavutil/opt.h" #include "libavutil/pixdesc.h" +#include "filters.h" #include "internal.h" enum FilterMode { @@ -565,7 +566,7 @@ static int filter_frame8(AVFilterLink *link, AVFrame *in) int tothue = 0; int dify = 0, difu = 0, difv = 0; uint16_t masky = 0, masku = 0, maskv = 0; - + int ret; int filtot[FILT_NUMB] = {0}; AVFrame *prev; @@ -588,7 +589,16 @@ static int filter_frame8(AVFilterLink *link, AVFrame *in) if (s->outfilter != FILTER_NONE) { out = av_frame_clone(in); - av_frame_make_writable(out); + if (!out) { + av_frame_free(&in); + return AVERROR(ENOMEM); + } + ret = ff_inlink_make_frame_writable(link, &out); + if (ret < 0) { + av_frame_free(&out); + av_frame_free(&in); + return ret; + } } ff_filter_execute(ctx, compute_sat_hue_metrics8, &td_huesat, @@ -790,7 +800,7 @@ static int filter_frame16(AVFilterLink *link, AVFrame *in) int filtot[FILT_NUMB] = {0}; AVFrame *prev; - + int ret; AVFrame *sat = s->frame_sat; AVFrame *hue = s->frame_hue; const uint16_t *p_sat = (uint16_t *)sat->data[0]; @@ -810,7 +820,16 @@ static int filter_frame16(AVFilterLink *link, AVFrame *in) if (s->outfilter != FILTER_NONE) { out = av_frame_clone(in); - av_frame_make_writable(out); + if (!out) { + av_frame_free(&in); + return AVERROR(ENOMEM); + } + ret = ff_inlink_make_frame_writable(link, &out); + if (ret < 0) { + av_frame_free(&out); + av_frame_free(&in); + return ret; + } } ff_filter_execute(ctx, compute_sat_hue_metrics16, &td_huesat, diff --git a/libavfilter/vf_telecine.c b/libavfilter/vf_telecine.c index e8de63bbcfe..227de6f733c 100644 --- a/libavfilter/vf_telecine.c +++ b/libavfilter/vf_telecine.c @@ -29,6 +29,7 @@ #include "libavutil/opt.h" #include "libavutil/pixdesc.h" #include "avfilter.h" +#include "filters.h" #include "formats.h" #include "internal.h" #include "video.h" @@ -182,7 +183,11 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *inpicref) } if (s->occupied) { - av_frame_make_writable(s->frame[nout]); + ret = ff_inlink_make_frame_writable(inlink, &s->frame[nout]); + if (ret < 0) { + av_frame_free(&inpicref); + return ret; + } for (i = 0; i < s->nb_planes; i++) { // fill in the EARLIER field from the buffered pic av_image_copy_plane(s->frame[nout]->data[i] + s->frame[nout]->linesize[i] * s->first_field, @@ -208,7 +213,11 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *inpicref) while (len >= 2) { // output THIS image as-is - av_frame_make_writable(s->frame[nout]); + ret = ff_inlink_make_frame_writable(inlink, &s->frame[nout]); + if (ret < 0) { + av_frame_free(&inpicref); + return ret; + } for (i = 0; i < s->nb_planes; i++) av_image_copy_plane(s->frame[nout]->data[i], s->frame[nout]->linesize[i], inpicref->data[i], inpicref->linesize[i], diff --git a/libavfilter/vf_vidstabdetect.c b/libavfilter/vf_vidstabdetect.c index 62b998e1715..b27b1e40a67 100644 --- a/libavfilter/vf_vidstabdetect.c +++ b/libavfilter/vf_vidstabdetect.c @@ -27,6 +27,7 @@ #include "libavutil/opt.h" #include "libavutil/pixdesc.h" #include "avfilter.h" +#include "filters.h" #include "internal.h" #include "vidstabutils.h" @@ -149,10 +150,15 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in) AVFilterLink *outlink = inlink->dst->outputs[0]; VSFrame frame; - int plane; + int plane, ret; - if (s->conf.show > 0 && !av_frame_is_writable(in)) - av_frame_make_writable(in); + if (s->conf.show > 0 && !av_frame_is_writable(in)) { + ret = ff_inlink_make_frame_writable(inlink, &in); + if (ret < 0) { + av_frame_free(&in); + return ret; + } + } for (plane = 0; plane < md->fi.planes; plane++) { frame.data[plane] = in->data[plane]; From 6b6f7db81932f94876ff4bcfd2da0582b8ab897e Mon Sep 17 00:00:00 2001 From: Marton Balint Date: Tue, 24 Jan 2023 00:35:54 +0100 Subject: [PATCH 0252/2172] avcodec: add AVCodecContext.frame_num as 64 bit variant to frame_number Frame counters can overflow relatively easily (INT_MAX number of frames is slightly more than 1 year for 60 fps content), so make sure we use 64 bit values for them. Also deprecate the old 32 bit frame_number attribute. Signed-off-by: Marton Balint --- doc/APIchanges | 4 ++++ doc/examples/decode_video.c | 4 ++-- fftools/ffmpeg.c | 2 +- libavcodec/4xm.c | 8 ++++---- libavcodec/8svx.c | 2 +- libavcodec/aacenc.c | 4 ++-- libavcodec/ansi.c | 2 +- libavcodec/atrac3plus.c | 4 ++-- libavcodec/avcodec.c | 7 ++++++- libavcodec/avcodec.h | 15 +++++++++++++++ libavcodec/bfi.c | 2 +- libavcodec/cdgraphics.c | 2 +- libavcodec/cljrenc.c | 2 +- libavcodec/decode.c | 22 ++++++++++++++++------ libavcodec/dvenc.c | 2 +- libavcodec/eac3enc.c | 2 +- libavcodec/encode.c | 14 ++++++++++++-- libavcodec/evrcdec.c | 4 ++-- libavcodec/flashsv2enc.c | 16 ++++++++-------- libavcodec/flashsvenc.c | 8 ++++---- libavcodec/g2meet.c | 4 ++-- libavcodec/gif.c | 4 ++-- libavcodec/h261dec.c | 2 +- libavcodec/h264_slice.c | 2 +- libavcodec/interplayvideo.c | 8 ++++---- libavcodec/ituh263dec.c | 2 +- libavcodec/libwebpenc_animencoder.c | 2 +- libavcodec/mjpegdec.c | 2 +- libavcodec/mlpenc.c | 6 +++--- libavcodec/mpegutils.c | 2 +- libavcodec/nuv.c | 2 +- libavcodec/options_table.h | 2 +- libavcodec/opusenc.c | 2 +- libavcodec/pngenc.c | 8 ++++---- libavcodec/pthread_frame.c | 5 +++++ libavcodec/qcelpdec.c | 4 ++-- libavcodec/qtrleenc.c | 2 +- libavcodec/rv10.c | 2 +- libavcodec/smcenc.c | 2 +- libavcodec/snowenc.c | 12 ++++++------ libavcodec/svq1enc.c | 6 +++--- libavcodec/svq3.c | 4 ++-- libavcodec/version.h | 2 +- libavcodec/version_major.h | 1 + libavcodec/vp3.c | 6 +++--- libavcodec/wcmv.c | 2 +- libavcodec/wmaprodec.c | 6 +++--- libavcodec/yop.c | 2 +- tools/decode_simple.c | 6 +++--- tools/scale_slice_test.c | 4 ++-- tools/venc_data_dump.c | 2 +- 51 files changed, 146 insertions(+), 96 deletions(-) diff --git a/doc/APIchanges b/doc/APIchanges index 2c4723c6695..f3ea960415f 100644 --- a/doc/APIchanges +++ b/doc/APIchanges @@ -2,6 +2,10 @@ The last version increases of all libraries were on 2023-02-09 API changes, most recent first: +2023-02-13 - xxxxxxxxxx - lavc 60.2.100 - avcodec.h + Add AVCodecContext.frame_num as a 64bit version of frame_number. + Deprecate AVCodecContext.frame_number. + 2023-02-12 - xxxxxxxxxx - lavfi 9.1.100 - avfilter.h Add filtergraph segment parsing API. New structs: diff --git a/doc/examples/decode_video.c b/doc/examples/decode_video.c index 81ec4b50e28..b0b3a6ae928 100644 --- a/doc/examples/decode_video.c +++ b/doc/examples/decode_video.c @@ -70,12 +70,12 @@ static void decode(AVCodecContext *dec_ctx, AVFrame *frame, AVPacket *pkt, exit(1); } - printf("saving frame %3d\n", dec_ctx->frame_number); + printf("saving frame %3"PRId64"\n", dec_ctx->frame_num); fflush(stdout); /* the picture is allocated by the decoder. no need to free it */ - snprintf(buf, sizeof(buf), "%s-%d", filename, dec_ctx->frame_number); + snprintf(buf, sizeof(buf), "%s-%"PRId64, filename, dec_ctx->frame_num); pgm_save(frame->data[0], frame->linesize[0], frame->width, frame->height, buf); } diff --git a/fftools/ffmpeg.c b/fftools/ffmpeg.c index 064ec6d4b3f..d721a5e7210 100644 --- a/fftools/ffmpeg.c +++ b/fftools/ffmpeg.c @@ -2115,7 +2115,7 @@ static int decode(InputStream *ist, AVCodecContext *avctx, fd = (FrameData*)frame->opaque_ref->data; fd->pts = frame->pts; fd->tb = avctx->pkt_timebase; - fd->idx = avctx->frame_number - 1; + fd->idx = avctx->frame_num - 1; } *got_frame = 1; diff --git a/libavcodec/4xm.c b/libavcodec/4xm.c index 5636fdef2df..fab3fb5b77f 100644 --- a/libavcodec/4xm.c +++ b/libavcodec/4xm.c @@ -875,7 +875,7 @@ static int decode_frame(AVCodecContext *avctx, AVFrame *picture, } for (i = 0; i < CFRAME_BUFFER_COUNT; i++) - if (f->cfrm[i].id && f->cfrm[i].id < avctx->frame_number) + if (f->cfrm[i].id && f->cfrm[i].id < avctx->frame_num) av_log(f->avctx, AV_LOG_ERROR, "lost c frame %d\n", f->cfrm[i].id); @@ -910,9 +910,9 @@ static int decode_frame(AVCodecContext *avctx, AVFrame *picture, buf = cfrm->data; frame_size = cfrm->size; - if (id != avctx->frame_number) - av_log(f->avctx, AV_LOG_ERROR, "cframe id mismatch %d %d\n", - id, avctx->frame_number); + if (id != avctx->frame_num) + av_log(f->avctx, AV_LOG_ERROR, "cframe id mismatch %d %"PRId64"\n", + id, avctx->frame_num); if (f->version <= 1) return AVERROR_INVALIDDATA; diff --git a/libavcodec/8svx.c b/libavcodec/8svx.c index ed635f9ede3..0a6d311cf1f 100644 --- a/libavcodec/8svx.c +++ b/libavcodec/8svx.c @@ -151,7 +151,7 @@ static int eightsvx_decode_frame(AVCodecContext *avctx, AVFrame *frame, *got_frame_ptr = 1; - return ((avctx->frame_number == 0) * hdr_size + buf_size) * channels; + return ((avctx->frame_num == 0) * hdr_size + buf_size) * channels; } static av_cold int eightsvx_decode_init(AVCodecContext *avctx) diff --git a/libavcodec/aacenc.c b/libavcodec/aacenc.c index 5bc60c7390a..ed036209e92 100644 --- a/libavcodec/aacenc.c +++ b/libavcodec/aacenc.c @@ -854,7 +854,7 @@ static int aac_encode_frame(AVCodecContext *avctx, AVPacket *avpkt, if (s->psypp) ff_psy_preprocess(s->psypp, s->planar_samples, s->channels); - if (!avctx->frame_number) + if (!avctx->frame_num) return 0; start_ch = 0; @@ -958,7 +958,7 @@ static int aac_encode_frame(AVCodecContext *avctx, AVPacket *avpkt, do { init_put_bits(&s->pb, avpkt->data, avpkt->size); - if ((avctx->frame_number & 0xFF)==1 && !(avctx->flags & AV_CODEC_FLAG_BITEXACT)) + if ((avctx->frame_num & 0xFF)==1 && !(avctx->flags & AV_CODEC_FLAG_BITEXACT)) put_bitstream_info(s, LIBAVCODEC_IDENT); start_ch = 0; target_bits = 0; diff --git a/libavcodec/ansi.c b/libavcodec/ansi.c index e15c1bb0977..c1e31266ec3 100644 --- a/libavcodec/ansi.c +++ b/libavcodec/ansi.c @@ -364,7 +364,7 @@ static int decode_frame(AVCodecContext *avctx, AVFrame *rframe, if ((ret = ff_reget_buffer(avctx, s->frame, 0)) < 0) return ret; - if (!avctx->frame_number) { + if (!avctx->frame_num) { for (i=0; iheight; i++) memset(s->frame->data[0]+ i*s->frame->linesize[0], 0, avctx->width); memset(s->frame->data[1], 0, AVPALETTE_SIZE); diff --git a/libavcodec/atrac3plus.c b/libavcodec/atrac3plus.c index a0836f11784..5661654ce31 100644 --- a/libavcodec/atrac3plus.c +++ b/libavcodec/atrac3plus.c @@ -1391,9 +1391,9 @@ static int decode_band_numwavs(GetBitContext *gb, Atrac3pChanUnitCtx *ctx, if (band_has_tones[sb]) { if (ctx->waves_info->tones_index + dst[sb].num_wavs > 48) { av_log(avctx, AV_LOG_ERROR, - "Too many tones: %d (max. 48), frame: %d!\n", + "Too many tones: %d (max. 48), frame: %"PRId64"!\n", ctx->waves_info->tones_index + dst[sb].num_wavs, - avctx->frame_number); + avctx->frame_num); return AVERROR_INVALIDDATA; } dst[sb].start_index = ctx->waves_info->tones_index; diff --git a/libavcodec/avcodec.c b/libavcodec/avcodec.c index 00a58518071..fb1362290f5 100644 --- a/libavcodec/avcodec.c +++ b/libavcodec/avcodec.c @@ -266,7 +266,12 @@ FF_ENABLE_DEPRECATION_WARNINGS goto free_and_end; } - avctx->frame_number = 0; + avctx->frame_num = 0; +#if FF_API_AVCTX_FRAME_NUMBER +FF_DISABLE_DEPRECATION_WARNINGS + avctx->frame_number = avctx->frame_num; +FF_ENABLE_DEPRECATION_WARNINGS +#endif avctx->codec_descriptor = avcodec_descriptor_get(avctx->codec_id); if ((avctx->codec->capabilities & AV_CODEC_CAP_EXPERIMENTAL) && diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h index 17416791a63..39881a1d2bc 100644 --- a/libavcodec/avcodec.h +++ b/libavcodec/avcodec.h @@ -1061,6 +1061,7 @@ typedef struct AVCodecContext { */ int frame_size; +#if FF_API_AVCTX_FRAME_NUMBER /** * Frame counter, set by libavcodec. * @@ -1069,8 +1070,11 @@ typedef struct AVCodecContext { * * @note the counter is not incremented if encoding/decoding resulted in * an error. + * @deprecated use frame_num instead */ + attribute_deprecated int frame_number; +#endif /** * number of bytes per packet if constant and known or 0 @@ -2048,6 +2052,17 @@ typedef struct AVCodecContext { * The decoder can then override during decoding as needed. */ AVChannelLayout ch_layout; + + /** + * Frame counter, set by libavcodec. + * + * - decoding: total number of frames returned from the decoder so far. + * - encoding: total number of frames passed to the encoder so far. + * + * @note the counter is not incremented if encoding/decoding resulted in + * an error. + */ + int64_t frame_num; } AVCodecContext; /** diff --git a/libavcodec/bfi.c b/libavcodec/bfi.c index 2b647419c79..c2682724515 100644 --- a/libavcodec/bfi.c +++ b/libavcodec/bfi.c @@ -66,7 +66,7 @@ static int bfi_decode_frame(AVCodecContext *avctx, AVFrame *frame, bytestream2_init(&g, avpkt->data, buf_size); /* Set frame parameters and palette, if necessary */ - if (!avctx->frame_number) { + if (!avctx->frame_num) { frame->pict_type = AV_PICTURE_TYPE_I; frame->key_frame = 1; /* Setting the palette */ diff --git a/libavcodec/cdgraphics.c b/libavcodec/cdgraphics.c index 51363b6be21..431e99cd762 100644 --- a/libavcodec/cdgraphics.c +++ b/libavcodec/cdgraphics.c @@ -374,7 +374,7 @@ static void cdg_decode_flush(AVCodecContext *avctx) return; memset(cc->frame->data[0], 0, cc->frame->linesize[0] * avctx->height); - if (!avctx->frame_number) + if (!avctx->frame_num) memset(cc->frame->data[1], 0, AVPALETTE_SIZE); } diff --git a/libavcodec/cljrenc.c b/libavcodec/cljrenc.c index d6589315205..31ad5ce0cfe 100644 --- a/libavcodec/cljrenc.c +++ b/libavcodec/cljrenc.c @@ -42,7 +42,7 @@ static int encode_frame(AVCodecContext *avctx, AVPacket *pkt, CLJRContext *a = avctx->priv_data; PutBitContext pb; int x, y, ret; - uint32_t dither= avctx->frame_number; + uint32_t dither= avctx->frame_num; static const uint32_t ordered_dither[2][2] = { { 0x10400000, 0x104F0000 }, diff --git a/libavcodec/decode.c b/libavcodec/decode.c index 93ecd36c2bf..be2be81089f 100644 --- a/libavcodec/decode.c +++ b/libavcodec/decode.c @@ -711,11 +711,16 @@ int ff_decode_receive_frame(AVCodecContext *avctx, AVFrame *frame) goto fail; } - avctx->frame_number++; + avctx->frame_num++; +#if FF_API_AVCTX_FRAME_NUMBER +FF_DISABLE_DEPRECATION_WARNINGS + avctx->frame_number = avctx->frame_num; +FF_ENABLE_DEPRECATION_WARNINGS +#endif if (avctx->flags & AV_CODEC_FLAG_DROPCHANGED) { - if (avctx->frame_number == 1) { + if (avctx->frame_num == 1) { avci->initial_format = frame->format; switch(avctx->codec_type) { case AVMEDIA_TYPE_VIDEO: @@ -732,7 +737,7 @@ int ff_decode_receive_frame(AVCodecContext *avctx, AVFrame *frame) } } - if (avctx->frame_number > 1) { + if (avctx->frame_num > 1) { changed = avci->initial_format != frame->format; switch(avctx->codec_type) { @@ -749,9 +754,9 @@ int ff_decode_receive_frame(AVCodecContext *avctx, AVFrame *frame) if (changed) { avci->changed_frames_dropped++; - av_log(avctx, AV_LOG_INFO, "dropped changed frame #%d pts %"PRId64 + av_log(avctx, AV_LOG_INFO, "dropped changed frame #%"PRId64" pts %"PRId64 " drop count: %d \n", - avctx->frame_number, frame->pts, + avctx->frame_num, frame->pts, avci->changed_frames_dropped); ret = AVERROR_INPUT_CHANGED; goto fail; @@ -916,7 +921,12 @@ int avcodec_decode_subtitle2(AVCodecContext *avctx, AVSubtitle *sub, } if (*got_sub_ptr) - avctx->frame_number++; + avctx->frame_num++; +#if FF_API_AVCTX_FRAME_NUMBER +FF_DISABLE_DEPRECATION_WARNINGS + avctx->frame_number = avctx->frame_num; +FF_ENABLE_DEPRECATION_WARNINGS +#endif } return ret; diff --git a/libavcodec/dvenc.c b/libavcodec/dvenc.c index 8f5fa050b0f..11dd5763af6 100644 --- a/libavcodec/dvenc.c +++ b/libavcodec/dvenc.c @@ -1144,7 +1144,7 @@ static void dv_format_frame(DVEncContext *c, uint8_t *buf) { int chan, i, j, k; /* We work with 720p frames split in half. The odd half-frame is chan 2,3 */ - int chan_offset = 2*(c->sys->height == 720 && c->avctx->frame_number & 1); + int chan_offset = 2*(c->sys->height == 720 && c->avctx->frame_num & 1); for (chan = 0; chan < c->sys->n_difchan; chan++) { for (i = 0; i < c->sys->difseg_size; i++) { diff --git a/libavcodec/eac3enc.c b/libavcodec/eac3enc.c index ab9eda261fe..4b3236d4e5e 100644 --- a/libavcodec/eac3enc.c +++ b/libavcodec/eac3enc.c @@ -189,7 +189,7 @@ void ff_eac3_output_frame_header(AC3EncodeContext *s) put_bits(&s->pb, 1, 0); } if (s->num_blocks != 6) - put_bits(&s->pb, 1, !(s->avctx->frame_number % 6)); /* converter sync flag */ + put_bits(&s->pb, 1, !(s->avctx->frame_num % 6)); /* converter sync flag */ put_bits(&s->pb, 1, 0); /* no additional bit stream info */ /* frame header */ diff --git a/libavcodec/encode.c b/libavcodec/encode.c index 6499d962cac..041fc7670e5 100644 --- a/libavcodec/encode.c +++ b/libavcodec/encode.c @@ -171,7 +171,12 @@ int avcodec_encode_subtitle(AVCodecContext *avctx, uint8_t *buf, int buf_size, } ret = ffcodec(avctx->codec)->cb.encode_sub(avctx, buf, buf_size, sub); - avctx->frame_number++; + avctx->frame_num++; +#if FF_API_AVCTX_FRAME_NUMBER +FF_DISABLE_DEPRECATION_WARNINGS + avctx->frame_number = avctx->frame_num; +FF_ENABLE_DEPRECATION_WARNINGS +#endif return ret; } @@ -503,7 +508,12 @@ int attribute_align_arg avcodec_send_frame(AVCodecContext *avctx, const AVFrame return ret; } - avctx->frame_number++; + avctx->frame_num++; +#if FF_API_AVCTX_FRAME_NUMBER +FF_DISABLE_DEPRECATION_WARNINGS + avctx->frame_number = avctx->frame_num; +FF_ENABLE_DEPRECATION_WARNINGS +#endif return 0; } diff --git a/libavcodec/evrcdec.c b/libavcodec/evrcdec.c index c4b0ad2957b..af7640d7e15 100644 --- a/libavcodec/evrcdec.c +++ b/libavcodec/evrcdec.c @@ -221,8 +221,8 @@ static evrc_packet_rate determine_bitrate(AVCodecContext *avctx, static void warn_insufficient_frame_quality(AVCodecContext *avctx, const char *message) { - av_log(avctx, AV_LOG_WARNING, "Frame #%d, %s\n", - avctx->frame_number, message); + av_log(avctx, AV_LOG_WARNING, "Frame #%"PRId64", %s\n", + avctx->frame_num, message); } /** diff --git a/libavcodec/flashsv2enc.c b/libavcodec/flashsv2enc.c index 46e24a9c1eb..75b48eb1fd3 100644 --- a/libavcodec/flashsv2enc.c +++ b/libavcodec/flashsv2enc.c @@ -105,7 +105,7 @@ typedef struct FlashSV2Context { int rows, cols; - int last_key_frame; + int64_t last_key_frame; int image_width, image_height; int block_width, block_height; @@ -787,7 +787,7 @@ static int optimum_use15_7(FlashSV2Context * s) { #ifndef FLASHSV2_DUMB double ideal = ((double)(s->avctx->bit_rate * s->avctx->time_base.den * s->avctx->ticks_per_frame)) / - ((double) s->avctx->time_base.num) * s->avctx->frame_number; + ((double) s->avctx->time_base.num) * s->avctx->frame_num; if (ideal + use15_7_threshold < s->total_bits) { return 1; } else { @@ -861,20 +861,20 @@ static int flashsv2_encode_frame(AVCodecContext *avctx, AVPacket *pkt, return res; /* First frame needs to be a keyframe */ - if (avctx->frame_number == 0) + if (avctx->frame_num == 0) keyframe = 1; /* Check the placement of keyframes */ if (avctx->gop_size > 0) { - if (avctx->frame_number >= s->last_key_frame + avctx->gop_size) + if (avctx->frame_num >= s->last_key_frame + avctx->gop_size) keyframe = 1; } if (!keyframe - && avctx->frame_number > s->last_key_frame + avctx->keyint_min) { + && avctx->frame_num > s->last_key_frame + avctx->keyint_min) { recommend_keyframe(s, &keyframe); if (keyframe) - av_log(avctx, AV_LOG_DEBUG, "Recommending key frame at frame %d\n", avctx->frame_number); + av_log(avctx, AV_LOG_DEBUG, "Recommending key frame at frame %"PRId64"\n", avctx->frame_num); } if (keyframe) { @@ -890,9 +890,9 @@ static int flashsv2_encode_frame(AVCodecContext *avctx, AVPacket *pkt, if (keyframe) { new_key_frame(s); - s->last_key_frame = avctx->frame_number; + s->last_key_frame = avctx->frame_num; pkt->flags |= AV_PKT_FLAG_KEY; - av_log(avctx, AV_LOG_DEBUG, "Inserting key frame at frame %d\n", avctx->frame_number); + av_log(avctx, AV_LOG_DEBUG, "Inserting key frame at frame %"PRId64"\n", avctx->frame_num); } pkt->size = res; diff --git a/libavcodec/flashsvenc.c b/libavcodec/flashsvenc.c index 6192bc25db0..5cf0602f5da 100644 --- a/libavcodec/flashsvenc.c +++ b/libavcodec/flashsvenc.c @@ -65,7 +65,7 @@ typedef struct FlashSVContext { AVBufferRef *prev_frame_buf; int image_width, image_height; unsigned packet_size; - int last_key_frame; + int64_t last_key_frame; uint8_t tmpblock[3 * 256 * 256]; } FlashSVContext; @@ -215,7 +215,7 @@ static int flashsv_encode_frame(AVCodecContext *avctx, AVPacket *pkt, /* Check the placement of keyframes */ if (avctx->gop_size > 0 && - avctx->frame_number >= s->last_key_frame + avctx->gop_size) { + avctx->frame_num >= s->last_key_frame + avctx->gop_size) { I_frame = 1; } @@ -229,8 +229,8 @@ static int flashsv_encode_frame(AVCodecContext *avctx, AVPacket *pkt, //mark the frame type so the muxer can mux it correctly if (I_frame) { - s->last_key_frame = avctx->frame_number; - ff_dlog(avctx, "Inserting keyframe at frame %d\n", avctx->frame_number); + s->last_key_frame = avctx->frame_num; + ff_dlog(avctx, "Inserting keyframe at frame %"PRId64"\n", avctx->frame_num); } if (I_frame) diff --git a/libavcodec/g2meet.c b/libavcodec/g2meet.c index 761fd22fc37..32b966e8ef9 100644 --- a/libavcodec/g2meet.c +++ b/libavcodec/g2meet.c @@ -931,8 +931,8 @@ static int epic_jb_decode_tile(G2MContext *c, int tile_x, int tile_y, if (ret) { av_log(avctx, AV_LOG_ERROR, - "ePIC: tile decoding failed, frame=%d, tile_x=%d, tile_y=%d\n", - avctx->frame_number, tile_x, tile_y); + "ePIC: tile decoding failed, frame=%"PRId64", tile_x=%d, tile_y=%d\n", + avctx->frame_num, tile_x, tile_y); return AVERROR_INVALIDDATA; } diff --git a/libavcodec/gif.c b/libavcodec/gif.c index e17ead0f823..131af6198ad 100644 --- a/libavcodec/gif.c +++ b/libavcodec/gif.c @@ -318,7 +318,7 @@ static int gif_image_write_image(AVCodecContext *avctx, disposal = GCE_DISPOSAL_INPLACE; } - if (s->image || !avctx->frame_number) { /* GIF header */ + if (s->image || !avctx->frame_num) { /* GIF header */ const uint32_t *global_palette = palette ? palette : s->palette; const AVRational sar = avctx->sample_aspect_ratio; int64_t aspect = 0; @@ -510,7 +510,7 @@ static int gif_encode_frame(AVCodecContext *avctx, AVPacket *pkt, } pkt->size = outbuf_ptr - pkt->data; - if (s->image || !avctx->frame_number) + if (s->image || !avctx->frame_num) pkt->flags |= AV_PKT_FLAG_KEY; *got_packet = 1; diff --git a/libavcodec/h261dec.c b/libavcodec/h261dec.c index 57f7e8bf357..84962939643 100644 --- a/libavcodec/h261dec.c +++ b/libavcodec/h261dec.c @@ -610,7 +610,7 @@ static int h261_decode_frame(AVCodecContext *avctx, AVFrame *pict, MpegEncContext *s = &h->s; int ret; - ff_dlog(avctx, "*****frame %d size=%d\n", avctx->frame_number, buf_size); + ff_dlog(avctx, "*****frame %"PRId64" size=%d\n", avctx->frame_num, buf_size); ff_dlog(avctx, "bytes=%x %x %x %x\n", buf[0], buf[1], buf[2], buf[3]); h->gob_start_code_skipped = 0; diff --git a/libavcodec/h264_slice.c b/libavcodec/h264_slice.c index 6188c746324..97e66a29077 100644 --- a/libavcodec/h264_slice.c +++ b/libavcodec/h264_slice.c @@ -1297,7 +1297,7 @@ static int h264_select_output_frame(H264Context *h) h->last_pocs[0] = cur->poc; cur->mmco_reset = 1; } else if(h->avctx->has_b_frames < out_of_order && !sps->bitstream_restriction_flag){ - int loglevel = h->avctx->frame_number > 1 ? AV_LOG_WARNING : AV_LOG_VERBOSE; + int loglevel = h->avctx->frame_num > 1 ? AV_LOG_WARNING : AV_LOG_VERBOSE; av_log(h->avctx, loglevel, "Increasing reorder buffer to %d\n", out_of_order); h->avctx->has_b_frames = out_of_order; } diff --git a/libavcodec/interplayvideo.c b/libavcodec/interplayvideo.c index 655326a7f1f..1a3461bf109 100644 --- a/libavcodec/interplayvideo.c +++ b/libavcodec/interplayvideo.c @@ -926,7 +926,7 @@ static void ipvideo_format_06_firstpass(IpvideoContext *s, AVFrame *frame, int16 } } else { /* Don't try to copy second_last_frame data on the first frames */ - if (s->avctx->frame_number > 2) + if (s->avctx->frame_num > 2) copy_from(s, s->second_last_frame, frame, 0, 0); } } @@ -1085,7 +1085,7 @@ static void ipvideo_decode_format_10_opcodes(IpvideoContext *s, AVFrame *frame) copy_from(s, s->cur_decode_frame, frame, 0, 0); } else { /* Don't try to copy last_frame data on the first frame */ - if (s->avctx->frame_number) + if (s->avctx->frame_num) copy_from(s, s->last_frame, frame, 0, 0); } skip *= 2; @@ -1144,8 +1144,8 @@ static void ipvideo_decode_format_11_opcodes(IpvideoContext *s, AVFrame *frame) ret = ipvideo_decode_block16[opcode](s, frame); } if (ret != 0) { - av_log(s->avctx, AV_LOG_ERROR, "decode problem on frame %d, @ block (%d, %d)\n", - s->avctx->frame_number, x, y); + av_log(s->avctx, AV_LOG_ERROR, "decode problem on frame %"PRId64", @ block (%d, %d)\n", + s->avctx->frame_num, x, y); return; } } diff --git a/libavcodec/ituh263dec.c b/libavcodec/ituh263dec.c index 2164cd7346e..d4a07071ec1 100644 --- a/libavcodec/ituh263dec.c +++ b/libavcodec/ituh263dec.c @@ -1093,7 +1093,7 @@ int ff_h263_decode_picture_header(MpegEncContext *s) align_get_bits(&s->gb); - if (show_bits(&s->gb, 2) == 2 && s->avctx->frame_number == 0) { + if (show_bits(&s->gb, 2) == 2 && s->avctx->frame_num == 0) { av_log(s->avctx, AV_LOG_WARNING, "Header looks like RTP instead of H.263\n"); } diff --git a/libavcodec/libwebpenc_animencoder.c b/libavcodec/libwebpenc_animencoder.c index 72d704f490f..8756231f23c 100644 --- a/libavcodec/libwebpenc_animencoder.c +++ b/libavcodec/libwebpenc_animencoder.c @@ -132,7 +132,7 @@ FF_ENABLE_DEPRECATION_WARNINGS goto end; } - if (!avctx->frame_number) { + if (!avctx->frame_num) { s->first_frame_pts = frame->pts; #if FF_API_REORDERED_OPAQUE FF_DISABLE_DEPRECATION_WARNINGS diff --git a/libavcodec/mjpegdec.c b/libavcodec/mjpegdec.c index b2be55af4af..c833d66c4db 100644 --- a/libavcodec/mjpegdec.c +++ b/libavcodec/mjpegdec.c @@ -2884,7 +2884,7 @@ av_cold int ff_mjpeg_decode_end(AVCodecContext *avctx) MJpegDecodeContext *s = avctx->priv_data; int i, j; - if (s->interlaced && s->bottom_field == !s->interlace_polarity && s->got_picture && !avctx->frame_number) { + if (s->interlaced && s->bottom_field == !s->interlace_polarity && s->got_picture && !avctx->frame_num) { av_log(avctx, AV_LOG_INFO, "Single field\n"); } diff --git a/libavcodec/mlpenc.c b/libavcodec/mlpenc.c index 1bc8995c58b..5995a6b51c6 100644 --- a/libavcodec/mlpenc.c +++ b/libavcodec/mlpenc.c @@ -2118,7 +2118,7 @@ static int mlp_encode_frame(AVCodecContext *avctx, AVPacket *avpkt, data = frame ? frame->data[0] : NULL; - ctx->frame_index = avctx->frame_number % ctx->max_restart_interval; + ctx->frame_index = avctx->frame_num % ctx->max_restart_interval; ctx->inout_buffer = ctx->major_inout_buffer + ctx->frame_index * ctx->one_sample_buffer_size; @@ -2128,7 +2128,7 @@ static int mlp_encode_frame(AVCodecContext *avctx, AVPacket *avpkt, ctx->write_buffer = ctx->inout_buffer; - if (avctx->frame_number < ctx->max_restart_interval) { + if (avctx->frame_num < ctx->max_restart_interval) { if (data) goto input_and_return; } @@ -2199,7 +2199,7 @@ static int mlp_encode_frame(AVCodecContext *avctx, AVPacket *avpkt, } if (!frame && ctx->last_frames < ctx->max_restart_interval - 1) - avctx->frame_number++; + avctx->frame_num++; if (bytes_written > 0) { ff_af_queue_remove(&ctx->afq, diff --git a/libavcodec/mpegutils.c b/libavcodec/mpegutils.c index 36d75b9633c..2d812a25bec 100644 --- a/libavcodec/mpegutils.c +++ b/libavcodec/mpegutils.c @@ -230,7 +230,7 @@ void ff_print_debug_info2(AVCodecContext *avctx, AVFrame *pict, if (mbcount) { AVFrameSideData *sd; - av_log(avctx, AV_LOG_DEBUG, "Adding %d MVs info to frame %d\n", mbcount, avctx->frame_number); + av_log(avctx, AV_LOG_DEBUG, "Adding %d MVs info to frame %"PRId64"\n", mbcount, avctx->frame_num); sd = av_frame_new_side_data(pict, AV_FRAME_DATA_MOTION_VECTORS, mbcount * sizeof(AVMotionVector)); if (!sd) { av_freep(&mvs); diff --git a/libavcodec/nuv.c b/libavcodec/nuv.c index 1d4f02217c1..d5391eee54c 100644 --- a/libavcodec/nuv.c +++ b/libavcodec/nuv.c @@ -139,7 +139,7 @@ static int decode_frame(AVCodecContext *avctx, AVFrame *picture, int size_change = 0; int minsize = 0; int flags = 0; - int result, init_frame = !avctx->frame_number; + int result, init_frame = !avctx->frame_num; enum { NUV_UNCOMPRESSED = '0', NUV_RTJPEG = '1', diff --git a/libavcodec/options_table.h b/libavcodec/options_table.h index bcd6f381917..4fea57673ad 100644 --- a/libavcodec/options_table.h +++ b/libavcodec/options_table.h @@ -97,7 +97,7 @@ static const AVOption avcodec_options[] = { #endif {"cutoff", "set cutoff bandwidth", OFFSET(cutoff), AV_OPT_TYPE_INT, {.i64 = DEFAULT }, INT_MIN, INT_MAX, A|E}, {"frame_size", NULL, OFFSET(frame_size), AV_OPT_TYPE_INT, {.i64 = DEFAULT }, 0, INT_MAX, A|E}, -{"frame_number", NULL, OFFSET(frame_number), AV_OPT_TYPE_INT, {.i64 = DEFAULT }, INT_MIN, INT_MAX}, +{"frame_number", NULL, OFFSET(frame_num), AV_OPT_TYPE_INT64, {.i64 = DEFAULT }, INT_MIN, INT_MAX}, {"delay", NULL, OFFSET(delay), AV_OPT_TYPE_INT, {.i64 = DEFAULT }, INT_MIN, INT_MAX}, {"qcomp", "video quantizer scale compression (VBR). Constant of ratecontrol equation. " "Recommended range for default rc_eq: 0.0-1.0", diff --git a/libavcodec/opusenc.c b/libavcodec/opusenc.c index 8b86aa7a354..a2f74a347b4 100644 --- a/libavcodec/opusenc.c +++ b/libavcodec/opusenc.c @@ -554,7 +554,7 @@ static int opus_encode_frame(AVCodecContext *avctx, AVPacket *avpkt, ff_bufqueue_add(avctx, &s->bufqueue, av_frame_clone(frame)); } else { ff_opus_psy_signal_eof(&s->psyctx); - if (!s->afq.remaining_samples || !avctx->frame_number) + if (!s->afq.remaining_samples || !avctx->frame_num) return 0; /* We've been flushed and there's nothing left to encode */ } diff --git a/libavcodec/pngenc.c b/libavcodec/pngenc.c index 43bf2039fff..1489256d00d 100644 --- a/libavcodec/pngenc.c +++ b/libavcodec/pngenc.c @@ -251,7 +251,7 @@ static void png_write_image_data(AVCodecContext *avctx, const AVCRC *crc_table = av_crc_get_table(AV_CRC_32_IEEE_LE); uint32_t crc = ~0U; - if (avctx->codec_id == AV_CODEC_ID_PNG || avctx->frame_number == 0) { + if (avctx->codec_id == AV_CODEC_ID_PNG || avctx->frame_num == 0) { png_write_chunk(&s->bytestream, MKTAG('I', 'D', 'A', 'T'), buf, length); return; } @@ -799,7 +799,7 @@ static int apng_encode_frame(AVCodecContext *avctx, const AVFrame *pict, APNGFctlChunk last_fctl_chunk = *best_last_fctl_chunk; APNGFctlChunk fctl_chunk = *best_fctl_chunk; - if (avctx->frame_number == 0) { + if (avctx->frame_num == 0) { best_fctl_chunk->width = pict->width; best_fctl_chunk->height = pict->height; best_fctl_chunk->x_offset = 0; @@ -924,7 +924,7 @@ static int encode_apng(AVCodecContext *avctx, AVPacket *pkt, if (pict && s->color_type == PNG_COLOR_TYPE_PALETTE) { uint32_t checksum = ~av_crc(av_crc_get_table(AV_CRC_32_IEEE_LE), ~0U, pict->data[1], 256 * sizeof(uint32_t)); - if (avctx->frame_number == 0) { + if (avctx->frame_num == 0) { s->palette_checksum = checksum; } else if (checksum != s->palette_checksum) { av_log(avctx, AV_LOG_ERROR, @@ -946,7 +946,7 @@ static int encode_apng(AVCodecContext *avctx, AVPacket *pkt, if (max_packet_size > INT_MAX) return AVERROR(ENOMEM); - if (avctx->frame_number == 0) { + if (avctx->frame_num == 0) { if (!pict) return AVERROR(EINVAL); diff --git a/libavcodec/pthread_frame.c b/libavcodec/pthread_frame.c index 71edd6b3ecd..d9d5afaa82d 100644 --- a/libavcodec/pthread_frame.c +++ b/libavcodec/pthread_frame.c @@ -362,7 +362,12 @@ static int update_context_from_user(AVCodecContext *dst, AVCodecContext *src) dst->skip_idct = src->skip_idct; dst->skip_frame = src->skip_frame; + dst->frame_num = src->frame_num; +#if FF_API_AVCTX_FRAME_NUMBER +FF_DISABLE_DEPRECATION_WARNINGS dst->frame_number = src->frame_number; +FF_ENABLE_DEPRECATION_WARNINGS +#endif #if FF_API_REORDERED_OPAQUE FF_DISABLE_DEPRECATION_WARNINGS dst->reordered_opaque = src->reordered_opaque; diff --git a/libavcodec/qcelpdec.c b/libavcodec/qcelpdec.c index 277c55100a9..1435fecc2eb 100644 --- a/libavcodec/qcelpdec.c +++ b/libavcodec/qcelpdec.c @@ -646,8 +646,8 @@ static qcelp_packet_rate determine_bitrate(AVCodecContext *avctx, static void warn_insufficient_frame_quality(AVCodecContext *avctx, const char *message) { - av_log(avctx, AV_LOG_WARNING, "Frame #%d, IFQ: %s\n", - avctx->frame_number, message); + av_log(avctx, AV_LOG_WARNING, "Frame #%"PRId64", IFQ: %s\n", + avctx->frame_num, message); } static void postfilter(QCELPContext *q, float *samples, float *lpc) diff --git a/libavcodec/qtrleenc.c b/libavcodec/qtrleenc.c index 3d51fcf8434..3846762745a 100644 --- a/libavcodec/qtrleenc.c +++ b/libavcodec/qtrleenc.c @@ -374,7 +374,7 @@ static int qtrle_encode_frame(AVCodecContext *avctx, AVPacket *pkt, return ret; if (avctx->gop_size == 0 || !s->previous_frame->data[0] || - (s->avctx->frame_number % avctx->gop_size) == 0) { + (s->avctx->frame_num % avctx->gop_size) == 0) { /* I-Frame */ s->key_frame = 1; } else { diff --git a/libavcodec/rv10.c b/libavcodec/rv10.c index a45683228e3..2233edfca55 100644 --- a/libavcodec/rv10.c +++ b/libavcodec/rv10.c @@ -603,7 +603,7 @@ static int rv10_decode_frame(AVCodecContext *avctx, AVFrame *pict, int slice_count; const uint8_t *slices_hdr = NULL; - ff_dlog(avctx, "*****frame %d size=%d\n", avctx->frame_number, buf_size); + ff_dlog(avctx, "*****frame %"PRId64" size=%d\n", avctx->frame_num, buf_size); /* no supplementary picture */ if (buf_size == 0) { diff --git a/libavcodec/smcenc.c b/libavcodec/smcenc.c index 3e8b5afcf67..40b53c40eef 100644 --- a/libavcodec/smcenc.c +++ b/libavcodec/smcenc.c @@ -542,7 +542,7 @@ static int smc_encode_frame(AVCodecContext *avctx, AVPacket *pkt, return ret; if (avctx->gop_size == 0 || !s->prev_frame->data[0] || - (avctx->frame_number % avctx->gop_size) == 0) { + (avctx->frame_num % avctx->gop_size) == 0) { s->key_frame = 1; } else { s->key_frame = 0; diff --git a/libavcodec/snowenc.c b/libavcodec/snowenc.c index 749c8067d2d..17c704716dd 100644 --- a/libavcodec/snowenc.c +++ b/libavcodec/snowenc.c @@ -1607,9 +1607,9 @@ static int encode_frame(AVCodecContext *avctx, AVPacket *pkt, pic->pict_type = pict->pict_type; pic->quality = pict->quality; - s->m.picture_number= avctx->frame_number; + s->m.picture_number= avctx->frame_num; if(avctx->flags&AV_CODEC_FLAG_PASS2){ - s->m.pict_type = pic->pict_type = s->m.rc_context.entry[avctx->frame_number].new_pict_type; + s->m.pict_type = pic->pict_type = s->m.rc_context.entry[avctx->frame_num].new_pict_type; s->keyframe = pic->pict_type == AV_PICTURE_TYPE_I; if(!(avctx->flags&AV_CODEC_FLAG_QSCALE)) { pic->quality = ff_rate_estimate_qscale(&s->m, 0); @@ -1617,11 +1617,11 @@ static int encode_frame(AVCodecContext *avctx, AVPacket *pkt, return -1; } }else{ - s->keyframe= avctx->gop_size==0 || avctx->frame_number % avctx->gop_size == 0; + s->keyframe= avctx->gop_size==0 || avctx->frame_num % avctx->gop_size == 0; s->m.pict_type = pic->pict_type = s->keyframe ? AV_PICTURE_TYPE_I : AV_PICTURE_TYPE_P; } - if(s->pass1_rc && avctx->frame_number == 0) + if(s->pass1_rc && avctx->frame_num == 0) pic->quality = 2*FF_QP2LAMBDA; if (pic->quality) { s->qlog = qscale2qlog(pic->quality); @@ -1856,13 +1856,13 @@ static int encode_frame(AVCodecContext *avctx, AVPacket *pkt, ff_snow_release_buffer(avctx); - s->current_picture->coded_picture_number = avctx->frame_number; + s->current_picture->coded_picture_number = avctx->frame_num; s->current_picture->pict_type = pic->pict_type; s->current_picture->quality = pic->quality; s->m.frame_bits = 8*(s->c.bytestream - s->c.bytestream_start); s->m.p_tex_bits = s->m.frame_bits - s->m.misc_bits - s->m.mv_bits; s->m.current_picture.f->display_picture_number = - s->m.current_picture.f->coded_picture_number = avctx->frame_number; + s->m.current_picture.f->coded_picture_number = avctx->frame_num; s->m.current_picture.f->quality = pic->quality; s->m.total_bits += 8*(s->c.bytestream - s->c.bytestream_start); if(s->pass1_rc) diff --git a/libavcodec/svq1enc.c b/libavcodec/svq1enc.c index e3ea0c1e474..4651e01ae87 100644 --- a/libavcodec/svq1enc.c +++ b/libavcodec/svq1enc.c @@ -548,10 +548,10 @@ static av_cold int svq1_encode_end(AVCodecContext *avctx) SVQ1EncContext *const s = avctx->priv_data; int i; - if (avctx->frame_number) + if (avctx->frame_num) av_log(avctx, AV_LOG_DEBUG, "RD: %f\n", s->rd_total / (double)(avctx->width * avctx->height * - avctx->frame_number)); + avctx->frame_num)); s->m.mb_type = NULL; ff_mpv_common_end(&s->m); @@ -684,7 +684,7 @@ static int svq1_encode_frame(AVCodecContext *avctx, AVPacket *pkt, FFSWAP(AVFrame*, s->current_picture, s->last_picture); - if (avctx->gop_size && (avctx->frame_number % avctx->gop_size)) + if (avctx->gop_size && (avctx->frame_num % avctx->gop_size)) s->pict_type = AV_PICTURE_TYPE_P; else s->pict_type = AV_PICTURE_TYPE_I; diff --git a/libavcodec/svq3.c b/libavcodec/svq3.c index b96c4f61f66..df514030b97 100644 --- a/libavcodec/svq3.c +++ b/libavcodec/svq3.c @@ -1542,12 +1542,12 @@ static int svq3_decode_frame(AVCodecContext *avctx, AVFrame *rframe, left = buf_size*8 - get_bits_count(&s->gb_slice); if (s->mb_y != s->mb_height || s->mb_x != s->mb_width) { - av_log(avctx, AV_LOG_INFO, "frame num %d incomplete pic x %d y %d left %d\n", avctx->frame_number, s->mb_y, s->mb_x, left); + av_log(avctx, AV_LOG_INFO, "frame num %"PRId64" incomplete pic x %d y %d left %d\n", avctx->frame_num, s->mb_y, s->mb_x, left); //av_hex_dump(stderr, buf+buf_size-8, 8); } if (left < 0) { - av_log(avctx, AV_LOG_ERROR, "frame num %d left %d\n", avctx->frame_number, left); + av_log(avctx, AV_LOG_ERROR, "frame num %"PRId64" left %d\n", avctx->frame_num, left); return -1; } diff --git a/libavcodec/version.h b/libavcodec/version.h index 59570094574..0550d7b0d87 100644 --- a/libavcodec/version.h +++ b/libavcodec/version.h @@ -29,7 +29,7 @@ #include "version_major.h" -#define LIBAVCODEC_VERSION_MINOR 1 +#define LIBAVCODEC_VERSION_MINOR 2 #define LIBAVCODEC_VERSION_MICRO 100 #define LIBAVCODEC_VERSION_INT AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \ diff --git a/libavcodec/version_major.h b/libavcodec/version_major.h index ae7cba45f31..c2f118b2620 100644 --- a/libavcodec/version_major.h +++ b/libavcodec/version_major.h @@ -44,6 +44,7 @@ #define FF_API_VT_OUTPUT_CALLBACK (LIBAVCODEC_VERSION_MAJOR < 61) #define FF_API_AVCODEC_CHROMA_POS (LIBAVCODEC_VERSION_MAJOR < 61) #define FF_API_VT_HWACCEL_CONTEXT (LIBAVCODEC_VERSION_MAJOR < 61) +#define FF_API_AVCTX_FRAME_NUMBER (LIBAVCODEC_VERSION_MAJOR < 61) // reminder to remove CrystalHD decoders on next major bump #define FF_CODEC_CRYSTAL_HD (LIBAVCODEC_VERSION_MAJOR < 61) diff --git a/libavcodec/vp3.c b/libavcodec/vp3.c index b731bc0669c..9660def675f 100644 --- a/libavcodec/vp3.c +++ b/libavcodec/vp3.c @@ -2654,8 +2654,8 @@ static int vp3_decode_frame(AVCodecContext *avctx, AVFrame *frame, s->qps[i] = -1; if (s->avctx->debug & FF_DEBUG_PICT_INFO) - av_log(s->avctx, AV_LOG_INFO, " VP3 %sframe #%d: Q index = %d\n", - s->keyframe ? "key" : "", avctx->frame_number + 1, s->qps[0]); + av_log(s->avctx, AV_LOG_INFO, " VP3 %sframe #%"PRId64": Q index = %d\n", + s->keyframe ? "key" : "", avctx->frame_num + 1, s->qps[0]); s->skip_loop_filter = !s->filter_limit_values[s->qps[0]] || avctx->skip_loop_filter >= (s->keyframe ? AVDISCARD_ALL @@ -2701,7 +2701,7 @@ static int vp3_decode_frame(AVCodecContext *avctx, AVFrame *frame, } #endif s->version = version; - if (avctx->frame_number == 0) + if (avctx->frame_num == 0) av_log(s->avctx, AV_LOG_DEBUG, "VP version: %d\n", s->version); } diff --git a/libavcodec/wcmv.c b/libavcodec/wcmv.c index 2f1d22bc246..097ac8b8e9a 100644 --- a/libavcodec/wcmv.c +++ b/libavcodec/wcmv.c @@ -156,7 +156,7 @@ static int decode_frame(AVCodecContext *avctx, AVFrame *frame, if (bytestream2_get_bytes_left(&gb) < 8LL * blocks) return AVERROR_INVALIDDATA; - if (!avctx->frame_number) { + if (!avctx->frame_num) { ptrdiff_t linesize[4] = { s->prev_frame->linesize[0], 0, 0, 0 }; av_image_fill_black(s->prev_frame->data, linesize, avctx->pix_fmt, 0, avctx->width, avctx->height); diff --git a/libavcodec/wmaprodec.c b/libavcodec/wmaprodec.c index 7f7357836a2..35e9caec560 100644 --- a/libavcodec/wmaprodec.c +++ b/libavcodec/wmaprodec.c @@ -1678,7 +1678,7 @@ static int decode_packet(AVCodecContext *avctx, WMAProDecodeCtx *s, skip_bits(gb, 2); } else { int num_frames = get_bits(gb, 6); - ff_dlog(avctx, "packet[%d]: number of frames %d\n", avctx->frame_number, num_frames); + ff_dlog(avctx, "packet[%"PRId64"]: number of frames %d\n", avctx->frame_num, num_frames); packet_sequence_number = 0; } @@ -1687,10 +1687,10 @@ static int decode_packet(AVCodecContext *avctx, WMAProDecodeCtx *s, if (avctx->codec_id != AV_CODEC_ID_WMAPRO) { skip_bits(gb, 3); s->skip_packets = get_bits(gb, 8); - ff_dlog(avctx, "packet[%d]: skip packets %d\n", avctx->frame_number, s->skip_packets); + ff_dlog(avctx, "packet[%"PRId64"]: skip packets %d\n", avctx->frame_num, s->skip_packets); } - ff_dlog(avctx, "packet[%d]: nbpf %x\n", avctx->frame_number, + ff_dlog(avctx, "packet[%"PRId64"]: nbpf %x\n", avctx->frame_num, num_bits_prev_frame); /** check for packet loss */ diff --git a/libavcodec/yop.c b/libavcodec/yop.c index 816fe8bdc8f..14244c942a6 100644 --- a/libavcodec/yop.c +++ b/libavcodec/yop.c @@ -207,7 +207,7 @@ static int yop_decode_frame(AVCodecContext *avctx, AVFrame *rframe, if ((ret = ff_reget_buffer(avctx, frame, 0)) < 0) return ret; - if (!avctx->frame_number) + if (!avctx->frame_num) memset(frame->data[1], 0, AVPALETTE_SIZE); s->dstbuf = frame->data[0]; diff --git a/tools/decode_simple.c b/tools/decode_simple.c index b679fd7ce6f..e02323064df 100644 --- a/tools/decode_simple.c +++ b/tools/decode_simple.c @@ -38,7 +38,7 @@ static int decode_read(DecodeContext *dc, int flush) int ret = 0; while (ret >= 0 && - (dc->max_frames == 0 || dc->decoder->frame_number < dc->max_frames)) { + (dc->max_frames == 0 || dc->decoder->frame_num < dc->max_frames)) { ret = avcodec_receive_frame(dc->decoder, dc->frame); if (ret < 0) { if (ret == AVERROR_EOF) { @@ -55,11 +55,11 @@ static int decode_read(DecodeContext *dc, int flush) if (ret < 0) return ret; - if (dc->max_frames && dc->decoder->frame_number == dc->max_frames) + if (dc->max_frames && dc->decoder->frame_num == dc->max_frames) return 1; } - return (dc->max_frames == 0 || dc->decoder->frame_number < dc->max_frames) ? 0 : 1; + return (dc->max_frames == 0 || dc->decoder->frame_num < dc->max_frames) ? 0 : 1; } int ds_run(DecodeContext *dc) diff --git a/tools/scale_slice_test.c b/tools/scale_slice_test.c index d869eaae740..4480bf85697 100644 --- a/tools/scale_slice_test.c +++ b/tools/scale_slice_test.c @@ -100,8 +100,8 @@ static int process_frame(DecodeContext *dc, AVFrame *frame) if (memcmp(pd->frame_ref->data[i], pd->frame_dst->data[i], pd->frame_ref->linesize[i] * (pd->frame_ref->height >> shift))) { - fprintf(stderr, "mismatch frame %d seed %u\n", - dc->decoder->frame_number - 1, pd->random_seed); + fprintf(stderr, "mismatch frame %"PRId64" seed %u\n", + dc->decoder->frame_num - 1, pd->random_seed); return AVERROR(EINVAL); } } diff --git a/tools/venc_data_dump.c b/tools/venc_data_dump.c index 3a3543f80f5..1401f06c733 100644 --- a/tools/venc_data_dump.c +++ b/tools/venc_data_dump.c @@ -38,7 +38,7 @@ static int process_frame(DecodeContext *dc, AVFrame *frame) if (!frame) return 0; - fprintf(stdout, "frame %d\n", dc->decoder->frame_number - 1); + fprintf(stdout, "frame %"PRId64"\n", dc->decoder->frame_num - 1); sd = av_frame_get_side_data(frame, AV_FRAME_DATA_VIDEO_ENC_PARAMS); if (sd) { From 817141c562b0c2b67c87ec8825921d2f524e26fb Mon Sep 17 00:00:00 2001 From: Marton Balint Date: Fri, 27 Jan 2023 22:37:11 +0100 Subject: [PATCH 0253/2172] avcodec/diracdec: do not use AVFrame.display_picture_number for decoding Signed-off-by: Marton Balint --- libavcodec/diracdec.c | 33 ++++++++++++++++++--------------- 1 file changed, 18 insertions(+), 15 deletions(-) diff --git a/libavcodec/diracdec.c b/libavcodec/diracdec.c index a5cad295974..22a2925188e 100644 --- a/libavcodec/diracdec.c +++ b/libavcodec/diracdec.c @@ -77,6 +77,7 @@ typedef struct { uint8_t *hpel[3][4]; uint8_t *hpel_base[3][4]; int reference; + unsigned picture_number; } DiracFrame; typedef struct { @@ -252,13 +253,13 @@ static inline int divide3(int x) return (int)((x+1U)*21845 + 10922) >> 16; } -static DiracFrame *remove_frame(DiracFrame *framelist[], int picnum) +static DiracFrame *remove_frame(DiracFrame *framelist[], unsigned picnum) { DiracFrame *remove_pic = NULL; int i, remove_idx = -1; for (i = 0; framelist[i]; i++) - if (framelist[i]->avframe->display_picture_number == picnum) { + if (framelist[i]->picture_number == picnum) { remove_pic = framelist[i]; remove_idx = i; } @@ -2002,7 +2003,7 @@ static int dirac_decode_picture_header(DiracContext *s) GetBitContext *gb = &s->gb; /* [DIRAC_STD] 11.1.1 Picture Header. picture_header() PICTURE_NUM */ - picnum = s->current_picture->avframe->display_picture_number = get_bits_long(gb, 32); + picnum = s->current_picture->picture_number = get_bits_long(gb, 32); av_log(s->avctx,AV_LOG_DEBUG,"PICTURE_NUM: %d\n",picnum); @@ -2021,9 +2022,9 @@ static int dirac_decode_picture_header(DiracContext *s) /* Jordi: this is needed if the referenced picture hasn't yet arrived */ for (j = 0; j < MAX_REFERENCE_FRAMES && refdist; j++) if (s->ref_frames[j] - && FFABS(s->ref_frames[j]->avframe->display_picture_number - refnum) < refdist) { + && FFABS(s->ref_frames[j]->picture_number - refnum) < refdist) { s->ref_pics[i] = s->ref_frames[j]; - refdist = FFABS(s->ref_frames[j]->avframe->display_picture_number - refnum); + refdist = FFABS(s->ref_frames[j]->picture_number - refnum); } if (!s->ref_pics[i] || refdist) @@ -2062,7 +2063,7 @@ static int dirac_decode_picture_header(DiracContext *s) /* if reference array is full, remove the oldest as per the spec */ while (add_frame(s->ref_frames, MAX_REFERENCE_FRAMES, s->current_picture)) { av_log(s->avctx, AV_LOG_ERROR, "Reference frame overflow\n"); - remove_frame(s->ref_frames, s->ref_frames[0]->avframe->display_picture_number)->reference &= DELAYED_PIC_REF; + remove_frame(s->ref_frames, s->ref_frames[0]->picture_number)->reference &= DELAYED_PIC_REF; } } @@ -2090,7 +2091,7 @@ static int get_delayed_pic(DiracContext *s, AVFrame *picture, int *got_frame) /* find frame with lowest picture number */ for (i = 1; s->delay_frames[i]; i++) - if (s->delay_frames[i]->avframe->display_picture_number < out->avframe->display_picture_number) { + if (s->delay_frames[i]->picture_number < out->picture_number) { out = s->delay_frames[i]; out_idx = i; } @@ -2102,6 +2103,7 @@ static int get_delayed_pic(DiracContext *s, AVFrame *picture, int *got_frame) out->reference ^= DELAYED_PIC_REF; if((ret = av_frame_ref(picture, out->avframe)) < 0) return ret; + picture->display_picture_number = out->picture_number; *got_frame = 1; } @@ -2318,19 +2320,19 @@ static int dirac_decode_frame(AVCodecContext *avctx, AVFrame *picture, if (!s->current_picture) return buf_size; - if (s->current_picture->avframe->display_picture_number > s->frame_number) { + if (s->current_picture->picture_number > s->frame_number) { DiracFrame *delayed_frame = remove_frame(s->delay_frames, s->frame_number); s->current_picture->reference |= DELAYED_PIC_REF; if (add_frame(s->delay_frames, MAX_DELAY, s->current_picture)) { - int min_num = s->delay_frames[0]->avframe->display_picture_number; + unsigned min_num = s->delay_frames[0]->picture_number; /* Too many delayed frames, so we display the frame with the lowest pts */ av_log(avctx, AV_LOG_ERROR, "Delay frame overflow\n"); for (i = 1; s->delay_frames[i]; i++) - if (s->delay_frames[i]->avframe->display_picture_number < min_num) - min_num = s->delay_frames[i]->avframe->display_picture_number; + if (s->delay_frames[i]->picture_number < min_num) + min_num = s->delay_frames[i]->picture_number; delayed_frame = remove_frame(s->delay_frames, min_num); add_frame(s->delay_frames, MAX_DELAY, s->current_picture); @@ -2340,18 +2342,19 @@ static int dirac_decode_frame(AVCodecContext *avctx, AVFrame *picture, delayed_frame->reference ^= DELAYED_PIC_REF; if((ret = av_frame_ref(picture, delayed_frame->avframe)) < 0) return ret; + s->frame_number = delayed_frame->picture_number + 1LL; + picture->display_picture_number = delayed_frame->picture_number; *got_frame = 1; } - } else if (s->current_picture->avframe->display_picture_number == s->frame_number) { + } else if (s->current_picture->picture_number == s->frame_number) { /* The right frame at the right time :-) */ if((ret = av_frame_ref(picture, s->current_picture->avframe)) < 0) return ret; + s->frame_number = s->current_picture->picture_number + 1LL; + picture->display_picture_number = s->current_picture->picture_number; *got_frame = 1; } - if (*got_frame) - s->frame_number = picture->display_picture_number + 1LL; - return buf_idx; } From 8e2c1249044e9207c88c13764797676d403e3f57 Mon Sep 17 00:00:00 2001 From: Marton Balint Date: Fri, 27 Jan 2023 23:13:05 +0100 Subject: [PATCH 0254/2172] avcodec/mpegvideo_enc: do not use AVFrame.*_picture_number for encoding Move these fields to MPEGPicture instead and use that. Signed-off-by: Marton Balint --- libavcodec/mpeg12enc.c | 4 ++-- libavcodec/mpegpicture.c | 4 ++++ libavcodec/mpegpicture.h | 3 +++ libavcodec/mpegvideo_enc.c | 17 ++++++++++------- libavcodec/ratecontrol.c | 4 ++-- libavcodec/snowenc.c | 5 ++--- 6 files changed, 23 insertions(+), 14 deletions(-) diff --git a/libavcodec/mpeg12enc.c b/libavcodec/mpeg12enc.c index 26cf33a3c68..a932b59678f 100644 --- a/libavcodec/mpeg12enc.c +++ b/libavcodec/mpeg12enc.c @@ -419,10 +419,10 @@ static void mpeg1_encode_sequence_header(MpegEncContext *s) /* 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 + + time_code = s->current_picture_ptr->coded_picture_number + mpeg12->timecode_frame_start; - mpeg12->gop_picture_number = s->current_picture_ptr->f->coded_picture_number; + mpeg12->gop_picture_number = s->current_picture_ptr->coded_picture_number; av_assert0(mpeg12->drop_frame_timecode == !!(mpeg12->tc.flags & AV_TIMECODE_FLAG_DROPFRAME)); if (mpeg12->drop_frame_timecode) diff --git a/libavcodec/mpegpicture.c b/libavcodec/mpegpicture.c index 977bc65191d..3204a70578c 100644 --- a/libavcodec/mpegpicture.c +++ b/libavcodec/mpegpicture.c @@ -332,6 +332,8 @@ void ff_mpeg_unref_picture(AVCodecContext *avctx, Picture *pic) pic->needs_realloc = 0; pic->reference = 0; pic->shared = 0; + pic->display_picture_number = 0; + pic->coded_picture_number = 0; } int ff_update_picture_tables(Picture *dst, const Picture *src) @@ -397,6 +399,8 @@ int ff_mpeg_ref_picture(AVCodecContext *avctx, Picture *dst, Picture *src) dst->needs_realloc = src->needs_realloc; dst->reference = src->reference; dst->shared = src->shared; + dst->display_picture_number = src->display_picture_number; + dst->coded_picture_number = src->coded_picture_number; return 0; fail: diff --git a/libavcodec/mpegpicture.h b/libavcodec/mpegpicture.h index a1455ee13c2..7919aa402ca 100644 --- a/libavcodec/mpegpicture.h +++ b/libavcodec/mpegpicture.h @@ -76,6 +76,9 @@ typedef struct Picture { int reference; int shared; + + int display_picture_number; + int coded_picture_number; } Picture; /** diff --git a/libavcodec/mpegvideo_enc.c b/libavcodec/mpegvideo_enc.c index 0e6a4c4ec54..7d3c8875f29 100644 --- a/libavcodec/mpegvideo_enc.c +++ b/libavcodec/mpegvideo_enc.c @@ -1219,7 +1219,7 @@ static int load_input_picture(MpegEncContext *s, const AVFrame *pic_arg) if (ret < 0) return ret; - pic->f->display_picture_number = display_picture_number; + pic->display_picture_number = display_picture_number; pic->f->pts = pts; // we set this here to avoid modifying pic_arg } else { /* Flushing: When we have not received enough input frames, @@ -1477,14 +1477,14 @@ static int select_input_picture(MpegEncContext *s) !s->next_picture_ptr || s->intra_only) { s->reordered_input_picture[0] = s->input_picture[0]; s->reordered_input_picture[0]->f->pict_type = AV_PICTURE_TYPE_I; - s->reordered_input_picture[0]->f->coded_picture_number = + s->reordered_input_picture[0]->coded_picture_number = s->coded_picture_number++; } else { int b_frames = 0; if (s->avctx->flags & AV_CODEC_FLAG_PASS2) { for (i = 0; i < s->max_b_frames + 1; i++) { - int pict_num = s->input_picture[0]->f->display_picture_number + i; + int pict_num = s->input_picture[0]->display_picture_number + i; if (pict_num >= s->rc_context.num_entries) break; @@ -1563,13 +1563,13 @@ static int select_input_picture(MpegEncContext *s) s->reordered_input_picture[0] = s->input_picture[b_frames]; if (s->reordered_input_picture[0]->f->pict_type != AV_PICTURE_TYPE_I) s->reordered_input_picture[0]->f->pict_type = AV_PICTURE_TYPE_P; - s->reordered_input_picture[0]->f->coded_picture_number = + s->reordered_input_picture[0]->coded_picture_number = s->coded_picture_number++; for (i = 0; i < b_frames; i++) { s->reordered_input_picture[i + 1] = s->input_picture[i]; s->reordered_input_picture[i + 1]->f->pict_type = AV_PICTURE_TYPE_B; - s->reordered_input_picture[i + 1]->f->coded_picture_number = + s->reordered_input_picture[i + 1]->coded_picture_number = s->coded_picture_number++; } } @@ -1604,6 +1604,8 @@ static int select_input_picture(MpegEncContext *s) ret = av_frame_copy_props(pic->f, s->reordered_input_picture[0]->f); if (ret < 0) return ret; + pic->coded_picture_number = s->reordered_input_picture[0]->coded_picture_number; + pic->display_picture_number = s->reordered_input_picture[0]->display_picture_number; /* mark us unused / free shared pic */ av_frame_unref(s->reordered_input_picture[0]->f); @@ -1618,7 +1620,8 @@ static int select_input_picture(MpegEncContext *s) s->new_picture->data[i] += INPLACE_OFFSET; } } - s->picture_number = s->new_picture->display_picture_number; + s->picture_number = s->current_picture_ptr->display_picture_number; + } return 0; } @@ -1954,7 +1957,7 @@ int ff_mpv_encode_picture(AVCodecContext *avctx, AVPacket *pkt, pkt->pts = s->current_picture.f->pts; pkt->duration = s->current_picture.f->duration; if (!s->low_delay && s->pict_type != AV_PICTURE_TYPE_B) { - if (!s->current_picture.f->coded_picture_number) + if (!s->current_picture.coded_picture_number) pkt->dts = pkt->pts - s->dts_delta; else pkt->dts = s->reordered_pts; diff --git a/libavcodec/ratecontrol.c b/libavcodec/ratecontrol.c index 4829172c2cd..6a40f9cbdc7 100644 --- a/libavcodec/ratecontrol.c +++ b/libavcodec/ratecontrol.c @@ -39,8 +39,8 @@ void ff_write_pass1_stats(MpegEncContext *s) snprintf(s->avctx->stats_out, 256, "in:%d out:%d type:%d q:%d itex:%d ptex:%d mv:%d misc:%d " "fcode:%d bcode:%d mc-var:%"PRId64" var:%"PRId64" icount:%d skipcount:%d hbits:%d;\n", - s->current_picture_ptr->f->display_picture_number, - s->current_picture_ptr->f->coded_picture_number, + s->current_picture_ptr->display_picture_number, + s->current_picture_ptr->coded_picture_number, s->pict_type, s->current_picture.f->quality, s->i_tex_bits, diff --git a/libavcodec/snowenc.c b/libavcodec/snowenc.c index 17c704716dd..658684c575f 100644 --- a/libavcodec/snowenc.c +++ b/libavcodec/snowenc.c @@ -1856,13 +1856,12 @@ static int encode_frame(AVCodecContext *avctx, AVPacket *pkt, ff_snow_release_buffer(avctx); - s->current_picture->coded_picture_number = avctx->frame_num; s->current_picture->pict_type = pic->pict_type; s->current_picture->quality = pic->quality; s->m.frame_bits = 8*(s->c.bytestream - s->c.bytestream_start); s->m.p_tex_bits = s->m.frame_bits - s->m.misc_bits - s->m.mv_bits; - s->m.current_picture.f->display_picture_number = - s->m.current_picture.f->coded_picture_number = avctx->frame_num; + s->m.current_picture.display_picture_number = + s->m.current_picture.coded_picture_number = avctx->frame_num; s->m.current_picture.f->quality = pic->quality; s->m.total_bits += 8*(s->c.bytestream - s->c.bytestream_start); if(s->pass1_rc) From 22960783978d9e0b6d4a4ed21f503bd24662aa7e Mon Sep 17 00:00:00 2001 From: Marton Balint Date: Sat, 28 Jan 2023 18:36:22 +0100 Subject: [PATCH 0255/2172] avutil/frame: deprecate AVFrame.coded_picture_number and display_picture_number Their usefulness is questionable, very few decoders set them, and their type should have been int64_t. A replacement field can be added later if a valid use case is found. Signed-off-by: Marton Balint --- doc/APIchanges | 4 ++++ doc/examples/demux_decode.c | 4 ++-- fftools/ffprobe.c | 4 ++++ libavcodec/diracdec.c | 12 ++++++++++++ libavcodec/h264_slice.c | 4 ++++ libavcodec/libuavs3d.c | 4 ++++ libavcodec/mpegvideo_dec.c | 4 ++++ libavutil/frame.c | 4 ++++ libavutil/frame.h | 4 ++++ libavutil/version.h | 3 ++- 10 files changed, 44 insertions(+), 3 deletions(-) diff --git a/doc/APIchanges b/doc/APIchanges index f3ea960415f..3ca724724b9 100644 --- a/doc/APIchanges +++ b/doc/APIchanges @@ -2,6 +2,10 @@ The last version increases of all libraries were on 2023-02-09 API changes, most recent first: +2023-02-13 - xxxxxxxxxx - lavu 58.1.100 - frame.h + Deprecate AVFrame.coded_picture_number and display_picture_number. + Their usefulness is questionable and very few decoders set them. + 2023-02-13 - xxxxxxxxxx - lavc 60.2.100 - avcodec.h Add AVCodecContext.frame_num as a 64bit version of frame_number. Deprecate AVCodecContext.frame_number. diff --git a/doc/examples/demux_decode.c b/doc/examples/demux_decode.c index ebef7a61142..298a369f436 100644 --- a/doc/examples/demux_decode.c +++ b/doc/examples/demux_decode.c @@ -73,8 +73,8 @@ static int output_video_frame(AVFrame *frame) return -1; } - printf("video_frame n:%d coded_n:%d\n", - video_frame_count++, frame->coded_picture_number); + printf("video_frame n:%d\n", + video_frame_count++); /* copy decoded frame to destination buffer: * this is required since rawvideo expects non aligned data */ diff --git a/fftools/ffprobe.c b/fftools/ffprobe.c index f5ac5c1554d..af927cb0843 100644 --- a/fftools/ffprobe.c +++ b/fftools/ffprobe.c @@ -2618,8 +2618,12 @@ static void show_frame(WriterContext *w, AVFrame *frame, AVStream *stream, print_str_opt("sample_aspect_ratio", "N/A"); } print_fmt("pict_type", "%c", av_get_picture_type_char(frame->pict_type)); +#if LIBAVUTIL_VERSION_MAJOR < 59 + AV_NOWARN_DEPRECATED( print_int("coded_picture_number", frame->coded_picture_number); print_int("display_picture_number", frame->display_picture_number); + ) +#endif print_int("interlaced_frame", frame->interlaced_frame); print_int("top_field_first", frame->top_field_first); print_int("repeat_pict", frame->repeat_pict); diff --git a/libavcodec/diracdec.c b/libavcodec/diracdec.c index 22a2925188e..0ae582befeb 100644 --- a/libavcodec/diracdec.c +++ b/libavcodec/diracdec.c @@ -2103,7 +2103,11 @@ static int get_delayed_pic(DiracContext *s, AVFrame *picture, int *got_frame) out->reference ^= DELAYED_PIC_REF; if((ret = av_frame_ref(picture, out->avframe)) < 0) return ret; +#if FF_API_FRAME_PICTURE_NUMBER +FF_DISABLE_DEPRECATION_WARNINGS picture->display_picture_number = out->picture_number; +FF_ENABLE_DEPRECATION_WARNINGS +#endif *got_frame = 1; } @@ -2343,7 +2347,11 @@ static int dirac_decode_frame(AVCodecContext *avctx, AVFrame *picture, if((ret = av_frame_ref(picture, delayed_frame->avframe)) < 0) return ret; s->frame_number = delayed_frame->picture_number + 1LL; +#if FF_API_FRAME_PICTURE_NUMBER +FF_DISABLE_DEPRECATION_WARNINGS picture->display_picture_number = delayed_frame->picture_number; +FF_ENABLE_DEPRECATION_WARNINGS +#endif *got_frame = 1; } } else if (s->current_picture->picture_number == s->frame_number) { @@ -2351,7 +2359,11 @@ static int dirac_decode_frame(AVCodecContext *avctx, AVFrame *picture, if((ret = av_frame_ref(picture, s->current_picture->avframe)) < 0) return ret; s->frame_number = s->current_picture->picture_number + 1LL; +#if FF_API_FRAME_PICTURE_NUMBER +FF_DISABLE_DEPRECATION_WARNINGS picture->display_picture_number = s->current_picture->picture_number; +FF_ENABLE_DEPRECATION_WARNINGS +#endif *got_frame = 1; } diff --git a/libavcodec/h264_slice.c b/libavcodec/h264_slice.c index 97e66a29077..7767e16cf15 100644 --- a/libavcodec/h264_slice.c +++ b/libavcodec/h264_slice.c @@ -489,7 +489,11 @@ static int h264_frame_start(H264Context *h) pic = &h->DPB[i]; pic->reference = h->droppable ? 0 : h->picture_structure; +#if FF_API_FRAME_PICTURE_NUMBER +FF_DISABLE_DEPRECATION_WARNINGS pic->f->coded_picture_number = h->coded_picture_number++; +FF_ENABLE_DEPRECATION_WARNINGS +#endif pic->field_picture = h->picture_structure != PICT_FRAME; pic->frame_num = h->poc.frame_num; /* diff --git a/libavcodec/libuavs3d.c b/libavcodec/libuavs3d.c index f5a6e59496f..b1ccb151e68 100644 --- a/libavcodec/libuavs3d.c +++ b/libavcodec/libuavs3d.c @@ -81,8 +81,12 @@ static void uavs3d_output_callback(uavs3d_io_frm_t *dec_frame) { frm->pkt_dts = dec_frame->dts; frm->pkt_pos = dec_frame->pkt_pos; frm->pkt_size = dec_frame->pkt_size; +#if FF_API_FRAME_PICTURE_NUMBER +FF_DISABLE_DEPRECATION_WARNINGS frm->coded_picture_number = dec_frame->dtr; frm->display_picture_number = dec_frame->ptr; +FF_ENABLE_DEPRECATION_WARNINGS +#endif if (dec_frame->type < 0 || dec_frame->type >= FF_ARRAY_ELEMS(ff_avs3_image_type)) { av_log(NULL, AV_LOG_WARNING, "Error frame type in uavs3d: %d.\n", dec_frame->type); diff --git a/libavcodec/mpegvideo_dec.c b/libavcodec/mpegvideo_dec.c index 7a0c51e53d1..522a0aada5f 100644 --- a/libavcodec/mpegvideo_dec.c +++ b/libavcodec/mpegvideo_dec.c @@ -320,7 +320,11 @@ int ff_mpv_frame_start(MpegEncContext *s, AVCodecContext *avctx) pic->reference = 3; } +#if FF_API_FRAME_PICTURE_NUMBER +FF_DISABLE_DEPRECATION_WARNINGS pic->f->coded_picture_number = s->coded_picture_number++; +FF_ENABLE_DEPRECATION_WARNINGS +#endif if (alloc_picture(s, pic) < 0) return -1; diff --git a/libavutil/frame.c b/libavutil/frame.c index 4d89c75dc88..9545477acc9 100644 --- a/libavutil/frame.c +++ b/libavutil/frame.c @@ -294,8 +294,12 @@ FF_ENABLE_DEPRECATION_WARNINGS #endif dst->quality = src->quality; dst->best_effort_timestamp = src->best_effort_timestamp; +#if FF_API_FRAME_PICTURE_NUMBER +FF_DISABLE_DEPRECATION_WARNINGS dst->coded_picture_number = src->coded_picture_number; dst->display_picture_number = src->display_picture_number; +FF_ENABLE_DEPRECATION_WARNINGS +#endif dst->flags = src->flags; dst->decode_error_flags = src->decode_error_flags; dst->color_primaries = src->color_primaries; diff --git a/libavutil/frame.h b/libavutil/frame.h index e5c92a0ca81..25802695493 100644 --- a/libavutil/frame.h +++ b/libavutil/frame.h @@ -451,14 +451,18 @@ typedef struct AVFrame { */ AVRational time_base; +#if FF_API_FRAME_PICTURE_NUMBER /** * picture number in bitstream order */ + attribute_deprecated int coded_picture_number; /** * picture number in display order */ + attribute_deprecated int display_picture_number; +#endif /** * quality (between 1 (good) and FF_LAMBDA_MAX (bad)) diff --git a/libavutil/version.h b/libavutil/version.h index 3ad38110c1a..11b4387f642 100644 --- a/libavutil/version.h +++ b/libavutil/version.h @@ -79,7 +79,7 @@ */ #define LIBAVUTIL_VERSION_MAJOR 58 -#define LIBAVUTIL_VERSION_MINOR 0 +#define LIBAVUTIL_VERSION_MINOR 1 #define LIBAVUTIL_VERSION_MICRO 100 #define LIBAVUTIL_VERSION_INT AV_VERSION_INT(LIBAVUTIL_VERSION_MAJOR, \ @@ -112,6 +112,7 @@ #define FF_API_AV_FOPEN_UTF8 (LIBAVUTIL_VERSION_MAJOR < 59) #define FF_API_PKT_DURATION (LIBAVUTIL_VERSION_MAJOR < 59) #define FF_API_REORDERED_OPAQUE (LIBAVUTIL_VERSION_MAJOR < 59) +#define FF_API_FRAME_PICTURE_NUMBER (LIBAVUTIL_VERSION_MAJOR < 59) /** * @} From f8d6d0fbf12b3247a37885cd0a5cd32ddc1f01b3 Mon Sep 17 00:00:00 2001 From: Ziemowit Laski Date: Fri, 10 Feb 2023 02:43:05 +0000 Subject: [PATCH 0256/2172] compat: Use '-' instead of '/' for rc.exe options MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When building FFMPEG in the MSYS environment under Windows, one must not use forward slashes ('/') for command-line options. It appears that the MSYS shell interprets these as absolute paths and then automatically rewrites them into equivalent Windows paths. For example, the '/nologo' switch below gets rewritten to something like 'C:/Program Files/Git/nologo', and this obviously breaks the build. Thankfully, most M$ tools accept dashes ('-') as well. Signed-off-by: Ziemowit Łąski <15880281+zlaski@users.noreply.github.com> Signed-off-by: Martin Storsjö --- compat/windows/mswindres | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/compat/windows/mswindres b/compat/windows/mswindres index 450525a33e3..8c14c96bae4 100755 --- a/compat/windows/mswindres +++ b/compat/windows/mswindres @@ -1,7 +1,7 @@ #!/bin/sh if [ "$1" = "--version" ]; then - rc.exe /? + rc.exe -? exit $? fi @@ -10,12 +10,12 @@ if [ $# -lt 2 ]; then exit 0 fi -EXTRA_OPTS="/nologo" +EXTRA_OPTS="-nologo" while [ $# -gt 2 ]; do case $1 in - -D*) EXTRA_OPTS="$EXTRA_OPTS /d$(echo $1 | sed -e "s/^..//" -e "s/ /\\\\ /g")" ;; - -I*) EXTRA_OPTS="$EXTRA_OPTS /i$(echo $1 | sed -e "s/^..//" -e "s/ /\\\\ /g")" ;; + -D*) EXTRA_OPTS="$EXTRA_OPTS -d$(echo $1 | sed -e "s/^..//" -e "s/ /\\\\ /g")" ;; + -I*) EXTRA_OPTS="$EXTRA_OPTS -i$(echo $1 | sed -e "s/^..//" -e "s/ /\\\\ /g")" ;; -o) OPT_OUT="$2"; shift ;; esac shift @@ -29,4 +29,4 @@ else fi eval set -- $EXTRA_OPTS -rc.exe "$@" /fo "$OUT" "$IN" +rc.exe "$@" -fo "$OUT" "$IN" From b8f9cc5e8e6a6832763172b517ab9cdc0594d533 Mon Sep 17 00:00:00 2001 From: Pierre-Anthony Lemieux Date: Thu, 15 Sep 2022 15:46:28 -0700 Subject: [PATCH 0257/2172] MAINTAINERS: add maintainer for the imf demuxer --- MAINTAINERS | 2 ++ 1 file changed, 2 insertions(+) diff --git a/MAINTAINERS b/MAINTAINERS index f87d43fce5c..854ccc3fa4c 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -427,6 +427,7 @@ Muxers/Demuxers: idcin.c Mike Melanson idroqdec.c Mike Melanson iff.c Jaikrishnan Menon + imf* Pierre-Anthony Lemieux img2*.c Michael Niedermayer ipmovie.c Mike Melanson ircam* Paul B Mahol @@ -624,6 +625,7 @@ Nikolay Aleksandrov 8978 1D8C FB71 588E 4B27 EAA8 C4F0 B5FC E011 13B1 Panagiotis Issaris 6571 13A3 33D9 3726 F728 AA98 F643 B12E ECF3 E029 Peter Ross A907 E02F A6E5 0CD2 34CD 20D2 6760 79C5 AC40 DD6B Philip Langdale 5DC5 8D66 5FBA 3A43 18EC 045E F8D6 B194 6A75 682E +Pierre-Anthony Lemieux (pal) F4B3 9492 E6F2 E4AF AEC8 46CB 698F A1F0 F8D4 EED4 Ramiro Polla 7859 C65B 751B 1179 792E DAE8 8E95 8B2F 9B6C 5700 Reimar Doeffinger C61D 16E5 9E2C D10C 8958 38A4 0899 A2B9 06D4 D9C7 Reinhard Tartler 9300 5DC2 7E87 6C37 ED7B CA9A 9808 3544 9453 48A4 From 7c41a083b756c8daf34cf1d6bb8367b2151b4e4f Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Mon, 13 Feb 2023 18:21:56 +0100 Subject: [PATCH 0258/2172] avcodec/rka: misc fixes and improvements --- libavcodec/rka.c | 117 ++++++++++++++++++++++++++--------------------- 1 file changed, 66 insertions(+), 51 deletions(-) diff --git a/libavcodec/rka.c b/libavcodec/rka.c index 6eba3dd9211..435fd10a3b4 100644 --- a/libavcodec/rka.c +++ b/libavcodec/rka.c @@ -68,8 +68,7 @@ typedef struct ChContext { AdaptiveModel *filt_size; AdaptiveModel *filt_bits; - int *bprob0; - int *bprob1; + uint32_t *bprob[2]; AdaptiveModel position; AdaptiveModel fshift; @@ -96,8 +95,7 @@ typedef struct RKAContext { uint32_t total_nb_samples; uint32_t samples_left; - int bprob0[257]; - int bprob1[257]; + uint32_t bprob[2][257]; AdaptiveModel filt_size; AdaptiveModel filt_bits; @@ -203,14 +201,14 @@ static int chctx_init(RKAContext *s, ChContext *c, c->filt_size = &s->filt_size; c->filt_bits = &s->filt_bits; - c->bprob0 = s->bprob0; - c->bprob1 = s->bprob1; + c->bprob[0] = s->bprob[0]; + c->bprob[1] = s->bprob[1]; c->srate_pad = (sample_rate << 13) / 44100 & 0xFFFFFFFCU; c->pos_idx = 1; - for (int i = 0; i < FF_ARRAY_ELEMS(s->bprob0); i++) - c->bprob0[i] = c->bprob1[i] = 1; + for (int i = 0; i < FF_ARRAY_ELEMS(s->bprob[0]); i++) + c->bprob[0][i] = c->bprob[1][i] = 1; for (int i = 0; i < 11; i++) { ret = adaptive_model_init(&c->coeff_bits[i], 32); @@ -247,8 +245,8 @@ static void init_acoder(ACoder *ac) static int ac_decode_bool(ACoder *ac, int freq1, int freq2) { - unsigned help, add, high; - int value, low; + unsigned help, add, high, value; + int low; low = ac->low; help = ac->high / (unsigned)(freq2 + freq1); @@ -270,7 +268,7 @@ static int ac_decode_bool(ACoder *ac, int freq1, int freq2) break; ac->value = bytestream2_get_byteu(&ac->gb) | (ac->value << 8); ac->high = high = ac->high << 8; - ac->low = low = ac->low << 8; + low = ac->low = ac->low << 8; } return -1; } @@ -287,27 +285,27 @@ static int ac_decode_bool(ACoder *ac, int freq1, int freq2) break; ac->value = bytestream2_get_byteu(&ac->gb) | (ac->value << 8); ac->high = add = ac->high << 8; - ac->low = low = ac->low << 8; + low = ac->low = ac->low << 8; } return -1; } static int decode_bool(ACoder *ac, ChContext *c, int idx) { - int x, b; + uint32_t x; + int b; - x = c->bprob0[idx]; - if (x + c->bprob1[idx] > 4096) { - c->bprob0[idx] = (x >> 1) + 1; - c->bprob1[idx] = (c->bprob1[idx] >> 1) + 1; + x = c->bprob[0][idx]; + if (x + c->bprob[1][idx] > 4096) { + c->bprob[0][idx] = (x >> 1) + 1; + c->bprob[1][idx] = (c->bprob[1][idx] >> 1) + 1; } - b = ac_decode_bool(ac, c->bprob0[idx], c->bprob1[idx]); - if (b == 1) { - c->bprob1[idx]++; - } else if (b == 0) { - c->bprob0[idx]++; - } + b = ac_decode_bool(ac, c->bprob[0][idx], c->bprob[1][idx]); + if (b < 0) + return b; + + c->bprob[b][idx]++; return b; } @@ -341,7 +339,7 @@ static int ac_update(ACoder *ac, int freq, int mul) if (((high + low) ^ low) > 0xffffff) { if (high > 0xffff) return 0; - ac->high = (-(int16_t)low) & 0xffff; + ac->high = (uint16_t)-(int16_t)low; } if (bytestream2_get_bytes_left(&ac->gb) <= 0) @@ -403,8 +401,8 @@ static void update_ch_subobj(AdaptiveModel *am) static int amdl_decode_int(AdaptiveModel *am, ACoder *ac, unsigned *dst, unsigned size) { - unsigned freq, size2; - int val, mul, j; + unsigned freq, size2, val, mul; + int j; size = FFMIN(size, am->buf_size - 1); @@ -437,7 +435,7 @@ static int amdl_decode_int(AdaptiveModel *am, ACoder *ac, unsigned *dst, unsigne j -= v; } } - freq = freq - j; + freq -= j; val = sum + 1; } else { freq = 0; @@ -549,7 +547,7 @@ static int ac_dec_bit(ACoder *ac) if (((high + low) ^ low) > 0xffffff) { if (high > 0xffff) return 0; - ac->high = (-(int16_t)low) & 0xffff; + ac->high = (uint16_t)-(int16_t)low; } if (bytestream2_get_bytes_left(&ac->gb) <= 0) @@ -567,7 +565,7 @@ static int ac_dec_bit(ACoder *ac) if (((high + low) ^ low) > 0xffffff) { if (high > 0xffff) return 1; - ac->high = (-(int16_t)low) & 0xffff; + ac->high = (uint16_t)-(int16_t)low; } if (bytestream2_get_bytes_left(&ac->gb) <= 0) @@ -586,11 +584,11 @@ static int mdl64_decode(ACoder *ac, Model64 *ctx, int *dst) int sign, idx, bits; unsigned val = 0; - if (ctx->zero[0] + ctx->zero[1] > 4000) { + if (ctx->zero[0] + ctx->zero[1] > 4000U) { ctx->zero[0] = (ctx->zero[0] >> 1) + 1; ctx->zero[1] = (ctx->zero[1] >> 1) + 1; } - if (ctx->sign[0] + ctx->sign[1] > 4000) { + if (ctx->sign[0] + ctx->sign[1] > 4000U) { ctx->sign[0] = (ctx->sign[0] >> 1) + 1; ctx->sign[1] = (ctx->sign[1] >> 1) + 1; } @@ -599,8 +597,9 @@ static int mdl64_decode(ACoder *ac, Model64 *ctx, int *dst) ctx->zero[0] += 2; dst[0] = 0; return 0; - } else if (sign < 0) + } else if (sign < 0) { return -1; + } ctx->zero[1] += 2; sign = ac_decode_bool(ac, ctx->sign[0], ctx->sign[1]); @@ -613,11 +612,12 @@ static int mdl64_decode(ACoder *ac, Model64 *ctx, int *dst) ac_get_freq(ac, 1 << bits, &val); ac_update(ac, val, 1); } else { - ac_get_freq(ac, 1 << (bits / 2), &val); + int hbits = bits / 2; + ac_get_freq(ac, 1 << hbits, &val); ac_update(ac, val, 1); - ac_get_freq(ac, 1 << (ctx->bits - (bits / 2)), &bits); + ac_get_freq(ac, 1 << (ctx->bits - (hbits)), &bits); ac_update(ac, val, 1); - val = val + (bits << (bits / 2)); + val += (bits << hbits); } } bits = ctx->size; @@ -649,14 +649,13 @@ static int mdl64_decode(ACoder *ac, Model64 *ctx, int *dst) return 0; } } - bits = bits + 1; + bits++; while (ac_dec_bit(ac) == 0) - bits = bits + 64; + bits += 64; ac_get_freq(ac, 64, &idx); ac_update(ac, idx, 1); idx += bits; - bits = val + 1 + (idx << ctx->bits); - dst[0] = bits; + dst[0] = val + 1 + (idx << ctx->bits); if (sign) dst[0] = -dst[0]; @@ -697,7 +696,7 @@ static int decode_filter(RKAContext *s, ChContext *ctx, ACoder *ac, int off, uns idx = (ctx->pos_idx + idx) % 11; ctx->pos_idx = idx; - for (int y = 0; y < split; y++, off++) { + for (int y = 0; y < FFMIN(split, size - x); y++, off++) { int midx, shift = idx, *src, sum = 16; midx = FFABS(last_val) >> shift; @@ -725,7 +724,7 @@ static int decode_filter(RKAContext *s, ChContext *ctx, ACoder *ac, int off, uns if (bits == 0) { ctx->buf1[off] = sum + val; } else { - ctx->buf1[off] = (val + (sum >> bits) * (1U << bits)) + + ctx->buf1[off] = (val + (sum >> bits) << bits) + (((1U << bits) - 1U) & ctx->buf1[off + -1]); } ctx->buf0[off] = ctx->buf1[off] + ctx->buf0[off + -1]; @@ -733,8 +732,8 @@ static int decode_filter(RKAContext *s, ChContext *ctx, ACoder *ac, int off, uns val = val * (1 << ctx->cmode & 0x1f); sum += ctx->buf0[off + -1] + val; switch (s->bps) { - case 16: sum = av_clip_int16(sum); break; - case 8: sum = av_clip_int8(sum); break; + case 16: sum = av_clip_int16(sum); break; + case 8: sum = av_clip_int8(sum); break; } ctx->buf1[off] = sum - ctx->buf0[off + -1]; ctx->buf0[off] = sum; @@ -770,28 +769,44 @@ static int decode_samples(AVCodecContext *avctx, ACoder *ac, ChContext *ctx, int return ret; ac_update(ac, segment_size, 1); segment_size *= 4; - decode_filter(s, ctx, ac, offset, segment_size); + ret = decode_filter(s, ctx, ac, offset, segment_size); + if (ret < 0) + return ret; } else { segment_size = ctx->srate_pad; if (mode) { if (mode > 2) { - decode_filter(s, ctx, ac, offset, segment_size / 4); + ret = decode_filter(s, ctx, ac, offset, segment_size / 4); + if (ret < 0) + return ret; offset2 = segment_size / 4 + offset; - decode_filter(s, ctx, ac, offset2, segment_size / 4); + ret = decode_filter(s, ctx, ac, offset2, segment_size / 4); + if (ret < 0) + return ret; offset2 = segment_size / 4 + offset2; } else { - decode_filter(s, ctx, ac, offset, segment_size / 2); + ret = decode_filter(s, ctx, ac, offset, segment_size / 2); + if (ret < 0) + return ret; offset2 = segment_size / 2 + offset; } if (mode & 1) { - decode_filter(s, ctx, ac, offset2, segment_size / 2); + ret = decode_filter(s, ctx, ac, offset2, segment_size / 2); + if (ret < 0) + return ret; } else { - decode_filter(s, ctx, ac, offset2, segment_size / 4); - decode_filter(s, ctx, ac, segment_size / 4 + offset2, segment_size / 4); + ret = decode_filter(s, ctx, ac, offset2, segment_size / 4); + if (ret < 0) + return ret; + ret = decode_filter(s, ctx, ac, segment_size / 4 + offset2, segment_size / 4); + if (ret < 0) + return ret; } } else { - decode_filter(s, ctx, ac, offset, ctx->srate_pad); + ret = decode_filter(s, ctx, ac, offset, ctx->srate_pad); + if (ret < 0) + return ret; } } From 052674f3ce17139de73ea00bb690584240b0478a Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Mon, 13 Feb 2023 21:03:13 +0100 Subject: [PATCH 0259/2172] avcodec/rka: add u8 sample format support --- libavcodec/rka.c | 89 +++++++++++++++++++++++++++++------------------- 1 file changed, 54 insertions(+), 35 deletions(-) diff --git a/libavcodec/rka.c b/libavcodec/rka.c index 435fd10a3b4..f479942832d 100644 --- a/libavcodec/rka.c +++ b/libavcodec/rka.c @@ -857,26 +857,28 @@ static int rka_decode_frame(AVCodecContext *avctx, AVFrame *frame, if (s->channels == 2) { int16_t *l16 = (int16_t *)frame->extended_data[0]; int16_t *r16 = (int16_t *)frame->extended_data[1]; + uint8_t *l8 = frame->extended_data[0]; + uint8_t *r8 = frame->extended_data[1]; - switch (avctx->sample_fmt) { - case AV_SAMPLE_FMT_S16P: - for (int n = 0; n < frame->nb_samples;) { - ret = decode_ch_samples(avctx, &s->ch[0]); - if (ret == 0) { - frame->nb_samples = n; - break; - } - if (ret < 0 || n + ret > frame->nb_samples) - return AVERROR_INVALIDDATA; + for (int n = 0; n < frame->nb_samples;) { + ret = decode_ch_samples(avctx, &s->ch[0]); + if (ret == 0) { + frame->nb_samples = n; + break; + } + if (ret < 0 || n + ret > frame->nb_samples) + return AVERROR_INVALIDDATA; - ret = decode_ch_samples(avctx, &s->ch[1]); - if (ret == 0) { - frame->nb_samples = n; - break; - } - if (ret < 0 || n + ret > frame->nb_samples) - return AVERROR_INVALIDDATA; + ret = decode_ch_samples(avctx, &s->ch[1]); + if (ret == 0) { + frame->nb_samples = n; + break; + } + if (ret < 0 || n + ret > frame->nb_samples) + return AVERROR_INVALIDDATA; + switch (avctx->sample_fmt) { + case AV_SAMPLE_FMT_S16P: for (int i = 0; i < ret; i++) { int l = s->ch[0].buf0[2560 + i]; int r = s->ch[1].buf0[2560 + i]; @@ -884,38 +886,55 @@ static int rka_decode_frame(AVCodecContext *avctx, AVFrame *frame, l16[n + i] = (l * 2 + r + 1) >> 1; r16[n + i] = (l * 2 - r + 1) >> 1; } + break; + case AV_SAMPLE_FMT_U8P: + for (int i = 0; i < ret; i++) { + int l = s->ch[0].buf0[2560 + i]; + int r = s->ch[1].buf0[2560 + i]; - n += ret; + l8[n + i] = ((l * 2 + r + 1) >> 1) + 0x7f; + r8[n + i] = ((l * 2 - r + 1) >> 1) + 0x7f; + } + break; + default: + return AVERROR_INVALIDDATA; } - break; - default: - return AVERROR_INVALIDDATA; + + n += ret; } } else { int16_t *m16 = (int16_t *)frame->data[0]; + uint8_t *m8 = frame->data[0]; - switch (avctx->sample_fmt) { - case AV_SAMPLE_FMT_S16P: - for (int n = 0; n < frame->nb_samples;) { - ret = decode_ch_samples(avctx, &s->ch[0]); - if (ret == 0) { - frame->nb_samples = n; - break; - } - if (ret < 0 || n + ret > frame->nb_samples) - return AVERROR_INVALIDDATA; + for (int n = 0; n < frame->nb_samples;) { + ret = decode_ch_samples(avctx, &s->ch[0]); + if (ret == 0) { + frame->nb_samples = n; + break; + } + if (ret < 0 || n + ret > frame->nb_samples) + return AVERROR_INVALIDDATA; + switch (avctx->sample_fmt) { + case AV_SAMPLE_FMT_S16P: for (int i = 0; i < ret; i++) { int m = s->ch[0].buf0[2560 + i]; m16[n + i] = m; } + break; + case AV_SAMPLE_FMT_U8P: + for (int i = 0; i < ret; i++) { + int m = s->ch[0].buf0[2560 + i]; - n += ret; + m8[n + i] = m + 0x7f; + } + break; + default: + return AVERROR_INVALIDDATA; } - break; - default: - return AVERROR_INVALIDDATA; + + n += ret; } } From 264cf752144ef109e580d1d420eeceacb898f8f9 Mon Sep 17 00:00:00 2001 From: Kieran Kunhya Date: Fri, 10 Feb 2023 22:46:03 +0000 Subject: [PATCH 0260/2172] vf_yadif: Remove unused emms_c --- libavfilter/vf_yadif.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/libavfilter/vf_yadif.c b/libavfilter/vf_yadif.c index afa4d1d53db..1be02de1a94 100644 --- a/libavfilter/vf_yadif.c +++ b/libavfilter/vf_yadif.c @@ -252,8 +252,6 @@ static void filter(AVFilterContext *ctx, AVFrame *dstpic, ff_filter_execute(ctx, filter_slice, &td, NULL, FFMIN(h, ff_filter_get_nb_threads(ctx))); } - - emms_c(); } static av_cold void uninit(AVFilterContext *ctx) From 02ddfeadbee52c1ad8c023a93594a8cb957e11db Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Ekstr=C3=B6m?= Date: Tue, 7 Feb 2023 21:37:10 +0200 Subject: [PATCH 0261/2172] avformat/movenc: allow writing out channel count in MP4 and 3GP MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ISOBMFF (14496-12) made this field ('channelcount') in the AudioSampleEntry structure non-template¹ somewhere before the release of the 2022 edition. As for ETSI TS 126 244 AKA 3GPP file format (V16.1.0, 2020-10), it does not seem contain any references limiting the channelcount entry in AudioSampleEntry or in its own definition of EVSSampleEntry. fate-mov-mp4-chapters test had to be adjusted as it output a mono vorbis stream, which would now be properly marked as such in the container. 1: As per 14496-12: Fields shown as “template” in the box descriptions are fields which are coded with a default value unless a derived specification defines their use and permits writers to use other values than the default. --- libavformat/movenc.c | 8 +------- tests/ref/fate/mov-mp4-chapters | 2 +- 2 files changed, 2 insertions(+), 8 deletions(-) diff --git a/libavformat/movenc.c b/libavformat/movenc.c index aca8b9d5853..c4fcb5f8b1b 100644 --- a/libavformat/movenc.c +++ b/libavformat/movenc.c @@ -1241,13 +1241,7 @@ static int mov_write_audio_tag(AVFormatContext *s, AVIOContext *pb, MOVMuxContex avio_wb16(pb, 16); avio_wb16(pb, track->audio_vbr ? -2 : 0); /* compression ID */ } else { /* reserved for mp4/3gp */ - if (track->par->codec_id == AV_CODEC_ID_FLAC || - track->par->codec_id == AV_CODEC_ID_ALAC || - track->par->codec_id == AV_CODEC_ID_OPUS) { - avio_wb16(pb, track->par->ch_layout.nb_channels); - } else { - avio_wb16(pb, 2); - } + avio_wb16(pb, track->par->ch_layout.nb_channels); if (track->par->codec_id == AV_CODEC_ID_FLAC || track->par->codec_id == AV_CODEC_ID_ALAC) { avio_wb16(pb, track->par->bits_per_raw_sample); diff --git a/tests/ref/fate/mov-mp4-chapters b/tests/ref/fate/mov-mp4-chapters index 34f84de1b1e..75cd3b3438d 100644 --- a/tests/ref/fate/mov-mp4-chapters +++ b/tests/ref/fate/mov-mp4-chapters @@ -1,4 +1,4 @@ -1fd844c2f5bf77c3344e88e30ad994e1 *tests/data/fate/mov-mp4-chapters.mp4 +7b6aaa99c86fa1f5abfc9f242abcfffa *tests/data/fate/mov-mp4-chapters.mp4 111248 tests/data/fate/mov-mp4-chapters.mp4 #extradata 0: 3469, 0xc6769ddc #tb 0: 1/44100 From b5534b94df7f9f5b3b5cd2bbc5eec98a360d2f96 Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Tue, 14 Feb 2023 09:46:46 +0100 Subject: [PATCH 0262/2172] avcodec/rka: fix lossy mode decoding --- libavcodec/rka.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/libavcodec/rka.c b/libavcodec/rka.c index f479942832d..7b3ba771a67 100644 --- a/libavcodec/rka.c +++ b/libavcodec/rka.c @@ -161,9 +161,9 @@ static av_cold int rka_decode_init(AVCodecContext *avctx) if ((avctx->extradata[15] & 4) != 0) cmode = -cmode; - s->ch[0].cmode = s->ch[1].cmode = cmode; - s->ch[0].cmode2 = -s->ch[0].cmode; - s->ch[1].cmode2 = -s->ch[1].cmode; + s->ch[0].cmode = s->ch[1].cmode = cmode < 0 ? 2 : cmode; + s->ch[0].cmode2 = cmode < 0 ? FFABS(cmode) : 0; + s->ch[1].cmode2 = cmode < 0 ? FFABS(cmode) : 0; av_log(avctx, AV_LOG_DEBUG, "cmode: %d\n", cmode); return 0; @@ -662,7 +662,9 @@ static int mdl64_decode(ACoder *ac, Model64 *ctx, int *dst) return 0; } -static const uint8_t tab[] = { 0, 3, 3, 2, 2, 1, 1, 1, 1 }; +static const uint8_t tab[16] = { + 0, 3, 3, 2, 2, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0 +}; static int decode_filter(RKAContext *s, ChContext *ctx, ACoder *ac, int off, unsigned size) { @@ -729,7 +731,7 @@ static int decode_filter(RKAContext *s, ChContext *ctx, ACoder *ac, int off, uns } ctx->buf0[off] = ctx->buf1[off] + ctx->buf0[off + -1]; } else { - val = val * (1 << ctx->cmode & 0x1f); + val <<= ctx->cmode; sum += ctx->buf0[off + -1] + val; switch (s->bps) { case 16: sum = av_clip_int16(sum); break; From 4113445e9d4d7600c676ee0e42f1dc7968de6e0f Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Tue, 14 Feb 2023 09:55:02 +0100 Subject: [PATCH 0263/2172] avformat/rka: improve probing --- libavformat/rka.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavformat/rka.c b/libavformat/rka.c index c1e64ebcb31..cc55480345c 100644 --- a/libavformat/rka.c +++ b/libavformat/rka.c @@ -42,7 +42,7 @@ static int rka_probe(const AVProbeData *p) p->buf[12] > 0 && p->buf[12] <= 2 && (p->buf[13] == 8 || p->buf[13] == 16) && - p->buf[15] & 2 != 0) + (p->buf[15] & 2) != 0) return AVPROBE_SCORE_EXTENSION + 30; return 0; } From cb350367660032e2e47fa379a3f119ddf60eb029 Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Wed, 15 Feb 2023 13:54:11 +0100 Subject: [PATCH 0264/2172] avcodec/rka: fix array overflow --- libavcodec/rka.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/libavcodec/rka.c b/libavcodec/rka.c index 7b3ba771a67..8719325a9ed 100644 --- a/libavcodec/rka.c +++ b/libavcodec/rka.c @@ -77,8 +77,8 @@ typedef struct ChContext { Model64 mdl64[4][11]; - int32_t buf0[12001]; - int32_t buf1[12001]; + int32_t buf0[131072+2560]; + int32_t buf1[131072+2560]; } ChContext; typedef struct RKAContext { @@ -701,6 +701,9 @@ static int decode_filter(RKAContext *s, ChContext *ctx, ACoder *ac, int off, uns for (int y = 0; y < FFMIN(split, size - x); y++, off++) { int midx, shift = idx, *src, sum = 16; + if (off >= FF_ARRAY_ELEMS(ctx->buf0)) + return -1; + midx = FFABS(last_val) >> shift; if (midx >= 15) { mdl64 = &ctx->mdl64[3][idx]; From 83a2007f40fdf70e3eb49bd5be6a46c8d223b3df Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Wed, 15 Feb 2023 14:08:28 +0100 Subject: [PATCH 0265/2172] avcodec/rka: fix decoding uncorrelated stereo --- libavcodec/rka.c | 57 ++++++++++++++++++++++++++---------------------- 1 file changed, 31 insertions(+), 26 deletions(-) diff --git a/libavcodec/rka.c b/libavcodec/rka.c index 8719325a9ed..da4ca52f359 100644 --- a/libavcodec/rka.c +++ b/libavcodec/rka.c @@ -90,6 +90,7 @@ typedef struct RKAContext { int bps; int align; int channels; + int correlated; int frame_samples; int last_nb_samples; uint32_t total_nb_samples; @@ -156,6 +157,7 @@ static av_cold int rka_decode_init(AVCodecContext *avctx) s->samples_left = s->total_nb_samples = (AV_RL32(avctx->extradata + 4)) / s->align; s->frame_samples = 131072 / s->align; s->last_nb_samples = s->total_nb_samples % s->frame_samples; + s->correlated = avctx->extradata[15] & 1; cmode = avctx->extradata[14] & 0xf; if ((avctx->extradata[15] & 4) != 0) @@ -859,7 +861,7 @@ static int rka_decode_frame(AVCodecContext *avctx, AVFrame *frame, if ((ret = ff_get_buffer(avctx, frame, 0)) < 0) return ret; - if (s->channels == 2) { + if (s->channels == 2 && s->correlated) { int16_t *l16 = (int16_t *)frame->extended_data[0]; int16_t *r16 = (int16_t *)frame->extended_data[1]; uint8_t *l8 = frame->extended_data[0]; @@ -908,35 +910,38 @@ static int rka_decode_frame(AVCodecContext *avctx, AVFrame *frame, n += ret; } } else { - int16_t *m16 = (int16_t *)frame->data[0]; - uint8_t *m8 = frame->data[0]; - for (int n = 0; n < frame->nb_samples;) { - ret = decode_ch_samples(avctx, &s->ch[0]); - if (ret == 0) { - frame->nb_samples = n; - break; - } - if (ret < 0 || n + ret > frame->nb_samples) - return AVERROR_INVALIDDATA; - - switch (avctx->sample_fmt) { - case AV_SAMPLE_FMT_S16P: - for (int i = 0; i < ret; i++) { - int m = s->ch[0].buf0[2560 + i]; - - m16[n + i] = m; + for (int ch = 0; ch < s->channels; ch++) { + int16_t *m16 = (int16_t *)frame->data[ch]; + uint8_t *m8 = frame->data[ch]; + + ret = decode_ch_samples(avctx, &s->ch[ch]); + if (ret == 0) { + frame->nb_samples = n; + break; } - break; - case AV_SAMPLE_FMT_U8P: - for (int i = 0; i < ret; i++) { - int m = s->ch[0].buf0[2560 + i]; - m8[n + i] = m + 0x7f; + if (ret < 0 || n + ret > frame->nb_samples) + return AVERROR_INVALIDDATA; + + switch (avctx->sample_fmt) { + case AV_SAMPLE_FMT_S16P: + for (int i = 0; i < ret; i++) { + int m = s->ch[ch].buf0[2560 + i]; + + m16[n + i] = m; + } + break; + case AV_SAMPLE_FMT_U8P: + for (int i = 0; i < ret; i++) { + int m = s->ch[ch].buf0[2560 + i]; + + m8[n + i] = m + 0x7f; + } + break; + default: + return AVERROR_INVALIDDATA; } - break; - default: - return AVERROR_INVALIDDATA; } n += ret; From 05b859af35ef4effa1a70b363f81834d6c5abbc8 Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Wed, 15 Feb 2023 14:11:16 +0100 Subject: [PATCH 0266/2172] avcodec/rka: fix channel value initialization --- libavcodec/rka.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libavcodec/rka.c b/libavcodec/rka.c index da4ca52f359..4c93caefff8 100644 --- a/libavcodec/rka.c +++ b/libavcodec/rka.c @@ -149,7 +149,8 @@ static av_cold int rka_decode_init(AVCodecContext *avctx) return AVERROR_INVALIDDATA; } - s->channels = avctx->ch_layout.nb_channels; + av_channel_layout_uninit(&avctx->ch_layout); + s->channels = avctx->ch_layout.nb_channels = avctx->extradata[12]; if (s->channels < 1 || s->channels > 2) return AVERROR_INVALIDDATA; From 5247dab6b1ca117de2e6df7f604663b5494d8541 Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Wed, 15 Feb 2023 14:13:38 +0100 Subject: [PATCH 0267/2172] avcodec/rka: fix long_name --- libavcodec/rka.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavcodec/rka.c b/libavcodec/rka.c index 4c93caefff8..461baf1e1f2 100644 --- a/libavcodec/rka.c +++ b/libavcodec/rka.c @@ -977,7 +977,7 @@ static av_cold int rka_decode_close(AVCodecContext *avctx) const FFCodec ff_rka_decoder = { .p.name = "rka", - CODEC_LONG_NAME("RKA (RK Audio"), + CODEC_LONG_NAME("RKA (RK Audio)"), .p.type = AVMEDIA_TYPE_AUDIO, .p.id = AV_CODEC_ID_RKA, .priv_data_size = sizeof(RKAContext), From eee6492df7a7dc6f70170eb6e8a14ae00d12afc8 Mon Sep 17 00:00:00 2001 From: Marton Balint Date: Mon, 13 Feb 2023 22:34:15 +0100 Subject: [PATCH 0268/2172] avcodec/libx265: fix else clause when zeroing reordered_opaque MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit CC libavcodec/libx265.o libavcodec/libx265.c: In function ‘libx265_encode_frame’: libavcodec/libx265.c:781:5: warning: this ‘else’ clause does not guard... [-Wmisleading-indentation] else ^~~~ libavcodec/libx265.c:782:1: note: ...this statement, but the latter is misleadingly indented as if it were guarded by the ‘else’ FF_DISABLE_DEPRECATION_WARNINGS ^~~ Signed-off-by: Marton Balint --- libavcodec/libx265.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libavcodec/libx265.c b/libavcodec/libx265.c index 6a2600c5e7e..420d0953af1 100644 --- a/libavcodec/libx265.c +++ b/libavcodec/libx265.c @@ -778,10 +778,11 @@ FF_ENABLE_DEPRECATION_WARNINGS rd_release(ctx, idx); } #if FF_API_REORDERED_OPAQUE - else + else { FF_DISABLE_DEPRECATION_WARNINGS avctx->reordered_opaque = 0; FF_ENABLE_DEPRECATION_WARNINGS + } #endif *got_packet = 1; From 927042b409fc19a62085888b3a349d7e9e013b2e Mon Sep 17 00:00:00 2001 From: Marton Balint Date: Mon, 13 Feb 2023 01:50:12 +0100 Subject: [PATCH 0269/2172] avformat: deprecate AVFormatContext io_close callback io_close2 should be used instead. Signed-off-by: Marton Balint --- doc/APIchanges | 4 ++++ libavformat/avformat.c | 6 ++++++ libavformat/avformat.h | 5 +++++ libavformat/dashenc.c | 4 ++++ libavformat/fifo.c | 4 ++++ libavformat/hlsenc.c | 4 ++++ libavformat/imfdec.c | 4 ++++ libavformat/options.c | 6 ++++++ libavformat/segment.c | 4 ++++ libavformat/tee.c | 4 ++++ libavformat/version_major.h | 1 + 11 files changed, 46 insertions(+) diff --git a/doc/APIchanges b/doc/APIchanges index 3ca724724b9..29161e30bfd 100644 --- a/doc/APIchanges +++ b/doc/APIchanges @@ -2,6 +2,10 @@ The last version increases of all libraries were on 2023-02-09 API changes, most recent first: +2023-02-16 - xxxxxxxxxx - lavf 60.2.100 - avformat.h + Deprecate AVFormatContext io_close callback. + The superior io_close2 callback should be used instead. + 2023-02-13 - xxxxxxxxxx - lavu 58.1.100 - frame.h Deprecate AVFrame.coded_picture_number and display_picture_number. Their usefulness is questionable and very few decoders set them. diff --git a/libavformat/avformat.c b/libavformat/avformat.c index fe7b068f4a2..708d90b38cc 100644 --- a/libavformat/avformat.c +++ b/libavformat/avformat.c @@ -854,10 +854,16 @@ int ff_format_io_close(AVFormatContext *s, AVIOContext **pb) { int ret = 0; if (*pb) { +#if FF_API_AVFORMAT_IO_CLOSE +FF_DISABLE_DEPRECATION_WARNINGS if (s->io_close == ff_format_io_close_default || s->io_close == NULL) +#endif ret = s->io_close2(s, *pb); +#if FF_API_AVFORMAT_IO_CLOSE else s->io_close(s, *pb); +FF_ENABLE_DEPRECATION_WARNINGS +#endif } *pb = NULL; return ret; diff --git a/libavformat/avformat.h b/libavformat/avformat.h index b986aacc785..1916aa2dc55 100644 --- a/libavformat/avformat.h +++ b/libavformat/avformat.h @@ -1663,10 +1663,15 @@ typedef struct AVFormatContext { int (*io_open)(struct AVFormatContext *s, AVIOContext **pb, const char *url, int flags, AVDictionary **options); +#if FF_API_AVFORMAT_IO_CLOSE /** * A callback for closing the streams opened with AVFormatContext.io_open(). + * + * @deprecated use io_close2 */ + attribute_deprecated void (*io_close)(struct AVFormatContext *s, AVIOContext *pb); +#endif /** * ',' separated list of disallowed protocols. diff --git a/libavformat/dashenc.c b/libavformat/dashenc.c index 52865eacb51..17fe5f430c6 100644 --- a/libavformat/dashenc.c +++ b/libavformat/dashenc.c @@ -1551,7 +1551,11 @@ static int dash_init(AVFormatContext *s) return AVERROR_MUXER_NOT_FOUND; ctx->interrupt_callback = s->interrupt_callback; ctx->opaque = s->opaque; +#if FF_API_AVFORMAT_IO_CLOSE +FF_DISABLE_DEPRECATION_WARNINGS ctx->io_close = s->io_close; +FF_ENABLE_DEPRECATION_WARNINGS +#endif 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 ebadeef645d..9a3a23729c9 100644 --- a/libavformat/fifo.c +++ b/libavformat/fifo.c @@ -501,7 +501,11 @@ static int fifo_mux_init(AVFormatContext *avf, const AVOutputFormat *oformat, if (ret < 0) return ret; avf2->opaque = avf->opaque; +#if FF_API_AVFORMAT_IO_CLOSE +FF_DISABLE_DEPRECATION_WARNINGS avf2->io_close = avf->io_close; +FF_ENABLE_DEPRECATION_WARNINGS +#endif 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 dcc363b42e3..e1f96feda3e 100644 --- a/libavformat/hlsenc.c +++ b/libavformat/hlsenc.c @@ -869,7 +869,11 @@ static int hls_mux_init(AVFormatContext *s, VariantStream *vs) oc->max_delay = s->max_delay; oc->opaque = s->opaque; oc->io_open = s->io_open; +#if FF_API_AVFORMAT_IO_CLOSE +FF_DISABLE_DEPRECATION_WARNINGS oc->io_close = s->io_close; +FF_ENABLE_DEPRECATION_WARNINGS +#endif 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/imfdec.c b/libavformat/imfdec.c index 03de9ce151d..4932b7ff1fc 100644 --- a/libavformat/imfdec.c +++ b/libavformat/imfdec.c @@ -379,7 +379,11 @@ static int open_track_resource_context(AVFormatContext *s, return AVERROR(ENOMEM); track_resource->ctx->io_open = s->io_open; +#if FF_API_AVFORMAT_IO_CLOSE +FF_DISABLE_DEPRECATION_WARNINGS track_resource->ctx->io_close = s->io_close; +FF_ENABLE_DEPRECATION_WARNINGS +#endif track_resource->ctx->io_close2 = s->io_close2; track_resource->ctx->flags |= s->flags & ~AVFMT_FLAG_CUSTOM_IO; diff --git a/libavformat/options.c b/libavformat/options.c index c7681122cd7..22ad523b2dc 100644 --- a/libavformat/options.c +++ b/libavformat/options.c @@ -151,10 +151,12 @@ 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); } +#if FF_API_AVFORMAT_IO_CLOSE void ff_format_io_close_default(AVFormatContext *s, AVIOContext *pb) { avio_close(pb); } +#endif static int io_close2_default(AVFormatContext *s, AVIOContext *pb) { @@ -172,7 +174,11 @@ AVFormatContext *avformat_alloc_context(void) s = &si->pub; s->av_class = &av_format_context_class; s->io_open = io_open_default; +#if FF_API_AVFORMAT_IO_CLOSE +FF_DISABLE_DEPRECATION_WARNINGS s->io_close = ff_format_io_close_default; +FF_ENABLE_DEPRECATION_WARNINGS +#endif s->io_close2= io_close2_default; av_opt_set_defaults(s); diff --git a/libavformat/segment.c b/libavformat/segment.c index eb629b342ce..2a82f39f318 100644 --- a/libavformat/segment.c +++ b/libavformat/segment.c @@ -160,7 +160,11 @@ static int segment_mux_init(AVFormatContext *s) oc->max_delay = s->max_delay; av_dict_copy(&oc->metadata, s->metadata, 0); oc->opaque = s->opaque; +#if FF_API_AVFORMAT_IO_CLOSE +FF_DISABLE_DEPRECATION_WARNINGS oc->io_close = s->io_close; +FF_ENABLE_DEPRECATION_WARNINGS +#endif 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 960b2ea574b..cb555f52fd1 100644 --- a/libavformat/tee.c +++ b/libavformat/tee.c @@ -236,7 +236,11 @@ static int open_slave(AVFormatContext *avf, char *slave, TeeSlave *tee_slave) av_dict_copy(&avf2->metadata, avf->metadata, 0); avf2->opaque = avf->opaque; avf2->io_open = avf->io_open; +#if FF_API_AVFORMAT_IO_CLOSE +FF_DISABLE_DEPRECATION_WARNINGS avf2->io_close = avf->io_close; +FF_ENABLE_DEPRECATION_WARNINGS +#endif avf2->io_close2 = avf->io_close2; avf2->interrupt_callback = avf->interrupt_callback; avf2->flags = avf->flags; diff --git a/libavformat/version_major.h b/libavformat/version_major.h index 9ccf40bdc17..293fbd33971 100644 --- a/libavformat/version_major.h +++ b/libavformat/version_major.h @@ -44,6 +44,7 @@ #define FF_API_COMPUTE_PKT_FIELDS2 (LIBAVFORMAT_VERSION_MAJOR < 61) #define FF_API_GET_END_PTS (LIBAVFORMAT_VERSION_MAJOR < 61) #define FF_API_AVIODIRCONTEXT (LIBAVFORMAT_VERSION_MAJOR < 61) +#define FF_API_AVFORMAT_IO_CLOSE (LIBAVFORMAT_VERSION_MAJOR < 61) #define FF_API_R_FRAME_RATE 1 From 742dfa28150911a9cd7deee1fd935320cf707f6f Mon Sep 17 00:00:00 2001 From: Haihao Xiang Date: Tue, 7 Feb 2023 11:59:06 +0800 Subject: [PATCH 0270/2172] lavfi/vf_stack_vaapi: factor out the common code for stack setting The common code will be used in QSV based stack filters. Signed-off-by: Haihao Xiang --- libavfilter/stack_internal.c | 355 +++++++++++++++++++++++++++++++ libavfilter/stack_internal.h | 60 ++++++ libavfilter/vf_stack_vaapi.c | 395 ++++------------------------------- 3 files changed, 452 insertions(+), 358 deletions(-) create mode 100644 libavfilter/stack_internal.c create mode 100644 libavfilter/stack_internal.h diff --git a/libavfilter/stack_internal.c b/libavfilter/stack_internal.c new file mode 100644 index 00000000000..0697ebdd12c --- /dev/null +++ b/libavfilter/stack_internal.c @@ -0,0 +1,355 @@ +/* + * 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 + */ + +#define OFFSET(x) offsetof(StackHWContext, x) +#define FLAGS (AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_FILTERING_PARAM) + +#define SET_OUTPUT_REGION(region, rx, ry, rw, rh) do { \ + region->x = rx; \ + region->y = ry; \ + region->width = rw; \ + region->height = rh; \ + } while (0) + +static int init_framesync(AVFilterContext *avctx) +{ + StackBaseContext *sctx = avctx->priv; + int ret; + + ret = ff_framesync_init(&sctx->fs, avctx, avctx->nb_inputs); + if (ret < 0) + return ret; + + sctx->fs.on_event = process_frame; + sctx->fs.opaque = sctx; + + for (int i = 0; i < sctx->nb_inputs; i++) { + FFFrameSyncIn *in = &sctx->fs.in[i]; + + in->before = EXT_STOP; + in->after = sctx->shortest ? EXT_STOP : EXT_INFINITY; + in->sync = 1; + in->time_base = avctx->inputs[i]->time_base; + } + + return ff_framesync_configure(&sctx->fs); +} + +static int config_comm_output(AVFilterLink *outlink) +{ + AVFilterContext *avctx = outlink->src; + StackBaseContext *sctx = avctx->priv; + AVFilterLink *inlink0 = avctx->inputs[0]; + int width, height, ret; + + if (sctx->mode == STACK_H) { + height = sctx->tile_height; + width = 0; + + if (!height) + height = inlink0->h; + + for (int i = 0; i < sctx->nb_inputs; i++) { + AVFilterLink *inlink = avctx->inputs[i]; + StackItemRegion *region = &sctx->regions[i]; + + SET_OUTPUT_REGION(region, width, 0, av_rescale(height, inlink->w, inlink->h), height); + width += av_rescale(height, inlink->w, inlink->h); + } + } else if (sctx->mode == STACK_V) { + height = 0; + width = sctx->tile_width; + + if (!width) + width = inlink0->w; + + for (int i = 0; i < sctx->nb_inputs; i++) { + AVFilterLink *inlink = avctx->inputs[i]; + StackItemRegion *region = &sctx->regions[i]; + + SET_OUTPUT_REGION(region, 0, height, width, av_rescale(width, inlink->h, inlink->w)); + height += av_rescale(width, inlink->h, inlink->w); + } + } else if (sctx->nb_grid_rows && sctx->nb_grid_columns) { + int xpos = 0, ypos = 0; + int ow, oh, k = 0; + + ow = sctx->tile_width; + oh = sctx->tile_height; + + if (!ow || !oh) { + ow = avctx->inputs[0]->w; + oh = avctx->inputs[0]->h; + } + + for (int i = 0; i < sctx->nb_grid_columns; i++) { + ypos = 0; + + for (int j = 0; j < sctx->nb_grid_rows; j++) { + StackItemRegion *region = &sctx->regions[k++]; + + SET_OUTPUT_REGION(region, xpos, ypos, ow, oh); + ypos += oh; + } + + xpos += ow; + } + + width = ow * sctx->nb_grid_columns; + height = oh * sctx->nb_grid_rows; + } else { + char *arg, *p = sctx->layout, *saveptr = NULL; + char *arg2, *p2, *saveptr2 = NULL; + char *arg3, *p3, *saveptr3 = NULL; + int xpos, ypos, size; + int ow, oh; + + width = 0; + height = 0; + + for (int i = 0; i < sctx->nb_inputs; i++) { + AVFilterLink *inlink = avctx->inputs[i]; + StackItemRegion *region = &sctx->regions[i]; + + ow = inlink->w; + oh = inlink->h; + + if (!(arg = av_strtok(p, "|", &saveptr))) + return AVERROR(EINVAL); + + p = NULL; + p2 = arg; + xpos = ypos = 0; + + for (int j = 0; j < 3; j++) { + if (!(arg2 = av_strtok(p2, "_", &saveptr2))) { + if (j == 2) + break; + else + return AVERROR(EINVAL); + } + + p2 = NULL; + p3 = arg2; + + if (j == 2) { + if ((ret = av_parse_video_size(&ow, &oh, p3)) < 0) { + av_log(avctx, AV_LOG_ERROR, "Invalid size '%s'\n", p3); + return ret; + } + + break; + } + + while ((arg3 = av_strtok(p3, "+", &saveptr3))) { + p3 = NULL; + if (sscanf(arg3, "w%d", &size) == 1) { + if (size == i || size < 0 || size >= sctx->nb_inputs) + return AVERROR(EINVAL); + + if (!j) + xpos += sctx->regions[size].width; + else + ypos += sctx->regions[size].width; + } else if (sscanf(arg3, "h%d", &size) == 1) { + if (size == i || size < 0 || size >= sctx->nb_inputs) + return AVERROR(EINVAL); + + if (!j) + xpos += sctx->regions[size].height; + else + ypos += sctx->regions[size].height; + } else if (sscanf(arg3, "%d", &size) == 1) { + if (size < 0) + return AVERROR(EINVAL); + + if (!j) + xpos += size; + else + ypos += size; + } else { + return AVERROR(EINVAL); + } + } + } + + SET_OUTPUT_REGION(region, xpos, ypos, ow, oh); + width = FFMAX(width, xpos + ow); + height = FFMAX(height, ypos + oh); + } + + } + + outlink->w = width; + outlink->h = height; + outlink->frame_rate = inlink0->frame_rate; + outlink->sample_aspect_ratio = inlink0->sample_aspect_ratio; + + for (int i = 1; i < sctx->nb_inputs; i++) { + AVFilterLink *inlink = avctx->inputs[i]; + if (outlink->frame_rate.num != inlink->frame_rate.num || + outlink->frame_rate.den != inlink->frame_rate.den) { + av_log(avctx, AV_LOG_VERBOSE, + "Video inputs have different frame rates, output will be VFR\n"); + outlink->frame_rate = av_make_q(1, 0); + break; + } + } + + ret = init_framesync(avctx); + if (ret < 0) + return ret; + + outlink->time_base = sctx->fs.time_base; + + return 0; +} + +static int stack_init(AVFilterContext *avctx) +{ + StackBaseContext *sctx = avctx->priv; + int ret; + + if (!strcmp(avctx->filter->name, HSTACK_NAME)) + sctx->mode = STACK_H; + else if (!strcmp(avctx->filter->name, VSTACK_NAME)) + sctx->mode = STACK_V; + else { + int is_grid; + + av_assert0(strcmp(avctx->filter->name, XSTACK_NAME) == 0); + sctx->mode = STACK_X; + is_grid = sctx->nb_grid_rows && sctx->nb_grid_columns; + + if (sctx->layout && is_grid) { + av_log(avctx, AV_LOG_ERROR, "Both layout and grid were specified. Only one is allowed.\n"); + return AVERROR(EINVAL); + } + + if (!sctx->layout && !is_grid) { + if (sctx->nb_inputs == 2) { + sctx->nb_grid_rows = 1; + sctx->nb_grid_columns = 2; + is_grid = 1; + } else { + av_log(avctx, AV_LOG_ERROR, "No layout or grid specified.\n"); + return AVERROR(EINVAL); + } + } + + if (is_grid) + sctx->nb_inputs = sctx->nb_grid_rows * sctx->nb_grid_columns; + + if (strcmp(sctx->fillcolor_str, "none") && + av_parse_color(sctx->fillcolor, sctx->fillcolor_str, -1, avctx) >= 0) { + sctx->fillcolor_enable = 1; + } else { + sctx->fillcolor_enable = 0; + } + } + + for (int i = 0; i < sctx->nb_inputs; i++) { + AVFilterPad pad = { 0 }; + + pad.type = AVMEDIA_TYPE_VIDEO; + pad.name = av_asprintf("input%d", i); + + if (!pad.name) + return AVERROR(ENOMEM); + + if ((ret = ff_append_inpad_free_name(avctx, &pad)) < 0) + return ret; + } + + sctx->regions = av_calloc(sctx->nb_inputs, sizeof(*sctx->regions)); + if (!sctx->regions) + return AVERROR(ENOMEM); + + return 0; +} + +static av_cold void stack_uninit(AVFilterContext *avctx) +{ + StackBaseContext *sctx = avctx->priv; + + av_freep(&sctx->regions); + ff_framesync_uninit(&sctx->fs); +} + +static int stack_activate(AVFilterContext *avctx) +{ + StackBaseContext *sctx = avctx->priv; + return ff_framesync_activate(&sctx->fs); +} + +static const AVFilterPad stack_outputs[] = { + { + .name = "default", + .type = AVMEDIA_TYPE_VIDEO, + .config_props = config_output, + }, +}; + +#define STACK_COMMON_OPTS \ + { "inputs", "Set number of inputs", OFFSET(base.nb_inputs), AV_OPT_TYPE_INT, { .i64 = 2 }, 2, UINT16_MAX, .flags = FLAGS }, \ + { "shortest", "Force termination when the shortest input terminates", OFFSET(base.shortest), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, FLAGS }, + +#define DEFINE_HSTACK_OPTIONS(api) \ + static const AVOption hstack_##api##_options[] = { \ + STACK_COMMON_OPTS \ + { "height", "Set output height (0 to use the height of input 0)", OFFSET(base.tile_height), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, UINT16_MAX, FLAGS }, \ + { NULL } \ + } + +#define DEFINE_VSTACK_OPTIONS(api) \ + static const AVOption vstack_##api##_options[] = { \ + STACK_COMMON_OPTS \ + { "width", "Set output width (0 to use the width of input 0)", OFFSET(base.tile_width), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, UINT16_MAX, FLAGS }, \ + { NULL } \ + } + +#define DEFINE_XSTACK_OPTIONS(api) \ + static const AVOption xstack_##api##_options[] = { \ + STACK_COMMON_OPTS \ + { "layout", "Set custom layout", OFFSET(base.layout), AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, .flags = FLAGS }, \ + { "grid", "set fixed size grid layout", OFFSET(base.nb_grid_columns), AV_OPT_TYPE_IMAGE_SIZE, {.str = NULL}, 0, 0, .flags = FLAGS }, \ + { "grid_tile_size", "set tile size in grid layout", OFFSET(base.tile_width), AV_OPT_TYPE_IMAGE_SIZE, {.str = NULL}, 0, 0, .flags = FLAGS }, \ + { "fill", "Set the color for unused pixels", OFFSET(base.fillcolor_str), AV_OPT_TYPE_STRING, {.str = "none"}, .flags = FLAGS }, \ + { NULL } \ + } + +#define DEFINE_STACK_FILTER(category, api, capi) \ + static const AVClass category##_##api##_class = { \ + .class_name = #category "_" #api, \ + .item_name = av_default_item_name, \ + .option = category##_##api##_options, \ + .version = LIBAVUTIL_VERSION_INT, \ + }; \ + const AVFilter ff_vf_##category##_##api = { \ + .name = #category "_" #api, \ + .description = NULL_IF_CONFIG_SMALL(#capi " " #category), \ + .priv_size = sizeof(StackHWContext), \ + .priv_class = &category##_##api##_class, \ + .init = api##_stack_init, \ + .uninit = api##_stack_uninit, \ + .activate = stack_activate, \ + FILTER_QUERY_FUNC(api##_stack_query_formats), \ + FILTER_OUTPUTS(stack_outputs), \ + .flags_internal = FF_FILTER_FLAG_HWFRAME_AWARE, \ + .flags = AVFILTER_FLAG_DYNAMIC_INPUTS, \ + } diff --git a/libavfilter/stack_internal.h b/libavfilter/stack_internal.h new file mode 100644 index 00000000000..ace88861529 --- /dev/null +++ b/libavfilter/stack_internal.h @@ -0,0 +1,60 @@ +/* + * 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_STACK_INTERNAL_H +#define AVFILTER_STACK_INTERNAL_H + +enum { + STACK_H = 0, + STACK_V = 1, + STACK_X = 2 +}; + +typedef struct StackItemRegion { + int x; + int y; + int width; + int height; +} StackItemRegion; + +typedef struct StackBaseContext { + HWContext hwctx; /**< must be the first field */ + + FFFrameSync fs; + int mode; + uint8_t fillcolor[4]; + int fillcolor_enable; + StackItemRegion *regions; + + /* Options */ + int nb_inputs; + int shortest; + int tile_width; + int tile_height; + int nb_grid_columns; + int nb_grid_rows; + char *layout; + char *fillcolor_str; +} StackBaseContext; + +static int config_comm_output(AVFilterLink *outlink); +static int stack_init(AVFilterContext *avctx); +static av_cold void stack_uninit(AVFilterContext *avctx); +static int stack_activate(AVFilterContext *avctx); + +#endif /* AVFILTER_STACK_INTERNAL_H */ diff --git a/libavfilter/vf_stack_vaapi.c b/libavfilter/vf_stack_vaapi.c index 403fbb19eb1..26dbe3f7aa7 100644 --- a/libavfilter/vf_stack_vaapi.c +++ b/libavfilter/vf_stack_vaapi.c @@ -42,33 +42,17 @@ #include "framesync.h" #include "vaapi_vpp.h" -#define OFFSET(x) offsetof(StackVAAPIContext, x) -#define FLAGS (AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_FILTERING_PARAM) - -enum { - STACK_VAAPI_H = 0, - STACK_VAAPI_V = 1, - STACK_VAAPI_X = 2 -}; +#define HSTACK_NAME "hstack_vaapi" +#define VSTACK_NAME "vstack_vaapi" +#define XSTACK_NAME "xstack_vaapi" +#define HWContext VAAPIVPPContext +#define StackHWContext StackVAAPIContext +#include "stack_internal.h" typedef struct StackVAAPIContext { - VAAPIVPPContext vppctx; /**< must be the first field */ + StackBaseContext base; - FFFrameSync fs; - int mode; VARectangle *rects; - uint8_t fillcolor[4]; - int fillcolor_enable; - - /* Options */ - int nb_inputs; - int shortest; - int tile_width; - int tile_height; - int nb_grid_columns; - int nb_grid_rows; - char *layout; - char *fillcolor_str; } StackVAAPIContext; static int process_frame(FFFrameSync *fs) @@ -122,14 +106,14 @@ static int process_frame(FFFrameSync *fs) params[i].surface = (VASurfaceID)(uintptr_t)iframe->data[3]; params[i].output_region = &sctx->rects[i]; - if (sctx->fillcolor_enable) - params[i].output_background_color = (sctx->fillcolor[3] << 24 | - sctx->fillcolor[0] << 16 | - sctx->fillcolor[1] << 8 | - sctx->fillcolor[2]); + if (sctx->base.fillcolor_enable) + params[i].output_background_color = (sctx->base.fillcolor[3] << 24 | + sctx->base.fillcolor[0] << 16 | + sctx->base.fillcolor[1] << 8 | + sctx->base.fillcolor[2]); } - oframe->pts = av_rescale_q(sctx->fs.pts, sctx->fs.time_base, outlink->time_base); + oframe->pts = av_rescale_q(sctx->base.fs.pts, sctx->base.fs.time_base, outlink->time_base); oframe->sample_aspect_ratio = outlink->sample_aspect_ratio; ret = ff_vaapi_vpp_render_pictures(avctx, params, avctx->nb_inputs, oframe); @@ -147,37 +131,6 @@ static int process_frame(FFFrameSync *fs) return ret; } -static int init_framesync(AVFilterContext *avctx) -{ - StackVAAPIContext *sctx = avctx->priv; - int ret; - - ret = ff_framesync_init(&sctx->fs, avctx, avctx->nb_inputs); - if (ret < 0) - return ret; - - sctx->fs.on_event = process_frame; - sctx->fs.opaque = sctx; - - for (int i = 0; i < sctx->nb_inputs; i++) { - FFFrameSyncIn *in = &sctx->fs.in[i]; - - in->before = EXT_STOP; - in->after = sctx->shortest ? EXT_STOP : EXT_INFINITY; - in->sync = 1; - in->time_base = avctx->inputs[i]->time_base; - } - - return ff_framesync_configure(&sctx->fs); -} - -#define SET_INPUT_REGION(rect, rx, ry, rw, rh) do { \ - rect->x = rx; \ - rect->y = ry; \ - rect->width = rw; \ - rect->height = rh; \ - } while (0) - static int config_output(AVFilterLink *outlink) { AVFilterContext *avctx = outlink->src; @@ -185,7 +138,7 @@ static int config_output(AVFilterLink *outlink) VAAPIVPPContext *vppctx = avctx->priv; AVFilterLink *inlink0 = avctx->inputs[0]; AVHWFramesContext *hwfc0 = NULL; - int width, height, ret; + int ret; if (inlink0->format != AV_PIX_FMT_VAAPI || !inlink0->hw_frames_ctx || !inlink0->hw_frames_ctx->data) { av_log(avctx, AV_LOG_ERROR, "Software pixel format is not supported.\n"); @@ -194,7 +147,7 @@ static int config_output(AVFilterLink *outlink) hwfc0 = (AVHWFramesContext *)inlink0->hw_frames_ctx->data; - for (int i = 1; i < sctx->nb_inputs; i++) { + for (int i = 1; i < sctx->base.nb_inputs; i++) { AVFilterLink *inlink = avctx->inputs[i]; AVHWFramesContext *hwfc = NULL; @@ -219,168 +172,19 @@ static int config_output(AVFilterLink *outlink) ff_vaapi_vpp_config_input(inlink0); vppctx->output_format = hwfc0->sw_format; - if (sctx->mode == STACK_VAAPI_H) { - height = sctx->tile_height; - width = 0; - - if (!height) - height = inlink0->h; - - for (int i = 0; i < sctx->nb_inputs; i++) { - AVFilterLink *inlink = avctx->inputs[i]; - VARectangle *rect = &sctx->rects[i]; - - SET_INPUT_REGION(rect, width, 0, av_rescale(height, inlink->w, inlink->h), height); - width += av_rescale(height, inlink->w, inlink->h); - } - } else if (sctx->mode == STACK_VAAPI_V) { - height = 0; - width = sctx->tile_width; - - if (!width) - width = inlink0->w; - - for (int i = 0; i < sctx->nb_inputs; i++) { - AVFilterLink *inlink = avctx->inputs[i]; - VARectangle *rect = &sctx->rects[i]; - - SET_INPUT_REGION(rect, 0, height, width, av_rescale(width, inlink->h, inlink->w)); - height += av_rescale(width, inlink->h, inlink->w); - } - } else if (sctx->nb_grid_rows && sctx->nb_grid_columns) { - int xpos = 0, ypos = 0; - int ow, oh, k = 0; - - ow = sctx->tile_width; - oh = sctx->tile_height; - - if (!ow || !oh) { - ow = avctx->inputs[0]->w; - oh = avctx->inputs[0]->h; - } - - for (int i = 0; i < sctx->nb_grid_columns; i++) { - ypos = 0; - - for (int j = 0; j < sctx->nb_grid_rows; j++) { - VARectangle *rect = &sctx->rects[k++]; - - SET_INPUT_REGION(rect, xpos, ypos, ow, oh); - ypos += oh; - } - - xpos += ow; - } - - width = ow * sctx->nb_grid_columns; - height = oh * sctx->nb_grid_rows; - } else { - char *arg, *p = sctx->layout, *saveptr = NULL; - char *arg2, *p2, *saveptr2 = NULL; - char *arg3, *p3, *saveptr3 = NULL; - int xpos, ypos, size; - int ow, oh; - - width = avctx->inputs[0]->w; - height = avctx->inputs[0]->h; - - for (int i = 0; i < sctx->nb_inputs; i++) { - AVFilterLink *inlink = avctx->inputs[i]; - VARectangle *rect = &sctx->rects[i]; - - ow = inlink->w; - oh = inlink->h; - - if (!(arg = av_strtok(p, "|", &saveptr))) - return AVERROR(EINVAL); - - p = NULL; - p2 = arg; - xpos = ypos = 0; - - for (int j = 0; j < 3; j++) { - if (!(arg2 = av_strtok(p2, "_", &saveptr2))) { - if (j == 2) - break; - else - return AVERROR(EINVAL); - } - - p2 = NULL; - p3 = arg2; - - if (j == 2) { - if ((ret = av_parse_video_size(&ow, &oh, p3)) < 0) { - av_log(avctx, AV_LOG_ERROR, "Invalid size '%s'\n", p3); - return ret; - } - - break; - } - - while ((arg3 = av_strtok(p3, "+", &saveptr3))) { - p3 = NULL; - if (sscanf(arg3, "w%d", &size) == 1) { - if (size == i || size < 0 || size >= sctx->nb_inputs) - return AVERROR(EINVAL); - - if (!j) - xpos += sctx->rects[size].width; - else - ypos += sctx->rects[size].width; - } else if (sscanf(arg3, "h%d", &size) == 1) { - if (size == i || size < 0 || size >= sctx->nb_inputs) - return AVERROR(EINVAL); - - if (!j) - xpos += sctx->rects[size].height; - else - ypos += sctx->rects[size].height; - } else if (sscanf(arg3, "%d", &size) == 1) { - if (size < 0) - return AVERROR(EINVAL); - - if (!j) - xpos += size; - else - ypos += size; - } else { - return AVERROR(EINVAL); - } - } - } - - SET_INPUT_REGION(rect, xpos, ypos, ow, oh); - width = FFMAX(width, xpos + ow); - height = FFMAX(height, ypos + oh); - } - - } - - outlink->w = width; - outlink->h = height; - outlink->frame_rate = inlink0->frame_rate; - outlink->sample_aspect_ratio = inlink0->sample_aspect_ratio; - - for (int i = 1; i < sctx->nb_inputs; i++) { - AVFilterLink *inlink = avctx->inputs[i]; - if (outlink->frame_rate.num != inlink->frame_rate.num || - outlink->frame_rate.den != inlink->frame_rate.den) { - av_log(avctx, AV_LOG_VERBOSE, - "Video inputs have different frame rates, output will be VFR\n"); - outlink->frame_rate = av_make_q(1, 0); - break; - } - } - - ret = init_framesync(avctx); + ret = config_comm_output(outlink); if (ret < 0) return ret; - outlink->time_base = sctx->fs.time_base; + for (int i = 0; i < sctx->base.nb_inputs; i++) { + sctx->rects[i].x = sctx->base.regions[i].x; + sctx->rects[i].y = sctx->base.regions[i].y; + sctx->rects[i].width = sctx->base.regions[i].width; + sctx->rects[i].height = sctx->base.regions[i].height; + } - vppctx->output_width = width; - vppctx->output_height = height; + vppctx->output_width = outlink->w; + vppctx->output_height = outlink->h; return ff_vaapi_vpp_config_output(outlink); } @@ -391,59 +195,12 @@ static int vaapi_stack_init(AVFilterContext *avctx) VAAPIVPPContext *vppctx = avctx->priv; int ret; - if (!strcmp(avctx->filter->name, "hstack_vaapi")) - sctx->mode = STACK_VAAPI_H; - else if (!strcmp(avctx->filter->name, "vstack_vaapi")) - sctx->mode = STACK_VAAPI_V; - else { - int is_grid; - - av_assert0(strcmp(avctx->filter->name, "xstack_vaapi") == 0); - sctx->mode = STACK_VAAPI_X; - is_grid = sctx->nb_grid_rows && sctx->nb_grid_columns; - - if (sctx->layout && is_grid) { - av_log(avctx, AV_LOG_ERROR, "Both layout and grid were specified. Only one is allowed.\n"); - return AVERROR(EINVAL); - } - - if (!sctx->layout && !is_grid) { - if (sctx->nb_inputs == 2) { - sctx->nb_grid_rows = 1; - sctx->nb_grid_columns = 2; - is_grid = 1; - } else { - av_log(avctx, AV_LOG_ERROR, "No layout or grid specified.\n"); - return AVERROR(EINVAL); - } - } - - if (is_grid) - sctx->nb_inputs = sctx->nb_grid_rows * sctx->nb_grid_columns; - - if (strcmp(sctx->fillcolor_str, "none") && - av_parse_color(sctx->fillcolor, sctx->fillcolor_str, -1, avctx) >= 0) { - sctx->fillcolor_enable = 1; - } else { - sctx->fillcolor_enable = 0; - } - } - - for (int i = 0; i < sctx->nb_inputs; i++) { - AVFilterPad pad = { 0 }; - - pad.type = AVMEDIA_TYPE_VIDEO; - pad.name = av_asprintf("input%d", i); - - if (!pad.name) - return AVERROR(ENOMEM); - - if ((ret = ff_append_inpad_free_name(avctx, &pad)) < 0) - return ret; - } + ret = stack_init(avctx); + if (ret) + return ret; /* stack region */ - sctx->rects = av_calloc(sctx->nb_inputs, sizeof(*sctx->rects)); + sctx->rects = av_calloc(sctx->base.nb_inputs, sizeof(*sctx->rects)); if (!sctx->rects) return AVERROR(ENOMEM); @@ -457,14 +214,9 @@ static av_cold void vaapi_stack_uninit(AVFilterContext *avctx) { StackVAAPIContext *sctx = avctx->priv; - ff_framesync_uninit(&sctx->fs); - av_freep(&sctx->rects); -} + stack_uninit(avctx); -static int vaapi_stack_activate(AVFilterContext *avctx) -{ - StackVAAPIContext *sctx = avctx->priv; - return ff_framesync_activate(&sctx->fs); + av_freep(&sctx->rects); } static int vaapi_stack_query_formats(AVFilterContext *avctx) @@ -477,98 +229,25 @@ static int vaapi_stack_query_formats(AVFilterContext *avctx) return ff_set_common_formats_from_list(avctx, pixel_formats); } -static const AVFilterPad vaapi_stack_outputs[] = { - { - .name = "default", - .type = AVMEDIA_TYPE_VIDEO, - .config_props = config_output, - }, -}; - -#define STACK_COMMON_OPTS \ - { "inputs", "Set number of inputs", OFFSET(nb_inputs), AV_OPT_TYPE_INT, { .i64 = 2 }, 2, UINT16_MAX, .flags = FLAGS }, \ - { "shortest", "Force termination when the shortest input terminates", OFFSET(shortest), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, FLAGS }, +#include "stack_internal.c" #if CONFIG_HSTACK_VAAPI_FILTER -static const AVOption hstack_vaapi_options[] = { - STACK_COMMON_OPTS - - { "height", "Set output height (0 to use the height of input 0)", OFFSET(tile_height), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, UINT16_MAX, FLAGS }, - { NULL } -}; - -AVFILTER_DEFINE_CLASS(hstack_vaapi); - -const AVFilter ff_vf_hstack_vaapi = { - .name = "hstack_vaapi", - .description = NULL_IF_CONFIG_SMALL("VA-API hstack."), - .priv_size = sizeof(StackVAAPIContext), - .priv_class = &hstack_vaapi_class, - .init = vaapi_stack_init, - .uninit = vaapi_stack_uninit, - .activate = vaapi_stack_activate, - FILTER_QUERY_FUNC(vaapi_stack_query_formats), - FILTER_OUTPUTS(vaapi_stack_outputs), - .flags_internal = FF_FILTER_FLAG_HWFRAME_AWARE, - .flags = AVFILTER_FLAG_DYNAMIC_INPUTS, -}; +DEFINE_HSTACK_OPTIONS(vaapi); +DEFINE_STACK_FILTER(hstack, vaapi, "VA-API"); #endif #if CONFIG_VSTACK_VAAPI_FILTER -static const AVOption vstack_vaapi_options[] = { - STACK_COMMON_OPTS - - { "width", "Set output width (0 to use the width of input 0)", OFFSET(tile_width), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, UINT16_MAX, FLAGS }, - { NULL } -}; - -AVFILTER_DEFINE_CLASS(vstack_vaapi); - -const AVFilter ff_vf_vstack_vaapi = { - .name = "vstack_vaapi", - .description = NULL_IF_CONFIG_SMALL("VA-API vstack."), - .priv_size = sizeof(StackVAAPIContext), - .priv_class = &vstack_vaapi_class, - .init = vaapi_stack_init, - .uninit = vaapi_stack_uninit, - .activate = vaapi_stack_activate, - FILTER_QUERY_FUNC(vaapi_stack_query_formats), - FILTER_OUTPUTS(vaapi_stack_outputs), - .flags_internal = FF_FILTER_FLAG_HWFRAME_AWARE, - .flags = AVFILTER_FLAG_DYNAMIC_INPUTS, -}; +DEFINE_VSTACK_OPTIONS(vaapi); +DEFINE_STACK_FILTER(vstack, vaapi, "VA-API"); #endif #if CONFIG_XSTACK_VAAPI_FILTER -static const AVOption xstack_vaapi_options[] = { - STACK_COMMON_OPTS - - { "layout", "Set custom layout", OFFSET(layout), AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, .flags = FLAGS }, - { "grid", "set fixed size grid layout", OFFSET(nb_grid_columns), AV_OPT_TYPE_IMAGE_SIZE, {.str = NULL}, 0, 0, .flags = FLAGS }, - { "grid_tile_size", "set tile size in grid layout", OFFSET(tile_width), AV_OPT_TYPE_IMAGE_SIZE, {.str = NULL}, 0, 0, .flags = FLAGS }, - { "fill", "Set the color for unused pixels", OFFSET(fillcolor_str), AV_OPT_TYPE_STRING, {.str = "none"}, .flags = FLAGS }, - { NULL } -}; - -AVFILTER_DEFINE_CLASS(xstack_vaapi); - -const AVFilter ff_vf_xstack_vaapi = { - .name = "xstack_vaapi", - .description = NULL_IF_CONFIG_SMALL("VA-API xstack."), - .priv_size = sizeof(StackVAAPIContext), - .priv_class = &xstack_vaapi_class, - .init = vaapi_stack_init, - .uninit = vaapi_stack_uninit, - .activate = vaapi_stack_activate, - FILTER_OUTPUTS(vaapi_stack_outputs), - FILTER_QUERY_FUNC(vaapi_stack_query_formats), - .flags_internal = FF_FILTER_FLAG_HWFRAME_AWARE, - .flags = AVFILTER_FLAG_DYNAMIC_INPUTS, -}; +DEFINE_XSTACK_OPTIONS(vaapi); +DEFINE_STACK_FILTER(xstack, vaapi, "VA-API"); #endif From 0f407cdea291ac39505dd20a81ed63f3ddf34ef1 Mon Sep 17 00:00:00 2001 From: Haihao Xiang Date: Tue, 7 Feb 2023 11:59:07 +0800 Subject: [PATCH 0271/2172] avfilter: add QSV variants of the stack filters Include hstack_qsv, vstack_qsv and xstack_qsv. They may accept input streams with different sizes. Examples: $ ffmpeg -hwaccel qsv -hwaccel_output_format qsv -i input.mp4 \ -filter_complex "[0:v][0:v]hstack_qsv" -f null - $ ffmpeg \ -hwaccel qsv -hwaccel_output_format qsv -i input.mp4 \ -hwaccel qsv -hwaccel_output_format qsv -i input.mp4 \ -hwaccel qsv -hwaccel_output_format qsv -i input.mp4 \ -hwaccel qsv -hwaccel_output_format qsv -i input.mp4 \ -filter_complex "[0:v][1:v][2:v][3:v]xstack_qsv=inputs=4:fill=0x000000:layout=0_0_1920x1080|w0_0_1920x1080|0_h0_1920x1080|w0_h0_1920x1080" \ -f null - Signed-off-by: Haihao Xiang --- Changelog | 1 + configure | 6 + doc/filters.texi | 88 +++++++++++++ libavfilter/Makefile | 3 + libavfilter/allfilters.c | 3 + libavfilter/version.h | 2 +- libavfilter/vf_stack_qsv.c | 254 +++++++++++++++++++++++++++++++++++++ 7 files changed, 356 insertions(+), 1 deletion(-) create mode 100644 libavfilter/vf_stack_qsv.c diff --git a/Changelog b/Changelog index d15acbe6782..0644f39d597 100644 --- a/Changelog +++ b/Changelog @@ -44,6 +44,7 @@ version : - RKA decoder and demuxer - filtergraph syntax in ffmpeg CLI now supports passing file contents as option values, by prefixing option name with '/' +- hstack_qsv, vstack_qsv and xstack_qsv filters version 5.1: diff --git a/configure b/configure index 932805ccf3c..bf8ae1c7897 100755 --- a/configure +++ b/configure @@ -3772,6 +3772,12 @@ yadif_videotoolbox_filter_deps="metal corevideo videotoolbox" hstack_vaapi_filter_deps="vaapi_1" vstack_vaapi_filter_deps="vaapi_1" xstack_vaapi_filter_deps="vaapi_1" +hstack_qsv_filter_deps="libmfx" +hstack_qsv_filter_select="qsvvpp" +vstack_qsv_filter_deps="libmfx" +vstack_qsv_filter_select="qsvvpp" +xstack_qsv_filter_deps="libmfx" +xstack_qsv_filter_select="qsvvpp" # examples avio_http_serve_files_deps="avformat avutil fork" diff --git a/doc/filters.texi b/doc/filters.texi index a4e235d2afc..d65f6ca69d5 100644 --- a/doc/filters.texi +++ b/doc/filters.texi @@ -26802,6 +26802,94 @@ See @ref{xstack}. @c man end VAAPI VIDEO FILTERS +@chapter QSV Video Filters +@c man begin QSV VIDEO FILTERS + +Below is a description of the currently available QSV video filters. + +To enable compilation of these filters you need to configure FFmpeg with +@code{--enable-libmfx} or @code{--enable-libvpl}. + +To use QSV filters, you need to setup the QSV device correctly. For more information, please read @url{https://trac.ffmpeg.org/wiki/Hardware/QuickSync} + +@section hstack_qsv +Stack input videos horizontally. + +This is the QSV variant of the @ref{hstack} filter, each input stream may +have different height, this filter will scale down/up each input stream while +keeping the orignal aspect. + +It accepts the following options: + +@table @option +@item inputs +See @ref{hstack}. + +@item shortest +See @ref{hstack}. + +@item height +Set height of output. If set to 0, this filter will set height of output to +height of the first input stream. Default value is 0. +@end table + +@section vstack_qsv +Stack input videos vertically. + +This is the QSV variant of the @ref{vstack} filter, each input stream may +have different width, this filter will scale down/up each input stream while +keeping the orignal aspect. + +It accepts the following options: + +@table @option +@item inputs +See @ref{vstack}. + +@item shortest +See @ref{vstack}. + +@item width +Set width of output. If set to 0, this filter will set width of output to +width of the first input stream. Default value is 0. +@end table + +@section xstack_qsv +Stack video inputs into custom layout. + +This is the QSV variant of the @ref{xstack} filter. + +It accepts the following options: + +@table @option +@item inputs +See @ref{xstack}. + +@item shortest +See @ref{xstack}. + +@item layout +See @ref{xstack}. +Moreover, this permits the user to supply output size for each input stream. +@example +xstack_qsv=inputs=4:layout=0_0_1920x1080|0_h0_1920x1080|w0_0_1920x1080|w0_h0_1920x1080 +@end example + +@item grid +See @ref{xstack}. + +@item grid_tile_size +Set output size for each input stream when @option{grid} is set. If this option +is not set, this filter will set output size by default to the size of the +first input stream. For the syntax of this option, check the +@ref{video size syntax,,"Video size" section in the ffmpeg-utils manual,ffmpeg-utils}. + +@item fill +See @ref{xstack}. +@end table + +@c man end QSV VIDEO FILTERS + @chapter Video Sources @c man begin VIDEO SOURCES diff --git a/libavfilter/Makefile b/libavfilter/Makefile index 0173b11870f..b3d3d981dd4 100644 --- a/libavfilter/Makefile +++ b/libavfilter/Makefile @@ -561,6 +561,9 @@ OBJS-$(CONFIG_ZSCALE_FILTER) += vf_zscale.o OBJS-$(CONFIG_HSTACK_VAAPI_FILTER) += vf_stack_vaapi.o framesync.o vaapi_vpp.o OBJS-$(CONFIG_VSTACK_VAAPI_FILTER) += vf_stack_vaapi.o framesync.o vaapi_vpp.o OBJS-$(CONFIG_XSTACK_VAAPI_FILTER) += vf_stack_vaapi.o framesync.o vaapi_vpp.o +OBJS-$(CONFIG_HSTACK_QSV_FILTER) += vf_stack_qsv.o framesync.o +OBJS-$(CONFIG_VSTACK_QSV_FILTER) += vf_stack_qsv.o framesync.o +OBJS-$(CONFIG_XSTACK_QSV_FILTER) += vf_stack_qsv.o framesync.o OBJS-$(CONFIG_ALLRGB_FILTER) += vsrc_testsrc.o OBJS-$(CONFIG_ALLYUV_FILTER) += vsrc_testsrc.o diff --git a/libavfilter/allfilters.c b/libavfilter/allfilters.c index 9cdcca48534..d7db46c2af9 100644 --- a/libavfilter/allfilters.c +++ b/libavfilter/allfilters.c @@ -526,6 +526,9 @@ extern const AVFilter ff_vf_zscale; extern const AVFilter ff_vf_hstack_vaapi; extern const AVFilter ff_vf_vstack_vaapi; extern const AVFilter ff_vf_xstack_vaapi; +extern const AVFilter ff_vf_hstack_qsv; +extern const AVFilter ff_vf_vstack_qsv; +extern const AVFilter ff_vf_xstack_qsv; extern const AVFilter ff_vsrc_allrgb; extern const AVFilter ff_vsrc_allyuv; diff --git a/libavfilter/version.h b/libavfilter/version.h index 1e884d9b44c..bece922c7f0 100644 --- a/libavfilter/version.h +++ b/libavfilter/version.h @@ -31,7 +31,7 @@ #include "version_major.h" -#define LIBAVFILTER_VERSION_MINOR 1 +#define LIBAVFILTER_VERSION_MINOR 2 #define LIBAVFILTER_VERSION_MICRO 100 diff --git a/libavfilter/vf_stack_qsv.c b/libavfilter/vf_stack_qsv.c new file mode 100644 index 00000000000..9eb0748bd61 --- /dev/null +++ b/libavfilter/vf_stack_qsv.c @@ -0,0 +1,254 @@ +/* + * 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 + * Hardware accelerated hstack, vstack and xstack filters based on Intel Quick Sync Video VPP + */ + +#include "config_components.h" + +#include "libavutil/opt.h" +#include "libavutil/common.h" +#include "libavutil/pixdesc.h" +#include "libavutil/eval.h" +#include "libavutil/hwcontext.h" +#include "libavutil/avstring.h" +#include "libavutil/avassert.h" +#include "libavutil/imgutils.h" +#include "libavutil/mathematics.h" +#include "libavutil/parseutils.h" + +#include "internal.h" +#include "filters.h" +#include "formats.h" +#include "video.h" + +#include "framesync.h" +#include "qsvvpp.h" + +#define HSTACK_NAME "hstack_qsv" +#define VSTACK_NAME "vstack_qsv" +#define XSTACK_NAME "xstack_qsv" +#define HWContext QSVVPPContext +#define StackHWContext StackQSVContext +#include "stack_internal.h" + +typedef struct StackQSVContext { + StackBaseContext base; + + QSVVPPParam qsv_param; + mfxExtVPPComposite comp_conf; +} StackQSVContext; + +static void rgb2yuv(float r, float g, float b, int *y, int *u, int *v, int depth) +{ + *y = ((0.21260*219.0/255.0) * r + (0.71520*219.0/255.0) * g + + (0.07220*219.0/255.0) * b) * ((1 << depth) - 1); + *u = (-(0.11457*224.0/255.0) * r - (0.38543*224.0/255.0) * g + + (0.50000*224.0/255.0) * b + 0.5) * ((1 << depth) - 1); + *v = ((0.50000*224.0/255.0) * r - (0.45415*224.0/255.0) * g - + (0.04585*224.0/255.0) * b + 0.5) * ((1 << depth) - 1); +} + +static int process_frame(FFFrameSync *fs) +{ + AVFilterContext *ctx = fs->parent; + QSVVPPContext *qsv = fs->opaque; + AVFrame *frame = NULL; + int ret = 0; + + for (int i = 0; i < ctx->nb_inputs; i++) { + ret = ff_framesync_get_frame(fs, i, &frame, 0); + if (ret == 0) + ret = ff_qsvvpp_filter_frame(qsv, ctx->inputs[i], frame); + if (ret < 0 && ret != AVERROR(EAGAIN)) + break; + } + + if (ret == 0 && qsv->got_frame == 0) { + for (int i = 0; i < ctx->nb_inputs; i++) + FF_FILTER_FORWARD_WANTED(ctx->outputs[0], ctx->inputs[i]); + + ret = FFERROR_NOT_READY; + } + + return ret; +} + +static int config_output(AVFilterLink *outlink) +{ + AVFilterContext *ctx = outlink->src; + StackQSVContext *sctx = ctx->priv; + AVFilterLink *inlink0 = ctx->inputs[0]; + enum AVPixelFormat in_format; + int depth = 8, ret; + mfxVPPCompInputStream *is = sctx->comp_conf.InputStream; + + if (inlink0->format == AV_PIX_FMT_QSV) { + if (!inlink0->hw_frames_ctx || !inlink0->hw_frames_ctx->data) + return AVERROR(EINVAL); + + in_format = ((AVHWFramesContext*)inlink0->hw_frames_ctx->data)->sw_format; + } else + in_format = inlink0->format; + + sctx->qsv_param.out_sw_format = in_format; + + for (int i = 1; i < sctx->base.nb_inputs; i++) { + AVFilterLink *inlink = ctx->inputs[i]; + + if (inlink0->format == AV_PIX_FMT_QSV) { + AVHWFramesContext *hwfc0 = (AVHWFramesContext *)inlink0->hw_frames_ctx->data; + AVHWFramesContext *hwfc = (AVHWFramesContext *)inlink->hw_frames_ctx->data; + + if (inlink0->format != inlink->format) { + av_log(ctx, AV_LOG_ERROR, "Mixing hardware and software pixel formats is not supported.\n"); + + return AVERROR(EINVAL); + } else if (hwfc0->device_ctx != hwfc->device_ctx) { + av_log(ctx, AV_LOG_ERROR, "Inputs with different underlying QSV devices are forbidden.\n"); + + return AVERROR(EINVAL); + } + } + } + + if (in_format == AV_PIX_FMT_P010) + depth = 10; + + if (sctx->base.fillcolor_enable) { + int Y, U, V; + + rgb2yuv(sctx->base.fillcolor[0] / 255.0, sctx->base.fillcolor[1] / 255.0, + sctx->base.fillcolor[2] / 255.0, &Y, &U, &V, depth); + sctx->comp_conf.Y = Y; + sctx->comp_conf.U = U; + sctx->comp_conf.V = V; + } + + ret = config_comm_output(outlink); + if (ret < 0) + return ret; + + for (int i = 0; i < sctx->base.nb_inputs; i++) { + is[i].DstX = sctx->base.regions[i].x; + is[i].DstY = sctx->base.regions[i].y; + is[i].DstW = sctx->base.regions[i].width; + is[i].DstH = sctx->base.regions[i].height; + is[i].GlobalAlpha = 255; + is[i].GlobalAlphaEnable = 0; + is[i].PixelAlphaEnable = 0; + } + + return ff_qsvvpp_init(ctx, &sctx->qsv_param); +} + +/* + * Callback for qsvvpp + * @Note: qsvvpp composition does not generate PTS for result frame. + * so we assign the PTS from framesync to the output frame. + */ + +static int filter_callback(AVFilterLink *outlink, AVFrame *frame) +{ + StackQSVContext *sctx = outlink->src->priv; + + frame->pts = av_rescale_q(sctx->base.fs.pts, + sctx->base.fs.time_base, outlink->time_base); + return ff_filter_frame(outlink, frame); +} + + +static int qsv_stack_init(AVFilterContext *ctx) +{ + StackQSVContext *sctx = ctx->priv; + int ret; + + ret = stack_init(ctx); + if (ret) + return ret; + + /* fill composite config */ + sctx->comp_conf.Header.BufferId = MFX_EXTBUFF_VPP_COMPOSITE; + sctx->comp_conf.Header.BufferSz = sizeof(sctx->comp_conf); + sctx->comp_conf.NumInputStream = sctx->base.nb_inputs; + sctx->comp_conf.InputStream = av_calloc(sctx->base.nb_inputs, + sizeof(*sctx->comp_conf.InputStream)); + if (!sctx->comp_conf.InputStream) + return AVERROR(ENOMEM); + + /* initialize QSVVPP params */ + sctx->qsv_param.filter_frame = filter_callback; + sctx->qsv_param.ext_buf = av_mallocz(sizeof(*sctx->qsv_param.ext_buf)); + + if (!sctx->qsv_param.ext_buf) + return AVERROR(ENOMEM); + + sctx->qsv_param.ext_buf[0] = (mfxExtBuffer *)&sctx->comp_conf; + sctx->qsv_param.num_ext_buf = 1; + sctx->qsv_param.num_crop = 0; + + return 0; +} + +static av_cold void qsv_stack_uninit(AVFilterContext *ctx) +{ + StackQSVContext *sctx = ctx->priv; + + stack_uninit(ctx); + + ff_qsvvpp_close(ctx); + av_freep(&sctx->comp_conf.InputStream); + av_freep(&sctx->qsv_param.ext_buf); +} + +static int qsv_stack_query_formats(AVFilterContext *ctx) +{ + static const enum AVPixelFormat pixel_formats[] = { + AV_PIX_FMT_NV12, + AV_PIX_FMT_P010, + AV_PIX_FMT_QSV, + AV_PIX_FMT_NONE, + }; + + return ff_set_common_formats_from_list(ctx, pixel_formats); +} + +#include "stack_internal.c" + +#if CONFIG_HSTACK_QSV_FILTER + +DEFINE_HSTACK_OPTIONS(qsv); +DEFINE_STACK_FILTER(hstack, qsv, "Quick Sync Video"); + +#endif + +#if CONFIG_VSTACK_QSV_FILTER + +DEFINE_VSTACK_OPTIONS(qsv); +DEFINE_STACK_FILTER(vstack, qsv, "Quick Sync Video"); + +#endif + +#if CONFIG_XSTACK_QSV_FILTER + +DEFINE_XSTACK_OPTIONS(qsv); +DEFINE_STACK_FILTER(xstack, qsv, "Quick Sync Video"); + +#endif From b7a335c5e9d2cd47dc8adeca2edc6714fa2d2996 Mon Sep 17 00:00:00 2001 From: Wenbin Chen Date: Wed, 8 Feb 2023 16:04:50 +0800 Subject: [PATCH 0272/2172] libavfilter/qsvvpp: check the return value Signed-off-by: Wenbin Chen --- libavfilter/qsvvpp.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/libavfilter/qsvvpp.c b/libavfilter/qsvvpp.c index e181e7b5846..54e7284234b 100644 --- a/libavfilter/qsvvpp.c +++ b/libavfilter/qsvvpp.c @@ -441,7 +441,10 @@ static QSVFrame *submit_frame(QSVVPPContext *s, AVFilterLink *inlink, AVFrame *p return NULL; } - av_frame_copy_props(qsv_frame->frame, picref); + if (av_frame_copy_props(qsv_frame->frame, picref) < 0) { + av_frame_free(&qsv_frame->frame); + return NULL; + } } else qsv_frame->frame = av_frame_clone(picref); From e530d38bbf5f58e3e22f87dff635a50e267abb77 Mon Sep 17 00:00:00 2001 From: Wenbin Chen Date: Mon, 13 Feb 2023 16:49:26 +0800 Subject: [PATCH 0273/2172] libavcodec/qsvenc: Do not pass RGB solorspace to VPL/MSDK When encode RGB frame, Intel driver convert RGB to YUV, so we cannot set RGB colorspace to VPL/MSDK. Signed-off-by: Wenbin Chen --- libavcodec/qsvenc.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/libavcodec/qsvenc.c b/libavcodec/qsvenc.c index 2f0e94a9148..d3f7532fc0e 100644 --- a/libavcodec/qsvenc.c +++ b/libavcodec/qsvenc.c @@ -1185,7 +1185,12 @@ static int init_video_param(AVCodecContext *avctx, QSVEncContext *q) q->extvsi.ColourDescriptionPresent = 1; q->extvsi.ColourPrimaries = avctx->color_primaries; q->extvsi.TransferCharacteristics = avctx->color_trc; - q->extvsi.MatrixCoefficients = avctx->colorspace; + if (avctx->colorspace == AVCOL_SPC_RGB) + // RGB will be converted to YUV, so RGB colorspace is not supported + q->extvsi.MatrixCoefficients = AVCOL_SPC_UNSPECIFIED; + else + q->extvsi.MatrixCoefficients = avctx->colorspace; + } if ((avctx->codec_id != AV_CODEC_ID_VP9) && (q->extvsi.VideoFullRange || q->extvsi.ColourDescriptionPresent)) { From aeceefa6220ccb8eac625f78c6fa90d048ccd2de Mon Sep 17 00:00:00 2001 From: Wenbin Chen Date: Mon, 13 Feb 2023 17:03:17 +0800 Subject: [PATCH 0274/2172] libavcodec/qsvenc: Flush cached frames before reset encoder According to https://github.com/Intel-Media-SDK/MediaSDK/blob/master/doc/mediasdk-man.md#configuration-change. Before calling MFXVideoENCODE_Reset, The application needs to retrieve any cached frames in the SDK encoder. A loop is added before MFXVideoENCODE_Reset to retrieve cached frames and add them to async_fifo, so that dynamic configuration works when async_depth > 1. Signed-off-by: Wenbin Chen --- libavcodec/qsvenc.c | 122 ++++++++++++++++++++++++-------------------- 1 file changed, 66 insertions(+), 56 deletions(-) diff --git a/libavcodec/qsvenc.c b/libavcodec/qsvenc.c index d3f7532fc0e..fc64a086e49 100644 --- a/libavcodec/qsvenc.c +++ b/libavcodec/qsvenc.c @@ -1605,7 +1605,7 @@ int ff_qsv_enc_init(AVCodecContext *avctx, QSVEncContext *q) q->param.AsyncDepth = q->async_depth; - q->async_fifo = av_fifo_alloc2(q->async_depth, sizeof(QSVPacket), 0); + q->async_fifo = av_fifo_alloc2(q->async_depth, sizeof(QSVPacket), AV_FIFO_FLAG_AUTO_GROW); if (!q->async_fifo) return AVERROR(ENOMEM); @@ -2301,58 +2301,6 @@ static int update_pic_timing_sei(AVCodecContext *avctx, QSVEncContext *q) return updated; } -static int update_parameters(AVCodecContext *avctx, QSVEncContext *q, - const AVFrame *frame) -{ - int needReset = 0, ret = 0; - - if (!frame || avctx->codec_id == AV_CODEC_ID_MJPEG) - return 0; - - needReset = update_qp(avctx, q); - needReset |= update_max_frame_size(avctx, q); - needReset |= update_gop_size(avctx, q); - needReset |= update_rir(avctx, q); - needReset |= update_low_delay_brc(avctx, q); - needReset |= update_frame_rate(avctx, q); - needReset |= update_bitrate(avctx, q); - needReset |= update_pic_timing_sei(avctx, q); - ret = update_min_max_qp(avctx, q); - if (ret < 0) - return ret; - needReset |= ret; - if (!needReset) - return 0; - - if (avctx->hwaccel_context) { - AVQSVContext *qsv = avctx->hwaccel_context; - int i, j; - q->param.ExtParam = q->extparam; - for (i = 0; i < qsv->nb_ext_buffers; i++) - q->param.ExtParam[i] = qsv->ext_buffers[i]; - q->param.NumExtParam = qsv->nb_ext_buffers; - - for (i = 0; i < q->nb_extparam_internal; i++) { - for (j = 0; j < qsv->nb_ext_buffers; j++) { - if (qsv->ext_buffers[j]->BufferId == q->extparam_internal[i]->BufferId) - break; - } - if (j < qsv->nb_ext_buffers) - continue; - q->param.ExtParam[q->param.NumExtParam++] = q->extparam_internal[i]; - } - } else { - q->param.ExtParam = q->extparam_internal; - q->param.NumExtParam = q->nb_extparam_internal; - } - av_log(avctx, AV_LOG_DEBUG, "Parameter change, call msdk reset.\n"); - ret = MFXVideoENCODE_Reset(q->session, &q->param); - if (ret < 0) - return ff_qsv_print_error(avctx, ret, "Error during resetting"); - - return 0; -} - static int encode_frame(AVCodecContext *avctx, QSVEncContext *q, const AVFrame *frame) { @@ -2443,7 +2391,7 @@ static int encode_frame(AVCodecContext *avctx, QSVEncContext *q, if (ret < 0) { ret = (ret == MFX_ERR_MORE_DATA) ? - 0 : ff_qsv_print_error(avctx, ret, "Error during encoding"); + AVERROR(EAGAIN) : ff_qsv_print_error(avctx, ret, "Error during encoding"); goto free; } @@ -2453,7 +2401,9 @@ static int encode_frame(AVCodecContext *avctx, QSVEncContext *q, ret = 0; if (*pkt.sync) { - av_fifo_write(q->async_fifo, &pkt, 1); + ret = av_fifo_write(q->async_fifo, &pkt, 1); + if (ret < 0) + goto free; } else { free: av_freep(&pkt.sync); @@ -2471,6 +2421,66 @@ static int encode_frame(AVCodecContext *avctx, QSVEncContext *q, goto free; } +static int update_parameters(AVCodecContext *avctx, QSVEncContext *q, + const AVFrame *frame) +{ + int needReset = 0, ret = 0; + + if (!frame || avctx->codec_id == AV_CODEC_ID_MJPEG) + return 0; + + needReset = update_qp(avctx, q); + needReset |= update_max_frame_size(avctx, q); + needReset |= update_gop_size(avctx, q); + needReset |= update_rir(avctx, q); + needReset |= update_low_delay_brc(avctx, q); + needReset |= update_frame_rate(avctx, q); + needReset |= update_bitrate(avctx, q); + needReset |= update_pic_timing_sei(avctx, q); + ret = update_min_max_qp(avctx, q); + if (ret < 0) + return ret; + needReset |= ret; + if (!needReset) + return 0; + + if (avctx->hwaccel_context) { + AVQSVContext *qsv = avctx->hwaccel_context; + int i, j; + q->param.ExtParam = q->extparam; + for (i = 0; i < qsv->nb_ext_buffers; i++) + q->param.ExtParam[i] = qsv->ext_buffers[i]; + q->param.NumExtParam = qsv->nb_ext_buffers; + + for (i = 0; i < q->nb_extparam_internal; i++) { + for (j = 0; j < qsv->nb_ext_buffers; j++) { + if (qsv->ext_buffers[j]->BufferId == q->extparam_internal[i]->BufferId) + break; + } + if (j < qsv->nb_ext_buffers) + continue; + q->param.ExtParam[q->param.NumExtParam++] = q->extparam_internal[i]; + } + } else { + q->param.ExtParam = q->extparam_internal; + q->param.NumExtParam = q->nb_extparam_internal; + } + + // Flush codec before reset configuration. + while (ret != AVERROR(EAGAIN)) { + ret = encode_frame(avctx, q, NULL); + if (ret < 0 && ret != AVERROR(EAGAIN)) + return ret; + } + + av_log(avctx, AV_LOG_DEBUG, "Parameter change, call msdk reset.\n"); + ret = MFXVideoENCODE_Reset(q->session, &q->param); + if (ret < 0) + return ff_qsv_print_error(avctx, ret, "Error during resetting"); + + return 0; +} + int ff_qsv_encode(AVCodecContext *avctx, QSVEncContext *q, AVPacket *pkt, const AVFrame *frame, int *got_packet) { @@ -2481,7 +2491,7 @@ int ff_qsv_encode(AVCodecContext *avctx, QSVEncContext *q, return ret; ret = encode_frame(avctx, q, frame); - if (ret < 0) + if (ret < 0 && ret != AVERROR(EAGAIN)) return ret; if ((av_fifo_can_read(q->async_fifo) >= q->async_depth) || From eabc304d123bb4193ae8dc7a602530c2e0d86450 Mon Sep 17 00:00:00 2001 From: Niklas Haas Date: Fri, 17 Feb 2023 18:35:39 +0100 Subject: [PATCH 0275/2172] avfilter/vf_libplacebo: add SMPTE ST2094 tone-mappers libplacebo gained these exciting new functions upstream. --- doc/filters.texi | 12 ++++++++++++ libavfilter/vf_libplacebo.c | 30 ++++++++++++++++++++---------- 2 files changed, 32 insertions(+), 10 deletions(-) diff --git a/doc/filters.texi b/doc/filters.texi index d65f6ca69d5..381a15a17df 100644 --- a/doc/filters.texi +++ b/doc/filters.texi @@ -16074,6 +16074,18 @@ Automatic selection based on internal heuristics. This is the default. Performs no tone-mapping, just clips out-of-range colors. Retains perfect color accuracy for in-range colors but completely destroys out-of-range information. Does not perform any black point adaptation. Not configurable. +@item st2094-40 +EETF from SMPTE ST 2094-40 Annex B, which applies the Bezier curves from HDR10+ +dynamic metadata based on Bezier curves to perform tone-mapping. The OOTF used +is adjusted based on the ratio between the targeted and actual display peak +luminances. +@item st2094-10 +EETF from SMPTE ST 2094-10 Annex B.2, which takes into account the input signal +average luminance in addition to the maximum/minimum. The configurable contrast +parameter influences the slope of the linear output segment, defaulting to +@code{1.0} for no increase/decrease in contrast. Note that this does not +currently include the subjective gain/offset/gamma controls defined in Annex +B.3. @item bt.2390 EETF from the ITU-R Report BT.2390, a hermite spline roll-off with linear segment. The knee point offset is configurable. Note that this parameter diff --git a/libavfilter/vf_libplacebo.c b/libavfilter/vf_libplacebo.c index 5b310771072..7cd495de261 100644 --- a/libavfilter/vf_libplacebo.c +++ b/libavfilter/vf_libplacebo.c @@ -29,6 +29,8 @@ enum { TONE_MAP_AUTO, TONE_MAP_CLIP, + TONE_MAP_ST2094_40, + TONE_MAP_ST2094_10, TONE_MAP_BT2390, TONE_MAP_BT2446A, TONE_MAP_SPLINE, @@ -41,16 +43,20 @@ enum { }; static const struct pl_tone_map_function * const tonemapping_funcs[TONE_MAP_COUNT] = { - [TONE_MAP_AUTO] = &pl_tone_map_auto, - [TONE_MAP_CLIP] = &pl_tone_map_clip, - [TONE_MAP_BT2390] = &pl_tone_map_bt2390, - [TONE_MAP_BT2446A] = &pl_tone_map_bt2446a, - [TONE_MAP_SPLINE] = &pl_tone_map_spline, - [TONE_MAP_REINHARD] = &pl_tone_map_reinhard, - [TONE_MAP_MOBIUS] = &pl_tone_map_mobius, - [TONE_MAP_HABLE] = &pl_tone_map_hable, - [TONE_MAP_GAMMA] = &pl_tone_map_gamma, - [TONE_MAP_LINEAR] = &pl_tone_map_linear, + [TONE_MAP_AUTO] = &pl_tone_map_auto, + [TONE_MAP_CLIP] = &pl_tone_map_clip, +#if PL_API_VER >= 246 + [TONE_MAP_ST2094_40] = &pl_tone_map_st2094_40, + [TONE_MAP_ST2094_10] = &pl_tone_map_st2094_10, +#endif + [TONE_MAP_BT2390] = &pl_tone_map_bt2390, + [TONE_MAP_BT2446A] = &pl_tone_map_bt2446a, + [TONE_MAP_SPLINE] = &pl_tone_map_spline, + [TONE_MAP_REINHARD] = &pl_tone_map_reinhard, + [TONE_MAP_MOBIUS] = &pl_tone_map_mobius, + [TONE_MAP_HABLE] = &pl_tone_map_hable, + [TONE_MAP_GAMMA] = &pl_tone_map_gamma, + [TONE_MAP_LINEAR] = &pl_tone_map_linear, }; typedef struct LibplaceboContext { @@ -790,6 +796,10 @@ static const AVOption libplacebo_options[] = { { "tonemapping", "Tone-mapping algorithm", OFFSET(tonemapping), AV_OPT_TYPE_INT, {.i64 = TONE_MAP_AUTO}, 0, TONE_MAP_COUNT - 1, DYNAMIC, "tonemap" }, { "auto", "Automatic selection", 0, AV_OPT_TYPE_CONST, {.i64 = TONE_MAP_AUTO}, 0, 0, STATIC, "tonemap" }, { "clip", "No tone mapping (clip", 0, AV_OPT_TYPE_CONST, {.i64 = TONE_MAP_CLIP}, 0, 0, STATIC, "tonemap" }, +#if PL_API_VER >= 246 + { "st2094-40", "SMPTE ST 2094-40", 0, AV_OPT_TYPE_CONST, {.i64 = TONE_MAP_ST2094_40}, 0, 0, STATIC, "tonemap" }, + { "st2094-10", "SMPTE ST 2094-10", 0, AV_OPT_TYPE_CONST, {.i64 = TONE_MAP_ST2094_10}, 0, 0, STATIC, "tonemap" }, +#endif { "bt.2390", "ITU-R BT.2390 EETF", 0, AV_OPT_TYPE_CONST, {.i64 = TONE_MAP_BT2390}, 0, 0, STATIC, "tonemap" }, { "bt.2446a", "ITU-R BT.2446 Method A", 0, AV_OPT_TYPE_CONST, {.i64 = TONE_MAP_BT2446A}, 0, 0, STATIC, "tonemap" }, { "spline", "Single-pivot polynomial spline", 0, AV_OPT_TYPE_CONST, {.i64 = TONE_MAP_SPLINE}, 0, 0, STATIC, "tonemap" }, From 097653bae6e6f78e8265476abc29cf296fe2a67c Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Tue, 14 Feb 2023 22:25:42 +0100 Subject: [PATCH 0276/2172] avformat/cdg: add probe --- libavformat/cdg.c | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/libavformat/cdg.c b/libavformat/cdg.c index 36f25e7f66b..f5982859114 100644 --- a/libavformat/cdg.c +++ b/libavformat/cdg.c @@ -26,6 +26,22 @@ #define CDG_COMMAND 0x09 #define CDG_MASK 0x3F +static int read_probe(const AVProbeData *p) +{ + const int cnt = p->buf_size / CDG_PACKET_SIZE; + int score = 0; + + for (int i = 0; i < cnt; i++) { + const int x = p->buf[i * CDG_PACKET_SIZE] & CDG_MASK; + + score += x == CDG_COMMAND; + if (x != CDG_COMMAND && x != 0) + return 0; + } + + return FFMIN(score, AVPROBE_SCORE_MAX); +} + static int read_header(AVFormatContext *s) { AVStream *vst; @@ -70,6 +86,7 @@ static int read_packet(AVFormatContext *s, AVPacket *pkt) const AVInputFormat ff_cdg_demuxer = { .name = "cdg", .long_name = NULL_IF_CONFIG_SMALL("CD Graphics"), + .read_probe = read_probe, .read_header = read_header, .read_packet = read_packet, .flags = AVFMT_GENERIC_INDEX, From 9f7e51e513665a72fb753887666259a883487947 Mon Sep 17 00:00:00 2001 From: Gyan Doshi Date: Sat, 11 Feb 2023 17:35:50 +0530 Subject: [PATCH 0277/2172] configure: select subordinate formats for HLS HLS segments may be MPEG-TS or fragmented MP4, so those (de)muxers are required for reading/writing HLS media segments. Fixes functionality with --disable-everything --enable-demuxer=hls --enable-muxer=hls --- configure | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/configure b/configure index bf8ae1c7897..b6616f00b6f 100755 --- a/configure +++ b/configure @@ -3436,8 +3436,8 @@ 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_demuxer_select="adts_header ac3_parser mov_demuxer mpegts_demuxer" +hls_muxer_select="mov_muxer mpegts_muxer" hls_muxer_suggest="gcrypt openssl" image2_alias_pix_demuxer_select="image2_demuxer" image2_brender_pix_demuxer_select="image2_demuxer" From 59a9727c241aa50f18e713dbabbdd5cf3d379411 Mon Sep 17 00:00:00 2001 From: Zhao Zhili Date: Tue, 7 Feb 2023 05:25:45 +0800 Subject: [PATCH 0278/2172] avformat/flvenc: fix EOS tag FLV spec only has AVC end of sequence tag, and the EOS tag has a CodecID as other video data packet. MPEG4 doesn't conformance to the spec, but it's there for a decade. So only 'fix' the EOS tag rather than remove it completely. Reviewed-by: Steven Liu Signed-off-by: Zhao Zhili --- libavformat/flvenc.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/libavformat/flvenc.c b/libavformat/flvenc.c index 81d9b6100da..64ea554dada 100644 --- a/libavformat/flvenc.c +++ b/libavformat/flvenc.c @@ -235,13 +235,16 @@ static void put_timestamp(AVIOContext *pb, int64_t ts) { avio_w8(pb, (ts >> 24) & 0x7F); } -static void put_avc_eos_tag(AVIOContext *pb, unsigned ts) +static void put_eos_tag(AVIOContext *pb, unsigned ts, enum AVCodecID codec_id) { + uint32_t tag = ff_codec_get_tag(flv_video_codec_ids, codec_id); + /* ub[4] FrameType = 1, ub[4] CodecId */ + tag |= 1 << 4; avio_w8(pb, FLV_TAG_TYPE_VIDEO); avio_wb24(pb, 5); /* Tag Data Size */ put_timestamp(pb, ts); avio_wb24(pb, 0); /* StreamId = 0 */ - avio_w8(pb, 23); /* ub[4] FrameType = 1, ub[4] CodecId = 7 */ + avio_w8(pb, tag); avio_w8(pb, 2); /* AVC end of sequence */ avio_wb24(pb, 0); /* Always 0 for AVC EOS. */ avio_wb32(pb, 16); /* Size of FLV tag */ @@ -783,7 +786,7 @@ static int flv_write_trailer(AVFormatContext *s) FLVStreamContext *sc = s->streams[i]->priv_data; if (par->codec_type == AVMEDIA_TYPE_VIDEO && (par->codec_id == AV_CODEC_ID_H264 || par->codec_id == AV_CODEC_ID_MPEG4)) - put_avc_eos_tag(pb, sc->last_ts); + put_eos_tag(pb, sc->last_ts, par->codec_id); } } From 42bf52b4c59c4e7997be08957a629dbc54116a38 Mon Sep 17 00:00:00 2001 From: Pierre-Anthony Lemieux Date: Tue, 10 Jan 2023 14:26:16 -0800 Subject: [PATCH 0279/2172] fate/imfdec: add audio test Adds a test where the temporal boundaries of audio and video resources do not line up. Signed-off-by: Pierre-Anthony Lemieux --- tests/fate/imf.mak | 3 + tests/ref/fate/imf-cpl-with-audio | 207 ++++++++++++++++++++++++++++++ 2 files changed, 210 insertions(+) create mode 100644 tests/ref/fate/imf-cpl-with-audio diff --git a/tests/fate/imf.mak b/tests/fate/imf.mak index feb54d13612..49ab35e7d99 100644 --- a/tests/fate/imf.mak +++ b/tests/fate/imf.mak @@ -1,6 +1,9 @@ FATE_IMF += fate-imf-cpl-with-repeat fate-imf-cpl-with-repeat: CMD = framecrc -f imf -i $(TARGET_SAMPLES)/imf/countdown/CPL_bb2ce11c-1bb6-4781-8e69-967183d02b9b.xml -c:v copy +FATE_IMF += fate-imf-cpl-with-audio +fate-imf-cpl-with-audio: CMD = framecrc -f imf -i $(TARGET_SAMPLES)/imf/countdown-audio/CPL_688f4f63-a317-4271-99bf-51444ff39c5b.xml -c:a copy + FATE_SAMPLES_FFMPEG-$(CONFIG_IMF_DEMUXER) += $(FATE_IMF) fate-imfdec: $(FATE_IMF) diff --git a/tests/ref/fate/imf-cpl-with-audio b/tests/ref/fate/imf-cpl-with-audio new file mode 100644 index 00000000000..b8d70ca5d89 --- /dev/null +++ b/tests/ref/fate/imf-cpl-with-audio @@ -0,0 +1,207 @@ +#tb 0: 1/24 +#media_type 0: video +#codec_id 0: rawvideo +#dimensions 0: 640x360 +#sar 0: 0/1 +#tb 1: 1/48000 +#media_type 1: audio +#codec_id 1: pcm_s24le +#sample_rate 1: 48000 +#channel_layout_name 1: stereo +0, 0, 0, 1, 1382400, 0x6a2c410c +1, 0, 0, 1920, 11520, 0x974f4bab +1, 1920, 1920, 1920, 11520, 0xdf793f69 +0, 1, 1, 1, 1382400, 0x5f0c67d2 +1, 3840, 3840, 1920, 11520, 0xfd69559a +0, 2, 2, 1, 1382400, 0x408e1262 +1, 5760, 5760, 1920, 11520, 0x28fa469b +0, 3, 3, 1, 1382400, 0x3567d455 +1, 7680, 7680, 1920, 11520, 0xe49161cf +0, 4, 4, 1, 1382400, 0x2312e68b +1, 9600, 9600, 1920, 11520, 0xb92c49ae +0, 5, 5, 1, 1382400, 0xe3d84ec2 +1, 11520, 11520, 1920, 11520, 0xd2b75d46 +0, 6, 6, 1, 1382400, 0xdbb3ab8c +1, 13440, 13440, 1920, 11520, 0xa13b5a9b +0, 7, 7, 1, 1382400, 0xeb250513 +1, 15360, 15360, 1920, 11520, 0xfe804299 +0, 8, 8, 1, 1382400, 0x26c3c8c0 +1, 17280, 17280, 1920, 11520, 0x7a8654d4 +0, 9, 9, 1, 1382400, 0xbc41a23e +1, 19200, 19200, 1920, 11520, 0x1a2e48a4 +0, 10, 10, 1, 1382400, 0x49d6a8de +1, 21120, 21120, 1920, 11520, 0x20504669 +0, 11, 11, 1, 1382400, 0x5e05cfa4 +1, 23040, 23040, 960, 5760, 0x74bf38f6 +0, 12, 12, 1, 1382400, 0x01327a34 +1, 24000, 24000, 1920, 11520, 0x974f4bab +1, 25920, 25920, 1920, 11520, 0xdf793f69 +0, 13, 13, 1, 1382400, 0x06ce3c36 +1, 27840, 27840, 1920, 11520, 0xfd69559a +0, 14, 14, 1, 1382400, 0x6aa24e6c +1, 29760, 29760, 1920, 11520, 0x28fa469b +0, 15, 15, 1, 1382400, 0x55d8b694 +1, 31680, 31680, 1920, 11520, 0xe49161cf +0, 16, 16, 1, 1382400, 0xcc6f136d +1, 33600, 33600, 1920, 11520, 0xb92c49ae +0, 17, 17, 1, 1382400, 0xe92b6ce5 +1, 35520, 35520, 1920, 11520, 0xd2b75d46 +0, 18, 18, 1, 1382400, 0x664d30a1 +1, 37440, 37440, 1920, 11520, 0xa13b5a9b +0, 19, 19, 1, 1382400, 0x09d80a1f +1, 39360, 39360, 1920, 11520, 0xfe804299 +0, 20, 20, 1, 1382400, 0x2b58536e +1, 41280, 41280, 1920, 11520, 0x7a8654d4 +0, 21, 21, 1, 1382400, 0xf24b7a34 +1, 43200, 43200, 1920, 11520, 0x1a2e48a4 +0, 22, 22, 1, 1382400, 0xe2a524c4 +1, 45120, 45120, 1920, 11520, 0x20504669 +0, 23, 23, 1, 1382400, 0xe841e6b7 +1, 47040, 47040, 1920, 11520, 0x7ad44ba6 +0, 24, 24, 1, 1382400, 0x6a2c410c +1, 48960, 48960, 1920, 11520, 0xc8934994 +0, 25, 25, 1, 1382400, 0x5f0c67d2 +1, 50880, 50880, 1920, 11520, 0x07ad70bb +0, 26, 26, 1, 1382400, 0x408e1262 +1, 52800, 52800, 1920, 11520, 0x1ba75d9a +0, 27, 27, 1, 1382400, 0x3567d455 +1, 54720, 54720, 1920, 11520, 0x0d4a435f +0, 28, 28, 1, 1382400, 0x2312e68b +1, 56640, 56640, 1920, 11520, 0x288b6c85 +0, 29, 29, 1, 1382400, 0xe3d84ec2 +1, 58560, 58560, 1920, 11520, 0x85da5f6e +0, 30, 30, 1, 1382400, 0xdbb3ab8c +1, 60480, 60480, 1920, 11520, 0x317a6ac0 +0, 31, 31, 1, 1382400, 0xeb250513 +1, 62400, 62400, 1920, 11520, 0xeea55aa3 +0, 32, 32, 1, 1382400, 0x26c3c8c0 +1, 64320, 64320, 1920, 11520, 0x598b604c +0, 33, 33, 1, 1382400, 0xbc41a23e +1, 66240, 66240, 1920, 11520, 0xbf6f4b95 +0, 34, 34, 1, 1382400, 0x49d6a8de +1, 68160, 68160, 1920, 11520, 0x52e66e81 +0, 35, 35, 1, 1382400, 0x5e05cfa4 +1, 70080, 70080, 1920, 11520, 0xca9b57c9 +0, 36, 36, 1, 1382400, 0x01327a34 +1, 72000, 72000, 1920, 11520, 0x974f4bab +1, 73920, 73920, 1920, 11520, 0xdf793f69 +0, 37, 37, 1, 1382400, 0x06ce3c36 +1, 75840, 75840, 1920, 11520, 0xfd69559a +0, 38, 38, 1, 1382400, 0x6aa24e6c +1, 77760, 77760, 1920, 11520, 0x28fa469b +0, 39, 39, 1, 1382400, 0x55d8b694 +1, 79680, 79680, 1920, 11520, 0xe49161cf +0, 40, 40, 1, 1382400, 0xcc6f136d +1, 81600, 81600, 1920, 11520, 0xb92c49ae +0, 41, 41, 1, 1382400, 0xe92b6ce5 +1, 83520, 83520, 1920, 11520, 0xd2b75d46 +0, 42, 42, 1, 1382400, 0x664d30a1 +1, 85440, 85440, 1920, 11520, 0xa13b5a9b +0, 43, 43, 1, 1382400, 0x09d80a1f +1, 87360, 87360, 1920, 11520, 0xfe804299 +0, 44, 44, 1, 1382400, 0x2b58536e +1, 89280, 89280, 1920, 11520, 0x7a8654d4 +0, 45, 45, 1, 1382400, 0xf24b7a34 +1, 91200, 91200, 1920, 11520, 0x1a2e48a4 +0, 46, 46, 1, 1382400, 0xe2a524c4 +1, 93120, 93120, 1920, 11520, 0x20504669 +0, 47, 47, 1, 1382400, 0xe841e6b7 +1, 95040, 95040, 1920, 11520, 0x7ad44ba6 +0, 48, 48, 1, 1382400, 0x6a2c410c +1, 96960, 96960, 1920, 11520, 0xc8934994 +0, 49, 49, 1, 1382400, 0x5f0c67d2 +1, 98880, 98880, 1920, 11520, 0x07ad70bb +0, 50, 50, 1, 1382400, 0x408e1262 +1, 100800, 100800, 1920, 11520, 0x1ba75d9a +0, 51, 51, 1, 1382400, 0x3567d455 +1, 102720, 102720, 1920, 11520, 0x0d4a435f +0, 52, 52, 1, 1382400, 0x2312e68b +1, 104640, 104640, 1920, 11520, 0x288b6c85 +0, 53, 53, 1, 1382400, 0xe3d84ec2 +1, 106560, 106560, 1920, 11520, 0x85da5f6e +0, 54, 54, 1, 1382400, 0xdbb3ab8c +1, 108480, 108480, 1920, 11520, 0x317a6ac0 +0, 55, 55, 1, 1382400, 0xeb250513 +1, 110400, 110400, 1920, 11520, 0xeea55aa3 +0, 56, 56, 1, 1382400, 0x26c3c8c0 +1, 112320, 112320, 1920, 11520, 0x598b604c +0, 57, 57, 1, 1382400, 0xbc41a23e +1, 114240, 114240, 1770, 10620, 0xabdba053 +0, 58, 58, 1, 1382400, 0x49d6a8de +1, 116010, 116010, 1920, 11520, 0x38de5240 +1, 117930, 117930, 1920, 11520, 0x05c23c05 +0, 59, 59, 1, 1382400, 0x5e05cfa4 +1, 119850, 119850, 1920, 11520, 0x70d7621a +0, 60, 60, 1, 1382400, 0x01327a34 +1, 121770, 121770, 1920, 11520, 0x2fef4788 +0, 61, 61, 1, 1382400, 0x06ce3c36 +1, 123690, 123690, 1920, 11520, 0x95b0542b +0, 62, 62, 1, 1382400, 0x6aa24e6c +1, 125610, 125610, 1920, 11520, 0x38654d48 +0, 63, 63, 1, 1382400, 0x55d8b694 +1, 127530, 127530, 1920, 11520, 0x06ec57ec +0, 64, 64, 1, 1382400, 0xcc6f136d +1, 129450, 129450, 1920, 11520, 0xd0a76908 +0, 65, 65, 1, 1382400, 0xe92b6ce5 +1, 131370, 131370, 1920, 11520, 0xbd7c4296 +0, 66, 66, 1, 1382400, 0x664d30a1 +1, 133290, 133290, 1920, 11520, 0x7fa54533 +0, 67, 67, 1, 1382400, 0x09d80a1f +1, 135210, 135210, 1920, 11520, 0x7e324f34 +0, 68, 68, 1, 1382400, 0x2b58536e +1, 137130, 137130, 1920, 11520, 0x2400410a +0, 69, 69, 1, 1382400, 0xf24b7a34 +1, 139050, 139050, 1920, 11520, 0x52c85b21 +0, 70, 70, 1, 1382400, 0xe2a524c4 +1, 140970, 140970, 1920, 11520, 0xa384487e +0, 71, 71, 1, 1382400, 0xe841e6b7 +1, 142890, 142890, 1920, 11520, 0xddf76717 +0, 72, 72, 1, 1382400, 0x6a2c410c +1, 144810, 144810, 1920, 11520, 0x78165e3a +0, 73, 73, 1, 1382400, 0x5f0c67d2 +1, 146730, 146730, 1920, 11520, 0x037b3e07 +0, 74, 74, 1, 1382400, 0x408e1262 +1, 148650, 148650, 1920, 11520, 0x03d87afa +0, 75, 75, 1, 1382400, 0x3567d455 +1, 150570, 150570, 1920, 11520, 0x17445f5a +0, 76, 76, 1, 1382400, 0x2312e68b +1, 152490, 152490, 1920, 11520, 0xbf48611b +0, 77, 77, 1, 1382400, 0xe3d84ec2 +1, 154410, 154410, 1920, 11520, 0xe5215b3c +0, 78, 78, 1, 1382400, 0xdbb3ab8c +1, 156330, 156330, 1920, 11520, 0x9d345af5 +0, 79, 79, 1, 1382400, 0xeb250513 +1, 158250, 158250, 1920, 11520, 0x3de75a0f +0, 80, 80, 1, 1382400, 0x26c3c8c0 +1, 160170, 160170, 1920, 11520, 0xe3ed6e63 +0, 81, 81, 1, 1382400, 0xbc41a23e +1, 162090, 162090, 1910, 11460, 0x5af73417 +0, 82, 82, 1, 1382400, 0x49d6a8de +1, 164000, 164000, 1920, 11520, 0xee0035c1 +1, 165920, 165920, 1920, 11520, 0x31424265 +0, 83, 83, 1, 1382400, 0x5e05cfa4 +1, 167840, 167840, 1920, 11520, 0x035d4a8d +0, 84, 84, 1, 1382400, 0x01327a34 +1, 169760, 169760, 1920, 11520, 0xa8375593 +0, 85, 85, 1, 1382400, 0x06ce3c36 +1, 171680, 171680, 1920, 11520, 0xbc3e65d3 +0, 86, 86, 1, 1382400, 0x6aa24e6c +1, 173600, 173600, 1920, 11520, 0xa2083bae +0, 87, 87, 1, 1382400, 0x55d8b694 +1, 175520, 175520, 1920, 11520, 0xa220604f +0, 88, 88, 1, 1382400, 0xcc6f136d +1, 177440, 177440, 1920, 11520, 0xd5d3598c +0, 89, 89, 1, 1382400, 0xe92b6ce5 +1, 179360, 179360, 1920, 11520, 0x0e376085 +0, 90, 90, 1, 1382400, 0x664d30a1 +1, 181280, 181280, 1920, 11520, 0x40d973bf +0, 91, 91, 1, 1382400, 0x09d80a1f +1, 183200, 183200, 1920, 11520, 0x05d74496 +0, 92, 92, 1, 1382400, 0x2b58536e +1, 185120, 185120, 1920, 11520, 0xec735e54 +0, 93, 93, 1, 1382400, 0xf24b7a34 +1, 187040, 187040, 1920, 11520, 0x485c5a96 +0, 94, 94, 1, 1382400, 0xe2a524c4 +1, 188960, 188960, 1920, 11520, 0x0ec2705d +0, 95, 95, 1, 1382400, 0xe841e6b7 +1, 190880, 190880, 1120, 6720, 0x81991480 From ec9bcf332909b38ea95921172be76c3faad1b32b Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Sun, 19 Feb 2023 17:47:19 +0100 Subject: [PATCH 0280/2172] Changelog: mark 6.0 Signed-off-by: Michael Niedermayer --- Changelog | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Changelog b/Changelog index 0644f39d597..1d5810ee024 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 6.0: - Radiance HDR image support - ddagrab (Desktop Duplication) video capture filter - ffmpeg -shortest_buf_duration option From e33c1a5494c451f60b072bc3b56b8984be556a55 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Sun, 19 Feb 2023 17:50:44 +0100 Subject: [PATCH 0281/2172] doc/APIchange: fill in missing things Signed-off-by: Michael Niedermayer --- doc/APIchanges | 56 +++++++++++++++++++++++++------------------------- 1 file changed, 28 insertions(+), 28 deletions(-) diff --git a/doc/APIchanges b/doc/APIchanges index 29161e30bfd..70136b22d34 100644 --- a/doc/APIchanges +++ b/doc/APIchanges @@ -2,19 +2,19 @@ The last version increases of all libraries were on 2023-02-09 API changes, most recent first: -2023-02-16 - xxxxxxxxxx - lavf 60.2.100 - avformat.h +2023-02-16 - 927042b409 - lavf 60.2.100 - avformat.h Deprecate AVFormatContext io_close callback. The superior io_close2 callback should be used instead. -2023-02-13 - xxxxxxxxxx - lavu 58.1.100 - frame.h +2023-02-13 - 2296078397 - lavu 58.1.100 - frame.h Deprecate AVFrame.coded_picture_number and display_picture_number. Their usefulness is questionable and very few decoders set them. -2023-02-13 - xxxxxxxxxx - lavc 60.2.100 - avcodec.h +2023-02-13 - 6b6f7db819 - lavc 60.2.100 - avcodec.h Add AVCodecContext.frame_num as a 64bit version of frame_number. Deprecate AVCodecContext.frame_number. -2023-02-12 - xxxxxxxxxx - lavfi 9.1.100 - avfilter.h +2023-02-12 - d1b9a3ddb4 - lavfi 9.1.100 - avfilter.h Add filtergraph segment parsing API. New structs: - AVFilterGraphSegment @@ -29,47 +29,47 @@ API changes, most recent first: - avfilter_graph_segment_link() - avfilter_graph_segment_apply() -2023-02-xx - xxxxxxxxxx - lavu 58.0.100 - csp.h +2023-02-09 - 719a93f4e4 - lavu 58.0.100 - csp.h Add av_csp_approximate_trc_gamma() and av_csp_trc_func_from_id(). Add av_csp_trc_function. -2023-02-xx - xxxxxxxxxx - lavc 60.0.100 - avcodec.h +2023-02-09 - 868a31b42d - lavc 60.0.100 - avcodec.h avcodec_decode_subtitle2() now accepts const AVPacket*. -2023-0x-xx - xxxxxxxxxx - lavc 59.63.100 +2023-02-04 - d02340b9e3 - lavc 59.63.100 Allow AV_CODEC_FLAG_COPY_OPAQUE to be used with decoders. -2023-01-29 - xxxxxxxxxx - lavc 59.59.100 - avcodec.h +2023-01-29 - a1a80f2e64 - lavc 59.59.100 - avcodec.h Add AV_CODEC_FLAG_COPY_OPAQUE and AV_CODEC_FLAG_FRAME_DURATION. -2023-01-13 - xxxxxxxxxx - lavu 57.44.100 - ambient_viewing_environment.h frame.h +2023-01-13 - 002d0ec740 - lavu 57.44.100 - ambient_viewing_environment.h frame.h Adds a new structure for holding H.274 Ambient Viewing Environment metadata, AVAmbientViewingEnvironment. Adds a new AVFrameSideDataType entry AV_FRAME_DATA_AMBIENT_VIEWING_ENVIRONMENT for it. -2022-12-xx - xxxxxxxxxx - lavc 59.55.100 - avcodec.h +2022-12-10 - 7a8d78f7e3 - lavc 59.55.100 - avcodec.h Add AV_HWACCEL_FLAG_UNSAFE_OUTPUT. -2022-11-xx - xxxxxxxxxx - lavu 57.43.100 - tx.h +2022-11-24 - e97368eba5 - lavu 57.43.100 - tx.h Add AV_TX_FLOAT_DCT, AV_TX_DOUBLE_DCT and AV_TX_INT32_DCT. -2022-xx-xx - xxxxxxxxxx - lavu 57.42.100 - dict.h +2022-11-06 - 9dad237928 - lavu 57.42.100 - dict.h Add av_dict_iterate(). -2022-11-03 - xxxxxxxxxx - lavu 57.41.100 - channel_layout.h +2022-11-03 - 6228ba141d - lavu 57.41.100 - channel_layout.h Add AV_CH_LAYOUT_7POINT1_TOP_BACK and AV_CHANNEL_LAYOUT_7POINT1_TOP_BACK. -2022-10-30 - xxxxxxxxxx - lavu 57.40.100 - channel_layout.h +2022-10-30 - 83e918de71 - lavu 57.40.100 - channel_layout.h Add AV_CH_LAYOUT_CUBE and AV_CHANNEL_LAYOUT_CUBE. -2022-10-11 - xxxxxxxxxx - lavu 57.39.101 - pixfmt.h +2022-10-11 - 479747645f - lavu 57.39.101 - pixfmt.h Add AV_PIX_FMT_RGBF32 and AV_PIX_FMT_RGBAF32. 2022-10-05 - 37d5ddc317 - lavu 57.39.100 - cpu.h Add AV_CPU_FLAG_RVB_BASIC. -2022-10-03 - xxxxxxxxxx - lavf 59.34.100 - avio.h +2022-10-03 - d09776d486 - lavf 59.34.100 - avio.h Make AVIODirContext an opaque type in a future major version bump. 2022-09-27 - 0c0a3deb18 - lavu 57.38.100 - cpu.h @@ -77,7 +77,7 @@ API changes, most recent first: AV_CPU_FLAG_RVV_I32, AV_CPU_FLAG_RVV_F32, AV_CPU_FLAG_RVV_I64, AV_CPU_FLAG_RVV_F64 -2022-09-26 - xxxxxxxxxx - lavc 59.48.100 - avcodec.h +2022-09-26 - a02a0e8db4 - lavc 59.48.100 - avcodec.h Deprecate avcodec_enum_to_chroma_pos() and avcodec_chroma_pos_to_enum(). Use av_chroma_location_enum_to_pos() or av_chroma_location_pos_to_enum() instead. @@ -87,19 +87,19 @@ API changes, most recent first: Add AV_PIX_FMT_RGBF32BE, AV_PIX_FMT_RGBF32LE, AV_PIX_FMT_RGBAF32BE, AV_PIX_FMT_RGBAF32LE. -2022-09-26 - xxxxxxxxxx - lavc 59.47.100 - avcodec.h defs.h +2022-09-26 - cf856d8957 - lavc 59.47.100 - avcodec.h defs.h Move the AV_EF_* and FF_COMPLIANCE_* defines from avcodec.h to defs.h. -2022-09-03 - xxxxxxxxxx - lavu 57.36.100 - pixfmt.h +2022-09-03 - d75c4693fe - lavu 57.36.100 - pixfmt.h Add AV_PIX_FMT_P012, AV_PIX_FMT_Y212, AV_PIX_FMT_XV30, AV_PIX_FMT_XV36 -2022-09-03 - xxxxxxxxxx - lavu 57.35.100 - file.h +2022-09-03 - dea9744560 - lavu 57.35.100 - file.h Deprecate av_tempfile() without replacement. -2022-08-03 - xxxxxxxxxx - lavu 57.34.100 - pixfmt.h +2022-08-03 - cc5a5c9860 - lavu 57.34.100 - pixfmt.h Add AV_PIX_FMT_VUYX. -2022-08-xx - xxxxxxxxxx - lavf 59 - avformat.h +2022-08-22 - 14726571dd - lavf 59 - avformat.h Deprecate av_stream_get_end_pts() without replacement. 2022-08-19 - 352799dca8 - lavc 59.42.102 - codec_id.h @@ -109,28 +109,28 @@ API changes, most recent first: 2022-08-07 - e95b08a7dd - lavu 57.33.101 - pixfmt.h Add AV_PIX_FMT_RGBAF16{BE,LE} pixel formats. -2022-08-xx - xxxxxxxxxx - lavu 57.33.100 - hwcontext_qsv.h +2022-08-12 - e0bbdbe0a6 - lavu 57.33.100 - hwcontext_qsv.h Add loader field to AVQSVDeviceContext -2022-08-03 - xxxxxxxxxx - lavu 57.32.100 - pixfmt.h +2022-08-03 - 6ab8a9d375 - lavu 57.32.100 - pixfmt.h Add AV_PIX_FMT_VUYA. -2022-08-xx - xxxxxxxxxx - lavc 59.41.100 - avcodec.h codec.h +2022-08-02 - e3838b856f - lavc 59.41.100 - avcodec.h codec.h Add AV_CODEC_FLAG_RECON_FRAME and AV_CODEC_CAP_ENCODER_RECON_FRAME. avcodec_receive_frame() may now be used on encoders when AV_CODEC_FLAG_RECON_FRAME is active. -2022-08-xx - xxxxxxxxxx - lavu 57.31.100 - frame.h +2022-08-02 - eede1d2927 - lavu 57.31.100 - frame.h av_frame_make_writable() may now be called on non-refcounted frames and will make a refcounted copy out of them. Previously an error was returned in such cases. -2022-07-xx - xxxxxxxxx - lavc 59.40.100 - avcodec.h +2022-07-30 - e1a0f2df3d - lavc 59.40.100 - avcodec.h Add the AV_CODEC_FLAG2_ICC_PROFILES flag to AVCodecContext, to enable automatic reading and writing of embedded ICC profiles in image files. The "flags2" option now supports the corresponding flag "icc_profiles". -2022-07-xx - xxxxxxxxxx - lavu 57.30.100 - frame.h +2022-07-19 - 4397f9a5a0 - lavu 57.30.100 - frame.h Add AVFrame.duration, deprecate AVFrame.pkt_duration. -------- 8< --------- FFmpeg 5.1 was cut here -------- 8< --------- From 62efa096af13fd5d01c6bd0f4b5e814e54ad64f6 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Sun, 19 Feb 2023 18:32:07 +0100 Subject: [PATCH 0282/2172] version.h: Bump minor for 6.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 0550d7b0d87..43794ea5885 100644 --- a/libavcodec/version.h +++ b/libavcodec/version.h @@ -29,7 +29,7 @@ #include "version_major.h" -#define LIBAVCODEC_VERSION_MINOR 2 +#define LIBAVCODEC_VERSION_MINOR 3 #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 25befdead12..ec6c3378743 100644 --- a/libavdevice/version.h +++ b/libavdevice/version.h @@ -29,7 +29,7 @@ #include "version_major.h" -#define LIBAVDEVICE_VERSION_MINOR 0 +#define LIBAVDEVICE_VERSION_MINOR 1 #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 bece922c7f0..7e0eb9af97d 100644 --- a/libavfilter/version.h +++ b/libavfilter/version.h @@ -31,7 +31,7 @@ #include "version_major.h" -#define LIBAVFILTER_VERSION_MINOR 2 +#define LIBAVFILTER_VERSION_MINOR 3 #define LIBAVFILTER_VERSION_MICRO 100 diff --git a/libavformat/version.h b/libavformat/version.h index 904e7f06aa6..7ff14839125 100644 --- a/libavformat/version.h +++ b/libavformat/version.h @@ -31,7 +31,7 @@ #include "version_major.h" -#define LIBAVFORMAT_VERSION_MINOR 2 +#define LIBAVFORMAT_VERSION_MINOR 3 #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 11b4387f642..e8ec6043490 100644 --- a/libavutil/version.h +++ b/libavutil/version.h @@ -79,7 +79,7 @@ */ #define LIBAVUTIL_VERSION_MAJOR 58 -#define LIBAVUTIL_VERSION_MINOR 1 +#define LIBAVUTIL_VERSION_MINOR 2 #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 bcbdd210c4f..8294f007bd5 100644 --- a/libpostproc/version.h +++ b/libpostproc/version.h @@ -30,7 +30,7 @@ #include "version_major.h" -#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 4b9952d9148..31ecf6fff30 100644 --- a/libswresample/version.h +++ b/libswresample/version.h @@ -30,7 +30,7 @@ #include "version_major.h" -#define LIBSWRESAMPLE_VERSION_MINOR 9 +#define LIBSWRESAMPLE_VERSION_MINOR 10 #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 148efd83eb5..4e54701aba8 100644 --- a/libswscale/version.h +++ b/libswscale/version.h @@ -28,7 +28,7 @@ #include "version_major.h" -#define LIBSWSCALE_VERSION_MINOR 0 +#define LIBSWSCALE_VERSION_MINOR 1 #define LIBSWSCALE_VERSION_MICRO 100 #define LIBSWSCALE_VERSION_INT AV_VERSION_INT(LIBSWSCALE_VERSION_MAJOR, \ From 9e80dfbfd9537964afa934eef4deb2b62c0831fd Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Sun, 19 Feb 2023 18:34:25 +0100 Subject: [PATCH 0283/2172] doc/APIchanges: Add 6.0 cut point Signed-off-by: Michael Niedermayer --- doc/APIchanges | 2 ++ 1 file changed, 2 insertions(+) diff --git a/doc/APIchanges b/doc/APIchanges index 70136b22d34..0ba18e86097 100644 --- a/doc/APIchanges +++ b/doc/APIchanges @@ -2,6 +2,8 @@ The last version increases of all libraries were on 2023-02-09 API changes, most recent first: +-------- 8< --------- FFmpeg 6.0 was cut here -------- 8< --------- + 2023-02-16 - 927042b409 - lavf 60.2.100 - avformat.h Deprecate AVFormatContext io_close callback. The superior io_close2 callback should be used instead. From 47ac3e60653da651dfa064b649d0ac297560d8d5 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Sun, 19 Feb 2023 18:37:36 +0100 Subject: [PATCH 0284/2172] version.h: Bump minor post 6.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 43794ea5885..06631ffa8c4 100644 --- a/libavcodec/version.h +++ b/libavcodec/version.h @@ -29,7 +29,7 @@ #include "version_major.h" -#define LIBAVCODEC_VERSION_MINOR 3 +#define LIBAVCODEC_VERSION_MINOR 4 #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 ec6c3378743..5cd01a1672c 100644 --- a/libavdevice/version.h +++ b/libavdevice/version.h @@ -29,7 +29,7 @@ #include "version_major.h" -#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 7e0eb9af97d..4d8f28e5127 100644 --- a/libavfilter/version.h +++ b/libavfilter/version.h @@ -31,7 +31,7 @@ #include "version_major.h" -#define LIBAVFILTER_VERSION_MINOR 3 +#define LIBAVFILTER_VERSION_MINOR 4 #define LIBAVFILTER_VERSION_MICRO 100 diff --git a/libavformat/version.h b/libavformat/version.h index 7ff14839125..af7d0a10249 100644 --- a/libavformat/version.h +++ b/libavformat/version.h @@ -31,7 +31,7 @@ #include "version_major.h" -#define LIBAVFORMAT_VERSION_MINOR 3 +#define LIBAVFORMAT_VERSION_MINOR 4 #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 e8ec6043490..900b7989718 100644 --- a/libavutil/version.h +++ b/libavutil/version.h @@ -79,7 +79,7 @@ */ #define LIBAVUTIL_VERSION_MAJOR 58 -#define LIBAVUTIL_VERSION_MINOR 2 +#define LIBAVUTIL_VERSION_MINOR 3 #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 8294f007bd5..0703ac1d7c7 100644 --- a/libpostproc/version.h +++ b/libpostproc/version.h @@ -30,7 +30,7 @@ #include "version_major.h" -#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 31ecf6fff30..9f589b11434 100644 --- a/libswresample/version.h +++ b/libswresample/version.h @@ -30,7 +30,7 @@ #include "version_major.h" -#define LIBSWRESAMPLE_VERSION_MINOR 10 +#define LIBSWRESAMPLE_VERSION_MINOR 11 #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 4e54701aba8..79f5c69f1c5 100644 --- a/libswscale/version.h +++ b/libswscale/version.h @@ -28,7 +28,7 @@ #include "version_major.h" -#define LIBSWSCALE_VERSION_MINOR 1 +#define LIBSWSCALE_VERSION_MINOR 2 #define LIBSWSCALE_VERSION_MICRO 100 #define LIBSWSCALE_VERSION_INT AV_VERSION_INT(LIBSWSCALE_VERSION_MAJOR, \ From 3807fbd90ab9c5125d21b39017ec48d40d3f019f Mon Sep 17 00:00:00 2001 From: Marton Balint Date: Thu, 16 Feb 2023 01:49:18 +0100 Subject: [PATCH 0285/2172] doc: remove docs for options removed at the bump Signed-off-by: Marton Balint --- doc/encoders.texi | 16 ---------------- doc/filters.texi | 5 ----- doc/muxers.texi | 6 ------ 3 files changed, 27 deletions(-) diff --git a/doc/encoders.texi b/doc/encoders.texi index 727f12a59dc..b02737b9dfb 100644 --- a/doc/encoders.texi +++ b/doc/encoders.texi @@ -1949,22 +1949,6 @@ Set the number of slices, used in parallelized encoding. Default value is 0. This is only used when @option{slice_mode} is set to @samp{fixed}. -@item slice_mode -Set slice mode. Can assume one of the following possible values: - -@table @samp -@item fixed -a fixed number of slices -@item rowmb -one slice per row of macroblocks -@item auto -automatic number of slices according to number of threads -@item dyn -dynamic slicing -@end table - -Default value is @samp{auto}. - @item loopfilter Enable loop filter, if set to 1 (automatically enabled). To disable set a value of 0. diff --git a/doc/filters.texi b/doc/filters.texi index 381a15a17df..47e92b92698 100644 --- a/doc/filters.texi +++ b/doc/filters.texi @@ -26943,11 +26943,6 @@ Specify the frame rate expected for the video stream. @item pixel_aspect, sar The sample (pixel) aspect ratio of the input video. -@item sws_param -This option is deprecated and ignored. Prepend @code{sws_flags=@var{flags};} -to the filtergraph description to specify swscale flags for automatically -inserted scalers. See @ref{Filtergraph syntax}. - @item hw_frames_ctx When using a hardware pixel format, this should be a reference to an AVHWFramesContext describing input frames. diff --git a/doc/muxers.texi b/doc/muxers.texi index ed5341be393..79dd8641825 100644 --- a/doc/muxers.texi +++ b/doc/muxers.texi @@ -795,12 +795,6 @@ deletes them. Increase this to allow continue clients to download segments which were recently referenced in the playlist. Default value is 1, meaning segments older than @code{hls_list_size+1} will be deleted. -@item hls_ts_options @var{options_list} -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. Unless @code{hls_flags single_file} is set, it also specifies source of starting sequence numbers of From e0cb89c354ea654bccc524a8a45321b93cb256d3 Mon Sep 17 00:00:00 2001 From: John Coiner Date: Sun, 12 Feb 2023 18:06:07 -0500 Subject: [PATCH 0286/2172] avformat/mpegtsenc: re-emit extradata ahead of IDR pictures even if AUD is already present Current mpegtsenc code only inserts SPS/PPS from extradata before IDR frames if AUD is also inserted. Unfortunately some encoders may preface a key frame with an AUD, but no SPS/PPS. In that case current code does not repeat the "extradata" and the resulting HLS stream may become noncompliant and unjoinable. Fix this by always inserting SPS/PPS and moving AUD to the beginning of the packet if it is already present. Fixes ticket #10148. Signed-off-by: Marton Balint --- libavformat/mpegtsenc.c | 48 +++++++++++++++++++++++++++++++++++------ 1 file changed, 41 insertions(+), 7 deletions(-) diff --git a/libavformat/mpegtsenc.c b/libavformat/mpegtsenc.c index 00ad426086f..ceed0895871 100644 --- a/libavformat/mpegtsenc.c +++ b/libavformat/mpegtsenc.c @@ -29,6 +29,8 @@ #include "libavcodec/ac3_parser_internal.h" #include "libavcodec/avcodec.h" +#include "libavcodec/bytestream.h" +#include "libavcodec/h264.h" #include "libavcodec/startcode.h" #include "avformat.h" @@ -1877,6 +1879,7 @@ static int mpegts_write_packet_internal(AVFormatContext *s, AVPacket *pkt) if (st->codecpar->codec_id == AV_CODEC_ID_H264) { const uint8_t *p = buf, *buf_end = p + size; + const uint8_t *found_aud = NULL, *found_aud_end = NULL; uint32_t state = -1; int extradd = (pkt->flags & AV_PKT_FLAG_KEY) ? st->codecpar->extradata_size : 0; int ret = ff_check_h264_startcode(s, st, pkt); @@ -1886,27 +1889,58 @@ static int mpegts_write_packet_internal(AVFormatContext *s, AVPacket *pkt) if (extradd && AV_RB24(st->codecpar->extradata) > 1) extradd = 0; + /* Ensure that all pictures are prefixed with an AUD, and that + * IDR pictures are also prefixed with SPS and PPS. SPS and PPS + * are assumed to be available in 'extradata' if not found in-band. */ do { p = avpriv_find_start_code(p, buf_end, &state); av_log(s, AV_LOG_TRACE, "nal %"PRId32"\n", state & 0x1f); - if ((state & 0x1f) == 7) + if ((state & 0x1f) == H264_NAL_SPS) extradd = 0; - } while (p < buf_end && (state & 0x1f) != 9 && - (state & 0x1f) != 5 && (state & 0x1f) != 1); - - if ((state & 0x1f) != 5) + if ((state & 0x1f) == H264_NAL_AUD) { + found_aud = p - 4; // start of the 0x000001 start code. + found_aud_end = p + 1; // first byte past the AUD. + if (found_aud < buf) + found_aud = buf; + if (buf_end < found_aud_end) + found_aud_end = buf_end; + } + } while (p < buf_end + && (state & 0x1f) != H264_NAL_IDR_SLICE + && (state & 0x1f) != H264_NAL_SLICE + && (extradd > 0 || !found_aud)); + if ((state & 0x1f) != H264_NAL_IDR_SLICE) extradd = 0; - if ((state & 0x1f) != 9) { // AUD NAL + + if (!found_aud) { + /* Prefix 'buf' with the missing AUD, and extradata if needed. */ data = av_malloc(pkt->size + 6 + extradd); if (!data) return AVERROR(ENOMEM); memcpy(data + 6, st->codecpar->extradata, extradd); memcpy(data + 6 + extradd, pkt->data, pkt->size); AV_WB32(data, 0x00000001); - data[4] = 0x09; + data[4] = H264_NAL_AUD; data[5] = 0xf0; // any slice type (0xe) + rbsp stop one bit buf = data; size = pkt->size + 6 + extradd; + } else if (extradd != 0) { + /* Move the AUD up to the beginning of the frame, where the H.264 + * spec requires it to appear. Emit the extradata after it. */ + PutByteContext pb; + const int new_pkt_size = pkt->size + 1 + extradd; + data = av_malloc(new_pkt_size); + if (!data) + return AVERROR(ENOMEM); + bytestream2_init_writer(&pb, data, new_pkt_size); + bytestream2_put_byte(&pb, 0x00); + bytestream2_put_buffer(&pb, found_aud, found_aud_end - found_aud); + bytestream2_put_buffer(&pb, st->codecpar->extradata, extradd); + bytestream2_put_buffer(&pb, pkt->data, found_aud - pkt->data); + bytestream2_put_buffer(&pb, found_aud_end, buf_end - found_aud_end); + av_assert0(new_pkt_size == bytestream2_tell_p(&pb)); + buf = data; + size = new_pkt_size; } } else if (st->codecpar->codec_id == AV_CODEC_ID_AAC) { if (pkt->size < 2) { From 1d14959f12ffd720377684af830a51d0cdb2aa8c Mon Sep 17 00:00:00 2001 From: James Almer Date: Fri, 17 Feb 2023 15:22:38 -0300 Subject: [PATCH 0287/2172] doc/resampler.texi: add missing swr channel layout options Signed-off-by: James Almer --- doc/resampler.texi | 14 ++------------ 1 file changed, 2 insertions(+), 12 deletions(-) diff --git a/doc/resampler.texi b/doc/resampler.texi index 5ed3f4377a2..d55654e7bc8 100644 --- a/doc/resampler.texi +++ b/doc/resampler.texi @@ -11,16 +11,6 @@ programmatic use. @table @option -@item ich, in_channel_count -Set the number of input channels. Default value is 0. Setting this -value is not mandatory if the corresponding channel layout -@option{in_channel_layout} is set. - -@item och, out_channel_count -Set the number of output channels. Default value is 0. Setting this -value is not mandatory if the corresponding channel layout -@option{out_channel_layout} is set. - @item uch, used_channel_count Set the number of used input channels. Default value is 0. This option is only used for special remapping. @@ -41,8 +31,8 @@ Specify the output sample format. It is set by default to @code{none}. Set the internal sample format. Default value is @code{none}. This will automatically be chosen when it is not explicitly set. -@item icl, in_channel_layout -@item ocl, out_channel_layout +@item ichl, in_chlayout +@item ochl, out_chlayout Set the input/output channel layout. See @ref{channel layout syntax,,the Channel Layout section in the ffmpeg-utils(1) manual,ffmpeg-utils} From 223c70cf1d8b816b59dede36a21492d7e8542e06 Mon Sep 17 00:00:00 2001 From: James Almer Date: Fri, 17 Feb 2023 15:41:56 -0300 Subject: [PATCH 0288/2172] swresample/swresample: add a used channel layout option using the new API Replaces the "used channel count" option, which is now deprecated. Signed-off-by: James Almer --- doc/resampler.texi | 4 +-- libswresample/options.c | 6 ++-- libswresample/rematrix.c | 2 +- libswresample/swresample.c | 56 ++++++++++++++++++----------- libswresample/swresample_internal.h | 5 +-- libswresample/x86/rematrix_init.c | 2 +- 6 files changed, 46 insertions(+), 29 deletions(-) diff --git a/doc/resampler.texi b/doc/resampler.texi index d55654e7bc8..a6224eefb30 100644 --- a/doc/resampler.texi +++ b/doc/resampler.texi @@ -11,8 +11,8 @@ programmatic use. @table @option -@item uch, used_channel_count -Set the number of used input channels. Default value is 0. This option is +@item uchl, used_chlayout +Set used input channel layout. Default is unset. This option is only used for special remapping. @item isr, in_sample_rate diff --git a/libswresample/options.c b/libswresample/options.c index ffa27c590d7..fb109fdbab1 100644 --- a/libswresample/options.c +++ b/libswresample/options.c @@ -46,9 +46,9 @@ static const AVOption options[]={ OFFSET(user_out_ch_count ), AV_OPT_TYPE_INT, {.i64=0 }, 0 , SWR_CH_MAX, PARAM|DEPREC}, {"out_channel_count" , "set output channel count (Deprecated, use out_chlayout)", OFFSET(user_out_ch_count ), AV_OPT_TYPE_INT, {.i64=0 }, 0 , SWR_CH_MAX, PARAM|DEPREC}, +{"uch" , "set used channel count" , OFFSET(user_used_ch_count), AV_OPT_TYPE_INT, {.i64=0 }, 0 , SWR_CH_MAX, PARAM|DEPREC}, +{"used_channel_count" , "set used channel count" , OFFSET(user_used_ch_count), AV_OPT_TYPE_INT, {.i64=0 }, 0 , SWR_CH_MAX, PARAM|DEPREC}, #endif -{"uch" , "set used channel count" , OFFSET(user_used_ch_count), AV_OPT_TYPE_INT, {.i64=0 }, 0 , SWR_CH_MAX, PARAM}, -{"used_channel_count" , "set used channel count" , OFFSET(user_used_ch_count), AV_OPT_TYPE_INT, {.i64=0 }, 0 , SWR_CH_MAX, PARAM}, {"isr" , "set input sample rate" , OFFSET( in_sample_rate), AV_OPT_TYPE_INT , {.i64=0 }, 0 , INT_MAX , PARAM}, {"in_sample_rate" , "set input sample rate" , OFFSET( in_sample_rate), AV_OPT_TYPE_INT , {.i64=0 }, 0 , INT_MAX , PARAM}, {"osr" , "set output sample rate" , OFFSET(out_sample_rate), AV_OPT_TYPE_INT , {.i64=0 }, 0 , INT_MAX , PARAM}, @@ -73,6 +73,8 @@ static const AVOption options[]={ {"in_chlayout" , "set input channel layout" , OFFSET(user_in_chlayout ), AV_OPT_TYPE_CHLAYOUT, {.str=NULL }, 0, 0 , PARAM, "chlayout"}, {"ochl" , "set output channel layout" , OFFSET(user_out_chlayout), AV_OPT_TYPE_CHLAYOUT, {.str=NULL }, 0, 0 , PARAM, "chlayout"}, {"out_chlayout" , "set output channel layout" , OFFSET(user_out_chlayout), AV_OPT_TYPE_CHLAYOUT, {.str=NULL }, 0, 0 , PARAM, "chlayout"}, +{"uchl" , "set used channel layout" , OFFSET(user_used_chlayout), AV_OPT_TYPE_CHLAYOUT, {.str=NULL }, 0, 0 , PARAM, "chlayout"}, +{"used_chlayout" , "set used channel layout" , OFFSET(user_used_chlayout), AV_OPT_TYPE_CHLAYOUT, {.str=NULL }, 0, 0 , PARAM, "chlayout"}, {"clev" , "set center mix level" , OFFSET(clev ), AV_OPT_TYPE_FLOAT, {.dbl=C_30DB }, -32 , 32 , PARAM}, {"center_mix_level" , "set center mix level" , OFFSET(clev ), AV_OPT_TYPE_FLOAT, {.dbl=C_30DB }, -32 , 32 , PARAM}, {"slev" , "set surround mix level" , OFFSET(slev ), AV_OPT_TYPE_FLOAT, {.dbl=C_30DB }, -32 , 32 , PARAM}, diff --git a/libswresample/rematrix.c b/libswresample/rematrix.c index 0c3fff6c423..79e8a43eac8 100644 --- a/libswresample/rematrix.c +++ b/libswresample/rematrix.c @@ -492,7 +492,7 @@ av_cold static int auto_matrix(SwrContext *s) av_cold int swri_rematrix_init(SwrContext *s){ int i, j; - int nb_in = s->used_ch_count; + int nb_in = s->used_ch_layout.nb_channels; int nb_out = s->out.ch_count; s->mix_any_f = NULL; diff --git a/libswresample/swresample.c b/libswresample/swresample.c index 5884f8d5330..6dc329a9d04 100644 --- a/libswresample/swresample.c +++ b/libswresample/swresample.c @@ -161,6 +161,7 @@ static void clear_context(SwrContext *s){ free_temp(&s->dither.temp); av_channel_layout_uninit(&s->in_ch_layout); av_channel_layout_uninit(&s->out_ch_layout); + av_channel_layout_uninit(&s->used_ch_layout); swri_audio_convert_free(&s-> in_convert); swri_audio_convert_free(&s->out_convert); swri_audio_convert_free(&s->full_convert); @@ -176,6 +177,7 @@ av_cold void swr_free(SwrContext **ss){ clear_context(s); av_channel_layout_uninit(&s->user_in_chlayout); av_channel_layout_uninit(&s->user_out_chlayout); + av_channel_layout_uninit(&s->user_used_chlayout); if (s->resampler) s->resampler->free(&s->resample); @@ -211,12 +213,20 @@ av_cold int swr_init(struct SwrContext *s){ av_log(s, AV_LOG_ERROR, "Requested output sample rate %d is invalid\n", s->out_sample_rate); return AVERROR(EINVAL); } - s->used_ch_count = s->user_used_ch_count; #if FF_API_OLD_CHANNEL_LAYOUT s->out.ch_count = s-> user_out_ch_count; s-> in.ch_count = s-> user_in_ch_count; // if the old/new fields are set inconsistently, prefer the old ones + if (s->user_used_ch_count && s->user_used_ch_count != s->user_used_chlayout.nb_channels) { + av_channel_layout_uninit(&s->used_ch_layout); + s->used_ch_layout.order = AV_CHANNEL_ORDER_UNSPEC; + s->used_ch_layout.nb_channels = s->user_used_ch_count; + } else if (av_channel_layout_check(&s->user_used_chlayout)) { + ret = av_channel_layout_copy(&s->used_ch_layout, &s->user_used_chlayout); + if (ret < 0) + return ret; + } if ((s->user_in_ch_count && s->user_in_ch_count != s->user_in_chlayout.nb_channels) || (s->user_in_ch_layout && (s->user_in_chlayout.order != AV_CHANNEL_ORDER_NATIVE || s->user_in_chlayout.u.mask != s->user_in_ch_layout))) { @@ -243,9 +253,9 @@ av_cold int swr_init(struct SwrContext *s){ } else if (av_channel_layout_check(&s->user_out_chlayout)) av_channel_layout_copy(&s->out_ch_layout, &s->user_out_chlayout); - if (!s->out.ch_count && !s->user_out_ch_layout) + if (!s->out.ch_count) s->out.ch_count = s->out_ch_layout.nb_channels; - if (!s-> in.ch_count && !s-> user_in_ch_layout) + if (!s-> in.ch_count) s-> in.ch_count = s->in_ch_layout.nb_channels; if (!(ret = av_channel_layout_check(&s->in_ch_layout)) || s->in_ch_layout.nb_channels > SWR_CH_MAX) { @@ -281,6 +291,7 @@ av_cold int swr_init(struct SwrContext *s){ ret = av_channel_layout_copy(&s->in_ch_layout, &s->user_in_chlayout); ret |= av_channel_layout_copy(&s->out_ch_layout, &s->user_out_chlayout); + ret |= av_channel_layout_copy(&s->used_ch_layout, &s->user_used_chlayout); if (ret < 0) return ret; #endif @@ -299,16 +310,19 @@ av_cold int swr_init(struct SwrContext *s){ return AVERROR(EINVAL); } - if(!s->used_ch_count) - s->used_ch_count= s->in.ch_count; + if (!av_channel_layout_check(&s->used_ch_layout)) + av_channel_layout_default(&s->used_ch_layout, s->in.ch_count); - if (s->used_ch_count && s->in_ch_layout.order != AV_CHANNEL_ORDER_UNSPEC && s->used_ch_count != s->in_ch_layout.nb_channels) { - av_log(s, AV_LOG_WARNING, "Input channel layout has a different number of channels than the number of used channels, ignoring layout\n"); + if (s->used_ch_layout.nb_channels != s->in_ch_layout.nb_channels) av_channel_layout_uninit(&s->in_ch_layout); - } - if (s->in_ch_layout.order == AV_CHANNEL_ORDER_UNSPEC) - av_channel_layout_default(&s->in_ch_layout, s->used_ch_count); + if (s->used_ch_layout.order == AV_CHANNEL_ORDER_UNSPEC) + av_channel_layout_default(&s->used_ch_layout, s->used_ch_layout.nb_channels); + if (s->in_ch_layout.order == AV_CHANNEL_ORDER_UNSPEC) { + ret = av_channel_layout_copy(&s->in_ch_layout, &s->used_ch_layout); + if (ret < 0) + return ret; + } if (s->out_ch_layout.order == AV_CHANNEL_ORDER_UNSPEC) av_channel_layout_default(&s->out_ch_layout, s->out.ch_count); @@ -389,8 +403,8 @@ av_cold int swr_init(struct SwrContext *s){ #define RSC 1 //FIXME finetune if(!s-> in.ch_count) s-> in.ch_count = s->in_ch_layout.nb_channels; - if(!s->used_ch_count) - s->used_ch_count= s->in.ch_count; + if (!av_channel_layout_check(&s->used_ch_layout)) + av_channel_layout_default(&s->used_ch_layout, s->in.ch_count); if(!s->out.ch_count) s->out.ch_count = s->out_ch_layout.nb_channels; @@ -410,23 +424,23 @@ av_cold int swr_init(struct SwrContext *s){ } #endif av_channel_layout_describe(&s->in_ch_layout, l1, sizeof(l1)); - if (s->in_ch_layout.order != AV_CHANNEL_ORDER_UNSPEC && s->used_ch_count != s->in_ch_layout.nb_channels) { - av_log(s, AV_LOG_ERROR, "Input channel layout %s mismatches specified channel count %d\n", l1, s->used_ch_count); + if (s->in_ch_layout.order != AV_CHANNEL_ORDER_UNSPEC && s->used_ch_layout.nb_channels != s->in_ch_layout.nb_channels) { + av_log(s, AV_LOG_ERROR, "Input channel layout %s mismatches specified channel count %d\n", l1, s->used_ch_layout.nb_channels); ret = AVERROR(EINVAL); goto fail; } if (( s->out_ch_layout.order == AV_CHANNEL_ORDER_UNSPEC - || s-> in_ch_layout.order == AV_CHANNEL_ORDER_UNSPEC) && s->used_ch_count != s->out.ch_count && !s->rematrix_custom) { + || s-> in_ch_layout.order == AV_CHANNEL_ORDER_UNSPEC) && s->used_ch_layout.nb_channels != s->out.ch_count && !s->rematrix_custom) { av_log(s, AV_LOG_ERROR, "Rematrix is needed between %s and %s " "but there is not enough information to do it\n", l1, l2); ret = AVERROR(EINVAL); goto fail; } -av_assert0(s->used_ch_count); +av_assert0(s->used_ch_layout.nb_channels); av_assert0(s->out.ch_count); - s->resample_first= RSC*s->out.ch_count/s->used_ch_count - RSC < s->out_sample_rate/(float)s-> in_sample_rate - 1.0; + s->resample_first= RSC*s->out.ch_count/s->used_ch_layout.nb_channels - RSC < s->out_sample_rate/(float)s-> in_sample_rate - 1.0; s->in_buffer= s->in; s->silence = s->in; @@ -442,7 +456,7 @@ av_assert0(s->out.ch_count); } s->in_convert = swri_audio_convert_alloc(s->int_sample_fmt, - s-> in_sample_fmt, s->used_ch_count, s->channel_map, 0); + s-> in_sample_fmt, s->used_ch_layout.nb_channels, s->channel_map, 0); s->out_convert= swri_audio_convert_alloc(s->out_sample_fmt, s->int_sample_fmt, s->out.ch_count, NULL, 0); @@ -457,9 +471,9 @@ av_assert0(s->out.ch_count); if(s->channel_map){ s->postin.ch_count= - s->midbuf.ch_count= s->used_ch_count; + s->midbuf.ch_count= s->used_ch_layout.nb_channels; if(s->resample) - s->in_buffer.ch_count= s->used_ch_count; + s->in_buffer.ch_count= s->used_ch_layout.nb_channels; } if(!s->resample_first){ s->midbuf.ch_count= s->out.ch_count; @@ -697,7 +711,7 @@ static int swr_convert_internal(struct SwrContext *s, AudioData *out, int out_co if((ret=swri_realloc_audio(&s->postin, in_count))<0) return ret; if(s->resample_first){ - av_assert0(s->midbuf.ch_count == s->used_ch_count); + av_assert0(s->midbuf.ch_count == s->used_ch_layout.nb_channels); if((ret=swri_realloc_audio(&s->midbuf, out_count))<0) return ret; }else{ diff --git a/libswresample/swresample_internal.h b/libswresample/swresample_internal.h index 262a0e2b8c0..ad902d73fa1 100644 --- a/libswresample/swresample_internal.h +++ b/libswresample/swresample_internal.h @@ -99,6 +99,7 @@ struct SwrContext { enum AVSampleFormat in_sample_fmt; ///< input sample format enum AVSampleFormat int_sample_fmt; ///< internal sample format (AV_SAMPLE_FMT_FLTP or AV_SAMPLE_FMT_S16P) enum AVSampleFormat out_sample_fmt; ///< output sample format + AVChannelLayout used_ch_layout; ///< number of used input channels (mapped channel count if channel_map, otherwise in.ch_count) AVChannelLayout in_ch_layout; ///< input channel layout AVChannelLayout out_ch_layout; ///< output channel layout int in_sample_rate; ///< input sample rate @@ -111,16 +112,16 @@ struct SwrContext { float rematrix_maxval; ///< maximum value for rematrixing output int matrix_encoding; /**< matrixed stereo encoding */ const int *channel_map; ///< channel index (or -1 if muted channel) map - int used_ch_count; ///< number of used input channels (mapped channel count if channel_map, otherwise in.ch_count) int engine; - int user_used_ch_count; ///< User set used channel count #if FF_API_OLD_CHANNEL_LAYOUT + int user_used_ch_count; ///< User set used channel count int user_in_ch_count; ///< User set input channel count int user_out_ch_count; ///< User set output channel count int64_t user_in_ch_layout; ///< User set input channel layout int64_t user_out_ch_layout; ///< User set output channel layout #endif + AVChannelLayout user_used_chlayout; ///< User set used channel layout AVChannelLayout user_in_chlayout; ///< User set input channel layout AVChannelLayout user_out_chlayout; ///< User set output channel layout enum AVSampleFormat user_int_sample_fmt; ///< User set internal sample format diff --git a/libswresample/x86/rematrix_init.c b/libswresample/x86/rematrix_init.c index b6ed38bf678..ce794eef90e 100644 --- a/libswresample/x86/rematrix_init.c +++ b/libswresample/x86/rematrix_init.c @@ -33,7 +33,7 @@ D(int16, sse2) av_cold int swri_rematrix_init_x86(struct SwrContext *s){ #if HAVE_X86ASM int mm_flags = av_get_cpu_flags(); - int nb_in = s->used_ch_count; + int nb_in = s->used_ch_layout.nb_channels; int nb_out = s->out.ch_count; int num = nb_in * nb_out; int i,j; From 4561232b1a36b7f8532c7939e4a508734053f6f0 Mon Sep 17 00:00:00 2001 From: James Almer Date: Fri, 17 Feb 2023 15:43:30 -0300 Subject: [PATCH 0289/2172] avfilter/af_pan: use the new swr used channel layout option Fixes ticket #10180 Signed-off-by: James Almer --- libavfilter/af_pan.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavfilter/af_pan.c b/libavfilter/af_pan.c index 067f6468053..4672648d467 100644 --- a/libavfilter/af_pan.c +++ b/libavfilter/af_pan.c @@ -313,7 +313,7 @@ static int config_props(AVFilterLink *link) pan->channel_map[i] = ch_id; } - av_opt_set_int(pan->swr, "uch", pan->nb_output_channels, 0); + av_opt_set_chlayout(pan->swr, "uchl", &pan->out_channel_layout, 0); swr_set_channel_mapping(pan->swr, pan->channel_map); } else { // renormalize From 2aec86695adf51e106c0722fa2b226e5a284fed1 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Sun, 19 Feb 2023 17:48:02 +0100 Subject: [PATCH 0290/2172] Changelog: Add back past 6.0 branch Signed-off-by: Michael Niedermayer --- Changelog | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Changelog b/Changelog index 1d5810ee024..b357f428abc 100644 --- a/Changelog +++ b/Changelog @@ -1,6 +1,8 @@ Entries are sorted chronologically from oldest to youngest within each release, releases are sorted from youngest to oldest. +version : + version 6.0: - Radiance HDR image support - ddagrab (Desktop Duplication) video capture filter From e16b874b6a7391da08a844d1f5b9714195d1842b Mon Sep 17 00:00:00 2001 From: wang-bin Date: Sat, 11 Feb 2023 16:04:05 +0800 Subject: [PATCH 0291/2172] avcodec/ccaption_dec: return the number of bytes decoded Signed-off-by: Anton Khirnov --- libavcodec/ccaption_dec.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavcodec/ccaption_dec.c b/libavcodec/ccaption_dec.c index 61eda9ff56f..661a4951a43 100644 --- a/libavcodec/ccaption_dec.c +++ b/libavcodec/ccaption_dec.c @@ -922,7 +922,7 @@ static int decode(AVCodecContext *avctx, AVSubtitle *sub, } *got_sub = sub->num_rects > 0; - return ret; + return avpkt->size; } #define OFFSET(x) offsetof(CCaptionSubContext, x) From cd4cd95d5e1cf87f5c0e525fd45d250832c027e9 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Sun, 29 Jan 2023 12:35:47 +0100 Subject: [PATCH 0292/2172] fftools/ffmpeg_demux: add an AVClass to Demuxer/InputFile Use it for logging. This makes log messages related to this input file more consistent. --- fftools/ffmpeg.h | 2 + fftools/ffmpeg_demux.c | 106 ++++++++++++++++++++++++++--------------- 2 files changed, 69 insertions(+), 39 deletions(-) diff --git a/fftools/ffmpeg.h b/fftools/ffmpeg.h index f1412f6446b..c657f559112 100644 --- a/fftools/ffmpeg.h +++ b/fftools/ffmpeg.h @@ -448,6 +448,8 @@ typedef struct LastFrameDuration { } LastFrameDuration; typedef struct InputFile { + const AVClass *class; + int index; AVFormatContext *ctx; diff --git a/fftools/ffmpeg_demux.c b/fftools/ffmpeg_demux.c index ffece607201..9f5d8fec24f 100644 --- a/fftools/ffmpeg_demux.c +++ b/fftools/ffmpeg_demux.c @@ -55,6 +55,9 @@ static const char *const opt_name_display_vflips[] = {"display_vflip" typedef struct Demuxer { InputFile f; + // name used for logging + char log_name[32]; + /* number of times input stream should be looped */ int loop; /* actual duration of the longest stream in a file at the moment when @@ -91,11 +94,10 @@ static void report_new_stream(Demuxer *d, const AVPacket *pkt) if (pkt->stream_index < d->nb_streams_warn) return; - av_log(NULL, AV_LOG_WARNING, - "New %s stream %d:%d at pos:%"PRId64" and DTS:%ss\n", + av_log(d, AV_LOG_WARNING, + "New %s stream with index %d at pos:%"PRId64" and DTS:%ss\n", av_get_media_type_string(st->codecpar->codec_type), - d->f.index, pkt->stream_index, - pkt->pos, av_ts2timestr(pkt->dts, &st->time_base)); + pkt->stream_index, pkt->pos, av_ts2timestr(pkt->dts, &st->time_base)); d->nb_streams_warn = pkt->stream_index + 1; } @@ -273,10 +275,10 @@ static void *input_thread(void *arg) } if (ret == AVERROR_EOF) - av_log(NULL, AV_LOG_VERBOSE, "EOF in input file %d\n", f->index); + av_log(d, AV_LOG_VERBOSE, "EOF while reading input\n"); else - av_log(NULL, AV_LOG_ERROR, "Error demuxing input file %d: %s\n", - f->index, av_err2str(ret)); + av_log(d, AV_LOG_ERROR, "Error during demuxing: %s\n", + av_err2str(ret)); break; } @@ -295,9 +297,9 @@ static void *input_thread(void *arg) } if (pkt->flags & AV_PKT_FLAG_CORRUPT) { - av_log(NULL, exit_on_error ? AV_LOG_FATAL : AV_LOG_WARNING, - "%s: corrupt input packet in stream %d\n", - f->ctx->url, pkt->stream_index); + av_log(d, exit_on_error ? AV_LOG_FATAL : AV_LOG_WARNING, + "corrupt input packet in stream %d\n", + pkt->stream_index); if (exit_on_error) { av_packet_unref(pkt); ret = AVERROR_INVALIDDATA; @@ -339,7 +341,7 @@ static void *input_thread(void *arg) av_packet_free(&pkt); - av_log(NULL, AV_LOG_VERBOSE, "Terminating demuxer thread %d\n", f->index); + av_log(d, AV_LOG_VERBOSE, "Terminating demuxer thread\n"); return NULL; } @@ -396,7 +398,7 @@ static int thread_start(Demuxer *d) } if ((ret = pthread_create(&d->thread, NULL, input_thread, d))) { - av_log(NULL, AV_LOG_ERROR, "pthread_create failed: %s. Try to increase `ulimit -v` or decrease `ulimit -s`.\n", strerror(ret)); + av_log(d, AV_LOG_ERROR, "pthread_create failed: %s. Try to increase `ulimit -v` or decrease `ulimit -s`.\n", strerror(ret)); ret = AVERROR(ret); goto fail; } @@ -839,6 +841,32 @@ static void dump_attachment(AVStream *st, const char *filename) avio_close(out); } +static const char *input_file_item_name(void *obj) +{ + const Demuxer *d = obj; + + return d->log_name; +} + +static const AVClass input_file_class = { + .class_name = "InputFile", + .version = LIBAVUTIL_VERSION_INT, + .item_name = input_file_item_name, + .category = AV_CLASS_CATEGORY_DEMUXER, +}; + +static Demuxer *demux_alloc(void) +{ + Demuxer *d = allocate_array_elem(&input_files, sizeof(*d), &nb_input_files); + + d->f.class = &input_file_class; + d->f.index = nb_input_files - 1; + + snprintf(d->log_name, sizeof(d->log_name), "in#%d", d->f.index); + + return d; +} + int ifile_open(const OptionsContext *o, const char *filename) { Demuxer *d; @@ -860,15 +888,18 @@ int ifile_open(const OptionsContext *o, const char *filename) int64_t stop_time = o->stop_time; int64_t recording_time = o->recording_time; + d = demux_alloc(); + f = &d->f; + if (stop_time != INT64_MAX && recording_time != INT64_MAX) { stop_time = INT64_MAX; - av_log(NULL, AV_LOG_WARNING, "-t and -to cannot be used together; using -t.\n"); + av_log(d, AV_LOG_WARNING, "-t and -to cannot be used together; using -t.\n"); } if (stop_time != INT64_MAX && recording_time == INT64_MAX) { int64_t start = start_time == AV_NOPTS_VALUE ? 0 : start_time; if (stop_time <= start) { - av_log(NULL, AV_LOG_ERROR, "-to value smaller than -ss; aborting.\n"); + av_log(d, AV_LOG_ERROR, "-to value smaller than -ss; aborting.\n"); exit_program(1); } else { recording_time = stop_time - start; @@ -877,7 +908,7 @@ int ifile_open(const OptionsContext *o, const char *filename) if (o->format) { if (!(file_iformat = av_find_input_format(o->format))) { - av_log(NULL, AV_LOG_FATAL, "Unknown input format: '%s'\n", o->format); + av_log(d, AV_LOG_FATAL, "Unknown input format: '%s'\n", o->format); exit_program(1); } } @@ -964,9 +995,13 @@ int ifile_open(const OptionsContext *o, const char *filename) if (err < 0) { print_error(filename, err); if (err == AVERROR_PROTOCOL_NOT_FOUND) - av_log(NULL, AV_LOG_ERROR, "Did you mean file:%s?\n", filename); + av_log(d, AV_LOG_ERROR, "Did you mean file:%s?\n", filename); exit_program(1); } + + av_strlcat(d->log_name, "/", sizeof(d->log_name)); + av_strlcat(d->log_name, ic->iformat->name, sizeof(d->log_name)); + if (scan_all_pmts_set) av_dict_set(&o->g->format_opts, "scan_all_pmts", NULL, AV_DICT_MATCH_CASE); remove_avoptions(&o->g->format_opts, o->g->codec_opts); @@ -989,7 +1024,7 @@ int ifile_open(const OptionsContext *o, const char *filename) av_freep(&opts); if (ret < 0) { - av_log(NULL, AV_LOG_FATAL, "%s: could not find codec parameters\n", filename); + av_log(d, AV_LOG_FATAL, "could not find codec parameters\n"); if (ic->nb_streams == 0) { avformat_close_input(&ic); exit_program(1); @@ -998,23 +1033,23 @@ int ifile_open(const OptionsContext *o, const char *filename) } if (start_time != AV_NOPTS_VALUE && start_time_eof != AV_NOPTS_VALUE) { - av_log(NULL, AV_LOG_WARNING, "Cannot use -ss and -sseof both, using -ss for %s\n", filename); + av_log(d, AV_LOG_WARNING, "Cannot use -ss and -sseof both, using -ss\n"); start_time_eof = AV_NOPTS_VALUE; } if (start_time_eof != AV_NOPTS_VALUE) { if (start_time_eof >= 0) { - av_log(NULL, AV_LOG_ERROR, "-sseof value must be negative; aborting\n"); + av_log(d, AV_LOG_ERROR, "-sseof value must be negative; aborting\n"); exit_program(1); } if (ic->duration > 0) { start_time = start_time_eof + ic->duration; if (start_time < 0) { - av_log(NULL, AV_LOG_WARNING, "-sseof value seeks to before start of file %s; ignored\n", filename); + av_log(d, AV_LOG_WARNING, "-sseof value seeks to before start of file; ignored\n"); start_time = AV_NOPTS_VALUE; } } else - av_log(NULL, AV_LOG_WARNING, "Cannot use -sseof, duration of %s not known\n", filename); + av_log(d, AV_LOG_WARNING, "Cannot use -sseof, file duration not known\n"); } timestamp = (start_time == AV_NOPTS_VALUE) ? 0 : start_time; /* add the stream start time */ @@ -1040,16 +1075,12 @@ int ifile_open(const OptionsContext *o, const char *filename) } ret = avformat_seek_file(ic, -1, INT64_MIN, seek_timestamp, seek_timestamp, 0); if (ret < 0) { - av_log(NULL, AV_LOG_WARNING, "%s: could not seek to position %0.3f\n", - filename, (double)timestamp / AV_TIME_BASE); + av_log(d, AV_LOG_WARNING, "could not seek to position %0.3f\n", + (double)timestamp / AV_TIME_BASE); } } - d = allocate_array_elem(&input_files, sizeof(*d), &nb_input_files); - f = &d->f; - f->ctx = ic; - f->index = nb_input_files - 1; f->start_time = start_time; f->recording_time = recording_time; f->input_sync_ref = o->input_sync_ref; @@ -1063,11 +1094,11 @@ int ifile_open(const OptionsContext *o, const char *filename) f->readrate = o->readrate ? o->readrate : 0.0; if (f->readrate < 0.0f) { - av_log(NULL, AV_LOG_ERROR, "Option -readrate for Input #%d is %0.3f; it must be non-negative.\n", f->index, f->readrate); + av_log(d, AV_LOG_ERROR, "Option -readrate is %0.3f; it must be non-negative.\n", f->readrate); exit_program(1); } if (f->readrate && f->rate_emu) { - av_log(NULL, AV_LOG_WARNING, "Both -readrate and -re set for Input #%d. Using -readrate %0.3f.\n", f->index, f->readrate); + av_log(d, AV_LOG_WARNING, "Both -readrate and -re set. Using -readrate %0.3f.\n", f->readrate); f->rate_emu = 0; } @@ -1100,19 +1131,16 @@ int ifile_open(const OptionsContext *o, const char *filename) if (!(option->flags & AV_OPT_FLAG_DECODING_PARAM)) { - av_log(NULL, AV_LOG_ERROR, "Codec AVOption %s (%s) specified for " - "input file #%d (%s) is not a decoding option.\n", e->key, - option->help ? option->help : "", f->index, - filename); + av_log(d, AV_LOG_ERROR, "Codec AVOption %s (%s) is not a decoding " + "option.\n", e->key, option->help ? option->help : ""); exit_program(1); } - av_log(NULL, AV_LOG_WARNING, "Codec AVOption %s (%s) specified for " - "input file #%d (%s) has not been used for any stream. The most " - "likely reason is either wrong type (e.g. a video option with " - "no video streams) or that it is a private option of some decoder " - "which was not actually used for any stream.\n", e->key, - option->help ? option->help : "", f->index, filename); + av_log(d, AV_LOG_WARNING, "Codec AVOption %s (%s) has not been used " + "for any stream. The most likely reason is either wrong type " + "(e.g. a video option with no video streams) or that it is a " + "private option of some decoder which was not actually used " + "for any stream.\n", e->key, option->help ? option->help : ""); } av_dict_free(&unused_opts); From 8a7554a57401ad41949fe355840cc053cb25274d Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Sat, 11 Feb 2023 07:30:15 +0100 Subject: [PATCH 0293/2172] fftools/ffmpeg_demux: add InputStream private data Move {min,max}_pts to it, which is not used outside of ffmpeg_demux. --- fftools/ffmpeg.h | 3 -- fftools/ffmpeg_demux.c | 63 ++++++++++++++++++++++++++++++------------ 2 files changed, 45 insertions(+), 21 deletions(-) diff --git a/fftools/ffmpeg.h b/fftools/ffmpeg.h index c657f559112..2d48a147b84 100644 --- a/fftools/ffmpeg.h +++ b/fftools/ffmpeg.h @@ -377,9 +377,6 @@ typedef struct InputStream { int64_t filter_in_rescale_delta_last; - int64_t min_pts; /* pts with the smallest value in a current stream */ - int64_t max_pts; /* pts with the higher value in a current stream */ - // when forcing constant input framerate through -r, // this contains the pts that will be given to the next decoded frame int64_t cfr_next_pts; diff --git a/fftools/ffmpeg_demux.c b/fftools/ffmpeg_demux.c index 9f5d8fec24f..b6b6b212714 100644 --- a/fftools/ffmpeg_demux.c +++ b/fftools/ffmpeg_demux.c @@ -52,6 +52,13 @@ static const char *const opt_name_display_rotations[] = {"display_rotati static const char *const opt_name_display_hflips[] = {"display_hflip", NULL}; static const char *const opt_name_display_vflips[] = {"display_vflip", NULL}; +typedef struct DemuxStream { + InputStream ist; + + int64_t min_pts; /* pts with the smallest value in a current stream */ + int64_t max_pts; /* pts with the higher value in a current stream */ +} DemuxStream; + typedef struct Demuxer { InputFile f; @@ -83,6 +90,11 @@ typedef struct DemuxMsg { int repeat_pict; } DemuxMsg; +static DemuxStream *ds_from_ist(InputStream *ist) +{ + return (DemuxStream*)ist; +} + static Demuxer *demuxer_from_ifile(InputFile *f) { return (Demuxer*)f; @@ -101,20 +113,20 @@ static void report_new_stream(Demuxer *d, const AVPacket *pkt) d->nb_streams_warn = pkt->stream_index + 1; } -static void ifile_duration_update(Demuxer *d, InputStream *ist, +static void ifile_duration_update(Demuxer *d, DemuxStream *ds, int64_t last_duration) { /* the total duration of the stream, max_pts - min_pts is * the duration of the stream without the last frame */ - if (ist->max_pts > ist->min_pts && - ist->max_pts - (uint64_t)ist->min_pts < INT64_MAX - last_duration) - last_duration += ist->max_pts - ist->min_pts; + if (ds->max_pts > ds->min_pts && + ds->max_pts - (uint64_t)ds->min_pts < INT64_MAX - last_duration) + last_duration += ds->max_pts - ds->min_pts; if (!d->duration || av_compare_ts(d->duration, d->time_base, - last_duration, ist->st->time_base) < 0) { + last_duration, ds->ist.st->time_base) < 0) { d->duration = last_duration; - d->time_base = ist->st->time_base; + d->time_base = ds->ist.st->time_base; } } @@ -122,7 +134,6 @@ static int seek_to_start(Demuxer *d) { InputFile *ifile = &d->f; AVFormatContext *is = ifile->ctx; - InputStream *ist; int ret; ret = avformat_seek_file(is, -1, INT64_MIN, is->start_time, is->start_time, 0); @@ -136,19 +147,21 @@ static int seek_to_start(Demuxer *d) int got_durations = 0; while (got_durations < ifile->audio_duration_queue_size) { + DemuxStream *ds; LastFrameDuration dur; ret = av_thread_message_queue_recv(ifile->audio_duration_queue, &dur, 0); if (ret < 0) return ret; got_durations++; - ist = ifile->streams[dur.stream_idx]; - ifile_duration_update(d, ist, dur.duration); + ds = ds_from_ist(ifile->streams[dur.stream_idx]); + ifile_duration_update(d, ds, dur.duration); } } else { for (int i = 0; i < ifile->nb_streams; i++) { int64_t duration = 0; - ist = ifile->streams[i]; + InputStream *ist = ifile->streams[i]; + DemuxStream *ds = ds_from_ist(ist); if (ist->framerate.num) { duration = av_rescale_q(1, av_inv_q(ist->framerate), ist->st->time_base); @@ -158,7 +171,7 @@ static int seek_to_start(Demuxer *d) duration = 1; } - ifile_duration_update(d, ist, duration); + ifile_duration_update(d, ds, duration); } } @@ -172,6 +185,7 @@ static void ts_fixup(Demuxer *d, AVPacket *pkt, int *repeat_pict) { InputFile *ifile = &d->f; InputStream *ist = ifile->streams[pkt->stream_index]; + DemuxStream *ds = ds_from_ist(ist); const int64_t start_time = ifile->start_time_effective; int64_t duration; @@ -216,8 +230,8 @@ static void ts_fixup(Demuxer *d, AVPacket *pkt, int *repeat_pict) duration = av_rescale_q(d->duration, d->time_base, ist->st->time_base); if (pkt->pts != AV_NOPTS_VALUE) { pkt->pts += duration; - ist->max_pts = FFMAX(pkt->pts, ist->max_pts); - ist->min_pts = FFMIN(pkt->pts, ist->min_pts); + ds->max_pts = FFMAX(pkt->pts, ds->max_pts); + ds->min_pts = FFMIN(pkt->pts, ds->min_pts); } if (pkt->dts != AV_NOPTS_VALUE) @@ -590,6 +604,18 @@ static void add_display_matrix_to_stream(const OptionsContext *o, vflip_set ? vflip : 0); } +static DemuxStream *demux_stream_alloc(Demuxer *d, AVStream *st) +{ + InputFile *f = &d->f; + DemuxStream *ds = allocate_array_elem(&f->streams, sizeof(*ds), + &f->nb_streams); + + ds->ist.st = st; + ds->ist.file_index = f->index; + + return ds; +} + /* Add all the streams from the given input file to the demuxer */ static void add_input_streams(const OptionsContext *o, Demuxer *d) { @@ -600,6 +626,7 @@ static void add_input_streams(const OptionsContext *o, Demuxer *d) for (i = 0; i < ic->nb_streams; i++) { AVStream *st = ic->streams[i]; AVCodecParameters *par = st->codecpar; + DemuxStream *ds; InputStream *ist; char *framerate = NULL, *hwaccel_device = NULL; const char *hwaccel = NULL; @@ -611,15 +638,15 @@ static void add_input_streams(const OptionsContext *o, Demuxer *d) const AVOption *discard_opt = av_opt_find(&cc, "skip_frame", NULL, 0, AV_OPT_SEARCH_FAKE_OBJ); - ist = ALLOC_ARRAY_ELEM(f->streams, f->nb_streams); - ist->st = st; - ist->file_index = f->index; + ds = demux_stream_alloc(d, st); + ist = &ds->ist; + ist->discard = 1; st->discard = AVDISCARD_ALL; ist->nb_samples = 0; ist->first_dts = AV_NOPTS_VALUE; - ist->min_pts = INT64_MAX; - ist->max_pts = INT64_MIN; + ds->min_pts = INT64_MAX; + ds->max_pts = INT64_MIN; ist->ts_scale = 1.0; MATCH_PER_STREAM_OPT(ts_scale, dbl, ist->ts_scale, ic, st); From d9079f6700b022460e4492dc6f9e349741db0bdd Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Sat, 11 Feb 2023 07:32:35 +0100 Subject: [PATCH 0294/2172] fftools/ffmpeg_demux: move InputStream.guess_layout_max to stack It is only needed while processing the stream in add_input_streams(), no reason to store it in the context. --- fftools/ffmpeg.h | 1 - fftools/ffmpeg_demux.c | 13 +++++++------ 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/fftools/ffmpeg.h b/fftools/ffmpeg.h index 2d48a147b84..66dda45f707 100644 --- a/fftools/ffmpeg.h +++ b/fftools/ffmpeg.h @@ -388,7 +388,6 @@ typedef struct InputStream { AVDictionary *decoder_opts; AVRational framerate; /* framerate forced with -r */ int top_field_first; - int guess_layout_max; int autorotate; diff --git a/fftools/ffmpeg_demux.c b/fftools/ffmpeg_demux.c index b6b6b212714..ac0431233e8 100644 --- a/fftools/ffmpeg_demux.c +++ b/fftools/ffmpeg_demux.c @@ -552,14 +552,14 @@ static const AVCodec *choose_decoder(const OptionsContext *o, AVFormatContext *s } } -static int guess_input_channel_layout(InputStream *ist) +static int guess_input_channel_layout(InputStream *ist, int guess_layout_max) { AVCodecContext *dec = ist->dec_ctx; if (dec->ch_layout.order == AV_CHANNEL_ORDER_UNSPEC) { char layout_name[256]; - if (dec->ch_layout.nb_channels > ist->guess_layout_max) + if (dec->ch_layout.nb_channels > guess_layout_max) return 0; av_channel_layout_default(&dec->ch_layout, dec->ch_layout.nb_channels); if (dec->ch_layout.order == AV_CHANNEL_ORDER_UNSPEC) @@ -800,11 +800,12 @@ static void add_input_streams(const OptionsContext *o, Demuxer *d) ist->framerate_guessed = av_guess_frame_rate(ic, st, NULL); break; - case AVMEDIA_TYPE_AUDIO: - ist->guess_layout_max = INT_MAX; - MATCH_PER_STREAM_OPT(guess_layout_max, i, ist->guess_layout_max, ic, st); - guess_input_channel_layout(ist); + case AVMEDIA_TYPE_AUDIO: { + int guess_layout_max = INT_MAX; + MATCH_PER_STREAM_OPT(guess_layout_max, i, guess_layout_max, ic, st); + guess_input_channel_layout(ist, guess_layout_max); break; + } case AVMEDIA_TYPE_DATA: case AVMEDIA_TYPE_SUBTITLE: { char *canvas_size = NULL; From 66c1e956aa271a19f710cf26118010bae5d6bc91 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Sat, 11 Feb 2023 07:59:36 +0100 Subject: [PATCH 0295/2172] fftools/ffmpeg_demux: add an AVClass to DemuxStream/InputStream Use it for logging. This makes log messages related to this input stream more consistent. --- fftools/ffmpeg.h | 2 ++ fftools/ffmpeg_demux.c | 79 ++++++++++++++++++++++++++---------------- 2 files changed, 52 insertions(+), 29 deletions(-) diff --git a/fftools/ffmpeg.h b/fftools/ffmpeg.h index 66dda45f707..401f424f790 100644 --- a/fftools/ffmpeg.h +++ b/fftools/ffmpeg.h @@ -333,6 +333,8 @@ typedef struct FilterGraph { } FilterGraph; typedef struct InputStream { + const AVClass *class; + int file_index; AVStream *st; int discard; /* true if stream data should be discarded */ diff --git a/fftools/ffmpeg_demux.c b/fftools/ffmpeg_demux.c index ac0431233e8..f2a1391a29f 100644 --- a/fftools/ffmpeg_demux.c +++ b/fftools/ffmpeg_demux.c @@ -55,6 +55,9 @@ static const char *const opt_name_display_vflips[] = {"display_vflip" typedef struct DemuxStream { InputStream ist; + // name used for logging + char log_name[32]; + int64_t min_pts; /* pts with the smallest value in a current stream */ int64_t max_pts; /* pts with the higher value in a current stream */ } DemuxStream; @@ -190,9 +193,8 @@ static void ts_fixup(Demuxer *d, AVPacket *pkt, int *repeat_pict) int64_t duration; if (debug_ts) { - av_log(NULL, AV_LOG_INFO, "demuxer -> ist_index:%d:%d type:%s " + av_log(ist, AV_LOG_INFO, "demuxer -> type:%s " "pkt_pts:%s pkt_pts_time:%s pkt_dts:%s pkt_dts_time:%s duration:%s duration_time:%s\n", - ifile->index, pkt->stream_index, av_get_media_type_string(ist->st->codecpar->codec_type), av_ts2str(pkt->pts), av_ts2timestr(pkt->pts, &ist->st->time_base), av_ts2str(pkt->dts), av_ts2timestr(pkt->dts, &ist->st->time_base), @@ -565,15 +567,15 @@ static int guess_input_channel_layout(InputStream *ist, int guess_layout_max) if (dec->ch_layout.order == AV_CHANNEL_ORDER_UNSPEC) return 0; av_channel_layout_describe(&dec->ch_layout, layout_name, sizeof(layout_name)); - av_log(NULL, AV_LOG_WARNING, "Guessed Channel Layout for Input Stream " - "#%d.%d : %s\n", ist->file_index, ist->st->index, layout_name); + av_log(ist, AV_LOG_WARNING, "Guessed Channel Layout: %s\n", layout_name); } return 1; } static void add_display_matrix_to_stream(const OptionsContext *o, - AVFormatContext *ctx, AVStream *st) + AVFormatContext *ctx, InputStream *ist) { + AVStream *st = ist->st; double rotation = DBL_MAX; int hflip = -1, vflip = -1; int hflip_set = 0, vflip_set = 0, rotation_set = 0; @@ -592,7 +594,7 @@ static void add_display_matrix_to_stream(const OptionsContext *o, buf = (int32_t *)av_stream_new_side_data(st, AV_PKT_DATA_DISPLAYMATRIX, sizeof(int32_t) * 9); if (!buf) { - av_log(NULL, AV_LOG_FATAL, "Failed to generate a display matrix!\n"); + av_log(ist, AV_LOG_FATAL, "Failed to generate a display matrix!\n"); exit_program(1); } @@ -604,14 +606,34 @@ static void add_display_matrix_to_stream(const OptionsContext *o, vflip_set ? vflip : 0); } +static const char *input_stream_item_name(void *obj) +{ + const DemuxStream *ds = obj; + + return ds->log_name; +} + +static const AVClass input_stream_class = { + .class_name = "InputStream", + .version = LIBAVUTIL_VERSION_INT, + .item_name = input_stream_item_name, + .category = AV_CLASS_CATEGORY_DEMUXER, +}; + static DemuxStream *demux_stream_alloc(Demuxer *d, AVStream *st) { + const char *type_str = av_get_media_type_string(st->codecpar->codec_type); InputFile *f = &d->f; DemuxStream *ds = allocate_array_elem(&f->streams, sizeof(*ds), &f->nb_streams); ds->ist.st = st; ds->ist.file_index = f->index; + ds->ist.class = &input_stream_class; + + snprintf(ds->log_name, sizeof(ds->log_name), "%cist#%d:%d/%s", + type_str ? *type_str : '?', d->f.index, st->index, + avcodec_get_name(st->codecpar->codec_id)); return ds; } @@ -663,20 +685,20 @@ static void add_input_streams(const OptionsContext *o, Demuxer *d) } if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) { - add_display_matrix_to_stream(o, ic, st); + add_display_matrix_to_stream(o, ic, ist); MATCH_PER_STREAM_OPT(hwaccels, str, hwaccel, ic, st); MATCH_PER_STREAM_OPT(hwaccel_output_formats, str, hwaccel_output_format, ic, st); if (!hwaccel_output_format && hwaccel && !strcmp(hwaccel, "cuvid")) { - av_log(NULL, AV_LOG_WARNING, + av_log(ist, AV_LOG_WARNING, "WARNING: defaulting hwaccel_output_format to cuda for compatibility " "with old commandlines. This behaviour is DEPRECATED and will be removed " "in the future. Please explicitly set \"-hwaccel_output_format cuda\".\n"); ist->hwaccel_output_format = AV_PIX_FMT_CUDA; } else if (!hwaccel_output_format && hwaccel && !strcmp(hwaccel, "qsv")) { - av_log(NULL, AV_LOG_WARNING, + av_log(ist, AV_LOG_WARNING, "WARNING: defaulting hwaccel_output_format to qsv for compatibility " "with old commandlines. This behaviour is DEPRECATED and will be removed " "in the future. Please explicitly set \"-hwaccel_output_format qsv\".\n"); @@ -688,7 +710,7 @@ static void add_input_streams(const OptionsContext *o, Demuxer *d) } else if (hwaccel_output_format) { ist->hwaccel_output_format = av_get_pix_fmt(hwaccel_output_format); if (ist->hwaccel_output_format == AV_PIX_FMT_NONE) { - av_log(NULL, AV_LOG_FATAL, "Unrecognised hwaccel output " + av_log(ist, AV_LOG_FATAL, "Unrecognised hwaccel output " "format: %s", hwaccel_output_format); } } else { @@ -712,15 +734,15 @@ static void add_input_streams(const OptionsContext *o, Demuxer *d) } if (!ist->hwaccel_id) { - av_log(NULL, AV_LOG_FATAL, "Unrecognized hwaccel: %s.\n", + av_log(ist, AV_LOG_FATAL, "Unrecognized hwaccel: %s.\n", hwaccel); - av_log(NULL, AV_LOG_FATAL, "Supported hwaccels: "); + av_log(ist, AV_LOG_FATAL, "Supported hwaccels: "); type = AV_HWDEVICE_TYPE_NONE; while ((type = av_hwdevice_iterate_types(type)) != AV_HWDEVICE_TYPE_NONE) - av_log(NULL, AV_LOG_FATAL, "%s ", + av_log(ist, AV_LOG_FATAL, "%s ", av_hwdevice_get_type_name(type)); - av_log(NULL, AV_LOG_FATAL, "\n"); + av_log(ist, AV_LOG_FATAL, "\n"); exit_program(1); } } @@ -752,7 +774,7 @@ static void add_input_streams(const OptionsContext *o, Demuxer *d) ist->user_set_discard = AVDISCARD_ALL; if (discard_str && av_opt_eval_int(&cc, discard_opt, discard_str, &ist->user_set_discard) < 0) { - av_log(NULL, AV_LOG_ERROR, "Error parsing discard %s.\n", + av_log(ist, AV_LOG_ERROR, "Error parsing discard %s.\n", discard_str); exit_program(1); } @@ -766,7 +788,7 @@ static void add_input_streams(const OptionsContext *o, Demuxer *d) ret = avcodec_parameters_to_context(ist->dec_ctx, par); if (ret < 0) { - av_log(NULL, AV_LOG_ERROR, "Error initializing the decoder context.\n"); + av_log(ist, AV_LOG_ERROR, "Error initializing the decoder context.\n"); exit_program(1); } @@ -789,7 +811,7 @@ static void add_input_streams(const OptionsContext *o, Demuxer *d) MATCH_PER_STREAM_OPT(frame_rates, str, framerate, ic, st); if (framerate && av_parse_video_rate(&ist->framerate, framerate) < 0) { - av_log(NULL, AV_LOG_ERROR, "Error parsing framerate %s.\n", + av_log(ist, AV_LOG_ERROR, "Error parsing framerate %s.\n", framerate); exit_program(1); } @@ -813,7 +835,7 @@ static void add_input_streams(const OptionsContext *o, Demuxer *d) MATCH_PER_STREAM_OPT(canvas_sizes, str, canvas_size, ic, st); if (canvas_size && av_parse_video_size(&ist->dec_ctx->width, &ist->dec_ctx->height, canvas_size) < 0) { - av_log(NULL, AV_LOG_FATAL, "Invalid canvas size: %s.\n", canvas_size); + av_log(ist, AV_LOG_FATAL, "Invalid canvas size: %s.\n", canvas_size); exit_program(1); } break; @@ -831,35 +853,34 @@ static void add_input_streams(const OptionsContext *o, Demuxer *d) ret = avcodec_parameters_from_context(ist->par, ist->dec_ctx); if (ret < 0) { - av_log(NULL, AV_LOG_ERROR, "Error initializing the decoder context.\n"); + av_log(ist, AV_LOG_ERROR, "Error initializing the decoder context.\n"); exit_program(1); } } } -static void dump_attachment(AVStream *st, const char *filename) +static void dump_attachment(InputStream *ist, const char *filename) { + AVStream *st = ist->st; int ret; AVIOContext *out = NULL; const AVDictionaryEntry *e; if (!st->codecpar->extradata_size) { - av_log(NULL, AV_LOG_WARNING, "No extradata to dump in stream #%d:%d.\n", - nb_input_files - 1, st->index); + av_log(ist, AV_LOG_WARNING, "No extradata to dump.\n"); return; } if (!*filename && (e = av_dict_get(st->metadata, "filename", NULL, 0))) filename = e->value; if (!*filename) { - av_log(NULL, AV_LOG_FATAL, "No filename specified and no 'filename' tag" - "in stream #%d:%d.\n", nb_input_files - 1, st->index); + av_log(ist, AV_LOG_FATAL, "No filename specified and no 'filename' tag"); exit_program(1); } assert_file_overwrite(filename); if ((ret = avio_open2(&out, filename, AVIO_FLAG_WRITE, &int_cb, NULL)) < 0) { - av_log(NULL, AV_LOG_FATAL, "Could not open file %s for writing.\n", + av_log(ist, AV_LOG_FATAL, "Could not open file %s for writing.\n", filename); exit_program(1); } @@ -1175,11 +1196,11 @@ int ifile_open(const OptionsContext *o, const char *filename) for (i = 0; i < o->nb_dump_attachment; i++) { int j; - for (j = 0; j < ic->nb_streams; j++) { - AVStream *st = ic->streams[j]; + for (j = 0; j < f->nb_streams; j++) { + InputStream *ist = f->streams[j]; - if (check_stream_specifier(ic, st, o->dump_attachment[i].specifier) == 1) - dump_attachment(st, o->dump_attachment[i].u.str); + if (check_stream_specifier(ic, ist->st, o->dump_attachment[i].specifier) == 1) + dump_attachment(ist, o->dump_attachment[i].u.str); } } From 156ca865697fcad6332ea75f4d97f12135975ac5 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Sat, 11 Feb 2023 08:17:55 +0100 Subject: [PATCH 0296/2172] fftools/ffmpeg: move ts_scale to DemuxStream It is not needed outside of ffmpeg_demux. --- fftools/ffmpeg.h | 1 - fftools/ffmpeg_demux.c | 10 ++++++---- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/fftools/ffmpeg.h b/fftools/ffmpeg.h index 401f424f790..4d4433f5bad 100644 --- a/fftools/ffmpeg.h +++ b/fftools/ffmpeg.h @@ -385,7 +385,6 @@ typedef struct InputStream { int64_t nb_samples; /* number of samples in the last decoded audio frame before looping */ - double ts_scale; int saw_first_ts; AVDictionary *decoder_opts; AVRational framerate; /* framerate forced with -r */ diff --git a/fftools/ffmpeg_demux.c b/fftools/ffmpeg_demux.c index f2a1391a29f..2033c1de54a 100644 --- a/fftools/ffmpeg_demux.c +++ b/fftools/ffmpeg_demux.c @@ -58,6 +58,8 @@ typedef struct DemuxStream { // name used for logging char log_name[32]; + double ts_scale; + int64_t min_pts; /* pts with the smallest value in a current stream */ int64_t max_pts; /* pts with the higher value in a current stream */ } DemuxStream; @@ -225,9 +227,9 @@ static void ts_fixup(Demuxer *d, AVPacket *pkt, int *repeat_pict) pkt->pts += av_rescale_q(ifile->ts_offset, AV_TIME_BASE_Q, ist->st->time_base); if (pkt->pts != AV_NOPTS_VALUE) - pkt->pts *= ist->ts_scale; + pkt->pts *= ds->ts_scale; if (pkt->dts != AV_NOPTS_VALUE) - pkt->dts *= ist->ts_scale; + pkt->dts *= ds->ts_scale; duration = av_rescale_q(d->duration, d->time_base, ist->st->time_base); if (pkt->pts != AV_NOPTS_VALUE) { @@ -670,8 +672,8 @@ static void add_input_streams(const OptionsContext *o, Demuxer *d) ds->min_pts = INT64_MAX; ds->max_pts = INT64_MIN; - ist->ts_scale = 1.0; - MATCH_PER_STREAM_OPT(ts_scale, dbl, ist->ts_scale, ic, st); + ds->ts_scale = 1.0; + MATCH_PER_STREAM_OPT(ts_scale, dbl, ds->ts_scale, ic, st); ist->autorotate = 1; MATCH_PER_STREAM_OPT(autorotate, i, ist->autorotate, ic, st); From 15de355e627ec63422663df84681e78d075c9648 Mon Sep 17 00:00:00 2001 From: Pierre-Anthony Lemieux Date: Thu, 5 Jan 2023 15:29:44 -0800 Subject: [PATCH 0297/2172] avformat/imfdec: remove the experimental flag Signed-off-by: Pierre-Anthony Lemieux --- libavformat/imfdec.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavformat/imfdec.c b/libavformat/imfdec.c index 4932b7ff1fc..7d04d0d8535 100644 --- a/libavformat/imfdec.c +++ b/libavformat/imfdec.c @@ -1022,7 +1022,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 | AVFMT_NO_BYTE_SEEK, + .flags = AVFMT_NO_BYTE_SEEK, .flags_internal = FF_FMT_INIT_CLEANUP, .priv_class = &imf_class, .priv_data_size = sizeof(IMFContext), From 23b4251808ba98773a1ab54a9b9706f442cf8299 Mon Sep 17 00:00:00 2001 From: Pierre-Anthony Lemieux Date: Thu, 5 Jan 2023 15:29:45 -0800 Subject: [PATCH 0298/2172] doc: improve IMF demuxer documentation Signed-off-by: Pierre-Anthony Lemieux --- doc/demuxers.texi | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/doc/demuxers.texi b/doc/demuxers.texi index 3c81024f038..2d33b47a569 100644 --- a/doc/demuxers.texi +++ b/doc/demuxers.texi @@ -307,7 +307,15 @@ stream which contains the alpha channel in addition to the ordinary video. Interoperable Master Format demuxer. -This demuxer presents audio and video streams found in an IMF Composition. +This demuxer presents audio and video streams found in an IMF Composition, as +specified in @url{https://doi.org/10.5594/SMPTE.ST2067-2.2020, SMPTE ST 2067-2}. + +@example +ffmpeg [-assetmaps ,,...] -i ... +@end example + +If @code{-assetmaps} is not specified, the demuxer looks for a file called +@file{ASSETMAP.xml} in the same directory as the CPL. @section flv, live_flv, kux From d80f3debe29821ea1fea2a62aff378695214c1c9 Mon Sep 17 00:00:00 2001 From: Pierre-Anthony Lemieux Date: Thu, 5 Jan 2023 15:29:46 -0800 Subject: [PATCH 0299/2172] fate/imfdec: remove imf experimental flag Signed-off-by: Pierre-Anthony Lemieux --- tests/fate/imf.mak | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/fate/imf.mak b/tests/fate/imf.mak index 49ab35e7d99..100822f5e01 100644 --- a/tests/fate/imf.mak +++ b/tests/fate/imf.mak @@ -1,8 +1,8 @@ FATE_IMF += fate-imf-cpl-with-repeat -fate-imf-cpl-with-repeat: CMD = framecrc -f imf -i $(TARGET_SAMPLES)/imf/countdown/CPL_bb2ce11c-1bb6-4781-8e69-967183d02b9b.xml -c:v copy +fate-imf-cpl-with-repeat: CMD = framecrc -i $(TARGET_SAMPLES)/imf/countdown/CPL_bb2ce11c-1bb6-4781-8e69-967183d02b9b.xml -c:v copy FATE_IMF += fate-imf-cpl-with-audio -fate-imf-cpl-with-audio: CMD = framecrc -f imf -i $(TARGET_SAMPLES)/imf/countdown-audio/CPL_688f4f63-a317-4271-99bf-51444ff39c5b.xml -c:a copy +fate-imf-cpl-with-audio: CMD = framecrc -i $(TARGET_SAMPLES)/imf/countdown-audio/CPL_688f4f63-a317-4271-99bf-51444ff39c5b.xml -c:a copy FATE_SAMPLES_FFMPEG-$(CONFIG_IMF_DEMUXER) += $(FATE_IMF) From 98d03e528f8c2f2e47086776d1d389b74282b6f2 Mon Sep 17 00:00:00 2001 From: Tong Wu Date: Tue, 14 Feb 2023 10:45:57 +0800 Subject: [PATCH 0300/2172] hwcontext_d3d11va: add mutiple supported DXGI formats Add support for VUYX, YUYV422, Y210, XV30, P012, Y212, XV36. The added formats work with qsv acceleration and will not have impact on d3d11va acceleration(-hwaccel d3d11va) since so far these formats are still not supported by using d3d11va acceleration. Hwupload and hwdownload can work with the added formats. Signed-off-by: Tong Wu --- libavutil/hwcontext_d3d11va.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/libavutil/hwcontext_d3d11va.c b/libavutil/hwcontext_d3d11va.c index 363ec6a47dc..aa50538d64c 100644 --- a/libavutil/hwcontext_d3d11va.c +++ b/libavutil/hwcontext_d3d11va.c @@ -89,6 +89,13 @@ static const struct { { DXGI_FORMAT_B8G8R8A8_UNORM, AV_PIX_FMT_BGRA }, { DXGI_FORMAT_R10G10B10A2_UNORM, AV_PIX_FMT_X2BGR10 }, { DXGI_FORMAT_R16G16B16A16_FLOAT, AV_PIX_FMT_RGBAF16 }, + { DXGI_FORMAT_AYUV, AV_PIX_FMT_VUYX }, + { DXGI_FORMAT_YUY2, AV_PIX_FMT_YUYV422 }, + { DXGI_FORMAT_Y210, AV_PIX_FMT_Y210 }, + { DXGI_FORMAT_Y410, AV_PIX_FMT_XV30 }, + { DXGI_FORMAT_P016, AV_PIX_FMT_P012 }, + { DXGI_FORMAT_Y216, AV_PIX_FMT_Y212 }, + { DXGI_FORMAT_Y416, AV_PIX_FMT_XV36 }, // Special opaque formats. The pix_fmt is merely a place holder, as the // opaque format cannot be accessed directly. { DXGI_FORMAT_420_OPAQUE, AV_PIX_FMT_YUV420P }, From 417eb7d50e68610ce017aaeb9bea9110ea8d5e5f Mon Sep 17 00:00:00 2001 From: Tong Wu Date: Tue, 14 Feb 2023 10:45:58 +0800 Subject: [PATCH 0301/2172] hwcontext_dxva2: add mutiple supported formats Add support for VUYX, YUYV422, Y210, XV30, P012, Y212, XV36. The added formats work with qsv acceleration and will not have impact on dxva2 acceleration(-hwaccel dxva2) since so far these formats are still not supported by using dxva2 acceleration. Hwupload and hwdownload can work with the added formats. Signed-off-by: Tong Wu --- libavutil/hwcontext_dxva2.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/libavutil/hwcontext_dxva2.c b/libavutil/hwcontext_dxva2.c index 53d00fa815b..ea378df7208 100644 --- a/libavutil/hwcontext_dxva2.c +++ b/libavutil/hwcontext_dxva2.c @@ -82,6 +82,13 @@ static const struct { } supported_formats[] = { { MKTAG('N', 'V', '1', '2'), AV_PIX_FMT_NV12 }, { MKTAG('P', '0', '1', '0'), AV_PIX_FMT_P010 }, + { MKTAG('A', 'Y', 'U', 'V'), AV_PIX_FMT_VUYX }, + { MKTAG('Y', 'U', 'Y', '2'), AV_PIX_FMT_YUYV422 }, + { MKTAG('Y', '2', '1', '0'), AV_PIX_FMT_Y210 }, + { MKTAG('Y', '4', '1', '0'), AV_PIX_FMT_XV30 }, + { MKTAG('P', '0', '1', '6'), AV_PIX_FMT_P012 }, + { MKTAG('Y', '2', '1', '6'), AV_PIX_FMT_Y212 }, + { MKTAG('Y', '4', '1', '6'), AV_PIX_FMT_XV36 }, { D3DFMT_P8, AV_PIX_FMT_PAL8 }, { D3DFMT_A8R8G8B8, AV_PIX_FMT_BGRA }, }; From d5cc7acff1a4ea3e14d67faf99966c31a30d2a4d Mon Sep 17 00:00:00 2001 From: Tong Wu Date: Tue, 14 Feb 2023 10:45:59 +0800 Subject: [PATCH 0302/2172] qsv: remove CONFIG_VAAPI for mutiple formats Remove CONFIG_VAAPI for VUYX, YUYV422, Y210, XV30, Y212, XV36. Make 8-bit, 10-bit, 12-bit YUV 4:2:2 video sources as well as YUV 4:4:4 video sources supported by d3d11va and dxva2 just like what VAAPI does. Sign-off-by: Tong Wu --- libavcodec/qsv.c | 4 ---- libavutil/hwcontext_qsv.c | 6 +++--- 2 files changed, 3 insertions(+), 7 deletions(-) diff --git a/libavcodec/qsv.c b/libavcodec/qsv.c index 7af154202c4..8eabf46b451 100644 --- a/libavcodec/qsv.c +++ b/libavcodec/qsv.c @@ -208,7 +208,6 @@ enum AVPixelFormat ff_qsv_map_fourcc(uint32_t fourcc) case MFX_FOURCC_P8: return AV_PIX_FMT_PAL8; case MFX_FOURCC_A2RGB10: return AV_PIX_FMT_X2RGB10; case MFX_FOURCC_RGB4: return AV_PIX_FMT_BGRA; -#if CONFIG_VAAPI case MFX_FOURCC_YUY2: return AV_PIX_FMT_YUYV422; case MFX_FOURCC_Y210: return AV_PIX_FMT_Y210; case MFX_FOURCC_AYUV: return AV_PIX_FMT_VUYX; @@ -217,7 +216,6 @@ enum AVPixelFormat ff_qsv_map_fourcc(uint32_t fourcc) case MFX_FOURCC_P016: return AV_PIX_FMT_P012; case MFX_FOURCC_Y216: return AV_PIX_FMT_Y212; case MFX_FOURCC_Y416: return AV_PIX_FMT_XV36; -#endif #endif } return AV_PIX_FMT_NONE; @@ -245,7 +243,6 @@ int ff_qsv_map_pixfmt(enum AVPixelFormat format, uint32_t *fourcc, uint16_t *shi *fourcc = MFX_FOURCC_RGB4; *shift = 0; return AV_PIX_FMT_BGRA; -#if CONFIG_VAAPI case AV_PIX_FMT_YUV422P: case AV_PIX_FMT_YUYV422: *fourcc = MFX_FOURCC_YUY2; @@ -277,7 +274,6 @@ int ff_qsv_map_pixfmt(enum AVPixelFormat format, uint32_t *fourcc, uint16_t *shi *fourcc = MFX_FOURCC_Y416; *shift = 1; return AV_PIX_FMT_XV36; -#endif #endif default: return AVERROR(ENOSYS); diff --git a/libavutil/hwcontext_qsv.c b/libavutil/hwcontext_qsv.c index 42851d4fd5d..67804288750 100644 --- a/libavutil/hwcontext_qsv.c +++ b/libavutil/hwcontext_qsv.c @@ -115,11 +115,12 @@ static const struct { { AV_PIX_FMT_BGRA, MFX_FOURCC_RGB4, 0 }, { AV_PIX_FMT_P010, MFX_FOURCC_P010, 1 }, { AV_PIX_FMT_PAL8, MFX_FOURCC_P8, 0 }, -#if CONFIG_VAAPI { AV_PIX_FMT_YUYV422, MFX_FOURCC_YUY2, 0 }, +#if CONFIG_VAAPI { AV_PIX_FMT_UYVY422, MFX_FOURCC_UYVY, 0 }, +#endif { AV_PIX_FMT_Y210, MFX_FOURCC_Y210, 1 }, // VUYX is used for VAAPI child device, @@ -144,7 +145,6 @@ static const struct { { AV_PIX_FMT_XV36, MFX_FOURCC_Y416, 1 }, #endif -#endif }; extern int ff_qsv_get_surface_base_handle(mfxFrameSurface1 *surf, @@ -1526,7 +1526,6 @@ static int map_frame_to_surface(const AVFrame *frame, mfxFrameSurface1 *surface) surface->Data.R = frame->data[0] + 2; surface->Data.A = frame->data[0] + 3; break; -#if CONFIG_VAAPI case AV_PIX_FMT_YUYV422: surface->Data.Y = frame->data[0]; surface->Data.U = frame->data[0] + 1; @@ -1558,6 +1557,7 @@ static int map_frame_to_surface(const AVFrame *frame, mfxFrameSurface1 *surface) // use the value from the frame. surface->Data.A = frame->data[0] + 6; break; +#if CONFIG_VAAPI case AV_PIX_FMT_UYVY422: surface->Data.Y = frame->data[0] + 1; surface->Data.U = frame->data[0]; From 53c1f5c2e28e54ea8174b196d5cf4a158907395a Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Mon, 20 Feb 2023 19:19:32 +0100 Subject: [PATCH 0303/2172] avformat/mov: Check samplesize and offset to avoid integer overflow Fixes: signed integer overflow: 9223372036854775584 + 536870912 cannot be represented in type 'long' Fixes: 55844/clusterfuzz-testcase-minimized-ffmpeg_dem_MOV_fuzzer-510613920664780 Found-by: continuous fuzzing process https://github.com/google/oss-fuzz/tree/master/projects/ffmpeg Signed-off-by: Michael Niedermayer --- libavformat/mov.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/libavformat/mov.c b/libavformat/mov.c index 6ab43b00c6b..8af564ed610 100644 --- a/libavformat/mov.c +++ b/libavformat/mov.c @@ -4192,6 +4192,13 @@ static void mov_build_index(MOVContext *mov, AVStream *st) if (keyframe) distance = 0; sample_size = sc->stsz_sample_size > 0 ? sc->stsz_sample_size : sc->sample_sizes[current_sample]; + if (current_offset > INT64_MAX - sample_size) { + av_log(mov->fc, AV_LOG_ERROR, "Current offset %"PRId64" or sample size %u is too large\n", + current_offset, + sample_size); + return; + } + if (sc->pseudo_stream_id == -1 || sc->stsc_data[stsc_index].id - 1 == sc->pseudo_stream_id) { AVIndexEntry *e; From b3df7ca748bf28e41a6fcb6792b485d8eb04b36a Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Mon, 20 Feb 2023 19:38:00 +0100 Subject: [PATCH 0304/2172] avformat/rka: Fix 1/0 with bps=1 Fixes: division by zero Fixes: 55940/clusterfuzz-testcase-minimized-ffmpeg_IO_DEMUXER_fuzzer-6333107679920128 The decoder does not support bps=1 and i have no such sample so it is not known if this duration is correct. Alternatively we could error out on all bps we currently do not support on the decoder side or not set duration. Found-by: continuous fuzzing process https://github.com/google/oss-fuzz/tree/master/projects/ffmpeg Signed-off-by: Michael Niedermayer --- libavformat/rka.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavformat/rka.c b/libavformat/rka.c index cc55480345c..39e5b3bce12 100644 --- a/libavformat/rka.c +++ b/libavformat/rka.c @@ -114,7 +114,7 @@ static int rka_read_header(AVFormatContext *s) par->ch_layout.nb_channels = channels; par->sample_rate = samplerate; par->bits_per_raw_sample = bps; - st->duration = nb_samples / (channels * (bps >> 3)); + st->duration = 8LL*nb_samples / (channels * bps); if (s->pb->seekable & AVIO_SEEKABLE_NORMAL) ff_ape_parse_tag(s); From d495747a9fc5fb8dcac4b23c5bdca3c5c16dd152 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Mon, 20 Feb 2023 19:53:19 +0100 Subject: [PATCH 0305/2172] avcodec/rka: Fix some integer anomalies Fixes: left shift of negative value -3201 Fixes: integer overflow: -76470276 * -25608 cannot be represented in type 'int' Fixes: 56052/clusterfuzz-testcase-minimized-ffmpeg_AV_CODEC_ID_RKA_fuzzer-5236218750435328 Found-by: continuous fuzzing process https://github.com/google/oss-fuzz/tree/master/projects/ffmpeg Signed-off-by: Michael Niedermayer --- libavcodec/rka.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/libavcodec/rka.c b/libavcodec/rka.c index 461baf1e1f2..994c563ffd0 100644 --- a/libavcodec/rka.c +++ b/libavcodec/rka.c @@ -723,16 +723,16 @@ static int decode_filter(RKAContext *s, ChContext *ctx, ACoder *ac, int off, uns last_val = val; src = &ctx->buf1[off + -1]; for (int i = 0; i < filt.size && i < 15; i++) - sum += filt.coeffs[i] * src[-i]; + sum += filt.coeffs[i] * (unsigned)src[-i]; sum = sum * 2; for (int i = 15; i < filt.size; i++) - sum += filt.coeffs[i] * src[-i]; + sum += filt.coeffs[i] * (unsigned)src[-i]; sum = sum >> 6; if (ctx->cmode == 0) { if (bits == 0) { ctx->buf1[off] = sum + val; } else { - ctx->buf1[off] = (val + (sum >> bits) << bits) + + ctx->buf1[off] = (val + (sum >> bits)) * (1 << bits) + (((1U << bits) - 1U) & ctx->buf1[off + -1]); } ctx->buf0[off] = ctx->buf1[off] + ctx->buf0[off + -1]; From 8874cfa2e174cf1a94123fc2f1a3aa4d307a270f Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Mon, 20 Feb 2023 20:00:44 +0100 Subject: [PATCH 0306/2172] avcodec/rka: check for size 1 filter Such filters will not advance and be stuck in the current implementation Fixes: Infinite loop Fixes: 56052/clusterfuzz-testcase-minimized-ffmpeg_AV_CODEC_ID_RKA_fuzzer-5236218750435328 Found-by: continuous fuzzing process https://github.com/google/oss-fuzz/tree/master/projects/ffmpeg Signed-off-by: Michael Niedermayer --- libavcodec/rka.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavcodec/rka.c b/libavcodec/rka.c index 994c563ffd0..7452acf27f6 100644 --- a/libavcodec/rka.c +++ b/libavcodec/rka.c @@ -691,7 +691,7 @@ static int decode_filter(RKAContext *s, ChContext *ctx, ACoder *ac, int off, uns else split = size >> 4; - if (size <= 0) + if (size <= 1) return 0; for (int x = 0; x < size;) { From a5d4e7e3f981ce90b92a9da7da26a3c2a2e061e9 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Mon, 20 Feb 2023 20:04:18 +0100 Subject: [PATCH 0307/2172] avcodec/rka: avoid negative value shift Fixes: left shift of negative value -81 Fixes: 56061/clusterfuzz-testcase-minimized-ffmpeg_AV_CODEC_ID_RKA_fuzzer-4649758062149632 Found-by: continuous fuzzing process https://github.com/google/oss-fuzz/tree/master/projects/ffmpeg Signed-off-by: Michael Niedermayer --- libavcodec/rka.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavcodec/rka.c b/libavcodec/rka.c index 7452acf27f6..1eb2289e586 100644 --- a/libavcodec/rka.c +++ b/libavcodec/rka.c @@ -737,7 +737,7 @@ static int decode_filter(RKAContext *s, ChContext *ctx, ACoder *ac, int off, uns } ctx->buf0[off] = ctx->buf1[off] + ctx->buf0[off + -1]; } else { - val <<= ctx->cmode; + val *= 1 << ctx->cmode; sum += ctx->buf0[off + -1] + val; switch (s->bps) { case 16: sum = av_clip_int16(sum); break; From a02e45a1f3cc6f07c7437c1e225dea2683f843cf Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Mon, 20 Feb 2023 20:09:36 +0100 Subject: [PATCH 0308/2172] avcodec/rka: avoid undefined doubling sum overflow Fixes: signed integer overflow: -2124073172 * 2 cannot be represented in type 'int' Fixes: 56099/clusterfuzz-testcase-minimized-ffmpeg_AV_CODEC_ID_RKA_fuzzer-4530933127839744 Found-by: continuous fuzzing process https://github.com/google/oss-fuzz/tree/master/projects/ffmpeg Signed-off-by: Michael Niedermayer --- libavcodec/rka.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavcodec/rka.c b/libavcodec/rka.c index 1eb2289e586..2212e3f9306 100644 --- a/libavcodec/rka.c +++ b/libavcodec/rka.c @@ -724,7 +724,7 @@ static int decode_filter(RKAContext *s, ChContext *ctx, ACoder *ac, int off, uns src = &ctx->buf1[off + -1]; for (int i = 0; i < filt.size && i < 15; i++) sum += filt.coeffs[i] * (unsigned)src[-i]; - sum = sum * 2; + sum = sum * 2U; for (int i = 15; i < filt.size; i++) sum += filt.coeffs[i] * (unsigned)src[-i]; sum = sum >> 6; From 8ead0ae68eb64ad325efafd686c434727f3d666a Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Sat, 18 Feb 2023 22:33:02 +0100 Subject: [PATCH 0309/2172] avcodec/ffv1dec: Check that num h/v slices is supported Fixes: out of array access Fixes: 55597/clusterfuzz-testcase-minimized-ffmpeg_AV_CODEC_ID_FFV1_fuzzer-4898293416329216 Found-by: continuous fuzzing process https://github.com/google/oss-fuzz/tree/master/projects/ffmpeg Signed-off-by: Michael Niedermayer --- libavcodec/ffv1dec.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/libavcodec/ffv1dec.c b/libavcodec/ffv1dec.c index d74786cec3a..180d24e6953 100644 --- a/libavcodec/ffv1dec.c +++ b/libavcodec/ffv1dec.c @@ -475,6 +475,11 @@ static int read_extra_header(FFV1Context *f) return AVERROR_INVALIDDATA; } + if (f->num_h_slices > MAX_SLICES / f->num_v_slices) { + av_log(f->avctx, AV_LOG_ERROR, "slice count unsupported\n"); + return AVERROR_PATCHWELCOME; + } + f->quant_table_count = get_symbol(c, state, 0); if (f->quant_table_count > (unsigned)MAX_QUANT_TABLES || !f->quant_table_count) { av_log(f->avctx, AV_LOG_ERROR, "quant table count %d is invalid\n", f->quant_table_count); From 2df271c78cd4b7d481a2d34abb71a2450b43c7e2 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Sat, 18 Feb 2023 23:03:37 +0100 Subject: [PATCH 0310/2172] avformat/wavarc: Check if extradata has been fully read Signed-off-by: Michael Niedermayer --- libavformat/wavarc.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/libavformat/wavarc.c b/libavformat/wavarc.c index 208b7237160..2b5d1b99ebb 100644 --- a/libavformat/wavarc.c +++ b/libavformat/wavarc.c @@ -22,6 +22,7 @@ #include "libavutil/channel_layout.h" #include "libavutil/intreadwrite.h" #include "avformat.h" +#include "avio_internal.h" #include "demux.h" #include "internal.h" @@ -84,7 +85,9 @@ static int wavarc_read_header(AVFormatContext *s) if (ret < 0) return ret; memcpy(par->extradata, data, sizeof(data)); - avio_read(pb, par->extradata + sizeof(data), fmt_len); + ret = ffio_read_size(pb, par->extradata + sizeof(data), fmt_len); + if (ret < 0) + return ret; par->codec_type = AVMEDIA_TYPE_AUDIO; par->codec_id = AV_CODEC_ID_WAVARC; From 4dee46426e6d23adda048414433c2887314a4267 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Sat, 18 Feb 2023 23:08:59 +0100 Subject: [PATCH 0311/2172] avcodec/wavarc: Check k Fixes: Assertion failure Fixes: 55849/clusterfuzz-testcase-minimized-ffmpeg_AV_CODEC_ID_WAVARC_fuzzer-6590105973555200 Found-by: continuous fuzzing process https://github.com/google/oss-fuzz/tree/master/projects/ffmpeg Signed-off-by: Michael Niedermayer --- libavcodec/wavarc.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/libavcodec/wavarc.c b/libavcodec/wavarc.c index b626daa66eb..8d37af95716 100644 --- a/libavcodec/wavarc.c +++ b/libavcodec/wavarc.c @@ -192,6 +192,8 @@ static int decode_1dif(AVCodecContext *avctx, if (block_type < 4 && block_type >= 0) { k = 1 + (avctx->sample_fmt == AV_SAMPLE_FMT_S16P); k = get_urice(gb, k) + 1; + if (k > 32) + return AVERROR_INVALIDDATA; } switch (block_type) { @@ -282,6 +284,8 @@ static int decode_2slp(AVCodecContext *avctx, if (block_type < 5 && block_type >= 0) { k = 1 + (avctx->sample_fmt == AV_SAMPLE_FMT_S16P); k = get_urice(gb, k) + 1; + if (k > 32) + return AVERROR_INVALIDDATA; } switch (block_type) { From d5bae704068dc37191280e024eecb8d02b762b28 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Wed, 11 Jan 2023 23:26:06 +0100 Subject: [PATCH 0312/2172] avcodec/pngdec: Check deloco index more exactly Fixes: out of array access: Fixes: 48567/clusterfuzz-testcase-minimized-ffmpeg_AV_CODEC_ID_PNG_fuzzer-6716193709096960 Alternatively it should be possible to limit this to 3 plane RGB 8 /16bit to ensure the size is what it should be Found-by: continuous fuzzing process https://github.com/google/oss-fuzz/tree/master/projects/ffmpeg Signed-off-by: Michael Niedermayer --- libavcodec/pngdec.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavcodec/pngdec.c b/libavcodec/pngdec.c index 0d969decf25..1ba1bb20d0e 100644 --- a/libavcodec/pngdec.c +++ b/libavcodec/pngdec.c @@ -329,7 +329,7 @@ void ff_png_filter_row(PNGDSPContext *dsp, uint8_t *dst, int filter_type, static void deloco_ ## NAME(TYPE *dst, int size, int alpha) \ { \ int i; \ - for (i = 0; i < size; i += 3 + alpha) { \ + for (i = 0; i < size - 2; i += 3 + alpha) { \ int g = dst [i + 1]; \ dst[i + 0] += g; \ dst[i + 2] += g; \ From df1a38d5200e14a29903f1027b4548d595c7ff8a Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Wed, 11 Jan 2023 23:56:05 +0100 Subject: [PATCH 0313/2172] avcodec/pngdec: dont skip/read chunk twice Fixes: out of array access Fixes: 48567/clusterfuzz-testcase-minimized-ffmpeg_AV_CODEC_ID_PNG_fuzzer-6668158952144896.fuzz Found-by: continuous fuzzing process https://github.com/google/oss-fuzz/tree/master/projects/ffmpeg Signed-off-by: Michael Niedermayer --- libavcodec/pngdec.c | 1 + 1 file changed, 1 insertion(+) diff --git a/libavcodec/pngdec.c b/libavcodec/pngdec.c index 1ba1bb20d0e..d63640345bc 100644 --- a/libavcodec/pngdec.c +++ b/libavcodec/pngdec.c @@ -1238,6 +1238,7 @@ static int decode_frame_common(AVCodecContext *avctx, PNGDecContext *s, } av_log(avctx, AV_LOG_ERROR, ", skipping\n"); bytestream2_skip(&s->gb, length + 8); /* tag */ + continue; } } tag = bytestream2_get_le32(&s->gb); From f0150cd41c2d3c01050a6c4f3df1de511a217913 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Thu, 12 Jan 2023 00:29:02 +0100 Subject: [PATCH 0314/2172] avcodec/videodsp_template: Adjust pointers to avoid undefined pointer things Fixes: subtraction of unsigned offset from 0xf6602770 overflowed to 0xf6638c80 Fixes: 48567/clusterfuzz-testcase-minimized-ffmpeg_AV_CODEC_ID_THEORA_fuzzer-495074400600064 Found-by: continuous fuzzing process https://github.com/google/oss-fuzz/tree/master/projects/ffmpeg Signed-off-by: Michael Niedermayer --- libavcodec/videodsp_template.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libavcodec/videodsp_template.c b/libavcodec/videodsp_template.c index 324d70f2cb2..d653f4d524d 100644 --- a/libavcodec/videodsp_template.c +++ b/libavcodec/videodsp_template.c @@ -64,7 +64,7 @@ void FUNC(ff_emulated_edge_mc)(uint8_t *buf, const uint8_t *src, av_assert2(start_x < end_x && block_w); w = end_x - start_x; - src += start_y * src_linesize + start_x * sizeof(pixel); + src += start_y * src_linesize + start_x * (ptrdiff_t)sizeof(pixel); buf += start_x * sizeof(pixel); // top @@ -87,7 +87,7 @@ void FUNC(ff_emulated_edge_mc)(uint8_t *buf, const uint8_t *src, buf += buf_linesize; } - buf -= block_h * buf_linesize + start_x * sizeof(pixel); + buf -= block_h * buf_linesize + start_x * (ptrdiff_t)sizeof(pixel); while (block_h--) { pixel *bufp = (pixel *) buf; From 01636a63d452c592ece35af6f72bb7affcad58f2 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Wed, 11 Jan 2023 18:59:16 +0100 Subject: [PATCH 0315/2172] avcodec/utils: allocate a line more for VC1 and WMV3 Fixes: out of array read on 32bit Fixes: 54857/clusterfuzz-testcase-minimized-ffmpeg_AV_CODEC_ID_VC1_fuzzer-5840588224462848 The chroma MC code reads over the currently allocated frame. Alternative fixes would be allocating a few bytes more at the end instead of a whole line extra or to adjust the threshold where the edge emu code is activated Found-by: continuous fuzzing process https://github.com/google/oss-fuzz/tree/master/projects/ffmpeg Signed-off-by: Michael Niedermayer --- libavcodec/utils.c | 1 + 1 file changed, 1 insertion(+) diff --git a/libavcodec/utils.c b/libavcodec/utils.c index 3b58c8a2edd..701bebe337c 100644 --- a/libavcodec/utils.c +++ b/libavcodec/utils.c @@ -323,6 +323,7 @@ void avcodec_align_dimensions2(AVCodecContext *s, int *width, int *height, *width = FFALIGN(*width, w_align); *height = FFALIGN(*height, h_align); if (s->codec_id == AV_CODEC_ID_H264 || s->lowres || + s->codec_id == AV_CODEC_ID_VC1 || s->codec_id == AV_CODEC_ID_WMV3 || s->codec_id == AV_CODEC_ID_VP5 || s->codec_id == AV_CODEC_ID_VP6 || s->codec_id == AV_CODEC_ID_VP6F || s->codec_id == AV_CODEC_ID_VP6A ) { From 4eef658ca59d3d6ba46ab52a36d7faf5fe820874 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Wed, 11 Jan 2023 19:39:38 +0100 Subject: [PATCH 0316/2172] avcodec/utils: Ensure linesize for SVQ3 Fixes: Assertion block_w * sizeof(uint8_t) <= ((buf_linesize) >= 0 ? (buf_linesize) : (-(buf_linesize)) Fixes: 54861/clusterfuzz-testcase-minimized-ffmpeg_AV_CODEC_ID_SVQ3_fuzzer-5352418248622080 Found-by: continuous fuzzing process https://github.com/google/oss-fuzz/tree/master/projects/ffmpeg Signed-off-by: Michael Niedermayer --- libavcodec/utils.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/libavcodec/utils.c b/libavcodec/utils.c index 701bebe337c..599da21dba2 100644 --- a/libavcodec/utils.c +++ b/libavcodec/utils.c @@ -337,6 +337,9 @@ void avcodec_align_dimensions2(AVCodecContext *s, int *width, int *height, // the next rounded up width is 32 *width = FFMAX(*width, 32); } + if (s->codec_id == AV_CODEC_ID_SVQ3) { + *width = FFMAX(*width, 32); + } for (i = 0; i < 4; i++) linesize_align[i] = STRIDE_ALIGN; From 49487045dde6f69194332aac51fd4e598e19c7b6 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Wed, 11 Jan 2023 20:42:23 +0100 Subject: [PATCH 0317/2172] avcodec/bink: Fix off by 1 error in ref end Fixes: out of array access Fixes: 48567/clusterfuzz-testcase-minimized-ffmpeg_AV_CODEC_ID_BINK_fuzzer-6657932926517248 Alterantivly to this it is possibly to allocate a bigger array Note: oss-fuzz assigned this issue to a unrelated theora bug so the bug number matches that Found-by: continuous fuzzing process https://github.com/google/oss-fuzz/tree/master/projects/ffmpeg Signed-off-by: Michael Niedermayer --- libavcodec/bink.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavcodec/bink.c b/libavcodec/bink.c index e3971e557aa..a3140114f0c 100644 --- a/libavcodec/bink.c +++ b/libavcodec/bink.c @@ -870,7 +870,7 @@ static int binkb_decode_plane(BinkContext *c, AVFrame *frame, GetBitContext *gb, binkb_init_bundles(c); ref_start = frame->data[plane_idx]; - ref_end = frame->data[plane_idx] + (bh * frame->linesize[plane_idx] + bw) * 8; + ref_end = frame->data[plane_idx] + (bh * frame->linesize[plane_idx] + bw - 1) * 8; for (i = 0; i < 64; i++) coordmap[i] = (i & 7) + (i >> 3) * stride; From ea9deafd3b13233802c4548c4c58a707d76805a3 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Wed, 11 Jan 2023 20:50:39 +0100 Subject: [PATCH 0318/2172] avcodec/bink: Avoid undefined out of array end pointers in binkb_decode_plane() Signed-off-by: Michael Niedermayer --- libavcodec/bink.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/libavcodec/bink.c b/libavcodec/bink.c index a3140114f0c..15fc9d29ed8 100644 --- a/libavcodec/bink.c +++ b/libavcodec/bink.c @@ -870,7 +870,7 @@ static int binkb_decode_plane(BinkContext *c, AVFrame *frame, GetBitContext *gb, binkb_init_bundles(c); ref_start = frame->data[plane_idx]; - ref_end = frame->data[plane_idx] + (bh * frame->linesize[plane_idx] + bw - 1) * 8; + ref_end = frame->data[plane_idx] + ((bh - 1) * frame->linesize[plane_idx] + bw - 1) * 8; for (i = 0; i < 64; i++) coordmap[i] = (i & 7) + (i >> 3) * stride; @@ -926,7 +926,7 @@ static int binkb_decode_plane(BinkContext *c, AVFrame *frame, GetBitContext *gb, xoff = binkb_get_value(c, BINKB_SRC_X_OFF); yoff = binkb_get_value(c, BINKB_SRC_Y_OFF) + ybias; ref = dst + xoff + yoff * stride; - if (ref < ref_start || ref + 8*stride > ref_end) { + if (ref < ref_start || ref > ref_end) { av_log(c->avctx, AV_LOG_WARNING, "Reference block is out of bounds\n"); } else if (ref + 8*stride < dst || ref >= dst + 8*stride) { c->put_pixels_tab(dst, ref, stride, 8); @@ -942,7 +942,7 @@ static int binkb_decode_plane(BinkContext *c, AVFrame *frame, GetBitContext *gb, xoff = binkb_get_value(c, BINKB_SRC_X_OFF); yoff = binkb_get_value(c, BINKB_SRC_Y_OFF) + ybias; ref = dst + xoff + yoff * stride; - if (ref < ref_start || ref + 8 * stride > ref_end) { + if (ref < ref_start || ref > ref_end) { av_log(c->avctx, AV_LOG_WARNING, "Reference block is out of bounds\n"); } else if (ref + 8*stride < dst || ref >= dst + 8*stride) { c->put_pixels_tab(dst, ref, stride, 8); @@ -974,7 +974,7 @@ static int binkb_decode_plane(BinkContext *c, AVFrame *frame, GetBitContext *gb, xoff = binkb_get_value(c, BINKB_SRC_X_OFF); yoff = binkb_get_value(c, BINKB_SRC_Y_OFF) + ybias; ref = dst + xoff + yoff * stride; - if (ref < ref_start || ref + 8 * stride > ref_end) { + if (ref < ref_start || ref > ref_end) { av_log(c->avctx, AV_LOG_WARNING, "Reference block is out of bounds\n"); } else if (ref + 8*stride < dst || ref >= dst + 8*stride) { c->put_pixels_tab(dst, ref, stride, 8); From 95f0f84dae4f040d91f1e60dc5438612c58e8906 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Thu, 12 Jan 2023 22:05:07 +0100 Subject: [PATCH 0319/2172] avcodec/xpmdec: Check size before allocation to avoid truncation Fixes:OOM Fixes:out of array access (no testcase) Fixes: 48567/clusterfuzz-testcase-minimized-ffmpeg_AV_CODEC_ID_XPM_fuzzer-6573323838685184 Found-by: continuous fuzzing process https://github.com/google/oss-fuzz/tree/master/projects/ffmpeg Signed-off-by: Michael Niedermayer --- libavcodec/xpmdec.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/libavcodec/xpmdec.c b/libavcodec/xpmdec.c index ff1f51dd32b..2550afb9d68 100644 --- a/libavcodec/xpmdec.c +++ b/libavcodec/xpmdec.c @@ -354,6 +354,9 @@ static int xpm_decode_frame(AVCodecContext *avctx, AVFrame *p, return AVERROR_INVALIDDATA; } + if (size > SIZE_MAX / 4) + return AVERROR(ENOMEM); + size *= 4; ptr += mod_strcspn(ptr, ",") + 1; From ac6eec1fc258efce219e4fccb84312a1b13a7a23 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Thu, 12 Jan 2023 23:42:59 +0100 Subject: [PATCH 0320/2172] avcodec/motionpixels: Mask pixels to valid values Fixes: out of array access Fixes: 48567/clusterfuzz-testcase-minimized-ffmpeg_AV_CODEC_ID_MOTIONPIXELS_fuzzer-6724203352555520 Found-by: continuous fuzzing process https://github.com/google/oss-fuzz/tree/master/projects/ffmpeg Signed-off-by: Michael Niedermayer --- libavcodec/motionpixels.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavcodec/motionpixels.c b/libavcodec/motionpixels.c index 4141c5a4957..a947ca05de7 100644 --- a/libavcodec/motionpixels.c +++ b/libavcodec/motionpixels.c @@ -185,7 +185,7 @@ static YuvPixel mp_get_yuv_from_rgb(MotionPixelsContext *mp, int x, int y) int color; color = *(uint16_t *)&mp->frame->data[0][y * mp->frame->linesize[0] + x * 2]; - return mp_rgb_yuv_table[color]; + return mp_rgb_yuv_table[color & 0x7FFF]; } static void mp_set_rgb_from_yuv(MotionPixelsContext *mp, int x, int y, const YuvPixel *p) From b09f31af1b5e483e614d0f5d673753c5ab778034 Mon Sep 17 00:00:00 2001 From: Shiyou Yin Date: Tue, 14 Feb 2023 20:25:56 +0800 Subject: [PATCH 0321/2172] avutil: [LA] use getauxval to do runtime check. Replace cpucfg with getauxval to avoid crash in case of some processor capabilities are not supportted by kernel used. Reviewed-by: Steven Liu --- libavutil/loongarch/cpu.c | 24 ++++++++---------------- 1 file changed, 8 insertions(+), 16 deletions(-) diff --git a/libavutil/loongarch/cpu.c b/libavutil/loongarch/cpu.c index e4b240bc44d..cad8504fde6 100644 --- a/libavutil/loongarch/cpu.c +++ b/libavutil/loongarch/cpu.c @@ -21,26 +21,18 @@ #include #include "cpu.h" +#include -#define LOONGARCH_CFG2 0x2 -#define LOONGARCH_CFG2_LSX (1 << 6) -#define LOONGARCH_CFG2_LASX (1 << 7) - -static int cpu_flags_cpucfg(void) +#define LA_HWCAP_LSX (1<<4) +#define LA_HWCAP_LASX (1<<5) +static int cpu_flags_getauxval(void) { int flags = 0; - uint32_t cfg2 = 0; - - __asm__ volatile( - "cpucfg %0, %1 \n\t" - : "+&r"(cfg2) - : "r"(LOONGARCH_CFG2) - ); + int flag = (int)getauxval(AT_HWCAP); - if (cfg2 & LOONGARCH_CFG2_LSX) + if (flag & LA_HWCAP_LSX) flags |= AV_CPU_FLAG_LSX; - - if (cfg2 & LOONGARCH_CFG2_LASX) + if (flag & LA_HWCAP_LASX) flags |= AV_CPU_FLAG_LASX; return flags; @@ -49,7 +41,7 @@ static int cpu_flags_cpucfg(void) int ff_get_cpu_flags_loongarch(void) { #if defined __linux__ - return cpu_flags_cpucfg(); + return cpu_flags_getauxval(); #else /* Assume no SIMD ASE supported */ return 0; From f45937754368fd6e34d4a4c61b8736f2d22136ab Mon Sep 17 00:00:00 2001 From: Linjie Fu Date: Thu, 16 Feb 2023 13:46:28 +0800 Subject: [PATCH 0322/2172] lavc/avcodec: Add HEVC Screen Content Coding Extensions profile Described in HEVC spec A.3.7. Bump minor version and add APIchanges entry for new added profile. Signed-off-by: Linjie Fu Signed-off-by: Fei Wang --- doc/APIchanges | 3 +++ libavcodec/avcodec.h | 1 + libavcodec/hevc_ps.c | 2 ++ libavcodec/profiles.c | 1 + libavcodec/version.h | 2 +- 5 files changed, 8 insertions(+), 1 deletion(-) diff --git a/doc/APIchanges b/doc/APIchanges index 0ba18e86097..9f851c73466 100644 --- a/doc/APIchanges +++ b/doc/APIchanges @@ -2,6 +2,9 @@ The last version increases of all libraries were on 2023-02-09 API changes, most recent first: +2023-02-25 - xxxxxxxxxx - lavc 60.5.100 - avcodec.h + Add FF_PROFILE_HEVC_SCC. + -------- 8< --------- FFmpeg 6.0 was cut here -------- 8< --------- 2023-02-16 - 927042b409 - lavf 60.2.100 - avformat.h diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h index 39881a1d2bc..9a0fe97cad1 100644 --- a/libavcodec/avcodec.h +++ b/libavcodec/avcodec.h @@ -1654,6 +1654,7 @@ typedef struct AVCodecContext { #define FF_PROFILE_HEVC_MAIN_10 2 #define FF_PROFILE_HEVC_MAIN_STILL_PICTURE 3 #define FF_PROFILE_HEVC_REXT 4 +#define FF_PROFILE_HEVC_SCC 9 #define FF_PROFILE_VVC_MAIN_10 1 #define FF_PROFILE_VVC_MAIN_10_444 33 diff --git a/libavcodec/hevc_ps.c b/libavcodec/hevc_ps.c index 5fe62ec35b7..4aa5b76d5f1 100644 --- a/libavcodec/hevc_ps.c +++ b/libavcodec/hevc_ps.c @@ -259,6 +259,8 @@ static int decode_profile_tier_level(GetBitContext *gb, AVCodecContext *avctx, av_log(avctx, AV_LOG_DEBUG, "Main Still Picture profile bitstream\n"); else if (ptl->profile_idc == FF_PROFILE_HEVC_REXT) av_log(avctx, AV_LOG_DEBUG, "Range Extension profile bitstream\n"); + else if (ptl->profile_idc == FF_PROFILE_HEVC_SCC) + av_log(avctx, AV_LOG_DEBUG, "Screen Content Coding Extension profile bitstream\n"); else av_log(avctx, AV_LOG_WARNING, "Unknown HEVC profile: %d\n", ptl->profile_idc); diff --git a/libavcodec/profiles.c b/libavcodec/profiles.c index 7af7fbeb130..2230fc5415d 100644 --- a/libavcodec/profiles.c +++ b/libavcodec/profiles.c @@ -85,6 +85,7 @@ const AVProfile ff_hevc_profiles[] = { { FF_PROFILE_HEVC_MAIN_10, "Main 10" }, { FF_PROFILE_HEVC_MAIN_STILL_PICTURE, "Main Still Picture" }, { FF_PROFILE_HEVC_REXT, "Rext" }, + { FF_PROFILE_HEVC_SCC, "Scc" }, { FF_PROFILE_UNKNOWN }, }; diff --git a/libavcodec/version.h b/libavcodec/version.h index 06631ffa8c4..7aa95fc3f1c 100644 --- a/libavcodec/version.h +++ b/libavcodec/version.h @@ -29,7 +29,7 @@ #include "version_major.h" -#define LIBAVCODEC_VERSION_MINOR 4 +#define LIBAVCODEC_VERSION_MINOR 5 #define LIBAVCODEC_VERSION_MICRO 100 #define LIBAVCODEC_VERSION_INT AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \ From 56e3cd23d486d6aa2e3dcddc57c8048547df4f42 Mon Sep 17 00:00:00 2001 From: Linjie Fu Date: Thu, 16 Feb 2023 13:46:29 +0800 Subject: [PATCH 0323/2172] lavc/hevc_ps: Add SPS/PPS parse support for HEVC extension syntax 1. Add extension syntax according to 7.3.2.2.3/7.3.2.3.3 in T-REC-H.265-201911. 2. Keep using parsed PPS when bitstream overread for compatibility. For example, the clip PS_A_VIDYO_3.bit in FATE test has incomplete extension syntax which will be overread and un-decodable if without this change. 3. Format brace in pps_range_extensions(). Signed-off-by: Linjie Fu Signed-off-by: Haihao Xiang Signed-off-by: Fei Wang --- libavcodec/hevc.h | 3 + libavcodec/hevc_ps.c | 289 +++++++++++++++++++++++++++++++++++++++++-- libavcodec/hevc_ps.h | 69 +++++++++++ 3 files changed, 349 insertions(+), 12 deletions(-) diff --git a/libavcodec/hevc.h b/libavcodec/hevc.h index 1804755327e..6b454a75c18 100644 --- a/libavcodec/hevc.h +++ b/libavcodec/hevc.h @@ -154,6 +154,9 @@ enum { // get near that, though, so set a lower limit here with the maximum // possible value for 4K video (at most 135 16x16 Ctb rows). HEVC_MAX_ENTRY_POINT_OFFSETS = HEVC_MAX_TILE_COLUMNS * 135, + + // A.3.7: Screen content coding extensions + HEVC_MAX_PALETTE_PREDICTOR_SIZE = 128, }; diff --git a/libavcodec/hevc_ps.c b/libavcodec/hevc_ps.c index 4aa5b76d5f1..348e4d8de2d 100644 --- a/libavcodec/hevc_ps.c +++ b/libavcodec/hevc_ps.c @@ -853,7 +853,7 @@ int ff_hevc_parse_sps(HEVCSPS *sps, GetBitContext *gb, unsigned int *sps_id, HEVCWindow *ow; int ret = 0; int log2_diff_max_min_transform_block_size; - int bit_depth_chroma, start, vui_present, sublayer_ordering_info; + int bit_depth_chroma, start, vui_present, sublayer_ordering_info, num_comps; int i; // Coded parameters @@ -1074,8 +1074,12 @@ int ff_hevc_parse_sps(HEVCSPS *sps, GetBitContext *gb, unsigned int *sps_id, decode_vui(gb, avctx, apply_defdispwin, sps); if (get_bits1(gb)) { // sps_extension_flag - sps->sps_range_extension_flag = get_bits1(gb); - skip_bits(gb, 7); //sps_extension_7bits = get_bits(gb, 7); + sps->sps_range_extension_flag = get_bits1(gb); + sps->sps_multilayer_extension_flag = get_bits1(gb); + sps->sps_3d_extension_flag = get_bits1(gb); + sps->sps_scc_extension_flag = get_bits1(gb); + skip_bits(gb, 4); // sps_extension_4bits + if (sps->sps_range_extension_flag) { sps->transform_skip_rotation_enabled_flag = get_bits1(gb); sps->transform_skip_context_enabled_flag = get_bits1(gb); @@ -1101,6 +1105,57 @@ int ff_hevc_parse_sps(HEVCSPS *sps, GetBitContext *gb, unsigned int *sps_id, av_log(avctx, AV_LOG_WARNING, "cabac_bypass_alignment_enabled_flag not yet implemented\n"); } + + if (sps->sps_multilayer_extension_flag) { + skip_bits1(gb); // inter_view_mv_vert_constraint_flag + av_log(avctx, AV_LOG_WARNING, + "sps_multilayer_extension_flag not yet implemented\n"); + } + + if (sps->sps_3d_extension_flag) { + for (i = 0; i <= 1; i++) { + skip_bits1(gb); // iv_di_mc_enabled_flag + skip_bits1(gb); // iv_mv_scal_enabled_flag + if (i == 0) { + get_ue_golomb_long(gb); // log2_ivmc_sub_pb_size_minus3 + skip_bits1(gb); // iv_res_pred_enabled_flag + skip_bits1(gb); // depth_ref_enabled_flag + skip_bits1(gb); // vsp_mc_enabled_flag + skip_bits1(gb); // dbbp_enabled_flag + } else { + skip_bits1(gb); // tex_mc_enabled_flag + get_ue_golomb_long(gb); // log2_ivmc_sub_pb_size_minus3 + skip_bits1(gb); // intra_contour_enabled_flag + skip_bits1(gb); // intra_dc_only_wedge_enabled_flag + skip_bits1(gb); // cqt_cu_part_pred_enabled_flag + skip_bits1(gb); // inter_dc_only_enabled_flag + skip_bits1(gb); // skip_intra_enabled_flag + } + } + av_log(avctx, AV_LOG_WARNING, + "sps_3d_extension_flag not yet implemented\n"); + } + + if (sps->sps_scc_extension_flag) { + sps->sps_curr_pic_ref_enabled_flag = get_bits1(gb); + sps->palette_mode_enabled_flag = get_bits1(gb); + if (sps->palette_mode_enabled_flag) { + sps->palette_max_size = get_ue_golomb_long(gb); + sps->delta_palette_max_predictor_size = get_ue_golomb_long(gb); + sps->sps_palette_predictor_initializers_present_flag = get_bits1(gb); + + if (sps->sps_palette_predictor_initializers_present_flag) { + sps->sps_num_palette_predictor_initializers_minus1 = get_ue_golomb_long(gb); + num_comps = !sps->chroma_format_idc ? 1 : 3; + for (int comp = 0; comp < num_comps; comp++) + for (i = 0; i <= sps->sps_num_palette_predictor_initializers_minus1; i++) + sps->sps_palette_predictor_initializer[comp][i] = + get_bits(gb, !comp ? sps->bit_depth : sps->bit_depth_chroma); + } + } + sps->motion_vector_resolution_control_idc = get_bits(gb, 2); + sps->intra_boundary_filtering_disabled_flag = get_bits1(gb); + } } if (apply_defdispwin) { sps->output_window.left_offset += sps->vui.def_disp_win.left_offset; @@ -1265,10 +1320,161 @@ static void hevc_pps_free(void *opaque, uint8_t *data) av_freep(&pps); } -static int pps_range_extensions(GetBitContext *gb, AVCodecContext *avctx, - HEVCPPS *pps, HEVCSPS *sps) { - int i; +static void colour_mapping_octants(GetBitContext *gb, HEVCPPS *pps, int inp_depth, + int idx_y, int idx_cb, int idx_cr, int inp_length) +{ + unsigned int split_octant_flag, part_num_y, coded_res_flag, res_coeff_q, res_coeff_r; + int bit_depth_cm_input_y, bit_depth_cm_output_y, cm_res_bits; + + part_num_y = 1 << pps->cm_y_part_num_log2; + + split_octant_flag = inp_depth < pps->cm_octant_depth ? get_bits1(gb) : 0; + + if (split_octant_flag) + for (int k = 0; k < 2; k++) + for (int m = 0; m < 2; m++) + for (int n = 0; n < 2; n++) + colour_mapping_octants(gb, pps, inp_depth + 1, + idx_y + part_num_y * k * inp_length / 2, + idx_cb + m * inp_length / 2, + idx_cr + n * inp_length / 2, + inp_length / 2); + else + for (int i = 0; i < part_num_y; i++) { + for (int j = 0; j < 4; j++) { + coded_res_flag = get_bits1(gb); + if (coded_res_flag) + for (int c = 0; c < 3; c++) { + res_coeff_q = get_ue_golomb_long(gb); + bit_depth_cm_input_y = 8 + pps->luma_bit_depth_cm_input_minus8; + bit_depth_cm_output_y = 8 + pps->luma_bit_depth_cm_output_minus8; + cm_res_bits = FFMAX(0, 10 + bit_depth_cm_input_y - bit_depth_cm_output_y - + pps->cm_res_quant_bits - (pps->cm_delta_flc_bits_minus1 + 1)); + res_coeff_r = cm_res_bits ? get_bits(gb, cm_res_bits) : 0; + if (res_coeff_q || res_coeff_r) + skip_bits1(gb); + } + } + } +} +static void colour_mapping_table(GetBitContext *gb, HEVCPPS *pps) +{ + pps->num_cm_ref_layers_minus1 = get_ue_golomb_long(gb); + for (int i = 0; i <= pps->num_cm_ref_layers_minus1; i++) + pps->cm_ref_layer_id[i] = get_bits(gb, 6); + + pps->cm_octant_depth = get_bits(gb, 2); + pps->cm_y_part_num_log2 = get_bits(gb, 2); + + pps->luma_bit_depth_cm_input_minus8 = get_ue_golomb_long(gb); + pps->chroma_bit_depth_cm_input_minus8 = get_ue_golomb_long(gb); + pps->luma_bit_depth_cm_output_minus8 = get_ue_golomb_long(gb); + pps->chroma_bit_depth_cm_output_minus8 = get_ue_golomb_long(gb); + + pps->cm_res_quant_bits = get_bits(gb, 2); + pps->cm_delta_flc_bits_minus1 = get_bits(gb, 2); + + if (pps->cm_octant_depth == 1) { + pps->cm_adapt_threshold_u_delta = get_se_golomb_long(gb); + pps->cm_adapt_threshold_v_delta = get_se_golomb_long(gb); + } + + colour_mapping_octants(gb, pps, 0, 0, 0, 0, 1 << pps->cm_octant_depth); +} + +static int pps_multilayer_extension(GetBitContext *gb, AVCodecContext *avctx, + HEVCPPS *pps, HEVCSPS *sps) +{ + pps->poc_reset_info_present_flag = get_bits1(gb); + pps->pps_infer_scaling_list_flag = get_bits1(gb); + if (pps->pps_infer_scaling_list_flag) + pps->pps_scaling_list_ref_layer_id = get_bits(gb, 6); + + pps->num_ref_loc_offsets = get_ue_golomb_long(gb); + for (int i = 0; i < pps->num_ref_loc_offsets; i++) { + pps->ref_loc_offset_layer_id[i] = get_bits(gb, 6); + pps->scaled_ref_layer_offset_present_flag[i] = get_bits1(gb); + if (pps->scaled_ref_layer_offset_present_flag[i]) { + pps->scaled_ref_layer_left_offset[pps->ref_loc_offset_layer_id[i]] = get_se_golomb_long(gb); + pps->scaled_ref_layer_top_offset[pps->ref_loc_offset_layer_id[i]] = get_se_golomb_long(gb); + pps->scaled_ref_layer_right_offset[pps->ref_loc_offset_layer_id[i]] = get_se_golomb_long(gb); + pps->scaled_ref_layer_bottom_offset[pps->ref_loc_offset_layer_id[i]] = get_se_golomb_long(gb); + } + + pps->ref_region_offset_present_flag[i] = get_bits1(gb); + if (pps->ref_region_offset_present_flag[i]) { + pps->ref_region_left_offset[pps->ref_loc_offset_layer_id[i]] = get_se_golomb_long(gb); + pps->ref_region_top_offset[pps->ref_loc_offset_layer_id[i]] = get_se_golomb_long(gb); + pps->ref_region_right_offset[pps->ref_loc_offset_layer_id[i]] = get_se_golomb_long(gb); + pps->ref_region_bottom_offset[pps->ref_loc_offset_layer_id[i]] = get_se_golomb_long(gb); + } + + pps->resample_phase_set_present_flag[i] = get_bits1(gb); + if (pps->resample_phase_set_present_flag[i]) { + pps->phase_hor_luma[pps->ref_loc_offset_layer_id[i]] = get_ue_golomb_long(gb); + pps->phase_ver_luma[pps->ref_loc_offset_layer_id[i]] = get_ue_golomb_long(gb); + pps->phase_hor_chroma_plus8[pps->ref_loc_offset_layer_id[i]] = get_ue_golomb_long(gb); + pps->phase_ver_chroma_plus8[pps->ref_loc_offset_layer_id[i]] = get_ue_golomb_long(gb); + } + } + + pps->colour_mapping_enabled_flag = get_bits1(gb); + if (pps->colour_mapping_enabled_flag) + colour_mapping_table(gb, pps); + + return 0; +} + +static void delta_dlt(GetBitContext *gb, HEVCPPS *pps) +{ + unsigned int num_val_delta_dlt, max_diff = 0; + int min_diff_minus1 = -1; + unsigned int len; + + num_val_delta_dlt = get_bits(gb, pps->pps_bit_depth_for_depth_layers_minus8 + 8); + if (num_val_delta_dlt) { + if (num_val_delta_dlt > 1) + max_diff = get_bits(gb, pps->pps_bit_depth_for_depth_layers_minus8 + 8); + if (num_val_delta_dlt > 2 && max_diff) { + len = av_log2(max_diff) + 1; + min_diff_minus1 = get_bits(gb, len); + } + if (max_diff > (min_diff_minus1 + 1)) + for (int k = 1; k < num_val_delta_dlt; k++) { + len = av_log2(max_diff - (min_diff_minus1 + 1)) + 1; + skip_bits(gb, len); // delta_val_diff_minus_min + } + } +} + +static int pps_3d_extension(GetBitContext *gb, AVCodecContext *avctx, + HEVCPPS *pps, HEVCSPS *sps) +{ + unsigned int pps_depth_layers_minus1; + + if (get_bits1(gb)) { // dlts_present_flag + pps_depth_layers_minus1 = get_bits(gb, 6); + pps->pps_bit_depth_for_depth_layers_minus8 = get_bits(gb, 4); + for (int i = 0; i <= pps_depth_layers_minus1; i++) { + if (get_bits1(gb)) { // dlt_flag[i] + if (!get_bits1(gb)) { // dlt_pred_flag[i] + if (get_bits1(gb)) { // dlt_val_flags_present_flag[i] + for (int j = 0; j <= ((1 << (pps->pps_bit_depth_for_depth_layers_minus8 + 8)) - 1); j++) + skip_bits1(gb); // dlt_value_flag[i][j] + } else + delta_dlt(gb, pps); + } + } + } + } + + return 0; +} + +static int pps_range_extensions(GetBitContext *gb, AVCodecContext *avctx, + HEVCPPS *pps, HEVCSPS *sps) +{ if (pps->transform_skip_enabled_flag) { pps->log2_max_transform_skip_block_size = get_ue_golomb_long(gb) + 2; } @@ -1282,7 +1488,7 @@ static int pps_range_extensions(GetBitContext *gb, AVCodecContext *avctx, "chroma_qp_offset_list_len_minus1 shall be in the range [0, 5].\n"); return AVERROR_INVALIDDATA; } - for (i = 0; i <= pps->chroma_qp_offset_list_len_minus1; i++) { + for (int i = 0; i <= pps->chroma_qp_offset_list_len_minus1; i++) { pps->cb_qp_offset_list[i] = get_se_golomb_long(gb); if (pps->cb_qp_offset_list[i]) { av_log(avctx, AV_LOG_WARNING, @@ -1306,6 +1512,47 @@ static int pps_range_extensions(GetBitContext *gb, AVCodecContext *avctx, return(0); } +static int pps_scc_extension(GetBitContext *gb, AVCodecContext *avctx, + HEVCPPS *pps, HEVCSPS *sps) +{ + int num_comps, ret; + + pps->pps_curr_pic_ref_enabled_flag = get_bits1(gb); + if (pps->residual_adaptive_colour_transform_enabled_flag = get_bits1(gb)) { + pps->pps_slice_act_qp_offsets_present_flag = get_bits1(gb); + pps->pps_act_y_qp_offset = get_se_golomb_long(gb) - 5; + pps->pps_act_cb_qp_offset = get_se_golomb_long(gb) - 5; + pps->pps_act_cr_qp_offset = get_se_golomb_long(gb) - 3; + +#define CHECK_QP_OFFSET(name) (pps->pps_act_ ## name ## _qp_offset <= -12 || \ + pps->pps_act_ ## name ## _qp_offset >= 12) + ret = CHECK_QP_OFFSET(y) || CHECK_QP_OFFSET(cb) || CHECK_QP_OFFSET(cr); +#undef CHECK_QP_OFFSET + if (ret) { + av_log(avctx, AV_LOG_ERROR, + "PpsActQpOffsetY/Cb/Cr shall be in the range of [-12, 12].\n"); + return AVERROR_INVALIDDATA; + } + } + + if (pps->pps_palette_predictor_initializers_present_flag = get_bits1(gb)) { + if ((pps->pps_num_palette_predictor_initializers = get_ue_golomb_long(gb)) > 0) { + pps->monochrome_palette_flag = get_bits1(gb); + pps->luma_bit_depth_entry_minus8 = get_ue_golomb_long(gb); + if (!pps->monochrome_palette_flag) + pps->chroma_bit_depth_entry_minus8 = get_ue_golomb_long(gb); + num_comps = pps->monochrome_palette_flag ? 1 : 3; + for (int comp = 0; comp < num_comps; comp++) + for (int i = 0; i < pps->pps_num_palette_predictor_initializers; i++) + pps->pps_palette_predictor_initializer[comp][i] = + get_bits(gb, 8 + (!comp ? pps->luma_bit_depth_entry_minus8 : + pps->chroma_bit_depth_entry_minus8)); + } + } + + return 0; +} + static inline int setup_pps(AVCodecContext *avctx, GetBitContext *gb, HEVCPPS *pps, HEVCSPS *sps) { @@ -1658,12 +1905,31 @@ int ff_hevc_decode_nal_pps(GetBitContext *gb, AVCodecContext *avctx, pps->slice_header_extension_present_flag = get_bits1(gb); if (get_bits1(gb)) { // pps_extension_present_flag - pps->pps_range_extensions_flag = get_bits1(gb); - skip_bits(gb, 7); // pps_extension_7bits - if (sps->ptl.general_ptl.profile_idc == FF_PROFILE_HEVC_REXT && pps->pps_range_extensions_flag) { + pps->pps_range_extensions_flag = get_bits1(gb); + pps->pps_multilayer_extension_flag = get_bits1(gb); + pps->pps_3d_extension_flag = get_bits1(gb); + pps->pps_scc_extension_flag = get_bits1(gb); + skip_bits(gb, 4); // pps_extension_4bits + + if (sps->ptl.general_ptl.profile_idc >= FF_PROFILE_HEVC_REXT && pps->pps_range_extensions_flag) { if ((ret = pps_range_extensions(gb, avctx, pps, sps)) < 0) goto err; } + + if (pps->pps_multilayer_extension_flag) { + if ((ret = pps_multilayer_extension(gb, avctx, pps, sps)) < 0) + goto err; + } + + if (pps->pps_3d_extension_flag) { + if ((ret = pps_3d_extension(gb, avctx, pps, sps)) < 0) + goto err; + } + + if (pps->pps_scc_extension_flag) { + if ((ret = pps_scc_extension(gb, avctx, pps, sps)) < 0) + goto err; + } } ret = setup_pps(avctx, gb, pps, sps); @@ -1671,9 +1937,8 @@ int ff_hevc_decode_nal_pps(GetBitContext *gb, AVCodecContext *avctx, goto err; if (get_bits_left(gb) < 0) { - av_log(avctx, AV_LOG_ERROR, + av_log(avctx, AV_LOG_WARNING, "Overread PPS by %d bits\n", -get_bits_left(gb)); - goto err; } remove_pps(ps, pps_id); diff --git a/libavcodec/hevc_ps.h b/libavcodec/hevc_ps.h index 18894cfed18..1f704108e35 100644 --- a/libavcodec/hevc_ps.h +++ b/libavcodec/hevc_ps.h @@ -210,6 +210,20 @@ typedef struct HEVCSPS { int persistent_rice_adaptation_enabled_flag; int cabac_bypass_alignment_enabled_flag; + int sps_multilayer_extension_flag; + int sps_3d_extension_flag; + + int sps_scc_extension_flag; + int sps_curr_pic_ref_enabled_flag; + int palette_mode_enabled_flag; + int palette_max_size; + int delta_palette_max_predictor_size; + int sps_palette_predictor_initializers_present_flag; + int sps_num_palette_predictor_initializers_minus1; + int sps_palette_predictor_initializer[3][HEVC_MAX_PALETTE_PREDICTOR_SIZE]; + int motion_vector_resolution_control_idc; + int intra_boundary_filtering_disabled_flag; + ///< coded frame dimension in various units int width; int height; @@ -284,6 +298,9 @@ typedef struct HEVCPPS { uint8_t slice_header_extension_present_flag; uint8_t log2_max_transform_skip_block_size; uint8_t pps_range_extensions_flag; + uint8_t pps_multilayer_extension_flag; + uint8_t pps_3d_extension_flag; + uint8_t pps_scc_extension_flag; uint8_t cross_component_prediction_enabled_flag; uint8_t chroma_qp_offset_list_enabled_flag; uint8_t diff_cu_chroma_qp_offset_depth; @@ -293,6 +310,58 @@ typedef struct HEVCPPS { uint8_t log2_sao_offset_scale_luma; uint8_t log2_sao_offset_scale_chroma; + // Multilayer extension parameters + uint8_t poc_reset_info_present_flag; + uint8_t pps_infer_scaling_list_flag; + uint8_t pps_scaling_list_ref_layer_id; + uint16_t num_ref_loc_offsets; + uint8_t ref_loc_offset_layer_id[64]; + uint8_t scaled_ref_layer_offset_present_flag[64]; + int8_t scaled_ref_layer_left_offset[64]; + int8_t scaled_ref_layer_top_offset[64]; + int8_t scaled_ref_layer_right_offset[64]; + int8_t scaled_ref_layer_bottom_offset[64]; + uint8_t ref_region_offset_present_flag[64]; + int8_t ref_region_left_offset[64]; + int8_t ref_region_top_offset[64]; + int8_t ref_region_right_offset[64]; + int8_t ref_region_bottom_offset[64]; + uint8_t resample_phase_set_present_flag[64]; + uint16_t phase_hor_luma[64]; + uint16_t phase_ver_luma[64]; + uint16_t phase_hor_chroma_plus8[64]; + uint16_t phase_ver_chroma_plus8[64]; + uint8_t colour_mapping_enabled_flag; + uint16_t num_cm_ref_layers_minus1; + uint8_t cm_ref_layer_id[63]; + uint8_t cm_octant_depth; + uint8_t cm_y_part_num_log2; + uint16_t luma_bit_depth_cm_input_minus8; + uint16_t chroma_bit_depth_cm_input_minus8; + uint16_t luma_bit_depth_cm_output_minus8; + uint16_t chroma_bit_depth_cm_output_minus8; + uint8_t cm_res_quant_bits; + uint8_t cm_delta_flc_bits_minus1; + int8_t cm_adapt_threshold_u_delta; + int8_t cm_adapt_threshold_v_delta; + + // 3D extension parameters + uint8_t pps_bit_depth_for_depth_layers_minus8; + + // SCC extension parameters + uint8_t pps_curr_pic_ref_enabled_flag; + uint8_t residual_adaptive_colour_transform_enabled_flag; + uint8_t pps_slice_act_qp_offsets_present_flag; + int8_t pps_act_y_qp_offset; // _plus5 + int8_t pps_act_cb_qp_offset; // _plus5 + int8_t pps_act_cr_qp_offset; // _plus3 + uint8_t pps_palette_predictor_initializers_present_flag; + uint8_t pps_num_palette_predictor_initializers; + uint8_t monochrome_palette_flag; + uint8_t luma_bit_depth_entry_minus8; + uint8_t chroma_bit_depth_entry_minus8; + uint8_t pps_palette_predictor_initializer[3][HEVC_MAX_PALETTE_PREDICTOR_SIZE]; + // Inferred parameters unsigned int *column_width; ///< ColumnWidth unsigned int *row_height; ///< RowHeight From c1dceaf0c74fc010cf43744c36af6d9ebaa0b13d Mon Sep 17 00:00:00 2001 From: Linjie Fu Date: Thu, 16 Feb 2023 13:46:30 +0800 Subject: [PATCH 0324/2172] lavc/hevcdec: Add slice parse support for HEVC SCC extension Signed-off-by: Linjie Fu Signed-off-by: Fei Wang --- libavcodec/hevcdec.c | 6 ++++++ libavcodec/hevcdec.h | 4 ++++ 2 files changed, 10 insertions(+) diff --git a/libavcodec/hevcdec.c b/libavcodec/hevcdec.c index 567e8d81d4a..f9a97ac7f51 100644 --- a/libavcodec/hevcdec.c +++ b/libavcodec/hevcdec.c @@ -856,6 +856,12 @@ static int hls_slice_header(HEVCContext *s) sh->slice_cr_qp_offset = 0; } + if (s->ps.pps->pps_slice_act_qp_offsets_present_flag) { + sh->slice_act_y_qp_offset = get_se_golomb(gb); + sh->slice_act_cb_qp_offset = get_se_golomb(gb); + sh->slice_act_cr_qp_offset = get_se_golomb(gb); + } + if (s->ps.pps->chroma_qp_offset_list_enabled_flag) sh->cu_chroma_qp_offset_enabled_flag = get_bits1(gb); else diff --git a/libavcodec/hevcdec.h b/libavcodec/hevcdec.h index 9d3f4adbb3c..7841ba85652 100644 --- a/libavcodec/hevcdec.h +++ b/libavcodec/hevcdec.h @@ -295,6 +295,10 @@ typedef struct SliceHeader { int slice_cb_qp_offset; int slice_cr_qp_offset; + int slice_act_y_qp_offset; + int slice_act_cb_qp_offset; + int slice_act_cr_qp_offset; + uint8_t cu_chroma_qp_offset_enabled_flag; int beta_offset; ///< beta_offset_div2 * 2 From 513d188d9bfe882580cdb8f3e9a8ed0c290875ad Mon Sep 17 00:00:00 2001 From: Linjie Fu Date: Thu, 16 Feb 2023 13:46:31 +0800 Subject: [PATCH 0325/2172] lavc/hevcdec: Fix the parsing for use_integer_mv_flag According to 7.3.6.1, use_integer_mv_flag should be parsed if motion_vector_resolution_control_idc equals to 2. If not present, it equals to motion_vector_resolution_control_idc. Signed-off-by: Linjie Fu Signed-off-by: Fei Wang --- libavcodec/hevcdec.c | 8 ++++++++ libavcodec/hevcdec.h | 1 + 2 files changed, 9 insertions(+) diff --git a/libavcodec/hevcdec.c b/libavcodec/hevcdec.c index f9a97ac7f51..52fa6271336 100644 --- a/libavcodec/hevcdec.c +++ b/libavcodec/hevcdec.c @@ -839,6 +839,14 @@ static int hls_slice_header(HEVCContext *s) sh->max_num_merge_cand); return AVERROR_INVALIDDATA; } + + // Syntax in 7.3.6.1 + if (s->ps.sps->motion_vector_resolution_control_idc == 2) + sh->use_integer_mv_flag = get_bits1(gb); + else + // Inferred to be equal to motion_vector_resolution_control_idc if not present + sh->use_integer_mv_flag = s->ps.sps->motion_vector_resolution_control_idc; + } sh->slice_qp_delta = get_se_golomb(gb); diff --git a/libavcodec/hevcdec.h b/libavcodec/hevcdec.h index 7841ba85652..a7fc669bcbc 100644 --- a/libavcodec/hevcdec.h +++ b/libavcodec/hevcdec.h @@ -305,6 +305,7 @@ typedef struct SliceHeader { int tc_offset; ///< tc_offset_div2 * 2 unsigned int max_num_merge_cand; ///< 5 - 5_minus_max_num_merge_cand + uint8_t use_integer_mv_flag; unsigned *entry_point_offset; int * offset; From fc3837ba85eafaeb5674c3d6b574a79da46d55b2 Mon Sep 17 00:00:00 2001 From: Linjie Fu Date: Thu, 16 Feb 2023 13:46:32 +0800 Subject: [PATCH 0326/2172] lavc/hevcdec: Set max_num_merge_cand to uint8_t uint8_t is big enough and keep consistent with the definition in cbs_h265.h. Signed-off-by: Linjie Fu Signed-off-by: Fei Wang --- libavcodec/hevcdec.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavcodec/hevcdec.h b/libavcodec/hevcdec.h index a7fc669bcbc..aab816791e1 100644 --- a/libavcodec/hevcdec.h +++ b/libavcodec/hevcdec.h @@ -304,7 +304,7 @@ typedef struct SliceHeader { int beta_offset; ///< beta_offset_div2 * 2 int tc_offset; ///< tc_offset_div2 * 2 - unsigned int max_num_merge_cand; ///< 5 - 5_minus_max_num_merge_cand + uint8_t max_num_merge_cand; ///< 5 - 5_minus_max_num_merge_cand uint8_t use_integer_mv_flag; unsigned *entry_point_offset; From 09c656d9c4f6fc66f0f2d60c235bb393b979e27f Mon Sep 17 00:00:00 2001 From: Linjie Fu Date: Thu, 16 Feb 2023 13:46:33 +0800 Subject: [PATCH 0327/2172] lavc/hevc: Update reference list for SCC Screen Content Coding allows non-intra slice in an IRAP frame which can reference the frame itself, and would mark the current decoded picture as "used for long-term reference", no matter TwoVersionsOfCurrDecPicFlag(8.1.3), hence some previous restricts are not suitable any more. Constructe RefPicListTemp and RefPicList according to 8-8/9/10. Disable slice decoding for SCC profile to avoid unexpected error in hevc native decoder and patch welcome. Signed-off-by: Linjie Fu Signed-off-by: Fei Wang --- libavcodec/hevc_refs.c | 21 ++++++++++++++++++++- libavcodec/hevcdec.c | 10 +++++++++- 2 files changed, 29 insertions(+), 2 deletions(-) diff --git a/libavcodec/hevc_refs.c b/libavcodec/hevc_refs.c index 811e8feff8a..96153a2459f 100644 --- a/libavcodec/hevc_refs.c +++ b/libavcodec/hevc_refs.c @@ -322,7 +322,7 @@ int ff_hevc_slice_rpl(HEVCContext *s) return ret; if (!(s->rps[ST_CURR_BEF].nb_refs + s->rps[ST_CURR_AFT].nb_refs + - s->rps[LT_CURR].nb_refs)) { + s->rps[LT_CURR].nb_refs) && !s->ps.pps->pps_curr_pic_ref_enabled_flag) { av_log(s->avctx, AV_LOG_ERROR, "Zero refs in the frame RPS.\n"); return AVERROR_INVALIDDATA; } @@ -349,6 +349,13 @@ int ff_hevc_slice_rpl(HEVCContext *s) rpl_tmp.nb_refs++; } } + // Construct RefPicList0, RefPicList1 (8-8, 8-10) + if (s->ps.pps->pps_curr_pic_ref_enabled_flag) { + rpl_tmp.list[rpl_tmp.nb_refs] = s->ref->poc; + rpl_tmp.ref[rpl_tmp.nb_refs] = s->ref; + rpl_tmp.isLongTerm[rpl_tmp.nb_refs] = 1; + rpl_tmp.nb_refs++; + } } /* reorder the references if necessary */ @@ -371,6 +378,14 @@ int ff_hevc_slice_rpl(HEVCContext *s) rpl->nb_refs = FFMIN(rpl->nb_refs, sh->nb_refs[list_idx]); } + // 8-9 + if (s->ps.pps->pps_curr_pic_ref_enabled_flag && + !sh->rpl_modification_flag[list_idx] && + rpl_tmp.nb_refs > sh->nb_refs[L0]) { + rpl->list[sh->nb_refs[L0] - 1] = s->ref->poc; + rpl->ref[sh->nb_refs[L0] - 1] = s->ref; + } + if (sh->collocated_list == list_idx && sh->collocated_ref_idx < rpl->nb_refs) s->ref->collocated_ref = rpl->ref[sh->collocated_ref_idx]; @@ -541,5 +556,9 @@ int ff_hevc_frame_nb_refs(const HEVCContext *s) for (i = 0; i < long_rps->nb_refs; i++) ret += !!long_rps->used[i]; } + + if (s->ps.pps->pps_curr_pic_ref_enabled_flag) + ret++; + return ret; } diff --git a/libavcodec/hevcdec.c b/libavcodec/hevcdec.c index 52fa6271336..121ceb4e751 100644 --- a/libavcodec/hevcdec.c +++ b/libavcodec/hevcdec.c @@ -668,7 +668,8 @@ static int hls_slice_header(HEVCContext *s) sh->slice_type); return AVERROR_INVALIDDATA; } - if (IS_IRAP(s) && sh->slice_type != HEVC_SLICE_I) { + if (IS_IRAP(s) && sh->slice_type != HEVC_SLICE_I && + !s->ps.pps->pps_curr_pic_ref_enabled_flag) { av_log(s->avctx, AV_LOG_ERROR, "Inter slices in an IRAP frame.\n"); return AVERROR_INVALIDDATA; } @@ -3123,6 +3124,13 @@ static int decode_nal_unit(HEVCContext *s, const H2645NAL *nal) if (ret < 0) goto fail; } else { + if (s->avctx->profile == FF_PROFILE_HEVC_SCC) { + av_log(s->avctx, AV_LOG_ERROR, + "SCC profile is not yet implemented in hevc native decoder.\n"); + ret = AVERROR_PATCHWELCOME; + goto fail; + } + if (s->threads_number > 1 && s->sh.num_entry_point_offsets > 0) ctb_addr_ts = hls_slice_data_wpp(s, nal); else From 7373bb24f76f6e2b85a18ea4ffb395bd38e148a8 Mon Sep 17 00:00:00 2001 From: Linjie Fu Date: Thu, 16 Feb 2023 13:46:34 +0800 Subject: [PATCH 0328/2172] lavc/vaapi_hevc: Pass SCC parameters Through VA-API Including sps/pps/slice parameters. Signed-off-by: Linjie Fu Signed-off-by: Fei Wang --- libavcodec/vaapi_hevc.c | 57 +++++++++++++++++++++++++++++++++++++---- 1 file changed, 52 insertions(+), 5 deletions(-) diff --git a/libavcodec/vaapi_hevc.c b/libavcodec/vaapi_hevc.c index 20fb36adfa8..a7b541750cf 100644 --- a/libavcodec/vaapi_hevc.c +++ b/libavcodec/vaapi_hevc.c @@ -126,6 +126,10 @@ static int vaapi_hevc_start_frame(AVCodecContext *avctx, const ScalingList *scaling_list = NULL; int pic_param_size, err, i; +#if VA_CHECK_VERSION(1, 2, 0) + int num_comps, pre_palette_size; +#endif + VAPictureParameterBufferHEVC *pic_param = (VAPictureParameterBufferHEVC *)&pic->pic_param; pic->pic.output_surface = ff_vaapi_get_surface_id(h->ref->frame); @@ -218,7 +222,8 @@ static int vaapi_hevc_start_frame(AVCodecContext *avctx, } #if VA_CHECK_VERSION(1, 2, 0) - if (avctx->profile == FF_PROFILE_HEVC_REXT) { + if (avctx->profile == FF_PROFILE_HEVC_REXT || + avctx->profile == FF_PROFILE_HEVC_SCC) { pic->pic_param.rext = (VAPictureParameterBufferHEVCRext) { .range_extension_pic_fields.bits = { .transform_skip_rotation_enabled_flag = sps->transform_skip_rotation_enabled_flag, @@ -245,8 +250,46 @@ static int vaapi_hevc_start_frame(AVCodecContext *avctx, for (i = 0; i < 6; i++) pic->pic_param.rext.cr_qp_offset_list[i] = pps->cr_qp_offset_list[i]; } + + pre_palette_size = pps->pps_palette_predictor_initializers_present_flag ? + pps->pps_num_palette_predictor_initializers : + (sps->sps_palette_predictor_initializers_present_flag ? + sps->sps_num_palette_predictor_initializers_minus1 + 1 : + 0); + + if (avctx->profile == FF_PROFILE_HEVC_SCC) { + pic->pic_param.scc = (VAPictureParameterBufferHEVCScc) { + .screen_content_pic_fields.bits = { + .pps_curr_pic_ref_enabled_flag = pps->pps_curr_pic_ref_enabled_flag, + .palette_mode_enabled_flag = sps->palette_mode_enabled_flag, + .motion_vector_resolution_control_idc = sps->motion_vector_resolution_control_idc, + .intra_boundary_filtering_disabled_flag = sps->intra_boundary_filtering_disabled_flag, + .residual_adaptive_colour_transform_enabled_flag + = pps->residual_adaptive_colour_transform_enabled_flag, + .pps_slice_act_qp_offsets_present_flag = pps->pps_slice_act_qp_offsets_present_flag, + }, + .palette_max_size = sps->palette_max_size, + .delta_palette_max_predictor_size = sps->delta_palette_max_predictor_size, + .predictor_palette_size = pre_palette_size, + .pps_act_y_qp_offset_plus5 = pps->residual_adaptive_colour_transform_enabled_flag ? + pps->pps_act_y_qp_offset + 5 : 0, + .pps_act_cb_qp_offset_plus5 = pps->residual_adaptive_colour_transform_enabled_flag ? + pps->pps_act_cb_qp_offset + 5 : 0, + .pps_act_cr_qp_offset_plus3 = pps->residual_adaptive_colour_transform_enabled_flag ? + pps->pps_act_cr_qp_offset + 3 : 0, + }; + + num_comps = pps->monochrome_palette_flag ? 1 : 3; + for (int comp = 0; comp < num_comps; comp++) + for (int j = 0; j < pre_palette_size; j++) + pic->pic_param.scc.predictor_palette_entries[comp][j] = + pps->pps_palette_predictor_initializers_present_flag ? + pps->pps_palette_predictor_initializer[comp][j]: + sps->sps_palette_predictor_initializer[comp][j]; + } + #endif - pic_param_size = avctx->profile == FF_PROFILE_HEVC_REXT ? + pic_param_size = avctx->profile >= FF_PROFILE_HEVC_REXT ? sizeof(pic->pic_param) : sizeof(VAPictureParameterBufferHEVC); err = ff_vaapi_decode_make_param_buffer(avctx, &pic->pic, @@ -299,7 +342,7 @@ static int vaapi_hevc_end_frame(AVCodecContext *avctx) VASliceParameterBufferHEVC *last_slice_param = (VASliceParameterBufferHEVC *)&pic->last_slice_param; int ret; - int slice_param_size = avctx->profile == FF_PROFILE_HEVC_REXT ? + int slice_param_size = avctx->profile >= FF_PROFILE_HEVC_REXT ? sizeof(pic->last_slice_param) : sizeof(VASliceParameterBufferHEVC); if (pic->last_size) { @@ -413,7 +456,7 @@ static int vaapi_hevc_decode_slice(AVCodecContext *avctx, VAAPIDecodePictureHEVC *pic = h->ref->hwaccel_picture_private; VASliceParameterBufferHEVC *last_slice_param = (VASliceParameterBufferHEVC *)&pic->last_slice_param; - int slice_param_size = avctx->profile == FF_PROFILE_HEVC_REXT ? + int slice_param_size = avctx->profile >= FF_PROFILE_HEVC_REXT ? sizeof(pic->last_slice_param) : sizeof(VASliceParameterBufferHEVC); int nb_list = (sh->slice_type == HEVC_SLICE_B) ? @@ -478,11 +521,15 @@ static int vaapi_hevc_decode_slice(AVCodecContext *avctx, fill_pred_weight_table(avctx, h, sh, last_slice_param); #if VA_CHECK_VERSION(1, 2, 0) - if (avctx->profile == FF_PROFILE_HEVC_REXT) { + if (avctx->profile >= FF_PROFILE_HEVC_REXT) { pic->last_slice_param.rext = (VASliceParameterBufferHEVCRext) { .slice_ext_flags.bits = { .cu_chroma_qp_offset_enabled_flag = sh->cu_chroma_qp_offset_enabled_flag, + .use_integer_mv_flag = sh->use_integer_mv_flag, }, + .slice_act_y_qp_offset = sh->slice_act_y_qp_offset, + .slice_act_cb_qp_offset = sh->slice_act_cb_qp_offset, + .slice_act_cr_qp_offset = sh->slice_act_cr_qp_offset, }; for (i = 0; i < 15 && i < sh->nb_refs[L0]; i++) { pic->last_slice_param.rext.luma_offset_l0[i] = sh->luma_offset_l0[i]; From fb1998f508598d02b8547ae4eadfc6649d4e476d Mon Sep 17 00:00:00 2001 From: Linjie Fu Date: Thu, 16 Feb 2023 13:46:35 +0800 Subject: [PATCH 0329/2172] lavc/vaapi_hevc: Add vaapi profile parse support for SCC Note that Screen-Extended Main 4:4:4 and 4:4:4 10 supports chroma_format_idc from 0, 1 or 3, hence both 420 and 444 are supported. Signed-off-by: Linjie Fu Signed-off-by: Fei Wang --- libavcodec/vaapi_decode.c | 4 +++- libavcodec/vaapi_hevc.c | 14 ++++++++++++-- libavcodec/vaapi_hevc.h | 2 +- 3 files changed, 16 insertions(+), 4 deletions(-) diff --git a/libavcodec/vaapi_decode.c b/libavcodec/vaapi_decode.c index 134f10eca5f..ab8c12e3642 100644 --- a/libavcodec/vaapi_decode.c +++ b/libavcodec/vaapi_decode.c @@ -410,7 +410,9 @@ static const struct { #endif #if VA_CHECK_VERSION(1, 2, 0) && CONFIG_HEVC_VAAPI_HWACCEL MAP(HEVC, HEVC_REXT, None, - ff_vaapi_parse_hevc_rext_profile ), + ff_vaapi_parse_hevc_rext_scc_profile ), + MAP(HEVC, HEVC_SCC, None, + ff_vaapi_parse_hevc_rext_scc_profile ), #endif MAP(MJPEG, MJPEG_HUFFMAN_BASELINE_DCT, JPEGBaseline), diff --git a/libavcodec/vaapi_hevc.c b/libavcodec/vaapi_hevc.c index a7b541750cf..1cf43bd4dc9 100644 --- a/libavcodec/vaapi_hevc.c +++ b/libavcodec/vaapi_hevc.c @@ -591,9 +591,9 @@ static int ptl_convert(const PTLCommon *general_ptl, H265RawProfileTierLevel *h2 } /* - * Find exact va_profile for HEVC Range Extension + * Find exact va_profile for HEVC Range Extension and Screen Content Coding Extension */ -VAProfile ff_vaapi_parse_hevc_rext_profile(AVCodecContext *avctx) +VAProfile ff_vaapi_parse_hevc_rext_scc_profile(AVCodecContext *avctx) { const HEVCContext *h = avctx->priv_data; const HEVCSPS *sps = h->ps.sps; @@ -632,6 +632,16 @@ VAProfile ff_vaapi_parse_hevc_rext_profile(AVCodecContext *avctx) else if (!strcmp(profile->name, "Main 4:4:4 12") || !strcmp(profile->name, "Main 4:4:4 12 Intra")) return VAProfileHEVCMain444_12; + else if (!strcmp(profile->name, "Screen-Extended Main")) + return VAProfileHEVCSccMain; + else if (!strcmp(profile->name, "Screen-Extended Main 10")) + return VAProfileHEVCSccMain10; + else if (!strcmp(profile->name, "Screen-Extended Main 4:4:4")) + return VAProfileHEVCSccMain444; +#if VA_CHECK_VERSION(1, 8, 0) + else if (!strcmp(profile->name, "Screen-Extended Main 4:4:4 10")) + return VAProfileHEVCSccMain444_10; +#endif #else av_log(avctx, AV_LOG_WARNING, "HEVC profile %s is " "not supported with this VA version.\n", profile->name); diff --git a/libavcodec/vaapi_hevc.h b/libavcodec/vaapi_hevc.h index b3b0e6fc1e9..449635d0d70 100644 --- a/libavcodec/vaapi_hevc.h +++ b/libavcodec/vaapi_hevc.h @@ -22,6 +22,6 @@ #include #include "avcodec.h" -VAProfile ff_vaapi_parse_hevc_rext_profile(AVCodecContext *avctx); +VAProfile ff_vaapi_parse_hevc_rext_scc_profile(AVCodecContext *avctx); #endif /* AVCODEC_VAAPI_HEVC_H */ From b7104243ff134f243c1916e7cfea702a6cf5bc54 Mon Sep 17 00:00:00 2001 From: Linjie Fu Date: Thu, 16 Feb 2023 13:46:36 +0800 Subject: [PATCH 0330/2172] lavc/vaapi_hevc: Set correct rps type for scc According to 8.1.3 and 8.3.2. Signed-off-by: Linjie Fu Signed-off-by: Fei Wang --- libavcodec/vaapi_hevc.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/libavcodec/vaapi_hevc.c b/libavcodec/vaapi_hevc.c index 1cf43bd4dc9..a06785f7a60 100644 --- a/libavcodec/vaapi_hevc.c +++ b/libavcodec/vaapi_hevc.c @@ -71,6 +71,7 @@ static void fill_vaapi_pic(VAPictureHEVC *va_pic, const HEVCFrame *pic, int rps_ static int find_frame_rps_type(const HEVCContext *h, const HEVCFrame *pic) { VASurfaceID pic_surf = ff_vaapi_get_surface_id(pic->frame); + const HEVCFrame *current_picture = h->ref; int i; for (i = 0; i < h->rps[ST_CURR_BEF].nb_refs; i++) { @@ -88,6 +89,9 @@ static int find_frame_rps_type(const HEVCContext *h, const HEVCFrame *pic) return VA_PICTURE_HEVC_RPS_LT_CURR; } + if (h->ps.pps->pps_curr_pic_ref_enabled_flag && current_picture->poc == pic->poc) + return VA_PICTURE_HEVC_LONG_TERM_REFERENCE; + return 0; } From 6489e0679d0b073dabf0e5b5c8ed5418cdeeea44 Mon Sep 17 00:00:00 2001 From: Linjie Fu Date: Thu, 16 Feb 2023 13:46:37 +0800 Subject: [PATCH 0331/2172] lavc/vaapi_hevc: Loose the restricts for SCC decoding Allow current picture as the reference picture. Signed-off-by: Linjie Fu Signed-off-by: Fei Wang --- libavcodec/vaapi_hevc.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libavcodec/vaapi_hevc.c b/libavcodec/vaapi_hevc.c index a06785f7a60..0e5da15e53e 100644 --- a/libavcodec/vaapi_hevc.c +++ b/libavcodec/vaapi_hevc.c @@ -104,7 +104,8 @@ static void fill_vaapi_reference_frames(const HEVCContext *h, VAPictureParameter const HEVCFrame *frame = NULL; while (!frame && j < FF_ARRAY_ELEMS(h->DPB)) { - if (&h->DPB[j] != current_picture && (h->DPB[j].flags & (HEVC_FRAME_FLAG_LONG_REF | HEVC_FRAME_FLAG_SHORT_REF))) + if ((&h->DPB[j] != current_picture || h->ps.pps->pps_curr_pic_ref_enabled_flag) && + (h->DPB[j].flags & (HEVC_FRAME_FLAG_LONG_REF | HEVC_FRAME_FLAG_SHORT_REF))) frame = &h->DPB[j]; j++; } From 0825b461e64b5924fdee7055643db65870d2eaae Mon Sep 17 00:00:00 2001 From: Wenbin Chen Date: Fri, 9 Dec 2022 14:36:23 +0800 Subject: [PATCH 0332/2172] libavcodec/qsvenc: Enable 444 encoding for RGB input MSDK/VPL uses 420 chroma format as default to encode RGB, and this is not a proper usage. Now enable 444 encoding for RGB input by default. When main profile is used, RGB input is still encoded in 420 format. Signed-off-by: Wenbin Chen --- libavcodec/qsvenc.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/libavcodec/qsvenc.c b/libavcodec/qsvenc.c index fc64a086e49..3607859cb85 100644 --- a/libavcodec/qsvenc.c +++ b/libavcodec/qsvenc.c @@ -1118,6 +1118,10 @@ static int init_video_param(AVCodecContext *avctx, QSVEncContext *q) q->extco3.MaxFrameSizeI = q->max_frame_size_i; if (q->max_frame_size_p >= 0) q->extco3.MaxFrameSizeP = q->max_frame_size_p; + if (sw_format == AV_PIX_FMT_BGRA && + (q->profile == MFX_PROFILE_HEVC_REXT || + q->profile == MFX_PROFILE_UNKNOWN)) + q->extco3.TargetChromaFormatPlus1 = MFX_CHROMAFORMAT_YUV444 + 1; q->extco3.ScenarioInfo = q->scenario; } else if (avctx->codec_id == AV_CODEC_ID_AV1) { From 15992a040dd017d6897131373321522fe2867a6d Mon Sep 17 00:00:00 2001 From: Fei Wang Date: Fri, 24 Feb 2023 13:45:49 +0800 Subject: [PATCH 0333/2172] lavu/hwcontext_vaapi: sync surface before export its DRM handle According to description of vaExportSurfaceHandle in libva, vaSyncSurface must be called if the contents of the surface will be read. Fixes ticket #9967. Reviewed-by: Zhao Zhili Signed-off-by: Fei Wang --- libavutil/hwcontext_vaapi.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/libavutil/hwcontext_vaapi.c b/libavutil/hwcontext_vaapi.c index 938bd5447d5..90c2c191d90 100644 --- a/libavutil/hwcontext_vaapi.c +++ b/libavutil/hwcontext_vaapi.c @@ -1319,8 +1319,17 @@ static int vaapi_map_to_drm_esh(AVHWFramesContext *hwfc, AVFrame *dst, surface_id = (VASurfaceID)(uintptr_t)src->data[3]; export_flags = VA_EXPORT_SURFACE_SEPARATE_LAYERS; - if (flags & AV_HWFRAME_MAP_READ) + if (flags & AV_HWFRAME_MAP_READ) { export_flags |= VA_EXPORT_SURFACE_READ_ONLY; + + vas = vaSyncSurface(hwctx->display, surface_id); + if (vas != VA_STATUS_SUCCESS) { + av_log(hwfc, AV_LOG_ERROR, "Failed to sync surface " + "%#x: %d (%s).\n", surface_id, vas, vaErrorStr(vas)); + return AVERROR(EIO); + } + } + if (flags & AV_HWFRAME_MAP_WRITE) export_flags |= VA_EXPORT_SURFACE_WRITE_ONLY; From 891ed24f77da99c6d41bb7c116ba5925e3206ce2 Mon Sep 17 00:00:00 2001 From: Steven Liu Date: Fri, 9 Dec 2022 12:37:36 +0800 Subject: [PATCH 0334/2172] avformat/hlsenc: hls_init_time should used in living stream mode When hls_init_time should available when hls_list_size > 0. Because the list will not refresh new top line segment when hls_list_size is 0 Signed-off-by: Steven Liu --- libavformat/hlsenc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavformat/hlsenc.c b/libavformat/hlsenc.c index e1f96feda3e..871afb571be 100644 --- a/libavformat/hlsenc.c +++ b/libavformat/hlsenc.c @@ -2947,7 +2947,7 @@ static int hls_init(AVFormatContext *s) av_log(hls, AV_LOG_DEBUG, "start_number evaluated to %"PRId64"\n", hls->start_sequence); } - hls->recording_time = hls->init_time ? hls->init_time : hls->time; + hls->recording_time = hls->init_time && hls->max_nb_segments > 0 ? hls->init_time : hls->time; if (hls->flags & HLS_SPLIT_BY_TIME && hls->flags & HLS_INDEPENDENT_SEGMENTS) { // Independent segments cannot be guaranteed when splitting by time From ec7fa13eb0f8567b4fb5096dc8efc364fe87dcb2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Storsj=C3=B6?= Date: Wed, 22 Feb 2023 15:51:27 +0200 Subject: [PATCH 0335/2172] aarch64: hevcdsp_idct: Reuse preexisting macros for transposes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Martin Storsjö --- libavcodec/aarch64/hevcdsp_idct_neon.S | 16 +++------------- 1 file changed, 3 insertions(+), 13 deletions(-) diff --git a/libavcodec/aarch64/hevcdsp_idct_neon.S b/libavcodec/aarch64/hevcdsp_idct_neon.S index 124c50998a7..c61fcb175d7 100644 --- a/libavcodec/aarch64/hevcdsp_idct_neon.S +++ b/libavcodec/aarch64/hevcdsp_idct_neon.S @@ -25,6 +25,7 @@ */ #include "libavutil/aarch64/asm.S" +#include "neon.S" const trans, align=4 .short 64, 83, 64, 36 @@ -279,20 +280,9 @@ endfunc sub \out3, v28.4s, v30.4s .endm -.macro transpose8_4x4 r0, r1, r2, r3 - trn1 v2.8h, \r0\().8h, \r1\().8h - trn2 v3.8h, \r0\().8h, \r1\().8h - trn1 v4.8h, \r2\().8h, \r3\().8h - trn2 v5.8h, \r2\().8h, \r3\().8h - trn1 \r0\().4s, v2.4s, v4.4s - trn2 \r2\().4s, v2.4s, v4.4s - trn1 \r1\().4s, v3.4s, v5.4s - trn2 \r3\().4s, v3.4s, v5.4s -.endm - .macro transpose_8x8 r0, r1, r2, r3, r4, r5, r6, r7 - transpose8_4x4 \r0, \r1, \r2, \r3 - transpose8_4x4 \r4, \r5, \r6, \r7 + transpose_4x8H \r0, \r1, \r2, \r3, v2, v3, v4, v5 + transpose_4x8H \r4, \r5, \r6, \r7, v2, v3, v4, v5 .endm .macro tr_8x4 shift, in0,in0t, in1,in1t, in2,in2t, in3,in3t, in4,in4t, in5,in5t, in6,in6t, in7,in7t, p1, p2 From 4b4de07721ed734fea7ec1058ccdc4cc11f3d2da Mon Sep 17 00:00:00 2001 From: xufuji456 <839789740@qq.com> Date: Fri, 24 Feb 2023 15:43:13 +0800 Subject: [PATCH 0336/2172] libavcodec/hevc: add hevc idct4x4 neon of aarch64 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Martin Storsjö --- libavcodec/aarch64/hevcdsp_idct_neon.S | 40 +++++++++++++++++++++++ libavcodec/aarch64/hevcdsp_init_aarch64.c | 4 +++ 2 files changed, 44 insertions(+) diff --git a/libavcodec/aarch64/hevcdsp_idct_neon.S b/libavcodec/aarch64/hevcdsp_idct_neon.S index c61fcb175d7..467cb0f48a6 100644 --- a/libavcodec/aarch64/hevcdsp_idct_neon.S +++ b/libavcodec/aarch64/hevcdsp_idct_neon.S @@ -246,6 +246,43 @@ function hevc_add_residual_32x32_16_neon, export=0 ret endfunc +.macro tr_4x4 in0, in1, in2, in3, out0, out1, out2, out3, shift + sshll v20.4s, \in0, #6 + sshll v21.4s, \in0, #6 + smull v22.4s, \in1, v4.h[1] + smull v23.4s, \in1, v4.h[3] + smlal v20.4s, \in2, v4.h[0] //e0 + smlsl v21.4s, \in2, v4.h[0] //e1 + smlal v22.4s, \in3, v4.h[3] //o0 + smlsl v23.4s, \in3, v4.h[1] //o1 + + add v24.4s, v20.4s, v22.4s + sub v20.4s, v20.4s, v22.4s + add v22.4s, v21.4s, v23.4s + sub v21.4s, v21.4s, v23.4s + sqrshrn \out0, v24.4s, #\shift + sqrshrn \out3, v20.4s, #\shift + sqrshrn \out1, v22.4s, #\shift + sqrshrn \out2, v21.4s, #\shift +.endm + +.macro idct_4x4 bitdepth +function ff_hevc_idct_4x4_\bitdepth\()_neon, export=1 + ld1 {v0.4h-v3.4h}, [x0] + + movrel x1, trans + ld1 {v4.4h}, [x1] + + tr_4x4 v0.4h, v1.4h, v2.4h, v3.4h, v16.4h, v17.4h, v18.4h, v19.4h, 7 + transpose_4x8H v16, v17, v18, v19, v26, v27, v28, v29 + + tr_4x4 v16.4h, v17.4h, v18.4h, v19.4h, v0.4h, v1.4h, v2.4h, v3.4h, 20 - \bitdepth + transpose_4x8H v0, v1, v2, v3, v26, v27, v28, v29 + st1 {v0.4h-v3.4h}, [x0] + ret +endfunc +.endm + .macro sum_sub out, in, c, op, p .ifc \op, + smlal\p \out, \in, \c @@ -568,6 +605,9 @@ function ff_hevc_idct_16x16_\bitdepth\()_neon, export=1 endfunc .endm +idct_4x4 8 +idct_4x4 10 + idct_8x8 8 idct_8x8 10 diff --git a/libavcodec/aarch64/hevcdsp_init_aarch64.c b/libavcodec/aarch64/hevcdsp_init_aarch64.c index 88a797f3931..1deefca0a25 100644 --- a/libavcodec/aarch64/hevcdsp_init_aarch64.c +++ b/libavcodec/aarch64/hevcdsp_init_aarch64.c @@ -49,6 +49,8 @@ void ff_hevc_add_residual_32x32_10_neon(uint8_t *_dst, const int16_t *coeffs, ptrdiff_t stride); void ff_hevc_add_residual_32x32_12_neon(uint8_t *_dst, const int16_t *coeffs, ptrdiff_t stride); +void ff_hevc_idct_4x4_8_neon(int16_t *coeffs, int col_limit); +void ff_hevc_idct_4x4_10_neon(int16_t *coeffs, int col_limit); void ff_hevc_idct_8x8_8_neon(int16_t *coeffs, int col_limit); void ff_hevc_idct_8x8_10_neon(int16_t *coeffs, int col_limit); void ff_hevc_idct_16x16_8_neon(int16_t *coeffs, int col_limit); @@ -119,6 +121,7 @@ av_cold void ff_hevc_dsp_init_aarch64(HEVCDSPContext *c, const int bit_depth) c->add_residual[1] = ff_hevc_add_residual_8x8_8_neon; c->add_residual[2] = ff_hevc_add_residual_16x16_8_neon; c->add_residual[3] = ff_hevc_add_residual_32x32_8_neon; + c->idct[0] = ff_hevc_idct_4x4_8_neon; c->idct[1] = ff_hevc_idct_8x8_8_neon; c->idct[2] = ff_hevc_idct_16x16_8_neon; c->idct_dc[0] = ff_hevc_idct_4x4_dc_8_neon; @@ -168,6 +171,7 @@ av_cold void ff_hevc_dsp_init_aarch64(HEVCDSPContext *c, const int bit_depth) c->add_residual[1] = ff_hevc_add_residual_8x8_10_neon; c->add_residual[2] = ff_hevc_add_residual_16x16_10_neon; c->add_residual[3] = ff_hevc_add_residual_32x32_10_neon; + c->idct[0] = ff_hevc_idct_4x4_10_neon; c->idct[1] = ff_hevc_idct_8x8_10_neon; c->idct[2] = ff_hevc_idct_16x16_10_neon; c->idct_dc[0] = ff_hevc_idct_4x4_dc_10_neon; From 05438db02437e241a418e266a354bf4e7be7ac59 Mon Sep 17 00:00:00 2001 From: xufuji456 <839789740@qq.com> Date: Fri, 24 Feb 2023 20:31:29 +0800 Subject: [PATCH 0337/2172] libavcodec/hevc: reuse scale_store on idct32x32_neon MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Martin Storsjö --- libavcodec/arm/hevcdsp_idct_neon.S | 18 ++---------------- 1 file changed, 2 insertions(+), 16 deletions(-) diff --git a/libavcodec/arm/hevcdsp_idct_neon.S b/libavcodec/arm/hevcdsp_idct_neon.S index 75795e6a6ae..41ca3b83a8b 100644 --- a/libavcodec/arm/hevcdsp_idct_neon.S +++ b/libavcodec/arm/hevcdsp_idct_neon.S @@ -876,28 +876,14 @@ function func_tr_32x4_\name movrel r9, trans + 32 vld1.s16 {q0}, [r9, :128]! vld1.s16 {q1}, [r9, :128] - - bl tr_block1 - add r4, sp, #2048 - vld1.s16 {q14-q15}, [r4, :128]! - butterfly32 q14, q10, q15, q11 - scale32 d22, d23, d20, d21, q1, q14, q10, q15, \shift - - vld1.s16 {q14-q15}, [r4, :128]! - butterfly32 q14, q12, q15, q13 - scale32 d2, d3, d28, d29, q1, q14, q12, q15, \shift - transpose8_4x4 d22, d20, d2, d28 - transpose8_4x4 d29, d3, d21, d23 + bl tr_block1 mov r1, r11 mov r2, #64 mov r8, #-64 add r3, r11, #(56 + 3 * 64) - store16 d22, d23, d20, d21, d2, d3, d28, d29, r8 - - @ reload multiplication coefficiens to q1 - vld1.s16 {q1}, [r9, :128] + scale_store \shift bl tr_block2 add r1, r11, #8 From 67fd1b79e727d61b71e357dcaddabdf02b0b4c4b Mon Sep 17 00:00:00 2001 From: xufuji456 <839789740@qq.com> Date: Tue, 28 Feb 2023 20:51:51 +0800 Subject: [PATCH 0338/2172] libavcodec/hevc: remove duplicate semicolon in hevcdsp_init_neon MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Martin Storsjö --- libavcodec/arm/hevcdsp_init_neon.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libavcodec/arm/hevcdsp_init_neon.c b/libavcodec/arm/hevcdsp_init_neon.c index 8094e6c62e2..1f26fc64541 100644 --- a/libavcodec/arm/hevcdsp_init_neon.c +++ b/libavcodec/arm/hevcdsp_init_neon.c @@ -119,7 +119,7 @@ QPEL_FUNC(ff_hevc_put_qpel_h3v3_neon_8); #define QPEL_FUNC_UW_PIX(name) \ void name(uint8_t *dst, ptrdiff_t dststride, const uint8_t *_src, ptrdiff_t _srcstride, \ - int height, intptr_t mx, intptr_t my, int width); + int height, intptr_t mx, intptr_t my, int width) QPEL_FUNC_UW_PIX(ff_hevc_put_qpel_uw_pixels_w4_neon_8); QPEL_FUNC_UW_PIX(ff_hevc_put_qpel_uw_pixels_w8_neon_8); QPEL_FUNC_UW_PIX(ff_hevc_put_qpel_uw_pixels_w16_neon_8); @@ -131,7 +131,7 @@ QPEL_FUNC_UW_PIX(ff_hevc_put_qpel_uw_pixels_w64_neon_8); #define QPEL_FUNC_UW(name) \ void name(uint8_t *dst, ptrdiff_t dststride, const uint8_t *_src, ptrdiff_t _srcstride, \ - int width, int height, const int16_t* src2, ptrdiff_t src2stride); + int width, int height, const int16_t* src2, ptrdiff_t src2stride) QPEL_FUNC_UW(ff_hevc_put_qpel_uw_pixels_neon_8); QPEL_FUNC_UW(ff_hevc_put_qpel_uw_v1_neon_8); QPEL_FUNC_UW(ff_hevc_put_qpel_uw_v2_neon_8); From 21101d9eb1f26c1f1a58454919a9ef5993ae9900 Mon Sep 17 00:00:00 2001 From: Zhao Zhili Date: Tue, 28 Feb 2023 19:12:17 +0100 Subject: [PATCH 0339/2172] avcodec/nvenc: fix potential NULL pointer dereference Signed-off-by: Timo Rothenpieler --- libavcodec/nvenc.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/libavcodec/nvenc.c b/libavcodec/nvenc.c index 8a284540422..a8b7a4c0a0b 100644 --- a/libavcodec/nvenc.c +++ b/libavcodec/nvenc.c @@ -178,6 +178,8 @@ static void reorder_queue_flush(AVFifo *queue) { FrameData fd; + av_assert0(queue); + while (av_fifo_read(queue, &fd, 1) >= 0) av_buffer_unref(&fd.frame_opaque_ref); } @@ -1853,8 +1855,11 @@ av_cold int ff_nvenc_encode_close(AVCodecContext *avctx) p_nvenc->nvEncEncodePicture(ctx->nvencoder, ¶ms); } - reorder_queue_flush(ctx->reorder_queue); - av_fifo_freep2(&ctx->reorder_queue); + if (ctx->reorder_queue) { + reorder_queue_flush(ctx->reorder_queue); + av_fifo_freep2(&ctx->reorder_queue); + } + av_fifo_freep2(&ctx->output_surface_ready_queue); av_fifo_freep2(&ctx->output_surface_queue); av_fifo_freep2(&ctx->unused_surface_queue); From fadfa147f812a3fe9e68723347d37b9cccd6222d Mon Sep 17 00:00:00 2001 From: Leo Izen Date: Thu, 2 Feb 2023 10:01:42 -0500 Subject: [PATCH 0340/2172] avcodec/pngdec: read colorspace info when decoding with AVDISCARD_ALL These chunks are lightweight and it's useful information to have when running ffmpeg -i or ffprobe, for example. --- libavcodec/pngdec.c | 136 ++++++++++++++++++++++------------- tests/ref/fate/png-icc | 8 +-- tests/ref/fate/png-side-data | 2 +- 3 files changed, 91 insertions(+), 55 deletions(-) diff --git a/libavcodec/pngdec.c b/libavcodec/pngdec.c index d63640345bc..9403d72f2f4 100644 --- a/libavcodec/pngdec.c +++ b/libavcodec/pngdec.c @@ -75,6 +75,7 @@ typedef struct PNGDecContext { int have_chrm; uint32_t white_point[2]; uint32_t display_primaries[3][2]; + int gamma; int have_srgb; int have_cicp; enum AVColorPrimaries cicp_primaries; @@ -641,6 +642,83 @@ static int decode_phys_chunk(AVCodecContext *avctx, PNGDecContext *s, return 0; } +/* + * This populates AVCodecContext fields so it must be called before + * ff_thread_finish_setup() to avoid a race condition with respect to the + * generic copying of avctx fields. + */ +static int populate_avctx_color_fields(AVCodecContext *avctx, AVFrame *frame) +{ + PNGDecContext *s = avctx->priv_data; + + if (s->have_cicp) { + if (s->cicp_primaries >= AVCOL_PRI_NB) + av_log(avctx, AV_LOG_WARNING, "unrecognized cICP primaries\n"); + else + avctx->color_primaries = frame->color_primaries = s->cicp_primaries; + if (s->cicp_trc >= AVCOL_TRC_NB) + av_log(avctx, AV_LOG_WARNING, "unrecognized cICP transfer\n"); + else + avctx->color_trc = frame->color_trc = s->cicp_trc; + if (s->cicp_range == 0) + av_log(avctx, AV_LOG_WARNING, "unsupported tv-range cICP chunk\n"); + } else if (s->iccp_data) { + AVFrameSideData *sd = av_frame_new_side_data(frame, AV_FRAME_DATA_ICC_PROFILE, s->iccp_data_len); + if (!sd) + return AVERROR(ENOMEM); + memcpy(sd->data, s->iccp_data, s->iccp_data_len); + av_dict_set(&sd->metadata, "name", s->iccp_name, 0); + } else if (s->have_srgb) { + avctx->color_primaries = frame->color_primaries = AVCOL_PRI_BT709; + avctx->color_trc = frame->color_trc = AVCOL_TRC_IEC61966_2_1; + } else if (s->have_chrm) { + AVColorPrimariesDesc desc; + enum AVColorPrimaries prim; + desc.wp.x = av_make_q(s->white_point[0], 100000); + desc.wp.y = av_make_q(s->white_point[1], 100000); + desc.prim.r.x = av_make_q(s->display_primaries[0][0], 100000); + desc.prim.r.y = av_make_q(s->display_primaries[0][1], 100000); + desc.prim.g.x = av_make_q(s->display_primaries[1][0], 100000); + desc.prim.g.y = av_make_q(s->display_primaries[1][1], 100000); + desc.prim.b.x = av_make_q(s->display_primaries[2][0], 100000); + desc.prim.b.y = av_make_q(s->display_primaries[2][1], 100000); + prim = av_csp_primaries_id_from_desc(&desc); + if (prim != AVCOL_PRI_UNSPECIFIED) + avctx->color_primaries = frame->color_primaries = prim; + else + av_log(avctx, AV_LOG_WARNING, "unknown cHRM primaries\n"); + } + + /* these chunks override gAMA */ + if (s->iccp_data || s->have_srgb || s->have_cicp) { + av_dict_set(&s->frame_metadata, "gamma", NULL, 0); + } else if (s->gamma) { + /* + * These values are 100000/2.2, 100000/2.8, 100000/2.6, and + * 100000/1.0 respectively. 45455, 35714, and 38462, and 100000. + * There's a 0.001 gamma tolerance here in case of floating + * point issues when the PNG was written. + * + * None of the other enums have a pure gamma curve so it makes + * sense to leave those to sRGB and cICP. + */ + if (s->gamma > 45355 && s->gamma < 45555) + avctx->color_trc = frame->color_trc = AVCOL_TRC_GAMMA22; + else if (s->gamma > 35614 && s->gamma < 35814) + avctx->color_trc = frame->color_trc = AVCOL_TRC_GAMMA28; + else if (s->gamma > 38362 && s->gamma < 38562) + avctx->color_trc = frame->color_trc = AVCOL_TRC_SMPTE428; + else if (s->gamma > 99900 && s->gamma < 100100) + avctx->color_trc = frame->color_trc = AVCOL_TRC_LINEAR; + } + + /* we only support pc-range RGB */ + avctx->colorspace = frame->colorspace = AVCOL_SPC_RGB; + avctx->color_range = frame->color_range = AVCOL_RANGE_JPEG; + + return 0; +} + static int decode_idat_chunk(AVCodecContext *avctx, PNGDecContext *s, GetByteContext *gb, AVFrame *p) { @@ -756,6 +834,8 @@ static int decode_idat_chunk(AVCodecContext *avctx, PNGDecContext *s, p->key_frame = 1; p->interlaced_frame = !!s->interlace_type; + if ((ret = populate_avctx_color_fields(avctx, p)) < 0) + return ret; ff_thread_finish_setup(avctx); /* compute the compressed row size */ @@ -1257,6 +1337,10 @@ static int decode_frame_common(AVCodecContext *avctx, PNGDecContext *s, case MKTAG('t', 'E', 'X', 't'): case MKTAG('I', 'D', 'A', 'T'): case MKTAG('t', 'R', 'N', 'S'): + case MKTAG('s', 'R', 'G', 'B'): + case MKTAG('c', 'I', 'C', 'P'): + case MKTAG('c', 'H', 'R', 'M'): + case MKTAG('g', 'A', 'M', 'A'): break; default: continue; @@ -1359,10 +1443,10 @@ static int decode_frame_common(AVCodecContext *avctx, PNGDecContext *s, case MKTAG('g', 'A', 'M', 'A'): { AVBPrint bp; char *gamma_str; - int num = bytestream2_get_be32(&gb_chunk); + s->gamma = bytestream2_get_be32(&gb_chunk); av_bprint_init(&bp, 0, AV_BPRINT_SIZE_UNLIMITED); - av_bprintf(&bp, "%i/%i", num, 100000); + av_bprintf(&bp, "%i/%i", s->gamma, 100000); ret = av_bprint_finalize(&bp, &gamma_str); if (ret < 0) return ret; @@ -1500,56 +1584,8 @@ static void clear_frame_metadata(PNGDecContext *s) static int output_frame(PNGDecContext *s, AVFrame *f) { - AVCodecContext *avctx = s->avctx; int ret; - if (s->have_cicp) { - if (s->cicp_primaries >= AVCOL_PRI_NB) - av_log(avctx, AV_LOG_WARNING, "unrecognized cICP primaries\n"); - else - avctx->color_primaries = f->color_primaries = s->cicp_primaries; - if (s->cicp_trc >= AVCOL_TRC_NB) - av_log(avctx, AV_LOG_WARNING, "unrecognized cICP transfer\n"); - else - avctx->color_trc = f->color_trc = s->cicp_trc; - avctx->color_range = f->color_range = - s->cicp_range == 0 ? AVCOL_RANGE_MPEG : AVCOL_RANGE_JPEG; - } else if (s->iccp_data) { - AVFrameSideData *sd = av_frame_new_side_data(f, AV_FRAME_DATA_ICC_PROFILE, s->iccp_data_len); - if (!sd) { - ret = AVERROR(ENOMEM); - goto fail; - } - memcpy(sd->data, s->iccp_data, s->iccp_data_len); - - av_dict_set(&sd->metadata, "name", s->iccp_name, 0); - } else if (s->have_srgb) { - avctx->color_primaries = f->color_primaries = AVCOL_PRI_BT709; - avctx->color_trc = f->color_trc = AVCOL_TRC_IEC61966_2_1; - } else if (s->have_chrm) { - AVColorPrimariesDesc desc; - enum AVColorPrimaries prim; - desc.wp.x = av_make_q(s->white_point[0], 100000); - desc.wp.y = av_make_q(s->white_point[1], 100000); - desc.prim.r.x = av_make_q(s->display_primaries[0][0], 100000); - desc.prim.r.y = av_make_q(s->display_primaries[0][1], 100000); - desc.prim.g.x = av_make_q(s->display_primaries[1][0], 100000); - desc.prim.g.y = av_make_q(s->display_primaries[1][1], 100000); - desc.prim.b.x = av_make_q(s->display_primaries[2][0], 100000); - desc.prim.b.y = av_make_q(s->display_primaries[2][1], 100000); - prim = av_csp_primaries_id_from_desc(&desc); - if (prim != AVCOL_PRI_UNSPECIFIED) - avctx->color_primaries = f->color_primaries = prim; - else - av_log(avctx, AV_LOG_WARNING, "unknown cHRM primaries\n"); - } - - /* these chunks override gAMA */ - if (s->iccp_data || s->have_srgb || s->have_cicp) - av_dict_set(&s->frame_metadata, "gamma", NULL, 0); - - avctx->colorspace = f->colorspace = AVCOL_SPC_RGB; - if (s->stereo_mode >= 0) { AVStereo3D *stereo3d = av_stereo3d_create_side_data(f); if (!stereo3d) { diff --git a/tests/ref/fate/png-icc b/tests/ref/fate/png-icc index 14de5446394..1f4eab1fb01 100644 --- a/tests/ref/fate/png-icc +++ b/tests/ref/fate/png-icc @@ -1,5 +1,5 @@ -a50d37a0e72bddea2fcbba6fb773e2a0 *tests/data/fate/png-icc.image2 -49397 tests/data/fate/png-icc.image2 +c460cd06a88ace94d7c76a6309aa8fb8 *tests/data/fate/png-icc.image2 +49441 tests/data/fate/png-icc.image2 #tb 0: 1/25 #media_type 0: video #codec_id 0: rawvideo @@ -21,7 +21,7 @@ pkt_duration_time=0.040000 duration=1 duration_time=0.040000 pkt_pos=0 -pkt_size=49397 +pkt_size=49441 width=128 height=128 pix_fmt=rgb24 @@ -34,7 +34,7 @@ top_field_first=0 repeat_pict=0 color_range=pc color_space=gbr -color_primaries=unknown +color_primaries=bt709 color_transfer=unknown chroma_location=unspecified [SIDE_DATA] diff --git a/tests/ref/fate/png-side-data b/tests/ref/fate/png-side-data index a4c16eb3957..8f955f76bc6 100644 --- a/tests/ref/fate/png-side-data +++ b/tests/ref/fate/png-side-data @@ -26,7 +26,7 @@ top_field_first=0 repeat_pict=0 color_range=pc color_space=gbr -color_primaries=unknown +color_primaries=bt709 color_transfer=unknown chroma_location=unspecified [SIDE_DATA] From 9998c31044cb05eb9392ce2fdb2b3a281e47e0da Mon Sep 17 00:00:00 2001 From: Stefano Sabatini Date: Mon, 6 Feb 2023 01:59:02 +0100 Subject: [PATCH 0341/2172] ffmpeg_demux: show fixed timestamps in ts_fixup Help debugging. --- fftools/ffmpeg_demux.c | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/fftools/ffmpeg_demux.c b/fftools/ffmpeg_demux.c index 2033c1de54a..db05ddb8e90 100644 --- a/fftools/ffmpeg_demux.c +++ b/fftools/ffmpeg_demux.c @@ -194,15 +194,19 @@ static void ts_fixup(Demuxer *d, AVPacket *pkt, int *repeat_pict) const int64_t start_time = ifile->start_time_effective; int64_t duration; - if (debug_ts) { - av_log(ist, AV_LOG_INFO, "demuxer -> type:%s " - "pkt_pts:%s pkt_pts_time:%s pkt_dts:%s pkt_dts_time:%s duration:%s duration_time:%s\n", - av_get_media_type_string(ist->st->codecpar->codec_type), - av_ts2str(pkt->pts), av_ts2timestr(pkt->pts, &ist->st->time_base), - av_ts2str(pkt->dts), av_ts2timestr(pkt->dts, &ist->st->time_base), - av_ts2str(pkt->duration), av_ts2timestr(pkt->duration, &ist->st->time_base)); +#define SHOW_TS_DEBUG(tag_) \ + if (debug_ts) { \ + av_log(ist, AV_LOG_INFO, "%s -> ist_index:%d:%d type:%s " \ + "pkt_pts:%s pkt_pts_time:%s pkt_dts:%s pkt_dts_time:%s duration:%s duration_time:%s\n", \ + tag_, ifile->index, pkt->stream_index, \ + av_get_media_type_string(ist->st->codecpar->codec_type), \ + av_ts2str(pkt->pts), av_ts2timestr(pkt->pts, &ist->st->time_base), \ + av_ts2str(pkt->dts), av_ts2timestr(pkt->dts, &ist->st->time_base), \ + av_ts2str(pkt->duration), av_ts2timestr(pkt->duration, &ist->st->time_base)); \ } + SHOW_TS_DEBUG("demuxer"); + if (!ist->wrap_correction_done && start_time != AV_NOPTS_VALUE && ist->st->pts_wrap_bits < 64) { int64_t stime, stime2; @@ -245,6 +249,8 @@ static void ts_fixup(Demuxer *d, AVPacket *pkt, int *repeat_pict) if (ist->st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO && av_stream_get_parser(ist->st)) *repeat_pict = av_stream_get_parser(ist->st)->repeat_pict; + + SHOW_TS_DEBUG("demuxer+tsfixup"); } static void thread_set_name(InputFile *f) From f88a4cb5e0c40b1578b4b7db66c6972da9f770c2 Mon Sep 17 00:00:00 2001 From: Stefano Sabatini Date: Sat, 11 Feb 2023 17:18:39 +0100 Subject: [PATCH 0342/2172] doc/ffmpeg: extend documentation for -dts_delta_threshold and -dts_error_threshold PR: https://patchwork.ffmpeg.org/project/ffmpeg/list/?series=8252 --- doc/ffmpeg.texi | 38 ++++++++++++++++++++++++++++++++------ 1 file changed, 32 insertions(+), 6 deletions(-) diff --git a/doc/ffmpeg.texi b/doc/ffmpeg.texi index d9d4b75567c..7feba8ab701 100644 --- a/doc/ffmpeg.texi +++ b/doc/ffmpeg.texi @@ -1837,12 +1837,38 @@ results, but increase memory use and latency. The default value is 10 seconds. -@item -dts_delta_threshold -Timestamp discontinuity delta threshold. -@item -dts_error_threshold @var{seconds} -Timestamp error delta threshold. This threshold use to discard crazy/damaged -timestamps and the default is 30 hours which is arbitrarily picked and quite -conservative. +@item -dts_delta_threshold @var{threshold} +Timestamp discontinuity delta threshold, expressed as a decimal number +of seconds. + +The timestamp discontinuity correction enabled by this option is only +applied to input formats accepting timestamp discontinuity (for which +the @code{AV_FMT_DISCONT} flag is enabled), e.g. MPEG-TS and HLS, and +is automatically disabled when employing the @code{-copy_ts} option +(unless wrapping is detected). + +If a timestamp discontinuity is detected whose absolute value is +greater than @var{threshold}, ffmpeg will remove the discontinuity by +decreasing/increasing the current DTS and PTS by the corresponding +delta value. + +The default value is 10. + +@item -dts_error_threshold @var{threshold} +Timestamp error delta threshold, expressed as a decimal number of +seconds. + +The timestamp correction enabled by this option is only applied to +input formats not accepting timestamp discontinuity (for which the +@code{AV_FMT_DISCONT} flag is not enabled). + +If a timestamp discontinuity is detected whose absolute value is +greater than @var{threshold}, ffmpeg will drop the PTS/DTS timestamp +value. + +The default value is @code{3600*30} (30 hours), which is arbitrarily +picked and quite conservative. + @item -muxdelay @var{seconds} (@emph{output}) Set the maximum demux-decode delay. @item -muxpreload @var{seconds} (@emph{output}) From 3ff4a3d2ec5eacc0f3194f7cc8b526496d0b8b37 Mon Sep 17 00:00:00 2001 From: JonHGee Date: Tue, 28 Feb 2023 21:25:13 +0000 Subject: [PATCH 0343/2172] libavcodec/libfdk-aacenc: Enable writing DRC metadata MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: JonHGee Signed-off-by: Martin Storsjö --- libavcodec/libfdk-aacenc.c | 67 ++++++++++++++++++++++++++++++-------- 1 file changed, 54 insertions(+), 13 deletions(-) diff --git a/libavcodec/libfdk-aacenc.c b/libavcodec/libfdk-aacenc.c index 54549de4735..ebf11516d93 100644 --- a/libavcodec/libfdk-aacenc.c +++ b/libavcodec/libfdk-aacenc.c @@ -46,6 +46,13 @@ typedef struct AACContext { int latm; int header_period; int vbr; + int drc_profile; + int drc_target_ref; + int comp_profile; + int comp_target_ref; + int prog_ref; + int metadata_mode; + AACENC_MetaData metaDataSetup; AudioFrameQueue afq; } AACContext; @@ -64,6 +71,11 @@ static const AVOption aac_enc_options[] = { { "latm", "Output LATM/LOAS encapsulated data", offsetof(AACContext, latm), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 1, AV_OPT_FLAG_AUDIO_PARAM | AV_OPT_FLAG_ENCODING_PARAM }, { "header_period", "StreamMuxConfig and PCE repetition period (in frames)", offsetof(AACContext, header_period), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 0xffff, AV_OPT_FLAG_AUDIO_PARAM | AV_OPT_FLAG_ENCODING_PARAM }, { "vbr", "VBR mode (1-5)", offsetof(AACContext, vbr), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 5, AV_OPT_FLAG_AUDIO_PARAM | AV_OPT_FLAG_ENCODING_PARAM }, + { "drc_profile", "The desired compression profile for AAC DRC", offsetof(AACContext, drc_profile), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 256, AV_OPT_FLAG_AUDIO_PARAM | AV_OPT_FLAG_ENCODING_PARAM }, + { "drc_target_ref", "Expected target reference level at decoder side in dB (for clipping prevention/limiter)", offsetof(AACContext, drc_target_ref), AV_OPT_TYPE_INT, { .i64 = 0.0 }, -31.75, 0, AV_OPT_FLAG_AUDIO_PARAM | AV_OPT_FLAG_ENCODING_PARAM }, + { "comp_profile", "The desired compression profile for AAC DRC", offsetof(AACContext, comp_profile), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 256, AV_OPT_FLAG_AUDIO_PARAM | AV_OPT_FLAG_ENCODING_PARAM }, + { "comp_target_ref", "Expected target reference level at decoder side in dB (for clipping prevention/limiter)", offsetof(AACContext, comp_target_ref), AV_OPT_TYPE_INT, { .i64 = 0.0 }, -31.75, 0, AV_OPT_FLAG_AUDIO_PARAM | AV_OPT_FLAG_ENCODING_PARAM }, + { "prog_ref", "The program reference level or dialog level in dB", offsetof(AACContext, prog_ref), AV_OPT_TYPE_INT, { .i64 = 0.0 }, -31.75, 0, AV_OPT_FLAG_AUDIO_PARAM | AV_OPT_FLAG_ENCODING_PARAM }, FF_AAC_PROFILE_OPTS { NULL } }; @@ -319,6 +331,30 @@ static av_cold int aac_encode_init(AVCodecContext *avctx) } } + s->metadata_mode = 0; + if (s->prog_ref) { + s->metadata_mode = 1; + s->metaDataSetup.prog_ref_level_present = 1; + s->metaDataSetup.prog_ref_level = s->prog_ref << 16; + } + if (s->drc_profile) { + s->metadata_mode = 1; + s->metaDataSetup.drc_profile = s->drc_profile; + s->metaDataSetup.drc_TargetRefLevel = s->drc_target_ref << 16; + if (s->comp_profile) { + /* Including the comp_profile means that we need to set the mode to ETSI */ + s->metadata_mode = 2; + s->metaDataSetup.comp_profile = s->comp_profile; + s->metaDataSetup.comp_TargetRefLevel = s->comp_target_ref << 16; + } + } + + if ((err = aacEncoder_SetParam(s->handle, AACENC_METADATA_MODE, s->metadata_mode)) != AACENC_OK) { + av_log(avctx, AV_LOG_ERROR, "Unable to set metadata mode to %d: %s\n", + s->metadata_mode, aac_get_error(err)); + goto error; + } + if ((err = aacEncEncode(s->handle, NULL, NULL, NULL, NULL)) != AACENC_OK) { av_log(avctx, AV_LOG_ERROR, "Unable to initialize the encoder: %s\n", aac_get_error(err)); @@ -363,11 +399,13 @@ static int aac_encode_frame(AVCodecContext *avctx, AVPacket *avpkt, AACENC_BufDesc in_buf = { 0 }, out_buf = { 0 }; AACENC_InArgs in_args = { 0 }; AACENC_OutArgs out_args = { 0 }; - int in_buffer_identifier = IN_AUDIO_DATA; - int in_buffer_size, in_buffer_element_size; + void* inBuffer[] = { 0, &s->metaDataSetup }; + int in_buffer_identifiers[] = { IN_AUDIO_DATA, IN_METADATA_SETUP }; + int in_buffer_element_sizes[] = { 2, sizeof(AACENC_MetaData) }; + int in_buffer_sizes[] = { 0, sizeof(s->metaDataSetup) }; int out_buffer_identifier = OUT_BITSTREAM_DATA; int out_buffer_size, out_buffer_element_size; - void *in_ptr, *out_ptr; + void *out_ptr; int ret; uint8_t dummy_buf[1]; AACENC_ERROR err; @@ -376,13 +414,12 @@ static int aac_encode_frame(AVCodecContext *avctx, AVPacket *avpkt, if (!frame) { /* Must be a non-null pointer, even if it's a dummy. We could use * the address of anything else on the stack as well. */ - in_ptr = dummy_buf; - in_buffer_size = 0; + inBuffer[0] = dummy_buf; in_args.numInSamples = -1; } else { - in_ptr = frame->data[0]; - in_buffer_size = 2 * avctx->ch_layout.nb_channels * frame->nb_samples; + inBuffer[0] = frame->data[0]; + in_buffer_sizes[0] = 2 * avctx->ch_layout.nb_channels * frame->nb_samples; in_args.numInSamples = avctx->ch_layout.nb_channels * frame->nb_samples; @@ -391,12 +428,16 @@ static int aac_encode_frame(AVCodecContext *avctx, AVPacket *avpkt, return ret; } - in_buffer_element_size = 2; - in_buf.numBufs = 1; - in_buf.bufs = &in_ptr; - in_buf.bufferIdentifiers = &in_buffer_identifier; - in_buf.bufSizes = &in_buffer_size; - in_buf.bufElSizes = &in_buffer_element_size; + if (s->metadata_mode == 0) { + in_buf.numBufs = 1; + } else { + in_buf.numBufs = 2; + } + + in_buf.bufs = (void**)inBuffer; + in_buf.bufferIdentifiers = in_buffer_identifiers; + in_buf.bufSizes = in_buffer_sizes; + in_buf.bufElSizes = in_buffer_element_sizes; /* The maximum packet size is 6144 bits aka 768 bytes per channel. */ ret = ff_alloc_packet(avctx, avpkt, FFMAX(8192, 768 * avctx->ch_layout.nb_channels)); From a0a0a804998da8d1a397479c9bafeb000e6be088 Mon Sep 17 00:00:00 2001 From: Jun Zhao Date: Sat, 25 Feb 2023 21:54:00 +0800 Subject: [PATCH 0344/2172] fftools/ffmpeg_filter: initialize the 'o' to silence the warning silence the warning: variable 'o' is used uninitialized whenever '&&' condition is false Signed-off-by: Jun Zhao --- fftools/ffmpeg_filter.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fftools/ffmpeg_filter.c b/fftools/ffmpeg_filter.c index 1f5bbf6c4d1..3504a3cc0ae 100644 --- a/fftools/ffmpeg_filter.c +++ b/fftools/ffmpeg_filter.c @@ -362,7 +362,7 @@ static int read_binary(const char *path, uint8_t **data, int *len) static int filter_opt_apply(AVFilterContext *f, const char *key, const char *val) { - const AVOption *o; + const AVOption *o = NULL; int ret; ret = av_opt_set(f, key, val, AV_OPT_SEARCH_CHILDREN); From 9a0d202118b1df1823598abe4c66e9243d435d30 Mon Sep 17 00:00:00 2001 From: Nicolas George Date: Wed, 8 Feb 2023 16:57:52 +0100 Subject: [PATCH 0345/2172] doc/dev_community: add the addresses of the committees Omitting the .org from the address should be protection enough against spam spiders. Signed-off-by: Nicolas George --- doc/dev_community/community.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/doc/dev_community/community.md b/doc/dev_community/community.md index 516ca5c05e7..837fa6f586a 100644 --- a/doc/dev_community/community.md +++ b/doc/dev_community/community.md @@ -58,6 +58,8 @@ Candidates for election can either be suggested or self-nominated. The conflict resolution process is detailed in the [resolution process](resolution_process.md) document. +The TC can be contacted at . + ## Community committee The Community Committee (CC) is here to arbitrage and make decisions when @@ -80,3 +82,5 @@ The members of the CC can be elected from outside of the GA. Candidates for election can either be suggested or self-nominated. The CC is governed by and responsible for enforcing the Code of Conduct. + +The CC can be contacted at . From 6709e468f6ce0febc914fece7cc5d08a9b0e7858 Mon Sep 17 00:00:00 2001 From: Thilo Borgmann Date: Wed, 8 Feb 2023 16:57:53 +0100 Subject: [PATCH 0346/2172] doc: Merge doc/dev_community/* and Code of Conduct into a seperate file Remove doc/dev_communit markup files completely as they are at the wrong place. Create a new community page, merging all of doc/dev_community and subsection Code of Conduct into a common place. The corresponding patch to ffmpeg-web puts the Organisation & Code of Conduct into a seperate community chapter on the FFmpeg website. --- doc/Makefile | 1 + doc/community.texi | 175 ++++++++++++++++++++++++ doc/dev_community/community.md | 86 ------------ doc/dev_community/resolution_process.md | 91 ------------ doc/developer.texi | 29 ---- doc/mailing-list-faq.texi | 2 +- 6 files changed, 177 insertions(+), 207 deletions(-) create mode 100644 doc/community.texi delete mode 100644 doc/dev_community/community.md delete mode 100644 doc/dev_community/resolution_process.md diff --git a/doc/Makefile b/doc/Makefile index 25774c7bad2..67586e4b748 100644 --- a/doc/Makefile +++ b/doc/Makefile @@ -19,6 +19,7 @@ MANPAGES3 = $(LIBRARIES-yes:%=doc/%.3) MANPAGES = $(MANPAGES1) $(MANPAGES3) PODPAGES = $(AVPROGS-yes:%=doc/%.pod) $(AVPROGS-yes:%=doc/%-all.pod) $(COMPONENTS-yes:%=doc/%.pod) $(LIBRARIES-yes:%=doc/%.pod) HTMLPAGES = $(AVPROGS-yes:%=doc/%.html) $(AVPROGS-yes:%=doc/%-all.html) $(COMPONENTS-yes:%=doc/%.html) $(LIBRARIES-yes:%=doc/%.html) \ + doc/community.html \ doc/developer.html \ doc/faq.html \ doc/fate.html \ diff --git a/doc/community.texi b/doc/community.texi new file mode 100644 index 00000000000..5fdd5f6d364 --- /dev/null +++ b/doc/community.texi @@ -0,0 +1,175 @@ +\input texinfo @c -*- texinfo -*- +@documentencoding UTF-8 + +@settitle Community +@titlepage +@center @titlefont{Community} +@end titlepage + +@top + +@contents + +@anchor{Organisation} +@chapter Organisation + +The FFmpeg project is organized through a community working on global consensus. + +Decisions are taken by the ensemble of active members, through voting and are aided by two committees. + +@anchor{General Assembly} +@chapter General Assembly + +The ensemble of active members is called the General Assembly (GA). + +The General Assembly is sovereign and legitimate for all its decisions regarding the FFmpeg project. + +The General Assembly is made up of active contributors. + +Contributors are considered "active contributors" if they have pushed more than 20 patches in the last 36 months in the main FFmpeg repository, or if they have been voted in by the GA. + +Additional members are added to the General Assembly through a vote after proposal by a member of the General Assembly. They are part of the GA for two years, after which they need a confirmation by the GA. + +A script to generate the current members of the general assembly (minus members voted in) can be found in `tools/general_assembly.pl`. + +@anchor{Voting} +@chapter Voting + +Voting is done using a ranked voting system, currently running on https://vote.ffmpeg.org/ . + +Majority vote means more than 50% of the expressed ballots. + +@anchor{Technical Committee} +@chapter Technical Committee + +The Technical Committee (TC) is here to arbitrate and make decisions when technical conflicts occur in the project. They will consider the merits of all the positions, judge them and make a decision. + +The TC resolves technical conflicts but is not a technical steering committee. + +Decisions by the TC are binding for all the contributors. + +Decisions made by the TC can be re-opened after 1 year or by a majority vote of the General Assembly, requested by one of the member of the GA. + +The TC is elected by the General Assembly for a duration of 1 year, and is composed of 5 members. Members can be re-elected if they wish. A majority vote in the General Assembly can trigger a new election of the TC. + +The members of the TC can be elected from outside of the GA. Candidates for election can either be suggested or self-nominated. + +The conflict resolution process is detailed in the resolution process document. + +The TC can be contacted at . + +@anchor{Resolution Process} +@section Resolution Process + +The Technical Committee (TC) is here to arbitrate and make decisions when technical conflicts occur in the project. + +The TC main role is to resolve technical conflicts. It is therefore not a technical steering committee, but it is understood that some decisions might impact the future of the project. + +@subsection Seizing + +The TC can take possession of any technical matter that it sees fit. + +To involve the TC in a matter, email tc@ or CC them on an ongoing discussion. + +As members of TC are developers, they also can email tc@ to raise an issue. +@subsection Announcement + +The TC, once seized, must announce itself on the main mailing list, with a [TC] tag. + +The TC has 2 modes of operation: a RFC one and an internal one. + +If the TC thinks it needs the input from the larger community, the TC can call for a RFC. Else, it can decide by itself. + +If the disagreement involves a member of the TC, that member should recuse themselves from the decision. + +The decision to use a RFC process or an internal discussion is a discretionary decision of the TC. + +The TC can also reject a seizure for a few reasons such as: the matter was not discussed enough previously; it lacks expertise to reach a beneficial decision on the matter; or the matter is too trivial. +@subsection RFC call + +In the RFC mode, one person from the TC posts on the mailing list the technical question and will request input from the community. + +The mail will have the following specification: + + a precise title + a specific tag [TC RFC] + a top-level email + contain a precise question that does not exceed 100 words and that is answerable by developers + may have an extra description, or a link to a previous discussion, if deemed necessary, + contain a precise end date for the answers. + +The answers from the community must be on the main mailing list and must have the following specification: + + keep the tag and the title unchanged + limited to 400 words + a first-level, answering directly to the main email + answering to the question. + +Further replies to answers are permitted, as long as they conform to the community standards of politeness, they are limited to 100 words, and are not nested more than once. (max-depth=2) + +After the end-date, mails on the thread will be ignored. + +Violations of those rules will be escalated through the Community Committee. + +After all the emails are in, the TC has 96 hours to give its final decision. Exceptionally, the TC can request an extra delay, that will be notified on the mailing list. +@subsection Within TC + +In the internal case, the TC has 96 hours to give its final decision. Exceptionally, the TC can request an extra delay. +@subsection Decisions + +The decisions from the TC will be sent on the mailing list, with the [TC] tag. + +Internally, the TC should take decisions with a majority, or using ranked-choice voting. + +The decision from the TC should be published with a summary of the reasons that lead to this decision. + +The decisions from the TC are final, until the matters are reopened after no less than one year. + +@anchor{Community Committee} +@chapter Community Committee + +The Community Committee (CC) is here to arbitrage and make decisions when inter-personal conflicts occur in the project. It will decide quickly and take actions, for the sake of the project. + +The CC can remove privileges of offending members, including removal of commit access and temporary ban from the community. + +Decisions made by the CC can be re-opened after 1 year or by a majority vote of the General Assembly. Indefinite bans from the community must be confirmed by the General Assembly, in a majority vote. + +The CC is elected by the General Assembly for a duration of 1 year, and is composed of 5 members. Members can be re-elected if they wish. A majority vote in the General Assembly can trigger a new election of the CC. + +The members of the CC can be elected from outside of the GA. Candidates for election can either be suggested or self-nominated. + +The CC is governed by and responsible for enforcing the Code of Conduct. + +The CC can be contacted at . + +@anchor{Code of Conduct} +@chapter Code of Conduct + +Be friendly and respectful towards others and third parties. +Treat others the way you yourself want to be treated. + +Be considerate. Not everyone shares the same viewpoint and priorities as you do. +Different opinions and interpretations help the project. +Looking at issues from a different perspective assists development. + +Do not assume malice for things that can be attributed to incompetence. Even if +it is malice, it's rarely good to start with that as initial assumption. + +Stay friendly even if someone acts contrarily. Everyone has a bad day +once in a while. +If you yourself have a bad day or are angry then try to take a break and reply +once you are calm and without anger if you have to. + +Try to help other team members and cooperate if you can. + +The goal of software development is to create technical excellence, not for any +individual to be better and "win" against the others. Large software projects +are only possible and successful through teamwork. + +If someone struggles do not put them down. Give them a helping hand +instead and point them in the right direction. + +Finally, keep in mind the immortal words of Bill and Ted, +"Be excellent to each other." + +@bye diff --git a/doc/dev_community/community.md b/doc/dev_community/community.md deleted file mode 100644 index 837fa6f586a..00000000000 --- a/doc/dev_community/community.md +++ /dev/null @@ -1,86 +0,0 @@ -# FFmpeg project - -## Organisation - -The FFmpeg project is organized through a community working on global consensus. - -Decisions are taken by the ensemble of active members, through voting and -are aided by two committees. - -## General Assembly - -The ensemble of active members is called the General Assembly (GA). - -The General Assembly is sovereign and legitimate for all its decisions -regarding the FFmpeg project. - -The General Assembly is made up of active contributors. - -Contributors are considered "active contributors" if they have pushed more -than 20 patches in the last 36 months in the main FFmpeg repository, or -if they have been voted in by the GA. - -Additional members are added to the General Assembly through a vote after -proposal by a member of the General Assembly. -They are part of the GA for two years, after which they need a confirmation by -the GA. - -A script to generate the current members of the general assembly (minus members -voted in) can be found in `tools/general_assembly.pl`. - -## Voting - -Voting is done using a ranked voting system, currently running on https://vote.ffmpeg.org/ . - -Majority vote means more than 50% of the expressed ballots. - -## Technical Committee - -The Technical Committee (TC) is here to arbitrate and make decisions when -technical conflicts occur in the project. -They will consider the merits of all the positions, judge them and make a -decision. - -The TC resolves technical conflicts but is not a technical steering committee. - -Decisions by the TC are binding for all the contributors. - -Decisions made by the TC can be re-opened after 1 year or by a majority vote -of the General Assembly, requested by one of the member of the GA. - -The TC is elected by the General Assembly for a duration of 1 year, and -is composed of 5 members. -Members can be re-elected if they wish. A majority vote in the General Assembly -can trigger a new election of the TC. - -The members of the TC can be elected from outside of the GA. -Candidates for election can either be suggested or self-nominated. - -The conflict resolution process is detailed in the [resolution process](resolution_process.md) document. - -The TC can be contacted at . - -## Community committee - -The Community Committee (CC) is here to arbitrage and make decisions when -inter-personal conflicts occur in the project. It will decide quickly and -take actions, for the sake of the project. - -The CC can remove privileges of offending members, including removal of -commit access and temporary ban from the community. - -Decisions made by the CC can be re-opened after 1 year or by a majority vote -of the General Assembly. Indefinite bans from the community must be confirmed -by the General Assembly, in a majority vote. - -The CC is elected by the General Assembly for a duration of 1 year, and is -composed of 5 members. -Members can be re-elected if they wish. A majority vote in the General Assembly -can trigger a new election of the CC. - -The members of the CC can be elected from outside of the GA. -Candidates for election can either be suggested or self-nominated. - -The CC is governed by and responsible for enforcing the Code of Conduct. - -The CC can be contacted at . diff --git a/doc/dev_community/resolution_process.md b/doc/dev_community/resolution_process.md deleted file mode 100644 index 4ed0b63c433..00000000000 --- a/doc/dev_community/resolution_process.md +++ /dev/null @@ -1,91 +0,0 @@ -# Technical Committee - -_This document only makes sense with the rules from [the community document](community)_. - -The Technical Committee (**TC**) is here to arbitrate and make decisions when -technical conflicts occur in the project. - -The TC main role is to resolve technical conflicts. -It is therefore not a technical steering committee, but it is understood that -some decisions might impact the future of the project. - -# Process - -## Seizing - -The TC can take possession of any technical matter that it sees fit. - -To involve the TC in a matter, email tc@ or CC them on an ongoing discussion. - -As members of TC are developers, they also can email tc@ to raise an issue. - -## Announcement - -The TC, once seized, must announce itself on the main mailing list, with a _[TC]_ tag. - -The TC has 2 modes of operation: a RFC one and an internal one. - -If the TC thinks it needs the input from the larger community, the TC can call -for a RFC. Else, it can decide by itself. - -If the disagreement involves a member of the TC, that member should recuse -themselves from the decision. - -The decision to use a RFC process or an internal discussion is a discretionary -decision of the TC. - -The TC can also reject a seizure for a few reasons such as: -the matter was not discussed enough previously; it lacks expertise to reach a -beneficial decision on the matter; or the matter is too trivial. - -### RFC call - -In the RFC mode, one person from the TC posts on the mailing list the -technical question and will request input from the community. - -The mail will have the following specification: -* a precise title -* a specific tag [TC RFC] -* a top-level email -* contain a precise question that does not exceed 100 words and that is answerable by developers -* may have an extra description, or a link to a previous discussion, if deemed necessary, -* contain a precise end date for the answers. - -The answers from the community must be on the main mailing list and must have -the following specification: -* keep the tag and the title unchanged -* limited to 400 words -* a first-level, answering directly to the main email -* answering to the question. - -Further replies to answers are permitted, as long as they conform to the -community standards of politeness, they are limited to 100 words, and are not -nested more than once. (max-depth=2) - -After the end-date, mails on the thread will be ignored. - -Violations of those rules will be escalated through the Community Committee. - -After all the emails are in, the TC has 96 hours to give its final decision. -Exceptionally, the TC can request an extra delay, that will be notified on the -mailing list. - -### Within TC - -In the internal case, the TC has 96 hours to give its final decision. -Exceptionally, the TC can request an extra delay. - - -## Decisions - -The decisions from the TC will be sent on the mailing list, with the _[TC]_ tag. - -Internally, the TC should take decisions with a majority, or using -ranked-choice voting. - -The decision from the TC should be published with a summary of the reasons that -lead to this decision. - -The decisions from the TC are final, until the matters are reopened after -no less than one year. - diff --git a/doc/developer.texi b/doc/developer.texi index 31b485b0f62..1275fa4f84b 100644 --- a/doc/developer.texi +++ b/doc/developer.texi @@ -421,35 +421,6 @@ finding a new maintainer and also don't forget to update the @file{MAINTAINERS} We think our rules are not too hard. If you have comments, contact us. -@chapter Code of conduct - -Be friendly and respectful towards others and third parties. -Treat others the way you yourself want to be treated. - -Be considerate. Not everyone shares the same viewpoint and priorities as you do. -Different opinions and interpretations help the project. -Looking at issues from a different perspective assists development. - -Do not assume malice for things that can be attributed to incompetence. Even if -it is malice, it's rarely good to start with that as initial assumption. - -Stay friendly even if someone acts contrarily. Everyone has a bad day -once in a while. -If you yourself have a bad day or are angry then try to take a break and reply -once you are calm and without anger if you have to. - -Try to help other team members and cooperate if you can. - -The goal of software development is to create technical excellence, not for any -individual to be better and "win" against the others. Large software projects -are only possible and successful through teamwork. - -If someone struggles do not put them down. Give them a helping hand -instead and point them in the right direction. - -Finally, keep in mind the immortal words of Bill and Ted, -"Be excellent to each other." - @anchor{Submitting patches} @chapter Submitting patches diff --git a/doc/mailing-list-faq.texi b/doc/mailing-list-faq.texi index 534ef3f8020..b2028eeee13 100644 --- a/doc/mailing-list-faq.texi +++ b/doc/mailing-list-faq.texi @@ -344,7 +344,7 @@ recommended. Avoid sending the same message to multiple mailing lists. @item -Please follow our @url{https://ffmpeg.org/developer.html#Code-of-conduct, Code of Conduct}. +Please follow our @url{https://ffmpeg.org/community.html#Code-of-conduct, Code of Conduct}. @end itemize @chapter Help From 083dde57e232389247f83273c04d45822701c9ca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Storsj=C3=B6?= Date: Wed, 1 Mar 2023 09:41:13 +0200 Subject: [PATCH 0347/2172] doc: Fix building community.html from the new community.texi MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In texi source, @ characters need to be escaped. This fixes the following build errors: community.texi:59: unknown command `ffmpeg' community.texi:143: unknown command `ffmpeg' Signed-off-by: Martin Storsjö --- doc/community.texi | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/community.texi b/doc/community.texi index 5fdd5f6d364..2b79850694a 100644 --- a/doc/community.texi +++ b/doc/community.texi @@ -56,7 +56,7 @@ The members of the TC can be elected from outside of the GA. Candidates for elec The conflict resolution process is detailed in the resolution process document. -The TC can be contacted at . +The TC can be contacted at . @anchor{Resolution Process} @section Resolution Process @@ -140,7 +140,7 @@ The members of the CC can be elected from outside of the GA. Candidates for elec The CC is governed by and responsible for enforcing the Code of Conduct. -The CC can be contacted at . +The CC can be contacted at . @anchor{Code of Conduct} @chapter Code of Conduct From e026e29460a2c43619b549c2d4fc40c29bbde1f8 Mon Sep 17 00:00:00 2001 From: JonHGee Date: Tue, 28 Feb 2023 23:08:10 +0000 Subject: [PATCH 0348/2172] libavcodec/libfdk-aacenc: send encoder delay/padding in packet side data MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: JonHGee Signed-off-by: Martin Storsjö --- libavcodec/libfdk-aacenc.c | 25 ++++++++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/libavcodec/libfdk-aacenc.c b/libavcodec/libfdk-aacenc.c index ebf11516d93..db5b0841e05 100644 --- a/libavcodec/libfdk-aacenc.c +++ b/libavcodec/libfdk-aacenc.c @@ -21,6 +21,7 @@ #include "libavutil/channel_layout.h" #include "libavutil/common.h" +#include "libavutil/intreadwrite.h" #include "libavutil/opt.h" #include "avcodec.h" #include "audio_frame_queue.h" @@ -53,6 +54,7 @@ typedef struct AACContext { int prog_ref; int metadata_mode; AACENC_MetaData metaDataSetup; + int delay_sent; AudioFrameQueue afq; } AACContext; @@ -406,7 +408,7 @@ static int aac_encode_frame(AVCodecContext *avctx, AVPacket *avpkt, int out_buffer_identifier = OUT_BITSTREAM_DATA; int out_buffer_size, out_buffer_element_size; void *out_ptr; - int ret; + int ret, discard_padding; uint8_t dummy_buf[1]; AACENC_ERROR err; @@ -469,6 +471,27 @@ static int aac_encode_frame(AVCodecContext *avctx, AVPacket *avpkt, ff_af_queue_remove(&s->afq, avctx->frame_size, &avpkt->pts, &avpkt->duration); + discard_padding = avctx->frame_size - avpkt->duration; + // Check if subtraction resulted in an overflow + if ((discard_padding < avctx->frame_size) != (avpkt->duration > 0)) { + av_log(avctx, AV_LOG_ERROR, "discard padding overflow\n"); + av_packet_unref(avpkt); + return AVERROR(EINVAL); + } + if ((!s->delay_sent && avctx->initial_padding > 0) || discard_padding > 0) { + uint8_t *side_data = + av_packet_new_side_data(avpkt, AV_PKT_DATA_SKIP_SAMPLES, 10); + if (!side_data) { + av_packet_unref(avpkt); + return AVERROR(ENOMEM); + } + if (!s->delay_sent) { + AV_WL32(side_data, avctx->initial_padding); + s->delay_sent = 1; + } + AV_WL32(side_data + 4, discard_padding); + } + avpkt->size = out_args.numOutBytes; *got_packet_ptr = 1; return 0; From 011f30fc8205eff8e775d04afb98e02685cd8a7a Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Tue, 28 Feb 2023 20:24:26 +0100 Subject: [PATCH 0349/2172] Use https for repository links Reviewed-by: Stefano Sabatini Signed-off-by: Michael Niedermayer --- CREDITS | 4 ++-- doc/authors.texi | 4 ++-- doc/git-howto.texi | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/CREDITS b/CREDITS index e29f0b853c9..f1aea93d6b1 100644 --- a/CREDITS +++ b/CREDITS @@ -1,6 +1,6 @@ -See the Git history of the project (git://source.ffmpeg.org/ffmpeg) to +See the Git history of the project (https://git.ffmpeg.org/ffmpeg) to get the names of people who have contributed to FFmpeg. To check the log, you can type the command "git log" in the FFmpeg source directory, or browse the online repository at -http://source.ffmpeg.org. +https://git.ffmpeg.org/ffmpeg diff --git a/doc/authors.texi b/doc/authors.texi index 6c8c1d7efad..ce088392f88 100644 --- a/doc/authors.texi +++ b/doc/authors.texi @@ -3,9 +3,9 @@ The FFmpeg developers. For details about the authorship, see the Git history of the project -(git://source.ffmpeg.org/ffmpeg), e.g. by typing the command +(https://git.ffmpeg.org/ffmpeg), e.g. by typing the command @command{git log} in the FFmpeg source directory, or browsing the -online repository at @url{http://source.ffmpeg.org}. +online repository at @url{https://git.ffmpeg.org/ffmpeg}. Maintainers for the specific components are listed in the file @file{MAINTAINERS} in the source code tree. diff --git a/doc/git-howto.texi b/doc/git-howto.texi index 5bb39bb9866..f4e2f2ec232 100644 --- a/doc/git-howto.texi +++ b/doc/git-howto.texi @@ -53,7 +53,7 @@ Most distribution and operating system provide a package for it. @section Cloning the source tree @example -git clone git://source.ffmpeg.org/ffmpeg +git clone https://git.ffmpeg.org/ffmpeg.git @end example This will put the FFmpeg sources into the directory @var{}. From de133eaabaea4d508475e2d2073b7c50238a79ee Mon Sep 17 00:00:00 2001 From: James Almer Date: Sat, 25 Feb 2023 18:51:31 -0300 Subject: [PATCH 0350/2172] avcodec/pthread_frame: remove forgotten deprecation warning wrappers Missed in e0786a8e. Reviewed-by: Anton Khirnov Signed-off-by: James Almer --- libavcodec/pthread_frame.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/libavcodec/pthread_frame.c b/libavcodec/pthread_frame.c index d9d5afaa82d..31785acbeff 100644 --- a/libavcodec/pthread_frame.c +++ b/libavcodec/pthread_frame.c @@ -903,10 +903,8 @@ static int thread_get_buffer_internal(AVCodecContext *avctx, AVFrame *f, int fla return ff_get_buffer(avctx, f, flags); p = avctx->internal->thread_ctx; -FF_DISABLE_DEPRECATION_WARNINGS if (atomic_load(&p->state) != STATE_SETTING_UP && ffcodec(avctx->codec)->update_thread_context) { -FF_ENABLE_DEPRECATION_WARNINGS av_log(avctx, AV_LOG_ERROR, "get_buffer() cannot be called after ff_thread_finish_setup()\n"); return -1; } From 8d226fb9786f34760e80e0d6b403bd63e9ac4ddd Mon Sep 17 00:00:00 2001 From: James Almer Date: Mon, 27 Feb 2023 10:37:18 -0300 Subject: [PATCH 0351/2172] avcodec/libvpxdec: remove unnecessary init_static_data function It's used only by the encoder. Reviewed-by: James Zern Signed-off-by: James Almer --- libavcodec/libvpxdec.c | 1 - 1 file changed, 1 deletion(-) diff --git a/libavcodec/libvpxdec.c b/libavcodec/libvpxdec.c index 0ae19c3f72a..8e6291fe209 100644 --- a/libavcodec/libvpxdec.c +++ b/libavcodec/libvpxdec.c @@ -391,6 +391,5 @@ FFCodec ff_libvpx_vp9_decoder = { FF_CODEC_DECODE_CB(vpx_decode), .caps_internal = FF_CODEC_CAP_NOT_INIT_THREADSAFE | FF_CODEC_CAP_AUTO_THREADS, - .init_static_data = ff_vp9_init_static, }; #endif /* CONFIG_LIBVPX_VP9_DECODER */ From 52a0852ae6aa046000bcb4ac4f3aff97f89dc17b Mon Sep 17 00:00:00 2001 From: James Almer Date: Mon, 27 Feb 2023 10:38:22 -0300 Subject: [PATCH 0352/2172] libavcodec/libvpxenc: move libvpx-vp9 init_static_data function to the only place it's used Signed-off-by: James Almer --- libavcodec/Makefile | 4 +-- libavcodec/libvpx.c | 81 ------------------------------------------ libavcodec/libvpx.h | 10 ------ libavcodec/libvpxenc.c | 41 ++++++++++++++++++++- 4 files changed, 42 insertions(+), 94 deletions(-) delete mode 100644 libavcodec/libvpx.c diff --git a/libavcodec/Makefile b/libavcodec/Makefile index 389253f5d08..6c797b8e14d 100644 --- a/libavcodec/Makefile +++ b/libavcodec/Makefile @@ -1121,8 +1121,8 @@ OBJS-$(CONFIG_LIBVORBIS_ENCODER) += libvorbisenc.o \ vorbis_data.o OBJS-$(CONFIG_LIBVPX_VP8_DECODER) += libvpxdec.o OBJS-$(CONFIG_LIBVPX_VP8_ENCODER) += libvpxenc.o -OBJS-$(CONFIG_LIBVPX_VP9_DECODER) += libvpxdec.o libvpx.o -OBJS-$(CONFIG_LIBVPX_VP9_ENCODER) += libvpxenc.o libvpx.o +OBJS-$(CONFIG_LIBVPX_VP9_DECODER) += libvpxdec.o +OBJS-$(CONFIG_LIBVPX_VP9_ENCODER) += libvpxenc.o OBJS-$(CONFIG_LIBWEBP_ENCODER) += libwebpenc_common.o libwebpenc.o OBJS-$(CONFIG_LIBWEBP_ANIM_ENCODER) += libwebpenc_common.o libwebpenc_animencoder.o OBJS-$(CONFIG_LIBX262_ENCODER) += libx264.o diff --git a/libavcodec/libvpx.c b/libavcodec/libvpx.c deleted file mode 100644 index 8601f82bd24..00000000000 --- a/libavcodec/libvpx.c +++ /dev/null @@ -1,81 +0,0 @@ -/* - * Copyright (c) 2013 Guillaume Martres - * - * 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 "libvpx.h" -#include "config.h" -#include "config_components.h" - -#if CONFIG_LIBVPX_VP9_ENCODER -#include -#include -#endif - -static const enum AVPixelFormat vp9_pix_fmts_def[] = { - AV_PIX_FMT_YUV420P, - AV_PIX_FMT_YUVA420P, - AV_PIX_FMT_NONE -}; - -#if CONFIG_LIBVPX_VP9_ENCODER -static const enum AVPixelFormat vp9_pix_fmts_highcol[] = { - AV_PIX_FMT_YUV420P, - AV_PIX_FMT_YUVA420P, - AV_PIX_FMT_YUV422P, - AV_PIX_FMT_YUV440P, - AV_PIX_FMT_YUV444P, - AV_PIX_FMT_GBRP, - AV_PIX_FMT_NONE -}; - -static const enum AVPixelFormat vp9_pix_fmts_highbd[] = { - AV_PIX_FMT_YUV420P, - AV_PIX_FMT_YUVA420P, - AV_PIX_FMT_YUV422P, - AV_PIX_FMT_YUV440P, - AV_PIX_FMT_YUV444P, - AV_PIX_FMT_YUV420P10, - AV_PIX_FMT_YUV422P10, - AV_PIX_FMT_YUV440P10, - AV_PIX_FMT_YUV444P10, - AV_PIX_FMT_YUV420P12, - AV_PIX_FMT_YUV422P12, - AV_PIX_FMT_YUV440P12, - AV_PIX_FMT_YUV444P12, - AV_PIX_FMT_GBRP, - AV_PIX_FMT_GBRP10, - AV_PIX_FMT_GBRP12, - AV_PIX_FMT_NONE -}; -#endif - -av_cold void ff_vp9_init_static(FFCodec *codec) -{ - codec->p.pix_fmts = vp9_pix_fmts_def; -#if CONFIG_LIBVPX_VP9_ENCODER - { - vpx_codec_caps_t codec_caps = vpx_codec_get_caps(vpx_codec_vp9_cx()); - if (codec_caps & VPX_CODEC_CAP_HIGHBITDEPTH) - codec->p.pix_fmts = vp9_pix_fmts_highbd; - else - codec->p.pix_fmts = vp9_pix_fmts_highcol; - } -#endif -} diff --git a/libavcodec/libvpx.h b/libavcodec/libvpx.h index 331feb8745a..4671e0edef3 100644 --- a/libavcodec/libvpx.h +++ b/libavcodec/libvpx.h @@ -21,16 +21,6 @@ #ifndef AVCODEC_LIBVPX_H #define AVCODEC_LIBVPX_H -#include - -#include "codec_internal.h" - #define MAX_VPX_THREADS 64 -void ff_vp9_init_static(FFCodec *codec); -#if 0 -enum AVPixelFormat ff_vpx_imgfmt_to_pixfmt(vpx_img_fmt_t img); -vpx_img_fmt_t ff_vpx_pixfmt_to_imgfmt(enum AVPixelFormat pix); -#endif - #endif /* AVCODEC_LIBVPX_H */ diff --git a/libavcodec/libvpxenc.c b/libavcodec/libvpxenc.c index 339d4d81469..5e6467a3d04 100644 --- a/libavcodec/libvpxenc.c +++ b/libavcodec/libvpxenc.c @@ -1979,6 +1979,45 @@ static av_cold int vp9_init(AVCodecContext *avctx) return vpx_init(avctx, vpx_codec_vp9_cx()); } +static const enum AVPixelFormat vp9_pix_fmts_highcol[] = { + AV_PIX_FMT_YUV420P, + AV_PIX_FMT_YUVA420P, + AV_PIX_FMT_YUV422P, + AV_PIX_FMT_YUV440P, + AV_PIX_FMT_YUV444P, + AV_PIX_FMT_GBRP, + AV_PIX_FMT_NONE +}; + +static const enum AVPixelFormat vp9_pix_fmts_highbd[] = { + AV_PIX_FMT_YUV420P, + AV_PIX_FMT_YUVA420P, + AV_PIX_FMT_YUV422P, + AV_PIX_FMT_YUV440P, + AV_PIX_FMT_YUV444P, + AV_PIX_FMT_YUV420P10, + AV_PIX_FMT_YUV422P10, + AV_PIX_FMT_YUV440P10, + AV_PIX_FMT_YUV444P10, + AV_PIX_FMT_YUV420P12, + AV_PIX_FMT_YUV422P12, + AV_PIX_FMT_YUV440P12, + AV_PIX_FMT_YUV444P12, + AV_PIX_FMT_GBRP, + AV_PIX_FMT_GBRP10, + AV_PIX_FMT_GBRP12, + AV_PIX_FMT_NONE +}; + +static av_cold void vp9_init_static(FFCodec *codec) +{ + vpx_codec_caps_t codec_caps = vpx_codec_get_caps(vpx_codec_vp9_cx()); + if (codec_caps & VPX_CODEC_CAP_HIGHBITDEPTH) + codec->p.pix_fmts = vp9_pix_fmts_highbd; + else + codec->p.pix_fmts = vp9_pix_fmts_highcol; +} + static const AVClass class_vp9 = { .class_name = "libvpx-vp9 encoder", .item_name = av_default_item_name, @@ -2003,6 +2042,6 @@ FFCodec ff_libvpx_vp9_encoder = { .caps_internal = FF_CODEC_CAP_NOT_INIT_THREADSAFE | FF_CODEC_CAP_AUTO_THREADS, .defaults = defaults, - .init_static_data = ff_vp9_init_static, + .init_static_data = vp9_init_static, }; #endif /* CONFIG_LIBVPX_VP9_ENCODER */ From 814178f92647be2411516bbb82f48532373d2554 Mon Sep 17 00:00:00 2001 From: Zhao Zhili Date: Wed, 1 Mar 2023 02:23:00 +0800 Subject: [PATCH 0353/2172] avcodec/aacps_tablegen: fix build error after avutil bump Fix tickets #10225 DECLARE_ALIGNED has been moved to mem_internal.h. Signed-off-by: Zhao Zhili Reviewed-by: Anton Khirnov --- libavcodec/aacps_tablegen.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavcodec/aacps_tablegen.h b/libavcodec/aacps_tablegen.h index 0ac4f68d68d..5fdd7f0a9dd 100644 --- a/libavcodec/aacps_tablegen.h +++ b/libavcodec/aacps_tablegen.h @@ -34,7 +34,7 @@ #include "libavutil/common.h" #include "libavutil/libm.h" #include "libavutil/mathematics.h" -#include "libavutil/mem.h" +#include "libavutil/mem_internal.h" #define NR_ALLPASS_BANDS20 30 #define NR_ALLPASS_BANDS34 50 #define PS_AP_LINKS 3 From a4e5b946332dd625affd0e259eb787575e5c32f2 Mon Sep 17 00:00:00 2001 From: Marth64 Date: Sat, 18 Feb 2023 13:43:00 -0600 Subject: [PATCH 0354/2172] avcodec/eac3dec: add detection of Atmos spatial extension profile Signed-off-by: Marth64 --- libavcodec/ac3dec.c | 1 + libavcodec/ac3dec.h | 1 + libavcodec/ac3dec_float.c | 2 ++ libavcodec/avcodec.h | 2 ++ libavcodec/codec_desc.c | 1 + libavcodec/eac3dec.c | 11 ++++++++++- libavcodec/profiles.c | 5 +++++ libavcodec/profiles.h | 1 + 8 files changed, 23 insertions(+), 1 deletion(-) diff --git a/libavcodec/ac3dec.c b/libavcodec/ac3dec.c index 0b120e6140a..fc0cbeb4938 100644 --- a/libavcodec/ac3dec.c +++ b/libavcodec/ac3dec.c @@ -1714,6 +1714,7 @@ static int ac3_decode_frame(AVCodecContext *avctx, AVFrame *frame, if (!err) { avctx->sample_rate = s->sample_rate; avctx->bit_rate = s->bit_rate + s->prev_bit_rate; + avctx->profile = s->eac3_extension_type_a == 1 ? FF_PROFILE_EAC3_DDP_ATMOS : FF_PROFILE_UNKNOWN; } if (!avctx->sample_rate) { diff --git a/libavcodec/ac3dec.h b/libavcodec/ac3dec.h index 138b462abb5..0829f4b40de 100644 --- a/libavcodec/ac3dec.h +++ b/libavcodec/ac3dec.h @@ -102,6 +102,7 @@ typedef struct AC3DecodeContext { int eac3; ///< indicates if current frame is E-AC-3 int eac3_frame_dependent_found; ///< bitstream has E-AC-3 dependent frame(s) int eac3_subsbtreamid_found; ///< bitstream has E-AC-3 additional substream(s) + int eac3_extension_type_a; ///< bitstream has E-AC-3 extension type A enabled frame(s) int dolby_surround_mode; ///< dolby surround mode (dsurmod) int dolby_surround_ex_mode; ///< dolby surround ex mode (dsurexmod) int dolby_headphone_mode; ///< dolby headphone mode (dheadphonmod) diff --git a/libavcodec/ac3dec_float.c b/libavcodec/ac3dec_float.c index b8868d8ee15..39d3cbd282b 100644 --- a/libavcodec/ac3dec_float.c +++ b/libavcodec/ac3dec_float.c @@ -33,6 +33,7 @@ #include "ac3dec.h" #include "codec_internal.h" +#include "profiles.h" #include "eac3dec.c" #include "ac3dec.c" @@ -92,6 +93,7 @@ const FFCodec ff_eac3_decoder = { .p.sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_FLTP, AV_SAMPLE_FMT_NONE }, .p.priv_class = &ac3_eac3_decoder_class, + .p.profiles = NULL_IF_CONFIG_SMALL(ff_eac3_profiles), .caps_internal = FF_CODEC_CAP_INIT_CLEANUP, }; #endif diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h index 9a0fe97cad1..3e9b0dbd263 100644 --- a/libavcodec/avcodec.h +++ b/libavcodec/avcodec.h @@ -1591,6 +1591,8 @@ typedef struct AVCodecContext { #define FF_PROFILE_DTS_HD_MA 60 #define FF_PROFILE_DTS_EXPRESS 70 +#define FF_PROFILE_EAC3_DDP_ATMOS 30 + #define FF_PROFILE_MPEG2_422 0 #define FF_PROFILE_MPEG2_HIGH 1 #define FF_PROFILE_MPEG2_SS 2 diff --git a/libavcodec/codec_desc.c b/libavcodec/codec_desc.c index 199f62df15b..4098d4f5a59 100644 --- a/libavcodec/codec_desc.c +++ b/libavcodec/codec_desc.c @@ -2931,6 +2931,7 @@ static const AVCodecDescriptor codec_descriptors[] = { .name = "eac3", .long_name = NULL_IF_CONFIG_SMALL("ATSC A/52B (AC-3, E-AC-3)"), .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSY, + .profiles = NULL_IF_CONFIG_SMALL(ff_eac3_profiles), }, { .id = AV_CODEC_ID_SIPR, diff --git a/libavcodec/eac3dec.c b/libavcodec/eac3dec.c index deca51dd3da..5c71751a0c8 100644 --- a/libavcodec/eac3dec.c +++ b/libavcodec/eac3dec.c @@ -464,7 +464,16 @@ static int ff_eac3_parse_header(AC3DecodeContext *s) if (get_bits1(gbc)) { int addbsil = get_bits(gbc, 6); for (i = 0; i < addbsil + 1; i++) { - skip_bits(gbc, 8); // skip additional bit stream info + if (i == 0) { + /* In this 8 bit chunk, the LSB is equal to flag_ec3_extension_type_a + which can be used to detect Atmos presence */ + skip_bits(gbc, 7); + if (get_bits1(gbc)) { + s->eac3_extension_type_a = 1; + } + } else { + skip_bits(gbc, 8); // skip additional bit stream info + } } } diff --git a/libavcodec/profiles.c b/libavcodec/profiles.c index 2230fc5415d..5c026ef380a 100644 --- a/libavcodec/profiles.c +++ b/libavcodec/profiles.c @@ -45,6 +45,11 @@ const AVProfile ff_dca_profiles[] = { { FF_PROFILE_UNKNOWN }, }; +const AVProfile ff_eac3_profiles[] = { + { FF_PROFILE_EAC3_DDP_ATMOS, "Dolby Digital Plus + Dolby Atmos"}, + { FF_PROFILE_UNKNOWN }, +}; + const AVProfile ff_dnxhd_profiles[] = { { FF_PROFILE_DNXHD, "DNXHD"}, { FF_PROFILE_DNXHR_LB, "DNXHR LB"}, diff --git a/libavcodec/profiles.h b/libavcodec/profiles.h index 41a19aa9add..6ebedbd03f4 100644 --- a/libavcodec/profiles.h +++ b/libavcodec/profiles.h @@ -58,6 +58,7 @@ extern const AVProfile ff_aac_profiles[]; extern const AVProfile ff_dca_profiles[]; +extern const AVProfile ff_eac3_profiles[]; extern const AVProfile ff_dnxhd_profiles[]; extern const AVProfile ff_h264_profiles[]; extern const AVProfile ff_hevc_profiles[]; From 96ed043afa44d468ff3629095f90d391450c4e60 Mon Sep 17 00:00:00 2001 From: Marth64 Date: Sat, 18 Feb 2023 11:24:38 -0600 Subject: [PATCH 0355/2172] avcodec/mlpdec: add detection of Atmos spatial extension profile in TrueHD Signed-off-by: Marth64 --- libavcodec/avcodec.h | 2 ++ libavcodec/codec_desc.c | 1 + libavcodec/mlpdec.c | 10 ++++++++++ libavcodec/profiles.c | 5 +++++ libavcodec/profiles.h | 1 + 5 files changed, 19 insertions(+) diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h index 3e9b0dbd263..0645114772c 100644 --- a/libavcodec/avcodec.h +++ b/libavcodec/avcodec.h @@ -1593,6 +1593,8 @@ typedef struct AVCodecContext { #define FF_PROFILE_EAC3_DDP_ATMOS 30 +#define FF_PROFILE_TRUEHD_ATMOS 30 + #define FF_PROFILE_MPEG2_422 0 #define FF_PROFILE_MPEG2_HIGH 1 #define FF_PROFILE_MPEG2_SS 2 diff --git a/libavcodec/codec_desc.c b/libavcodec/codec_desc.c index 4098d4f5a59..e80ac077006 100644 --- a/libavcodec/codec_desc.c +++ b/libavcodec/codec_desc.c @@ -2960,6 +2960,7 @@ static const AVCodecDescriptor codec_descriptors[] = { .name = "truehd", .long_name = NULL_IF_CONFIG_SMALL("TrueHD"), .props = AV_CODEC_PROP_LOSSLESS, + .profiles = NULL_IF_CONFIG_SMALL(ff_truehd_profiles), }, { .id = AV_CODEC_ID_MP4ALS, diff --git a/libavcodec/mlpdec.c b/libavcodec/mlpdec.c index 0ee1f0982c6..966ee0f0a2f 100644 --- a/libavcodec/mlpdec.c +++ b/libavcodec/mlpdec.c @@ -42,6 +42,7 @@ #include "mlpdsp.h" #include "mlp.h" #include "config.h" +#include "profiles.h" /** number of bits used for VLC lookup - longest Huffman code is 9 */ #if ARCH_ARM @@ -392,6 +393,14 @@ static int read_major_sync(MLPDecodeContext *m, GetBitContext *gb) m->num_substreams = mh.num_substreams; m->substream_info = mh.substream_info; + /* If there is a 4th substream and the MSB of substream_info is set, + * there is a 16-channel spatial presentation (Atmos in TrueHD). + */ + if (m->avctx->codec_id == AV_CODEC_ID_TRUEHD + && m->num_substreams == 4 && m->substream_info >> 7 == 1) { + m->avctx->profile = FF_PROFILE_TRUEHD_ATMOS; + } + /* limit to decoding 3 substreams, as the 4th is used by Dolby Atmos for non-audio data */ m->max_decoded_substream = FFMIN(m->num_substreams - 1, 2); @@ -1452,5 +1461,6 @@ const FFCodec ff_truehd_decoder = { FF_CODEC_DECODE_CB(read_access_unit), .flush = mlp_decode_flush, .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_CHANNEL_CONF, + .p.profiles = NULL_IF_CONFIG_SMALL(ff_truehd_profiles), }; #endif /* CONFIG_TRUEHD_DECODER */ diff --git a/libavcodec/profiles.c b/libavcodec/profiles.c index 5c026ef380a..ec5d646344c 100644 --- a/libavcodec/profiles.c +++ b/libavcodec/profiles.c @@ -50,6 +50,11 @@ const AVProfile ff_eac3_profiles[] = { { FF_PROFILE_UNKNOWN }, }; +const AVProfile ff_truehd_profiles[] = { + { FF_PROFILE_TRUEHD_ATMOS, "Dolby TrueHD + Dolby Atmos"}, + { FF_PROFILE_UNKNOWN }, +}; + const AVProfile ff_dnxhd_profiles[] = { { FF_PROFILE_DNXHD, "DNXHD"}, { FF_PROFILE_DNXHR_LB, "DNXHR LB"}, diff --git a/libavcodec/profiles.h b/libavcodec/profiles.h index 6ebedbd03f4..1d523992fc2 100644 --- a/libavcodec/profiles.h +++ b/libavcodec/profiles.h @@ -59,6 +59,7 @@ extern const AVProfile ff_aac_profiles[]; extern const AVProfile ff_dca_profiles[]; extern const AVProfile ff_eac3_profiles[]; +extern const AVProfile ff_truehd_profiles[]; extern const AVProfile ff_dnxhd_profiles[]; extern const AVProfile ff_h264_profiles[]; extern const AVProfile ff_hevc_profiles[]; From 98a4699216fbc3a4e382ba6a10026eab39b5214e Mon Sep 17 00:00:00 2001 From: Marth64 Date: Fri, 17 Feb 2023 19:14:56 -0600 Subject: [PATCH 0356/2172] avcodec/dca_xll: add detection of DTS:X and DTS:X IMAX Signed-off-by: Marth64 --- libavcodec/avcodec.h | 15 +++++++++------ libavcodec/dca_syncwords.h | 3 +++ libavcodec/dca_xll.c | 26 +++++++++++++++++++++++++- libavcodec/dca_xll.h | 3 +++ libavcodec/profiles.c | 14 ++++++++------ 5 files changed, 48 insertions(+), 13 deletions(-) diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h index 0645114772c..75775a36932 100644 --- a/libavcodec/avcodec.h +++ b/libavcodec/avcodec.h @@ -1584,12 +1584,15 @@ typedef struct AVCodecContext { #define FF_PROFILE_DNXHR_HQX 4 #define FF_PROFILE_DNXHR_444 5 -#define FF_PROFILE_DTS 20 -#define FF_PROFILE_DTS_ES 30 -#define FF_PROFILE_DTS_96_24 40 -#define FF_PROFILE_DTS_HD_HRA 50 -#define FF_PROFILE_DTS_HD_MA 60 -#define FF_PROFILE_DTS_EXPRESS 70 +#define FF_PROFILE_DTS 20 +#define FF_PROFILE_DTS_ES 30 +#define FF_PROFILE_DTS_96_24 40 +#define FF_PROFILE_DTS_HD_HRA 50 +#define FF_PROFILE_DTS_HD_MA 60 +#define FF_PROFILE_DTS_EXPRESS 70 +#define FF_PROFILE_DTS_HD_MA_X 61 +#define FF_PROFILE_DTS_HD_MA_X_IMAX 62 + #define FF_PROFILE_EAC3_DDP_ATMOS 30 diff --git a/libavcodec/dca_syncwords.h b/libavcodec/dca_syncwords.h index 4d2cd5f56d5..649bbd90dcf 100644 --- a/libavcodec/dca_syncwords.h +++ b/libavcodec/dca_syncwords.h @@ -33,4 +33,7 @@ #define DCA_SYNCWORD_SUBSTREAM_CORE 0x02B09261U #define DCA_SYNCWORD_REV1AUX 0x9A1105A0U +#define DCA_SYNCWORD_XLL_X 0x02000850U +#define DCA_SYNCWORD_XLL_X_IMAX 0xF14000D0U + #endif /* AVCODEC_DCA_SYNCWORDS_H */ diff --git a/libavcodec/dca_xll.c b/libavcodec/dca_xll.c index fe2c766d981..b8cf37a35f1 100644 --- a/libavcodec/dca_xll.c +++ b/libavcodec/dca_xll.c @@ -18,6 +18,7 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#include "avcodec.h" #include "libavutil/channel_layout.h" #include "dcadec.h" #include "dcadata.h" @@ -1054,6 +1055,22 @@ static int parse_frame(DCAXllDecoder *s, const uint8_t *data, int size, DCAExssA return ret; if ((ret = parse_band_data(s)) < 0) return ret; + + if (s->frame_size * 8 > FFALIGN(get_bits_count(&s->gb), 32)) { + unsigned int extradata_syncword; + + // Align to dword + skip_bits_long(&s->gb, -get_bits_count(&s->gb) & 31); + + extradata_syncword = show_bits_long(&s->gb, 32); + + if (extradata_syncword == DCA_SYNCWORD_XLL_X) { + s->x_syncword_present = 1; + } else if ((extradata_syncword >> 1) == (DCA_SYNCWORD_XLL_X_IMAX >> 1)) { + s->x_imax_syncword_present = 1; + } + } + if (ff_dca_seek_bits(&s->gb, s->frame_size * 8)) { av_log(s->avctx, AV_LOG_ERROR, "Read past end of XLL frame\n"); return AVERROR_INVALIDDATA; @@ -1428,8 +1445,15 @@ int ff_dca_xll_filter_frame(DCAXllDecoder *s, AVFrame *frame) return AVERROR(EINVAL); } + if (s->x_imax_syncword_present) { + avctx->profile = FF_PROFILE_DTS_HD_MA_X_IMAX; + } else if (s->x_syncword_present) { + avctx->profile = FF_PROFILE_DTS_HD_MA_X; + } else { + avctx->profile = FF_PROFILE_DTS_HD_MA; + } + avctx->bits_per_raw_sample = p->storage_bit_res; - avctx->profile = FF_PROFILE_DTS_HD_MA; avctx->bit_rate = 0; frame->nb_samples = nsamples = s->nframesamples << (s->nfreqbands - 1); diff --git a/libavcodec/dca_xll.h b/libavcodec/dca_xll.h index d7c1a13ec86..a22bbb8d770 100644 --- a/libavcodec/dca_xll.h +++ b/libavcodec/dca_xll.h @@ -135,6 +135,9 @@ typedef struct DCAXllDecoder { DCADSPContext *dcadsp; + int x_syncword_present; ///< Syncword for extension data at end of frame (DTS:X) is present + int x_imax_syncword_present; ///< Syncword for extension data at end of frame (DTS:X IMAX) is present + int output_mask; int32_t *output_samples[DCA_SPEAKER_COUNT]; } DCAXllDecoder; diff --git a/libavcodec/profiles.c b/libavcodec/profiles.c index ec5d646344c..545626337cb 100644 --- a/libavcodec/profiles.c +++ b/libavcodec/profiles.c @@ -36,12 +36,14 @@ const AVProfile ff_aac_profiles[] = { }; const AVProfile ff_dca_profiles[] = { - { FF_PROFILE_DTS, "DTS" }, - { FF_PROFILE_DTS_ES, "DTS-ES" }, - { FF_PROFILE_DTS_96_24, "DTS 96/24" }, - { FF_PROFILE_DTS_HD_HRA, "DTS-HD HRA" }, - { FF_PROFILE_DTS_HD_MA, "DTS-HD MA" }, - { FF_PROFILE_DTS_EXPRESS, "DTS Express" }, + { FF_PROFILE_DTS, "DTS" }, + { FF_PROFILE_DTS_ES, "DTS-ES" }, + { FF_PROFILE_DTS_96_24, "DTS 96/24" }, + { FF_PROFILE_DTS_HD_HRA, "DTS-HD HRA" }, + { FF_PROFILE_DTS_HD_MA, "DTS-HD MA" }, + { FF_PROFILE_DTS_HD_MA_X, "DTS-HD MA + DTS:X" }, + { FF_PROFILE_DTS_HD_MA_X_IMAX, "DTS-HD MA + DTS:X IMAX" }, + { FF_PROFILE_DTS_EXPRESS, "DTS Express" }, { FF_PROFILE_UNKNOWN }, }; From 373ef1c4faed714963a688209871acfe1fca46a7 Mon Sep 17 00:00:00 2001 From: Marth64 Date: Fri, 17 Feb 2023 19:14:57 -0600 Subject: [PATCH 0357/2172] avcodec/version: bump minor version to accommodate spatial audio detection Signed-off-by: Marth64 --- doc/APIchanges | 4 ++++ libavcodec/version.h | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/doc/APIchanges b/doc/APIchanges index 9f851c73466..14737223cb0 100644 --- a/doc/APIchanges +++ b/doc/APIchanges @@ -2,6 +2,10 @@ The last version increases of all libraries were on 2023-02-09 API changes, most recent first: +2023-03-02 - xxxxxxxxxx - lavc 60.6.100 - avcodec.h + Add FF_PROFILE_EAC3_DDP_ATMOS, FF_PROFILE_TRUEHD_ATMOS, + FF_PROFILE_DTS_HD_MA_X and FF_PROFILE_DTS_HD_MA_X_IMAX. + 2023-02-25 - xxxxxxxxxx - lavc 60.5.100 - avcodec.h Add FF_PROFILE_HEVC_SCC. diff --git a/libavcodec/version.h b/libavcodec/version.h index 7aa95fc3f1c..da54f878874 100644 --- a/libavcodec/version.h +++ b/libavcodec/version.h @@ -29,7 +29,7 @@ #include "version_major.h" -#define LIBAVCODEC_VERSION_MINOR 5 +#define LIBAVCODEC_VERSION_MINOR 6 #define LIBAVCODEC_VERSION_MICRO 100 #define LIBAVCODEC_VERSION_INT AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \ From 79b40ff58c2e6f59d7a5e6d289243a10ff1dccb4 Mon Sep 17 00:00:00 2001 From: Werner Robitza Date: Tue, 28 Feb 2023 12:42:03 +0100 Subject: [PATCH 0358/2172] doc/filters: update SITI description The filter implements the 'legacy' version from a superseded recommendation. --- doc/filters.texi | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/doc/filters.texi b/doc/filters.texi index 47e92b92698..7a7b2ba4e79 100644 --- a/doc/filters.texi +++ b/doc/filters.texi @@ -21593,9 +21593,11 @@ ffmpeg -i input1.mkv -i input2.mkv -filter_complex "[0:v][1:v] signature=nb_inpu @anchor{siti} @section siti -Calculate Spatial Info (SI) and Temporal Info (TI) scores for a video, as defined -in ITU-T P.910: Subjective video quality assessment methods for multimedia -applications. Available PDF at @url{https://www.itu.int/rec/T-REC-P.910-199909-S/en }. +Calculate Spatial Information (SI) and Temporal Information (TI) scores for a video, +as defined in ITU-T Rec. P.910 (11/21): Subjective video quality assessment methods +for multimedia applications. Available PDF at @url{https://www.itu.int/rec/T-REC-P.910-202111-S/en}. +Note that this is a legacy implementation that corresponds to a superseded recommendation. +Refer to ITU-T Rec. P.910 (07/22) for the latest version: @url{https://www.itu.int/rec/T-REC-P.910-202207-I/en} It accepts the following option: From 432adca5fedcb277b9a715a723cfd40735ec58f8 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Mon, 20 Feb 2023 19:47:51 +0100 Subject: [PATCH 0359/2172] lavc: disable an obsolete hack for real video AVCodecContext.slice_{count,offset} are unneeded since 2007, commit 383b123ed37df4ff99010646f1fa5911ff1428cc and following. Deprecate those fields. --- libavcodec/avcodec.h | 4 ++++ libavcodec/options_table.h | 2 ++ libavcodec/pthread_frame.c | 8 ++++++++ libavcodec/rv10.c | 28 +++++++++++----------------- libavcodec/rv34.c | 14 +++++--------- libavcodec/version_major.h | 1 + 6 files changed, 31 insertions(+), 26 deletions(-) diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h index 75775a36932..87ebee22b19 100644 --- a/libavcodec/avcodec.h +++ b/libavcodec/avcodec.h @@ -771,11 +771,13 @@ typedef struct AVCodecContext { */ float dark_masking; +#if FF_API_SLICE_OFFSET /** * slice count * - encoding: Set by libavcodec. * - decoding: Set by user (or 0). */ + attribute_deprecated int slice_count; /** @@ -783,7 +785,9 @@ typedef struct AVCodecContext { * - encoding: Set/allocated by libavcodec. * - decoding: Set/allocated by user (or NULL). */ + attribute_deprecated int *slice_offset; +#endif /** * sample aspect ratio (0 if unknown) diff --git a/libavcodec/options_table.h b/libavcodec/options_table.h index 4fea57673ad..f331ce28619 100644 --- a/libavcodec/options_table.h +++ b/libavcodec/options_table.h @@ -177,7 +177,9 @@ static const AVOption avcodec_options[] = { {"xvidmmx", "deprecated, for compatibility only", 0, AV_OPT_TYPE_CONST, {.i64 = FF_IDCT_XVID }, INT_MIN, INT_MAX, V|E|D, "idct"}, {"faani", "floating point AAN IDCT", 0, AV_OPT_TYPE_CONST, {.i64 = FF_IDCT_FAAN }, INT_MIN, INT_MAX, V|D|E, "idct"}, {"simpleauto", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = FF_IDCT_SIMPLEAUTO }, INT_MIN, INT_MAX, V|E|D, "idct"}, +#if FF_API_SLICE_OFFSET {"slice_count", NULL, OFFSET(slice_count), AV_OPT_TYPE_INT, {.i64 = DEFAULT }, INT_MIN, INT_MAX}, +#endif {"ec", "set error concealment strategy", OFFSET(error_concealment), AV_OPT_TYPE_FLAGS, {.i64 = 3 }, INT_MIN, INT_MAX, V|D, "ec"}, {"guess_mvs", "iterative motion vector (MV) search (slow)", 0, AV_OPT_TYPE_CONST, {.i64 = FF_EC_GUESS_MVS }, INT_MIN, INT_MAX, V|D, "ec"}, {"deblock", "use strong deblock filter for damaged MBs", 0, AV_OPT_TYPE_CONST, {.i64 = FF_EC_DEBLOCK }, INT_MIN, INT_MAX, V|D, "ec"}, diff --git a/libavcodec/pthread_frame.c b/libavcodec/pthread_frame.c index 31785acbeff..74864e19c5a 100644 --- a/libavcodec/pthread_frame.c +++ b/libavcodec/pthread_frame.c @@ -374,6 +374,8 @@ FF_DISABLE_DEPRECATION_WARNINGS FF_ENABLE_DEPRECATION_WARNINGS #endif +#if FF_API_SLICE_OFFSET +FF_DISABLE_DEPRECATION_WARNINGS if (src->slice_count && src->slice_offset) { if (dst->slice_count < src->slice_count) { int err = av_reallocp_array(&dst->slice_offset, src->slice_count, @@ -385,6 +387,8 @@ FF_ENABLE_DEPRECATION_WARNINGS src->slice_count * sizeof(*dst->slice_offset)); } dst->slice_count = src->slice_count; +FF_ENABLE_DEPRECATION_WARNINGS +#endif av_packet_unref(dst->internal->last_pkt_props); err = av_packet_copy_props(dst->internal->last_pkt_props, src->internal->last_pkt_props); @@ -686,7 +690,11 @@ void ff_frame_thread_free(AVCodecContext *avctx, int thread_count) av_freep(&ctx->priv_data); } +#if FF_API_SLICE_OFFSET +FF_DISABLE_DEPRECATION_WARNINGS av_freep(&ctx->slice_offset); +FF_ENABLE_DEPRECATION_WARNINGS +#endif av_buffer_unref(&ctx->internal->pool); av_packet_free(&ctx->internal->last_pkt_props); diff --git a/libavcodec/rv10.c b/libavcodec/rv10.c index 2233edfca55..bb1ead5002c 100644 --- a/libavcodec/rv10.c +++ b/libavcodec/rv10.c @@ -587,10 +587,7 @@ static int rv10_decode_packet(AVCodecContext *avctx, const uint8_t *buf, static int get_slice_offset(AVCodecContext *avctx, const uint8_t *buf, int n) { - if (avctx->slice_count) - return avctx->slice_offset[n]; - else - return AV_RL32(buf + n * 8); + return AV_RL32(buf + n * 8); } static int rv10_decode_frame(AVCodecContext *avctx, AVFrame *pict, @@ -610,21 +607,18 @@ static int rv10_decode_frame(AVCodecContext *avctx, AVFrame *pict, return 0; } - if (!avctx->slice_count) { - slice_count = (*buf++) + 1; - buf_size--; + slice_count = (*buf++) + 1; + buf_size--; - if (!slice_count || buf_size <= 8 * slice_count) { - av_log(avctx, AV_LOG_ERROR, "Invalid slice count: %d.\n", - slice_count); - return AVERROR_INVALIDDATA; - } + if (!slice_count || buf_size <= 8 * slice_count) { + av_log(avctx, AV_LOG_ERROR, "Invalid slice count: %d.\n", + slice_count); + return AVERROR_INVALIDDATA; + } - slices_hdr = buf + 4; - buf += 8 * slice_count; - buf_size -= 8 * slice_count; - } else - slice_count = avctx->slice_count; + slices_hdr = buf + 4; + buf += 8 * slice_count; + buf_size -= 8 * slice_count; for (i = 0; i < slice_count; i++) { unsigned offset = get_slice_offset(avctx, slices_hdr, i); diff --git a/libavcodec/rv34.c b/libavcodec/rv34.c index be188edc475..45f64666f85 100644 --- a/libavcodec/rv34.c +++ b/libavcodec/rv34.c @@ -1549,8 +1549,7 @@ int ff_rv34_decode_update_thread_context(AVCodecContext *dst, const AVCodecConte static int get_slice_offset(AVCodecContext *avctx, const uint8_t *buf, int n, int slice_count, int buf_size) { if (n < slice_count) { - if(avctx->slice_count) return avctx->slice_offset[n]; - else return AV_RL32(buf + n*8 - 4) == 1 ? AV_RL32(buf + n*8) : AV_RB32(buf + n*8); + return AV_RL32(buf + n*8 - 4) == 1 ? AV_RL32(buf + n*8) : AV_RB32(buf + n*8); } else return buf_size; } @@ -1623,13 +1622,10 @@ int ff_rv34_decode_frame(AVCodecContext *avctx, AVFrame *pict, return 0; } - if(!avctx->slice_count){ - slice_count = (*buf++) + 1; - slices_hdr = buf + 4; - buf += 8 * slice_count; - buf_size -= 1 + 8 * slice_count; - }else - slice_count = avctx->slice_count; + slice_count = (*buf++) + 1; + slices_hdr = buf + 4; + buf += 8 * slice_count; + buf_size -= 1 + 8 * slice_count; offset = get_slice_offset(avctx, slices_hdr, 0, slice_count, buf_size); //parse first slice header to check whether this frame can be decoded diff --git a/libavcodec/version_major.h b/libavcodec/version_major.h index c2f118b2620..40db213499a 100644 --- a/libavcodec/version_major.h +++ b/libavcodec/version_major.h @@ -45,6 +45,7 @@ #define FF_API_AVCODEC_CHROMA_POS (LIBAVCODEC_VERSION_MAJOR < 61) #define FF_API_VT_HWACCEL_CONTEXT (LIBAVCODEC_VERSION_MAJOR < 61) #define FF_API_AVCTX_FRAME_NUMBER (LIBAVCODEC_VERSION_MAJOR < 61) +#define FF_API_SLICE_OFFSET (LIBAVCODEC_VERSION_MAJOR < 61) // reminder to remove CrystalHD decoders on next major bump #define FF_CODEC_CRYSTAL_HD (LIBAVCODEC_VERSION_MAJOR < 61) From 3153c441e1d980ff9931ed26a0e01b4e366ac521 Mon Sep 17 00:00:00 2001 From: Nicolas Gaullier Date: Tue, 21 Feb 2023 11:12:32 +0100 Subject: [PATCH 0360/2172] avcodec/ac3: Remove unused fields Signed-off-by: Nicolas Gaullier Signed-off-by: Anton Khirnov --- libavcodec/ac3dec.h | 2 -- 1 file changed, 2 deletions(-) diff --git a/libavcodec/ac3dec.h b/libavcodec/ac3dec.h index 0829f4b40de..98de7b5abff 100644 --- a/libavcodec/ac3dec.h +++ b/libavcodec/ac3dec.h @@ -90,7 +90,6 @@ typedef struct AC3DecodeContext { int lfe_on; ///< lfe channel in use int dialog_normalization[2]; ///< dialog level in dBFS (dialnorm) int compression_exists[2]; ///< compression field is valid for frame (compre) - int compression_gain[2]; ///< gain to apply for heavy compression (compr) int channel_map; ///< custom channel map (chanmap) int preferred_downmix; ///< Preferred 2-channel downmix mode (dmixmod) int center_mix_level; ///< Center mix level index @@ -100,7 +99,6 @@ typedef struct AC3DecodeContext { int lfe_mix_level_exists; ///< indicates if lfemixlevcod is specified (lfemixlevcode) int lfe_mix_level; ///< LFE mix level index (lfemixlevcod) int eac3; ///< indicates if current frame is E-AC-3 - int eac3_frame_dependent_found; ///< bitstream has E-AC-3 dependent frame(s) int eac3_subsbtreamid_found; ///< bitstream has E-AC-3 additional substream(s) int eac3_extension_type_a; ///< bitstream has E-AC-3 extension type A enabled frame(s) int dolby_surround_mode; ///< dolby surround mode (dsurmod) From ad17e2922482fd34b056d87e46097abb2c4996ce Mon Sep 17 00:00:00 2001 From: Stefano Sabatini Date: Wed, 1 Mar 2023 01:00:17 +0100 Subject: [PATCH 0361/2172] lavfi/buffersrc: issue more specific error in case of invalid parameters --- libavfilter/buffersrc.c | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/libavfilter/buffersrc.c b/libavfilter/buffersrc.c index ba17450b937..a1740da0546 100644 --- a/libavfilter/buffersrc.c +++ b/libavfilter/buffersrc.c @@ -273,9 +273,16 @@ static av_cold int init_video(AVFilterContext *ctx) { BufferSourceContext *c = ctx->priv; - if (c->pix_fmt == AV_PIX_FMT_NONE || !c->w || !c->h || - av_q2d(c->time_base) <= 0) { - av_log(ctx, AV_LOG_ERROR, "Invalid parameters provided.\n"); + if (c->pix_fmt == AV_PIX_FMT_NONE) { + av_log(ctx, AV_LOG_ERROR, "Unspecified pixel format\n"); + return AVERROR(EINVAL); + } + if (c->w <= 0 || c->h <= 0) { + av_log(ctx, AV_LOG_ERROR, "Invalid size %dx%d\n", c->w, c->h); + return AVERROR(EINVAL); + } + if (av_q2d(c->time_base) <= 0) { + av_log(ctx, AV_LOG_ERROR, "Invalid time base %d/%d\n", c->time_base.num, c->time_base.den); return AVERROR(EINVAL); } From adca877acb930faf1a5d686af93b9f657cebf1b5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Ekstr=C3=B6m?= Date: Sat, 4 Feb 2023 21:21:10 +0200 Subject: [PATCH 0362/2172] avformat/mov: check that pcmC box is of the expected type MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit As per 23003-5:2020 this box is defined as PCMConfig extends FullBox(‘pcmC’, version = 0, 0), which means that version is 0 and flags should be zero. --- libavformat/mov.c | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/libavformat/mov.c b/libavformat/mov.c index 8af564ed610..cdd44a9e440 100644 --- a/libavformat/mov.c +++ b/libavformat/mov.c @@ -1590,14 +1590,23 @@ static int mov_read_enda(MOVContext *c, AVIOContext *pb, MOVAtom atom) static int mov_read_pcmc(MOVContext *c, AVIOContext *pb, MOVAtom atom) { int format_flags; + int version, flags; if (atom.size < 6) { av_log(c->fc, AV_LOG_ERROR, "Empty pcmC box\n"); return AVERROR_INVALIDDATA; } - avio_r8(pb); // version - avio_rb24(pb); // flags + version = avio_r8(pb); + flags = avio_rb24(pb); + + if (version != 0 || flags != 0) { + av_log(c->fc, AV_LOG_ERROR, + "Unsupported 'pcmC' box with version %d, flags: %x", + version, flags); + return AVERROR_INVALIDDATA; + } + format_flags = avio_r8(pb); if (format_flags == 1) // indicates little-endian format. If not present, big-endian format is used set_last_stream_little_endian(c->fc); From 912ac82a3c769792ad992534f3df9b0a549ff827 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Ekstr=C3=B6m?= Date: Sat, 4 Feb 2023 21:26:01 +0200 Subject: [PATCH 0363/2172] avformat/mov: base pcmC endianness on just the LSB As per 23003-5:2020, the rest of the bits are reserved, and thus in the future they may be utilized for something else. Quote: format_flags is a field of flags that modify the default PCM sample format. Undefined flags are reserved and shall be zero. The following flag is defined: 0x01 indicates little-endian format. If not present, big-endian format is used. --- libavformat/mov.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavformat/mov.c b/libavformat/mov.c index cdd44a9e440..a9911c0f799 100644 --- a/libavformat/mov.c +++ b/libavformat/mov.c @@ -1608,7 +1608,7 @@ static int mov_read_pcmc(MOVContext *c, AVIOContext *pb, MOVAtom atom) } format_flags = avio_r8(pb); - if (format_flags == 1) // indicates little-endian format. If not present, big-endian format is used + if (format_flags & 1) // indicates little-endian format. If not present, big-endian format is used set_last_stream_little_endian(c->fc); return 0; From 2fd86d9afadf9b62c2e900505558141a35e2ed6f Mon Sep 17 00:00:00 2001 From: James Almer Date: Thu, 2 Mar 2023 10:00:02 -0300 Subject: [PATCH 0364/2172] avfilter/graphparser: fix filter instance name when an id is provided Restores the behavior of naming the instance filter@id, which was accidentally changed to simpy id in commit f17051eaae. Fixes ticket #10226. Signed-off-by: James Almer --- libavfilter/graphparser.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/libavfilter/graphparser.c b/libavfilter/graphparser.c index 8e12416ccb6..4347131fad1 100644 --- a/libavfilter/graphparser.c +++ b/libavfilter/graphparser.c @@ -532,8 +532,7 @@ int avfilter_graph_segment_create_filters(AVFilterGraphSegment *seg, int flags) for (size_t j = 0; j < ch->nb_filters; j++) { AVFilterParams *p = ch->filters[j]; const AVFilter *f = avfilter_get_by_name(p->filter_name); - char inst_name[30], *name = p->instance_name ? p->instance_name : - inst_name; + char name[64]; // skip already processed filters if (p->filter || !p->filter_name) @@ -546,7 +545,9 @@ int avfilter_graph_segment_create_filters(AVFilterGraphSegment *seg, int flags) } if (!p->instance_name) - snprintf(inst_name, sizeof(inst_name), "Parsed_%s_%zu", f->name, idx); + snprintf(name, sizeof(name), "Parsed_%s_%zu", f->name, idx); + else + snprintf(name, sizeof(name), "%s@%s", f->name, p->instance_name); p->filter = avfilter_graph_alloc_filter(seg->graph, f, name); if (!p->filter) From e50a02b0f674f050e8b0e6e07342e27d1fc872e0 Mon Sep 17 00:00:00 2001 From: James Darnley Date: Fri, 17 Feb 2023 14:08:10 +0100 Subject: [PATCH 0365/2172] tests: actually test yadif's 10 and 16-bit functions --- tests/fate/filter-video.mak | 4 +-- tests/ref/fate/filter-yadif10 | 60 +++++++++++++++++------------------ tests/ref/fate/filter-yadif16 | 60 +++++++++++++++++------------------ 3 files changed, 62 insertions(+), 62 deletions(-) diff --git a/tests/fate/filter-video.mak b/tests/fate/filter-video.mak index 63873a7a077..704087b8359 100644 --- a/tests/fate/filter-video.mak +++ b/tests/fate/filter-video.mak @@ -16,8 +16,8 @@ fate-filter-yadif-mode0: CMD = framecrc -flags bitexact -idct simple -i $(TARGET fate-filter-yadif-mode1: CMD = framecrc -flags bitexact -idct simple -i $(TARGET_SAMPLES)/mpeg2/mpeg2_field_encoding.ts -frames:v 59 -vf yadif=1 FATE_YADIF-$(call FILTERDEMDEC, YADIF SCALE, MPEGTS, MPEG2VIDEO) += fate-filter-yadif10 fate-filter-yadif16 -fate-filter-yadif10: CMD = framecrc -flags bitexact -idct simple -i $(TARGET_SAMPLES)/mpeg2/mpeg2_field_encoding.ts -flags bitexact -pix_fmt yuv420p10le -frames:v 30 -vf yadif=0,scale -fate-filter-yadif16: CMD = framecrc -flags bitexact -idct simple -i $(TARGET_SAMPLES)/mpeg2/mpeg2_field_encoding.ts -flags bitexact -pix_fmt yuv420p16le -frames:v 30 -vf yadif=0,scale +fate-filter-yadif10: CMD = framecrc -flags bitexact -idct simple -i $(TARGET_SAMPLES)/mpeg2/mpeg2_field_encoding.ts -flags bitexact -pix_fmt yuv420p10le -frames:v 30 -vf scale,yadif=0 +fate-filter-yadif16: CMD = framecrc -flags bitexact -idct simple -i $(TARGET_SAMPLES)/mpeg2/mpeg2_field_encoding.ts -flags bitexact -pix_fmt yuv420p16le -frames:v 30 -vf scale,yadif=0 FATE_FILTER_SAMPLES-yes += $(FATE_YADIF-yes) diff --git a/tests/ref/fate/filter-yadif10 b/tests/ref/fate/filter-yadif10 index 28e799fc1f0..1a8063fee9c 100644 --- a/tests/ref/fate/filter-yadif10 +++ b/tests/ref/fate/filter-yadif10 @@ -3,33 +3,33 @@ #codec_id 0: rawvideo #dimensions 0: 720x576 #sar 0: 16/15 -0, 9, 9, 1, 1244160, 0xe0c2231b -0, 10, 10, 1, 1244160, 0xdc7caa43 -0, 11, 11, 1, 1244160, 0x52c4dfbf -0, 12, 12, 1, 1244160, 0x7c577f07 -0, 13, 13, 1, 1244160, 0x5b6ad7ce -0, 14, 14, 1, 1244160, 0x6f15ce76 -0, 15, 15, 1, 1244160, 0xf120034a -0, 16, 16, 1, 1244160, 0x9c65ba64 -0, 17, 17, 1, 1244160, 0x883b237e -0, 18, 18, 1, 1244160, 0xb8292e0d -0, 19, 19, 1, 1244160, 0xbc392721 -0, 20, 20, 1, 1244160, 0x7cd82ec9 -0, 21, 21, 1, 1244160, 0x167325eb -0, 22, 22, 1, 1244160, 0x49bafa73 -0, 23, 23, 1, 1244160, 0xe1ff6dbf -0, 24, 24, 1, 1244160, 0x85f710b6 -0, 25, 25, 1, 1244160, 0xd1fd4cdb -0, 26, 26, 1, 1244160, 0xafee03c5 -0, 27, 27, 1, 1244160, 0x566be070 -0, 28, 28, 1, 1244160, 0xb6abbd01 -0, 29, 29, 1, 1244160, 0xa98f38fd -0, 30, 30, 1, 1244160, 0x00f4736b -0, 31, 31, 1, 1244160, 0x6b0f9dd2 -0, 32, 32, 1, 1244160, 0x15810b92 -0, 33, 33, 1, 1244160, 0x0b516465 -0, 34, 34, 1, 1244160, 0x927d15e6 -0, 35, 35, 1, 1244160, 0xd102f2bf -0, 36, 36, 1, 1244160, 0xdd8b3b20 -0, 37, 37, 1, 1244160, 0x229ac529 -0, 38, 38, 1, 1244160, 0xf844e0a2 +0, 9, 9, 1, 1244160, 0x67910b3d +0, 10, 10, 1, 1244160, 0xdbb80927 +0, 11, 11, 1, 1244160, 0xd5d4f27a +0, 12, 12, 1, 1244160, 0xde270630 +0, 13, 13, 1, 1244160, 0xe57833cc +0, 14, 14, 1, 1244160, 0xc806eabd +0, 15, 15, 1, 1244160, 0xe041958a +0, 16, 16, 1, 1244160, 0x0007fdc7 +0, 17, 17, 1, 1244160, 0xed25afda +0, 18, 18, 1, 1244160, 0x43f8e068 +0, 19, 19, 1, 1244160, 0xd95b763a +0, 20, 20, 1, 1244160, 0xf99cacdb +0, 21, 21, 1, 1244160, 0x3c33ec50 +0, 22, 22, 1, 1244160, 0xf5260151 +0, 23, 23, 1, 1244160, 0x88e9f2e9 +0, 24, 24, 1, 1244160, 0x104cfe20 +0, 25, 25, 1, 1244160, 0x804d6a33 +0, 26, 26, 1, 1244160, 0x8c668008 +0, 27, 27, 1, 1244160, 0x63cf270a +0, 28, 28, 1, 1244160, 0xc526e89a +0, 29, 29, 1, 1244160, 0xe318e4d4 +0, 30, 30, 1, 1244160, 0x7c6b63a3 +0, 31, 31, 1, 1244160, 0x40deffdd +0, 32, 32, 1, 1244160, 0xd256c2a9 +0, 33, 33, 1, 1244160, 0xc44d9f6b +0, 34, 34, 1, 1244160, 0xab9c9f60 +0, 35, 35, 1, 1244160, 0xba3caff9 +0, 36, 36, 1, 1244160, 0x9efcf7d9 +0, 37, 37, 1, 1244160, 0x150d3dd5 +0, 38, 38, 1, 1244160, 0xf0dca6ac diff --git a/tests/ref/fate/filter-yadif16 b/tests/ref/fate/filter-yadif16 index 0c856ab37a8..ca700239ae6 100644 --- a/tests/ref/fate/filter-yadif16 +++ b/tests/ref/fate/filter-yadif16 @@ -3,33 +3,33 @@ #codec_id 0: rawvideo #dimensions 0: 720x576 #sar 0: 16/15 -0, 9, 9, 1, 1244160, 0x24eeca92 -0, 10, 10, 1, 1244160, 0x96b8e646 -0, 11, 11, 1, 1244160, 0xc11fc5da -0, 12, 12, 1, 1244160, 0xc15f9168 -0, 13, 13, 1, 1244160, 0xba1c738e -0, 14, 14, 1, 1244160, 0x56b59681 -0, 15, 15, 1, 1244160, 0x14ad778d -0, 16, 16, 1, 1244160, 0x18dc584b -0, 17, 17, 1, 1244160, 0xe4c11635 -0, 18, 18, 1, 1244160, 0x85cc0dc0 -0, 19, 19, 1, 1244160, 0x2d6a65a4 -0, 20, 20, 1, 1244160, 0x4054d8f9 -0, 21, 21, 1, 1244160, 0xebce97d3 -0, 22, 22, 1, 1244160, 0x79437c93 -0, 23, 23, 1, 1244160, 0x6438ed40 -0, 24, 24, 1, 1244160, 0x9121928c -0, 25, 25, 1, 1244160, 0xb8731075 -0, 26, 26, 1, 1244160, 0xfb01310e -0, 27, 27, 1, 1244160, 0x97be489c -0, 28, 28, 1, 1244160, 0xa5b4b8aa -0, 29, 29, 1, 1244160, 0x00a7ae0f -0, 30, 30, 1, 1244160, 0x514fa990 -0, 31, 31, 1, 1244160, 0xd73c3f66 -0, 32, 32, 1, 1244160, 0x3602e6c3 -0, 33, 33, 1, 1244160, 0xa16ad8ab -0, 34, 34, 1, 1244160, 0xdf11ac80 -0, 35, 35, 1, 1244160, 0x1f084421 -0, 36, 36, 1, 1244160, 0x9fc1bd32 -0, 37, 37, 1, 1244160, 0x1389f6cf -0, 38, 38, 1, 1244160, 0x6fc5f0e5 +0, 9, 9, 1, 1244160, 0x4dc19e70 +0, 10, 10, 1, 1244160, 0x96235156 +0, 11, 11, 1, 1244160, 0x4f8e700a +0, 12, 12, 1, 1244160, 0xcfae5b9e +0, 13, 13, 1, 1244160, 0x05885981 +0, 14, 14, 1, 1244160, 0x2eeade5e +0, 15, 15, 1, 1244160, 0xd208cb2c +0, 16, 16, 1, 1244160, 0xdbf4419e +0, 17, 17, 1, 1244160, 0xa4221dd0 +0, 18, 18, 1, 1244160, 0x18562eed +0, 19, 19, 1, 1244160, 0x146f4d85 +0, 20, 20, 1, 1244160, 0x024dcc1f +0, 21, 21, 1, 1244160, 0xd5b5e7c2 +0, 22, 22, 1, 1244160, 0x4961324b +0, 23, 23, 1, 1244160, 0xb0bba154 +0, 24, 24, 1, 1244160, 0xeba2ca02 +0, 25, 25, 1, 1244160, 0x288bd802 +0, 26, 26, 1, 1244160, 0x8979b9dd +0, 27, 27, 1, 1244160, 0x0b1b3a04 +0, 28, 28, 1, 1244160, 0xdefab084 +0, 29, 29, 1, 1244160, 0xf2bf0d16 +0, 30, 30, 1, 1244160, 0xa080b06c +0, 31, 31, 1, 1244160, 0xa9d79809 +0, 32, 32, 1, 1244160, 0xb89287e7 +0, 33, 33, 1, 1244160, 0xa3131327 +0, 34, 34, 1, 1244160, 0x43640034 +0, 35, 35, 1, 1244160, 0x714e1780 +0, 36, 36, 1, 1244160, 0x91ade9c5 +0, 37, 37, 1, 1244160, 0x0ea017da +0, 38, 38, 1, 1244160, 0xa81a5fef From b10eabdab3e2bd5d4d8e66064dda63185d6829b4 Mon Sep 17 00:00:00 2001 From: xufuji456 <839789740@qq.com> Date: Mon, 6 Mar 2023 10:18:01 +0800 Subject: [PATCH 0366/2172] codec/arm/hevcdsp_idct_neon: remove duplicate mov MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Martin Storsjö --- libavcodec/arm/hevcdsp_idct_neon.S | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/libavcodec/arm/hevcdsp_idct_neon.S b/libavcodec/arm/hevcdsp_idct_neon.S index 41ca3b83a8b..66ed1c67852 100644 --- a/libavcodec/arm/hevcdsp_idct_neon.S +++ b/libavcodec/arm/hevcdsp_idct_neon.S @@ -877,33 +877,27 @@ function func_tr_32x4_\name vld1.s16 {q0}, [r9, :128]! vld1.s16 {q1}, [r9, :128] add r4, sp, #2048 + mov r2, #64 + mov r8, #-64 bl tr_block1 mov r1, r11 - mov r2, #64 - mov r8, #-64 add r3, r11, #(56 + 3 * 64) scale_store \shift bl tr_block2 add r1, r11, #8 add r3, r11, #(48 + 3 * 64) - mov r2, #64 - mov r8, #-64 scale_store \shift bl tr_block3 add r1, r11, #16 add r3, r11, #(40 + 3 * 64) - mov r2, #64 - mov r8, #-64 scale_store \shift bl tr_block4 add r1, r11, #24 add r3, r11, #(32 + 3 * 64) - mov r2, #64 - mov r8, #-64 scale_store \shift bx r10 From f9620d74cd49c35223304ba41e28be6144e45783 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Storsj=C3=B6?= Date: Sun, 5 Mar 2023 23:36:53 +0200 Subject: [PATCH 0367/2172] vulkan: Fix win/i386 calling convention MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This fixes the following error when compiling with a modern version of Clang for Windows/i386: src/libavutil/hwcontext_vulkan.c:738:32: error: incompatible function pointer types initializing 'PFN_vkDebugUtilsMessengerCallbackEXT' (aka 'unsigned int (*)(enum VkDebugUtilsMessageSeverityFlagBitsEXT, unsigned int, const struct VkDebugUtilsMessengerCallbackDataEXT *, void *) __attribute__((stdcall))') with an expression of type 'VkBool32 (VkDebugUtilsMessageSeverityFlagBitsEXT, VkDebugUtilsMessageTypeFlagsEXT, const VkDebugUtilsMessengerCallbackDataEXT *, void *)' (aka 'unsigned int (enum VkDebugUtilsMessageSeverityFlagBitsEXT, unsigned int, const struct VkDebugUtilsMessengerCallbackDataEXT *, void *)') [-Wincompatible-function-pointer-types] .pfnUserCallback = vk_dbg_callback, ^~~~~~~~~~~~~~~ Signed-off-by: Martin Storsjö --- libavutil/hwcontext_vulkan.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/libavutil/hwcontext_vulkan.c b/libavutil/hwcontext_vulkan.c index 2a9b5f4aac6..5b86aa65e90 100644 --- a/libavutil/hwcontext_vulkan.c +++ b/libavutil/hwcontext_vulkan.c @@ -401,10 +401,10 @@ static const char *vk_ret2str(VkResult res) #undef CASE } -static VkBool32 vk_dbg_callback(VkDebugUtilsMessageSeverityFlagBitsEXT severity, - VkDebugUtilsMessageTypeFlagsEXT messageType, - const VkDebugUtilsMessengerCallbackDataEXT *data, - void *priv) +static VkBool32 VKAPI_CALL vk_dbg_callback(VkDebugUtilsMessageSeverityFlagBitsEXT severity, + VkDebugUtilsMessageTypeFlagsEXT messageType, + const VkDebugUtilsMessengerCallbackDataEXT *data, + void *priv) { int l; AVHWDeviceContext *ctx = priv; From cc76e8340d28438c1ac56ee7dfd774d25e944264 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kacper=20Michaj=C5=82ow?= Date: Thu, 2 Mar 2023 17:27:30 +0100 Subject: [PATCH 0368/2172] lavu/vulkan: fix handle type for 32-bit targets MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fixes compilation with clang which errors out on Wint-conversion. Signed-off-by: Kacper Michajłow Signed-off-by: Martin Storsjö --- libavutil/hwcontext_vulkan.c | 2 +- libavutil/vulkan.h | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/libavutil/hwcontext_vulkan.c b/libavutil/hwcontext_vulkan.c index 5b86aa65e90..ffd4f5dec4e 100644 --- a/libavutil/hwcontext_vulkan.c +++ b/libavutil/hwcontext_vulkan.c @@ -1149,7 +1149,7 @@ static void free_exec_ctx(AVHWFramesContext *hwfc, VulkanExecCtx *cmd) av_freep(&cmd->queues); av_freep(&cmd->bufs); - cmd->pool = NULL; + cmd->pool = VK_NULL_HANDLE; } static VkCommandBuffer get_buf_exec_ctx(AVHWFramesContext *hwfc, VulkanExecCtx *cmd) diff --git a/libavutil/vulkan.h b/libavutil/vulkan.h index d1ea1e24fb8..90922c6cf3d 100644 --- a/libavutil/vulkan.h +++ b/libavutil/vulkan.h @@ -122,7 +122,11 @@ typedef struct FFVulkanPipeline { VkDescriptorSetLayout *desc_layout; VkDescriptorPool desc_pool; VkDescriptorSet *desc_set; +#if VK_USE_64_BIT_PTR_DEFINES == 1 void **desc_staging; +#else + uint64_t *desc_staging; +#endif VkDescriptorSetLayoutBinding **desc_binding; VkDescriptorUpdateTemplate *desc_template; int *desc_set_initialized; From b465e6fed0f7bc1b9a0bf934c8674bc56cb82e36 Mon Sep 17 00:00:00 2001 From: James Almer Date: Fri, 3 Mar 2023 13:19:02 -0300 Subject: [PATCH 0369/2172] avcodec/libdav1d: export Dynamic HDR10+ frame metadata As defined in https://aomediacodec.github.io/av1-hdr10plus/ Reviewed-by: Ronald S. Bultje Signed-off-by: James Almer --- libavcodec/libdav1d.c | 36 ++++++++++++++++++++++++++++++++---- 1 file changed, 32 insertions(+), 4 deletions(-) diff --git a/libavcodec/libdav1d.c b/libavcodec/libdav1d.c index 2488a709c72..1f0c36fc552 100644 --- a/libavcodec/libdav1d.c +++ b/libavcodec/libdav1d.c @@ -33,6 +33,7 @@ #include "bytestream.h" #include "codec_internal.h" #include "decode.h" +#include "dynamic_hdr10_plus.h" #include "internal.h" #define FF_DAV1D_VERSION_AT_LEAST(x,y) \ @@ -511,12 +512,14 @@ FF_ENABLE_DEPRECATION_WARNINGS } if (p->itut_t35) { GetByteContext gb; - unsigned int user_identifier; + int provider_code; bytestream2_init(&gb, p->itut_t35->payload, p->itut_t35->payload_size); - bytestream2_skip(&gb, 1); // terminal provider code - bytestream2_skip(&gb, 1); // terminal provider oriented code - user_identifier = bytestream2_get_be32(&gb); + + provider_code = bytestream2_get_be16(&gb); + switch (provider_code) { + case 0x31: { // atsc_provider_code + uint32_t user_identifier = bytestream2_get_be32(&gb); switch (user_identifier) { case MKBETAG('G', 'A', '9', '4'): { // closed captions AVBufferRef *buf = NULL; @@ -536,6 +539,31 @@ FF_ENABLE_DEPRECATION_WARNINGS default: // ignore unsupported identifiers break; } + } + case 0x3C: { // smpte_provider_code + AVDynamicHDRPlus *hdrplus; + int provider_oriented_code = bytestream2_get_be16(&gb); + int application_identifier = bytestream2_get_byte(&gb); + + if (p->itut_t35->country_code != 0xB5 || + provider_oriented_code != 1 || application_identifier != 4) + break; + + hdrplus = av_dynamic_hdr_plus_create_side_data(frame); + if (!hdrplus) { + res = AVERROR(ENOMEM); + goto fail; + } + + res = ff_parse_itu_t_t35_to_dynamic_hdr10_plus(hdrplus, gb.buffer, + bytestream2_get_bytes_left(&gb)); + if (res < 0) + goto fail; + break; + } + default: // ignore unsupported provider codes + break; + } } if (p->frame_hdr->film_grain.present && (!dav1d->apply_grain || (c->export_side_data & AV_CODEC_EXPORT_DATA_FILM_GRAIN))) { From 7dc0944ce2a99549351e1be619ec2edec6d2acf8 Mon Sep 17 00:00:00 2001 From: James Almer Date: Fri, 3 Mar 2023 13:25:31 -0300 Subject: [PATCH 0370/2172] avcodec/libdav1d: reindent after previous commit Signed-off-by: James Almer --- libavcodec/libdav1d.c | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/libavcodec/libdav1d.c b/libavcodec/libdav1d.c index 1f0c36fc552..eb1225ea1a0 100644 --- a/libavcodec/libdav1d.c +++ b/libavcodec/libdav1d.c @@ -519,26 +519,26 @@ FF_ENABLE_DEPRECATION_WARNINGS provider_code = bytestream2_get_be16(&gb); switch (provider_code) { case 0x31: { // atsc_provider_code - uint32_t user_identifier = bytestream2_get_be32(&gb); - switch (user_identifier) { - case MKBETAG('G', 'A', '9', '4'): { // closed captions - AVBufferRef *buf = NULL; + uint32_t user_identifier = bytestream2_get_be32(&gb); + switch (user_identifier) { + case MKBETAG('G', 'A', '9', '4'): { // closed captions + AVBufferRef *buf = NULL; - res = ff_parse_a53_cc(&buf, gb.buffer, bytestream2_get_bytes_left(&gb)); - if (res < 0) - goto fail; - if (!res) - break; + res = ff_parse_a53_cc(&buf, gb.buffer, bytestream2_get_bytes_left(&gb)); + if (res < 0) + goto fail; + if (!res) + break; - if (!av_frame_new_side_data_from_buf(frame, AV_FRAME_DATA_A53_CC, buf)) - av_buffer_unref(&buf); + if (!av_frame_new_side_data_from_buf(frame, AV_FRAME_DATA_A53_CC, buf)) + av_buffer_unref(&buf); - c->properties |= FF_CODEC_PROPERTY_CLOSED_CAPTIONS; - break; - } - default: // ignore unsupported identifiers - break; - } + c->properties |= FF_CODEC_PROPERTY_CLOSED_CAPTIONS; + break; + } + default: // ignore unsupported identifiers + break; + } } case 0x3C: { // smpte_provider_code AVDynamicHDRPlus *hdrplus; From f758d4fcb93b77115b6d971859f5bee56f8070b8 Mon Sep 17 00:00:00 2001 From: rcombs Date: Fri, 13 Jan 2023 11:25:49 -0600 Subject: [PATCH 0371/2172] lavf/matroska: add support for ARIB captions --- libavformat/matroska.c | 1 + libavformat/matroskadec.c | 30 ++++++++++++++++++++++++++++++ libavformat/matroskaenc.c | 23 +++++++++++++++++++++++ 3 files changed, 54 insertions(+) diff --git a/libavformat/matroska.c b/libavformat/matroska.c index 90d94b65bf7..79b2d099841 100644 --- a/libavformat/matroska.c +++ b/libavformat/matroska.c @@ -76,6 +76,7 @@ const CodecTags ff_mkv_codec_tags[]={ {"S_DVBSUB" , AV_CODEC_ID_DVB_SUBTITLE}, {"S_HDMV/PGS" , AV_CODEC_ID_HDMV_PGS_SUBTITLE}, {"S_HDMV/TEXTST" , AV_CODEC_ID_HDMV_TEXT_SUBTITLE}, + {"S_ARIBSUB" , AV_CODEC_ID_ARIB_CAPTION}, {"V_AV1" , AV_CODEC_ID_AV1}, {"V_AVS2" , AV_CODEC_ID_AVS2}, diff --git a/libavformat/matroskadec.c b/libavformat/matroskadec.c index d582f566a21..3a888e3ada9 100644 --- a/libavformat/matroskadec.c +++ b/libavformat/matroskadec.c @@ -50,6 +50,7 @@ #include "libavutil/time_internal.h" #include "libavutil/spherical.h" +#include "libavcodec/avcodec.h" #include "libavcodec/bytestream.h" #include "libavcodec/flac.h" #include "libavcodec/mpeg4audio.h" @@ -2813,6 +2814,35 @@ static int matroska_parse_tracks(AVFormatContext *s) /* we don't need any value stored in CodecPrivate. make sure that it's not exported as extradata. */ track->codec_priv.size = 0; + } else if (codec_id == AV_CODEC_ID_ARIB_CAPTION && track->codec_priv.size == 3) { + int component_tag = track->codec_priv.data[0]; + int data_component_id = AV_RB16(track->codec_priv.data + 1); + + switch (data_component_id) { + case 0x0008: + // [0x30..0x37] are component tags utilized for + // non-mobile captioning service ("profile A"). + if (component_tag >= 0x30 && component_tag <= 0x37) { + st->codecpar->profile = FF_PROFILE_ARIB_PROFILE_A; + } + break; + case 0x0012: + // component tag 0x87 signifies a mobile/partial reception + // (1seg) captioning service ("profile C"). + if (component_tag == 0x87) { + st->codecpar->profile = FF_PROFILE_ARIB_PROFILE_C; + } + break; + default: + break; + } + + if (st->codecpar->profile == FF_PROFILE_UNKNOWN) + av_log(matroska->ctx, AV_LOG_WARNING, + "Unknown ARIB caption profile utilized: %02x / %04x\n", + component_tag, data_component_id); + + track->codec_priv.size = 0; } track->codec_priv.size -= extradata_offset; diff --git a/libavformat/matroskaenc.c b/libavformat/matroskaenc.c index 113541bd9a2..954b7d828f2 100644 --- a/libavformat/matroskaenc.c +++ b/libavformat/matroskaenc.c @@ -58,6 +58,7 @@ #include "libavutil/stereo3d.h" #include "libavcodec/av1.h" +#include "libavcodec/avcodec.h" #include "libavcodec/codec_desc.h" #include "libavcodec/xiph.h" #include "libavcodec/mpeg4audio.h" @@ -1142,6 +1143,27 @@ static int mkv_assemble_native_codecprivate(AVFormatContext *s, AVIOContext *dyn else *size_to_reserve = MAX_PCE_SIZE; break; + case AV_CODEC_ID_ARIB_CAPTION: { + unsigned stream_identifier, data_component_id; + switch (par->profile) { + case FF_PROFILE_ARIB_PROFILE_A: + stream_identifier = 0x30; + data_component_id = 0x0008; + break; + case FF_PROFILE_ARIB_PROFILE_C: + stream_identifier = 0x87; + data_component_id = 0x0012; + break; + default: + av_log(s, AV_LOG_ERROR, + "Unset/unknown ARIB caption profile %d utilized!\n", + par->profile); + return AVERROR_INVALIDDATA; + } + avio_w8(dyn_cp, stream_identifier); + avio_wb16(dyn_cp, data_component_id); + break; + } #endif default: if (CONFIG_MATROSKA_MUXER && par->codec_id == AV_CODEC_ID_PRORES && @@ -3274,6 +3296,7 @@ static const AVCodecTag additional_subtitle_tags[] = { { AV_CODEC_ID_DVB_SUBTITLE, 0xFFFFFFFF }, { AV_CODEC_ID_DVD_SUBTITLE, 0xFFFFFFFF }, { AV_CODEC_ID_HDMV_PGS_SUBTITLE, 0xFFFFFFFF }, + { AV_CODEC_ID_ARIB_CAPTION, 0xFFFFFFFF }, { AV_CODEC_ID_NONE, 0xFFFFFFFF } }; From 05ea0457fc50555287ecc2e304bc42dd0e05481b Mon Sep 17 00:00:00 2001 From: jackarain Date: Fri, 3 Mar 2023 20:31:39 +0800 Subject: [PATCH 0372/2172] avformat/udp: check for memory allocation failure when setting localaddr Signed-off-by: jackarain Signed-off-by: Marton Balint --- libavformat/udp.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/libavformat/udp.c b/libavformat/udp.c index e8980b29d82..909213a4677 100644 --- a/libavformat/udp.c +++ b/libavformat/udp.c @@ -740,6 +740,10 @@ static int udp_open(URLContext *h, const char *uri, int flags) if (av_find_info_tag(buf, sizeof(buf), "localaddr", p)) { av_freep(&s->localaddr); s->localaddr = av_strdup(buf); + if (!s->localaddr) { + ret = AVERROR(ENOMEM); + goto fail; + } } if (av_find_info_tag(buf, sizeof(buf), "sources", p)) { if ((ret = ff_ip_parse_sources(h, buf, &s->filters)) < 0) From 4e3916dbce629a411ba9d04bf395c8f80aa681fa Mon Sep 17 00:00:00 2001 From: jackarain Date: Fri, 3 Mar 2023 20:47:59 +0800 Subject: [PATCH 0373/2172] avformat/tls: check for memory allocation failure when setting options Signed-off-by: jackarain Signed-off-by: Marton Balint --- libavformat/tls.c | 26 ++++++++++++++++++++------ 1 file changed, 20 insertions(+), 6 deletions(-) diff --git a/libavformat/tls.c b/libavformat/tls.c index e42d399862b..33e8ec384f8 100644 --- a/libavformat/tls.c +++ b/libavformat/tls.c @@ -30,15 +30,18 @@ #include "libavutil/opt.h" #include "libavutil/parseutils.h" -static void set_options(TLSShared *c, const char *uri) +static int set_options(TLSShared *c, const char *uri) { char buf[1024]; const char *p = strchr(uri, '?'); if (!p) - return; + return 0; - if (!c->ca_file && av_find_info_tag(buf, sizeof(buf), "cafile", p)) + if (!c->ca_file && av_find_info_tag(buf, sizeof(buf), "cafile", p)) { c->ca_file = av_strdup(buf); + if (!c->ca_file) + return AVERROR(ENOMEM); + } if (!c->verify && av_find_info_tag(buf, sizeof(buf), "verify", p)) { char *endptr = NULL; @@ -47,11 +50,19 @@ static void set_options(TLSShared *c, const char *uri) c->verify = 1; } - if (!c->cert_file && av_find_info_tag(buf, sizeof(buf), "cert", p)) + if (!c->cert_file && av_find_info_tag(buf, sizeof(buf), "cert", p)) { c->cert_file = av_strdup(buf); + if (!c->cert_file) + return AVERROR(ENOMEM); + } - if (!c->key_file && av_find_info_tag(buf, sizeof(buf), "key", p)) + if (!c->key_file && av_find_info_tag(buf, sizeof(buf), "key", p)) { c->key_file = av_strdup(buf); + if (!c->key_file) + return AVERROR(ENOMEM); + } + + return 0; } int ff_tls_open_underlying(TLSShared *c, URLContext *parent, const char *uri, AVDictionary **options) @@ -63,8 +74,11 @@ int ff_tls_open_underlying(TLSShared *c, URLContext *parent, const char *uri, AV const char *proxy_path; char *env_http_proxy, *env_no_proxy; int use_proxy; + int ret; - set_options(c, uri); + ret = set_options(c, uri); + if (ret < 0) + return ret; if (c->listen) snprintf(opts, sizeof(opts), "?listen=1"); From 6f1c00695973b48d5cb7ed574577634634f8a084 Mon Sep 17 00:00:00 2001 From: "Michael J. Walsh" Date: Fri, 3 Mar 2023 16:24:02 +0000 Subject: [PATCH 0374/2172] avformat/http: cookie path attribute should be optional not compulsory The path attribute in the Set-Cookie header is optional but treated by ffmpeg as being compulsory. Signed-off-by: Michael J. Walsh Signed-off-by: Marton Balint --- libavformat/http.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libavformat/http.c b/libavformat/http.c index 7bce8215354..0817aafb5b2 100644 --- a/libavformat/http.c +++ b/libavformat/http.c @@ -1293,9 +1293,9 @@ static int get_cookies(HTTPContext *s, char **cookies, const char *path, goto skip_cookie; } - // ensure this cookie matches the path + // if a cookie path is provided, ensure the request path is within that path e = av_dict_get(cookie_params, "path", NULL, 0); - if (!e || av_strncasecmp(path, e->value, strlen(e->value))) + if (e && av_strncasecmp(path, e->value, strlen(e->value))) goto skip_cookie; // cookie parameters match, so copy the value From 8fd345f0180c655d18071d0445d797f27bb1efe7 Mon Sep 17 00:00:00 2001 From: Devin Heitmueller Date: Fri, 3 Mar 2023 16:08:13 -0500 Subject: [PATCH 0375/2172] avdevice/decklink_enc: don't take for granted that first frame to decklink output will be PTS 0 The existing code assumed that the first frame received by the decklink output would always be PTS zero. However if running in other timing modes than the default of CBR, items such as frame dropping at the beginning may result in starting at a non-zero PTS. For example, in our setup because we discard probing data and run with "-vsync 2" the first video frame scheduled to the decklink output will have a PTS around 170. Scheduling frames too far into the future will either fail or cause a backlog of frames scheduled far enough into the future that the entire pipeline will stall. Issue can be reproduced with the following command-line: ./ffmpeg -copyts -i foo.ts -f decklink -vcodec v210 -ac 2 'DeckLink Duo (4)' Keep track of the PTS of the first frame received, so that when we enable start playback we can provide that value to the decklink driver. Thanks to Marton Balint for review and suggestion to use AV_NOPTS_VALUE rather than zero for the initial value. Signed-off-by: Devin Heitmueller Signed-off-by: Marton Balint --- libavdevice/decklink_common.h | 1 + libavdevice/decklink_enc.cpp | 8 ++++++-- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/libavdevice/decklink_common.h b/libavdevice/decklink_common.h index 79d6ac5b384..088e165ee7c 100644 --- a/libavdevice/decklink_common.h +++ b/libavdevice/decklink_common.h @@ -118,6 +118,7 @@ struct decklink_ctx { /* Status */ int playback_started; + int64_t first_pts; int64_t last_pts; unsigned long frameCount; unsigned int dropped; diff --git a/libavdevice/decklink_enc.cpp b/libavdevice/decklink_enc.cpp index fb686b9032d..5a435ddc784 100644 --- a/libavdevice/decklink_enc.cpp +++ b/libavdevice/decklink_enc.cpp @@ -486,6 +486,9 @@ static int decklink_write_video_packet(AVFormatContext *avctx, AVPacket *pkt) ctx->frames_buffer_available_spots--; pthread_mutex_unlock(&ctx->mutex); + if (ctx->first_pts == AV_NOPTS_VALUE) + ctx->first_pts = pkt->pts; + /* Schedule frame for playback. */ hr = ctx->dlo->ScheduleVideoFrame((class IDeckLinkVideoFrame *) frame, pkt->pts * ctx->bmd_tb_num, @@ -505,14 +508,14 @@ static int decklink_write_video_packet(AVFormatContext *avctx, AVPacket *pkt) " Video may misbehave!\n"); /* Preroll video frames. */ - if (!ctx->playback_started && pkt->pts > ctx->frames_preroll) { + if (!ctx->playback_started && pkt->pts > (ctx->first_pts + ctx->frames_preroll)) { av_log(avctx, AV_LOG_DEBUG, "Ending audio preroll.\n"); if (ctx->audio && ctx->dlo->EndAudioPreroll() != S_OK) { av_log(avctx, AV_LOG_ERROR, "Could not end audio preroll!\n"); return AVERROR(EIO); } av_log(avctx, AV_LOG_DEBUG, "Starting scheduled playback.\n"); - if (ctx->dlo->StartScheduledPlayback(0, ctx->bmd_tb_den, 1.0) != S_OK) { + if (ctx->dlo->StartScheduledPlayback(ctx->first_pts * ctx->bmd_tb_num, ctx->bmd_tb_den, 1.0) != S_OK) { av_log(avctx, AV_LOG_ERROR, "Could not start scheduled playback!\n"); return AVERROR(EIO); } @@ -559,6 +562,7 @@ av_cold int ff_decklink_write_header(AVFormatContext *avctx) ctx->list_formats = cctx->list_formats; ctx->preroll = cctx->preroll; ctx->duplex_mode = cctx->duplex_mode; + ctx->first_pts = AV_NOPTS_VALUE; if (cctx->link > 0 && (unsigned int)cctx->link < FF_ARRAY_ELEMS(decklink_link_conf_map)) ctx->link = decklink_link_conf_map[cctx->link]; cctx->ctx = ctx; From 25d09ac0eb175fa75da7107eb2f05e5b17152ffa Mon Sep 17 00:00:00 2001 From: Devin Heitmueller Date: Fri, 3 Mar 2023 16:08:14 -0500 Subject: [PATCH 0376/2172] avdevice/decklink_enc: fix setting of last_pts to only be set for video The ff_decklink_write_packet() was always caching the last pts received, to be used when calling StopScheduledPlayback(). However because audio and video are on different timebases and the call to StopScheduledPlayback() expects the video timebase, we'll end up sending a weird value to the stop routine if the last packet received contained audio. Move the setting of last_pts to just be for the video stream. Signed-off-by: Devin Heitmueller Signed-off-by: Marton Balint --- libavdevice/decklink_enc.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libavdevice/decklink_enc.cpp b/libavdevice/decklink_enc.cpp index 5a435ddc784..573b9e687ca 100644 --- a/libavdevice/decklink_enc.cpp +++ b/libavdevice/decklink_enc.cpp @@ -441,6 +441,8 @@ static int decklink_write_video_packet(AVFormatContext *avctx, AVPacket *pkt) uint32_t buffered; HRESULT hr; + ctx->last_pts = FFMAX(ctx->last_pts, pkt->pts); + if (st->codecpar->codec_id == AV_CODEC_ID_WRAPPED_AVFRAME) { if (tmp->format != AV_PIX_FMT_UYVY422 || tmp->width != ctx->bmd_width || @@ -629,8 +631,6 @@ int ff_decklink_write_packet(AVFormatContext *avctx, AVPacket *pkt) struct decklink_ctx *ctx = (struct decklink_ctx *)cctx->ctx; AVStream *st = avctx->streams[pkt->stream_index]; - ctx->last_pts = FFMAX(ctx->last_pts, pkt->pts); - if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) return decklink_write_video_packet(avctx, pkt); else if (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) From aca7ef78cca7fbfe02cbaf51e3349e831a4a7dd6 Mon Sep 17 00:00:00 2001 From: Devin Heitmueller Date: Fri, 3 Mar 2023 16:08:15 -0500 Subject: [PATCH 0377/2172] avdevice/decklink_enc: fix unused variable compiler warnings Due to refactoring, the ctx/cctx variables are never actually used in ff_decklink_write_packet(), so just remove them. Signed-off-by: Devin Heitmueller Signed-off-by: Marton Balint --- libavdevice/decklink_enc.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/libavdevice/decklink_enc.cpp b/libavdevice/decklink_enc.cpp index 573b9e687ca..8d423f6b6e9 100644 --- a/libavdevice/decklink_enc.cpp +++ b/libavdevice/decklink_enc.cpp @@ -627,8 +627,6 @@ av_cold int ff_decklink_write_header(AVFormatContext *avctx) int ff_decklink_write_packet(AVFormatContext *avctx, AVPacket *pkt) { - struct decklink_cctx *cctx = (struct decklink_cctx *)avctx->priv_data; - struct decklink_ctx *ctx = (struct decklink_ctx *)cctx->ctx; AVStream *st = avctx->streams[pkt->stream_index]; if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) From 1a4560ce4e957f16fbfce9d5e563f3c06ded37d1 Mon Sep 17 00:00:00 2001 From: asivery Date: Tue, 27 Sep 2022 00:13:10 +0200 Subject: [PATCH 0378/2172] avformat/aea: make the AEA demuxer return EOF at the end of file instead of EIO Signed-off-by: asivery Signed-off-by: Marton Balint --- libavformat/aea.c | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/libavformat/aea.c b/libavformat/aea.c index f4b39e4f9ec..d16217381b6 100644 --- a/libavformat/aea.c +++ b/libavformat/aea.c @@ -90,13 +90,7 @@ static int aea_read_header(AVFormatContext *s) static int aea_read_packet(AVFormatContext *s, AVPacket *pkt) { - int ret = av_get_packet(s->pb, pkt, s->streams[0]->codecpar->block_align); - - pkt->stream_index = 0; - if (ret <= 0) - return AVERROR(EIO); - - return ret; + return av_get_packet(s->pb, pkt, s->streams[0]->codecpar->block_align); } const AVInputFormat ff_aea_demuxer = { From 81bc7bc52e27d592c00fb4ed39a448d18d4d42db Mon Sep 17 00:00:00 2001 From: Wang Yaqiang Date: Thu, 9 Mar 2023 17:29:12 +0800 Subject: [PATCH 0379/2172] avformat/img2dec: fix unable to find svg format when the svg resources start with " Signed-off-by: Marton Balint --- libavformat/img2dec.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/libavformat/img2dec.c b/libavformat/img2dec.c index 5a63d7c81d8..c037b6aa882 100644 --- a/libavformat/img2dec.c +++ b/libavformat/img2dec.c @@ -964,8 +964,13 @@ static int svg_probe(const AVProbeData *p) { const uint8_t *b = p->buf; const uint8_t *end = p->buf + p->buf_size; - - if (memcmp(p->buf, "= end - 5) + return 0; + if (!memcmp(b, "buf, " Date: Tue, 26 Jan 2021 16:59:16 +0100 Subject: [PATCH 0380/2172] lavu/frame: improve AVFrame.opaque[_ref] documentation Make them match each other, mention interaction with AV_CODEC_FLAG_COPY_OPAQUE. --- libavutil/frame.h | 30 +++++++++++++++++++++++------- 1 file changed, 23 insertions(+), 7 deletions(-) diff --git a/libavutil/frame.h b/libavutil/frame.h index 25802695493..4ed27cf43fe 100644 --- a/libavutil/frame.h +++ b/libavutil/frame.h @@ -470,7 +470,18 @@ typedef struct AVFrame { int quality; /** - * for some private data of the user + * Frame owner's private data. + * + * This field may be set by the code that allocates/owns the frame data. + * It is then not touched by any library functions, except: + * - it is copied to other references by av_frame_copy_props() (and hence by + * av_frame_ref()); + * - it is set to NULL when the frame is cleared by av_frame_unref() + * - on the caller's explicit request. E.g. libavcodec encoders/decoders + * will copy this field to/from @ref AVPacket "AVPackets" if the caller sets + * @ref AV_CODEC_FLAG_COPY_OPAQUE. + * + * @see opaque_ref the reference-counted analogue */ void *opaque; @@ -678,13 +689,18 @@ typedef struct AVFrame { AVBufferRef *hw_frames_ctx; /** - * AVBufferRef for free use by the API user. FFmpeg will never check the - * contents of the buffer ref. FFmpeg calls av_buffer_unref() on it when - * the frame is unreferenced. av_frame_copy_props() calls create a new - * reference with av_buffer_ref() for the target frame's opaque_ref field. + * Frame owner's private data. + * + * This field may be set by the code that allocates/owns the frame data. + * It is then not touched by any library functions, except: + * - a new reference to the underlying buffer is propagated by + * av_frame_copy_props() (and hence by av_frame_ref()); + * - it is unreferenced in av_frame_unref(); + * - on the caller's explicit request. E.g. libavcodec encoders/decoders + * will propagate a new reference to/from @ref AVPacket "AVPackets" if the + * caller sets @ref AV_CODEC_FLAG_COPY_OPAQUE. * - * This is unrelated to the opaque field, although it serves a similar - * purpose. + * @see opaque the plain pointer analogue */ AVBufferRef *opaque_ref; From f367aa5db69d5c4825b154333a309b2a53f4cb5d Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Tue, 28 Feb 2023 11:30:48 +0100 Subject: [PATCH 0381/2172] lavc/libvpxenc: drop frame_number It is not used, except to check whether the packet is valid before writing HDR metadata to the packet in storeframe(). However, that check serves no purpose, as the encoded packet is already treated as valid higher up in this function. --- libavcodec/libvpxenc.c | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/libavcodec/libvpxenc.c b/libavcodec/libvpxenc.c index 5e6467a3d04..f6a9e5c0b76 100644 --- a/libavcodec/libvpxenc.c +++ b/libavcodec/libvpxenc.c @@ -63,7 +63,6 @@ struct FrameListData { uint32_t flags; /**< flags for this frame */ uint64_t sse[4]; int have_sse; /**< true if we have pending sse[] */ - uint64_t frame_number; struct FrameListData *next; }; @@ -84,7 +83,6 @@ typedef struct VPxEncoderContext { int deadline; //i.e., RT/GOOD/BEST uint64_t sse[4]; int have_sse; /**< true if we have pending sse[] */ - uint64_t frame_number; struct FrameListData *coded_frame_list; struct FrameListData *alpha_coded_frame_list; @@ -1220,9 +1218,8 @@ static inline void cx_pktcpy(struct FrameListData *dst, dst->sz = src->data.frame.sz; dst->buf = src->data.frame.buf; dst->have_sse = 0; - /* For alt-ref frame, don't store PSNR or increment frame_number */ + /* For alt-ref frame, don't store PSNR */ if (!(dst->flags & VPX_FRAME_IS_INVISIBLE)) { - dst->frame_number = ++ctx->frame_number; dst->have_sse = ctx->have_sse; if (ctx->have_sse) { /* associate last-seen SSE to the frame. */ @@ -1232,8 +1229,6 @@ static inline void cx_pktcpy(struct FrameListData *dst, memcpy(dst->sse, ctx->sse, sizeof(dst->sse)); ctx->have_sse = 0; } - } else { - dst->frame_number = -1; /* sanity marker */ } } @@ -1289,13 +1284,11 @@ static int storeframe(AVCodecContext *avctx, struct FrameListData *cx_frame, AV_WB64(side_data, 1); memcpy(side_data + 8, alpha_cx_frame->buf, alpha_cx_frame->sz); } - if (cx_frame->frame_number != -1) { if (ctx->hdr10_plus_fifo) { int err = copy_hdr10_plus_to_pkt(ctx->hdr10_plus_fifo, pkt); if (err < 0) return err; } - } return pkt->size; } From 31fc61fb0c79be578bcb9b919e675e2540ceb652 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Tue, 28 Feb 2023 11:30:48 +0100 Subject: [PATCH 0382/2172] lavc/libvpxenc: reindent --- libavcodec/libvpxenc.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/libavcodec/libvpxenc.c b/libavcodec/libvpxenc.c index f6a9e5c0b76..1b52317bad2 100644 --- a/libavcodec/libvpxenc.c +++ b/libavcodec/libvpxenc.c @@ -1284,11 +1284,11 @@ static int storeframe(AVCodecContext *avctx, struct FrameListData *cx_frame, AV_WB64(side_data, 1); memcpy(side_data + 8, alpha_cx_frame->buf, alpha_cx_frame->sz); } - if (ctx->hdr10_plus_fifo) { - int err = copy_hdr10_plus_to_pkt(ctx->hdr10_plus_fifo, pkt); - if (err < 0) - return err; - } + if (ctx->hdr10_plus_fifo) { + int err = copy_hdr10_plus_to_pkt(ctx->hdr10_plus_fifo, pkt); + if (err < 0) + return err; + } return pkt->size; } From 7141a37e2f622211910952a5ac9283d694108064 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Tue, 28 Feb 2023 11:39:36 +0100 Subject: [PATCH 0383/2172] lavc/libvpxenc: rename hdr10_plus_fifo and related objects This AVFifo is used to propagate HDR metadata from input frames to output packets, since libvpx does not allow passing through arbitrary user data. It will be extended to pass through other kinds of data in future commits, so give it a more generic name. --- libavcodec/libvpxenc.c | 51 +++++++++++++++++++++--------------------- 1 file changed, 26 insertions(+), 25 deletions(-) diff --git a/libavcodec/libvpxenc.c b/libavcodec/libvpxenc.c index 1b52317bad2..7d5af7332c0 100644 --- a/libavcodec/libvpxenc.c +++ b/libavcodec/libvpxenc.c @@ -66,10 +66,10 @@ struct FrameListData { struct FrameListData *next; }; -typedef struct FrameHDR10Plus { +typedef struct FrameData { int64_t pts; AVBufferRef *hdr10_plus; -} FrameHDR10Plus; +} FrameData; typedef struct VPxEncoderContext { AVClass *class; @@ -130,7 +130,9 @@ typedef struct VPxEncoderContext { int corpus_complexity; int tpl_model; int min_gf_interval; - AVFifo *hdr10_plus_fifo; + + // This FIFO is used to propagate various properties from frames to packets. + AVFifo *fifo; /** * If the driver does not support ROI then warn the first time we * encounter a frame with ROI side data. @@ -327,32 +329,32 @@ static av_cold void free_frame_list(struct FrameListData *list) } } -static av_cold void free_hdr10_plus_fifo(AVFifo **fifo) +static av_cold void fifo_free(AVFifo **fifo) { - FrameHDR10Plus frame_hdr10_plus; - while (av_fifo_read(*fifo, &frame_hdr10_plus, 1) >= 0) - av_buffer_unref(&frame_hdr10_plus.hdr10_plus); + FrameData fd; + while (av_fifo_read(*fifo, &fd, 1) >= 0) + av_buffer_unref(&fd.hdr10_plus); av_fifo_freep2(fifo); } -static int copy_hdr10_plus_to_pkt(AVFifo *fifo, AVPacket *pkt) +static int frame_data_apply(AVFifo *fifo, AVPacket *pkt) { - FrameHDR10Plus frame_hdr10_plus; + FrameData fd; uint8_t *data; - if (!pkt || av_fifo_peek(fifo, &frame_hdr10_plus, 1, 0) < 0) + if (!pkt || av_fifo_peek(fifo, &fd, 1, 0) < 0) return 0; - if (!frame_hdr10_plus.hdr10_plus || frame_hdr10_plus.pts != pkt->pts) + if (!fd.hdr10_plus || fd.pts != pkt->pts) return 0; av_fifo_drain2(fifo, 1); - data = av_packet_new_side_data(pkt, AV_PKT_DATA_DYNAMIC_HDR10_PLUS, frame_hdr10_plus.hdr10_plus->size); + data = av_packet_new_side_data(pkt, AV_PKT_DATA_DYNAMIC_HDR10_PLUS, fd.hdr10_plus->size); if (!data) { - av_buffer_unref(&frame_hdr10_plus.hdr10_plus); + av_buffer_unref(&fd.hdr10_plus); return AVERROR(ENOMEM); } - memcpy(data, frame_hdr10_plus.hdr10_plus->data, frame_hdr10_plus.hdr10_plus->size); - av_buffer_unref(&frame_hdr10_plus.hdr10_plus); + memcpy(data, fd.hdr10_plus->data, fd.hdr10_plus->size); + av_buffer_unref(&fd.hdr10_plus); return 0; } @@ -447,8 +449,8 @@ static av_cold int vpx_free(AVCodecContext *avctx) av_freep(&avctx->stats_out); free_frame_list(ctx->coded_frame_list); free_frame_list(ctx->alpha_coded_frame_list); - if (ctx->hdr10_plus_fifo) - free_hdr10_plus_fifo(&ctx->hdr10_plus_fifo); + if (ctx->fifo) + fifo_free(&ctx->fifo); return 0; } @@ -919,9 +921,8 @@ static av_cold int vpx_init(AVCodecContext *avctx, // Keep HDR10+ if it has bit depth higher than 8 and // it has PQ trc (SMPTE2084). if (enccfg.g_bit_depth > 8 && avctx->color_trc == AVCOL_TRC_SMPTE2084) { - ctx->hdr10_plus_fifo = av_fifo_alloc2(1, sizeof(FrameHDR10Plus), - AV_FIFO_FLAG_AUTO_GROW); - if (!ctx->hdr10_plus_fifo) + ctx->fifo = av_fifo_alloc2(1, sizeof(FrameData), AV_FIFO_FLAG_AUTO_GROW); + if (!ctx->fifo) return AVERROR(ENOMEM); } } @@ -1284,8 +1285,8 @@ static int storeframe(AVCodecContext *avctx, struct FrameListData *cx_frame, AV_WB64(side_data, 1); memcpy(side_data + 8, alpha_cx_frame->buf, alpha_cx_frame->sz); } - if (ctx->hdr10_plus_fifo) { - int err = copy_hdr10_plus_to_pkt(ctx->hdr10_plus_fifo, pkt); + if (ctx->fifo) { + int err = frame_data_apply(ctx->fifo, pkt); if (err < 0) return err; } @@ -1702,18 +1703,18 @@ static int vpx_encode(AVCodecContext *avctx, AVPacket *pkt, } } - if (ctx->hdr10_plus_fifo) { + if (ctx->fifo) { AVFrameSideData *hdr10_plus_metadata; // Add HDR10+ metadata to queue. hdr10_plus_metadata = av_frame_get_side_data(frame, AV_FRAME_DATA_DYNAMIC_HDR_PLUS); if (hdr10_plus_metadata) { int err; - struct FrameHDR10Plus data; + FrameData data; data.pts = frame->pts; data.hdr10_plus = av_buffer_ref(hdr10_plus_metadata->buf); if (!data.hdr10_plus) return AVERROR(ENOMEM); - err = av_fifo_write(ctx->hdr10_plus_fifo, &data, 1); + err = av_fifo_write(ctx->fifo, &data, 1); if (err < 0) { av_buffer_unref(&data.hdr10_plus); return err; From 5bda4ec6c3cb6f286bb40dee4457c3c26e0f78cb Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Tue, 28 Feb 2023 12:20:39 +0100 Subject: [PATCH 0384/2172] lavc/libvpxenc: handle frame durations and AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE --- libavcodec/libvpxenc.c | 139 +++++++++++++++++++++++++++++------------ libavcodec/version.h | 2 +- 2 files changed, 100 insertions(+), 41 deletions(-) diff --git a/libavcodec/libvpxenc.c b/libavcodec/libvpxenc.c index 7d5af7332c0..8000689726f 100644 --- a/libavcodec/libvpxenc.c +++ b/libavcodec/libvpxenc.c @@ -68,6 +68,14 @@ struct FrameListData { typedef struct FrameData { int64_t pts; + int64_t duration; + +#if FF_API_REORDERED_OPAQUE + int64_t reordered_opaque; +#endif + void *frame_opaque; + AVBufferRef *frame_opaque_ref; + AVBufferRef *hdr10_plus; } FrameData; @@ -329,32 +337,101 @@ static av_cold void free_frame_list(struct FrameListData *list) } } +static void frame_data_uninit(FrameData *fd) +{ + av_buffer_unref(&fd->frame_opaque_ref); + av_buffer_unref(&fd->hdr10_plus); +} + static av_cold void fifo_free(AVFifo **fifo) { FrameData fd; while (av_fifo_read(*fifo, &fd, 1) >= 0) - av_buffer_unref(&fd.hdr10_plus); + frame_data_uninit(&fd); av_fifo_freep2(fifo); } -static int frame_data_apply(AVFifo *fifo, AVPacket *pkt) +static int frame_data_submit(AVCodecContext *avctx, AVFifo *fifo, + const AVFrame *frame) +{ + VPxContext *ctx = avctx->priv_data; + const struct vpx_codec_enc_cfg *enccfg = ctx->encoder.config.enc; + + FrameData fd = { .pts = frame->pts }; + + AVFrameSideData *av_uninit(sd); + int ret; + +#if CONFIG_LIBVPX_VP9_ENCODER + // Keep HDR10+ if it has bit depth higher than 8 and + // it has PQ trc (SMPTE2084). + sd = av_frame_get_side_data(frame, AV_FRAME_DATA_DYNAMIC_HDR_PLUS); + if (avctx->codec_id == AV_CODEC_ID_VP9 && sd && + enccfg->g_bit_depth > 8 && avctx->color_trc == AVCOL_TRC_SMPTE2084) { + fd.hdr10_plus = av_buffer_ref(sd->buf); + if (!fd.hdr10_plus) + return AVERROR(ENOMEM); + } +#endif + + fd.duration = frame->duration; + fd.frame_opaque = frame->opaque; + if (avctx->flags & AV_CODEC_FLAG_COPY_OPAQUE && frame->opaque_ref) { + ret = av_buffer_replace(&fd.frame_opaque_ref, frame->opaque_ref); + if (ret < 0) + goto fail; + } +#if FF_API_REORDERED_OPAQUE +FF_DISABLE_DEPRECATION_WARNINGS + fd.reordered_opaque = frame->reordered_opaque; +FF_ENABLE_DEPRECATION_WARNINGS +#endif + + ret = av_fifo_write(fifo, &fd, 1); + if (ret < 0) + goto fail; + + return 0; +fail: + frame_data_uninit(&fd); + return ret; +} + +static int frame_data_apply(AVCodecContext *avctx, AVFifo *fifo, AVPacket *pkt) { FrameData fd; uint8_t *data; if (!pkt || av_fifo_peek(fifo, &fd, 1, 0) < 0) return 0; - if (!fd.hdr10_plus || fd.pts != pkt->pts) + if (fd.pts != pkt->pts) return 0; av_fifo_drain2(fifo, 1); - data = av_packet_new_side_data(pkt, AV_PKT_DATA_DYNAMIC_HDR10_PLUS, fd.hdr10_plus->size); - if (!data) { +#if FF_API_REORDERED_OPAQUE +FF_DISABLE_DEPRECATION_WARNINGS + avctx->reordered_opaque = fd.reordered_opaque; +FF_ENABLE_DEPRECATION_WARNINGS +#endif + + pkt->duration = fd.duration; + if (avctx->flags & AV_CODEC_FLAG_COPY_OPAQUE) { + pkt->opaque = fd.frame_opaque; + pkt->opaque_ref = fd.frame_opaque_ref; + fd.frame_opaque_ref = NULL; + } + av_buffer_unref(&fd.frame_opaque_ref); + + if (fd.hdr10_plus) { + data = av_packet_new_side_data(pkt, AV_PKT_DATA_DYNAMIC_HDR10_PLUS, fd.hdr10_plus->size); + if (!data) { + av_buffer_unref(&fd.hdr10_plus); + return AVERROR(ENOMEM); + } + + memcpy(data, fd.hdr10_plus->data, fd.hdr10_plus->size); av_buffer_unref(&fd.hdr10_plus); - return AVERROR(ENOMEM); } - memcpy(data, fd.hdr10_plus->data, fd.hdr10_plus->size); - av_buffer_unref(&fd.hdr10_plus); return 0; } @@ -914,17 +991,14 @@ static av_cold int vpx_init(AVCodecContext *avctx, return AVERROR(EINVAL); } + ctx->fifo = av_fifo_alloc2(1, sizeof(FrameData), AV_FIFO_FLAG_AUTO_GROW); + if (!ctx->fifo) + return AVERROR(ENOMEM); + #if CONFIG_LIBVPX_VP9_ENCODER if (avctx->codec_id == AV_CODEC_ID_VP9) { if (set_pix_fmt(avctx, codec_caps, &enccfg, &flags, &img_fmt)) return AVERROR(EINVAL); - // Keep HDR10+ if it has bit depth higher than 8 and - // it has PQ trc (SMPTE2084). - if (enccfg.g_bit_depth > 8 && avctx->color_trc == AVCOL_TRC_SMPTE2084) { - ctx->fifo = av_fifo_alloc2(1, sizeof(FrameData), AV_FIFO_FLAG_AUTO_GROW); - if (!ctx->fifo) - return AVERROR(ENOMEM); - } } #endif @@ -1285,11 +1359,9 @@ static int storeframe(AVCodecContext *avctx, struct FrameListData *cx_frame, AV_WB64(side_data, 1); memcpy(side_data + 8, alpha_cx_frame->buf, alpha_cx_frame->sz); } - if (ctx->fifo) { - int err = frame_data_apply(ctx->fifo, pkt); - if (err < 0) - return err; - } + ret = frame_data_apply(avctx, ctx->fifo, pkt); + if (ret < 0) + return ret; return pkt->size; } @@ -1703,24 +1775,9 @@ static int vpx_encode(AVCodecContext *avctx, AVPacket *pkt, } } - if (ctx->fifo) { - AVFrameSideData *hdr10_plus_metadata; - // Add HDR10+ metadata to queue. - hdr10_plus_metadata = av_frame_get_side_data(frame, AV_FRAME_DATA_DYNAMIC_HDR_PLUS); - if (hdr10_plus_metadata) { - int err; - FrameData data; - data.pts = frame->pts; - data.hdr10_plus = av_buffer_ref(hdr10_plus_metadata->buf); - if (!data.hdr10_plus) - return AVERROR(ENOMEM); - err = av_fifo_write(ctx->fifo, &data, 1); - if (err < 0) { - av_buffer_unref(&data.hdr10_plus); - return err; - } - } - } + res = frame_data_submit(avctx, ctx->fifo, frame); + if (res < 0) + return res; } // this is for encoding with preset temporal layering patterns defined in @@ -1953,7 +2010,8 @@ const FFCodec ff_libvpx_vp8_encoder = { .p.type = AVMEDIA_TYPE_VIDEO, .p.id = AV_CODEC_ID_VP8, .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_DELAY | - AV_CODEC_CAP_OTHER_THREADS, + AV_CODEC_CAP_OTHER_THREADS | + AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE, .priv_data_size = sizeof(VPxContext), .init = vp8_init, FF_CODEC_ENCODE_CB(vpx_encode), @@ -2025,7 +2083,8 @@ FFCodec ff_libvpx_vp9_encoder = { .p.type = AVMEDIA_TYPE_VIDEO, .p.id = AV_CODEC_ID_VP9, .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_DELAY | - AV_CODEC_CAP_OTHER_THREADS, + AV_CODEC_CAP_OTHER_THREADS | + AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE, .p.profiles = NULL_IF_CONFIG_SMALL(ff_vp9_profiles), .p.priv_class = &class_vp9, .p.wrapper_name = "libvpx", diff --git a/libavcodec/version.h b/libavcodec/version.h index da54f878874..39dbec02081 100644 --- a/libavcodec/version.h +++ b/libavcodec/version.h @@ -30,7 +30,7 @@ #include "version_major.h" #define LIBAVCODEC_VERSION_MINOR 6 -#define LIBAVCODEC_VERSION_MICRO 100 +#define LIBAVCODEC_VERSION_MICRO 101 #define LIBAVCODEC_VERSION_INT AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \ LIBAVCODEC_VERSION_MINOR, \ From 62a241e505abfa96b4329875ecc76aaa1d57519e Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Tue, 28 Feb 2023 12:20:39 +0100 Subject: [PATCH 0385/2172] lavc/libvpxenc: drop a useless condition A non-NULL packet is always passed to frame_data_apply(). --- libavcodec/libvpxenc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavcodec/libvpxenc.c b/libavcodec/libvpxenc.c index 8000689726f..79cd863093a 100644 --- a/libavcodec/libvpxenc.c +++ b/libavcodec/libvpxenc.c @@ -401,7 +401,7 @@ static int frame_data_apply(AVCodecContext *avctx, AVFifo *fifo, AVPacket *pkt) { FrameData fd; uint8_t *data; - if (!pkt || av_fifo_peek(fifo, &fd, 1, 0) < 0) + if (av_fifo_peek(fifo, &fd, 1, 0) < 0) return 0; if (fd.pts != pkt->pts) return 0; From 942fb48c38b9a26c4fe2b282cc11f9c22c68bf1f Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Tue, 28 Feb 2023 12:53:35 +0100 Subject: [PATCH 0386/2172] lavc/libvpxenc: handle queue desync more gracefully If the packets returned by libvpx and our internal frame properties queue get desynchronized for some reason (should not happen, but it is not clear libvpx API guarantees this), we will keep adding to the queue indefinitely and never remove anything. Change the code to drain the queue even if timestamps do not match. --- libavcodec/libvpxenc.c | 23 +++++++++++++++-------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/libavcodec/libvpxenc.c b/libavcodec/libvpxenc.c index 79cd863093a..3d7b809b2f5 100644 --- a/libavcodec/libvpxenc.c +++ b/libavcodec/libvpxenc.c @@ -401,11 +401,16 @@ static int frame_data_apply(AVCodecContext *avctx, AVFifo *fifo, AVPacket *pkt) { FrameData fd; uint8_t *data; + int ret = 0; + if (av_fifo_peek(fifo, &fd, 1, 0) < 0) return 0; - if (fd.pts != pkt->pts) - return 0; - av_fifo_drain2(fifo, 1); + if (fd.pts != pkt->pts) { + av_log(avctx, AV_LOG_WARNING, + "Mismatching timestamps: libvpx %"PRId64" queued %"PRId64"; " + "this is a bug, please report it\n", pkt->pts, fd.pts); + goto skip; + } #if FF_API_REORDERED_OPAQUE FF_DISABLE_DEPRECATION_WARNINGS @@ -419,20 +424,22 @@ FF_ENABLE_DEPRECATION_WARNINGS pkt->opaque_ref = fd.frame_opaque_ref; fd.frame_opaque_ref = NULL; } - av_buffer_unref(&fd.frame_opaque_ref); if (fd.hdr10_plus) { data = av_packet_new_side_data(pkt, AV_PKT_DATA_DYNAMIC_HDR10_PLUS, fd.hdr10_plus->size); if (!data) { - av_buffer_unref(&fd.hdr10_plus); - return AVERROR(ENOMEM); + ret = AVERROR(ENOMEM); + goto skip; } memcpy(data, fd.hdr10_plus->data, fd.hdr10_plus->size); - av_buffer_unref(&fd.hdr10_plus); } - return 0; +skip: + av_fifo_drain2(fifo, 1); + frame_data_uninit(&fd); + + return ret; } static av_cold int codecctl_int(AVCodecContext *avctx, From ae95c87e64aa7ec29e0bad19016950171c3db3c6 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Tue, 28 Feb 2023 13:00:32 +0100 Subject: [PATCH 0387/2172] lavc/libvpxenc: drop FrameListData.duration It is write-only. --- libavcodec/libvpxenc.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/libavcodec/libvpxenc.c b/libavcodec/libvpxenc.c index 3d7b809b2f5..a20e9498429 100644 --- a/libavcodec/libvpxenc.c +++ b/libavcodec/libvpxenc.c @@ -58,8 +58,6 @@ struct FrameListData { size_t sz; /**< length of compressed data */ int64_t pts; /**< time stamp to show frame (in timebase units) */ - unsigned long duration; /**< duration to show frame - (in timebase units) */ uint32_t flags; /**< flags for this frame */ uint64_t sse[4]; int have_sse; /**< true if we have pending sse[] */ @@ -1295,7 +1293,6 @@ static inline void cx_pktcpy(struct FrameListData *dst, VPxContext *ctx) { dst->pts = src->data.frame.pts; - dst->duration = src->data.frame.duration; dst->flags = src->data.frame.flags; dst->sz = src->data.frame.sz; dst->buf = src->data.frame.buf; From fefcba1c1bc8f65464d2eec0ae75f9f511a003a5 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Thu, 9 Mar 2023 16:35:06 +0100 Subject: [PATCH 0388/2172] lavfi/graphparser: use correct logging context --- libavfilter/graphparser.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavfilter/graphparser.c b/libavfilter/graphparser.c index 4347131fad1..9f8acea2ac5 100644 --- a/libavfilter/graphparser.c +++ b/libavfilter/graphparser.c @@ -475,7 +475,7 @@ int avfilter_graph_segment_parse(AVFilterGraph *graph, const char *graph_str, graph_str += strspn(graph_str, WHITESPACES); - ret = parse_sws_flags(&graph_str, &seg->scale_sws_opts, &graph); + ret = parse_sws_flags(&graph_str, &seg->scale_sws_opts, graph); if (ret < 0) goto fail; From 7a8560cb22dd9f5c54df71af3fef26db9a2a28b0 Mon Sep 17 00:00:00 2001 From: Timo Rothenpieler Date: Fri, 10 Mar 2023 13:09:10 +0100 Subject: [PATCH 0389/2172] avcodec/nvenc: avoid failing b_ref_mode check when unset --- libavcodec/nvenc.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/libavcodec/nvenc.c b/libavcodec/nvenc.c index a8b7a4c0a0b..9acf3e86974 100644 --- a/libavcodec/nvenc.c +++ b/libavcodec/nvenc.c @@ -459,7 +459,7 @@ static int nvenc_check_cap(AVCodecContext *avctx, NV_ENC_CAPS cap) static int nvenc_check_capabilities(AVCodecContext *avctx) { NvencContext *ctx = avctx->priv_data; - int ret; + int tmp, ret; ret = nvenc_check_codec_support(avctx); if (ret < 0) { @@ -540,16 +540,18 @@ static int nvenc_check_capabilities(AVCodecContext *avctx) } #ifdef NVENC_HAVE_BFRAME_REF_MODE + tmp = (ctx->b_ref_mode >= 0) ? ctx->b_ref_mode : NV_ENC_BFRAME_REF_MODE_DISABLED; ret = nvenc_check_cap(avctx, NV_ENC_CAPS_SUPPORT_BFRAME_REF_MODE); - if (ctx->b_ref_mode == NV_ENC_BFRAME_REF_MODE_EACH && ret != 1 && ret != 3) { + if (tmp == NV_ENC_BFRAME_REF_MODE_EACH && ret != 1 && ret != 3) { av_log(avctx, AV_LOG_WARNING, "Each B frame as reference is not supported\n"); return AVERROR(ENOSYS); - } else if (ctx->b_ref_mode != NV_ENC_BFRAME_REF_MODE_DISABLED && ret == 0) { + } else if (tmp != NV_ENC_BFRAME_REF_MODE_DISABLED && ret == 0) { av_log(avctx, AV_LOG_WARNING, "B frames as references are not supported\n"); return AVERROR(ENOSYS); } #else - if (ctx->b_ref_mode != 0) { + tmp = (ctx->b_ref_mode >= 0) ? ctx->b_ref_mode : 0; + if (tmp > 0) { av_log(avctx, AV_LOG_WARNING, "B frames as references need SDK 8.1 at build time\n"); return AVERROR(ENOSYS); } From d6d576505163c9c5cb42539a6e53d53b003fd252 Mon Sep 17 00:00:00 2001 From: James Almer Date: Sun, 5 Mar 2023 20:32:23 -0300 Subject: [PATCH 0390/2172] avcodec/av1dec: parse and export Metadata OBUs This includes Mastering Display, Content light level, and some ITU-T T35 metadata like closed captions and HDR10+. Signed-off-by: James Almer --- libavcodec/av1dec.c | 167 ++++++++++++++++++++++++++++++++++++++++++++ libavcodec/av1dec.h | 8 +++ 2 files changed, 175 insertions(+) diff --git a/libavcodec/av1dec.c b/libavcodec/av1dec.c index d83c902f1f8..314c721ac23 100644 --- a/libavcodec/av1dec.c +++ b/libavcodec/av1dec.c @@ -21,13 +21,16 @@ #include "config_components.h" #include "libavutil/film_grain_params.h" +#include "libavutil/mastering_display_metadata.h" #include "libavutil/pixdesc.h" #include "libavutil/opt.h" #include "avcodec.h" #include "av1dec.h" +#include "atsc_a53.h" #include "bytestream.h" #include "codec_internal.h" #include "decode.h" +#include "dynamic_hdr10_plus.h" #include "hwconfig.h" #include "profiles.h" #include "thread.h" @@ -645,6 +648,7 @@ static int av1_frame_ref(AVCodecContext *avctx, AV1Frame *dst, const AV1Frame *s static av_cold int av1_decode_free(AVCodecContext *avctx) { AV1DecContext *s = avctx->priv_data; + AV1RawMetadataITUTT35 itut_t35; for (int i = 0; i < FF_ARRAY_ELEMS(s->ref); i++) { av1_frame_unref(avctx, &s->ref[i]); @@ -655,8 +659,14 @@ static av_cold int av1_decode_free(AVCodecContext *avctx) av_buffer_unref(&s->seq_ref); av_buffer_unref(&s->header_ref); + av_buffer_unref(&s->cll_ref); + av_buffer_unref(&s->mdcv_ref); av_freep(&s->tile_group_info); + while (s->itut_t35_fifo && av_fifo_read(s->itut_t35_fifo, &itut_t35, 1) >= 0) + av_buffer_unref(&itut_t35.payload_ref); + av_fifo_freep2(&s->itut_t35_fifo); + ff_cbs_fragment_free(&s->current_obu); ff_cbs_close(&s->cbc); @@ -771,6 +781,11 @@ static av_cold int av1_decode_init(AVCodecContext *avctx) if (ret < 0) return ret; + s->itut_t35_fifo = av_fifo_alloc2(1, sizeof(AV1RawMetadataITUTT35), + AV_FIFO_FLAG_AUTO_GROW); + if (!s->itut_t35_fifo) + return AVERROR(ENOMEM); + av_opt_set_int(s->cbc->priv_data, "operating_point", s->operating_point, 0); if (avctx->extradata && avctx->extradata_size) { @@ -852,6 +867,107 @@ static int av1_frame_alloc(AVCodecContext *avctx, AV1Frame *f) return ret; } +static int export_itut_t35(AVCodecContext *avctx, AVFrame *frame, + const AV1RawMetadataITUTT35 *itut_t35) +{ + GetByteContext gb; + int ret, provider_code; + + bytestream2_init(&gb, itut_t35->payload, itut_t35->payload_size); + + provider_code = bytestream2_get_be16(&gb); + switch (provider_code) { + case 0x31: { // atsc_provider_code + uint32_t user_identifier = bytestream2_get_be32(&gb); + switch (user_identifier) { + case MKBETAG('G', 'A', '9', '4'): { // closed captions + AVBufferRef *buf = NULL; + + ret = ff_parse_a53_cc(&buf, gb.buffer, bytestream2_get_bytes_left(&gb)); + if (ret < 0) + return ret; + if (!ret) + break; + + if (!av_frame_new_side_data_from_buf(frame, AV_FRAME_DATA_A53_CC, buf)) + av_buffer_unref(&buf); + + avctx->properties |= FF_CODEC_PROPERTY_CLOSED_CAPTIONS; + break; + } + default: // ignore unsupported identifiers + break; + } + } + case 0x3C: { // smpte_provider_code + AVDynamicHDRPlus *hdrplus; + int provider_oriented_code = bytestream2_get_be16(&gb); + int application_identifier = bytestream2_get_byte(&gb); + + if (itut_t35->itu_t_t35_country_code != 0xB5 || + provider_oriented_code != 1 || application_identifier != 4) + break; + + hdrplus = av_dynamic_hdr_plus_create_side_data(frame); + if (!hdrplus) + return AVERROR(ENOMEM); + + ret = ff_parse_itu_t_t35_to_dynamic_hdr10_plus(hdrplus, gb.buffer, + bytestream2_get_bytes_left(&gb)); + if (ret < 0) + return ret; + break; + } + default: // ignore unsupported provider codes + break; + } + + return 0; +} + +static int export_metadata(AVCodecContext *avctx, AVFrame *frame) +{ + AV1DecContext *s = avctx->priv_data; + AV1RawMetadataITUTT35 itut_t35; + int ret = 0; + + if (s->mdcv) { + AVMasteringDisplayMetadata *mastering = av_mastering_display_metadata_create_side_data(frame); + if (!mastering) + return AVERROR(ENOMEM); + + for (int i = 0; i < 3; i++) { + mastering->display_primaries[i][0] = av_make_q(s->mdcv->primary_chromaticity_x[i], 1 << 16); + mastering->display_primaries[i][1] = av_make_q(s->mdcv->primary_chromaticity_y[i], 1 << 16); + } + mastering->white_point[0] = av_make_q(s->mdcv->white_point_chromaticity_x, 1 << 16); + mastering->white_point[1] = av_make_q(s->mdcv->white_point_chromaticity_y, 1 << 16); + + mastering->max_luminance = av_make_q(s->mdcv->luminance_max, 1 << 8); + mastering->min_luminance = av_make_q(s->mdcv->luminance_min, 1 << 14); + + mastering->has_primaries = 1; + mastering->has_luminance = 1; + } + + if (s->cll) { + AVContentLightMetadata *light = av_content_light_metadata_create_side_data(frame); + if (!light) + return AVERROR(ENOMEM); + + light->MaxCLL = s->cll->max_cll; + light->MaxFALL = s->cll->max_fall; + } + + while (av_fifo_read(s->itut_t35_fifo, &itut_t35, 1) >= 0) { + if (ret >= 0) + ret = export_itut_t35(avctx, frame, &itut_t35); + av_buffer_unref(&itut_t35.payload_ref); + } + + return ret; +} + static int export_film_grain(AVCodecContext *avctx, AVFrame *frame) { AV1DecContext *s = avctx->priv_data; @@ -928,6 +1044,12 @@ static int set_output_frame(AVCodecContext *avctx, AVFrame *frame, if (ret < 0) return ret; + ret = export_metadata(avctx, frame); + if (ret < 0) { + av_frame_unref(frame); + return ret; + } + if (avctx->export_side_data & AV_CODEC_EXPORT_DATA_FILM_GRAIN) { ret = export_film_grain(avctx, frame); if (ret < 0) { @@ -1173,7 +1295,47 @@ static int av1_decode_frame(AVCodecContext *avctx, AVFrame *frame, case AV1_OBU_TILE_LIST: case AV1_OBU_TEMPORAL_DELIMITER: case AV1_OBU_PADDING: + break; case AV1_OBU_METADATA: + switch (obu->obu.metadata.metadata_type) { + case AV1_METADATA_TYPE_HDR_CLL: + av_buffer_unref(&s->cll_ref); + s->cll_ref = av_buffer_ref(unit->content_ref); + if (!s->cll_ref) { + s->cll = NULL; + ret = AVERROR(ENOMEM); + goto end; + } + s->cll = &obu->obu.metadata.metadata.hdr_cll; + break; + case AV1_METADATA_TYPE_HDR_MDCV: + av_buffer_unref(&s->mdcv_ref); + s->mdcv_ref = av_buffer_ref(unit->content_ref); + if (!s->mdcv_ref) { + s->mdcv = NULL; + ret = AVERROR(ENOMEM); + goto end; + } + s->mdcv = &obu->obu.metadata.metadata.hdr_mdcv; + break; + case AV1_METADATA_TYPE_ITUT_T35: { + AV1RawMetadataITUTT35 itut_t35; + memcpy(&itut_t35, &obu->obu.metadata.metadata.itut_t35, sizeof(itut_t35)); + itut_t35.payload_ref = av_buffer_ref(obu->obu.metadata.metadata.itut_t35.payload_ref); + if (!itut_t35.payload_ref) { + ret = AVERROR(ENOMEM); + goto end; + } + ret = av_fifo_write(s->itut_t35_fifo, &itut_t35, 1); + if (ret < 0) { + av_buffer_unref(&itut_t35.payload_ref); + goto end; + } + break; + } + default: + break; + } break; default: av_log(avctx, AV_LOG_DEBUG, @@ -1218,6 +1380,7 @@ static int av1_decode_frame(AVCodecContext *avctx, AVFrame *frame, static void av1_decode_flush(AVCodecContext *avctx) { AV1DecContext *s = avctx->priv_data; + AV1RawMetadataITUTT35 itut_t35; for (int i = 0; i < FF_ARRAY_ELEMS(s->ref); i++) av1_frame_unref(avctx, &s->ref[i]); @@ -1226,6 +1389,10 @@ static void av1_decode_flush(AVCodecContext *avctx) s->operating_point_idc = 0; s->raw_frame_header = NULL; s->raw_seq = NULL; + s->cll = NULL; + s->mdcv = NULL; + while (av_fifo_read(s->itut_t35_fifo, &itut_t35, 1) >= 0) + av_buffer_unref(&itut_t35.payload_ref); ff_cbs_flush(s->cbc); } diff --git a/libavcodec/av1dec.h b/libavcodec/av1dec.h index 82c7084e99f..cef899f81f7 100644 --- a/libavcodec/av1dec.h +++ b/libavcodec/av1dec.h @@ -23,6 +23,7 @@ #include +#include "libavutil/fifo.h" #include "libavutil/buffer.h" #include "libavutil/frame.h" #include "libavutil/pixfmt.h" @@ -73,6 +74,13 @@ typedef struct AV1DecContext { AVBufferRef *header_ref; AV1RawFrameHeader *raw_frame_header; TileGroupInfo *tile_group_info; + + AVBufferRef *cll_ref; + AV1RawMetadataHDRCLL *cll; + AVBufferRef *mdcv_ref; + AV1RawMetadataHDRMDCV *mdcv; + AVFifo *itut_t35_fifo; + uint16_t tile_num; uint16_t tg_start; uint16_t tg_end; From 68a858fcc913c4939798c7b6580a814184a1089b Mon Sep 17 00:00:00 2001 From: James Almer Date: Tue, 7 Mar 2023 09:03:26 -0300 Subject: [PATCH 0391/2172] avcodec/av1dec: make CBS parse only the OBU types we care about Signed-off-by: James Almer --- libavcodec/av1dec.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/libavcodec/av1dec.c b/libavcodec/av1dec.c index 314c721ac23..a80e37e33fc 100644 --- a/libavcodec/av1dec.c +++ b/libavcodec/av1dec.c @@ -752,6 +752,16 @@ static int update_context_with_frame_header(AVCodecContext *avctx, return 0; } +static const CodedBitstreamUnitType decompose_unit_types[] = { + AV1_OBU_FRAME, + AV1_OBU_FRAME_HEADER, + AV1_OBU_METADATA, + AV1_OBU_REDUNDANT_FRAME_HEADER, + AV1_OBU_SEQUENCE_HEADER, + AV1_OBU_TEMPORAL_DELIMITER, + AV1_OBU_TILE_GROUP, +}; + static av_cold int av1_decode_init(AVCodecContext *avctx) { AV1DecContext *s = avctx->priv_data; @@ -781,6 +791,9 @@ static av_cold int av1_decode_init(AVCodecContext *avctx) if (ret < 0) return ret; + s->cbc->decompose_unit_types = decompose_unit_types; + s->cbc->nb_decompose_unit_types = FF_ARRAY_ELEMS(decompose_unit_types); + s->itut_t35_fifo = av_fifo_alloc2(1, sizeof(AV1RawMetadataITUTT35), AV_FIFO_FLAG_AUTO_GROW); if (!s->itut_t35_fifo) From e60cd2e98b8ea11e4e40584b20e9599ca291fbaa Mon Sep 17 00:00:00 2001 From: James Almer Date: Tue, 7 Mar 2023 11:38:05 -0300 Subject: [PATCH 0392/2172] fate/vpx: add a vp9_superframe_bsf test This splits a sample and merges it again, so it also tests the vp9_superframe_split bsf Signed-off-by: James Almer --- tests/fate/vpx.mak | 4 ++++ tests/ref/fate/vp9-superframe-bsf | 30 ++++++++++++++++++++++++++++++ 2 files changed, 34 insertions(+) create mode 100644 tests/ref/fate/vp9-superframe-bsf diff --git a/tests/fate/vpx.mak b/tests/fate/vpx.mak index e18f3df38b5..b0a3cd2fd79 100644 --- a/tests/fate/vpx.mak +++ b/tests/fate/vpx.mak @@ -138,6 +138,10 @@ fate-vp9-05-resize: REF = $(SRC_PATH)/tests/ref/fate/vp9-05-resize fate-vp9-encparams: CMD = venc_data $(TARGET_SAMPLES)/vp9-test-vectors/vp90-2-segmentation-aq-akiyo.webm 0 5 FATE_SAMPLES_DUMP_DATA-$(call DEMDEC, MATROSKA, VP9) += fate-vp9-encparams +FATE_VP9-$(call ALLYES, MATROSKA_DEMUXER VP9_PARSER VP9_SUPERFRAME_SPLIT_BSF \ + VP9_SUPERFRAME_BSF FILE_PROTOCOL FRAMECRC_MUXER) += fate-vp9-superframe-bsf +fate-vp9-superframe-bsf: CMD = framecrc -i $(TARGET_SAMPLES)/vp9-test-vectors/vp90-2-segmentation-sf-akiyo.webm -c:v copy -bsf:v vp9_superframe_split,vp9_superframe + FATE_VP9-$(call DEMDEC, MATROSKA, VP9) += fate-vp9-encparams FATE_SAMPLES_FFMPEG += $(FATE_VP9-yes) diff --git a/tests/ref/fate/vp9-superframe-bsf b/tests/ref/fate/vp9-superframe-bsf new file mode 100644 index 00000000000..d7985c6973e --- /dev/null +++ b/tests/ref/fate/vp9-superframe-bsf @@ -0,0 +1,30 @@ +#tb 0: 1/1000 +#media_type 0: video +#codec_id 0: vp9 +#dimensions 0: 352x288 +#sar 0: 1/1 +0, 0, 0, 33, 6958, 0x38e58ee6, S=1, 12 +0, 33, 33, 33, 852, 0x3edf9ed0, F=0x0 +0, 66, 66, 33, 27, 0x62d007e5, F=0x0 +0, 100, 100, 33, 25, 0x51980749, F=0x0 +0, 133, 133, 33, 50, 0xcc45133d, F=0x0 +0, 166, 166, 33, 50, 0xd1fe14e2, F=0x0 +0, 200, 200, 33, 32, 0x98ff0ab7, F=0x0 +0, 233, 233, 33, 45, 0x4f6b0fbb, F=0x0 +0, 266, 266, 33, 54, 0xe975139c, F=0x0 +0, 300, 300, 33, 36, 0xd8ff0e13, F=0x0 +0, 333, 333, 33, 47, 0xc31915b5, F=0x0 +0, 367, 367, 33, 50, 0xbe84156d, F=0x0 +0, 400, 400, 33, 37, 0xbb3c0ba7, F=0x0 +0, 433, 433, 33, 48, 0xb01913e2, F=0x0 +0, 467, 467, 33, 39, 0xe8cc0d02, F=0x0 +0, 500, 500, 33, 51, 0x05fe157f, F=0x0 +0, 533, 533, 33, 24, 0x4c500657, F=0x0 +0, 567, 567, 33, 52, 0xcf501420, F=0x0 +0, 600, 600, 33, 59, 0x8a451926, F=0x0 +0, 633, 633, 33, 74, 0xec501f1e, F=0x0 +0, 667, 667, 33, 53, 0x027a1607, F=0x0 +0, 700, 700, 33, 71, 0x81a41ccf, F=0x0 +0, 734, 734, 33, 58, 0x653f17b2, F=0x0 +0, 767, 767, 33, 40, 0x1fdd106c, F=0x0 +0, 800, 800, 33, 54, 0x9dd11210, F=0x0 From 205117d87fdc01cd8e150aa6f4d16cf69f7b4ca4 Mon Sep 17 00:00:00 2001 From: James Almer Date: Tue, 7 Mar 2023 23:56:30 -0300 Subject: [PATCH 0393/2172] avfilter/stack_internal: add missing header includes Fixes make checkheaders Signed-off-by: James Almer --- libavfilter/Makefile | 2 +- libavfilter/stack_internal.h | 6 ++++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/libavfilter/Makefile b/libavfilter/Makefile index b3d3d981dd4..fc75d705e04 100644 --- a/libavfilter/Makefile +++ b/libavfilter/Makefile @@ -629,7 +629,7 @@ SKIPHEADERS-$(CONFIG_LIBVIDSTAB) += vidstabutils.h SKIPHEADERS-$(CONFIG_QSVVPP) += qsvvpp.h SKIPHEADERS-$(CONFIG_OPENCL) += opencl.h -SKIPHEADERS-$(CONFIG_VAAPI) += vaapi_vpp.h +SKIPHEADERS-$(CONFIG_VAAPI) += vaapi_vpp.h stack_internal.h SKIPHEADERS-$(CONFIG_VULKAN) += vulkan.h vulkan_filter.h TOOLS = graph2dot diff --git a/libavfilter/stack_internal.h b/libavfilter/stack_internal.h index ace88861529..a5be36c270a 100644 --- a/libavfilter/stack_internal.h +++ b/libavfilter/stack_internal.h @@ -19,6 +19,12 @@ #ifndef AVFILTER_STACK_INTERNAL_H #define AVFILTER_STACK_INTERNAL_H +#include + +#include "libavutil/attributes.h" +#include "framesync.h" +#include "vaapi_vpp.h" + enum { STACK_H = 0, STACK_V = 1, From a3bf63c26e6197a9b6e490538667368530a9dcd3 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Thu, 9 Mar 2023 16:02:31 +0100 Subject: [PATCH 0394/2172] lavc/decode: stop mangling last_pkt_props->opaque MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit It is currently abused to store packet size, which breaks AV_CODEC_FLAG_COPY_OPAQUE. Use stream_index instead, which is unused in libavcodec and has the same type as size. Found-by: Martin Storsjö --- libavcodec/decode.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/libavcodec/decode.c b/libavcodec/decode.c index be2be81089f..d1ba7f167fa 100644 --- a/libavcodec/decode.c +++ b/libavcodec/decode.c @@ -140,7 +140,7 @@ static int extract_packet_props(AVCodecInternal *avci, const AVPacket *pkt) if (pkt) { ret = av_packet_copy_props(avci->last_pkt_props, pkt); if (!ret) - avci->last_pkt_props->opaque = (void *)(intptr_t)pkt->size; // Needed for ff_decode_frame_props(). + avci->last_pkt_props->stream_index = pkt->size; // Needed for ff_decode_frame_props(). } return ret; } @@ -461,7 +461,7 @@ FF_ENABLE_DEPRECATION_WARNINGS pkt->dts = AV_NOPTS_VALUE; if (!(codec->caps_internal & FF_CODEC_CAP_SETS_FRAME_PROPS)) { // See extract_packet_props() comment. - avci->last_pkt_props->opaque = (void *)((intptr_t)avci->last_pkt_props->opaque - consumed); + avci->last_pkt_props->stream_index = avci->last_pkt_props->stream_index - consumed; avci->last_pkt_props->pts = AV_NOPTS_VALUE; avci->last_pkt_props->dts = AV_NOPTS_VALUE; } @@ -1355,7 +1355,7 @@ int ff_decode_frame_props(AVCodecContext *avctx, AVFrame *frame) int ret = ff_decode_frame_props_from_pkt(avctx, frame, pkt); if (ret < 0) return ret; - frame->pkt_size = (int)(intptr_t)pkt->opaque; + frame->pkt_size = pkt->stream_index; } #if FF_API_REORDERED_OPAQUE FF_DISABLE_DEPRECATION_WARNINGS From 358588c8205195a7b038e8aaa0bf002768ac535b Mon Sep 17 00:00:00 2001 From: James Almer Date: Sat, 11 Mar 2023 10:03:53 -0300 Subject: [PATCH 0395/2172] Revert "avfilter/stack_internal: add missing header includes" This reverts commit 205117d87fdc01cd8e150aa6f4d16cf69f7b4ca4. This didn't fix make checkheaders after all, and also broke compilation in some scenarios. Signed-off-by: James Almer --- libavfilter/Makefile | 2 +- libavfilter/stack_internal.h | 6 ------ 2 files changed, 1 insertion(+), 7 deletions(-) diff --git a/libavfilter/Makefile b/libavfilter/Makefile index fc75d705e04..b3d3d981dd4 100644 --- a/libavfilter/Makefile +++ b/libavfilter/Makefile @@ -629,7 +629,7 @@ SKIPHEADERS-$(CONFIG_LIBVIDSTAB) += vidstabutils.h SKIPHEADERS-$(CONFIG_QSVVPP) += qsvvpp.h SKIPHEADERS-$(CONFIG_OPENCL) += opencl.h -SKIPHEADERS-$(CONFIG_VAAPI) += vaapi_vpp.h stack_internal.h +SKIPHEADERS-$(CONFIG_VAAPI) += vaapi_vpp.h SKIPHEADERS-$(CONFIG_VULKAN) += vulkan.h vulkan_filter.h TOOLS = graph2dot diff --git a/libavfilter/stack_internal.h b/libavfilter/stack_internal.h index a5be36c270a..ace88861529 100644 --- a/libavfilter/stack_internal.h +++ b/libavfilter/stack_internal.h @@ -19,12 +19,6 @@ #ifndef AVFILTER_STACK_INTERNAL_H #define AVFILTER_STACK_INTERNAL_H -#include - -#include "libavutil/attributes.h" -#include "framesync.h" -#include "vaapi_vpp.h" - enum { STACK_H = 0, STACK_V = 1, From dcf963f4906fa594aea3e54d3f2f84637624acca Mon Sep 17 00:00:00 2001 From: Stefano Sabatini Date: Tue, 28 Feb 2023 23:26:43 +0100 Subject: [PATCH 0396/2172] lavc/avcodec.h: extend documentation for avcodec_open2() In particular, clarify how to set options in the codec context, and mention when to use avcodec_parameters_to_context(). Fix trac issues: http://trac.ffmpeg.org/ticket/5781 http://trac.ffmpeg.org/ticket/5838 --- libavcodec/avcodec.h | 36 +++++++++++++++++++++++++++++++----- 1 file changed, 31 insertions(+), 5 deletions(-) diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h index 87ebee22b19..30f1d312f4e 100644 --- a/libavcodec/avcodec.h +++ b/libavcodec/avcodec.h @@ -2429,9 +2429,16 @@ int avcodec_parameters_to_context(AVCodecContext *codec, * avcodec_find_decoder() and avcodec_find_encoder() provide an easy way for * retrieving a codec. * - * @note Always call this function before using decoding routines (such as - * @ref avcodec_receive_frame()). + * Depending on the codec, you might need to set options in the codec context + * also for decoding (e.g. width, height, or the pixel or audio sample format in + * the case the information is not available in the bitstream, as when decoding + * raw audio or video). * + * Options in the codec context can be set either by setting them in the options + * AVDictionary, or by setting the values in the context itself, directly or by + * using the av_opt_set() API before calling this function. + * + * Example: * @code * av_dict_set(&opts, "b", "2.5M", 0); * codec = avcodec_find_decoder(AV_CODEC_ID_H264); @@ -2444,17 +2451,36 @@ int avcodec_parameters_to_context(AVCodecContext *codec, * exit(1); * @endcode * + * In the case AVCodecParameters are available (e.g. when demuxing a stream + * using libavformat, and accessing the AVStream contained in the demuxer), the + * codec parameters can be copied to the codec context using + * avcodec_parameters_to_context(), as in the following example: + * + * @code + * AVStream *stream = ...; + * context = avcodec_alloc_context3(codec); + * if (avcodec_parameters_to_context(context, stream->codecpar) < 0) + * exit(1); + * if (avcodec_open2(context, codec, NULL) < 0) + * exit(1); + * @endcode + * + * @note Always call this function before using decoding routines (such as + * @ref avcodec_receive_frame()). + * * @param avctx The context to initialize. * @param codec The codec to open this context for. If a non-NULL codec has been * previously passed to avcodec_alloc_context3() or * for this context, then this parameter MUST be either NULL or * equal to the previously passed codec. - * @param options A dictionary filled with AVCodecContext and codec-private options. - * On return this object will be filled with options that were not found. + * @param options A dictionary filled with AVCodecContext and codec-private + * options, which are set on top of the options already set in + * avctx, can be NULL. On return this object will be filled with + * options that were not found in the avctx codec context. * * @return zero on success, a negative value on error * @see avcodec_alloc_context3(), avcodec_find_decoder(), avcodec_find_encoder(), - * av_dict_set(), av_opt_find(). + * av_dict_set(), av_opt_set(), av_opt_find(), avcodec_parameters_to_context() */ int avcodec_open2(AVCodecContext *avctx, const AVCodec *codec, AVDictionary **options); From cd0d267b9265af9c3cf19fca0a65992933e4a877 Mon Sep 17 00:00:00 2001 From: Stefano Sabatini Date: Sun, 5 Mar 2023 18:59:10 +0100 Subject: [PATCH 0397/2172] doc/examples/mux: rename alloc_picture to alloc_frame The new name is consistent with the updated API. --- doc/examples/mux.c | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/doc/examples/mux.c b/doc/examples/mux.c index d1f682e1968..b034aad56f7 100644 --- a/doc/examples/mux.c +++ b/doc/examples/mux.c @@ -379,27 +379,27 @@ static int write_audio_frame(AVFormatContext *oc, OutputStream *ost) /**************************************************************/ /* video output */ -static AVFrame *alloc_picture(enum AVPixelFormat pix_fmt, int width, int height) +static AVFrame *alloc_frame(enum AVPixelFormat pix_fmt, int width, int height) { - AVFrame *picture; + AVFrame *frame; int ret; - picture = av_frame_alloc(); - if (!picture) + frame = av_frame_alloc(); + if (!frame) return NULL; - picture->format = pix_fmt; - picture->width = width; - picture->height = height; + frame->format = pix_fmt; + frame->width = width; + frame->height = height; /* allocate the buffers for the frame data */ - ret = av_frame_get_buffer(picture, 0); + ret = av_frame_get_buffer(frame, 0); if (ret < 0) { fprintf(stderr, "Could not allocate frame data.\n"); exit(1); } - return picture; + return frame; } static void open_video(AVFormatContext *oc, const AVCodec *codec, @@ -420,7 +420,7 @@ static void open_video(AVFormatContext *oc, const AVCodec *codec, } /* allocate and init a re-usable frame */ - ost->frame = alloc_picture(c->pix_fmt, c->width, c->height); + ost->frame = alloc_frame(c->pix_fmt, c->width, c->height); if (!ost->frame) { fprintf(stderr, "Could not allocate video frame\n"); exit(1); @@ -431,9 +431,9 @@ static void open_video(AVFormatContext *oc, const AVCodec *codec, * output format. */ ost->tmp_frame = NULL; if (c->pix_fmt != AV_PIX_FMT_YUV420P) { - ost->tmp_frame = alloc_picture(AV_PIX_FMT_YUV420P, c->width, c->height); + ost->tmp_frame = alloc_frame(AV_PIX_FMT_YUV420P, c->width, c->height); if (!ost->tmp_frame) { - fprintf(stderr, "Could not allocate temporary picture\n"); + fprintf(stderr, "Could not allocate temporary video frame\n"); exit(1); } } From 8e5e578453a2b539c93e94bca82157f43417afbf Mon Sep 17 00:00:00 2001 From: James Almer Date: Sun, 12 Mar 2023 16:31:54 -0300 Subject: [PATCH 0398/2172] avocdec/Makefile: add missing dependencies to av1 and libdav1d decoders Missed in d6d576505163c9c5cb42539a6e53d53b003fd252 and b465e6fed0f7bc1b9a0bf934c8674bc56cb82e36 Respectively. Signed-off-by: James Almer --- configure | 2 +- libavcodec/Makefile | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/configure b/configure index b6616f00b6f..03d3c429a58 100755 --- a/configure +++ b/configure @@ -2774,7 +2774,7 @@ asv1_encoder_select="aandcttables bswapdsp fdctdsp pixblockdsp" asv2_decoder_select="blockdsp bswapdsp idctdsp" asv2_encoder_select="aandcttables bswapdsp fdctdsp pixblockdsp" atrac1_decoder_select="sinewin" -av1_decoder_select="av1_frame_split_bsf cbs_av1" +av1_decoder_select="av1_frame_split_bsf cbs_av1 atsc_a53" bink_decoder_select="blockdsp hpeldsp" binkaudio_dct_decoder_select="wma_freqs" binkaudio_rdft_decoder_select="wma_freqs" diff --git a/libavcodec/Makefile b/libavcodec/Makefile index 6c797b8e14d..abae4909d2b 100644 --- a/libavcodec/Makefile +++ b/libavcodec/Makefile @@ -250,7 +250,7 @@ OBJS-$(CONFIG_ATRAC3PAL_DECODER) += atrac3plusdec.o atrac3plus.o \ OBJS-$(CONFIG_ATRAC9_DECODER) += atrac9dec.o OBJS-$(CONFIG_AURA_DECODER) += cyuv.o OBJS-$(CONFIG_AURA2_DECODER) += aura.o -OBJS-$(CONFIG_AV1_DECODER) += av1dec.o +OBJS-$(CONFIG_AV1_DECODER) += av1dec.o dynamic_hdr10_plus.o OBJS-$(CONFIG_AV1_CUVID_DECODER) += cuviddec.o OBJS-$(CONFIG_AV1_MEDIACODEC_DECODER) += mediacodecdec.o OBJS-$(CONFIG_AV1_NVENC_ENCODER) += nvenc_av1.o nvenc.o @@ -1082,7 +1082,7 @@ OBJS-$(CONFIG_LIBARIBB24_DECODER) += libaribb24.o ass.o OBJS-$(CONFIG_LIBCELT_DECODER) += libcelt_dec.o OBJS-$(CONFIG_LIBCODEC2_DECODER) += libcodec2.o OBJS-$(CONFIG_LIBCODEC2_ENCODER) += libcodec2.o -OBJS-$(CONFIG_LIBDAV1D_DECODER) += libdav1d.o +OBJS-$(CONFIG_LIBDAV1D_DECODER) += libdav1d.o dynamic_hdr10_plus.o OBJS-$(CONFIG_LIBDAVS2_DECODER) += libdavs2.o OBJS-$(CONFIG_LIBFDK_AAC_DECODER) += libfdk-aacdec.o OBJS-$(CONFIG_LIBFDK_AAC_ENCODER) += libfdk-aacenc.o From 87ad0a5dd7d12c91badc215c3b5d6745fa7acb02 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Sun, 5 Mar 2023 22:25:04 +0100 Subject: [PATCH 0399/2172] avcodec/escape124: fix signdness of end of input check Fixes: Timeout Fixes: 56561/clusterfuzz-testcase-minimized-ffmpeg_AV_CODEC_ID_ESCAPE124_fuzzer-5560363635834880 Found-by: continuous fuzzing process https://github.com/google/oss-fuzz/tree/master/projects/ffmpeg Signed-off-by: Michael Niedermayer --- libavcodec/escape124.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavcodec/escape124.c b/libavcodec/escape124.c index 024eec59ce8..e9c6b2df1b2 100644 --- a/libavcodec/escape124.c +++ b/libavcodec/escape124.c @@ -89,7 +89,7 @@ static CodeBook unpack_codebook(GetBitContext* gb, unsigned depth, unsigned i, j; CodeBook cb = { 0 }; - if (size >= INT_MAX / 34 || get_bits_left(gb) < size * 34) + if (size >= INT_MAX / 34 || get_bits_left(gb) < (int)size * 34) return cb; if (size >= INT_MAX / sizeof(MacroBlock)) From 98df605f7a8e80471a113f7beb0983c90aa84525 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Sun, 5 Mar 2023 22:37:44 +0100 Subject: [PATCH 0400/2172] avcodec/escape124: Fix some return codes Signed-off-by: Michael Niedermayer --- libavcodec/escape124.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/libavcodec/escape124.c b/libavcodec/escape124.c index e9c6b2df1b2..064a4e6bf57 100644 --- a/libavcodec/escape124.c +++ b/libavcodec/escape124.c @@ -89,11 +89,6 @@ static CodeBook unpack_codebook(GetBitContext* gb, unsigned depth, unsigned i, j; CodeBook cb = { 0 }; - if (size >= INT_MAX / 34 || get_bits_left(gb) < (int)size * 34) - return cb; - - if (size >= INT_MAX / sizeof(MacroBlock)) - return cb; cb.blocks = av_malloc(size ? size * sizeof(MacroBlock) : 1); if (!cb.blocks) return cb; @@ -225,7 +220,7 @@ static int escape124_decode_frame(AVCodecContext *avctx, AVFrame *frame, // represent a lower bound of the space needed for skipped superblocks. Non // skipped SBs need more space. if (get_bits_left(&gb) < 64 + s->num_superblocks * 23LL / 4320) - return -1; + return AVERROR_INVALIDDATA; frame_flags = get_bits_long(&gb, 32); frame_size = get_bits_long(&gb, 32); @@ -276,9 +271,14 @@ static int escape124_decode_frame(AVCodecContext *avctx, AVFrame *frame, } av_freep(&s->codebooks[i].blocks); + if (cb_size >= INT_MAX / 34 || get_bits_left(&gb) < (int)cb_size * 34) + return AVERROR_INVALIDDATA; + + if (cb_size >= INT_MAX / sizeof(MacroBlock)) + return AVERROR_INVALIDDATA; s->codebooks[i] = unpack_codebook(&gb, cb_depth, cb_size); if (!s->codebooks[i].blocks) - return -1; + return AVERROR(ENOMEM); } } From f669dd4dff83024ac80d79a4a5d7089902236a00 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Sun, 5 Mar 2023 22:43:56 +0100 Subject: [PATCH 0401/2172] avcodec/escape124: Simplify unpack_codebook() Signed-off-by: Michael Niedermayer --- libavcodec/escape124.c | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/libavcodec/escape124.c b/libavcodec/escape124.c index 064a4e6bf57..e8a8395f4b1 100644 --- a/libavcodec/escape124.c +++ b/libavcodec/escape124.c @@ -97,15 +97,12 @@ static CodeBook unpack_codebook(GetBitContext* gb, unsigned depth, cb.size = size; for (i = 0; i < size; i++) { unsigned mask_bits = get_bits(gb, 4); - unsigned color0 = get_bits(gb, 15); - unsigned color1 = get_bits(gb, 15); - - for (j = 0; j < 4; j++) { - if (mask_bits & (1 << j)) - cb.blocks[i].pixels[j] = color1; - else - cb.blocks[i].pixels[j] = color0; - } + unsigned color[2]; + color[0] = get_bits(gb, 15); + color[1] = get_bits(gb, 15); + + for (j = 0; j < 4; j++) + cb.blocks[i].pixels[j] = color[(mask_bits>>j) & 1]; } return cb; } From 7c130d6911f5b09bfc648f6ae678c4c0749f61bb Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Sun, 27 Nov 2022 23:34:33 +0100 Subject: [PATCH 0402/2172] avcodec/mpeg12dec: Check input size Fixes: Timeout Fixes: 53599/clusterfuzz-testcase-minimized-ffmpeg_AV_CODEC_ID_IPU_fuzzer-4950102511058944 Found-by: continuous fuzzing process https://github.com/google/oss-fuzz/tree/master/projects/ffmpeg Signed-off-by: Michael Niedermayer --- libavcodec/mpeg12dec.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/libavcodec/mpeg12dec.c b/libavcodec/mpeg12dec.c index 457d985265d..6c4cbccc597 100644 --- a/libavcodec/mpeg12dec.c +++ b/libavcodec/mpeg12dec.c @@ -2956,6 +2956,10 @@ static int ipu_decode_frame(AVCodecContext *avctx, AVFrame *frame, GetBitContext *gb = &m->gb; int ret; + // Check for minimal intra MB size (considering mb header, luma & chroma dc VLC, ac EOB VLC) + if (avpkt->size*8LL < (avctx->width+15)/16 * ((avctx->height+15)/16) * (2 + 3*4 + 2*2 + 2*6)) + return AVERROR_INVALIDDATA; + ret = ff_get_buffer(avctx, frame, 0); if (ret < 0) return ret; From 11eca6018c40f5ebe6af93cbc4b4dce447d8b3bc Mon Sep 17 00:00:00 2001 From: Niklas Haas Date: Mon, 13 Mar 2023 15:10:26 +0100 Subject: [PATCH 0403/2172] avfilter/vf_libplacebo: wrap deprecated opts in FF_API define Signed-off-by: Niklas Haas Signed-off-by: James Almer --- libavfilter/version_major.h | 2 ++ libavfilter/vf_libplacebo.c | 8 ++++++++ 2 files changed, 10 insertions(+) diff --git a/libavfilter/version_major.h b/libavfilter/version_major.h index 899dfdb27db..1decc4012ee 100644 --- a/libavfilter/version_major.h +++ b/libavfilter/version_major.h @@ -35,4 +35,6 @@ * the public API and may change, break or disappear at any time. */ +#define FF_API_LIBPLACEBO_OPTS (LIBAVFILTER_VERSION_MAJOR < 10) + #endif /* AVFILTER_VERSION_MAJOR_H */ diff --git a/libavfilter/vf_libplacebo.c b/libavfilter/vf_libplacebo.c index 7cd495de261..d7572328906 100644 --- a/libavfilter/vf_libplacebo.c +++ b/libavfilter/vf_libplacebo.c @@ -132,11 +132,14 @@ typedef struct LibplaceboContext { int inverse_tonemapping; float crosstalk; int tonemapping_lut_size; + +#if FF_API_LIBPLACEBO_OPTS /* for backwards compatibility */ float desat_str; float desat_exp; int gamut_warning; int gamut_clipping; +#endif /* pl_dither_params */ int dithering; @@ -380,6 +383,7 @@ static int process_frames(AVFilterContext *avctx, AVFrame *out, AVFrame *in) pl_rect2df_aspect_set(&target.crop, aspect, s->pad_crop_ratio); } +#if FF_API_LIBPLACEBO_OPTS /* backwards compatibility with older API */ if (!tonemapping_mode && (s->desat_str >= 0.0f || s->desat_exp >= 0.0f)) { float str = s->desat_str < 0.0f ? 0.9f : s->desat_str; @@ -397,6 +401,7 @@ static int process_frames(AVFilterContext *avctx, AVFrame *out, AVFrame *in) gamut_mode = PL_GAMUT_WARN; if (s->gamut_clipping) gamut_mode = PL_GAMUT_DESATURATE; +#endif /* Update render params */ params = (struct pl_render_params) { @@ -818,11 +823,14 @@ static const AVOption libplacebo_options[] = { { "inverse_tonemapping", "Inverse tone mapping (range expansion)", OFFSET(inverse_tonemapping), AV_OPT_TYPE_BOOL, {.i64 = 0}, 0, 1, DYNAMIC }, { "tonemapping_crosstalk", "Crosstalk factor for tone-mapping", OFFSET(crosstalk), AV_OPT_TYPE_FLOAT, {.dbl = 0.04}, 0.0, 0.30, DYNAMIC }, { "tonemapping_lut_size", "Tone-mapping LUT size", OFFSET(tonemapping_lut_size), AV_OPT_TYPE_INT, {.i64 = 256}, 2, 1024, DYNAMIC }, + +#if FF_API_LIBPLACEBO_OPTS /* deprecated options for backwards compatibility, defaulting to -1 to not override the new defaults */ { "desaturation_strength", "Desaturation strength", OFFSET(desat_str), AV_OPT_TYPE_FLOAT, {.dbl = -1.0}, -1.0, 1.0, DYNAMIC | AV_OPT_FLAG_DEPRECATED }, { "desaturation_exponent", "Desaturation exponent", OFFSET(desat_exp), AV_OPT_TYPE_FLOAT, {.dbl = -1.0}, -1.0, 10.0, DYNAMIC | AV_OPT_FLAG_DEPRECATED }, { "gamut_warning", "Highlight out-of-gamut colors", OFFSET(gamut_warning), AV_OPT_TYPE_BOOL, {.i64 = 0}, 0, 1, DYNAMIC | AV_OPT_FLAG_DEPRECATED }, { "gamut_clipping", "Enable colorimetric gamut clipping", OFFSET(gamut_clipping), AV_OPT_TYPE_BOOL, {.i64 = 0}, 0, 1, DYNAMIC | AV_OPT_FLAG_DEPRECATED }, +#endif { "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" }, From 1231003c3c6d4839a9e838d06f8e16ee7690958f Mon Sep 17 00:00:00 2001 From: Niklas Haas Date: Mon, 13 Mar 2023 14:33:16 +0100 Subject: [PATCH 0404/2172] avfilter/vf_libplacebo: remove deprecated field This has not been functional since a year ago, including in our current minimum dependency of libplacebo (v4.192.0). It also causes build errors against libplacebo v6, so it needs to be removed from the code. We can keep the option around for now, but it should also be removed soon. Signed-off-by: Niklas Haas Signed-off-by: James Almer --- doc/filters.texi | 3 --- libavfilter/vf_libplacebo.c | 7 ++++--- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/doc/filters.texi b/doc/filters.texi index 7a7b2ba4e79..77b594f69cb 100644 --- a/doc/filters.texi +++ b/doc/filters.texi @@ -16242,9 +16242,6 @@ Disable linear light scaling. @item disable_builtin Disable built-in GPU sampling (forces LUT). -@item force_icc_lut -Force the use of a full ICC 3DLUT for gamut mapping. - @item disable_fbos Forcibly disable FBOs, resulting in loss of almost all functionality, but offering the maximum possible speed. diff --git a/libavfilter/vf_libplacebo.c b/libavfilter/vf_libplacebo.c index d7572328906..757dc519e9a 100644 --- a/libavfilter/vf_libplacebo.c +++ b/libavfilter/vf_libplacebo.c @@ -97,7 +97,6 @@ typedef struct LibplaceboContext { float polar_cutoff; int disable_linear; int disable_builtin; - int force_icc_lut; int force_dither; int disable_fbos; @@ -139,6 +138,7 @@ typedef struct LibplaceboContext { float desat_exp; int gamut_warning; int gamut_clipping; + int force_icc_lut; #endif /* pl_dither_params */ @@ -463,7 +463,6 @@ 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_icc_lut = s->force_icc_lut, .force_dither = s->force_dither, .disable_fbos = s->disable_fbos, }; @@ -855,7 +854,9 @@ static const AVOption libplacebo_options[] = { { "polar_cutoff", "Polar LUT cutoff", OFFSET(polar_cutoff), AV_OPT_TYPE_FLOAT, {.dbl = 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_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 }, +#if FF_API_LIBPLACEBO_OPTS + { "force_icc_lut", "Deprecated, does nothing", OFFSET(force_icc_lut), AV_OPT_TYPE_BOOL, {.i64 = 0}, 0, 1, DYNAMIC | AV_OPT_FLAG_DEPRECATED }, +#endif { "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 fba9d9609fe00c8c4d04b76f9ecdd274aad318dd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Ekstr=C3=B6m?= Date: Thu, 9 Mar 2023 20:27:06 +0200 Subject: [PATCH 0405/2172] avcodec/libsvtav1: use larger of bit rate and max rate for buffer size Generally if maxrate is set, the calculation should be maxrate over bufsize. This additionally enables CRF + maxrate & bufsize usage. In order to keep negative values from enabling zero to be treated as larger and causing a division by zero, check that one of the variables is larger than zero. --- libavcodec/libsvtav1.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/libavcodec/libsvtav1.c b/libavcodec/libsvtav1.c index 56e1e22b512..9174e2753cd 100644 --- a/libavcodec/libsvtav1.c +++ b/libavcodec/libsvtav1.c @@ -184,8 +184,10 @@ static int config_enc_params(EbSvtAv1EncConfiguration *param, param->min_qp_allowed = avctx->qmin; } param->max_bit_rate = avctx->rc_max_rate; - if (avctx->bit_rate && avctx->rc_buffer_size) - param->maximum_buffer_size_ms = avctx->rc_buffer_size * 1000LL / avctx->bit_rate; + if ((avctx->bit_rate > 0 || avctx->rc_max_rate > 0) && avctx->rc_buffer_size) + param->maximum_buffer_size_ms = + avctx->rc_buffer_size * 1000LL / + FFMAX(avctx->bit_rate, avctx->rc_max_rate); if (svt_enc->crf > 0) { param->qp = svt_enc->crf; @@ -302,7 +304,8 @@ static int config_enc_params(EbSvtAv1EncConfiguration *param, avctx->bit_rate = param->rate_control_mode > 0 ? param->target_bit_rate : 0; avctx->rc_max_rate = param->max_bit_rate; - avctx->rc_buffer_size = param->maximum_buffer_size_ms * avctx->bit_rate / 1000LL; + avctx->rc_buffer_size = param->maximum_buffer_size_ms * + FFMAX(avctx->bit_rate, avctx->rc_max_rate) / 1000LL; if (avctx->bit_rate || avctx->rc_max_rate || avctx->rc_buffer_size) { AVCPBProperties *cpb_props = ff_add_cpb_side_data(avctx); From 7f825d3335e7612c3ce47975ebfe59bd1c418ea4 Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt Date: Sun, 12 Mar 2023 18:50:26 +0100 Subject: [PATCH 0406/2172] avcodec/libxavs: Use frame_num instead of frame_number Forgotten in 6b6f7db81932f94876ff4bcfd2da0582b8ab897e. Reviewed-by: Marton Balint Signed-off-by: Andreas Rheinhardt --- libavcodec/libxavs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavcodec/libxavs.c b/libavcodec/libxavs.c index 9ed73d1042a..6c29539f243 100644 --- a/libavcodec/libxavs.c +++ b/libavcodec/libxavs.c @@ -141,7 +141,7 @@ static int XAVS_frame(AVCodecContext *avctx, AVPacket *pkt, x4->pic.i_pts = frame->pts; x4->pic.i_type = XAVS_TYPE_AUTO; - x4->pts_buffer[avctx->frame_number % (avctx->max_b_frames+1)] = frame->pts; + x4->pts_buffer[avctx->frame_num % (avctx->max_b_frames+1)] = frame->pts; } if (xavs_encoder_encode(x4->enc, &nal, &nnal, From 430dcd52b6683f92ddc3e089de46a5acda999ea1 Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt Date: Sun, 12 Mar 2023 18:50:57 +0100 Subject: [PATCH 0407/2172] avcodec/libopencore-amr: Use frame_number instead of frame_num Forgotten in 6b6f7db81932f94876ff4bcfd2da0582b8ab897e. Reviewed-by: Marton Balint Signed-off-by: Andreas Rheinhardt --- libavcodec/libopencore-amr.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libavcodec/libopencore-amr.c b/libavcodec/libopencore-amr.c index fd9e6e63430..641a1561298 100644 --- a/libavcodec/libopencore-amr.c +++ b/libavcodec/libopencore-amr.c @@ -106,8 +106,8 @@ static int amr_nb_decode_frame(AVCodecContext *avctx, AVFrame *frame, enum Mode dec_mode; int packet_size, ret; - ff_dlog(avctx, "amr_decode_frame buf=%p buf_size=%d frame_count=%d!!\n", - buf, buf_size, avctx->frame_number); + ff_dlog(avctx, "amr_decode_frame buf=%p buf_size=%d frame_count=%"PRId64"!!\n", + buf, buf_size, avctx->frame_num); /* get output buffer */ frame->nb_samples = 160; From 4175022bdb958597d8d73e803bc18d0da93c46c3 Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt Date: Sun, 12 Mar 2023 19:05:05 +0100 Subject: [PATCH 0408/2172] avcodec/libvpxdec: Constify VP9-decoder Possible since 8d226fb9786f34760e80e0d6b403bd63e9ac4ddd. Reviewed-by: James Zern Signed-off-by: Andreas Rheinhardt --- libavcodec/allcodecs.c | 2 +- libavcodec/libvpxdec.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/libavcodec/allcodecs.c b/libavcodec/allcodecs.c index e593ad19afc..385ee348035 100644 --- a/libavcodec/allcodecs.c +++ b/libavcodec/allcodecs.c @@ -798,7 +798,7 @@ extern const FFCodec ff_libvorbis_decoder; extern const FFCodec ff_libvpx_vp8_encoder; extern const FFCodec ff_libvpx_vp8_decoder; extern FFCodec ff_libvpx_vp9_encoder; -extern FFCodec ff_libvpx_vp9_decoder; +extern const FFCodec ff_libvpx_vp9_decoder; /* preferred over libwebp */ extern const FFCodec ff_libwebp_anim_encoder; extern const FFCodec ff_libwebp_encoder; diff --git a/libavcodec/libvpxdec.c b/libavcodec/libvpxdec.c index 8e6291fe209..f480545ae04 100644 --- a/libavcodec/libvpxdec.c +++ b/libavcodec/libvpxdec.c @@ -377,7 +377,7 @@ static av_cold int vp9_init(AVCodecContext *avctx) return vpx_init(avctx, &ctx->decoder, vpx_codec_vp9_dx()); } -FFCodec ff_libvpx_vp9_decoder = { +const FFCodec ff_libvpx_vp9_decoder = { .p.name = "libvpx-vp9", CODEC_LONG_NAME("libvpx VP9"), .p.type = AVMEDIA_TYPE_VIDEO, From 1091963d3898eac8aaf8402dc5a5f9867ba96bd1 Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt Date: Sun, 12 Mar 2023 22:35:20 +0100 Subject: [PATCH 0409/2172] avfilter/vf_ssim360: Use correct type in sizeof MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit SSIM360Context.ssim360_hist is an array of four pointers to double; so sizeof(*ssim360_hist[0]) (=sizeof(double)) is the correct size to use to calculate the amount of memory to allocate, not sizeof(*ssim360_hist) (which is sizeof(double*)). Use FF_ALLOCZ_TYPED_ARRAY to avoid this issue altogether. Fixes Coverity issue #1520671. Reviewed-by: Anton Khirnov Reviewed-by: Jan Ekström Signed-off-by: Andreas Rheinhardt --- libavfilter/vf_ssim360.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavfilter/vf_ssim360.c b/libavfilter/vf_ssim360.c index 3eb8e43bbc8..f8ce0744f23 100644 --- a/libavfilter/vf_ssim360.c +++ b/libavfilter/vf_ssim360.c @@ -1624,7 +1624,7 @@ static int config_output(AVFilterLink *outlink) memset(s->ssim360_percentile_sum, 0, sizeof(s->ssim360_percentile_sum)); for (int i = 0; i < s->nb_components; i++) { - s->ssim360_hist[i] = av_calloc(SSIM360_HIST_SIZE, sizeof(*s->ssim360_hist)); + FF_ALLOCZ_TYPED_ARRAY(s->ssim360_hist[i], SSIM360_HIST_SIZE); if (!s->ssim360_hist[i]) return AVERROR(ENOMEM); } From 2732d0507c5ee6961d49212e71717fc4fbc72d16 Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt Date: Sun, 12 Mar 2023 22:45:57 +0100 Subject: [PATCH 0410/2172] avfilter/vf_ssim360: Remove dead code MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fixes Coverity issue #1520669. Reviewed-by: Anton Khirnov Reviewed-by: Jan Ekström Signed-off-by: Andreas Rheinhardt --- libavfilter/vf_ssim360.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/libavfilter/vf_ssim360.c b/libavfilter/vf_ssim360.c index f8ce0744f23..5794275c2cd 100644 --- a/libavfilter/vf_ssim360.c +++ b/libavfilter/vf_ssim360.c @@ -1274,10 +1274,6 @@ static int parse_heatmaps(void *logctx, HeatmapList **proot, ret = AVERROR(ENOMEM); goto fail; } - if (!line) { - av_freep(&line); - break; - } // first value is frame id av_strtok(line, ",", &saveptr); From f456c192d99019ff7f0587abb7a4802a1d7ba102 Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt Date: Sun, 12 Mar 2023 22:51:06 +0100 Subject: [PATCH 0411/2172] avcodec/libx264: Fix leak in case of allocation failure MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fixes Coverity issue #1518906. Reviewed-by: Anton Khirnov Reviewed-by: Jan Ekström Signed-off-by: Andreas Rheinhardt --- libavcodec/libx264.c | 1 + 1 file changed, 1 insertion(+) diff --git a/libavcodec/libx264.c b/libavcodec/libx264.c index f65ac5dacc2..e59939a8a7a 100644 --- a/libavcodec/libx264.c +++ b/libavcodec/libx264.c @@ -503,6 +503,7 @@ FF_ENABLE_DEPRECATION_WARNINGS if (sei_data) { pic->extra_sei.payloads = av_mallocz(sizeof(pic->extra_sei.payloads[0])); if (pic->extra_sei.payloads == NULL) { + av_free(sei_data); ret = AVERROR(ENOMEM); goto fail; } From df53d7a19424698b0d8f6f7cc8907b03dfcabba8 Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt Date: Sun, 12 Mar 2023 23:27:57 +0100 Subject: [PATCH 0412/2172] avcodec/libx264: Pass x264_picture_t* directly MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reviewed-by: Anton Khirnov Reviewed-by: Jan Ekström Signed-off-by: Andreas Rheinhardt --- libavcodec/libx264.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/libavcodec/libx264.c b/libavcodec/libx264.c index e59939a8a7a..df70e9df9bd 100644 --- a/libavcodec/libx264.c +++ b/libavcodec/libx264.c @@ -311,11 +311,8 @@ static void reconfig_encoder(AVCodecContext *ctx, const AVFrame *frame) } } -static void free_picture(AVCodecContext *ctx) +static void free_picture(x264_picture_t *pic) { - 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); @@ -554,7 +551,7 @@ FF_ENABLE_DEPRECATION_WARNINGS return 0; fail: - free_picture(ctx); + free_picture(pic); *ppic = NULL; return ret; } From 19e35edaf1f44f19932cdfbc01fec19fc49ed5a2 Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt Date: Mon, 13 Mar 2023 05:49:31 +0100 Subject: [PATCH 0413/2172] avcodec/libx264: Use dedicated pointer for accesses MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reviewed-by: Anton Khirnov Reviewed-by: Jan Ekström Signed-off-by: Andreas Rheinhardt --- libavcodec/libx264.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/libavcodec/libx264.c b/libavcodec/libx264.c index df70e9df9bd..94006d2b203 100644 --- a/libavcodec/libx264.c +++ b/libavcodec/libx264.c @@ -498,19 +498,19 @@ FF_ENABLE_DEPRECATION_WARNINGS goto fail; if (sei_data) { - pic->extra_sei.payloads = av_mallocz(sizeof(pic->extra_sei.payloads[0])); - if (pic->extra_sei.payloads == NULL) { + sei->payloads = av_mallocz(sizeof(sei->payloads[0])); + if (!sei->payloads) { av_free(sei_data); ret = AVERROR(ENOMEM); goto fail; } - pic->extra_sei.sei_free = av_free; + sei->sei_free = av_free; - pic->extra_sei.payloads[0].payload_size = sei_size; - pic->extra_sei.payloads[0].payload = sei_data; - pic->extra_sei.num_payloads = 1; - pic->extra_sei.payloads[0].payload_type = 4; + sei->payloads[0].payload_size = sei_size; + sei->payloads[0].payload = sei_data; + sei->payloads[0].payload_type = 4; + sei->num_payloads = 1; } } From a6e9d01f88a707f8a2057e01b5ad2e8968109530 Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt Date: Mon, 13 Mar 2023 13:41:43 +0100 Subject: [PATCH 0414/2172] avcodec/libx264: Use av_pix_fmt_count_planes() where appropriate MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This also fixes the number of planes for the NV formats (this seems to not have caused any problems). Reviewed-by: Anton Khirnov Reviewed-by: Jan Ekström Signed-off-by: Andreas Rheinhardt --- libavcodec/libx264.c | 24 +----------------------- 1 file changed, 1 insertion(+), 23 deletions(-) diff --git a/libavcodec/libx264.c b/libavcodec/libx264.c index 94006d2b203..92828fabc34 100644 --- a/libavcodec/libx264.c +++ b/libavcodec/libx264.c @@ -189,28 +189,6 @@ static int encode_nals(AVCodecContext *ctx, AVPacket *pkt, return 1; } -static int avfmt2_num_planes(int avfmt) -{ - switch (avfmt) { - case AV_PIX_FMT_YUV420P: - case AV_PIX_FMT_YUVJ420P: - case AV_PIX_FMT_YUV420P9: - case AV_PIX_FMT_YUV420P10: - case AV_PIX_FMT_YUV444P: - return 3; - - case AV_PIX_FMT_BGR0: - case AV_PIX_FMT_BGR24: - case AV_PIX_FMT_RGB24: - case AV_PIX_FMT_GRAY8: - case AV_PIX_FMT_GRAY10: - return 1; - - default: - return 3; - } -} - static void reconfig_encoder(AVCodecContext *ctx, const AVFrame *frame) { X264Context *x4 = ctx->priv_data; @@ -440,7 +418,7 @@ static int setup_frame(AVCodecContext *ctx, const AVFrame *frame, #endif if (bit_depth > 8) pic->img.i_csp |= X264_CSP_HIGH_DEPTH; - pic->img.i_plane = avfmt2_num_planes(ctx->pix_fmt); + pic->img.i_plane = av_pix_fmt_count_planes(ctx->pix_fmt); for (int i = 0; i < pic->img.i_plane; i++) { pic->img.plane[i] = frame->data[i]; From d04dbf48fc7474747e27caceeed7153d1c0585e4 Mon Sep 17 00:00:00 2001 From: Zhao Zhili Date: Mon, 6 Mar 2023 20:02:07 +0800 Subject: [PATCH 0415/2172] avformat/mov: fix ISO/IEC 23003-5 support Missing floating-point formats support. Signed-off-by: Zhao Zhili --- libavformat/isom.h | 2 ++ libavformat/mov.c | 49 ++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 51 insertions(+) diff --git a/libavformat/isom.h b/libavformat/isom.h index 5107b4eb748..4b1cd42f0fd 100644 --- a/libavformat/isom.h +++ b/libavformat/isom.h @@ -418,6 +418,8 @@ static inline enum AVCodecID ff_mov_get_lpcm_codec_id(int bps, int flags) #define MOV_ISMV_TTML_TAG MKTAG('d', 'f', 'x', 'p') #define MOV_MP4_TTML_TAG MKTAG('s', 't', 'p', 'p') +#define MOV_MP4_FPCM_TAG MKTAG('f', 'p', 'c', 'm') +#define MOV_MP4_IPCM_TAG MKTAG('i', 'p', 'c', 'm') struct MP4TrackKindValueMapping { int disposition; diff --git a/libavformat/mov.c b/libavformat/mov.c index a9911c0f799..14528bdcaa1 100644 --- a/libavformat/mov.c +++ b/libavformat/mov.c @@ -1591,6 +1591,10 @@ static int mov_read_pcmc(MOVContext *c, AVIOContext *pb, MOVAtom atom) { int format_flags; int version, flags; + int pcm_sample_size; + AVFormatContext *fc = c->fc; + AVStream *st; + MOVStreamContext *sc; if (atom.size < 6) { av_log(c->fc, AV_LOG_ERROR, "Empty pcmC box\n"); @@ -1608,6 +1612,51 @@ static int mov_read_pcmc(MOVContext *c, AVIOContext *pb, MOVAtom atom) } format_flags = avio_r8(pb); + pcm_sample_size = avio_r8(pb); + + if (fc->nb_streams < 1) + return AVERROR_INVALIDDATA; + + st = fc->streams[fc->nb_streams - 1]; + sc = st->priv_data; + + if (sc->format == MOV_MP4_FPCM_TAG) { + switch (pcm_sample_size) { + case 32: + st->codecpar->codec_id = AV_CODEC_ID_PCM_F32BE; + break; + case 64: + st->codecpar->codec_id = AV_CODEC_ID_PCM_F64BE; + break; + default: + av_log(fc, AV_LOG_ERROR, "invalid pcm_sample_size %d for %s\n", + pcm_sample_size, + av_fourcc2str(sc->format)); + return AVERROR_INVALIDDATA; + } + } else if (sc->format == MOV_MP4_IPCM_TAG) { + switch (pcm_sample_size) { + case 16: + st->codecpar->codec_id = AV_CODEC_ID_PCM_S16BE; + break; + case 24: + st->codecpar->codec_id = AV_CODEC_ID_PCM_S24BE; + break; + case 32: + st->codecpar->codec_id = AV_CODEC_ID_PCM_S32BE; + break; + default: + av_log(fc, AV_LOG_ERROR, "invalid pcm_sample_size %d for %s\n", + pcm_sample_size, + av_fourcc2str(sc->format)); + return AVERROR_INVALIDDATA; + } + } else { + av_log(fc, AV_LOG_ERROR, "'pcmC' with invalid sample entry '%s'\n", + av_fourcc2str(sc->format)); + return AVERROR_INVALIDDATA; + } + if (format_flags & 1) // indicates little-endian format. If not present, big-endian format is used set_last_stream_little_endian(c->fc); From a3dc677b9f060c08c0000503f640bc9bf6a66c51 Mon Sep 17 00:00:00 2001 From: Zhao Zhili Date: Mon, 6 Mar 2023 20:02:08 +0800 Subject: [PATCH 0416/2172] avformat/isom_tags: remove ipcm from movaudio_tags ipcm is defined by ISO/IEC 23003-5, not defined by quicktime. After adding ISO/IEC 23003-5 support, we don't need it for ticket #9219. Signed-off-by: Zhao Zhili --- libavformat/isom_tags.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/libavformat/isom_tags.c b/libavformat/isom_tags.c index e2b80405cc8..86c72725256 100644 --- a/libavformat/isom_tags.c +++ b/libavformat/isom_tags.c @@ -321,8 +321,6 @@ 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_S32BE, MKTAG('i', 'n', '3', '2') }, From d7e864366be2c4807d6d0796177051ad32c6378d Mon Sep 17 00:00:00 2001 From: Zhao Zhili Date: Mon, 6 Mar 2023 20:02:09 +0800 Subject: [PATCH 0417/2172] avformat/mov: parse ISO-14496-12 ChannelLayout Only support chnl version 0 now. Signed-off-by: Zhao Zhili --- libavformat/mov.c | 85 +++++++++++- libavformat/mov_chan.c | 296 +++++++++++++++++++++++++++++++++++++++++ libavformat/mov_chan.h | 26 ++++ 3 files changed, 406 insertions(+), 1 deletion(-) diff --git a/libavformat/mov.c b/libavformat/mov.c index 14528bdcaa1..057fd872b10 100644 --- a/libavformat/mov.c +++ b/libavformat/mov.c @@ -940,6 +940,88 @@ static int mov_read_chan(MOVContext *c, AVIOContext *pb, MOVAtom atom) return 0; } +static int mov_read_chnl(MOVContext *c, AVIOContext *pb, MOVAtom atom) +{ + int64_t end = av_sat_add64(avio_tell(pb), atom.size); + int stream_structure; + int version, flags; + int ret = 0; + AVStream *st; + + if (c->fc->nb_streams < 1) + return 0; + st = c->fc->streams[c->fc->nb_streams-1]; + + version = avio_r8(pb); + flags = avio_rb24(pb); + if (version != 0 || flags != 0) { + av_log(c->fc, AV_LOG_ERROR, + "Unsupported 'chnl' box with version %d, flags: %#x", + version, flags); + return AVERROR_INVALIDDATA; + } + + stream_structure = avio_r8(pb); + + // stream carries channels + if (stream_structure & 1) { + int layout = avio_r8(pb); + + av_log(c->fc, AV_LOG_TRACE, "'chnl' layout %d\n", layout); + if (!layout) { + uint8_t *positions = av_malloc(st->codecpar->ch_layout.nb_channels); + + if (!positions) + return AVERROR(ENOMEM); + for (int i = 0; i < st->codecpar->ch_layout.nb_channels; i++) { + int speaker_pos = avio_r8(pb); + + av_log(c->fc, AV_LOG_TRACE, "speaker_position %d\n", speaker_pos); + if (speaker_pos == 126) { // explicit position + avpriv_request_sample(c->fc, "explicit position"); + av_freep(&positions); + return AVERROR_PATCHWELCOME; + } else { + positions[i] = speaker_pos; + } + } + + ret = ff_mov_get_layout_from_channel_positions(positions, + st->codecpar->ch_layout.nb_channels, + &st->codecpar->ch_layout); + av_freep(&positions); + if (ret) { + av_log(c->fc, AV_LOG_ERROR, + "get channel layout from speaker positions failed, %s\n", + av_err2str(ret)); + return ret; + } + } else { + uint64_t omitted_channel_map = avio_rb64(pb); + + if (omitted_channel_map) { + avpriv_request_sample(c->fc, "omitted_channel_map 0x%" PRIx64 " != 0", + omitted_channel_map); + return AVERROR_PATCHWELCOME; + } + ff_mov_get_channel_layout_from_config(layout, &st->codecpar->ch_layout); + } + } + + // stream carries objects + if (stream_structure & 2) { + int obj_count = avio_r8(pb); + av_log(c->fc, AV_LOG_TRACE, "'chnl' with object_count %d\n", obj_count); + } + + if (avio_tell(pb) != end) { + av_log(c->fc, AV_LOG_WARNING, "skip %" PRId64 " bytes of unknown data inside chnl\n", + end - avio_tell(pb)); + avio_seek(pb, end, SEEK_SET); + } + return ret; +} + static int mov_read_wfex(MOVContext *c, AVIOContext *pb, MOVAtom atom) { AVStream *st; @@ -7817,7 +7899,8 @@ static const MOVParseTableEntry mov_default_parse_table[] = { { MKTAG('w','i','d','e'), mov_read_wide }, /* place holder */ { MKTAG('w','f','e','x'), mov_read_wfex }, { MKTAG('c','m','o','v'), mov_read_cmov }, -{ MKTAG('c','h','a','n'), mov_read_chan }, /* channel layout */ +{ MKTAG('c','h','a','n'), mov_read_chan }, /* channel layout from quicktime */ +{ MKTAG('c','h','n','l'), mov_read_chnl }, /* channel layout from ISO-14496-12 */ { MKTAG('d','v','c','1'), mov_read_dvc1 }, { MKTAG('s','g','p','d'), mov_read_sgpd }, { MKTAG('s','b','g','p'), mov_read_sbgp }, diff --git a/libavformat/mov_chan.c b/libavformat/mov_chan.c index f66bf0df7fd..df17976e597 100644 --- a/libavformat/mov_chan.c +++ b/libavformat/mov_chan.c @@ -551,3 +551,299 @@ int ff_mov_read_chan(AVFormatContext *s, AVIOContext *pb, AVStream *st, return 0; } + +/* ISO/IEC 23001-8, 8.2 */ +static const AVChannelLayout iso_channel_configuration[] = { + // 0: any setup + {}, + + // 1: centre front + AV_CHANNEL_LAYOUT_MONO, + + // 2: left front, right front + AV_CHANNEL_LAYOUT_STEREO, + + // 3: centre front, left front, right front + AV_CHANNEL_LAYOUT_SURROUND, + + // 4: centre front, left front, right front, rear centre + AV_CHANNEL_LAYOUT_4POINT0, + + // 5: centre front, left front, right front, left surround, right surround + AV_CHANNEL_LAYOUT_5POINT0, + + // 6: 5 + LFE + AV_CHANNEL_LAYOUT_5POINT1, + + // 7: centre front, left front centre, right front centre, + // left front, right front, left surround, right surround, LFE + AV_CHANNEL_LAYOUT_7POINT1_WIDE, + + // 8: channel1, channel2 + AV_CHANNEL_LAYOUT_STEREO_DOWNMIX, + + // 9: left front, right front, rear centre + AV_CHANNEL_LAYOUT_2_1, + + // 10: left front, right front, left surround, right surround + AV_CHANNEL_LAYOUT_2_2, + + // 11: centre front, left front, right front, left surround, right surround, rear centre, LFE + AV_CHANNEL_LAYOUT_6POINT1, + + // 12: centre front, left front, right front + // left surround, right surround + // rear surround left, rear surround right + // LFE + AV_CHANNEL_LAYOUT_7POINT1, + + // 13: + AV_CHANNEL_LAYOUT_22POINT2, + + // 14: + AV_CHANNEL_LAYOUT_7POINT1_TOP_BACK, + + // TODO: 15 - 20 +}; + +/* ISO/IEC 23001-8, table 8 */ +static const enum AVChannel iso_channel_position[] = { + // 0: left front + AV_CHAN_FRONT_LEFT, + + // 1: right front + AV_CHAN_FRONT_RIGHT, + + // 2: centre front + AV_CHAN_FRONT_CENTER, + + // 3: low frequence enhancement + AV_CHAN_LOW_FREQUENCY, + + // 4: left surround + // TODO + AV_CHAN_NONE, + + // 5: right surround + // TODO + AV_CHAN_NONE, + + // 6: left front centre + AV_CHAN_FRONT_LEFT_OF_CENTER, + + // 7: right front centre + AV_CHAN_FRONT_RIGHT_OF_CENTER, + + // 8: rear surround left + AV_CHAN_BACK_LEFT, + + // 9: rear surround right + AV_CHAN_BACK_RIGHT, + + // 10: rear centre + AV_CHAN_BACK_CENTER, + + // 11: left surround direct + AV_CHAN_SURROUND_DIRECT_LEFT, + + // 12: right surround direct + AV_CHAN_SURROUND_DIRECT_RIGHT, + + // 13: left side surround + AV_CHAN_SIDE_LEFT, + + // 14: right side surround + AV_CHAN_SIDE_RIGHT, + + // 15: left wide front + AV_CHAN_WIDE_LEFT, + + // 16: right wide front + AV_CHAN_WIDE_RIGHT, + + // 17: left front vertical height + AV_CHAN_TOP_FRONT_LEFT, + + // 18: right front vertical height + AV_CHAN_TOP_FRONT_RIGHT, + + // 19: centre front vertical height + AV_CHAN_TOP_FRONT_CENTER, + + // 20: left surround vertical height rear + AV_CHAN_TOP_BACK_LEFT, + + // 21: right surround vertical height rear + AV_CHAN_TOP_BACK_RIGHT, + + // 22: centre vertical height rear + AV_CHAN_TOP_BACK_CENTER, + + // 23: left vertical height side surround + AV_CHAN_TOP_SIDE_LEFT, + + // 24: right vertical height side surround + AV_CHAN_TOP_SIDE_RIGHT, + + // 25: top centre surround + AV_CHAN_TOP_CENTER, + + // 26: low frequency enhancement 2 + AV_CHAN_LOW_FREQUENCY_2, + + // 27: left front vertical bottom + AV_CHAN_BOTTOM_FRONT_LEFT, + + // 28: right front vertical bottom + AV_CHAN_BOTTOM_FRONT_RIGHT, + + // 29: centre front vertical bottom + AV_CHAN_BOTTOM_FRONT_CENTER, + + // 30: left vertical height surround + // TODO + AV_CHAN_NONE, + + // 31: right vertical height surround + // TODO + AV_CHAN_NONE, + + // 32, 33, 34, 35, reserved + AV_CHAN_NONE, + AV_CHAN_NONE, + AV_CHAN_NONE, + AV_CHAN_NONE, + + // 36: low frequency enhancement 3 + AV_CHAN_NONE, + + // 37: left edge of screen + AV_CHAN_NONE, + // 38: right edge of screen + AV_CHAN_NONE, + // 39: half-way between centre of screen and left edge of screen + AV_CHAN_NONE, + // 40: half-way between centre of screen and right edge of screen + AV_CHAN_NONE, + + // 41: left back surround + AV_CHAN_NONE, + + // 42: right back surround + AV_CHAN_NONE, + + // 43 - 125: reserved + // 126: explicit position + // 127: unknown /undefined +}; + +int ff_mov_get_channel_config_from_layout(const AVChannelLayout *layout, int *config) +{ + // Set default value which means any setup in 23001-8 + *config = 0; + for (int i = 0; i < FF_ARRAY_ELEMS(iso_channel_configuration); i++) { + if (!av_channel_layout_compare(layout, iso_channel_configuration + i)) { + *config = i; + break; + } + } + + return 0; +} + +int ff_mov_get_channel_layout_from_config(int config, AVChannelLayout *layout) +{ + if (config > 0 && config < FF_ARRAY_ELEMS(iso_channel_configuration)) { + av_channel_layout_copy(layout, &iso_channel_configuration[config]); + return 0; + } + + return -1; +} + +int ff_mov_get_channel_positions_from_layout(const AVChannelLayout *layout, + uint8_t *position, int position_num) +{ + enum AVChannel channel; + + if (position_num < layout->nb_channels) + return AVERROR(EINVAL); + + for (int i = 0; i < layout->nb_channels; i++) { + position[i] = 127; + channel = av_channel_layout_channel_from_index(layout, i); + if (channel == AV_CHAN_NONE) + return AVERROR(EINVAL); + + for (int j = 0; j < FF_ARRAY_ELEMS(iso_channel_position); j++) { + if (iso_channel_position[j] == channel) { + position[i] = j; + break; + } + } + if (position[i] == 127) + return AVERROR(EINVAL); + } + + return 0; +} + +int ff_mov_get_layout_from_channel_positions(const uint8_t *position, int position_num, + AVChannelLayout *layout) +{ + int ret; + enum AVChannel channel; + + av_channel_layout_uninit(layout); + + if (position_num <= 63) { + layout->order = AV_CHANNEL_ORDER_NATIVE; + layout->nb_channels = position_num; + for (int i = 0; i < position_num; i++) { + if (position[i] >= FF_ARRAY_ELEMS(iso_channel_position)) { + ret = AVERROR_PATCHWELCOME; + goto error; + } + + channel = iso_channel_position[position[i]]; + // unsupported layout + if (channel == AV_CHAN_NONE) { + ret = AVERROR_PATCHWELCOME; + goto error; + } + + layout->u.mask |= 1ULL << channel; + } + } else { + layout->order = AV_CHANNEL_ORDER_CUSTOM; + layout->nb_channels = position_num; + layout->u.map = av_calloc(position_num, sizeof(*layout->u.map)); + if (!layout->u.map) { + ret = AVERROR(ENOMEM); + goto error; + } + + for (int i = 0; i < position_num; i++) { + if (position[i] >= FF_ARRAY_ELEMS(iso_channel_position)) { + ret = AVERROR_PATCHWELCOME; + goto error; + } + + channel = iso_channel_position[position[i]]; + // unsupported layout + if (channel == AV_CHAN_NONE) { + ret = AVERROR_PATCHWELCOME; + goto error; + } + + layout->u.map[i].id = channel; + } + } + + + return 0; + +error: + av_channel_layout_uninit(layout); + return ret; +} diff --git a/libavformat/mov_chan.h b/libavformat/mov_chan.h index 93d98787986..8c807798ab4 100644 --- a/libavformat/mov_chan.h +++ b/libavformat/mov_chan.h @@ -163,4 +163,30 @@ int ff_mov_get_channel_layout_tag(const AVCodecParameters *par, int ff_mov_read_chan(AVFormatContext *s, AVIOContext *pb, AVStream *st, int64_t size); +/** + * Get ISO/IEC 23001-8 ChannelConfiguration from AVChannelLayout. + * + */ +int ff_mov_get_channel_config_from_layout(const AVChannelLayout *layout, int *config); + +/** + * Get AVChannelLayout from ISO/IEC 23001-8 ChannelConfiguration. + * + * @return 0 for success, -1 for doesn't match, layout is untouched on failure + */ + +int ff_mov_get_channel_layout_from_config(int config, AVChannelLayout *layout); + +/** + * Get ISO/IEC 23001-8 OutputChannelPosition from AVChannelLayout. + */ +int ff_mov_get_channel_positions_from_layout(const AVChannelLayout *layout, + uint8_t *position, int position_num); + +/** + * Get AVChannelLayout from ISO/IEC 23001-8 OutputChannelPosition. + */ +int ff_mov_get_layout_from_channel_positions(const uint8_t *position, int position_num, + AVChannelLayout *layout); + #endif /* AVFORMAT_MOV_CHAN_H */ From d4ee177a36c59b19de474d3713304c7828263cb0 Mon Sep 17 00:00:00 2001 From: Zhao Zhili Date: Mon, 6 Mar 2023 20:02:10 +0800 Subject: [PATCH 0418/2172] avformat/movenc: add PCM in mp4 support It's defined by ISO/IEC 23003-5. Fixes ticket #10185 Signed-off-by: Zhao Zhili --- libavformat/movenc.c | 84 +++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 83 insertions(+), 1 deletion(-) diff --git a/libavformat/movenc.c b/libavformat/movenc.c index c4fcb5f8b1b..2ec575c954d 100644 --- a/libavformat/movenc.c +++ b/libavformat/movenc.c @@ -1179,6 +1179,68 @@ static int mov_write_btrt_tag(AVIOContext *pb, MOVTrack *track) return update_size(pb, pos); } +static int mov_write_chnl_tag(AVFormatContext *s, AVIOContext *pb, MOVTrack *track) +{ + int64_t pos = avio_tell(pb); + int config = 0; + int ret; + uint8_t *speaker_pos = NULL; + const AVChannelLayout *layout = &track->par->ch_layout; + + ret = ff_mov_get_channel_config_from_layout(layout, &config); + if (ret || !config) { + config = 0; + speaker_pos = av_malloc(layout->nb_channels); + ret = ff_mov_get_channel_positions_from_layout(layout, + speaker_pos, layout->nb_channels); + if (ret) { + char buf[128] = {}; + + av_freep(&speaker_pos); + av_channel_layout_describe(layout, buf, sizeof(buf)); + av_log(s, AV_LOG_ERROR, "unsupported channel layout %s\n", buf); + return ret; + } + } + + avio_wb32(pb, 0); /* size */ + ffio_wfourcc(pb, "chnl"); + avio_wb32(pb, 0); /* version & flags */ + + avio_w8(pb, 1); /* stream_structure */ + avio_w8(pb, config); + if (config) { + avio_wb64(pb, 0); + } else { + for (int i = 0; i < layout->nb_channels; i++) + avio_w8(pb, speaker_pos[i]); + av_freep(&speaker_pos); + } + + return update_size(pb, pos); +} + +static int mov_write_pcmc_tag(AVFormatContext *s, AVIOContext *pb, MOVTrack *track) +{ + int64_t pos = avio_tell(pb); + int format_flags; + + avio_wb32(pb, 0); /* size */ + ffio_wfourcc(pb, "pcmC"); + avio_wb32(pb, 0); /* version & flags */ + + /* 0x01: indicates little-endian format */ + format_flags = (track->par->codec_id == AV_CODEC_ID_PCM_F32LE || + track->par->codec_id == AV_CODEC_ID_PCM_F64LE || + track->par->codec_id == AV_CODEC_ID_PCM_S16LE || + track->par->codec_id == AV_CODEC_ID_PCM_S24LE || + track->par->codec_id == AV_CODEC_ID_PCM_S32LE); + avio_w8(pb, format_flags); + avio_w8(pb, track->par->bits_per_raw_sample); + + return update_size(pb, pos); +} + static int mov_write_audio_tag(AVFormatContext *s, AVIOContext *pb, MOVMuxContext *mov, MOVTrack *track) { int64_t pos = avio_tell(pb); @@ -1305,7 +1367,13 @@ static int mov_write_audio_tag(AVFormatContext *s, AVIOContext *pb, MOVMuxContex ret = mov_write_dops_tag(s, pb, track); else if (track->par->codec_id == AV_CODEC_ID_TRUEHD) ret = mov_write_dmlp_tag(s, pb, track); - else if (track->vos_len > 0) + else if (tag == MOV_MP4_IPCM_TAG || tag == MOV_MP4_FPCM_TAG) { + if (track->par->ch_layout.nb_channels > 1) + ret = mov_write_chnl_tag(s, pb, track); + if (ret < 0) + return ret; + ret = mov_write_pcmc_tag(s, pb, track); + } else if (track->vos_len > 0) ret = mov_write_glbl_tag(pb, track); if (ret < 0) @@ -7744,6 +7812,20 @@ static const AVCodecTag codec_mp4_tags[] = { { AV_CODEC_ID_MPEGH_3D_AUDIO, MKTAG('m', 'h', 'm', '1') }, { AV_CODEC_ID_TTML, MOV_MP4_TTML_TAG }, { AV_CODEC_ID_TTML, MOV_ISMV_TTML_TAG }, + + /* ISO/IEC 23003-5 integer formats */ + { AV_CODEC_ID_PCM_S16BE, MOV_MP4_IPCM_TAG }, + { AV_CODEC_ID_PCM_S16LE, MOV_MP4_IPCM_TAG }, + { AV_CODEC_ID_PCM_S24BE, MOV_MP4_IPCM_TAG }, + { AV_CODEC_ID_PCM_S24LE, MOV_MP4_IPCM_TAG }, + { AV_CODEC_ID_PCM_S32BE, MOV_MP4_IPCM_TAG }, + { AV_CODEC_ID_PCM_S32LE, MOV_MP4_IPCM_TAG }, + /* ISO/IEC 23003-5 floating-point formats */ + { AV_CODEC_ID_PCM_F32BE, MOV_MP4_FPCM_TAG }, + { AV_CODEC_ID_PCM_F32LE, MOV_MP4_FPCM_TAG }, + { AV_CODEC_ID_PCM_F64BE, MOV_MP4_FPCM_TAG }, + { AV_CODEC_ID_PCM_F64LE, MOV_MP4_FPCM_TAG }, + { AV_CODEC_ID_NONE, 0 }, }; #if CONFIG_MP4_MUXER || CONFIG_PSP_MUXER From 9e1ffeda8ce4eec647a2643afbf169214cc995f7 Mon Sep 17 00:00:00 2001 From: Zhao Zhili Date: Mon, 6 Mar 2023 20:02:11 +0800 Subject: [PATCH 0419/2172] fate/mov: add PCM in mp4 test Signed-off-by: Zhao Zhili --- tests/fate/mov.mak | 12 ++++++++++++ tests/filtergraphs/mov-mp4-pcm | 5 +++++ tests/ref/fate/mov-mp4-pcm | 27 +++++++++++++++++++++++++++ tests/ref/fate/mov-mp4-pcm-float | 7 +++++++ 4 files changed, 51 insertions(+) create mode 100644 tests/filtergraphs/mov-mp4-pcm create mode 100644 tests/ref/fate/mov-mp4-pcm create mode 100644 tests/ref/fate/mov-mp4-pcm-float diff --git a/tests/fate/mov.mak b/tests/fate/mov.mak index 8a7218a2158..d7954456913 100644 --- a/tests/fate/mov.mak +++ b/tests/fate/mov.mak @@ -165,6 +165,18 @@ FATE_MOV_FFMPEG-$(call TRANSCODE, PCM_S16LE, MOV, WAV_DEMUXER PAN_FILTER) \ fate-mov-channel-description: tests/data/asynth-44100-1.wav tests/data/filtergraphs/mov-channel-description fate-mov-channel-description: CMD = transcode wav $(TARGET_PATH)/tests/data/asynth-44100-1.wav mov "-filter_complex_script $(TARGET_PATH)/tests/data/filtergraphs/mov-channel-description -map [outFL] -map [outFR] -map [outFC] -map [outLFE] -map [outBL] -map [outBR] -map [outDL] -map [outDR] -c:a pcm_s16le" "-map 0 -c copy -frames:a 0" +# Test PCM in mp4 and channel layout +FATE_MOV_FFMPEG-$(call TRANSCODE, PCM_S16LE, MOV, WAV_DEMUXER PAN_FILTER) \ + += fate-mov-mp4-pcm +fate-mov-mp4-pcm: tests/data/asynth-44100-1.wav tests/data/filtergraphs/mov-mp4-pcm +fate-mov-mp4-pcm: CMD = transcode wav $(TARGET_PATH)/tests/data/asynth-44100-1.wav mp4 "-filter_complex_script $(TARGET_PATH)/tests/data/filtergraphs/mov-mp4-pcm -map [mono] -map [stereo] -map [2.1] -map [5.1] -map [7.1] -c:a pcm_s16le" "-map 0 -c copy -frames:a 0" + +# Test floating sample format PCM in mp4 and unusual channel layout +FATE_MOV_FFMPEG-$(call TRANSCODE, PCM_S16LE, MOV, WAV_DEMUXER PAN_FILTER) \ + += fate-mov-mp4-pcm-float +fate-mov-mp4-pcm-float: tests/data/asynth-44100-1.wav +fate-mov-mp4-pcm-float: CMD = transcode wav $(TARGET_PATH)/tests/data/asynth-44100-1.wav mp4 "-af aresample,pan=FL+LFE+BR|c0=c0|c1=c0|c2=c0 -c:a pcm_f32le" "-map 0 -c copy -frames:a 0" + FATE_FFMPEG += $(FATE_MOV_FFMPEG-yes) fate-mov: $(FATE_MOV) $(FATE_MOV_FFMPEG-yes) $(FATE_MOV_FFPROBE) $(FATE_MOV_FASTSTART) $(FATE_MOV_FFMPEG_FFPROBE-yes) diff --git a/tests/filtergraphs/mov-mp4-pcm b/tests/filtergraphs/mov-mp4-pcm new file mode 100644 index 00000000000..7fa25a2c3c7 --- /dev/null +++ b/tests/filtergraphs/mov-mp4-pcm @@ -0,0 +1,5 @@ +[0:a:0]pan=mono|c0=c0[mono]; +[0:a:0]pan=stereo|c0=c0|c1=c0[stereo]; +[0:a:0]pan=2.1|c0=c0|c1=c0|c2=c0[2.1]; +[0:a:0]pan=5.1|c0=c0|c1=c0|c2=c0|c3=c0|c4=c0|c5=c0[5.1]; +[0:a:0]pan=7.1|c0=c0|c1=c0|c2=c0|c3=c0|c4=c0|c5=c0|c6=c0|c7=c0[7.1]; diff --git a/tests/ref/fate/mov-mp4-pcm b/tests/ref/fate/mov-mp4-pcm new file mode 100644 index 00000000000..b34f5e59e16 --- /dev/null +++ b/tests/ref/fate/mov-mp4-pcm @@ -0,0 +1,27 @@ +1573ecbd24a65a6ec23ef08a861614b3 *tests/data/fate/mov-mp4-pcm.mp4 +10589277 tests/data/fate/mov-mp4-pcm.mp4 +#tb 0: 1/44100 +#media_type 0: audio +#codec_id 0: pcm_s16le +#sample_rate 0: 44100 +#channel_layout_name 0: mono +#tb 1: 1/44100 +#media_type 1: audio +#codec_id 1: pcm_s16le +#sample_rate 1: 44100 +#channel_layout_name 1: stereo +#tb 2: 1/44100 +#media_type 2: audio +#codec_id 2: pcm_s16le +#sample_rate 2: 44100 +#channel_layout_name 2: 2.1 +#tb 3: 1/44100 +#media_type 3: audio +#codec_id 3: pcm_s16le +#sample_rate 3: 44100 +#channel_layout_name 3: 5.1 +#tb 4: 1/44100 +#media_type 4: audio +#codec_id 4: pcm_s16le +#sample_rate 4: 44100 +#channel_layout_name 4: 7.1 diff --git a/tests/ref/fate/mov-mp4-pcm-float b/tests/ref/fate/mov-mp4-pcm-float new file mode 100644 index 00000000000..851b79090ca --- /dev/null +++ b/tests/ref/fate/mov-mp4-pcm-float @@ -0,0 +1,7 @@ +691a76a847e0f3720c09cca341971f19 *tests/data/fate/mov-mp4-pcm-float.mp4 +3175929 tests/data/fate/mov-mp4-pcm-float.mp4 +#tb 0: 1/44100 +#media_type 0: audio +#codec_id 0: pcm_f32le +#sample_rate 0: 44100 +#channel_layout_name 0: 3 channels (FL+LFE+BR) From 0d35634eaa6cd2b41292518489d559b030c00702 Mon Sep 17 00:00:00 2001 From: James Almer Date: Wed, 15 Mar 2023 12:42:13 -0300 Subject: [PATCH 0420/2172] avcodec/libdav1d: Fix unintended fallthrough Based on a patch by Andreas Rheinhardt Signed-off-by: James Almer --- libavcodec/libdav1d.c | 1 + 1 file changed, 1 insertion(+) diff --git a/libavcodec/libdav1d.c b/libavcodec/libdav1d.c index eb1225ea1a0..632023ba73f 100644 --- a/libavcodec/libdav1d.c +++ b/libavcodec/libdav1d.c @@ -539,6 +539,7 @@ FF_ENABLE_DEPRECATION_WARNINGS default: // ignore unsupported identifiers break; } + break; } case 0x3C: { // smpte_provider_code AVDynamicHDRPlus *hdrplus; From 85b185b504759c794d872ade303bb9be4f79cdcc Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt Date: Wed, 15 Mar 2023 15:00:33 +0100 Subject: [PATCH 0421/2172] avcodec/av1dec: Fix unintended fallthrough Fixes Coverity issue #1521982. Reviewed-by: James Almer Signed-off-by: Andreas Rheinhardt --- libavcodec/av1dec.c | 1 + 1 file changed, 1 insertion(+) diff --git a/libavcodec/av1dec.c b/libavcodec/av1dec.c index a80e37e33fc..4d3b559b967 100644 --- a/libavcodec/av1dec.c +++ b/libavcodec/av1dec.c @@ -911,6 +911,7 @@ static int export_itut_t35(AVCodecContext *avctx, AVFrame *frame, default: // ignore unsupported identifiers break; } + break; } case 0x3C: { // smpte_provider_code AVDynamicHDRPlus *hdrplus; From c3a79990996e1edbce78ebad5d69a9b88a88d0a6 Mon Sep 17 00:00:00 2001 From: Tong Wu Date: Thu, 16 Mar 2023 13:32:58 +0800 Subject: [PATCH 0422/2172] avformat/mov: fix 2 compile errors Compiler: MSVC 14.35.32215 Error type: error C2059: syntax error: '}' Related commit: 9e1ffed fate/mov: add PCM in mp4 test d7e8643 avformat/mov: parse ISO-14496-12 ChannelLayout Signed-off-by: Tong Wu Signed-off-by: Zhao Zhili Reviewed-by: Haihao Xiang --- libavformat/mov_chan.c | 2 +- libavformat/movenc.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/libavformat/mov_chan.c b/libavformat/mov_chan.c index df17976e597..f3d51899e1f 100644 --- a/libavformat/mov_chan.c +++ b/libavformat/mov_chan.c @@ -555,7 +555,7 @@ int ff_mov_read_chan(AVFormatContext *s, AVIOContext *pb, AVStream *st, /* ISO/IEC 23001-8, 8.2 */ static const AVChannelLayout iso_channel_configuration[] = { // 0: any setup - {}, + {0}, // 1: centre front AV_CHANNEL_LAYOUT_MONO, diff --git a/libavformat/movenc.c b/libavformat/movenc.c index 2ec575c954d..68e7f8222b9 100644 --- a/libavformat/movenc.c +++ b/libavformat/movenc.c @@ -1194,7 +1194,7 @@ static int mov_write_chnl_tag(AVFormatContext *s, AVIOContext *pb, MOVTrack *tra ret = ff_mov_get_channel_positions_from_layout(layout, speaker_pos, layout->nb_channels); if (ret) { - char buf[128] = {}; + char buf[128] = {0}; av_freep(&speaker_pos); av_channel_layout_describe(layout, buf, sizeof(buf)); From dc61d5cf195bc6de9263883c42a58348863e6d4f Mon Sep 17 00:00:00 2001 From: James Almer Date: Thu, 16 Mar 2023 11:27:50 -0300 Subject: [PATCH 0423/2172] avfilter/vf_untile: swap the chroma shift values used for plane offsets Fixes ticket #10265 Signed-off-by: James Almer --- libavfilter/vf_untile.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libavfilter/vf_untile.c b/libavfilter/vf_untile.c index 5d7709d68c1..c8dafd1e60b 100644 --- a/libavfilter/vf_untile.c +++ b/libavfilter/vf_untile.c @@ -134,8 +134,8 @@ static int activate(AVFilterContext *ctx) if (!(s->desc->flags & AV_PIX_FMT_FLAG_PAL)) { for (i = 1; i < 3; i ++) { if (out->data[i]) { - out->data[i] += (y >> s->desc->log2_chroma_w) * out->linesize[i]; - out->data[i] += (x >> s->desc->log2_chroma_h) * s->max_step[i]; + out->data[i] += (y >> s->desc->log2_chroma_h) * out->linesize[i]; + out->data[i] += (x >> s->desc->log2_chroma_w) * s->max_step[i]; } } } From 14719b79394207df812fe7b6bc34fdee9f928ccb Mon Sep 17 00:00:00 2001 From: James Almer Date: Thu, 16 Mar 2023 11:33:32 -0300 Subject: [PATCH 0424/2172] fate: add a yuv422p test for the untile filter Signed-off-by: James Almer --- tests/fate/filter-video.mak | 3 +++ tests/ref/fate/filter-untile-yuv422p | 13 +++++++++++++ 2 files changed, 16 insertions(+) create mode 100644 tests/ref/fate/filter-untile-yuv422p diff --git a/tests/fate/filter-video.mak b/tests/fate/filter-video.mak index 704087b8359..444adc6be6a 100644 --- a/tests/fate/filter-video.mak +++ b/tests/fate/filter-video.mak @@ -314,6 +314,9 @@ FATE_FILTER_VSYNTH-$(call FILTERDEMDEC, TRIM, IMAGE2, PGM) += $(FATE_TRIM) FATE_FILTER-$(call FILTERFRAMECRC, TESTSRC2 UNTILE) += fate-filter-untile fate-filter-untile: CMD = framecrc -lavfi testsrc2=d=1:r=2,untile=2x2 +FATE_FILTER-$(call FILTERFRAMECRC, TESTSRC2 UNTILE) += fate-filter-untile-yuv422p +fate-filter-untile-yuv422p: CMD = framecrc -lavfi testsrc2=d=1:r=2,format=yuv422p,untile=2x2 + FATE_FILTER_VSYNTH_PGMYUV-$(CONFIG_UNSHARP_FILTER) += fate-filter-unsharp fate-filter-unsharp: CMD = framecrc -c:v pgmyuv -i $(SRC) -vf unsharp=11:11:-1.5:11:11:-1.5 diff --git a/tests/ref/fate/filter-untile-yuv422p b/tests/ref/fate/filter-untile-yuv422p new file mode 100644 index 00000000000..b212ccd8caf --- /dev/null +++ b/tests/ref/fate/filter-untile-yuv422p @@ -0,0 +1,13 @@ +#tb 0: 1/8 +#media_type 0: video +#codec_id 0: rawvideo +#dimensions 0: 160x120 +#sar 0: 1/1 +0, 0, 0, 1, 38400, 0xaadbf3e0 +0, 1, 1, 1, 38400, 0x02c882d1 +0, 2, 2, 1, 38400, 0xc246dcaa +0, 3, 3, 1, 38400, 0x4503b0df +0, 4, 4, 1, 38400, 0x3ed4a056 +0, 5, 5, 1, 38400, 0x374a85a6 +0, 6, 6, 1, 38400, 0xb03343d6 +0, 7, 7, 1, 38400, 0x188e8b4b From 6273fb36ccefa38f4bd378d1611375492e70cac6 Mon Sep 17 00:00:00 2001 From: Devin Heitmueller Date: Thu, 9 Mar 2023 12:04:04 -0500 Subject: [PATCH 0425/2172] avformat/mpegtsenc: Restrict "async" behavior to KLV async packets The original code would strip off the PTS/DTS of any packets which had a stream ID of STREAM_ID_PRIVATE_STREAM_1. While the intent was to apply this to asynchronous KLV packets, it was being applied to any codec that had that same stream ID (including types such as SMPTE 2038). Add a clause to the if() statement to ensure it only gets applied if the codec actually is KLV. Signed-off-by: Devin Heitmueller 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 ceed0895871..3f201cce1d8 100644 --- a/libavformat/mpegtsenc.c +++ b/libavformat/mpegtsenc.c @@ -1455,7 +1455,8 @@ static int get_pes_stream_id(AVFormatContext *s, AVStream *st, int stream_id, in st->codecpar->codec_id == AV_CODEC_ID_TIMED_ID3) { return STREAM_ID_PRIVATE_STREAM_1; } else if (st->codecpar->codec_type == AVMEDIA_TYPE_DATA) { - if (stream_id == STREAM_ID_PRIVATE_STREAM_1) /* asynchronous KLV */ + if (st->codecpar->codec_id == AV_CODEC_ID_SMPTE_KLV && + stream_id == STREAM_ID_PRIVATE_STREAM_1) /* asynchronous KLV */ *async = 1; return stream_id != -1 ? stream_id : STREAM_ID_METADATA_STREAM; } else { From 3be46ee7672b2363058c9f7116d04b09a82b1202 Mon Sep 17 00:00:00 2001 From: Zhao Zhili Date: Fri, 17 Mar 2023 18:51:16 +0800 Subject: [PATCH 0426/2172] libavutil/hdr_dynamic_vivid_metadata: fix three spline params There are two group of three_Spline params. Signed-off-by: Zhao Zhili --- doc/APIchanges | 4 ++ libavutil/hdr_dynamic_vivid_metadata.h | 63 +++++++++++++++++++++++++- libavutil/version.h | 3 +- 3 files changed, 68 insertions(+), 2 deletions(-) diff --git a/doc/APIchanges b/doc/APIchanges index 14737223cb0..5914fac2cdc 100644 --- a/doc/APIchanges +++ b/doc/APIchanges @@ -2,6 +2,10 @@ The last version increases of all libraries were on 2023-02-09 API changes, most recent first: +2023-03-17 - xxxxxxxxxx - lavu 58.4.100 - hdr_dynamic_vivid_metadata.h + Add two group of three spline params. + Deprecate previous define which only supports one group of params. + 2023-03-02 - xxxxxxxxxx - lavc 60.6.100 - avcodec.h Add FF_PROFILE_EAC3_DDP_ATMOS, FF_PROFILE_TRUEHD_ATMOS, FF_PROFILE_DTS_HD_MA_X and FF_PROFILE_DTS_HD_MA_X_IMAX. diff --git a/libavutil/hdr_dynamic_vivid_metadata.h b/libavutil/hdr_dynamic_vivid_metadata.h index a34f83072cb..4524a815578 100644 --- a/libavutil/hdr_dynamic_vivid_metadata.h +++ b/libavutil/hdr_dynamic_vivid_metadata.h @@ -24,6 +24,52 @@ #include "frame.h" #include "rational.h" +/** + * HDR Vivid three spline params. + */ +typedef struct AVHDRVivid3SplineParams { + /** + * The mode of three Spline. the value shall be in the range + * of 0 to 3, inclusive. + */ + int th_mode; + + /** + * three_Spline_TH_enable_MB is in the range of 0.0 to 1.0, inclusive + * and in multiples of 1.0/255. + * + */ + AVRational th_enable_mb; + + /** + * 3Spline_TH_enable of three Spline. + * The value shall be in the range of 0.0 to 1.0, inclusive. + * and in multiples of 1.0/4095. + */ + AVRational th_enable; + + /** + * 3Spline_TH_Delta1 of three Spline. + * The value shall be in the range of 0.0 to 0.25, inclusive, + * and in multiples of 0.25/1023. + */ + AVRational th_delta1; + + /** + * 3Spline_TH_Delta2 of three Spline. + * The value shall be in the range of 0.0 to 0.25, inclusive, + * and in multiples of 0.25/1023. + */ + AVRational th_delta2; + + /** + * 3Spline_enable_Strength of three Spline. + * The value shall be in the range of 0.0 to 1.0, inclusive, + * and in multiples of 1.0/255. + */ + AVRational enable_strength; +} AVHDRVivid3SplineParams; + /** * Color tone mapping parameters at a processing window in a dynamic metadata for * CUVA 005.1:2021. @@ -122,46 +168,61 @@ typedef struct AVHDRVividColorToneMappingParams { */ int three_Spline_num; +#if FF_API_HDR_VIVID_THREE_SPLINE /** * The mode of three Spline. the value shall be in the range * of 0 to 3, inclusive. + * @deprecated Use three_spline instead */ + attribute_deprecated int three_Spline_TH_mode; /** * three_Spline_TH_enable_MB is in the range of 0.0 to 1.0, inclusive * and in multiples of 1.0/255. - * + * @deprecated Use three_spline instead */ + attribute_deprecated AVRational three_Spline_TH_enable_MB; /** * 3Spline_TH_enable of three Spline. * The value shall be in the range of 0.0 to 1.0, inclusive. * and in multiples of 1.0/4095. + * @deprecated Use three_spline instead */ + attribute_deprecated AVRational three_Spline_TH_enable; /** * 3Spline_TH_Delta1 of three Spline. * The value shall be in the range of 0.0 to 0.25, inclusive, * and in multiples of 0.25/1023. + * @deprecated Use three_spline instead */ + attribute_deprecated AVRational three_Spline_TH_Delta1; /** * 3Spline_TH_Delta2 of three Spline. * The value shall be in the range of 0.0 to 0.25, inclusive, * and in multiples of 0.25/1023. + * @deprecated Use three_spline instead */ + attribute_deprecated AVRational three_Spline_TH_Delta2; /** * 3Spline_enable_Strength of three Spline. * The value shall be in the range of 0.0 to 1.0, inclusive, * and in multiples of 1.0/255. + * @deprecated Use three_spline instead */ + attribute_deprecated AVRational three_Spline_enable_Strength; +#endif + + AVHDRVivid3SplineParams three_spline[2]; } AVHDRVividColorToneMappingParams; diff --git a/libavutil/version.h b/libavutil/version.h index 900b7989718..a89a0d406f0 100644 --- a/libavutil/version.h +++ b/libavutil/version.h @@ -79,7 +79,7 @@ */ #define LIBAVUTIL_VERSION_MAJOR 58 -#define LIBAVUTIL_VERSION_MINOR 3 +#define LIBAVUTIL_VERSION_MINOR 4 #define LIBAVUTIL_VERSION_MICRO 100 #define LIBAVUTIL_VERSION_INT AV_VERSION_INT(LIBAVUTIL_VERSION_MAJOR, \ @@ -113,6 +113,7 @@ #define FF_API_PKT_DURATION (LIBAVUTIL_VERSION_MAJOR < 59) #define FF_API_REORDERED_OPAQUE (LIBAVUTIL_VERSION_MAJOR < 59) #define FF_API_FRAME_PICTURE_NUMBER (LIBAVUTIL_VERSION_MAJOR < 59) +#define FF_API_HDR_VIVID_THREE_SPLINE (LIBAVUTIL_VERSION_MAJOR < 59) /** * @} From 0f2bef268408c83bb236c398ce42eafa7ec328c7 Mon Sep 17 00:00:00 2001 From: Zhao Zhili Date: Fri, 17 Mar 2023 18:51:16 +0800 Subject: [PATCH 0427/2172] avcodec/dynamic_hdr_vivid: fix three spline params Signed-off-by: Zhao Zhili --- libavcodec/dynamic_hdr_vivid.c | 34 +++++++++++++++++++++++----------- 1 file changed, 23 insertions(+), 11 deletions(-) diff --git a/libavcodec/dynamic_hdr_vivid.c b/libavcodec/dynamic_hdr_vivid.c index d689669dec0..f2bc0c9059c 100644 --- a/libavcodec/dynamic_hdr_vivid.c +++ b/libavcodec/dynamic_hdr_vivid.c @@ -98,26 +98,38 @@ int ff_parse_itu_t_t35_to_dynamic_hdr_vivid(AVDynamicHDRVivid *s, const uint8_t return AVERROR_INVALIDDATA; tm_params->three_Spline_enable_flag = get_bits(gb, 1); if (tm_params->three_Spline_enable_flag) { + AVHDRVivid3SplineParams *three_spline; + if (get_bits_left(gb) < 1 + tm_params->three_Spline_num * (2 + 12 + 28 + 1)) return AVERROR_INVALIDDATA; tm_params->three_Spline_num = get_bits(gb, 1) + 1; + if (tm_params->three_Spline_num > FF_ARRAY_ELEMS(tm_params->three_spline)) + return AVERROR_INVALIDDATA; for (int j = 0; j < tm_params->three_Spline_num; j++) { - tm_params->three_Spline_TH_mode = get_bits(gb, 2); - if (tm_params->three_Spline_TH_mode == 0 || tm_params->three_Spline_TH_mode == 2) { + three_spline = &tm_params->three_spline[j]; + three_spline->th_mode = get_bits(gb, 2); + if (three_spline->th_mode == 0 || three_spline->th_mode == 2) { if (get_bits_left(gb) < 8) return AVERROR_INVALIDDATA; - tm_params->three_Spline_TH_enable_MB = (AVRational){get_bits(gb, 8), 255}; + three_spline->th_enable_mb = (AVRational){get_bits(gb, 8), 255}; } - tm_params->three_Spline_TH_enable = (AVRational){get_bits(gb, 12), 4095}; - tm_params->three_Spline_TH_Delta1 = (AVRational){get_bits(gb, 10), 1023}; - tm_params->three_Spline_TH_Delta2 = (AVRational){get_bits(gb, 10), 1023}; - tm_params->three_Spline_enable_Strength = (AVRational){get_bits(gb, 8), 255}; + three_spline->th_enable = (AVRational){get_bits(gb, 12), 4095}; + three_spline->th_delta1 = (AVRational){get_bits(gb, 10), 1023}; + three_spline->th_delta2 = (AVRational){get_bits(gb, 10), 1023}; + three_spline->enable_strength = (AVRational){get_bits(gb, 8), 255}; } - } else { - tm_params->three_Spline_num = 1; - tm_params->three_Spline_TH_mode = 0; +#if FF_API_HDR_VIVID_THREE_SPLINE + three_spline = &tm_params->three_spline[0]; +FF_DISABLE_DEPRECATION_WARNINGS + tm_params->three_Spline_TH_mode = three_spline->th_mode; + tm_params->three_Spline_TH_enable_MB = three_spline->th_enable_mb; + tm_params->three_Spline_TH_enable = three_spline->th_enable; + tm_params->three_Spline_TH_Delta1 = three_spline->th_delta1; + tm_params->three_Spline_TH_Delta2 = three_spline->th_delta2; + tm_params->three_Spline_enable_Strength = three_spline->enable_strength; +FF_ENABLE_DEPRECATION_WARNINGS +#endif } - } } } From 4ec2861559ee4e619195c4eb0b2ed8b2f0b9afc1 Mon Sep 17 00:00:00 2001 From: Zhao Zhili Date: Fri, 17 Mar 2023 18:51:16 +0800 Subject: [PATCH 0428/2172] avfilter/vf_showinfo: fix HDR vivid info Signed-off-by: Zhao Zhili --- libavfilter/vf_showinfo.c | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/libavfilter/vf_showinfo.c b/libavfilter/vf_showinfo.c index e55625b3382..e6c9d60a85c 100644 --- a/libavfilter/vf_showinfo.c +++ b/libavfilter/vf_showinfo.c @@ -354,19 +354,20 @@ static void dump_dynamic_hdr_vivid(AVFilterContext *ctx, AVFrameSideData *sd) av_log(ctx, AV_LOG_INFO, "3Spline_enable_flag[%d][%d]: %d, ", w, i, tm_params->three_Spline_enable_flag); if (tm_params->three_Spline_enable_flag) { - av_log(ctx, AV_LOG_INFO, "3Spline_TH_mode[%d][%d]: %d, ", w, i, tm_params->three_Spline_TH_mode); - for (int j = 0; j < tm_params->three_Spline_num; j++) { - av_log(ctx, AV_LOG_INFO, "3Spline_TH_enable_MB[%d][%d][%d]: %.4f, ", - w, i, j, av_q2d(tm_params->three_Spline_TH_enable_MB)); + const AVHDRVivid3SplineParams *three_spline = &tm_params->three_spline[j]; + av_log(ctx, AV_LOG_INFO, "3Spline_TH_mode[%d][%d]: %d, ", w, i, three_spline->th_mode); + if (three_spline->th_mode == 0 || three_spline->th_mode == 2) + av_log(ctx, AV_LOG_INFO, "3Spline_TH_enable_MB[%d][%d][%d]: %.4f, ", + w, i, j, av_q2d(three_spline->th_enable_mb)); av_log(ctx, AV_LOG_INFO, "3Spline_TH_enable[%d][%d][%d]: %.4f, ", - w, i, j, av_q2d(tm_params->three_Spline_TH_enable)); + w, i, j, av_q2d(three_spline->th_enable)); av_log(ctx, AV_LOG_INFO, "3Spline_TH_Delta1[%d][%d][%d]: %.4f, ", - w, i, j, av_q2d(tm_params->three_Spline_TH_Delta1)); + w, i, j, av_q2d(three_spline->th_delta1)); av_log(ctx, AV_LOG_INFO, "3Spline_TH_Delta2[%d][%d][%d]: %.4f, ", - w, i, j, av_q2d(tm_params->three_Spline_TH_Delta2)); + w, i, j, av_q2d(three_spline->th_delta2)); av_log(ctx, AV_LOG_INFO, "3Spline_enable_Strength[%d][%d][%d]: %.4f, ", - w, i, j, av_q2d(tm_params->three_Spline_enable_Strength)); + w, i, j, av_q2d(three_spline->enable_strength)); } } } From 8de8f1df7724dc0700adc9a641a52f804c871e70 Mon Sep 17 00:00:00 2001 From: Zhao Zhili Date: Fri, 17 Mar 2023 18:51:16 +0800 Subject: [PATCH 0429/2172] fftools/ffprobe: fix HDR vivid info Signed-off-by: Zhao Zhili --- fftools/ffprobe.c | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/fftools/ffprobe.c b/fftools/ffprobe.c index af927cb0843..0db419d0931 100644 --- a/fftools/ffprobe.c +++ b/fftools/ffprobe.c @@ -2246,14 +2246,16 @@ static void print_dynamic_hdr_vivid(WriterContext *w, const AVDynamicHDRVivid *m print_int("3Spline_enable_flag", tm_params->three_Spline_enable_flag); if (tm_params->three_Spline_enable_flag) { print_int("3Spline_num", tm_params->three_Spline_num); - print_int("3Spline_TH_mode", tm_params->three_Spline_TH_mode); for (int j = 0; j < tm_params->three_Spline_num; j++) { - print_q("3Spline_TH_enable_MB", tm_params->three_Spline_TH_enable_MB, '/'); - print_q("3Spline_TH_enable", tm_params->three_Spline_TH_enable, '/'); - print_q("3Spline_TH_Delta1", tm_params->three_Spline_TH_Delta1, '/'); - print_q("3Spline_TH_Delta2", tm_params->three_Spline_TH_Delta2, '/'); - print_q("3Spline_enable_Strength", tm_params->three_Spline_enable_Strength, '/'); + const AVHDRVivid3SplineParams *three_spline = &tm_params->three_spline[j]; + print_int("3Spline_TH_mode", three_spline->th_mode); + if (three_spline->th_mode == 0 || three_spline->th_mode == 2) + print_q("3Spline_TH_enable_MB", three_spline->th_enable_mb, '/'); + print_q("3Spline_TH_enable", three_spline->th_enable, '/'); + print_q("3Spline_TH_Delta1", three_spline->th_delta1, '/'); + print_q("3Spline_TH_Delta2", three_spline->th_delta2, '/'); + print_q("3Spline_enable_Strength", three_spline->enable_strength, '/'); } } } From ac5dffdfe68645ad69af049bb6402eeb3c8ba318 Mon Sep 17 00:00:00 2001 From: Zhao Zhili Date: Fri, 17 Mar 2023 18:51:16 +0800 Subject: [PATCH 0430/2172] libavcodec/dynamic_hdr_vivid: fix start code check Signed-off-by: Zhao Zhili --- libavcodec/dynamic_hdr_vivid.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libavcodec/dynamic_hdr_vivid.c b/libavcodec/dynamic_hdr_vivid.c index f2bc0c9059c..9847b88e61c 100644 --- a/libavcodec/dynamic_hdr_vivid.c +++ b/libavcodec/dynamic_hdr_vivid.c @@ -46,7 +46,8 @@ int ff_parse_itu_t_t35_to_dynamic_hdr_vivid(AVDynamicHDRVivid *s, const uint8_t return AVERROR_INVALIDDATA; s->system_start_code = get_bits(gb, 8); - if (s->system_start_code == 0x01) { + // T/UWA 005.1-2022, table 11 + if (s->system_start_code >= 0x01 && s->system_start_code <= 0x07) { s->num_windows = 1; if (get_bits_left(gb) < 12 * 4 * s->num_windows) From 9a1b142712966736f5dae60c81f192e99bedd04c Mon Sep 17 00:00:00 2001 From: Zhao Zhili Date: Fri, 17 Mar 2023 18:51:16 +0800 Subject: [PATCH 0431/2172] avcodec/dynamic_hdr_vivid: fix base_param_Delta It conflicts the comments. The operation based on Delta_enable_mode can be applied by user during tone mapping. Signed-off-by: Zhao Zhili --- libavcodec/dynamic_hdr_vivid.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/libavcodec/dynamic_hdr_vivid.c b/libavcodec/dynamic_hdr_vivid.c index 9847b88e61c..30f7dfc71f6 100644 --- a/libavcodec/dynamic_hdr_vivid.c +++ b/libavcodec/dynamic_hdr_vivid.c @@ -90,10 +90,7 @@ int ff_parse_itu_t_t35_to_dynamic_hdr_vivid(AVDynamicHDRVivid *s, const uint8_t tm_params->base_param_k2 = get_bits(gb, 2); tm_params->base_param_k3 = get_bits(gb, 4); tm_params->base_param_Delta_enable_mode = get_bits(gb, 3); - if (tm_params->base_param_Delta_enable_mode == 2 || tm_params->base_param_Delta_enable_mode == 6) - tm_params->base_param_Delta = (AVRational){get_bits(gb, 7) * -1, base_param_Delta_den}; - else - tm_params->base_param_Delta = (AVRational){get_bits(gb, 7), base_param_Delta_den}; + tm_params->base_param_Delta = (AVRational){get_bits(gb, 7), base_param_Delta_den}; if (get_bits_left(gb) < 1) return AVERROR_INVALIDDATA; From 229363732eb64097f74ad14ac217e4c52036a6c4 Mon Sep 17 00:00:00 2001 From: Zhao Zhili Date: Fri, 17 Mar 2023 18:51:16 +0800 Subject: [PATCH 0432/2172] avcodec/dynamic_hdr_vivid: fix base_enable_flag control The base_enable_flag is parallel to three_Spline_enable_flag. The typesetting of the specification is very misleading. Signed-off-by: Zhao Zhili --- libavcodec/dynamic_hdr_vivid.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/libavcodec/dynamic_hdr_vivid.c b/libavcodec/dynamic_hdr_vivid.c index 30f7dfc71f6..7cb13cbf322 100644 --- a/libavcodec/dynamic_hdr_vivid.c +++ b/libavcodec/dynamic_hdr_vivid.c @@ -91,7 +91,7 @@ int ff_parse_itu_t_t35_to_dynamic_hdr_vivid(AVDynamicHDRVivid *s, const uint8_t tm_params->base_param_k3 = get_bits(gb, 4); tm_params->base_param_Delta_enable_mode = get_bits(gb, 3); tm_params->base_param_Delta = (AVRational){get_bits(gb, 7), base_param_Delta_den}; - + } if (get_bits_left(gb) < 1) return AVERROR_INVALIDDATA; tm_params->three_Spline_enable_flag = get_bits(gb, 1); @@ -128,7 +128,6 @@ FF_DISABLE_DEPRECATION_WARNINGS FF_ENABLE_DEPRECATION_WARNINGS #endif } - } } } From c62fe3eee25910ee1573a0063623348895b56426 Mon Sep 17 00:00:00 2001 From: Zhao Zhili Date: Fri, 17 Mar 2023 18:51:16 +0800 Subject: [PATCH 0433/2172] avcodec/dynamic_hdr_vivid: reindent after the previous commit Signed-off-by: Zhao Zhili --- libavcodec/dynamic_hdr_vivid.c | 60 +++++++++++++++++----------------- 1 file changed, 30 insertions(+), 30 deletions(-) diff --git a/libavcodec/dynamic_hdr_vivid.c b/libavcodec/dynamic_hdr_vivid.c index 7cb13cbf322..a9b69107982 100644 --- a/libavcodec/dynamic_hdr_vivid.c +++ b/libavcodec/dynamic_hdr_vivid.c @@ -92,42 +92,42 @@ int ff_parse_itu_t_t35_to_dynamic_hdr_vivid(AVDynamicHDRVivid *s, const uint8_t tm_params->base_param_Delta_enable_mode = get_bits(gb, 3); tm_params->base_param_Delta = (AVRational){get_bits(gb, 7), base_param_Delta_den}; } - if (get_bits_left(gb) < 1) + if (get_bits_left(gb) < 1) + return AVERROR_INVALIDDATA; + tm_params->three_Spline_enable_flag = get_bits(gb, 1); + if (tm_params->three_Spline_enable_flag) { + AVHDRVivid3SplineParams *three_spline; + + if (get_bits_left(gb) < 1 + tm_params->three_Spline_num * (2 + 12 + 28 + 1)) + return AVERROR_INVALIDDATA; + tm_params->three_Spline_num = get_bits(gb, 1) + 1; + if (tm_params->three_Spline_num > FF_ARRAY_ELEMS(tm_params->three_spline)) return AVERROR_INVALIDDATA; - tm_params->three_Spline_enable_flag = get_bits(gb, 1); - if (tm_params->three_Spline_enable_flag) { - AVHDRVivid3SplineParams *three_spline; - - if (get_bits_left(gb) < 1 + tm_params->three_Spline_num * (2 + 12 + 28 + 1)) - return AVERROR_INVALIDDATA; - tm_params->three_Spline_num = get_bits(gb, 1) + 1; - if (tm_params->three_Spline_num > FF_ARRAY_ELEMS(tm_params->three_spline)) - return AVERROR_INVALIDDATA; - for (int j = 0; j < tm_params->three_Spline_num; j++) { - three_spline = &tm_params->three_spline[j]; - three_spline->th_mode = get_bits(gb, 2); - if (three_spline->th_mode == 0 || three_spline->th_mode == 2) { - if (get_bits_left(gb) < 8) - return AVERROR_INVALIDDATA; - three_spline->th_enable_mb = (AVRational){get_bits(gb, 8), 255}; - } - three_spline->th_enable = (AVRational){get_bits(gb, 12), 4095}; - three_spline->th_delta1 = (AVRational){get_bits(gb, 10), 1023}; - three_spline->th_delta2 = (AVRational){get_bits(gb, 10), 1023}; - three_spline->enable_strength = (AVRational){get_bits(gb, 8), 255}; + for (int j = 0; j < tm_params->three_Spline_num; j++) { + three_spline = &tm_params->three_spline[j]; + three_spline->th_mode = get_bits(gb, 2); + if (three_spline->th_mode == 0 || three_spline->th_mode == 2) { + if (get_bits_left(gb) < 8) + return AVERROR_INVALIDDATA; + three_spline->th_enable_mb = (AVRational){get_bits(gb, 8), 255}; } + three_spline->th_enable = (AVRational){get_bits(gb, 12), 4095}; + three_spline->th_delta1 = (AVRational){get_bits(gb, 10), 1023}; + three_spline->th_delta2 = (AVRational){get_bits(gb, 10), 1023}; + three_spline->enable_strength = (AVRational){get_bits(gb, 8), 255}; + } #if FF_API_HDR_VIVID_THREE_SPLINE - three_spline = &tm_params->three_spline[0]; + three_spline = &tm_params->three_spline[0]; FF_DISABLE_DEPRECATION_WARNINGS - tm_params->three_Spline_TH_mode = three_spline->th_mode; - tm_params->three_Spline_TH_enable_MB = three_spline->th_enable_mb; - tm_params->three_Spline_TH_enable = three_spline->th_enable; - tm_params->three_Spline_TH_Delta1 = three_spline->th_delta1; - tm_params->three_Spline_TH_Delta2 = three_spline->th_delta2; - tm_params->three_Spline_enable_Strength = three_spline->enable_strength; + tm_params->three_Spline_TH_mode = three_spline->th_mode; + tm_params->three_Spline_TH_enable_MB = three_spline->th_enable_mb; + tm_params->three_Spline_TH_enable = three_spline->th_enable; + tm_params->three_Spline_TH_Delta1 = three_spline->th_delta1; + tm_params->three_Spline_TH_Delta2 = three_spline->th_delta2; + tm_params->three_Spline_enable_Strength = three_spline->enable_strength; FF_ENABLE_DEPRECATION_WARNINGS #endif - } + } } } From 13deb775cfccb10bf03789ca9d05e2a3f6131126 Mon Sep 17 00:00:00 2001 From: Zhao Zhili Date: Fri, 17 Mar 2023 18:51:16 +0800 Subject: [PATCH 0434/2172] fftools/ffprobe: fix print_dynamic_hdr_vivid Don't print tone_mapping_param_num if tone_mapping_mode_flag is disabled. Signed-off-by: Zhao Zhili --- fftools/ffprobe.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fftools/ffprobe.c b/fftools/ffprobe.c index 0db419d0931..969fa1b9f84 100644 --- a/fftools/ffprobe.c +++ b/fftools/ffprobe.c @@ -2221,8 +2221,8 @@ static void print_dynamic_hdr_vivid(WriterContext *w, const AVDynamicHDRVivid *m const AVHDRVividColorTransformParams *params = &metadata->params[n]; print_int("tone_mapping_mode_flag", params->tone_mapping_mode_flag); - print_int("tone_mapping_param_num", params->tone_mapping_param_num); if (params->tone_mapping_mode_flag) { + print_int("tone_mapping_param_num", params->tone_mapping_param_num); for (int i = 0; i < params->tone_mapping_param_num; i++) { const AVHDRVividColorToneMappingParams *tm_params = ¶ms->tm_params[i]; From 55c8c9493f34e35066e23989991ccc604dbc6da7 Mon Sep 17 00:00:00 2001 From: Wenbin Chen Date: Thu, 2 Mar 2023 10:33:36 +0800 Subject: [PATCH 0435/2172] libavcodec/qsvenc: Add dynamic setting support of low_delay_brc to av1_qsv Signed-off-by: Wenbin Chen --- doc/encoders.texi | 2 +- libavcodec/qsvenc.c | 5 ++++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/doc/encoders.texi b/doc/encoders.texi index b02737b9dfb..e9b34010edb 100644 --- a/doc/encoders.texi +++ b/doc/encoders.texi @@ -3344,7 +3344,7 @@ Supported in h264_qsv. Change these value to reset qsv codec's max/min qp configuration. @item @var{low_delay_brc} -Supported in h264_qsv and hevc_qsv. +Supported in h264_qsv, hevc_qsv and av1_qsv. Change this value to reset qsv codec's low_delay_brc configuration. @item @var{framerate} diff --git a/libavcodec/qsvenc.c b/libavcodec/qsvenc.c index 3607859cb85..c975302b4f2 100644 --- a/libavcodec/qsvenc.c +++ b/libavcodec/qsvenc.c @@ -1127,6 +1127,7 @@ static int init_video_param(AVCodecContext *avctx, QSVEncContext *q) } else if (avctx->codec_id == AV_CODEC_ID_AV1) { if (q->low_delay_brc >= 0) q->extco3.LowDelayBRC = q->low_delay_brc ? MFX_CODINGOPTION_ON : MFX_CODINGOPTION_OFF; + q->old_low_delay_brc = q->low_delay_brc; } if (avctx->codec_id == AV_CODEC_ID_HEVC) { @@ -2213,7 +2214,9 @@ static int update_low_delay_brc(AVCodecContext *avctx, QSVEncContext *q) { int updated = 0; - if (avctx->codec_id != AV_CODEC_ID_H264 && avctx->codec_id != AV_CODEC_ID_HEVC) + if (avctx->codec_id != AV_CODEC_ID_H264 && + avctx->codec_id != AV_CODEC_ID_HEVC && + avctx->codec_id != AV_CODEC_ID_AV1) return 0; UPDATE_PARAM(q->old_low_delay_brc, q->low_delay_brc); From 2db22d14bf5f0ae62e5ee335017abba3ac458ce9 Mon Sep 17 00:00:00 2001 From: Wenbin Chen Date: Thu, 2 Mar 2023 10:54:31 +0800 Subject: [PATCH 0436/2172] doc/examples/qsv_transcode: Fix a bug when use more than one parameter set Signed-off-by: Wenbin Chen --- doc/examples/qsv_transcode.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/examples/qsv_transcode.c b/doc/examples/qsv_transcode.c index 7ea3ef5674b..48128b200c5 100644 --- a/doc/examples/qsv_transcode.c +++ b/doc/examples/qsv_transcode.c @@ -88,7 +88,7 @@ static int dynamic_set_parameter(AVCodecContext *avctx) if (current_setting_number < setting_number && frame_number == dynamic_setting[current_setting_number].frame_number) { AVDictionaryEntry *e = NULL; - ret = str_to_dict(dynamic_setting[current_setting_number].optstr, &opts); + ret = str_to_dict(dynamic_setting[current_setting_number++].optstr, &opts); if (ret < 0) { fprintf(stderr, "The dynamic parameter is wrong\n"); goto fail; From 31a23149da2d24e4404800efb2aa73112bf2f4d9 Mon Sep 17 00:00:00 2001 From: Wenbin Chen Date: Mon, 13 Mar 2023 13:24:06 +0800 Subject: [PATCH 0437/2172] doc/encoders: Add av1 to qsv encoder's summary Signed-off-by: Wenbin Chen --- doc/encoders.texi | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/encoders.texi b/doc/encoders.texi index e9b34010edb..af3bd43cbe5 100644 --- a/doc/encoders.texi +++ b/doc/encoders.texi @@ -3188,8 +3188,8 @@ recommended value) and do not set a size constraint. @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, +VP9, AV1) @subsection Ratecontrol Method The ratecontrol method is selected as follows: From d0c6389e91f2e3254c602be9b5ca2e35922c39a3 Mon Sep 17 00:00:00 2001 From: Zhao Zhili Date: Sat, 11 Mar 2023 04:48:44 +0800 Subject: [PATCH 0438/2172] avcodec/mediacodecdec: refactor color space utils So it can be shared with encoder. Signed-off-by: Zhao Zhili --- libavcodec/mediacodec_wrapper.c | 102 ++++++++++++++++++++++++++++++ libavcodec/mediacodec_wrapper.h | 73 +++++++++++++++++++++ libavcodec/mediacodecdec_common.c | 87 ++----------------------- 3 files changed, 179 insertions(+), 83 deletions(-) diff --git a/libavcodec/mediacodec_wrapper.c b/libavcodec/mediacodec_wrapper.c index 34ec2134aa1..d1fb640ec21 100644 --- a/libavcodec/mediacodec_wrapper.c +++ b/libavcodec/mediacodec_wrapper.c @@ -2542,3 +2542,105 @@ int ff_Build_SDK_INT(AVCodecContext *avctx) return ret; } + +static struct { + enum FFAMediaFormatColorRange mf_range; + enum AVColorRange range; +} color_range_map[] = { + { COLOR_RANGE_FULL, AVCOL_RANGE_JPEG }, + { COLOR_RANGE_LIMITED, AVCOL_RANGE_MPEG }, +}; + +static struct { + enum FFAMediaFormatColorStandard mf_standard; + enum AVColorSpace space; +} color_space_map[] = { + { COLOR_STANDARD_BT709, AVCOL_SPC_BT709 }, + { COLOR_STANDARD_BT601_PAL, AVCOL_SPC_BT470BG }, + { COLOR_STANDARD_BT601_NTSC, AVCOL_SPC_SMPTE170M }, + { COLOR_STANDARD_BT2020, AVCOL_SPC_BT2020_NCL }, +}; + +static struct { + enum FFAMediaFormatColorStandard mf_standard; + enum AVColorPrimaries primaries; +} color_primaries_map[] = { + { COLOR_STANDARD_BT709, AVCOL_PRI_BT709 }, + { COLOR_STANDARD_BT601_PAL, AVCOL_PRI_BT470BG }, + { COLOR_STANDARD_BT601_NTSC, AVCOL_PRI_SMPTE170M }, + { COLOR_STANDARD_BT2020, AVCOL_PRI_BT2020 }, +}; + +static struct { + enum FFAMediaFormatColorTransfer mf_transfer; + enum AVColorTransferCharacteristic transfer; +} color_transfer_map[] = { + { COLOR_TRANSFER_LINEAR, AVCOL_TRC_LINEAR }, + { COLOR_TRANSFER_SDR_VIDEO, AVCOL_TRC_SMPTE170M }, + { COLOR_TRANSFER_ST2084, AVCOL_TRC_SMPTEST2084 }, + { COLOR_TRANSFER_HLG, AVCOL_TRC_ARIB_STD_B67 }, +}; + +enum AVColorRange ff_AMediaFormatColorRange_to_AVColorRange(int color_range) +{ + for (int i = 0; i < FF_ARRAY_ELEMS(color_range_map); i++) + if (color_range_map[i].mf_range == color_range) + return color_range_map[i].range; + + return AVCOL_RANGE_UNSPECIFIED; +} + +int ff_AMediaFormatColorRange_from_AVColorRange(enum AVColorRange color_range) +{ + for (int i = 0; i < FF_ARRAY_ELEMS(color_range_map); i++) + if (color_range_map[i].range == color_range) + return color_range_map[i].mf_range; + return COLOR_RANGE_UNSPECIFIED; +} + +enum AVColorSpace ff_AMediaFormatColorStandard_to_AVColorSpace(int color_standard) +{ + for (int i = 0; i < FF_ARRAY_ELEMS(color_space_map); i++) + if (color_space_map[i].mf_standard == color_standard) + return color_space_map[i].space; + + return AVCOL_SPC_UNSPECIFIED; +} + +int ff_AMediaFormatColorStandard_from_AVColorSpace(enum AVColorSpace color_space) +{ + for (int i = 0; i < FF_ARRAY_ELEMS(color_space_map); i++) + if (color_space_map[i].space == color_space) + return color_space_map[i].mf_standard; + + return COLOR_STANDARD_UNSPECIFIED; +} + +enum AVColorPrimaries ff_AMediaFormatColorStandard_to_AVColorPrimaries(int color_standard) +{ + for (int i = 0; i < FF_ARRAY_ELEMS(color_primaries_map); i++) + if (color_primaries_map[i].mf_standard == color_standard) + return color_primaries_map[i].primaries; + + return AVCOL_PRI_UNSPECIFIED; +} + +enum AVColorTransferCharacteristic +ff_AMediaFormatColorTransfer_to_AVColorTransfer(int color_transfer) +{ + for (int i = 0; i < FF_ARRAY_ELEMS(color_transfer_map); i++) + if (color_transfer_map[i].mf_transfer == color_transfer) + return color_transfer_map[i].transfer; + + return AVCOL_TRC_UNSPECIFIED; +} + +int ff_AMediaFormatColorTransfer_from_AVColorTransfer( + enum AVColorTransferCharacteristic color_transfer) +{ + for (int i = 0; i < FF_ARRAY_ELEMS(color_transfer_map); i++) + if (color_transfer_map[i].transfer == color_transfer) + return color_transfer_map[i].mf_transfer; + + return COLOR_TRANSFER_UNSPECIFIED; +} diff --git a/libavcodec/mediacodec_wrapper.h b/libavcodec/mediacodec_wrapper.h index 1b81e6db843..11a42604979 100644 --- a/libavcodec/mediacodec_wrapper.h +++ b/libavcodec/mediacodec_wrapper.h @@ -345,4 +345,77 @@ static inline int ff_AMediaCodec_signalEndOfInputStream(FFAMediaCodec *codec) int ff_Build_SDK_INT(AVCodecContext *avctx); +enum FFAMediaFormatColorRange { + COLOR_RANGE_UNSPECIFIED = 0x0, + COLOR_RANGE_FULL = 0x1, + COLOR_RANGE_LIMITED = 0x2, +}; + +enum FFAMediaFormatColorStandard { + COLOR_STANDARD_UNSPECIFIED = 0x0, + COLOR_STANDARD_BT709 = 0x1, + COLOR_STANDARD_BT601_PAL = 0x2, + COLOR_STANDARD_BT601_NTSC = 0x4, + COLOR_STANDARD_BT2020 = 0x6, +}; + +enum FFAMediaFormatColorTransfer { + COLOR_TRANSFER_UNSPECIFIED = 0x0, + COLOR_TRANSFER_LINEAR = 0x1, + COLOR_TRANSFER_SDR_VIDEO = 0x3, + COLOR_TRANSFER_ST2084 = 0x6, + COLOR_TRANSFER_HLG = 0x7, +}; + +/** + * Map MediaFormat color range to AVColorRange. + * + * return AVCOL_RANGE_UNSPECIFIED when failed. + */ +enum AVColorRange ff_AMediaFormatColorRange_to_AVColorRange(int color_range); + +/** + * Map AVColorRange to MediaFormat color range. + * + * return COLOR_RANGE_UNSPECIFIED when failed. + */ +int ff_AMediaFormatColorRange_from_AVColorRange(enum AVColorRange color_range); + +/** + * Map MediaFormat color standard to AVColorSpace. + * + * return AVCOL_SPC_UNSPECIFIED when failed. + */ +enum AVColorSpace ff_AMediaFormatColorStandard_to_AVColorSpace(int color_standard); + +/** + * Map AVColorSpace to MediaFormat color standard. + * + * return COLOR_STANDARD_UNSPECIFIED when failed. + */ +int ff_AMediaFormatColorStandard_from_AVColorSpace(enum AVColorSpace color_space); + +/** + * Map MediaFormat color standard to AVColorPrimaries. + * + * return AVCOL_PRI_UNSPECIFIED when failed. + */ +enum AVColorPrimaries ff_AMediaFormatColorStandard_to_AVColorPrimaries(int color_standard); + +/** + * Map MediaFormat color transfer to AVColorTransferCharacteristic. + * + * return AVCOL_TRC_UNSPECIFIED when failed. + */ +enum AVColorTransferCharacteristic +ff_AMediaFormatColorTransfer_to_AVColorTransfer(int color_transfer); + +/** + * Map AVColorTransferCharacteristic to MediaFormat color transfer. + * + * return COLOR_TRANSFER_UNSPECIFIED when failed. + */ +int ff_AMediaFormatColorTransfer_from_AVColorTransfer( + enum AVColorTransferCharacteristic color_transfer); + #endif /* AVCODEC_MEDIACODEC_WRAPPER_H */ diff --git a/libavcodec/mediacodecdec_common.c b/libavcodec/mediacodecdec_common.c index 03bee119188..1151bb71f9b 100644 --- a/libavcodec/mediacodecdec_common.c +++ b/libavcodec/mediacodecdec_common.c @@ -85,85 +85,6 @@ #define OUTPUT_DEQUEUE_TIMEOUT_US 8000 #define OUTPUT_DEQUEUE_BLOCK_TIMEOUT_US 1000000 -enum { - COLOR_RANGE_FULL = 0x1, - COLOR_RANGE_LIMITED = 0x2, -}; - -static enum AVColorRange mcdec_get_color_range(int color_range) -{ - switch (color_range) { - case COLOR_RANGE_FULL: - return AVCOL_RANGE_JPEG; - case COLOR_RANGE_LIMITED: - return AVCOL_RANGE_MPEG; - default: - return AVCOL_RANGE_UNSPECIFIED; - } -} - -enum { - COLOR_STANDARD_BT709 = 0x1, - COLOR_STANDARD_BT601_PAL = 0x2, - COLOR_STANDARD_BT601_NTSC = 0x4, - COLOR_STANDARD_BT2020 = 0x6, -}; - -static enum AVColorSpace mcdec_get_color_space(int color_standard) -{ - switch (color_standard) { - case COLOR_STANDARD_BT709: - return AVCOL_SPC_BT709; - case COLOR_STANDARD_BT601_PAL: - return AVCOL_SPC_BT470BG; - case COLOR_STANDARD_BT601_NTSC: - return AVCOL_SPC_SMPTE170M; - case COLOR_STANDARD_BT2020: - return AVCOL_SPC_BT2020_NCL; - default: - return AVCOL_SPC_UNSPECIFIED; - } -} - -static enum AVColorPrimaries mcdec_get_color_pri(int color_standard) -{ - switch (color_standard) { - case COLOR_STANDARD_BT709: - return AVCOL_PRI_BT709; - case COLOR_STANDARD_BT601_PAL: - return AVCOL_PRI_BT470BG; - case COLOR_STANDARD_BT601_NTSC: - return AVCOL_PRI_SMPTE170M; - case COLOR_STANDARD_BT2020: - return AVCOL_PRI_BT2020; - default: - return AVCOL_PRI_UNSPECIFIED; - } -} - -enum { - COLOR_TRANSFER_LINEAR = 0x1, - COLOR_TRANSFER_SDR_VIDEO = 0x3, - COLOR_TRANSFER_ST2084 = 0x6, - COLOR_TRANSFER_HLG = 0x7, -}; - -static enum AVColorTransferCharacteristic mcdec_get_color_trc(int color_transfer) -{ - switch (color_transfer) { - case COLOR_TRANSFER_LINEAR: - return AVCOL_TRC_LINEAR; - case COLOR_TRANSFER_SDR_VIDEO: - return AVCOL_TRC_SMPTE170M; - case COLOR_TRANSFER_ST2084: - return AVCOL_TRC_SMPTEST2084; - case COLOR_TRANSFER_HLG: - return AVCOL_TRC_ARIB_STD_B67; - default: - return AVCOL_TRC_UNSPECIFIED; - } -} - enum { COLOR_FormatYUV420Planar = 0x13, COLOR_FormatYUV420SemiPlanar = 0x15, @@ -517,17 +438,17 @@ static int mediacodec_dec_parse_format(AVCodecContext *avctx, MediaCodecDecConte AMEDIAFORMAT_GET_INT32(color_range, "color-range", 0); if (color_range) - avctx->color_range = mcdec_get_color_range(color_range); + avctx->color_range = ff_AMediaFormatColorRange_to_AVColorRange(color_range); AMEDIAFORMAT_GET_INT32(color_standard, "color-standard", 0); if (color_standard) { - avctx->colorspace = mcdec_get_color_space(color_standard); - avctx->color_primaries = mcdec_get_color_pri(color_standard); + avctx->colorspace = ff_AMediaFormatColorStandard_to_AVColorSpace(color_standard); + avctx->color_primaries = ff_AMediaFormatColorStandard_to_AVColorPrimaries(color_standard); } AMEDIAFORMAT_GET_INT32(color_transfer, "color-transfer", 0); if (color_transfer) - avctx->color_trc = mcdec_get_color_trc(color_transfer); + avctx->color_trc = ff_AMediaFormatColorTransfer_to_AVColorTransfer(color_transfer); av_log(avctx, AV_LOG_INFO, "Output crop parameters top=%d bottom=%d left=%d right=%d, " From f543f12817a2c11e942dc3f3eca78287417e13fa Mon Sep 17 00:00:00 2001 From: Zhao Zhili Date: Sat, 11 Mar 2023 04:48:45 +0800 Subject: [PATCH 0439/2172] avcodec/mediacodecenc: pass colorspace info to encoder Signed-off-by: Zhao Zhili --- libavcodec/mediacodecenc.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/libavcodec/mediacodecenc.c b/libavcodec/mediacodecenc.c index a92a8dc5a9c..2ab56597fe7 100644 --- a/libavcodec/mediacodecenc.c +++ b/libavcodec/mediacodecenc.c @@ -243,6 +243,16 @@ static av_cold int mediacodec_init(AVCodecContext *avctx) } } + ret = ff_AMediaFormatColorRange_from_AVColorRange(avctx->color_range); + if (ret != COLOR_RANGE_UNSPECIFIED) + ff_AMediaFormat_setInt32(format, "color-range", ret); + ret = ff_AMediaFormatColorStandard_from_AVColorSpace(avctx->colorspace); + if (ret != COLOR_STANDARD_UNSPECIFIED) + ff_AMediaFormat_setInt32(format, "color-standard", ret); + ret = ff_AMediaFormatColorTransfer_from_AVColorTransfer(avctx->color_trc); + if (ret != COLOR_TRANSFER_UNSPECIFIED) + ff_AMediaFormat_setInt32(format, "color-transfer", ret); + if (avctx->bit_rate) ff_AMediaFormat_setInt32(format, "bitrate", avctx->bit_rate); if (s->bitrate_mode >= 0) From 590d169bdb48e0fc30975ef4a93c4617273314a5 Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt Date: Tue, 14 Mar 2023 02:25:39 +0100 Subject: [PATCH 0440/2172] avcodec/decode: Reset MMX state for receive_frame decoders, too FFmpeg's assembly code currently does not abide by the plattform-specific ABIs wrt its handling of the X86 MMX flag: Resetting the MMX state is deferred to avoid doing it multiple times instead of ensuring that the CPU is in floating point state upon return from any function. Furthermore, resetting said state is sometimes done generically, namely for all the decoders using the ordinary decode callback; yet this is not done for the decoders using the receive_frame API. This led to problems when MJPEG (and the MJPEG-based decoders) were switched to the receive_frame API in commit e9a2a8777317d91af658f774c68442ac4aa726ec, because ff_mjpeg_decode_sos() only resets the MMX state on success, not on failure. Such issues are probably still possible with SMVJPEG, which still uses the receive_frame API. See issue #10210. This commit therefore also resets the MMX state for the receive_frame API to avoid any more surprises of this sort. Reviewed-by: Anton Khirnov Signed-off-by: Andreas Rheinhardt --- libavcodec/decode.c | 1 + 1 file changed, 1 insertion(+) diff --git a/libavcodec/decode.c b/libavcodec/decode.c index d1ba7f167fa..22a0f8eb252 100644 --- a/libavcodec/decode.c +++ b/libavcodec/decode.c @@ -547,6 +547,7 @@ static int decode_receive_frame_internal(AVCodecContext *avctx, AVFrame *frame) if (codec->cb_type == FF_CODEC_CB_TYPE_RECEIVE_FRAME) { ret = codec->cb.receive_frame(avctx, frame); + emms_c(); } else ret = decode_simple_receive_frame(avctx, frame); From af26a8ffbb8a553a890eefefd019cf2b1ccbdc84 Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt Date: Mon, 13 Mar 2023 05:00:44 +0100 Subject: [PATCH 0441/2172] avcodec/libmp3lame: Remove redundant av_packet_unref() The AVPacket given to an encoder's encode callback is unreferenced generically on error. Signed-off-by: Andreas Rheinhardt --- libavcodec/libmp3lame.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/libavcodec/libmp3lame.c b/libavcodec/libmp3lame.c index 26e58baa3d0..e119189f2ae 100644 --- a/libavcodec/libmp3lame.c +++ b/libavcodec/libmp3lame.c @@ -280,17 +280,14 @@ static int mp3lame_encode_frame(AVCodecContext *avctx, AVPacket *avpkt, // Check if subtraction resulted in an overflow if ((discard_padding < avctx->frame_size) != (avpkt->duration > 0)) { av_log(avctx, AV_LOG_ERROR, "discard padding overflow\n"); - av_packet_unref(avpkt); return AVERROR(EINVAL); } if ((!s->delay_sent && avctx->initial_padding > 0) || discard_padding > 0) { uint8_t* side_data = av_packet_new_side_data(avpkt, AV_PKT_DATA_SKIP_SAMPLES, 10); - if(!side_data) { - av_packet_unref(avpkt); + if (!side_data) return AVERROR(ENOMEM); - } if (!s->delay_sent) { AV_WL32(side_data, avctx->initial_padding); s->delay_sent = 1; From e5abcf0d290df85b78b9f52d52e824a7f1123d11 Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt Date: Mon, 13 Mar 2023 05:03:52 +0100 Subject: [PATCH 0442/2172] avcodec/libfdk-aacenc: Remove redundant av_packet_unref() The AVPacket given to an encoder's encode callback is unreferenced generically on error. Signed-off-by: Andreas Rheinhardt --- libavcodec/libfdk-aacenc.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/libavcodec/libfdk-aacenc.c b/libavcodec/libfdk-aacenc.c index db5b0841e05..eb97e0fb417 100644 --- a/libavcodec/libfdk-aacenc.c +++ b/libavcodec/libfdk-aacenc.c @@ -475,16 +475,13 @@ static int aac_encode_frame(AVCodecContext *avctx, AVPacket *avpkt, // Check if subtraction resulted in an overflow if ((discard_padding < avctx->frame_size) != (avpkt->duration > 0)) { av_log(avctx, AV_LOG_ERROR, "discard padding overflow\n"); - av_packet_unref(avpkt); return AVERROR(EINVAL); } if ((!s->delay_sent && avctx->initial_padding > 0) || discard_padding > 0) { uint8_t *side_data = av_packet_new_side_data(avpkt, AV_PKT_DATA_SKIP_SAMPLES, 10); - if (!side_data) { - av_packet_unref(avpkt); + if (!side_data) return AVERROR(ENOMEM); - } if (!s->delay_sent) { AV_WL32(side_data, avctx->initial_padding); s->delay_sent = 1; From adb5f7b41faf354a3e0bf722f44aeb230aefa310 Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt Date: Mon, 13 Mar 2023 05:08:53 +0100 Subject: [PATCH 0443/2172] avcodec/libopusenc: Remove redundant av_packet_unref() The AVPacket given to an encoder's encode callback is unreferenced generically on error. Signed-off-by: Andreas Rheinhardt --- libavcodec/libopusenc.c | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/libavcodec/libopusenc.c b/libavcodec/libopusenc.c index 75bc491c9ef..5a0786f32fd 100644 --- a/libavcodec/libopusenc.c +++ b/libavcodec/libopusenc.c @@ -512,18 +512,14 @@ static int libopus_encode(AVCodecContext *avctx, AVPacket *avpkt, discard_padding = opus->opts.packet_size - avpkt->duration; // Check if subtraction resulted in an overflow - if ((discard_padding < opus->opts.packet_size) != (avpkt->duration > 0)) { - av_packet_unref(avpkt); + if ((discard_padding < opus->opts.packet_size) != (avpkt->duration > 0)) return AVERROR(EINVAL); - } if (discard_padding > 0) { uint8_t* side_data = av_packet_new_side_data(avpkt, AV_PKT_DATA_SKIP_SAMPLES, 10); - if(!side_data) { - av_packet_unref(avpkt); + if (!side_data) return AVERROR(ENOMEM); - } AV_WL32(side_data + 4, discard_padding); } From 771c27119d13c3c1d0ced53dbb72a65e8ad2d9c7 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Wed, 15 Mar 2023 22:48:28 +0100 Subject: [PATCH 0444/2172] avfilter/vf_uspp: update to new APIs Signed-off-by: Michael Niedermayer --- configure | 1 - libavfilter/vf_uspp.c | 49 ++++++++++++++++++++++++++++++++++++------- 2 files changed, 41 insertions(+), 9 deletions(-) diff --git a/configure b/configure index 03d3c429a58..0370e25577e 100755 --- a/configure +++ b/configure @@ -7359,7 +7359,6 @@ enable frame_thread_encoder # they are kept disabled for now, but will be removed if # nobody updates and re-enables them disable mcdeint_filter -disable uspp_filter enabled asm || { arch=c; disable $ARCH_LIST $ARCH_EXT_LIST; } diff --git a/libavfilter/vf_uspp.c b/libavfilter/vf_uspp.c index 051de007716..43114e1b50b 100644 --- a/libavfilter/vf_uspp.c +++ b/libavfilter/vf_uspp.c @@ -53,6 +53,7 @@ typedef struct USPPContext { int outbuf_size; uint8_t *outbuf; AVCodecContext *avctx_enc[BLOCK*BLOCK]; + AVCodecContext *avctx_dec[BLOCK*BLOCK]; AVPacket *pkt; AVFrame *frame; AVFrame *frame_dec; @@ -244,7 +245,6 @@ static void filter(USPPContext *p, uint8_t *dst[3], uint8_t *src[3], const int BLOCKc = BLOCK >> p->hsub; int offset; AVPacket *pkt = p->pkt; - int got_pkt_ptr; av_packet_unref(pkt); pkt->data = p->outbuf; @@ -255,14 +255,28 @@ static void filter(USPPContext *p, uint8_t *dst[3], uint8_t *src[3], p->frame->data[2] = p->src[2] + x1c + y1c * p->frame->linesize[2]; p->frame->format = p->avctx_enc[i]->pix_fmt; - ret = avcodec_encode_video2(p->avctx_enc[i], pkt, p->frame, &got_pkt_ptr); + ret = avcodec_send_frame(p->avctx_enc[i], p->frame); if (ret < 0) { - av_log(p->avctx_enc[i], AV_LOG_ERROR, "Encoding failed\n"); + av_log(p->avctx_enc[i], AV_LOG_ERROR, "Error sending a frame for encoding\n"); + continue; + } + ret = avcodec_receive_packet(p->avctx_enc[i], pkt); + if (ret < 0) { + av_log(p->avctx_enc[i], AV_LOG_ERROR, "Error receiving a packet from encoding\n"); continue; } - av_packet_unref(pkt); - p->frame_dec = p->avctx_enc[i]->coded_frame; + ret = avcodec_send_packet(p->avctx_dec[i], pkt); + av_packet_unref(pkt); + if (ret < 0) { + av_log(p->avctx_dec[i], AV_LOG_ERROR, "Error sending a packet for decoding\n"); + continue; + } + ret = avcodec_receive_frame(p->avctx_dec[i], p->frame_dec); + if (ret < 0) { + av_log(p->avctx_dec[i], AV_LOG_ERROR, "Error receiving a frame from decoding\n"); + continue; + } offset = (BLOCK-x1) + (BLOCK-y1) * p->frame_dec->linesize[0]; @@ -315,10 +329,15 @@ static int config_input(AVFilterLink *inlink) int i; const AVCodec *enc = avcodec_find_encoder(AV_CODEC_ID_SNOW); + const AVCodec *dec = avcodec_find_decoder(AV_CODEC_ID_SNOW); if (!enc) { av_log(ctx, AV_LOG_ERROR, "SNOW encoder not found.\n"); return AVERROR(EINVAL); } + if (!dec) { + av_log(ctx, AV_LOG_ERROR, "SNOW decoder not found.\n"); + return AVERROR(EINVAL); + } uspp->hsub = desc->log2_chroma_w; uspp->vsub = desc->log2_chroma_h; @@ -341,15 +360,20 @@ static int config_input(AVFilterLink *inlink) } for (i = 0; i < (1<log2_count); i++) { - AVCodecContext *avctx_enc; + AVCodecContext *avctx_enc, *avctx_dec; AVDictionary *opts = NULL; int ret; if (!(uspp->avctx_enc[i] = avcodec_alloc_context3(NULL))) return AVERROR(ENOMEM); + if (!(uspp->avctx_dec[i] = avcodec_alloc_context3(NULL))) + return AVERROR(ENOMEM); avctx_enc = uspp->avctx_enc[i]; + avctx_dec = uspp->avctx_dec[i]; + avctx_dec->width = avctx_enc->width = width + BLOCK; + avctx_dec->height = avctx_enc->height = height + BLOCK; avctx_enc->time_base = (AVRational){1,25}; // meaningless avctx_enc->gop_size = INT_MAX; @@ -358,17 +382,24 @@ static int config_input(AVFilterLink *inlink) avctx_enc->flags = AV_CODEC_FLAG_QSCALE | AV_CODEC_FLAG_LOW_DELAY; avctx_enc->strict_std_compliance = FF_COMPLIANCE_EXPERIMENTAL; avctx_enc->global_quality = 123; - av_dict_set(&opts, "no_bitstream", "1", 0); ret = avcodec_open2(avctx_enc, enc, &opts); av_dict_free(&opts); if (ret < 0) return ret; av_assert0(avctx_enc->codec); + + + ret = avcodec_open2(avctx_dec, dec, NULL); + if (ret < 0) + return ret; + } uspp->outbuf_size = (width + BLOCK) * (height + BLOCK) * 10; if (!(uspp->frame = av_frame_alloc())) return AVERROR(ENOMEM); + if (!(uspp->frame_dec = av_frame_alloc())) + return AVERROR(ENOMEM); if (!(uspp->pkt = av_packet_alloc())) return AVERROR(ENOMEM); if (!(uspp->outbuf = av_malloc(uspp->outbuf_size))) @@ -460,8 +491,10 @@ static av_cold void uninit(AVFilterContext *ctx) av_freep(&uspp->src[i]); } - for (i = 0; i < (1 << uspp->log2_count); i++) + for (i = 0; i < (1 << uspp->log2_count); i++) { avcodec_free_context(&uspp->avctx_enc[i]); + avcodec_free_context(&uspp->avctx_dec[i]); + } av_freep(&uspp->non_b_qp_table); av_freep(&uspp->outbuf); From cee4b99d41dd2434c300c5db3dc6511c38707985 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Wed, 15 Mar 2023 22:53:13 +0100 Subject: [PATCH 0445/2172] avfilter/vf_uspp: Support any codec Signed-off-by: Michael Niedermayer --- doc/filters.texi | 3 +++ libavfilter/vf_uspp.c | 11 ++++++----- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/doc/filters.texi b/doc/filters.texi index 77b594f69cb..d634924bfb0 100644 --- a/doc/filters.texi +++ b/doc/filters.texi @@ -23364,6 +23364,9 @@ that value the speed drops by a factor of approximately 2. Default value is @item qp Force a constant quantization parameter. If not set, the filter will use the QP from the video stream (if available). + +@item codec +Use specified codec instead of snow. @end table @section v360 diff --git a/libavfilter/vf_uspp.c b/libavfilter/vf_uspp.c index 43114e1b50b..a7bf8e30877 100644 --- a/libavfilter/vf_uspp.c +++ b/libavfilter/vf_uspp.c @@ -46,6 +46,7 @@ typedef struct USPPContext { int log2_count; int hsub, vsub; int qp; + char *codec_name; enum AVVideoEncParamsType qscale_type; int temp_stride[3]; uint8_t *src[3]; @@ -68,6 +69,7 @@ static const AVOption uspp_options[] = { { "quality", "set quality", OFFSET(log2_count), AV_OPT_TYPE_INT, {.i64 = 3}, 0, MAX_LEVEL, FLAGS }, { "qp", "force a constant quantizer parameter", OFFSET(qp), AV_OPT_TYPE_INT, {.i64 = 0}, 0, 63, FLAGS }, { "use_bframe_qp", "use B-frames' QP", OFFSET(use_bframe_qp), AV_OPT_TYPE_BOOL,{.i64 = 0}, 0, 1, FLAGS }, + { "codec", "Codec name", OFFSET(codec_name), AV_OPT_TYPE_STRING, {.str = "snow"}, 0, 0, FLAGS }, { NULL } }; @@ -327,15 +329,14 @@ static int config_input(AVFilterLink *inlink) const int width = inlink->w; const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(inlink->format); int i; - - const AVCodec *enc = avcodec_find_encoder(AV_CODEC_ID_SNOW); - const AVCodec *dec = avcodec_find_decoder(AV_CODEC_ID_SNOW); + const AVCodec *enc = avcodec_find_encoder_by_name(uspp->codec_name); + const AVCodec *dec = avcodec_find_decoder_by_name(uspp->codec_name); if (!enc) { - av_log(ctx, AV_LOG_ERROR, "SNOW encoder not found.\n"); + av_log(ctx, AV_LOG_ERROR, "encoder %s not found.\n", uspp->codec_name); return AVERROR(EINVAL); } if (!dec) { - av_log(ctx, AV_LOG_ERROR, "SNOW decoder not found.\n"); + av_log(ctx, AV_LOG_ERROR, "decoder %s not found.\n", uspp->codec_name); return AVERROR(EINVAL); } From 3ead1fe41310066dde4e99292e8e36db1b8707d9 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Thu, 16 Mar 2023 00:25:33 +0100 Subject: [PATCH 0446/2172] avfilter/vf_uspp: about 10x the speed with threads Signed-off-by: Michael Niedermayer --- libavfilter/vf_uspp.c | 183 +++++++++++++++++++++++------------------- 1 file changed, 101 insertions(+), 82 deletions(-) diff --git a/libavfilter/vf_uspp.c b/libavfilter/vf_uspp.c index a7bf8e30877..f60eb230a2f 100644 --- a/libavfilter/vf_uspp.c +++ b/libavfilter/vf_uspp.c @@ -44,6 +44,7 @@ typedef struct USPPContext { const AVClass *av_class; int log2_count; + int count; int hsub, vsub; int qp; char *codec_name; @@ -55,12 +56,13 @@ typedef struct USPPContext { uint8_t *outbuf; AVCodecContext *avctx_enc[BLOCK*BLOCK]; AVCodecContext *avctx_dec[BLOCK*BLOCK]; - AVPacket *pkt; - AVFrame *frame; - AVFrame *frame_dec; + AVPacket *pkt [BLOCK*BLOCK]; + AVFrame *frame [BLOCK*BLOCK]; + AVFrame *frame_dec [BLOCK*BLOCK]; int8_t *non_b_qp_table; int non_b_qp_stride; int use_bframe_qp; + int quality; } USPPContext; #define OFFSET(x) offsetof(USPPContext, x) @@ -188,13 +190,87 @@ static void store_slice_c(uint8_t *dst, const uint16_t *src, } } -static void filter(USPPContext *p, uint8_t *dst[3], uint8_t *src[3], +static int filter_1phase(AVFilterContext *ctx, void *arg, int i, int nb_jobs) +{ + USPPContext *p = ctx->priv; + int ret, x, y; + int width = ctx->inputs[0]->w; + int height = ctx->inputs[0]->h; + + const int x1 = offset[i+nb_jobs-1][0]; + const int y1 = offset[i+nb_jobs-1][1]; + const int x1c = x1 >> p->hsub; + const int y1c = y1 >> p->vsub; + const int BLOCKc = BLOCK >> p->hsub; + int offset; + AVPacket *pkt = p->pkt[i]; + + av_packet_unref(pkt); + pkt->data = p->outbuf; + pkt->size = p->outbuf_size; + + p->frame[i]->linesize[0] = p->temp_stride[0]; + p->frame[i]->linesize[1] = p->temp_stride[1]; + p->frame[i]->linesize[2] = p->temp_stride[2]; + p->frame[i]->height = height + BLOCK; + p->frame[i]->width = width + BLOCK; + p->frame[i]->data[0] = p->src[0] + x1 + y1 * p->frame[i]->linesize[0]; + p->frame[i]->data[1] = p->src[1] + x1c + y1c * p->frame[i]->linesize[1]; + p->frame[i]->data[2] = p->src[2] + x1c + y1c * p->frame[i]->linesize[2]; + p->frame[i]->format = p->avctx_enc[i]->pix_fmt; + p->frame[i]->quality = p->quality; + + ret = avcodec_send_frame(p->avctx_enc[i], p->frame[i]); + if (ret < 0) { + av_log(p->avctx_enc[i], AV_LOG_ERROR, "Error sending a frame for encoding\n"); + return ret; + } + ret = avcodec_receive_packet(p->avctx_enc[i], pkt); + if (ret < 0) { + av_log(p->avctx_enc[i], AV_LOG_ERROR, "Error receiving a packet from encoding\n"); + return ret; + } + + ret = avcodec_send_packet(p->avctx_dec[i], pkt); + av_packet_unref(pkt); + if (ret < 0) { + av_log(p->avctx_dec[i], AV_LOG_ERROR, "Error sending a packet for decoding\n"); + return ret; + } + ret = avcodec_receive_frame(p->avctx_dec[i], p->frame_dec[i]); + if (ret < 0) { + av_log(p->avctx_dec[i], AV_LOG_ERROR, "Error receiving a frame from decoding\n"); + return ret; + } + + offset = (BLOCK-x1) + (BLOCK-y1) * p->frame_dec[i]->linesize[0]; + + for (y = 0; y < height; y++) + for (x = 0; x < width; x++) + p->temp[0][x + y * p->temp_stride[0]] += p->frame_dec[i]->data[0][x + y * p->frame_dec[i]->linesize[0] + offset]; + + + if (!p->frame_dec[i]->data[2] || !p->temp[2]) + return 0; + + offset = (BLOCKc-x1c) + (BLOCKc-y1c) * p->frame_dec[i]->linesize[1]; + + for (y = 0; y < AV_CEIL_RSHIFT(height, p->vsub); y++) { + for (x = 0; x < AV_CEIL_RSHIFT(width, p->hsub); x++) { + p->temp[1][x + y * p->temp_stride[1]] += p->frame_dec[i]->data[1][x + y * p->frame_dec[i]->linesize[1] + offset]; + p->temp[2][x + y * p->temp_stride[2]] += p->frame_dec[i]->data[2][x + y * p->frame_dec[i]->linesize[2] + offset]; + } + } + + return 0; +} + +static void filter(AVFilterContext *ctx, uint8_t *dst[3], uint8_t *src[3], int dst_stride[3], int src_stride[3], int width, int height, uint8_t *qp_store, int qp_stride) { + USPPContext *p = ctx->priv; int x, y, i, j; - const int count = 1<log2_count; - int ret; for (i = 0; i < 3; i++) { int is_chroma = !!i; @@ -219,12 +295,11 @@ static void filter(USPPContext *p, uint8_t *dst[3], uint8_t *src[3], memcpy(p->src[i] + (h+block +y) * stride, p->src[i] + (h-y+block-1) * stride, stride); } - p->frame->linesize[i] = stride; memset(p->temp[i], 0, (h + 2 * block) * stride * sizeof(int16_t)); } if (p->qp) - p->frame->quality = p->qp * FF_QP2LAMBDA; + p->quality = p->qp * FF_QP2LAMBDA; else { int qpsum=0; int qpcount = (height>>4) * (height>>4); @@ -233,71 +308,11 @@ static void filter(USPPContext *p, uint8_t *dst[3], uint8_t *src[3], for (x = 0; x < (width>>4); x++) qpsum += qp_store[x + y * qp_stride]; } - p->frame->quality = ff_norm_qscale((qpsum + qpcount/2) / qpcount, p->qscale_type) * FF_QP2LAMBDA; + p->quality = ff_norm_qscale((qpsum + qpcount/2) / qpcount, p->qscale_type) * FF_QP2LAMBDA; } // init per MB qscale stuff FIXME - p->frame->height = height + BLOCK; - p->frame->width = width + BLOCK; - - for (i = 0; i < count; i++) { - const int x1 = offset[i+count-1][0]; - const int y1 = offset[i+count-1][1]; - const int x1c = x1 >> p->hsub; - const int y1c = y1 >> p->vsub; - const int BLOCKc = BLOCK >> p->hsub; - int offset; - AVPacket *pkt = p->pkt; - - av_packet_unref(pkt); - pkt->data = p->outbuf; - pkt->size = p->outbuf_size; - - p->frame->data[0] = p->src[0] + x1 + y1 * p->frame->linesize[0]; - p->frame->data[1] = p->src[1] + x1c + y1c * p->frame->linesize[1]; - p->frame->data[2] = p->src[2] + x1c + y1c * p->frame->linesize[2]; - p->frame->format = p->avctx_enc[i]->pix_fmt; - - ret = avcodec_send_frame(p->avctx_enc[i], p->frame); - if (ret < 0) { - av_log(p->avctx_enc[i], AV_LOG_ERROR, "Error sending a frame for encoding\n"); - continue; - } - ret = avcodec_receive_packet(p->avctx_enc[i], pkt); - if (ret < 0) { - av_log(p->avctx_enc[i], AV_LOG_ERROR, "Error receiving a packet from encoding\n"); - continue; - } - - ret = avcodec_send_packet(p->avctx_dec[i], pkt); - av_packet_unref(pkt); - if (ret < 0) { - av_log(p->avctx_dec[i], AV_LOG_ERROR, "Error sending a packet for decoding\n"); - continue; - } - ret = avcodec_receive_frame(p->avctx_dec[i], p->frame_dec); - if (ret < 0) { - av_log(p->avctx_dec[i], AV_LOG_ERROR, "Error receiving a frame from decoding\n"); - continue; - } - - offset = (BLOCK-x1) + (BLOCK-y1) * p->frame_dec->linesize[0]; - - for (y = 0; y < height; y++) - for (x = 0; x < width; x++) - p->temp[0][x + y * p->temp_stride[0]] += p->frame_dec->data[0][x + y * p->frame_dec->linesize[0] + offset]; - - if (!src[2] || !dst[2]) - continue; - - offset = (BLOCKc-x1c) + (BLOCKc-y1c) * p->frame_dec->linesize[1]; - for (y = 0; y < AV_CEIL_RSHIFT(height, p->vsub); y++) { - for (x = 0; x < AV_CEIL_RSHIFT(width, p->hsub); x++) { - p->temp[1][x + y * p->temp_stride[1]] += p->frame_dec->data[1][x + y * p->frame_dec->linesize[1] + offset]; - p->temp[2][x + y * p->temp_stride[2]] += p->frame_dec->data[2][x + y * p->frame_dec->linesize[2] + offset]; - } - } - } + ff_filter_execute(ctx, filter_1phase, NULL, NULL, p->count); for (j = 0; j < 3; j++) { int is_chroma = !!j; @@ -342,6 +357,7 @@ static int config_input(AVFilterLink *inlink) uspp->hsub = desc->log2_chroma_w; uspp->vsub = desc->log2_chroma_h; + uspp->count = 1<log2_count; for (i = 0; i < 3; i++) { int is_chroma = !!i; @@ -360,7 +376,7 @@ static int config_input(AVFilterLink *inlink) return AVERROR(ENOMEM); } - for (i = 0; i < (1<log2_count); i++) { + for (i = 0; i < uspp->count; i++) { AVCodecContext *avctx_enc, *avctx_dec; AVDictionary *opts = NULL; int ret; @@ -383,6 +399,8 @@ static int config_input(AVFilterLink *inlink) avctx_enc->flags = AV_CODEC_FLAG_QSCALE | AV_CODEC_FLAG_LOW_DELAY; avctx_enc->strict_std_compliance = FF_COMPLIANCE_EXPERIMENTAL; avctx_enc->global_quality = 123; + avctx_dec->thread_count = + avctx_enc->thread_count = 1; // We do threading in the filter with muiltiple codecs ret = avcodec_open2(avctx_enc, enc, &opts); av_dict_free(&opts); if (ret < 0) @@ -394,15 +412,15 @@ static int config_input(AVFilterLink *inlink) if (ret < 0) return ret; + if (!(uspp->frame[i] = av_frame_alloc())) + return AVERROR(ENOMEM); + if (!(uspp->frame_dec[i] = av_frame_alloc())) + return AVERROR(ENOMEM); + if (!(uspp->pkt[i] = av_packet_alloc())) + return AVERROR(ENOMEM); } uspp->outbuf_size = (width + BLOCK) * (height + BLOCK) * 10; - if (!(uspp->frame = av_frame_alloc())) - return AVERROR(ENOMEM); - if (!(uspp->frame_dec = av_frame_alloc())) - return AVERROR(ENOMEM); - if (!(uspp->pkt = av_packet_alloc())) - return AVERROR(ENOMEM); if (!(uspp->outbuf = av_malloc(uspp->outbuf_size))) return AVERROR(ENOMEM); @@ -464,7 +482,7 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in) out->height = in->height; } - filter(uspp, out->data, in->data, out->linesize, in->linesize, + filter(ctx, out->data, in->data, out->linesize, in->linesize, inlink->w, inlink->h, qp_table, qp_stride); } } @@ -492,15 +510,16 @@ static av_cold void uninit(AVFilterContext *ctx) av_freep(&uspp->src[i]); } - for (i = 0; i < (1 << uspp->log2_count); i++) { + for (i = 0; i < uspp->count; i++) { avcodec_free_context(&uspp->avctx_enc[i]); avcodec_free_context(&uspp->avctx_dec[i]); + av_frame_free(&uspp->frame[i]); + av_frame_free(&uspp->frame_dec[i]); + av_packet_free(&uspp->pkt[i]); } av_freep(&uspp->non_b_qp_table); av_freep(&uspp->outbuf); - av_packet_free(&uspp->pkt); - av_frame_free(&uspp->frame); } static const AVFilterPad uspp_inputs[] = { @@ -528,5 +547,5 @@ const AVFilter ff_vf_uspp = { FILTER_OUTPUTS(uspp_outputs), FILTER_PIXFMTS_ARRAY(pix_fmts), .priv_class = &uspp_class, - .flags = AVFILTER_FLAG_SUPPORT_TIMELINE_INTERNAL, + .flags = AVFILTER_FLAG_SUPPORT_TIMELINE_INTERNAL | AVFILTER_FLAG_SLICE_THREADS, }; From 57afccc0ef8d3024ffb2d1b2d25c9670b9501248 Mon Sep 17 00:00:00 2001 From: Haihao Xiang Date: Thu, 16 Mar 2023 10:20:52 +0800 Subject: [PATCH 0447/2172] lavfi/vf_vpp_qsv: set the right timestamp for AVERROR_EOF Rescale the timestamp for AVERROR_EOF. This can fix tickets 10261 and 10262. Tested-by: Dmitry Rogozhkin Signed-off-by: Haihao Xiang --- libavfilter/vf_vpp_qsv.c | 1 + 1 file changed, 1 insertion(+) diff --git a/libavfilter/vf_vpp_qsv.c b/libavfilter/vf_vpp_qsv.c index ac77f7bb4ba..b4dd7a41913 100644 --- a/libavfilter/vf_vpp_qsv.c +++ b/libavfilter/vf_vpp_qsv.c @@ -602,6 +602,7 @@ static int activate(AVFilterContext *ctx) return FFERROR_NOT_READY; eof: + pts = av_rescale_q(pts, inlink->time_base, outlink->time_base); ff_outlink_set_status(outlink, status, pts); return 0; } From 0ad64cdd92a132b57748bd8b84db955e1369f74e Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Fri, 17 Mar 2023 18:29:34 +0100 Subject: [PATCH 0448/2172] fftools/ffmpeg_filter: initialize graph inputs/outputs Avoids uninitialized free on error. Found-by: Paul B Mahol --- fftools/ffmpeg_filter.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/fftools/ffmpeg_filter.c b/fftools/ffmpeg_filter.c index 3504a3cc0ae..62d0eefa6d3 100644 --- a/fftools/ffmpeg_filter.c +++ b/fftools/ffmpeg_filter.c @@ -445,6 +445,9 @@ static int graph_parse(AVFilterGraph *graph, const char *desc, AVFilterGraphSegment *seg; int ret; + *inputs = NULL; + *outputs = NULL; + ret = avfilter_graph_segment_parse(graph, desc, 0, &seg); if (ret < 0) return ret; From e6126abc6997058ca49ee596b70611bbe367163e Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Thu, 9 Mar 2023 16:59:12 +0100 Subject: [PATCH 0449/2172] fftools/ffprobe: stop using AVFrame.pkt_{pos,size} These fields are ad-hoc and will be deprecated. Use the recently-added AV_CODEC_FLAG_COPY_OPAQUE to pass arbitrary user data from packets to frames. Changes the result of the flcl1905 test, which uses ffprobe to decode wmav2 with multiple frames per packet. Such packets are handled internally by calling the decoder's decode callback multiple times, offsetting the internal packet's data pointer and decreasing its size after each call. The output pkt_size value before this commit is then the remaining internal packet size at the time of each internal decode call. After this commit, output pkt_size is simply the size of the full packet submitted by the caller to the decoder. This is more correct, since internal packets are never seen by the caller and should have no observable outside effects. --- fftools/ffprobe.c | 26 +++- tests/ref/fate/flcl1905 | 318 ++++++++++++++++++++-------------------- 2 files changed, 181 insertions(+), 163 deletions(-) diff --git a/fftools/ffprobe.c b/fftools/ffprobe.c index 969fa1b9f84..95dda97edcd 100644 --- a/fftools/ffprobe.c +++ b/fftools/ffprobe.c @@ -79,6 +79,12 @@ # define pthread_mutex_unlock(a) do{}while(0) #endif +// attached as opaque_ref to packets/frames +typedef struct FrameData { + int64_t pkt_pos; + int pkt_size; +} FrameData; + typedef struct InputStream { AVStream *st; @@ -2571,6 +2577,7 @@ static void show_subtitle(WriterContext *w, AVSubtitle *sub, AVStream *stream, static void show_frame(WriterContext *w, AVFrame *frame, AVStream *stream, AVFormatContext *fmt_ctx) { + FrameData *fd = frame->opaque_ref ? (FrameData*)frame->opaque_ref->data : NULL; AVBPrint pbuf; char val_str[128]; const char *s; @@ -2599,10 +2606,10 @@ static void show_frame(WriterContext *w, AVFrame *frame, AVStream *stream, #endif print_duration_ts ("duration", frame->duration); print_duration_time("duration_time", frame->duration, &stream->time_base); - if (frame->pkt_pos != -1) print_fmt ("pkt_pos", "%"PRId64, frame->pkt_pos); - else print_str_opt("pkt_pos", "N/A"); - if (frame->pkt_size != -1) print_val ("pkt_size", frame->pkt_size, unit_byte_str); - else print_str_opt("pkt_size", "N/A"); + if (fd && fd->pkt_pos != -1) print_fmt ("pkt_pos", "%"PRId64, fd->pkt_pos); + else print_str_opt("pkt_pos", "N/A"); + if (fd && fd->pkt_size != -1) print_val ("pkt_size", fd->pkt_size, unit_byte_str); + else print_str_opt("pkt_size", "N/A"); switch (stream->codecpar->codec_type) { AVRational sar; @@ -2911,6 +2918,15 @@ static int read_interval_packets(WriterContext *w, InputFile *ifile, } if (do_read_frames) { int packet_new = 1; + FrameData *fd; + + pkt->opaque_ref = av_buffer_allocz(sizeof(*fd)); + if (!pkt->opaque_ref) + return AVERROR(ENOMEM); + fd = (FrameData*)pkt->opaque_ref->data; + fd->pkt_pos = pkt->pos; + fd->pkt_size = pkt->size; + while (process_frame(w, ifile, frame, pkt, &packet_new) > 0); } } @@ -3405,6 +3421,8 @@ static int open_input_file(InputFile *ifile, const char *filename, av_dict_set(&codec_opts, "threads", "1", 0); } + av_dict_set(&opts, "flags", "+copy_opaque", AV_DICT_MULTIKEY); + ist->dec_ctx->pkt_timebase = stream->time_base; if (avcodec_open2(ist->dec_ctx, codec, &opts) < 0) { diff --git a/tests/ref/fate/flcl1905 b/tests/ref/fate/flcl1905 index 666b2600e43..c8b9d8bce4c 100644 --- a/tests/ref/fate/flcl1905 +++ b/tests/ref/fate/flcl1905 @@ -1,192 +1,192 @@ packet|codec_type=audio|stream_index=0|pts=0|pts_time=0.000000|dts=0|dts_time=0.000000|duration=22528|duration_time=0.510839|size=4092|pos=56|flags=K__ -frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=56|pkt_size=3348|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown -frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=56|pkt_size=2976|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown -frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=56|pkt_size=2604|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown -frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=56|pkt_size=2232|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown -frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=56|pkt_size=1860|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown -frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=56|pkt_size=1488|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown -frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=56|pkt_size=1116|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown -frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=56|pkt_size=744|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown -frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=56|pkt_size=372|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown +frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=56|pkt_size=4092|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown +frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=56|pkt_size=4092|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown +frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=56|pkt_size=4092|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown +frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=56|pkt_size=4092|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown +frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=56|pkt_size=4092|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown +frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=56|pkt_size=4092|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown +frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=56|pkt_size=4092|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown +frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=56|pkt_size=4092|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown +frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=56|pkt_size=4092|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown packet|codec_type=audio|stream_index=0|pts=22528|pts_time=0.510839|dts=22528|dts_time=0.510839|duration=22528|duration_time=0.510839|size=4092|pos=4148|flags=K__ frame|media_type=audio|stream_index=0|key_frame=1|pts=22528|pts_time=0.510839|pkt_dts=22528|pkt_dts_time=0.510839|best_effort_timestamp=22528|best_effort_timestamp_time=0.510839|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=4148|pkt_size=4092|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown -frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=4148|pkt_size=3720|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown -frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=4148|pkt_size=3348|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown -frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=4148|pkt_size=2976|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown -frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=4148|pkt_size=2604|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown -frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=4148|pkt_size=2232|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown -frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=4148|pkt_size=1860|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown -frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=4148|pkt_size=1488|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown -frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=4148|pkt_size=1116|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown -frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=4148|pkt_size=744|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown -frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=4148|pkt_size=372|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown +frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=4148|pkt_size=4092|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown +frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=4148|pkt_size=4092|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown +frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=4148|pkt_size=4092|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown +frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=4148|pkt_size=4092|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown +frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=4148|pkt_size=4092|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown +frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=4148|pkt_size=4092|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown +frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=4148|pkt_size=4092|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown +frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=4148|pkt_size=4092|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown +frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=4148|pkt_size=4092|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown +frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=4148|pkt_size=4092|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown packet|codec_type=audio|stream_index=0|pts=45056|pts_time=1.021678|dts=45056|dts_time=1.021678|duration=22528|duration_time=0.510839|size=4092|pos=8240|flags=K__ frame|media_type=audio|stream_index=0|key_frame=1|pts=45056|pts_time=1.021678|pkt_dts=45056|pkt_dts_time=1.021678|best_effort_timestamp=45056|best_effort_timestamp_time=1.021678|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=8240|pkt_size=4092|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown -frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=8240|pkt_size=3720|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown -frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=8240|pkt_size=3348|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown -frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=8240|pkt_size=2976|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown -frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=8240|pkt_size=2604|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown -frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=8240|pkt_size=2232|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown -frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=8240|pkt_size=1860|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown -frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=8240|pkt_size=1488|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown -frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=8240|pkt_size=1116|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown -frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=8240|pkt_size=744|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown -frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=8240|pkt_size=372|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown +frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=8240|pkt_size=4092|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown +frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=8240|pkt_size=4092|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown +frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=8240|pkt_size=4092|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown +frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=8240|pkt_size=4092|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown +frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=8240|pkt_size=4092|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown +frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=8240|pkt_size=4092|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown +frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=8240|pkt_size=4092|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown +frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=8240|pkt_size=4092|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown +frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=8240|pkt_size=4092|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown +frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=8240|pkt_size=4092|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown packet|codec_type=audio|stream_index=0|pts=67584|pts_time=1.532517|dts=67584|dts_time=1.532517|duration=22528|duration_time=0.510839|size=4092|pos=12332|flags=K__ frame|media_type=audio|stream_index=0|key_frame=1|pts=67584|pts_time=1.532517|pkt_dts=67584|pkt_dts_time=1.532517|best_effort_timestamp=67584|best_effort_timestamp_time=1.532517|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=12332|pkt_size=4092|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown -frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=12332|pkt_size=3720|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown -frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=12332|pkt_size=3348|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown -frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=12332|pkt_size=2976|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown -frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=12332|pkt_size=2604|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown -frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=12332|pkt_size=2232|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown -frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=12332|pkt_size=1860|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown -frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=12332|pkt_size=1488|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown -frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=12332|pkt_size=1116|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown -frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=12332|pkt_size=744|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown -frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=12332|pkt_size=372|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown +frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=12332|pkt_size=4092|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown +frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=12332|pkt_size=4092|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown +frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=12332|pkt_size=4092|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown +frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=12332|pkt_size=4092|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown +frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=12332|pkt_size=4092|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown +frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=12332|pkt_size=4092|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown +frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=12332|pkt_size=4092|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown +frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=12332|pkt_size=4092|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown +frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=12332|pkt_size=4092|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown +frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=12332|pkt_size=4092|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown packet|codec_type=audio|stream_index=0|pts=90112|pts_time=2.043356|dts=90112|dts_time=2.043356|duration=22528|duration_time=0.510839|size=4092|pos=16424|flags=K__ frame|media_type=audio|stream_index=0|key_frame=1|pts=90112|pts_time=2.043356|pkt_dts=90112|pkt_dts_time=2.043356|best_effort_timestamp=90112|best_effort_timestamp_time=2.043356|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=16424|pkt_size=4092|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown -frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=16424|pkt_size=3720|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown -frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=16424|pkt_size=3348|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown -frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=16424|pkt_size=2976|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown -frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=16424|pkt_size=2604|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown -frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=16424|pkt_size=2232|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown -frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=16424|pkt_size=1860|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown -frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=16424|pkt_size=1488|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown -frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=16424|pkt_size=1116|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown -frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=16424|pkt_size=744|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown -frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=16424|pkt_size=372|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown +frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=16424|pkt_size=4092|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown +frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=16424|pkt_size=4092|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown +frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=16424|pkt_size=4092|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown +frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=16424|pkt_size=4092|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown +frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=16424|pkt_size=4092|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown +frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=16424|pkt_size=4092|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown +frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=16424|pkt_size=4092|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown +frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=16424|pkt_size=4092|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown +frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=16424|pkt_size=4092|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown +frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=16424|pkt_size=4092|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown packet|codec_type=audio|stream_index=0|pts=112640|pts_time=2.554195|dts=112640|dts_time=2.554195|duration=22528|duration_time=0.510839|size=4092|pos=20516|flags=K__ frame|media_type=audio|stream_index=0|key_frame=1|pts=112640|pts_time=2.554195|pkt_dts=112640|pkt_dts_time=2.554195|best_effort_timestamp=112640|best_effort_timestamp_time=2.554195|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=20516|pkt_size=4092|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown -frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=20516|pkt_size=3720|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown -frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=20516|pkt_size=3348|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown -frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=20516|pkt_size=2976|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown -frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=20516|pkt_size=2604|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown -frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=20516|pkt_size=2232|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown -frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=20516|pkt_size=1860|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown -frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=20516|pkt_size=1488|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown -frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=20516|pkt_size=1116|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown -frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=20516|pkt_size=744|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown -frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=20516|pkt_size=372|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown +frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=20516|pkt_size=4092|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown +frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=20516|pkt_size=4092|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown +frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=20516|pkt_size=4092|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown +frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=20516|pkt_size=4092|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown +frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=20516|pkt_size=4092|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown +frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=20516|pkt_size=4092|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown +frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=20516|pkt_size=4092|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown +frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=20516|pkt_size=4092|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown +frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=20516|pkt_size=4092|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown +frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=20516|pkt_size=4092|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown packet|codec_type=audio|stream_index=0|pts=135168|pts_time=3.065034|dts=135168|dts_time=3.065034|duration=22528|duration_time=0.510839|size=4092|pos=24608|flags=K__ frame|media_type=audio|stream_index=0|key_frame=1|pts=135168|pts_time=3.065034|pkt_dts=135168|pkt_dts_time=3.065034|best_effort_timestamp=135168|best_effort_timestamp_time=3.065034|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=24608|pkt_size=4092|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown -frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=24608|pkt_size=3720|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown -frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=24608|pkt_size=3348|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown -frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=24608|pkt_size=2976|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown -frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=24608|pkt_size=2604|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown -frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=24608|pkt_size=2232|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown -frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=24608|pkt_size=1860|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown -frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=24608|pkt_size=1488|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown -frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=24608|pkt_size=1116|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown -frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=24608|pkt_size=744|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown -frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=24608|pkt_size=372|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown +frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=24608|pkt_size=4092|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown +frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=24608|pkt_size=4092|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown +frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=24608|pkt_size=4092|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown +frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=24608|pkt_size=4092|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown +frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=24608|pkt_size=4092|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown +frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=24608|pkt_size=4092|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown +frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=24608|pkt_size=4092|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown +frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=24608|pkt_size=4092|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown +frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=24608|pkt_size=4092|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown +frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=24608|pkt_size=4092|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown packet|codec_type=audio|stream_index=0|pts=157696|pts_time=3.575873|dts=157696|dts_time=3.575873|duration=22528|duration_time=0.510839|size=4092|pos=28700|flags=K__ frame|media_type=audio|stream_index=0|key_frame=1|pts=157696|pts_time=3.575873|pkt_dts=157696|pkt_dts_time=3.575873|best_effort_timestamp=157696|best_effort_timestamp_time=3.575873|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=28700|pkt_size=4092|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown -frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=28700|pkt_size=3720|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown -frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=28700|pkt_size=3348|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown -frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=28700|pkt_size=2976|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown -frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=28700|pkt_size=2604|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown -frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=28700|pkt_size=2232|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown -frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=28700|pkt_size=1860|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown -frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=28700|pkt_size=1488|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown -frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=28700|pkt_size=1116|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown -frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=28700|pkt_size=744|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown -frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=28700|pkt_size=372|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown +frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=28700|pkt_size=4092|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown +frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=28700|pkt_size=4092|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown +frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=28700|pkt_size=4092|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown +frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=28700|pkt_size=4092|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown +frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=28700|pkt_size=4092|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown +frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=28700|pkt_size=4092|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown +frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=28700|pkt_size=4092|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown +frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=28700|pkt_size=4092|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown +frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=28700|pkt_size=4092|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown +frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=28700|pkt_size=4092|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown packet|codec_type=audio|stream_index=0|pts=180224|pts_time=4.086712|dts=180224|dts_time=4.086712|duration=22528|duration_time=0.510839|size=4092|pos=32792|flags=K__ frame|media_type=audio|stream_index=0|key_frame=1|pts=180224|pts_time=4.086712|pkt_dts=180224|pkt_dts_time=4.086712|best_effort_timestamp=180224|best_effort_timestamp_time=4.086712|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=32792|pkt_size=4092|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown -frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=32792|pkt_size=3720|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown -frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=32792|pkt_size=3348|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown -frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=32792|pkt_size=2976|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown -frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=32792|pkt_size=2604|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown -frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=32792|pkt_size=2232|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown -frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=32792|pkt_size=1860|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown -frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=32792|pkt_size=1488|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown -frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=32792|pkt_size=1116|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown -frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=32792|pkt_size=744|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown -frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=32792|pkt_size=372|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown +frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=32792|pkt_size=4092|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown +frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=32792|pkt_size=4092|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown +frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=32792|pkt_size=4092|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown +frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=32792|pkt_size=4092|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown +frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=32792|pkt_size=4092|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown +frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=32792|pkt_size=4092|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown +frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=32792|pkt_size=4092|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown +frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=32792|pkt_size=4092|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown +frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=32792|pkt_size=4092|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown +frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=32792|pkt_size=4092|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown packet|codec_type=audio|stream_index=0|pts=202752|pts_time=4.597551|dts=202752|dts_time=4.597551|duration=22528|duration_time=0.510839|size=4092|pos=36884|flags=K__ frame|media_type=audio|stream_index=0|key_frame=1|pts=202752|pts_time=4.597551|pkt_dts=202752|pkt_dts_time=4.597551|best_effort_timestamp=202752|best_effort_timestamp_time=4.597551|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=36884|pkt_size=4092|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown -frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=36884|pkt_size=3720|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown -frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=36884|pkt_size=3348|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown -frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=36884|pkt_size=2976|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown -frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=36884|pkt_size=2604|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown -frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=36884|pkt_size=2232|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown -frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=36884|pkt_size=1860|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown -frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=36884|pkt_size=1488|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown -frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=36884|pkt_size=1116|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown -frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=36884|pkt_size=744|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown -frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=36884|pkt_size=372|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown +frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=36884|pkt_size=4092|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown +frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=36884|pkt_size=4092|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown +frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=36884|pkt_size=4092|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown +frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=36884|pkt_size=4092|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown +frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=36884|pkt_size=4092|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown +frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=36884|pkt_size=4092|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown +frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=36884|pkt_size=4092|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown +frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=36884|pkt_size=4092|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown +frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=36884|pkt_size=4092|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown +frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=36884|pkt_size=4092|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown packet|codec_type=audio|stream_index=0|pts=225280|pts_time=5.108390|dts=225280|dts_time=5.108390|duration=22528|duration_time=0.510839|size=4092|pos=40976|flags=K__ frame|media_type=audio|stream_index=0|key_frame=1|pts=225280|pts_time=5.108390|pkt_dts=225280|pkt_dts_time=5.108390|best_effort_timestamp=225280|best_effort_timestamp_time=5.108390|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=40976|pkt_size=4092|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown -frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=40976|pkt_size=3720|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown -frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=40976|pkt_size=3348|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown -frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=40976|pkt_size=2976|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown -frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=40976|pkt_size=2604|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown -frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=40976|pkt_size=2232|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown -frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=40976|pkt_size=1860|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown -frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=40976|pkt_size=1488|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown -frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=40976|pkt_size=1116|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown -frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=40976|pkt_size=744|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown -frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=40976|pkt_size=372|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown +frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=40976|pkt_size=4092|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown +frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=40976|pkt_size=4092|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown +frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=40976|pkt_size=4092|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown +frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=40976|pkt_size=4092|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown +frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=40976|pkt_size=4092|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown +frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=40976|pkt_size=4092|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown +frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=40976|pkt_size=4092|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown +frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=40976|pkt_size=4092|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown +frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=40976|pkt_size=4092|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown +frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=40976|pkt_size=4092|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown packet|codec_type=audio|stream_index=0|pts=247808|pts_time=5.619229|dts=247808|dts_time=5.619229|duration=22528|duration_time=0.510839|size=4092|pos=45068|flags=K__ frame|media_type=audio|stream_index=0|key_frame=1|pts=247808|pts_time=5.619229|pkt_dts=247808|pkt_dts_time=5.619229|best_effort_timestamp=247808|best_effort_timestamp_time=5.619229|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=45068|pkt_size=4092|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown -frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=45068|pkt_size=3720|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown -frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=45068|pkt_size=3348|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown -frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=45068|pkt_size=2976|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown -frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=45068|pkt_size=2604|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown -frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=45068|pkt_size=2232|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown -frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=45068|pkt_size=1860|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown -frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=45068|pkt_size=1488|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown -frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=45068|pkt_size=1116|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown -frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=45068|pkt_size=744|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown -frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=45068|pkt_size=372|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown +frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=45068|pkt_size=4092|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown +frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=45068|pkt_size=4092|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown +frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=45068|pkt_size=4092|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown +frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=45068|pkt_size=4092|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown +frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=45068|pkt_size=4092|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown +frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=45068|pkt_size=4092|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown +frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=45068|pkt_size=4092|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown +frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=45068|pkt_size=4092|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown +frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=45068|pkt_size=4092|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown +frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=45068|pkt_size=4092|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown packet|codec_type=audio|stream_index=0|pts=270336|pts_time=6.130068|dts=270336|dts_time=6.130068|duration=22528|duration_time=0.510839|size=4092|pos=49160|flags=K__ frame|media_type=audio|stream_index=0|key_frame=1|pts=270336|pts_time=6.130068|pkt_dts=270336|pkt_dts_time=6.130068|best_effort_timestamp=270336|best_effort_timestamp_time=6.130068|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=49160|pkt_size=4092|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown -frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=49160|pkt_size=3720|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown -frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=49160|pkt_size=3348|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown -frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=49160|pkt_size=2976|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown -frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=49160|pkt_size=2604|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown -frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=49160|pkt_size=2232|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown -frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=49160|pkt_size=1860|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown -frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=49160|pkt_size=1488|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown -frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=49160|pkt_size=1116|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown -frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=49160|pkt_size=744|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown -frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=49160|pkt_size=372|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown +frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=49160|pkt_size=4092|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown +frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=49160|pkt_size=4092|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown +frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=49160|pkt_size=4092|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown +frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=49160|pkt_size=4092|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown +frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=49160|pkt_size=4092|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown +frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=49160|pkt_size=4092|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown +frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=49160|pkt_size=4092|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown +frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=49160|pkt_size=4092|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown +frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=49160|pkt_size=4092|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown +frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=49160|pkt_size=4092|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown packet|codec_type=audio|stream_index=0|pts=292864|pts_time=6.640907|dts=292864|dts_time=6.640907|duration=22528|duration_time=0.510839|size=4092|pos=53252|flags=K__ frame|media_type=audio|stream_index=0|key_frame=1|pts=292864|pts_time=6.640907|pkt_dts=292864|pkt_dts_time=6.640907|best_effort_timestamp=292864|best_effort_timestamp_time=6.640907|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=53252|pkt_size=4092|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown -frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=53252|pkt_size=3720|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown -frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=53252|pkt_size=3348|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown -frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=53252|pkt_size=2976|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown -frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=53252|pkt_size=2604|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown -frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=53252|pkt_size=2232|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown -frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=53252|pkt_size=1860|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown -frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=53252|pkt_size=1488|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown -frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=53252|pkt_size=1116|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown -frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=53252|pkt_size=744|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown -frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=53252|pkt_size=372|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown +frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=53252|pkt_size=4092|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown +frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=53252|pkt_size=4092|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown +frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=53252|pkt_size=4092|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown +frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=53252|pkt_size=4092|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown +frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=53252|pkt_size=4092|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown +frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=53252|pkt_size=4092|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown +frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=53252|pkt_size=4092|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown +frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=53252|pkt_size=4092|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown +frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=53252|pkt_size=4092|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown +frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=53252|pkt_size=4092|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown packet|codec_type=audio|stream_index=0|pts=315392|pts_time=7.151746|dts=315392|dts_time=7.151746|duration=22528|duration_time=0.510839|size=4092|pos=57344|flags=K__ frame|media_type=audio|stream_index=0|key_frame=1|pts=315392|pts_time=7.151746|pkt_dts=315392|pkt_dts_time=7.151746|best_effort_timestamp=315392|best_effort_timestamp_time=7.151746|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=57344|pkt_size=4092|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown -frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=57344|pkt_size=3720|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown -frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=57344|pkt_size=3348|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown -frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=57344|pkt_size=2976|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown -frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=57344|pkt_size=2604|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown -frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=57344|pkt_size=2232|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown -frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=57344|pkt_size=1860|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown -frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=57344|pkt_size=1488|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown -frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=57344|pkt_size=1116|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown -frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=57344|pkt_size=744|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown -frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=57344|pkt_size=372|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown +frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=57344|pkt_size=4092|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown +frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=57344|pkt_size=4092|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown +frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=57344|pkt_size=4092|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown +frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=57344|pkt_size=4092|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown +frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=57344|pkt_size=4092|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown +frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=57344|pkt_size=4092|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown +frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=57344|pkt_size=4092|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown +frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=57344|pkt_size=4092|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown +frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=57344|pkt_size=4092|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown +frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=57344|pkt_size=4092|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown packet|codec_type=audio|stream_index=0|pts=337920|pts_time=7.662585|dts=337920|dts_time=7.662585|duration=22528|duration_time=0.510839|size=4092|pos=61436|flags=K__ frame|media_type=audio|stream_index=0|key_frame=1|pts=337920|pts_time=7.662585|pkt_dts=337920|pkt_dts_time=7.662585|best_effort_timestamp=337920|best_effort_timestamp_time=7.662585|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=61436|pkt_size=4092|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown -frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=61436|pkt_size=3720|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown -frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=61436|pkt_size=3348|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown -frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=61436|pkt_size=2976|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown -frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=61436|pkt_size=2604|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown -frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=61436|pkt_size=2232|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown -frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=61436|pkt_size=1860|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown -frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=61436|pkt_size=1488|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown -frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=61436|pkt_size=1116|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown -frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=61436|pkt_size=744|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown -frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=61436|pkt_size=372|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown +frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=61436|pkt_size=4092|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown +frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=61436|pkt_size=4092|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown +frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=61436|pkt_size=4092|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown +frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=61436|pkt_size=4092|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown +frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=61436|pkt_size=4092|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown +frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=61436|pkt_size=4092|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown +frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=61436|pkt_size=4092|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown +frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=61436|pkt_size=4092|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown +frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=61436|pkt_size=4092|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown +frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|duration=22528|duration_time=0.510839|pkt_pos=61436|pkt_size=4092|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown packet|codec_type=audio|stream_index=0|pts=360448|pts_time=8.173424|dts=360448|dts_time=8.173424|duration=44|duration_time=0.000998|size=8|pos=65528|flags=K_C frame|media_type=audio|stream_index=0|key_frame=1|pts=N/A|pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=44|pkt_duration_time=0.000998|duration=44|duration_time=0.000998|pkt_pos=65528|pkt_size=8|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown From 9141c0cfd81ec976215563d4819c3501951e5dfd Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Fri, 10 Mar 2023 08:48:13 +0100 Subject: [PATCH 0450/2172] fftools/ffplay: drop an unused function argument --- fftools/ffplay.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/fftools/ffplay.c b/fftools/ffplay.c index d6479aef5f7..f09ff59ccc1 100644 --- a/fftools/ffplay.c +++ b/fftools/ffplay.c @@ -1553,7 +1553,8 @@ static double vp_duration(VideoState *is, Frame *vp, Frame *nextvp) { } } -static void update_video_pts(VideoState *is, double pts, int64_t pos, int serial) { +static void update_video_pts(VideoState *is, double pts, int serial) +{ /* update current video pts */ set_clock(&is->vidclk, pts, serial); sync_clock_to_slave(&is->extclk, &is->vidclk); @@ -1618,7 +1619,7 @@ static void video_refresh(void *opaque, double *remaining_time) SDL_LockMutex(is->pictq.mutex); if (!isnan(vp->pts)) - update_video_pts(is, vp->pts, vp->pos, vp->serial); + update_video_pts(is, vp->pts, vp->serial); SDL_UnlockMutex(is->pictq.mutex); if (frame_queue_nb_remaining(&is->pictq) > 1) { From c29e5ab5c1d0fc161018d02b0308104a88e110ad Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Fri, 10 Mar 2023 09:39:06 +0100 Subject: [PATCH 0451/2172] fftools/ffplay: depend on avfilter Making lavfi optional adds a lot of complexity for very questionable gain. --- configure | 2 +- fftools/ffplay.c | 80 ++++-------------------------------------------- 2 files changed, 7 insertions(+), 75 deletions(-) diff --git a/configure b/configure index 0370e25577e..8980cec7ee8 100755 --- a/configure +++ b/configure @@ -3836,7 +3836,7 @@ ffmpeg_select="aformat_filter anull_filter atrim_filter format_filter hflip_filter null_filter transpose_filter trim_filter vflip_filter" ffmpeg_suggest="ole32 psapi shell32" -ffplay_deps="avcodec avformat swscale swresample sdl2" +ffplay_deps="avcodec avformat avfilter swscale swresample sdl2" ffplay_select="rdft crop_filter transpose_filter hflip_filter vflip_filter rotate_filter" ffplay_suggest="shell32" ffprobe_deps="avcodec avformat" diff --git a/fftools/ffplay.c b/fftools/ffplay.c index f09ff59ccc1..0a96511475a 100644 --- a/fftools/ffplay.c +++ b/fftools/ffplay.c @@ -50,11 +50,9 @@ #include "libavcodec/avfft.h" #include "libswresample/swresample.h" -#if CONFIG_AVFILTER -# include "libavfilter/avfilter.h" -# include "libavfilter/buffersink.h" -# include "libavfilter/buffersrc.h" -#endif +#include "libavfilter/avfilter.h" +#include "libavfilter/buffersink.h" +#include "libavfilter/buffersrc.h" #include #include @@ -109,8 +107,6 @@ const int program_birth_year = 2003; #define USE_ONEPASS_SUBTITLE_RENDER 1 -static unsigned sws_flags = SWS_BICUBIC; - typedef struct MyAVPacketList { AVPacket *pkt; int serial; @@ -250,9 +246,7 @@ typedef struct VideoState { int audio_volume; int muted; struct AudioParams audio_src; -#if CONFIG_AVFILTER struct AudioParams audio_filter_src; -#endif struct AudioParams audio_tgt; struct SwrContext *swr_ctx; int frame_drops_early; @@ -284,7 +278,6 @@ typedef struct VideoState { AVStream *video_st; PacketQueue videoq; double max_frame_duration; // maximum duration of a frame - above this, we consider the jump a timestamp discontinuity - struct SwsContext *img_convert_ctx; struct SwsContext *sub_convert_ctx; int eof; @@ -292,14 +285,12 @@ typedef struct VideoState { int width, height, xleft, ytop; int step; -#if CONFIG_AVFILTER int vfilter_idx; AVFilterContext *in_video_filter; // the first filter in the video chain AVFilterContext *out_video_filter; // the last filter in the video chain AVFilterContext *in_audio_filter; // the first filter in the audio chain AVFilterContext *out_audio_filter; // the last filter in the audio chain AVFilterGraph *agraph; // audio filter graph -#endif int last_video_stream, last_audio_stream, last_subtitle_stream; @@ -347,11 +338,9 @@ static const char *video_codec_name; double rdftspeed = 0.02; static int64_t cursor_last_shown; static int cursor_hidden = 0; -#if CONFIG_AVFILTER static const char **vfilters_list = NULL; static int nb_vfilters = 0; static char *afilters = NULL; -#endif static int autorotate = 1; static int find_stream_info = 1; static int filter_nbthreads = 0; @@ -393,14 +382,12 @@ static const struct TextureFormatEntry { { AV_PIX_FMT_NONE, SDL_PIXELFORMAT_UNKNOWN }, }; -#if CONFIG_AVFILTER static int opt_add_vfilter(void *optctx, const char *opt, const char *arg) { GROW_ARRAY(vfilters_list, nb_vfilters); vfilters_list[nb_vfilters - 1] = arg; return 0; } -#endif static inline int cmp_audio_fmts(enum AVSampleFormat fmt1, int64_t channel_count1, @@ -891,7 +878,8 @@ static void get_sdl_pix_fmt_and_blendmode(int format, Uint32 *sdl_pix_fmt, SDL_B } } -static int upload_texture(SDL_Texture **tex, AVFrame *frame, struct SwsContext **img_convert_ctx) { +static int upload_texture(SDL_Texture **tex, AVFrame *frame) +{ int ret = 0; Uint32 sdl_pix_fmt; SDL_BlendMode sdl_blendmode; @@ -899,24 +887,6 @@ static int upload_texture(SDL_Texture **tex, AVFrame *frame, struct SwsContext * if (realloc_texture(tex, sdl_pix_fmt == SDL_PIXELFORMAT_UNKNOWN ? SDL_PIXELFORMAT_ARGB8888 : sdl_pix_fmt, frame->width, frame->height, sdl_blendmode, 0) < 0) return -1; switch (sdl_pix_fmt) { - case SDL_PIXELFORMAT_UNKNOWN: - /* This should only happen if we are not using avfilter... */ - *img_convert_ctx = sws_getCachedContext(*img_convert_ctx, - frame->width, frame->height, frame->format, frame->width, frame->height, - AV_PIX_FMT_BGRA, sws_flags, NULL, NULL, NULL); - if (*img_convert_ctx != NULL) { - uint8_t *pixels[4]; - int pitch[4]; - if (!SDL_LockTexture(*tex, NULL, (void **)pixels, pitch)) { - sws_scale(*img_convert_ctx, (const uint8_t * const *)frame->data, frame->linesize, - 0, frame->height, pixels, pitch); - SDL_UnlockTexture(*tex); - } - } else { - av_log(NULL, AV_LOG_FATAL, "Cannot initialize the conversion context\n"); - ret = -1; - } - break; case SDL_PIXELFORMAT_IYUV: if (frame->linesize[0] > 0 && frame->linesize[1] > 0 && frame->linesize[2] > 0) { ret = SDL_UpdateYUVTexture(*tex, NULL, frame->data[0], frame->linesize[0], @@ -1014,7 +984,7 @@ static void video_image_display(VideoState *is) set_sdl_yuv_conversion_mode(vp->frame); if (!vp->uploaded) { - if (upload_texture(&is->vid_texture, vp->frame, &is->img_convert_ctx) < 0) { + if (upload_texture(&is->vid_texture, vp->frame) < 0) { set_sdl_yuv_conversion_mode(NULL); return; } @@ -1272,7 +1242,6 @@ static void stream_close(VideoState *is) frame_queue_destory(&is->sampq); frame_queue_destory(&is->subpq); SDL_DestroyCond(is->continue_read_thread); - sws_freeContext(is->img_convert_ctx); sws_freeContext(is->sub_convert_ctx); av_free(is->filename); if (is->vis_texture) @@ -1294,9 +1263,7 @@ static void do_exit(VideoState *is) if (window) SDL_DestroyWindow(window); uninit_opts(); -#if CONFIG_AVFILTER av_freep(&vfilters_list); -#endif avformat_network_deinit(); if (show_status) printf("\n"); @@ -1794,7 +1761,6 @@ static int get_video_frame(VideoState *is, AVFrame *frame) return got_picture; } -#if CONFIG_AVFILTER static int configure_filtergraph(AVFilterGraph *graph, const char *filtergraph, AVFilterContext *source_ctx, AVFilterContext *sink_ctx) { @@ -2022,17 +1988,14 @@ static int configure_audio_filters(VideoState *is, const char *afilters, int for return ret; } -#endif /* CONFIG_AVFILTER */ static int audio_thread(void *arg) { VideoState *is = arg; AVFrame *frame = av_frame_alloc(); Frame *af; -#if CONFIG_AVFILTER int last_serial = -1; int reconfigure; -#endif int got_frame = 0; AVRational tb; int ret = 0; @@ -2047,7 +2010,6 @@ static int audio_thread(void *arg) if (got_frame) { tb = (AVRational){1, frame->sample_rate}; -#if CONFIG_AVFILTER reconfigure = cmp_audio_fmts(is->audio_filter_src.fmt, is->audio_filter_src.ch_layout.nb_channels, frame->format, frame->ch_layout.nb_channels) || @@ -2080,7 +2042,6 @@ static int audio_thread(void *arg) while ((ret = av_buffersink_get_frame_flags(is->out_audio_filter, frame, 0)) >= 0) { tb = av_buffersink_get_time_base(is->out_audio_filter); -#endif if (!(af = frame_queue_peek_writable(&is->sampq))) goto the_end; @@ -2092,19 +2053,15 @@ static int audio_thread(void *arg) av_frame_move_ref(af->frame, frame); frame_queue_push(&is->sampq); -#if CONFIG_AVFILTER if (is->audioq.serial != is->auddec.pkt_serial) break; } if (ret == AVERROR_EOF) is->auddec.finished = is->auddec.pkt_serial; -#endif } } while (ret >= 0 || ret == AVERROR(EAGAIN) || ret == AVERROR_EOF); the_end: -#if CONFIG_AVFILTER avfilter_graph_free(&is->agraph); -#endif av_frame_free(&frame); return ret; } @@ -2130,7 +2087,6 @@ static int video_thread(void *arg) AVRational tb = is->video_st->time_base; AVRational frame_rate = av_guess_frame_rate(is->ic, is->video_st, NULL); -#if CONFIG_AVFILTER AVFilterGraph *graph = NULL; AVFilterContext *filt_out = NULL, *filt_in = NULL; int last_w = 0; @@ -2138,7 +2094,6 @@ static int video_thread(void *arg) enum AVPixelFormat last_format = -2; int last_serial = -1; int last_vfilter_idx = 0; -#endif if (!frame) return AVERROR(ENOMEM); @@ -2150,7 +2105,6 @@ static int video_thread(void *arg) if (!ret) continue; -#if CONFIG_AVFILTER if ( last_w != frame->width || last_h != frame->height || last_format != frame->format @@ -2205,24 +2159,19 @@ static int video_thread(void *arg) if (fabs(is->frame_last_filter_delay) > AV_NOSYNC_THRESHOLD / 10.0) is->frame_last_filter_delay = 0; tb = av_buffersink_get_time_base(filt_out); -#endif duration = (frame_rate.num && frame_rate.den ? av_q2d((AVRational){frame_rate.den, frame_rate.num}) : 0); pts = (frame->pts == AV_NOPTS_VALUE) ? NAN : frame->pts * av_q2d(tb); ret = queue_picture(is, frame, pts, duration, frame->pkt_pos, is->viddec.pkt_serial); av_frame_unref(frame); -#if CONFIG_AVFILTER if (is->videoq.serial != is->viddec.pkt_serial) break; } -#endif if (ret < 0) goto the_end; } the_end: -#if CONFIG_AVFILTER avfilter_graph_free(&graph); -#endif av_frame_free(&frame); return 0; } @@ -2631,7 +2580,6 @@ static int stream_component_open(VideoState *is, int stream_index) ic->streams[stream_index]->discard = AVDISCARD_DEFAULT; switch (avctx->codec_type) { case AVMEDIA_TYPE_AUDIO: -#if CONFIG_AVFILTER { AVFilterContext *sink; @@ -2648,12 +2596,6 @@ static int stream_component_open(VideoState *is, int stream_index) if (ret < 0) goto fail; } -#else - sample_rate = avctx->sample_rate; - ret = av_channel_layout_copy(&ch_layout, &avctx->ch_layout); - if (ret < 0) - goto fail; -#endif /* prepare audio output */ if ((ret = audio_open(is, &ch_layout, sample_rate, &is->audio_tgt)) < 0) @@ -3327,7 +3269,6 @@ static void event_loop(VideoState *cur_stream) stream_cycle_channel(cur_stream, AVMEDIA_TYPE_SUBTITLE); break; case SDLK_w: -#if CONFIG_AVFILTER if (cur_stream->show_mode == SHOW_MODE_VIDEO && cur_stream->vfilter_idx < nb_vfilters - 1) { if (++cur_stream->vfilter_idx >= nb_vfilters) cur_stream->vfilter_idx = 0; @@ -3335,9 +3276,6 @@ static void event_loop(VideoState *cur_stream) cur_stream->vfilter_idx = 0; toggle_audio_display(cur_stream); } -#else - toggle_audio_display(cur_stream); -#endif break; case SDLK_PAGEUP: if (cur_stream->ic->nb_chapters <= 1) { @@ -3601,10 +3539,8 @@ static const OptionDef options[] = { { "window_title", OPT_STRING | HAS_ARG, { &window_title }, "set window title", "window title" }, { "left", OPT_INT | HAS_ARG | OPT_EXPERT, { &screen_left }, "set the x position for the left of the window", "x pos" }, { "top", OPT_INT | HAS_ARG | OPT_EXPERT, { &screen_top }, "set the y position for the top of the window", "y pos" }, -#if CONFIG_AVFILTER { "vf", OPT_EXPERT | HAS_ARG, { .func_arg = opt_add_vfilter }, "set video filters", "filter_graph" }, { "af", OPT_STRING | HAS_ARG, { &afilters }, "set audio filters", "filter_graph" }, -#endif { "rdftspeed", OPT_INT | HAS_ARG| OPT_AUDIO | OPT_EXPERT, { &rdftspeed }, "rdft speed", "msecs" }, { "showmode", HAS_ARG, { .func_arg = opt_show_mode}, "select show mode (0 = video, 1 = waves, 2 = RDFT)", "mode" }, { "i", OPT_BOOL, { &dummy}, "read specified file", "input_file"}, @@ -3635,11 +3571,7 @@ void show_help_default(const char *opt, const char *arg) printf("\n"); show_help_children(avcodec_get_class(), AV_OPT_FLAG_DECODING_PARAM); show_help_children(avformat_get_class(), AV_OPT_FLAG_DECODING_PARAM); -#if !CONFIG_AVFILTER - show_help_children(sws_get_class(), AV_OPT_FLAG_ENCODING_PARAM); -#else show_help_children(avfilter_get_class(), AV_OPT_FLAG_FILTERING_PARAM); -#endif printf("\nWhile playing:\n" "q, ESC quit\n" "f toggle full screen\n" From 2fb3ee17877415fde76a7582797349484844b74d Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Thu, 9 Mar 2023 16:59:12 +0100 Subject: [PATCH 0452/2172] fftools/ffplay: stop using AVFrame.pkt_pos This field is ad-hoc and will be deprecated. Use the recently-added AV_CODEC_FLAG_COPY_OPAQUE to pass arbitrary user data from packets to frames. --- fftools/ffplay.c | 26 ++++++++++++++++++++++++-- 1 file changed, 24 insertions(+), 2 deletions(-) diff --git a/fftools/ffplay.c b/fftools/ffplay.c index 0a96511475a..15fd6449740 100644 --- a/fftools/ffplay.c +++ b/fftools/ffplay.c @@ -146,6 +146,10 @@ typedef struct Clock { int *queue_serial; /* pointer to the current packet queue serial, used for obsolete clock detection */ } Clock; +typedef struct FrameData { + int64_t pkt_pos; +} FrameData; + /* Common struct for handling all types of decoded data and allocated render buffers. */ typedef struct Frame { AVFrame *frame; @@ -640,6 +644,16 @@ static int decoder_decode_frame(Decoder *d, AVFrame *frame, AVSubtitle *sub) { } av_packet_unref(d->pkt); } else { + if (d->pkt->buf && !d->pkt->opaque_ref) { + FrameData *fd; + + d->pkt->opaque_ref = av_buffer_allocz(sizeof(*fd)); + if (!d->pkt->opaque_ref) + return AVERROR(ENOMEM); + fd = (FrameData*)d->pkt->opaque_ref->data; + fd->pkt_pos = d->pkt->pos; + } + if (avcodec_send_packet(d->avctx, d->pkt) == AVERROR(EAGAIN)) { av_log(d->avctx, AV_LOG_ERROR, "Receive_frame and send_packet both returned EAGAIN, which is an API violation.\n"); d->packet_pending = 1; @@ -2041,12 +2055,13 @@ static int audio_thread(void *arg) goto the_end; while ((ret = av_buffersink_get_frame_flags(is->out_audio_filter, frame, 0)) >= 0) { + FrameData *fd = frame->opaque_ref ? (FrameData*)frame->opaque_ref->data : NULL; tb = av_buffersink_get_time_base(is->out_audio_filter); if (!(af = frame_queue_peek_writable(&is->sampq))) goto the_end; af->pts = (frame->pts == AV_NOPTS_VALUE) ? NAN : frame->pts * av_q2d(tb); - af->pos = frame->pkt_pos; + af->pos = fd ? fd->pkt_pos : -1; af->serial = is->auddec.pkt_serial; af->duration = av_q2d((AVRational){frame->nb_samples, frame->sample_rate}); @@ -2145,6 +2160,8 @@ static int video_thread(void *arg) goto the_end; while (ret >= 0) { + FrameData *fd; + is->frame_last_returned_time = av_gettime_relative() / 1000000.0; ret = av_buffersink_get_frame_flags(filt_out, frame, 0); @@ -2155,13 +2172,15 @@ static int video_thread(void *arg) break; } + fd = frame->opaque_ref ? (FrameData*)frame->opaque_ref->data : NULL; + is->frame_last_filter_delay = av_gettime_relative() / 1000000.0 - is->frame_last_returned_time; if (fabs(is->frame_last_filter_delay) > AV_NOSYNC_THRESHOLD / 10.0) is->frame_last_filter_delay = 0; tb = av_buffersink_get_time_base(filt_out); duration = (frame_rate.num && frame_rate.den ? av_q2d((AVRational){frame_rate.den, frame_rate.num}) : 0); pts = (frame->pts == AV_NOPTS_VALUE) ? NAN : frame->pts * av_q2d(tb); - ret = queue_picture(is, frame, pts, duration, frame->pkt_pos, is->viddec.pkt_serial); + ret = queue_picture(is, frame, pts, duration, fd ? fd->pkt_pos : -1, is->viddec.pkt_serial); av_frame_unref(frame); if (is->videoq.serial != is->viddec.pkt_serial) break; @@ -2567,6 +2586,9 @@ static int stream_component_open(VideoState *is, int stream_index) av_dict_set(&opts, "threads", "auto", 0); if (stream_lowres) av_dict_set_int(&opts, "lowres", stream_lowres, 0); + + av_dict_set(&opts, "flags", "+copy_opaque", AV_DICT_MULTIKEY); + if ((ret = avcodec_open2(avctx, codec, &opts)) < 0) { goto fail; } From 27f8c9b27bce42a4a6a4c64e03fab769579c8683 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Fri, 10 Mar 2023 10:48:34 +0100 Subject: [PATCH 0453/2172] lavu/frame: deprecate AVFrame.pkt_{pos,size} These fields are supposed to store information about the packet the frame was decoded from, specifically the byte offset it was stored at and its size. However, - the fields are highly ad-hoc - there is no strong reason why specifically those (and not any other) packet properties should have a dedicated field in AVFrame; unlike e.g. the timestamps, there is no fundamental link between coded packet offset/size and decoded frames - they only make sense for frames produced by decoding demuxed packets, and even then it is not always the case that the encoded data was stored in the file as a contiguous sequence of bytes (in order for pos to be well-defined) - pkt_pos was added without much explanation, apparently to allow passthrough of this information through lavfi in order to handle byte seeking in ffplay. That is now implemented using arbitrary user data passthrough in AVFrame.opaque_ref. - several filters use pkt_pos as a variable available to user-supplied expressions, but there seems to be no established motivation for using them. - pkt_size was added for use in ffprobe, but that too is now handled without using this field. Additonally, the values of this field produced by libavcodec are flawed, as described in the previous ffprobe conversion commit. In summary - these fields are ill-defined and insufficiently motivated, so deprecate them. --- doc/filters.texi | 35 ++++++++++++------------ libavcodec/av1dec.c | 4 +++ libavcodec/crystalhd.c | 6 ++++- libavcodec/cuviddec.c | 6 ++++- libavcodec/decode.c | 18 ++++++++++++- libavcodec/libuavs3d.c | 8 ++++++ libavdevice/lavfi.c | 8 ++++++ libavfilter/af_ashowinfo.c | 3 +-- libavfilter/af_volume.c | 16 ++++++++--- libavfilter/asrc_flite.c | 4 +++ libavfilter/avfilter.c | 8 ++++++ libavfilter/f_select.c | 6 +++++ libavfilter/f_sendcmd.c | 8 ++++++ libavfilter/setpts.c | 16 +++++++---- libavfilter/vf_crop.c | 14 ++++++++-- libavfilter/vf_drawtext.c | 14 +++++++++- libavfilter/vf_eq.c | 10 +++++-- libavfilter/vf_eq.h | 4 +++ libavfilter/vf_overlay.c | 18 ++++++++++--- libavfilter/vf_overlay.h | 2 ++ libavfilter/vf_overlay_cuda.c | 24 ++++++++++++----- libavfilter/vf_scale.c | 30 +++++++++++++++++++-- libavfilter/vf_scale_npp.c | 51 +++++++++++++++++++++++++++++------ libavfilter/vf_showinfo.c | 3 +-- libavfilter/vf_swaprect.c | 16 +++++++++-- libavutil/frame.c | 8 ++++++ libavutil/frame.h | 10 +++++++ libavutil/version.h | 1 + 28 files changed, 291 insertions(+), 60 deletions(-) diff --git a/doc/filters.texi b/doc/filters.texi index d634924bfb0..dbe3f5fd9f5 100644 --- a/doc/filters.texi +++ b/doc/filters.texi @@ -299,7 +299,8 @@ timestamp expressed in seconds, NAN if the input timestamp is unknown sequential number of the input frame, starting from 0 @item pos -the position in the file of the input frame, NAN if unknown +the position in the file of the input frame, NAN if unknown; deprecated, do +not use @item w @item h @@ -3005,10 +3006,6 @@ depends on the filter input pad, and is usually 1/@var{sample_rate}. @item pts_time The presentation timestamp of the input frame in seconds. -@item pos -position of the frame in the input stream, -1 if this information in -unavailable and/or meaningless (for example in case of synthetic audio) - @item fmt The sample format. @@ -7306,7 +7303,7 @@ number of samples consumed by the filter @item nb_samples number of samples in the current frame @item pos -original frame position in the file +original frame position in the file; deprecated, do not use @item pts frame PTS @item sample_rate @@ -10428,7 +10425,8 @@ pixel format "yuv422p" @var{hsub} is 2 and @var{vsub} is 1. The number of the input frame, starting from 0. @item pos -the position in the file of the input frame, NAN if unknown +the position in the file of the input frame, NAN if unknown; deprecated, +do not use @item t The timestamp expressed in seconds. It's NAN if the input timestamp is unknown. @@ -12772,7 +12770,7 @@ frame count of the input frame starting from 0 @item pos byte position of the corresponding packet in the input file, NAN if -unspecified +unspecified; deprecated, do not use @item r frame rate of the input video, NAN if the input frame rate is unknown @@ -18148,7 +18146,8 @@ format. For example for the pixel format "yuv422p" @var{hsub} is 2 and the number of input frame, starting from 0 @item pos -the position in the file of the input frame, NAN if unknown +the position in the file of the input frame, NAN if unknown; deprecated, +do not use @item t The timestamp, expressed in seconds. It's NAN if the input timestamp is unknown. @@ -18157,7 +18156,7 @@ The timestamp, expressed in seconds. It's NAN if the input timestamp is unknown. This filter also supports the @ref{framesync} options. -Note that the @var{n}, @var{pos}, @var{t} variables are available only +Note that the @var{n}, @var{t} variables are available only when evaluation is done @emph{per frame}, and will evaluate to NAN when @option{eval} is set to @samp{init}. @@ -18312,6 +18311,7 @@ The ordinal index of the main input frame, starting from 0. @item pos The byte offset position in the file of the main input frame, NAN if unknown. +Deprecated, do not use. @item t The timestamp of the main input frame, expressed in seconds, NAN if unknown. @@ -20196,6 +20196,7 @@ seconds. Only available with @code{eval=frame}. 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}. +Deprecated, do not use. @end table @subsection Examples @@ -20528,6 +20529,7 @@ seconds. Only available with @code{eval=frame}. 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}. +Deprecated, do not use. @end table @section scale2ref @@ -21151,10 +21153,6 @@ time base units. The time base unit depends on the filter input pad. The Presentation TimeStamp of the input frame, expressed as a number of seconds. -@item pos -The position of the frame in the input stream, or -1 if this information is -unavailable and/or meaningless (for example in case of synthetic video). - @item fmt The pixel format name. @@ -22235,7 +22233,8 @@ The number of the input frame, starting from 0. The timestamp expressed in seconds. It's NAN if the input timestamp is unknown. @item pos -the position in the file of the input frame, NAN if unknown +the position in the file of the input frame, NAN if unknown; deprecated, +do not use @end table @subsection Commands @@ -28910,7 +28909,7 @@ This is 1 if the filtered frame is a key-frame, 0 otherwise. @item pos the position in the file of the filtered frame, -1 if the information -is not available (e.g. for synthetic video) +is not available (e.g. for synthetic video); deprecated, do not use @item scene @emph{(video only)} value between 0 and 1 to indicate a new scene; a low value reflects a low @@ -29100,7 +29099,7 @@ constants: @table @option @item POS Original position in the file of the frame, or undefined if undefined -for the current frame. +for the current frame. Deprecated, do not use. @item PTS The presentation timestamp in input. @@ -29248,7 +29247,7 @@ the time in seconds of the current frame @item POS original position in the file of the frame, or undefined if undefined -for the current frame +for the current frame; deprecated, do not use @item PREV_INPTS The previous input PTS. diff --git a/libavcodec/av1dec.c b/libavcodec/av1dec.c index 4d3b559b967..5c14756a57b 100644 --- a/libavcodec/av1dec.c +++ b/libavcodec/av1dec.c @@ -1074,7 +1074,11 @@ static int set_output_frame(AVCodecContext *avctx, AVFrame *frame, frame->pts = pkt->pts; frame->pkt_dts = pkt->dts; +#if FF_API_FRAME_PKT +FF_DISABLE_DEPRECATION_WARNINGS frame->pkt_size = pkt->size; +FF_ENABLE_DEPRECATION_WARNINGS +#endif *got_frame = 1; diff --git a/libavcodec/crystalhd.c b/libavcodec/crystalhd.c index 688cdffbcb5..a48d60f123d 100644 --- a/libavcodec/crystalhd.c +++ b/libavcodec/crystalhd.c @@ -549,9 +549,13 @@ static inline CopyRet copy_frame(AVCodecContext *avctx, frame->pts = pkt_pts; - frame->pkt_pos = -1; frame->duration = 0; +#if FF_API_FRAME_PKT +FF_DISABLE_DEPRECATION_WARNINGS + frame->pkt_pos = -1; frame->pkt_size = -1; +FF_ENABLE_DEPRECATION_WARNINGS +#endif if (!priv->need_second_field) { *got_frame = 1; diff --git a/libavcodec/cuviddec.c b/libavcodec/cuviddec.c index 4ba7918b644..76e70aa6483 100644 --- a/libavcodec/cuviddec.c +++ b/libavcodec/cuviddec.c @@ -623,9 +623,13 @@ static int cuvid_output_frame(AVCodecContext *avctx, AVFrame *frame) /* CUVIDs opaque reordering breaks the internal pkt logic. * So set pkt_pts and clear all the other pkt_ fields. */ - frame->pkt_pos = -1; frame->duration = 0; +#if FF_API_FRAME_PKT +FF_DISABLE_DEPRECATION_WARNINGS + frame->pkt_pos = -1; frame->pkt_size = -1; +FF_ENABLE_DEPRECATION_WARNINGS +#endif frame->interlaced_frame = !parsed_frame.is_deinterlacing && !parsed_frame.dispinfo.progressive_frame; diff --git a/libavcodec/decode.c b/libavcodec/decode.c index 22a0f8eb252..40f5a3ba598 100644 --- a/libavcodec/decode.c +++ b/libavcodec/decode.c @@ -139,8 +139,10 @@ static int extract_packet_props(AVCodecInternal *avci, const AVPacket *pkt) av_packet_unref(avci->last_pkt_props); if (pkt) { ret = av_packet_copy_props(avci->last_pkt_props, pkt); +#if FF_API_FRAME_PKT if (!ret) avci->last_pkt_props->stream_index = pkt->size; // Needed for ff_decode_frame_props(). +#endif } return ret; } @@ -287,8 +289,12 @@ static inline int decode_simple_internal(AVCodecContext *avctx, AVFrame *frame, if (!(codec->caps_internal & FF_CODEC_CAP_SETS_PKT_DTS)) frame->pkt_dts = pkt->dts; if (avctx->codec->type == AVMEDIA_TYPE_VIDEO) { +#if FF_API_FRAME_PKT +FF_DISABLE_DEPRECATION_WARNINGS if(!avctx->has_b_frames) frame->pkt_pos = pkt->pos; +FF_ENABLE_DEPRECATION_WARNINGS +#endif //FIXME these should be under if(!avctx->has_b_frames) /* get_buffer is supposed to set frame parameters */ if (!(avctx->codec->capabilities & AV_CODEC_CAP_DR1)) { @@ -460,8 +466,10 @@ FF_ENABLE_DEPRECATION_WARNINGS pkt->pts = AV_NOPTS_VALUE; pkt->dts = AV_NOPTS_VALUE; if (!(codec->caps_internal & FF_CODEC_CAP_SETS_FRAME_PROPS)) { +#if FF_API_FRAME_PKT // See extract_packet_props() comment. avci->last_pkt_props->stream_index = avci->last_pkt_props->stream_index - consumed; +#endif avci->last_pkt_props->pts = AV_NOPTS_VALUE; avci->last_pkt_props->dts = AV_NOPTS_VALUE; } @@ -1313,9 +1321,13 @@ int ff_decode_frame_props_from_pkt(const AVCodecContext *avctx, }; frame->pts = pkt->pts; - frame->pkt_pos = pkt->pos; frame->duration = pkt->duration; +#if FF_API_FRAME_PKT +FF_DISABLE_DEPRECATION_WARNINGS + frame->pkt_pos = pkt->pos; frame->pkt_size = pkt->size; +FF_ENABLE_DEPRECATION_WARNINGS +#endif for (int i = 0; i < FF_ARRAY_ELEMS(sd); i++) { size_t size; @@ -1356,7 +1368,11 @@ int ff_decode_frame_props(AVCodecContext *avctx, AVFrame *frame) int ret = ff_decode_frame_props_from_pkt(avctx, frame, pkt); if (ret < 0) return ret; +#if FF_API_FRAME_PKT +FF_DISABLE_DEPRECATION_WARNINGS frame->pkt_size = pkt->stream_index; +FF_ENABLE_DEPRECATION_WARNINGS +#endif } #if FF_API_REORDERED_OPAQUE FF_DISABLE_DEPRECATION_WARNINGS diff --git a/libavcodec/libuavs3d.c b/libavcodec/libuavs3d.c index b1ccb151e68..5c08d2b8d3e 100644 --- a/libavcodec/libuavs3d.c +++ b/libavcodec/libuavs3d.c @@ -79,8 +79,12 @@ static void uavs3d_output_callback(uavs3d_io_frm_t *dec_frame) { frm->pts = dec_frame->pts; frm->pkt_dts = dec_frame->dts; +#if FF_API_FRAME_PKT +FF_DISABLE_DEPRECATION_WARNINGS frm->pkt_pos = dec_frame->pkt_pos; frm->pkt_size = dec_frame->pkt_size; +FF_ENABLE_DEPRECATION_WARNINGS +#endif #if FF_API_FRAME_PICTURE_NUMBER FF_DISABLE_DEPRECATION_WARNINGS frm->coded_picture_number = dec_frame->dtr; @@ -175,8 +179,12 @@ static int libuavs3d_decode_frame(AVCodecContext *avctx, AVFrame *frm, uavs3d_io_frm_t *frm_dec = &h->dec_frame; buf_end = buf + buf_size; +#if FF_API_FRAME_PKT +FF_DISABLE_DEPRECATION_WARNINGS frm_dec->pkt_pos = avpkt->pos; frm_dec->pkt_size = avpkt->size; +FF_ENABLE_DEPRECATION_WARNINGS +#endif while (!finish) { int bs_len; diff --git a/libavdevice/lavfi.c b/libavdevice/lavfi.c index 246f7dff3b3..9c1fcf334b5 100644 --- a/libavdevice/lavfi.c +++ b/libavdevice/lavfi.c @@ -343,7 +343,11 @@ static int create_subcc_packet(AVFormatContext *avctx, AVFrame *frame, memcpy(lavfi->subcc_packet.data, sd->data, sd->size); lavfi->subcc_packet.stream_index = stream_idx; lavfi->subcc_packet.pts = frame->pts; +#if FF_API_FRAME_PKT +FF_DISABLE_DEPRECATION_WARNINGS lavfi->subcc_packet.pos = frame->pkt_pos; +FF_ENABLE_DEPRECATION_WARNINGS +#endif return 0; } @@ -450,7 +454,11 @@ static int lavfi_read_packet(AVFormatContext *avctx, AVPacket *pkt) pkt->stream_index = stream_idx; pkt->pts = frame->pts; +#if FF_API_FRAME_PKT +FF_DISABLE_DEPRECATION_WARNINGS pkt->pos = frame->pkt_pos; +FF_ENABLE_DEPRECATION_WARNINGS +#endif if (st->codecpar->codec_type != AVMEDIA_TYPE_VIDEO) av_frame_free(&frame); diff --git a/libavfilter/af_ashowinfo.c b/libavfilter/af_ashowinfo.c index 36ba38b478b..20900369d0b 100644 --- a/libavfilter/af_ashowinfo.c +++ b/libavfilter/af_ashowinfo.c @@ -213,12 +213,11 @@ FF_ENABLE_DEPRECATION_WARNINGS av_channel_layout_describe(&buf->ch_layout, chlayout_str, sizeof(chlayout_str)); av_log(ctx, AV_LOG_INFO, - "n:%"PRId64" pts:%s pts_time:%s pos:%"PRId64" " + "n:%"PRId64" pts:%s pts_time:%s " "fmt:%s channels:%d chlayout:%s rate:%d nb_samples:%d " "checksum:%08"PRIX32" ", inlink->frame_count_out, av_ts2str(buf->pts), av_ts2timestr(buf->pts, &inlink->time_base), - buf->pkt_pos, av_get_sample_fmt_name(buf->format), buf->ch_layout.nb_channels, chlayout_str, buf->sample_rate, buf->nb_samples, checksum); diff --git a/libavfilter/af_volume.c b/libavfilter/af_volume.c index f6e183df8d3..926529947cd 100644 --- a/libavfilter/af_volume.c +++ b/libavfilter/af_volume.c @@ -48,7 +48,9 @@ static const char *const var_names[] = { "nb_channels", ///< number of channels "nb_consumed_samples", ///< number of samples consumed by the filter "nb_samples", ///< number of samples in the current frame +#if FF_API_FRAME_PKT "pos", ///< position in the file of the frame +#endif "pts", ///< frame presentation timestamp "sample_rate", ///< sample rate "startpts", ///< PTS at start of stream @@ -288,7 +290,9 @@ static int config_output(AVFilterLink *outlink) vol->var_values[VAR_N] = vol->var_values[VAR_NB_CONSUMED_SAMPLES] = vol->var_values[VAR_NB_SAMPLES] = +#if FF_API_FRAME_PKT vol->var_values[VAR_POS] = +#endif vol->var_values[VAR_PTS] = vol->var_values[VAR_STARTPTS] = vol->var_values[VAR_STARTT] = @@ -330,7 +334,6 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *buf) AVFilterLink *outlink = inlink->dst->outputs[0]; int nb_samples = buf->nb_samples; AVFrame *out_buf; - int64_t pos; AVFrameSideData *sd = av_frame_get_side_data(buf, AV_FRAME_DATA_REPLAYGAIN); int ret; @@ -380,8 +383,15 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *buf) vol->var_values[VAR_T ] = TS2T(buf->pts, inlink->time_base); vol->var_values[VAR_N ] = inlink->frame_count_out; - pos = buf->pkt_pos; - vol->var_values[VAR_POS] = pos == -1 ? NAN : pos; +#if FF_API_FRAME_PKT +FF_DISABLE_DEPRECATION_WARNINGS + { + int64_t pos; + pos = buf->pkt_pos; + vol->var_values[VAR_POS] = pos == -1 ? NAN : pos; + } +FF_ENABLE_DEPRECATION_WARNINGS +#endif if (vol->eval_mode == EVAL_MODE_FRAME) set_volume(ctx); diff --git a/libavfilter/asrc_flite.c b/libavfilter/asrc_flite.c index 5fab8086bac..1c3053aa39d 100644 --- a/libavfilter/asrc_flite.c +++ b/libavfilter/asrc_flite.c @@ -272,7 +272,11 @@ static int request_frame(AVFilterLink *outlink) memcpy(samplesref->data[0], flite->wave_samples, nb_samples * flite->wave->num_channels * 2); samplesref->pts = flite->pts; +#if FF_API_FRAME_PKT +FF_DISABLE_DEPRECATION_WARNINGS samplesref->pkt_pos = -1; +FF_ENABLE_DEPRECATION_WARNINGS +#endif samplesref->sample_rate = flite->wave->sample_rate; flite->pts += nb_samples; flite->wave_samples += nb_samples * flite->wave->num_channels; diff --git a/libavfilter/avfilter.c b/libavfilter/avfilter.c index ec83b691bf8..8d5702a0c85 100644 --- a/libavfilter/avfilter.c +++ b/libavfilter/avfilter.c @@ -487,7 +487,9 @@ static const char *const var_names[] = { enum { VAR_T, VAR_N, +#if FF_API_FRAME_PKT VAR_POS, +#endif VAR_W, VAR_H, VAR_VARS_NB @@ -1464,7 +1466,11 @@ int ff_inlink_evaluate_timeline_at_frame(AVFilterLink *link, const AVFrame *fram { AVFilterContext *dstctx = link->dst; int64_t pts = frame->pts; +#if FF_API_FRAME_PKT +FF_DISABLE_DEPRECATION_WARNINGS int64_t pos = frame->pkt_pos; +FF_ENABLE_DEPRECATION_WARNINGS +#endif if (!dstctx->enable_str) return 1; @@ -1473,7 +1479,9 @@ int ff_inlink_evaluate_timeline_at_frame(AVFilterLink *link, const AVFrame *fram dstctx->var_values[VAR_T] = pts == AV_NOPTS_VALUE ? NAN : pts * av_q2d(link->time_base); dstctx->var_values[VAR_W] = link->w; dstctx->var_values[VAR_H] = link->h; +#if FF_API_FRAME_PKT dstctx->var_values[VAR_POS] = pos == -1 ? NAN : pos; +#endif return fabs(av_expr_eval(dstctx->enable, dstctx->var_values, NULL)) >= 0.5; } diff --git a/libavfilter/f_select.c b/libavfilter/f_select.c index 1cfe2d59e5e..d76c248fc5b 100644 --- a/libavfilter/f_select.c +++ b/libavfilter/f_select.c @@ -134,7 +134,9 @@ enum var_name { VAR_PREV_SELECTED_N, VAR_KEY, +#if FF_API_FRAME_PKT VAR_POS, +#endif VAR_SCENE, @@ -339,7 +341,11 @@ static void select_frame(AVFilterContext *ctx, AVFrame *frame) select->var_values[VAR_N ] = inlink->frame_count_out; select->var_values[VAR_PTS] = TS2D(frame->pts); select->var_values[VAR_T ] = TS2D(frame->pts) * av_q2d(inlink->time_base); +#if FF_API_FRAME_PKT +FF_DISABLE_DEPRECATION_WARNINGS select->var_values[VAR_POS] = frame->pkt_pos == -1 ? NAN : frame->pkt_pos; +FF_ENABLE_DEPRECATION_WARNINGS +#endif select->var_values[VAR_KEY] = frame->key_frame; select->var_values[VAR_CONCATDEC_SELECT] = get_concatdec_select(frame, av_rescale_q(frame->pts, inlink->time_base, AV_TIME_BASE_Q)); diff --git a/libavfilter/f_sendcmd.c b/libavfilter/f_sendcmd.c index 857b8413131..eb49f8babab 100644 --- a/libavfilter/f_sendcmd.c +++ b/libavfilter/f_sendcmd.c @@ -43,7 +43,9 @@ static const char *const var_names[] = { "N", /* frame number */ "T", /* frame time in seconds */ +#if FF_API_FRAME_PKT "POS", /* original position in the file of the frame */ +#endif "PTS", /* frame pts */ "TS", /* interval start time in seconds */ "TE", /* interval end time in seconds */ @@ -56,7 +58,9 @@ static const char *const var_names[] = { enum var_name { VAR_N, VAR_T, +#if FF_API_FRAME_PKT VAR_POS, +#endif VAR_PTS, VAR_TS, VAR_TE, @@ -531,7 +535,11 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *ref) double current = TS2T(ref->pts, inlink->time_base); var_values[VAR_N] = inlink->frame_count_in; +#if FF_API_FRAME_PKT +FF_DISABLE_DEPRECATION_WARNINGS var_values[VAR_POS] = ref->pkt_pos == -1 ? NAN : ref->pkt_pos; +FF_ENABLE_DEPRECATION_WARNINGS +#endif var_values[VAR_PTS] = TS2D(ref->pts); var_values[VAR_T] = current; var_values[VAR_TS] = start; diff --git a/libavfilter/setpts.c b/libavfilter/setpts.c index 171fae88c0c..5bcc0c2dcf2 100644 --- a/libavfilter/setpts.c +++ b/libavfilter/setpts.c @@ -45,7 +45,9 @@ static const char *const var_names[] = { "N", ///< frame / sample number (starting at zero) "NB_CONSUMED_SAMPLES", ///< number of samples consumed by the filter (only audio) "NB_SAMPLES", ///< number of samples in the current frame (only audio) +#if FF_API_FRAME_PKT "POS", ///< original position in the file of the frame +#endif "PREV_INPTS", ///< previous input PTS "PREV_INT", ///< previous input time in seconds "PREV_OUTPTS", ///< previous output PTS @@ -70,7 +72,9 @@ enum var_name { VAR_N, VAR_NB_CONSUMED_SAMPLES, VAR_NB_SAMPLES, +#if FF_API_FRAME_PKT VAR_POS, +#endif VAR_PREV_INPTS, VAR_PREV_INT, VAR_PREV_OUTPTS, @@ -161,7 +165,11 @@ static double eval_pts(SetPTSContext *setpts, AVFilterLink *inlink, AVFrame *fra } setpts->var_values[VAR_PTS ] = TS2D(pts); setpts->var_values[VAR_T ] = TS2T(pts, inlink->time_base); +#if FF_API_FRAME_PKT +FF_DISABLE_DEPRECATION_WARNINGS setpts->var_values[VAR_POS ] = !frame || frame->pkt_pos == -1 ? NAN : frame->pkt_pos; +FF_ENABLE_DEPRECATION_WARNINGS +#endif setpts->var_values[VAR_RTCTIME ] = av_gettime(); if (frame) { @@ -187,11 +195,10 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *frame) frame->pts = D2TS(d); av_log(inlink->dst, AV_LOG_TRACE, - "N:%"PRId64" PTS:%s T:%f POS:%s", + "N:%"PRId64" PTS:%s T:%f", (int64_t)setpts->var_values[VAR_N], d2istr(setpts->var_values[VAR_PTS]), - setpts->var_values[VAR_T], - d2istr(setpts->var_values[VAR_POS])); + setpts->var_values[VAR_T]); switch (inlink->type) { case AVMEDIA_TYPE_VIDEO: av_log(inlink->dst, AV_LOG_TRACE, " INTERLACED:%"PRId64, @@ -242,10 +249,9 @@ static int activate(AVFilterContext *ctx) if (ff_inlink_acknowledge_status(inlink, &status, &pts)) { double d = eval_pts(setpts, inlink, NULL, pts); - av_log(ctx, AV_LOG_TRACE, "N:EOF PTS:%s T:%f POS:%s -> PTS:%s T:%f\n", + av_log(ctx, AV_LOG_TRACE, "N:EOF PTS:%s T:%f -> PTS:%s T:%f\n", d2istr(setpts->var_values[VAR_PTS]), setpts->var_values[VAR_T], - d2istr(setpts->var_values[VAR_POS]), d2istr(d), TS2T(d, inlink->time_base)); ff_outlink_set_status(outlink, status, D2TS(d)); return 0; diff --git a/libavfilter/vf_crop.c b/libavfilter/vf_crop.c index c7cbfa51ef9..6361209941a 100644 --- a/libavfilter/vf_crop.c +++ b/libavfilter/vf_crop.c @@ -50,7 +50,9 @@ static const char *const var_names[] = { "x", "y", "n", ///< number of frame +#if FF_API_FRAME_PKT "pos", ///< position in the file +#endif "t", ///< timestamp expressed in seconds NULL }; @@ -68,7 +70,9 @@ enum var_name { VAR_X, VAR_Y, VAR_N, +#if FF_API_FRAME_PKT VAR_POS, +#endif VAR_T, VAR_VARS_NB }; @@ -145,7 +149,9 @@ static int config_input(AVFilterLink *link) s->var_values[VAR_OUT_H] = s->var_values[VAR_OH] = NAN; s->var_values[VAR_N] = 0; s->var_values[VAR_T] = NAN; +#if FF_API_FRAME_PKT s->var_values[VAR_POS] = NAN; +#endif av_image_fill_max_pixsteps(s->max_step, NULL, pix_desc); @@ -257,8 +263,12 @@ static int filter_frame(AVFilterLink *link, AVFrame *frame) s->var_values[VAR_N] = link->frame_count_out; s->var_values[VAR_T] = frame->pts == AV_NOPTS_VALUE ? NAN : frame->pts * av_q2d(link->time_base); +#if FF_API_FRAME_PKT +FF_DISABLE_DEPRECATION_WARNINGS s->var_values[VAR_POS] = frame->pkt_pos == -1 ? NAN : frame->pkt_pos; +FF_ENABLE_DEPRECATION_WARNINGS +#endif s->var_values[VAR_X] = av_expr_eval(s->x_pexpr, s->var_values, NULL); s->var_values[VAR_Y] = av_expr_eval(s->y_pexpr, s->var_values, NULL); /* It is necessary if x is expressed from y */ @@ -280,8 +290,8 @@ static int filter_frame(AVFilterLink *link, AVFrame *frame) s->y &= ~((1 << s->vsub) - 1); } - av_log(ctx, AV_LOG_TRACE, "n:%d t:%f pos:%f x:%d y:%d x+w:%d y+h:%d\n", - (int)s->var_values[VAR_N], s->var_values[VAR_T], s->var_values[VAR_POS], + av_log(ctx, AV_LOG_TRACE, "n:%d t:%f x:%d y:%d x+w:%d y+h:%d\n", + (int)s->var_values[VAR_N], s->var_values[VAR_T], s->x, s->y, s->x+s->w, s->y+s->h); if (desc->flags & AV_PIX_FMT_FLAG_HWACCEL) { diff --git a/libavfilter/vf_drawtext.c b/libavfilter/vf_drawtext.c index 50012bb258a..71ab851462b 100644 --- a/libavfilter/vf_drawtext.c +++ b/libavfilter/vf_drawtext.c @@ -90,11 +90,15 @@ static const char *const var_names[] = { "x", "y", "pict_type", +#if FF_API_FRAME_PKT "pkt_pos", +#endif #if FF_API_PKT_DURATION "pkt_duration", #endif +#if FF_API_FRAME_PKT "pkt_size", +#endif "duration", NULL }; @@ -133,11 +137,15 @@ enum var_name { VAR_X, VAR_Y, VAR_PICT_TYPE, +#if FF_API_FRAME_PKT VAR_PKT_POS, +#endif #if FF_API_PKT_DURATION VAR_PKT_DURATION, #endif +#if FF_API_FRAME_PKT VAR_PKT_SIZE, +#endif VAR_DURATION, VAR_VARS_NB }; @@ -1654,7 +1662,12 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *frame) NAN : frame->pts * av_q2d(inlink->time_base); s->var_values[VAR_PICT_TYPE] = frame->pict_type; +#if FF_API_FRAME_PKT +FF_DISABLE_DEPRECATION_WARNINGS s->var_values[VAR_PKT_POS] = frame->pkt_pos; + s->var_values[VAR_PKT_SIZE] = frame->pkt_size; +FF_ENABLE_DEPRECATION_WARNINGS +#endif #if FF_API_PKT_DURATION FF_DISABLE_DEPRECATION_WARNINGS s->var_values[VAR_PKT_DURATION] = frame->pkt_duration * av_q2d(inlink->time_base); @@ -1665,7 +1678,6 @@ FF_DISABLE_DEPRECATION_WARNINGS FF_ENABLE_DEPRECATION_WARNINGS #endif s->var_values[VAR_DURATION] = frame->duration * av_q2d(inlink->time_base); - s->var_values[VAR_PKT_SIZE] = frame->pkt_size; s->metadata = frame->metadata; diff --git a/libavfilter/vf_eq.c b/libavfilter/vf_eq.c index 46636dd29d3..7955bf717e1 100644 --- a/libavfilter/vf_eq.c +++ b/libavfilter/vf_eq.c @@ -221,7 +221,6 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in) AVFilterLink *outlink = inlink->dst->outputs[0]; EQContext *eq = ctx->priv; AVFrame *out; - int64_t pos = in->pkt_pos; const AVPixFmtDescriptor *desc; int i; @@ -235,7 +234,14 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in) desc = av_pix_fmt_desc_get(inlink->format); eq->var_values[VAR_N] = inlink->frame_count_out; - eq->var_values[VAR_POS] = pos == -1 ? NAN : pos; +#if FF_API_FRAME_PKT +FF_DISABLE_DEPRECATION_WARNINGS + { + int64_t pos = in->pkt_pos; + eq->var_values[VAR_POS] = pos == -1 ? NAN : pos; + } +FF_ENABLE_DEPRECATION_WARNINGS +#endif eq->var_values[VAR_T] = TS2T(in->pts, inlink->time_base); if (eq->eval_mode == EVAL_MODE_FRAME) { diff --git a/libavfilter/vf_eq.h b/libavfilter/vf_eq.h index fc8d4a711a8..50850ea42c3 100644 --- a/libavfilter/vf_eq.h +++ b/libavfilter/vf_eq.h @@ -30,7 +30,9 @@ static const char *const var_names[] = { "n", // frame count +#if FF_API_FRAME_PKT "pos", // frame position +#endif "r", // frame rate "t", // timestamp expressed in seconds NULL @@ -38,7 +40,9 @@ static const char *const var_names[] = { enum var_name { VAR_N, +#if FF_API_FRAME_PKT VAR_POS, +#endif VAR_R, VAR_T, VAR_NB diff --git a/libavfilter/vf_overlay.c b/libavfilter/vf_overlay.c index e201e07c159..36c04ac21ba 100644 --- a/libavfilter/vf_overlay.c +++ b/libavfilter/vf_overlay.c @@ -55,7 +55,9 @@ static const char *const var_names[] = { "x", "y", "n", ///< number of frame +#if FF_API_FRAME_PKT "pos", ///< position in the file +#endif "t", ///< timestamp expressed in seconds NULL }; @@ -290,7 +292,9 @@ static int config_input_overlay(AVFilterLink *inlink) s->var_values[VAR_Y] = NAN; s->var_values[VAR_N] = 0; s->var_values[VAR_T] = NAN; +#if FF_API_FRAME_PKT s->var_values[VAR_POS] = NAN; +#endif if ((ret = set_expr(&s->x_pexpr, s->x_expr, "x", ctx)) < 0 || (ret = set_expr(&s->y_pexpr, s->y_expr, "y", ctx)) < 0) @@ -1007,12 +1011,18 @@ static int do_blend(FFFrameSync *fs) return ff_filter_frame(ctx->outputs[0], mainpic); if (s->eval_mode == EVAL_MODE_FRAME) { - int64_t pos = mainpic->pkt_pos; s->var_values[VAR_N] = inlink->frame_count_out; s->var_values[VAR_T] = mainpic->pts == AV_NOPTS_VALUE ? NAN : mainpic->pts * av_q2d(inlink->time_base); - s->var_values[VAR_POS] = pos == -1 ? NAN : pos; +#if FF_API_FRAME_PKT +FF_DISABLE_DEPRECATION_WARNINGS + { + int64_t pos = mainpic->pkt_pos; + s->var_values[VAR_POS] = pos == -1 ? NAN : pos; + } +FF_ENABLE_DEPRECATION_WARNINGS +#endif s->var_values[VAR_OVERLAY_W] = s->var_values[VAR_OW] = second->width; s->var_values[VAR_OVERLAY_H] = s->var_values[VAR_OH] = second->height; @@ -1020,8 +1030,8 @@ static int do_blend(FFFrameSync *fs) s->var_values[VAR_MAIN_H ] = s->var_values[VAR_MH] = mainpic->height; eval_expr(ctx); - av_log(ctx, AV_LOG_DEBUG, "n:%f t:%f pos:%f x:%f xi:%d y:%f yi:%d\n", - s->var_values[VAR_N], s->var_values[VAR_T], s->var_values[VAR_POS], + av_log(ctx, AV_LOG_DEBUG, "n:%f t:%f x:%f xi:%d y:%f yi:%d\n", + s->var_values[VAR_N], s->var_values[VAR_T], s->var_values[VAR_X], s->x, s->var_values[VAR_Y], s->y); } diff --git a/libavfilter/vf_overlay.h b/libavfilter/vf_overlay.h index 30a1a7371ca..7e65095a062 100644 --- a/libavfilter/vf_overlay.h +++ b/libavfilter/vf_overlay.h @@ -34,7 +34,9 @@ enum var_name { VAR_X, VAR_Y, VAR_N, +#if FF_API_FRAME_PKT VAR_POS, +#endif VAR_T, VAR_VARS_NB }; diff --git a/libavfilter/vf_overlay_cuda.c b/libavfilter/vf_overlay_cuda.c index b2cbb9c625d..e9455ffcfff 100644 --- a/libavfilter/vf_overlay_cuda.c +++ b/libavfilter/vf_overlay_cuda.c @@ -68,7 +68,9 @@ enum var_name { VAR_X, VAR_Y, VAR_N, +#if FF_API_FRAME_PKT VAR_POS, +#endif VAR_T, VAR_VARS_NB }; @@ -87,7 +89,9 @@ static const char *const var_names[] = { "x", "y", "n", ///< number of frame +#if FF_API_FRAME_PKT "pos", ///< position in the file +#endif "t", ///< timestamp expressed in seconds NULL }; @@ -238,8 +242,6 @@ static int overlay_cuda_blend(FFFrameSync *fs) AVFrame *input_main, *input_overlay; - int pos = 0; - ctx->cu_ctx = cuda_ctx; // read main and overlay frames from inputs @@ -268,11 +270,19 @@ static int overlay_cuda_blend(FFFrameSync *fs) } if (ctx->eval_mode == EVAL_MODE_FRAME) { - pos = input_main->pkt_pos; ctx->var_values[VAR_N] = inlink->frame_count_out; ctx->var_values[VAR_T] = input_main->pts == AV_NOPTS_VALUE ? NAN : input_main->pts * av_q2d(inlink->time_base); - ctx->var_values[VAR_POS] = pos == -1 ? NAN : pos; + +#if FF_API_FRAME_PKT +FF_DISABLE_DEPRECATION_WARNINGS + { + int64_t pos = input_main->pkt_pos; + ctx->var_values[VAR_POS] = pos == -1 ? NAN : pos; + } +FF_ENABLE_DEPRECATION_WARNINGS +#endif + ctx->var_values[VAR_OVERLAY_W] = ctx->var_values[VAR_OW] = input_overlay->width; ctx->var_values[VAR_OVERLAY_H] = ctx->var_values[VAR_OH] = input_overlay->height; ctx->var_values[VAR_MAIN_W ] = ctx->var_values[VAR_MW] = input_main->width; @@ -280,8 +290,8 @@ static int overlay_cuda_blend(FFFrameSync *fs) eval_expr(avctx); - av_log(avctx, AV_LOG_DEBUG, "n:%f t:%f pos:%f x:%f xi:%d y:%f yi:%d\n", - ctx->var_values[VAR_N], ctx->var_values[VAR_T], ctx->var_values[VAR_POS], + av_log(avctx, AV_LOG_DEBUG, "n:%f t:%f x:%f xi:%d y:%f yi:%d\n", + ctx->var_values[VAR_N], ctx->var_values[VAR_T], ctx->var_values[VAR_X], ctx->x_position, ctx->var_values[VAR_Y], ctx->y_position); } @@ -355,7 +365,9 @@ static int config_input_overlay(AVFilterLink *inlink) s->var_values[VAR_Y] = NAN; s->var_values[VAR_N] = 0; s->var_values[VAR_T] = NAN; +#if FF_API_FRAME_PKT s->var_values[VAR_POS] = NAN; +#endif if ((ret = set_expr(&s->x_pexpr, s->x_expr, "x", ctx)) < 0 || (ret = set_expr(&s->y_pexpr, s->y_expr, "y", ctx)) < 0) diff --git a/libavfilter/vf_scale.c b/libavfilter/vf_scale.c index 85047e35248..6b827635966 100644 --- a/libavfilter/vf_scale.c +++ b/libavfilter/vf_scale.c @@ -56,7 +56,9 @@ static const char *const var_names[] = { "ovsub", "n", "t", +#if FF_API_FRAME_PKT "pos", +#endif "main_w", "main_h", "main_a", @@ -84,7 +86,9 @@ enum var_name { VAR_OVSUB, VAR_N, VAR_T, +#if FF_API_FRAME_PKT VAR_POS, +#endif VAR_S2R_MAIN_W, VAR_S2R_MAIN_H, VAR_S2R_MAIN_A, @@ -205,7 +209,9 @@ static int check_exprs(AVFilterContext *ctx) if (scale->eval_mode == EVAL_MODE_INIT && (vars_w[VAR_N] || vars_h[VAR_N] || vars_w[VAR_T] || vars_h[VAR_T] || +#if FF_API_FRAME_PKT vars_w[VAR_POS] || vars_h[VAR_POS] || +#endif 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]) ) { @@ -738,8 +744,16 @@ static int scale_frame(AVFilterLink *link, AVFrame *in, AVFrame **frame_out) if (scale->eval_mode == EVAL_MODE_FRAME && !frame_changed && ctx->filter != &ff_vf_scale2ref && - !(vars_w[VAR_N] || vars_w[VAR_T] || vars_w[VAR_POS]) && - !(vars_h[VAR_N] || vars_h[VAR_T] || vars_h[VAR_POS]) && + !(vars_w[VAR_N] || vars_w[VAR_T] +#if FF_API_FRAME_PKT + || vars_w[VAR_POS] +#endif + ) && + !(vars_h[VAR_N] || vars_h[VAR_T] +#if FF_API_FRAME_PKT + || vars_h[VAR_POS] +#endif + ) && scale->w && scale->h) goto scale; @@ -761,11 +775,19 @@ static int scale_frame(AVFilterLink *link, AVFrame *in, AVFrame **frame_out) if (ctx->filter == &ff_vf_scale2ref) { scale->var_values[VAR_S2R_MAIN_N] = link->frame_count_out; scale->var_values[VAR_S2R_MAIN_T] = TS2T(in->pts, link->time_base); +#if FF_API_FRAME_PKT +FF_DISABLE_DEPRECATION_WARNINGS scale->var_values[VAR_S2R_MAIN_POS] = in->pkt_pos == -1 ? NAN : in->pkt_pos; +FF_ENABLE_DEPRECATION_WARNINGS +#endif } else { scale->var_values[VAR_N] = link->frame_count_out; scale->var_values[VAR_T] = TS2T(in->pts, link->time_base); +#if FF_API_FRAME_PKT +FF_DISABLE_DEPRECATION_WARNINGS scale->var_values[VAR_POS] = in->pkt_pos == -1 ? NAN : in->pkt_pos; +FF_ENABLE_DEPRECATION_WARNINGS +#endif } link->dst->inputs[0]->format = in->format; @@ -915,7 +937,11 @@ static int filter_frame_ref(AVFilterLink *link, AVFrame *in) 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); +#if FF_API_FRAME_PKT +FF_DISABLE_DEPRECATION_WARNINGS scale->var_values[VAR_POS] = in->pkt_pos == -1 ? NAN : in->pkt_pos; +FF_ENABLE_DEPRECATION_WARNINGS +#endif } return ff_filter_frame(outlink, in); diff --git a/libavfilter/vf_scale_npp.c b/libavfilter/vf_scale_npp.c index 6ce82e53027..3cfead82bf9 100644 --- a/libavfilter/vf_scale_npp.c +++ b/libavfilter/vf_scale_npp.c @@ -84,7 +84,9 @@ static const char *const var_names[] = { "dar", "n", "t", +#if FF_API_FRAME_PKT "pos", +#endif "main_w", "main_h", "main_a", @@ -92,7 +94,9 @@ static const char *const var_names[] = { "main_dar", "mdar", "main_n", "main_t", +#if FF_API_FRAME_PKT "main_pos", +#endif NULL }; @@ -106,7 +110,9 @@ enum var_name { VAR_DAR, VAR_N, VAR_T, +#if FF_API_FRAME_PKT VAR_POS, +#endif VAR_S2R_MAIN_W, VAR_S2R_MAIN_H, VAR_S2R_MAIN_A, @@ -114,7 +120,9 @@ enum var_name { VAR_S2R_MAIN_DAR, VAR_S2R_MDAR, VAR_S2R_MAIN_N, VAR_S2R_MAIN_T, +#if FF_API_FRAME_PKT VAR_S2R_MAIN_POS, +#endif VARS_NB }; @@ -204,8 +212,11 @@ static int check_exprs(AVFilterContext* ctx) 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])) { + vars_w[VAR_S2R_MAIN_T] || vars_h[VAR_S2R_MAIN_T] +#if FF_API_FRAME_PKT + || vars_w[VAR_S2R_MAIN_POS] || vars_h[VAR_S2R_MAIN_POS] +#endif + )) { av_log(ctx, AV_LOG_ERROR, "Expressions with scale2ref_npp variables are not valid in scale_npp filter.\n"); return AVERROR(EINVAL); } @@ -213,11 +224,16 @@ static int check_exprs(AVFilterContext* ctx) if (scale->eval_mode == EVAL_MODE_INIT && (vars_w[VAR_N] || vars_h[VAR_N] || vars_w[VAR_T] || vars_h[VAR_T] || +#if FF_API_FRAME_PKT vars_w[VAR_POS] || vars_h[VAR_POS] || +#endif 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"); + vars_w[VAR_S2R_MAIN_T] || vars_h[VAR_S2R_MAIN_T] +#if FF_API_FRAME_PKT + || vars_w[VAR_S2R_MAIN_POS] || vars_h[VAR_S2R_MAIN_POS] +#endif + ) ) { + av_log(ctx, AV_LOG_ERROR, "Expressions with frame variables 'n', 't', are not valid in init eval_mode.\n"); return AVERROR(EINVAL); } @@ -790,9 +806,16 @@ static int nppscale_scale(AVFilterLink *link, AVFrame *out, AVFrame *in) 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) + !(vars_w[VAR_N] || vars_w[VAR_T] +#if FF_API_FRAME_PKT + || vars_w[VAR_POS] +#endif + ) && + !(vars_h[VAR_N] || vars_h[VAR_T] +#if FF_API_FRAME_PKT + || vars_h[VAR_POS] +#endif + ) && s->w && s->h) goto scale; if (s->eval_mode == EVAL_MODE_INIT) { @@ -813,11 +836,19 @@ static int nppscale_scale(AVFilterLink *link, AVFrame *out, AVFrame *in) 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); +#if FF_API_FRAME_PKT +FF_DISABLE_DEPRECATION_WARNINGS s->var_values[VAR_S2R_MAIN_POS] = in->pkt_pos == -1 ? NAN : in->pkt_pos; +FF_ENABLE_DEPRECATION_WARNINGS +#endif } else { s->var_values[VAR_N] = link->frame_count_out; s->var_values[VAR_T] = TS2T(in->pts, link->time_base); +#if FF_API_FRAME_PKT +FF_DISABLE_DEPRECATION_WARNINGS s->var_values[VAR_POS] = in->pkt_pos == -1 ? NAN : in->pkt_pos; +FF_ENABLE_DEPRECATION_WARNINGS +#endif } link->format = in->format; @@ -932,7 +963,11 @@ static int nppscale_filter_frame_ref(AVFilterLink *link, AVFrame *in) 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); +#if FF_API_FRAME_PKT +FF_DISABLE_DEPRECATION_WARNINGS scale->var_values[VAR_POS] = in->pkt_pos == -1 ? NAN : in->pkt_pos; +FF_ENABLE_DEPRECATION_WARNINGS +#endif } return ff_filter_frame(outlink, in); diff --git a/libavfilter/vf_showinfo.c b/libavfilter/vf_showinfo.c index e6c9d60a85c..9caa618b01c 100644 --- a/libavfilter/vf_showinfo.c +++ b/libavfilter/vf_showinfo.c @@ -714,12 +714,11 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *frame) av_log(ctx, AV_LOG_INFO, "n:%4"PRId64" pts:%7s pts_time:%-7s duration:%7"PRId64 - " duration_time:%-7s pos:%9"PRId64" " + " duration_time:%-7s " "fmt:%s sar:%d/%d s:%dx%d i:%c iskey:%d type:%c ", inlink->frame_count_out, av_ts2str(frame->pts), av_ts2timestr(frame->pts, &inlink->time_base), frame->duration, av_ts2timestr(frame->duration, &inlink->time_base), - frame->pkt_pos, desc->name, frame->sample_aspect_ratio.num, frame->sample_aspect_ratio.den, frame->width, frame->height, diff --git a/libavfilter/vf_swaprect.c b/libavfilter/vf_swaprect.c index b76e3bb99dc..fad650151f9 100644 --- a/libavfilter/vf_swaprect.c +++ b/libavfilter/vf_swaprect.c @@ -64,8 +64,16 @@ static int query_formats(AVFilterContext *ctx) return ff_set_common_formats(ctx, ff_formats_pixdesc_filter(0, reject_flags)); } -static const char *const var_names[] = { "w", "h", "a", "n", "t", "pos", "sar", "dar", NULL }; -enum { VAR_W, VAR_H, VAR_A, VAR_N, VAR_T, VAR_POS, VAR_SAR, VAR_DAR, VAR_VARS_NB }; +static const char *const var_names[] = { "w", "h", "a", "n", "t", +#if FF_API_FRAME_PKT + "pos", +#endif + "sar", "dar", NULL }; +enum { VAR_W, VAR_H, VAR_A, VAR_N, VAR_T, +#if FF_API_FRAME_PKT + VAR_POS, +#endif + VAR_SAR, VAR_DAR, VAR_VARS_NB }; static int filter_frame(AVFilterLink *inlink, AVFrame *in) { @@ -90,7 +98,11 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in) var_values[VAR_DAR] = var_values[VAR_A] * var_values[VAR_SAR]; var_values[VAR_N] = inlink->frame_count_out; var_values[VAR_T] = in->pts == AV_NOPTS_VALUE ? NAN : in->pts * av_q2d(inlink->time_base); +#if FF_API_FRAME_PKT +FF_DISABLE_DEPRECATION_WARNINGS var_values[VAR_POS] = in->pkt_pos == -1 ? NAN : in->pkt_pos; +FF_ENABLE_DEPRECATION_WARNINGS +#endif ret = av_expr_parse_and_eval(&dw, s->w, var_names, &var_values[0], diff --git a/libavutil/frame.c b/libavutil/frame.c index 9545477acc9..5c9afb0d036 100644 --- a/libavutil/frame.c +++ b/libavutil/frame.c @@ -48,8 +48,12 @@ FF_DISABLE_DEPRECATION_WARNINGS frame->pkt_duration = 0; FF_ENABLE_DEPRECATION_WARNINGS #endif +#if FF_API_FRAME_PKT +FF_DISABLE_DEPRECATION_WARNINGS frame->pkt_pos = -1; frame->pkt_size = -1; +FF_ENABLE_DEPRECATION_WARNINGS +#endif frame->time_base = (AVRational){ 0, 1 }; frame->key_frame = 1; frame->sample_aspect_ratio = (AVRational){ 0, 1 }; @@ -279,8 +283,12 @@ static int frame_copy_props(AVFrame *dst, const AVFrame *src, int force_copy) dst->sample_rate = src->sample_rate; dst->opaque = src->opaque; dst->pkt_dts = src->pkt_dts; +#if FF_API_FRAME_PKT +FF_DISABLE_DEPRECATION_WARNINGS dst->pkt_pos = src->pkt_pos; dst->pkt_size = src->pkt_size; +FF_ENABLE_DEPRECATION_WARNINGS +#endif #if FF_API_PKT_DURATION FF_DISABLE_DEPRECATION_WARNINGS dst->pkt_duration = src->pkt_duration; diff --git a/libavutil/frame.h b/libavutil/frame.h index 4ed27cf43fe..5b58c14ac32 100644 --- a/libavutil/frame.h +++ b/libavutil/frame.h @@ -622,12 +622,17 @@ typedef struct AVFrame { */ int64_t best_effort_timestamp; +#if FF_API_FRAME_PKT /** * reordered pos from the last AVPacket that has been input into the decoder * - encoding: unused * - decoding: Read by user. + * @deprecated use AV_CODEC_FLAG_COPY_OPAQUE to pass through arbitrary user + * data from packets to frames */ + attribute_deprecated int64_t pkt_pos; +#endif #if FF_API_PKT_DURATION /** @@ -673,14 +678,19 @@ typedef struct AVFrame { int channels; #endif +#if FF_API_FRAME_PKT /** * size of the corresponding packet containing the compressed * frame. * It is set to a negative value if unknown. * - encoding: unused * - decoding: set by libavcodec, read by user. + * @deprecated use AV_CODEC_FLAG_COPY_OPAQUE to pass through arbitrary user + * data from packets to frames */ + attribute_deprecated int pkt_size; +#endif /** * For hwaccel-format frames, this should be a reference to the diff --git a/libavutil/version.h b/libavutil/version.h index a89a0d406f0..93aa7a10502 100644 --- a/libavutil/version.h +++ b/libavutil/version.h @@ -114,6 +114,7 @@ #define FF_API_REORDERED_OPAQUE (LIBAVUTIL_VERSION_MAJOR < 59) #define FF_API_FRAME_PICTURE_NUMBER (LIBAVUTIL_VERSION_MAJOR < 59) #define FF_API_HDR_VIVID_THREE_SPLINE (LIBAVUTIL_VERSION_MAJOR < 59) +#define FF_API_FRAME_PKT (LIBAVUTIL_VERSION_MAJOR < 59) /** * @} From a36ad2c649c5da5e09d6f4491c5b9e18194e7289 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Mon, 14 Nov 2022 17:55:40 +0100 Subject: [PATCH 0454/2172] doc/developer.texi: document the use of other languages than C --- doc/developer.texi | 38 ++++++++++++++++++++++++++++++++++++-- 1 file changed, 36 insertions(+), 2 deletions(-) diff --git a/doc/developer.texi b/doc/developer.texi index 1275fa4f84b..db5afafa4b6 100644 --- a/doc/developer.texi +++ b/doc/developer.texi @@ -56,9 +56,9 @@ and should try to fix issues their commit causes. @anchor{Coding Rules} @chapter Coding Rules -@section C language features +@section Language -FFmpeg is programmed in the ISO C99 language, extended with: +FFmpeg is mainly programmed in the ISO C99 language, extended with: @itemize @bullet @item Atomic operations from C11 @file{stdatomic.h}. They are emulated on @@ -83,6 +83,40 @@ complex numbers; mixed statements and declarations. @end itemize +@subsection SIMD/DSP +@anchor{SIMD/DSP} + +As modern compilers are unable to generate efficient SIMD or other +performance-critical DSP code from plain C, handwritten assembly is used. +Usually such code is isolated in a separate function. Then the standard approach +is writing multiple versions of this function – a plain C one that works +everywhere and may also be useful for debugging, and potentially multiple +architecture-specific optimized implementations. Initialization code then +chooses the best available version at runtime and loads it into a function +pointer; the function in question is then always called through this pointer. + +The specific syntax used for writing assembly is: +@itemize @bullet +@item +NASM on x86; + +@item +GAS on ARM. +@end itemize + +@subsection Other languages + +Other languages than C may be used in special cases: +@itemize @bullet +@item +Compiler intrinsics or inline assembly when the code in question cannot be +written in the standard way described in the @ref{SIMD/DSP} section. This +typically applies to code that needs to be inlined. + +@item +Objective-C where required for interacting with macOS-specific interfaces. +@end itemize + @section Code formatting conventions There are the following guidelines regarding the indentation in files: From f4dd302a3862fa5e2cc26cf72c842a242681196f Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Thu, 24 Nov 2022 10:15:01 +0100 Subject: [PATCH 0455/2172] doc/developer.texi: document checkasm --- doc/developer.texi | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/doc/developer.texi b/doc/developer.texi index db5afafa4b6..5e283227be3 100644 --- a/doc/developer.texi +++ b/doc/developer.texi @@ -104,6 +104,10 @@ NASM on x86; GAS on ARM. @end itemize +A unit testing framework for assembly called @code{checkasm} lives under +@file{tests/checkasm}. All new assembly should come with @code{checkasm} tests; +adding tests for existing assembly that lacks them is also strongly encouraged. + @subsection Other languages Other languages than C may be used in special cases: From 49b733c73c59f34d03ec6bc46b397b207108d975 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Sat, 11 Mar 2023 16:39:25 +0100 Subject: [PATCH 0456/2172] doc/developer.texi: add a section on API/ABI compatibility Document established practices in it. --- doc/developer.texi | 162 ++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 146 insertions(+), 16 deletions(-) diff --git a/doc/developer.texi b/doc/developer.texi index 5e283227be3..c625a9feed7 100644 --- a/doc/developer.texi +++ b/doc/developer.texi @@ -217,6 +217,7 @@ int myfunc(int my_parameter) ... @end example +@anchor{Naming conventions} @section Naming conventions Names of functions, variables, and struct members must be lowercase, using @@ -387,22 +388,6 @@ time-frame (12h for build failures and security fixes, 3 days small changes, Also note, the maintainer can simply ask for more time to review! @section Code -@subheading API/ABI changes should be discussed before they are made. -Do not change behavior of the programs (renaming options etc) or public -API or ABI without first discussing it on the ffmpeg-devel mailing list. -Do not remove widely used functionality or features (redundant code can be removed). - -@subheading Remember to check if you need to bump versions for libav*. -Depending on the change, you may need to change the version integer. -Incrementing the first component means no backward compatibility to -previous versions (e.g. removal of a function from the public API). -Incrementing the second component means backward compatible change -(e.g. addition of a function to the public API or extension of an -existing data structure). -Incrementing the third component means a noteworthy binary compatible -change (e.g. encoder bug fix that matters for the decoder). The third -component always starts at 100 to distinguish FFmpeg from Libav. - @subheading Warnings for correct code may be disabled if there is no other option. Compiler warnings indicate potential bugs or code with bad style. If a type of warning always points to correct and clean code, that warning should @@ -417,6 +402,151 @@ Never write to unallocated memory, never write over the end of arrays, always check values read from some untrusted source before using them as array index or other risky things. +@section Library public interfaces +Every library in FFmpeg provides a set of public APIs in its installed headers, +which are those listed in the variable @code{HEADERS} in that library's +@file{Makefile}. All identifiers defined in those headers (except for those +explicitly documented otherwise), and corresponding symbols exported from +compiled shared or static libraries are considered public interfaces and must +comply with the API and ABI compatibility rules described in this section. + +Public APIs must be backward compatible within a given major version. I.e. any +valid user code that compiles and works with a given library version must still +compile and work with any later version, as long as the major version number is +unchanged. "Valid user code" here means code that is calling our APIs in a +documented and/or intended manner and is not relying on any undefined behavior. +Incrementing the major version may break backward compatibility, but only to the +extent described in @ref{Major version bumps}. + +We also guarantee backward ABI compatibility for shared and static libraries. +I.e. it should be possible to replace a shared or static build of our library +with a build of any later version (re-linking the user binary in the static +case) without breaking any valid user binaries, as long as the major version +number remains unchanged. + +@subsection Adding new interfaces +Any new public identifiers in installed headers are considered new API - this +includes new functions, structs, macros, enum values, typedefs, new fields in +existing functions, new installed headers, etc. Consider the following +guidelines when adding new APIs. + +@subsubheading Motivation +While new APIs can be added relatively easily, changing or removing them is much +harder due to abovementioned compatibility requirements. You should then +consider carefully whether the functionality you are adding really needs to be +exposed to our callers as new public API. + +Your new API should have at least one well-established use case outside of the +library that cannot be easily achieved with existing APIs. Every library in +FFmpeg also has a defined scope - your new API must fit within it. + +@subsubheading Replacing existing APIs +If your new API is replacing an existing one, it should be strictly superior to +it, so that the advantages of using the new API outweight the cost to the +callers of changing their code. After adding the new API you should then +deprecate the old one and schedule it for removal, as described in +@ref{Removing interfaces}. + +If you deem an existing API deficient and want to fix it, the preferred approach +in most cases is to add a differently-named replacement and deprecate the +existing API rather than modify it. It is important to make the changes visible +to our callers (e.g. through compile- or run-time deprecation warnings) and make +it clear how to transition to the new API (e.g. in the Doxygen documentation or +on the wiki). + +@subsubheading API design +The FFmpeg libraries are used by a variety of callers to perform a wide range of +multimedia-related processing tasks. You should therefore - within reason - try +to design your new API for the broadest feasible set of use cases and avoid +unnecessarily limiting it to a specific type of callers (e.g. just media +playback or just transcoding). + +@subsubheading Consistency +Check whether similar APIs already exist in FFmpeg. If they do, try to model +your new addition on them to achieve better overall consistency. + +The naming of your new identifiers should follow the @ref{Naming conventions} +and be aligned with other similar APIs, if applicable. + +@subsubheading Extensibility +You should also consider how your API might be extended in the future in a +backward-compatible way. If you are adding a new struct @code{AVFoo}, the +standard approach is requiring the caller to always allocate it through a +constructor function, typically named @code{av_foo_alloc()}. This way new fields +may be added to the end of the struct without breaking ABI compatibility. +Typically you will also want a destructor - @code{av_foo_free(AVFoo**)} that +frees the indirectly supplied object (and its contents, if applicable) and +writes @code{NULL} to the supplied pointer, thus eliminating the potential +dangling pointer in the caller's memory. + +If you are adding new functions, consider whether it might be desirable to tweak +their behavior in the future - you may want to add a flags argument, even though +it would be unused initially. + +@subsubheading Documentation +All new APIs must be documented as Doxygen-formatted comments above the +identifiers you add to the public headers. You should also briefly mention the +change in @file{doc/APIchanges}. + +@subsubheading Bump the version +Backward-incompatible API or ABI changes require incrementing (bumping) the +major version number, as described in @ref{Major version bumps}. Major +bumps are significant events that happen on a schedule - so if your change +strictly requires one you should add it under @code{#if} preprocesor guards that +disable it until the next major bump happens. + +New APIs that can be added without breaking API or ABI compatibility require +bumping the minor version number. + +Incrementing the third (micro) version component means a noteworthy binary +compatible change (e.g. encoder bug fix that matters for the decoder). The third +component always starts at 100 to distinguish FFmpeg from Libav. + +@anchor{Removing interfaces} +@subsection Removing interfaces +Due to abovementioned compatibility guarantees, removing APIs is an involved +process that should only be undertaken with good reason. Typically a deficient, +restrictive, or otherwise inadequate API is replaced by a superior one, though +it does at times happen that we remove an API without any replacement (e.g. when +the feature it provides is deemed not worth the maintenance effort, out of scope +of the project, fundamentally flawed, etc.). + +The removal has two steps - first the API is deprecated and scheduled for +removal, but remains present and functional. The second step is actually +removing the API - this is described in @ref{Major version bumps}. + +To deprecate an API you should signal to our users that they should stop using +it. E.g. if you intend to remove struct members or functions, you should mark +them with @code{attribute_deprecated}. When this cannot be done, it may be +possible to detect the use of the deprecated API at runtime and print a warning +(though take care not to print it too often). You should also document the +deprecation (and the replacement, if applicable) in the relevant Doxygen +documentation block. + +Finally, you should define a deprecation guard along the lines of +@code{#define FF_API_ (LIBAVBAR_VERSION_MAJOR < XX)} (where XX is the major +version in which the API will be removed) in @file{libavbar/version_major.h} +(@file{version.h} in case of @code{libavutil}). Then wrap all uses of the +deprecated API in @code{#if FF_API_ .... #endif}, so that the code will +automatically get disabled once the major version reaches XX. You can also use +@code{FF_DISABLE_DEPRECATION_WARNINGS} and @code{FF_ENABLE_DEPRECATION_WARNINGS} +to suppress compiler deprecation warnings inside these guards. You should test +that the code compiles and works with the guard macro evaluating to both true +and false. + +@anchor{Major version bumps} +@subsection Major version bumps +A major version bump signifies an API and/or ABI compatibility break. To reduce +the negative effects on our callers, who are required to adapt their code, +backward-incompatible changes during a major bump should be limited to: +@itemize @bullet +@item +Removing previously deprecated APIs. + +@item +Performing ABI- but not API-breaking changes, like reordering struct contents. +@end itemize + @section Documentation/Other @subheading Subscribe to the ffmpeg-devel mailing list. It is important to be subscribed to the From 1e406692e5a1e6d9ca852f746088a5610ff80d14 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Fri, 10 Mar 2023 13:36:48 +0100 Subject: [PATCH 0457/2172] fftools/ffmpeg_mux_init: avoid invalid reads in forced keyframe parsing Fixes #10243 --- fftools/ffmpeg_mux_init.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fftools/ffmpeg_mux_init.c b/fftools/ffmpeg_mux_init.c index b3cc502fddc..09d24ba8e5b 100644 --- a/fftools/ffmpeg_mux_init.c +++ b/fftools/ffmpeg_mux_init.c @@ -2063,7 +2063,7 @@ static void parse_forced_key_frames(KeyframeForceCtx *kf, const Muxer *mux, if (next) *next++ = 0; - if (!memcmp(p, "chapters", 8)) { + if (strstr(p, "chapters") == p) { AVChapter * const *ch = mux->fc->chapters; unsigned int nb_ch = mux->fc->nb_chapters; int j; From 6f2413a203c7dced3230f82cbc2c053872c1a713 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rapha=C3=ABl=20Zumer?= Date: Thu, 16 Mar 2023 17:25:32 -0400 Subject: [PATCH 0458/2172] avcodec/avutil: move dynamic HDR10+ metadata parsing to libavutil MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Raphaël Zumer Signed-off-by: James Almer --- libavcodec/Makefile | 6 +- libavcodec/av1dec.c | 6 +- libavcodec/dynamic_hdr10_plus.c | 198 ------------------------------- libavcodec/dynamic_hdr10_plus.h | 35 ------ libavcodec/h2645_sei.c | 6 +- libavcodec/libdav1d.c | 6 +- libavutil/hdr_dynamic_metadata.c | 190 +++++++++++++++++++++++++++++ libavutil/hdr_dynamic_metadata.h | 13 ++ 8 files changed, 215 insertions(+), 245 deletions(-) delete mode 100644 libavcodec/dynamic_hdr10_plus.c delete mode 100644 libavcodec/dynamic_hdr10_plus.h diff --git a/libavcodec/Makefile b/libavcodec/Makefile index abae4909d2b..408ecd1e315 100644 --- a/libavcodec/Makefile +++ b/libavcodec/Makefile @@ -104,7 +104,7 @@ OBJS-$(CONFIG_H264_SEI) += h264_sei.o h2645_sei.o OBJS-$(CONFIG_HEVCPARSE) += hevc_parse.o hevc_ps.o hevc_data.o \ h2645data.o h2645_parse.o h2645_vui.o OBJS-$(CONFIG_HEVC_SEI) += hevc_sei.o h2645_sei.o \ - dynamic_hdr10_plus.o dynamic_hdr_vivid.o + dynamic_hdr_vivid.o OBJS-$(CONFIG_HPELDSP) += hpeldsp.o OBJS-$(CONFIG_HUFFMAN) += huffman.o OBJS-$(CONFIG_HUFFYUVDSP) += huffyuvdsp.o @@ -250,7 +250,7 @@ OBJS-$(CONFIG_ATRAC3PAL_DECODER) += atrac3plusdec.o atrac3plus.o \ OBJS-$(CONFIG_ATRAC9_DECODER) += atrac9dec.o OBJS-$(CONFIG_AURA_DECODER) += cyuv.o OBJS-$(CONFIG_AURA2_DECODER) += aura.o -OBJS-$(CONFIG_AV1_DECODER) += av1dec.o dynamic_hdr10_plus.o +OBJS-$(CONFIG_AV1_DECODER) += av1dec.o OBJS-$(CONFIG_AV1_CUVID_DECODER) += cuviddec.o OBJS-$(CONFIG_AV1_MEDIACODEC_DECODER) += mediacodecdec.o OBJS-$(CONFIG_AV1_NVENC_ENCODER) += nvenc_av1.o nvenc.o @@ -1082,7 +1082,7 @@ OBJS-$(CONFIG_LIBARIBB24_DECODER) += libaribb24.o ass.o OBJS-$(CONFIG_LIBCELT_DECODER) += libcelt_dec.o OBJS-$(CONFIG_LIBCODEC2_DECODER) += libcodec2.o OBJS-$(CONFIG_LIBCODEC2_ENCODER) += libcodec2.o -OBJS-$(CONFIG_LIBDAV1D_DECODER) += libdav1d.o dynamic_hdr10_plus.o +OBJS-$(CONFIG_LIBDAV1D_DECODER) += libdav1d.o OBJS-$(CONFIG_LIBDAVS2_DECODER) += libdavs2.o OBJS-$(CONFIG_LIBFDK_AAC_DECODER) += libfdk-aacdec.o OBJS-$(CONFIG_LIBFDK_AAC_ENCODER) += libfdk-aacenc.o diff --git a/libavcodec/av1dec.c b/libavcodec/av1dec.c index 5c14756a57b..807852e317e 100644 --- a/libavcodec/av1dec.c +++ b/libavcodec/av1dec.c @@ -20,6 +20,7 @@ #include "config_components.h" +#include "libavutil/hdr_dynamic_metadata.h" #include "libavutil/film_grain_params.h" #include "libavutil/mastering_display_metadata.h" #include "libavutil/pixdesc.h" @@ -30,7 +31,6 @@ #include "bytestream.h" #include "codec_internal.h" #include "decode.h" -#include "dynamic_hdr10_plus.h" #include "hwconfig.h" #include "profiles.h" #include "thread.h" @@ -926,8 +926,8 @@ static int export_itut_t35(AVCodecContext *avctx, AVFrame *frame, if (!hdrplus) return AVERROR(ENOMEM); - ret = ff_parse_itu_t_t35_to_dynamic_hdr10_plus(hdrplus, gb.buffer, - bytestream2_get_bytes_left(&gb)); + ret = av_dynamic_hdr_plus_from_t35(hdrplus, gb.buffer, + bytestream2_get_bytes_left(&gb)); if (ret < 0) return ret; break; diff --git a/libavcodec/dynamic_hdr10_plus.c b/libavcodec/dynamic_hdr10_plus.c deleted file mode 100644 index 34a44aac655..00000000000 --- a/libavcodec/dynamic_hdr10_plus.c +++ /dev/null @@ -1,198 +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 "dynamic_hdr10_plus.h" -#include "get_bits.h" - -static const int64_t luminance_den = 1; -static const int32_t peak_luminance_den = 15; -static const int64_t rgb_den = 100000; -static const int32_t fraction_pixel_den = 1000; -static const int32_t knee_point_den = 4095; -static const int32_t bezier_anchor_den = 1023; -static const int32_t saturation_weight_den = 8; - -int ff_parse_itu_t_t35_to_dynamic_hdr10_plus(AVDynamicHDRPlus *s, const uint8_t *data, - int size) -{ - GetBitContext gbc, *gb = &gbc; - int ret; - - if (!s) - return AVERROR(ENOMEM); - - ret = init_get_bits8(gb, data, size); - if (ret < 0) - return ret; - - if (get_bits_left(gb) < 10) - return AVERROR_INVALIDDATA; - - s->application_version = get_bits(gb, 8); - s->num_windows = get_bits(gb, 2); - - if (s->num_windows < 1 || s->num_windows > 3) { - return AVERROR_INVALIDDATA; - } - - if (get_bits_left(gb) < ((19 * 8 + 1) * (s->num_windows - 1))) - return AVERROR_INVALIDDATA; - - for (int w = 1; w < s->num_windows; w++) { - // The corners are set to absolute coordinates here. They should be - // converted to the relative coordinates (in [0, 1]) in the decoder. - AVHDRPlusColorTransformParams *params = &s->params[w]; - params->window_upper_left_corner_x = - (AVRational){get_bits(gb, 16), 1}; - params->window_upper_left_corner_y = - (AVRational){get_bits(gb, 16), 1}; - params->window_lower_right_corner_x = - (AVRational){get_bits(gb, 16), 1}; - params->window_lower_right_corner_y = - (AVRational){get_bits(gb, 16), 1}; - - params->center_of_ellipse_x = get_bits(gb, 16); - params->center_of_ellipse_y = get_bits(gb, 16); - params->rotation_angle = get_bits(gb, 8); - params->semimajor_axis_internal_ellipse = get_bits(gb, 16); - params->semimajor_axis_external_ellipse = get_bits(gb, 16); - params->semiminor_axis_external_ellipse = get_bits(gb, 16); - params->overlap_process_option = get_bits1(gb); - } - - if (get_bits_left(gb) < 28) - return AVERROR_INVALIDDATA; - - s->targeted_system_display_maximum_luminance = - (AVRational){get_bits_long(gb, 27), luminance_den}; - s->targeted_system_display_actual_peak_luminance_flag = get_bits1(gb); - - if (s->targeted_system_display_actual_peak_luminance_flag) { - int rows, cols; - if (get_bits_left(gb) < 10) - return AVERROR_INVALIDDATA; - rows = get_bits(gb, 5); - cols = get_bits(gb, 5); - if (((rows < 2) || (rows > 25)) || ((cols < 2) || (cols > 25))) { - return AVERROR_INVALIDDATA; - } - s->num_rows_targeted_system_display_actual_peak_luminance = rows; - s->num_cols_targeted_system_display_actual_peak_luminance = cols; - - if (get_bits_left(gb) < (rows * cols * 4)) - return AVERROR_INVALIDDATA; - - for (int i = 0; i < rows; i++) { - for (int j = 0; j < cols; j++) { - s->targeted_system_display_actual_peak_luminance[i][j] = - (AVRational){get_bits(gb, 4), peak_luminance_den}; - } - } - } - for (int w = 0; w < s->num_windows; w++) { - AVHDRPlusColorTransformParams *params = &s->params[w]; - if (get_bits_left(gb) < (3 * 17 + 17 + 4)) - return AVERROR_INVALIDDATA; - - for (int i = 0; i < 3; i++) { - params->maxscl[i] = - (AVRational){get_bits(gb, 17), rgb_den}; - } - params->average_maxrgb = - (AVRational){get_bits(gb, 17), rgb_den}; - params->num_distribution_maxrgb_percentiles = get_bits(gb, 4); - - if (get_bits_left(gb) < - (params->num_distribution_maxrgb_percentiles * 24)) - return AVERROR_INVALIDDATA; - - for (int i = 0; i < params->num_distribution_maxrgb_percentiles; i++) { - params->distribution_maxrgb[i].percentage = get_bits(gb, 7); - params->distribution_maxrgb[i].percentile = - (AVRational){get_bits(gb, 17), rgb_den}; - } - - if (get_bits_left(gb) < 10) - return AVERROR_INVALIDDATA; - - params->fraction_bright_pixels = (AVRational){get_bits(gb, 10), fraction_pixel_den}; - } - if (get_bits_left(gb) < 1) - return AVERROR_INVALIDDATA; - s->mastering_display_actual_peak_luminance_flag = get_bits1(gb); - if (s->mastering_display_actual_peak_luminance_flag) { - int rows, cols; - if (get_bits_left(gb) < 10) - return AVERROR_INVALIDDATA; - rows = get_bits(gb, 5); - cols = get_bits(gb, 5); - if (((rows < 2) || (rows > 25)) || ((cols < 2) || (cols > 25))) { - return AVERROR_INVALIDDATA; - } - s->num_rows_mastering_display_actual_peak_luminance = rows; - s->num_cols_mastering_display_actual_peak_luminance = cols; - - if (get_bits_left(gb) < (rows * cols * 4)) - return AVERROR_INVALIDDATA; - - for (int i = 0; i < rows; i++) { - for (int j = 0; j < cols; j++) { - s->mastering_display_actual_peak_luminance[i][j] = - (AVRational){get_bits(gb, 4), peak_luminance_den}; - } - } - } - - for (int w = 0; w < s->num_windows; w++) { - AVHDRPlusColorTransformParams *params = &s->params[w]; - if (get_bits_left(gb) < 1) - return AVERROR_INVALIDDATA; - - params->tone_mapping_flag = get_bits1(gb); - if (params->tone_mapping_flag) { - if (get_bits_left(gb) < 28) - return AVERROR_INVALIDDATA; - - params->knee_point_x = - (AVRational){get_bits(gb, 12), knee_point_den}; - params->knee_point_y = - (AVRational){get_bits(gb, 12), knee_point_den}; - params->num_bezier_curve_anchors = get_bits(gb, 4); - - if (get_bits_left(gb) < (params->num_bezier_curve_anchors * 10)) - return AVERROR_INVALIDDATA; - - for (int i = 0; i < params->num_bezier_curve_anchors; i++) { - params->bezier_curve_anchors[i] = - (AVRational){get_bits(gb, 10), bezier_anchor_den}; - } - } - - if (get_bits_left(gb) < 1) - return AVERROR_INVALIDDATA; - params->color_saturation_mapping_flag = get_bits1(gb); - if (params->color_saturation_mapping_flag) { - if (get_bits_left(gb) < 6) - return AVERROR_INVALIDDATA; - params->color_saturation_weight = - (AVRational){get_bits(gb, 6), saturation_weight_den}; - } - } - - return 0; -} diff --git a/libavcodec/dynamic_hdr10_plus.h b/libavcodec/dynamic_hdr10_plus.h deleted file mode 100644 index cd7acf04329..00000000000 --- a/libavcodec/dynamic_hdr10_plus.h +++ /dev/null @@ -1,35 +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 AVCODEC_DYNAMIC_HDR10_PLUS_H -#define AVCODEC_DYNAMIC_HDR10_PLUS_H - -#include "libavutil/hdr_dynamic_metadata.h" - -/** - * Parse the user data registered ITU-T T.35 to AVbuffer (AVDynamicHDRPlus). - * @param s A pointer containing the decoded AVDynamicHDRPlus structure. - * @param data The byte array containing the raw ITU-T T.35 data. - * @param size Size of the data array in bytes. - * - * @return 0 if succeed. Otherwise, returns the appropriate AVERROR. - */ -int ff_parse_itu_t_t35_to_dynamic_hdr10_plus(AVDynamicHDRPlus *s, const uint8_t *data, - int size); - -#endif /* AVCODEC_DYNAMIC_HDR10_PLUS_H */ diff --git a/libavcodec/h2645_sei.c b/libavcodec/h2645_sei.c index 6e4a9a1af25..63ab711bc94 100644 --- a/libavcodec/h2645_sei.c +++ b/libavcodec/h2645_sei.c @@ -27,13 +27,13 @@ #include "libavutil/ambient_viewing_environment.h" #include "libavutil/display.h" +#include "libavutil/hdr_dynamic_metadata.h" #include "libavutil/film_grain_params.h" #include "libavutil/pixdesc.h" #include "libavutil/stereo3d.h" #include "atsc_a53.h" #include "avcodec.h" -#include "dynamic_hdr10_plus.h" #include "dynamic_hdr_vivid.h" #include "get_bits.h" #include "golomb.h" @@ -52,8 +52,8 @@ static int decode_registered_user_data_dynamic_hdr_plus(HEVCSEIDynamicHDRPlus *s if (!metadata) return AVERROR(ENOMEM); - err = ff_parse_itu_t_t35_to_dynamic_hdr10_plus(metadata, gb->buffer, - bytestream2_get_bytes_left(gb)); + err = av_dynamic_hdr_plus_from_t35(metadata, gb->buffer, + bytestream2_get_bytes_left(gb)); if (err < 0) { av_free(metadata); return err; diff --git a/libavcodec/libdav1d.c b/libavcodec/libdav1d.c index 632023ba73f..ddf2311a41a 100644 --- a/libavcodec/libdav1d.c +++ b/libavcodec/libdav1d.c @@ -24,6 +24,7 @@ #include "libavutil/avassert.h" #include "libavutil/cpu.h" #include "libavutil/film_grain_params.h" +#include "libavutil/hdr_dynamic_metadata.h" #include "libavutil/mastering_display_metadata.h" #include "libavutil/imgutils.h" #include "libavutil/opt.h" @@ -33,7 +34,6 @@ #include "bytestream.h" #include "codec_internal.h" #include "decode.h" -#include "dynamic_hdr10_plus.h" #include "internal.h" #define FF_DAV1D_VERSION_AT_LEAST(x,y) \ @@ -556,8 +556,8 @@ FF_ENABLE_DEPRECATION_WARNINGS goto fail; } - res = ff_parse_itu_t_t35_to_dynamic_hdr10_plus(hdrplus, gb.buffer, - bytestream2_get_bytes_left(&gb)); + res = av_dynamic_hdr_plus_from_t35(hdrplus, gb.buffer, + bytestream2_get_bytes_left(&gb)); if (res < 0) goto fail; break; diff --git a/libavutil/hdr_dynamic_metadata.c b/libavutil/hdr_dynamic_metadata.c index 0fa1ee82de2..bcf638f5c3d 100644 --- a/libavutil/hdr_dynamic_metadata.c +++ b/libavutil/hdr_dynamic_metadata.c @@ -20,6 +20,18 @@ #include "hdr_dynamic_metadata.h" #include "mem.h" +#include "libavcodec/defs.h" +#include "libavcodec/get_bits.h" + +#define T35_PAYLOAD_MAX_SIZE 907 + +static const int64_t luminance_den = 1; +static const int32_t peak_luminance_den = 15; +static const int64_t rgb_den = 100000; +static const int32_t fraction_pixel_den = 1000; +static const int32_t knee_point_den = 4095; +static const int32_t bezier_anchor_den = 1023; +static const int32_t saturation_weight_den = 8; AVDynamicHDRPlus *av_dynamic_hdr_plus_alloc(size_t *size) { @@ -45,3 +57,181 @@ AVDynamicHDRPlus *av_dynamic_hdr_plus_create_side_data(AVFrame *frame) return (AVDynamicHDRPlus *)side_data->data; } + +int av_dynamic_hdr_plus_from_t35(AVDynamicHDRPlus *s, const uint8_t *data, + size_t size) +{ + uint8_t padded_buf[T35_PAYLOAD_MAX_SIZE + AV_INPUT_BUFFER_PADDING_SIZE]; + GetBitContext gbc, *gb = &gbc; + int ret; + + if (!s) + return AVERROR(ENOMEM); + + if (size > T35_PAYLOAD_MAX_SIZE) + return AVERROR(EINVAL); + + memcpy(padded_buf, data, size); + // Zero-initialize the buffer padding to avoid overreads into uninitialized data. + memset(padded_buf + size, 0, AV_INPUT_BUFFER_PADDING_SIZE); + + ret = init_get_bits8(gb, padded_buf, size); + if (ret < 0) + return ret; + + if (get_bits_left(gb) < 10) + return AVERROR_INVALIDDATA; + + s->application_version = get_bits(gb, 8); + s->num_windows = get_bits(gb, 2); + + if (s->num_windows < 1 || s->num_windows > 3) { + return AVERROR_INVALIDDATA; + } + + if (get_bits_left(gb) < ((19 * 8 + 1) * (s->num_windows - 1))) + return AVERROR_INVALIDDATA; + + for (int w = 1; w < s->num_windows; w++) { + // The corners are set to absolute coordinates here. They should be + // converted to the relative coordinates (in [0, 1]) in the decoder. + AVHDRPlusColorTransformParams *params = &s->params[w]; + params->window_upper_left_corner_x = + (AVRational){get_bits(gb, 16), 1}; + params->window_upper_left_corner_y = + (AVRational){get_bits(gb, 16), 1}; + params->window_lower_right_corner_x = + (AVRational){get_bits(gb, 16), 1}; + params->window_lower_right_corner_y = + (AVRational){get_bits(gb, 16), 1}; + + params->center_of_ellipse_x = get_bits(gb, 16); + params->center_of_ellipse_y = get_bits(gb, 16); + params->rotation_angle = get_bits(gb, 8); + params->semimajor_axis_internal_ellipse = get_bits(gb, 16); + params->semimajor_axis_external_ellipse = get_bits(gb, 16); + params->semiminor_axis_external_ellipse = get_bits(gb, 16); + params->overlap_process_option = get_bits1(gb); + } + + if (get_bits_left(gb) < 28) + return AVERROR_INVALIDDATA; + + s->targeted_system_display_maximum_luminance = + (AVRational){get_bits_long(gb, 27), luminance_den}; + s->targeted_system_display_actual_peak_luminance_flag = get_bits1(gb); + + if (s->targeted_system_display_actual_peak_luminance_flag) { + int rows, cols; + if (get_bits_left(gb) < 10) + return AVERROR_INVALIDDATA; + rows = get_bits(gb, 5); + cols = get_bits(gb, 5); + if (((rows < 2) || (rows > 25)) || ((cols < 2) || (cols > 25))) { + return AVERROR_INVALIDDATA; + } + s->num_rows_targeted_system_display_actual_peak_luminance = rows; + s->num_cols_targeted_system_display_actual_peak_luminance = cols; + + if (get_bits_left(gb) < (rows * cols * 4)) + return AVERROR_INVALIDDATA; + + for (int i = 0; i < rows; i++) { + for (int j = 0; j < cols; j++) { + s->targeted_system_display_actual_peak_luminance[i][j] = + (AVRational){get_bits(gb, 4), peak_luminance_den}; + } + } + } + for (int w = 0; w < s->num_windows; w++) { + AVHDRPlusColorTransformParams *params = &s->params[w]; + if (get_bits_left(gb) < (3 * 17 + 17 + 4)) + return AVERROR_INVALIDDATA; + + for (int i = 0; i < 3; i++) { + params->maxscl[i] = + (AVRational){get_bits(gb, 17), rgb_den}; + } + params->average_maxrgb = + (AVRational){get_bits(gb, 17), rgb_den}; + params->num_distribution_maxrgb_percentiles = get_bits(gb, 4); + + if (get_bits_left(gb) < + (params->num_distribution_maxrgb_percentiles * 24)) + return AVERROR_INVALIDDATA; + + for (int i = 0; i < params->num_distribution_maxrgb_percentiles; i++) { + params->distribution_maxrgb[i].percentage = get_bits(gb, 7); + params->distribution_maxrgb[i].percentile = + (AVRational){get_bits(gb, 17), rgb_den}; + } + + if (get_bits_left(gb) < 10) + return AVERROR_INVALIDDATA; + + params->fraction_bright_pixels = (AVRational){get_bits(gb, 10), fraction_pixel_den}; + } + if (get_bits_left(gb) < 1) + return AVERROR_INVALIDDATA; + s->mastering_display_actual_peak_luminance_flag = get_bits1(gb); + if (s->mastering_display_actual_peak_luminance_flag) { + int rows, cols; + if (get_bits_left(gb) < 10) + return AVERROR_INVALIDDATA; + rows = get_bits(gb, 5); + cols = get_bits(gb, 5); + if (((rows < 2) || (rows > 25)) || ((cols < 2) || (cols > 25))) { + return AVERROR_INVALIDDATA; + } + s->num_rows_mastering_display_actual_peak_luminance = rows; + s->num_cols_mastering_display_actual_peak_luminance = cols; + + if (get_bits_left(gb) < (rows * cols * 4)) + return AVERROR_INVALIDDATA; + + for (int i = 0; i < rows; i++) { + for (int j = 0; j < cols; j++) { + s->mastering_display_actual_peak_luminance[i][j] = + (AVRational){get_bits(gb, 4), peak_luminance_den}; + } + } + } + + for (int w = 0; w < s->num_windows; w++) { + AVHDRPlusColorTransformParams *params = &s->params[w]; + if (get_bits_left(gb) < 1) + return AVERROR_INVALIDDATA; + + params->tone_mapping_flag = get_bits1(gb); + if (params->tone_mapping_flag) { + if (get_bits_left(gb) < 28) + return AVERROR_INVALIDDATA; + + params->knee_point_x = + (AVRational){get_bits(gb, 12), knee_point_den}; + params->knee_point_y = + (AVRational){get_bits(gb, 12), knee_point_den}; + params->num_bezier_curve_anchors = get_bits(gb, 4); + + if (get_bits_left(gb) < (params->num_bezier_curve_anchors * 10)) + return AVERROR_INVALIDDATA; + + for (int i = 0; i < params->num_bezier_curve_anchors; i++) { + params->bezier_curve_anchors[i] = + (AVRational){get_bits(gb, 10), bezier_anchor_den}; + } + } + + if (get_bits_left(gb) < 1) + return AVERROR_INVALIDDATA; + params->color_saturation_mapping_flag = get_bits1(gb); + if (params->color_saturation_mapping_flag) { + if (get_bits_left(gb) < 6) + return AVERROR_INVALIDDATA; + params->color_saturation_weight = + (AVRational){get_bits(gb, 6), saturation_weight_den}; + } + } + + return 0; +} diff --git a/libavutil/hdr_dynamic_metadata.h b/libavutil/hdr_dynamic_metadata.h index 2d72de56aec..a0e5cb1db64 100644 --- a/libavutil/hdr_dynamic_metadata.h +++ b/libavutil/hdr_dynamic_metadata.h @@ -340,4 +340,17 @@ AVDynamicHDRPlus *av_dynamic_hdr_plus_alloc(size_t *size); */ AVDynamicHDRPlus *av_dynamic_hdr_plus_create_side_data(AVFrame *frame); +/** + * Parse the user data registered ITU-T T.35 to AVbuffer (AVDynamicHDRPlus). + * The T.35 buffer must begin with the application mode, skipping the + * country code, terminal provider codes, and application identifier. + * @param s A pointer containing the decoded AVDynamicHDRPlus structure. + * @param data The byte array containing the raw ITU-T T.35 data. + * @param size Size of the data array in bytes. + * + * @return >= 0 on success. Otherwise, returns the appropriate AVERROR. + */ +int av_dynamic_hdr_plus_from_t35(AVDynamicHDRPlus *s, const uint8_t *data, + size_t size); + #endif /* AVUTIL_HDR_DYNAMIC_METADATA_H */ From 0a3ce5f73842714de9bc29719ae5f965901bd1de Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rapha=C3=ABl=20Zumer?= Date: Tue, 14 Mar 2023 19:05:35 -0400 Subject: [PATCH 0459/2172] avutil: add HDR10+ dynamic metadata serialization function MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Mohammad Izadi Signed-off-by: Raphaël Zumer Signed-off-by: James Almer --- doc/APIchanges | 5 ++ libavutil/hdr_dynamic_metadata.c | 148 +++++++++++++++++++++++++++++++ libavutil/hdr_dynamic_metadata.h | 12 +++ libavutil/version.h | 2 +- 4 files changed, 166 insertions(+), 1 deletion(-) diff --git a/doc/APIchanges b/doc/APIchanges index 5914fac2cdc..931c172b786 100644 --- a/doc/APIchanges +++ b/doc/APIchanges @@ -2,6 +2,11 @@ The last version increases of all libraries were on 2023-02-09 API changes, most recent first: +2023-03-21 - xxxxxxxxxx - lavu 58.5.100 - hdr_dynamic_metadata.h + Add av_dynamic_hdr_plus_from_t35() and av_dynamic_hdr_plus_to_t35() + functions to convert between raw T.35 payloads containing dynamic + HDR10+ metadata and their parsed representations as AVDynamicHDRPlus. + 2023-03-17 - xxxxxxxxxx - lavu 58.4.100 - hdr_dynamic_vivid_metadata.h Add two group of three spline params. Deprecate previous define which only supports one group of params. diff --git a/libavutil/hdr_dynamic_metadata.c b/libavutil/hdr_dynamic_metadata.c index bcf638f5c3d..d458788c32c 100644 --- a/libavutil/hdr_dynamic_metadata.c +++ b/libavutil/hdr_dynamic_metadata.c @@ -22,6 +22,7 @@ #include "mem.h" #include "libavcodec/defs.h" #include "libavcodec/get_bits.h" +#include "libavcodec/put_bits.h" #define T35_PAYLOAD_MAX_SIZE 907 @@ -235,3 +236,150 @@ int av_dynamic_hdr_plus_from_t35(AVDynamicHDRPlus *s, const uint8_t *data, return 0; } + +int av_dynamic_hdr_plus_to_t35(const AVDynamicHDRPlus *s, uint8_t **data, size_t *size) +{ + uint8_t *buf; + size_t size_bits, size_bytes; + PutBitContext pbc, *pb = &pbc; + + if (!s || !data) + return AVERROR(EINVAL); + + /** + * Buffer size per CTA-861-H p.253-254: + * 48 header bits (excluded from the serialized payload) + * 8 bits for application_mode + * 2 bits for num_windows + * 153 bits for window geometry, for each window above 1 + * 27 bits for targeted_system_display_maximum_luminance + * 1-2511 bits for targeted system display peak luminance information + * 82-442 bits per window for pixel distribution information + * 1-2511 bits for mastering display peak luminance information + * 1-179 bits per window for tonemapping information + * 1-7 bits per window for color saturation mapping information + * Total: 123-7249 bits, excluding trimmed header bits + */ + size_bits = 8; + + size_bits += 2; + + for (int w = 1; w < s->num_windows; w++) + size_bits += 153; + + size_bits += 27; + + size_bits += 1; + if (s->targeted_system_display_actual_peak_luminance_flag) + size_bits += 10 + + s->num_rows_targeted_system_display_actual_peak_luminance * + s->num_cols_targeted_system_display_actual_peak_luminance * 4; + + for (int w = 0; w < s->num_windows; w++) + size_bits += 72 + s->params[w].num_distribution_maxrgb_percentiles * 24 + 10; + + size_bits += 1; + if (s->mastering_display_actual_peak_luminance_flag) + size_bits += 10 + + s->num_rows_mastering_display_actual_peak_luminance * + s->num_cols_mastering_display_actual_peak_luminance * 4; + + for (int w = 0; w < s->num_windows; w++) { + size_bits += 1; + if (s->params[w].tone_mapping_flag) + size_bits += 28 + s->params[w].num_bezier_curve_anchors * 10; + + size_bits += 1; + if (s->params[w].color_saturation_mapping_flag) + size_bits += 6; + } + + size_bytes = (size_bits + 7) / 8; + + buf = av_mallocz(size_bytes); + if (!buf) + return AVERROR(ENOMEM); + + init_put_bits(pb, buf, size_bytes); + + // application_mode is set to Application Version 1 + put_bits(pb, 8, 1); + + // Payload as per CTA-861-H p.253-254 + put_bits(pb, 2, s->num_windows); + + for (int w = 1; w < s->num_windows; w++) { + put_bits(pb, 16, s->params[w].window_upper_left_corner_x.num / s->params[w].window_upper_left_corner_x.den); + put_bits(pb, 16, s->params[w].window_upper_left_corner_y.num / s->params[w].window_upper_left_corner_y.den); + put_bits(pb, 16, s->params[w].window_lower_right_corner_x.num / s->params[w].window_lower_right_corner_x.den); + put_bits(pb, 16, s->params[w].window_lower_right_corner_y.num / s->params[w].window_lower_right_corner_y.den); + put_bits(pb, 16, s->params[w].center_of_ellipse_x); + put_bits(pb, 16, s->params[w].center_of_ellipse_y); + put_bits(pb, 8, s->params[w].rotation_angle); + put_bits(pb, 16, s->params[w].semimajor_axis_internal_ellipse); + put_bits(pb, 16, s->params[w].semimajor_axis_external_ellipse); + put_bits(pb, 16, s->params[w].semiminor_axis_external_ellipse); + put_bits(pb, 1, s->params[w].overlap_process_option); + } + + put_bits(pb, 27, s->targeted_system_display_maximum_luminance.num * luminance_den / + s->targeted_system_display_maximum_luminance.den); + put_bits(pb, 1, s->targeted_system_display_actual_peak_luminance_flag); + if (s->targeted_system_display_actual_peak_luminance_flag) { + put_bits(pb, 5, s->num_rows_targeted_system_display_actual_peak_luminance); + put_bits(pb, 5, s->num_cols_targeted_system_display_actual_peak_luminance); + for (int i = 0; i < s->num_rows_targeted_system_display_actual_peak_luminance; i++) { + for (int j = 0; j < s->num_cols_targeted_system_display_actual_peak_luminance; j++) + put_bits(pb, 4, s->targeted_system_display_actual_peak_luminance[i][j].num * peak_luminance_den / + s->targeted_system_display_actual_peak_luminance[i][j].den); + } + } + + for (int w = 0; w < s->num_windows; w++) { + for (int i = 0; i < 3; i++) + put_bits(pb, 17, s->params[w].maxscl[i].num * rgb_den / s->params[w].maxscl[i].den); + put_bits(pb, 17, s->params[w].average_maxrgb.num * rgb_den / s->params[w].average_maxrgb.den); + put_bits(pb, 4, s->params[w].num_distribution_maxrgb_percentiles); + for (int i = 0; i < s->params[w].num_distribution_maxrgb_percentiles; i++) { + put_bits(pb, 7, s->params[w].distribution_maxrgb[i].percentage); + put_bits(pb, 17, s->params[w].distribution_maxrgb[i].percentile.num * rgb_den / + s->params[w].distribution_maxrgb[i].percentile.den); + } + put_bits(pb, 10, s->params[w].fraction_bright_pixels.num * fraction_pixel_den / + s->params[w].fraction_bright_pixels.den); + } + + put_bits(pb, 1, s->mastering_display_actual_peak_luminance_flag); + if (s->mastering_display_actual_peak_luminance_flag) { + put_bits(pb, 5, s->num_rows_mastering_display_actual_peak_luminance); + put_bits(pb, 5, s->num_cols_mastering_display_actual_peak_luminance); + for (int i = 0; i < s->num_rows_mastering_display_actual_peak_luminance; i++) { + for (int j = 0; j < s->num_cols_mastering_display_actual_peak_luminance; j++) + put_bits(pb, 4, s->mastering_display_actual_peak_luminance[i][j].num * peak_luminance_den / + s->mastering_display_actual_peak_luminance[i][j].den); + } + } + + for (int w = 0; w < s->num_windows; w++) { + put_bits(pb, 1, s->params[w].tone_mapping_flag); + if (s->params[w].tone_mapping_flag) { + put_bits(pb, 12, s->params[w].knee_point_x.num * knee_point_den / s->params[w].knee_point_x.den); + put_bits(pb, 12, s->params[w].knee_point_y.num * knee_point_den / s->params[w].knee_point_y.den); + put_bits(pb, 4, s->params[w].num_bezier_curve_anchors); + for (int i = 0; i < s->params[w].num_bezier_curve_anchors; i++) + put_bits(pb, 10, s->params[w].bezier_curve_anchors[i].num * bezier_anchor_den / + s->params[w].bezier_curve_anchors[i].den); + put_bits(pb, 1, s->params[w].color_saturation_mapping_flag); + if (s->params[w].color_saturation_mapping_flag) + put_bits(pb, 6, s->params[w].color_saturation_weight.num * saturation_weight_den / + s->params[w].color_saturation_weight.den); + } + } + + flush_put_bits(pb); + + *data = buf; + if (size) + *size = size_bytes; + return 0; +} diff --git a/libavutil/hdr_dynamic_metadata.h b/libavutil/hdr_dynamic_metadata.h index a0e5cb1db64..771bb8f468d 100644 --- a/libavutil/hdr_dynamic_metadata.h +++ b/libavutil/hdr_dynamic_metadata.h @@ -353,4 +353,16 @@ AVDynamicHDRPlus *av_dynamic_hdr_plus_create_side_data(AVFrame *frame); int av_dynamic_hdr_plus_from_t35(AVDynamicHDRPlus *s, const uint8_t *data, size_t size); +/** + * Serialize dynamic HDR10+ metadata to a user data registered ITU-T T.35 buffer, + * excluding the first 48 bytes of the header, and beginning with the application mode. + * @param s A pointer containing the decoded AVDynamicHDRPlus structure. + * @param data A pointer to a byte buffer to be allocated and filled + * with the serialized metadata. + * @param size A pointer to a size to be set to the returned buffer's size (optional). + * + * @return >= 0 on success. Otherwise, returns the appropriate AVERROR. + */ +int av_dynamic_hdr_plus_to_t35(const AVDynamicHDRPlus *s, uint8_t **data, size_t *size); + #endif /* AVUTIL_HDR_DYNAMIC_METADATA_H */ diff --git a/libavutil/version.h b/libavutil/version.h index 93aa7a10502..a232381ba56 100644 --- a/libavutil/version.h +++ b/libavutil/version.h @@ -79,7 +79,7 @@ */ #define LIBAVUTIL_VERSION_MAJOR 58 -#define LIBAVUTIL_VERSION_MINOR 4 +#define LIBAVUTIL_VERSION_MINOR 5 #define LIBAVUTIL_VERSION_MICRO 100 #define LIBAVUTIL_VERSION_INT AV_VERSION_INT(LIBAVUTIL_VERSION_MAJOR, \ From b68a6ba469daae89fcf651d5ec44cc1821a014e4 Mon Sep 17 00:00:00 2001 From: rcombs Date: Mon, 20 Feb 2023 18:24:25 -0600 Subject: [PATCH 0460/2172] ffmpeg: send only one rect per packet when encoding ASS The packet and rect formats are identical, so there's no support for multiple rects per packet. --- fftools/ffmpeg.c | 25 +++++++++++++++---------- 1 file changed, 15 insertions(+), 10 deletions(-) diff --git a/fftools/ffmpeg.c b/fftools/ffmpeg.c index d721a5e7210..438bee8fef6 100644 --- a/fftools/ffmpeg.c +++ b/fftools/ffmpeg.c @@ -1072,6 +1072,8 @@ static void do_subtitle_out(OutputFile *of, /* XXX: signal it in the codec context ? */ if (enc->codec_id == AV_CODEC_ID_DVB_SUBTITLE) nb = 2; + else if (enc->codec_id == AV_CODEC_ID_ASS) + nb = FFMAX(sub->num_rects, 1); else nb = 1; @@ -1080,7 +1082,7 @@ static void do_subtitle_out(OutputFile *of, if (output_files[ost->file_index]->start_time != AV_NOPTS_VALUE) pts -= output_files[ost->file_index]->start_time; for (i = 0; i < nb; i++) { - unsigned save_num_rects = sub->num_rects; + AVSubtitle local_sub = *sub; if (!check_recording_time(ost, pts, AV_TIME_BASE_Q)) return; @@ -1089,19 +1091,22 @@ static void do_subtitle_out(OutputFile *of, if (ret < 0) report_and_exit(AVERROR(ENOMEM)); - sub->pts = pts; + local_sub.pts = pts; // start_display_time is required to be 0 - sub->pts += av_rescale_q(sub->start_display_time, (AVRational){ 1, 1000 }, AV_TIME_BASE_Q); - sub->end_display_time -= sub->start_display_time; - sub->start_display_time = 0; - if (i == 1) - sub->num_rects = 0; + local_sub.pts += av_rescale_q(sub->start_display_time, (AVRational){ 1, 1000 }, AV_TIME_BASE_Q); + local_sub.end_display_time -= sub->start_display_time; + local_sub.start_display_time = 0; + + if (enc->codec_id == AV_CODEC_ID_DVB_SUBTITLE && i == 1) + local_sub.num_rects = 0; + else if (enc->codec_id == AV_CODEC_ID_ASS && sub->num_rects > 0) { + local_sub.num_rects = 1; + local_sub.rects += i; + } ost->frames_encoded++; - subtitle_out_size = avcodec_encode_subtitle(enc, pkt->data, pkt->size, sub); - if (i == 1) - sub->num_rects = save_num_rects; + subtitle_out_size = avcodec_encode_subtitle(enc, pkt->data, pkt->size, &local_sub); if (subtitle_out_size < 0) { av_log(ost, AV_LOG_FATAL, "Subtitle encoding failed\n"); exit_program(1); From c0d9327a63db2b7f15783b59488a480e5d9d6d56 Mon Sep 17 00:00:00 2001 From: rcombs Date: Wed, 8 Mar 2023 15:33:24 -0600 Subject: [PATCH 0461/2172] lavc/ass: error if not passed exactly 1 rect This never produced valid output. --- libavcodec/assenc.c | 29 ++++++++++++++--------------- 1 file changed, 14 insertions(+), 15 deletions(-) diff --git a/libavcodec/assenc.c b/libavcodec/assenc.c index db6fd25dd7c..e548b9fd3bd 100644 --- a/libavcodec/assenc.c +++ b/libavcodec/assenc.c @@ -45,27 +45,26 @@ static int ass_encode_frame(AVCodecContext *avctx, unsigned char *buf, int bufsize, const AVSubtitle *sub) { - int i, len, total_len = 0; + int len; - for (i=0; inum_rects; i++) { - const char *ass = sub->rects[i]->ass; - - if (sub->rects[i]->type != SUBTITLE_ASS) { - av_log(avctx, AV_LOG_ERROR, "Only SUBTITLE_ASS type supported.\n"); - return AVERROR(EINVAL); - } + if (sub->num_rects != 1) { + av_log(avctx, AV_LOG_ERROR, "Only one rect per AVSubtitle is supported in ASS.\n"); + return AVERROR_INVALIDDATA; + } - len = av_strlcpy(buf+total_len, ass, bufsize-total_len); + if (sub->rects[0]->type != SUBTITLE_ASS) { + av_log(avctx, AV_LOG_ERROR, "Only SUBTITLE_ASS type supported.\n"); + return AVERROR(EINVAL); + } - if (len > bufsize-total_len-1) { - av_log(avctx, AV_LOG_ERROR, "Buffer too small for ASS event.\n"); - return AVERROR_BUFFER_TOO_SMALL; - } + len = av_strlcpy(buf, sub->rects[0]->ass, bufsize); - total_len += len; + if (len > bufsize - 1) { + av_log(avctx, AV_LOG_ERROR, "Buffer too small for ASS event.\n"); + return AVERROR_BUFFER_TOO_SMALL; } - return total_len; + return len; } #if CONFIG_SSA_ENCODER From 9413bdc381112711a7beb6d6b8d8fc4b4ff6ca01 Mon Sep 17 00:00:00 2001 From: xufuji456 <839789740@qq.com> Date: Thu, 16 Mar 2023 14:58:30 +0800 Subject: [PATCH 0462/2172] avcodec/arm/hevc: remove duplicate mov of deblock neon MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Martin Storsjö --- libavcodec/arm/hevcdsp_deblock_neon.S | 2 -- 1 file changed, 2 deletions(-) diff --git a/libavcodec/arm/hevcdsp_deblock_neon.S b/libavcodec/arm/hevcdsp_deblock_neon.S index 7cb7487ef61..ebcd056430f 100644 --- a/libavcodec/arm/hevcdsp_deblock_neon.S +++ b/libavcodec/arm/hevcdsp_deblock_neon.S @@ -107,7 +107,6 @@ vshl.s16 q5, q5, #1 vcgt.s16 q3, q0, q4 - vmovn.i16 d6, q3 vshr.s16 q1, q0, #2 vmovn.i16 d6, q3 vcgt.s16 q5, q1, q5 @@ -146,7 +145,6 @@ vtrn.32 q2, q5 vand q5, q2 vneg.s16 q6, q7 - vmovn.i16 d4, q5 vmovn.i16 d4, q2 vmov r8, s8 From 37cde570bc2dcd64a15c5d9a37b9fa0d78d84f9f Mon Sep 17 00:00:00 2001 From: "J. Dekker" Date: Wed, 22 Mar 2023 00:57:00 +0100 Subject: [PATCH 0463/2172] lavc/aarch64: add clip N macro Signed-off-by: J. Dekker --- libavcodec/aarch64/hevcdsp_idct_neon.S | 19 +++++-------------- libavcodec/aarch64/neon.S | 11 +++++++++++ 2 files changed, 16 insertions(+), 14 deletions(-) diff --git a/libavcodec/aarch64/hevcdsp_idct_neon.S b/libavcodec/aarch64/hevcdsp_idct_neon.S index 467cb0f48a6..3e59dd20bbd 100644 --- a/libavcodec/aarch64/hevcdsp_idct_neon.S +++ b/libavcodec/aarch64/hevcdsp_idct_neon.S @@ -5,7 +5,7 @@ * * Ported from arm/hevcdsp_idct_neon.S by * Copyright (c) 2020 Reimar Döffinger - * Copyright (c) 2020 J. Dekker + * Copyright (c) 2023 J. Dekker * * This file is part of FFmpeg. * @@ -38,13 +38,6 @@ const trans, align=4 .short 31, 22, 13, 4 endconst -.macro clip2 in1, in2, min, max - smax \in1, \in1, \min - smax \in2, \in2, \min - smin \in1, \in1, \max - smin \in2, \in2, \max -.endm - function ff_hevc_add_residual_4x4_8_neon, export=1 ld1 {v0.8h-v1.8h}, [x1] ld1 {v2.s}[0], [x0], x2 @@ -182,7 +175,7 @@ function hevc_add_residual_4x4_16_neon, export=0 ld1 {v3.d}[1], [x12], x2 movi v4.8h, #0 sqadd v1.8h, v1.8h, v3.8h - clip2 v0.8h, v1.8h, v4.8h, v21.8h + clip v4.8h, v21.8h, v0.8h, v1.8h st1 {v0.d}[0], [x0], x2 st1 {v0.d}[1], [x0], x2 st1 {v1.d}[0], [x0], x2 @@ -201,7 +194,7 @@ function hevc_add_residual_8x8_16_neon, export=0 sqadd v0.8h, v0.8h, v2.8h ld1 {v3.8h}, [x12] sqadd v1.8h, v1.8h, v3.8h - clip2 v0.8h, v1.8h, v4.8h, v21.8h + clip v4.8h, v21.8h, v0.8h, v1.8h st1 {v0.8h}, [x0], x2 st1 {v1.8h}, [x12], x2 bne 1b @@ -221,8 +214,7 @@ function hevc_add_residual_16x16_16_neon, export=0 sqadd v1.8h, v1.8h, v17.8h sqadd v2.8h, v2.8h, v18.8h sqadd v3.8h, v3.8h, v19.8h - clip2 v0.8h, v1.8h, v20.8h, v21.8h - clip2 v2.8h, v3.8h, v20.8h, v21.8h + clip v20.8h, v21.8h, v0.8h, v1.8h, v2.8h, v3.8h st1 {v0.8h-v1.8h}, [x0], x2 st1 {v2.8h-v3.8h}, [x12], x2 bne 1b @@ -239,8 +231,7 @@ function hevc_add_residual_32x32_16_neon, export=0 sqadd v1.8h, v1.8h, v17.8h sqadd v2.8h, v2.8h, v18.8h sqadd v3.8h, v3.8h, v19.8h - clip2 v0.8h, v1.8h, v20.8h, v21.8h - clip2 v2.8h, v3.8h, v20.8h, v21.8h + clip v20.8h, v21.8h, v0.8h, v1.8h, v2.8h, v3.8h st1 {v0.8h-v3.8h}, [x0], x2 bne 1b ret diff --git a/libavcodec/aarch64/neon.S b/libavcodec/aarch64/neon.S index 1ad32c359d4..bc105e48619 100644 --- a/libavcodec/aarch64/neon.S +++ b/libavcodec/aarch64/neon.S @@ -1,6 +1,8 @@ /* * This file is part of FFmpeg. * + * Copyright (c) 2023 J. Dekker + * * 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 @@ -16,6 +18,15 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +.macro clip min, max, regs:vararg +.irp x, \regs + smax \x, \x, \min +.endr +.irp x, \regs + smin \x, \x, \max +.endr +.endm + .macro transpose_8x8B r0, r1, r2, r3, r4, r5, r6, r7, r8, r9 trn1 \r8\().8B, \r0\().8B, \r1\().8B trn2 \r9\().8B, \r0\().8B, \r1\().8B From cbcc817353a019da4332ad43deb7bbc4e695d02a Mon Sep 17 00:00:00 2001 From: James Almer Date: Thu, 16 Mar 2023 14:09:49 -0300 Subject: [PATCH 0464/2172] avcodec/vorbisdec: export skip_samples instead of dropping frames pts may not be set on input packets, which could result in the entire stream being discarded. This reverts commit 8fc2dedfe6e8fcc58dd052bf3b85cd4754133b17, reintroducing the behavior it replaced but now allowing the caller to manually drop the preroll samples by looking at the skip_samples side data at the start while ignoring it on seek, by setting the skip_manual avctx flag. Fixes ticket #10251. Suggested-by: Anton Khirnov Signed-off-by: James Almer --- libavcodec/vorbisdec.c | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/libavcodec/vorbisdec.c b/libavcodec/vorbisdec.c index dd856a6dfee..e9dad4ef4fd 100644 --- a/libavcodec/vorbisdec.c +++ b/libavcodec/vorbisdec.c @@ -38,6 +38,7 @@ #include "codec_internal.h" #include "decode.h" #include "get_bits.h" +#include "internal.h" #include "vorbis.h" #include "vorbisdsp.h" #include "vorbis_data.h" @@ -134,7 +135,6 @@ typedef struct vorbis_context_s { av_tx_fn mdct_fn[2]; uint8_t first_frame; - int64_t initial_pts; uint32_t version; uint8_t audio_channels; uint32_t audio_samplerate; @@ -1839,13 +1839,7 @@ static int vorbis_decode_frame(AVCodecContext *avctx, AVFrame *frame, if (!vc->first_frame) { vc->first_frame = 1; - vc->initial_pts = frame->pts; - } - - if (frame->pts == vc->initial_pts) { - *got_frame_ptr = 0; - av_frame_unref(frame); - return buf_size; + avctx->internal->skip_samples = len; } ff_dlog(NULL, "parsed %d bytes %d bits, returned %d samples (*ch*bits) \n", @@ -1877,6 +1871,7 @@ static av_cold void vorbis_decode_flush(AVCodecContext *avctx) sizeof(*vc->saved)); } vc->previous_window = -1; + vc->first_frame = 0; } const FFCodec ff_vorbis_decoder = { From 30cea1d39b94716f2e24f6d5b07e5bc686fdbaf6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Storsj=C3=B6?= Date: Thu, 23 Mar 2023 09:38:50 +0200 Subject: [PATCH 0465/2172] Revert "avcodec/arm/hevc: remove duplicate mov of deblock neon" MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This reverts commit 9413bdc381112711a7beb6d6b8d8fc4b4ff6ca01. That commit broke the fate HEVC tests - unfortunately I only tested checkasm for that patch, and that function is still lacking checkasm coverage. Signed-off-by: Martin Storsjö --- libavcodec/arm/hevcdsp_deblock_neon.S | 2 ++ 1 file changed, 2 insertions(+) diff --git a/libavcodec/arm/hevcdsp_deblock_neon.S b/libavcodec/arm/hevcdsp_deblock_neon.S index ebcd056430f..7cb7487ef61 100644 --- a/libavcodec/arm/hevcdsp_deblock_neon.S +++ b/libavcodec/arm/hevcdsp_deblock_neon.S @@ -107,6 +107,7 @@ vshl.s16 q5, q5, #1 vcgt.s16 q3, q0, q4 + vmovn.i16 d6, q3 vshr.s16 q1, q0, #2 vmovn.i16 d6, q3 vcgt.s16 q5, q1, q5 @@ -145,6 +146,7 @@ vtrn.32 q2, q5 vand q5, q2 vneg.s16 q6, q7 + vmovn.i16 d4, q5 vmovn.i16 d4, q2 vmov r8, s8 From 632c34993195f716e9fa575af3de80d07fd50991 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Wed, 15 Mar 2023 18:57:36 +0100 Subject: [PATCH 0466/2172] lavfi: add a flag for filters able to work with hw_device_ctx This way the caller can set it just on the filters that can make use of it. --- doc/APIchanges | 3 +++ libavfilter/avfilter.h | 9 +++++++++ libavfilter/stack_internal.c | 4 ++-- libavfilter/version.h | 2 +- libavfilter/vf_avgblur_opencl.c | 1 + libavfilter/vf_avgblur_vulkan.c | 1 + libavfilter/vf_blend_vulkan.c | 1 + libavfilter/vf_chromaber_vulkan.c | 1 + libavfilter/vf_colorkey_opencl.c | 3 ++- libavfilter/vf_convolution_opencl.c | 4 ++++ libavfilter/vf_deshake_opencl.c | 3 ++- libavfilter/vf_flip_vulkan.c | 1 + libavfilter/vf_gblur_vulkan.c | 1 + libavfilter/vf_libplacebo.c | 1 + libavfilter/vf_neighbor_opencl.c | 1 + libavfilter/vf_nlmeans_opencl.c | 1 + libavfilter/vf_overlay_opencl.c | 1 + libavfilter/vf_overlay_qsv.c | 1 + libavfilter/vf_overlay_vulkan.c | 1 + libavfilter/vf_pad_opencl.c | 3 ++- libavfilter/vf_program_opencl.c | 4 +++- libavfilter/vf_remap_opencl.c | 1 + libavfilter/vf_scale_vulkan.c | 1 + libavfilter/vf_stack_qsv.c | 6 +++--- libavfilter/vf_stack_vaapi.c | 6 +++--- libavfilter/vf_tonemap_opencl.c | 1 + libavfilter/vf_transpose_opencl.c | 1 + libavfilter/vf_transpose_vulkan.c | 1 + libavfilter/vf_unsharp_opencl.c | 1 + libavfilter/vf_vpp_qsv.c | 1 + libavfilter/vf_xfade_opencl.c | 1 + libavfilter/vsrc_ddagrab.c | 1 + 32 files changed, 55 insertions(+), 13 deletions(-) diff --git a/doc/APIchanges b/doc/APIchanges index 931c172b786..29ddaa31bd5 100644 --- a/doc/APIchanges +++ b/doc/APIchanges @@ -2,6 +2,9 @@ The last version increases of all libraries were on 2023-02-09 API changes, most recent first: +2023-03-xx - xxxxxxxxxx - lavfi 9.5.100 - avfilter.h + Add AVFILTER_FLAG_HWDEVICE. + 2023-03-21 - xxxxxxxxxx - lavu 58.5.100 - hdr_dynamic_metadata.h Add av_dynamic_hdr_plus_from_t35() and av_dynamic_hdr_plus_to_t35() functions to convert between raw T.35 payloads containing dynamic diff --git a/libavfilter/avfilter.h b/libavfilter/avfilter.h index d0d45844681..d69381aed4f 100644 --- a/libavfilter/avfilter.h +++ b/libavfilter/avfilter.h @@ -131,6 +131,11 @@ enum AVMediaType avfilter_pad_get_type(const AVFilterPad *pads, int pad_idx); * received by the filter on one of its inputs. */ #define AVFILTER_FLAG_METADATA_ONLY (1 << 3) + +/** + * The filter can create hardware frames using AVFilterContext.hw_device_ctx. + */ +#define AVFILTER_FLAG_HWDEVICE (1 << 4) /** * Some filters support a generic "enable" expression option that can be used * to enable or disable a filter in the timeline. Filters supporting this @@ -444,6 +449,10 @@ struct AVFilterContext { * in particular, a filter which consumes or processes hardware frames will * instead use the hw_frames_ctx field in AVFilterLink to carry the * hardware context information. + * + * May be set by the caller on filters flagged with AVFILTER_FLAG_HWDEVICE + * before initializing the filter with avfilter_init_str() or + * avfilter_init_dict(). */ AVBufferRef *hw_device_ctx; diff --git a/libavfilter/stack_internal.c b/libavfilter/stack_internal.c index 0697ebdd12c..1ee20d66cf2 100644 --- a/libavfilter/stack_internal.c +++ b/libavfilter/stack_internal.c @@ -333,7 +333,7 @@ static const AVFilterPad stack_outputs[] = { { NULL } \ } -#define DEFINE_STACK_FILTER(category, api, capi) \ +#define DEFINE_STACK_FILTER(category, api, capi, filter_flags) \ static const AVClass category##_##api##_class = { \ .class_name = #category "_" #api, \ .item_name = av_default_item_name, \ @@ -351,5 +351,5 @@ static const AVFilterPad stack_outputs[] = { FILTER_QUERY_FUNC(api##_stack_query_formats), \ FILTER_OUTPUTS(stack_outputs), \ .flags_internal = FF_FILTER_FLAG_HWFRAME_AWARE, \ - .flags = AVFILTER_FLAG_DYNAMIC_INPUTS, \ + .flags = AVFILTER_FLAG_DYNAMIC_INPUTS | filter_flags, \ } diff --git a/libavfilter/version.h b/libavfilter/version.h index 4d8f28e5127..523a7fe0a6e 100644 --- a/libavfilter/version.h +++ b/libavfilter/version.h @@ -31,7 +31,7 @@ #include "version_major.h" -#define LIBAVFILTER_VERSION_MINOR 4 +#define LIBAVFILTER_VERSION_MINOR 5 #define LIBAVFILTER_VERSION_MICRO 100 diff --git a/libavfilter/vf_avgblur_opencl.c b/libavfilter/vf_avgblur_opencl.c index 7c0578b694b..68f3a632492 100644 --- a/libavfilter/vf_avgblur_opencl.c +++ b/libavfilter/vf_avgblur_opencl.c @@ -390,6 +390,7 @@ const AVFilter ff_vf_boxblur_opencl = { FILTER_OUTPUTS(avgblur_opencl_outputs), FILTER_SINGLE_PIXFMT(AV_PIX_FMT_OPENCL), .flags_internal = FF_FILTER_FLAG_HWFRAME_AWARE, + .flags = AVFILTER_FLAG_HWDEVICE, }; #endif /* CONFIG_BOXBLUR_OPENCL_FILTER */ diff --git a/libavfilter/vf_avgblur_vulkan.c b/libavfilter/vf_avgblur_vulkan.c index d118ce802ca..6a54d158ce1 100644 --- a/libavfilter/vf_avgblur_vulkan.c +++ b/libavfilter/vf_avgblur_vulkan.c @@ -418,4 +418,5 @@ const AVFilter ff_vf_avgblur_vulkan = { FILTER_SINGLE_PIXFMT(AV_PIX_FMT_VULKAN), .priv_class = &avgblur_vulkan_class, .flags_internal = FF_FILTER_FLAG_HWFRAME_AWARE, + .flags = AVFILTER_FLAG_HWDEVICE, }; diff --git a/libavfilter/vf_blend_vulkan.c b/libavfilter/vf_blend_vulkan.c index fcc21cbc8d5..4cee688a22f 100644 --- a/libavfilter/vf_blend_vulkan.c +++ b/libavfilter/vf_blend_vulkan.c @@ -500,5 +500,6 @@ const AVFilter ff_vf_blend_vulkan = { FILTER_SINGLE_PIXFMT(AV_PIX_FMT_VULKAN), .priv_class = &blend_vulkan_class, .flags_internal = FF_FILTER_FLAG_HWFRAME_AWARE, + .flags = AVFILTER_FLAG_HWDEVICE, .process_command = &process_command, }; diff --git a/libavfilter/vf_chromaber_vulkan.c b/libavfilter/vf_chromaber_vulkan.c index b9423e417e3..62b99cc4d91 100644 --- a/libavfilter/vf_chromaber_vulkan.c +++ b/libavfilter/vf_chromaber_vulkan.c @@ -349,4 +349,5 @@ const AVFilter ff_vf_chromaber_vulkan = { FILTER_SINGLE_PIXFMT(AV_PIX_FMT_VULKAN), .priv_class = &chromaber_vulkan_class, .flags_internal = FF_FILTER_FLAG_HWFRAME_AWARE, + .flags = AVFILTER_FLAG_HWDEVICE, }; diff --git a/libavfilter/vf_colorkey_opencl.c b/libavfilter/vf_colorkey_opencl.c index 84be1999a89..2b019b290c1 100644 --- a/libavfilter/vf_colorkey_opencl.c +++ b/libavfilter/vf_colorkey_opencl.c @@ -238,5 +238,6 @@ const AVFilter ff_vf_colorkey_opencl = { FILTER_INPUTS(colorkey_opencl_inputs), FILTER_OUTPUTS(colorkey_opencl_outputs), FILTER_SINGLE_PIXFMT(AV_PIX_FMT_OPENCL), - .flags_internal = FF_FILTER_FLAG_HWFRAME_AWARE + .flags_internal = FF_FILTER_FLAG_HWFRAME_AWARE, + .flags = AVFILTER_FLAG_HWDEVICE, }; diff --git a/libavfilter/vf_convolution_opencl.c b/libavfilter/vf_convolution_opencl.c index de3d38b553b..bf721a7416b 100644 --- a/libavfilter/vf_convolution_opencl.c +++ b/libavfilter/vf_convolution_opencl.c @@ -373,6 +373,7 @@ const AVFilter ff_vf_convolution_opencl = { FILTER_OUTPUTS(convolution_opencl_outputs), FILTER_SINGLE_PIXFMT(AV_PIX_FMT_OPENCL), .flags_internal = FF_FILTER_FLAG_HWFRAME_AWARE, + .flags = AVFILTER_FLAG_HWDEVICE, }; #endif /* CONFIG_CONVOLUTION_OPENCL_FILTER */ @@ -399,6 +400,7 @@ const AVFilter ff_vf_sobel_opencl = { FILTER_OUTPUTS(convolution_opencl_outputs), FILTER_SINGLE_PIXFMT(AV_PIX_FMT_OPENCL), .flags_internal = FF_FILTER_FLAG_HWFRAME_AWARE, + .flags = AVFILTER_FLAG_HWDEVICE, }; #endif /* CONFIG_SOBEL_OPENCL_FILTER */ @@ -425,6 +427,7 @@ const AVFilter ff_vf_prewitt_opencl = { FILTER_OUTPUTS(convolution_opencl_outputs), FILTER_SINGLE_PIXFMT(AV_PIX_FMT_OPENCL), .flags_internal = FF_FILTER_FLAG_HWFRAME_AWARE, + .flags = AVFILTER_FLAG_HWDEVICE, }; #endif /* CONFIG_PREWITT_OPENCL_FILTER */ @@ -451,6 +454,7 @@ const AVFilter ff_vf_roberts_opencl = { FILTER_OUTPUTS(convolution_opencl_outputs), FILTER_SINGLE_PIXFMT(AV_PIX_FMT_OPENCL), .flags_internal = FF_FILTER_FLAG_HWFRAME_AWARE, + .flags = AVFILTER_FLAG_HWDEVICE, }; #endif /* CONFIG_ROBERTS_OPENCL_FILTER */ diff --git a/libavfilter/vf_deshake_opencl.c b/libavfilter/vf_deshake_opencl.c index d488da7fa0c..e670a4cc234 100644 --- a/libavfilter/vf_deshake_opencl.c +++ b/libavfilter/vf_deshake_opencl.c @@ -2169,5 +2169,6 @@ const AVFilter ff_vf_deshake_opencl = { FILTER_INPUTS(deshake_opencl_inputs), FILTER_OUTPUTS(deshake_opencl_outputs), FILTER_SINGLE_PIXFMT(AV_PIX_FMT_OPENCL), - .flags_internal = FF_FILTER_FLAG_HWFRAME_AWARE + .flags_internal = FF_FILTER_FLAG_HWFRAME_AWARE, + .flags = AVFILTER_FLAG_HWDEVICE, }; diff --git a/libavfilter/vf_flip_vulkan.c b/libavfilter/vf_flip_vulkan.c index 0223786ef1f..6868e39ee63 100644 --- a/libavfilter/vf_flip_vulkan.c +++ b/libavfilter/vf_flip_vulkan.c @@ -366,4 +366,5 @@ const AVFilter ff_vf_flip_vulkan = { FILTER_SINGLE_PIXFMT(AV_PIX_FMT_VULKAN), .priv_class = &flip_vulkan_class, .flags_internal = FF_FILTER_FLAG_HWFRAME_AWARE, + .flags = AVFILTER_FLAG_HWDEVICE, }; diff --git a/libavfilter/vf_gblur_vulkan.c b/libavfilter/vf_gblur_vulkan.c index d61f3c778c0..e6ffc8c0735 100644 --- a/libavfilter/vf_gblur_vulkan.c +++ b/libavfilter/vf_gblur_vulkan.c @@ -503,4 +503,5 @@ const AVFilter ff_vf_gblur_vulkan = { FILTER_SINGLE_PIXFMT(AV_PIX_FMT_VULKAN), .priv_class = &gblur_vulkan_class, .flags_internal = FF_FILTER_FLAG_HWFRAME_AWARE, + .flags = AVFILTER_FLAG_HWDEVICE, }; diff --git a/libavfilter/vf_libplacebo.c b/libavfilter/vf_libplacebo.c index 757dc519e9a..ba852de08d6 100644 --- a/libavfilter/vf_libplacebo.c +++ b/libavfilter/vf_libplacebo.c @@ -893,4 +893,5 @@ const AVFilter ff_vf_libplacebo = { FILTER_QUERY_FUNC(libplacebo_query_format), .priv_class = &libplacebo_class, .flags_internal = FF_FILTER_FLAG_HWFRAME_AWARE, + .flags = AVFILTER_FLAG_HWDEVICE, }; diff --git a/libavfilter/vf_neighbor_opencl.c b/libavfilter/vf_neighbor_opencl.c index 3b83cee3da6..d2d93cd2405 100644 --- a/libavfilter/vf_neighbor_opencl.c +++ b/libavfilter/vf_neighbor_opencl.c @@ -312,6 +312,7 @@ const AVFilter ff_vf_dilation_opencl = { FILTER_OUTPUTS(neighbor_opencl_outputs), FILTER_SINGLE_PIXFMT(AV_PIX_FMT_OPENCL), .flags_internal = FF_FILTER_FLAG_HWFRAME_AWARE, + .flags = AVFILTER_FLAG_HWDEVICE, }; #endif /* CONFIG_DILATION_OPENCL_FILTER */ diff --git a/libavfilter/vf_nlmeans_opencl.c b/libavfilter/vf_nlmeans_opencl.c index c0ac8bf95dd..ca3ec45d7a3 100644 --- a/libavfilter/vf_nlmeans_opencl.c +++ b/libavfilter/vf_nlmeans_opencl.c @@ -438,4 +438,5 @@ const AVFilter ff_vf_nlmeans_opencl = { FILTER_OUTPUTS(nlmeans_opencl_outputs), FILTER_SINGLE_PIXFMT(AV_PIX_FMT_OPENCL), .flags_internal = FF_FILTER_FLAG_HWFRAME_AWARE, + .flags = AVFILTER_FLAG_HWDEVICE, }; diff --git a/libavfilter/vf_overlay_opencl.c b/libavfilter/vf_overlay_opencl.c index 1e3ad903e11..38a3fc8795a 100644 --- a/libavfilter/vf_overlay_opencl.c +++ b/libavfilter/vf_overlay_opencl.c @@ -322,4 +322,5 @@ const AVFilter ff_vf_overlay_opencl = { FILTER_OUTPUTS(overlay_opencl_outputs), FILTER_SINGLE_PIXFMT(AV_PIX_FMT_OPENCL), .flags_internal = FF_FILTER_FLAG_HWFRAME_AWARE, + .flags = AVFILTER_FLAG_HWDEVICE, }; diff --git a/libavfilter/vf_overlay_qsv.c b/libavfilter/vf_overlay_qsv.c index 5bec7dd414c..edc7f79c865 100644 --- a/libavfilter/vf_overlay_qsv.c +++ b/libavfilter/vf_overlay_qsv.c @@ -429,4 +429,5 @@ const AVFilter ff_vf_overlay_qsv = { FILTER_QUERY_FUNC(overlay_qsv_query_formats), .priv_class = &overlay_qsv_class, .flags_internal = FF_FILTER_FLAG_HWFRAME_AWARE, + .flags = AVFILTER_FLAG_HWDEVICE, }; diff --git a/libavfilter/vf_overlay_vulkan.c b/libavfilter/vf_overlay_vulkan.c index e87ee830007..6db7baddfdd 100644 --- a/libavfilter/vf_overlay_vulkan.c +++ b/libavfilter/vf_overlay_vulkan.c @@ -494,4 +494,5 @@ const AVFilter ff_vf_overlay_vulkan = { FILTER_SINGLE_PIXFMT(AV_PIX_FMT_VULKAN), .priv_class = &overlay_vulkan_class, .flags_internal = FF_FILTER_FLAG_HWFRAME_AWARE, + .flags = AVFILTER_FLAG_HWDEVICE, }; diff --git a/libavfilter/vf_pad_opencl.c b/libavfilter/vf_pad_opencl.c index 728e850f720..d6b71765eeb 100644 --- a/libavfilter/vf_pad_opencl.c +++ b/libavfilter/vf_pad_opencl.c @@ -391,5 +391,6 @@ const AVFilter ff_vf_pad_opencl = { FILTER_INPUTS(pad_opencl_inputs), FILTER_OUTPUTS(pad_opencl_outputs), FILTER_SINGLE_PIXFMT(AV_PIX_FMT_OPENCL), - .flags_internal = FF_FILTER_FLAG_HWFRAME_AWARE + .flags_internal = FF_FILTER_FLAG_HWFRAME_AWARE, + .flags = AVFILTER_FLAG_HWDEVICE, }; diff --git a/libavfilter/vf_program_opencl.c b/libavfilter/vf_program_opencl.c index 55c1e6547c4..8a4881b38e4 100644 --- a/libavfilter/vf_program_opencl.c +++ b/libavfilter/vf_program_opencl.c @@ -362,7 +362,8 @@ const AVFilter ff_vf_program_opencl = { .description = NULL_IF_CONFIG_SMALL("Filter video using an OpenCL program"), .priv_size = sizeof(ProgramOpenCLContext), .priv_class = &program_opencl_class, - .flags = AVFILTER_FLAG_DYNAMIC_INPUTS, + .flags = AVFILTER_FLAG_DYNAMIC_INPUTS | + AVFILTER_FLAG_HWDEVICE, .preinit = &program_opencl_framesync_preinit, .init = &program_opencl_init, .uninit = &program_opencl_uninit, @@ -421,6 +422,7 @@ const AVFilter ff_vsrc_openclsrc = { FILTER_OUTPUTS(openclsrc_outputs), FILTER_SINGLE_PIXFMT(AV_PIX_FMT_OPENCL), .flags_internal = FF_FILTER_FLAG_HWFRAME_AWARE, + .flags = AVFILTER_FLAG_HWDEVICE, }; #endif diff --git a/libavfilter/vf_remap_opencl.c b/libavfilter/vf_remap_opencl.c index f3f84bde64a..eeb1eb5d69d 100644 --- a/libavfilter/vf_remap_opencl.c +++ b/libavfilter/vf_remap_opencl.c @@ -351,4 +351,5 @@ const AVFilter ff_vf_remap_opencl = { FILTER_SINGLE_PIXFMT(AV_PIX_FMT_OPENCL), .priv_class = &remap_opencl_class, .flags_internal = FF_FILTER_FLAG_HWFRAME_AWARE, + .flags = AVFILTER_FLAG_HWDEVICE, }; diff --git a/libavfilter/vf_scale_vulkan.c b/libavfilter/vf_scale_vulkan.c index c1404208962..3b09f0dcc12 100644 --- a/libavfilter/vf_scale_vulkan.c +++ b/libavfilter/vf_scale_vulkan.c @@ -531,4 +531,5 @@ const AVFilter ff_vf_scale_vulkan = { FILTER_SINGLE_PIXFMT(AV_PIX_FMT_VULKAN), .priv_class = &scale_vulkan_class, .flags_internal = FF_FILTER_FLAG_HWFRAME_AWARE, + .flags = AVFILTER_FLAG_HWDEVICE, }; diff --git a/libavfilter/vf_stack_qsv.c b/libavfilter/vf_stack_qsv.c index 9eb0748bd61..3e6aefe44bf 100644 --- a/libavfilter/vf_stack_qsv.c +++ b/libavfilter/vf_stack_qsv.c @@ -235,20 +235,20 @@ static int qsv_stack_query_formats(AVFilterContext *ctx) #if CONFIG_HSTACK_QSV_FILTER DEFINE_HSTACK_OPTIONS(qsv); -DEFINE_STACK_FILTER(hstack, qsv, "Quick Sync Video"); +DEFINE_STACK_FILTER(hstack, qsv, "Quick Sync Video", AVFILTER_FLAG_HWDEVICE); #endif #if CONFIG_VSTACK_QSV_FILTER DEFINE_VSTACK_OPTIONS(qsv); -DEFINE_STACK_FILTER(vstack, qsv, "Quick Sync Video"); +DEFINE_STACK_FILTER(vstack, qsv, "Quick Sync Video", AVFILTER_FLAG_HWDEVICE); #endif #if CONFIG_XSTACK_QSV_FILTER DEFINE_XSTACK_OPTIONS(qsv); -DEFINE_STACK_FILTER(xstack, qsv, "Quick Sync Video"); +DEFINE_STACK_FILTER(xstack, qsv, "Quick Sync Video", AVFILTER_FLAG_HWDEVICE); #endif diff --git a/libavfilter/vf_stack_vaapi.c b/libavfilter/vf_stack_vaapi.c index 26dbe3f7aa7..8e9471e6d7b 100644 --- a/libavfilter/vf_stack_vaapi.c +++ b/libavfilter/vf_stack_vaapi.c @@ -234,20 +234,20 @@ static int vaapi_stack_query_formats(AVFilterContext *avctx) #if CONFIG_HSTACK_VAAPI_FILTER DEFINE_HSTACK_OPTIONS(vaapi); -DEFINE_STACK_FILTER(hstack, vaapi, "VA-API"); +DEFINE_STACK_FILTER(hstack, vaapi, "VA-API", 0); #endif #if CONFIG_VSTACK_VAAPI_FILTER DEFINE_VSTACK_OPTIONS(vaapi); -DEFINE_STACK_FILTER(vstack, vaapi, "VA-API"); +DEFINE_STACK_FILTER(vstack, vaapi, "VA-API", 0); #endif #if CONFIG_XSTACK_VAAPI_FILTER DEFINE_XSTACK_OPTIONS(vaapi); -DEFINE_STACK_FILTER(xstack, vaapi, "VA-API"); +DEFINE_STACK_FILTER(xstack, vaapi, "VA-API", 0); #endif diff --git a/libavfilter/vf_tonemap_opencl.c b/libavfilter/vf_tonemap_opencl.c index f6ebb694a81..883eb043427 100644 --- a/libavfilter/vf_tonemap_opencl.c +++ b/libavfilter/vf_tonemap_opencl.c @@ -547,4 +547,5 @@ const AVFilter ff_vf_tonemap_opencl = { FILTER_OUTPUTS(tonemap_opencl_outputs), FILTER_SINGLE_PIXFMT(AV_PIX_FMT_OPENCL), .flags_internal = FF_FILTER_FLAG_HWFRAME_AWARE, + .flags = AVFILTER_FLAG_HWDEVICE, }; diff --git a/libavfilter/vf_transpose_opencl.c b/libavfilter/vf_transpose_opencl.c index c6e8bd2f531..56d34d193bc 100644 --- a/libavfilter/vf_transpose_opencl.c +++ b/libavfilter/vf_transpose_opencl.c @@ -281,4 +281,5 @@ const AVFilter ff_vf_transpose_opencl = { FILTER_OUTPUTS(transpose_opencl_outputs), FILTER_SINGLE_PIXFMT(AV_PIX_FMT_OPENCL), .flags_internal = FF_FILTER_FLAG_HWFRAME_AWARE, + .flags = AVFILTER_FLAG_HWDEVICE, }; diff --git a/libavfilter/vf_transpose_vulkan.c b/libavfilter/vf_transpose_vulkan.c index 30d052e08cc..3b2ce4fb693 100644 --- a/libavfilter/vf_transpose_vulkan.c +++ b/libavfilter/vf_transpose_vulkan.c @@ -343,4 +343,5 @@ const AVFilter ff_vf_transpose_vulkan = { FILTER_SINGLE_PIXFMT(AV_PIX_FMT_VULKAN), .priv_class = &transpose_vulkan_class, .flags_internal = FF_FILTER_FLAG_HWFRAME_AWARE, + .flags = AVFILTER_FLAG_HWDEVICE, }; diff --git a/libavfilter/vf_unsharp_opencl.c b/libavfilter/vf_unsharp_opencl.c index 53e310de099..2c3ac14050d 100644 --- a/libavfilter/vf_unsharp_opencl.c +++ b/libavfilter/vf_unsharp_opencl.c @@ -407,4 +407,5 @@ const AVFilter ff_vf_unsharp_opencl = { FILTER_OUTPUTS(unsharp_opencl_outputs), FILTER_SINGLE_PIXFMT(AV_PIX_FMT_OPENCL), .flags_internal = FF_FILTER_FLAG_HWFRAME_AWARE, + .flags = AVFILTER_FLAG_HWDEVICE, }; diff --git a/libavfilter/vf_vpp_qsv.c b/libavfilter/vf_vpp_qsv.c index b4dd7a41913..76f0bc3df1c 100644 --- a/libavfilter/vf_vpp_qsv.c +++ b/libavfilter/vf_vpp_qsv.c @@ -649,6 +649,7 @@ const AVFilter ff_vf_##sn##_qsv = { \ fmts, \ .activate = activate, \ .flags_internal = FF_FILTER_FLAG_HWFRAME_AWARE, \ + .flags = AVFILTER_FLAG_HWDEVICE, \ }; #if CONFIG_VPP_QSV_FILTER diff --git a/libavfilter/vf_xfade_opencl.c b/libavfilter/vf_xfade_opencl.c index cca4980e012..415cf7ac35d 100644 --- a/libavfilter/vf_xfade_opencl.c +++ b/libavfilter/vf_xfade_opencl.c @@ -433,4 +433,5 @@ const AVFilter ff_vf_xfade_opencl = { FILTER_OUTPUTS(xfade_opencl_outputs), FILTER_SINGLE_PIXFMT(AV_PIX_FMT_OPENCL), .flags_internal = FF_FILTER_FLAG_HWFRAME_AWARE, + .flags = AVFILTER_FLAG_HWDEVICE, }; diff --git a/libavfilter/vsrc_ddagrab.c b/libavfilter/vsrc_ddagrab.c index 00c72187eaa..042842104f0 100644 --- a/libavfilter/vsrc_ddagrab.c +++ b/libavfilter/vsrc_ddagrab.c @@ -1056,4 +1056,5 @@ const AVFilter ff_vsrc_ddagrab = { FILTER_OUTPUTS(ddagrab_outputs), FILTER_SINGLE_PIXFMT(AV_PIX_FMT_D3D11), .flags_internal = FF_FILTER_FLAG_HWFRAME_AWARE, + .flags = AVFILTER_FLAG_HWDEVICE, }; From 3f63685c3554aea7f72bab1fdbde440820816d37 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Wed, 15 Mar 2023 19:09:11 +0100 Subject: [PATCH 0467/2172] fftools/ffmpeg: supply hw_device_ctx to filters before initializing them This is more correct, but was not possible before the recently-added filtergraph parsing API. Also, only pass hw devices to filters that are flagged as capable of using them. Tested-by: Niklas Haas --- fftools/ffmpeg.h | 7 ++++++- fftools/ffmpeg_filter.c | 26 ++++++++++++++++++++------ fftools/ffmpeg_hw.c | 21 +++++---------------- 3 files changed, 31 insertions(+), 23 deletions(-) diff --git a/fftools/ffmpeg.h b/fftools/ffmpeg.h index 4d4433f5bad..823218e2142 100644 --- a/fftools/ffmpeg.h +++ b/fftools/ffmpeg.h @@ -802,7 +802,12 @@ void hw_device_free_all(void); int hw_device_setup_for_decode(InputStream *ist); int hw_device_setup_for_encode(OutputStream *ost); -int hw_device_setup_for_filter(FilterGraph *fg); +/** + * Get a hardware device to be used with this filtergraph. + * The returned reference is owned by the callee, the caller + * must ref it explicitly for long-term use. + */ +AVBufferRef *hw_device_for_filter(void); int hwaccel_decode_init(AVCodecContext *avctx); diff --git a/fftools/ffmpeg_filter.c b/fftools/ffmpeg_filter.c index 62d0eefa6d3..4fde1200674 100644 --- a/fftools/ffmpeg_filter.c +++ b/fftools/ffmpeg_filter.c @@ -440,7 +440,8 @@ static int graph_opts_apply(AVFilterGraphSegment *seg) } static int graph_parse(AVFilterGraph *graph, const char *desc, - AVFilterInOut **inputs, AVFilterInOut **outputs) + AVFilterInOut **inputs, AVFilterInOut **outputs, + AVBufferRef *hw_device) { AVFilterGraphSegment *seg; int ret; @@ -456,6 +457,20 @@ static int graph_parse(AVFilterGraph *graph, const char *desc, if (ret < 0) goto fail; + if (hw_device) { + for (int i = 0; i < graph->nb_filters; i++) { + AVFilterContext *f = graph->filters[i]; + + if (!(f->filter->flags & AVFILTER_FLAG_HWDEVICE)) + continue; + f->hw_device_ctx = av_buffer_ref(hw_device); + if (!f->hw_device_ctx) { + ret = AVERROR(ENOMEM); + goto fail; + } + } + } + ret = graph_opts_apply(seg); if (ret < 0) goto fail; @@ -480,7 +495,7 @@ int init_complex_filtergraph(FilterGraph *fg) return AVERROR(ENOMEM); graph->nb_threads = 1; - ret = graph_parse(graph, fg->graph_desc, &inputs, &outputs); + ret = graph_parse(graph, fg->graph_desc, &inputs, &outputs, NULL); if (ret < 0) goto fail; @@ -1114,6 +1129,7 @@ static int graph_is_meta(AVFilterGraph *graph) int configure_filtergraph(FilterGraph *fg) { + AVBufferRef *hw_device; AVFilterInOut *inputs, *outputs, *cur; int ret, i, simple = filtergraph_is_simple(fg); const char *graph_desc = simple ? fg->outputs[0]->ost->avfilter : @@ -1157,11 +1173,9 @@ int configure_filtergraph(FilterGraph *fg) fg->graph->nb_threads = filter_complex_nbthreads; } - if ((ret = graph_parse(fg->graph, graph_desc, &inputs, &outputs)) < 0) - goto fail; + hw_device = hw_device_for_filter(); - ret = hw_device_setup_for_filter(fg); - if (ret < 0) + if ((ret = graph_parse(fg->graph, graph_desc, &inputs, &outputs, hw_device)) < 0) goto fail; if (simple && (!inputs || inputs->next || !outputs || outputs->next)) { diff --git a/fftools/ffmpeg_hw.c b/fftools/ffmpeg_hw.c index 88fa7824701..e67145211c8 100644 --- a/fftools/ffmpeg_hw.c +++ b/fftools/ffmpeg_hw.c @@ -548,17 +548,14 @@ int hwaccel_decode_init(AVCodecContext *avctx) return 0; } -int hw_device_setup_for_filter(FilterGraph *fg) +AVBufferRef *hw_device_for_filter(void) { - HWDevice *dev; - int i; - // Pick the last hardware device if the user doesn't pick the device for // filters explicitly with the filter_hw_device option. if (filter_hw_device) - dev = filter_hw_device; + return filter_hw_device->device_ref; else if (nb_hw_devices > 0) { - dev = hw_devices[nb_hw_devices - 1]; + HWDevice *dev = hw_devices[nb_hw_devices - 1]; if (nb_hw_devices > 1) av_log(NULL, AV_LOG_WARNING, "There are %d hardware devices. device " @@ -567,17 +564,9 @@ int hw_device_setup_for_filter(FilterGraph *fg) "%s is not usable for filters.\n", nb_hw_devices, dev->name, av_hwdevice_get_type_name(dev->type), dev->name); - } else - dev = NULL; - if (dev) { - for (i = 0; i < fg->graph->nb_filters; i++) { - fg->graph->filters[i]->hw_device_ctx = - av_buffer_ref(dev->device_ref); - if (!fg->graph->filters[i]->hw_device_ctx) - return AVERROR(ENOMEM); - } + return dev->device_ref; } - return 0; + return NULL; } From 90488e14408119f6c3a2061a6c26ee8bcfaddbce Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Ekstr=C3=B6m?= Date: Sun, 12 Mar 2023 20:59:04 +0200 Subject: [PATCH 0468/2172] avutil/frame: move counters utilized in loops to their scope This way we can clean up separate definitions in functions with just a single loop, as well as have no reuse between different loops' counters in functions with multiple. --- libavutil/frame.c | 76 ++++++++++++++++++++--------------------------- 1 file changed, 32 insertions(+), 44 deletions(-) diff --git a/libavutil/frame.c b/libavutil/frame.c index 5c9afb0d036..c905e8d6119 100644 --- a/libavutil/frame.c +++ b/libavutil/frame.c @@ -78,9 +78,7 @@ static void free_side_data(AVFrameSideData **ptr_sd) static void wipe_side_data(AVFrame *frame) { - int i; - - for (i = 0; i < frame->nb_side_data; i++) { + for (int i = 0; i < frame->nb_side_data; i++) { free_side_data(&frame->side_data[i]); } frame->nb_side_data = 0; @@ -112,7 +110,7 @@ void av_frame_free(AVFrame **frame) static int get_video_buffer(AVFrame *frame, int align) { const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(frame->format); - int ret, i, padded_height, total_size; + int ret, padded_height, total_size; int plane_padding = FFMAX(16 + 16/*STRIDE_ALIGN*/, align); ptrdiff_t linesizes[4]; size_t sizes[4]; @@ -127,7 +125,7 @@ static int get_video_buffer(AVFrame *frame, int align) if (align <= 0) align = 32; /* STRIDE_ALIGN. Should be av_cpu_max_align() */ - for(i=1; i<=align; i+=i) { + for (int i = 1; i <= align; i += i) { ret = av_image_fill_linesizes(frame->linesize, frame->format, FFALIGN(frame->width, i)); if (ret < 0) @@ -136,11 +134,11 @@ static int get_video_buffer(AVFrame *frame, int align) break; } - for (i = 0; i < 4 && frame->linesize[i]; i++) + for (int i = 0; i < 4 && frame->linesize[i]; i++) frame->linesize[i] = FFALIGN(frame->linesize[i], align); } - for (i = 0; i < 4; i++) + for (int i = 0; i < 4; i++) linesizes[i] = frame->linesize[i]; padded_height = FFALIGN(frame->height, 32); @@ -149,7 +147,7 @@ static int get_video_buffer(AVFrame *frame, int align) return ret; total_size = 4*plane_padding; - for (i = 0; i < 4; i++) { + for (int i = 0; i < 4; i++) { if (sizes[i] > INT_MAX - total_size) return AVERROR(EINVAL); total_size += sizes[i]; @@ -165,7 +163,7 @@ static int get_video_buffer(AVFrame *frame, int align) frame->buf[0]->data, frame->linesize)) < 0) goto fail; - for (i = 1; i < 4; i++) { + for (int i = 1; i < 4; i++) { if (frame->data[i]) frame->data[i] += i * plane_padding; } @@ -182,7 +180,7 @@ static int get_audio_buffer(AVFrame *frame, int align) { int planar = av_sample_fmt_is_planar(frame->format); int channels, planes; - int ret, i; + int ret; #if FF_API_OLD_CHANNEL_LAYOUT FF_DISABLE_DEPRECATION_WARNINGS @@ -223,7 +221,7 @@ FF_ENABLE_DEPRECATION_WARNINGS } else frame->extended_data = frame->data; - for (i = 0; i < FFMIN(planes, AV_NUM_DATA_POINTERS); i++) { + for (int i = 0; i < FFMIN(planes, AV_NUM_DATA_POINTERS); i++) { frame->buf[i] = av_buffer_alloc(frame->linesize[0]); if (!frame->buf[i]) { av_frame_unref(frame); @@ -231,7 +229,7 @@ FF_ENABLE_DEPRECATION_WARNINGS } frame->extended_data[i] = frame->data[i] = frame->buf[i]->data; } - for (i = 0; i < planes - AV_NUM_DATA_POINTERS; i++) { + for (int i = 0; i < planes - AV_NUM_DATA_POINTERS; i++) { frame->extended_buf[i] = av_buffer_alloc(frame->linesize[0]); if (!frame->extended_buf[i]) { av_frame_unref(frame); @@ -265,7 +263,7 @@ FF_ENABLE_DEPRECATION_WARNINGS static int frame_copy_props(AVFrame *dst, const AVFrame *src, int force_copy) { - int ret, i; + int ret; dst->key_frame = src->key_frame; dst->pict_type = src->pict_type; @@ -318,7 +316,7 @@ FF_ENABLE_DEPRECATION_WARNINGS av_dict_copy(&dst->metadata, src->metadata, 0); - for (i = 0; i < src->nb_side_data; i++) { + for (int i = 0; i < src->nb_side_data; i++) { const AVFrameSideData *sd_src = src->side_data[i]; AVFrameSideData *sd_dst; if ( sd_src->type == AV_FRAME_DATA_PANSCAN @@ -351,7 +349,7 @@ FF_ENABLE_DEPRECATION_WARNINGS int av_frame_ref(AVFrame *dst, const AVFrame *src) { - int i, ret = 0; + int ret = 0; av_assert1(dst->width == 0 && dst->height == 0); #if FF_API_OLD_CHANNEL_LAYOUT @@ -406,7 +404,7 @@ FF_ENABLE_DEPRECATION_WARNINGS } /* ref the buffers */ - for (i = 0; i < FF_ARRAY_ELEMS(src->buf); i++) { + for (int i = 0; i < FF_ARRAY_ELEMS(src->buf); i++) { if (!src->buf[i]) continue; dst->buf[i] = av_buffer_ref(src->buf[i]); @@ -425,7 +423,7 @@ FF_ENABLE_DEPRECATION_WARNINGS } dst->nb_extended_buf = src->nb_extended_buf; - for (i = 0; i < src->nb_extended_buf; i++) { + for (int i = 0; i < src->nb_extended_buf; i++) { dst->extended_buf[i] = av_buffer_ref(src->extended_buf[i]); if (!dst->extended_buf[i]) { ret = AVERROR(ENOMEM); @@ -485,16 +483,14 @@ AVFrame *av_frame_clone(const AVFrame *src) void av_frame_unref(AVFrame *frame) { - int i; - if (!frame) return; wipe_side_data(frame); - for (i = 0; i < FF_ARRAY_ELEMS(frame->buf); i++) + for (int i = 0; i < FF_ARRAY_ELEMS(frame->buf); i++) av_buffer_unref(&frame->buf[i]); - for (i = 0; i < frame->nb_extended_buf; i++) + for (int i = 0; i < frame->nb_extended_buf; i++) av_buffer_unref(&frame->extended_buf[i]); av_freep(&frame->extended_buf); av_dict_free(&frame->metadata); @@ -531,16 +527,16 @@ FF_ENABLE_DEPRECATION_WARNINGS int av_frame_is_writable(AVFrame *frame) { - int i, ret = 1; + int ret = 1; /* assume non-refcounted frames are not writable */ if (!frame->buf[0]) return 0; - for (i = 0; i < FF_ARRAY_ELEMS(frame->buf); i++) + for (int i = 0; i < FF_ARRAY_ELEMS(frame->buf); i++) if (frame->buf[i]) ret &= !!av_buffer_is_writable(frame->buf[i]); - for (i = 0; i < frame->nb_extended_buf; i++) + for (int i = 0; i < frame->nb_extended_buf; i++) ret &= !!av_buffer_is_writable(frame->extended_buf[i]); return ret; @@ -607,7 +603,7 @@ int av_frame_copy_props(AVFrame *dst, const AVFrame *src) AVBufferRef *av_frame_get_plane_buffer(AVFrame *frame, int plane) { uint8_t *data; - int planes, i; + int planes; if (frame->nb_samples) { int channels = frame->ch_layout.nb_channels; @@ -630,12 +626,12 @@ FF_ENABLE_DEPRECATION_WARNINGS return NULL; data = frame->extended_data[plane]; - for (i = 0; i < FF_ARRAY_ELEMS(frame->buf) && frame->buf[i]; i++) { + for (int i = 0; i < FF_ARRAY_ELEMS(frame->buf) && frame->buf[i]; i++) { AVBufferRef *buf = frame->buf[i]; if (data >= buf->data && data < buf->data + buf->size) return buf; } - for (i = 0; i < frame->nb_extended_buf; i++) { + for (int i = 0; i < frame->nb_extended_buf; i++) { AVBufferRef *buf = frame->extended_buf[i]; if (data >= buf->data && data < buf->data + buf->size) return buf; @@ -690,9 +686,7 @@ AVFrameSideData *av_frame_new_side_data(AVFrame *frame, AVFrameSideData *av_frame_get_side_data(const AVFrame *frame, enum AVFrameSideDataType type) { - int i; - - for (i = 0; i < frame->nb_side_data; i++) { + for (int i = 0; i < frame->nb_side_data; i++) { if (frame->side_data[i]->type == type) return frame->side_data[i]; } @@ -702,7 +696,7 @@ AVFrameSideData *av_frame_get_side_data(const AVFrame *frame, static int frame_copy_video(AVFrame *dst, const AVFrame *src) { const uint8_t *src_data[4]; - int i, planes; + int planes; if (dst->width < src->width || dst->height < src->height) @@ -712,7 +706,7 @@ static int frame_copy_video(AVFrame *dst, const AVFrame *src) return av_hwframe_transfer_data(dst, src, 0); planes = av_pix_fmt_count_planes(dst->format); - for (i = 0; i < planes; i++) + for (int i = 0; i < planes; i++) if (!dst->data[i] || !src->data[i]) return AVERROR(EINVAL); @@ -729,7 +723,6 @@ static int frame_copy_audio(AVFrame *dst, const AVFrame *src) int planar = av_sample_fmt_is_planar(dst->format); int channels = dst->ch_layout.nb_channels; int planes = planar ? channels : 1; - int i; #if FF_API_OLD_CHANNEL_LAYOUT FF_DISABLE_DEPRECATION_WARNINGS @@ -757,7 +750,7 @@ FF_ENABLE_DEPRECATION_WARNINGS #endif return AVERROR(EINVAL); - for (i = 0; i < planes; i++) + for (int i = 0; i < planes; i++) if (!dst->extended_data[i] || !src->extended_data[i]) return AVERROR(EINVAL); @@ -789,9 +782,7 @@ FF_ENABLE_DEPRECATION_WARNINGS void av_frame_remove_side_data(AVFrame *frame, enum AVFrameSideDataType type) { - int i; - - for (i = frame->nb_side_data - 1; i >= 0; i--) { + for (int i = frame->nb_side_data - 1; i >= 0; i--) { AVFrameSideData *sd = frame->side_data[i]; if (sd->type == type) { free_side_data(&frame->side_data[i]); @@ -838,9 +829,7 @@ const char *av_frame_side_data_name(enum AVFrameSideDataType type) static int calc_cropping_offsets(size_t offsets[4], const AVFrame *frame, const AVPixFmtDescriptor *desc) { - int i, j; - - for (i = 0; frame->data[i]; i++) { + for (int i = 0; frame->data[i]; i++) { const AVComponentDescriptor *comp = NULL; int shift_x = (i == 1 || i == 2) ? desc->log2_chroma_w : 0; int shift_y = (i == 1 || i == 2) ? desc->log2_chroma_h : 0; @@ -851,7 +840,7 @@ static int calc_cropping_offsets(size_t offsets[4], const AVFrame *frame, } /* find any component descriptor for this plane */ - for (j = 0; j < desc->nb_components; j++) { + for (int j = 0; j < desc->nb_components; j++) { if (desc->comp[j].plane == i) { comp = &desc->comp[j]; break; @@ -871,7 +860,6 @@ int av_frame_apply_cropping(AVFrame *frame, int flags) { const AVPixFmtDescriptor *desc; size_t offsets[4]; - int i; if (!(frame->width > 0 && frame->height > 0)) return AVERROR(EINVAL); @@ -906,7 +894,7 @@ int av_frame_apply_cropping(AVFrame *frame, int flags) int log2_crop_align = frame->crop_left ? ff_ctz(frame->crop_left) : INT_MAX; int min_log2_align = INT_MAX; - for (i = 0; frame->data[i]; i++) { + for (int i = 0; frame->data[i]; i++) { int log2_align = offsets[i] ? ff_ctz(offsets[i]) : INT_MAX; min_log2_align = FFMIN(log2_align, min_log2_align); } @@ -922,7 +910,7 @@ int av_frame_apply_cropping(AVFrame *frame, int flags) } } - for (i = 0; frame->data[i]; i++) + for (int i = 0; frame->data[i]; i++) frame->data[i] += offsets[i]; frame->width -= (frame->crop_left + frame->crop_right); From b503b5a0cf80f38ecf4737c012b621b7e94f242a Mon Sep 17 00:00:00 2001 From: James Darnley Date: Mon, 20 Feb 2023 20:55:08 +0100 Subject: [PATCH 0469/2172] avfilter/bwdif: move filter_line init to a dedicated function --- libavfilter/bwdif.h | 3 ++- libavfilter/vf_bwdif.c | 13 +++++++++---- libavfilter/x86/vf_bwdif_init.c | 4 +--- 3 files changed, 12 insertions(+), 8 deletions(-) diff --git a/libavfilter/bwdif.h b/libavfilter/bwdif.h index 889ff772edd..5749345f784 100644 --- a/libavfilter/bwdif.h +++ b/libavfilter/bwdif.h @@ -37,6 +37,7 @@ typedef struct BWDIFContext { int parity, int clip_max, int spat); } BWDIFContext; -void ff_bwdif_init_x86(BWDIFContext *bwdif); +void ff_bwdif_init_filter_line(BWDIFContext *bwdif, int bit_depth); +void ff_bwdif_init_x86(BWDIFContext *bwdif, int bit_depth); #endif /* AVFILTER_BWDIF_H */ diff --git a/libavfilter/vf_bwdif.c b/libavfilter/vf_bwdif.c index 65c617ebb33..34e8c5e234e 100644 --- a/libavfilter/vf_bwdif.c +++ b/libavfilter/vf_bwdif.c @@ -340,7 +340,14 @@ static int config_props(AVFilterLink *link) yadif->csp = av_pix_fmt_desc_get(link->format); yadif->filter = filter; - if (yadif->csp->comp[0].depth > 8) { + ff_bwdif_init_filter_line(s, yadif->csp->comp[0].depth); + + return 0; +} + +av_cold void ff_bwdif_init_filter_line(BWDIFContext *s, int bit_depth) +{ + if (bit_depth > 8) { s->filter_intra = filter_intra_16bit; s->filter_line = filter_line_c_16bit; s->filter_edge = filter_edge_16bit; @@ -351,10 +358,8 @@ static int config_props(AVFilterLink *link) } #if ARCH_X86 - ff_bwdif_init_x86(s); + ff_bwdif_init_x86(s, bit_depth); #endif - - return 0; } diff --git a/libavfilter/x86/vf_bwdif_init.c b/libavfilter/x86/vf_bwdif_init.c index e24e5cd9b1c..ba7bc40c3d3 100644 --- a/libavfilter/x86/vf_bwdif_init.c +++ b/libavfilter/x86/vf_bwdif_init.c @@ -42,11 +42,9 @@ void ff_bwdif_filter_line_12bit_ssse3(void *dst, void *prev, void *cur, void *ne int mrefs2, int prefs3, int mrefs3, int prefs4, int mrefs4, int parity, int clip_max); -av_cold void ff_bwdif_init_x86(BWDIFContext *bwdif) +av_cold void ff_bwdif_init_x86(BWDIFContext *bwdif, int bit_depth) { - YADIFContext *yadif = &bwdif->yadif; int cpu_flags = av_get_cpu_flags(); - int bit_depth = (!yadif->csp) ? 8 : yadif->csp->comp[0].depth; if (bit_depth <= 8) { if (EXTERNAL_SSE2(cpu_flags)) From 087faf8cac51e5e20a5f41b36b8d4c2705a10039 Mon Sep 17 00:00:00 2001 From: James Darnley Date: Mon, 20 Feb 2023 20:55:08 +0100 Subject: [PATCH 0470/2172] checkasm: add test for bwdif --- tests/checkasm/Makefile | 1 + tests/checkasm/checkasm.c | 3 ++ tests/checkasm/checkasm.h | 1 + tests/checkasm/vf_bwdif.c | 84 +++++++++++++++++++++++++++++++++++++++ tests/fate/checkasm.mak | 1 + 5 files changed, 90 insertions(+) create mode 100644 tests/checkasm/vf_bwdif.c diff --git a/tests/checkasm/Makefile b/tests/checkasm/Makefile index a6f06c7007c..b6a43f181fc 100644 --- a/tests/checkasm/Makefile +++ b/tests/checkasm/Makefile @@ -40,6 +40,7 @@ CHECKASMOBJS-$(CONFIG_AVCODEC) += $(AVCODECOBJS-yes) # libavfilter tests AVFILTEROBJS-$(CONFIG_AFIR_FILTER) += af_afir.o AVFILTEROBJS-$(CONFIG_BLEND_FILTER) += vf_blend.o +AVFILTEROBJS-$(CONFIG_BWDIF_FILTER) += vf_bwdif.o AVFILTEROBJS-$(CONFIG_COLORSPACE_FILTER) += vf_colorspace.o AVFILTEROBJS-$(CONFIG_EQ_FILTER) += vf_eq.o AVFILTEROBJS-$(CONFIG_GBLUR_FILTER) += vf_gblur.o diff --git a/tests/checkasm/checkasm.c b/tests/checkasm/checkasm.c index e96d84a7dae..5e729cf0e01 100644 --- a/tests/checkasm/checkasm.c +++ b/tests/checkasm/checkasm.c @@ -179,6 +179,9 @@ static const struct { #if CONFIG_BLEND_FILTER { "vf_blend", checkasm_check_blend }, #endif + #if CONFIG_BWDIF_FILTER + { "vf_bwdif", checkasm_check_vf_bwdif }, + #endif #if CONFIG_COLORSPACE_FILTER { "vf_colorspace", checkasm_check_colorspace }, #endif diff --git a/tests/checkasm/checkasm.h b/tests/checkasm/checkasm.h index 8744a81218a..e9e73c6fa07 100644 --- a/tests/checkasm/checkasm.h +++ b/tests/checkasm/checkasm.h @@ -82,6 +82,7 @@ void checkasm_check_utvideodsp(void); void checkasm_check_v210dec(void); void checkasm_check_v210enc(void); void checkasm_check_vc1dsp(void); +void checkasm_check_vf_bwdif(void); void checkasm_check_vf_eq(void); void checkasm_check_vf_gblur(void); void checkasm_check_vf_hflip(void); diff --git a/tests/checkasm/vf_bwdif.c b/tests/checkasm/vf_bwdif.c new file mode 100644 index 00000000000..46224bb5757 --- /dev/null +++ b/tests/checkasm/vf_bwdif.c @@ -0,0 +1,84 @@ +/* + * 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 "checkasm.h" +#include "libavcodec/internal.h" +#include "libavfilter/bwdif.h" + +#define WIDTH 256 + +#define randomize_buffers(buf0, buf1, mask, count) \ + for (size_t i = 0; i < count; i++) \ + buf0[i] = buf1[i] = rnd() & mask + +#define BODY(type, depth) \ + do { \ + type prev0[9*WIDTH], prev1[9*WIDTH]; \ + type next0[9*WIDTH], next1[9*WIDTH]; \ + type cur0[9*WIDTH], cur1[9*WIDTH]; \ + type dst0[WIDTH], dst1[WIDTH]; \ + const int stride = WIDTH; \ + const int mask = (1< Date: Mon, 20 Mar 2023 15:52:07 +0100 Subject: [PATCH 0471/2172] tests: add bwdif to fate filter tests --- tests/fate/filter-video.mak | 9 +++++ tests/ref/fate/filter-bwdif-mode0 | 35 +++++++++++++++++ tests/ref/fate/filter-bwdif-mode1 | 64 +++++++++++++++++++++++++++++++ tests/ref/fate/filter-bwdif10 | 35 +++++++++++++++++ 4 files changed, 143 insertions(+) create mode 100644 tests/ref/fate/filter-bwdif-mode0 create mode 100644 tests/ref/fate/filter-bwdif-mode1 create mode 100644 tests/ref/fate/filter-bwdif10 diff --git a/tests/fate/filter-video.mak b/tests/fate/filter-video.mak index 444adc6be6a..c588286c38e 100644 --- a/tests/fate/filter-video.mak +++ b/tests/fate/filter-video.mak @@ -11,6 +11,15 @@ fate-filter-owdenoise-sample: CMP = oneoff FATE_FILTER_SAMPLES-$(call FILTERDEMDEC, PERMS DELOGO, RM, RV30) += fate-filter-delogo fate-filter-delogo: CMD = framecrc -i $(TARGET_SAMPLES)/real/rv30.rm -vf perms=random,delogo=show=0:x=290:y=25:w=26:h=16 -an +FATE_BWDIF-$(call FILTERDEMDEC, BWDIF, MPEGTS, MPEG2VIDEO) += fate-filter-bwdif-mode0 fate-filter-bwdif-mode1 +fate-filter-bwdif-mode0: CMD = framecrc -flags bitexact -idct simple -i $(TARGET_SAMPLES)/mpeg2/mpeg2_field_encoding.ts -frames:v 30 -vf bwdif=send_frame +fate-filter-bwdif-mode1: CMD = framecrc -flags bitexact -idct simple -i $(TARGET_SAMPLES)/mpeg2/mpeg2_field_encoding.ts -frames:v 59 -vf bwdif=send_field + +FATE_BWDIF-$(call FILTERDEMDEC, BWDIF SCALE, MPEGTS, MPEG2VIDEO) += fate-filter-bwdif10 +fate-filter-bwdif10: CMD = framecrc -flags bitexact -idct simple -i $(TARGET_SAMPLES)/mpeg2/mpeg2_field_encoding.ts -flags bitexact -pix_fmt yuv420p10le -frames:v 30 -vf scale,bwdif=0 + +FATE_FILTER_SAMPLES-yes += $(FATE_BWDIF-yes) + FATE_YADIF-$(call FILTERDEMDEC, YADIF, MPEGTS, MPEG2VIDEO) += fate-filter-yadif-mode0 fate-filter-yadif-mode1 fate-filter-yadif-mode0: CMD = framecrc -flags bitexact -idct simple -i $(TARGET_SAMPLES)/mpeg2/mpeg2_field_encoding.ts -frames:v 30 -vf yadif=0 fate-filter-yadif-mode1: CMD = framecrc -flags bitexact -idct simple -i $(TARGET_SAMPLES)/mpeg2/mpeg2_field_encoding.ts -frames:v 59 -vf yadif=1 diff --git a/tests/ref/fate/filter-bwdif-mode0 b/tests/ref/fate/filter-bwdif-mode0 new file mode 100644 index 00000000000..23dcaee9009 --- /dev/null +++ b/tests/ref/fate/filter-bwdif-mode0 @@ -0,0 +1,35 @@ +#tb 0: 1/25 +#media_type 0: video +#codec_id 0: rawvideo +#dimensions 0: 720x576 +#sar 0: 16/15 +0, 9, 9, 1, 622080, 0xd435648a +0, 10, 10, 1, 622080, 0x62085455 +0, 11, 11, 1, 622080, 0x60f943a0 +0, 12, 12, 1, 622080, 0x5396f14a +0, 13, 13, 1, 622080, 0x2df2ea4c +0, 14, 14, 1, 622080, 0x706af6eb +0, 15, 15, 1, 622080, 0x38f6f1c2 +0, 16, 16, 1, 622080, 0x6259b7a0 +0, 17, 17, 1, 622080, 0x056994e9 +0, 18, 18, 1, 622080, 0x34be703b +0, 19, 19, 1, 622080, 0x408de27c +0, 20, 20, 1, 622080, 0xdff42f6d +0, 21, 21, 1, 622080, 0x4c39202f +0, 22, 22, 1, 622080, 0x169beb1e +0, 23, 23, 1, 622080, 0xf5776ac0 +0, 24, 24, 1, 622080, 0xc66befc3 +0, 25, 25, 1, 622080, 0xa9ac8298 +0, 26, 26, 1, 622080, 0xbbfd898f +0, 27, 27, 1, 622080, 0x86e3b9af +0, 28, 28, 1, 622080, 0xeeb31455 +0, 29, 29, 1, 622080, 0x1819236d +0, 30, 30, 1, 622080, 0x414b01b0 +0, 31, 31, 1, 622080, 0x77e4b4f7 +0, 32, 32, 1, 622080, 0xf5683a8c +0, 33, 33, 1, 622080, 0xe8455a05 +0, 34, 34, 1, 622080, 0x2a03160d +0, 35, 35, 1, 622080, 0x9135bebc +0, 36, 36, 1, 622080, 0x9c1e1cf0 +0, 37, 37, 1, 622080, 0xd84e67c9 +0, 38, 38, 1, 622080, 0xfa864e1d diff --git a/tests/ref/fate/filter-bwdif-mode1 b/tests/ref/fate/filter-bwdif-mode1 new file mode 100644 index 00000000000..e8db88c932b --- /dev/null +++ b/tests/ref/fate/filter-bwdif-mode1 @@ -0,0 +1,64 @@ +#tb 0: 1/50 +#media_type 0: video +#codec_id 0: rawvideo +#dimensions 0: 720x576 +#sar 0: 16/15 +0, 18, 18, 1, 622080, 0xd435648a +0, 19, 19, 1, 622080, 0xef4617cc +0, 20, 20, 1, 622080, 0x62085455 +0, 21, 21, 1, 622080, 0x5b5ae735 +0, 22, 22, 1, 622080, 0x60f943a0 +0, 23, 23, 1, 622080, 0x80d2110e +0, 24, 24, 1, 622080, 0x5396f14a +0, 25, 25, 1, 622080, 0xb11be6b9 +0, 26, 26, 1, 622080, 0x2df2ea4c +0, 27, 27, 1, 622080, 0x402a7334 +0, 28, 28, 1, 622080, 0x706af6eb +0, 29, 29, 1, 622080, 0x4c506242 +0, 30, 30, 1, 622080, 0x38f6f1c2 +0, 31, 31, 1, 622080, 0x40ef0f29 +0, 32, 32, 1, 622080, 0x6259b7a0 +0, 33, 33, 1, 622080, 0xd7eba0ce +0, 34, 34, 1, 622080, 0x056994e9 +0, 35, 35, 1, 622080, 0xc06c5c99 +0, 36, 36, 1, 622080, 0x34be703b +0, 37, 37, 1, 622080, 0x18febe87 +0, 38, 38, 1, 622080, 0x408de27c +0, 39, 39, 1, 622080, 0x0cb0451f +0, 40, 40, 1, 622080, 0xdff42f6d +0, 41, 41, 1, 622080, 0x02416446 +0, 42, 42, 1, 622080, 0x4c39202f +0, 43, 43, 1, 622080, 0x84bb80c3 +0, 44, 44, 1, 622080, 0x169beb1e +0, 45, 45, 1, 622080, 0x60751ec3 +0, 46, 46, 1, 622080, 0xf5776ac0 +0, 47, 47, 1, 622080, 0xd8123d7b +0, 48, 48, 1, 622080, 0xc66befc3 +0, 49, 49, 1, 622080, 0x8ae04f9a +0, 50, 50, 1, 622080, 0xa9ac8298 +0, 51, 51, 1, 622080, 0xc6b1d464 +0, 52, 52, 1, 622080, 0xbbfd898f +0, 53, 53, 1, 622080, 0x264672da +0, 54, 54, 1, 622080, 0x86e3b9af +0, 55, 55, 1, 622080, 0x50795644 +0, 56, 56, 1, 622080, 0xeeb31455 +0, 57, 57, 1, 622080, 0xdfffdd20 +0, 58, 58, 1, 622080, 0x1819236d +0, 59, 59, 1, 622080, 0x739f3964 +0, 60, 60, 1, 622080, 0x414b01b0 +0, 61, 61, 1, 622080, 0xdf966fbf +0, 62, 62, 1, 622080, 0x77e4b4f7 +0, 63, 63, 1, 622080, 0x344f80cc +0, 64, 64, 1, 622080, 0xf5683a8c +0, 65, 65, 1, 622080, 0x4946b788 +0, 66, 66, 1, 622080, 0xe8455a05 +0, 67, 67, 1, 622080, 0xd0632a1e +0, 68, 68, 1, 622080, 0x2a03160d +0, 69, 69, 1, 622080, 0x7a234b71 +0, 70, 70, 1, 622080, 0x9135bebc +0, 71, 71, 1, 622080, 0x66c60582 +0, 72, 72, 1, 622080, 0x9c1e1cf0 +0, 73, 73, 1, 622080, 0x4a5ba0ef +0, 74, 74, 1, 622080, 0xd84e67c9 +0, 75, 75, 1, 622080, 0xdf9f4d83 +0, 76, 76, 1, 622080, 0xfa864e1d diff --git a/tests/ref/fate/filter-bwdif10 b/tests/ref/fate/filter-bwdif10 new file mode 100644 index 00000000000..85ce5438806 --- /dev/null +++ b/tests/ref/fate/filter-bwdif10 @@ -0,0 +1,35 @@ +#tb 0: 1/25 +#media_type 0: video +#codec_id 0: rawvideo +#dimensions 0: 720x576 +#sar 0: 16/15 +0, 9, 9, 1, 1244160, 0x57c21e2b +0, 10, 10, 1, 1244160, 0x57152296 +0, 11, 11, 1, 1244160, 0x0074598b +0, 12, 12, 1, 1244160, 0x44537bb8 +0, 13, 13, 1, 1244160, 0x6f27ab9c +0, 14, 14, 1, 1244160, 0x1f195e10 +0, 15, 15, 1, 1244160, 0xc5644298 +0, 16, 16, 1, 1244160, 0x24c1230e +0, 17, 17, 1, 1244160, 0x2651b213 +0, 18, 18, 1, 1244160, 0x88efe863 +0, 19, 19, 1, 1244160, 0x8bf0ada1 +0, 20, 20, 1, 1244160, 0x8b6c013a +0, 21, 21, 1, 1244160, 0x69ebc579 +0, 22, 22, 1, 1244160, 0xa45d0f0c +0, 23, 23, 1, 1244160, 0x272162e4 +0, 24, 24, 1, 1244160, 0x8c456817 +0, 25, 25, 1, 1244160, 0x872c58ee +0, 26, 26, 1, 1244160, 0x9318cb95 +0, 27, 27, 1, 1244160, 0xcaec95f1 +0, 28, 28, 1, 1244160, 0x8b01a105 +0, 29, 29, 1, 1244160, 0x956de85e +0, 30, 30, 1, 1244160, 0xa2998ab9 +0, 31, 31, 1, 1244160, 0xa56b5621 +0, 32, 32, 1, 1244160, 0x7bd6b161 +0, 33, 33, 1, 1244160, 0xbcb75d7a +0, 34, 34, 1, 1244160, 0xe5e94727 +0, 35, 35, 1, 1244160, 0xf3145c67 +0, 36, 36, 1, 1244160, 0xcf63df5a +0, 37, 37, 1, 1244160, 0x77d08ec8 +0, 38, 38, 1, 1244160, 0xc99d2eb2 From 073ec3b9da01f80fe5e9853fb2df9ce088fd5d0a Mon Sep 17 00:00:00 2001 From: James Darnley Date: Mon, 20 Feb 2023 20:55:08 +0100 Subject: [PATCH 0472/2172] avfilter/bwdif: add avx2 filter_line function MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 8-bit: 2.24x faster (1925±1.3 vs. 859±2.2 decicycles) compared with ssse3 10-bit: 2.00x faster (1703±1.7 vs. 853±2.0 decicycles) compared with ssse3 --- libavfilter/x86/vf_bwdif.asm | 29 ++++++++++++++++++++++++----- libavfilter/x86/vf_bwdif_init.c | 12 ++++++++++++ 2 files changed, 36 insertions(+), 5 deletions(-) diff --git a/libavfilter/x86/vf_bwdif.asm b/libavfilter/x86/vf_bwdif.asm index 0b453da53b3..c93b41ec488 100644 --- a/libavfilter/x86/vf_bwdif.asm +++ b/libavfilter/x86/vf_bwdif.asm @@ -26,18 +26,22 @@ %include "libavutil/x86/x86util.asm" -SECTION_RODATA +SECTION_RODATA 32 -pw_coefhf: times 4 dw 1016, 5570 -pw_coefhf1: times 8 dw -3801 -pw_coefsp: times 4 dw 5077, -981 -pw_splfdif: times 4 dw -768, 768 +pw_coefhf: times 8 dw 1016, 5570 +pw_coefhf1: times 16 dw -3801 +pw_coefsp: times 8 dw 5077, -981 +pw_splfdif: times 8 dw -768, 768 SECTION .text %macro LOAD8 2 + %if mmsize == 32 + pmovzxbw %1, %2 + %else movh %1, %2 punpcklbw %1, m7 + %endif %endmacro %macro LOAD12 2 @@ -45,8 +49,14 @@ SECTION .text %endmacro %macro DISP8 0 + %if mmsize == 32 + vextracti128 xm1, m2, 1 + packuswb xm2, xm1 + movu [dstq], xm2 + %else packuswb m2, m2 movh [dstq], m2 + %endif %endmacro %macro DISP12 0 @@ -244,8 +254,12 @@ cglobal bwdif_filter_line_12bit, 4, 9, 13, 0, dst, prev, cur, next, w, \ prefs, mrefs, prefs2, mrefs2, \ prefs3, mrefs3, prefs4, \ mrefs4, parity, clip_max + %if mmsize == 32 + vpbroadcastw m12, WORD clip_maxm + %else movd m12, DWORD clip_maxm SPLATW m12, m12, 0 + %endif %else cglobal bwdif_filter_line_12bit, 4, 6, 8, 80, dst, prev, cur, next, w, \ prefs, mrefs, prefs2, mrefs2, \ @@ -264,3 +278,8 @@ INIT_XMM ssse3 BWDIF INIT_XMM sse2 BWDIF + +%if HAVE_AVX2_EXTERNAL && ARCH_X86_64 +INIT_YMM avx2 +BWDIF +%endif diff --git a/libavfilter/x86/vf_bwdif_init.c b/libavfilter/x86/vf_bwdif_init.c index ba7bc40c3d3..f833318c100 100644 --- a/libavfilter/x86/vf_bwdif_init.c +++ b/libavfilter/x86/vf_bwdif_init.c @@ -32,6 +32,10 @@ void ff_bwdif_filter_line_ssse3(void *dst, void *prev, void *cur, void *next, int w, int prefs, int mrefs, int prefs2, int mrefs2, int prefs3, int mrefs3, int prefs4, int mrefs4, int parity, int clip_max); +void ff_bwdif_filter_line_avx2(void *dst, void *prev, void *cur, void *next, + int w, int prefs, int mrefs, int prefs2, + int mrefs2, int prefs3, int mrefs3, int prefs4, + int mrefs4, int parity, int clip_max); void ff_bwdif_filter_line_12bit_sse2(void *dst, void *prev, void *cur, void *next, int w, int prefs, int mrefs, int prefs2, @@ -41,6 +45,10 @@ void ff_bwdif_filter_line_12bit_ssse3(void *dst, void *prev, void *cur, void *ne int w, int prefs, int mrefs, int prefs2, int mrefs2, int prefs3, int mrefs3, int prefs4, int mrefs4, int parity, int clip_max); +void ff_bwdif_filter_line_12bit_avx2(void *dst, void *prev, void *cur, void *next, + int w, int prefs, int mrefs, int prefs2, + int mrefs2, int prefs3, int mrefs3, int prefs4, + int mrefs4, int parity, int clip_max); av_cold void ff_bwdif_init_x86(BWDIFContext *bwdif, int bit_depth) { @@ -51,10 +59,14 @@ av_cold void ff_bwdif_init_x86(BWDIFContext *bwdif, int bit_depth) bwdif->filter_line = ff_bwdif_filter_line_sse2; if (EXTERNAL_SSSE3(cpu_flags)) bwdif->filter_line = ff_bwdif_filter_line_ssse3; + if (ARCH_X86_64 && EXTERNAL_AVX2(cpu_flags)) + bwdif->filter_line = ff_bwdif_filter_line_avx2; } else if (bit_depth <= 12) { if (EXTERNAL_SSE2(cpu_flags)) bwdif->filter_line = ff_bwdif_filter_line_12bit_sse2; if (EXTERNAL_SSSE3(cpu_flags)) bwdif->filter_line = ff_bwdif_filter_line_12bit_ssse3; + if (ARCH_X86_64 && EXTERNAL_AVX2(cpu_flags)) + bwdif->filter_line = ff_bwdif_filter_line_12bit_avx2; } } From 9a23d8d894907dab4e8ae4a0818c6f983d3b64f2 Mon Sep 17 00:00:00 2001 From: Jun Zhao Date: Sat, 4 Mar 2023 18:53:32 +0800 Subject: [PATCH 0473/2172] lavfi/Makefile: fix make checkheaders fail Add stack_internal.h to the list of skipped headers to fix make checkheaders fail, it's introduced by commit 742dfa281 Signed-off-by: Jun Zhao --- libavfilter/Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libavfilter/Makefile b/libavfilter/Makefile index b3d3d981dd4..71e198bbf9c 100644 --- a/libavfilter/Makefile +++ b/libavfilter/Makefile @@ -627,9 +627,9 @@ SHLIBOBJS-$(HAVE_GNU_WINDRES) += avfilterres.o SKIPHEADERS-$(CONFIG_LCMS2) += fflcms2.h SKIPHEADERS-$(CONFIG_LIBVIDSTAB) += vidstabutils.h -SKIPHEADERS-$(CONFIG_QSVVPP) += qsvvpp.h +SKIPHEADERS-$(CONFIG_QSVVPP) += qsvvpp.h stack_internal.h SKIPHEADERS-$(CONFIG_OPENCL) += opencl.h -SKIPHEADERS-$(CONFIG_VAAPI) += vaapi_vpp.h +SKIPHEADERS-$(CONFIG_VAAPI) += vaapi_vpp.h stack_internal.h SKIPHEADERS-$(CONFIG_VULKAN) += vulkan.h vulkan_filter.h TOOLS = graph2dot From a53bb071fee72bf297e788fdb26565ca1b5668de Mon Sep 17 00:00:00 2001 From: Jun Zhao Date: Tue, 7 Mar 2023 07:36:19 +0800 Subject: [PATCH 0474/2172] lavf/mpeg: Add G.711 A law support Add G.711 A law support Signed-off-by: Jun Zhao --- libavformat/mpeg.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/libavformat/mpeg.c b/libavformat/mpeg.c index 864b08d8f8b..781c3162d6d 100644 --- a/libavformat/mpeg.c +++ b/libavformat/mpeg.c @@ -549,6 +549,9 @@ static int mpegps_read_packet(AVFormatContext *s, } else if (es_type == STREAM_TYPE_AUDIO_AC3) { codec_id = AV_CODEC_ID_AC3; type = AVMEDIA_TYPE_AUDIO; + } else if (es_type == 0x90) { + codec_id = AV_CODEC_ID_PCM_ALAW; + type = AVMEDIA_TYPE_AUDIO; } else if (m->imkh_cctv && es_type == 0x91) { codec_id = AV_CODEC_ID_PCM_MULAW; type = AVMEDIA_TYPE_AUDIO; From aca8ceb870b0d3c6d126f165f04322ad569671a4 Mon Sep 17 00:00:00 2001 From: James Almer Date: Sat, 25 Mar 2023 09:30:52 -0300 Subject: [PATCH 0475/2172] x86/vf_bwdif_init: limit AVX2 functions using 256bit vectors to cpus known to be fast with it Signed-off-by: James Almer --- libavfilter/x86/vf_bwdif_init.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libavfilter/x86/vf_bwdif_init.c b/libavfilter/x86/vf_bwdif_init.c index f833318c100..57f908a8efb 100644 --- a/libavfilter/x86/vf_bwdif_init.c +++ b/libavfilter/x86/vf_bwdif_init.c @@ -59,14 +59,14 @@ av_cold void ff_bwdif_init_x86(BWDIFContext *bwdif, int bit_depth) bwdif->filter_line = ff_bwdif_filter_line_sse2; if (EXTERNAL_SSSE3(cpu_flags)) bwdif->filter_line = ff_bwdif_filter_line_ssse3; - if (ARCH_X86_64 && EXTERNAL_AVX2(cpu_flags)) + if (ARCH_X86_64 && EXTERNAL_AVX2_FAST(cpu_flags)) bwdif->filter_line = ff_bwdif_filter_line_avx2; } else if (bit_depth <= 12) { if (EXTERNAL_SSE2(cpu_flags)) bwdif->filter_line = ff_bwdif_filter_line_12bit_sse2; if (EXTERNAL_SSSE3(cpu_flags)) bwdif->filter_line = ff_bwdif_filter_line_12bit_ssse3; - if (ARCH_X86_64 && EXTERNAL_AVX2(cpu_flags)) + if (ARCH_X86_64 && EXTERNAL_AVX2_FAST(cpu_flags)) bwdif->filter_line = ff_bwdif_filter_line_12bit_avx2; } } From 6ee6dd93eb68605914eed32b69142f87967c1f3f Mon Sep 17 00:00:00 2001 From: James Almer Date: Sat, 25 Mar 2023 09:07:22 -0300 Subject: [PATCH 0476/2172] fftools/ffprobe: add support for HDR10+ packet side data Signed-off-by: James Almer --- fftools/ffprobe.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/fftools/ffprobe.c b/fftools/ffprobe.c index 95dda97edcd..561b514f0b3 100644 --- a/fftools/ffprobe.c +++ b/fftools/ffprobe.c @@ -2360,6 +2360,9 @@ static void print_pkt_side_data(WriterContext *w, AVContentLightMetadata *metadata = (AVContentLightMetadata *)sd->data; print_int("max_content", metadata->MaxCLL); print_int("max_average", metadata->MaxFALL); + } else if (sd->type == AV_PKT_DATA_DYNAMIC_HDR10_PLUS) { + AVDynamicHDRPlus *metadata = (AVDynamicHDRPlus *)sd->data; + print_dynamic_hdr10_plus(w, metadata); } else if (sd->type == AV_PKT_DATA_DOVI_CONF) { AVDOVIDecoderConfigurationRecord *dovi = (AVDOVIDecoderConfigurationRecord *)sd->data; print_int("dv_version_major", dovi->dv_version_major); From 0fbae2178b4ffda298b10473aa6fe17ef524eff9 Mon Sep 17 00:00:00 2001 From: Jerome Martinez Date: Tue, 14 Mar 2023 09:49:16 +0100 Subject: [PATCH 0477/2172] avformat/mxfenc: SMPTE RDD 48:2018 Amd 1:2022 support --- libavformat/Makefile | 3 +- libavformat/mxfenc.c | 163 +++++++++++++++++++++++++++++++++- libavformat/rangecoder_dec.c | 1 + tests/fate/lavf-container.mak | 2 + tests/ref/lavf/mxf_ffv1 | 3 + 5 files changed, 169 insertions(+), 3 deletions(-) create mode 100644 libavformat/rangecoder_dec.c create mode 100644 tests/ref/lavf/mxf_ffv1 diff --git a/libavformat/Makefile b/libavformat/Makefile index 47bbbbfb2a9..048649689b1 100644 --- a/libavformat/Makefile +++ b/libavformat/Makefile @@ -712,7 +712,8 @@ 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_MXF_MUXER) += golomb_tab.o \ + rangecoder_dec.o SHLIBOBJS-$(CONFIG_NUT_MUXER) += mpegaudiotabs.o SHLIBOBJS-$(CONFIG_RTPDEC) += jpegtables.o SHLIBOBJS-$(CONFIG_RTP_MUXER) += golomb_tab.o jpegtables.o \ diff --git a/libavformat/mxfenc.c b/libavformat/mxfenc.c index a29d678098c..d83908ec0e3 100644 --- a/libavformat/mxfenc.c +++ b/libavformat/mxfenc.c @@ -51,6 +51,7 @@ #include "libavcodec/golomb.h" #include "libavcodec/h264.h" #include "libavcodec/packet_internal.h" +#include "libavcodec/rangecoder.h" #include "libavcodec/startcode.h" #include "avformat.h" #include "avio_internal.h" @@ -102,6 +103,7 @@ typedef struct MXFStreamContext { int b_picture_count; ///< maximum number of consecutive b pictures, used in mpeg-2 descriptor int low_delay; ///< low delay, used in mpeg-2 descriptor int avc_intra; + int micro_version; ///< format micro_version, used in ffv1 descriptor } MXFStreamContext; typedef struct MXFContainerEssenceEntry { @@ -130,6 +132,7 @@ enum ULIndex { INDEX_H264, INDEX_S436M, INDEX_PRORES, + INDEX_FFV1, }; static const struct { @@ -144,6 +147,7 @@ static const struct { { AV_CODEC_ID_JPEG2000, INDEX_JPEG2000 }, { AV_CODEC_ID_H264, INDEX_H264 }, { AV_CODEC_ID_PRORES, INDEX_PRORES }, + { AV_CODEC_ID_FFV1, INDEX_FFV1 }, { AV_CODEC_ID_NONE } }; @@ -151,6 +155,7 @@ static void mxf_write_wav_desc(AVFormatContext *s, AVStream *st); static void mxf_write_aes3_desc(AVFormatContext *s, AVStream *st); static void mxf_write_mpegvideo_desc(AVFormatContext *s, AVStream *st); static void mxf_write_h264_desc(AVFormatContext *s, AVStream *st); +static void mxf_write_ffv1_desc(AVFormatContext *s, AVStream *st); static void mxf_write_cdci_desc(AVFormatContext *s, AVStream *st); static void mxf_write_generic_sound_desc(AVFormatContext *s, AVStream *st); static void mxf_write_s436m_anc_desc(AVFormatContext *s, AVStream *st); @@ -208,6 +213,11 @@ static const MXFContainerEssenceEntry mxf_essence_container_uls[] = { { 0x06,0x0E,0x2B,0x34,0x01,0x02,0x01,0x01,0x0d,0x01,0x03,0x01,0x15,0x01,0x17,0x00 }, { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0d,0x04,0x01,0x02,0x02,0x03,0x06,0x03,0x00 }, mxf_write_cdci_desc }, + // FFV1 + { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0d,0x0d,0x01,0x03,0x01,0x02,0x23,0x01,0x00 }, + { 0x06,0x0E,0x2B,0x34,0x01,0x02,0x01,0x01,0x0d,0x01,0x03,0x01,0x15,0x01,0x1d,0x00 }, + { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0d,0x04,0x01,0x02,0x02,0x03,0x09,0x00,0x00 }, + mxf_write_ffv1_desc }, { { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, @@ -232,6 +242,15 @@ static const UID mxf_d10_container_uls[] = { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x01,0x0D,0x01,0x03,0x01,0x02,0x01,0x06,0x01 }, // D-10 525/50 NTSC 30mb/s }; + +static const UID mxf_ffv1_codec_uls[] = { + { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x0D,0x04,0x01,0x02,0x02,0x03,0x09,0x01,0x00 }, // FFV1 version 0 + { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x0D,0x04,0x01,0x02,0x02,0x03,0x09,0x02,0x00 }, // FFV1 version 1 + { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x0D,0x04,0x01,0x02,0x02,0x03,0x09,0x03,0x00 }, // FFV1 version 2 (was only experimental) + { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x0D,0x04,0x01,0x02,0x02,0x03,0x09,0x04,0x00 }, // FFV1 version 3 + { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x0D,0x04,0x01,0x02,0x02,0x03,0x09,0x05,0x00 }, // FFV1 version 4 +}; + static const uint8_t product_uid[] = { 0xAD,0xAB,0x44,0x24,0x2f,0x25,0x4d,0xc7,0x92,0xff,0x29,0xbd,0x00,0x0c,0x00,0x02}; static const uint8_t uuid_base[] = { 0xAD,0xAB,0x44,0x24,0x2f,0x25,0x4d,0xc7,0x92,0xff }; static const uint8_t umid_ul[] = { 0x06,0x0A,0x2B,0x34,0x01,0x01,0x01,0x05,0x01,0x01,0x0D,0x00,0x13 }; @@ -390,6 +409,10 @@ static const MXFLocalTagPair mxf_local_tag_batch[] = { { 0x8302, FF_MXF_MasteringDisplayWhitePointChromaticity }, { 0x8303, FF_MXF_MasteringDisplayMaximumLuminance }, { 0x8304, FF_MXF_MasteringDisplayMinimumLuminance }, + // FFV1 + { 0xDFD9, {0x06,0x0E,0x2B,0x34,0x01,0x01,0x01,0x0E,0x04,0x01,0x06,0x0C,0x06,0x00,0x00,0x00}}, /* FFV1 Micro-version */ + { 0xDFDA, {0x06,0x0E,0x2B,0x34,0x01,0x01,0x01,0x0E,0x04,0x01,0x06,0x0C,0x05,0x00,0x00,0x00}}, /* FFV1 Version */ + { 0xDFDB, {0x06,0x0E,0x2B,0x34,0x01,0x01,0x01,0x0E,0x04,0x01,0x06,0x0C,0x01,0x00,0x00,0x00}}, /* FFV1 Initialization Metadata */ }; #define MXF_NUM_TAGS FF_ARRAY_ELEMS(mxf_local_tag_batch) @@ -526,7 +549,7 @@ static void mxf_write_primer_pack(AVFormatContext *s) MXFContext *mxf = s->priv_data; AVIOContext *pb = s->pb; int local_tag_number = MXF_NUM_TAGS, i; - int will_have_avc_tags = 0, will_have_mastering_tags = 0; + int will_have_avc_tags = 0, will_have_mastering_tags = 0, will_have_ffv1_tags = 0; for (i = 0; i < s->nb_streams; i++) { MXFStreamContext *sc = s->streams[i]->priv_data; @@ -536,6 +559,9 @@ static void mxf_write_primer_pack(AVFormatContext *s) if (av_stream_get_side_data(s->streams[i], AV_PKT_DATA_MASTERING_DISPLAY_METADATA, NULL)) { will_have_mastering_tags = 1; } + if (s->streams[i]->codecpar->codec_id == AV_CODEC_ID_FFV1) { + will_have_ffv1_tags = 1; + } } if (!mxf->store_user_comments) { @@ -544,8 +570,11 @@ static void mxf_write_primer_pack(AVFormatContext *s) mxf_mark_tag_unused(mxf, 0x5003); } - if (!will_have_avc_tags) { + if (!will_have_avc_tags && !will_have_ffv1_tags) { mxf_mark_tag_unused(mxf, 0x8100); + } + + if (!will_have_avc_tags) { mxf_mark_tag_unused(mxf, 0x8200); mxf_mark_tag_unused(mxf, 0x8201); mxf_mark_tag_unused(mxf, 0x8202); @@ -558,6 +587,12 @@ static void mxf_write_primer_pack(AVFormatContext *s) mxf_mark_tag_unused(mxf, 0x8304); } + if (!will_have_ffv1_tags) { + mxf_mark_tag_unused(mxf, 0xDFD9); + mxf_mark_tag_unused(mxf, 0xDFDA); + mxf_mark_tag_unused(mxf, 0xDFDB); + } + for (i = 0; i < MXF_NUM_TAGS; i++) { if (mxf->unused_tags[i]) { local_tag_number--; @@ -1094,9 +1129,11 @@ static const UID mxf_mpegvideo_descriptor_key = { 0x06,0x0E,0x2B,0x34,0x02,0x53, static const UID mxf_wav_descriptor_key = { 0x06,0x0E,0x2B,0x34,0x02,0x53,0x01,0x01,0x0d,0x01,0x01,0x01,0x01,0x01,0x48,0x00 }; static const UID mxf_aes3_descriptor_key = { 0x06,0x0E,0x2B,0x34,0x02,0x53,0x01,0x01,0x0d,0x01,0x01,0x01,0x01,0x01,0x47,0x00 }; static const UID mxf_cdci_descriptor_key = { 0x06,0x0E,0x2B,0x34,0x02,0x53,0x01,0x01,0x0D,0x01,0x01,0x01,0x01,0x01,0x28,0x00 }; +static const UID mxf_rgba_descriptor_key = { 0x06,0x0E,0x2B,0x34,0x02,0x53,0x01,0x01,0x0D,0x01,0x01,0x01,0x01,0x01,0x29,0x00 }; static const UID mxf_generic_sound_descriptor_key = { 0x06,0x0E,0x2B,0x34,0x02,0x53,0x01,0x01,0x0D,0x01,0x01,0x01,0x01,0x01,0x42,0x00 }; static const UID mxf_avc_subdescriptor_key = { 0x06,0x0E,0x2B,0x34,0x02,0x53,0x01,0x01,0x0d,0x01,0x01,0x01,0x01,0x01,0x6E,0x00 }; +static const UID mxf_ffv1_subdescriptor_key = { 0x06,0x0E,0x2B,0x34,0x02,0x53,0x01,0x01,0x0d,0x01,0x01,0x01,0x01,0x01,0x81,0x03 }; static inline uint16_t rescale_mastering_chroma(AVRational q) { @@ -1198,6 +1235,7 @@ static int64_t mxf_write_cdci_common(AVFormatContext *s, AVStream *st, const UID avio_wb32(pb, -((st->codecpar->height - display_height)&1)); } + if (key != mxf_rgba_descriptor_key) { // component depth mxf_write_local_tag(s, 4, 0x3301); avio_wb32(pb, sc->component_depth); @@ -1234,6 +1272,7 @@ static int64_t mxf_write_cdci_common(AVFormatContext *s, AVStream *st, const UID mxf_write_local_tag(s, 4, 0x3306); avio_wb32(pb, color); } + } // if (key != mxf_rgba_descriptor_key) if (sc->signal_standard) { mxf_write_local_tag(s, 1, 0x3215); @@ -1329,6 +1368,13 @@ static int64_t mxf_write_cdci_common(AVFormatContext *s, AVStream *st, const UID mxf_write_uuid(pb, AVCSubDescriptor, 0); } + if (st->codecpar->codec_id == AV_CODEC_ID_FFV1) { + // write ffv1 sub descriptor ref + mxf_write_local_tag(s, 8 + 16, 0x8100); + mxf_write_refs_count(pb, 1); + mxf_write_uuid(pb, FFV1SubDescriptor, 0); + } + return pos; } @@ -1387,6 +1433,47 @@ static void mxf_write_h264_desc(AVFormatContext *s, AVStream *st) } } +static void mxf_write_ffv1_subdesc(AVFormatContext *s, AVStream *st) +{ + AVIOContext *pb = s->pb; + MXFStreamContext *sc = st->priv_data; + int64_t pos; + + avio_write(pb, mxf_ffv1_subdescriptor_key, 16); + klv_encode_ber4_length(pb, 0); + pos = avio_tell(pb); + + mxf_write_local_tag(s, 16, 0x3C0A); + mxf_write_uuid(pb, FFV1SubDescriptor, 0); + + if (st->codecpar->extradata_size) { + mxf_write_local_tag(s, st->codecpar->extradata_size, 0xDFDB); + avio_write(pb, st->codecpar->extradata, st->codecpar->extradata_size); // FFV1InitializationMetadata + } + + mxf_write_local_tag(s, 2, 0xDFDA); + avio_wb16(pb, (*sc->codec_ul)[14]); // FFV1Version + + if (st->codecpar->extradata_size) { + mxf_write_local_tag(s, 2, 0xDFD9); + avio_wb16(pb, sc->micro_version); // FFV1MicroVersion + } + + mxf_update_klv_size(s->pb, pos); +} + +static void mxf_write_ffv1_desc(AVFormatContext *s, AVStream *st) +{ + int is_rgb, pos; + const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(st->codecpar->format); + av_assert0(desc); + is_rgb = desc->flags & AV_PIX_FMT_FLAG_RGB; + + pos = mxf_write_cdci_common(s, st, is_rgb ? mxf_rgba_descriptor_key : mxf_cdci_descriptor_key); + mxf_update_klv_size(s->pb, pos); + mxf_write_ffv1_subdesc(s, st); +} + static void mxf_write_s436m_anc_desc(AVFormatContext *s, AVStream *st) { int64_t pos = mxf_write_generic_desc(s, st, mxf_s436m_anc_descriptor_key); @@ -2347,6 +2434,73 @@ static int mxf_parse_h264_frame(AVFormatContext *s, AVStream *st, return 1; } +static inline int get_ffv1_unsigned_symbol(RangeCoder *c, uint8_t *state) { + if(get_rac(c, state+0)) + return 0; + else{ + int i, e; + unsigned a; + e= 0; + while(get_rac(c, state+1 + FFMIN(e,9))){ //1..10 + e++; + if (e > 31) + return AVERROR_INVALIDDATA; + } + + a= 1; + for(i=e-1; i>=0; i--){ + a += a + get_rac(c, state+22 + FFMIN(i,9)); //22..31 + } + + return a; + } +} +#define FFV1_CONTEXT_SIZE 32 +static int mxf_parse_ffv1_frame(AVFormatContext *s, AVStream *st, AVPacket *pkt) +{ + MXFContext *mxf = s->priv_data; + MXFStreamContext *sc = st->priv_data; + uint8_t state[FFV1_CONTEXT_SIZE]; + RangeCoder c; + unsigned v; + + sc->frame_size = pkt->size; + + if (mxf->header_written) + return 1; + + memset(state, 128, sizeof(state)); + if (st->codecpar->extradata) { + ff_init_range_decoder(&c, st->codecpar->extradata, st->codecpar->extradata_size); + ff_build_rac_states(&c, 0.05 * (1LL << 32), 256 - 8); + v = get_ffv1_unsigned_symbol(&c, state); + av_assert0(v >= 2); + if (v > 4) { + return 0; + } + sc->micro_version = get_ffv1_unsigned_symbol(&c, state); + } else { + uint8_t keystate = 128; + ff_init_range_decoder(&c, pkt->data, pkt->size); + ff_build_rac_states(&c, 0.05 * (1LL << 32), 256 - 8); + get_rac(&c, &keystate); // keyframe + v = get_ffv1_unsigned_symbol(&c, state); + av_assert0(v < 2); + } + sc->codec_ul = &mxf_ffv1_codec_uls[v]; + + if (st->codecpar->field_order > AV_FIELD_PROGRESSIVE) { + sc->interlaced = 1; + sc->field_dominance = st->codecpar->field_order == (st->codecpar->field_order == AV_FIELD_TT || st->codecpar->field_order == AV_FIELD_TB) ? 1 : 2; + } + sc->aspect_ratio.num = st->codecpar->width * st->codecpar->sample_aspect_ratio.num; + sc->aspect_ratio.den = st->codecpar->height * st->codecpar->sample_aspect_ratio.den; + av_reduce(&sc->aspect_ratio.num, &sc->aspect_ratio.den, + sc->aspect_ratio.num, sc->aspect_ratio.den, INT_MAX); + + return 1; +} + static const UID mxf_mpeg2_codec_uls[] = { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x03,0x04,0x01,0x02,0x02,0x01,0x01,0x10,0x00 }, // MP-ML I-Frame { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x03,0x04,0x01,0x02,0x02,0x01,0x01,0x11,0x00 }, // MP-ML Long GOP @@ -2958,6 +3112,11 @@ static int mxf_write_packet(AVFormatContext *s, AVPacket *pkt) av_log(s, AV_LOG_ERROR, "could not get h264 profile\n"); return -1; } + } else if (st->codecpar->codec_id == AV_CODEC_ID_FFV1) { + if (!mxf_parse_ffv1_frame(s, st, pkt)) { + av_log(s, AV_LOG_ERROR, "could not get ffv1 version\n"); + return -1; + } } if (mxf->cbr_index) { diff --git a/libavformat/rangecoder_dec.c b/libavformat/rangecoder_dec.c new file mode 100644 index 00000000000..7b727f656e5 --- /dev/null +++ b/libavformat/rangecoder_dec.c @@ -0,0 +1 @@ +#include "libavcodec/rangecoder.c" diff --git a/tests/fate/lavf-container.mak b/tests/fate/lavf-container.mak index 4bf7636b56c..214ad6fc0d7 100644 --- a/tests/fate/lavf-container.mak +++ b/tests/fate/lavf-container.mak @@ -8,6 +8,7 @@ FATE_LAVF_CONTAINER-$(call ENCDEC2, MPEG4, MP2, MATROSKA) + FATE_LAVF_CONTAINER-$(call ENCDEC2, MPEG4, PCM_ALAW, MOV) += mov mov_rtphint ismv FATE_LAVF_CONTAINER-$(call ENCDEC, MPEG4, MOV) += mp4 FATE_LAVF_CONTAINER-$(call ENCDEC2, MPEG1VIDEO, MP2, MPEG1SYSTEM MPEGPS) += mpg +FATE_LAVF_CONTAINER-$(call ENCDEC , FFV1, MXF) += mxf_ffv1 FATE_LAVF_CONTAINER-$(call ENCDEC2, MPEG2VIDEO, PCM_S16LE, MXF) += mxf mxf_dv25 mxf_dvcpro50 FATE_LAVF_CONTAINER-$(call ENCDEC2, MPEG2VIDEO, PCM_S16LE, MXF_D10 MXF) += mxf_d10 FATE_LAVF_CONTAINER-$(call ENCDEC2, DNXHD, PCM_S16LE, MXF_OPATOM MXF) += mxf_opatom mxf_opatom_audio @@ -55,6 +56,7 @@ fate-lavf-mxf: CMD = lavf_container_timecode "-ar 48000 -bf 2 -threads 1" fate-lavf-mxf_d10: CMD = lavf_container "-ar 48000 -ac 2" "-r 25 -vf scale=720:576,pad=720:608:0:32 -c:v mpeg2video -g 0 -flags +ildct+low_delay -dc 10 -non_linear_quant 1 -intra_vlc 1 -qscale 1 -ps 1 -qmin 1 -rc_max_vbv_use 1 -rc_min_vbv_use 1 -pix_fmt yuv422p -minrate 30000k -maxrate 30000k -b 30000k -bufsize 1200000 -top 1 -rc_init_occupancy 1200000 -qmax 12 -f mxf_d10" fate-lavf-mxf_dv25: CMD = lavf_container "-ar 48000 -ac 2" "-r 25 -vf scale=720:576,setdar=4/3 -c:v dvvideo -pix_fmt yuv420p -b 25000k -top 0 -f mxf" fate-lavf-mxf_dvcpro50: CMD = lavf_container "-ar 48000 -ac 2" "-r 25 -vf scale=720:576,setdar=16/9 -c:v dvvideo -pix_fmt yuv422p -b 50000k -top 0 -f mxf" +fate-lavf-mxf_ffv1: CMD = lavf_container "-an" "-r 25 -vf scale=720:576,setdar=4/3 -c:v ffv1 -level 3 -pix_fmt yuv420p -f mxf" fate-lavf-mxf_opatom: CMD = lavf_container "" "-s 1920x1080 -c:v dnxhd -pix_fmt yuv422p -vb 36M -f mxf_opatom -map 0" fate-lavf-mxf_opatom_audio: CMD = lavf_container "-ar 48000 -ac 1" "-f mxf_opatom -mxf_audio_edit_rate 25 -map 1" fate-lavf-smjpeg: CMD = lavf_container "" "-f smjpeg" diff --git a/tests/ref/lavf/mxf_ffv1 b/tests/ref/lavf/mxf_ffv1 new file mode 100644 index 00000000000..b89e6a214e7 --- /dev/null +++ b/tests/ref/lavf/mxf_ffv1 @@ -0,0 +1,3 @@ +0426b93bbf06aedf083f00cd4ebaf36f *tests/data/lavf/lavf.mxf_ffv1 +5587001 tests/data/lavf/lavf.mxf_ffv1 +tests/data/lavf/lavf.mxf_ffv1 CRC=0x02354cdc From 653ee3f159411a1b97c19b96393a39f29569ed99 Mon Sep 17 00:00:00 2001 From: Thilo Borgmann Date: Wed, 15 Mar 2023 19:30:37 +0100 Subject: [PATCH 0478/2172] fftools/ffmpeg_mux_init: Use all metadata selectors if none is specified. Fixes regression from 3c7dd5ed37da6d2de06c4850de5a319ca9cdd47f. Fixes ticket #10157. --- fftools/ffmpeg_mux_init.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/fftools/ffmpeg_mux_init.c b/fftools/ffmpeg_mux_init.c index 09d24ba8e5b..bfe2abbe0b0 100644 --- a/fftools/ffmpeg_mux_init.c +++ b/fftools/ffmpeg_mux_init.c @@ -1819,11 +1819,11 @@ static int copy_metadata(Muxer *mux, AVFormatContext *ic, parse_meta_type(mux, inspec, &type_in, &idx_in, &istream_spec); parse_meta_type(mux, outspec, &type_out, &idx_out, &ostream_spec); - if (type_in == 'g' || type_out == 'g') + if (type_in == 'g' || type_out == 'g' || !*outspec) *metadata_global_manual = 1; - if (type_in == 's' || type_out == 's') + if (type_in == 's' || type_out == 's' || !*outspec) *metadata_streams_manual = 1; - if (type_in == 'c' || type_out == 'c') + if (type_in == 'c' || type_out == 'c' || !*outspec) *metadata_chapters_manual = 1; /* ic is NULL when just disabling automatic mappings */ From 5ffe18bcea9fcb1b3c816b8faeffcb17ca4b2669 Mon Sep 17 00:00:00 2001 From: Junxian Zhu Date: Thu, 1 Dec 2022 15:00:06 +0800 Subject: [PATCH 0479/2172] mips: fix build fail on MIPS R6 Add macro define to avoid causing build fail with incompatible assembler code on MIPS R6. Signed-off-by: Junxian Zhu Reviewed-by: Shiyou Yin Signed-off-by: Michael Niedermayer --- libavcodec/mips/cabac.h | 2 ++ libavcodec/mips/compute_antialias_fixed.h | 2 ++ libavutil/mips/generic_macros_msa.h | 6 +++--- 3 files changed, 7 insertions(+), 3 deletions(-) diff --git a/libavcodec/mips/cabac.h b/libavcodec/mips/cabac.h index 39c308c7e0d..20ecab43207 100644 --- a/libavcodec/mips/cabac.h +++ b/libavcodec/mips/cabac.h @@ -30,6 +30,7 @@ #include "libavutil/mips/mmiutils.h" #include "config.h" +#if !HAVE_MIPS32R6 && !HAVE_MIPS64R6 #define get_cabac_inline get_cabac_inline_mips static av_always_inline int get_cabac_inline_mips(CABACContext *c, uint8_t * const state){ @@ -225,4 +226,5 @@ static av_always_inline int get_cabac_bypass_sign_mips(CABACContext *c, int val) return res; } +#endif /* !HAVE_MIPS32R6 && !HAVE_MIPS64R6 */ #endif /* AVCODEC_MIPS_CABAC_H */ diff --git a/libavcodec/mips/compute_antialias_fixed.h b/libavcodec/mips/compute_antialias_fixed.h index 1f395d23027..982002ad4cd 100644 --- a/libavcodec/mips/compute_antialias_fixed.h +++ b/libavcodec/mips/compute_antialias_fixed.h @@ -56,6 +56,7 @@ #define AVCODEC_MIPS_COMPUTE_ANTIALIAS_FIXED_H #if HAVE_INLINE_ASM +#if !HAVE_MIPS32R6 && !HAVE_MIPS64R6 static void compute_antialias_mips_fixed(MPADecodeContext *s, GranuleDef *g) { @@ -246,6 +247,7 @@ static void compute_antialias_mips_fixed(MPADecodeContext *s, } } #define compute_antialias compute_antialias_mips_fixed +#endif /* !HAVE_MIPS32R6 && !HAVE_MIPS64R6 */ #endif /* HAVE_INLINE_ASM */ #endif /* AVCODEC_MIPS_COMPUTE_ANTIALIAS_FIXED_H */ diff --git a/libavutil/mips/generic_macros_msa.h b/libavutil/mips/generic_macros_msa.h index 1486f7296e2..9beb0443ed3 100644 --- a/libavutil/mips/generic_macros_msa.h +++ b/libavutil/mips/generic_macros_msa.h @@ -44,7 +44,7 @@ #define ST_UW(...) ST_V(v4u32, __VA_ARGS__) #define ST_SW(...) ST_V(v4i32, __VA_ARGS__) -#if (__mips_isa_rev >= 6) +#if HAVE_MIPS32R6 || HAVE_MIPS64R6 #define LH(psrc) \ ( { \ uint16_t val_lh_m = *(uint16_t *)(psrc); \ @@ -85,7 +85,7 @@ #define SW(val, pdst) *(uint32_t *)(pdst) = (val); #define SD(val, pdst) *(uint64_t *)(pdst) = (val); -#else // !(__mips_isa_rev >= 6) +#else // !HAVE_MIPS32R6 && !HAVE_MIPS64R6 #define LH(psrc) \ ( { \ uint8_t *psrc_lh_m = (uint8_t *) (psrc); \ @@ -188,7 +188,7 @@ SW(val0_sd_m, pdst_sd_m); \ SW(val1_sd_m, pdst_sd_m + 4); \ } -#endif // (__mips_isa_rev >= 6) +#endif // HAVE_MIPS32R6 || HAVE_MIPS64R6 /* Description : Load 4 words with stride Arguments : Inputs - psrc (source pointer to load from) From 8b3351bbead47f7f306621b45c8f2391b6bd23d2 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Thu, 23 Mar 2023 19:07:47 +0100 Subject: [PATCH 0480/2172] avcodec/tests/snowenc: unbreak DWT tests the IDWT data type mismatched current code Signed-off-by: Michael Niedermayer --- libavcodec/tests/snowenc.c | 23 ++++++++++++++--------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/libavcodec/tests/snowenc.c b/libavcodec/tests/snowenc.c index e423ab0541b..80643091442 100644 --- a/libavcodec/tests/snowenc.c +++ b/libavcodec/tests/snowenc.c @@ -31,6 +31,7 @@ int main(void){ #define width 256 #define height 256 int buffer[2][width*height]; + short obuffer[width*height]; SnowContext s; int i; AVLFG prng; @@ -49,24 +50,28 @@ int main(void){ printf("testing 5/3 DWT\n"); for(i=0; i20) printf("fsck: %6d %12d %7d\n",i, buffer[0][i], buffer[1][i]); + if(FFABS(buffer[1][i] - obuffer[i])>20) printf("fsck: %4dx%4d %12d %7d\n",i%width, i/width, buffer[1][i], obuffer[i]); { int level, orientation, x, y; @@ -87,12 +92,12 @@ int main(void){ if(orientation&1) buf+=w; if(orientation>1) buf+=stride>>1; - memset(buffer[0], 0, sizeof(int)*width*height); + memset(obuffer, 0, sizeof(short)*width*height); buf[w/2 + h/2*stride]= 256*256; - ff_spatial_idwt((IDWTELEM*)buffer[0], s.temp_idwt_buffer, width, height, width, s.spatial_decomposition_type, s.spatial_decomposition_count); + ff_spatial_idwt(obuffer, s.temp_idwt_buffer, width, height, width, s.spatial_decomposition_type, s.spatial_decomposition_count); for(y=0; y Date: Fri, 24 Mar 2023 00:18:06 +0100 Subject: [PATCH 0481/2172] avcodec/snowenc: Fix visual weight calculation Signed-off-by: Michael Niedermayer --- libavcodec/snowenc.c | 8 ++++++-- tests/ref/seek/vsynth_lena-snow | 28 +++++++++++++------------- tests/ref/vsynth/vsynth1-snow | 8 ++++---- tests/ref/vsynth/vsynth1-snow-hpel | 8 ++++---- tests/ref/vsynth/vsynth2-snow | 8 ++++---- tests/ref/vsynth/vsynth2-snow-hpel | 8 ++++---- tests/ref/vsynth/vsynth_lena-snow | 8 ++++---- tests/ref/vsynth/vsynth_lena-snow-hpel | 8 ++++---- 8 files changed, 44 insertions(+), 40 deletions(-) diff --git a/libavcodec/snowenc.c b/libavcodec/snowenc.c index 658684c575f..3ff100364d5 100644 --- a/libavcodec/snowenc.c +++ b/libavcodec/snowenc.c @@ -1551,10 +1551,10 @@ static void calculate_visual_weight(SnowContext *s, Plane *p){ int level, orientation, x, y; for(level=0; levelspatial_decomposition_count; level++){ + int64_t error=0; for(orientation=level ? 1 : 0; orientation<4; orientation++){ SubBand *b= &p->band[level][orientation]; IDWTELEM *ibuf= b->ibuf; - int64_t error=0; memset(s->spatial_idwt_buffer, 0, sizeof(*s->spatial_idwt_buffer)*width*height); ibuf[b->width/2 + b->height/2*b->stride]= 256*16; @@ -1565,9 +1565,13 @@ static void calculate_visual_weight(SnowContext *s, Plane *p){ error += d*d; } } - + if (orientation == 2) + error /= 2; b->qlog= (int)(QROOT * log2(352256.0/sqrt(error)) + 0.5); + if (orientation != 1) + error = 0; } + p->band[level][1].qlog = p->band[level][2].qlog; } } diff --git a/tests/ref/seek/vsynth_lena-snow b/tests/ref/seek/vsynth_lena-snow index 33d6c27463e..b2d2d22cda4 100644 --- a/tests/ref/seek/vsynth_lena-snow +++ b/tests/ref/seek/vsynth_lena-snow @@ -2,45 +2,45 @@ ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 5652 size: 3035 ret: 0 st:-1 flags:0 ts:-1.000000 ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 5652 size: 3035 ret: 0 st:-1 flags:1 ts: 1.894167 -ret: 0 st: 0 flags:1 dts: 1.440000 pts: 1.440000 pos: 39806 size: 3640 +ret: 0 st: 0 flags:1 dts: 1.440000 pts: 1.440000 pos: 39690 size: 3640 ret: 0 st: 0 flags:0 ts: 0.800000 -ret: 0 st: 0 flags:1 dts: 0.960000 pts: 0.960000 pos: 27442 size: 3494 +ret: 0 st: 0 flags:1 dts: 0.960000 pts: 0.960000 pos: 27382 size: 3493 ret:-1 st: 0 flags:1 ts:-0.320000 ret:-1 st:-1 flags:0 ts: 2.576668 ret: 0 st:-1 flags:1 ts: 1.470835 -ret: 0 st: 0 flags:1 dts: 1.440000 pts: 1.440000 pos: 39806 size: 3640 +ret: 0 st: 0 flags:1 dts: 1.440000 pts: 1.440000 pos: 39690 size: 3640 ret: 0 st: 0 flags:0 ts: 0.360000 -ret: 0 st: 0 flags:1 dts: 0.480000 pts: 0.480000 pos: 16134 size: 3244 +ret: 0 st: 0 flags:1 dts: 0.480000 pts: 0.480000 pos: 16074 size: 3245 ret:-1 st: 0 flags:1 ts:-0.760000 ret:-1 st:-1 flags:0 ts: 2.153336 ret: 0 st:-1 flags:1 ts: 1.047503 -ret: 0 st: 0 flags:1 dts: 0.960000 pts: 0.960000 pos: 27442 size: 3494 +ret: 0 st: 0 flags:1 dts: 0.960000 pts: 0.960000 pos: 27382 size: 3493 ret: 0 st: 0 flags:0 ts:-0.040000 ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 5652 size: 3035 ret: 0 st: 0 flags:1 ts: 2.840000 -ret: 0 st: 0 flags:1 dts: 1.920000 pts: 1.920000 pos: 52608 size: 3582 +ret: 0 st: 0 flags:1 dts: 1.920000 pts: 1.920000 pos: 52538 size: 3582 ret: 0 st:-1 flags:0 ts: 1.730004 -ret: 0 st: 0 flags:1 dts: 1.920000 pts: 1.920000 pos: 52608 size: 3582 +ret: 0 st: 0 flags:1 dts: 1.920000 pts: 1.920000 pos: 52538 size: 3582 ret: 0 st:-1 flags:1 ts: 0.624171 -ret: 0 st: 0 flags:1 dts: 0.480000 pts: 0.480000 pos: 16134 size: 3244 +ret: 0 st: 0 flags:1 dts: 0.480000 pts: 0.480000 pos: 16074 size: 3245 ret: 0 st: 0 flags:0 ts:-0.480000 ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 5652 size: 3035 ret: 0 st: 0 flags:1 ts: 2.400000 -ret: 0 st: 0 flags:1 dts: 1.920000 pts: 1.920000 pos: 52608 size: 3582 +ret: 0 st: 0 flags:1 dts: 1.920000 pts: 1.920000 pos: 52538 size: 3582 ret: 0 st:-1 flags:0 ts: 1.306672 -ret: 0 st: 0 flags:1 dts: 1.440000 pts: 1.440000 pos: 39806 size: 3640 +ret: 0 st: 0 flags:1 dts: 1.440000 pts: 1.440000 pos: 39690 size: 3640 ret: 0 st:-1 flags:1 ts: 0.200839 ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 5652 size: 3035 ret: 0 st: 0 flags:0 ts:-0.920000 ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 5652 size: 3035 ret: 0 st: 0 flags:1 ts: 2.000000 -ret: 0 st: 0 flags:1 dts: 1.920000 pts: 1.920000 pos: 52608 size: 3582 +ret: 0 st: 0 flags:1 dts: 1.920000 pts: 1.920000 pos: 52538 size: 3582 ret: 0 st:-1 flags:0 ts: 0.883340 -ret: 0 st: 0 flags:1 dts: 0.960000 pts: 0.960000 pos: 27442 size: 3494 +ret: 0 st: 0 flags:1 dts: 0.960000 pts: 0.960000 pos: 27382 size: 3493 ret:-1 st:-1 flags:1 ts:-0.222493 ret:-1 st: 0 flags:0 ts: 2.680000 ret: 0 st: 0 flags:1 ts: 1.560000 -ret: 0 st: 0 flags:1 dts: 1.440000 pts: 1.440000 pos: 39806 size: 3640 +ret: 0 st: 0 flags:1 dts: 1.440000 pts: 1.440000 pos: 39690 size: 3640 ret: 0 st:-1 flags:0 ts: 0.460008 -ret: 0 st: 0 flags:1 dts: 0.480000 pts: 0.480000 pos: 16134 size: 3244 +ret: 0 st: 0 flags:1 dts: 0.480000 pts: 0.480000 pos: 16074 size: 3245 ret:-1 st:-1 flags:1 ts:-0.645825 diff --git a/tests/ref/vsynth/vsynth1-snow b/tests/ref/vsynth/vsynth1-snow index f20abd2ee4e..b0e3a0bfd76 100644 --- a/tests/ref/vsynth/vsynth1-snow +++ b/tests/ref/vsynth/vsynth1-snow @@ -1,4 +1,4 @@ -67c10f8d52fcd1103caa675a1408bf6e *tests/data/fate/vsynth1-snow.avi -136088 tests/data/fate/vsynth1-snow.avi -bfc0bcc4bc7b956933aa58acc587018d *tests/data/fate/vsynth1-snow.out.rawvideo -stddev: 22.77 PSNR: 20.98 MAXDIFF: 175 bytes: 7603200/ 7603200 +c4c77a6fb926b89fe6591c398f5cd4db *tests/data/fate/vsynth1-snow.avi +136160 tests/data/fate/vsynth1-snow.avi +dcf8b3f62d9c3ae2b2d0fbbacbf83e4e *tests/data/fate/vsynth1-snow.out.rawvideo +stddev: 22.74 PSNR: 20.99 MAXDIFF: 173 bytes: 7603200/ 7603200 diff --git a/tests/ref/vsynth/vsynth1-snow-hpel b/tests/ref/vsynth/vsynth1-snow-hpel index 39780ad8a2f..72b082b2cee 100644 --- a/tests/ref/vsynth/vsynth1-snow-hpel +++ b/tests/ref/vsynth/vsynth1-snow-hpel @@ -1,4 +1,4 @@ -e62ae25d5040d04622a965bcb27fdb1e *tests/data/fate/vsynth1-snow-hpel.avi -138446 tests/data/fate/vsynth1-snow-hpel.avi -57c914cd150f8fc260b5989ce3e5884c *tests/data/fate/vsynth1-snow-hpel.out.rawvideo -stddev: 22.74 PSNR: 20.99 MAXDIFF: 172 bytes: 7603200/ 7603200 +5c9eb93646eb0e5570d37e9adc9625e4 *tests/data/fate/vsynth1-snow-hpel.avi +138580 tests/data/fate/vsynth1-snow-hpel.avi +3382bdde624d8bb4af206a5ac6614605 *tests/data/fate/vsynth1-snow-hpel.out.rawvideo +stddev: 22.71 PSNR: 21.00 MAXDIFF: 171 bytes: 7603200/ 7603200 diff --git a/tests/ref/vsynth/vsynth2-snow b/tests/ref/vsynth/vsynth2-snow index e9607bb7d09..355f89d5f4f 100644 --- a/tests/ref/vsynth/vsynth2-snow +++ b/tests/ref/vsynth/vsynth2-snow @@ -1,4 +1,4 @@ -0a41e73ddd2f54936490655b46dad4a3 *tests/data/fate/vsynth2-snow.avi -72868 tests/data/fate/vsynth2-snow.avi -34a75f5cf8a71159f1a572d9cedcfef9 *tests/data/fate/vsynth2-snow.out.rawvideo -stddev: 13.73 PSNR: 25.37 MAXDIFF: 162 bytes: 7603200/ 7603200 +5e130d6a48b69348eee7f7c76c5869a3 *tests/data/fate/vsynth2-snow.avi +72942 tests/data/fate/vsynth2-snow.avi +9b6cee60e3ec0d1f312a8a25a7878fcc *tests/data/fate/vsynth2-snow.out.rawvideo +stddev: 13.39 PSNR: 25.59 MAXDIFF: 154 bytes: 7603200/ 7603200 diff --git a/tests/ref/vsynth/vsynth2-snow-hpel b/tests/ref/vsynth/vsynth2-snow-hpel index 66839fd6f6c..ec3b5dfad24 100644 --- a/tests/ref/vsynth/vsynth2-snow-hpel +++ b/tests/ref/vsynth/vsynth2-snow-hpel @@ -1,4 +1,4 @@ -9bc409e4794ee50691a26c9c836d31a7 *tests/data/fate/vsynth2-snow-hpel.avi -79728 tests/data/fate/vsynth2-snow-hpel.avi -2cc64d8171175a1532fd7d3ed3011fbf *tests/data/fate/vsynth2-snow-hpel.out.rawvideo -stddev: 13.70 PSNR: 25.39 MAXDIFF: 162 bytes: 7603200/ 7603200 +8edcf0fd7f066972ff77d5b891ed6dde *tests/data/fate/vsynth2-snow-hpel.avi +79798 tests/data/fate/vsynth2-snow-hpel.avi +7e0f2a24feda6fb3e54b85511a28c45f *tests/data/fate/vsynth2-snow-hpel.out.rawvideo +stddev: 13.35 PSNR: 25.62 MAXDIFF: 157 bytes: 7603200/ 7603200 diff --git a/tests/ref/vsynth/vsynth_lena-snow b/tests/ref/vsynth/vsynth_lena-snow index ec29a78483a..582c294531e 100644 --- a/tests/ref/vsynth/vsynth_lena-snow +++ b/tests/ref/vsynth/vsynth_lena-snow @@ -1,4 +1,4 @@ -8e96f337e8f4ccac7d72ef517e1d2208 *tests/data/fate/vsynth_lena-snow.avi -57680 tests/data/fate/vsynth_lena-snow.avi -90963cfd2359d460001c94d94256dc2b *tests/data/fate/vsynth_lena-snow.out.rawvideo -stddev: 10.48 PSNR: 27.72 MAXDIFF: 119 bytes: 7603200/ 7603200 +bf2cf9cacc1d98388798be98872049ee *tests/data/fate/vsynth_lena-snow.avi +57604 tests/data/fate/vsynth_lena-snow.avi +707a42eb20195913be55ba8dfadf72fb *tests/data/fate/vsynth_lena-snow.out.rawvideo +stddev: 10.37 PSNR: 27.81 MAXDIFF: 120 bytes: 7603200/ 7603200 diff --git a/tests/ref/vsynth/vsynth_lena-snow-hpel b/tests/ref/vsynth/vsynth_lena-snow-hpel index 2d6edd8a799..67effebc8a6 100644 --- a/tests/ref/vsynth/vsynth_lena-snow-hpel +++ b/tests/ref/vsynth/vsynth_lena-snow-hpel @@ -1,4 +1,4 @@ -56b14cb1cbb637536233982e87f7ac3e *tests/data/fate/vsynth_lena-snow-hpel.avi -61764 tests/data/fate/vsynth_lena-snow-hpel.avi -244b0266127fa354d8485234b2c388e4 *tests/data/fate/vsynth_lena-snow-hpel.out.rawvideo -stddev: 10.45 PSNR: 27.74 MAXDIFF: 119 bytes: 7603200/ 7603200 +c6ec87a11415a99b1a781f9f5bacb722 *tests/data/fate/vsynth_lena-snow-hpel.avi +61814 tests/data/fate/vsynth_lena-snow-hpel.avi +40f330397b7acf6bdbb3ec6d908be451 *tests/data/fate/vsynth_lena-snow-hpel.out.rawvideo +stddev: 10.34 PSNR: 27.83 MAXDIFF: 118 bytes: 7603200/ 7603200 From 771c266c0be29e6a1001fbd6795dd343147da1f2 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Fri, 24 Mar 2023 00:31:40 +0100 Subject: [PATCH 0482/2172] avcodec/tests/snowenc: return a failure if DWT/IDWT mismatches Signed-off-by: Michael Niedermayer --- libavcodec/tests/snowenc.c | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/libavcodec/tests/snowenc.c b/libavcodec/tests/snowenc.c index 80643091442..19635899d95 100644 --- a/libavcodec/tests/snowenc.c +++ b/libavcodec/tests/snowenc.c @@ -37,6 +37,7 @@ int main(void){ AVLFG prng; s.spatial_decomposition_count=6; s.spatial_decomposition_type=1; + int ret = 0; s.temp_dwt_buffer = av_calloc(width, sizeof(*s.temp_dwt_buffer)); s.temp_idwt_buffer = av_calloc(width, sizeof(*s.temp_idwt_buffer)); @@ -58,7 +59,10 @@ int main(void){ ff_spatial_idwt(obuffer, s.temp_idwt_buffer, width, height, width, s.spatial_decomposition_type, s.spatial_decomposition_count); for(i=0; i20) printf("fsck: %4dx%4d %12d %7d\n",i%width, i/width, buffer[1][i], obuffer[i]); + if(FFABS(buffer[1][i] - obuffer[i])>20) { + printf("fsck: %4dx%4d %12d %7d\n",i%width, i/width, buffer[1][i], obuffer[i]); + ret = 1; + } { int level, orientation, x, y; @@ -137,5 +144,5 @@ int main(void){ } } - return 0; + return ret; } From 163013c72452621624f634c706824c77222b77c5 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Fri, 24 Mar 2023 00:48:56 +0100 Subject: [PATCH 0483/2172] avcodec/tests/snowenc: Fix 2nd test --- libavcodec/tests/snowenc.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libavcodec/tests/snowenc.c b/libavcodec/tests/snowenc.c index 19635899d95..37198cd4e3b 100644 --- a/libavcodec/tests/snowenc.c +++ b/libavcodec/tests/snowenc.c @@ -93,14 +93,14 @@ int main(void){ int w= width >> (s.spatial_decomposition_count-level); int h= height >> (s.spatial_decomposition_count-level); int stride= width << (s.spatial_decomposition_count-level); - DWTELEM *buf= buffer[0]; + IDWTELEM *buf= obuffer; int64_t error=0; if(orientation&1) buf+=w; if(orientation>1) buf+=stride>>1; memset(obuffer, 0, sizeof(short)*width*height); - buf[w/2 + h/2*stride]= 256*256; + buf[w/2 + h/2*stride]= 8*256; ff_spatial_idwt(obuffer, s.temp_idwt_buffer, width, height, width, s.spatial_decomposition_type, s.spatial_decomposition_count); for(y=0; y Date: Sun, 19 Mar 2023 12:23:28 +0100 Subject: [PATCH 0484/2172] avcodec/snowenc: AV_CODEC_CAP_ENCODER_RECON_FRAME support Signed-off-by: Michael Niedermayer --- libavcodec/snowenc.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/libavcodec/snowenc.c b/libavcodec/snowenc.c index 3ff100364d5..4cf7ff1145e 100644 --- a/libavcodec/snowenc.c +++ b/libavcodec/snowenc.c @@ -26,6 +26,7 @@ #include "avcodec.h" #include "codec_internal.h" #include "encode.h" +#include "internal.h" //For AVCodecInternal.recon_frame #include "me_cmp.h" #include "packet_internal.h" #include "snow_dwt.h" @@ -1580,6 +1581,7 @@ static int encode_frame(AVCodecContext *avctx, AVPacket *pkt, { SnowContext *s = avctx->priv_data; RangeCoder * const c= &s->c; + AVCodecInternal *avci = avctx->internal; AVFrame *pic; const int width= s->avctx->width; const int height= s->avctx->height; @@ -1881,6 +1883,10 @@ static int encode_frame(AVCodecContext *avctx, AVPacket *pkt, s->encoding_error, (s->avctx->flags&AV_CODEC_FLAG_PSNR) ? SNOW_MAX_PLANES : 0, s->current_picture->pict_type); + if (s->avctx->flags & AV_CODEC_FLAG_RECON_FRAME) { + av_frame_unref(avci->recon_frame); + av_frame_ref(avci->recon_frame, s->current_picture); + } pkt->size = ff_rac_terminate(c, 0); if (s->current_picture->key_frame) @@ -1938,7 +1944,9 @@ const FFCodec ff_snow_encoder = { CODEC_LONG_NAME("Snow"), .p.type = AVMEDIA_TYPE_VIDEO, .p.id = AV_CODEC_ID_SNOW, - .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE, + .p.capabilities = AV_CODEC_CAP_DR1 | + AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE | + AV_CODEC_CAP_ENCODER_RECON_FRAME, .priv_data_size = sizeof(SnowContext), .init = encode_init, FF_CODEC_ENCODE_CB(encode_frame), From 5310c975cf9c5e54fa3d5492887a9f7e03b71b7e Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Sun, 19 Mar 2023 12:24:37 +0100 Subject: [PATCH 0485/2172] avfilter/vf_uspp: add AV_CODEC_FLAG_RECON_FRAME support about 50% faster (based on command line fps) Signed-off-by: Michael Niedermayer --- libavfilter/vf_uspp.c | 53 +++++++++++++++++++++++++++---------------- 1 file changed, 34 insertions(+), 19 deletions(-) diff --git a/libavfilter/vf_uspp.c b/libavfilter/vf_uspp.c index f60eb230a2f..ffdaa907b2a 100644 --- a/libavfilter/vf_uspp.c +++ b/libavfilter/vf_uspp.c @@ -231,16 +231,25 @@ static int filter_1phase(AVFilterContext *ctx, void *arg, int i, int nb_jobs) return ret; } - ret = avcodec_send_packet(p->avctx_dec[i], pkt); - av_packet_unref(pkt); - if (ret < 0) { - av_log(p->avctx_dec[i], AV_LOG_ERROR, "Error sending a packet for decoding\n"); - return ret; - } - ret = avcodec_receive_frame(p->avctx_dec[i], p->frame_dec[i]); - if (ret < 0) { - av_log(p->avctx_dec[i], AV_LOG_ERROR, "Error receiving a frame from decoding\n"); - return ret; + if (p->avctx_enc[i]->flags & AV_CODEC_FLAG_RECON_FRAME) { + av_packet_unref(pkt); + ret = avcodec_receive_frame(p->avctx_enc[i], p->frame_dec[i]); + if (ret < 0) { + av_log(p->avctx_dec[i], AV_LOG_ERROR, "Error receiving a frame from encoding\n"); + return ret; + } + } else { + ret = avcodec_send_packet(p->avctx_dec[i], pkt); + av_packet_unref(pkt); + if (ret < 0) { + av_log(p->avctx_dec[i], AV_LOG_ERROR, "Error sending a packet for decoding\n"); + return ret; + } + ret = avcodec_receive_frame(p->avctx_dec[i], p->frame_dec[i]); + if (ret < 0) { + av_log(p->avctx_dec[i], AV_LOG_ERROR, "Error receiving a frame from decoding\n"); + return ret; + } } offset = (BLOCK-x1) + (BLOCK-y1) * p->frame_dec[i]->linesize[0]; @@ -383,23 +392,21 @@ static int config_input(AVFilterLink *inlink) if (!(uspp->avctx_enc[i] = avcodec_alloc_context3(NULL))) return AVERROR(ENOMEM); - if (!(uspp->avctx_dec[i] = avcodec_alloc_context3(NULL))) - return AVERROR(ENOMEM); avctx_enc = uspp->avctx_enc[i]; - avctx_dec = uspp->avctx_dec[i]; - avctx_dec->width = avctx_enc->width = width + BLOCK; - avctx_dec->height = avctx_enc->height = height + BLOCK; avctx_enc->time_base = (AVRational){1,25}; // meaningless avctx_enc->gop_size = INT_MAX; avctx_enc->max_b_frames = 0; avctx_enc->pix_fmt = inlink->format; avctx_enc->flags = AV_CODEC_FLAG_QSCALE | AV_CODEC_FLAG_LOW_DELAY; + if (enc->capabilities & AV_CODEC_CAP_ENCODER_RECON_FRAME) { + avctx_enc->flags |= AV_CODEC_FLAG_RECON_FRAME; + av_dict_set(&opts, "no_bitstream", "1", 0); + } avctx_enc->strict_std_compliance = FF_COMPLIANCE_EXPERIMENTAL; avctx_enc->global_quality = 123; - avctx_dec->thread_count = avctx_enc->thread_count = 1; // We do threading in the filter with muiltiple codecs ret = avcodec_open2(avctx_enc, enc, &opts); av_dict_free(&opts); @@ -408,9 +415,17 @@ static int config_input(AVFilterLink *inlink) av_assert0(avctx_enc->codec); - ret = avcodec_open2(avctx_dec, dec, NULL); - if (ret < 0) - return ret; + if (!(enc->capabilities & AV_CODEC_CAP_ENCODER_RECON_FRAME)) { + if (!(uspp->avctx_dec[i] = avcodec_alloc_context3(NULL))) + return AVERROR(ENOMEM); + avctx_dec = uspp->avctx_dec[i]; + avctx_dec->width = avctx_enc->width; + avctx_dec->height = avctx_enc->height; + avctx_dec->thread_count = 1; + ret = avcodec_open2(avctx_dec, dec, NULL); + if (ret < 0) + return ret; + } if (!(uspp->frame[i] = av_frame_alloc())) return AVERROR(ENOMEM); From 06b451d276e80e659bf12165aa8ef4cf9a48cc38 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Sun, 19 Mar 2023 19:42:11 +0100 Subject: [PATCH 0486/2172] avfilter/vf_mcdeint: update to new API Signed-off-by: Michael Niedermayer --- configure | 5 ----- doc/filters.texi | 2 -- libavfilter/vf_mcdeint.c | 30 +++++++++++++++++++++++------- 3 files changed, 23 insertions(+), 14 deletions(-) diff --git a/configure b/configure index 8980cec7ee8..9072420d83a 100755 --- a/configure +++ b/configure @@ -7355,11 +7355,6 @@ esac enable frame_thread_encoder -# these filters depend on removed avcodec APIs -# they are kept disabled for now, but will be removed if -# nobody updates and re-enables them -disable mcdeint_filter - enabled asm || { arch=c; disable $ARCH_LIST $ARCH_EXT_LIST; } check_deps $CONFIG_LIST \ diff --git a/doc/filters.texi b/doc/filters.texi index dbe3f5fd9f5..4449998ba4d 100644 --- a/doc/filters.texi +++ b/doc/filters.texi @@ -16986,8 +16986,6 @@ Apply motion-compensation deinterlacing. It needs one field per frame as input and must thus be used together with yadif=1/3 or equivalent. -This filter is only available in ffmpeg version 4.4 or earlier. - This filter accepts the following options: @table @option @item mode diff --git a/libavfilter/vf_mcdeint.c b/libavfilter/vf_mcdeint.c index e747521c0a8..a2c3e79b9e5 100644 --- a/libavfilter/vf_mcdeint.c +++ b/libavfilter/vf_mcdeint.c @@ -75,6 +75,7 @@ typedef struct MCDeintContext { int parity; ///< MCDeintParity int qp; AVPacket *pkt; + AVFrame *frame_dec; AVCodecContext *enc_ctx; } MCDeintContext; @@ -116,6 +117,9 @@ static int config_props(AVFilterLink *inlink) mcdeint->pkt = av_packet_alloc(); if (!mcdeint->pkt) return AVERROR(ENOMEM); + mcdeint->frame_dec = av_frame_alloc(); + if (!mcdeint->frame_dec) + return AVERROR(ENOMEM); mcdeint->enc_ctx = avcodec_alloc_context3(enc); if (!mcdeint->enc_ctx) return AVERROR(ENOMEM); @@ -126,7 +130,7 @@ static int config_props(AVFilterLink *inlink) enc_ctx->gop_size = INT_MAX; enc_ctx->max_b_frames = 0; enc_ctx->pix_fmt = AV_PIX_FMT_YUV420P; - enc_ctx->flags = AV_CODEC_FLAG_QSCALE | AV_CODEC_FLAG_LOW_DELAY; + enc_ctx->flags = AV_CODEC_FLAG_QSCALE | AV_CODEC_FLAG_LOW_DELAY | AV_CODEC_FLAG_RECON_FRAME; enc_ctx->strict_std_compliance = FF_COMPLIANCE_EXPERIMENTAL; enc_ctx->global_quality = 1; enc_ctx->me_cmp = enc_ctx->me_sub_cmp = FF_CMP_SAD; @@ -160,15 +164,16 @@ static av_cold void uninit(AVFilterContext *ctx) av_packet_free(&mcdeint->pkt); avcodec_free_context(&mcdeint->enc_ctx); + av_frame_free(&mcdeint->frame_dec); } static int filter_frame(AVFilterLink *inlink, AVFrame *inpic) { MCDeintContext *mcdeint = inlink->dst->priv; AVFilterLink *outlink = inlink->dst->outputs[0]; - AVFrame *outpic, *frame_dec; + AVFrame *outpic, *frame_dec = mcdeint->frame_dec; AVPacket *pkt = mcdeint->pkt; - int x, y, i, ret, got_frame = 0; + int x, y, i, ret; outpic = ff_get_video_buffer(outlink, outlink->w, outlink->h); if (!outpic) { @@ -178,11 +183,22 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *inpic) av_frame_copy_props(outpic, inpic); inpic->quality = mcdeint->qp * FF_QP2LAMBDA; - ret = avcodec_encode_video2(mcdeint->enc_ctx, pkt, inpic, &got_frame); - if (ret < 0) + ret = avcodec_send_frame(mcdeint->enc_ctx, inpic); + if (ret < 0) { + av_log(mcdeint->enc_ctx, AV_LOG_ERROR, "Error sending a frame for encoding\n"); goto end; - - frame_dec = mcdeint->enc_ctx->coded_frame; + } + ret = avcodec_receive_packet(mcdeint->enc_ctx, pkt); + if (ret < 0) { + av_log(mcdeint->enc_ctx, AV_LOG_ERROR, "Error receiving a packet from encoding\n"); + goto end; + } + av_packet_unref(pkt); + ret = avcodec_receive_frame(mcdeint->enc_ctx, frame_dec); + if (ret < 0) { + av_log(mcdeint->enc_ctx, AV_LOG_ERROR, "Error receiving a frame from encoding\n"); + goto end; + } for (i = 0; i < 3; i++) { int is_chroma = !!i; From 5c216d081d24fddbcc64dc876a0cb31523c618c6 Mon Sep 17 00:00:00 2001 From: Ting Fu Date: Fri, 24 Mar 2023 15:30:38 +0800 Subject: [PATCH 0487/2172] lavfi/dnn: fix corruption when TF backend infer failed Signed-off-by: Ting Fu --- libavfilter/dnn/dnn_backend_tf.c | 15 +-------------- 1 file changed, 1 insertion(+), 14 deletions(-) diff --git a/libavfilter/dnn/dnn_backend_tf.c b/libavfilter/dnn/dnn_backend_tf.c index 3b5084b67b0..9570f188d2c 100644 --- a/libavfilter/dnn/dnn_backend_tf.c +++ b/libavfilter/dnn/dnn_backend_tf.c @@ -175,10 +175,6 @@ static int tf_start_inference(void *args) request->status); if (TF_GetCode(request->status) != TF_OK) { av_log(&tf_model->ctx, AV_LOG_ERROR, "%s", TF_Message(request->status)); - tf_free_request(infer_request); - if (ff_safe_queue_push_back(tf_model->request_queue, request) < 0) { - destroy_request_item(&request); - } return DNN_GENERIC_ERROR; } return 0; @@ -438,8 +434,6 @@ static int load_tf_model(TFModel *tf_model, const char *model_filename) TF_DeleteImportGraphDefOptions(graph_opts); TF_DeleteBuffer(graph_def); if (TF_GetCode(tf_model->status) != TF_OK){ - TF_DeleteGraph(tf_model->graph); - TF_DeleteStatus(tf_model->status); av_log(ctx, AV_LOG_ERROR, "Failed to import serialized graph to model graph\n"); av_freep(&sess_config); return DNN_GENERIC_ERROR; @@ -452,8 +446,6 @@ static int load_tf_model(TFModel *tf_model, const char *model_filename) TF_SetConfig(sess_opts, sess_config, sess_config_length,tf_model->status); av_freep(&sess_config); if (TF_GetCode(tf_model->status) != TF_OK) { - TF_DeleteGraph(tf_model->graph); - TF_DeleteStatus(tf_model->status); TF_DeleteSessionOptions(sess_opts); av_log(ctx, AV_LOG_ERROR, "Failed to set config for sess options with %s\n", tf_model->ctx.options.sess_config); @@ -465,8 +457,6 @@ static int load_tf_model(TFModel *tf_model, const char *model_filename) TF_DeleteSessionOptions(sess_opts); if (TF_GetCode(tf_model->status) != TF_OK) { - TF_DeleteGraph(tf_model->graph); - TF_DeleteStatus(tf_model->status); av_log(ctx, AV_LOG_ERROR, "Failed to create new session with model graph\n"); return DNN_GENERIC_ERROR; } @@ -479,9 +469,6 @@ static int load_tf_model(TFModel *tf_model, const char *model_filename) &init_op, 1, NULL, tf_model->status); if (TF_GetCode(tf_model->status) != TF_OK) { - TF_DeleteSession(tf_model->session, tf_model->status); - TF_DeleteGraph(tf_model->graph); - TF_DeleteStatus(tf_model->status); av_log(ctx, AV_LOG_ERROR, "Failed to run session when initializing\n"); return DNN_GENERIC_ERROR; } @@ -865,6 +852,7 @@ DNNModel *ff_dnn_load_model_tf(const char *model_filename, DNNFunctionType func_ av_freep(&model); return NULL; } + model->model = tf_model; tf_model->model = model; ctx = &tf_model->ctx; ctx->class = &dnn_tensorflow_class; @@ -931,7 +919,6 @@ DNNModel *ff_dnn_load_model_tf(const char *model_filename, DNNFunctionType func_ goto err; } - model->model = tf_model; model->get_input = &get_input_tf; model->get_output = &get_output_tf; model->options = options; From af052f9066a14ab633ef8e0bda49a432771efe74 Mon Sep 17 00:00:00 2001 From: Ting Fu Date: Fri, 24 Mar 2023 15:30:39 +0800 Subject: [PATCH 0488/2172] lavfi/dnn: fix mem leak in TF backend error handle Signed-off-by: Ting Fu --- libavfilter/dnn/dnn_backend_tf.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/libavfilter/dnn/dnn_backend_tf.c b/libavfilter/dnn/dnn_backend_tf.c index 9570f188d2c..fe1baa2e5eb 100644 --- a/libavfilter/dnn/dnn_backend_tf.c +++ b/libavfilter/dnn/dnn_backend_tf.c @@ -457,6 +457,7 @@ static int load_tf_model(TFModel *tf_model, const char *model_filename) TF_DeleteSessionOptions(sess_opts); if (TF_GetCode(tf_model->status) != TF_OK) { + av_freep(&sess_config); av_log(ctx, AV_LOG_ERROR, "Failed to create new session with model graph\n"); return DNN_GENERIC_ERROR; } @@ -469,6 +470,7 @@ static int load_tf_model(TFModel *tf_model, const char *model_filename) &init_op, 1, NULL, tf_model->status); if (TF_GetCode(tf_model->status) != TF_OK) { + av_freep(&sess_config); av_log(ctx, AV_LOG_ERROR, "Failed to run session when initializing\n"); return DNN_GENERIC_ERROR; } @@ -1125,6 +1127,7 @@ static int execute_model_tf(TFRequestItem *request, Queue *lltask_queue) if (ff_safe_queue_push_back(tf_model->request_queue, request) < 0) { destroy_request_item(&request); } + ff_dnn_free_model_tf(&tf_model->model); return ret; } @@ -1161,12 +1164,14 @@ int ff_dnn_execute_model_tf(const DNNModel *model, DNNExecBaseParams *exec_param ret = extract_lltask_from_task(task, tf_model->lltask_queue); if (ret != 0) { + av_freep(&task); av_log(ctx, AV_LOG_ERROR, "unable to extract last level task from task.\n"); return ret; } request = ff_safe_queue_pop_front(tf_model->request_queue); if (!request) { + av_freep(&task); av_log(ctx, AV_LOG_ERROR, "unable to get infer request.\n"); return AVERROR(EINVAL); } From bc589c91f7c32851328ef90bd56a7b8e917e5f5f Mon Sep 17 00:00:00 2001 From: Ting Fu Date: Fri, 24 Mar 2023 15:30:40 +0800 Subject: [PATCH 0489/2172] lavfi/dnn: add error info for TF backend filling task failure Signed-off-by: Ting Fu --- libavfilter/dnn/dnn_backend_tf.c | 1 + 1 file changed, 1 insertion(+) diff --git a/libavfilter/dnn/dnn_backend_tf.c b/libavfilter/dnn/dnn_backend_tf.c index fe1baa2e5eb..3d372a56281 100644 --- a/libavfilter/dnn/dnn_backend_tf.c +++ b/libavfilter/dnn/dnn_backend_tf.c @@ -1152,6 +1152,7 @@ int ff_dnn_execute_model_tf(const DNNModel *model, DNNExecBaseParams *exec_param ret = ff_dnn_fill_task(task, exec_params, tf_model, ctx->options.async, 1); if (ret != 0) { + av_log(ctx, AV_LOG_ERROR, "Fill task with invalid parameter(s).\n"); av_freep(&task); return ret; } From fd97a161577e552c4b9894cec3c0e10e020978cc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Storsj=C3=B6?= Date: Sun, 26 Mar 2023 12:38:48 +0300 Subject: [PATCH 0490/2172] tests: Fix fate-source after 0fbae2178b4ffda298b10473aa6fe17ef524eff9 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Martin Storsjö --- tests/ref/fate/source | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/ref/fate/source b/tests/ref/fate/source index 3b7ea9c3796..7b5f14b4f02 100644 --- a/tests/ref/fate/source +++ b/tests/ref/fate/source @@ -13,6 +13,7 @@ libavfilter/log2_tab.c libavformat/file_open.c libavformat/golomb_tab.c libavformat/log2_tab.c +libavformat/rangecoder_dec.c libswresample/log2_tab.c libswscale/log2_tab.c tools/uncoded_frame.c From 261fb55e393a16ebebd0e0a4b16b2f84e6b2f43d Mon Sep 17 00:00:00 2001 From: Stefano Sabatini Date: Tue, 24 Jan 2023 23:56:54 +0100 Subject: [PATCH 0491/2172] doc/ffmpeg: add vstats format documentation Address issue: http://trac.ffmpeg.org/ticket/7520 --- doc/ffmpeg.texi | 77 ++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 67 insertions(+), 10 deletions(-) diff --git a/doc/ffmpeg.texi b/doc/ffmpeg.texi index 7feba8ab701..6baf51bf0a5 100644 --- a/doc/ffmpeg.texi +++ b/doc/ffmpeg.texi @@ -1025,20 +1025,19 @@ factor if negative. @item -psnr Calculate PSNR of compressed frames. This option is deprecated, pass the PSNR flag to the encoder instead, using @code{-flags +psnr}. -@item -vstats -Dump video coding statistics to @file{vstats_HHMMSS.log}. -@item -vstats_file @var{file} -Dump video coding statistics to @var{file}. -@item -vstats_version @var{file} -Specifies which version of the vstats format to use. Default is 2. -version = 1 : +@item -vstats +Dump video coding statistics to @file{vstats_HHMMSS.log}. See the +@ref{vstats_file_format,,vstats file format} section for the format description. -@code{frame= %5d q= %2.1f PSNR= %6.2f f_size= %6d s_size= %8.0fkB time= %0.3f br= %7.1fkbits/s avg_br= %7.1fkbits/s} +@item -vstats_file @var{file} +Dump video coding statistics to @var{file}. See the +@ref{vstats_file_format,,vstats file format} section for the format description. -version > 1: +@item -vstats_version @var{file} +Specify which version of the vstats format to use. Default is @code{2}. See the +@ref{vstats_file_format,,vstats file format} section for the format description. -@code{out= %2d st= %2d frame= %5d q= %2.1f PSNR= %6.2f f_size= %6d s_size= %8.0fkB time= %0.3f br= %7.1fkbits/s avg_br= %7.1fkbits/s} @item -top[:@var{stream_specifier}] @var{n} (@emph{output,per-stream}) top=1/bottom=0/auto=-1 field first @item -vtag @var{fourcc/tag} (@emph{output}) @@ -2087,6 +2086,7 @@ 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. +@anchor{stats_enc_options} @item -stats_enc_pre[:@var{stream_specifier}] @var{path} (@emph{output,per-stream}) @item -stats_enc_post[:@var{stream_specifier}] @var{path} (@emph{output,per-stream}) @item -stats_mux_pre[:@var{stream_specifier}] @var{path} (@emph{output,per-stream}) @@ -2254,6 +2254,63 @@ search for the file @file{libvpx-1080p.avpreset}. If no such file is found, then ffmpeg will search for a file named @var{arg}.avpreset in the same directories. +@anchor{vstats_file_format} +@section vstats file format +The @code{-vstats} and @code{-vstats_file} options enable generation of a file +containing statistics about the generated video outputs. + +The @code{-vstats_version} option controls the format version of the generated +file. + +With version @code{1} the format is: +@example +frame= @var{FRAME} q= @var{FRAME_QUALITY} PSNR= @var{PSNR} f_size= @var{FRAME_SIZE} s_size= @var{STREAM_SIZE}kB time= @var{TIMESTAMP} br= @var{BITRATE}kbits/s avg_br= @var{AVERAGE_BITRATE}kbits/s +@end example + +With version @code{2} the format is: +@example +out= @var{OUT_FILE_INDEX} st= @var{OUT_FILE_STREAM_INDEX} frame= @var{FRAME_NUMBER} q= @var{FRAME_QUALITY}f PSNR= @var{PSNR} f_size= @var{FRAME_SIZE} s_size= @var{STREAM_SIZE}kB time= @var{TIMESTAMP} br= @var{BITRATE}kbits/s avg_br= @var{AVERAGE_BITRATE}kbits/s +@end example + +The value corresponding to each key is described below: +@table @option +@item avg_br +average bitrate expressed in Kbits/s + +@item br +bitrate expressed in Kbits/s + +@item frame +number of encoded frame + +@item out +out file index + +@item PSNR +Peak Signal to Noise Ratio + +@item q +quality of the frame + +@item f_size +encoded packet size expressed as number of bytes + +@item s_size +stream size expressed in KiB + +@item st +out file stream index + +@item time +time of the packet + +@item type +picture type +@end table + +See also the @ref{stats_enc_options,,-stats_enc options} for an alternative way +to show encoding statistics. + @c man end OPTIONS @chapter Examples From 0d3a2f9370608a86007baa7e164c6e2a70869830 Mon Sep 17 00:00:00 2001 From: Devin Heitmueller Date: Sun, 26 Mar 2023 00:33:18 +0100 Subject: [PATCH 0492/2172] avcodec: add SMPTE 2038 VANC data codec used in MPEG-TS streams Signed-off-by: Marton Balint --- libavcodec/codec_desc.c | 6 ++++++ libavcodec/codec_id.h | 1 + libavcodec/version.h | 4 ++-- 3 files changed, 9 insertions(+), 2 deletions(-) diff --git a/libavcodec/codec_desc.c b/libavcodec/codec_desc.c index e80ac077006..d912704891a 100644 --- a/libavcodec/codec_desc.c +++ b/libavcodec/codec_desc.c @@ -3627,6 +3627,12 @@ static const AVCodecDescriptor codec_descriptors[] = { .long_name = NULL_IF_CONFIG_SMALL("binary data"), .mime_types= MT("application/octet-stream"), }, + { + .id = AV_CODEC_ID_SMPTE_2038, + .type = AVMEDIA_TYPE_DATA, + .name = "smpte_2038", + .long_name = NULL_IF_CONFIG_SMALL("SMPTE ST 2038 VANC in MPEG-2 TS"), + }, { .id = AV_CODEC_ID_MPEG2TS, .type = AVMEDIA_TYPE_DATA, diff --git a/libavcodec/codec_id.h b/libavcodec/codec_id.h index 89a4a0cb893..64df9699f42 100644 --- a/libavcodec/codec_id.h +++ b/libavcodec/codec_id.h @@ -582,6 +582,7 @@ enum AVCodecID { AV_CODEC_ID_DVD_NAV, AV_CODEC_ID_TIMED_ID3, AV_CODEC_ID_BIN_DATA, + AV_CODEC_ID_SMPTE_2038, AV_CODEC_ID_PROBE = 0x19000, ///< codec_id is not known (like AV_CODEC_ID_NONE) but lavf should attempt to identify it diff --git a/libavcodec/version.h b/libavcodec/version.h index 39dbec02081..7acb261bb3b 100644 --- a/libavcodec/version.h +++ b/libavcodec/version.h @@ -29,8 +29,8 @@ #include "version_major.h" -#define LIBAVCODEC_VERSION_MINOR 6 -#define LIBAVCODEC_VERSION_MICRO 101 +#define LIBAVCODEC_VERSION_MINOR 7 +#define LIBAVCODEC_VERSION_MICRO 100 #define LIBAVCODEC_VERSION_INT AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \ LIBAVCODEC_VERSION_MINOR, \ From 19798229dfdb84b0055a9a242cce019075000493 Mon Sep 17 00:00:00 2001 From: Devin Heitmueller Date: Fri, 17 Mar 2023 11:03:49 -0400 Subject: [PATCH 0493/2172] avformat/mpegts: add support for preserving SMPTE 2038 when transcoding MPEG-TS streams Add the appropriate descriptors to the MPEG-TS demux and mux to ensure that SMPTE 2038 VANC streams are properly preserved when using codec copy (including adding the appropriate PMT descriptors). The focus of this patch is TS input to TS output. A separate patch adds support for output of 2038 VANC over decklink SDI. Thanks to Marton Balint for feedback to preserve ABI compatibility. Signed-off-by: Devin Heitmueller Signed-off-by: Marton Balint --- libavformat/mpegts.c | 1 + libavformat/mpegtsenc.c | 5 +++++ libavformat/mux.c | 6 ++++-- 3 files changed, 10 insertions(+), 2 deletions(-) diff --git a/libavformat/mpegts.c b/libavformat/mpegts.c index d97702fcd7d..a8fa3c0b28c 100644 --- a/libavformat/mpegts.c +++ b/libavformat/mpegts.c @@ -866,6 +866,7 @@ static const StreamType REGD_types[] = { { MKTAG('E', 'A', 'C', '3'), AVMEDIA_TYPE_AUDIO, AV_CODEC_ID_EAC3 }, { MKTAG('H', 'E', 'V', 'C'), AVMEDIA_TYPE_VIDEO, AV_CODEC_ID_HEVC }, { MKTAG('K', 'L', 'V', 'A'), AVMEDIA_TYPE_DATA, AV_CODEC_ID_SMPTE_KLV }, + { MKTAG('V', 'A', 'N', 'C'), AVMEDIA_TYPE_DATA, AV_CODEC_ID_SMPTE_2038 }, { MKTAG('I', 'D', '3', ' '), AVMEDIA_TYPE_DATA, AV_CODEC_ID_TIMED_ID3 }, { MKTAG('V', 'C', '-', '1'), AVMEDIA_TYPE_VIDEO, AV_CODEC_ID_VC1 }, { MKTAG('O', 'p', 'u', 's'), AVMEDIA_TYPE_AUDIO, AV_CODEC_ID_OPUS }, diff --git a/libavformat/mpegtsenc.c b/libavformat/mpegtsenc.c index 3f201cce1d8..700fc549df9 100644 --- a/libavformat/mpegtsenc.c +++ b/libavformat/mpegtsenc.c @@ -422,6 +422,9 @@ static int get_dvb_stream_type(AVFormatContext *s, AVStream *st) case AV_CODEC_ID_TIMED_ID3: stream_type = STREAM_TYPE_METADATA; break; + case AV_CODEC_ID_SMPTE_2038: + stream_type = STREAM_TYPE_PRIVATE_DATA; + break; case AV_CODEC_ID_DVB_SUBTITLE: case AV_CODEC_ID_DVB_TELETEXT: case AV_CODEC_ID_ARIB_CAPTION: @@ -804,6 +807,8 @@ static int mpegts_write_pmt(AVFormatContext *s, MpegTSService *service) case AVMEDIA_TYPE_DATA: if (codec_id == AV_CODEC_ID_SMPTE_KLV) { put_registration_descriptor(&q, MKTAG('K', 'L', 'V', 'A')); + } else if (codec_id == AV_CODEC_ID_SMPTE_2038) { + put_registration_descriptor(&q, MKTAG('V', 'A', 'N', 'C')); } else if (codec_id == AV_CODEC_ID_TIMED_ID3) { const char *tag = "ID3 "; *q++ = METADATA_DESCRIPTOR; diff --git a/libavformat/mux.c b/libavformat/mux.c index 04de05ec178..0bc9b6b87dd 100644 --- a/libavformat/mux.c +++ b/libavformat/mux.c @@ -304,7 +304,8 @@ FF_ENABLE_DEPRECATION_WARNINGS par->codec_tag = av_codec_get_tag(of->p.codec_tag, par->codec_id); } - if (par->codec_type != AVMEDIA_TYPE_ATTACHMENT) + if (par->codec_type != AVMEDIA_TYPE_ATTACHMENT && + par->codec_id != AV_CODEC_ID_SMPTE_2038) si->nb_interleaved_streams++; } si->interleave_packet = of->interleave_packet; @@ -942,7 +943,8 @@ int ff_interleave_packet_per_dts(AVFormatContext *s, AVPacket *pkt, ++stream_count; } else if (par->codec_type != AVMEDIA_TYPE_ATTACHMENT && par->codec_id != AV_CODEC_ID_VP8 && - par->codec_id != AV_CODEC_ID_VP9) { + par->codec_id != AV_CODEC_ID_VP9 && + par->codec_id != AV_CODEC_ID_SMPTE_2038) { ++noninterleaved_count; } } From 20dade27d96da4f502b0cf26e6bbd7c6d976e653 Mon Sep 17 00:00:00 2001 From: James Almer Date: Sun, 26 Mar 2023 16:28:38 -0300 Subject: [PATCH 0494/2172] fftools/ffprobe: print crop_* frame fields Reviewed-by: Stefano Sabatini Signed-off-by: James Almer --- doc/ffprobe.xsd | 4 + fftools/ffprobe.c | 4 + tests/ref/fate/exif-image-embedded | 4 + tests/ref/fate/exif-image-jpg | 4 + tests/ref/fate/exif-image-tiff | 4 + tests/ref/fate/exif-image-webp | 4 + tests/ref/fate/ffprobe_compact | 16 ++-- tests/ref/fate/ffprobe_csv | 16 ++-- tests/ref/fate/ffprobe_default | 32 +++++++ tests/ref/fate/ffprobe_flat | 32 +++++++ tests/ref/fate/ffprobe_ini | 32 +++++++ tests/ref/fate/ffprobe_json | 32 +++++++ tests/ref/fate/ffprobe_xml | 16 ++-- tests/ref/fate/ffprobe_xsd | 16 ++-- tests/ref/fate/h264-dts_5frames | 20 +++++ tests/ref/fate/jpg-icc | 4 + tests/ref/fate/mov-zombie | 130 ++++++++++++++--------------- tests/ref/fate/png-icc | 4 + tests/ref/fate/png-side-data | 4 + 19 files changed, 281 insertions(+), 97 deletions(-) diff --git a/doc/ffprobe.xsd b/doc/ffprobe.xsd index 0920380108f..87ca265d63d 100644 --- a/doc/ffprobe.xsd +++ b/doc/ffprobe.xsd @@ -106,6 +106,10 @@ + + + + diff --git a/fftools/ffprobe.c b/fftools/ffprobe.c index 561b514f0b3..d6e5a79c7e7 100644 --- a/fftools/ffprobe.c +++ b/fftools/ffprobe.c @@ -2620,6 +2620,10 @@ static void show_frame(WriterContext *w, AVFrame *frame, AVStream *stream, case AVMEDIA_TYPE_VIDEO: print_int("width", frame->width); print_int("height", frame->height); + print_int("crop_top", frame->crop_top); + print_int("crop_bottom", frame->crop_bottom); + print_int("crop_left", frame->crop_left); + print_int("crop_right", frame->crop_left); s = av_get_pix_fmt_name(frame->format); if (s) print_str ("pix_fmt", s); else print_str_opt("pix_fmt", "unknown"); diff --git a/tests/ref/fate/exif-image-embedded b/tests/ref/fate/exif-image-embedded index 210d7b54db5..d5937e9f863 100644 --- a/tests/ref/fate/exif-image-embedded +++ b/tests/ref/fate/exif-image-embedded @@ -16,6 +16,10 @@ pkt_pos=N/A pkt_size=15760 width=263 height=263 +crop_top=0 +crop_bottom=0 +crop_left=0 +crop_right=0 pix_fmt=yuvj420p sample_aspect_ratio=1:1 pict_type=I diff --git a/tests/ref/fate/exif-image-jpg b/tests/ref/fate/exif-image-jpg index 2d5fe18d610..bed265b7176 100644 --- a/tests/ref/fate/exif-image-jpg +++ b/tests/ref/fate/exif-image-jpg @@ -16,6 +16,10 @@ pkt_pos=N/A pkt_size=46095 width=400 height=225 +crop_top=0 +crop_bottom=0 +crop_left=0 +crop_right=0 pix_fmt=yuvj422p sample_aspect_ratio=1:1 pict_type=I diff --git a/tests/ref/fate/exif-image-tiff b/tests/ref/fate/exif-image-tiff index e447a465a5b..6b1c4dca666 100644 --- a/tests/ref/fate/exif-image-tiff +++ b/tests/ref/fate/exif-image-tiff @@ -16,6 +16,10 @@ pkt_pos=0 pkt_size=67604 width=200 height=112 +crop_top=0 +crop_bottom=0 +crop_left=0 +crop_right=0 pix_fmt=rgb24 sample_aspect_ratio=1:1 pict_type=? diff --git a/tests/ref/fate/exif-image-webp b/tests/ref/fate/exif-image-webp index 477986c0812..783abefc60a 100644 --- a/tests/ref/fate/exif-image-webp +++ b/tests/ref/fate/exif-image-webp @@ -16,6 +16,10 @@ pkt_pos=0 pkt_size=39276 width=400 height=225 +crop_top=0 +crop_bottom=0 +crop_left=0 +crop_right=0 pix_fmt=yuv420p sample_aspect_ratio=N/A pict_type=I diff --git a/tests/ref/fate/ffprobe_compact b/tests/ref/fate/ffprobe_compact index f00a4485614..d5eaca7d973 100644 --- a/tests/ref/fate/ffprobe_compact +++ b/tests/ref/fate/ffprobe_compact @@ -1,31 +1,31 @@ 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|duration=1024|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|duration=2048|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 +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|duration=2048|duration_time=0.040000|pkt_pos=2744|pkt_size=230400|width=320|height=240|crop_top=0|crop_bottom=0|crop_left=0|crop_right=0|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|duration=2048|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 +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|duration=2048|duration_time=0.040000|pkt_pos=233165|pkt_size=30000|width=100|height=100|crop_top=0|crop_bottom=0|crop_left=0|crop_right=0|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|duration=1024|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|duration=2048|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 +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|duration=2048|duration_time=0.040000|pkt_pos=265248|pkt_size=230400|width=320|height=240|crop_top=0|crop_bottom=0|crop_left=0|crop_right=0|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|duration=2048|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 +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|duration=2048|duration_time=0.040000|pkt_pos=495672|pkt_size=30000|width=100|height=100|crop_top=0|crop_bottom=0|crop_left=0|crop_right=0|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|duration=1024|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|duration=1024|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|duration=2048|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 +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|duration=2048|duration_time=0.040000|pkt_pos=529826|pkt_size=230400|width=320|height=240|crop_top=0|crop_bottom=0|crop_left=0|crop_right=0|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|duration=2048|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 +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|duration=2048|duration_time=0.040000|pkt_pos=760250|pkt_size=30000|width=100|height=100|crop_top=0|crop_bottom=0|crop_left=0|crop_right=0|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|duration=1024|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|duration=393|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|duration=2048|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 +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|duration=2048|duration_time=0.040000|pkt_pos=793142|pkt_size=230400|width=320|height=240|crop_top=0|crop_bottom=0|crop_left=0|crop_right=0|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|duration=2048|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 +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|duration=2048|duration_time=0.040000|pkt_pos=1023566|pkt_size=30000|width=100|height=100|crop_top=0|crop_bottom=0|crop_left=0|crop_right=0|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|initial_padding=0|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=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 diff --git a/tests/ref/fate/ffprobe_csv b/tests/ref/fate/ffprobe_csv index 2ec2836c263..f1204e60505 100644 --- a/tests/ref/fate/ffprobe_csv +++ b/tests/ref/fate/ffprobe_csv @@ -1,31 +1,31 @@ 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,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,2048,0.040000,2744,230400,320,240,rgb24,1:1,I,0,0,0,0,0,unknown,unknown,unknown,unknown,unspecified +frame,video,1,1,0,0.000000,0,0.000000,0,0.000000,2048,0.040000,2048,0.040000,2744,230400,320,240,0,0,0,0,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,2048,0.040000,233165,30000,100,100,rgb24,1:1,I,0,0,0,0,0,unknown,unknown,unknown,unknown,unspecified +frame,video,2,1,0,0.000000,0,0.000000,0,0.000000,2048,0.040000,2048,0.040000,233165,30000,100,100,0,0,0,0,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,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,2048,0.040000,265248,230400,320,240,rgb24,1:1,I,0,0,0,0,0,unknown,unknown,unknown,unknown,unspecified +frame,video,1,1,2048,0.040000,2048,0.040000,2048,0.040000,2048,0.040000,2048,0.040000,265248,230400,320,240,0,0,0,0,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,2048,0.040000,495672,30000,100,100,rgb24,1:1,I,0,0,0,0,0,unknown,unknown,unknown,unknown,unspecified +frame,video,2,1,2048,0.040000,2048,0.040000,2048,0.040000,2048,0.040000,2048,0.040000,495672,30000,100,100,0,0,0,0,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,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,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,2048,0.040000,529826,230400,320,240,rgb24,1:1,I,0,0,0,0,0,unknown,unknown,unknown,unknown,unspecified +frame,video,1,1,4096,0.080000,4096,0.080000,4096,0.080000,2048,0.040000,2048,0.040000,529826,230400,320,240,0,0,0,0,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,2048,0.040000,760250,30000,100,100,rgb24,1:1,I,0,0,0,0,0,unknown,unknown,unknown,unknown,unspecified +frame,video,2,1,4096,0.080000,4096,0.080000,4096,0.080000,2048,0.040000,2048,0.040000,760250,30000,100,100,0,0,0,0,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,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,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,2048,0.040000,793142,230400,320,240,rgb24,1:1,I,0,0,0,0,0,unknown,unknown,unknown,unknown,unspecified +frame,video,1,1,6144,0.120000,6144,0.120000,6144,0.120000,2048,0.040000,2048,0.040000,793142,230400,320,240,0,0,0,0,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,2048,0.040000,1023566,30000,100,100,rgb24,1:1,I,0,0,0,0,0,unknown,unknown,unknown,unknown,unspecified +frame,video,2,1,6144,0.120000,6144,0.120000,6144,0.120000,2048,0.040000,2048,0.040000,1023566,30000,100,100,0,0,0,0,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,0,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,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 diff --git a/tests/ref/fate/ffprobe_default b/tests/ref/fate/ffprobe_default index f8c18a1e504..c054b789e22 100644 --- a/tests/ref/fate/ffprobe_default +++ b/tests/ref/fate/ffprobe_default @@ -63,6 +63,10 @@ pkt_pos=2744 pkt_size=230400 width=320 height=240 +crop_top=0 +crop_bottom=0 +crop_left=0 +crop_right=0 pix_fmt=rgb24 sample_aspect_ratio=1:1 pict_type=I @@ -108,6 +112,10 @@ pkt_pos=233165 pkt_size=30000 width=100 height=100 +crop_top=0 +crop_bottom=0 +crop_left=0 +crop_right=0 pix_fmt=rgb24 sample_aspect_ratio=1:1 pict_type=I @@ -187,6 +195,10 @@ pkt_pos=265248 pkt_size=230400 width=320 height=240 +crop_top=0 +crop_bottom=0 +crop_left=0 +crop_right=0 pix_fmt=rgb24 sample_aspect_ratio=1:1 pict_type=I @@ -232,6 +244,10 @@ pkt_pos=495672 pkt_size=30000 width=100 height=100 +crop_top=0 +crop_bottom=0 +crop_left=0 +crop_right=0 pix_fmt=rgb24 sample_aspect_ratio=1:1 pict_type=I @@ -345,6 +361,10 @@ pkt_pos=529826 pkt_size=230400 width=320 height=240 +crop_top=0 +crop_bottom=0 +crop_left=0 +crop_right=0 pix_fmt=rgb24 sample_aspect_ratio=1:1 pict_type=I @@ -390,6 +410,10 @@ pkt_pos=760250 pkt_size=30000 width=100 height=100 +crop_top=0 +crop_bottom=0 +crop_left=0 +crop_right=0 pix_fmt=rgb24 sample_aspect_ratio=1:1 pict_type=I @@ -503,6 +527,10 @@ pkt_pos=793142 pkt_size=230400 width=320 height=240 +crop_top=0 +crop_bottom=0 +crop_left=0 +crop_right=0 pix_fmt=rgb24 sample_aspect_ratio=1:1 pict_type=I @@ -548,6 +576,10 @@ pkt_pos=1023566 pkt_size=30000 width=100 height=100 +crop_top=0 +crop_bottom=0 +crop_left=0 +crop_right=0 pix_fmt=rgb24 sample_aspect_ratio=1:1 pict_type=I diff --git a/tests/ref/fate/ffprobe_flat b/tests/ref/fate/ffprobe_flat index ee4373408f0..165d34958ae 100644 --- a/tests/ref/fate/ffprobe_flat +++ b/tests/ref/fate/ffprobe_flat @@ -56,6 +56,10 @@ 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 +packets_and_frames.frame.1.crop_top=0 +packets_and_frames.frame.1.crop_bottom=0 +packets_and_frames.frame.1.crop_left=0 +packets_and_frames.frame.1.crop_right=0 packets_and_frames.frame.1.pix_fmt="rgb24" packets_and_frames.frame.1.sample_aspect_ratio="1:1" packets_and_frames.frame.1.pict_type="I" @@ -97,6 +101,10 @@ 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 +packets_and_frames.frame.2.crop_top=0 +packets_and_frames.frame.2.crop_bottom=0 +packets_and_frames.frame.2.crop_left=0 +packets_and_frames.frame.2.crop_right=0 packets_and_frames.frame.2.pix_fmt="rgb24" packets_and_frames.frame.2.sample_aspect_ratio="1:1" packets_and_frames.frame.2.pict_type="I" @@ -168,6 +176,10 @@ 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 +packets_and_frames.frame.4.crop_top=0 +packets_and_frames.frame.4.crop_bottom=0 +packets_and_frames.frame.4.crop_left=0 +packets_and_frames.frame.4.crop_right=0 packets_and_frames.frame.4.pix_fmt="rgb24" packets_and_frames.frame.4.sample_aspect_ratio="1:1" packets_and_frames.frame.4.pict_type="I" @@ -209,6 +221,10 @@ 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 +packets_and_frames.frame.5.crop_top=0 +packets_and_frames.frame.5.crop_bottom=0 +packets_and_frames.frame.5.crop_left=0 +packets_and_frames.frame.5.crop_right=0 packets_and_frames.frame.5.pix_fmt="rgb24" packets_and_frames.frame.5.sample_aspect_ratio="1:1" packets_and_frames.frame.5.pict_type="I" @@ -310,6 +326,10 @@ 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 +packets_and_frames.frame.8.crop_top=0 +packets_and_frames.frame.8.crop_bottom=0 +packets_and_frames.frame.8.crop_left=0 +packets_and_frames.frame.8.crop_right=0 packets_and_frames.frame.8.pix_fmt="rgb24" packets_and_frames.frame.8.sample_aspect_ratio="1:1" packets_and_frames.frame.8.pict_type="I" @@ -351,6 +371,10 @@ 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 +packets_and_frames.frame.9.crop_top=0 +packets_and_frames.frame.9.crop_bottom=0 +packets_and_frames.frame.9.crop_left=0 +packets_and_frames.frame.9.crop_right=0 packets_and_frames.frame.9.pix_fmt="rgb24" packets_and_frames.frame.9.sample_aspect_ratio="1:1" packets_and_frames.frame.9.pict_type="I" @@ -452,6 +476,10 @@ 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 +packets_and_frames.frame.12.crop_top=0 +packets_and_frames.frame.12.crop_bottom=0 +packets_and_frames.frame.12.crop_left=0 +packets_and_frames.frame.12.crop_right=0 packets_and_frames.frame.12.pix_fmt="rgb24" packets_and_frames.frame.12.sample_aspect_ratio="1:1" packets_and_frames.frame.12.pict_type="I" @@ -493,6 +521,10 @@ 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 +packets_and_frames.frame.13.crop_top=0 +packets_and_frames.frame.13.crop_bottom=0 +packets_and_frames.frame.13.crop_left=0 +packets_and_frames.frame.13.crop_right=0 packets_and_frames.frame.13.pix_fmt="rgb24" packets_and_frames.frame.13.sample_aspect_ratio="1:1" packets_and_frames.frame.13.pict_type="I" diff --git a/tests/ref/fate/ffprobe_ini b/tests/ref/fate/ffprobe_ini index 77a12eaa135..df970b92dd4 100644 --- a/tests/ref/fate/ffprobe_ini +++ b/tests/ref/fate/ffprobe_ini @@ -65,6 +65,10 @@ pkt_pos=2744 pkt_size=230400 width=320 height=240 +crop_top=0 +crop_bottom=0 +crop_left=0 +crop_right=0 pix_fmt=rgb24 sample_aspect_ratio=1\:1 pict_type=I @@ -110,6 +114,10 @@ pkt_pos=233165 pkt_size=30000 width=100 height=100 +crop_top=0 +crop_bottom=0 +crop_left=0 +crop_right=0 pix_fmt=rgb24 sample_aspect_ratio=1\:1 pict_type=I @@ -189,6 +197,10 @@ pkt_pos=265248 pkt_size=230400 width=320 height=240 +crop_top=0 +crop_bottom=0 +crop_left=0 +crop_right=0 pix_fmt=rgb24 sample_aspect_ratio=1\:1 pict_type=I @@ -234,6 +246,10 @@ pkt_pos=495672 pkt_size=30000 width=100 height=100 +crop_top=0 +crop_bottom=0 +crop_left=0 +crop_right=0 pix_fmt=rgb24 sample_aspect_ratio=1\:1 pict_type=I @@ -347,6 +363,10 @@ pkt_pos=529826 pkt_size=230400 width=320 height=240 +crop_top=0 +crop_bottom=0 +crop_left=0 +crop_right=0 pix_fmt=rgb24 sample_aspect_ratio=1\:1 pict_type=I @@ -392,6 +412,10 @@ pkt_pos=760250 pkt_size=30000 width=100 height=100 +crop_top=0 +crop_bottom=0 +crop_left=0 +crop_right=0 pix_fmt=rgb24 sample_aspect_ratio=1\:1 pict_type=I @@ -505,6 +529,10 @@ pkt_pos=793142 pkt_size=230400 width=320 height=240 +crop_top=0 +crop_bottom=0 +crop_left=0 +crop_right=0 pix_fmt=rgb24 sample_aspect_ratio=1\:1 pict_type=I @@ -550,6 +578,10 @@ pkt_pos=1023566 pkt_size=30000 width=100 height=100 +crop_top=0 +crop_bottom=0 +crop_left=0 +crop_right=0 pix_fmt=rgb24 sample_aspect_ratio=1\:1 pict_type=I diff --git a/tests/ref/fate/ffprobe_json b/tests/ref/fate/ffprobe_json index 89e89e4a7a1..deef72aca8f 100644 --- a/tests/ref/fate/ffprobe_json +++ b/tests/ref/fate/ffprobe_json @@ -68,6 +68,10 @@ "pkt_size": "230400", "width": 320, "height": 240, + "crop_top": 0, + "crop_bottom": 0, + "crop_left": 0, + "crop_right": 0, "pix_fmt": "rgb24", "sample_aspect_ratio": "1:1", "pict_type": "I", @@ -110,6 +114,10 @@ "pkt_size": "30000", "width": 100, "height": 100, + "crop_top": 0, + "crop_bottom": 0, + "crop_left": 0, + "crop_right": 0, "pix_fmt": "rgb24", "sample_aspect_ratio": "1:1", "pict_type": "I", @@ -187,6 +195,10 @@ "pkt_size": "230400", "width": 320, "height": 240, + "crop_top": 0, + "crop_bottom": 0, + "crop_left": 0, + "crop_right": 0, "pix_fmt": "rgb24", "sample_aspect_ratio": "1:1", "pict_type": "I", @@ -229,6 +241,10 @@ "pkt_size": "30000", "width": 100, "height": 100, + "crop_top": 0, + "crop_bottom": 0, + "crop_left": 0, + "crop_right": 0, "pix_fmt": "rgb24", "sample_aspect_ratio": "1:1", "pict_type": "I", @@ -341,6 +357,10 @@ "pkt_size": "230400", "width": 320, "height": 240, + "crop_top": 0, + "crop_bottom": 0, + "crop_left": 0, + "crop_right": 0, "pix_fmt": "rgb24", "sample_aspect_ratio": "1:1", "pict_type": "I", @@ -383,6 +403,10 @@ "pkt_size": "30000", "width": 100, "height": 100, + "crop_top": 0, + "crop_bottom": 0, + "crop_left": 0, + "crop_right": 0, "pix_fmt": "rgb24", "sample_aspect_ratio": "1:1", "pict_type": "I", @@ -495,6 +519,10 @@ "pkt_size": "230400", "width": 320, "height": 240, + "crop_top": 0, + "crop_bottom": 0, + "crop_left": 0, + "crop_right": 0, "pix_fmt": "rgb24", "sample_aspect_ratio": "1:1", "pict_type": "I", @@ -537,6 +565,10 @@ "pkt_size": "30000", "width": 100, "height": 100, + "crop_top": 0, + "crop_bottom": 0, + "crop_left": 0, + "crop_right": 0, "pix_fmt": "rgb24", "sample_aspect_ratio": "1:1", "pict_type": "I", diff --git a/tests/ref/fate/ffprobe_xml b/tests/ref/fate/ffprobe_xml index bd0db8746fb..4e893edaa9c 100644 --- a/tests/ref/fate/ffprobe_xml +++ b/tests/ref/fate/ffprobe_xml @@ -4,31 +4,31 @@ - + - + - + - + - + - + - + - + diff --git a/tests/ref/fate/ffprobe_xsd b/tests/ref/fate/ffprobe_xsd index f05813bc4d0..b6bb9ab8a70 100644 --- a/tests/ref/fate/ffprobe_xsd +++ b/tests/ref/fate/ffprobe_xsd @@ -4,31 +4,31 @@ - + - + - + - + - + - + - + - + diff --git a/tests/ref/fate/h264-dts_5frames b/tests/ref/fate/h264-dts_5frames index ef54d5de827..f0a92587171 100644 --- a/tests/ref/fate/h264-dts_5frames +++ b/tests/ref/fate/h264-dts_5frames @@ -16,6 +16,10 @@ pkt_pos=651 pkt_size=14428 width=512 height=256 +crop_top=0 +crop_bottom=0 +crop_left=0 +crop_right=0 pix_fmt=yuv420p sample_aspect_ratio=1:1 pict_type=I @@ -48,6 +52,10 @@ pkt_pos=15085 pkt_size=11 width=512 height=256 +crop_top=0 +crop_bottom=0 +crop_left=0 +crop_right=0 pix_fmt=yuv420p sample_aspect_ratio=1:1 pict_type=P @@ -80,6 +88,10 @@ pkt_pos=15102 pkt_size=11 width=512 height=256 +crop_top=0 +crop_bottom=0 +crop_left=0 +crop_right=0 pix_fmt=yuv420p sample_aspect_ratio=1:1 pict_type=P @@ -112,6 +124,10 @@ pkt_pos=15119 pkt_size=11 width=512 height=256 +crop_top=0 +crop_bottom=0 +crop_left=0 +crop_right=0 pix_fmt=yuv420p sample_aspect_ratio=1:1 pict_type=P @@ -144,6 +160,10 @@ pkt_pos=15136 pkt_size=11 width=512 height=256 +crop_top=0 +crop_bottom=0 +crop_left=0 +crop_right=0 pix_fmt=yuv420p sample_aspect_ratio=1:1 pict_type=P diff --git a/tests/ref/fate/jpg-icc b/tests/ref/fate/jpg-icc index a0a33e0d3e1..cc7ab604e1d 100644 --- a/tests/ref/fate/jpg-icc +++ b/tests/ref/fate/jpg-icc @@ -24,6 +24,10 @@ pkt_pos=0 pkt_size=11010 width=128 height=128 +crop_top=0 +crop_bottom=0 +crop_left=0 +crop_right=0 pix_fmt=yuvj444p sample_aspect_ratio=1:1 pict_type=I diff --git a/tests/ref/fate/mov-zombie b/tests/ref/fate/mov-zombie index 49730a2e889..3472d1d5d05 100644 --- a/tests/ref/fate/mov-zombie +++ b/tests/ref/fate/mov-zombie @@ -1,197 +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|duration=3003|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 +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|duration=3003|duration_time=0.033367|pkt_pos=11309|pkt_size=4133|width=160|height=240|crop_top=0|crop_bottom=0|crop_left=0|crop_right=0|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|duration=3003|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 +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|duration=3003|duration_time=0.033367|pkt_pos=16519|pkt_size=355|width=160|height=240|crop_top=0|crop_bottom=0|crop_left=0|crop_right=0|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|duration=3003|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 +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|duration=3003|duration_time=0.033367|pkt_pos=15442|pkt_size=1077|width=160|height=240|crop_top=0|crop_bottom=0|crop_left=0|crop_right=0|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|duration=3003|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 +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|duration=3003|duration_time=0.033367|pkt_pos=17984|pkt_size=430|width=160|height=240|crop_top=0|crop_bottom=0|crop_left=0|crop_right=0|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|duration=3003|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 +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|duration=3003|duration_time=0.033367|pkt_pos=16874|pkt_size=1110|width=160|height=240|crop_top=0|crop_bottom=0|crop_left=0|crop_right=0|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|duration=3003|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 +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|duration=3003|duration_time=0.033367|pkt_pos=19899|pkt_size=1005|width=160|height=240|crop_top=0|crop_bottom=0|crop_left=0|crop_right=0|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|duration=3003|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 +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|duration=3003|duration_time=0.033367|pkt_pos=18414|pkt_size=1485|width=160|height=240|crop_top=0|crop_bottom=0|crop_left=0|crop_right=0|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|duration=3003|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 +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|duration=3003|duration_time=0.033367|pkt_pos=22880|pkt_size=904|width=160|height=240|crop_top=0|crop_bottom=0|crop_left=0|crop_right=0|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|duration=3003|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 +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|duration=3003|duration_time=0.033367|pkt_pos=20904|pkt_size=1976|width=160|height=240|crop_top=0|crop_bottom=0|crop_left=0|crop_right=0|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|duration=3003|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 +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|duration=3003|duration_time=0.033367|pkt_pos=25038|pkt_size=700|width=160|height=240|crop_top=0|crop_bottom=0|crop_left=0|crop_right=0|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|duration=3003|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 +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|duration=3003|duration_time=0.033367|pkt_pos=23784|pkt_size=1254|width=160|height=240|crop_top=0|crop_bottom=0|crop_left=0|crop_right=0|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|duration=3003|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 +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|duration=3003|duration_time=0.033367|pkt_pos=27049|pkt_size=631|width=160|height=240|crop_top=0|crop_bottom=0|crop_left=0|crop_right=0|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|duration=3003|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 +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|duration=3003|duration_time=0.033367|pkt_pos=25738|pkt_size=1311|width=160|height=240|crop_top=0|crop_bottom=0|crop_left=0|crop_right=0|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|duration=3003|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 +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|duration=3003|duration_time=0.033367|pkt_pos=28976|pkt_size=466|width=160|height=240|crop_top=0|crop_bottom=0|crop_left=0|crop_right=0|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|duration=3003|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 +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|duration=3003|duration_time=0.033367|pkt_pos=27680|pkt_size=1296|width=160|height=240|crop_top=0|crop_bottom=0|crop_left=0|crop_right=0|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|duration=3003|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 +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|duration=3003|duration_time=0.033367|pkt_pos=31080|pkt_size=907|width=160|height=240|crop_top=0|crop_bottom=0|crop_left=0|crop_right=0|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|duration=3003|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 +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|duration=3003|duration_time=0.033367|pkt_pos=29442|pkt_size=1638|width=160|height=240|crop_top=0|crop_bottom=0|crop_left=0|crop_right=0|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|duration=3003|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 +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|duration=3003|duration_time=0.033367|pkt_pos=33349|pkt_size=682|width=160|height=240|crop_top=0|crop_bottom=0|crop_left=0|crop_right=0|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|duration=3003|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 +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|duration=3003|duration_time=0.033367|pkt_pos=31987|pkt_size=1362|width=160|height=240|crop_top=0|crop_bottom=0|crop_left=0|crop_right=0|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|duration=3003|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 +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|duration=3003|duration_time=0.033367|pkt_pos=36948|pkt_size=1174|width=160|height=240|crop_top=0|crop_bottom=0|crop_left=0|crop_right=0|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|duration=3003|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 +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|duration=3003|duration_time=0.033367|pkt_pos=34031|pkt_size=2917|width=160|height=240|crop_top=0|crop_bottom=0|crop_left=0|crop_right=0|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|duration=3003|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 +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|duration=3003|duration_time=0.033367|pkt_pos=39870|pkt_size=926|width=160|height=240|crop_top=0|crop_bottom=0|crop_left=0|crop_right=0|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|duration=3003|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 +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|duration=3003|duration_time=0.033367|pkt_pos=38122|pkt_size=1748|width=160|height=240|crop_top=0|crop_bottom=0|crop_left=0|crop_right=0|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|duration=3003|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 +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|duration=3003|duration_time=0.033367|pkt_pos=40796|pkt_size=918|width=160|height=240|crop_top=0|crop_bottom=0|crop_left=0|crop_right=0|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|duration=3003|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 +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|duration=3003|duration_time=0.033367|pkt_pos=41714|pkt_size=3846|width=160|height=240|crop_top=0|crop_bottom=0|crop_left=0|crop_right=0|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|duration=3003|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 +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|duration=3003|duration_time=0.033367|pkt_pos=47492|pkt_size=1159|width=160|height=240|crop_top=0|crop_bottom=0|crop_left=0|crop_right=0|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|duration=3003|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 +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|duration=3003|duration_time=0.033367|pkt_pos=45560|pkt_size=1932|width=160|height=240|crop_top=0|crop_bottom=0|crop_left=0|crop_right=0|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|duration=3003|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 +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|duration=3003|duration_time=0.033367|pkt_pos=50173|pkt_size=719|width=160|height=240|crop_top=0|crop_bottom=0|crop_left=0|crop_right=0|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|duration=3003|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 +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|duration=3003|duration_time=0.033367|pkt_pos=48651|pkt_size=1522|width=160|height=240|crop_top=0|crop_bottom=0|crop_left=0|crop_right=0|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|duration=3003|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 +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|duration=3003|duration_time=0.033367|pkt_pos=52592|pkt_size=1099|width=160|height=240|crop_top=0|crop_bottom=0|crop_left=0|crop_right=0|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|duration=3003|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 +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|duration=3003|duration_time=0.033367|pkt_pos=50892|pkt_size=1700|width=160|height=240|crop_top=0|crop_bottom=0|crop_left=0|crop_right=0|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|duration=3003|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 +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|duration=3003|duration_time=0.033367|pkt_pos=56249|pkt_size=1008|width=160|height=240|crop_top=0|crop_bottom=0|crop_left=0|crop_right=0|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|duration=3003|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 +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|duration=3003|duration_time=0.033367|pkt_pos=53691|pkt_size=2558|width=160|height=240|crop_top=0|crop_bottom=0|crop_left=0|crop_right=0|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|duration=3003|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 +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|duration=3003|duration_time=0.033367|pkt_pos=58493|pkt_size=607|width=160|height=240|crop_top=0|crop_bottom=0|crop_left=0|crop_right=0|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|duration=3003|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 +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|duration=3003|duration_time=0.033367|pkt_pos=57257|pkt_size=1236|width=160|height=240|crop_top=0|crop_bottom=0|crop_left=0|crop_right=0|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|duration=3003|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 +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|duration=3003|duration_time=0.033367|pkt_pos=60983|pkt_size=893|width=160|height=240|crop_top=0|crop_bottom=0|crop_left=0|crop_right=0|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|duration=3003|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 +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|duration=3003|duration_time=0.033367|pkt_pos=59100|pkt_size=1883|width=160|height=240|crop_top=0|crop_bottom=0|crop_left=0|crop_right=0|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|duration=3003|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 +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|duration=3003|duration_time=0.033367|pkt_pos=63181|pkt_size=472|width=160|height=240|crop_top=0|crop_bottom=0|crop_left=0|crop_right=0|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|duration=3003|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 +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|duration=3003|duration_time=0.033367|pkt_pos=61876|pkt_size=1305|width=160|height=240|crop_top=0|crop_bottom=0|crop_left=0|crop_right=0|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|duration=3003|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 +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|duration=3003|duration_time=0.033367|pkt_pos=65064|pkt_size=616|width=160|height=240|crop_top=0|crop_bottom=0|crop_left=0|crop_right=0|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|duration=3003|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 +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|duration=3003|duration_time=0.033367|pkt_pos=63653|pkt_size=1411|width=160|height=240|crop_top=0|crop_bottom=0|crop_left=0|crop_right=0|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|duration=3003|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 +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|duration=3003|duration_time=0.033367|pkt_pos=66971|pkt_size=470|width=160|height=240|crop_top=0|crop_bottom=0|crop_left=0|crop_right=0|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|duration=3003|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 +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|duration=3003|duration_time=0.033367|pkt_pos=65680|pkt_size=1291|width=160|height=240|crop_top=0|crop_bottom=0|crop_left=0|crop_right=0|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|duration=3003|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 +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|duration=3003|duration_time=0.033367|pkt_pos=69418|pkt_size=436|width=160|height=240|crop_top=0|crop_bottom=0|crop_left=0|crop_right=0|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|duration=3003|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 +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|duration=3003|duration_time=0.033367|pkt_pos=67441|pkt_size=1977|width=160|height=240|crop_top=0|crop_bottom=0|crop_left=0|crop_right=0|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|duration=3003|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 +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|duration=3003|duration_time=0.033367|pkt_pos=72420|pkt_size=886|width=160|height=240|crop_top=0|crop_bottom=0|crop_left=0|crop_right=0|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|duration=3003|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 +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|duration=3003|duration_time=0.033367|pkt_pos=69854|pkt_size=2566|width=160|height=240|crop_top=0|crop_bottom=0|crop_left=0|crop_right=0|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|duration=3003|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 +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|duration=3003|duration_time=0.033367|pkt_pos=73306|pkt_size=1330|width=160|height=240|crop_top=0|crop_bottom=0|crop_left=0|crop_right=0|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|duration=3003|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 +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|duration=3003|duration_time=0.033367|pkt_pos=74636|pkt_size=2227|width=160|height=240|crop_top=0|crop_bottom=0|crop_left=0|crop_right=0|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|duration=3003|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 +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|duration=3003|duration_time=0.033367|pkt_pos=79073|pkt_size=1498|width=160|height=240|crop_top=0|crop_bottom=0|crop_left=0|crop_right=0|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|duration=3003|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 +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|duration=3003|duration_time=0.033367|pkt_pos=76863|pkt_size=2210|width=160|height=240|crop_top=0|crop_bottom=0|crop_left=0|crop_right=0|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|duration=3003|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 +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|duration=3003|duration_time=0.033367|pkt_pos=82292|pkt_size=1238|width=160|height=240|crop_top=0|crop_bottom=0|crop_left=0|crop_right=0|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|duration=3003|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 +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|duration=3003|duration_time=0.033367|pkt_pos=80571|pkt_size=1721|width=160|height=240|crop_top=0|crop_bottom=0|crop_left=0|crop_right=0|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|duration=3003|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 +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|duration=3003|duration_time=0.033367|pkt_pos=85283|pkt_size=1014|width=160|height=240|crop_top=0|crop_bottom=0|crop_left=0|crop_right=0|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|duration=3003|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 +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|duration=3003|duration_time=0.033367|pkt_pos=83530|pkt_size=1753|width=160|height=240|crop_top=0|crop_bottom=0|crop_left=0|crop_right=0|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|duration=3003|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 +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|duration=3003|duration_time=0.033367|pkt_pos=88705|pkt_size=1727|width=160|height=240|crop_top=0|crop_bottom=0|crop_left=0|crop_right=0|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|duration=3003|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 +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|duration=3003|duration_time=0.033367|pkt_pos=86297|pkt_size=2408|width=160|height=240|crop_top=0|crop_bottom=0|crop_left=0|crop_right=0|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|duration=3003|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 +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|duration=3003|duration_time=0.033367|pkt_pos=91936|pkt_size=957|width=160|height=240|crop_top=0|crop_bottom=0|crop_left=0|crop_right=0|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|duration=3003|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 +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|duration=3003|duration_time=0.033367|pkt_pos=90432|pkt_size=1504|width=160|height=240|crop_top=0|crop_bottom=0|crop_left=0|crop_right=0|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|duration=3003|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 +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|duration=3003|duration_time=0.033367|pkt_pos=94783|pkt_size=1239|width=160|height=240|crop_top=0|crop_bottom=0|crop_left=0|crop_right=0|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|duration=3003|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 +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|duration=3003|duration_time=0.033367|pkt_pos=92893|pkt_size=1890|width=160|height=240|crop_top=0|crop_bottom=0|crop_left=0|crop_right=0|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|duration=3003|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 +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|duration=3003|duration_time=0.033367|pkt_pos=97878|pkt_size=1302|width=160|height=240|crop_top=0|crop_bottom=0|crop_left=0|crop_right=0|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|duration=3003|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 +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|duration=3003|duration_time=0.033367|pkt_pos=96022|pkt_size=1856|width=160|height=240|crop_top=0|crop_bottom=0|crop_left=0|crop_right=0|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|duration=3003|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 +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|duration=3003|duration_time=0.033367|pkt_pos=100846|pkt_size=974|width=160|height=240|crop_top=0|crop_bottom=0|crop_left=0|crop_right=0|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=__C -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|duration=3003|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 +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|duration=3003|duration_time=0.033367|pkt_pos=99180|pkt_size=1666|width=160|height=240|crop_top=0|crop_bottom=0|crop_left=0|crop_right=0|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 diff --git a/tests/ref/fate/png-icc b/tests/ref/fate/png-icc index 1f4eab1fb01..8927cb331a3 100644 --- a/tests/ref/fate/png-icc +++ b/tests/ref/fate/png-icc @@ -24,6 +24,10 @@ pkt_pos=0 pkt_size=49441 width=128 height=128 +crop_top=0 +crop_bottom=0 +crop_left=0 +crop_right=0 pix_fmt=rgb24 sample_aspect_ratio=1:1 pict_type=I diff --git a/tests/ref/fate/png-side-data b/tests/ref/fate/png-side-data index 8f955f76bc6..629971bd239 100644 --- a/tests/ref/fate/png-side-data +++ b/tests/ref/fate/png-side-data @@ -16,6 +16,10 @@ pkt_pos=0 pkt_size=40194 width=128 height=128 +crop_top=0 +crop_bottom=0 +crop_left=0 +crop_right=0 pix_fmt=rgb24 sample_aspect_ratio=1:1 pict_type=I From cd954aa3c6e522053d6983a8bda8019e0feee826 Mon Sep 17 00:00:00 2001 From: Marton Balint Date: Sun, 26 Mar 2023 21:38:26 +0200 Subject: [PATCH 0495/2172] avformat/mxfenc: reindent after last mxfenc commit Signed-off-by: Marton Balint --- libavformat/mxfenc.c | 72 ++++++++++++++++++++++---------------------- 1 file changed, 36 insertions(+), 36 deletions(-) diff --git a/libavformat/mxfenc.c b/libavformat/mxfenc.c index d83908ec0e3..c79d0dc4bef 100644 --- a/libavformat/mxfenc.c +++ b/libavformat/mxfenc.c @@ -1236,43 +1236,43 @@ static int64_t mxf_write_cdci_common(AVFormatContext *s, AVStream *st, const UID } if (key != mxf_rgba_descriptor_key) { - // component depth - mxf_write_local_tag(s, 4, 0x3301); - avio_wb32(pb, sc->component_depth); - - // horizontal subsampling - mxf_write_local_tag(s, 4, 0x3302); - avio_wb32(pb, sc->h_chroma_sub_sample); - - // vertical subsampling - mxf_write_local_tag(s, 4, 0x3308); - avio_wb32(pb, sc->v_chroma_sub_sample); - - // color siting - mxf_write_local_tag(s, 1, 0x3303); - avio_w8(pb, sc->color_siting); - - // Padding Bits - mxf_write_local_tag(s, 2, 0x3307); - avio_wb16(pb, 0); - - if (st->codecpar->color_range != AVCOL_RANGE_UNSPECIFIED) { - int black = 0, - white = (1<component_depth) - 1, - color = (1<component_depth); - if (st->codecpar->color_range == AVCOL_RANGE_MPEG) { - black = 1 << (sc->component_depth - 4); - white = 235 << (sc->component_depth - 8); - color = (14 << (sc->component_depth - 4)) + 1; + // component depth + mxf_write_local_tag(s, 4, 0x3301); + avio_wb32(pb, sc->component_depth); + + // horizontal subsampling + mxf_write_local_tag(s, 4, 0x3302); + avio_wb32(pb, sc->h_chroma_sub_sample); + + // vertical subsampling + mxf_write_local_tag(s, 4, 0x3308); + avio_wb32(pb, sc->v_chroma_sub_sample); + + // color siting + mxf_write_local_tag(s, 1, 0x3303); + avio_w8(pb, sc->color_siting); + + // Padding Bits + mxf_write_local_tag(s, 2, 0x3307); + avio_wb16(pb, 0); + + if (st->codecpar->color_range != AVCOL_RANGE_UNSPECIFIED) { + int black = 0, + white = (1<component_depth) - 1, + color = (1<component_depth); + if (st->codecpar->color_range == AVCOL_RANGE_MPEG) { + black = 1 << (sc->component_depth - 4); + white = 235 << (sc->component_depth - 8); + color = (14 << (sc->component_depth - 4)) + 1; + } + mxf_write_local_tag(s, 4, 0x3304); + avio_wb32(pb, black); + mxf_write_local_tag(s, 4, 0x3305); + avio_wb32(pb, white); + mxf_write_local_tag(s, 4, 0x3306); + avio_wb32(pb, color); } - mxf_write_local_tag(s, 4, 0x3304); - avio_wb32(pb, black); - mxf_write_local_tag(s, 4, 0x3305); - avio_wb32(pb, white); - mxf_write_local_tag(s, 4, 0x3306); - avio_wb32(pb, color); - } - } // if (key != mxf_rgba_descriptor_key) + } if (sc->signal_standard) { mxf_write_local_tag(s, 1, 0x3215); From 174ca11d915c5258115b208285a232de94d6e14a Mon Sep 17 00:00:00 2001 From: Jerome Martinez Date: Sat, 14 Jan 2023 13:32:36 +0100 Subject: [PATCH 0496/2172] avformat/mxfenc: fix stored/sampled/displayed width/height According to MXF specs the Stored Rectangle corresponds to the data which is passed to the compressor and received from the decompressor, so they should contain the width / height extended to the macroblock boundary. In practice however width and height values rounded to the upper 16 multiples are only seen when muxing MPEG formats. Therefore this patch changes stored width and height values to unrounded for all non-MPEG formats, even macroblock based ones. For DNXHD the specs (ST 2019-4) explicitly indicates to use 1080 for 1088p. For ProRes the specs (RDD 44) only refer to to ST 377-1 without precision but no known commercial implementations are using rounded values. DV is not using 16x16 macroblocks, so 16 rounding makes no sense. The patch also fixes Sampled Width / Display Width to use unrounded values. Signed-off-by: Marton Balint --- libavformat/mxfenc.c | 27 +++++++++++++++++++++------ tests/fate/lavf-container.mak | 3 ++- tests/ref/lavf/mxf_dvcpro100 | 3 +++ tests/ref/lavf/mxf_opatom | 2 +- 4 files changed, 27 insertions(+), 8 deletions(-) create mode 100644 tests/ref/lavf/mxf_dvcpro100 diff --git a/libavformat/mxfenc.c b/libavformat/mxfenc.c index c79d0dc4bef..9eba208ffb6 100644 --- a/libavformat/mxfenc.c +++ b/libavformat/mxfenc.c @@ -1149,8 +1149,9 @@ static int64_t mxf_write_cdci_common(AVFormatContext *s, AVStream *st, const UID { MXFStreamContext *sc = st->priv_data; AVIOContext *pb = s->pb; - int stored_width = 0; - int stored_height = (st->codecpar->height+15)/16*16; + int stored_width = st->codecpar->width; + int stored_height = st->codecpar->height; + int display_width; int display_height; int f1, f2; const MXFCodecUL *color_primaries_ul; @@ -1169,12 +1170,24 @@ static int64_t mxf_write_cdci_common(AVFormatContext *s, AVStream *st, const UID else if (st->codecpar->height == 720) stored_width = 1280; } - if (!stored_width) - stored_width = (st->codecpar->width+15)/16*16; + display_width = stored_width; + switch (st->codecpar->codec_id) { + case AV_CODEC_ID_MPEG2VIDEO: + case AV_CODEC_ID_H264: + //Based on 16x16 macroblocks + stored_width = (stored_width+15)/16*16; + stored_height = (stored_height+15)/16*16; + break; + default: + break; + } + + //Stored width mxf_write_local_tag(s, 4, 0x3203); avio_wb32(pb, stored_width); + //Stored height mxf_write_local_tag(s, 4, 0x3202); avio_wb32(pb, stored_height>>sc->interlaced); @@ -1194,7 +1207,7 @@ static int64_t mxf_write_cdci_common(AVFormatContext *s, AVStream *st, const UID //Sampled width mxf_write_local_tag(s, 4, 0x3205); - avio_wb32(pb, stored_width); + avio_wb32(pb, display_width); //Samples height mxf_write_local_tag(s, 4, 0x3204); @@ -1208,8 +1221,9 @@ static int64_t mxf_write_cdci_common(AVFormatContext *s, AVStream *st, const UID mxf_write_local_tag(s, 4, 0x3207); avio_wb32(pb, 0); + //Display width mxf_write_local_tag(s, 4, 0x3209); - avio_wb32(pb, stored_width); + avio_wb32(pb, display_width); if (st->codecpar->height == 608) // PAL + VBI display_height = 576; @@ -1218,6 +1232,7 @@ static int64_t mxf_write_cdci_common(AVFormatContext *s, AVStream *st, const UID else display_height = st->codecpar->height; + //Display height mxf_write_local_tag(s, 4, 0x3208); avio_wb32(pb, display_height>>sc->interlaced); diff --git a/tests/fate/lavf-container.mak b/tests/fate/lavf-container.mak index 214ad6fc0d7..f7d674d9d50 100644 --- a/tests/fate/lavf-container.mak +++ b/tests/fate/lavf-container.mak @@ -9,7 +9,7 @@ FATE_LAVF_CONTAINER-$(call ENCDEC2, MPEG4, PCM_ALAW, MOV) + FATE_LAVF_CONTAINER-$(call ENCDEC, MPEG4, MOV) += mp4 FATE_LAVF_CONTAINER-$(call ENCDEC2, MPEG1VIDEO, MP2, MPEG1SYSTEM MPEGPS) += mpg FATE_LAVF_CONTAINER-$(call ENCDEC , FFV1, MXF) += mxf_ffv1 -FATE_LAVF_CONTAINER-$(call ENCDEC2, MPEG2VIDEO, PCM_S16LE, MXF) += mxf mxf_dv25 mxf_dvcpro50 +FATE_LAVF_CONTAINER-$(call ENCDEC2, MPEG2VIDEO, PCM_S16LE, MXF) += mxf mxf_dv25 mxf_dvcpro50 mxf_dvcpro100 FATE_LAVF_CONTAINER-$(call ENCDEC2, MPEG2VIDEO, PCM_S16LE, MXF_D10 MXF) += mxf_d10 FATE_LAVF_CONTAINER-$(call ENCDEC2, DNXHD, PCM_S16LE, MXF_OPATOM MXF) += mxf_opatom mxf_opatom_audio FATE_LAVF_CONTAINER-$(call ENCDEC2, MPEG4, MP2, NUT) += nut @@ -56,6 +56,7 @@ fate-lavf-mxf: CMD = lavf_container_timecode "-ar 48000 -bf 2 -threads 1" fate-lavf-mxf_d10: CMD = lavf_container "-ar 48000 -ac 2" "-r 25 -vf scale=720:576,pad=720:608:0:32 -c:v mpeg2video -g 0 -flags +ildct+low_delay -dc 10 -non_linear_quant 1 -intra_vlc 1 -qscale 1 -ps 1 -qmin 1 -rc_max_vbv_use 1 -rc_min_vbv_use 1 -pix_fmt yuv422p -minrate 30000k -maxrate 30000k -b 30000k -bufsize 1200000 -top 1 -rc_init_occupancy 1200000 -qmax 12 -f mxf_d10" fate-lavf-mxf_dv25: CMD = lavf_container "-ar 48000 -ac 2" "-r 25 -vf scale=720:576,setdar=4/3 -c:v dvvideo -pix_fmt yuv420p -b 25000k -top 0 -f mxf" fate-lavf-mxf_dvcpro50: CMD = lavf_container "-ar 48000 -ac 2" "-r 25 -vf scale=720:576,setdar=16/9 -c:v dvvideo -pix_fmt yuv422p -b 50000k -top 0 -f mxf" +fate-lavf-mxf_dvcpro100: CMD = lavf_container "-ar 48000 -ac 2" "-r 25 -vf scale=1440:1080,setdar=16/9 -c:v dvvideo -pix_fmt yuv422p -b 100000k -top 0 -f mxf" fate-lavf-mxf_ffv1: CMD = lavf_container "-an" "-r 25 -vf scale=720:576,setdar=4/3 -c:v ffv1 -level 3 -pix_fmt yuv420p -f mxf" fate-lavf-mxf_opatom: CMD = lavf_container "" "-s 1920x1080 -c:v dnxhd -pix_fmt yuv422p -vb 36M -f mxf_opatom -map 0" fate-lavf-mxf_opatom_audio: CMD = lavf_container "-ar 48000 -ac 1" "-f mxf_opatom -mxf_audio_edit_rate 25 -map 1" diff --git a/tests/ref/lavf/mxf_dvcpro100 b/tests/ref/lavf/mxf_dvcpro100 new file mode 100644 index 00000000000..8193828e2c8 --- /dev/null +++ b/tests/ref/lavf/mxf_dvcpro100 @@ -0,0 +1,3 @@ +efa5cdde54ac38b02827ee8b6d7f03a4 *tests/data/lavf/lavf.mxf_dvcpro100 +14637613 tests/data/lavf/lavf.mxf_dvcpro100 +tests/data/lavf/lavf.mxf_dvcpro100 CRC=0x245e9a5f diff --git a/tests/ref/lavf/mxf_opatom b/tests/ref/lavf/mxf_opatom index 75f85b604e6..fa722418139 100644 --- a/tests/ref/lavf/mxf_opatom +++ b/tests/ref/lavf/mxf_opatom @@ -1,3 +1,3 @@ -215ea72602bfeb70e99fc9d79fef073c *tests/data/lavf/lavf.mxf_opatom +6418766ca9b8b23fae74a80d66f26f3e *tests/data/lavf/lavf.mxf_opatom 4717625 tests/data/lavf/lavf.mxf_opatom tests/data/lavf/lavf.mxf_opatom CRC=0xb13ba2f8 From ee8fc4f355c0b0c419109085f1d47248570cf3cc Mon Sep 17 00:00:00 2001 From: Fei Wang Date: Tue, 28 Feb 2023 15:01:00 +0800 Subject: [PATCH 0497/2172] lavc/vp9: Add RGB* formats for VAAPI hwaccel Signed-off-by: Fei Wang --- libavcodec/vp9.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/libavcodec/vp9.c b/libavcodec/vp9.c index 7c0a2464467..7ff387faf48 100644 --- a/libavcodec/vp9.c +++ b/libavcodec/vp9.c @@ -239,6 +239,13 @@ static int update_size(AVCodecContext *avctx, int w, int h) case AV_PIX_FMT_YUV444P12: #if CONFIG_VP9_VAAPI_HWACCEL *fmtp++ = AV_PIX_FMT_VAAPI; +#endif + break; + case AV_PIX_FMT_GBRP: + case AV_PIX_FMT_GBRP10: + case AV_PIX_FMT_GBRP12: +#if CONFIG_VP9_VAAPI_HWACCEL + *fmtp++ = AV_PIX_FMT_VAAPI; #endif break; } From 4f555682172d838ba994df0482485973d45c6fdf Mon Sep 17 00:00:00 2001 From: "J. Dekker" Date: Thu, 23 Mar 2023 14:38:51 +0100 Subject: [PATCH 0498/2172] configure: add LTO optarg This allows users to specify an argument such as './configure --enable-lto=thin' to use ThinLTO with Clang. The old functionality with './configure --enable-lto' is preserved. Signed-off-by: J. Dekker --- configure | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/configure b/configure index 9072420d83a..cec001fb165 100755 --- a/configure +++ b/configure @@ -412,7 +412,7 @@ Toolchain options: --build-suffix=SUFFIX library name suffix [] --enable-pic build position-independent code --enable-thumb compile for Thumb instruction set - --enable-lto use link-time optimization + --enable-lto[=arg] use link-time optimization --env="ENV=override" override the environment variables Advanced options (experts only): @@ -2524,7 +2524,6 @@ CMDLINE_SELECT=" debug extra_warnings logging - lto optimizations rpath stripping @@ -4170,6 +4169,9 @@ for opt do --enable-sdl) enable sdl2 ;; + --enable-lto*) + lto=-f${opt#--enable-} + ;; --enable-*=*|--disable-*=*) eval $(echo "${opt%%=*}" | sed 's/--/action=/;s/-/ thing=/') is_in "${thing}s" $COMPONENT_LIST || die_unknown "$opt" @@ -4639,7 +4641,7 @@ icl_flags(){ # on Windows, does enable remarks so disable them here. -Wall) echo $flag -Qdiag-disable:remark ;; -std=c99) echo -Qstd=c99 ;; - -flto) echo -ipo ;; + -flto*) echo -ipo ;; esac done } @@ -4647,7 +4649,7 @@ icl_flags(){ icc_flags(){ for flag; do case $flag in - -flto) echo -ipo ;; + -flto*) echo -ipo ;; *) echo $flag ;; esac done @@ -7182,17 +7184,17 @@ fi check_optflags(){ check_cflags "$@" - enabled lto && check_ldflags "$@" + [ -n "$lto" ] && check_ldflags "$@" } check_optflags $optflags check_optflags -fno-math-errno check_optflags -fno-signed-zeros -if enabled lto; then +if [ -n "$lto" ]; then test "$cc_type" != "$ld_type" && die "LTO requires same compiler and linker" - check_cflags -flto - check_ldflags -flto $cpuflags + check_cflags $lto + check_ldflags $lto $cpuflags disable inline_asm_direct_symbol_refs fi @@ -7223,7 +7225,7 @@ if enabled icc; then # icc 11.0 and 11.1 work with ebp_available, but don't pass the test enable ebp_available # The test above does not test linking - enabled lto && disable symver_asm_label + [ -n "$lto" ] && disable symver_asm_label if enabled x86_32; then icc_version=$($cc -dumpversion) test ${icc_version%%.*} -ge 11 && From f7abe92bd7939b6aeeb2393fe141033e733305d4 Mon Sep 17 00:00:00 2001 From: "J. Dekker" Date: Thu, 2 Mar 2023 12:13:25 +0100 Subject: [PATCH 0499/2172] avcodec/er: remove check for fields This change on its own is almost certainly not correct; however, in testing, many samples show notable improvement. Signed-off-by: J. Dekker --- libavcodec/error_resilience.c | 9 +++++++-- libavcodec/error_resilience.h | 1 + 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/libavcodec/error_resilience.c b/libavcodec/error_resilience.c index 2aa6f1d8640..bd7050062ce 100644 --- a/libavcodec/error_resilience.c +++ b/libavcodec/error_resilience.c @@ -805,8 +805,7 @@ void ff_er_frame_start(ERContext *s) static int er_supported(ERContext *s) { if(s->avctx->hwaccel && s->avctx->hwaccel->decode_slice || - !s->cur_pic.f || - s->cur_pic.field_picture + !s->cur_pic.f ) return 0; return 1; @@ -908,6 +907,12 @@ void ff_er_frame_end(ERContext *s) (s->avctx->skip_top + s->avctx->skip_bottom)) { return; } + + if (!s->warned_fields && (s->cur_pic.field_picture || s->cur_pic.f->interlaced_frame)) { + av_log(s->avctx, AV_LOG_WARNING, "Error concealment is not fully implemented for field pictures.\n"); + s->warned_fields = 1; + } + linesize = s->cur_pic.f->linesize; if ( s->avctx->codec_id == AV_CODEC_ID_MPEG2VIDEO diff --git a/libavcodec/error_resilience.h b/libavcodec/error_resilience.h index 47cc8a4fc67..55efacaccc5 100644 --- a/libavcodec/error_resilience.h +++ b/libavcodec/error_resilience.h @@ -87,6 +87,7 @@ typedef struct ERContext { int (*mv)[2][4][2], int mb_x, int mb_y, int mb_intra, int mb_skipped); void *opaque; + int warned_fields; } ERContext; void ff_er_frame_start(ERContext *s); From c38370dc5d3068f302cf8d86c7c85c31f7550429 Mon Sep 17 00:00:00 2001 From: Fei Wang Date: Mon, 27 Mar 2023 13:25:53 +0800 Subject: [PATCH 0500/2172] avcodec/hevcdec: Replace number with enum Keep same style with IS_IDR()/IS_BLA(). Signed-off-by: Fei Wang --- libavcodec/hevcdec.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavcodec/hevcdec.h b/libavcodec/hevcdec.h index aab816791e1..94609e46993 100644 --- a/libavcodec/hevcdec.h +++ b/libavcodec/hevcdec.h @@ -75,7 +75,7 @@ #define IS_IDR(s) ((s)->nal_unit_type == HEVC_NAL_IDR_W_RADL || (s)->nal_unit_type == HEVC_NAL_IDR_N_LP) #define IS_BLA(s) ((s)->nal_unit_type == HEVC_NAL_BLA_W_RADL || (s)->nal_unit_type == HEVC_NAL_BLA_W_LP || \ (s)->nal_unit_type == HEVC_NAL_BLA_N_LP) -#define IS_IRAP(s) ((s)->nal_unit_type >= 16 && (s)->nal_unit_type <= 23) +#define IS_IRAP(s) ((s)->nal_unit_type >= HEVC_NAL_BLA_W_LP && (s)->nal_unit_type <= HEVC_NAL_RSV_IRAP_VCL23) enum RPSType { ST_CURR_BEF = 0, From 9026f446d64b5d64fc3a281c86f8f02b8401cbaf Mon Sep 17 00:00:00 2001 From: Fei Wang Date: Mon, 27 Mar 2023 13:26:27 +0800 Subject: [PATCH 0501/2172] lavc/hevcdec: Initialize missed parameters in slice header for IDR frame Signed-off-by: Fei Wang --- libavcodec/hevcdec.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/libavcodec/hevcdec.c b/libavcodec/hevcdec.c index 121ceb4e751..1a0beac9011 100644 --- a/libavcodec/hevcdec.c +++ b/libavcodec/hevcdec.c @@ -732,8 +732,13 @@ static int hls_slice_header(HEVCContext *s) else sh->slice_temporal_mvp_enabled_flag = 0; } else { - s->sh.short_term_rps = NULL; - s->poc = 0; + s->poc = 0; + sh->pic_order_cnt_lsb = 0; + sh->short_term_ref_pic_set_sps_flag = 0; + sh->short_term_ref_pic_set_size = 0; + sh->short_term_rps = NULL; + sh->long_term_ref_pic_set_size = 0; + sh->slice_temporal_mvp_enabled_flag = 0; } /* 8.3.1 */ From c549bc9d96b901c1df1e564be541ed052e92d943 Mon Sep 17 00:00:00 2001 From: Fei Wang Date: Mon, 27 Mar 2023 13:26:53 +0800 Subject: [PATCH 0502/2172] lavc/vaapi_hevc: Remove duplicate code Signed-off-by: Fei Wang --- libavcodec/vaapi_hevc.c | 6 ------ 1 file changed, 6 deletions(-) diff --git a/libavcodec/vaapi_hevc.c b/libavcodec/vaapi_hevc.c index 0e5da15e53e..984af75c843 100644 --- a/libavcodec/vaapi_hevc.c +++ b/libavcodec/vaapi_hevc.c @@ -542,12 +542,6 @@ static int vaapi_hevc_decode_slice(AVCodecContext *avctx, pic->last_slice_param.rext.ChromaOffsetL0[i][1] = sh->chroma_offset_l0[i][1]; } - for (i = 0; i < 15 && i < sh->nb_refs[L0]; i++) { - pic->last_slice_param.rext.luma_offset_l0[i] = sh->luma_offset_l0[i]; - pic->last_slice_param.rext.ChromaOffsetL0[i][0] = sh->chroma_offset_l0[i][0]; - pic->last_slice_param.rext.ChromaOffsetL0[i][1] = sh->chroma_offset_l0[i][1]; - } - if (sh->slice_type == HEVC_SLICE_B) { for (i = 0; i < 15 && i < sh->nb_refs[L1]; i++) { pic->last_slice_param.rext.luma_offset_l1[i] = sh->luma_offset_l1[i]; From 2e61ae2cbe5e046d38f2592e2ccc5944520c3430 Mon Sep 17 00:00:00 2001 From: "J. Dekker" Date: Mon, 27 Mar 2023 14:00:00 +0200 Subject: [PATCH 0503/2172] fate: specify EC-off for damaged inter samples The previous commit allowed turning on error correction for interlaced samples. Turning it off amounts to a no-op for FATE. These samples should be tested with EC1-3 (guess_mvs/deblock/favor_inter) additionally. Signed-off-by: J. Dekker --- tests/fate/filter-video.mak | 14 +++++++------- tests/fate/video.mak | 2 +- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/tests/fate/filter-video.mak b/tests/fate/filter-video.mak index c588286c38e..e6de7de734d 100644 --- a/tests/fate/filter-video.mak +++ b/tests/fate/filter-video.mak @@ -12,21 +12,21 @@ FATE_FILTER_SAMPLES-$(call FILTERDEMDEC, PERMS DELOGO, RM, RV30) += fate-filter- fate-filter-delogo: CMD = framecrc -i $(TARGET_SAMPLES)/real/rv30.rm -vf perms=random,delogo=show=0:x=290:y=25:w=26:h=16 -an FATE_BWDIF-$(call FILTERDEMDEC, BWDIF, MPEGTS, MPEG2VIDEO) += fate-filter-bwdif-mode0 fate-filter-bwdif-mode1 -fate-filter-bwdif-mode0: CMD = framecrc -flags bitexact -idct simple -i $(TARGET_SAMPLES)/mpeg2/mpeg2_field_encoding.ts -frames:v 30 -vf bwdif=send_frame -fate-filter-bwdif-mode1: CMD = framecrc -flags bitexact -idct simple -i $(TARGET_SAMPLES)/mpeg2/mpeg2_field_encoding.ts -frames:v 59 -vf bwdif=send_field +fate-filter-bwdif-mode0: CMD = framecrc -ec 0 -flags bitexact -idct simple -i $(TARGET_SAMPLES)/mpeg2/mpeg2_field_encoding.ts -frames:v 30 -vf bwdif=send_frame +fate-filter-bwdif-mode1: CMD = framecrc -ec 0 -flags bitexact -idct simple -i $(TARGET_SAMPLES)/mpeg2/mpeg2_field_encoding.ts -frames:v 59 -vf bwdif=send_field FATE_BWDIF-$(call FILTERDEMDEC, BWDIF SCALE, MPEGTS, MPEG2VIDEO) += fate-filter-bwdif10 -fate-filter-bwdif10: CMD = framecrc -flags bitexact -idct simple -i $(TARGET_SAMPLES)/mpeg2/mpeg2_field_encoding.ts -flags bitexact -pix_fmt yuv420p10le -frames:v 30 -vf scale,bwdif=0 +fate-filter-bwdif10: CMD = framecrc -ec 0 -flags bitexact -idct simple -i $(TARGET_SAMPLES)/mpeg2/mpeg2_field_encoding.ts -flags bitexact -pix_fmt yuv420p10le -frames:v 30 -vf scale,bwdif=0 FATE_FILTER_SAMPLES-yes += $(FATE_BWDIF-yes) FATE_YADIF-$(call FILTERDEMDEC, YADIF, MPEGTS, MPEG2VIDEO) += fate-filter-yadif-mode0 fate-filter-yadif-mode1 -fate-filter-yadif-mode0: CMD = framecrc -flags bitexact -idct simple -i $(TARGET_SAMPLES)/mpeg2/mpeg2_field_encoding.ts -frames:v 30 -vf yadif=0 -fate-filter-yadif-mode1: CMD = framecrc -flags bitexact -idct simple -i $(TARGET_SAMPLES)/mpeg2/mpeg2_field_encoding.ts -frames:v 59 -vf yadif=1 +fate-filter-yadif-mode0: CMD = framecrc -ec 0 -flags bitexact -idct simple -i $(TARGET_SAMPLES)/mpeg2/mpeg2_field_encoding.ts -frames:v 30 -vf yadif=0 +fate-filter-yadif-mode1: CMD = framecrc -ec 0 -flags bitexact -idct simple -i $(TARGET_SAMPLES)/mpeg2/mpeg2_field_encoding.ts -frames:v 59 -vf yadif=1 FATE_YADIF-$(call FILTERDEMDEC, YADIF SCALE, MPEGTS, MPEG2VIDEO) += fate-filter-yadif10 fate-filter-yadif16 -fate-filter-yadif10: CMD = framecrc -flags bitexact -idct simple -i $(TARGET_SAMPLES)/mpeg2/mpeg2_field_encoding.ts -flags bitexact -pix_fmt yuv420p10le -frames:v 30 -vf scale,yadif=0 -fate-filter-yadif16: CMD = framecrc -flags bitexact -idct simple -i $(TARGET_SAMPLES)/mpeg2/mpeg2_field_encoding.ts -flags bitexact -pix_fmt yuv420p16le -frames:v 30 -vf scale,yadif=0 +fate-filter-yadif10: CMD = framecrc -ec 0 -flags bitexact -idct simple -i $(TARGET_SAMPLES)/mpeg2/mpeg2_field_encoding.ts -flags bitexact -pix_fmt yuv420p10le -frames:v 30 -vf scale,yadif=0 +fate-filter-yadif16: CMD = framecrc -ec 0 -flags bitexact -idct simple -i $(TARGET_SAMPLES)/mpeg2/mpeg2_field_encoding.ts -flags bitexact -pix_fmt yuv420p16le -frames:v 30 -vf scale,yadif=0 FATE_FILTER_SAMPLES-yes += $(FATE_YADIF-yes) diff --git a/tests/fate/video.mak b/tests/fate/video.mak index d7639a39789..a2011d0dad8 100644 --- a/tests/fate/video.mak +++ b/tests/fate/video.mak @@ -255,7 +255,7 @@ fate-mpeg2-field-enc: CMD = framecrc -flags +bitexact -idct simple -i $(TARGET_S fate-mpeg2-ticket186: CMD = framecrc -flags +bitexact -idct simple -i $(TARGET_SAMPLES)/mpeg2/t.mpg -an FATE_VIDEO-$(call FRAMECRC, MPEGVIDEO, MPEG2VIDEO) += fate-mpeg2-ticket6677 -fate-mpeg2-ticket6677: CMD = framecrc -flags +bitexact -idct simple -i $(TARGET_SAMPLES)/mpeg2/sony-ct3.bs +fate-mpeg2-ticket6677: CMD = framecrc -ec 0 -flags +bitexact -idct simple -i $(TARGET_SAMPLES)/mpeg2/sony-ct3.bs FATE_VIDEO-$(call FRAMECRC, MV, MVC1, SCALE_FILTER) += fate-mv-mvc1 fate-mv-mvc1: CMD = framecrc -i $(TARGET_SAMPLES)/mv/posture.mv -an -frames 25 -pix_fmt rgb555le -vf scale From 3f4c41839d5d3d02a12cc6a7407e6586996040e7 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Mon, 27 Mar 2023 09:47:39 +0200 Subject: [PATCH 0504/2172] lavf: return AVERROR_EOF rather than EIO on EOF --- libavformat/anm.c | 2 +- libavformat/dauddec.c | 2 +- libavformat/filmstripdec.c | 2 +- libavformat/idroqdec.c | 2 +- libavformat/sol.c | 3 ++- libavformat/vc1test.c | 2 +- 6 files changed, 7 insertions(+), 6 deletions(-) diff --git a/libavformat/anm.c b/libavformat/anm.c index 7feba4ed1e7..f2ac6958a9a 100644 --- a/libavformat/anm.c +++ b/libavformat/anm.c @@ -172,7 +172,7 @@ static int read_packet(AVFormatContext *s, int tmp, record_size; if (avio_feof(s->pb)) - return AVERROR(EIO); + return AVERROR_EOF; if (anm->page < 0) return anm->page; diff --git a/libavformat/dauddec.c b/libavformat/dauddec.c index dbbd39a3b40..0cbf7e4e368 100644 --- a/libavformat/dauddec.c +++ b/libavformat/dauddec.c @@ -41,7 +41,7 @@ static int daud_packet(AVFormatContext *s, AVPacket *pkt) { AVIOContext *pb = s->pb; int ret, size; if (avio_feof(pb)) - return AVERROR(EIO); + return AVERROR_EOF; size = avio_rb16(pb); avio_rb16(pb); // unknown ret = av_get_packet(pb, pkt, size); diff --git a/libavformat/filmstripdec.c b/libavformat/filmstripdec.c index 2b6ba63fcf0..000f807181d 100644 --- a/libavformat/filmstripdec.c +++ b/libavformat/filmstripdec.c @@ -86,7 +86,7 @@ static int read_packet(AVFormatContext *s, AVStream *st = s->streams[0]; if (avio_feof(s->pb)) - return AVERROR(EIO); + return AVERROR_EOF; pkt->dts = avio_tell(s->pb) / (st->codecpar->width * (int64_t)(st->codecpar->height + film->leading) * 4); pkt->size = av_get_packet(s->pb, pkt, st->codecpar->width * st->codecpar->height * 4); avio_skip(s->pb, st->codecpar->width * (int64_t) film->leading * 4); diff --git a/libavformat/idroqdec.c b/libavformat/idroqdec.c index c9fc972780a..01ea2bb77ba 100644 --- a/libavformat/idroqdec.c +++ b/libavformat/idroqdec.c @@ -107,7 +107,7 @@ static int roq_read_packet(AVFormatContext *s, while (!packet_read) { if (avio_feof(s->pb)) - return AVERROR(EIO); + return AVERROR_EOF; /* get the next chunk preamble */ if ((ret = avio_read(pb, preamble, RoQ_CHUNK_PREAMBLE_SIZE)) != diff --git a/libavformat/sol.c b/libavformat/sol.c index b92cfb36fee..a276642728c 100644 --- a/libavformat/sol.c +++ b/libavformat/sol.c @@ -127,7 +127,8 @@ static int sol_read_packet(AVFormatContext *s, int ret; if (avio_feof(s->pb)) - return AVERROR(EIO); + return AVERROR_EOF; + ret= av_get_packet(s->pb, pkt, MAX_SIZE); if (ret < 0) return ret; diff --git a/libavformat/vc1test.c b/libavformat/vc1test.c index 67edc699c5f..f63ffee69bb 100644 --- a/libavformat/vc1test.c +++ b/libavformat/vc1test.c @@ -101,7 +101,7 @@ static int vc1t_read_packet(AVFormatContext *s, uint32_t pts; if(avio_feof(pb)) - return AVERROR(EIO); + return AVERROR_EOF; frame_size = avio_rl24(pb); if(avio_r8(pb) & 0x80) From 9bf1848acfb7cbdb7f8dcaa07649467dfb3cec7b Mon Sep 17 00:00:00 2001 From: "U. Artie Eoff" Date: Fri, 24 Mar 2023 12:14:58 -0400 Subject: [PATCH 0505/2172] lavfi: add hwdevice flag to hwupload/hwmap This fixes a regression introduced by: commit 3f63685c3554aea7f72bab1fdbde440820816d37 and commit 632c34993195f716e9fa575af3de80d07fd50991 ...where command-lines like: ffmpeg -v verbose -hwaccel qsv \ -init_hw_device qsv=qsv,child_device=/dev/dri/renderD128 \ -hwaccel_output_format qsv -f rawvideo -pix_fmt yuv420p \ -s:v 352x288 -r:v 25 -i input.yuv \ -vf 'format=nv12,hwupload=extra_hw_frames=120' \ -an -c:v h264_qsv -y output.h264 ffmpeg -v verbose -hwaccel qsv \ -init_hw_device qsv=qsv,child_device=/dev/dri/renderD128 \ -hwaccel_output_format qsv -f rawvideo -pix_fmt nv12 \ -s:v 352x288 -r:v 25 -i input.yuv \ -vf 'format=nv12|qsv,hwupload=extra_hw_frames=16,vpp_qsv=procamp=1:saturation=1.0,hwdownload,format=nv12' \ -pix_fmt nv12 -f rawvideo -fps_mode passthrough -an -y output.yuv ...produced errors like: [hwupload @ 0x55b6171d0dc0] A hardware device reference is required to upload frames to. [Parsed_hwupload_1 @ 0x55b6172053c0] Query format failed for 'Parsed_hwupload_1': Invalid argument Error reinitializing filters! Failed to inject frame into filter network: Invalid argument Signed-off-by: U. Artie Eoff Signed-off-by: Anton Khirnov --- libavfilter/vf_hwmap.c | 1 + libavfilter/vf_hwupload.c | 1 + 2 files changed, 2 insertions(+) diff --git a/libavfilter/vf_hwmap.c b/libavfilter/vf_hwmap.c index 2e03dfc1fec..e246b22603b 100644 --- a/libavfilter/vf_hwmap.c +++ b/libavfilter/vf_hwmap.c @@ -427,4 +427,5 @@ const AVFilter ff_vf_hwmap = { FILTER_OUTPUTS(hwmap_outputs), FILTER_QUERY_FUNC(hwmap_query_formats), .flags_internal = FF_FILTER_FLAG_HWFRAME_AWARE, + .flags = AVFILTER_FLAG_HWDEVICE, }; diff --git a/libavfilter/vf_hwupload.c b/libavfilter/vf_hwupload.c index dbc41734ccc..ef61bb41375 100644 --- a/libavfilter/vf_hwupload.c +++ b/libavfilter/vf_hwupload.c @@ -258,4 +258,5 @@ const AVFilter ff_vf_hwupload = { FILTER_OUTPUTS(hwupload_outputs), FILTER_QUERY_FUNC(hwupload_query_formats), .flags_internal = FF_FILTER_FLAG_HWFRAME_AWARE, + .flags = AVFILTER_FLAG_HWDEVICE, }; From 992e984fa86ed4447082be4915996908b6acf3b5 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Tue, 18 Oct 2022 13:37:25 +0200 Subject: [PATCH 0506/2172] tools/decode_simple: always call process_frame(NULL) at the end Currently this would not be done if max_frames is triggered. Makes no difference in either of the tools currently using decode_simple, but may be important in future tools. --- tools/decode_simple.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tools/decode_simple.c b/tools/decode_simple.c index e02323064df..8a9e7c5f71c 100644 --- a/tools/decode_simple.c +++ b/tools/decode_simple.c @@ -73,7 +73,7 @@ int ds_run(DecodeContext *dc) while (ret >= 0) { ret = av_read_frame(dc->demuxer, dc->pkt); if (ret < 0) - goto flush; + break; if (dc->pkt->stream_index != dc->stream->index) { av_packet_unref(dc->pkt); continue; @@ -91,10 +91,9 @@ int ds_run(DecodeContext *dc) fprintf(stderr, "Error decoding: %d\n", ret); return ret; } else if (ret > 0) - return 0; + goto finish; } -flush: avcodec_send_packet(dc->decoder, NULL); ret = decode_read(dc, 1); if (ret < 0) { @@ -102,7 +101,8 @@ int ds_run(DecodeContext *dc) return ret; } - return 0; +finish: + return dc->process_frame(dc, NULL); } void ds_free(DecodeContext *dc) From 554c6d7cb1aa529f8189af3f4655283d39291809 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Tue, 18 Oct 2022 13:37:25 +0200 Subject: [PATCH 0507/2172] tools/decode_simple: initialize decoder parameters with container info --- tools/decode_simple.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/tools/decode_simple.c b/tools/decode_simple.c index 8a9e7c5f71c..6532e368d46 100644 --- a/tools/decode_simple.c +++ b/tools/decode_simple.c @@ -149,6 +149,10 @@ int ds_open(DecodeContext *dc, const char *url, int stream_idx) if (!dc->decoder) return AVERROR(ENOMEM); + ret = avcodec_parameters_to_context(dc->decoder, dc->stream->codecpar); + if (ret < 0) + goto fail; + return 0; fail: From ea748c7a4dd2a3c6b6637f2bc1b10cc9c1e7c6e2 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Sun, 17 Jul 2022 20:27:36 +0200 Subject: [PATCH 0508/2172] tools: add an AV_CODEC_CAP_ENCODER_RECON_FRAME test tool --- Makefile | 2 + tools/Makefile | 3 +- tools/enc_recon_frame_test.c | 393 +++++++++++++++++++++++++++++++++++ 3 files changed, 397 insertions(+), 1 deletion(-) create mode 100644 tools/enc_recon_frame_test.c diff --git a/Makefile b/Makefile index 1fb742f3909..bf1b69f96b0 100644 --- a/Makefile +++ b/Makefile @@ -67,6 +67,8 @@ tools/target_io_dem_fuzzer$(EXESUF): tools/target_io_dem_fuzzer.o $(FF_DEP_LIBS) tools/enum_options$(EXESUF): ELIBS = $(FF_EXTRALIBS) tools/enum_options$(EXESUF): $(FF_DEP_LIBS) +tools/enc_recon_frame_test$(EXESUF): $(FF_DEP_LIBS) +tools/enc_recon_frame_test$(EXESUF): ELIBS = $(FF_EXTRALIBS) tools/scale_slice_test$(EXESUF): $(FF_DEP_LIBS) tools/scale_slice_test$(EXESUF): ELIBS = $(FF_EXTRALIBS) tools/sofa2wavs$(EXESUF): ELIBS = $(FF_EXTRALIBS) diff --git a/tools/Makefile b/tools/Makefile index 4afa23342dc..dee6a416688 100644 --- a/tools/Makefile +++ b/tools/Makefile @@ -1,4 +1,4 @@ -TOOLS = enum_options qt-faststart scale_slice_test trasher uncoded_frame +TOOLS = enc_recon_frame_test enum_options qt-faststart scale_slice_test trasher uncoded_frame TOOLS-$(CONFIG_LIBMYSOFA) += sofa2wavs TOOLS-$(CONFIG_ZLIB) += cws2fws @@ -17,6 +17,7 @@ tools/target_dem_fuzzer.o: tools/target_dem_fuzzer.c tools/target_io_dem_fuzzer.o: tools/target_dem_fuzzer.c $(COMPILE_C) -DIO_FLAT=0 +tools/enc_recon_frame_test$(EXESUF): tools/decode_simple.o tools/venc_data_dump$(EXESUF): tools/decode_simple.o tools/scale_slice_test$(EXESUF): tools/decode_simple.o diff --git a/tools/enc_recon_frame_test.c b/tools/enc_recon_frame_test.c new file mode 100644 index 00000000000..d23accd49d4 --- /dev/null +++ b/tools/enc_recon_frame_test.c @@ -0,0 +1,393 @@ +/* + * copyright (c) 2022 Anton Khirnov + * + * 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 + */ + +/* A test for AV_CODEC_FLAG_RECON_FRAME + * TODO: dump reconstructed frames to disk */ + +#include +#include +#include + +#include "decode_simple.h" + +#include "libavutil/adler32.h" +#include "libavutil/common.h" +#include "libavutil/error.h" +#include "libavutil/frame.h" +#include "libavutil/imgutils.h" +#include "libavutil/opt.h" + +#include "libavformat/avformat.h" + +#include "libavcodec/avcodec.h" +#include "libavcodec/codec.h" + +#include "libswscale/swscale.h" + +typedef struct FrameChecksum { + int64_t ts; + uint32_t checksum[4]; +} FrameChecksum; + +typedef struct PrivData { + AVCodecContext *enc; + AVCodecContext *dec; + + int64_t pts_in; + + AVPacket *pkt; + AVFrame *frame, *frame_recon; + + struct SwsContext *scaler; + + FrameChecksum *checksums_decoded; + size_t nb_checksums_decoded; + FrameChecksum *checksums_recon; + size_t nb_checksums_recon; +} PrivData; + +static int frame_hash(FrameChecksum **pc, size_t *nb_c, int64_t ts, + const AVFrame *frame) +{ + FrameChecksum *c; + int shift_h[4] = { 0 }, shift_v[4] = { 0 }; + + c = av_realloc_array(*pc, *nb_c + 1, sizeof(*c)); + if (!c) + return AVERROR(ENOMEM); + *pc = c; + (*nb_c)++; + + c += *nb_c - 1; + memset(c, 0, sizeof(*c)); + + av_pix_fmt_get_chroma_sub_sample(frame->format, &shift_h[1], &shift_v[1]); + shift_h[2] = shift_h[1]; + shift_v[2] = shift_v[1]; + + c->ts = ts; + for (int p = 0; frame->data[p]; p++) { + const uint8_t *data = frame->data[p]; + int linesize = av_image_get_linesize(frame->format, frame->width, p); + uint32_t checksum = 0; + + for (int j = 0; j < frame->height >> shift_v[p]; j++) { + checksum = av_adler32_update(checksum, data, linesize); + data += frame->linesize[p]; + } + + c->checksum[p] = checksum; + } + + return 0; +} + +static int recon_frame_process(PrivData *pd, const AVPacket *pkt) +{ + AVFrame *f = pd->frame_recon; + int ret; + + ret = avcodec_receive_frame(pd->enc, f); + if (ret < 0) { + fprintf(stderr, "Error retrieving a reconstructed frame\n"); + return ret; + } + + // the encoder's internal format (in which the reconsturcted frames are + // exported) may be different from the user-facing pixel format + if (f->format != pd->enc->pix_fmt) { + if (!pd->scaler) { + pd->scaler = sws_getContext(f->width, f->height, f->format, + f->width, f->height, pd->enc->pix_fmt, + SWS_BITEXACT, NULL, NULL, NULL); + if (!pd->scaler) + return AVERROR(ENOMEM); + } + + ret = sws_scale_frame(pd->scaler, pd->frame, f); + if (ret < 0) { + fprintf(stderr, "Error converting pixel formats\n"); + return ret; + } + + av_frame_unref(f); + f = pd->frame; + } + + ret = frame_hash(&pd->checksums_recon, &pd->nb_checksums_recon, + pkt->pts, f); + av_frame_unref(f); + + return 0; +} + +static int process_frame(DecodeContext *dc, AVFrame *frame) +{ + PrivData *pd = dc->opaque; + int ret; + + if (!avcodec_is_open(pd->enc)) { + if (!frame) { + fprintf(stderr, "No input frames were decoded\n"); + return AVERROR_INVALIDDATA; + } + + pd->enc->width = frame->width; + pd->enc->height = frame->height; + pd->enc->pix_fmt = frame->format; + pd->enc->thread_count = dc->decoder->thread_count; + pd->enc->thread_type = dc->decoder->thread_type; + + // real timestamps do not matter for this test, so we just + // pretend the input is 25fps CFR to avoid any timestamp issues + pd->enc->time_base = (AVRational){ 1, 25 }; + + ret = avcodec_open2(pd->enc, NULL, NULL); + if (ret < 0) { + fprintf(stderr, "Error opening the encoder\n"); + return ret; + } + } + + if (frame) { + frame->pts = pd->pts_in++; + + // avoid forcing coded frame type + frame->pict_type = AV_PICTURE_TYPE_NONE; + } + + ret = avcodec_send_frame(pd->enc, frame); + if (ret < 0) { + fprintf(stderr, "Error submitting a frame for encoding\n"); + return ret; + } + + while (1) { + AVPacket *pkt = pd->pkt; + + ret = avcodec_receive_packet(pd->enc, pkt); + if (ret == AVERROR(EAGAIN)) + break; + else if (ret == AVERROR_EOF) + pkt = NULL; + else if (ret < 0) { + fprintf(stderr, "Error receiving a frame from the encoder\n"); + return ret; + } + + if (pkt) { + ret = recon_frame_process(pd, pkt); + if (ret < 0) + return ret; + } + + if (!avcodec_is_open(pd->dec)) { + if (!pkt) { + fprintf(stderr, "No packets were received from the encoder\n"); + return AVERROR(EINVAL); + } + + pd->dec->width = pd->enc->width; + pd->dec->height = pd->enc->height; + pd->dec->pix_fmt = pd->enc->pix_fmt; + pd->dec->thread_count = dc->decoder->thread_count; + pd->dec->thread_type = dc->decoder->thread_type; + if (pd->enc->extradata_size) { + pd->dec->extradata = av_memdup(pd->enc->extradata, + pd->enc->extradata_size + AV_INPUT_BUFFER_PADDING_SIZE); + if (!pd->dec->extradata) + return AVERROR(ENOMEM); + } + + ret = avcodec_open2(pd->dec, NULL, NULL); + if (ret < 0) { + fprintf(stderr, "Error opening the decoder\n"); + return ret; + } + } + + ret = avcodec_send_packet(pd->dec, pkt); + if (ret < 0) { + fprintf(stderr, "Error sending a packet to decoder\n"); + return ret; + } + + while (1) { + ret = avcodec_receive_frame(pd->dec, pd->frame); + if (ret == AVERROR(EAGAIN)) + break; + else if (ret == AVERROR_EOF) + return 0; + else if (ret < 0) { + fprintf(stderr, "Error receving a frame from decoder\n"); + return ret; + } + + ret = frame_hash(&pd->checksums_decoded, &pd->nb_checksums_decoded, + pd->frame->pts, pd->frame); + av_frame_unref(pd->frame); + if (ret < 0) + return ret; + } + + } + + return 0; +} + +static int frame_checksum_compare(const void *a, const void *b) +{ + const FrameChecksum *ca = a; + const FrameChecksum *cb = b; + if (ca->ts == cb->ts) + return 0; + return FFSIGN(ca->ts - cb->ts); +} + +int main(int argc, char **argv) +{ + PrivData pd; + DecodeContext dc; + + const char *filename, *enc_name, *enc_opts, *thread_type = NULL, *nb_threads = NULL; + const AVCodec *enc, *dec; + int ret = 0, max_frames = 0; + + if (argc < 4) { + fprintf(stderr, + "Usage: %s " + "[ [ ]\n", + argv[0]); + return 0; + } + + filename = argv[1]; + enc_name = argv[2]; + enc_opts = argv[3]; + if (argc >= 5) + max_frames = strtol(argv[4], NULL, 0); + if (argc >= 6) + nb_threads = argv[5]; + if (argc >= 7) + thread_type = argv[6]; + + memset(&dc, 0, sizeof(dc)); + memset(&pd, 0, sizeof(pd)); + + enc = avcodec_find_encoder_by_name(enc_name); + if (!enc) { + fprintf(stderr, "No such encoder: %s\n", enc_name); + return 1; + } + if (!(enc->capabilities & AV_CODEC_CAP_ENCODER_RECON_FRAME)) { + fprintf(stderr, "Encoder '%s' cannot ouput reconstructed frames\n", + enc->name); + return 1; + } + + dec = avcodec_find_decoder(enc->id); + if (!dec) { + fprintf(stderr, "No decoder for: %s\n", avcodec_get_name(enc->id)); + return 1; + } + + pd.enc = avcodec_alloc_context3(enc); + if (!pd.enc) { + fprintf(stderr, "Error allocating encoder\n"); + return 1; + } + + ret = av_set_options_string(pd.enc, enc_opts, "=", ","); + if (ret < 0) { + fprintf(stderr, "Error setting encoder options\n"); + goto fail; + } + pd.enc->flags |= AV_CODEC_FLAG_RECON_FRAME | AV_CODEC_FLAG_BITEXACT; + + pd.dec = avcodec_alloc_context3(dec); + if (!pd.dec) { + fprintf(stderr, "Error allocating decoder\n"); + goto fail; + } + + pd.dec->flags |= AV_CODEC_FLAG_BITEXACT; + pd.dec->err_recognition |= AV_EF_CRCCHECK; + + pd.frame = av_frame_alloc(); + pd.frame_recon = av_frame_alloc(); + pd.pkt = av_packet_alloc(); + if (!pd.frame ||!pd.frame_recon || !pd.pkt) { + ret = 1; + goto fail; + } + + ret = ds_open(&dc, filename, 0); + if (ret < 0) { + fprintf(stderr, "Error opening the file\n"); + goto fail; + } + + dc.process_frame = process_frame; + dc.opaque = &pd; + dc.max_frames = max_frames; + + ret = av_dict_set(&dc.decoder_opts, "threads", nb_threads, 0); + ret |= av_dict_set(&dc.decoder_opts, "thread_type", thread_type, 0); + + ret = ds_run(&dc); + if (ret < 0) + goto fail; + + if (pd.nb_checksums_decoded != pd.nb_checksums_recon) { + fprintf(stderr, "Mismatching frame counts: recon=%zu decoded=%zu\n", + pd.nb_checksums_recon, pd.nb_checksums_decoded); + ret = 1; + goto fail; + } + + // reconstructed frames are in coded order, sort them by pts into presentation order + qsort(pd.checksums_recon, pd.nb_checksums_recon, sizeof(*pd.checksums_recon), + frame_checksum_compare); + + for (size_t i = 0; i < pd.nb_checksums_decoded; i++) { + const FrameChecksum *d = &pd.checksums_decoded[i]; + const FrameChecksum *r = &pd.checksums_recon[i]; + + for (int p = 0; p < FF_ARRAY_ELEMS(d->checksum); p++) + if (d->checksum[p] != r->checksum[p]) { + fprintf(stderr, "Checksum mismatch in frame ts=%"PRId64", plane %d\n", + d->ts, p); + ret = 1; + goto fail; + } + } + fprintf(stderr, "All %zu encoded frames match\n", pd.nb_checksums_decoded); + +fail: + avcodec_free_context(&pd.enc); + avcodec_free_context(&pd.dec); + av_freep(&pd.checksums_decoded); + av_freep(&pd.checksums_recon); + av_frame_free(&pd.frame); + av_frame_free(&pd.frame_recon); + av_packet_free(&pd.pkt); + ds_free(&dc); + return !!ret; +} From 5f87c9915d9c7f1f3565cb207b8ebf5c42a9cd5e Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Fri, 24 Mar 2023 10:00:56 +0100 Subject: [PATCH 0509/2172] lavc/avcodec: fix documentation typo --- libavcodec/avcodec.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h index 30f1d312f4e..d1bcb3026cd 100644 --- a/libavcodec/avcodec.h +++ b/libavcodec/avcodec.h @@ -243,7 +243,7 @@ typedef struct RcOverride{ #define AV_CODEC_FLAG_RECON_FRAME (1 << 6) /** * @par decoding - * Request the decoder to propagate each packets AVPacket.opaque and + * Request the decoder to propagate each packet's AVPacket.opaque and * AVPacket.opaque_ref to its corresponding output AVFrame. * * @par encoding: From 83eb52323c5a2664a9802cb8fc3fc2784c733dfb Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Fri, 24 Mar 2023 10:03:39 +0100 Subject: [PATCH 0510/2172] lavc: expand doxy for AV_CODEC_FLAG_RECON_FRAME --- libavcodec/avcodec.h | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h index d1bcb3026cd..7a6eb4c0e2f 100644 --- a/libavcodec/avcodec.h +++ b/libavcodec/avcodec.h @@ -239,6 +239,15 @@ typedef struct RcOverride{ * * Should only be used with encoders flagged with the * @ref AV_CODEC_CAP_ENCODER_RECON_FRAME capability. + * + * @note + * Each reconstructed frame returned by the encoder corresponds to the last + * encoded packet, i.e. the frames are returned in coded order rather than + * presentation order. + * + * @note + * Frame parameters (like pixel format or dimensions) do not have to match the + * AVCodecContext values. Make sure to use the values from the returned frame. */ #define AV_CODEC_FLAG_RECON_FRAME (1 << 6) /** From b62632e2c93bc77aa5f1a4de8f2ad40980ef8d65 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Fri, 24 Mar 2023 10:07:44 +0100 Subject: [PATCH 0511/2172] lavc: turn mentions of AV_CODEC_FLAG_RECON_FRAME in doxy into links --- libavcodec/avcodec.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h index 7a6eb4c0e2f..18ca0e24943 100644 --- a/libavcodec/avcodec.h +++ b/libavcodec/avcodec.h @@ -2665,7 +2665,7 @@ int avcodec_send_packet(AVCodecContext *avctx, const AVPacket *avpkt); /** * Return decoded output data from a decoder or encoder (when the - * AV_CODEC_FLAG_RECON_FRAME flag is used). + * @ref AV_CODEC_FLAG_RECON_FRAME flag is used). * * @param avctx codec context * @param frame This will be set to a reference-counted video or audio @@ -2679,7 +2679,7 @@ int avcodec_send_packet(AVCodecContext *avctx, const AVPacket *avpkt); * @retval AVERROR_EOF the codec has been fully flushed, and there will be * no more output frames * @retval AVERROR(EINVAL) codec not opened, or it is an encoder without the - * AV_CODEC_FLAG_RECON_FRAME flag enabled + * @ref AV_CODEC_FLAG_RECON_FRAME flag enabled * @retval AVERROR_INPUT_CHANGED current decoded frame has changed parameters with * respect to first decoded frame. Applicable when flag * AV_CODEC_FLAG_DROPCHANGED is set. From d6e30291db22b70c3d8a2a41f0f2287854cb6de4 Mon Sep 17 00:00:00 2001 From: James Almer Date: Mon, 27 Mar 2023 11:20:20 -0300 Subject: [PATCH 0512/2172] fate/lavf-container: add missing swscale deps to mxf_dvcpro100 and mxf_ffv1 Signed-off-by: James Almer --- tests/fate/lavf-container.mak | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/fate/lavf-container.mak b/tests/fate/lavf-container.mak index f7d674d9d50..1b473e36e1f 100644 --- a/tests/fate/lavf-container.mak +++ b/tests/fate/lavf-container.mak @@ -24,8 +24,8 @@ FATE_LAVF_CONTAINER_RESAMPLE := asf avi dv_pal dv_ntsc gxf_pal gxf_ntsc \ FATE_LAVF_CONTAINER-$(!CONFIG_ARESAMPLE_FILTER) := $(filter-out $(FATE_LAVF_CONTAINER_RESAMPLE),$(FATE_LAVF_CONTAINER-yes)) FATE_LAVF_CONTAINER_SCALE := dv dv_pal dv_ntsc flm gxf gxf_pal gxf_ntsc \ - mxf_dv25 mxf_dvcpro50 mxf_d10 mxf_opatom \ - smjpeg + mxf_dv25 mxf_dvcpro50 mxf_dvcpro100 mxf_d10 \ + mxf_ffv1 mxf_opatom smjpeg FATE_LAVF_CONTAINER-$(!CONFIG_SCALE_FILTER) := $(filter-out $(FATE_LAVF_CONTAINER_SCALE),$(FATE_LAVF_CONTAINER-yes)) FATE_LAVF_CONTAINER = $(FATE_LAVF_CONTAINER-yes:%=fate-lavf-%) From e1dc78a13d2bbce6f1ed525a207427b3ac01eab8 Mon Sep 17 00:00:00 2001 From: TADANO Tokumei Date: Thu, 23 Feb 2023 19:17:16 +0900 Subject: [PATCH 0513/2172] lavc/codec_desc.c: remove AV_CODEC_PROP_TEXT_SUB property from ARIB_CAPTION To support bitmap subtitle output, remove AV_CODEC_PROP_TEXT_SUB property from codec descriptor for AV_CODEC_ID_ARIB_CAPTION. This is similar to `libavcodec/libzvbi-teletextdec.c` (AV_CODEC_ID_DVB_TELETEXT). Instead, each subtitle decoder has to specify a subtitile format. `libavcodec/libaribb24.c` uses same AV_CODEC_ID_ARIB_CAPTION and expects AV_CODEC_PROP_TEXT_SUB to be set, so this adds a line to specify a format there. Signed-off-by: rcombs --- libavcodec/codec_desc.c | 1 - libavcodec/libaribb24.c | 1 + 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/libavcodec/codec_desc.c b/libavcodec/codec_desc.c index d912704891a..efdcb59bc9a 100644 --- a/libavcodec/codec_desc.c +++ b/libavcodec/codec_desc.c @@ -3550,7 +3550,6 @@ static const AVCodecDescriptor codec_descriptors[] = { .type = AVMEDIA_TYPE_SUBTITLE, .name = "arib_caption", .long_name = NULL_IF_CONFIG_SMALL("ARIB STD-B24 caption"), - .props = AV_CODEC_PROP_TEXT_SUB, .profiles = NULL_IF_CONFIG_SMALL(ff_arib_caption_profiles), }, diff --git a/libavcodec/libaribb24.c b/libavcodec/libaribb24.c index 8ccf3c4b5d8..e3e244be996 100644 --- a/libavcodec/libaribb24.c +++ b/libavcodec/libaribb24.c @@ -291,6 +291,7 @@ static int libaribb24_handle_regions(AVCodecContext *avctx, AVSubtitle *sub) av_log(avctx, AV_LOG_DEBUG, "Styled ASS line: %s\n", buf.str); + sub->format = 1; /* text */ ret = ff_ass_add_rect(sub, buf.str, b24->read_order++, 0, NULL, NULL); } From 38bb137e9923a4c4c64befcf8b5fda29691440e0 Mon Sep 17 00:00:00 2001 From: TADANO Tokumei Date: Thu, 23 Feb 2023 19:17:17 +0900 Subject: [PATCH 0514/2172] lavf/mpegts.c: set some properties for ARIB caption Some additional properties are set for ARIB caption. * need_parsing = 0 ARIB caption doesn't require any parser. This avoids "parser not found" warning message. * need_context_update = 1 When any profiles are changed, set this flag to notify. Signed-off-by: rcombs --- libavformat/mpegts.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/libavformat/mpegts.c b/libavformat/mpegts.c index a8fa3c0b28c..385d78b98bb 100644 --- a/libavformat/mpegts.c +++ b/libavformat/mpegts.c @@ -2176,8 +2176,12 @@ int ff_parse_mpeg2_descriptor(AVFormatContext *fc, AVStream *st, int stream_type st->codecpar->codec_type = AVMEDIA_TYPE_SUBTITLE; st->codecpar->codec_id = AV_CODEC_ID_ARIB_CAPTION; - st->codecpar->profile = picked_profile; + if (st->codecpar->profile != picked_profile) { + st->codecpar->profile = picked_profile; + sti->need_context_update = 1; + } sti->request_probe = 0; + sti->need_parsing = 0; } break; case 0xb0: /* DOVI video stream descriptor */ From b6138633cdf2ecae22c4c02029e91245c430c4fe Mon Sep 17 00:00:00 2001 From: TADANO Tokumei Date: Thu, 23 Feb 2023 19:17:15 +0900 Subject: [PATCH 0515/2172] lavc/libaribcaption.c: add ARIB caption decoder using libaribcaption This patch add another ARIB caption decoder using libaribcaption external library. Unlike libaribb24, it supports 3 types of subtitle outputs: * text: plain text * ass: ASS formatted text * bitmap: bitmap image Default subtitle type is ass as same as libaribb24. Advantages compared with libaribb24 on ASS subtitle are: * Subtitle positioning. * Multi-rect subtitle: some captions are displayed at different position at a time. * More stability and reproducibility. To compile with this feature: * libaribcaption external library has to be pre-installed. https://github.com/xqq/libaribcaption * configure with `--enable-libaribcaption` option. `--enable-libaribb24` and `--enable-libaribcaption` options are not exclusive. If both enabled, libaribcaption precedes as order listed in `libavcodec/allcodecs.c`. Signed-off-by: rcombs --- Changelog | 1 + configure | 4 + doc/decoders.texi | 150 +++++ libavcodec/Makefile | 1 + libavcodec/allcodecs.c | 2 + libavcodec/libaribcaption.c | 1171 +++++++++++++++++++++++++++++++++++ 6 files changed, 1329 insertions(+) create mode 100644 libavcodec/libaribcaption.c diff --git a/Changelog b/Changelog index b357f428abc..a40f32c23f9 100644 --- a/Changelog +++ b/Changelog @@ -2,6 +2,7 @@ Entries are sorted chronologically from oldest to youngest within each release, releases are sorted from youngest to oldest. version : +- libaribcaption decoder version 6.0: - Radiance HDR image support diff --git a/configure b/configure index cec001fb165..fe367462a10 100755 --- a/configure +++ b/configure @@ -218,6 +218,7 @@ External library support: --enable-lcms2 enable ICC profile support via LittleCMS 2 [no] --enable-libaom enable AV1 video encoding/decoding via libaom [no] --enable-libaribb24 enable ARIB text and caption decoding via libaribb24 [no] + --enable-libaribcaption enable ARIB text and caption decoding via libaribcaption [no] --enable-libass enable libass subtitles rendering, needed for subtitles and ass filter [no] --enable-libbluray enable BluRay reading using libbluray [no] @@ -1805,6 +1806,7 @@ EXTERNAL_LIBRARY_LIST=" ladspa lcms2 libaom + libaribcaption libass libbluray libbs2b @@ -3331,6 +3333,7 @@ libaom_av1_decoder_deps="libaom" libaom_av1_encoder_deps="libaom" libaom_av1_encoder_select="extract_extradata_bsf" libaribb24_decoder_deps="libaribb24" +libaribcaption_decoder_deps="libaribcaption" libcelt_decoder_deps="libcelt" libcodec2_decoder_deps="libcodec2" libcodec2_encoder_deps="libcodec2" @@ -6569,6 +6572,7 @@ enabled libaom && require_pkg_config libaom "aom >= 1.0.0" aom/aom_co enabled libaribb24 && { check_pkg_config libaribb24 "aribb24 > 1.0.3" "aribb24/aribb24.h" arib_instance_new || { enabled gpl && require_pkg_config libaribb24 aribb24 "aribb24/aribb24.h" arib_instance_new; } || die "ERROR: libaribb24 requires version higher than 1.0.3 or --enable-gpl."; } +enabled libaribcaption && require_pkg_config libaribcaption "libaribcaption >= 0.1.0" "aribcaption/aribcaption.h" aribcc_context_alloc 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 >= 0.11.0" ass/ass.h ass_library_init diff --git a/doc/decoders.texi b/doc/decoders.texi index 5ba85cf9b14..09b8314dd2a 100644 --- a/doc/decoders.texi +++ b/doc/decoders.texi @@ -353,6 +353,156 @@ Enabled by default. @end table +@section libaribcaption + +Yet another ARIB STD-B24 caption decoder using external @dfn{libaribcaption} +library. + +Implements profiles A and C of the Japanse ARIB STD-B24 standard, +Brazilian ABNT NBR 15606-1, and Philippines version of ISDB-T. + +Requires the presence of the libaribcaption headers and library +(@url{https://github.com/xqq/libaribcaption}) during configuration. +You need to explicitly configure the build with @code{--enable-libaribcaption}. +If both @dfn{libaribb24} and @dfn{libaribcaption} are enabled, @dfn{libaribcaption} +decoder precedes. + +@subsection libaribcaption Decoder Options + +@table @option + +@item -sub_type @var{subtitle_type} +Specifies the format of the decoded subtitles. + +@table @samp +@item bitmap +Graphical image. +@item ass +ASS formatted text. +@item text +Simple text based output without formatting. +@end table + +The default is @dfn{ass} as same as @dfn{libaribb24} decoder. +Some present players (e.g., @dfn{mpv}) expect ASS format for ARIB caption. + +@item -caption_encoding @var{encoding_scheme} +Specifies the encoding scheme of input subtitle text. + +@table @samp +@item auto +Automatically detect text encoding. +@item jis +8bit-char JIS encoding defined in ARIB STD B24. +This encoding used in Japan for ISDB captions. +@item utf8 +UTF-8 encoding defined in ARIB STD B24. +This encoding is used in Philippines for ISDB-T captions. +@item latin +Latin character encoding defined in ABNT NBR 15606-1. +This encoding is used in South America for SBTVD / ISDB-Tb captions. +@end table + +The default is @dfn{ass} as same as @dfn{libaribb24} decoder. +Some present players (e.g., @dfn{mpv}) expect ASS format for ARIB caption. + +@item -font @var{font_name[,font_name2,...]} +Specify comma-separated list of font family names to be used for @dfn{bitmap} +or @dfn{ass} type subtitle rendering. +Only first font name is used for @dfn{ass} type subtitle. + +If not specified, use internaly defined default font family. + +@item -ass_single_rect @var{boolean} +ARIB STD-B24 specifies that some captions may be displayed at different +positions at a time (multi-rectangle subtitle). +Since some players (e.g., old @dfn{mpv}) can't handle multiple ASS rectangles +in a single AVSubtitle, or multiple ASS rectangles of indeterminate duration +with the same start timestamp, this option can change the behavior so that +all the texts are displayed in a single ASS rectangle. + +The default is @var{false}. + +If your player cannot handle AVSubtitles with multiple ASS rectangles properly, +set this option to @var{true} or define @env{ASS_SINGLE_RECT=1} to change +default behavior at compilation. + +@item -replace_fullwidth_ascii @var{boolean} +Specify whether to replace MSZ (Middle Size, half width) fullwidth +alphanumerics with halfwidth alphanumerics. + +The default is @var{true}. + +@item -force_outline_text @var{boolean} +Specify whether always render outline text for all characters regardless of +the indication by charactor style. + +The default is @var{false}. + +@item -outline_width @var{number} (0.0 - 3.0) +Specify width for outline text, in dots (relative). + +The default is @var{1.5}. + +@item -ignore_background @var{boolean} +Specify whether to ignore background color rendering. + +The default is @var{false}. + +@item -ignore_ruby @var{boolean} +Specify whether to ignore rendering for ruby-like (furigana) characters. + +The default is @var{false}. + +@item -replace_drcs @var{boolean} +Specify whether to render replaced DRCS characters as Unicode characters. + +The default is @var{true}. + +@item -canvas_size @var{image_size} +Specify the resolution of the canvas to render subtitles to; usually, this +should be frame size of input video. +This only applies when @code{-subtitle_type} is set to @var{bitmap}. + +The libaribcaption decoder assumes input frame size for bitmap rendering as below: +@enumerate +@item +PROFILE_A : 1440 x 1080 with SAR (PAR) 4:3 +@item +PROFILE_C : 320 x 180 with SAR (PAR) 1:1 +@end enumerate + +If actual frame size of input video does not match above assumption, +the rendered captions may be distorted. +To make the captions undistorted, add @code{-canvas_size} option to specify +actual input video size. + +Note that the @code{-canvas_size} option is not required for video with +different size but same aspect ratio. +In such cases, the caption will be stretched or shrunk to actual video size +if @code{-canvas_size} option is not specified. +If @code{-canvas_size} option is specified with different size, +the caption will be stretched or shrunk as specified size with calculated SAR. + +@end table + +@subsection libaribcaption decoder usage examples + +Display MPEG-TS file with ARIB subtitle by @code{ffplay} tool: +@example +ffplay -sub_type bitmap MPEG.TS +@end example + +Display MPEG-TS file with input frame size 1920x1080 by @code{ffplay} tool: +@example +ffplay -sub_type bitmap -canvas_size 1920x1080 MPEG.TS +@end example + +Embed ARIB subtitle in transcoded video: +@example +ffmpeg -sub_type bitmap -i src.m2t -filter_complex "[0:v][0:s]overlay" -vcodec h264 dest.mp4 +@end example + @section dvbsub @subsection Options diff --git a/libavcodec/Makefile b/libavcodec/Makefile index 408ecd1e315..711d2690d0b 100644 --- a/libavcodec/Makefile +++ b/libavcodec/Makefile @@ -1079,6 +1079,7 @@ OBJS-$(CONFIG_PCM_MULAW_AT_ENCODER) += audiotoolboxenc.o OBJS-$(CONFIG_LIBAOM_AV1_DECODER) += libaomdec.o libaom.o OBJS-$(CONFIG_LIBAOM_AV1_ENCODER) += libaomenc.o libaom.o OBJS-$(CONFIG_LIBARIBB24_DECODER) += libaribb24.o ass.o +OBJS-$(CONFIG_LIBARIBCAPTION_DECODER) += libaribcaption.o ass.o OBJS-$(CONFIG_LIBCELT_DECODER) += libcelt_dec.o OBJS-$(CONFIG_LIBCODEC2_DECODER) += libcodec2.o OBJS-$(CONFIG_LIBCODEC2_ENCODER) += libcodec2.o diff --git a/libavcodec/allcodecs.c b/libavcodec/allcodecs.c index 385ee348035..3cbb93347b4 100644 --- a/libavcodec/allcodecs.c +++ b/libavcodec/allcodecs.c @@ -759,6 +759,8 @@ extern const FFCodec ff_pcm_mulaw_at_decoder; extern const FFCodec ff_qdmc_at_decoder; extern const FFCodec ff_qdm2_at_decoder; extern FFCodec ff_libaom_av1_encoder; +/* preferred over libaribb24 */ +extern const FFCodec ff_libaribcaption_decoder; extern const FFCodec ff_libaribb24_decoder; extern const FFCodec ff_libcelt_decoder; extern const FFCodec ff_libcodec2_encoder; diff --git a/libavcodec/libaribcaption.c b/libavcodec/libaribcaption.c new file mode 100644 index 00000000000..747ca8a2e47 --- /dev/null +++ b/libavcodec/libaribcaption.c @@ -0,0 +1,1171 @@ +/* + * ARIB STD-B24 caption decoder using the libaribcaption library + * Copyright (c) 2022 TADANO Tokumei + * + * 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 "codec_internal.h" +#include "internal.h" +#include "libavcodec/ass.h" +#include "libavutil/avstring.h" +#include "libavutil/avutil.h" +#include "libavutil/thread.h" +#include "libavutil/log.h" +#include "libavutil/opt.h" + +#include + +#if !defined(DEFAULT_FONT_ASS) +# define DEFAULT_FONT_ASS "sans-serif" +#endif + +#define ARIBC_BPRINT_SIZE_INIT 64 +#define ARIBC_BPRINT_SIZE_MAX (8 * 1024) +#define ARIBC_ALPHA_MAX_NUM 4 +#define ARIBC_ALPHA_DEFAULT_FRONT 0xFF +#define ARIBC_ALPHA_DEFAULT_BACK 0x80 + +#define ARIBCC_COLOR_RGB(c) ((c) & 0xFFFFFF) +#define ARIBCC_COLOR_DIFF_RGB(c1,c2) (((c1) ^ (c2)) & 0x00FFFFFF) +#define ARIBCC_COLOR_DIFF_A(c1,c2) (((c1) ^ (c2)) & 0xFF000000) + +#define CLUT_RGBA(r,g,b,a) (((unsigned)(a) << 24) | ((r) << 16) | ((g) << 8) | (b)) +#define CLUT_A(c) (((c) >> 24) & 0xFF) +#define CLUT_R(c) (((c) >> 16) & 0xFF) +#define CLUT_G(c) (((c) >> 8) & 0xFF) +#define CLUT_B(c) ( (c) & 0xFF) + +#define ARIBCC_COLOR_TO_CLUT_RGBA(c,a) (((ARIBCC_COLOR_A(c) ? ARIBCC_COLOR_A(c) : (a)) << 24) | \ + (ARIBCC_COLOR_R(c) << 16) | \ + (ARIBCC_COLOR_G(c) << 8) | \ + (ARIBCC_COLOR_B(c))) + +typedef struct ARIBCaptionContext { + AVClass *class; + AVCodecContext *avctx; + const AVPacket *avpkt; + AVSubtitle *sub; + + aribcc_context_t *context; + aribcc_decoder_t *decoder; + aribcc_renderer_t *renderer; + + int subtitle_type; + int encoding_scheme; + bool ass_single_rect; + char *font; + bool replace_fullwidth_ascii; + bool force_stroke_text; + bool ignore_background; + bool ignore_ruby; + float stroke_width; + bool replace_drcs; + + int64_t pts; + AVRational time_base; + int canvas_width; + int canvas_height; + int plane_width; + int plane_height; + int frame_width; + int frame_height; + int bitmap_plane_width; + int bitmap_plane_height; + int font_size; + int charstyle; + int border_style; + int readorder; + + aribcc_caption_t caption; + aribcc_render_result_t render_result; + uint32_t *clut; + int clut_idx; + int clut_overflow; + uint8_t clut_alpha[ARIBC_ALPHA_MAX_NUM]; +} ARIBCaptionContext; + +static void hex_dump_debug(void *ctx, const char *buf, int buf_size) +{ + int i; + + for (i = 0; i < buf_size; i++) { + ff_dlog(ctx, "%02hhx ", buf[i]); + if (i % 16 == 15) + ff_dlog(ctx, "\n"); + } + if (i % 16) + ff_dlog(ctx, "\n"); +} + +static void logcat_callback(aribcc_loglevel_t level, const char* message, void* userdata) +{ + ARIBCaptionContext *ctx = userdata; + int lvl; + + if (ctx->decoder != NULL) { + switch (level) { + case ARIBCC_LOGLEVEL_ERROR: + lvl = AV_LOG_ERROR; + break; + case ARIBCC_LOGLEVEL_WARNING: + lvl = AV_LOG_WARNING; + break; + default: + lvl = AV_LOG_INFO; + } + + av_log(ctx, lvl, "%s\n", message); + } +} + +static void estimate_video_frame_size(ARIBCaptionContext *ctx) +{ + if (ctx->avctx->width > 0 && ctx->avctx->height > 0) { + /* input video size specified by -canvas_size option */ + ctx->bitmap_plane_width = ctx->avctx->width; + ctx->bitmap_plane_height = ctx->avctx->height; + } else if (ctx->plane_width == 960) { + /* ARIB TR-B14 Fascicle 2 Volume 3 [Section 2] 4.3.1 */ + /* ARIB TR-B14 Fascicle 2 Volume 3 [Section 2] Appendix-4 */ + ctx->bitmap_plane_width = 1440; + ctx->bitmap_plane_height = 1080; + } else { + ctx->bitmap_plane_width = ctx->plane_width; + ctx->bitmap_plane_height = ctx->plane_height; + } + /* Expand either width or height */ + if (ctx->bitmap_plane_height * ctx->plane_width > ctx->bitmap_plane_width * ctx->plane_height) { + ctx->frame_height = ctx->bitmap_plane_height; + ctx->frame_width = ctx->frame_height * ctx->plane_width / ctx->plane_height; + } else { + ctx->frame_width = ctx->bitmap_plane_width; + ctx->frame_height = ctx->frame_width * ctx->plane_height / ctx->plane_width; + } +} + +static void clut_set_alpha(ARIBCaptionContext *ctx, uint8_t a) +{ + int i; + + for (i = 0; i < ARIBC_ALPHA_MAX_NUM; i++) { + if (ctx->clut_alpha[i] == 0) { + ctx->clut_alpha[i] = a; + return; + } + if (ctx->clut_alpha[i] == a) + return; + } + return; +} + +static uint8_t clut_find_nearlest_alpha(ARIBCaptionContext *ctx, uint8_t a) +{ + int i, j, d; + + if (a == 0) + return a; + d = 256; + j = 0; + for (i = 0; i < ARIBC_ALPHA_MAX_NUM; i++) { + if (ctx->clut_alpha[i] == a) + return a; + if (ctx->clut_alpha[i] == 0) + break; + if (abs((int)a - (int)ctx->clut_alpha[i]) < d) { + d = abs((int)a - (int)ctx->clut_alpha[i]); + j = i; + } + } + return ctx->clut_alpha[j]; +} + +static int clut_find(ARIBCaptionContext *ctx, uint32_t rgba) +{ + int i; + + for (i = 0; i < ctx->clut_idx; i++) { + if (ctx->clut[i] == rgba) + return i; + } + return -1; +} + +static inline int clut_color_distance(uint32_t rgba1, uint32_t rgba2) +{ + return abs((int)CLUT_R(rgba1) - (int)CLUT_R(rgba2)) + + abs((int)CLUT_G(rgba1) - (int)CLUT_G(rgba2)) + + abs((int)CLUT_B(rgba1) - (int)CLUT_B(rgba2)); +} + +static uint8_t clut_pick_or_set(ARIBCaptionContext *ctx, int r, int g, int b, int a) +{ + int c, i, d, d_min; + uint32_t rgba; + + a = clut_find_nearlest_alpha(ctx, a); + if (a == 0) + return 0; /* transparent */ + rgba = CLUT_RGBA(r,g,b,a); + + d_min = 256 * 3; + c = 0; + for (i = 0; i < ctx->clut_idx; i++) { + if (ctx->clut[i] == rgba) + return i; + if (CLUT_A(ctx->clut[i]) != a) + continue; + d = clut_color_distance(ctx->clut[i], rgba); + if (d < d_min) { + d_min = d; + c = i; + } + } + if (d_min > 3) { + if (ctx->clut_idx >= AVPALETTE_COUNT) + ctx->clut_overflow++; + else { + c = ctx->clut_idx; + ctx->clut[ctx->clut_idx++] = rgba; + } + } + return c; +} + +/* initialiaze CLUT with each character colors */ +static void clut_init(ARIBCaptionContext *ctx, aribcc_caption_region_t *region) +{ + aribcc_color_t text_color, back_color, stroke_color; + uint32_t rgba; + + ctx->clut[0] = CLUT_RGBA(0,0,0,0); /* transparent */ + ctx->clut_alpha[0] = 0xFF; + ctx->clut_idx = 1; + ctx->clut_overflow = 0; + text_color = region->chars[0].text_color; + back_color = region->chars[0].back_color; + stroke_color = region->chars[0].stroke_color; + rgba = ARIBCC_COLOR_TO_CLUT_RGBA(text_color, ARIBC_ALPHA_DEFAULT_FRONT); + ctx->clut[ctx->clut_idx++] = rgba; + clut_set_alpha(ctx, CLUT_A(rgba)); + rgba = ARIBCC_COLOR_TO_CLUT_RGBA(back_color, ARIBC_ALPHA_DEFAULT_BACK); + ctx->clut[ctx->clut_idx++] = rgba; + clut_set_alpha(ctx, CLUT_A(rgba)); + rgba = ARIBCC_COLOR_TO_CLUT_RGBA(stroke_color, ARIBC_ALPHA_DEFAULT_FRONT); + if (clut_find(ctx, rgba) < 0) { + ctx->clut[ctx->clut_idx++] = rgba; + clut_set_alpha(ctx, CLUT_A(rgba)); + } + + for (int i = 1; i < region->char_count; i++) { + if (region->chars[i].text_color != text_color) { + rgba = ARIBCC_COLOR_TO_CLUT_RGBA(region->chars[i].text_color, + ARIBC_ALPHA_DEFAULT_FRONT); + if (clut_find(ctx, rgba) < 0) { + ctx->clut[ctx->clut_idx++] = rgba; + clut_set_alpha(ctx, CLUT_A(rgba)); + } + } + if (region->chars[i].back_color != back_color) { + rgba = ARIBCC_COLOR_TO_CLUT_RGBA(region->chars[i].back_color, + ARIBC_ALPHA_DEFAULT_BACK); + if (clut_find(ctx, rgba) < 0) { + ctx->clut[ctx->clut_idx++] = rgba; + clut_set_alpha(ctx, CLUT_A(rgba)); + } + } + if (region->chars[i].stroke_color != stroke_color) { + rgba = ARIBCC_COLOR_TO_CLUT_RGBA(region->chars[i].stroke_color, + ARIBC_ALPHA_DEFAULT_FRONT); + if (clut_find(ctx, rgba) < 0) { + if (ctx->clut_idx < AVPALETTE_COUNT) + ctx->clut[ctx->clut_idx++] = rgba; + clut_set_alpha(ctx, CLUT_A(rgba)); + } + } + } +} + +/** + * aribcaption_trans_{bitmap|ass|text}_subtitle() + * + * Transfer decoded subtitle to AVSubtitle with corresponding subtitle type. + * + * @param ctx pointer to the ARIBCaptionContext + * @return > 0 number of rectangles to be displayed + * = 0 no subtitle + * < 0 error code + */ +static int aribcaption_trans_bitmap_subtitle(ARIBCaptionContext *ctx) +{ + int ret = 0; + AVSubtitle *sub = ctx->sub; + int status, rect_idx; + int old_width = ctx->frame_width; + int old_height = ctx->frame_height; + + if (ctx->caption.plane_width > 0 && ctx->caption.plane_height > 0) { + ctx->plane_width = ctx->caption.plane_width; + ctx->plane_height = ctx->caption.plane_height; + } + estimate_video_frame_size(ctx); + if (ctx->frame_width != old_width || ctx->frame_height != old_height) { + ff_dlog(ctx, "canvas: %dx%d plane: %dx%d bitmap: %dx%d frame: %dx%d\n", + ctx->avctx->width, ctx->avctx->height, + ctx->plane_width, ctx->plane_height, + ctx->bitmap_plane_width, ctx->bitmap_plane_height, + ctx->frame_width, ctx->frame_height); + if (!aribcc_renderer_set_frame_size(ctx->renderer, + ctx->frame_width, ctx->frame_height)) { + av_log(ctx, AV_LOG_ERROR, + "aribcc_renderer_set_frame_size() returned with error.\n"); + return AVERROR_EXTERNAL; + } + } + + status = aribcc_renderer_append_caption(ctx->renderer, &ctx->caption); + if (!status) { + av_log(ctx, AV_LOG_ERROR, + "aribcc_renderer_append_caption() returned with error.\n"); + return AVERROR_EXTERNAL; + } + + status = aribcc_renderer_render(ctx->renderer, ctx->pts, &ctx->render_result); + switch (status) { + case ARIBCC_RENDER_STATUS_GOT_IMAGE: + break; + + case ARIBCC_RENDER_STATUS_GOT_IMAGE_UNCHANGED: + aribcc_render_result_cleanup(&ctx->render_result); + ff_dlog(ctx, "got image unchanged\n"); + return 0; + + case ARIBCC_RENDER_STATUS_NO_IMAGE: + ff_dlog(ctx, "no image\n"); + return 0; + + case ARIBCC_RENDER_STATUS_ERROR: + av_log(ctx, AV_LOG_ERROR, + "aribcc_renderer_render() returned with error.\n"); + return AVERROR_EXTERNAL; + + default: + aribcc_render_result_cleanup(&ctx->render_result); + av_log(ctx, AV_LOG_ERROR, + "aribcc_renderer_render() returned unknown status: %d\n", status); + return AVERROR_EXTERNAL; + } + + if (!ctx->render_result.image_count || ctx->render_result.images == NULL) { + aribcc_render_result_cleanup(&ctx->render_result); + ff_dlog(ctx, "no image (%d)\n", ctx->render_result.image_count); + return 0; + } + + sub->format = 0; /* graphic */ + sub->rects = av_calloc(ctx->render_result.image_count, sizeof(*sub->rects)); + if (!sub->rects) { + ret = AVERROR(ENOMEM); + goto fail; + } + for (int i = 0; i < ctx->render_result.image_count; i++) { + sub->rects[i] = av_mallocz(sizeof(*sub->rects[i])); + if (!sub->rects[i]) { + ret = AVERROR(ENOMEM); + goto fail; + } + } + + for (rect_idx = 0; rect_idx < ctx->caption.region_count; rect_idx++) { + AVSubtitleRect *rect = sub->rects[rect_idx]; + aribcc_image_t *image = &ctx->render_result.images[rect_idx]; + int w, h, shrink_height, dst_idx; + + clut_init(ctx, &ctx->caption.regions[rect_idx]); + + rect->w = image->width * ctx->bitmap_plane_width / ctx->frame_width; + rect->h = image->height * ctx->bitmap_plane_height / ctx->frame_height; + rect->data[0] = av_mallocz(rect->w * rect->h); + if (!rect->data[0]) { + ret = AVERROR(ENOMEM); + goto fail; + } + if ((image->height != rect->h && image->width != rect->w) || + image->stride < image->width * 4 || + image->stride * image->height > image->bitmap_size) { + av_log(ctx, AV_LOG_ERROR, "Bug: unexpected rendered image: %d(%d)x%d -> %dx%d\n", + image->width, image->stride / 4, image->height, rect->w, rect->h); + ret = AVERROR_EXTERNAL; + goto fail; + } + + shrink_height = image->height != rect->h; + dst_idx = 0; + for (h = 0; h < rect->h; h++) { + for (w = 0; w < rect->w; w++) { + /* Bi-linear interpolation */ + int n, m, idx0, idx1, r, g, b, a; + if (shrink_height) { + int div_a, y0, y1; + div_a = h * ctx->frame_height; + n = ctx->bitmap_plane_height; + y0 = div_a / n; + y1 = FFMIN(y0 + 1, image->height - 1); + m = div_a - n * y0; + idx0 = image->stride * y0 + w * 4; + idx1 = image->stride * y1 + w * 4; + } else { + int div_a, x0, x1; + div_a = w * ctx->frame_width; + n = ctx->bitmap_plane_width; + x0 = div_a / n; + x1 = FFMIN(x0 + 1, image->width - 1); + m = div_a - n * x0; + idx0 = image->stride * h + x0 * 4; + idx1 = image->stride * h + x1 * 4; + } + r = (image->bitmap[idx0++] * (n - m) + image->bitmap[idx1++] * m) / n; + g = (image->bitmap[idx0++] * (n - m) + image->bitmap[idx1++] * m) / n; + b = (image->bitmap[idx0++] * (n - m) + image->bitmap[idx1++] * m) / n; + a = (image->bitmap[idx0++] * (n - m) + image->bitmap[idx1++] * m) / n; + rect->data[0][dst_idx++] = clut_pick_or_set(ctx, r, g, b, a); + } + } + rect->data[1] = av_memdup(ctx->clut, AVPALETTE_SIZE); + if (!rect->data[1]) { + ret = AVERROR(ENOMEM); + goto fail; + } + + if (ctx->avctx->profile == FF_PROFILE_ARIB_PROFILE_C) { + /* ARIB TR-B14 version 3.8 Fascicle 1-(2/2) Volume 3 [Section 4] */ + /* No position information is provided for profile C */ + rect->x = (ctx->frame_width - rect->w) / 2; + rect->y = ctx->frame_height - rect->h * (ctx->caption.region_count - rect_idx); + } else { + rect->x = image->dst_x * ctx->bitmap_plane_width / ctx->frame_width; + rect->y = image->dst_y * ctx->bitmap_plane_height / ctx->frame_height; + } + rect->type = SUBTITLE_BITMAP; + rect->linesize[0] = rect->w; + rect->nb_colors = 256; + + ff_dlog(ctx, "BITMAP subtitle%s (%d,%d) %dx%d -> (%d,%d) %dx%d [%d]: %d colors\n", + (ctx->caption.regions[rect_idx].is_ruby) ? " (ruby)" : "", + image->dst_x, image->dst_y, image->width, image->height, + rect->x, rect->y, rect->w, rect->h, + rect_idx, ctx->clut_idx); + if (ctx->clut_overflow) + av_log(ctx, AV_LOG_WARNING, "CLUT overflow (%d).\n", ctx->clut_overflow); + } + sub->num_rects = rect_idx; + + return rect_idx; + +fail: + if (sub->rects) { + for (int i = 0; i < ctx->caption.region_count; i++) { + if (sub->rects[i]) { + av_freep(&sub->rects[i]->data[0]); + av_freep(&sub->rects[i]->data[1]); + av_freep(&sub->rects[i]); + } + } + av_freep(&sub->rects); + } + sub->num_rects = 0; + + return ret; +} + +static int set_ass_header(ARIBCaptionContext *ctx) +{ + AVCodecContext *avctx = ctx->avctx; + int outline, shadow; + const char *font_name; + const char *fonts = ctx->font; + + if (ctx->border_style == 4) { + outline = 0; + shadow = 4; + } else { + outline = 1; + shadow = 0; + } + if (ctx->force_stroke_text) + outline = (int)(ctx->stroke_width * 4.0 / 3.0); + + if (fonts && *fonts) + font_name = av_get_token(&fonts, ","); + else + font_name = av_strdup(DEFAULT_FONT_ASS); + if (!font_name) + return AVERROR(ENOMEM); + + av_freep(&avctx->subtitle_header); + avctx->subtitle_header = av_asprintf( + "[Script Info]\r\n" + "ScriptType: v4.00+\r\n" + "PlayResX: %d\r\n" + "PlayResY: %d\r\n" + "WrapStyle: 2\r\n" /* 2: no word wrapping */ + "\r\n" + + "[V4+ Styles]\r\n" + "Format: Name, " + "Fontname, Fontsize, " + "PrimaryColour, SecondaryColour, OutlineColour, BackColour, " + "Bold, Italic, Underline, StrikeOut, " + "ScaleX, ScaleY, " + "Spacing, Angle, " + "BorderStyle, Outline, Shadow, " + "Alignment, MarginL, MarginR, MarginV, " + "Encoding\r\n" + + "Style: " + "Default," /* Name */ + "%s,%d," /* Font{name,size} */ + "&H%x,&H%x,&H%x,&H%x," /* {Primary,Secondary,Outline,Back}Colour */ + "%d,%d,%d,0," /* Bold, Italic, Underline, StrikeOut */ + "100,100," /* Scale{X,Y} */ + "0,0," /* Spacing, Angle */ + "%d,%d,%d," /* BorderStyle, Outline, Shadow */ + "%d,10,10,10," /* Alignment, Margin[LRV] */ + "0\r\n" /* Encoding */ + "\r\n" + + "[Events]\r\n" + "Format: Layer, Start, End, Style, Name, MarginL, MarginR, MarginV, Effect, Text\r\n", + ctx->plane_width, ctx->plane_height, + font_name, ctx->font_size, + ASS_DEFAULT_COLOR, ASS_DEFAULT_COLOR, + ASS_DEFAULT_BACK_COLOR, ASS_DEFAULT_BACK_COLOR, + -ASS_DEFAULT_BOLD, -ASS_DEFAULT_ITALIC, -ASS_DEFAULT_UNDERLINE, + ctx->border_style, outline, shadow, ASS_DEFAULT_ALIGNMENT); + + av_freep(&font_name); + if (!avctx->subtitle_header) + return AVERROR(ENOMEM); + avctx->subtitle_header_size = strlen(avctx->subtitle_header); + return 0; +} + +static void set_ass_color(AVBPrint *buf, int color_num, + aribcc_color_t new_color, aribcc_color_t old_color) +{ + if (ARIBCC_COLOR_DIFF_RGB(new_color, old_color)) + av_bprintf(buf, "{\\%dc&H%06x&}", color_num, + ARIBCC_COLOR_RGB(new_color)); + if (ARIBCC_COLOR_DIFF_A(new_color, old_color)) + av_bprintf(buf, "{\\%da&H%02x&}", color_num, + 0xFF - ARIBCC_COLOR_A(new_color)); +} + +static int aribcaption_trans_ass_subtitle(ARIBCaptionContext *ctx) +{ + AVSubtitle *sub = ctx->sub; + AVBPrint buf; + bool single_rect = ctx->ass_single_rect; + int ret = 0, rect_idx; + + if (ctx->caption.plane_width > 0 && ctx->caption.plane_height > 0 && + (ctx->caption.plane_width != ctx->plane_width || + ctx->caption.plane_height != ctx->plane_height)) { + ctx->plane_width = ctx->caption.plane_width; + ctx->plane_height = ctx->caption.plane_height; + if ((ret = set_ass_header(ctx)) < 0) + return ret; + } + + /* ARIB TR-B14 version 3.8 Fascicle 1-(2/2) Volume 3 [Section 4] */ + /* No position information is provided for profile C */ + if (ctx->avctx->profile == FF_PROFILE_ARIB_PROFILE_C) + single_rect = true; + + sub->format = 1; /* text */ + if (ctx->caption.region_count == 0) { + /* clear previous caption for indefinite duration */ + ff_ass_add_rect(sub, "", ctx->readorder++, 0, NULL, NULL); + return 1; + } + + av_bprint_init(&buf, ARIBC_BPRINT_SIZE_INIT, ARIBC_BPRINT_SIZE_MAX); + + if (single_rect && ctx->avctx->profile != FF_PROFILE_ARIB_PROFILE_C) { + int x, y, rx, ry; + x = ctx->plane_width; + y = ctx->plane_height; + for (int i = 0; i < ctx->caption.region_count; i++) { + rx = ctx->caption.regions[i].x; + ry = ctx->caption.regions[i].y; + if (rx < x) + x = rx; + if (ry < y) + y = ry; + } + av_bprintf(&buf, "{\\an7}"); + if (y < 0) + y += ctx->plane_height; + if (x > 0 || y > 0) + av_bprintf(&buf, "{\\pos(%d,%d)}", x, y); + } + + rect_idx = 0; + for (int i = 0; i < ctx->caption.region_count; i++) { + aribcc_caption_region_t *region = &ctx->caption.regions[i]; + aribcc_color_t text_color = ARIBCC_MAKE_RGBA(0xFF, 0xFF, 0xFF, + ARIBC_ALPHA_DEFAULT_FRONT); + aribcc_color_t stroke_color = ARIBCC_MAKE_RGBA(0, 0, 0, + ARIBC_ALPHA_DEFAULT_FRONT); + aribcc_color_t back_color = ARIBCC_MAKE_RGBA(0, 0, 0, + ARIBC_ALPHA_DEFAULT_BACK); + aribcc_charstyle_t charstyle = ctx->charstyle; + int char_width = ctx->font_size; + int char_height = ctx->font_size; + int char_horizontal_spacing = 0; + + if (region->is_ruby && ctx->ignore_ruby) + continue; + + if (!single_rect) { + int x = region->x; + int y = region->y; + if (x < 0) + x += ctx->plane_width; + if (y < 0) + y += ctx->plane_height; + av_bprint_clear(&buf); + av_bprintf(&buf, "{\\an7}"); + if (x > 0 || y > 0) + av_bprintf(&buf, "{\\pos(%d,%d)}", x, y); + } + if (region->is_ruby) + av_bprintf(&buf, "{\\fs%d}", char_height / 2); + + for (int j = 0; j < region->char_count; j++) { + aribcc_caption_char_t *ch = ®ion->chars[j]; + + if (ctx->avctx->profile != FF_PROFILE_ARIB_PROFILE_C) { + if (ch->char_horizontal_spacing != char_horizontal_spacing) { + av_bprintf(&buf, "{\\fsp%d}", (region->is_ruby) ? + ch->char_horizontal_spacing / 2 : + ch->char_horizontal_spacing); + char_horizontal_spacing = ch->char_horizontal_spacing; + } + if (ch->char_width != char_width) { + av_bprintf(&buf, "{\\fscx%"PRId64"}", + av_rescale(ch->char_width, 100, ctx->font_size)); + char_width = ch->char_width; + } + if (ch->char_height != char_height) { + av_bprintf(&buf, "{\\fscy%"PRId64"}", + av_rescale(ch->char_height, 100, ctx->font_size)); + char_height = ch->char_height; + } + } + if (ch->style != charstyle) { + aribcc_charstyle_t diff = ch->style ^ charstyle; + if (diff & ARIBCC_CHARSTYLE_STROKE) { + if (charstyle & ARIBCC_CHARSTYLE_STROKE) { + if (ctx->force_stroke_text) + av_bprintf(&buf, "{\\bord%d}", + (int)(ctx->stroke_width * 4.0 / 3.0)); + else + av_bprintf(&buf, "{\\bord0}"); + } else + av_bprintf(&buf, "{\\bord3}"); + } + if (diff & ARIBCC_CHARSTYLE_BOLD) { + if (charstyle & ARIBCC_CHARSTYLE_BOLD) + av_bprintf(&buf, "{\\b0}"); + else + av_bprintf(&buf, "{\\b1}"); + } + if (diff & ARIBCC_CHARSTYLE_ITALIC) { + if (charstyle & ARIBCC_CHARSTYLE_ITALIC) + av_bprintf(&buf, "{\\i0}"); + else + av_bprintf(&buf, "{\\i1}"); + } + if (diff & ARIBCC_CHARSTYLE_UNDERLINE) { + if (charstyle & ARIBCC_CHARSTYLE_UNDERLINE) + av_bprintf(&buf, "{\\u0}"); + else + av_bprintf(&buf, "{\\u1}"); + } + charstyle = ch->style; + } + if (ch->text_color != text_color) { + set_ass_color(&buf, 1, ch->text_color, text_color); + text_color = ch->text_color; + } + if (ch->stroke_color != stroke_color) { + set_ass_color(&buf, 3, ch->stroke_color, stroke_color); + stroke_color = ch->stroke_color; + } + if (ch->back_color != back_color) { + if (ctx->border_style == 4) + set_ass_color(&buf, 4, ch->back_color, back_color); + else + set_ass_color(&buf, 3, ch->back_color, back_color); + back_color = ch->back_color; + } + if (region->chars[j].type == ARIBCC_CHARTYPE_DRCS) + av_bprintf(&buf, "\xe3\x80\x93"); /* Geta Mark */ + else + ff_ass_bprint_text_event(&buf, ch->u8str, strlen(ch->u8str), "", 0); + } + + if (single_rect) { + if (i + 1 < ctx->caption.region_count) + av_bprintf(&buf, "{\\r}\\N"); + ff_dlog(ctx, "ASS subtitle%s (%d,%d) %dx%d [%d]\n", + (region->is_ruby) ? " (ruby)" : "", + region->x, region->y, region->width, region->height, + rect_idx); + } else { + if (!av_bprint_is_complete(&buf)) { + ret = AVERROR(ENOMEM); + goto fail; + } + ff_dlog(ctx, "ASS subtitle%s (%d,%d) %dx%d [%d]: %s\n", + (region->is_ruby) ? " (ruby)" : "", + region->x, region->y, region->width, region->height, + rect_idx, buf.str); + + ret = ff_ass_add_rect(sub, buf.str, ctx->readorder++, 0 , NULL, NULL); + if (ret != 0) + goto fail; + rect_idx++; + } + } + if (single_rect) { + if (!av_bprint_is_complete(&buf)) { + ret = AVERROR(ENOMEM); + goto fail; + } + ff_dlog(ctx, "ASS subtitle: %s\n", buf.str); + + ret = ff_ass_add_rect(sub, buf.str, ctx->readorder++, 0 , NULL, NULL); + if (ret != 0) + goto fail; + rect_idx++; + } + + av_bprint_finalize(&buf, NULL); + return rect_idx; + +fail: + if (sub->rects) { + for (int i = 0; i < ctx->caption.region_count; i++) { + if (sub->rects[i]) { + av_freep(&sub->rects[i]->ass); + av_freep(&sub->rects[i]); + } + } + av_freep(&sub->rects); + } + sub->num_rects = 0; + av_bprint_finalize(&buf, NULL); + + return ret; +} + +static int aribcaption_trans_text_subtitle(ARIBCaptionContext *ctx) +{ + AVSubtitle *sub = ctx->sub; + AVSubtitleRect *rect; + int ret = 0; + const char *text; + + sub->rects = av_calloc(ctx->caption.region_count, sizeof(*sub->rects)); + if (!sub->rects) { + ret = AVERROR(ENOMEM); + goto fail; + } + sub->num_rects = 1; + + sub->rects[0] = av_mallocz(sizeof(*sub->rects[0])); + if (!sub->rects[0]) { + ret = AVERROR(ENOMEM); + goto fail; + } + rect = sub->rects[0]; + + if (ctx->caption.region_count == 0) + text = ""; /* clear previous caption */ + else { + text = ctx->caption.text; + ff_dlog(ctx, "TEXT subtitle: %s\n", text); + } + rect->text = av_strdup(text); + if (!rect->text) { + ret = AVERROR(ENOMEM); + goto fail; + } + + sub->format = 1; /* text */ + rect->type = SUBTITLE_TEXT; + + return 1; + +fail: + if (sub->rects) { + rect = sub->rects[0]; + if (rect) { + av_freep(&rect->text); + av_freep(&rect); + } + av_freep(&sub->rects); + } + sub->num_rects = 0; + + return ret; +} + +static int aribcaption_decode(AVCodecContext *avctx, AVSubtitle *sub, + int *got_sub_ptr, const AVPacket *avpkt) +{ + ARIBCaptionContext *ctx = avctx->priv_data; + int status; + + ff_dlog(ctx, "ARIB caption packet pts=%"PRIx64":\n", avpkt->pts); + if (sub->num_rects) { + avpriv_request_sample(ctx, "Different Version of Segment asked Twice"); + return AVERROR_PATCHWELCOME; + } + hex_dump_debug(ctx, avpkt->data, avpkt->size); + + ctx->sub = sub; + ctx->avpkt = avpkt; + ctx->time_base = avctx->pkt_timebase; + if (ctx->time_base.num <= 0 || ctx->time_base.den <= 0) { + av_log(ctx, AV_LOG_VERBOSE, "No timebase set. assuming 90kHz.\n"); + ctx->time_base = av_make_q(1, 90000); + } + if (avpkt->pts == AV_NOPTS_VALUE) + ctx->pts = ARIBCC_PTS_NOPTS; + else + ctx->pts = av_rescale_q(avpkt->pts, ctx->time_base, (AVRational){1, 1000}); + + status = aribcc_decoder_decode(ctx->decoder, avpkt->data, avpkt->size, + ctx->pts, &ctx->caption); + if (status == ARIBCC_DECODE_STATUS_ERROR) { + av_log(ctx, AV_LOG_ERROR, + "aribcc_decoder_decode() returned with error.\n"); + return AVERROR(EAGAIN); + } + if (status == ARIBCC_DECODE_STATUS_NO_CAPTION) { + ff_dlog(ctx, "No caption.\n"); + return avpkt->size; + } else { + ff_dlog(ctx, "type=%02x, flags=%x, lang=%03x\n", + ctx->caption.type, ctx->caption.flags, ctx->caption.iso6392_language_code); + ff_dlog(ctx, "region count = %d, start=%d.%d, duration=%d.%d\n", + ctx->caption.region_count, + (int)(ctx->caption.pts / 1000), (int)(ctx->caption.pts % 1000), + (int)((ctx->caption.wait_duration == ARIBCC_DURATION_INDEFINITE) ? + -1 : ctx->caption.wait_duration / 1000), + (int)((ctx->caption.wait_duration == ARIBCC_DURATION_INDEFINITE) ? + 0 : ctx->caption.wait_duration % 1000)); + } + + switch ((enum AVSubtitleType) ctx->subtitle_type) { + case SUBTITLE_TEXT: + status = aribcaption_trans_text_subtitle(ctx); + break; + + case SUBTITLE_ASS: + status = aribcaption_trans_ass_subtitle(ctx); + break; + + case SUBTITLE_BITMAP: + status = aribcaption_trans_bitmap_subtitle(ctx); + break; + + case SUBTITLE_NONE: + default: + status = 0; + } + + if (status < 0) { + av_log(ctx, AV_LOG_ERROR, "Failed to set Subtitle: %s\n", + av_err2str(status)); + aribcc_caption_cleanup(&ctx->caption); + return status; + } + if (status > 0) { + *got_sub_ptr = 1; + if (ctx->avpkt->pts != AV_NOPTS_VALUE) + sub->pts = av_rescale_q(ctx->avpkt->pts, + ctx->time_base, AV_TIME_BASE_Q); + if (ctx->caption.wait_duration == ARIBCC_DURATION_INDEFINITE) + sub->end_display_time = UINT32_MAX; + else + sub->end_display_time = (uint32_t)ctx->caption.wait_duration; + } + + aribcc_caption_cleanup(&ctx->caption); + return avpkt->size; +} + +static void aribcaption_flush(AVCodecContext *avctx) +{ + ARIBCaptionContext *ctx = avctx->priv_data; + + if (ctx->decoder) + aribcc_decoder_flush(ctx->decoder); + if (ctx->renderer) + aribcc_renderer_flush(ctx->renderer); + if (!(avctx->flags2 & AV_CODEC_FLAG2_RO_FLUSH_NOOP)) + ctx->readorder = 0; +} + +static int aribcaption_close(AVCodecContext *avctx) +{ + ARIBCaptionContext *ctx = avctx->priv_data; + + av_freep(&ctx->clut); + if (ctx->renderer) + aribcc_renderer_free(ctx->renderer); + if (ctx->decoder) + aribcc_decoder_free(ctx->decoder); + if (ctx->context) + aribcc_context_free(ctx->context); + + return 0; +} + +static int aribcaption_init(AVCodecContext *avctx) +{ + ARIBCaptionContext *ctx = avctx->priv_data; + aribcc_profile_t profile; + int ret = 0; + + ctx->avctx = avctx; + + switch (avctx->profile) { + case FF_PROFILE_ARIB_PROFILE_A: + profile = ARIBCC_PROFILE_A; + /* assume 960x540 at initial state */ + ctx->plane_width = 960; + ctx->plane_height = 540; + ctx->font_size = 36; + break; + case FF_PROFILE_ARIB_PROFILE_C: + profile = ARIBCC_PROFILE_C; + ctx->plane_width = 320; + ctx->plane_height = 180; + ctx->font_size = 16; + break; + default: + av_log(avctx, AV_LOG_ERROR, "Unknown or unsupported profile set.\n"); + return AVERROR(EINVAL); + } + /* determine BorderStyle of ASS header */ + if (ctx->ignore_background) + ctx->border_style = 1; + else + ctx->border_style = 4; + ctx->charstyle = ARIBCC_CHARSTYLE_DEFAULT; + if (ctx->force_stroke_text || ctx->ignore_background) + ctx->charstyle |= ARIBCC_CHARSTYLE_STROKE; + + if (!(ctx->context = aribcc_context_alloc())) { + av_log(avctx, AV_LOG_ERROR, "Failed to alloc libaribcaption context.\n"); + return AVERROR_EXTERNAL; + } + aribcc_context_set_logcat_callback(ctx->context, logcat_callback, avctx); + if (!(ctx->decoder = aribcc_decoder_alloc(ctx->context))) { + av_log(avctx, AV_LOG_ERROR, "Failed to alloc libaribcaption decoder.\n"); + return AVERROR_EXTERNAL; + } + if (!aribcc_decoder_initialize(ctx->decoder, + (enum aribcc_encoding_scheme_t) ctx->encoding_scheme, + ARIBCC_CAPTIONTYPE_CAPTION, + profile, + ARIBCC_LANGUAGEID_FIRST)) { + av_log(avctx, AV_LOG_ERROR, "Failed to initialize libaribcaption decoder.\n"); + return AVERROR_EXTERNAL; + } + aribcc_decoder_set_replace_msz_fullwidth_ascii(ctx->decoder, + ctx->replace_fullwidth_ascii); + + /* Similar behavior as ffmpeg tool to set canvas size */ + if (ctx->canvas_width > 0 && ctx->canvas_height > 0 && + (ctx->avctx->width == 0 || ctx->avctx->height == 0)) { + ctx->avctx->width = ctx->canvas_width; + ctx->avctx->height = ctx->canvas_height; + } + + switch ((enum AVSubtitleType) ctx->subtitle_type) { + case SUBTITLE_ASS: + ret = set_ass_header(ctx); + if (ret != 0) { + av_log(avctx, AV_LOG_ERROR, "Failed to set ASS header: %s\n", + av_err2str(ret)); + return ret; + } + break; + + case SUBTITLE_BITMAP: + if(!(ctx->renderer = aribcc_renderer_alloc(ctx->context))) { + av_log(avctx, AV_LOG_ERROR, "Failed to alloc libaribcaption renderer.\n"); + return AVERROR_EXTERNAL; + } + if(!aribcc_renderer_initialize(ctx->renderer, + ARIBCC_CAPTIONTYPE_CAPTION, + ARIBCC_FONTPROVIDER_TYPE_AUTO, + ARIBCC_TEXTRENDERER_TYPE_AUTO)) { + av_log(avctx, AV_LOG_ERROR, "Failed to initialize libaribcaption renderer.\n"); + return AVERROR_EXTERNAL; + } + estimate_video_frame_size(ctx); + ff_dlog(ctx, "canvas: %dx%d plane: %dx%d bitmap: %dx%d frame: %dx%d\n", + ctx->avctx->width, ctx->avctx->height, + ctx->plane_width, ctx->plane_height, + ctx->bitmap_plane_width, ctx->bitmap_plane_height, + ctx->frame_width, ctx->frame_height); + if (!aribcc_renderer_set_frame_size(ctx->renderer, + ctx->frame_width, ctx->frame_height)) { + av_log(ctx, AV_LOG_ERROR, + "aribcc_renderer_set_frame_size() returned with error.\n"); + return AVERROR_EXTERNAL; + } + + if (!(ctx->clut = av_mallocz(AVPALETTE_SIZE))) + return AVERROR(ENOMEM); + + aribcc_renderer_set_storage_policy(ctx->renderer, ARIBCC_CAPTION_STORAGE_POLICY_MINIMUM, 0); + aribcc_renderer_set_replace_drcs(ctx->renderer, ctx->replace_drcs); + aribcc_renderer_set_force_stroke_text(ctx->renderer, ctx->force_stroke_text); + aribcc_renderer_set_force_no_background(ctx->renderer, ctx->ignore_background); + aribcc_renderer_set_force_no_ruby(ctx->renderer, ctx->ignore_ruby); + aribcc_renderer_set_stroke_width(ctx->renderer, ctx->stroke_width); + if (ctx->font) { + int is_nomem = 0; + size_t count = 0; + const char **font_families = NULL; + const char *fonts = ctx->font; + + while (*fonts) { + const char **ff = av_realloc_array(font_families, count + 1, sizeof(*font_families)); + if (!ff) { + is_nomem = 1; + break; + } else { + font_families = ff; + ff[count++] = av_get_token(&fonts, ","); + if (!ff[count - 1]) { + is_nomem = 1; + break; + } else if (*fonts) + fonts++; + } + } + if (!is_nomem && count) + aribcc_renderer_set_default_font_family(ctx->renderer, font_families, count, true); + while (count) + av_freep(&font_families[--count]); + av_freep(&font_families); + if (is_nomem) + return AVERROR(ENOMEM); + } + break; + + case SUBTITLE_TEXT: + case SUBTITLE_NONE: + default: + /* do nothing */ ; + } + + ctx->readorder = 0; + + return 0; +} + +#if !defined(ASS_SINGLE_RECT) +# define ASS_SINGLE_RECT 0 +#endif + +#define OFFSET(x) offsetof(ARIBCaptionContext, x) +#define SD AV_OPT_FLAG_SUBTITLE_PARAM | AV_OPT_FLAG_DECODING_PARAM +static const AVOption options[] = { + { "sub_type", "subtitle rendering type", + OFFSET(subtitle_type), AV_OPT_TYPE_INT, + { .i64 = SUBTITLE_ASS }, SUBTITLE_NONE, SUBTITLE_ASS, SD, "type" }, + { "none", "do nothing", 0, AV_OPT_TYPE_CONST, + { .i64 = SUBTITLE_NONE }, .flags = SD, .unit = "type" }, + { "bitmap", "bitmap rendering", 0, AV_OPT_TYPE_CONST, + { .i64 = SUBTITLE_BITMAP }, .flags = SD, .unit = "type" }, + { "text", "plain text", 0, AV_OPT_TYPE_CONST, + { .i64 = SUBTITLE_TEXT }, .flags = SD, .unit = "type" }, + { "ass", "formatted text", 0, AV_OPT_TYPE_CONST, + { .i64 = SUBTITLE_ASS }, .flags = SD, .unit = "type" }, + { "caption_encoding", "encoding scheme of subtitle text", + OFFSET(encoding_scheme), AV_OPT_TYPE_INT, { .i64 = ARIBCC_ENCODING_SCHEME_AUTO }, + ARIBCC_ENCODING_SCHEME_AUTO, ARIBCC_ENCODING_SCHEME_ABNT_NBR_15606_1_LATIN, SD, "encoding" }, + { "auto", "automatically detect encoding scheme", 0, AV_OPT_TYPE_CONST, + { .i64 = ARIBCC_ENCODING_SCHEME_AUTO }, .flags = SD, .unit = "encoding" }, + { "jis", "8bit-char JIS encoding (Japanese ISDB captions)", 0, AV_OPT_TYPE_CONST, + { .i64 = ARIBCC_ENCODING_SCHEME_ARIB_STD_B24_JIS }, .flags = SD, .unit = "encoding" }, + { "utf8", "UTF-8 encoding (Philippines ISDB-T captions)", 0, AV_OPT_TYPE_CONST, + { .i64 = ARIBCC_ENCODING_SCHEME_ARIB_STD_B24_UTF8 }, .flags = SD, .unit = "encoding" }, + { "latin", "latin characters (SBTVD / ISDB-Tb captions used in South America)", 0, AV_OPT_TYPE_CONST, + { .i64 = ARIBCC_ENCODING_SCHEME_ABNT_NBR_15606_1_LATIN }, .flags = SD, .unit = "encoding" }, + { "ass_single_rect", "workaround of ASS subtitle for players which can't handle multi-rectangle [ass]", + OFFSET(ass_single_rect), AV_OPT_TYPE_BOOL, { .i64 = ASS_SINGLE_RECT }, 0, 1, SD }, + { "font", "comma-separated font family [ass, bitmap]", + OFFSET(font), AV_OPT_TYPE_STRING, { .str = NULL }, 0, 0, SD }, + { "replace_fullwidth_ascii", "replace MSZ fullwidth alphanumerics with halfwidth alphanumerics [ass, bitmap]", + OFFSET(replace_fullwidth_ascii), AV_OPT_TYPE_BOOL, { .i64 = 1 }, 0, 1, SD }, + { "force_outline_text", "always render characters with outline [(ass), bitmap]", + OFFSET(force_stroke_text), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, SD }, + { "ignore_background", "ignore rendering caption background [(ass), bitmap]", + OFFSET(ignore_background), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, SD }, + { "ignore_ruby", "ignore ruby-like characters [ass, bitmap]", + OFFSET(ignore_ruby), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, SD }, + { "outline_width", "outline width of text [(ass), bitmap]", + OFFSET(stroke_width), AV_OPT_TYPE_FLOAT, { .dbl = 1.5 }, 0.0, 3.0, SD }, + { "replace_drcs", "replace known DRCS [bitmap]", + OFFSET(replace_drcs), AV_OPT_TYPE_BOOL, { .i64 = 1 }, 0, 1, SD }, + {"canvas_size", "set input video size (WxH or abbreviation) [bitmap]", + OFFSET(canvas_width), AV_OPT_TYPE_IMAGE_SIZE, { .str = NULL }, 0, INT_MAX, SD }, + { NULL } +}; + +static const AVClass aribcaption_class = { + .class_name = "aribcaption decoder", + .item_name = av_default_item_name, + .option = options, + .version = LIBAVUTIL_VERSION_INT, +}; + +const FFCodec ff_libaribcaption_decoder = { + .p.name = "libaribcaption", + .p.long_name = NULL_IF_CONFIG_SMALL("ARIB STD-B24 caption decoder"), + .p.type = AVMEDIA_TYPE_SUBTITLE, + .p.id = AV_CODEC_ID_ARIB_CAPTION, + .priv_data_size = sizeof(ARIBCaptionContext), + .init = aribcaption_init, + .close = aribcaption_close, + FF_CODEC_DECODE_SUB_CB(aribcaption_decode), + .flush = aribcaption_flush, + .p.priv_class = &aribcaption_class, + .caps_internal = FF_CODEC_CAP_INIT_CLEANUP, +}; From e0835b4878f4f866a540e739683411d72c91f431 Mon Sep 17 00:00:00 2001 From: rcombs Date: Tue, 28 Mar 2023 16:29:46 -0400 Subject: [PATCH 0516/2172] lavc/vorbis_parser: ignore unrecognized packet types --- libavcodec/vorbis_parser.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libavcodec/vorbis_parser.c b/libavcodec/vorbis_parser.c index a7d15d4ce99..d2c9e647ce5 100644 --- a/libavcodec/vorbis_parser.c +++ b/libavcodec/vorbis_parser.c @@ -234,7 +234,8 @@ int av_vorbis_parse_frame_flags(AVVorbisParseContext *s, const uint8_t *buf, else if (buf[0] == 5) *flags |= VORBIS_FLAG_SETUP; else - goto bad_packet; + av_log(s, AV_LOG_VERBOSE, "Ignoring packet with unknown type %u\n", + buf[0]); /* Special packets have no duration. */ return 0; From 57271e4a685c51488cd69c2a52190280f012976e Mon Sep 17 00:00:00 2001 From: rcombs Date: Tue, 28 Mar 2023 16:29:51 -0400 Subject: [PATCH 0517/2172] lavf/oggdec: fix demux with unrecognized header packets Fixes ticket #10289. Co-authored-by: James Almer --- libavformat/oggparsevorbis.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/libavformat/oggparsevorbis.c b/libavformat/oggparsevorbis.c index 061840c2ed4..6fd12560bc9 100644 --- a/libavformat/oggparsevorbis.c +++ b/libavformat/oggparsevorbis.c @@ -311,7 +311,12 @@ static int vorbis_header(AVFormatContext *s, int idx) if (!(pkt_type & 1)) return priv->vp ? 0 : AVERROR_INVALIDDATA; - if (os->psize < 1 || pkt_type > 5) + if (pkt_type > 5) { + av_log(s, AV_LOG_VERBOSE, "Ignoring packet with unknown type %d\n", pkt_type); + return 1; + } + + if (os->psize < 1) return AVERROR_INVALIDDATA; if (priv->packet[pkt_type >> 1]) From 030b34eac9b6234487c1b6ad4c1d56f07e05150d Mon Sep 17 00:00:00 2001 From: Stefano Sabatini Date: Sun, 26 Mar 2023 17:29:12 +0200 Subject: [PATCH 0518/2172] doc/filters/drawtext: clarify meaning of strftime format string Also clarify what should be used instead of the strftime expansion mode. --- doc/filters.texi | 28 +++++++++++++++------------- 1 file changed, 15 insertions(+), 13 deletions(-) diff --git a/doc/filters.texi b/doc/filters.texi index 4449998ba4d..b397100ff84 100644 --- a/doc/filters.texi +++ b/doc/filters.texi @@ -12103,13 +12103,12 @@ The default value of @var{bordercolor} is "black". @item expansion Select how the @var{text} is expanded. Can be either @code{none}, -@code{strftime} (deprecated) or -@code{normal} (default). See the @ref{drawtext_expansion, Text expansion} section -below for details. +@code{strftime} (deprecated) or @code{normal} (default). See the +@ref{drawtext_expansion, Text expansion} section below for details. @item basetime Set a start time for the count. Value is in microseconds. Only applied -in the deprecated strftime expansion mode. To emulate in normal expansion +in the deprecated @code{strftime} expansion mode. To emulate in normal expansion mode use the @code{pts} function, supplying the start time (in seconds) as the second argument. @@ -12340,10 +12339,12 @@ The current packet's size (in bytes). @anchor{drawtext_expansion} @subsection Text expansion -If @option{expansion} is set to @code{strftime}, -the filter recognizes strftime() sequences in the provided text and -expands them accordingly. Check the documentation of strftime(). This -feature is deprecated. +If @option{expansion} is set to @code{strftime}, the filter recognizes +sequences accepted by the @code{strftime} C function in the provided +text and expands them accordingly. Check the documentation of +@code{strftime}. This feature is deprecated in favor of @code{normal} +expansion with the @code{gmtime} or @code{localtime} expansion +functions. If @option{expansion} is set to @code{none}, the text is printed verbatim. @@ -12390,13 +12391,13 @@ It can be used to add padding with zeros from the left. @item gmtime The time at which the filter is running, expressed in UTC. -It can accept an argument: a strftime() format string. +It can accept an argument: a @code{strftime} C function format string. The format string is extended to support the variable @var{%[1-6]N} which prints fractions of the second with optionally specified number of digits. @item localtime The time at which the filter is running, expressed in the local time zone. -It can accept an argument: a strftime() format string. +It can accept an argument: a @code{strftime} C function format string. The format string is extended to support the variable @var{%[1-6]N} which prints fractions of the second with optionally specified number of digits. @@ -12438,8 +12439,8 @@ If the format is set to @code{hms}, a third argument @code{24HH} may be supplied to present the hour part of the formatted timestamp in 24h format (00-23). -If the format is set to @code{localtime} or @code{gmtime}, -a third argument may be supplied: a strftime() format string. +If the format is set to @code{localtime} or @code{gmtime}, a third +argument may be supplied: a @code{strftime} C function format string. By default, @var{YYYY-MM-DD HH:MM:SS} format will be used. @end table @@ -12543,7 +12544,8 @@ drawtext="text='Test Text': fontsize=h/30: x=(w-text_w)/2: y=(h-text_h*2)" @end example @item -Print the date of a real-time encoding (see strftime(3)): +Print the date of a real-time encoding (see documentation for the +@code{strftime} C function): @example drawtext='fontfile=FreeSans.ttf:text=%@{localtime\:%a %b %d %Y@}' @end example From 7792f53e5e66eb3a340e93af12ab80c4a197e6b7 Mon Sep 17 00:00:00 2001 From: Stefano Sabatini Date: Sun, 26 Mar 2023 17:47:52 +0200 Subject: [PATCH 0519/2172] doc/filters: propose solutions to avoid shell escaping Reference drawtext textfile option and ffmpeg -filter_complex_script and -filter_script as possible solutions to avoid shell escaping. Address issue: http://trac.ffmpeg.org/ticket/9008 --- doc/ffmpeg.texi | 2 ++ doc/filters.texi | 22 +++++++++++++++++----- 2 files changed, 19 insertions(+), 5 deletions(-) diff --git a/doc/ffmpeg.texi b/doc/ffmpeg.texi index 6baf51bf0a5..adfc2726ff8 100644 --- a/doc/ffmpeg.texi +++ b/doc/ffmpeg.texi @@ -769,6 +769,7 @@ syntax. See the @ref{filter_complex_option,,-filter_complex option} if you want to create filtergraphs with multiple inputs and/or outputs. +@anchor{filter_script option} @item -filter_script[:@var{stream_specifier}] @var{filename} (@emph{output,per-stream}) This option is similar to @option{-filter}, the only difference is that its argument is the name of the file from which a filtergraph description is to be @@ -1978,6 +1979,7 @@ The default is the number of available CPUs. Define a complex filtergraph, i.e. one with arbitrary number of inputs and/or outputs. Equivalent to @option{-filter_complex}. +@anchor{filter_complex_script option} @item -filter_complex_script @var{filename} (@emph{global}) This option is similar to @option{-filter_complex}, the only difference is that its argument is the name of the file from which a complex filtergraph diff --git a/doc/filters.texi b/doc/filters.texi index b397100ff84..1c9d5233405 100644 --- a/doc/filters.texi +++ b/doc/filters.texi @@ -282,6 +282,18 @@ previous string will finally result in: -vf "drawtext=text=this is a \\\\\\'string\\\\\\'\\\\: may contain one\\, or more\\, special characters" @end example +In order to avoid cumbersome escaping when using a commandline tool accepting a +filter specification as input, it is advisable to avoid direct inclusion of the +filter or options specification in the shell. + +For example, in case of the @ref{drawtext,,drawtext filter}, you might prefer to +use the @option{textfile} option in place of @option{text} to specify the text +to render. + +When using the @command{ffmpeg} tool, you might consider to use the +@ref{filter_script option,,-filter_script option,ffmpeg} or +@ref{filter_complex_script option,,-filter_complex_script option,ffmpeg}. + @chapter Timeline editing Some filters support a generic @option{enable} option. For the filters @@ -12359,11 +12371,11 @@ braces is a function name, possibly followed by arguments separated by ':'. If the arguments contain special characters or delimiters (':' or '@}'), they should be escaped. -Note that they probably must also be escaped as the value for the -@option{text} option in the filter argument string and as the filter -argument in the filtergraph description, and possibly also for the shell, -that makes up to four levels of escaping; using a text file avoids these -problems. +Note that they probably must also be escaped as the value for the @option{text} +option in the filter argument string and as the filter argument in the +filtergraph description, and possibly also for the shell, that makes up to four +levels of escaping; using a text file with the @option{textfile} option avoids +these problems. The following functions are available: From 5c1330798978cee5b4d7926bea611820b1019804 Mon Sep 17 00:00:00 2001 From: Stefano Sabatini Date: Sun, 26 Mar 2023 19:32:17 +0200 Subject: [PATCH 0520/2172] doc/filters: mentions that whitespaces are ignored in the filtergraph specification Also provide example showing how to use this feature to improve filtergraph readability. Address issue: http://trac.ffmpeg.org/ticket/8115 --- doc/filters.texi | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/doc/filters.texi b/doc/filters.texi index 1c9d5233405..889de8b11a0 100644 --- a/doc/filters.texi +++ b/doc/filters.texi @@ -214,6 +214,23 @@ In a complete filterchain all the unlabelled filter input and output pads must be connected. A filtergraph is considered valid if all the filter input and output pads of all the filterchains are connected. +Leading and trailing whitespaces (space, tabs, or line feeds) separating tokens +in the filtergraph specification are ignored. This means that the filtergraph +can be expressed using empty lines and spaces to improve redability. + +For example, the filtergraph: +@example +testsrc,split[L1],hflip[L2];[L1][L2] hstack +@end example + +can be represented as: +@example +testsrc, +split [L1], hflip [L2]; + +[L1][L2] hstack +@end example + Libavfilter will automatically insert @ref{scale} filters where format conversion is required. It is possible to specify swscale flags for those automatically inserted scalers by prepending From 7d58df7bb2b01be7a8ed8f4dfec183e3f96dd764 Mon Sep 17 00:00:00 2001 From: Stefano Sabatini Date: Sun, 26 Mar 2023 20:08:56 +0200 Subject: [PATCH 0521/2172] lavfi/aspect: apply style fixes --- libavfilter/vf_aspect.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/libavfilter/vf_aspect.c b/libavfilter/vf_aspect.c index 0a10a5a1769..b453de70c55 100644 --- a/libavfilter/vf_aspect.c +++ b/libavfilter/vf_aspect.c @@ -41,7 +41,8 @@ static const char *const var_names[] = { "w", "h", - "a", "dar", + "a", + "dar", "sar", "hsub", "vsub", @@ -51,7 +52,8 @@ static const char *const var_names[] = { enum var_name { VAR_W, VAR_H, - VAR_A, VAR_DAR, + VAR_A, + VAR_DAR, VAR_SAR, VAR_HSUB, VAR_VSUB, @@ -105,8 +107,8 @@ static int get_aspect_ratio(AVFilterLink *inlink, AVRational *aspect_ratio) /* evaluate new aspect ratio*/ ret = av_expr_parse_and_eval(&res, s->ratio_expr, - var_names, var_values, - NULL, NULL, NULL, NULL, NULL, 0, ctx); + var_names, var_values, + NULL, NULL, NULL, NULL, NULL, 0, ctx); if (ret < 0) { ret = av_parse_ratio(aspect_ratio, s->ratio_expr, s->max, 0, ctx); } else From 47c56ff5540fd5e402e805c8878b8d5e59f40f96 Mon Sep 17 00:00:00 2001 From: Stefano Sabatini Date: Sun, 26 Mar 2023 20:14:08 +0200 Subject: [PATCH 0522/2172] doc/filters/aspect: update documentation Drop mention of unsupported N:M syntax, dropped since 0ed61546c459. Also, drop reference of common expression constants, and fix description of a expression parameter. Fix issue: http://trac.ffmpeg.org/ticket/9974 --- doc/filters.texi | 18 +++++------------- 1 file changed, 5 insertions(+), 13 deletions(-) diff --git a/doc/filters.texi b/doc/filters.texi index 889de8b11a0..62146e717f4 100644 --- a/doc/filters.texi +++ b/doc/filters.texi @@ -20888,12 +20888,9 @@ It accepts the following parameters: @item r, ratio, dar (@code{setdar} only), sar (@code{setsar} only) Set the aspect ratio used by the filter. -The parameter can be a floating point number string, an expression, or -a string of the form @var{num}:@var{den}, where @var{num} and -@var{den} are the numerator and denominator of the aspect ratio. If -the parameter is not specified, it is assumed the value "0". -In case the form "@var{num}:@var{den}" is used, the @code{:} character -should be escaped. +The parameter can be a floating point number string, or an expression. If the +parameter is not specified, the value "0" is assumed, meaning that the same +input value is used. @item max Set the maximum integer value to use for expressing numerator and @@ -20902,19 +20899,14 @@ Default value is @code{100}. @end table -The parameter @var{sar} is an expression containing -the following constants: +The parameter @var{sar} is an expression containing the following constants: @table @option -@item E, PI, PHI -These are approximated values for the mathematical constants e -(Euler's number), pi (Greek pi), and phi (the golden ratio). - @item w, h The input width and height. @item a -These are the same as @var{w} / @var{h}. +Same as @var{w} / @var{h}. @item sar The input sample aspect ratio. From 42d99d51324eabf2facdbc514b056de91a3c4c85 Mon Sep 17 00:00:00 2001 From: Stefano Sabatini Date: Sun, 26 Mar 2023 20:35:59 +0200 Subject: [PATCH 0523/2172] doc/outdevs/sdl: sort options by name --- doc/outdevs.texi | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/doc/outdevs.texi b/doc/outdevs.texi index aa41e295230..49eb6f8b1f8 100644 --- a/doc/outdevs.texi +++ b/doc/outdevs.texi @@ -421,32 +421,32 @@ For more information about SDL, check: @table @option -@item window_title -Set the SDL window title, if not specified default to the filename -specified for the output device. - @item icon_title Set the name of the iconified SDL window, if not specified it is set to the same value of @var{window_title}. +@item window_enable_quit +Enable quit action (using window button or keyboard key) +when non-zero value is provided. +Default value is 1 (enable quit action) + +@item window_fullscreen +Set fullscreen mode when non-zero value is provided. +Default value is zero. + @item window_size Set the SDL window size, can be a string of the form @var{width}x@var{height} or a video size abbreviation. If not specified it defaults to the size of the input video, downscaled according to the aspect ratio. +@item window_title +Set the SDL window title, if not specified default to the filename +specified for the output device. + @item window_x @item window_y Set the position of the window on the screen. - -@item window_fullscreen -Set fullscreen mode when non-zero value is provided. -Default value is zero. - -@item window_enable_quit -Enable quit action (using window button or keyboard key) -when non-zero value is provided. -Default value is 1 (enable quit action) @end table @subsection Interactive commands From 64016356bc1ed934188bbf6b9e1332b08ecebb4e Mon Sep 17 00:00:00 2001 From: Stefano Sabatini Date: Sun, 26 Mar 2023 20:43:26 +0200 Subject: [PATCH 0524/2172] doc/outdevs/sdl: update options documentation Drop mention of missing icon_title option, document window_borderless option. Fix issue: http://trac.ffmpeg.org/ticket/9583 --- doc/outdevs.texi | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/doc/outdevs.texi b/doc/outdevs.texi index 49eb6f8b1f8..93391dbed75 100644 --- a/doc/outdevs.texi +++ b/doc/outdevs.texi @@ -421,14 +421,14 @@ For more information about SDL, check: @table @option -@item icon_title -Set the name of the iconified SDL window, if not specified it is set -to the same value of @var{window_title}. +@item window_borderless +Set SDL window border off. +Default value is 0 (enable window border). @item window_enable_quit Enable quit action (using window button or keyboard key) when non-zero value is provided. -Default value is 1 (enable quit action) +Default value is 1 (enable quit action). @item window_fullscreen Set fullscreen mode when non-zero value is provided. From 0684e58886881a998f1a7b510d73600ff1df2b90 Mon Sep 17 00:00:00 2001 From: Stefano Sabatini Date: Sun, 26 Mar 2023 20:49:09 +0200 Subject: [PATCH 0525/2172] doc/filters/paletteuse: mention none dithering value Fix issue: http://trac.ffmpeg.org/ticket/9950 --- doc/filters.texi | 2 ++ 1 file changed, 2 insertions(+) diff --git a/doc/filters.texi b/doc/filters.texi index 62146e717f4..913c4712aa1 100644 --- a/doc/filters.texi +++ b/doc/filters.texi @@ -18652,6 +18652,8 @@ Frankie Sierra dithering v3 (error diffusion) Burkes dithering (error diffusion) @item atkinson Atkinson dithering by Bill Atkinson at Apple Computer (error diffusion) +@item none +Disable dithering. @end table Default is @var{sierra2_4a}. From 4d216654ca72dfd23fcafcc5195db0eb9bdd483b Mon Sep 17 00:00:00 2001 From: jackarain Date: Fri, 3 Mar 2023 17:49:26 +0800 Subject: [PATCH 0526/2172] libavformat/tcp: add local_addr/local_port for network option Signed-off-by: jackarain Signed-off-by: Anton Khirnov --- doc/protocols.texi | 6 +++++ libavformat/network.c | 14 ++++++++---- libavformat/network.h | 2 +- libavformat/tcp.c | 53 +++++++++++++++++++++++++++++++++++++++++-- libavformat/version.h | 2 +- 5 files changed, 69 insertions(+), 8 deletions(-) diff --git a/doc/protocols.texi b/doc/protocols.texi index 21ae6181a05..b3fad55591d 100644 --- a/doc/protocols.texi +++ b/doc/protocols.texi @@ -1882,6 +1882,12 @@ The list of supported options follows. Listen for an incoming connection. 0 disables listen, 1 enables listen in single client mode, 2 enables listen in multi-client mode. Default value is 0. +@item local_addr=@var{addr} +Local IP address of a network interface used for tcp socket connect. + +@item local_port=@var{port} +Local port used for tcp socket connect. + @item timeout=@var{microseconds} Set raise error timeout, expressed in microseconds. diff --git a/libavformat/network.c b/libavformat/network.c index 21e20b3e9a9..f752efc4114 100644 --- a/libavformat/network.c +++ b/libavformat/network.c @@ -356,7 +356,7 @@ struct ConnectionAttempt { static int start_connect_attempt(struct ConnectionAttempt *attempt, struct addrinfo **ptr, int timeout_ms, URLContext *h, - void (*customize_fd)(void *, int), void *customize_ctx) + int (*customize_fd)(void *, int, int), void *customize_ctx) { struct addrinfo *ai = *ptr; int ret; @@ -371,8 +371,14 @@ static int start_connect_attempt(struct ConnectionAttempt *attempt, ff_socket_nonblock(attempt->fd, 1); - if (customize_fd) - customize_fd(customize_ctx, attempt->fd); + if (customize_fd) { + ret = customize_fd(customize_ctx, attempt->fd, ai->ai_family); + if (ret) { + closesocket(attempt->fd); + attempt->fd = -1; + return ret; + } + } while ((ret = connect(attempt->fd, ai->ai_addr, ai->ai_addrlen))) { ret = ff_neterrno(); @@ -402,7 +408,7 @@ static int start_connect_attempt(struct ConnectionAttempt *attempt, int ff_connect_parallel(struct addrinfo *addrs, int timeout_ms_per_address, int parallel, URLContext *h, int *fd, - void (*customize_fd)(void *, int), void *customize_ctx) + int (*customize_fd)(void *, int, int), void *customize_ctx) { struct ConnectionAttempt attempts[3]; struct pollfd pfd[3]; diff --git a/libavformat/network.h b/libavformat/network.h index 71c49a73fbb..ca214087fc9 100644 --- a/libavformat/network.h +++ b/libavformat/network.h @@ -336,6 +336,6 @@ void ff_log_net_error(void *ctx, int level, const char* prefix); */ int ff_connect_parallel(struct addrinfo *addrs, int timeout_ms_per_address, int parallel, URLContext *h, int *fd, - void (*customize_fd)(void *, int), void *customize_ctx); + int (*customize_fd)(void *, int, int), void *customize_ctx); #endif /* AVFORMAT_NETWORK_H */ diff --git a/libavformat/tcp.c b/libavformat/tcp.c index a11ccbb913a..a8896334571 100644 --- a/libavformat/tcp.c +++ b/libavformat/tcp.c @@ -36,6 +36,8 @@ typedef struct TCPContext { const AVClass *class; int fd; int listen; + char *local_port; + char *local_addr; int open_timeout; int rw_timeout; int listen_timeout; @@ -52,6 +54,8 @@ typedef struct TCPContext { #define E AV_OPT_FLAG_ENCODING_PARAM static const AVOption options[] = { { "listen", "Listen for incoming connections", OFFSET(listen), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 2, .flags = D|E }, + { "local_port", "Local port", OFFSET(local_port), AV_OPT_TYPE_STRING, { .str = NULL }, 0, 0, .flags = D|E }, + { "local_addr", "Local address", OFFSET(local_addr), AV_OPT_TYPE_STRING, { .str = NULL }, 0, 0, .flags = D|E }, { "timeout", "set timeout (in microseconds) of socket I/O operations", OFFSET(rw_timeout), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, INT_MAX, .flags = D|E }, { "listen_timeout", "Connection awaiting timeout (in milliseconds)", OFFSET(listen_timeout), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, INT_MAX, .flags = D|E }, { "send_buffer_size", "Socket send buffer size (in bytes)", OFFSET(send_buffer_size), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, INT_MAX, .flags = D|E }, @@ -70,9 +74,40 @@ static const AVClass tcp_class = { .version = LIBAVUTIL_VERSION_INT, }; -static void customize_fd(void *ctx, int fd) +static int customize_fd(void *ctx, int fd, int family) { TCPContext *s = ctx; + + if (s->local_addr || s->local_port) { + struct addrinfo hints = { 0 }, *ai, *cur_ai; + int ret; + + hints.ai_family = family; + hints.ai_socktype = SOCK_STREAM; + + ret = getaddrinfo(s->local_addr, s->local_port, &hints, &ai); + if (ret) { + av_log(ctx, AV_LOG_ERROR, + "Failed to getaddrinfo local addr: %s port: %s err: %s\n", + s->local_addr, s->local_port, gai_strerror(ret)); + return ret; + } + + cur_ai = ai; + while (cur_ai) { + ret = bind(fd, (struct sockaddr *)cur_ai->ai_addr, (int)cur_ai->ai_addrlen); + if (ret) + cur_ai = cur_ai->ai_next; + else + break; + } + freeaddrinfo(ai); + + if (ret) { + ff_log_net_error(ctx, AV_LOG_ERROR, "bind local failed"); + return ret; + } + } /* Set the socket's send or receive buffer sizes, if specified. If unspecified or setting fails, system default is used. */ if (s->recv_buffer_size > 0) { @@ -97,6 +132,8 @@ static void customize_fd(void *ctx, int fd) } } #endif /* !HAVE_WINSOCK2_H */ + + return 0; } /* return non zero if error */ @@ -129,6 +166,18 @@ static int tcp_open(URLContext *h, const char *uri, int flags) if (buf == endptr) s->listen = 1; } + if (av_find_info_tag(buf, sizeof(buf), "local_port", p)) { + av_freep(&s->local_port); + s->local_port = av_strdup(buf); + if (!s->local_addr) + return AVERROR(ENOMEM); + } + if (av_find_info_tag(buf, sizeof(buf), "local_addr", p)) { + av_freep(&s->local_addr); + s->local_addr = av_strdup(buf); + if (!s->local_addr) + return AVERROR(ENOMEM); + } if (av_find_info_tag(buf, sizeof(buf), "timeout", p)) { s->rw_timeout = strtol(buf, NULL, 10); } @@ -183,7 +232,7 @@ static int tcp_open(URLContext *h, const char *uri, int flags) } if (fd < 0) goto fail1; - customize_fd(s, fd); + customize_fd(s, fd, cur_ai->ai_family); } if (s->listen == 2) { diff --git a/libavformat/version.h b/libavformat/version.h index af7d0a10249..cc56b7cf5ca 100644 --- a/libavformat/version.h +++ b/libavformat/version.h @@ -32,7 +32,7 @@ #include "version_major.h" #define LIBAVFORMAT_VERSION_MINOR 4 -#define LIBAVFORMAT_VERSION_MICRO 100 +#define LIBAVFORMAT_VERSION_MICRO 101 #define LIBAVFORMAT_VERSION_INT AV_VERSION_INT(LIBAVFORMAT_VERSION_MAJOR, \ LIBAVFORMAT_VERSION_MINOR, \ From b75159682a5838a53b436da5535daabfe1b66595 Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Thu, 30 Mar 2023 14:06:45 +0200 Subject: [PATCH 0527/2172] avfilter/af_rubberband: use correct array for multichannels --- libavfilter/af_rubberband.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libavfilter/af_rubberband.c b/libavfilter/af_rubberband.c index 34a16056673..c56bf5d82fc 100644 --- a/libavfilter/af_rubberband.c +++ b/libavfilter/af_rubberband.c @@ -100,7 +100,7 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in) if (s->first_pts == AV_NOPTS_VALUE) s->first_pts = in->pts; - rubberband_process(s->rbs, (const float *const *)in->data, in->nb_samples, ff_outlink_get_status(inlink)); + rubberband_process(s->rbs, (const float *const *)in->extended_data, in->nb_samples, ff_outlink_get_status(inlink)); s->nb_samples_in += in->nb_samples; nb_samples = rubberband_available(s->rbs); @@ -113,7 +113,7 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in) out->pts = s->first_pts + av_rescale_q(s->nb_samples_out, (AVRational){ 1, outlink->sample_rate }, outlink->time_base); - nb_samples = rubberband_retrieve(s->rbs, (float *const *)out->data, nb_samples); + nb_samples = rubberband_retrieve(s->rbs, (float *const *)out->extended_data, nb_samples); out->nb_samples = nb_samples; ret = ff_filter_frame(outlink, out); s->nb_samples_out += nb_samples; From 412d43b09a2e21c6c76ca87cc5f05a504a1fee1a Mon Sep 17 00:00:00 2001 From: Haihao Xiang Date: Wed, 8 Mar 2023 13:10:48 +0800 Subject: [PATCH 0528/2172] lavfi/vf_vpp_qsv: only add the given output sw format to output pad Otherwise the output format is not changed when output is in system memory. For example, the output format is still p010le in the following case: $ ffmpeg -qsv_device /dev/dri/renderD128 -f lavfi -i testsrc -vf "format=p010le,vpp_qsv=extra_hw_frames=8:format=nv12" -f null - ... Output #0, null, to 'pipe:': Metadata: encoder : Lavf60.4.100 Stream #0:0: Video: wrapped_avframe, p010le(tv, progressive), 320x240 [SAR 1:1 DAR 4:3], q=2-31, 200 kb/s, 25 fps, 25 tbn Signed-off-by: Haihao Xiang --- libavfilter/vf_vpp_qsv.c | 23 ++++++++++++++++------- 1 file changed, 16 insertions(+), 7 deletions(-) diff --git a/libavfilter/vf_vpp_qsv.c b/libavfilter/vf_vpp_qsv.c index 76f0bc3df1c..334a86551b8 100644 --- a/libavfilter/vf_vpp_qsv.c +++ b/libavfilter/vf_vpp_qsv.c @@ -714,7 +714,8 @@ static const AVOption vpp_options[] = { static int vpp_query_formats(AVFilterContext *ctx) { - int ret; + VPPContext *vpp = ctx->priv; + int ret, i = 0; static const enum AVPixelFormat in_pix_fmts[] = { AV_PIX_FMT_YUV420P, AV_PIX_FMT_NV12, @@ -727,17 +728,25 @@ static int vpp_query_formats(AVFilterContext *ctx) AV_PIX_FMT_QSV, AV_PIX_FMT_NONE }; - static const enum AVPixelFormat out_pix_fmts[] = { - AV_PIX_FMT_NV12, - AV_PIX_FMT_P010, - AV_PIX_FMT_QSV, - AV_PIX_FMT_NONE - }; + static enum AVPixelFormat out_pix_fmts[4]; ret = ff_formats_ref(ff_make_format_list(in_pix_fmts), &ctx->inputs[0]->outcfg.formats); if (ret < 0) return ret; + + /* User specifies the output format */ + if (vpp->out_format == AV_PIX_FMT_NV12 || + vpp->out_format == AV_PIX_FMT_P010) + out_pix_fmts[i++] = vpp->out_format; + else { + out_pix_fmts[i++] = AV_PIX_FMT_NV12; + out_pix_fmts[i++] = AV_PIX_FMT_P010; + } + + out_pix_fmts[i++] = AV_PIX_FMT_QSV; + out_pix_fmts[i++] = AV_PIX_FMT_NONE; + return ff_formats_ref(ff_make_format_list(out_pix_fmts), &ctx->outputs[0]->incfg.formats); } From d2e1389285eb31581b3370508ddaf226f79148fe Mon Sep 17 00:00:00 2001 From: Raphael Schlarb Date: Thu, 30 Mar 2023 14:27:41 +0200 Subject: [PATCH 0529/2172] avcodec/libfdk-accenc: Add option to set frame length when encoding with libfdk_aac MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Some specifications require the size of ld/eld frames to be 480 samples instead of the default 512. libfdk_aac provides an option to set an alternative frame size, but it's not exposed via the ffmpeg interface. This patch adds a frame_length option to solve this problem. Signed-off-by: Raphael Schlarb Reviewed-by: Martin Storsjö Signed-off-by: James Almer --- libavcodec/libfdk-aacenc.c | 11 +++++++++++ libavcodec/version.h | 2 +- 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/libavcodec/libfdk-aacenc.c b/libavcodec/libfdk-aacenc.c index eb97e0fb417..515e235baa0 100644 --- a/libavcodec/libfdk-aacenc.c +++ b/libavcodec/libfdk-aacenc.c @@ -55,6 +55,7 @@ typedef struct AACContext { int metadata_mode; AACENC_MetaData metaDataSetup; int delay_sent; + int frame_length; AudioFrameQueue afq; } AACContext; @@ -78,6 +79,7 @@ static const AVOption aac_enc_options[] = { { "comp_profile", "The desired compression profile for AAC DRC", offsetof(AACContext, comp_profile), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 256, AV_OPT_FLAG_AUDIO_PARAM | AV_OPT_FLAG_ENCODING_PARAM }, { "comp_target_ref", "Expected target reference level at decoder side in dB (for clipping prevention/limiter)", offsetof(AACContext, comp_target_ref), AV_OPT_TYPE_INT, { .i64 = 0.0 }, -31.75, 0, AV_OPT_FLAG_AUDIO_PARAM | AV_OPT_FLAG_ENCODING_PARAM }, { "prog_ref", "The program reference level or dialog level in dB", offsetof(AACContext, prog_ref), AV_OPT_TYPE_INT, { .i64 = 0.0 }, -31.75, 0, AV_OPT_FLAG_AUDIO_PARAM | AV_OPT_FLAG_ENCODING_PARAM }, + { "frame_length", "The desired frame length", offsetof(AACContext, frame_length), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, 1024, AV_OPT_FLAG_AUDIO_PARAM | AV_OPT_FLAG_ENCODING_PARAM }, FF_AAC_PROFILE_OPTS { NULL } }; @@ -166,6 +168,15 @@ static av_cold int aac_encode_init(AVCodecContext *avctx) } } + if (s->frame_length >= 0) { + if ((err = aacEncoder_SetParam(s->handle, AACENC_GRANULE_LENGTH, + s->frame_length)) != AACENC_OK) { + av_log(avctx, AV_LOG_ERROR, "Unable to set granule length: %s\n", + aac_get_error(err)); + goto error; + } + } + if ((err = aacEncoder_SetParam(s->handle, AACENC_SAMPLERATE, avctx->sample_rate)) != AACENC_OK) { av_log(avctx, AV_LOG_ERROR, "Unable to set the sample rate %d: %s\n", diff --git a/libavcodec/version.h b/libavcodec/version.h index 7acb261bb3b..ecb096f38bd 100644 --- a/libavcodec/version.h +++ b/libavcodec/version.h @@ -30,7 +30,7 @@ #include "version_major.h" #define LIBAVCODEC_VERSION_MINOR 7 -#define LIBAVCODEC_VERSION_MICRO 100 +#define LIBAVCODEC_VERSION_MICRO 101 #define LIBAVCODEC_VERSION_INT AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \ LIBAVCODEC_VERSION_MINOR, \ From 113f684271ff437c496aa3a59277a76908c0a0ae Mon Sep 17 00:00:00 2001 From: James Almer Date: Fri, 31 Mar 2023 08:51:58 -0300 Subject: [PATCH 0530/2172] doc/encoders: add an entry for the frame_length option from libfdk-aac MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reviewed-by: Martin Storsjö Signed-off-by: James Almer --- doc/encoders.texi | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/doc/encoders.texi b/doc/encoders.texi index af3bd43cbe5..3cb6fc1ce72 100644 --- a/doc/encoders.texi +++ b/doc/encoders.texi @@ -789,6 +789,11 @@ about 80-96 kbps/channel @end table Default value is 0. + +@item frame_length +Set the audio frame length in samples. Default value is the internal +default of the library. Refer to the library's documentation for information +about supported values. @end table @subsection Examples From 84b454935fae2633a8a5dd075e22393f3e8f932f Mon Sep 17 00:00:00 2001 From: Leo Izen Date: Tue, 21 Mar 2023 23:26:25 -0400 Subject: [PATCH 0531/2172] avcodec/pngdec: support sBIT chunks Add support for reading sBIT chunks, which mark the significant bit depth of the PNG file. This passes the metadata using the field bits_per_raw_sample of AVCodecContext. Signed-off-by: Leo Izen --- libavcodec/pngdec.c | 48 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 48 insertions(+) diff --git a/libavcodec/pngdec.c b/libavcodec/pngdec.c index 9403d72f2f4..8fbb71f60f6 100644 --- a/libavcodec/pngdec.c +++ b/libavcodec/pngdec.c @@ -98,6 +98,7 @@ typedef struct PNGDecContext { int bpp; int has_trns; uint8_t transparent_color_be[6]; + int significant_bits; uint32_t palette[256]; uint8_t *crow_buf; @@ -716,6 +717,14 @@ static int populate_avctx_color_fields(AVCodecContext *avctx, AVFrame *frame) avctx->colorspace = frame->colorspace = AVCOL_SPC_RGB; avctx->color_range = frame->color_range = AVCOL_RANGE_JPEG; + /* + * tRNS sets alpha depth to full, so we ignore sBIT if set. + * As a result we must wait until now to set + * avctx->bits_per_raw_sample in case tRNS appears after sBIT + */ + if (!s->has_trns && s->significant_bits > 0) + avctx->bits_per_raw_sample = s->significant_bits; + return 0; } @@ -996,6 +1005,41 @@ static int decode_iccp_chunk(PNGDecContext *s, GetByteContext *gb, AVFrame *f) return ret; } +static int decode_sbit_chunk(AVCodecContext *avctx, PNGDecContext *s, + GetByteContext *gb) +{ + int bits = 0; + int channels; + + if (!(s->hdr_state & PNG_IHDR)) { + av_log(avctx, AV_LOG_ERROR, "sBIT before IHDR\n"); + return AVERROR_INVALIDDATA; + } + + if (s->pic_state & PNG_IDAT) { + av_log(avctx, AV_LOG_ERROR, "sBIT after IDAT\n"); + return AVERROR_INVALIDDATA; + } + + channels = ff_png_get_nb_channels(s->color_type); + + if (bytestream2_get_bytes_left(gb) != channels) + return AVERROR_INVALIDDATA; + + for (int i = 0; i < channels; i++) { + int b = bytestream2_get_byteu(gb); + bits = FFMAX(b, bits); + } + + if (bits < 0 || bits > s->bit_depth) { + av_log(avctx, AV_LOG_ERROR, "Invalid significant bits: %d\n", bits); + return AVERROR_INVALIDDATA; + } + s->significant_bits = bits; + + return 0; +} + static void handle_small_bpp(PNGDecContext *s, AVFrame *p) { if (s->bits_per_pixel == 1 && s->color_type == PNG_COLOR_TYPE_PALETTE) { @@ -1440,6 +1484,10 @@ static int decode_frame_common(AVCodecContext *avctx, PNGDecContext *s, break; } + case MKTAG('s', 'B', 'I', 'T'): + if ((ret = decode_sbit_chunk(avctx, s, &gb_chunk)) < 0) + goto fail; + break; case MKTAG('g', 'A', 'M', 'A'): { AVBPrint bp; char *gamma_str; From c125860892e931d9b10f88ace73c91484815c3a8 Mon Sep 17 00:00:00 2001 From: Leo Izen Date: Tue, 21 Mar 2023 23:26:26 -0400 Subject: [PATCH 0532/2172] avcodec/pngenc: write sBIT chunks Add support for writing sBIT chunks, which mark the significant bit depth of the PNG file. This obtains the metadata using the field bits_per_raw_sample of AVCodecContext. Signed-off-by: Leo Izen --- libavcodec/pngenc.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/libavcodec/pngenc.c b/libavcodec/pngenc.c index 1489256d00d..21b033ea163 100644 --- a/libavcodec/pngenc.c +++ b/libavcodec/pngenc.c @@ -442,6 +442,12 @@ static int encode_headers(AVCodecContext *avctx, const AVFrame *pict) if (png_get_gama(pict->color_trc, s->buf)) png_write_chunk(&s->bytestream, MKTAG('g', 'A', 'M', 'A'), s->buf, 4); + if (avctx->bits_per_raw_sample > 0 && avctx->bits_per_raw_sample < s->bit_depth) { + int len = ff_png_get_nb_channels(s->color_type); + memset(s->buf, avctx->bits_per_raw_sample, len); + png_write_chunk(&s->bytestream, MKTAG('s', 'B', 'I', 'T'), s->buf, len); + } + /* put the palette if needed, must be after colorspace information */ if (s->color_type == PNG_COLOR_TYPE_PALETTE) { int has_alpha, alpha, i; From 182663a58a7a099e02e76da3b0f96d63e5c26a6d Mon Sep 17 00:00:00 2001 From: Christopher Degawa Date: Mon, 2 Jan 2023 17:01:28 -0600 Subject: [PATCH 0533/2172] get_cabac_inline_x86: Don't inline the assembly function on 32 bit MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit While the inline cabac assembly has worked correctly in i386 builds historically, modern compiler updates has started showing issues with it, when the function gets inlined into larger contexts that fail to provide the amount of free registers as this function requires. This was an issue with Clang on Windows on i386, which was fixed in c6d284b945324a7bc70ea8b9056040c8148aa835. However, recently the same issues also have started showing up with GCC (both for Windows and Linux). Whether the issue appears seems dependent on a lot of optimizer tuning (e.g. the issue appears or goes away depenent on the combinaton of -march= and -mtune= options), potentially due to the compiler making different decisions on how much to inline. Fixes: https://trac.ffmpeg.org/ticket/8903 Signed-off-by: Martin Storsjö --- libavcodec/x86/cabac.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavcodec/x86/cabac.h b/libavcodec/x86/cabac.h index b046a56a6b7..ce2aefcbac8 100644 --- a/libavcodec/x86/cabac.h +++ b/libavcodec/x86/cabac.h @@ -178,7 +178,7 @@ #if HAVE_7REGS && !BROKEN_COMPILER #define get_cabac_inline get_cabac_inline_x86 static -#if defined(_WIN32) && !defined(_WIN64) && defined(__clang__) +#if ARCH_X86_32 av_noinline #else av_always_inline From 33d06de6381aeaf0e6281f8ba0a39ed3bfda19fa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Storsj=C3=B6?= Date: Fri, 24 Mar 2023 23:08:10 +0200 Subject: [PATCH 0534/2172] libavformat: Account for negative position differences in ff_configure_buffers_for_index MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When scanning through the index, account for the fact that the compared samples may be located in an unexpected order in the file; this function is mainly interested in the absolute difference between file locations. Signed-off-by: Martin Storsjö --- libavformat/seek.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/libavformat/seek.c b/libavformat/seek.c index a236e285c04..faa47f961fa 100644 --- a/libavformat/seek.c +++ b/libavformat/seek.c @@ -208,9 +208,11 @@ void ff_configure_buffers_for_index(AVFormatContext *s, int64_t time_tolerance) for (; i2 < sti2->nb_index_entries; i2++) { const AVIndexEntry *const e2 = &sti2->index_entries[i2]; int64_t e2_pts = av_rescale_q(e2->timestamp, st2->time_base, AV_TIME_BASE_Q); + int64_t cur_delta; if (e2_pts < e1_pts || e2_pts - (uint64_t)e1_pts < time_tolerance) continue; - pos_delta = FFMAX(pos_delta, e1->pos - e2->pos); + cur_delta = FFABS(e1->pos - e2->pos); + pos_delta = FFMAX(pos_delta, cur_delta); break; } } From c221036502751d7a6e1403a9868c60f1ff357963 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Storsj=C3=B6?= Date: Tue, 21 Mar 2023 13:29:44 +0200 Subject: [PATCH 0535/2172] libavformat: Improve ff_configure_buffers_for_index for excessive deltas MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Previously, the ff_configure_buffers_for_index function had upper sanity limits of 16 MB (1<<24) for buffer_size and 8 MB (1<<23) for short_seek_threshold. However, if the index contained entries with a much larger delta, setting pos_delta to a value larger than the sanity limit, we would end up not increasing the buffer size at all. Instead, ignore the individual deltas that are excessive, but increase the buffer size based on the deltas that are below the sanity limit. Only count deltas that are below 1<<23, 8 MB; pos_delta gets doubled before setting the buffer size - this matches the previous maximum buffer size of 1<<24, 16 MB. This can happen e.g. with a mov file with some tracks containing some samples that belong in the start of the file, at the end of the mdat, while the rest of the file is mostly reasonably interleaved; previously those samples caused the maximum pos_delta to skyrocket, skipping any buffer size enlargement. Signed-off-by: Martin Storsjö --- libavformat/seek.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/libavformat/seek.c b/libavformat/seek.c index faa47f961fa..386312cd3a4 100644 --- a/libavformat/seek.c +++ b/libavformat/seek.c @@ -204,7 +204,9 @@ void ff_configure_buffers_for_index(AVFormatContext *s, int64_t time_tolerance) const AVIndexEntry *const e1 = &sti1->index_entries[i1]; int64_t e1_pts = av_rescale_q(e1->timestamp, st1->time_base, AV_TIME_BASE_Q); - skip = FFMAX(skip, e1->size); + if (e1->size < (1 << 23)) + skip = FFMAX(skip, e1->size); + for (; i2 < sti2->nb_index_entries; i2++) { const AVIndexEntry *const e2 = &sti2->index_entries[i2]; int64_t e2_pts = av_rescale_q(e2->timestamp, st2->time_base, AV_TIME_BASE_Q); @@ -212,7 +214,8 @@ void ff_configure_buffers_for_index(AVFormatContext *s, int64_t time_tolerance) if (e2_pts < e1_pts || e2_pts - (uint64_t)e1_pts < time_tolerance) continue; cur_delta = FFABS(e1->pos - e2->pos); - pos_delta = FFMAX(pos_delta, cur_delta); + if (cur_delta < (1 << 23)) + pos_delta = FFMAX(pos_delta, cur_delta); break; } } @@ -222,7 +225,7 @@ void ff_configure_buffers_for_index(AVFormatContext *s, int64_t time_tolerance) pos_delta *= 2; ctx = ffiocontext(s->pb); /* XXX This could be adjusted depending on protocol*/ - if (s->pb->buffer_size < pos_delta && pos_delta < (1<<24)) { + if (s->pb->buffer_size < pos_delta) { av_log(s, AV_LOG_VERBOSE, "Reconfiguring buffers to size %"PRId64"\n", pos_delta); /* realloc the buffer and the original data will be retained */ @@ -234,9 +237,7 @@ void ff_configure_buffers_for_index(AVFormatContext *s, int64_t time_tolerance) ctx->short_seek_threshold = FFMAX(ctx->short_seek_threshold, pos_delta/2); } - if (skip < (1<<23)) { - ctx->short_seek_threshold = FFMAX(ctx->short_seek_threshold, skip); - } + ctx->short_seek_threshold = FFMAX(ctx->short_seek_threshold, skip); } int av_index_search_timestamp(AVStream *st, int64_t wanted_timestamp, int flags) From dd7e30724b739af9642917b1d04ba56d12e5e13f Mon Sep 17 00:00:00 2001 From: Gyan Doshi Date: Thu, 30 Mar 2023 23:19:56 +0530 Subject: [PATCH 0536/2172] avformat/tcp: correct strdup check Fixes CID 1524608. --- libavformat/tcp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavformat/tcp.c b/libavformat/tcp.c index a8896334571..db41394a845 100644 --- a/libavformat/tcp.c +++ b/libavformat/tcp.c @@ -169,7 +169,7 @@ static int tcp_open(URLContext *h, const char *uri, int flags) if (av_find_info_tag(buf, sizeof(buf), "local_port", p)) { av_freep(&s->local_port); s->local_port = av_strdup(buf); - if (!s->local_addr) + if (!s->local_port) return AVERROR(ENOMEM); } if (av_find_info_tag(buf, sizeof(buf), "local_addr", p)) { From 139f3352ed4bbe762c6f87b2443c9378c2beaae3 Mon Sep 17 00:00:00 2001 From: Samuel Raposo Vieira Mira Date: Mon, 27 Mar 2023 15:21:34 +0000 Subject: [PATCH 0537/2172] avcodec/mediacodec: add vp9 encoder using mediacodec The only encoders avaliable using mediacodec were h264 and hevc. This patch adds the vp9 encoder. Signed-off-by: Samuel Mira > Signed-off-by: Zhao Zhili --- configure | 3 ++ libavcodec/Makefile | 1 + libavcodec/allcodecs.c | 1 + libavcodec/mediacodec_wrapper.c | 24 +++++++++++++ libavcodec/mediacodecenc.c | 61 +++++++++++++++++++++++++++++++++ libavcodec/version.h | 4 +-- 6 files changed, 92 insertions(+), 2 deletions(-) diff --git a/configure b/configure index fe367462a10..f4afa00a6ea 100755 --- a/configure +++ b/configure @@ -3248,6 +3248,9 @@ vp8_v4l2m2m_decoder_deps="v4l2_m2m vp8_v4l2_m2m" vp8_v4l2m2m_encoder_deps="v4l2_m2m vp8_v4l2_m2m" vp9_cuvid_decoder_deps="cuvid" vp9_mediacodec_decoder_deps="mediacodec" +vp9_mediacodec_decoder_extralibs="-landroid" +vp9_mediacodec_encoder_deps="mediacodec" +vp9_mediacodec_encoder_extralibs="-landroid" vp9_qsv_decoder_select="qsvdec" vp9_rkmpp_decoder_deps="rkmpp" vp9_vaapi_encoder_deps="VAEncPictureParameterBufferVP9" diff --git a/libavcodec/Makefile b/libavcodec/Makefile index 711d2690d0b..fd0a89aa7f4 100644 --- a/libavcodec/Makefile +++ b/libavcodec/Makefile @@ -774,6 +774,7 @@ OBJS-$(CONFIG_VP9_DECODER) += vp9.o vp9data.o vp9dsp.o vp9lpf.o vp9r vp9dsp_8bpp.o vp9dsp_10bpp.o vp9dsp_12bpp.o OBJS-$(CONFIG_VP9_CUVID_DECODER) += cuviddec.o OBJS-$(CONFIG_VP9_MEDIACODEC_DECODER) += mediacodecdec.o +OBJS-$(CONFIG_VP9_MEDIACODEC_ENCODER) += mediacodecenc.o OBJS-$(CONFIG_VP9_RKMPP_DECODER) += rkmppdec.o OBJS-$(CONFIG_VP9_VAAPI_ENCODER) += vaapi_encode_vp9.o OBJS-$(CONFIG_VP9_QSV_ENCODER) += qsvenc_vp9.o diff --git a/libavcodec/allcodecs.c b/libavcodec/allcodecs.c index 3cbb93347b4..ea6edd0195f 100644 --- a/libavcodec/allcodecs.c +++ b/libavcodec/allcodecs.c @@ -884,6 +884,7 @@ extern const FFCodec ff_vp8_v4l2m2m_encoder; extern const FFCodec ff_vp8_vaapi_encoder; extern const FFCodec ff_vp9_cuvid_decoder; extern const FFCodec ff_vp9_mediacodec_decoder; +extern const FFCodec ff_vp9_mediacodec_encoder; extern const FFCodec ff_vp9_qsv_decoder; extern const FFCodec ff_vp9_vaapi_encoder; extern const FFCodec ff_vp9_qsv_encoder; diff --git a/libavcodec/mediacodec_wrapper.c b/libavcodec/mediacodec_wrapper.c index d1fb640ec21..b13211d435d 100644 --- a/libavcodec/mediacodec_wrapper.c +++ b/libavcodec/mediacodec_wrapper.c @@ -319,10 +319,23 @@ int ff_AMediaCodecProfile_getProfileFromAVCodecContext(AVCodecContext *avctx) static const int HEVCProfileMain10HDR10 = 0x1000; static const int HEVCProfileMain10HDR10Plus = 0x2000; + static const int VP9Profile0 = 0x01; + static const int VP9Profile1 = 0x02; + static const int VP9Profile2 = 0x04; + static const int VP9Profile3 = 0x08; + static const int VP9Profile2HDR = 0x1000; + static const int VP9Profile3HDR = 0x2000; + static const int VP9Profile2HDR10Plus = 0x4000; + static const int VP9Profile3HDR10Plus = 0x8000; + // Unused yet. (void)AVCProfileConstrainedHigh; (void)HEVCProfileMain10HDR10; (void)HEVCProfileMain10HDR10Plus; + (void)VP9Profile2HDR; + (void)VP9Profile3HDR; + (void)VP9Profile2HDR10Plus; + (void)VP9Profile3HDR10Plus; if (avctx->codec_id == AV_CODEC_ID_H264) { switch(avctx->profile) { @@ -357,6 +370,17 @@ int ff_AMediaCodecProfile_getProfileFromAVCodecContext(AVCodecContext *avctx) case FF_PROFILE_HEVC_MAIN_10: return HEVCProfileMain10; } + } else if (avctx->codec_id == AV_CODEC_ID_VP9) { + switch (avctx->profile) { + case FF_PROFILE_VP9_0: + return VP9Profile0; + case FF_PROFILE_VP9_1: + return VP9Profile1; + case FF_PROFILE_VP9_2: + return VP9Profile2; + case FF_PROFILE_VP9_3: + return VP9Profile3; + } } return -1; diff --git a/libavcodec/mediacodecenc.c b/libavcodec/mediacodecenc.c index 2ab56597fe7..c7e2beb1aef 100644 --- a/libavcodec/mediacodecenc.c +++ b/libavcodec/mediacodecenc.c @@ -164,6 +164,9 @@ static av_cold int mediacodec_init(AVCodecContext *avctx) case AV_CODEC_ID_HEVC: codec_mime = "video/hevc"; break; + case AV_CODEC_ID_VP9: + codec_mime = "video/x-vnd.on2.vp9"; + break; default: av_assert0(0); } @@ -764,3 +767,61 @@ static const AVOption hevc_options[] = { DECLARE_MEDIACODEC_ENCODER(hevc, "H.265", AV_CODEC_ID_HEVC) #endif // CONFIG_HEVC_MEDIACODEC_ENCODER + +#if CONFIG_VP9_MEDIACODEC_ENCODER + +enum MediaCodecVP9Level { + VP9Level1 = 0x1, + VP9Level11 = 0x2, + VP9Level2 = 0x4, + VP9Level21 = 0x8, + VP9Level3 = 0x10, + VP9Level31 = 0x20, + VP9Level4 = 0x40, + VP9Level41 = 0x80, + VP9Level5 = 0x100, + VP9Level51 = 0x200, + VP9Level52 = 0x400, + VP9Level6 = 0x800, + VP9Level61 = 0x1000, + VP9Level62 = 0x2000, +}; + +static const AVOption vp9_options[] = { + COMMON_OPTION + { "level", "Specify tier and level", + OFFSET(level), AV_OPT_TYPE_INT, {.i64 = 0}, 0, INT_MAX, VE, "level" }, + { "1", "Level 1", + 0, AV_OPT_TYPE_CONST, { .i64 = VP9Level1 }, 0, 0, VE, "level" }, + { "1.1", "Level 1.1", + 0, AV_OPT_TYPE_CONST, { .i64 = VP9Level11 }, 0, 0, VE, "level" }, + { "2", "Level 2", + 0, AV_OPT_TYPE_CONST, { .i64 = VP9Level2 }, 0, 0, VE, "level" }, + { "2.1", "Level 2.1", + 0, AV_OPT_TYPE_CONST, { .i64 = VP9Level21 }, 0, 0, VE, "level" }, + { "3", "Level 3", + 0, AV_OPT_TYPE_CONST, { .i64 = VP9Level3 }, 0, 0, VE, "level" }, + { "3.1", "Level 3.1", + 0, AV_OPT_TYPE_CONST, { .i64 = VP9Level31 }, 0, 0, VE, "level" }, + { "4", "Level 4", + 0, AV_OPT_TYPE_CONST, { .i64 = VP9Level4 }, 0, 0, VE, "level" }, + { "4.1", "Level 4.1", + 0, AV_OPT_TYPE_CONST, { .i64 = VP9Level41 }, 0, 0, VE, "level" }, + { "5", "Level 5", + 0, AV_OPT_TYPE_CONST, { .i64 = VP9Level5 }, 0, 0, VE, "level" }, + { "5.1", "Level 5.1", + 0, AV_OPT_TYPE_CONST, { .i64 = VP9Level51 }, 0, 0, VE, "level" }, + { "5.2", "Level 5.2", + 0, AV_OPT_TYPE_CONST, { .i64 = VP9Level52 }, 0, 0, VE, "level" }, + { "6", "Level 6", + 0, AV_OPT_TYPE_CONST, { .i64 = VP9Level6 }, 0, 0, VE, "level" }, + { "6.1", "Level 4.1", + 0, AV_OPT_TYPE_CONST, { .i64 = VP9Level61 }, 0, 0, VE, "level" }, + { "6.2", "Level 6.2", + 0, AV_OPT_TYPE_CONST, { .i64 = VP9Level62 }, 0, 0, VE, "level" }, + { NULL, } +}; + +DECLARE_MEDIACODEC_ENCODER(vp9, "VP9", AV_CODEC_ID_VP9) + +#endif // CONFIG_VP9_MEDIACODEC_ENCODER diff --git a/libavcodec/version.h b/libavcodec/version.h index ecb096f38bd..37c4c394511 100644 --- a/libavcodec/version.h +++ b/libavcodec/version.h @@ -29,8 +29,8 @@ #include "version_major.h" -#define LIBAVCODEC_VERSION_MINOR 7 -#define LIBAVCODEC_VERSION_MICRO 101 +#define LIBAVCODEC_VERSION_MINOR 8 +#define LIBAVCODEC_VERSION_MICRO 100 #define LIBAVCODEC_VERSION_INT AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \ LIBAVCODEC_VERSION_MINOR, \ From b4eca5cce2a1a2872f6525ba50082536ee080445 Mon Sep 17 00:00:00 2001 From: Samuel Raposo Vieira Mira Date: Mon, 27 Mar 2023 15:21:27 +0000 Subject: [PATCH 0538/2172] avcodec/mediacodec: add mpeg4 encoder This patch will add MPEG4 encoder using Android Mediacodec Signed-off-by: Samuel Mira > Signed-off-by: Zhao Zhili --- configure | 2 ++ libavcodec/Makefile | 1 + libavcodec/allcodecs.c | 1 + libavcodec/mediacodec_wrapper.c | 55 +++++++++++++++++++++++++++++++++ libavcodec/mediacodecenc.c | 49 +++++++++++++++++++++++++++++ libavcodec/version.h | 2 +- 6 files changed, 109 insertions(+), 1 deletion(-) diff --git a/configure b/configure index f4afa00a6ea..16b94103b52 100755 --- a/configure +++ b/configure @@ -3228,6 +3228,8 @@ mpeg2_v4l2m2m_decoder_deps="v4l2_m2m mpeg2_v4l2_m2m" mpeg4_crystalhd_decoder_select="crystalhd" mpeg4_cuvid_decoder_deps="cuvid" mpeg4_mediacodec_decoder_deps="mediacodec" +mpeg4_mediacodec_encoder_deps="mediacodec" +mpeg4_mediacodec_encoder_extralibs="-landroid" mpeg4_mmal_decoder_deps="mmal" mpeg4_omx_encoder_deps="omx" mpeg4_v4l2m2m_decoder_deps="v4l2_m2m mpeg4_v4l2_m2m" diff --git a/libavcodec/Makefile b/libavcodec/Makefile index fd0a89aa7f4..d23d4d4a967 100644 --- a/libavcodec/Makefile +++ b/libavcodec/Makefile @@ -542,6 +542,7 @@ OBJS-$(CONFIG_MPEG4_DECODER) += mpeg4videodsp.o xvididct.o OBJS-$(CONFIG_MPEG4_ENCODER) += mpeg4videoenc.o OBJS-$(CONFIG_MPEG4_CUVID_DECODER) += cuviddec.o OBJS-$(CONFIG_MPEG4_MEDIACODEC_DECODER) += mediacodecdec.o +OBJS-$(CONFIG_MPEG4_MEDIACODEC_ENCODER) += mediacodecenc.o OBJS-$(CONFIG_MPEG4_OMX_ENCODER) += omx.o OBJS-$(CONFIG_MPEG4_V4L2M2M_DECODER) += v4l2_m2m_dec.o OBJS-$(CONFIG_MPEG4_V4L2M2M_ENCODER) += v4l2_m2m_enc.o diff --git a/libavcodec/allcodecs.c b/libavcodec/allcodecs.c index ea6edd0195f..a73d1c9fcc7 100644 --- a/libavcodec/allcodecs.c +++ b/libavcodec/allcodecs.c @@ -873,6 +873,7 @@ extern const FFCodec ff_mpeg2_qsv_encoder; extern const FFCodec ff_mpeg2_vaapi_encoder; extern const FFCodec ff_mpeg4_cuvid_decoder; extern const FFCodec ff_mpeg4_mediacodec_decoder; +extern const FFCodec ff_mpeg4_mediacodec_encoder; extern const FFCodec ff_mpeg4_omx_encoder; extern const FFCodec ff_mpeg4_v4l2m2m_encoder; extern const FFCodec ff_prores_videotoolbox_encoder; diff --git a/libavcodec/mediacodec_wrapper.c b/libavcodec/mediacodec_wrapper.c index b13211d435d..1c29bb74066 100644 --- a/libavcodec/mediacodec_wrapper.c +++ b/libavcodec/mediacodec_wrapper.c @@ -328,6 +328,23 @@ int ff_AMediaCodecProfile_getProfileFromAVCodecContext(AVCodecContext *avctx) static const int VP9Profile2HDR10Plus = 0x4000; static const int VP9Profile3HDR10Plus = 0x8000; + static const int MPEG4ProfileSimple = 0x01; + static const int MPEG4ProfileSimpleScalable = 0x02; + static const int MPEG4ProfileCore = 0x04; + static const int MPEG4ProfileMain = 0x08; + static const int MPEG4ProfileNbit = 0x10; + static const int MPEG4ProfileScalableTexture = 0x20; + static const int MPEG4ProfileSimpleFBA = 0x80; + static const int MPEG4ProfileSimpleFace = 0x40; + static const int MPEG4ProfileBasicAnimated = 0x100; + static const int MPEG4ProfileHybrid = 0x200; + static const int MPEG4ProfileAdvancedRealTime = 0x400; + static const int MPEG4ProfileCoreScalable = 0x800; + static const int MPEG4ProfileAdvancedCoding = 0x1000; + static const int MPEG4ProfileAdvancedCore = 0x2000; + static const int MPEG4ProfileAdvancedScalable = 0x4000; + static const int MPEG4ProfileAdvancedSimple = 0x8000; + // Unused yet. (void)AVCProfileConstrainedHigh; (void)HEVCProfileMain10HDR10; @@ -381,6 +398,44 @@ int ff_AMediaCodecProfile_getProfileFromAVCodecContext(AVCodecContext *avctx) case FF_PROFILE_VP9_3: return VP9Profile3; } + } else if(avctx->codec_id == AV_CODEC_ID_MPEG4) { + switch (avctx->profile) + { + case FF_PROFILE_MPEG4_SIMPLE: + return MPEG4ProfileSimple; + case FF_PROFILE_MPEG4_SIMPLE_SCALABLE: + return MPEG4ProfileSimpleScalable; + case FF_PROFILE_MPEG4_CORE: + return MPEG4ProfileCore; + case FF_PROFILE_MPEG4_MAIN: + return MPEG4ProfileMain; + case FF_PROFILE_MPEG4_N_BIT: + return MPEG4ProfileNbit; + case FF_PROFILE_MPEG4_SCALABLE_TEXTURE: + return MPEG4ProfileScalableTexture; + case FF_PROFILE_MPEG4_SIMPLE_FACE_ANIMATION: + return MPEG4ProfileSimpleFBA; + case FF_PROFILE_MPEG4_BASIC_ANIMATED_TEXTURE: + return MPEG4ProfileBasicAnimated; + case FF_PROFILE_MPEG4_HYBRID: + return MPEG4ProfileHybrid; + case FF_PROFILE_MPEG4_ADVANCED_REAL_TIME: + return MPEG4ProfileAdvancedRealTime; + case FF_PROFILE_MPEG4_CORE_SCALABLE: + return MPEG4ProfileCoreScalable; + case FF_PROFILE_MPEG4_ADVANCED_CODING: + return MPEG4ProfileAdvancedCoding; + case FF_PROFILE_MPEG4_ADVANCED_CORE: + return MPEG4ProfileAdvancedCore; + case FF_PROFILE_MPEG4_ADVANCED_SCALABLE_TEXTURE: + return MPEG4ProfileAdvancedScalable; + case FF_PROFILE_MPEG4_ADVANCED_SIMPLE: + return MPEG4ProfileAdvancedSimple; + case FF_PROFILE_MPEG4_SIMPLE_STUDIO: + // Studio profiles are not supported by mediacodec. + default: + break; + } } return -1; diff --git a/libavcodec/mediacodecenc.c b/libavcodec/mediacodecenc.c index c7e2beb1aef..0767cd01659 100644 --- a/libavcodec/mediacodecenc.c +++ b/libavcodec/mediacodecenc.c @@ -167,6 +167,9 @@ static av_cold int mediacodec_init(AVCodecContext *avctx) case AV_CODEC_ID_VP9: codec_mime = "video/x-vnd.on2.vp9"; break; + case AV_CODEC_ID_MPEG4: + codec_mime = "video/mp4v-es"; + break; default: av_assert0(0); } @@ -825,3 +828,49 @@ static const AVOption vp9_options[] = { DECLARE_MEDIACODEC_ENCODER(vp9, "VP9", AV_CODEC_ID_VP9) #endif // CONFIG_VP9_MEDIACODEC_ENCODER + +#if CONFIG_MPEG4_MEDIACODEC_ENCODER + +enum MediaCodecMpeg4Level { + MPEG4Level0 = 0x01, + MPEG4Level0b = 0x02, + MPEG4Level1 = 0x04, + MPEG4Level2 = 0x08, + MPEG4Level3 = 0x10, + MPEG4Level3b = 0x18, + MPEG4Level4 = 0x20, + MPEG4Level4a = 0x40, + MPEG4Level5 = 0x80, + MPEG4Level6 = 0x100, +}; + +static const AVOption mpeg4_options[] = { + COMMON_OPTION + { "level", "Specify tier and level", + OFFSET(level), AV_OPT_TYPE_INT, {.i64 = 0}, 0, INT_MAX, VE, "level" }, + { "0", "Level 0", + 0, AV_OPT_TYPE_CONST, { .i64 = MPEG4Level0 }, 0, 0, VE, "level" }, + { "0b", "Level 0b", + 0, AV_OPT_TYPE_CONST, { .i64 = MPEG4Level0b }, 0, 0, VE, "level" }, + { "1", "Level 1", + 0, AV_OPT_TYPE_CONST, { .i64 = MPEG4Level1 }, 0, 0, VE, "level" }, + { "2", "Level 2", + 0, AV_OPT_TYPE_CONST, { .i64 = MPEG4Level2 }, 0, 0, VE, "level" }, + { "3", "Level 3", + 0, AV_OPT_TYPE_CONST, { .i64 = MPEG4Level3 }, 0, 0, VE, "level" }, + { "3b", "Level 3b", + 0, AV_OPT_TYPE_CONST, { .i64 = MPEG4Level3b }, 0, 0, VE, "level" }, + { "4", "Level 4", + 0, AV_OPT_TYPE_CONST, { .i64 = MPEG4Level4 }, 0, 0, VE, "level" }, + { "4a", "Level 4a", + 0, AV_OPT_TYPE_CONST, { .i64 = MPEG4Level4a }, 0, 0, VE, "level" }, + { "5", "Level 5", + 0, AV_OPT_TYPE_CONST, { .i64 = MPEG4Level5 }, 0, 0, VE, "level" }, + { "6", "Level 6", + 0, AV_OPT_TYPE_CONST, { .i64 = MPEG4Level6 }, 0, 0, VE, "level" }, + { NULL, } +}; + +DECLARE_MEDIACODEC_ENCODER(mpeg4, "MPEG-4", AV_CODEC_ID_MPEG4) + +#endif // CONFIG_MPEG4_MEDIACODEC_ENCODER diff --git a/libavcodec/version.h b/libavcodec/version.h index 37c4c394511..230d5fa13e6 100644 --- a/libavcodec/version.h +++ b/libavcodec/version.h @@ -29,7 +29,7 @@ #include "version_major.h" -#define LIBAVCODEC_VERSION_MINOR 8 +#define LIBAVCODEC_VERSION_MINOR 9 #define LIBAVCODEC_VERSION_MICRO 100 #define LIBAVCODEC_VERSION_INT AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \ From 26eb3129dffed2fa4922b4336ce689403a65c6ed Mon Sep 17 00:00:00 2001 From: Stefano Sabatini Date: Sun, 15 Jan 2023 18:16:45 +0100 Subject: [PATCH 0539/2172] lavc: clarify color_range semantics Extend description for decoding and encoding use cases. Address issue: http://trac.ffmpeg.org/ticket/443 --- libavcodec/avcodec.h | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h index 18ca0e24943..1e91b9cb532 100644 --- a/libavcodec/avcodec.h +++ b/libavcodec/avcodec.h @@ -1016,8 +1016,11 @@ typedef struct AVCodecContext { /** * MPEG vs JPEG YUV range. - * - encoding: Set by user - * - decoding: Set by libavcodec + * - encoding: Set by user to override the default output color range value, + * If not specified, libavcodec sets the color range depending on the + * output format. + * - decoding: Set by libavcodec, can be set by the user to propagate the + * color range to components reading from the decoder context. */ enum AVColorRange color_range; From ee25a434dce2faf6c1766fbb9bfb36d2715aaa87 Mon Sep 17 00:00:00 2001 From: Stefano Sabatini Date: Sun, 26 Mar 2023 21:21:50 +0200 Subject: [PATCH 0540/2172] doc/filters/find_rect: extend documentation Document metadata entries set by the filter, extend and clarify options, add additional example showing how to extract the generated data. Address issue: http://trac.ffmpeg.org/ticket/8766 --- doc/filters.texi | 47 +++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 45 insertions(+), 2 deletions(-) diff --git a/doc/filters.texi b/doc/filters.texi index 913c4712aa1..120fe6664a3 100644 --- a/doc/filters.texi +++ b/doc/filters.texi @@ -13768,7 +13768,35 @@ value. @section find_rect -Find a rectangular object +Find a rectangular object in the input video. + +The object to search for must be specified as a gray8 image specified with the +@option{object} option. + +For each possible match, a score is computed. If the score reaches the specified +threshold, the object is considered found. + +If the input video contains multiple instances of the object, the filter will +find only one of them. + +When an object is found, the following metadata entries are set in the matching +frame: +@table @option +@item lavfi.rect.w +width of object + +@item lavfi.rect.h +height of object + +@item lavfi.rect.x +x position of object + +@item lavfi.rect.y +y position of object + +@item lavfi.rect.score +match score of the found object +@end table It accepts the following options: @@ -13777,7 +13805,12 @@ It accepts the following options: Filepath of the object image, needs to be in gray8. @item threshold -Detection threshold, default is 0.5. +Detection threshold, expressed as a decimal number in the range 0-1. + +A threshold value of 0.01 means only exact matches, a threshold of 0.99 means +almost everything matches. + +Default value is 0.5. @item mipmaps Number of mipmaps, default is 3. @@ -13797,6 +13830,16 @@ Cover a rectangular object by the supplied image of a given video using @command @example ffmpeg -i file.ts -vf find_rect=newref.pgm,cover_rect=cover.jpg:mode=cover new.mkv @end example + +@item +Find the position of an object in each frame using @command{ffprobe} and write +it to a log file: +@example +ffprobe -f lavfi movie=test.mp4,find_rect=object=object.pgm:threshold=0.3 \ + -show_entries frame=pkt_pts_time:frame_tags=lavfi.rect.x,lavfi.rect.y \ + -of csv -o find_rect.csv +@end example + @end itemize @section floodfill From 627d5a87bbe0495cdde10be7da9d3fe3810a3dc7 Mon Sep 17 00:00:00 2001 From: Stefano Sabatini Date: Mon, 27 Mar 2023 02:22:28 +0200 Subject: [PATCH 0541/2172] doc/ffmpeg: slightly rework introductory examples In particular, add a sentence to introduce the example, and add a simpler starting example with no options. Also use different format for input.avi and output.mp4, to convey that the conversion also works on the container format. Address issue: http://trac.ffmpeg.org/ticket/8730 --- doc/ffmpeg.texi | 22 +++++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/doc/ffmpeg.texi b/doc/ffmpeg.texi index adfc2726ff8..630971d90b9 100644 --- a/doc/ffmpeg.texi +++ b/doc/ffmpeg.texi @@ -49,24 +49,32 @@ Do not mix input and output files -- first specify all input files, then all output files. Also do not mix options which belong to different files. All options apply ONLY to the next input or output file and are reset between files. +Some simple examples follow. + @itemize @item -To set the video bitrate of the output file to 64 kbit/s: +Convert an input media file to a different format, by re-encoding media streams: +@example +ffmpeg -i input.avi output.mp4 +@end example + +@item +Set the video bitrate of the output file to 64 kbit/s: @example -ffmpeg -i input.avi -b:v 64k -bufsize 64k output.avi +ffmpeg -i input.avi -b:v 64k -bufsize 64k output.mp4 @end example @item -To force the frame rate of the output file to 24 fps: +Force the frame rate of the output file to 24 fps: @example -ffmpeg -i input.avi -r 24 output.avi +ffmpeg -i input.avi -r 24 output.mp4 @end example @item -To force the frame rate of the input file (valid for raw formats only) -to 1 fps and the frame rate of the output file to 24 fps: +Force the frame rate of the input file (valid for raw formats only) to 1 fps and +the frame rate of the output file to 24 fps: @example -ffmpeg -r 1 -i input.m2v -r 24 output.avi +ffmpeg -r 1 -i input.m2v -r 24 output.mp4 @end example @end itemize From 686e14e9fb8b77950fd29f7eb7907505abc67311 Mon Sep 17 00:00:00 2001 From: Stefano Sabatini Date: Wed, 29 Mar 2023 01:17:03 +0200 Subject: [PATCH 0542/2172] doc/platform: drop reference to ffmpeg.zeranoe.com It was closed in September 2020. Fix issue: http://trac.ffmpeg.org/ticket/9734 --- doc/platform.texi | 3 --- 1 file changed, 3 deletions(-) diff --git a/doc/platform.texi b/doc/platform.texi index 4090b856700..764911d2302 100644 --- a/doc/platform.texi +++ b/doc/platform.texi @@ -92,9 +92,6 @@ For information about compiling FFmpeg on OS/2 see @chapter Windows -To get help and instructions for building FFmpeg under Windows, check out -the FFmpeg Windows Help Forum at @url{http://ffmpeg.zeranoe.com/forum/}. - @section Native Windows compilation using MinGW or MinGW-w64 FFmpeg can be built to run natively on Windows using the MinGW-w64 From 774d358e0fd520ab9503447c5f8f5e1633b96e39 Mon Sep 17 00:00:00 2001 From: Stefano Sabatini Date: Sun, 26 Mar 2023 23:34:10 +0200 Subject: [PATCH 0543/2172] tools/zmqshell: port to python3 Also extend docs, use argparse and logging. --- tools/zmqshell.py | 63 ++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 52 insertions(+), 11 deletions(-) diff --git a/tools/zmqshell.py b/tools/zmqshell.py index a7d11260063..8d941636e1e 100755 --- a/tools/zmqshell.py +++ b/tools/zmqshell.py @@ -1,6 +1,32 @@ -#!/usr/bin/env python2 +#!/usr/bin/env python3 + +import argparse +import cmd +import logging +import sys +import zmq + +HELP = ''' +Provide a shell used to send interactive commands to a zmq filter. + +The command assumes there is a running zmq or azmq filter acting as a +ZMQ server. + +You can send a command to it, follwing the syntax: +TARGET COMMAND [COMMAND_ARGS] + +* TARGET is the target filter identifier to send the command to +* COMMAND is the name of the command sent to the filter +* COMMAND_ARGS is the optional specification of command arguments + +See the zmq/azmq filters documentation for more details, and the +zeromq documentation at: +https://zeromq.org/ +''' + +logging.basicConfig(format='zmqshell|%(levelname)s> %(message)s', level=logging.INFO) +log = logging.getLogger() -import sys, zmq, cmd class LavfiCmd(cmd.Cmd): prompt = 'lavfi> ' @@ -14,13 +40,28 @@ def __init__(self, bind_address): def onecmd(self, cmd): if cmd == 'EOF': sys.exit(0) - print 'Sending command:[%s]' % cmd - self.requester.send(cmd) - message = self.requester.recv() - print 'Received reply:[%s]' % message - -try: - bind_address = sys.argv[1] if len(sys.argv) > 1 else "tcp://localhost:5555" - LavfiCmd(bind_address).cmdloop('FFmpeg libavfilter interactive shell') -except KeyboardInterrupt: + log.info(f"Sending command: {cmd}") + self.requester.send_string(cmd) + response = self.requester.recv_string() + log.info(f"Received response: {response}") + + +class Formatter( + argparse.ArgumentDefaultsHelpFormatter, argparse.RawDescriptionHelpFormatter +): pass + + +def main(): + parser = argparse.ArgumentParser(description=HELP, formatter_class=Formatter) + parser.add_argument('--bind-address', '-b', default='tcp://localhost:5555', help='specify bind address used to communicate with ZMQ') + + args = parser.parse_args() + try: + LavfiCmd(args.bind_address).cmdloop('FFmpeg libavfilter interactive shell') + except KeyboardInterrupt: + pass + + +if __name__ == '__main__': + main() From 9d140ecaf80762aa13a71ea528ec4431e0355ed1 Mon Sep 17 00:00:00 2001 From: Stefano Sabatini Date: Sat, 25 Mar 2023 17:17:37 +0100 Subject: [PATCH 0544/2172] lavfi/unsharp: clarify invalid filter param constraints Clarify failure in case of x/y building a too big matrix. Example: $ ffmpeg -hide_banner -f lavfi -i color=c=white:size=640x360,unsharp=lx=5:ly=23 -f null -t 1 - [Parsed_unsharp_1 @ 0x5650e1c30240] luma matrix size (lx/2+ly/2)*2=26 greater than maximum value 25 color=c=white:size=640x360,unsharp=lx=5:ly=23: Invalid argument Fix trac issue: http://trac.ffmpeg.org/ticket/6033 --- libavfilter/vf_unsharp.c | 30 ++++++++++++++++++++++-------- 1 file changed, 22 insertions(+), 8 deletions(-) diff --git a/libavfilter/vf_unsharp.c b/libavfilter/vf_unsharp.c index e88e732c9ed..5e17ebce1ed 100644 --- a/libavfilter/vf_unsharp.c +++ b/libavfilter/vf_unsharp.c @@ -171,7 +171,10 @@ static int apply_unsharp_c(AVFilterContext *ctx, AVFrame *in, AVFrame *out) return 0; } -static void set_filter_param(UnsharpFilterParam *fp, int msize_x, int msize_y, float amount) +#define MAX_SCALEBITS 25 + +static int set_filter_param(AVFilterContext *ctx, const char *name, const char *short_name, + UnsharpFilterParam *fp, int msize_x, int msize_y, float amount) { fp->msize_x = msize_x; fp->msize_y = msize_y; @@ -181,20 +184,31 @@ static void set_filter_param(UnsharpFilterParam *fp, int msize_x, int msize_y, f fp->steps_y = msize_y / 2; fp->scalebits = (fp->steps_x + fp->steps_y) * 2; fp->halfscale = 1 << (fp->scalebits - 1); + + if (fp->scalebits > MAX_SCALEBITS) { + av_log(ctx, AV_LOG_ERROR, "%s matrix size (%sx/2+%sy/2)*2=%d greater than maximum value %d\n", + name, short_name, short_name, fp->scalebits, MAX_SCALEBITS); + return AVERROR(EINVAL); + } + + return 0; } static av_cold int init(AVFilterContext *ctx) { UnsharpContext *s = ctx->priv; + int ret; - set_filter_param(&s->luma, s->lmsize_x, s->lmsize_y, s->lamount); - set_filter_param(&s->chroma, s->cmsize_x, s->cmsize_y, s->camount); - set_filter_param(&s->alpha, s->amsize_x, s->amsize_y, s->aamount); +#define SET_FILTER_PARAM(name_, short_) \ + ret = set_filter_param(ctx, #name_, #short_, &s->name_, \ + s->short_##msize_x, s->short_##msize_y, s->short_##amount); \ + if (ret < 0) \ + return ret; \ + + SET_FILTER_PARAM(luma, l); + SET_FILTER_PARAM(chroma, c); + SET_FILTER_PARAM(alpha, a); - if (s->luma.scalebits >= 26 || s->chroma.scalebits >= 26 || s->alpha.scalebits >= 26) { - av_log(ctx, AV_LOG_ERROR, "luma or chroma or alpha matrix size too big\n"); - return AVERROR(EINVAL); - } s->apply_unsharp = apply_unsharp_c; return 0; } From 85c62b48e9189d84746009f26a4cff41ad5d4603 Mon Sep 17 00:00:00 2001 From: Devin Heitmueller Date: Fri, 17 Mar 2023 11:02:31 -0400 Subject: [PATCH 0545/2172] avcodec/bytestream: fix warnings with signed/unsigned compare in bytestream.h When including the header in decklink_enc.cpp it would be fed through the C++ compiler rather than the C compiler, which has more strict warnings when comparing signed/unsigned values. Make the local variables unsigned to match the arguments they are being passed for those functions. Signed-off-by: Devin Heitmueller Signed-off-by: Marton Balint --- libavcodec/bytestream.h | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/libavcodec/bytestream.h b/libavcodec/bytestream.h index d0033f14f36..67080604b92 100644 --- a/libavcodec/bytestream.h +++ b/libavcodec/bytestream.h @@ -180,7 +180,7 @@ static av_always_inline void bytestream2_skipu(GetByteContext *g, static av_always_inline void bytestream2_skip_p(PutByteContext *p, unsigned int size) { - int size2; + unsigned int size2; if (p->eof) return; size2 = FFMIN(p->buffer_end - p->buffer, size); @@ -268,7 +268,7 @@ static av_always_inline unsigned int bytestream2_get_buffer(GetByteContext *g, uint8_t *dst, unsigned int size) { - int size2 = FFMIN(g->buffer_end - g->buffer, size); + unsigned int size2 = FFMIN(g->buffer_end - g->buffer, size); memcpy(dst, g->buffer, size2); g->buffer += size2; return size2; @@ -287,7 +287,7 @@ static av_always_inline unsigned int bytestream2_put_buffer(PutByteContext *p, const uint8_t *src, unsigned int size) { - int size2; + unsigned int size2; if (p->eof) return 0; size2 = FFMIN(p->buffer_end - p->buffer, size); @@ -311,7 +311,7 @@ static av_always_inline void bytestream2_set_buffer(PutByteContext *p, const uint8_t c, unsigned int size) { - int size2; + unsigned int size2; if (p->eof) return; size2 = FFMIN(p->buffer_end - p->buffer, size); @@ -348,7 +348,7 @@ static av_always_inline unsigned int bytestream2_copy_buffer(PutByteContext *p, GetByteContext *g, unsigned int size) { - int size2; + unsigned int size2; if (p->eof) return 0; From 5f92a192315fc9349e7c9bdc923666f79d5c5e8d Mon Sep 17 00:00:00 2001 From: Marton Balint Date: Wed, 29 Mar 2023 00:01:17 +0200 Subject: [PATCH 0546/2172] avformat/assenc: avoid incorrect copy of null terminator When writing a subtitle SSA/ASS subtitle file, the AVCodecParameters::extradata buffer is written directly to the output. In the case where the buffer is filled from a matroska source file produced by some older versions of Handbrake, this buffer ends with a null terminating character, which is then erroneously copied into the middle of the output file. The change here avoids this problem by treating it as a string rather than a raw buffer. This way it is agnostic as to whether the source buffer was null terminated or not. Fixes ticket #10203. Reported-by: Tim Angus Signed-off-by: Marton Balint --- libavformat/assenc.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libavformat/assenc.c b/libavformat/assenc.c index 85a1e533715..6ecfb045173 100644 --- a/libavformat/assenc.c +++ b/libavformat/assenc.c @@ -70,8 +70,9 @@ static int write_header(AVFormatContext *s) ass->trailer = trailer; } + header_size = av_strnlen(par->extradata, header_size); avio_write(s->pb, par->extradata, header_size); - if (par->extradata[header_size - 1] != '\n') + if (header_size && par->extradata[header_size - 1] != '\n') avio_write(s->pb, "\r\n", 2); ass->ssa_mode = !strstr(par->extradata, "\n[V4+ Styles]"); if (!strstr(par->extradata, "\n[Events]")) From 1942dbb8cab8417838793d9810a21673355f3a9b Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Sun, 26 Mar 2023 19:49:21 +0200 Subject: [PATCH 0547/2172] avcodec/wavarc: Fix several integer overflows Fixes: signed integer overflow: -532410125 + -1759642300 cannot be represented in type 'int' Fixes: 57045/clusterfuzz-testcase-minimized-ffmpeg_AV_CODEC_ID_WAVARC_fuzzer-637023665297817 Found-by: continuous fuzzing process https://github.com/google/oss-fuzz/tree/master/projects/ffmpeg Signed-off-by: Michael Niedermayer --- libavcodec/wavarc.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/libavcodec/wavarc.c b/libavcodec/wavarc.c index 8d37af95716..896972cec82 100644 --- a/libavcodec/wavarc.c +++ b/libavcodec/wavarc.c @@ -349,7 +349,7 @@ static int decode_2slp(AVCodecContext *avctx, int sum = 15; for (int o = 0; o < order; o++) - sum += s->filter[ch][o] * samples[n + 70 - o - 1]; + sum += s->filter[ch][o] * (unsigned)samples[n + 70 - o - 1]; samples[n + 70] = get_srice(gb, k) + (sum >> 4); } @@ -452,7 +452,7 @@ static int wavarc_decode(AVCodecContext *avctx, AVFrame *frame, const int *src = s->samples[ch] + s->offset; for (int n = 0; n < frame->nb_samples; n++) - dst[n] = src[n] * (1 << s->shift) + 0x80U; + dst[n] = src[n] * (1U << s->shift) + 0x80U; } break; case AV_SAMPLE_FMT_S16P: @@ -461,7 +461,7 @@ static int wavarc_decode(AVCodecContext *avctx, AVFrame *frame, const int *src = s->samples[ch] + s->offset; for (int n = 0; n < frame->nb_samples; n++) - dst[n] = src[n] * (1 << s->shift); + dst[n] = src[n] * (1U << s->shift); } break; } From c2ed905b68d79d4e7823aae69578cdbf2bf191af Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Sun, 26 Mar 2023 20:31:05 +0200 Subject: [PATCH 0548/2172] avcodec/vc1dec: Use av_fast_realloc() for slices Fixes: Timeout Fixes: 57281/clusterfuzz-testcase-minimized-ffmpeg_AV_CODEC_ID_VC1IMAGE_fuzzer-4594141064724480 Found-by: continuous fuzzing process https://github.com/google/oss-fuzz/tree/master/projects/ffmpeg Signed-off-by: Michael Niedermayer --- libavcodec/vc1dec.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/libavcodec/vc1dec.c b/libavcodec/vc1dec.c index 5cb4c544c9a..18fb616fff5 100644 --- a/libavcodec/vc1dec.c +++ b/libavcodec/vc1dec.c @@ -836,6 +836,7 @@ static int vc1_decode_frame(AVCodecContext *avctx, AVFrame *pict, const uint8_t *rawbuf; int raw_size; } *slices = NULL, *tmp; + unsigned slices_allocated = 0; v->second_field = 0; @@ -859,6 +860,7 @@ static int vc1_decode_frame(AVCodecContext *avctx, AVFrame *pict, //for advanced profile we may need to parse and unescape data if (avctx->codec_id == AV_CODEC_ID_VC1 || avctx->codec_id == AV_CODEC_ID_VC1IMAGE) { int buf_size2 = 0; + size_t next_allocated = 0; buf2 = av_mallocz(buf_size + AV_INPUT_BUFFER_PADDING_SIZE); if (!buf2) return AVERROR(ENOMEM); @@ -882,7 +884,8 @@ static int vc1_decode_frame(AVCodecContext *avctx, AVFrame *pict, int buf_size3; if (avctx->hwaccel) buf_start_second_field = start; - tmp = av_realloc_array(slices, sizeof(*slices), n_slices+1); + av_size_mult(sizeof(*slices), n_slices+1, &next_allocated); + tmp = next_allocated ? av_fast_realloc(slices, &slices_allocated, next_allocated) : NULL; if (!tmp) { ret = AVERROR(ENOMEM); goto err; @@ -911,7 +914,8 @@ static int vc1_decode_frame(AVCodecContext *avctx, AVFrame *pict, break; case VC1_CODE_SLICE: { int buf_size3; - tmp = av_realloc_array(slices, sizeof(*slices), n_slices+1); + av_size_mult(sizeof(*slices), n_slices+1, &next_allocated); + tmp = next_allocated ? av_fast_realloc(slices, &slices_allocated, next_allocated) : NULL; if (!tmp) { ret = AVERROR(ENOMEM); goto err; @@ -946,7 +950,8 @@ static int vc1_decode_frame(AVCodecContext *avctx, AVFrame *pict, } else { // found field marker, unescape second field if (avctx->hwaccel) buf_start_second_field = divider; - tmp = av_realloc_array(slices, sizeof(*slices), n_slices+1); + av_size_mult(sizeof(*slices), n_slices+1, &next_allocated); + tmp = next_allocated ? av_fast_realloc(slices, &slices_allocated, next_allocated) : NULL; if (!tmp) { ret = AVERROR(ENOMEM); goto err; From 6d1d8609ac1054017ea3d11b325ed94a1205e9fd Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Sun, 26 Mar 2023 21:34:03 +0200 Subject: [PATCH 0549/2172] avcodec/g729postfilter: Limit shift in long term filter Fixes: shift exponent 34 is too large for 32-bit type 'int' Fixes: 57389/clusterfuzz-testcase-minimized-ffmpeg_AV_CODEC_ID_ACELP_KELVIN_fuzzer-6229522659016704 Found-by: continuous fuzzing process https://github.com/google/oss-fuzz/tree/master/projects/ffmpeg Signed-off-by: Michael Niedermayer --- libavcodec/g729postfilter.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavcodec/g729postfilter.c b/libavcodec/g729postfilter.c index f3cacbac05b..26e937f0baf 100644 --- a/libavcodec/g729postfilter.c +++ b/libavcodec/g729postfilter.c @@ -353,7 +353,7 @@ static int16_t long_term_filter(AudioDSPContext *adsp, int pitch_delay_int, if (tmp > 0) L_temp0 >>= tmp; else - L_temp1 >>= -tmp; + L_temp1 >>= FFMIN(-tmp, 31); /* Check if longer filter increases the values of R'(k). */ if (L_temp1 > L_temp0) { From dab1cd2dc0471d497f481736059b2023c5b7986a Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Sun, 26 Mar 2023 22:35:50 +0200 Subject: [PATCH 0550/2172] avcodec/vp3: Check width to avoid assertion failure Fixes: Assertion failure on x86-32 av_assert2(block_w * sizeof(pixel) <= FFABS(buf_linesize)); in ff_emulated_edge_mc() Fixes: 39641/clusterfuzz-testcase-minimized-ffmpeg_AV_CODEC_ID_THEORA_fuzzer-5925660741206016 Found-by: continuous fuzzing process https://github.com/google/oss-fuzz/tree/master/projects/ffmpeg Signed-off-by: Michael Niedermayer --- libavcodec/vp3.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/libavcodec/vp3.c b/libavcodec/vp3.c index 9660def675f..22348559461 100644 --- a/libavcodec/vp3.c +++ b/libavcodec/vp3.c @@ -2353,6 +2353,8 @@ static av_cold int vp3_decode_init(AVCodecContext *avctx) s->avctx = avctx; s->width = FFALIGN(avctx->coded_width, 16); s->height = FFALIGN(avctx->coded_height, 16); + if (s->width < 18) + return AVERROR_PATCHWELCOME; if (avctx->codec_id != AV_CODEC_ID_THEORA) avctx->pix_fmt = AV_PIX_FMT_YUV420P; avctx->chroma_sample_location = AVCHROMA_LOC_CENTER; @@ -2919,7 +2921,9 @@ static int theora_decode_header(AVCodecContext *avctx, GetBitContext *gb) /* sanity check */ if (av_image_check_size(visible_width, visible_height, 0, avctx) < 0 || visible_width + offset_x > s->width || - visible_height + offset_y > s->height) { + visible_height + offset_y > s->height || + visible_width < 18 + ) { av_log(avctx, AV_LOG_ERROR, "Invalid frame dimensions - w:%d h:%d x:%d y:%d (%dx%d).\n", visible_width, visible_height, offset_x, offset_y, @@ -2965,6 +2969,8 @@ static int theora_decode_header(AVCodecContext *avctx, GetBitContext *gb) } else avctx->pix_fmt = AV_PIX_FMT_YUV420P; + if (s->width < 18) + return AVERROR_PATCHWELCOME; ret = ff_set_dimensions(avctx, s->width, s->height); if (ret < 0) return ret; From f6955b6df4b599ff5604e82987b96957414f8dd5 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Thu, 30 Mar 2023 18:15:36 +0200 Subject: [PATCH 0551/2172] avcodec/j2kenc: fix 5/3 DWT identifer Signed-off-by: Michael Niedermayer --- libavcodec/j2kenc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavcodec/j2kenc.c b/libavcodec/j2kenc.c index 6406f90ac2c..821967f9e43 100644 --- a/libavcodec/j2kenc.c +++ b/libavcodec/j2kenc.c @@ -1810,7 +1810,7 @@ static const AVOption options[] = { { "tile_height", "Tile Height", OFFSET(tile_height), AV_OPT_TYPE_INT, { .i64 = 256 }, 1, 1<<30, VE, }, { "pred", "DWT Type", OFFSET(pred), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 1, VE, "pred" }, { "dwt97int", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = 0 }, INT_MIN, INT_MAX, VE, "pred" }, - { "dwt53", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = 0 }, INT_MIN, INT_MAX, VE, "pred" }, + { "dwt53", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = 1 }, INT_MIN, INT_MAX, VE, "pred" }, { "sop", "SOP marker", OFFSET(sop), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 1, VE, }, { "eph", "EPH marker", OFFSET(eph), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 1, VE, }, { "prog", "Progression Order", OFFSET(prog), AV_OPT_TYPE_INT, { .i64 = 0 }, JPEG2000_PGOD_LRCP, JPEG2000_PGOD_CPRL, VE, "prog" }, From 0adb375377f369b69b24d86bbfe674b7693ccf3c Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Thu, 30 Mar 2023 18:18:05 +0200 Subject: [PATCH 0552/2172] avcodec/j2kenc: remove misleading pred value This field is only checked for being 0 or not and not zero means 5/3 Signed-off-by: Michael Niedermayer --- libavcodec/j2kenc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavcodec/j2kenc.c b/libavcodec/j2kenc.c index 821967f9e43..0e23a8a8399 100644 --- a/libavcodec/j2kenc.c +++ b/libavcodec/j2kenc.c @@ -1729,7 +1729,7 @@ static av_cold int j2kenc_init(AVCodecContext *avctx) if (avctx->pix_fmt == AV_PIX_FMT_PAL8 && (s->pred != FF_DWT97_INT || s->format != CODEC_JP2)) { av_log(s->avctx, AV_LOG_WARNING, "Forcing lossless jp2 for pal8\n"); - s->pred = FF_DWT97_INT; + s->pred = 1; s->format = CODEC_JP2; } From 816676085e3d32f27d4001d9b95590046c487eb6 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Thu, 30 Mar 2023 18:21:28 +0200 Subject: [PATCH 0553/2172] avcodec/j2kenc: Fix funky bpno errors on decoding Signed-off-by: Michael Niedermayer --- libavcodec/j2kenc.c | 3 +-- tests/ref/vsynth/vsynth1-jpeg2000-97 | 4 ++-- tests/ref/vsynth/vsynth2-jpeg2000 | 4 ++-- tests/ref/vsynth/vsynth2-jpeg2000-97 | 4 ++-- tests/ref/vsynth/vsynth3-jpeg2000 | 4 ++-- tests/ref/vsynth/vsynth3-jpeg2000-97 | 4 ++-- tests/ref/vsynth/vsynth_lena-jpeg2000 | 4 ++-- tests/ref/vsynth/vsynth_lena-jpeg2000-97 | 4 ++-- 8 files changed, 15 insertions(+), 16 deletions(-) diff --git a/libavcodec/j2kenc.c b/libavcodec/j2kenc.c index 0e23a8a8399..236c720dfed 100644 --- a/libavcodec/j2kenc.c +++ b/libavcodec/j2kenc.c @@ -721,11 +721,10 @@ static void encode_cblk(Jpeg2000EncoderContext *s, Jpeg2000T1Context *t1, Jpeg20 if (max == 0){ cblk->nonzerobits = 0; - bpno = 0; } else{ cblk->nonzerobits = av_log2(max) + 1 - NMSEDEC_FRACBITS; - bpno = cblk->nonzerobits - 1; } + bpno = cblk->nonzerobits - 1; cblk->data[0] = 0; ff_mqc_initenc(&t1->mqc, cblk->data + 1); diff --git a/tests/ref/vsynth/vsynth1-jpeg2000-97 b/tests/ref/vsynth/vsynth1-jpeg2000-97 index 6ab5aa4237c..c979ab5c364 100644 --- a/tests/ref/vsynth/vsynth1-jpeg2000-97 +++ b/tests/ref/vsynth/vsynth1-jpeg2000-97 @@ -1,4 +1,4 @@ -e4d03b2e3c03e56c7f831b1e662c4031 *tests/data/fate/vsynth1-jpeg2000-97.avi -3643928 tests/data/fate/vsynth1-jpeg2000-97.avi +5e6d32b7205d31245b0d1f015d08b515 *tests/data/fate/vsynth1-jpeg2000-97.avi +3643886 tests/data/fate/vsynth1-jpeg2000-97.avi a2262f1da2f49bc196b780a6b47ec4e8 *tests/data/fate/vsynth1-jpeg2000-97.out.rawvideo stddev: 4.23 PSNR: 35.59 MAXDIFF: 53 bytes: 7603200/ 7603200 diff --git a/tests/ref/vsynth/vsynth2-jpeg2000 b/tests/ref/vsynth/vsynth2-jpeg2000 index d0df0099ea0..b60307d5da6 100644 --- a/tests/ref/vsynth/vsynth2-jpeg2000 +++ b/tests/ref/vsynth/vsynth2-jpeg2000 @@ -1,4 +1,4 @@ -8c8a68ca748190c71b3ea43e5ab7f502 *tests/data/fate/vsynth2-jpeg2000.avi -1538736 tests/data/fate/vsynth2-jpeg2000.avi +bfe90391779a02319aab98b06dd18e6c *tests/data/fate/vsynth2-jpeg2000.avi +1538724 tests/data/fate/vsynth2-jpeg2000.avi 64fadc87447268cf90503cb294db7f61 *tests/data/fate/vsynth2-jpeg2000.out.rawvideo stddev: 4.91 PSNR: 34.29 MAXDIFF: 55 bytes: 7603200/ 7603200 diff --git a/tests/ref/vsynth/vsynth2-jpeg2000-97 b/tests/ref/vsynth/vsynth2-jpeg2000-97 index 33c1fb2425d..591f8b6bb32 100644 --- a/tests/ref/vsynth/vsynth2-jpeg2000-97 +++ b/tests/ref/vsynth/vsynth2-jpeg2000-97 @@ -1,4 +1,4 @@ -c8f76055f59804ca72dbd66eb4db83a2 *tests/data/fate/vsynth2-jpeg2000-97.avi -2464138 tests/data/fate/vsynth2-jpeg2000-97.avi +aa5573136c54b1855d8d00efe2a149bd *tests/data/fate/vsynth2-jpeg2000-97.avi +2464134 tests/data/fate/vsynth2-jpeg2000-97.avi 1f63c8b065e847e4c63d57ce23442ea8 *tests/data/fate/vsynth2-jpeg2000-97.out.rawvideo stddev: 3.21 PSNR: 37.99 MAXDIFF: 26 bytes: 7603200/ 7603200 diff --git a/tests/ref/vsynth/vsynth3-jpeg2000 b/tests/ref/vsynth/vsynth3-jpeg2000 index ecc286b9a46..894dba27dc5 100644 --- a/tests/ref/vsynth/vsynth3-jpeg2000 +++ b/tests/ref/vsynth/vsynth3-jpeg2000 @@ -1,4 +1,4 @@ -776bf3234cbf25002f129b89baab42ea *tests/data/fate/vsynth3-jpeg2000.avi -67400 tests/data/fate/vsynth3-jpeg2000.avi +1d039969504abdc143b410f99b5f9171 *tests/data/fate/vsynth3-jpeg2000.avi +67354 tests/data/fate/vsynth3-jpeg2000.avi 098f5980667e1fcd50452b1dc1a74f61 *tests/data/fate/vsynth3-jpeg2000.out.rawvideo stddev: 5.47 PSNR: 33.36 MAXDIFF: 48 bytes: 86700/ 86700 diff --git a/tests/ref/vsynth/vsynth3-jpeg2000-97 b/tests/ref/vsynth/vsynth3-jpeg2000-97 index df10f43270c..5d9d0837917 100644 --- a/tests/ref/vsynth/vsynth3-jpeg2000-97 +++ b/tests/ref/vsynth/vsynth3-jpeg2000-97 @@ -1,4 +1,4 @@ -cd023db503f03ef72dd83e4617a90c7b *tests/data/fate/vsynth3-jpeg2000-97.avi -85606 tests/data/fate/vsynth3-jpeg2000-97.avi +522e12684aca4262a9d613cb2db7006c *tests/data/fate/vsynth3-jpeg2000-97.avi +85526 tests/data/fate/vsynth3-jpeg2000-97.avi 8def36ad1413ab3a5c2af2e1af4603f9 *tests/data/fate/vsynth3-jpeg2000-97.out.rawvideo stddev: 4.51 PSNR: 35.04 MAXDIFF: 47 bytes: 86700/ 86700 diff --git a/tests/ref/vsynth/vsynth_lena-jpeg2000 b/tests/ref/vsynth/vsynth_lena-jpeg2000 index 88629add21a..e2cbc899d35 100644 --- a/tests/ref/vsynth/vsynth_lena-jpeg2000 +++ b/tests/ref/vsynth/vsynth_lena-jpeg2000 @@ -1,4 +1,4 @@ -b8aaa45236f77a2a626791d462fd8ac1 *tests/data/fate/vsynth_lena-jpeg2000.avi -1188886 tests/data/fate/vsynth_lena-jpeg2000.avi +51f061731d7fb987ff4e71789785225e *tests/data/fate/vsynth_lena-jpeg2000.avi +1188882 tests/data/fate/vsynth_lena-jpeg2000.avi 39a2c5b61cd0cf2821c6fb4cceba2fa8 *tests/data/fate/vsynth_lena-jpeg2000.out.rawvideo stddev: 4.30 PSNR: 35.45 MAXDIFF: 45 bytes: 7603200/ 7603200 diff --git a/tests/ref/vsynth/vsynth_lena-jpeg2000-97 b/tests/ref/vsynth/vsynth_lena-jpeg2000-97 index b6f5f75f77a..05393001859 100644 --- a/tests/ref/vsynth/vsynth_lena-jpeg2000-97 +++ b/tests/ref/vsynth/vsynth_lena-jpeg2000-97 @@ -1,4 +1,4 @@ -b2d9525433c6300674f504922d762437 *tests/data/fate/vsynth_lena-jpeg2000-97.avi -1937232 tests/data/fate/vsynth_lena-jpeg2000-97.avi +80fe872c8afaad914da6ef037957d93b *tests/data/fate/vsynth_lena-jpeg2000-97.avi +1937216 tests/data/fate/vsynth_lena-jpeg2000-97.avi 1b97333a8dc115a5ba609b0070d89d4d *tests/data/fate/vsynth_lena-jpeg2000-97.out.rawvideo stddev: 2.82 PSNR: 39.10 MAXDIFF: 24 bytes: 7603200/ 7603200 From b7418f768cd79a2a3d1fed273f8f199baa4f0f3f Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Thu, 30 Mar 2023 18:26:19 +0200 Subject: [PATCH 0554/2172] avcodec/j2kenc: Add AV_PIX_FMT_YUV440P Signed-off-by: Michael Niedermayer --- libavcodec/j2kenc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavcodec/j2kenc.c b/libavcodec/j2kenc.c index 236c720dfed..75bac3c2d84 100644 --- a/libavcodec/j2kenc.c +++ b/libavcodec/j2kenc.c @@ -1841,7 +1841,7 @@ const FFCodec ff_jpeg2000_encoder = { .close = j2kenc_destroy, .p.pix_fmts = (const enum AVPixelFormat[]) { AV_PIX_FMT_RGB24, AV_PIX_FMT_YUV444P, AV_PIX_FMT_GRAY8, - AV_PIX_FMT_YUV420P, AV_PIX_FMT_YUV422P, + AV_PIX_FMT_YUV420P, AV_PIX_FMT_YUV422P, AV_PIX_FMT_YUV440P, AV_PIX_FMT_YUV410P, AV_PIX_FMT_YUV411P, AV_PIX_FMT_PAL8, AV_PIX_FMT_RGB48, AV_PIX_FMT_GRAY16, From 644d15716d5cfb28e4ea0c0ada163f70807e9a5c Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Thu, 30 Mar 2023 18:40:31 +0200 Subject: [PATCH 0555/2172] avcodec/j2kenc: simplify pixel format setup Signed-off-by: Michael Niedermayer --- libavcodec/j2kenc.c | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/libavcodec/j2kenc.c b/libavcodec/j2kenc.c index 75bac3c2d84..c3a7a264dc0 100644 --- a/libavcodec/j2kenc.c +++ b/libavcodec/j2kenc.c @@ -1716,6 +1716,7 @@ static av_cold int j2kenc_init(AVCodecContext *avctx) Jpeg2000EncoderContext *s = avctx->priv_data; Jpeg2000CodingStyle *codsty = &s->codsty; Jpeg2000QuantStyle *qntsty = &s->qntsty; + const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(avctx->pix_fmt); s->avctx = avctx; av_log(s->avctx, AV_LOG_DEBUG, "init\n"); @@ -1758,20 +1759,13 @@ static av_cold int j2kenc_init(AVCodecContext *avctx) s->width = avctx->width; s->height = avctx->height; + s->ncomponents = desc->nb_components; for (i = 0; i < 3; i++) { - if (avctx->pix_fmt == AV_PIX_FMT_GRAY16 || avctx->pix_fmt == AV_PIX_FMT_RGB48) - s->cbps[i] = 16; - else - s->cbps[i] = 8; + s->cbps[i] = desc->comp[i].depth; } - if (avctx->pix_fmt == AV_PIX_FMT_RGB24 || avctx->pix_fmt == AV_PIX_FMT_RGB48){ - s->ncomponents = 3; - } else if (avctx->pix_fmt == AV_PIX_FMT_GRAY8 || avctx->pix_fmt == AV_PIX_FMT_PAL8 || avctx->pix_fmt == AV_PIX_FMT_GRAY16){ - s->ncomponents = 1; - } else{ // planar YUV + if ((desc->flags & AV_PIX_FMT_FLAG_PLANAR) && s->ncomponents > 1) { s->planar = 1; - s->ncomponents = 3; ret = av_pix_fmt_get_chroma_sub_sample(avctx->pix_fmt, s->chroma_shift, s->chroma_shift + 1); if (ret) From 7fb70d27a26bb4072edf68857636fa4343ee24a3 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Thu, 30 Mar 2023 18:50:26 +0200 Subject: [PATCH 0556/2172] avcodec/j2kenc: Replace BGR48 / GRAY16 test by test for number of bits BGR48 is not supported and this was probably meant to be RGB48 so this fixes RGB48 a bit Signed-off-by: Michael Niedermayer --- libavcodec/j2kenc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavcodec/j2kenc.c b/libavcodec/j2kenc.c index c3a7a264dc0..d837b8b949e 100644 --- a/libavcodec/j2kenc.c +++ b/libavcodec/j2kenc.c @@ -1542,7 +1542,7 @@ static int encode_frame(AVCodecContext *avctx, AVPacket *pkt, s->lambda = s->picture->quality * LAMBDA_SCALE; - if (avctx->pix_fmt == AV_PIX_FMT_BGR48 || avctx->pix_fmt == AV_PIX_FMT_GRAY16) + if (s->cbps[0] > 8) copy_frame_16(s); else copy_frame_8(s); From ad4d647591dbd953a5cf3a32a779ee5e42465bbb Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Thu, 30 Mar 2023 18:57:56 +0200 Subject: [PATCH 0557/2172] avcodec/j2kenc: Replace RGB24 special case by generic test This fixes RGB48 with libavcodec as decoder Signed-off-by: Michael Niedermayer --- libavcodec/j2kenc.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libavcodec/j2kenc.c b/libavcodec/j2kenc.c index d837b8b949e..8d9c1fdb1c0 100644 --- a/libavcodec/j2kenc.c +++ b/libavcodec/j2kenc.c @@ -1530,6 +1530,7 @@ static int encode_frame(AVCodecContext *avctx, AVPacket *pkt, int tileno, ret; Jpeg2000EncoderContext *s = avctx->priv_data; uint8_t *chunkstart, *jp2cstart, *jp2hstart; + const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(avctx->pix_fmt); if ((ret = ff_alloc_packet(avctx, pkt, avctx->width*avctx->height*9 + AV_INPUT_BUFFER_MIN_SIZE)) < 0) return ret; @@ -1586,7 +1587,7 @@ static int encode_frame(AVCodecContext *avctx, AVPacket *pkt, bytestream_put_byte(&s->buf, 1); bytestream_put_byte(&s->buf, 0); bytestream_put_byte(&s->buf, 0); - if (avctx->pix_fmt == AV_PIX_FMT_RGB24 || avctx->pix_fmt == AV_PIX_FMT_PAL8) { + if ((desc->flags & AV_PIX_FMT_FLAG_RGB) || avctx->pix_fmt == AV_PIX_FMT_PAL8) { bytestream_put_be32(&s->buf, 16); } else if (s->ncomponents == 1) { bytestream_put_be32(&s->buf, 17); From b41dabd00dcaaf83e6750cceffa5543451ff12fc Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Thu, 30 Mar 2023 19:27:00 +0200 Subject: [PATCH 0558/2172] avcodec/j2kenc: Planar RGB support Signed-off-by: Michael Niedermayer --- libavcodec/j2kenc.c | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/libavcodec/j2kenc.c b/libavcodec/j2kenc.c index 8d9c1fdb1c0..0715d424a15 100644 --- a/libavcodec/j2kenc.c +++ b/libavcodec/j2kenc.c @@ -115,6 +115,7 @@ typedef struct { int width, height; ///< image width and height uint8_t cbps[4]; ///< bits per sample in particular components + uint8_t comp_remap[4]; int chroma_shift[2]; uint8_t planar; int ncomponents; @@ -512,17 +513,18 @@ static int init_tiles(Jpeg2000EncoderContext *s) Jpeg2000Tile *tile = s->tile + tileno; \ if (s->planar){ \ for (compno = 0; compno < s->ncomponents; compno++){ \ + int icompno = s->comp_remap[compno]; \ Jpeg2000Component *comp = tile->comp + compno; \ int *dst = comp->i_data; \ int cbps = s->cbps[compno]; \ - line = (const PIXEL*)s->picture->data[compno] \ - + comp->coord[1][0] * (s->picture->linesize[compno] / sizeof(PIXEL)) \ + line = (const PIXEL*)s->picture->data[icompno] \ + + comp->coord[1][0] * (s->picture->linesize[icompno] / sizeof(PIXEL)) \ + comp->coord[0][0]; \ for (y = comp->coord[1][0]; y < comp->coord[1][1]; y++){ \ const PIXEL *ptr = line; \ for (x = comp->coord[0][0]; x < comp->coord[0][1]; x++) \ *dst++ = *ptr++ - (1 << (cbps - 1)); \ - line += s->picture->linesize[compno] / sizeof(PIXEL); \ + line += s->picture->linesize[icompno] / sizeof(PIXEL); \ } \ } \ } else{ \ @@ -1763,6 +1765,7 @@ static av_cold int j2kenc_init(AVCodecContext *avctx) s->ncomponents = desc->nb_components; for (i = 0; i < 3; i++) { s->cbps[i] = desc->comp[i].depth; + s->comp_remap[i] = i; //default } if ((desc->flags & AV_PIX_FMT_FLAG_PLANAR) && s->ncomponents > 1) { @@ -1771,6 +1774,11 @@ static av_cold int j2kenc_init(AVCodecContext *avctx) s->chroma_shift, s->chroma_shift + 1); if (ret) return ret; + if (desc->flags & AV_PIX_FMT_FLAG_RGB) { + s->comp_remap[0] = 2; + s->comp_remap[1] = 0; + s->comp_remap[2] = 1; + } } ff_thread_once(&init_static_once, init_luts); From b2404bd9aa7b311005d19b92ba2798a2c24cb7c8 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Thu, 30 Mar 2023 19:27:31 +0200 Subject: [PATCH 0559/2172] avcodec/j2kenc: More complete list of supported pixel formats Signed-off-by: Michael Niedermayer --- libavcodec/j2kenc.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/libavcodec/j2kenc.c b/libavcodec/j2kenc.c index 0715d424a15..462ba6da507 100644 --- a/libavcodec/j2kenc.c +++ b/libavcodec/j2kenc.c @@ -1843,11 +1843,16 @@ const FFCodec ff_jpeg2000_encoder = { FF_CODEC_ENCODE_CB(encode_frame), .close = j2kenc_destroy, .p.pix_fmts = (const enum AVPixelFormat[]) { - AV_PIX_FMT_RGB24, AV_PIX_FMT_YUV444P, AV_PIX_FMT_GRAY8, - AV_PIX_FMT_YUV420P, AV_PIX_FMT_YUV422P, AV_PIX_FMT_YUV440P, - AV_PIX_FMT_YUV410P, AV_PIX_FMT_YUV411P, + AV_PIX_FMT_RGB24, AV_PIX_FMT_RGB48, + AV_PIX_FMT_GBR24P,AV_PIX_FMT_GBRP9, AV_PIX_FMT_GBRP10, AV_PIX_FMT_GBRP12, AV_PIX_FMT_GBRP14, AV_PIX_FMT_GBRP16, + 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_YUV420P, AV_PIX_FMT_YUV420P9, AV_PIX_FMT_YUV420P10, AV_PIX_FMT_YUV420P12, AV_PIX_FMT_YUV420P14, AV_PIX_FMT_YUV420P16, + AV_PIX_FMT_YUV422P, AV_PIX_FMT_YUV422P9, AV_PIX_FMT_YUV422P10, AV_PIX_FMT_YUV422P12, AV_PIX_FMT_YUV422P14, AV_PIX_FMT_YUV422P16, + AV_PIX_FMT_YUV444P, AV_PIX_FMT_YUV444P9, AV_PIX_FMT_YUV444P10, AV_PIX_FMT_YUV444P12, AV_PIX_FMT_YUV444P14, AV_PIX_FMT_YUV444P16, + AV_PIX_FMT_YUV440P, AV_PIX_FMT_YUV440P10, AV_PIX_FMT_YUV440P12, + AV_PIX_FMT_YUV411P, + AV_PIX_FMT_YUV410P, AV_PIX_FMT_PAL8, - AV_PIX_FMT_RGB48, AV_PIX_FMT_GRAY16, AV_PIX_FMT_NONE }, .p.priv_class = &j2k_class, From 35b8b4f229afeed13ceade0058dca5cbadbe527e Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Thu, 30 Mar 2023 19:29:09 +0200 Subject: [PATCH 0560/2172] avcodec/j2kenc: support threads Signed-off-by: Michael Niedermayer --- libavcodec/j2kenc.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libavcodec/j2kenc.c b/libavcodec/j2kenc.c index 462ba6da507..97b0da1c976 100644 --- a/libavcodec/j2kenc.c +++ b/libavcodec/j2kenc.c @@ -1837,7 +1837,8 @@ const FFCodec ff_jpeg2000_encoder = { CODEC_LONG_NAME("JPEG 2000"), .p.type = AVMEDIA_TYPE_VIDEO, .p.id = AV_CODEC_ID_JPEG2000, - .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE, + .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE | + AV_CODEC_CAP_FRAME_THREADS, .priv_data_size = sizeof(Jpeg2000EncoderContext), .init = j2kenc_init, FF_CODEC_ENCODE_CB(encode_frame), From 60ccb3fe787be3bb10fc4545b3593cd1e0b769ed Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Thu, 30 Mar 2023 19:34:01 +0200 Subject: [PATCH 0561/2172] Remove libopenjpeg decoder We do not support other video/image decoders when we have our own. Signed-off-by: Michael Niedermayer --- configure | 1 - libavcodec/Makefile | 1 - libavcodec/allcodecs.c | 1 - libavcodec/libopenjpegdec.c | 516 ------------------------------------ 4 files changed, 519 deletions(-) delete mode 100644 libavcodec/libopenjpegdec.c diff --git a/configure b/configure index 16b94103b52..6e363eb4702 100755 --- a/configure +++ b/configure @@ -3369,7 +3369,6 @@ libopencore_amrwb_decoder_deps="libopencore_amrwb" libopenh264_decoder_deps="libopenh264" libopenh264_decoder_select="h264_mp4toannexb_bsf" libopenh264_encoder_deps="libopenh264" -libopenjpeg_decoder_deps="libopenjpeg" libopenjpeg_encoder_deps="libopenjpeg" libopenmpt_demuxer_deps="libopenmpt" libopus_decoder_deps="libopus" diff --git a/libavcodec/Makefile b/libavcodec/Makefile index d23d4d4a967..aa10fbfcf8f 100644 --- a/libavcodec/Makefile +++ b/libavcodec/Makefile @@ -1104,7 +1104,6 @@ OBJS-$(CONFIG_LIBOPENCORE_AMRNB_ENCODER) += libopencore-amr.o OBJS-$(CONFIG_LIBOPENCORE_AMRWB_DECODER) += libopencore-amr.o OBJS-$(CONFIG_LIBOPENH264_DECODER) += libopenh264dec.o libopenh264.o OBJS-$(CONFIG_LIBOPENH264_ENCODER) += libopenh264enc.o libopenh264.o -OBJS-$(CONFIG_LIBOPENJPEG_DECODER) += libopenjpegdec.o OBJS-$(CONFIG_LIBOPENJPEG_ENCODER) += libopenjpegenc.o OBJS-$(CONFIG_LIBOPUS_DECODER) += libopusdec.o libopus.o \ vorbis_data.o diff --git a/libavcodec/allcodecs.c b/libavcodec/allcodecs.c index a73d1c9fcc7..797fe394860 100644 --- a/libavcodec/allcodecs.c +++ b/libavcodec/allcodecs.c @@ -782,7 +782,6 @@ extern const FFCodec ff_libopencore_amrnb_encoder; extern const FFCodec ff_libopencore_amrnb_decoder; extern const FFCodec ff_libopencore_amrwb_decoder; extern const FFCodec ff_libopenjpeg_encoder; -extern const FFCodec ff_libopenjpeg_decoder; extern const FFCodec ff_libopus_encoder; extern const FFCodec ff_libopus_decoder; extern const FFCodec ff_librav1e_encoder; diff --git a/libavcodec/libopenjpegdec.c b/libavcodec/libopenjpegdec.c deleted file mode 100644 index 206db07ec70..00000000000 --- a/libavcodec/libopenjpegdec.c +++ /dev/null @@ -1,516 +0,0 @@ -/* - * JPEG 2000 decoding support via OpenJPEG - * Copyright (c) 2009 Jaikrishnan Menon - * - * 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 - * JPEG 2000 decoder using libopenjpeg - */ - -#include "libavutil/common.h" -#include "libavutil/imgutils.h" -#include "libavutil/intreadwrite.h" -#include "libavutil/opt.h" -#include "libavutil/pixfmt.h" - -#include "avcodec.h" -#include "codec_internal.h" -#include "decode.h" -#include "thread.h" - -#include - -#define JP2_SIG_TYPE 0x6A502020 -#define JP2_SIG_VALUE 0x0D0A870A - -// pix_fmts with lower bpp have to be listed before -// similar pix_fmts with higher bpp. -#define RGB_PIXEL_FORMATS AV_PIX_FMT_RGB24, AV_PIX_FMT_RGBA, \ - AV_PIX_FMT_RGB48, AV_PIX_FMT_RGBA64 - -#define GRAY_PIXEL_FORMATS AV_PIX_FMT_GRAY8, AV_PIX_FMT_YA8, \ - AV_PIX_FMT_GRAY10, AV_PIX_FMT_GRAY12, AV_PIX_FMT_GRAY14, \ - AV_PIX_FMT_GRAY16, AV_PIX_FMT_YA16 - -#define YUV_PIXEL_FORMATS AV_PIX_FMT_YUV410P, AV_PIX_FMT_YUV411P, AV_PIX_FMT_YUVA420P, \ - AV_PIX_FMT_YUV420P, AV_PIX_FMT_YUV422P, AV_PIX_FMT_YUVA422P, \ - AV_PIX_FMT_YUV440P, AV_PIX_FMT_YUV444P, AV_PIX_FMT_YUVA444P, \ - AV_PIX_FMT_YUV420P9, AV_PIX_FMT_YUV422P9, AV_PIX_FMT_YUV444P9, \ - AV_PIX_FMT_YUVA420P9, AV_PIX_FMT_YUVA422P9, AV_PIX_FMT_YUVA444P9, \ - AV_PIX_FMT_YUV420P10, AV_PIX_FMT_YUV422P10, AV_PIX_FMT_YUV444P10, \ - AV_PIX_FMT_YUVA420P10, AV_PIX_FMT_YUVA422P10, AV_PIX_FMT_YUVA444P10, \ - AV_PIX_FMT_YUV420P12, AV_PIX_FMT_YUV422P12, AV_PIX_FMT_YUV444P12, \ - AV_PIX_FMT_YUV420P14, AV_PIX_FMT_YUV422P14, AV_PIX_FMT_YUV444P14, \ - AV_PIX_FMT_YUV420P16, AV_PIX_FMT_YUV422P16, AV_PIX_FMT_YUV444P16, \ - AV_PIX_FMT_YUVA420P16, AV_PIX_FMT_YUVA422P16, AV_PIX_FMT_YUVA444P16 - -#define XYZ_PIXEL_FORMATS AV_PIX_FMT_XYZ12 - -static const enum AVPixelFormat libopenjpeg_rgb_pix_fmts[] = { - RGB_PIXEL_FORMATS -}; -static const enum AVPixelFormat libopenjpeg_gray_pix_fmts[] = { - GRAY_PIXEL_FORMATS -}; -static const enum AVPixelFormat libopenjpeg_yuv_pix_fmts[] = { - YUV_PIXEL_FORMATS -}; -static const enum AVPixelFormat libopenjpeg_all_pix_fmts[] = { - RGB_PIXEL_FORMATS, GRAY_PIXEL_FORMATS, YUV_PIXEL_FORMATS, XYZ_PIXEL_FORMATS -}; - -typedef struct LibOpenJPEGContext { - AVClass *class; - opj_dparameters_t dec_params; - int lowqual; -} LibOpenJPEGContext; - -static void error_callback(const char *msg, void *data) -{ - av_log(data, AV_LOG_ERROR, "%s", msg); -} - -static void warning_callback(const char *msg, void *data) -{ - av_log(data, AV_LOG_WARNING, "%s", msg); -} - -static void info_callback(const char *msg, void *data) -{ - av_log(data, AV_LOG_DEBUG, "%s", msg); -} - -typedef struct BufferReader { - int pos; - int size; - const uint8_t *buffer; -} BufferReader; - -static OPJ_SIZE_T stream_read(void *out_buffer, OPJ_SIZE_T nb_bytes, void *user_data) -{ - BufferReader *reader = user_data; - int remaining; - - if (reader->pos == reader->size) { - return (OPJ_SIZE_T)-1; - } - remaining = reader->size - reader->pos; - if (nb_bytes > remaining) { - nb_bytes = remaining; - } - memcpy(out_buffer, reader->buffer + reader->pos, nb_bytes); - reader->pos += (int)nb_bytes; - return nb_bytes; -} - -static OPJ_OFF_T stream_skip(OPJ_OFF_T nb_bytes, void *user_data) -{ - BufferReader *reader = user_data; - if (nb_bytes < 0) { - if (reader->pos == 0) { - return (OPJ_SIZE_T)-1; - } - if (nb_bytes + reader->pos < 0) { - nb_bytes = -reader->pos; - } - } else { - int remaining; - - if (reader->pos == reader->size) { - return (OPJ_SIZE_T)-1; - } - remaining = reader->size - reader->pos; - if (nb_bytes > remaining) { - nb_bytes = remaining; - } - } - reader->pos += (int)nb_bytes; - return nb_bytes; -} - -static OPJ_BOOL stream_seek(OPJ_OFF_T nb_bytes, void *user_data) -{ - BufferReader *reader = user_data; - if (nb_bytes < 0 || nb_bytes > reader->size) { - return OPJ_FALSE; - } - reader->pos = (int)nb_bytes; - return OPJ_TRUE; -} - -static inline int libopenjpeg_matches_pix_fmt(const opj_image_t *image, enum AVPixelFormat pix_fmt) -{ - const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(pix_fmt); - int match = 1; - - if (desc->nb_components != image->numcomps) { - return 0; - } - - switch (desc->nb_components) { - case 4: - match = match && - desc->comp[3].depth >= image->comps[3].prec && - 1 == image->comps[3].dx && - 1 == image->comps[3].dy; - case 3: - match = match && - desc->comp[2].depth >= image->comps[2].prec && - 1 << desc->log2_chroma_w == image->comps[2].dx && - 1 << desc->log2_chroma_h == image->comps[2].dy; - case 2: - match = match && - desc->comp[1].depth >= image->comps[1].prec && - 1 << desc->log2_chroma_w == image->comps[1].dx && - 1 << desc->log2_chroma_h == image->comps[1].dy; - case 1: - match = match && - desc->comp[0].depth >= image->comps[0].prec && - 1 == image->comps[0].dx && - 1 == image->comps[0].dy; - default: - break; - } - - return match; -} - -static inline enum AVPixelFormat libopenjpeg_guess_pix_fmt(const opj_image_t *image) { - int index; - const enum AVPixelFormat *possible_fmts = NULL; - int possible_fmts_nb = 0; - - switch (image->color_space) { - case OPJ_CLRSPC_SRGB: - possible_fmts = libopenjpeg_rgb_pix_fmts; - possible_fmts_nb = FF_ARRAY_ELEMS(libopenjpeg_rgb_pix_fmts); - break; - case OPJ_CLRSPC_GRAY: - possible_fmts = libopenjpeg_gray_pix_fmts; - possible_fmts_nb = FF_ARRAY_ELEMS(libopenjpeg_gray_pix_fmts); - break; - case OPJ_CLRSPC_SYCC: - possible_fmts = libopenjpeg_yuv_pix_fmts; - possible_fmts_nb = FF_ARRAY_ELEMS(libopenjpeg_yuv_pix_fmts); - break; - default: - possible_fmts = libopenjpeg_all_pix_fmts; - possible_fmts_nb = FF_ARRAY_ELEMS(libopenjpeg_all_pix_fmts); - break; - } - - for (index = 0; index < possible_fmts_nb; ++index) - if (libopenjpeg_matches_pix_fmt(image, possible_fmts[index])) { - return possible_fmts[index]; - } - - return AV_PIX_FMT_NONE; -} - -static inline int libopenjpeg_ispacked(enum AVPixelFormat pix_fmt) -{ - const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(pix_fmt); - int i, component_plane; - - if (pix_fmt == AV_PIX_FMT_GRAY16) - return 0; - - component_plane = desc->comp[0].plane; - for (i = 1; i < desc->nb_components; i++) - if (component_plane != desc->comp[i].plane) - return 0; - return 1; -} - -static inline void libopenjpeg_copy_to_packed8(AVFrame *picture, opj_image_t *image) { - uint8_t *img_ptr; - int index, x, y, c; - for (y = 0; y < picture->height; y++) { - index = y * picture->width; - img_ptr = picture->data[0] + y * picture->linesize[0]; - for (x = 0; x < picture->width; x++, index++) - for (c = 0; c < image->numcomps; c++) - *img_ptr++ = 0x80 * image->comps[c].sgnd + image->comps[c].data[index]; - } -} - -static inline void libopenjpeg_copy_to_packed16(AVFrame *picture, opj_image_t *image) { - uint16_t *img_ptr; - const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(picture->format); - int index, x, y, c; - int adjust[4]; - for (x = 0; x < image->numcomps; x++) - adjust[x] = FFMAX(FFMIN(desc->comp[x].depth - image->comps[x].prec, 8), 0) + desc->comp[x].shift; - - for (y = 0; y < picture->height; y++) { - index = y * picture->width; - img_ptr = (uint16_t *) (picture->data[0] + y * picture->linesize[0]); - for (x = 0; x < picture->width; x++, index++) - for (c = 0; c < image->numcomps; c++) - *img_ptr++ = (1 << image->comps[c].prec - 1) * image->comps[c].sgnd + - (unsigned)image->comps[c].data[index] << adjust[c]; - } -} - -static inline void libopenjpeg_copyto8(AVFrame *picture, opj_image_t *image) { - int *comp_data; - uint8_t *img_ptr; - int index, x, y; - - for (index = 0; index < image->numcomps; index++) { - comp_data = image->comps[index].data; - for (y = 0; y < image->comps[index].h; y++) { - img_ptr = picture->data[index] + y * picture->linesize[index]; - for (x = 0; x < image->comps[index].w; x++) { - *img_ptr = 0x80 * image->comps[index].sgnd + *comp_data; - img_ptr++; - comp_data++; - } - } - } -} - -static inline void libopenjpeg_copyto16(AVFrame *picture, opj_image_t *image) { - int *comp_data; - uint16_t *img_ptr; - const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(picture->format); - int index, x, y; - int adjust[4]; - for (x = 0; x < image->numcomps; x++) - adjust[x] = FFMAX(FFMIN(desc->comp[x].depth - image->comps[x].prec, 8), 0) + desc->comp[x].shift; - - for (index = 0; index < image->numcomps; index++) { - comp_data = image->comps[index].data; - for (y = 0; y < image->comps[index].h; y++) { - img_ptr = (uint16_t *)(picture->data[index] + y * picture->linesize[index]); - for (x = 0; x < image->comps[index].w; x++) { - *img_ptr = (1 << image->comps[index].prec - 1) * image->comps[index].sgnd + - (unsigned)*comp_data << adjust[index]; - img_ptr++; - comp_data++; - } - } - } -} - -static av_cold int libopenjpeg_decode_init(AVCodecContext *avctx) -{ - LibOpenJPEGContext *ctx = avctx->priv_data; - - opj_set_default_decoder_parameters(&ctx->dec_params); - return 0; -} - -static int libopenjpeg_decode_frame(AVCodecContext *avctx, AVFrame *picture, - int *got_frame, AVPacket *avpkt) -{ - const uint8_t *buf = avpkt->data; - int buf_size = avpkt->size; - LibOpenJPEGContext *ctx = avctx->priv_data; - const AVPixFmtDescriptor *desc; - int width, height, ret; - int pixel_size = 0; - int ispacked = 0; - int i; - opj_image_t *image = NULL; - BufferReader reader = {0, avpkt->size, avpkt->data}; - opj_codec_t *dec = NULL; - opj_stream_t *stream = NULL; - - *got_frame = 0; - - // Check if input is a raw jpeg2k codestream or in jp2 wrapping - if ((AV_RB32(buf) == 12) && - (AV_RB32(buf + 4) == JP2_SIG_TYPE) && - (AV_RB32(buf + 8) == JP2_SIG_VALUE)) { - dec = opj_create_decompress(OPJ_CODEC_JP2); - } else { - /* If the AVPacket contains a jp2c box, then skip to - * the starting byte of the codestream. */ - if (AV_RB32(buf + 4) == AV_RB32("jp2c")) - buf += 8; - dec = opj_create_decompress(OPJ_CODEC_J2K); - } - - if (!dec) { - av_log(avctx, AV_LOG_ERROR, "Error initializing decoder.\n"); - ret = AVERROR_EXTERNAL; - goto done; - } - - if (!opj_set_error_handler(dec, error_callback, avctx) || - !opj_set_warning_handler(dec, warning_callback, avctx) || - !opj_set_info_handler(dec, info_callback, avctx)) { - av_log(avctx, AV_LOG_ERROR, "Error setting decoder handlers.\n"); - ret = AVERROR_EXTERNAL; - goto done; - } - - ctx->dec_params.cp_layer = ctx->lowqual; - ctx->dec_params.cp_reduce = avctx->lowres; - - // Tie decoder with decoding parameters - opj_setup_decoder(dec, &ctx->dec_params); - - stream = opj_stream_default_create(OPJ_STREAM_READ); - - if (!stream) { - av_log(avctx, AV_LOG_ERROR, - "Codestream could not be opened for reading.\n"); - ret = AVERROR_EXTERNAL; - goto done; - } - - opj_stream_set_read_function(stream, stream_read); - opj_stream_set_skip_function(stream, stream_skip); - opj_stream_set_seek_function(stream, stream_seek); - opj_stream_set_user_data(stream, &reader, NULL); - opj_stream_set_user_data_length(stream, avpkt->size); - // Decode the header only. - ret = !opj_read_header(stream, dec, &image); - - if (ret) { - av_log(avctx, AV_LOG_ERROR, "Error decoding codestream header.\n"); - ret = AVERROR_EXTERNAL; - goto done; - } - - width = image->x1 - image->x0; - height = image->y1 - image->y0; - - ret = ff_set_dimensions(avctx, width, height); - if (ret < 0) - goto done; - - if (avctx->pix_fmt != AV_PIX_FMT_NONE) - if (!libopenjpeg_matches_pix_fmt(image, avctx->pix_fmt)) - avctx->pix_fmt = AV_PIX_FMT_NONE; - - if (avctx->pix_fmt == AV_PIX_FMT_NONE) - avctx->pix_fmt = libopenjpeg_guess_pix_fmt(image); - - if (avctx->pix_fmt == AV_PIX_FMT_NONE) { - av_log(avctx, AV_LOG_ERROR, "Unable to determine pixel format.\n"); - ret = AVERROR_UNKNOWN; - goto done; - } - for (i = 0; i < image->numcomps; i++) - if (image->comps[i].prec > avctx->bits_per_raw_sample) - avctx->bits_per_raw_sample = image->comps[i].prec; - - if ((ret = ff_thread_get_buffer(avctx, picture, 0)) < 0) - goto done; - - ret = !opj_decode(dec, stream, image); - - if (ret) { - av_log(avctx, AV_LOG_ERROR, "Error decoding codestream.\n"); - ret = AVERROR_EXTERNAL; - goto done; - } - - for (i = 0; i < image->numcomps; i++) { - if (!image->comps[i].data) { - av_log(avctx, AV_LOG_ERROR, - "Image component %d contains no data.\n", i); - ret = AVERROR_INVALIDDATA; - goto done; - } - } - - desc = av_pix_fmt_desc_get(avctx->pix_fmt); - pixel_size = desc->comp[0].step; - ispacked = libopenjpeg_ispacked(avctx->pix_fmt); - - switch (pixel_size) { - case 1: - if (ispacked) { - libopenjpeg_copy_to_packed8(picture, image); - } else { - libopenjpeg_copyto8(picture, image); - } - break; - case 2: - if (ispacked) { - libopenjpeg_copy_to_packed8(picture, image); - } else { - libopenjpeg_copyto16(picture, image); - } - break; - case 3: - case 4: - if (ispacked) { - libopenjpeg_copy_to_packed8(picture, image); - } - break; - case 6: - case 8: - if (ispacked) { - libopenjpeg_copy_to_packed16(picture, image); - } - break; - default: - avpriv_report_missing_feature(avctx, "Pixel size %d", pixel_size); - ret = AVERROR_PATCHWELCOME; - goto done; - } - - *got_frame = 1; - picture->pict_type = AV_PICTURE_TYPE_I; - picture->key_frame = 1; - ret = buf_size; - -done: - opj_image_destroy(image); - opj_stream_destroy(stream); - opj_destroy_codec(dec); - return ret; -} - -#define OFFSET(x) offsetof(LibOpenJPEGContext, x) -#define VD AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_DECODING_PARAM - -static const AVOption options[] = { - { "lowqual", "Limit the number of layers used for decoding", - OFFSET(lowqual), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, INT_MAX, VD }, - { NULL }, -}; - -static const AVClass openjpeg_class = { - .class_name = "libopenjpeg", - .item_name = av_default_item_name, - .option = options, - .version = LIBAVUTIL_VERSION_INT, -}; - -const FFCodec ff_libopenjpeg_decoder = { - .p.name = "libopenjpeg", - CODEC_LONG_NAME("OpenJPEG JPEG 2000"), - .p.type = AVMEDIA_TYPE_VIDEO, - .p.id = AV_CODEC_ID_JPEG2000, - .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_FRAME_THREADS, - .p.max_lowres = 31, - .p.priv_class = &openjpeg_class, - .p.wrapper_name = "libopenjpeg", - .caps_internal = FF_CODEC_CAP_NOT_INIT_THREADSAFE, - .priv_data_size = sizeof(LibOpenJPEGContext), - .init = libopenjpeg_decode_init, - FF_CODEC_DECODE_CB(libopenjpeg_decode_frame), -}; From 5666c3b8be25e1bc49589b054ed67baa2da32f98 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Fri, 31 Mar 2023 00:38:20 +0200 Subject: [PATCH 0562/2172] avcodec/j2kenc: Add alpha support Signed-off-by: Michael Niedermayer --- libavcodec/j2kenc.c | 27 +++++++++++++++++---------- 1 file changed, 17 insertions(+), 10 deletions(-) diff --git a/libavcodec/j2kenc.c b/libavcodec/j2kenc.c index 97b0da1c976..b924396d7c0 100644 --- a/libavcodec/j2kenc.c +++ b/libavcodec/j2kenc.c @@ -320,8 +320,8 @@ static int put_siz(Jpeg2000EncoderContext *s) for (i = 0; i < s->ncomponents; i++){ // Ssiz_i XRsiz_i, YRsiz_i bytestream_put_byte(&s->buf, s->cbps[i] - 1); - bytestream_put_byte(&s->buf, i?1<chroma_shift[0]:1); - bytestream_put_byte(&s->buf, i?1<chroma_shift[1]:1); + bytestream_put_byte(&s->buf, (i+1&2)?1<chroma_shift[0]:1); + bytestream_put_byte(&s->buf, (i+1&2)?1<chroma_shift[1]:1); } return 0; } @@ -432,7 +432,7 @@ static void compute_rates(Jpeg2000EncoderContext* s) for (compno = 0; compno < s->ncomponents; compno++) { int tilew = tile->comp[compno].coord[0][1] - tile->comp[compno].coord[0][0]; int tileh = tile->comp[compno].coord[1][1] - tile->comp[compno].coord[1][0]; - int scale = (compno?1 << s->chroma_shift[0]:1) * (compno?1 << s->chroma_shift[1]:1); + int scale = ((compno+1&2)?1 << s->chroma_shift[0]:1) * ((compno+1&2)?1 << s->chroma_shift[1]:1); for (layno = 0; layno < s->nlayers; layno++) { if (s->layer_rates[layno] > 0) { tile->layer_rates[layno] += (double)(tilew * tileh) * s->ncomponents * s->cbps[compno] / @@ -484,7 +484,7 @@ static int init_tiles(Jpeg2000EncoderContext *s) comp->coord[0][1] = comp->coord_o[0][1] = FFMIN((tilex+1)*s->tile_width, s->width); comp->coord[1][0] = comp->coord_o[1][0] = tiley * s->tile_height; comp->coord[1][1] = comp->coord_o[1][1] = FFMIN((tiley+1)*s->tile_height, s->height); - if (compno > 0) + if (compno + 1 & 2) for (i = 0; i < 2; i++) for (j = 0; j < 2; j++) comp->coord[i][j] = comp->coord_o[i][j] = ff_jpeg2000_ceildivpow2(comp->coord[i][j], s->chroma_shift[i]); @@ -493,8 +493,8 @@ static int init_tiles(Jpeg2000EncoderContext *s) codsty, qntsty, s->cbps[compno], - compno?1<chroma_shift[0]:1, - compno?1<chroma_shift[1]:1, + (compno+1&2)?1<chroma_shift[0]:1, + (compno+1&2)?1<chroma_shift[1]:1, s->avctx )) < 0) return ret; @@ -1009,7 +1009,7 @@ static int encode_packets(Jpeg2000EncoderContext *s, Jpeg2000Tile *tile, int til Jpeg2000Component *comp = tile->comp + compno; uint8_t reducedresno = codsty->nreslevels - 1 -reslevelno; // ==> N_L - r Jpeg2000ResLevel *reslevel = comp->reslevel + reslevelno; - int log_subsampling[2] = { compno?s->chroma_shift[0]:0, compno?s->chroma_shift[1]:0}; + int log_subsampling[2] = { (compno+1&2)?s->chroma_shift[0]:0, (compno+1&2)?s->chroma_shift[1]:0}; unsigned prcx, prcy; int trx0, try0; @@ -1070,7 +1070,7 @@ static int encode_packets(Jpeg2000EncoderContext *s, Jpeg2000Tile *tile, int til for (x = tile_coord[0][0]; x < tile_coord[0][1]; x = (x/step_x + 1)*step_x) { for (compno = 0; compno < s->ncomponents; compno++) { Jpeg2000Component *comp = tile->comp + compno; - int log_subsampling[2] = { compno?s->chroma_shift[0]:0, compno?s->chroma_shift[1]:0}; + int log_subsampling[2] = { (compno+1&2)?s->chroma_shift[0]:0, (compno+1&2)?s->chroma_shift[1]:0}; for (reslevelno = 0; reslevelno < codsty->nreslevels; reslevelno++) { unsigned prcx, prcy; @@ -1116,7 +1116,7 @@ static int encode_packets(Jpeg2000EncoderContext *s, Jpeg2000Tile *tile, int til case JPEG2000_PGOD_CPRL: for (compno = 0; compno < s->ncomponents; compno++) { Jpeg2000Component *comp = tile->comp + compno; - int log_subsampling[2] = { compno?s->chroma_shift[0]:0, compno?s->chroma_shift[1]:0}; + int log_subsampling[2] = { (compno+1&2)?s->chroma_shift[0]:0, (compno+1&2)?s->chroma_shift[1]:0}; step_x = 32; step_y = 32; @@ -1763,7 +1763,7 @@ static av_cold int j2kenc_init(AVCodecContext *avctx) s->height = avctx->height; s->ncomponents = desc->nb_components; - for (i = 0; i < 3; i++) { + for (i = 0; i < 4; i++) { s->cbps[i] = desc->comp[i].depth; s->comp_remap[i] = i; //default } @@ -1853,6 +1853,13 @@ const FFCodec ff_jpeg2000_encoder = { AV_PIX_FMT_YUV440P, AV_PIX_FMT_YUV440P10, AV_PIX_FMT_YUV440P12, AV_PIX_FMT_YUV411P, AV_PIX_FMT_YUV410P, + + AV_PIX_FMT_RGBA, AV_PIX_FMT_RGBA64, + AV_PIX_FMT_GBRAP, AV_PIX_FMT_GBRAP10, AV_PIX_FMT_GBRAP12, AV_PIX_FMT_GBRAP16, + AV_PIX_FMT_YUVA420P, AV_PIX_FMT_YUVA420P9, AV_PIX_FMT_YUVA420P10, AV_PIX_FMT_YUVA420P16, + AV_PIX_FMT_YUVA422P, AV_PIX_FMT_YUVA422P9, AV_PIX_FMT_YUVA422P10, AV_PIX_FMT_YUVA422P16, + AV_PIX_FMT_YUVA444P, AV_PIX_FMT_YUVA444P9, AV_PIX_FMT_YUVA444P10, AV_PIX_FMT_YUVA444P16, + AV_PIX_FMT_PAL8, AV_PIX_FMT_NONE }, From c6dedaf491c7cfd44130cc4411b650b5b837a8a1 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Sun, 2 Apr 2023 22:19:53 +0200 Subject: [PATCH 0563/2172] tests: Add more j2k tests to cover a wider range of cases Signed-off-by: Michael Niedermayer --- tests/fate/vcodec.mak | 4 +++- tests/ref/vsynth/vsynth1-jpeg2000-gbrp12 | 4 ++++ tests/ref/vsynth/vsynth1-jpeg2000-yuva444p16 | 4 ++++ tests/ref/vsynth/vsynth2-jpeg2000-gbrp12 | 4 ++++ tests/ref/vsynth/vsynth2-jpeg2000-yuva444p16 | 4 ++++ tests/ref/vsynth/vsynth3-jpeg2000-gbrp12 | 4 ++++ tests/ref/vsynth/vsynth3-jpeg2000-yuva444p16 | 4 ++++ tests/ref/vsynth/vsynth_lena-jpeg2000-gbrp12 | 4 ++++ tests/ref/vsynth/vsynth_lena-jpeg2000-yuva444p16 | 4 ++++ 9 files changed, 35 insertions(+), 1 deletion(-) create mode 100644 tests/ref/vsynth/vsynth1-jpeg2000-gbrp12 create mode 100644 tests/ref/vsynth/vsynth1-jpeg2000-yuva444p16 create mode 100644 tests/ref/vsynth/vsynth2-jpeg2000-gbrp12 create mode 100644 tests/ref/vsynth/vsynth2-jpeg2000-yuva444p16 create mode 100644 tests/ref/vsynth/vsynth3-jpeg2000-gbrp12 create mode 100644 tests/ref/vsynth/vsynth3-jpeg2000-yuva444p16 create mode 100644 tests/ref/vsynth/vsynth_lena-jpeg2000-gbrp12 create mode 100644 tests/ref/vsynth/vsynth_lena-jpeg2000-yuva444p16 diff --git a/tests/fate/vcodec.mak b/tests/fate/vcodec.mak index 1a47fc8bf61..9c3e796547e 100644 --- a/tests/fate/vcodec.mak +++ b/tests/fate/vcodec.mak @@ -219,9 +219,11 @@ FATE_VCODEC_SCALE-$(call ENCDEC, JPEGLS, AVI) += jpegls fate-vsynth%-jpegls: ENCOPTS = -sws_flags neighbor+full_chroma_int fate-vsynth%-jpegls: DECOPTS = -sws_flags area -FATE_VCODEC_SCALE-$(call ENCDEC, JPEG2000, AVI) += jpeg2000 jpeg2000-97 +FATE_VCODEC_SCALE-$(call ENCDEC, JPEG2000, AVI) += jpeg2000 jpeg2000-97 jpeg2000-gbrp12 jpeg2000-yuva444p16 fate-vsynth%-jpeg2000: ENCOPTS = -qscale 7 -strict experimental -pred 1 -pix_fmt rgb24 fate-vsynth%-jpeg2000-97: ENCOPTS = -qscale 7 -strict experimental -pix_fmt rgb24 +fate-vsynth%-jpeg2000-gbrp12: ENCOPTS = -qscale 5 -strict experimental -pred 1 -pix_fmt gbrp12 +fate-vsynth%-jpeg2000-yuva444p16: ENCOPTS = -qscale 8 -strict experimental -pred 1 -pix_fmt yuva444p16 FATE_VCODEC-$(call ENCDEC, LJPEG MJPEG, AVI) += ljpeg fate-vsynth%-ljpeg: ENCOPTS = -strict -1 diff --git a/tests/ref/vsynth/vsynth1-jpeg2000-gbrp12 b/tests/ref/vsynth/vsynth1-jpeg2000-gbrp12 new file mode 100644 index 00000000000..0c6d47778f1 --- /dev/null +++ b/tests/ref/vsynth/vsynth1-jpeg2000-gbrp12 @@ -0,0 +1,4 @@ +78b35a445001d2879386fdad16a2f0be *tests/data/fate/vsynth1-jpeg2000-gbrp12.avi +8163968 tests/data/fate/vsynth1-jpeg2000-gbrp12.avi +e934632ff63a00b4f2c9b3061f9c410e *tests/data/fate/vsynth1-jpeg2000-gbrp12.out.rawvideo +stddev: 3.51 PSNR: 37.21 MAXDIFF: 43 bytes: 7603200/ 7603200 diff --git a/tests/ref/vsynth/vsynth1-jpeg2000-yuva444p16 b/tests/ref/vsynth/vsynth1-jpeg2000-yuva444p16 new file mode 100644 index 00000000000..363ddc4ffaa --- /dev/null +++ b/tests/ref/vsynth/vsynth1-jpeg2000-yuva444p16 @@ -0,0 +1,4 @@ +9261706cfd4dfd8db38fc9bdafe6bef7 *tests/data/fate/vsynth1-jpeg2000-yuva444p16.avi +12433462 tests/data/fate/vsynth1-jpeg2000-yuva444p16.avi +6bc7131cd19dbb59339bb13a6d53b94d *tests/data/fate/vsynth1-jpeg2000-yuva444p16.out.rawvideo +stddev: 12.97 PSNR: 25.87 MAXDIFF: 169 bytes: 7603200/ 7603200 diff --git a/tests/ref/vsynth/vsynth2-jpeg2000-gbrp12 b/tests/ref/vsynth/vsynth2-jpeg2000-gbrp12 new file mode 100644 index 00000000000..fad6af57414 --- /dev/null +++ b/tests/ref/vsynth/vsynth2-jpeg2000-gbrp12 @@ -0,0 +1,4 @@ +3b20090f3d1f8804789c0dfdc68049fb *tests/data/fate/vsynth2-jpeg2000-gbrp12.avi +8484786 tests/data/fate/vsynth2-jpeg2000-gbrp12.avi +44c4232da8e05ce034558ee1c5899e0a *tests/data/fate/vsynth2-jpeg2000-gbrp12.out.rawvideo +stddev: 1.23 PSNR: 46.30 MAXDIFF: 14 bytes: 7603200/ 7603200 diff --git a/tests/ref/vsynth/vsynth2-jpeg2000-yuva444p16 b/tests/ref/vsynth/vsynth2-jpeg2000-yuva444p16 new file mode 100644 index 00000000000..bec08da307e --- /dev/null +++ b/tests/ref/vsynth/vsynth2-jpeg2000-yuva444p16 @@ -0,0 +1,4 @@ +54063ab98e48b2a079b63643fe26e082 *tests/data/fate/vsynth2-jpeg2000-yuva444p16.avi +11489842 tests/data/fate/vsynth2-jpeg2000-yuva444p16.avi +a4232b2959472f88b5310572456fa900 *tests/data/fate/vsynth2-jpeg2000-yuva444p16.out.rawvideo +stddev: 11.69 PSNR: 26.77 MAXDIFF: 188 bytes: 7603200/ 7603200 diff --git a/tests/ref/vsynth/vsynth3-jpeg2000-gbrp12 b/tests/ref/vsynth/vsynth3-jpeg2000-gbrp12 new file mode 100644 index 00000000000..0010dbed583 --- /dev/null +++ b/tests/ref/vsynth/vsynth3-jpeg2000-gbrp12 @@ -0,0 +1,4 @@ +1ca41231325bbacd1dc3b60785ba7fcc *tests/data/fate/vsynth3-jpeg2000-gbrp12.avi +143116 tests/data/fate/vsynth3-jpeg2000-gbrp12.avi +3a84f9e8db1b0f1f5dbf14062eb7975d *tests/data/fate/vsynth3-jpeg2000-gbrp12.out.rawvideo +stddev: 3.83 PSNR: 36.45 MAXDIFF: 42 bytes: 86700/ 86700 diff --git a/tests/ref/vsynth/vsynth3-jpeg2000-yuva444p16 b/tests/ref/vsynth/vsynth3-jpeg2000-yuva444p16 new file mode 100644 index 00000000000..dae44f40bd1 --- /dev/null +++ b/tests/ref/vsynth/vsynth3-jpeg2000-yuva444p16 @@ -0,0 +1,4 @@ +afdff47e9c71d912153e59a56afdf2a9 *tests/data/fate/vsynth3-jpeg2000-yuva444p16.avi +194250 tests/data/fate/vsynth3-jpeg2000-yuva444p16.avi +9e0ef11f8c85206a950a919cb679f129 *tests/data/fate/vsynth3-jpeg2000-yuva444p16.out.rawvideo +stddev: 10.72 PSNR: 27.53 MAXDIFF: 82 bytes: 86700/ 86700 diff --git a/tests/ref/vsynth/vsynth_lena-jpeg2000-gbrp12 b/tests/ref/vsynth/vsynth_lena-jpeg2000-gbrp12 new file mode 100644 index 00000000000..d008d84753c --- /dev/null +++ b/tests/ref/vsynth/vsynth_lena-jpeg2000-gbrp12 @@ -0,0 +1,4 @@ +04c3662db7b6e91640c94877a631a277 *tests/data/fate/vsynth_lena-jpeg2000-gbrp12.avi +8023408 tests/data/fate/vsynth_lena-jpeg2000-gbrp12.avi +c7e9b9e26292975e04046984aa3646cd *tests/data/fate/vsynth_lena-jpeg2000-gbrp12.out.rawvideo +stddev: 0.81 PSNR: 49.93 MAXDIFF: 12 bytes: 7603200/ 7603200 diff --git a/tests/ref/vsynth/vsynth_lena-jpeg2000-yuva444p16 b/tests/ref/vsynth/vsynth_lena-jpeg2000-yuva444p16 new file mode 100644 index 00000000000..d9e856735b2 --- /dev/null +++ b/tests/ref/vsynth/vsynth_lena-jpeg2000-yuva444p16 @@ -0,0 +1,4 @@ +e9c56e128cf980db7c8e965d2afc0ea6 *tests/data/fate/vsynth_lena-jpeg2000-yuva444p16.avi +11109882 tests/data/fate/vsynth_lena-jpeg2000-yuva444p16.avi +3e1a4f9ca46c2dd3fd997c01a0dfb130 *tests/data/fate/vsynth_lena-jpeg2000-yuva444p16.out.rawvideo +stddev: 11.67 PSNR: 26.79 MAXDIFF: 150 bytes: 7603200/ 7603200 From 6941788d24ea350498ecb327e03d625974e55d9f Mon Sep 17 00:00:00 2001 From: Gyan Doshi Date: Sun, 26 Mar 2023 12:40:09 +0530 Subject: [PATCH 0564/2172] avformat/movenc: correct loci parameter handling 3GPP TS 26.244 Table 8.10 specifies that longitude is written before latitude. The MOV demuxer already expects the correct order. So, write them in that order. However, the user supplied string may also be used in MOV mode which requires ISO 6709 format which specifies latitude first. The demuxer also exports the loci value in that format. So parser adjusted as well. --- libavformat/movenc.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/libavformat/movenc.c b/libavformat/movenc.c index 68e7f8222b9..c370922c7d8 100644 --- a/libavformat/movenc.c +++ b/libavformat/movenc.c @@ -4021,13 +4021,13 @@ static int mov_write_loci_tag(AVFormatContext *s, AVIOContext *pb) return 0; ptr = t->value; - longitude = strtod(ptr, &end); + latitude = strtod(ptr, &end); if (end == ptr) { av_log(s, AV_LOG_WARNING, "malformed location metadata\n"); return 0; } ptr = end; - latitude = strtod(ptr, &end); + longitude = strtod(ptr, &end); if (end == ptr) { av_log(s, AV_LOG_WARNING, "malformed location metadata\n"); return 0; @@ -4048,8 +4048,8 @@ static int mov_write_loci_tag(AVFormatContext *s, AVIOContext *pb) avio_wb16(pb, lang); avio_write(pb, place, strlen(place) + 1); avio_w8(pb, 0); /* role of place (0 == shooting location, 1 == real location, 2 == fictional location) */ - avio_wb32(pb, latitude_fix); avio_wb32(pb, longitude_fix); + avio_wb32(pb, latitude_fix); avio_wb32(pb, altitude_fix); avio_write(pb, astronomical_body, strlen(astronomical_body) + 1); avio_w8(pb, 0); /* additional notes, null terminated string */ From 9a245bdf5d7860b8bc5e5c21a105a075925b719a Mon Sep 17 00:00:00 2001 From: Kyle Manning Date: Sun, 2 Apr 2023 16:19:44 -0700 Subject: [PATCH 0565/2172] avcodec/nvenc: fix b-frame DTS behavior with fractional framerates When using fractional framerates (or any fraction with a numerator != 1), DTS values for packets would be calculated incorrectly. Signed-off-by: Kyle Manning Signed-off-by: Timo Rothenpieler --- libavcodec/nvenc.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libavcodec/nvenc.c b/libavcodec/nvenc.c index 9acf3e86974..50a4fa6f69e 100644 --- a/libavcodec/nvenc.c +++ b/libavcodec/nvenc.c @@ -2266,7 +2266,8 @@ static int nvenc_set_timestamp(AVCodecContext *avctx, dts = reorder_queue_dequeue(ctx->reorder_queue, avctx, pkt); if (avctx->codec_descriptor->props & AV_CODEC_PROP_REORDER) { - pkt->dts = dts - FFMAX(ctx->encode_config.frameIntervalP - 1, 0) * FFMAX(avctx->ticks_per_frame, 1); + pkt->dts = dts - + FFMAX(ctx->encode_config.frameIntervalP - 1, 0) * FFMAX(avctx->ticks_per_frame, 1) * FFMAX(avctx->time_base.num, 1); } else { pkt->dts = pkt->pts; } From 4c00aa036e52ea1c65f4ed02ec41bf101b4c1b58 Mon Sep 17 00:00:00 2001 From: James Almer Date: Wed, 22 Mar 2023 09:37:46 -0300 Subject: [PATCH 0566/2172] avcodec/libx264: add a flush callback Signed-off-by: James Almer --- libavcodec/libx264.c | 26 +++++++++++++++++++++++--- 1 file changed, 23 insertions(+), 3 deletions(-) diff --git a/libavcodec/libx264.c b/libavcodec/libx264.c index 92828fabc34..cfdd4222362 100644 --- a/libavcodec/libx264.c +++ b/libavcodec/libx264.c @@ -151,7 +151,7 @@ static int encode_nals(AVCodecContext *ctx, AVPacket *pkt, { X264Context *x4 = ctx->priv_data; uint8_t *p; - uint64_t size = x4->sei_size; + uint64_t size = FFMAX(x4->sei_size, 0); int ret; if (!nnal) @@ -178,8 +178,8 @@ static int encode_nals(AVCodecContext *ctx, AVPacket *pkt, memcpy(p, x4->sei, x4->sei_size); p += x4->sei_size; size -= x4->sei_size; - x4->sei_size = 0; - av_freep(&x4->sei); + /* Keep the value around in case of flush */ + x4->sei_size = -x4->sei_size; } /* x264 guarantees the payloads of the NALs @@ -648,6 +648,24 @@ FF_ENABLE_DEPRECATION_WARNINGS return 0; } +static void X264_flush(AVCodecContext *avctx) +{ + X264Context *x4 = avctx->priv_data; + x264_nal_t *nal; + int nnal, ret; + x264_picture_t pic_out = {0}; + + do { + ret = x264_encoder_encode(x4->enc, &nal, &nnal, NULL, &pic_out); + } while (ret > 0 && x264_encoder_delayed_frames(x4->enc)); + + for (int i = 0; i < x4->nb_reordered_opaque; i++) + opaque_uninit(&x4->reordered_opaque[i]); + + if (x4->sei_size < 0) + x4->sei_size = -x4->sei_size; +} + static av_cold int X264_close(AVCodecContext *avctx) { X264Context *x4 = avctx->priv_data; @@ -1335,12 +1353,14 @@ FFCodec ff_libx264_encoder = { .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_DELAY | AV_CODEC_CAP_OTHER_THREADS | AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE | + AV_CODEC_CAP_ENCODER_FLUSH | AV_CODEC_CAP_ENCODER_RECON_FRAME, .p.priv_class = &x264_class, .p.wrapper_name = "libx264", .priv_data_size = sizeof(X264Context), .init = X264_init, FF_CODEC_ENCODE_CB(X264_frame), + .flush = X264_flush, .close = X264_close, .defaults = x264_defaults, #if X264_BUILD < 153 From 97c95961f0d78368d6318f02aeaeb2da5b8f1443 Mon Sep 17 00:00:00 2001 From: James Almer Date: Mon, 27 Mar 2023 11:19:16 -0300 Subject: [PATCH 0567/2172] avcodec/libfdk-aaceenc: add a flush callback Signed-off-by: James Almer --- libavcodec/libfdk-aacenc.c | 40 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/libavcodec/libfdk-aacenc.c b/libavcodec/libfdk-aacenc.c index 515e235baa0..e08c6a0c6c1 100644 --- a/libavcodec/libfdk-aacenc.c +++ b/libavcodec/libfdk-aacenc.c @@ -134,6 +134,44 @@ static int aac_encode_close(AVCodecContext *avctx) return 0; } +static void aac_encode_flush(AVCodecContext *avctx) +{ + AACContext *s = avctx->priv_data; + AACENC_BufDesc in_buf = { 0 }, out_buf = { 0 }; + AACENC_InArgs in_args = { 0 }; + AACENC_OutArgs out_args; + int64_t pts, duration; + uint8_t dummy_in[1], dummy_out[1]; + int in_buffer_identifiers[] = { IN_AUDIO_DATA, IN_METADATA_SETUP }; + int in_buffer_element_sizes[] = { 2, sizeof(AACENC_MetaData) }; + int in_buffer_sizes[] = { 0, sizeof(s->metaDataSetup) }; + int out_buffer_identifier = OUT_BITSTREAM_DATA; + int out_buffer_size = sizeof(dummy_out), out_buffer_element_size = 1; + void* inBuffer[] = { dummy_in, &s->metaDataSetup }; + void *out_ptr = dummy_out; + AACENC_ERROR err; + + ff_af_queue_remove(&s->afq, s->afq.frame_count, &pts, &duration); + + in_buf.bufs = (void **)inBuffer; + in_buf.numBufs = s->metadata_mode == 0 ? 1 : 2; + in_buf.bufferIdentifiers = in_buffer_identifiers; + in_buf.bufSizes = in_buffer_sizes; + in_buf.bufElSizes = in_buffer_element_sizes; + + out_buf.numBufs = 1; + out_buf.bufs = &out_ptr; + out_buf.bufferIdentifiers = &out_buffer_identifier; + out_buf.bufSizes = &out_buffer_size; + out_buf.bufElSizes = &out_buffer_element_size; + + err = aacEncEncode(s->handle, &in_buf, &out_buf, &in_args, &out_args); + if (err != AACENC_OK) { + av_log(avctx, AV_LOG_ERROR, "Unexpected error while flushing: %s\n", + aac_get_error(err)); + } +} + static av_cold int aac_encode_init(AVCodecContext *avctx) { AACContext *s = avctx->priv_data; @@ -572,11 +610,13 @@ const FFCodec ff_libfdk_aac_encoder = { .p.type = AVMEDIA_TYPE_AUDIO, .p.id = AV_CODEC_ID_AAC, .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_DELAY | + AV_CODEC_CAP_ENCODER_FLUSH | AV_CODEC_CAP_SMALL_LAST_FRAME, .caps_internal = FF_CODEC_CAP_NOT_INIT_THREADSAFE, .priv_data_size = sizeof(AACContext), .init = aac_encode_init, FF_CODEC_ENCODE_CB(aac_encode_frame), + .flush = aac_encode_flush, .close = aac_encode_close, .p.sample_fmts = (const enum AVSampleFormat[]){ AV_SAMPLE_FMT_S16, AV_SAMPLE_FMT_NONE }, From dffb058f3b1f9a9b681d7e923eee77c170c5bf54 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Thu, 30 Mar 2023 11:20:48 +0200 Subject: [PATCH 0568/2172] lavf: fall back to a more meaningful log instance name An uninitialized AVFormatContext instance with neither iformat nor oformat set will currently log as 'NULL', which is confusing and unhelpful. Print 'AVFormatContext' instead, which provides more information. This happens e.g. if choosing an output format fails in avformat_alloc_output_context2(). E.g. with the following commandline: ffmpeg -i -f foobar -y /dev/null before: [NULL @ 0x5580377834c0] Requested output format 'foobar' is not a suitable output format after: [AVFormatContext @ 0x55fa15bb34c0] Requested output format 'foobar' is not a suitable output format --- libavformat/options.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavformat/options.c b/libavformat/options.c index 22ad523b2dc..e4a3aceed0a 100644 --- a/libavformat/options.c +++ b/libavformat/options.c @@ -44,7 +44,7 @@ static const char* format_to_name(void* ptr) AVFormatContext* fc = (AVFormatContext*) ptr; if(fc->iformat) return fc->iformat->name; else if(fc->oformat) return fc->oformat->name; - else return "NULL"; + else return fc->av_class->class_name; } static void *format_child_next(void *obj, void *prev) From 1d3f7178aee8a4aee8fcea8ba5d03db22e18ba20 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Thu, 30 Mar 2023 11:23:34 +0200 Subject: [PATCH 0569/2172] lavf/mux: clarify log messages when choosing oformat fails Current log messages talk about 'suitable' output formats. This is confusing, because it suggests that some formats are suitable, while others are not, which is not the case. Also, suggest possible user actions when format cannot be guessed from a filename. --- libavformat/mux.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/libavformat/mux.c b/libavformat/mux.c index 0bc9b6b87dd..415bd3948f5 100644 --- a/libavformat/mux.c +++ b/libavformat/mux.c @@ -102,7 +102,7 @@ int avformat_alloc_output_context2(AVFormatContext **avctx, const AVOutputFormat if (format) { oformat = av_guess_format(format, NULL, NULL); if (!oformat) { - av_log(s, AV_LOG_ERROR, "Requested output format '%s' is not a suitable output format\n", format); + av_log(s, AV_LOG_ERROR, "Requested output format '%s' is not known.\n", format); ret = AVERROR(EINVAL); goto error; } @@ -110,8 +110,10 @@ int avformat_alloc_output_context2(AVFormatContext **avctx, const AVOutputFormat oformat = av_guess_format(NULL, filename, NULL); if (!oformat) { ret = AVERROR(EINVAL); - av_log(s, AV_LOG_ERROR, "Unable to find a suitable output format for '%s'\n", - filename); + av_log(s, AV_LOG_ERROR, + "Unable to choose an output format for '%s'; " + "use a standard extension for the filename or specify " + "the format manually.\n", filename); goto error; } } From bf6df790c2fe37019c08b60632814e5f27eb86c2 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Fri, 31 Mar 2023 10:22:28 +0200 Subject: [PATCH 0570/2172] doc/ffmpeg: refine program title It is a media converter, not just a video converter. --- doc/ffmpeg.texi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/ffmpeg.texi b/doc/ffmpeg.texi index 630971d90b9..85ce4369bdd 100644 --- a/doc/ffmpeg.texi +++ b/doc/ffmpeg.texi @@ -2584,7 +2584,7 @@ ffmpeg-devices(1), ffmpeg-protocols(1), ffmpeg-filters(1) @ignore @setfilename ffmpeg -@settitle ffmpeg video converter +@settitle ffmpeg media converter @end ignore From 2244722f1f3c3a2d0ea02c07631e73bcb0bbba81 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Fri, 31 Mar 2023 10:22:28 +0200 Subject: [PATCH 0571/2172] doc/ffmpeg: rewrite the introductory paragraph This is not the place to boast about high-quality polyphase filters - the most important feature of the program is its universality. --- doc/ffmpeg.texi | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/doc/ffmpeg.texi b/doc/ffmpeg.texi index 85ce4369bdd..d433d60ce9f 100644 --- a/doc/ffmpeg.texi +++ b/doc/ffmpeg.texi @@ -17,9 +17,9 @@ ffmpeg [@var{global_options}] @{[@var{input_file_options}] -i @file{input_url}@} @chapter Description @c man begin DESCRIPTION -@command{ffmpeg} is a very fast video and audio converter that can also grab from -a live audio/video source. It can also convert between arbitrary sample -rates and resize video on the fly with a high quality polyphase filter. +@command{ffmpeg} is a universal media converter. It can read a wide variety of +inputs - including live grabbing/recording devices - filter, and transcode them +into a plethora of output formats. @command{ffmpeg} reads from an arbitrary number of input "files" (which can be regular files, pipes, network streams, grabbing devices, etc.), specified by the From 44513156e3724264f35ace8a8b5ecc226013f06e Mon Sep 17 00:00:00 2001 From: James Almer Date: Sun, 12 Mar 2023 15:02:06 -0300 Subject: [PATCH 0572/2172] avformat/matroskadec: support parsing more than one BlockMore element Signed-off-by: James Almer --- libavformat/matroskadec.c | 62 ++++++++++++++++++++++++++------------- 1 file changed, 41 insertions(+), 21 deletions(-) diff --git a/libavformat/matroskadec.c b/libavformat/matroskadec.c index 3a888e3ada9..b7f9870f3d8 100644 --- a/libavformat/matroskadec.c +++ b/libavformat/matroskadec.c @@ -349,13 +349,17 @@ typedef struct MatroskaLevel { uint64_t length; } MatroskaLevel; +typedef struct MatroskaBlockMore { + uint64_t additional_id; + EbmlBin additional; +} MatroskaBlockMore; + typedef struct MatroskaBlock { uint64_t duration; CountedElement reference; uint64_t non_simple; EbmlBin bin; - uint64_t additional_id; - EbmlBin additional; + EbmlList blockmore; int64_t discard_padding; } MatroskaBlock; @@ -759,13 +763,13 @@ static EbmlSyntax matroska_segments[] = { }; static EbmlSyntax matroska_blockmore[] = { - { MATROSKA_ID_BLOCKADDID, EBML_UINT, 0, 0, offsetof(MatroskaBlock,additional_id), { .u = 1 } }, - { MATROSKA_ID_BLOCKADDITIONAL, EBML_BIN, 0, 0, offsetof(MatroskaBlock,additional) }, + { MATROSKA_ID_BLOCKADDID, EBML_UINT, 0, 0, offsetof(MatroskaBlockMore,additional_id), { .u = 1 } }, + { MATROSKA_ID_BLOCKADDITIONAL, EBML_BIN, 0, 0, offsetof(MatroskaBlockMore,additional) }, CHILD_OF(matroska_blockadditions) }; static EbmlSyntax matroska_blockadditions[] = { - { MATROSKA_ID_BLOCKMORE, EBML_NEST, 0, 0, 0, {.n = matroska_blockmore} }, + { MATROSKA_ID_BLOCKMORE, EBML_NEST, 0, sizeof(MatroskaBlockMore), offsetof(MatroskaBlock, blockmore), { .n = matroska_blockmore } }, CHILD_OF(matroska_blockgroup) }; @@ -3610,12 +3614,28 @@ static int matroska_parse_webvtt(MatroskaDemuxContext *matroska, return 0; } +static int matroska_parse_block_additional(MatroskaDemuxContext *matroska, + AVPacket *pkt, + const uint8_t *data, int size, uint64_t id) +{ + uint8_t *side_data = av_packet_new_side_data(pkt, + AV_PKT_DATA_MATROSKA_BLOCKADDITIONAL, + size + (size_t)8); + if (!side_data) + return AVERROR(ENOMEM); + + AV_WB64(side_data, id); + memcpy(side_data + 8, data, size); + + return 0; +} + static int matroska_parse_frame(MatroskaDemuxContext *matroska, MatroskaTrack *track, AVStream *st, AVBufferRef *buf, uint8_t *data, int pkt_size, uint64_t timecode, uint64_t lace_duration, int64_t pos, int is_keyframe, - uint8_t *additional, uint64_t additional_id, int additional_size, + MatroskaBlockMore *blockmore, int nb_blockmore, int64_t discard_padding) { uint8_t *pkt_data = data; @@ -3647,7 +3667,7 @@ static int matroska_parse_frame(MatroskaDemuxContext *matroska, buf = NULL; } - if (!pkt_size && !additional_size) + if (!pkt_size && !nb_blockmore) goto no_output; if (!buf) @@ -3666,16 +3686,18 @@ static int matroska_parse_frame(MatroskaDemuxContext *matroska, pkt->flags = is_keyframe; pkt->stream_index = st->index; - if (additional_size > 0) { - uint8_t *side_data = av_packet_new_side_data(pkt, - AV_PKT_DATA_MATROSKA_BLOCKADDITIONAL, - additional_size + 8); - if (!side_data) { + for (int i = 0; i < nb_blockmore; i++) { + MatroskaBlockMore *more = &blockmore[i]; + + if (!more->additional.size) + continue; + + res = matroska_parse_block_additional(matroska, pkt, more->additional.data, + more->additional.size, more->additional_id); + if (res < 0) { av_packet_unref(pkt); - return AVERROR(ENOMEM); + return res; } - AV_WB64(side_data, additional_id); - memcpy(side_data + 8, additional, additional_size); } if (discard_padding) { @@ -3721,7 +3743,7 @@ static int matroska_parse_frame(MatroskaDemuxContext *matroska, static int matroska_parse_block(MatroskaDemuxContext *matroska, AVBufferRef *buf, uint8_t *data, int size, int64_t pos, uint64_t cluster_time, uint64_t block_duration, int is_keyframe, - uint8_t *additional, uint64_t additional_id, int additional_size, + MatroskaBlockMore *blockmore, int nb_blockmore, int64_t cluster_pos, int64_t discard_padding) { uint64_t timecode = AV_NOPTS_VALUE; @@ -3856,7 +3878,7 @@ static int matroska_parse_block(MatroskaDemuxContext *matroska, AVBufferRef *buf res = matroska_parse_frame(matroska, track, st, buf, out_data, out_size, timecode, lace_duration, pos, !n ? is_keyframe : 0, - additional, additional_id, additional_size, + blockmore, nb_blockmore, discard_padding); if (res) return res; @@ -3897,14 +3919,12 @@ static int matroska_parse_cluster(MatroskaDemuxContext *matroska) if (res >= 0 && block->bin.size > 0) { int is_keyframe = block->non_simple ? block->reference.count == 0 : -1; - uint8_t* additional = block->additional.size > 0 ? - block->additional.data : NULL; res = matroska_parse_block(matroska, block->bin.buf, block->bin.data, block->bin.size, block->bin.pos, cluster->timecode, block->duration, - is_keyframe, additional, block->additional_id, - block->additional.size, cluster->pos, + is_keyframe, block->blockmore.elem, + block->blockmore.nb_elem, cluster->pos, block->discard_padding); } From 6def862559ec8986a80e8036236ab5a87bad54e1 Mon Sep 17 00:00:00 2001 From: James Almer Date: Sun, 19 Mar 2023 11:51:24 -0300 Subject: [PATCH 0573/2172] avformat/matroskadec: set the default value for BlockAddIDType Signed-off-by: James Almer --- libavformat/matroska.h | 4 ++++ libavformat/matroskadec.c | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/libavformat/matroska.h b/libavformat/matroska.h index 45077ed33f9..de63cdc7ae9 100644 --- a/libavformat/matroska.h +++ b/libavformat/matroska.h @@ -358,6 +358,10 @@ typedef enum { MATROSKA_VIDEO_PROJECTION_TYPE_MESH = 3, } MatroskaVideoProjectionType; +typedef enum { + MATROSKA_BLOCK_ADD_ID_TYPE_DEFAULT = 0, +} MatroskaBlockAddIDType; + /* * Matroska Codec IDs, strings */ diff --git a/libavformat/matroskadec.c b/libavformat/matroskadec.c index b7f9870f3d8..a19b97043c8 100644 --- a/libavformat/matroskadec.c +++ b/libavformat/matroskadec.c @@ -591,7 +591,7 @@ static EbmlSyntax matroska_track_operation[] = { 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_BLKADDIDTYPE, EBML_UINT, 0, 0, offsetof(MatroskaBlockAdditionMapping, type), { .u = MATROSKA_BLOCK_ADD_ID_TYPE_DEFAULT } }, { MATROSKA_ID_BLKADDIDEXTRADATA, EBML_BIN, 0, 0, offsetof(MatroskaBlockAdditionMapping, extradata) }, CHILD_OF(matroska_track) }; From c73cf41f1e839b4d1239ab144f0f18876225a914 Mon Sep 17 00:00:00 2001 From: James Almer Date: Sun, 12 Mar 2023 15:48:10 -0300 Subject: [PATCH 0574/2172] avformat/matroskadec: export Dynamic HDR10+ packet side data Signed-off-by: James Almer --- libavformat/matroska.h | 3 ++ libavformat/matroskadec.c | 80 +++++++++++++++++++++++++++++++++++---- 2 files changed, 76 insertions(+), 7 deletions(-) diff --git a/libavformat/matroska.h b/libavformat/matroska.h index de63cdc7ae9..b39517709c2 100644 --- a/libavformat/matroska.h +++ b/libavformat/matroska.h @@ -360,8 +360,11 @@ typedef enum { typedef enum { MATROSKA_BLOCK_ADD_ID_TYPE_DEFAULT = 0, + MATROSKA_BLOCK_ADD_ID_TYPE_ITU_T_T35 = 4, } MatroskaBlockAddIDType; +#define MATROSKA_BLOCK_ADD_ID_ITU_T_T35 4 + /* * Matroska Codec IDs, strings */ diff --git a/libavformat/matroskadec.c b/libavformat/matroskadec.c index a19b97043c8..32907f413a1 100644 --- a/libavformat/matroskadec.c +++ b/libavformat/matroskadec.c @@ -40,6 +40,7 @@ #include "libavutil/dict.h" #include "libavutil/dict_internal.h" #include "libavutil/display.h" +#include "libavutil/hdr_dynamic_metadata.h" #include "libavutil/intfloat.h" #include "libavutil/intreadwrite.h" #include "libavutil/lzo.h" @@ -284,6 +285,7 @@ typedef struct MatroskaTrack { int needs_decoding; uint64_t max_block_additional_id; EbmlList block_addition_mappings; + int blockaddid_itu_t_t35; uint32_t palette[AVPALETTE_COUNT]; int has_palette; @@ -423,6 +425,8 @@ typedef struct MatroskaDemuxContext { MatroskaCluster current_cluster; + int is_webm; + /* WebM DASH Manifest live flag */ int is_live; @@ -2378,7 +2382,7 @@ static int mkv_parse_dvcc_dvvc(AVFormatContext *s, AVStream *st, const MatroskaT 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) +static int mkv_parse_block_addition_mappings(AVFormatContext *s, AVStream *st, MatroskaTrack *track) { const EbmlList *mappings_list = &track->block_addition_mappings; MatroskaBlockAdditionMapping *mappings = mappings_list->elem; @@ -2388,6 +2392,18 @@ static int mkv_parse_block_addition_mappings(AVFormatContext *s, AVStream *st, c MatroskaBlockAdditionMapping *mapping = &mappings[i]; switch (mapping->type) { + case MATROSKA_BLOCK_ADD_ID_TYPE_ITU_T_T35: + if (mapping->value != MATROSKA_BLOCK_ADD_ID_ITU_T_T35) { + int strict = s->strict_std_compliance >= FF_COMPLIANCE_STRICT; + av_log(s, strict ? AV_LOG_ERROR : AV_LOG_WARNING, + "Invalid Block Addition Value 0x%"PRIx64" for Block Addition Mapping Type " + "\"ITU T.35 metadata\"\n", mapping->value); + if (!strict) + break; + return AVERROR_INVALIDDATA; + } + track->blockaddid_itu_t_t35 = 1; + break; case MKBETAG('d','v','c','C'): case MKBETAG('d','v','v','C'): if ((ret = mkv_parse_dvcc_dvvc(s, st, track, &mapping->extradata)) < 0) @@ -2814,10 +2830,12 @@ static int matroska_parse_tracks(AVFormatContext *s) AV_WL16(extradata, 0x410); } else if (codec_id == AV_CODEC_ID_PRORES && track->codec_priv.size == 4) { fourcc = AV_RL32(track->codec_priv.data); - } else if (codec_id == AV_CODEC_ID_VP9 && track->codec_priv.size) { + } else if (codec_id == AV_CODEC_ID_VP9) { /* we don't need any value stored in CodecPrivate. make sure that it's not exported as extradata. */ track->codec_priv.size = 0; + /* Assume BlockAddID 4 is ITU-T T.35 metadata if WebM */ + track->blockaddid_itu_t_t35 = matroska->is_webm; } else if (codec_id == AV_CODEC_ID_ARIB_CAPTION && track->codec_priv.size == 3) { int component_tag = track->codec_priv.data[0]; int data_component_id = AV_RB16(track->codec_priv.data + 1); @@ -3081,6 +3099,8 @@ static int matroska_read_header(AVFormatContext *s) return AVERROR_INVALIDDATA; } } + matroska->is_webm = !strcmp(ebml.doctype, "webm"); + ebml_free(ebml_syntax, &ebml); matroska->pkt = si->parse_pkt; @@ -3615,12 +3635,58 @@ static int matroska_parse_webvtt(MatroskaDemuxContext *matroska, } static int matroska_parse_block_additional(MatroskaDemuxContext *matroska, - AVPacket *pkt, + MatroskaTrack *track, AVPacket *pkt, const uint8_t *data, int size, uint64_t id) { - uint8_t *side_data = av_packet_new_side_data(pkt, - AV_PKT_DATA_MATROSKA_BLOCKADDITIONAL, - size + (size_t)8); + uint8_t *side_data; + int res; + + switch (id) { + case 4: { + GetByteContext bc; + int country_code, provider_code; + int provider_oriented_code, application_identifier; + size_t hdrplus_size; + AVDynamicHDRPlus *hdrplus; + + if (!track->blockaddid_itu_t_t35 || size < 6) + break; //ignore + + bytestream2_init(&bc, data, size); + + /* ITU-T T.35 metadata */ + country_code = bytestream2_get_byteu(&bc); + provider_code = bytestream2_get_be16u(&bc); + + if (country_code != 0xB5 || provider_code != 0x3C) + break; // ignore + + provider_oriented_code = bytestream2_get_be16u(&bc); + application_identifier = bytestream2_get_byteu(&bc); + + if (provider_oriented_code != 1 || application_identifier != 4) + break; // ignore + + hdrplus = av_dynamic_hdr_plus_alloc(&hdrplus_size); + if (!hdrplus) + return AVERROR(ENOMEM); + + if ((res = av_dynamic_hdr_plus_from_t35(hdrplus, bc.buffer, + bytestream2_get_bytes_left(&bc))) < 0 || + (res = av_packet_add_side_data(pkt, AV_PKT_DATA_DYNAMIC_HDR10_PLUS, + (uint8_t *)hdrplus, hdrplus_size)) < 0) { + av_free(hdrplus); + return res; + } + + return 0; + } + default: + break; + } + + side_data = av_packet_new_side_data(pkt, AV_PKT_DATA_MATROSKA_BLOCKADDITIONAL, + size + (size_t)8); if (!side_data) return AVERROR(ENOMEM); @@ -3692,7 +3758,7 @@ static int matroska_parse_frame(MatroskaDemuxContext *matroska, if (!more->additional.size) continue; - res = matroska_parse_block_additional(matroska, pkt, more->additional.data, + res = matroska_parse_block_additional(matroska, track, pkt, more->additional.data, more->additional.size, more->additional_id); if (res < 0) { av_packet_unref(pkt); From 00fde8063a0aa8c663ba628cb054a204bfca4aa4 Mon Sep 17 00:00:00 2001 From: James Almer Date: Sun, 12 Mar 2023 16:23:56 -0300 Subject: [PATCH 0575/2172] avformat/matroska: add a few more Block Addition ID Type enum values Signed-off-by: James Almer --- libavformat/matroska.h | 4 ++++ libavformat/matroskadec.c | 6 +++--- libavformat/matroskaenc.c | 6 +++--- 3 files changed, 10 insertions(+), 6 deletions(-) diff --git a/libavformat/matroska.h b/libavformat/matroska.h index b39517709c2..ead7c085b9a 100644 --- a/libavformat/matroska.h +++ b/libavformat/matroska.h @@ -360,9 +360,13 @@ typedef enum { typedef enum { MATROSKA_BLOCK_ADD_ID_TYPE_DEFAULT = 0, + MATROSKA_BLOCK_ADD_ID_TYPE_OPAQUE = 1, MATROSKA_BLOCK_ADD_ID_TYPE_ITU_T_T35 = 4, + MATROSKA_BLOCK_ADD_ID_TYPE_DVCC = 0x64766343, // MKBETAG('d','v','c','C') + MATROSKA_BLOCK_ADD_ID_TYPE_DVVC = 0x64767643, // MKBETAG('d','v','v','C') } MatroskaBlockAddIDType; +#define MATROSKA_BLOCK_ADD_ID_OPAQUE 1 #define MATROSKA_BLOCK_ADD_ID_ITU_T_T35 4 /* diff --git a/libavformat/matroskadec.c b/libavformat/matroskadec.c index 32907f413a1..3c7c2b7c706 100644 --- a/libavformat/matroskadec.c +++ b/libavformat/matroskadec.c @@ -767,7 +767,7 @@ static EbmlSyntax matroska_segments[] = { }; static EbmlSyntax matroska_blockmore[] = { - { MATROSKA_ID_BLOCKADDID, EBML_UINT, 0, 0, offsetof(MatroskaBlockMore,additional_id), { .u = 1 } }, + { MATROSKA_ID_BLOCKADDID, EBML_UINT, 0, 0, offsetof(MatroskaBlockMore,additional_id), { .u = MATROSKA_BLOCK_ADD_ID_OPAQUE } }, { MATROSKA_ID_BLOCKADDITIONAL, EBML_BIN, 0, 0, offsetof(MatroskaBlockMore,additional) }, CHILD_OF(matroska_blockadditions) }; @@ -2404,8 +2404,8 @@ static int mkv_parse_block_addition_mappings(AVFormatContext *s, AVStream *st, M } track->blockaddid_itu_t_t35 = 1; break; - case MKBETAG('d','v','c','C'): - case MKBETAG('d','v','v','C'): + case MATROSKA_BLOCK_ADD_ID_TYPE_DVCC: + case MATROSKA_BLOCK_ADD_ID_TYPE_DVVC: if ((ret = mkv_parse_dvcc_dvvc(s, st, track, &mapping->extradata)) < 0) return ret; diff --git a/libavformat/matroskaenc.c b/libavformat/matroskaenc.c index 954b7d828f2..6b24d26d596 100644 --- a/libavformat/matroskaenc.c +++ b/libavformat/matroskaenc.c @@ -1612,9 +1612,9 @@ static void mkv_write_dovi(AVFormatContext *s, AVIOContext *pb, AVStream *st) + (2 + 1 + 4) + (2 + 1 + ISOM_DVCC_DVVC_SIZE); if (dovi->dv_profile > 7) { - type = MKBETAG('d', 'v', 'v', 'C'); + type = MATROSKA_BLOCK_ADD_ID_TYPE_DVVC; } else { - type = MKBETAG('d', 'v', 'c', 'C'); + type = MATROSKA_BLOCK_ADD_ID_TYPE_DVCC; } ff_isom_put_dvcc_dvvc(s, buf, dovi); @@ -2657,7 +2657,7 @@ static int mkv_write_block(void *logctx, MatroskaMuxContext *mkv, &side_data_size); if (side_data && side_data_size >= 8 && // Only the Codec-specific BlockMore (id == 1) is currently supported. - (additional_id = AV_RB64(side_data)) == 1) { + (additional_id = AV_RB64(side_data)) == MATROSKA_BLOCK_ADD_ID_TYPE_OPAQUE) { ebml_writer_open_master(&writer, MATROSKA_ID_BLOCKADDITIONS); ebml_writer_open_master(&writer, MATROSKA_ID_BLOCKMORE); /* Until dbc50f8a our demuxer used a wrong default value From 1c2a1e07500017c873a318fe2f49011f35c1f534 Mon Sep 17 00:00:00 2001 From: James Almer Date: Sun, 19 Mar 2023 10:52:47 -0300 Subject: [PATCH 0576/2172] avformat/matroskaenc: write a MaxBlockAdditionID element A non zero value is mandatory for Matroska if the track has blocks with BlockAdditions. Signed-off-by: James Almer --- libavformat/matroskaenc.c | 35 +++++++++++++-- tests/ref/fate/aac-autobsf-adtstoasc | 4 +- tests/ref/fate/matroska-avoid-negative-ts | 4 +- tests/ref/fate/matroska-dovi-write-config7 | 4 +- tests/ref/fate/matroska-dovi-write-config8 | 4 +- tests/ref/fate/matroska-dvbsub-remux | 4 +- tests/ref/fate/matroska-encoding-delay | 14 +++--- tests/ref/fate/matroska-flac-extradata-update | 4 +- tests/ref/fate/matroska-h264-remux | 4 +- .../fate/matroska-mastering-display-metadata | 4 +- tests/ref/fate/matroska-move-cues-to-front | 4 +- tests/ref/fate/matroska-mpegts-remux | 4 +- tests/ref/fate/matroska-ms-mode | 4 +- tests/ref/fate/matroska-ogg-opus-remux | 10 ++--- tests/ref/fate/matroska-opus-remux | 10 ++--- tests/ref/fate/matroska-pgs-remux | 4 +- tests/ref/fate/matroska-pgs-remux-durations | 4 +- tests/ref/fate/matroska-qt-mode | 4 +- tests/ref/fate/matroska-spherical-mono-remux | 4 +- tests/ref/fate/matroska-vp8-alpha-remux | 4 +- tests/ref/fate/matroska-zero-length-block | 4 +- tests/ref/fate/rgb24-mkv | 4 +- tests/ref/fate/shortest-sub | 4 +- tests/ref/lavf-fate/av1.mkv | 4 +- tests/ref/lavf/mka | 4 +- tests/ref/lavf/mkv | 4 +- tests/ref/lavf/mkv_attachment | 4 +- tests/ref/seek/lavf-mkv | 44 +++++++++---------- 28 files changed, 116 insertions(+), 89 deletions(-) diff --git a/libavformat/matroskaenc.c b/libavformat/matroskaenc.c index 6b24d26d596..3b0998ecc88 100644 --- a/libavformat/matroskaenc.c +++ b/libavformat/matroskaenc.c @@ -188,6 +188,8 @@ typedef struct mkv_track { int64_t last_timestamp; int64_t duration; int64_t duration_offset; + uint64_t max_blockaddid; + int64_t blockadditionmapping_offset; int codecpriv_offset; unsigned codecpriv_size; ///< size reserved for CodecPrivate excluding header+length field int64_t ts_offset; @@ -1597,12 +1599,21 @@ static int mkv_write_stereo_mode(AVFormatContext *s, EbmlWriter *writer, return 0; } -static void mkv_write_dovi(AVFormatContext *s, AVIOContext *pb, AVStream *st) +static void mkv_write_blockadditionmapping(AVFormatContext *s, MatroskaMuxContext *mkv, + AVIOContext *pb, mkv_track *track, AVStream *st) { #if CONFIG_MATROSKA_MUXER AVDOVIDecoderConfigurationRecord *dovi = (AVDOVIDecoderConfigurationRecord *) av_stream_get_side_data(st, AV_PKT_DATA_DOVI_CONF, NULL); + if (IS_SEEKABLE(s->pb, mkv)) { + track->blockadditionmapping_offset = avio_tell(pb); + // We can't know at this point if there will be a block with BlockAdditions, so + // we either write the default value here, or a void element. Either of them will + // be overwritten when finishing the track. + put_ebml_uint(mkv->track.bc, MATROSKA_ID_TRACKMAXBLKADDID, 0); + } + if (dovi && dovi->dv_profile <= 10) { ebml_master mapping; uint8_t buf[ISOM_DVCC_DVVC_SIZE]; @@ -1846,9 +1857,6 @@ static int mkv_write_track(AVFormatContext *s, MatroskaMuxContext *mkv, if (ret < 0) return ret; - if (!IS_WEBM(mkv)) - mkv_write_dovi(s, pb, st); - break; case AVMEDIA_TYPE_AUDIO: @@ -1924,6 +1932,9 @@ static int mkv_write_track(AVFormatContext *s, MatroskaMuxContext *mkv, return AVERROR(EINVAL); } + if (!IS_WEBM(mkv)) + mkv_write_blockadditionmapping(s, mkv, pb, track, st); + if (!IS_WEBM(mkv) || par->codec_id != AV_CODEC_ID_WEBVTT) { uint8_t *codecpriv; int codecpriv_size, max_payload_size; @@ -2667,6 +2678,7 @@ static int mkv_write_block(void *logctx, MatroskaMuxContext *mkv, side_data + 8, side_data_size - 8); ebml_writer_close_master(&writer); ebml_writer_close_master(&writer); + track->max_blockaddid = additional_id; } if (!force_blockgroup && writer.nb_elements == 2) { @@ -3070,6 +3082,21 @@ static int mkv_write_trailer(AVFormatContext *s) if (mkv->track.bc) { // write Tracks master + if (!IS_WEBM(mkv)) + for (unsigned i = 0; i < s->nb_streams; i++) { + const mkv_track *track = &mkv->tracks[i]; + + if (!track->max_blockaddid) + continue; + + // We reserved a single byte to write this value. + av_assert0(track->max_blockaddid <= 0xFF); + + avio_seek(mkv->track.bc, track->blockadditionmapping_offset, SEEK_SET); + + put_ebml_uint(mkv->track.bc, MATROSKA_ID_TRACKMAXBLKADDID, track->max_blockaddid); + } + avio_seek(pb, mkv->track.pos, SEEK_SET); ret = end_ebml_master_crc32(pb, &mkv->track.bc, mkv, MATROSKA_ID_TRACKS, 0, 0, 0); diff --git a/tests/ref/fate/aac-autobsf-adtstoasc b/tests/ref/fate/aac-autobsf-adtstoasc index 57bfcae18bf..76125083b6e 100644 --- a/tests/ref/fate/aac-autobsf-adtstoasc +++ b/tests/ref/fate/aac-autobsf-adtstoasc @@ -1,5 +1,5 @@ -4342e4f3f93b16514bda511b3b7fd93a *tests/data/fate/aac-autobsf-adtstoasc.matroska -6642 tests/data/fate/aac-autobsf-adtstoasc.matroska +3d4465a7ea2cfba31af737e288c892fe *tests/data/fate/aac-autobsf-adtstoasc.matroska +6646 tests/data/fate/aac-autobsf-adtstoasc.matroska #extradata 0: 2, 0x0030001c #tb 0: 1/1000 #media_type 0: audio diff --git a/tests/ref/fate/matroska-avoid-negative-ts b/tests/ref/fate/matroska-avoid-negative-ts index 129ea1be663..73616cbc5a4 100644 --- a/tests/ref/fate/matroska-avoid-negative-ts +++ b/tests/ref/fate/matroska-avoid-negative-ts @@ -1,5 +1,5 @@ -fbe66be73d379073e0705891f290a6b2 *tests/data/fate/matroska-avoid-negative-ts.matroska -973055 tests/data/fate/matroska-avoid-negative-ts.matroska +ff83530bf89f9ab1df0d181bb848c475 *tests/data/fate/matroska-avoid-negative-ts.matroska +973063 tests/data/fate/matroska-avoid-negative-ts.matroska #extradata 0: 22, 0x2885037c #tb 0: 1/1000 #media_type 0: video diff --git a/tests/ref/fate/matroska-dovi-write-config7 b/tests/ref/fate/matroska-dovi-write-config7 index 9207b14b5c3..8b40848f4a1 100644 --- a/tests/ref/fate/matroska-dovi-write-config7 +++ b/tests/ref/fate/matroska-dovi-write-config7 @@ -1,5 +1,5 @@ -d23b8b0d0613a82ba36fdc27acf3ef5d *tests/data/fate/matroska-dovi-write-config7.matroska -72672 tests/data/fate/matroska-dovi-write-config7.matroska +b4db571fe6304f159a0383a38c9c0cee *tests/data/fate/matroska-dovi-write-config7.matroska +72680 tests/data/fate/matroska-dovi-write-config7.matroska #extradata 0: 116, 0x2b8d1669 #extradata 1: 116, 0x2b8d1669 #tb 0: 1/1000 diff --git a/tests/ref/fate/matroska-dovi-write-config8 b/tests/ref/fate/matroska-dovi-write-config8 index 5feb7b80652..c36d3a8a07e 100644 --- a/tests/ref/fate/matroska-dovi-write-config8 +++ b/tests/ref/fate/matroska-dovi-write-config8 @@ -1,5 +1,5 @@ -0047ca43aa8ab2948752e367f184dc1f *tests/data/fate/matroska-dovi-write-config8.matroska -3600576 tests/data/fate/matroska-dovi-write-config8.matroska +8c77c1d18ee58a8923c411d3ba006a46 *tests/data/fate/matroska-dovi-write-config8.matroska +3600584 tests/data/fate/matroska-dovi-write-config8.matroska #extradata 0: 551, 0xa18acf66 #extradata 1: 2, 0x00340022 #tb 0: 1/1000 diff --git a/tests/ref/fate/matroska-dvbsub-remux b/tests/ref/fate/matroska-dvbsub-remux index b7346b8f55c..03341d96681 100644 --- a/tests/ref/fate/matroska-dvbsub-remux +++ b/tests/ref/fate/matroska-dvbsub-remux @@ -1,5 +1,5 @@ -77d210dc36d7a01988d159b3c902524c *tests/data/fate/matroska-dvbsub-remux.matroska -39010 tests/data/fate/matroska-dvbsub-remux.matroska +5d1591e9abd7e1373d43bc776572aaf7 *tests/data/fate/matroska-dvbsub-remux.matroska +39018 tests/data/fate/matroska-dvbsub-remux.matroska #extradata 0: 5, 0x00bb0064 #extradata 1: 5, 0x00bb0064 #tb 0: 1/1000 diff --git a/tests/ref/fate/matroska-encoding-delay b/tests/ref/fate/matroska-encoding-delay index e6cf4790f52..401de4facf3 100644 --- a/tests/ref/fate/matroska-encoding-delay +++ b/tests/ref/fate/matroska-encoding-delay @@ -1,5 +1,5 @@ -b933b7b94de55ae029369312d48d8649 *tests/data/fate/matroska-encoding-delay.matroska -961221 tests/data/fate/matroska-encoding-delay.matroska +1f6f9c0fbaba0f128acbea296cec1887 *tests/data/fate/matroska-encoding-delay.matroska +961229 tests/data/fate/matroska-encoding-delay.matroska #extradata 0: 22, 0x32ea0490 #tb 0: 1/1000 #media_type 0: video @@ -32,7 +32,7 @@ dts_time=-0.010000 duration=24 duration_time=0.024000 size=1152 -pos=1238 +pos=1246 flags=K__ [/PACKET] [PACKET] @@ -45,7 +45,7 @@ dts_time=0.000000 duration=40 duration_time=0.040000 size=237628 -pos=2398 +pos=2406 flags=K__ [/PACKET] [PACKET] @@ -58,7 +58,7 @@ dts_time=0.014000 duration=24 duration_time=0.024000 size=1152 -pos=240033 +pos=240041 flags=K__ [/PACKET] [PACKET] @@ -71,7 +71,7 @@ dts_time=0.038000 duration=24 duration_time=0.024000 size=1152 -pos=241208 +pos=241216 flags=K__ [/PACKET] [PACKET] @@ -84,7 +84,7 @@ dts_time=0.040000 duration=40 duration_time=0.040000 size=238066 -pos=242368 +pos=242376 flags=K__ [/PACKET] [STREAM] diff --git a/tests/ref/fate/matroska-flac-extradata-update b/tests/ref/fate/matroska-flac-extradata-update index d5814925f50..d6713aaafaf 100644 --- a/tests/ref/fate/matroska-flac-extradata-update +++ b/tests/ref/fate/matroska-flac-extradata-update @@ -1,5 +1,5 @@ -28bc0ded5dc520d955caf29db80d35da *tests/data/fate/matroska-flac-extradata-update.matroska -1795 tests/data/fate/matroska-flac-extradata-update.matroska +fdbfdc51b519fd5e8f425aca1e7b8704 *tests/data/fate/matroska-flac-extradata-update.matroska +1807 tests/data/fate/matroska-flac-extradata-update.matroska #extradata 0: 34, 0x93650c81 #extradata 1: 34, 0x93650c81 #extradata 2: 34, 0x93650c81 diff --git a/tests/ref/fate/matroska-h264-remux b/tests/ref/fate/matroska-h264-remux index 6edd88fba87..9a9a98217c6 100644 --- a/tests/ref/fate/matroska-h264-remux +++ b/tests/ref/fate/matroska-h264-remux @@ -1,5 +1,5 @@ -3c00191234d5c4d77151d38a86403101 *tests/data/fate/matroska-h264-remux.matroska -2036033 tests/data/fate/matroska-h264-remux.matroska +fa3352ef6d3abd7d93f8627981a53f6f *tests/data/fate/matroska-h264-remux.matroska +2036049 tests/data/fate/matroska-h264-remux.matroska #tb 0: 1/25 #media_type 0: video #codec_id 0: rawvideo diff --git a/tests/ref/fate/matroska-mastering-display-metadata b/tests/ref/fate/matroska-mastering-display-metadata index 5b23e9506cb..95df3594c75 100644 --- a/tests/ref/fate/matroska-mastering-display-metadata +++ b/tests/ref/fate/matroska-mastering-display-metadata @@ -1,5 +1,5 @@ -69a904789151abaee46033391a4fce46 *tests/data/fate/matroska-mastering-display-metadata.matroska -1669555 tests/data/fate/matroska-mastering-display-metadata.matroska +e9a5f7314d6ae2ef16713335df2b5903 *tests/data/fate/matroska-mastering-display-metadata.matroska +1669571 tests/data/fate/matroska-mastering-display-metadata.matroska #extradata 0: 4, 0x040901a3 #extradata 3: 200, 0x506463a8 #tb 0: 1/1000 diff --git a/tests/ref/fate/matroska-move-cues-to-front b/tests/ref/fate/matroska-move-cues-to-front index 78697b2eae3..79ccc2fd935 100644 --- a/tests/ref/fate/matroska-move-cues-to-front +++ b/tests/ref/fate/matroska-move-cues-to-front @@ -1,5 +1,5 @@ -8ebfcf15768bbe66611e349383fbf26a *tests/data/fate/matroska-move-cues-to-front.matroska -23210287 tests/data/fate/matroska-move-cues-to-front.matroska +74a5ed3f0b14112322c8bf3e94d6e98b *tests/data/fate/matroska-move-cues-to-front.matroska +23210297 tests/data/fate/matroska-move-cues-to-front.matroska #tb 0: 1/1000 #media_type 0: audio #codec_id 0: pcm_s24be diff --git a/tests/ref/fate/matroska-mpegts-remux b/tests/ref/fate/matroska-mpegts-remux index 2faab0892f0..af41b57af16 100644 --- a/tests/ref/fate/matroska-mpegts-remux +++ b/tests/ref/fate/matroska-mpegts-remux @@ -1,5 +1,5 @@ -acaf3ebe07afe9815e0a984921d3ab87 *tests/data/fate/matroska-mpegts-remux.matroska -6494 tests/data/fate/matroska-mpegts-remux.matroska +ca1b91e49b6e238b641007c186d8f424 *tests/data/fate/matroska-mpegts-remux.matroska +6502 tests/data/fate/matroska-mpegts-remux.matroska #tb 0: 1/1000 #media_type 0: audio #codec_id 0: ac3 diff --git a/tests/ref/fate/matroska-ms-mode b/tests/ref/fate/matroska-ms-mode index f90a7e431f7..0a42ab0748a 100644 --- a/tests/ref/fate/matroska-ms-mode +++ b/tests/ref/fate/matroska-ms-mode @@ -1,5 +1,5 @@ -afb4fc9b2ca6cafc03d8029fdf4da876 *tests/data/fate/matroska-ms-mode.matroska -413086 tests/data/fate/matroska-ms-mode.matroska +7f0b825626a028765098222816ba56b8 *tests/data/fate/matroska-ms-mode.matroska +413094 tests/data/fate/matroska-ms-mode.matroska #extradata 0: 40, 0x54290c93 #extradata 1: 114, 0xb6c80771 #tb 0: 1/1000 diff --git a/tests/ref/fate/matroska-ogg-opus-remux b/tests/ref/fate/matroska-ogg-opus-remux index 473b9ff00c9..cd3eade361f 100644 --- a/tests/ref/fate/matroska-ogg-opus-remux +++ b/tests/ref/fate/matroska-ogg-opus-remux @@ -1,5 +1,5 @@ -a3f98769fe55bc5234cf75fb1949749a *tests/data/fate/matroska-ogg-opus-remux.matroska -10200 tests/data/fate/matroska-ogg-opus-remux.matroska +b602a1a4aaa4fbca4b8aaf39b66d7235 *tests/data/fate/matroska-ogg-opus-remux.matroska +10204 tests/data/fate/matroska-ogg-opus-remux.matroska #extradata 0: 19, 0x399c0471 #tb 0: 1/1000 #media_type 0: audio @@ -57,7 +57,7 @@ dts_time=-0.007000 duration=20 duration_time=0.020000 size=402 -pos=540 +pos=544 flags=K__ [/PACKET] [PACKET] @@ -70,7 +70,7 @@ dts_time=0.013000 duration=20 duration_time=0.020000 size=216 -pos=949 +pos=953 flags=K__ [/PACKET] [PACKET] @@ -83,7 +83,7 @@ dts_time=0.033000 duration=20 duration_time=0.020000 size=215 -pos=1172 +pos=1176 flags=K__ [/PACKET] [STREAM] diff --git a/tests/ref/fate/matroska-opus-remux b/tests/ref/fate/matroska-opus-remux index 8ebc80ee360..975510e1670 100644 --- a/tests/ref/fate/matroska-opus-remux +++ b/tests/ref/fate/matroska-opus-remux @@ -1,5 +1,5 @@ -551e45142f0989b281e837a3a86f0218 *tests/data/fate/matroska-opus-remux.matroska -9355 tests/data/fate/matroska-opus-remux.matroska +fe0258eb0d4b525203ea240c87a154d3 *tests/data/fate/matroska-opus-remux.matroska +9359 tests/data/fate/matroska-opus-remux.matroska #extradata 0: 19, 0x3a04048f #tb 0: 1/1000 #media_type 0: audio @@ -68,7 +68,7 @@ dts_time=-0.007000 duration=20 duration_time=0.020000 size=320 -pos=496 +pos=500 flags=K__ [/PACKET] [PACKET] @@ -81,7 +81,7 @@ dts_time=0.014000 duration=20 duration_time=0.020000 size=159 -pos=823 +pos=827 flags=K__ [/PACKET] [PACKET] @@ -94,7 +94,7 @@ dts_time=0.034000 duration=20 duration_time=0.020000 size=148 -pos=989 +pos=993 flags=K__ [/PACKET] [STREAM] diff --git a/tests/ref/fate/matroska-pgs-remux b/tests/ref/fate/matroska-pgs-remux index ed5beb74631..a086111495b 100644 --- a/tests/ref/fate/matroska-pgs-remux +++ b/tests/ref/fate/matroska-pgs-remux @@ -1,5 +1,5 @@ -6703d4e9a905bc5a1fc529776e8ffb51 *tests/data/fate/matroska-pgs-remux.matroska -49744 tests/data/fate/matroska-pgs-remux.matroska +d39daa393d66ae0b0c153be045897585 *tests/data/fate/matroska-pgs-remux.matroska +49748 tests/data/fate/matroska-pgs-remux.matroska #tb 0: 1/1000 #media_type 0: subtitle #codec_id 0: hdmv_pgs_subtitle diff --git a/tests/ref/fate/matroska-pgs-remux-durations b/tests/ref/fate/matroska-pgs-remux-durations index a255640fa6b..37494cd98f8 100644 --- a/tests/ref/fate/matroska-pgs-remux-durations +++ b/tests/ref/fate/matroska-pgs-remux-durations @@ -1,5 +1,5 @@ -a547f8b6463a60e5ef2e9a2b117c4dfa *tests/data/fate/matroska-pgs-remux-durations.matroska -49756 tests/data/fate/matroska-pgs-remux-durations.matroska +27af80eecea4f15f415f22841bc699d5 *tests/data/fate/matroska-pgs-remux-durations.matroska +49760 tests/data/fate/matroska-pgs-remux-durations.matroska #tb 0: 1/1000 #media_type 0: subtitle #codec_id 0: hdmv_pgs_subtitle diff --git a/tests/ref/fate/matroska-qt-mode b/tests/ref/fate/matroska-qt-mode index 17a8e6619ed..d54f5d167cc 100644 --- a/tests/ref/fate/matroska-qt-mode +++ b/tests/ref/fate/matroska-qt-mode @@ -1,5 +1,5 @@ -39a3d6faff69892c8a20301560b80b14 *tests/data/fate/matroska-qt-mode.matroska -1884224 tests/data/fate/matroska-qt-mode.matroska +c3483a76cd0bfbaf80a32dad041b6f52 *tests/data/fate/matroska-qt-mode.matroska +1884232 tests/data/fate/matroska-qt-mode.matroska #extradata 0: 90, 0x817d0185 #tb 0: 1/1000 #media_type 0: video diff --git a/tests/ref/fate/matroska-spherical-mono-remux b/tests/ref/fate/matroska-spherical-mono-remux index 6b975c15862..c65d206e910 100644 --- a/tests/ref/fate/matroska-spherical-mono-remux +++ b/tests/ref/fate/matroska-spherical-mono-remux @@ -1,5 +1,5 @@ -31cdace875cb696973d5a493ce776eea *tests/data/fate/matroska-spherical-mono-remux.matroska -161554 tests/data/fate/matroska-spherical-mono-remux.matroska +dfc2e196ca14cce155b1a081a0628fd3 *tests/data/fate/matroska-spherical-mono-remux.matroska +161562 tests/data/fate/matroska-spherical-mono-remux.matroska #extradata 0: 43, 0x2b0e0d7b #extradata 1: 43, 0x2b0e0d7b #tb 0: 1/1000 diff --git a/tests/ref/fate/matroska-vp8-alpha-remux b/tests/ref/fate/matroska-vp8-alpha-remux index 17c15ec9df4..1fad574edd0 100644 --- a/tests/ref/fate/matroska-vp8-alpha-remux +++ b/tests/ref/fate/matroska-vp8-alpha-remux @@ -1,5 +1,5 @@ -fd4f24bf776a2f84e01b0aa7fdfece38 *tests/data/fate/matroska-vp8-alpha-remux.matroska -235011 tests/data/fate/matroska-vp8-alpha-remux.matroska +3339f3fa157bdd63f22f5a579f308c89 *tests/data/fate/matroska-vp8-alpha-remux.matroska +235015 tests/data/fate/matroska-vp8-alpha-remux.matroska #tb 0: 1/1000 #media_type 0: video #codec_id 0: vp8 diff --git a/tests/ref/fate/matroska-zero-length-block b/tests/ref/fate/matroska-zero-length-block index bef887d58b2..3987cc14c48 100644 --- a/tests/ref/fate/matroska-zero-length-block +++ b/tests/ref/fate/matroska-zero-length-block @@ -1,5 +1,5 @@ -d9c8efb9d64addce3cac97e6c417d985 *tests/data/fate/matroska-zero-length-block.matroska -630 tests/data/fate/matroska-zero-length-block.matroska +f577fad2fff41d6e055f605281582b8d *tests/data/fate/matroska-zero-length-block.matroska +634 tests/data/fate/matroska-zero-length-block.matroska #tb 0: 1/1000 #media_type 0: subtitle #codec_id 0: subrip diff --git a/tests/ref/fate/rgb24-mkv b/tests/ref/fate/rgb24-mkv index f2cff5ff962..d037c01b32c 100644 --- a/tests/ref/fate/rgb24-mkv +++ b/tests/ref/fate/rgb24-mkv @@ -1,5 +1,5 @@ -a46cb669137f18ac0a42012485e5e863 *tests/data/fate/rgb24-mkv.matroska -58211 tests/data/fate/rgb24-mkv.matroska +69dc9d35fdfadccb28c7baf401776ec3 *tests/data/fate/rgb24-mkv.matroska +58215 tests/data/fate/rgb24-mkv.matroska #tb 0: 1/10 #media_type 0: video #codec_id 0: rawvideo diff --git a/tests/ref/fate/shortest-sub b/tests/ref/fate/shortest-sub index 53f89925b94..b6571b4f32e 100644 --- a/tests/ref/fate/shortest-sub +++ b/tests/ref/fate/shortest-sub @@ -1,5 +1,5 @@ -145b9b48d56f9c966bf41657f7569954 *tests/data/fate/shortest-sub.matroska -139232 tests/data/fate/shortest-sub.matroska +d334a0eee71351ddad0a63011107909f *tests/data/fate/shortest-sub.matroska +139240 tests/data/fate/shortest-sub.matroska #extradata 1: 167, 0xf7272d5f #tb 0: 1/1000 #media_type 0: video diff --git a/tests/ref/lavf-fate/av1.mkv b/tests/ref/lavf-fate/av1.mkv index 2008e1a9321..382e3aeee34 100644 --- a/tests/ref/lavf-fate/av1.mkv +++ b/tests/ref/lavf-fate/av1.mkv @@ -1,3 +1,3 @@ -72a4713f9165c73574d40e8b81c5d70f *tests/data/lavf-fate/lavf.av1.mkv -55642 tests/data/lavf-fate/lavf.av1.mkv +7d2c39dd98d5776425a4015e1eead6c6 *tests/data/lavf-fate/lavf.av1.mkv +55646 tests/data/lavf-fate/lavf.av1.mkv tests/data/lavf-fate/lavf.av1.mkv CRC=0x7c27cc15 diff --git a/tests/ref/lavf/mka b/tests/ref/lavf/mka index 7af63e07790..93a0b8f71a4 100644 --- a/tests/ref/lavf/mka +++ b/tests/ref/lavf/mka @@ -1,3 +1,3 @@ -e2d55cd3844fd7237a92181dbbcb08d9 *tests/data/lavf/lavf.mka -43569 tests/data/lavf/lavf.mka +77db16a9fe1c42a230c85124bfb40cad *tests/data/lavf/lavf.mka +43573 tests/data/lavf/lavf.mka tests/data/lavf/lavf.mka CRC=0x3a1da17e diff --git a/tests/ref/lavf/mkv b/tests/ref/lavf/mkv index d54c44a647b..fbd40fc1cb7 100644 --- a/tests/ref/lavf/mkv +++ b/tests/ref/lavf/mkv @@ -1,3 +1,3 @@ -0934e35639b6735c1e26595e8f47ba70 *tests/data/lavf/lavf.mkv -320409 tests/data/lavf/lavf.mkv +32b87b6adbe76df1008bc074f82fabb0 *tests/data/lavf/lavf.mkv +320417 tests/data/lavf/lavf.mkv tests/data/lavf/lavf.mkv CRC=0xec6c3c68 diff --git a/tests/ref/lavf/mkv_attachment b/tests/ref/lavf/mkv_attachment index ad964240989..2966a827cc3 100644 --- a/tests/ref/lavf/mkv_attachment +++ b/tests/ref/lavf/mkv_attachment @@ -1,3 +1,3 @@ -d2708709bdd6817d9cb2b475fdfa903f *tests/data/lavf/lavf.mkv_attachment -472559 tests/data/lavf/lavf.mkv_attachment +41739c51209d94b4763f9dbe4d1e1dc9 *tests/data/lavf/lavf.mkv_attachment +472567 tests/data/lavf/lavf.mkv_attachment tests/data/lavf/lavf.mkv_attachment CRC=0xec6c3c68 diff --git a/tests/ref/seek/lavf-mkv b/tests/ref/seek/lavf-mkv index 8ac0354164e..06ba6e03803 100644 --- a/tests/ref/seek/lavf-mkv +++ b/tests/ref/seek/lavf-mkv @@ -1,48 +1,48 @@ -ret: 0 st: 1 flags:1 dts:-0.011000 pts:-0.011000 pos: 657 size: 208 +ret: 0 st: 1 flags:1 dts:-0.011000 pts:-0.011000 pos: 665 size: 208 ret: 0 st:-1 flags:0 ts:-1.000000 -ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 873 size: 27837 +ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 881 size: 27837 ret: 0 st:-1 flags:1 ts: 1.894167 -ret: 0 st: 0 flags:1 dts: 0.960000 pts: 0.960000 pos: 292289 size: 27834 +ret: 0 st: 0 flags:1 dts: 0.960000 pts: 0.960000 pos: 292297 size: 27834 ret: 0 st: 0 flags:0 ts: 0.788000 -ret: 0 st: 0 flags:1 dts: 0.960000 pts: 0.960000 pos: 292289 size: 27834 +ret: 0 st: 0 flags:1 dts: 0.960000 pts: 0.960000 pos: 292297 size: 27834 ret: 0 st: 0 flags:1 ts:-0.317000 -ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 873 size: 27837 +ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 881 size: 27837 ret:-1 st: 1 flags:0 ts: 2.577000 ret: 0 st: 1 flags:1 ts: 1.471000 -ret: 0 st: 1 flags:1 dts: 0.982000 pts: 0.982000 pos: 320130 size: 209 +ret: 0 st: 1 flags:1 dts: 0.982000 pts: 0.982000 pos: 320138 size: 209 ret: 0 st:-1 flags:0 ts: 0.365002 -ret: 0 st: 0 flags:1 dts: 0.480000 pts: 0.480000 pos: 146841 size: 27925 +ret: 0 st: 0 flags:1 dts: 0.480000 pts: 0.480000 pos: 146849 size: 27925 ret: 0 st:-1 flags:1 ts:-0.740831 -ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 873 size: 27837 +ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 881 size: 27837 ret:-1 st: 0 flags:0 ts: 2.153000 ret: 0 st: 0 flags:1 ts: 1.048000 -ret: 0 st: 0 flags:1 dts: 0.960000 pts: 0.960000 pos: 292289 size: 27834 +ret: 0 st: 0 flags:1 dts: 0.960000 pts: 0.960000 pos: 292297 size: 27834 ret: 0 st: 1 flags:0 ts:-0.058000 -ret: 0 st: 1 flags:1 dts:-0.011000 pts:-0.011000 pos: 657 size: 208 +ret: 0 st: 1 flags:1 dts:-0.011000 pts:-0.011000 pos: 665 size: 208 ret: 0 st: 1 flags:1 ts: 2.836000 -ret: 0 st: 1 flags:1 dts: 0.982000 pts: 0.982000 pos: 320130 size: 209 +ret: 0 st: 1 flags:1 dts: 0.982000 pts: 0.982000 pos: 320138 size: 209 ret:-1 st:-1 flags:0 ts: 1.730004 ret: 0 st:-1 flags:1 ts: 0.624171 -ret: 0 st: 0 flags:1 dts: 0.480000 pts: 0.480000 pos: 146841 size: 27925 +ret: 0 st: 0 flags:1 dts: 0.480000 pts: 0.480000 pos: 146849 size: 27925 ret: 0 st: 0 flags:0 ts:-0.482000 -ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 873 size: 27837 +ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 881 size: 27837 ret: 0 st: 0 flags:1 ts: 2.413000 -ret: 0 st: 0 flags:1 dts: 0.960000 pts: 0.960000 pos: 292289 size: 27834 +ret: 0 st: 0 flags:1 dts: 0.960000 pts: 0.960000 pos: 292297 size: 27834 ret:-1 st: 1 flags:0 ts: 1.307000 ret: 0 st: 1 flags:1 ts: 0.201000 -ret: 0 st: 1 flags:1 dts:-0.011000 pts:-0.011000 pos: 657 size: 208 +ret: 0 st: 1 flags:1 dts:-0.011000 pts:-0.011000 pos: 665 size: 208 ret: 0 st:-1 flags:0 ts:-0.904994 -ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 873 size: 27837 +ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 881 size: 27837 ret: 0 st:-1 flags:1 ts: 1.989173 -ret: 0 st: 0 flags:1 dts: 0.960000 pts: 0.960000 pos: 292289 size: 27834 +ret: 0 st: 0 flags:1 dts: 0.960000 pts: 0.960000 pos: 292297 size: 27834 ret: 0 st: 0 flags:0 ts: 0.883000 -ret: 0 st: 0 flags:1 dts: 0.960000 pts: 0.960000 pos: 292289 size: 27834 +ret: 0 st: 0 flags:1 dts: 0.960000 pts: 0.960000 pos: 292297 size: 27834 ret: 0 st: 0 flags:1 ts:-0.222000 -ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 873 size: 27837 +ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 881 size: 27837 ret:-1 st: 1 flags:0 ts: 2.672000 ret: 0 st: 1 flags:1 ts: 1.566000 -ret: 0 st: 1 flags:1 dts: 0.982000 pts: 0.982000 pos: 320130 size: 209 +ret: 0 st: 1 flags:1 dts: 0.982000 pts: 0.982000 pos: 320138 size: 209 ret: 0 st:-1 flags:0 ts: 0.460008 -ret: 0 st: 0 flags:1 dts: 0.480000 pts: 0.480000 pos: 146841 size: 27925 +ret: 0 st: 0 flags:1 dts: 0.480000 pts: 0.480000 pos: 146849 size: 27925 ret: 0 st:-1 flags:1 ts:-0.645825 -ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 873 size: 27837 +ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 881 size: 27837 From 61b27b15fc924d7fa35baa61cfbc91568945f5db Mon Sep 17 00:00:00 2001 From: James Almer Date: Sat, 1 Apr 2023 12:12:11 -0300 Subject: [PATCH 0577/2172] avutil/hdr_dynamic_metadata: allow av_dynamic_hdr_plus_to_t35() to accept an existing buffer The function now accepts an existing buffer to avoid unnecessary allocations, as well as only reporting the needed amount of bytes if you pass a NULL pointer as input for data. For this, both parameters become input and output, as well as making data optional. This is backwards compatible, and as such not breaking any existing use of the function in external code (if there's any). Signed-off-by: James Almer --- doc/APIchanges | 5 +++++ libavutil/hdr_dynamic_metadata.c | 28 ++++++++++++++++++++-------- libavutil/hdr_dynamic_metadata.h | 14 +++++++++++--- libavutil/version.h | 2 +- 4 files changed, 37 insertions(+), 12 deletions(-) diff --git a/doc/APIchanges b/doc/APIchanges index 29ddaa31bd5..44ba3ad634b 100644 --- a/doc/APIchanges +++ b/doc/APIchanges @@ -2,6 +2,11 @@ The last version increases of all libraries were on 2023-02-09 API changes, most recent first: +2023-04-04 - xxxxxxxxxx - lavu 58.6.100 - hdr_dynamic_metadata.h + Add AV_HDR_PLUS_MAX_PAYLOAD_SIZE. + av_dynamic_hdr_plus_create_side_data() now accepts a user provided + buffer. + 2023-03-xx - xxxxxxxxxx - lavfi 9.5.100 - avfilter.h Add AVFILTER_FLAG_HWDEVICE. diff --git a/libavutil/hdr_dynamic_metadata.c b/libavutil/hdr_dynamic_metadata.c index d458788c32c..7033f060c0a 100644 --- a/libavutil/hdr_dynamic_metadata.c +++ b/libavutil/hdr_dynamic_metadata.c @@ -18,14 +18,13 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#include "avassert.h" #include "hdr_dynamic_metadata.h" #include "mem.h" #include "libavcodec/defs.h" #include "libavcodec/get_bits.h" #include "libavcodec/put_bits.h" -#define T35_PAYLOAD_MAX_SIZE 907 - static const int64_t luminance_den = 1; static const int32_t peak_luminance_den = 15; static const int64_t rgb_den = 100000; @@ -62,14 +61,14 @@ AVDynamicHDRPlus *av_dynamic_hdr_plus_create_side_data(AVFrame *frame) int av_dynamic_hdr_plus_from_t35(AVDynamicHDRPlus *s, const uint8_t *data, size_t size) { - uint8_t padded_buf[T35_PAYLOAD_MAX_SIZE + AV_INPUT_BUFFER_PADDING_SIZE]; + uint8_t padded_buf[AV_HDR_PLUS_MAX_PAYLOAD_SIZE + AV_INPUT_BUFFER_PADDING_SIZE]; GetBitContext gbc, *gb = &gbc; int ret; if (!s) return AVERROR(ENOMEM); - if (size > T35_PAYLOAD_MAX_SIZE) + if (size > AV_HDR_PLUS_MAX_PAYLOAD_SIZE) return AVERROR(EINVAL); memcpy(padded_buf, data, size); @@ -243,8 +242,10 @@ int av_dynamic_hdr_plus_to_t35(const AVDynamicHDRPlus *s, uint8_t **data, size_t size_t size_bits, size_bytes; PutBitContext pbc, *pb = &pbc; - if (!s || !data) + if (!s) return AVERROR(EINVAL); + if ((!data || *data) && !size) + return AVERROR(EINVAL); /** * Buffer size per CTA-861-H p.253-254: @@ -296,9 +297,20 @@ int av_dynamic_hdr_plus_to_t35(const AVDynamicHDRPlus *s, uint8_t **data, size_t size_bytes = (size_bits + 7) / 8; - buf = av_mallocz(size_bytes); - if (!buf) - return AVERROR(ENOMEM); + av_assert0(size_bytes <= AV_HDR_PLUS_MAX_PAYLOAD_SIZE); + + if (!data) { + *size = size_bytes; + return 0; + } else if (*data) { + if (*size < size_bytes) + return AVERROR_BUFFER_TOO_SMALL; + buf = *data; + } else { + buf = av_malloc(size_bytes); + if (!buf) + return AVERROR(ENOMEM); + } init_put_bits(pb, buf, size_bytes); diff --git a/libavutil/hdr_dynamic_metadata.h b/libavutil/hdr_dynamic_metadata.h index 771bb8f468d..09e9d8bbccf 100644 --- a/libavutil/hdr_dynamic_metadata.h +++ b/libavutil/hdr_dynamic_metadata.h @@ -353,13 +353,21 @@ AVDynamicHDRPlus *av_dynamic_hdr_plus_create_side_data(AVFrame *frame); int av_dynamic_hdr_plus_from_t35(AVDynamicHDRPlus *s, const uint8_t *data, size_t size); +#define AV_HDR_PLUS_MAX_PAYLOAD_SIZE 907 + /** * Serialize dynamic HDR10+ metadata to a user data registered ITU-T T.35 buffer, * excluding the first 48 bytes of the header, and beginning with the application mode. * @param s A pointer containing the decoded AVDynamicHDRPlus structure. - * @param data A pointer to a byte buffer to be allocated and filled - * with the serialized metadata. - * @param size A pointer to a size to be set to the returned buffer's size (optional). + * @param data[in,out] A pointer to pointer to a byte buffer to be filled with the + * serialized metadata. + * If *data is NULL, a buffer be will be allocated and a pointer to + * it stored in its place. The caller assumes ownership of the buffer. + * May be NULL, in which case the function will only store the + * required buffer size in *size. + * @param size[in,out] A pointer to a size to be set to the returned buffer's size. + * If *data is not NULL, *size must contain the size of the input + * buffer. May be NULL only if *data is NULL. * * @return >= 0 on success. Otherwise, returns the appropriate AVERROR. */ diff --git a/libavutil/version.h b/libavutil/version.h index a232381ba56..40f92af0550 100644 --- a/libavutil/version.h +++ b/libavutil/version.h @@ -79,7 +79,7 @@ */ #define LIBAVUTIL_VERSION_MAJOR 58 -#define LIBAVUTIL_VERSION_MINOR 5 +#define LIBAVUTIL_VERSION_MINOR 6 #define LIBAVUTIL_VERSION_MICRO 100 #define LIBAVUTIL_VERSION_INT AV_VERSION_INT(LIBAVUTIL_VERSION_MAJOR, \ From 8f534618b5acfb40f146651ba2a3b88fc00eb8b9 Mon Sep 17 00:00:00 2001 From: Marton Balint Date: Sun, 26 Mar 2023 22:16:38 +0200 Subject: [PATCH 0578/2172] avformat/mxfdec: treat Random Index Pack as end of file RIP, if exists is the last KLV item in the MXF files therefore we can stop parsing the file if it is encountered. This allows us to support files created by broken muxers such as OpenCube MXFTk Advanced 2.8.0.0.1. which dumps some extra garbage after the RIP. Signed-off-by: Marton Balint --- libavformat/mxfdec.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/libavformat/mxfdec.c b/libavformat/mxfdec.c index 45306172076..8a7008b298c 100644 --- a/libavformat/mxfdec.c +++ b/libavformat/mxfdec.c @@ -3739,7 +3739,10 @@ static int mxf_read_header(AVFormatContext *s) while (!avio_feof(s->pb)) { const MXFMetadataReadTableEntry *metadata; - if (klv_read_packet(&klv, s->pb) < 0) { + ret = klv_read_packet(&klv, s->pb); + if (ret < 0 || IS_KLV_KEY(klv.key, ff_mxf_random_index_pack_key)) { + if (ret >= 0 && avio_size(s->pb) > klv.next_klv) + av_log(s, AV_LOG_WARNING, "data after the RandomIndexPack, assuming end of file\n"); /* EOF - seek to previous partition or stop */ if(mxf_parse_handle_partition_or_eof(mxf) <= 0) break; From 88da4b5fcdbdee6fae9774dad4b2b28560fe8a3c Mon Sep 17 00:00:00 2001 From: Marton Balint Date: Tue, 28 Mar 2023 23:29:51 +0200 Subject: [PATCH 0579/2172] fate: split mxf test dependencies to DV and MPEG2 Signed-off-by: Marton Balint --- tests/fate/lavf-container.mak | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/fate/lavf-container.mak b/tests/fate/lavf-container.mak index 1b473e36e1f..93740475b49 100644 --- a/tests/fate/lavf-container.mak +++ b/tests/fate/lavf-container.mak @@ -9,7 +9,8 @@ FATE_LAVF_CONTAINER-$(call ENCDEC2, MPEG4, PCM_ALAW, MOV) + FATE_LAVF_CONTAINER-$(call ENCDEC, MPEG4, MOV) += mp4 FATE_LAVF_CONTAINER-$(call ENCDEC2, MPEG1VIDEO, MP2, MPEG1SYSTEM MPEGPS) += mpg FATE_LAVF_CONTAINER-$(call ENCDEC , FFV1, MXF) += mxf_ffv1 -FATE_LAVF_CONTAINER-$(call ENCDEC2, MPEG2VIDEO, PCM_S16LE, MXF) += mxf mxf_dv25 mxf_dvcpro50 mxf_dvcpro100 +FATE_LAVF_CONTAINER-$(call ENCDEC2, MPEG2VIDEO, PCM_S16LE, MXF) += mxf +FATE_LAVF_CONTAINER-$(call ENCDEC2, DVVIDEO, PCM_S16LE, MXF) += mxf_dv25 mxf_dvcpro50 mxf_dvcpro100 FATE_LAVF_CONTAINER-$(call ENCDEC2, MPEG2VIDEO, PCM_S16LE, MXF_D10 MXF) += mxf_d10 FATE_LAVF_CONTAINER-$(call ENCDEC2, DNXHD, PCM_S16LE, MXF_OPATOM MXF) += mxf_opatom mxf_opatom_audio FATE_LAVF_CONTAINER-$(call ENCDEC2, MPEG4, MP2, NUT) += nut From 33ef8778e0d94b9346eab2373c154b7aa539900c Mon Sep 17 00:00:00 2001 From: Devin Heitmueller Date: Mon, 27 Mar 2023 15:58:10 -0400 Subject: [PATCH 0580/2172] avdevice/decklink_enc: Add support for output of Active Format Description (AFD) Implement support for including AFD in decklink output when putting out 10-bit VANC data. Updated to reflect feedback in 2018 from Marton Balint , Carl Eugen Hoyos and Aaron Levinson . Also includes fixes to set the AR field based on the SAR, as well as now sending the AFD info in both fields for interlaced formats. Signed-off-by: Devin Heitmueller Signed-off-by: Marton Balint --- libavdevice/decklink_enc.cpp | 90 +++++++++++++++++++++++++++++++++++- 1 file changed, 88 insertions(+), 2 deletions(-) diff --git a/libavdevice/decklink_enc.cpp b/libavdevice/decklink_enc.cpp index 8d423f6b6e9..62676ea68e9 100644 --- a/libavdevice/decklink_enc.cpp +++ b/libavdevice/decklink_enc.cpp @@ -367,8 +367,93 @@ static void construct_cc(AVFormatContext *avctx, struct decklink_ctx *ctx, } } +/* See SMPTE ST 2016-3:2009 */ +static void construct_afd(AVFormatContext *avctx, struct decklink_ctx *ctx, + AVPacket *pkt, struct klvanc_line_set_s *vanc_lines, + AVStream *st) +{ + struct klvanc_packet_afd_s *afd = NULL; + uint16_t *afd_words = NULL; + uint16_t len; + size_t size; + int f1_line = 12, f2_line = 0, ret; + + const uint8_t *data = av_packet_get_side_data(pkt, AV_PKT_DATA_AFD, &size); + if (!data || size == 0) + return; + + ret = klvanc_create_AFD(&afd); + if (ret) + return; + + ret = klvanc_set_AFD_val(afd, data[0]); + if (ret) { + av_log(avctx, AV_LOG_ERROR, "Invalid AFD value specified: %d\n", + data[0]); + klvanc_destroy_AFD(afd); + return; + } + + /* Compute the AR flag based on the DAR (see ST 2016-1:2009 Sec 9.1). Note, we treat + anything below 1.4 as 4:3 (as opposed to the standard 1.33), because there are lots + of streams in the field that aren't *exactly* 4:3 but a tiny bit larger after doing + the math... */ + if (av_cmp_q((AVRational) {st->codecpar->width * st->codecpar->sample_aspect_ratio.num, + st->codecpar->height * st->codecpar->sample_aspect_ratio.den}, (AVRational) {14, 10}) == 1) + afd->aspectRatio = ASPECT_16x9; + else + afd->aspectRatio = ASPECT_4x3; + + ret = klvanc_convert_AFD_to_words(afd, &afd_words, &len); + if (ret) { + av_log(avctx, AV_LOG_ERROR, "Failed converting AFD packet to words\n"); + goto out; + } + + ret = klvanc_line_insert(ctx->vanc_ctx, vanc_lines, afd_words, len, f1_line, 0); + if (ret) { + av_log(avctx, AV_LOG_ERROR, "VANC line insertion failed\n"); + goto out; + } + + /* For interlaced video, insert into both fields. Switching lines for field 2 + derived from SMPTE RP 168:2009, Sec 6, Table 2. */ + switch (ctx->bmd_mode) { + case bmdModeNTSC: + case bmdModeNTSC2398: + f2_line = 273 - 10 + f1_line; + break; + case bmdModePAL: + f2_line = 319 - 6 + f1_line; + break; + case bmdModeHD1080i50: + case bmdModeHD1080i5994: + case bmdModeHD1080i6000: + f2_line = 569 - 7 + f1_line; + break; + default: + f2_line = 0; + break; + } + + if (f2_line > 0) { + ret = klvanc_line_insert(ctx->vanc_ctx, vanc_lines, afd_words, len, f2_line, 0); + if (ret) { + av_log(avctx, AV_LOG_ERROR, "VANC line insertion failed\n"); + goto out; + } + } + +out: + if (afd) + klvanc_destroy_AFD(afd); + if (afd_words) + free(afd_words); +} + static int decklink_construct_vanc(AVFormatContext *avctx, struct decklink_ctx *ctx, - AVPacket *pkt, decklink_frame *frame) + AVPacket *pkt, decklink_frame *frame, + AVStream *st) { struct klvanc_line_set_s vanc_lines = { 0 }; int ret = 0, i; @@ -377,6 +462,7 @@ static int decklink_construct_vanc(AVFormatContext *avctx, struct decklink_ctx * return 0; construct_cc(avctx, ctx, pkt, &vanc_lines); + construct_afd(avctx, ctx, pkt, &vanc_lines, st); IDeckLinkVideoFrameAncillary *vanc; int result = ctx->dlo->CreateAncillaryData(bmdFormat10BitYUV, &vanc); @@ -468,7 +554,7 @@ static int decklink_write_video_packet(AVFormatContext *avctx, AVPacket *pkt) frame = new decklink_frame(ctx, avpacket, st->codecpar->codec_id, ctx->bmd_height, ctx->bmd_width); #if CONFIG_LIBKLVANC - if (decklink_construct_vanc(avctx, ctx, pkt, frame)) + if (decklink_construct_vanc(avctx, ctx, pkt, frame, st)) av_log(avctx, AV_LOG_ERROR, "Failed to construct VANC\n"); #endif } From 916be62da1303f5fc9165b85c81d43899947c270 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Mon, 3 Apr 2023 00:21:00 +0200 Subject: [PATCH 0581/2172] tests/fate/vcodec.mak: drop strict experimental from j2k tests Signed-off-by: Michael Niedermayer --- tests/fate/vcodec.mak | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/fate/vcodec.mak b/tests/fate/vcodec.mak index 9c3e796547e..bf9de0327a5 100644 --- a/tests/fate/vcodec.mak +++ b/tests/fate/vcodec.mak @@ -220,10 +220,10 @@ fate-vsynth%-jpegls: ENCOPTS = -sws_flags neighbor+full_chroma_int fate-vsynth%-jpegls: DECOPTS = -sws_flags area FATE_VCODEC_SCALE-$(call ENCDEC, JPEG2000, AVI) += jpeg2000 jpeg2000-97 jpeg2000-gbrp12 jpeg2000-yuva444p16 -fate-vsynth%-jpeg2000: ENCOPTS = -qscale 7 -strict experimental -pred 1 -pix_fmt rgb24 -fate-vsynth%-jpeg2000-97: ENCOPTS = -qscale 7 -strict experimental -pix_fmt rgb24 -fate-vsynth%-jpeg2000-gbrp12: ENCOPTS = -qscale 5 -strict experimental -pred 1 -pix_fmt gbrp12 -fate-vsynth%-jpeg2000-yuva444p16: ENCOPTS = -qscale 8 -strict experimental -pred 1 -pix_fmt yuva444p16 +fate-vsynth%-jpeg2000: ENCOPTS = -qscale 7 -pred 1 -pix_fmt rgb24 +fate-vsynth%-jpeg2000-97: ENCOPTS = -qscale 7 -pix_fmt rgb24 +fate-vsynth%-jpeg2000-gbrp12: ENCOPTS = -qscale 5 -pred 1 -pix_fmt gbrp12 +fate-vsynth%-jpeg2000-yuva444p16: ENCOPTS = -qscale 8 -pred 1 -pix_fmt yuva444p16 FATE_VCODEC-$(call ENCDEC, LJPEG MJPEG, AVI) += ljpeg fate-vsynth%-ljpeg: ENCOPTS = -strict -1 From f0cd5610e0ef34fb5c2b705586fa143c7884ce63 Mon Sep 17 00:00:00 2001 From: Jerome Martinez Date: Tue, 4 Apr 2023 16:57:03 +0200 Subject: [PATCH 0582/2172] avcodec/ffv1dec: reject unsupported ffv1 versions Signed-off-by: Michael Niedermayer --- libavcodec/ffv1dec.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/libavcodec/ffv1dec.c b/libavcodec/ffv1dec.c index 180d24e6953..a3f93022334 100644 --- a/libavcodec/ffv1dec.c +++ b/libavcodec/ffv1dec.c @@ -439,6 +439,11 @@ static int read_extra_header(FFV1Context *f) av_log(f->avctx, AV_LOG_ERROR, "Invalid version in global header\n"); return AVERROR_INVALIDDATA; } + if (f->version > 4) { + av_log(f->avctx, AV_LOG_ERROR, "unsupported version %d\n", + f->version); + return AVERROR_PATCHWELCOME; + } if (f->version > 2) { c->bytestream_end -= 4; f->micro_version = get_symbol(c, state, 0); From feeeefc3db04810286cd647f235ced0ec6c3eba8 Mon Sep 17 00:00:00 2001 From: Jerome Martinez Date: Tue, 4 Apr 2023 16:57:03 +0200 Subject: [PATCH 0583/2172] avformat/mxfenc: reject unsupported ffv1 versions Signed-off-by: Michael Niedermayer --- libavformat/mxfenc.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/libavformat/mxfenc.c b/libavformat/mxfenc.c index 9eba208ffb6..d8252ed68f3 100644 --- a/libavformat/mxfenc.c +++ b/libavformat/mxfenc.c @@ -2493,6 +2493,10 @@ static int mxf_parse_ffv1_frame(AVFormatContext *s, AVStream *st, AVPacket *pkt) if (v > 4) { return 0; } + if (v > 4) { + av_log(s, AV_LOG_ERROR, "unsupported ffv1 version %d\n", v); + return 0; + } sc->micro_version = get_ffv1_unsigned_symbol(&c, state); } else { uint8_t keystate = 128; From 68c151cb1b3bc254aeebe7460f9b0eb58e55dbb2 Mon Sep 17 00:00:00 2001 From: "J. Dekker" Date: Tue, 21 Mar 2023 18:44:03 +0100 Subject: [PATCH 0584/2172] checkasm: add hevc_deblock chroma test Signed-off-by: J. Dekker --- tests/checkasm/Makefile | 2 +- tests/checkasm/checkasm.c | 1 + tests/checkasm/checkasm.h | 1 + tests/checkasm/hevc_deblock.c | 101 ++++++++++++++++++++++++++++++++++ tests/fate/checkasm.mak | 1 + 5 files changed, 105 insertions(+), 1 deletion(-) create mode 100644 tests/checkasm/hevc_deblock.c diff --git a/tests/checkasm/Makefile b/tests/checkasm/Makefile index b6a43f181fc..64d3c00168f 100644 --- a/tests/checkasm/Makefile +++ b/tests/checkasm/Makefile @@ -28,7 +28,7 @@ AVCODECOBJS-$(CONFIG_HUFFYUV_DECODER) += huffyuvdsp.o AVCODECOBJS-$(CONFIG_JPEG2000_DECODER) += jpeg2000dsp.o AVCODECOBJS-$(CONFIG_OPUS_DECODER) += opusdsp.o AVCODECOBJS-$(CONFIG_PIXBLOCKDSP) += pixblockdsp.o -AVCODECOBJS-$(CONFIG_HEVC_DECODER) += hevc_add_res.o hevc_idct.o hevc_sao.o hevc_pel.o +AVCODECOBJS-$(CONFIG_HEVC_DECODER) += hevc_add_res.o hevc_deblock.o hevc_idct.o hevc_sao.o hevc_pel.o AVCODECOBJS-$(CONFIG_UTVIDEO_DECODER) += utvideodsp.o AVCODECOBJS-$(CONFIG_V210_DECODER) += v210dec.o AVCODECOBJS-$(CONFIG_V210_ENCODER) += v210enc.o diff --git a/tests/checkasm/checkasm.c b/tests/checkasm/checkasm.c index 5e729cf0e01..d4df964d6bd 100644 --- a/tests/checkasm/checkasm.c +++ b/tests/checkasm/checkasm.c @@ -116,6 +116,7 @@ static const struct { #endif #if CONFIG_HEVC_DECODER { "hevc_add_res", checkasm_check_hevc_add_res }, + { "hevc_deblock", checkasm_check_hevc_deblock }, { "hevc_idct", checkasm_check_hevc_idct }, { "hevc_pel", checkasm_check_hevc_pel }, { "hevc_sao", checkasm_check_hevc_sao }, diff --git a/tests/checkasm/checkasm.h b/tests/checkasm/checkasm.h index e9e73c6fa07..03b27efa276 100644 --- a/tests/checkasm/checkasm.h +++ b/tests/checkasm/checkasm.h @@ -60,6 +60,7 @@ void checkasm_check_h264dsp(void); void checkasm_check_h264pred(void); void checkasm_check_h264qpel(void); void checkasm_check_hevc_add_res(void); +void checkasm_check_hevc_deblock(void); void checkasm_check_hevc_idct(void); void checkasm_check_hevc_pel(void); void checkasm_check_hevc_sao(void); diff --git a/tests/checkasm/hevc_deblock.c b/tests/checkasm/hevc_deblock.c new file mode 100644 index 00000000000..e003f98d029 --- /dev/null +++ b/tests/checkasm/hevc_deblock.c @@ -0,0 +1,101 @@ +/* + * 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/intreadwrite.h" +#include "libavutil/mem_internal.h" + +#include "libavcodec/avcodec.h" +#include "libavcodec/hevcdsp.h" + +#include "checkasm.h" + +static const uint32_t pixel_mask[3] = { 0xffffffff, 0x03ff03ff, 0x0fff0fff }; + +#define SIZEOF_PIXEL ((bit_depth + 7) / 8) +#define BUF_STRIDE (8 * 2) +#define BUF_LINES (8) +#define BUF_OFFSET (BUF_STRIDE * BUF_LINES) +#define BUF_SIZE (BUF_STRIDE * BUF_LINES + BUF_OFFSET * 2) + +#define randomize_buffers(buf0, buf1, size) \ + do { \ + uint32_t mask = pixel_mask[(bit_depth - 8) >> 1]; \ + int k; \ + for (k = 0; k < size; k += 4) { \ + uint32_t r = rnd() & mask; \ + AV_WN32A(buf0 + k, r); \ + AV_WN32A(buf1 + k, r); \ + } \ + } while (0) + +static void check_deblock_chroma(HEVCDSPContext h, int bit_depth) +{ + int32_t tc[2] = { 0, 0 }; + // no_p, no_q can only be { 0,0 } for the simpler assembly (non *_c + // variant) functions, see deblocking_filter_CTB() in hevc_filter.c + uint8_t no_p[2] = { 0, 0 }; + uint8_t no_q[2] = { 0, 0 }; + LOCAL_ALIGNED_32(uint8_t, buf0, [BUF_SIZE]); + LOCAL_ALIGNED_32(uint8_t, buf1, [BUF_SIZE]); + + declare_func_emms(AV_CPU_FLAG_MMX, void, uint8_t *pix, ptrdiff_t stride, int32_t *tc, uint8_t *no_p, uint8_t *no_q); + + if (check_func(h.hevc_h_loop_filter_chroma, "hevc_h_loop_filter_chroma%d", bit_depth)) { + for (int i = 0; i < 4; i++) { + randomize_buffers(buf0, buf1, BUF_SIZE); + // see betatable[] in hevc_filter.c + tc[0] = (rnd() & 63) + (rnd() & 1); + tc[1] = (rnd() & 63) + (rnd() & 1); + + call_ref(buf0 + BUF_OFFSET, BUF_STRIDE, tc, no_p, no_q); + call_new(buf1 + BUF_OFFSET, BUF_STRIDE, tc, no_p, no_q); + if (memcmp(buf0, buf1, BUF_SIZE)) + fail(); + } + bench_new(buf1 + BUF_OFFSET, BUF_STRIDE, tc, no_p, no_q); + } + + if (check_func(h.hevc_v_loop_filter_chroma, "hevc_v_loop_filter_chroma%d", bit_depth)) { + for (int i = 0; i < 4; i++) { + randomize_buffers(buf0, buf1, BUF_SIZE); + // see betatable[] in hevc_filter.c + tc[0] = (rnd() & 63) + (rnd() & 1); + tc[1] = (rnd() & 63) + (rnd() & 1); + + call_ref(buf0 + BUF_OFFSET, BUF_STRIDE, tc, no_p, no_q); + call_new(buf1 + BUF_OFFSET, BUF_STRIDE, tc, no_p, no_q); + if (memcmp(buf0, buf1, BUF_SIZE)) + fail(); + } + bench_new(buf1 + BUF_OFFSET, BUF_STRIDE, tc, no_p, no_q); + } +} + +void checkasm_check_hevc_deblock(void) +{ + int bit_depth; + + for (bit_depth = 8; bit_depth <= 12; bit_depth += 2) { + HEVCDSPContext h; + ff_hevc_dsp_init(&h, bit_depth); + check_deblock_chroma(h, bit_depth); + } + report("chroma"); +} diff --git a/tests/fate/checkasm.mak b/tests/fate/checkasm.mak index 6a7d4a12261..c208e2abca8 100644 --- a/tests/fate/checkasm.mak +++ b/tests/fate/checkasm.mak @@ -15,6 +15,7 @@ FATE_CHECKASM = fate-checkasm-aacpsdsp \ fate-checkasm-h264pred \ fate-checkasm-h264qpel \ fate-checkasm-hevc_add_res \ + fate-checkasm-hevc_deblock \ fate-checkasm-hevc_idct \ fate-checkasm-hevc_pel \ fate-checkasm-hevc_sao \ From b564ad8eacc581b57f0c78bba13d08dfc2cecddf Mon Sep 17 00:00:00 2001 From: "J. Dekker" Date: Wed, 29 Mar 2023 15:03:57 +0200 Subject: [PATCH 0585/2172] lavc/aarch64: add hevc deblock chroma 8-12bit Benched on Ampere Altra: hevc_h_loop_filter_chroma8_c: 367.7 hevc_h_loop_filter_chroma8_neon: 31.0 hevc_h_loop_filter_chroma10_c: 396.7 hevc_h_loop_filter_chroma10_neon: 27.5 hevc_h_loop_filter_chroma12_c: 377.0 hevc_h_loop_filter_chroma12_neon: 31.7 hevc_v_loop_filter_chroma8_c: 369.0 hevc_v_loop_filter_chroma8_neon: 55.0 hevc_v_loop_filter_chroma10_c: 389.0 hevc_v_loop_filter_chroma10_neon: 54.0 hevc_v_loop_filter_chroma12_c: 389.5 hevc_v_loop_filter_chroma12_neon: 53.0 Signed-off-by: J. Dekker --- libavcodec/aarch64/Makefile | 3 +- libavcodec/aarch64/hevcdsp_deblock_neon.S | 183 ++++++++++++++++++++++ libavcodec/aarch64/hevcdsp_init_aarch64.c | 18 +++ 3 files changed, 203 insertions(+), 1 deletion(-) create mode 100644 libavcodec/aarch64/hevcdsp_deblock_neon.S diff --git a/libavcodec/aarch64/Makefile b/libavcodec/aarch64/Makefile index 02fb51c3ab9..216191640c7 100644 --- a/libavcodec/aarch64/Makefile +++ b/libavcodec/aarch64/Makefile @@ -65,7 +65,8 @@ NEON-OBJS-$(CONFIG_VP9_DECODER) += aarch64/vp9itxfm_16bpp_neon.o \ aarch64/vp9lpf_neon.o \ aarch64/vp9mc_16bpp_neon.o \ aarch64/vp9mc_neon.o -NEON-OBJS-$(CONFIG_HEVC_DECODER) += aarch64/hevcdsp_idct_neon.o \ +NEON-OBJS-$(CONFIG_HEVC_DECODER) += aarch64/hevcdsp_deblock_neon.o \ + aarch64/hevcdsp_idct_neon.o \ aarch64/hevcdsp_init_aarch64.o \ aarch64/hevcdsp_qpel_neon.o \ aarch64/hevcdsp_sao_neon.o diff --git a/libavcodec/aarch64/hevcdsp_deblock_neon.S b/libavcodec/aarch64/hevcdsp_deblock_neon.S new file mode 100644 index 00000000000..8227f656496 --- /dev/null +++ b/libavcodec/aarch64/hevcdsp_deblock_neon.S @@ -0,0 +1,183 @@ +/* -*-arm64-*- + * vim: syntax=arm64asm + * + * Copyright (c) 2014 Seppo Tomperi + * Copyright (c) 2023 J. Dekker + * + * 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/aarch64/asm.S" +#include "neon.S" + +.macro hevc_loop_filter_chroma_start bitdepth + mov x4, x30 + ldr w14, [x2] + ldr w15, [x2, #4] +.if \bitdepth > 8 + lsl w14, w14, #(\bitdepth - 8) + lsl w15, w15, #(\bitdepth - 8) +.endif + adds w2, w14, w15 + b.eq 1f + dup v16.4h, w14 + dup v17.4h, w15 + trn1 v16.2d, v16.2d, v17.2d +.if \bitdepth > 8 + mvni v19.8h, #((0xff << (\bitdepth - 8)) & 0xff), lsl #8 + movi v18.8h, #0 +.endif + neg v17.8h, v16.8h +.endm + +.macro hevc_loop_filter_chroma_body bitdepth +.if \bitdepth <= 8 + uxtl v20.8h, v0.8b // p1 + uxtl v1.8h, v1.8b // p0 + uxtl v2.8h, v2.8b // q0 + uxtl v23.8h, v3.8b // q1 + va .req v20 + vb .req v23 +.else // required to specify both cases as we are unable to do: v0 .req v20 + va .req v0 + vb .req v3 +.endif + sub v5.8h, v2.8h, v1.8h // q0 - p0 + sub v6.8h, va.8h, vb.8h // p1 - q1 + shl v5.8h, v5.8h, #2 + add v5.8h, v6.8h, v5.8h + srshr v5.8h, v5.8h, #3 + clip v17.8h, v16.8h, v5.8h + sqadd v1.8h, v1.8h, v5.8h // p0 + delta + sqsub v2.8h, v2.8h, v5.8h // q0 - delta +.if \bitdepth <= 8 + sqxtun v1.8b, v1.8h + sqxtun v2.8b, v2.8h +.else + clip v18.8h, v19.8h, v1.8h, v2.8h +.endif +.unreq va +.unreq vb +.endm + +function hevc_loop_filter_chroma_body_8_neon, export=0 + hevc_loop_filter_chroma_body 8 + ret +endfunc + +function hevc_loop_filter_chroma_body_10_neon, export=0 +hevc_loop_filter_chroma_body_12_neon: + hevc_loop_filter_chroma_body 10 + ret +endfunc + +// void ff_hevc_h_loop_filter_chroma_8_neon(uint8_t *_pix, ptrdiff_t _stride, int *_tc, uint8_t *_no_p, uint8_t *_no_q); + +.macro hevc_h_loop_filter_chroma bitdepth +function ff_hevc_h_loop_filter_chroma_\bitdepth\()_neon, export=1 + hevc_loop_filter_chroma_start \bitdepth + sub x0, x0, x1, lsl #1 +.if \bitdepth > 8 + ld1 {v0.8h}, [x0], x1 + ld1 {v1.8h}, [x0], x1 + ld1 {v2.8h}, [x0], x1 + ld1 {v3.8h}, [x0] +.else + ld1 {v0.8b}, [x0], x1 + ld1 {v1.8b}, [x0], x1 + ld1 {v2.8b}, [x0], x1 + ld1 {v3.8b}, [x0] +.endif + sub x0, x0, x1, lsl #1 + bl hevc_loop_filter_chroma_body_\bitdepth\()_neon +.if \bitdepth > 8 + st1 {v1.8h}, [x0], x1 + st1 {v2.8h}, [x0] +.else + st1 {v1.8b}, [x0], x1 + st1 {v2.8b}, [x0] +.endif +1: ret x4 +endfunc +.endm + +.macro hevc_v_loop_filter_chroma bitdepth +function ff_hevc_v_loop_filter_chroma_\bitdepth\()_neon, export=1 + hevc_loop_filter_chroma_start \bitdepth +.if \bitdepth > 8 + sub x0, x0, #4 + add x3, x0, x1 + lsl x1, x1, #1 + ld1 {v0.d}[0], [x0], x1 + ld1 {v1.d}[0], [x3], x1 + ld1 {v2.d}[0], [x0], x1 + ld1 {v3.d}[0], [x3], x1 + ld1 {v0.d}[1], [x0], x1 + ld1 {v1.d}[1], [x3], x1 + ld1 {v2.d}[1], [x0], x1 + ld1 {v3.d}[1], [x3], x1 + transpose_4x8H v0, v1, v2, v3, v28, v29, v30, v31 +.else + sub x0, x0, #2 + add x3, x0, x1 + lsl x1, x1, #1 + ld1 {v0.s}[0], [x0], x1 + ld1 {v1.s}[0], [x3], x1 + ld1 {v2.s}[0], [x0], x1 + ld1 {v3.s}[0], [x3], x1 + ld1 {v0.s}[1], [x0], x1 + ld1 {v1.s}[1], [x3], x1 + ld1 {v2.s}[1], [x0], x1 + ld1 {v3.s}[1], [x3], x1 + transpose_4x8B v0, v1, v2, v3, v28, v29, v30, v31 +.endif + sub x0, x0, x1, lsl #2 + sub x3, x3, x1, lsl #2 + bl hevc_loop_filter_chroma_body_\bitdepth\()_neon +.if \bitdepth > 8 + transpose_4x8H v0, v1, v2, v3, v28, v29, v30, v31 + st1 {v0.d}[0], [x0], x1 + st1 {v1.d}[0], [x3], x1 + st1 {v2.d}[0], [x0], x1 + st1 {v3.d}[0], [x3], x1 + st1 {v0.d}[1], [x0], x1 + st1 {v1.d}[1], [x3], x1 + st1 {v2.d}[1], [x0], x1 + st1 {v3.d}[1], [x3] +.else + transpose_4x8B v0, v1, v2, v3, v28, v29, v30, v31 + st1 {v0.s}[0], [x0], x1 + st1 {v1.s}[0], [x3], x1 + st1 {v2.s}[0], [x0], x1 + st1 {v3.s}[0], [x3], x1 + st1 {v0.s}[1], [x0], x1 + st1 {v1.s}[1], [x3], x1 + st1 {v2.s}[1], [x0], x1 + st1 {v3.s}[1], [x3] +.endif +1: ret x4 +endfunc +.endm + +hevc_h_loop_filter_chroma 8 +hevc_h_loop_filter_chroma 10 +hevc_h_loop_filter_chroma 12 + +hevc_v_loop_filter_chroma 8 +hevc_v_loop_filter_chroma 10 +hevc_v_loop_filter_chroma 12 diff --git a/libavcodec/aarch64/hevcdsp_init_aarch64.c b/libavcodec/aarch64/hevcdsp_init_aarch64.c index 1deefca0a25..a923bae35c3 100644 --- a/libavcodec/aarch64/hevcdsp_init_aarch64.c +++ b/libavcodec/aarch64/hevcdsp_init_aarch64.c @@ -25,6 +25,18 @@ #include "libavutil/aarch64/cpu.h" #include "libavcodec/hevcdsp.h" +void ff_hevc_v_loop_filter_chroma_8_neon(uint8_t *_pix, ptrdiff_t _stride, + const int *_tc, const uint8_t *_no_p, const uint8_t *_no_q); +void ff_hevc_v_loop_filter_chroma_10_neon(uint8_t *_pix, ptrdiff_t _stride, + const int *_tc, const uint8_t *_no_p, const uint8_t *_no_q); +void ff_hevc_v_loop_filter_chroma_12_neon(uint8_t *_pix, ptrdiff_t _stride, + const int *_tc, const uint8_t *_no_p, const uint8_t *_no_q); +void ff_hevc_h_loop_filter_chroma_8_neon(uint8_t *_pix, ptrdiff_t _stride, + const int *_tc, const uint8_t *_no_p, const uint8_t *_no_q); +void ff_hevc_h_loop_filter_chroma_10_neon(uint8_t *_pix, ptrdiff_t _stride, + const int *_tc, const uint8_t *_no_p, const uint8_t *_no_q); +void ff_hevc_h_loop_filter_chroma_12_neon(uint8_t *_pix, ptrdiff_t _stride, + const int *_tc, const uint8_t *_no_p, const uint8_t *_no_q); void ff_hevc_add_residual_4x4_8_neon(uint8_t *_dst, const int16_t *coeffs, ptrdiff_t stride); void ff_hevc_add_residual_4x4_10_neon(uint8_t *_dst, const int16_t *coeffs, @@ -117,6 +129,8 @@ av_cold void ff_hevc_dsp_init_aarch64(HEVCDSPContext *c, const int bit_depth) if (!have_neon(av_get_cpu_flags())) return; if (bit_depth == 8) { + c->hevc_h_loop_filter_chroma = ff_hevc_h_loop_filter_chroma_8_neon; + c->hevc_v_loop_filter_chroma = ff_hevc_v_loop_filter_chroma_8_neon; c->add_residual[0] = ff_hevc_add_residual_4x4_8_neon; c->add_residual[1] = ff_hevc_add_residual_8x8_8_neon; c->add_residual[2] = ff_hevc_add_residual_16x16_8_neon; @@ -167,6 +181,8 @@ av_cold void ff_hevc_dsp_init_aarch64(HEVCDSPContext *c, const int bit_depth) c->put_hevc_qpel_bi[9][0][1] = ff_hevc_put_hevc_qpel_bi_h16_8_neon; } if (bit_depth == 10) { + c->hevc_h_loop_filter_chroma = ff_hevc_h_loop_filter_chroma_10_neon; + c->hevc_v_loop_filter_chroma = ff_hevc_v_loop_filter_chroma_10_neon; c->add_residual[0] = ff_hevc_add_residual_4x4_10_neon; c->add_residual[1] = ff_hevc_add_residual_8x8_10_neon; c->add_residual[2] = ff_hevc_add_residual_16x16_10_neon; @@ -180,6 +196,8 @@ av_cold void ff_hevc_dsp_init_aarch64(HEVCDSPContext *c, const int bit_depth) c->idct_dc[3] = ff_hevc_idct_32x32_dc_10_neon; } if (bit_depth == 12) { + c->hevc_h_loop_filter_chroma = ff_hevc_h_loop_filter_chroma_12_neon; + c->hevc_v_loop_filter_chroma = ff_hevc_v_loop_filter_chroma_12_neon; c->add_residual[0] = ff_hevc_add_residual_4x4_12_neon; c->add_residual[1] = ff_hevc_add_residual_8x8_12_neon; c->add_residual[2] = ff_hevc_add_residual_16x16_12_neon; From 88de01d878167cbff9af32c0b7366e0aae3db2bd Mon Sep 17 00:00:00 2001 From: James Almer Date: Wed, 5 Apr 2023 12:16:29 -0300 Subject: [PATCH 0586/2172] avformat/matroskadec: parse all BlockAdditionMapping elements and export the correct value as BlockAdditional side data Signed-off-by: James Almer --- libavformat/matroskadec.c | 57 ++++++++++++++++++++++++++++++--------- 1 file changed, 44 insertions(+), 13 deletions(-) diff --git a/libavformat/matroskadec.c b/libavformat/matroskadec.c index 3c7c2b7c706..e19a837902f 100644 --- a/libavformat/matroskadec.c +++ b/libavformat/matroskadec.c @@ -2392,17 +2392,23 @@ static int mkv_parse_block_addition_mappings(AVFormatContext *s, AVStream *st, M MatroskaBlockAdditionMapping *mapping = &mappings[i]; switch (mapping->type) { + case MATROSKA_BLOCK_ADD_ID_TYPE_DEFAULT: + av_log(s, AV_LOG_DEBUG, + "Explicit block Addition Mapping type \"Use BlockAddIDValue\", value %"PRIu64"," + " name \"%s\" found.\n", mapping->value, mapping->name ? mapping->name : ""); + break; + case MATROSKA_BLOCK_ADD_ID_TYPE_OPAQUE: case MATROSKA_BLOCK_ADD_ID_TYPE_ITU_T_T35: - if (mapping->value != MATROSKA_BLOCK_ADD_ID_ITU_T_T35) { + if (mapping->value != mapping->type) { int strict = s->strict_std_compliance >= FF_COMPLIANCE_STRICT; av_log(s, strict ? AV_LOG_ERROR : AV_LOG_WARNING, "Invalid Block Addition Value 0x%"PRIx64" for Block Addition Mapping Type " - "\"ITU T.35 metadata\"\n", mapping->value); - if (!strict) - break; - return AVERROR_INVALIDDATA; + "0x%"PRIx64", name \"%s\"\n", mapping->value, mapping->type, + mapping->name ? mapping->name : ""); + if (strict) + return AVERROR_INVALIDDATA; } - track->blockaddid_itu_t_t35 = 1; + track->blockaddid_itu_t_t35 |= mapping->type == MATROSKA_BLOCK_ADD_ID_TYPE_ITU_T_T35; break; case MATROSKA_BLOCK_ADD_ID_TYPE_DVCC: case MATROSKA_BLOCK_ADD_ID_TYPE_DVVC: @@ -2412,8 +2418,18 @@ static int mkv_parse_block_addition_mappings(AVFormatContext *s, AVStream *st, M break; default: av_log(s, AV_LOG_DEBUG, - "Unknown block additional mapping type 0x%"PRIx64", value %"PRIu64", name \"%s\"\n", + "Unknown Block Addition Mapping type 0x%"PRIx64", value %"PRIu64", name \"%s\"\n", mapping->type, mapping->value, mapping->name ? mapping->name : ""); + if (mapping->value < 2) { + int strict = s->strict_std_compliance >= FF_COMPLIANCE_STRICT; + av_log(s, strict ? AV_LOG_ERROR : AV_LOG_WARNING, + "Invalid Block Addition value 0x%"PRIu64" for unknown Block Addition Mapping " + "type %"PRIx64", name \"%s\"\n", mapping->value, mapping->type, + mapping->name ? mapping->name : ""); + if (strict) + return AVERROR_INVALIDDATA; + } + break; } } @@ -3638,11 +3654,28 @@ static int matroska_parse_block_additional(MatroskaDemuxContext *matroska, MatroskaTrack *track, AVPacket *pkt, const uint8_t *data, int size, uint64_t id) { + const EbmlList *mappings_list = &track->block_addition_mappings; + MatroskaBlockAdditionMapping *mappings = mappings_list->elem, *mapping = NULL; uint8_t *side_data; int res; + for (int i = 0; i < mappings_list->nb_elem; i++) { + if (id != mappings[i].value) + continue; + mapping = &mappings[i]; + break; + } + + if (id != 1 && !matroska->is_webm && !mapping) { + av_log(matroska->ctx, AV_LOG_WARNING, "BlockAddID %"PRIu64" has no mapping. Skipping\n", id); + return 0; + } + + if (mapping && mapping->type) + id = mapping->type; + switch (id) { - case 4: { + case MATROSKA_BLOCK_ADD_ID_TYPE_ITU_T_T35: { GetByteContext bc; int country_code, provider_code; int provider_oriented_code, application_identifier; @@ -3678,13 +3711,9 @@ static int matroska_parse_block_additional(MatroskaDemuxContext *matroska, av_free(hdrplus); return res; } - - return 0; - } - default: break; } - + default: side_data = av_packet_new_side_data(pkt, AV_PKT_DATA_MATROSKA_BLOCKADDITIONAL, size + (size_t)8); if (!side_data) @@ -3692,6 +3721,8 @@ static int matroska_parse_block_additional(MatroskaDemuxContext *matroska, AV_WB64(side_data, id); memcpy(side_data + 8, data, size); + break; + } return 0; } From 2133cadfcf9a613cf2c0060f9896bba49dabfba4 Mon Sep 17 00:00:00 2001 From: James Almer Date: Fri, 7 Apr 2023 11:57:17 -0300 Subject: [PATCH 0587/2172] avformat/matroskadec: reindent after the previous commit Signed-off-by: James Almer --- libavformat/matroskadec.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/libavformat/matroskadec.c b/libavformat/matroskadec.c index e19a837902f..d6ad7783993 100644 --- a/libavformat/matroskadec.c +++ b/libavformat/matroskadec.c @@ -3714,13 +3714,13 @@ static int matroska_parse_block_additional(MatroskaDemuxContext *matroska, break; } default: - side_data = av_packet_new_side_data(pkt, AV_PKT_DATA_MATROSKA_BLOCKADDITIONAL, - size + (size_t)8); - if (!side_data) - return AVERROR(ENOMEM); + side_data = av_packet_new_side_data(pkt, AV_PKT_DATA_MATROSKA_BLOCKADDITIONAL, + size + (size_t)8); + if (!side_data) + return AVERROR(ENOMEM); - AV_WB64(side_data, id); - memcpy(side_data + 8, data, size); + AV_WB64(side_data, id); + memcpy(side_data + 8, data, size); break; } From 6d31619af2826adfe5aa71990cebafa8cbd6ecde Mon Sep 17 00:00:00 2001 From: James Almer Date: Fri, 7 Apr 2023 13:59:33 -0300 Subject: [PATCH 0588/2172] avformat/matroskadec: validate MaxBlockAdditionID in the presence of BlockAdditions The Matroska spec requires it to be equal to the highest BlockAddID value in a BlockAdditions, but being purely an informative element, only abort if strict compliance is requested, as demuxing is otherwise unaffected. Signed-off-by: James Almer --- libavformat/matroskadec.c | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/libavformat/matroskadec.c b/libavformat/matroskadec.c index d6ad7783993..a3846106bfa 100644 --- a/libavformat/matroskadec.c +++ b/libavformat/matroskadec.c @@ -3659,6 +3659,16 @@ static int matroska_parse_block_additional(MatroskaDemuxContext *matroska, uint8_t *side_data; int res; + if (!matroska->is_webm && track->max_block_additional_id && id > track->max_block_additional_id) { + int strict = matroska->ctx->strict_std_compliance >= FF_COMPLIANCE_STRICT; + av_log(matroska->ctx, strict ? AV_LOG_ERROR : AV_LOG_WARNING, + "BlockAddID %"PRIu64" is higher than the reported MaxBlockAdditionID %"PRIu64" " + "for Track with TrackNumber %"PRIu64"\n", id, track->max_block_additional_id, + track->num); + if (strict) + return AVERROR_INVALIDDATA; + } + for (int i = 0; i < mappings_list->nb_elem; i++) { if (id != mappings[i].value) continue; @@ -3767,6 +3777,17 @@ static int matroska_parse_frame(MatroskaDemuxContext *matroska, if (!pkt_size && !nb_blockmore) goto no_output; + if (!matroska->is_webm && nb_blockmore && !track->max_block_additional_id) { + int strict = matroska->ctx->strict_std_compliance >= FF_COMPLIANCE_STRICT; + av_log(matroska->ctx, strict ? AV_LOG_ERROR : AV_LOG_WARNING, + "Unexpected BlockAdditions found in a Block from Track with TrackNumber %"PRIu64" " + "where MaxBlockAdditionID is 0\n", track->num); + if (strict) { + res = AVERROR_INVALIDDATA; + goto fail; + } + } + if (!buf) pkt->buf = av_buffer_create(pkt_data, pkt_size + AV_INPUT_BUFFER_PADDING_SIZE, NULL, NULL, 0); From e1f691b2e82c38d3c87a22a0e58f8a3e41c67428 Mon Sep 17 00:00:00 2001 From: James Almer Date: Sat, 8 Apr 2023 10:21:56 -0300 Subject: [PATCH 0589/2172] avformat/matroskadec: remove itu_t_t35 flag from MatroskaTrack It's no longer needed after 88de01d878. Signed-off-by: James Almer --- libavformat/matroskadec.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/libavformat/matroskadec.c b/libavformat/matroskadec.c index a3846106bfa..b3922ab8b02 100644 --- a/libavformat/matroskadec.c +++ b/libavformat/matroskadec.c @@ -285,7 +285,6 @@ typedef struct MatroskaTrack { int needs_decoding; uint64_t max_block_additional_id; EbmlList block_addition_mappings; - int blockaddid_itu_t_t35; uint32_t palette[AVPALETTE_COUNT]; int has_palette; @@ -2408,7 +2407,6 @@ static int mkv_parse_block_addition_mappings(AVFormatContext *s, AVStream *st, M if (strict) return AVERROR_INVALIDDATA; } - track->blockaddid_itu_t_t35 |= mapping->type == MATROSKA_BLOCK_ADD_ID_TYPE_ITU_T_T35; break; case MATROSKA_BLOCK_ADD_ID_TYPE_DVCC: case MATROSKA_BLOCK_ADD_ID_TYPE_DVVC: @@ -2850,8 +2848,6 @@ static int matroska_parse_tracks(AVFormatContext *s) /* we don't need any value stored in CodecPrivate. make sure that it's not exported as extradata. */ track->codec_priv.size = 0; - /* Assume BlockAddID 4 is ITU-T T.35 metadata if WebM */ - track->blockaddid_itu_t_t35 = matroska->is_webm; } else if (codec_id == AV_CODEC_ID_ARIB_CAPTION && track->codec_priv.size == 3) { int component_tag = track->codec_priv.data[0]; int data_component_id = AV_RB16(track->codec_priv.data + 1); @@ -3692,7 +3688,7 @@ static int matroska_parse_block_additional(MatroskaDemuxContext *matroska, size_t hdrplus_size; AVDynamicHDRPlus *hdrplus; - if (!track->blockaddid_itu_t_t35 || size < 6) + if (size < 6) break; //ignore bytestream2_init(&bc, data, size); From bda44f0f39e8ee646e54f15989d7845f4bf58d26 Mon Sep 17 00:00:00 2001 From: James Almer Date: Sun, 19 Mar 2023 11:32:38 -0300 Subject: [PATCH 0590/2172] avformat/matroskaenc: support writing Dynamic HDR10+ packet side data Signed-off-by: James Almer --- libavformat/matroskaenc.c | 79 ++++++++++++++++--- tests/ref/fate/aac-autobsf-adtstoasc | 4 +- tests/ref/fate/matroska-avoid-negative-ts | 4 +- tests/ref/fate/matroska-dovi-write-config7 | 4 +- tests/ref/fate/matroska-dovi-write-config8 | 4 +- tests/ref/fate/matroska-dvbsub-remux | 4 +- tests/ref/fate/matroska-encoding-delay | 14 ++-- tests/ref/fate/matroska-flac-extradata-update | 4 +- tests/ref/fate/matroska-h264-remux | 4 +- .../fate/matroska-mastering-display-metadata | 4 +- tests/ref/fate/matroska-move-cues-to-front | 4 +- tests/ref/fate/matroska-mpegts-remux | 4 +- tests/ref/fate/matroska-ms-mode | 4 +- tests/ref/fate/matroska-ogg-opus-remux | 10 +-- tests/ref/fate/matroska-opus-remux | 10 +-- tests/ref/fate/matroska-pgs-remux | 4 +- tests/ref/fate/matroska-pgs-remux-durations | 4 +- tests/ref/fate/matroska-qt-mode | 4 +- tests/ref/fate/matroska-spherical-mono-remux | 4 +- tests/ref/fate/matroska-vp8-alpha-remux | 4 +- tests/ref/fate/matroska-zero-length-block | 4 +- tests/ref/fate/rgb24-mkv | 4 +- tests/ref/fate/shortest-sub | 4 +- tests/ref/lavf-fate/av1.mkv | 4 +- tests/ref/lavf/mka | 4 +- tests/ref/lavf/mkv | 4 +- tests/ref/lavf/mkv_attachment | 4 +- tests/ref/seek/lavf-mkv | 44 +++++------ 28 files changed, 151 insertions(+), 98 deletions(-) diff --git a/libavformat/matroskaenc.c b/libavformat/matroskaenc.c index 3b0998ecc88..59ed5be951d 100644 --- a/libavformat/matroskaenc.c +++ b/libavformat/matroskaenc.c @@ -44,6 +44,7 @@ #include "libavutil/channel_layout.h" #include "libavutil/crc.h" #include "libavutil/dict.h" +#include "libavutil/hdr_dynamic_metadata.h" #include "libavutil/intfloat.h" #include "libavutil/intreadwrite.h" #include "libavutil/lfg.h" @@ -59,6 +60,7 @@ #include "libavcodec/av1.h" #include "libavcodec/avcodec.h" +#include "libavcodec/bytestream.h" #include "libavcodec/codec_desc.h" #include "libavcodec/xiph.h" #include "libavcodec/mpeg4audio.h" @@ -1612,6 +1614,10 @@ static void mkv_write_blockadditionmapping(AVFormatContext *s, MatroskaMuxContex // we either write the default value here, or a void element. Either of them will // be overwritten when finishing the track. put_ebml_uint(mkv->track.bc, MATROSKA_ID_TRACKMAXBLKADDID, 0); + // Similarly, reserve space for an eventual HDR10+ ITU T.35 metadata BlockAdditionMapping. + put_ebml_void(pb, 3 /* BlockAdditionMapping */ + + 4 /* BlockAddIDValue */ + + 4 /* BlockAddIDType */); } if (dovi && dovi->dv_profile <= 10) { @@ -2618,17 +2624,27 @@ static int webm_reformat_vtt(MatroskaMuxContext *mkv, AVIOContext *pb, return 0; } +static void mkv_write_blockadditional(EbmlWriter *writer, const uint8_t *buf, + size_t size, uint64_t additional_id) +{ + ebml_writer_open_master(writer, MATROSKA_ID_BLOCKMORE); + ebml_writer_add_uint(writer, MATROSKA_ID_BLOCKADDID, additional_id); + ebml_writer_add_bin (writer, MATROSKA_ID_BLOCKADDITIONAL, buf, size); + ebml_writer_close_master(writer); +} + static int mkv_write_block(void *logctx, MatroskaMuxContext *mkv, AVIOContext *pb, const AVCodecParameters *par, mkv_track *track, const AVPacket *pkt, int keyframe, int64_t ts, uint64_t duration, int force_blockgroup, int64_t relative_packet_pos) { - uint8_t *side_data; + uint8_t *side_data, *buf = NULL; size_t side_data_size; uint64_t additional_id; unsigned track_number = track->track_num; - EBML_WRITER(9); + int ret; + EBML_WRITER(13); mkv->cur_block.track = track; mkv->cur_block.pkt = pkt; @@ -2663,24 +2679,52 @@ static int mkv_write_block(void *logctx, MatroskaMuxContext *mkv, } } + ebml_writer_open_master(&writer, MATROSKA_ID_BLOCKADDITIONS); side_data = av_packet_get_side_data(pkt, AV_PKT_DATA_MATROSKA_BLOCKADDITIONAL, &side_data_size); if (side_data && side_data_size >= 8 && // Only the Codec-specific BlockMore (id == 1) is currently supported. (additional_id = AV_RB64(side_data)) == MATROSKA_BLOCK_ADD_ID_TYPE_OPAQUE) { - ebml_writer_open_master(&writer, MATROSKA_ID_BLOCKADDITIONS); - ebml_writer_open_master(&writer, MATROSKA_ID_BLOCKMORE); - /* Until dbc50f8a our demuxer used a wrong default value - * of BlockAddID, so we write it unconditionally. */ - ebml_writer_add_uint(&writer, MATROSKA_ID_BLOCKADDID, additional_id); - ebml_writer_add_bin (&writer, MATROSKA_ID_BLOCKADDITIONAL, - side_data + 8, side_data_size - 8); - ebml_writer_close_master(&writer); - ebml_writer_close_master(&writer); - track->max_blockaddid = additional_id; + mkv_write_blockadditional(&writer, side_data + 8, side_data_size - 8, + additional_id); + track->max_blockaddid = FFMAX(track->max_blockaddid, additional_id); + } + + side_data = av_packet_get_side_data(pkt, + AV_PKT_DATA_DYNAMIC_HDR10_PLUS, + &side_data_size); + if (side_data && side_data_size) { + uint8_t *payload; + size_t payload_size, buf_size; + int ret = av_dynamic_hdr_plus_to_t35((AVDynamicHDRPlus *)side_data, NULL, + &payload_size); + if (ret < 0) + return ret; + + buf_size = payload_size + 6; + buf = payload = av_malloc(buf_size); + if (!buf) + return AVERROR(ENOMEM); + + bytestream_put_byte(&payload, 0xB5); // country_code + bytestream_put_be16(&payload, 0x3C); // provider_code + bytestream_put_be16(&payload, 0x01); // provider_oriented_code + bytestream_put_byte(&payload, 0x04); // application_identifier + + ret = av_dynamic_hdr_plus_to_t35((AVDynamicHDRPlus *)side_data, &payload, + &payload_size); + if (ret < 0) + return ret; + + mkv_write_blockadditional(&writer, buf, buf_size, + MATROSKA_BLOCK_ADD_ID_ITU_T_T35); + track->max_blockaddid = FFMAX(track->max_blockaddid, + MATROSKA_BLOCK_ADD_ID_ITU_T_T35); } + ebml_writer_close_or_discard_master(&writer); + if (!force_blockgroup && writer.nb_elements == 2) { /* Nothing except the BlockGroup + Block. Can use a SimpleBlock. */ writer.elements++; // Skip the BlockGroup. @@ -2693,7 +2737,10 @@ static int mkv_write_block(void *logctx, MatroskaMuxContext *mkv, ebml_writer_add_sint(&writer, MATROSKA_ID_BLOCKREFERENCE, track->last_timestamp - ts); - return ebml_writer_write(&writer, pb); + ret = ebml_writer_write(&writer, pb); + av_free(buf); + + return ret; } static int mkv_end_cluster(AVFormatContext *s) @@ -3095,6 +3142,12 @@ static int mkv_write_trailer(AVFormatContext *s) avio_seek(mkv->track.bc, track->blockadditionmapping_offset, SEEK_SET); put_ebml_uint(mkv->track.bc, MATROSKA_ID_TRACKMAXBLKADDID, track->max_blockaddid); + if (track->max_blockaddid == MATROSKA_BLOCK_ADD_ID_ITU_T_T35) { + ebml_master mapping_master = start_ebml_master(mkv->track.bc, MATROSKA_ID_TRACKBLKADDMAPPING, 8); + put_ebml_uint(mkv->track.bc, MATROSKA_ID_BLKADDIDTYPE, MATROSKA_BLOCK_ADD_ID_TYPE_ITU_T_T35); + put_ebml_uint(mkv->track.bc, MATROSKA_ID_BLKADDIDVALUE, MATROSKA_BLOCK_ADD_ID_ITU_T_T35); + end_ebml_master(mkv->track.bc, mapping_master); + } } avio_seek(pb, mkv->track.pos, SEEK_SET); diff --git a/tests/ref/fate/aac-autobsf-adtstoasc b/tests/ref/fate/aac-autobsf-adtstoasc index 76125083b6e..12b80ef6bd6 100644 --- a/tests/ref/fate/aac-autobsf-adtstoasc +++ b/tests/ref/fate/aac-autobsf-adtstoasc @@ -1,5 +1,5 @@ -3d4465a7ea2cfba31af737e288c892fe *tests/data/fate/aac-autobsf-adtstoasc.matroska -6646 tests/data/fate/aac-autobsf-adtstoasc.matroska +68cb46874ca6029d3ae3a184b4a71b04 *tests/data/fate/aac-autobsf-adtstoasc.matroska +6657 tests/data/fate/aac-autobsf-adtstoasc.matroska #extradata 0: 2, 0x0030001c #tb 0: 1/1000 #media_type 0: audio diff --git a/tests/ref/fate/matroska-avoid-negative-ts b/tests/ref/fate/matroska-avoid-negative-ts index 73616cbc5a4..dcde937d52f 100644 --- a/tests/ref/fate/matroska-avoid-negative-ts +++ b/tests/ref/fate/matroska-avoid-negative-ts @@ -1,5 +1,5 @@ -ff83530bf89f9ab1df0d181bb848c475 *tests/data/fate/matroska-avoid-negative-ts.matroska -973063 tests/data/fate/matroska-avoid-negative-ts.matroska +6a1a524a5700de7b94bce5a283bbe8b9 *tests/data/fate/matroska-avoid-negative-ts.matroska +973085 tests/data/fate/matroska-avoid-negative-ts.matroska #extradata 0: 22, 0x2885037c #tb 0: 1/1000 #media_type 0: video diff --git a/tests/ref/fate/matroska-dovi-write-config7 b/tests/ref/fate/matroska-dovi-write-config7 index 8b40848f4a1..ef4c87d8858 100644 --- a/tests/ref/fate/matroska-dovi-write-config7 +++ b/tests/ref/fate/matroska-dovi-write-config7 @@ -1,5 +1,5 @@ -b4db571fe6304f159a0383a38c9c0cee *tests/data/fate/matroska-dovi-write-config7.matroska -72680 tests/data/fate/matroska-dovi-write-config7.matroska +82581e39700ff479516c33402e8b1d5d *tests/data/fate/matroska-dovi-write-config7.matroska +72702 tests/data/fate/matroska-dovi-write-config7.matroska #extradata 0: 116, 0x2b8d1669 #extradata 1: 116, 0x2b8d1669 #tb 0: 1/1000 diff --git a/tests/ref/fate/matroska-dovi-write-config8 b/tests/ref/fate/matroska-dovi-write-config8 index c36d3a8a07e..bb22563eee1 100644 --- a/tests/ref/fate/matroska-dovi-write-config8 +++ b/tests/ref/fate/matroska-dovi-write-config8 @@ -1,5 +1,5 @@ -8c77c1d18ee58a8923c411d3ba006a46 *tests/data/fate/matroska-dovi-write-config8.matroska -3600584 tests/data/fate/matroska-dovi-write-config8.matroska +09ff3c0a038eec0cdf4773929b24f41a *tests/data/fate/matroska-dovi-write-config8.matroska +3600606 tests/data/fate/matroska-dovi-write-config8.matroska #extradata 0: 551, 0xa18acf66 #extradata 1: 2, 0x00340022 #tb 0: 1/1000 diff --git a/tests/ref/fate/matroska-dvbsub-remux b/tests/ref/fate/matroska-dvbsub-remux index 03341d96681..b5bb0283436 100644 --- a/tests/ref/fate/matroska-dvbsub-remux +++ b/tests/ref/fate/matroska-dvbsub-remux @@ -1,5 +1,5 @@ -5d1591e9abd7e1373d43bc776572aaf7 *tests/data/fate/matroska-dvbsub-remux.matroska -39018 tests/data/fate/matroska-dvbsub-remux.matroska +7154511243fd7edb695c159bb12a0948 *tests/data/fate/matroska-dvbsub-remux.matroska +39041 tests/data/fate/matroska-dvbsub-remux.matroska #extradata 0: 5, 0x00bb0064 #extradata 1: 5, 0x00bb0064 #tb 0: 1/1000 diff --git a/tests/ref/fate/matroska-encoding-delay b/tests/ref/fate/matroska-encoding-delay index 401de4facf3..086fe94e93b 100644 --- a/tests/ref/fate/matroska-encoding-delay +++ b/tests/ref/fate/matroska-encoding-delay @@ -1,5 +1,5 @@ -1f6f9c0fbaba0f128acbea296cec1887 *tests/data/fate/matroska-encoding-delay.matroska -961229 tests/data/fate/matroska-encoding-delay.matroska +ce2ab14d45217a043f9f50fe6adfe5ce *tests/data/fate/matroska-encoding-delay.matroska +961251 tests/data/fate/matroska-encoding-delay.matroska #extradata 0: 22, 0x32ea0490 #tb 0: 1/1000 #media_type 0: video @@ -32,7 +32,7 @@ dts_time=-0.010000 duration=24 duration_time=0.024000 size=1152 -pos=1246 +pos=1268 flags=K__ [/PACKET] [PACKET] @@ -45,7 +45,7 @@ dts_time=0.000000 duration=40 duration_time=0.040000 size=237628 -pos=2406 +pos=2428 flags=K__ [/PACKET] [PACKET] @@ -58,7 +58,7 @@ dts_time=0.014000 duration=24 duration_time=0.024000 size=1152 -pos=240041 +pos=240063 flags=K__ [/PACKET] [PACKET] @@ -71,7 +71,7 @@ dts_time=0.038000 duration=24 duration_time=0.024000 size=1152 -pos=241216 +pos=241238 flags=K__ [/PACKET] [PACKET] @@ -84,7 +84,7 @@ dts_time=0.040000 duration=40 duration_time=0.040000 size=238066 -pos=242376 +pos=242398 flags=K__ [/PACKET] [STREAM] diff --git a/tests/ref/fate/matroska-flac-extradata-update b/tests/ref/fate/matroska-flac-extradata-update index d6713aaafaf..37e0367297e 100644 --- a/tests/ref/fate/matroska-flac-extradata-update +++ b/tests/ref/fate/matroska-flac-extradata-update @@ -1,5 +1,5 @@ -fdbfdc51b519fd5e8f425aca1e7b8704 *tests/data/fate/matroska-flac-extradata-update.matroska -1807 tests/data/fate/matroska-flac-extradata-update.matroska +8a75767c14e63e7d15291c5c4918a661 *tests/data/fate/matroska-flac-extradata-update.matroska +1840 tests/data/fate/matroska-flac-extradata-update.matroska #extradata 0: 34, 0x93650c81 #extradata 1: 34, 0x93650c81 #extradata 2: 34, 0x93650c81 diff --git a/tests/ref/fate/matroska-h264-remux b/tests/ref/fate/matroska-h264-remux index 9a9a98217c6..bfc80a273f4 100644 --- a/tests/ref/fate/matroska-h264-remux +++ b/tests/ref/fate/matroska-h264-remux @@ -1,5 +1,5 @@ -fa3352ef6d3abd7d93f8627981a53f6f *tests/data/fate/matroska-h264-remux.matroska -2036049 tests/data/fate/matroska-h264-remux.matroska +38ede644af311f443d7446600f25a8e3 *tests/data/fate/matroska-h264-remux.matroska +2036093 tests/data/fate/matroska-h264-remux.matroska #tb 0: 1/25 #media_type 0: video #codec_id 0: rawvideo diff --git a/tests/ref/fate/matroska-mastering-display-metadata b/tests/ref/fate/matroska-mastering-display-metadata index 95df3594c75..c63365c181d 100644 --- a/tests/ref/fate/matroska-mastering-display-metadata +++ b/tests/ref/fate/matroska-mastering-display-metadata @@ -1,5 +1,5 @@ -e9a5f7314d6ae2ef16713335df2b5903 *tests/data/fate/matroska-mastering-display-metadata.matroska -1669571 tests/data/fate/matroska-mastering-display-metadata.matroska +a4924bfe22ed0c72b0eddc353bbee10c *tests/data/fate/matroska-mastering-display-metadata.matroska +1669615 tests/data/fate/matroska-mastering-display-metadata.matroska #extradata 0: 4, 0x040901a3 #extradata 3: 200, 0x506463a8 #tb 0: 1/1000 diff --git a/tests/ref/fate/matroska-move-cues-to-front b/tests/ref/fate/matroska-move-cues-to-front index 79ccc2fd935..ce3b9fce928 100644 --- a/tests/ref/fate/matroska-move-cues-to-front +++ b/tests/ref/fate/matroska-move-cues-to-front @@ -1,5 +1,5 @@ -74a5ed3f0b14112322c8bf3e94d6e98b *tests/data/fate/matroska-move-cues-to-front.matroska -23210297 tests/data/fate/matroska-move-cues-to-front.matroska +03ed7fcf99dd993ebb9bc9c6c93ba73e *tests/data/fate/matroska-move-cues-to-front.matroska +23210319 tests/data/fate/matroska-move-cues-to-front.matroska #tb 0: 1/1000 #media_type 0: audio #codec_id 0: pcm_s24be diff --git a/tests/ref/fate/matroska-mpegts-remux b/tests/ref/fate/matroska-mpegts-remux index af41b57af16..1f211dfc298 100644 --- a/tests/ref/fate/matroska-mpegts-remux +++ b/tests/ref/fate/matroska-mpegts-remux @@ -1,5 +1,5 @@ -ca1b91e49b6e238b641007c186d8f424 *tests/data/fate/matroska-mpegts-remux.matroska -6502 tests/data/fate/matroska-mpegts-remux.matroska +53424355db1d78441b62ad114d6ea502 *tests/data/fate/matroska-mpegts-remux.matroska +6524 tests/data/fate/matroska-mpegts-remux.matroska #tb 0: 1/1000 #media_type 0: audio #codec_id 0: ac3 diff --git a/tests/ref/fate/matroska-ms-mode b/tests/ref/fate/matroska-ms-mode index 0a42ab0748a..b12e9ac9f27 100644 --- a/tests/ref/fate/matroska-ms-mode +++ b/tests/ref/fate/matroska-ms-mode @@ -1,5 +1,5 @@ -7f0b825626a028765098222816ba56b8 *tests/data/fate/matroska-ms-mode.matroska -413094 tests/data/fate/matroska-ms-mode.matroska +f3b1b804d40d70d012e85ba6d03ea8f1 *tests/data/fate/matroska-ms-mode.matroska +413116 tests/data/fate/matroska-ms-mode.matroska #extradata 0: 40, 0x54290c93 #extradata 1: 114, 0xb6c80771 #tb 0: 1/1000 diff --git a/tests/ref/fate/matroska-ogg-opus-remux b/tests/ref/fate/matroska-ogg-opus-remux index cd3eade361f..c70c58a697b 100644 --- a/tests/ref/fate/matroska-ogg-opus-remux +++ b/tests/ref/fate/matroska-ogg-opus-remux @@ -1,5 +1,5 @@ -b602a1a4aaa4fbca4b8aaf39b66d7235 *tests/data/fate/matroska-ogg-opus-remux.matroska -10204 tests/data/fate/matroska-ogg-opus-remux.matroska +d891990279e6ba202448f9fffde52d3f *tests/data/fate/matroska-ogg-opus-remux.matroska +10215 tests/data/fate/matroska-ogg-opus-remux.matroska #extradata 0: 19, 0x399c0471 #tb 0: 1/1000 #media_type 0: audio @@ -57,7 +57,7 @@ dts_time=-0.007000 duration=20 duration_time=0.020000 size=402 -pos=544 +pos=555 flags=K__ [/PACKET] [PACKET] @@ -70,7 +70,7 @@ dts_time=0.013000 duration=20 duration_time=0.020000 size=216 -pos=953 +pos=964 flags=K__ [/PACKET] [PACKET] @@ -83,7 +83,7 @@ dts_time=0.033000 duration=20 duration_time=0.020000 size=215 -pos=1176 +pos=1187 flags=K__ [/PACKET] [STREAM] diff --git a/tests/ref/fate/matroska-opus-remux b/tests/ref/fate/matroska-opus-remux index 975510e1670..f5dcbe164ea 100644 --- a/tests/ref/fate/matroska-opus-remux +++ b/tests/ref/fate/matroska-opus-remux @@ -1,5 +1,5 @@ -fe0258eb0d4b525203ea240c87a154d3 *tests/data/fate/matroska-opus-remux.matroska -9359 tests/data/fate/matroska-opus-remux.matroska +dc14cd32921d86e03c155bb745edf44b *tests/data/fate/matroska-opus-remux.matroska +9370 tests/data/fate/matroska-opus-remux.matroska #extradata 0: 19, 0x3a04048f #tb 0: 1/1000 #media_type 0: audio @@ -68,7 +68,7 @@ dts_time=-0.007000 duration=20 duration_time=0.020000 size=320 -pos=500 +pos=511 flags=K__ [/PACKET] [PACKET] @@ -81,7 +81,7 @@ dts_time=0.014000 duration=20 duration_time=0.020000 size=159 -pos=827 +pos=838 flags=K__ [/PACKET] [PACKET] @@ -94,7 +94,7 @@ dts_time=0.034000 duration=20 duration_time=0.020000 size=148 -pos=993 +pos=1004 flags=K__ [/PACKET] [STREAM] diff --git a/tests/ref/fate/matroska-pgs-remux b/tests/ref/fate/matroska-pgs-remux index a086111495b..482357b8995 100644 --- a/tests/ref/fate/matroska-pgs-remux +++ b/tests/ref/fate/matroska-pgs-remux @@ -1,5 +1,5 @@ -d39daa393d66ae0b0c153be045897585 *tests/data/fate/matroska-pgs-remux.matroska -49748 tests/data/fate/matroska-pgs-remux.matroska +60161b7f8af39a8d280cc8b1f8693129 *tests/data/fate/matroska-pgs-remux.matroska +49759 tests/data/fate/matroska-pgs-remux.matroska #tb 0: 1/1000 #media_type 0: subtitle #codec_id 0: hdmv_pgs_subtitle diff --git a/tests/ref/fate/matroska-pgs-remux-durations b/tests/ref/fate/matroska-pgs-remux-durations index 37494cd98f8..6280110948b 100644 --- a/tests/ref/fate/matroska-pgs-remux-durations +++ b/tests/ref/fate/matroska-pgs-remux-durations @@ -1,5 +1,5 @@ -27af80eecea4f15f415f22841bc699d5 *tests/data/fate/matroska-pgs-remux-durations.matroska -49760 tests/data/fate/matroska-pgs-remux-durations.matroska +2c78a4337f61f24175a8ffe06087e581 *tests/data/fate/matroska-pgs-remux-durations.matroska +49771 tests/data/fate/matroska-pgs-remux-durations.matroska #tb 0: 1/1000 #media_type 0: subtitle #codec_id 0: hdmv_pgs_subtitle diff --git a/tests/ref/fate/matroska-qt-mode b/tests/ref/fate/matroska-qt-mode index d54f5d167cc..e14584893bd 100644 --- a/tests/ref/fate/matroska-qt-mode +++ b/tests/ref/fate/matroska-qt-mode @@ -1,5 +1,5 @@ -c3483a76cd0bfbaf80a32dad041b6f52 *tests/data/fate/matroska-qt-mode.matroska -1884232 tests/data/fate/matroska-qt-mode.matroska +a976ac0fd5c1ca916280f64525d12c10 *tests/data/fate/matroska-qt-mode.matroska +1884254 tests/data/fate/matroska-qt-mode.matroska #extradata 0: 90, 0x817d0185 #tb 0: 1/1000 #media_type 0: video diff --git a/tests/ref/fate/matroska-spherical-mono-remux b/tests/ref/fate/matroska-spherical-mono-remux index c65d206e910..0940e3ea861 100644 --- a/tests/ref/fate/matroska-spherical-mono-remux +++ b/tests/ref/fate/matroska-spherical-mono-remux @@ -1,5 +1,5 @@ -dfc2e196ca14cce155b1a081a0628fd3 *tests/data/fate/matroska-spherical-mono-remux.matroska -161562 tests/data/fate/matroska-spherical-mono-remux.matroska +281555d95fca08f3ba103eefa1c22b54 *tests/data/fate/matroska-spherical-mono-remux.matroska +161584 tests/data/fate/matroska-spherical-mono-remux.matroska #extradata 0: 43, 0x2b0e0d7b #extradata 1: 43, 0x2b0e0d7b #tb 0: 1/1000 diff --git a/tests/ref/fate/matroska-vp8-alpha-remux b/tests/ref/fate/matroska-vp8-alpha-remux index 1fad574edd0..86024b34774 100644 --- a/tests/ref/fate/matroska-vp8-alpha-remux +++ b/tests/ref/fate/matroska-vp8-alpha-remux @@ -1,5 +1,5 @@ -3339f3fa157bdd63f22f5a579f308c89 *tests/data/fate/matroska-vp8-alpha-remux.matroska -235015 tests/data/fate/matroska-vp8-alpha-remux.matroska +635702724143e90d2a3ec457f65676cf *tests/data/fate/matroska-vp8-alpha-remux.matroska +235026 tests/data/fate/matroska-vp8-alpha-remux.matroska #tb 0: 1/1000 #media_type 0: video #codec_id 0: vp8 diff --git a/tests/ref/fate/matroska-zero-length-block b/tests/ref/fate/matroska-zero-length-block index 3987cc14c48..0f90ccbdd78 100644 --- a/tests/ref/fate/matroska-zero-length-block +++ b/tests/ref/fate/matroska-zero-length-block @@ -1,5 +1,5 @@ -f577fad2fff41d6e055f605281582b8d *tests/data/fate/matroska-zero-length-block.matroska -634 tests/data/fate/matroska-zero-length-block.matroska +b9a8a67ffdba18eec1c04827d3d404ca *tests/data/fate/matroska-zero-length-block.matroska +645 tests/data/fate/matroska-zero-length-block.matroska #tb 0: 1/1000 #media_type 0: subtitle #codec_id 0: subrip diff --git a/tests/ref/fate/rgb24-mkv b/tests/ref/fate/rgb24-mkv index d037c01b32c..484198aaa4a 100644 --- a/tests/ref/fate/rgb24-mkv +++ b/tests/ref/fate/rgb24-mkv @@ -1,5 +1,5 @@ -69dc9d35fdfadccb28c7baf401776ec3 *tests/data/fate/rgb24-mkv.matroska -58215 tests/data/fate/rgb24-mkv.matroska +4801308890e7a9db51fc13b05f817165 *tests/data/fate/rgb24-mkv.matroska +58226 tests/data/fate/rgb24-mkv.matroska #tb 0: 1/10 #media_type 0: video #codec_id 0: rawvideo diff --git a/tests/ref/fate/shortest-sub b/tests/ref/fate/shortest-sub index b6571b4f32e..4db0e133285 100644 --- a/tests/ref/fate/shortest-sub +++ b/tests/ref/fate/shortest-sub @@ -1,5 +1,5 @@ -d334a0eee71351ddad0a63011107909f *tests/data/fate/shortest-sub.matroska -139240 tests/data/fate/shortest-sub.matroska +791a2ce136bef538491bbe31ac0134b1 *tests/data/fate/shortest-sub.matroska +139262 tests/data/fate/shortest-sub.matroska #extradata 1: 167, 0xf7272d5f #tb 0: 1/1000 #media_type 0: video diff --git a/tests/ref/lavf-fate/av1.mkv b/tests/ref/lavf-fate/av1.mkv index 382e3aeee34..685fd708115 100644 --- a/tests/ref/lavf-fate/av1.mkv +++ b/tests/ref/lavf-fate/av1.mkv @@ -1,3 +1,3 @@ -7d2c39dd98d5776425a4015e1eead6c6 *tests/data/lavf-fate/lavf.av1.mkv -55646 tests/data/lavf-fate/lavf.av1.mkv +279268e8d6ffcc2299e725a756bbb1a0 *tests/data/lavf-fate/lavf.av1.mkv +55657 tests/data/lavf-fate/lavf.av1.mkv tests/data/lavf-fate/lavf.av1.mkv CRC=0x7c27cc15 diff --git a/tests/ref/lavf/mka b/tests/ref/lavf/mka index 93a0b8f71a4..40b1f07f9b5 100644 --- a/tests/ref/lavf/mka +++ b/tests/ref/lavf/mka @@ -1,3 +1,3 @@ -77db16a9fe1c42a230c85124bfb40cad *tests/data/lavf/lavf.mka -43573 tests/data/lavf/lavf.mka +dffd74918d13be7dd07e83832de3a15c *tests/data/lavf/lavf.mka +43584 tests/data/lavf/lavf.mka tests/data/lavf/lavf.mka CRC=0x3a1da17e diff --git a/tests/ref/lavf/mkv b/tests/ref/lavf/mkv index fbd40fc1cb7..0aeb7cfae6b 100644 --- a/tests/ref/lavf/mkv +++ b/tests/ref/lavf/mkv @@ -1,3 +1,3 @@ -32b87b6adbe76df1008bc074f82fabb0 *tests/data/lavf/lavf.mkv -320417 tests/data/lavf/lavf.mkv +fde4f0580865684b878f0e13997213af *tests/data/lavf/lavf.mkv +320439 tests/data/lavf/lavf.mkv tests/data/lavf/lavf.mkv CRC=0xec6c3c68 diff --git a/tests/ref/lavf/mkv_attachment b/tests/ref/lavf/mkv_attachment index 2966a827cc3..6ab72b9a450 100644 --- a/tests/ref/lavf/mkv_attachment +++ b/tests/ref/lavf/mkv_attachment @@ -1,3 +1,3 @@ -41739c51209d94b4763f9dbe4d1e1dc9 *tests/data/lavf/lavf.mkv_attachment -472567 tests/data/lavf/lavf.mkv_attachment +c75c844f592d44c2a79ff5fc1e8179e0 *tests/data/lavf/lavf.mkv_attachment +472589 tests/data/lavf/lavf.mkv_attachment tests/data/lavf/lavf.mkv_attachment CRC=0xec6c3c68 diff --git a/tests/ref/seek/lavf-mkv b/tests/ref/seek/lavf-mkv index 06ba6e03803..90d91e3968e 100644 --- a/tests/ref/seek/lavf-mkv +++ b/tests/ref/seek/lavf-mkv @@ -1,48 +1,48 @@ -ret: 0 st: 1 flags:1 dts:-0.011000 pts:-0.011000 pos: 665 size: 208 +ret: 0 st: 1 flags:1 dts:-0.011000 pts:-0.011000 pos: 687 size: 208 ret: 0 st:-1 flags:0 ts:-1.000000 -ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 881 size: 27837 +ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 903 size: 27837 ret: 0 st:-1 flags:1 ts: 1.894167 -ret: 0 st: 0 flags:1 dts: 0.960000 pts: 0.960000 pos: 292297 size: 27834 +ret: 0 st: 0 flags:1 dts: 0.960000 pts: 0.960000 pos: 292319 size: 27834 ret: 0 st: 0 flags:0 ts: 0.788000 -ret: 0 st: 0 flags:1 dts: 0.960000 pts: 0.960000 pos: 292297 size: 27834 +ret: 0 st: 0 flags:1 dts: 0.960000 pts: 0.960000 pos: 292319 size: 27834 ret: 0 st: 0 flags:1 ts:-0.317000 -ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 881 size: 27837 +ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 903 size: 27837 ret:-1 st: 1 flags:0 ts: 2.577000 ret: 0 st: 1 flags:1 ts: 1.471000 -ret: 0 st: 1 flags:1 dts: 0.982000 pts: 0.982000 pos: 320138 size: 209 +ret: 0 st: 1 flags:1 dts: 0.982000 pts: 0.982000 pos: 320160 size: 209 ret: 0 st:-1 flags:0 ts: 0.365002 -ret: 0 st: 0 flags:1 dts: 0.480000 pts: 0.480000 pos: 146849 size: 27925 +ret: 0 st: 0 flags:1 dts: 0.480000 pts: 0.480000 pos: 146871 size: 27925 ret: 0 st:-1 flags:1 ts:-0.740831 -ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 881 size: 27837 +ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 903 size: 27837 ret:-1 st: 0 flags:0 ts: 2.153000 ret: 0 st: 0 flags:1 ts: 1.048000 -ret: 0 st: 0 flags:1 dts: 0.960000 pts: 0.960000 pos: 292297 size: 27834 +ret: 0 st: 0 flags:1 dts: 0.960000 pts: 0.960000 pos: 292319 size: 27834 ret: 0 st: 1 flags:0 ts:-0.058000 -ret: 0 st: 1 flags:1 dts:-0.011000 pts:-0.011000 pos: 665 size: 208 +ret: 0 st: 1 flags:1 dts:-0.011000 pts:-0.011000 pos: 687 size: 208 ret: 0 st: 1 flags:1 ts: 2.836000 -ret: 0 st: 1 flags:1 dts: 0.982000 pts: 0.982000 pos: 320138 size: 209 +ret: 0 st: 1 flags:1 dts: 0.982000 pts: 0.982000 pos: 320160 size: 209 ret:-1 st:-1 flags:0 ts: 1.730004 ret: 0 st:-1 flags:1 ts: 0.624171 -ret: 0 st: 0 flags:1 dts: 0.480000 pts: 0.480000 pos: 146849 size: 27925 +ret: 0 st: 0 flags:1 dts: 0.480000 pts: 0.480000 pos: 146871 size: 27925 ret: 0 st: 0 flags:0 ts:-0.482000 -ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 881 size: 27837 +ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 903 size: 27837 ret: 0 st: 0 flags:1 ts: 2.413000 -ret: 0 st: 0 flags:1 dts: 0.960000 pts: 0.960000 pos: 292297 size: 27834 +ret: 0 st: 0 flags:1 dts: 0.960000 pts: 0.960000 pos: 292319 size: 27834 ret:-1 st: 1 flags:0 ts: 1.307000 ret: 0 st: 1 flags:1 ts: 0.201000 -ret: 0 st: 1 flags:1 dts:-0.011000 pts:-0.011000 pos: 665 size: 208 +ret: 0 st: 1 flags:1 dts:-0.011000 pts:-0.011000 pos: 687 size: 208 ret: 0 st:-1 flags:0 ts:-0.904994 -ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 881 size: 27837 +ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 903 size: 27837 ret: 0 st:-1 flags:1 ts: 1.989173 -ret: 0 st: 0 flags:1 dts: 0.960000 pts: 0.960000 pos: 292297 size: 27834 +ret: 0 st: 0 flags:1 dts: 0.960000 pts: 0.960000 pos: 292319 size: 27834 ret: 0 st: 0 flags:0 ts: 0.883000 -ret: 0 st: 0 flags:1 dts: 0.960000 pts: 0.960000 pos: 292297 size: 27834 +ret: 0 st: 0 flags:1 dts: 0.960000 pts: 0.960000 pos: 292319 size: 27834 ret: 0 st: 0 flags:1 ts:-0.222000 -ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 881 size: 27837 +ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 903 size: 27837 ret:-1 st: 1 flags:0 ts: 2.672000 ret: 0 st: 1 flags:1 ts: 1.566000 -ret: 0 st: 1 flags:1 dts: 0.982000 pts: 0.982000 pos: 320138 size: 209 +ret: 0 st: 1 flags:1 dts: 0.982000 pts: 0.982000 pos: 320160 size: 209 ret: 0 st:-1 flags:0 ts: 0.460008 -ret: 0 st: 0 flags:1 dts: 0.480000 pts: 0.480000 pos: 146849 size: 27925 +ret: 0 st: 0 flags:1 dts: 0.480000 pts: 0.480000 pos: 146871 size: 27925 ret: 0 st:-1 flags:1 ts:-0.645825 -ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 881 size: 27837 +ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 903 size: 27837 From 30f1f89572239b9335464fb665ec91eeb743ffd7 Mon Sep 17 00:00:00 2001 From: James Almer Date: Sun, 19 Mar 2023 17:43:59 -0300 Subject: [PATCH 0591/2172] fate/matroska: add HDR10+ muxing tests Signed-off-by: James Almer --- tests/fate/matroska.mak | 8 +++ tests/ref/fate/matroska-hdr10-plus-remux | 63 ++++++++++++++++++++++++ tests/ref/fate/webm-hdr10-plus-remux | 63 ++++++++++++++++++++++++ 3 files changed, 134 insertions(+) create mode 100644 tests/ref/fate/matroska-hdr10-plus-remux create mode 100644 tests/ref/fate/webm-hdr10-plus-remux diff --git a/tests/fate/matroska.mak b/tests/fate/matroska.mak index 39137ad4bee..7c4eed358f2 100644 --- a/tests/fate/matroska.mak +++ b/tests/fate/matroska.mak @@ -217,6 +217,14 @@ FATE_MATROSKA_FFMPEG_FFPROBE-$(call REMUX, WEBM MATROSKA, WEBVTT_DEMUXER) \ += fate-webm-webvtt-remux fate-webm-webvtt-remux: CMD = transcode webvtt $(TARGET_SAMPLES)/sub/WebVTT_capability_tester.vtt webm "-map 0 -map 0 -map 0 -map 0 -c:s copy -disposition:0 original+descriptions+hearing_impaired -disposition:1 lyrics+default+metadata -disposition:2 comment+forced -disposition:3 karaoke+captions+dub" "-map 0:0 -map 0:1 -c copy" "-show_entries stream_disposition:stream=index,codec_name:packet=stream_index,pts:packet_side_data_list -show_data_hash CRC32" +FATE_MATROSKA_FFMPEG_FFPROBE-$(call REMUX, WEBM MATROSKA, VP9_PARSER) \ + += fate-webm-hdr10-plus-remux +fate-webm-hdr10-plus-remux: CMD = transcode webm $(TARGET_SAMPLES)/mkv/hdr10_plus_vp9_sample.webm webm "-map 0 -c:v copy" "-map 0 -c:v copy" "-show_packets" + +FATE_MATROSKA_FFMPEG_FFPROBE-$(call REMUX, MATROSKA, VP9_PARSER) \ + += fate-matroska-hdr10-plus-remux +fate-matroska-hdr10-plus-remux: CMD = transcode webm $(TARGET_SAMPLES)/mkv/hdr10_plus_vp9_sample.webm matroska "-map 0 -c:v copy" "-map 0 -c:v copy" "-show_packets" + FATE_SAMPLES_AVCONV += $(FATE_MATROSKA-yes) FATE_SAMPLES_FFPROBE += $(FATE_MATROSKA_FFPROBE-yes) FATE_SAMPLES_FFMPEG_FFPROBE += $(FATE_MATROSKA_FFMPEG_FFPROBE-yes) diff --git a/tests/ref/fate/matroska-hdr10-plus-remux b/tests/ref/fate/matroska-hdr10-plus-remux new file mode 100644 index 00000000000..bb0580db336 --- /dev/null +++ b/tests/ref/fate/matroska-hdr10-plus-remux @@ -0,0 +1,63 @@ +0f941512f69b1cc0ac27f3375e56a0cc *tests/data/fate/matroska-hdr10-plus-remux.matroska +13892 tests/data/fate/matroska-hdr10-plus-remux.matroska +#tb 0: 1/1000 +#media_type 0: video +#codec_id 0: vp9 +#dimensions 0: 1280x720 +#sar 0: 1/1 +0, 0, 0, 40, 13350, 0x5f64e443, S=1, 11304 +[PACKET] +codec_type=video +stream_index=0 +pts=0 +pts_time=0.000000 +dts=0 +dts_time=0.000000 +duration=40 +duration_time=0.040000 +size=13350 +pos=436 +flags=K__ +[SIDE_DATA] +side_data_type=HDR10+ Dynamic Metadata (SMPTE 2094-40) +application version=1 +num_windows=1 +targeted_system_display_maximum_luminance=400/1 +maxscl=3340/100000 +maxscl=2870/100000 +maxscl=2720/100000 +average_maxrgb=510/100000 +num_distribution_maxrgb_percentiles=9 +distribution_maxrgb_percentage=1 +distribution_maxrgb_percentile=30/100000 +distribution_maxrgb_percentage=5 +distribution_maxrgb_percentile=2940/100000 +distribution_maxrgb_percentage=10 +distribution_maxrgb_percentile=255/100000 +distribution_maxrgb_percentage=25 +distribution_maxrgb_percentile=70/100000 +distribution_maxrgb_percentage=50 +distribution_maxrgb_percentile=1340/100000 +distribution_maxrgb_percentage=75 +distribution_maxrgb_percentile=1600/100000 +distribution_maxrgb_percentage=90 +distribution_maxrgb_percentile=1850/100000 +distribution_maxrgb_percentage=95 +distribution_maxrgb_percentile=1950/100000 +distribution_maxrgb_percentage=99 +distribution_maxrgb_percentile=2940/100000 +fraction_bright_pixels=1/1000 +knee_point_x=0/4095 +knee_point_y=0/4095 +num_bezier_curve_anchors=9 +bezier_curve_anchors=102/1023 +bezier_curve_anchors=205/1023 +bezier_curve_anchors=307/1023 +bezier_curve_anchors=410/1023 +bezier_curve_anchors=512/1023 +bezier_curve_anchors=614/1023 +bezier_curve_anchors=717/1023 +bezier_curve_anchors=819/1023 +bezier_curve_anchors=922/1023 +[/SIDE_DATA] +[/PACKET] diff --git a/tests/ref/fate/webm-hdr10-plus-remux b/tests/ref/fate/webm-hdr10-plus-remux new file mode 100644 index 00000000000..d8dbb935989 --- /dev/null +++ b/tests/ref/fate/webm-hdr10-plus-remux @@ -0,0 +1,63 @@ +30923c8d916f5719f62727f24957974f *tests/data/fate/webm-hdr10-plus-remux.webm +13843 tests/data/fate/webm-hdr10-plus-remux.webm +#tb 0: 1/1000 +#media_type 0: video +#codec_id 0: vp9 +#dimensions 0: 1280x720 +#sar 0: 1/1 +0, 0, 0, 40, 13350, 0x5f64e443, S=1, 11304 +[PACKET] +codec_type=video +stream_index=0 +pts=0 +pts_time=0.000000 +dts=0 +dts_time=0.000000 +duration=40 +duration_time=0.040000 +size=13350 +pos=393 +flags=K__ +[SIDE_DATA] +side_data_type=HDR10+ Dynamic Metadata (SMPTE 2094-40) +application version=1 +num_windows=1 +targeted_system_display_maximum_luminance=400/1 +maxscl=3340/100000 +maxscl=2870/100000 +maxscl=2720/100000 +average_maxrgb=510/100000 +num_distribution_maxrgb_percentiles=9 +distribution_maxrgb_percentage=1 +distribution_maxrgb_percentile=30/100000 +distribution_maxrgb_percentage=5 +distribution_maxrgb_percentile=2940/100000 +distribution_maxrgb_percentage=10 +distribution_maxrgb_percentile=255/100000 +distribution_maxrgb_percentage=25 +distribution_maxrgb_percentile=70/100000 +distribution_maxrgb_percentage=50 +distribution_maxrgb_percentile=1340/100000 +distribution_maxrgb_percentage=75 +distribution_maxrgb_percentile=1600/100000 +distribution_maxrgb_percentage=90 +distribution_maxrgb_percentile=1850/100000 +distribution_maxrgb_percentage=95 +distribution_maxrgb_percentile=1950/100000 +distribution_maxrgb_percentage=99 +distribution_maxrgb_percentile=2940/100000 +fraction_bright_pixels=1/1000 +knee_point_x=0/4095 +knee_point_y=0/4095 +num_bezier_curve_anchors=9 +bezier_curve_anchors=102/1023 +bezier_curve_anchors=205/1023 +bezier_curve_anchors=307/1023 +bezier_curve_anchors=410/1023 +bezier_curve_anchors=512/1023 +bezier_curve_anchors=614/1023 +bezier_curve_anchors=717/1023 +bezier_curve_anchors=819/1023 +bezier_curve_anchors=922/1023 +[/SIDE_DATA] +[/PACKET] From 12d1f7c4b783abcdbcb8e5a0c981601ec07f972f Mon Sep 17 00:00:00 2001 From: Devin Heitmueller Date: Fri, 7 Apr 2023 17:36:14 -0400 Subject: [PATCH 0592/2172] avdevice/decklink_enc: Add support for compressed AC-3 output over SDI Extend the decklink output to include support for compressed AC-3, encapsulated using the SMPTE ST 377:2015 standard. This functionality can be exercised by using the "copy" codec when the input audio stream is AC-3. For example: ./ffmpeg -i ~/foo.ts -codec:a copy -f decklink 'UltraStudio Mini Monitor' Note that the default behavior continues to be to do PCM output, which means without specifying the copy codec a stream containing AC-3 will be decoded and downmixed to stereo audio before output. Thanks to Marton Balint for providing feedback. Signed-off-by: Devin Heitmueller Signed-off-by: Marton Balint --- libavdevice/decklink_enc.cpp | 100 +++++++++++++++++++++++++++++------ 1 file changed, 85 insertions(+), 15 deletions(-) diff --git a/libavdevice/decklink_enc.cpp b/libavdevice/decklink_enc.cpp index 62676ea68e9..92bfdb279fe 100644 --- a/libavdevice/decklink_enc.cpp +++ b/libavdevice/decklink_enc.cpp @@ -32,6 +32,7 @@ extern "C" { extern "C" { #include "libavformat/avformat.h" +#include "libavcodec/bytestream.h" #include "libavutil/internal.h" #include "libavutil/imgutils.h" #include "avdevice.h" @@ -243,19 +244,32 @@ static int decklink_setup_audio(AVFormatContext *avctx, AVStream *st) av_log(avctx, AV_LOG_ERROR, "Only one audio stream is supported!\n"); return -1; } - if (c->sample_rate != 48000) { - av_log(avctx, AV_LOG_ERROR, "Unsupported sample rate!" - " Only 48kHz is supported.\n"); - return -1; - } - if (c->ch_layout.nb_channels != 2 && c->ch_layout.nb_channels != 8 && c->ch_layout.nb_channels != 16) { - av_log(avctx, AV_LOG_ERROR, "Unsupported number of channels!" - " Only 2, 8 or 16 channels are supported.\n"); + + if (c->codec_id == AV_CODEC_ID_AC3) { + /* Regardless of the number of channels in the codec, we're only + using 2 SDI audio channels at 48000Hz */ + ctx->channels = 2; + } else if (c->codec_id == AV_CODEC_ID_PCM_S16LE) { + if (c->sample_rate != 48000) { + av_log(avctx, AV_LOG_ERROR, "Unsupported sample rate!" + " Only 48kHz is supported.\n"); + return -1; + } + if (c->ch_layout.nb_channels != 2 && c->ch_layout.nb_channels != 8 && c->ch_layout.nb_channels != 16) { + av_log(avctx, AV_LOG_ERROR, "Unsupported number of channels!" + " Only 2, 8 or 16 channels are supported.\n"); + return -1; + } + ctx->channels = c->ch_layout.nb_channels; + } else { + av_log(avctx, AV_LOG_ERROR, "Unsupported codec specified!" + " Only PCM_S16LE and AC-3 are supported.\n"); return -1; } + if (ctx->dlo->EnableAudioOutput(bmdAudioSampleRate48kHz, bmdAudioSampleType16bitInteger, - c->ch_layout.nb_channels, + ctx->channels, bmdAudioOutputStreamTimestamped) != S_OK) { av_log(avctx, AV_LOG_ERROR, "Could not enable audio output!\n"); return -1; @@ -266,14 +280,52 @@ static int decklink_setup_audio(AVFormatContext *avctx, AVStream *st) } /* The device expects the sample rate to be fixed. */ - avpriv_set_pts_info(st, 64, 1, c->sample_rate); - ctx->channels = c->ch_layout.nb_channels; + avpriv_set_pts_info(st, 64, 1, 48000); ctx->audio = 1; return 0; } +/* Wrap the AC-3 packet into an S337 payload that is in S16LE format which can be easily + injected into the PCM stream. Note: despite the function name, only AC-3 is implemented */ +static int create_s337_payload(AVPacket *pkt, uint8_t **outbuf, int *outsize) +{ + /* Note: if the packet size is not divisible by four, we need to make the actual + payload larger to ensure it ends on an two channel S16LE boundary */ + int payload_size = FFALIGN(pkt->size, 4) + 8; + uint16_t bitcount = pkt->size * 8; + uint8_t *s337_payload; + PutByteContext pb; + + /* Sanity check: According to SMPTE ST 340:2015 Sec 4.1, the AC-3 sync frame will + exactly match the 1536 samples of baseband (PCM) audio that it represents. */ + if (pkt->size > 1536) + return AVERROR(EINVAL); + + /* Encapsulate AC3 syncframe into SMPTE 337 packet */ + s337_payload = (uint8_t *) av_malloc(payload_size); + if (s337_payload == NULL) + return AVERROR(ENOMEM); + bytestream2_init_writer(&pb, s337_payload, payload_size); + bytestream2_put_le16u(&pb, 0xf872); /* Sync word 1 */ + bytestream2_put_le16u(&pb, 0x4e1f); /* Sync word 1 */ + bytestream2_put_le16u(&pb, 0x0001); /* Burst Info, including data type (1=ac3) */ + bytestream2_put_le16u(&pb, bitcount); /* Length code */ + for (int i = 0; i < (pkt->size - 1); i += 2) + bytestream2_put_le16u(&pb, (pkt->data[i] << 8) | pkt->data[i+1]); + + /* Ensure final payload is aligned on 4-byte boundary */ + if (pkt->size & 1) + bytestream2_put_le16u(&pb, pkt->data[pkt->size - 1] << 8); + if ((pkt->size & 3 == 1) || (pkt->size & 3 == 2)) + bytestream2_put_le16u(&pb, 0); + + *outsize = payload_size; + *outbuf = s337_payload; + return 0; +} + av_cold int ff_decklink_write_trailer(AVFormatContext *avctx) { struct decklink_cctx *cctx = (struct decklink_cctx *)avctx->priv_data; @@ -617,21 +669,39 @@ static int decklink_write_audio_packet(AVFormatContext *avctx, AVPacket *pkt) { struct decklink_cctx *cctx = (struct decklink_cctx *)avctx->priv_data; struct decklink_ctx *ctx = (struct decklink_ctx *)cctx->ctx; - int sample_count = pkt->size / (ctx->channels << 1); + AVStream *st = avctx->streams[pkt->stream_index]; + int sample_count; uint32_t buffered; + uint8_t *outbuf = NULL; + int ret = 0; ctx->dlo->GetBufferedAudioSampleFrameCount(&buffered); if (pkt->pts > 1 && !buffered) av_log(avctx, AV_LOG_WARNING, "There's no buffered audio." " Audio will misbehave!\n"); - if (ctx->dlo->ScheduleAudioSamples(pkt->data, sample_count, pkt->pts, + if (st->codecpar->codec_id == AV_CODEC_ID_AC3) { + /* Encapsulate AC3 syncframe into SMPTE 337 packet */ + int outbuf_size; + ret = create_s337_payload(pkt, &outbuf, &outbuf_size); + if (ret < 0) + return ret; + sample_count = outbuf_size / 4; + } else { + sample_count = pkt->size / (ctx->channels << 1); + outbuf = pkt->data; + } + + if (ctx->dlo->ScheduleAudioSamples(outbuf, sample_count, pkt->pts, bmdAudioSampleRate48kHz, NULL) != S_OK) { av_log(avctx, AV_LOG_ERROR, "Could not schedule audio samples.\n"); - return AVERROR(EIO); + ret = AVERROR(EIO); } - return 0; + if (st->codecpar->codec_id == AV_CODEC_ID_AC3) + av_freep(&outbuf); + + return ret; } extern "C" { From 05e34523bc5db91618c0f1e9c8923eaf3ed1e74d Mon Sep 17 00:00:00 2001 From: Jerome Martinez Date: Wed, 19 Oct 2022 11:47:33 +0200 Subject: [PATCH 0593/2172] avcodec/dpx: fix check of minimal data size for unpadded content stride value is not relevant with unpadded content and the total count of pixels (width x height) must be used instead of the rounding based on width only then multiplied by height unpadded_10bit value computing is moved sooner in the code in order to be able to use it during computing of minimal content size. Also make sure to only set it for 10bit. Fix 'Overread buffer' error when the content is not lucky enough to have (enough) padding bytes at the end for not being rejected by the formula based on the stride value Fixes ticket #10259. Signed-off-by: Jerome Martinez Signed-off-by: Marton Balint --- libavcodec/dpx.c | 35 +++++++++++++++++++---------------- 1 file changed, 19 insertions(+), 16 deletions(-) diff --git a/libavcodec/dpx.c b/libavcodec/dpx.c index 4f50608461e..31e4a3f82c4 100644 --- a/libavcodec/dpx.c +++ b/libavcodec/dpx.c @@ -476,14 +476,31 @@ static int decode_frame(AVCodecContext *avctx, AVFrame *p, avctx->colorspace = AVCOL_SPC_RGB; } + av_strlcpy(creator, avpkt->data + 160, 100); + creator[100] = '\0'; + av_dict_set(&p->metadata, "Creator", creator, 0); + + av_strlcpy(input_device, avpkt->data + 1556, 32); + input_device[32] = '\0'; + av_dict_set(&p->metadata, "Input Device", input_device, 0); + + // Some devices do not pad 10bit samples to whole 32bit words per row + if (!memcmp(input_device, "Scanity", 7) || + !memcmp(creator, "Lasergraphics Inc.", 18)) { + if (bits_per_color == 10) + unpadded_10bit = 1; + } + // Table 3c: Runs will always break at scan line boundaries. Packing // will always break to the next 32-bit word at scan-line boundaries. // Unfortunately, the encoder produced invalid files, so attempt // to detect it + // Also handle special case with unpadded content need_align = FFALIGN(stride, 4); - if (need_align*avctx->height + (int64_t)offset > avpkt->size) { + if (need_align*avctx->height + (int64_t)offset > avpkt->size && + (!unpadded_10bit || (avctx->width * avctx->height * elements + 2) / 3 * 4 + (int64_t)offset > avpkt->size)) { // Alignment seems unappliable, try without - if (stride*avctx->height + (int64_t)offset > avpkt->size) { + if (stride*avctx->height + (int64_t)offset > avpkt->size || unpadded_10bit) { av_log(avctx, AV_LOG_ERROR, "Overread buffer. Invalid header?\n"); return AVERROR_INVALIDDATA; } else { @@ -609,20 +626,6 @@ static int decode_frame(AVCodecContext *avctx, AVFrame *p, if ((ret = ff_get_buffer(avctx, p, 0)) < 0) return ret; - av_strlcpy(creator, avpkt->data + 160, 100); - creator[100] = '\0'; - av_dict_set(&p->metadata, "Creator", creator, 0); - - av_strlcpy(input_device, avpkt->data + 1556, 32); - input_device[32] = '\0'; - av_dict_set(&p->metadata, "Input Device", input_device, 0); - - // Some devices do not pad 10bit samples to whole 32bit words per row - if (!memcmp(input_device, "Scanity", 7) || - !memcmp(creator, "Lasergraphics Inc.", 18)) { - unpadded_10bit = 1; - } - // Move pointer to offset from start of file buf = avpkt->data + offset; From 82a14f360279ab252c2d17719ae72dd361f8277d Mon Sep 17 00:00:00 2001 From: James Almer Date: Sat, 8 Apr 2023 14:59:40 -0300 Subject: [PATCH 0594/2172] avformat/matroskadec: also validate the mapping when BlockAddIDType is 0 Signed-off-by: James Almer --- libavformat/matroskadec.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/libavformat/matroskadec.c b/libavformat/matroskadec.c index b3922ab8b02..6cccbcbe039 100644 --- a/libavformat/matroskadec.c +++ b/libavformat/matroskadec.c @@ -2389,16 +2389,18 @@ static int mkv_parse_block_addition_mappings(AVFormatContext *s, AVStream *st, M for (int i = 0; i < mappings_list->nb_elem; i++) { MatroskaBlockAdditionMapping *mapping = &mappings[i]; + uint64_t type = mapping->type; switch (mapping->type) { case MATROSKA_BLOCK_ADD_ID_TYPE_DEFAULT: av_log(s, AV_LOG_DEBUG, "Explicit block Addition Mapping type \"Use BlockAddIDValue\", value %"PRIu64"," " name \"%s\" found.\n", mapping->value, mapping->name ? mapping->name : ""); - break; + type = MATROSKA_BLOCK_ADD_ID_TYPE_OPAQUE; + // fall-through case MATROSKA_BLOCK_ADD_ID_TYPE_OPAQUE: case MATROSKA_BLOCK_ADD_ID_TYPE_ITU_T_T35: - if (mapping->value != mapping->type) { + if (mapping->value != type) { int strict = s->strict_std_compliance >= FF_COMPLIANCE_STRICT; av_log(s, strict ? AV_LOG_ERROR : AV_LOG_WARNING, "Invalid Block Addition Value 0x%"PRIx64" for Block Addition Mapping Type " From aa8ff2240ce9ed2bc67d1e5fabfb77f38c823fb7 Mon Sep 17 00:00:00 2001 From: Jun Zhao Date: Mon, 3 Apr 2023 20:03:28 +0800 Subject: [PATCH 0595/2172] lavc/videotoolboxenc: fix warnings fix mixing declarations and code and function declaration without a prototype warnings Signed-off-by: Jun Zhao --- libavcodec/videotoolboxenc.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/libavcodec/videotoolboxenc.c b/libavcodec/videotoolboxenc.c index 56971471e4e..c6f22723d6d 100644 --- a/libavcodec/videotoolboxenc.c +++ b/libavcodec/videotoolboxenc.c @@ -120,7 +120,7 @@ do{ \ static pthread_once_t once_ctrl = PTHREAD_ONCE_INIT; -static void loadVTEncSymbols(){ +static void loadVTEncSymbols(void){ compat_keys.CMVideoFormatDescriptionGetHEVCParameterSetAtIndex = (getParameterSetAtIndex)dlsym( RTLD_DEFAULT, @@ -1650,8 +1650,8 @@ static int find_sei_end(AVCodecContext *avctx, { int nal_type; size_t sei_payload_size = 0; - *sei_end = NULL; uint8_t *nal_start = nal_data; + *sei_end = NULL; if (!nal_size) return 0; @@ -2041,7 +2041,7 @@ static int vtenc_cm_to_avpacket( return AVERROR_EXTERNAL; } - int status = get_params_size(avctx, vid_fmt, &header_size); + status = get_params_size(avctx, vid_fmt, &header_size); if (status) return status; } From 639ded10e3599b7dd52a4bd7c06589689d177d08 Mon Sep 17 00:00:00 2001 From: Jun Zhao Date: Mon, 3 Apr 2023 20:08:23 +0800 Subject: [PATCH 0596/2172] lavc/videotoolbox: fix warnings fix mixing declarations and code warnings Signed-off-by: Jun Zhao --- libavcodec/videotoolbox.c | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/libavcodec/videotoolbox.c b/libavcodec/videotoolbox.c index e42fea6f325..64443255917 100644 --- a/libavcodec/videotoolbox.c +++ b/libavcodec/videotoolbox.c @@ -799,6 +799,9 @@ static CFDictionaryRef videotoolbox_buffer_attributes_create(int width, static CFDictionaryRef videotoolbox_decoder_config_create(CMVideoCodecType codec_type, AVCodecContext *avctx) { + CFMutableDictionaryRef avc_info; + CFDataRef data = NULL; + CFMutableDictionaryRef config_info = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, &kCFTypeDictionaryKeyCallBacks, @@ -810,9 +813,6 @@ static CFDictionaryRef videotoolbox_decoder_config_create(CMVideoCodecType codec kVTVideoDecoderSpecification_RequireHardwareAcceleratedVideoDecoder, kCFBooleanTrue); - CFMutableDictionaryRef avc_info; - CFDataRef data = NULL; - avc_info = CFDictionaryCreateMutable(kCFAllocatorDefault, 1, &kCFTypeDictionaryKeyCallBacks, @@ -1072,13 +1072,14 @@ static int videotoolbox_hevc_end_frame(AVCodecContext *avctx) HEVCContext *h = avctx->priv_data; AVFrame *frame = h->ref->frame; VTContext *vtctx = avctx->internal->hwaccel_priv_data; + int ret; h->output_frame->crop_right = 0; h->output_frame->crop_left = 0; h->output_frame->crop_top = 0; h->output_frame->crop_bottom = 0; - int ret = ff_videotoolbox_common_end_frame(avctx, frame); + ret = ff_videotoolbox_common_end_frame(avctx, frame); vtctx->bitstream_size = 0; return ret; } @@ -1132,15 +1133,17 @@ static int videotoolbox_prores_end_frame(AVCodecContext *avctx) } static enum AVPixelFormat videotoolbox_best_pixel_format(AVCodecContext *avctx) { + int depth; 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() - int depth = descriptor->comp[0].depth; if (descriptor->flags & AV_PIX_FMT_FLAG_ALPHA) return AV_PIX_FMT_AYUV64; + 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; @@ -1194,6 +1197,7 @@ int ff_videotoolbox_common_init(AVCodecContext *avctx) VTContext *vtctx = avctx->internal->hwaccel_priv_data; AVHWFramesContext *hw_frames; int err; + bool full_range; vtctx->logctx = avctx; @@ -1241,7 +1245,7 @@ int ff_videotoolbox_common_init(AVCodecContext *avctx) goto fail; } - bool full_range = avctx->color_range == AVCOL_RANGE_JPEG; + full_range = avctx->color_range == AVCOL_RANGE_JPEG; vtctx->vt_ctx->cv_pix_fmt_type = av_map_videotoolbox_format_from_pixfmt2(hw_frames->sw_format, full_range); if (!vtctx->vt_ctx->cv_pix_fmt_type) { From 34b8af796341887766cfa02fe5f4383039919bb6 Mon Sep 17 00:00:00 2001 From: Zhao Zhili Date: Thu, 16 Mar 2023 00:27:51 +0800 Subject: [PATCH 0597/2172] avformat/flvenc: use extract_extradata bsf when necessary Signed-off-by: Zhao Zhili --- libavformat/flvenc.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/libavformat/flvenc.c b/libavformat/flvenc.c index 64ea554dada..fbf7eabaf8c 100644 --- a/libavformat/flvenc.c +++ b/libavformat/flvenc.c @@ -1023,13 +1023,15 @@ static int flv_write_packet(AVFormatContext *s, AVPacket *pkt) static int flv_check_bitstream(AVFormatContext *s, AVStream *st, const AVPacket *pkt) { - int ret = 1; - if (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); + return ff_stream_add_bitstream_filter(st, "aac_adtstoasc", NULL); } - return ret; + if (!st->codecpar->extradata_size && + (st->codecpar->codec_id == AV_CODEC_ID_H264 || + st->codecpar->codec_id == AV_CODEC_ID_MPEG4)) + return ff_stream_add_bitstream_filter(st, "extract_extradata", NULL); + return 1; } static void flv_deinit(AVFormatContext *s) From 862a626c9db537f4ba248649353166a5004189b3 Mon Sep 17 00:00:00 2001 From: Zhao Zhili Date: Thu, 16 Mar 2023 00:27:52 +0800 Subject: [PATCH 0598/2172] avcodec/mediacodecenc: warning when global header is requested. Add suggests to use extract_extradata bsf. Signed-off-by: Zhao Zhili --- libavcodec/mediacodecenc.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/libavcodec/mediacodecenc.c b/libavcodec/mediacodecenc.c index 0767cd01659..e4b583a542f 100644 --- a/libavcodec/mediacodecenc.c +++ b/libavcodec/mediacodecenc.c @@ -323,6 +323,10 @@ static av_cold int mediacodec_init(AVCodecContext *avctx) goto bailout; mediacodec_output_format(avctx); + if (avctx->flags & AV_CODEC_FLAG_GLOBAL_HEADER) + av_log(avctx, AV_LOG_WARNING, + "Mediacodec encoder doesn't support AV_CODEC_FLAG_GLOBAL_HEADER. " + "Use extract_extradata bsf when necessary.\n"); s->frame = av_frame_alloc(); if (!s->frame) From 416e2661ea9c2b55d5b9e25d687f0d2a839d6cd6 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Mon, 3 Apr 2023 12:04:50 +0200 Subject: [PATCH 0599/2172] fftools/ffmpeg: make sure non-lavfi streams are closed on input EOF --- fftools/ffmpeg.c | 1 + 1 file changed, 1 insertion(+) diff --git a/fftools/ffmpeg.c b/fftools/ffmpeg.c index 438bee8fef6..2f1f8305074 100644 --- a/fftools/ffmpeg.c +++ b/fftools/ffmpeg.c @@ -3804,6 +3804,7 @@ static int process_input(int file_index) if (ost->ist == ist && (!ost->enc_ctx || ost->enc_ctx->codec_type == AVMEDIA_TYPE_SUBTITLE)) { OutputFile *of = output_files[ost->file_index]; + close_output_stream(ost); of_output_packet(of, ost->pkt, ost, 1); } } From e1d12aaa453b267011c388f7de8cfb6936d08fec Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Mon, 27 Mar 2023 07:15:00 +0200 Subject: [PATCH 0600/2172] fftools/ffmpeg: do not return finished streams from choose_output() --- fftools/ffmpeg.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fftools/ffmpeg.c b/fftools/ffmpeg.c index 2f1f8305074..cb7cec68e5d 100644 --- a/fftools/ffmpeg.c +++ b/fftools/ffmpeg.c @@ -3493,7 +3493,7 @@ static OutputStream *choose_output(void) ost->initialized, ost->inputs_done, ost->finished); } - if (!ost->initialized && !ost->inputs_done) + if (!ost->initialized && !ost->inputs_done && !ost->finished) return ost->unavailable ? NULL : ost; if (!ost->finished && opts < opts_min) { From 8e23a62eff08715ce5ec021c7b4de7ad9c716089 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Mon, 20 Mar 2023 16:50:19 +0100 Subject: [PATCH 0601/2172] fftools/ffmpeg: drop InputStream.processing_needed It is equivalent to !InputStream.discard. --- fftools/ffmpeg.c | 4 ++-- fftools/ffmpeg.h | 1 - fftools/ffmpeg_filter.c | 1 - fftools/ffmpeg_mux_init.c | 3 --- 4 files changed, 2 insertions(+), 7 deletions(-) diff --git a/fftools/ffmpeg.c b/fftools/ffmpeg.c index cb7cec68e5d..3a68640cada 100644 --- a/fftools/ffmpeg.c +++ b/fftools/ffmpeg.c @@ -3648,7 +3648,7 @@ static void decode_flush(InputFile *ifile) InputStream *ist = ifile->streams[i]; int ret; - if (!ist->processing_needed) + if (ist->discard) continue; do { @@ -3793,7 +3793,7 @@ static int process_input(int file_index) for (i = 0; i < ifile->nb_streams; i++) { ist = ifile->streams[i]; - if (ist->processing_needed) { + if (!ist->discard) { ret = process_input_packet(ist, NULL, 0); if (ret>0) return 0; diff --git a/fftools/ffmpeg.h b/fftools/ffmpeg.h index 823218e2142..791deedc071 100644 --- a/fftools/ffmpeg.h +++ b/fftools/ffmpeg.h @@ -342,7 +342,6 @@ typedef struct InputStream { int decoding_needed; /* non zero if the packets must be decoded in 'raw_fifo', see DECODING_FOR_* */ #define DECODING_FOR_OST 1 #define DECODING_FOR_FILTER 2 - int processing_needed; /* non zero if the packets must be processed */ // should attach FrameData as opaque_ref after decoding int want_frame_data; diff --git a/fftools/ffmpeg_filter.c b/fftools/ffmpeg_filter.c index 4fde1200674..314b89b5850 100644 --- a/fftools/ffmpeg_filter.c +++ b/fftools/ffmpeg_filter.c @@ -296,7 +296,6 @@ static void init_input_filter(FilterGraph *fg, AVFilterInOut *in) ist->discard = 0; ist->decoding_needed |= DECODING_FOR_FILTER; - ist->processing_needed = 1; ist->st->discard = AVDISCARD_NONE; ifilter = ALLOC_ARRAY_ELEM(fg->inputs, fg->nb_inputs); diff --git a/fftools/ffmpeg_mux_init.c b/fftools/ffmpeg_mux_init.c index bfe2abbe0b0..f426db5820f 100644 --- a/fftools/ffmpeg_mux_init.c +++ b/fftools/ffmpeg_mux_init.c @@ -2283,7 +2283,6 @@ int of_open(const OptionsContext *o, const char *filename) if (ost->enc_ctx && ost->ist) { InputStream *ist = ost->ist; ist->decoding_needed |= DECODING_FOR_OST; - ist->processing_needed = 1; if (ost->st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO || ost->st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) { @@ -2294,8 +2293,6 @@ int of_open(const OptionsContext *o, const char *filename) exit_program(1); } } - } else if (ost->ist) { - ost->ist->processing_needed = 1; } /* set the filter output constraints */ From 87e9f5ad3c119b1058c66bcc5747f1417e0fbddc Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Mon, 20 Mar 2023 17:01:59 +0100 Subject: [PATCH 0602/2172] fftools/ffmpeg: move initializing next_[pd]ts to add_input_streams() They are initialized to constants, so it makes most sense to do it as soon as possible. --- fftools/ffmpeg.c | 3 --- fftools/ffmpeg_demux.c | 3 +++ 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/fftools/ffmpeg.c b/fftools/ffmpeg.c index 3a68640cada..b273f3e4779 100644 --- a/fftools/ffmpeg.c +++ b/fftools/ffmpeg.c @@ -2848,9 +2848,6 @@ static int init_input_stream(InputStream *ist, char *error, int error_len) assert_avoptions(ist->decoder_opts); } - ist->next_pts = AV_NOPTS_VALUE; - ist->next_dts = AV_NOPTS_VALUE; - return 0; } diff --git a/fftools/ffmpeg_demux.c b/fftools/ffmpeg_demux.c index db05ddb8e90..354d3165c9c 100644 --- a/fftools/ffmpeg_demux.c +++ b/fftools/ffmpeg_demux.c @@ -675,6 +675,9 @@ static void add_input_streams(const OptionsContext *o, Demuxer *d) st->discard = AVDISCARD_ALL; ist->nb_samples = 0; ist->first_dts = AV_NOPTS_VALUE; + ist->next_pts = AV_NOPTS_VALUE; + ist->next_dts = AV_NOPTS_VALUE; + ds->min_pts = INT64_MAX; ds->max_pts = INT64_MIN; From 090950f8327c01b1775615b1da723dc6cc8a30a0 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Tue, 21 Mar 2023 12:36:03 +0100 Subject: [PATCH 0603/2172] fftools/sync_queue: use timebase from input frames/packets They are always properly set now. Avoid a separate timebase-setting call, which duplicates the knowledge of the timebase being used. --- fftools/ffmpeg.c | 3 --- fftools/ffmpeg_mux.c | 3 --- fftools/sync_queue.c | 39 ++++++++++++++++++++++----------------- fftools/sync_queue.h | 6 ------ 4 files changed, 22 insertions(+), 29 deletions(-) diff --git a/fftools/ffmpeg.c b/fftools/ffmpeg.c index b273f3e4779..b407b6f9072 100644 --- a/fftools/ffmpeg.c +++ b/fftools/ffmpeg.c @@ -3194,9 +3194,6 @@ static int init_output_stream_encode(OutputStream *ost, AVFrame *frame) if (ost->bitexact) enc_ctx->flags |= AV_CODEC_FLAG_BITEXACT; - if (ost->sq_idx_encode >= 0) - sq_set_tb(of->sq_encode, ost->sq_idx_encode, enc_ctx->time_base); - ost->mux_timebase = enc_ctx->time_base; return 0; diff --git a/fftools/ffmpeg_mux.c b/fftools/ffmpeg_mux.c index cf580519495..1937bc2aa79 100644 --- a/fftools/ffmpeg_mux.c +++ b/fftools/ffmpeg_mux.c @@ -586,9 +586,6 @@ int of_stream_init(OutputFile *of, OutputStream *ost) MuxStream *ms = ms_from_ost(ost); int ret; - if (ost->sq_idx_mux >= 0) - sq_set_tb(mux->sq_mux, ost->sq_idx_mux, ost->mux_timebase); - /* 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/sync_queue.c b/fftools/sync_queue.c index c2b23ee4f5a..7c348af3002 100644 --- a/fftools/sync_queue.c +++ b/fftools/sync_queue.c @@ -84,6 +84,26 @@ static int frame_null(const SyncQueue *sq, SyncQueueFrame frame) return (sq->type == SYNC_QUEUE_PACKETS) ? (frame.p == NULL) : (frame.f == NULL); } +static void tb_update(const SyncQueue *sq, SyncQueueStream *st, + const SyncQueueFrame frame) +{ + AVRational tb = (sq->type == SYNC_QUEUE_PACKETS) ? + frame.p->time_base : frame.f->time_base; + + av_assert0(tb.num > 0 && tb.den > 0); + + if (tb.num == st->tb.num && tb.den == st->tb.den) + return; + + // timebase should not change after the first frame + av_assert0(!av_fifo_can_read(st->fifo)); + + if (st->head_ts != AV_NOPTS_VALUE) + st->head_ts = av_rescale_q(st->head_ts, st->tb, tb); + + st->tb = tb; +} + static void finish_stream(SyncQueue *sq, unsigned int stream_idx) { SyncQueueStream *st = &sq->streams[stream_idx]; @@ -241,8 +261,6 @@ int sq_send(SyncQueue *sq, unsigned int stream_idx, SyncQueueFrame frame) av_assert0(stream_idx < sq->nb_streams); st = &sq->streams[stream_idx]; - av_assert0(st->tb.num > 0 && st->tb.den > 0); - if (frame_null(sq, frame)) { finish_stream(sq, stream_idx); return 0; @@ -250,6 +268,8 @@ int sq_send(SyncQueue *sq, unsigned int stream_idx, SyncQueueFrame frame) if (st->finished) return AVERROR_EOF; + tb_update(sq, st, frame); + ret = objpool_get(sq->pool, (void**)&dst); if (ret < 0) return ret; @@ -375,21 +395,6 @@ int sq_add_stream(SyncQueue *sq, int limiting) return sq->nb_streams++; } -void sq_set_tb(SyncQueue *sq, unsigned int stream_idx, AVRational tb) -{ - SyncQueueStream *st; - - av_assert0(stream_idx < sq->nb_streams); - st = &sq->streams[stream_idx]; - - av_assert0(!av_fifo_can_read(st->fifo)); - - if (st->head_ts != AV_NOPTS_VALUE) - st->head_ts = av_rescale_q(st->head_ts, st->tb, tb); - - st->tb = tb; -} - void sq_limit_frames(SyncQueue *sq, unsigned int stream_idx, uint64_t frames) { SyncQueueStream *st; diff --git a/fftools/sync_queue.h b/fftools/sync_queue.h index 3f823ff0d91..17d282c38c0 100644 --- a/fftools/sync_queue.h +++ b/fftools/sync_queue.h @@ -59,12 +59,6 @@ void sq_free(SyncQueue **sq); */ int sq_add_stream(SyncQueue *sq, int limiting); -/** - * Set the timebase for the stream with index stream_idx. Should be called - * before sending any frames for this stream. - */ -void sq_set_tb(SyncQueue *sq, unsigned int stream_idx, AVRational tb); - /** * Limit the number of output frames for stream with index stream_idx * to max_frames. From 98b41d0bd22258618fd8885368e8493e56208ccb Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Wed, 13 Apr 2022 09:30:52 +0200 Subject: [PATCH 0604/2172] fftools/sync_queue: document overall design --- fftools/sync_queue.c | 35 +++++++++++++++++++++++++++++++++++ fftools/sync_queue.h | 5 +++++ 2 files changed, 40 insertions(+) diff --git a/fftools/sync_queue.c b/fftools/sync_queue.c index 7c348af3002..0aee4ef5ffc 100644 --- a/fftools/sync_queue.c +++ b/fftools/sync_queue.c @@ -28,6 +28,41 @@ #include "objpool.h" #include "sync_queue.h" +/* + * How this works: + * -------------- + * time: 0 1 2 3 4 5 6 7 8 9 10 11 12 13 + * ------------------------------------------------------------------- + * | | | | | | | | | | | | | | + * | ┌───┐┌────────┐┌───┐┌─────────────┐ + * stream 0| │d=1││ d=2 ││d=1││ d=3 │ + * | └───┘└────────┘└───┘└─────────────┘ + * ┌───┐ ┌───────────────────────┐ + * stream 1│d=1│ │ d=5 │ + * └───┘ └───────────────────────┘ + * | ┌───┐┌───┐┌───┐┌───┐ + * stream 2| │d=1││d=1││d=1││d=1│ <- stream 2 is the head stream of the queue + * | └───┘└───┘└───┘└───┘ + * ^ ^ + * [stream 2 tail] [stream 2 head] + * + * We have N streams (N=3 in the diagram), each stream is a FIFO. The *tail* of + * each FIFO is the frame with smallest end time, the *head* is the frame with + * the largest end time. Frames submitted to the queue with sq_send() are placed + * after the head, frames returned to the caller with sq_receive() are taken + * from the tail. + * + * The head stream of the whole queue (SyncQueue.head_stream) is the limiting + * stream with the *smallest* head timestamp, i.e. the stream whose source lags + * furthest behind all other streams. It determines which frames can be output + * from the queue. + * + * In the diagram, the head stream is 2, because it head time is t=5, while + * streams 0 and 1 end at t=8 and t=9 respectively. All frames that _end_ at + * or before t=5 can be output, i.e. the first 3 frames from stream 0, first + * frame from stream 1, and all 4 frames from stream 2. + */ + typedef struct SyncQueueStream { AVFifo *fifo; AVRational tb; diff --git a/fftools/sync_queue.h b/fftools/sync_queue.h index 17d282c38c0..9659ee5d500 100644 --- a/fftools/sync_queue.h +++ b/fftools/sync_queue.h @@ -38,6 +38,11 @@ typedef union SyncQueueFrame { #define SQFRAME(frame) ((SyncQueueFrame){ .f = (frame) }) #define SQPKT(pkt) ((SyncQueueFrame){ .p = (pkt) }) +/** + * A sync queue provides timestamp synchronization between multiple streams. + * Some of these streams are marked as "limiting", then the queue ensures no + * stream gets ahead of any of the limiting streams. + */ typedef struct SyncQueue SyncQueue; /** From 9a85245adfdb259da27a50e7822a7c842e5a3247 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Wed, 22 Mar 2023 12:03:16 +0100 Subject: [PATCH 0605/2172] fftools/sync_queue: support operation with no limiting streams ffmpeg CLI will not create such queues currently, but this will become useful in following commits. --- fftools/sync_queue.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/fftools/sync_queue.c b/fftools/sync_queue.c index 0aee4ef5ffc..4204a821c14 100644 --- a/fftools/sync_queue.c +++ b/fftools/sync_queue.c @@ -96,6 +96,8 @@ struct SyncQueue { // pool of preallocated frames to avoid constant allocations ObjPool *pool; + + int have_limiting; }; static void frame_move(const SyncQueue *sq, SyncQueueFrame dst, @@ -354,8 +356,9 @@ static int receive_for_stream(SyncQueue *sq, unsigned int stream_idx, /* We can release frames that do not end after the queue head. * Frames with no timestamps are just passed through with no conditions. + * Frames are also passed through when there are no limiting streams. */ - if (cmp <= 0 || ts == AV_NOPTS_VALUE) { + if (cmp <= 0 || ts == AV_NOPTS_VALUE || !sq->have_limiting) { frame_move(sq, frame, peek); objpool_release(sq->pool, (void**)&peek); av_fifo_drain2(st->fifo, 1); @@ -427,6 +430,8 @@ int sq_add_stream(SyncQueue *sq, int limiting) st->frames_max = UINT64_MAX; st->limiting = limiting; + sq->have_limiting |= limiting; + return sq->nb_streams++; } From 81cca3dae34b78b367a183fd1726d83f67dbf326 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Wed, 22 Mar 2023 15:09:49 +0100 Subject: [PATCH 0606/2172] fftools/sync_queue: make sure audio duration matches sample count For audio AVFrames, nb_samples is typically more trustworthy than duration. Since sync queues look at durations, make sure they match the sample count. The last audio frame in the fate-shortest test is now gone. This is more correct, since it outlasts the last video frame. --- fftools/sync_queue.c | 15 ++++++++++++++- tests/ref/fate/shortest | 1 - 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/fftools/sync_queue.c b/fftools/sync_queue.c index 4204a821c14..5b98253a4a4 100644 --- a/fftools/sync_queue.c +++ b/fftools/sync_queue.c @@ -116,6 +116,11 @@ static int64_t frame_ts(const SyncQueue *sq, SyncQueueFrame frame) frame.f->pts + frame.f->duration; } +static int frame_samples(const SyncQueue *sq, SyncQueueFrame frame) +{ + return (sq->type == SYNC_QUEUE_PACKETS) ? 0 : frame.f->nb_samples; +} + static int frame_null(const SyncQueue *sq, SyncQueueFrame frame) { return (sq->type == SYNC_QUEUE_PACKETS) ? (frame.p == NULL) : (frame.f == NULL); @@ -293,7 +298,7 @@ int sq_send(SyncQueue *sq, unsigned int stream_idx, SyncQueueFrame frame) SyncQueueStream *st; SyncQueueFrame dst; int64_t ts; - int ret; + int ret, nb_samples; av_assert0(stream_idx < sq->nb_streams); st = &sq->streams[stream_idx]; @@ -313,6 +318,14 @@ int sq_send(SyncQueue *sq, unsigned int stream_idx, SyncQueueFrame frame) frame_move(sq, dst, frame); + nb_samples = frame_samples(sq, dst); + // make sure frame duration is consistent with sample count + if (nb_samples) { + av_assert0(dst.f->sample_rate > 0); + dst.f->duration = av_rescale_q(nb_samples, (AVRational){ 1, dst.f->sample_rate }, + dst.f->time_base); + } + ts = frame_ts(sq, dst); ret = av_fifo_write(st->fifo, &dst, 1); diff --git a/tests/ref/fate/shortest b/tests/ref/fate/shortest index be93ff0da17..b5845508cf9 100644 --- a/tests/ref/fate/shortest +++ b/tests/ref/fate/shortest @@ -115,4 +115,3 @@ 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 f9d3c0653334c0ee17ca01cbcaaab467e24ce0c6 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Thu, 23 Mar 2023 08:38:19 +0100 Subject: [PATCH 0607/2172] fftools/sync_queue: allow requesting a specific number of audio samples This will be made useful in following commits. --- fftools/sync_queue.c | 184 ++++++++++++++++++++++++++++++++++++++++--- fftools/sync_queue.h | 10 +++ 2 files changed, 185 insertions(+), 9 deletions(-) diff --git a/fftools/sync_queue.c b/fftools/sync_queue.c index 5b98253a4a4..42a6b89b79c 100644 --- a/fftools/sync_queue.c +++ b/fftools/sync_queue.c @@ -20,10 +20,13 @@ #include #include "libavutil/avassert.h" +#include "libavutil/channel_layout.h" +#include "libavutil/cpu.h" #include "libavutil/error.h" #include "libavutil/fifo.h" #include "libavutil/mathematics.h" #include "libavutil/mem.h" +#include "libavutil/samplefmt.h" #include "objpool.h" #include "sync_queue.h" @@ -67,6 +70,8 @@ typedef struct SyncQueueStream { AVFifo *fifo; AVRational tb; + /* number of audio samples in fifo */ + uint64_t samples_queued; /* stream head: largest timestamp seen */ int64_t head_ts; int limiting; @@ -74,7 +79,9 @@ typedef struct SyncQueueStream { int finished; uint64_t frames_sent; + uint64_t samples_sent; uint64_t frames_max; + int frame_samples; } SyncQueueStream; struct SyncQueue { @@ -98,6 +105,8 @@ struct SyncQueue { ObjPool *pool; int have_limiting; + + uintptr_t align_mask; }; static void frame_move(const SyncQueue *sq, SyncQueueFrame dst, @@ -109,8 +118,18 @@ static void frame_move(const SyncQueue *sq, SyncQueueFrame dst, av_frame_move_ref(dst.f, src.f); } -static int64_t frame_ts(const SyncQueue *sq, SyncQueueFrame frame) +/** + * Compute the end timestamp of a frame. If nb_samples is provided, consider + * the frame to have this number of audio samples, otherwise use frame duration. + */ +static int64_t frame_end(const SyncQueue *sq, SyncQueueFrame frame, int nb_samples) { + if (nb_samples) { + int64_t d = av_rescale_q(nb_samples, (AVRational){ 1, frame.f->sample_rate}, + frame.f->time_base); + return frame.f->pts + d; + } + return (sq->type == SYNC_QUEUE_PACKETS) ? frame.p->pts + frame.p->duration : frame.f->pts + frame.f->duration; @@ -265,7 +284,7 @@ static int overflow_heartbeat(SyncQueue *sq, int stream_idx) /* get the chosen stream's tail timestamp */ for (size_t i = 0; tail_ts == AV_NOPTS_VALUE && av_fifo_peek(st->fifo, &frame, 1, i) >= 0; i++) - tail_ts = frame_ts(sq, frame); + tail_ts = frame_end(sq, frame, 0); /* overflow triggers when the tail is over specified duration behind the head */ if (tail_ts == AV_NOPTS_VALUE || tail_ts >= st->head_ts || @@ -326,7 +345,7 @@ int sq_send(SyncQueue *sq, unsigned int stream_idx, SyncQueueFrame frame) dst.f->time_base); } - ts = frame_ts(sq, dst); + ts = frame_end(sq, dst, 0); ret = av_fifo_write(st->fifo, &dst, 1); if (ret < 0) { @@ -337,13 +356,131 @@ int sq_send(SyncQueue *sq, unsigned int stream_idx, SyncQueueFrame frame) stream_update_ts(sq, stream_idx, ts); - st->frames_sent++; + st->samples_queued += nb_samples; + st->samples_sent += nb_samples; + + if (st->frame_samples) + st->frames_sent = st->samples_sent / st->frame_samples; + else + st->frames_sent++; + if (st->frames_sent >= st->frames_max) finish_stream(sq, stream_idx); return 0; } +static void offset_audio(AVFrame *f, int nb_samples) +{ + const int planar = av_sample_fmt_is_planar(f->format); + const int planes = planar ? f->ch_layout.nb_channels : 1; + const int bps = av_get_bytes_per_sample(f->format); + const int offset = nb_samples * bps * (planar ? 1 : f->ch_layout.nb_channels); + + av_assert0(bps > 0); + av_assert0(nb_samples < f->nb_samples); + + for (int i = 0; i < planes; i++) { + f->extended_data[i] += offset; + if (i < FF_ARRAY_ELEMS(f->data)) + f->data[i] = f->extended_data[i]; + } + f->linesize[0] -= offset; + f->nb_samples -= nb_samples; + f->duration = av_rescale_q(f->nb_samples, (AVRational){ 1, f->sample_rate }, + f->time_base); + f->pts += av_rescale_q(nb_samples, (AVRational){ 1, f->sample_rate }, + f->time_base); +} + +static int frame_is_aligned(const SyncQueue *sq, const AVFrame *frame) +{ + // only checks linesize[0], so only works for audio + av_assert0(frame->nb_samples > 0); + av_assert0(sq->align_mask); + + // only check data[0], because we always offset all data pointers + // by the same offset, so if one is aligned, all are + if (!((uintptr_t)frame->data[0] & sq->align_mask) && + !(frame->linesize[0] & sq->align_mask) && + frame->linesize[0] > sq->align_mask) + return 1; + + return 0; +} + +static int receive_samples(SyncQueue *sq, SyncQueueStream *st, + AVFrame *dst, int nb_samples) +{ + SyncQueueFrame src; + int ret; + + av_assert0(st->samples_queued >= nb_samples); + + ret = av_fifo_peek(st->fifo, &src, 1, 0); + av_assert0(ret >= 0); + + // peeked frame has enough samples and its data is aligned + // -> we can just make a reference and limit its sample count + if (src.f->nb_samples > nb_samples && frame_is_aligned(sq, src.f)) { + ret = av_frame_ref(dst, src.f); + if (ret < 0) + return ret; + + dst->nb_samples = nb_samples; + offset_audio(src.f, nb_samples); + st->samples_queued -= nb_samples; + + return 0; + } + + // otherwise allocate a new frame and copy the data + ret = av_channel_layout_copy(&dst->ch_layout, &src.f->ch_layout); + if (ret < 0) + return ret; + + dst->format = src.f->format; + dst->nb_samples = nb_samples; + + ret = av_frame_get_buffer(dst, 0); + if (ret < 0) + goto fail; + + ret = av_frame_copy_props(dst, src.f); + if (ret < 0) + goto fail; + + dst->nb_samples = 0; + while (dst->nb_samples < nb_samples) { + int to_copy; + + ret = av_fifo_peek(st->fifo, &src, 1, 0); + av_assert0(ret >= 0); + + to_copy = FFMIN(nb_samples - dst->nb_samples, src.f->nb_samples); + + av_samples_copy(dst->extended_data, src.f->extended_data, dst->nb_samples, + 0, to_copy, dst->ch_layout.nb_channels, dst->format); + + if (to_copy < src.f->nb_samples) + offset_audio(src.f, to_copy); + else { + av_frame_unref(src.f); + objpool_release(sq->pool, (void**)&src); + av_fifo_drain2(st->fifo, 1); + } + st->samples_queued -= to_copy; + + dst->nb_samples += to_copy; + } + + return 0; + +fail: + av_frame_unref(dst); + return ret; +} + static int receive_for_stream(SyncQueue *sq, unsigned int stream_idx, SyncQueueFrame frame) { @@ -354,13 +491,18 @@ static int receive_for_stream(SyncQueue *sq, unsigned int stream_idx, av_assert0(stream_idx < sq->nb_streams); st = &sq->streams[stream_idx]; - if (av_fifo_can_read(st->fifo)) { + if (av_fifo_can_read(st->fifo) && + (st->frame_samples <= st->samples_queued || st->finished)) { + int nb_samples = st->frame_samples; SyncQueueFrame peek; int64_t ts; int cmp = 1; + if (st->finished) + nb_samples = FFMIN(nb_samples, st->samples_queued); + av_fifo_peek(st->fifo, &peek, 1, 0); - ts = frame_ts(sq, peek); + ts = frame_end(sq, peek, nb_samples); /* check if this stream's tail timestamp does not overtake * the overall queue head */ @@ -372,9 +514,19 @@ static int receive_for_stream(SyncQueue *sq, unsigned int stream_idx, * Frames are also passed through when there are no limiting streams. */ if (cmp <= 0 || ts == AV_NOPTS_VALUE || !sq->have_limiting) { - frame_move(sq, frame, peek); - objpool_release(sq->pool, (void**)&peek); - av_fifo_drain2(st->fifo, 1); + if (nb_samples && + (nb_samples != peek.f->nb_samples || !frame_is_aligned(sq, peek.f))) { + int ret = receive_samples(sq, st, frame.f, nb_samples); + if (ret < 0) + return ret; + } else { + frame_move(sq, frame, peek); + objpool_release(sq->pool, (void**)&peek); + av_fifo_drain2(st->fifo, 1); + av_assert0(st->samples_queued >= frame_samples(sq, frame)); + st->samples_queued -= frame_samples(sq, frame); + } + return 0; } } @@ -460,6 +612,20 @@ void sq_limit_frames(SyncQueue *sq, unsigned int stream_idx, uint64_t frames) finish_stream(sq, stream_idx); } +void sq_frame_samples(SyncQueue *sq, unsigned int stream_idx, + int frame_samples) +{ + SyncQueueStream *st; + + av_assert0(sq->type == SYNC_QUEUE_FRAMES); + av_assert0(stream_idx < sq->nb_streams); + st = &sq->streams[stream_idx]; + + st->frame_samples = frame_samples; + + sq->align_mask = av_cpu_max_align() - 1; +} + SyncQueue *sq_alloc(enum SyncQueueType type, int64_t buf_size_us) { SyncQueue *sq = av_mallocz(sizeof(*sq)); diff --git a/fftools/sync_queue.h b/fftools/sync_queue.h index 9659ee5d500..bc7cd423907 100644 --- a/fftools/sync_queue.h +++ b/fftools/sync_queue.h @@ -71,6 +71,16 @@ int sq_add_stream(SyncQueue *sq, int limiting); void sq_limit_frames(SyncQueue *sq, unsigned int stream_idx, uint64_t max_frames); +/** + * Set a constant output audio frame size, in samples. Can only be used with + * SYNC_QUEUE_FRAMES queues and audio streams. + * + * All output frames will have exactly frame_samples audio samples, except + * possibly for the last one, which may have fewer. + */ +void sq_frame_samples(SyncQueue *sq, unsigned int stream_idx, + int frame_samples); + /** * Submit a frame for the stream with index stream_idx. * From 923c6ab170669793d3311cbfd465a967d44f1636 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Fri, 24 Mar 2023 08:59:05 +0100 Subject: [PATCH 0608/2172] fftools/ffmpeg: use sync queues for enforcing audio frame size The code currently uses lavfi for this, which creates a sort of configuration dependency loop - the encoder should be ideally initialized with information from the first audio frame, but to get this frame one needs to first open the encoder to know the frame size. This necessitates an awkward workaround, which causes audio handling to be different from video. With this change, audio encoder initialization is congruent with video. --- fftools/ffmpeg.c | 58 ++++++++------------------------------- fftools/ffmpeg_filter.c | 8 ------ fftools/ffmpeg_mux_init.c | 19 +++++++++---- 3 files changed, 25 insertions(+), 60 deletions(-) diff --git a/fftools/ffmpeg.c b/fftools/ffmpeg.c index b407b6f9072..28f7d70b31c 100644 --- a/fftools/ffmpeg.c +++ b/fftools/ffmpeg.c @@ -1028,6 +1028,8 @@ static void do_audio_out(OutputFile *of, OutputStream *ost, AVCodecContext *enc = ost->enc_ctx; int ret; + init_output_stream_wrapper(ost, frame, 1); + if (frame->pts == AV_NOPTS_VALUE) frame->pts = ost->next_pts; else { @@ -1378,18 +1380,6 @@ static int reap_filters(int flush) continue; filter = ost->filter->filter; - /* - * Unlike video, with audio the audio frame size matters. - * Currently we are fully reliant on the lavfi filter chain to - * do the buffering deed for us, and thus the frame size parameter - * needs to be set accordingly. Where does one get the required - * frame size? From the initialized AVCodecContext of an audio - * encoder. Thus, if we have gotten to an audio stream, initialize - * the encoder earlier than receiving the first AVFrame. - */ - if (av_buffersink_get_type(filter) == AVMEDIA_TYPE_AUDIO) - init_output_stream_wrapper(ost, NULL, 1); - filtered_frame = ost->filtered_frame; while (1) { @@ -1432,6 +1422,7 @@ static int reap_filters(int flush) break; case AVMEDIA_TYPE_AUDIO: if (!(enc->codec->capabilities & AV_CODEC_CAP_PARAM_CHANGE) && + avcodec_is_open(enc) && enc->ch_layout.nb_channels != filtered_frame->ch_layout.nb_channels) { av_log(NULL, AV_LOG_ERROR, "Audio filter graph output is not normalized and encoder does not support parameter changes\n"); @@ -3238,10 +3229,13 @@ static int init_output_stream(OutputStream *ost, AVFrame *frame, ost->file_index, ost->index); return ret; } - if (codec->type == AVMEDIA_TYPE_AUDIO && - !(codec->capabilities & AV_CODEC_CAP_VARIABLE_FRAME_SIZE)) - av_buffersink_set_frame_size(ost->filter->filter, - ost->enc_ctx->frame_size); + + if (ost->enc_ctx->frame_size) { + av_assert0(ost->sq_idx_encode >= 0); + sq_frame_samples(output_files[ost->file_index]->sq_encode, + ost->sq_idx_encode, ost->enc_ctx->frame_size); + } + assert_avoptions(ost->encoder_opts); if (ost->enc_ctx->bit_rate && ost->enc_ctx->bit_rate < 1000 && ost->enc_ctx->codec_id != AV_CODEC_ID_CODEC2 /* don't complain about 700 bit/s modes */) @@ -3331,12 +3325,8 @@ static int transcode_init(void) /* * initialize stream copy and subtitle/data streams. - * Encoded AVFrame based streams will get initialized as follows: - * - when the first AVFrame is received in do_video_out - * - just before the first AVFrame is received in either transcode_step - * or reap_filters due to us requiring the filter chain buffer sink - * to be configured with the correct audio frame size, which is only - * known after the encoder is initialized. + * Encoded AVFrame based streams will get initialized when the first AVFrame + * is received in do_video_out */ for (OutputStream *ost = ost_iter(NULL); ost; ost = ost_iter(ost)) { if (ost->enc_ctx && @@ -3943,30 +3933,6 @@ static int transcode_step(void) } if (ost->filter && ost->filter->graph->graph) { - /* - * Similar case to the early audio initialization in reap_filters. - * Audio is special in ffmpeg.c currently as we depend on lavfi's - * audio frame buffering/creation to get the output audio frame size - * in samples correct. The audio frame size for the filter chain is - * configured during the output stream initialization. - * - * Apparently avfilter_graph_request_oldest (called in - * transcode_from_filter just down the line) peeks. Peeking already - * puts one frame "ready to be given out", which means that any - * update in filter buffer sink configuration afterwards will not - * help us. And yes, even if it would be utilized, - * av_buffersink_get_samples is affected, as it internally utilizes - * the same early exit for peeked frames. - * - * In other words, if avfilter_graph_request_oldest would not make - * further filter chain configuration or usage of - * av_buffersink_get_samples useless (by just causing the return - * of the peeked AVFrame as-is), we could get rid of this additional - * early encoder initialization. - */ - if (av_buffersink_get_type(ost->filter->filter) == AVMEDIA_TYPE_AUDIO) - init_output_stream_wrapper(ost, NULL, 1); - if ((ret = transcode_from_filter(ost->filter->graph, &ist)) < 0) return ret; if (!ist) diff --git a/fftools/ffmpeg_filter.c b/fftools/ffmpeg_filter.c index 314b89b5850..c9fd65e9022 100644 --- a/fftools/ffmpeg_filter.c +++ b/fftools/ffmpeg_filter.c @@ -1242,14 +1242,6 @@ int configure_filtergraph(FilterGraph *fg) fg->reconfiguration = 1; - for (i = 0; i < fg->nb_outputs; i++) { - OutputStream *ost = fg->outputs[i]->ost; - if (ost->enc_ctx->codec_type == AVMEDIA_TYPE_AUDIO && - !(ost->enc_ctx->codec->capabilities & AV_CODEC_CAP_VARIABLE_FRAME_SIZE)) - av_buffersink_set_frame_size(ost->filter->filter, - ost->enc_ctx->frame_size); - } - for (i = 0; i < fg->nb_inputs; i++) { AVFrame *tmp; while (av_fifo_read(fg->inputs[i]->frame_queue, &tmp, 1) >= 0) { diff --git a/fftools/ffmpeg_mux_init.c b/fftools/ffmpeg_mux_init.c index f426db5820f..2e9bdcfde1a 100644 --- a/fftools/ffmpeg_mux_init.c +++ b/fftools/ffmpeg_mux_init.c @@ -1451,7 +1451,7 @@ static void create_streams(Muxer *mux, const OptionsContext *o) static int setup_sync_queues(Muxer *mux, AVFormatContext *oc, int64_t buf_size_us) { OutputFile *of = &mux->of; - int nb_av_enc = 0, nb_interleaved = 0; + int nb_av_enc = 0, nb_audio_fs = 0, nb_interleaved = 0; int limit_frames = 0, limit_frames_av_enc = 0; #define IS_AV_ENC(ost, type) \ @@ -1468,19 +1468,26 @@ static int setup_sync_queues(Muxer *mux, AVFormatContext *oc, int64_t buf_size_u nb_interleaved += IS_INTERLEAVED(type); nb_av_enc += IS_AV_ENC(ost, type); + nb_audio_fs += (ost->enc_ctx && type == AVMEDIA_TYPE_AUDIO && + !(ost->enc_ctx->codec->capabilities & AV_CODEC_CAP_VARIABLE_FRAME_SIZE)); limit_frames |= ms->max_frames < INT64_MAX; limit_frames_av_enc |= (ms->max_frames < INT64_MAX) && IS_AV_ENC(ost, type); } if (!((nb_interleaved > 1 && of->shortest) || - (nb_interleaved > 0 && limit_frames))) + (nb_interleaved > 0 && limit_frames) || + nb_audio_fs)) return 0; - /* if we have more than one encoded audio/video streams, or at least - * one encoded audio/video stream is frame-limited, then we - * synchronize them before encoding */ - if ((of->shortest && nb_av_enc > 1) || limit_frames_av_enc) { + /* we use a sync queue before encoding when: + * - 'shortest' is in effect and we have two or more encoded audio/video + * streams + * - at least one encoded audio/video stream is frame-limited, since + * that has similar semantics to 'shortest' + * - at least one audio encoder requires constant frame sizes + */ + if ((of->shortest && nb_av_enc > 1) || limit_frames_av_enc || nb_audio_fs) { of->sq_encode = sq_alloc(SYNC_QUEUE_FRAMES, buf_size_us); if (!of->sq_encode) return AVERROR(ENOMEM); From 237f9b9682a0f18345dcf6841527a795a32b3eb5 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Fri, 24 Mar 2023 17:12:32 +0100 Subject: [PATCH 0609/2172] fftools/ffmpeg: stop handling AVMEDIA_TYPE_DATA in init_output_stream_encode() We do not support data encoders, so this should never be reached. --- fftools/ffmpeg.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/fftools/ffmpeg.c b/fftools/ffmpeg.c index 28f7d70b31c..d74145183ee 100644 --- a/fftools/ffmpeg.c +++ b/fftools/ffmpeg.c @@ -3174,8 +3174,6 @@ static int init_output_stream_encode(OutputStream *ost, AVFrame *frame) } } - break; - case AVMEDIA_TYPE_DATA: break; default: abort(); From e1e0c2c7f2f499ca47401d75140cfd3042e3bb8a Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Fri, 24 Mar 2023 17:26:04 +0100 Subject: [PATCH 0610/2172] fftools/ffmpeg: drop unnecessary indirection init_output_stream() can print log messages directly, there is no need to ship them to the caller. --- fftools/ffmpeg.c | 23 +++++++---------------- 1 file changed, 7 insertions(+), 16 deletions(-) diff --git a/fftools/ffmpeg.c b/fftools/ffmpeg.c index d74145183ee..8c0121a066c 100644 --- a/fftools/ffmpeg.c +++ b/fftools/ffmpeg.c @@ -724,23 +724,18 @@ static double adjust_frame_pts_to_encoder_tb(OutputFile *of, OutputStream *ost, return float_pts; } -static int init_output_stream(OutputStream *ost, AVFrame *frame, - char *error, int error_len); +static int init_output_stream(OutputStream *ost, AVFrame *frame); static int init_output_stream_wrapper(OutputStream *ost, AVFrame *frame, unsigned int fatal) { int ret = AVERROR_BUG; - char error[1024] = {0}; if (ost->initialized) return 0; - ret = init_output_stream(ost, frame, error, sizeof(error)); + ret = init_output_stream(ost, frame); if (ret < 0) { - av_log(ost, AV_LOG_ERROR, "Error initializing output stream: %s\n", - error); - if (fatal) exit_program(1); } @@ -3188,8 +3183,7 @@ static int init_output_stream_encode(OutputStream *ost, AVFrame *frame) return 0; } -static int init_output_stream(OutputStream *ost, AVFrame *frame, - char *error, int error_len) +static int init_output_stream(OutputStream *ost, AVFrame *frame) { int ret = 0; @@ -3212,19 +3206,16 @@ static int init_output_stream(OutputStream *ost, AVFrame *frame, ret = hw_device_setup_for_encode(ost); if (ret < 0) { - snprintf(error, error_len, "Device setup failed for " - "encoder on output stream #%d:%d : %s", - ost->file_index, ost->index, av_err2str(ret)); + av_log(ost, AV_LOG_ERROR, + "Encoding hardware device setup failed: %s\n", av_err2str(ret)); return ret; } if ((ret = avcodec_open2(ost->enc_ctx, codec, &ost->encoder_opts)) < 0) { if (ret == AVERROR_EXPERIMENTAL) abort_codec_experimental(codec, 1); - snprintf(error, error_len, - "Error while opening encoder for output stream #%d:%d - " - "maybe incorrect parameters such as bit_rate, rate, width or height", - ost->file_index, ost->index); + av_log(ost, AV_LOG_ERROR, "Error while opening encoder - maybe " + "incorrect parameters such as bit_rate, rate, width or height.\n"); return ret; } From e1fe6c5577a3d298b1ad5be5555774b4a3becdfc Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Fri, 24 Mar 2023 17:30:07 +0100 Subject: [PATCH 0611/2172] fftools/ffmpeg: use stack variables to shorten code --- fftools/ffmpeg.c | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/fftools/ffmpeg.c b/fftools/ffmpeg.c index 8c0121a066c..90ca5dd3ebe 100644 --- a/fftools/ffmpeg.c +++ b/fftools/ffmpeg.c @@ -3018,6 +3018,7 @@ static int init_output_stream_encode(OutputStream *ost, AVFrame *frame) InputStream *ist = ost->ist; AVCodecContext *enc_ctx = ost->enc_ctx; AVCodecContext *dec_ctx = NULL; + const AVCodec *enc = enc_ctx->codec; OutputFile *of = output_files[ost->file_index]; int ret; @@ -3044,9 +3045,9 @@ static int init_output_stream_encode(OutputStream *ost, AVFrame *frame) !ost->frame_rate.den)) ost->frame_rate = ost->max_frame_rate; - if (enc_ctx->codec->supported_framerates && !ost->force_fps) { - int idx = av_find_nearest_q_idx(ost->frame_rate, enc_ctx->codec->supported_framerates); - ost->frame_rate = enc_ctx->codec->supported_framerates[idx]; + if (enc->supported_framerates && !ost->force_fps) { + int idx = av_find_nearest_q_idx(ost->frame_rate, enc->supported_framerates); + ost->frame_rate = enc->supported_framerates[idx]; } // reduce frame rate for mpeg4 to be within the spec limits if (enc_ctx->codec_id == AV_CODEC_ID_MPEG4) { @@ -3119,7 +3120,7 @@ static int init_output_stream_encode(OutputStream *ost, AVFrame *frame) frame->top_field_first = !!ost->top_field_first; if (frame->interlaced_frame) { - if (enc_ctx->codec->id == AV_CODEC_ID_MJPEG) + if (enc->id == AV_CODEC_ID_MJPEG) enc_ctx->field_order = frame->top_field_first ? AV_FIELD_TT:AV_FIELD_BB; else enc_ctx->field_order = frame->top_field_first ? AV_FIELD_TB:AV_FIELD_BT; @@ -3143,12 +3144,12 @@ static int init_output_stream_encode(OutputStream *ost, AVFrame *frame) } if (dec_ctx && dec_ctx->subtitle_header) { /* ASS code assumes this buffer is null terminated so add extra byte. */ - ost->enc_ctx->subtitle_header = av_mallocz(dec_ctx->subtitle_header_size + 1); - if (!ost->enc_ctx->subtitle_header) + enc_ctx->subtitle_header = av_mallocz(dec_ctx->subtitle_header_size + 1); + if (!enc_ctx->subtitle_header) return AVERROR(ENOMEM); - memcpy(ost->enc_ctx->subtitle_header, dec_ctx->subtitle_header, + memcpy(enc_ctx->subtitle_header, dec_ctx->subtitle_header, dec_ctx->subtitle_header_size); - ost->enc_ctx->subtitle_header_size = dec_ctx->subtitle_header_size; + enc_ctx->subtitle_header_size = dec_ctx->subtitle_header_size; } if (ist && ist->dec->type == AVMEDIA_TYPE_SUBTITLE && enc_ctx->codec_type == AVMEDIA_TYPE_SUBTITLE) { @@ -3156,7 +3157,7 @@ static int init_output_stream_encode(OutputStream *ost, AVFrame *frame) AVCodecDescriptor const *input_descriptor = avcodec_descriptor_get(ist->dec->id); AVCodecDescriptor const *output_descriptor = - avcodec_descriptor_get(ost->enc_ctx->codec_id); + avcodec_descriptor_get(enc_ctx->codec_id); if (input_descriptor) input_props = input_descriptor->props & (AV_CODEC_PROP_TEXT_SUB | AV_CODEC_PROP_BITMAP_SUB); if (output_descriptor) From 39291f19e2bd13df98e729705886ab199f95b410 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Fri, 24 Mar 2023 17:51:38 +0100 Subject: [PATCH 0612/2172] fftools/ffmpeg: move encoder initialization to init_output_stream_encode Encoder initialization is currently split rather arbitrarily between init_output_stream_encode() and init_output_stream(). Move all of it to init_output_stream_encode(). --- fftools/ffmpeg.c | 37 +++++++++++++++++-------------------- 1 file changed, 17 insertions(+), 20 deletions(-) diff --git a/fftools/ffmpeg.c b/fftools/ffmpeg.c index 90ca5dd3ebe..0bc9850cf9b 100644 --- a/fftools/ffmpeg.c +++ b/fftools/ffmpeg.c @@ -3179,27 +3179,10 @@ static int init_output_stream_encode(OutputStream *ost, AVFrame *frame) if (ost->bitexact) enc_ctx->flags |= AV_CODEC_FLAG_BITEXACT; - ost->mux_timebase = enc_ctx->time_base; - - return 0; -} - -static int init_output_stream(OutputStream *ost, AVFrame *frame) -{ - int ret = 0; - - if (ost->enc_ctx) { - const AVCodec *codec = ost->enc_ctx->codec; - InputStream *ist = ost->ist; - - ret = init_output_stream_encode(ost, frame); - if (ret < 0) - return ret; - if (!av_dict_get(ost->encoder_opts, "threads", NULL, 0)) av_dict_set(&ost->encoder_opts, "threads", "auto", 0); - if (codec->capabilities & AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE) { + if (enc->capabilities & AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE) { ret = av_dict_set(&ost->encoder_opts, "flags", "+copy_opaque", AV_DICT_MULTIKEY); if (ret < 0) return ret; @@ -3212,9 +3195,9 @@ static int init_output_stream(OutputStream *ost, AVFrame *frame) return ret; } - if ((ret = avcodec_open2(ost->enc_ctx, codec, &ost->encoder_opts)) < 0) { + if ((ret = avcodec_open2(ost->enc_ctx, enc, &ost->encoder_opts)) < 0) { if (ret == AVERROR_EXPERIMENTAL) - abort_codec_experimental(codec, 1); + abort_codec_experimental(enc, 1); av_log(ost, AV_LOG_ERROR, "Error while opening encoder - maybe " "incorrect parameters such as bit_rate, rate, width or height.\n"); return ret; @@ -3282,6 +3265,20 @@ static int init_output_stream(OutputStream *ost, AVFrame *frame) // copy estimated duration as a hint to the muxer if (ost->st->duration <= 0 && ist && ist->st->duration > 0) ost->st->duration = av_rescale_q(ist->st->duration, ist->st->time_base, ost->st->time_base); + + ost->mux_timebase = enc_ctx->time_base; + + return 0; +} + +static int init_output_stream(OutputStream *ost, AVFrame *frame) +{ + int ret = 0; + + if (ost->enc_ctx) { + ret = init_output_stream_encode(ost, frame); + if (ret < 0) + return ret; } else if (ost->ist) { ret = init_output_stream_streamcopy(ost); if (ret < 0) From 1dabd4851928b868e62ae8a0b006eb2568dda62e Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Fri, 24 Mar 2023 17:53:03 +0100 Subject: [PATCH 0613/2172] fftools/ffmpeg: reindent after previous commit --- fftools/ffmpeg.c | 142 +++++++++++++++++++++++------------------------ 1 file changed, 71 insertions(+), 71 deletions(-) diff --git a/fftools/ffmpeg.c b/fftools/ffmpeg.c index 0bc9850cf9b..42b2735fb4d 100644 --- a/fftools/ffmpeg.c +++ b/fftools/ffmpeg.c @@ -3179,92 +3179,92 @@ static int init_output_stream_encode(OutputStream *ost, AVFrame *frame) if (ost->bitexact) enc_ctx->flags |= AV_CODEC_FLAG_BITEXACT; - if (!av_dict_get(ost->encoder_opts, "threads", NULL, 0)) - av_dict_set(&ost->encoder_opts, "threads", "auto", 0); + if (!av_dict_get(ost->encoder_opts, "threads", NULL, 0)) + av_dict_set(&ost->encoder_opts, "threads", "auto", 0); - if (enc->capabilities & AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE) { - ret = av_dict_set(&ost->encoder_opts, "flags", "+copy_opaque", AV_DICT_MULTIKEY); - if (ret < 0) - return ret; - } - - ret = hw_device_setup_for_encode(ost); - if (ret < 0) { - av_log(ost, AV_LOG_ERROR, - "Encoding hardware device setup failed: %s\n", av_err2str(ret)); + if (enc->capabilities & AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE) { + ret = av_dict_set(&ost->encoder_opts, "flags", "+copy_opaque", AV_DICT_MULTIKEY); + if (ret < 0) return ret; - } + } - if ((ret = avcodec_open2(ost->enc_ctx, enc, &ost->encoder_opts)) < 0) { - if (ret == AVERROR_EXPERIMENTAL) - abort_codec_experimental(enc, 1); - av_log(ost, AV_LOG_ERROR, "Error while opening encoder - maybe " - "incorrect parameters such as bit_rate, rate, width or height.\n"); - return ret; - } + ret = hw_device_setup_for_encode(ost); + if (ret < 0) { + av_log(ost, AV_LOG_ERROR, + "Encoding hardware device setup failed: %s\n", av_err2str(ret)); + return ret; + } - if (ost->enc_ctx->frame_size) { - av_assert0(ost->sq_idx_encode >= 0); - sq_frame_samples(output_files[ost->file_index]->sq_encode, - ost->sq_idx_encode, ost->enc_ctx->frame_size); - } + if ((ret = avcodec_open2(ost->enc_ctx, enc, &ost->encoder_opts)) < 0) { + if (ret == AVERROR_EXPERIMENTAL) + abort_codec_experimental(enc, 1); + av_log(ost, AV_LOG_ERROR, "Error while opening encoder - maybe " + "incorrect parameters such as bit_rate, rate, width or height.\n"); + return ret; + } - assert_avoptions(ost->encoder_opts); - if (ost->enc_ctx->bit_rate && ost->enc_ctx->bit_rate < 1000 && - ost->enc_ctx->codec_id != AV_CODEC_ID_CODEC2 /* don't complain about 700 bit/s modes */) - av_log(ost, AV_LOG_WARNING, "The bitrate parameter is set too low." - " It takes bits/s as argument, not kbits/s\n"); + if (ost->enc_ctx->frame_size) { + av_assert0(ost->sq_idx_encode >= 0); + sq_frame_samples(output_files[ost->file_index]->sq_encode, + ost->sq_idx_encode, ost->enc_ctx->frame_size); + } - ret = avcodec_parameters_from_context(ost->st->codecpar, ost->enc_ctx); - if (ret < 0) { - av_log(ost, AV_LOG_FATAL, - "Error initializing the output stream codec context.\n"); - exit_program(1); - } + assert_avoptions(ost->encoder_opts); + if (ost->enc_ctx->bit_rate && ost->enc_ctx->bit_rate < 1000 && + ost->enc_ctx->codec_id != AV_CODEC_ID_CODEC2 /* don't complain about 700 bit/s modes */) + av_log(ost, AV_LOG_WARNING, "The bitrate parameter is set too low." + " It takes bits/s as argument, not kbits/s\n"); - if (ost->enc_ctx->nb_coded_side_data) { - int i; + ret = avcodec_parameters_from_context(ost->st->codecpar, ost->enc_ctx); + if (ret < 0) { + av_log(ost, AV_LOG_FATAL, + "Error initializing the output stream codec context.\n"); + exit_program(1); + } - for (i = 0; i < ost->enc_ctx->nb_coded_side_data; i++) { - const AVPacketSideData *sd_src = &ost->enc_ctx->coded_side_data[i]; - uint8_t *dst_data; + if (ost->enc_ctx->nb_coded_side_data) { + int i; - dst_data = av_stream_new_side_data(ost->st, sd_src->type, sd_src->size); - if (!dst_data) - return AVERROR(ENOMEM); - memcpy(dst_data, sd_src->data, sd_src->size); - } + for (i = 0; i < ost->enc_ctx->nb_coded_side_data; i++) { + const AVPacketSideData *sd_src = &ost->enc_ctx->coded_side_data[i]; + uint8_t *dst_data; + + dst_data = av_stream_new_side_data(ost->st, sd_src->type, sd_src->size); + if (!dst_data) + return AVERROR(ENOMEM); + memcpy(dst_data, sd_src->data, sd_src->size); } + } - /* - * Add global input side data. For now this is naive, and copies it - * from the input stream's global side data. All side data should - * really be funneled over AVFrame and libavfilter, then added back to - * packet side data, and then potentially using the first packet for - * global side data. - */ - if (ist) { - int i; - for (i = 0; i < ist->st->nb_side_data; i++) { - AVPacketSideData *sd = &ist->st->side_data[i]; - if (sd->type != AV_PKT_DATA_CPB_PROPERTIES) { - uint8_t *dst = av_stream_new_side_data(ost->st, sd->type, sd->size); - if (!dst) - return AVERROR(ENOMEM); - memcpy(dst, sd->data, sd->size); - if (ist->autorotate && sd->type == AV_PKT_DATA_DISPLAYMATRIX) - av_display_rotation_set((int32_t *)dst, 0); - } + /* + * Add global input side data. For now this is naive, and copies it + * from the input stream's global side data. All side data should + * really be funneled over AVFrame and libavfilter, then added back to + * packet side data, and then potentially using the first packet for + * global side data. + */ + if (ist) { + int i; + for (i = 0; i < ist->st->nb_side_data; i++) { + AVPacketSideData *sd = &ist->st->side_data[i]; + if (sd->type != AV_PKT_DATA_CPB_PROPERTIES) { + uint8_t *dst = av_stream_new_side_data(ost->st, sd->type, sd->size); + if (!dst) + return AVERROR(ENOMEM); + memcpy(dst, sd->data, sd->size); + if (ist->autorotate && sd->type == AV_PKT_DATA_DISPLAYMATRIX) + av_display_rotation_set((int32_t *)dst, 0); } } + } - // copy timebase while removing common factors - if (ost->st->time_base.num <= 0 || ost->st->time_base.den <= 0) - ost->st->time_base = av_add_q(ost->enc_ctx->time_base, (AVRational){0, 1}); + // copy timebase while removing common factors + if (ost->st->time_base.num <= 0 || ost->st->time_base.den <= 0) + ost->st->time_base = av_add_q(ost->enc_ctx->time_base, (AVRational){0, 1}); - // copy estimated duration as a hint to the muxer - if (ost->st->duration <= 0 && ist && ist->st->duration > 0) - ost->st->duration = av_rescale_q(ist->st->duration, ist->st->time_base, ost->st->time_base); + // copy estimated duration as a hint to the muxer + if (ost->st->duration <= 0 && ist && ist->st->duration > 0) + ost->st->duration = av_rescale_q(ist->st->duration, ist->st->time_base, ost->st->time_base); ost->mux_timebase = enc_ctx->time_base; From d96f2fbf76fd2587d8f9aa984591439cf38bfb0b Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Sat, 25 Mar 2023 04:36:28 +0100 Subject: [PATCH 0614/2172] fftools/ffmpeg: move initializing encoders to a new file This file will contain more encoding-related code in the future. --- fftools/Makefile | 1 + fftools/ffmpeg.c | 306 +------------------------------------- fftools/ffmpeg.h | 2 + fftools/ffmpeg_enc.c | 342 +++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 346 insertions(+), 305 deletions(-) create mode 100644 fftools/ffmpeg_enc.c diff --git a/fftools/Makefile b/fftools/Makefile index 8ac38e75d2f..9939c7095cc 100644 --- a/fftools/Makefile +++ b/fftools/Makefile @@ -11,6 +11,7 @@ ALLAVPROGS_G = $(AVBASENAMES:%=%$(PROGSSUF)_g$(EXESUF)) OBJS-ffmpeg += \ fftools/ffmpeg_demux.o \ + fftools/ffmpeg_enc.o \ fftools/ffmpeg_filter.o \ fftools/ffmpeg_hw.o \ fftools/ffmpeg_mux.o \ diff --git a/fftools/ffmpeg.c b/fftools/ffmpeg.c index 42b2735fb4d..c439f94de1b 100644 --- a/fftools/ffmpeg.c +++ b/fftools/ffmpeg.c @@ -2967,316 +2967,12 @@ static int init_output_stream_streamcopy(OutputStream *ost) return 0; } -static void set_encoder_id(OutputFile *of, OutputStream *ost) -{ - const char *cname = ost->enc_ctx->codec->name; - uint8_t *encoder_string; - int encoder_string_len; - - if (av_dict_get(ost->st->metadata, "encoder", NULL, 0)) - return; - - encoder_string_len = sizeof(LIBAVCODEC_IDENT) + strlen(cname) + 2; - encoder_string = av_mallocz(encoder_string_len); - if (!encoder_string) - report_and_exit(AVERROR(ENOMEM)); - - if (!of->bitexact && !ost->bitexact) - av_strlcpy(encoder_string, LIBAVCODEC_IDENT " ", encoder_string_len); - else - av_strlcpy(encoder_string, "Lavc ", encoder_string_len); - av_strlcat(encoder_string, cname, encoder_string_len); - av_dict_set(&ost->st->metadata, "encoder", encoder_string, - AV_DICT_DONT_STRDUP_VAL | AV_DICT_DONT_OVERWRITE); -} - -static void init_encoder_time_base(OutputStream *ost, AVRational default_time_base) -{ - InputStream *ist = ost->ist; - AVCodecContext *enc_ctx = ost->enc_ctx; - - if (ost->enc_timebase.num > 0) { - enc_ctx->time_base = ost->enc_timebase; - return; - } - - if (ost->enc_timebase.num < 0) { - if (ist) { - enc_ctx->time_base = ist->st->time_base; - return; - } - - av_log(ost, AV_LOG_WARNING, - "Input stream data not available, using default time base\n"); - } - - enc_ctx->time_base = default_time_base; -} - -static int init_output_stream_encode(OutputStream *ost, AVFrame *frame) -{ - InputStream *ist = ost->ist; - AVCodecContext *enc_ctx = ost->enc_ctx; - AVCodecContext *dec_ctx = NULL; - const AVCodec *enc = enc_ctx->codec; - OutputFile *of = output_files[ost->file_index]; - int ret; - - set_encoder_id(output_files[ost->file_index], ost); - - if (ist) { - dec_ctx = ist->dec_ctx; - } - - 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 (!ost->frame_rate.num && !ost->max_frame_rate.num) { - ost->frame_rate = (AVRational){25, 1}; - av_log(ost, AV_LOG_WARNING, - "No information " - "about the input framerate is available. Falling " - "back to a default value of 25fps. Use the -r option " - "if you want a different framerate.\n"); - } - - if (ost->max_frame_rate.num && - (av_q2d(ost->frame_rate) > av_q2d(ost->max_frame_rate) || - !ost->frame_rate.den)) - ost->frame_rate = ost->max_frame_rate; - - if (enc->supported_framerates && !ost->force_fps) { - int idx = av_find_nearest_q_idx(ost->frame_rate, enc->supported_framerates); - ost->frame_rate = enc->supported_framerates[idx]; - } - // reduce frame rate for mpeg4 to be within the spec limits - if (enc_ctx->codec_id == AV_CODEC_ID_MPEG4) { - av_reduce(&ost->frame_rate.num, &ost->frame_rate.den, - ost->frame_rate.num, ost->frame_rate.den, 65535); - } - } - - switch (enc_ctx->codec_type) { - case AVMEDIA_TYPE_AUDIO: - enc_ctx->sample_fmt = av_buffersink_get_format(ost->filter->filter); - enc_ctx->sample_rate = av_buffersink_get_sample_rate(ost->filter->filter); - ret = av_buffersink_get_ch_layout(ost->filter->filter, &enc_ctx->ch_layout); - if (ret < 0) - return ret; - - 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_get_bytes_per_sample(enc_ctx->sample_fmt) << 3); - - init_encoder_time_base(ost, av_make_q(1, enc_ctx->sample_rate)); - break; - - case AVMEDIA_TYPE_VIDEO: - init_encoder_time_base(ost, av_inv_q(ost->frame_rate)); - - if (!(enc_ctx->time_base.num && enc_ctx->time_base.den)) - enc_ctx->time_base = av_buffersink_get_time_base(ost->filter->filter); - if ( av_q2d(enc_ctx->time_base) < 0.001 && ost->vsync_method != VSYNC_PASSTHROUGH - && (ost->vsync_method == VSYNC_CFR || ost->vsync_method == VSYNC_VSCFR || - (ost->vsync_method == VSYNC_AUTO && !(of->format->flags & AVFMT_VARIABLE_FPS)))){ - av_log(ost, AV_LOG_WARNING, "Frame rate very high for a muxer not efficiently supporting it.\n" - "Please consider specifying a lower framerate, a different muxer or " - "setting vsync/fps_mode to vfr\n"); - } - - enc_ctx->width = av_buffersink_get_w(ost->filter->filter); - enc_ctx->height = av_buffersink_get_h(ost->filter->filter); - enc_ctx->sample_aspect_ratio = ost->st->sample_aspect_ratio = - ost->frame_aspect_ratio.num ? // overridden by the -aspect cli option - av_mul_q(ost->frame_aspect_ratio, (AVRational){ enc_ctx->height, enc_ctx->width }) : - av_buffersink_get_sample_aspect_ratio(ost->filter->filter); - - enc_ctx->pix_fmt = av_buffersink_get_format(ost->filter->filter); - - 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); - - if (frame) { - enc_ctx->color_range = frame->color_range; - enc_ctx->color_primaries = frame->color_primaries; - enc_ctx->color_trc = frame->color_trc; - enc_ctx->colorspace = frame->colorspace; - enc_ctx->chroma_sample_location = frame->chroma_location; - } - - enc_ctx->framerate = ost->frame_rate; - - ost->st->avg_frame_rate = ost->frame_rate; - - // Field order: autodetection - if (frame) { - if (enc_ctx->flags & (AV_CODEC_FLAG_INTERLACED_DCT | AV_CODEC_FLAG_INTERLACED_ME) && - ost->top_field_first >= 0) - frame->top_field_first = !!ost->top_field_first; - - if (frame->interlaced_frame) { - if (enc->id == AV_CODEC_ID_MJPEG) - enc_ctx->field_order = frame->top_field_first ? AV_FIELD_TT:AV_FIELD_BB; - else - enc_ctx->field_order = frame->top_field_first ? AV_FIELD_TB:AV_FIELD_BT; - } else - enc_ctx->field_order = AV_FIELD_PROGRESSIVE; - } - - // Field order: override - if (ost->top_field_first == 0) { - enc_ctx->field_order = AV_FIELD_BB; - } else if (ost->top_field_first == 1) { - enc_ctx->field_order = AV_FIELD_TT; - } - - break; - case AVMEDIA_TYPE_SUBTITLE: - enc_ctx->time_base = AV_TIME_BASE_Q; - if (!enc_ctx->width) { - enc_ctx->width = ost->ist->par->width; - enc_ctx->height = ost->ist->par->height; - } - if (dec_ctx && dec_ctx->subtitle_header) { - /* ASS code assumes this buffer is null terminated so add extra byte. */ - enc_ctx->subtitle_header = av_mallocz(dec_ctx->subtitle_header_size + 1); - if (!enc_ctx->subtitle_header) - return AVERROR(ENOMEM); - memcpy(enc_ctx->subtitle_header, dec_ctx->subtitle_header, - dec_ctx->subtitle_header_size); - enc_ctx->subtitle_header_size = dec_ctx->subtitle_header_size; - } - if (ist && ist->dec->type == AVMEDIA_TYPE_SUBTITLE && - enc_ctx->codec_type == AVMEDIA_TYPE_SUBTITLE) { - int input_props = 0, output_props = 0; - AVCodecDescriptor const *input_descriptor = - avcodec_descriptor_get(ist->dec->id); - AVCodecDescriptor const *output_descriptor = - avcodec_descriptor_get(enc_ctx->codec_id); - if (input_descriptor) - input_props = input_descriptor->props & (AV_CODEC_PROP_TEXT_SUB | AV_CODEC_PROP_BITMAP_SUB); - if (output_descriptor) - output_props = output_descriptor->props & (AV_CODEC_PROP_TEXT_SUB | AV_CODEC_PROP_BITMAP_SUB); - if (input_props && output_props && input_props != output_props) { - av_log(ost, AV_LOG_ERROR, - "Subtitle encoding currently only possible from text to text " - "or bitmap to bitmap"); - return AVERROR_INVALIDDATA; - } - } - - break; - default: - abort(); - break; - } - - if (ost->bitexact) - enc_ctx->flags |= AV_CODEC_FLAG_BITEXACT; - - if (!av_dict_get(ost->encoder_opts, "threads", NULL, 0)) - av_dict_set(&ost->encoder_opts, "threads", "auto", 0); - - if (enc->capabilities & AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE) { - ret = av_dict_set(&ost->encoder_opts, "flags", "+copy_opaque", AV_DICT_MULTIKEY); - if (ret < 0) - return ret; - } - - ret = hw_device_setup_for_encode(ost); - if (ret < 0) { - av_log(ost, AV_LOG_ERROR, - "Encoding hardware device setup failed: %s\n", av_err2str(ret)); - return ret; - } - - if ((ret = avcodec_open2(ost->enc_ctx, enc, &ost->encoder_opts)) < 0) { - if (ret == AVERROR_EXPERIMENTAL) - abort_codec_experimental(enc, 1); - av_log(ost, AV_LOG_ERROR, "Error while opening encoder - maybe " - "incorrect parameters such as bit_rate, rate, width or height.\n"); - return ret; - } - - if (ost->enc_ctx->frame_size) { - av_assert0(ost->sq_idx_encode >= 0); - sq_frame_samples(output_files[ost->file_index]->sq_encode, - ost->sq_idx_encode, ost->enc_ctx->frame_size); - } - - assert_avoptions(ost->encoder_opts); - if (ost->enc_ctx->bit_rate && ost->enc_ctx->bit_rate < 1000 && - ost->enc_ctx->codec_id != AV_CODEC_ID_CODEC2 /* don't complain about 700 bit/s modes */) - av_log(ost, AV_LOG_WARNING, "The bitrate parameter is set too low." - " It takes bits/s as argument, not kbits/s\n"); - - ret = avcodec_parameters_from_context(ost->st->codecpar, ost->enc_ctx); - if (ret < 0) { - av_log(ost, AV_LOG_FATAL, - "Error initializing the output stream codec context.\n"); - exit_program(1); - } - - if (ost->enc_ctx->nb_coded_side_data) { - int i; - - for (i = 0; i < ost->enc_ctx->nb_coded_side_data; i++) { - const AVPacketSideData *sd_src = &ost->enc_ctx->coded_side_data[i]; - uint8_t *dst_data; - - dst_data = av_stream_new_side_data(ost->st, sd_src->type, sd_src->size); - if (!dst_data) - return AVERROR(ENOMEM); - memcpy(dst_data, sd_src->data, sd_src->size); - } - } - - /* - * Add global input side data. For now this is naive, and copies it - * from the input stream's global side data. All side data should - * really be funneled over AVFrame and libavfilter, then added back to - * packet side data, and then potentially using the first packet for - * global side data. - */ - if (ist) { - int i; - for (i = 0; i < ist->st->nb_side_data; i++) { - AVPacketSideData *sd = &ist->st->side_data[i]; - if (sd->type != AV_PKT_DATA_CPB_PROPERTIES) { - uint8_t *dst = av_stream_new_side_data(ost->st, sd->type, sd->size); - if (!dst) - return AVERROR(ENOMEM); - memcpy(dst, sd->data, sd->size); - if (ist->autorotate && sd->type == AV_PKT_DATA_DISPLAYMATRIX) - av_display_rotation_set((int32_t *)dst, 0); - } - } - } - - // copy timebase while removing common factors - if (ost->st->time_base.num <= 0 || ost->st->time_base.den <= 0) - ost->st->time_base = av_add_q(ost->enc_ctx->time_base, (AVRational){0, 1}); - - // copy estimated duration as a hint to the muxer - if (ost->st->duration <= 0 && ist && ist->st->duration > 0) - ost->st->duration = av_rescale_q(ist->st->duration, ist->st->time_base, ost->st->time_base); - - ost->mux_timebase = enc_ctx->time_base; - - return 0; -} - static int init_output_stream(OutputStream *ost, AVFrame *frame) { int ret = 0; if (ost->enc_ctx) { - ret = init_output_stream_encode(ost, frame); + ret = enc_open(ost, frame); if (ret < 0) return ret; } else if (ost->ist) { diff --git a/fftools/ffmpeg.h b/fftools/ffmpeg.h index 791deedc071..c1e2bbc3001 100644 --- a/fftools/ffmpeg.h +++ b/fftools/ffmpeg.h @@ -810,6 +810,8 @@ AVBufferRef *hw_device_for_filter(void); int hwaccel_decode_init(AVCodecContext *avctx); +int enc_open(OutputStream *ost, AVFrame *frame); + /* * Initialize muxing state for the given stream, should be called * after the codec/streamcopy setup has been done. diff --git a/fftools/ffmpeg_enc.c b/fftools/ffmpeg_enc.c new file mode 100644 index 00000000000..9db2ff5ef3b --- /dev/null +++ b/fftools/ffmpeg_enc.c @@ -0,0 +1,342 @@ +/* + * 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 "ffmpeg.h" + +#include "libavutil/avassert.h" +#include "libavutil/avstring.h" +#include "libavutil/avutil.h" +#include "libavutil/dict.h" +#include "libavutil/display.h" +#include "libavutil/eval.h" +#include "libavutil/frame.h" +#include "libavutil/log.h" +#include "libavutil/pixdesc.h" +#include "libavutil/rational.h" + +#include "libavfilter/buffersink.h" + +#include "libavcodec/avcodec.h" + +#include "libavformat/avformat.h" + +static void set_encoder_id(OutputFile *of, OutputStream *ost) +{ + const char *cname = ost->enc_ctx->codec->name; + uint8_t *encoder_string; + int encoder_string_len; + + if (av_dict_get(ost->st->metadata, "encoder", NULL, 0)) + return; + + encoder_string_len = sizeof(LIBAVCODEC_IDENT) + strlen(cname) + 2; + encoder_string = av_mallocz(encoder_string_len); + if (!encoder_string) + report_and_exit(AVERROR(ENOMEM)); + + if (!of->bitexact && !ost->bitexact) + av_strlcpy(encoder_string, LIBAVCODEC_IDENT " ", encoder_string_len); + else + av_strlcpy(encoder_string, "Lavc ", encoder_string_len); + av_strlcat(encoder_string, cname, encoder_string_len); + av_dict_set(&ost->st->metadata, "encoder", encoder_string, + AV_DICT_DONT_STRDUP_VAL | AV_DICT_DONT_OVERWRITE); +} + +static void init_encoder_time_base(OutputStream *ost, AVRational default_time_base) +{ + InputStream *ist = ost->ist; + AVCodecContext *enc_ctx = ost->enc_ctx; + + if (ost->enc_timebase.num > 0) { + enc_ctx->time_base = ost->enc_timebase; + return; + } + + if (ost->enc_timebase.num < 0) { + if (ist) { + enc_ctx->time_base = ist->st->time_base; + return; + } + + av_log(ost, AV_LOG_WARNING, + "Input stream data not available, using default time base\n"); + } + + enc_ctx->time_base = default_time_base; +} + +int enc_open(OutputStream *ost, AVFrame *frame) +{ + InputStream *ist = ost->ist; + AVCodecContext *enc_ctx = ost->enc_ctx; + AVCodecContext *dec_ctx = NULL; + const AVCodec *enc = enc_ctx->codec; + OutputFile *of = output_files[ost->file_index]; + int ret; + + set_encoder_id(output_files[ost->file_index], ost); + + if (ist) { + dec_ctx = ist->dec_ctx; + } + + 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 (!ost->frame_rate.num && !ost->max_frame_rate.num) { + ost->frame_rate = (AVRational){25, 1}; + av_log(ost, AV_LOG_WARNING, + "No information " + "about the input framerate is available. Falling " + "back to a default value of 25fps. Use the -r option " + "if you want a different framerate.\n"); + } + + if (ost->max_frame_rate.num && + (av_q2d(ost->frame_rate) > av_q2d(ost->max_frame_rate) || + !ost->frame_rate.den)) + ost->frame_rate = ost->max_frame_rate; + + if (enc->supported_framerates && !ost->force_fps) { + int idx = av_find_nearest_q_idx(ost->frame_rate, enc->supported_framerates); + ost->frame_rate = enc->supported_framerates[idx]; + } + // reduce frame rate for mpeg4 to be within the spec limits + if (enc_ctx->codec_id == AV_CODEC_ID_MPEG4) { + av_reduce(&ost->frame_rate.num, &ost->frame_rate.den, + ost->frame_rate.num, ost->frame_rate.den, 65535); + } + } + + switch (enc_ctx->codec_type) { + case AVMEDIA_TYPE_AUDIO: + enc_ctx->sample_fmt = av_buffersink_get_format(ost->filter->filter); + enc_ctx->sample_rate = av_buffersink_get_sample_rate(ost->filter->filter); + ret = av_buffersink_get_ch_layout(ost->filter->filter, &enc_ctx->ch_layout); + if (ret < 0) + return ret; + + 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_get_bytes_per_sample(enc_ctx->sample_fmt) << 3); + + init_encoder_time_base(ost, av_make_q(1, enc_ctx->sample_rate)); + break; + + case AVMEDIA_TYPE_VIDEO: + init_encoder_time_base(ost, av_inv_q(ost->frame_rate)); + + if (!(enc_ctx->time_base.num && enc_ctx->time_base.den)) + enc_ctx->time_base = av_buffersink_get_time_base(ost->filter->filter); + if ( av_q2d(enc_ctx->time_base) < 0.001 && ost->vsync_method != VSYNC_PASSTHROUGH + && (ost->vsync_method == VSYNC_CFR || ost->vsync_method == VSYNC_VSCFR || + (ost->vsync_method == VSYNC_AUTO && !(of->format->flags & AVFMT_VARIABLE_FPS)))){ + av_log(ost, AV_LOG_WARNING, "Frame rate very high for a muxer not efficiently supporting it.\n" + "Please consider specifying a lower framerate, a different muxer or " + "setting vsync/fps_mode to vfr\n"); + } + + enc_ctx->width = av_buffersink_get_w(ost->filter->filter); + enc_ctx->height = av_buffersink_get_h(ost->filter->filter); + enc_ctx->sample_aspect_ratio = ost->st->sample_aspect_ratio = + ost->frame_aspect_ratio.num ? // overridden by the -aspect cli option + av_mul_q(ost->frame_aspect_ratio, (AVRational){ enc_ctx->height, enc_ctx->width }) : + av_buffersink_get_sample_aspect_ratio(ost->filter->filter); + + enc_ctx->pix_fmt = av_buffersink_get_format(ost->filter->filter); + + 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); + + if (frame) { + enc_ctx->color_range = frame->color_range; + enc_ctx->color_primaries = frame->color_primaries; + enc_ctx->color_trc = frame->color_trc; + enc_ctx->colorspace = frame->colorspace; + enc_ctx->chroma_sample_location = frame->chroma_location; + } + + enc_ctx->framerate = ost->frame_rate; + + ost->st->avg_frame_rate = ost->frame_rate; + + // Field order: autodetection + if (frame) { + if (enc_ctx->flags & (AV_CODEC_FLAG_INTERLACED_DCT | AV_CODEC_FLAG_INTERLACED_ME) && + ost->top_field_first >= 0) + frame->top_field_first = !!ost->top_field_first; + + if (frame->interlaced_frame) { + if (enc->id == AV_CODEC_ID_MJPEG) + enc_ctx->field_order = frame->top_field_first ? AV_FIELD_TT:AV_FIELD_BB; + else + enc_ctx->field_order = frame->top_field_first ? AV_FIELD_TB:AV_FIELD_BT; + } else + enc_ctx->field_order = AV_FIELD_PROGRESSIVE; + } + + // Field order: override + if (ost->top_field_first == 0) { + enc_ctx->field_order = AV_FIELD_BB; + } else if (ost->top_field_first == 1) { + enc_ctx->field_order = AV_FIELD_TT; + } + + break; + case AVMEDIA_TYPE_SUBTITLE: + enc_ctx->time_base = AV_TIME_BASE_Q; + if (!enc_ctx->width) { + enc_ctx->width = ost->ist->par->width; + enc_ctx->height = ost->ist->par->height; + } + if (dec_ctx && dec_ctx->subtitle_header) { + /* ASS code assumes this buffer is null terminated so add extra byte. */ + enc_ctx->subtitle_header = av_mallocz(dec_ctx->subtitle_header_size + 1); + if (!enc_ctx->subtitle_header) + return AVERROR(ENOMEM); + memcpy(enc_ctx->subtitle_header, dec_ctx->subtitle_header, + dec_ctx->subtitle_header_size); + enc_ctx->subtitle_header_size = dec_ctx->subtitle_header_size; + } + if (ist && ist->dec->type == AVMEDIA_TYPE_SUBTITLE && + enc_ctx->codec_type == AVMEDIA_TYPE_SUBTITLE) { + int input_props = 0, output_props = 0; + AVCodecDescriptor const *input_descriptor = + avcodec_descriptor_get(ist->dec->id); + AVCodecDescriptor const *output_descriptor = + avcodec_descriptor_get(enc_ctx->codec_id); + if (input_descriptor) + input_props = input_descriptor->props & (AV_CODEC_PROP_TEXT_SUB | AV_CODEC_PROP_BITMAP_SUB); + if (output_descriptor) + output_props = output_descriptor->props & (AV_CODEC_PROP_TEXT_SUB | AV_CODEC_PROP_BITMAP_SUB); + if (input_props && output_props && input_props != output_props) { + av_log(ost, AV_LOG_ERROR, + "Subtitle encoding currently only possible from text to text " + "or bitmap to bitmap"); + return AVERROR_INVALIDDATA; + } + } + + break; + default: + abort(); + break; + } + + if (ost->bitexact) + enc_ctx->flags |= AV_CODEC_FLAG_BITEXACT; + + if (!av_dict_get(ost->encoder_opts, "threads", NULL, 0)) + av_dict_set(&ost->encoder_opts, "threads", "auto", 0); + + if (enc->capabilities & AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE) { + ret = av_dict_set(&ost->encoder_opts, "flags", "+copy_opaque", AV_DICT_MULTIKEY); + if (ret < 0) + return ret; + } + + ret = hw_device_setup_for_encode(ost); + if (ret < 0) { + av_log(ost, AV_LOG_ERROR, + "Encoding hardware device setup failed: %s\n", av_err2str(ret)); + return ret; + } + + if ((ret = avcodec_open2(ost->enc_ctx, enc, &ost->encoder_opts)) < 0) { + if (ret != AVERROR_EXPERIMENTAL) + av_log(ost, AV_LOG_ERROR, "Error while opening encoder - maybe " + "incorrect parameters such as bit_rate, rate, width or height.\n"); + return ret; + } + + if (ost->enc_ctx->frame_size) { + av_assert0(ost->sq_idx_encode >= 0); + sq_frame_samples(output_files[ost->file_index]->sq_encode, + ost->sq_idx_encode, ost->enc_ctx->frame_size); + } + + assert_avoptions(ost->encoder_opts); + if (ost->enc_ctx->bit_rate && ost->enc_ctx->bit_rate < 1000 && + ost->enc_ctx->codec_id != AV_CODEC_ID_CODEC2 /* don't complain about 700 bit/s modes */) + av_log(ost, AV_LOG_WARNING, "The bitrate parameter is set too low." + " It takes bits/s as argument, not kbits/s\n"); + + ret = avcodec_parameters_from_context(ost->st->codecpar, ost->enc_ctx); + if (ret < 0) { + av_log(ost, AV_LOG_FATAL, + "Error initializing the output stream codec context.\n"); + exit_program(1); + } + + if (ost->enc_ctx->nb_coded_side_data) { + int i; + + for (i = 0; i < ost->enc_ctx->nb_coded_side_data; i++) { + const AVPacketSideData *sd_src = &ost->enc_ctx->coded_side_data[i]; + uint8_t *dst_data; + + dst_data = av_stream_new_side_data(ost->st, sd_src->type, sd_src->size); + if (!dst_data) + return AVERROR(ENOMEM); + memcpy(dst_data, sd_src->data, sd_src->size); + } + } + + /* + * Add global input side data. For now this is naive, and copies it + * from the input stream's global side data. All side data should + * really be funneled over AVFrame and libavfilter, then added back to + * packet side data, and then potentially using the first packet for + * global side data. + */ + if (ist) { + int i; + for (i = 0; i < ist->st->nb_side_data; i++) { + AVPacketSideData *sd = &ist->st->side_data[i]; + if (sd->type != AV_PKT_DATA_CPB_PROPERTIES) { + uint8_t *dst = av_stream_new_side_data(ost->st, sd->type, sd->size); + if (!dst) + return AVERROR(ENOMEM); + memcpy(dst, sd->data, sd->size); + if (ist->autorotate && sd->type == AV_PKT_DATA_DISPLAYMATRIX) + av_display_rotation_set((int32_t *)dst, 0); + } + } + } + + // copy timebase while removing common factors + if (ost->st->time_base.num <= 0 || ost->st->time_base.den <= 0) + ost->st->time_base = av_add_q(ost->enc_ctx->time_base, (AVRational){0, 1}); + + // copy estimated duration as a hint to the muxer + if (ost->st->duration <= 0 && ist && ist->st->duration > 0) + ost->st->duration = av_rescale_q(ist->st->duration, ist->st->time_base, ost->st->time_base); + + ost->mux_timebase = enc_ctx->time_base; + + return 0; +} From a996478e8c492215e021a22d7b197c255d05f725 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Sat, 25 Mar 2023 05:00:11 +0100 Subject: [PATCH 0615/2172] fftools/ffmpeg: simplify output stream initialization call graph Several places in the code currently call init_output_stream_wrapper(), which in turn calls init_output_stream(), which then calls either enc_open() or init_output_stream_streamcopy(), followed by of_stream_init(), which tells the muxer the stream is ready for muxing. All except one of these callers are in the encoding code, which will be moved to ffmpeg_enc.c. Keeping this structure would then necessitate ffmpeg_enc.c calling back into the common code in ffmpeg.c, which would then just call ffmpeg_mux, thus making the already convoluted call chain even more so. Simplify the situation by using separate paths for filter-fed output streams (audio and video encoders) and others (subtitles, streamcopy, data, attachments). --- fftools/ffmpeg.c | 51 +++++++++++++++++--------------------------- fftools/ffmpeg_enc.c | 7 ++++++ 2 files changed, 27 insertions(+), 31 deletions(-) diff --git a/fftools/ffmpeg.c b/fftools/ffmpeg.c index c439f94de1b..5b42a914f86 100644 --- a/fftools/ffmpeg.c +++ b/fftools/ffmpeg.c @@ -724,25 +724,6 @@ static double adjust_frame_pts_to_encoder_tb(OutputFile *of, OutputStream *ost, return float_pts; } -static int init_output_stream(OutputStream *ost, AVFrame *frame); - -static int init_output_stream_wrapper(OutputStream *ost, AVFrame *frame, - unsigned int fatal) -{ - int ret = AVERROR_BUG; - - if (ost->initialized) - return 0; - - ret = init_output_stream(ost, frame); - if (ret < 0) { - if (fatal) - exit_program(1); - } - - return ret; -} - static double psnr(double d) { return -10.0 * log10(d); @@ -1023,7 +1004,9 @@ static void do_audio_out(OutputFile *of, OutputStream *ost, AVCodecContext *enc = ost->enc_ctx; int ret; - init_output_stream_wrapper(ost, frame, 1); + ret = enc_open(ost, frame); + if (ret < 0) + exit_program(1); if (frame->pts == AV_NOPTS_VALUE) frame->pts = ost->next_pts; @@ -1264,7 +1247,9 @@ static void do_video_out(OutputFile *of, InputStream *ist = ost->ist; AVFilterContext *filter = ost->filter->filter; - init_output_stream_wrapper(ost, next_picture, 1); + ret = enc_open(ost, next_picture); + if (ret < 0) + exit_program(1); frame_rate = av_buffersink_get_frame_rate(filter); if (frame_rate.num > 0 && frame_rate.den > 0) @@ -1820,7 +1805,9 @@ static void flush_encoders(void) of_output_packet(of, ost->pkt, ost, 1); } - init_output_stream_wrapper(ost, NULL, 1); + ret = enc_open(ost, NULL); + if (ret < 0) + exit_program(1); } if (enc->codec_type != AVMEDIA_TYPE_VIDEO && enc->codec_type != AVMEDIA_TYPE_AUDIO) @@ -2967,24 +2954,26 @@ static int init_output_stream_streamcopy(OutputStream *ost) return 0; } -static int init_output_stream(OutputStream *ost, AVFrame *frame) +static int init_output_stream_nofilter(OutputStream *ost) { int ret = 0; if (ost->enc_ctx) { - ret = enc_open(ost, frame); + ret = enc_open(ost, NULL); if (ret < 0) return ret; - } else if (ost->ist) { - ret = init_output_stream_streamcopy(ost); + } else { + if (ost->ist) { + ret = init_output_stream_streamcopy(ost); + if (ret < 0) + return ret; + } + + ret = of_stream_init(output_files[ost->file_index], ost); if (ret < 0) return ret; } - ret = of_stream_init(output_files[ost->file_index], ost); - if (ret < 0) - return ret; - return ret; } @@ -3017,7 +3006,7 @@ static int transcode_init(void) ost->st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO)) continue; - ret = init_output_stream_wrapper(ost, NULL, 0); + ret = init_output_stream_nofilter(ost); if (ret < 0) goto dump_format; } diff --git a/fftools/ffmpeg_enc.c b/fftools/ffmpeg_enc.c index 9db2ff5ef3b..a4660051a29 100644 --- a/fftools/ffmpeg_enc.c +++ b/fftools/ffmpeg_enc.c @@ -93,6 +93,9 @@ int enc_open(OutputStream *ost, AVFrame *frame) OutputFile *of = output_files[ost->file_index]; int ret; + if (ost->initialized) + return 0; + set_encoder_id(output_files[ost->file_index], ost); if (ist) { @@ -338,5 +341,9 @@ int enc_open(OutputStream *ost, AVFrame *frame) ost->mux_timebase = enc_ctx->time_base; + ret = of_stream_init(of, ost); + if (ret < 0) + return ret; + return 0; } From b79448fa38fbc54086b72fa83136168bda2cadf8 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Sat, 25 Mar 2023 11:52:28 +0100 Subject: [PATCH 0616/2172] fftools/ffmpeg: replace ff_dlog() with av_log() ff_dlog() is a lavu internal macro, and av_log() at trace level is just as good here. --- fftools/ffmpeg.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/fftools/ffmpeg.c b/fftools/ffmpeg.c index 5b42a914f86..37578081a33 100644 --- a/fftools/ffmpeg.c +++ b/fftools/ffmpeg.c @@ -49,7 +49,6 @@ #include "libavutil/samplefmt.h" #include "libavutil/fifo.h" #include "libavutil/hwcontext.h" -#include "libavutil/internal.h" #include "libavutil/intreadwrite.h" #include "libavutil/dict.h" #include "libavutil/display.h" @@ -1202,13 +1201,14 @@ static enum AVPictureType forced_kf_apply(void *logctx, KeyframeForceCtx *kf, kf->expr_const_values[FKF_T] = pts_time; res = av_expr_eval(kf->pexpr, kf->expr_const_values, NULL); - ff_dlog(NULL, "force_key_frame: n:%f n_forced:%f prev_forced_n:%f t:%f prev_forced_t:%f -> res:%f\n", - kf->expr_const_values[FKF_N], - kf->expr_const_values[FKF_N_FORCED], - kf->expr_const_values[FKF_PREV_FORCED_N], - kf->expr_const_values[FKF_T], - kf->expr_const_values[FKF_PREV_FORCED_T], - res); + av_log(logctx, AV_LOG_TRACE, + "force_key_frame: n:%f n_forced:%f prev_forced_n:%f t:%f prev_forced_t:%f -> res:%f\n", + kf->expr_const_values[FKF_N], + kf->expr_const_values[FKF_N_FORCED], + kf->expr_const_values[FKF_PREV_FORCED_N], + kf->expr_const_values[FKF_T], + kf->expr_const_values[FKF_PREV_FORCED_T], + res); kf->expr_const_values[FKF_N] += 1; From 9de5dc74fd1b0eafafadfeb6e9fefae579f872c8 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Sat, 25 Mar 2023 05:37:42 +0100 Subject: [PATCH 0617/2172] fftools/ffmpeg: move subtitle encoding to ffmpeg_enc.c --- fftools/ffmpeg.c | 86 ++------------------------------------------ fftools/ffmpeg.h | 3 ++ fftools/ffmpeg_enc.c | 80 +++++++++++++++++++++++++++++++++++++++++ 3 files changed, 85 insertions(+), 84 deletions(-) diff --git a/fftools/ffmpeg.c b/fftools/ffmpeg.c index 37578081a33..6bb421b86d3 100644 --- a/fftools/ffmpeg.c +++ b/fftools/ffmpeg.c @@ -669,7 +669,7 @@ static void close_output_stream(OutputStream *ost) sq_send(of->sq_encode, ost->sq_idx_encode, SQFRAME(NULL)); } -static int check_recording_time(OutputStream *ost, int64_t ts, AVRational tb) +int check_recording_time(OutputStream *ost, int64_t ts, AVRational tb) { OutputFile *of = output_files[ost->file_index]; @@ -1027,88 +1027,6 @@ static void do_audio_out(OutputFile *of, OutputStream *ost, exit_program(1); } -static void do_subtitle_out(OutputFile *of, - OutputStream *ost, - AVSubtitle *sub) -{ - int subtitle_out_max_size = 1024 * 1024; - int subtitle_out_size, nb, i, ret; - AVCodecContext *enc; - AVPacket *pkt = ost->pkt; - int64_t pts; - - if (sub->pts == AV_NOPTS_VALUE) { - av_log(ost, AV_LOG_ERROR, "Subtitle packets must have a pts\n"); - if (exit_on_error) - exit_program(1); - return; - } - - enc = ost->enc_ctx; - - /* Note: DVB subtitle need one packet to draw them and one other - packet to clear them */ - /* XXX: signal it in the codec context ? */ - if (enc->codec_id == AV_CODEC_ID_DVB_SUBTITLE) - nb = 2; - else if (enc->codec_id == AV_CODEC_ID_ASS) - nb = FFMAX(sub->num_rects, 1); - else - nb = 1; - - /* shift timestamp to honor -ss and make check_recording_time() work with -t */ - pts = sub->pts; - if (output_files[ost->file_index]->start_time != AV_NOPTS_VALUE) - pts -= output_files[ost->file_index]->start_time; - for (i = 0; i < nb; i++) { - AVSubtitle local_sub = *sub; - - if (!check_recording_time(ost, pts, AV_TIME_BASE_Q)) - return; - - ret = av_new_packet(pkt, subtitle_out_max_size); - if (ret < 0) - report_and_exit(AVERROR(ENOMEM)); - - local_sub.pts = pts; - // start_display_time is required to be 0 - local_sub.pts += av_rescale_q(sub->start_display_time, (AVRational){ 1, 1000 }, AV_TIME_BASE_Q); - local_sub.end_display_time -= sub->start_display_time; - local_sub.start_display_time = 0; - - if (enc->codec_id == AV_CODEC_ID_DVB_SUBTITLE && i == 1) - local_sub.num_rects = 0; - else if (enc->codec_id == AV_CODEC_ID_ASS && sub->num_rects > 0) { - local_sub.num_rects = 1; - local_sub.rects += i; - } - - ost->frames_encoded++; - - subtitle_out_size = avcodec_encode_subtitle(enc, pkt->data, pkt->size, &local_sub); - if (subtitle_out_size < 0) { - av_log(ost, AV_LOG_FATAL, "Subtitle encoding failed\n"); - exit_program(1); - } - - av_shrink_packet(pkt, subtitle_out_size); - pkt->time_base = ost->mux_timebase; - pkt->pts = av_rescale_q(sub->pts, AV_TIME_BASE_Q, pkt->time_base); - pkt->duration = av_rescale_q(sub->end_display_time, (AVRational){ 1, 1000 }, pkt->time_base); - if (enc->codec_id == AV_CODEC_ID_DVB_SUBTITLE) { - /* XXX: the pts correction is handled here. Maybe handling - it in the codec would be better */ - if (i == 0) - pkt->pts += av_rescale_q(sub->start_display_time, (AVRational){ 1, 1000 }, pkt->time_base); - else - pkt->pts += av_rescale_q(sub->end_display_time, (AVRational){ 1, 1000 }, pkt->time_base); - } - pkt->dts = pkt->pts; - - of_output_packet(of, pkt, ost, 0); - } -} - /* Convert frame timestamps to the encoder timebase and decide how many times * should this (and possibly previous) frame be repeated in order to conform to * desired target framerate (if any). @@ -2351,7 +2269,7 @@ static int process_subtitle(InputStream *ist, AVSubtitle *subtitle, int *got_out || ost->enc_ctx->codec_type != AVMEDIA_TYPE_SUBTITLE) continue; - do_subtitle_out(output_files[ost->file_index], ost, subtitle); + enc_subtitle(output_files[ost->file_index], ost, subtitle); } out: diff --git a/fftools/ffmpeg.h b/fftools/ffmpeg.h index c1e2bbc3001..ffb0ca33ac9 100644 --- a/fftools/ffmpeg.h +++ b/fftools/ffmpeg.h @@ -811,6 +811,9 @@ AVBufferRef *hw_device_for_filter(void); int hwaccel_decode_init(AVCodecContext *avctx); int enc_open(OutputStream *ost, AVFrame *frame); +void enc_subtitle(OutputFile *of, OutputStream *ost, AVSubtitle *sub); + +int check_recording_time(OutputStream *ost, int64_t ts, AVRational tb); /* * Initialize muxing state for the given stream, should be called diff --git a/fftools/ffmpeg_enc.c b/fftools/ffmpeg_enc.c index a4660051a29..bcc560b9b77 100644 --- a/fftools/ffmpeg_enc.c +++ b/fftools/ffmpeg_enc.c @@ -347,3 +347,83 @@ int enc_open(OutputStream *ost, AVFrame *frame) return 0; } + +void enc_subtitle(OutputFile *of, OutputStream *ost, AVSubtitle *sub) +{ + int subtitle_out_max_size = 1024 * 1024; + int subtitle_out_size, nb, i, ret; + AVCodecContext *enc; + AVPacket *pkt = ost->pkt; + int64_t pts; + + if (sub->pts == AV_NOPTS_VALUE) { + av_log(ost, AV_LOG_ERROR, "Subtitle packets must have a pts\n"); + if (exit_on_error) + exit_program(1); + return; + } + + enc = ost->enc_ctx; + + /* Note: DVB subtitle need one packet to draw them and one other + packet to clear them */ + /* XXX: signal it in the codec context ? */ + if (enc->codec_id == AV_CODEC_ID_DVB_SUBTITLE) + nb = 2; + else if (enc->codec_id == AV_CODEC_ID_ASS) + nb = FFMAX(sub->num_rects, 1); + else + nb = 1; + + /* shift timestamp to honor -ss and make check_recording_time() work with -t */ + pts = sub->pts; + if (output_files[ost->file_index]->start_time != AV_NOPTS_VALUE) + pts -= output_files[ost->file_index]->start_time; + for (i = 0; i < nb; i++) { + AVSubtitle local_sub = *sub; + + if (!check_recording_time(ost, pts, AV_TIME_BASE_Q)) + return; + + ret = av_new_packet(pkt, subtitle_out_max_size); + if (ret < 0) + report_and_exit(AVERROR(ENOMEM)); + + local_sub.pts = pts; + // start_display_time is required to be 0 + local_sub.pts += av_rescale_q(sub->start_display_time, (AVRational){ 1, 1000 }, AV_TIME_BASE_Q); + local_sub.end_display_time -= sub->start_display_time; + local_sub.start_display_time = 0; + + if (enc->codec_id == AV_CODEC_ID_DVB_SUBTITLE && i == 1) + local_sub.num_rects = 0; + else if (enc->codec_id == AV_CODEC_ID_ASS && sub->num_rects > 0) { + local_sub.num_rects = 1; + local_sub.rects += i; + } + + ost->frames_encoded++; + + subtitle_out_size = avcodec_encode_subtitle(enc, pkt->data, pkt->size, &local_sub); + if (subtitle_out_size < 0) { + av_log(ost, AV_LOG_FATAL, "Subtitle encoding failed\n"); + exit_program(1); + } + + av_shrink_packet(pkt, subtitle_out_size); + pkt->time_base = ost->mux_timebase; + pkt->pts = av_rescale_q(sub->pts, AV_TIME_BASE_Q, pkt->time_base); + pkt->duration = av_rescale_q(sub->end_display_time, (AVRational){ 1, 1000 }, pkt->time_base); + if (enc->codec_id == AV_CODEC_ID_DVB_SUBTITLE) { + /* XXX: the pts correction is handled here. Maybe handling + it in the codec would be better */ + if (i == 0) + pkt->pts += av_rescale_q(sub->start_display_time, (AVRational){ 1, 1000 }, pkt->time_base); + else + pkt->pts += av_rescale_q(sub->end_display_time, (AVRational){ 1, 1000 }, pkt->time_base); + } + pkt->dts = pkt->pts; + + of_output_packet(of, pkt, ost, 0); + } +} From 44accfef41d6c9711f2ad62b91bcaf0f0f935030 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Sat, 25 Mar 2023 11:49:54 +0100 Subject: [PATCH 0618/2172] fftools/ffmpeg: move audio/video encoding code to ffmpeg_enc.c --- fftools/ffmpeg.c | 690 +------------------------------------------ fftools/ffmpeg.h | 31 +- fftools/ffmpeg_enc.c | 660 +++++++++++++++++++++++++++++++++++++++++ 3 files changed, 702 insertions(+), 679 deletions(-) diff --git a/fftools/ffmpeg.c b/fftools/ffmpeg.c index 6bb421b86d3..07fc9789436 100644 --- a/fftools/ffmpeg.c +++ b/fftools/ffmpeg.c @@ -62,7 +62,6 @@ #include "libavutil/time.h" #include "libavutil/thread.h" #include "libavutil/threadmessage.h" -#include "libavcodec/mathops.h" #include "libavcodec/version.h" #include "libavformat/os_support.h" @@ -110,14 +109,7 @@ const char program_name[] = "ffmpeg"; const int program_birth_year = 2000; -static FILE *vstats_file; - -// optionally attached as opaque_ref to decoded AVFrames -typedef struct FrameData { - uint64_t idx; - int64_t pts; - AVRational tb; -} FrameData; +FILE *vstats_file; typedef struct BenchmarkTimeStamps { int64_t real_usec; @@ -125,14 +117,11 @@ typedef struct BenchmarkTimeStamps { int64_t sys_usec; } BenchmarkTimeStamps; -static int trigger_fix_sub_duration_heartbeat(OutputStream *ost, const AVPacket *pkt); static BenchmarkTimeStamps get_benchmark_time_stamps(void); static int64_t getmaxrss(void); -static int ifilter_has_all_input_formats(FilterGraph *fg); -static int64_t nb_frames_dup = 0; -static uint64_t dup_warning = 1000; -static int64_t nb_frames_drop = 0; +int64_t nb_frames_dup = 0; +int64_t nb_frames_drop = 0; static int64_t decode_error_stat[2]; unsigned nb_output_dumped = 0; @@ -582,9 +571,7 @@ static void ffmpeg_cleanup(int ret) ffmpeg_exited = 1; } -/* iterate over all output streams in all output files; - * pass NULL to start iteration */ -static OutputStream *ost_iter(OutputStream *prev) +OutputStream *ost_iter(OutputStream *prev) { int of_idx = prev ? prev->file_index : 0; int ost_idx = prev ? prev->index + 1 : 0; @@ -639,7 +626,7 @@ static void abort_codec_experimental(const AVCodec *c, int encoder) exit_program(1); } -static void update_benchmark(const char *fmt, ...) +void update_benchmark(const char *fmt, ...) { if (do_benchmark_all) { BenchmarkTimeStamps t = get_benchmark_time_stamps(); @@ -660,7 +647,7 @@ static void update_benchmark(const char *fmt, ...) } } -static void close_output_stream(OutputStream *ost) +void close_output_stream(OutputStream *ost) { OutputFile *of = output_files[ost->file_index]; ost->finished |= ENCODER_FINISHED; @@ -669,594 +656,6 @@ static void close_output_stream(OutputStream *ost) sq_send(of->sq_encode, ost->sq_idx_encode, SQFRAME(NULL)); } -int check_recording_time(OutputStream *ost, int64_t ts, AVRational tb) -{ - OutputFile *of = output_files[ost->file_index]; - - if (of->recording_time != INT64_MAX && - av_compare_ts(ts, tb, of->recording_time, AV_TIME_BASE_Q) >= 0) { - close_output_stream(ost); - return 0; - } - return 1; -} - -static double adjust_frame_pts_to_encoder_tb(OutputFile *of, OutputStream *ost, - AVFrame *frame) -{ - double float_pts = AV_NOPTS_VALUE; // this is identical to frame.pts but with higher precision - const int64_t start_time = (of->start_time == AV_NOPTS_VALUE) ? - 0 : of->start_time; - - AVCodecContext *const enc = ost->enc_ctx; - - AVRational tb = enc->time_base; - AVRational filter_tb = frame->time_base; - const int extra_bits = av_clip(29 - av_log2(tb.den), 0, 16); - - if (frame->pts == AV_NOPTS_VALUE) - goto early_exit; - - tb.den <<= extra_bits; - float_pts = av_rescale_q(frame->pts, filter_tb, tb) - - av_rescale_q(start_time, AV_TIME_BASE_Q, tb); - float_pts /= 1 << extra_bits; - // avoid exact midoints to reduce the chance of rounding differences, this - // can be removed in case the fps code is changed to work with integers - float_pts += FFSIGN(float_pts) * 1.0 / (1<<17); - - frame->pts = av_rescale_q(frame->pts, filter_tb, enc->time_base) - - av_rescale_q(start_time, AV_TIME_BASE_Q, enc->time_base); - frame->time_base = enc->time_base; - -early_exit: - - if (debug_ts) { - av_log(NULL, AV_LOG_INFO, "filter -> pts:%s pts_time:%s exact:%f time_base:%d/%d\n", - frame ? av_ts2str(frame->pts) : "NULL", - (enc && frame) ? av_ts2timestr(frame->pts, &enc->time_base) : "NULL", - float_pts, - enc ? enc->time_base.num : -1, - enc ? enc->time_base.den : -1); - } - - return float_pts; -} - -static double psnr(double d) -{ - return -10.0 * log10(d); -} - -static void update_video_stats(OutputStream *ost, const AVPacket *pkt, int write_vstats) -{ - const uint8_t *sd = av_packet_get_side_data(pkt, AV_PKT_DATA_QUALITY_STATS, - NULL); - AVCodecContext *enc = ost->enc_ctx; - int64_t frame_number; - double ti1, bitrate, avg_bitrate; - - ost->quality = sd ? AV_RL32(sd) : -1; - ost->pict_type = sd ? sd[4] : AV_PICTURE_TYPE_NONE; - - for (int i = 0; ierror); i++) { - if (sd && i < sd[5]) - ost->error[i] = AV_RL64(sd + 8 + 8*i); - else - ost->error[i] = -1; - } - - if (!write_vstats) - return; - - /* this is executed just the first time update_video_stats is called */ - if (!vstats_file) { - vstats_file = fopen(vstats_filename, "w"); - if (!vstats_file) { - perror("fopen"); - exit_program(1); - } - } - - frame_number = ost->packets_encoded; - if (vstats_version <= 1) { - fprintf(vstats_file, "frame= %5"PRId64" q= %2.1f ", frame_number, - ost->quality / (float)FF_QP2LAMBDA); - } else { - fprintf(vstats_file, "out= %2d st= %2d frame= %5"PRId64" q= %2.1f ", ost->file_index, ost->index, frame_number, - ost->quality / (float)FF_QP2LAMBDA); - } - - if (ost->error[0]>=0 && (enc->flags & AV_CODEC_FLAG_PSNR)) - fprintf(vstats_file, "PSNR= %6.2f ", psnr(ost->error[0] / (enc->width * enc->height * 255.0 * 255.0))); - - fprintf(vstats_file,"f_size= %6d ", pkt->size); - /* compute pts value */ - ti1 = pkt->dts * av_q2d(pkt->time_base); - if (ti1 < 0.01) - ti1 = 0.01; - - bitrate = (pkt->size * 8) / av_q2d(enc->time_base) / 1000.0; - avg_bitrate = (double)(ost->data_size_enc * 8) / ti1 / 1000.0; - fprintf(vstats_file, "s_size= %8.0fkB time= %0.3f br= %7.1fkbits/s avg_br= %7.1fkbits/s ", - (double)ost->data_size_enc / 1024, ti1, bitrate, avg_bitrate); - fprintf(vstats_file, "type= %c\n", av_get_picture_type_char(ost->pict_type)); -} - -void enc_stats_write(OutputStream *ost, EncStats *es, - const AVFrame *frame, const AVPacket *pkt, - uint64_t frame_num) -{ - AVIOContext *io = es->io; - AVRational tb = frame ? frame->time_base : pkt->time_base; - int64_t pts = frame ? frame->pts : pkt->pts; - - AVRational tbi = (AVRational){ 0, 1}; - int64_t ptsi = INT64_MAX; - - const FrameData *fd; - - if ((frame && frame->opaque_ref) || (pkt && pkt->opaque_ref)) { - fd = (const FrameData*)(frame ? frame->opaque_ref->data : pkt->opaque_ref->data); - tbi = fd->tb; - ptsi = fd->pts; - } - - for (size_t i = 0; i < es->nb_components; i++) { - const EncStatsComponent *c = &es->components[i]; - - switch (c->type) { - case ENC_STATS_LITERAL: avio_write (io, c->str, c->str_len); continue; - case ENC_STATS_FILE_IDX: avio_printf(io, "%d", ost->file_index); continue; - case ENC_STATS_STREAM_IDX: avio_printf(io, "%d", ost->index); continue; - case ENC_STATS_TIMEBASE: avio_printf(io, "%d/%d", tb.num, tb.den); continue; - case ENC_STATS_TIMEBASE_IN: avio_printf(io, "%d/%d", tbi.num, tbi.den); continue; - case ENC_STATS_PTS: avio_printf(io, "%"PRId64, pts); continue; - case ENC_STATS_PTS_IN: avio_printf(io, "%"PRId64, ptsi); continue; - case ENC_STATS_PTS_TIME: avio_printf(io, "%g", pts * av_q2d(tb)); continue; - case ENC_STATS_PTS_TIME_IN: avio_printf(io, "%g", ptsi == INT64_MAX ? - INFINITY : ptsi * av_q2d(tbi)); continue; - case ENC_STATS_FRAME_NUM: avio_printf(io, "%"PRIu64, frame_num); continue; - case ENC_STATS_FRAME_NUM_IN: avio_printf(io, "%"PRIu64, fd ? fd->idx : -1); continue; - } - - if (frame) { - switch (c->type) { - case ENC_STATS_SAMPLE_NUM: avio_printf(io, "%"PRIu64, ost->samples_encoded); continue; - case ENC_STATS_NB_SAMPLES: avio_printf(io, "%d", frame->nb_samples); continue; - default: av_assert0(0); - } - } else { - switch (c->type) { - case ENC_STATS_DTS: avio_printf(io, "%"PRId64, pkt->dts); continue; - case ENC_STATS_DTS_TIME: avio_printf(io, "%g", pkt->dts * av_q2d(tb)); continue; - case ENC_STATS_PKT_SIZE: avio_printf(io, "%d", pkt->size); continue; - case ENC_STATS_BITRATE: { - double duration = FFMAX(pkt->duration, 1) * av_q2d(tb); - avio_printf(io, "%g", 8.0 * pkt->size / duration); - continue; - } - case ENC_STATS_AVG_BITRATE: { - double duration = pkt->dts * av_q2d(tb); - avio_printf(io, "%g", duration > 0 ? 8.0 * ost->data_size_enc / duration : -1.); - continue; - } - default: av_assert0(0); - } - } - } - avio_w8(io, '\n'); - avio_flush(io); -} - -static int encode_frame(OutputFile *of, OutputStream *ost, AVFrame *frame) -{ - AVCodecContext *enc = ost->enc_ctx; - AVPacket *pkt = ost->pkt; - const char *type_desc = av_get_media_type_string(enc->codec_type); - const char *action = frame ? "encode" : "flush"; - int ret; - - if (frame) { - if (ost->enc_stats_pre.io) - enc_stats_write(ost, &ost->enc_stats_pre, frame, NULL, - ost->frames_encoded); - - ost->frames_encoded++; - ost->samples_encoded += frame->nb_samples; - - if (debug_ts) { - av_log(ost, AV_LOG_INFO, "encoder <- type:%s " - "frame_pts:%s frame_pts_time:%s time_base:%d/%d\n", - type_desc, - av_ts2str(frame->pts), av_ts2timestr(frame->pts, &enc->time_base), - enc->time_base.num, enc->time_base.den); - } - } - - update_benchmark(NULL); - - ret = avcodec_send_frame(enc, frame); - if (ret < 0 && !(ret == AVERROR_EOF && !frame)) { - av_log(ost, AV_LOG_ERROR, "Error submitting %s frame to the encoder\n", - type_desc); - return ret; - } - - while (1) { - ret = avcodec_receive_packet(enc, pkt); - update_benchmark("%s_%s %d.%d", action, type_desc, - ost->file_index, ost->index); - - pkt->time_base = enc->time_base; - - /* if two pass, output log on success and EOF */ - if ((ret >= 0 || ret == AVERROR_EOF) && ost->logfile && enc->stats_out) - fprintf(ost->logfile, "%s", enc->stats_out); - - if (ret == AVERROR(EAGAIN)) { - av_assert0(frame); // should never happen during flushing - return 0; - } else if (ret == AVERROR_EOF) { - of_output_packet(of, pkt, ost, 1); - return ret; - } else if (ret < 0) { - av_log(ost, AV_LOG_ERROR, "%s encoding failed\n", type_desc); - return ret; - } - - if (enc->codec_type == AVMEDIA_TYPE_VIDEO) - update_video_stats(ost, pkt, !!vstats_filename); - if (ost->enc_stats_post.io) - enc_stats_write(ost, &ost->enc_stats_post, NULL, pkt, - ost->packets_encoded); - - if (debug_ts) { - av_log(ost, AV_LOG_INFO, "encoder -> type:%s " - "pkt_pts:%s pkt_pts_time:%s pkt_dts:%s pkt_dts_time:%s " - "duration:%s duration_time:%s\n", - type_desc, - av_ts2str(pkt->pts), av_ts2timestr(pkt->pts, &enc->time_base), - av_ts2str(pkt->dts), av_ts2timestr(pkt->dts, &enc->time_base), - av_ts2str(pkt->duration), av_ts2timestr(pkt->duration, &enc->time_base)); - } - - av_packet_rescale_ts(pkt, pkt->time_base, ost->mux_timebase); - pkt->time_base = ost->mux_timebase; - - if (debug_ts) { - av_log(ost, AV_LOG_INFO, "encoder -> type:%s " - "pkt_pts:%s pkt_pts_time:%s pkt_dts:%s pkt_dts_time:%s " - "duration:%s duration_time:%s\n", - type_desc, - av_ts2str(pkt->pts), av_ts2timestr(pkt->pts, &enc->time_base), - av_ts2str(pkt->dts), av_ts2timestr(pkt->dts, &enc->time_base), - av_ts2str(pkt->duration), av_ts2timestr(pkt->duration, &enc->time_base)); - } - - if ((ret = trigger_fix_sub_duration_heartbeat(ost, pkt)) < 0) { - av_log(NULL, AV_LOG_ERROR, - "Subtitle heartbeat logic failed in %s! (%s)\n", - __func__, av_err2str(ret)); - exit_program(1); - } - - ost->data_size_enc += pkt->size; - - ost->packets_encoded++; - - of_output_packet(of, pkt, ost, 0); - } - - av_assert0(0); -} - -static int submit_encode_frame(OutputFile *of, OutputStream *ost, - AVFrame *frame) -{ - int ret; - - if (ost->sq_idx_encode < 0) - return encode_frame(of, ost, frame); - - if (frame) { - ret = av_frame_ref(ost->sq_frame, frame); - if (ret < 0) - return ret; - frame = ost->sq_frame; - } - - ret = sq_send(of->sq_encode, ost->sq_idx_encode, - SQFRAME(frame)); - if (ret < 0) { - if (frame) - av_frame_unref(frame); - if (ret != AVERROR_EOF) - return ret; - } - - while (1) { - AVFrame *enc_frame = ost->sq_frame; - - ret = sq_receive(of->sq_encode, ost->sq_idx_encode, - SQFRAME(enc_frame)); - if (ret == AVERROR_EOF) { - enc_frame = NULL; - } else if (ret < 0) { - return (ret == AVERROR(EAGAIN)) ? 0 : ret; - } - - ret = encode_frame(of, ost, enc_frame); - if (enc_frame) - av_frame_unref(enc_frame); - if (ret < 0) { - if (ret == AVERROR_EOF) - close_output_stream(ost); - return ret; - } - } -} - -static void do_audio_out(OutputFile *of, OutputStream *ost, - AVFrame *frame) -{ - AVCodecContext *enc = ost->enc_ctx; - int ret; - - ret = enc_open(ost, frame); - if (ret < 0) - exit_program(1); - - if (frame->pts == AV_NOPTS_VALUE) - frame->pts = ost->next_pts; - else { - int64_t start_time = (of->start_time == AV_NOPTS_VALUE) ? 0 : of->start_time; - frame->pts = - av_rescale_q(frame->pts, frame->time_base, enc->time_base) - - av_rescale_q(start_time, AV_TIME_BASE_Q, enc->time_base); - } - frame->time_base = enc->time_base; - - if (!check_recording_time(ost, frame->pts, frame->time_base)) - return; - - ost->next_pts = frame->pts + frame->nb_samples; - - ret = submit_encode_frame(of, ost, frame); - if (ret < 0 && ret != AVERROR_EOF) - exit_program(1); -} - -/* Convert frame timestamps to the encoder timebase and decide how many times - * should this (and possibly previous) frame be repeated in order to conform to - * desired target framerate (if any). - */ -static void video_sync_process(OutputFile *of, OutputStream *ost, - AVFrame *next_picture, double duration, - int64_t *nb_frames, int64_t *nb_frames_prev) -{ - double delta0, delta; - - double sync_ipts = adjust_frame_pts_to_encoder_tb(of, ost, next_picture); - /* delta0 is the "drift" between the input frame (next_picture) and - * where it would fall in the output. */ - delta0 = sync_ipts - ost->next_pts; - delta = delta0 + duration; - - // tracks the number of times the PREVIOUS frame should be duplicated, - // mostly for variable framerate (VFR) - *nb_frames_prev = 0; - /* by default, we output a single frame */ - *nb_frames = 1; - - if (delta0 < 0 && - delta > 0 && - ost->vsync_method != VSYNC_PASSTHROUGH && - ost->vsync_method != VSYNC_DROP) { - if (delta0 < -0.6) { - av_log(ost, AV_LOG_VERBOSE, "Past duration %f too large\n", -delta0); - } else - av_log(ost, AV_LOG_DEBUG, "Clipping frame in rate conversion by %f\n", -delta0); - sync_ipts = ost->next_pts; - duration += delta0; - delta0 = 0; - } - - switch (ost->vsync_method) { - case VSYNC_VSCFR: - if (ost->vsync_frame_number == 0 && delta0 >= 0.5) { - av_log(ost, AV_LOG_DEBUG, "Not duplicating %d initial frames\n", (int)lrintf(delta0)); - delta = duration; - delta0 = 0; - ost->next_pts = llrint(sync_ipts); - } - case VSYNC_CFR: - // FIXME set to 0.5 after we fix some dts/pts bugs like in avidec.c - if (frame_drop_threshold && delta < frame_drop_threshold && ost->vsync_frame_number) { - *nb_frames = 0; - } else if (delta < -1.1) - *nb_frames = 0; - else if (delta > 1.1) { - *nb_frames = llrintf(delta); - if (delta0 > 1.1) - *nb_frames_prev = llrintf(delta0 - 0.6); - } - next_picture->duration = 1; - break; - case VSYNC_VFR: - if (delta <= -0.6) - *nb_frames = 0; - else if (delta > 0.6) - ost->next_pts = llrint(sync_ipts); - next_picture->duration = duration; - break; - case VSYNC_DROP: - case VSYNC_PASSTHROUGH: - next_picture->duration = duration; - ost->next_pts = llrint(sync_ipts); - break; - default: - av_assert0(0); - } -} - -static enum AVPictureType forced_kf_apply(void *logctx, KeyframeForceCtx *kf, - AVRational tb, const AVFrame *in_picture, - int dup_idx) -{ - double pts_time; - - if (kf->ref_pts == AV_NOPTS_VALUE) - kf->ref_pts = in_picture->pts; - - pts_time = (in_picture->pts - kf->ref_pts) * av_q2d(tb); - if (kf->index < kf->nb_pts && - av_compare_ts(in_picture->pts, tb, kf->pts[kf->index], AV_TIME_BASE_Q) >= 0) { - kf->index++; - goto force_keyframe; - } else if (kf->pexpr) { - double res; - kf->expr_const_values[FKF_T] = pts_time; - res = av_expr_eval(kf->pexpr, - kf->expr_const_values, NULL); - av_log(logctx, AV_LOG_TRACE, - "force_key_frame: n:%f n_forced:%f prev_forced_n:%f t:%f prev_forced_t:%f -> res:%f\n", - kf->expr_const_values[FKF_N], - kf->expr_const_values[FKF_N_FORCED], - kf->expr_const_values[FKF_PREV_FORCED_N], - kf->expr_const_values[FKF_T], - kf->expr_const_values[FKF_PREV_FORCED_T], - res); - - kf->expr_const_values[FKF_N] += 1; - - if (res) { - kf->expr_const_values[FKF_PREV_FORCED_N] = kf->expr_const_values[FKF_N] - 1; - kf->expr_const_values[FKF_PREV_FORCED_T] = kf->expr_const_values[FKF_T]; - kf->expr_const_values[FKF_N_FORCED] += 1; - goto force_keyframe; - } - } else if (kf->type == KF_FORCE_SOURCE && - in_picture->key_frame == 1 && !dup_idx) { - goto force_keyframe; - } else if (kf->type == KF_FORCE_SOURCE_NO_DROP && !dup_idx) { - kf->dropped_keyframe = 0; - if ((in_picture->key_frame == 1) || kf->dropped_keyframe) - goto force_keyframe; - } - - return AV_PICTURE_TYPE_NONE; - -force_keyframe: - av_log(logctx, AV_LOG_DEBUG, "Forced keyframe at time %f\n", pts_time); - return AV_PICTURE_TYPE_I; -} - -/* May modify/reset next_picture */ -static void do_video_out(OutputFile *of, - OutputStream *ost, - AVFrame *next_picture) -{ - int ret; - AVCodecContext *enc = ost->enc_ctx; - AVRational frame_rate; - int64_t nb_frames, nb_frames_prev, i; - double duration = 0; - InputStream *ist = ost->ist; - AVFilterContext *filter = ost->filter->filter; - - ret = enc_open(ost, next_picture); - if (ret < 0) - exit_program(1); - - frame_rate = av_buffersink_get_frame_rate(filter); - if (frame_rate.num > 0 && frame_rate.den > 0) - duration = 1/(av_q2d(frame_rate) * av_q2d(enc->time_base)); - - if(ist && ist->st->start_time != AV_NOPTS_VALUE && ist->first_dts != AV_NOPTS_VALUE && ost->frame_rate.num) - duration = FFMIN(duration, 1/(av_q2d(ost->frame_rate) * av_q2d(enc->time_base))); - - if (!ost->filters_script && - !ost->filters && - (nb_filtergraphs == 0 || !filtergraphs[0]->graph_desc) && - next_picture && - ist && - lrintf(next_picture->duration * av_q2d(ist->st->time_base) / av_q2d(enc->time_base)) > 0) { - duration = lrintf(next_picture->duration * av_q2d(ist->st->time_base) / av_q2d(enc->time_base)); - } - - if (!next_picture) { - //end, flushing - nb_frames_prev = nb_frames = mid_pred(ost->last_nb0_frames[0], - ost->last_nb0_frames[1], - ost->last_nb0_frames[2]); - } else { - video_sync_process(of, ost, next_picture, duration, - &nb_frames, &nb_frames_prev); - } - - memmove(ost->last_nb0_frames + 1, - ost->last_nb0_frames, - sizeof(ost->last_nb0_frames[0]) * (FF_ARRAY_ELEMS(ost->last_nb0_frames) - 1)); - ost->last_nb0_frames[0] = nb_frames_prev; - - if (nb_frames_prev == 0 && ost->last_dropped) { - nb_frames_drop++; - av_log(ost, AV_LOG_VERBOSE, - "*** dropping frame %"PRId64" at ts %"PRId64"\n", - ost->vsync_frame_number, ost->last_frame->pts); - } - if (nb_frames > (nb_frames_prev && ost->last_dropped) + (nb_frames > nb_frames_prev)) { - if (nb_frames > dts_error_threshold * 30) { - av_log(ost, AV_LOG_ERROR, "%"PRId64" frame duplication too large, skipping\n", nb_frames - 1); - nb_frames_drop++; - return; - } - nb_frames_dup += nb_frames - (nb_frames_prev && ost->last_dropped) - (nb_frames > nb_frames_prev); - av_log(ost, AV_LOG_VERBOSE, "*** %"PRId64" dup!\n", nb_frames - 1); - if (nb_frames_dup > dup_warning) { - av_log(ost, AV_LOG_WARNING, "More than %"PRIu64" frames duplicated\n", dup_warning); - dup_warning *= 10; - } - } - ost->last_dropped = nb_frames == nb_frames_prev && next_picture; - ost->kf.dropped_keyframe = ost->last_dropped && next_picture && next_picture->key_frame; - - /* duplicates frame if needed */ - for (i = 0; i < nb_frames; i++) { - AVFrame *in_picture; - - if (i < nb_frames_prev && ost->last_frame->buf[0]) { - in_picture = ost->last_frame; - } else - in_picture = next_picture; - - if (!in_picture) - return; - - in_picture->pts = ost->next_pts; - - if (!check_recording_time(ost, in_picture->pts, ost->enc_ctx->time_base)) - return; - - in_picture->quality = enc->global_quality; - in_picture->pict_type = forced_kf_apply(ost, &ost->kf, enc->time_base, in_picture, i); - - ret = submit_encode_frame(of, ost, in_picture); - if (ret == AVERROR_EOF) - break; - else if (ret < 0) - exit_program(1); - - ost->next_pts++; - ost->vsync_frame_number++; - } - - av_frame_unref(ost->last_frame); - if (next_picture) - av_frame_move_ref(ost->last_frame, next_picture); -} - /** * Get and encode new output from any of the filtergraphs, without causing * activity. @@ -1269,7 +668,6 @@ static int reap_filters(int flush) /* Reap all buffers present in the buffer sinks */ for (OutputStream *ost = ost_iter(NULL); ost; ost = ost_iter(ost)) { - OutputFile *of = output_files[ost->file_index]; AVFilterContext *filter; AVCodecContext *enc = ost->enc_ctx; int ret = 0; @@ -1289,7 +687,7 @@ static int reap_filters(int flush) "Error in av_buffersink_get_frame_flags(): %s\n", av_err2str(ret)); } else if (flush && ret == AVERROR_EOF) { if (av_buffersink_get_type(filter) == AVMEDIA_TYPE_VIDEO) - do_video_out(of, ost, NULL); + enc_frame(ost, NULL); } break; } @@ -1316,7 +714,7 @@ static int reap_filters(int flush) if (!ost->frame_aspect_ratio.num) enc->sample_aspect_ratio = filtered_frame->sample_aspect_ratio; - do_video_out(of, ost, filtered_frame); + enc_frame(ost, filtered_frame); break; case AVMEDIA_TYPE_AUDIO: if (!(enc->codec->capabilities & AV_CODEC_CAP_PARAM_CHANGE) && @@ -1326,7 +724,7 @@ static int reap_filters(int flush) "Audio filter graph output is not normalized and encoder does not support parameter changes\n"); break; } - do_audio_out(of, ost, filtered_frame); + enc_frame(ost, filtered_frame); break; default: // TODO support subtitle filters @@ -1657,7 +1055,7 @@ static void print_report(int is_last_report, int64_t timer_start, int64_t cur_ti print_final_stats(total_size); } -static int ifilter_parameters_from_codecpar(InputFilter *ifilter, AVCodecParameters *par) +int ifilter_parameters_from_codecpar(InputFilter *ifilter, AVCodecParameters *par) { int ret; @@ -1675,68 +1073,6 @@ static int ifilter_parameters_from_codecpar(InputFilter *ifilter, AVCodecParamet return 0; } -static void flush_encoders(void) -{ - int ret; - - for (OutputStream *ost = ost_iter(NULL); ost; ost = ost_iter(ost)) { - OutputFile *of = output_files[ost->file_index]; - if (ost->sq_idx_encode >= 0) - sq_send(of->sq_encode, ost->sq_idx_encode, SQFRAME(NULL)); - } - - for (OutputStream *ost = ost_iter(NULL); ost; ost = ost_iter(ost)) { - AVCodecContext *enc = ost->enc_ctx; - OutputFile *of = output_files[ost->file_index]; - - if (!enc) - continue; - - // Try to enable encoding with no input frames. - // Maybe we should just let encoding fail instead. - if (!ost->initialized) { - FilterGraph *fg = ost->filter->graph; - - av_log(ost, AV_LOG_WARNING, - "Finishing stream without any data written to it.\n"); - - if (ost->filter && !fg->graph) { - int x; - for (x = 0; x < fg->nb_inputs; x++) { - InputFilter *ifilter = fg->inputs[x]; - if (ifilter->format < 0 && - ifilter_parameters_from_codecpar(ifilter, ifilter->ist->par) < 0) { - av_log(ost, AV_LOG_ERROR, "Error copying paramerets from input stream\n"); - exit_program(1); - } - } - - if (!ifilter_has_all_input_formats(fg)) - continue; - - ret = configure_filtergraph(fg); - if (ret < 0) { - av_log(ost, AV_LOG_ERROR, "Error configuring filter graph\n"); - exit_program(1); - } - - of_output_packet(of, ost->pkt, ost, 1); - } - - ret = enc_open(ost, NULL); - if (ret < 0) - exit_program(1); - } - - if (enc->codec_type != AVMEDIA_TYPE_VIDEO && enc->codec_type != AVMEDIA_TYPE_AUDIO) - continue; - - ret = submit_encode_frame(of, ost, NULL); - if (ret != AVERROR_EOF) - exit_program(1); - } -} - /* * Check whether a packet from ist should be written into ost at this time */ @@ -1859,7 +1195,7 @@ static void check_decode_result(InputStream *ist, int *got_output, int ret) } // Filters can be configured only if the formats of all inputs are known. -static int ifilter_has_all_input_formats(FilterGraph *fg) +int ifilter_has_all_input_formats(FilterGraph *fg) { int i; for (i = 0; i < fg->nb_inputs; i++) { @@ -2377,7 +1713,7 @@ static int fix_sub_duration_heartbeat(InputStream *ist, int64_t signal_pts) return process_subtitle(ist, &subtitle, &got_output); } -static int trigger_fix_sub_duration_heartbeat(OutputStream *ost, const AVPacket *pkt) +int trigger_fix_sub_duration_heartbeat(OutputStream *ost, const AVPacket *pkt) { OutputFile *of = output_files[ost->file_index]; int64_t signal_pts = av_rescale_q(pkt->pts, pkt->time_base, @@ -3608,7 +2944,7 @@ static int transcode(void) process_input_packet(ist, NULL, 0); } } - flush_encoders(); + enc_flush(); term_exit(); diff --git a/fftools/ffmpeg.h b/fftools/ffmpeg.h index ffb0ca33ac9..c30659176eb 100644 --- a/fftools/ffmpeg.h +++ b/fftools/ffmpeg.h @@ -707,6 +707,13 @@ typedef struct OutputFile { int bitexact; } OutputFile; +// optionally attached as opaque_ref to decoded AVFrames +typedef struct FrameData { + uint64_t idx; + int64_t pts; + AVRational tb; +} FrameData; + extern InputFile **input_files; extern int nb_input_files; @@ -760,6 +767,11 @@ extern int copy_unknown_streams; extern int recast_media; +extern FILE *vstats_file; + +extern int64_t nb_frames_dup; +extern int64_t nb_frames_drop; + #if FFMPEG_OPT_PSNR extern int do_psnr; #endif @@ -788,6 +800,8 @@ int init_complex_filtergraph(FilterGraph *fg); void sub2video_update(InputStream *ist, int64_t heartbeat_pts, AVSubtitle *sub); int ifilter_parameters_from_frame(InputFilter *ifilter, const AVFrame *frame); +int ifilter_parameters_from_codecpar(InputFilter *ifilter, AVCodecParameters *par); +int ifilter_has_all_input_formats(FilterGraph *fg); int ffmpeg_parse_options(int argc, char **argv); @@ -812,8 +826,8 @@ int hwaccel_decode_init(AVCodecContext *avctx); int enc_open(OutputStream *ost, AVFrame *frame); void enc_subtitle(OutputFile *of, OutputStream *ost, AVSubtitle *sub); - -int check_recording_time(OutputStream *ost, int64_t ts, AVRational tb); +void enc_frame(OutputStream *ost, AVFrame *frame); +void enc_flush(void); /* * Initialize muxing state for the given stream, should be called @@ -861,6 +875,19 @@ int ifile_get_packet(InputFile *f, AVPacket **pkt); * pass NULL to start iteration */ InputStream *ist_iter(InputStream *prev); +/* iterate over all output streams in all output files; + * pass NULL to start iteration */ +OutputStream *ost_iter(OutputStream *prev); + +static inline double psnr(double d) +{ + return -10.0 * log10(d); +} + +void close_output_stream(OutputStream *ost); +int trigger_fix_sub_duration_heartbeat(OutputStream *ost, const AVPacket *pkt); +void update_benchmark(const char *fmt, ...); + #define SPECIFIER_OPT_FMT_str "%s" #define SPECIFIER_OPT_FMT_i "%i" #define SPECIFIER_OPT_FMT_i64 "%"PRId64 diff --git a/fftools/ffmpeg_enc.c b/fftools/ffmpeg_enc.c index bcc560b9b77..c0e3eaa1e8b 100644 --- a/fftools/ffmpeg_enc.c +++ b/fftools/ffmpeg_enc.c @@ -28,16 +28,23 @@ #include "libavutil/display.h" #include "libavutil/eval.h" #include "libavutil/frame.h" +#include "libavutil/intreadwrite.h" #include "libavutil/log.h" #include "libavutil/pixdesc.h" #include "libavutil/rational.h" +#include "libavutil/timestamp.h" #include "libavfilter/buffersink.h" #include "libavcodec/avcodec.h" +// FIXME private header, used for mid_pred() +#include "libavcodec/mathops.h" + #include "libavformat/avformat.h" +static uint64_t dup_warning = 1000; + static void set_encoder_id(OutputFile *of, OutputStream *ost) { const char *cname = ost->enc_ctx->codec->name; @@ -348,6 +355,18 @@ int enc_open(OutputStream *ost, AVFrame *frame) return 0; } +static int check_recording_time(OutputStream *ost, int64_t ts, AVRational tb) +{ + OutputFile *of = output_files[ost->file_index]; + + if (of->recording_time != INT64_MAX && + av_compare_ts(ts, tb, of->recording_time, AV_TIME_BASE_Q) >= 0) { + close_output_stream(ost); + return 0; + } + return 1; +} + void enc_subtitle(OutputFile *of, OutputStream *ost, AVSubtitle *sub) { int subtitle_out_max_size = 1024 * 1024; @@ -427,3 +446,644 @@ void enc_subtitle(OutputFile *of, OutputStream *ost, AVSubtitle *sub) of_output_packet(of, pkt, ost, 0); } } + +void enc_stats_write(OutputStream *ost, EncStats *es, + const AVFrame *frame, const AVPacket *pkt, + uint64_t frame_num) +{ + AVIOContext *io = es->io; + AVRational tb = frame ? frame->time_base : pkt->time_base; + int64_t pts = frame ? frame->pts : pkt->pts; + + AVRational tbi = (AVRational){ 0, 1}; + int64_t ptsi = INT64_MAX; + + const FrameData *fd; + + if ((frame && frame->opaque_ref) || (pkt && pkt->opaque_ref)) { + fd = (const FrameData*)(frame ? frame->opaque_ref->data : pkt->opaque_ref->data); + tbi = fd->tb; + ptsi = fd->pts; + } + + for (size_t i = 0; i < es->nb_components; i++) { + const EncStatsComponent *c = &es->components[i]; + + switch (c->type) { + case ENC_STATS_LITERAL: avio_write (io, c->str, c->str_len); continue; + case ENC_STATS_FILE_IDX: avio_printf(io, "%d", ost->file_index); continue; + case ENC_STATS_STREAM_IDX: avio_printf(io, "%d", ost->index); continue; + case ENC_STATS_TIMEBASE: avio_printf(io, "%d/%d", tb.num, tb.den); continue; + case ENC_STATS_TIMEBASE_IN: avio_printf(io, "%d/%d", tbi.num, tbi.den); continue; + case ENC_STATS_PTS: avio_printf(io, "%"PRId64, pts); continue; + case ENC_STATS_PTS_IN: avio_printf(io, "%"PRId64, ptsi); continue; + case ENC_STATS_PTS_TIME: avio_printf(io, "%g", pts * av_q2d(tb)); continue; + case ENC_STATS_PTS_TIME_IN: avio_printf(io, "%g", ptsi == INT64_MAX ? + INFINITY : ptsi * av_q2d(tbi)); continue; + case ENC_STATS_FRAME_NUM: avio_printf(io, "%"PRIu64, frame_num); continue; + case ENC_STATS_FRAME_NUM_IN: avio_printf(io, "%"PRIu64, fd ? fd->idx : -1); continue; + } + + if (frame) { + switch (c->type) { + case ENC_STATS_SAMPLE_NUM: avio_printf(io, "%"PRIu64, ost->samples_encoded); continue; + case ENC_STATS_NB_SAMPLES: avio_printf(io, "%d", frame->nb_samples); continue; + default: av_assert0(0); + } + } else { + switch (c->type) { + case ENC_STATS_DTS: avio_printf(io, "%"PRId64, pkt->dts); continue; + case ENC_STATS_DTS_TIME: avio_printf(io, "%g", pkt->dts * av_q2d(tb)); continue; + case ENC_STATS_PKT_SIZE: avio_printf(io, "%d", pkt->size); continue; + case ENC_STATS_BITRATE: { + double duration = FFMAX(pkt->duration, 1) * av_q2d(tb); + avio_printf(io, "%g", 8.0 * pkt->size / duration); + continue; + } + case ENC_STATS_AVG_BITRATE: { + double duration = pkt->dts * av_q2d(tb); + avio_printf(io, "%g", duration > 0 ? 8.0 * ost->data_size_enc / duration : -1.); + continue; + } + default: av_assert0(0); + } + } + } + avio_w8(io, '\n'); + avio_flush(io); +} + +static void update_video_stats(OutputStream *ost, const AVPacket *pkt, int write_vstats) +{ + const uint8_t *sd = av_packet_get_side_data(pkt, AV_PKT_DATA_QUALITY_STATS, + NULL); + AVCodecContext *enc = ost->enc_ctx; + int64_t frame_number; + double ti1, bitrate, avg_bitrate; + + ost->quality = sd ? AV_RL32(sd) : -1; + ost->pict_type = sd ? sd[4] : AV_PICTURE_TYPE_NONE; + + for (int i = 0; ierror); i++) { + if (sd && i < sd[5]) + ost->error[i] = AV_RL64(sd + 8 + 8*i); + else + ost->error[i] = -1; + } + + if (!write_vstats) + return; + + /* this is executed just the first time update_video_stats is called */ + if (!vstats_file) { + vstats_file = fopen(vstats_filename, "w"); + if (!vstats_file) { + perror("fopen"); + exit_program(1); + } + } + + frame_number = ost->packets_encoded; + if (vstats_version <= 1) { + fprintf(vstats_file, "frame= %5"PRId64" q= %2.1f ", frame_number, + ost->quality / (float)FF_QP2LAMBDA); + } else { + fprintf(vstats_file, "out= %2d st= %2d frame= %5"PRId64" q= %2.1f ", ost->file_index, ost->index, frame_number, + ost->quality / (float)FF_QP2LAMBDA); + } + + if (ost->error[0]>=0 && (enc->flags & AV_CODEC_FLAG_PSNR)) + fprintf(vstats_file, "PSNR= %6.2f ", psnr(ost->error[0] / (enc->width * enc->height * 255.0 * 255.0))); + + fprintf(vstats_file,"f_size= %6d ", pkt->size); + /* compute pts value */ + ti1 = pkt->dts * av_q2d(pkt->time_base); + if (ti1 < 0.01) + ti1 = 0.01; + + bitrate = (pkt->size * 8) / av_q2d(enc->time_base) / 1000.0; + avg_bitrate = (double)(ost->data_size_enc * 8) / ti1 / 1000.0; + fprintf(vstats_file, "s_size= %8.0fkB time= %0.3f br= %7.1fkbits/s avg_br= %7.1fkbits/s ", + (double)ost->data_size_enc / 1024, ti1, bitrate, avg_bitrate); + fprintf(vstats_file, "type= %c\n", av_get_picture_type_char(ost->pict_type)); +} + +static int encode_frame(OutputFile *of, OutputStream *ost, AVFrame *frame) +{ + AVCodecContext *enc = ost->enc_ctx; + AVPacket *pkt = ost->pkt; + const char *type_desc = av_get_media_type_string(enc->codec_type); + const char *action = frame ? "encode" : "flush"; + int ret; + + if (frame) { + if (ost->enc_stats_pre.io) + enc_stats_write(ost, &ost->enc_stats_pre, frame, NULL, + ost->frames_encoded); + + ost->frames_encoded++; + ost->samples_encoded += frame->nb_samples; + + if (debug_ts) { + av_log(ost, AV_LOG_INFO, "encoder <- type:%s " + "frame_pts:%s frame_pts_time:%s time_base:%d/%d\n", + type_desc, + av_ts2str(frame->pts), av_ts2timestr(frame->pts, &enc->time_base), + enc->time_base.num, enc->time_base.den); + } + } + + update_benchmark(NULL); + + ret = avcodec_send_frame(enc, frame); + if (ret < 0 && !(ret == AVERROR_EOF && !frame)) { + av_log(ost, AV_LOG_ERROR, "Error submitting %s frame to the encoder\n", + type_desc); + return ret; + } + + while (1) { + ret = avcodec_receive_packet(enc, pkt); + update_benchmark("%s_%s %d.%d", action, type_desc, + ost->file_index, ost->index); + + pkt->time_base = enc->time_base; + + /* if two pass, output log on success and EOF */ + if ((ret >= 0 || ret == AVERROR_EOF) && ost->logfile && enc->stats_out) + fprintf(ost->logfile, "%s", enc->stats_out); + + if (ret == AVERROR(EAGAIN)) { + av_assert0(frame); // should never happen during flushing + return 0; + } else if (ret == AVERROR_EOF) { + of_output_packet(of, pkt, ost, 1); + return ret; + } else if (ret < 0) { + av_log(ost, AV_LOG_ERROR, "%s encoding failed\n", type_desc); + return ret; + } + + if (enc->codec_type == AVMEDIA_TYPE_VIDEO) + update_video_stats(ost, pkt, !!vstats_filename); + if (ost->enc_stats_post.io) + enc_stats_write(ost, &ost->enc_stats_post, NULL, pkt, + ost->packets_encoded); + + if (debug_ts) { + av_log(ost, AV_LOG_INFO, "encoder -> type:%s " + "pkt_pts:%s pkt_pts_time:%s pkt_dts:%s pkt_dts_time:%s " + "duration:%s duration_time:%s\n", + type_desc, + av_ts2str(pkt->pts), av_ts2timestr(pkt->pts, &enc->time_base), + av_ts2str(pkt->dts), av_ts2timestr(pkt->dts, &enc->time_base), + av_ts2str(pkt->duration), av_ts2timestr(pkt->duration, &enc->time_base)); + } + + av_packet_rescale_ts(pkt, pkt->time_base, ost->mux_timebase); + pkt->time_base = ost->mux_timebase; + + if (debug_ts) { + av_log(ost, AV_LOG_INFO, "encoder -> type:%s " + "pkt_pts:%s pkt_pts_time:%s pkt_dts:%s pkt_dts_time:%s " + "duration:%s duration_time:%s\n", + type_desc, + av_ts2str(pkt->pts), av_ts2timestr(pkt->pts, &enc->time_base), + av_ts2str(pkt->dts), av_ts2timestr(pkt->dts, &enc->time_base), + av_ts2str(pkt->duration), av_ts2timestr(pkt->duration, &enc->time_base)); + } + + if ((ret = trigger_fix_sub_duration_heartbeat(ost, pkt)) < 0) { + av_log(NULL, AV_LOG_ERROR, + "Subtitle heartbeat logic failed in %s! (%s)\n", + __func__, av_err2str(ret)); + exit_program(1); + } + + ost->data_size_enc += pkt->size; + + ost->packets_encoded++; + + of_output_packet(of, pkt, ost, 0); + } + + av_assert0(0); +} + +static int submit_encode_frame(OutputFile *of, OutputStream *ost, + AVFrame *frame) +{ + int ret; + + if (ost->sq_idx_encode < 0) + return encode_frame(of, ost, frame); + + if (frame) { + ret = av_frame_ref(ost->sq_frame, frame); + if (ret < 0) + return ret; + frame = ost->sq_frame; + } + + ret = sq_send(of->sq_encode, ost->sq_idx_encode, + SQFRAME(frame)); + if (ret < 0) { + if (frame) + av_frame_unref(frame); + if (ret != AVERROR_EOF) + return ret; + } + + while (1) { + AVFrame *enc_frame = ost->sq_frame; + + ret = sq_receive(of->sq_encode, ost->sq_idx_encode, + SQFRAME(enc_frame)); + if (ret == AVERROR_EOF) { + enc_frame = NULL; + } else if (ret < 0) { + return (ret == AVERROR(EAGAIN)) ? 0 : ret; + } + + ret = encode_frame(of, ost, enc_frame); + if (enc_frame) + av_frame_unref(enc_frame); + if (ret < 0) { + if (ret == AVERROR_EOF) + close_output_stream(ost); + return ret; + } + } +} + +static void do_audio_out(OutputFile *of, OutputStream *ost, + AVFrame *frame) +{ + AVCodecContext *enc = ost->enc_ctx; + int ret; + + ret = enc_open(ost, frame); + if (ret < 0) + exit_program(1); + + if (frame->pts == AV_NOPTS_VALUE) + frame->pts = ost->next_pts; + else { + int64_t start_time = (of->start_time == AV_NOPTS_VALUE) ? 0 : of->start_time; + frame->pts = + av_rescale_q(frame->pts, frame->time_base, enc->time_base) - + av_rescale_q(start_time, AV_TIME_BASE_Q, enc->time_base); + } + frame->time_base = enc->time_base; + + if (!check_recording_time(ost, frame->pts, frame->time_base)) + return; + + ost->next_pts = frame->pts + frame->nb_samples; + + ret = submit_encode_frame(of, ost, frame); + if (ret < 0 && ret != AVERROR_EOF) + exit_program(1); +} + +static double adjust_frame_pts_to_encoder_tb(OutputFile *of, OutputStream *ost, + AVFrame *frame) +{ + double float_pts = AV_NOPTS_VALUE; // this is identical to frame.pts but with higher precision + const int64_t start_time = (of->start_time == AV_NOPTS_VALUE) ? + 0 : of->start_time; + + AVCodecContext *const enc = ost->enc_ctx; + + AVRational tb = enc->time_base; + AVRational filter_tb = frame->time_base; + const int extra_bits = av_clip(29 - av_log2(tb.den), 0, 16); + + if (frame->pts == AV_NOPTS_VALUE) + goto early_exit; + + tb.den <<= extra_bits; + float_pts = av_rescale_q(frame->pts, filter_tb, tb) - + av_rescale_q(start_time, AV_TIME_BASE_Q, tb); + float_pts /= 1 << extra_bits; + // avoid exact midoints to reduce the chance of rounding differences, this + // can be removed in case the fps code is changed to work with integers + float_pts += FFSIGN(float_pts) * 1.0 / (1<<17); + + frame->pts = av_rescale_q(frame->pts, filter_tb, enc->time_base) - + av_rescale_q(start_time, AV_TIME_BASE_Q, enc->time_base); + frame->time_base = enc->time_base; + +early_exit: + + if (debug_ts) { + av_log(NULL, AV_LOG_INFO, "filter -> pts:%s pts_time:%s exact:%f time_base:%d/%d\n", + frame ? av_ts2str(frame->pts) : "NULL", + (enc && frame) ? av_ts2timestr(frame->pts, &enc->time_base) : "NULL", + float_pts, + enc ? enc->time_base.num : -1, + enc ? enc->time_base.den : -1); + } + + return float_pts; +} + +/* Convert frame timestamps to the encoder timebase and decide how many times + * should this (and possibly previous) frame be repeated in order to conform to + * desired target framerate (if any). + */ +static void video_sync_process(OutputFile *of, OutputStream *ost, + AVFrame *next_picture, double duration, + int64_t *nb_frames, int64_t *nb_frames_prev) +{ + double delta0, delta; + + double sync_ipts = adjust_frame_pts_to_encoder_tb(of, ost, next_picture); + /* delta0 is the "drift" between the input frame (next_picture) and + * where it would fall in the output. */ + delta0 = sync_ipts - ost->next_pts; + delta = delta0 + duration; + + // tracks the number of times the PREVIOUS frame should be duplicated, + // mostly for variable framerate (VFR) + *nb_frames_prev = 0; + /* by default, we output a single frame */ + *nb_frames = 1; + + if (delta0 < 0 && + delta > 0 && + ost->vsync_method != VSYNC_PASSTHROUGH && + ost->vsync_method != VSYNC_DROP) { + if (delta0 < -0.6) { + av_log(ost, AV_LOG_VERBOSE, "Past duration %f too large\n", -delta0); + } else + av_log(ost, AV_LOG_DEBUG, "Clipping frame in rate conversion by %f\n", -delta0); + sync_ipts = ost->next_pts; + duration += delta0; + delta0 = 0; + } + + switch (ost->vsync_method) { + case VSYNC_VSCFR: + if (ost->vsync_frame_number == 0 && delta0 >= 0.5) { + av_log(ost, AV_LOG_DEBUG, "Not duplicating %d initial frames\n", (int)lrintf(delta0)); + delta = duration; + delta0 = 0; + ost->next_pts = llrint(sync_ipts); + } + case VSYNC_CFR: + // FIXME set to 0.5 after we fix some dts/pts bugs like in avidec.c + if (frame_drop_threshold && delta < frame_drop_threshold && ost->vsync_frame_number) { + *nb_frames = 0; + } else if (delta < -1.1) + *nb_frames = 0; + else if (delta > 1.1) { + *nb_frames = llrintf(delta); + if (delta0 > 1.1) + *nb_frames_prev = llrintf(delta0 - 0.6); + } + next_picture->duration = 1; + break; + case VSYNC_VFR: + if (delta <= -0.6) + *nb_frames = 0; + else if (delta > 0.6) + ost->next_pts = llrint(sync_ipts); + next_picture->duration = duration; + break; + case VSYNC_DROP: + case VSYNC_PASSTHROUGH: + next_picture->duration = duration; + ost->next_pts = llrint(sync_ipts); + break; + default: + av_assert0(0); + } +} + +static enum AVPictureType forced_kf_apply(void *logctx, KeyframeForceCtx *kf, + AVRational tb, const AVFrame *in_picture, + int dup_idx) +{ + double pts_time; + + if (kf->ref_pts == AV_NOPTS_VALUE) + kf->ref_pts = in_picture->pts; + + pts_time = (in_picture->pts - kf->ref_pts) * av_q2d(tb); + if (kf->index < kf->nb_pts && + av_compare_ts(in_picture->pts, tb, kf->pts[kf->index], AV_TIME_BASE_Q) >= 0) { + kf->index++; + goto force_keyframe; + } else if (kf->pexpr) { + double res; + kf->expr_const_values[FKF_T] = pts_time; + res = av_expr_eval(kf->pexpr, + kf->expr_const_values, NULL); + av_log(logctx, AV_LOG_TRACE, + "force_key_frame: n:%f n_forced:%f prev_forced_n:%f t:%f prev_forced_t:%f -> res:%f\n", + kf->expr_const_values[FKF_N], + kf->expr_const_values[FKF_N_FORCED], + kf->expr_const_values[FKF_PREV_FORCED_N], + kf->expr_const_values[FKF_T], + kf->expr_const_values[FKF_PREV_FORCED_T], + res); + + kf->expr_const_values[FKF_N] += 1; + + if (res) { + kf->expr_const_values[FKF_PREV_FORCED_N] = kf->expr_const_values[FKF_N] - 1; + kf->expr_const_values[FKF_PREV_FORCED_T] = kf->expr_const_values[FKF_T]; + kf->expr_const_values[FKF_N_FORCED] += 1; + goto force_keyframe; + } + } else if (kf->type == KF_FORCE_SOURCE && + in_picture->key_frame == 1 && !dup_idx) { + goto force_keyframe; + } else if (kf->type == KF_FORCE_SOURCE_NO_DROP && !dup_idx) { + kf->dropped_keyframe = 0; + if ((in_picture->key_frame == 1) || kf->dropped_keyframe) + goto force_keyframe; + } + + return AV_PICTURE_TYPE_NONE; + +force_keyframe: + av_log(logctx, AV_LOG_DEBUG, "Forced keyframe at time %f\n", pts_time); + return AV_PICTURE_TYPE_I; +} + +/* May modify/reset next_picture */ +static void do_video_out(OutputFile *of, + OutputStream *ost, + AVFrame *next_picture) +{ + int ret; + AVCodecContext *enc = ost->enc_ctx; + AVRational frame_rate; + int64_t nb_frames, nb_frames_prev, i; + double duration = 0; + InputStream *ist = ost->ist; + AVFilterContext *filter = ost->filter->filter; + + ret = enc_open(ost, next_picture); + if (ret < 0) + exit_program(1); + + frame_rate = av_buffersink_get_frame_rate(filter); + if (frame_rate.num > 0 && frame_rate.den > 0) + duration = 1/(av_q2d(frame_rate) * av_q2d(enc->time_base)); + + if(ist && ist->st->start_time != AV_NOPTS_VALUE && ist->first_dts != AV_NOPTS_VALUE && ost->frame_rate.num) + duration = FFMIN(duration, 1/(av_q2d(ost->frame_rate) * av_q2d(enc->time_base))); + + if (!ost->filters_script && + !ost->filters && + (nb_filtergraphs == 0 || !filtergraphs[0]->graph_desc) && + next_picture && + ist && + lrintf(next_picture->duration * av_q2d(ist->st->time_base) / av_q2d(enc->time_base)) > 0) { + duration = lrintf(next_picture->duration * av_q2d(ist->st->time_base) / av_q2d(enc->time_base)); + } + + if (!next_picture) { + //end, flushing + nb_frames_prev = nb_frames = mid_pred(ost->last_nb0_frames[0], + ost->last_nb0_frames[1], + ost->last_nb0_frames[2]); + } else { + video_sync_process(of, ost, next_picture, duration, + &nb_frames, &nb_frames_prev); + } + + memmove(ost->last_nb0_frames + 1, + ost->last_nb0_frames, + sizeof(ost->last_nb0_frames[0]) * (FF_ARRAY_ELEMS(ost->last_nb0_frames) - 1)); + ost->last_nb0_frames[0] = nb_frames_prev; + + if (nb_frames_prev == 0 && ost->last_dropped) { + nb_frames_drop++; + av_log(ost, AV_LOG_VERBOSE, + "*** dropping frame %"PRId64" at ts %"PRId64"\n", + ost->vsync_frame_number, ost->last_frame->pts); + } + if (nb_frames > (nb_frames_prev && ost->last_dropped) + (nb_frames > nb_frames_prev)) { + if (nb_frames > dts_error_threshold * 30) { + av_log(ost, AV_LOG_ERROR, "%"PRId64" frame duplication too large, skipping\n", nb_frames - 1); + nb_frames_drop++; + return; + } + nb_frames_dup += nb_frames - (nb_frames_prev && ost->last_dropped) - (nb_frames > nb_frames_prev); + av_log(ost, AV_LOG_VERBOSE, "*** %"PRId64" dup!\n", nb_frames - 1); + if (nb_frames_dup > dup_warning) { + av_log(ost, AV_LOG_WARNING, "More than %"PRIu64" frames duplicated\n", dup_warning); + dup_warning *= 10; + } + } + ost->last_dropped = nb_frames == nb_frames_prev && next_picture; + ost->kf.dropped_keyframe = ost->last_dropped && next_picture && next_picture->key_frame; + + /* duplicates frame if needed */ + for (i = 0; i < nb_frames; i++) { + AVFrame *in_picture; + + if (i < nb_frames_prev && ost->last_frame->buf[0]) { + in_picture = ost->last_frame; + } else + in_picture = next_picture; + + if (!in_picture) + return; + + in_picture->pts = ost->next_pts; + + if (!check_recording_time(ost, in_picture->pts, ost->enc_ctx->time_base)) + return; + + in_picture->quality = enc->global_quality; + in_picture->pict_type = forced_kf_apply(ost, &ost->kf, enc->time_base, in_picture, i); + + ret = submit_encode_frame(of, ost, in_picture); + if (ret == AVERROR_EOF) + break; + else if (ret < 0) + exit_program(1); + + ost->next_pts++; + ost->vsync_frame_number++; + } + + av_frame_unref(ost->last_frame); + if (next_picture) + av_frame_move_ref(ost->last_frame, next_picture); +} + +void enc_frame(OutputStream *ost, AVFrame *frame) +{ + OutputFile *of = output_files[ost->file_index]; + + if (ost->enc_ctx->codec_type == AVMEDIA_TYPE_VIDEO) do_video_out(of, ost, frame); + else do_audio_out(of, ost, frame); +} + +void enc_flush(void) +{ + int ret; + + for (OutputStream *ost = ost_iter(NULL); ost; ost = ost_iter(ost)) { + OutputFile *of = output_files[ost->file_index]; + if (ost->sq_idx_encode >= 0) + sq_send(of->sq_encode, ost->sq_idx_encode, SQFRAME(NULL)); + } + + for (OutputStream *ost = ost_iter(NULL); ost; ost = ost_iter(ost)) { + AVCodecContext *enc = ost->enc_ctx; + OutputFile *of = output_files[ost->file_index]; + + if (!enc) + continue; + + // Try to enable encoding with no input frames. + // Maybe we should just let encoding fail instead. + if (!ost->initialized) { + FilterGraph *fg = ost->filter->graph; + + av_log(ost, AV_LOG_WARNING, + "Finishing stream without any data written to it.\n"); + + if (ost->filter && !fg->graph) { + int x; + for (x = 0; x < fg->nb_inputs; x++) { + InputFilter *ifilter = fg->inputs[x]; + if (ifilter->format < 0 && + ifilter_parameters_from_codecpar(ifilter, ifilter->ist->par) < 0) { + av_log(ost, AV_LOG_ERROR, "Error copying paramerets from input stream\n"); + exit_program(1); + } + } + + if (!ifilter_has_all_input_formats(fg)) + continue; + + ret = configure_filtergraph(fg); + if (ret < 0) { + av_log(ost, AV_LOG_ERROR, "Error configuring filter graph\n"); + exit_program(1); + } + + of_output_packet(of, ost->pkt, ost, 1); + } + + ret = enc_open(ost, NULL); + if (ret < 0) + exit_program(1); + } + + if (enc->codec_type != AVMEDIA_TYPE_VIDEO && enc->codec_type != AVMEDIA_TYPE_AUDIO) + continue; + + ret = submit_encode_frame(of, ost, NULL); + if (ret != AVERROR_EOF) + exit_program(1); + } +} From f30b620e98ca35eb669fae4fbe4911b779c8413d Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Sat, 25 Mar 2023 19:46:28 +0100 Subject: [PATCH 0619/2172] fftools/ffmpeg: add encoder private data Start by moving OutputStream.last_frame to it. In the future it will hold other encoder-internal state. --- fftools/ffmpeg.h | 7 +++++- fftools/ffmpeg_enc.c | 51 +++++++++++++++++++++++++++++++++++---- fftools/ffmpeg_mux.c | 3 ++- fftools/ffmpeg_mux_init.c | 8 +++--- 4 files changed, 58 insertions(+), 11 deletions(-) diff --git a/fftools/ffmpeg.h b/fftools/ffmpeg.h index c30659176eb..8193dabb573 100644 --- a/fftools/ffmpeg.h +++ b/fftools/ffmpeg.h @@ -557,6 +557,8 @@ typedef struct KeyframeForceCtx { int dropped_keyframe; } KeyframeForceCtx; +typedef struct Encoder Encoder; + typedef struct OutputStream { const AVClass *class; @@ -588,9 +590,9 @@ typedef struct OutputStream { AVRational mux_timebase; AVRational enc_timebase; + Encoder *enc; AVCodecContext *enc_ctx; AVFrame *filtered_frame; - AVFrame *last_frame; AVFrame *sq_frame; AVPacket *pkt; int64_t last_dropped; @@ -824,6 +826,9 @@ AVBufferRef *hw_device_for_filter(void); int hwaccel_decode_init(AVCodecContext *avctx); +int enc_alloc(Encoder **penc, const AVCodec *codec); +void enc_free(Encoder **penc); + int enc_open(OutputStream *ost, AVFrame *frame); void enc_subtitle(OutputFile *of, OutputStream *ost, AVSubtitle *sub); void enc_frame(OutputStream *ost, AVFrame *frame); diff --git a/fftools/ffmpeg_enc.c b/fftools/ffmpeg_enc.c index c0e3eaa1e8b..1387e05cf67 100644 --- a/fftools/ffmpeg_enc.c +++ b/fftools/ffmpeg_enc.c @@ -43,8 +43,48 @@ #include "libavformat/avformat.h" +struct Encoder { + AVFrame *last_frame; +}; + static uint64_t dup_warning = 1000; +void enc_free(Encoder **penc) +{ + Encoder *enc = *penc; + + if (!enc) + return; + + av_frame_free(&enc->last_frame); + + av_freep(penc); +} + +int enc_alloc(Encoder **penc, const AVCodec *codec) +{ + Encoder *enc; + + *penc = NULL; + + enc = av_mallocz(sizeof(*enc)); + if (!enc) + return AVERROR(ENOMEM); + + if (codec->type == AVMEDIA_TYPE_VIDEO) { + enc->last_frame = av_frame_alloc(); + if (!enc->last_frame) + goto fail; + } + + *penc = enc; + + return 0; +fail: + enc_free(&enc); + return AVERROR(ENOMEM); +} + static void set_encoder_id(OutputFile *of, OutputStream *ost) { const char *cname = ost->enc_ctx->codec->name; @@ -919,6 +959,7 @@ static void do_video_out(OutputFile *of, AVFrame *next_picture) { int ret; + Encoder *e = ost->enc; AVCodecContext *enc = ost->enc_ctx; AVRational frame_rate; int64_t nb_frames, nb_frames_prev, i; @@ -965,7 +1006,7 @@ static void do_video_out(OutputFile *of, nb_frames_drop++; av_log(ost, AV_LOG_VERBOSE, "*** dropping frame %"PRId64" at ts %"PRId64"\n", - ost->vsync_frame_number, ost->last_frame->pts); + ost->vsync_frame_number, e->last_frame->pts); } if (nb_frames > (nb_frames_prev && ost->last_dropped) + (nb_frames > nb_frames_prev)) { if (nb_frames > dts_error_threshold * 30) { @@ -987,8 +1028,8 @@ static void do_video_out(OutputFile *of, for (i = 0; i < nb_frames; i++) { AVFrame *in_picture; - if (i < nb_frames_prev && ost->last_frame->buf[0]) { - in_picture = ost->last_frame; + if (i < nb_frames_prev && e->last_frame->buf[0]) { + in_picture = e->last_frame; } else in_picture = next_picture; @@ -1013,9 +1054,9 @@ static void do_video_out(OutputFile *of, ost->vsync_frame_number++; } - av_frame_unref(ost->last_frame); + av_frame_unref(e->last_frame); if (next_picture) - av_frame_move_ref(ost->last_frame, next_picture); + av_frame_move_ref(e->last_frame, next_picture); } void enc_frame(OutputStream *ost, AVFrame *frame) diff --git a/fftools/ffmpeg_mux.c b/fftools/ffmpeg_mux.c index 1937bc2aa79..527567831ff 100644 --- a/fftools/ffmpeg_mux.c +++ b/fftools/ffmpeg_mux.c @@ -643,6 +643,8 @@ static void ost_free(OutputStream **post) return; ms = ms_from_ost(ost); + enc_free(&ost->enc); + if (ost->logfile) { if (fclose(ost->logfile)) av_log(ms, AV_LOG_ERROR, @@ -662,7 +664,6 @@ static void ost_free(OutputStream **post) av_frame_free(&ost->filtered_frame); av_frame_free(&ost->sq_frame); - av_frame_free(&ost->last_frame); av_packet_free(&ost->pkt); av_dict_free(&ost->encoder_opts); diff --git a/fftools/ffmpeg_mux_init.c b/fftools/ffmpeg_mux_init.c index 2e9bdcfde1a..6c53a8810d0 100644 --- a/fftools/ffmpeg_mux_init.c +++ b/fftools/ffmpeg_mux_init.c @@ -462,6 +462,10 @@ static OutputStream *new_output_stream(Muxer *mux, const OptionsContext *o, if (!ost->enc_ctx) report_and_exit(AVERROR(ENOMEM)); + ret = enc_alloc(&ost->enc, enc); + if (ret < 0) + report_and_exit(ret); + av_strlcat(ms->log_name, "/", sizeof(ms->log_name)); av_strlcat(ms->log_name, enc->name, sizeof(ms->log_name)); } else { @@ -933,10 +937,6 @@ static OutputStream *new_video_stream(Muxer *mux, const OptionsContext *o, Input ost->avfilter = get_ost_filters(o, oc, ost); if (!ost->avfilter) exit_program(1); - - ost->last_frame = av_frame_alloc(); - if (!ost->last_frame) - report_and_exit(AVERROR(ENOMEM)); } else check_streamcopy_filters(o, oc, ost, AVMEDIA_TYPE_VIDEO); From a2a09932f2c5e7ab23e6821d812439fff913f328 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Sat, 25 Mar 2023 19:58:00 +0100 Subject: [PATCH 0620/2172] fftools/ffmpeg: stop including os_support.h It was added for usleep(), which - is not used in ffmpeg - is not handled in os_support.h anymore --- fftools/ffmpeg.c | 1 - 1 file changed, 1 deletion(-) diff --git a/fftools/ffmpeg.c b/fftools/ffmpeg.c index 07fc9789436..d2789b6f5bb 100644 --- a/fftools/ffmpeg.c +++ b/fftools/ffmpeg.c @@ -63,7 +63,6 @@ #include "libavutil/thread.h" #include "libavutil/threadmessage.h" #include "libavcodec/version.h" -#include "libavformat/os_support.h" # include "libavfilter/avfilter.h" # include "libavfilter/buffersrc.h" From 2225134e7d4992eecd2be8ced90977877a138e90 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Sat, 25 Mar 2023 20:02:23 +0100 Subject: [PATCH 0621/2172] fftools/ffmpeg: clean up #includes Drop unneeded ctype.h and math.h. Group all system headers together. Sort unconditional includes alphabetically. Group local includes by the library, sort alphabetically. --- fftools/ffmpeg.c | 74 ++++++++++++++++++++++++------------------------ 1 file changed, 37 insertions(+), 37 deletions(-) diff --git a/fftools/ffmpeg.c b/fftools/ffmpeg.c index d2789b6f5bb..750ab76693e 100644 --- a/fftools/ffmpeg.c +++ b/fftools/ffmpeg.c @@ -24,14 +24,14 @@ */ #include "config.h" -#include -#include -#include -#include + #include #include #include #include +#include +#include +#include #if HAVE_IO_H #include @@ -40,34 +40,6 @@ #include #endif -#include "libavformat/avformat.h" -#include "libavdevice/avdevice.h" -#include "libswresample/swresample.h" -#include "libavutil/opt.h" -#include "libavutil/channel_layout.h" -#include "libavutil/parseutils.h" -#include "libavutil/samplefmt.h" -#include "libavutil/fifo.h" -#include "libavutil/hwcontext.h" -#include "libavutil/intreadwrite.h" -#include "libavutil/dict.h" -#include "libavutil/display.h" -#include "libavutil/mathematics.h" -#include "libavutil/pixdesc.h" -#include "libavutil/avstring.h" -#include "libavutil/libm.h" -#include "libavutil/imgutils.h" -#include "libavutil/timestamp.h" -#include "libavutil/bprint.h" -#include "libavutil/time.h" -#include "libavutil/thread.h" -#include "libavutil/threadmessage.h" -#include "libavcodec/version.h" - -# include "libavfilter/avfilter.h" -# include "libavfilter/buffersrc.h" -# include "libavfilter/buffersink.h" - #if HAVE_SYS_RESOURCE_H #include #include @@ -83,7 +55,6 @@ #include #endif - #if HAVE_SYS_SELECT_H #include #endif @@ -97,14 +68,43 @@ #include #endif -#include +#include "libavutil/avassert.h" +#include "libavutil/avstring.h" +#include "libavutil/bprint.h" +#include "libavutil/channel_layout.h" +#include "libavutil/dict.h" +#include "libavutil/display.h" +#include "libavutil/fifo.h" +#include "libavutil/hwcontext.h" +#include "libavutil/imgutils.h" +#include "libavutil/intreadwrite.h" +#include "libavutil/libm.h" +#include "libavutil/mathematics.h" +#include "libavutil/opt.h" +#include "libavutil/parseutils.h" +#include "libavutil/pixdesc.h" +#include "libavutil/samplefmt.h" +#include "libavutil/thread.h" +#include "libavutil/threadmessage.h" +#include "libavutil/time.h" +#include "libavutil/timestamp.h" + +#include "libavcodec/version.h" + +#include "libavformat/avformat.h" + +#include "libavdevice/avdevice.h" + +#include "libswresample/swresample.h" + +#include "libavfilter/avfilter.h" +#include "libavfilter/buffersrc.h" +#include "libavfilter/buffersink.h" -#include "ffmpeg.h" #include "cmdutils.h" +#include "ffmpeg.h" #include "sync_queue.h" -#include "libavutil/avassert.h" - const char program_name[] = "ffmpeg"; const int program_birth_year = 2000; From f098eaee56b5dd7707b572f9fd0512f8bc72ed77 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Sat, 25 Mar 2023 20:13:34 +0100 Subject: [PATCH 0622/2172] fftools/ffmpeg_enc: factorize calling enc_init() It is done in the same way for both audio and video, so can be moved to enc_frame(). --- fftools/ffmpeg_enc.c | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/fftools/ffmpeg_enc.c b/fftools/ffmpeg_enc.c index 1387e05cf67..2f1803a74c3 100644 --- a/fftools/ffmpeg_enc.c +++ b/fftools/ffmpeg_enc.c @@ -762,10 +762,6 @@ static void do_audio_out(OutputFile *of, OutputStream *ost, AVCodecContext *enc = ost->enc_ctx; int ret; - ret = enc_open(ost, frame); - if (ret < 0) - exit_program(1); - if (frame->pts == AV_NOPTS_VALUE) frame->pts = ost->next_pts; else { @@ -967,10 +963,6 @@ static void do_video_out(OutputFile *of, InputStream *ist = ost->ist; AVFilterContext *filter = ost->filter->filter; - ret = enc_open(ost, next_picture); - if (ret < 0) - exit_program(1); - frame_rate = av_buffersink_get_frame_rate(filter); if (frame_rate.num > 0 && frame_rate.den > 0) duration = 1/(av_q2d(frame_rate) * av_q2d(enc->time_base)); @@ -1062,6 +1054,11 @@ static void do_video_out(OutputFile *of, void enc_frame(OutputStream *ost, AVFrame *frame) { OutputFile *of = output_files[ost->file_index]; + int ret; + + ret = enc_open(ost, frame); + if (ret < 0) + exit_program(1); if (ost->enc_ctx->codec_type == AVMEDIA_TYPE_VIDEO) do_video_out(of, ost, frame); else do_audio_out(of, ost, frame); From b18a9c29713abc3a1b081de3f320ab53a47120c6 Mon Sep 17 00:00:00 2001 From: Leo Izen Date: Thu, 16 Mar 2023 15:32:14 -0400 Subject: [PATCH 0623/2172] avcodec/mjpegdec: support weird RGB subsampling with progressive This allows weird subsampling with progressive JPEGs to be decoded, such as full-RG and only B subsampled. Signed-off-by: Leo Izen --- libavcodec/mjpegdec.c | 27 +++++++++++++++++---------- 1 file changed, 17 insertions(+), 10 deletions(-) diff --git a/libavcodec/mjpegdec.c b/libavcodec/mjpegdec.c index c833d66c4db..3fc18aac73b 100644 --- a/libavcodec/mjpegdec.c +++ b/libavcodec/mjpegdec.c @@ -571,10 +571,15 @@ int ff_mjpeg_decode_sof(MJpegDecodeContext *s) case 0x22221100: case 0x22112200: case 0x11222200: - if (s->bits <= 8) s->avctx->pix_fmt = s->cs_itu601 ? AV_PIX_FMT_YUV444P : AV_PIX_FMT_YUVJ444P; - else + if (s->bits > 8) goto unk_pixfmt; - s->avctx->color_range = s->cs_itu601 ? AVCOL_RANGE_MPEG : AVCOL_RANGE_JPEG; + if (s->adobe_transform == 0 || s->component_id[0] == 'R' && + s->component_id[1] == 'G' && s->component_id[2] == 'B') { + s->avctx->pix_fmt = AV_PIX_FMT_GBRP; + } else { + s->avctx->pix_fmt = s->cs_itu601 ? AV_PIX_FMT_YUV444P : AV_PIX_FMT_YUVJ444P; + s->avctx->color_range = s->cs_itu601 ? AVCOL_RANGE_MPEG : AVCOL_RANGE_JPEG; + } break; case 0x11000000: case 0x13000000: @@ -673,10 +678,6 @@ int ff_mjpeg_decode_sof(MJpegDecodeContext *s) avpriv_report_missing_feature(s->avctx, "Lowres for weird subsampling"); return AVERROR_PATCHWELCOME; } - if ((AV_RB32(s->upscale_h) || AV_RB32(s->upscale_v)) && s->progressive && s->avctx->pix_fmt == AV_PIX_FMT_GBRP) { - avpriv_report_missing_feature(s->avctx, "progressive for weird subsampling"); - return AVERROR_PATCHWELCOME; - } if (s->ls) { memset(s->upscale_h, 0, sizeof(s->upscale_h)); memset(s->upscale_v, 0, sizeof(s->upscale_v)); @@ -1697,9 +1698,6 @@ int ff_mjpeg_decode_sos(MJpegDecodeContext *s, const uint8_t *mb_bitmask, s->h_scount[i] = s->h_count[index]; s->v_scount[i] = s->v_count[index]; - if((nb_components == 1 || nb_components == 3) && s->nb_components == 3 && s->avctx->pix_fmt == AV_PIX_FMT_GBR24P) - index = (index+2)%3; - s->comp_index[i] = index; s->dc_index[i] = get_bits(&s->gb, 4); @@ -2722,6 +2720,15 @@ int ff_mjpeg_decode_frame_from_buf(AVCodecContext *avctx, AVFrame *frame, } } } + + if (s->avctx->pix_fmt == AV_PIX_FMT_GBRP) { + av_assert0(s->nb_components == 3); + FFSWAP(uint8_t *, frame->data[0], frame->data[2]); + FFSWAP(uint8_t *, frame->data[0], frame->data[1]); + FFSWAP(int, frame->linesize[0], frame->linesize[2]); + FFSWAP(int, frame->linesize[0], frame->linesize[1]); + } + if (s->adobe_transform == 0 && s->avctx->pix_fmt == AV_PIX_FMT_GBRAP) { int w = s->picture_ptr->width; int h = s->picture_ptr->height; From c558fcf41e2027a1096d00b286954da2cc4ae73f Mon Sep 17 00:00:00 2001 From: James Almer Date: Mon, 10 Apr 2023 18:45:21 -0300 Subject: [PATCH 0624/2172] avformat/matroskadec: also export non-HDR10+ ITU-T T.35 payloads as BlockAdditional side data Partially reverts a change from 88de01d878167cbff9af32c0b7366e0aae3db2bd, and 2133cadfcf9a613cf2c0060f9896bba49dabfba4. Signed-off-by: James Almer --- libavformat/matroskadec.c | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/libavformat/matroskadec.c b/libavformat/matroskadec.c index 6cccbcbe039..49950956b63 100644 --- a/libavformat/matroskadec.c +++ b/libavformat/matroskadec.c @@ -3719,19 +3719,21 @@ static int matroska_parse_block_additional(MatroskaDemuxContext *matroska, av_free(hdrplus); return res; } - break; + + return 0; } default: - side_data = av_packet_new_side_data(pkt, AV_PKT_DATA_MATROSKA_BLOCKADDITIONAL, - size + (size_t)8); - if (!side_data) - return AVERROR(ENOMEM); - - AV_WB64(side_data, id); - memcpy(side_data + 8, data, size); break; } + side_data = av_packet_new_side_data(pkt, AV_PKT_DATA_MATROSKA_BLOCKADDITIONAL, + size + (size_t)8); + if (!side_data) + return AVERROR(ENOMEM); + + AV_WB64(side_data, id); + memcpy(side_data + 8, data, size); + return 0; } From 1a7df525f6c2ea0287351dfad4580d57d23ff730 Mon Sep 17 00:00:00 2001 From: James Almer Date: Mon, 10 Apr 2023 22:12:13 -0300 Subject: [PATCH 0625/2172] avformat/matroskaenc: fix memory leak in fail codepath Signed-off-by: James Almer --- libavformat/matroskaenc.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libavformat/matroskaenc.c b/libavformat/matroskaenc.c index 59ed5be951d..492b86b8d7c 100644 --- a/libavformat/matroskaenc.c +++ b/libavformat/matroskaenc.c @@ -2715,7 +2715,7 @@ static int mkv_write_block(void *logctx, MatroskaMuxContext *mkv, ret = av_dynamic_hdr_plus_to_t35((AVDynamicHDRPlus *)side_data, &payload, &payload_size); if (ret < 0) - return ret; + goto fail; mkv_write_blockadditional(&writer, buf, buf_size, MATROSKA_BLOCK_ADD_ID_ITU_T_T35); @@ -2738,6 +2738,7 @@ static int mkv_write_block(void *logctx, MatroskaMuxContext *mkv, track->last_timestamp - ts); ret = ebml_writer_write(&writer, pb); +fail: av_free(buf); return ret; From ab177c7469ee41523548dab640bba694b3c16d34 Mon Sep 17 00:00:00 2001 From: Zhao Zhili Date: Wed, 5 Apr 2023 20:50:16 +0800 Subject: [PATCH 0626/2172] configure: cleanup mediacodec dependency Signed-off-by: Zhao Zhili --- configure | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/configure b/configure index 6e363eb4702..76461415c95 100755 --- a/configure +++ b/configure @@ -2999,6 +2999,7 @@ cuvid_deps="ffnvcodec" d3d11va_deps="dxva_h ID3D11VideoDecoder ID3D11VideoContext" dxva2_deps="dxva2api_h DXVA2_ConfigPictureDecode ole32 user32" ffnvcodec_deps_any="libdl LoadLibrary" +mediacodec_deps="android" nvdec_deps="ffnvcodec" vaapi_x11_deps="xlib_x11" videotoolbox_hwaccel_deps="videotoolbox pthreads" @@ -3159,7 +3160,6 @@ aac_mf_encoder_deps="mediafoundation" ac3_mf_encoder_deps="mediafoundation" av1_cuvid_decoder_deps="cuvid CUVIDAV1PICPARAMS" av1_mediacodec_decoder_deps="mediacodec" -av1_mediacodec_decoder_extralibs="-landroid" av1_nvenc_encoder_deps="nvenc NV_ENC_PIC_PARAMS_AV1" av1_nvenc_encoder_select="atsc_a53" h263_v4l2m2m_decoder_deps="v4l2_m2m h263_v4l2_m2m" @@ -3169,10 +3169,8 @@ h264_crystalhd_decoder_select="crystalhd h264_mp4toannexb_bsf h264_parser" h264_cuvid_decoder_deps="cuvid" h264_cuvid_decoder_select="h264_mp4toannexb_bsf" h264_mediacodec_decoder_deps="mediacodec" -h264_mediacodec_decoder_extralibs="-landroid" h264_mediacodec_decoder_select="h264_mp4toannexb_bsf h264_parser" h264_mediacodec_encoder_deps="mediacodec" -h264_mediacodec_encoder_extralibs="-landroid" h264_mediacodec_encoder_select="h264_metadata" h264_mf_encoder_deps="mediafoundation" h264_mmal_decoder_deps="mmal" @@ -3191,10 +3189,8 @@ hevc_amf_encoder_deps="amf" hevc_cuvid_decoder_deps="cuvid" hevc_cuvid_decoder_select="hevc_mp4toannexb_bsf" hevc_mediacodec_decoder_deps="mediacodec" -hevc_mediacodec_decoder_extralibs="-landroid" hevc_mediacodec_decoder_select="hevc_mp4toannexb_bsf hevc_parser" hevc_mediacodec_encoder_deps="mediacodec" -hevc_mediacodec_encoder_extralibs="-landroid" hevc_mediacodec_encoder_select="hevc_metadata" hevc_mf_encoder_deps="mediafoundation" hevc_nvenc_encoder_deps="nvenc" @@ -3229,7 +3225,6 @@ mpeg4_crystalhd_decoder_select="crystalhd" mpeg4_cuvid_decoder_deps="cuvid" mpeg4_mediacodec_decoder_deps="mediacodec" mpeg4_mediacodec_encoder_deps="mediacodec" -mpeg4_mediacodec_encoder_extralibs="-landroid" mpeg4_mmal_decoder_deps="mmal" mpeg4_omx_encoder_deps="omx" mpeg4_v4l2m2m_decoder_deps="v4l2_m2m mpeg4_v4l2_m2m" @@ -3250,9 +3245,7 @@ vp8_v4l2m2m_decoder_deps="v4l2_m2m vp8_v4l2_m2m" vp8_v4l2m2m_encoder_deps="v4l2_m2m vp8_v4l2_m2m" vp9_cuvid_decoder_deps="cuvid" vp9_mediacodec_decoder_deps="mediacodec" -vp9_mediacodec_decoder_extralibs="-landroid" vp9_mediacodec_encoder_deps="mediacodec" -vp9_mediacodec_encoder_extralibs="-landroid" vp9_qsv_decoder_select="qsvdec" vp9_rkmpp_decoder_deps="rkmpp" vp9_vaapi_encoder_deps="VAEncPictureParameterBufferVP9" From ef09db1eaca22cad6dab0335be19bb5de86d4f24 Mon Sep 17 00:00:00 2001 From: Zhao Zhili Date: Wed, 5 Apr 2023 20:50:17 +0800 Subject: [PATCH 0627/2172] configure: add mediacodec_extralibs to avutil Fix #10299 Signed-off-by: Zhao Zhili --- configure | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure b/configure index 76461415c95..8f77e13541f 100755 --- a/configure +++ b/configure @@ -3827,7 +3827,7 @@ swscale_suggest="libm stdatomic" avcodec_extralibs="pthreads_extralibs iconv_extralibs dxva2_extralibs lcms2_extralibs" avfilter_extralibs="pthreads_extralibs" -avutil_extralibs="d3d11va_extralibs nanosleep_extralibs pthreads_extralibs vaapi_drm_extralibs vaapi_x11_extralibs vdpau_x11_extralibs" +avutil_extralibs="d3d11va_extralibs mediacodec_extralibs nanosleep_extralibs pthreads_extralibs vaapi_drm_extralibs vaapi_x11_extralibs vdpau_x11_extralibs" # programs ffmpeg_deps="avcodec avfilter avformat threads" From 4dffa564d1cc0fa49d88e19ac998de6e9c26ab52 Mon Sep 17 00:00:00 2001 From: Zhao Zhili Date: Wed, 5 Apr 2023 20:50:18 +0800 Subject: [PATCH 0628/2172] configure: remove duplicated extralibs of android_camera Signed-off-by: Zhao Zhili --- configure | 1 - 1 file changed, 1 deletion(-) diff --git a/configure b/configure index 8f77e13541f..033db7442d3 100755 --- a/configure +++ b/configure @@ -3504,7 +3504,6 @@ xwma_demuxer_select="riffdec" # indevs / outdevs android_camera_indev_deps="android camera2ndk mediandk pthreads" -android_camera_indev_extralibs="-landroid -lcamera2ndk -lmediandk" alsa_indev_deps="alsa" alsa_outdev_deps="alsa" avfoundation_indev_deps="avfoundation corevideo coremedia pthreads" From 00a062b8d55ce868449404142b3cf137940f7ab4 Mon Sep 17 00:00:00 2001 From: xufuji456 <839789740@qq.com> Date: Tue, 11 Apr 2023 19:10:02 +0800 Subject: [PATCH 0629/2172] codec/aarch64/hevc:add idct_32x32_neon MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit got 73% speed up (run_count=1000, CPU=Cortex A53) idct_32x32_neon: 4826 idct_32x32_c: 18236 idct_32x32_neon: 4824 idct_32x32_c: 18149 idct_32x32_neon: 4937 idct_32x32_c: 18333 Signed-off-by: Martin Storsjö --- libavcodec/aarch64/hevcdsp_idct_neon.S | 289 +++++++++++++++++++--- libavcodec/aarch64/hevcdsp_init_aarch64.c | 5 + 2 files changed, 266 insertions(+), 28 deletions(-) diff --git a/libavcodec/aarch64/hevcdsp_idct_neon.S b/libavcodec/aarch64/hevcdsp_idct_neon.S index 3e59dd20bbd..976dec236a5 100644 --- a/libavcodec/aarch64/hevcdsp_idct_neon.S +++ b/libavcodec/aarch64/hevcdsp_idct_neon.S @@ -6,6 +6,7 @@ * Ported from arm/hevcdsp_idct_neon.S by * Copyright (c) 2020 Reimar Döffinger * Copyright (c) 2023 J. Dekker + * Copyright (c) 2023 xu fulong <839789740@qq.com> * * This file is part of FFmpeg. * @@ -477,34 +478,52 @@ endfunc sqrshrn2 \out3\().8h, \in7, \shift .endm -.macro transpose16_4x4_2 r0, r1, r2, r3 +// use temp register to transpose, then we can reuse it +.macro transpose16_4x4_2 r0, r1, r2, r3, tmp0, tmp1, tmp2, tmp3, tmp4, tmp5 // lower halves - trn1 v2.4h, \r0\().4h, \r1\().4h - trn2 v3.4h, \r0\().4h, \r1\().4h - trn1 v4.4h, \r2\().4h, \r3\().4h - trn2 v5.4h, \r2\().4h, \r3\().4h - trn1 v6.2s, v2.2s, v4.2s - trn2 v7.2s, v2.2s, v4.2s - trn1 v2.2s, v3.2s, v5.2s - trn2 v4.2s, v3.2s, v5.2s - mov \r0\().d[0], v6.d[0] - mov \r2\().d[0], v7.d[0] - mov \r1\().d[0], v2.d[0] - mov \r3\().d[0], v4.d[0] + trn1 \tmp0\().4h, \r0\().4h, \r1\().4h + trn2 \tmp1\().4h, \r0\().4h, \r1\().4h + trn1 \tmp2\().4h, \r2\().4h, \r3\().4h + trn2 \tmp3\().4h, \r2\().4h, \r3\().4h + trn1 \tmp4\().2s, \tmp0\().2s, \tmp2\().2s + trn2 \tmp5\().2s, \tmp0\().2s, \tmp2\().2s + trn1 \tmp0\().2s, \tmp1\().2s, \tmp3\().2s + trn2 \tmp2\().2s, \tmp1\().2s, \tmp3\().2s + mov \r0\().d[0], \tmp4\().d[0] + mov \r2\().d[0], \tmp5\().d[0] + mov \r1\().d[0], \tmp0\().d[0] + mov \r3\().d[0], \tmp2\().d[0] // upper halves in reverse order - trn1 v2.8h, \r3\().8h, \r2\().8h - trn2 v3.8h, \r3\().8h, \r2\().8h - trn1 v4.8h, \r1\().8h, \r0\().8h - trn2 v5.8h, \r1\().8h, \r0\().8h - trn1 v6.4s, v2.4s, v4.4s - trn2 v7.4s, v2.4s, v4.4s - trn1 v2.4s, v3.4s, v5.4s - trn2 v4.4s, v3.4s, v5.4s - mov \r3\().d[1], v6.d[1] - mov \r1\().d[1], v7.d[1] - mov \r2\().d[1], v2.d[1] - mov \r0\().d[1], v4.d[1] + trn1 \tmp0\().8h, \r3\().8h, \r2\().8h + trn2 \tmp1\().8h, \r3\().8h, \r2\().8h + trn1 \tmp2\().8h, \r1\().8h, \r0\().8h + trn2 \tmp3\().8h, \r1\().8h, \r0\().8h + trn1 \tmp4\().4s, \tmp0\().4s, \tmp2\().4s + trn2 \tmp5\().4s, \tmp0\().4s, \tmp2\().4s + trn1 \tmp0\().4s, \tmp1\().4s, \tmp3\().4s + trn2 \tmp2\().4s, \tmp1\().4s, \tmp3\().4s + mov \r3\().d[1], \tmp4\().d[1] + mov \r1\().d[1], \tmp5\().d[1] + mov \r2\().d[1], \tmp0\().d[1] + mov \r0\().d[1], \tmp2\().d[1] +.endm + +// stores in0, in2, in4, in6 ascending from off1 and +// stores in1, in3, in5, in7 descending from off2 +.macro store_to_stack off1, off2, in0, in2, in4, in6, in7, in5, in3, in1 + add x1, sp, #\off1 + add x3, sp, #\off2 + mov x2, #-16 + mov x4, #16 + st1 {\in0}, [x1], x4 + st1 {\in1}, [x3], x2 + st1 {\in2}, [x1], x4 + st1 {\in3}, [x3], x2 + st1 {\in4}, [x1], x4 + st1 {\in5}, [x3], x2 + st1 {\in6}, [x1] + st1 {\in7}, [x3] .endm .macro tr_16x4 name, shift, offset, step @@ -543,27 +562,34 @@ function func_tr_16x4_\name add x4, sp, #\offset ld1 {v16.4s-v19.4s}, [x4], #64 - butterfly16 v16.4s, v21.4s, v17.4s, v22.4s, v18.4s, v23.4s, v19.4s, v24.4s + .if \shift > 0 scale v29, v30, v31, v24, v20.4s, v16.4s, v21.4s, v17.4s, v22.4s, v18.4s, v23.4s, v19.4s, \shift - transpose16_4x4_2 v29, v30, v31, v24 + transpose16_4x4_2 v29, v30, v31, v24, v2, v3, v4, v5, v6, v7 mov x1, x6 add x3, x6, #(24 +3*32) mov x2, #32 mov x4, #-32 store16 v29.d, v30.d, v31.d, v24.d, x4 + .else + store_to_stack \offset, (\offset + 240), v20.4s, v21.4s, v22.4s, v23.4s, v19.4s, v18.4s, v17.4s, v16.4s + .endif add x4, sp, #(\offset + 64) ld1 {v16.4s-v19.4s}, [x4] butterfly16 v16.4s, v25.4s, v17.4s, v26.4s, v18.4s, v27.4s, v19.4s, v28.4s + .if \shift > 0 scale v29, v30, v31, v20, v20.4s, v16.4s, v25.4s, v17.4s, v26.4s, v18.4s, v27.4s, v19.4s, \shift - transpose16_4x4_2 v29, v30, v31, v20 + transpose16_4x4_2 v29, v30, v31, v20, v2, v3, v4, v5, v6, v7 add x1, x6, #8 add x3, x6, #(16 + 3 * 32) mov x2, #32 mov x4, #-32 store16 v29.d, v30.d, v31.d, v20.d, x4 + .else + store_to_stack (\offset + 64), (\offset + 176), v20.4s, v25.4s, v26.4s, v27.4s, v19.4s, v18.4s, v17.4s, v16.4s + .endif ret endfunc @@ -596,6 +622,203 @@ function ff_hevc_idct_16x16_\bitdepth\()_neon, export=1 endfunc .endm +.macro load32 + add x1, x5, #64 + add x3, x1, #128 + mov x2, #256 + ld1 {v4.d}[0], [x1], x2 + ld1 {v4.d}[1], [x3], x2 + ld1 {v5.d}[0], [x1], x2 + ld1 {v5.d}[1], [x3], x2 + ld1 {v6.d}[0], [x1], x2 + ld1 {v6.d}[1], [x3], x2 + ld1 {v7.d}[0], [x1], x2 + ld1 {v7.d}[1], [x3], x2 + ld1 {v16.d}[0], [x1], x2 + ld1 {v16.d}[1], [x3], x2 + ld1 {v17.d}[0], [x1], x2 + ld1 {v17.d}[1], [x3], x2 + ld1 {v18.d}[0], [x1], x2 + ld1 {v18.d}[1], [x3], x2 + ld1 {v19.d}[0], [x1], x2 + ld1 {v19.d}[1], [x3], x2 +.endm + +.macro add_member32 in, t0, t1, t2, t3, op0, op1, op2, op3, p + sum_sub v24.4s, \in, \t0, \op0, \p + sum_sub v25.4s, \in, \t1, \op1, \p + sum_sub v26.4s, \in, \t2, \op2, \p + sum_sub v27.4s, \in, \t3, \op3, \p +.endm + +.macro butterfly32 in0, in1, in2, in3, out + add \out, \in0, \in1 + sub \in0, \in0, \in1 + add \in1, \in2, \in3 + sub \in2, \in2, \in3 +.endm + +.macro multiply in + smull v24.4s, v4.4h, \in\().h[0] + smull v25.4s, v4.4h, \in\().h[1] + smull v26.4s, v4.4h, \in\().h[2] + smull v27.4s, v4.4h, \in\().h[3] +.endm + +.macro scale_store shift + ld1 {v28.8h-v31.8h}, [x4], #64 + butterfly32 v28.4s, v24.4s, v29.4s, v25.4s, v2.4s + butterfly32 v30.4s, v26.4s, v31.4s, v27.4s, v3.4s + scale v20, v21, v22, v23, v2.4s, v28.4s, v24.4s, v29.4s, v3.4s, v30.4s, v26.4s, v31.4s, \shift + + transpose16_4x4_2 v20, v21, v22, v23, v24, v25, v26, v27, v28, v29 + store16 v20.d, v21.d, v22.d, v23.d, x8 + + // reload coefficients + ld1 {v2.4h-v3.4h}, [x9] +.endm + +function tr_block1 + multiply v0 + add_member32 v4.8h, v0.h[1], v1.h[0], v1.h[3], v2.h[2], +, +, +, +, 2 + add_member32 v5.4h, v0.h[2], v1.h[3], v3.h[0], v3.h[2], +, +, +, - + add_member32 v5.8h, v0.h[3], v2.h[2], v3.h[2], v1.h[3], +, +, -, -, 2 + add_member32 v6.4h, v1.h[0], v3.h[1], v2.h[1], v0.h[0], +, +, -, - + add_member32 v6.8h, v1.h[1], v3.h[3], v1.h[0], v1.h[2], +, -, -, -, 2 + add_member32 v7.4h, v1.h[2], v3.h[0], v0.h[0], v3.h[1], +, -, -, - + add_member32 v7.8h, v1.h[3], v2.h[1], v1.h[1], v2.h[3], +, -, -, +, 2 + add_member32 v16.4h, v2.h[0], v1.h[2], v2.h[2], v1.h[0], +, -, -, + + add_member32 v16.8h, v2.h[1], v0.h[3], v3.h[3], v0.h[2], +, -, -, +, 2 + add_member32 v17.4h, v2.h[2], v0.h[1], v2.h[3], v2.h[1], +, -, +, + + add_member32 v17.8h, v2.h[3], v0.h[2], v1.h[2], v3.h[3], +, -, +, -, 2 + add_member32 v18.4h, v3.h[0], v1.h[1], v0.h[1], v2.h[0], +, -, +, - + add_member32 v18.8h, v3.h[1], v2.h[0], v0.h[3], v0.h[1], +, -, +, -, 2 + add_member32 v19.4h, v3.h[2], v2.h[3], v2.h[0], v1.h[1], +, -, +, - + add_member32 v19.8h, v3.h[3], v3.h[2], v3.h[1], v3.h[0], +, -, +, -, 2 + ret +endfunc + +function tr_block2 + multiply v1 + add_member32 v4.8h, v3.h[1], v3.h[3], v3.h[0], v2.h[1], +, -, -, -, 2 + add_member32 v5.4h, v2.h[1], v1.h[0], v0.h[0], v1.h[1], -, -, -, - + add_member32 v5.8h, v0.h[0], v1.h[2], v3.h[1], v2.h[3], -, -, -, +, 2 + add_member32 v6.4h, v2.h[0], v3.h[2], v1.h[1], v0.h[3], -, +, +, + + add_member32 v6.8h, v3.h[2], v0.h[3], v1.h[3], v3.h[1], +, +, +, -, 2 + add_member32 v7.4h, v1.h[1], v1.h[3], v2.h[3], v0.h[0], +, +, -, - + add_member32 v7.8h, v0.h[3], v3.h[1], v0.h[1], v3.h[3], +, -, -, +, 2 + add_member32 v16.4h, v3.h[0], v0.h[2], v3.h[2], v0.h[1], +, -, -, + + add_member32 v16.8h, v2.h[2], v2.h[0], v1.h[0], v3.h[2], -, -, +, +, 2 + add_member32 v17.4h, v0.h[1], v3.h[0], v2.h[0], v0.h[2], -, +, +, - + add_member32 v17.8h, v1.h[3], v0.h[1], v2.h[2], v3.h[0], -, +, -, -, 2 + add_member32 v18.4h, v3.h[3], v2.h[1], v0.h[2], v1.h[0], +, +, -, + + add_member32 v18.8h, v1.h[2], v2.h[3], v3.h[3], v2.h[2], +, -, -, +, 2 + add_member32 v19.4h, v0.h[2], v0.h[1], v0.h[3], v1.h[2], +, -, +, - + add_member32 v19.8h, v2.h[3], v2.h[2], v2.h[1], v2.h[0], +, -, +, -, 2 + ret +endfunc + +function tr_block3 + multiply v2 + add_member32 v4.8h, v1.h[2], v0.h[3], v0.h[0], v0.h[2], -, -, -, -, 2 + add_member32 v5.4h, v2.h[2], v3.h[3], v2.h[3], v1.h[2], -, -, +, + + add_member32 v5.8h, v1.h[0], v0.h[2], v2.h[1], v3.h[3], +, +, +, -, 2 + add_member32 v6.4h, v3.h[0], v2.h[2], v0.h[1], v1.h[3], +, -, -, - + add_member32 v6.8h, v0.h[2], v2.h[0], v3.h[0], v0.h[0], -, -, +, +, 2 + add_member32 v7.4h, v3.h[2], v1.h[0], v2.h[0], v2.h[2], -, +, +, - + add_member32 v7.8h, v0.h[0], v3.h[2], v0.h[2], v3.h[0], +, +, -, -, 2 + add_member32 v16.4h, v3.h[3], v0.h[1], v3.h[1], v0.h[3], -, -, +, + + add_member32 v16.8h, v0.h[1], v2.h[3], v1.h[3], v1.h[1], -, +, +, -, 2 + add_member32 v17.4h, v3.h[1], v1.h[3], v0.h[3], v3.h[2], +, +, -, + + add_member32 v17.8h, v0.h[3], v1.h[1], v3.h[2], v2.h[0], +, -, +, +, 2 + add_member32 v18.4h, v2.h[3], v3.h[1], v1.h[2], v0.h[1], -, -, +, - + add_member32 v18.8h, v1.h[1], v0.h[0], v1.h[0], v2.h[1], -, +, -, +, 2 + add_member32 v19.4h, v2.h[1], v3.h[0], v3.h[3], v3.h[1], +, -, +, + + add_member32 v19.8h, v1.h[3], v1.h[2], v1.h[1], v1.h[0], +, -, +, -, 2 + ret +endfunc + +function tr_block4 + multiply v3 + add_member32 v4.8h, v1.h[1], v2.h[0], v2.h[3], v3.h[2], -, -, -, -, 2 + add_member32 v5.4h, v0.h[0], v0.h[3], v2.h[0], v3.h[1], +, +, +, + + add_member32 v5.8h, v2.h[0], v0.h[0], v1.h[1], v3.h[0], -, -, -, -, 2 + add_member32 v6.4h, v3.h[3], v1.h[2], v0.h[2], v2.h[3], +, +, +, + + add_member32 v6.8h, v2.h[1], v2.h[3], v0.h[0], v2.h[2], +, -, -, -, 2 + add_member32 v7.4h, v0.h[2], v3.h[3], v0.h[3], v2.h[1], -, -, +, + + add_member32 v7.8h, v1.h[0], v2.h[2], v1.h[2], v2.h[0], +, +, -, -, 2 + add_member32 v16.4h, v2.h[3], v1.h[1], v2.h[1], v1.h[3], -, -, +, + + add_member32 v16.8h, v3.h[1], v0.h[1], v3.h[0], v1.h[2], -, +, -, -, 2 + add_member32 v17.4h, v1.h[2], v1.h[0], v3.h[3], v1.h[1], +, -, +, + + add_member32 v17.8h, v0.h[1], v2.h[1], v3.h[1], v1.h[0], -, +, +, -, 2 + add_member32 v18.4h, v1.h[3], v3.h[2], v2.h[2], v0.h[3], +, -, -, + + add_member32 v18.8h, v3.h[2], v3.h[0], v1.h[3], v0.h[2], -, -, +, -, 2 + add_member32 v19.4h, v2.h[2], v1.h[3], v1.h[0], v0.h[1], -, +, -, + + add_member32 v19.8h, v0.h[3], v0.h[2], v0.h[1], v0.h[0], +, -, +, -, 2 + ret +endfunc + +.macro tr_32x4 name, shift +function func_tr_32x4_\name + mov x10, x30 + bl func_tr_16x4_noscale + + load32 + movrel x9, trans, 32 + ld1 {v0.4h-v1.4h}, [x9], #16 + ld1 {v2.4h-v3.4h}, [x9] + add x4, sp, #2048 + mov x2, #64 + mov x8, #-64 + + bl tr_block1 + mov x1, x11 + add x3, x11, #(56 + 3 * 64) + scale_store \shift + + bl tr_block2 + add x1, x11, #8 + add x3, x11, #(48 + 3 * 64) + scale_store \shift + + bl tr_block3 + add x1, x11, #16 + add x3, x11, #(40 + 3 * 64) + scale_store \shift + + bl tr_block4 + add x1, x11, #24 + add x3, x11, #(32 + 3 * 64) + scale_store \shift + + br x10 +endfunc +.endm + +.macro idct_32x32 bitdepth +function ff_hevc_idct_32x32_\bitdepth\()_neon, export=1 + mov x15, x30 + // allocate a temp buffer + sub sp, sp, #2432 + +.irp i, 0, 1, 2, 3, 4, 5, 6, 7 + add x5, x0, #(8 * \i) + add x11, sp, #(8 * \i * 32) + bl func_tr_32x4_firstpass +.endr + +.irp i, 0, 1, 2, 3, 4, 5, 6, 7 + add x5, sp, #(8 * \i) + add x11, x0, #(8 * \i * 32) + bl func_tr_32x4_secondpass_\bitdepth +.endr + + add sp, sp, #2432 + mov x30, x15 + ret +endfunc +.endm + idct_4x4 8 idct_4x4 10 @@ -605,10 +828,20 @@ idct_8x8 10 tr_16x4 firstpass, 7, 512, 1 tr_16x4 secondpass_8, 20 - 8, 512, 1 tr_16x4 secondpass_10, 20 - 10, 512, 1 +tr_16x4 noscale, 0, 2048, 4 idct_16x16 8 idct_16x16 10 +.ltorg +tr_32x4 firstpass, 7 +tr_32x4 secondpass_8, 20 - 8 +tr_32x4 secondpass_10, 20 - 10 +.ltorg + +idct_32x32 8 +idct_32x32 10 + // void ff_hevc_idct_NxN_dc_DEPTH_neon(int16_t *coeffs) .macro idct_dc size, bitdepth function ff_hevc_idct_\size\()x\size\()_dc_\bitdepth\()_neon, export=1 diff --git a/libavcodec/aarch64/hevcdsp_init_aarch64.c b/libavcodec/aarch64/hevcdsp_init_aarch64.c index a923bae35c3..4cc8732ad3a 100644 --- a/libavcodec/aarch64/hevcdsp_init_aarch64.c +++ b/libavcodec/aarch64/hevcdsp_init_aarch64.c @@ -1,5 +1,6 @@ /* * Copyright (c) 2020 Reimar Döffinger + * Copyright (c) 2023 xu fulong <839789740@qq.com> * * This file is part of FFmpeg. * @@ -67,6 +68,8 @@ void ff_hevc_idct_8x8_8_neon(int16_t *coeffs, int col_limit); void ff_hevc_idct_8x8_10_neon(int16_t *coeffs, int col_limit); void ff_hevc_idct_16x16_8_neon(int16_t *coeffs, int col_limit); void ff_hevc_idct_16x16_10_neon(int16_t *coeffs, int col_limit); +void ff_hevc_idct_32x32_8_neon(int16_t *coeffs, int col_limit); +void ff_hevc_idct_32x32_10_neon(int16_t *coeffs, int col_limit); void ff_hevc_idct_4x4_dc_8_neon(int16_t *coeffs); void ff_hevc_idct_8x8_dc_8_neon(int16_t *coeffs); void ff_hevc_idct_16x16_dc_8_neon(int16_t *coeffs); @@ -138,6 +141,7 @@ av_cold void ff_hevc_dsp_init_aarch64(HEVCDSPContext *c, const int bit_depth) c->idct[0] = ff_hevc_idct_4x4_8_neon; c->idct[1] = ff_hevc_idct_8x8_8_neon; c->idct[2] = ff_hevc_idct_16x16_8_neon; + c->idct[3] = ff_hevc_idct_32x32_8_neon; c->idct_dc[0] = ff_hevc_idct_4x4_dc_8_neon; c->idct_dc[1] = ff_hevc_idct_8x8_dc_8_neon; c->idct_dc[2] = ff_hevc_idct_16x16_dc_8_neon; @@ -190,6 +194,7 @@ av_cold void ff_hevc_dsp_init_aarch64(HEVCDSPContext *c, const int bit_depth) c->idct[0] = ff_hevc_idct_4x4_10_neon; c->idct[1] = ff_hevc_idct_8x8_10_neon; c->idct[2] = ff_hevc_idct_16x16_10_neon; + c->idct[3] = ff_hevc_idct_32x32_10_neon; c->idct_dc[0] = ff_hevc_idct_4x4_dc_10_neon; c->idct_dc[1] = ff_hevc_idct_8x8_dc_10_neon; c->idct_dc[2] = ff_hevc_idct_16x16_dc_10_neon; From 1179bb703e35543e15401f05a4cc81cc389756ba Mon Sep 17 00:00:00 2001 From: Leo Izen Date: Tue, 4 Apr 2023 10:16:21 -0400 Subject: [PATCH 0630/2172] avcodec/libjxlenc: use reciprocol gamma for GAMMA22 and GAMMA28 libjxl rejects JxlColorEncoding->gamma 2.2f or 2.8f and expects 1/2.2f or 1/2.8f, respectively. Signed-off-by: Leo Izen --- libavcodec/libjxlenc.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libavcodec/libjxlenc.c b/libavcodec/libjxlenc.c index 897452f5750..d707f3a61b5 100644 --- a/libavcodec/libjxlenc.c +++ b/libavcodec/libjxlenc.c @@ -335,11 +335,11 @@ static int libjxl_encode_frame(AVCodecContext *avctx, AVPacket *pkt, const AVFra break; case AVCOL_TRC_GAMMA22: jxl_color.transfer_function = JXL_TRANSFER_FUNCTION_GAMMA; - jxl_color.gamma = 2.2; + jxl_color.gamma = 1/2.2f; break; case AVCOL_TRC_GAMMA28: jxl_color.transfer_function = JXL_TRANSFER_FUNCTION_GAMMA; - jxl_color.gamma = 2.8; + jxl_color.gamma = 1/2.8f; break; default: if (pix_desc->flags & AV_PIX_FMT_FLAG_FLOAT) { From 30def6365d24eb2052d9072d15e024c498478c03 Mon Sep 17 00:00:00 2001 From: xufuji456 <839789740@qq.com> Date: Thu, 13 Apr 2023 14:46:43 +0800 Subject: [PATCH 0631/2172] checkasm/hevc: add transform_luma test MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: xufuji456 <839789740@qq.com> Signed-off-by: Martin Storsjö --- tests/checkasm/hevc_idct.c | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/tests/checkasm/hevc_idct.c b/tests/checkasm/hevc_idct.c index 338b8a23e4a..446d69f931e 100644 --- a/tests/checkasm/hevc_idct.c +++ b/tests/checkasm/hevc_idct.c @@ -84,6 +84,27 @@ static void check_idct_dc(HEVCDSPContext h, int bit_depth) } } +static void check_transform_luma(HEVCDSPContext *h, int bit_depth) +{ + LOCAL_ALIGNED(32, int16_t, coeffs0, [32 * 32]); + LOCAL_ALIGNED(32, int16_t, coeffs1, [32 * 32]); + + int block_size = 4; + int size = block_size * block_size; + declare_func_emms(AV_CPU_FLAG_MMXEXT, void, int16_t *coeffs); + + randomize_buffers(coeffs0, size); + memcpy(coeffs1, coeffs0, sizeof(*coeffs0) * size); + + if (check_func(h->transform_4x4_luma, "hevc_transform_luma_4x4_%d", bit_depth)) { + call_ref(coeffs0); + call_new(coeffs1); + if (memcmp(coeffs0, coeffs1, sizeof(*coeffs0) * size)) + fail(); + bench_new(coeffs1); + } +} + void checkasm_check_hevc_idct(void) { int bit_depth; @@ -103,4 +124,12 @@ void checkasm_check_hevc_idct(void) check_idct(h, bit_depth); } report("idct"); + + for (bit_depth = 8; bit_depth <= 12; bit_depth += 2) { + HEVCDSPContext h; + + ff_hevc_dsp_init(&h, bit_depth); + check_transform_luma(&h, bit_depth); + } + report("transform_luma"); } From 1e91a3950232e391ac49a5dfdc958154a212fa4a Mon Sep 17 00:00:00 2001 From: xufuji456 <839789740@qq.com> Date: Thu, 13 Apr 2023 15:09:19 +0800 Subject: [PATCH 0632/2172] checkasm: pass context as pointer MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: xufuji456 <839789740@qq.com> Signed-off-by: Martin Storsjö --- tests/checkasm/hevc_add_res.c | 6 +++--- tests/checkasm/hevc_deblock.c | 8 ++++---- tests/checkasm/hevc_idct.c | 12 ++++++------ tests/checkasm/hevc_sao.c | 12 ++++++------ tests/checkasm/huffyuvdsp.c | 8 ++++---- tests/checkasm/llviddsp.c | 32 ++++++++++++++++---------------- 6 files changed, 39 insertions(+), 39 deletions(-) diff --git a/tests/checkasm/hevc_add_res.c b/tests/checkasm/hevc_add_res.c index f17d121939e..f35e9fccd9b 100644 --- a/tests/checkasm/hevc_add_res.c +++ b/tests/checkasm/hevc_add_res.c @@ -66,7 +66,7 @@ static void compare_add_res(int size, ptrdiff_t stride, int overflow_test, int m bench_new(dst1, res1, stride); } -static void check_add_res(HEVCDSPContext h, int bit_depth) +static void check_add_res(HEVCDSPContext *h, int bit_depth) { int i; int mask = bit_depth == 8 ? 0xFFFF : bit_depth == 10 ? 0x03FF : 0x07FF; @@ -76,7 +76,7 @@ static void check_add_res(HEVCDSPContext h, int bit_depth) int size = block_size * block_size; ptrdiff_t stride = block_size << (bit_depth > 8); - if (check_func(h.add_residual[i - 2], "hevc_add_res_%dx%d_%d", block_size, block_size, bit_depth)) { + if (check_func(h->add_residual[i - 2], "hevc_add_res_%dx%d_%d", block_size, block_size, bit_depth)) { compare_add_res(size, stride, 0, mask); // overflow test for res = -32768 compare_add_res(size, stride, 1, mask); @@ -92,7 +92,7 @@ void checkasm_check_hevc_add_res(void) HEVCDSPContext h; ff_hevc_dsp_init(&h, bit_depth); - check_add_res(h, bit_depth); + check_add_res(&h, bit_depth); } report("add_residual"); } diff --git a/tests/checkasm/hevc_deblock.c b/tests/checkasm/hevc_deblock.c index e003f98d029..5e4338af1cd 100644 --- a/tests/checkasm/hevc_deblock.c +++ b/tests/checkasm/hevc_deblock.c @@ -45,7 +45,7 @@ static const uint32_t pixel_mask[3] = { 0xffffffff, 0x03ff03ff, 0x0fff0fff }; } \ } while (0) -static void check_deblock_chroma(HEVCDSPContext h, int bit_depth) +static void check_deblock_chroma(HEVCDSPContext *h, int bit_depth) { int32_t tc[2] = { 0, 0 }; // no_p, no_q can only be { 0,0 } for the simpler assembly (non *_c @@ -57,7 +57,7 @@ static void check_deblock_chroma(HEVCDSPContext h, int bit_depth) declare_func_emms(AV_CPU_FLAG_MMX, void, uint8_t *pix, ptrdiff_t stride, int32_t *tc, uint8_t *no_p, uint8_t *no_q); - if (check_func(h.hevc_h_loop_filter_chroma, "hevc_h_loop_filter_chroma%d", bit_depth)) { + if (check_func(h->hevc_h_loop_filter_chroma, "hevc_h_loop_filter_chroma%d", bit_depth)) { for (int i = 0; i < 4; i++) { randomize_buffers(buf0, buf1, BUF_SIZE); // see betatable[] in hevc_filter.c @@ -72,7 +72,7 @@ static void check_deblock_chroma(HEVCDSPContext h, int bit_depth) bench_new(buf1 + BUF_OFFSET, BUF_STRIDE, tc, no_p, no_q); } - if (check_func(h.hevc_v_loop_filter_chroma, "hevc_v_loop_filter_chroma%d", bit_depth)) { + if (check_func(h->hevc_v_loop_filter_chroma, "hevc_v_loop_filter_chroma%d", bit_depth)) { for (int i = 0; i < 4; i++) { randomize_buffers(buf0, buf1, BUF_SIZE); // see betatable[] in hevc_filter.c @@ -95,7 +95,7 @@ void checkasm_check_hevc_deblock(void) for (bit_depth = 8; bit_depth <= 12; bit_depth += 2) { HEVCDSPContext h; ff_hevc_dsp_init(&h, bit_depth); - check_deblock_chroma(h, bit_depth); + check_deblock_chroma(&h, bit_depth); } report("chroma"); } diff --git a/tests/checkasm/hevc_idct.c b/tests/checkasm/hevc_idct.c index 446d69f931e..49cfc4801fd 100644 --- a/tests/checkasm/hevc_idct.c +++ b/tests/checkasm/hevc_idct.c @@ -36,7 +36,7 @@ } \ } while (0) -static void check_idct(HEVCDSPContext h, int bit_depth) +static void check_idct(HEVCDSPContext *h, int bit_depth) { int i; LOCAL_ALIGNED(32, int16_t, coeffs0, [32 * 32]); @@ -50,7 +50,7 @@ static void check_idct(HEVCDSPContext h, int bit_depth) randomize_buffers(coeffs0, size); memcpy(coeffs1, coeffs0, sizeof(*coeffs0) * size); - if (check_func(h.idct[i - 2], "hevc_idct_%dx%d_%d", block_size, block_size, bit_depth)) { + if (check_func(h->idct[i - 2], "hevc_idct_%dx%d_%d", block_size, block_size, bit_depth)) { call_ref(coeffs0, col_limit); call_new(coeffs1, col_limit); if (memcmp(coeffs0, coeffs1, sizeof(*coeffs0) * size)) @@ -60,7 +60,7 @@ static void check_idct(HEVCDSPContext h, int bit_depth) } } -static void check_idct_dc(HEVCDSPContext h, int bit_depth) +static void check_idct_dc(HEVCDSPContext *h, int bit_depth) { int i; LOCAL_ALIGNED(32, int16_t, coeffs0, [32 * 32]); @@ -74,7 +74,7 @@ static void check_idct_dc(HEVCDSPContext h, int bit_depth) randomize_buffers(coeffs0, size); memcpy(coeffs1, coeffs0, sizeof(*coeffs0) * size); - if (check_func(h.idct_dc[i - 2], "hevc_idct_%dx%d_dc_%d", block_size, block_size, bit_depth)) { + if (check_func(h->idct_dc[i - 2], "hevc_idct_%dx%d_dc_%d", block_size, block_size, bit_depth)) { call_ref(coeffs0); call_new(coeffs1); if (memcmp(coeffs0, coeffs1, sizeof(*coeffs0) * size)) @@ -113,7 +113,7 @@ void checkasm_check_hevc_idct(void) HEVCDSPContext h; ff_hevc_dsp_init(&h, bit_depth); - check_idct_dc(h, bit_depth); + check_idct_dc(&h, bit_depth); } report("idct_dc"); @@ -121,7 +121,7 @@ void checkasm_check_hevc_idct(void) HEVCDSPContext h; ff_hevc_dsp_init(&h, bit_depth); - check_idct(h, bit_depth); + check_idct(&h, bit_depth); } report("idct"); diff --git a/tests/checkasm/hevc_sao.c b/tests/checkasm/hevc_sao.c index 4a23010243a..cfee2ddf501 100644 --- a/tests/checkasm/hevc_sao.c +++ b/tests/checkasm/hevc_sao.c @@ -66,7 +66,7 @@ static const uint32_t sao_size[5] = {8, 16, 32, 48, 64}; } \ } while (0) -static void check_sao_band(HEVCDSPContext h, int bit_depth) +static void check_sao_band(HEVCDSPContext *h, int bit_depth) { int i; LOCAL_ALIGNED_32(uint8_t, dst0, [BUF_SIZE]); @@ -83,7 +83,7 @@ static void check_sao_band(HEVCDSPContext h, int bit_depth) declare_func_emms(AV_CPU_FLAG_MMX, void, uint8_t *dst, uint8_t *src, ptrdiff_t dst_stride, ptrdiff_t src_stride, int16_t *sao_offset_val, int sao_left_class, int width, int height); - if (check_func(h.sao_band_filter[i], "hevc_sao_band_%d_%d", block_size, bit_depth)) { + if (check_func(h->sao_band_filter[i], "hevc_sao_band_%d_%d", block_size, bit_depth)) { for (int w = prev_size + 4; w <= block_size; w += 4) { randomize_buffers(src0, src1, BUF_SIZE); @@ -103,7 +103,7 @@ static void check_sao_band(HEVCDSPContext h, int bit_depth) } } -static void check_sao_edge(HEVCDSPContext h, int bit_depth) +static void check_sao_edge(HEVCDSPContext *h, int bit_depth) { int i; LOCAL_ALIGNED_32(uint8_t, dst0, [BUF_SIZE]); @@ -127,7 +127,7 @@ static void check_sao_edge(HEVCDSPContext h, int bit_depth) memset(dst0, 0, BUF_SIZE); memset(dst1, 0, BUF_SIZE); - if (check_func(h.sao_edge_filter[i], "hevc_sao_edge_%d_%d", block_size, bit_depth)) { + if (check_func(h->sao_edge_filter[i], "hevc_sao_edge_%d_%d", block_size, bit_depth)) { call_ref(dst0, src0 + offset, stride, offset_val, eo, w, block_size); call_new(dst1, src1 + offset, stride, offset_val, eo, w, block_size); for (int j = 0; j < block_size; j++) { @@ -148,7 +148,7 @@ void checkasm_check_hevc_sao(void) HEVCDSPContext h; ff_hevc_dsp_init(&h, bit_depth); - check_sao_band(h, bit_depth); + check_sao_band(&h, bit_depth); } report("sao_band"); @@ -156,7 +156,7 @@ void checkasm_check_hevc_sao(void) HEVCDSPContext h; ff_hevc_dsp_init(&h, bit_depth); - check_sao_edge(h, bit_depth); + check_sao_edge(&h, bit_depth); } report("sao_edge"); } diff --git a/tests/checkasm/huffyuvdsp.c b/tests/checkasm/huffyuvdsp.c index 16e6bfb8084..6ba27e267f7 100644 --- a/tests/checkasm/huffyuvdsp.c +++ b/tests/checkasm/huffyuvdsp.c @@ -35,7 +35,7 @@ buf[j] = rnd() & 0xFFFF; \ } while (0) -static void check_add_int16(HuffYUVDSPContext c, unsigned mask, int width, const char * name) +static void check_add_int16(HuffYUVDSPContext *c, unsigned mask, int width, const char * name) { uint16_t *src0 = av_mallocz(width * sizeof(uint16_t)); uint16_t *src1 = av_mallocz(width * sizeof(uint16_t)); @@ -50,7 +50,7 @@ static void check_add_int16(HuffYUVDSPContext c, unsigned mask, int width, const randomize_buffers(src0, width); memcpy(src1, src0, width * sizeof(uint16_t)); - if (check_func(c.add_int16, "%s", name)) { + if (check_func(c->add_int16, "%s", name)) { call_ref(dst0, src0, mask, width); call_new(dst1, src1, mask, width); if (memcmp(dst0, dst1, width * sizeof(uint16_t))) @@ -72,10 +72,10 @@ void checkasm_check_huffyuvdsp(void) ff_huffyuvdsp_init(&c, AV_PIX_FMT_YUV422P); /*! test width not multiple of mmsize */ - check_add_int16(c, 65535, width, "add_int16_rnd_width"); + check_add_int16(&c, 65535, width, "add_int16_rnd_width"); report("add_int16_rnd_width"); /*! test always with the same size (for perf test) */ - check_add_int16(c, 65535, 16*128, "add_int16_128"); + check_add_int16(&c, 65535, 16*128, "add_int16_128"); report("add_int16_128"); } diff --git a/tests/checkasm/llviddsp.c b/tests/checkasm/llviddsp.c index d948a9832de..00ad21a7cc4 100644 --- a/tests/checkasm/llviddsp.c +++ b/tests/checkasm/llviddsp.c @@ -42,7 +42,7 @@ randomize_buffers(a0, width * sizeof(type));\ memcpy(a1, a0, width*sizeof(type));\ -static void check_add_bytes(LLVidDSPContext c, int width) +static void check_add_bytes(LLVidDSPContext *c, int width) { uint8_t *dst0 = av_mallocz(width); uint8_t *dst1 = av_mallocz(width); @@ -56,7 +56,7 @@ static void check_add_bytes(LLVidDSPContext c, int width) fail(); - if (check_func(c.add_bytes, "add_bytes")) { + if (check_func(c->add_bytes, "add_bytes")) { call_ref(dst0, src0, width); call_new(dst1, src1, width); if (memcmp(dst0, dst1, width)) @@ -70,7 +70,7 @@ static void check_add_bytes(LLVidDSPContext c, int width) av_free(dst1); } -static void check_add_median_pred(LLVidDSPContext c, int width) { +static void check_add_median_pred(LLVidDSPContext *c, int width) { int A0, A1, B0, B1; uint8_t *dst0 = av_mallocz(width); uint8_t *dst1 = av_mallocz(width); @@ -91,7 +91,7 @@ static void check_add_median_pred(LLVidDSPContext c, int width) { B1 = B0; - if (check_func(c.add_median_pred, "add_median_pred")) { + if (check_func(c->add_median_pred, "add_median_pred")) { call_ref(dst0, src0, diff0, width, &A0, &B0); call_new(dst1, src1, diff1, width, &A1, &B1); if (memcmp(dst0, dst1, width) || (A0 != A1) || (B0 != B1)) @@ -107,7 +107,7 @@ static void check_add_median_pred(LLVidDSPContext c, int width) { av_free(dst1); } -static void check_add_left_pred(LLVidDSPContext c, int width, int acc, const char * report) +static void check_add_left_pred(LLVidDSPContext *c, int width, int acc, const char * report) { int res0, res1; uint8_t *dst0 = av_mallocz(width); @@ -121,7 +121,7 @@ static void check_add_left_pred(LLVidDSPContext c, int width, int acc, const cha if (!dst0 || !dst1) fail(); - if (check_func(c.add_left_pred, "%s", report)) { + if (check_func(c->add_left_pred, "%s", report)) { res0 = call_ref(dst0, src0, width, acc); res1 = call_new(dst1, src1, width, acc); if ((res0 & 0xFF) != (res1 & 0xFF)||\ @@ -136,7 +136,7 @@ static void check_add_left_pred(LLVidDSPContext c, int width, int acc, const cha av_free(dst1); } -static void check_add_left_pred_16(LLVidDSPContext c, unsigned mask, int width, unsigned acc, const char * report) +static void check_add_left_pred_16(LLVidDSPContext *c, unsigned mask, int width, unsigned acc, const char * report) { int res0, res1; uint16_t *dst0 = av_calloc(width, sizeof(*dst0)); @@ -150,7 +150,7 @@ static void check_add_left_pred_16(LLVidDSPContext c, unsigned mask, int width, if (!dst0 || !dst1) fail(); - if (check_func(c.add_left_pred_int16, "%s", report)) { + if (check_func(c->add_left_pred_int16, "%s", report)) { res0 = call_ref(dst0, src0, mask, width, acc); res1 = call_new(dst1, src1, mask, width, acc); if ((res0 &0xFFFF) != (res1 &0xFFFF)||\ @@ -165,7 +165,7 @@ static void check_add_left_pred_16(LLVidDSPContext c, unsigned mask, int width, av_free(dst1); } -static void check_add_gradient_pred(LLVidDSPContext c, int w) { +static void check_add_gradient_pred(LLVidDSPContext *c, int w) { int src_size, stride; uint8_t *src0, *src1; declare_func(void, uint8_t *src, const ptrdiff_t stride, @@ -178,7 +178,7 @@ static void check_add_gradient_pred(LLVidDSPContext c, int w) { init_buffer(src0, src1, uint8_t, src_size); - if (check_func(c.add_gradient_pred, "add_gradient_pred")) { + if (check_func(c->add_gradient_pred, "add_gradient_pred")) { call_ref(src0 + stride + 32, stride, w); call_new(src1 + stride + 32, stride, w); if (memcmp(src0, src1, stride)||/* previous line doesn't change */ @@ -200,21 +200,21 @@ void checkasm_check_llviddsp(void) ff_llviddsp_init(&c); - check_add_bytes(c, width); + check_add_bytes(&c, width); report("add_bytes"); - check_add_median_pred(c, width); + check_add_median_pred(&c, width); report("add_median_pred"); - check_add_left_pred(c, width, 0, "add_left_pred_zero"); + check_add_left_pred(&c, width, 0, "add_left_pred_zero"); report("add_left_pred_zero"); - check_add_left_pred(c, width, accRnd, "add_left_pred_rnd_acc"); + check_add_left_pred(&c, width, accRnd, "add_left_pred_rnd_acc"); report("add_left_pred_rnd_acc"); - check_add_left_pred_16(c, 255, width, accRnd, "add_left_pred_int16"); + check_add_left_pred_16(&c, 255, width, accRnd, "add_left_pred_int16"); report("add_left_pred_int16"); - check_add_gradient_pred(c, width); + check_add_gradient_pred(&c, width); report("add_gradient_pred"); } From 45202556cb4446cd154896cdf70ad4e9d66c21e2 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Mon, 27 Mar 2023 07:37:29 +0200 Subject: [PATCH 0633/2172] fftools/ffmpeg: move OutputStream.vsync_frame_number to Encoder It is video encoding-only and does not need to be visible outside of ffmpeg_enc.c --- fftools/ffmpeg.h | 2 -- fftools/ffmpeg_enc.c | 11 +++++++---- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/fftools/ffmpeg.h b/fftools/ffmpeg.h index 8193dabb573..886124d8745 100644 --- a/fftools/ffmpeg.h +++ b/fftools/ffmpeg.h @@ -571,8 +571,6 @@ typedef struct OutputStream { InputStream *ist; AVStream *st; /* stream in the output file */ - /* number of frames emitted by the video-encoding sync code */ - int64_t vsync_frame_number; /* predicted pts of the next frame to be encoded * audio/video encoding only */ int64_t next_pts; diff --git a/fftools/ffmpeg_enc.c b/fftools/ffmpeg_enc.c index 2f1803a74c3..5266026945e 100644 --- a/fftools/ffmpeg_enc.c +++ b/fftools/ffmpeg_enc.c @@ -45,6 +45,8 @@ struct Encoder { AVFrame *last_frame; + /* number of frames emitted by the video-encoding sync code */ + int64_t vsync_frame_number; }; static uint64_t dup_warning = 1000; @@ -832,6 +834,7 @@ static void video_sync_process(OutputFile *of, OutputStream *ost, AVFrame *next_picture, double duration, int64_t *nb_frames, int64_t *nb_frames_prev) { + Encoder *e = ost->enc; double delta0, delta; double sync_ipts = adjust_frame_pts_to_encoder_tb(of, ost, next_picture); @@ -861,7 +864,7 @@ static void video_sync_process(OutputFile *of, OutputStream *ost, switch (ost->vsync_method) { case VSYNC_VSCFR: - if (ost->vsync_frame_number == 0 && delta0 >= 0.5) { + if (e->vsync_frame_number == 0 && delta0 >= 0.5) { av_log(ost, AV_LOG_DEBUG, "Not duplicating %d initial frames\n", (int)lrintf(delta0)); delta = duration; delta0 = 0; @@ -869,7 +872,7 @@ static void video_sync_process(OutputFile *of, OutputStream *ost, } case VSYNC_CFR: // FIXME set to 0.5 after we fix some dts/pts bugs like in avidec.c - if (frame_drop_threshold && delta < frame_drop_threshold && ost->vsync_frame_number) { + if (frame_drop_threshold && delta < frame_drop_threshold && e->vsync_frame_number) { *nb_frames = 0; } else if (delta < -1.1) *nb_frames = 0; @@ -998,7 +1001,7 @@ static void do_video_out(OutputFile *of, nb_frames_drop++; av_log(ost, AV_LOG_VERBOSE, "*** dropping frame %"PRId64" at ts %"PRId64"\n", - ost->vsync_frame_number, e->last_frame->pts); + e->vsync_frame_number, e->last_frame->pts); } if (nb_frames > (nb_frames_prev && ost->last_dropped) + (nb_frames > nb_frames_prev)) { if (nb_frames > dts_error_threshold * 30) { @@ -1043,7 +1046,7 @@ static void do_video_out(OutputFile *of, exit_program(1); ost->next_pts++; - ost->vsync_frame_number++; + e->vsync_frame_number++; } av_frame_unref(e->last_frame); From 710da200fc19d2e72723e0363b0d23ba8c8027a7 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Mon, 27 Mar 2023 07:37:29 +0200 Subject: [PATCH 0634/2172] fftools/ffmpeg: move OutputStream.next_pts to Encoder It is audio/video encoding-only and does not need to be visible outside of ffmpeg_enc.c --- fftools/ffmpeg.h | 3 --- fftools/ffmpeg_enc.c | 22 +++++++++++++--------- 2 files changed, 13 insertions(+), 12 deletions(-) diff --git a/fftools/ffmpeg.h b/fftools/ffmpeg.h index 886124d8745..e7e7d885773 100644 --- a/fftools/ffmpeg.h +++ b/fftools/ffmpeg.h @@ -571,9 +571,6 @@ typedef struct OutputStream { InputStream *ist; AVStream *st; /* stream in the output file */ - /* predicted pts of the next frame to be encoded - * audio/video encoding only */ - int64_t next_pts; /* dts of the last packet sent to the muxing queue, in AV_TIME_BASE_Q */ int64_t last_mux_dts; /* pts of the last frame received from the filters, in AV_TIME_BASE_Q */ diff --git a/fftools/ffmpeg_enc.c b/fftools/ffmpeg_enc.c index 5266026945e..bb11cdf42aa 100644 --- a/fftools/ffmpeg_enc.c +++ b/fftools/ffmpeg_enc.c @@ -44,6 +44,9 @@ #include "libavformat/avformat.h" struct Encoder { + /* predicted pts of the next frame to be encoded */ + int64_t next_pts; + AVFrame *last_frame; /* number of frames emitted by the video-encoding sync code */ int64_t vsync_frame_number; @@ -761,11 +764,12 @@ static int submit_encode_frame(OutputFile *of, OutputStream *ost, static void do_audio_out(OutputFile *of, OutputStream *ost, AVFrame *frame) { + Encoder *e = ost->enc; AVCodecContext *enc = ost->enc_ctx; int ret; if (frame->pts == AV_NOPTS_VALUE) - frame->pts = ost->next_pts; + frame->pts = e->next_pts; else { int64_t start_time = (of->start_time == AV_NOPTS_VALUE) ? 0 : of->start_time; frame->pts = @@ -777,7 +781,7 @@ static void do_audio_out(OutputFile *of, OutputStream *ost, if (!check_recording_time(ost, frame->pts, frame->time_base)) return; - ost->next_pts = frame->pts + frame->nb_samples; + e->next_pts = frame->pts + frame->nb_samples; ret = submit_encode_frame(of, ost, frame); if (ret < 0 && ret != AVERROR_EOF) @@ -840,7 +844,7 @@ static void video_sync_process(OutputFile *of, OutputStream *ost, double sync_ipts = adjust_frame_pts_to_encoder_tb(of, ost, next_picture); /* delta0 is the "drift" between the input frame (next_picture) and * where it would fall in the output. */ - delta0 = sync_ipts - ost->next_pts; + delta0 = sync_ipts - e->next_pts; delta = delta0 + duration; // tracks the number of times the PREVIOUS frame should be duplicated, @@ -857,7 +861,7 @@ static void video_sync_process(OutputFile *of, OutputStream *ost, av_log(ost, AV_LOG_VERBOSE, "Past duration %f too large\n", -delta0); } else av_log(ost, AV_LOG_DEBUG, "Clipping frame in rate conversion by %f\n", -delta0); - sync_ipts = ost->next_pts; + sync_ipts = e->next_pts; duration += delta0; delta0 = 0; } @@ -868,7 +872,7 @@ static void video_sync_process(OutputFile *of, OutputStream *ost, av_log(ost, AV_LOG_DEBUG, "Not duplicating %d initial frames\n", (int)lrintf(delta0)); delta = duration; delta0 = 0; - ost->next_pts = llrint(sync_ipts); + e->next_pts = llrint(sync_ipts); } case VSYNC_CFR: // FIXME set to 0.5 after we fix some dts/pts bugs like in avidec.c @@ -887,13 +891,13 @@ static void video_sync_process(OutputFile *of, OutputStream *ost, if (delta <= -0.6) *nb_frames = 0; else if (delta > 0.6) - ost->next_pts = llrint(sync_ipts); + e->next_pts = llrint(sync_ipts); next_picture->duration = duration; break; case VSYNC_DROP: case VSYNC_PASSTHROUGH: next_picture->duration = duration; - ost->next_pts = llrint(sync_ipts); + e->next_pts = llrint(sync_ipts); break; default: av_assert0(0); @@ -1031,7 +1035,7 @@ static void do_video_out(OutputFile *of, if (!in_picture) return; - in_picture->pts = ost->next_pts; + in_picture->pts = e->next_pts; if (!check_recording_time(ost, in_picture->pts, ost->enc_ctx->time_base)) return; @@ -1045,7 +1049,7 @@ static void do_video_out(OutputFile *of, else if (ret < 0) exit_program(1); - ost->next_pts++; + e->next_pts++; e->vsync_frame_number++; } From 87ae84e4afb2d137b1e229250b576226b1433a79 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Mon, 27 Mar 2023 07:37:29 +0200 Subject: [PATCH 0635/2172] fftools/ffmpeg: move OutputStream.sq_frame to Encoder It is audio/video encoding-only and does not need to be visible outside of ffmpeg_enc.c --- fftools/ffmpeg.h | 1 - fftools/ffmpeg_enc.c | 17 ++++++++++++++--- fftools/ffmpeg_mux.c | 1 - fftools/ffmpeg_mux_init.c | 4 ---- 4 files changed, 14 insertions(+), 9 deletions(-) diff --git a/fftools/ffmpeg.h b/fftools/ffmpeg.h index e7e7d885773..84418d8da57 100644 --- a/fftools/ffmpeg.h +++ b/fftools/ffmpeg.h @@ -588,7 +588,6 @@ typedef struct OutputStream { Encoder *enc; AVCodecContext *enc_ctx; AVFrame *filtered_frame; - AVFrame *sq_frame; AVPacket *pkt; int64_t last_dropped; int64_t last_nb0_frames[3]; diff --git a/fftools/ffmpeg_enc.c b/fftools/ffmpeg_enc.c index bb11cdf42aa..5c56ad0325e 100644 --- a/fftools/ffmpeg_enc.c +++ b/fftools/ffmpeg_enc.c @@ -50,6 +50,8 @@ struct Encoder { AVFrame *last_frame; /* number of frames emitted by the video-encoding sync code */ int64_t vsync_frame_number; + + AVFrame *sq_frame; }; static uint64_t dup_warning = 1000; @@ -62,6 +64,7 @@ void enc_free(Encoder **penc) return; av_frame_free(&enc->last_frame); + av_frame_free(&enc->sq_frame); av_freep(penc); } @@ -139,6 +142,7 @@ static void init_encoder_time_base(OutputStream *ost, AVRational default_time_ba int enc_open(OutputStream *ost, AVFrame *frame) { InputStream *ist = ost->ist; + Encoder *e = ost->enc; AVCodecContext *enc_ctx = ost->enc_ctx; AVCodecContext *dec_ctx = NULL; const AVCodec *enc = enc_ctx->codec; @@ -328,6 +332,12 @@ int enc_open(OutputStream *ost, AVFrame *frame) return ret; } + if (ost->sq_idx_encode >= 0) { + e->sq_frame = av_frame_alloc(); + if (!e->sq_frame) + return AVERROR(ENOMEM); + } + if (ost->enc_ctx->frame_size) { av_assert0(ost->sq_idx_encode >= 0); sq_frame_samples(output_files[ost->file_index]->sq_encode, @@ -718,16 +728,17 @@ static int encode_frame(OutputFile *of, OutputStream *ost, AVFrame *frame) static int submit_encode_frame(OutputFile *of, OutputStream *ost, AVFrame *frame) { + Encoder *e = ost->enc; int ret; if (ost->sq_idx_encode < 0) return encode_frame(of, ost, frame); if (frame) { - ret = av_frame_ref(ost->sq_frame, frame); + ret = av_frame_ref(e->sq_frame, frame); if (ret < 0) return ret; - frame = ost->sq_frame; + frame = e->sq_frame; } ret = sq_send(of->sq_encode, ost->sq_idx_encode, @@ -740,7 +751,7 @@ static int submit_encode_frame(OutputFile *of, OutputStream *ost, } while (1) { - AVFrame *enc_frame = ost->sq_frame; + AVFrame *enc_frame = e->sq_frame; ret = sq_receive(of->sq_encode, ost->sq_idx_encode, SQFRAME(enc_frame)); diff --git a/fftools/ffmpeg_mux.c b/fftools/ffmpeg_mux.c index 527567831ff..5663b8f11d3 100644 --- a/fftools/ffmpeg_mux.c +++ b/fftools/ffmpeg_mux.c @@ -663,7 +663,6 @@ static void ost_free(OutputStream **post) av_bsf_free(&ms->bsf_ctx); av_frame_free(&ost->filtered_frame); - av_frame_free(&ost->sq_frame); av_packet_free(&ost->pkt); av_dict_free(&ost->encoder_opts); diff --git a/fftools/ffmpeg_mux_init.c b/fftools/ffmpeg_mux_init.c index 6c53a8810d0..ee5829c7fed 100644 --- a/fftools/ffmpeg_mux_init.c +++ b/fftools/ffmpeg_mux_init.c @@ -1505,10 +1505,6 @@ static int setup_sync_queues(Muxer *mux, AVFormatContext *oc, int64_t buf_size_u if (ost->sq_idx_encode < 0) return ost->sq_idx_encode; - ost->sq_frame = av_frame_alloc(); - if (!ost->sq_frame) - return AVERROR(ENOMEM); - if (ms->max_frames != INT64_MAX) sq_limit_frames(of->sq_encode, ost->sq_idx_encode, ms->max_frames); } From 83da6d3f54fc85784e0ef843ee6e0c03e338722e Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Mon, 27 Mar 2023 07:37:29 +0200 Subject: [PATCH 0636/2172] fftools/ffmpeg: move OutputStream.last_nb0_frames to Encoder It is video encoding-only and does not need to be visible outside of ffmpeg_enc.c Also, rename the variable to frames_prev_hist to be consistent with the naming in do_video_out(). --- fftools/ffmpeg.h | 1 - fftools/ffmpeg_enc.c | 18 +++++++++++------- 2 files changed, 11 insertions(+), 8 deletions(-) diff --git a/fftools/ffmpeg.h b/fftools/ffmpeg.h index 84418d8da57..b45a2039ce4 100644 --- a/fftools/ffmpeg.h +++ b/fftools/ffmpeg.h @@ -590,7 +590,6 @@ typedef struct OutputStream { AVFrame *filtered_frame; AVPacket *pkt; int64_t last_dropped; - int64_t last_nb0_frames[3]; /* video only */ AVRational frame_rate; diff --git a/fftools/ffmpeg_enc.c b/fftools/ffmpeg_enc.c index 5c56ad0325e..7f6bd76f10d 100644 --- a/fftools/ffmpeg_enc.c +++ b/fftools/ffmpeg_enc.c @@ -50,6 +50,10 @@ struct Encoder { AVFrame *last_frame; /* number of frames emitted by the video-encoding sync code */ int64_t vsync_frame_number; + /* history of nb_frames_prev, i.e. the number of times the + * previous frame was duplicated by vsync code in recent + * do_video_out() calls */ + int64_t frames_prev_hist[3]; AVFrame *sq_frame; }; @@ -999,18 +1003,18 @@ static void do_video_out(OutputFile *of, if (!next_picture) { //end, flushing - nb_frames_prev = nb_frames = mid_pred(ost->last_nb0_frames[0], - ost->last_nb0_frames[1], - ost->last_nb0_frames[2]); + nb_frames_prev = nb_frames = mid_pred(e->frames_prev_hist[0], + e->frames_prev_hist[1], + e->frames_prev_hist[2]); } else { video_sync_process(of, ost, next_picture, duration, &nb_frames, &nb_frames_prev); } - memmove(ost->last_nb0_frames + 1, - ost->last_nb0_frames, - sizeof(ost->last_nb0_frames[0]) * (FF_ARRAY_ELEMS(ost->last_nb0_frames) - 1)); - ost->last_nb0_frames[0] = nb_frames_prev; + memmove(e->frames_prev_hist + 1, + e->frames_prev_hist, + sizeof(e->frames_prev_hist[0]) * (FF_ARRAY_ELEMS(e->frames_prev_hist) - 1)); + e->frames_prev_hist[0] = nb_frames_prev; if (nb_frames_prev == 0 && ost->last_dropped) { nb_frames_drop++; From fd91ac11ed5aa2a22a02a89f8a363551a368c638 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Mon, 27 Mar 2023 08:12:14 +0200 Subject: [PATCH 0637/2172] fftools/ffmpeg: move OutputStream.last_filter_pts to OutputFilter This value is associated with the filtergraph output rather than the output stream, so this is a more appropriate place for it. --- fftools/ffmpeg.c | 8 ++++---- fftools/ffmpeg.h | 5 +++-- fftools/ffmpeg_filter.c | 21 +++++++++++++++------ fftools/ffmpeg_mux_init.c | 1 - 4 files changed, 22 insertions(+), 13 deletions(-) diff --git a/fftools/ffmpeg.c b/fftools/ffmpeg.c index 750ab76693e..1f50b82794a 100644 --- a/fftools/ffmpeg.c +++ b/fftools/ffmpeg.c @@ -697,8 +697,8 @@ static int reap_filters(int flush) if (filtered_frame->pts != AV_NOPTS_VALUE) { AVRational tb = av_buffersink_get_time_base(filter); - ost->last_filter_pts = av_rescale_q(filtered_frame->pts, tb, - AV_TIME_BASE_Q); + ost->filter->last_pts = av_rescale_q(filtered_frame->pts, tb, + AV_TIME_BASE_Q); filtered_frame->time_base = tb; if (debug_ts) @@ -2391,8 +2391,8 @@ static OutputStream *choose_output(void) for (OutputStream *ost = ost_iter(NULL); ost; ost = ost_iter(ost)) { int64_t opts; - if (ost->filter && ost->last_filter_pts != AV_NOPTS_VALUE) { - opts = ost->last_filter_pts; + if (ost->filter && ost->filter->last_pts != AV_NOPTS_VALUE) { + opts = ost->filter->last_pts; } else { opts = ost->last_mux_dts == AV_NOPTS_VALUE ? INT64_MIN : ost->last_mux_dts; diff --git a/fftools/ffmpeg.h b/fftools/ffmpeg.h index b45a2039ce4..84ce0173201 100644 --- a/fftools/ffmpeg.h +++ b/fftools/ffmpeg.h @@ -314,6 +314,9 @@ typedef struct OutputFilter { const int *formats; const AVChannelLayout *ch_layouts; const int *sample_rates; + + /* pts of the last frame received from this filter, in AV_TIME_BASE_Q */ + int64_t last_pts; } OutputFilter; typedef struct FilterGraph { @@ -573,8 +576,6 @@ typedef struct OutputStream { AVStream *st; /* stream in the output file */ /* dts of the last packet sent to the muxing queue, in AV_TIME_BASE_Q */ int64_t last_mux_dts; - /* pts of the last frame received from the filters, in AV_TIME_BASE_Q */ - int64_t last_filter_pts; // timestamp from which the streamcopied streams should start, // in AV_TIME_BASE_Q; diff --git a/fftools/ffmpeg_filter.c b/fftools/ffmpeg_filter.c index c9fd65e9022..f48ae83a401 100644 --- a/fftools/ffmpeg_filter.c +++ b/fftools/ffmpeg_filter.c @@ -176,6 +176,18 @@ static void choose_channel_layouts(OutputFilter *ofilter, AVBPrint *bprint) av_bprint_chars(bprint, ':', 1); } +static OutputFilter *ofilter_alloc(FilterGraph *fg) +{ + OutputFilter *ofilter; + + ofilter = ALLOC_ARRAY_ELEM(fg->outputs, fg->nb_outputs); + ofilter->graph = fg; + ofilter->format = -1; + ofilter->last_pts = AV_NOPTS_VALUE; + + return ofilter; +} + int init_simple_filtergraph(InputStream *ist, OutputStream *ost) { FilterGraph *fg = av_mallocz(sizeof(*fg)); @@ -186,10 +198,8 @@ int init_simple_filtergraph(InputStream *ist, OutputStream *ost) report_and_exit(AVERROR(ENOMEM)); fg->index = nb_filtergraphs; - ofilter = ALLOC_ARRAY_ELEM(fg->outputs, fg->nb_outputs); - ofilter->ost = ost; - ofilter->graph = fg; - ofilter->format = -1; + ofilter = ofilter_alloc(fg); + ofilter->ost = ost; ost->filter = ofilter; @@ -502,9 +512,8 @@ int init_complex_filtergraph(FilterGraph *fg) init_input_filter(fg, cur); for (cur = outputs; cur;) { - OutputFilter *const ofilter = ALLOC_ARRAY_ELEM(fg->outputs, fg->nb_outputs); + OutputFilter *const ofilter = ofilter_alloc(fg); - ofilter->graph = fg; ofilter->out_tmp = cur; ofilter->type = avfilter_pad_get_type(cur->filter_ctx->output_pads, cur->pad_idx); diff --git a/fftools/ffmpeg_mux_init.c b/fftools/ffmpeg_mux_init.c index ee5829c7fed..3490c99c945 100644 --- a/fftools/ffmpeg_mux_init.c +++ b/fftools/ffmpeg_mux_init.c @@ -649,7 +649,6 @@ static OutputStream *new_output_stream(Muxer *mux, const OptionsContext *o, ost->ist->st->discard = ost->ist->user_set_discard; } ost->last_mux_dts = AV_NOPTS_VALUE; - ost->last_filter_pts = AV_NOPTS_VALUE; MATCH_PER_STREAM_OPT(copy_initial_nonkeyframes, i, ost->copy_initial_nonkeyframes, oc, st); From 5d4f467cc9202e09fd1197aa9fb0a447db2369f9 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Fri, 31 Mar 2023 12:55:53 +0200 Subject: [PATCH 0638/2172] fftools/ffmpeg_enc: replace abort() with av_assert0(0) This is consistent with the treatment of other unreachable paths. --- fftools/ffmpeg_enc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fftools/ffmpeg_enc.c b/fftools/ffmpeg_enc.c index 7f6bd76f10d..2aaef806f6e 100644 --- a/fftools/ffmpeg_enc.c +++ b/fftools/ffmpeg_enc.c @@ -306,7 +306,7 @@ int enc_open(OutputStream *ost, AVFrame *frame) break; default: - abort(); + av_assert0(0); break; } From f2c8dff9067ce04bf9db44dcae95f1649a623217 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Tue, 28 Mar 2023 09:31:56 +0200 Subject: [PATCH 0639/2172] fftools/ffmpeg: drop a useless goto There is no cleanup in transcode(), can return an error directly. --- fftools/ffmpeg.c | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/fftools/ffmpeg.c b/fftools/ffmpeg.c index 1f50b82794a..1cd9a8f29f6 100644 --- a/fftools/ffmpeg.c +++ b/fftools/ffmpeg.c @@ -2905,7 +2905,7 @@ static int transcode(void) ret = transcode_init(); if (ret < 0) - goto fail; + return ret; if (stdin_interaction) { av_log(NULL, AV_LOG_INFO, "Press [q] to stop, [?] for help\n"); @@ -2975,11 +2975,7 @@ static int transcode(void) hw_device_free_all(); - /* finished ! */ - ret = 0; - - fail: - return ret; + return 0; } static BenchmarkTimeStamps get_benchmark_time_stamps(void) From d99846d2f22b210ce91535a44822b93d522df829 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Tue, 28 Mar 2023 09:42:30 +0200 Subject: [PATCH 0640/2172] fftools/ffmpeg: move the hw_device_free_all() call to ffmpeg_cleanup() Frees devices on failure as well as success. --- fftools/ffmpeg.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/fftools/ffmpeg.c b/fftools/ffmpeg.c index 1cd9a8f29f6..816b6c4b083 100644 --- a/fftools/ffmpeg.c +++ b/fftools/ffmpeg.c @@ -551,6 +551,8 @@ static void ffmpeg_cleanup(int ret) av_freep(&vstats_filename); of_enc_stats_close(); + hw_device_free_all(); + av_freep(&filter_nbthreads); av_freep(&input_files); @@ -2973,8 +2975,6 @@ static int transcode(void) exit_program(1); } - hw_device_free_all(); - return 0; } From 5cf81bed881f2aad6f3fec441129d050338b90d7 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Tue, 28 Mar 2023 09:59:24 +0200 Subject: [PATCH 0641/2172] fftools/ffmpeg: eliminate the main_return_code global Properly pass muxing return codes through the call stack instead. Slightly changes behavior in case of errors: * the output IO stream is closed even if writing the trailer returns an error, which should be more correct * all files get properly closed with -xerror, even if one of them fails --- fftools/ffmpeg.c | 18 ++++++++---------- fftools/ffmpeg.h | 12 +++++++++++- fftools/ffmpeg_mux.c | 12 +++++------- 3 files changed, 24 insertions(+), 18 deletions(-) diff --git a/fftools/ffmpeg.c b/fftools/ffmpeg.c index 816b6c4b083..7431482accc 100644 --- a/fftools/ffmpeg.c +++ b/fftools/ffmpeg.c @@ -318,7 +318,6 @@ static volatile int received_sigterm = 0; static volatile int received_nb_signals = 0; static atomic_int transcode_init_done = ATOMIC_VAR_INIT(0); static volatile int ffmpeg_exited = 0; -int main_return_code = 0; static int64_t copy_ts_first_pts = AV_NOPTS_VALUE; static void @@ -2951,9 +2950,8 @@ static int transcode(void) /* write the trailer if needed */ for (i = 0; i < nb_output_files; i++) { - ret = of_write_trailer(output_files[i]); - if (ret < 0 && exit_on_error) - exit_program(1); + int err = of_write_trailer(output_files[i]); + ret = err_merge(ret, err); } /* dump report by using the first video and audio streams */ @@ -2975,7 +2973,7 @@ static int transcode(void) exit_program(1); } - return 0; + return ret; } static BenchmarkTimeStamps get_benchmark_time_stamps(void) @@ -3061,9 +3059,8 @@ int main(int argc, char **argv) } current_time = ti = get_benchmark_time_stamps(); - if (transcode() < 0) - exit_program(1); - if (do_benchmark) { + ret = transcode(); + if (ret >= 0 && do_benchmark) { int64_t utime, stime, rtime; current_time = get_benchmark_time_stamps(); utime = current_time.user_usec - ti.user_usec; @@ -3078,6 +3075,7 @@ int main(int argc, char **argv) if ((decode_error_stat[0] + decode_error_stat[1]) * max_error_rate < decode_error_stat[1]) exit_program(69); - exit_program(received_nb_signals ? 255 : main_return_code); - return main_return_code; + ret = received_nb_signals ? 255 : ret; + exit_program(ret); + return ret; } diff --git a/fftools/ffmpeg.h b/fftools/ffmpeg.h index 84ce0173201..ddfeeabf759 100644 --- a/fftools/ffmpeg.h +++ b/fftools/ffmpeg.h @@ -756,7 +756,6 @@ extern const OptionDef options[]; extern HWDevice *filter_hw_device; extern unsigned nb_output_dumped; -extern int main_return_code; extern int ignore_unknown_streams; extern int copy_unknown_streams; @@ -887,6 +886,17 @@ void close_output_stream(OutputStream *ost); int trigger_fix_sub_duration_heartbeat(OutputStream *ost, const AVPacket *pkt); void update_benchmark(const char *fmt, ...); +/** + * Merge two return codes - return one of the error codes if at least one of + * them was negative, 0 otherwise. + * Currently just picks the first one, eventually we might want to do something + * more sophisticated, like sorting them by priority. + */ +static inline int err_merge(int err0, int err1) +{ + return (err0 < 0) ? err0 : FFMIN(err1, 0); +} + #define SPECIFIER_OPT_FMT_str "%s" #define SPECIFIER_OPT_FMT_i "%i" #define SPECIFIER_OPT_FMT_i64 "%"PRId64 diff --git a/fftools/ffmpeg_mux.c b/fftools/ffmpeg_mux.c index 5663b8f11d3..c2b7993e66c 100644 --- a/fftools/ffmpeg_mux.c +++ b/fftools/ffmpeg_mux.c @@ -602,7 +602,7 @@ int of_write_trailer(OutputFile *of) { Muxer *mux = mux_from_of(of); AVFormatContext *fc = mux->fc; - int ret; + int ret, mux_result = 0; if (!mux->tq) { av_log(mux, AV_LOG_ERROR, @@ -611,14 +611,12 @@ int of_write_trailer(OutputFile *of) return AVERROR(EINVAL); } - ret = thread_stop(mux); - if (ret < 0) - main_return_code = ret; + mux_result = thread_stop(mux); ret = av_write_trailer(fc); if (ret < 0) { av_log(mux, AV_LOG_ERROR, "Error writing trailer: %s\n", av_err2str(ret)); - return ret; + mux_result = err_merge(mux_result, ret); } mux->last_filesize = filesize(fc->pb); @@ -627,11 +625,11 @@ int of_write_trailer(OutputFile *of) ret = avio_closep(&fc->pb); if (ret < 0) { av_log(mux, AV_LOG_ERROR, "Error closing file: %s\n", av_err2str(ret)); - return ret; + mux_result = err_merge(mux_result, ret); } } - return 0; + return mux_result; } static void ost_free(OutputStream **post) From 79e136f14b4f2ef9afdc5cf81fb15f0a4cec0950 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Tue, 28 Mar 2023 10:26:15 +0200 Subject: [PATCH 0642/2172] fftools/ffmpeg: factorize checking whether any output was written This is currently done in two places: * at the end of print_final_stats(), which merely prints a warning if the total size of all written packets is zero * at the end of transcode() (under a misleading historical 'close each encoder' comment), which instead checks the packet count to implement -abort_on empty_output[_stream] Consolidate both of these blocks into a single function called from of_write_trailer(), which is a more appropriate place for this. Also, return an error code rather than exit immediately, which ensures all output files are properly closed. --- fftools/ffmpeg.c | 30 ------------------------------ fftools/ffmpeg_mux.c | 43 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 43 insertions(+), 30 deletions(-) diff --git a/fftools/ffmpeg.c b/fftools/ffmpeg.c index 7431482accc..48e771cbc53 100644 --- a/fftools/ffmpeg.c +++ b/fftools/ffmpeg.c @@ -745,7 +745,6 @@ static void print_final_stats(int64_t total_size) uint64_t data_size = 0; float percent = -1.0; int i, j; - int pass1_used = 1; for (OutputStream *ost = ost_iter(NULL); ost; ost = ost_iter(ost)) { AVCodecParameters *par = ost->st->codecpar; @@ -759,10 +758,6 @@ static void print_final_stats(int64_t total_size) } extra_size += par->extradata_size; data_size += s; - if (ost->enc_ctx && - (ost->enc_ctx->flags & (AV_CODEC_FLAG_PASS1 | AV_CODEC_FLAG_PASS2)) - != AV_CODEC_FLAG_PASS1) - pass1_used = 0; } if (data_size && total_size>0 && total_size >= data_size) @@ -848,14 +843,6 @@ static void print_final_stats(int64_t total_size) av_log(NULL, AV_LOG_VERBOSE, " Total: %"PRIu64" packets (%"PRIu64" bytes) muxed\n", total_packets, total_size); } - if(video_size + data_size + audio_size + subtitle_size + extra_size == 0){ - av_log(NULL, AV_LOG_WARNING, "Output file is empty, nothing was encoded "); - if (pass1_used) { - av_log(NULL, AV_LOG_WARNING, "\n"); - } else { - av_log(NULL, AV_LOG_WARNING, "(check -ss / -t / -frames parameters if used)\n"); - } - } } static void print_report(int is_last_report, int64_t timer_start, int64_t cur_time) @@ -2902,7 +2889,6 @@ static int transcode(void) int ret, i; InputStream *ist; int64_t timer_start; - int64_t total_packets_written = 0; ret = transcode_init(); if (ret < 0) @@ -2957,22 +2943,6 @@ static int transcode(void) /* dump report by using the first video and audio streams */ print_report(1, timer_start, av_gettime_relative()); - /* close each encoder */ - for (OutputStream *ost = ost_iter(NULL); ost; ost = ost_iter(ost)) { - uint64_t packets_written; - packets_written = atomic_load(&ost->packets_written); - total_packets_written += packets_written; - if (!packets_written && (abort_on_flags & ABORT_ON_FLAG_EMPTY_OUTPUT_STREAM)) { - av_log(ost, AV_LOG_FATAL, "Empty output\n"); - exit_program(1); - } - } - - if (!total_packets_written && (abort_on_flags & ABORT_ON_FLAG_EMPTY_OUTPUT)) { - av_log(NULL, AV_LOG_FATAL, "Empty output\n"); - exit_program(1); - } - return ret; } diff --git a/fftools/ffmpeg_mux.c b/fftools/ffmpeg_mux.c index c2b7993e66c..9a91861bd46 100644 --- a/fftools/ffmpeg_mux.c +++ b/fftools/ffmpeg_mux.c @@ -598,6 +598,45 @@ int of_stream_init(OutputFile *of, OutputStream *ost) return mux_check_init(mux); } +static int check_written(OutputFile *of) +{ + int64_t total_packets_written = 0; + int pass1_used = 1; + int ret = 0; + + for (int i = 0; i < of->nb_streams; i++) { + OutputStream *ost = of->streams[i]; + uint64_t packets_written = atomic_load(&ost->packets_written); + + total_packets_written += packets_written; + + if (ost->enc_ctx && + (ost->enc_ctx->flags & (AV_CODEC_FLAG_PASS1 | AV_CODEC_FLAG_PASS2)) + != AV_CODEC_FLAG_PASS1) + pass1_used = 0; + + if (!packets_written && + (abort_on_flags & ABORT_ON_FLAG_EMPTY_OUTPUT_STREAM)) { + av_log(ost, AV_LOG_FATAL, "Empty output stream\n"); + ret = err_merge(ret, AVERROR(EINVAL)); + } + } + + if (!total_packets_written) { + int level = AV_LOG_WARNING; + + if (abort_on_flags & ABORT_ON_FLAG_EMPTY_OUTPUT) { + ret = err_merge(ret, AVERROR(EINVAL)); + level = AV_LOG_FATAL; + } + + av_log(of, level, "Output file is empty, nothing was encoded%s\n", + pass1_used ? "" : "(check -ss / -t / -frames parameters if used)"); + } + + return ret; +} + int of_write_trailer(OutputFile *of) { Muxer *mux = mux_from_of(of); @@ -629,6 +668,10 @@ int of_write_trailer(OutputFile *of) } } + // check whether anything was actually written + ret = check_written(of); + mux_result = err_merge(mux_result, ret); + return mux_result; } From 3b6b0d1afb4b19e34f2b4732137118482b5b9ec0 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Tue, 28 Mar 2023 10:43:49 +0200 Subject: [PATCH 0643/2172] fftools/ffmpeg: move printing verbose muxing stats to ffmpeg_mux This is a more appropriate place for this. --- fftools/ffmpeg.c | 34 ---------------------------------- fftools/ffmpeg_mux.c | 37 +++++++++++++++++++++++++++++++++++++ 2 files changed, 37 insertions(+), 34 deletions(-) diff --git a/fftools/ffmpeg.c b/fftools/ffmpeg.c index 48e771cbc53..e1748114b32 100644 --- a/fftools/ffmpeg.c +++ b/fftools/ffmpeg.c @@ -809,40 +809,6 @@ static void print_final_stats(int64_t total_size) av_log(NULL, AV_LOG_VERBOSE, " Total: %"PRIu64" packets (%"PRIu64" bytes) demuxed\n", total_packets, total_size); } - - for (i = 0; i < nb_output_files; i++) { - OutputFile *of = output_files[i]; - uint64_t total_packets = 0, total_size = 0; - - av_log(NULL, AV_LOG_VERBOSE, "Output file #%d (%s):\n", - i, of->url); - - for (j = 0; j < of->nb_streams; j++) { - OutputStream *ost = of->streams[j]; - enum AVMediaType type = ost->st->codecpar->codec_type; - - total_size += ost->data_size_mux; - total_packets += atomic_load(&ost->packets_written); - - av_log(NULL, AV_LOG_VERBOSE, " Output stream #%d:%d (%s): ", - i, j, av_get_media_type_string(type)); - if (ost->enc_ctx) { - av_log(NULL, AV_LOG_VERBOSE, "%"PRIu64" frames encoded", - ost->frames_encoded); - if (type == AVMEDIA_TYPE_AUDIO) - av_log(NULL, AV_LOG_VERBOSE, " (%"PRIu64" samples)", ost->samples_encoded); - av_log(NULL, AV_LOG_VERBOSE, "; "); - } - - av_log(NULL, AV_LOG_VERBOSE, "%"PRIu64" packets muxed (%"PRIu64" bytes); ", - atomic_load(&ost->packets_written), ost->data_size_mux); - - av_log(NULL, AV_LOG_VERBOSE, "\n"); - } - - av_log(NULL, AV_LOG_VERBOSE, " Total: %"PRIu64" packets (%"PRIu64" bytes) muxed\n", - total_packets, total_size); - } } static void print_report(int is_last_report, int64_t timer_start, int64_t cur_time) diff --git a/fftools/ffmpeg_mux.c b/fftools/ffmpeg_mux.c index 9a91861bd46..5acd3b9b9d9 100644 --- a/fftools/ffmpeg_mux.c +++ b/fftools/ffmpeg_mux.c @@ -637,6 +637,41 @@ static int check_written(OutputFile *of) return ret; } +static void mux_final_stats(Muxer *mux) +{ + OutputFile *of = &mux->of; + uint64_t total_packets = 0, total_size = 0; + + av_log(NULL, AV_LOG_VERBOSE, "Output file #%d (%s):\n", + of->index, of->url); + + for (int j = 0; j < of->nb_streams; j++) { + OutputStream *ost = of->streams[j]; + enum AVMediaType type = ost->st->codecpar->codec_type; + + total_size += ost->data_size_mux; + total_packets += atomic_load(&ost->packets_written); + + av_log(NULL, AV_LOG_VERBOSE, " Output stream #%d:%d (%s): ", + of->index, j, av_get_media_type_string(type)); + if (ost->enc_ctx) { + av_log(NULL, AV_LOG_VERBOSE, "%"PRIu64" frames encoded", + ost->frames_encoded); + if (type == AVMEDIA_TYPE_AUDIO) + av_log(NULL, AV_LOG_VERBOSE, " (%"PRIu64" samples)", ost->samples_encoded); + av_log(NULL, AV_LOG_VERBOSE, "; "); + } + + av_log(NULL, AV_LOG_VERBOSE, "%"PRIu64" packets muxed (%"PRIu64" bytes); ", + atomic_load(&ost->packets_written), ost->data_size_mux); + + av_log(NULL, AV_LOG_VERBOSE, "\n"); + } + + av_log(NULL, AV_LOG_VERBOSE, " Total: %"PRIu64" packets (%"PRIu64" bytes) muxed\n", + total_packets, total_size); +} + int of_write_trailer(OutputFile *of) { Muxer *mux = mux_from_of(of); @@ -668,6 +703,8 @@ int of_write_trailer(OutputFile *of) } } + mux_final_stats(mux); + // check whether anything was actually written ret = check_written(of); mux_result = err_merge(mux_result, ret); From c1764d067df1593808728c378ead9cf6fca30084 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Tue, 28 Mar 2023 10:44:34 +0200 Subject: [PATCH 0644/2172] fftools/ffmpeg_mux: reindent --- fftools/ffmpeg_mux.c | 56 ++++++++++++++++++++++---------------------- 1 file changed, 28 insertions(+), 28 deletions(-) diff --git a/fftools/ffmpeg_mux.c b/fftools/ffmpeg_mux.c index 5acd3b9b9d9..f3a3a9b7a24 100644 --- a/fftools/ffmpeg_mux.c +++ b/fftools/ffmpeg_mux.c @@ -639,37 +639,37 @@ static int check_written(OutputFile *of) static void mux_final_stats(Muxer *mux) { - OutputFile *of = &mux->of; - uint64_t total_packets = 0, total_size = 0; - - av_log(NULL, AV_LOG_VERBOSE, "Output file #%d (%s):\n", - of->index, of->url); - - for (int j = 0; j < of->nb_streams; j++) { - OutputStream *ost = of->streams[j]; - enum AVMediaType type = ost->st->codecpar->codec_type; - - total_size += ost->data_size_mux; - total_packets += atomic_load(&ost->packets_written); - - av_log(NULL, AV_LOG_VERBOSE, " Output stream #%d:%d (%s): ", - of->index, j, av_get_media_type_string(type)); - if (ost->enc_ctx) { - av_log(NULL, AV_LOG_VERBOSE, "%"PRIu64" frames encoded", - ost->frames_encoded); - if (type == AVMEDIA_TYPE_AUDIO) - av_log(NULL, AV_LOG_VERBOSE, " (%"PRIu64" samples)", ost->samples_encoded); - av_log(NULL, AV_LOG_VERBOSE, "; "); - } + OutputFile *of = &mux->of; + uint64_t total_packets = 0, total_size = 0; + + av_log(NULL, AV_LOG_VERBOSE, "Output file #%d (%s):\n", + of->index, of->url); + + for (int j = 0; j < of->nb_streams; j++) { + OutputStream *ost = of->streams[j]; + enum AVMediaType type = ost->st->codecpar->codec_type; + + total_size += ost->data_size_mux; + total_packets += atomic_load(&ost->packets_written); + + av_log(NULL, AV_LOG_VERBOSE, " Output stream #%d:%d (%s): ", + of->index, j, av_get_media_type_string(type)); + if (ost->enc_ctx) { + av_log(NULL, AV_LOG_VERBOSE, "%"PRIu64" frames encoded", + ost->frames_encoded); + if (type == AVMEDIA_TYPE_AUDIO) + av_log(NULL, AV_LOG_VERBOSE, " (%"PRIu64" samples)", ost->samples_encoded); + av_log(NULL, AV_LOG_VERBOSE, "; "); + } - av_log(NULL, AV_LOG_VERBOSE, "%"PRIu64" packets muxed (%"PRIu64" bytes); ", - atomic_load(&ost->packets_written), ost->data_size_mux); + av_log(NULL, AV_LOG_VERBOSE, "%"PRIu64" packets muxed (%"PRIu64" bytes); ", + atomic_load(&ost->packets_written), ost->data_size_mux); - av_log(NULL, AV_LOG_VERBOSE, "\n"); - } + av_log(NULL, AV_LOG_VERBOSE, "\n"); + } - av_log(NULL, AV_LOG_VERBOSE, " Total: %"PRIu64" packets (%"PRIu64" bytes) muxed\n", - total_packets, total_size); + av_log(NULL, AV_LOG_VERBOSE, " Total: %"PRIu64" packets (%"PRIu64" bytes) muxed\n", + total_packets, total_size); } int of_write_trailer(OutputFile *of) From 6b2e222a452f97669815af768f2ab014b856232e Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Tue, 28 Mar 2023 10:46:47 +0200 Subject: [PATCH 0645/2172] fftools/ffmpeg_mux: log final stats to muxer context --- fftools/ffmpeg_mux.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/fftools/ffmpeg_mux.c b/fftools/ffmpeg_mux.c index f3a3a9b7a24..441f1cd3a72 100644 --- a/fftools/ffmpeg_mux.c +++ b/fftools/ffmpeg_mux.c @@ -642,7 +642,7 @@ static void mux_final_stats(Muxer *mux) OutputFile *of = &mux->of; uint64_t total_packets = 0, total_size = 0; - av_log(NULL, AV_LOG_VERBOSE, "Output file #%d (%s):\n", + av_log(of, AV_LOG_VERBOSE, "Output file #%d (%s):\n", of->index, of->url); for (int j = 0; j < of->nb_streams; j++) { @@ -652,23 +652,23 @@ static void mux_final_stats(Muxer *mux) total_size += ost->data_size_mux; total_packets += atomic_load(&ost->packets_written); - av_log(NULL, AV_LOG_VERBOSE, " Output stream #%d:%d (%s): ", + av_log(of, AV_LOG_VERBOSE, " Output stream #%d:%d (%s): ", of->index, j, av_get_media_type_string(type)); if (ost->enc_ctx) { - av_log(NULL, AV_LOG_VERBOSE, "%"PRIu64" frames encoded", + av_log(of, AV_LOG_VERBOSE, "%"PRIu64" frames encoded", ost->frames_encoded); if (type == AVMEDIA_TYPE_AUDIO) - av_log(NULL, AV_LOG_VERBOSE, " (%"PRIu64" samples)", ost->samples_encoded); - av_log(NULL, AV_LOG_VERBOSE, "; "); + av_log(of, AV_LOG_VERBOSE, " (%"PRIu64" samples)", ost->samples_encoded); + av_log(of, AV_LOG_VERBOSE, "; "); } - av_log(NULL, AV_LOG_VERBOSE, "%"PRIu64" packets muxed (%"PRIu64" bytes); ", + av_log(of, AV_LOG_VERBOSE, "%"PRIu64" packets muxed (%"PRIu64" bytes); ", atomic_load(&ost->packets_written), ost->data_size_mux); - av_log(NULL, AV_LOG_VERBOSE, "\n"); + av_log(of, AV_LOG_VERBOSE, "\n"); } - av_log(NULL, AV_LOG_VERBOSE, " Total: %"PRIu64" packets (%"PRIu64" bytes) muxed\n", + av_log(of, AV_LOG_VERBOSE, " Total: %"PRIu64" packets (%"PRIu64" bytes) muxed\n", total_packets, total_size); } From 37b118096ae278f8123bc918a283e7ff6f0611a9 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Tue, 28 Mar 2023 11:13:32 +0200 Subject: [PATCH 0646/2172] fftools/ffmpeg: rewrite printing the final output sizes Current code in print_final_stats(), printing the final summary such as video:8851kB audio:548kB subtitle:0kB other streams:0kB global headers:20kB muxing overhead: 0.559521% was written with a single output file in mind and makes very little sense otherwise. Print this information in mux_final_stats() instead, one line per output file. Use the correct filesize, if available. --- fftools/ffmpeg.c | 37 ++----------------------------------- fftools/ffmpeg_mux.c | 36 +++++++++++++++++++++++++++++++++--- 2 files changed, 35 insertions(+), 38 deletions(-) diff --git a/fftools/ffmpeg.c b/fftools/ffmpeg.c index e1748114b32..0a2dc856291 100644 --- a/fftools/ffmpeg.c +++ b/fftools/ffmpeg.c @@ -738,43 +738,10 @@ static int reap_filters(int flush) return 0; } -static void print_final_stats(int64_t total_size) +static void print_final_stats(void) { - uint64_t video_size = 0, audio_size = 0, extra_size = 0, other_size = 0; - uint64_t subtitle_size = 0; - uint64_t data_size = 0; - float percent = -1.0; int i, j; - for (OutputStream *ost = ost_iter(NULL); ost; ost = ost_iter(ost)) { - AVCodecParameters *par = ost->st->codecpar; - const uint64_t s = ost->data_size_mux; - - switch (par->codec_type) { - case AVMEDIA_TYPE_VIDEO: video_size += s; break; - case AVMEDIA_TYPE_AUDIO: audio_size += s; break; - case AVMEDIA_TYPE_SUBTITLE: subtitle_size += s; break; - default: other_size += s; break; - } - extra_size += par->extradata_size; - data_size += s; - } - - if (data_size && total_size>0 && total_size >= data_size) - percent = 100.0 * (total_size - data_size) / data_size; - - av_log(NULL, AV_LOG_INFO, "video:%1.0fkB audio:%1.0fkB subtitle:%1.0fkB other streams:%1.0fkB global headers:%1.0fkB muxing overhead: ", - video_size / 1024.0, - audio_size / 1024.0, - subtitle_size / 1024.0, - other_size / 1024.0, - extra_size / 1024.0); - if (percent >= 0.0) - av_log(NULL, AV_LOG_INFO, "%f%%", percent); - else - av_log(NULL, AV_LOG_INFO, "unknown"); - av_log(NULL, AV_LOG_INFO, "\n"); - /* print verbose per-stream stats */ for (i = 0; i < nb_input_files; i++) { InputFile *f = input_files[i]; @@ -1005,7 +972,7 @@ static void print_report(int is_last_report, int64_t timer_start, int64_t cur_ti first_report = 0; if (is_last_report) - print_final_stats(total_size); + print_final_stats(); } int ifilter_parameters_from_codecpar(InputFilter *ifilter, AVCodecParameters *par) diff --git a/fftools/ffmpeg_mux.c b/fftools/ffmpeg_mux.c index 441f1cd3a72..01a11117a93 100644 --- a/fftools/ffmpeg_mux.c +++ b/fftools/ffmpeg_mux.c @@ -641,15 +641,30 @@ static void mux_final_stats(Muxer *mux) { OutputFile *of = &mux->of; uint64_t total_packets = 0, total_size = 0; + uint64_t video_size = 0, audio_size = 0, subtitle_size = 0, + extra_size = 0, other_size = 0; + + uint8_t overhead[16] = "unknown"; + int64_t file_size = of_filesize(of); av_log(of, AV_LOG_VERBOSE, "Output file #%d (%s):\n", of->index, of->url); for (int j = 0; j < of->nb_streams; j++) { OutputStream *ost = of->streams[j]; - enum AVMediaType type = ost->st->codecpar->codec_type; + const AVCodecParameters *par = ost->st->codecpar; + const enum AVMediaType type = par->codec_type; + const uint64_t s = ost->data_size_mux; + + switch (type) { + case AVMEDIA_TYPE_VIDEO: video_size += s; break; + case AVMEDIA_TYPE_AUDIO: audio_size += s; break; + case AVMEDIA_TYPE_SUBTITLE: subtitle_size += s; break; + default: other_size += s; break; + } - total_size += ost->data_size_mux; + extra_size += par->extradata_size; + total_size += s; total_packets += atomic_load(&ost->packets_written); av_log(of, AV_LOG_VERBOSE, " Output stream #%d:%d (%s): ", @@ -663,13 +678,28 @@ static void mux_final_stats(Muxer *mux) } av_log(of, AV_LOG_VERBOSE, "%"PRIu64" packets muxed (%"PRIu64" bytes); ", - atomic_load(&ost->packets_written), ost->data_size_mux); + atomic_load(&ost->packets_written), s); av_log(of, AV_LOG_VERBOSE, "\n"); } av_log(of, AV_LOG_VERBOSE, " Total: %"PRIu64" packets (%"PRIu64" bytes) muxed\n", total_packets, total_size); + + if (total_size && file_size > 0 && file_size >= total_size) { + snprintf(overhead, sizeof(overhead), "%f%%", + 100.0 * (file_size - total_size) / total_size); + } + + av_log(of, AV_LOG_INFO, + "video:%1.0fkB audio:%1.0fkB subtitle:%1.0fkB other streams:%1.0fkB " + "global headers:%1.0fkB muxing overhead: %s\n", + video_size / 1024.0, + audio_size / 1024.0, + subtitle_size / 1024.0, + other_size / 1024.0, + extra_size / 1024.0, + overhead); } int of_write_trailer(OutputFile *of) From 0288951174ba60b413dea720427c2b06dced9b73 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Tue, 28 Mar 2023 11:24:42 +0200 Subject: [PATCH 0647/2172] fftools/ffmpeg_mux: make data_size_mux private to ffmpeg_mux It is no longer used outside of this file. --- fftools/ffmpeg.h | 2 -- fftools/ffmpeg_mux.c | 5 +++-- fftools/ffmpeg_mux.h | 3 +++ 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/fftools/ffmpeg.h b/fftools/ffmpeg.h index ddfeeabf759..bbcbf1aa807 100644 --- a/fftools/ffmpeg.h +++ b/fftools/ffmpeg.h @@ -649,8 +649,6 @@ typedef struct OutputStream { int keep_pix_fmt; /* stats */ - // combined size of all the packets sent to the muxer - uint64_t data_size_mux; // combined size of all the packets received from the encoder uint64_t data_size_enc; // number of packets send to the muxer diff --git a/fftools/ffmpeg_mux.c b/fftools/ffmpeg_mux.c index 01a11117a93..b3169251154 100644 --- a/fftools/ffmpeg_mux.c +++ b/fftools/ffmpeg_mux.c @@ -128,7 +128,7 @@ static int write_packet(Muxer *mux, OutputStream *ost, AVPacket *pkt) } ms->last_mux_dts = pkt->dts; - ost->data_size_mux += pkt->size; + ms->data_size_mux += pkt->size; frame_num = atomic_fetch_add(&ost->packets_written, 1); pkt->stream_index = ost->index; @@ -652,9 +652,10 @@ static void mux_final_stats(Muxer *mux) for (int j = 0; j < of->nb_streams; j++) { OutputStream *ost = of->streams[j]; + MuxStream *ms = ms_from_ost(ost); const AVCodecParameters *par = ost->st->codecpar; const enum AVMediaType type = par->codec_type; - const uint64_t s = ost->data_size_mux; + const uint64_t s = ms->data_size_mux; switch (type) { case AVMEDIA_TYPE_VIDEO: video_size += s; break; diff --git a/fftools/ffmpeg_mux.h b/fftools/ffmpeg_mux.h index c76dc2e5246..3fab74b2ed9 100644 --- a/fftools/ffmpeg_mux.h +++ b/fftools/ffmpeg_mux.h @@ -63,6 +63,9 @@ typedef struct MuxStream { /* dts of the last packet sent to the muxer, in the stream timebase * used for making up missing dts values */ int64_t last_mux_dts; + + // combined size of all the packets sent to the muxer + uint64_t data_size_mux; } MuxStream; typedef struct Muxer { From 5d97ba5d9c01e478fce2159af49552e9fffde1c0 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Tue, 28 Mar 2023 11:32:53 +0200 Subject: [PATCH 0648/2172] fftools/ffmpeg: move printing verbose demuxing stats to ffmpeg_demux This is a more appropriate place for this. --- fftools/ffmpeg.c | 43 ------------------------------------------ fftools/ffmpeg_demux.c | 38 +++++++++++++++++++++++++++++++++++++ 2 files changed, 38 insertions(+), 43 deletions(-) diff --git a/fftools/ffmpeg.c b/fftools/ffmpeg.c index 0a2dc856291..02a7f20554c 100644 --- a/fftools/ffmpeg.c +++ b/fftools/ffmpeg.c @@ -738,46 +738,6 @@ static int reap_filters(int flush) return 0; } -static void print_final_stats(void) -{ - int i, j; - - /* print verbose per-stream stats */ - for (i = 0; i < nb_input_files; i++) { - InputFile *f = input_files[i]; - uint64_t total_packets = 0, total_size = 0; - - av_log(NULL, AV_LOG_VERBOSE, "Input file #%d (%s):\n", - i, f->ctx->url); - - for (j = 0; j < f->nb_streams; j++) { - InputStream *ist = f->streams[j]; - enum AVMediaType type = ist->par->codec_type; - - total_size += ist->data_size; - total_packets += ist->nb_packets; - - av_log(NULL, AV_LOG_VERBOSE, " Input stream #%d:%d (%s): ", - i, j, av_get_media_type_string(type)); - av_log(NULL, AV_LOG_VERBOSE, "%"PRIu64" packets read (%"PRIu64" bytes); ", - ist->nb_packets, ist->data_size); - - if (ist->decoding_needed) { - av_log(NULL, AV_LOG_VERBOSE, "%"PRIu64" frames decoded", - ist->frames_decoded); - if (type == AVMEDIA_TYPE_AUDIO) - av_log(NULL, AV_LOG_VERBOSE, " (%"PRIu64" samples)", ist->samples_decoded); - av_log(NULL, AV_LOG_VERBOSE, "; "); - } - - av_log(NULL, AV_LOG_VERBOSE, "\n"); - } - - av_log(NULL, AV_LOG_VERBOSE, " Total: %"PRIu64" packets (%"PRIu64" bytes) demuxed\n", - total_packets, total_size); - } -} - static void print_report(int is_last_report, int64_t timer_start, int64_t cur_time) { AVBPrint buf, buf_script; @@ -970,9 +930,6 @@ static void print_report(int is_last_report, int64_t timer_start, int64_t cur_ti } first_report = 0; - - if (is_last_report) - print_final_stats(); } int ifilter_parameters_from_codecpar(InputFilter *ifilter, AVCodecParameters *par) diff --git a/fftools/ffmpeg_demux.c b/fftools/ffmpeg_demux.c index 354d3165c9c..8fafbc3354c 100644 --- a/fftools/ffmpeg_demux.c +++ b/fftools/ffmpeg_demux.c @@ -480,6 +480,41 @@ int ifile_get_packet(InputFile *f, AVPacket **pkt) return 0; } +static void demux_final_stats(Demuxer *d) +{ + InputFile *f = &d->f; + uint64_t total_packets = 0, total_size = 0; + + av_log(NULL, AV_LOG_VERBOSE, "Input file #%d (%s):\n", + f->index, f->ctx->url); + + for (int j = 0; j < f->nb_streams; j++) { + InputStream *ist = f->streams[j]; + enum AVMediaType type = ist->par->codec_type; + + total_size += ist->data_size; + total_packets += ist->nb_packets; + + av_log(NULL, AV_LOG_VERBOSE, " Input stream #%d:%d (%s): ", + f->index, j, av_get_media_type_string(type)); + av_log(NULL, AV_LOG_VERBOSE, "%"PRIu64" packets read (%"PRIu64" bytes); ", + ist->nb_packets, ist->data_size); + + if (ist->decoding_needed) { + av_log(NULL, AV_LOG_VERBOSE, "%"PRIu64" frames decoded", + ist->frames_decoded); + if (type == AVMEDIA_TYPE_AUDIO) + av_log(NULL, AV_LOG_VERBOSE, " (%"PRIu64" samples)", ist->samples_decoded); + av_log(NULL, AV_LOG_VERBOSE, "; "); + } + + av_log(NULL, AV_LOG_VERBOSE, "\n"); + } + + av_log(NULL, AV_LOG_VERBOSE, " Total: %"PRIu64" packets (%"PRIu64" bytes) demuxed\n", + total_packets, total_size); +} + static void ist_free(InputStream **pist) { InputStream *ist = *pist; @@ -512,6 +547,9 @@ void ifile_close(InputFile **pf) thread_stop(d); + if (f->ctx) + demux_final_stats(d); + for (int i = 0; i < f->nb_streams; i++) ist_free(&f->streams[i]); av_freep(&f->streams); From 28e258a8094b9c0baf6a0fbb2414673179032e64 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Tue, 28 Mar 2023 11:33:36 +0200 Subject: [PATCH 0649/2172] fftools/ffmpeg_demux: reindent --- fftools/ffmpeg_demux.c | 52 +++++++++++++++++++++--------------------- 1 file changed, 26 insertions(+), 26 deletions(-) diff --git a/fftools/ffmpeg_demux.c b/fftools/ffmpeg_demux.c index 8fafbc3354c..a2bfd0ab95f 100644 --- a/fftools/ffmpeg_demux.c +++ b/fftools/ffmpeg_demux.c @@ -482,37 +482,37 @@ int ifile_get_packet(InputFile *f, AVPacket **pkt) static void demux_final_stats(Demuxer *d) { - InputFile *f = &d->f; - uint64_t total_packets = 0, total_size = 0; + InputFile *f = &d->f; + uint64_t total_packets = 0, total_size = 0; - av_log(NULL, AV_LOG_VERBOSE, "Input file #%d (%s):\n", - f->index, f->ctx->url); + av_log(NULL, AV_LOG_VERBOSE, "Input file #%d (%s):\n", + f->index, f->ctx->url); - for (int j = 0; j < f->nb_streams; j++) { - InputStream *ist = f->streams[j]; - enum AVMediaType type = ist->par->codec_type; - - total_size += ist->data_size; - total_packets += ist->nb_packets; - - av_log(NULL, AV_LOG_VERBOSE, " Input stream #%d:%d (%s): ", - f->index, j, av_get_media_type_string(type)); - av_log(NULL, AV_LOG_VERBOSE, "%"PRIu64" packets read (%"PRIu64" bytes); ", - ist->nb_packets, ist->data_size); - - if (ist->decoding_needed) { - av_log(NULL, AV_LOG_VERBOSE, "%"PRIu64" frames decoded", - ist->frames_decoded); - if (type == AVMEDIA_TYPE_AUDIO) - av_log(NULL, AV_LOG_VERBOSE, " (%"PRIu64" samples)", ist->samples_decoded); - av_log(NULL, AV_LOG_VERBOSE, "; "); - } + for (int j = 0; j < f->nb_streams; j++) { + InputStream *ist = f->streams[j]; + enum AVMediaType type = ist->par->codec_type; + + total_size += ist->data_size; + total_packets += ist->nb_packets; - av_log(NULL, AV_LOG_VERBOSE, "\n"); + av_log(NULL, AV_LOG_VERBOSE, " Input stream #%d:%d (%s): ", + f->index, j, av_get_media_type_string(type)); + av_log(NULL, AV_LOG_VERBOSE, "%"PRIu64" packets read (%"PRIu64" bytes); ", + ist->nb_packets, ist->data_size); + + if (ist->decoding_needed) { + av_log(NULL, AV_LOG_VERBOSE, "%"PRIu64" frames decoded", + ist->frames_decoded); + if (type == AVMEDIA_TYPE_AUDIO) + av_log(NULL, AV_LOG_VERBOSE, " (%"PRIu64" samples)", ist->samples_decoded); + av_log(NULL, AV_LOG_VERBOSE, "; "); } - av_log(NULL, AV_LOG_VERBOSE, " Total: %"PRIu64" packets (%"PRIu64" bytes) demuxed\n", - total_packets, total_size); + av_log(NULL, AV_LOG_VERBOSE, "\n"); + } + + av_log(NULL, AV_LOG_VERBOSE, " Total: %"PRIu64" packets (%"PRIu64" bytes) demuxed\n", + total_packets, total_size); } static void ist_free(InputStream **pist) From 952110f9746034224e6c31961f106a9f139652fb Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Fri, 31 Mar 2023 09:55:46 +0200 Subject: [PATCH 0650/2172] fftools/ffmpeg_demux: log final stats to demuxer context --- fftools/ffmpeg_demux.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/fftools/ffmpeg_demux.c b/fftools/ffmpeg_demux.c index a2bfd0ab95f..93eed28809d 100644 --- a/fftools/ffmpeg_demux.c +++ b/fftools/ffmpeg_demux.c @@ -485,7 +485,7 @@ static void demux_final_stats(Demuxer *d) InputFile *f = &d->f; uint64_t total_packets = 0, total_size = 0; - av_log(NULL, AV_LOG_VERBOSE, "Input file #%d (%s):\n", + av_log(f, AV_LOG_VERBOSE, "Input file #%d (%s):\n", f->index, f->ctx->url); for (int j = 0; j < f->nb_streams; j++) { @@ -495,23 +495,23 @@ static void demux_final_stats(Demuxer *d) total_size += ist->data_size; total_packets += ist->nb_packets; - av_log(NULL, AV_LOG_VERBOSE, " Input stream #%d:%d (%s): ", + av_log(f, AV_LOG_VERBOSE, " Input stream #%d:%d (%s): ", f->index, j, av_get_media_type_string(type)); - av_log(NULL, AV_LOG_VERBOSE, "%"PRIu64" packets read (%"PRIu64" bytes); ", + av_log(f, AV_LOG_VERBOSE, "%"PRIu64" packets read (%"PRIu64" bytes); ", ist->nb_packets, ist->data_size); if (ist->decoding_needed) { - av_log(NULL, AV_LOG_VERBOSE, "%"PRIu64" frames decoded", + av_log(f, AV_LOG_VERBOSE, "%"PRIu64" frames decoded", ist->frames_decoded); if (type == AVMEDIA_TYPE_AUDIO) - av_log(NULL, AV_LOG_VERBOSE, " (%"PRIu64" samples)", ist->samples_decoded); - av_log(NULL, AV_LOG_VERBOSE, "; "); + av_log(f, AV_LOG_VERBOSE, " (%"PRIu64" samples)", ist->samples_decoded); + av_log(f, AV_LOG_VERBOSE, "; "); } - av_log(NULL, AV_LOG_VERBOSE, "\n"); + av_log(f, AV_LOG_VERBOSE, "\n"); } - av_log(NULL, AV_LOG_VERBOSE, " Total: %"PRIu64" packets (%"PRIu64" bytes) demuxed\n", + av_log(f, AV_LOG_VERBOSE, " Total: %"PRIu64" packets (%"PRIu64" bytes) demuxed\n", total_packets, total_size); } From 2f24290c8edd14262ee8a674a64b1223e1cbbf41 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Tue, 28 Mar 2023 11:48:50 +0200 Subject: [PATCH 0651/2172] fftools/ffmpeg: disable and deprecate -qphist This option adds a long string of numbers to the progress line, where i-th number contains the base-2 logarithm of the number of times a frame with this QP value was seen by print_report(). There are multiple problems with this feature: * despite this existing since 2005, web search shows no indication that it was ever useful for any meaningful purpose; * the format of what is printed is entirely undocumented, one has to find it out from the source code; * QP values above 31 are silently ignored; * it only works with one video stream; * as it relies on global state, it is in conflict with ongoing architectural changes. It then seems that the nontrivial cost of maintaining this option is not worth its negligible (or possibly negative - since it pollutes the already large option space) value. Users who really need similar functionality can also implement it themselves using -vstats. --- doc/ffmpeg.texi | 2 -- fftools/ffmpeg.c | 10 ---------- fftools/ffmpeg.h | 2 +- fftools/ffmpeg_opt.c | 15 ++++++++++++--- 4 files changed, 13 insertions(+), 16 deletions(-) diff --git a/doc/ffmpeg.texi b/doc/ffmpeg.texi index d433d60ce9f..cb8aa13df27 100644 --- a/doc/ffmpeg.texi +++ b/doc/ffmpeg.texi @@ -1051,8 +1051,6 @@ Specify which version of the vstats format to use. Default is @code{2}. See the top=1/bottom=0/auto=-1 field first @item -vtag @var{fourcc/tag} (@emph{output}) Force video tag/fourcc. This is an alias for @code{-tag:v}. -@item -qphist (@emph{global}) -Show QP histogram @item -vbsf @var{bitstream_filter} Deprecated see -bsf diff --git a/fftools/ffmpeg.c b/fftools/ffmpeg.c index 02a7f20554c..74aba28a9bf 100644 --- a/fftools/ffmpeg.c +++ b/fftools/ffmpeg.c @@ -748,7 +748,6 @@ static void print_report(int is_last_report, int64_t timer_start, int64_t cur_ti int64_t pts = INT64_MIN + 1; static int64_t last_time = -1; static int first_report = 1; - static int qp_histogram[52]; int hours, mins, secs, us; const char *hours_sign; int ret; @@ -794,14 +793,6 @@ static void print_report(int is_last_report, int64_t timer_start, int64_t cur_ti ost->file_index, ost->index, q); if (is_last_report) av_bprintf(&buf, "L"); - if (qp_hist) { - int j; - int qp = lrintf(q); - if (qp >= 0 && qp < FF_ARRAY_ELEMS(qp_histogram)) - qp_histogram[qp]++; - for (j = 0; j < 32; j++) - av_bprintf(&buf, "%X", av_log2(qp_histogram[j] + 1)); - } if (enc && (enc->flags & AV_CODEC_FLAG_PSNR) && (ost->pict_type != AV_PICTURE_TYPE_NONE || is_last_report)) { @@ -2321,7 +2312,6 @@ static int check_keyboard_interaction(int64_t cur_time) } 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; if (key == 'c' || key == 'C'){ char buf[4096], target[64], command[256], arg[256] = {0}; double time; diff --git a/fftools/ffmpeg.h b/fftools/ffmpeg.h index bbcbf1aa807..80a1192ed02 100644 --- a/fftools/ffmpeg.h +++ b/fftools/ffmpeg.h @@ -54,6 +54,7 @@ #define FFMPEG_OPT_MAP_CHANNEL 1 #define FFMPEG_OPT_MAP_SYNC 1 #define FFMPEG_ROTATION_METADATA 1 +#define FFMPEG_OPT_QPHIST 1 enum VideoSyncMethod { VSYNC_AUTO = -1, @@ -738,7 +739,6 @@ extern int exit_on_error; extern int abort_on_flags; extern int print_stats; extern int64_t stats_period; -extern int qp_hist; extern int stdin_interaction; extern AVIOContext *progress_avio; extern float max_error_rate; diff --git a/fftools/ffmpeg_opt.c b/fftools/ffmpeg_opt.c index 055275d8139..aa9aa0e9b45 100644 --- a/fftools/ffmpeg_opt.c +++ b/fftools/ffmpeg_opt.c @@ -80,7 +80,6 @@ int debug_ts = 0; int exit_on_error = 0; int abort_on_flags = 0; int print_stats = -1; -int qp_hist = 0; int stdin_interaction = 1; float max_error_rate = 2.0/3; char *filter_nbthreads; @@ -1344,6 +1343,14 @@ int opt_timelimit(void *optctx, const char *opt, const char *arg) return 0; } +#if FFMPEG_OPT_QPHIST +static int opt_qphist(void *optctx, const char *opt, const char *arg) +{ + av_log(NULL, AV_LOG_WARNING, "Option -%s is deprecated and has no effect\n", opt); + return 0; +} +#endif + #define OFFSET(x) offsetof(OptionsContext, x) const OptionDef options[] = { /* main options */ @@ -1627,8 +1634,10 @@ const OptionDef options[] = { { "vtag", OPT_VIDEO | HAS_ARG | OPT_EXPERT | OPT_PERFILE | OPT_INPUT | OPT_OUTPUT, { .func_arg = opt_old2new }, "force video tag/fourcc", "fourcc/tag" }, - { "qphist", OPT_VIDEO | OPT_BOOL | OPT_EXPERT , { &qp_hist }, - "show QP histogram" }, +#if FFMPEG_OPT_QPHIST + { "qphist", OPT_VIDEO | OPT_EXPERT , { .func_arg = opt_qphist }, + "deprecated, does nothing" }, +#endif { "fps_mode", OPT_VIDEO | HAS_ARG | OPT_STRING | OPT_EXPERT | OPT_SPEC | OPT_OUTPUT, { .off = OFFSET(fps_mode) }, "set framerate mode for matching video streams; overrides vsync" }, From 5297250920bc03cc39bff586788564f60fb38af3 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Wed, 29 Mar 2023 10:34:11 +0200 Subject: [PATCH 0652/2172] fftools/ffmpeg_filter: stop setting encoder channel layout unnecessarily The channel layout is set before opening the encoder, in enc_open(). Messing with it in configure_output_audio_filter() cannot accomplish anything meaningful. --- fftools/ffmpeg_filter.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/fftools/ffmpeg_filter.c b/fftools/ffmpeg_filter.c index f48ae83a401..584f51ac3f2 100644 --- a/fftools/ffmpeg_filter.c +++ b/fftools/ffmpeg_filter.c @@ -699,7 +699,6 @@ static int configure_output_audio_filter(FilterGraph *fg, OutputFilter *ofilter, { OutputStream *ost = ofilter->ost; OutputFile *of = output_files[ost->file_index]; - AVCodecContext *codec = ost->enc_ctx; AVFilterContext *last_filter = out->filter_ctx; int pad_idx = out->pad_idx; AVBPrint args; @@ -750,9 +749,6 @@ static int configure_output_audio_filter(FilterGraph *fg, OutputFilter *ofilter, } #endif - if (codec->ch_layout.order == AV_CHANNEL_ORDER_UNSPEC) - av_channel_layout_default(&codec->ch_layout, codec->ch_layout.nb_channels); - choose_sample_fmts(ofilter, &args); choose_sample_rates(ofilter, &args); choose_channel_layouts(ofilter, &args); From 798da60e6a1c2f1fd7f243829f5e007e69e914d0 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Thu, 30 Mar 2023 11:34:21 +0200 Subject: [PATCH 0653/2172] fftools/ffmpeg_mux_init: print more meaningful error messages --- fftools/ffmpeg_mux_init.c | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/fftools/ffmpeg_mux_init.c b/fftools/ffmpeg_mux_init.c index 3490c99c945..4b6c704046a 100644 --- a/fftools/ffmpeg_mux_init.c +++ b/fftools/ffmpeg_mux_init.c @@ -2247,7 +2247,8 @@ int of_open(const OptionsContext *o, const char *filename) err = avformat_alloc_output_context2(&oc, NULL, o->format, filename); if (!oc) { - print_error(filename, err); + av_log(mux, AV_LOG_FATAL, "Error initializing the muxer for %s: %s\n", + filename, av_err2str(err)); exit_program(1); } mux->fc = oc; @@ -2334,11 +2335,12 @@ int of_open(const OptionsContext *o, const char *filename) } /* check filename in case of an image number is expected */ - if (oc->oformat->flags & AVFMT_NEEDNUMBER) { - if (!av_filename_number_test(oc->url)) { - print_error(oc->url, AVERROR(EINVAL)); - exit_program(1); - } + if (oc->oformat->flags & AVFMT_NEEDNUMBER && !av_filename_number_test(oc->url)) { + av_log(mux, AV_LOG_FATAL, + "Output filename '%s' does not contain a numeric pattern like " + "'%%d', which is required by output format '%s'.\n", + oc->url, oc->oformat->name); + exit_program(1); } if (!(oc->oformat->flags & AVFMT_NOFILE)) { @@ -2349,7 +2351,8 @@ int of_open(const OptionsContext *o, const char *filename) if ((err = avio_open2(&oc->pb, filename, AVIO_FLAG_WRITE, &oc->interrupt_callback, &mux->opts)) < 0) { - print_error(filename, err); + av_log(mux, AV_LOG_FATAL, "Error opening output %s: %s\n", + filename, av_err2str(err)); exit_program(1); } } else if (strcmp(oc->oformat->name, "image2")==0 && !av_filename_number_test(filename)) From a85e7e5dea542019feb85ab0730338c10c770746 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Fri, 31 Mar 2023 12:47:03 +0200 Subject: [PATCH 0654/2172] fftools/ffmpeg: track a list of non-lavfi outputs in InputStream Currently, output streams where an input stream is sent directly (i.e. not through lavfi) are determined by iterating over ALL the output streams and skipping the irrelevant ones. This is awkward and inefficient. --- fftools/ffmpeg.c | 21 +++++++++------------ fftools/ffmpeg.h | 10 ++++++++++ fftools/ffmpeg_demux.c | 7 +++++++ fftools/ffmpeg_mux_init.c | 3 +++ 4 files changed, 29 insertions(+), 12 deletions(-) diff --git a/fftools/ffmpeg.c b/fftools/ffmpeg.c index 74aba28a9bf..f65ff879c79 100644 --- a/fftools/ffmpeg.c +++ b/fftools/ffmpeg.c @@ -948,9 +948,6 @@ static int check_output_constraints(InputStream *ist, OutputStream *ost) { OutputFile *of = output_files[ost->file_index]; - if (ost->ist != ist) - return 0; - if (ost->finished & MUXER_FINISHED) return 0; @@ -1468,7 +1465,8 @@ static int process_subtitle(InputStream *ist, AVSubtitle *subtitle, int *got_out if (!subtitle->num_rects) goto out; - for (OutputStream *ost = ost_iter(NULL); ost; ost = ost_iter(ost)) { + for (int oidx = 0; oidx < ist->nb_outputs; oidx++) { + OutputStream *ost = ist->outputs[oidx]; if (!check_output_constraints(ist, ost) || !ost->enc_ctx || ost->enc_ctx->codec_type != AVMEDIA_TYPE_SUBTITLE) continue; @@ -1830,7 +1828,8 @@ static int process_input_packet(InputStream *ist, const AVPacket *pkt, int no_eo } else if (!ist->decoding_needed) eof_reached = 1; - for (OutputStream *ost = ost_iter(NULL); ost; ost = ost_iter(ost)) { + for (int oidx = 0; oidx < ist->nb_outputs; oidx++) { + OutputStream *ost = ist->outputs[oidx]; if (!check_output_constraints(ist, ost) || ost->enc_ctx || (!pkt && no_eof)) continue; @@ -2577,13 +2576,11 @@ static int process_input(int file_index) } /* mark all outputs that don't go through lavfi as finished */ - for (OutputStream *ost = ost_iter(NULL); ost; ost = ost_iter(ost)) { - if (ost->ist == ist && - (!ost->enc_ctx || ost->enc_ctx->codec_type == AVMEDIA_TYPE_SUBTITLE)) { - OutputFile *of = output_files[ost->file_index]; - close_output_stream(ost); - of_output_packet(of, ost->pkt, ost, 1); - } + for (int oidx = 0; oidx < ist->nb_outputs; oidx++) { + OutputStream *ost = ist->outputs[oidx]; + OutputFile *of = output_files[ost->file_index]; + close_output_stream(ost); + of_output_packet(of, ost->pkt, ost, 1); } } diff --git a/fftools/ffmpeg.h b/fftools/ffmpeg.h index 80a1192ed02..aef2bbc0df4 100644 --- a/fftools/ffmpeg.h +++ b/fftools/ffmpeg.h @@ -416,6 +416,14 @@ typedef struct InputStream { InputFilter **filters; int nb_filters; + /* + * Output targets that do not go through lavfi, i.e. subtitles or + * streamcopy. Those two cases are distinguished by the OutputStream + * having an encoder or not. + */ + struct OutputStream **outputs; + int nb_outputs; + int reinit_filters; /* hwaccel options */ @@ -867,6 +875,8 @@ void ifile_close(InputFile **f); */ int ifile_get_packet(InputFile *f, AVPacket **pkt); +void ist_output_add(InputStream *ist, OutputStream *ost); + /* iterate over all input streams in all input files; * pass NULL to start iteration */ InputStream *ist_iter(InputStream *prev); diff --git a/fftools/ffmpeg_demux.c b/fftools/ffmpeg_demux.c index 93eed28809d..f2da0826adc 100644 --- a/fftools/ffmpeg_demux.c +++ b/fftools/ffmpeg_demux.c @@ -528,6 +528,7 @@ static void ist_free(InputStream **pist) avsubtitle_free(&ist->prev_sub.subtitle); av_frame_free(&ist->sub2video.frame); av_freep(&ist->filters); + av_freep(&ist->outputs); av_freep(&ist->hwaccel_device); av_freep(&ist->dts_buffer); @@ -559,6 +560,12 @@ void ifile_close(InputFile **pf) av_freep(pf); } +void ist_output_add(InputStream *ist, OutputStream *ost) +{ + GROW_ARRAY(ist->outputs, ist->nb_outputs); + ist->outputs[ist->nb_outputs - 1] = ost; +} + static const AVCodec *choose_decoder(const OptionsContext *o, AVFormatContext *s, AVStream *st, enum HWAccelID hwaccel_id, enum AVHWDeviceType hwaccel_device_type) diff --git a/fftools/ffmpeg_mux_init.c b/fftools/ffmpeg_mux_init.c index 4b6c704046a..62e5643a042 100644 --- a/fftools/ffmpeg_mux_init.c +++ b/fftools/ffmpeg_mux_init.c @@ -647,6 +647,9 @@ static OutputStream *new_output_stream(Muxer *mux, const OptionsContext *o, if (ost->ist) { ost->ist->discard = 0; ost->ist->st->discard = ost->ist->user_set_discard; + + if (!(ost->enc && (type == AVMEDIA_TYPE_VIDEO || type == AVMEDIA_TYPE_AUDIO))) + ist_output_add(ost->ist, ost); } ost->last_mux_dts = AV_NOPTS_VALUE; From ceb0275e45d82357b94a4a0a6a515a507c1e6b2f Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Sat, 1 Apr 2023 20:13:15 +0200 Subject: [PATCH 0655/2172] fftools/ffmpeg: stop calling check_output_constraints() for streamcopy That function only contains two checks now - whether the muxer returned EOF and whether the packet timestamp is before requested output start time. The first check is unnecessary, since the packet will just be rejected by the muxer. The second check is better combined with a related check directly in do_streamcopy(). --- fftools/ffmpeg.c | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/fftools/ffmpeg.c b/fftools/ffmpeg.c index f65ff879c79..44ead4e3bcc 100644 --- a/fftools/ffmpeg.c +++ b/fftools/ffmpeg.c @@ -976,10 +976,14 @@ static void do_streamcopy(InputStream *ist, OutputStream *ost, const AVPacket *p !ost->copy_initial_nonkeyframes) return; - if (!ost->streamcopy_started && !ost->copy_prior_start) { - if (pkt->pts == AV_NOPTS_VALUE ? - ist->pts < ost->ts_copy_start : - pkt->pts < av_rescale_q(ost->ts_copy_start, AV_TIME_BASE_Q, ist->st->time_base)) + if (!ost->streamcopy_started) { + if (!ost->copy_prior_start && + (pkt->pts == AV_NOPTS_VALUE ? + ist->pts < ost->ts_copy_start : + pkt->pts < av_rescale_q(ost->ts_copy_start, AV_TIME_BASE_Q, ist->st->time_base))) + return; + + if (of->start_time != AV_NOPTS_VALUE && ist->pts < of->start_time) return; } @@ -1830,8 +1834,7 @@ static int process_input_packet(InputStream *ist, const AVPacket *pkt, int no_eo for (int oidx = 0; oidx < ist->nb_outputs; oidx++) { OutputStream *ost = ist->outputs[oidx]; - if (!check_output_constraints(ist, ost) || ost->enc_ctx || - (!pkt && no_eof)) + if (ost->enc_ctx || (!pkt && no_eof)) continue; do_streamcopy(ist, ost, pkt); From fdf29dcebb4f24c962221910546c3a15a87d11ee Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Sat, 1 Apr 2023 20:22:48 +0200 Subject: [PATCH 0656/2172] fftools/ffmpeg: inline check_output_constraints() into its only caller Which is subtitle encoding. Also, check for AVSubtitle.pts rather than InputStream.pts, since that is the more authoritative value and is guaranteed to be valid. --- fftools/ffmpeg.c | 19 +------------------ fftools/ffmpeg_enc.c | 3 +++ 2 files changed, 4 insertions(+), 18 deletions(-) diff --git a/fftools/ffmpeg.c b/fftools/ffmpeg.c index 44ead4e3bcc..95e4044dc6d 100644 --- a/fftools/ffmpeg.c +++ b/fftools/ffmpeg.c @@ -941,22 +941,6 @@ int ifilter_parameters_from_codecpar(InputFilter *ifilter, AVCodecParameters *pa return 0; } -/* - * Check whether a packet from ist should be written into ost at this time - */ -static int check_output_constraints(InputStream *ist, OutputStream *ost) -{ - OutputFile *of = output_files[ost->file_index]; - - if (ost->finished & MUXER_FINISHED) - return 0; - - if (of->start_time != AV_NOPTS_VALUE && ist->pts < of->start_time) - return 0; - - return 1; -} - static void do_streamcopy(InputStream *ist, OutputStream *ost, const AVPacket *pkt) { OutputFile *of = output_files[ost->file_index]; @@ -1471,8 +1455,7 @@ static int process_subtitle(InputStream *ist, AVSubtitle *subtitle, int *got_out for (int oidx = 0; oidx < ist->nb_outputs; oidx++) { OutputStream *ost = ist->outputs[oidx]; - if (!check_output_constraints(ist, ost) || !ost->enc_ctx - || ost->enc_ctx->codec_type != AVMEDIA_TYPE_SUBTITLE) + if (!ost->enc_ctx || ost->enc_ctx->codec_type != AVMEDIA_TYPE_SUBTITLE) continue; enc_subtitle(output_files[ost->file_index], ost, subtitle); diff --git a/fftools/ffmpeg_enc.c b/fftools/ffmpeg_enc.c index 2aaef806f6e..a0779c45ae6 100644 --- a/fftools/ffmpeg_enc.c +++ b/fftools/ffmpeg_enc.c @@ -440,6 +440,9 @@ void enc_subtitle(OutputFile *of, OutputStream *ost, AVSubtitle *sub) exit_program(1); return; } + if (ost->finished || + (of->start_time != AV_NOPTS_VALUE && sub->pts < of->start_time)) + return; enc = ost->enc_ctx; From d1cb31d7d8a59f131d6ca2b7d5b4cf4dccc795cf Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Sat, 1 Apr 2023 20:45:46 +0200 Subject: [PATCH 0657/2172] fftools/ffmpeg_demux: set the timebase on demuxed packets Simplifies tracking what timebase are the timestamps in. Will be useful in following commits. --- fftools/ffmpeg_demux.c | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/fftools/ffmpeg_demux.c b/fftools/ffmpeg_demux.c index f2da0826adc..7ff57273c9a 100644 --- a/fftools/ffmpeg_demux.c +++ b/fftools/ffmpeg_demux.c @@ -194,15 +194,17 @@ static void ts_fixup(Demuxer *d, AVPacket *pkt, int *repeat_pict) const int64_t start_time = ifile->start_time_effective; int64_t duration; + pkt->time_base = ist->st->time_base; + #define SHOW_TS_DEBUG(tag_) \ if (debug_ts) { \ av_log(ist, AV_LOG_INFO, "%s -> ist_index:%d:%d type:%s " \ "pkt_pts:%s pkt_pts_time:%s pkt_dts:%s pkt_dts_time:%s duration:%s duration_time:%s\n", \ tag_, ifile->index, pkt->stream_index, \ av_get_media_type_string(ist->st->codecpar->codec_type), \ - av_ts2str(pkt->pts), av_ts2timestr(pkt->pts, &ist->st->time_base), \ - av_ts2str(pkt->dts), av_ts2timestr(pkt->dts, &ist->st->time_base), \ - av_ts2str(pkt->duration), av_ts2timestr(pkt->duration, &ist->st->time_base)); \ + av_ts2str(pkt->pts), av_ts2timestr(pkt->pts, &pkt->time_base), \ + av_ts2str(pkt->dts), av_ts2timestr(pkt->dts, &pkt->time_base), \ + av_ts2str(pkt->duration), av_ts2timestr(pkt->duration, &pkt->time_base)); \ } SHOW_TS_DEBUG("demuxer"); @@ -211,7 +213,7 @@ static void ts_fixup(Demuxer *d, AVPacket *pkt, int *repeat_pict) ist->st->pts_wrap_bits < 64) { int64_t stime, stime2; - stime = av_rescale_q(start_time, AV_TIME_BASE_Q, ist->st->time_base); + stime = av_rescale_q(start_time, AV_TIME_BASE_Q, pkt->time_base); stime2= stime + (1ULL<st->pts_wrap_bits); ist->wrap_correction_done = 1; @@ -226,16 +228,16 @@ static void ts_fixup(Demuxer *d, AVPacket *pkt, int *repeat_pict) } if (pkt->dts != AV_NOPTS_VALUE) - pkt->dts += av_rescale_q(ifile->ts_offset, AV_TIME_BASE_Q, ist->st->time_base); + pkt->dts += av_rescale_q(ifile->ts_offset, AV_TIME_BASE_Q, pkt->time_base); if (pkt->pts != AV_NOPTS_VALUE) - pkt->pts += av_rescale_q(ifile->ts_offset, AV_TIME_BASE_Q, ist->st->time_base); + pkt->pts += av_rescale_q(ifile->ts_offset, AV_TIME_BASE_Q, pkt->time_base); if (pkt->pts != AV_NOPTS_VALUE) pkt->pts *= ds->ts_scale; if (pkt->dts != AV_NOPTS_VALUE) pkt->dts *= ds->ts_scale; - duration = av_rescale_q(d->duration, d->time_base, ist->st->time_base); + duration = av_rescale_q(d->duration, d->time_base, pkt->time_base); if (pkt->pts != AV_NOPTS_VALUE) { pkt->pts += duration; ds->max_pts = FFMAX(pkt->pts, ds->max_pts); From d867f9ab8cf50b12b978c9cb72871c53fd606d75 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Sat, 1 Apr 2023 20:52:30 +0200 Subject: [PATCH 0658/2172] fftools/ffmpeg: use AVPacket.time_base to simplify do_streamcopy() Besides making the code shorter, this also reduces the use of InputStream in this function and will allow not accessing it at all in the future. --- fftools/ffmpeg.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/fftools/ffmpeg.c b/fftools/ffmpeg.c index 95e4044dc6d..f905836af68 100644 --- a/fftools/ffmpeg.c +++ b/fftools/ffmpeg.c @@ -964,7 +964,7 @@ static void do_streamcopy(InputStream *ist, OutputStream *ost, const AVPacket *p if (!ost->copy_prior_start && (pkt->pts == AV_NOPTS_VALUE ? ist->pts < ost->ts_copy_start : - pkt->pts < av_rescale_q(ost->ts_copy_start, AV_TIME_BASE_Q, ist->st->time_base))) + pkt->pts < av_rescale_q(ost->ts_copy_start, AV_TIME_BASE_Q, pkt->time_base))) return; if (of->start_time != AV_NOPTS_VALUE && ist->pts < of->start_time) @@ -995,7 +995,7 @@ static void do_streamcopy(InputStream *ist, OutputStream *ost, const AVPacket *p opkt->time_base = ost->mux_timebase; if (pkt->pts != AV_NOPTS_VALUE) - opkt->pts = av_rescale_q(pkt->pts, ist->st->time_base, opkt->time_base) - ost_tb_start_time; + opkt->pts = av_rescale_q(pkt->pts, pkt->time_base, opkt->time_base) - ost_tb_start_time; if (pkt->dts == AV_NOPTS_VALUE) { opkt->dts = av_rescale_q(ist->dts, AV_TIME_BASE_Q, opkt->time_base); @@ -1003,16 +1003,16 @@ static void do_streamcopy(InputStream *ist, OutputStream *ost, const AVPacket *p int duration = av_get_audio_frame_duration2(ist->par, pkt->size); if(!duration) duration = ist->par->frame_size; - opkt->dts = av_rescale_delta(ist->st->time_base, pkt->dts, + opkt->dts = av_rescale_delta(pkt->time_base, pkt->dts, (AVRational){1, ist->par->sample_rate}, duration, &ist->filter_in_rescale_delta_last, opkt->time_base); /* dts will be set immediately afterwards to what pts is now */ opkt->pts = opkt->dts - ost_tb_start_time; } else - opkt->dts = av_rescale_q(pkt->dts, ist->st->time_base, opkt->time_base); + opkt->dts = av_rescale_q(pkt->dts, pkt->time_base, opkt->time_base); opkt->dts -= ost_tb_start_time; - opkt->duration = av_rescale_q(pkt->duration, ist->st->time_base, opkt->time_base); + opkt->duration = av_rescale_q(pkt->duration, pkt->time_base, opkt->time_base); { int ret = trigger_fix_sub_duration_heartbeat(ost, pkt); From 0feff04956992a535b6567a9395c8bf4083f1d5e Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Mon, 27 Mar 2023 08:26:18 +0200 Subject: [PATCH 0659/2172] fftools/ffmpeg: only set InputStream.next_pts for decoding It is write-only for streamcopy. --- fftools/ffmpeg.c | 3 +-- fftools/ffmpeg.h | 3 ++- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/fftools/ffmpeg.c b/fftools/ffmpeg.c index f905836af68..4d4083d474f 100644 --- a/fftools/ffmpeg.c +++ b/fftools/ffmpeg.c @@ -1670,7 +1670,7 @@ static int process_input_packet(InputStream *ist, const AVPacket *pkt, int no_eo if (pkt && pkt->dts != AV_NOPTS_VALUE) { ist->next_dts = ist->dts = av_rescale_q(pkt->dts, ist->st->time_base, AV_TIME_BASE_Q); if (par->codec_type != AVMEDIA_TYPE_VIDEO || !ist->decoding_needed) - ist->next_pts = ist->pts = ist->dts; + ist->pts = ist->dts; } // while we have more to decode or while the decoder did output something on EOF @@ -1811,7 +1811,6 @@ static int process_input_packet(InputStream *ist, const AVPacket *pkt, int no_eo break; } ist->pts = ist->dts; - ist->next_pts = ist->next_dts; } else if (!ist->decoding_needed) eof_reached = 1; diff --git a/fftools/ffmpeg.h b/fftools/ffmpeg.h index aef2bbc0df4..50e58583853 100644 --- a/fftools/ffmpeg.h +++ b/fftools/ffmpeg.h @@ -370,7 +370,8 @@ typedef struct InputStream { int64_t first_dts; ///< dts of the first packet read for this stream (in AV_TIME_BASE units) int64_t dts; ///< dts of the last packet read for this stream (in AV_TIME_BASE units) - int64_t next_pts; ///< synthetic pts for the next decode frame (in AV_TIME_BASE units) + /* predicted pts of the next decoded frame, in AV_TIME_BASE */ + int64_t next_pts; int64_t pts; ///< current pts of the decoded frame (in AV_TIME_BASE units) int wrap_correction_done; From 106eb58ceb5f2bc64f44435408bec24e6332a381 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Mon, 3 Apr 2023 13:47:12 +0200 Subject: [PATCH 0660/2172] fftools/ffmpeg: move checking for input -t out of do_streamcopy() This check is entirely about the properties of the input stream, while do_streamcopy() should contain code specific to a given output stream. --- fftools/ffmpeg.c | 31 ++++++++++++++++++------------- 1 file changed, 18 insertions(+), 13 deletions(-) diff --git a/fftools/ffmpeg.c b/fftools/ffmpeg.c index 4d4083d474f..5c80f3b65f1 100644 --- a/fftools/ffmpeg.c +++ b/fftools/ffmpeg.c @@ -944,7 +944,6 @@ int ifilter_parameters_from_codecpar(InputFilter *ifilter, AVCodecParameters *pa static void do_streamcopy(InputStream *ist, OutputStream *ost, const AVPacket *pkt) { OutputFile *of = output_files[ost->file_index]; - InputFile *f = input_files [ist->file_index]; int64_t start_time = (of->start_time == AV_NOPTS_VALUE) ? 0 : of->start_time; int64_t ost_tb_start_time = av_rescale_q(start_time, AV_TIME_BASE_Q, ost->mux_timebase); AVPacket *opkt = ost->pkt; @@ -977,18 +976,6 @@ static void do_streamcopy(InputStream *ist, OutputStream *ost, const AVPacket *p return; } - if (f->recording_time != INT64_MAX) { - start_time = 0; - if (copy_ts) { - start_time += f->start_time != AV_NOPTS_VALUE ? f->start_time : 0; - start_time += start_at_zero ? 0 : f->start_time_effective; - } - if (ist->pts >= f->recording_time + start_time) { - close_output_stream(ost); - return; - } - } - if (av_packet_ref(opkt, pkt) < 0) exit_program(1); @@ -1636,10 +1623,12 @@ static int send_filter_eof(InputStream *ist) /* pkt = NULL means EOF (needed to flush decoder buffers) */ static int process_input_packet(InputStream *ist, const AVPacket *pkt, int no_eof) { + InputFile *f = input_files[ist->file_index]; const AVCodecParameters *par = ist->par; int ret = 0; int repeating = 0; int eof_reached = 0; + int duration_exceeded; AVPacket *avpkt = ist->pkt; @@ -1814,11 +1803,27 @@ static int process_input_packet(InputStream *ist, const AVPacket *pkt, int no_eo } else if (!ist->decoding_needed) eof_reached = 1; + duration_exceeded = 0; + if (f->recording_time != INT64_MAX) { + int64_t start_time = 0; + if (copy_ts) { + start_time += f->start_time != AV_NOPTS_VALUE ? f->start_time : 0; + start_time += start_at_zero ? 0 : f->start_time_effective; + } + if (ist->pts >= f->recording_time + start_time) + duration_exceeded = 1; + } + for (int oidx = 0; oidx < ist->nb_outputs; oidx++) { OutputStream *ost = ist->outputs[oidx]; if (ost->enc_ctx || (!pkt && no_eof)) continue; + if (duration_exceeded) { + close_output_stream(ost); + continue; + } + do_streamcopy(ist, ost, pkt); } From d56652fdc8e1315309516be320a7250854550fa5 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Tue, 4 Apr 2023 09:25:13 +0200 Subject: [PATCH 0661/2172] fftools/ffmpeg: stop using InputStream.pts for streamcopy This field contains different values depending on whether the stream is being decoded or not. When it is, InputStream.pts is set to the timestamp of the last decoded frame. Otherwise, it is made equal to InputStream.dts. Since a given InputStream can be at the same time decoded and streamcopied to any number of output streams, this use is incorrect, as decoded frame timestamps can be delayed with respect to input packets by an arbitrary amount (e.g. depending on the thread count when frame threading is used). Replace all uses of InputStream.pts for streamcopy with InputStream.dts, which is its value when decoding is not performed. Stop setting InputStream.pts for pure streamcopy. Also, pass InputStream.dts as a parameter to do_streamcopy(), which will allow that function to be decoupled from InputStream completely in the future. --- fftools/ffmpeg.c | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/fftools/ffmpeg.c b/fftools/ffmpeg.c index 5c80f3b65f1..d14ae62e860 100644 --- a/fftools/ffmpeg.c +++ b/fftools/ffmpeg.c @@ -941,7 +941,11 @@ int ifilter_parameters_from_codecpar(InputFilter *ifilter, AVCodecParameters *pa return 0; } -static void do_streamcopy(InputStream *ist, OutputStream *ost, const AVPacket *pkt) +/** + * @param dts predicted packet dts in AV_TIME_BASE_Q + */ +static void do_streamcopy(InputStream *ist, OutputStream *ost, + const AVPacket *pkt, int64_t dts) { OutputFile *of = output_files[ost->file_index]; int64_t start_time = (of->start_time == AV_NOPTS_VALUE) ? 0 : of->start_time; @@ -962,16 +966,16 @@ static void do_streamcopy(InputStream *ist, OutputStream *ost, const AVPacket *p if (!ost->streamcopy_started) { if (!ost->copy_prior_start && (pkt->pts == AV_NOPTS_VALUE ? - ist->pts < ost->ts_copy_start : + dts < ost->ts_copy_start : pkt->pts < av_rescale_q(ost->ts_copy_start, AV_TIME_BASE_Q, pkt->time_base))) return; - if (of->start_time != AV_NOPTS_VALUE && ist->pts < of->start_time) + if (of->start_time != AV_NOPTS_VALUE && dts < of->start_time) return; } if (of->recording_time != INT64_MAX && - ist->pts >= of->recording_time + start_time) { + dts >= of->recording_time + start_time) { close_output_stream(ost); return; } @@ -985,7 +989,7 @@ static void do_streamcopy(InputStream *ist, OutputStream *ost, const AVPacket *p opkt->pts = av_rescale_q(pkt->pts, pkt->time_base, opkt->time_base) - ost_tb_start_time; if (pkt->dts == AV_NOPTS_VALUE) { - opkt->dts = av_rescale_q(ist->dts, AV_TIME_BASE_Q, opkt->time_base); + opkt->dts = av_rescale_q(dts, AV_TIME_BASE_Q, opkt->time_base); } else if (ost->st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) { int duration = av_get_audio_frame_duration2(ist->par, pkt->size); if(!duration) @@ -1639,7 +1643,6 @@ static int process_input_packet(InputStream *ist, const AVPacket *pkt, int no_eo if (pkt && pkt->pts != AV_NOPTS_VALUE && !ist->decoding_needed) { ist->first_dts = ist->dts += av_rescale_q(pkt->pts, ist->st->time_base, AV_TIME_BASE_Q); - ist->pts = ist->dts; //unused but better to set it to a value thats not totally wrong } ist->saw_first_ts = 1; } @@ -1658,7 +1661,7 @@ static int process_input_packet(InputStream *ist, const AVPacket *pkt, int no_eo if (pkt && pkt->dts != AV_NOPTS_VALUE) { ist->next_dts = ist->dts = av_rescale_q(pkt->dts, ist->st->time_base, AV_TIME_BASE_Q); - if (par->codec_type != AVMEDIA_TYPE_VIDEO || !ist->decoding_needed) + if (par->codec_type != AVMEDIA_TYPE_VIDEO) ist->pts = ist->dts; } @@ -1810,7 +1813,7 @@ static int process_input_packet(InputStream *ist, const AVPacket *pkt, int no_eo start_time += f->start_time != AV_NOPTS_VALUE ? f->start_time : 0; start_time += start_at_zero ? 0 : f->start_time_effective; } - if (ist->pts >= f->recording_time + start_time) + if (ist->dts >= f->recording_time + start_time) duration_exceeded = 1; } @@ -1824,7 +1827,7 @@ static int process_input_packet(InputStream *ist, const AVPacket *pkt, int no_eo continue; } - do_streamcopy(ist, ost, pkt); + do_streamcopy(ist, ost, pkt, ist->dts); } return !eof_reached; From ba4b73c9779c32580f8a3ba08602a5d94e0bcd7c Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Wed, 5 Apr 2023 19:09:48 +0200 Subject: [PATCH 0662/2172] lavf/rawdec: set avg_frame_rate Timestamps in two FATE H.264 conformance tests now start at 1 instead of 0, which also happens in some other H.264 tests before this commit and so is not a big issue. Conversely, timestamps in some HEVC conformance tests start from a smaller value now. Ideally this should be addressed later in a more general way. h264-conformance-frext-frext2_panasonic_b no longer requires -vsync passthrough. --- libavformat/rawdec.c | 1 + tests/fate/h264.mak | 2 +- .../h264-conformance-frext-frext2_panasonic_b | 30 +++++++++---------- .../h264-conformance-frext-frext4_panasonic_a | 20 ++++++------- .../fate/hevc-conformance-CIP_A_Panasonic_3 | 4 +-- .../fate/hevc-conformance-CIP_C_Panasonic_2 | 4 +-- .../ref/fate/hevc-conformance-SDH_A_Orange_3 | 4 +-- tests/ref/fate/hevc-small422chroma | 2 +- 8 files changed, 34 insertions(+), 33 deletions(-) diff --git a/libavformat/rawdec.c b/libavformat/rawdec.c index de804366ed1..9126a9e53b0 100644 --- a/libavformat/rawdec.c +++ b/libavformat/rawdec.c @@ -86,6 +86,7 @@ int ff_raw_video_read_header(AVFormatContext *s) st->codecpar->codec_id = s->iformat->raw_codec_id; sti->need_parsing = AVSTREAM_PARSE_FULL_RAW; + st->avg_frame_rate = s1->framerate; sti->avctx->framerate = s1->framerate; avpriv_set_pts_info(st, 64, 1, 1200000); diff --git a/tests/fate/h264.mak b/tests/fate/h264.mak index b883f3a3ffa..c8ed23955ac 100644 --- a/tests/fate/h264.mak +++ b/tests/fate/h264.mak @@ -346,7 +346,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 passthrough +fate-h264-conformance-frext-frext2_panasonic_b: CMD = framecrc -i $(TARGET_SAMPLES)/h264-conformance/FRext/FRExt2_Panasonic.avc 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 diff --git a/tests/ref/fate/h264-conformance-frext-frext2_panasonic_b b/tests/ref/fate/h264-conformance-frext-frext2_panasonic_b index 76e4d26cf8f..d4435700828 100644 --- a/tests/ref/fate/h264-conformance-frext-frext2_panasonic_b +++ b/tests/ref/fate/h264-conformance-frext-frext2_panasonic_b @@ -3,18 +3,18 @@ #codec_id 0: rawvideo #dimensions 0: 352x288 #sar 0: 0/1 -0, 0, 0, 1, 152064, 0x0147a2a9 -0, 1, 1, 1, 152064, 0xe2365351 -0, 2, 2, 1, 152064, 0xb5f9daee -0, 3, 3, 1, 152064, 0xd60818b2 -0, 4, 4, 1, 152064, 0x21b528e5 -0, 5, 5, 1, 152064, 0x9c9dda18 -0, 6, 6, 1, 152064, 0x387fe7de -0, 7, 7, 1, 152064, 0x8f0c5a1e -0, 8, 8, 1, 152064, 0x02409694 -0, 9, 9, 1, 152064, 0x2b36a7a7 -0, 10, 10, 1, 152064, 0x3c6d3863 -0, 11, 11, 1, 152064, 0xaa7835e1 -0, 12, 12, 1, 152064, 0x6d105fe7 -0, 13, 13, 1, 152064, 0x9a348732 -0, 14, 14, 1, 152064, 0x96a3af13 +0, 1, 1, 1, 152064, 0x0147a2a9 +0, 2, 2, 1, 152064, 0xe2365351 +0, 3, 3, 1, 152064, 0xb5f9daee +0, 4, 4, 1, 152064, 0xd60818b2 +0, 5, 5, 1, 152064, 0x21b528e5 +0, 6, 6, 1, 152064, 0x9c9dda18 +0, 7, 7, 1, 152064, 0x387fe7de +0, 8, 8, 1, 152064, 0x8f0c5a1e +0, 9, 9, 1, 152064, 0x02409694 +0, 10, 10, 1, 152064, 0x2b36a7a7 +0, 11, 11, 1, 152064, 0x3c6d3863 +0, 12, 12, 1, 152064, 0xaa7835e1 +0, 13, 13, 1, 152064, 0x6d105fe7 +0, 14, 14, 1, 152064, 0x9a348732 +0, 15, 15, 1, 152064, 0x96a3af13 diff --git a/tests/ref/fate/h264-conformance-frext-frext4_panasonic_a b/tests/ref/fate/h264-conformance-frext-frext4_panasonic_a index 5640228a263..1f678d1122c 100644 --- a/tests/ref/fate/h264-conformance-frext-frext4_panasonic_a +++ b/tests/ref/fate/h264-conformance-frext-frext4_panasonic_a @@ -3,13 +3,13 @@ #codec_id 0: rawvideo #dimensions 0: 352x288 #sar 0: 0/1 -0, 0, 0, 1, 152064, 0xd604d440 -0, 1, 1, 1, 152064, 0x08ef262c -0, 2, 2, 1, 152064, 0x992fca8e -0, 3, 3, 1, 152064, 0x5a02ee15 -0, 4, 4, 1, 152064, 0xf15d5c66 -0, 5, 5, 1, 152064, 0x360dda12 -0, 6, 6, 1, 152064, 0x18b54985 -0, 7, 7, 1, 152064, 0xf12b6cde -0, 8, 8, 1, 152064, 0x3b2e63f7 -0, 9, 9, 1, 152064, 0x140abcfd +0, 1, 1, 1, 152064, 0xd604d440 +0, 2, 2, 1, 152064, 0x08ef262c +0, 3, 3, 1, 152064, 0x992fca8e +0, 4, 4, 1, 152064, 0x5a02ee15 +0, 5, 5, 1, 152064, 0xf15d5c66 +0, 6, 6, 1, 152064, 0x360dda12 +0, 7, 7, 1, 152064, 0x18b54985 +0, 8, 8, 1, 152064, 0xf12b6cde +0, 9, 9, 1, 152064, 0x3b2e63f7 +0, 10, 10, 1, 152064, 0x140abcfd diff --git a/tests/ref/fate/hevc-conformance-CIP_A_Panasonic_3 b/tests/ref/fate/hevc-conformance-CIP_A_Panasonic_3 index ebe0f676d27..3adef2f366e 100644 --- a/tests/ref/fate/hevc-conformance-CIP_A_Panasonic_3 +++ b/tests/ref/fate/hevc-conformance-CIP_A_Panasonic_3 @@ -3,5 +3,5 @@ #codec_id 0: rawvideo #dimensions 0: 416x240 #sar 0: 0/1 -0, 2, 2, 1, 149760, 0x6e1f16d0 -0, 3, 3, 1, 149760, 0x5be5bde9 +0, 0, 0, 1, 149760, 0x6e1f16d0 +0, 1, 1, 1, 149760, 0x5be5bde9 diff --git a/tests/ref/fate/hevc-conformance-CIP_C_Panasonic_2 b/tests/ref/fate/hevc-conformance-CIP_C_Panasonic_2 index 74f7f8cd74b..8e6c681cfef 100644 --- a/tests/ref/fate/hevc-conformance-CIP_C_Panasonic_2 +++ b/tests/ref/fate/hevc-conformance-CIP_C_Panasonic_2 @@ -3,5 +3,5 @@ #codec_id 0: rawvideo #dimensions 0: 416x240 #sar 0: 0/1 -0, 2, 2, 1, 149760, 0xcd1019b2 -0, 3, 3, 1, 149760, 0xeb39efeb +0, 0, 0, 1, 149760, 0xcd1019b2 +0, 1, 1, 1, 149760, 0xeb39efeb diff --git a/tests/ref/fate/hevc-conformance-SDH_A_Orange_3 b/tests/ref/fate/hevc-conformance-SDH_A_Orange_3 index e5bc4f8121b..f3ef192c6a6 100644 --- a/tests/ref/fate/hevc-conformance-SDH_A_Orange_3 +++ b/tests/ref/fate/hevc-conformance-SDH_A_Orange_3 @@ -3,5 +3,5 @@ #codec_id 0: rawvideo #dimensions 0: 1920x1080 #sar 0: 0/1 -0, 2, 2, 1, 3110400, 0x0117aa5d -0, 3, 3, 1, 3110400, 0xa737bc56 +0, 0, 0, 1, 3110400, 0x0117aa5d +0, 1, 1, 1, 3110400, 0xa737bc56 diff --git a/tests/ref/fate/hevc-small422chroma b/tests/ref/fate/hevc-small422chroma index 954829a0ab6..de0ea46c31a 100644 --- a/tests/ref/fate/hevc-small422chroma +++ b/tests/ref/fate/hevc-small422chroma @@ -3,4 +3,4 @@ #codec_id 0: rawvideo #dimensions 0: 3840x2160 #sar 0: 1/1 -0, 11, 11, 1, 33177600, 0x53015e18 +0, 7, 7, 1, 33177600, 0x53015e18 From 7b827a029338ef8af689e84a352825797b286e26 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Wed, 5 Apr 2023 16:35:22 +0200 Subject: [PATCH 0663/2172] lavf/demux: treat streams with AVSTREAM_PARSE_FULL_RAW as having timestamps In this case the timestamps are set by the parser. Cf. a6b3471c44fd981d3b33ea9050f78a0bc9494c5e Required by the following commit. --- libavformat/demux.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavformat/demux.c b/libavformat/demux.c index b19ab86d08d..06de71cd6e3 100644 --- a/libavformat/demux.c +++ b/libavformat/demux.c @@ -2569,7 +2569,7 @@ int avformat_find_stream_info(AVFormatContext *ic, AVDictionary **options) extract_extradata_check(st)) break; if (sti->first_dts == AV_NOPTS_VALUE && - !(ic->iformat->flags & AVFMT_NOTIMESTAMPS) && + (!(ic->iformat->flags & AVFMT_NOTIMESTAMPS) || sti->need_parsing == AVSTREAM_PARSE_FULL_RAW) && sti->codec_info_nb_frames < ((st->disposition & AV_DISPOSITION_ATTACHED_PIC) ? 1 : ic->max_ts_probe) && (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO || st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO)) From be3b1e27e5cb7a390ab1bfa2265d0b0e2f0bcbce Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Wed, 5 Apr 2023 16:43:03 +0200 Subject: [PATCH 0664/2172] lavf/rawdec: mark raw demuxers as having no timestamps Changes the result of the h264_redundant_pps-mov test, where the output timebase is now 1001/24000 instead of 1/24. This is more correct, as the source file actually is 23.98fps. --- libavformat/rawdec.h | 2 +- tests/ref/fate/h264_redundant_pps-mov | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/libavformat/rawdec.h b/libavformat/rawdec.h index f843fe5a2e0..91d0b659afd 100644 --- a/libavformat/rawdec.h +++ b/libavformat/rawdec.h @@ -57,7 +57,7 @@ const AVInputFormat ff_ ## shortname ## _demuxer = {\ .read_header = ff_raw_video_read_header,\ .read_packet = ff_raw_read_partial_packet,\ .extensions = ext,\ - .flags = flag,\ + .flags = flag | AVFMT_NOTIMESTAMPS,\ .raw_codec_id = id,\ .priv_data_size = sizeof(FFRawVideoDemuxerContext),\ .priv_class = &ff_rawvideo_demuxer_class,\ diff --git a/tests/ref/fate/h264_redundant_pps-mov b/tests/ref/fate/h264_redundant_pps-mov index 7cab0e0b29b..a8a1fae933b 100644 --- a/tests/ref/fate/h264_redundant_pps-mov +++ b/tests/ref/fate/h264_redundant_pps-mov @@ -1,6 +1,6 @@ ac2e8f528dae4e4d610fa3517d2c94fb *tests/data/fate/h264_redundant_pps-mov.h264 187284 tests/data/fate/h264_redundant_pps-mov.h264 -#tb 0: 1/24 +#tb 0: 1001/24000 #media_type 0: video #codec_id 0: rawvideo #dimensions 0: 640x360 From 95fa4edbd668971df7c815610b1c263793043e27 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Fri, 7 Apr 2023 11:03:37 +0200 Subject: [PATCH 0665/2172] fftools/ffmpeg: improve decoder -ts_debug line * log to the input stream log context * drop the now-duplicate index/type information * show pkt_dts and frame duration --- fftools/ffmpeg.c | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/fftools/ffmpeg.c b/fftools/ffmpeg.c index d14ae62e860..379f6c73cdc 100644 --- a/fftools/ffmpeg.c +++ b/fftools/ffmpeg.c @@ -1379,12 +1379,20 @@ static int decode_video(InputStream *ist, AVPacket *pkt, int *got_output, int64_ } if (debug_ts) { - av_log(NULL, AV_LOG_INFO, "decoder -> ist_index:%d type:video " - "frame_pts:%s frame_pts_time:%s best_effort_ts:%"PRId64" best_effort_ts_time:%s keyframe:%d frame_type:%d time_base:%d/%d\n", - ist->st->index, av_ts2str(decoded_frame->pts), + av_log(ist, AV_LOG_INFO, + "decoder -> pts:%s pts_time:%s " + "pkt_dts:%s pkt_dts_time:%s " + "best_effort_ts:%"PRId64" best_effort_ts_time:%s " + "duration:%s duration_time:%s " + "keyframe:%d frame_type:%d time_base:%d/%d\n", + av_ts2str(decoded_frame->pts), av_ts2timestr(decoded_frame->pts, &ist->st->time_base), + av_ts2str(decoded_frame->pkt_dts), + av_ts2timestr(decoded_frame->pkt_dts, &ist->st->time_base), best_effort_timestamp, av_ts2timestr(best_effort_timestamp, &ist->st->time_base), + av_ts2str(decoded_frame->duration), + av_ts2timestr(decoded_frame->duration, &ist->st->time_base), decoded_frame->key_frame, decoded_frame->pict_type, ist->st->time_base.num, ist->st->time_base.den); } From 380db569287ba99d903b7629f209b9adc7fd2723 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Sat, 8 Apr 2023 16:22:41 +0200 Subject: [PATCH 0666/2172] fftools/ffmpeg: use InputStream.pts as last resort for decoded frame pts --- fftools/ffmpeg.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/fftools/ffmpeg.c b/fftools/ffmpeg.c index 379f6c73cdc..741448c29a0 100644 --- a/fftools/ffmpeg.c +++ b/fftools/ffmpeg.c @@ -1371,6 +1371,9 @@ static int decode_video(InputStream *ist, AVPacket *pkt, int *got_output, int64_ ist->nb_dts_buffer--; } + if (best_effort_timestamp == AV_NOPTS_VALUE) + best_effort_timestamp = av_rescale_q(ist->pts, AV_TIME_BASE_Q, ist->st->time_base); + if(best_effort_timestamp != AV_NOPTS_VALUE) { int64_t ts = av_rescale_q(decoded_frame->pts = best_effort_timestamp, ist->st->time_base, AV_TIME_BASE_Q); From 5d407cb2d71176240487171bb0e803c3d2e36f15 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Sun, 9 Apr 2023 09:55:55 +0200 Subject: [PATCH 0667/2172] fftools/ffmpeg: change video decoding timestamp generation When no timestamps are available from the container, the video decoding code will currently use fake dts values - generated in process_input_packet() based on a combination of information from the decoder and the parser (obtained via the demuxer) - to generate timestamps during decoder flushing. This is fragile, hard to follow, and unnecessarily convoluted, since more reliable information can be obtained directly from post-decoding values. The new code keeps track of the last decoded frame pts and estimates its duration based on a number of heuristics. Timestamps generated when both pts and pkt_dts are missing are then simple pts+duration of the last frame. The heuristics are somewhat complicated by the fact that lavf insists on making up packet timestamps based on its highly incomplete information. That should be removed in the future, allowing to further simplify this code. The results of the following tests change: * h264-3386 now requires -fps_mode passthrough to avoid dropping frames at the end; this is a pathology of the interaction of the new and old code, and the fact that the sample switches from field to frame coding in the last packet, and will be fixed in following commits * hevc-conformance-DELTAQP_A_BRCM_4 stops inventing an arbitrary timestamp gap at the end * hevc-small422chroma - the single frame output by this test now has a timestamp of 0, rather than an arbitrary 7 --- fftools/ffmpeg.c | 79 ++++++++++++++----- fftools/ffmpeg.h | 9 ++- fftools/ffmpeg_demux.c | 3 +- tests/fate/h264.mak | 2 +- tests/ref/fate/h264-3386 | 6 +- .../fate/hevc-conformance-DELTAQP_A_BRCM_4 | 2 +- tests/ref/fate/hevc-small422chroma | 2 +- 7 files changed, 75 insertions(+), 28 deletions(-) diff --git a/fftools/ffmpeg.c b/fftools/ffmpeg.c index 741448c29a0..757d837d5fc 100644 --- a/fftools/ffmpeg.c +++ b/fftools/ffmpeg.c @@ -1275,11 +1275,63 @@ static int decode_audio(InputStream *ist, AVPacket *pkt, int *got_output, return err < 0 ? err : ret; } +static int64_t video_duration_estimate(const InputStream *ist, const AVFrame *frame) +{ + const InputFile *ifile = input_files[ist->file_index]; + const int container_nots = !!(ifile->ctx->iformat->flags & AVFMT_NOTIMESTAMPS); + int64_t codec_duration = 0; + + // XXX lavf currently makes up frame durations when they are not provided by + // the container. As there is no way to reliably distinguish real container + // durations from the fake made-up ones, we use heuristics based on whether + // the container has timestamps. Eventually lavf should stop making up + // durations, then this should be simplified. + + // prefer frame duration for containers with timestamps + if (frame->duration > 0 && !container_nots) + return frame->duration; + + if (ist->dec_ctx->framerate.den && ist->dec_ctx->framerate.num) { + int ticks = frame->repeat_pict >= 0 ? + frame->repeat_pict + 1 : + ist->dec_ctx->ticks_per_frame; + codec_duration = av_rescale_q(ticks, av_inv_q(ist->dec_ctx->framerate), + ist->st->time_base); + } + + // prefer codec-layer duration for containers without timestamps + if (codec_duration > 0 && container_nots) + return codec_duration; + + // when timestamps are available, repeat last frame's actual duration + // (i.e. pts difference between this and last frame) + if (frame->pts != AV_NOPTS_VALUE && ist->last_frame_pts != AV_NOPTS_VALUE && + frame->pts > ist->last_frame_pts) + return frame->pts - ist->last_frame_pts; + + // try frame/codec duration + if (frame->duration > 0) + return frame->duration; + if (codec_duration > 0) + return codec_duration; + + // try average framerate + if (ist->st->avg_frame_rate.num && ist->st->avg_frame_rate.den) { + int64_t d = av_rescale_q(1, av_inv_q(ist->st->avg_frame_rate), + ist->st->time_base); + if (d > 0) + return d; + } + + // last resort is last frame's estimated duration, and 1 + return FFMAX(ist->last_frame_duration_est, 1); +} + static int decode_video(InputStream *ist, AVPacket *pkt, int *got_output, int64_t *duration_pts, int eof, int *decode_failed) { AVFrame *decoded_frame = ist->decoded_frame; - int i, ret = 0, err = 0; + int ret = 0, err = 0; int64_t best_effort_timestamp; int64_t dts = AV_NOPTS_VALUE; @@ -1295,16 +1347,6 @@ static int decode_video(InputStream *ist, AVPacket *pkt, int *got_output, int64_ pkt->dts = dts; // ffmpeg.c probably shouldn't do this } - // The old code used to set dts on the drain packet, which does not work - // with the new API anymore. - if (eof) { - void *new = av_realloc_array(ist->dts_buffer, ist->nb_dts_buffer + 1, sizeof(ist->dts_buffer[0])); - if (!new) - return AVERROR(ENOMEM); - ist->dts_buffer = new; - ist->dts_buffer[ist->nb_dts_buffer++] = dts; - } - update_benchmark(NULL); ret = decode(ist, ist->dec_ctx, decoded_frame, got_output, pkt); update_benchmark("decode_video %d.%d", ist->file_index, ist->st->index); @@ -1363,13 +1405,10 @@ static int decode_video(InputStream *ist, AVPacket *pkt, int *got_output, int64_ if (ist->framerate.num) best_effort_timestamp = ist->cfr_next_pts++; - if (eof && best_effort_timestamp == AV_NOPTS_VALUE && ist->nb_dts_buffer > 0) { - best_effort_timestamp = ist->dts_buffer[0]; - - for (i = 0; i < ist->nb_dts_buffer - 1; i++) - ist->dts_buffer[i] = ist->dts_buffer[i + 1]; - ist->nb_dts_buffer--; - } + // no timestamp available - extrapolate from previous frame duration + if (best_effort_timestamp == AV_NOPTS_VALUE && + ist->last_frame_pts != AV_NOPTS_VALUE) + best_effort_timestamp = ist->last_frame_pts + ist->last_frame_duration_est; if (best_effort_timestamp == AV_NOPTS_VALUE) best_effort_timestamp = av_rescale_q(ist->pts, AV_TIME_BASE_Q, ist->st->time_base); @@ -1381,6 +1420,10 @@ static int decode_video(InputStream *ist, AVPacket *pkt, int *got_output, int64_ ist->next_pts = ist->pts = ts; } + // update timestamp history + ist->last_frame_duration_est = video_duration_estimate(ist, decoded_frame); + ist->last_frame_pts = decoded_frame->pts; + if (debug_ts) { av_log(ist, AV_LOG_INFO, "decoder -> pts:%s pts_time:%s " diff --git a/fftools/ffmpeg.h b/fftools/ffmpeg.h index 50e58583853..17076f018d6 100644 --- a/fftools/ffmpeg.h +++ b/fftools/ffmpeg.h @@ -373,6 +373,12 @@ typedef struct InputStream { /* predicted pts of the next decoded frame, in AV_TIME_BASE */ int64_t next_pts; int64_t pts; ///< current pts of the decoded frame (in AV_TIME_BASE units) + + // pts/estimated duration of the last decoded video frame + // in decoder timebase + int64_t last_frame_pts; + int64_t last_frame_duration_est; + int wrap_correction_done; // the value of AVCodecParserContext.repeat_pict from the AVStream parser @@ -445,9 +451,6 @@ typedef struct InputStream { uint64_t frames_decoded; uint64_t samples_decoded; - int64_t *dts_buffer; - int nb_dts_buffer; - int got_output; } InputStream; diff --git a/fftools/ffmpeg_demux.c b/fftools/ffmpeg_demux.c index 7ff57273c9a..b9849d1669f 100644 --- a/fftools/ffmpeg_demux.c +++ b/fftools/ffmpeg_demux.c @@ -532,7 +532,6 @@ static void ist_free(InputStream **pist) av_freep(&ist->filters); av_freep(&ist->outputs); av_freep(&ist->hwaccel_device); - av_freep(&ist->dts_buffer); avcodec_free_context(&ist->dec_ctx); avcodec_parameters_free(&ist->par); @@ -879,6 +878,8 @@ static void add_input_streams(const OptionsContext *o, Demuxer *d) ist->framerate_guessed = av_guess_frame_rate(ic, st, NULL); + ist->last_frame_pts = AV_NOPTS_VALUE; + break; case AVMEDIA_TYPE_AUDIO: { int guess_layout_max = INT_MAX; diff --git a/tests/fate/h264.mak b/tests/fate/h264.mak index c8ed23955ac..7998879ed31 100644 --- a/tests/fate/h264.mak +++ b/tests/fate/h264.mak @@ -444,7 +444,7 @@ fate-h264-mixed-nal-coding: CMD = framecrc -i $(TARGET_SAM fate-h264-ref-pic-mod-overflow: CMD = framecrc -i $(TARGET_SAMPLES)/h264/ref-pic-mod-overflow.h264 fate-h264-twofields-packet: CMD = framecrc -i $(TARGET_SAMPLES)/h264/twofields_packet.mp4 -an -frames 30 fate-h264-unescaped-extradata: CMD = framecrc -i $(TARGET_SAMPLES)/h264/unescaped_extradata.mp4 -an -frames 10 -fate-h264-3386: CMD = framecrc -i $(TARGET_SAMPLES)/h264/bbc2.sample.h264 +fate-h264-3386: CMD = framecrc -i $(TARGET_SAMPLES)/h264/bbc2.sample.h264 -fps_mode passthrough fate-h264-missing-frame: CMD = framecrc -i $(TARGET_SAMPLES)/h264/nondeterministic_cut.h264 fate-h264-timecode: CMD = framecrc -i $(TARGET_SAMPLES)/h264/crew_cif_timecode-2.h264 diff --git a/tests/ref/fate/h264-3386 b/tests/ref/fate/h264-3386 index 421581f8c63..f1a25a2dc04 100644 --- a/tests/ref/fate/h264-3386 +++ b/tests/ref/fate/h264-3386 @@ -47,6 +47,6 @@ 0, 45, 45, 1, 2332800, 0x80b968d3 0, 46, 46, 1, 2332800, 0xa45f4e6f 0, 47, 47, 1, 2332800, 0xe0fcbade -0, 48, 48, 1, 2332800, 0x19568f4d -0, 49, 49, 1, 2332800, 0x33c53f59 -0, 50, 50, 1, 2332800, 0xbdbe8fbf +0, 47, 47, 1, 2332800, 0x19568f4d +0, 48, 48, 1, 2332800, 0x33c53f59 +0, 49, 49, 1, 2332800, 0xbdbe8fbf diff --git a/tests/ref/fate/hevc-conformance-DELTAQP_A_BRCM_4 b/tests/ref/fate/hevc-conformance-DELTAQP_A_BRCM_4 index 5ca3faf58fb..2abd58b64be 100644 --- a/tests/ref/fate/hevc-conformance-DELTAQP_A_BRCM_4 +++ b/tests/ref/fate/hevc-conformance-DELTAQP_A_BRCM_4 @@ -98,4 +98,4 @@ 0, 92, 92, 1, 3133440, 0x761571be 0, 93, 93, 1, 3133440, 0x34dc14a1 0, 94, 94, 1, 3133440, 0xbb94c2d4 -0, 96, 96, 1, 3133440, 0x5300e459 +0, 95, 95, 1, 3133440, 0x5300e459 diff --git a/tests/ref/fate/hevc-small422chroma b/tests/ref/fate/hevc-small422chroma index de0ea46c31a..dca2af0a1a3 100644 --- a/tests/ref/fate/hevc-small422chroma +++ b/tests/ref/fate/hevc-small422chroma @@ -3,4 +3,4 @@ #codec_id 0: rawvideo #dimensions 0: 3840x2160 #sar 0: 1/1 -0, 7, 7, 1, 33177600, 0x53015e18 +0, 0, 0, 1, 33177600, 0x53015e18 From cea71b213901488714cb3c16671b92091390b9f6 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Sun, 9 Apr 2023 15:01:29 +0200 Subject: [PATCH 0668/2172] fftools/ffmpeg: stop using fake dts for generating timestamps When no packet dts values are available from the container, video decoding code will currently use its own guessed values, which will then be propagated to pkt_dts on decoded frames and used as pts in certain cases. This is inaccurate, fragile, and unnecessarily convoluted. Simply removing this allows the extrapolation code introduced in the previous commit to do a better job. Changes the results of numerous h264 and hevc FATE tests, where no spurious timestamp gaps are generated anymore. Several tests no longer need -vsync passthrough. --- fftools/ffmpeg.c | 7 - tests/fate/h264.mak | 4 +- tests/ref/fate/h264-3386 | 94 +-- .../fate/h264-conformance-cabac_mot_fld0_full | 60 +- .../h264-conformance-cabac_mot_picaff0_full | 60 +- .../ref/fate/h264-conformance-cabref3_sand_d | 100 +-- tests/ref/fate/h264-conformance-cafi1_sva_c | 66 +- .../ref/fate/h264-conformance-capa1_toshiba_b | 180 +++--- .../ref/fate/h264-conformance-capama3_sand_f | 100 +-- .../h264-conformance-cavlc_mot_fld0_full_b | 60 +- .../h264-conformance-cavlc_mot_picaff0_full_b | 60 +- tests/ref/fate/h264-conformance-cvfi1_sony_d | 34 +- tests/ref/fate/h264-conformance-cvfi1_sva_c | 14 +- tests/ref/fate/h264-conformance-cvfi2_sony_h | 34 +- tests/ref/fate/h264-conformance-cvfi2_sva_c | 26 +- .../fate/h264-conformance-cvmapaqp3_sony_e | 14 +- .../fate/h264-conformance-cvmp_mot_fld_l30_b | 60 +- .../fate/h264-conformance-cvmp_mot_frm_l31_b | 60 +- .../ref/fate/h264-conformance-cvnlfi1_sony_c | 34 +- .../ref/fate/h264-conformance-cvnlfi2_sony_h | 34 +- .../ref/fate/h264-conformance-cvpa1_toshiba_b | 180 +++--- tests/ref/fate/h264-conformance-fi1_sony_e | 34 +- .../fate/h264-conformance-frext-bcrm_freh10 | 200 +++--- .../fate/h264-conformance-frext-brcm_freh11 | 200 +++--- .../fate/h264-conformance-frext-brcm_freh4 | 200 +++--- tests/ref/fate/h264-conformance-frext-freh6 | 200 +++--- tests/ref/fate/h264-conformance-frext-freh7_b | 200 +++--- .../h264-conformance-frext-frext2_panasonic_b | 30 +- .../h264-conformance-frext-frext4_panasonic_a | 20 +- .../fate/h264-conformance-frext-hcaff1_hhi_b | 20 +- .../fate/h264-conformance-frext-hpcafl_bcrm_c | 600 +++++++++--------- .../h264-conformance-frext-hpcaflnl_bcrm_c | 600 +++++++++--------- .../h264-conformance-frext-hpcamapalq_bcrm_b | 316 ++++----- .../fate/h264-conformance-frext-hpcvfl_bcrm_a | 600 +++++++++--------- .../h264-conformance-frext-hpcvflnl_bcrm_a | 600 +++++++++--------- .../ref/fate/h264-conformance-mr3_tandberg_b | 582 ++++++++--------- tests/ref/fate/h264-conformance-mr6_bt_b | 120 ++-- tests/ref/fate/h264-conformance-mr7_bt_b | 100 +-- tests/ref/fate/h264-conformance-mr8_bt_b | 116 ++-- tests/ref/fate/h264-conformance-mr9_bt_b | 96 +-- .../fate/h264-conformance-sharp_mp_field_1_b | 30 +- .../fate/h264-conformance-sharp_mp_field_2_b | 30 +- .../fate/h264-conformance-sharp_mp_field_3_b | 30 +- .../fate/h264-conformance-sharp_mp_paff_1r2 | 26 +- .../fate/h264-conformance-sharp_mp_paff_2r | 26 +- tests/ref/fate/h264-intra-refresh-recovery | 20 +- .../hevc-conformance-BUMPING_A_ericsson_1 | 90 +-- .../fate/hevc-conformance-NUT_A_ericsson_5 | 24 +- .../hevc-conformance-NoOutPrior_A_Qualcomm_1 | 36 +- .../hevc-conformance-NoOutPrior_B_Qualcomm_1 | 50 +- .../fate/hevc-conformance-OPFLAG_B_Qualcomm_1 | 118 ++-- .../fate/hevc-conformance-OPFLAG_C_Qualcomm_1 | 162 ++--- .../ref/fate/hevc-conformance-RAP_A_docomo_4 | 172 ++--- .../ref/fate/hevc-conformance-RAP_B_Bossen_1 | 26 +- 54 files changed, 3474 insertions(+), 3481 deletions(-) diff --git a/fftools/ffmpeg.c b/fftools/ffmpeg.c index 757d837d5fc..6e445427761 100644 --- a/fftools/ffmpeg.c +++ b/fftools/ffmpeg.c @@ -1333,7 +1333,6 @@ static int decode_video(InputStream *ist, AVPacket *pkt, int *got_output, int64_ AVFrame *decoded_frame = ist->decoded_frame; int ret = 0, err = 0; int64_t best_effort_timestamp; - int64_t dts = AV_NOPTS_VALUE; // With fate-indeo3-2, we're getting 0-sized packets before EOF for some // reason. This seems like a semi-critical bug. Don't trigger EOF, and @@ -1341,12 +1340,6 @@ static int decode_video(InputStream *ist, AVPacket *pkt, int *got_output, int64_ if (!eof && pkt && pkt->size == 0) return 0; - if (ist->dts != AV_NOPTS_VALUE) - dts = av_rescale_q(ist->dts, AV_TIME_BASE_Q, ist->st->time_base); - if (pkt) { - pkt->dts = dts; // ffmpeg.c probably shouldn't do this - } - update_benchmark(NULL); ret = decode(ist, ist->dec_ctx, decoded_frame, got_output, pkt); update_benchmark("decode_video %d.%d", ist->file_index, ist->st->index); diff --git a/tests/fate/h264.mak b/tests/fate/h264.mak index 7998879ed31..173806861aa 100644 --- a/tests/fate/h264.mak +++ b/tests/fate/h264.mak @@ -365,7 +365,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 passthrough +fate-h264-conformance-frext-hpcamapalq_bcrm_b: CMD = framecrc -i $(TARGET_SAMPLES)/h264-conformance/FRext/HPCAMAPALQ_BRCM_B.264 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 @@ -444,7 +444,7 @@ fate-h264-mixed-nal-coding: CMD = framecrc -i $(TARGET_SAM fate-h264-ref-pic-mod-overflow: CMD = framecrc -i $(TARGET_SAMPLES)/h264/ref-pic-mod-overflow.h264 fate-h264-twofields-packet: CMD = framecrc -i $(TARGET_SAMPLES)/h264/twofields_packet.mp4 -an -frames 30 fate-h264-unescaped-extradata: CMD = framecrc -i $(TARGET_SAMPLES)/h264/unescaped_extradata.mp4 -an -frames 10 -fate-h264-3386: CMD = framecrc -i $(TARGET_SAMPLES)/h264/bbc2.sample.h264 -fps_mode passthrough +fate-h264-3386: CMD = framecrc -i $(TARGET_SAMPLES)/h264/bbc2.sample.h264 fate-h264-missing-frame: CMD = framecrc -i $(TARGET_SAMPLES)/h264/nondeterministic_cut.h264 fate-h264-timecode: CMD = framecrc -i $(TARGET_SAMPLES)/h264/crew_cif_timecode-2.h264 diff --git a/tests/ref/fate/h264-3386 b/tests/ref/fate/h264-3386 index f1a25a2dc04..0b15d88cdf6 100644 --- a/tests/ref/fate/h264-3386 +++ b/tests/ref/fate/h264-3386 @@ -3,50 +3,50 @@ #codec_id 0: rawvideo #dimensions 0: 1440x1080 #sar 0: 4/3 -0, 3, 3, 1, 2332800, 0xa9dcb2ac -0, 4, 4, 1, 2332800, 0x9b17af27 -0, 5, 5, 1, 2332800, 0x02da3196 -0, 6, 6, 1, 2332800, 0x9c78ed62 -0, 7, 7, 1, 2332800, 0xa6e926a0 -0, 8, 8, 1, 2332800, 0x324e51d2 -0, 9, 9, 1, 2332800, 0xd8289620 -0, 10, 10, 1, 2332800, 0xfc3619f9 -0, 11, 11, 1, 2332800, 0x6b8d2560 -0, 12, 12, 1, 2332800, 0x5714dca0 -0, 13, 13, 1, 2332800, 0x246e2842 -0, 14, 14, 1, 2332800, 0x59bc0b2e -0, 15, 15, 1, 2332800, 0x24fe5cfa -0, 16, 16, 1, 2332800, 0xb9607c3e -0, 17, 17, 1, 2332800, 0x663669c9 -0, 19, 19, 1, 2332800, 0xd37fd62f -0, 20, 20, 1, 2332800, 0x2d7db904 -0, 21, 21, 1, 2332800, 0x79a53eba -0, 22, 22, 1, 2332800, 0x3b0c7e19 -0, 23, 23, 1, 2332800, 0xd12f64c5 -0, 24, 24, 1, 2332800, 0xacdb407f -0, 25, 25, 1, 2332800, 0x829d7e61 -0, 26, 26, 1, 2332800, 0x7932b82f -0, 27, 27, 1, 2332800, 0x61f81627 -0, 28, 28, 1, 2332800, 0xa1a2e000 -0, 29, 29, 1, 2332800, 0x93aad5e9 -0, 30, 30, 1, 2332800, 0x9993b5b5 -0, 31, 31, 1, 2332800, 0x6ac48232 -0, 32, 32, 1, 2332800, 0x5738f9c0 -0, 33, 33, 1, 2332800, 0x82a59d01 -0, 34, 34, 1, 2332800, 0xc4664862 -0, 35, 35, 1, 2332800, 0xf0e6222d -0, 36, 36, 1, 2332800, 0xd29e7100 -0, 37, 37, 1, 2332800, 0xe093ef85 -0, 38, 38, 1, 2332800, 0x28c68a65 -0, 39, 39, 1, 2332800, 0x49a6b21e -0, 40, 40, 1, 2332800, 0xfb28a097 -0, 41, 41, 1, 2332800, 0xade1e336 -0, 42, 42, 1, 2332800, 0xe5118412 -0, 43, 43, 1, 2332800, 0x58750176 -0, 44, 44, 1, 2332800, 0xacb99939 -0, 45, 45, 1, 2332800, 0x80b968d3 -0, 46, 46, 1, 2332800, 0xa45f4e6f -0, 47, 47, 1, 2332800, 0xe0fcbade -0, 47, 47, 1, 2332800, 0x19568f4d -0, 48, 48, 1, 2332800, 0x33c53f59 -0, 49, 49, 1, 2332800, 0xbdbe8fbf +0, 0, 0, 1, 2332800, 0xa9dcb2ac +0, 1, 1, 1, 2332800, 0x9b17af27 +0, 2, 2, 1, 2332800, 0x02da3196 +0, 3, 3, 1, 2332800, 0x9c78ed62 +0, 4, 4, 1, 2332800, 0xa6e926a0 +0, 5, 5, 1, 2332800, 0x324e51d2 +0, 6, 6, 1, 2332800, 0xd8289620 +0, 7, 7, 1, 2332800, 0xfc3619f9 +0, 8, 8, 1, 2332800, 0x6b8d2560 +0, 9, 9, 1, 2332800, 0x5714dca0 +0, 10, 10, 1, 2332800, 0x246e2842 +0, 11, 11, 1, 2332800, 0x59bc0b2e +0, 12, 12, 1, 2332800, 0x24fe5cfa +0, 13, 13, 1, 2332800, 0xb9607c3e +0, 14, 14, 1, 2332800, 0x663669c9 +0, 15, 15, 1, 2332800, 0xd37fd62f +0, 16, 16, 1, 2332800, 0x2d7db904 +0, 17, 17, 1, 2332800, 0x79a53eba +0, 18, 18, 1, 2332800, 0x3b0c7e19 +0, 19, 19, 1, 2332800, 0xd12f64c5 +0, 20, 20, 1, 2332800, 0xacdb407f +0, 21, 21, 1, 2332800, 0x829d7e61 +0, 22, 22, 1, 2332800, 0x7932b82f +0, 23, 23, 1, 2332800, 0x61f81627 +0, 24, 24, 1, 2332800, 0xa1a2e000 +0, 25, 25, 1, 2332800, 0x93aad5e9 +0, 26, 26, 1, 2332800, 0x9993b5b5 +0, 27, 27, 1, 2332800, 0x6ac48232 +0, 28, 28, 1, 2332800, 0x5738f9c0 +0, 29, 29, 1, 2332800, 0x82a59d01 +0, 30, 30, 1, 2332800, 0xc4664862 +0, 31, 31, 1, 2332800, 0xf0e6222d +0, 32, 32, 1, 2332800, 0xd29e7100 +0, 33, 33, 1, 2332800, 0xe093ef85 +0, 34, 34, 1, 2332800, 0x28c68a65 +0, 35, 35, 1, 2332800, 0x49a6b21e +0, 36, 36, 1, 2332800, 0xfb28a097 +0, 37, 37, 1, 2332800, 0xade1e336 +0, 38, 38, 1, 2332800, 0xe5118412 +0, 39, 39, 1, 2332800, 0x58750176 +0, 40, 40, 1, 2332800, 0xacb99939 +0, 41, 41, 1, 2332800, 0x80b968d3 +0, 42, 42, 1, 2332800, 0xa45f4e6f +0, 43, 43, 1, 2332800, 0xe0fcbade +0, 44, 44, 1, 2332800, 0x19568f4d +0, 45, 45, 1, 2332800, 0x33c53f59 +0, 46, 46, 1, 2332800, 0xbdbe8fbf diff --git a/tests/ref/fate/h264-conformance-cabac_mot_fld0_full b/tests/ref/fate/h264-conformance-cabac_mot_fld0_full index 62bea9cd989..8778fef98e0 100644 --- a/tests/ref/fate/h264-conformance-cabac_mot_fld0_full +++ b/tests/ref/fate/h264-conformance-cabac_mot_fld0_full @@ -3,33 +3,33 @@ #codec_id 0: rawvideo #dimensions 0: 720x480 #sar 0: 0/1 -0, 1, 1, 1, 518400, 0xbf168f4e -0, 2, 2, 1, 518400, 0xeda5e54f -0, 3, 3, 1, 518400, 0xef496d43 -0, 4, 4, 1, 518400, 0x6b68dad5 -0, 5, 5, 1, 518400, 0x9a40a7de -0, 6, 6, 1, 518400, 0x0c21c018 -0, 7, 7, 1, 518400, 0x4ac5a846 -0, 8, 8, 1, 518400, 0x3a1aa817 -0, 9, 9, 1, 518400, 0xcc4eb434 -0, 10, 10, 1, 518400, 0x4368a3c2 -0, 11, 11, 1, 518400, 0xb923682f -0, 12, 12, 1, 518400, 0xd95460a8 -0, 13, 13, 1, 518400, 0x8e8518aa -0, 14, 14, 1, 518400, 0x292a1a80 -0, 15, 15, 1, 518400, 0xbada388e -0, 16, 16, 1, 518400, 0xa67f63c9 -0, 17, 17, 1, 518400, 0x9fc77e21 -0, 18, 18, 1, 518400, 0xe99dc2ac -0, 19, 19, 1, 518400, 0x17d7d080 -0, 20, 20, 1, 518400, 0x41760c0b -0, 21, 21, 1, 518400, 0x3c70f34d -0, 22, 22, 1, 518400, 0x0d640285 -0, 23, 23, 1, 518400, 0x448893e8 -0, 24, 24, 1, 518400, 0x08194490 -0, 25, 25, 1, 518400, 0xcf227031 -0, 26, 26, 1, 518400, 0x8d94587d -0, 27, 27, 1, 518400, 0x696fca01 -0, 28, 28, 1, 518400, 0xe0ab234b -0, 29, 29, 1, 518400, 0x0620153b -0, 30, 30, 1, 518400, 0xb78c146c +0, 0, 0, 1, 518400, 0xbf168f4e +0, 1, 1, 1, 518400, 0xeda5e54f +0, 2, 2, 1, 518400, 0xef496d43 +0, 3, 3, 1, 518400, 0x6b68dad5 +0, 4, 4, 1, 518400, 0x9a40a7de +0, 5, 5, 1, 518400, 0x0c21c018 +0, 6, 6, 1, 518400, 0x4ac5a846 +0, 7, 7, 1, 518400, 0x3a1aa817 +0, 8, 8, 1, 518400, 0xcc4eb434 +0, 9, 9, 1, 518400, 0x4368a3c2 +0, 10, 10, 1, 518400, 0xb923682f +0, 11, 11, 1, 518400, 0xd95460a8 +0, 12, 12, 1, 518400, 0x8e8518aa +0, 13, 13, 1, 518400, 0x292a1a80 +0, 14, 14, 1, 518400, 0xbada388e +0, 15, 15, 1, 518400, 0xa67f63c9 +0, 16, 16, 1, 518400, 0x9fc77e21 +0, 17, 17, 1, 518400, 0xe99dc2ac +0, 18, 18, 1, 518400, 0x17d7d080 +0, 19, 19, 1, 518400, 0x41760c0b +0, 20, 20, 1, 518400, 0x3c70f34d +0, 21, 21, 1, 518400, 0x0d640285 +0, 22, 22, 1, 518400, 0x448893e8 +0, 23, 23, 1, 518400, 0x08194490 +0, 24, 24, 1, 518400, 0xcf227031 +0, 25, 25, 1, 518400, 0x8d94587d +0, 26, 26, 1, 518400, 0x696fca01 +0, 27, 27, 1, 518400, 0xe0ab234b +0, 28, 28, 1, 518400, 0x0620153b +0, 29, 29, 1, 518400, 0xb78c146c diff --git a/tests/ref/fate/h264-conformance-cabac_mot_picaff0_full b/tests/ref/fate/h264-conformance-cabac_mot_picaff0_full index 465cde76165..5651e4b57c2 100644 --- a/tests/ref/fate/h264-conformance-cabac_mot_picaff0_full +++ b/tests/ref/fate/h264-conformance-cabac_mot_picaff0_full @@ -3,33 +3,33 @@ #codec_id 0: rawvideo #dimensions 0: 720x480 #sar 0: 0/1 -0, 1, 1, 1, 518400, 0xd8b58a23 -0, 2, 2, 1, 518400, 0xe53b4aba -0, 3, 3, 1, 518400, 0x6cbca47a -0, 4, 4, 1, 518400, 0xceb51253 -0, 5, 5, 1, 518400, 0x60cb3cdd -0, 6, 6, 1, 518400, 0x7b633553 -0, 7, 7, 1, 518400, 0x10c012c9 -0, 8, 8, 1, 518400, 0xa340ee20 -0, 9, 9, 1, 518400, 0x574c22c2 -0, 10, 10, 1, 518400, 0xbcdb1bf7 -0, 11, 11, 1, 518400, 0x57811e9a -0, 12, 12, 1, 518400, 0xdd4af748 -0, 13, 13, 1, 518400, 0xb931a637 -0, 14, 14, 1, 518400, 0xcef6ce95 -0, 15, 15, 1, 518400, 0xd28c7085 -0, 16, 16, 1, 518400, 0xae9daf53 -0, 17, 17, 1, 518400, 0xca29d819 -0, 18, 18, 1, 518400, 0x3c4bd7eb -0, 19, 19, 1, 518400, 0x912ee227 -0, 20, 20, 1, 518400, 0xb67d0e27 -0, 21, 21, 1, 518400, 0x8cf7309d -0, 22, 22, 1, 518400, 0x358ad344 -0, 23, 23, 1, 518400, 0x4462c642 -0, 24, 24, 1, 518400, 0x3bb43428 -0, 25, 25, 1, 518400, 0x12d6f8ca -0, 26, 26, 1, 518400, 0x003f13aa -0, 27, 27, 1, 518400, 0x6cd8c432 -0, 28, 28, 1, 518400, 0xee5ff01b -0, 29, 29, 1, 518400, 0xba0616ee -0, 30, 30, 1, 518400, 0x37fa7891 +0, 0, 0, 1, 518400, 0xd8b58a23 +0, 1, 1, 1, 518400, 0xe53b4aba +0, 2, 2, 1, 518400, 0x6cbca47a +0, 3, 3, 1, 518400, 0xceb51253 +0, 4, 4, 1, 518400, 0x60cb3cdd +0, 5, 5, 1, 518400, 0x7b633553 +0, 6, 6, 1, 518400, 0x10c012c9 +0, 7, 7, 1, 518400, 0xa340ee20 +0, 8, 8, 1, 518400, 0x574c22c2 +0, 9, 9, 1, 518400, 0xbcdb1bf7 +0, 10, 10, 1, 518400, 0x57811e9a +0, 11, 11, 1, 518400, 0xdd4af748 +0, 12, 12, 1, 518400, 0xb931a637 +0, 13, 13, 1, 518400, 0xcef6ce95 +0, 14, 14, 1, 518400, 0xd28c7085 +0, 15, 15, 1, 518400, 0xae9daf53 +0, 16, 16, 1, 518400, 0xca29d819 +0, 17, 17, 1, 518400, 0x3c4bd7eb +0, 18, 18, 1, 518400, 0x912ee227 +0, 19, 19, 1, 518400, 0xb67d0e27 +0, 20, 20, 1, 518400, 0x8cf7309d +0, 21, 21, 1, 518400, 0x358ad344 +0, 22, 22, 1, 518400, 0x4462c642 +0, 23, 23, 1, 518400, 0x3bb43428 +0, 24, 24, 1, 518400, 0x12d6f8ca +0, 25, 25, 1, 518400, 0x003f13aa +0, 26, 26, 1, 518400, 0x6cd8c432 +0, 27, 27, 1, 518400, 0xee5ff01b +0, 28, 28, 1, 518400, 0xba0616ee +0, 29, 29, 1, 518400, 0x37fa7891 diff --git a/tests/ref/fate/h264-conformance-cabref3_sand_d b/tests/ref/fate/h264-conformance-cabref3_sand_d index 5dfdfac3aa2..d5cd4458797 100644 --- a/tests/ref/fate/h264-conformance-cabref3_sand_d +++ b/tests/ref/fate/h264-conformance-cabref3_sand_d @@ -3,53 +3,53 @@ #codec_id 0: rawvideo #dimensions 0: 352x288 #sar 0: 0/1 -0, 1, 1, 1, 152064, 0x2061bbd0 -0, 2, 2, 1, 152064, 0x41adb750 -0, 3, 3, 1, 152064, 0x6e889e90 -0, 4, 4, 1, 152064, 0xbb5e60f5 -0, 5, 5, 1, 152064, 0x5a32eca7 -0, 6, 6, 1, 152064, 0x5cb05e88 -0, 7, 7, 1, 152064, 0x2fff3e6c -0, 8, 8, 1, 152064, 0xd917c85e -0, 9, 9, 1, 152064, 0x6eac446f -0, 10, 10, 1, 152064, 0x238b24b0 -0, 11, 11, 1, 152064, 0x3f3bd44c -0, 12, 12, 1, 152064, 0x73982bc5 -0, 13, 13, 1, 152064, 0xf6188a82 -0, 14, 14, 1, 152064, 0x818c5b41 -0, 15, 15, 1, 152064, 0x000d1012 -0, 16, 16, 1, 152064, 0xc4a8750e -0, 17, 17, 1, 152064, 0x1689bb77 -0, 18, 18, 1, 152064, 0x8f52f338 -0, 19, 19, 1, 152064, 0xbf5ee06b -0, 20, 20, 1, 152064, 0x89508ad7 -0, 21, 21, 1, 152064, 0x2b1986a6 -0, 22, 22, 1, 152064, 0xe6fd6b0e -0, 23, 23, 1, 152064, 0x883e2e4e -0, 24, 24, 1, 152064, 0xd133db07 -0, 25, 25, 1, 152064, 0x39b3bb22 -0, 26, 26, 1, 152064, 0x8447410a -0, 27, 27, 1, 152064, 0x9c66c6e5 -0, 28, 28, 1, 152064, 0x514de9cc -0, 29, 29, 1, 152064, 0x08d9f1da -0, 30, 30, 1, 152064, 0x8f10f536 -0, 31, 31, 1, 152064, 0x57d4b27b -0, 32, 32, 1, 152064, 0x46f56d3c -0, 33, 33, 1, 152064, 0x5d260230 -0, 34, 34, 1, 152064, 0x4a72aeac -0, 35, 35, 1, 152064, 0x5cfe187f -0, 36, 36, 1, 152064, 0x08e55cb2 -0, 37, 37, 1, 152064, 0x4727f34f -0, 38, 38, 1, 152064, 0xd6a26f1c -0, 39, 39, 1, 152064, 0xcc1fcf9c -0, 40, 40, 1, 152064, 0x3681b775 -0, 41, 41, 1, 152064, 0xf580c7d9 -0, 42, 42, 1, 152064, 0xaa6747fb -0, 43, 43, 1, 152064, 0x2e22f9f9 -0, 44, 44, 1, 152064, 0xb3ee6d81 -0, 45, 45, 1, 152064, 0x930b0145 -0, 46, 46, 1, 152064, 0xae36af99 -0, 47, 47, 1, 152064, 0xeb58fd26 -0, 48, 48, 1, 152064, 0xb9004da3 -0, 49, 49, 1, 152064, 0x2b25e444 -0, 50, 50, 1, 152064, 0xb36927de +0, 0, 0, 1, 152064, 0x2061bbd0 +0, 1, 1, 1, 152064, 0x41adb750 +0, 2, 2, 1, 152064, 0x6e889e90 +0, 3, 3, 1, 152064, 0xbb5e60f5 +0, 4, 4, 1, 152064, 0x5a32eca7 +0, 5, 5, 1, 152064, 0x5cb05e88 +0, 6, 6, 1, 152064, 0x2fff3e6c +0, 7, 7, 1, 152064, 0xd917c85e +0, 8, 8, 1, 152064, 0x6eac446f +0, 9, 9, 1, 152064, 0x238b24b0 +0, 10, 10, 1, 152064, 0x3f3bd44c +0, 11, 11, 1, 152064, 0x73982bc5 +0, 12, 12, 1, 152064, 0xf6188a82 +0, 13, 13, 1, 152064, 0x818c5b41 +0, 14, 14, 1, 152064, 0x000d1012 +0, 15, 15, 1, 152064, 0xc4a8750e +0, 16, 16, 1, 152064, 0x1689bb77 +0, 17, 17, 1, 152064, 0x8f52f338 +0, 18, 18, 1, 152064, 0xbf5ee06b +0, 19, 19, 1, 152064, 0x89508ad7 +0, 20, 20, 1, 152064, 0x2b1986a6 +0, 21, 21, 1, 152064, 0xe6fd6b0e +0, 22, 22, 1, 152064, 0x883e2e4e +0, 23, 23, 1, 152064, 0xd133db07 +0, 24, 24, 1, 152064, 0x39b3bb22 +0, 25, 25, 1, 152064, 0x8447410a +0, 26, 26, 1, 152064, 0x9c66c6e5 +0, 27, 27, 1, 152064, 0x514de9cc +0, 28, 28, 1, 152064, 0x08d9f1da +0, 29, 29, 1, 152064, 0x8f10f536 +0, 30, 30, 1, 152064, 0x57d4b27b +0, 31, 31, 1, 152064, 0x46f56d3c +0, 32, 32, 1, 152064, 0x5d260230 +0, 33, 33, 1, 152064, 0x4a72aeac +0, 34, 34, 1, 152064, 0x5cfe187f +0, 35, 35, 1, 152064, 0x08e55cb2 +0, 36, 36, 1, 152064, 0x4727f34f +0, 37, 37, 1, 152064, 0xd6a26f1c +0, 38, 38, 1, 152064, 0xcc1fcf9c +0, 39, 39, 1, 152064, 0x3681b775 +0, 40, 40, 1, 152064, 0xf580c7d9 +0, 41, 41, 1, 152064, 0xaa6747fb +0, 42, 42, 1, 152064, 0x2e22f9f9 +0, 43, 43, 1, 152064, 0xb3ee6d81 +0, 44, 44, 1, 152064, 0x930b0145 +0, 45, 45, 1, 152064, 0xae36af99 +0, 46, 46, 1, 152064, 0xeb58fd26 +0, 47, 47, 1, 152064, 0xb9004da3 +0, 48, 48, 1, 152064, 0x2b25e444 +0, 49, 49, 1, 152064, 0xb36927de diff --git a/tests/ref/fate/h264-conformance-cafi1_sva_c b/tests/ref/fate/h264-conformance-cafi1_sva_c index 91ae0fd934f..11d958fd4cd 100644 --- a/tests/ref/fate/h264-conformance-cafi1_sva_c +++ b/tests/ref/fate/h264-conformance-cafi1_sva_c @@ -3,36 +3,36 @@ #codec_id 0: rawvideo #dimensions 0: 720x480 #sar 0: 0/1 -0, 1, 1, 1, 518400, 0x47bd73fa -0, 2, 2, 1, 518400, 0xfe3ea7cc -0, 3, 3, 1, 518400, 0x9bc549ae -0, 4, 4, 1, 518400, 0x7bb7f0a1 -0, 5, 5, 1, 518400, 0x328903d4 -0, 6, 6, 1, 518400, 0x96ab366b -0, 7, 7, 1, 518400, 0xa923eed3 -0, 8, 8, 1, 518400, 0x162b08f6 -0, 9, 9, 1, 518400, 0xe711bd8b -0, 10, 10, 1, 518400, 0x55e2d4ed -0, 11, 11, 1, 518400, 0x7dd3107b -0, 12, 12, 1, 518400, 0x0ed20bcf -0, 13, 13, 1, 518400, 0x352f5743 -0, 14, 14, 1, 518400, 0x0a3aeb5e -0, 15, 15, 1, 518400, 0xc458eda3 -0, 16, 16, 1, 518400, 0xe8d5fec5 -0, 17, 17, 1, 518400, 0x18fc6c37 -0, 18, 18, 1, 518400, 0x448add76 -0, 19, 19, 1, 518400, 0x8741ead7 -0, 20, 20, 1, 518400, 0x7008a751 -0, 21, 21, 1, 518400, 0x4ca0633d -0, 22, 22, 1, 518400, 0x021ab800 -0, 23, 23, 1, 518400, 0xfb91ba57 -0, 24, 24, 1, 518400, 0x90e71dd0 -0, 25, 25, 1, 518400, 0xac859de5 -0, 26, 26, 1, 518400, 0xce9790bd -0, 27, 27, 1, 518400, 0x010ade8b -0, 28, 28, 1, 518400, 0xd0b3a399 -0, 29, 29, 1, 518400, 0x6cafcff3 -0, 30, 30, 1, 518400, 0xc32284c0 -0, 31, 31, 1, 518400, 0x1af8f73e -0, 32, 32, 1, 518400, 0x3babd71e -0, 33, 33, 1, 518400, 0xd77cb86b +0, 0, 0, 1, 518400, 0x47bd73fa +0, 1, 1, 1, 518400, 0xfe3ea7cc +0, 2, 2, 1, 518400, 0x9bc549ae +0, 3, 3, 1, 518400, 0x7bb7f0a1 +0, 4, 4, 1, 518400, 0x328903d4 +0, 5, 5, 1, 518400, 0x96ab366b +0, 6, 6, 1, 518400, 0xa923eed3 +0, 7, 7, 1, 518400, 0x162b08f6 +0, 8, 8, 1, 518400, 0xe711bd8b +0, 9, 9, 1, 518400, 0x55e2d4ed +0, 10, 10, 1, 518400, 0x7dd3107b +0, 11, 11, 1, 518400, 0x0ed20bcf +0, 12, 12, 1, 518400, 0x352f5743 +0, 13, 13, 1, 518400, 0x0a3aeb5e +0, 14, 14, 1, 518400, 0xc458eda3 +0, 15, 15, 1, 518400, 0xe8d5fec5 +0, 16, 16, 1, 518400, 0x18fc6c37 +0, 17, 17, 1, 518400, 0x448add76 +0, 18, 18, 1, 518400, 0x8741ead7 +0, 19, 19, 1, 518400, 0x7008a751 +0, 20, 20, 1, 518400, 0x4ca0633d +0, 21, 21, 1, 518400, 0x021ab800 +0, 22, 22, 1, 518400, 0xfb91ba57 +0, 23, 23, 1, 518400, 0x90e71dd0 +0, 24, 24, 1, 518400, 0xac859de5 +0, 25, 25, 1, 518400, 0xce9790bd +0, 26, 26, 1, 518400, 0x010ade8b +0, 27, 27, 1, 518400, 0xd0b3a399 +0, 28, 28, 1, 518400, 0x6cafcff3 +0, 29, 29, 1, 518400, 0xc32284c0 +0, 30, 30, 1, 518400, 0x1af8f73e +0, 31, 31, 1, 518400, 0x3babd71e +0, 32, 32, 1, 518400, 0xd77cb86b diff --git a/tests/ref/fate/h264-conformance-capa1_toshiba_b b/tests/ref/fate/h264-conformance-capa1_toshiba_b index 8a97a30459d..c88dc547eac 100644 --- a/tests/ref/fate/h264-conformance-capa1_toshiba_b +++ b/tests/ref/fate/h264-conformance-capa1_toshiba_b @@ -3,93 +3,93 @@ #codec_id 0: rawvideo #dimensions 0: 352x288 #sar 0: 0/1 -0, 1, 1, 1, 152064, 0x4040d2fc -0, 2, 2, 1, 152064, 0x0d8f9897 -0, 3, 3, 1, 152064, 0xc23321cd -0, 4, 4, 1, 152064, 0x3c9225eb -0, 5, 5, 1, 152064, 0x8927006f -0, 6, 6, 1, 152064, 0xf706a302 -0, 7, 7, 1, 152064, 0x8219c106 -0, 8, 8, 1, 152064, 0x06c990ea -0, 9, 9, 1, 152064, 0x3a0f1135 -0, 10, 10, 1, 152064, 0x4cff21d3 -0, 11, 11, 1, 152064, 0x6be0e050 -0, 12, 12, 1, 152064, 0x718b6c7b -0, 13, 13, 1, 152064, 0x24b38713 -0, 14, 14, 1, 152064, 0x500553fb -0, 15, 15, 1, 152064, 0x531ae610 -0, 16, 16, 1, 152064, 0x46f4ff1b -0, 17, 17, 1, 152064, 0xe5abe5ff -0, 18, 18, 1, 152064, 0x97daa351 -0, 19, 19, 1, 152064, 0xfbef0a8f -0, 20, 20, 1, 152064, 0xbe76134f -0, 21, 21, 1, 152064, 0xa4bf10ea -0, 22, 22, 1, 152064, 0xb2fb32af -0, 23, 23, 1, 152064, 0xd33027a5 -0, 24, 24, 1, 152064, 0x78e20c2b -0, 25, 25, 1, 152064, 0xefda2d6f -0, 26, 26, 1, 152064, 0xb99126f0 -0, 27, 27, 1, 152064, 0x89d7e465 -0, 28, 28, 1, 152064, 0x6150ff97 -0, 29, 29, 1, 152064, 0xde03d937 -0, 30, 30, 1, 152064, 0xd90ca874 -0, 31, 31, 1, 152064, 0xb120b294 -0, 32, 32, 1, 152064, 0x644eade4 -0, 33, 33, 1, 152064, 0xd1bb004f -0, 34, 34, 1, 152064, 0x99806a8b -0, 35, 35, 1, 152064, 0x8c6b635f -0, 36, 36, 1, 152064, 0xa269fa8b -0, 37, 37, 1, 152064, 0xc11c0e64 -0, 38, 38, 1, 152064, 0xac13f5eb -0, 39, 39, 1, 152064, 0x895799cf -0, 40, 40, 1, 152064, 0x95a9bea1 -0, 41, 41, 1, 152064, 0xe998dfba -0, 42, 42, 1, 152064, 0xc72d8460 -0, 43, 43, 1, 152064, 0xd1cb9b9a -0, 44, 44, 1, 152064, 0xb49aadd3 -0, 45, 45, 1, 152064, 0x8bc38547 -0, 46, 46, 1, 152064, 0x3485984b -0, 47, 47, 1, 152064, 0xdf305c0a -0, 48, 48, 1, 152064, 0x6a1ec990 -0, 49, 49, 1, 152064, 0x595e0de4 -0, 50, 50, 1, 152064, 0xe1baf7c4 -0, 51, 51, 1, 152064, 0xf08b9b47 -0, 52, 52, 1, 152064, 0x6532ba6f -0, 53, 53, 1, 152064, 0x3de67da6 -0, 54, 54, 1, 152064, 0x439ffd04 -0, 55, 55, 1, 152064, 0x6e6c1e97 -0, 56, 56, 1, 152064, 0x8e5aee7a -0, 57, 57, 1, 152064, 0xd634999a -0, 58, 58, 1, 152064, 0xadfa9e8b -0, 59, 59, 1, 152064, 0x1b9090f5 -0, 60, 60, 1, 152064, 0x29094dfc -0, 61, 61, 1, 152064, 0x56748851 -0, 62, 62, 1, 152064, 0x2316719d -0, 63, 63, 1, 152064, 0x2ee0060b -0, 64, 64, 1, 152064, 0x3edb36d4 -0, 65, 65, 1, 152064, 0x9ef437a3 -0, 66, 66, 1, 152064, 0x8d9af72e -0, 67, 67, 1, 152064, 0xab86389c -0, 68, 68, 1, 152064, 0xd3b34576 -0, 69, 69, 1, 152064, 0x9e5b04f4 -0, 70, 70, 1, 152064, 0x6a164c17 -0, 71, 71, 1, 152064, 0xcecf20ab -0, 72, 72, 1, 152064, 0x07c8e273 -0, 73, 73, 1, 152064, 0x9b46fe6a -0, 74, 74, 1, 152064, 0xc1e8002b -0, 75, 75, 1, 152064, 0xdebdbe53 -0, 76, 76, 1, 152064, 0x0d2dfd99 -0, 77, 77, 1, 152064, 0xe8ae925f -0, 78, 78, 1, 152064, 0xe1fe6272 -0, 79, 79, 1, 152064, 0xbb74d5e6 -0, 80, 80, 1, 152064, 0xc7b5d949 -0, 81, 81, 1, 152064, 0x9b15b020 -0, 82, 82, 1, 152064, 0xc8201f44 -0, 83, 83, 1, 152064, 0x30d03303 -0, 84, 84, 1, 152064, 0x9f66fbc2 -0, 85, 85, 1, 152064, 0x482b71ec -0, 86, 86, 1, 152064, 0x1c9e50bf -0, 87, 87, 1, 152064, 0x89f247e4 -0, 88, 88, 1, 152064, 0xaa5f9141 -0, 89, 89, 1, 152064, 0xb816aa8c -0, 90, 90, 1, 152064, 0x3112a619 +0, 0, 0, 1, 152064, 0x4040d2fc +0, 1, 1, 1, 152064, 0x0d8f9897 +0, 2, 2, 1, 152064, 0xc23321cd +0, 3, 3, 1, 152064, 0x3c9225eb +0, 4, 4, 1, 152064, 0x8927006f +0, 5, 5, 1, 152064, 0xf706a302 +0, 6, 6, 1, 152064, 0x8219c106 +0, 7, 7, 1, 152064, 0x06c990ea +0, 8, 8, 1, 152064, 0x3a0f1135 +0, 9, 9, 1, 152064, 0x4cff21d3 +0, 10, 10, 1, 152064, 0x6be0e050 +0, 11, 11, 1, 152064, 0x718b6c7b +0, 12, 12, 1, 152064, 0x24b38713 +0, 13, 13, 1, 152064, 0x500553fb +0, 14, 14, 1, 152064, 0x531ae610 +0, 15, 15, 1, 152064, 0x46f4ff1b +0, 16, 16, 1, 152064, 0xe5abe5ff +0, 17, 17, 1, 152064, 0x97daa351 +0, 18, 18, 1, 152064, 0xfbef0a8f +0, 19, 19, 1, 152064, 0xbe76134f +0, 20, 20, 1, 152064, 0xa4bf10ea +0, 21, 21, 1, 152064, 0xb2fb32af +0, 22, 22, 1, 152064, 0xd33027a5 +0, 23, 23, 1, 152064, 0x78e20c2b +0, 24, 24, 1, 152064, 0xefda2d6f +0, 25, 25, 1, 152064, 0xb99126f0 +0, 26, 26, 1, 152064, 0x89d7e465 +0, 27, 27, 1, 152064, 0x6150ff97 +0, 28, 28, 1, 152064, 0xde03d937 +0, 29, 29, 1, 152064, 0xd90ca874 +0, 30, 30, 1, 152064, 0xb120b294 +0, 31, 31, 1, 152064, 0x644eade4 +0, 32, 32, 1, 152064, 0xd1bb004f +0, 33, 33, 1, 152064, 0x99806a8b +0, 34, 34, 1, 152064, 0x8c6b635f +0, 35, 35, 1, 152064, 0xa269fa8b +0, 36, 36, 1, 152064, 0xc11c0e64 +0, 37, 37, 1, 152064, 0xac13f5eb +0, 38, 38, 1, 152064, 0x895799cf +0, 39, 39, 1, 152064, 0x95a9bea1 +0, 40, 40, 1, 152064, 0xe998dfba +0, 41, 41, 1, 152064, 0xc72d8460 +0, 42, 42, 1, 152064, 0xd1cb9b9a +0, 43, 43, 1, 152064, 0xb49aadd3 +0, 44, 44, 1, 152064, 0x8bc38547 +0, 45, 45, 1, 152064, 0x3485984b +0, 46, 46, 1, 152064, 0xdf305c0a +0, 47, 47, 1, 152064, 0x6a1ec990 +0, 48, 48, 1, 152064, 0x595e0de4 +0, 49, 49, 1, 152064, 0xe1baf7c4 +0, 50, 50, 1, 152064, 0xf08b9b47 +0, 51, 51, 1, 152064, 0x6532ba6f +0, 52, 52, 1, 152064, 0x3de67da6 +0, 53, 53, 1, 152064, 0x439ffd04 +0, 54, 54, 1, 152064, 0x6e6c1e97 +0, 55, 55, 1, 152064, 0x8e5aee7a +0, 56, 56, 1, 152064, 0xd634999a +0, 57, 57, 1, 152064, 0xadfa9e8b +0, 58, 58, 1, 152064, 0x1b9090f5 +0, 59, 59, 1, 152064, 0x29094dfc +0, 60, 60, 1, 152064, 0x56748851 +0, 61, 61, 1, 152064, 0x2316719d +0, 62, 62, 1, 152064, 0x2ee0060b +0, 63, 63, 1, 152064, 0x3edb36d4 +0, 64, 64, 1, 152064, 0x9ef437a3 +0, 65, 65, 1, 152064, 0x8d9af72e +0, 66, 66, 1, 152064, 0xab86389c +0, 67, 67, 1, 152064, 0xd3b34576 +0, 68, 68, 1, 152064, 0x9e5b04f4 +0, 69, 69, 1, 152064, 0x6a164c17 +0, 70, 70, 1, 152064, 0xcecf20ab +0, 71, 71, 1, 152064, 0x07c8e273 +0, 72, 72, 1, 152064, 0x9b46fe6a +0, 73, 73, 1, 152064, 0xc1e8002b +0, 74, 74, 1, 152064, 0xdebdbe53 +0, 75, 75, 1, 152064, 0x0d2dfd99 +0, 76, 76, 1, 152064, 0xe8ae925f +0, 77, 77, 1, 152064, 0xe1fe6272 +0, 78, 78, 1, 152064, 0xbb74d5e6 +0, 79, 79, 1, 152064, 0xc7b5d949 +0, 80, 80, 1, 152064, 0x9b15b020 +0, 81, 81, 1, 152064, 0xc8201f44 +0, 82, 82, 1, 152064, 0x30d03303 +0, 83, 83, 1, 152064, 0x9f66fbc2 +0, 84, 84, 1, 152064, 0x482b71ec +0, 85, 85, 1, 152064, 0x1c9e50bf +0, 86, 86, 1, 152064, 0x89f247e4 +0, 87, 87, 1, 152064, 0xaa5f9141 +0, 88, 88, 1, 152064, 0xb816aa8c +0, 89, 89, 1, 152064, 0x3112a619 diff --git a/tests/ref/fate/h264-conformance-capama3_sand_f b/tests/ref/fate/h264-conformance-capama3_sand_f index 50d54604938..b847b9a2b99 100644 --- a/tests/ref/fate/h264-conformance-capama3_sand_f +++ b/tests/ref/fate/h264-conformance-capama3_sand_f @@ -3,53 +3,53 @@ #codec_id 0: rawvideo #dimensions 0: 352x288 #sar 0: 0/1 -0, 1, 1, 1, 152064, 0xf772f152 -0, 2, 2, 1, 152064, 0xc416d300 -0, 3, 3, 1, 152064, 0xc2275c94 -0, 4, 4, 1, 152064, 0x1bd35645 -0, 5, 5, 1, 152064, 0x60327bf5 -0, 6, 6, 1, 152064, 0x7f5541bd -0, 7, 7, 1, 152064, 0x52e5ebad -0, 8, 8, 1, 152064, 0xb8e5c1f3 -0, 9, 9, 1, 152064, 0x2b4e3653 -0, 10, 10, 1, 152064, 0x9a8f8499 -0, 11, 11, 1, 152064, 0x32d4e9fb -0, 12, 12, 1, 152064, 0x0bc73d7a -0, 13, 13, 1, 152064, 0xb58a8b87 -0, 14, 14, 1, 152064, 0xddbc5468 -0, 15, 15, 1, 152064, 0xcfa30b64 -0, 16, 16, 1, 152064, 0xad411f36 -0, 17, 17, 1, 152064, 0x2f8c4d9b -0, 18, 18, 1, 152064, 0xc8523359 -0, 19, 19, 1, 152064, 0x86be9861 -0, 20, 20, 1, 152064, 0x7518d731 -0, 21, 21, 1, 152064, 0x425fbfab -0, 22, 22, 1, 152064, 0x4f00250d -0, 23, 23, 1, 152064, 0x12b40617 -0, 24, 24, 1, 152064, 0x65ff925d -0, 25, 25, 1, 152064, 0xc76a94c9 -0, 26, 26, 1, 152064, 0x640170d5 -0, 27, 27, 1, 152064, 0xd338a090 -0, 28, 28, 1, 152064, 0xce715174 -0, 29, 29, 1, 152064, 0x7bded195 -0, 30, 30, 1, 152064, 0x09e7d3b9 -0, 31, 31, 1, 152064, 0x651e1518 -0, 32, 32, 1, 152064, 0x03cadc5f -0, 33, 33, 1, 152064, 0x08906919 -0, 34, 34, 1, 152064, 0x3303ebe0 -0, 35, 35, 1, 152064, 0xa28676c5 -0, 36, 36, 1, 152064, 0x3900ecaf -0, 37, 37, 1, 152064, 0xeb795a05 -0, 38, 38, 1, 152064, 0x870034df -0, 39, 39, 1, 152064, 0x69b0527a -0, 40, 40, 1, 152064, 0xb2b314f9 -0, 41, 41, 1, 152064, 0x1a44ea1a -0, 42, 42, 1, 152064, 0xe6eaec87 -0, 43, 43, 1, 152064, 0xd9ad818e -0, 44, 44, 1, 152064, 0x9c7ff76e -0, 45, 45, 1, 152064, 0x74c45abb -0, 46, 46, 1, 152064, 0x2f4fa5c6 -0, 47, 47, 1, 152064, 0x19620702 -0, 48, 48, 1, 152064, 0xfc9601f3 -0, 49, 49, 1, 152064, 0x33e0d8e7 -0, 50, 50, 1, 152064, 0xdf7f2a80 +0, 0, 0, 1, 152064, 0xf772f152 +0, 1, 1, 1, 152064, 0xc416d300 +0, 2, 2, 1, 152064, 0xc2275c94 +0, 3, 3, 1, 152064, 0x1bd35645 +0, 4, 4, 1, 152064, 0x60327bf5 +0, 5, 5, 1, 152064, 0x7f5541bd +0, 6, 6, 1, 152064, 0x52e5ebad +0, 7, 7, 1, 152064, 0xb8e5c1f3 +0, 8, 8, 1, 152064, 0x2b4e3653 +0, 9, 9, 1, 152064, 0x9a8f8499 +0, 10, 10, 1, 152064, 0x32d4e9fb +0, 11, 11, 1, 152064, 0x0bc73d7a +0, 12, 12, 1, 152064, 0xb58a8b87 +0, 13, 13, 1, 152064, 0xddbc5468 +0, 14, 14, 1, 152064, 0xcfa30b64 +0, 15, 15, 1, 152064, 0xad411f36 +0, 16, 16, 1, 152064, 0x2f8c4d9b +0, 17, 17, 1, 152064, 0xc8523359 +0, 18, 18, 1, 152064, 0x86be9861 +0, 19, 19, 1, 152064, 0x7518d731 +0, 20, 20, 1, 152064, 0x425fbfab +0, 21, 21, 1, 152064, 0x4f00250d +0, 22, 22, 1, 152064, 0x12b40617 +0, 23, 23, 1, 152064, 0x65ff925d +0, 24, 24, 1, 152064, 0xc76a94c9 +0, 25, 25, 1, 152064, 0x640170d5 +0, 26, 26, 1, 152064, 0xd338a090 +0, 27, 27, 1, 152064, 0xce715174 +0, 28, 28, 1, 152064, 0x7bded195 +0, 29, 29, 1, 152064, 0x09e7d3b9 +0, 30, 30, 1, 152064, 0x651e1518 +0, 31, 31, 1, 152064, 0x03cadc5f +0, 32, 32, 1, 152064, 0x08906919 +0, 33, 33, 1, 152064, 0x3303ebe0 +0, 34, 34, 1, 152064, 0xa28676c5 +0, 35, 35, 1, 152064, 0x3900ecaf +0, 36, 36, 1, 152064, 0xeb795a05 +0, 37, 37, 1, 152064, 0x870034df +0, 38, 38, 1, 152064, 0x69b0527a +0, 39, 39, 1, 152064, 0xb2b314f9 +0, 40, 40, 1, 152064, 0x1a44ea1a +0, 41, 41, 1, 152064, 0xe6eaec87 +0, 42, 42, 1, 152064, 0xd9ad818e +0, 43, 43, 1, 152064, 0x9c7ff76e +0, 44, 44, 1, 152064, 0x74c45abb +0, 45, 45, 1, 152064, 0x2f4fa5c6 +0, 46, 46, 1, 152064, 0x19620702 +0, 47, 47, 1, 152064, 0xfc9601f3 +0, 48, 48, 1, 152064, 0x33e0d8e7 +0, 49, 49, 1, 152064, 0xdf7f2a80 diff --git a/tests/ref/fate/h264-conformance-cavlc_mot_fld0_full_b b/tests/ref/fate/h264-conformance-cavlc_mot_fld0_full_b index 7c5663e623a..0ee9a397f5a 100644 --- a/tests/ref/fate/h264-conformance-cavlc_mot_fld0_full_b +++ b/tests/ref/fate/h264-conformance-cavlc_mot_fld0_full_b @@ -3,33 +3,33 @@ #codec_id 0: rawvideo #dimensions 0: 720x480 #sar 0: 0/1 -0, 1, 1, 1, 518400, 0x99d0df36 -0, 2, 2, 1, 518400, 0xa8601c1a -0, 3, 3, 1, 518400, 0x4a17d235 -0, 4, 4, 1, 518400, 0x75f23abf -0, 5, 5, 1, 518400, 0x746aad53 -0, 6, 6, 1, 518400, 0xb0b8913e -0, 7, 7, 1, 518400, 0x60a27f57 -0, 8, 8, 1, 518400, 0xfa227f3e -0, 9, 9, 1, 518400, 0x7a1e57c2 -0, 10, 10, 1, 518400, 0xcbbaa84f -0, 11, 11, 1, 518400, 0xf9c1bd13 -0, 12, 12, 1, 518400, 0x9e80caaf -0, 13, 13, 1, 518400, 0x14cc6928 -0, 14, 14, 1, 518400, 0xca0353ef -0, 15, 15, 1, 518400, 0xcad65e5f -0, 16, 16, 1, 518400, 0xd5bc47b3 -0, 17, 17, 1, 518400, 0xa9893d36 -0, 18, 18, 1, 518400, 0x69bd9085 -0, 19, 19, 1, 518400, 0xff33c476 -0, 20, 20, 1, 518400, 0x9538adf7 -0, 21, 21, 1, 518400, 0xd4ff3b62 -0, 22, 22, 1, 518400, 0x021a11fd -0, 23, 23, 1, 518400, 0x293e6f9f -0, 24, 24, 1, 518400, 0x5d38e4c3 -0, 25, 25, 1, 518400, 0xd1f4ad49 -0, 26, 26, 1, 518400, 0xf13dd946 -0, 27, 27, 1, 518400, 0x0359e9ff -0, 28, 28, 1, 518400, 0xb61098ad -0, 29, 29, 1, 518400, 0xa855b11c -0, 30, 30, 1, 518400, 0x7fcf9343 +0, 0, 0, 1, 518400, 0x99d0df36 +0, 1, 1, 1, 518400, 0xa8601c1a +0, 2, 2, 1, 518400, 0x4a17d235 +0, 3, 3, 1, 518400, 0x75f23abf +0, 4, 4, 1, 518400, 0x746aad53 +0, 5, 5, 1, 518400, 0xb0b8913e +0, 6, 6, 1, 518400, 0x60a27f57 +0, 7, 7, 1, 518400, 0xfa227f3e +0, 8, 8, 1, 518400, 0x7a1e57c2 +0, 9, 9, 1, 518400, 0xcbbaa84f +0, 10, 10, 1, 518400, 0xf9c1bd13 +0, 11, 11, 1, 518400, 0x9e80caaf +0, 12, 12, 1, 518400, 0x14cc6928 +0, 13, 13, 1, 518400, 0xca0353ef +0, 14, 14, 1, 518400, 0xcad65e5f +0, 15, 15, 1, 518400, 0xd5bc47b3 +0, 16, 16, 1, 518400, 0xa9893d36 +0, 17, 17, 1, 518400, 0x69bd9085 +0, 18, 18, 1, 518400, 0xff33c476 +0, 19, 19, 1, 518400, 0x9538adf7 +0, 20, 20, 1, 518400, 0xd4ff3b62 +0, 21, 21, 1, 518400, 0x021a11fd +0, 22, 22, 1, 518400, 0x293e6f9f +0, 23, 23, 1, 518400, 0x5d38e4c3 +0, 24, 24, 1, 518400, 0xd1f4ad49 +0, 25, 25, 1, 518400, 0xf13dd946 +0, 26, 26, 1, 518400, 0x0359e9ff +0, 27, 27, 1, 518400, 0xb61098ad +0, 28, 28, 1, 518400, 0xa855b11c +0, 29, 29, 1, 518400, 0x7fcf9343 diff --git a/tests/ref/fate/h264-conformance-cavlc_mot_picaff0_full_b b/tests/ref/fate/h264-conformance-cavlc_mot_picaff0_full_b index 8b63e8b5ea7..c0f6a5ed12c 100644 --- a/tests/ref/fate/h264-conformance-cavlc_mot_picaff0_full_b +++ b/tests/ref/fate/h264-conformance-cavlc_mot_picaff0_full_b @@ -3,33 +3,33 @@ #codec_id 0: rawvideo #dimensions 0: 720x480 #sar 0: 0/1 -0, 1, 1, 1, 518400, 0xf6b83a0e -0, 2, 2, 1, 518400, 0xc5e8b8ee -0, 3, 3, 1, 518400, 0xb3bc6e43 -0, 4, 4, 1, 518400, 0x5b08dc73 -0, 5, 5, 1, 518400, 0x4a7f7690 -0, 6, 6, 1, 518400, 0x8a9f4275 -0, 7, 7, 1, 518400, 0xc7cb92fd -0, 8, 8, 1, 518400, 0xc721e231 -0, 9, 9, 1, 518400, 0xfb31371b -0, 10, 10, 1, 518400, 0xac57f5d9 -0, 11, 11, 1, 518400, 0x92b7debc -0, 12, 12, 1, 518400, 0xfe3e533e -0, 13, 13, 1, 518400, 0x1b3a7a72 -0, 14, 14, 1, 518400, 0x98df2d81 -0, 15, 15, 1, 518400, 0xe0ce9c52 -0, 16, 16, 1, 518400, 0x6a31166d -0, 17, 17, 1, 518400, 0x64ffd4d2 -0, 18, 18, 1, 518400, 0x3ec062ef -0, 19, 19, 1, 518400, 0x3480fae1 -0, 20, 20, 1, 518400, 0xa87ae4b7 -0, 21, 21, 1, 518400, 0xd301319f -0, 22, 22, 1, 518400, 0xa9284989 -0, 23, 23, 1, 518400, 0x3de73b50 -0, 24, 24, 1, 518400, 0x30a79f84 -0, 25, 25, 1, 518400, 0x7d5152d4 -0, 26, 26, 1, 518400, 0x25514095 -0, 27, 27, 1, 518400, 0x1749a05f -0, 28, 28, 1, 518400, 0x598139a7 -0, 29, 29, 1, 518400, 0x3cece862 -0, 30, 30, 1, 518400, 0xe1c27efe +0, 0, 0, 1, 518400, 0xf6b83a0e +0, 1, 1, 1, 518400, 0xc5e8b8ee +0, 2, 2, 1, 518400, 0xb3bc6e43 +0, 3, 3, 1, 518400, 0x5b08dc73 +0, 4, 4, 1, 518400, 0x4a7f7690 +0, 5, 5, 1, 518400, 0x8a9f4275 +0, 6, 6, 1, 518400, 0xc7cb92fd +0, 7, 7, 1, 518400, 0xc721e231 +0, 8, 8, 1, 518400, 0xfb31371b +0, 9, 9, 1, 518400, 0xac57f5d9 +0, 10, 10, 1, 518400, 0x92b7debc +0, 11, 11, 1, 518400, 0xfe3e533e +0, 12, 12, 1, 518400, 0x1b3a7a72 +0, 13, 13, 1, 518400, 0x98df2d81 +0, 14, 14, 1, 518400, 0xe0ce9c52 +0, 15, 15, 1, 518400, 0x6a31166d +0, 16, 16, 1, 518400, 0x64ffd4d2 +0, 17, 17, 1, 518400, 0x3ec062ef +0, 18, 18, 1, 518400, 0x3480fae1 +0, 19, 19, 1, 518400, 0xa87ae4b7 +0, 20, 20, 1, 518400, 0xd301319f +0, 21, 21, 1, 518400, 0xa9284989 +0, 22, 22, 1, 518400, 0x3de73b50 +0, 23, 23, 1, 518400, 0x30a79f84 +0, 24, 24, 1, 518400, 0x7d5152d4 +0, 25, 25, 1, 518400, 0x25514095 +0, 26, 26, 1, 518400, 0x1749a05f +0, 27, 27, 1, 518400, 0x598139a7 +0, 28, 28, 1, 518400, 0x3cece862 +0, 29, 29, 1, 518400, 0xe1c27efe diff --git a/tests/ref/fate/h264-conformance-cvfi1_sony_d b/tests/ref/fate/h264-conformance-cvfi1_sony_d index bcb2a150687..bf998bcf8a9 100644 --- a/tests/ref/fate/h264-conformance-cvfi1_sony_d +++ b/tests/ref/fate/h264-conformance-cvfi1_sony_d @@ -3,20 +3,20 @@ #codec_id 0: rawvideo #dimensions 0: 720x480 #sar 0: 0/1 -0, 1, 1, 1, 518400, 0xd9444d71 -0, 2, 2, 1, 518400, 0x5d8928cd -0, 3, 3, 1, 518400, 0xea5bc08b -0, 4, 4, 1, 518400, 0xb4465d31 -0, 5, 5, 1, 518400, 0x983b5dbb -0, 6, 6, 1, 518400, 0x54936746 -0, 7, 7, 1, 518400, 0x7ae38b02 -0, 8, 8, 1, 518400, 0xc2a0dd83 -0, 9, 9, 1, 518400, 0x61cac7a6 -0, 10, 10, 1, 518400, 0xb0038443 -0, 11, 11, 1, 518400, 0x16514296 -0, 12, 12, 1, 518400, 0xa68dd470 -0, 13, 13, 1, 518400, 0x2572f868 -0, 14, 14, 1, 518400, 0x770a3239 -0, 15, 15, 1, 518400, 0xdd04f6d2 -0, 16, 16, 1, 518400, 0xa5e5d01e -0, 17, 17, 1, 518400, 0x5fe25c86 +0, 0, 0, 1, 518400, 0xd9444d71 +0, 1, 1, 1, 518400, 0x5d8928cd +0, 2, 2, 1, 518400, 0xea5bc08b +0, 3, 3, 1, 518400, 0xb4465d31 +0, 4, 4, 1, 518400, 0x983b5dbb +0, 5, 5, 1, 518400, 0x54936746 +0, 6, 6, 1, 518400, 0x7ae38b02 +0, 7, 7, 1, 518400, 0xc2a0dd83 +0, 8, 8, 1, 518400, 0x61cac7a6 +0, 9, 9, 1, 518400, 0xb0038443 +0, 10, 10, 1, 518400, 0x16514296 +0, 11, 11, 1, 518400, 0xa68dd470 +0, 12, 12, 1, 518400, 0x2572f868 +0, 13, 13, 1, 518400, 0x770a3239 +0, 14, 14, 1, 518400, 0xdd04f6d2 +0, 15, 15, 1, 518400, 0xa5e5d01e +0, 16, 16, 1, 518400, 0x5fe25c86 diff --git a/tests/ref/fate/h264-conformance-cvfi1_sva_c b/tests/ref/fate/h264-conformance-cvfi1_sva_c index 1a4841a3778..55628842f57 100644 --- a/tests/ref/fate/h264-conformance-cvfi1_sva_c +++ b/tests/ref/fate/h264-conformance-cvfi1_sva_c @@ -3,10 +3,10 @@ #codec_id 0: rawvideo #dimensions 0: 720x480 #sar 0: 0/1 -0, 1, 1, 1, 518400, 0x8f022263 -0, 2, 2, 1, 518400, 0x02692654 -0, 3, 3, 1, 518400, 0x55eff579 -0, 4, 4, 1, 518400, 0x6c1bdf1d -0, 5, 5, 1, 518400, 0xbbedf5e4 -0, 6, 6, 1, 518400, 0xb90d740d -0, 7, 7, 1, 518400, 0x81300adb +0, 0, 0, 1, 518400, 0x8f022263 +0, 1, 1, 1, 518400, 0x02692654 +0, 2, 2, 1, 518400, 0x55eff579 +0, 3, 3, 1, 518400, 0x6c1bdf1d +0, 4, 4, 1, 518400, 0xbbedf5e4 +0, 5, 5, 1, 518400, 0xb90d740d +0, 6, 6, 1, 518400, 0x81300adb diff --git a/tests/ref/fate/h264-conformance-cvfi2_sony_h b/tests/ref/fate/h264-conformance-cvfi2_sony_h index f86d077f0a5..deb9b38ad8c 100644 --- a/tests/ref/fate/h264-conformance-cvfi2_sony_h +++ b/tests/ref/fate/h264-conformance-cvfi2_sony_h @@ -3,20 +3,20 @@ #codec_id 0: rawvideo #dimensions 0: 720x480 #sar 0: 0/1 -0, 1, 1, 1, 518400, 0xd9444d71 -0, 2, 2, 1, 518400, 0x491faf75 -0, 3, 3, 1, 518400, 0xf8b4d15c -0, 4, 4, 1, 518400, 0x99d9f60c -0, 5, 5, 1, 518400, 0x46c17a6d -0, 6, 6, 1, 518400, 0x30b9447d -0, 7, 7, 1, 518400, 0x135d0c76 -0, 8, 8, 1, 518400, 0x1b831a3c -0, 9, 9, 1, 518400, 0x5910def8 -0, 10, 10, 1, 518400, 0x8db90147 -0, 11, 11, 1, 518400, 0x6a2b79c7 -0, 12, 12, 1, 518400, 0xc8d302e5 -0, 13, 13, 1, 518400, 0x515bb024 -0, 14, 14, 1, 518400, 0xedf7836c -0, 15, 15, 1, 518400, 0x7e247b9d -0, 16, 16, 1, 518400, 0x10c9bb10 -0, 17, 17, 1, 518400, 0xe38e2807 +0, 0, 0, 1, 518400, 0xd9444d71 +0, 1, 1, 1, 518400, 0x491faf75 +0, 2, 2, 1, 518400, 0xf8b4d15c +0, 3, 3, 1, 518400, 0x99d9f60c +0, 4, 4, 1, 518400, 0x46c17a6d +0, 5, 5, 1, 518400, 0x30b9447d +0, 6, 6, 1, 518400, 0x135d0c76 +0, 7, 7, 1, 518400, 0x1b831a3c +0, 8, 8, 1, 518400, 0x5910def8 +0, 9, 9, 1, 518400, 0x8db90147 +0, 10, 10, 1, 518400, 0x6a2b79c7 +0, 11, 11, 1, 518400, 0xc8d302e5 +0, 12, 12, 1, 518400, 0x515bb024 +0, 13, 13, 1, 518400, 0xedf7836c +0, 14, 14, 1, 518400, 0x7e247b9d +0, 15, 15, 1, 518400, 0x10c9bb10 +0, 16, 16, 1, 518400, 0xe38e2807 diff --git a/tests/ref/fate/h264-conformance-cvfi2_sva_c b/tests/ref/fate/h264-conformance-cvfi2_sva_c index 5fe4546d1bb..e2a0b6da785 100644 --- a/tests/ref/fate/h264-conformance-cvfi2_sva_c +++ b/tests/ref/fate/h264-conformance-cvfi2_sva_c @@ -3,16 +3,16 @@ #codec_id 0: rawvideo #dimensions 0: 720x480 #sar 0: 0/1 -0, 1, 1, 1, 518400, 0x4073cc0b -0, 2, 2, 1, 518400, 0x5f599a48 -0, 3, 3, 1, 518400, 0xc6fe555a -0, 4, 4, 1, 518400, 0xe63ac345 -0, 5, 5, 1, 518400, 0x9b4f0c5c -0, 6, 6, 1, 518400, 0x98aaba2d -0, 7, 7, 1, 518400, 0xd629bd09 -0, 8, 8, 1, 518400, 0xe9796c37 -0, 9, 9, 1, 518400, 0xba54d16e -0, 10, 10, 1, 518400, 0xe396c3eb -0, 11, 11, 1, 518400, 0x63ee4b81 -0, 12, 12, 1, 518400, 0x68ac6986 -0, 13, 13, 1, 518400, 0xe0d53000 +0, 0, 0, 1, 518400, 0x4073cc0b +0, 1, 1, 1, 518400, 0x5f599a48 +0, 2, 2, 1, 518400, 0xc6fe555a +0, 3, 3, 1, 518400, 0xe63ac345 +0, 4, 4, 1, 518400, 0x9b4f0c5c +0, 5, 5, 1, 518400, 0x98aaba2d +0, 6, 6, 1, 518400, 0xd629bd09 +0, 7, 7, 1, 518400, 0xe9796c37 +0, 8, 8, 1, 518400, 0xba54d16e +0, 9, 9, 1, 518400, 0xe396c3eb +0, 10, 10, 1, 518400, 0x63ee4b81 +0, 11, 11, 1, 518400, 0x68ac6986 +0, 12, 12, 1, 518400, 0xe0d53000 diff --git a/tests/ref/fate/h264-conformance-cvmapaqp3_sony_e b/tests/ref/fate/h264-conformance-cvmapaqp3_sony_e index d29adc899eb..8cc81e62ac8 100644 --- a/tests/ref/fate/h264-conformance-cvmapaqp3_sony_e +++ b/tests/ref/fate/h264-conformance-cvmapaqp3_sony_e @@ -4,10 +4,10 @@ #dimensions 0: 720x480 #sar 0: 0/1 0, 0, 0, 1, 518400, 0x80dffda2 -0, 2, 2, 1, 518400, 0x9450183b -0, 3, 3, 1, 518400, 0x85d429a7 -0, 4, 4, 1, 518400, 0xe1f3b686 -0, 5, 5, 1, 518400, 0x2180c761 -0, 6, 6, 1, 518400, 0x30269c7c -0, 7, 7, 1, 518400, 0xe9aa575a -0, 8, 8, 1, 518400, 0x7b815a0a +0, 1, 1, 1, 518400, 0x9450183b +0, 2, 2, 1, 518400, 0x85d429a7 +0, 3, 3, 1, 518400, 0xe1f3b686 +0, 4, 4, 1, 518400, 0x2180c761 +0, 5, 5, 1, 518400, 0x30269c7c +0, 6, 6, 1, 518400, 0xe9aa575a +0, 7, 7, 1, 518400, 0x7b815a0a diff --git a/tests/ref/fate/h264-conformance-cvmp_mot_fld_l30_b b/tests/ref/fate/h264-conformance-cvmp_mot_fld_l30_b index 2f3f50dc928..94d4dff0b18 100644 --- a/tests/ref/fate/h264-conformance-cvmp_mot_fld_l30_b +++ b/tests/ref/fate/h264-conformance-cvmp_mot_fld_l30_b @@ -3,33 +3,33 @@ #codec_id 0: rawvideo #dimensions 0: 720x480 #sar 0: 0/1 -0, 1, 1, 1, 518400, 0xe9c7643e -0, 2, 2, 1, 518400, 0xba7456ec -0, 3, 3, 1, 518400, 0xdeb96749 -0, 4, 4, 1, 518400, 0xa101a986 -0, 5, 5, 1, 518400, 0x3db7baa5 -0, 6, 6, 1, 518400, 0xf3dfcec7 -0, 7, 7, 1, 518400, 0x79b4f537 -0, 8, 8, 1, 518400, 0x9e64fe68 -0, 9, 9, 1, 518400, 0x0e810b53 -0, 10, 10, 1, 518400, 0x20baf3b8 -0, 11, 11, 1, 518400, 0x0a49d341 -0, 12, 12, 1, 518400, 0xa8304ab5 -0, 13, 13, 1, 518400, 0x2600e98f -0, 14, 14, 1, 518400, 0x9253e3e8 -0, 15, 15, 1, 518400, 0xd6e12783 -0, 16, 16, 1, 518400, 0x6894fc79 -0, 17, 17, 1, 518400, 0xfb60d3e3 -0, 18, 18, 1, 518400, 0x523602be -0, 19, 19, 1, 518400, 0x4979f409 -0, 20, 20, 1, 518400, 0x50d4e2ab -0, 21, 21, 1, 518400, 0xa8c2140a -0, 22, 22, 1, 518400, 0x45c0bc15 -0, 23, 23, 1, 518400, 0xaef78cab -0, 24, 24, 1, 518400, 0xec539d02 -0, 25, 25, 1, 518400, 0x602585ea -0, 26, 26, 1, 518400, 0xda263463 -0, 27, 27, 1, 518400, 0xa03d8922 -0, 28, 28, 1, 518400, 0x43ea1c1d -0, 29, 29, 1, 518400, 0xb1e055a6 -0, 30, 30, 1, 518400, 0x6fff9398 +0, 0, 0, 1, 518400, 0xe9c7643e +0, 1, 1, 1, 518400, 0xba7456ec +0, 2, 2, 1, 518400, 0xdeb96749 +0, 3, 3, 1, 518400, 0xa101a986 +0, 4, 4, 1, 518400, 0x3db7baa5 +0, 5, 5, 1, 518400, 0xf3dfcec7 +0, 6, 6, 1, 518400, 0x79b4f537 +0, 7, 7, 1, 518400, 0x9e64fe68 +0, 8, 8, 1, 518400, 0x0e810b53 +0, 9, 9, 1, 518400, 0x20baf3b8 +0, 10, 10, 1, 518400, 0x0a49d341 +0, 11, 11, 1, 518400, 0xa8304ab5 +0, 12, 12, 1, 518400, 0x2600e98f +0, 13, 13, 1, 518400, 0x9253e3e8 +0, 14, 14, 1, 518400, 0xd6e12783 +0, 15, 15, 1, 518400, 0x6894fc79 +0, 16, 16, 1, 518400, 0xfb60d3e3 +0, 17, 17, 1, 518400, 0x523602be +0, 18, 18, 1, 518400, 0x4979f409 +0, 19, 19, 1, 518400, 0x50d4e2ab +0, 20, 20, 1, 518400, 0xa8c2140a +0, 21, 21, 1, 518400, 0x45c0bc15 +0, 22, 22, 1, 518400, 0xaef78cab +0, 23, 23, 1, 518400, 0xec539d02 +0, 24, 24, 1, 518400, 0x602585ea +0, 25, 25, 1, 518400, 0xda263463 +0, 26, 26, 1, 518400, 0xa03d8922 +0, 27, 27, 1, 518400, 0x43ea1c1d +0, 28, 28, 1, 518400, 0xb1e055a6 +0, 29, 29, 1, 518400, 0x6fff9398 diff --git a/tests/ref/fate/h264-conformance-cvmp_mot_frm_l31_b b/tests/ref/fate/h264-conformance-cvmp_mot_frm_l31_b index 25d46c4bb4c..fc6b1b7d5ea 100644 --- a/tests/ref/fate/h264-conformance-cvmp_mot_frm_l31_b +++ b/tests/ref/fate/h264-conformance-cvmp_mot_frm_l31_b @@ -3,33 +3,33 @@ #codec_id 0: rawvideo #dimensions 0: 720x480 #sar 0: 0/1 -0, 1, 1, 1, 518400, 0x7b2475e3 -0, 2, 2, 1, 518400, 0xda786a87 -0, 3, 3, 1, 518400, 0xb1dd8108 -0, 4, 4, 1, 518400, 0x760ed65d -0, 5, 5, 1, 518400, 0x8632d20c -0, 6, 6, 1, 518400, 0xdd81e625 -0, 7, 7, 1, 518400, 0x853f1c41 -0, 8, 8, 1, 518400, 0x20191585 -0, 9, 9, 1, 518400, 0x0367e357 -0, 10, 10, 1, 518400, 0x60521167 -0, 11, 11, 1, 518400, 0xa887d4cc -0, 12, 12, 1, 518400, 0x9a450f9e -0, 13, 13, 1, 518400, 0xe9620841 -0, 14, 14, 1, 518400, 0xb482fb0e -0, 15, 15, 1, 518400, 0x7b79f670 -0, 16, 16, 1, 518400, 0x9d37f1d1 -0, 17, 17, 1, 518400, 0xe358d323 -0, 18, 18, 1, 518400, 0x62ade59c -0, 19, 19, 1, 518400, 0xdd78da66 -0, 20, 20, 1, 518400, 0xd97b867b -0, 21, 21, 1, 518400, 0x8a90cf8c -0, 22, 22, 1, 518400, 0x9d386610 -0, 23, 23, 1, 518400, 0x2c590f46 -0, 24, 24, 1, 518400, 0x92662861 -0, 25, 25, 1, 518400, 0x6979f563 -0, 26, 26, 1, 518400, 0xdd0fa1b2 -0, 27, 27, 1, 518400, 0xccbf1c1c -0, 28, 28, 1, 518400, 0x7e358112 -0, 29, 29, 1, 518400, 0xb7c0d89d -0, 30, 30, 1, 518400, 0xc6b03973 +0, 0, 0, 1, 518400, 0x7b2475e3 +0, 1, 1, 1, 518400, 0xda786a87 +0, 2, 2, 1, 518400, 0xb1dd8108 +0, 3, 3, 1, 518400, 0x760ed65d +0, 4, 4, 1, 518400, 0x8632d20c +0, 5, 5, 1, 518400, 0xdd81e625 +0, 6, 6, 1, 518400, 0x853f1c41 +0, 7, 7, 1, 518400, 0x20191585 +0, 8, 8, 1, 518400, 0x0367e357 +0, 9, 9, 1, 518400, 0x60521167 +0, 10, 10, 1, 518400, 0xa887d4cc +0, 11, 11, 1, 518400, 0x9a450f9e +0, 12, 12, 1, 518400, 0xe9620841 +0, 13, 13, 1, 518400, 0xb482fb0e +0, 14, 14, 1, 518400, 0x7b79f670 +0, 15, 15, 1, 518400, 0x9d37f1d1 +0, 16, 16, 1, 518400, 0xe358d323 +0, 17, 17, 1, 518400, 0x62ade59c +0, 18, 18, 1, 518400, 0xdd78da66 +0, 19, 19, 1, 518400, 0xd97b867b +0, 20, 20, 1, 518400, 0x8a90cf8c +0, 21, 21, 1, 518400, 0x9d386610 +0, 22, 22, 1, 518400, 0x2c590f46 +0, 23, 23, 1, 518400, 0x92662861 +0, 24, 24, 1, 518400, 0x6979f563 +0, 25, 25, 1, 518400, 0xdd0fa1b2 +0, 26, 26, 1, 518400, 0xccbf1c1c +0, 27, 27, 1, 518400, 0x7e358112 +0, 28, 28, 1, 518400, 0xb7c0d89d +0, 29, 29, 1, 518400, 0xc6b03973 diff --git a/tests/ref/fate/h264-conformance-cvnlfi1_sony_c b/tests/ref/fate/h264-conformance-cvnlfi1_sony_c index 47b1a4b2ac9..02a6b537523 100644 --- a/tests/ref/fate/h264-conformance-cvnlfi1_sony_c +++ b/tests/ref/fate/h264-conformance-cvnlfi1_sony_c @@ -3,20 +3,20 @@ #codec_id 0: rawvideo #dimensions 0: 720x480 #sar 0: 0/1 -0, 1, 1, 1, 518400, 0x0fbb4e71 -0, 2, 2, 1, 518400, 0x4b816734 -0, 3, 3, 1, 518400, 0x0c350f19 -0, 4, 4, 1, 518400, 0xda049cb6 -0, 5, 5, 1, 518400, 0x1f3e7bb9 -0, 6, 6, 1, 518400, 0x995cbe66 -0, 7, 7, 1, 518400, 0x07f7e65c -0, 8, 8, 1, 518400, 0xfcb7487f -0, 9, 9, 1, 518400, 0xb080f48a -0, 10, 10, 1, 518400, 0x3ef5b7e4 -0, 11, 11, 1, 518400, 0xa1518e1c -0, 12, 12, 1, 518400, 0xb36f1cc9 -0, 13, 13, 1, 518400, 0x86ea48af -0, 14, 14, 1, 518400, 0xe42373b7 -0, 15, 15, 1, 518400, 0xa8435828 -0, 16, 16, 1, 518400, 0xc942ea0e -0, 17, 17, 1, 518400, 0xcc597514 +0, 0, 0, 1, 518400, 0x0fbb4e71 +0, 1, 1, 1, 518400, 0x4b816734 +0, 2, 2, 1, 518400, 0x0c350f19 +0, 3, 3, 1, 518400, 0xda049cb6 +0, 4, 4, 1, 518400, 0x1f3e7bb9 +0, 5, 5, 1, 518400, 0x995cbe66 +0, 6, 6, 1, 518400, 0x07f7e65c +0, 7, 7, 1, 518400, 0xfcb7487f +0, 8, 8, 1, 518400, 0xb080f48a +0, 9, 9, 1, 518400, 0x3ef5b7e4 +0, 10, 10, 1, 518400, 0xa1518e1c +0, 11, 11, 1, 518400, 0xb36f1cc9 +0, 12, 12, 1, 518400, 0x86ea48af +0, 13, 13, 1, 518400, 0xe42373b7 +0, 14, 14, 1, 518400, 0xa8435828 +0, 15, 15, 1, 518400, 0xc942ea0e +0, 16, 16, 1, 518400, 0xcc597514 diff --git a/tests/ref/fate/h264-conformance-cvnlfi2_sony_h b/tests/ref/fate/h264-conformance-cvnlfi2_sony_h index 48d625e1cbb..c7128ba3369 100644 --- a/tests/ref/fate/h264-conformance-cvnlfi2_sony_h +++ b/tests/ref/fate/h264-conformance-cvnlfi2_sony_h @@ -3,20 +3,20 @@ #codec_id 0: rawvideo #dimensions 0: 720x480 #sar 0: 0/1 -0, 1, 1, 1, 518400, 0x0fbb4e71 -0, 2, 2, 1, 518400, 0xc46bec04 -0, 3, 3, 1, 518400, 0xc50ffc1d -0, 4, 4, 1, 518400, 0x684b07b7 -0, 5, 5, 1, 518400, 0xde799af0 -0, 6, 6, 1, 518400, 0xed497b27 -0, 7, 7, 1, 518400, 0x3e9d1e3a -0, 8, 8, 1, 518400, 0x154d3c5c -0, 9, 9, 1, 518400, 0x5257e37c -0, 10, 10, 1, 518400, 0x6e15139a -0, 11, 11, 1, 518400, 0x5dc39c59 -0, 12, 12, 1, 518400, 0xe1803100 -0, 13, 13, 1, 518400, 0xb4d4d535 -0, 14, 14, 1, 518400, 0x7a97a25d -0, 15, 15, 1, 518400, 0xf86b8923 -0, 16, 16, 1, 518400, 0x3355be98 -0, 17, 17, 1, 518400, 0x8f555830 +0, 0, 0, 1, 518400, 0x0fbb4e71 +0, 1, 1, 1, 518400, 0xc46bec04 +0, 2, 2, 1, 518400, 0xc50ffc1d +0, 3, 3, 1, 518400, 0x684b07b7 +0, 4, 4, 1, 518400, 0xde799af0 +0, 5, 5, 1, 518400, 0xed497b27 +0, 6, 6, 1, 518400, 0x3e9d1e3a +0, 7, 7, 1, 518400, 0x154d3c5c +0, 8, 8, 1, 518400, 0x5257e37c +0, 9, 9, 1, 518400, 0x6e15139a +0, 10, 10, 1, 518400, 0x5dc39c59 +0, 11, 11, 1, 518400, 0xe1803100 +0, 12, 12, 1, 518400, 0xb4d4d535 +0, 13, 13, 1, 518400, 0x7a97a25d +0, 14, 14, 1, 518400, 0xf86b8923 +0, 15, 15, 1, 518400, 0x3355be98 +0, 16, 16, 1, 518400, 0x8f555830 diff --git a/tests/ref/fate/h264-conformance-cvpa1_toshiba_b b/tests/ref/fate/h264-conformance-cvpa1_toshiba_b index fb4104f18d0..6bf9ee39346 100644 --- a/tests/ref/fate/h264-conformance-cvpa1_toshiba_b +++ b/tests/ref/fate/h264-conformance-cvpa1_toshiba_b @@ -3,93 +3,93 @@ #codec_id 0: rawvideo #dimensions 0: 352x288 #sar 0: 0/1 -0, 1, 1, 1, 152064, 0x128cd77a -0, 2, 2, 1, 152064, 0x565b9fc1 -0, 3, 3, 1, 152064, 0xbe322679 -0, 4, 4, 1, 152064, 0x0ea4238f -0, 5, 5, 1, 152064, 0x1e08fb3c -0, 6, 6, 1, 152064, 0x6da3a93c -0, 7, 7, 1, 152064, 0x75e5b181 -0, 8, 8, 1, 152064, 0xa0b39334 -0, 9, 9, 1, 152064, 0xa0d10d6d -0, 10, 10, 1, 152064, 0x33842bcb -0, 11, 11, 1, 152064, 0x9a74e1e4 -0, 12, 12, 1, 152064, 0xc2037244 -0, 13, 13, 1, 152064, 0x364b8ae4 -0, 14, 14, 1, 152064, 0x18c04971 -0, 15, 15, 1, 152064, 0x7234ecb5 -0, 16, 16, 1, 152064, 0x3719f8bc -0, 17, 17, 1, 152064, 0x1285ead1 -0, 18, 18, 1, 152064, 0xd3bfab18 -0, 19, 19, 1, 152064, 0x898111e2 -0, 20, 20, 1, 152064, 0x681c15fc -0, 21, 21, 1, 152064, 0x8e501572 -0, 22, 22, 1, 152064, 0xd7c838be -0, 23, 23, 1, 152064, 0xede424b2 -0, 24, 24, 1, 152064, 0xcfc20240 -0, 25, 25, 1, 152064, 0x13992e86 -0, 26, 26, 1, 152064, 0x56fb251a -0, 27, 27, 1, 152064, 0xee9be320 -0, 28, 28, 1, 152064, 0xea650153 -0, 29, 29, 1, 152064, 0x2cb6dabe -0, 30, 30, 1, 152064, 0xf44fa4b5 -0, 31, 31, 1, 152064, 0xdac2adff -0, 32, 32, 1, 152064, 0x9e15a1dc -0, 33, 33, 1, 152064, 0x28d00970 -0, 34, 34, 1, 152064, 0xe4277347 -0, 35, 35, 1, 152064, 0xebd25ad1 -0, 36, 36, 1, 152064, 0x029402da -0, 37, 37, 1, 152064, 0x1a2311ef -0, 38, 38, 1, 152064, 0xb86bf96a -0, 39, 39, 1, 152064, 0x67d7a5b0 -0, 40, 40, 1, 152064, 0x573abc2d -0, 41, 41, 1, 152064, 0xbe97dec0 -0, 42, 42, 1, 152064, 0x592b91a4 -0, 43, 43, 1, 152064, 0x9adda65e -0, 44, 44, 1, 152064, 0x0354b2cb -0, 45, 45, 1, 152064, 0x91e27ff9 -0, 46, 46, 1, 152064, 0x389f8625 -0, 47, 47, 1, 152064, 0x90175850 -0, 48, 48, 1, 152064, 0x2d36c427 -0, 49, 49, 1, 152064, 0xc0dd14ab -0, 50, 50, 1, 152064, 0xd49bf131 -0, 51, 51, 1, 152064, 0x0d4a9b92 -0, 52, 52, 1, 152064, 0xae9bb2f1 -0, 53, 53, 1, 152064, 0x36847ade -0, 54, 54, 1, 152064, 0x74810382 -0, 55, 55, 1, 152064, 0xc56d1d9f -0, 56, 56, 1, 152064, 0xcfefe3ae -0, 57, 57, 1, 152064, 0xeaa39353 -0, 58, 58, 1, 152064, 0x14289aef -0, 59, 59, 1, 152064, 0x74ba8f3b -0, 60, 60, 1, 152064, 0xdcaa518d -0, 61, 61, 1, 152064, 0x6e4881c2 -0, 62, 62, 1, 152064, 0xa4db767d -0, 63, 63, 1, 152064, 0x239b0b19 -0, 64, 64, 1, 152064, 0x5d054236 -0, 65, 65, 1, 152064, 0x6f392d7c -0, 66, 66, 1, 152064, 0x5c2af146 -0, 67, 67, 1, 152064, 0x26b439af -0, 68, 68, 1, 152064, 0xba7043ab -0, 69, 69, 1, 152064, 0x0816000c -0, 70, 70, 1, 152064, 0x3a713c05 -0, 71, 71, 1, 152064, 0xb3111f6d -0, 72, 72, 1, 152064, 0xdbf8dae2 -0, 73, 73, 1, 152064, 0x09ddf22e -0, 74, 74, 1, 152064, 0x8871fa7e -0, 75, 75, 1, 152064, 0x9f5db7a1 -0, 76, 76, 1, 152064, 0xcc38f225 -0, 77, 77, 1, 152064, 0xa1d18df9 -0, 78, 78, 1, 152064, 0x9b1c5d6a -0, 79, 79, 1, 152064, 0x9f2bc696 -0, 80, 80, 1, 152064, 0xc39bd11a -0, 81, 81, 1, 152064, 0x4ceca7d0 -0, 82, 82, 1, 152064, 0x63a60f1d -0, 83, 83, 1, 152064, 0x4cd31f28 -0, 84, 84, 1, 152064, 0x9c9af5d1 -0, 85, 85, 1, 152064, 0x6def65fc -0, 86, 86, 1, 152064, 0x1011466d -0, 87, 87, 1, 152064, 0xfeca406d -0, 88, 88, 1, 152064, 0xd1ca8a1e -0, 89, 89, 1, 152064, 0x30caa195 -0, 90, 90, 1, 152064, 0x31a09a48 +0, 0, 0, 1, 152064, 0x128cd77a +0, 1, 1, 1, 152064, 0x565b9fc1 +0, 2, 2, 1, 152064, 0xbe322679 +0, 3, 3, 1, 152064, 0x0ea4238f +0, 4, 4, 1, 152064, 0x1e08fb3c +0, 5, 5, 1, 152064, 0x6da3a93c +0, 6, 6, 1, 152064, 0x75e5b181 +0, 7, 7, 1, 152064, 0xa0b39334 +0, 8, 8, 1, 152064, 0xa0d10d6d +0, 9, 9, 1, 152064, 0x33842bcb +0, 10, 10, 1, 152064, 0x9a74e1e4 +0, 11, 11, 1, 152064, 0xc2037244 +0, 12, 12, 1, 152064, 0x364b8ae4 +0, 13, 13, 1, 152064, 0x18c04971 +0, 14, 14, 1, 152064, 0x7234ecb5 +0, 15, 15, 1, 152064, 0x3719f8bc +0, 16, 16, 1, 152064, 0x1285ead1 +0, 17, 17, 1, 152064, 0xd3bfab18 +0, 18, 18, 1, 152064, 0x898111e2 +0, 19, 19, 1, 152064, 0x681c15fc +0, 20, 20, 1, 152064, 0x8e501572 +0, 21, 21, 1, 152064, 0xd7c838be +0, 22, 22, 1, 152064, 0xede424b2 +0, 23, 23, 1, 152064, 0xcfc20240 +0, 24, 24, 1, 152064, 0x13992e86 +0, 25, 25, 1, 152064, 0x56fb251a +0, 26, 26, 1, 152064, 0xee9be320 +0, 27, 27, 1, 152064, 0xea650153 +0, 28, 28, 1, 152064, 0x2cb6dabe +0, 29, 29, 1, 152064, 0xf44fa4b5 +0, 30, 30, 1, 152064, 0xdac2adff +0, 31, 31, 1, 152064, 0x9e15a1dc +0, 32, 32, 1, 152064, 0x28d00970 +0, 33, 33, 1, 152064, 0xe4277347 +0, 34, 34, 1, 152064, 0xebd25ad1 +0, 35, 35, 1, 152064, 0x029402da +0, 36, 36, 1, 152064, 0x1a2311ef +0, 37, 37, 1, 152064, 0xb86bf96a +0, 38, 38, 1, 152064, 0x67d7a5b0 +0, 39, 39, 1, 152064, 0x573abc2d +0, 40, 40, 1, 152064, 0xbe97dec0 +0, 41, 41, 1, 152064, 0x592b91a4 +0, 42, 42, 1, 152064, 0x9adda65e +0, 43, 43, 1, 152064, 0x0354b2cb +0, 44, 44, 1, 152064, 0x91e27ff9 +0, 45, 45, 1, 152064, 0x389f8625 +0, 46, 46, 1, 152064, 0x90175850 +0, 47, 47, 1, 152064, 0x2d36c427 +0, 48, 48, 1, 152064, 0xc0dd14ab +0, 49, 49, 1, 152064, 0xd49bf131 +0, 50, 50, 1, 152064, 0x0d4a9b92 +0, 51, 51, 1, 152064, 0xae9bb2f1 +0, 52, 52, 1, 152064, 0x36847ade +0, 53, 53, 1, 152064, 0x74810382 +0, 54, 54, 1, 152064, 0xc56d1d9f +0, 55, 55, 1, 152064, 0xcfefe3ae +0, 56, 56, 1, 152064, 0xeaa39353 +0, 57, 57, 1, 152064, 0x14289aef +0, 58, 58, 1, 152064, 0x74ba8f3b +0, 59, 59, 1, 152064, 0xdcaa518d +0, 60, 60, 1, 152064, 0x6e4881c2 +0, 61, 61, 1, 152064, 0xa4db767d +0, 62, 62, 1, 152064, 0x239b0b19 +0, 63, 63, 1, 152064, 0x5d054236 +0, 64, 64, 1, 152064, 0x6f392d7c +0, 65, 65, 1, 152064, 0x5c2af146 +0, 66, 66, 1, 152064, 0x26b439af +0, 67, 67, 1, 152064, 0xba7043ab +0, 68, 68, 1, 152064, 0x0816000c +0, 69, 69, 1, 152064, 0x3a713c05 +0, 70, 70, 1, 152064, 0xb3111f6d +0, 71, 71, 1, 152064, 0xdbf8dae2 +0, 72, 72, 1, 152064, 0x09ddf22e +0, 73, 73, 1, 152064, 0x8871fa7e +0, 74, 74, 1, 152064, 0x9f5db7a1 +0, 75, 75, 1, 152064, 0xcc38f225 +0, 76, 76, 1, 152064, 0xa1d18df9 +0, 77, 77, 1, 152064, 0x9b1c5d6a +0, 78, 78, 1, 152064, 0x9f2bc696 +0, 79, 79, 1, 152064, 0xc39bd11a +0, 80, 80, 1, 152064, 0x4ceca7d0 +0, 81, 81, 1, 152064, 0x63a60f1d +0, 82, 82, 1, 152064, 0x4cd31f28 +0, 83, 83, 1, 152064, 0x9c9af5d1 +0, 84, 84, 1, 152064, 0x6def65fc +0, 85, 85, 1, 152064, 0x1011466d +0, 86, 86, 1, 152064, 0xfeca406d +0, 87, 87, 1, 152064, 0xd1ca8a1e +0, 88, 88, 1, 152064, 0x30caa195 +0, 89, 89, 1, 152064, 0x31a09a48 diff --git a/tests/ref/fate/h264-conformance-fi1_sony_e b/tests/ref/fate/h264-conformance-fi1_sony_e index 4b3dedce5c3..c48306679c9 100644 --- a/tests/ref/fate/h264-conformance-fi1_sony_e +++ b/tests/ref/fate/h264-conformance-fi1_sony_e @@ -3,20 +3,20 @@ #codec_id 0: rawvideo #dimensions 0: 192x128 #sar 0: 0/1 -0, 1, 1, 1, 36864, 0x3d54d3e3 -0, 2, 2, 1, 36864, 0xa9573ef0 -0, 3, 3, 1, 36864, 0x0ea5f263 -0, 4, 4, 1, 36864, 0x5a849fb9 -0, 5, 5, 1, 36864, 0x7ddb1eff -0, 6, 6, 1, 36864, 0x5e73e3b7 -0, 7, 7, 1, 36864, 0x7d50d329 -0, 8, 8, 1, 36864, 0xf2c2cd27 -0, 9, 9, 1, 36864, 0xdf4f4628 -0, 10, 10, 1, 36864, 0xddd6d5be -0, 11, 11, 1, 36864, 0xb530e1aa -0, 12, 12, 1, 36864, 0xeca42470 -0, 13, 13, 1, 36864, 0xa5701caf -0, 14, 14, 1, 36864, 0x6f5d28fc -0, 15, 15, 1, 36864, 0xd4ab4ab2 -0, 16, 16, 1, 36864, 0xf2dfcc22 -0, 17, 17, 1, 36864, 0xcaa87e79 +0, 0, 0, 1, 36864, 0x3d54d3e3 +0, 1, 1, 1, 36864, 0xa9573ef0 +0, 2, 2, 1, 36864, 0x0ea5f263 +0, 3, 3, 1, 36864, 0x5a849fb9 +0, 4, 4, 1, 36864, 0x7ddb1eff +0, 5, 5, 1, 36864, 0x5e73e3b7 +0, 6, 6, 1, 36864, 0x7d50d329 +0, 7, 7, 1, 36864, 0xf2c2cd27 +0, 8, 8, 1, 36864, 0xdf4f4628 +0, 9, 9, 1, 36864, 0xddd6d5be +0, 10, 10, 1, 36864, 0xb530e1aa +0, 11, 11, 1, 36864, 0xeca42470 +0, 12, 12, 1, 36864, 0xa5701caf +0, 13, 13, 1, 36864, 0x6f5d28fc +0, 14, 14, 1, 36864, 0xd4ab4ab2 +0, 15, 15, 1, 36864, 0xf2dfcc22 +0, 16, 16, 1, 36864, 0xcaa87e79 diff --git a/tests/ref/fate/h264-conformance-frext-bcrm_freh10 b/tests/ref/fate/h264-conformance-frext-bcrm_freh10 index 4e41aa6cdcb..7592f6c5169 100644 --- a/tests/ref/fate/h264-conformance-frext-bcrm_freh10 +++ b/tests/ref/fate/h264-conformance-frext-bcrm_freh10 @@ -3,103 +3,103 @@ #codec_id 0: rawvideo #dimensions 0: 352x288 #sar 0: 0/1 -0, 1, 1, 1, 152064, 0xbdc2b880 -0, 2, 2, 1, 152064, 0x4ebf93fe -0, 3, 3, 1, 152064, 0xe30d6871 -0, 4, 4, 1, 152064, 0x04f46b9b -0, 5, 5, 1, 152064, 0xd7dd219a -0, 6, 6, 1, 152064, 0x02fc6511 -0, 7, 7, 1, 152064, 0x98868faa -0, 8, 8, 1, 152064, 0x54b94f92 -0, 9, 9, 1, 152064, 0xe3b6be4b -0, 10, 10, 1, 152064, 0xf148cf10 -0, 11, 11, 1, 152064, 0xda3239b8 -0, 12, 12, 1, 152064, 0x6c5d7331 -0, 13, 13, 1, 152064, 0x825f1fea -0, 14, 14, 1, 152064, 0x47791056 -0, 15, 15, 1, 152064, 0xc08e8a58 -0, 16, 16, 1, 152064, 0x020299f3 -0, 17, 17, 1, 152064, 0x0dfd4457 -0, 18, 18, 1, 152064, 0xcf005e68 -0, 19, 19, 1, 152064, 0x1f9e2c32 -0, 20, 20, 1, 152064, 0xa8359324 -0, 21, 21, 1, 152064, 0x4b03752d -0, 22, 22, 1, 152064, 0xd6281621 -0, 23, 23, 1, 152064, 0xc97ac928 -0, 24, 24, 1, 152064, 0xded90dcd -0, 25, 25, 1, 152064, 0xd6883255 -0, 26, 26, 1, 152064, 0x6edb4d4f -0, 27, 27, 1, 152064, 0xd6f93a80 -0, 28, 28, 1, 152064, 0x163d6153 -0, 29, 29, 1, 152064, 0x04b90c06 -0, 30, 30, 1, 152064, 0xee8730c1 -0, 31, 31, 1, 152064, 0xd5f5c669 -0, 32, 32, 1, 152064, 0xcc600b1f -0, 33, 33, 1, 152064, 0x15ddde03 -0, 34, 34, 1, 152064, 0xd0388dd0 -0, 35, 35, 1, 152064, 0xa292ab7d -0, 36, 36, 1, 152064, 0xacf584e9 -0, 37, 37, 1, 152064, 0xcef42714 -0, 38, 38, 1, 152064, 0xeb162f35 -0, 39, 39, 1, 152064, 0x0a07de7b -0, 40, 40, 1, 152064, 0x7ae76c81 -0, 41, 41, 1, 152064, 0x139c8fda -0, 42, 42, 1, 152064, 0x43724411 -0, 43, 43, 1, 152064, 0x07b2ddea -0, 44, 44, 1, 152064, 0x831a1cc7 -0, 45, 45, 1, 152064, 0x092f5073 -0, 46, 46, 1, 152064, 0xe5b6d380 -0, 47, 47, 1, 152064, 0xdd30d69e -0, 48, 48, 1, 152064, 0x887020b2 -0, 49, 49, 1, 152064, 0x84436510 -0, 50, 50, 1, 152064, 0x49f63606 -0, 51, 51, 1, 152064, 0x6b96e959 -0, 52, 52, 1, 152064, 0xc6247cc7 -0, 53, 53, 1, 152064, 0x7a67c532 -0, 54, 54, 1, 152064, 0x93f4c476 -0, 55, 55, 1, 152064, 0x3c119654 -0, 56, 56, 1, 152064, 0xa45f7c72 -0, 57, 57, 1, 152064, 0x2ac50cb0 -0, 58, 58, 1, 152064, 0x9bf16d06 -0, 59, 59, 1, 152064, 0xfa0750d9 -0, 60, 60, 1, 152064, 0x02197630 -0, 61, 61, 1, 152064, 0x6d44f9b5 -0, 62, 62, 1, 152064, 0x86b211f5 -0, 63, 63, 1, 152064, 0xf4fda5d0 -0, 64, 64, 1, 152064, 0x36f840a7 -0, 65, 65, 1, 152064, 0x42412992 -0, 66, 66, 1, 152064, 0xd0c9ba37 -0, 67, 67, 1, 152064, 0xc40eba62 -0, 68, 68, 1, 152064, 0x2d093b53 -0, 69, 69, 1, 152064, 0xee39c69c -0, 70, 70, 1, 152064, 0xcbbf8968 -0, 71, 71, 1, 152064, 0xfddc1704 -0, 72, 72, 1, 152064, 0x8dc47c61 -0, 73, 73, 1, 152064, 0xf15580bf -0, 74, 74, 1, 152064, 0x9c71a8b0 -0, 75, 75, 1, 152064, 0x19b90b9f -0, 76, 76, 1, 152064, 0xb65ae287 -0, 77, 77, 1, 152064, 0xf265693d -0, 78, 78, 1, 152064, 0x721714a1 -0, 79, 79, 1, 152064, 0x383e8ac5 -0, 80, 80, 1, 152064, 0x02558677 -0, 81, 81, 1, 152064, 0xdaab3cdf -0, 82, 82, 1, 152064, 0xc939a2f6 -0, 83, 83, 1, 152064, 0x977afa7f -0, 84, 84, 1, 152064, 0xe5e65f35 -0, 85, 85, 1, 152064, 0x247546fa -0, 86, 86, 1, 152064, 0x49ff2094 -0, 87, 87, 1, 152064, 0x9fd58cda -0, 88, 88, 1, 152064, 0x3e31b6e3 -0, 89, 89, 1, 152064, 0x75c6d796 -0, 90, 90, 1, 152064, 0x4ab3e7bb -0, 91, 91, 1, 152064, 0x393935ea -0, 92, 92, 1, 152064, 0xc8e62905 -0, 93, 93, 1, 152064, 0xbb149e61 -0, 94, 94, 1, 152064, 0x2553c4c5 -0, 95, 95, 1, 152064, 0x7f82a8b4 -0, 96, 96, 1, 152064, 0x26ef31e6 -0, 97, 97, 1, 152064, 0xf029744a -0, 98, 98, 1, 152064, 0x0a6f191a -0, 99, 99, 1, 152064, 0x55808643 -0, 100, 100, 1, 152064, 0x27576172 +0, 0, 0, 1, 152064, 0xbdc2b880 +0, 1, 1, 1, 152064, 0x4ebf93fe +0, 2, 2, 1, 152064, 0xe30d6871 +0, 3, 3, 1, 152064, 0x04f46b9b +0, 4, 4, 1, 152064, 0xd7dd219a +0, 5, 5, 1, 152064, 0x02fc6511 +0, 6, 6, 1, 152064, 0x98868faa +0, 7, 7, 1, 152064, 0x54b94f92 +0, 8, 8, 1, 152064, 0xe3b6be4b +0, 9, 9, 1, 152064, 0xf148cf10 +0, 10, 10, 1, 152064, 0xda3239b8 +0, 11, 11, 1, 152064, 0x6c5d7331 +0, 12, 12, 1, 152064, 0x825f1fea +0, 13, 13, 1, 152064, 0x47791056 +0, 14, 14, 1, 152064, 0xc08e8a58 +0, 15, 15, 1, 152064, 0x020299f3 +0, 16, 16, 1, 152064, 0x0dfd4457 +0, 17, 17, 1, 152064, 0xcf005e68 +0, 18, 18, 1, 152064, 0x1f9e2c32 +0, 19, 19, 1, 152064, 0xa8359324 +0, 20, 20, 1, 152064, 0x4b03752d +0, 21, 21, 1, 152064, 0xd6281621 +0, 22, 22, 1, 152064, 0xc97ac928 +0, 23, 23, 1, 152064, 0xded90dcd +0, 24, 24, 1, 152064, 0xd6883255 +0, 25, 25, 1, 152064, 0x6edb4d4f +0, 26, 26, 1, 152064, 0xd6f93a80 +0, 27, 27, 1, 152064, 0x163d6153 +0, 28, 28, 1, 152064, 0x04b90c06 +0, 29, 29, 1, 152064, 0xee8730c1 +0, 30, 30, 1, 152064, 0xd5f5c669 +0, 31, 31, 1, 152064, 0xcc600b1f +0, 32, 32, 1, 152064, 0x15ddde03 +0, 33, 33, 1, 152064, 0xd0388dd0 +0, 34, 34, 1, 152064, 0xa292ab7d +0, 35, 35, 1, 152064, 0xacf584e9 +0, 36, 36, 1, 152064, 0xcef42714 +0, 37, 37, 1, 152064, 0xeb162f35 +0, 38, 38, 1, 152064, 0x0a07de7b +0, 39, 39, 1, 152064, 0x7ae76c81 +0, 40, 40, 1, 152064, 0x139c8fda +0, 41, 41, 1, 152064, 0x43724411 +0, 42, 42, 1, 152064, 0x07b2ddea +0, 43, 43, 1, 152064, 0x831a1cc7 +0, 44, 44, 1, 152064, 0x092f5073 +0, 45, 45, 1, 152064, 0xe5b6d380 +0, 46, 46, 1, 152064, 0xdd30d69e +0, 47, 47, 1, 152064, 0x887020b2 +0, 48, 48, 1, 152064, 0x84436510 +0, 49, 49, 1, 152064, 0x49f63606 +0, 50, 50, 1, 152064, 0x6b96e959 +0, 51, 51, 1, 152064, 0xc6247cc7 +0, 52, 52, 1, 152064, 0x7a67c532 +0, 53, 53, 1, 152064, 0x93f4c476 +0, 54, 54, 1, 152064, 0x3c119654 +0, 55, 55, 1, 152064, 0xa45f7c72 +0, 56, 56, 1, 152064, 0x2ac50cb0 +0, 57, 57, 1, 152064, 0x9bf16d06 +0, 58, 58, 1, 152064, 0xfa0750d9 +0, 59, 59, 1, 152064, 0x02197630 +0, 60, 60, 1, 152064, 0x6d44f9b5 +0, 61, 61, 1, 152064, 0x86b211f5 +0, 62, 62, 1, 152064, 0xf4fda5d0 +0, 63, 63, 1, 152064, 0x36f840a7 +0, 64, 64, 1, 152064, 0x42412992 +0, 65, 65, 1, 152064, 0xd0c9ba37 +0, 66, 66, 1, 152064, 0xc40eba62 +0, 67, 67, 1, 152064, 0x2d093b53 +0, 68, 68, 1, 152064, 0xee39c69c +0, 69, 69, 1, 152064, 0xcbbf8968 +0, 70, 70, 1, 152064, 0xfddc1704 +0, 71, 71, 1, 152064, 0x8dc47c61 +0, 72, 72, 1, 152064, 0xf15580bf +0, 73, 73, 1, 152064, 0x9c71a8b0 +0, 74, 74, 1, 152064, 0x19b90b9f +0, 75, 75, 1, 152064, 0xb65ae287 +0, 76, 76, 1, 152064, 0xf265693d +0, 77, 77, 1, 152064, 0x721714a1 +0, 78, 78, 1, 152064, 0x383e8ac5 +0, 79, 79, 1, 152064, 0x02558677 +0, 80, 80, 1, 152064, 0xdaab3cdf +0, 81, 81, 1, 152064, 0xc939a2f6 +0, 82, 82, 1, 152064, 0x977afa7f +0, 83, 83, 1, 152064, 0xe5e65f35 +0, 84, 84, 1, 152064, 0x247546fa +0, 85, 85, 1, 152064, 0x49ff2094 +0, 86, 86, 1, 152064, 0x9fd58cda +0, 87, 87, 1, 152064, 0x3e31b6e3 +0, 88, 88, 1, 152064, 0x75c6d796 +0, 89, 89, 1, 152064, 0x4ab3e7bb +0, 90, 90, 1, 152064, 0x393935ea +0, 91, 91, 1, 152064, 0xc8e62905 +0, 92, 92, 1, 152064, 0xbb149e61 +0, 93, 93, 1, 152064, 0x2553c4c5 +0, 94, 94, 1, 152064, 0x7f82a8b4 +0, 95, 95, 1, 152064, 0x26ef31e6 +0, 96, 96, 1, 152064, 0xf029744a +0, 97, 97, 1, 152064, 0x0a6f191a +0, 98, 98, 1, 152064, 0x55808643 +0, 99, 99, 1, 152064, 0x27576172 diff --git a/tests/ref/fate/h264-conformance-frext-brcm_freh11 b/tests/ref/fate/h264-conformance-frext-brcm_freh11 index 1ba3b7e1810..5bb9aa447e4 100644 --- a/tests/ref/fate/h264-conformance-frext-brcm_freh11 +++ b/tests/ref/fate/h264-conformance-frext-brcm_freh11 @@ -3,103 +3,103 @@ #codec_id 0: rawvideo #dimensions 0: 352x288 #sar 0: 0/1 -0, 1, 1, 1, 152064, 0x9744ac59 -0, 2, 2, 1, 152064, 0x3eba88bf -0, 3, 3, 1, 152064, 0xd4105c5a -0, 4, 4, 1, 152064, 0x452966a3 -0, 5, 5, 1, 152064, 0x30071add -0, 6, 6, 1, 152064, 0x0eb75245 -0, 7, 7, 1, 152064, 0x4daa80fa -0, 8, 8, 1, 152064, 0xf53a43a1 -0, 9, 9, 1, 152064, 0xa55ab43d -0, 10, 10, 1, 152064, 0x915ec82e -0, 11, 11, 1, 152064, 0xadce2f9a -0, 12, 12, 1, 152064, 0xf7a25715 -0, 13, 13, 1, 152064, 0x90c91c7d -0, 14, 14, 1, 152064, 0x4f0df4ef -0, 15, 15, 1, 152064, 0xf6e0783c -0, 16, 16, 1, 152064, 0x417c8ca8 -0, 17, 17, 1, 152064, 0xd33d29d8 -0, 18, 18, 1, 152064, 0xc9723fa3 -0, 19, 19, 1, 152064, 0x3e4f22f4 -0, 20, 20, 1, 152064, 0xd5aa7bd8 -0, 21, 21, 1, 152064, 0x2a425b54 -0, 22, 22, 1, 152064, 0x2d400788 -0, 23, 23, 1, 152064, 0x12fab3a4 -0, 24, 24, 1, 152064, 0x5544f881 -0, 25, 25, 1, 152064, 0xd0612cc5 -0, 26, 26, 1, 152064, 0x157b3654 -0, 27, 27, 1, 152064, 0x04b61fe0 -0, 28, 28, 1, 152064, 0x897d600a -0, 29, 29, 1, 152064, 0x0d94fa29 -0, 30, 30, 1, 152064, 0xc0fe249d -0, 31, 31, 1, 152064, 0x65abc1d6 -0, 32, 32, 1, 152064, 0x2bd5f09d -0, 33, 33, 1, 152064, 0xd3eebd28 -0, 34, 34, 1, 152064, 0x93458649 -0, 35, 35, 1, 152064, 0x55e793a6 -0, 36, 36, 1, 152064, 0x9fc378ce -0, 37, 37, 1, 152064, 0x24c32731 -0, 38, 38, 1, 152064, 0x3c321c50 -0, 39, 39, 1, 152064, 0xcef3ca8b -0, 40, 40, 1, 152064, 0x97116676 -0, 41, 41, 1, 152064, 0x73ae78f6 -0, 42, 42, 1, 152064, 0xdeec219e -0, 43, 43, 1, 152064, 0xc061d584 -0, 44, 44, 1, 152064, 0xcf47f6c9 -0, 45, 45, 1, 152064, 0x280d3a2d -0, 46, 46, 1, 152064, 0xb660c846 -0, 47, 47, 1, 152064, 0xe167c588 -0, 48, 48, 1, 152064, 0x08f808de -0, 49, 49, 1, 152064, 0x9de65c0b -0, 50, 50, 1, 152064, 0xc52a1937 -0, 51, 51, 1, 152064, 0xf5a4d86f -0, 52, 52, 1, 152064, 0xbef86d37 -0, 53, 53, 1, 152064, 0xa227b21b -0, 54, 54, 1, 152064, 0x0601ad35 -0, 55, 55, 1, 152064, 0x15198730 -0, 56, 56, 1, 152064, 0x9af764c6 -0, 57, 57, 1, 152064, 0x1a95e99a -0, 58, 58, 1, 152064, 0x6bef5aa8 -0, 59, 59, 1, 152064, 0x92f03267 -0, 60, 60, 1, 152064, 0x0a3d56cb -0, 61, 61, 1, 152064, 0xd9c9f62e -0, 62, 62, 1, 152064, 0xcd81ea16 -0, 63, 63, 1, 152064, 0x8ed789c0 -0, 64, 64, 1, 152064, 0x5a5e356f -0, 65, 65, 1, 152064, 0x2f260ebf -0, 66, 66, 1, 152064, 0xa0379c89 -0, 67, 67, 1, 152064, 0x100cb40c -0, 68, 68, 1, 152064, 0xaad2220a -0, 69, 69, 1, 152064, 0xec82aa8d -0, 70, 70, 1, 152064, 0x91088303 -0, 71, 71, 1, 152064, 0x0cce0e9e -0, 72, 72, 1, 152064, 0xf3bc716a -0, 73, 73, 1, 152064, 0x989879c5 -0, 74, 74, 1, 152064, 0x491297a0 -0, 75, 75, 1, 152064, 0xdc16f30d -0, 76, 76, 1, 152064, 0xb9bfdd57 -0, 77, 77, 1, 152064, 0x5fba59c2 -0, 78, 78, 1, 152064, 0x89c40529 -0, 79, 79, 1, 152064, 0x1b3e7b54 -0, 80, 80, 1, 152064, 0x5d0d7903 -0, 81, 81, 1, 152064, 0x2e3434e1 -0, 82, 82, 1, 152064, 0x1f47a276 -0, 83, 83, 1, 152064, 0xa22de2b1 -0, 84, 84, 1, 152064, 0x77344844 -0, 85, 85, 1, 152064, 0x6a6b3fce -0, 86, 86, 1, 152064, 0x82660651 -0, 87, 87, 1, 152064, 0x51e67cc9 -0, 88, 88, 1, 152064, 0xb790ae51 -0, 89, 89, 1, 152064, 0x906bc6b6 -0, 90, 90, 1, 152064, 0x55c5dc21 -0, 91, 91, 1, 152064, 0xb51f3004 -0, 92, 92, 1, 152064, 0x68500a25 -0, 93, 93, 1, 152064, 0x5dbc812e -0, 94, 94, 1, 152064, 0x895eb6ed -0, 95, 95, 1, 152064, 0x2f5594fc -0, 96, 96, 1, 152064, 0x04a222a9 -0, 97, 97, 1, 152064, 0x90036f6a -0, 98, 98, 1, 152064, 0x8b8b064c -0, 99, 99, 1, 152064, 0xd47c7334 -0, 100, 100, 1, 152064, 0x13f06213 +0, 0, 0, 1, 152064, 0x9744ac59 +0, 1, 1, 1, 152064, 0x3eba88bf +0, 2, 2, 1, 152064, 0xd4105c5a +0, 3, 3, 1, 152064, 0x452966a3 +0, 4, 4, 1, 152064, 0x30071add +0, 5, 5, 1, 152064, 0x0eb75245 +0, 6, 6, 1, 152064, 0x4daa80fa +0, 7, 7, 1, 152064, 0xf53a43a1 +0, 8, 8, 1, 152064, 0xa55ab43d +0, 9, 9, 1, 152064, 0x915ec82e +0, 10, 10, 1, 152064, 0xadce2f9a +0, 11, 11, 1, 152064, 0xf7a25715 +0, 12, 12, 1, 152064, 0x90c91c7d +0, 13, 13, 1, 152064, 0x4f0df4ef +0, 14, 14, 1, 152064, 0xf6e0783c +0, 15, 15, 1, 152064, 0x417c8ca8 +0, 16, 16, 1, 152064, 0xd33d29d8 +0, 17, 17, 1, 152064, 0xc9723fa3 +0, 18, 18, 1, 152064, 0x3e4f22f4 +0, 19, 19, 1, 152064, 0xd5aa7bd8 +0, 20, 20, 1, 152064, 0x2a425b54 +0, 21, 21, 1, 152064, 0x2d400788 +0, 22, 22, 1, 152064, 0x12fab3a4 +0, 23, 23, 1, 152064, 0x5544f881 +0, 24, 24, 1, 152064, 0xd0612cc5 +0, 25, 25, 1, 152064, 0x157b3654 +0, 26, 26, 1, 152064, 0x04b61fe0 +0, 27, 27, 1, 152064, 0x897d600a +0, 28, 28, 1, 152064, 0x0d94fa29 +0, 29, 29, 1, 152064, 0xc0fe249d +0, 30, 30, 1, 152064, 0x65abc1d6 +0, 31, 31, 1, 152064, 0x2bd5f09d +0, 32, 32, 1, 152064, 0xd3eebd28 +0, 33, 33, 1, 152064, 0x93458649 +0, 34, 34, 1, 152064, 0x55e793a6 +0, 35, 35, 1, 152064, 0x9fc378ce +0, 36, 36, 1, 152064, 0x24c32731 +0, 37, 37, 1, 152064, 0x3c321c50 +0, 38, 38, 1, 152064, 0xcef3ca8b +0, 39, 39, 1, 152064, 0x97116676 +0, 40, 40, 1, 152064, 0x73ae78f6 +0, 41, 41, 1, 152064, 0xdeec219e +0, 42, 42, 1, 152064, 0xc061d584 +0, 43, 43, 1, 152064, 0xcf47f6c9 +0, 44, 44, 1, 152064, 0x280d3a2d +0, 45, 45, 1, 152064, 0xb660c846 +0, 46, 46, 1, 152064, 0xe167c588 +0, 47, 47, 1, 152064, 0x08f808de +0, 48, 48, 1, 152064, 0x9de65c0b +0, 49, 49, 1, 152064, 0xc52a1937 +0, 50, 50, 1, 152064, 0xf5a4d86f +0, 51, 51, 1, 152064, 0xbef86d37 +0, 52, 52, 1, 152064, 0xa227b21b +0, 53, 53, 1, 152064, 0x0601ad35 +0, 54, 54, 1, 152064, 0x15198730 +0, 55, 55, 1, 152064, 0x9af764c6 +0, 56, 56, 1, 152064, 0x1a95e99a +0, 57, 57, 1, 152064, 0x6bef5aa8 +0, 58, 58, 1, 152064, 0x92f03267 +0, 59, 59, 1, 152064, 0x0a3d56cb +0, 60, 60, 1, 152064, 0xd9c9f62e +0, 61, 61, 1, 152064, 0xcd81ea16 +0, 62, 62, 1, 152064, 0x8ed789c0 +0, 63, 63, 1, 152064, 0x5a5e356f +0, 64, 64, 1, 152064, 0x2f260ebf +0, 65, 65, 1, 152064, 0xa0379c89 +0, 66, 66, 1, 152064, 0x100cb40c +0, 67, 67, 1, 152064, 0xaad2220a +0, 68, 68, 1, 152064, 0xec82aa8d +0, 69, 69, 1, 152064, 0x91088303 +0, 70, 70, 1, 152064, 0x0cce0e9e +0, 71, 71, 1, 152064, 0xf3bc716a +0, 72, 72, 1, 152064, 0x989879c5 +0, 73, 73, 1, 152064, 0x491297a0 +0, 74, 74, 1, 152064, 0xdc16f30d +0, 75, 75, 1, 152064, 0xb9bfdd57 +0, 76, 76, 1, 152064, 0x5fba59c2 +0, 77, 77, 1, 152064, 0x89c40529 +0, 78, 78, 1, 152064, 0x1b3e7b54 +0, 79, 79, 1, 152064, 0x5d0d7903 +0, 80, 80, 1, 152064, 0x2e3434e1 +0, 81, 81, 1, 152064, 0x1f47a276 +0, 82, 82, 1, 152064, 0xa22de2b1 +0, 83, 83, 1, 152064, 0x77344844 +0, 84, 84, 1, 152064, 0x6a6b3fce +0, 85, 85, 1, 152064, 0x82660651 +0, 86, 86, 1, 152064, 0x51e67cc9 +0, 87, 87, 1, 152064, 0xb790ae51 +0, 88, 88, 1, 152064, 0x906bc6b6 +0, 89, 89, 1, 152064, 0x55c5dc21 +0, 90, 90, 1, 152064, 0xb51f3004 +0, 91, 91, 1, 152064, 0x68500a25 +0, 92, 92, 1, 152064, 0x5dbc812e +0, 93, 93, 1, 152064, 0x895eb6ed +0, 94, 94, 1, 152064, 0x2f5594fc +0, 95, 95, 1, 152064, 0x04a222a9 +0, 96, 96, 1, 152064, 0x90036f6a +0, 97, 97, 1, 152064, 0x8b8b064c +0, 98, 98, 1, 152064, 0xd47c7334 +0, 99, 99, 1, 152064, 0x13f06213 diff --git a/tests/ref/fate/h264-conformance-frext-brcm_freh4 b/tests/ref/fate/h264-conformance-frext-brcm_freh4 index 019df15b1de..9898def9fde 100644 --- a/tests/ref/fate/h264-conformance-frext-brcm_freh4 +++ b/tests/ref/fate/h264-conformance-frext-brcm_freh4 @@ -3,103 +3,103 @@ #codec_id 0: rawvideo #dimensions 0: 352x288 #sar 0: 0/1 -0, 1, 1, 1, 152064, 0x9744ac59 -0, 2, 2, 1, 152064, 0xe1c69d97 -0, 3, 3, 1, 152064, 0x9ae85f93 -0, 4, 4, 1, 152064, 0x452966a3 -0, 5, 5, 1, 152064, 0xe8192823 -0, 6, 6, 1, 152064, 0x58b764eb -0, 7, 7, 1, 152064, 0x51b686b1 -0, 8, 8, 1, 152064, 0x4bca5822 -0, 9, 9, 1, 152064, 0x29abc41c -0, 10, 10, 1, 152064, 0x850ec94f -0, 11, 11, 1, 152064, 0xac2c34f8 -0, 12, 12, 1, 152064, 0x080c6e67 -0, 13, 13, 1, 152064, 0x5e4e14d2 -0, 14, 14, 1, 152064, 0x978b054c -0, 15, 15, 1, 152064, 0x861d8c3c -0, 16, 16, 1, 152064, 0xe0818918 -0, 17, 17, 1, 152064, 0x8b834511 -0, 18, 18, 1, 152064, 0x223f567c -0, 19, 19, 1, 152064, 0x6d61298d -0, 20, 20, 1, 152064, 0xfe30826e -0, 21, 21, 1, 152064, 0x4bad4f98 -0, 22, 22, 1, 152064, 0x69d5fdca -0, 23, 23, 1, 152064, 0xe45bba1b -0, 24, 24, 1, 152064, 0xa6d81298 -0, 25, 25, 1, 152064, 0x7f3f2c91 -0, 26, 26, 1, 152064, 0x658754b9 -0, 27, 27, 1, 152064, 0x2c6d3eba -0, 28, 28, 1, 152064, 0x4500600c -0, 29, 29, 1, 152064, 0xa745f74b -0, 30, 30, 1, 152064, 0x2bf21fca -0, 31, 31, 1, 152064, 0x08b8bdb3 -0, 32, 32, 1, 152064, 0x5a9d0a8b -0, 33, 33, 1, 152064, 0x3a57d523 -0, 34, 34, 1, 152064, 0x3606826e -0, 35, 35, 1, 152064, 0x3b91a8fb -0, 36, 36, 1, 152064, 0x37c28959 -0, 37, 37, 1, 152064, 0xb51d1e75 -0, 38, 38, 1, 152064, 0x13be3f58 -0, 39, 39, 1, 152064, 0x0ed0e7cf -0, 40, 40, 1, 152064, 0x298560d4 -0, 41, 41, 1, 152064, 0x62b68373 -0, 42, 42, 1, 152064, 0xf8bb4520 -0, 43, 43, 1, 152064, 0x90dfd6af -0, 44, 44, 1, 152064, 0xf4770d20 -0, 45, 45, 1, 152064, 0x0d9549a0 -0, 46, 46, 1, 152064, 0x004eccb1 -0, 47, 47, 1, 152064, 0x3146d46b -0, 48, 48, 1, 152064, 0x078d1808 -0, 49, 49, 1, 152064, 0x5d8d60cd -0, 50, 50, 1, 152064, 0x8ff52dd8 -0, 51, 51, 1, 152064, 0x5aa3ccf7 -0, 52, 52, 1, 152064, 0x5bec6c39 -0, 53, 53, 1, 152064, 0xd44cae9d -0, 54, 54, 1, 152064, 0xa1b0a151 -0, 55, 55, 1, 152064, 0xe3be7bb2 -0, 56, 56, 1, 152064, 0x50096775 -0, 57, 57, 1, 152064, 0xdffff851 -0, 58, 58, 1, 152064, 0x1d7250eb -0, 59, 59, 1, 152064, 0x69663ca7 -0, 60, 60, 1, 152064, 0x62f77fc7 -0, 61, 61, 1, 152064, 0xbab8f471 -0, 62, 62, 1, 152064, 0x6af31785 -0, 63, 63, 1, 152064, 0xcbb2a9aa -0, 64, 64, 1, 152064, 0xc57c32b9 -0, 65, 65, 1, 152064, 0xecbe2ce0 -0, 66, 66, 1, 152064, 0x2fbebf81 -0, 67, 67, 1, 152064, 0xa168af68 -0, 68, 68, 1, 152064, 0x1e5631ac -0, 69, 69, 1, 152064, 0xe69fc927 -0, 70, 70, 1, 152064, 0x8e5c81d8 -0, 71, 71, 1, 152064, 0x42402010 -0, 72, 72, 1, 152064, 0xd7267482 -0, 73, 73, 1, 152064, 0x64b280df -0, 74, 74, 1, 152064, 0xc4cbafcc -0, 75, 75, 1, 152064, 0xcf2f1e8b -0, 76, 76, 1, 152064, 0x4d6fdb3f -0, 77, 77, 1, 152064, 0xf22d6fed -0, 78, 78, 1, 152064, 0x625b167c -0, 79, 79, 1, 152064, 0x41348089 -0, 80, 80, 1, 152064, 0x6db2779b -0, 81, 81, 1, 152064, 0xe87030a8 -0, 82, 82, 1, 152064, 0x91b29cdd -0, 83, 83, 1, 152064, 0xe824f242 -0, 84, 84, 1, 152064, 0xac995380 -0, 85, 85, 1, 152064, 0x7efe361b -0, 86, 86, 1, 152064, 0xe10c0c26 -0, 87, 87, 1, 152064, 0x93108260 -0, 88, 88, 1, 152064, 0xbf4caed7 -0, 89, 89, 1, 152064, 0xb6a4d826 -0, 90, 90, 1, 152064, 0x78beea4e -0, 91, 91, 1, 152064, 0xdf612df9 -0, 92, 92, 1, 152064, 0xa9ef2830 -0, 93, 93, 1, 152064, 0x06448895 -0, 94, 94, 1, 152064, 0x332eb6d5 -0, 95, 95, 1, 152064, 0x935ba2c5 -0, 96, 96, 1, 152064, 0x62a22656 -0, 97, 97, 1, 152064, 0x06a670a7 -0, 98, 98, 1, 152064, 0xf60b1af0 -0, 99, 99, 1, 152064, 0x85177c10 -0, 100, 100, 1, 152064, 0x5e4e5c4b +0, 0, 0, 1, 152064, 0x9744ac59 +0, 1, 1, 1, 152064, 0xe1c69d97 +0, 2, 2, 1, 152064, 0x9ae85f93 +0, 3, 3, 1, 152064, 0x452966a3 +0, 4, 4, 1, 152064, 0xe8192823 +0, 5, 5, 1, 152064, 0x58b764eb +0, 6, 6, 1, 152064, 0x51b686b1 +0, 7, 7, 1, 152064, 0x4bca5822 +0, 8, 8, 1, 152064, 0x29abc41c +0, 9, 9, 1, 152064, 0x850ec94f +0, 10, 10, 1, 152064, 0xac2c34f8 +0, 11, 11, 1, 152064, 0x080c6e67 +0, 12, 12, 1, 152064, 0x5e4e14d2 +0, 13, 13, 1, 152064, 0x978b054c +0, 14, 14, 1, 152064, 0x861d8c3c +0, 15, 15, 1, 152064, 0xe0818918 +0, 16, 16, 1, 152064, 0x8b834511 +0, 17, 17, 1, 152064, 0x223f567c +0, 18, 18, 1, 152064, 0x6d61298d +0, 19, 19, 1, 152064, 0xfe30826e +0, 20, 20, 1, 152064, 0x4bad4f98 +0, 21, 21, 1, 152064, 0x69d5fdca +0, 22, 22, 1, 152064, 0xe45bba1b +0, 23, 23, 1, 152064, 0xa6d81298 +0, 24, 24, 1, 152064, 0x7f3f2c91 +0, 25, 25, 1, 152064, 0x658754b9 +0, 26, 26, 1, 152064, 0x2c6d3eba +0, 27, 27, 1, 152064, 0x4500600c +0, 28, 28, 1, 152064, 0xa745f74b +0, 29, 29, 1, 152064, 0x2bf21fca +0, 30, 30, 1, 152064, 0x08b8bdb3 +0, 31, 31, 1, 152064, 0x5a9d0a8b +0, 32, 32, 1, 152064, 0x3a57d523 +0, 33, 33, 1, 152064, 0x3606826e +0, 34, 34, 1, 152064, 0x3b91a8fb +0, 35, 35, 1, 152064, 0x37c28959 +0, 36, 36, 1, 152064, 0xb51d1e75 +0, 37, 37, 1, 152064, 0x13be3f58 +0, 38, 38, 1, 152064, 0x0ed0e7cf +0, 39, 39, 1, 152064, 0x298560d4 +0, 40, 40, 1, 152064, 0x62b68373 +0, 41, 41, 1, 152064, 0xf8bb4520 +0, 42, 42, 1, 152064, 0x90dfd6af +0, 43, 43, 1, 152064, 0xf4770d20 +0, 44, 44, 1, 152064, 0x0d9549a0 +0, 45, 45, 1, 152064, 0x004eccb1 +0, 46, 46, 1, 152064, 0x3146d46b +0, 47, 47, 1, 152064, 0x078d1808 +0, 48, 48, 1, 152064, 0x5d8d60cd +0, 49, 49, 1, 152064, 0x8ff52dd8 +0, 50, 50, 1, 152064, 0x5aa3ccf7 +0, 51, 51, 1, 152064, 0x5bec6c39 +0, 52, 52, 1, 152064, 0xd44cae9d +0, 53, 53, 1, 152064, 0xa1b0a151 +0, 54, 54, 1, 152064, 0xe3be7bb2 +0, 55, 55, 1, 152064, 0x50096775 +0, 56, 56, 1, 152064, 0xdffff851 +0, 57, 57, 1, 152064, 0x1d7250eb +0, 58, 58, 1, 152064, 0x69663ca7 +0, 59, 59, 1, 152064, 0x62f77fc7 +0, 60, 60, 1, 152064, 0xbab8f471 +0, 61, 61, 1, 152064, 0x6af31785 +0, 62, 62, 1, 152064, 0xcbb2a9aa +0, 63, 63, 1, 152064, 0xc57c32b9 +0, 64, 64, 1, 152064, 0xecbe2ce0 +0, 65, 65, 1, 152064, 0x2fbebf81 +0, 66, 66, 1, 152064, 0xa168af68 +0, 67, 67, 1, 152064, 0x1e5631ac +0, 68, 68, 1, 152064, 0xe69fc927 +0, 69, 69, 1, 152064, 0x8e5c81d8 +0, 70, 70, 1, 152064, 0x42402010 +0, 71, 71, 1, 152064, 0xd7267482 +0, 72, 72, 1, 152064, 0x64b280df +0, 73, 73, 1, 152064, 0xc4cbafcc +0, 74, 74, 1, 152064, 0xcf2f1e8b +0, 75, 75, 1, 152064, 0x4d6fdb3f +0, 76, 76, 1, 152064, 0xf22d6fed +0, 77, 77, 1, 152064, 0x625b167c +0, 78, 78, 1, 152064, 0x41348089 +0, 79, 79, 1, 152064, 0x6db2779b +0, 80, 80, 1, 152064, 0xe87030a8 +0, 81, 81, 1, 152064, 0x91b29cdd +0, 82, 82, 1, 152064, 0xe824f242 +0, 83, 83, 1, 152064, 0xac995380 +0, 84, 84, 1, 152064, 0x7efe361b +0, 85, 85, 1, 152064, 0xe10c0c26 +0, 86, 86, 1, 152064, 0x93108260 +0, 87, 87, 1, 152064, 0xbf4caed7 +0, 88, 88, 1, 152064, 0xb6a4d826 +0, 89, 89, 1, 152064, 0x78beea4e +0, 90, 90, 1, 152064, 0xdf612df9 +0, 91, 91, 1, 152064, 0xa9ef2830 +0, 92, 92, 1, 152064, 0x06448895 +0, 93, 93, 1, 152064, 0x332eb6d5 +0, 94, 94, 1, 152064, 0x935ba2c5 +0, 95, 95, 1, 152064, 0x62a22656 +0, 96, 96, 1, 152064, 0x06a670a7 +0, 97, 97, 1, 152064, 0xf60b1af0 +0, 98, 98, 1, 152064, 0x85177c10 +0, 99, 99, 1, 152064, 0x5e4e5c4b diff --git a/tests/ref/fate/h264-conformance-frext-freh6 b/tests/ref/fate/h264-conformance-frext-freh6 index a5264d61dce..57ac261800a 100644 --- a/tests/ref/fate/h264-conformance-frext-freh6 +++ b/tests/ref/fate/h264-conformance-frext-freh6 @@ -3,103 +3,103 @@ #codec_id 0: rawvideo #dimensions 0: 352x288 #sar 0: 0/1 -0, 1, 1, 1, 152064, 0x3b21d6cd -0, 2, 2, 1, 152064, 0xc32088c6 -0, 3, 3, 1, 152064, 0x65a64cee -0, 4, 4, 1, 152064, 0x0bd45a5b -0, 5, 5, 1, 152064, 0xb2210d4d -0, 6, 6, 1, 152064, 0xf5b15527 -0, 7, 7, 1, 152064, 0x806572ad -0, 8, 8, 1, 152064, 0x6ecb1fc8 -0, 9, 9, 1, 152064, 0xc25e96d5 -0, 10, 10, 1, 152064, 0x5593b825 -0, 11, 11, 1, 152064, 0xf3be1cff -0, 12, 12, 1, 152064, 0xa9155072 -0, 13, 13, 1, 152064, 0xd5552e26 -0, 14, 14, 1, 152064, 0x7bf0dbee -0, 15, 15, 1, 152064, 0x998b4911 -0, 16, 16, 1, 152064, 0xcc71bbe0 -0, 17, 17, 1, 152064, 0x602415b8 -0, 18, 18, 1, 152064, 0xcfff37cf -0, 19, 19, 1, 152064, 0x7cf824a8 -0, 20, 20, 1, 152064, 0x34816ee5 -0, 21, 21, 1, 152064, 0x1480540c -0, 22, 22, 1, 152064, 0xc2351aaf -0, 23, 23, 1, 152064, 0x3b8eac9f -0, 24, 24, 1, 152064, 0x92a8faf8 -0, 25, 25, 1, 152064, 0x7b6121c8 -0, 26, 26, 1, 152064, 0xe73a3bac -0, 27, 27, 1, 152064, 0xcd6e1e36 -0, 28, 28, 1, 152064, 0xb24660b1 -0, 29, 29, 1, 152064, 0xa290ec25 -0, 30, 30, 1, 152064, 0x308915ff -0, 31, 31, 1, 152064, 0x1e8dd4db -0, 32, 32, 1, 152064, 0x1372f2e0 -0, 33, 33, 1, 152064, 0xa07cc1d0 -0, 34, 34, 1, 152064, 0x34bb872c -0, 35, 35, 1, 152064, 0x59e6a565 -0, 36, 36, 1, 152064, 0x9a097932 -0, 37, 37, 1, 152064, 0x938f2e20 -0, 38, 38, 1, 152064, 0x59a8157d -0, 39, 39, 1, 152064, 0x5cacd404 -0, 40, 40, 1, 152064, 0xdad068f5 -0, 41, 41, 1, 152064, 0x7ba67d47 -0, 42, 42, 1, 152064, 0xc2a11e2d -0, 43, 43, 1, 152064, 0xd37fdef7 -0, 44, 44, 1, 152064, 0x19a3f80a -0, 45, 45, 1, 152064, 0x7ec7426a -0, 46, 46, 1, 152064, 0x8ffedb61 -0, 47, 47, 1, 152064, 0x82aebdd0 -0, 48, 48, 1, 152064, 0xdfc920cc -0, 49, 49, 1, 152064, 0x2a467698 -0, 50, 50, 1, 152064, 0xd08a37d5 -0, 51, 51, 1, 152064, 0xe606e66a -0, 52, 52, 1, 152064, 0x0e7b8bd8 -0, 53, 53, 1, 152064, 0xf983c732 -0, 54, 54, 1, 152064, 0x9b82c2e7 -0, 55, 55, 1, 152064, 0xa990a47e -0, 56, 56, 1, 152064, 0x2d5679f1 -0, 57, 57, 1, 152064, 0x7f1c0201 -0, 58, 58, 1, 152064, 0xc38b709d -0, 59, 59, 1, 152064, 0x040246d8 -0, 60, 60, 1, 152064, 0xbc856021 -0, 61, 61, 1, 152064, 0x81e01a78 -0, 62, 62, 1, 152064, 0xaff1e7f1 -0, 63, 63, 1, 152064, 0x1fee7715 -0, 64, 64, 1, 152064, 0x65053711 -0, 65, 65, 1, 152064, 0x238a0118 -0, 66, 66, 1, 152064, 0x563491b4 -0, 67, 67, 1, 152064, 0x5974a6cc -0, 68, 68, 1, 152064, 0xd8682c35 -0, 69, 69, 1, 152064, 0x85c49e96 -0, 70, 70, 1, 152064, 0x29486faa -0, 71, 71, 1, 152064, 0x1a4f0579 -0, 72, 72, 1, 152064, 0x6ab86c2f -0, 73, 73, 1, 152064, 0x36a36d2b -0, 74, 74, 1, 152064, 0x3bd77543 -0, 75, 75, 1, 152064, 0x8fbddc41 -0, 76, 76, 1, 152064, 0xccc6e0a5 -0, 77, 77, 1, 152064, 0x00a9539e -0, 78, 78, 1, 152064, 0x07ba0714 -0, 79, 79, 1, 152064, 0xbab2735d -0, 80, 80, 1, 152064, 0x79cb5ba0 -0, 81, 81, 1, 152064, 0xdbcc1c92 -0, 82, 82, 1, 152064, 0xffec952c -0, 83, 83, 1, 152064, 0xc31ac68e -0, 84, 84, 1, 152064, 0x24293eb9 -0, 85, 85, 1, 152064, 0x7b9b2cb4 -0, 86, 86, 1, 152064, 0x9dd4fe95 -0, 87, 87, 1, 152064, 0xb62e8baf -0, 88, 88, 1, 152064, 0x9fefc174 -0, 89, 89, 1, 152064, 0xe027c24e -0, 90, 90, 1, 152064, 0xe38adc70 -0, 91, 91, 1, 152064, 0xc7bf536f -0, 92, 92, 1, 152064, 0x4448f330 -0, 93, 93, 1, 152064, 0x4dad5339 -0, 94, 94, 1, 152064, 0x48fbab15 -0, 95, 95, 1, 152064, 0xe6c97b2c -0, 96, 96, 1, 152064, 0x3c3829ee -0, 97, 97, 1, 152064, 0x927772c0 -0, 98, 98, 1, 152064, 0xbb0f0ef4 -0, 99, 99, 1, 152064, 0xe65780a7 -0, 100, 100, 1, 152064, 0xaf8f6d72 +0, 0, 0, 1, 152064, 0x3b21d6cd +0, 1, 1, 1, 152064, 0xc32088c6 +0, 2, 2, 1, 152064, 0x65a64cee +0, 3, 3, 1, 152064, 0x0bd45a5b +0, 4, 4, 1, 152064, 0xb2210d4d +0, 5, 5, 1, 152064, 0xf5b15527 +0, 6, 6, 1, 152064, 0x806572ad +0, 7, 7, 1, 152064, 0x6ecb1fc8 +0, 8, 8, 1, 152064, 0xc25e96d5 +0, 9, 9, 1, 152064, 0x5593b825 +0, 10, 10, 1, 152064, 0xf3be1cff +0, 11, 11, 1, 152064, 0xa9155072 +0, 12, 12, 1, 152064, 0xd5552e26 +0, 13, 13, 1, 152064, 0x7bf0dbee +0, 14, 14, 1, 152064, 0x998b4911 +0, 15, 15, 1, 152064, 0xcc71bbe0 +0, 16, 16, 1, 152064, 0x602415b8 +0, 17, 17, 1, 152064, 0xcfff37cf +0, 18, 18, 1, 152064, 0x7cf824a8 +0, 19, 19, 1, 152064, 0x34816ee5 +0, 20, 20, 1, 152064, 0x1480540c +0, 21, 21, 1, 152064, 0xc2351aaf +0, 22, 22, 1, 152064, 0x3b8eac9f +0, 23, 23, 1, 152064, 0x92a8faf8 +0, 24, 24, 1, 152064, 0x7b6121c8 +0, 25, 25, 1, 152064, 0xe73a3bac +0, 26, 26, 1, 152064, 0xcd6e1e36 +0, 27, 27, 1, 152064, 0xb24660b1 +0, 28, 28, 1, 152064, 0xa290ec25 +0, 29, 29, 1, 152064, 0x308915ff +0, 30, 30, 1, 152064, 0x1e8dd4db +0, 31, 31, 1, 152064, 0x1372f2e0 +0, 32, 32, 1, 152064, 0xa07cc1d0 +0, 33, 33, 1, 152064, 0x34bb872c +0, 34, 34, 1, 152064, 0x59e6a565 +0, 35, 35, 1, 152064, 0x9a097932 +0, 36, 36, 1, 152064, 0x938f2e20 +0, 37, 37, 1, 152064, 0x59a8157d +0, 38, 38, 1, 152064, 0x5cacd404 +0, 39, 39, 1, 152064, 0xdad068f5 +0, 40, 40, 1, 152064, 0x7ba67d47 +0, 41, 41, 1, 152064, 0xc2a11e2d +0, 42, 42, 1, 152064, 0xd37fdef7 +0, 43, 43, 1, 152064, 0x19a3f80a +0, 44, 44, 1, 152064, 0x7ec7426a +0, 45, 45, 1, 152064, 0x8ffedb61 +0, 46, 46, 1, 152064, 0x82aebdd0 +0, 47, 47, 1, 152064, 0xdfc920cc +0, 48, 48, 1, 152064, 0x2a467698 +0, 49, 49, 1, 152064, 0xd08a37d5 +0, 50, 50, 1, 152064, 0xe606e66a +0, 51, 51, 1, 152064, 0x0e7b8bd8 +0, 52, 52, 1, 152064, 0xf983c732 +0, 53, 53, 1, 152064, 0x9b82c2e7 +0, 54, 54, 1, 152064, 0xa990a47e +0, 55, 55, 1, 152064, 0x2d5679f1 +0, 56, 56, 1, 152064, 0x7f1c0201 +0, 57, 57, 1, 152064, 0xc38b709d +0, 58, 58, 1, 152064, 0x040246d8 +0, 59, 59, 1, 152064, 0xbc856021 +0, 60, 60, 1, 152064, 0x81e01a78 +0, 61, 61, 1, 152064, 0xaff1e7f1 +0, 62, 62, 1, 152064, 0x1fee7715 +0, 63, 63, 1, 152064, 0x65053711 +0, 64, 64, 1, 152064, 0x238a0118 +0, 65, 65, 1, 152064, 0x563491b4 +0, 66, 66, 1, 152064, 0x5974a6cc +0, 67, 67, 1, 152064, 0xd8682c35 +0, 68, 68, 1, 152064, 0x85c49e96 +0, 69, 69, 1, 152064, 0x29486faa +0, 70, 70, 1, 152064, 0x1a4f0579 +0, 71, 71, 1, 152064, 0x6ab86c2f +0, 72, 72, 1, 152064, 0x36a36d2b +0, 73, 73, 1, 152064, 0x3bd77543 +0, 74, 74, 1, 152064, 0x8fbddc41 +0, 75, 75, 1, 152064, 0xccc6e0a5 +0, 76, 76, 1, 152064, 0x00a9539e +0, 77, 77, 1, 152064, 0x07ba0714 +0, 78, 78, 1, 152064, 0xbab2735d +0, 79, 79, 1, 152064, 0x79cb5ba0 +0, 80, 80, 1, 152064, 0xdbcc1c92 +0, 81, 81, 1, 152064, 0xffec952c +0, 82, 82, 1, 152064, 0xc31ac68e +0, 83, 83, 1, 152064, 0x24293eb9 +0, 84, 84, 1, 152064, 0x7b9b2cb4 +0, 85, 85, 1, 152064, 0x9dd4fe95 +0, 86, 86, 1, 152064, 0xb62e8baf +0, 87, 87, 1, 152064, 0x9fefc174 +0, 88, 88, 1, 152064, 0xe027c24e +0, 89, 89, 1, 152064, 0xe38adc70 +0, 90, 90, 1, 152064, 0xc7bf536f +0, 91, 91, 1, 152064, 0x4448f330 +0, 92, 92, 1, 152064, 0x4dad5339 +0, 93, 93, 1, 152064, 0x48fbab15 +0, 94, 94, 1, 152064, 0xe6c97b2c +0, 95, 95, 1, 152064, 0x3c3829ee +0, 96, 96, 1, 152064, 0x927772c0 +0, 97, 97, 1, 152064, 0xbb0f0ef4 +0, 98, 98, 1, 152064, 0xe65780a7 +0, 99, 99, 1, 152064, 0xaf8f6d72 diff --git a/tests/ref/fate/h264-conformance-frext-freh7_b b/tests/ref/fate/h264-conformance-frext-freh7_b index cb56f627cf0..b078cf1b353 100644 --- a/tests/ref/fate/h264-conformance-frext-freh7_b +++ b/tests/ref/fate/h264-conformance-frext-freh7_b @@ -3,103 +3,103 @@ #codec_id 0: rawvideo #dimensions 0: 352x288 #sar 0: 0/1 -0, 1, 1, 1, 152064, 0x89f2e8d5 -0, 2, 2, 1, 152064, 0x35b99397 -0, 3, 3, 1, 152064, 0x6ef46744 -0, 4, 4, 1, 152064, 0xec4d6c1c -0, 5, 5, 1, 152064, 0xad6e0c70 -0, 6, 6, 1, 152064, 0x2db534b3 -0, 7, 7, 1, 152064, 0xcbd25ddd -0, 8, 8, 1, 152064, 0xd90708b4 -0, 9, 9, 1, 152064, 0xc2aa52df -0, 10, 10, 1, 152064, 0xbcfc84dc -0, 11, 11, 1, 152064, 0xa5a6d269 -0, 12, 12, 1, 152064, 0x27220ce9 -0, 13, 13, 1, 152064, 0xf075ee6d -0, 14, 14, 1, 152064, 0x9fd3c2ac -0, 15, 15, 1, 152064, 0xcba24c2d -0, 16, 16, 1, 152064, 0x41cd9441 -0, 17, 17, 1, 152064, 0x0126efa3 -0, 18, 18, 1, 152064, 0xf62112af -0, 19, 19, 1, 152064, 0x35aff50f -0, 20, 20, 1, 152064, 0xcb0b276f -0, 21, 21, 1, 152064, 0xc7ef0214 -0, 22, 22, 1, 152064, 0x7f78d387 -0, 23, 23, 1, 152064, 0x266c673d -0, 24, 24, 1, 152064, 0x1d39c073 -0, 25, 25, 1, 152064, 0x6a3ae455 -0, 26, 26, 1, 152064, 0xe4ce0230 -0, 27, 27, 1, 152064, 0x7f95e87b -0, 28, 28, 1, 152064, 0x7c552236 -0, 29, 29, 1, 152064, 0x24c799b9 -0, 30, 30, 1, 152064, 0x5042d974 -0, 31, 31, 1, 152064, 0xe934a5b8 -0, 32, 32, 1, 152064, 0x6d59c884 -0, 33, 33, 1, 152064, 0xd00f7fdb -0, 34, 34, 1, 152064, 0x62ac3ebd -0, 35, 35, 1, 152064, 0xb40a6c25 -0, 36, 36, 1, 152064, 0x8706188c -0, 37, 37, 1, 152064, 0x7682e339 -0, 38, 38, 1, 152064, 0x1061d943 -0, 39, 39, 1, 152064, 0x50fa684a -0, 40, 40, 1, 152064, 0xab4b1975 -0, 41, 41, 1, 152064, 0x2d043acb -0, 42, 42, 1, 152064, 0xe3c2ec0a -0, 43, 43, 1, 152064, 0xb9bc99dc -0, 44, 44, 1, 152064, 0x051fb857 -0, 45, 45, 1, 152064, 0x71d1fe52 -0, 46, 46, 1, 152064, 0x4230c694 -0, 47, 47, 1, 152064, 0xb412a137 -0, 48, 48, 1, 152064, 0x2f50f90d -0, 49, 49, 1, 152064, 0x68a1466f -0, 50, 50, 1, 152064, 0x77e3f47b -0, 51, 51, 1, 152064, 0x4d08de2b -0, 52, 52, 1, 152064, 0x1fc663be -0, 53, 53, 1, 152064, 0x2c8ba712 -0, 54, 54, 1, 152064, 0xd50d85b9 -0, 55, 55, 1, 152064, 0xe8483437 -0, 56, 56, 1, 152064, 0x4e331e4c -0, 57, 57, 1, 152064, 0x0f64a7a0 -0, 58, 58, 1, 152064, 0x797b0b8c -0, 59, 59, 1, 152064, 0x1b91e6d8 -0, 60, 60, 1, 152064, 0xf3a1f3b6 -0, 61, 61, 1, 152064, 0x2b94bd52 -0, 62, 62, 1, 152064, 0x1f30962e -0, 63, 63, 1, 152064, 0x853321cf -0, 64, 64, 1, 152064, 0x8266c0ac -0, 65, 65, 1, 152064, 0x25498be0 -0, 66, 66, 1, 152064, 0x0f653af9 -0, 67, 67, 1, 152064, 0x0a025f7e -0, 68, 68, 1, 152064, 0x1cfbae04 -0, 69, 69, 1, 152064, 0x3a874757 -0, 70, 70, 1, 152064, 0x2c67006e -0, 71, 71, 1, 152064, 0x1d409bce -0, 72, 72, 1, 152064, 0xfe43121f -0, 73, 73, 1, 152064, 0x43411830 -0, 74, 74, 1, 152064, 0x536d26ca -0, 75, 75, 1, 152064, 0x9eb873ea -0, 76, 76, 1, 152064, 0x093f93ec -0, 77, 77, 1, 152064, 0xdf6f0381 -0, 78, 78, 1, 152064, 0xa9f4b5e5 -0, 79, 79, 1, 152064, 0x08f71ef8 -0, 80, 80, 1, 152064, 0x7a68f820 -0, 81, 81, 1, 152064, 0xae0c73e7 -0, 82, 82, 1, 152064, 0x886ae6c7 -0, 83, 83, 1, 152064, 0x9357f433 -0, 84, 84, 1, 152064, 0xcc335068 -0, 85, 85, 1, 152064, 0x2ea108ab -0, 86, 86, 1, 152064, 0x06d7dcb0 -0, 87, 87, 1, 152064, 0x81dc81bc -0, 88, 88, 1, 152064, 0xfb32b626 -0, 89, 89, 1, 152064, 0x2787d1c7 -0, 90, 90, 1, 152064, 0x69e51118 -0, 91, 91, 1, 152064, 0xba15d94d -0, 92, 92, 1, 152064, 0xc41c09cf -0, 93, 93, 1, 152064, 0x7e50e12f -0, 94, 94, 1, 152064, 0x0763ddbe -0, 95, 95, 1, 152064, 0x8a09bb88 -0, 96, 96, 1, 152064, 0x530752b7 -0, 97, 97, 1, 152064, 0x9b159923 -0, 98, 98, 1, 152064, 0xcbb83ed3 -0, 99, 99, 1, 152064, 0xdeb5ac0e -0, 100, 100, 1, 152064, 0x189299d4 +0, 0, 0, 1, 152064, 0x89f2e8d5 +0, 1, 1, 1, 152064, 0x35b99397 +0, 2, 2, 1, 152064, 0x6ef46744 +0, 3, 3, 1, 152064, 0xec4d6c1c +0, 4, 4, 1, 152064, 0xad6e0c70 +0, 5, 5, 1, 152064, 0x2db534b3 +0, 6, 6, 1, 152064, 0xcbd25ddd +0, 7, 7, 1, 152064, 0xd90708b4 +0, 8, 8, 1, 152064, 0xc2aa52df +0, 9, 9, 1, 152064, 0xbcfc84dc +0, 10, 10, 1, 152064, 0xa5a6d269 +0, 11, 11, 1, 152064, 0x27220ce9 +0, 12, 12, 1, 152064, 0xf075ee6d +0, 13, 13, 1, 152064, 0x9fd3c2ac +0, 14, 14, 1, 152064, 0xcba24c2d +0, 15, 15, 1, 152064, 0x41cd9441 +0, 16, 16, 1, 152064, 0x0126efa3 +0, 17, 17, 1, 152064, 0xf62112af +0, 18, 18, 1, 152064, 0x35aff50f +0, 19, 19, 1, 152064, 0xcb0b276f +0, 20, 20, 1, 152064, 0xc7ef0214 +0, 21, 21, 1, 152064, 0x7f78d387 +0, 22, 22, 1, 152064, 0x266c673d +0, 23, 23, 1, 152064, 0x1d39c073 +0, 24, 24, 1, 152064, 0x6a3ae455 +0, 25, 25, 1, 152064, 0xe4ce0230 +0, 26, 26, 1, 152064, 0x7f95e87b +0, 27, 27, 1, 152064, 0x7c552236 +0, 28, 28, 1, 152064, 0x24c799b9 +0, 29, 29, 1, 152064, 0x5042d974 +0, 30, 30, 1, 152064, 0xe934a5b8 +0, 31, 31, 1, 152064, 0x6d59c884 +0, 32, 32, 1, 152064, 0xd00f7fdb +0, 33, 33, 1, 152064, 0x62ac3ebd +0, 34, 34, 1, 152064, 0xb40a6c25 +0, 35, 35, 1, 152064, 0x8706188c +0, 36, 36, 1, 152064, 0x7682e339 +0, 37, 37, 1, 152064, 0x1061d943 +0, 38, 38, 1, 152064, 0x50fa684a +0, 39, 39, 1, 152064, 0xab4b1975 +0, 40, 40, 1, 152064, 0x2d043acb +0, 41, 41, 1, 152064, 0xe3c2ec0a +0, 42, 42, 1, 152064, 0xb9bc99dc +0, 43, 43, 1, 152064, 0x051fb857 +0, 44, 44, 1, 152064, 0x71d1fe52 +0, 45, 45, 1, 152064, 0x4230c694 +0, 46, 46, 1, 152064, 0xb412a137 +0, 47, 47, 1, 152064, 0x2f50f90d +0, 48, 48, 1, 152064, 0x68a1466f +0, 49, 49, 1, 152064, 0x77e3f47b +0, 50, 50, 1, 152064, 0x4d08de2b +0, 51, 51, 1, 152064, 0x1fc663be +0, 52, 52, 1, 152064, 0x2c8ba712 +0, 53, 53, 1, 152064, 0xd50d85b9 +0, 54, 54, 1, 152064, 0xe8483437 +0, 55, 55, 1, 152064, 0x4e331e4c +0, 56, 56, 1, 152064, 0x0f64a7a0 +0, 57, 57, 1, 152064, 0x797b0b8c +0, 58, 58, 1, 152064, 0x1b91e6d8 +0, 59, 59, 1, 152064, 0xf3a1f3b6 +0, 60, 60, 1, 152064, 0x2b94bd52 +0, 61, 61, 1, 152064, 0x1f30962e +0, 62, 62, 1, 152064, 0x853321cf +0, 63, 63, 1, 152064, 0x8266c0ac +0, 64, 64, 1, 152064, 0x25498be0 +0, 65, 65, 1, 152064, 0x0f653af9 +0, 66, 66, 1, 152064, 0x0a025f7e +0, 67, 67, 1, 152064, 0x1cfbae04 +0, 68, 68, 1, 152064, 0x3a874757 +0, 69, 69, 1, 152064, 0x2c67006e +0, 70, 70, 1, 152064, 0x1d409bce +0, 71, 71, 1, 152064, 0xfe43121f +0, 72, 72, 1, 152064, 0x43411830 +0, 73, 73, 1, 152064, 0x536d26ca +0, 74, 74, 1, 152064, 0x9eb873ea +0, 75, 75, 1, 152064, 0x093f93ec +0, 76, 76, 1, 152064, 0xdf6f0381 +0, 77, 77, 1, 152064, 0xa9f4b5e5 +0, 78, 78, 1, 152064, 0x08f71ef8 +0, 79, 79, 1, 152064, 0x7a68f820 +0, 80, 80, 1, 152064, 0xae0c73e7 +0, 81, 81, 1, 152064, 0x886ae6c7 +0, 82, 82, 1, 152064, 0x9357f433 +0, 83, 83, 1, 152064, 0xcc335068 +0, 84, 84, 1, 152064, 0x2ea108ab +0, 85, 85, 1, 152064, 0x06d7dcb0 +0, 86, 86, 1, 152064, 0x81dc81bc +0, 87, 87, 1, 152064, 0xfb32b626 +0, 88, 88, 1, 152064, 0x2787d1c7 +0, 89, 89, 1, 152064, 0x69e51118 +0, 90, 90, 1, 152064, 0xba15d94d +0, 91, 91, 1, 152064, 0xc41c09cf +0, 92, 92, 1, 152064, 0x7e50e12f +0, 93, 93, 1, 152064, 0x0763ddbe +0, 94, 94, 1, 152064, 0x8a09bb88 +0, 95, 95, 1, 152064, 0x530752b7 +0, 96, 96, 1, 152064, 0x9b159923 +0, 97, 97, 1, 152064, 0xcbb83ed3 +0, 98, 98, 1, 152064, 0xdeb5ac0e +0, 99, 99, 1, 152064, 0x189299d4 diff --git a/tests/ref/fate/h264-conformance-frext-frext2_panasonic_b b/tests/ref/fate/h264-conformance-frext-frext2_panasonic_b index d4435700828..76e4d26cf8f 100644 --- a/tests/ref/fate/h264-conformance-frext-frext2_panasonic_b +++ b/tests/ref/fate/h264-conformance-frext-frext2_panasonic_b @@ -3,18 +3,18 @@ #codec_id 0: rawvideo #dimensions 0: 352x288 #sar 0: 0/1 -0, 1, 1, 1, 152064, 0x0147a2a9 -0, 2, 2, 1, 152064, 0xe2365351 -0, 3, 3, 1, 152064, 0xb5f9daee -0, 4, 4, 1, 152064, 0xd60818b2 -0, 5, 5, 1, 152064, 0x21b528e5 -0, 6, 6, 1, 152064, 0x9c9dda18 -0, 7, 7, 1, 152064, 0x387fe7de -0, 8, 8, 1, 152064, 0x8f0c5a1e -0, 9, 9, 1, 152064, 0x02409694 -0, 10, 10, 1, 152064, 0x2b36a7a7 -0, 11, 11, 1, 152064, 0x3c6d3863 -0, 12, 12, 1, 152064, 0xaa7835e1 -0, 13, 13, 1, 152064, 0x6d105fe7 -0, 14, 14, 1, 152064, 0x9a348732 -0, 15, 15, 1, 152064, 0x96a3af13 +0, 0, 0, 1, 152064, 0x0147a2a9 +0, 1, 1, 1, 152064, 0xe2365351 +0, 2, 2, 1, 152064, 0xb5f9daee +0, 3, 3, 1, 152064, 0xd60818b2 +0, 4, 4, 1, 152064, 0x21b528e5 +0, 5, 5, 1, 152064, 0x9c9dda18 +0, 6, 6, 1, 152064, 0x387fe7de +0, 7, 7, 1, 152064, 0x8f0c5a1e +0, 8, 8, 1, 152064, 0x02409694 +0, 9, 9, 1, 152064, 0x2b36a7a7 +0, 10, 10, 1, 152064, 0x3c6d3863 +0, 11, 11, 1, 152064, 0xaa7835e1 +0, 12, 12, 1, 152064, 0x6d105fe7 +0, 13, 13, 1, 152064, 0x9a348732 +0, 14, 14, 1, 152064, 0x96a3af13 diff --git a/tests/ref/fate/h264-conformance-frext-frext4_panasonic_a b/tests/ref/fate/h264-conformance-frext-frext4_panasonic_a index 1f678d1122c..5640228a263 100644 --- a/tests/ref/fate/h264-conformance-frext-frext4_panasonic_a +++ b/tests/ref/fate/h264-conformance-frext-frext4_panasonic_a @@ -3,13 +3,13 @@ #codec_id 0: rawvideo #dimensions 0: 352x288 #sar 0: 0/1 -0, 1, 1, 1, 152064, 0xd604d440 -0, 2, 2, 1, 152064, 0x08ef262c -0, 3, 3, 1, 152064, 0x992fca8e -0, 4, 4, 1, 152064, 0x5a02ee15 -0, 5, 5, 1, 152064, 0xf15d5c66 -0, 6, 6, 1, 152064, 0x360dda12 -0, 7, 7, 1, 152064, 0x18b54985 -0, 8, 8, 1, 152064, 0xf12b6cde -0, 9, 9, 1, 152064, 0x3b2e63f7 -0, 10, 10, 1, 152064, 0x140abcfd +0, 0, 0, 1, 152064, 0xd604d440 +0, 1, 1, 1, 152064, 0x08ef262c +0, 2, 2, 1, 152064, 0x992fca8e +0, 3, 3, 1, 152064, 0x5a02ee15 +0, 4, 4, 1, 152064, 0xf15d5c66 +0, 5, 5, 1, 152064, 0x360dda12 +0, 6, 6, 1, 152064, 0x18b54985 +0, 7, 7, 1, 152064, 0xf12b6cde +0, 8, 8, 1, 152064, 0x3b2e63f7 +0, 9, 9, 1, 152064, 0x140abcfd diff --git a/tests/ref/fate/h264-conformance-frext-hcaff1_hhi_b b/tests/ref/fate/h264-conformance-frext-hcaff1_hhi_b index f541135929e..67badb6c2b6 100644 --- a/tests/ref/fate/h264-conformance-frext-hcaff1_hhi_b +++ b/tests/ref/fate/h264-conformance-frext-hcaff1_hhi_b @@ -3,13 +3,13 @@ #codec_id 0: rawvideo #dimensions 0: 352x288 #sar 0: 0/1 -0, 1, 1, 1, 152064, 0xb055a9bd -0, 2, 2, 1, 152064, 0x9e1eadb6 -0, 3, 3, 1, 152064, 0x48f117d2 -0, 4, 4, 1, 152064, 0x3e3ff049 -0, 5, 5, 1, 152064, 0x2ff80943 -0, 6, 6, 1, 152064, 0xc5ee16a6 -0, 7, 7, 1, 152064, 0x38c33f28 -0, 8, 8, 1, 152064, 0x3e8444c7 -0, 9, 9, 1, 152064, 0x14ca4ab2 -0, 10, 10, 1, 152064, 0xe20e78f7 +0, 0, 0, 1, 152064, 0xb055a9bd +0, 1, 1, 1, 152064, 0x9e1eadb6 +0, 2, 2, 1, 152064, 0x48f117d2 +0, 3, 3, 1, 152064, 0x3e3ff049 +0, 4, 4, 1, 152064, 0x2ff80943 +0, 5, 5, 1, 152064, 0xc5ee16a6 +0, 6, 6, 1, 152064, 0x38c33f28 +0, 7, 7, 1, 152064, 0x3e8444c7 +0, 8, 8, 1, 152064, 0x14ca4ab2 +0, 9, 9, 1, 152064, 0xe20e78f7 diff --git a/tests/ref/fate/h264-conformance-frext-hpcafl_bcrm_c b/tests/ref/fate/h264-conformance-frext-hpcafl_bcrm_c index 25551fb0210..0febed6d6f2 100644 --- a/tests/ref/fate/h264-conformance-frext-hpcafl_bcrm_c +++ b/tests/ref/fate/h264-conformance-frext-hpcafl_bcrm_c @@ -3,303 +3,303 @@ #codec_id 0: rawvideo #dimensions 0: 352x288 #sar 0: 0/1 -0, 1, 1, 1, 152064, 0x502ec077 -0, 2, 2, 1, 152064, 0x84807243 -0, 3, 3, 1, 152064, 0xd7474a6e -0, 4, 4, 1, 152064, 0x793469bb -0, 5, 5, 1, 152064, 0xb7a0faf7 -0, 6, 6, 1, 152064, 0x1d3d3cba -0, 7, 7, 1, 152064, 0xb62583de -0, 8, 8, 1, 152064, 0xc8422fb1 -0, 9, 9, 1, 152064, 0x321dc699 -0, 10, 10, 1, 152064, 0x7a34d350 -0, 11, 11, 1, 152064, 0xaa4c302d -0, 12, 12, 1, 152064, 0x45fa7ab0 -0, 13, 13, 1, 152064, 0xc7262e41 -0, 14, 14, 1, 152064, 0x3550000c -0, 15, 15, 1, 152064, 0xf4bab54b -0, 16, 16, 1, 152064, 0xaccf9c1a -0, 17, 17, 1, 152064, 0x9bee20e9 -0, 18, 18, 1, 152064, 0x47fb7720 -0, 19, 19, 1, 152064, 0x12c63ffb -0, 20, 20, 1, 152064, 0xfa2b8b4d -0, 21, 21, 1, 152064, 0x279964bd -0, 22, 22, 1, 152064, 0xb8b01c7e -0, 23, 23, 1, 152064, 0x816fa010 -0, 24, 24, 1, 152064, 0x59fe1c8c -0, 25, 25, 1, 152064, 0x13393fad -0, 26, 26, 1, 152064, 0x991a50a4 -0, 27, 27, 1, 152064, 0x57df3eb7 -0, 28, 28, 1, 152064, 0x744371df -0, 29, 29, 1, 152064, 0xe9f6d3ff -0, 30, 30, 1, 152064, 0xc506fba0 -0, 31, 31, 1, 152064, 0x6295b90e -0, 32, 32, 1, 152064, 0xa19cee2d -0, 33, 33, 1, 152064, 0xf8c1b3ca -0, 34, 34, 1, 152064, 0x69f68ce0 -0, 35, 35, 1, 152064, 0x80558bb6 -0, 36, 36, 1, 152064, 0x27824fa5 -0, 37, 37, 1, 152064, 0x27c929a1 -0, 38, 38, 1, 152064, 0xc0fe06d1 -0, 39, 39, 1, 152064, 0xc52bc58c -0, 40, 40, 1, 152064, 0x0a5363c7 -0, 41, 41, 1, 152064, 0xd0f45a0d -0, 42, 42, 1, 152064, 0x274710f9 -0, 43, 43, 1, 152064, 0x89d2d390 -0, 44, 44, 1, 152064, 0x12a9bfb0 -0, 45, 45, 1, 152064, 0x04501a93 -0, 46, 46, 1, 152064, 0xf92cbbf4 -0, 47, 47, 1, 152064, 0xf6d1b27d -0, 48, 48, 1, 152064, 0xe3e904c3 -0, 49, 49, 1, 152064, 0x58f8516d -0, 50, 50, 1, 152064, 0x70370c2b -0, 51, 51, 1, 152064, 0xfeebc88c -0, 52, 52, 1, 152064, 0x974c6ed6 -0, 53, 53, 1, 152064, 0x401bdcf2 -0, 54, 54, 1, 152064, 0xfe61e278 -0, 55, 55, 1, 152064, 0x96ba8bb9 -0, 56, 56, 1, 152064, 0x988492fd -0, 57, 57, 1, 152064, 0xd1d913a9 -0, 58, 58, 1, 152064, 0x6bc46f0e -0, 59, 59, 1, 152064, 0x695ef706 -0, 60, 60, 1, 152064, 0x142045c9 -0, 61, 61, 1, 152064, 0xb390ed87 -0, 62, 62, 1, 152064, 0xb9e6d2e5 -0, 63, 63, 1, 152064, 0xe348797f -0, 64, 64, 1, 152064, 0x1cbd29d6 -0, 65, 65, 1, 152064, 0xbd7dd694 -0, 66, 66, 1, 152064, 0x516873c3 -0, 67, 67, 1, 152064, 0x27bba182 -0, 68, 68, 1, 152064, 0x7541f920 -0, 69, 69, 1, 152064, 0xfdf67042 -0, 70, 70, 1, 152064, 0x6c3c7896 -0, 71, 71, 1, 152064, 0xed86c467 -0, 72, 72, 1, 152064, 0x4ea83ca2 -0, 73, 73, 1, 152064, 0xa3e6725b -0, 74, 74, 1, 152064, 0x917f5f16 -0, 75, 75, 1, 152064, 0x8cf2d2e1 -0, 76, 76, 1, 152064, 0x57a8d116 -0, 77, 77, 1, 152064, 0x0db267d4 -0, 78, 78, 1, 152064, 0xce782ac5 -0, 79, 79, 1, 152064, 0x1c9d8518 -0, 80, 80, 1, 152064, 0x47598ac7 -0, 81, 81, 1, 152064, 0xc5033d97 -0, 82, 82, 1, 152064, 0xd7aaa3a4 -0, 83, 83, 1, 152064, 0x078afc96 -0, 84, 84, 1, 152064, 0xc9fe673d -0, 85, 85, 1, 152064, 0xe9284066 -0, 86, 86, 1, 152064, 0xbc570982 -0, 87, 87, 1, 152064, 0x0aac8574 -0, 88, 88, 1, 152064, 0x098cbeee -0, 89, 89, 1, 152064, 0x19c36a9d -0, 90, 90, 1, 152064, 0x8fe4a893 -0, 91, 91, 1, 152064, 0x0b652f17 -0, 92, 92, 1, 152064, 0x10f2e6bf -0, 93, 93, 1, 152064, 0x7ce5634e -0, 94, 94, 1, 152064, 0x8fe4ac6c -0, 95, 95, 1, 152064, 0xcaba749e -0, 96, 96, 1, 152064, 0x5f8a0d5c -0, 97, 97, 1, 152064, 0xcaa66bbc -0, 98, 98, 1, 152064, 0xc87ae617 -0, 99, 99, 1, 152064, 0xe8ef4dd7 -0, 100, 100, 1, 152064, 0xdfca5a07 -0, 101, 101, 1, 152064, 0x5f7eab7d -0, 102, 102, 1, 152064, 0x8a65ebbb -0, 103, 103, 1, 152064, 0x4beab4a0 -0, 104, 104, 1, 152064, 0xb5e6ab30 -0, 105, 105, 1, 152064, 0x8fe4f4d4 -0, 106, 106, 1, 152064, 0x95bde1ca -0, 107, 107, 1, 152064, 0xcc5e3a53 -0, 108, 108, 1, 152064, 0xf09f1dd7 -0, 109, 109, 1, 152064, 0x10179672 -0, 110, 110, 1, 152064, 0x4ad16184 -0, 111, 111, 1, 152064, 0x9efa0e23 -0, 112, 112, 1, 152064, 0x22f59522 -0, 113, 113, 1, 152064, 0x4d38f09d -0, 114, 114, 1, 152064, 0x4c5ebf56 -0, 115, 115, 1, 152064, 0xb19d5077 -0, 116, 116, 1, 152064, 0xa98576b9 -0, 117, 117, 1, 152064, 0x65324239 -0, 118, 118, 1, 152064, 0x709e4031 -0, 119, 119, 1, 152064, 0xf8e81681 -0, 120, 120, 1, 152064, 0x058514e5 -0, 121, 121, 1, 152064, 0xd1d1c806 -0, 122, 122, 1, 152064, 0x0e4dde57 -0, 123, 123, 1, 152064, 0x49e9c2bb -0, 124, 124, 1, 152064, 0x01417ce6 -0, 125, 125, 1, 152064, 0xda7ebbf1 -0, 126, 126, 1, 152064, 0xa22906b7 -0, 127, 127, 1, 152064, 0x32e2df87 -0, 128, 128, 1, 152064, 0x69917c8f -0, 129, 129, 1, 152064, 0xea8ed2cc -0, 130, 130, 1, 152064, 0x0b8d57f1 -0, 131, 131, 1, 152064, 0x5f683bcd -0, 132, 132, 1, 152064, 0x5162fe2f -0, 133, 133, 1, 152064, 0x49c052f8 -0, 134, 134, 1, 152064, 0x990b69ba -0, 135, 135, 1, 152064, 0xa6d4f99f -0, 136, 136, 1, 152064, 0xe79ef4da -0, 137, 137, 1, 152064, 0x5e8a3847 -0, 138, 138, 1, 152064, 0x38b1e75f -0, 139, 139, 1, 152064, 0xf5c91bed -0, 140, 140, 1, 152064, 0xd59a6d26 -0, 141, 141, 1, 152064, 0xc361de06 -0, 142, 142, 1, 152064, 0x63ed2229 -0, 143, 143, 1, 152064, 0xb8229205 -0, 144, 144, 1, 152064, 0x7c6619af -0, 145, 145, 1, 152064, 0x4126b02f -0, 146, 146, 1, 152064, 0x9250b99b -0, 147, 147, 1, 152064, 0x589778f9 -0, 148, 148, 1, 152064, 0xed1fa45b -0, 149, 149, 1, 152064, 0x700b6f32 -0, 150, 150, 1, 152064, 0x0590df55 -0, 151, 151, 1, 152064, 0x3e9c4018 -0, 152, 152, 1, 152064, 0x957b8860 -0, 153, 153, 1, 152064, 0x56161560 -0, 154, 154, 1, 152064, 0xbc43bc3b -0, 155, 155, 1, 152064, 0x508d8632 -0, 156, 156, 1, 152064, 0xbc5736d8 -0, 157, 157, 1, 152064, 0xed7d3aef -0, 158, 158, 1, 152064, 0x1dcdda9f -0, 159, 159, 1, 152064, 0x8ef6d5c9 -0, 160, 160, 1, 152064, 0x15466acc -0, 161, 161, 1, 152064, 0x45d4cf67 -0, 162, 162, 1, 152064, 0x8c900b9d -0, 163, 163, 1, 152064, 0x747006e0 -0, 164, 164, 1, 152064, 0xac920a0c -0, 165, 165, 1, 152064, 0xb8210c27 -0, 166, 166, 1, 152064, 0x7dbb873a -0, 167, 167, 1, 152064, 0x0d4d7584 -0, 168, 168, 1, 152064, 0xefb3fe60 -0, 169, 169, 1, 152064, 0x905e2644 -0, 170, 170, 1, 152064, 0x7c04e534 -0, 171, 171, 1, 152064, 0x8889972a -0, 172, 172, 1, 152064, 0x21c7d8ad -0, 173, 173, 1, 152064, 0x1c641176 -0, 174, 174, 1, 152064, 0xf71489a4 -0, 175, 175, 1, 152064, 0xd7ac5555 -0, 176, 176, 1, 152064, 0xb4609c6d -0, 177, 177, 1, 152064, 0xf5b2bd5e -0, 178, 178, 1, 152064, 0x9f43ce57 -0, 179, 179, 1, 152064, 0x77642dd3 -0, 180, 180, 1, 152064, 0x3e79565c -0, 181, 181, 1, 152064, 0x95f40b8e -0, 182, 182, 1, 152064, 0x3c8ca4d4 -0, 183, 183, 1, 152064, 0xa02ac497 -0, 184, 184, 1, 152064, 0x4c93b377 -0, 185, 185, 1, 152064, 0x55f5ac68 -0, 186, 186, 1, 152064, 0xf8652eca -0, 187, 187, 1, 152064, 0x56e94574 -0, 188, 188, 1, 152064, 0x6d8302e1 -0, 189, 189, 1, 152064, 0x29a57061 -0, 190, 190, 1, 152064, 0x24e4cfdc -0, 191, 191, 1, 152064, 0xf5a5d62a -0, 192, 192, 1, 152064, 0x998870c1 -0, 193, 193, 1, 152064, 0xa15b1f4e -0, 194, 194, 1, 152064, 0xb0ccb51f -0, 195, 195, 1, 152064, 0xeaaf59ab -0, 196, 196, 1, 152064, 0x7e2b4fe6 -0, 197, 197, 1, 152064, 0x72299fea -0, 198, 198, 1, 152064, 0x769da8b2 -0, 199, 199, 1, 152064, 0xefad7ef8 -0, 200, 200, 1, 152064, 0x24819983 -0, 201, 201, 1, 152064, 0x2aad32ab -0, 202, 202, 1, 152064, 0xc80cac79 -0, 203, 203, 1, 152064, 0x1659d628 -0, 204, 204, 1, 152064, 0xef941f66 -0, 205, 205, 1, 152064, 0x0d7fcdb5 -0, 206, 206, 1, 152064, 0x7c1853fa -0, 207, 207, 1, 152064, 0xb94c4d3c -0, 208, 208, 1, 152064, 0xc47adfc2 -0, 209, 209, 1, 152064, 0x366a6729 -0, 210, 210, 1, 152064, 0x7eb37b70 -0, 211, 211, 1, 152064, 0xafd54c27 -0, 212, 212, 1, 152064, 0x67b18636 -0, 213, 213, 1, 152064, 0x93b22dcf -0, 214, 214, 1, 152064, 0xa64991f1 -0, 215, 215, 1, 152064, 0xd32a7102 -0, 216, 216, 1, 152064, 0xff665d1c -0, 217, 217, 1, 152064, 0xf107cc31 -0, 218, 218, 1, 152064, 0xf5b25652 -0, 219, 219, 1, 152064, 0x8caf783d -0, 220, 220, 1, 152064, 0x72f3eb00 -0, 221, 221, 1, 152064, 0xb5aea5f8 -0, 222, 222, 1, 152064, 0xee70e870 -0, 223, 223, 1, 152064, 0x7c3a0156 -0, 224, 224, 1, 152064, 0x871b6383 -0, 225, 225, 1, 152064, 0x48d831ff -0, 226, 226, 1, 152064, 0xca233913 -0, 227, 227, 1, 152064, 0xe14bc5eb -0, 228, 228, 1, 152064, 0x9b1d27e7 -0, 229, 229, 1, 152064, 0xfb9637f7 -0, 230, 230, 1, 152064, 0x0c022157 -0, 231, 231, 1, 152064, 0x16d35fc9 -0, 232, 232, 1, 152064, 0x6d935f71 -0, 233, 233, 1, 152064, 0xae4066fa -0, 234, 234, 1, 152064, 0xcef94fdc -0, 235, 235, 1, 152064, 0xc234edb9 -0, 236, 236, 1, 152064, 0x26a4f2e2 -0, 237, 237, 1, 152064, 0xd29ac23e -0, 238, 238, 1, 152064, 0xb7604395 -0, 239, 239, 1, 152064, 0x408084f6 -0, 240, 240, 1, 152064, 0x0a02026c -0, 241, 241, 1, 152064, 0x78b33c7c -0, 242, 242, 1, 152064, 0xcb02b874 -0, 243, 243, 1, 152064, 0xf566513b -0, 244, 244, 1, 152064, 0xb34e52b1 -0, 245, 245, 1, 152064, 0xf55ff493 -0, 246, 246, 1, 152064, 0xb0e8282a -0, 247, 247, 1, 152064, 0xe9510bbe -0, 248, 248, 1, 152064, 0x292e8c5a -0, 249, 249, 1, 152064, 0x62b9d2b0 -0, 250, 250, 1, 152064, 0x3a8cc827 -0, 251, 251, 1, 152064, 0x25cc465e -0, 252, 252, 1, 152064, 0xf2bc32e2 -0, 253, 253, 1, 152064, 0x6141f914 -0, 254, 254, 1, 152064, 0x1171256f -0, 255, 255, 1, 152064, 0x13cb2ded -0, 256, 256, 1, 152064, 0x3d4ca557 -0, 257, 257, 1, 152064, 0xf2b9e72e -0, 258, 258, 1, 152064, 0x03f7547a -0, 259, 259, 1, 152064, 0xc7302955 -0, 260, 260, 1, 152064, 0xe78a46d3 -0, 261, 261, 1, 152064, 0x3726a270 -0, 262, 262, 1, 152064, 0x2f65722a -0, 263, 263, 1, 152064, 0x55acce40 -0, 264, 264, 1, 152064, 0xf6fa9db2 -0, 265, 265, 1, 152064, 0x70a36937 -0, 266, 266, 1, 152064, 0x9313742d -0, 267, 267, 1, 152064, 0x2eb14e53 -0, 268, 268, 1, 152064, 0x3d47c9c3 -0, 269, 269, 1, 152064, 0xd0a90348 -0, 270, 270, 1, 152064, 0x6ad48088 -0, 271, 271, 1, 152064, 0x68e64738 -0, 272, 272, 1, 152064, 0x04c3735a -0, 273, 273, 1, 152064, 0x51d0593f -0, 274, 274, 1, 152064, 0x42cf2b48 -0, 275, 275, 1, 152064, 0xa5496a0c -0, 276, 276, 1, 152064, 0x84c25549 -0, 277, 277, 1, 152064, 0x96691600 -0, 278, 278, 1, 152064, 0x423135db -0, 279, 279, 1, 152064, 0x8d2e08b6 -0, 280, 280, 1, 152064, 0xaeb4c840 -0, 281, 281, 1, 152064, 0xf3e71780 -0, 282, 282, 1, 152064, 0x8858228b -0, 283, 283, 1, 152064, 0xf28613f8 -0, 284, 284, 1, 152064, 0xb5327882 -0, 285, 285, 1, 152064, 0xbb60bb85 -0, 286, 286, 1, 152064, 0x345ab1c9 -0, 287, 287, 1, 152064, 0x8aac2cba -0, 288, 288, 1, 152064, 0x7ce15b4c -0, 289, 289, 1, 152064, 0xc09c55c0 -0, 290, 290, 1, 152064, 0x8482ddd6 -0, 291, 291, 1, 152064, 0xab222a13 -0, 292, 292, 1, 152064, 0xd39b0dea -0, 293, 293, 1, 152064, 0x6dab6e06 -0, 294, 294, 1, 152064, 0xec0891bd -0, 295, 295, 1, 152064, 0x88bd9701 -0, 296, 296, 1, 152064, 0xdf13072a -0, 297, 297, 1, 152064, 0x23b33081 -0, 298, 298, 1, 152064, 0x63943137 -0, 299, 299, 1, 152064, 0xab6a9052 -0, 300, 300, 1, 152064, 0x05485494 +0, 0, 0, 1, 152064, 0x502ec077 +0, 1, 1, 1, 152064, 0x84807243 +0, 2, 2, 1, 152064, 0xd7474a6e +0, 3, 3, 1, 152064, 0x793469bb +0, 4, 4, 1, 152064, 0xb7a0faf7 +0, 5, 5, 1, 152064, 0x1d3d3cba +0, 6, 6, 1, 152064, 0xb62583de +0, 7, 7, 1, 152064, 0xc8422fb1 +0, 8, 8, 1, 152064, 0x321dc699 +0, 9, 9, 1, 152064, 0x7a34d350 +0, 10, 10, 1, 152064, 0xaa4c302d +0, 11, 11, 1, 152064, 0x45fa7ab0 +0, 12, 12, 1, 152064, 0xc7262e41 +0, 13, 13, 1, 152064, 0x3550000c +0, 14, 14, 1, 152064, 0xf4bab54b +0, 15, 15, 1, 152064, 0xaccf9c1a +0, 16, 16, 1, 152064, 0x9bee20e9 +0, 17, 17, 1, 152064, 0x47fb7720 +0, 18, 18, 1, 152064, 0x12c63ffb +0, 19, 19, 1, 152064, 0xfa2b8b4d +0, 20, 20, 1, 152064, 0x279964bd +0, 21, 21, 1, 152064, 0xb8b01c7e +0, 22, 22, 1, 152064, 0x816fa010 +0, 23, 23, 1, 152064, 0x59fe1c8c +0, 24, 24, 1, 152064, 0x13393fad +0, 25, 25, 1, 152064, 0x991a50a4 +0, 26, 26, 1, 152064, 0x57df3eb7 +0, 27, 27, 1, 152064, 0x744371df +0, 28, 28, 1, 152064, 0xe9f6d3ff +0, 29, 29, 1, 152064, 0xc506fba0 +0, 30, 30, 1, 152064, 0x6295b90e +0, 31, 31, 1, 152064, 0xa19cee2d +0, 32, 32, 1, 152064, 0xf8c1b3ca +0, 33, 33, 1, 152064, 0x69f68ce0 +0, 34, 34, 1, 152064, 0x80558bb6 +0, 35, 35, 1, 152064, 0x27824fa5 +0, 36, 36, 1, 152064, 0x27c929a1 +0, 37, 37, 1, 152064, 0xc0fe06d1 +0, 38, 38, 1, 152064, 0xc52bc58c +0, 39, 39, 1, 152064, 0x0a5363c7 +0, 40, 40, 1, 152064, 0xd0f45a0d +0, 41, 41, 1, 152064, 0x274710f9 +0, 42, 42, 1, 152064, 0x89d2d390 +0, 43, 43, 1, 152064, 0x12a9bfb0 +0, 44, 44, 1, 152064, 0x04501a93 +0, 45, 45, 1, 152064, 0xf92cbbf4 +0, 46, 46, 1, 152064, 0xf6d1b27d +0, 47, 47, 1, 152064, 0xe3e904c3 +0, 48, 48, 1, 152064, 0x58f8516d +0, 49, 49, 1, 152064, 0x70370c2b +0, 50, 50, 1, 152064, 0xfeebc88c +0, 51, 51, 1, 152064, 0x974c6ed6 +0, 52, 52, 1, 152064, 0x401bdcf2 +0, 53, 53, 1, 152064, 0xfe61e278 +0, 54, 54, 1, 152064, 0x96ba8bb9 +0, 55, 55, 1, 152064, 0x988492fd +0, 56, 56, 1, 152064, 0xd1d913a9 +0, 57, 57, 1, 152064, 0x6bc46f0e +0, 58, 58, 1, 152064, 0x695ef706 +0, 59, 59, 1, 152064, 0x142045c9 +0, 60, 60, 1, 152064, 0xb390ed87 +0, 61, 61, 1, 152064, 0xb9e6d2e5 +0, 62, 62, 1, 152064, 0xe348797f +0, 63, 63, 1, 152064, 0x1cbd29d6 +0, 64, 64, 1, 152064, 0xbd7dd694 +0, 65, 65, 1, 152064, 0x516873c3 +0, 66, 66, 1, 152064, 0x27bba182 +0, 67, 67, 1, 152064, 0x7541f920 +0, 68, 68, 1, 152064, 0xfdf67042 +0, 69, 69, 1, 152064, 0x6c3c7896 +0, 70, 70, 1, 152064, 0xed86c467 +0, 71, 71, 1, 152064, 0x4ea83ca2 +0, 72, 72, 1, 152064, 0xa3e6725b +0, 73, 73, 1, 152064, 0x917f5f16 +0, 74, 74, 1, 152064, 0x8cf2d2e1 +0, 75, 75, 1, 152064, 0x57a8d116 +0, 76, 76, 1, 152064, 0x0db267d4 +0, 77, 77, 1, 152064, 0xce782ac5 +0, 78, 78, 1, 152064, 0x1c9d8518 +0, 79, 79, 1, 152064, 0x47598ac7 +0, 80, 80, 1, 152064, 0xc5033d97 +0, 81, 81, 1, 152064, 0xd7aaa3a4 +0, 82, 82, 1, 152064, 0x078afc96 +0, 83, 83, 1, 152064, 0xc9fe673d +0, 84, 84, 1, 152064, 0xe9284066 +0, 85, 85, 1, 152064, 0xbc570982 +0, 86, 86, 1, 152064, 0x0aac8574 +0, 87, 87, 1, 152064, 0x098cbeee +0, 88, 88, 1, 152064, 0x19c36a9d +0, 89, 89, 1, 152064, 0x8fe4a893 +0, 90, 90, 1, 152064, 0x0b652f17 +0, 91, 91, 1, 152064, 0x10f2e6bf +0, 92, 92, 1, 152064, 0x7ce5634e +0, 93, 93, 1, 152064, 0x8fe4ac6c +0, 94, 94, 1, 152064, 0xcaba749e +0, 95, 95, 1, 152064, 0x5f8a0d5c +0, 96, 96, 1, 152064, 0xcaa66bbc +0, 97, 97, 1, 152064, 0xc87ae617 +0, 98, 98, 1, 152064, 0xe8ef4dd7 +0, 99, 99, 1, 152064, 0xdfca5a07 +0, 100, 100, 1, 152064, 0x5f7eab7d +0, 101, 101, 1, 152064, 0x8a65ebbb +0, 102, 102, 1, 152064, 0x4beab4a0 +0, 103, 103, 1, 152064, 0xb5e6ab30 +0, 104, 104, 1, 152064, 0x8fe4f4d4 +0, 105, 105, 1, 152064, 0x95bde1ca +0, 106, 106, 1, 152064, 0xcc5e3a53 +0, 107, 107, 1, 152064, 0xf09f1dd7 +0, 108, 108, 1, 152064, 0x10179672 +0, 109, 109, 1, 152064, 0x4ad16184 +0, 110, 110, 1, 152064, 0x9efa0e23 +0, 111, 111, 1, 152064, 0x22f59522 +0, 112, 112, 1, 152064, 0x4d38f09d +0, 113, 113, 1, 152064, 0x4c5ebf56 +0, 114, 114, 1, 152064, 0xb19d5077 +0, 115, 115, 1, 152064, 0xa98576b9 +0, 116, 116, 1, 152064, 0x65324239 +0, 117, 117, 1, 152064, 0x709e4031 +0, 118, 118, 1, 152064, 0xf8e81681 +0, 119, 119, 1, 152064, 0x058514e5 +0, 120, 120, 1, 152064, 0xd1d1c806 +0, 121, 121, 1, 152064, 0x0e4dde57 +0, 122, 122, 1, 152064, 0x49e9c2bb +0, 123, 123, 1, 152064, 0x01417ce6 +0, 124, 124, 1, 152064, 0xda7ebbf1 +0, 125, 125, 1, 152064, 0xa22906b7 +0, 126, 126, 1, 152064, 0x32e2df87 +0, 127, 127, 1, 152064, 0x69917c8f +0, 128, 128, 1, 152064, 0xea8ed2cc +0, 129, 129, 1, 152064, 0x0b8d57f1 +0, 130, 130, 1, 152064, 0x5f683bcd +0, 131, 131, 1, 152064, 0x5162fe2f +0, 132, 132, 1, 152064, 0x49c052f8 +0, 133, 133, 1, 152064, 0x990b69ba +0, 134, 134, 1, 152064, 0xa6d4f99f +0, 135, 135, 1, 152064, 0xe79ef4da +0, 136, 136, 1, 152064, 0x5e8a3847 +0, 137, 137, 1, 152064, 0x38b1e75f +0, 138, 138, 1, 152064, 0xf5c91bed +0, 139, 139, 1, 152064, 0xd59a6d26 +0, 140, 140, 1, 152064, 0xc361de06 +0, 141, 141, 1, 152064, 0x63ed2229 +0, 142, 142, 1, 152064, 0xb8229205 +0, 143, 143, 1, 152064, 0x7c6619af +0, 144, 144, 1, 152064, 0x4126b02f +0, 145, 145, 1, 152064, 0x9250b99b +0, 146, 146, 1, 152064, 0x589778f9 +0, 147, 147, 1, 152064, 0xed1fa45b +0, 148, 148, 1, 152064, 0x700b6f32 +0, 149, 149, 1, 152064, 0x0590df55 +0, 150, 150, 1, 152064, 0x3e9c4018 +0, 151, 151, 1, 152064, 0x957b8860 +0, 152, 152, 1, 152064, 0x56161560 +0, 153, 153, 1, 152064, 0xbc43bc3b +0, 154, 154, 1, 152064, 0x508d8632 +0, 155, 155, 1, 152064, 0xbc5736d8 +0, 156, 156, 1, 152064, 0xed7d3aef +0, 157, 157, 1, 152064, 0x1dcdda9f +0, 158, 158, 1, 152064, 0x8ef6d5c9 +0, 159, 159, 1, 152064, 0x15466acc +0, 160, 160, 1, 152064, 0x45d4cf67 +0, 161, 161, 1, 152064, 0x8c900b9d +0, 162, 162, 1, 152064, 0x747006e0 +0, 163, 163, 1, 152064, 0xac920a0c +0, 164, 164, 1, 152064, 0xb8210c27 +0, 165, 165, 1, 152064, 0x7dbb873a +0, 166, 166, 1, 152064, 0x0d4d7584 +0, 167, 167, 1, 152064, 0xefb3fe60 +0, 168, 168, 1, 152064, 0x905e2644 +0, 169, 169, 1, 152064, 0x7c04e534 +0, 170, 170, 1, 152064, 0x8889972a +0, 171, 171, 1, 152064, 0x21c7d8ad +0, 172, 172, 1, 152064, 0x1c641176 +0, 173, 173, 1, 152064, 0xf71489a4 +0, 174, 174, 1, 152064, 0xd7ac5555 +0, 175, 175, 1, 152064, 0xb4609c6d +0, 176, 176, 1, 152064, 0xf5b2bd5e +0, 177, 177, 1, 152064, 0x9f43ce57 +0, 178, 178, 1, 152064, 0x77642dd3 +0, 179, 179, 1, 152064, 0x3e79565c +0, 180, 180, 1, 152064, 0x95f40b8e +0, 181, 181, 1, 152064, 0x3c8ca4d4 +0, 182, 182, 1, 152064, 0xa02ac497 +0, 183, 183, 1, 152064, 0x4c93b377 +0, 184, 184, 1, 152064, 0x55f5ac68 +0, 185, 185, 1, 152064, 0xf8652eca +0, 186, 186, 1, 152064, 0x56e94574 +0, 187, 187, 1, 152064, 0x6d8302e1 +0, 188, 188, 1, 152064, 0x29a57061 +0, 189, 189, 1, 152064, 0x24e4cfdc +0, 190, 190, 1, 152064, 0xf5a5d62a +0, 191, 191, 1, 152064, 0x998870c1 +0, 192, 192, 1, 152064, 0xa15b1f4e +0, 193, 193, 1, 152064, 0xb0ccb51f +0, 194, 194, 1, 152064, 0xeaaf59ab +0, 195, 195, 1, 152064, 0x7e2b4fe6 +0, 196, 196, 1, 152064, 0x72299fea +0, 197, 197, 1, 152064, 0x769da8b2 +0, 198, 198, 1, 152064, 0xefad7ef8 +0, 199, 199, 1, 152064, 0x24819983 +0, 200, 200, 1, 152064, 0x2aad32ab +0, 201, 201, 1, 152064, 0xc80cac79 +0, 202, 202, 1, 152064, 0x1659d628 +0, 203, 203, 1, 152064, 0xef941f66 +0, 204, 204, 1, 152064, 0x0d7fcdb5 +0, 205, 205, 1, 152064, 0x7c1853fa +0, 206, 206, 1, 152064, 0xb94c4d3c +0, 207, 207, 1, 152064, 0xc47adfc2 +0, 208, 208, 1, 152064, 0x366a6729 +0, 209, 209, 1, 152064, 0x7eb37b70 +0, 210, 210, 1, 152064, 0xafd54c27 +0, 211, 211, 1, 152064, 0x67b18636 +0, 212, 212, 1, 152064, 0x93b22dcf +0, 213, 213, 1, 152064, 0xa64991f1 +0, 214, 214, 1, 152064, 0xd32a7102 +0, 215, 215, 1, 152064, 0xff665d1c +0, 216, 216, 1, 152064, 0xf107cc31 +0, 217, 217, 1, 152064, 0xf5b25652 +0, 218, 218, 1, 152064, 0x8caf783d +0, 219, 219, 1, 152064, 0x72f3eb00 +0, 220, 220, 1, 152064, 0xb5aea5f8 +0, 221, 221, 1, 152064, 0xee70e870 +0, 222, 222, 1, 152064, 0x7c3a0156 +0, 223, 223, 1, 152064, 0x871b6383 +0, 224, 224, 1, 152064, 0x48d831ff +0, 225, 225, 1, 152064, 0xca233913 +0, 226, 226, 1, 152064, 0xe14bc5eb +0, 227, 227, 1, 152064, 0x9b1d27e7 +0, 228, 228, 1, 152064, 0xfb9637f7 +0, 229, 229, 1, 152064, 0x0c022157 +0, 230, 230, 1, 152064, 0x16d35fc9 +0, 231, 231, 1, 152064, 0x6d935f71 +0, 232, 232, 1, 152064, 0xae4066fa +0, 233, 233, 1, 152064, 0xcef94fdc +0, 234, 234, 1, 152064, 0xc234edb9 +0, 235, 235, 1, 152064, 0x26a4f2e2 +0, 236, 236, 1, 152064, 0xd29ac23e +0, 237, 237, 1, 152064, 0xb7604395 +0, 238, 238, 1, 152064, 0x408084f6 +0, 239, 239, 1, 152064, 0x0a02026c +0, 240, 240, 1, 152064, 0x78b33c7c +0, 241, 241, 1, 152064, 0xcb02b874 +0, 242, 242, 1, 152064, 0xf566513b +0, 243, 243, 1, 152064, 0xb34e52b1 +0, 244, 244, 1, 152064, 0xf55ff493 +0, 245, 245, 1, 152064, 0xb0e8282a +0, 246, 246, 1, 152064, 0xe9510bbe +0, 247, 247, 1, 152064, 0x292e8c5a +0, 248, 248, 1, 152064, 0x62b9d2b0 +0, 249, 249, 1, 152064, 0x3a8cc827 +0, 250, 250, 1, 152064, 0x25cc465e +0, 251, 251, 1, 152064, 0xf2bc32e2 +0, 252, 252, 1, 152064, 0x6141f914 +0, 253, 253, 1, 152064, 0x1171256f +0, 254, 254, 1, 152064, 0x13cb2ded +0, 255, 255, 1, 152064, 0x3d4ca557 +0, 256, 256, 1, 152064, 0xf2b9e72e +0, 257, 257, 1, 152064, 0x03f7547a +0, 258, 258, 1, 152064, 0xc7302955 +0, 259, 259, 1, 152064, 0xe78a46d3 +0, 260, 260, 1, 152064, 0x3726a270 +0, 261, 261, 1, 152064, 0x2f65722a +0, 262, 262, 1, 152064, 0x55acce40 +0, 263, 263, 1, 152064, 0xf6fa9db2 +0, 264, 264, 1, 152064, 0x70a36937 +0, 265, 265, 1, 152064, 0x9313742d +0, 266, 266, 1, 152064, 0x2eb14e53 +0, 267, 267, 1, 152064, 0x3d47c9c3 +0, 268, 268, 1, 152064, 0xd0a90348 +0, 269, 269, 1, 152064, 0x6ad48088 +0, 270, 270, 1, 152064, 0x68e64738 +0, 271, 271, 1, 152064, 0x04c3735a +0, 272, 272, 1, 152064, 0x51d0593f +0, 273, 273, 1, 152064, 0x42cf2b48 +0, 274, 274, 1, 152064, 0xa5496a0c +0, 275, 275, 1, 152064, 0x84c25549 +0, 276, 276, 1, 152064, 0x96691600 +0, 277, 277, 1, 152064, 0x423135db +0, 278, 278, 1, 152064, 0x8d2e08b6 +0, 279, 279, 1, 152064, 0xaeb4c840 +0, 280, 280, 1, 152064, 0xf3e71780 +0, 281, 281, 1, 152064, 0x8858228b +0, 282, 282, 1, 152064, 0xf28613f8 +0, 283, 283, 1, 152064, 0xb5327882 +0, 284, 284, 1, 152064, 0xbb60bb85 +0, 285, 285, 1, 152064, 0x345ab1c9 +0, 286, 286, 1, 152064, 0x8aac2cba +0, 287, 287, 1, 152064, 0x7ce15b4c +0, 288, 288, 1, 152064, 0xc09c55c0 +0, 289, 289, 1, 152064, 0x8482ddd6 +0, 290, 290, 1, 152064, 0xab222a13 +0, 291, 291, 1, 152064, 0xd39b0dea +0, 292, 292, 1, 152064, 0x6dab6e06 +0, 293, 293, 1, 152064, 0xec0891bd +0, 294, 294, 1, 152064, 0x88bd9701 +0, 295, 295, 1, 152064, 0xdf13072a +0, 296, 296, 1, 152064, 0x23b33081 +0, 297, 297, 1, 152064, 0x63943137 +0, 298, 298, 1, 152064, 0xab6a9052 +0, 299, 299, 1, 152064, 0x05485494 diff --git a/tests/ref/fate/h264-conformance-frext-hpcaflnl_bcrm_c b/tests/ref/fate/h264-conformance-frext-hpcaflnl_bcrm_c index d6c41dd6430..9958f1616f4 100644 --- a/tests/ref/fate/h264-conformance-frext-hpcaflnl_bcrm_c +++ b/tests/ref/fate/h264-conformance-frext-hpcaflnl_bcrm_c @@ -3,303 +3,303 @@ #codec_id 0: rawvideo #dimensions 0: 352x288 #sar 0: 0/1 -0, 1, 1, 1, 152064, 0x3e39c08b -0, 2, 2, 1, 152064, 0xabc67990 -0, 3, 3, 1, 152064, 0x19614e74 -0, 4, 4, 1, 152064, 0xa3776beb -0, 5, 5, 1, 152064, 0xcce6ffdf -0, 6, 6, 1, 152064, 0xb0e94746 -0, 7, 7, 1, 152064, 0xdb1a84ef -0, 8, 8, 1, 152064, 0xb2624509 -0, 9, 9, 1, 152064, 0x32e2d826 -0, 10, 10, 1, 152064, 0xb3bddf0b -0, 11, 11, 1, 152064, 0x2e273ce3 -0, 12, 12, 1, 152064, 0x67af7e4d -0, 13, 13, 1, 152064, 0x505c3261 -0, 14, 14, 1, 152064, 0xa43d015e -0, 15, 15, 1, 152064, 0xad41c1f6 -0, 16, 16, 1, 152064, 0x633ba55f -0, 17, 17, 1, 152064, 0xe80634f0 -0, 18, 18, 1, 152064, 0x80a07dc9 -0, 19, 19, 1, 152064, 0x0e7a3bbf -0, 20, 20, 1, 152064, 0xcb099196 -0, 21, 21, 1, 152064, 0x57c96db5 -0, 22, 22, 1, 152064, 0xccd422fa -0, 23, 23, 1, 152064, 0x0850b7a7 -0, 24, 24, 1, 152064, 0x30e33156 -0, 25, 25, 1, 152064, 0x34e13f9a -0, 26, 26, 1, 152064, 0x03d36000 -0, 27, 27, 1, 152064, 0xbf7d49da -0, 28, 28, 1, 152064, 0x77336d09 -0, 29, 29, 1, 152064, 0xca8be5a9 -0, 30, 30, 1, 152064, 0xe57c0b08 -0, 31, 31, 1, 152064, 0xbe77c093 -0, 32, 32, 1, 152064, 0x6bf1ff05 -0, 33, 33, 1, 152064, 0x9142babf -0, 34, 34, 1, 152064, 0x08db8e67 -0, 35, 35, 1, 152064, 0x69ac8cb6 -0, 36, 36, 1, 152064, 0xaa3b5c88 -0, 37, 37, 1, 152064, 0x9bd32638 -0, 38, 38, 1, 152064, 0x7972115a -0, 39, 39, 1, 152064, 0x5c1dd47b -0, 40, 40, 1, 152064, 0x8a196e02 -0, 41, 41, 1, 152064, 0xa89672bc -0, 42, 42, 1, 152064, 0x27b220e4 -0, 43, 43, 1, 152064, 0xfa38dc4a -0, 44, 44, 1, 152064, 0x4784c639 -0, 45, 45, 1, 152064, 0xa5e4229a -0, 46, 46, 1, 152064, 0xa986bdfc -0, 47, 47, 1, 152064, 0x2951b47b -0, 48, 48, 1, 152064, 0x4df404a6 -0, 49, 49, 1, 152064, 0xc75155e8 -0, 50, 50, 1, 152064, 0xfc05248c -0, 51, 51, 1, 152064, 0x5d53da10 -0, 52, 52, 1, 152064, 0x284376ec -0, 53, 53, 1, 152064, 0x19fce380 -0, 54, 54, 1, 152064, 0x876be6c9 -0, 55, 55, 1, 152064, 0x39eb8ff9 -0, 56, 56, 1, 152064, 0x289c9543 -0, 57, 57, 1, 152064, 0x24dd2356 -0, 58, 58, 1, 152064, 0x1dc17d3c -0, 59, 59, 1, 152064, 0xd17c00ac -0, 60, 60, 1, 152064, 0xc2ad54de -0, 61, 61, 1, 152064, 0xbe11ee2f -0, 62, 62, 1, 152064, 0x3db9dc89 -0, 63, 63, 1, 152064, 0xac0d7bc2 -0, 64, 64, 1, 152064, 0x8dab2dde -0, 65, 65, 1, 152064, 0x566ad225 -0, 66, 66, 1, 152064, 0x587c7853 -0, 67, 67, 1, 152064, 0x601c9c80 -0, 68, 68, 1, 152064, 0x2afaf751 -0, 69, 69, 1, 152064, 0x1c9f7e3a -0, 70, 70, 1, 152064, 0x899475bf -0, 71, 71, 1, 152064, 0x0d65c7d9 -0, 72, 72, 1, 152064, 0xafd63d12 -0, 73, 73, 1, 152064, 0x162e62b9 -0, 74, 74, 1, 152064, 0x5c9554be -0, 75, 75, 1, 152064, 0x35fbdaa2 -0, 76, 76, 1, 152064, 0x6438cbd8 -0, 77, 77, 1, 152064, 0xde0772c9 -0, 78, 78, 1, 152064, 0x79f82854 -0, 79, 79, 1, 152064, 0x86957840 -0, 80, 80, 1, 152064, 0xd9468cbf -0, 81, 81, 1, 152064, 0x23e74609 -0, 82, 82, 1, 152064, 0x3919a146 -0, 83, 83, 1, 152064, 0xd641078b -0, 84, 84, 1, 152064, 0x24397220 -0, 85, 85, 1, 152064, 0xe7fc3a7c -0, 86, 86, 1, 152064, 0x3997154a -0, 87, 87, 1, 152064, 0x2af3952c -0, 88, 88, 1, 152064, 0x274ac07a -0, 89, 89, 1, 152064, 0x288f7b09 -0, 90, 90, 1, 152064, 0xe6f9b022 -0, 91, 91, 1, 152064, 0xf09e2fbb -0, 92, 92, 1, 152064, 0x7244e477 -0, 93, 93, 1, 152064, 0x0dfc72eb -0, 94, 94, 1, 152064, 0x0322b21f -0, 95, 95, 1, 152064, 0x18b08205 -0, 96, 96, 1, 152064, 0x6606153e -0, 97, 97, 1, 152064, 0x85186272 -0, 98, 98, 1, 152064, 0x3369f064 -0, 99, 99, 1, 152064, 0xbe0d5a44 -0, 100, 100, 1, 152064, 0x320258bb -0, 101, 101, 1, 152064, 0x4d6fb091 -0, 102, 102, 1, 152064, 0xc9bbf5e7 -0, 103, 103, 1, 152064, 0x0aa1b69b -0, 104, 104, 1, 152064, 0x85b9ac11 -0, 105, 105, 1, 152064, 0xb25ff818 -0, 106, 106, 1, 152064, 0xa155dc25 -0, 107, 107, 1, 152064, 0xa8e03bfd -0, 108, 108, 1, 152064, 0x0a862956 -0, 109, 109, 1, 152064, 0x11b49264 -0, 110, 110, 1, 152064, 0xa94e664e -0, 111, 111, 1, 152064, 0x330e0fa2 -0, 112, 112, 1, 152064, 0xaf3d9518 -0, 113, 113, 1, 152064, 0x0836f2e8 -0, 114, 114, 1, 152064, 0xbf6dc578 -0, 115, 115, 1, 152064, 0x7b524d20 -0, 116, 116, 1, 152064, 0x9ef7677f -0, 117, 117, 1, 152064, 0xeacf3f34 -0, 118, 118, 1, 152064, 0xfb4e3dbe -0, 119, 119, 1, 152064, 0xb46e25cb -0, 120, 120, 1, 152064, 0x363c1603 -0, 121, 121, 1, 152064, 0x263fc542 -0, 122, 122, 1, 152064, 0xf106e548 -0, 123, 123, 1, 152064, 0xde43c56a -0, 124, 124, 1, 152064, 0xc2c4770a -0, 125, 125, 1, 152064, 0x122fce19 -0, 126, 126, 1, 152064, 0x3ba01434 -0, 127, 127, 1, 152064, 0x0e8ce5ee -0, 128, 128, 1, 152064, 0x6ceb82e1 -0, 129, 129, 1, 152064, 0xa23ee21c -0, 130, 130, 1, 152064, 0xc6d960f9 -0, 131, 131, 1, 152064, 0x0de15258 -0, 132, 132, 1, 152064, 0x187b0333 -0, 133, 133, 1, 152064, 0x92e6582f -0, 134, 134, 1, 152064, 0xb9586ce0 -0, 135, 135, 1, 152064, 0xefd803b5 -0, 136, 136, 1, 152064, 0x24eafb29 -0, 137, 137, 1, 152064, 0x20c73b14 -0, 138, 138, 1, 152064, 0xbd7ceaaa -0, 139, 139, 1, 152064, 0x775216c8 -0, 140, 140, 1, 152064, 0xa08971c7 -0, 141, 141, 1, 152064, 0xef0ee865 -0, 142, 142, 1, 152064, 0x9ac61c2f -0, 143, 143, 1, 152064, 0x52ae8ea9 -0, 144, 144, 1, 152064, 0x06571c14 -0, 145, 145, 1, 152064, 0x6e78ad33 -0, 146, 146, 1, 152064, 0xad01c627 -0, 147, 147, 1, 152064, 0xbfe074d3 -0, 148, 148, 1, 152064, 0x9357a183 -0, 149, 149, 1, 152064, 0x8de7767f -0, 150, 150, 1, 152064, 0xa5e6e76e -0, 151, 151, 1, 152064, 0xa6f646fe -0, 152, 152, 1, 152064, 0x132e99f8 -0, 153, 153, 1, 152064, 0xb79f27de -0, 154, 154, 1, 152064, 0x36d3cdcf -0, 155, 155, 1, 152064, 0xdc938336 -0, 156, 156, 1, 152064, 0xacaa3a7f -0, 157, 157, 1, 152064, 0xc61a37fd -0, 158, 158, 1, 152064, 0x4fe1ddf0 -0, 159, 159, 1, 152064, 0xc0f7d660 -0, 160, 160, 1, 152064, 0xd72458ea -0, 161, 161, 1, 152064, 0x6978d123 -0, 162, 162, 1, 152064, 0x64e60ccf -0, 163, 163, 1, 152064, 0xaa07004c -0, 164, 164, 1, 152064, 0x07cd1064 -0, 165, 165, 1, 152064, 0xa82320e5 -0, 166, 166, 1, 152064, 0xaedd8d30 -0, 167, 167, 1, 152064, 0x79b082ea -0, 168, 168, 1, 152064, 0x9ed800ab -0, 169, 169, 1, 152064, 0xde592bb4 -0, 170, 170, 1, 152064, 0xd966df88 -0, 171, 171, 1, 152064, 0xf921988a -0, 172, 172, 1, 152064, 0x557ad9ae -0, 173, 173, 1, 152064, 0xc3f31a9a -0, 174, 174, 1, 152064, 0x65248561 -0, 175, 175, 1, 152064, 0x63df4aa6 -0, 176, 176, 1, 152064, 0x618da0a9 -0, 177, 177, 1, 152064, 0xe6f1c435 -0, 178, 178, 1, 152064, 0x9f90c38f -0, 179, 179, 1, 152064, 0xd2853e14 -0, 180, 180, 1, 152064, 0x6e0268a9 -0, 181, 181, 1, 152064, 0x393712d1 -0, 182, 182, 1, 152064, 0x470da25f -0, 183, 183, 1, 152064, 0xaf55cb3d -0, 184, 184, 1, 152064, 0x6935b8b9 -0, 185, 185, 1, 152064, 0x5409a15f -0, 186, 186, 1, 152064, 0x09073fee -0, 187, 187, 1, 152064, 0xfb274e82 -0, 188, 188, 1, 152064, 0x1a770581 -0, 189, 189, 1, 152064, 0x17277d0d -0, 190, 190, 1, 152064, 0xd4dcd982 -0, 191, 191, 1, 152064, 0x6b04eaf3 -0, 192, 192, 1, 152064, 0x8a3d822e -0, 193, 193, 1, 152064, 0x1b971ec9 -0, 194, 194, 1, 152064, 0x14e0c0f6 -0, 195, 195, 1, 152064, 0x00667450 -0, 196, 196, 1, 152064, 0xd2385902 -0, 197, 197, 1, 152064, 0x905da6ab -0, 198, 198, 1, 152064, 0xa3ffb18b -0, 199, 199, 1, 152064, 0x10d48b19 -0, 200, 200, 1, 152064, 0xb2c7a3bd -0, 201, 201, 1, 152064, 0x45593e96 -0, 202, 202, 1, 152064, 0x47a0b60c -0, 203, 203, 1, 152064, 0x68c6d1b9 -0, 204, 204, 1, 152064, 0xbc881fcc -0, 205, 205, 1, 152064, 0x422cc6f2 -0, 206, 206, 1, 152064, 0x9b686410 -0, 207, 207, 1, 152064, 0x35dc5e86 -0, 208, 208, 1, 152064, 0x247bedaa -0, 209, 209, 1, 152064, 0x22b76fd1 -0, 210, 210, 1, 152064, 0x67cc7a75 -0, 211, 211, 1, 152064, 0xa197521e -0, 212, 212, 1, 152064, 0x428c8662 -0, 213, 213, 1, 152064, 0x33dc2c73 -0, 214, 214, 1, 152064, 0x5b538903 -0, 215, 215, 1, 152064, 0x3c4176b6 -0, 216, 216, 1, 152064, 0x774364ba -0, 217, 217, 1, 152064, 0xf237d03e -0, 218, 218, 1, 152064, 0xac8746fb -0, 219, 219, 1, 152064, 0x6b306a84 -0, 220, 220, 1, 152064, 0xa2ace513 -0, 221, 221, 1, 152064, 0x709c9be7 -0, 222, 222, 1, 152064, 0x2403f373 -0, 223, 223, 1, 152064, 0x147bf717 -0, 224, 224, 1, 152064, 0xe58964c8 -0, 225, 225, 1, 152064, 0xa0da36fc -0, 226, 226, 1, 152064, 0x1ac1355c -0, 227, 227, 1, 152064, 0x8a31c9f2 -0, 228, 228, 1, 152064, 0x42ba205c -0, 229, 229, 1, 152064, 0xa11b3575 -0, 230, 230, 1, 152064, 0xcb35207c -0, 231, 231, 1, 152064, 0x528f6189 -0, 232, 232, 1, 152064, 0x34f05bd7 -0, 233, 233, 1, 152064, 0x72317356 -0, 234, 234, 1, 152064, 0xaabd5028 -0, 235, 235, 1, 152064, 0x13dbeb7b -0, 236, 236, 1, 152064, 0x62f1e8a8 -0, 237, 237, 1, 152064, 0x1723bfcd -0, 238, 238, 1, 152064, 0x5c083c00 -0, 239, 239, 1, 152064, 0x52137894 -0, 240, 240, 1, 152064, 0xef1e082c -0, 241, 241, 1, 152064, 0x664b3d53 -0, 242, 242, 1, 152064, 0x2eb9b296 -0, 243, 243, 1, 152064, 0xd0ca511e -0, 244, 244, 1, 152064, 0x012d4724 -0, 245, 245, 1, 152064, 0xa847f5af -0, 246, 246, 1, 152064, 0x483a2fde -0, 247, 247, 1, 152064, 0xd1ab0257 -0, 248, 248, 1, 152064, 0x414692c7 -0, 249, 249, 1, 152064, 0x0b79df88 -0, 250, 250, 1, 152064, 0xdaa2c4a3 -0, 251, 251, 1, 152064, 0xd1b44500 -0, 252, 252, 1, 152064, 0xfd3d2cf3 -0, 253, 253, 1, 152064, 0xfdc0f748 -0, 254, 254, 1, 152064, 0xce762a2a -0, 255, 255, 1, 152064, 0x08b63572 -0, 256, 256, 1, 152064, 0x5a46a38d -0, 257, 257, 1, 152064, 0x03cee9c0 -0, 258, 258, 1, 152064, 0x9ee45473 -0, 259, 259, 1, 152064, 0x5a432386 -0, 260, 260, 1, 152064, 0x54c83d87 -0, 261, 261, 1, 152064, 0xc9caa1de -0, 262, 262, 1, 152064, 0xa28367f1 -0, 263, 263, 1, 152064, 0x2607cdf1 -0, 264, 264, 1, 152064, 0x06baa8de -0, 265, 265, 1, 152064, 0xf5346e32 -0, 266, 266, 1, 152064, 0x6d3e732b -0, 267, 267, 1, 152064, 0x798c584b -0, 268, 268, 1, 152064, 0x4076c948 -0, 269, 269, 1, 152064, 0x868cf63a -0, 270, 270, 1, 152064, 0x23107ac5 -0, 271, 271, 1, 152064, 0x306f3fe2 -0, 272, 272, 1, 152064, 0xbd1d71d6 -0, 273, 273, 1, 152064, 0x1429545f -0, 274, 274, 1, 152064, 0xaded29aa -0, 275, 275, 1, 152064, 0x9b455a94 -0, 276, 276, 1, 152064, 0xb3774ce7 -0, 277, 277, 1, 152064, 0x92580986 -0, 278, 278, 1, 152064, 0x0eae2f95 -0, 279, 279, 1, 152064, 0x599208b2 -0, 280, 280, 1, 152064, 0x4804c04c -0, 281, 281, 1, 152064, 0x5f730e8f -0, 282, 282, 1, 152064, 0x3e501d1e -0, 283, 283, 1, 152064, 0x32100740 -0, 284, 284, 1, 152064, 0x62226ff8 -0, 285, 285, 1, 152064, 0x7683b622 -0, 286, 286, 1, 152064, 0xc3e0aec1 -0, 287, 287, 1, 152064, 0xfac12608 -0, 288, 288, 1, 152064, 0xb21a5781 -0, 289, 289, 1, 152064, 0x8f1e4964 -0, 290, 290, 1, 152064, 0x0f62dd6e -0, 291, 291, 1, 152064, 0xac062ac4 -0, 292, 292, 1, 152064, 0x1b320f7a -0, 293, 293, 1, 152064, 0x346e7211 -0, 294, 294, 1, 152064, 0xe47592f3 -0, 295, 295, 1, 152064, 0xa3a7919c -0, 296, 296, 1, 152064, 0xa3580fa6 -0, 297, 297, 1, 152064, 0xc73430c1 -0, 298, 298, 1, 152064, 0x994a2c18 -0, 299, 299, 1, 152064, 0x0b5d8d45 -0, 300, 300, 1, 152064, 0x9eed5109 +0, 0, 0, 1, 152064, 0x3e39c08b +0, 1, 1, 1, 152064, 0xabc67990 +0, 2, 2, 1, 152064, 0x19614e74 +0, 3, 3, 1, 152064, 0xa3776beb +0, 4, 4, 1, 152064, 0xcce6ffdf +0, 5, 5, 1, 152064, 0xb0e94746 +0, 6, 6, 1, 152064, 0xdb1a84ef +0, 7, 7, 1, 152064, 0xb2624509 +0, 8, 8, 1, 152064, 0x32e2d826 +0, 9, 9, 1, 152064, 0xb3bddf0b +0, 10, 10, 1, 152064, 0x2e273ce3 +0, 11, 11, 1, 152064, 0x67af7e4d +0, 12, 12, 1, 152064, 0x505c3261 +0, 13, 13, 1, 152064, 0xa43d015e +0, 14, 14, 1, 152064, 0xad41c1f6 +0, 15, 15, 1, 152064, 0x633ba55f +0, 16, 16, 1, 152064, 0xe80634f0 +0, 17, 17, 1, 152064, 0x80a07dc9 +0, 18, 18, 1, 152064, 0x0e7a3bbf +0, 19, 19, 1, 152064, 0xcb099196 +0, 20, 20, 1, 152064, 0x57c96db5 +0, 21, 21, 1, 152064, 0xccd422fa +0, 22, 22, 1, 152064, 0x0850b7a7 +0, 23, 23, 1, 152064, 0x30e33156 +0, 24, 24, 1, 152064, 0x34e13f9a +0, 25, 25, 1, 152064, 0x03d36000 +0, 26, 26, 1, 152064, 0xbf7d49da +0, 27, 27, 1, 152064, 0x77336d09 +0, 28, 28, 1, 152064, 0xca8be5a9 +0, 29, 29, 1, 152064, 0xe57c0b08 +0, 30, 30, 1, 152064, 0xbe77c093 +0, 31, 31, 1, 152064, 0x6bf1ff05 +0, 32, 32, 1, 152064, 0x9142babf +0, 33, 33, 1, 152064, 0x08db8e67 +0, 34, 34, 1, 152064, 0x69ac8cb6 +0, 35, 35, 1, 152064, 0xaa3b5c88 +0, 36, 36, 1, 152064, 0x9bd32638 +0, 37, 37, 1, 152064, 0x7972115a +0, 38, 38, 1, 152064, 0x5c1dd47b +0, 39, 39, 1, 152064, 0x8a196e02 +0, 40, 40, 1, 152064, 0xa89672bc +0, 41, 41, 1, 152064, 0x27b220e4 +0, 42, 42, 1, 152064, 0xfa38dc4a +0, 43, 43, 1, 152064, 0x4784c639 +0, 44, 44, 1, 152064, 0xa5e4229a +0, 45, 45, 1, 152064, 0xa986bdfc +0, 46, 46, 1, 152064, 0x2951b47b +0, 47, 47, 1, 152064, 0x4df404a6 +0, 48, 48, 1, 152064, 0xc75155e8 +0, 49, 49, 1, 152064, 0xfc05248c +0, 50, 50, 1, 152064, 0x5d53da10 +0, 51, 51, 1, 152064, 0x284376ec +0, 52, 52, 1, 152064, 0x19fce380 +0, 53, 53, 1, 152064, 0x876be6c9 +0, 54, 54, 1, 152064, 0x39eb8ff9 +0, 55, 55, 1, 152064, 0x289c9543 +0, 56, 56, 1, 152064, 0x24dd2356 +0, 57, 57, 1, 152064, 0x1dc17d3c +0, 58, 58, 1, 152064, 0xd17c00ac +0, 59, 59, 1, 152064, 0xc2ad54de +0, 60, 60, 1, 152064, 0xbe11ee2f +0, 61, 61, 1, 152064, 0x3db9dc89 +0, 62, 62, 1, 152064, 0xac0d7bc2 +0, 63, 63, 1, 152064, 0x8dab2dde +0, 64, 64, 1, 152064, 0x566ad225 +0, 65, 65, 1, 152064, 0x587c7853 +0, 66, 66, 1, 152064, 0x601c9c80 +0, 67, 67, 1, 152064, 0x2afaf751 +0, 68, 68, 1, 152064, 0x1c9f7e3a +0, 69, 69, 1, 152064, 0x899475bf +0, 70, 70, 1, 152064, 0x0d65c7d9 +0, 71, 71, 1, 152064, 0xafd63d12 +0, 72, 72, 1, 152064, 0x162e62b9 +0, 73, 73, 1, 152064, 0x5c9554be +0, 74, 74, 1, 152064, 0x35fbdaa2 +0, 75, 75, 1, 152064, 0x6438cbd8 +0, 76, 76, 1, 152064, 0xde0772c9 +0, 77, 77, 1, 152064, 0x79f82854 +0, 78, 78, 1, 152064, 0x86957840 +0, 79, 79, 1, 152064, 0xd9468cbf +0, 80, 80, 1, 152064, 0x23e74609 +0, 81, 81, 1, 152064, 0x3919a146 +0, 82, 82, 1, 152064, 0xd641078b +0, 83, 83, 1, 152064, 0x24397220 +0, 84, 84, 1, 152064, 0xe7fc3a7c +0, 85, 85, 1, 152064, 0x3997154a +0, 86, 86, 1, 152064, 0x2af3952c +0, 87, 87, 1, 152064, 0x274ac07a +0, 88, 88, 1, 152064, 0x288f7b09 +0, 89, 89, 1, 152064, 0xe6f9b022 +0, 90, 90, 1, 152064, 0xf09e2fbb +0, 91, 91, 1, 152064, 0x7244e477 +0, 92, 92, 1, 152064, 0x0dfc72eb +0, 93, 93, 1, 152064, 0x0322b21f +0, 94, 94, 1, 152064, 0x18b08205 +0, 95, 95, 1, 152064, 0x6606153e +0, 96, 96, 1, 152064, 0x85186272 +0, 97, 97, 1, 152064, 0x3369f064 +0, 98, 98, 1, 152064, 0xbe0d5a44 +0, 99, 99, 1, 152064, 0x320258bb +0, 100, 100, 1, 152064, 0x4d6fb091 +0, 101, 101, 1, 152064, 0xc9bbf5e7 +0, 102, 102, 1, 152064, 0x0aa1b69b +0, 103, 103, 1, 152064, 0x85b9ac11 +0, 104, 104, 1, 152064, 0xb25ff818 +0, 105, 105, 1, 152064, 0xa155dc25 +0, 106, 106, 1, 152064, 0xa8e03bfd +0, 107, 107, 1, 152064, 0x0a862956 +0, 108, 108, 1, 152064, 0x11b49264 +0, 109, 109, 1, 152064, 0xa94e664e +0, 110, 110, 1, 152064, 0x330e0fa2 +0, 111, 111, 1, 152064, 0xaf3d9518 +0, 112, 112, 1, 152064, 0x0836f2e8 +0, 113, 113, 1, 152064, 0xbf6dc578 +0, 114, 114, 1, 152064, 0x7b524d20 +0, 115, 115, 1, 152064, 0x9ef7677f +0, 116, 116, 1, 152064, 0xeacf3f34 +0, 117, 117, 1, 152064, 0xfb4e3dbe +0, 118, 118, 1, 152064, 0xb46e25cb +0, 119, 119, 1, 152064, 0x363c1603 +0, 120, 120, 1, 152064, 0x263fc542 +0, 121, 121, 1, 152064, 0xf106e548 +0, 122, 122, 1, 152064, 0xde43c56a +0, 123, 123, 1, 152064, 0xc2c4770a +0, 124, 124, 1, 152064, 0x122fce19 +0, 125, 125, 1, 152064, 0x3ba01434 +0, 126, 126, 1, 152064, 0x0e8ce5ee +0, 127, 127, 1, 152064, 0x6ceb82e1 +0, 128, 128, 1, 152064, 0xa23ee21c +0, 129, 129, 1, 152064, 0xc6d960f9 +0, 130, 130, 1, 152064, 0x0de15258 +0, 131, 131, 1, 152064, 0x187b0333 +0, 132, 132, 1, 152064, 0x92e6582f +0, 133, 133, 1, 152064, 0xb9586ce0 +0, 134, 134, 1, 152064, 0xefd803b5 +0, 135, 135, 1, 152064, 0x24eafb29 +0, 136, 136, 1, 152064, 0x20c73b14 +0, 137, 137, 1, 152064, 0xbd7ceaaa +0, 138, 138, 1, 152064, 0x775216c8 +0, 139, 139, 1, 152064, 0xa08971c7 +0, 140, 140, 1, 152064, 0xef0ee865 +0, 141, 141, 1, 152064, 0x9ac61c2f +0, 142, 142, 1, 152064, 0x52ae8ea9 +0, 143, 143, 1, 152064, 0x06571c14 +0, 144, 144, 1, 152064, 0x6e78ad33 +0, 145, 145, 1, 152064, 0xad01c627 +0, 146, 146, 1, 152064, 0xbfe074d3 +0, 147, 147, 1, 152064, 0x9357a183 +0, 148, 148, 1, 152064, 0x8de7767f +0, 149, 149, 1, 152064, 0xa5e6e76e +0, 150, 150, 1, 152064, 0xa6f646fe +0, 151, 151, 1, 152064, 0x132e99f8 +0, 152, 152, 1, 152064, 0xb79f27de +0, 153, 153, 1, 152064, 0x36d3cdcf +0, 154, 154, 1, 152064, 0xdc938336 +0, 155, 155, 1, 152064, 0xacaa3a7f +0, 156, 156, 1, 152064, 0xc61a37fd +0, 157, 157, 1, 152064, 0x4fe1ddf0 +0, 158, 158, 1, 152064, 0xc0f7d660 +0, 159, 159, 1, 152064, 0xd72458ea +0, 160, 160, 1, 152064, 0x6978d123 +0, 161, 161, 1, 152064, 0x64e60ccf +0, 162, 162, 1, 152064, 0xaa07004c +0, 163, 163, 1, 152064, 0x07cd1064 +0, 164, 164, 1, 152064, 0xa82320e5 +0, 165, 165, 1, 152064, 0xaedd8d30 +0, 166, 166, 1, 152064, 0x79b082ea +0, 167, 167, 1, 152064, 0x9ed800ab +0, 168, 168, 1, 152064, 0xde592bb4 +0, 169, 169, 1, 152064, 0xd966df88 +0, 170, 170, 1, 152064, 0xf921988a +0, 171, 171, 1, 152064, 0x557ad9ae +0, 172, 172, 1, 152064, 0xc3f31a9a +0, 173, 173, 1, 152064, 0x65248561 +0, 174, 174, 1, 152064, 0x63df4aa6 +0, 175, 175, 1, 152064, 0x618da0a9 +0, 176, 176, 1, 152064, 0xe6f1c435 +0, 177, 177, 1, 152064, 0x9f90c38f +0, 178, 178, 1, 152064, 0xd2853e14 +0, 179, 179, 1, 152064, 0x6e0268a9 +0, 180, 180, 1, 152064, 0x393712d1 +0, 181, 181, 1, 152064, 0x470da25f +0, 182, 182, 1, 152064, 0xaf55cb3d +0, 183, 183, 1, 152064, 0x6935b8b9 +0, 184, 184, 1, 152064, 0x5409a15f +0, 185, 185, 1, 152064, 0x09073fee +0, 186, 186, 1, 152064, 0xfb274e82 +0, 187, 187, 1, 152064, 0x1a770581 +0, 188, 188, 1, 152064, 0x17277d0d +0, 189, 189, 1, 152064, 0xd4dcd982 +0, 190, 190, 1, 152064, 0x6b04eaf3 +0, 191, 191, 1, 152064, 0x8a3d822e +0, 192, 192, 1, 152064, 0x1b971ec9 +0, 193, 193, 1, 152064, 0x14e0c0f6 +0, 194, 194, 1, 152064, 0x00667450 +0, 195, 195, 1, 152064, 0xd2385902 +0, 196, 196, 1, 152064, 0x905da6ab +0, 197, 197, 1, 152064, 0xa3ffb18b +0, 198, 198, 1, 152064, 0x10d48b19 +0, 199, 199, 1, 152064, 0xb2c7a3bd +0, 200, 200, 1, 152064, 0x45593e96 +0, 201, 201, 1, 152064, 0x47a0b60c +0, 202, 202, 1, 152064, 0x68c6d1b9 +0, 203, 203, 1, 152064, 0xbc881fcc +0, 204, 204, 1, 152064, 0x422cc6f2 +0, 205, 205, 1, 152064, 0x9b686410 +0, 206, 206, 1, 152064, 0x35dc5e86 +0, 207, 207, 1, 152064, 0x247bedaa +0, 208, 208, 1, 152064, 0x22b76fd1 +0, 209, 209, 1, 152064, 0x67cc7a75 +0, 210, 210, 1, 152064, 0xa197521e +0, 211, 211, 1, 152064, 0x428c8662 +0, 212, 212, 1, 152064, 0x33dc2c73 +0, 213, 213, 1, 152064, 0x5b538903 +0, 214, 214, 1, 152064, 0x3c4176b6 +0, 215, 215, 1, 152064, 0x774364ba +0, 216, 216, 1, 152064, 0xf237d03e +0, 217, 217, 1, 152064, 0xac8746fb +0, 218, 218, 1, 152064, 0x6b306a84 +0, 219, 219, 1, 152064, 0xa2ace513 +0, 220, 220, 1, 152064, 0x709c9be7 +0, 221, 221, 1, 152064, 0x2403f373 +0, 222, 222, 1, 152064, 0x147bf717 +0, 223, 223, 1, 152064, 0xe58964c8 +0, 224, 224, 1, 152064, 0xa0da36fc +0, 225, 225, 1, 152064, 0x1ac1355c +0, 226, 226, 1, 152064, 0x8a31c9f2 +0, 227, 227, 1, 152064, 0x42ba205c +0, 228, 228, 1, 152064, 0xa11b3575 +0, 229, 229, 1, 152064, 0xcb35207c +0, 230, 230, 1, 152064, 0x528f6189 +0, 231, 231, 1, 152064, 0x34f05bd7 +0, 232, 232, 1, 152064, 0x72317356 +0, 233, 233, 1, 152064, 0xaabd5028 +0, 234, 234, 1, 152064, 0x13dbeb7b +0, 235, 235, 1, 152064, 0x62f1e8a8 +0, 236, 236, 1, 152064, 0x1723bfcd +0, 237, 237, 1, 152064, 0x5c083c00 +0, 238, 238, 1, 152064, 0x52137894 +0, 239, 239, 1, 152064, 0xef1e082c +0, 240, 240, 1, 152064, 0x664b3d53 +0, 241, 241, 1, 152064, 0x2eb9b296 +0, 242, 242, 1, 152064, 0xd0ca511e +0, 243, 243, 1, 152064, 0x012d4724 +0, 244, 244, 1, 152064, 0xa847f5af +0, 245, 245, 1, 152064, 0x483a2fde +0, 246, 246, 1, 152064, 0xd1ab0257 +0, 247, 247, 1, 152064, 0x414692c7 +0, 248, 248, 1, 152064, 0x0b79df88 +0, 249, 249, 1, 152064, 0xdaa2c4a3 +0, 250, 250, 1, 152064, 0xd1b44500 +0, 251, 251, 1, 152064, 0xfd3d2cf3 +0, 252, 252, 1, 152064, 0xfdc0f748 +0, 253, 253, 1, 152064, 0xce762a2a +0, 254, 254, 1, 152064, 0x08b63572 +0, 255, 255, 1, 152064, 0x5a46a38d +0, 256, 256, 1, 152064, 0x03cee9c0 +0, 257, 257, 1, 152064, 0x9ee45473 +0, 258, 258, 1, 152064, 0x5a432386 +0, 259, 259, 1, 152064, 0x54c83d87 +0, 260, 260, 1, 152064, 0xc9caa1de +0, 261, 261, 1, 152064, 0xa28367f1 +0, 262, 262, 1, 152064, 0x2607cdf1 +0, 263, 263, 1, 152064, 0x06baa8de +0, 264, 264, 1, 152064, 0xf5346e32 +0, 265, 265, 1, 152064, 0x6d3e732b +0, 266, 266, 1, 152064, 0x798c584b +0, 267, 267, 1, 152064, 0x4076c948 +0, 268, 268, 1, 152064, 0x868cf63a +0, 269, 269, 1, 152064, 0x23107ac5 +0, 270, 270, 1, 152064, 0x306f3fe2 +0, 271, 271, 1, 152064, 0xbd1d71d6 +0, 272, 272, 1, 152064, 0x1429545f +0, 273, 273, 1, 152064, 0xaded29aa +0, 274, 274, 1, 152064, 0x9b455a94 +0, 275, 275, 1, 152064, 0xb3774ce7 +0, 276, 276, 1, 152064, 0x92580986 +0, 277, 277, 1, 152064, 0x0eae2f95 +0, 278, 278, 1, 152064, 0x599208b2 +0, 279, 279, 1, 152064, 0x4804c04c +0, 280, 280, 1, 152064, 0x5f730e8f +0, 281, 281, 1, 152064, 0x3e501d1e +0, 282, 282, 1, 152064, 0x32100740 +0, 283, 283, 1, 152064, 0x62226ff8 +0, 284, 284, 1, 152064, 0x7683b622 +0, 285, 285, 1, 152064, 0xc3e0aec1 +0, 286, 286, 1, 152064, 0xfac12608 +0, 287, 287, 1, 152064, 0xb21a5781 +0, 288, 288, 1, 152064, 0x8f1e4964 +0, 289, 289, 1, 152064, 0x0f62dd6e +0, 290, 290, 1, 152064, 0xac062ac4 +0, 291, 291, 1, 152064, 0x1b320f7a +0, 292, 292, 1, 152064, 0x346e7211 +0, 293, 293, 1, 152064, 0xe47592f3 +0, 294, 294, 1, 152064, 0xa3a7919c +0, 295, 295, 1, 152064, 0xa3580fa6 +0, 296, 296, 1, 152064, 0xc73430c1 +0, 297, 297, 1, 152064, 0x994a2c18 +0, 298, 298, 1, 152064, 0x0b5d8d45 +0, 299, 299, 1, 152064, 0x9eed5109 diff --git a/tests/ref/fate/h264-conformance-frext-hpcamapalq_bcrm_b b/tests/ref/fate/h264-conformance-frext-hpcamapalq_bcrm_b index 72b15b11e16..1b03e88a1f1 100644 --- a/tests/ref/fate/h264-conformance-frext-hpcamapalq_bcrm_b +++ b/tests/ref/fate/h264-conformance-frext-hpcamapalq_bcrm_b @@ -3,78 +3,78 @@ #codec_id 0: rawvideo #dimensions 0: 352x288 #sar 0: 0/1 -0, 1, 1, 1, 152064, 0xf8248ceb -0, 2, 2, 1, 152064, 0xb6204c81 +0, 0, 0, 1, 152064, 0xf8248ceb +0, 1, 1, 1, 152064, 0xb6204c81 0, 2, 2, 1, 152064, 0x22fb1737 0, 3, 3, 1, 152064, 0xce8c3fd7 -0, 5, 5, 1, 152064, 0xee88cedc +0, 4, 4, 1, 152064, 0xee88cedc 0, 5, 5, 1, 152064, 0x1d4209ca -0, 7, 7, 1, 152064, 0x6fb15238 -0, 8, 8, 1, 152064, 0x505200c2 +0, 6, 6, 1, 152064, 0x6fb15238 +0, 7, 7, 1, 152064, 0x505200c2 0, 8, 8, 1, 152064, 0xb73574ba 0, 9, 9, 1, 152064, 0x0586a097 -0, 11, 11, 1, 152064, 0xed50fe02 +0, 10, 10, 1, 152064, 0xed50fe02 0, 11, 11, 1, 152064, 0x222221ab 0, 12, 12, 1, 152064, 0x8afefd46 -0, 14, 14, 1, 152064, 0x6832c5cc -0, 15, 15, 1, 152064, 0xba4c8110 +0, 13, 13, 1, 152064, 0x6832c5cc +0, 14, 14, 1, 152064, 0xba4c8110 0, 15, 15, 1, 152064, 0x95c07e1e 0, 16, 16, 1, 152064, 0xc5d6fde9 -0, 18, 18, 1, 152064, 0xe75a4921 -0, 19, 19, 1, 152064, 0x53b61688 +0, 17, 17, 1, 152064, 0xe75a4921 +0, 18, 18, 1, 152064, 0x53b61688 0, 19, 19, 1, 152064, 0x0335424b -0, 21, 21, 1, 152064, 0x621742c7 -0, 22, 22, 1, 152064, 0x4f69f41b +0, 20, 20, 1, 152064, 0x621742c7 +0, 21, 21, 1, 152064, 0x4f69f41b 0, 22, 22, 1, 152064, 0x6b3f65d7 -0, 24, 24, 1, 152064, 0x8dfde04f +0, 23, 23, 1, 152064, 0x8dfde04f 0, 24, 24, 1, 152064, 0x30750ff5 -0, 26, 26, 1, 152064, 0xe3d70f3c +0, 25, 25, 1, 152064, 0xe3d70f3c 0, 26, 26, 1, 152064, 0x0c1af825 -0, 28, 28, 1, 152064, 0x58a53935 +0, 27, 27, 1, 152064, 0x58a53935 0, 28, 28, 1, 152064, 0xc63d9e98 -0, 30, 30, 1, 152064, 0xa85fdc48 +0, 29, 29, 1, 152064, 0xa85fdc48 0, 30, 30, 1, 152064, 0x01bb9784 -0, 32, 32, 1, 152064, 0xdd5cb509 +0, 31, 31, 1, 152064, 0xdd5cb509 0, 32, 32, 1, 152064, 0x29ae7d2b -0, 34, 34, 1, 152064, 0xdb08593e -0, 35, 35, 1, 152064, 0x372d5d4e -0, 36, 36, 1, 152064, 0x31522664 -0, 37, 37, 1, 152064, 0x3f13f335 +0, 33, 33, 1, 152064, 0xdb08593e +0, 34, 34, 1, 152064, 0x372d5d4e +0, 35, 35, 1, 152064, 0x31522664 +0, 36, 36, 1, 152064, 0x3f13f335 0, 37, 37, 1, 152064, 0xfd10c19a -0, 39, 39, 1, 152064, 0xef728975 -0, 40, 40, 1, 152064, 0x8e79234d -0, 41, 41, 1, 152064, 0x47022791 +0, 38, 38, 1, 152064, 0xef728975 +0, 39, 39, 1, 152064, 0x8e79234d +0, 40, 40, 1, 152064, 0x47022791 0, 41, 41, 1, 152064, 0x1ef9d297 0, 42, 42, 1, 152064, 0x77bf9738 0, 43, 43, 1, 152064, 0xd6bc8f03 -0, 45, 45, 1, 152064, 0x283ded4a -0, 46, 46, 1, 152064, 0xd87098d1 +0, 44, 44, 1, 152064, 0x283ded4a +0, 45, 45, 1, 152064, 0xd87098d1 0, 46, 46, 1, 152064, 0x300077a2 0, 47, 47, 1, 152064, 0x30ffbea4 -0, 49, 49, 1, 152064, 0x5dc5356b +0, 48, 48, 1, 152064, 0x5dc5356b 0, 49, 49, 1, 152064, 0x31cce185 0, 50, 50, 1, 152064, 0x47fc9148 -0, 52, 52, 1, 152064, 0x1641491e +0, 51, 51, 1, 152064, 0x1641491e 0, 52, 52, 1, 152064, 0x2184937d -0, 54, 54, 1, 152064, 0x126eb74a +0, 53, 53, 1, 152064, 0x126eb74a 0, 54, 54, 1, 152064, 0x25c07593 0, 55, 55, 1, 152064, 0xb1294e7e -0, 57, 57, 1, 152064, 0x8b35f45d -0, 58, 58, 1, 152064, 0x54765025 +0, 56, 56, 1, 152064, 0x8b35f45d +0, 57, 57, 1, 152064, 0x54765025 0, 58, 58, 1, 152064, 0x1d17e901 -0, 60, 60, 1, 152064, 0xaeab358d -0, 61, 61, 1, 152064, 0xf682c91f +0, 59, 59, 1, 152064, 0xaeab358d +0, 60, 60, 1, 152064, 0xf682c91f 0, 61, 61, 1, 152064, 0x0b4c9b06 0, 62, 62, 1, 152064, 0x45f326dc -0, 64, 64, 1, 152064, 0x132eeda3 +0, 63, 63, 1, 152064, 0x132eeda3 0, 64, 64, 1, 152064, 0x3c9b8e16 0, 65, 65, 1, 152064, 0x1be133c1 0, 66, 66, 1, 152064, 0xfa876720 -0, 68, 68, 1, 152064, 0x1666cdb8 +0, 67, 67, 1, 152064, 0x1666cdb8 0, 68, 68, 1, 152064, 0x362f418f 0, 69, 69, 1, 152064, 0x926b4a96 0, 70, 70, 1, 152064, 0xee3da1df -0, 72, 72, 1, 152064, 0xc11f025d +0, 71, 71, 1, 152064, 0xc11f025d 0, 72, 72, 1, 152064, 0x9ba62c19 0, 73, 73, 1, 152064, 0x0d66194f 0, 74, 74, 1, 152064, 0x2fd09340 @@ -82,224 +82,224 @@ 0, 76, 76, 1, 152064, 0xa3192ce6 0, 77, 77, 1, 152064, 0x6bfce0e1 0, 78, 78, 1, 152064, 0x3b7c5286 -0, 80, 80, 1, 152064, 0xb52f4bf5 -0, 81, 81, 1, 152064, 0x30870027 +0, 79, 79, 1, 152064, 0xb52f4bf5 +0, 80, 80, 1, 152064, 0x30870027 0, 81, 81, 1, 152064, 0x6f8e71c3 0, 82, 82, 1, 152064, 0x8d41b09a 0, 83, 83, 1, 152064, 0xc1ff1d05 0, 84, 84, 1, 152064, 0xca54125c 0, 85, 85, 1, 152064, 0x3342d823 -0, 87, 87, 1, 152064, 0xcc4a7542 -0, 88, 88, 1, 152064, 0x21fc9a9d +0, 86, 86, 1, 152064, 0xcc4a7542 +0, 87, 87, 1, 152064, 0x21fc9a9d 0, 88, 88, 1, 152064, 0x91587574 0, 89, 89, 1, 152064, 0x30929cc2 0, 90, 90, 1, 152064, 0xf07606b7 -0, 92, 92, 1, 152064, 0x0476b876 -0, 93, 93, 1, 152064, 0x213333dc +0, 91, 91, 1, 152064, 0x0476b876 +0, 92, 92, 1, 152064, 0x213333dc 0, 93, 93, 1, 152064, 0x87c67597 -0, 95, 95, 1, 152064, 0x05434641 -0, 96, 96, 1, 152064, 0x959eeffc +0, 94, 94, 1, 152064, 0x05434641 +0, 95, 95, 1, 152064, 0x959eeffc 0, 96, 96, 1, 152064, 0x92a130b4 -0, 98, 98, 1, 152064, 0x53d0b544 -0, 99, 99, 1, 152064, 0xaf8c233e -0, 100, 100, 1, 152064, 0xd3d4259a -0, 101, 101, 1, 152064, 0xa0287753 +0, 97, 97, 1, 152064, 0x53d0b544 +0, 98, 98, 1, 152064, 0xaf8c233e +0, 99, 99, 1, 152064, 0xd3d4259a +0, 100, 100, 1, 152064, 0xa0287753 0, 101, 101, 1, 152064, 0xfa23972a 0, 102, 102, 1, 152064, 0xacae756d -0, 104, 104, 1, 152064, 0xd8b58b5c +0, 103, 103, 1, 152064, 0xd8b58b5c 0, 104, 104, 1, 152064, 0x7db2c755 -0, 106, 106, 1, 152064, 0x31e7b79a -0, 107, 107, 1, 152064, 0xd8660d98 +0, 105, 105, 1, 152064, 0x31e7b79a +0, 106, 106, 1, 152064, 0xd8660d98 0, 107, 107, 1, 152064, 0xdcf0d10d 0, 108, 108, 1, 152064, 0x3e6567e6 -0, 110, 110, 1, 152064, 0xec3530fd +0, 109, 109, 1, 152064, 0xec3530fd 0, 110, 110, 1, 152064, 0xf686c61a 0, 111, 111, 1, 152064, 0x6e706804 -0, 113, 113, 1, 152064, 0x5fd4a1a3 -0, 114, 114, 1, 152064, 0xbb3384f7 +0, 112, 112, 1, 152064, 0x5fd4a1a3 +0, 113, 113, 1, 152064, 0xbb3384f7 0, 114, 114, 1, 152064, 0x8ffb14dd -0, 116, 116, 1, 152064, 0x01253a73 -0, 117, 117, 1, 152064, 0xf89c15df +0, 115, 115, 1, 152064, 0x01253a73 +0, 116, 116, 1, 152064, 0xf89c15df 0, 117, 117, 1, 152064, 0xda2b0b4c -0, 119, 119, 1, 152064, 0xfc9dfcc1 -0, 120, 120, 1, 152064, 0xfef4f0fa +0, 118, 118, 1, 152064, 0xfc9dfcc1 +0, 119, 119, 1, 152064, 0xfef4f0fa 0, 120, 120, 1, 152064, 0x91669bea -0, 122, 122, 1, 152064, 0x3664a565 +0, 121, 121, 1, 152064, 0x3664a565 0, 122, 122, 1, 152064, 0x32dd7923 0, 123, 123, 1, 152064, 0x26825231 0, 124, 124, 1, 152064, 0x5f81896e -0, 126, 126, 1, 152064, 0x0c64ca2f +0, 125, 125, 1, 152064, 0x0c64ca2f 0, 126, 126, 1, 152064, 0x488bb665 -0, 128, 128, 1, 152064, 0x4d183a0f +0, 127, 127, 1, 152064, 0x4d183a0f 0, 128, 128, 1, 152064, 0xed169321 0, 129, 129, 1, 152064, 0xcec22917 0, 130, 130, 1, 152064, 0xbe04ea6c -0, 132, 132, 1, 152064, 0x32b8bf9f -0, 133, 133, 1, 152064, 0x9c7c2e13 -0, 134, 134, 1, 152064, 0x232e3016 -0, 135, 135, 1, 152064, 0x1b76c08e -0, 136, 136, 1, 152064, 0x7425d821 +0, 131, 131, 1, 152064, 0x32b8bf9f +0, 132, 132, 1, 152064, 0x9c7c2e13 +0, 133, 133, 1, 152064, 0x232e3016 +0, 134, 134, 1, 152064, 0x1b76c08e +0, 135, 135, 1, 152064, 0x7425d821 0, 136, 136, 1, 152064, 0x0818ff3c 0, 137, 137, 1, 152064, 0xb4f2c42b 0, 138, 138, 1, 152064, 0xe029f979 -0, 140, 140, 1, 152064, 0x97c54c2f -0, 141, 141, 1, 152064, 0xd101c3b5 +0, 139, 139, 1, 152064, 0x97c54c2f +0, 140, 140, 1, 152064, 0xd101c3b5 0, 141, 141, 1, 152064, 0x5ed1f5d4 -0, 143, 143, 1, 152064, 0xc28264d1 +0, 142, 142, 1, 152064, 0xc28264d1 0, 143, 143, 1, 152064, 0xa162dd31 0, 144, 144, 1, 152064, 0x2ee872ce -0, 146, 146, 1, 152064, 0x809a8fce +0, 145, 145, 1, 152064, 0x809a8fce 0, 146, 146, 1, 152064, 0xcfcc3ef9 -0, 148, 148, 1, 152064, 0xa5be6ce3 +0, 147, 147, 1, 152064, 0xa5be6ce3 0, 148, 148, 1, 152064, 0xd75930a0 -0, 150, 150, 1, 152064, 0x28acb80f -0, 151, 151, 1, 152064, 0x223f2152 -0, 152, 152, 1, 152064, 0x0cf070cb +0, 149, 149, 1, 152064, 0x28acb80f +0, 150, 150, 1, 152064, 0x223f2152 +0, 151, 151, 1, 152064, 0x0cf070cb 0, 152, 152, 1, 152064, 0xcc7d011e -0, 154, 154, 1, 152064, 0xb2c2a63c +0, 153, 153, 1, 152064, 0xb2c2a63c 0, 154, 154, 1, 152064, 0x15514caa -0, 156, 156, 1, 152064, 0x0c6d18ee +0, 155, 155, 1, 152064, 0x0c6d18ee 0, 156, 156, 1, 152064, 0x33b4265d 0, 157, 157, 1, 152064, 0xb4abaaaf -0, 159, 159, 1, 152064, 0x26a7a856 +0, 158, 158, 1, 152064, 0x26a7a856 0, 159, 159, 1, 152064, 0xc75249cc -0, 161, 161, 1, 152064, 0x59ccb0e1 -0, 162, 162, 1, 152064, 0xc613f202 -0, 163, 163, 1, 152064, 0xd1c0e171 +0, 160, 160, 1, 152064, 0x59ccb0e1 +0, 161, 161, 1, 152064, 0xc613f202 +0, 162, 162, 1, 152064, 0xd1c0e171 0, 163, 163, 1, 152064, 0xa195da2b 0, 164, 164, 1, 152064, 0xbc7ed475 0, 165, 165, 1, 152064, 0x99206e2c -0, 167, 167, 1, 152064, 0x0ef04e03 -0, 168, 168, 1, 152064, 0x68cbc6a1 +0, 166, 166, 1, 152064, 0x0ef04e03 +0, 167, 167, 1, 152064, 0x68cbc6a1 0, 168, 168, 1, 152064, 0x2a5304b1 0, 169, 169, 1, 152064, 0xf017978b 0, 170, 170, 1, 152064, 0x94f5641a -0, 172, 172, 1, 152064, 0xd681bd8f +0, 171, 171, 1, 152064, 0xd681bd8f 0, 172, 172, 1, 152064, 0x16e1e3a3 -0, 174, 174, 1, 152064, 0xe4486c7e -0, 175, 175, 1, 152064, 0xa1bd394e +0, 173, 173, 1, 152064, 0xe4486c7e +0, 174, 174, 1, 152064, 0xa1bd394e 0, 175, 175, 1, 152064, 0x49ad5959 -0, 177, 177, 1, 152064, 0x82219b70 -0, 178, 178, 1, 152064, 0x64e2abcf -0, 179, 179, 1, 152064, 0x6d7d05d8 -0, 180, 180, 1, 152064, 0xd9ac2251 +0, 176, 176, 1, 152064, 0x82219b70 +0, 177, 177, 1, 152064, 0x64e2abcf +0, 178, 178, 1, 152064, 0x6d7d05d8 +0, 179, 179, 1, 152064, 0xd9ac2251 0, 180, 180, 1, 152064, 0xf477eee5 -0, 182, 182, 1, 152064, 0xb9826a78 +0, 181, 181, 1, 152064, 0xb9826a78 0, 182, 182, 1, 152064, 0x97828a37 -0, 184, 184, 1, 152064, 0x12099b1f +0, 183, 183, 1, 152064, 0x12099b1f 0, 184, 184, 1, 152064, 0x1ec45fa7 -0, 186, 186, 1, 152064, 0xfd5501c9 +0, 185, 185, 1, 152064, 0xfd5501c9 0, 186, 186, 1, 152064, 0x6a8b26a3 -0, 188, 188, 1, 152064, 0xae58ff40 -0, 189, 189, 1, 152064, 0xc0f47aa1 +0, 187, 187, 1, 152064, 0xae58ff40 +0, 188, 188, 1, 152064, 0xc0f47aa1 0, 189, 189, 1, 152064, 0x08bfa548 0, 190, 190, 1, 152064, 0x7f2ff5ef -0, 192, 192, 1, 152064, 0x5efa94a3 -0, 193, 193, 1, 152064, 0xf786f970 -0, 194, 194, 1, 152064, 0xab6bc712 +0, 191, 191, 1, 152064, 0x5efa94a3 +0, 192, 192, 1, 152064, 0xf786f970 +0, 193, 193, 1, 152064, 0xab6bc712 0, 194, 194, 1, 152064, 0x25647bee -0, 196, 196, 1, 152064, 0x54333ad5 -0, 197, 197, 1, 152064, 0xb3a99413 +0, 195, 195, 1, 152064, 0x54333ad5 +0, 196, 196, 1, 152064, 0xb3a99413 0, 197, 197, 1, 152064, 0xe7a78a0d -0, 199, 199, 1, 152064, 0xa5054abc -0, 200, 200, 1, 152064, 0xb94896ea +0, 198, 198, 1, 152064, 0xa5054abc +0, 199, 199, 1, 152064, 0xb94896ea 0, 200, 200, 1, 152064, 0x9f641bca -0, 202, 202, 1, 152064, 0x7363901c +0, 201, 201, 1, 152064, 0x7363901c 0, 202, 202, 1, 152064, 0xd340a000 0, 203, 203, 1, 152064, 0x0217f413 0, 204, 204, 1, 152064, 0xbbdba6e6 0, 205, 205, 1, 152064, 0xabc42617 -0, 207, 207, 1, 152064, 0xa3442925 -0, 208, 208, 1, 152064, 0x7d06c7e9 +0, 206, 206, 1, 152064, 0xa3442925 +0, 207, 207, 1, 152064, 0x7d06c7e9 0, 208, 208, 1, 152064, 0xa45e32df 0, 209, 209, 1, 152064, 0xf5ed407f -0, 211, 211, 1, 152064, 0x5ec235d5 -0, 212, 212, 1, 152064, 0xa5706635 -0, 213, 213, 1, 152064, 0xa44a209b -0, 214, 214, 1, 152064, 0xf2137e37 -0, 215, 215, 1, 152064, 0x5220508f +0, 210, 210, 1, 152064, 0x5ec235d5 +0, 211, 211, 1, 152064, 0xa5706635 +0, 212, 212, 1, 152064, 0xa44a209b +0, 213, 213, 1, 152064, 0xf2137e37 +0, 214, 214, 1, 152064, 0x5220508f 0, 215, 215, 1, 152064, 0xae6b37da -0, 217, 217, 1, 152064, 0xdf09b6cd +0, 216, 216, 1, 152064, 0xdf09b6cd 0, 217, 217, 1, 152064, 0x2d39e1c0 -0, 219, 219, 1, 152064, 0xc8284a76 -0, 220, 220, 1, 152064, 0x7d7bbe76 +0, 218, 218, 1, 152064, 0xc8284a76 +0, 219, 219, 1, 152064, 0x7d7bbe76 0, 220, 220, 1, 152064, 0xcfed7416 0, 221, 221, 1, 152064, 0x81caaedd 0, 222, 222, 1, 152064, 0x9dcdd771 -0, 224, 224, 1, 152064, 0x46c1331b -0, 225, 225, 1, 152064, 0xace60efa +0, 223, 223, 1, 152064, 0x46c1331b +0, 224, 224, 1, 152064, 0xace60efa 0, 225, 225, 1, 152064, 0x9e0909f7 -0, 227, 227, 1, 152064, 0x72f5a321 +0, 226, 226, 1, 152064, 0x72f5a321 0, 227, 227, 1, 152064, 0x68f8cdcc 0, 228, 228, 1, 152064, 0xcc59fdd9 -0, 230, 230, 1, 152064, 0xc0a700c6 -0, 231, 231, 1, 152064, 0xf4254dcf +0, 229, 229, 1, 152064, 0xc0a700c6 +0, 230, 230, 1, 152064, 0xf4254dcf 0, 231, 231, 1, 152064, 0xc59b46d1 -0, 233, 233, 1, 152064, 0x2e5b2524 -0, 234, 234, 1, 152064, 0x46051293 +0, 232, 232, 1, 152064, 0x2e5b2524 +0, 233, 233, 1, 152064, 0x46051293 0, 234, 234, 1, 152064, 0x3cbcd1cd 0, 235, 235, 1, 152064, 0x9f308587 -0, 237, 237, 1, 152064, 0x6b91633f +0, 236, 236, 1, 152064, 0x6b91633f 0, 237, 237, 1, 152064, 0xb7191012 -0, 239, 239, 1, 152064, 0xd2fd030f -0, 240, 240, 1, 152064, 0x15a0ae2e -0, 241, 241, 1, 152064, 0xac3920d0 +0, 238, 238, 1, 152064, 0xd2fd030f +0, 239, 239, 1, 152064, 0x15a0ae2e +0, 240, 240, 1, 152064, 0xac3920d0 0, 241, 241, 1, 152064, 0x0eef80aa 0, 242, 242, 1, 152064, 0x319008f1 -0, 244, 244, 1, 152064, 0x7734450c +0, 243, 243, 1, 152064, 0x7734450c 0, 244, 244, 1, 152064, 0xf112df62 0, 245, 245, 1, 152064, 0x1dd8ffae -0, 247, 247, 1, 152064, 0x655ef429 +0, 246, 246, 1, 152064, 0x655ef429 0, 247, 247, 1, 152064, 0x27026213 -0, 249, 249, 1, 152064, 0x5c14b015 -0, 250, 250, 1, 152064, 0x9512abeb -0, 251, 251, 1, 152064, 0x961812b2 +0, 248, 248, 1, 152064, 0x5c14b015 +0, 249, 249, 1, 152064, 0x9512abeb +0, 250, 250, 1, 152064, 0x961812b2 0, 251, 251, 1, 152064, 0xb8890aea 0, 252, 252, 1, 152064, 0x4519db9a 0, 253, 253, 1, 152064, 0xf358034a -0, 255, 255, 1, 152064, 0x45d9f2ab +0, 254, 254, 1, 152064, 0x45d9f2ab 0, 255, 255, 1, 152064, 0xebd47e7d 0, 256, 256, 1, 152064, 0x15578be9 -0, 258, 258, 1, 152064, 0x1b373b2d +0, 257, 257, 1, 152064, 0x1b373b2d 0, 258, 258, 1, 152064, 0xbbe707e5 0, 259, 259, 1, 152064, 0x5bf62385 -0, 261, 261, 1, 152064, 0x832e6ef5 -0, 262, 262, 1, 152064, 0x761e5968 +0, 260, 260, 1, 152064, 0x832e6ef5 +0, 261, 261, 1, 152064, 0x761e5968 0, 262, 262, 1, 152064, 0x251f984d -0, 264, 264, 1, 152064, 0xbda48899 +0, 263, 263, 1, 152064, 0xbda48899 0, 264, 264, 1, 152064, 0x3fd843b9 -0, 266, 266, 1, 152064, 0x00485425 -0, 267, 267, 1, 152064, 0x4e282b39 -0, 268, 268, 1, 152064, 0x2630a8ea -0, 269, 269, 1, 152064, 0x5ea5c973 -0, 270, 270, 1, 152064, 0xfc436d21 -0, 271, 271, 1, 152064, 0x69852ef5 -0, 272, 272, 1, 152064, 0x44cb5589 -0, 273, 273, 1, 152064, 0x32f32725 -0, 274, 274, 1, 152064, 0x54d50aca -0, 275, 275, 1, 152064, 0xe7a639bb -0, 276, 276, 1, 152064, 0x01be2ad5 -0, 277, 277, 1, 152064, 0x5c63eca4 -0, 278, 278, 1, 152064, 0x94e91116 +0, 265, 265, 1, 152064, 0x00485425 +0, 266, 266, 1, 152064, 0x4e282b39 +0, 267, 267, 1, 152064, 0x2630a8ea +0, 268, 268, 1, 152064, 0x5ea5c973 +0, 269, 269, 1, 152064, 0xfc436d21 +0, 270, 270, 1, 152064, 0x69852ef5 +0, 271, 271, 1, 152064, 0x44cb5589 +0, 272, 272, 1, 152064, 0x32f32725 +0, 273, 273, 1, 152064, 0x54d50aca +0, 274, 274, 1, 152064, 0xe7a639bb +0, 275, 275, 1, 152064, 0x01be2ad5 +0, 276, 276, 1, 152064, 0x5c63eca4 +0, 277, 277, 1, 152064, 0x94e91116 0, 278, 278, 1, 152064, 0x9a8be637 0, 279, 279, 1, 152064, 0x165d9a12 -0, 281, 281, 1, 152064, 0x8c25ca0a -0, 282, 282, 1, 152064, 0x4ee2ed32 -0, 283, 283, 1, 152064, 0x4b2fe0c6 -0, 284, 284, 1, 152064, 0x521e434e -0, 285, 285, 1, 152064, 0x97679d7e -0, 286, 286, 1, 152064, 0x886b9506 +0, 280, 280, 1, 152064, 0x8c25ca0a +0, 281, 281, 1, 152064, 0x4ee2ed32 +0, 282, 282, 1, 152064, 0x4b2fe0c6 +0, 283, 283, 1, 152064, 0x521e434e +0, 284, 284, 1, 152064, 0x97679d7e +0, 285, 285, 1, 152064, 0x886b9506 0, 286, 286, 1, 152064, 0x4283eda8 -0, 288, 288, 1, 152064, 0xef793c49 +0, 287, 287, 1, 152064, 0xef793c49 0, 288, 288, 1, 152064, 0x68ac2afe -0, 290, 290, 1, 152064, 0x3d1ab510 +0, 289, 289, 1, 152064, 0x3d1ab510 0, 290, 290, 1, 152064, 0x98d3ec95 0, 291, 291, 1, 152064, 0x09f7e512 -0, 293, 293, 1, 152064, 0x801355dd -0, 294, 294, 1, 152064, 0xf2e87a11 +0, 292, 292, 1, 152064, 0x801355dd +0, 293, 293, 1, 152064, 0xf2e87a11 0, 294, 294, 1, 152064, 0x16757601 0, 295, 295, 1, 152064, 0x3074d74a -0, 297, 297, 1, 152064, 0xec8c1290 -0, 298, 298, 1, 152064, 0x46fb1877 +0, 296, 296, 1, 152064, 0xec8c1290 +0, 297, 297, 1, 152064, 0x46fb1877 0, 298, 298, 1, 152064, 0xf0b662c4 0, 299, 299, 1, 152064, 0xf8683940 diff --git a/tests/ref/fate/h264-conformance-frext-hpcvfl_bcrm_a b/tests/ref/fate/h264-conformance-frext-hpcvfl_bcrm_a index 25551fb0210..0febed6d6f2 100644 --- a/tests/ref/fate/h264-conformance-frext-hpcvfl_bcrm_a +++ b/tests/ref/fate/h264-conformance-frext-hpcvfl_bcrm_a @@ -3,303 +3,303 @@ #codec_id 0: rawvideo #dimensions 0: 352x288 #sar 0: 0/1 -0, 1, 1, 1, 152064, 0x502ec077 -0, 2, 2, 1, 152064, 0x84807243 -0, 3, 3, 1, 152064, 0xd7474a6e -0, 4, 4, 1, 152064, 0x793469bb -0, 5, 5, 1, 152064, 0xb7a0faf7 -0, 6, 6, 1, 152064, 0x1d3d3cba -0, 7, 7, 1, 152064, 0xb62583de -0, 8, 8, 1, 152064, 0xc8422fb1 -0, 9, 9, 1, 152064, 0x321dc699 -0, 10, 10, 1, 152064, 0x7a34d350 -0, 11, 11, 1, 152064, 0xaa4c302d -0, 12, 12, 1, 152064, 0x45fa7ab0 -0, 13, 13, 1, 152064, 0xc7262e41 -0, 14, 14, 1, 152064, 0x3550000c -0, 15, 15, 1, 152064, 0xf4bab54b -0, 16, 16, 1, 152064, 0xaccf9c1a -0, 17, 17, 1, 152064, 0x9bee20e9 -0, 18, 18, 1, 152064, 0x47fb7720 -0, 19, 19, 1, 152064, 0x12c63ffb -0, 20, 20, 1, 152064, 0xfa2b8b4d -0, 21, 21, 1, 152064, 0x279964bd -0, 22, 22, 1, 152064, 0xb8b01c7e -0, 23, 23, 1, 152064, 0x816fa010 -0, 24, 24, 1, 152064, 0x59fe1c8c -0, 25, 25, 1, 152064, 0x13393fad -0, 26, 26, 1, 152064, 0x991a50a4 -0, 27, 27, 1, 152064, 0x57df3eb7 -0, 28, 28, 1, 152064, 0x744371df -0, 29, 29, 1, 152064, 0xe9f6d3ff -0, 30, 30, 1, 152064, 0xc506fba0 -0, 31, 31, 1, 152064, 0x6295b90e -0, 32, 32, 1, 152064, 0xa19cee2d -0, 33, 33, 1, 152064, 0xf8c1b3ca -0, 34, 34, 1, 152064, 0x69f68ce0 -0, 35, 35, 1, 152064, 0x80558bb6 -0, 36, 36, 1, 152064, 0x27824fa5 -0, 37, 37, 1, 152064, 0x27c929a1 -0, 38, 38, 1, 152064, 0xc0fe06d1 -0, 39, 39, 1, 152064, 0xc52bc58c -0, 40, 40, 1, 152064, 0x0a5363c7 -0, 41, 41, 1, 152064, 0xd0f45a0d -0, 42, 42, 1, 152064, 0x274710f9 -0, 43, 43, 1, 152064, 0x89d2d390 -0, 44, 44, 1, 152064, 0x12a9bfb0 -0, 45, 45, 1, 152064, 0x04501a93 -0, 46, 46, 1, 152064, 0xf92cbbf4 -0, 47, 47, 1, 152064, 0xf6d1b27d -0, 48, 48, 1, 152064, 0xe3e904c3 -0, 49, 49, 1, 152064, 0x58f8516d -0, 50, 50, 1, 152064, 0x70370c2b -0, 51, 51, 1, 152064, 0xfeebc88c -0, 52, 52, 1, 152064, 0x974c6ed6 -0, 53, 53, 1, 152064, 0x401bdcf2 -0, 54, 54, 1, 152064, 0xfe61e278 -0, 55, 55, 1, 152064, 0x96ba8bb9 -0, 56, 56, 1, 152064, 0x988492fd -0, 57, 57, 1, 152064, 0xd1d913a9 -0, 58, 58, 1, 152064, 0x6bc46f0e -0, 59, 59, 1, 152064, 0x695ef706 -0, 60, 60, 1, 152064, 0x142045c9 -0, 61, 61, 1, 152064, 0xb390ed87 -0, 62, 62, 1, 152064, 0xb9e6d2e5 -0, 63, 63, 1, 152064, 0xe348797f -0, 64, 64, 1, 152064, 0x1cbd29d6 -0, 65, 65, 1, 152064, 0xbd7dd694 -0, 66, 66, 1, 152064, 0x516873c3 -0, 67, 67, 1, 152064, 0x27bba182 -0, 68, 68, 1, 152064, 0x7541f920 -0, 69, 69, 1, 152064, 0xfdf67042 -0, 70, 70, 1, 152064, 0x6c3c7896 -0, 71, 71, 1, 152064, 0xed86c467 -0, 72, 72, 1, 152064, 0x4ea83ca2 -0, 73, 73, 1, 152064, 0xa3e6725b -0, 74, 74, 1, 152064, 0x917f5f16 -0, 75, 75, 1, 152064, 0x8cf2d2e1 -0, 76, 76, 1, 152064, 0x57a8d116 -0, 77, 77, 1, 152064, 0x0db267d4 -0, 78, 78, 1, 152064, 0xce782ac5 -0, 79, 79, 1, 152064, 0x1c9d8518 -0, 80, 80, 1, 152064, 0x47598ac7 -0, 81, 81, 1, 152064, 0xc5033d97 -0, 82, 82, 1, 152064, 0xd7aaa3a4 -0, 83, 83, 1, 152064, 0x078afc96 -0, 84, 84, 1, 152064, 0xc9fe673d -0, 85, 85, 1, 152064, 0xe9284066 -0, 86, 86, 1, 152064, 0xbc570982 -0, 87, 87, 1, 152064, 0x0aac8574 -0, 88, 88, 1, 152064, 0x098cbeee -0, 89, 89, 1, 152064, 0x19c36a9d -0, 90, 90, 1, 152064, 0x8fe4a893 -0, 91, 91, 1, 152064, 0x0b652f17 -0, 92, 92, 1, 152064, 0x10f2e6bf -0, 93, 93, 1, 152064, 0x7ce5634e -0, 94, 94, 1, 152064, 0x8fe4ac6c -0, 95, 95, 1, 152064, 0xcaba749e -0, 96, 96, 1, 152064, 0x5f8a0d5c -0, 97, 97, 1, 152064, 0xcaa66bbc -0, 98, 98, 1, 152064, 0xc87ae617 -0, 99, 99, 1, 152064, 0xe8ef4dd7 -0, 100, 100, 1, 152064, 0xdfca5a07 -0, 101, 101, 1, 152064, 0x5f7eab7d -0, 102, 102, 1, 152064, 0x8a65ebbb -0, 103, 103, 1, 152064, 0x4beab4a0 -0, 104, 104, 1, 152064, 0xb5e6ab30 -0, 105, 105, 1, 152064, 0x8fe4f4d4 -0, 106, 106, 1, 152064, 0x95bde1ca -0, 107, 107, 1, 152064, 0xcc5e3a53 -0, 108, 108, 1, 152064, 0xf09f1dd7 -0, 109, 109, 1, 152064, 0x10179672 -0, 110, 110, 1, 152064, 0x4ad16184 -0, 111, 111, 1, 152064, 0x9efa0e23 -0, 112, 112, 1, 152064, 0x22f59522 -0, 113, 113, 1, 152064, 0x4d38f09d -0, 114, 114, 1, 152064, 0x4c5ebf56 -0, 115, 115, 1, 152064, 0xb19d5077 -0, 116, 116, 1, 152064, 0xa98576b9 -0, 117, 117, 1, 152064, 0x65324239 -0, 118, 118, 1, 152064, 0x709e4031 -0, 119, 119, 1, 152064, 0xf8e81681 -0, 120, 120, 1, 152064, 0x058514e5 -0, 121, 121, 1, 152064, 0xd1d1c806 -0, 122, 122, 1, 152064, 0x0e4dde57 -0, 123, 123, 1, 152064, 0x49e9c2bb -0, 124, 124, 1, 152064, 0x01417ce6 -0, 125, 125, 1, 152064, 0xda7ebbf1 -0, 126, 126, 1, 152064, 0xa22906b7 -0, 127, 127, 1, 152064, 0x32e2df87 -0, 128, 128, 1, 152064, 0x69917c8f -0, 129, 129, 1, 152064, 0xea8ed2cc -0, 130, 130, 1, 152064, 0x0b8d57f1 -0, 131, 131, 1, 152064, 0x5f683bcd -0, 132, 132, 1, 152064, 0x5162fe2f -0, 133, 133, 1, 152064, 0x49c052f8 -0, 134, 134, 1, 152064, 0x990b69ba -0, 135, 135, 1, 152064, 0xa6d4f99f -0, 136, 136, 1, 152064, 0xe79ef4da -0, 137, 137, 1, 152064, 0x5e8a3847 -0, 138, 138, 1, 152064, 0x38b1e75f -0, 139, 139, 1, 152064, 0xf5c91bed -0, 140, 140, 1, 152064, 0xd59a6d26 -0, 141, 141, 1, 152064, 0xc361de06 -0, 142, 142, 1, 152064, 0x63ed2229 -0, 143, 143, 1, 152064, 0xb8229205 -0, 144, 144, 1, 152064, 0x7c6619af -0, 145, 145, 1, 152064, 0x4126b02f -0, 146, 146, 1, 152064, 0x9250b99b -0, 147, 147, 1, 152064, 0x589778f9 -0, 148, 148, 1, 152064, 0xed1fa45b -0, 149, 149, 1, 152064, 0x700b6f32 -0, 150, 150, 1, 152064, 0x0590df55 -0, 151, 151, 1, 152064, 0x3e9c4018 -0, 152, 152, 1, 152064, 0x957b8860 -0, 153, 153, 1, 152064, 0x56161560 -0, 154, 154, 1, 152064, 0xbc43bc3b -0, 155, 155, 1, 152064, 0x508d8632 -0, 156, 156, 1, 152064, 0xbc5736d8 -0, 157, 157, 1, 152064, 0xed7d3aef -0, 158, 158, 1, 152064, 0x1dcdda9f -0, 159, 159, 1, 152064, 0x8ef6d5c9 -0, 160, 160, 1, 152064, 0x15466acc -0, 161, 161, 1, 152064, 0x45d4cf67 -0, 162, 162, 1, 152064, 0x8c900b9d -0, 163, 163, 1, 152064, 0x747006e0 -0, 164, 164, 1, 152064, 0xac920a0c -0, 165, 165, 1, 152064, 0xb8210c27 -0, 166, 166, 1, 152064, 0x7dbb873a -0, 167, 167, 1, 152064, 0x0d4d7584 -0, 168, 168, 1, 152064, 0xefb3fe60 -0, 169, 169, 1, 152064, 0x905e2644 -0, 170, 170, 1, 152064, 0x7c04e534 -0, 171, 171, 1, 152064, 0x8889972a -0, 172, 172, 1, 152064, 0x21c7d8ad -0, 173, 173, 1, 152064, 0x1c641176 -0, 174, 174, 1, 152064, 0xf71489a4 -0, 175, 175, 1, 152064, 0xd7ac5555 -0, 176, 176, 1, 152064, 0xb4609c6d -0, 177, 177, 1, 152064, 0xf5b2bd5e -0, 178, 178, 1, 152064, 0x9f43ce57 -0, 179, 179, 1, 152064, 0x77642dd3 -0, 180, 180, 1, 152064, 0x3e79565c -0, 181, 181, 1, 152064, 0x95f40b8e -0, 182, 182, 1, 152064, 0x3c8ca4d4 -0, 183, 183, 1, 152064, 0xa02ac497 -0, 184, 184, 1, 152064, 0x4c93b377 -0, 185, 185, 1, 152064, 0x55f5ac68 -0, 186, 186, 1, 152064, 0xf8652eca -0, 187, 187, 1, 152064, 0x56e94574 -0, 188, 188, 1, 152064, 0x6d8302e1 -0, 189, 189, 1, 152064, 0x29a57061 -0, 190, 190, 1, 152064, 0x24e4cfdc -0, 191, 191, 1, 152064, 0xf5a5d62a -0, 192, 192, 1, 152064, 0x998870c1 -0, 193, 193, 1, 152064, 0xa15b1f4e -0, 194, 194, 1, 152064, 0xb0ccb51f -0, 195, 195, 1, 152064, 0xeaaf59ab -0, 196, 196, 1, 152064, 0x7e2b4fe6 -0, 197, 197, 1, 152064, 0x72299fea -0, 198, 198, 1, 152064, 0x769da8b2 -0, 199, 199, 1, 152064, 0xefad7ef8 -0, 200, 200, 1, 152064, 0x24819983 -0, 201, 201, 1, 152064, 0x2aad32ab -0, 202, 202, 1, 152064, 0xc80cac79 -0, 203, 203, 1, 152064, 0x1659d628 -0, 204, 204, 1, 152064, 0xef941f66 -0, 205, 205, 1, 152064, 0x0d7fcdb5 -0, 206, 206, 1, 152064, 0x7c1853fa -0, 207, 207, 1, 152064, 0xb94c4d3c -0, 208, 208, 1, 152064, 0xc47adfc2 -0, 209, 209, 1, 152064, 0x366a6729 -0, 210, 210, 1, 152064, 0x7eb37b70 -0, 211, 211, 1, 152064, 0xafd54c27 -0, 212, 212, 1, 152064, 0x67b18636 -0, 213, 213, 1, 152064, 0x93b22dcf -0, 214, 214, 1, 152064, 0xa64991f1 -0, 215, 215, 1, 152064, 0xd32a7102 -0, 216, 216, 1, 152064, 0xff665d1c -0, 217, 217, 1, 152064, 0xf107cc31 -0, 218, 218, 1, 152064, 0xf5b25652 -0, 219, 219, 1, 152064, 0x8caf783d -0, 220, 220, 1, 152064, 0x72f3eb00 -0, 221, 221, 1, 152064, 0xb5aea5f8 -0, 222, 222, 1, 152064, 0xee70e870 -0, 223, 223, 1, 152064, 0x7c3a0156 -0, 224, 224, 1, 152064, 0x871b6383 -0, 225, 225, 1, 152064, 0x48d831ff -0, 226, 226, 1, 152064, 0xca233913 -0, 227, 227, 1, 152064, 0xe14bc5eb -0, 228, 228, 1, 152064, 0x9b1d27e7 -0, 229, 229, 1, 152064, 0xfb9637f7 -0, 230, 230, 1, 152064, 0x0c022157 -0, 231, 231, 1, 152064, 0x16d35fc9 -0, 232, 232, 1, 152064, 0x6d935f71 -0, 233, 233, 1, 152064, 0xae4066fa -0, 234, 234, 1, 152064, 0xcef94fdc -0, 235, 235, 1, 152064, 0xc234edb9 -0, 236, 236, 1, 152064, 0x26a4f2e2 -0, 237, 237, 1, 152064, 0xd29ac23e -0, 238, 238, 1, 152064, 0xb7604395 -0, 239, 239, 1, 152064, 0x408084f6 -0, 240, 240, 1, 152064, 0x0a02026c -0, 241, 241, 1, 152064, 0x78b33c7c -0, 242, 242, 1, 152064, 0xcb02b874 -0, 243, 243, 1, 152064, 0xf566513b -0, 244, 244, 1, 152064, 0xb34e52b1 -0, 245, 245, 1, 152064, 0xf55ff493 -0, 246, 246, 1, 152064, 0xb0e8282a -0, 247, 247, 1, 152064, 0xe9510bbe -0, 248, 248, 1, 152064, 0x292e8c5a -0, 249, 249, 1, 152064, 0x62b9d2b0 -0, 250, 250, 1, 152064, 0x3a8cc827 -0, 251, 251, 1, 152064, 0x25cc465e -0, 252, 252, 1, 152064, 0xf2bc32e2 -0, 253, 253, 1, 152064, 0x6141f914 -0, 254, 254, 1, 152064, 0x1171256f -0, 255, 255, 1, 152064, 0x13cb2ded -0, 256, 256, 1, 152064, 0x3d4ca557 -0, 257, 257, 1, 152064, 0xf2b9e72e -0, 258, 258, 1, 152064, 0x03f7547a -0, 259, 259, 1, 152064, 0xc7302955 -0, 260, 260, 1, 152064, 0xe78a46d3 -0, 261, 261, 1, 152064, 0x3726a270 -0, 262, 262, 1, 152064, 0x2f65722a -0, 263, 263, 1, 152064, 0x55acce40 -0, 264, 264, 1, 152064, 0xf6fa9db2 -0, 265, 265, 1, 152064, 0x70a36937 -0, 266, 266, 1, 152064, 0x9313742d -0, 267, 267, 1, 152064, 0x2eb14e53 -0, 268, 268, 1, 152064, 0x3d47c9c3 -0, 269, 269, 1, 152064, 0xd0a90348 -0, 270, 270, 1, 152064, 0x6ad48088 -0, 271, 271, 1, 152064, 0x68e64738 -0, 272, 272, 1, 152064, 0x04c3735a -0, 273, 273, 1, 152064, 0x51d0593f -0, 274, 274, 1, 152064, 0x42cf2b48 -0, 275, 275, 1, 152064, 0xa5496a0c -0, 276, 276, 1, 152064, 0x84c25549 -0, 277, 277, 1, 152064, 0x96691600 -0, 278, 278, 1, 152064, 0x423135db -0, 279, 279, 1, 152064, 0x8d2e08b6 -0, 280, 280, 1, 152064, 0xaeb4c840 -0, 281, 281, 1, 152064, 0xf3e71780 -0, 282, 282, 1, 152064, 0x8858228b -0, 283, 283, 1, 152064, 0xf28613f8 -0, 284, 284, 1, 152064, 0xb5327882 -0, 285, 285, 1, 152064, 0xbb60bb85 -0, 286, 286, 1, 152064, 0x345ab1c9 -0, 287, 287, 1, 152064, 0x8aac2cba -0, 288, 288, 1, 152064, 0x7ce15b4c -0, 289, 289, 1, 152064, 0xc09c55c0 -0, 290, 290, 1, 152064, 0x8482ddd6 -0, 291, 291, 1, 152064, 0xab222a13 -0, 292, 292, 1, 152064, 0xd39b0dea -0, 293, 293, 1, 152064, 0x6dab6e06 -0, 294, 294, 1, 152064, 0xec0891bd -0, 295, 295, 1, 152064, 0x88bd9701 -0, 296, 296, 1, 152064, 0xdf13072a -0, 297, 297, 1, 152064, 0x23b33081 -0, 298, 298, 1, 152064, 0x63943137 -0, 299, 299, 1, 152064, 0xab6a9052 -0, 300, 300, 1, 152064, 0x05485494 +0, 0, 0, 1, 152064, 0x502ec077 +0, 1, 1, 1, 152064, 0x84807243 +0, 2, 2, 1, 152064, 0xd7474a6e +0, 3, 3, 1, 152064, 0x793469bb +0, 4, 4, 1, 152064, 0xb7a0faf7 +0, 5, 5, 1, 152064, 0x1d3d3cba +0, 6, 6, 1, 152064, 0xb62583de +0, 7, 7, 1, 152064, 0xc8422fb1 +0, 8, 8, 1, 152064, 0x321dc699 +0, 9, 9, 1, 152064, 0x7a34d350 +0, 10, 10, 1, 152064, 0xaa4c302d +0, 11, 11, 1, 152064, 0x45fa7ab0 +0, 12, 12, 1, 152064, 0xc7262e41 +0, 13, 13, 1, 152064, 0x3550000c +0, 14, 14, 1, 152064, 0xf4bab54b +0, 15, 15, 1, 152064, 0xaccf9c1a +0, 16, 16, 1, 152064, 0x9bee20e9 +0, 17, 17, 1, 152064, 0x47fb7720 +0, 18, 18, 1, 152064, 0x12c63ffb +0, 19, 19, 1, 152064, 0xfa2b8b4d +0, 20, 20, 1, 152064, 0x279964bd +0, 21, 21, 1, 152064, 0xb8b01c7e +0, 22, 22, 1, 152064, 0x816fa010 +0, 23, 23, 1, 152064, 0x59fe1c8c +0, 24, 24, 1, 152064, 0x13393fad +0, 25, 25, 1, 152064, 0x991a50a4 +0, 26, 26, 1, 152064, 0x57df3eb7 +0, 27, 27, 1, 152064, 0x744371df +0, 28, 28, 1, 152064, 0xe9f6d3ff +0, 29, 29, 1, 152064, 0xc506fba0 +0, 30, 30, 1, 152064, 0x6295b90e +0, 31, 31, 1, 152064, 0xa19cee2d +0, 32, 32, 1, 152064, 0xf8c1b3ca +0, 33, 33, 1, 152064, 0x69f68ce0 +0, 34, 34, 1, 152064, 0x80558bb6 +0, 35, 35, 1, 152064, 0x27824fa5 +0, 36, 36, 1, 152064, 0x27c929a1 +0, 37, 37, 1, 152064, 0xc0fe06d1 +0, 38, 38, 1, 152064, 0xc52bc58c +0, 39, 39, 1, 152064, 0x0a5363c7 +0, 40, 40, 1, 152064, 0xd0f45a0d +0, 41, 41, 1, 152064, 0x274710f9 +0, 42, 42, 1, 152064, 0x89d2d390 +0, 43, 43, 1, 152064, 0x12a9bfb0 +0, 44, 44, 1, 152064, 0x04501a93 +0, 45, 45, 1, 152064, 0xf92cbbf4 +0, 46, 46, 1, 152064, 0xf6d1b27d +0, 47, 47, 1, 152064, 0xe3e904c3 +0, 48, 48, 1, 152064, 0x58f8516d +0, 49, 49, 1, 152064, 0x70370c2b +0, 50, 50, 1, 152064, 0xfeebc88c +0, 51, 51, 1, 152064, 0x974c6ed6 +0, 52, 52, 1, 152064, 0x401bdcf2 +0, 53, 53, 1, 152064, 0xfe61e278 +0, 54, 54, 1, 152064, 0x96ba8bb9 +0, 55, 55, 1, 152064, 0x988492fd +0, 56, 56, 1, 152064, 0xd1d913a9 +0, 57, 57, 1, 152064, 0x6bc46f0e +0, 58, 58, 1, 152064, 0x695ef706 +0, 59, 59, 1, 152064, 0x142045c9 +0, 60, 60, 1, 152064, 0xb390ed87 +0, 61, 61, 1, 152064, 0xb9e6d2e5 +0, 62, 62, 1, 152064, 0xe348797f +0, 63, 63, 1, 152064, 0x1cbd29d6 +0, 64, 64, 1, 152064, 0xbd7dd694 +0, 65, 65, 1, 152064, 0x516873c3 +0, 66, 66, 1, 152064, 0x27bba182 +0, 67, 67, 1, 152064, 0x7541f920 +0, 68, 68, 1, 152064, 0xfdf67042 +0, 69, 69, 1, 152064, 0x6c3c7896 +0, 70, 70, 1, 152064, 0xed86c467 +0, 71, 71, 1, 152064, 0x4ea83ca2 +0, 72, 72, 1, 152064, 0xa3e6725b +0, 73, 73, 1, 152064, 0x917f5f16 +0, 74, 74, 1, 152064, 0x8cf2d2e1 +0, 75, 75, 1, 152064, 0x57a8d116 +0, 76, 76, 1, 152064, 0x0db267d4 +0, 77, 77, 1, 152064, 0xce782ac5 +0, 78, 78, 1, 152064, 0x1c9d8518 +0, 79, 79, 1, 152064, 0x47598ac7 +0, 80, 80, 1, 152064, 0xc5033d97 +0, 81, 81, 1, 152064, 0xd7aaa3a4 +0, 82, 82, 1, 152064, 0x078afc96 +0, 83, 83, 1, 152064, 0xc9fe673d +0, 84, 84, 1, 152064, 0xe9284066 +0, 85, 85, 1, 152064, 0xbc570982 +0, 86, 86, 1, 152064, 0x0aac8574 +0, 87, 87, 1, 152064, 0x098cbeee +0, 88, 88, 1, 152064, 0x19c36a9d +0, 89, 89, 1, 152064, 0x8fe4a893 +0, 90, 90, 1, 152064, 0x0b652f17 +0, 91, 91, 1, 152064, 0x10f2e6bf +0, 92, 92, 1, 152064, 0x7ce5634e +0, 93, 93, 1, 152064, 0x8fe4ac6c +0, 94, 94, 1, 152064, 0xcaba749e +0, 95, 95, 1, 152064, 0x5f8a0d5c +0, 96, 96, 1, 152064, 0xcaa66bbc +0, 97, 97, 1, 152064, 0xc87ae617 +0, 98, 98, 1, 152064, 0xe8ef4dd7 +0, 99, 99, 1, 152064, 0xdfca5a07 +0, 100, 100, 1, 152064, 0x5f7eab7d +0, 101, 101, 1, 152064, 0x8a65ebbb +0, 102, 102, 1, 152064, 0x4beab4a0 +0, 103, 103, 1, 152064, 0xb5e6ab30 +0, 104, 104, 1, 152064, 0x8fe4f4d4 +0, 105, 105, 1, 152064, 0x95bde1ca +0, 106, 106, 1, 152064, 0xcc5e3a53 +0, 107, 107, 1, 152064, 0xf09f1dd7 +0, 108, 108, 1, 152064, 0x10179672 +0, 109, 109, 1, 152064, 0x4ad16184 +0, 110, 110, 1, 152064, 0x9efa0e23 +0, 111, 111, 1, 152064, 0x22f59522 +0, 112, 112, 1, 152064, 0x4d38f09d +0, 113, 113, 1, 152064, 0x4c5ebf56 +0, 114, 114, 1, 152064, 0xb19d5077 +0, 115, 115, 1, 152064, 0xa98576b9 +0, 116, 116, 1, 152064, 0x65324239 +0, 117, 117, 1, 152064, 0x709e4031 +0, 118, 118, 1, 152064, 0xf8e81681 +0, 119, 119, 1, 152064, 0x058514e5 +0, 120, 120, 1, 152064, 0xd1d1c806 +0, 121, 121, 1, 152064, 0x0e4dde57 +0, 122, 122, 1, 152064, 0x49e9c2bb +0, 123, 123, 1, 152064, 0x01417ce6 +0, 124, 124, 1, 152064, 0xda7ebbf1 +0, 125, 125, 1, 152064, 0xa22906b7 +0, 126, 126, 1, 152064, 0x32e2df87 +0, 127, 127, 1, 152064, 0x69917c8f +0, 128, 128, 1, 152064, 0xea8ed2cc +0, 129, 129, 1, 152064, 0x0b8d57f1 +0, 130, 130, 1, 152064, 0x5f683bcd +0, 131, 131, 1, 152064, 0x5162fe2f +0, 132, 132, 1, 152064, 0x49c052f8 +0, 133, 133, 1, 152064, 0x990b69ba +0, 134, 134, 1, 152064, 0xa6d4f99f +0, 135, 135, 1, 152064, 0xe79ef4da +0, 136, 136, 1, 152064, 0x5e8a3847 +0, 137, 137, 1, 152064, 0x38b1e75f +0, 138, 138, 1, 152064, 0xf5c91bed +0, 139, 139, 1, 152064, 0xd59a6d26 +0, 140, 140, 1, 152064, 0xc361de06 +0, 141, 141, 1, 152064, 0x63ed2229 +0, 142, 142, 1, 152064, 0xb8229205 +0, 143, 143, 1, 152064, 0x7c6619af +0, 144, 144, 1, 152064, 0x4126b02f +0, 145, 145, 1, 152064, 0x9250b99b +0, 146, 146, 1, 152064, 0x589778f9 +0, 147, 147, 1, 152064, 0xed1fa45b +0, 148, 148, 1, 152064, 0x700b6f32 +0, 149, 149, 1, 152064, 0x0590df55 +0, 150, 150, 1, 152064, 0x3e9c4018 +0, 151, 151, 1, 152064, 0x957b8860 +0, 152, 152, 1, 152064, 0x56161560 +0, 153, 153, 1, 152064, 0xbc43bc3b +0, 154, 154, 1, 152064, 0x508d8632 +0, 155, 155, 1, 152064, 0xbc5736d8 +0, 156, 156, 1, 152064, 0xed7d3aef +0, 157, 157, 1, 152064, 0x1dcdda9f +0, 158, 158, 1, 152064, 0x8ef6d5c9 +0, 159, 159, 1, 152064, 0x15466acc +0, 160, 160, 1, 152064, 0x45d4cf67 +0, 161, 161, 1, 152064, 0x8c900b9d +0, 162, 162, 1, 152064, 0x747006e0 +0, 163, 163, 1, 152064, 0xac920a0c +0, 164, 164, 1, 152064, 0xb8210c27 +0, 165, 165, 1, 152064, 0x7dbb873a +0, 166, 166, 1, 152064, 0x0d4d7584 +0, 167, 167, 1, 152064, 0xefb3fe60 +0, 168, 168, 1, 152064, 0x905e2644 +0, 169, 169, 1, 152064, 0x7c04e534 +0, 170, 170, 1, 152064, 0x8889972a +0, 171, 171, 1, 152064, 0x21c7d8ad +0, 172, 172, 1, 152064, 0x1c641176 +0, 173, 173, 1, 152064, 0xf71489a4 +0, 174, 174, 1, 152064, 0xd7ac5555 +0, 175, 175, 1, 152064, 0xb4609c6d +0, 176, 176, 1, 152064, 0xf5b2bd5e +0, 177, 177, 1, 152064, 0x9f43ce57 +0, 178, 178, 1, 152064, 0x77642dd3 +0, 179, 179, 1, 152064, 0x3e79565c +0, 180, 180, 1, 152064, 0x95f40b8e +0, 181, 181, 1, 152064, 0x3c8ca4d4 +0, 182, 182, 1, 152064, 0xa02ac497 +0, 183, 183, 1, 152064, 0x4c93b377 +0, 184, 184, 1, 152064, 0x55f5ac68 +0, 185, 185, 1, 152064, 0xf8652eca +0, 186, 186, 1, 152064, 0x56e94574 +0, 187, 187, 1, 152064, 0x6d8302e1 +0, 188, 188, 1, 152064, 0x29a57061 +0, 189, 189, 1, 152064, 0x24e4cfdc +0, 190, 190, 1, 152064, 0xf5a5d62a +0, 191, 191, 1, 152064, 0x998870c1 +0, 192, 192, 1, 152064, 0xa15b1f4e +0, 193, 193, 1, 152064, 0xb0ccb51f +0, 194, 194, 1, 152064, 0xeaaf59ab +0, 195, 195, 1, 152064, 0x7e2b4fe6 +0, 196, 196, 1, 152064, 0x72299fea +0, 197, 197, 1, 152064, 0x769da8b2 +0, 198, 198, 1, 152064, 0xefad7ef8 +0, 199, 199, 1, 152064, 0x24819983 +0, 200, 200, 1, 152064, 0x2aad32ab +0, 201, 201, 1, 152064, 0xc80cac79 +0, 202, 202, 1, 152064, 0x1659d628 +0, 203, 203, 1, 152064, 0xef941f66 +0, 204, 204, 1, 152064, 0x0d7fcdb5 +0, 205, 205, 1, 152064, 0x7c1853fa +0, 206, 206, 1, 152064, 0xb94c4d3c +0, 207, 207, 1, 152064, 0xc47adfc2 +0, 208, 208, 1, 152064, 0x366a6729 +0, 209, 209, 1, 152064, 0x7eb37b70 +0, 210, 210, 1, 152064, 0xafd54c27 +0, 211, 211, 1, 152064, 0x67b18636 +0, 212, 212, 1, 152064, 0x93b22dcf +0, 213, 213, 1, 152064, 0xa64991f1 +0, 214, 214, 1, 152064, 0xd32a7102 +0, 215, 215, 1, 152064, 0xff665d1c +0, 216, 216, 1, 152064, 0xf107cc31 +0, 217, 217, 1, 152064, 0xf5b25652 +0, 218, 218, 1, 152064, 0x8caf783d +0, 219, 219, 1, 152064, 0x72f3eb00 +0, 220, 220, 1, 152064, 0xb5aea5f8 +0, 221, 221, 1, 152064, 0xee70e870 +0, 222, 222, 1, 152064, 0x7c3a0156 +0, 223, 223, 1, 152064, 0x871b6383 +0, 224, 224, 1, 152064, 0x48d831ff +0, 225, 225, 1, 152064, 0xca233913 +0, 226, 226, 1, 152064, 0xe14bc5eb +0, 227, 227, 1, 152064, 0x9b1d27e7 +0, 228, 228, 1, 152064, 0xfb9637f7 +0, 229, 229, 1, 152064, 0x0c022157 +0, 230, 230, 1, 152064, 0x16d35fc9 +0, 231, 231, 1, 152064, 0x6d935f71 +0, 232, 232, 1, 152064, 0xae4066fa +0, 233, 233, 1, 152064, 0xcef94fdc +0, 234, 234, 1, 152064, 0xc234edb9 +0, 235, 235, 1, 152064, 0x26a4f2e2 +0, 236, 236, 1, 152064, 0xd29ac23e +0, 237, 237, 1, 152064, 0xb7604395 +0, 238, 238, 1, 152064, 0x408084f6 +0, 239, 239, 1, 152064, 0x0a02026c +0, 240, 240, 1, 152064, 0x78b33c7c +0, 241, 241, 1, 152064, 0xcb02b874 +0, 242, 242, 1, 152064, 0xf566513b +0, 243, 243, 1, 152064, 0xb34e52b1 +0, 244, 244, 1, 152064, 0xf55ff493 +0, 245, 245, 1, 152064, 0xb0e8282a +0, 246, 246, 1, 152064, 0xe9510bbe +0, 247, 247, 1, 152064, 0x292e8c5a +0, 248, 248, 1, 152064, 0x62b9d2b0 +0, 249, 249, 1, 152064, 0x3a8cc827 +0, 250, 250, 1, 152064, 0x25cc465e +0, 251, 251, 1, 152064, 0xf2bc32e2 +0, 252, 252, 1, 152064, 0x6141f914 +0, 253, 253, 1, 152064, 0x1171256f +0, 254, 254, 1, 152064, 0x13cb2ded +0, 255, 255, 1, 152064, 0x3d4ca557 +0, 256, 256, 1, 152064, 0xf2b9e72e +0, 257, 257, 1, 152064, 0x03f7547a +0, 258, 258, 1, 152064, 0xc7302955 +0, 259, 259, 1, 152064, 0xe78a46d3 +0, 260, 260, 1, 152064, 0x3726a270 +0, 261, 261, 1, 152064, 0x2f65722a +0, 262, 262, 1, 152064, 0x55acce40 +0, 263, 263, 1, 152064, 0xf6fa9db2 +0, 264, 264, 1, 152064, 0x70a36937 +0, 265, 265, 1, 152064, 0x9313742d +0, 266, 266, 1, 152064, 0x2eb14e53 +0, 267, 267, 1, 152064, 0x3d47c9c3 +0, 268, 268, 1, 152064, 0xd0a90348 +0, 269, 269, 1, 152064, 0x6ad48088 +0, 270, 270, 1, 152064, 0x68e64738 +0, 271, 271, 1, 152064, 0x04c3735a +0, 272, 272, 1, 152064, 0x51d0593f +0, 273, 273, 1, 152064, 0x42cf2b48 +0, 274, 274, 1, 152064, 0xa5496a0c +0, 275, 275, 1, 152064, 0x84c25549 +0, 276, 276, 1, 152064, 0x96691600 +0, 277, 277, 1, 152064, 0x423135db +0, 278, 278, 1, 152064, 0x8d2e08b6 +0, 279, 279, 1, 152064, 0xaeb4c840 +0, 280, 280, 1, 152064, 0xf3e71780 +0, 281, 281, 1, 152064, 0x8858228b +0, 282, 282, 1, 152064, 0xf28613f8 +0, 283, 283, 1, 152064, 0xb5327882 +0, 284, 284, 1, 152064, 0xbb60bb85 +0, 285, 285, 1, 152064, 0x345ab1c9 +0, 286, 286, 1, 152064, 0x8aac2cba +0, 287, 287, 1, 152064, 0x7ce15b4c +0, 288, 288, 1, 152064, 0xc09c55c0 +0, 289, 289, 1, 152064, 0x8482ddd6 +0, 290, 290, 1, 152064, 0xab222a13 +0, 291, 291, 1, 152064, 0xd39b0dea +0, 292, 292, 1, 152064, 0x6dab6e06 +0, 293, 293, 1, 152064, 0xec0891bd +0, 294, 294, 1, 152064, 0x88bd9701 +0, 295, 295, 1, 152064, 0xdf13072a +0, 296, 296, 1, 152064, 0x23b33081 +0, 297, 297, 1, 152064, 0x63943137 +0, 298, 298, 1, 152064, 0xab6a9052 +0, 299, 299, 1, 152064, 0x05485494 diff --git a/tests/ref/fate/h264-conformance-frext-hpcvflnl_bcrm_a b/tests/ref/fate/h264-conformance-frext-hpcvflnl_bcrm_a index d6c41dd6430..9958f1616f4 100644 --- a/tests/ref/fate/h264-conformance-frext-hpcvflnl_bcrm_a +++ b/tests/ref/fate/h264-conformance-frext-hpcvflnl_bcrm_a @@ -3,303 +3,303 @@ #codec_id 0: rawvideo #dimensions 0: 352x288 #sar 0: 0/1 -0, 1, 1, 1, 152064, 0x3e39c08b -0, 2, 2, 1, 152064, 0xabc67990 -0, 3, 3, 1, 152064, 0x19614e74 -0, 4, 4, 1, 152064, 0xa3776beb -0, 5, 5, 1, 152064, 0xcce6ffdf -0, 6, 6, 1, 152064, 0xb0e94746 -0, 7, 7, 1, 152064, 0xdb1a84ef -0, 8, 8, 1, 152064, 0xb2624509 -0, 9, 9, 1, 152064, 0x32e2d826 -0, 10, 10, 1, 152064, 0xb3bddf0b -0, 11, 11, 1, 152064, 0x2e273ce3 -0, 12, 12, 1, 152064, 0x67af7e4d -0, 13, 13, 1, 152064, 0x505c3261 -0, 14, 14, 1, 152064, 0xa43d015e -0, 15, 15, 1, 152064, 0xad41c1f6 -0, 16, 16, 1, 152064, 0x633ba55f -0, 17, 17, 1, 152064, 0xe80634f0 -0, 18, 18, 1, 152064, 0x80a07dc9 -0, 19, 19, 1, 152064, 0x0e7a3bbf -0, 20, 20, 1, 152064, 0xcb099196 -0, 21, 21, 1, 152064, 0x57c96db5 -0, 22, 22, 1, 152064, 0xccd422fa -0, 23, 23, 1, 152064, 0x0850b7a7 -0, 24, 24, 1, 152064, 0x30e33156 -0, 25, 25, 1, 152064, 0x34e13f9a -0, 26, 26, 1, 152064, 0x03d36000 -0, 27, 27, 1, 152064, 0xbf7d49da -0, 28, 28, 1, 152064, 0x77336d09 -0, 29, 29, 1, 152064, 0xca8be5a9 -0, 30, 30, 1, 152064, 0xe57c0b08 -0, 31, 31, 1, 152064, 0xbe77c093 -0, 32, 32, 1, 152064, 0x6bf1ff05 -0, 33, 33, 1, 152064, 0x9142babf -0, 34, 34, 1, 152064, 0x08db8e67 -0, 35, 35, 1, 152064, 0x69ac8cb6 -0, 36, 36, 1, 152064, 0xaa3b5c88 -0, 37, 37, 1, 152064, 0x9bd32638 -0, 38, 38, 1, 152064, 0x7972115a -0, 39, 39, 1, 152064, 0x5c1dd47b -0, 40, 40, 1, 152064, 0x8a196e02 -0, 41, 41, 1, 152064, 0xa89672bc -0, 42, 42, 1, 152064, 0x27b220e4 -0, 43, 43, 1, 152064, 0xfa38dc4a -0, 44, 44, 1, 152064, 0x4784c639 -0, 45, 45, 1, 152064, 0xa5e4229a -0, 46, 46, 1, 152064, 0xa986bdfc -0, 47, 47, 1, 152064, 0x2951b47b -0, 48, 48, 1, 152064, 0x4df404a6 -0, 49, 49, 1, 152064, 0xc75155e8 -0, 50, 50, 1, 152064, 0xfc05248c -0, 51, 51, 1, 152064, 0x5d53da10 -0, 52, 52, 1, 152064, 0x284376ec -0, 53, 53, 1, 152064, 0x19fce380 -0, 54, 54, 1, 152064, 0x876be6c9 -0, 55, 55, 1, 152064, 0x39eb8ff9 -0, 56, 56, 1, 152064, 0x289c9543 -0, 57, 57, 1, 152064, 0x24dd2356 -0, 58, 58, 1, 152064, 0x1dc17d3c -0, 59, 59, 1, 152064, 0xd17c00ac -0, 60, 60, 1, 152064, 0xc2ad54de -0, 61, 61, 1, 152064, 0xbe11ee2f -0, 62, 62, 1, 152064, 0x3db9dc89 -0, 63, 63, 1, 152064, 0xac0d7bc2 -0, 64, 64, 1, 152064, 0x8dab2dde -0, 65, 65, 1, 152064, 0x566ad225 -0, 66, 66, 1, 152064, 0x587c7853 -0, 67, 67, 1, 152064, 0x601c9c80 -0, 68, 68, 1, 152064, 0x2afaf751 -0, 69, 69, 1, 152064, 0x1c9f7e3a -0, 70, 70, 1, 152064, 0x899475bf -0, 71, 71, 1, 152064, 0x0d65c7d9 -0, 72, 72, 1, 152064, 0xafd63d12 -0, 73, 73, 1, 152064, 0x162e62b9 -0, 74, 74, 1, 152064, 0x5c9554be -0, 75, 75, 1, 152064, 0x35fbdaa2 -0, 76, 76, 1, 152064, 0x6438cbd8 -0, 77, 77, 1, 152064, 0xde0772c9 -0, 78, 78, 1, 152064, 0x79f82854 -0, 79, 79, 1, 152064, 0x86957840 -0, 80, 80, 1, 152064, 0xd9468cbf -0, 81, 81, 1, 152064, 0x23e74609 -0, 82, 82, 1, 152064, 0x3919a146 -0, 83, 83, 1, 152064, 0xd641078b -0, 84, 84, 1, 152064, 0x24397220 -0, 85, 85, 1, 152064, 0xe7fc3a7c -0, 86, 86, 1, 152064, 0x3997154a -0, 87, 87, 1, 152064, 0x2af3952c -0, 88, 88, 1, 152064, 0x274ac07a -0, 89, 89, 1, 152064, 0x288f7b09 -0, 90, 90, 1, 152064, 0xe6f9b022 -0, 91, 91, 1, 152064, 0xf09e2fbb -0, 92, 92, 1, 152064, 0x7244e477 -0, 93, 93, 1, 152064, 0x0dfc72eb -0, 94, 94, 1, 152064, 0x0322b21f -0, 95, 95, 1, 152064, 0x18b08205 -0, 96, 96, 1, 152064, 0x6606153e -0, 97, 97, 1, 152064, 0x85186272 -0, 98, 98, 1, 152064, 0x3369f064 -0, 99, 99, 1, 152064, 0xbe0d5a44 -0, 100, 100, 1, 152064, 0x320258bb -0, 101, 101, 1, 152064, 0x4d6fb091 -0, 102, 102, 1, 152064, 0xc9bbf5e7 -0, 103, 103, 1, 152064, 0x0aa1b69b -0, 104, 104, 1, 152064, 0x85b9ac11 -0, 105, 105, 1, 152064, 0xb25ff818 -0, 106, 106, 1, 152064, 0xa155dc25 -0, 107, 107, 1, 152064, 0xa8e03bfd -0, 108, 108, 1, 152064, 0x0a862956 -0, 109, 109, 1, 152064, 0x11b49264 -0, 110, 110, 1, 152064, 0xa94e664e -0, 111, 111, 1, 152064, 0x330e0fa2 -0, 112, 112, 1, 152064, 0xaf3d9518 -0, 113, 113, 1, 152064, 0x0836f2e8 -0, 114, 114, 1, 152064, 0xbf6dc578 -0, 115, 115, 1, 152064, 0x7b524d20 -0, 116, 116, 1, 152064, 0x9ef7677f -0, 117, 117, 1, 152064, 0xeacf3f34 -0, 118, 118, 1, 152064, 0xfb4e3dbe -0, 119, 119, 1, 152064, 0xb46e25cb -0, 120, 120, 1, 152064, 0x363c1603 -0, 121, 121, 1, 152064, 0x263fc542 -0, 122, 122, 1, 152064, 0xf106e548 -0, 123, 123, 1, 152064, 0xde43c56a -0, 124, 124, 1, 152064, 0xc2c4770a -0, 125, 125, 1, 152064, 0x122fce19 -0, 126, 126, 1, 152064, 0x3ba01434 -0, 127, 127, 1, 152064, 0x0e8ce5ee -0, 128, 128, 1, 152064, 0x6ceb82e1 -0, 129, 129, 1, 152064, 0xa23ee21c -0, 130, 130, 1, 152064, 0xc6d960f9 -0, 131, 131, 1, 152064, 0x0de15258 -0, 132, 132, 1, 152064, 0x187b0333 -0, 133, 133, 1, 152064, 0x92e6582f -0, 134, 134, 1, 152064, 0xb9586ce0 -0, 135, 135, 1, 152064, 0xefd803b5 -0, 136, 136, 1, 152064, 0x24eafb29 -0, 137, 137, 1, 152064, 0x20c73b14 -0, 138, 138, 1, 152064, 0xbd7ceaaa -0, 139, 139, 1, 152064, 0x775216c8 -0, 140, 140, 1, 152064, 0xa08971c7 -0, 141, 141, 1, 152064, 0xef0ee865 -0, 142, 142, 1, 152064, 0x9ac61c2f -0, 143, 143, 1, 152064, 0x52ae8ea9 -0, 144, 144, 1, 152064, 0x06571c14 -0, 145, 145, 1, 152064, 0x6e78ad33 -0, 146, 146, 1, 152064, 0xad01c627 -0, 147, 147, 1, 152064, 0xbfe074d3 -0, 148, 148, 1, 152064, 0x9357a183 -0, 149, 149, 1, 152064, 0x8de7767f -0, 150, 150, 1, 152064, 0xa5e6e76e -0, 151, 151, 1, 152064, 0xa6f646fe -0, 152, 152, 1, 152064, 0x132e99f8 -0, 153, 153, 1, 152064, 0xb79f27de -0, 154, 154, 1, 152064, 0x36d3cdcf -0, 155, 155, 1, 152064, 0xdc938336 -0, 156, 156, 1, 152064, 0xacaa3a7f -0, 157, 157, 1, 152064, 0xc61a37fd -0, 158, 158, 1, 152064, 0x4fe1ddf0 -0, 159, 159, 1, 152064, 0xc0f7d660 -0, 160, 160, 1, 152064, 0xd72458ea -0, 161, 161, 1, 152064, 0x6978d123 -0, 162, 162, 1, 152064, 0x64e60ccf -0, 163, 163, 1, 152064, 0xaa07004c -0, 164, 164, 1, 152064, 0x07cd1064 -0, 165, 165, 1, 152064, 0xa82320e5 -0, 166, 166, 1, 152064, 0xaedd8d30 -0, 167, 167, 1, 152064, 0x79b082ea -0, 168, 168, 1, 152064, 0x9ed800ab -0, 169, 169, 1, 152064, 0xde592bb4 -0, 170, 170, 1, 152064, 0xd966df88 -0, 171, 171, 1, 152064, 0xf921988a -0, 172, 172, 1, 152064, 0x557ad9ae -0, 173, 173, 1, 152064, 0xc3f31a9a -0, 174, 174, 1, 152064, 0x65248561 -0, 175, 175, 1, 152064, 0x63df4aa6 -0, 176, 176, 1, 152064, 0x618da0a9 -0, 177, 177, 1, 152064, 0xe6f1c435 -0, 178, 178, 1, 152064, 0x9f90c38f -0, 179, 179, 1, 152064, 0xd2853e14 -0, 180, 180, 1, 152064, 0x6e0268a9 -0, 181, 181, 1, 152064, 0x393712d1 -0, 182, 182, 1, 152064, 0x470da25f -0, 183, 183, 1, 152064, 0xaf55cb3d -0, 184, 184, 1, 152064, 0x6935b8b9 -0, 185, 185, 1, 152064, 0x5409a15f -0, 186, 186, 1, 152064, 0x09073fee -0, 187, 187, 1, 152064, 0xfb274e82 -0, 188, 188, 1, 152064, 0x1a770581 -0, 189, 189, 1, 152064, 0x17277d0d -0, 190, 190, 1, 152064, 0xd4dcd982 -0, 191, 191, 1, 152064, 0x6b04eaf3 -0, 192, 192, 1, 152064, 0x8a3d822e -0, 193, 193, 1, 152064, 0x1b971ec9 -0, 194, 194, 1, 152064, 0x14e0c0f6 -0, 195, 195, 1, 152064, 0x00667450 -0, 196, 196, 1, 152064, 0xd2385902 -0, 197, 197, 1, 152064, 0x905da6ab -0, 198, 198, 1, 152064, 0xa3ffb18b -0, 199, 199, 1, 152064, 0x10d48b19 -0, 200, 200, 1, 152064, 0xb2c7a3bd -0, 201, 201, 1, 152064, 0x45593e96 -0, 202, 202, 1, 152064, 0x47a0b60c -0, 203, 203, 1, 152064, 0x68c6d1b9 -0, 204, 204, 1, 152064, 0xbc881fcc -0, 205, 205, 1, 152064, 0x422cc6f2 -0, 206, 206, 1, 152064, 0x9b686410 -0, 207, 207, 1, 152064, 0x35dc5e86 -0, 208, 208, 1, 152064, 0x247bedaa -0, 209, 209, 1, 152064, 0x22b76fd1 -0, 210, 210, 1, 152064, 0x67cc7a75 -0, 211, 211, 1, 152064, 0xa197521e -0, 212, 212, 1, 152064, 0x428c8662 -0, 213, 213, 1, 152064, 0x33dc2c73 -0, 214, 214, 1, 152064, 0x5b538903 -0, 215, 215, 1, 152064, 0x3c4176b6 -0, 216, 216, 1, 152064, 0x774364ba -0, 217, 217, 1, 152064, 0xf237d03e -0, 218, 218, 1, 152064, 0xac8746fb -0, 219, 219, 1, 152064, 0x6b306a84 -0, 220, 220, 1, 152064, 0xa2ace513 -0, 221, 221, 1, 152064, 0x709c9be7 -0, 222, 222, 1, 152064, 0x2403f373 -0, 223, 223, 1, 152064, 0x147bf717 -0, 224, 224, 1, 152064, 0xe58964c8 -0, 225, 225, 1, 152064, 0xa0da36fc -0, 226, 226, 1, 152064, 0x1ac1355c -0, 227, 227, 1, 152064, 0x8a31c9f2 -0, 228, 228, 1, 152064, 0x42ba205c -0, 229, 229, 1, 152064, 0xa11b3575 -0, 230, 230, 1, 152064, 0xcb35207c -0, 231, 231, 1, 152064, 0x528f6189 -0, 232, 232, 1, 152064, 0x34f05bd7 -0, 233, 233, 1, 152064, 0x72317356 -0, 234, 234, 1, 152064, 0xaabd5028 -0, 235, 235, 1, 152064, 0x13dbeb7b -0, 236, 236, 1, 152064, 0x62f1e8a8 -0, 237, 237, 1, 152064, 0x1723bfcd -0, 238, 238, 1, 152064, 0x5c083c00 -0, 239, 239, 1, 152064, 0x52137894 -0, 240, 240, 1, 152064, 0xef1e082c -0, 241, 241, 1, 152064, 0x664b3d53 -0, 242, 242, 1, 152064, 0x2eb9b296 -0, 243, 243, 1, 152064, 0xd0ca511e -0, 244, 244, 1, 152064, 0x012d4724 -0, 245, 245, 1, 152064, 0xa847f5af -0, 246, 246, 1, 152064, 0x483a2fde -0, 247, 247, 1, 152064, 0xd1ab0257 -0, 248, 248, 1, 152064, 0x414692c7 -0, 249, 249, 1, 152064, 0x0b79df88 -0, 250, 250, 1, 152064, 0xdaa2c4a3 -0, 251, 251, 1, 152064, 0xd1b44500 -0, 252, 252, 1, 152064, 0xfd3d2cf3 -0, 253, 253, 1, 152064, 0xfdc0f748 -0, 254, 254, 1, 152064, 0xce762a2a -0, 255, 255, 1, 152064, 0x08b63572 -0, 256, 256, 1, 152064, 0x5a46a38d -0, 257, 257, 1, 152064, 0x03cee9c0 -0, 258, 258, 1, 152064, 0x9ee45473 -0, 259, 259, 1, 152064, 0x5a432386 -0, 260, 260, 1, 152064, 0x54c83d87 -0, 261, 261, 1, 152064, 0xc9caa1de -0, 262, 262, 1, 152064, 0xa28367f1 -0, 263, 263, 1, 152064, 0x2607cdf1 -0, 264, 264, 1, 152064, 0x06baa8de -0, 265, 265, 1, 152064, 0xf5346e32 -0, 266, 266, 1, 152064, 0x6d3e732b -0, 267, 267, 1, 152064, 0x798c584b -0, 268, 268, 1, 152064, 0x4076c948 -0, 269, 269, 1, 152064, 0x868cf63a -0, 270, 270, 1, 152064, 0x23107ac5 -0, 271, 271, 1, 152064, 0x306f3fe2 -0, 272, 272, 1, 152064, 0xbd1d71d6 -0, 273, 273, 1, 152064, 0x1429545f -0, 274, 274, 1, 152064, 0xaded29aa -0, 275, 275, 1, 152064, 0x9b455a94 -0, 276, 276, 1, 152064, 0xb3774ce7 -0, 277, 277, 1, 152064, 0x92580986 -0, 278, 278, 1, 152064, 0x0eae2f95 -0, 279, 279, 1, 152064, 0x599208b2 -0, 280, 280, 1, 152064, 0x4804c04c -0, 281, 281, 1, 152064, 0x5f730e8f -0, 282, 282, 1, 152064, 0x3e501d1e -0, 283, 283, 1, 152064, 0x32100740 -0, 284, 284, 1, 152064, 0x62226ff8 -0, 285, 285, 1, 152064, 0x7683b622 -0, 286, 286, 1, 152064, 0xc3e0aec1 -0, 287, 287, 1, 152064, 0xfac12608 -0, 288, 288, 1, 152064, 0xb21a5781 -0, 289, 289, 1, 152064, 0x8f1e4964 -0, 290, 290, 1, 152064, 0x0f62dd6e -0, 291, 291, 1, 152064, 0xac062ac4 -0, 292, 292, 1, 152064, 0x1b320f7a -0, 293, 293, 1, 152064, 0x346e7211 -0, 294, 294, 1, 152064, 0xe47592f3 -0, 295, 295, 1, 152064, 0xa3a7919c -0, 296, 296, 1, 152064, 0xa3580fa6 -0, 297, 297, 1, 152064, 0xc73430c1 -0, 298, 298, 1, 152064, 0x994a2c18 -0, 299, 299, 1, 152064, 0x0b5d8d45 -0, 300, 300, 1, 152064, 0x9eed5109 +0, 0, 0, 1, 152064, 0x3e39c08b +0, 1, 1, 1, 152064, 0xabc67990 +0, 2, 2, 1, 152064, 0x19614e74 +0, 3, 3, 1, 152064, 0xa3776beb +0, 4, 4, 1, 152064, 0xcce6ffdf +0, 5, 5, 1, 152064, 0xb0e94746 +0, 6, 6, 1, 152064, 0xdb1a84ef +0, 7, 7, 1, 152064, 0xb2624509 +0, 8, 8, 1, 152064, 0x32e2d826 +0, 9, 9, 1, 152064, 0xb3bddf0b +0, 10, 10, 1, 152064, 0x2e273ce3 +0, 11, 11, 1, 152064, 0x67af7e4d +0, 12, 12, 1, 152064, 0x505c3261 +0, 13, 13, 1, 152064, 0xa43d015e +0, 14, 14, 1, 152064, 0xad41c1f6 +0, 15, 15, 1, 152064, 0x633ba55f +0, 16, 16, 1, 152064, 0xe80634f0 +0, 17, 17, 1, 152064, 0x80a07dc9 +0, 18, 18, 1, 152064, 0x0e7a3bbf +0, 19, 19, 1, 152064, 0xcb099196 +0, 20, 20, 1, 152064, 0x57c96db5 +0, 21, 21, 1, 152064, 0xccd422fa +0, 22, 22, 1, 152064, 0x0850b7a7 +0, 23, 23, 1, 152064, 0x30e33156 +0, 24, 24, 1, 152064, 0x34e13f9a +0, 25, 25, 1, 152064, 0x03d36000 +0, 26, 26, 1, 152064, 0xbf7d49da +0, 27, 27, 1, 152064, 0x77336d09 +0, 28, 28, 1, 152064, 0xca8be5a9 +0, 29, 29, 1, 152064, 0xe57c0b08 +0, 30, 30, 1, 152064, 0xbe77c093 +0, 31, 31, 1, 152064, 0x6bf1ff05 +0, 32, 32, 1, 152064, 0x9142babf +0, 33, 33, 1, 152064, 0x08db8e67 +0, 34, 34, 1, 152064, 0x69ac8cb6 +0, 35, 35, 1, 152064, 0xaa3b5c88 +0, 36, 36, 1, 152064, 0x9bd32638 +0, 37, 37, 1, 152064, 0x7972115a +0, 38, 38, 1, 152064, 0x5c1dd47b +0, 39, 39, 1, 152064, 0x8a196e02 +0, 40, 40, 1, 152064, 0xa89672bc +0, 41, 41, 1, 152064, 0x27b220e4 +0, 42, 42, 1, 152064, 0xfa38dc4a +0, 43, 43, 1, 152064, 0x4784c639 +0, 44, 44, 1, 152064, 0xa5e4229a +0, 45, 45, 1, 152064, 0xa986bdfc +0, 46, 46, 1, 152064, 0x2951b47b +0, 47, 47, 1, 152064, 0x4df404a6 +0, 48, 48, 1, 152064, 0xc75155e8 +0, 49, 49, 1, 152064, 0xfc05248c +0, 50, 50, 1, 152064, 0x5d53da10 +0, 51, 51, 1, 152064, 0x284376ec +0, 52, 52, 1, 152064, 0x19fce380 +0, 53, 53, 1, 152064, 0x876be6c9 +0, 54, 54, 1, 152064, 0x39eb8ff9 +0, 55, 55, 1, 152064, 0x289c9543 +0, 56, 56, 1, 152064, 0x24dd2356 +0, 57, 57, 1, 152064, 0x1dc17d3c +0, 58, 58, 1, 152064, 0xd17c00ac +0, 59, 59, 1, 152064, 0xc2ad54de +0, 60, 60, 1, 152064, 0xbe11ee2f +0, 61, 61, 1, 152064, 0x3db9dc89 +0, 62, 62, 1, 152064, 0xac0d7bc2 +0, 63, 63, 1, 152064, 0x8dab2dde +0, 64, 64, 1, 152064, 0x566ad225 +0, 65, 65, 1, 152064, 0x587c7853 +0, 66, 66, 1, 152064, 0x601c9c80 +0, 67, 67, 1, 152064, 0x2afaf751 +0, 68, 68, 1, 152064, 0x1c9f7e3a +0, 69, 69, 1, 152064, 0x899475bf +0, 70, 70, 1, 152064, 0x0d65c7d9 +0, 71, 71, 1, 152064, 0xafd63d12 +0, 72, 72, 1, 152064, 0x162e62b9 +0, 73, 73, 1, 152064, 0x5c9554be +0, 74, 74, 1, 152064, 0x35fbdaa2 +0, 75, 75, 1, 152064, 0x6438cbd8 +0, 76, 76, 1, 152064, 0xde0772c9 +0, 77, 77, 1, 152064, 0x79f82854 +0, 78, 78, 1, 152064, 0x86957840 +0, 79, 79, 1, 152064, 0xd9468cbf +0, 80, 80, 1, 152064, 0x23e74609 +0, 81, 81, 1, 152064, 0x3919a146 +0, 82, 82, 1, 152064, 0xd641078b +0, 83, 83, 1, 152064, 0x24397220 +0, 84, 84, 1, 152064, 0xe7fc3a7c +0, 85, 85, 1, 152064, 0x3997154a +0, 86, 86, 1, 152064, 0x2af3952c +0, 87, 87, 1, 152064, 0x274ac07a +0, 88, 88, 1, 152064, 0x288f7b09 +0, 89, 89, 1, 152064, 0xe6f9b022 +0, 90, 90, 1, 152064, 0xf09e2fbb +0, 91, 91, 1, 152064, 0x7244e477 +0, 92, 92, 1, 152064, 0x0dfc72eb +0, 93, 93, 1, 152064, 0x0322b21f +0, 94, 94, 1, 152064, 0x18b08205 +0, 95, 95, 1, 152064, 0x6606153e +0, 96, 96, 1, 152064, 0x85186272 +0, 97, 97, 1, 152064, 0x3369f064 +0, 98, 98, 1, 152064, 0xbe0d5a44 +0, 99, 99, 1, 152064, 0x320258bb +0, 100, 100, 1, 152064, 0x4d6fb091 +0, 101, 101, 1, 152064, 0xc9bbf5e7 +0, 102, 102, 1, 152064, 0x0aa1b69b +0, 103, 103, 1, 152064, 0x85b9ac11 +0, 104, 104, 1, 152064, 0xb25ff818 +0, 105, 105, 1, 152064, 0xa155dc25 +0, 106, 106, 1, 152064, 0xa8e03bfd +0, 107, 107, 1, 152064, 0x0a862956 +0, 108, 108, 1, 152064, 0x11b49264 +0, 109, 109, 1, 152064, 0xa94e664e +0, 110, 110, 1, 152064, 0x330e0fa2 +0, 111, 111, 1, 152064, 0xaf3d9518 +0, 112, 112, 1, 152064, 0x0836f2e8 +0, 113, 113, 1, 152064, 0xbf6dc578 +0, 114, 114, 1, 152064, 0x7b524d20 +0, 115, 115, 1, 152064, 0x9ef7677f +0, 116, 116, 1, 152064, 0xeacf3f34 +0, 117, 117, 1, 152064, 0xfb4e3dbe +0, 118, 118, 1, 152064, 0xb46e25cb +0, 119, 119, 1, 152064, 0x363c1603 +0, 120, 120, 1, 152064, 0x263fc542 +0, 121, 121, 1, 152064, 0xf106e548 +0, 122, 122, 1, 152064, 0xde43c56a +0, 123, 123, 1, 152064, 0xc2c4770a +0, 124, 124, 1, 152064, 0x122fce19 +0, 125, 125, 1, 152064, 0x3ba01434 +0, 126, 126, 1, 152064, 0x0e8ce5ee +0, 127, 127, 1, 152064, 0x6ceb82e1 +0, 128, 128, 1, 152064, 0xa23ee21c +0, 129, 129, 1, 152064, 0xc6d960f9 +0, 130, 130, 1, 152064, 0x0de15258 +0, 131, 131, 1, 152064, 0x187b0333 +0, 132, 132, 1, 152064, 0x92e6582f +0, 133, 133, 1, 152064, 0xb9586ce0 +0, 134, 134, 1, 152064, 0xefd803b5 +0, 135, 135, 1, 152064, 0x24eafb29 +0, 136, 136, 1, 152064, 0x20c73b14 +0, 137, 137, 1, 152064, 0xbd7ceaaa +0, 138, 138, 1, 152064, 0x775216c8 +0, 139, 139, 1, 152064, 0xa08971c7 +0, 140, 140, 1, 152064, 0xef0ee865 +0, 141, 141, 1, 152064, 0x9ac61c2f +0, 142, 142, 1, 152064, 0x52ae8ea9 +0, 143, 143, 1, 152064, 0x06571c14 +0, 144, 144, 1, 152064, 0x6e78ad33 +0, 145, 145, 1, 152064, 0xad01c627 +0, 146, 146, 1, 152064, 0xbfe074d3 +0, 147, 147, 1, 152064, 0x9357a183 +0, 148, 148, 1, 152064, 0x8de7767f +0, 149, 149, 1, 152064, 0xa5e6e76e +0, 150, 150, 1, 152064, 0xa6f646fe +0, 151, 151, 1, 152064, 0x132e99f8 +0, 152, 152, 1, 152064, 0xb79f27de +0, 153, 153, 1, 152064, 0x36d3cdcf +0, 154, 154, 1, 152064, 0xdc938336 +0, 155, 155, 1, 152064, 0xacaa3a7f +0, 156, 156, 1, 152064, 0xc61a37fd +0, 157, 157, 1, 152064, 0x4fe1ddf0 +0, 158, 158, 1, 152064, 0xc0f7d660 +0, 159, 159, 1, 152064, 0xd72458ea +0, 160, 160, 1, 152064, 0x6978d123 +0, 161, 161, 1, 152064, 0x64e60ccf +0, 162, 162, 1, 152064, 0xaa07004c +0, 163, 163, 1, 152064, 0x07cd1064 +0, 164, 164, 1, 152064, 0xa82320e5 +0, 165, 165, 1, 152064, 0xaedd8d30 +0, 166, 166, 1, 152064, 0x79b082ea +0, 167, 167, 1, 152064, 0x9ed800ab +0, 168, 168, 1, 152064, 0xde592bb4 +0, 169, 169, 1, 152064, 0xd966df88 +0, 170, 170, 1, 152064, 0xf921988a +0, 171, 171, 1, 152064, 0x557ad9ae +0, 172, 172, 1, 152064, 0xc3f31a9a +0, 173, 173, 1, 152064, 0x65248561 +0, 174, 174, 1, 152064, 0x63df4aa6 +0, 175, 175, 1, 152064, 0x618da0a9 +0, 176, 176, 1, 152064, 0xe6f1c435 +0, 177, 177, 1, 152064, 0x9f90c38f +0, 178, 178, 1, 152064, 0xd2853e14 +0, 179, 179, 1, 152064, 0x6e0268a9 +0, 180, 180, 1, 152064, 0x393712d1 +0, 181, 181, 1, 152064, 0x470da25f +0, 182, 182, 1, 152064, 0xaf55cb3d +0, 183, 183, 1, 152064, 0x6935b8b9 +0, 184, 184, 1, 152064, 0x5409a15f +0, 185, 185, 1, 152064, 0x09073fee +0, 186, 186, 1, 152064, 0xfb274e82 +0, 187, 187, 1, 152064, 0x1a770581 +0, 188, 188, 1, 152064, 0x17277d0d +0, 189, 189, 1, 152064, 0xd4dcd982 +0, 190, 190, 1, 152064, 0x6b04eaf3 +0, 191, 191, 1, 152064, 0x8a3d822e +0, 192, 192, 1, 152064, 0x1b971ec9 +0, 193, 193, 1, 152064, 0x14e0c0f6 +0, 194, 194, 1, 152064, 0x00667450 +0, 195, 195, 1, 152064, 0xd2385902 +0, 196, 196, 1, 152064, 0x905da6ab +0, 197, 197, 1, 152064, 0xa3ffb18b +0, 198, 198, 1, 152064, 0x10d48b19 +0, 199, 199, 1, 152064, 0xb2c7a3bd +0, 200, 200, 1, 152064, 0x45593e96 +0, 201, 201, 1, 152064, 0x47a0b60c +0, 202, 202, 1, 152064, 0x68c6d1b9 +0, 203, 203, 1, 152064, 0xbc881fcc +0, 204, 204, 1, 152064, 0x422cc6f2 +0, 205, 205, 1, 152064, 0x9b686410 +0, 206, 206, 1, 152064, 0x35dc5e86 +0, 207, 207, 1, 152064, 0x247bedaa +0, 208, 208, 1, 152064, 0x22b76fd1 +0, 209, 209, 1, 152064, 0x67cc7a75 +0, 210, 210, 1, 152064, 0xa197521e +0, 211, 211, 1, 152064, 0x428c8662 +0, 212, 212, 1, 152064, 0x33dc2c73 +0, 213, 213, 1, 152064, 0x5b538903 +0, 214, 214, 1, 152064, 0x3c4176b6 +0, 215, 215, 1, 152064, 0x774364ba +0, 216, 216, 1, 152064, 0xf237d03e +0, 217, 217, 1, 152064, 0xac8746fb +0, 218, 218, 1, 152064, 0x6b306a84 +0, 219, 219, 1, 152064, 0xa2ace513 +0, 220, 220, 1, 152064, 0x709c9be7 +0, 221, 221, 1, 152064, 0x2403f373 +0, 222, 222, 1, 152064, 0x147bf717 +0, 223, 223, 1, 152064, 0xe58964c8 +0, 224, 224, 1, 152064, 0xa0da36fc +0, 225, 225, 1, 152064, 0x1ac1355c +0, 226, 226, 1, 152064, 0x8a31c9f2 +0, 227, 227, 1, 152064, 0x42ba205c +0, 228, 228, 1, 152064, 0xa11b3575 +0, 229, 229, 1, 152064, 0xcb35207c +0, 230, 230, 1, 152064, 0x528f6189 +0, 231, 231, 1, 152064, 0x34f05bd7 +0, 232, 232, 1, 152064, 0x72317356 +0, 233, 233, 1, 152064, 0xaabd5028 +0, 234, 234, 1, 152064, 0x13dbeb7b +0, 235, 235, 1, 152064, 0x62f1e8a8 +0, 236, 236, 1, 152064, 0x1723bfcd +0, 237, 237, 1, 152064, 0x5c083c00 +0, 238, 238, 1, 152064, 0x52137894 +0, 239, 239, 1, 152064, 0xef1e082c +0, 240, 240, 1, 152064, 0x664b3d53 +0, 241, 241, 1, 152064, 0x2eb9b296 +0, 242, 242, 1, 152064, 0xd0ca511e +0, 243, 243, 1, 152064, 0x012d4724 +0, 244, 244, 1, 152064, 0xa847f5af +0, 245, 245, 1, 152064, 0x483a2fde +0, 246, 246, 1, 152064, 0xd1ab0257 +0, 247, 247, 1, 152064, 0x414692c7 +0, 248, 248, 1, 152064, 0x0b79df88 +0, 249, 249, 1, 152064, 0xdaa2c4a3 +0, 250, 250, 1, 152064, 0xd1b44500 +0, 251, 251, 1, 152064, 0xfd3d2cf3 +0, 252, 252, 1, 152064, 0xfdc0f748 +0, 253, 253, 1, 152064, 0xce762a2a +0, 254, 254, 1, 152064, 0x08b63572 +0, 255, 255, 1, 152064, 0x5a46a38d +0, 256, 256, 1, 152064, 0x03cee9c0 +0, 257, 257, 1, 152064, 0x9ee45473 +0, 258, 258, 1, 152064, 0x5a432386 +0, 259, 259, 1, 152064, 0x54c83d87 +0, 260, 260, 1, 152064, 0xc9caa1de +0, 261, 261, 1, 152064, 0xa28367f1 +0, 262, 262, 1, 152064, 0x2607cdf1 +0, 263, 263, 1, 152064, 0x06baa8de +0, 264, 264, 1, 152064, 0xf5346e32 +0, 265, 265, 1, 152064, 0x6d3e732b +0, 266, 266, 1, 152064, 0x798c584b +0, 267, 267, 1, 152064, 0x4076c948 +0, 268, 268, 1, 152064, 0x868cf63a +0, 269, 269, 1, 152064, 0x23107ac5 +0, 270, 270, 1, 152064, 0x306f3fe2 +0, 271, 271, 1, 152064, 0xbd1d71d6 +0, 272, 272, 1, 152064, 0x1429545f +0, 273, 273, 1, 152064, 0xaded29aa +0, 274, 274, 1, 152064, 0x9b455a94 +0, 275, 275, 1, 152064, 0xb3774ce7 +0, 276, 276, 1, 152064, 0x92580986 +0, 277, 277, 1, 152064, 0x0eae2f95 +0, 278, 278, 1, 152064, 0x599208b2 +0, 279, 279, 1, 152064, 0x4804c04c +0, 280, 280, 1, 152064, 0x5f730e8f +0, 281, 281, 1, 152064, 0x3e501d1e +0, 282, 282, 1, 152064, 0x32100740 +0, 283, 283, 1, 152064, 0x62226ff8 +0, 284, 284, 1, 152064, 0x7683b622 +0, 285, 285, 1, 152064, 0xc3e0aec1 +0, 286, 286, 1, 152064, 0xfac12608 +0, 287, 287, 1, 152064, 0xb21a5781 +0, 288, 288, 1, 152064, 0x8f1e4964 +0, 289, 289, 1, 152064, 0x0f62dd6e +0, 290, 290, 1, 152064, 0xac062ac4 +0, 291, 291, 1, 152064, 0x1b320f7a +0, 292, 292, 1, 152064, 0x346e7211 +0, 293, 293, 1, 152064, 0xe47592f3 +0, 294, 294, 1, 152064, 0xa3a7919c +0, 295, 295, 1, 152064, 0xa3580fa6 +0, 296, 296, 1, 152064, 0xc73430c1 +0, 297, 297, 1, 152064, 0x994a2c18 +0, 298, 298, 1, 152064, 0x0b5d8d45 +0, 299, 299, 1, 152064, 0x9eed5109 diff --git a/tests/ref/fate/h264-conformance-mr3_tandberg_b b/tests/ref/fate/h264-conformance-mr3_tandberg_b index e86d7218360..b0948448cd4 100644 --- a/tests/ref/fate/h264-conformance-mr3_tandberg_b +++ b/tests/ref/fate/h264-conformance-mr3_tandberg_b @@ -12,294 +12,294 @@ 0, 6, 6, 1, 38016, 0x7cc17319 0, 7, 7, 1, 38016, 0x0f7e8cab 0, 8, 8, 1, 38016, 0x1876abee -0, 10, 10, 1, 38016, 0xda748c2f -0, 11, 11, 1, 38016, 0x7b4dbff0 -0, 12, 12, 1, 38016, 0xd4a1b24a -0, 13, 13, 1, 38016, 0x714cb4cc -0, 14, 14, 1, 38016, 0x2c6d80f0 -0, 15, 15, 1, 38016, 0x92266151 -0, 16, 16, 1, 38016, 0x6b766a23 -0, 17, 17, 1, 38016, 0xb24f7efe -0, 18, 18, 1, 38016, 0x8410838e -0, 19, 19, 1, 38016, 0x67fe872a -0, 20, 20, 1, 38016, 0x55b49d36 -0, 21, 21, 1, 38016, 0x7a1c9c41 -0, 22, 22, 1, 38016, 0xb4818e0e -0, 23, 23, 1, 38016, 0x25f6683c -0, 24, 24, 1, 38016, 0xe4d141a4 -0, 25, 25, 1, 38016, 0x808216ad -0, 26, 26, 1, 38016, 0x2acf0baf -0, 27, 27, 1, 38016, 0xf3de13c4 -0, 28, 28, 1, 38016, 0x5f412187 -0, 29, 29, 1, 38016, 0xb31a340a -0, 30, 30, 1, 38016, 0x019d42d1 -0, 31, 31, 1, 38016, 0xeeb94b9b -0, 32, 32, 1, 38016, 0xef55472e -0, 33, 33, 1, 38016, 0xdb5e3697 -0, 34, 34, 1, 38016, 0x8565303e -0, 35, 35, 1, 38016, 0x5f9c2c1b -0, 36, 36, 1, 38016, 0xeb3d27f4 -0, 37, 37, 1, 38016, 0x9a43282d -0, 38, 38, 1, 38016, 0xe04720c6 -0, 39, 39, 1, 38016, 0x19cc0eba -0, 40, 40, 1, 38016, 0x218efeb6 -0, 41, 41, 1, 38016, 0x7733f491 -0, 42, 42, 1, 38016, 0x7f3bede9 -0, 43, 43, 1, 38016, 0x49c5ec0d -0, 44, 44, 1, 38016, 0x803cf19e -0, 45, 45, 1, 38016, 0x31de0d3f -0, 46, 46, 1, 38016, 0xa7e30426 -0, 47, 47, 1, 38016, 0xba37f068 -0, 48, 48, 1, 38016, 0x2842bdf8 -0, 49, 49, 1, 38016, 0x76df97dc -0, 50, 50, 1, 38016, 0xf3246d26 -0, 51, 51, 1, 38016, 0x0a384d72 -0, 52, 52, 1, 38016, 0x40964f41 -0, 53, 53, 1, 38016, 0x46364324 -0, 54, 54, 1, 38016, 0x7cbf3db4 -0, 55, 55, 1, 38016, 0x7a223bec -0, 56, 56, 1, 38016, 0x458651c1 -0, 57, 57, 1, 38016, 0xb82d7e3c -0, 58, 58, 1, 38016, 0x0f50a55d -0, 59, 59, 1, 38016, 0xc306cae4 -0, 60, 60, 1, 38016, 0x9d6ddfcb -0, 61, 61, 1, 38016, 0xb602e8e9 -0, 62, 62, 1, 38016, 0xbf0ae386 -0, 63, 63, 1, 38016, 0x0a8bd46e -0, 64, 64, 1, 38016, 0xd437c5c1 -0, 65, 65, 1, 38016, 0xd61d9959 -0, 66, 66, 1, 38016, 0x70639b56 -0, 67, 67, 1, 38016, 0x36fd407b -0, 68, 68, 1, 38016, 0x58ce3ddd -0, 69, 69, 1, 38016, 0x86cc1d8c -0, 70, 70, 1, 38016, 0xee422dc2 -0, 71, 71, 1, 38016, 0xab475639 -0, 72, 72, 1, 38016, 0xc1327ad8 -0, 73, 73, 1, 38016, 0x63d196d4 -0, 74, 74, 1, 38016, 0x1aba8ebd -0, 75, 75, 1, 38016, 0x74a269ac -0, 76, 76, 1, 38016, 0x267f3563 -0, 77, 77, 1, 38016, 0xa18ff180 -0, 78, 78, 1, 38016, 0x70c9c9fd -0, 79, 79, 1, 38016, 0xa6c59f9c -0, 80, 80, 1, 38016, 0xd7cd8927 -0, 81, 81, 1, 38016, 0xd30b7345 -0, 82, 82, 1, 38016, 0x679a4dda -0, 83, 83, 1, 38016, 0xeb0562de -0, 84, 84, 1, 38016, 0xdd7d6cdb -0, 85, 85, 1, 38016, 0xd6e26b73 -0, 86, 86, 1, 38016, 0xa65a860f -0, 87, 87, 1, 38016, 0xae95c71e -0, 88, 88, 1, 38016, 0x1a89ca86 -0, 89, 89, 1, 38016, 0xa33ecee6 -0, 90, 90, 1, 38016, 0x821da6cb -0, 91, 91, 1, 38016, 0xf0e1612f -0, 92, 92, 1, 38016, 0x67b8516b -0, 93, 93, 1, 38016, 0x62f965bc -0, 94, 94, 1, 38016, 0xd1917aa6 -0, 95, 95, 1, 38016, 0xe72db54d -0, 96, 96, 1, 38016, 0x9b64e721 -0, 97, 97, 1, 38016, 0xa819efda -0, 98, 98, 1, 38016, 0xeacfdacb -0, 99, 99, 1, 38016, 0x52f235e1 -0, 100, 100, 1, 38016, 0x2b512cb8 -0, 101, 101, 1, 38016, 0xaac73fb3 -0, 102, 102, 1, 38016, 0x7d2d504f -0, 103, 103, 1, 38016, 0x396d503a -0, 104, 104, 1, 38016, 0x97905235 -0, 105, 105, 1, 38016, 0xf0056693 -0, 106, 106, 1, 38016, 0x728a6a9e -0, 107, 107, 1, 38016, 0x0eed7824 -0, 108, 108, 1, 38016, 0x59506237 -0, 109, 109, 1, 38016, 0xd4304c93 -0, 110, 110, 1, 38016, 0x7e663ee8 -0, 111, 111, 1, 38016, 0x0ebc2d11 -0, 112, 112, 1, 38016, 0x52db2112 -0, 113, 113, 1, 38016, 0x74aa1815 -0, 114, 114, 1, 38016, 0x57a60dc6 -0, 115, 115, 1, 38016, 0x86e9fa32 -0, 116, 116, 1, 38016, 0x67e8ff09 -0, 117, 117, 1, 38016, 0x26e8f7ea -0, 118, 118, 1, 38016, 0x183dff56 -0, 119, 119, 1, 38016, 0xa470af8d -0, 120, 120, 1, 38016, 0xe017d594 -0, 121, 121, 1, 38016, 0xb899d48b -0, 122, 122, 1, 38016, 0x0d3bc5f7 -0, 123, 123, 1, 38016, 0xd68bbb0d -0, 124, 124, 1, 38016, 0x8bf5b4cb -0, 125, 125, 1, 38016, 0x6bfcaa47 -0, 126, 126, 1, 38016, 0x29a9b01b -0, 127, 127, 1, 38016, 0xcdedbdb7 -0, 128, 128, 1, 38016, 0xdb5ad9c3 -0, 129, 129, 1, 38016, 0x468aeef6 -0, 130, 130, 1, 38016, 0xdc2b143e -0, 131, 131, 1, 38016, 0x6776277c -0, 132, 132, 1, 38016, 0xb78d5294 -0, 133, 133, 1, 38016, 0x1dfb63ab -0, 134, 134, 1, 38016, 0xbd1f99bc -0, 135, 135, 1, 38016, 0xde16b89a -0, 136, 136, 1, 38016, 0xbf46edca -0, 137, 137, 1, 38016, 0x6306e8c4 -0, 138, 138, 1, 38016, 0x7b09d224 -0, 139, 139, 1, 38016, 0xfea1aff6 -0, 140, 140, 1, 38016, 0x183686b0 -0, 141, 141, 1, 38016, 0x665a61ff -0, 142, 142, 1, 38016, 0xc8af42d1 -0, 143, 143, 1, 38016, 0xe2326bc1 -0, 144, 144, 1, 38016, 0x56dbde82 -0, 145, 145, 1, 38016, 0xa0254f97 -0, 146, 146, 1, 38016, 0x3b74a0b4 -0, 147, 147, 1, 38016, 0x9aee9b7f -0, 148, 148, 1, 38016, 0xd94b6133 -0, 149, 149, 1, 38016, 0x5819f795 -0, 150, 150, 1, 38016, 0xc45a8c02 -0, 151, 151, 1, 38016, 0x2f9204a0 -0, 152, 152, 1, 38016, 0xbe09e051 -0, 153, 153, 1, 38016, 0xb542badd -0, 154, 154, 1, 38016, 0x23bd9e00 -0, 155, 155, 1, 38016, 0x4f338d3d -0, 156, 156, 1, 38016, 0x8c91e8f3 -0, 157, 157, 1, 38016, 0xa7347d57 -0, 158, 158, 1, 38016, 0x6d91de4d -0, 159, 159, 1, 38016, 0x3443d936 -0, 160, 160, 1, 38016, 0x9d25b4e2 -0, 161, 161, 1, 38016, 0xd93cd4b3 -0, 162, 162, 1, 38016, 0xa1c9e9a0 -0, 163, 163, 1, 38016, 0x1482f220 -0, 164, 164, 1, 38016, 0x1295f270 -0, 165, 165, 1, 38016, 0x399ae9da -0, 166, 166, 1, 38016, 0x85dcdf28 -0, 167, 167, 1, 38016, 0x4207b9e5 -0, 168, 168, 1, 38016, 0xad1c9d75 -0, 169, 169, 1, 38016, 0x4a266c14 -0, 170, 170, 1, 38016, 0x3afc4508 -0, 171, 171, 1, 38016, 0x2b1b2385 -0, 172, 172, 1, 38016, 0x738f005f -0, 173, 173, 1, 38016, 0xfec3d833 -0, 174, 174, 1, 38016, 0x3f7f6ae9 -0, 175, 175, 1, 38016, 0xd8551823 -0, 176, 176, 1, 38016, 0x6df03570 -0, 177, 177, 1, 38016, 0x767c3054 -0, 178, 178, 1, 38016, 0x89bd342c -0, 179, 179, 1, 38016, 0x77ba806c -0, 180, 180, 1, 38016, 0x1c98005c -0, 181, 181, 1, 38016, 0xa13ce2a3 -0, 182, 182, 1, 38016, 0x1be59915 -0, 183, 183, 1, 38016, 0x279c6027 -0, 184, 184, 1, 38016, 0x96ac11a2 -0, 185, 185, 1, 38016, 0x3ae95131 -0, 186, 186, 1, 38016, 0xae19f7fe -0, 187, 187, 1, 38016, 0xcde4efe6 -0, 188, 188, 1, 38016, 0x5ecc3f7a -0, 189, 189, 1, 38016, 0x79645152 -0, 190, 190, 1, 38016, 0x1ee2e89f -0, 191, 191, 1, 38016, 0x91d34bb4 -0, 192, 192, 1, 38016, 0xf019d464 -0, 193, 193, 1, 38016, 0x8eb07205 -0, 194, 194, 1, 38016, 0x5399bb5b -0, 195, 195, 1, 38016, 0x61f0c77a -0, 196, 196, 1, 38016, 0xb2bd8726 -0, 197, 197, 1, 38016, 0x47b89243 -0, 198, 198, 1, 38016, 0xebfe4d76 -0, 199, 199, 1, 38016, 0xe8f87d91 -0, 200, 200, 1, 38016, 0x5e9fb239 -0, 201, 201, 1, 38016, 0x357ca1f8 -0, 202, 202, 1, 38016, 0x757d2e02 -0, 203, 203, 1, 38016, 0x40672e7c -0, 204, 204, 1, 38016, 0xd966abca -0, 205, 205, 1, 38016, 0xe98d0d47 -0, 206, 206, 1, 38016, 0x341babf5 -0, 207, 207, 1, 38016, 0xd12d5a0c -0, 208, 208, 1, 38016, 0xea2f99ab -0, 209, 209, 1, 38016, 0x14bce88e -0, 210, 210, 1, 38016, 0xe4bda9e8 -0, 211, 211, 1, 38016, 0x2c57ec89 -0, 212, 212, 1, 38016, 0x28bbb83e -0, 213, 213, 1, 38016, 0xf8444b54 -0, 214, 214, 1, 38016, 0x3aba03cd -0, 215, 215, 1, 38016, 0x373daa20 -0, 216, 216, 1, 38016, 0x69586597 -0, 217, 217, 1, 38016, 0xc0c70d53 -0, 218, 218, 1, 38016, 0x76a5df5a -0, 219, 219, 1, 38016, 0x1afde8f0 -0, 220, 220, 1, 38016, 0x9638285a -0, 221, 221, 1, 38016, 0x9f0686c0 -0, 222, 222, 1, 38016, 0xc65b2238 -0, 223, 223, 1, 38016, 0x0d61b610 -0, 224, 224, 1, 38016, 0x78e14e1f -0, 225, 225, 1, 38016, 0xcf80ac4a -0, 226, 226, 1, 38016, 0xe094083d -0, 227, 227, 1, 38016, 0xee5e612e -0, 228, 228, 1, 38016, 0x51cdad9d -0, 229, 229, 1, 38016, 0xae41100e -0, 230, 230, 1, 38016, 0x77558f58 -0, 231, 231, 1, 38016, 0xb9503b95 -0, 232, 232, 1, 38016, 0xb71dffeb -0, 233, 233, 1, 38016, 0x1872e3e6 -0, 234, 234, 1, 38016, 0x29c3d252 -0, 235, 235, 1, 38016, 0x1c77c6ec -0, 236, 236, 1, 38016, 0x26feb194 -0, 237, 237, 1, 38016, 0x3307c3c4 -0, 238, 238, 1, 38016, 0x8e5a8080 -0, 239, 239, 1, 38016, 0x933472f7 -0, 240, 240, 1, 38016, 0xd4768d84 -0, 241, 241, 1, 38016, 0x3324485f -0, 242, 242, 1, 38016, 0xd50af078 -0, 243, 243, 1, 38016, 0x53820752 -0, 244, 244, 1, 38016, 0xbe7f1c47 -0, 245, 245, 1, 38016, 0xe43d3a34 -0, 246, 246, 1, 38016, 0x57194b82 -0, 247, 247, 1, 38016, 0x68a052ed -0, 248, 248, 1, 38016, 0x5c898052 -0, 249, 249, 1, 38016, 0x7104a6ad -0, 250, 250, 1, 38016, 0x1676b5e8 -0, 251, 251, 1, 38016, 0xe1cfd375 -0, 252, 252, 1, 38016, 0x16fede04 -0, 253, 253, 1, 38016, 0xca49dd4a -0, 254, 254, 1, 38016, 0x7b98d9d1 -0, 255, 255, 1, 38016, 0x4020d210 -0, 256, 256, 1, 38016, 0x62c5d1e4 -0, 257, 257, 1, 38016, 0x756abdb4 -0, 258, 258, 1, 38016, 0x558fb00f -0, 259, 259, 1, 38016, 0x4ab0b1f1 -0, 260, 260, 1, 38016, 0x7c9fb0c2 -0, 261, 261, 1, 38016, 0xcecfbdd0 -0, 262, 262, 1, 38016, 0x70e6d174 -0, 263, 263, 1, 38016, 0x83d7ddde -0, 264, 264, 1, 38016, 0xbbcde2d9 -0, 265, 265, 1, 38016, 0xc89eeaef -0, 266, 266, 1, 38016, 0x8565e15c -0, 267, 267, 1, 38016, 0x28e0db24 -0, 268, 268, 1, 38016, 0x1d9dd334 -0, 269, 269, 1, 38016, 0xce02c452 -0, 270, 270, 1, 38016, 0xe29dbd0c -0, 271, 271, 1, 38016, 0x4aa3b638 -0, 272, 272, 1, 38016, 0x5533c135 -0, 273, 273, 1, 38016, 0x6c57b65f -0, 274, 274, 1, 38016, 0x23d3b851 -0, 275, 275, 1, 38016, 0xd8cbb960 -0, 276, 276, 1, 38016, 0x02edb916 -0, 277, 277, 1, 38016, 0xa622bd42 -0, 278, 278, 1, 38016, 0x4ba5be1c -0, 279, 279, 1, 38016, 0xe69bb625 -0, 280, 280, 1, 38016, 0xbca5b292 -0, 281, 281, 1, 38016, 0xde38b1c8 -0, 282, 282, 1, 38016, 0xe9e3b617 -0, 283, 283, 1, 38016, 0x216cc574 -0, 284, 284, 1, 38016, 0x3780c5ad -0, 285, 285, 1, 38016, 0x5531e3f9 -0, 286, 286, 1, 38016, 0xe2c5f5d4 -0, 287, 287, 1, 38016, 0x24cefc6e -0, 288, 288, 1, 38016, 0xa3ce003d -0, 289, 289, 1, 38016, 0x42d01c9e -0, 290, 290, 1, 38016, 0xbfc13689 -0, 291, 291, 1, 38016, 0x122647a9 -0, 292, 292, 1, 38016, 0xe45254da -0, 293, 293, 1, 38016, 0xad955b0c -0, 294, 294, 1, 38016, 0x4b086abb -0, 295, 295, 1, 38016, 0xd4857b8c -0, 296, 296, 1, 38016, 0xa71594ce -0, 297, 297, 1, 38016, 0x04e4a73d -0, 298, 298, 1, 38016, 0x295abf63 -0, 299, 299, 1, 38016, 0xbe4ed5dd -0, 300, 300, 1, 38016, 0x087bcf64 +0, 9, 9, 1, 38016, 0xda748c2f +0, 10, 10, 1, 38016, 0x7b4dbff0 +0, 11, 11, 1, 38016, 0xd4a1b24a +0, 12, 12, 1, 38016, 0x714cb4cc +0, 13, 13, 1, 38016, 0x2c6d80f0 +0, 14, 14, 1, 38016, 0x92266151 +0, 15, 15, 1, 38016, 0x6b766a23 +0, 16, 16, 1, 38016, 0xb24f7efe +0, 17, 17, 1, 38016, 0x8410838e +0, 18, 18, 1, 38016, 0x67fe872a +0, 19, 19, 1, 38016, 0x55b49d36 +0, 20, 20, 1, 38016, 0x7a1c9c41 +0, 21, 21, 1, 38016, 0xb4818e0e +0, 22, 22, 1, 38016, 0x25f6683c +0, 23, 23, 1, 38016, 0xe4d141a4 +0, 24, 24, 1, 38016, 0x808216ad +0, 25, 25, 1, 38016, 0x2acf0baf +0, 26, 26, 1, 38016, 0xf3de13c4 +0, 27, 27, 1, 38016, 0x5f412187 +0, 28, 28, 1, 38016, 0xb31a340a +0, 29, 29, 1, 38016, 0x019d42d1 +0, 30, 30, 1, 38016, 0xeeb94b9b +0, 31, 31, 1, 38016, 0xef55472e +0, 32, 32, 1, 38016, 0xdb5e3697 +0, 33, 33, 1, 38016, 0x8565303e +0, 34, 34, 1, 38016, 0x5f9c2c1b +0, 35, 35, 1, 38016, 0xeb3d27f4 +0, 36, 36, 1, 38016, 0x9a43282d +0, 37, 37, 1, 38016, 0xe04720c6 +0, 38, 38, 1, 38016, 0x19cc0eba +0, 39, 39, 1, 38016, 0x218efeb6 +0, 40, 40, 1, 38016, 0x7733f491 +0, 41, 41, 1, 38016, 0x7f3bede9 +0, 42, 42, 1, 38016, 0x49c5ec0d +0, 43, 43, 1, 38016, 0x803cf19e +0, 44, 44, 1, 38016, 0x31de0d3f +0, 45, 45, 1, 38016, 0xa7e30426 +0, 46, 46, 1, 38016, 0xba37f068 +0, 47, 47, 1, 38016, 0x2842bdf8 +0, 48, 48, 1, 38016, 0x76df97dc +0, 49, 49, 1, 38016, 0xf3246d26 +0, 50, 50, 1, 38016, 0x0a384d72 +0, 51, 51, 1, 38016, 0x40964f41 +0, 52, 52, 1, 38016, 0x46364324 +0, 53, 53, 1, 38016, 0x7cbf3db4 +0, 54, 54, 1, 38016, 0x7a223bec +0, 55, 55, 1, 38016, 0x458651c1 +0, 56, 56, 1, 38016, 0xb82d7e3c +0, 57, 57, 1, 38016, 0x0f50a55d +0, 58, 58, 1, 38016, 0xc306cae4 +0, 59, 59, 1, 38016, 0x9d6ddfcb +0, 60, 60, 1, 38016, 0xb602e8e9 +0, 61, 61, 1, 38016, 0xbf0ae386 +0, 62, 62, 1, 38016, 0x0a8bd46e +0, 63, 63, 1, 38016, 0xd437c5c1 +0, 64, 64, 1, 38016, 0xd61d9959 +0, 65, 65, 1, 38016, 0x70639b56 +0, 66, 66, 1, 38016, 0x36fd407b +0, 67, 67, 1, 38016, 0x58ce3ddd +0, 68, 68, 1, 38016, 0x86cc1d8c +0, 69, 69, 1, 38016, 0xee422dc2 +0, 70, 70, 1, 38016, 0xab475639 +0, 71, 71, 1, 38016, 0xc1327ad8 +0, 72, 72, 1, 38016, 0x63d196d4 +0, 73, 73, 1, 38016, 0x1aba8ebd +0, 74, 74, 1, 38016, 0x74a269ac +0, 75, 75, 1, 38016, 0x267f3563 +0, 76, 76, 1, 38016, 0xa18ff180 +0, 77, 77, 1, 38016, 0x70c9c9fd +0, 78, 78, 1, 38016, 0xa6c59f9c +0, 79, 79, 1, 38016, 0xd7cd8927 +0, 80, 80, 1, 38016, 0xd30b7345 +0, 81, 81, 1, 38016, 0x679a4dda +0, 82, 82, 1, 38016, 0xeb0562de +0, 83, 83, 1, 38016, 0xdd7d6cdb +0, 84, 84, 1, 38016, 0xd6e26b73 +0, 85, 85, 1, 38016, 0xa65a860f +0, 86, 86, 1, 38016, 0xae95c71e +0, 87, 87, 1, 38016, 0x1a89ca86 +0, 88, 88, 1, 38016, 0xa33ecee6 +0, 89, 89, 1, 38016, 0x821da6cb +0, 90, 90, 1, 38016, 0xf0e1612f +0, 91, 91, 1, 38016, 0x67b8516b +0, 92, 92, 1, 38016, 0x62f965bc +0, 93, 93, 1, 38016, 0xd1917aa6 +0, 94, 94, 1, 38016, 0xe72db54d +0, 95, 95, 1, 38016, 0x9b64e721 +0, 96, 96, 1, 38016, 0xa819efda +0, 97, 97, 1, 38016, 0xeacfdacb +0, 98, 98, 1, 38016, 0x52f235e1 +0, 99, 99, 1, 38016, 0x2b512cb8 +0, 100, 100, 1, 38016, 0xaac73fb3 +0, 101, 101, 1, 38016, 0x7d2d504f +0, 102, 102, 1, 38016, 0x396d503a +0, 103, 103, 1, 38016, 0x97905235 +0, 104, 104, 1, 38016, 0xf0056693 +0, 105, 105, 1, 38016, 0x728a6a9e +0, 106, 106, 1, 38016, 0x0eed7824 +0, 107, 107, 1, 38016, 0x59506237 +0, 108, 108, 1, 38016, 0xd4304c93 +0, 109, 109, 1, 38016, 0x7e663ee8 +0, 110, 110, 1, 38016, 0x0ebc2d11 +0, 111, 111, 1, 38016, 0x52db2112 +0, 112, 112, 1, 38016, 0x74aa1815 +0, 113, 113, 1, 38016, 0x57a60dc6 +0, 114, 114, 1, 38016, 0x86e9fa32 +0, 115, 115, 1, 38016, 0x67e8ff09 +0, 116, 116, 1, 38016, 0x26e8f7ea +0, 117, 117, 1, 38016, 0x183dff56 +0, 118, 118, 1, 38016, 0xa470af8d +0, 119, 119, 1, 38016, 0xe017d594 +0, 120, 120, 1, 38016, 0xb899d48b +0, 121, 121, 1, 38016, 0x0d3bc5f7 +0, 122, 122, 1, 38016, 0xd68bbb0d +0, 123, 123, 1, 38016, 0x8bf5b4cb +0, 124, 124, 1, 38016, 0x6bfcaa47 +0, 125, 125, 1, 38016, 0x29a9b01b +0, 126, 126, 1, 38016, 0xcdedbdb7 +0, 127, 127, 1, 38016, 0xdb5ad9c3 +0, 128, 128, 1, 38016, 0x468aeef6 +0, 129, 129, 1, 38016, 0xdc2b143e +0, 130, 130, 1, 38016, 0x6776277c +0, 131, 131, 1, 38016, 0xb78d5294 +0, 132, 132, 1, 38016, 0x1dfb63ab +0, 133, 133, 1, 38016, 0xbd1f99bc +0, 134, 134, 1, 38016, 0xde16b89a +0, 135, 135, 1, 38016, 0xbf46edca +0, 136, 136, 1, 38016, 0x6306e8c4 +0, 137, 137, 1, 38016, 0x7b09d224 +0, 138, 138, 1, 38016, 0xfea1aff6 +0, 139, 139, 1, 38016, 0x183686b0 +0, 140, 140, 1, 38016, 0x665a61ff +0, 141, 141, 1, 38016, 0xc8af42d1 +0, 142, 142, 1, 38016, 0xe2326bc1 +0, 143, 143, 1, 38016, 0x56dbde82 +0, 144, 144, 1, 38016, 0xa0254f97 +0, 145, 145, 1, 38016, 0x3b74a0b4 +0, 146, 146, 1, 38016, 0x9aee9b7f +0, 147, 147, 1, 38016, 0xd94b6133 +0, 148, 148, 1, 38016, 0x5819f795 +0, 149, 149, 1, 38016, 0xc45a8c02 +0, 150, 150, 1, 38016, 0x2f9204a0 +0, 151, 151, 1, 38016, 0xbe09e051 +0, 152, 152, 1, 38016, 0xb542badd +0, 153, 153, 1, 38016, 0x23bd9e00 +0, 154, 154, 1, 38016, 0x4f338d3d +0, 155, 155, 1, 38016, 0x8c91e8f3 +0, 156, 156, 1, 38016, 0xa7347d57 +0, 157, 157, 1, 38016, 0x6d91de4d +0, 158, 158, 1, 38016, 0x3443d936 +0, 159, 159, 1, 38016, 0x9d25b4e2 +0, 160, 160, 1, 38016, 0xd93cd4b3 +0, 161, 161, 1, 38016, 0xa1c9e9a0 +0, 162, 162, 1, 38016, 0x1482f220 +0, 163, 163, 1, 38016, 0x1295f270 +0, 164, 164, 1, 38016, 0x399ae9da +0, 165, 165, 1, 38016, 0x85dcdf28 +0, 166, 166, 1, 38016, 0x4207b9e5 +0, 167, 167, 1, 38016, 0xad1c9d75 +0, 168, 168, 1, 38016, 0x4a266c14 +0, 169, 169, 1, 38016, 0x3afc4508 +0, 170, 170, 1, 38016, 0x2b1b2385 +0, 171, 171, 1, 38016, 0x738f005f +0, 172, 172, 1, 38016, 0xfec3d833 +0, 173, 173, 1, 38016, 0x3f7f6ae9 +0, 174, 174, 1, 38016, 0xd8551823 +0, 175, 175, 1, 38016, 0x6df03570 +0, 176, 176, 1, 38016, 0x767c3054 +0, 177, 177, 1, 38016, 0x89bd342c +0, 178, 178, 1, 38016, 0x77ba806c +0, 179, 179, 1, 38016, 0x1c98005c +0, 180, 180, 1, 38016, 0xa13ce2a3 +0, 181, 181, 1, 38016, 0x1be59915 +0, 182, 182, 1, 38016, 0x279c6027 +0, 183, 183, 1, 38016, 0x96ac11a2 +0, 184, 184, 1, 38016, 0x3ae95131 +0, 185, 185, 1, 38016, 0xae19f7fe +0, 186, 186, 1, 38016, 0xcde4efe6 +0, 187, 187, 1, 38016, 0x5ecc3f7a +0, 188, 188, 1, 38016, 0x79645152 +0, 189, 189, 1, 38016, 0x1ee2e89f +0, 190, 190, 1, 38016, 0x91d34bb4 +0, 191, 191, 1, 38016, 0xf019d464 +0, 192, 192, 1, 38016, 0x8eb07205 +0, 193, 193, 1, 38016, 0x5399bb5b +0, 194, 194, 1, 38016, 0x61f0c77a +0, 195, 195, 1, 38016, 0xb2bd8726 +0, 196, 196, 1, 38016, 0x47b89243 +0, 197, 197, 1, 38016, 0xebfe4d76 +0, 198, 198, 1, 38016, 0xe8f87d91 +0, 199, 199, 1, 38016, 0x5e9fb239 +0, 200, 200, 1, 38016, 0x357ca1f8 +0, 201, 201, 1, 38016, 0x757d2e02 +0, 202, 202, 1, 38016, 0x40672e7c +0, 203, 203, 1, 38016, 0xd966abca +0, 204, 204, 1, 38016, 0xe98d0d47 +0, 205, 205, 1, 38016, 0x341babf5 +0, 206, 206, 1, 38016, 0xd12d5a0c +0, 207, 207, 1, 38016, 0xea2f99ab +0, 208, 208, 1, 38016, 0x14bce88e +0, 209, 209, 1, 38016, 0xe4bda9e8 +0, 210, 210, 1, 38016, 0x2c57ec89 +0, 211, 211, 1, 38016, 0x28bbb83e +0, 212, 212, 1, 38016, 0xf8444b54 +0, 213, 213, 1, 38016, 0x3aba03cd +0, 214, 214, 1, 38016, 0x373daa20 +0, 215, 215, 1, 38016, 0x69586597 +0, 216, 216, 1, 38016, 0xc0c70d53 +0, 217, 217, 1, 38016, 0x76a5df5a +0, 218, 218, 1, 38016, 0x1afde8f0 +0, 219, 219, 1, 38016, 0x9638285a +0, 220, 220, 1, 38016, 0x9f0686c0 +0, 221, 221, 1, 38016, 0xc65b2238 +0, 222, 222, 1, 38016, 0x0d61b610 +0, 223, 223, 1, 38016, 0x78e14e1f +0, 224, 224, 1, 38016, 0xcf80ac4a +0, 225, 225, 1, 38016, 0xe094083d +0, 226, 226, 1, 38016, 0xee5e612e +0, 227, 227, 1, 38016, 0x51cdad9d +0, 228, 228, 1, 38016, 0xae41100e +0, 229, 229, 1, 38016, 0x77558f58 +0, 230, 230, 1, 38016, 0xb9503b95 +0, 231, 231, 1, 38016, 0xb71dffeb +0, 232, 232, 1, 38016, 0x1872e3e6 +0, 233, 233, 1, 38016, 0x29c3d252 +0, 234, 234, 1, 38016, 0x1c77c6ec +0, 235, 235, 1, 38016, 0x26feb194 +0, 236, 236, 1, 38016, 0x3307c3c4 +0, 237, 237, 1, 38016, 0x8e5a8080 +0, 238, 238, 1, 38016, 0x933472f7 +0, 239, 239, 1, 38016, 0xd4768d84 +0, 240, 240, 1, 38016, 0x3324485f +0, 241, 241, 1, 38016, 0xd50af078 +0, 242, 242, 1, 38016, 0x53820752 +0, 243, 243, 1, 38016, 0xbe7f1c47 +0, 244, 244, 1, 38016, 0xe43d3a34 +0, 245, 245, 1, 38016, 0x57194b82 +0, 246, 246, 1, 38016, 0x68a052ed +0, 247, 247, 1, 38016, 0x5c898052 +0, 248, 248, 1, 38016, 0x7104a6ad +0, 249, 249, 1, 38016, 0x1676b5e8 +0, 250, 250, 1, 38016, 0xe1cfd375 +0, 251, 251, 1, 38016, 0x16fede04 +0, 252, 252, 1, 38016, 0xca49dd4a +0, 253, 253, 1, 38016, 0x7b98d9d1 +0, 254, 254, 1, 38016, 0x4020d210 +0, 255, 255, 1, 38016, 0x62c5d1e4 +0, 256, 256, 1, 38016, 0x756abdb4 +0, 257, 257, 1, 38016, 0x558fb00f +0, 258, 258, 1, 38016, 0x4ab0b1f1 +0, 259, 259, 1, 38016, 0x7c9fb0c2 +0, 260, 260, 1, 38016, 0xcecfbdd0 +0, 261, 261, 1, 38016, 0x70e6d174 +0, 262, 262, 1, 38016, 0x83d7ddde +0, 263, 263, 1, 38016, 0xbbcde2d9 +0, 264, 264, 1, 38016, 0xc89eeaef +0, 265, 265, 1, 38016, 0x8565e15c +0, 266, 266, 1, 38016, 0x28e0db24 +0, 267, 267, 1, 38016, 0x1d9dd334 +0, 268, 268, 1, 38016, 0xce02c452 +0, 269, 269, 1, 38016, 0xe29dbd0c +0, 270, 270, 1, 38016, 0x4aa3b638 +0, 271, 271, 1, 38016, 0x5533c135 +0, 272, 272, 1, 38016, 0x6c57b65f +0, 273, 273, 1, 38016, 0x23d3b851 +0, 274, 274, 1, 38016, 0xd8cbb960 +0, 275, 275, 1, 38016, 0x02edb916 +0, 276, 276, 1, 38016, 0xa622bd42 +0, 277, 277, 1, 38016, 0x4ba5be1c +0, 278, 278, 1, 38016, 0xe69bb625 +0, 279, 279, 1, 38016, 0xbca5b292 +0, 280, 280, 1, 38016, 0xde38b1c8 +0, 281, 281, 1, 38016, 0xe9e3b617 +0, 282, 282, 1, 38016, 0x216cc574 +0, 283, 283, 1, 38016, 0x3780c5ad +0, 284, 284, 1, 38016, 0x5531e3f9 +0, 285, 285, 1, 38016, 0xe2c5f5d4 +0, 286, 286, 1, 38016, 0x24cefc6e +0, 287, 287, 1, 38016, 0xa3ce003d +0, 288, 288, 1, 38016, 0x42d01c9e +0, 289, 289, 1, 38016, 0xbfc13689 +0, 290, 290, 1, 38016, 0x122647a9 +0, 291, 291, 1, 38016, 0xe45254da +0, 292, 292, 1, 38016, 0xad955b0c +0, 293, 293, 1, 38016, 0x4b086abb +0, 294, 294, 1, 38016, 0xd4857b8c +0, 295, 295, 1, 38016, 0xa71594ce +0, 296, 296, 1, 38016, 0x04e4a73d +0, 297, 297, 1, 38016, 0x295abf63 +0, 298, 298, 1, 38016, 0xbe4ed5dd +0, 299, 299, 1, 38016, 0x087bcf64 diff --git a/tests/ref/fate/h264-conformance-mr6_bt_b b/tests/ref/fate/h264-conformance-mr6_bt_b index ddfc3d98ee7..34aa8bfd463 100644 --- a/tests/ref/fate/h264-conformance-mr6_bt_b +++ b/tests/ref/fate/h264-conformance-mr6_bt_b @@ -3,63 +3,63 @@ #codec_id 0: rawvideo #dimensions 0: 192x128 #sar 0: 0/1 -0, 1, 1, 1, 36864, 0x954464be -0, 2, 2, 1, 36864, 0xace1d90b -0, 3, 3, 1, 36864, 0x8f149f03 -0, 4, 4, 1, 36864, 0xea9b21eb -0, 5, 5, 1, 36864, 0xb51d9fe3 -0, 6, 6, 1, 36864, 0x61bd11d7 -0, 7, 7, 1, 36864, 0x9d36980f -0, 8, 8, 1, 36864, 0xa4192c5e -0, 9, 9, 1, 36864, 0x11006433 -0, 10, 10, 1, 36864, 0x4a243e46 -0, 11, 11, 1, 36864, 0x1807b5e8 -0, 12, 12, 1, 36864, 0xbe37743c -0, 13, 13, 1, 36864, 0x82491319 -0, 14, 14, 1, 36864, 0x006e9914 -0, 15, 15, 1, 36864, 0xa5261884 -0, 16, 16, 1, 36864, 0x2030c9d6 -0, 17, 17, 1, 36864, 0xc80eb1ce -0, 18, 18, 1, 36864, 0x4d559791 -0, 19, 19, 1, 36864, 0xf5f900ee -0, 20, 20, 1, 36864, 0x2cc9c0d7 -0, 21, 21, 1, 36864, 0x5ba14186 -0, 22, 22, 1, 36864, 0x47a46865 -0, 23, 23, 1, 36864, 0x5ba180b7 -0, 24, 24, 1, 36864, 0xc67c4876 -0, 25, 25, 1, 36864, 0x4311d75d -0, 26, 26, 1, 36864, 0x56edb851 -0, 27, 27, 1, 36864, 0x7e5aa3e0 -0, 28, 28, 1, 36864, 0x8df8283a -0, 29, 29, 1, 36864, 0xb8583ddf -0, 30, 30, 1, 36864, 0xf33fb779 -0, 31, 31, 1, 36864, 0xe9942ddc -0, 32, 32, 1, 36864, 0x2bc5f7fa -0, 33, 33, 1, 36864, 0xc7b66c65 -0, 34, 34, 1, 36864, 0x1a524319 -0, 35, 35, 1, 36864, 0xf60c6141 -0, 36, 36, 1, 36864, 0x113f41f2 -0, 37, 37, 1, 36864, 0xad191a31 -0, 38, 38, 1, 36864, 0x3898264a -0, 39, 39, 1, 36864, 0x3c2f34a4 -0, 40, 40, 1, 36864, 0xd0fc76aa -0, 41, 41, 1, 36864, 0x2870b546 -0, 42, 42, 1, 36864, 0x7d326fb4 -0, 43, 43, 1, 36864, 0xd7ed14e1 -0, 44, 44, 1, 36864, 0x205174aa -0, 45, 45, 1, 36864, 0xa3a88be9 -0, 46, 46, 1, 36864, 0xd6f01751 -0, 47, 47, 1, 36864, 0x5420bb80 -0, 48, 48, 1, 36864, 0xe14518f9 -0, 49, 49, 1, 36864, 0x931db61e -0, 50, 50, 1, 36864, 0x052ecfae -0, 51, 51, 1, 36864, 0x29b1b0f5 -0, 52, 52, 1, 36864, 0xa3057117 -0, 53, 53, 1, 36864, 0x954464be -0, 54, 54, 1, 36864, 0xace1d90b -0, 55, 55, 1, 36864, 0x8f149f03 -0, 56, 56, 1, 36864, 0x485722c5 -0, 57, 57, 1, 36864, 0x534b18f9 -0, 58, 58, 1, 36864, 0xc893a0a6 -0, 59, 59, 1, 36864, 0x8b04e1dd -0, 60, 60, 1, 36864, 0xaf536964 +0, 0, 0, 1, 36864, 0x954464be +0, 1, 1, 1, 36864, 0xace1d90b +0, 2, 2, 1, 36864, 0x8f149f03 +0, 3, 3, 1, 36864, 0xea9b21eb +0, 4, 4, 1, 36864, 0xb51d9fe3 +0, 5, 5, 1, 36864, 0x61bd11d7 +0, 6, 6, 1, 36864, 0x9d36980f +0, 7, 7, 1, 36864, 0xa4192c5e +0, 8, 8, 1, 36864, 0x11006433 +0, 9, 9, 1, 36864, 0x4a243e46 +0, 10, 10, 1, 36864, 0x1807b5e8 +0, 11, 11, 1, 36864, 0xbe37743c +0, 12, 12, 1, 36864, 0x82491319 +0, 13, 13, 1, 36864, 0x006e9914 +0, 14, 14, 1, 36864, 0xa5261884 +0, 15, 15, 1, 36864, 0x2030c9d6 +0, 16, 16, 1, 36864, 0xc80eb1ce +0, 17, 17, 1, 36864, 0x4d559791 +0, 18, 18, 1, 36864, 0xf5f900ee +0, 19, 19, 1, 36864, 0x2cc9c0d7 +0, 20, 20, 1, 36864, 0x5ba14186 +0, 21, 21, 1, 36864, 0x47a46865 +0, 22, 22, 1, 36864, 0x5ba180b7 +0, 23, 23, 1, 36864, 0xc67c4876 +0, 24, 24, 1, 36864, 0x4311d75d +0, 25, 25, 1, 36864, 0x56edb851 +0, 26, 26, 1, 36864, 0x7e5aa3e0 +0, 27, 27, 1, 36864, 0x8df8283a +0, 28, 28, 1, 36864, 0xb8583ddf +0, 29, 29, 1, 36864, 0xf33fb779 +0, 30, 30, 1, 36864, 0xe9942ddc +0, 31, 31, 1, 36864, 0x2bc5f7fa +0, 32, 32, 1, 36864, 0xc7b66c65 +0, 33, 33, 1, 36864, 0x1a524319 +0, 34, 34, 1, 36864, 0xf60c6141 +0, 35, 35, 1, 36864, 0x113f41f2 +0, 36, 36, 1, 36864, 0xad191a31 +0, 37, 37, 1, 36864, 0x3898264a +0, 38, 38, 1, 36864, 0x3c2f34a4 +0, 39, 39, 1, 36864, 0xd0fc76aa +0, 40, 40, 1, 36864, 0x2870b546 +0, 41, 41, 1, 36864, 0x7d326fb4 +0, 42, 42, 1, 36864, 0xd7ed14e1 +0, 43, 43, 1, 36864, 0x205174aa +0, 44, 44, 1, 36864, 0xa3a88be9 +0, 45, 45, 1, 36864, 0xd6f01751 +0, 46, 46, 1, 36864, 0x5420bb80 +0, 47, 47, 1, 36864, 0xe14518f9 +0, 48, 48, 1, 36864, 0x931db61e +0, 49, 49, 1, 36864, 0x052ecfae +0, 50, 50, 1, 36864, 0x29b1b0f5 +0, 51, 51, 1, 36864, 0xa3057117 +0, 52, 52, 1, 36864, 0x954464be +0, 53, 53, 1, 36864, 0xace1d90b +0, 54, 54, 1, 36864, 0x8f149f03 +0, 55, 55, 1, 36864, 0x485722c5 +0, 56, 56, 1, 36864, 0x534b18f9 +0, 57, 57, 1, 36864, 0xc893a0a6 +0, 58, 58, 1, 36864, 0x8b04e1dd +0, 59, 59, 1, 36864, 0xaf536964 diff --git a/tests/ref/fate/h264-conformance-mr7_bt_b b/tests/ref/fate/h264-conformance-mr7_bt_b index becd797c8fe..551767ce1da 100644 --- a/tests/ref/fate/h264-conformance-mr7_bt_b +++ b/tests/ref/fate/h264-conformance-mr7_bt_b @@ -13,53 +13,53 @@ 0, 7, 7, 1, 36864, 0xf2f324dd 0, 8, 8, 1, 36864, 0x592b5a01 0, 9, 9, 1, 36864, 0x4c2f2d91 -0, 11, 11, 1, 36864, 0x8baeb610 -0, 12, 12, 1, 36864, 0x86d47617 -0, 13, 13, 1, 36864, 0xf11011cc -0, 14, 14, 1, 36864, 0xe56a9daa -0, 15, 15, 1, 36864, 0xd57119d6 -0, 16, 16, 1, 36864, 0xe28fcde7 -0, 17, 17, 1, 36864, 0x9aeeba86 -0, 18, 18, 1, 36864, 0xa518a7c5 -0, 19, 19, 1, 36864, 0x9af410be -0, 20, 20, 1, 36864, 0x1fedd12f -0, 21, 21, 1, 36864, 0xa8032e03 -0, 22, 22, 1, 36864, 0x579e6274 -0, 23, 23, 1, 36864, 0x99846ef6 -0, 24, 24, 1, 36864, 0xb5ad3ca7 -0, 25, 25, 1, 36864, 0x7845cb90 -0, 26, 26, 1, 36864, 0x569fae24 -0, 27, 27, 1, 36864, 0x8a3c9f98 -0, 28, 28, 1, 36864, 0x0b7722af -0, 29, 29, 1, 36864, 0x699c2dd8 -0, 30, 30, 1, 36864, 0xd477af13 -0, 31, 31, 1, 36864, 0x17b62d7c -0, 32, 32, 1, 36864, 0xb1ecf6a7 -0, 33, 33, 1, 36864, 0xf9c17e4c -0, 34, 34, 1, 36864, 0xe7c44618 -0, 35, 35, 1, 36864, 0x7e23654e -0, 36, 36, 1, 36864, 0xd8a0457c -0, 37, 37, 1, 36864, 0x57e11df1 -0, 38, 38, 1, 36864, 0xd54d2a43 -0, 39, 39, 1, 36864, 0xc6f03950 -0, 40, 40, 1, 36864, 0x687e750e -0, 41, 41, 1, 36864, 0x2870b546 -0, 42, 42, 1, 36864, 0xda0370d0 -0, 43, 43, 1, 36864, 0x5a2e0bff -0, 44, 44, 1, 36864, 0xe1f07533 -0, 45, 45, 1, 36864, 0x3de892b9 -0, 46, 46, 1, 36864, 0xe5c31505 -0, 47, 47, 1, 36864, 0x96b8c082 -0, 48, 48, 1, 36864, 0x55391423 -0, 49, 49, 1, 36864, 0xc285bd71 -0, 50, 50, 1, 36864, 0xf702d9f3 -0, 51, 51, 1, 36864, 0x7afbadf8 -0, 52, 52, 1, 36864, 0xd9b568f7 -0, 53, 53, 1, 36864, 0x579e6274 -0, 54, 54, 1, 36864, 0x8650c61c -0, 55, 55, 1, 36864, 0xbc359647 -0, 56, 56, 1, 36864, 0x5522328c -0, 57, 57, 1, 36864, 0x02821fd6 -0, 58, 58, 1, 36864, 0xb4ee9562 -0, 59, 59, 1, 36864, 0xcefedb68 -0, 60, 60, 1, 36864, 0xd959782e +0, 10, 10, 1, 36864, 0x8baeb610 +0, 11, 11, 1, 36864, 0x86d47617 +0, 12, 12, 1, 36864, 0xf11011cc +0, 13, 13, 1, 36864, 0xe56a9daa +0, 14, 14, 1, 36864, 0xd57119d6 +0, 15, 15, 1, 36864, 0xe28fcde7 +0, 16, 16, 1, 36864, 0x9aeeba86 +0, 17, 17, 1, 36864, 0xa518a7c5 +0, 18, 18, 1, 36864, 0x9af410be +0, 19, 19, 1, 36864, 0x1fedd12f +0, 20, 20, 1, 36864, 0xa8032e03 +0, 21, 21, 1, 36864, 0x579e6274 +0, 22, 22, 1, 36864, 0x99846ef6 +0, 23, 23, 1, 36864, 0xb5ad3ca7 +0, 24, 24, 1, 36864, 0x7845cb90 +0, 25, 25, 1, 36864, 0x569fae24 +0, 26, 26, 1, 36864, 0x8a3c9f98 +0, 27, 27, 1, 36864, 0x0b7722af +0, 28, 28, 1, 36864, 0x699c2dd8 +0, 29, 29, 1, 36864, 0xd477af13 +0, 30, 30, 1, 36864, 0x17b62d7c +0, 31, 31, 1, 36864, 0xb1ecf6a7 +0, 32, 32, 1, 36864, 0xf9c17e4c +0, 33, 33, 1, 36864, 0xe7c44618 +0, 34, 34, 1, 36864, 0x7e23654e +0, 35, 35, 1, 36864, 0xd8a0457c +0, 36, 36, 1, 36864, 0x57e11df1 +0, 37, 37, 1, 36864, 0xd54d2a43 +0, 38, 38, 1, 36864, 0xc6f03950 +0, 39, 39, 1, 36864, 0x687e750e +0, 40, 40, 1, 36864, 0x2870b546 +0, 41, 41, 1, 36864, 0xda0370d0 +0, 42, 42, 1, 36864, 0x5a2e0bff +0, 43, 43, 1, 36864, 0xe1f07533 +0, 44, 44, 1, 36864, 0x3de892b9 +0, 45, 45, 1, 36864, 0xe5c31505 +0, 46, 46, 1, 36864, 0x96b8c082 +0, 47, 47, 1, 36864, 0x55391423 +0, 48, 48, 1, 36864, 0xc285bd71 +0, 49, 49, 1, 36864, 0xf702d9f3 +0, 50, 50, 1, 36864, 0x7afbadf8 +0, 51, 51, 1, 36864, 0xd9b568f7 +0, 52, 52, 1, 36864, 0x579e6274 +0, 53, 53, 1, 36864, 0x8650c61c +0, 54, 54, 1, 36864, 0xbc359647 +0, 55, 55, 1, 36864, 0x5522328c +0, 56, 56, 1, 36864, 0x02821fd6 +0, 57, 57, 1, 36864, 0xb4ee9562 +0, 58, 58, 1, 36864, 0xcefedb68 +0, 59, 59, 1, 36864, 0xd959782e diff --git a/tests/ref/fate/h264-conformance-mr8_bt_b b/tests/ref/fate/h264-conformance-mr8_bt_b index 40373e6985b..7981c422459 100644 --- a/tests/ref/fate/h264-conformance-mr8_bt_b +++ b/tests/ref/fate/h264-conformance-mr8_bt_b @@ -3,61 +3,61 @@ #codec_id 0: rawvideo #dimensions 0: 192x128 #sar 0: 0/1 -0, 1, 1, 1, 36864, 0x36df68f4 -0, 2, 2, 1, 36864, 0x52d4c6d9 -0, 3, 3, 1, 36864, 0xad16b0be -0, 4, 4, 1, 36864, 0xf8c72556 -0, 5, 5, 1, 36864, 0x70aaad30 -0, 6, 6, 1, 36864, 0x53cffd5e -0, 7, 7, 1, 36864, 0xb3fa8abc -0, 8, 8, 1, 36864, 0x9c894009 -0, 9, 9, 1, 36864, 0xfbc08050 -0, 10, 10, 1, 36864, 0x9d5b2d65 -0, 11, 11, 1, 36864, 0x3bd8bb5d -0, 12, 12, 1, 36864, 0x8d976ecf -0, 13, 13, 1, 36864, 0x25010368 -0, 14, 14, 1, 36864, 0xb6e6a11c -0, 15, 15, 1, 36864, 0x595a3967 -0, 16, 16, 1, 36864, 0x4fbcb9a8 -0, 17, 17, 1, 36864, 0xc7c5c16b -0, 18, 18, 1, 36864, 0x661ae1eb -0, 19, 19, 1, 36864, 0x169f04a7 -0, 20, 20, 1, 36864, 0xd124c93a -0, 21, 21, 1, 36864, 0x3f642dba -0, 22, 22, 1, 36864, 0xe7ad6956 -0, 23, 23, 1, 36864, 0x47dc76d3 -0, 24, 24, 1, 36864, 0x496a3917 -0, 25, 25, 1, 36864, 0xa976d5f3 -0, 26, 26, 1, 36864, 0x507bb685 -0, 27, 27, 1, 36864, 0x2f61ac12 -0, 28, 28, 1, 36864, 0x527818d8 -0, 29, 29, 1, 36864, 0xa4983396 -0, 30, 30, 1, 36864, 0x3ec9b07b -0, 31, 31, 1, 36864, 0x7db52d99 -0, 32, 32, 1, 36864, 0xe974fd00 -0, 33, 33, 1, 36864, 0x9c677a4f -0, 34, 34, 1, 36864, 0x108f3a05 -0, 35, 35, 1, 36864, 0x23a56ba2 -0, 36, 36, 1, 36864, 0x4c8d47e8 -0, 37, 37, 1, 36864, 0x9e0b0f09 -0, 38, 38, 1, 36864, 0x4d262b16 -0, 39, 39, 1, 36864, 0x6122402e -0, 40, 40, 1, 36864, 0xed037036 -0, 41, 41, 1, 36864, 0x62b3ba08 -0, 42, 42, 1, 36864, 0x7f876930 -0, 43, 43, 1, 36864, 0x4a6c0983 -0, 44, 44, 1, 36864, 0xf9787086 -0, 45, 45, 1, 36864, 0x01d1b1b5 -0, 46, 46, 1, 36864, 0xc1622655 -0, 47, 47, 1, 36864, 0x27e8e0f7 -0, 48, 48, 1, 36864, 0xc1622655 -0, 49, 49, 1, 36864, 0x12c2b7e9 -0, 50, 50, 1, 36864, 0xd752d2ef -0, 51, 51, 1, 36864, 0xcbb1c3a7 -0, 52, 52, 1, 36864, 0x18c56fba -0, 53, 53, 1, 36864, 0xb1b3771c -0, 54, 54, 1, 36864, 0x284ef3c4 -0, 55, 55, 1, 36864, 0xda6eb5a0 -0, 56, 56, 1, 36864, 0x17ad337c -0, 57, 57, 1, 36864, 0xe2801e4f -0, 58, 58, 1, 36864, 0x6c33bd17 +0, 0, 0, 1, 36864, 0x36df68f4 +0, 1, 1, 1, 36864, 0x52d4c6d9 +0, 2, 2, 1, 36864, 0xad16b0be +0, 3, 3, 1, 36864, 0xf8c72556 +0, 4, 4, 1, 36864, 0x70aaad30 +0, 5, 5, 1, 36864, 0x53cffd5e +0, 6, 6, 1, 36864, 0xb3fa8abc +0, 7, 7, 1, 36864, 0x9c894009 +0, 8, 8, 1, 36864, 0xfbc08050 +0, 9, 9, 1, 36864, 0x9d5b2d65 +0, 10, 10, 1, 36864, 0x3bd8bb5d +0, 11, 11, 1, 36864, 0x8d976ecf +0, 12, 12, 1, 36864, 0x25010368 +0, 13, 13, 1, 36864, 0xb6e6a11c +0, 14, 14, 1, 36864, 0x595a3967 +0, 15, 15, 1, 36864, 0x4fbcb9a8 +0, 16, 16, 1, 36864, 0xc7c5c16b +0, 17, 17, 1, 36864, 0x661ae1eb +0, 18, 18, 1, 36864, 0x169f04a7 +0, 19, 19, 1, 36864, 0xd124c93a +0, 20, 20, 1, 36864, 0x3f642dba +0, 21, 21, 1, 36864, 0xe7ad6956 +0, 22, 22, 1, 36864, 0x47dc76d3 +0, 23, 23, 1, 36864, 0x496a3917 +0, 24, 24, 1, 36864, 0xa976d5f3 +0, 25, 25, 1, 36864, 0x507bb685 +0, 26, 26, 1, 36864, 0x2f61ac12 +0, 27, 27, 1, 36864, 0x527818d8 +0, 28, 28, 1, 36864, 0xa4983396 +0, 29, 29, 1, 36864, 0x3ec9b07b +0, 30, 30, 1, 36864, 0x7db52d99 +0, 31, 31, 1, 36864, 0xe974fd00 +0, 32, 32, 1, 36864, 0x9c677a4f +0, 33, 33, 1, 36864, 0x108f3a05 +0, 34, 34, 1, 36864, 0x23a56ba2 +0, 35, 35, 1, 36864, 0x4c8d47e8 +0, 36, 36, 1, 36864, 0x9e0b0f09 +0, 37, 37, 1, 36864, 0x4d262b16 +0, 38, 38, 1, 36864, 0x6122402e +0, 39, 39, 1, 36864, 0xed037036 +0, 40, 40, 1, 36864, 0x62b3ba08 +0, 41, 41, 1, 36864, 0x7f876930 +0, 42, 42, 1, 36864, 0x4a6c0983 +0, 43, 43, 1, 36864, 0xf9787086 +0, 44, 44, 1, 36864, 0x01d1b1b5 +0, 45, 45, 1, 36864, 0xc1622655 +0, 46, 46, 1, 36864, 0x27e8e0f7 +0, 47, 47, 1, 36864, 0xc1622655 +0, 48, 48, 1, 36864, 0x12c2b7e9 +0, 49, 49, 1, 36864, 0xd752d2ef +0, 50, 50, 1, 36864, 0xcbb1c3a7 +0, 51, 51, 1, 36864, 0x18c56fba +0, 52, 52, 1, 36864, 0xb1b3771c +0, 53, 53, 1, 36864, 0x284ef3c4 +0, 54, 54, 1, 36864, 0xda6eb5a0 +0, 55, 55, 1, 36864, 0x17ad337c +0, 56, 56, 1, 36864, 0xe2801e4f +0, 57, 57, 1, 36864, 0x6c33bd17 diff --git a/tests/ref/fate/h264-conformance-mr9_bt_b b/tests/ref/fate/h264-conformance-mr9_bt_b index 99dd0dc3228..bbd90e67f94 100644 --- a/tests/ref/fate/h264-conformance-mr9_bt_b +++ b/tests/ref/fate/h264-conformance-mr9_bt_b @@ -13,51 +13,51 @@ 0, 7, 7, 1, 36864, 0x75122807 0, 8, 8, 1, 36864, 0x27036a2b 0, 9, 9, 1, 36864, 0x00072654 -0, 11, 11, 1, 36864, 0x49fab4fd -0, 12, 12, 1, 36864, 0x975a7545 -0, 13, 13, 1, 36864, 0x9b080a2f -0, 14, 14, 1, 36864, 0x78db960e -0, 15, 15, 1, 36864, 0xd7a928d4 -0, 16, 16, 1, 36864, 0x0a83ba1b -0, 17, 17, 1, 36864, 0xad6bb30c -0, 18, 18, 1, 36864, 0xf6addb0d -0, 19, 19, 1, 36864, 0x00540a0a -0, 20, 20, 1, 36864, 0x049cc748 -0, 21, 21, 1, 36864, 0x5b1e2291 -0, 22, 22, 1, 36864, 0x2367706e -0, 23, 23, 1, 36864, 0x88ef6b11 -0, 24, 24, 1, 36864, 0x85b73230 -0, 25, 25, 1, 36864, 0xe46cd522 -0, 26, 26, 1, 36864, 0x98489c05 -0, 27, 27, 1, 36864, 0x7e439564 -0, 28, 28, 1, 36864, 0x71330799 -0, 29, 29, 1, 36864, 0x81a6239e -0, 30, 30, 1, 36864, 0x8005a302 -0, 31, 31, 1, 36864, 0xdf132e3f -0, 32, 32, 1, 36864, 0x2a1d00de -0, 33, 33, 1, 36864, 0x7bb57e14 -0, 34, 34, 1, 36864, 0xf2a637cf -0, 35, 35, 1, 36864, 0xae6f6916 -0, 36, 36, 1, 36864, 0x2f1d4763 -0, 37, 37, 1, 36864, 0xa4e1145e -0, 38, 38, 1, 36864, 0xc1644392 -0, 39, 39, 1, 36864, 0x21853537 -0, 40, 40, 1, 36864, 0x0bc45bac -0, 41, 41, 1, 36864, 0x84ccb8ee -0, 42, 42, 1, 36864, 0x65de651c -0, 43, 43, 1, 36864, 0x33ff027e -0, 44, 44, 1, 36864, 0xefe47056 -0, 45, 45, 1, 36864, 0x8952b47c -0, 46, 46, 1, 36864, 0x78730fcf -0, 47, 47, 1, 36864, 0x14bae79f -0, 48, 48, 1, 36864, 0x53230fbe -0, 49, 49, 1, 36864, 0x15b0b245 -0, 50, 50, 1, 36864, 0x45fbd155 -0, 51, 51, 1, 36864, 0x41cfbac4 -0, 52, 52, 1, 36864, 0x0d635d61 -0, 53, 53, 1, 36864, 0x55aa8d3c -0, 54, 54, 1, 36864, 0x8f02fbaf -0, 55, 55, 1, 36864, 0xb17fac3f -0, 56, 56, 1, 36864, 0xc12627f9 -0, 57, 57, 1, 36864, 0xa5971e4a -0, 58, 58, 1, 36864, 0x3677abfe +0, 10, 10, 1, 36864, 0x49fab4fd +0, 11, 11, 1, 36864, 0x975a7545 +0, 12, 12, 1, 36864, 0x9b080a2f +0, 13, 13, 1, 36864, 0x78db960e +0, 14, 14, 1, 36864, 0xd7a928d4 +0, 15, 15, 1, 36864, 0x0a83ba1b +0, 16, 16, 1, 36864, 0xad6bb30c +0, 17, 17, 1, 36864, 0xf6addb0d +0, 18, 18, 1, 36864, 0x00540a0a +0, 19, 19, 1, 36864, 0x049cc748 +0, 20, 20, 1, 36864, 0x5b1e2291 +0, 21, 21, 1, 36864, 0x2367706e +0, 22, 22, 1, 36864, 0x88ef6b11 +0, 23, 23, 1, 36864, 0x85b73230 +0, 24, 24, 1, 36864, 0xe46cd522 +0, 25, 25, 1, 36864, 0x98489c05 +0, 26, 26, 1, 36864, 0x7e439564 +0, 27, 27, 1, 36864, 0x71330799 +0, 28, 28, 1, 36864, 0x81a6239e +0, 29, 29, 1, 36864, 0x8005a302 +0, 30, 30, 1, 36864, 0xdf132e3f +0, 31, 31, 1, 36864, 0x2a1d00de +0, 32, 32, 1, 36864, 0x7bb57e14 +0, 33, 33, 1, 36864, 0xf2a637cf +0, 34, 34, 1, 36864, 0xae6f6916 +0, 35, 35, 1, 36864, 0x2f1d4763 +0, 36, 36, 1, 36864, 0xa4e1145e +0, 37, 37, 1, 36864, 0xc1644392 +0, 38, 38, 1, 36864, 0x21853537 +0, 39, 39, 1, 36864, 0x0bc45bac +0, 40, 40, 1, 36864, 0x84ccb8ee +0, 41, 41, 1, 36864, 0x65de651c +0, 42, 42, 1, 36864, 0x33ff027e +0, 43, 43, 1, 36864, 0xefe47056 +0, 44, 44, 1, 36864, 0x8952b47c +0, 45, 45, 1, 36864, 0x78730fcf +0, 46, 46, 1, 36864, 0x14bae79f +0, 47, 47, 1, 36864, 0x53230fbe +0, 48, 48, 1, 36864, 0x15b0b245 +0, 49, 49, 1, 36864, 0x45fbd155 +0, 50, 50, 1, 36864, 0x41cfbac4 +0, 51, 51, 1, 36864, 0x0d635d61 +0, 52, 52, 1, 36864, 0x55aa8d3c +0, 53, 53, 1, 36864, 0x8f02fbaf +0, 54, 54, 1, 36864, 0xb17fac3f +0, 55, 55, 1, 36864, 0xc12627f9 +0, 56, 56, 1, 36864, 0xa5971e4a +0, 57, 57, 1, 36864, 0x3677abfe diff --git a/tests/ref/fate/h264-conformance-sharp_mp_field_1_b b/tests/ref/fate/h264-conformance-sharp_mp_field_1_b index 688cd2a391b..cdabcceca6d 100644 --- a/tests/ref/fate/h264-conformance-sharp_mp_field_1_b +++ b/tests/ref/fate/h264-conformance-sharp_mp_field_1_b @@ -3,18 +3,18 @@ #codec_id 0: rawvideo #dimensions 0: 720x480 #sar 0: 0/1 -0, 1, 1, 1, 518400, 0xc93c7c47 -0, 2, 2, 1, 518400, 0xa3f2e502 -0, 3, 3, 1, 518400, 0xb98920a4 -0, 4, 4, 1, 518400, 0xad098ec1 -0, 5, 5, 1, 518400, 0x3009b7aa -0, 6, 6, 1, 518400, 0xcf514018 -0, 7, 7, 1, 518400, 0xd869038d -0, 8, 8, 1, 518400, 0x3ce5e188 -0, 9, 9, 1, 518400, 0x029b4c14 -0, 10, 10, 1, 518400, 0xd2224afc -0, 11, 11, 1, 518400, 0xbbca027c -0, 12, 12, 1, 518400, 0x1f3fa0ac -0, 13, 13, 1, 518400, 0x823b0125 -0, 14, 14, 1, 518400, 0xaaa27cfb -0, 15, 15, 1, 518400, 0x5e926a4a +0, 0, 0, 1, 518400, 0xc93c7c47 +0, 1, 1, 1, 518400, 0xa3f2e502 +0, 2, 2, 1, 518400, 0xb98920a4 +0, 3, 3, 1, 518400, 0xad098ec1 +0, 4, 4, 1, 518400, 0x3009b7aa +0, 5, 5, 1, 518400, 0xcf514018 +0, 6, 6, 1, 518400, 0xd869038d +0, 7, 7, 1, 518400, 0x3ce5e188 +0, 8, 8, 1, 518400, 0x029b4c14 +0, 9, 9, 1, 518400, 0xd2224afc +0, 10, 10, 1, 518400, 0xbbca027c +0, 11, 11, 1, 518400, 0x1f3fa0ac +0, 12, 12, 1, 518400, 0x823b0125 +0, 13, 13, 1, 518400, 0xaaa27cfb +0, 14, 14, 1, 518400, 0x5e926a4a diff --git a/tests/ref/fate/h264-conformance-sharp_mp_field_2_b b/tests/ref/fate/h264-conformance-sharp_mp_field_2_b index aa21e014653..0574f8ff87b 100644 --- a/tests/ref/fate/h264-conformance-sharp_mp_field_2_b +++ b/tests/ref/fate/h264-conformance-sharp_mp_field_2_b @@ -3,18 +3,18 @@ #codec_id 0: rawvideo #dimensions 0: 720x480 #sar 0: 0/1 -0, 1, 1, 1, 518400, 0xc93c7c47 -0, 2, 2, 1, 518400, 0xf0c4b44a -0, 3, 3, 1, 518400, 0x3f5dc91c -0, 4, 4, 1, 518400, 0x03dc8453 -0, 5, 5, 1, 518400, 0x5e5227af -0, 6, 6, 1, 518400, 0x9e7136af -0, 7, 7, 1, 518400, 0x963a2e3a -0, 8, 8, 1, 518400, 0xa544be6c -0, 9, 9, 1, 518400, 0xefa1f63a -0, 10, 10, 1, 518400, 0x62155ff1 -0, 11, 11, 1, 518400, 0x253eb857 -0, 12, 12, 1, 518400, 0x73530327 -0, 13, 13, 1, 518400, 0x8920c9a3 -0, 14, 14, 1, 518400, 0x4bdd038c -0, 15, 15, 1, 518400, 0xea6016dd +0, 0, 0, 1, 518400, 0xc93c7c47 +0, 1, 1, 1, 518400, 0xf0c4b44a +0, 2, 2, 1, 518400, 0x3f5dc91c +0, 3, 3, 1, 518400, 0x03dc8453 +0, 4, 4, 1, 518400, 0x5e5227af +0, 5, 5, 1, 518400, 0x9e7136af +0, 6, 6, 1, 518400, 0x963a2e3a +0, 7, 7, 1, 518400, 0xa544be6c +0, 8, 8, 1, 518400, 0xefa1f63a +0, 9, 9, 1, 518400, 0x62155ff1 +0, 10, 10, 1, 518400, 0x253eb857 +0, 11, 11, 1, 518400, 0x73530327 +0, 12, 12, 1, 518400, 0x8920c9a3 +0, 13, 13, 1, 518400, 0x4bdd038c +0, 14, 14, 1, 518400, 0xea6016dd diff --git a/tests/ref/fate/h264-conformance-sharp_mp_field_3_b b/tests/ref/fate/h264-conformance-sharp_mp_field_3_b index 45792a1b213..6a92245f2f1 100644 --- a/tests/ref/fate/h264-conformance-sharp_mp_field_3_b +++ b/tests/ref/fate/h264-conformance-sharp_mp_field_3_b @@ -3,18 +3,18 @@ #codec_id 0: rawvideo #dimensions 0: 720x480 #sar 0: 0/1 -0, 1, 1, 1, 518400, 0xc93c7c47 -0, 2, 2, 1, 518400, 0x7112ac25 -0, 3, 3, 1, 518400, 0x28bc28d2 -0, 4, 4, 1, 518400, 0x6fc36875 -0, 5, 5, 1, 518400, 0x3de99be0 -0, 6, 6, 1, 518400, 0x97125499 -0, 7, 7, 1, 518400, 0xb96fca3a -0, 8, 8, 1, 518400, 0x1ec56c0f -0, 9, 9, 1, 518400, 0xc65901d0 -0, 10, 10, 1, 518400, 0x2baa1bfa -0, 11, 11, 1, 518400, 0x244fc6b7 -0, 12, 12, 1, 518400, 0xc3536383 -0, 13, 13, 1, 518400, 0xbcf40d5a -0, 14, 14, 1, 518400, 0x955f4734 -0, 15, 15, 1, 518400, 0xe1b0275e +0, 0, 0, 1, 518400, 0xc93c7c47 +0, 1, 1, 1, 518400, 0x7112ac25 +0, 2, 2, 1, 518400, 0x28bc28d2 +0, 3, 3, 1, 518400, 0x6fc36875 +0, 4, 4, 1, 518400, 0x3de99be0 +0, 5, 5, 1, 518400, 0x97125499 +0, 6, 6, 1, 518400, 0xb96fca3a +0, 7, 7, 1, 518400, 0x1ec56c0f +0, 8, 8, 1, 518400, 0xc65901d0 +0, 9, 9, 1, 518400, 0x2baa1bfa +0, 10, 10, 1, 518400, 0x244fc6b7 +0, 11, 11, 1, 518400, 0xc3536383 +0, 12, 12, 1, 518400, 0xbcf40d5a +0, 13, 13, 1, 518400, 0x955f4734 +0, 14, 14, 1, 518400, 0xe1b0275e diff --git a/tests/ref/fate/h264-conformance-sharp_mp_paff_1r2 b/tests/ref/fate/h264-conformance-sharp_mp_paff_1r2 index 35168666ccf..8a7aa249f62 100644 --- a/tests/ref/fate/h264-conformance-sharp_mp_paff_1r2 +++ b/tests/ref/fate/h264-conformance-sharp_mp_paff_1r2 @@ -5,16 +5,16 @@ #sar 0: 0/1 0, 0, 0, 1, 518400, 0xc93c7c47 0, 1, 1, 1, 518400, 0xfb452a9c -0, 3, 3, 1, 518400, 0x2f7a35bd -0, 4, 4, 1, 518400, 0xe63e30b9 -0, 5, 5, 1, 518400, 0x39628205 -0, 6, 6, 1, 518400, 0x17fa1ea4 -0, 7, 7, 1, 518400, 0xd5ee83e2 -0, 8, 8, 1, 518400, 0x611ee98d -0, 9, 9, 1, 518400, 0x07c1eeb8 -0, 10, 10, 1, 518400, 0x9dff3418 -0, 11, 11, 1, 518400, 0x87cd2f56 -0, 12, 12, 1, 518400, 0x88675628 -0, 13, 13, 1, 518400, 0x9bb8c9a0 -0, 14, 14, 1, 518400, 0xe6c1df00 -0, 15, 15, 1, 518400, 0xfcaab7a7 +0, 2, 2, 1, 518400, 0x2f7a35bd +0, 3, 3, 1, 518400, 0xe63e30b9 +0, 4, 4, 1, 518400, 0x39628205 +0, 5, 5, 1, 518400, 0x17fa1ea4 +0, 6, 6, 1, 518400, 0xd5ee83e2 +0, 7, 7, 1, 518400, 0x611ee98d +0, 8, 8, 1, 518400, 0x07c1eeb8 +0, 9, 9, 1, 518400, 0x9dff3418 +0, 10, 10, 1, 518400, 0x87cd2f56 +0, 11, 11, 1, 518400, 0x88675628 +0, 12, 12, 1, 518400, 0x9bb8c9a0 +0, 13, 13, 1, 518400, 0xe6c1df00 +0, 14, 14, 1, 518400, 0xfcaab7a7 diff --git a/tests/ref/fate/h264-conformance-sharp_mp_paff_2r b/tests/ref/fate/h264-conformance-sharp_mp_paff_2r index 9fb88701f54..ded91a9bede 100644 --- a/tests/ref/fate/h264-conformance-sharp_mp_paff_2r +++ b/tests/ref/fate/h264-conformance-sharp_mp_paff_2r @@ -5,16 +5,16 @@ #sar 0: 0/1 0, 0, 0, 1, 518400, 0xc93c7c47 0, 1, 1, 1, 518400, 0xfb452a9c -0, 3, 3, 1, 518400, 0x2f7a35bd -0, 4, 4, 1, 518400, 0xe63e30b9 -0, 5, 5, 1, 518400, 0x39628205 -0, 6, 6, 1, 518400, 0x17fa1ea4 -0, 7, 7, 1, 518400, 0xd5ee83e2 -0, 8, 8, 1, 518400, 0x4fd6d5c9 -0, 9, 9, 1, 518400, 0x8703c999 -0, 10, 10, 1, 518400, 0x1a87e2d3 -0, 11, 11, 1, 518400, 0xa27fc4d0 -0, 12, 12, 1, 518400, 0x6effab5d -0, 13, 13, 1, 518400, 0x51ea02c9 -0, 14, 14, 1, 518400, 0xbcf84c88 -0, 15, 15, 1, 518400, 0x1d41076b +0, 2, 2, 1, 518400, 0x2f7a35bd +0, 3, 3, 1, 518400, 0xe63e30b9 +0, 4, 4, 1, 518400, 0x39628205 +0, 5, 5, 1, 518400, 0x17fa1ea4 +0, 6, 6, 1, 518400, 0xd5ee83e2 +0, 7, 7, 1, 518400, 0x4fd6d5c9 +0, 8, 8, 1, 518400, 0x8703c999 +0, 9, 9, 1, 518400, 0x1a87e2d3 +0, 10, 10, 1, 518400, 0xa27fc4d0 +0, 11, 11, 1, 518400, 0x6effab5d +0, 12, 12, 1, 518400, 0x51ea02c9 +0, 13, 13, 1, 518400, 0xbcf84c88 +0, 14, 14, 1, 518400, 0x1d41076b diff --git a/tests/ref/fate/h264-intra-refresh-recovery b/tests/ref/fate/h264-intra-refresh-recovery index e85fe7bae86..a0a030fa100 100644 --- a/tests/ref/fate/h264-intra-refresh-recovery +++ b/tests/ref/fate/h264-intra-refresh-recovery @@ -3,13 +3,13 @@ #codec_id 0: rawvideo #dimensions 0: 320x240 #sar 0: 0/1 -0, 57, 57, 1, 115200, 0x4a17d50b -0, 58, 58, 1, 115200, 0x1283d05b -0, 59, 59, 1, 115200, 0x2747c650 -0, 60, 60, 1, 115200, 0xba23c933 -0, 61, 61, 1, 115200, 0x8a96c54b -0, 62, 62, 1, 115200, 0x748ac6d3 -0, 63, 63, 1, 115200, 0x719ca491 -0, 64, 64, 1, 115200, 0x3d259d4d -0, 65, 65, 1, 115200, 0xe3599aa8 -0, 66, 66, 1, 115200, 0x6fd4affe +0, 0, 0, 1, 115200, 0x4a17d50b +0, 1, 1, 1, 115200, 0x1283d05b +0, 2, 2, 1, 115200, 0x2747c650 +0, 3, 3, 1, 115200, 0xba23c933 +0, 4, 4, 1, 115200, 0x8a96c54b +0, 5, 5, 1, 115200, 0x748ac6d3 +0, 6, 6, 1, 115200, 0x719ca491 +0, 7, 7, 1, 115200, 0x3d259d4d +0, 8, 8, 1, 115200, 0xe3599aa8 +0, 9, 9, 1, 115200, 0x6fd4affe diff --git a/tests/ref/fate/hevc-conformance-BUMPING_A_ericsson_1 b/tests/ref/fate/hevc-conformance-BUMPING_A_ericsson_1 index 046b1846f8d..fe890040e6f 100644 --- a/tests/ref/fate/hevc-conformance-BUMPING_A_ericsson_1 +++ b/tests/ref/fate/hevc-conformance-BUMPING_A_ericsson_1 @@ -7,48 +7,48 @@ 0, 1, 1, 1, 149760, 0x73610669 0, 2, 2, 1, 149760, 0xc01620f4 0, 3, 3, 1, 149760, 0x847a4297 -0, 8, 8, 1, 149760, 0x8b2db700 -0, 9, 9, 1, 149760, 0x17b1d77c -0, 10, 10, 1, 149760, 0xc31ee8a5 -0, 11, 11, 1, 149760, 0x19541295 -0, 12, 12, 1, 149760, 0xd050be45 -0, 13, 13, 1, 149760, 0x45cf8e84 -0, 14, 14, 1, 149760, 0x0dd3e4d4 -0, 16, 16, 1, 149760, 0xc8347a7c -0, 17, 17, 1, 149760, 0x24089674 -0, 18, 18, 1, 149760, 0xdf2c44e4 -0, 19, 19, 1, 149760, 0x83f5100b -0, 20, 20, 1, 149760, 0x9a060faf -0, 24, 24, 1, 149760, 0x4cdc6101 -0, 25, 25, 1, 149760, 0xe492ad68 -0, 26, 26, 1, 149760, 0x35b73887 -0, 27, 27, 1, 149760, 0x259f898a -0, 28, 28, 1, 149760, 0x21df021b -0, 29, 29, 1, 149760, 0xdddc1cfe -0, 32, 32, 1, 149760, 0x53841bf5 -0, 33, 33, 1, 149760, 0x16745d74 -0, 34, 34, 1, 149760, 0x66e79e6a -0, 35, 35, 1, 149760, 0x35f04b5a -0, 40, 40, 1, 149760, 0x1472eee7 -0, 41, 41, 1, 149760, 0x42d0147c -0, 42, 42, 1, 149760, 0x57c9bdc2 -0, 43, 43, 1, 149760, 0x20ad4cc7 -0, 44, 44, 1, 149760, 0x1617ef6c -0, 45, 45, 1, 149760, 0xccdf4da2 -0, 46, 46, 1, 149760, 0xc173b762 -0, 47, 47, 1, 149760, 0xe7390c69 -0, 48, 48, 1, 149760, 0xfd0c97d3 -0, 49, 49, 1, 149760, 0xaeb2d61f -0, 50, 50, 1, 149760, 0xe7b114d2 -0, 51, 51, 1, 149760, 0x1b771de4 -0, 52, 52, 1, 149760, 0xd3e03840 -0, 53, 53, 1, 149760, 0x702ef44b -0, 57, 57, 1, 149760, 0xe96f848b -0, 58, 58, 1, 149760, 0xa0ae24d9 -0, 59, 59, 1, 149760, 0x1b9efdfb -0, 60, 60, 1, 149760, 0xceac9bc7 -0, 61, 61, 1, 149760, 0x73078700 -0, 62, 62, 1, 149760, 0xa736637e -0, 63, 63, 1, 149760, 0xbd353c9d -0, 64, 64, 1, 149760, 0x750a23ba -0, 65, 65, 1, 149760, 0x4144c56e +0, 4, 4, 1, 149760, 0x8b2db700 +0, 5, 5, 1, 149760, 0x17b1d77c +0, 6, 6, 1, 149760, 0xc31ee8a5 +0, 7, 7, 1, 149760, 0x19541295 +0, 8, 8, 1, 149760, 0xd050be45 +0, 9, 9, 1, 149760, 0x45cf8e84 +0, 10, 10, 1, 149760, 0x0dd3e4d4 +0, 11, 11, 1, 149760, 0xc8347a7c +0, 12, 12, 1, 149760, 0x24089674 +0, 13, 13, 1, 149760, 0xdf2c44e4 +0, 14, 14, 1, 149760, 0x83f5100b +0, 15, 15, 1, 149760, 0x9a060faf +0, 16, 16, 1, 149760, 0x4cdc6101 +0, 17, 17, 1, 149760, 0xe492ad68 +0, 18, 18, 1, 149760, 0x35b73887 +0, 19, 19, 1, 149760, 0x259f898a +0, 20, 20, 1, 149760, 0x21df021b +0, 21, 21, 1, 149760, 0xdddc1cfe +0, 22, 22, 1, 149760, 0x53841bf5 +0, 23, 23, 1, 149760, 0x16745d74 +0, 24, 24, 1, 149760, 0x66e79e6a +0, 25, 25, 1, 149760, 0x35f04b5a +0, 26, 26, 1, 149760, 0x1472eee7 +0, 27, 27, 1, 149760, 0x42d0147c +0, 28, 28, 1, 149760, 0x57c9bdc2 +0, 29, 29, 1, 149760, 0x20ad4cc7 +0, 30, 30, 1, 149760, 0x1617ef6c +0, 31, 31, 1, 149760, 0xccdf4da2 +0, 32, 32, 1, 149760, 0xc173b762 +0, 33, 33, 1, 149760, 0xe7390c69 +0, 34, 34, 1, 149760, 0xfd0c97d3 +0, 35, 35, 1, 149760, 0xaeb2d61f +0, 36, 36, 1, 149760, 0xe7b114d2 +0, 37, 37, 1, 149760, 0x1b771de4 +0, 38, 38, 1, 149760, 0xd3e03840 +0, 39, 39, 1, 149760, 0x702ef44b +0, 40, 40, 1, 149760, 0xe96f848b +0, 41, 41, 1, 149760, 0xa0ae24d9 +0, 42, 42, 1, 149760, 0x1b9efdfb +0, 43, 43, 1, 149760, 0xceac9bc7 +0, 44, 44, 1, 149760, 0x73078700 +0, 45, 45, 1, 149760, 0xa736637e +0, 46, 46, 1, 149760, 0xbd353c9d +0, 47, 47, 1, 149760, 0x750a23ba +0, 48, 48, 1, 149760, 0x4144c56e diff --git a/tests/ref/fate/hevc-conformance-NUT_A_ericsson_5 b/tests/ref/fate/hevc-conformance-NUT_A_ericsson_5 index a375c4806e3..7ac223ef7bf 100644 --- a/tests/ref/fate/hevc-conformance-NUT_A_ericsson_5 +++ b/tests/ref/fate/hevc-conformance-NUT_A_ericsson_5 @@ -25,15 +25,15 @@ 0, 19, 19, 1, 149760, 0x0580f2be 0, 20, 20, 1, 149760, 0x8e4cea96 0, 21, 21, 1, 149760, 0x6c98d019 -0, 24, 24, 1, 149760, 0x842803c8 -0, 25, 25, 1, 149760, 0xddc196ee -0, 26, 26, 1, 149760, 0x89e45523 -0, 27, 27, 1, 149760, 0x2a36b008 -0, 28, 28, 1, 149760, 0x14a319f7 -0, 29, 29, 1, 149760, 0x7394854c -0, 30, 30, 1, 149760, 0x26dcf933 -0, 31, 31, 1, 149760, 0x5b000b7e -0, 32, 32, 1, 149760, 0x6e76bded -0, 33, 33, 1, 149760, 0x0284d92d -0, 34, 34, 1, 149760, 0xf14a25e0 -0, 35, 35, 1, 149760, 0x10c03d98 +0, 22, 22, 1, 149760, 0x842803c8 +0, 23, 23, 1, 149760, 0xddc196ee +0, 24, 24, 1, 149760, 0x89e45523 +0, 25, 25, 1, 149760, 0x2a36b008 +0, 26, 26, 1, 149760, 0x14a319f7 +0, 27, 27, 1, 149760, 0x7394854c +0, 28, 28, 1, 149760, 0x26dcf933 +0, 29, 29, 1, 149760, 0x5b000b7e +0, 30, 30, 1, 149760, 0x6e76bded +0, 31, 31, 1, 149760, 0x0284d92d +0, 32, 32, 1, 149760, 0xf14a25e0 +0, 33, 33, 1, 149760, 0x10c03d98 diff --git a/tests/ref/fate/hevc-conformance-NoOutPrior_A_Qualcomm_1 b/tests/ref/fate/hevc-conformance-NoOutPrior_A_Qualcomm_1 index 0c930f6556c..5de9da9a397 100644 --- a/tests/ref/fate/hevc-conformance-NoOutPrior_A_Qualcomm_1 +++ b/tests/ref/fate/hevc-conformance-NoOutPrior_A_Qualcomm_1 @@ -25,21 +25,21 @@ 0, 19, 19, 1, 599040, 0x4227009b 0, 20, 20, 1, 599040, 0x1bda8be4 0, 21, 21, 1, 599040, 0xd1d5dcb4 -0, 32, 32, 1, 599040, 0x00a0249f -0, 33, 33, 1, 599040, 0x7263f7cf -0, 34, 34, 1, 599040, 0x47054be4 -0, 35, 35, 1, 599040, 0xda083f52 -0, 36, 36, 1, 599040, 0xf2906ab1 -0, 37, 37, 1, 599040, 0x20936797 -0, 38, 38, 1, 599040, 0x644d7c3e -0, 39, 39, 1, 599040, 0x7c00e8bf -0, 40, 40, 1, 599040, 0x041f8a48 -0, 41, 41, 1, 599040, 0xcef6e936 -0, 42, 42, 1, 599040, 0x361461e9 -0, 43, 43, 1, 599040, 0xf663ba0a -0, 44, 44, 1, 599040, 0x4d3371d3 -0, 45, 45, 1, 599040, 0xed6b5c92 -0, 46, 46, 1, 599040, 0xdec67f6e -0, 47, 47, 1, 599040, 0xbafa50c0 -0, 48, 48, 1, 599040, 0xc9181637 -0, 49, 49, 1, 599040, 0x95834e17 +0, 22, 22, 1, 599040, 0x00a0249f +0, 23, 23, 1, 599040, 0x7263f7cf +0, 24, 24, 1, 599040, 0x47054be4 +0, 25, 25, 1, 599040, 0xda083f52 +0, 26, 26, 1, 599040, 0xf2906ab1 +0, 27, 27, 1, 599040, 0x20936797 +0, 28, 28, 1, 599040, 0x644d7c3e +0, 29, 29, 1, 599040, 0x7c00e8bf +0, 30, 30, 1, 599040, 0x041f8a48 +0, 31, 31, 1, 599040, 0xcef6e936 +0, 32, 32, 1, 599040, 0x361461e9 +0, 33, 33, 1, 599040, 0xf663ba0a +0, 34, 34, 1, 599040, 0x4d3371d3 +0, 35, 35, 1, 599040, 0xed6b5c92 +0, 36, 36, 1, 599040, 0xdec67f6e +0, 37, 37, 1, 599040, 0xbafa50c0 +0, 38, 38, 1, 599040, 0xc9181637 +0, 39, 39, 1, 599040, 0x95834e17 diff --git a/tests/ref/fate/hevc-conformance-NoOutPrior_B_Qualcomm_1 b/tests/ref/fate/hevc-conformance-NoOutPrior_B_Qualcomm_1 index 83fd3bc313f..f107e937d7f 100644 --- a/tests/ref/fate/hevc-conformance-NoOutPrior_B_Qualcomm_1 +++ b/tests/ref/fate/hevc-conformance-NoOutPrior_B_Qualcomm_1 @@ -25,28 +25,28 @@ 0, 19, 19, 1, 599040, 0x4227009b 0, 20, 20, 1, 599040, 0x1bda8be4 0, 21, 21, 1, 599040, 0xd1d5dcb4 -0, 25, 25, 1, 599040, 0x00d87745 -0, 26, 26, 1, 599040, 0x9b689b16 -0, 27, 27, 1, 599040, 0x40ae530a -0, 28, 28, 1, 599040, 0x8284f649 -0, 29, 29, 1, 599040, 0x37423ae4 -0, 30, 30, 1, 599040, 0xb3f72b02 -0, 31, 31, 1, 599040, 0xc0cc5860 -0, 32, 32, 1, 599040, 0x00a0249f -0, 33, 33, 1, 599040, 0x7263f7cf -0, 34, 34, 1, 599040, 0x47054be4 -0, 35, 35, 1, 599040, 0xda083f52 -0, 36, 36, 1, 599040, 0xf2906ab1 -0, 37, 37, 1, 599040, 0x20936797 -0, 38, 38, 1, 599040, 0x644d7c3e -0, 39, 39, 1, 599040, 0x7c00e8bf -0, 40, 40, 1, 599040, 0x041f8a48 -0, 41, 41, 1, 599040, 0xcef6e936 -0, 42, 42, 1, 599040, 0x361461e9 -0, 43, 43, 1, 599040, 0xf663ba0a -0, 44, 44, 1, 599040, 0x4d3371d3 -0, 45, 45, 1, 599040, 0xed6b5c92 -0, 46, 46, 1, 599040, 0xdec67f6e -0, 47, 47, 1, 599040, 0xbafa50c0 -0, 48, 48, 1, 599040, 0xc9181637 -0, 49, 49, 1, 599040, 0x95834e17 +0, 22, 22, 1, 599040, 0x00d87745 +0, 23, 23, 1, 599040, 0x9b689b16 +0, 24, 24, 1, 599040, 0x40ae530a +0, 25, 25, 1, 599040, 0x8284f649 +0, 26, 26, 1, 599040, 0x37423ae4 +0, 27, 27, 1, 599040, 0xb3f72b02 +0, 28, 28, 1, 599040, 0xc0cc5860 +0, 29, 29, 1, 599040, 0x00a0249f +0, 30, 30, 1, 599040, 0x7263f7cf +0, 31, 31, 1, 599040, 0x47054be4 +0, 32, 32, 1, 599040, 0xda083f52 +0, 33, 33, 1, 599040, 0xf2906ab1 +0, 34, 34, 1, 599040, 0x20936797 +0, 35, 35, 1, 599040, 0x644d7c3e +0, 36, 36, 1, 599040, 0x7c00e8bf +0, 37, 37, 1, 599040, 0x041f8a48 +0, 38, 38, 1, 599040, 0xcef6e936 +0, 39, 39, 1, 599040, 0x361461e9 +0, 40, 40, 1, 599040, 0xf663ba0a +0, 41, 41, 1, 599040, 0x4d3371d3 +0, 42, 42, 1, 599040, 0xed6b5c92 +0, 43, 43, 1, 599040, 0xdec67f6e +0, 44, 44, 1, 599040, 0xbafa50c0 +0, 45, 45, 1, 599040, 0xc9181637 +0, 46, 46, 1, 599040, 0x95834e17 diff --git a/tests/ref/fate/hevc-conformance-OPFLAG_B_Qualcomm_1 b/tests/ref/fate/hevc-conformance-OPFLAG_B_Qualcomm_1 index e71e3131a05..cc4a22f92e4 100644 --- a/tests/ref/fate/hevc-conformance-OPFLAG_B_Qualcomm_1 +++ b/tests/ref/fate/hevc-conformance-OPFLAG_B_Qualcomm_1 @@ -42,62 +42,62 @@ 0, 36, 36, 1, 599040, 0xd2152e6b 0, 37, 37, 1, 599040, 0xe4c37cc7 0, 38, 38, 1, 599040, 0xec3393c3 -0, 40, 40, 1, 599040, 0x1fe16574 -0, 41, 41, 1, 599040, 0xa3a8c14d -0, 42, 42, 1, 599040, 0x32eb90aa -0, 43, 43, 1, 599040, 0xebca8310 -0, 44, 44, 1, 599040, 0x7888627f -0, 45, 45, 1, 599040, 0xe048335c -0, 46, 46, 1, 599040, 0xe2262b9c -0, 47, 47, 1, 599040, 0xb8c2b115 -0, 48, 48, 1, 599040, 0x2ff4194b -0, 49, 49, 1, 599040, 0x3a9b5520 -0, 50, 50, 1, 599040, 0xbd8c0486 -0, 51, 51, 1, 599040, 0xc8b8f29e -0, 52, 52, 1, 599040, 0xbc12f62c -0, 53, 53, 1, 599040, 0x04bb6438 -0, 54, 54, 1, 599040, 0x07971646 -0, 55, 55, 1, 599040, 0x0193dabe -0, 56, 56, 1, 599040, 0x20f41d9e -0, 57, 57, 1, 599040, 0x04b40718 -0, 58, 58, 1, 599040, 0x75d2c51c -0, 59, 59, 1, 599040, 0x9b8c2c50 -0, 60, 60, 1, 599040, 0x970e39ea -0, 61, 61, 1, 599040, 0x7c4264aa -0, 62, 62, 1, 599040, 0xe939a6fd -0, 63, 63, 1, 599040, 0xc8b95f8d -0, 64, 64, 1, 599040, 0x9e2f384a -0, 65, 65, 1, 599040, 0x7dc74724 -0, 66, 66, 1, 599040, 0x7e93bc5f -0, 67, 67, 1, 599040, 0x99b2c09d -0, 68, 68, 1, 599040, 0x284e436f -0, 69, 69, 1, 599040, 0xaa303eee -0, 70, 70, 1, 599040, 0x65e54342 -0, 71, 71, 1, 599040, 0x2fe183cd -0, 72, 72, 1, 599040, 0x5953c191 -0, 74, 74, 1, 599040, 0x0fc9a701 -0, 75, 75, 1, 599040, 0x0eea5327 -0, 76, 76, 1, 599040, 0x118752f1 -0, 77, 77, 1, 599040, 0x778c7711 -0, 78, 78, 1, 599040, 0x6f3ad6a5 -0, 79, 79, 1, 599040, 0xf70fcd3d -0, 80, 80, 1, 599040, 0x85a366cb -0, 81, 81, 1, 599040, 0xdda47432 -0, 82, 82, 1, 599040, 0x86379004 -0, 83, 83, 1, 599040, 0xfc539512 -0, 84, 84, 1, 599040, 0x04e70786 -0, 85, 85, 1, 599040, 0x7dddc8f7 -0, 86, 86, 1, 599040, 0xa76a3b6e -0, 87, 87, 1, 599040, 0x44183060 -0, 88, 88, 1, 599040, 0x6f691c5a -0, 89, 89, 1, 599040, 0x39d25e12 -0, 90, 90, 1, 599040, 0xfe3aad0d -0, 91, 91, 1, 599040, 0x57f76928 -0, 92, 92, 1, 599040, 0x4e68eed5 -0, 93, 93, 1, 599040, 0x3a589d50 -0, 94, 94, 1, 599040, 0x92ec69b8 -0, 95, 95, 1, 599040, 0x9f78926e -0, 96, 96, 1, 599040, 0xa1ca1b1d -0, 97, 97, 1, 599040, 0x140240eb -0, 98, 98, 1, 599040, 0x61fa01af -0, 99, 99, 1, 599040, 0x79f9e3ae +0, 39, 39, 1, 599040, 0x1fe16574 +0, 40, 40, 1, 599040, 0xa3a8c14d +0, 41, 41, 1, 599040, 0x32eb90aa +0, 42, 42, 1, 599040, 0xebca8310 +0, 43, 43, 1, 599040, 0x7888627f +0, 44, 44, 1, 599040, 0xe048335c +0, 45, 45, 1, 599040, 0xe2262b9c +0, 46, 46, 1, 599040, 0xb8c2b115 +0, 47, 47, 1, 599040, 0x2ff4194b +0, 48, 48, 1, 599040, 0x3a9b5520 +0, 49, 49, 1, 599040, 0xbd8c0486 +0, 50, 50, 1, 599040, 0xc8b8f29e +0, 51, 51, 1, 599040, 0xbc12f62c +0, 52, 52, 1, 599040, 0x04bb6438 +0, 53, 53, 1, 599040, 0x07971646 +0, 54, 54, 1, 599040, 0x0193dabe +0, 55, 55, 1, 599040, 0x20f41d9e +0, 56, 56, 1, 599040, 0x04b40718 +0, 57, 57, 1, 599040, 0x75d2c51c +0, 58, 58, 1, 599040, 0x9b8c2c50 +0, 59, 59, 1, 599040, 0x970e39ea +0, 60, 60, 1, 599040, 0x7c4264aa +0, 61, 61, 1, 599040, 0xe939a6fd +0, 62, 62, 1, 599040, 0xc8b95f8d +0, 63, 63, 1, 599040, 0x9e2f384a +0, 64, 64, 1, 599040, 0x7dc74724 +0, 65, 65, 1, 599040, 0x7e93bc5f +0, 66, 66, 1, 599040, 0x99b2c09d +0, 67, 67, 1, 599040, 0x284e436f +0, 68, 68, 1, 599040, 0xaa303eee +0, 69, 69, 1, 599040, 0x65e54342 +0, 70, 70, 1, 599040, 0x2fe183cd +0, 71, 71, 1, 599040, 0x5953c191 +0, 72, 72, 1, 599040, 0x0fc9a701 +0, 73, 73, 1, 599040, 0x0eea5327 +0, 74, 74, 1, 599040, 0x118752f1 +0, 75, 75, 1, 599040, 0x778c7711 +0, 76, 76, 1, 599040, 0x6f3ad6a5 +0, 77, 77, 1, 599040, 0xf70fcd3d +0, 78, 78, 1, 599040, 0x85a366cb +0, 79, 79, 1, 599040, 0xdda47432 +0, 80, 80, 1, 599040, 0x86379004 +0, 81, 81, 1, 599040, 0xfc539512 +0, 82, 82, 1, 599040, 0x04e70786 +0, 83, 83, 1, 599040, 0x7dddc8f7 +0, 84, 84, 1, 599040, 0xa76a3b6e +0, 85, 85, 1, 599040, 0x44183060 +0, 86, 86, 1, 599040, 0x6f691c5a +0, 87, 87, 1, 599040, 0x39d25e12 +0, 88, 88, 1, 599040, 0xfe3aad0d +0, 89, 89, 1, 599040, 0x57f76928 +0, 90, 90, 1, 599040, 0x4e68eed5 +0, 91, 91, 1, 599040, 0x3a589d50 +0, 92, 92, 1, 599040, 0x92ec69b8 +0, 93, 93, 1, 599040, 0x9f78926e +0, 94, 94, 1, 599040, 0xa1ca1b1d +0, 95, 95, 1, 599040, 0x140240eb +0, 96, 96, 1, 599040, 0x61fa01af +0, 97, 97, 1, 599040, 0x79f9e3ae diff --git a/tests/ref/fate/hevc-conformance-OPFLAG_C_Qualcomm_1 b/tests/ref/fate/hevc-conformance-OPFLAG_C_Qualcomm_1 index ffc4f517737..233b0426719 100644 --- a/tests/ref/fate/hevc-conformance-OPFLAG_C_Qualcomm_1 +++ b/tests/ref/fate/hevc-conformance-OPFLAG_C_Qualcomm_1 @@ -18,84 +18,84 @@ 0, 12, 12, 1, 599040, 0x1991f1f9 0, 13, 13, 1, 599040, 0x36e54ba2 0, 14, 14, 1, 599040, 0x698ce0c6 -0, 16, 16, 1, 599040, 0xc6dd131e -0, 17, 17, 1, 599040, 0x0a22f4c5 -0, 18, 18, 1, 599040, 0xd6a0c196 -0, 19, 19, 1, 599040, 0x699a3e69 -0, 20, 20, 1, 599040, 0x4227009b -0, 21, 21, 1, 599040, 0xd1d5dcb4 -0, 22, 22, 1, 599040, 0x58b2edb3 -0, 23, 23, 1, 599040, 0xd1f795d8 -0, 24, 24, 1, 599040, 0x3331d5e6 -0, 25, 25, 1, 599040, 0x5e5ec2c9 -0, 26, 26, 1, 599040, 0x3b907bf5 -0, 27, 27, 1, 599040, 0xefcbf471 -0, 28, 28, 1, 599040, 0x2769a578 -0, 30, 30, 1, 599040, 0x812ce986 -0, 31, 31, 1, 599040, 0xf07c212c -0, 32, 32, 1, 599040, 0x00a0249f -0, 33, 33, 1, 599040, 0x7263f7cf -0, 34, 34, 1, 599040, 0x47054be4 -0, 35, 35, 1, 599040, 0xda083f52 -0, 36, 36, 1, 599040, 0xf2906ab1 -0, 37, 37, 1, 599040, 0x20936797 -0, 38, 38, 1, 599040, 0x644d7c3e -0, 39, 39, 1, 599040, 0x7c00e8bf -0, 40, 40, 1, 599040, 0x041f8a48 -0, 41, 41, 1, 599040, 0xcef6e936 -0, 42, 42, 1, 599040, 0x361461e9 -0, 43, 43, 1, 599040, 0xf663ba0a -0, 44, 44, 1, 599040, 0x4d3371d3 -0, 45, 45, 1, 599040, 0xed6b5c92 -0, 47, 47, 1, 599040, 0xdec67f6e -0, 48, 48, 1, 599040, 0xbafa50c0 -0, 49, 49, 1, 599040, 0xc9181637 -0, 50, 50, 1, 599040, 0x29eadcac -0, 51, 51, 1, 599040, 0xb258430f -0, 52, 52, 1, 599040, 0x49dc8716 -0, 53, 53, 1, 599040, 0x80b0a3b3 -0, 54, 54, 1, 599040, 0x5d8275a7 -0, 55, 55, 1, 599040, 0xe236242d -0, 56, 56, 1, 599040, 0x3e14bb43 -0, 57, 57, 1, 599040, 0x20e6e2d7 -0, 58, 58, 1, 599040, 0x19cad4ee -0, 59, 59, 1, 599040, 0x13fd16f1 -0, 60, 60, 1, 599040, 0x98e56b95 -0, 61, 61, 1, 599040, 0x028e4c6a -0, 63, 63, 1, 599040, 0x5bd1131d -0, 64, 64, 1, 599040, 0x0afe3873 -0, 65, 65, 1, 599040, 0xea93e425 -0, 66, 66, 1, 599040, 0xeb301be1 -0, 67, 67, 1, 599040, 0x443ca0a3 -0, 68, 68, 1, 599040, 0xb68b40a1 -0, 69, 69, 1, 599040, 0xf58f75b9 -0, 70, 70, 1, 599040, 0xefa27c52 -0, 71, 71, 1, 599040, 0xac676fa5 -0, 72, 72, 1, 599040, 0x688d1582 -0, 73, 73, 1, 599040, 0x9067a4ef -0, 74, 74, 1, 599040, 0xdc753d6c -0, 75, 75, 1, 599040, 0x6f6da304 -0, 76, 76, 1, 599040, 0xa7606f97 -0, 77, 77, 1, 599040, 0xb53c8c18 -0, 78, 78, 1, 599040, 0x3572d550 -0, 79, 79, 1, 599040, 0x123d5423 -0, 80, 80, 1, 599040, 0x89f11e50 -0, 81, 81, 1, 599040, 0x702649cc -0, 82, 82, 1, 599040, 0x2b4767c4 -0, 83, 83, 1, 599040, 0xf18b9628 -0, 84, 84, 1, 599040, 0x1ef72a6b -0, 85, 85, 1, 599040, 0x0a8c9641 -0, 86, 86, 1, 599040, 0xf2fa0233 -0, 87, 87, 1, 599040, 0x99385e51 -0, 88, 88, 1, 599040, 0x77b413cf -0, 89, 89, 1, 599040, 0x6360c9e3 -0, 90, 90, 1, 599040, 0xe216b383 -0, 91, 91, 1, 599040, 0x54df8826 -0, 92, 92, 1, 599040, 0x6691e1ee -0, 93, 93, 1, 599040, 0x37bebd20 -0, 94, 94, 1, 599040, 0xf05184e4 -0, 95, 95, 1, 599040, 0xbd7fab4f -0, 96, 96, 1, 599040, 0x70211cdc -0, 97, 97, 1, 599040, 0x4f4c375b -0, 98, 98, 1, 599040, 0x2d645b5a -0, 99, 99, 1, 599040, 0x475d263f +0, 15, 15, 1, 599040, 0xc6dd131e +0, 16, 16, 1, 599040, 0x0a22f4c5 +0, 17, 17, 1, 599040, 0xd6a0c196 +0, 18, 18, 1, 599040, 0x699a3e69 +0, 19, 19, 1, 599040, 0x4227009b +0, 20, 20, 1, 599040, 0xd1d5dcb4 +0, 21, 21, 1, 599040, 0x58b2edb3 +0, 22, 22, 1, 599040, 0xd1f795d8 +0, 23, 23, 1, 599040, 0x3331d5e6 +0, 24, 24, 1, 599040, 0x5e5ec2c9 +0, 25, 25, 1, 599040, 0x3b907bf5 +0, 26, 26, 1, 599040, 0xefcbf471 +0, 27, 27, 1, 599040, 0x2769a578 +0, 28, 28, 1, 599040, 0x812ce986 +0, 29, 29, 1, 599040, 0xf07c212c +0, 30, 30, 1, 599040, 0x00a0249f +0, 31, 31, 1, 599040, 0x7263f7cf +0, 32, 32, 1, 599040, 0x47054be4 +0, 33, 33, 1, 599040, 0xda083f52 +0, 34, 34, 1, 599040, 0xf2906ab1 +0, 35, 35, 1, 599040, 0x20936797 +0, 36, 36, 1, 599040, 0x644d7c3e +0, 37, 37, 1, 599040, 0x7c00e8bf +0, 38, 38, 1, 599040, 0x041f8a48 +0, 39, 39, 1, 599040, 0xcef6e936 +0, 40, 40, 1, 599040, 0x361461e9 +0, 41, 41, 1, 599040, 0xf663ba0a +0, 42, 42, 1, 599040, 0x4d3371d3 +0, 43, 43, 1, 599040, 0xed6b5c92 +0, 44, 44, 1, 599040, 0xdec67f6e +0, 45, 45, 1, 599040, 0xbafa50c0 +0, 46, 46, 1, 599040, 0xc9181637 +0, 47, 47, 1, 599040, 0x29eadcac +0, 48, 48, 1, 599040, 0xb258430f +0, 49, 49, 1, 599040, 0x49dc8716 +0, 50, 50, 1, 599040, 0x80b0a3b3 +0, 51, 51, 1, 599040, 0x5d8275a7 +0, 52, 52, 1, 599040, 0xe236242d +0, 53, 53, 1, 599040, 0x3e14bb43 +0, 54, 54, 1, 599040, 0x20e6e2d7 +0, 55, 55, 1, 599040, 0x19cad4ee +0, 56, 56, 1, 599040, 0x13fd16f1 +0, 57, 57, 1, 599040, 0x98e56b95 +0, 58, 58, 1, 599040, 0x028e4c6a +0, 59, 59, 1, 599040, 0x5bd1131d +0, 60, 60, 1, 599040, 0x0afe3873 +0, 61, 61, 1, 599040, 0xea93e425 +0, 62, 62, 1, 599040, 0xeb301be1 +0, 63, 63, 1, 599040, 0x443ca0a3 +0, 64, 64, 1, 599040, 0xb68b40a1 +0, 65, 65, 1, 599040, 0xf58f75b9 +0, 66, 66, 1, 599040, 0xefa27c52 +0, 67, 67, 1, 599040, 0xac676fa5 +0, 68, 68, 1, 599040, 0x688d1582 +0, 69, 69, 1, 599040, 0x9067a4ef +0, 70, 70, 1, 599040, 0xdc753d6c +0, 71, 71, 1, 599040, 0x6f6da304 +0, 72, 72, 1, 599040, 0xa7606f97 +0, 73, 73, 1, 599040, 0xb53c8c18 +0, 74, 74, 1, 599040, 0x3572d550 +0, 75, 75, 1, 599040, 0x123d5423 +0, 76, 76, 1, 599040, 0x89f11e50 +0, 77, 77, 1, 599040, 0x702649cc +0, 78, 78, 1, 599040, 0x2b4767c4 +0, 79, 79, 1, 599040, 0xf18b9628 +0, 80, 80, 1, 599040, 0x1ef72a6b +0, 81, 81, 1, 599040, 0x0a8c9641 +0, 82, 82, 1, 599040, 0xf2fa0233 +0, 83, 83, 1, 599040, 0x99385e51 +0, 84, 84, 1, 599040, 0x77b413cf +0, 85, 85, 1, 599040, 0x6360c9e3 +0, 86, 86, 1, 599040, 0xe216b383 +0, 87, 87, 1, 599040, 0x54df8826 +0, 88, 88, 1, 599040, 0x6691e1ee +0, 89, 89, 1, 599040, 0x37bebd20 +0, 90, 90, 1, 599040, 0xf05184e4 +0, 91, 91, 1, 599040, 0xbd7fab4f +0, 92, 92, 1, 599040, 0x70211cdc +0, 93, 93, 1, 599040, 0x4f4c375b +0, 94, 94, 1, 599040, 0x2d645b5a +0, 95, 95, 1, 599040, 0x475d263f diff --git a/tests/ref/fate/hevc-conformance-RAP_A_docomo_4 b/tests/ref/fate/hevc-conformance-RAP_A_docomo_4 index fbbedb236c4..51ea08b5845 100644 --- a/tests/ref/fate/hevc-conformance-RAP_A_docomo_4 +++ b/tests/ref/fate/hevc-conformance-RAP_A_docomo_4 @@ -3,89 +3,89 @@ #codec_id 0: rawvideo #dimensions 0: 416x240 #sar 0: 0/1 -0, 7, 7, 1, 149760, 0x1ae5f13d -0, 8, 8, 1, 149760, 0x0a6ad0e3 -0, 9, 9, 1, 149760, 0x2415af05 -0, 10, 10, 1, 149760, 0xf50f6eef -0, 11, 11, 1, 149760, 0xef65835c -0, 12, 12, 1, 149760, 0x4929b5cb -0, 13, 13, 1, 149760, 0x165c6f55 -0, 14, 14, 1, 149760, 0x9caaa249 -0, 15, 15, 1, 149760, 0x6c25c4cf -0, 16, 16, 1, 149760, 0x4678cef0 -0, 17, 17, 1, 149760, 0x72e04433 -0, 18, 18, 1, 149760, 0x36f8aa9d -0, 19, 19, 1, 149760, 0x255189ad -0, 20, 20, 1, 149760, 0x712d7f7f -0, 21, 21, 1, 149760, 0x4d088988 -0, 22, 22, 1, 149760, 0xc0da3925 -0, 23, 23, 1, 149760, 0x9990db7c -0, 24, 24, 1, 149760, 0xb02cc0e8 -0, 25, 25, 1, 149760, 0x3e859d8f -0, 26, 26, 1, 149760, 0xce786bc1 -0, 27, 27, 1, 149760, 0x87555e5f -0, 28, 28, 1, 149760, 0x3c95fb7e -0, 29, 29, 1, 149760, 0xf092b65e -0, 30, 30, 1, 149760, 0x7db2c04c -0, 31, 31, 1, 149760, 0x7d39eb21 -0, 32, 32, 1, 149760, 0x2cfd7d57 -0, 33, 33, 1, 149760, 0xb1902c06 -0, 34, 34, 1, 149760, 0xe0eae1d7 -0, 35, 35, 1, 149760, 0xf8212977 -0, 36, 36, 1, 149760, 0x6cb31328 -0, 37, 37, 1, 149760, 0x862ab736 -0, 38, 38, 1, 149760, 0xc7a87f44 -0, 39, 39, 1, 149760, 0x8ff7a1a1 -0, 40, 40, 1, 149760, 0xd7bee49b -0, 41, 41, 1, 149760, 0x1925db84 -0, 42, 42, 1, 149760, 0xf32a7dc6 -0, 43, 43, 1, 149760, 0x02a1e3b6 -0, 44, 44, 1, 149760, 0xb6398aad -0, 45, 45, 1, 149760, 0xa3756e2d -0, 46, 46, 1, 149760, 0xf90f3732 -0, 47, 47, 1, 149760, 0x3b05115a -0, 48, 48, 1, 149760, 0x81ca9bdb -0, 49, 49, 1, 149760, 0xa75ee938 -0, 50, 50, 1, 149760, 0x9e5c232f -0, 51, 51, 1, 149760, 0x64cb04e9 -0, 52, 52, 1, 149760, 0x4064df52 -0, 53, 53, 1, 149760, 0x47fa0afc -0, 54, 54, 1, 149760, 0xd209252e -0, 55, 55, 1, 149760, 0x2f811f02 -0, 56, 56, 1, 149760, 0x733b6721 -0, 57, 57, 1, 149760, 0x30b12427 -0, 58, 58, 1, 149760, 0xdf58d3e2 -0, 59, 59, 1, 149760, 0xc144d7be -0, 60, 60, 1, 149760, 0x48f0ac79 -0, 61, 61, 1, 149760, 0xb8d8a2c6 -0, 62, 62, 1, 149760, 0x2a7d916d -0, 63, 63, 1, 149760, 0xd9d38cd5 -0, 64, 64, 1, 149760, 0xd7c7f9a6 -0, 65, 65, 1, 149760, 0x64d0df7a -0, 66, 66, 1, 149760, 0x4e365cff -0, 67, 67, 1, 149760, 0x74bc2a8b -0, 68, 68, 1, 149760, 0x70a7cd2b -0, 69, 69, 1, 149760, 0x0836b51e -0, 70, 70, 1, 149760, 0xbc37b5d7 -0, 71, 71, 1, 149760, 0xb6d651e5 -0, 72, 72, 1, 149760, 0x7aa0e35f -0, 73, 73, 1, 149760, 0x0fbc89a3 -0, 74, 74, 1, 149760, 0x2ca2f2a6 -0, 75, 75, 1, 149760, 0xf742c5c5 -0, 76, 76, 1, 149760, 0x4117208f -0, 77, 77, 1, 149760, 0xec392efb -0, 78, 78, 1, 149760, 0xbfba5063 -0, 79, 79, 1, 149760, 0xb2499f48 -0, 80, 80, 1, 149760, 0xf1183244 -0, 81, 81, 1, 149760, 0x364a6400 -0, 82, 82, 1, 149760, 0xfcfddf36 -0, 83, 83, 1, 149760, 0xbcc1b37e -0, 84, 84, 1, 149760, 0xab364748 -0, 85, 85, 1, 149760, 0xebb27fcd -0, 86, 86, 1, 149760, 0xe2e7a723 -0, 87, 87, 1, 149760, 0xf671b5e0 -0, 88, 88, 1, 149760, 0xbf0cc349 -0, 89, 89, 1, 149760, 0xf195d868 -0, 90, 90, 1, 149760, 0xe0097460 -0, 91, 91, 1, 149760, 0x3d4c1812 -0, 92, 92, 1, 149760, 0x133cd867 +0, 0, 0, 1, 149760, 0x1ae5f13d +0, 1, 1, 1, 149760, 0x0a6ad0e3 +0, 2, 2, 1, 149760, 0x2415af05 +0, 3, 3, 1, 149760, 0xf50f6eef +0, 4, 4, 1, 149760, 0xef65835c +0, 5, 5, 1, 149760, 0x4929b5cb +0, 6, 6, 1, 149760, 0x165c6f55 +0, 7, 7, 1, 149760, 0x9caaa249 +0, 8, 8, 1, 149760, 0x6c25c4cf +0, 9, 9, 1, 149760, 0x4678cef0 +0, 10, 10, 1, 149760, 0x72e04433 +0, 11, 11, 1, 149760, 0x36f8aa9d +0, 12, 12, 1, 149760, 0x255189ad +0, 13, 13, 1, 149760, 0x712d7f7f +0, 14, 14, 1, 149760, 0x4d088988 +0, 15, 15, 1, 149760, 0xc0da3925 +0, 16, 16, 1, 149760, 0x9990db7c +0, 17, 17, 1, 149760, 0xb02cc0e8 +0, 18, 18, 1, 149760, 0x3e859d8f +0, 19, 19, 1, 149760, 0xce786bc1 +0, 20, 20, 1, 149760, 0x87555e5f +0, 21, 21, 1, 149760, 0x3c95fb7e +0, 22, 22, 1, 149760, 0xf092b65e +0, 23, 23, 1, 149760, 0x7db2c04c +0, 24, 24, 1, 149760, 0x7d39eb21 +0, 25, 25, 1, 149760, 0x2cfd7d57 +0, 26, 26, 1, 149760, 0xb1902c06 +0, 27, 27, 1, 149760, 0xe0eae1d7 +0, 28, 28, 1, 149760, 0xf8212977 +0, 29, 29, 1, 149760, 0x6cb31328 +0, 30, 30, 1, 149760, 0x862ab736 +0, 31, 31, 1, 149760, 0xc7a87f44 +0, 32, 32, 1, 149760, 0x8ff7a1a1 +0, 33, 33, 1, 149760, 0xd7bee49b +0, 34, 34, 1, 149760, 0x1925db84 +0, 35, 35, 1, 149760, 0xf32a7dc6 +0, 36, 36, 1, 149760, 0x02a1e3b6 +0, 37, 37, 1, 149760, 0xb6398aad +0, 38, 38, 1, 149760, 0xa3756e2d +0, 39, 39, 1, 149760, 0xf90f3732 +0, 40, 40, 1, 149760, 0x3b05115a +0, 41, 41, 1, 149760, 0x81ca9bdb +0, 42, 42, 1, 149760, 0xa75ee938 +0, 43, 43, 1, 149760, 0x9e5c232f +0, 44, 44, 1, 149760, 0x64cb04e9 +0, 45, 45, 1, 149760, 0x4064df52 +0, 46, 46, 1, 149760, 0x47fa0afc +0, 47, 47, 1, 149760, 0xd209252e +0, 48, 48, 1, 149760, 0x2f811f02 +0, 49, 49, 1, 149760, 0x733b6721 +0, 50, 50, 1, 149760, 0x30b12427 +0, 51, 51, 1, 149760, 0xdf58d3e2 +0, 52, 52, 1, 149760, 0xc144d7be +0, 53, 53, 1, 149760, 0x48f0ac79 +0, 54, 54, 1, 149760, 0xb8d8a2c6 +0, 55, 55, 1, 149760, 0x2a7d916d +0, 56, 56, 1, 149760, 0xd9d38cd5 +0, 57, 57, 1, 149760, 0xd7c7f9a6 +0, 58, 58, 1, 149760, 0x64d0df7a +0, 59, 59, 1, 149760, 0x4e365cff +0, 60, 60, 1, 149760, 0x74bc2a8b +0, 61, 61, 1, 149760, 0x70a7cd2b +0, 62, 62, 1, 149760, 0x0836b51e +0, 63, 63, 1, 149760, 0xbc37b5d7 +0, 64, 64, 1, 149760, 0xb6d651e5 +0, 65, 65, 1, 149760, 0x7aa0e35f +0, 66, 66, 1, 149760, 0x0fbc89a3 +0, 67, 67, 1, 149760, 0x2ca2f2a6 +0, 68, 68, 1, 149760, 0xf742c5c5 +0, 69, 69, 1, 149760, 0x4117208f +0, 70, 70, 1, 149760, 0xec392efb +0, 71, 71, 1, 149760, 0xbfba5063 +0, 72, 72, 1, 149760, 0xb2499f48 +0, 73, 73, 1, 149760, 0xf1183244 +0, 74, 74, 1, 149760, 0x364a6400 +0, 75, 75, 1, 149760, 0xfcfddf36 +0, 76, 76, 1, 149760, 0xbcc1b37e +0, 77, 77, 1, 149760, 0xab364748 +0, 78, 78, 1, 149760, 0xebb27fcd +0, 79, 79, 1, 149760, 0xe2e7a723 +0, 80, 80, 1, 149760, 0xf671b5e0 +0, 81, 81, 1, 149760, 0xbf0cc349 +0, 82, 82, 1, 149760, 0xf195d868 +0, 83, 83, 1, 149760, 0xe0097460 +0, 84, 84, 1, 149760, 0x3d4c1812 +0, 85, 85, 1, 149760, 0x133cd867 diff --git a/tests/ref/fate/hevc-conformance-RAP_B_Bossen_1 b/tests/ref/fate/hevc-conformance-RAP_B_Bossen_1 index e661ff245eb..53e733bd755 100644 --- a/tests/ref/fate/hevc-conformance-RAP_B_Bossen_1 +++ b/tests/ref/fate/hevc-conformance-RAP_B_Bossen_1 @@ -70,16 +70,16 @@ 0, 64, 64, 1, 149760, 0x3362678b 0, 65, 65, 1, 149760, 0x6e7fc851 0, 66, 66, 1, 149760, 0x33f96449 -0, 77, 77, 1, 149760, 0xb3ba8cfb -0, 78, 78, 1, 149760, 0x64787995 -0, 79, 79, 1, 149760, 0xc10de4c4 -0, 80, 80, 1, 149760, 0x18dd343f -0, 81, 81, 1, 149760, 0xa1c51358 -0, 82, 82, 1, 149760, 0x91fe6361 -0, 83, 83, 1, 149760, 0xeec85f94 -0, 84, 84, 1, 149760, 0x00a57402 -0, 85, 85, 1, 149760, 0x4e88cc16 -0, 86, 86, 1, 149760, 0xdbd51976 -0, 87, 87, 1, 149760, 0xfebf6b1a -0, 88, 88, 1, 149760, 0x052546d2 -0, 89, 89, 1, 149760, 0x046cd73b +0, 67, 67, 1, 149760, 0xb3ba8cfb +0, 68, 68, 1, 149760, 0x64787995 +0, 69, 69, 1, 149760, 0xc10de4c4 +0, 70, 70, 1, 149760, 0x18dd343f +0, 71, 71, 1, 149760, 0xa1c51358 +0, 72, 72, 1, 149760, 0x91fe6361 +0, 73, 73, 1, 149760, 0xeec85f94 +0, 74, 74, 1, 149760, 0x00a57402 +0, 75, 75, 1, 149760, 0x4e88cc16 +0, 76, 76, 1, 149760, 0xdbd51976 +0, 77, 77, 1, 149760, 0xfebf6b1a +0, 78, 78, 1, 149760, 0x052546d2 +0, 79, 79, 1, 149760, 0x046cd73b From 4eaaa38d3dfb8863a62f3646a62e4098b1c078d5 Mon Sep 17 00:00:00 2001 From: Niklas Haas Date: Mon, 10 Apr 2023 15:58:51 +0200 Subject: [PATCH 0669/2172] avutil: make av_frame_get_plane_buffer accept a const AVFrame* Signed-off-by: Niklas Haas --- doc/APIchanges | 3 +++ libavutil/frame.c | 2 +- libavutil/frame.h | 2 +- 3 files changed, 5 insertions(+), 2 deletions(-) diff --git a/doc/APIchanges b/doc/APIchanges index 44ba3ad634b..0b609e3d3b2 100644 --- a/doc/APIchanges +++ b/doc/APIchanges @@ -2,6 +2,9 @@ The last version increases of all libraries were on 2023-02-09 API changes, most recent first: +2023-04-10 - xxxxxxxxxx - lavu 58.6.100 - frame.h + av_frame_get_plane_buffer() now accepts const AVFrame*. + 2023-04-04 - xxxxxxxxxx - lavu 58.6.100 - hdr_dynamic_metadata.h Add AV_HDR_PLUS_MAX_PAYLOAD_SIZE. av_dynamic_hdr_plus_create_side_data() now accepts a user provided diff --git a/libavutil/frame.c b/libavutil/frame.c index c905e8d6119..f420a6e1871 100644 --- a/libavutil/frame.c +++ b/libavutil/frame.c @@ -600,7 +600,7 @@ int av_frame_copy_props(AVFrame *dst, const AVFrame *src) return frame_copy_props(dst, src, 1); } -AVBufferRef *av_frame_get_plane_buffer(AVFrame *frame, int plane) +AVBufferRef *av_frame_get_plane_buffer(const AVFrame *frame, int plane) { uint8_t *data; int planes; diff --git a/libavutil/frame.h b/libavutil/frame.h index 5b58c14ac32..f85d630c5ce 100644 --- a/libavutil/frame.h +++ b/libavutil/frame.h @@ -901,7 +901,7 @@ int av_frame_copy_props(AVFrame *dst, const AVFrame *src); * @return the buffer reference that contains the plane or NULL if the input * frame is not valid. */ -AVBufferRef *av_frame_get_plane_buffer(AVFrame *frame, int plane); +AVBufferRef *av_frame_get_plane_buffer(const AVFrame *frame, int plane); /** * Add a new side data to a frame. From bd2f00f665cc964fc1942518cdf27bd6e8b6d388 Mon Sep 17 00:00:00 2001 From: xufuji456 <839789740@qq.com> Date: Thu, 13 Apr 2023 21:34:47 +0800 Subject: [PATCH 0670/2172] codec/aarch64/hevc: add transform_luma_neon MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit got 56% speed up (run_count=1000, CPU=Cortex A53) transform_4x4_luma_neon: 45 transform_4x4_luma_c: 103 Signed-off-by: xufuji456 <839789740@qq.com> Signed-off-by: Martin Storsjö --- libavcodec/aarch64/hevcdsp_idct_neon.S | 48 +++++++++++++++++++++++ libavcodec/aarch64/hevcdsp_init_aarch64.c | 2 + 2 files changed, 50 insertions(+) diff --git a/libavcodec/aarch64/hevcdsp_idct_neon.S b/libavcodec/aarch64/hevcdsp_idct_neon.S index 976dec236a5..b7f23386a47 100644 --- a/libavcodec/aarch64/hevcdsp_idct_neon.S +++ b/libavcodec/aarch64/hevcdsp_idct_neon.S @@ -842,6 +842,54 @@ tr_32x4 secondpass_10, 20 - 10 idct_32x32 8 idct_32x32 10 +.macro tr4_luma_shift r0, r1, r2, r3, shift + saddl v0.4s, \r0, \r2 // c0 = src0 + src2 + saddl v1.4s, \r2, \r3 // c1 = src2 + src3 + ssubl v2.4s, \r0, \r3 // c2 = src0 - src3 + smull v3.4s, \r1, v21.4h // c3 = 74 * src1 + + saddl v7.4s, \r0, \r3 // src0 + src3 + ssubw v7.4s, v7.4s, \r2 // src0 - src2 + src3 + mul v7.4s, v7.4s, v18.4s // dst2 = 74 * (src0 - src2 + src3) + + mul v5.4s, v0.4s, v19.4s // 29 * c0 + mul v6.4s, v1.4s, v20.4s // 55 * c1 + add v5.4s, v5.4s, v6.4s // 29 * c0 + 55 * c1 + add v5.4s, v5.4s, v3.4s // dst0 = 29 * c0 + 55 * c1 + c3 + + mul v1.4s, v1.4s, v19.4s // 29 * c1 + mul v6.4s, v2.4s, v20.4s // 55 * c2 + sub v6.4s, v6.4s, v1.4s // 55 * c2 - 29 * c1 + add v6.4s, v6.4s, v3.4s // dst1 = 55 * c2 - 29 * c1 + c3 + + mul v0.4s, v0.4s, v20.4s // 55 * c0 + mul v2.4s, v2.4s, v19.4s // 29 * c2 + add v0.4s, v0.4s, v2.4s // 55 * c0 + 29 * c2 + sub v0.4s, v0.4s, v3.4s // dst3 = 55 * c0 + 29 * c2 - c3 + + sqrshrn \r0, v5.4s, \shift + sqrshrn \r1, v6.4s, \shift + sqrshrn \r2, v7.4s, \shift + sqrshrn \r3, v0.4s, \shift +.endm + +function ff_hevc_transform_luma_4x4_neon_8, export=1 + ld1 {v28.4h-v31.4h}, [x0] + movi v18.4s, #74 + movi v19.4s, #29 + movi v20.4s, #55 + movi v21.4h, #74 + + tr4_luma_shift v28.4h, v29.4h, v30.4h, v31.4h, #7 + transpose_4x4H v28, v29, v30, v31, v22, v23, v24, v25 + + tr4_luma_shift v28.4h, v29.4h, v30.4h, v31.4h, #12 + transpose_4x4H v28, v29, v30, v31, v22, v23, v24, v25 + + st1 {v28.4h-v31.4h}, [x0] + ret +endfunc + // void ff_hevc_idct_NxN_dc_DEPTH_neon(int16_t *coeffs) .macro idct_dc size, bitdepth function ff_hevc_idct_\size\()x\size\()_dc_\bitdepth\()_neon, export=1 diff --git a/libavcodec/aarch64/hevcdsp_init_aarch64.c b/libavcodec/aarch64/hevcdsp_init_aarch64.c index 4cc8732ad3a..be1049a2ec7 100644 --- a/libavcodec/aarch64/hevcdsp_init_aarch64.c +++ b/libavcodec/aarch64/hevcdsp_init_aarch64.c @@ -78,6 +78,7 @@ void ff_hevc_idct_4x4_dc_10_neon(int16_t *coeffs); void ff_hevc_idct_8x8_dc_10_neon(int16_t *coeffs); void ff_hevc_idct_16x16_dc_10_neon(int16_t *coeffs); void ff_hevc_idct_32x32_dc_10_neon(int16_t *coeffs); +void ff_hevc_transform_luma_4x4_neon_8(int16_t *coeffs); void ff_hevc_sao_band_filter_8x8_8_neon(uint8_t *_dst, const uint8_t *_src, ptrdiff_t stride_dst, ptrdiff_t stride_src, const int16_t *sao_offset_val, int sao_left_class, @@ -146,6 +147,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->transform_4x4_luma = ff_hevc_transform_luma_4x4_neon_8; c->sao_band_filter[0] = c->sao_band_filter[1] = c->sao_band_filter[2] = From eb96cfbf57822f7ce0af508d4a9ecd2224cbd565 Mon Sep 17 00:00:00 2001 From: Nongji Chen Date: Wed, 13 Sep 2017 11:40:15 +0300 Subject: [PATCH 0671/2172] ffmpeg: make timestamp discontinuity logging a warning MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In most cases this should only occur once or so per stream in an input, and in case the logic ends up in an eternal loop, it should be visible to the end user instead of being completely invisible. Signed-off-by: Jan Ekström --- fftools/ffmpeg.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fftools/ffmpeg.c b/fftools/ffmpeg.c index 6e445427761..e9c6a8281e6 100644 --- a/fftools/ffmpeg.c +++ b/fftools/ffmpeg.c @@ -2512,7 +2512,7 @@ static void ts_discontinuity_detect(InputFile *ifile, InputStream *ist, if (FFABS(delta) > 1LL * dts_delta_threshold * AV_TIME_BASE || pkt_dts + AV_TIME_BASE/10 < FFMAX(ist->pts, ist->dts)) { ifile->ts_offset_discont -= delta; - av_log(NULL, AV_LOG_DEBUG, + av_log(NULL, AV_LOG_WARNING, "timestamp discontinuity for stream #%d:%d " "(id=%d, type=%s): %"PRId64", new offset= %"PRId64"\n", ist->file_index, ist->st->index, ist->st->id, From f0f596dbc6b45b544d2d2d4fb78c0a2bdc3e6eb1 Mon Sep 17 00:00:00 2001 From: Zhao Zhili Date: Wed, 5 Apr 2023 22:50:08 +0800 Subject: [PATCH 0672/2172] avutil/internal: remove timer.h again MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit timer.h has been removed from internal.h, and then added back with 3e6088f for convenience. This patch removed it again for the following reasons: 1. Only includes what's necessary is a common and safe strategy. 2. It fixed some build errors on Android: a. libavutil/timer.h includes sys/ioctl.h, and ioctl.h includes termios.h on Android. b. termios.h reserves names prefixed with ‘c_’, ‘V’, ‘I’, ‘O’, and ‘TC’; and names prefixed with ‘B’ followed by a digit. c. libavcodec uses B0 B1 and so on as variable names a lot. So the code failed to build with --enable-linux-perf, or --target-os=Linux. Signed-off-by: Zhao Zhili --- libavutil/internal.h | 1 - 1 file changed, 1 deletion(-) diff --git a/libavutil/internal.h b/libavutil/internal.h index 454c59aa50d..001103142ba 100644 --- a/libavutil/internal.h +++ b/libavutil/internal.h @@ -40,7 +40,6 @@ #include #include "config.h" #include "attributes.h" -#include "timer.h" #include "macros.h" #include "pixfmt.h" From d5fdfbac4a933d52f17729555ab447be80d68bd5 Mon Sep 17 00:00:00 2001 From: Zhao Zhili Date: Fri, 7 Apr 2023 03:31:40 +0800 Subject: [PATCH 0673/2172] avformat/flvenc: use local variable to shorten code Signed-off-by: Zhao Zhili --- libavformat/flvenc.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/libavformat/flvenc.c b/libavformat/flvenc.c index fbf7eabaf8c..7873a0080f8 100644 --- a/libavformat/flvenc.c +++ b/libavformat/flvenc.c @@ -508,18 +508,18 @@ static void flv_write_codec_header(AVFormatContext* s, AVCodecParameters* par, i if (!par->extradata_size && (flv->flags & FLV_AAC_SEQ_HEADER_DETECT)) { PutBitContext pbc; int samplerate_index; - int channels = flv->audio_par->ch_layout.nb_channels - - (flv->audio_par->ch_layout.nb_channels == 8 ? 1 : 0); + int channels = par->ch_layout.nb_channels + - (par->ch_layout.nb_channels == 8 ? 1 : 0); uint8_t data[2]; for (samplerate_index = 0; samplerate_index < 16; samplerate_index++) - if (flv->audio_par->sample_rate + if (par->sample_rate == ff_mpeg4audio_sample_rates[samplerate_index]) break; init_put_bits(&pbc, data, sizeof(data)); - put_bits(&pbc, 5, flv->audio_par->profile + 1); //profile + put_bits(&pbc, 5, par->profile + 1); //profile put_bits(&pbc, 4, samplerate_index); //sample rate index put_bits(&pbc, 4, channels); put_bits(&pbc, 1, 0); //frame length - 1024 samples From c8e1955408968a0206e9ae749451a46542ca9674 Mon Sep 17 00:00:00 2001 From: Zhao Zhili Date: Fri, 7 Apr 2023 22:56:38 +0800 Subject: [PATCH 0674/2172] avformat/flvenc: avoid an extra allocate Signed-off-by: Zhao Zhili --- libavformat/flvenc.c | 30 +++++++++++++----------------- 1 file changed, 13 insertions(+), 17 deletions(-) diff --git a/libavformat/flvenc.c b/libavformat/flvenc.c index 7873a0080f8..721f0628114 100644 --- a/libavformat/flvenc.c +++ b/libavformat/flvenc.c @@ -117,12 +117,9 @@ typedef struct FLVContext { AVCodecParameters *data_par; int flags; + int64_t last_ts[FLV_STREAM_TYPE_NB]; } FLVContext; -typedef struct FLVStreamContext { - int64_t last_ts; ///< last timestamp for each stream -} FLVStreamContext; - static int get_audio_flags(AVFormatContext *s, AVCodecParameters *par) { int flags = (par->bits_per_coded_sample == 16) ? FLV_SAMPLESSIZE_16BIT @@ -609,9 +606,15 @@ static int flv_init(struct AVFormatContext *s) int i; FLVContext *flv = s->priv_data; + if (s->nb_streams > FLV_STREAM_TYPE_NB) { + av_log(s, AV_LOG_ERROR, "invalid number of streams %d\n", + s->nb_streams); + return AVERROR(EINVAL); + } + for (i = 0; i < s->nb_streams; i++) { AVCodecParameters *par = s->streams[i]->codecpar; - FLVStreamContext *sc; + switch (par->codec_type) { case AVMEDIA_TYPE_VIDEO: if (s->streams[i]->avg_frame_rate.den && @@ -675,12 +678,7 @@ static int flv_init(struct AVFormatContext *s) return AVERROR(EINVAL); } avpriv_set_pts_info(s->streams[i], 32, 1, 1000); /* 32 bit pts in ms */ - - sc = av_mallocz(sizeof(FLVStreamContext)); - if (!sc) - return AVERROR(ENOMEM); - s->streams[i]->priv_data = sc; - sc->last_ts = -1; + flv->last_ts[i] = -1; } flv->delay = AV_NOPTS_VALUE; @@ -783,10 +781,9 @@ static int flv_write_trailer(AVFormatContext *s) /* Add EOS tag */ for (i = 0; i < s->nb_streams; i++) { AVCodecParameters *par = s->streams[i]->codecpar; - FLVStreamContext *sc = s->streams[i]->priv_data; if (par->codec_type == AVMEDIA_TYPE_VIDEO && (par->codec_id == AV_CODEC_ID_H264 || par->codec_id == AV_CODEC_ID_MPEG4)) - put_eos_tag(pb, sc->last_ts, par->codec_id); + put_eos_tag(pb, flv->last_ts[i], par->codec_id); } } @@ -821,7 +818,6 @@ static int flv_write_packet(AVFormatContext *s, AVPacket *pkt) AVIOContext *pb = s->pb; AVCodecParameters *par = s->streams[pkt->stream_index]->codecpar; FLVContext *flv = s->priv_data; - FLVStreamContext *sc = s->streams[pkt->stream_index]->priv_data; unsigned ts; int size = pkt->size; uint8_t *data = NULL; @@ -919,13 +915,13 @@ static int flv_write_packet(AVFormatContext *s, AVPacket *pkt) } /* check Speex packet duration */ - if (par->codec_id == AV_CODEC_ID_SPEEX && ts - sc->last_ts > 160) + if (par->codec_id == AV_CODEC_ID_SPEEX && ts - flv->last_ts[pkt->stream_index] > 160) av_log(s, AV_LOG_WARNING, "Warning: Speex stream has more than " "8 frames per packet. Adobe Flash " "Player cannot handle this!\n"); - if (sc->last_ts < ts) - sc->last_ts = ts; + if (flv->last_ts[pkt->stream_index] < ts) + flv->last_ts[pkt->stream_index] = ts; if (size + flags_size >= 1<<24) { av_log(s, AV_LOG_ERROR, "Too large packet with size %u >= %u\n", From 19c2dc677f81c940aebe63ed09dacf5c725f0b35 Mon Sep 17 00:00:00 2001 From: James Almer Date: Wed, 12 Apr 2023 22:52:05 -0300 Subject: [PATCH 0675/2172] avformat/concatf: check if any nodes were allocated Fixes ticket #10304 Signed-off-by: James Almer --- libavformat/concat.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/libavformat/concat.c b/libavformat/concat.c index dc0985e40cf..825e43a7fad 100644 --- a/libavformat/concat.c +++ b/libavformat/concat.c @@ -296,6 +296,8 @@ static av_cold int concatf_open(URLContext *h, const char *uri, int flags) av_bprint_finalize(&bp, NULL); data->length = i; + if (!data->length) + err = AVERROR_INVALIDDATA; if (err < 0) concat_close(h); From 92885f26817b6b2515ac9fd5410c9e8be64bd0c0 Mon Sep 17 00:00:00 2001 From: James Almer Date: Wed, 12 Apr 2023 22:53:33 -0300 Subject: [PATCH 0676/2172] avutil/wchar_filename: propagate MultiByteToWideChar() and WideCharToMultiByte() failures Don't return success if the string could not be converted. Signed-off-by: James Almer --- libavutil/wchar_filename.h | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/libavutil/wchar_filename.h b/libavutil/wchar_filename.h index 9a04a069f1f..fbc0a551468 100644 --- a/libavutil/wchar_filename.h +++ b/libavutil/wchar_filename.h @@ -32,7 +32,8 @@ static inline int utf8towchar(const char *filename_utf8, wchar_t **filename_w) num_chars = MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, filename_utf8, -1, NULL, 0); if (num_chars <= 0) { *filename_w = NULL; - return 0; + errno = EINVAL; + return -1; } *filename_w = (wchar_t *)av_calloc(num_chars, sizeof(wchar_t)); if (!*filename_w) { @@ -52,7 +53,8 @@ static inline int wchartocp(unsigned int code_page, const wchar_t *filename_w, NULL, 0, NULL, NULL); if (num_chars <= 0) { *filename = NULL; - return 0; + errno = EINVAL; + return -1; } *filename = (char*)av_malloc_array(num_chars, sizeof *filename); if (!*filename) { From 5cda6b94f45c347805cbd5a0c7ed1d712b5722d7 Mon Sep 17 00:00:00 2001 From: James Almer Date: Thu, 13 Apr 2023 09:58:25 -0300 Subject: [PATCH 0677/2172] avcodec/aacpsy: clip global_quality within the psy_vbr_map array boundaries Fixes ticket #10317. Signed-off-by: James Almer --- libavcodec/aacpsy.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavcodec/aacpsy.c b/libavcodec/aacpsy.c index 4c5ab2c9d5d..933369e445a 100644 --- a/libavcodec/aacpsy.c +++ b/libavcodec/aacpsy.c @@ -267,7 +267,7 @@ static av_cold void lame_window_init(AacPsyContext *ctx, AVCodecContext *avctx) AacPsyChannel *pch = &ctx->ch[i]; if (avctx->flags & AV_CODEC_FLAG_QSCALE) - pch->attack_threshold = psy_vbr_map[avctx->global_quality / FF_QP2LAMBDA].st_lrm; + pch->attack_threshold = psy_vbr_map[av_clip(avctx->global_quality / FF_QP2LAMBDA, 0, 10)].st_lrm; else pch->attack_threshold = lame_calc_attack_threshold(avctx->bit_rate / avctx->ch_layout.nb_channels / 1000); From 7c6e26a18403376987541f1ca801ae225f8ee6d4 Mon Sep 17 00:00:00 2001 From: James Almer Date: Thu, 13 Apr 2023 10:19:57 -0300 Subject: [PATCH 0678/2172] avcodec/mp_cmp: reject invalid comparison function values Fixes tickets #10306 and #10318. Signed-off-by: James Almer --- libavcodec/dvenc.c | 4 +++- libavcodec/me_cmp.c | 9 +++++++-- libavcodec/me_cmp.h | 2 +- libavcodec/motion_est.c | 11 +++++++---- libavcodec/mpegvideo_enc.c | 6 ++++-- libavcodec/snowenc.c | 6 ++++-- 6 files changed, 26 insertions(+), 12 deletions(-) diff --git a/libavcodec/dvenc.c b/libavcodec/dvenc.c index 11dd5763af6..cd442b524df 100644 --- a/libavcodec/dvenc.c +++ b/libavcodec/dvenc.c @@ -104,7 +104,9 @@ static av_cold int dvvideo_encode_init(AVCodecContext *avctx) ff_fdctdsp_init(&fdsp, avctx); ff_me_cmp_init(&mecc, avctx); ff_pixblockdsp_init(&pdsp, avctx); - ff_set_cmp(&mecc, mecc.ildct_cmp, avctx->ildct_cmp); + ret = ff_set_cmp(&mecc, mecc.ildct_cmp, avctx->ildct_cmp); + if (ret < 0) + return AVERROR(EINVAL); s->get_pixels = pdsp.get_pixels; s->ildct_cmp = mecc.ildct_cmp[5]; diff --git a/libavcodec/me_cmp.c b/libavcodec/me_cmp.c index e2f9f84b055..cd05e63ffd6 100644 --- a/libavcodec/me_cmp.c +++ b/libavcodec/me_cmp.c @@ -473,8 +473,9 @@ static int zero_cmp(MpegEncContext *s, const uint8_t *a, const uint8_t *b, return 0; } -void ff_set_cmp(MECmpContext *c, me_cmp_func *cmp, int type) +int ff_set_cmp(MECmpContext *c, me_cmp_func *cmp, int type) { + int ret = 0; int i; memset(cmp, 0, sizeof(void *) * 6); @@ -533,9 +534,13 @@ void ff_set_cmp(MECmpContext *c, me_cmp_func *cmp, int type) #endif default: av_log(NULL, AV_LOG_ERROR, - "internal error in cmp function selection\n"); + "invalid cmp function selection\n"); + ret = -1; + break; } } + + return ret; } #define BUTTERFLY2(o1, o2, i1, i2) \ diff --git a/libavcodec/me_cmp.h b/libavcodec/me_cmp.h index 90ea76c891a..aefd32a7dc9 100644 --- a/libavcodec/me_cmp.h +++ b/libavcodec/me_cmp.h @@ -89,7 +89,7 @@ void ff_me_cmp_init_ppc(MECmpContext *c, AVCodecContext *avctx); void ff_me_cmp_init_x86(MECmpContext *c, AVCodecContext *avctx); void ff_me_cmp_init_mips(MECmpContext *c, AVCodecContext *avctx); -void ff_set_cmp(MECmpContext *c, me_cmp_func *cmp, int type); +int ff_set_cmp(MECmpContext *c, me_cmp_func *cmp, int type); void ff_dsputil_init_dwt(MECmpContext *c); diff --git a/libavcodec/motion_est.c b/libavcodec/motion_est.c index d17ffe42b43..df9d1befa83 100644 --- a/libavcodec/motion_est.c +++ b/libavcodec/motion_est.c @@ -309,6 +309,7 @@ int ff_init_me(MpegEncContext *s){ MotionEstContext * const c= &s->me; int cache_size= FFMIN(ME_MAP_SIZE>>ME_MAP_SHIFT, 1<avctx->dia_size)&255, FFABS(s->avctx->pre_dia_size)&255); + int ret; if(FFMIN(s->avctx->dia_size, s->avctx->pre_dia_size) < -FFMIN(ME_MAP_SIZE, MAX_SAB_SIZE)){ av_log(s->avctx, AV_LOG_ERROR, "ME_MAP size is too small for SAB diamond\n"); @@ -324,10 +325,12 @@ int ff_init_me(MpegEncContext *s){ av_log(s->avctx, AV_LOG_INFO, "ME_MAP size may be a little small for the selected diamond size\n"); } - ff_set_cmp(&s->mecc, s->mecc.me_pre_cmp, c->avctx->me_pre_cmp); - ff_set_cmp(&s->mecc, s->mecc.me_cmp, c->avctx->me_cmp); - ff_set_cmp(&s->mecc, s->mecc.me_sub_cmp, c->avctx->me_sub_cmp); - ff_set_cmp(&s->mecc, s->mecc.mb_cmp, c->avctx->mb_cmp); + ret = ff_set_cmp(&s->mecc, s->mecc.me_pre_cmp, c->avctx->me_pre_cmp); + ret |= ff_set_cmp(&s->mecc, s->mecc.me_cmp, c->avctx->me_cmp); + ret |= ff_set_cmp(&s->mecc, s->mecc.me_sub_cmp, c->avctx->me_sub_cmp); + ret |= ff_set_cmp(&s->mecc, s->mecc.mb_cmp, c->avctx->mb_cmp); + if (ret < 0) + return ret; c->flags = get_flags(c, 0, c->avctx->me_cmp &FF_CMP_CHROMA); c->sub_flags= get_flags(c, 0, c->avctx->me_sub_cmp&FF_CMP_CHROMA); diff --git a/libavcodec/mpegvideo_enc.c b/libavcodec/mpegvideo_enc.c index 7d3c8875f29..bcd2f9ef1d6 100644 --- a/libavcodec/mpegvideo_enc.c +++ b/libavcodec/mpegvideo_enc.c @@ -902,8 +902,10 @@ av_cold int ff_mpv_encode_init(AVCodecContext *avctx) s->quant_precision = 5; - 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); + ret = ff_set_cmp(&s->mecc, s->mecc.ildct_cmp, avctx->ildct_cmp); + ret |= ff_set_cmp(&s->mecc, s->mecc.frame_skip_cmp, s->frame_skip_cmp); + if (ret < 0) + return AVERROR(EINVAL); if (CONFIG_H263_ENCODER && s->out_format == FMT_H263) { ff_h263_encode_init(s); diff --git a/libavcodec/snowenc.c b/libavcodec/snowenc.c index 4cf7ff1145e..31a48972a50 100644 --- a/libavcodec/snowenc.c +++ b/libavcodec/snowenc.c @@ -130,8 +130,10 @@ static av_cold int encode_init(AVCodecContext *avctx) if (ret) return ret; - ff_set_cmp(&s->mecc, s->mecc.me_cmp, s->avctx->me_cmp); - ff_set_cmp(&s->mecc, s->mecc.me_sub_cmp, s->avctx->me_sub_cmp); + ret = ff_set_cmp(&s->mecc, s->mecc.me_cmp, s->avctx->me_cmp); + ret |= ff_set_cmp(&s->mecc, s->mecc.me_sub_cmp, s->avctx->me_sub_cmp); + if (ret < 0) + return AVERROR(EINVAL); s->input_picture = av_frame_alloc(); if (!s->input_picture) From 27e7857bd1127974ffe1512293abee83b1035194 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Sun, 9 Apr 2023 13:18:42 +0200 Subject: [PATCH 0679/2172] avcodec/huffyuvdec: Fix undefined behavior with shift Fixes: left shift of negative value -1 Fixes: 57554/clusterfuzz-testcase-minimized-ffmpeg_AV_CODEC_ID_FFVHUFF_fuzzer-4853603839115264 Found-by: continuous fuzzing process https://github.com/google/oss-fuzz/tree/master/projects/ffmpeg Signed-off-by: Michael Niedermayer --- libavcodec/huffyuvdec.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libavcodec/huffyuvdec.c b/libavcodec/huffyuvdec.c index 7d3515cc889..8ba67bbdeb5 100644 --- a/libavcodec/huffyuvdec.c +++ b/libavcodec/huffyuvdec.c @@ -695,9 +695,9 @@ static void decode_422_bitstream(HYuvDecContext *s, int count) /* TODO instead of restarting the read when the code isn't in the first level * of the joint table, jump into the 2nd level of the individual table. */ #define READ_2PIX_PLANE16(dst0, dst1, plane){\ - dst0 = get_vlc2(&s->gb, s->vlc[plane].table, VLC_BITS, 3)<<2;\ + dst0 = get_vlc2(&s->gb, s->vlc[plane].table, VLC_BITS, 3)*4;\ dst0 += get_bits(&s->gb, 2);\ - dst1 = get_vlc2(&s->gb, s->vlc[plane].table, VLC_BITS, 3)<<2;\ + dst1 = get_vlc2(&s->gb, s->vlc[plane].table, VLC_BITS, 3)*4;\ dst1 += get_bits(&s->gb, 2);\ } static void decode_plane_bitstream(HYuvDecContext *s, int width, int plane) From 80ac1fd1483a4b3c92a6e59d24cb050dfecb90df Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Sun, 9 Apr 2023 14:31:16 +0200 Subject: [PATCH 0680/2172] avcodec/hevc_ps: Check num_ref_loc_offsets Fixes: Writing arbitrarily over the array end Fixes: 57812/clusterfuzz-testcase-minimized-ffmpeg_DEMUXER_fuzzer-4536557859373056 Found-by: continuous fuzzing process https://github.com/google/oss-fuzz/tree/master/projects/ffmpeg Signed-off-by: Michael Niedermayer --- libavcodec/hevc_ps.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/libavcodec/hevc_ps.c b/libavcodec/hevc_ps.c index 348e4d8de2d..be1d668c263 100644 --- a/libavcodec/hevc_ps.c +++ b/libavcodec/hevc_ps.c @@ -1392,6 +1392,10 @@ static int pps_multilayer_extension(GetBitContext *gb, AVCodecContext *avctx, pps->pps_scaling_list_ref_layer_id = get_bits(gb, 6); pps->num_ref_loc_offsets = get_ue_golomb_long(gb); + if (pps->num_ref_loc_offsets > FF_ARRAY_ELEMS(pps->ref_loc_offset_layer_id)) { + pps->num_ref_loc_offsets = 0; + return AVERROR_INVALIDDATA; + } for (int i = 0; i < pps->num_ref_loc_offsets; i++) { pps->ref_loc_offset_layer_id[i] = get_bits(gb, 6); pps->scaled_ref_layer_offset_present_flag[i] = get_bits1(gb); From 0ecda4fbce8e77152e9b450c4efa8c1b81c8982e Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Sun, 9 Apr 2023 14:48:37 +0200 Subject: [PATCH 0681/2172] avcodec/rka: Fix signed integer overflow in decode_filter() Fixes: signed integer overflow: -631553 * 32768 cannot be represented in type 'int' Fixes: 57814/clusterfuzz-testcase-minimized-ffmpeg_AV_CODEC_ID_RKA_fuzzer-4614661233573888 Found-by: continuous fuzzing process https://github.com/google/oss-fuzz/tree/master/projects/ffmpeg Signed-off-by: Michael Niedermayer --- libavcodec/rka.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavcodec/rka.c b/libavcodec/rka.c index 2212e3f9306..3e86d83819c 100644 --- a/libavcodec/rka.c +++ b/libavcodec/rka.c @@ -737,7 +737,7 @@ static int decode_filter(RKAContext *s, ChContext *ctx, ACoder *ac, int off, uns } ctx->buf0[off] = ctx->buf1[off] + ctx->buf0[off + -1]; } else { - val *= 1 << ctx->cmode; + val *= 1U << ctx->cmode; sum += ctx->buf0[off + -1] + val; switch (s->bps) { case 16: sum = av_clip_int16(sum); break; From 5366ae12b9ba60404822f6b39b41f6c0d98a7c8a Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Sun, 9 Apr 2023 15:18:55 +0200 Subject: [PATCH 0682/2172] avcodec/escape124: Check that blocks are allocated before use Fixes: NULL pointer dereference Fixes: 57819/clusterfuzz-testcase-minimized-ffmpeg_AV_CODEC_ID_ESCAPE124_fuzzer-5077280228769792 Found-by: continuous fuzzing process https://github.com/google/oss-fuzz/tree/master/projects/ffmpeg Signed-off-by: Michael Niedermayer --- libavcodec/escape124.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavcodec/escape124.c b/libavcodec/escape124.c index e8a8395f4b1..592de09a9fd 100644 --- a/libavcodec/escape124.c +++ b/libavcodec/escape124.c @@ -155,7 +155,7 @@ static MacroBlock decode_macroblock(Escape124Context* s, GetBitContext* gb, // This condition can occur with invalid bitstreams and // *codebook_index == 2 - if (block_index >= s->codebooks[*codebook_index].size) + if (block_index >= s->codebooks[*codebook_index].size || !s->codebooks[*codebook_index].blocks) return (MacroBlock) { { 0 } }; return s->codebooks[*codebook_index].blocks[block_index]; From fa618f5f492f94d19dd8d32bcea084523fb4e2d8 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Sun, 9 Apr 2023 15:31:32 +0200 Subject: [PATCH 0683/2172] Revert "avcodec/er: remove check for fields" Fixes: out of array write on x86-32 Fixes: 57825/clusterfuzz-testcase-minimized-ffmpeg_AV_CODEC_ID_MPEG2VIDEO_fuzzer-6094366187061248 Fixes: 57829/clusterfuzz-testcase-minimized-ffmpeg_AV_CODEC_ID_MPEG2VIDEO_fuzzer-4526419991724032 Found-by: continuous fuzzing process https://github.com/google/oss-fuzz/tree/master/projects/ffmpeg This reverts commit f7abe92bd7939b6aeeb2393fe141033e733305d4. --- libavcodec/error_resilience.c | 9 ++------- libavcodec/error_resilience.h | 1 - 2 files changed, 2 insertions(+), 8 deletions(-) diff --git a/libavcodec/error_resilience.c b/libavcodec/error_resilience.c index bd7050062ce..2aa6f1d8640 100644 --- a/libavcodec/error_resilience.c +++ b/libavcodec/error_resilience.c @@ -805,7 +805,8 @@ void ff_er_frame_start(ERContext *s) static int er_supported(ERContext *s) { if(s->avctx->hwaccel && s->avctx->hwaccel->decode_slice || - !s->cur_pic.f + !s->cur_pic.f || + s->cur_pic.field_picture ) return 0; return 1; @@ -907,12 +908,6 @@ void ff_er_frame_end(ERContext *s) (s->avctx->skip_top + s->avctx->skip_bottom)) { return; } - - if (!s->warned_fields && (s->cur_pic.field_picture || s->cur_pic.f->interlaced_frame)) { - av_log(s->avctx, AV_LOG_WARNING, "Error concealment is not fully implemented for field pictures.\n"); - s->warned_fields = 1; - } - linesize = s->cur_pic.f->linesize; if ( s->avctx->codec_id == AV_CODEC_ID_MPEG2VIDEO diff --git a/libavcodec/error_resilience.h b/libavcodec/error_resilience.h index 55efacaccc5..47cc8a4fc67 100644 --- a/libavcodec/error_resilience.h +++ b/libavcodec/error_resilience.h @@ -87,7 +87,6 @@ typedef struct ERContext { int (*mv)[2][4][2], int mb_x, int mb_y, int mb_intra, int mb_skipped); void *opaque; - int warned_fields; } ERContext; void ff_er_frame_start(ERContext *s); From c66e13cbac72bf26be28d5dcff451e89f882a2c2 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Sat, 8 Apr 2023 00:25:43 +0200 Subject: [PATCH 0684/2172] avcodec/jpeg2000dec: Add YA16 support Signed-off-by: Michael Niedermayer --- libavcodec/jpeg2000dec.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/libavcodec/jpeg2000dec.c b/libavcodec/jpeg2000dec.c index c2b81ec103d..da7152646b4 100644 --- a/libavcodec/jpeg2000dec.c +++ b/libavcodec/jpeg2000dec.c @@ -449,6 +449,10 @@ static int get_siz(Jpeg2000DecoderContext *s) s->cdx[0] == s->cdx[1] && s->cdy[0] == s->cdy[1]) { s->avctx->pix_fmt = AV_PIX_FMT_YA8; i = 0; + } else if (ncomponents == 2 && s->precision == 16 && + s->cdx[0] == s->cdx[1] && s->cdy[0] == s->cdy[1]) { + s->avctx->pix_fmt = AV_PIX_FMT_YA16; + i = 0; } else if (ncomponents == 1 && s->precision == 8) { s->avctx->pix_fmt = AV_PIX_FMT_GRAY8; i = 0; From a3f49168dcbf3ad7c60db065f40af60427a55a96 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Sat, 8 Apr 2023 00:25:59 +0200 Subject: [PATCH 0685/2172] avcodec/j2kenc: Add YA8 and YA16 support Signed-off-by: Michael Niedermayer --- libavcodec/j2kenc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavcodec/j2kenc.c b/libavcodec/j2kenc.c index b924396d7c0..2b0c58cff43 100644 --- a/libavcodec/j2kenc.c +++ b/libavcodec/j2kenc.c @@ -1853,7 +1853,7 @@ const FFCodec ff_jpeg2000_encoder = { AV_PIX_FMT_YUV440P, AV_PIX_FMT_YUV440P10, AV_PIX_FMT_YUV440P12, AV_PIX_FMT_YUV411P, AV_PIX_FMT_YUV410P, - + AV_PIX_FMT_YA8, AV_PIX_FMT_YA16, AV_PIX_FMT_RGBA, AV_PIX_FMT_RGBA64, AV_PIX_FMT_GBRAP, AV_PIX_FMT_GBRAP10, AV_PIX_FMT_GBRAP12, AV_PIX_FMT_GBRAP16, AV_PIX_FMT_YUVA420P, AV_PIX_FMT_YUVA420P9, AV_PIX_FMT_YUVA420P10, AV_PIX_FMT_YUVA420P16, From f8d0b13de5fe1a3d158dcc6f419c45c368b1dd4f Mon Sep 17 00:00:00 2001 From: Jiasheng Jiang Date: Mon, 17 Apr 2023 10:32:12 +0800 Subject: [PATCH 0686/2172] avcodec/rv34: Add check for av_malloc Add the check for the return value of the av_malloc in order to avoid NULL pointer deference. Fixes: b86ab38137 ("Add weighted motion compensation for RV40 B-frames") Signed-off-by: Jiasheng Jiang --- libavcodec/rv34.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/libavcodec/rv34.c b/libavcodec/rv34.c index 45f64666f85..51f18147af8 100644 --- a/libavcodec/rv34.c +++ b/libavcodec/rv34.c @@ -1692,6 +1692,8 @@ int ff_rv34_decode_frame(AVCodecContext *avctx, AVFrame *pict, int i; r->tmp_b_block_base = av_malloc(s->linesize * 48); + if (!r->tmp_b_block_base) + return AVERROR(ENOMEM); for (i = 0; i < 2; i++) r->tmp_b_block_y[i] = r->tmp_b_block_base + i * 16 * s->linesize; From b9ba036680b4164f6e415a85877dfa659ae4dde1 Mon Sep 17 00:00:00 2001 From: Jiasheng Jiang Date: Mon, 17 Apr 2023 10:32:51 +0800 Subject: [PATCH 0687/2172] avcodec/msvideo1enc: Add check for av_malloc Add the check for the return value of the av_malloc in order to avoid NULL pointer deference. Fixes: e4be3485af ("MS Video 1 encoder") Signed-off-by: Jiasheng Jiang --- libavcodec/msvideo1enc.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/libavcodec/msvideo1enc.c b/libavcodec/msvideo1enc.c index 36cfd39a854..1fb8be88835 100644 --- a/libavcodec/msvideo1enc.c +++ b/libavcodec/msvideo1enc.c @@ -84,6 +84,8 @@ static int encode_frame(AVCodecContext *avctx, AVPacket *pkt, if(!c->prev) c->prev = av_malloc(avctx->width * 3 * (avctx->height + 3)); + if (!c->prev) + return AVERROR(ENOMEM); prevptr = c->prev + avctx->width * 3 * (FFALIGN(avctx->height, 4) - 1); src = (const uint16_t*)(p->data[0] + p->linesize[0]*(FFALIGN(avctx->height, 4) - 1)); if(c->keyint >= avctx->keyint_min) From 1cd5a383d49f94b05699b234b0d3c98f2969b810 Mon Sep 17 00:00:00 2001 From: "jianfeng.zheng" Date: Fri, 31 Mar 2023 19:54:06 +0800 Subject: [PATCH 0688/2172] vaapi: support VAProfileH264High10 decoding see https://github.com/intel/libva/pull/664 Signed-off-by: jianfeng.zheng --- libavcodec/h264_slice.c | 9 ++++++++- libavcodec/vaapi_decode.c | 5 +++++ 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/libavcodec/h264_slice.c b/libavcodec/h264_slice.c index 7767e16cf15..d05b83a1216 100644 --- a/libavcodec/h264_slice.c +++ b/libavcodec/h264_slice.c @@ -809,8 +809,15 @@ static enum AVPixelFormat get_pixel_format(H264Context *h, int force_callback) *fmt++ = AV_PIX_FMT_YUV444P10; } else if (CHROMA422(h)) *fmt++ = AV_PIX_FMT_YUV422P10; - else + else { +#if CONFIG_H264_VAAPI_HWACCEL + // Just add as candidate. Whether VAProfileH264High10 usable or + // not is decided by vaapi_decode_make_config() defined in FFmpeg + // and vaQueryCodingProfile() defined in libva. + *fmt++ = AV_PIX_FMT_VAAPI; +#endif *fmt++ = AV_PIX_FMT_YUV420P10; + } break; case 12: if (CHROMA444(h)) { diff --git a/libavcodec/vaapi_decode.c b/libavcodec/vaapi_decode.c index ab8c12e3642..dd55cbd6f1c 100644 --- a/libavcodec/vaapi_decode.c +++ b/libavcodec/vaapi_decode.c @@ -398,6 +398,11 @@ static const struct { MAP(MPEG4, MPEG4_ADVANCED_SIMPLE, MPEG4AdvancedSimple), MAP(MPEG4, MPEG4_MAIN, MPEG4Main ), +#if VA_CHECK_VERSION(1, 18, 0) + MAP(H264, H264_HIGH_10_INTRA, + H264High10 ), + MAP(H264, H264_HIGH_10, H264High10 ), +#endif MAP(H264, H264_CONSTRAINED_BASELINE, H264ConstrainedBaseline), MAP(H264, H264_MAIN, H264Main ), From 65e537b83379d2d6f87343f9bd59968b21d949a3 Mon Sep 17 00:00:00 2001 From: "jianfeng.zheng" Date: Fri, 31 Mar 2023 19:54:23 +0800 Subject: [PATCH 0689/2172] vaapi: support VAProfileH264High10 encoding see https://github.com/intel/libva/pull/664 Signed-off-by: jianfeng.zheng --- libavcodec/vaapi_encode_h264.c | 27 ++++++++++++++++++++++----- 1 file changed, 22 insertions(+), 5 deletions(-) diff --git a/libavcodec/vaapi_encode_h264.c b/libavcodec/vaapi_encode_h264.c index 645f6a978db..9ad017d5402 100644 --- a/libavcodec/vaapi_encode_h264.c +++ b/libavcodec/vaapi_encode_h264.c @@ -23,6 +23,7 @@ #include "libavutil/avassert.h" #include "libavutil/common.h" +#include "libavutil/pixdesc.h" #include "libavutil/internal.h" #include "libavutil/opt.h" @@ -301,10 +302,21 @@ static int vaapi_encode_h264_init_sequence_params(AVCodecContext *avctx) H264RawPPS *pps = &priv->raw_pps; VAEncSequenceParameterBufferH264 *vseq = ctx->codec_sequence_params; VAEncPictureParameterBufferH264 *vpic = ctx->codec_picture_params; + const AVPixFmtDescriptor *desc; + int bit_depth; memset(sps, 0, sizeof(*sps)); memset(pps, 0, sizeof(*pps)); + desc = av_pix_fmt_desc_get(priv->common.input_frames->sw_format); + av_assert0(desc); + if (desc->nb_components == 1 || desc->log2_chroma_w != 1 || desc->log2_chroma_h != 1) { + av_log(avctx, AV_LOG_ERROR, "Chroma format of input pixel format " + "%s is not supported.\n", desc->name); + return AVERROR(EINVAL); + } + bit_depth = desc->comp[0].depth; + sps->nal_unit_header.nal_ref_idc = 3; sps->nal_unit_header.nal_unit_type = H264_NAL_SPS; @@ -314,11 +326,11 @@ static int vaapi_encode_h264_init_sequence_params(AVCodecContext *avctx) avctx->profile == FF_PROFILE_H264_MAIN) sps->constraint_set1_flag = 1; - if (avctx->profile == FF_PROFILE_H264_HIGH) + if (avctx->profile == FF_PROFILE_H264_HIGH || avctx->profile == FF_PROFILE_H264_HIGH_10) sps->constraint_set3_flag = ctx->gop_size == 1; if (avctx->profile == FF_PROFILE_H264_MAIN || - avctx->profile == FF_PROFILE_H264_HIGH) { + avctx->profile == FF_PROFILE_H264_HIGH || avctx->profile == FF_PROFILE_H264_HIGH_10) { sps->constraint_set4_flag = 1; sps->constraint_set5_flag = ctx->b_per_p == 0; } @@ -359,6 +371,8 @@ static int vaapi_encode_h264_init_sequence_params(AVCodecContext *avctx) sps->seq_parameter_set_id = 0; sps->chroma_format_idc = 1; + sps->bit_depth_luma_minus8 = bit_depth - 8; + sps->bit_depth_chroma_minus8 = bit_depth - 8; sps->log2_max_frame_num_minus4 = 4; sps->pic_order_cnt_type = ctx->max_b_depth ? 0 : 2; @@ -1144,6 +1158,9 @@ static av_cold int vaapi_encode_h264_configure(AVCodecContext *avctx) } static const VAAPIEncodeProfile vaapi_encode_h264_profiles[] = { +#if VA_CHECK_VERSION(1, 18, 0) + { FF_PROFILE_H264_HIGH_10, 10, 3, 1, 1, VAProfileH264High10 }, +#endif { FF_PROFILE_H264_HIGH, 8, 3, 1, 1, VAProfileH264High }, { FF_PROFILE_H264_MAIN, 8, 3, 1, 1, VAProfileH264Main }, { FF_PROFILE_H264_CONSTRAINED_BASELINE, @@ -1208,10 +1225,9 @@ static av_cold int vaapi_encode_h264_init(AVCodecContext *avctx) av_log(avctx, AV_LOG_ERROR, "H.264 extended profile " "is not supported.\n"); return AVERROR_PATCHWELCOME; - case FF_PROFILE_H264_HIGH_10: case FF_PROFILE_H264_HIGH_10_INTRA: - av_log(avctx, AV_LOG_ERROR, "H.264 10-bit profiles " - "are not supported.\n"); + av_log(avctx, AV_LOG_ERROR, "H.264 high 10 intra profile " + "is not supported.\n"); return AVERROR_PATCHWELCOME; case FF_PROFILE_H264_HIGH_422: case FF_PROFILE_H264_HIGH_422_INTRA: @@ -1304,6 +1320,7 @@ static const AVOption vaapi_encode_h264_options[] = { { PROFILE("constrained_baseline", FF_PROFILE_H264_CONSTRAINED_BASELINE) }, { PROFILE("main", FF_PROFILE_H264_MAIN) }, { PROFILE("high", FF_PROFILE_H264_HIGH) }, + { PROFILE("high10", FF_PROFILE_H264_HIGH_10) }, #undef PROFILE { "level", "Set level (level_idc)", From 89c9a3ac3542c3684e511607d88b265bfa6aa64f Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Thu, 13 Apr 2023 15:56:54 +0200 Subject: [PATCH 0690/2172] fftools/ffmpeg: avoid possible invalid reads with short -tag values Fixes #10319 and #10309. --- fftools/ffmpeg_demux.c | 8 ++++++-- fftools/ffmpeg_mux_init.c | 7 +++++-- 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/fftools/ffmpeg_demux.c b/fftools/ffmpeg_demux.c index b9849d1669f..d89e28b9f6f 100644 --- a/fftools/ffmpeg_demux.c +++ b/fftools/ffmpeg_demux.c @@ -736,8 +736,12 @@ static void add_input_streams(const OptionsContext *o, Demuxer *d) MATCH_PER_STREAM_OPT(codec_tags, str, codec_tag, ic, st); if (codec_tag) { uint32_t tag = strtol(codec_tag, &next, 0); - if (*next) - tag = AV_RL32(codec_tag); + if (*next) { + uint8_t buf[4] = { 0 }; + memcpy(buf, codec_tag, FFMIN(sizeof(buf), strlen(codec_tag))); + tag = AV_RL32(buf); + } + st->codecpar->codec_tag = tag; } diff --git a/fftools/ffmpeg_mux_init.c b/fftools/ffmpeg_mux_init.c index 62e5643a042..aab423464ca 100644 --- a/fftools/ffmpeg_mux_init.c +++ b/fftools/ffmpeg_mux_init.c @@ -610,8 +610,11 @@ static OutputStream *new_output_stream(Muxer *mux, const OptionsContext *o, MATCH_PER_STREAM_OPT(codec_tags, str, codec_tag, oc, st); if (codec_tag) { uint32_t tag = strtol(codec_tag, &next, 0); - if (*next) - tag = AV_RL32(codec_tag); + if (*next) { + uint8_t buf[4] = { 0 }; + memcpy(buf, codec_tag, FFMIN(sizeof(buf), strlen(codec_tag))); + tag = AV_RL32(buf); + } ost->st->codecpar->codec_tag = tag; if (ost->enc_ctx) ost->enc_ctx->codec_tag = tag; From a7f26b1c63bcbf7a8b59ce1908c5af53215814f4 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Mon, 10 Apr 2023 13:24:41 +0200 Subject: [PATCH 0691/2172] fftools/ffmpeg_mux_init: move new_output_stream() lower in the file Reduces the diff in the following commit. Temporarily add a forward declaration for new_output_stream(), it will be removed in the next commit. --- fftools/ffmpeg_mux_init.c | 487 +++++++++++++++++++------------------- 1 file changed, 245 insertions(+), 242 deletions(-) diff --git a/fftools/ffmpeg_mux_init.c b/fftools/ffmpeg_mux_init.c index aab423464ca..906b2d1a449 100644 --- a/fftools/ffmpeg_mux_init.c +++ b/fftools/ffmpeg_mux_init.c @@ -419,248 +419,7 @@ static MuxStream *mux_stream_alloc(Muxer *mux, enum AVMediaType type) } static OutputStream *new_output_stream(Muxer *mux, const OptionsContext *o, - enum AVMediaType type, InputStream *ist) -{ - AVFormatContext *oc = mux->fc; - MuxStream *ms; - OutputStream *ost; - const AVCodec *enc; - AVStream *st = avformat_new_stream(oc, NULL); - int ret = 0; - const char *bsfs = NULL, *time_base = NULL; - char *next, *codec_tag = NULL; - double qscale = -1; - int i; - - if (!st) - report_and_exit(AVERROR(ENOMEM)); - - if (oc->nb_streams - 1 < o->nb_streamid_map) - st->id = o->streamid_map[oc->nb_streams - 1]; - - ms = mux_stream_alloc(mux, type); - ost = &ms->ost; - - ms->muxing_queue = av_fifo_alloc2(8, sizeof(AVPacket*), 0); - if (!ms->muxing_queue) - report_and_exit(AVERROR(ENOMEM)); - ms->last_mux_dts = AV_NOPTS_VALUE; - - ost->st = st; - ost->ist = ist; - ost->kf.ref_pts = AV_NOPTS_VALUE; - st->codecpar->codec_type = type; - - ret = choose_encoder(o, oc, ost, &enc); - if (ret < 0) { - av_log(ost, AV_LOG_FATAL, "Error selecting an encoder\n"); - exit_program(1); - } - - if (enc) { - ost->enc_ctx = avcodec_alloc_context3(enc); - if (!ost->enc_ctx) - report_and_exit(AVERROR(ENOMEM)); - - ret = enc_alloc(&ost->enc, enc); - if (ret < 0) - report_and_exit(ret); - - av_strlcat(ms->log_name, "/", sizeof(ms->log_name)); - av_strlcat(ms->log_name, enc->name, sizeof(ms->log_name)); - } else { - av_strlcat(ms->log_name, "/copy", sizeof(ms->log_name)); - } - - ost->filtered_frame = av_frame_alloc(); - if (!ost->filtered_frame) - report_and_exit(AVERROR(ENOMEM)); - - ost->pkt = av_packet_alloc(); - if (!ost->pkt) - report_and_exit(AVERROR(ENOMEM)); - - if (ost->enc_ctx) { - AVCodecContext *enc = ost->enc_ctx; - AVIOContext *s = NULL; - char *buf = NULL, *arg = NULL, *preset = NULL; - const char *enc_stats_pre = NULL, *enc_stats_post = NULL, *mux_stats = NULL; - - ost->encoder_opts = filter_codec_opts(o->g->codec_opts, enc->codec_id, - oc, st, enc->codec); - - MATCH_PER_STREAM_OPT(presets, str, preset, oc, st); - ost->autoscale = 1; - MATCH_PER_STREAM_OPT(autoscale, i, ost->autoscale, oc, st); - if (preset && (!(ret = get_preset_file_2(preset, enc->codec->name, &s)))) { - AVBPrint bprint; - av_bprint_init(&bprint, 0, AV_BPRINT_SIZE_UNLIMITED); - do { - av_bprint_clear(&bprint); - buf = get_line(s, &bprint); - if (!buf[0] || buf[0] == '#') - continue; - if (!(arg = strchr(buf, '='))) { - av_log(ost, 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); - } while (!s->eof_reached); - av_bprint_finalize(&bprint, NULL); - avio_closep(&s); - } - if (ret) { - av_log(ost, AV_LOG_FATAL, - "Preset %s specified, but could not be opened.\n", preset); - exit_program(1); - } - - MATCH_PER_STREAM_OPT(enc_stats_pre, str, enc_stats_pre, oc, st); - if (enc_stats_pre && - (type == AVMEDIA_TYPE_VIDEO || type == AVMEDIA_TYPE_AUDIO)) { - const char *format = "{fidx} {sidx} {n} {t}"; - - MATCH_PER_STREAM_OPT(enc_stats_pre_fmt, str, format, oc, st); - - ret = enc_stats_init(ost, &ost->enc_stats_pre, 1, enc_stats_pre, format); - if (ret < 0) - exit_program(1); - } - - MATCH_PER_STREAM_OPT(enc_stats_post, str, enc_stats_post, oc, st); - if (enc_stats_post && - (type == AVMEDIA_TYPE_VIDEO || type == AVMEDIA_TYPE_AUDIO)) { - const char *format = "{fidx} {sidx} {n} {t}"; - - MATCH_PER_STREAM_OPT(enc_stats_post_fmt, str, format, oc, st); - - ret = enc_stats_init(ost, &ost->enc_stats_post, 0, enc_stats_post, format); - if (ret < 0) - exit_program(1); - } - - MATCH_PER_STREAM_OPT(mux_stats, str, mux_stats, oc, st); - if (mux_stats && - (type == AVMEDIA_TYPE_VIDEO || type == AVMEDIA_TYPE_AUDIO)) { - const char *format = "{fidx} {sidx} {n} {t}"; - - MATCH_PER_STREAM_OPT(mux_stats_fmt, str, format, oc, st); - - ret = enc_stats_init(ost, &ms->stats, 0, mux_stats, format); - if (ret < 0) - exit_program(1); - } - } else { - ost->encoder_opts = filter_codec_opts(o->g->codec_opts, AV_CODEC_ID_NONE, oc, st, NULL); - } - - - if (o->bitexact) { - ost->bitexact = 1; - } else if (ost->enc_ctx) { - ost->bitexact = check_opt_bitexact(ost->enc_ctx, ost->encoder_opts, "flags", - AV_CODEC_FLAG_BITEXACT); - } - - MATCH_PER_STREAM_OPT(time_bases, str, time_base, oc, st); - if (time_base) { - AVRational q; - if (av_parse_ratio(&q, time_base, INT_MAX, 0, NULL) < 0 || - q.num <= 0 || q.den <= 0) { - av_log(ost, AV_LOG_FATAL, "Invalid time base: %s\n", time_base); - exit_program(1); - } - st->time_base = q; - } - - MATCH_PER_STREAM_OPT(enc_time_bases, str, time_base, oc, st); - if (time_base) { - AVRational q; - if (av_parse_ratio(&q, time_base, INT_MAX, 0, NULL) < 0 || - q.den <= 0) { - av_log(ost, AV_LOG_FATAL, "Invalid time base: %s\n", time_base); - exit_program(1); - } - ost->enc_timebase = q; - } - - ms->max_frames = INT64_MAX; - MATCH_PER_STREAM_OPT(max_frames, i64, ms->max_frames, oc, st); - for (i = 0; inb_max_frames; i++) { - char *p = o->max_frames[i].specifier; - if (!*p && type != AVMEDIA_TYPE_VIDEO) { - av_log(ost, AV_LOG_WARNING, "Applying unspecific -frames to non video streams, maybe you meant -vframes ?\n"); - break; - } - } - - ost->copy_prior_start = -1; - MATCH_PER_STREAM_OPT(copy_prior_start, i, ost->copy_prior_start, oc ,st); - - MATCH_PER_STREAM_OPT(bitstream_filters, str, bsfs, oc, st); - if (bsfs && *bsfs) { - ret = av_bsf_list_parse_str(bsfs, &ms->bsf_ctx); - if (ret < 0) { - av_log(ost, AV_LOG_ERROR, "Error parsing bitstream filter sequence '%s': %s\n", bsfs, av_err2str(ret)); - exit_program(1); - } - } - - MATCH_PER_STREAM_OPT(codec_tags, str, codec_tag, oc, st); - if (codec_tag) { - uint32_t tag = strtol(codec_tag, &next, 0); - if (*next) { - uint8_t buf[4] = { 0 }; - memcpy(buf, codec_tag, FFMIN(sizeof(buf), strlen(codec_tag))); - tag = AV_RL32(buf); - } - ost->st->codecpar->codec_tag = tag; - if (ost->enc_ctx) - ost->enc_ctx->codec_tag = tag; - } - - MATCH_PER_STREAM_OPT(qscale, dbl, qscale, oc, st); - if (ost->enc_ctx && qscale >= 0) { - ost->enc_ctx->flags |= AV_CODEC_FLAG_QSCALE; - ost->enc_ctx->global_quality = FF_QP2LAMBDA * qscale; - } - - ms->max_muxing_queue_size = 128; - MATCH_PER_STREAM_OPT(max_muxing_queue_size, i, ms->max_muxing_queue_size, oc, st); - - ms->muxing_queue_data_threshold = 50*1024*1024; - MATCH_PER_STREAM_OPT(muxing_queue_data_threshold, i, ms->muxing_queue_data_threshold, oc, st); - - MATCH_PER_STREAM_OPT(bits_per_raw_sample, i, ost->bits_per_raw_sample, - oc, st); - - MATCH_PER_STREAM_OPT(fix_sub_duration_heartbeat, i, ost->fix_sub_duration_heartbeat, - oc, st); - - if (oc->oformat->flags & AVFMT_GLOBALHEADER && ost->enc_ctx) - ost->enc_ctx->flags |= AV_CODEC_FLAG_GLOBAL_HEADER; - - av_dict_copy(&ost->sws_dict, o->g->sws_dict, 0); - - av_dict_copy(&ost->swr_opts, o->g->swr_opts, 0); - if (ost->enc_ctx && av_get_exact_bits_per_sample(ost->enc_ctx->codec_id) == 24) - av_dict_set(&ost->swr_opts, "output_sample_bits", "24", 0); - - if (ost->ist) { - ost->ist->discard = 0; - ost->ist->st->discard = ost->ist->user_set_discard; - - if (!(ost->enc && (type == AVMEDIA_TYPE_VIDEO || type == AVMEDIA_TYPE_AUDIO))) - ist_output_add(ost->ist, ost); - } - ost->last_mux_dts = AV_NOPTS_VALUE; - - MATCH_PER_STREAM_OPT(copy_initial_nonkeyframes, i, - ost->copy_initial_nonkeyframes, oc, st); - - return ost; -} + enum AVMediaType type, InputStream *ist); static char *get_ost_filters(const OptionsContext *o, AVFormatContext *oc, OutputStream *ost) @@ -1101,6 +860,250 @@ static OutputStream *new_subtitle_stream(Muxer *mux, const OptionsContext *o, In return ost; } +static OutputStream *new_output_stream(Muxer *mux, const OptionsContext *o, + enum AVMediaType type, InputStream *ist) +{ + AVFormatContext *oc = mux->fc; + MuxStream *ms; + OutputStream *ost; + const AVCodec *enc; + AVStream *st = avformat_new_stream(oc, NULL); + int ret = 0; + const char *bsfs = NULL, *time_base = NULL; + char *next, *codec_tag = NULL; + double qscale = -1; + int i; + + if (!st) + report_and_exit(AVERROR(ENOMEM)); + + if (oc->nb_streams - 1 < o->nb_streamid_map) + st->id = o->streamid_map[oc->nb_streams - 1]; + + ms = mux_stream_alloc(mux, type); + ost = &ms->ost; + + ms->muxing_queue = av_fifo_alloc2(8, sizeof(AVPacket*), 0); + if (!ms->muxing_queue) + report_and_exit(AVERROR(ENOMEM)); + ms->last_mux_dts = AV_NOPTS_VALUE; + + ost->st = st; + ost->ist = ist; + ost->kf.ref_pts = AV_NOPTS_VALUE; + st->codecpar->codec_type = type; + + ret = choose_encoder(o, oc, ost, &enc); + if (ret < 0) { + av_log(ost, AV_LOG_FATAL, "Error selecting an encoder\n"); + exit_program(1); + } + + if (enc) { + ost->enc_ctx = avcodec_alloc_context3(enc); + if (!ost->enc_ctx) + report_and_exit(AVERROR(ENOMEM)); + + ret = enc_alloc(&ost->enc, enc); + if (ret < 0) + report_and_exit(ret); + + av_strlcat(ms->log_name, "/", sizeof(ms->log_name)); + av_strlcat(ms->log_name, enc->name, sizeof(ms->log_name)); + } else { + av_strlcat(ms->log_name, "/copy", sizeof(ms->log_name)); + } + + ost->filtered_frame = av_frame_alloc(); + if (!ost->filtered_frame) + report_and_exit(AVERROR(ENOMEM)); + + ost->pkt = av_packet_alloc(); + if (!ost->pkt) + report_and_exit(AVERROR(ENOMEM)); + + if (ost->enc_ctx) { + AVCodecContext *enc = ost->enc_ctx; + AVIOContext *s = NULL; + char *buf = NULL, *arg = NULL, *preset = NULL; + const char *enc_stats_pre = NULL, *enc_stats_post = NULL, *mux_stats = NULL; + + ost->encoder_opts = filter_codec_opts(o->g->codec_opts, enc->codec_id, + oc, st, enc->codec); + + MATCH_PER_STREAM_OPT(presets, str, preset, oc, st); + ost->autoscale = 1; + MATCH_PER_STREAM_OPT(autoscale, i, ost->autoscale, oc, st); + if (preset && (!(ret = get_preset_file_2(preset, enc->codec->name, &s)))) { + AVBPrint bprint; + av_bprint_init(&bprint, 0, AV_BPRINT_SIZE_UNLIMITED); + do { + av_bprint_clear(&bprint); + buf = get_line(s, &bprint); + if (!buf[0] || buf[0] == '#') + continue; + if (!(arg = strchr(buf, '='))) { + av_log(ost, 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); + } while (!s->eof_reached); + av_bprint_finalize(&bprint, NULL); + avio_closep(&s); + } + if (ret) { + av_log(ost, AV_LOG_FATAL, + "Preset %s specified, but could not be opened.\n", preset); + exit_program(1); + } + + MATCH_PER_STREAM_OPT(enc_stats_pre, str, enc_stats_pre, oc, st); + if (enc_stats_pre && + (type == AVMEDIA_TYPE_VIDEO || type == AVMEDIA_TYPE_AUDIO)) { + const char *format = "{fidx} {sidx} {n} {t}"; + + MATCH_PER_STREAM_OPT(enc_stats_pre_fmt, str, format, oc, st); + + ret = enc_stats_init(ost, &ost->enc_stats_pre, 1, enc_stats_pre, format); + if (ret < 0) + exit_program(1); + } + + MATCH_PER_STREAM_OPT(enc_stats_post, str, enc_stats_post, oc, st); + if (enc_stats_post && + (type == AVMEDIA_TYPE_VIDEO || type == AVMEDIA_TYPE_AUDIO)) { + const char *format = "{fidx} {sidx} {n} {t}"; + + MATCH_PER_STREAM_OPT(enc_stats_post_fmt, str, format, oc, st); + + ret = enc_stats_init(ost, &ost->enc_stats_post, 0, enc_stats_post, format); + if (ret < 0) + exit_program(1); + } + + MATCH_PER_STREAM_OPT(mux_stats, str, mux_stats, oc, st); + if (mux_stats && + (type == AVMEDIA_TYPE_VIDEO || type == AVMEDIA_TYPE_AUDIO)) { + const char *format = "{fidx} {sidx} {n} {t}"; + + MATCH_PER_STREAM_OPT(mux_stats_fmt, str, format, oc, st); + + ret = enc_stats_init(ost, &ms->stats, 0, mux_stats, format); + if (ret < 0) + exit_program(1); + } + } else { + ost->encoder_opts = filter_codec_opts(o->g->codec_opts, AV_CODEC_ID_NONE, oc, st, NULL); + } + + + if (o->bitexact) { + ost->bitexact = 1; + } else if (ost->enc_ctx) { + ost->bitexact = check_opt_bitexact(ost->enc_ctx, ost->encoder_opts, "flags", + AV_CODEC_FLAG_BITEXACT); + } + + MATCH_PER_STREAM_OPT(time_bases, str, time_base, oc, st); + if (time_base) { + AVRational q; + if (av_parse_ratio(&q, time_base, INT_MAX, 0, NULL) < 0 || + q.num <= 0 || q.den <= 0) { + av_log(ost, AV_LOG_FATAL, "Invalid time base: %s\n", time_base); + exit_program(1); + } + st->time_base = q; + } + + MATCH_PER_STREAM_OPT(enc_time_bases, str, time_base, oc, st); + if (time_base) { + AVRational q; + if (av_parse_ratio(&q, time_base, INT_MAX, 0, NULL) < 0 || + q.den <= 0) { + av_log(ost, AV_LOG_FATAL, "Invalid time base: %s\n", time_base); + exit_program(1); + } + ost->enc_timebase = q; + } + + ms->max_frames = INT64_MAX; + MATCH_PER_STREAM_OPT(max_frames, i64, ms->max_frames, oc, st); + for (i = 0; inb_max_frames; i++) { + char *p = o->max_frames[i].specifier; + if (!*p && type != AVMEDIA_TYPE_VIDEO) { + av_log(ost, AV_LOG_WARNING, "Applying unspecific -frames to non video streams, maybe you meant -vframes ?\n"); + break; + } + } + + ost->copy_prior_start = -1; + MATCH_PER_STREAM_OPT(copy_prior_start, i, ost->copy_prior_start, oc ,st); + + MATCH_PER_STREAM_OPT(bitstream_filters, str, bsfs, oc, st); + if (bsfs && *bsfs) { + ret = av_bsf_list_parse_str(bsfs, &ms->bsf_ctx); + if (ret < 0) { + av_log(ost, AV_LOG_ERROR, "Error parsing bitstream filter sequence '%s': %s\n", bsfs, av_err2str(ret)); + exit_program(1); + } + } + + MATCH_PER_STREAM_OPT(codec_tags, str, codec_tag, oc, st); + if (codec_tag) { + uint32_t tag = strtol(codec_tag, &next, 0); + if (*next) { + uint8_t buf[4] = { 0 }; + memcpy(buf, codec_tag, FFMIN(sizeof(buf), strlen(codec_tag))); + tag = AV_RL32(buf); + } + ost->st->codecpar->codec_tag = tag; + if (ost->enc_ctx) + ost->enc_ctx->codec_tag = tag; + } + + MATCH_PER_STREAM_OPT(qscale, dbl, qscale, oc, st); + if (ost->enc_ctx && qscale >= 0) { + ost->enc_ctx->flags |= AV_CODEC_FLAG_QSCALE; + ost->enc_ctx->global_quality = FF_QP2LAMBDA * qscale; + } + + ms->max_muxing_queue_size = 128; + MATCH_PER_STREAM_OPT(max_muxing_queue_size, i, ms->max_muxing_queue_size, oc, st); + + ms->muxing_queue_data_threshold = 50*1024*1024; + MATCH_PER_STREAM_OPT(muxing_queue_data_threshold, i, ms->muxing_queue_data_threshold, oc, st); + + MATCH_PER_STREAM_OPT(bits_per_raw_sample, i, ost->bits_per_raw_sample, + oc, st); + + MATCH_PER_STREAM_OPT(fix_sub_duration_heartbeat, i, ost->fix_sub_duration_heartbeat, + oc, st); + + if (oc->oformat->flags & AVFMT_GLOBALHEADER && ost->enc_ctx) + ost->enc_ctx->flags |= AV_CODEC_FLAG_GLOBAL_HEADER; + + av_dict_copy(&ost->sws_dict, o->g->sws_dict, 0); + + av_dict_copy(&ost->swr_opts, o->g->swr_opts, 0); + if (ost->enc_ctx && av_get_exact_bits_per_sample(ost->enc_ctx->codec_id) == 24) + av_dict_set(&ost->swr_opts, "output_sample_bits", "24", 0); + + if (ost->ist) { + ost->ist->discard = 0; + ost->ist->st->discard = ost->ist->user_set_discard; + + if (!(ost->enc && (type == AVMEDIA_TYPE_VIDEO || type == AVMEDIA_TYPE_AUDIO))) + ist_output_add(ost->ist, ost); + } + ost->last_mux_dts = AV_NOPTS_VALUE; + + MATCH_PER_STREAM_OPT(copy_initial_nonkeyframes, i, + ost->copy_initial_nonkeyframes, oc, st); + + return ost; +} + static void init_output_filter(OutputFilter *ofilter, const OptionsContext *o, Muxer *mux) { From 9bae55165d583a09209b4826af8a8d9ac67511b0 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Mon, 10 Apr 2023 13:57:46 +0200 Subject: [PATCH 0692/2172] fftools/ffmpeg_mux_init: restructure output stream creation Creating a new output stream of a given type is currently done by calling new__stream(), which all start by calling new_output_stream() to allocate the stream and do common init, followed by type-specific init. Reverse this structure - the caller now calls the common function ost_add() with the type as a parameter, which then calls the type-specific function internally. This will allow adding common code that runs after type-specific code in future commits. --- fftools/ffmpeg_mux_init.c | 89 +++++++++++++++------------------------ 1 file changed, 35 insertions(+), 54 deletions(-) diff --git a/fftools/ffmpeg_mux_init.c b/fftools/ffmpeg_mux_init.c index 906b2d1a449..3fa39e14560 100644 --- a/fftools/ffmpeg_mux_init.c +++ b/fftools/ffmpeg_mux_init.c @@ -418,9 +418,6 @@ static MuxStream *mux_stream_alloc(Muxer *mux, enum AVMediaType type) return ms; } -static OutputStream *new_output_stream(Muxer *mux, const OptionsContext *o, - enum AVMediaType type, InputStream *ist); - static char *get_ost_filters(const OptionsContext *o, AVFormatContext *oc, OutputStream *ost) { @@ -471,14 +468,13 @@ static void parse_matrix_coeffs(void *logctx, uint16_t *dest, const char *str) } } -static OutputStream *new_video_stream(Muxer *mux, const OptionsContext *o, InputStream *ist) +static void new_stream_video(Muxer *mux, const OptionsContext *o, + OutputStream *ost) { AVFormatContext *oc = mux->fc; AVStream *st; - OutputStream *ost; char *frame_rate = NULL, *max_frame_rate = NULL, *frame_aspect_ratio = NULL; - ost = new_output_stream(mux, o, AVMEDIA_TYPE_VIDEO, ist); st = ost->st; MATCH_PER_STREAM_OPT(frame_rates, str, frame_rate, oc, st); @@ -703,17 +699,14 @@ static OutputStream *new_video_stream(Muxer *mux, const OptionsContext *o, Input exit_program(1); } else check_streamcopy_filters(o, oc, ost, AVMEDIA_TYPE_VIDEO); - - return ost; } -static OutputStream *new_audio_stream(Muxer *mux, const OptionsContext *o, InputStream *ist) +static void new_stream_audio(Muxer *mux, const OptionsContext *o, + OutputStream *ost) { AVFormatContext *oc = mux->fc; AVStream *st; - OutputStream *ost; - ost = new_output_stream(mux, o, AVMEDIA_TYPE_AUDIO, ist); st = ost->st; @@ -801,49 +794,37 @@ static OutputStream *new_audio_stream(Muxer *mux, const OptionsContext *o, Input #endif } else check_streamcopy_filters(o, oc, ost, AVMEDIA_TYPE_AUDIO); - - return ost; } -static OutputStream *new_data_stream(Muxer *mux, const OptionsContext *o, InputStream *ist) +static void new_stream_data(Muxer *mux, const OptionsContext *o, + OutputStream *ost) { - OutputStream *ost; - - ost = new_output_stream(mux, o, AVMEDIA_TYPE_DATA, ist); if (ost->enc_ctx) { av_log(ost, AV_LOG_FATAL, "Data stream encoding not supported yet (only streamcopy)\n"); exit_program(1); } - - return ost; } -static OutputStream *new_unknown_stream(Muxer *mux, const OptionsContext *o, InputStream *ist) +static void new_stream_unknown(Muxer *mux, const OptionsContext *o, + OutputStream *ost) { - OutputStream *ost; - - ost = new_output_stream(mux, o, AVMEDIA_TYPE_UNKNOWN, ist); if (ost->enc_ctx) { av_log(ost, AV_LOG_FATAL, "Unknown stream encoding not supported yet (only streamcopy)\n"); exit_program(1); } - - return ost; } -static OutputStream *new_attachment_stream(Muxer *mux, const OptionsContext *o, InputStream *ist) +static void new_stream_attachment(Muxer *mux, const OptionsContext *o, + OutputStream *ost) { - OutputStream *ost = new_output_stream(mux, o, AVMEDIA_TYPE_ATTACHMENT, ist); ost->finished = 1; - return ost; } -static OutputStream *new_subtitle_stream(Muxer *mux, const OptionsContext *o, InputStream *ist) +static void new_stream_subtitle(Muxer *mux, const OptionsContext *o, + OutputStream *ost) { AVStream *st; - OutputStream *ost; - ost = new_output_stream(mux, o, AVMEDIA_TYPE_SUBTITLE, ist); st = ost->st; if (ost->enc_ctx) { @@ -856,12 +837,10 @@ static OutputStream *new_subtitle_stream(Muxer *mux, const OptionsContext *o, In exit_program(1); } } - - return ost; } -static OutputStream *new_output_stream(Muxer *mux, const OptionsContext *o, - enum AVMediaType type, InputStream *ist) +static OutputStream *ost_add(Muxer *mux, const OptionsContext *o, + enum AVMediaType type, InputStream *ist) { AVFormatContext *oc = mux->fc; MuxStream *ms; @@ -1101,6 +1080,15 @@ static OutputStream *new_output_stream(Muxer *mux, const OptionsContext *o, MATCH_PER_STREAM_OPT(copy_initial_nonkeyframes, i, ost->copy_initial_nonkeyframes, oc, st); + switch (type) { + case AVMEDIA_TYPE_VIDEO: new_stream_video (mux, o, ost); break; + case AVMEDIA_TYPE_AUDIO: new_stream_audio (mux, o, ost); break; + case AVMEDIA_TYPE_SUBTITLE: new_stream_subtitle (mux, o, ost); break; + case AVMEDIA_TYPE_DATA: new_stream_data (mux, o, ost); break; + case AVMEDIA_TYPE_ATTACHMENT: new_stream_attachment(mux, o, ost); break; + default: new_stream_unknown (mux, o, ost); break; + } + return ost; } @@ -1110,8 +1098,8 @@ static void init_output_filter(OutputFilter *ofilter, const OptionsContext *o, OutputStream *ost; switch (ofilter->type) { - case AVMEDIA_TYPE_VIDEO: ost = new_video_stream(mux, o, NULL); break; - case AVMEDIA_TYPE_AUDIO: ost = new_audio_stream(mux, o, NULL); break; + case AVMEDIA_TYPE_VIDEO: ost = ost_add(mux, o, AVMEDIA_TYPE_VIDEO, NULL); break; + case AVMEDIA_TYPE_AUDIO: ost = ost_add(mux, o, AVMEDIA_TYPE_AUDIO, NULL); break; default: av_log(mux, AV_LOG_FATAL, "Only video and audio filters are supported " "currently.\n"); @@ -1193,7 +1181,7 @@ static void map_auto_video(Muxer *mux, const OptionsContext *o) } } if (best_ist) - new_video_stream(mux, o, best_ist); + ost_add(mux, o, AVMEDIA_TYPE_VIDEO, best_ist); } static void map_auto_audio(Muxer *mux, const OptionsContext *o) @@ -1235,7 +1223,7 @@ static void map_auto_audio(Muxer *mux, const OptionsContext *o) } } if (best_ist) - new_audio_stream(mux, o, best_ist); + ost_add(mux, o, AVMEDIA_TYPE_AUDIO, best_ist); } static void map_auto_subtitle(Muxer *mux, const OptionsContext *o) @@ -1270,7 +1258,7 @@ static void map_auto_subtitle(Muxer *mux, const OptionsContext *o) input_descriptor && output_descriptor && (!input_descriptor->props || !output_descriptor->props)) { - new_subtitle_stream(mux, o, ist); + ost_add(mux, o, AVMEDIA_TYPE_SUBTITLE, ist); break; } } @@ -1290,7 +1278,7 @@ static void map_auto_data(Muxer *mux, const OptionsContext *o) continue; if (ist->st->codecpar->codec_type == AVMEDIA_TYPE_DATA && ist->st->codecpar->codec_id == codec_id ) - new_data_stream(mux, o, ist); + ost_add(mux, o, AVMEDIA_TYPE_DATA, ist); } } @@ -1339,18 +1327,8 @@ static void map_manual(Muxer *mux, const OptionsContext *o, const StreamMap *map if(o-> data_disable && ist->st->codecpar->codec_type == AVMEDIA_TYPE_DATA) return; - switch (ist->st->codecpar->codec_type) { - case AVMEDIA_TYPE_VIDEO: new_video_stream (mux, o, ist); break; - case AVMEDIA_TYPE_AUDIO: new_audio_stream (mux, o, ist); break; - case AVMEDIA_TYPE_SUBTITLE: new_subtitle_stream (mux, o, ist); break; - case AVMEDIA_TYPE_DATA: new_data_stream (mux, o, ist); break; - case AVMEDIA_TYPE_ATTACHMENT: new_attachment_stream(mux, o, ist); break; - case AVMEDIA_TYPE_UNKNOWN: - if (copy_unknown_streams) { - new_unknown_stream (mux, o, ist); - break; - } - default: + if (ist->st->codecpar->codec_type == AVMEDIA_TYPE_UNKNOWN && + !copy_unknown_streams) { av_log(mux, ignore_unknown_streams ? AV_LOG_WARNING : AV_LOG_FATAL, "Cannot map stream #%d:%d - unsupported type.\n", map->file_index, map->stream_index); @@ -1361,7 +1339,10 @@ static void map_manual(Muxer *mux, const OptionsContext *o, const StreamMap *map "If you want them copied, please use -copy_unknown\n"); exit_program(1); } + return; } + + ost_add(mux, o, ist->st->codecpar->codec_type, ist); } } @@ -1395,7 +1376,7 @@ static void of_add_attachments(Muxer *mux, const OptionsContext *o) avio_read(pb, attachment, len); memset(attachment + len, 0, AV_INPUT_BUFFER_PADDING_SIZE); - ost = new_attachment_stream(mux, o, NULL); + ost = ost_add(mux, o, AVMEDIA_TYPE_ATTACHMENT, NULL); ost->attachment_filename = o->attachments[i]; ost->st->codecpar->extradata = attachment; ost->st->codecpar->extradata_size = len; From 12f3f41bbff75efb6f25da9ae470102103707aec Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Mon, 10 Apr 2023 15:10:34 +0200 Subject: [PATCH 0693/2172] fftools/ffmpeg: move init_output_stream_streamcopy() to ffmpeg_mux_init Everything in it can be done immediately when creating the output stream, there is no reason to postpone it. --- fftools/ffmpeg.c | 136 ------------------------------------ fftools/ffmpeg_mux_init.c | 143 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 143 insertions(+), 136 deletions(-) diff --git a/fftools/ffmpeg.c b/fftools/ffmpeg.c index e9c6a8281e6..d59de62546b 100644 --- a/fftools/ffmpeg.c +++ b/fftools/ffmpeg.c @@ -1985,136 +1985,6 @@ static int init_input_stream(InputStream *ist, char *error, int error_len) return 0; } -static int init_output_stream_streamcopy(OutputStream *ost) -{ - OutputFile *of = output_files[ost->file_index]; - InputStream *ist = ost->ist; - InputFile *ifile = input_files[ist->file_index]; - AVCodecParameters *par = ost->st->codecpar; - AVCodecContext *codec_ctx; - AVRational sar; - int i, ret; - uint32_t codec_tag = par->codec_tag; - - av_assert0(ist && !ost->filter); - - codec_ctx = avcodec_alloc_context3(NULL); - if (!codec_ctx) - return AVERROR(ENOMEM); - - ret = avcodec_parameters_to_context(codec_ctx, ist->par); - if (ret >= 0) - ret = av_opt_set_dict(codec_ctx, &ost->encoder_opts); - if (ret < 0) { - av_log(ost, AV_LOG_FATAL, - "Error setting up codec context options.\n"); - avcodec_free_context(&codec_ctx); - return ret; - } - - ret = avcodec_parameters_from_context(par, codec_ctx); - avcodec_free_context(&codec_ctx); - if (ret < 0) { - av_log(ost, AV_LOG_FATAL, - "Error getting reference codec parameters.\n"); - return ret; - } - - if (!codec_tag) { - unsigned int codec_tag_tmp; - if (!of->format->codec_tag || - av_codec_get_id (of->format->codec_tag, par->codec_tag) == par->codec_id || - !av_codec_get_tag2(of->format->codec_tag, par->codec_id, &codec_tag_tmp)) - codec_tag = par->codec_tag; - } - - par->codec_tag = codec_tag; - - if (!ost->frame_rate.num) - ost->frame_rate = ist->framerate; - - if (ost->frame_rate.num) - ost->st->avg_frame_rate = ost->frame_rate; - else - ost->st->avg_frame_rate = ist->st->avg_frame_rate; - - ret = avformat_transfer_internal_stream_timing_info(of->format, ost->st, ist->st, copy_tb); - if (ret < 0) - return ret; - - // copy timebase while removing common factors - if (ost->st->time_base.num <= 0 || ost->st->time_base.den <= 0) { - if (ost->frame_rate.num) - ost->st->time_base = av_inv_q(ost->frame_rate); - else - ost->st->time_base = av_add_q(av_stream_get_codec_timebase(ost->st), (AVRational){0, 1}); - } - - // copy estimated duration as a hint to the muxer - 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); - - if (!ost->copy_prior_start) { - ost->ts_copy_start = (of->start_time == AV_NOPTS_VALUE) ? - 0 : of->start_time; - if (copy_ts && ifile->start_time != AV_NOPTS_VALUE) { - ost->ts_copy_start = FFMAX(ost->ts_copy_start, - ifile->start_time + ifile->ts_offset); - } - } - - 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]; - uint8_t *dst_data; - - dst_data = av_stream_new_side_data(ost->st, sd_src->type, sd_src->size); - if (!dst_data) - return AVERROR(ENOMEM); - memcpy(dst_data, sd_src->data, sd_src->size); - } - } - -#if FFMPEG_ROTATION_METADATA - if (ost->rotate_overridden) { - uint8_t *sd = av_stream_new_side_data(ost->st, AV_PKT_DATA_DISPLAYMATRIX, - sizeof(int32_t) * 9); - if (sd) - av_display_rotation_set((int32_t *)sd, -ost->rotate_override_value); - } -#endif - - switch (par->codec_type) { - case AVMEDIA_TYPE_AUDIO: - if ((par->block_align == 1 || par->block_align == 1152 || par->block_align == 576) && - par->codec_id == AV_CODEC_ID_MP3) - par->block_align = 0; - if (par->codec_id == AV_CODEC_ID_AC3) - par->block_align = 0; - break; - case AVMEDIA_TYPE_VIDEO: - if (ost->frame_aspect_ratio.num) { // overridden by the -aspect cli option - sar = - av_mul_q(ost->frame_aspect_ratio, - (AVRational){ par->height, par->width }); - av_log(ost, AV_LOG_WARNING, "Overriding aspect ratio " - "with stream copy may produce invalid files\n"); - } - else if (ist->st->sample_aspect_ratio.num) - sar = ist->st->sample_aspect_ratio; - else - sar = par->sample_aspect_ratio; - ost->st->sample_aspect_ratio = par->sample_aspect_ratio = sar; - ost->st->avg_frame_rate = ist->st->avg_frame_rate; - ost->st->r_frame_rate = ist->st->r_frame_rate; - break; - } - - ost->mux_timebase = ist->st->time_base; - - return 0; -} - static int init_output_stream_nofilter(OutputStream *ost) { int ret = 0; @@ -2124,12 +1994,6 @@ static int init_output_stream_nofilter(OutputStream *ost) if (ret < 0) return ret; } else { - if (ost->ist) { - ret = init_output_stream_streamcopy(ost); - if (ret < 0) - return ret; - } - ret = of_stream_init(output_files[ost->file_index], ost); if (ret < 0) return ret; diff --git a/fftools/ffmpeg_mux_init.c b/fftools/ffmpeg_mux_init.c index 3fa39e14560..c16967cea81 100644 --- a/fftools/ffmpeg_mux_init.c +++ b/fftools/ffmpeg_mux_init.c @@ -37,6 +37,7 @@ #include "libavutil/avutil.h" #include "libavutil/bprint.h" #include "libavutil/dict.h" +#include "libavutil/display.h" #include "libavutil/getenv_utf8.h" #include "libavutil/intreadwrite.h" #include "libavutil/log.h" @@ -839,6 +840,142 @@ static void new_stream_subtitle(Muxer *mux, const OptionsContext *o, } } +static int streamcopy_init(const Muxer *mux, const OptionsContext *o, + OutputStream *ost) +{ + const InputStream *ist = ost->ist; + const InputFile *ifile = input_files[ist->file_index]; + + AVCodecParameters *par = ost->st->codecpar; + uint32_t codec_tag = par->codec_tag; + + AVCodecContext *codec_ctx = NULL; + AVDictionary *codec_opts = NULL; + int ret = 0; + + codec_ctx = avcodec_alloc_context3(NULL); + if (!codec_ctx) + return AVERROR(ENOMEM); + + ret = avcodec_parameters_to_context(codec_ctx, ist->par); + if (ret >= 0) + ret = av_opt_set_dict(codec_ctx, &ost->encoder_opts); + if (ret < 0) { + av_log(ost, AV_LOG_FATAL, + "Error setting up codec context options.\n"); + goto fail; + } + + ret = avcodec_parameters_from_context(par, codec_ctx); + if (ret < 0) { + av_log(ost, AV_LOG_FATAL, + "Error getting reference codec parameters.\n"); + goto fail; + } + + if (!codec_tag) { + const struct AVCodecTag * const *ct = mux->fc->oformat->codec_tag; + unsigned int codec_tag_tmp; + if (!ct || av_codec_get_id (ct, par->codec_tag) == par->codec_id || + !av_codec_get_tag2(ct, par->codec_id, &codec_tag_tmp)) + codec_tag = par->codec_tag; + } + + par->codec_tag = codec_tag; + + if (!ost->frame_rate.num) + ost->frame_rate = ist->framerate; + + if (ost->frame_rate.num) + ost->st->avg_frame_rate = ost->frame_rate; + else + ost->st->avg_frame_rate = ist->st->avg_frame_rate; + + ret = avformat_transfer_internal_stream_timing_info(mux->fc->oformat, + ost->st, ist->st, copy_tb); + if (ret < 0) + goto fail; + + // copy timebase while removing common factors + if (ost->st->time_base.num <= 0 || ost->st->time_base.den <= 0) { + if (ost->frame_rate.num) + ost->st->time_base = av_inv_q(ost->frame_rate); + else + ost->st->time_base = av_add_q(av_stream_get_codec_timebase(ost->st), (AVRational){0, 1}); + } + + // copy estimated duration as a hint to the muxer + 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); + + if (!ost->copy_prior_start) { + ost->ts_copy_start = (mux->of.start_time == AV_NOPTS_VALUE) ? + 0 : mux->of.start_time; + if (copy_ts && ifile->start_time != AV_NOPTS_VALUE) { + ost->ts_copy_start = FFMAX(ost->ts_copy_start, + ifile->start_time + ifile->ts_offset); + } + } + + if (ist->st->nb_side_data) { + for (int i = 0; i < ist->st->nb_side_data; i++) { + const AVPacketSideData *sd_src = &ist->st->side_data[i]; + uint8_t *dst_data; + + dst_data = av_stream_new_side_data(ost->st, sd_src->type, sd_src->size); + if (!dst_data) { + ret = AVERROR(ENOMEM); + goto fail; + } + memcpy(dst_data, sd_src->data, sd_src->size); + } + } + +#if FFMPEG_ROTATION_METADATA + if (ost->rotate_overridden) { + uint8_t *sd = av_stream_new_side_data(ost->st, AV_PKT_DATA_DISPLAYMATRIX, + sizeof(int32_t) * 9); + if (sd) + av_display_rotation_set((int32_t *)sd, -ost->rotate_override_value); + } +#endif + + switch (par->codec_type) { + case AVMEDIA_TYPE_AUDIO: + if ((par->block_align == 1 || par->block_align == 1152 || par->block_align == 576) && + par->codec_id == AV_CODEC_ID_MP3) + par->block_align = 0; + if (par->codec_id == AV_CODEC_ID_AC3) + par->block_align = 0; + break; + case AVMEDIA_TYPE_VIDEO: { + AVRational sar; + if (ost->frame_aspect_ratio.num) { // overridden by the -aspect cli option + sar = + av_mul_q(ost->frame_aspect_ratio, + (AVRational){ par->height, par->width }); + av_log(ost, AV_LOG_WARNING, "Overriding aspect ratio " + "with stream copy may produce invalid files\n"); + } + else if (ist->st->sample_aspect_ratio.num) + sar = ist->st->sample_aspect_ratio; + else + sar = par->sample_aspect_ratio; + ost->st->sample_aspect_ratio = par->sample_aspect_ratio = sar; + ost->st->avg_frame_rate = ist->st->avg_frame_rate; + ost->st->r_frame_rate = ist->st->r_frame_rate; + break; + } + } + + ost->mux_timebase = ist->st->time_base; + +fail: + avcodec_free_context(&codec_ctx); + av_dict_free(&codec_opts); + return ret; +} + static OutputStream *ost_add(Muxer *mux, const OptionsContext *o, enum AVMediaType type, InputStream *ist) { @@ -1089,6 +1226,12 @@ static OutputStream *ost_add(Muxer *mux, const OptionsContext *o, default: new_stream_unknown (mux, o, ost); break; } + if (ost->ist && !ost->enc) { + ret = streamcopy_init(mux, o, ost); + if (ret < 0) + exit_program(1); + } + return ost; } From a0452ee83750afe0e279d3cbe7a678e2a72f93b4 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Mon, 10 Apr 2023 21:42:48 +0200 Subject: [PATCH 0694/2172] fftools/ffmpeg_mux_init: remove a redundant check --- fftools/ffmpeg_mux_init.c | 20 +++++++++----------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/fftools/ffmpeg_mux_init.c b/fftools/ffmpeg_mux_init.c index c16967cea81..74f0d5f56b8 100644 --- a/fftools/ffmpeg_mux_init.c +++ b/fftools/ffmpeg_mux_init.c @@ -917,18 +917,16 @@ static int streamcopy_init(const Muxer *mux, const OptionsContext *o, } } - if (ist->st->nb_side_data) { - for (int i = 0; i < ist->st->nb_side_data; i++) { - const AVPacketSideData *sd_src = &ist->st->side_data[i]; - uint8_t *dst_data; - - dst_data = av_stream_new_side_data(ost->st, sd_src->type, sd_src->size); - if (!dst_data) { - ret = AVERROR(ENOMEM); - goto fail; - } - memcpy(dst_data, sd_src->data, sd_src->size); + for (int i = 0; i < ist->st->nb_side_data; i++) { + const AVPacketSideData *sd_src = &ist->st->side_data[i]; + uint8_t *dst_data; + + dst_data = av_stream_new_side_data(ost->st, sd_src->type, sd_src->size); + if (!dst_data) { + ret = AVERROR(ENOMEM); + goto fail; } + memcpy(dst_data, sd_src->data, sd_src->size); } #if FFMPEG_ROTATION_METADATA From 4fc513b5e379dc4d45c8aa23af7d580708bbe4d9 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Tue, 11 Apr 2023 09:34:29 +0200 Subject: [PATCH 0695/2172] fftools/ffmpeg: move a misplaced assignment Changing AVCodecContext.sample_aspect_ratio after the encoder was opened is by itself questionable, but if anywhere it belongs in encoding rather than filtering code. --- fftools/ffmpeg.c | 3 --- fftools/ffmpeg_enc.c | 3 +++ 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/fftools/ffmpeg.c b/fftools/ffmpeg.c index d59de62546b..0f43b7baa71 100644 --- a/fftools/ffmpeg.c +++ b/fftools/ffmpeg.c @@ -711,9 +711,6 @@ static int reap_filters(int flush) switch (av_buffersink_get_type(filter)) { case AVMEDIA_TYPE_VIDEO: - if (!ost->frame_aspect_ratio.num) - enc->sample_aspect_ratio = filtered_frame->sample_aspect_ratio; - enc_frame(ost, filtered_frame); break; case AVMEDIA_TYPE_AUDIO: diff --git a/fftools/ffmpeg_enc.c b/fftools/ffmpeg_enc.c index a0779c45ae6..0236e50e386 100644 --- a/fftools/ffmpeg_enc.c +++ b/fftools/ffmpeg_enc.c @@ -653,6 +653,9 @@ static int encode_frame(OutputFile *of, OutputStream *ost, AVFrame *frame) av_ts2str(frame->pts), av_ts2timestr(frame->pts, &enc->time_base), enc->time_base.num, enc->time_base.den); } + + if (frame->sample_aspect_ratio.num && !ost->frame_aspect_ratio.num) + enc->sample_aspect_ratio = frame->sample_aspect_ratio; } update_benchmark(NULL); From 4358d4d8e71bc5ff205f43daac8448fc4953c794 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Tue, 11 Apr 2023 09:57:08 +0200 Subject: [PATCH 0696/2172] fftools/ffmpeg: move a check to a more appropriate place reap_filters() no longer needs to access the encoding context. --- fftools/ffmpeg.c | 21 +-------------------- fftools/ffmpeg_enc.c | 7 +++++++ 2 files changed, 8 insertions(+), 20 deletions(-) diff --git a/fftools/ffmpeg.c b/fftools/ffmpeg.c index 0f43b7baa71..054a9ce88ad 100644 --- a/fftools/ffmpeg.c +++ b/fftools/ffmpeg.c @@ -669,7 +669,6 @@ static int reap_filters(int flush) /* Reap all buffers present in the buffer sinks */ for (OutputStream *ost = ost_iter(NULL); ost; ost = ost_iter(ost)) { AVFilterContext *filter; - AVCodecContext *enc = ost->enc_ctx; int ret = 0; if (!ost->filter || !ost->filter->graph->graph) @@ -709,25 +708,7 @@ static int reap_filters(int flush) tb.num, tb.den); } - switch (av_buffersink_get_type(filter)) { - case AVMEDIA_TYPE_VIDEO: - enc_frame(ost, filtered_frame); - break; - case AVMEDIA_TYPE_AUDIO: - if (!(enc->codec->capabilities & AV_CODEC_CAP_PARAM_CHANGE) && - avcodec_is_open(enc) && - enc->ch_layout.nb_channels != filtered_frame->ch_layout.nb_channels) { - av_log(NULL, AV_LOG_ERROR, - "Audio filter graph output is not normalized and encoder does not support parameter changes\n"); - break; - } - enc_frame(ost, filtered_frame); - break; - default: - // TODO support subtitle filters - av_assert0(0); - } - + enc_frame(ost, filtered_frame); av_frame_unref(filtered_frame); } } diff --git a/fftools/ffmpeg_enc.c b/fftools/ffmpeg_enc.c index 0236e50e386..063053623f3 100644 --- a/fftools/ffmpeg_enc.c +++ b/fftools/ffmpeg_enc.c @@ -789,6 +789,13 @@ static void do_audio_out(OutputFile *of, OutputStream *ost, AVCodecContext *enc = ost->enc_ctx; int ret; + if (!(enc->codec->capabilities & AV_CODEC_CAP_PARAM_CHANGE) && + enc->ch_layout.nb_channels != frame->ch_layout.nb_channels) { + av_log(ost, AV_LOG_ERROR, + "Audio channel count changed and encoder does not support parameter changes\n"); + return; + } + if (frame->pts == AV_NOPTS_VALUE) frame->pts = e->next_pts; else { From 0c44db4646e42aae8054769f5c1976289c7d9bb3 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Tue, 11 Apr 2023 11:23:21 +0200 Subject: [PATCH 0697/2172] fftools/ffmpeg: drop unnecessary indirection init_input_stream() can print log messages directly, there is no need to ship them to the caller. Also, log errors to the InputStream and avoid duplicate information in the message. --- fftools/ffmpeg.c | 26 +++++++++++--------------- 1 file changed, 11 insertions(+), 15 deletions(-) diff --git a/fftools/ffmpeg.c b/fftools/ffmpeg.c index 054a9ce88ad..0ceb25fed00 100644 --- a/fftools/ffmpeg.c +++ b/fftools/ffmpeg.c @@ -1907,15 +1907,16 @@ static enum AVPixelFormat get_format(AVCodecContext *s, const enum AVPixelFormat return *p; } -static int init_input_stream(InputStream *ist, char *error, int error_len) +static int init_input_stream(InputStream *ist) { int ret; if (ist->decoding_needed) { const AVCodec *codec = ist->dec; if (!codec) { - snprintf(error, error_len, "Decoder (codec %s) not found for input stream #%d:%d", - avcodec_get_name(ist->dec_ctx->codec_id), ist->file_index, ist->st->index); + av_log(ist, AV_LOG_ERROR, + "Decoding requested, but no decoder found for: %s\n", + avcodec_get_name(ist->dec_ctx->codec_id)); return AVERROR(EINVAL); } @@ -1941,9 +1942,9 @@ static int init_input_stream(InputStream *ist, char *error, int error_len) ret = hw_device_setup_for_decode(ist); if (ret < 0) { - snprintf(error, error_len, "Device setup failed for " - "decoder on input stream #%d:%d : %s", - ist->file_index, ist->st->index, av_err2str(ret)); + av_log(ist, AV_LOG_ERROR, + "Hardware device setup failed for decoder: %s\n", + av_err2str(ret)); return ret; } @@ -1951,10 +1952,8 @@ static int init_input_stream(InputStream *ist, char *error, int error_len) if (ret == AVERROR_EXPERIMENTAL) abort_codec_experimental(codec, 0); - snprintf(error, error_len, - "Error while opening decoder for input stream " - "#%d:%d : %s", - ist->file_index, ist->st->index, av_err2str(ret)); + av_log(ist, AV_LOG_ERROR, "Error while opening decoder: %s\n", + av_err2str(ret)); return ret; } assert_avoptions(ist->decoder_opts); @@ -1983,7 +1982,6 @@ static int init_output_stream_nofilter(OutputStream *ost) static int transcode_init(void) { int ret = 0; - char error[1024] = {0}; /* init framerate emulation */ for (int i = 0; i < nb_input_files; i++) { @@ -1995,7 +1993,7 @@ static int transcode_init(void) /* init input streams */ for (InputStream *ist = ist_iter(NULL); ist; ist = ist_iter(ist)) - if ((ret = init_input_stream(ist, error, sizeof(error))) < 0) + if ((ret = init_input_stream(ist)) < 0) goto dump_format; /* @@ -2105,10 +2103,8 @@ static int transcode_init(void) av_log(NULL, AV_LOG_INFO, "\n"); } - if (ret) { - av_log(NULL, AV_LOG_ERROR, "%s\n", error); + if (ret) return ret; - } atomic_store(&transcode_init_done, 1); From c7438e87377b95191b395fcf72f1653ac69eab9c Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Tue, 11 Apr 2023 12:48:41 +0200 Subject: [PATCH 0698/2172] fftools/ffmpeg_mux_init: consolidate input stream flagging code Makes it easier to see where the input stream is modified from muxer code. --- fftools/ffmpeg_mux_init.c | 42 ++++++++++++++++++--------------------- 1 file changed, 19 insertions(+), 23 deletions(-) diff --git a/fftools/ffmpeg_mux_init.c b/fftools/ffmpeg_mux_init.c index 74f0d5f56b8..46fa17beb23 100644 --- a/fftools/ffmpeg_mux_init.c +++ b/fftools/ffmpeg_mux_init.c @@ -1203,13 +1203,6 @@ static OutputStream *ost_add(Muxer *mux, const OptionsContext *o, if (ost->enc_ctx && av_get_exact_bits_per_sample(ost->enc_ctx->codec_id) == 24) av_dict_set(&ost->swr_opts, "output_sample_bits", "24", 0); - if (ost->ist) { - ost->ist->discard = 0; - ost->ist->st->discard = ost->ist->user_set_discard; - - if (!(ost->enc && (type == AVMEDIA_TYPE_VIDEO || type == AVMEDIA_TYPE_AUDIO))) - ist_output_add(ost->ist, ost); - } ost->last_mux_dts = AV_NOPTS_VALUE; MATCH_PER_STREAM_OPT(copy_initial_nonkeyframes, i, @@ -1224,6 +1217,25 @@ static OutputStream *ost_add(Muxer *mux, const OptionsContext *o, default: new_stream_unknown (mux, o, ost); break; } + if (ost->ist) { + ost->ist->discard = 0; + ost->ist->st->discard = ost->ist->user_set_discard; + + if (ost->enc) + ost->ist->decoding_needed |= DECODING_FOR_OST; + + if (ost->enc && + (type == AVMEDIA_TYPE_VIDEO || type == AVMEDIA_TYPE_AUDIO)) { + ret = init_simple_filtergraph(ost->ist, ost); + if (ret < 0) { + av_log(ost, AV_LOG_ERROR, + "Error initializing a simple filtergraph\n"); + exit_program(1); + } + } else + ist_output_add(ost->ist, ost); + } + if (ost->ist && !ost->enc) { ret = streamcopy_init(mux, o, ost); if (ret < 0) @@ -2410,25 +2422,9 @@ int of_open(const OptionsContext *o, const char *filename) /* check if all codec options have been used */ validate_enc_avopt(mux, o->g->codec_opts); - /* set the decoding_needed flags and create simple filtergraphs */ for (int i = 0; i < of->nb_streams; i++) { OutputStream *ost = of->streams[i]; - if (ost->enc_ctx && ost->ist) { - InputStream *ist = ost->ist; - ist->decoding_needed |= DECODING_FOR_OST; - - if (ost->st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO || - ost->st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) { - err = init_simple_filtergraph(ist, ost); - if (err < 0) { - av_log(ost, AV_LOG_ERROR, - "Error initializing a simple filtergraph\n"); - exit_program(1); - } - } - } - /* set the filter output constraints */ if (ost->filter) { const AVCodec *c = ost->enc_ctx->codec; From ae071c9e3944ebe12e4088c81992f31d974ea904 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Tue, 11 Apr 2023 12:57:30 +0200 Subject: [PATCH 0699/2172] fftools/ffmpeg: add a function adding a destination filter for InputStream This way filtering code does not directly mess with InputStream internals. Will become more useful in following commits. --- fftools/ffmpeg.h | 1 + fftools/ffmpeg_demux.c | 6 ++++++ fftools/ffmpeg_filter.c | 8 +++----- 3 files changed, 10 insertions(+), 5 deletions(-) diff --git a/fftools/ffmpeg.h b/fftools/ffmpeg.h index 17076f018d6..d25377514e6 100644 --- a/fftools/ffmpeg.h +++ b/fftools/ffmpeg.h @@ -880,6 +880,7 @@ void ifile_close(InputFile **f); int ifile_get_packet(InputFile *f, AVPacket **pkt); void ist_output_add(InputStream *ist, OutputStream *ost); +void ist_filter_add(InputStream *ist, InputFilter *ifilter); /* iterate over all input streams in all input files; * pass NULL to start iteration */ diff --git a/fftools/ffmpeg_demux.c b/fftools/ffmpeg_demux.c index d89e28b9f6f..6f68c7f6b5d 100644 --- a/fftools/ffmpeg_demux.c +++ b/fftools/ffmpeg_demux.c @@ -567,6 +567,12 @@ void ist_output_add(InputStream *ist, OutputStream *ost) ist->outputs[ist->nb_outputs - 1] = ost; } +void ist_filter_add(InputStream *ist, InputFilter *ifilter) +{ + GROW_ARRAY(ist->filters, ist->nb_filters); + ist->filters[ist->nb_filters - 1] = ifilter; +} + static const AVCodec *choose_decoder(const OptionsContext *o, AVFormatContext *s, AVStream *st, enum HWAccelID hwaccel_id, enum AVHWDeviceType hwaccel_device_type) diff --git a/fftools/ffmpeg_filter.c b/fftools/ffmpeg_filter.c index 584f51ac3f2..d2a185cf98b 100644 --- a/fftools/ffmpeg_filter.c +++ b/fftools/ffmpeg_filter.c @@ -212,12 +212,11 @@ int init_simple_filtergraph(InputStream *ist, OutputStream *ost) if (!ifilter->frame_queue) report_and_exit(AVERROR(ENOMEM)); - GROW_ARRAY(ist->filters, ist->nb_filters); - ist->filters[ist->nb_filters - 1] = ifilter; - GROW_ARRAY(filtergraphs, nb_filtergraphs); filtergraphs[nb_filtergraphs - 1] = fg; + ist_filter_add(ist, ifilter); + return 0; } @@ -319,8 +318,7 @@ static void init_input_filter(FilterGraph *fg, AVFilterInOut *in) if (!ifilter->frame_queue) report_and_exit(AVERROR(ENOMEM)); - GROW_ARRAY(ist->filters, ist->nb_filters); - ist->filters[ist->nb_filters - 1] = ifilter; + ist_filter_add(ist, ifilter); } static int read_binary(const char *path, uint8_t **data, int *len) From ff92ecad2fca6143637538fb7ab3423205ebb4a7 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Tue, 11 Apr 2023 13:05:46 +0200 Subject: [PATCH 0700/2172] fftools/ffmpeg: stop setting InputStream fields from muxing/filtering code Set InputStream.decoding_needed/discard/etc. only from ist_{filter,output},add() functions. Reduces the knowledge of InputStream internals in muxing/filtering code. --- fftools/ffmpeg.h | 2 +- fftools/ffmpeg_demux.c | 13 ++++++++++++- fftools/ffmpeg_filter.c | 8 ++------ fftools/ffmpeg_mux_init.c | 6 ------ 4 files changed, 15 insertions(+), 14 deletions(-) diff --git a/fftools/ffmpeg.h b/fftools/ffmpeg.h index d25377514e6..c73fc8a4593 100644 --- a/fftools/ffmpeg.h +++ b/fftools/ffmpeg.h @@ -880,7 +880,7 @@ void ifile_close(InputFile **f); int ifile_get_packet(InputFile *f, AVPacket **pkt); void ist_output_add(InputStream *ist, OutputStream *ost); -void ist_filter_add(InputStream *ist, InputFilter *ifilter); +void ist_filter_add(InputStream *ist, InputFilter *ifilter, int is_simple); /* iterate over all input streams in all input files; * pass NULL to start iteration */ diff --git a/fftools/ffmpeg_demux.c b/fftools/ffmpeg_demux.c index 6f68c7f6b5d..c7141abadf8 100644 --- a/fftools/ffmpeg_demux.c +++ b/fftools/ffmpeg_demux.c @@ -561,14 +561,25 @@ void ifile_close(InputFile **pf) av_freep(pf); } +static void ist_use(InputStream *ist, int decoding_needed) +{ + ist->discard = 0; + ist->st->discard = ist->user_set_discard; + ist->decoding_needed |= decoding_needed; +} + void ist_output_add(InputStream *ist, OutputStream *ost) { + ist_use(ist, ost->enc ? DECODING_FOR_OST : 0); + GROW_ARRAY(ist->outputs, ist->nb_outputs); ist->outputs[ist->nb_outputs - 1] = ost; } -void ist_filter_add(InputStream *ist, InputFilter *ifilter) +void ist_filter_add(InputStream *ist, InputFilter *ifilter, int is_simple) { + ist_use(ist, is_simple ? DECODING_FOR_OST : DECODING_FOR_FILTER); + GROW_ARRAY(ist->filters, ist->nb_filters); ist->filters[ist->nb_filters - 1] = ifilter; } diff --git a/fftools/ffmpeg_filter.c b/fftools/ffmpeg_filter.c index d2a185cf98b..1d88d2e3b1e 100644 --- a/fftools/ffmpeg_filter.c +++ b/fftools/ffmpeg_filter.c @@ -215,7 +215,7 @@ int init_simple_filtergraph(InputStream *ist, OutputStream *ost) GROW_ARRAY(filtergraphs, nb_filtergraphs); filtergraphs[nb_filtergraphs - 1] = fg; - ist_filter_add(ist, ifilter); + ist_filter_add(ist, ifilter, 1); return 0; } @@ -303,10 +303,6 @@ static void init_input_filter(FilterGraph *fg, AVFilterInOut *in) } av_assert0(ist); - ist->discard = 0; - ist->decoding_needed |= DECODING_FOR_FILTER; - ist->st->discard = AVDISCARD_NONE; - ifilter = ALLOC_ARRAY_ELEM(fg->inputs, fg->nb_inputs); ifilter->ist = ist; ifilter->graph = fg; @@ -318,7 +314,7 @@ static void init_input_filter(FilterGraph *fg, AVFilterInOut *in) if (!ifilter->frame_queue) report_and_exit(AVERROR(ENOMEM)); - ist_filter_add(ist, ifilter); + ist_filter_add(ist, ifilter, 0); } static int read_binary(const char *path, uint8_t **data, int *len) diff --git a/fftools/ffmpeg_mux_init.c b/fftools/ffmpeg_mux_init.c index 46fa17beb23..92bca0cddd7 100644 --- a/fftools/ffmpeg_mux_init.c +++ b/fftools/ffmpeg_mux_init.c @@ -1218,12 +1218,6 @@ static OutputStream *ost_add(Muxer *mux, const OptionsContext *o, } if (ost->ist) { - ost->ist->discard = 0; - ost->ist->st->discard = ost->ist->user_set_discard; - - if (ost->enc) - ost->ist->decoding_needed |= DECODING_FOR_OST; - if (ost->enc && (type == AVMEDIA_TYPE_VIDEO || type == AVMEDIA_TYPE_AUDIO)) { ret = init_simple_filtergraph(ost->ist, ost); From 9ce1a041d8879379cc2a4231d073738616b2c3e5 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Tue, 11 Apr 2023 13:21:56 +0200 Subject: [PATCH 0701/2172] fftools/ffmpeg: move opening decoders to a new file All decoding code will be moved to this file in the future. --- fftools/Makefile | 1 + fftools/ffmpeg.c | 111 +---------------------------------- fftools/ffmpeg.h | 2 + fftools/ffmpeg_dec.c | 135 +++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 139 insertions(+), 110 deletions(-) create mode 100644 fftools/ffmpeg_dec.c diff --git a/fftools/Makefile b/fftools/Makefile index 9939c7095cc..56820e6bc83 100644 --- a/fftools/Makefile +++ b/fftools/Makefile @@ -10,6 +10,7 @@ ALLAVPROGS = $(AVBASENAMES:%=%$(PROGSSUF)$(EXESUF)) ALLAVPROGS_G = $(AVBASENAMES:%=%$(PROGSSUF)_g$(EXESUF)) OBJS-ffmpeg += \ + fftools/ffmpeg_dec.o \ fftools/ffmpeg_demux.o \ fftools/ffmpeg_enc.o \ fftools/ffmpeg_filter.o \ diff --git a/fftools/ffmpeg.c b/fftools/ffmpeg.c index 0ceb25fed00..ba92b2aa846 100644 --- a/fftools/ffmpeg.c +++ b/fftools/ffmpeg.c @@ -621,11 +621,6 @@ void assert_avoptions(AVDictionary *m) } } -static void abort_codec_experimental(const AVCodec *c, int encoder) -{ - exit_program(1); -} - void update_benchmark(const char *fmt, ...) { if (do_benchmark_all) { @@ -1858,110 +1853,6 @@ static int process_input_packet(InputStream *ist, const AVPacket *pkt, int no_eo return !eof_reached; } -static enum AVPixelFormat get_format(AVCodecContext *s, const enum AVPixelFormat *pix_fmts) -{ - InputStream *ist = s->opaque; - const enum AVPixelFormat *p; - int ret; - - for (p = pix_fmts; *p != AV_PIX_FMT_NONE; p++) { - const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(*p); - const AVCodecHWConfig *config = NULL; - int i; - - if (!(desc->flags & AV_PIX_FMT_FLAG_HWACCEL)) - break; - - if (ist->hwaccel_id == HWACCEL_GENERIC || - ist->hwaccel_id == HWACCEL_AUTO) { - for (i = 0;; i++) { - config = avcodec_get_hw_config(s->codec, i); - if (!config) - break; - if (!(config->methods & - AV_CODEC_HW_CONFIG_METHOD_HW_DEVICE_CTX)) - continue; - if (config->pix_fmt == *p) - break; - } - } - if (config && config->device_type == ist->hwaccel_device_type) { - ret = hwaccel_decode_init(s); - if (ret < 0) { - if (ist->hwaccel_id == HWACCEL_GENERIC) { - av_log(NULL, AV_LOG_FATAL, - "%s hwaccel requested for input stream #%d:%d, " - "but cannot be initialized.\n", - av_hwdevice_get_type_name(config->device_type), - ist->file_index, ist->st->index); - return AV_PIX_FMT_NONE; - } - continue; - } - - ist->hwaccel_pix_fmt = *p; - break; - } - } - - return *p; -} - -static int init_input_stream(InputStream *ist) -{ - int ret; - - if (ist->decoding_needed) { - const AVCodec *codec = ist->dec; - if (!codec) { - av_log(ist, AV_LOG_ERROR, - "Decoding requested, but no decoder found for: %s\n", - avcodec_get_name(ist->dec_ctx->codec_id)); - return AVERROR(EINVAL); - } - - ist->dec_ctx->opaque = ist; - ist->dec_ctx->get_format = get_format; - - if (ist->dec_ctx->codec_id == AV_CODEC_ID_DVB_SUBTITLE && - (ist->decoding_needed & DECODING_FOR_OST)) { - av_dict_set(&ist->decoder_opts, "compute_edt", "1", AV_DICT_DONT_OVERWRITE); - if (ist->decoding_needed & DECODING_FOR_FILTER) - av_log(NULL, AV_LOG_WARNING, "Warning using DVB subtitles for filtering and output at the same time is not fully supported, also see -compute_edt [0|1]\n"); - } - - /* Useful for subtitles retiming by lavf (FIXME), skipping samples in - * audio, and video decoders such as cuvid or mediacodec */ - ist->dec_ctx->pkt_timebase = ist->st->time_base; - - if (!av_dict_get(ist->decoder_opts, "threads", NULL, 0)) - av_dict_set(&ist->decoder_opts, "threads", "auto", 0); - /* Attached pics are sparse, therefore we would not want to delay their decoding till EOF. */ - if (ist->st->disposition & AV_DISPOSITION_ATTACHED_PIC) - av_dict_set(&ist->decoder_opts, "threads", "1", 0); - - ret = hw_device_setup_for_decode(ist); - if (ret < 0) { - av_log(ist, AV_LOG_ERROR, - "Hardware device setup failed for decoder: %s\n", - av_err2str(ret)); - return ret; - } - - if ((ret = avcodec_open2(ist->dec_ctx, codec, &ist->decoder_opts)) < 0) { - if (ret == AVERROR_EXPERIMENTAL) - abort_codec_experimental(codec, 0); - - av_log(ist, AV_LOG_ERROR, "Error while opening decoder: %s\n", - av_err2str(ret)); - return ret; - } - assert_avoptions(ist->decoder_opts); - } - - return 0; -} - static int init_output_stream_nofilter(OutputStream *ost) { int ret = 0; @@ -1993,7 +1884,7 @@ static int transcode_init(void) /* init input streams */ for (InputStream *ist = ist_iter(NULL); ist; ist = ist_iter(ist)) - if ((ret = init_input_stream(ist)) < 0) + if (ist->decoding_needed && (ret = dec_open(ist)) < 0) goto dump_format; /* diff --git a/fftools/ffmpeg.h b/fftools/ffmpeg.h index c73fc8a4593..5833c138120 100644 --- a/fftools/ffmpeg.h +++ b/fftools/ffmpeg.h @@ -829,6 +829,8 @@ AVBufferRef *hw_device_for_filter(void); int hwaccel_decode_init(AVCodecContext *avctx); +int dec_open(InputStream *ist); + int enc_alloc(Encoder **penc, const AVCodec *codec); void enc_free(Encoder **penc); diff --git a/fftools/ffmpeg_dec.c b/fftools/ffmpeg_dec.c new file mode 100644 index 00000000000..ccf558649ce --- /dev/null +++ b/fftools/ffmpeg_dec.c @@ -0,0 +1,135 @@ +/* + * 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/dict.h" +#include "libavutil/error.h" +#include "libavutil/log.h" +#include "libavutil/pixdesc.h" +#include "libavutil/pixfmt.h" + +#include "libavcodec/avcodec.h" +#include "libavcodec/codec.h" + +#include "ffmpeg.h" + +static void abort_codec_experimental(const AVCodec *c, int encoder) +{ + exit_program(1); +} + +static enum AVPixelFormat get_format(AVCodecContext *s, const enum AVPixelFormat *pix_fmts) +{ + InputStream *ist = s->opaque; + const enum AVPixelFormat *p; + int ret; + + for (p = pix_fmts; *p != AV_PIX_FMT_NONE; p++) { + const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(*p); + const AVCodecHWConfig *config = NULL; + int i; + + if (!(desc->flags & AV_PIX_FMT_FLAG_HWACCEL)) + break; + + if (ist->hwaccel_id == HWACCEL_GENERIC || + ist->hwaccel_id == HWACCEL_AUTO) { + for (i = 0;; i++) { + config = avcodec_get_hw_config(s->codec, i); + if (!config) + break; + if (!(config->methods & + AV_CODEC_HW_CONFIG_METHOD_HW_DEVICE_CTX)) + continue; + if (config->pix_fmt == *p) + break; + } + } + if (config && config->device_type == ist->hwaccel_device_type) { + ret = hwaccel_decode_init(s); + if (ret < 0) { + if (ist->hwaccel_id == HWACCEL_GENERIC) { + av_log(NULL, AV_LOG_FATAL, + "%s hwaccel requested for input stream #%d:%d, " + "but cannot be initialized.\n", + av_hwdevice_get_type_name(config->device_type), + ist->file_index, ist->st->index); + return AV_PIX_FMT_NONE; + } + continue; + } + + ist->hwaccel_pix_fmt = *p; + break; + } + } + + return *p; +} + +int dec_open(InputStream *ist) +{ + const AVCodec *codec = ist->dec; + int ret; + + if (!codec) { + av_log(ist, AV_LOG_ERROR, + "Decoding requested, but no decoder found for: %s\n", + avcodec_get_name(ist->dec_ctx->codec_id)); + return AVERROR(EINVAL); + } + + ist->dec_ctx->opaque = ist; + ist->dec_ctx->get_format = get_format; + + if (ist->dec_ctx->codec_id == AV_CODEC_ID_DVB_SUBTITLE && + (ist->decoding_needed & DECODING_FOR_OST)) { + av_dict_set(&ist->decoder_opts, "compute_edt", "1", AV_DICT_DONT_OVERWRITE); + if (ist->decoding_needed & DECODING_FOR_FILTER) + av_log(NULL, AV_LOG_WARNING, "Warning using DVB subtitles for filtering and output at the same time is not fully supported, also see -compute_edt [0|1]\n"); + } + + /* Useful for subtitles retiming by lavf (FIXME), skipping samples in + * audio, and video decoders such as cuvid or mediacodec */ + ist->dec_ctx->pkt_timebase = ist->st->time_base; + + if (!av_dict_get(ist->decoder_opts, "threads", NULL, 0)) + av_dict_set(&ist->decoder_opts, "threads", "auto", 0); + /* Attached pics are sparse, therefore we would not want to delay their decoding till EOF. */ + if (ist->st->disposition & AV_DISPOSITION_ATTACHED_PIC) + av_dict_set(&ist->decoder_opts, "threads", "1", 0); + + ret = hw_device_setup_for_decode(ist); + if (ret < 0) { + av_log(ist, AV_LOG_ERROR, + "Hardware device setup failed for decoder: %s\n", + av_err2str(ret)); + return ret; + } + + if ((ret = avcodec_open2(ist->dec_ctx, codec, &ist->decoder_opts)) < 0) { + if (ret == AVERROR_EXPERIMENTAL) + abort_codec_experimental(codec, 0); + + av_log(ist, AV_LOG_ERROR, "Error while opening decoder: %s\n", + av_err2str(ret)); + return ret; + } + assert_avoptions(ist->decoder_opts); + + return 0; +} From 503c705634a0f92505e9f01080338590d1653ef0 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Tue, 11 Apr 2023 13:23:47 +0200 Subject: [PATCH 0702/2172] fftools/ffmpeg_dec: reindent after previous commit --- fftools/ffmpeg_dec.c | 80 ++++++++++++++++++++++---------------------- 1 file changed, 40 insertions(+), 40 deletions(-) diff --git a/fftools/ffmpeg_dec.c b/fftools/ffmpeg_dec.c index ccf558649ce..d6fd0de1267 100644 --- a/fftools/ffmpeg_dec.c +++ b/fftools/ffmpeg_dec.c @@ -83,53 +83,53 @@ static enum AVPixelFormat get_format(AVCodecContext *s, const enum AVPixelFormat int dec_open(InputStream *ist) { - const AVCodec *codec = ist->dec; + const AVCodec *codec = ist->dec; int ret; - if (!codec) { - av_log(ist, AV_LOG_ERROR, - "Decoding requested, but no decoder found for: %s\n", - avcodec_get_name(ist->dec_ctx->codec_id)); - return AVERROR(EINVAL); - } + if (!codec) { + av_log(ist, AV_LOG_ERROR, + "Decoding requested, but no decoder found for: %s\n", + avcodec_get_name(ist->dec_ctx->codec_id)); + return AVERROR(EINVAL); + } - ist->dec_ctx->opaque = ist; - ist->dec_ctx->get_format = get_format; + ist->dec_ctx->opaque = ist; + ist->dec_ctx->get_format = get_format; - if (ist->dec_ctx->codec_id == AV_CODEC_ID_DVB_SUBTITLE && - (ist->decoding_needed & DECODING_FOR_OST)) { - av_dict_set(&ist->decoder_opts, "compute_edt", "1", AV_DICT_DONT_OVERWRITE); - if (ist->decoding_needed & DECODING_FOR_FILTER) - av_log(NULL, AV_LOG_WARNING, "Warning using DVB subtitles for filtering and output at the same time is not fully supported, also see -compute_edt [0|1]\n"); - } + if (ist->dec_ctx->codec_id == AV_CODEC_ID_DVB_SUBTITLE && + (ist->decoding_needed & DECODING_FOR_OST)) { + av_dict_set(&ist->decoder_opts, "compute_edt", "1", AV_DICT_DONT_OVERWRITE); + if (ist->decoding_needed & DECODING_FOR_FILTER) + av_log(NULL, AV_LOG_WARNING, "Warning using DVB subtitles for filtering and output at the same time is not fully supported, also see -compute_edt [0|1]\n"); + } - /* Useful for subtitles retiming by lavf (FIXME), skipping samples in - * audio, and video decoders such as cuvid or mediacodec */ - ist->dec_ctx->pkt_timebase = ist->st->time_base; - - if (!av_dict_get(ist->decoder_opts, "threads", NULL, 0)) - av_dict_set(&ist->decoder_opts, "threads", "auto", 0); - /* Attached pics are sparse, therefore we would not want to delay their decoding till EOF. */ - if (ist->st->disposition & AV_DISPOSITION_ATTACHED_PIC) - av_dict_set(&ist->decoder_opts, "threads", "1", 0); - - ret = hw_device_setup_for_decode(ist); - if (ret < 0) { - av_log(ist, AV_LOG_ERROR, - "Hardware device setup failed for decoder: %s\n", - av_err2str(ret)); - return ret; - } + /* Useful for subtitles retiming by lavf (FIXME), skipping samples in + * audio, and video decoders such as cuvid or mediacodec */ + ist->dec_ctx->pkt_timebase = ist->st->time_base; + + if (!av_dict_get(ist->decoder_opts, "threads", NULL, 0)) + av_dict_set(&ist->decoder_opts, "threads", "auto", 0); + /* Attached pics are sparse, therefore we would not want to delay their decoding till EOF. */ + if (ist->st->disposition & AV_DISPOSITION_ATTACHED_PIC) + av_dict_set(&ist->decoder_opts, "threads", "1", 0); + + ret = hw_device_setup_for_decode(ist); + if (ret < 0) { + av_log(ist, AV_LOG_ERROR, + "Hardware device setup failed for decoder: %s\n", + av_err2str(ret)); + return ret; + } - if ((ret = avcodec_open2(ist->dec_ctx, codec, &ist->decoder_opts)) < 0) { - if (ret == AVERROR_EXPERIMENTAL) - abort_codec_experimental(codec, 0); + if ((ret = avcodec_open2(ist->dec_ctx, codec, &ist->decoder_opts)) < 0) { + if (ret == AVERROR_EXPERIMENTAL) + abort_codec_experimental(codec, 0); - av_log(ist, AV_LOG_ERROR, "Error while opening decoder: %s\n", - av_err2str(ret)); - return ret; - } - assert_avoptions(ist->decoder_opts); + av_log(ist, AV_LOG_ERROR, "Error while opening decoder: %s\n", + av_err2str(ret)); + return ret; + } + assert_avoptions(ist->decoder_opts); return 0; } From c8fa58430edd6b2c3527d851baaa5a418e2ab9e2 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Tue, 11 Apr 2023 13:24:24 +0200 Subject: [PATCH 0703/2172] fftools/ffmpeg_dec: drop useless abort_codec_experimental() It does nothing beyond exit_program(). --- fftools/ffmpeg_dec.c | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/fftools/ffmpeg_dec.c b/fftools/ffmpeg_dec.c index d6fd0de1267..658e7418e93 100644 --- a/fftools/ffmpeg_dec.c +++ b/fftools/ffmpeg_dec.c @@ -27,11 +27,6 @@ #include "ffmpeg.h" -static void abort_codec_experimental(const AVCodec *c, int encoder) -{ - exit_program(1); -} - static enum AVPixelFormat get_format(AVCodecContext *s, const enum AVPixelFormat *pix_fmts) { InputStream *ist = s->opaque; @@ -123,7 +118,7 @@ int dec_open(InputStream *ist) if ((ret = avcodec_open2(ist->dec_ctx, codec, &ist->decoder_opts)) < 0) { if (ret == AVERROR_EXPERIMENTAL) - abort_codec_experimental(codec, 0); + exit_program(1); av_log(ist, AV_LOG_ERROR, "Error while opening decoder: %s\n", av_err2str(ret)); From 2058402e001268e8bc68b33a8979429a73ed1b74 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Tue, 11 Apr 2023 13:27:44 +0200 Subject: [PATCH 0704/2172] fftools/ffmpeg: open decoders right after we know they are needed Will allow initializing subtitle encoding earlier. --- fftools/ffmpeg.c | 5 ----- fftools/ffmpeg_demux.c | 6 ++++++ 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/fftools/ffmpeg.c b/fftools/ffmpeg.c index ba92b2aa846..c2dafeb46e1 100644 --- a/fftools/ffmpeg.c +++ b/fftools/ffmpeg.c @@ -1882,11 +1882,6 @@ static int transcode_init(void) ifile->streams[j]->start = av_gettime_relative(); } - /* init input streams */ - for (InputStream *ist = ist_iter(NULL); ist; ist = ist_iter(ist)) - if (ist->decoding_needed && (ret = dec_open(ist)) < 0) - goto dump_format; - /* * initialize stream copy and subtitle/data streams. * Encoded AVFrame based streams will get initialized when the first AVFrame diff --git a/fftools/ffmpeg_demux.c b/fftools/ffmpeg_demux.c index c7141abadf8..5afb3ff2c82 100644 --- a/fftools/ffmpeg_demux.c +++ b/fftools/ffmpeg_demux.c @@ -566,6 +566,12 @@ static void ist_use(InputStream *ist, int decoding_needed) ist->discard = 0; ist->st->discard = ist->user_set_discard; ist->decoding_needed |= decoding_needed; + + if (decoding_needed && !avcodec_is_open(ist->dec_ctx)) { + int ret = dec_open(ist); + if (ret < 0) + report_and_exit(ret); + } } void ist_output_add(InputStream *ist, OutputStream *ost) From de38e17583bf5b542188810c1079abcf0c9ff8da Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Tue, 11 Apr 2023 13:47:12 +0200 Subject: [PATCH 0705/2172] fftools/ffmpeg: initialize no-filter streams earlier There is no reason to postpone it until transcode_init() anymore, it can be done right at the end of of_open(). --- fftools/ffmpeg.c | 34 ---------------------------------- fftools/ffmpeg_mux_init.c | 32 ++++++++++++++++++++++++++++++++ 2 files changed, 32 insertions(+), 34 deletions(-) diff --git a/fftools/ffmpeg.c b/fftools/ffmpeg.c index c2dafeb46e1..14861fec4e9 100644 --- a/fftools/ffmpeg.c +++ b/fftools/ffmpeg.c @@ -1853,23 +1853,6 @@ static int process_input_packet(InputStream *ist, const AVPacket *pkt, int no_eo return !eof_reached; } -static int init_output_stream_nofilter(OutputStream *ost) -{ - int ret = 0; - - if (ost->enc_ctx) { - ret = enc_open(ost, NULL); - if (ret < 0) - return ret; - } else { - ret = of_stream_init(output_files[ost->file_index], ost); - if (ret < 0) - return ret; - } - - return ret; -} - static int transcode_init(void) { int ret = 0; @@ -1882,22 +1865,6 @@ static int transcode_init(void) ifile->streams[j]->start = av_gettime_relative(); } - /* - * initialize stream copy and subtitle/data streams. - * Encoded AVFrame based streams will get initialized when the first AVFrame - * is received in do_video_out - */ - for (OutputStream *ost = ost_iter(NULL); ost; ost = ost_iter(ost)) { - if (ost->enc_ctx && - (ost->st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO || - ost->st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO)) - continue; - - ret = init_output_stream_nofilter(ost); - if (ret < 0) - goto dump_format; - } - /* discard unused programs */ for (int i = 0; i < nb_input_files; i++) { InputFile *ifile = input_files[i]; @@ -1914,7 +1881,6 @@ static int transcode_init(void) } } - dump_format: /* dump the stream mapping */ av_log(NULL, AV_LOG_INFO, "Stream mapping:\n"); for (InputStream *ist = ist_iter(NULL); ist; ist = ist_iter(ist)) { diff --git a/fftools/ffmpeg_mux_init.c b/fftools/ffmpeg_mux_init.c index 92bca0cddd7..3d14b8268d8 100644 --- a/fftools/ffmpeg_mux_init.c +++ b/fftools/ffmpeg_mux_init.c @@ -2317,6 +2317,23 @@ static void validate_enc_avopt(Muxer *mux, const AVDictionary *codec_avopt) av_dict_free(&unused_opts); } +static int init_output_stream_nofilter(OutputStream *ost) +{ + int ret = 0; + + if (ost->enc_ctx) { + ret = enc_open(ost, NULL); + if (ret < 0) + return ret; + } else { + ret = of_stream_init(output_files[ost->file_index], ost); + if (ret < 0) + return ret; + } + + return ret; +} + static const char *output_file_item_name(void *obj) { const Muxer *mux = obj; @@ -2512,6 +2529,21 @@ int of_open(const OptionsContext *o, const char *filename) of->url = filename; + /* initialize stream copy and subtitle/data streams. + * Encoded AVFrame based streams will get initialized when the first AVFrame + * is received in do_video_out + */ + for (int i = 0; i < of->nb_streams; i++) { + OutputStream *ost = of->streams[i]; + + if (ost->filter) + continue; + + err = init_output_stream_nofilter(ost); + if (err < 0) + report_and_exit(err); + } + /* write the header for files with no streams */ if (of->format->flags & AVFMT_NOSTREAMS && oc->nb_streams == 0) { int ret = mux_check_init(mux); From a064aed4c37836468f4156e6b3aaf150a626fa50 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Tue, 11 Apr 2023 10:15:55 +0200 Subject: [PATCH 0706/2172] fftools/ffmpeg: store stream media type in OutputStream Reduces access to a deeply nested muxer property OutputStream.st->codecpar->codec_type for this fundamental and immutable stream property. Besides making the code shorter, this will allow making the AVStream (OutputStream.st) private to the muxer in the future. --- fftools/ffmpeg.c | 4 ++-- fftools/ffmpeg.h | 2 ++ fftools/ffmpeg_mux.c | 11 +++++------ fftools/ffmpeg_mux_init.c | 26 ++++++++++++-------------- 4 files changed, 21 insertions(+), 22 deletions(-) diff --git a/fftools/ffmpeg.c b/fftools/ffmpeg.c index 14861fec4e9..d143244e7c5 100644 --- a/fftools/ffmpeg.c +++ b/fftools/ffmpeg.c @@ -748,12 +748,12 @@ static void print_report(int is_last_report, int64_t timer_start, int64_t cur_ti const AVCodecContext * const enc = ost->enc_ctx; const float q = enc ? ost->quality / (float) FF_QP2LAMBDA : -1; - if (vid && ost->st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) { + if (vid && ost->type == AVMEDIA_TYPE_VIDEO) { av_bprintf(&buf, "q=%2.1f ", q); av_bprintf(&buf_script, "stream_%d_%d_q=%.1f\n", ost->file_index, ost->index, q); } - if (!vid && ost->st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) { + if (!vid && ost->type == AVMEDIA_TYPE_VIDEO) { float fps; uint64_t frame_number = atomic_load(&ost->packets_written); diff --git a/fftools/ffmpeg.h b/fftools/ffmpeg.h index 5833c138120..f08f5db49ee 100644 --- a/fftools/ffmpeg.h +++ b/fftools/ffmpeg.h @@ -578,6 +578,8 @@ typedef struct Encoder Encoder; typedef struct OutputStream { const AVClass *class; + enum AVMediaType type; + int file_index; /* file index */ int index; /* stream index in the output file */ diff --git a/fftools/ffmpeg_mux.c b/fftools/ffmpeg_mux.c index b3169251154..eb64d8c3ff4 100644 --- a/fftools/ffmpeg_mux.c +++ b/fftools/ffmpeg_mux.c @@ -62,7 +62,6 @@ static int write_packet(Muxer *mux, OutputStream *ost, AVPacket *pkt) { MuxStream *ms = ms_from_ost(ost); AVFormatContext *s = mux->fc; - AVStream *st = ost->st; int64_t fs; uint64_t frame_num; int ret; @@ -74,10 +73,10 @@ static int write_packet(Muxer *mux, OutputStream *ost, AVPacket *pkt) goto fail; } - if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO && ost->vsync_method == VSYNC_DROP) + if (ost->type == AVMEDIA_TYPE_VIDEO && ost->vsync_method == VSYNC_DROP) pkt->pts = pkt->dts = AV_NOPTS_VALUE; - if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) { + if (ost->type == AVMEDIA_TYPE_VIDEO) { if (ost->frame_rate.num && ost->is_cfr) { if (pkt->duration > 0) av_log(ost, AV_LOG_WARNING, "Overriding packet duration by frame rate, this should not happen\n"); @@ -101,12 +100,12 @@ static int write_packet(Muxer *mux, OutputStream *ost, AVPacket *pkt) - FFMIN3(pkt->pts, pkt->dts, ms->last_mux_dts + 1) - FFMAX3(pkt->pts, pkt->dts, ms->last_mux_dts + 1); } - if ((st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO || st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO || st->codecpar->codec_type == AVMEDIA_TYPE_SUBTITLE) && + if ((ost->type == AVMEDIA_TYPE_AUDIO || ost->type == AVMEDIA_TYPE_VIDEO || ost->type == AVMEDIA_TYPE_SUBTITLE) && pkt->dts != AV_NOPTS_VALUE && ms->last_mux_dts != AV_NOPTS_VALUE) { int64_t max = ms->last_mux_dts + !(s->oformat->flags & AVFMT_TS_NONSTRICT); if (pkt->dts < max) { - int loglevel = max - pkt->dts > 2 || st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO ? AV_LOG_WARNING : AV_LOG_DEBUG; + int loglevel = max - pkt->dts > 2 || ost->type == AVMEDIA_TYPE_VIDEO ? AV_LOG_WARNING : AV_LOG_DEBUG; if (exit_on_error) loglevel = AV_LOG_ERROR; av_log(s, loglevel, "Non-monotonous DTS in output stream " @@ -136,7 +135,7 @@ static int write_packet(Muxer *mux, OutputStream *ost, AVPacket *pkt) if (debug_ts) { av_log(ost, AV_LOG_INFO, "muxer <- type:%s " "pkt_pts:%s pkt_pts_time:%s pkt_dts:%s pkt_dts_time:%s duration:%s duration_time:%s size:%d\n", - av_get_media_type_string(st->codecpar->codec_type), + av_get_media_type_string(ost->type), av_ts2str(pkt->pts), av_ts2timestr(pkt->pts, &ost->st->time_base), av_ts2str(pkt->dts), av_ts2timestr(pkt->dts, &ost->st->time_base), av_ts2str(pkt->duration), av_ts2timestr(pkt->duration, &ost->st->time_base), diff --git a/fftools/ffmpeg_mux_init.c b/fftools/ffmpeg_mux_init.c index 3d14b8268d8..b53f5d278dd 100644 --- a/fftools/ffmpeg_mux_init.c +++ b/fftools/ffmpeg_mux_init.c @@ -108,7 +108,7 @@ static int check_opt_bitexact(void *ctx, const AVDictionary *opts, static int choose_encoder(const OptionsContext *o, AVFormatContext *s, OutputStream *ost, const AVCodec **enc) { - enum AVMediaType type = ost->st->codecpar->codec_type; + enum AVMediaType type = ost->type; char *codec_name = NULL; *enc = NULL; @@ -117,7 +117,7 @@ static int choose_encoder(const OptionsContext *o, AVFormatContext *s, MATCH_PER_STREAM_OPT(codec_names, str, codec_name, s, ost->st); if (!codec_name) { ost->st->codecpar->codec_id = av_guess_codec(s->oformat, NULL, s->url, - NULL, ost->st->codecpar->codec_type); + NULL, ost->type); *enc = avcodec_find_encoder(ost->st->codecpar->codec_id); if (!*enc) { av_log(ost, AV_LOG_FATAL, "Automatic encoder selection failed " @@ -127,7 +127,7 @@ static int choose_encoder(const OptionsContext *o, AVFormatContext *s, return AVERROR_ENCODER_NOT_FOUND; } } else if (strcmp(codec_name, "copy")) { - *enc = find_codec_or_die(ost, codec_name, ost->st->codecpar->codec_type, 1); + *enc = find_codec_or_die(ost, codec_name, ost->type, 1); ost->st->codecpar->codec_id = (*enc)->id; } } @@ -410,6 +410,7 @@ static MuxStream *mux_stream_alloc(Muxer *mux, enum AVMediaType type) ms->ost.file_index = mux->of.index; ms->ost.index = mux->of.nb_streams - 1; + ms->ost.type = type; ms->ost.class = &output_stream_class; @@ -422,8 +423,6 @@ static MuxStream *mux_stream_alloc(Muxer *mux, enum AVMediaType type) static char *get_ost_filters(const OptionsContext *o, AVFormatContext *oc, OutputStream *ost) { - AVStream *st = ost->st; - if (ost->filters_script && ost->filters) { av_log(ost, AV_LOG_ERROR, "Both -filter and -filter_script set\n"); exit_program(1); @@ -434,8 +433,7 @@ static char *get_ost_filters(const OptionsContext *o, AVFormatContext *oc, else if (ost->filters) return av_strdup(ost->filters); - return av_strdup(st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO ? - "null" : "anull"); + return av_strdup(ost->type == AVMEDIA_TYPE_VIDEO ? "null" : "anull"); } static void check_streamcopy_filters(const OptionsContext *o, AVFormatContext *oc, @@ -1597,7 +1595,7 @@ static int setup_sync_queues(Muxer *mux, AVFormatContext *oc, int64_t buf_size_u for (int i = 0; i < oc->nb_streams; i++) { OutputStream *ost = of->streams[i]; MuxStream *ms = ms_from_ost(ost); - enum AVMediaType type = ost->st->codecpar->codec_type; + enum AVMediaType type = ost->type; ost->sq_idx_encode = -1; ost->sq_idx_mux = -1; @@ -1631,7 +1629,7 @@ static int setup_sync_queues(Muxer *mux, AVFormatContext *oc, int64_t buf_size_u for (int i = 0; i < oc->nb_streams; i++) { OutputStream *ost = of->streams[i]; MuxStream *ms = ms_from_ost(ost); - enum AVMediaType type = ost->st->codecpar->codec_type; + enum AVMediaType type = ost->type; if (!IS_AV_ENC(ost, type)) continue; @@ -1660,7 +1658,7 @@ static int setup_sync_queues(Muxer *mux, AVFormatContext *oc, int64_t buf_size_u for (int i = 0; i < oc->nb_streams; i++) { OutputStream *ost = of->streams[i]; MuxStream *ms = ms_from_ost(ost); - enum AVMediaType type = ost->st->codecpar->codec_type; + enum AVMediaType type = ost->type; if (!IS_INTERLEAVED(type)) continue; @@ -2116,7 +2114,7 @@ static int set_dispositions(Muxer *mux, const OptionsContext *o) for (int i = 0; i < ctx->nb_streams; i++) { OutputStream *ost = of->streams[i]; - nb_streams[ost->st->codecpar->codec_type]++; + nb_streams[ost->type]++; MATCH_PER_STREAM_OPT(disposition, str, dispositions[i], ctx, ost->st); @@ -2126,7 +2124,7 @@ static int set_dispositions(Muxer *mux, const OptionsContext *o) ost->st->disposition = ost->ist->st->disposition; if (ost->st->disposition & AV_DISPOSITION_DEFAULT) - have_default[ost->st->codecpar->codec_type] = 1; + have_default[ost->type] = 1; } } @@ -2149,7 +2147,7 @@ static int set_dispositions(Muxer *mux, const OptionsContext *o) // "Suitable" means the first of that type, skipping attached pictures. for (int i = 0; i < ctx->nb_streams; i++) { OutputStream *ost = of->streams[i]; - enum AVMediaType type = ost->st->codecpar->codec_type; + enum AVMediaType type = ost->type; if (nb_streams[type] < 2 || have_default[type] || ost->st->disposition & AV_DISPOSITION_ATTACHED_PIC) @@ -2242,7 +2240,7 @@ static int process_forced_keyframes(Muxer *mux, const OptionsContext *o) MATCH_PER_STREAM_OPT(forced_key_frames, str, forced_keyframes, mux->fc, ost->st); - if (!(ost->st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO && + if (!(ost->type == AVMEDIA_TYPE_VIDEO && ost->enc_ctx && forced_keyframes)) continue; From a34f483291e5e635e55e0d326c23bb8c352852c3 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Thu, 13 Apr 2023 14:22:28 +0200 Subject: [PATCH 0707/2172] fftools/ffmpeg: add muxer-input codec parameters to OutputStream It stores codec parameters of the stream submitted to the muxer, which may be different from the codec parameters in AVStream due to bitstream filtering. This avoids the confusing back and forth synchronisation between the encoder, bitstream filters, and the muxer, now information flows only in one direction. It also reduces the need for non-muxing code to access AVStream. --- fftools/ffmpeg.h | 6 ++++++ fftools/ffmpeg_enc.c | 2 +- fftools/ffmpeg_mux.c | 6 ++++-- fftools/ffmpeg_mux_init.c | 20 +++++++++++++------- 4 files changed, 24 insertions(+), 10 deletions(-) diff --git a/fftools/ffmpeg.h b/fftools/ffmpeg.h index f08f5db49ee..8ec0f1b3f35 100644 --- a/fftools/ffmpeg.h +++ b/fftools/ffmpeg.h @@ -583,6 +583,12 @@ typedef struct OutputStream { int file_index; /* file index */ int index; /* stream index in the output file */ + /** + * Codec parameters for packets submitted to the muxer (i.e. before + * bitstream filtering, if any). + */ + AVCodecParameters *par_in; + /* input stream that is the source for this output stream; * may be NULL for streams with no well-defined source, e.g. * attachments or outputs from complex filtergraphs */ diff --git a/fftools/ffmpeg_enc.c b/fftools/ffmpeg_enc.c index 063053623f3..2462f53a828 100644 --- a/fftools/ffmpeg_enc.c +++ b/fftools/ffmpeg_enc.c @@ -354,7 +354,7 @@ int enc_open(OutputStream *ost, AVFrame *frame) av_log(ost, AV_LOG_WARNING, "The bitrate parameter is set too low." " It takes bits/s as argument, not kbits/s\n"); - ret = avcodec_parameters_from_context(ost->st->codecpar, ost->enc_ctx); + ret = avcodec_parameters_from_context(ost->par_in, ost->enc_ctx); if (ret < 0) { av_log(ost, AV_LOG_FATAL, "Error initializing the output stream codec context.\n"); diff --git a/fftools/ffmpeg_mux.c b/fftools/ffmpeg_mux.c index eb64d8c3ff4..40b439eea23 100644 --- a/fftools/ffmpeg_mux.c +++ b/fftools/ffmpeg_mux.c @@ -556,9 +556,9 @@ static int bsf_init(MuxStream *ms) int ret; if (!ctx) - return 0; + return avcodec_parameters_copy(ost->st->codecpar, ost->par_in); - ret = avcodec_parameters_copy(ctx->par_in, ost->st->codecpar); + ret = avcodec_parameters_copy(ctx->par_in, ost->par_in); if (ret < 0) return ret; @@ -768,6 +768,8 @@ static void ost_free(OutputStream **post) av_fifo_freep2(&ms->muxing_queue); } + avcodec_parameters_free(&ost->par_in); + av_bsf_free(&ms->bsf_ctx); av_frame_free(&ost->filtered_frame); diff --git a/fftools/ffmpeg_mux_init.c b/fftools/ffmpeg_mux_init.c index b53f5d278dd..64a3e1ffe5b 100644 --- a/fftools/ffmpeg_mux_init.c +++ b/fftools/ffmpeg_mux_init.c @@ -116,19 +116,19 @@ static int choose_encoder(const OptionsContext *o, AVFormatContext *s, if (type == AVMEDIA_TYPE_VIDEO || type == AVMEDIA_TYPE_AUDIO || type == AVMEDIA_TYPE_SUBTITLE) { MATCH_PER_STREAM_OPT(codec_names, str, codec_name, s, ost->st); if (!codec_name) { - ost->st->codecpar->codec_id = av_guess_codec(s->oformat, NULL, s->url, + ost->par_in->codec_id = av_guess_codec(s->oformat, NULL, s->url, NULL, ost->type); - *enc = avcodec_find_encoder(ost->st->codecpar->codec_id); + *enc = avcodec_find_encoder(ost->par_in->codec_id); if (!*enc) { av_log(ost, AV_LOG_FATAL, "Automatic encoder selection failed " "Default encoder for format %s (codec %s) is " "probably disabled. Please choose an encoder manually.\n", - s->oformat->name, avcodec_get_name(ost->st->codecpar->codec_id)); + s->oformat->name, avcodec_get_name(ost->par_in->codec_id)); return AVERROR_ENCODER_NOT_FOUND; } } else if (strcmp(codec_name, "copy")) { *enc = find_codec_or_die(ost, codec_name, ost->type, 1); - ost->st->codecpar->codec_id = (*enc)->id; + ost->par_in->codec_id = (*enc)->id; } } @@ -844,7 +844,7 @@ static int streamcopy_init(const Muxer *mux, const OptionsContext *o, const InputStream *ist = ost->ist; const InputFile *ifile = input_files[ist->file_index]; - AVCodecParameters *par = ost->st->codecpar; + AVCodecParameters *par = ost->par_in; uint32_t codec_tag = par->codec_tag; AVCodecContext *codec_ctx = NULL; @@ -995,6 +995,10 @@ static OutputStream *ost_add(Muxer *mux, const OptionsContext *o, ms = mux_stream_alloc(mux, type); ost = &ms->ost; + ost->par_in = avcodec_parameters_alloc(); + if (!ost->par_in) + report_and_exit(AVERROR(ENOMEM)); + ms->muxing_queue = av_fifo_alloc2(8, sizeof(AVPacket*), 0); if (!ms->muxing_queue) report_and_exit(AVERROR(ENOMEM)); @@ -1003,6 +1007,7 @@ static OutputStream *ost_add(Muxer *mux, const OptionsContext *o, ost->st = st; ost->ist = ist; ost->kf.ref_pts = AV_NOPTS_VALUE; + ost->par_in->codec_type = type; st->codecpar->codec_type = type; ret = choose_encoder(o, oc, ost, &enc); @@ -1170,6 +1175,7 @@ static OutputStream *ost_add(Muxer *mux, const OptionsContext *o, tag = AV_RL32(buf); } ost->st->codecpar->codec_tag = tag; + ost->par_in->codec_tag = tag; if (ost->enc_ctx) ost->enc_ctx->codec_tag = tag; } @@ -1523,8 +1529,8 @@ static void of_add_attachments(Muxer *mux, const OptionsContext *o) ost = ost_add(mux, o, AVMEDIA_TYPE_ATTACHMENT, NULL); ost->attachment_filename = o->attachments[i]; - ost->st->codecpar->extradata = attachment; - ost->st->codecpar->extradata_size = len; + ost->par_in->extradata = attachment; + ost->par_in->extradata_size = len; p = strrchr(o->attachments[i], '/'); av_dict_set(&ost->st->metadata, "filename", (p && *p) ? p + 1 : o->attachments[i], AV_DICT_DONT_OVERWRITE); From 2178ff2162ba4898c5f1cc3f334b00392451efd6 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Tue, 4 Apr 2023 09:44:42 +0200 Subject: [PATCH 0708/2172] fftools/ffmpeg: move do_streamcopy() to ffmpeg_mux do_streamcopy() is muxing code, so this is a more appropriate place for this. The last uses of InputStream in it will be removed in following commits. --- fftools/ffmpeg.c | 81 +------------------------------------------- fftools/ffmpeg.h | 7 ++++ fftools/ffmpeg_mux.c | 76 +++++++++++++++++++++++++++++++++++++++++ 3 files changed, 84 insertions(+), 80 deletions(-) diff --git a/fftools/ffmpeg.c b/fftools/ffmpeg.c index d143244e7c5..84ace5d4149 100644 --- a/fftools/ffmpeg.c +++ b/fftools/ffmpeg.c @@ -914,85 +914,6 @@ int ifilter_parameters_from_codecpar(InputFilter *ifilter, AVCodecParameters *pa return 0; } -/** - * @param dts predicted packet dts in AV_TIME_BASE_Q - */ -static void do_streamcopy(InputStream *ist, OutputStream *ost, - const AVPacket *pkt, int64_t dts) -{ - OutputFile *of = output_files[ost->file_index]; - int64_t start_time = (of->start_time == AV_NOPTS_VALUE) ? 0 : of->start_time; - int64_t ost_tb_start_time = av_rescale_q(start_time, AV_TIME_BASE_Q, ost->mux_timebase); - AVPacket *opkt = ost->pkt; - - av_packet_unref(opkt); - // EOF: flush output bitstream filters. - if (!pkt) { - of_output_packet(of, opkt, ost, 1); - return; - } - - if (!ost->streamcopy_started && !(pkt->flags & AV_PKT_FLAG_KEY) && - !ost->copy_initial_nonkeyframes) - return; - - if (!ost->streamcopy_started) { - if (!ost->copy_prior_start && - (pkt->pts == AV_NOPTS_VALUE ? - dts < ost->ts_copy_start : - pkt->pts < av_rescale_q(ost->ts_copy_start, AV_TIME_BASE_Q, pkt->time_base))) - return; - - if (of->start_time != AV_NOPTS_VALUE && dts < of->start_time) - return; - } - - if (of->recording_time != INT64_MAX && - dts >= of->recording_time + start_time) { - close_output_stream(ost); - return; - } - - if (av_packet_ref(opkt, pkt) < 0) - exit_program(1); - - opkt->time_base = ost->mux_timebase; - - if (pkt->pts != AV_NOPTS_VALUE) - opkt->pts = av_rescale_q(pkt->pts, pkt->time_base, opkt->time_base) - ost_tb_start_time; - - if (pkt->dts == AV_NOPTS_VALUE) { - opkt->dts = av_rescale_q(dts, AV_TIME_BASE_Q, opkt->time_base); - } else if (ost->st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) { - int duration = av_get_audio_frame_duration2(ist->par, pkt->size); - if(!duration) - duration = ist->par->frame_size; - opkt->dts = av_rescale_delta(pkt->time_base, pkt->dts, - (AVRational){1, ist->par->sample_rate}, duration, - &ist->filter_in_rescale_delta_last, opkt->time_base); - /* dts will be set immediately afterwards to what pts is now */ - opkt->pts = opkt->dts - ost_tb_start_time; - } else - opkt->dts = av_rescale_q(pkt->dts, pkt->time_base, opkt->time_base); - opkt->dts -= ost_tb_start_time; - - opkt->duration = av_rescale_q(pkt->duration, pkt->time_base, opkt->time_base); - - { - int ret = trigger_fix_sub_duration_heartbeat(ost, pkt); - if (ret < 0) { - av_log(NULL, AV_LOG_ERROR, - "Subtitle heartbeat logic failed in %s! (%s)\n", - __func__, av_err2str(ret)); - exit_program(1); - } - } - - of_output_packet(of, opkt, ost, 0); - - ost->streamcopy_started = 1; -} - static void check_decode_result(InputStream *ist, int *got_output, int ret) { if (*got_output || ret<0) @@ -1847,7 +1768,7 @@ static int process_input_packet(InputStream *ist, const AVPacket *pkt, int no_eo continue; } - do_streamcopy(ist, ost, pkt, ist->dts); + of_streamcopy(ist, ost, pkt, ist->dts); } return !eof_reached; diff --git a/fftools/ffmpeg.h b/fftools/ffmpeg.h index 8ec0f1b3f35..46b4614ec4d 100644 --- a/fftools/ffmpeg.h +++ b/fftools/ffmpeg.h @@ -872,6 +872,13 @@ void of_enc_stats_close(void); * must be supplied in this case. */ void of_output_packet(OutputFile *of, AVPacket *pkt, OutputStream *ost, int eof); + +/** + * @param dts predicted packet dts in AV_TIME_BASE_Q + */ +void of_streamcopy(InputStream *ist, OutputStream *ost, + const AVPacket *pkt, int64_t dts); + int64_t of_filesize(OutputFile *of); int ifile_open(const OptionsContext *o, const char *filename); diff --git a/fftools/ffmpeg_mux.c b/fftools/ffmpeg_mux.c index 40b439eea23..96ed50f73cc 100644 --- a/fftools/ffmpeg_mux.c +++ b/fftools/ffmpeg_mux.c @@ -378,6 +378,82 @@ void of_output_packet(OutputFile *of, AVPacket *pkt, OutputStream *ost, int eof) } +void of_streamcopy(InputStream *ist, OutputStream *ost, + const AVPacket *pkt, int64_t dts) +{ + OutputFile *of = output_files[ost->file_index]; + int64_t start_time = (of->start_time == AV_NOPTS_VALUE) ? 0 : of->start_time; + int64_t ost_tb_start_time = av_rescale_q(start_time, AV_TIME_BASE_Q, ost->mux_timebase); + AVPacket *opkt = ost->pkt; + + av_packet_unref(opkt); + // EOF: flush output bitstream filters. + if (!pkt) { + of_output_packet(of, opkt, ost, 1); + return; + } + + if (!ost->streamcopy_started && !(pkt->flags & AV_PKT_FLAG_KEY) && + !ost->copy_initial_nonkeyframes) + return; + + if (!ost->streamcopy_started) { + if (!ost->copy_prior_start && + (pkt->pts == AV_NOPTS_VALUE ? + dts < ost->ts_copy_start : + pkt->pts < av_rescale_q(ost->ts_copy_start, AV_TIME_BASE_Q, pkt->time_base))) + return; + + if (of->start_time != AV_NOPTS_VALUE && dts < of->start_time) + return; + } + + if (of->recording_time != INT64_MAX && + dts >= of->recording_time + start_time) { + close_output_stream(ost); + return; + } + + if (av_packet_ref(opkt, pkt) < 0) + exit_program(1); + + opkt->time_base = ost->mux_timebase; + + if (pkt->pts != AV_NOPTS_VALUE) + opkt->pts = av_rescale_q(pkt->pts, pkt->time_base, opkt->time_base) - ost_tb_start_time; + + if (pkt->dts == AV_NOPTS_VALUE) { + opkt->dts = av_rescale_q(dts, AV_TIME_BASE_Q, opkt->time_base); + } else if (ost->st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) { + int duration = av_get_audio_frame_duration2(ist->par, pkt->size); + if(!duration) + duration = ist->par->frame_size; + opkt->dts = av_rescale_delta(pkt->time_base, pkt->dts, + (AVRational){1, ist->par->sample_rate}, duration, + &ist->filter_in_rescale_delta_last, opkt->time_base); + /* dts will be set immediately afterwards to what pts is now */ + opkt->pts = opkt->dts - ost_tb_start_time; + } else + opkt->dts = av_rescale_q(pkt->dts, pkt->time_base, opkt->time_base); + opkt->dts -= ost_tb_start_time; + + opkt->duration = av_rescale_q(pkt->duration, pkt->time_base, opkt->time_base); + + { + int ret = trigger_fix_sub_duration_heartbeat(ost, pkt); + if (ret < 0) { + av_log(NULL, AV_LOG_ERROR, + "Subtitle heartbeat logic failed in %s! (%s)\n", + __func__, av_err2str(ret)); + exit_program(1); + } + } + + of_output_packet(of, opkt, ost, 0); + + ost->streamcopy_started = 1; +} + static int thread_stop(Muxer *mux) { void *ret; From 150c992490d723124f05c77425aa8689dbcbbebc Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Thu, 13 Apr 2023 14:27:40 +0200 Subject: [PATCH 0709/2172] fftools/ffmpeg_mux: use output stream parameters in of_streamcopy() They should always be the same as the input stream parameters, but this reduces the need to access InputStream in muxing code. --- fftools/ffmpeg_mux.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/fftools/ffmpeg_mux.c b/fftools/ffmpeg_mux.c index 96ed50f73cc..db6ad9d5896 100644 --- a/fftools/ffmpeg_mux.c +++ b/fftools/ffmpeg_mux.c @@ -425,11 +425,11 @@ void of_streamcopy(InputStream *ist, OutputStream *ost, if (pkt->dts == AV_NOPTS_VALUE) { opkt->dts = av_rescale_q(dts, AV_TIME_BASE_Q, opkt->time_base); } else if (ost->st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) { - int duration = av_get_audio_frame_duration2(ist->par, pkt->size); + int duration = av_get_audio_frame_duration2(ost->par_in, pkt->size); if(!duration) - duration = ist->par->frame_size; + duration = ost->par_in->frame_size; opkt->dts = av_rescale_delta(pkt->time_base, pkt->dts, - (AVRational){1, ist->par->sample_rate}, duration, + (AVRational){1, ost->par_in->sample_rate}, duration, &ist->filter_in_rescale_delta_last, opkt->time_base); /* dts will be set immediately afterwards to what pts is now */ opkt->pts = opkt->dts - ost_tb_start_time; From 3f11582ca3d40fd98d00ad52b84348add4aa3b31 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Thu, 13 Apr 2023 14:32:57 +0200 Subject: [PATCH 0710/2172] fftools/ffmpeg_mux: stop using filter_in_rescale_delta_last for streamcopy That field was added to store timestamp conversion state for audio decoding code. Later it started being used by streamcopy as well, but that use is wrong because, for a given input stream, both decoding and an arbitrary number of streamcopies may be performed simultaneously. They would then all overwrite the same state variable. Store this state in MuxStream instead. This is the last use of InputStream in of_streamcopy(), so the ist parameter can now be removed. --- fftools/ffmpeg.c | 2 +- fftools/ffmpeg.h | 3 +-- fftools/ffmpeg_mux.c | 6 +++--- fftools/ffmpeg_mux.h | 3 +++ 4 files changed, 8 insertions(+), 6 deletions(-) diff --git a/fftools/ffmpeg.c b/fftools/ffmpeg.c index 84ace5d4149..a7e856e9e2e 100644 --- a/fftools/ffmpeg.c +++ b/fftools/ffmpeg.c @@ -1768,7 +1768,7 @@ static int process_input_packet(InputStream *ist, const AVPacket *pkt, int no_eo continue; } - of_streamcopy(ist, ost, pkt, ist->dts); + of_streamcopy(ost, pkt, ist->dts); } return !eof_reached; diff --git a/fftools/ffmpeg.h b/fftools/ffmpeg.h index 46b4614ec4d..6ad3245166d 100644 --- a/fftools/ffmpeg.h +++ b/fftools/ffmpeg.h @@ -876,8 +876,7 @@ void of_output_packet(OutputFile *of, AVPacket *pkt, OutputStream *ost, int eof) /** * @param dts predicted packet dts in AV_TIME_BASE_Q */ -void of_streamcopy(InputStream *ist, OutputStream *ost, - const AVPacket *pkt, int64_t dts); +void of_streamcopy(OutputStream *ost, const AVPacket *pkt, int64_t dts); int64_t of_filesize(OutputFile *of); diff --git a/fftools/ffmpeg_mux.c b/fftools/ffmpeg_mux.c index db6ad9d5896..8c710c2eacb 100644 --- a/fftools/ffmpeg_mux.c +++ b/fftools/ffmpeg_mux.c @@ -378,10 +378,10 @@ void of_output_packet(OutputFile *of, AVPacket *pkt, OutputStream *ost, int eof) } -void of_streamcopy(InputStream *ist, OutputStream *ost, - const AVPacket *pkt, int64_t dts) +void of_streamcopy(OutputStream *ost, const AVPacket *pkt, int64_t dts) { OutputFile *of = output_files[ost->file_index]; + MuxStream *ms = ms_from_ost(ost); int64_t start_time = (of->start_time == AV_NOPTS_VALUE) ? 0 : of->start_time; int64_t ost_tb_start_time = av_rescale_q(start_time, AV_TIME_BASE_Q, ost->mux_timebase); AVPacket *opkt = ost->pkt; @@ -430,7 +430,7 @@ void of_streamcopy(InputStream *ist, OutputStream *ost, duration = ost->par_in->frame_size; opkt->dts = av_rescale_delta(pkt->time_base, pkt->dts, (AVRational){1, ost->par_in->sample_rate}, duration, - &ist->filter_in_rescale_delta_last, opkt->time_base); + &ms->ts_rescale_delta_last, opkt->time_base); /* dts will be set immediately afterwards to what pts is now */ opkt->pts = opkt->dts - ost_tb_start_time; } else diff --git a/fftools/ffmpeg_mux.h b/fftools/ffmpeg_mux.h index 3fab74b2ed9..e8c4ea4847a 100644 --- a/fftools/ffmpeg_mux.h +++ b/fftools/ffmpeg_mux.h @@ -64,6 +64,9 @@ typedef struct MuxStream { * used for making up missing dts values */ int64_t last_mux_dts; + // audio streamcopy - state for av_rescale_delta() + int64_t ts_rescale_delta_last; + // combined size of all the packets sent to the muxer uint64_t data_size_mux; } MuxStream; From 83646146fe65805e06e1f846635a4b17cba7e71c Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Thu, 13 Apr 2023 14:45:58 +0200 Subject: [PATCH 0711/2172] fftools/ffmpeg_mux: make ts_copy_start private to muxing code It is no longer used outside of ffmpeg_mux* --- fftools/ffmpeg.h | 5 ----- fftools/ffmpeg_mux.c | 4 ++-- fftools/ffmpeg_mux.h | 5 +++++ fftools/ffmpeg_mux_init.c | 10 ++++++---- 4 files changed, 13 insertions(+), 11 deletions(-) diff --git a/fftools/ffmpeg.h b/fftools/ffmpeg.h index 6ad3245166d..e626fac18a8 100644 --- a/fftools/ffmpeg.h +++ b/fftools/ffmpeg.h @@ -598,11 +598,6 @@ typedef struct OutputStream { /* dts of the last packet sent to the muxing queue, in AV_TIME_BASE_Q */ int64_t last_mux_dts; - // timestamp from which the streamcopied streams should start, - // in AV_TIME_BASE_Q; - // everything before it should be discarded - int64_t ts_copy_start; - // the timebase of the packets sent to the muxer AVRational mux_timebase; AVRational enc_timebase; diff --git a/fftools/ffmpeg_mux.c b/fftools/ffmpeg_mux.c index 8c710c2eacb..d832116c124 100644 --- a/fftools/ffmpeg_mux.c +++ b/fftools/ffmpeg_mux.c @@ -400,8 +400,8 @@ void of_streamcopy(OutputStream *ost, const AVPacket *pkt, int64_t dts) if (!ost->streamcopy_started) { if (!ost->copy_prior_start && (pkt->pts == AV_NOPTS_VALUE ? - dts < ost->ts_copy_start : - pkt->pts < av_rescale_q(ost->ts_copy_start, AV_TIME_BASE_Q, pkt->time_base))) + dts < ms->ts_copy_start : + pkt->pts < av_rescale_q(ms->ts_copy_start, AV_TIME_BASE_Q, pkt->time_base))) return; if (of->start_time != AV_NOPTS_VALUE && dts < of->start_time) diff --git a/fftools/ffmpeg_mux.h b/fftools/ffmpeg_mux.h index e8c4ea4847a..25cf1b547f5 100644 --- a/fftools/ffmpeg_mux.h +++ b/fftools/ffmpeg_mux.h @@ -60,6 +60,11 @@ typedef struct MuxStream { /* Threshold after which max_muxing_queue_size will be in effect */ size_t muxing_queue_data_threshold; + // timestamp from which the streamcopied streams should start, + // in AV_TIME_BASE_Q; + // everything before it should be discarded + int64_t ts_copy_start; + /* dts of the last packet sent to the muxer, in the stream timebase * used for making up missing dts values */ int64_t last_mux_dts; diff --git a/fftools/ffmpeg_mux_init.c b/fftools/ffmpeg_mux_init.c index 64a3e1ffe5b..555ccfd796b 100644 --- a/fftools/ffmpeg_mux_init.c +++ b/fftools/ffmpeg_mux_init.c @@ -841,6 +841,8 @@ static void new_stream_subtitle(Muxer *mux, const OptionsContext *o, static int streamcopy_init(const Muxer *mux, const OptionsContext *o, OutputStream *ost) { + MuxStream *ms = ms_from_ost(ost); + const InputStream *ist = ost->ist; const InputFile *ifile = input_files[ist->file_index]; @@ -907,11 +909,11 @@ static int streamcopy_init(const Muxer *mux, const OptionsContext *o, ost->st->duration = av_rescale_q(ist->st->duration, ist->st->time_base, ost->st->time_base); if (!ost->copy_prior_start) { - ost->ts_copy_start = (mux->of.start_time == AV_NOPTS_VALUE) ? - 0 : mux->of.start_time; + ms->ts_copy_start = (mux->of.start_time == AV_NOPTS_VALUE) ? + 0 : mux->of.start_time; if (copy_ts && ifile->start_time != AV_NOPTS_VALUE) { - ost->ts_copy_start = FFMAX(ost->ts_copy_start, - ifile->start_time + ifile->ts_offset); + ms->ts_copy_start = FFMAX(ms->ts_copy_start, + ifile->start_time + ifile->ts_offset); } } From 8763b9cc36457a35e6f092a9791c4ba0ab870a24 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Thu, 13 Apr 2023 14:45:58 +0200 Subject: [PATCH 0712/2172] fftools/ffmpeg_mux: make streamcopy_started private to muxing code It is no longer used outside of ffmpeg_mux* --- fftools/ffmpeg.h | 1 - fftools/ffmpeg_mux.c | 6 +++--- fftools/ffmpeg_mux.h | 2 ++ 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/fftools/ffmpeg.h b/fftools/ffmpeg.h index e626fac18a8..cc72b1cb6e7 100644 --- a/fftools/ffmpeg.h +++ b/fftools/ffmpeg.h @@ -658,7 +658,6 @@ typedef struct OutputStream { int inputs_done; const char *attachment_filename; - int streamcopy_started; int copy_initial_nonkeyframes; int copy_prior_start; diff --git a/fftools/ffmpeg_mux.c b/fftools/ffmpeg_mux.c index d832116c124..01ccac55ce3 100644 --- a/fftools/ffmpeg_mux.c +++ b/fftools/ffmpeg_mux.c @@ -393,11 +393,11 @@ void of_streamcopy(OutputStream *ost, const AVPacket *pkt, int64_t dts) return; } - if (!ost->streamcopy_started && !(pkt->flags & AV_PKT_FLAG_KEY) && + if (!ms->streamcopy_started && !(pkt->flags & AV_PKT_FLAG_KEY) && !ost->copy_initial_nonkeyframes) return; - if (!ost->streamcopy_started) { + if (!ms->streamcopy_started) { if (!ost->copy_prior_start && (pkt->pts == AV_NOPTS_VALUE ? dts < ms->ts_copy_start : @@ -451,7 +451,7 @@ void of_streamcopy(OutputStream *ost, const AVPacket *pkt, int64_t dts) of_output_packet(of, opkt, ost, 0); - ost->streamcopy_started = 1; + ms->streamcopy_started = 1; } static int thread_stop(Muxer *mux) diff --git a/fftools/ffmpeg_mux.h b/fftools/ffmpeg_mux.h index 25cf1b547f5..0938a261ee6 100644 --- a/fftools/ffmpeg_mux.h +++ b/fftools/ffmpeg_mux.h @@ -74,6 +74,8 @@ typedef struct MuxStream { // combined size of all the packets sent to the muxer uint64_t data_size_mux; + + int streamcopy_started; } MuxStream; typedef struct Muxer { From 7f8827f28e0d6641fb8c015250f541037e50a208 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Thu, 13 Apr 2023 14:45:58 +0200 Subject: [PATCH 0713/2172] fftools/ffmpeg_mux: make copy_prior_start private to muxing code It is no longer used outside of ffmpeg_mux* --- fftools/ffmpeg.h | 1 - fftools/ffmpeg_mux.c | 2 +- fftools/ffmpeg_mux.h | 1 + fftools/ffmpeg_mux_init.c | 6 +++--- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/fftools/ffmpeg.h b/fftools/ffmpeg.h index cc72b1cb6e7..25c33cf2073 100644 --- a/fftools/ffmpeg.h +++ b/fftools/ffmpeg.h @@ -659,7 +659,6 @@ typedef struct OutputStream { const char *attachment_filename; int copy_initial_nonkeyframes; - int copy_prior_start; int keep_pix_fmt; diff --git a/fftools/ffmpeg_mux.c b/fftools/ffmpeg_mux.c index 01ccac55ce3..f52205cf30e 100644 --- a/fftools/ffmpeg_mux.c +++ b/fftools/ffmpeg_mux.c @@ -398,7 +398,7 @@ void of_streamcopy(OutputStream *ost, const AVPacket *pkt, int64_t dts) return; if (!ms->streamcopy_started) { - if (!ost->copy_prior_start && + if (!ms->copy_prior_start && (pkt->pts == AV_NOPTS_VALUE ? dts < ms->ts_copy_start : pkt->pts < av_rescale_q(ms->ts_copy_start, AV_TIME_BASE_Q, pkt->time_base))) diff --git a/fftools/ffmpeg_mux.h b/fftools/ffmpeg_mux.h index 0938a261ee6..81c46981617 100644 --- a/fftools/ffmpeg_mux.h +++ b/fftools/ffmpeg_mux.h @@ -75,6 +75,7 @@ typedef struct MuxStream { // combined size of all the packets sent to the muxer uint64_t data_size_mux; + int copy_prior_start; int streamcopy_started; } MuxStream; diff --git a/fftools/ffmpeg_mux_init.c b/fftools/ffmpeg_mux_init.c index 555ccfd796b..51fdd882327 100644 --- a/fftools/ffmpeg_mux_init.c +++ b/fftools/ffmpeg_mux_init.c @@ -908,7 +908,7 @@ static int streamcopy_init(const Muxer *mux, const OptionsContext *o, 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); - if (!ost->copy_prior_start) { + if (!ms->copy_prior_start) { ms->ts_copy_start = (mux->of.start_time == AV_NOPTS_VALUE) ? 0 : mux->of.start_time; if (copy_ts && ifile->start_time != AV_NOPTS_VALUE) { @@ -1156,8 +1156,8 @@ static OutputStream *ost_add(Muxer *mux, const OptionsContext *o, } } - ost->copy_prior_start = -1; - MATCH_PER_STREAM_OPT(copy_prior_start, i, ost->copy_prior_start, oc ,st); + ms->copy_prior_start = -1; + MATCH_PER_STREAM_OPT(copy_prior_start, i, ms->copy_prior_start, oc ,st); MATCH_PER_STREAM_OPT(bitstream_filters, str, bsfs, oc, st); if (bsfs && *bsfs) { From 30699c103f433164f40be4f67f3fb07a402a8050 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Thu, 13 Apr 2023 14:45:58 +0200 Subject: [PATCH 0714/2172] fftools/ffmpeg_mux: make copy_initial_nonkeyframes private to muxing code It is no longer used outside of ffmpeg_mux* --- fftools/ffmpeg.h | 1 - fftools/ffmpeg_mux.c | 2 +- fftools/ffmpeg_mux.h | 1 + fftools/ffmpeg_mux_init.c | 2 +- 4 files changed, 3 insertions(+), 3 deletions(-) diff --git a/fftools/ffmpeg.h b/fftools/ffmpeg.h index 25c33cf2073..494ea4abd33 100644 --- a/fftools/ffmpeg.h +++ b/fftools/ffmpeg.h @@ -658,7 +658,6 @@ typedef struct OutputStream { int inputs_done; const char *attachment_filename; - int copy_initial_nonkeyframes; int keep_pix_fmt; diff --git a/fftools/ffmpeg_mux.c b/fftools/ffmpeg_mux.c index f52205cf30e..7778510d2cc 100644 --- a/fftools/ffmpeg_mux.c +++ b/fftools/ffmpeg_mux.c @@ -394,7 +394,7 @@ void of_streamcopy(OutputStream *ost, const AVPacket *pkt, int64_t dts) } if (!ms->streamcopy_started && !(pkt->flags & AV_PKT_FLAG_KEY) && - !ost->copy_initial_nonkeyframes) + !ms->copy_initial_nonkeyframes) return; if (!ms->streamcopy_started) { diff --git a/fftools/ffmpeg_mux.h b/fftools/ffmpeg_mux.h index 81c46981617..7e0454dfba2 100644 --- a/fftools/ffmpeg_mux.h +++ b/fftools/ffmpeg_mux.h @@ -75,6 +75,7 @@ typedef struct MuxStream { // combined size of all the packets sent to the muxer uint64_t data_size_mux; + int copy_initial_nonkeyframes; int copy_prior_start; int streamcopy_started; } MuxStream; diff --git a/fftools/ffmpeg_mux_init.c b/fftools/ffmpeg_mux_init.c index 51fdd882327..89c0ac90ea5 100644 --- a/fftools/ffmpeg_mux_init.c +++ b/fftools/ffmpeg_mux_init.c @@ -1212,7 +1212,7 @@ static OutputStream *ost_add(Muxer *mux, const OptionsContext *o, ost->last_mux_dts = AV_NOPTS_VALUE; MATCH_PER_STREAM_OPT(copy_initial_nonkeyframes, i, - ost->copy_initial_nonkeyframes, oc, st); + ms->copy_initial_nonkeyframes, oc, st); switch (type) { case AVMEDIA_TYPE_VIDEO: new_stream_video (mux, o, ost); break; From 0b0fa5c2a82d3b89d921f2808bc5f23a2e8e98aa Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Thu, 13 Apr 2023 14:45:58 +0200 Subject: [PATCH 0715/2172] fftools/ffmpeg_enc: make data_size_enc private to encoding code It is no longer used outside of ffmpeg_enc.c --- fftools/ffmpeg.h | 2 -- fftools/ffmpeg_enc.c | 14 ++++++++++---- 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/fftools/ffmpeg.h b/fftools/ffmpeg.h index 494ea4abd33..a9302a95f0e 100644 --- a/fftools/ffmpeg.h +++ b/fftools/ffmpeg.h @@ -662,8 +662,6 @@ typedef struct OutputStream { int keep_pix_fmt; /* stats */ - // combined size of all the packets received from the encoder - uint64_t data_size_enc; // number of packets send to the muxer atomic_uint_least64_t packets_written; // number of frames/samples sent to the encoder diff --git a/fftools/ffmpeg_enc.c b/fftools/ffmpeg_enc.c index 2462f53a828..45bf4b127f7 100644 --- a/fftools/ffmpeg_enc.c +++ b/fftools/ffmpeg_enc.c @@ -56,6 +56,9 @@ struct Encoder { int64_t frames_prev_hist[3]; AVFrame *sq_frame; + + // combined size of all the packets received from the encoder + uint64_t data_size; }; static uint64_t dup_warning = 1000; @@ -513,6 +516,7 @@ void enc_stats_write(OutputStream *ost, EncStats *es, const AVFrame *frame, const AVPacket *pkt, uint64_t frame_num) { + Encoder *e = ost->enc; AVIOContext *io = es->io; AVRational tb = frame ? frame->time_base : pkt->time_base; int64_t pts = frame ? frame->pts : pkt->pts; @@ -564,7 +568,7 @@ void enc_stats_write(OutputStream *ost, EncStats *es, } case ENC_STATS_AVG_BITRATE: { double duration = pkt->dts * av_q2d(tb); - avio_printf(io, "%g", duration > 0 ? 8.0 * ost->data_size_enc / duration : -1.); + avio_printf(io, "%g", duration > 0 ? 8.0 * e->data_size / duration : -1.); continue; } default: av_assert0(0); @@ -577,6 +581,7 @@ void enc_stats_write(OutputStream *ost, EncStats *es, static void update_video_stats(OutputStream *ost, const AVPacket *pkt, int write_vstats) { + Encoder *e = ost->enc; const uint8_t *sd = av_packet_get_side_data(pkt, AV_PKT_DATA_QUALITY_STATS, NULL); AVCodecContext *enc = ost->enc_ctx; @@ -624,14 +629,15 @@ static void update_video_stats(OutputStream *ost, const AVPacket *pkt, int write ti1 = 0.01; bitrate = (pkt->size * 8) / av_q2d(enc->time_base) / 1000.0; - avg_bitrate = (double)(ost->data_size_enc * 8) / ti1 / 1000.0; + avg_bitrate = (double)(e->data_size * 8) / ti1 / 1000.0; fprintf(vstats_file, "s_size= %8.0fkB time= %0.3f br= %7.1fkbits/s avg_br= %7.1fkbits/s ", - (double)ost->data_size_enc / 1024, ti1, bitrate, avg_bitrate); + (double)e->data_size / 1024, ti1, bitrate, avg_bitrate); fprintf(vstats_file, "type= %c\n", av_get_picture_type_char(ost->pict_type)); } static int encode_frame(OutputFile *of, OutputStream *ost, AVFrame *frame) { + Encoder *e = ost->enc; AVCodecContext *enc = ost->enc_ctx; AVPacket *pkt = ost->pkt; const char *type_desc = av_get_media_type_string(enc->codec_type); @@ -725,7 +731,7 @@ static int encode_frame(OutputFile *of, OutputStream *ost, AVFrame *frame) exit_program(1); } - ost->data_size_enc += pkt->size; + e->data_size += pkt->size; ost->packets_encoded++; From c3625ccfcd74bacff2ec6764dea8ef2beb5e9ef7 Mon Sep 17 00:00:00 2001 From: Leo Izen Date: Thu, 13 Apr 2023 08:45:06 -0400 Subject: [PATCH 0716/2172] avcodec/mjpegdec: fix regression with baseline RGB JPEGs Commit b18a9c29713abc3a1b081de3f320ab53a47120c6 introduced a regression that broke some baseline RGB jpegs. (See Trac issue #4045). This fixes that. Signed-off-by: Leo Izen --- libavcodec/mjpegdec.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/libavcodec/mjpegdec.c b/libavcodec/mjpegdec.c index 3fc18aac73b..01537d4774b 100644 --- a/libavcodec/mjpegdec.c +++ b/libavcodec/mjpegdec.c @@ -1698,6 +1698,9 @@ int ff_mjpeg_decode_sos(MJpegDecodeContext *s, const uint8_t *mb_bitmask, s->h_scount[i] = s->h_count[index]; s->v_scount[i] = s->v_count[index]; + if(nb_components == 3 && s->nb_components == 3 && s->avctx->pix_fmt == AV_PIX_FMT_GBRP) + index = (index+2)%3; + s->comp_index[i] = index; s->dc_index[i] = get_bits(&s->gb, 4); @@ -2721,7 +2724,7 @@ int ff_mjpeg_decode_frame_from_buf(AVCodecContext *avctx, AVFrame *frame, } } - if (s->avctx->pix_fmt == AV_PIX_FMT_GBRP) { + if (s->avctx->pix_fmt == AV_PIX_FMT_GBRP && s->progressive) { av_assert0(s->nb_components == 3); FFSWAP(uint8_t *, frame->data[0], frame->data[2]); FFSWAP(uint8_t *, frame->data[0], frame->data[1]); From 3eb4e28c26c3bce608214f392ab1fe6ee28ec1df Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Thu, 9 Mar 2023 13:57:14 +0100 Subject: [PATCH 0717/2172] libavcodec/lcldec: width and height should not be unsigned Computations like col < width - 3 will not work with unsigned width=1 Signed-off-by: Michael Niedermayer --- libavcodec/lcldec.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libavcodec/lcldec.c b/libavcodec/lcldec.c index 5cc0a29bcd2..95206eeb69c 100644 --- a/libavcodec/lcldec.c +++ b/libavcodec/lcldec.c @@ -169,8 +169,8 @@ static int decode_frame(AVCodecContext *avctx, AVFrame *frame, int row, col; unsigned char *encoded = avpkt->data, *outptr; uint8_t *y_out, *u_out, *v_out; - unsigned int width = avctx->width; // Real image width - unsigned int height = avctx->height; // Real image height + int width = avctx->width; // Real image width + int height = avctx->height; // Real image height unsigned int mszh_dlen; unsigned char yq, y1q, uq, vq; int uqvq, ret; From 0cf1ac905d2d97355a389c3baa4e132824b29f21 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Thu, 9 Mar 2023 13:57:15 +0100 Subject: [PATCH 0718/2172] avcodec/lcldec: Support 4:1:1 and 4:2:2 with odd width Fixes: Ticket10240 Fixes: zlib_306_306_yuv422.avi Fixes: zlib_306_306_yuv411.avi Signed-off-by: Michael Niedermayer --- libavcodec/lcldec.c | 22 +++++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/libavcodec/lcldec.c b/libavcodec/lcldec.c index 95206eeb69c..0196460eb28 100644 --- a/libavcodec/lcldec.c +++ b/libavcodec/lcldec.c @@ -403,6 +403,11 @@ static int decode_frame(AVCodecContext *avctx, AVFrame *frame, v_out[ col >> 1 ] = *encoded++ + 128; v_out[(col >> 1) + 1] = *encoded++ + 128; } + if (col && col < width) { + u_out[ col >> 1 ] = u_out[(col>>1) - 1]; + v_out[ col >> 1 ] = v_out[(col>>1) - 1]; + } + y_out -= frame->linesize[0]; u_out -= frame->linesize[1]; v_out -= frame->linesize[2]; @@ -424,6 +429,10 @@ static int decode_frame(AVCodecContext *avctx, AVFrame *frame, u_out[col >> 2] = *encoded++ + 128; v_out[col >> 2] = *encoded++ + 128; } + if (col && col < width) { + u_out[col >> 2] = u_out[(col>>2) - 1]; + v_out[col >> 2] = v_out[(col>>2) - 1]; + } y_out -= frame->linesize[0]; u_out -= frame->linesize[1]; v_out -= frame->linesize[2]; @@ -481,6 +490,7 @@ static av_cold int decode_init(AVCodecContext *avctx) FFALIGN(avctx->height, 4); unsigned int max_decomp_size; int subsample_h, subsample_v; + int partial_h_supported = 0; if (avctx->extradata_size < 8) { av_log(avctx, AV_LOG_ERROR, "Extradata size too small.\n"); @@ -502,14 +512,11 @@ static av_cold int decode_init(AVCodecContext *avctx) av_log(avctx, AV_LOG_DEBUG, "Image type is YUV 1:1:1.\n"); break; case IMGTYPE_YUV422: - c->decomp_size = basesize * 2; + c->decomp_size = (avctx->width & ~3) * avctx->height * 2; max_decomp_size = max_basesize * 2; avctx->pix_fmt = AV_PIX_FMT_YUV422P; av_log(avctx, AV_LOG_DEBUG, "Image type is YUV 4:2:2.\n"); - if (avctx->width % 4) { - avpriv_request_sample(avctx, "Unsupported dimensions"); - return AVERROR_INVALIDDATA; - } + partial_h_supported = 1; break; case IMGTYPE_RGB24: c->decomp_size = basesize * 3; @@ -518,10 +525,11 @@ static av_cold int decode_init(AVCodecContext *avctx) av_log(avctx, AV_LOG_DEBUG, "Image type is RGB 24.\n"); break; case IMGTYPE_YUV411: - c->decomp_size = basesize / 2 * 3; + c->decomp_size = (avctx->width & ~3) * avctx->height / 2 * 3; max_decomp_size = max_basesize / 2 * 3; avctx->pix_fmt = AV_PIX_FMT_YUV411P; av_log(avctx, AV_LOG_DEBUG, "Image type is YUV 4:1:1.\n"); + partial_h_supported = 1; break; case IMGTYPE_YUV211: c->decomp_size = basesize * 2; @@ -541,7 +549,7 @@ static av_cold int decode_init(AVCodecContext *avctx) } av_pix_fmt_get_chroma_sub_sample(avctx->pix_fmt, &subsample_h, &subsample_v); - if (avctx->width % (1<height % (1<width % (1<height % (1< Date: Thu, 9 Mar 2023 13:57:16 +0100 Subject: [PATCH 0719/2172] avcodec/lcldec: 420 seems missing 2 bytes, ignore that Fixes: Ticket 10238 Fixes: mszh_306_306_yuv420.avi Signed-off-by: Michael Niedermayer --- libavcodec/lcldec.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/libavcodec/lcldec.c b/libavcodec/lcldec.c index 0196460eb28..f9a0755e4d3 100644 --- a/libavcodec/lcldec.c +++ b/libavcodec/lcldec.c @@ -219,7 +219,9 @@ static int decode_frame(AVCodecContext *avctx, AVFrame *frame, if (c->decomp_size != mszh_dlen) { av_log(avctx, AV_LOG_ERROR, "Decoded size differs (%d != %d)\n", c->decomp_size, mszh_dlen); - return AVERROR_INVALIDDATA; + if (c->decomp_size != mszh_dlen && + c->decomp_size != mszh_dlen + 2) // YUV420 306x306 is missing 2 bytes + return AVERROR_INVALIDDATA; } encoded = c->decomp_buf; len = mszh_dlen; From e2c3aa8e2b800c5b860315277b3ea426b8b23393 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Thu, 9 Mar 2023 13:57:17 +0100 Subject: [PATCH 0720/2172] avcodec/lcldec: More space for rgb24 Fixes: Ticket 10239 Fixes: zlib_306_306_rgb24.av Signed-off-by: Michael Niedermayer --- libavcodec/lcldec.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/libavcodec/lcldec.c b/libavcodec/lcldec.c index f9a0755e4d3..eb5139a5c51 100644 --- a/libavcodec/lcldec.c +++ b/libavcodec/lcldec.c @@ -152,6 +152,8 @@ static int zlib_decomp(AVCodecContext *avctx, const uint8_t *src, int src_len, i if (expected != (unsigned int)zstream->total_out) { av_log(avctx, AV_LOG_ERROR, "Decoded size differs (%d != %lu)\n", expected, zstream->total_out); + if (expected > (unsigned int)zstream->total_out) + return (unsigned int)zstream->total_out; return AVERROR_UNKNOWN; } return zstream->total_out; @@ -278,12 +280,13 @@ static int decode_frame(AVCodecContext *avctx, AVFrame *frame, ret = zlib_decomp(avctx, buf + 8 + mthread_inlen, len - 8 - mthread_inlen, mthread_outlen, mthread_outlen); if (ret < 0) return ret; + len = c->decomp_size; } else { int ret = zlib_decomp(avctx, buf, len, 0, c->decomp_size); if (ret < 0) return ret; + len = ret; } encoded = c->decomp_buf; - len = c->decomp_size; break; #endif default: @@ -521,7 +524,7 @@ static av_cold int decode_init(AVCodecContext *avctx) partial_h_supported = 1; break; case IMGTYPE_RGB24: - c->decomp_size = basesize * 3; + c->decomp_size = FFALIGN(avctx->width*3, 4) * avctx->height; max_decomp_size = max_basesize * 3; avctx->pix_fmt = AV_PIX_FMT_BGR24; av_log(avctx, AV_LOG_DEBUG, "Image type is RGB 24.\n"); From 1440bf15e2b911cb41b88f2340878ca596d987c0 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Tue, 29 Mar 2022 23:24:59 +0200 Subject: [PATCH 0721/2172] avcodec/pcm_rechunk_bsf: unref packet before putting a new one in Fixes: memleak Fixes: 45982/clusterfuzz-testcase-minimized-ffmpeg_BSF_PCM_RECHUNK_fuzzer-5562089618407424 Found-by: continuous fuzzing process https://github.com/google/oss-fuzz/tree/master/projects/ffmpeg Signed-off-by: Michael Niedermayer --- libavcodec/pcm_rechunk_bsf.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libavcodec/pcm_rechunk_bsf.c b/libavcodec/pcm_rechunk_bsf.c index 108d9e90b99..032f9149164 100644 --- a/libavcodec/pcm_rechunk_bsf.c +++ b/libavcodec/pcm_rechunk_bsf.c @@ -151,7 +151,8 @@ static int rechunk_filter(AVBSFContext *ctx, AVPacket *pkt) av_packet_move_ref(pkt, s->in_pkt); return send_packet(s, nb_samples, pkt); } - } + } else + av_packet_unref(s->in_pkt); ret = ff_bsf_get_packet_ref(ctx, s->in_pkt); if (ret == AVERROR_EOF && s->out_pkt->size) { From 13450b67229540fd79075a84185b29db1eec2687 Mon Sep 17 00:00:00 2001 From: James Almer Date: Fri, 14 Apr 2023 16:34:21 -0300 Subject: [PATCH 0722/2172] avcodec/mpegvideo_enc: ensure lmin is smaller than lmax Fixes ticket #10234 Signed-off-by: James Almer --- libavcodec/ituh263enc.c | 5 +++++ libavcodec/mpegvideo_enc.c | 5 +++++ 2 files changed, 10 insertions(+) diff --git a/libavcodec/ituh263enc.c b/libavcodec/ituh263enc.c index c30ecad4382..97abfb3f456 100644 --- a/libavcodec/ituh263enc.c +++ b/libavcodec/ituh263enc.c @@ -865,6 +865,11 @@ av_cold void ff_h263_encode_init(MpegEncContext *s) s->c_dc_scale_table= ff_mpeg1_dc_scale_table; } + if (s->lmin > s->lmax) { + av_log(s->avctx, AV_LOG_WARNING, "Clipping lmin value to %d\n", s->lmax); + s->lmin = s->lmax; + } + ff_thread_once(&init_static_once, h263_encode_init_static); } diff --git a/libavcodec/mpegvideo_enc.c b/libavcodec/mpegvideo_enc.c index bcd2f9ef1d6..efd8e63aa89 100644 --- a/libavcodec/mpegvideo_enc.c +++ b/libavcodec/mpegvideo_enc.c @@ -798,6 +798,11 @@ av_cold int ff_mpv_encode_init(AVCodecContext *avctx) AV_CODEC_FLAG_INTERLACED_ME) || s->alternate_scan); + if (s->lmin > s->lmax) { + av_log(avctx, AV_LOG_WARNING, "Clipping lmin value to %d\n", s->lmax); + s->lmin = s->lmax; + } + /* init */ ff_mpv_idct_init(s); if ((ret = ff_mpv_common_init(s)) < 0) From 989ff02472acb0566416bca13a161793bc59f52e Mon Sep 17 00:00:00 2001 From: "Ronald S. Bultje" Date: Mon, 17 Apr 2023 10:52:10 -0400 Subject: [PATCH 0723/2172] yuv4mpegenc: add bitdepth multiplier after rounding width. Fixes output of HBD odd-width chroma. --- libavformat/yuv4mpegenc.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libavformat/yuv4mpegenc.c b/libavformat/yuv4mpegenc.c index fc6b08e0cd4..2fa5ee2714d 100644 --- a/libavformat/yuv4mpegenc.c +++ b/libavformat/yuv4mpegenc.c @@ -195,13 +195,14 @@ static int yuv4_write_packet(AVFormatContext *s, AVPacket *pkt) /* The following code presumes all planes to be non-interleaved. */ for (int k = 0; k < desc->nb_components; k++) { - int plane_height = height, plane_width = width * desc->comp[k].step; + int plane_height = height, plane_width = width; const uint8_t *ptr = frame->data[k]; if (desc->nb_components >= 3 && (k == 1 || k == 2)) { /* chroma? */ plane_width = AV_CEIL_RSHIFT(plane_width, desc->log2_chroma_w); plane_height = AV_CEIL_RSHIFT(plane_height, desc->log2_chroma_h); } + plane_width *= desc->comp[k].step; for (int i = 0; i < plane_height; i++) { avio_write(pb, ptr, plane_width); From e392674399e19c104e5b13f37440facd7f3dcd6c Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Fri, 14 Apr 2023 09:01:31 +0200 Subject: [PATCH 0724/2172] lavfi: ensure audio frame durations match the sample count --- libavfilter/avfilter.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/libavfilter/avfilter.c b/libavfilter/avfilter.c index 8d5702a0c85..d2e9ba47ef8 100644 --- a/libavfilter/avfilter.c +++ b/libavfilter/avfilter.c @@ -997,6 +997,14 @@ int ff_filter_frame(AVFilterLink *link, AVFrame *frame) av_log(link->dst, AV_LOG_ERROR, "Sample rate change is not supported\n"); goto error; } + + frame->duration = av_rescale_q(frame->nb_samples, (AVRational){ 1, frame->sample_rate }, + link->time_base); +#if FF_API_PKT_DURATION +FF_DISABLE_DEPRECATION_WARNINGS + frame->pkt_duration = frame->duration; +FF_ENABLE_DEPRECATION_WARNINGS +#endif } link->frame_blocked_in = link->frame_wanted_out = 0; From 6118be25e15121bcd4770585900723bd9baefc9b Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Fri, 14 Apr 2023 10:15:07 +0200 Subject: [PATCH 0725/2172] lavc/encode: do not use pkt_duration for encoding Current code prefers deprecated AVFrame.pkt_duration over its replacement AVFrame.duration whenever the former is set and not equal to the latter. However, duration will only be actually used when the caller sets the AV_CODEC_FLAG_FRAME_DURATION flag, which was added _after_ AVFrame.duration. This implies that any caller aware of AV_CODEC_FLAG_FRAME_DURATION is also aware of AVFrame.duration. pkt_duration should then never be used. --- libavcodec/encode.c | 7 ------- 1 file changed, 7 deletions(-) diff --git a/libavcodec/encode.c b/libavcodec/encode.c index 041fc7670e5..0f11efc481a 100644 --- a/libavcodec/encode.c +++ b/libavcodec/encode.c @@ -457,13 +457,6 @@ static int encode_send_frame_internal(AVCodecContext *avctx, const AVFrame *src) finish: -#if FF_API_PKT_DURATION -FF_DISABLE_DEPRECATION_WARNINGS - if (dst->pkt_duration && dst->pkt_duration != dst->duration) - dst->duration = dst->pkt_duration; -FF_ENABLE_DEPRECATION_WARNINGS -#endif - if (avctx->codec->type == AVMEDIA_TYPE_VIDEO) { ret = encode_generate_icc_profile(avctx, dst); if (ret < 0) From 7ec4881f3e660ab1c6e8f157a55524bc367ae5f4 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Fri, 14 Apr 2023 18:01:20 +0200 Subject: [PATCH 0726/2172] lavc/mjpegdec: simplify smvjpeg_receive_frame() Unify the code for returning the first and every subsequent frame in a packet. --- libavcodec/mjpegdec.c | 26 +++++++++----------------- 1 file changed, 9 insertions(+), 17 deletions(-) diff --git a/libavcodec/mjpegdec.c b/libavcodec/mjpegdec.c index 01537d4774b..9e78d644a18 100644 --- a/libavcodec/mjpegdec.c +++ b/libavcodec/mjpegdec.c @@ -3023,26 +3023,20 @@ static int smvjpeg_receive_frame(AVCodecContext *avctx, AVFrame *frame) { MJpegDecodeContext *s = avctx->priv_data; AVPacket *const pkt = avctx->internal->in_pkt; - int64_t pkt_dts; int got_frame = 0; int ret; - if (s->smv_next_frame > 0) { - av_assert0(s->smv_frame->buf[0]); - ret = av_frame_ref(frame, s->smv_frame); - if (ret < 0) - return ret; - - smv_process_frame(avctx, frame); - return 0; - } + if (s->smv_next_frame > 0) + goto return_frame; ret = ff_decode_get_packet(avctx, pkt); if (ret < 0) return ret; - ret = ff_mjpeg_decode_frame(avctx, frame, &got_frame, pkt); - pkt_dts = pkt->dts; + av_frame_unref(s->smv_frame); + + ret = ff_mjpeg_decode_frame(avctx, s->smv_frame, &got_frame, pkt); + s->smv_frame->pkt_dts = pkt->dts; av_packet_unref(pkt); if (ret < 0) return ret; @@ -3050,11 +3044,9 @@ static int smvjpeg_receive_frame(AVCodecContext *avctx, AVFrame *frame) if (!got_frame) return AVERROR(EAGAIN); - frame->pkt_dts = pkt_dts; - - av_assert0(frame->buf[0]); - av_frame_unref(s->smv_frame); - ret = av_frame_ref(s->smv_frame, frame); +return_frame: + av_assert0(s->smv_frame->buf[0]); + ret = av_frame_ref(frame, s->smv_frame); if (ret < 0) return ret; From b088d59347ed24c9346d8bc1c81ee09637fbd7ec Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Fri, 14 Apr 2023 18:06:29 +0200 Subject: [PATCH 0727/2172] lavc/mjpegdec: properly set pts and duration for smvjpeg A single smvjpeg packet decodes into one large mjpeg frame, slices of which are then returned as output frames. Packet duration covers all of these slices. --- libavcodec/mjpegdec.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/libavcodec/mjpegdec.c b/libavcodec/mjpegdec.c index 9e78d644a18..c41d4bce5eb 100644 --- a/libavcodec/mjpegdec.c +++ b/libavcodec/mjpegdec.c @@ -3013,6 +3013,8 @@ static void smv_process_frame(AVCodecContext *avctx, AVFrame *frame) frame->crop_top = FFMIN(s->smv_next_frame * avctx->height, frame->height); frame->crop_bottom = frame->height - (s->smv_next_frame + 1) * avctx->height; + if (s->smv_frame->pts != AV_NOPTS_VALUE) + s->smv_frame->pts += s->smv_frame->duration; s->smv_next_frame = (s->smv_next_frame + 1) % s->smv_frames_per_jpeg; if (s->smv_next_frame == 0) @@ -3044,6 +3046,9 @@ static int smvjpeg_receive_frame(AVCodecContext *avctx, AVFrame *frame) if (!got_frame) return AVERROR(EAGAIN); + // packet duration covers all the frames in the packet + s->smv_frame->duration /= s->smv_frames_per_jpeg; + return_frame: av_assert0(s->smv_frame->buf[0]); ret = av_frame_ref(frame, s->smv_frame); From 9a44e0335c0b0ba54ec854e2579f9bb7237032f5 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Fri, 14 Apr 2023 11:12:22 +0200 Subject: [PATCH 0728/2172] fftools/sync_queue: update audio frame duration when re-chunking --- fftools/sync_queue.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/fftools/sync_queue.c b/fftools/sync_queue.c index 42a6b89b79c..a7aac040470 100644 --- a/fftools/sync_queue.c +++ b/fftools/sync_queue.c @@ -431,7 +431,7 @@ static int receive_samples(SyncQueue *sq, SyncQueueStream *st, offset_audio(src.f, nb_samples); st->samples_queued -= nb_samples; - return 0; + goto finish; } // otherwise allocate a new frame and copy the data @@ -474,6 +474,10 @@ static int receive_samples(SyncQueue *sq, SyncQueueStream *st, dst->nb_samples += to_copy; } +finish: + dst->duration = av_rescale_q(nb_samples, (AVRational){ 1, dst->sample_rate }, + dst->time_base); + return 0; fail: From af286f17a1c79b6d543c586cf020d08d4e84f0eb Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Fri, 14 Apr 2023 11:24:39 +0200 Subject: [PATCH 0729/2172] fftools/ffmpeg_enc: set audio frame duration when encoding --- fftools/ffmpeg_enc.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/fftools/ffmpeg_enc.c b/fftools/ffmpeg_enc.c index 45bf4b127f7..a35c9f60e5d 100644 --- a/fftools/ffmpeg_enc.c +++ b/fftools/ffmpeg_enc.c @@ -811,6 +811,8 @@ static void do_audio_out(OutputFile *of, OutputStream *ost, av_rescale_q(start_time, AV_TIME_BASE_Q, enc->time_base); } frame->time_base = enc->time_base; + frame->duration = av_rescale_q(frame->nb_samples, (AVRational){1, frame->sample_rate}, + enc->time_base); if (!check_recording_time(ost, frame->pts, frame->time_base)) return; From c17e33c0589c64354d6daf2b19f0134329c9407f Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Fri, 14 Apr 2023 11:16:02 +0200 Subject: [PATCH 0730/2172] fftools/ffmpeg: propagate frame durations to packets when encoding Remove now-obsolete code setting packet durations pre-muxing for CFR encoded video. Changes output in the following FATE tests: * numerous adpcm tests * ffmpeg-filter_complex_audio * lavf-asf * lavf-mkv * lavf-mkv_attachment * matroska-encoding-delay All of these change due to the fact that the output duration is now the actual input data duration and does not include padding added by the encoder. * apng-osample: less wrong packet durations are now passed to the muxer. They are not entirely correct, because the first frame duration should be 3 rather than 2. This is caused by the vsync code and should be addressed later, but this change is a step in the right direction. * tscc2-mov: last output frame has a duration of 11 rather than 1 - this corresponds to the duration actually returned by the demuxer. * film-cvid: video frame durations are now 2 rather than 1 - this corresponds to durations actually returned by the demuxer and matches the timestamps. * mpeg2-ticket6677: durations of some video frames are now 2 rather than 1 - this matches the timestamps. --- fftools/ffmpeg_enc.c | 2 + fftools/ffmpeg_mux.c | 9 - tests/ref/acodec/adpcm-ima_wav | 2 +- tests/ref/acodec/adpcm-ima_wav-trellis | 2 +- tests/ref/acodec/adpcm-ms | 2 +- tests/ref/acodec/adpcm-ms-trellis | 2 +- tests/ref/acodec/adpcm-swf | 2 +- tests/ref/acodec/adpcm-swf-trellis | 2 +- tests/ref/acodec/adpcm-swf-wav | 2 +- tests/ref/acodec/adpcm-yamaha | 2 +- tests/ref/acodec/adpcm-yamaha-trellis | 2 +- tests/ref/fate/apng-osample | 12 +- tests/ref/fate/autorotate | 4 +- tests/ref/fate/ffmpeg-filter_complex_audio | 2 +- tests/ref/fate/film-cvid | 216 ++++++++++----------- tests/ref/fate/matroska-encoding-delay | 2 +- tests/ref/fate/mpeg2-ticket6677 | 4 +- tests/ref/fate/tscc2-mov | 2 +- tests/ref/lavf/asf | 2 +- tests/ref/lavf/mkv | 2 +- tests/ref/lavf/mkv_attachment | 2 +- 21 files changed, 135 insertions(+), 142 deletions(-) diff --git a/fftools/ffmpeg_enc.c b/fftools/ffmpeg_enc.c index a35c9f60e5d..e3dc858bc33 100644 --- a/fftools/ffmpeg_enc.c +++ b/fftools/ffmpeg_enc.c @@ -325,6 +325,8 @@ int enc_open(OutputStream *ost, AVFrame *frame) return ret; } + av_dict_set(&ost->encoder_opts, "flags", "+frame_duration", AV_DICT_MULTIKEY); + ret = hw_device_setup_for_encode(ost); if (ret < 0) { av_log(ost, AV_LOG_ERROR, diff --git a/fftools/ffmpeg_mux.c b/fftools/ffmpeg_mux.c index 7778510d2cc..a2e8873ad27 100644 --- a/fftools/ffmpeg_mux.c +++ b/fftools/ffmpeg_mux.c @@ -76,15 +76,6 @@ static int write_packet(Muxer *mux, OutputStream *ost, AVPacket *pkt) if (ost->type == AVMEDIA_TYPE_VIDEO && ost->vsync_method == VSYNC_DROP) pkt->pts = pkt->dts = AV_NOPTS_VALUE; - if (ost->type == AVMEDIA_TYPE_VIDEO) { - if (ost->frame_rate.num && ost->is_cfr) { - if (pkt->duration > 0) - av_log(ost, AV_LOG_WARNING, "Overriding packet duration by frame rate, this should not happen\n"); - pkt->duration = av_rescale_q(1, av_inv_q(ost->frame_rate), - pkt->time_base); - } - } - av_packet_rescale_ts(pkt, pkt->time_base, ost->st->time_base); pkt->time_base = ost->st->time_base; diff --git a/tests/ref/acodec/adpcm-ima_wav b/tests/ref/acodec/adpcm-ima_wav index bd3306dfc5b..44ca53a5651 100644 --- a/tests/ref/acodec/adpcm-ima_wav +++ b/tests/ref/acodec/adpcm-ima_wav @@ -1,4 +1,4 @@ -56b75c3a6dacedcf2ce7b0586aa33594 *tests/data/fate/acodec-adpcm-ima_wav.wav +af0b82a719762cc6e1a952a6081231cf *tests/data/fate/acodec-adpcm-ima_wav.wav 267324 tests/data/fate/acodec-adpcm-ima_wav.wav 78a2af1c895792d0c221d127bdd48ece *tests/data/fate/acodec-adpcm-ima_wav.out.wav stddev: 903.51 PSNR: 37.21 MAXDIFF:34026 bytes: 1058400/ 1061748 diff --git a/tests/ref/acodec/adpcm-ima_wav-trellis b/tests/ref/acodec/adpcm-ima_wav-trellis index 10d78c74f2c..29c28edddfb 100644 --- a/tests/ref/acodec/adpcm-ima_wav-trellis +++ b/tests/ref/acodec/adpcm-ima_wav-trellis @@ -1,4 +1,4 @@ -f9075c7a3adb2cd114b0bac69afcada6 *tests/data/fate/acodec-adpcm-ima_wav-trellis.wav +6f0df0f3275f833c341d63b9054caebb *tests/data/fate/acodec-adpcm-ima_wav-trellis.wav 267324 tests/data/fate/acodec-adpcm-ima_wav-trellis.wav 26a9b280c14737b159c56e60181f1170 *tests/data/fate/acodec-adpcm-ima_wav-trellis.out.wav stddev: 710.03 PSNR: 39.30 MAXDIFF:25944 bytes: 1058400/ 1061748 diff --git a/tests/ref/acodec/adpcm-ms b/tests/ref/acodec/adpcm-ms index c760b783c23..9f546c9b772 100644 --- a/tests/ref/acodec/adpcm-ms +++ b/tests/ref/acodec/adpcm-ms @@ -1,4 +1,4 @@ -a407b87daeef5b25dfb6c5b3f519e9c1 *tests/data/fate/acodec-adpcm-ms.wav +ed29590dc005c64940c46cfe4a0e8eba *tests/data/fate/acodec-adpcm-ms.wav 268378 tests/data/fate/acodec-adpcm-ms.wav 7be370f937c51e8a967e6a3d08d5156a *tests/data/fate/acodec-adpcm-ms.out.wav stddev: 1050.01 PSNR: 35.91 MAXDIFF:29806 bytes: 1058400/ 1060576 diff --git a/tests/ref/acodec/adpcm-ms-trellis b/tests/ref/acodec/adpcm-ms-trellis index 8587e703c63..e7ea230dbac 100644 --- a/tests/ref/acodec/adpcm-ms-trellis +++ b/tests/ref/acodec/adpcm-ms-trellis @@ -1,4 +1,4 @@ -7ed05f7a88046aa4cd547ddf71953637 *tests/data/fate/acodec-adpcm-ms-trellis.wav +70deb036ed0bf3dd03699eafbbfa51b7 *tests/data/fate/acodec-adpcm-ms-trellis.wav 268378 tests/data/fate/acodec-adpcm-ms-trellis.wav ed9d9cdfd264f2ec6c79127c04dd224e *tests/data/fate/acodec-adpcm-ms-trellis.out.wav stddev: 896.03 PSNR: 37.28 MAXDIFF:28029 bytes: 1058400/ 1060576 diff --git a/tests/ref/acodec/adpcm-swf b/tests/ref/acodec/adpcm-swf index 61d92da0846..0bc9d6ffd0a 100644 --- a/tests/ref/acodec/adpcm-swf +++ b/tests/ref/acodec/adpcm-swf @@ -1,4 +1,4 @@ -64aedd1487cb355406dde36d2bba374f *tests/data/fate/acodec-adpcm-swf.flv +03bda567604b31c86c8740a044eedb1d *tests/data/fate/acodec-adpcm-swf.flv 267801 tests/data/fate/acodec-adpcm-swf.flv 9d061488fdc1a557bdc454b9d1aba59c *tests/data/fate/acodec-adpcm-swf.out.wav stddev: 919.82 PSNR: 37.06 MAXDIFF:51119 bytes: 1058400/ 1064960 diff --git a/tests/ref/acodec/adpcm-swf-trellis b/tests/ref/acodec/adpcm-swf-trellis index f4c69ca622f..a6f9b10ac03 100644 --- a/tests/ref/acodec/adpcm-swf-trellis +++ b/tests/ref/acodec/adpcm-swf-trellis @@ -1,4 +1,4 @@ -fde151ce9b8be0e144e72113508bcff6 *tests/data/fate/acodec-adpcm-swf-trellis.flv +83d6efddeb11bb0f0a4131a6384c7e4b *tests/data/fate/acodec-adpcm-swf-trellis.flv 267801 tests/data/fate/acodec-adpcm-swf-trellis.flv 6a0007e42d92a225a8becddedccf9a0f *tests/data/fate/acodec-adpcm-swf-trellis.out.wav stddev: 731.05 PSNR: 39.05 MAXDIFF:51119 bytes: 1058400/ 1064960 diff --git a/tests/ref/acodec/adpcm-swf-wav b/tests/ref/acodec/adpcm-swf-wav index 80ce287b019..a6c51c565e2 100644 --- a/tests/ref/acodec/adpcm-swf-wav +++ b/tests/ref/acodec/adpcm-swf-wav @@ -1,4 +1,4 @@ -a21ee5ba531ec89e306d78c861eb6ed1 *tests/data/fate/acodec-adpcm-swf-wav.wav +e8a4ac69e50211f3ef828d26b7051397 *tests/data/fate/acodec-adpcm-swf-wav.wav 266624 tests/data/fate/acodec-adpcm-swf-wav.wav 9d061488fdc1a557bdc454b9d1aba59c *tests/data/fate/acodec-adpcm-swf-wav.out.wav stddev: 919.82 PSNR: 37.06 MAXDIFF:51119 bytes: 1058400/ 1064960 diff --git a/tests/ref/acodec/adpcm-yamaha b/tests/ref/acodec/adpcm-yamaha index f3e6dbede20..8b949792455 100644 --- a/tests/ref/acodec/adpcm-yamaha +++ b/tests/ref/acodec/adpcm-yamaha @@ -1,4 +1,4 @@ -245c194e84d482a70ca89de9c0bbd591 *tests/data/fate/acodec-adpcm-yamaha.wav +4719ae6d28c4b13c270caefb34fde140 *tests/data/fate/acodec-adpcm-yamaha.wav 265274 tests/data/fate/acodec-adpcm-yamaha.wav 758b4aee62964831d0a335ada9672104 *tests/data/fate/acodec-adpcm-yamaha.out.wav stddev: 1242.71 PSNR: 34.44 MAXDIFF:39960 bytes: 1058400/ 1060864 diff --git a/tests/ref/acodec/adpcm-yamaha-trellis b/tests/ref/acodec/adpcm-yamaha-trellis index 909a95139bc..f653f214921 100644 --- a/tests/ref/acodec/adpcm-yamaha-trellis +++ b/tests/ref/acodec/adpcm-yamaha-trellis @@ -1,4 +1,4 @@ -c8306ada93ef52b1e87b6758853f4937 *tests/data/fate/acodec-adpcm-yamaha-trellis.wav +6601c0c29d2ac6ed2eee94b13bc3f289 *tests/data/fate/acodec-adpcm-yamaha-trellis.wav 265274 tests/data/fate/acodec-adpcm-yamaha-trellis.wav 8ad27b0ea7e13e70ed334b5ec26c62ef *tests/data/fate/acodec-adpcm-yamaha-trellis.out.wav stddev: 926.56 PSNR: 36.99 MAXDIFF:33570 bytes: 1058400/ 1060864 diff --git a/tests/ref/fate/apng-osample b/tests/ref/fate/apng-osample index 5fca5e667d9..c91dd5284d4 100644 --- a/tests/ref/fate/apng-osample +++ b/tests/ref/fate/apng-osample @@ -3,9 +3,9 @@ #codec_id 0: rawvideo #dimensions 0: 116x135 #sar 0: 0/1 -0, 0, 0, 1, 62640, 0x31eb581d -0, 3, 3, 1, 62640, 0x29e11b82 -0, 6, 6, 1, 62640, 0x207ed588 -0, 9, 9, 1, 62640, 0x3845c906 -0, 12, 12, 1, 62640, 0x6797fe69 -0, 15, 15, 1, 62640, 0x1f086a09 +0, 0, 0, 2, 62640, 0x31eb581d +0, 3, 3, 3, 62640, 0x29e11b82 +0, 6, 6, 3, 62640, 0x207ed588 +0, 9, 9, 3, 62640, 0x3845c906 +0, 12, 12, 3, 62640, 0x6797fe69 +0, 15, 15, 3, 62640, 0x1f086a09 diff --git a/tests/ref/fate/autorotate b/tests/ref/fate/autorotate index c18a017abff..dff628bbff8 100644 --- a/tests/ref/fate/autorotate +++ b/tests/ref/fate/autorotate @@ -1,5 +1,5 @@ -e432aa783e79208a61052f6ced525fff *tests/data/fate/autorotate.mov -197358 tests/data/fate/autorotate.mov +701a366a5b97ea92b0e25f5d059a0dd6 *tests/data/fate/autorotate.mov +197366 tests/data/fate/autorotate.mov #extradata 0: 34, 0x9d7d073f #tb 0: 1/15360 #media_type 0: video diff --git a/tests/ref/fate/ffmpeg-filter_complex_audio b/tests/ref/fate/ffmpeg-filter_complex_audio index 0d1f6500408..3f2f670514d 100644 --- a/tests/ref/fate/ffmpeg-filter_complex_audio +++ b/tests/ref/fate/ffmpeg-filter_complex_audio @@ -6,4 +6,4 @@ 0, -256, -256, 1536, 416, 0x3001fb2d 0, 1280, 1280, 1536, 418, 0xba72fc16 0, 2816, 2816, 1536, 418, 0xba72fc16 -0, 4352, 4352, 1536, 418, 0xba72fc16 +0, 4352, 4352, 3, 418, 0xba72fc16 diff --git a/tests/ref/fate/film-cvid b/tests/ref/fate/film-cvid index 24540bf131e..60bbc192d8e 100644 --- a/tests/ref/fate/film-cvid +++ b/tests/ref/fate/film-cvid @@ -4,112 +4,112 @@ #dimensions 0: 320x224 #sar 0: 0/1 0, 0, 0, 1, 215040, 0x067c5362 -0, 2, 2, 1, 215040, 0xd9eacb98 -0, 4, 4, 1, 215040, 0x3c8a4cbd -0, 6, 6, 1, 215040, 0xbdf996e1 -0, 8, 8, 1, 215040, 0x1b7fa123 -0, 10, 10, 1, 215040, 0x834b4a8d -0, 12, 12, 1, 215040, 0xf4b1bebe -0, 14, 14, 1, 215040, 0x088c3802 -0, 16, 16, 1, 215040, 0xf6ddedb9 -0, 18, 18, 1, 215040, 0x2791d538 -0, 20, 20, 1, 215040, 0x81fe4688 -0, 22, 22, 1, 215040, 0xad864fbd -0, 24, 24, 1, 215040, 0xa637a97a -0, 26, 26, 1, 215040, 0x2287e378 -0, 28, 28, 1, 215040, 0x13a017d7 -0, 30, 30, 1, 215040, 0x89a4acee -0, 32, 32, 1, 215040, 0x97888ffc -0, 34, 34, 1, 215040, 0x7c2c3b58 -0, 36, 36, 1, 215040, 0x2e3ab808 -0, 38, 38, 1, 215040, 0x2d553af2 -0, 40, 40, 1, 215040, 0x929c420e -0, 42, 42, 1, 215040, 0x4841bd6d -0, 44, 44, 1, 215040, 0xb350fbcd -0, 46, 46, 1, 215040, 0x0d70b918 -0, 48, 48, 1, 215040, 0xf98b0f47 -0, 50, 50, 1, 215040, 0x748b8ff2 -0, 52, 52, 1, 215040, 0x62017c38 -0, 54, 54, 1, 215040, 0x46042bb4 -0, 56, 56, 1, 215040, 0xe7a74806 -0, 58, 58, 1, 215040, 0xb4c856e6 -0, 60, 60, 1, 215040, 0xb21a28dd -0, 62, 62, 1, 215040, 0x2a6e0834 -0, 64, 64, 1, 215040, 0x7044d6ca -0, 66, 66, 1, 215040, 0x17780335 -0, 68, 68, 1, 215040, 0x94f51e7a -0, 70, 70, 1, 215040, 0x5beb5f5f -0, 72, 72, 1, 215040, 0xc7d59527 -0, 74, 74, 1, 215040, 0x40f69049 -0, 76, 76, 1, 215040, 0x1f78740e -0, 78, 78, 1, 215040, 0x49f7265d -0, 80, 80, 1, 215040, 0x057ac5c9 -0, 82, 82, 1, 215040, 0x649bd476 -0, 84, 84, 1, 215040, 0x1c75aa43 -0, 86, 86, 1, 215040, 0xc4bd1e29 -0, 88, 88, 1, 215040, 0x5033fa74 -0, 90, 90, 1, 215040, 0xba5c949e -0, 92, 92, 1, 215040, 0x2fa78a0e -0, 94, 94, 1, 215040, 0x9d363dce -0, 96, 96, 1, 215040, 0xd1dc82b0 -0, 98, 98, 1, 215040, 0xd25be322 -0, 100, 100, 1, 215040, 0xf1374ef9 -0, 102, 102, 1, 215040, 0x33467b42 -0, 104, 104, 1, 215040, 0x7ec7dfad -0, 106, 106, 1, 215040, 0x706ed416 -0, 108, 108, 1, 215040, 0x6576b3eb -0, 110, 110, 1, 215040, 0x6576b3eb -0, 112, 112, 1, 215040, 0x6576b3eb -0, 114, 114, 1, 215040, 0x6576b3eb -0, 116, 116, 1, 215040, 0x6576b3eb -0, 118, 118, 1, 215040, 0x6576b3eb -0, 120, 120, 1, 215040, 0x6576b3eb -0, 122, 122, 1, 215040, 0x6873993d -0, 124, 124, 1, 215040, 0x8c2a84d8 -0, 126, 126, 1, 215040, 0xdd456bd5 -0, 128, 128, 1, 215040, 0x50fa4f3d -0, 130, 130, 1, 215040, 0x00c4369c -0, 132, 132, 1, 215040, 0xe4c220d2 -0, 134, 134, 1, 215040, 0xe43a033b -0, 136, 136, 1, 215040, 0x72f6e32c -0, 138, 138, 1, 215040, 0xb738c69c -0, 140, 140, 1, 215040, 0x56bda3fe -0, 142, 142, 1, 215040, 0xaa2f7da3 -0, 144, 144, 1, 215040, 0xf21f5c24 -0, 146, 146, 1, 215040, 0xd33e3579 -0, 148, 148, 1, 215040, 0x6a601495 -0, 150, 150, 1, 215040, 0xdfcff1e0 -0, 152, 152, 1, 215040, 0xa774d327 -0, 154, 154, 1, 215040, 0x8e9db8c9 -0, 156, 156, 1, 215040, 0xb4fd9689 -0, 158, 158, 1, 215040, 0xa80b77ff -0, 160, 160, 1, 215040, 0x1d9c6568 -0, 162, 162, 1, 215040, 0x388c515a -0, 164, 164, 1, 215040, 0x388c515a -0, 166, 166, 1, 215040, 0x388c515a -0, 168, 168, 1, 215040, 0x388c515a -0, 170, 170, 1, 215040, 0x388c515a -0, 172, 172, 1, 215040, 0x388c515a -0, 174, 174, 1, 215040, 0x388c515a -0, 176, 176, 1, 215040, 0x388c515a -0, 178, 178, 1, 215040, 0x388c515a -0, 180, 180, 1, 215040, 0x388c515a -0, 182, 182, 1, 215040, 0x388c515a -0, 184, 184, 1, 215040, 0x3aef5fee -0, 186, 186, 1, 215040, 0x3aef5fee -0, 188, 188, 1, 215040, 0x3aef5fee -0, 190, 190, 1, 215040, 0x3aef5fee -0, 192, 192, 1, 215040, 0x7f8e4b62 -0, 194, 194, 1, 215040, 0xbf9fcae8 -0, 196, 196, 1, 215040, 0x02f9a66c -0, 198, 198, 1, 215040, 0x00ef062f -0, 200, 200, 1, 215040, 0xe83b132c -0, 202, 202, 1, 215040, 0x2701d21b -0, 204, 204, 1, 215040, 0xbea79188 -0, 206, 206, 1, 215040, 0x6f6d3109 -0, 208, 208, 1, 215040, 0x4173f1e8 -0, 210, 210, 1, 215040, 0xd7adfce1 -0, 212, 212, 1, 215040, 0xa3825ffd -0, 214, 214, 1, 215040, 0x41e63fe4 -0, 216, 216, 1, 215040, 0xb525b9c5 +0, 2, 2, 2, 215040, 0xd9eacb98 +0, 4, 4, 2, 215040, 0x3c8a4cbd +0, 6, 6, 2, 215040, 0xbdf996e1 +0, 8, 8, 2, 215040, 0x1b7fa123 +0, 10, 10, 2, 215040, 0x834b4a8d +0, 12, 12, 2, 215040, 0xf4b1bebe +0, 14, 14, 2, 215040, 0x088c3802 +0, 16, 16, 2, 215040, 0xf6ddedb9 +0, 18, 18, 2, 215040, 0x2791d538 +0, 20, 20, 2, 215040, 0x81fe4688 +0, 22, 22, 2, 215040, 0xad864fbd +0, 24, 24, 2, 215040, 0xa637a97a +0, 26, 26, 2, 215040, 0x2287e378 +0, 28, 28, 2, 215040, 0x13a017d7 +0, 30, 30, 2, 215040, 0x89a4acee +0, 32, 32, 2, 215040, 0x97888ffc +0, 34, 34, 2, 215040, 0x7c2c3b58 +0, 36, 36, 2, 215040, 0x2e3ab808 +0, 38, 38, 2, 215040, 0x2d553af2 +0, 40, 40, 2, 215040, 0x929c420e +0, 42, 42, 2, 215040, 0x4841bd6d +0, 44, 44, 2, 215040, 0xb350fbcd +0, 46, 46, 2, 215040, 0x0d70b918 +0, 48, 48, 2, 215040, 0xf98b0f47 +0, 50, 50, 2, 215040, 0x748b8ff2 +0, 52, 52, 2, 215040, 0x62017c38 +0, 54, 54, 2, 215040, 0x46042bb4 +0, 56, 56, 2, 215040, 0xe7a74806 +0, 58, 58, 2, 215040, 0xb4c856e6 +0, 60, 60, 2, 215040, 0xb21a28dd +0, 62, 62, 2, 215040, 0x2a6e0834 +0, 64, 64, 2, 215040, 0x7044d6ca +0, 66, 66, 2, 215040, 0x17780335 +0, 68, 68, 2, 215040, 0x94f51e7a +0, 70, 70, 2, 215040, 0x5beb5f5f +0, 72, 72, 2, 215040, 0xc7d59527 +0, 74, 74, 2, 215040, 0x40f69049 +0, 76, 76, 2, 215040, 0x1f78740e +0, 78, 78, 2, 215040, 0x49f7265d +0, 80, 80, 2, 215040, 0x057ac5c9 +0, 82, 82, 2, 215040, 0x649bd476 +0, 84, 84, 2, 215040, 0x1c75aa43 +0, 86, 86, 2, 215040, 0xc4bd1e29 +0, 88, 88, 2, 215040, 0x5033fa74 +0, 90, 90, 2, 215040, 0xba5c949e +0, 92, 92, 2, 215040, 0x2fa78a0e +0, 94, 94, 2, 215040, 0x9d363dce +0, 96, 96, 2, 215040, 0xd1dc82b0 +0, 98, 98, 2, 215040, 0xd25be322 +0, 100, 100, 2, 215040, 0xf1374ef9 +0, 102, 102, 2, 215040, 0x33467b42 +0, 104, 104, 2, 215040, 0x7ec7dfad +0, 106, 106, 2, 215040, 0x706ed416 +0, 108, 108, 2, 215040, 0x6576b3eb +0, 110, 110, 2, 215040, 0x6576b3eb +0, 112, 112, 2, 215040, 0x6576b3eb +0, 114, 114, 2, 215040, 0x6576b3eb +0, 116, 116, 2, 215040, 0x6576b3eb +0, 118, 118, 2, 215040, 0x6576b3eb +0, 120, 120, 2, 215040, 0x6576b3eb +0, 122, 122, 2, 215040, 0x6873993d +0, 124, 124, 2, 215040, 0x8c2a84d8 +0, 126, 126, 2, 215040, 0xdd456bd5 +0, 128, 128, 2, 215040, 0x50fa4f3d +0, 130, 130, 2, 215040, 0x00c4369c +0, 132, 132, 2, 215040, 0xe4c220d2 +0, 134, 134, 2, 215040, 0xe43a033b +0, 136, 136, 2, 215040, 0x72f6e32c +0, 138, 138, 2, 215040, 0xb738c69c +0, 140, 140, 2, 215040, 0x56bda3fe +0, 142, 142, 2, 215040, 0xaa2f7da3 +0, 144, 144, 2, 215040, 0xf21f5c24 +0, 146, 146, 2, 215040, 0xd33e3579 +0, 148, 148, 2, 215040, 0x6a601495 +0, 150, 150, 2, 215040, 0xdfcff1e0 +0, 152, 152, 2, 215040, 0xa774d327 +0, 154, 154, 2, 215040, 0x8e9db8c9 +0, 156, 156, 2, 215040, 0xb4fd9689 +0, 158, 158, 2, 215040, 0xa80b77ff +0, 160, 160, 2, 215040, 0x1d9c6568 +0, 162, 162, 2, 215040, 0x388c515a +0, 164, 164, 2, 215040, 0x388c515a +0, 166, 166, 2, 215040, 0x388c515a +0, 168, 168, 2, 215040, 0x388c515a +0, 170, 170, 2, 215040, 0x388c515a +0, 172, 172, 2, 215040, 0x388c515a +0, 174, 174, 2, 215040, 0x388c515a +0, 176, 176, 2, 215040, 0x388c515a +0, 178, 178, 2, 215040, 0x388c515a +0, 180, 180, 2, 215040, 0x388c515a +0, 182, 182, 2, 215040, 0x388c515a +0, 184, 184, 2, 215040, 0x3aef5fee +0, 186, 186, 2, 215040, 0x3aef5fee +0, 188, 188, 2, 215040, 0x3aef5fee +0, 190, 190, 2, 215040, 0x3aef5fee +0, 192, 192, 2, 215040, 0x7f8e4b62 +0, 194, 194, 2, 215040, 0xbf9fcae8 +0, 196, 196, 2, 215040, 0x02f9a66c +0, 198, 198, 2, 215040, 0x00ef062f +0, 200, 200, 2, 215040, 0xe83b132c +0, 202, 202, 2, 215040, 0x2701d21b +0, 204, 204, 2, 215040, 0xbea79188 +0, 206, 206, 2, 215040, 0x6f6d3109 +0, 208, 208, 2, 215040, 0x4173f1e8 +0, 210, 210, 2, 215040, 0xd7adfce1 +0, 212, 212, 2, 215040, 0xa3825ffd +0, 214, 214, 2, 215040, 0x41e63fe4 +0, 216, 216, 2, 215040, 0xb525b9c5 0, 218, 218, 1, 215040, 0x00000000 diff --git a/tests/ref/fate/matroska-encoding-delay b/tests/ref/fate/matroska-encoding-delay index 086fe94e93b..437992468db 100644 --- a/tests/ref/fate/matroska-encoding-delay +++ b/tests/ref/fate/matroska-encoding-delay @@ -1,4 +1,4 @@ -ce2ab14d45217a043f9f50fe6adfe5ce *tests/data/fate/matroska-encoding-delay.matroska +416f35d123daef715b7c4bbb75c9c778 *tests/data/fate/matroska-encoding-delay.matroska 961251 tests/data/fate/matroska-encoding-delay.matroska #extradata 0: 22, 0x32ea0490 #tb 0: 1/1000 diff --git a/tests/ref/fate/mpeg2-ticket6677 b/tests/ref/fate/mpeg2-ticket6677 index 2079a08c204..01e46b559b8 100644 --- a/tests/ref/fate/mpeg2-ticket6677 +++ b/tests/ref/fate/mpeg2-ticket6677 @@ -4,9 +4,9 @@ #dimensions 0: 720x480 #sar 0: 8/9 0, 1, 1, 1, 518400, 0xc1866f5f -0, 2, 2, 1, 518400, 0x9ba32764 +0, 2, 2, 2, 518400, 0x9ba32764 0, 4, 4, 1, 518400, 0xa9031bb8 0, 5, 5, 1, 518400, 0x5e2c3502 0, 6, 6, 1, 518400, 0xe860027a -0, 7, 7, 1, 518400, 0xa9152430 +0, 7, 7, 2, 518400, 0xa9152430 0, 9, 9, 1, 518400, 0xb98dd9f7 diff --git a/tests/ref/fate/tscc2-mov b/tests/ref/fate/tscc2-mov index 679f5bb63cb..068002a82e2 100644 --- a/tests/ref/fate/tscc2-mov +++ b/tests/ref/fate/tscc2-mov @@ -7,4 +7,4 @@ 0, 1, 1, 1, 1180116, 0x6f73e080 0, 2, 2, 1, 1180116, 0x5244d9e5 0, 3, 3, 1, 1180116, 0x629bf10f -0, 4, 4, 1, 1180116, 0x97c726cb +0, 4, 4, 11, 1180116, 0x97c726cb diff --git a/tests/ref/lavf/asf b/tests/ref/lavf/asf index fbcbd480d0f..340461fdb52 100644 --- a/tests/ref/lavf/asf +++ b/tests/ref/lavf/asf @@ -1,3 +1,3 @@ -76f131a5426f0ba5fc7409d1a1bbfdd7 *tests/data/lavf/lavf.asf +776cd99d73857d4ef824e3936c6a0932 *tests/data/lavf/lavf.asf 333585 tests/data/lavf/lavf.asf tests/data/lavf/lavf.asf CRC=0xf6340a10 diff --git a/tests/ref/lavf/mkv b/tests/ref/lavf/mkv index 0aeb7cfae6b..5d0bf06fa91 100644 --- a/tests/ref/lavf/mkv +++ b/tests/ref/lavf/mkv @@ -1,3 +1,3 @@ -fde4f0580865684b878f0e13997213af *tests/data/lavf/lavf.mkv +1dce6c32d49a8f637262db2d8e7f2744 *tests/data/lavf/lavf.mkv 320439 tests/data/lavf/lavf.mkv tests/data/lavf/lavf.mkv CRC=0xec6c3c68 diff --git a/tests/ref/lavf/mkv_attachment b/tests/ref/lavf/mkv_attachment index 6ab72b9a450..b79bf9a619e 100644 --- a/tests/ref/lavf/mkv_attachment +++ b/tests/ref/lavf/mkv_attachment @@ -1,3 +1,3 @@ -c75c844f592d44c2a79ff5fc1e8179e0 *tests/data/lavf/lavf.mkv_attachment +140ffb4f6a734972a9d38f4e6d57f304 *tests/data/lavf/lavf.mkv_attachment 472589 tests/data/lavf/lavf.mkv_attachment tests/data/lavf/lavf.mkv_attachment CRC=0xec6c3c68 From 7fece7676b6bffd9f697455c1fc99c02fd4d5c27 Mon Sep 17 00:00:00 2001 From: James Almer Date: Mon, 17 Apr 2023 00:11:06 -0300 Subject: [PATCH 0731/2172] avcodec/hevc_ps: further constrain allowed num_ref_loc_offsets values The spec says: "The value of num_ref_loc_offsets shall be in the range of 0 to vps_max_layers_minus1, inclusive". Signed-off-by: James Almer --- libavcodec/hevc_ps.c | 13 +++++++------ libavcodec/hevc_ps.h | 2 +- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/libavcodec/hevc_ps.c b/libavcodec/hevc_ps.c index be1d668c263..69d5504ce19 100644 --- a/libavcodec/hevc_ps.c +++ b/libavcodec/hevc_ps.c @@ -1384,18 +1384,17 @@ static void colour_mapping_table(GetBitContext *gb, HEVCPPS *pps) } static int pps_multilayer_extension(GetBitContext *gb, AVCodecContext *avctx, - HEVCPPS *pps, HEVCSPS *sps) + HEVCPPS *pps, HEVCSPS *sps, HEVCVPS *vps) { pps->poc_reset_info_present_flag = get_bits1(gb); pps->pps_infer_scaling_list_flag = get_bits1(gb); if (pps->pps_infer_scaling_list_flag) pps->pps_scaling_list_ref_layer_id = get_bits(gb, 6); - pps->num_ref_loc_offsets = get_ue_golomb_long(gb); - if (pps->num_ref_loc_offsets > FF_ARRAY_ELEMS(pps->ref_loc_offset_layer_id)) { - pps->num_ref_loc_offsets = 0; + pps->num_ref_loc_offsets = get_ue_golomb(gb); + if (pps->num_ref_loc_offsets > vps->vps_max_layers - 1) return AVERROR_INVALIDDATA; - } + for (int i = 0; i < pps->num_ref_loc_offsets; i++) { pps->ref_loc_offset_layer_id[i] = get_bits(gb, 6); pps->scaled_ref_layer_offset_present_flag[i] = get_bits1(gb); @@ -1693,6 +1692,7 @@ int ff_hevc_decode_nal_pps(GetBitContext *gb, AVCodecContext *avctx, HEVCParamSets *ps) { HEVCSPS *sps = NULL; + HEVCVPS *vps = NULL; int i, ret = 0; unsigned int pps_id = 0; ptrdiff_t nal_size; @@ -1753,6 +1753,7 @@ int ff_hevc_decode_nal_pps(GetBitContext *gb, AVCodecContext *avctx, goto err; } sps = (HEVCSPS *)ps->sps_list[pps->sps_id]->data; + vps = (HEVCVPS *)ps->vps_list[sps->vps_id]->data; pps->dependent_slice_segments_enabled_flag = get_bits1(gb); pps->output_flag_present_flag = get_bits1(gb); @@ -1921,7 +1922,7 @@ int ff_hevc_decode_nal_pps(GetBitContext *gb, AVCodecContext *avctx, } if (pps->pps_multilayer_extension_flag) { - if ((ret = pps_multilayer_extension(gb, avctx, pps, sps)) < 0) + if ((ret = pps_multilayer_extension(gb, avctx, pps, sps, vps)) < 0) goto err; } diff --git a/libavcodec/hevc_ps.h b/libavcodec/hevc_ps.h index 1f704108e35..184f87a0012 100644 --- a/libavcodec/hevc_ps.h +++ b/libavcodec/hevc_ps.h @@ -314,7 +314,7 @@ typedef struct HEVCPPS { uint8_t poc_reset_info_present_flag; uint8_t pps_infer_scaling_list_flag; uint8_t pps_scaling_list_ref_layer_id; - uint16_t num_ref_loc_offsets; + uint8_t num_ref_loc_offsets; uint8_t ref_loc_offset_layer_id[64]; uint8_t scaled_ref_layer_offset_present_flag[64]; int8_t scaled_ref_layer_left_offset[64]; From ab0f3f7fbf5e97752ba8d72ed0eddb61aaded787 Mon Sep 17 00:00:00 2001 From: James Almer Date: Mon, 17 Apr 2023 10:27:06 -0300 Subject: [PATCH 0732/2172] avcodec/hevc_ps: fix storage type for some PPS multilayer extension fields MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The spec states that the range of values for them is −2^14 to 2^14 − 1, inclusive. Signed-off-by: James Almer --- libavcodec/hevc_ps.h | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/libavcodec/hevc_ps.h b/libavcodec/hevc_ps.h index 184f87a0012..5a80cf5d80d 100644 --- a/libavcodec/hevc_ps.h +++ b/libavcodec/hevc_ps.h @@ -317,15 +317,15 @@ typedef struct HEVCPPS { uint8_t num_ref_loc_offsets; uint8_t ref_loc_offset_layer_id[64]; uint8_t scaled_ref_layer_offset_present_flag[64]; - int8_t scaled_ref_layer_left_offset[64]; - int8_t scaled_ref_layer_top_offset[64]; - int8_t scaled_ref_layer_right_offset[64]; - int8_t scaled_ref_layer_bottom_offset[64]; + int16_t scaled_ref_layer_left_offset[64]; + int16_t scaled_ref_layer_top_offset[64]; + int16_t scaled_ref_layer_right_offset[64]; + int16_t scaled_ref_layer_bottom_offset[64]; uint8_t ref_region_offset_present_flag[64]; - int8_t ref_region_left_offset[64]; - int8_t ref_region_top_offset[64]; - int8_t ref_region_right_offset[64]; - int8_t ref_region_bottom_offset[64]; + int16_t ref_region_left_offset[64]; + int16_t ref_region_top_offset[64]; + int16_t ref_region_right_offset[64]; + int16_t ref_region_bottom_offset[64]; uint8_t resample_phase_set_present_flag[64]; uint16_t phase_hor_luma[64]; uint16_t phase_ver_luma[64]; From 0760528af2cfd4dfa9eb23788a308183bd68acf3 Mon Sep 17 00:00:00 2001 From: James Almer Date: Mon, 17 Apr 2023 10:30:28 -0300 Subject: [PATCH 0733/2172] avcodec/hevc_ps: use get_ue_golomb() for some PPS multilayer extension fields Also remove the _plus* and _minus* parts of some of these to be in line with other similar fields in the decoder. Signed-off-by: James Almer --- libavcodec/hevc_ps.c | 27 +++++++++++++-------------- libavcodec/hevc_ps.h | 18 +++++++++--------- 2 files changed, 22 insertions(+), 23 deletions(-) diff --git a/libavcodec/hevc_ps.c b/libavcodec/hevc_ps.c index 69d5504ce19..7401ea23f5c 100644 --- a/libavcodec/hevc_ps.c +++ b/libavcodec/hevc_ps.c @@ -1324,7 +1324,7 @@ static void colour_mapping_octants(GetBitContext *gb, HEVCPPS *pps, int inp_dept int idx_y, int idx_cb, int idx_cr, int inp_length) { unsigned int split_octant_flag, part_num_y, coded_res_flag, res_coeff_q, res_coeff_r; - int bit_depth_cm_input_y, bit_depth_cm_output_y, cm_res_bits; + int cm_res_bits; part_num_y = 1 << pps->cm_y_part_num_log2; @@ -1346,10 +1346,9 @@ static void colour_mapping_octants(GetBitContext *gb, HEVCPPS *pps, int inp_dept if (coded_res_flag) for (int c = 0; c < 3; c++) { res_coeff_q = get_ue_golomb_long(gb); - bit_depth_cm_input_y = 8 + pps->luma_bit_depth_cm_input_minus8; - bit_depth_cm_output_y = 8 + pps->luma_bit_depth_cm_output_minus8; - cm_res_bits = FFMAX(0, 10 + bit_depth_cm_input_y - bit_depth_cm_output_y - - pps->cm_res_quant_bits - (pps->cm_delta_flc_bits_minus1 + 1)); + cm_res_bits = FFMAX(0, 10 + pps->luma_bit_depth_cm_input - + pps->luma_bit_depth_cm_output - + pps->cm_res_quant_bits - pps->cm_delta_flc_bits); res_coeff_r = cm_res_bits ? get_bits(gb, cm_res_bits) : 0; if (res_coeff_q || res_coeff_r) skip_bits1(gb); @@ -1367,13 +1366,13 @@ static void colour_mapping_table(GetBitContext *gb, HEVCPPS *pps) pps->cm_octant_depth = get_bits(gb, 2); pps->cm_y_part_num_log2 = get_bits(gb, 2); - pps->luma_bit_depth_cm_input_minus8 = get_ue_golomb_long(gb); - pps->chroma_bit_depth_cm_input_minus8 = get_ue_golomb_long(gb); - pps->luma_bit_depth_cm_output_minus8 = get_ue_golomb_long(gb); - pps->chroma_bit_depth_cm_output_minus8 = get_ue_golomb_long(gb); + pps->luma_bit_depth_cm_input = get_ue_golomb(gb) + 8; + pps->chroma_bit_depth_cm_input = get_ue_golomb(gb) + 8; + pps->luma_bit_depth_cm_output = get_ue_golomb(gb) + 8; + pps->chroma_bit_depth_cm_output = get_ue_golomb(gb) + 8; pps->cm_res_quant_bits = get_bits(gb, 2); - pps->cm_delta_flc_bits_minus1 = get_bits(gb, 2); + pps->cm_delta_flc_bits = get_bits(gb, 2) + 1; if (pps->cm_octant_depth == 1) { pps->cm_adapt_threshold_u_delta = get_se_golomb_long(gb); @@ -1415,10 +1414,10 @@ static int pps_multilayer_extension(GetBitContext *gb, AVCodecContext *avctx, pps->resample_phase_set_present_flag[i] = get_bits1(gb); if (pps->resample_phase_set_present_flag[i]) { - pps->phase_hor_luma[pps->ref_loc_offset_layer_id[i]] = get_ue_golomb_long(gb); - pps->phase_ver_luma[pps->ref_loc_offset_layer_id[i]] = get_ue_golomb_long(gb); - pps->phase_hor_chroma_plus8[pps->ref_loc_offset_layer_id[i]] = get_ue_golomb_long(gb); - pps->phase_ver_chroma_plus8[pps->ref_loc_offset_layer_id[i]] = get_ue_golomb_long(gb); + pps->phase_hor_luma[pps->ref_loc_offset_layer_id[i]] = get_ue_golomb_31(gb); + pps->phase_ver_luma[pps->ref_loc_offset_layer_id[i]] = get_ue_golomb_31(gb); + pps->phase_hor_chroma[pps->ref_loc_offset_layer_id[i]] = get_ue_golomb(gb) - 8; + pps->phase_ver_chroma[pps->ref_loc_offset_layer_id[i]] = get_ue_golomb(gb) - 8; } } diff --git a/libavcodec/hevc_ps.h b/libavcodec/hevc_ps.h index 5a80cf5d80d..0c9c2786628 100644 --- a/libavcodec/hevc_ps.h +++ b/libavcodec/hevc_ps.h @@ -327,21 +327,21 @@ typedef struct HEVCPPS { int16_t ref_region_right_offset[64]; int16_t ref_region_bottom_offset[64]; uint8_t resample_phase_set_present_flag[64]; - uint16_t phase_hor_luma[64]; - uint16_t phase_ver_luma[64]; - uint16_t phase_hor_chroma_plus8[64]; - uint16_t phase_ver_chroma_plus8[64]; + uint8_t phase_hor_luma[64]; + uint8_t phase_ver_luma[64]; + int8_t phase_hor_chroma[64]; + int8_t phase_ver_chroma[64]; uint8_t colour_mapping_enabled_flag; uint16_t num_cm_ref_layers_minus1; uint8_t cm_ref_layer_id[63]; uint8_t cm_octant_depth; uint8_t cm_y_part_num_log2; - uint16_t luma_bit_depth_cm_input_minus8; - uint16_t chroma_bit_depth_cm_input_minus8; - uint16_t luma_bit_depth_cm_output_minus8; - uint16_t chroma_bit_depth_cm_output_minus8; + uint8_t luma_bit_depth_cm_input; + uint8_t chroma_bit_depth_cm_input; + uint8_t luma_bit_depth_cm_output; + uint8_t chroma_bit_depth_cm_output; uint8_t cm_res_quant_bits; - uint8_t cm_delta_flc_bits_minus1; + uint8_t cm_delta_flc_bits; int8_t cm_adapt_threshold_u_delta; int8_t cm_adapt_threshold_v_delta; From 40bae5be5e33dd5695936f47524800213bc34000 Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Mon, 17 Apr 2023 19:19:42 +0200 Subject: [PATCH 0734/2172] avcodec: add PDV decoder --- Changelog | 1 + configure | 1 + libavcodec/Makefile | 1 + libavcodec/allcodecs.c | 1 + libavcodec/codec_desc.c | 7 +++ libavcodec/codec_id.h | 1 + libavcodec/pdvdec.c | 127 ++++++++++++++++++++++++++++++++++++++++ libavcodec/version.h | 2 +- 8 files changed, 140 insertions(+), 1 deletion(-) create mode 100644 libavcodec/pdvdec.c diff --git a/Changelog b/Changelog index a40f32c23f9..b972302beb6 100644 --- a/Changelog +++ b/Changelog @@ -3,6 +3,7 @@ releases are sorted from youngest to oldest. version : - libaribcaption decoder +- Playdate video decoder version 6.0: - Radiance HDR image support diff --git a/configure b/configure index 033db7442d3..549ed1401c3 100755 --- a/configure +++ b/configure @@ -2899,6 +2899,7 @@ notchlc_decoder_select="lzf" nuv_decoder_select="idctdsp" opus_decoder_deps="swresample" opus_encoder_select="audio_frame_queue" +pdv_decoder_deps="zlib" png_decoder_select="inflate_wrapper" png_encoder_select="deflate_wrapper llvidencdsp" prores_decoder_select="blockdsp idctdsp" diff --git a/libavcodec/Makefile b/libavcodec/Makefile index aa10fbfcf8f..a1a8b8b88e9 100644 --- a/libavcodec/Makefile +++ b/libavcodec/Makefile @@ -583,6 +583,7 @@ OBJS-$(CONFIG_PBM_DECODER) += pnmdec.o pnm.o OBJS-$(CONFIG_PBM_ENCODER) += pnmenc.o OBJS-$(CONFIG_PCX_DECODER) += pcx.o OBJS-$(CONFIG_PCX_ENCODER) += pcxenc.o +OBJS-$(CONFIG_PDV_DECODER) += pdvdec.o OBJS-$(CONFIG_PFM_DECODER) += pnmdec.o pnm.o OBJS-$(CONFIG_PFM_ENCODER) += pnmenc.o OBJS-$(CONFIG_PGM_DECODER) += pnmdec.o pnm.o diff --git a/libavcodec/allcodecs.c b/libavcodec/allcodecs.c index 797fe394860..8eeed34e57b 100644 --- a/libavcodec/allcodecs.c +++ b/libavcodec/allcodecs.c @@ -251,6 +251,7 @@ extern const FFCodec ff_pbm_encoder; extern const FFCodec ff_pbm_decoder; extern const FFCodec ff_pcx_encoder; extern const FFCodec ff_pcx_decoder; +extern const FFCodec ff_pdv_decoder; extern const FFCodec ff_pfm_encoder; extern const FFCodec ff_pfm_decoder; extern const FFCodec ff_pgm_encoder; diff --git a/libavcodec/codec_desc.c b/libavcodec/codec_desc.c index efdcb59bc9a..d40977d6b3b 100644 --- a/libavcodec/codec_desc.c +++ b/libavcodec/codec_desc.c @@ -1923,6 +1923,13 @@ static const AVCodecDescriptor codec_descriptors[] = { .long_name = NULL_IF_CONFIG_SMALL("ViewQuest VQC"), .props = AV_CODEC_PROP_LOSSY, }, + { + .id = AV_CODEC_ID_PDV, + .type = AVMEDIA_TYPE_VIDEO, + .name = "pdv", + .long_name = NULL_IF_CONFIG_SMALL("PDV (PlayDate Video)"), + .props = AV_CODEC_PROP_LOSSY, + }, /* various PCM "codecs" */ { diff --git a/libavcodec/codec_id.h b/libavcodec/codec_id.h index 64df9699f42..70800ec20b1 100644 --- a/libavcodec/codec_id.h +++ b/libavcodec/codec_id.h @@ -320,6 +320,7 @@ enum AVCodecID { AV_CODEC_ID_WBMP, AV_CODEC_ID_MEDIA100, AV_CODEC_ID_VQC, + AV_CODEC_ID_PDV, /* various PCM "codecs" */ AV_CODEC_ID_FIRST_AUDIO = 0x10000, ///< A dummy id pointing at the start of audio codecs diff --git a/libavcodec/pdvdec.c b/libavcodec/pdvdec.c new file mode 100644 index 00000000000..690a298e167 --- /dev/null +++ b/libavcodec/pdvdec.c @@ -0,0 +1,127 @@ +/* + * PDV video format + * + * Copyright (c) 2023 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 "avcodec.h" +#include "codec_internal.h" +#include "decode.h" +#include "zlib_wrapper.h" + +#include + +typedef struct PDVContext { + AVFrame *previous_frame; + FFZStream zstream; +} PDVContext; + +static av_cold int decode_init(AVCodecContext *avctx) +{ + PDVContext *s = avctx->priv_data; + + avctx->pix_fmt = AV_PIX_FMT_MONOBLACK; + + s->previous_frame = av_frame_alloc(); + if (!s->previous_frame) + return AVERROR(ENOMEM); + + return ff_inflate_init(&s->zstream, avctx); +} + +static av_cold int decode_end(AVCodecContext *avctx) +{ + PDVContext *s = avctx->priv_data; + + av_frame_free(&s->previous_frame); + ff_inflate_end(&s->zstream); + + return 0; +} + +static int decode_frame(AVCodecContext *avctx, AVFrame *frame, + int *got_frame, AVPacket *avpkt) +{ + PDVContext *s = avctx->priv_data; + AVFrame *prev_frame = s->previous_frame; + z_stream *const zstream = &s->zstream.zstream; + uint8_t *dst, *prev = prev_frame->data[0]; + int ret, zret; + + zret = inflateReset(zstream); + if (zret != Z_OK) { + av_log(avctx, AV_LOG_ERROR, "Could not reset inflate: %d.\n", zret); + return AVERROR_INVALIDDATA; + } + + if ((ret = ff_get_buffer(avctx, frame, AV_GET_BUFFER_FLAG_REF)) < 0) + return ret; + + zstream->next_in = avpkt->data; + zstream->avail_in = avpkt->size; + + dst = frame->data[0]; + for (int i = 0; i < avctx->height; i++) { + zstream->next_out = dst; + zstream->avail_out = (avctx->width + 7) >> 3; + + zret = inflate(zstream, Z_SYNC_FLUSH); + if (zret != Z_OK && zret != Z_STREAM_END) { + av_log(avctx, AV_LOG_ERROR, + "Inflate failed with return code: %d.\n", zret); + return AVERROR_INVALIDDATA; + } + + if (!(avpkt->flags & AV_PKT_FLAG_KEY)) { + for (int j = 0; j < (avctx->width + 7) >> 3; j++) + dst[j] ^= prev[j]; + prev += prev_frame->linesize[0]; + } + + dst += frame->linesize[0]; + } + + av_frame_unref(s->previous_frame); + if ((ret = av_frame_ref(s->previous_frame, frame)) < 0) + return ret; + + if (avpkt->flags & AV_PKT_FLAG_KEY) { + frame->key_frame = 1; + frame->pict_type = AV_PICTURE_TYPE_I; + } else { + frame->pict_type = AV_PICTURE_TYPE_P; + } + + *got_frame = 1; + + return avpkt->size; +} + +const FFCodec ff_pdv_decoder = { + .p.name = "pdv", + CODEC_LONG_NAME("PDV (PlayDate Video)"), + .priv_data_size = sizeof(PDVContext), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_PDV, + .p.capabilities = AV_CODEC_CAP_DR1, + .caps_internal = FF_CODEC_CAP_SKIP_FRAME_FILL_PARAM, + .init = decode_init, + .close = decode_end, + FF_CODEC_DECODE_CB(decode_frame), +}; diff --git a/libavcodec/version.h b/libavcodec/version.h index 230d5fa13e6..80e2ae630df 100644 --- a/libavcodec/version.h +++ b/libavcodec/version.h @@ -29,7 +29,7 @@ #include "version_major.h" -#define LIBAVCODEC_VERSION_MINOR 9 +#define LIBAVCODEC_VERSION_MINOR 10 #define LIBAVCODEC_VERSION_MICRO 100 #define LIBAVCODEC_VERSION_INT AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \ From dc2da568cfd281740102032582ca25bbf4449100 Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Mon, 17 Apr 2023 17:45:23 +0200 Subject: [PATCH 0735/2172] avformat: add PDV demuxer --- Changelog | 2 +- libavformat/Makefile | 1 + libavformat/allformats.c | 1 + libavformat/pdvdec.c | 173 +++++++++++++++++++++++++++++++++++++++ libavformat/version.h | 4 +- 5 files changed, 178 insertions(+), 3 deletions(-) create mode 100644 libavformat/pdvdec.c diff --git a/Changelog b/Changelog index b972302beb6..4284a250a22 100644 --- a/Changelog +++ b/Changelog @@ -3,7 +3,7 @@ releases are sorted from youngest to oldest. version : - libaribcaption decoder -- Playdate video decoder +- Playdate video decoder and demuxer version 6.0: - Radiance HDR image support diff --git a/libavformat/Makefile b/libavformat/Makefile index 048649689b1..f8ad7c6a116 100644 --- a/libavformat/Makefile +++ b/libavformat/Makefile @@ -471,6 +471,7 @@ OBJS-$(CONFIG_PCM_U8_DEMUXER) += pcmdec.o pcm.o OBJS-$(CONFIG_PCM_U8_MUXER) += pcmenc.o rawenc.o OBJS-$(CONFIG_PCM_VIDC_DEMUXER) += pcmdec.o pcm.o OBJS-$(CONFIG_PCM_VIDC_MUXER) += pcmenc.o rawenc.o +OBJS-$(CONFIG_PDV_DEMUXER) += pdvdec.o OBJS-$(CONFIG_PJS_DEMUXER) += pjsdec.o subtitles.o OBJS-$(CONFIG_PMP_DEMUXER) += pmpdec.o OBJS-$(CONFIG_PP_BNK_DEMUXER) += pp_bnk.o diff --git a/libavformat/allformats.c b/libavformat/allformats.c index cb5b69e9cd6..efdb34e29d9 100644 --- a/libavformat/allformats.c +++ b/libavformat/allformats.c @@ -369,6 +369,7 @@ extern const AVInputFormat ff_pcm_u16le_demuxer; extern const FFOutputFormat ff_pcm_u16le_muxer; extern const AVInputFormat ff_pcm_u8_demuxer; extern const FFOutputFormat ff_pcm_u8_muxer; +extern const AVInputFormat ff_pdv_demuxer; extern const AVInputFormat ff_pjs_demuxer; extern const AVInputFormat ff_pmp_demuxer; extern const AVInputFormat ff_pp_bnk_demuxer; diff --git a/libavformat/pdvdec.c b/libavformat/pdvdec.c new file mode 100644 index 00000000000..9d3f386e40d --- /dev/null +++ b/libavformat/pdvdec.c @@ -0,0 +1,173 @@ +/* + * PDV demuxer + * Copyright (c) 2023 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 "avformat.h" +#include "internal.h" + +#define PDV_MAGIC "Playdate VID\x00\x00\x00\x00" + +typedef struct PDVDemuxContext { + int current_frame; + uint8_t *frame_flags; + uint32_t *frame_offsets; +} PDVDemuxContext; + +static int pdv_probe(const AVProbeData *pd) +{ + if (strncmp(pd->buf, PDV_MAGIC, sizeof(PDV_MAGIC) - 1) == 0) + return AVPROBE_SCORE_MAX; + return 0; +} + +static int pdv_read_header(AVFormatContext *s) +{ + PDVDemuxContext *p = s->priv_data; + AVIOContext *pb = s->pb; + AVCodecParameters *par; + AVStream *st; + uint64_t start; + uint32_t fps; + + avio_skip(pb, 16); + + st = avformat_new_stream(s, NULL); + if (!st) + return AVERROR(ENOMEM); + + par = st->codecpar; + par->codec_type = AVMEDIA_TYPE_VIDEO; + par->codec_id = AV_CODEC_ID_PDV; + st->start_time = 0; + st->duration = + st->nb_frames = avio_rl16(pb); + avio_skip(pb, 2); + fps = avio_rl32(pb); + st->avg_frame_rate = av_d2q(av_int2float(fps), INT_MAX); + par->width = avio_rl16(pb); + par->height = avio_rl16(pb); + + avpriv_set_pts_info(st, 64, st->avg_frame_rate.den, st->avg_frame_rate.num); + + p->current_frame = 0; + p->frame_flags = av_calloc(st->nb_frames + 1, sizeof(*p->frame_flags)); + p->frame_offsets = av_calloc(st->nb_frames + 1, sizeof(*p->frame_offsets)); + + if (!p->frame_flags || !p->frame_offsets) + return AVERROR(ENOMEM); + + for (int n = 0; n <= st->nb_frames; n++) { + const uint32_t entry = avio_rl32(pb); + + p->frame_flags[n] = entry & 3; + p->frame_offsets[n] = entry >> 2; + } + + start = avio_tell(pb); + + for (int n = 0; n < st->nb_frames; n++) { + const uint64_t pos = start + p->frame_offsets[n]; + const int32_t size = p->frame_offsets[n+1] - p->frame_offsets[n]; + const int flags = p->frame_flags[n] & 1 ? AVINDEX_KEYFRAME : 0; + + if (p->frame_flags[n] == 0 || size <= 0 || + ((pb->seekable & AVIO_SEEKABLE_NORMAL) && pos + size > avio_size(pb))) + break; + av_add_index_entry(st, pos, n, size, 0, flags); + } + + return 0; +} + +static int pdv_read_packet(AVFormatContext *s, AVPacket *pkt) +{ + PDVDemuxContext *p = s->priv_data; + AVStream *st = s->streams[0]; + FFStream *const sti = ffstream(st); + AVIOContext *pb = s->pb; + int32_t size, flags, ret; + int64_t pos; + + if (p->current_frame >= st->nb_frames) + return AVERROR_EOF; + + if (p->current_frame >= sti->nb_index_entries) + return AVERROR(EIO); + + pos = sti->index_entries[p->current_frame].pos; + flags = sti->index_entries[p->current_frame].flags; + size = sti->index_entries[p->current_frame].size; + + avio_seek(pb, pos, SEEK_SET); + if (avio_feof(pb) || ((pb->seekable & AVIO_SEEKABLE_NORMAL) && pos + size > avio_size(pb)) || size == 0) + return AVERROR_EOF; + + ret = av_get_packet(pb, pkt, size); + if (ret < 0) + return ret; + + if (flags & AVINDEX_KEYFRAME) + pkt->flags |= AV_PKT_FLAG_KEY; + pkt->stream_index = 0; + pkt->pts = p->current_frame++; + pkt->duration = 1; + + return 0; +} + +static int pdv_read_close(AVFormatContext *s) +{ + PDVDemuxContext *p = s->priv_data; + + av_freep(&p->frame_flags); + av_freep(&p->frame_offsets); + + return 0; +} + +static int pdv_read_seek(AVFormatContext *s, int stream_index, int64_t timestamp, int flags) +{ + PDVDemuxContext *p = s->priv_data; + AVStream *st = s->streams[stream_index]; + int index = av_index_search_timestamp(st, timestamp, flags); + + if (index < 0) + return -1; + + if (avio_seek(s->pb, ffstream(st)->index_entries[index].pos, SEEK_SET) < 0) + return -1; + + p->current_frame = index; + + return 0; +} + +const AVInputFormat ff_pdv_demuxer = { + .name = "pdv", + .long_name = NULL_IF_CONFIG_SMALL("PlayDate Video"), + .priv_data_size = sizeof(PDVDemuxContext), + .flags_internal = FF_FMT_INIT_CLEANUP, + .read_probe = pdv_probe, + .read_header = pdv_read_header, + .read_packet = pdv_read_packet, + .read_close = pdv_read_close, + .read_seek = pdv_read_seek, + .extensions = "pdv", +}; diff --git a/libavformat/version.h b/libavformat/version.h index cc56b7cf5ca..e2634b85ae1 100644 --- a/libavformat/version.h +++ b/libavformat/version.h @@ -31,8 +31,8 @@ #include "version_major.h" -#define LIBAVFORMAT_VERSION_MINOR 4 -#define LIBAVFORMAT_VERSION_MICRO 101 +#define LIBAVFORMAT_VERSION_MINOR 5 +#define LIBAVFORMAT_VERSION_MICRO 100 #define LIBAVFORMAT_VERSION_INT AV_VERSION_INT(LIBAVFORMAT_VERSION_MAJOR, \ LIBAVFORMAT_VERSION_MINOR, \ From 0dceda12e7c3d10865e1167407878381efa5a138 Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Thu, 20 Apr 2023 17:10:27 +0200 Subject: [PATCH 0736/2172] avcodec/pdvdec: fix leaks on init failure and when seeking --- libavcodec/pdvdec.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/libavcodec/pdvdec.c b/libavcodec/pdvdec.c index 690a298e167..d1a3d1d3f9b 100644 --- a/libavcodec/pdvdec.c +++ b/libavcodec/pdvdec.c @@ -113,6 +113,13 @@ static int decode_frame(AVCodecContext *avctx, AVFrame *frame, return avpkt->size; } +static void decode_flush(AVCodecContext *avctx) +{ + PDVContext *s = avctx->priv_data; + + av_frame_unref(s->previous_frame); +} + const FFCodec ff_pdv_decoder = { .p.name = "pdv", CODEC_LONG_NAME("PDV (PlayDate Video)"), @@ -120,8 +127,10 @@ const FFCodec ff_pdv_decoder = { .p.type = AVMEDIA_TYPE_VIDEO, .p.id = AV_CODEC_ID_PDV, .p.capabilities = AV_CODEC_CAP_DR1, - .caps_internal = FF_CODEC_CAP_SKIP_FRAME_FILL_PARAM, + .caps_internal = FF_CODEC_CAP_SKIP_FRAME_FILL_PARAM | + FF_CODEC_CAP_INIT_CLEANUP, .init = decode_init, .close = decode_end, + .flush = decode_flush, FF_CODEC_DECODE_CB(decode_frame), }; From adeb5b6c67f84ba3a6b527c374e9d41129473b22 Mon Sep 17 00:00:00 2001 From: James Almer Date: Thu, 20 Apr 2023 12:50:01 -0300 Subject: [PATCH 0737/2172] avcodec/pdvdec: honor the requested avctx->skip_frame value The decoder is tagged as being FF_CODEC_CAP_SKIP_FRAME_FILL_PARAM, so might as well make use of it. Reviewed-by: Paul B Mahol Signed-off-by: James Almer --- libavcodec/pdvdec.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/libavcodec/pdvdec.c b/libavcodec/pdvdec.c index d1a3d1d3f9b..b1fc19b1c93 100644 --- a/libavcodec/pdvdec.c +++ b/libavcodec/pdvdec.c @@ -64,6 +64,11 @@ static int decode_frame(AVCodecContext *avctx, AVFrame *frame, uint8_t *dst, *prev = prev_frame->data[0]; int ret, zret; + if (avctx->skip_frame >= AVDISCARD_ALL || + (avctx->skip_frame >= AVDISCARD_NONINTRA && + !(avpkt->flags & AV_PKT_FLAG_KEY))) + return avpkt->size; + zret = inflateReset(zstream); if (zret != Z_OK) { av_log(avctx, AV_LOG_ERROR, "Could not reset inflate: %d.\n", zret); From 4570ba5d86784f6a49e49e6cddfb0d5fb4bcd39a Mon Sep 17 00:00:00 2001 From: Steven Liu Date: Fri, 21 Apr 2023 14:04:11 +0800 Subject: [PATCH 0738/2172] fate/png-icc-parse: update ref data When enable lcms2, the fate-png-icc-parse will get error bellow. TEST png-icc-parse This because updated how PNG handles colors (no longer using mastering display metadata for that). Reviewed-by: Leo Izen Signed-off-by: Steven Liu --- tests/ref/fate/png-icc-parse | 17 +++++------------ 1 file changed, 5 insertions(+), 12 deletions(-) diff --git a/tests/ref/fate/png-icc-parse b/tests/ref/fate/png-icc-parse index 18bb18a8047..ffefce270ad 100644 --- a/tests/ref/fate/png-icc-parse +++ b/tests/ref/fate/png-icc-parse @@ -16,6 +16,10 @@ pkt_pos=0 pkt_size=40194 width=128 height=128 +crop_top=0 +crop_bottom=0 +crop_left=0 +crop_right=0 pix_fmt=rgb24 sample_aspect_ratio=1:1 pict_type=I @@ -25,7 +29,7 @@ interlaced_frame=1 top_field_first=0 repeat_pict=0 color_range=pc -color_space=unknown +color_space=gbr color_primaries=bt709 color_transfer=iec61966-2-1 chroma_location=unspecified @@ -34,15 +38,4 @@ side_data_type=ICC profile name=Photoshop ICC profile size=3144 [/SIDE_DATA] -[SIDE_DATA] -side_data_type=Mastering display metadata -red_x=63999/100000 -red_y=33001/100000 -green_x=30000/100000 -green_y=60000/100000 -blue_x=15000/100000 -blue_y=5999/100000 -white_point_x=31269/100000 -white_point_y=32899/100000 -[/SIDE_DATA] [/FRAME] From 0e1745774ebd0ee077a66d4122ab2c810a01ec05 Mon Sep 17 00:00:00 2001 From: James Almer Date: Fri, 21 Apr 2023 09:25:40 -0300 Subject: [PATCH 0739/2172] fftools/ffprobe: fix printing AVFrame.crop_right Signed-off-by: James Almer --- fftools/ffprobe.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fftools/ffprobe.c b/fftools/ffprobe.c index d6e5a79c7e7..6e72c37721b 100644 --- a/fftools/ffprobe.c +++ b/fftools/ffprobe.c @@ -2623,7 +2623,7 @@ static void show_frame(WriterContext *w, AVFrame *frame, AVStream *stream, print_int("crop_top", frame->crop_top); print_int("crop_bottom", frame->crop_bottom); print_int("crop_left", frame->crop_left); - print_int("crop_right", frame->crop_left); + print_int("crop_right", frame->crop_right); s = av_get_pix_fmt_name(frame->format); if (s) print_str ("pix_fmt", s); else print_str_opt("pix_fmt", "unknown"); From 869248c053856e654002f0650b02d22648b563ba Mon Sep 17 00:00:00 2001 From: Leo Izen Date: Mon, 17 Apr 2023 15:29:55 -0400 Subject: [PATCH 0740/2172] avcodec/mjpegdec: fix remaining RGB JPEGs The change introduced in b18a9c29713abc3a1b081de3f320ab53a47120c6 created a regression for non-subsampled progressive RGB jpegs. This should fix that. Additionally, this should fix other RGB JPEGs broken before the recent patches, such as those in Trac issue #10190. --- libavcodec/mjpegdec.c | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/libavcodec/mjpegdec.c b/libavcodec/mjpegdec.c index c41d4bce5eb..9b55002c4b7 100644 --- a/libavcodec/mjpegdec.c +++ b/libavcodec/mjpegdec.c @@ -604,7 +604,7 @@ int ff_mjpeg_decode_sof(MJpegDecodeContext *s) if (s->bits <= 8) s->avctx->pix_fmt = AV_PIX_FMT_GBRP; else goto unk_pixfmt; - s->upscale_v[0] = s->upscale_v[1] = 1; + s->upscale_v[1] = s->upscale_v[2] = 1; } else { if (pix_fmt_id == 0x14111100) s->upscale_v[1] = s->upscale_v[2] = 1; @@ -619,7 +619,7 @@ int ff_mjpeg_decode_sof(MJpegDecodeContext *s) if (s->bits <= 8) s->avctx->pix_fmt = AV_PIX_FMT_GBRP; else goto unk_pixfmt; - s->upscale_h[0] = s->upscale_h[1] = 1; + s->upscale_h[1] = s->upscale_h[2] = 1; } else { if (s->bits <= 8) s->avctx->pix_fmt = s->cs_itu601 ? AV_PIX_FMT_YUV422P : AV_PIX_FMT_YUVJ422P; else s->avctx->pix_fmt = AV_PIX_FMT_YUV422P16; @@ -1698,9 +1698,6 @@ int ff_mjpeg_decode_sos(MJpegDecodeContext *s, const uint8_t *mb_bitmask, s->h_scount[i] = s->h_count[index]; s->v_scount[i] = s->v_count[index]; - if(nb_components == 3 && s->nb_components == 3 && s->avctx->pix_fmt == AV_PIX_FMT_GBRP) - index = (index+2)%3; - s->comp_index[i] = index; s->dc_index[i] = get_bits(&s->gb, 4); @@ -2724,7 +2721,7 @@ int ff_mjpeg_decode_frame_from_buf(AVCodecContext *avctx, AVFrame *frame, } } - if (s->avctx->pix_fmt == AV_PIX_FMT_GBRP && s->progressive) { + if (s->avctx->pix_fmt == AV_PIX_FMT_GBRP) { av_assert0(s->nb_components == 3); FFSWAP(uint8_t *, frame->data[0], frame->data[2]); FFSWAP(uint8_t *, frame->data[0], frame->data[1]); From 453b524974423de9d933f5856b511d2b3f4cdec6 Mon Sep 17 00:00:00 2001 From: Leo Izen Date: Tue, 18 Apr 2023 10:49:24 -0400 Subject: [PATCH 0741/2172] fate: add tests for RGB jpegs Added framecrc tests for RGB JPEGs to verify future changes to the decoder. --- tests/fate/image.mak | 9 +++++++++ tests/ref/fate/jpg-rgb-221 | 6 ++++++ tests/ref/fate/jpg-rgb-baseline | 6 ++++++ tests/ref/fate/jpg-rgb-progressive | 6 ++++++ 4 files changed, 27 insertions(+) create mode 100644 tests/ref/fate/jpg-rgb-221 create mode 100644 tests/ref/fate/jpg-rgb-baseline create mode 100644 tests/ref/fate/jpg-rgb-progressive diff --git a/tests/fate/image.mak b/tests/fate/image.mak index 42dd90feaaf..93bc715ca3c 100644 --- a/tests/fate/image.mak +++ b/tests/fate/image.mak @@ -337,6 +337,15 @@ fate-jpg-12bpp: CMD = framecrc -idct simple -i $(TARGET_SAMPLES)/jpg/12bpp.jpg - FATE_JPG += fate-jpg-jfif fate-jpg-jfif: CMD = framecrc -idct simple -i $(TARGET_SAMPLES)/jpg/20242.jpg +FATE_JPG += fate-jpg-rgb-baseline +fate-jpg-rgb-baseline: CMD = framecrc -idct simple -i $(TARGET_SAMPLES)/jpg/george-insect-rgb-baseline.jpg + +FATE_JPG += fate-jpg-rgb-progressive +fate-jpg-rgb-progressive: CMD = framecrc -idct simple -i $(TARGET_SAMPLES)/jpg/george-insect-rgb-progressive.jpg + +FATE_JPG += fate-jpg-rgb-221 +fate-jpg-rgb-221: CMD = framecrc -idct simple -i $(TARGET_SAMPLES)/jpg/george-insect-rgb-xyb.jpg + FATE_JPG_TRANSCODE-$(call TRANSCODE, MJPEG, MJPEG IMAGE_JPEG_PIPE, IMAGE_PNG_PIPE_DEMUXER PNG_DECODER SCALE_FILTER) += fate-jpg-icc fate-jpg-icc: CMD = transcode png_pipe $(TARGET_SAMPLES)/png1/lena-int_rgb24.png mjpeg "-vf scale" "" "-show_frames" diff --git a/tests/ref/fate/jpg-rgb-221 b/tests/ref/fate/jpg-rgb-221 new file mode 100644 index 00000000000..32250db4939 --- /dev/null +++ b/tests/ref/fate/jpg-rgb-221 @@ -0,0 +1,6 @@ +#tb 0: 1/25 +#media_type 0: video +#codec_id 0: rawvideo +#dimensions 0: 64x43 +#sar 0: 0/1 +0, 0, 0, 1, 8256, 0x81617757 diff --git a/tests/ref/fate/jpg-rgb-baseline b/tests/ref/fate/jpg-rgb-baseline new file mode 100644 index 00000000000..f7ff29e9a2e --- /dev/null +++ b/tests/ref/fate/jpg-rgb-baseline @@ -0,0 +1,6 @@ +#tb 0: 1/25 +#media_type 0: video +#codec_id 0: rawvideo +#dimensions 0: 64x43 +#sar 0: 0/1 +0, 0, 0, 1, 8256, 0x98ad8863 diff --git a/tests/ref/fate/jpg-rgb-progressive b/tests/ref/fate/jpg-rgb-progressive new file mode 100644 index 00000000000..b0d118d21a7 --- /dev/null +++ b/tests/ref/fate/jpg-rgb-progressive @@ -0,0 +1,6 @@ +#tb 0: 1/25 +#media_type 0: video +#codec_id 0: rawvideo +#dimensions 0: 64x43 +#sar 0: 0/1 +0, 0, 0, 1, 8256, 0xbb6e8830 From 86645bf0a6b2a02b90bf0a17a14d7e750b1b9d40 Mon Sep 17 00:00:00 2001 From: James Almer Date: Mon, 17 Apr 2023 20:52:23 -0300 Subject: [PATCH 0742/2172] avcodec/pcm_rechunk_bsf: assert that in_pkt is empty after merging its data into out_pkt If it's not empty here, then a leak would ocurr immediately after. Signed-off-by: James Almer --- libavcodec/pcm_rechunk_bsf.c | 1 + 1 file changed, 1 insertion(+) diff --git a/libavcodec/pcm_rechunk_bsf.c b/libavcodec/pcm_rechunk_bsf.c index 032f9149164..28b5722ac97 100644 --- a/libavcodec/pcm_rechunk_bsf.c +++ b/libavcodec/pcm_rechunk_bsf.c @@ -139,6 +139,7 @@ static int rechunk_filter(AVBSFContext *ctx, AVPacket *pkt) av_packet_move_ref(pkt, s->out_pkt); return send_packet(s, nb_samples, pkt); } + av_assert0(!s->in_pkt->size); } else if (s->in_pkt->size > data_size) { ret = av_packet_ref(pkt, s->in_pkt); if (ret < 0) From de5e2570f07ec1d801c739e13a98ec717899fb3f Mon Sep 17 00:00:00 2001 From: Jun Zhao Date: Tue, 18 Apr 2023 17:08:52 +0800 Subject: [PATCH 0743/2172] lavc/libopenh264: Support full range videos in transcoding Support full range videos when transcoding, enabled the YUVJ420P to avoid auto scale from YUVJ420P to YUV420P Signed-off-by: Jun Zhao --- libavcodec/libopenh264enc.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/libavcodec/libopenh264enc.c b/libavcodec/libopenh264enc.c index 8b4755f5ba4..cccc11fbb7e 100644 --- a/libavcodec/libopenh264enc.c +++ b/libavcodec/libopenh264enc.c @@ -311,10 +311,12 @@ 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); - } + } else if (avctx->pix_fmt == AV_PIX_FMT_YUVJ420P) + param.sSpatialLayers[0].bFullRange = 1; if (avctx->colorspace != AVCOL_SPC_UNSPECIFIED || avctx->color_primaries != AVCOL_PRI_UNSPECIFIED || @@ -443,6 +445,7 @@ const FFCodec ff_libopenh264_encoder = { .caps_internal = FF_CODEC_CAP_INIT_CLEANUP | FF_CODEC_CAP_AUTO_THREADS, .p.pix_fmts = (const enum AVPixelFormat[]){ AV_PIX_FMT_YUV420P, + AV_PIX_FMT_YUVJ420P, AV_PIX_FMT_NONE }, .defaults = svc_enc_defaults, .p.priv_class = &class, From 73ddcad990e2c9c050df6b57509d11137e61eae4 Mon Sep 17 00:00:00 2001 From: Jun Zhao Date: Tue, 18 Apr 2023 23:19:18 +0800 Subject: [PATCH 0744/2172] lavc/libopenh264: refine the code refine the code Signed-off-by: Jun Zhao --- libavcodec/libopenh264enc.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/libavcodec/libopenh264enc.c b/libavcodec/libopenh264enc.c index cccc11fbb7e..3c605fe8ea4 100644 --- a/libavcodec/libopenh264enc.c +++ b/libavcodec/libopenh264enc.c @@ -313,7 +313,6 @@ static av_cold int svc_encode_init(AVCodecContext *avctx) 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); } else if (avctx->pix_fmt == AV_PIX_FMT_YUVJ420P) param.sSpatialLayers[0].bFullRange = 1; @@ -321,7 +320,6 @@ static av_cold int svc_encode_init(AVCodecContext *avctx) 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; } @@ -331,6 +329,9 @@ static av_cold int svc_encode_init(AVCodecContext *avctx) param.sSpatialLayers[0].uiColorPrimaries = avctx->color_primaries; if (avctx->color_trc != AVCOL_TRC_UNSPECIFIED) param.sSpatialLayers[0].uiTransferCharacteristics = avctx->color_trc; + + param.sSpatialLayers[0].bVideoSignalTypePresent = + (param.sSpatialLayers[0].bFullRange || param.sSpatialLayers[0].bColorDescriptionPresent); #endif if ((*s->encoder)->InitializeExt(s->encoder, ¶m) != cmResultSuccess) { From 95a78c08c17b73a50ad64c1b82e47970a3f2bc41 Mon Sep 17 00:00:00 2001 From: James Almer Date: Thu, 20 Apr 2023 10:12:47 -0300 Subject: [PATCH 0745/2172] avcodec/hevcdec: further constrain some slice header field values num_ref_idx_l0_active_minus1, num_ref_idx_l1_active_minus1, num_ref_idx_l0_default_active_minus1, and num_ref_idx_l1_default_active_minus1 are all in the range 0 to 14, inclusive. Signed-off-by: James Almer --- libavcodec/hevc_ps.c | 10 ++++++++-- libavcodec/hevcdec.c | 6 +++--- 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/libavcodec/hevc_ps.c b/libavcodec/hevc_ps.c index 7401ea23f5c..f29f783f774 100644 --- a/libavcodec/hevc_ps.c +++ b/libavcodec/hevc_ps.c @@ -1762,8 +1762,14 @@ int ff_hevc_decode_nal_pps(GetBitContext *gb, AVCodecContext *avctx, pps->cabac_init_present_flag = get_bits1(gb); - pps->num_ref_idx_l0_default_active = get_ue_golomb_long(gb) + 1; - pps->num_ref_idx_l1_default_active = get_ue_golomb_long(gb) + 1; + pps->num_ref_idx_l0_default_active = get_ue_golomb_31(gb) + 1; + pps->num_ref_idx_l1_default_active = get_ue_golomb_31(gb) + 1; + if (pps->num_ref_idx_l0_default_active >= HEVC_MAX_REFS || + pps->num_ref_idx_l1_default_active >= HEVC_MAX_REFS) { + av_log(avctx, AV_LOG_ERROR, "Too many default refs in PPS: %d/%d.\n", + pps->num_ref_idx_l0_default_active, pps->num_ref_idx_l1_default_active); + goto err; + } pps->pic_init_qp_minus26 = get_se_golomb(gb); diff --git a/libavcodec/hevcdec.c b/libavcodec/hevcdec.c index 1a0beac9011..0fa4fdd59d3 100644 --- a/libavcodec/hevcdec.c +++ b/libavcodec/hevcdec.c @@ -773,11 +773,11 @@ static int hls_slice_header(HEVCContext *s) sh->nb_refs[L1] = s->ps.pps->num_ref_idx_l1_default_active; if (get_bits1(gb)) { // num_ref_idx_active_override_flag - sh->nb_refs[L0] = get_ue_golomb_long(gb) + 1; + sh->nb_refs[L0] = get_ue_golomb_31(gb) + 1; if (sh->slice_type == HEVC_SLICE_B) - sh->nb_refs[L1] = get_ue_golomb_long(gb) + 1; + sh->nb_refs[L1] = get_ue_golomb_31(gb) + 1; } - if (sh->nb_refs[L0] > HEVC_MAX_REFS || sh->nb_refs[L1] > HEVC_MAX_REFS) { + if (sh->nb_refs[L0] >= HEVC_MAX_REFS || sh->nb_refs[L1] >= HEVC_MAX_REFS) { av_log(s->avctx, AV_LOG_ERROR, "Too many refs: %d/%d.\n", sh->nb_refs[L0], sh->nb_refs[L1]); return AVERROR_INVALIDDATA; From 41bbf2e372f39d99e9fafd2a90a44c4d517d85c0 Mon Sep 17 00:00:00 2001 From: James Almer Date: Fri, 21 Apr 2023 09:08:56 -0300 Subject: [PATCH 0746/2172] fate/h264: test disabling cropping Signed-off-by: James Almer --- tests/fate/h264.mak | 4 +- tests/ref/fate/h264-afd | 288 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 291 insertions(+), 1 deletion(-) diff --git a/tests/fate/h264.mak b/tests/fate/h264.mak index 173806861aa..0ff3d6df55f 100644 --- a/tests/fate/h264.mak +++ b/tests/fate/h264.mak @@ -451,7 +451,9 @@ fate-h264-timecode: CMD = framecrc -i $(TARGET_SAM fate-h264-reinit-%: CMD = framecrc -i $(TARGET_SAMPLES)/h264/$(@:fate-h264-%=%).h264 -vf scale,format=yuv444p10le,scale=w=352:h=288 fate-h264-dts_5frames: CMD = probeframes $(TARGET_SAMPLES)/h264/dts_5frames.mkv -fate-h264-afd: CMD = run ffprobe$(PROGSSUF)$(EXESUF) -bitexact -show_entries frame_side_data_list $(TARGET_SAMPLES)/h264/bbc2.sample.h264 +fate-h264-afd: CMD = run ffprobe$(PROGSSUF)$(EXESUF) -bitexact -apply_cropping 0 \ + -show_entries frame=width,height,crop_top,crop_bottom,crop_left,crop_right:frame_side_data_list:stream=width,height,coded_width,coded_height \ + $(TARGET_SAMPLES)/h264/bbc2.sample.h264 fate-h264-encparams: CMD = venc_data $(TARGET_SAMPLES)/h264-conformance/FRext/FRExt_MMCO4_Sony_B.264 0 1 FATE_SAMPLES_DUMP_DATA += fate-h264-encparams diff --git a/tests/ref/fate/h264-afd b/tests/ref/fate/h264-afd index a45e899eea7..56d16f23072 100644 --- a/tests/ref/fate/h264-afd +++ b/tests/ref/fate/h264-afd @@ -1,282 +1,570 @@ [FRAME] +width=1440 +height=1088 +crop_top=0 +crop_bottom=8 +crop_left=0 +crop_right=0 [SIDE_DATA] side_data_type=Active format description active_format=14 [/SIDE_DATA] [/FRAME] [FRAME] +width=1440 +height=1088 +crop_top=0 +crop_bottom=8 +crop_left=0 +crop_right=0 [SIDE_DATA] side_data_type=Active format description active_format=14 [/SIDE_DATA] [/FRAME] [FRAME] +width=1440 +height=1088 +crop_top=0 +crop_bottom=8 +crop_left=0 +crop_right=0 [SIDE_DATA] side_data_type=Active format description active_format=14 [/SIDE_DATA] [/FRAME] [FRAME] +width=1440 +height=1088 +crop_top=0 +crop_bottom=8 +crop_left=0 +crop_right=0 [SIDE_DATA] side_data_type=Active format description active_format=14 [/SIDE_DATA] [/FRAME] [FRAME] +width=1440 +height=1088 +crop_top=0 +crop_bottom=8 +crop_left=0 +crop_right=0 [SIDE_DATA] side_data_type=Active format description active_format=14 [/SIDE_DATA] [/FRAME] [FRAME] +width=1440 +height=1088 +crop_top=0 +crop_bottom=8 +crop_left=0 +crop_right=0 [SIDE_DATA] side_data_type=Active format description active_format=14 [/SIDE_DATA] [/FRAME] [FRAME] +width=1440 +height=1088 +crop_top=0 +crop_bottom=8 +crop_left=0 +crop_right=0 [SIDE_DATA] side_data_type=Active format description active_format=14 [/SIDE_DATA] [/FRAME] [FRAME] +width=1440 +height=1088 +crop_top=0 +crop_bottom=8 +crop_left=0 +crop_right=0 [SIDE_DATA] side_data_type=Active format description active_format=14 [/SIDE_DATA] [/FRAME] [FRAME] +width=1440 +height=1088 +crop_top=0 +crop_bottom=8 +crop_left=0 +crop_right=0 [SIDE_DATA] side_data_type=Active format description active_format=14 [/SIDE_DATA] [/FRAME] [FRAME] +width=1440 +height=1088 +crop_top=0 +crop_bottom=8 +crop_left=0 +crop_right=0 [SIDE_DATA] side_data_type=Active format description active_format=14 [/SIDE_DATA] [/FRAME] [FRAME] +width=1440 +height=1088 +crop_top=0 +crop_bottom=8 +crop_left=0 +crop_right=0 [SIDE_DATA] side_data_type=Active format description active_format=14 [/SIDE_DATA] [/FRAME] [FRAME] +width=1440 +height=1088 +crop_top=0 +crop_bottom=8 +crop_left=0 +crop_right=0 [SIDE_DATA] side_data_type=Active format description active_format=14 [/SIDE_DATA] [/FRAME] [FRAME] +width=1440 +height=1088 +crop_top=0 +crop_bottom=8 +crop_left=0 +crop_right=0 [SIDE_DATA] side_data_type=Active format description active_format=14 [/SIDE_DATA] [/FRAME] [FRAME] +width=1440 +height=1088 +crop_top=0 +crop_bottom=8 +crop_left=0 +crop_right=0 [SIDE_DATA] side_data_type=Active format description active_format=14 [/SIDE_DATA] [/FRAME] [FRAME] +width=1440 +height=1088 +crop_top=0 +crop_bottom=8 +crop_left=0 +crop_right=0 [SIDE_DATA] side_data_type=Active format description active_format=14 [/SIDE_DATA] [/FRAME] [FRAME] +width=1440 +height=1088 +crop_top=0 +crop_bottom=8 +crop_left=0 +crop_right=0 [SIDE_DATA] side_data_type=Active format description active_format=14 [/SIDE_DATA] [/FRAME] [FRAME] +width=1440 +height=1088 +crop_top=0 +crop_bottom=8 +crop_left=0 +crop_right=0 [SIDE_DATA] side_data_type=Active format description active_format=14 [/SIDE_DATA] [/FRAME] [FRAME] +width=1440 +height=1088 +crop_top=0 +crop_bottom=8 +crop_left=0 +crop_right=0 [SIDE_DATA] side_data_type=Active format description active_format=14 [/SIDE_DATA] [/FRAME] [FRAME] +width=1440 +height=1088 +crop_top=0 +crop_bottom=8 +crop_left=0 +crop_right=0 [SIDE_DATA] side_data_type=Active format description active_format=14 [/SIDE_DATA] [/FRAME] [FRAME] +width=1440 +height=1088 +crop_top=0 +crop_bottom=8 +crop_left=0 +crop_right=0 [SIDE_DATA] side_data_type=Active format description active_format=14 [/SIDE_DATA] [/FRAME] [FRAME] +width=1440 +height=1088 +crop_top=0 +crop_bottom=8 +crop_left=0 +crop_right=0 [SIDE_DATA] side_data_type=Active format description active_format=14 [/SIDE_DATA] [/FRAME] [FRAME] +width=1440 +height=1088 +crop_top=0 +crop_bottom=8 +crop_left=0 +crop_right=0 [SIDE_DATA] side_data_type=Active format description active_format=14 [/SIDE_DATA] [/FRAME] [FRAME] +width=1440 +height=1088 +crop_top=0 +crop_bottom=8 +crop_left=0 +crop_right=0 [SIDE_DATA] side_data_type=Active format description active_format=14 [/SIDE_DATA] [/FRAME] [FRAME] +width=1440 +height=1088 +crop_top=0 +crop_bottom=8 +crop_left=0 +crop_right=0 [SIDE_DATA] side_data_type=Active format description active_format=14 [/SIDE_DATA] [/FRAME] [FRAME] +width=1440 +height=1088 +crop_top=0 +crop_bottom=8 +crop_left=0 +crop_right=0 [SIDE_DATA] side_data_type=Active format description active_format=14 [/SIDE_DATA] [/FRAME] [FRAME] +width=1440 +height=1088 +crop_top=0 +crop_bottom=8 +crop_left=0 +crop_right=0 [SIDE_DATA] side_data_type=Active format description active_format=14 [/SIDE_DATA] [/FRAME] [FRAME] +width=1440 +height=1088 +crop_top=0 +crop_bottom=8 +crop_left=0 +crop_right=0 [SIDE_DATA] side_data_type=Active format description active_format=14 [/SIDE_DATA] [/FRAME] [FRAME] +width=1440 +height=1088 +crop_top=0 +crop_bottom=8 +crop_left=0 +crop_right=0 [SIDE_DATA] side_data_type=Active format description active_format=14 [/SIDE_DATA] [/FRAME] [FRAME] +width=1440 +height=1088 +crop_top=0 +crop_bottom=8 +crop_left=0 +crop_right=0 [SIDE_DATA] side_data_type=Active format description active_format=14 [/SIDE_DATA] [/FRAME] [FRAME] +width=1440 +height=1088 +crop_top=0 +crop_bottom=8 +crop_left=0 +crop_right=0 [SIDE_DATA] side_data_type=Active format description active_format=14 [/SIDE_DATA] [/FRAME] [FRAME] +width=1440 +height=1088 +crop_top=0 +crop_bottom=8 +crop_left=0 +crop_right=0 [SIDE_DATA] side_data_type=Active format description active_format=14 [/SIDE_DATA] [/FRAME] [FRAME] +width=1440 +height=1088 +crop_top=0 +crop_bottom=8 +crop_left=0 +crop_right=0 [SIDE_DATA] side_data_type=Active format description active_format=14 [/SIDE_DATA] [/FRAME] [FRAME] +width=1440 +height=1088 +crop_top=0 +crop_bottom=8 +crop_left=0 +crop_right=0 [SIDE_DATA] side_data_type=Active format description active_format=14 [/SIDE_DATA] [/FRAME] [FRAME] +width=1440 +height=1088 +crop_top=0 +crop_bottom=8 +crop_left=0 +crop_right=0 [SIDE_DATA] side_data_type=Active format description active_format=14 [/SIDE_DATA] [/FRAME] [FRAME] +width=1440 +height=1088 +crop_top=0 +crop_bottom=8 +crop_left=0 +crop_right=0 [SIDE_DATA] side_data_type=Active format description active_format=14 [/SIDE_DATA] [/FRAME] [FRAME] +width=1440 +height=1088 +crop_top=0 +crop_bottom=8 +crop_left=0 +crop_right=0 [SIDE_DATA] side_data_type=Active format description active_format=14 [/SIDE_DATA] [/FRAME] [FRAME] +width=1440 +height=1088 +crop_top=0 +crop_bottom=8 +crop_left=0 +crop_right=0 [SIDE_DATA] side_data_type=Active format description active_format=14 [/SIDE_DATA] [/FRAME] [FRAME] +width=1440 +height=1088 +crop_top=0 +crop_bottom=8 +crop_left=0 +crop_right=0 [SIDE_DATA] side_data_type=Active format description active_format=14 [/SIDE_DATA] [/FRAME] [FRAME] +width=1440 +height=1088 +crop_top=0 +crop_bottom=8 +crop_left=0 +crop_right=0 [SIDE_DATA] side_data_type=Active format description active_format=14 [/SIDE_DATA] [/FRAME] [FRAME] +width=1440 +height=1088 +crop_top=0 +crop_bottom=8 +crop_left=0 +crop_right=0 [SIDE_DATA] side_data_type=Active format description active_format=14 [/SIDE_DATA] [/FRAME] [FRAME] +width=1440 +height=1088 +crop_top=0 +crop_bottom=8 +crop_left=0 +crop_right=0 [SIDE_DATA] side_data_type=Active format description active_format=14 [/SIDE_DATA] [/FRAME] [FRAME] +width=1440 +height=1088 +crop_top=0 +crop_bottom=8 +crop_left=0 +crop_right=0 [SIDE_DATA] side_data_type=Active format description active_format=14 [/SIDE_DATA] [/FRAME] [FRAME] +width=1440 +height=1088 +crop_top=0 +crop_bottom=8 +crop_left=0 +crop_right=0 [SIDE_DATA] side_data_type=Active format description active_format=14 [/SIDE_DATA] [/FRAME] [FRAME] +width=1440 +height=1088 +crop_top=0 +crop_bottom=8 +crop_left=0 +crop_right=0 [SIDE_DATA] side_data_type=Active format description active_format=14 [/SIDE_DATA] [/FRAME] [FRAME] +width=1440 +height=1088 +crop_top=0 +crop_bottom=8 +crop_left=0 +crop_right=0 [SIDE_DATA] side_data_type=Active format description active_format=14 [/SIDE_DATA] [/FRAME] [FRAME] +width=1440 +height=1088 +crop_top=0 +crop_bottom=8 +crop_left=0 +crop_right=0 [SIDE_DATA] side_data_type=Active format description active_format=14 [/SIDE_DATA] [/FRAME] [FRAME] +width=1440 +height=1088 +crop_top=0 +crop_bottom=8 +crop_left=0 +crop_right=0 [SIDE_DATA] side_data_type=Active format description active_format=14 [/SIDE_DATA] [/FRAME] +[STREAM] +width=1440 +height=1080 +coded_width=1440 +coded_height=1088 +[/STREAM] From 014c02d43bbf35113d5794e4708cb84179d0c9d3 Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Sat, 22 Apr 2023 15:31:34 +0200 Subject: [PATCH 0747/2172] avfilter/af_anlms: simplify query formats --- libavfilter/af_anlms.c | 21 ++------------------- 1 file changed, 2 insertions(+), 19 deletions(-) diff --git a/libavfilter/af_anlms.c b/libavfilter/af_anlms.c index 6658cd29400..a2c854b0b88 100644 --- a/libavfilter/af_anlms.c +++ b/libavfilter/af_anlms.c @@ -78,23 +78,6 @@ static const AVOption anlms_options[] = { AVFILTER_DEFINE_CLASS_EXT(anlms, "anlm(f|s)", anlms_options); -static int query_formats(AVFilterContext *ctx) -{ - static const enum AVSampleFormat sample_fmts[] = { - AV_SAMPLE_FMT_FLTP, - AV_SAMPLE_FMT_NONE - }; - int ret = ff_set_common_all_channel_counts(ctx); - if (ret < 0) - return ret; - - ret = ff_set_common_formats_from_list(ctx, sample_fmts); - if (ret < 0) - return ret; - - return ff_set_common_all_samplerates(ctx); -} - static float fir_sample(AudioNLMSContext *s, float sample, float *delay, float *coeffs, float *tmp, int *offset) { @@ -316,7 +299,7 @@ const AVFilter ff_af_anlms = { .activate = activate, FILTER_INPUTS(inputs), FILTER_OUTPUTS(outputs), - FILTER_QUERY_FUNC(query_formats), + FILTER_SINGLE_SAMPLEFMT(AV_SAMPLE_FMT_FLTP), .flags = AVFILTER_FLAG_SUPPORT_TIMELINE_INTERNAL | AVFILTER_FLAG_SLICE_THREADS, .process_command = ff_filter_process_command, @@ -332,7 +315,7 @@ const AVFilter ff_af_anlmf = { .activate = activate, FILTER_INPUTS(inputs), FILTER_OUTPUTS(outputs), - FILTER_QUERY_FUNC(query_formats), + FILTER_SINGLE_SAMPLEFMT(AV_SAMPLE_FMT_FLTP), .flags = AVFILTER_FLAG_SUPPORT_TIMELINE_INTERNAL | AVFILTER_FLAG_SLICE_THREADS, .process_command = ff_filter_process_command, From eddf7e2a3e9459fd26a76fb2984a6c9b994e2d89 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Sun, 22 Jan 2023 00:51:05 +0100 Subject: [PATCH 0748/2172] avutil/tx_priv: Use unsigned in BF() to avoid signed overflows Fixes: signed integer overflow: 100183269 - -2132769113 cannot be represented in type 'int' Fixes: 55063/clusterfuzz-testcase-minimized-ffmpeg_AV_CODEC_ID_AAC_FIXED_fuzzer-5039294027005952 Found-by: continuous fuzzing process https://github.com/google/oss-fuzz/tree/master/projects/ffmpeg Signed-off-by: Michael Niedermayer --- libavutil/tx_priv.h | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/libavutil/tx_priv.h b/libavutil/tx_priv.h index 72f336eea71..d5ff8e14213 100644 --- a/libavutil/tx_priv.h +++ b/libavutil/tx_priv.h @@ -102,6 +102,12 @@ typedef void TXComplex; #define FOLD(a, b) ((a) + (b)) +#define BF(x, y, a, b) \ + do { \ + x = (a) - (b); \ + y = (a) + (b); \ + } while (0) + #elif defined(TX_INT32) /* Properly rounds the result */ @@ -132,14 +138,14 @@ typedef void TXComplex; #define FOLD(x, y) ((int32_t)((x) + (unsigned)(y) + 32) >> 6) -#endif /* TX_INT32 */ - #define BF(x, y, a, b) \ do { \ - x = (a) - (b); \ - y = (a) + (b); \ + x = (a) - (unsigned)(b); \ + y = (a) + (unsigned)(b); \ } while (0) +#endif /* TX_INT32 */ + #define CMUL3(c, a, b) CMUL((c).re, (c).im, (a).re, (a).im, (b).re, (b).im) /* Codelet flags, used to pick codelets. Must be a superset of enum AVTXFlags, From 38adbc6eebd7f2f34ecf1b0b18019e88bad9d9f4 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Tue, 24 Jan 2023 22:48:46 +0100 Subject: [PATCH 0749/2172] avcodec/g2meet: Replace fake allocation avoidance for framebuf framebuf is only allocated when the new width/height are larger than the old but nothing sets the old so its always allocated. Use av_fast_mallocz() instead. Fixes: Timeout Fixes: 55094/clusterfuzz-testcase-minimized-ffmpeg_AV_CODEC_ID_G2M_fuzzer-5116909932904448 Found-by: continuous fuzzing process https://github.com/google/oss-fuzz/tree/master/projects/ffmpeg Signed-off-by: Michael Niedermayer --- libavcodec/g2meet.c | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/libavcodec/g2meet.c b/libavcodec/g2meet.c index 32b966e8ef9..05b5a5124fb 100644 --- a/libavcodec/g2meet.c +++ b/libavcodec/g2meet.c @@ -145,7 +145,8 @@ typedef struct G2MContext { int got_header; uint8_t *framebuf; - int framebuf_stride, old_width, old_height; + int framebuf_stride; + unsigned int framebuf_allocated; uint8_t *synth_tile, *jpeg_tile, *epic_buf, *epic_buf_base; int tile_stride, epic_buf_stride, old_tile_w, old_tile_h; @@ -1160,14 +1161,13 @@ static int g2m_init_buffers(G2MContext *c) { int aligned_height; - if (!c->framebuf || c->old_width < c->width || c->old_height < c->height) { - c->framebuf_stride = FFALIGN(c->width + 15, 16) * 3; - aligned_height = c->height + 15; - av_free(c->framebuf); - c->framebuf = av_calloc(c->framebuf_stride, aligned_height); - if (!c->framebuf) - return AVERROR(ENOMEM); - } + c->framebuf_stride = FFALIGN(c->width + 15, 16) * 3; + aligned_height = c->height + 15; + + av_fast_mallocz(&c->framebuf, &c->framebuf_allocated, c->framebuf_stride * aligned_height); + if (!c->framebuf) + return AVERROR(ENOMEM); + if (!c->synth_tile || !c->jpeg_tile || (c->compression == 2 && !c->epic_buf_base) || c->old_tile_w < c->tile_width || @@ -1617,6 +1617,7 @@ static av_cold int g2m_decode_end(AVCodecContext *avctx) av_freep(&c->jpeg_tile); av_freep(&c->cursor); av_freep(&c->framebuf); + c->framebuf_allocated = 0; return 0; } From 99dc7517827e8cbd4d63488eff57e6b21b4b6f3f Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Wed, 25 Jan 2023 00:14:24 +0100 Subject: [PATCH 0750/2172] tools/target_dec_fuzzer: Adjust threshold for EXR Fixes: Timeout Fixes: 55106/clusterfuzz-testcase-minimized-ffmpeg_AV_CODEC_ID_EXR_fuzzer-5052199338377216 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 a9472eebe61..93869db04c6 100644 --- a/tools/target_dec_fuzzer.c +++ b/tools/target_dec_fuzzer.c @@ -227,6 +227,7 @@ int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { 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_EXR: maxpixels /= 1024; break; case AV_CODEC_ID_FFV1: maxpixels /= 32; break; case AV_CODEC_ID_FFWAVESYNTH: maxsamples /= 16384; break; case AV_CODEC_ID_FLAC: maxsamples /= 1024; break; From cadd7e7a7589b5c118ad1648a09c629a6b65a3be Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Sun, 12 Feb 2023 22:49:01 +0100 Subject: [PATCH 0751/2172] avcodec/vorbisdec: Check codebook float values to be finite Fixes: Timeout Fixes: 55116/clusterfuzz-testcase-minimized-ffmpeg_AV_CODEC_ID_VORBIS_fuzzer-4572159970508800 Signed-off-by: Michael Niedermayer --- libavcodec/vorbisdec.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/libavcodec/vorbisdec.c b/libavcodec/vorbisdec.c index e9dad4ef4fd..1d2a0997607 100644 --- a/libavcodec/vorbisdec.c +++ b/libavcodec/vorbisdec.c @@ -368,6 +368,10 @@ static int vorbis_parse_setup_hdr_codebooks(vorbis_context *vc) unsigned codebook_value_bits = get_bits(gb, 4) + 1; unsigned codebook_sequence_p = get_bits1(gb); + if (!isfinite(codebook_minimum_value) || !isfinite(codebook_delta_value)) { + ret = AVERROR_INVALIDDATA; + goto error; + } ff_dlog(NULL, " We expect %d numbers for building the codevectors. \n", codebook_lookup_values); ff_dlog(NULL, " delta %f minmum %f \n", From 4a466aab306b47b07c13d14a077abd207bc10ad1 Mon Sep 17 00:00:00 2001 From: caleb Date: Fri, 14 Apr 2023 12:14:41 -0700 Subject: [PATCH 0752/2172] avcodec/jpeg2000dec: move decoder structs to a header file Signed-off-by: Pierre-Anthony Lemieux --- libavcodec/jpeg2000dec.c | 88 +---------------------------- libavcodec/jpeg2000dec.h | 119 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 120 insertions(+), 87 deletions(-) create mode 100644 libavcodec/jpeg2000dec.h diff --git a/libavcodec/jpeg2000dec.c b/libavcodec/jpeg2000dec.c index da7152646b4..2319efdd773 100644 --- a/libavcodec/jpeg2000dec.c +++ b/libavcodec/jpeg2000dec.c @@ -42,6 +42,7 @@ #include "jpeg2000.h" #include "jpeg2000dsp.h" #include "profiles.h" +#include "jpeg2000dec.h" #define JP2_SIG_TYPE 0x6A502020 #define JP2_SIG_VALUE 0x0D0A870A @@ -51,93 +52,6 @@ #define HAD_COC 0x01 #define HAD_QCC 0x02 -#define MAX_POCS 32 - -typedef struct Jpeg2000POCEntry { - uint16_t LYEpoc; - uint16_t CSpoc; - uint16_t CEpoc; - uint8_t RSpoc; - uint8_t REpoc; - uint8_t Ppoc; -} Jpeg2000POCEntry; - -typedef struct Jpeg2000POC { - Jpeg2000POCEntry poc[MAX_POCS]; - int nb_poc; - int is_default; -} Jpeg2000POC; - -typedef struct Jpeg2000TilePart { - uint8_t tile_index; // Tile index who refers the tile-part - const uint8_t *tp_end; - GetByteContext header_tpg; // bit stream of header if PPM header is used - GetByteContext tpg; // bit stream in tile-part -} Jpeg2000TilePart; - -/* RMK: For JPEG2000 DCINEMA 3 tile-parts in a tile - * one per component, so tile_part elements have a size of 3 */ -typedef struct Jpeg2000Tile { - Jpeg2000Component *comp; - uint8_t properties[4]; - Jpeg2000CodingStyle codsty[4]; - Jpeg2000QuantStyle qntsty[4]; - Jpeg2000POC poc; - Jpeg2000TilePart tile_part[32]; - uint8_t has_ppt; // whether this tile has a ppt marker - uint8_t *packed_headers; // contains packed headers. Used only along with PPT marker - int packed_headers_size; // size in bytes of the packed headers - GetByteContext packed_headers_stream; // byte context corresponding to packed headers - uint16_t tp_idx; // Tile-part index - int coord[2][2]; // border coordinates {{x0, x1}, {y0, y1}} -} Jpeg2000Tile; - -typedef struct Jpeg2000DecoderContext { - AVClass *class; - AVCodecContext *avctx; - GetByteContext g; - - int width, height; - int image_offset_x, image_offset_y; - int tile_offset_x, tile_offset_y; - uint8_t cbps[4]; // bits per sample in particular components - uint8_t sgnd[4]; // if a component is signed - uint8_t properties[4]; - - uint8_t has_ppm; - uint8_t *packed_headers; // contains packed headers. Used only along with PPM marker - int packed_headers_size; - GetByteContext packed_headers_stream; - uint8_t in_tile_headers; - - int cdx[4], cdy[4]; - int precision; - int ncomponents; - int colour_space; - uint32_t palette[256]; - int8_t pal8; - int cdef[4]; - int tile_width, tile_height; - unsigned numXtiles, numYtiles; - int maxtilelen; - AVRational sar; - - Jpeg2000CodingStyle codsty[4]; - Jpeg2000QuantStyle qntsty[4]; - Jpeg2000POC poc; - uint8_t roi_shift[4]; - - int bit_index; - - int curtileno; - - Jpeg2000Tile *tile; - Jpeg2000DSPContext dsp; - - /*options parameters*/ - int reduction_factor; -} Jpeg2000DecoderContext; - /* get_bits functions for JPEG2000 packet bitstream * It is a get_bit function with a bit-stuffing routine. If the value of the * byte is 0xFF, the next byte includes an extra zero bit stuffed into the MSB. diff --git a/libavcodec/jpeg2000dec.h b/libavcodec/jpeg2000dec.h new file mode 100644 index 00000000000..d0ca6e7a794 --- /dev/null +++ b/libavcodec/jpeg2000dec.h @@ -0,0 +1,119 @@ +/* + * JPEG 2000 image decoder + * Copyright (c) 2007 Kamil Nowosad + * Copyright (c) 2013 Nicolas Bertrand + * Copyright (c) 2022 Caleb Etemesi + * + * 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_JPEG2000DEC_H +#define AVCODEC_JPEG2000DEC_H + +#include "bytestream.h" +#include "jpeg2000.h" +#include "jpeg2000dsp.h" + + +#define MAX_POCS 32 + +typedef struct Jpeg2000POCEntry { + uint16_t LYEpoc; + uint16_t CSpoc; + uint16_t CEpoc; + uint8_t RSpoc; + uint8_t REpoc; + uint8_t Ppoc; +} Jpeg2000POCEntry; + +typedef struct Jpeg2000POC { + Jpeg2000POCEntry poc[MAX_POCS]; + int nb_poc; + int is_default; +} Jpeg2000POC; + +typedef struct Jpeg2000TilePart { + uint8_t tile_index; // Tile index who refers the tile-part + const uint8_t *tp_end; + GetByteContext header_tpg; // bit stream of header if PPM header is used + GetByteContext tpg; // bit stream in tile-part +} Jpeg2000TilePart; + +/* RMK: For JPEG2000 DCINEMA 3 tile-parts in a tile + * one per component, so tile_part elements have a size of 3 */ +typedef struct Jpeg2000Tile { + Jpeg2000Component *comp; + uint8_t properties[4]; + Jpeg2000CodingStyle codsty[4]; + Jpeg2000QuantStyle qntsty[4]; + Jpeg2000POC poc; + Jpeg2000TilePart tile_part[32]; + uint8_t has_ppt; // whether this tile has a ppt marker + uint8_t *packed_headers; // contains packed headers. Used only along with PPT marker + int packed_headers_size; // size in bytes of the packed headers + GetByteContext packed_headers_stream; // byte context corresponding to packed headers + uint16_t tp_idx; // Tile-part index + int coord[2][2]; // border coordinates {{x0, x1}, {y0, y1}} +} Jpeg2000Tile; + +typedef struct Jpeg2000DecoderContext { + AVClass *class; + AVCodecContext *avctx; + GetByteContext g; + + int width, height; + int image_offset_x, image_offset_y; + int tile_offset_x, tile_offset_y; + uint8_t cbps[4]; // bits per sample in particular components + uint8_t sgnd[4]; // if a component is signed + uint8_t properties[4]; + + uint8_t has_ppm; + uint8_t *packed_headers; // contains packed headers. Used only along with PPM marker + int packed_headers_size; + GetByteContext packed_headers_stream; + uint8_t in_tile_headers; + + int cdx[4], cdy[4]; + int precision; + int ncomponents; + int colour_space; + uint32_t palette[256]; + int8_t pal8; + int cdef[4]; + int tile_width, tile_height; + unsigned numXtiles, numYtiles; + int maxtilelen; + AVRational sar; + + Jpeg2000CodingStyle codsty[4]; + Jpeg2000QuantStyle qntsty[4]; + Jpeg2000POC poc; + uint8_t roi_shift[4]; + + int bit_index; + + int curtileno; + + Jpeg2000Tile *tile; + Jpeg2000DSPContext dsp; + + /*options parameters*/ + int reduction_factor; +} Jpeg2000DecoderContext; + +#endif //AVCODEC_JPEG2000DEC_H From b9c42cdf8d9c38c9975c7fe5616a7f984a789de8 Mon Sep 17 00:00:00 2001 From: caleb Date: Fri, 14 Apr 2023 12:14:42 -0700 Subject: [PATCH 0753/2172] avcodec/jpeg2000dec: add support for HTJ2K block decoding Signed-off-by: Pierre-Anthony Lemieux --- libavcodec/Makefile | 2 +- libavcodec/jpeg2000.h | 5 +- libavcodec/jpeg2000dec.c | 66 +- libavcodec/jpeg2000htdec.c | 1451 ++++++++++++++++++++++++++++++++++++ libavcodec/jpeg2000htdec.h | 34 + 5 files changed, 1539 insertions(+), 19 deletions(-) create mode 100644 libavcodec/jpeg2000htdec.c create mode 100644 libavcodec/jpeg2000htdec.h diff --git a/libavcodec/Makefile b/libavcodec/Makefile index a1a8b8b88e9..b0971ce833e 100644 --- a/libavcodec/Makefile +++ b/libavcodec/Makefile @@ -469,7 +469,7 @@ OBJS-$(CONFIG_JACOSUB_DECODER) += jacosubdec.o ass.o OBJS-$(CONFIG_JPEG2000_ENCODER) += j2kenc.o mqcenc.o mqc.o jpeg2000.o \ jpeg2000dwt.o OBJS-$(CONFIG_JPEG2000_DECODER) += jpeg2000dec.o jpeg2000.o jpeg2000dsp.o \ - jpeg2000dwt.o mqcdec.o mqc.o + jpeg2000dwt.o mqcdec.o mqc.o jpeg2000htdec.o OBJS-$(CONFIG_JPEGLS_DECODER) += jpeglsdec.o jpegls.o OBJS-$(CONFIG_JPEGLS_ENCODER) += jpeglsenc.o jpegls.o OBJS-$(CONFIG_JV_DECODER) += jvdec.o diff --git a/libavcodec/jpeg2000.h b/libavcodec/jpeg2000.h index e5ecb4cbf91..d004c08f104 100644 --- a/libavcodec/jpeg2000.h +++ b/libavcodec/jpeg2000.h @@ -111,7 +111,7 @@ enum Jpeg2000Quantsty { // quantization style #define JPEG2000_CSTY_SOP 0x02 // SOP marker present #define JPEG2000_CSTY_EPH 0x04 // EPH marker present #define JPEG2000_CTSY_HTJ2K_F 0x40 // Only HT code-blocks (Rec. ITU-T T.814 | ISO/IEC 15444-15) are present -#define JPEG2000_CTSY_HTJ2K_M 0xC0 // HT code blocks (Rec. ITU-T T.814 | ISO/IEC 15444-15) can be present +#define JPEG2000_CTSY_HTJ2K_M 0xC0 // HT code-blocks (Rec. ITU-T T.814 | ISO/IEC 15444-15) can be present // Progression orders #define JPEG2000_PGOD_LRCP 0x00 // Layer-resolution level-component-position progression @@ -189,6 +189,9 @@ typedef struct Jpeg2000Cblk { Jpeg2000Pass *passes; Jpeg2000Layer *layers; int coord[2][2]; // border coordinates {{x0, x1}, {y0, y1}} + /* specific to HT code-blocks */ + int zbp; + int pass_lengths[2]; } Jpeg2000Cblk; // code block typedef struct Jpeg2000Prec { diff --git a/libavcodec/jpeg2000dec.c b/libavcodec/jpeg2000dec.c index 2319efdd773..40e66501107 100644 --- a/libavcodec/jpeg2000dec.c +++ b/libavcodec/jpeg2000dec.c @@ -43,6 +43,7 @@ #include "jpeg2000dsp.h" #include "profiles.h" #include "jpeg2000dec.h" +#include "jpeg2000htdec.h" #define JP2_SIG_TYPE 0x6A502020 #define JP2_SIG_VALUE 0x0D0A870A @@ -440,12 +441,12 @@ static int get_cox(Jpeg2000DecoderContext *s, Jpeg2000CodingStyle *c) c->cblk_style = bytestream2_get_byteu(&s->g); if (c->cblk_style != 0) { // cblk style if (c->cblk_style & JPEG2000_CTSY_HTJ2K_M || c->cblk_style & JPEG2000_CTSY_HTJ2K_F) { - av_log(s->avctx, AV_LOG_ERROR, "Support for High throughput JPEG 2000 is not yet available\n"); - return AVERROR_PATCHWELCOME; + av_log(s->avctx,AV_LOG_TRACE,"High Throughput jpeg 2000 codestream.\n"); + } else { + av_log(s->avctx, AV_LOG_WARNING, "extra cblk styles %X\n", c->cblk_style); + if (c->cblk_style & JPEG2000_CBLK_BYPASS) + av_log(s->avctx, AV_LOG_WARNING, "Selective arithmetic coding bypass\n"); } - av_log(s->avctx, AV_LOG_WARNING, "extra cblk styles %X\n", c->cblk_style); - if (c->cblk_style & JPEG2000_CBLK_BYPASS) - av_log(s->avctx, AV_LOG_WARNING, "Selective arithmetic coding bypass\n"); } c->transform = bytestream2_get_byteu(&s->g); // DWT transformation type /* set integer 9/7 DWT in case of BITEXACT flag */ @@ -1070,13 +1071,15 @@ static int jpeg2000_decode_packet(Jpeg2000DecoderContext *s, Jpeg2000Tile *tile, return incl; if (!cblk->npasses) { - int v = expn[bandno] + numgbits - 1 - - tag_tree_decode(s, prec->zerobits + cblkno, 100); + int zbp = tag_tree_decode(s, prec->zerobits + cblkno, 100); + int v = expn[bandno] + numgbits - 1 - zbp; + if (v < 0 || v > 30) { av_log(s->avctx, AV_LOG_ERROR, "nonzerobits %d invalid or unsupported\n", v); return AVERROR_INVALIDDATA; } + cblk->zbp = zbp; cblk->nonzerobits = v; } if ((newpasses = getnpasses(s)) < 0) @@ -1117,8 +1120,23 @@ static int jpeg2000_decode_packet(Jpeg2000DecoderContext *s, Jpeg2000Tile *tile, } } - if ((ret = get_bits(s, av_log2(newpasses1) + cblk->lblock)) < 0) - return ret; + if (newpasses > 1 && (codsty->cblk_style & JPEG2000_CTSY_HTJ2K_F)) { + // Retrieve pass lengths for each pass + int href_passes = (cblk->npasses + newpasses - 1) % 3; + int eb = av_log2(newpasses - href_passes); + int extra_bit = newpasses > 2 ? 1 : 0; + if ((ret = get_bits(s, llen + eb + 3)) < 0) + return ret; + cblk->pass_lengths[0] = ret; + if ((ret = get_bits(s, llen + 3 + extra_bit)) < 0) + return ret; + cblk->pass_lengths[1] = ret; + ret = cblk->pass_lengths[0] + cblk->pass_lengths[1]; + } else { + if ((ret = get_bits(s, av_log2(newpasses1) + cblk->lblock)) < 0) + return ret; + cblk->pass_lengths[0] = ret; + } if (ret > cblk->data_allocated) { size_t new_size = FFMAX(2*cblk->data_allocated, ret); void *new = av_realloc(cblk->data, new_size); @@ -1867,9 +1885,12 @@ static inline void tile_codeblocks(const Jpeg2000DecoderContext *s, Jpeg2000Tile /* Loop on tile components */ for (compno = 0; compno < s->ncomponents; compno++) { - Jpeg2000Component *comp = tile->comp + compno; - Jpeg2000CodingStyle *codsty = tile->codsty + compno; + Jpeg2000Component *comp = tile->comp + compno; + Jpeg2000CodingStyle *codsty = tile->codsty + compno; + Jpeg2000QuantStyle *quantsty = tile->qntsty + compno; + int coded = 0; + int subbandno = 0; t1.stride = (1<log2_cblk_width) + 2; @@ -1877,7 +1898,7 @@ static inline void tile_codeblocks(const Jpeg2000DecoderContext *s, Jpeg2000Tile for (reslevelno = 0; reslevelno < codsty->nreslevels2decode; reslevelno++) { Jpeg2000ResLevel *rlevel = comp->reslevel + reslevelno; /* Loop on bands */ - for (bandno = 0; bandno < rlevel->nbands; bandno++) { + for (bandno = 0; bandno < rlevel->nbands; bandno++, subbandno++) { int nb_precincts, precno; Jpeg2000Band *band = rlevel->band + bandno; int cblkno = 0, bandpos; @@ -1897,12 +1918,23 @@ static inline void tile_codeblocks(const Jpeg2000DecoderContext *s, Jpeg2000Tile for (cblkno = 0; cblkno < prec->nb_codeblocks_width * prec->nb_codeblocks_height; cblkno++) { - int x, y; + int x, y, ret; + /* See Rec. ITU-T T.800, Equation E-2 */ + int magp = quantsty->expn[subbandno] + quantsty->nguardbits - 1; + Jpeg2000Cblk *cblk = prec->cblk + cblkno; - int ret = decode_cblk(s, codsty, &t1, cblk, - cblk->coord[0][1] - cblk->coord[0][0], - cblk->coord[1][1] - cblk->coord[1][0], - bandpos, comp->roi_shift); + + if (codsty->cblk_style & JPEG2000_CTSY_HTJ2K_F) + ret = ff_jpeg2000_decode_htj2k(s, codsty, &t1, cblk, + cblk->coord[0][1] - cblk->coord[0][0], + cblk->coord[1][1] - cblk->coord[1][0], + magp, comp->roi_shift); + else + ret = decode_cblk(s, codsty, &t1, cblk, + cblk->coord[0][1] - cblk->coord[0][0], + cblk->coord[1][1] - cblk->coord[1][0], + bandpos, comp->roi_shift); + if (ret) coded = 1; else diff --git a/libavcodec/jpeg2000htdec.c b/libavcodec/jpeg2000htdec.c new file mode 100644 index 00000000000..51cd96e0f1c --- /dev/null +++ b/libavcodec/jpeg2000htdec.c @@ -0,0 +1,1451 @@ +/* + * Copyright (c) 2022 Caleb Etemesi + * + * 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 2019 - 2021, Osamu Watanabe + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. 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. + * + * 3. Neither the name of the copyright holder nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * 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. + */ + +#include +#include "libavutil/attributes.h" +#include "libavutil/common.h" +#include "libavutil/avassert.h" +#include "jpeg2000htdec.h" +#include "jpeg2000.h" +#include "jpeg2000dec.h" + +#define J2K_Q1 0 +#define J2K_Q2 1 + +#define HT_SHIFT_SIGMA 0 +#define HT_SHIFT_SCAN 4 +#define HT_SHIFT_REF 3 +#define HT_SHIFT_REF_IND 2 + +/* See Rec. ITU-T T.800, Table 2 */ +const static uint8_t mel_e[13] = { 0, 0, 0, 1, 1, 1, 2, 2, 2, 3, 3, 4, 5 }; + +static const uint16_t dec_cxt_vlc_table1[1024]; +static const uint16_t dec_cxt_vlc_table0[1024]; + +typedef struct StateVars { + int32_t pos; + uint32_t bits; + uint32_t tmp; + uint32_t last; + uint8_t bits_left; + uint64_t bit_buf; +} StateVars; + +typedef struct MelDecoderState { + uint8_t k; + uint8_t run; + uint8_t one; +} MelDecoderState; + +/** + * Given a precomputed c, checks whether n % d == 0. c is precomputed from d + * using precompute_c(). + */ +av_always_inline +static uint32_t is_divisible(uint32_t n, uint64_t c) +{ + return n * c <= c - 1; +} + +/** + * Precompute the number c used by is_divisible(). + */ +av_always_inline +static uint64_t precompute_c(uint32_t d) +{ + return 1 + (0xffffffffffffffffull / d); +} + +static void jpeg2000_init_zero(StateVars *s) +{ + s->bits_left = 0; + s->bit_buf = 0; + s->tmp = 0; + s->bits = 0; + s->pos = 0; + s->last = 0; +} + +static void jpeg2000_init_mel(StateVars *s, uint32_t Pcup) +{ + jpeg2000_init_zero(s); + s->pos = Pcup; +} + +static void jpeg2000_init_mag_ref(StateVars *s, uint32_t Lref) +{ + s->pos = Lref - 2; + s->bits = 0; + s->last = 0xFF; + s->tmp = 0; + s->bits_left = 0; + s->bit_buf = 0; +} + +static void jpeg2000_init_mel_decoder(MelDecoderState *mel_state) +{ + mel_state->k = 0; + mel_state->run = 0; + mel_state->one = 0; +} + +/** + * Refill the buffer backwards in little endian while skipping over stuffing + * bits. Stuffing bits are those that appear in the position of any byte whose + * LSBs are all 1's if the last consumed byte was larger than 0x8F. + */ +static int jpeg2000_bitbuf_refill_backwards(StateVars *buffer, const uint8_t *array) +{ + uint64_t tmp = 0; + int32_t position = buffer->pos; + uint32_t new_bits = 32; + + if (buffer->bits_left >= 32) + return 0; // enough data, no need to pull in more bits + + /** + * We are reading bytes from end to start and need to handle being close to + * the end. Subtracting by 4 means we will read some of the bytes of the MEL + * byte stream since the MEL byte stream ends at the start of the VLC byte + * stream. This is okay as they are masked away since we check for cases + * where that occurs (when the position is less than 4). + */ + position -= 4; + + tmp = AV_RB32(&array[position + 1]); + + if (buffer->pos < 4){ + /* mask un-needed bits if we are close to input end */ + uint64_t mask = (1ull << (buffer->pos + 1) * 8) - 1; + tmp &= mask; + } + + /** + * Unstuff bits. Load a temporary byte, which precedes the position we + * currently at, to ensure that we can also un-stuff if the stuffed bit is + * the bottom most bits. + */ + tmp <<= 8; + tmp |= array[buffer->pos + 1]; + + if ((tmp & 0x7FFF000000) > 0x7F8F000000) { + tmp &= 0x7FFFFFFFFF; + new_bits--; + } + if ((tmp & 0x007FFF0000) > 0x007F8F0000) { + tmp = (tmp & 0x007FFFFFFF) + ((tmp & 0xFF00000000) >> 1); + new_bits--; + } + if ((tmp & 0x00007FFF00) > 0x00007F8F00) { + tmp = (tmp & 0x00007FFFFF) + ((tmp & 0xFFFF000000) >> 1); + new_bits--; + } + if ((tmp & 0x0000007FFF) > 0x0000007F8F) { + tmp = (tmp & 0x0000007FFF) + ((tmp & 0xFFFFFF0000) >> 1); + new_bits--; + } + + tmp >>= 8; // Remove temporary byte loaded + + /* Add bits to the MSB of the bit buffer */ + buffer->bit_buf |= tmp << buffer->bits_left; + buffer->bits_left += new_bits; + buffer->pos = FFMAX(0, position); + return 0; +} + +/** + * Refill the bit-buffer reading new bits going forward + * in the stream while skipping over stuffed bits. + */ +static void jpeg2000_bitbuf_refill_forward(StateVars *buffer, const uint8_t *array, + uint32_t length) +{ + while (buffer->bits_left < 32) { + buffer->tmp = 0xFF; + buffer->bits = (buffer->last == 0xFF) ? 7 : 8; + if (buffer->pos <= length) { + buffer->tmp = array[buffer->pos]; + buffer->pos += 1; + buffer->last = buffer->tmp; + } + buffer->bit_buf |= ((uint64_t) buffer->tmp) << buffer->bits_left; + buffer->bits_left += buffer->bits; + } +} + +/** + * Drops bits from lower bits in the bit buffer. buf contains the bit buffers. + * nbits is the number of bits to remove. + */ +av_always_inline +static void jpeg2000_bitbuf_drop_bits_lsb(StateVars *buf, uint8_t nbits) +{ + av_assert2(buf->bits_left >= nbits); // cannot read more bits than available + buf->bit_buf >>= nbits; + buf->bits_left -= nbits; +} + +/** + * Get bits from the bit buffer reading them from the least significant bits + * moving to the most significant bits. In case there are fewer bits, refill + * from buf moving backwards. + */ +av_always_inline +static uint64_t jpeg2000_bitbuf_get_bits_lsb(StateVars *bit_stream, uint8_t nbits, + const uint8_t *buf) +{ + uint64_t bits; + uint64_t mask = (1ull << nbits) - 1; + if (bit_stream->bits_left < nbits) + jpeg2000_bitbuf_refill_backwards(bit_stream, buf); + bits = bit_stream->bit_buf & mask; + jpeg2000_bitbuf_drop_bits_lsb(bit_stream, nbits); + return bits; +} + +/** + * Get bits from the bit buffer reading them from the least significant bits + * moving to the most significant bits. In case there are fewer bits, refill from + * buf moving forward. + */ +av_always_inline +static uint64_t jpeg2000_bitbuf_get_bits_lsb_forward(StateVars *bit_stream, + uint8_t nbits, const uint8_t *buf, + uint32_t length) +{ + uint64_t bits; + uint64_t mask = (1ull << nbits) - 1; + + if (bit_stream->bits_left <= nbits) + jpeg2000_bitbuf_refill_forward(bit_stream, buf, length); + bits = bit_stream->bit_buf & mask; + jpeg2000_bitbuf_drop_bits_lsb(bit_stream, nbits); + return bits; +} + +/** + * Look ahead bit buffer without discarding bits. + */ +av_always_inline +static uint64_t jpeg2000_bitbuf_peek_bits_lsb(StateVars *stream, uint8_t nbits) +{ + uint64_t mask = (1ull << nbits) - 1; + return stream->bit_buf & mask; +} + +static void jpeg2000_init_vlc(StateVars *s, uint32_t Lcup, uint32_t Pcup, + const uint8_t *Dcup) +{ + s->bits_left = 0; + s->bit_buf = 0; + s->pos = Lcup - 2 - Pcup; + s->last = Dcup[Lcup - 2]; + s->tmp = (s->last) >> 4; + s->bits = ((s->tmp & 7) < 7) ? 4 : 3; + + jpeg2000_bitbuf_refill_backwards(s, Dcup + Pcup); + jpeg2000_bitbuf_drop_bits_lsb(s, 4); +} + +/** + * Decode prefix codes for VLC segment. See Rec. ITU-T T.814, 7.3.5. + */ +av_always_inline +static int jpeg2000_decode_ctx_vlc(const Jpeg2000DecoderContext *s, + StateVars *vlc_stream, const uint16_t *table, + const uint8_t *Dcup, uint8_t *sig_pat, + uint8_t *res_off, uint8_t *emb_pat_k, + uint8_t *emb_pat_1, uint8_t pos, + uint32_t Pcup, uint16_t context) +{ + uint32_t value; + uint8_t len; + uint64_t index; + uint64_t code_word; + + jpeg2000_bitbuf_refill_backwards(vlc_stream, Dcup + Pcup); + + code_word = vlc_stream->bit_buf & 0x7f; + index = code_word + (context << 7); + + av_assert0(index < 1024); // The CxtVLC table has 1024 entries. + + value = table[index]; + + len = (value & 0x000F) >> 1; + + res_off[pos] = (uint8_t) (value & 1); + sig_pat[pos] = (uint8_t) ((value & 0x00F0) >> 4); + emb_pat_k[pos] = (uint8_t) ((value & 0x0F00) >> 8); + emb_pat_1[pos] = (uint8_t) ((value & 0xF000) >> 12); + + jpeg2000_bitbuf_drop_bits_lsb(vlc_stream, len); + return 0; +} + +/** + * Decode variable length u-vlc prefix. See decodeUPrefix procedure at Rec. + * ITU-T T.814, 7.3.6. + */ +av_always_inline +static uint8_t vlc_decode_u_prefix(StateVars *vlc_stream, const uint8_t *refill_array) +{ + static const uint8_t return_value[8] = { 5, 1, 2, 1, 3, 1, 2, 1 }; + static const uint8_t drop_bits[8] = { 3, 1, 2, 1, 3, 1, 2, 1 }; + + uint8_t bits; + + if (vlc_stream->bits_left < 3) + jpeg2000_bitbuf_refill_backwards(vlc_stream, refill_array); + + bits = jpeg2000_bitbuf_peek_bits_lsb(vlc_stream, 3); + + jpeg2000_bitbuf_drop_bits_lsb(vlc_stream, drop_bits[bits]); + return return_value[bits]; +} + +/** + * Decode variable length u-vlc suffix. See decodeUSuffix procedure at Rec. + * ITU-T T.814, 7.3.6. + */ +av_always_inline +static uint8_t vlc_decode_u_suffix(StateVars *vlc_stream, uint8_t suffix, + const uint8_t *refill_array) +{ + static const int mask[] = { 1, 31 }; + static const int drop_bits[] = { 1, 5 }; + + uint8_t bits; + int cond = suffix != 3; + if (suffix < 3) + return 0; + + if (vlc_stream->bits_left < 5) + jpeg2000_bitbuf_refill_backwards(vlc_stream, refill_array); + + bits = jpeg2000_bitbuf_peek_bits_lsb(vlc_stream, 5); + + jpeg2000_bitbuf_drop_bits_lsb(vlc_stream, drop_bits[cond]); + return bits & mask[cond]; +} + +/** + * Decode u-vlc extension values. See decodeUExtension procedure at Rec. ITU-T + * T.814, 7.3.6. + */ +av_always_inline +static uint8_t vlc_decode_u_extension(StateVars *vlc_stream, uint8_t suffix, + const uint8_t *refill_array) +{ + return jpeg2000_bitbuf_get_bits_lsb(vlc_stream, 4 * (suffix >= 28), refill_array); +} + +/** + * Magnitude and Sign decode procedures. See decodeMagSgnValue procedure at Rec. + * ITU-T T.814, 7.3.8. + */ +av_always_inline +static int32_t jpeg2000_decode_mag_sgn(StateVars *mag_sgn_stream, int32_t m_n, + int32_t i_n, const uint8_t *buf, uint32_t length) +{ + int32_t val = 0; + if (m_n > 0) { + val = jpeg2000_bitbuf_get_bits_lsb_forward(mag_sgn_stream,m_n,buf,length); + val += (i_n << m_n); + } + return val; +} + +av_always_inline +static void recover_mag_sgn(StateVars *mag_sgn, uint8_t pos, uint16_t q, int32_t m_n[2], + int32_t known_1[2], const uint8_t emb_pat_1[2], + int32_t v[2][4], int32_t m[2][4], uint8_t *E, + uint32_t *mu_n, const uint8_t *Dcup, uint32_t Pcup, + uint32_t pLSB) +{ + for (int i = 0; i < 4; i++) { + int32_t n = 4 * q + i; + m_n[pos] = m[pos][i]; + known_1[pos] = (emb_pat_1[pos] >> i) & 1; + v[pos][i] = jpeg2000_decode_mag_sgn(mag_sgn, m_n[pos], known_1[pos], Dcup, Pcup); + + if (m_n[pos] != 0) { + E[n] = 32 - ff_clz(v[pos][i] | 1); + mu_n[n] = (v[pos][i] >> 1) + 1; + mu_n[n] <<= pLSB; + mu_n[n] |= ((uint32_t) (v[pos][i] & 1)) << 31; // sign bit. + } + } +} + +static int jpeg2000_import_bit(StateVars *stream, const uint8_t *array, uint32_t length) +{ + int cond = stream->pos <= length; + int pos = FFMIN(stream->pos, length); + if (stream->bits == 0) { + stream->bits = (stream->tmp == 0xFF) ? 7 : 8; + stream->pos += cond; + stream->tmp = cond ? array[pos] : 0xFF; + } + stream->bits -= 1; + return (stream->tmp >> stream->bits) & 1; +} + +static int jpeg2000_peek_bit(StateVars *stream, const uint8_t *array, uint32_t length) +{ + if (stream->bits == 0) { + int cond = stream->pos <= length; + int pos = FFMIN(stream->pos, length); + stream->bits = (stream->tmp == 0xFF) ? 7 : 8; + stream->pos += cond; + stream->tmp = cond ? array[pos] : 0xFF; + } + return (stream->tmp >> stream->bits) & 1; +} + +static int jpeg2000_decode_mel_sym(MelDecoderState *mel_state, + StateVars *mel_stream, + const uint8_t *Dcup, + uint32_t Lcup) +{ + + if (mel_state->run == 0 && mel_state->one == 0) { + uint8_t eval; + uint8_t bit; + + eval = mel_e[mel_state->k]; + bit = jpeg2000_import_bit(mel_stream, Dcup, Lcup); + if (bit == 1) { + mel_state->run = 1 << eval; + mel_state->k = FFMIN(12, mel_state->k + 1); + } else { + mel_state->run = 0; + while (eval > 0) { + bit = jpeg2000_import_bit(mel_stream, Dcup, Lcup); + mel_state->run = (2 * (mel_state->run)) + bit; + eval -= 1; + } + mel_state->k = FFMAX(0, mel_state->k - 1); + mel_state->one = 1; + } + } + if (mel_state->run > 0) { + mel_state->run -= 1; + return 0; + } else { + mel_state->one = 0; + return 1; + } +} + +/** + * Magref decoding procedures. + */ +av_always_inline +static int jpeg2000_import_magref_bit(StateVars *stream, const uint8_t *array, + uint32_t length) +{ + return jpeg2000_bitbuf_get_bits_lsb(stream, 1, array); +} + +/** + * Signal EMB decode. + */ +static int jpeg2000_decode_sig_emb(const Jpeg2000DecoderContext *s, MelDecoderState *mel_state, + StateVars *mel_stream, StateVars *vlc_stream, + const uint16_t *vlc_table, const uint8_t *Dcup, + uint8_t *sig_pat, uint8_t *res_off, uint8_t *emb_pat_k, + uint8_t *emb_pat_1, uint8_t pos, uint16_t context, + uint32_t Lcup, uint32_t Pcup) +{ + if (context == 0) { + uint8_t sym; + sym = jpeg2000_decode_mel_sym(mel_state, mel_stream, Dcup, Lcup); + if (sym == 0) { + sig_pat[pos] = 0; + res_off[pos] = 0; + emb_pat_k[pos] = 0; + emb_pat_1[pos] = 0; + return 0; + } + } + return jpeg2000_decode_ctx_vlc(s, vlc_stream, vlc_table, Dcup, sig_pat, + res_off, emb_pat_k, emb_pat_1, pos, Pcup, + context); +} + +av_always_inline +static int jpeg2000_get_state(int x1, int x2, int width, int shift_by, + const uint8_t *block_states) +{ + return (block_states[(x1 + 1) * (width + 2) + (x2 + 1)] >> shift_by) & 1; +} + +av_always_inline +static void jpeg2000_modify_state(int x1, int x2, int width, + int value, uint8_t *block_states) +{ + block_states[(x1 + 1) * (width + 2) + (x2 + 1)] |= value; +} + +av_always_inline +static int jpeg2000_decode_ht_cleanup_segment(const Jpeg2000DecoderContext *s, + Jpeg2000Cblk *cblk, Jpeg2000T1Context *t1, + MelDecoderState *mel_state, + StateVars *mel_stream, StateVars *vlc_stream, + StateVars *mag_sgn_stream, const uint8_t *Dcup, + uint32_t Lcup, uint32_t Pcup, uint8_t pLSB, + int width, int height, int32_t *sample_buf, + uint8_t *block_states) +{ + uint16_t q = 0; // Represents current quad position + uint16_t q1, q2; + uint16_t context1, context2; + uint16_t context = 0; + + uint8_t sig_pat[2] = { 0 }; // significance pattern + uint8_t res_off[2] = { 0 }; // residual offset + uint8_t emb_pat_k[2] = { 0 }; // exponent Max Bound pattern K + uint8_t emb_pat_1[2] = { 0 }; // exponent Max Bound pattern 1 + uint8_t gamma[2] = { 0 }; + + uint8_t E_n[2] = { 0 }; + uint8_t E_ne[2] = { 0 }; + uint8_t E_nw[2] = { 0 }; + uint8_t E_nf[2] = { 0 }; + + uint8_t max_e[2] = { 0 }; + uint8_t u_pfx[2] = { 0 }; + uint8_t u_sfx[2] = { 0 }; + uint8_t u_ext[2] = { 0 }; + + int32_t u[2] = { 0 }; + int32_t U[2] = { 0 }; // exponent bound + int32_t m_n[2] = { 0 }; + int32_t known_1[2] = { 0 }; + + int32_t m[2][4] = { 0 }; + int32_t v[2][4] = { 0 }; + + uint8_t kappa[2] = { 1, 1 }; + + int ret = 0; + + int sp; + + uint64_t c; + + uint8_t *sigma; + uint32_t *mu; + + const uint8_t *vlc_buf = Dcup + Pcup; + + /* convert to raster-scan */ + const uint16_t is_border_x = width % 2; + const uint16_t is_border_y = height % 2; + + const uint16_t quad_width = ff_jpeg2000_ceildivpow2(width, 1); + const uint16_t quad_height = ff_jpeg2000_ceildivpow2(height, 1); + + size_t buf_size = 4 * quad_width * quad_height; + + uint8_t *sigma_n = av_calloc(buf_size, sizeof(uint8_t)); + uint8_t *E = av_calloc(buf_size, sizeof(uint8_t)); + uint32_t *mu_n = av_calloc(buf_size, sizeof(uint32_t)); + + if (!sigma_n || !E || !mu_n) { + ret = AVERROR(ENOMEM); + goto free; + } + + sigma = sigma_n; + mu = mu_n; + + while (q < quad_width - 1) { + q1 = q; + q2 = q1 + 1; + + if ((ret = jpeg2000_decode_sig_emb(s, mel_state, mel_stream, vlc_stream, + dec_cxt_vlc_table0, Dcup, sig_pat, res_off, + emb_pat_k, emb_pat_1, J2K_Q1, context, Lcup, + Pcup)) < 0) + goto free; + + for (int i = 0; i < 4; i++) + sigma_n[4 * q1 + i] = (sig_pat[J2K_Q1] >> i) & 1; + + /* calculate context */ + context = sigma_n[4 * q1]; // f + context |= sigma_n[4 * q1 + 1]; // sf + context += sigma_n[4 * q1 + 2] << 1; // w << 1 + context += sigma_n[4 * q1 + 3] << 2; + + if ((ret = jpeg2000_decode_sig_emb(s, mel_state, mel_stream, vlc_stream, + dec_cxt_vlc_table0, Dcup, sig_pat, res_off, + emb_pat_k, emb_pat_1, J2K_Q2, context, Lcup, + Pcup)) < 0) + goto free; + + for (int i = 0; i < 4; i++) + sigma_n[4 * q2 + i] = (sig_pat[J2K_Q2] >> i) & 1; + + /* calculate context for the next quad */ + context = sigma_n[4 * q2]; // f + context |= sigma_n[4 * q2 + 1]; // sf + context += sigma_n[4 * q2 + 2] << 1; // w << 1 + context += sigma_n[4 * q2 + 3] << 2; // sw << 2 + + u[0] = 0; + u[1] = 0; + + jpeg2000_bitbuf_refill_backwards(vlc_stream, vlc_buf); + + if (res_off[J2K_Q1] == 1 && res_off[J2K_Q2] == 1) { + + if (jpeg2000_decode_mel_sym(mel_state, mel_stream, Dcup, Lcup) == 1) { + + u_pfx[J2K_Q1] = vlc_decode_u_prefix(vlc_stream, vlc_buf); + u_pfx[J2K_Q2] = vlc_decode_u_prefix(vlc_stream, vlc_buf); + + u_sfx[J2K_Q1] = vlc_decode_u_suffix(vlc_stream, u_pfx[J2K_Q1], vlc_buf); + u_sfx[J2K_Q2] = vlc_decode_u_suffix(vlc_stream, u_pfx[J2K_Q2], vlc_buf); + + u_ext[J2K_Q1] = vlc_decode_u_extension(vlc_stream, u_sfx[J2K_Q1], vlc_buf); + u_ext[J2K_Q2] = vlc_decode_u_extension(vlc_stream, u_sfx[J2K_Q2], vlc_buf); + + u[J2K_Q1] = 2 + u_pfx[J2K_Q1] + u_sfx[J2K_Q1] + (u_ext[J2K_Q1] * 4); + u[J2K_Q2] = 2 + u_pfx[J2K_Q2] + u_sfx[J2K_Q2] + (u_ext[J2K_Q2] * 4); + + } else { + u_pfx[J2K_Q1] = vlc_decode_u_prefix(vlc_stream, vlc_buf); + + if (u_pfx[J2K_Q1] > 2) { + u[J2K_Q2] = jpeg2000_bitbuf_get_bits_lsb(vlc_stream, 1, vlc_buf) + 1; + u_sfx[J2K_Q1] = vlc_decode_u_suffix(vlc_stream, u_pfx[J2K_Q1], vlc_buf); + u_ext[J2K_Q1] = vlc_decode_u_extension(vlc_stream, u_sfx[J2K_Q1], vlc_buf); + } else { + u_pfx[J2K_Q2] = vlc_decode_u_prefix(vlc_stream, vlc_buf); + u_sfx[J2K_Q1] = vlc_decode_u_suffix(vlc_stream, u_pfx[J2K_Q1], vlc_buf); + u_sfx[J2K_Q2] = vlc_decode_u_suffix(vlc_stream, u_pfx[J2K_Q2], vlc_buf); + u_ext[J2K_Q1] = vlc_decode_u_extension(vlc_stream, u_sfx[J2K_Q1], vlc_buf); + u_ext[J2K_Q2] = vlc_decode_u_extension(vlc_stream, u_sfx[J2K_Q2], vlc_buf); + u[J2K_Q2] = u_pfx[J2K_Q2] + u_sfx[J2K_Q2] + (u_ext[J2K_Q2] * 4); + } + /* See Rec. ITU-T T.814, 7.3.6(3) */ + u[J2K_Q1] = u_pfx[J2K_Q1] + u_sfx[J2K_Q1] + (u_ext[J2K_Q1] * 4); + } + + } else if (res_off[J2K_Q1] == 1 || res_off[J2K_Q2] == 1) { + uint8_t pos = res_off[J2K_Q1] == 1 ? 0 : 1; + u_pfx[pos] = vlc_decode_u_prefix(vlc_stream, vlc_buf); + u_sfx[pos] = vlc_decode_u_suffix(vlc_stream, u_pfx[pos], vlc_buf); + u_ext[pos] = vlc_decode_u_extension(vlc_stream, u_sfx[pos], vlc_buf); + u[pos] = u_pfx[pos] + u_sfx[pos] + (u_ext[pos] * 4); + } + U[J2K_Q1] = kappa[J2K_Q1] + u[J2K_Q1]; + U[J2K_Q2] = kappa[J2K_Q2] + u[J2K_Q2]; + + for (int i = 0; i < 4; i++) { + m[J2K_Q1][i] = sigma_n[4 * q1 + i] * U[J2K_Q1] - ((emb_pat_k[J2K_Q1] >> i) & 1); + m[J2K_Q2][i] = sigma_n[4 * q2 + i] * U[J2K_Q2] - ((emb_pat_k[J2K_Q2] >> i) & 1); + } + + recover_mag_sgn(mag_sgn_stream, J2K_Q1, q1, m_n, known_1, emb_pat_1, v, m, + E, mu_n, Dcup, Pcup, pLSB); + + recover_mag_sgn(mag_sgn_stream, J2K_Q2, q2, m_n, known_1, emb_pat_1, v, m, + E, mu_n, Dcup, Pcup, pLSB); + + q += 2; // Move to the next quad pair + } + + if (quad_width % 2 == 1) { + q1 = q; + + if ((ret = jpeg2000_decode_sig_emb(s, mel_state, mel_stream, vlc_stream, + dec_cxt_vlc_table0, Dcup, sig_pat, res_off, + emb_pat_k, emb_pat_1, J2K_Q1, context, Lcup, + Pcup)) < 0) + goto free; + + for (int i = 0; i < 4; i++) + sigma_n[4 * q1 + i] = (sig_pat[J2K_Q1] >> i) & 1; + + u[J2K_Q1] = 0; + + if (res_off[J2K_Q1] == 1) { + u_pfx[J2K_Q1] = vlc_decode_u_prefix(vlc_stream, vlc_buf); + u_sfx[J2K_Q1] = vlc_decode_u_suffix(vlc_stream, u_pfx[J2K_Q1], vlc_buf); + u_ext[J2K_Q1] = vlc_decode_u_extension(vlc_stream, u_sfx[J2K_Q1], vlc_buf); + u[J2K_Q1] = u_pfx[J2K_Q1] + u_sfx[J2K_Q1] + (u_ext[J2K_Q1] * 4); + } + + U[J2K_Q1] = kappa[J2K_Q1] + u[J2K_Q1]; + + for (int i = 0; i < 4; i++) + m[J2K_Q1][i] = sigma_n[4 * q1 + i] * U[J2K_Q1] - ((emb_pat_k[J2K_Q1] >> i) & 1); + + recover_mag_sgn(mag_sgn_stream, J2K_Q1, q1, m_n, known_1, emb_pat_1, v, m, + E, mu_n, Dcup, Pcup, pLSB); + + q++; // move to next quad pair + } + + /** + * Initial line pair end. As an optimization, we can replace modulo + * operations with checking if a number is divisible , since that's the only + * thing we need. This is paired with is_divisible. Credits to Daniel Lemire + * blog post [1]. + * + * [1] + * https://lemire.me/blog/2019/02/08/faster-remainders-when-the-divisor-is-a-constant-beating-compilers-and-libdivide/ + * + * It's UB on zero, but the spec doesn't allow a quad being zero, so we + * error out early in case that's the case. + */ + c = precompute_c(quad_width); + + for (int row = 1; row < quad_height; row++) { + while ((q - (row * quad_width)) < quad_width - 1 && q < (quad_height * quad_width)) { + q1 = q; + q2 = q + 1; + context1 = sigma_n[4 * (q1 - quad_width) + 1]; + context1 += sigma_n[4 * (q1 - quad_width) + 3] << 2; // ne + + if (!is_divisible(q1, c)) { + context1 |= sigma_n[4 * (q1 - quad_width) - 1]; // nw + context1 += (sigma_n[4 * q1 - 1] | sigma_n[4 * q1 - 2]) << 1; // sw | q + } + if (!is_divisible(q1 + 1, c)) + context1 |= sigma_n[4 * (q1 - quad_width) + 5] << 2; + + if ((ret = jpeg2000_decode_sig_emb(s, mel_state, mel_stream, vlc_stream, + dec_cxt_vlc_table1, Dcup, sig_pat, res_off, + emb_pat_k, emb_pat_1, J2K_Q1, context1, Lcup, + Pcup)) + < 0) + goto free; + + for (int i = 0; i < 4; i++) + sigma_n[4 * q1 + i] = (sig_pat[J2K_Q1] >> i) & 1; + + context2 = sigma_n[4 * (q2 - quad_width) + 1]; + context2 += sigma_n[4 * (q2 - quad_width) + 3] << 2; + + if (!is_divisible(q2, c)) { + context2 |= sigma_n[4 * (q2 - quad_width) - 1]; + context2 += (sigma_n[4 * q2 - 1] | sigma_n[4 * q2 - 2]) << 1; + } + if (!is_divisible(q2 + 1, c)) + context2 |= sigma_n[4 * (q2 - quad_width) + 5] << 2; + + if ((ret = jpeg2000_decode_sig_emb(s, mel_state, mel_stream, vlc_stream, + dec_cxt_vlc_table1, Dcup, sig_pat, res_off, + emb_pat_k, emb_pat_1, J2K_Q2, context2, Lcup, + Pcup)) + < 0) + goto free; + + for (int i = 0; i < 4; i++) + sigma_n[4 * q2 + i] = (sig_pat[J2K_Q2] >> i) & 1; + + u[J2K_Q1] = 0; + u[J2K_Q2] = 0; + + jpeg2000_bitbuf_refill_backwards(vlc_stream, vlc_buf); + + if (res_off[J2K_Q1] == 1 && res_off[J2K_Q2] == 1) { + u_pfx[J2K_Q1] = vlc_decode_u_prefix(vlc_stream, vlc_buf); + u_pfx[J2K_Q2] = vlc_decode_u_prefix(vlc_stream, vlc_buf); + + u_sfx[J2K_Q1] = vlc_decode_u_suffix(vlc_stream, u_pfx[J2K_Q1], vlc_buf); + u_sfx[J2K_Q2] = vlc_decode_u_suffix(vlc_stream, u_pfx[J2K_Q2], vlc_buf); + + u_ext[J2K_Q1] = vlc_decode_u_extension(vlc_stream, u_sfx[J2K_Q1], vlc_buf); + u_ext[J2K_Q2] = vlc_decode_u_extension(vlc_stream, u_sfx[J2K_Q2], vlc_buf); + + u[J2K_Q1] = u_pfx[J2K_Q1] + u_sfx[J2K_Q1] + (u_ext[J2K_Q1] << 2); + u[J2K_Q2] = u_pfx[J2K_Q2] + u_sfx[J2K_Q2] + (u_ext[J2K_Q2] << 2); + + } else if (res_off[J2K_Q1] == 1 || res_off[J2K_Q2] == 1) { + uint8_t pos = res_off[J2K_Q1] == 1 ? 0 : 1; + + u_pfx[pos] = vlc_decode_u_prefix(vlc_stream, vlc_buf); + u_sfx[pos] = vlc_decode_u_suffix(vlc_stream, u_pfx[pos], vlc_buf); + u_ext[pos] = vlc_decode_u_extension(vlc_stream, u_sfx[pos], vlc_buf); + + u[pos] = u_pfx[pos] + u_sfx[pos] + (u_ext[pos] << 2); + } + sp = sig_pat[J2K_Q1]; + + gamma[J2K_Q1] = 1; + + if (sp == 0 || sp == 1 || sp == 2 || sp == 4 || sp == 8) + gamma[J2K_Q1] = 0; + + sp = sig_pat[J2K_Q2]; + + gamma[J2K_Q2] = 1; + + if (sp == 0 || sp == 1 || sp == 2 || sp == 4 || sp == 8) + gamma[J2K_Q2] = 0; + + E_n[J2K_Q1] = E[4 * (q1 - quad_width) + 1]; + E_n[J2K_Q2] = E[4 * (q2 - quad_width) + 1]; + + E_ne[J2K_Q1] = E[4 * (q1 - quad_width) + 3]; + E_ne[J2K_Q2] = E[4 * (q2 - quad_width) + 3]; + + E_nw[J2K_Q1] = (!is_divisible(q1, c)) * E[FFMAX((4 * (q1 - quad_width) - 1), 0)]; + E_nw[J2K_Q2] = (!is_divisible(q2, c)) * E[FFMAX((4 * (q2 - quad_width) - 1), 0)]; + + E_nf[J2K_Q1] = (!is_divisible(q1 + 1, c)) * E[4 * (q1 - quad_width) + 5]; + E_nf[J2K_Q2] = (!is_divisible(q2 + 1, c)) * E[4 * (q2 - quad_width) + 5]; + + max_e[J2K_Q1] = FFMAX(E_nw[J2K_Q1], FFMAX3(E_n[J2K_Q1], E_ne[J2K_Q1], E_nf[J2K_Q1])); + max_e[J2K_Q2] = FFMAX(E_nw[J2K_Q2], FFMAX3(E_n[J2K_Q2], E_ne[J2K_Q2], E_nf[J2K_Q2])); + + kappa[J2K_Q1] = FFMAX(1, gamma[J2K_Q1] * (max_e[J2K_Q1] - 1)); + kappa[J2K_Q2] = FFMAX(1, gamma[J2K_Q2] * (max_e[J2K_Q2] - 1)); + + U[J2K_Q1] = kappa[J2K_Q1] + u[J2K_Q1]; + U[J2K_Q2] = kappa[J2K_Q2] + u[J2K_Q2]; + + for (int i = 0; i < 4; i++) { + m[J2K_Q1][i] = sigma_n[4 * q1 + i] * U[J2K_Q1] - ((emb_pat_k[J2K_Q1] >> i) & 1); + m[J2K_Q2][i] = sigma_n[4 * q2 + i] * U[J2K_Q2] - ((emb_pat_k[J2K_Q2] >> i) & 1); + } + recover_mag_sgn(mag_sgn_stream, J2K_Q1, q1, m_n, known_1, emb_pat_1, v, m, + E, mu_n, Dcup, Pcup, pLSB); + + recover_mag_sgn(mag_sgn_stream, J2K_Q2, q2, m_n, known_1, emb_pat_1, v, m, + E, mu_n, Dcup, Pcup, pLSB); + + q += 2; // Move to the next quad pair + } + + if (quad_width % 2 == 1) { + q1 = q; + + /* calculate context for current quad */ + context1 = sigma_n[4 * (q1 - quad_width) + 1]; + context1 += (sigma_n[4 * (q1 - quad_width) + 3] << 2); + + if (!is_divisible(q1, c)) { + context1 |= sigma_n[4 * (q1 - quad_width) - 1]; + context1 += (sigma_n[4 * q1 - 1] | sigma_n[4 * q1 - 2]) << 1; + } + if (!is_divisible(q1 + 1, c)) + context1 |= sigma_n[4 * (q1 - quad_width) + 5] << 2; + + if ((ret = jpeg2000_decode_sig_emb(s, mel_state, mel_stream, vlc_stream, + dec_cxt_vlc_table1, Dcup, sig_pat, res_off, + emb_pat_k, emb_pat_1, J2K_Q1, context1, Lcup, + Pcup)) < 0) + goto free; + + for (int i = 0; i < 4; i++) + sigma_n[4 * q1 + i] = (sig_pat[J2K_Q1] >> i) & 1; + + u[J2K_Q1] = 0; + + /* Recover mag_sgn value */ + if (res_off[J2K_Q1] == 1) { + u_pfx[J2K_Q1] = vlc_decode_u_prefix(vlc_stream, vlc_buf); + u_sfx[J2K_Q1] = vlc_decode_u_suffix(vlc_stream, u_pfx[J2K_Q1], vlc_buf); + u_ext[J2K_Q1] = vlc_decode_u_extension(vlc_stream, u_sfx[J2K_Q1], vlc_buf); + + u[J2K_Q1] = u_pfx[J2K_Q1] + u_sfx[J2K_Q1] + (u_ext[J2K_Q1] << 2); + } + + sp = sig_pat[J2K_Q1]; + + gamma[J2K_Q1] = 1; + + if (sp == 0 || sp == 1 || sp == 2 || sp == 4 || sp == 8) + gamma[J2K_Q1] = 0; + + E_n[J2K_Q1] = E[4 * (q1 - quad_width) + 1]; + + E_ne[J2K_Q1] = E[4 * (q1 - quad_width) + 3]; + + E_nw[J2K_Q1] = (!is_divisible(q1, c)) * E[FFMAX((4 * (q1 - quad_width) - 1), 0)]; + + E_nf[J2K_Q1] = (!is_divisible(q1 + 1, c)) * E[4 * (q1 - quad_width) + 5]; + + max_e[J2K_Q1] = FFMAX(E_nw[J2K_Q1], FFMAX3(E_n[J2K_Q1], E_ne[J2K_Q1], E_nf[J2K_Q1])); + + kappa[J2K_Q1] = FFMAX(1, gamma[J2K_Q1] * (max_e[J2K_Q1] - 1)); + + U[J2K_Q1] = kappa[J2K_Q1] + u[J2K_Q1]; + + for (int i = 0; i < 4; i++) + m[J2K_Q1][i] = sigma_n[4 * q1 + i] * U[J2K_Q1] - ((emb_pat_k[J2K_Q1] >> i) & 1); + + recover_mag_sgn(mag_sgn_stream, J2K_Q1, q1, m_n, known_1, emb_pat_1, v, m, + E, mu_n, Dcup, Pcup, pLSB); + q += 1; + } + } + + // convert to raster-scan + for (int y = 0; y < quad_height; y++) { + for (int x = 0; x < quad_width; x++) { + int j1, j2; + int x1, x2 , x3; + + j1 = 2 * y; + j2 = 2 * x; + + sample_buf[j2 + (j1 * width)] = (int32_t)*mu; + jpeg2000_modify_state(j1, j2, width, *sigma, block_states); + sigma += 1; + mu += 1; + + x1 = y != quad_height - 1 || is_border_y == 0; + sample_buf[j2 + ((j1 + 1) * width)] = ((int32_t)*mu) * x1; + jpeg2000_modify_state(j1 + 1, j2, width, (*sigma) * x1, block_states); + sigma += 1; + mu += 1; + + x2 = x != quad_width - 1 || is_border_x == 0; + sample_buf[(j2 + 1) + (j1 * width)] = ((int32_t)*mu) * x2; + jpeg2000_modify_state(j1, j2 + 1, width, (*sigma) * x2, block_states); + sigma += 1; + mu += 1; + + x3 = x1 | x2; + sample_buf[(j2 + 1) + (j1 + 1) * width] = ((int32_t)*mu) * x3; + jpeg2000_modify_state(j1 + 1, j2 + 1, width, (*sigma) * x3, block_states); + sigma += 1; + mu += 1; + } + } + ret = 1; +free: + av_freep(&sigma_n); + av_freep(&E); + av_freep(&mu_n); + return ret; +} + +static void jpeg2000_calc_mbr(uint8_t *mbr, const uint16_t i, const uint16_t j, + const uint32_t mbr_info, uint8_t causal_cond, + uint8_t *block_states, int width) +{ + int local_mbr = 0; + + local_mbr |= jpeg2000_get_state(i - 1, j - 1, width, HT_SHIFT_SIGMA, block_states); + local_mbr |= jpeg2000_get_state(i - 1, j + 0, width, HT_SHIFT_SIGMA, block_states); + local_mbr |= jpeg2000_get_state(i - 1, j + 1, width, HT_SHIFT_SIGMA, block_states); + + local_mbr |= jpeg2000_get_state(i + 0, j - 1, width, HT_SHIFT_SIGMA, block_states); + local_mbr |= jpeg2000_get_state(i + 0, j + 1, width, HT_SHIFT_SIGMA, block_states); + + local_mbr |= jpeg2000_get_state(i + 1, j - 1, width, HT_SHIFT_SIGMA, block_states) * causal_cond; + local_mbr |= jpeg2000_get_state(i + 1, j + 0, width, HT_SHIFT_SIGMA, block_states) * causal_cond; + local_mbr |= jpeg2000_get_state(i + 1, j + 1, width, HT_SHIFT_SIGMA, block_states) * causal_cond; + + local_mbr |= jpeg2000_get_state(i - 1, j - 1, width, HT_SHIFT_REF, block_states) * + jpeg2000_get_state(i - 1, j - 1, width, HT_SHIFT_SCAN, block_states); + local_mbr |= jpeg2000_get_state(i - 1, j + 0, width, HT_SHIFT_REF, block_states) * + jpeg2000_get_state(i - 1, j - 1, width, HT_SHIFT_SCAN, block_states); + local_mbr |= jpeg2000_get_state(i - 1, j + 1, width, HT_SHIFT_REF, block_states) * + jpeg2000_get_state(i - 1, j + 1, width, HT_SHIFT_SCAN, block_states); + + local_mbr |= jpeg2000_get_state(i + 0, j - 1, width, HT_SHIFT_REF, block_states) * + jpeg2000_get_state(i + 0, j - 1, width, HT_SHIFT_SCAN, block_states); + local_mbr |= jpeg2000_get_state(i + 0, j + 1, width, HT_SHIFT_REF, block_states) * + jpeg2000_get_state(i + 0, j + 1, width, HT_SHIFT_SCAN, block_states); + + local_mbr |= jpeg2000_get_state(i + 1, j - 1, width, HT_SHIFT_REF, block_states) * + jpeg2000_get_state(i + 1, j - 1, width, HT_SHIFT_SCAN, block_states) * causal_cond; + local_mbr |= jpeg2000_get_state(i + 1, j + 0, width, HT_SHIFT_REF, block_states) * + jpeg2000_get_state(i + 1, j + 0, width, HT_SHIFT_SCAN, block_states) * causal_cond; + local_mbr |= jpeg2000_get_state(i + 1, j + 1, width, HT_SHIFT_REF, block_states) * + jpeg2000_get_state(i + 1, j + 1, width, HT_SHIFT_SCAN, block_states) * causal_cond; + + *mbr |= local_mbr; +} + +static void jpeg2000_process_stripes_block(StateVars *sig_prop, int i_s, int j_s, + int width, int height, int stride, int pLSB, + int32_t *sample_buf, uint8_t *block_states, + uint8_t *magref_segment, uint32_t magref_length) +{ + for (int j = j_s; j < j_s + width; j++) { + uint32_t mbr_info = 0; + for (int i = i_s; i < i_s + height; i++) { + int modify_state, cond; + uint8_t bit; + uint8_t causal_cond = i != (i_s + height - 1); + int32_t *sp = &sample_buf[j + (i * (stride - 2))]; + uint8_t mbr = 0; + + if (jpeg2000_get_state(i, j, stride - 2, HT_SHIFT_SIGMA, block_states) == 0) + jpeg2000_calc_mbr(&mbr, i, j, mbr_info & 0x1EF, causal_cond, block_states, stride - 2); + mbr_info >>= 3; + cond = mbr != 0; + bit = jpeg2000_peek_bit(sig_prop, magref_segment, magref_length); + *sp |= (bit * cond) << pLSB; + sig_prop->bits -= cond; + modify_state = (((1 << HT_SHIFT_REF_IND) | (1 << HT_SHIFT_REF)) * cond) | 1 << HT_SHIFT_SCAN; + jpeg2000_modify_state(i, j, stride - 2, modify_state, block_states); + } + } +} + +/** + * See procedure decodeSigPropMag at Rec. ITU-T T.814, 7.4. +*/ +av_noinline +static void jpeg2000_decode_sigprop_segment(Jpeg2000Cblk *cblk, uint16_t width, + uint16_t height, uint8_t *magref_segment, + uint32_t magref_length, uint8_t pLSB, + int32_t *sample_buf, uint8_t *block_states) +{ + StateVars sp_dec; + + const uint16_t num_v_stripe = height / 4; + const uint16_t num_h_stripe = width / 4; + int b_width = 4; + int b_height = 4; + int stride = width + 2; + + int last_width; + uint16_t i = 0, j = 0; + + jpeg2000_init_zero(&sp_dec); + + for (int n1 = 0; n1 < num_v_stripe; n1++) { + j = 0; + for (int n2 = 0; n2 < num_h_stripe; n2++) { + jpeg2000_process_stripes_block(&sp_dec, i, j, b_width, b_height, stride, + pLSB, sample_buf, block_states, magref_segment, + magref_length); + j += 4; + } + last_width = width % 4; + if (last_width) + jpeg2000_process_stripes_block(&sp_dec, i, j, last_width, b_height, stride, + pLSB, sample_buf, block_states, magref_segment, + magref_length); + i += 4; + } + + /* Decode remaining height stripes */ + b_height = height % 4; + j = 0; + for (int n2 = 0; n2 < num_h_stripe; n2++) { + jpeg2000_process_stripes_block(&sp_dec, i, j, b_width, b_height, stride, + pLSB, sample_buf, block_states, magref_segment, + magref_length); + j += 4; + } + last_width = width % 4; + if (last_width) + jpeg2000_process_stripes_block(&sp_dec, i, j, last_width, b_height, stride, + pLSB, sample_buf, block_states, magref_segment, + magref_length); +} + +/** + * See procedure decodeSigPropMag at Rec. ITU-T T.814, 7.5. +*/ +static int +jpeg2000_decode_magref_segment(Jpeg2000Cblk *cblk, uint16_t width, uint16_t block_height, uint8_t *magref_segment, + uint32_t magref_length, uint8_t pLSB, int32_t *sample_buf, uint8_t *block_states) +{ + + StateVars mag_ref = { 0 }; + const uint16_t num_v_stripe = block_height / 4; + uint16_t height = 4; + uint16_t i_start = 0; + int32_t *sp; + + jpeg2000_init_mag_ref(&mag_ref, magref_length); + + for (int n1 = 0; n1 < num_v_stripe; n1++) { + for (int j = 0; j < width; j++) { + for (int i = i_start; i < i_start + height; i++) { + /** + * We move column wise, going from one quad to another. See + * Rec. ITU-T T.814, Figure 7. + */ + sp = &sample_buf[j + i * width]; + if (jpeg2000_get_state(i, j, width, HT_SHIFT_SIGMA, block_states) != 0) { + jpeg2000_modify_state(i, j, width, 1 << HT_SHIFT_REF_IND, block_states); + *sp |= jpeg2000_import_magref_bit(&mag_ref, magref_segment, magref_length) << pLSB; + } + } + } + i_start += 4; + } + height = block_height % 4; + for (int j = 0; j < width; j++) { + for (int i = i_start; i < i_start + height; i++) { + sp = &sample_buf[j + i * width]; + if (jpeg2000_get_state(i, j, width, HT_SHIFT_SIGMA, block_states) != 0) { + jpeg2000_modify_state(i, j, width, 1 << HT_SHIFT_REF_IND, block_states); + *sp |= jpeg2000_import_magref_bit(&mag_ref, magref_segment, magref_length) << pLSB; + } + } + } + return 1; +} + + +int +ff_jpeg2000_decode_htj2k(const Jpeg2000DecoderContext *s, Jpeg2000CodingStyle *codsty, Jpeg2000T1Context *t1, Jpeg2000Cblk *cblk, + int width, int height, int magp, uint8_t roi_shift) +{ + uint8_t p0 = 0; // Number of placeholder passes + uint32_t Lcup; // Length of HT cleanup segment + uint32_t Lref; // Length of Refinement segment + uint32_t Scup; // HT cleanup segment suffix length + uint32_t Pcup; // HT cleanup segment prefix length + + uint8_t S_blk; // Number of skipped magnitude bitplanes + uint8_t pLSB; + + uint8_t *Dcup; // Byte of an HT cleanup segment + uint8_t *Dref; // Byte of an HT refinement segment + + int z_blk; // Number of ht coding pass + + uint8_t empty_passes; + + StateVars mag_sgn; // Magnitude and Sign + StateVars mel; // Adaptive run-length coding + StateVars vlc; // Variable Length coding + StateVars sig_prop; // Significance propagation + + MelDecoderState mel_state; + + int ret; + + /* Temporary buffers */ + int32_t *sample_buf; + uint8_t *block_states; + + int32_t n, val; // Post-processing + + int32_t M_b = magp; + + /* codeblock size as constrained by Rec. ITU-T T.800, Table A.18 */ + av_assert0(width <= 1024U && height <= 1024U); + av_assert0(width * height <= 4096); + av_assert0(width * height > 0); + + memset(t1->data, 0, t1->stride * height * sizeof(*t1->data)); + memset(t1->flags, 0, t1->stride * (height + 2) * sizeof(*t1->flags)); + + if (cblk->npasses == 0) + return 0; + + if (cblk->npasses > 3) + p0 = 0; + else if (cblk->length == 0) + p0 = 1; + + empty_passes = p0 * 3; + z_blk = cblk->npasses - empty_passes; + + if (z_blk <= 0) + return 0; // No passes within this set, continue + + Lcup = cblk->pass_lengths[0]; + Lref = cblk->pass_lengths[1]; + + if (Lcup < 2) { + av_log(s->avctx, AV_LOG_ERROR, + "Cleanup pass length must be at least 2 bytes in length\n"); + return AVERROR_INVALIDDATA; + } + Dcup = cblk->data; + Dref = cblk->data + Lcup; // Dref comes after the refinement segment + S_blk = p0 + cblk->zbp; + pLSB = 30 - S_blk; + + Scup = (Dcup[Lcup - 1] << 4) + (Dcup[Lcup - 2] & 0x0F); + + if (Scup < 2 || Scup > Lcup || Scup > 4079) { + av_log(s->avctx, AV_LOG_ERROR, "Cleanup pass suffix length is invalid %d\n", + Scup); + ret = AVERROR_INVALIDDATA; + goto free; + } + Pcup = Lcup - Scup; + + /* modDcup shall be done before the creation of vlc instance. */ + Dcup[Lcup - 1] = 0xFF; + Dcup[Lcup - 2] |= 0x0F; + + /* Magnitude and refinement */ + jpeg2000_init_zero(&mag_sgn); + jpeg2000_bitbuf_refill_forward(&mag_sgn, Dcup, Pcup); + + /* Significance propagation */ + jpeg2000_init_zero(&sig_prop); + + /* Adaptive run length */ + jpeg2000_init_mel(&mel, Pcup); + + /* Variable Length coding */ + jpeg2000_init_vlc(&vlc, Lcup, Pcup, Dcup); + + jpeg2000_init_mel_decoder(&mel_state); + + sample_buf = av_calloc((width + 4) * (height + 4), sizeof(int32_t)); + block_states = av_calloc((width + 4) * (height + 4), sizeof(uint8_t)); + + if (!sample_buf || !block_states) { + ret = AVERROR(ENOMEM); + goto free; + } + if ((ret = jpeg2000_decode_ht_cleanup_segment(s, cblk, t1, &mel_state, &mel, &vlc, + &mag_sgn, Dcup, Lcup, Pcup, pLSB, width, + height, sample_buf, block_states)) < 0) + goto free; + + if (cblk->npasses > 1) + jpeg2000_decode_sigprop_segment(cblk, width, height, Dref, Lref, + pLSB - 1, sample_buf, block_states); + + if (cblk->npasses > 2) + if ((ret = jpeg2000_decode_magref_segment(cblk, width, height, Dref, Lref, + pLSB - 1, sample_buf, block_states)) < 0) + goto free; + + pLSB = 31 - M_b; + + /* Reconstruct the sample values */ + for (int y = 0; y < height; y++) { + for (int x = 0; x < width; x++) { + n = x + (y * t1->stride); + val = sample_buf[x + (y * width)]; + /* Convert sign-magnitude to two's complement. */ + val = val >> 31 ? 0x80000000 - val : val; + val >>= (pLSB - 1); + t1->data[n] = val; + } + } +free: + av_freep(&sample_buf); + av_freep(&block_states); + return ret; +} + +/** + * CtxVLC tables (see Rec. ITU-T T.800, Annex C) as found at + * https://github.com/osamu620/OpenHTJ2K (author: Osamu Watanabe) + */ +static const uint16_t dec_cxt_vlc_table1[1024] = { + 0x0016, 0x006A, 0x0046, 0x00DD, 0x0086, 0x888B, 0x0026, 0x444D, 0x0016, 0x00AA, 0x0046, 0x88AD, 0x0086, + 0x003A, 0x0026, 0x00DE, 0x0016, 0x00CA, 0x0046, 0x009D, 0x0086, 0x005A, 0x0026, 0x222D, 0x0016, 0x009A, + 0x0046, 0x007D, 0x0086, 0x01FD, 0x0026, 0x007E, 0x0016, 0x006A, 0x0046, 0x88CD, 0x0086, 0x888B, 0x0026, + 0x111D, 0x0016, 0x00AA, 0x0046, 0x005D, 0x0086, 0x003A, 0x0026, 0x00EE, 0x0016, 0x00CA, 0x0046, 0x00BD, + 0x0086, 0x005A, 0x0026, 0x11FF, 0x0016, 0x009A, 0x0046, 0x003D, 0x0086, 0x04ED, 0x0026, 0x2AAF, 0x0016, + 0x006A, 0x0046, 0x00DD, 0x0086, 0x888B, 0x0026, 0x444D, 0x0016, 0x00AA, 0x0046, 0x88AD, 0x0086, 0x003A, + 0x0026, 0x44EF, 0x0016, 0x00CA, 0x0046, 0x009D, 0x0086, 0x005A, 0x0026, 0x222D, 0x0016, 0x009A, 0x0046, + 0x007D, 0x0086, 0x01FD, 0x0026, 0x00BE, 0x0016, 0x006A, 0x0046, 0x88CD, 0x0086, 0x888B, 0x0026, 0x111D, + 0x0016, 0x00AA, 0x0046, 0x005D, 0x0086, 0x003A, 0x0026, 0x4CCF, 0x0016, 0x00CA, 0x0046, 0x00BD, 0x0086, + 0x005A, 0x0026, 0x00FE, 0x0016, 0x009A, 0x0046, 0x003D, 0x0086, 0x04ED, 0x0026, 0x006F, 0x0002, 0x0088, + 0x0002, 0x005C, 0x0002, 0x0018, 0x0002, 0x00DE, 0x0002, 0x0028, 0x0002, 0x009C, 0x0002, 0x004A, 0x0002, + 0x007E, 0x0002, 0x0088, 0x0002, 0x00CC, 0x0002, 0x0018, 0x0002, 0x888F, 0x0002, 0x0028, 0x0002, 0x00FE, + 0x0002, 0x003A, 0x0002, 0x222F, 0x0002, 0x0088, 0x0002, 0x04FD, 0x0002, 0x0018, 0x0002, 0x00BE, 0x0002, + 0x0028, 0x0002, 0x00BF, 0x0002, 0x004A, 0x0002, 0x006E, 0x0002, 0x0088, 0x0002, 0x00AC, 0x0002, 0x0018, + 0x0002, 0x444F, 0x0002, 0x0028, 0x0002, 0x00EE, 0x0002, 0x003A, 0x0002, 0x113F, 0x0002, 0x0088, 0x0002, + 0x005C, 0x0002, 0x0018, 0x0002, 0x00CF, 0x0002, 0x0028, 0x0002, 0x009C, 0x0002, 0x004A, 0x0002, 0x006F, + 0x0002, 0x0088, 0x0002, 0x00CC, 0x0002, 0x0018, 0x0002, 0x009F, 0x0002, 0x0028, 0x0002, 0x00EF, 0x0002, + 0x003A, 0x0002, 0x233F, 0x0002, 0x0088, 0x0002, 0x04FD, 0x0002, 0x0018, 0x0002, 0x00AF, 0x0002, 0x0028, + 0x0002, 0x44FF, 0x0002, 0x004A, 0x0002, 0x005F, 0x0002, 0x0088, 0x0002, 0x00AC, 0x0002, 0x0018, 0x0002, + 0x007F, 0x0002, 0x0028, 0x0002, 0x00DF, 0x0002, 0x003A, 0x0002, 0x111F, 0x0002, 0x0028, 0x0002, 0x005C, + 0x0002, 0x008A, 0x0002, 0x00BF, 0x0002, 0x0018, 0x0002, 0x00FE, 0x0002, 0x00CC, 0x0002, 0x007E, 0x0002, + 0x0028, 0x0002, 0x8FFF, 0x0002, 0x004A, 0x0002, 0x007F, 0x0002, 0x0018, 0x0002, 0x00DF, 0x0002, 0x00AC, + 0x0002, 0x133F, 0x0002, 0x0028, 0x0002, 0x222D, 0x0002, 0x008A, 0x0002, 0x00BE, 0x0002, 0x0018, 0x0002, + 0x44EF, 0x0002, 0x2AAD, 0x0002, 0x006E, 0x0002, 0x0028, 0x0002, 0x15FF, 0x0002, 0x004A, 0x0002, 0x009E, + 0x0002, 0x0018, 0x0002, 0x00CF, 0x0002, 0x003C, 0x0002, 0x223F, 0x0002, 0x0028, 0x0002, 0x005C, 0x0002, + 0x008A, 0x0002, 0x2BBF, 0x0002, 0x0018, 0x0002, 0x04EF, 0x0002, 0x00CC, 0x0002, 0x006F, 0x0002, 0x0028, + 0x0002, 0x27FF, 0x0002, 0x004A, 0x0002, 0x009F, 0x0002, 0x0018, 0x0002, 0x00DE, 0x0002, 0x00AC, 0x0002, + 0x444F, 0x0002, 0x0028, 0x0002, 0x222D, 0x0002, 0x008A, 0x0002, 0x8AAF, 0x0002, 0x0018, 0x0002, 0x00EE, + 0x0002, 0x2AAD, 0x0002, 0x005F, 0x0002, 0x0028, 0x0002, 0x44FF, 0x0002, 0x004A, 0x0002, 0x888F, 0x0002, + 0x0018, 0x0002, 0xAAAF, 0x0002, 0x003C, 0x0002, 0x111F, 0x0004, 0x8FFD, 0x0028, 0x005C, 0x0004, 0x00BC, + 0x008A, 0x66FF, 0x0004, 0x00CD, 0x0018, 0x111D, 0x0004, 0x009C, 0x003A, 0x8AAF, 0x0004, 0x00FC, 0x0028, + 0x133D, 0x0004, 0x00AC, 0x004A, 0x3BBF, 0x0004, 0x2BBD, 0x0018, 0x5FFF, 0x0004, 0x006C, 0x157D, 0x455F, + 0x0004, 0x2FFD, 0x0028, 0x222D, 0x0004, 0x22AD, 0x008A, 0x44EF, 0x0004, 0x00CC, 0x0018, 0x4FFF, 0x0004, + 0x007C, 0x003A, 0x447F, 0x0004, 0x04DD, 0x0028, 0x233D, 0x0004, 0x009D, 0x004A, 0x00DE, 0x0004, 0x88BD, + 0x0018, 0xAFFF, 0x0004, 0x115D, 0x1FFD, 0x444F, 0x0004, 0x8FFD, 0x0028, 0x005C, 0x0004, 0x00BC, 0x008A, + 0x8CEF, 0x0004, 0x00CD, 0x0018, 0x111D, 0x0004, 0x009C, 0x003A, 0x888F, 0x0004, 0x00FC, 0x0028, 0x133D, + 0x0004, 0x00AC, 0x004A, 0x44DF, 0x0004, 0x2BBD, 0x0018, 0x8AFF, 0x0004, 0x006C, 0x157D, 0x006F, 0x0004, + 0x2FFD, 0x0028, 0x222D, 0x0004, 0x22AD, 0x008A, 0x00EE, 0x0004, 0x00CC, 0x0018, 0x2EEF, 0x0004, 0x007C, + 0x003A, 0x277F, 0x0004, 0x04DD, 0x0028, 0x233D, 0x0004, 0x009D, 0x004A, 0x1BBF, 0x0004, 0x88BD, 0x0018, + 0x37FF, 0x0004, 0x115D, 0x1FFD, 0x333F, 0x0002, 0x0088, 0x0002, 0x02ED, 0x0002, 0x00CA, 0x0002, 0x4CCF, + 0x0002, 0x0048, 0x0002, 0x23FF, 0x0002, 0x001A, 0x0002, 0x888F, 0x0002, 0x0088, 0x0002, 0x006C, 0x0002, + 0x002A, 0x0002, 0x00AF, 0x0002, 0x0048, 0x0002, 0x22EF, 0x0002, 0x00AC, 0x0002, 0x005F, 0x0002, 0x0088, + 0x0002, 0x444D, 0x0002, 0x00CA, 0x0002, 0xCCCF, 0x0002, 0x0048, 0x0002, 0x00FE, 0x0002, 0x001A, 0x0002, + 0x006F, 0x0002, 0x0088, 0x0002, 0x005C, 0x0002, 0x002A, 0x0002, 0x009F, 0x0002, 0x0048, 0x0002, 0x00DF, + 0x0002, 0x03FD, 0x0002, 0x222F, 0x0002, 0x0088, 0x0002, 0x02ED, 0x0002, 0x00CA, 0x0002, 0x8CCF, 0x0002, + 0x0048, 0x0002, 0x11FF, 0x0002, 0x001A, 0x0002, 0x007E, 0x0002, 0x0088, 0x0002, 0x006C, 0x0002, 0x002A, + 0x0002, 0x007F, 0x0002, 0x0048, 0x0002, 0x00EE, 0x0002, 0x00AC, 0x0002, 0x003E, 0x0002, 0x0088, 0x0002, + 0x444D, 0x0002, 0x00CA, 0x0002, 0x00BE, 0x0002, 0x0048, 0x0002, 0x00BF, 0x0002, 0x001A, 0x0002, 0x003F, + 0x0002, 0x0088, 0x0002, 0x005C, 0x0002, 0x002A, 0x0002, 0x009E, 0x0002, 0x0048, 0x0002, 0x00DE, 0x0002, + 0x03FD, 0x0002, 0x111F, 0x0004, 0x8AED, 0x0048, 0x888D, 0x0004, 0x00DC, 0x00CA, 0x3FFF, 0x0004, 0xCFFD, + 0x002A, 0x003D, 0x0004, 0x00BC, 0x005A, 0x8DDF, 0x0004, 0x8FFD, 0x0048, 0x006C, 0x0004, 0x027D, 0x008A, + 0x99FF, 0x0004, 0x00EC, 0x00FA, 0x003C, 0x0004, 0x00AC, 0x001A, 0x009F, 0x0004, 0x2FFD, 0x0048, 0x007C, + 0x0004, 0x44CD, 0x00CA, 0x67FF, 0x0004, 0x1FFD, 0x002A, 0x444D, 0x0004, 0x00AD, 0x005A, 0x8CCF, 0x0004, + 0x4FFD, 0x0048, 0x445D, 0x0004, 0x01BD, 0x008A, 0x4EEF, 0x0004, 0x45DD, 0x00FA, 0x111D, 0x0004, 0x009C, + 0x001A, 0x222F, 0x0004, 0x8AED, 0x0048, 0x888D, 0x0004, 0x00DC, 0x00CA, 0xAFFF, 0x0004, 0xCFFD, 0x002A, + 0x003D, 0x0004, 0x00BC, 0x005A, 0x11BF, 0x0004, 0x8FFD, 0x0048, 0x006C, 0x0004, 0x027D, 0x008A, 0x22EF, + 0x0004, 0x00EC, 0x00FA, 0x003C, 0x0004, 0x00AC, 0x001A, 0x227F, 0x0004, 0x2FFD, 0x0048, 0x007C, 0x0004, + 0x44CD, 0x00CA, 0x5DFF, 0x0004, 0x1FFD, 0x002A, 0x444D, 0x0004, 0x00AD, 0x005A, 0x006F, 0x0004, 0x4FFD, + 0x0048, 0x445D, 0x0004, 0x01BD, 0x008A, 0x11DF, 0x0004, 0x45DD, 0x00FA, 0x111D, 0x0004, 0x009C, 0x001A, + 0x155F, 0x0006, 0x00FC, 0x0018, 0x111D, 0x0048, 0x888D, 0x00AA, 0x4DDF, 0x0006, 0x2AAD, 0x005A, 0x67FF, + 0x0028, 0x223D, 0x00BC, 0xAAAF, 0x0006, 0x00EC, 0x0018, 0x5FFF, 0x0048, 0x006C, 0x008A, 0xCCCF, 0x0006, + 0x009D, 0x00CA, 0x44EF, 0x0028, 0x003C, 0x8FFD, 0x137F, 0x0006, 0x8EED, 0x0018, 0x1FFF, 0x0048, 0x007C, + 0x00AA, 0x4CCF, 0x0006, 0x227D, 0x005A, 0x1DDF, 0x0028, 0x444D, 0x4FFD, 0x155F, 0x0006, 0x00DC, 0x0018, + 0x2EEF, 0x0048, 0x445D, 0x008A, 0x22BF, 0x0006, 0x009C, 0x00CA, 0x8CDF, 0x0028, 0x222D, 0x2FFD, 0x226F, + 0x0006, 0x00FC, 0x0018, 0x111D, 0x0048, 0x888D, 0x00AA, 0x1BBF, 0x0006, 0x2AAD, 0x005A, 0x33FF, 0x0028, + 0x223D, 0x00BC, 0x8AAF, 0x0006, 0x00EC, 0x0018, 0x9BFF, 0x0048, 0x006C, 0x008A, 0x8ABF, 0x0006, 0x009D, + 0x00CA, 0x4EEF, 0x0028, 0x003C, 0x8FFD, 0x466F, 0x0006, 0x8EED, 0x0018, 0xCFFF, 0x0048, 0x007C, 0x00AA, + 0x8CCF, 0x0006, 0x227D, 0x005A, 0xAEEF, 0x0028, 0x444D, 0x4FFD, 0x477F, 0x0006, 0x00DC, 0x0018, 0xAFFF, + 0x0048, 0x445D, 0x008A, 0x2BBF, 0x0006, 0x009C, 0x00CA, 0x44DF, 0x0028, 0x222D, 0x2FFD, 0x133F, 0x00F6, + 0xAFFD, 0x1FFB, 0x003C, 0x0008, 0x23BD, 0x007A, 0x11DF, 0x00F6, 0x45DD, 0x2FFB, 0x4EEF, 0x00DA, 0x177D, + 0xCFFD, 0x377F, 0x00F6, 0x3FFD, 0x8FFB, 0x111D, 0x0008, 0x009C, 0x005A, 0x1BBF, 0x00F6, 0x00CD, 0x00BA, + 0x8DDF, 0x4FFB, 0x006C, 0x9BFD, 0x455F, 0x00F6, 0x67FD, 0x1FFB, 0x002C, 0x0008, 0x00AC, 0x007A, 0x009F, + 0x00F6, 0x00AD, 0x2FFB, 0x7FFF, 0x00DA, 0x004C, 0x5FFD, 0x477F, 0x00F6, 0x00EC, 0x8FFB, 0x001C, 0x0008, + 0x008C, 0x005A, 0x888F, 0x00F6, 0x00CC, 0x00BA, 0x2EEF, 0x4FFB, 0x115D, 0x8AED, 0x113F, 0x00F6, 0xAFFD, + 0x1FFB, 0x003C, 0x0008, 0x23BD, 0x007A, 0x1DDF, 0x00F6, 0x45DD, 0x2FFB, 0xBFFF, 0x00DA, 0x177D, 0xCFFD, + 0x447F, 0x00F6, 0x3FFD, 0x8FFB, 0x111D, 0x0008, 0x009C, 0x005A, 0x277F, 0x00F6, 0x00CD, 0x00BA, 0x22EF, + 0x4FFB, 0x006C, 0x9BFD, 0x444F, 0x00F6, 0x67FD, 0x1FFB, 0x002C, 0x0008, 0x00AC, 0x007A, 0x11BF, 0x00F6, + 0x00AD, 0x2FFB, 0xFFFF, 0x00DA, 0x004C, 0x5FFD, 0x233F, 0x00F6, 0x00EC, 0x8FFB, 0x001C, 0x0008, 0x008C, + 0x005A, 0x006F, 0x00F6, 0x00CC, 0x00BA, 0x8BBF, 0x4FFB, 0x115D, 0x8AED, 0x222F}; + +static const uint16_t dec_cxt_vlc_table0[1024] = { + 0x0026, 0x00AA, 0x0046, 0x006C, 0x0086, 0x8AED, 0x0018, 0x8DDF, 0x0026, 0x01BD, 0x0046, 0x5FFF, 0x0086, + 0x027D, 0x005A, 0x155F, 0x0026, 0x003A, 0x0046, 0x444D, 0x0086, 0x4CCD, 0x0018, 0xCCCF, 0x0026, 0x2EFD, + 0x0046, 0x99FF, 0x0086, 0x009C, 0x00CA, 0x133F, 0x0026, 0x00AA, 0x0046, 0x445D, 0x0086, 0x8CCD, 0x0018, + 0x11DF, 0x0026, 0x4FFD, 0x0046, 0xCFFF, 0x0086, 0x009D, 0x005A, 0x007E, 0x0026, 0x003A, 0x0046, 0x1FFF, + 0x0086, 0x88AD, 0x0018, 0x00BE, 0x0026, 0x8FFD, 0x0046, 0x4EEF, 0x0086, 0x888D, 0x00CA, 0x111F, 0x0026, + 0x00AA, 0x0046, 0x006C, 0x0086, 0x8AED, 0x0018, 0x45DF, 0x0026, 0x01BD, 0x0046, 0x22EF, 0x0086, 0x027D, + 0x005A, 0x227F, 0x0026, 0x003A, 0x0046, 0x444D, 0x0086, 0x4CCD, 0x0018, 0x11BF, 0x0026, 0x2EFD, 0x0046, + 0x00FE, 0x0086, 0x009C, 0x00CA, 0x223F, 0x0026, 0x00AA, 0x0046, 0x445D, 0x0086, 0x8CCD, 0x0018, 0x00DE, + 0x0026, 0x4FFD, 0x0046, 0xABFF, 0x0086, 0x009D, 0x005A, 0x006F, 0x0026, 0x003A, 0x0046, 0x6EFF, 0x0086, + 0x88AD, 0x0018, 0x2AAF, 0x0026, 0x8FFD, 0x0046, 0x00EE, 0x0086, 0x888D, 0x00CA, 0x222F, 0x0004, 0x00CA, + 0x0088, 0x027D, 0x0004, 0x4CCD, 0x0028, 0x00FE, 0x0004, 0x2AFD, 0x0048, 0x005C, 0x0004, 0x009D, 0x0018, + 0x00DE, 0x0004, 0x01BD, 0x0088, 0x006C, 0x0004, 0x88AD, 0x0028, 0x11DF, 0x0004, 0x8AED, 0x0048, 0x003C, + 0x0004, 0x888D, 0x0018, 0x111F, 0x0004, 0x00CA, 0x0088, 0x006D, 0x0004, 0x88CD, 0x0028, 0x88FF, 0x0004, + 0x8BFD, 0x0048, 0x444D, 0x0004, 0x009C, 0x0018, 0x00BE, 0x0004, 0x4EFD, 0x0088, 0x445D, 0x0004, 0x00AC, + 0x0028, 0x00EE, 0x0004, 0x45DD, 0x0048, 0x222D, 0x0004, 0x003D, 0x0018, 0x007E, 0x0004, 0x00CA, 0x0088, + 0x027D, 0x0004, 0x4CCD, 0x0028, 0x1FFF, 0x0004, 0x2AFD, 0x0048, 0x005C, 0x0004, 0x009D, 0x0018, 0x11BF, + 0x0004, 0x01BD, 0x0088, 0x006C, 0x0004, 0x88AD, 0x0028, 0x22EF, 0x0004, 0x8AED, 0x0048, 0x003C, 0x0004, + 0x888D, 0x0018, 0x227F, 0x0004, 0x00CA, 0x0088, 0x006D, 0x0004, 0x88CD, 0x0028, 0x4EEF, 0x0004, 0x8BFD, + 0x0048, 0x444D, 0x0004, 0x009C, 0x0018, 0x2AAF, 0x0004, 0x4EFD, 0x0088, 0x445D, 0x0004, 0x00AC, 0x0028, + 0x8DDF, 0x0004, 0x45DD, 0x0048, 0x222D, 0x0004, 0x003D, 0x0018, 0x155F, 0x0004, 0x005A, 0x0088, 0x006C, + 0x0004, 0x88DD, 0x0028, 0x23FF, 0x0004, 0x11FD, 0x0048, 0x444D, 0x0004, 0x00AD, 0x0018, 0x00BE, 0x0004, + 0x137D, 0x0088, 0x155D, 0x0004, 0x00CC, 0x0028, 0x00DE, 0x0004, 0x02ED, 0x0048, 0x111D, 0x0004, 0x009D, + 0x0018, 0x007E, 0x0004, 0x005A, 0x0088, 0x455D, 0x0004, 0x44CD, 0x0028, 0x00EE, 0x0004, 0x1FFD, 0x0048, + 0x003C, 0x0004, 0x00AC, 0x0018, 0x555F, 0x0004, 0x47FD, 0x0088, 0x113D, 0x0004, 0x02BD, 0x0028, 0x477F, + 0x0004, 0x4CDD, 0x0048, 0x8FFF, 0x0004, 0x009C, 0x0018, 0x222F, 0x0004, 0x005A, 0x0088, 0x006C, 0x0004, + 0x88DD, 0x0028, 0x00FE, 0x0004, 0x11FD, 0x0048, 0x444D, 0x0004, 0x00AD, 0x0018, 0x888F, 0x0004, 0x137D, + 0x0088, 0x155D, 0x0004, 0x00CC, 0x0028, 0x8CCF, 0x0004, 0x02ED, 0x0048, 0x111D, 0x0004, 0x009D, 0x0018, + 0x006F, 0x0004, 0x005A, 0x0088, 0x455D, 0x0004, 0x44CD, 0x0028, 0x1DDF, 0x0004, 0x1FFD, 0x0048, 0x003C, + 0x0004, 0x00AC, 0x0018, 0x227F, 0x0004, 0x47FD, 0x0088, 0x113D, 0x0004, 0x02BD, 0x0028, 0x22BF, 0x0004, + 0x4CDD, 0x0048, 0x22EF, 0x0004, 0x009C, 0x0018, 0x233F, 0x0006, 0x4DDD, 0x4FFB, 0xCFFF, 0x0018, 0x113D, + 0x005A, 0x888F, 0x0006, 0x23BD, 0x008A, 0x00EE, 0x002A, 0x155D, 0xAAFD, 0x277F, 0x0006, 0x44CD, 0x8FFB, + 0x44EF, 0x0018, 0x467D, 0x004A, 0x2AAF, 0x0006, 0x00AC, 0x555B, 0x99DF, 0x1FFB, 0x003C, 0x5FFD, 0x266F, + 0x0006, 0x1DDD, 0x4FFB, 0x6EFF, 0x0018, 0x177D, 0x005A, 0x1BBF, 0x0006, 0x88AD, 0x008A, 0x5DDF, 0x002A, + 0x444D, 0x2FFD, 0x667F, 0x0006, 0x00CC, 0x8FFB, 0x2EEF, 0x0018, 0x455D, 0x004A, 0x119F, 0x0006, 0x009C, + 0x555B, 0x8CCF, 0x1FFB, 0x111D, 0x8CED, 0x006E, 0x0006, 0x4DDD, 0x4FFB, 0x3FFF, 0x0018, 0x113D, 0x005A, + 0x11BF, 0x0006, 0x23BD, 0x008A, 0x8DDF, 0x002A, 0x155D, 0xAAFD, 0x222F, 0x0006, 0x44CD, 0x8FFB, 0x00FE, + 0x0018, 0x467D, 0x004A, 0x899F, 0x0006, 0x00AC, 0x555B, 0x00DE, 0x1FFB, 0x003C, 0x5FFD, 0x446F, 0x0006, + 0x1DDD, 0x4FFB, 0x9BFF, 0x0018, 0x177D, 0x005A, 0x00BE, 0x0006, 0x88AD, 0x008A, 0xCDDF, 0x002A, 0x444D, + 0x2FFD, 0x007E, 0x0006, 0x00CC, 0x8FFB, 0x4EEF, 0x0018, 0x455D, 0x004A, 0x377F, 0x0006, 0x009C, 0x555B, + 0x8BBF, 0x1FFB, 0x111D, 0x8CED, 0x233F, 0x0004, 0x00AA, 0x0088, 0x047D, 0x0004, 0x01DD, 0x0028, 0x11DF, + 0x0004, 0x27FD, 0x0048, 0x005C, 0x0004, 0x8AAD, 0x0018, 0x2BBF, 0x0004, 0x009C, 0x0088, 0x006C, 0x0004, + 0x00CC, 0x0028, 0x00EE, 0x0004, 0x8CED, 0x0048, 0x222D, 0x0004, 0x888D, 0x0018, 0x007E, 0x0004, 0x00AA, + 0x0088, 0x006D, 0x0004, 0x88CD, 0x0028, 0x00FE, 0x0004, 0x19FD, 0x0048, 0x003C, 0x0004, 0x2AAD, 0x0018, + 0xAAAF, 0x0004, 0x8BFD, 0x0088, 0x005D, 0x0004, 0x00BD, 0x0028, 0x4CCF, 0x0004, 0x44ED, 0x0048, 0x4FFF, + 0x0004, 0x223D, 0x0018, 0x111F, 0x0004, 0x00AA, 0x0088, 0x047D, 0x0004, 0x01DD, 0x0028, 0x99FF, 0x0004, + 0x27FD, 0x0048, 0x005C, 0x0004, 0x8AAD, 0x0018, 0x00BE, 0x0004, 0x009C, 0x0088, 0x006C, 0x0004, 0x00CC, + 0x0028, 0x00DE, 0x0004, 0x8CED, 0x0048, 0x222D, 0x0004, 0x888D, 0x0018, 0x444F, 0x0004, 0x00AA, 0x0088, + 0x006D, 0x0004, 0x88CD, 0x0028, 0x2EEF, 0x0004, 0x19FD, 0x0048, 0x003C, 0x0004, 0x2AAD, 0x0018, 0x447F, + 0x0004, 0x8BFD, 0x0088, 0x005D, 0x0004, 0x00BD, 0x0028, 0x009F, 0x0004, 0x44ED, 0x0048, 0x67FF, 0x0004, + 0x223D, 0x0018, 0x133F, 0x0006, 0x00CC, 0x008A, 0x9DFF, 0x2FFB, 0x467D, 0x1FFD, 0x99BF, 0x0006, 0x2AAD, + 0x002A, 0x66EF, 0x4FFB, 0x005C, 0x2EED, 0x377F, 0x0006, 0x89BD, 0x004A, 0x00FE, 0x8FFB, 0x006C, 0x67FD, + 0x889F, 0x0006, 0x888D, 0x001A, 0x5DDF, 0x00AA, 0x222D, 0x89DD, 0x444F, 0x0006, 0x2BBD, 0x008A, 0xCFFF, + 0x2FFB, 0x226D, 0x009C, 0x00BE, 0x0006, 0xAAAD, 0x002A, 0x1DDF, 0x4FFB, 0x003C, 0x4DDD, 0x466F, 0x0006, + 0x8AAD, 0x004A, 0xAEEF, 0x8FFB, 0x445D, 0x8EED, 0x177F, 0x0006, 0x233D, 0x001A, 0x4CCF, 0x00AA, 0xAFFF, + 0x88CD, 0x133F, 0x0006, 0x00CC, 0x008A, 0x77FF, 0x2FFB, 0x467D, 0x1FFD, 0x3BBF, 0x0006, 0x2AAD, 0x002A, + 0x00EE, 0x4FFB, 0x005C, 0x2EED, 0x007E, 0x0006, 0x89BD, 0x004A, 0x4EEF, 0x8FFB, 0x006C, 0x67FD, 0x667F, + 0x0006, 0x888D, 0x001A, 0x00DE, 0x00AA, 0x222D, 0x89DD, 0x333F, 0x0006, 0x2BBD, 0x008A, 0x57FF, 0x2FFB, + 0x226D, 0x009C, 0x199F, 0x0006, 0xAAAD, 0x002A, 0x99DF, 0x4FFB, 0x003C, 0x4DDD, 0x155F, 0x0006, 0x8AAD, + 0x004A, 0xCEEF, 0x8FFB, 0x445D, 0x8EED, 0x277F, 0x0006, 0x233D, 0x001A, 0x1BBF, 0x00AA, 0x3FFF, 0x88CD, + 0x111F, 0x0006, 0x45DD, 0x2FFB, 0x111D, 0x0018, 0x467D, 0x8FFD, 0xCCCF, 0x0006, 0x19BD, 0x004A, 0x22EF, + 0x002A, 0x222D, 0x3FFD, 0x888F, 0x0006, 0x00CC, 0x008A, 0x00FE, 0x0018, 0x115D, 0xCFFD, 0x8AAF, 0x0006, + 0x00AC, 0x003A, 0x8CDF, 0x1FFB, 0x133D, 0x66FD, 0x466F, 0x0006, 0x8CCD, 0x2FFB, 0x5FFF, 0x0018, 0x006C, + 0x4FFD, 0xABBF, 0x0006, 0x22AD, 0x004A, 0x00EE, 0x002A, 0x233D, 0xAEFD, 0x377F, 0x0006, 0x2BBD, 0x008A, + 0x55DF, 0x0018, 0x005C, 0x177D, 0x119F, 0x0006, 0x009C, 0x003A, 0x4CCF, 0x1FFB, 0x333D, 0x8EED, 0x444F, + 0x0006, 0x45DD, 0x2FFB, 0x111D, 0x0018, 0x467D, 0x8FFD, 0x99BF, 0x0006, 0x19BD, 0x004A, 0x2EEF, 0x002A, + 0x222D, 0x3FFD, 0x667F, 0x0006, 0x00CC, 0x008A, 0x4EEF, 0x0018, 0x115D, 0xCFFD, 0x899F, 0x0006, 0x00AC, + 0x003A, 0x00DE, 0x1FFB, 0x133D, 0x66FD, 0x226F, 0x0006, 0x8CCD, 0x2FFB, 0x9BFF, 0x0018, 0x006C, 0x4FFD, + 0x00BE, 0x0006, 0x22AD, 0x004A, 0x1DDF, 0x002A, 0x233D, 0xAEFD, 0x007E, 0x0006, 0x2BBD, 0x008A, 0xCEEF, + 0x0018, 0x005C, 0x177D, 0x277F, 0x0006, 0x009C, 0x003A, 0x8BBF, 0x1FFB, 0x333D, 0x8EED, 0x455F, 0x1FF9, + 0x1DDD, 0xAFFB, 0x00DE, 0x8FF9, 0x001C, 0xFFFB, 0x477F, 0x4FF9, 0x177D, 0x3FFB, 0x3BBF, 0x2FF9, 0xAEEF, + 0x8EED, 0x444F, 0x1FF9, 0x22AD, 0x000A, 0x8BBF, 0x8FF9, 0x00FE, 0xCFFD, 0x007E, 0x4FF9, 0x115D, 0x5FFB, + 0x577F, 0x2FF9, 0x8DDF, 0x2EED, 0x333F, 0x1FF9, 0x2BBD, 0xAFFB, 0x88CF, 0x8FF9, 0xBFFF, 0xFFFB, 0x377F, + 0x4FF9, 0x006D, 0x3FFB, 0x00BE, 0x2FF9, 0x66EF, 0x9FFD, 0x133F, 0x1FF9, 0x009D, 0x000A, 0xABBF, 0x8FF9, + 0xDFFF, 0x6FFD, 0x006E, 0x4FF9, 0x002C, 0x5FFB, 0x888F, 0x2FF9, 0xCDDF, 0x4DDD, 0x222F, 0x1FF9, 0x1DDD, + 0xAFFB, 0x4CCF, 0x8FF9, 0x001C, 0xFFFB, 0x277F, 0x4FF9, 0x177D, 0x3FFB, 0x99BF, 0x2FF9, 0xCEEF, 0x8EED, + 0x004E, 0x1FF9, 0x22AD, 0x000A, 0x00AE, 0x8FF9, 0x7FFF, 0xCFFD, 0x005E, 0x4FF9, 0x115D, 0x5FFB, 0x009E, + 0x2FF9, 0x5DDF, 0x2EED, 0x003E, 0x1FF9, 0x2BBD, 0xAFFB, 0x00CE, 0x8FF9, 0xEFFF, 0xFFFB, 0x667F, 0x4FF9, + 0x006D, 0x3FFB, 0x8AAF, 0x2FF9, 0x00EE, 0x9FFD, 0x233F, 0x1FF9, 0x009D, 0x000A, 0x1BBF, 0x8FF9, 0x4EEF, + 0x6FFD, 0x455F, 0x4FF9, 0x002C, 0x5FFB, 0x008E, 0x2FF9, 0x99DF, 0x4DDD, 0x111F}; diff --git a/libavcodec/jpeg2000htdec.h b/libavcodec/jpeg2000htdec.h new file mode 100644 index 00000000000..572d095c927 --- /dev/null +++ b/libavcodec/jpeg2000htdec.h @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2022 Caleb Etemesi + * + * 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_JPEG2000HTDEC_H +#define AVCODEC_JPEG2000HTDEC_H + +#include "jpeg2000dec.h" + +/** + * HT Block decoder as specified in Rec. ITU-T T.814 | ISO/IEC 15444-15 + */ + +int ff_jpeg2000_decode_htj2k(const Jpeg2000DecoderContext *s, Jpeg2000CodingStyle *codsty, + Jpeg2000T1Context *t1, Jpeg2000Cblk *cblk, int width, + int height, int magp, uint8_t roi_shift); + +#endif /* AVCODEC_JPEG2000HTDEC_H */ From 7ecf1bff6d216b83b8634783fb9024452b63f2d1 Mon Sep 17 00:00:00 2001 From: Pierre-Anthony Lemieux Date: Fri, 14 Apr 2023 12:14:43 -0700 Subject: [PATCH 0754/2172] fate/jpeg2000: add JPEG 2000 tests using ITU/ISO conformance materials Adds JPEG 2000 decoder tests using materials from the conformance suite specified in Rec. ITU-T T.803 | ISO/IEC 15444-4. The test materials are available at https://gitlab.com/wg1/htj2k-codestreams Signed-off-by: Pierre-Anthony Lemieux --- tests/Makefile | 1 + tests/fate/jpeg2000.mak | 64 ++++++++++++++++++++++++ tests/ref/fate/jpeg2000dec-ds0_ht_01_b11 | 6 +++ tests/ref/fate/jpeg2000dec-p0_01 | 6 +++ tests/ref/fate/jpeg2000dec-p0_02 | 6 +++ tests/ref/fate/jpeg2000dec-p0_03 | 6 +++ tests/ref/fate/jpeg2000dec-p0_04 | 6 +++ tests/ref/fate/jpeg2000dec-p0_05 | 6 +++ tests/ref/fate/jpeg2000dec-p0_07 | 6 +++ tests/ref/fate/jpeg2000dec-p0_08 | 6 +++ tests/ref/fate/jpeg2000dec-p0_09 | 6 +++ tests/ref/fate/jpeg2000dec-p0_11 | 6 +++ tests/ref/fate/jpeg2000dec-p0_12 | 6 +++ tests/ref/fate/jpeg2000dec-p0_14 | 6 +++ tests/ref/fate/jpeg2000dec-p0_15 | 6 +++ tests/ref/fate/jpeg2000dec-p0_16 | 6 +++ 16 files changed, 149 insertions(+) create mode 100644 tests/fate/jpeg2000.mak create mode 100644 tests/ref/fate/jpeg2000dec-ds0_ht_01_b11 create mode 100644 tests/ref/fate/jpeg2000dec-p0_01 create mode 100644 tests/ref/fate/jpeg2000dec-p0_02 create mode 100644 tests/ref/fate/jpeg2000dec-p0_03 create mode 100644 tests/ref/fate/jpeg2000dec-p0_04 create mode 100644 tests/ref/fate/jpeg2000dec-p0_05 create mode 100644 tests/ref/fate/jpeg2000dec-p0_07 create mode 100644 tests/ref/fate/jpeg2000dec-p0_08 create mode 100644 tests/ref/fate/jpeg2000dec-p0_09 create mode 100644 tests/ref/fate/jpeg2000dec-p0_11 create mode 100644 tests/ref/fate/jpeg2000dec-p0_12 create mode 100644 tests/ref/fate/jpeg2000dec-p0_14 create mode 100644 tests/ref/fate/jpeg2000dec-p0_15 create mode 100644 tests/ref/fate/jpeg2000dec-p0_16 diff --git a/tests/Makefile b/tests/Makefile index 1d50e1d1753..d80065a9bfa 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -200,6 +200,7 @@ include $(SRC_PATH)/tests/fate/id3v2.mak include $(SRC_PATH)/tests/fate/image.mak include $(SRC_PATH)/tests/fate/imf.mak include $(SRC_PATH)/tests/fate/indeo.mak +include $(SRC_PATH)/tests/fate/jpeg2000.mak include $(SRC_PATH)/tests/fate/libavcodec.mak include $(SRC_PATH)/tests/fate/libavdevice.mak include $(SRC_PATH)/tests/fate/libavformat.mak diff --git a/tests/fate/jpeg2000.mak b/tests/fate/jpeg2000.mak new file mode 100644 index 00000000000..b72908f7105 --- /dev/null +++ b/tests/fate/jpeg2000.mak @@ -0,0 +1,64 @@ +# The following tests are based on the conformance suite specified in +# Rec. ITU-T T.803 | ISO/IEC 15444-4 available at the following URLs: +# * https://gitlab.com/wg1/htj2k-codestreams +# * https://www.itu.int/rec/T-REC-T.803/en +# * https://www.iso.org/standard/81574.html +# +# Notes: +# * p0_06.j2k is not included because it uses a pixel format that is not +# supported (4:2:2:1) +# * p0_10.j2k is not included because errors are emitted during decoding and +# there are significant deviations from the reference image in the bottom-left +# quadrant +# * p0_13.j2k is not included because it uses a pixel format that is not +# supported (257 color channels) +# * p0_04.j2k and p0_05.j2k exceed the error thresholds specified in the +# conformance suite +# * p0_09.j2k matches the reference image exactly when bitexact is not used, but +# exceed the error thresholds specified in the conformance suite when bitexact +# is used + +FATE_JPEG2000DEC += fate-jpeg2000dec-p0_01 +fate-jpeg2000dec-p0_01: CMD = framecrc -flags +bitexact -i $(TARGET_SAMPLES)/jpeg2000/itu-iso/codestreams_profile0/p0_01.j2k + +FATE_JPEG2000DEC += fate-jpeg2000dec-p0_02 +fate-jpeg2000dec-p0_02: CMD = framecrc -flags +bitexact -i $(TARGET_SAMPLES)/jpeg2000/itu-iso/codestreams_profile0/p0_02.j2k + +FATE_JPEG2000DEC += fate-jpeg2000dec-p0_03 +fate-jpeg2000dec-p0_03: CMD = framecrc -flags +bitexact -i $(TARGET_SAMPLES)/jpeg2000/itu-iso/codestreams_profile0/p0_03.j2k + +FATE_JPEG2000DEC += fate-jpeg2000dec-p0_04 +fate-jpeg2000dec-p0_04: CMD = framecrc -flags +bitexact -i $(TARGET_SAMPLES)/jpeg2000/itu-iso/codestreams_profile0/p0_04.j2k + +FATE_JPEG2000DEC += fate-jpeg2000dec-p0_05 +fate-jpeg2000dec-p0_05: CMD = framecrc -flags +bitexact -i $(TARGET_SAMPLES)/jpeg2000/itu-iso/codestreams_profile0/p0_05.j2k + +FATE_JPEG2000DEC += fate-jpeg2000dec-p0_07 +fate-jpeg2000dec-p0_07: CMD = framecrc -flags +bitexact -auto_conversion_filters -i $(TARGET_SAMPLES)/jpeg2000/itu-iso/codestreams_profile0/p0_07.j2k -pix_fmt rgb48le + +FATE_JPEG2000DEC += fate-jpeg2000dec-p0_08 +fate-jpeg2000dec-p0_08: CMD = framecrc -flags +bitexact -auto_conversion_filters -lowres 1 -i $(TARGET_SAMPLES)/jpeg2000/itu-iso/codestreams_profile0/p0_08.j2k -pix_fmt rgb48le + +FATE_JPEG2000DEC += fate-jpeg2000dec-p0_09 +fate-jpeg2000dec-p0_09: CMD = framecrc -flags +bitexact -i $(TARGET_SAMPLES)/jpeg2000/itu-iso/codestreams_profile0/p0_09.j2k + +FATE_JPEG2000DEC += fate-jpeg2000dec-p0_11 +fate-jpeg2000dec-p0_11: CMD = framecrc -flags +bitexact -i $(TARGET_SAMPLES)/jpeg2000/itu-iso/codestreams_profile0/p0_11.j2k + +FATE_JPEG2000DEC += fate-jpeg2000dec-p0_12 +fate-jpeg2000dec-p0_12: CMD = framecrc -flags +bitexact -i $(TARGET_SAMPLES)/jpeg2000/itu-iso/codestreams_profile0/p0_12.j2k + +FATE_JPEG2000DEC += fate-jpeg2000dec-p0_14 +fate-jpeg2000dec-p0_14: CMD = framecrc -flags +bitexact -i $(TARGET_SAMPLES)/jpeg2000/itu-iso/codestreams_profile0/p0_14.j2k + +FATE_JPEG2000DEC += fate-jpeg2000dec-p0_15 +fate-jpeg2000dec-p0_15: CMD = framecrc -flags +bitexact -i $(TARGET_SAMPLES)/jpeg2000/itu-iso/codestreams_profile0/p0_15.j2k + +FATE_JPEG2000DEC += fate-jpeg2000dec-p0_16 +fate-jpeg2000dec-p0_16: CMD = framecrc -flags +bitexact -i $(TARGET_SAMPLES)/jpeg2000/itu-iso/codestreams_profile0/p0_16.j2k + +FATE_JPEG2000DEC += fate-jpeg2000dec-ds0_ht_01_b11 +fate-jpeg2000dec-ds0_ht_01_b11: CMD = framecrc -flags +bitexact -i $(TARGET_SAMPLES)/jpeg2000/itu-iso/htj2k_bsets_profile0/ds0_ht_01_b11.j2k + +FATE_SAMPLES_FFMPEG += $(FATE_JPEG2000DEC) +fate-jpeg2000dec: $(FATE_JPEG2000DEC) diff --git a/tests/ref/fate/jpeg2000dec-ds0_ht_01_b11 b/tests/ref/fate/jpeg2000dec-ds0_ht_01_b11 new file mode 100644 index 00000000000..af3eaa086d8 --- /dev/null +++ b/tests/ref/fate/jpeg2000dec-ds0_ht_01_b11 @@ -0,0 +1,6 @@ +#tb 0: 1/25 +#media_type 0: video +#codec_id 0: rawvideo +#dimensions 0: 128x128 +#sar 0: 0/1 +0, 0, 0, 1, 16384, 0x44426324 diff --git a/tests/ref/fate/jpeg2000dec-p0_01 b/tests/ref/fate/jpeg2000dec-p0_01 new file mode 100644 index 00000000000..d923cc21094 --- /dev/null +++ b/tests/ref/fate/jpeg2000dec-p0_01 @@ -0,0 +1,6 @@ +#tb 0: 1/25 +#media_type 0: video +#codec_id 0: rawvideo +#dimensions 0: 128x128 +#sar 0: 0/1 +0, 0, 0, 1, 16384, 0x04a3647e diff --git a/tests/ref/fate/jpeg2000dec-p0_02 b/tests/ref/fate/jpeg2000dec-p0_02 new file mode 100644 index 00000000000..f96d24c1213 --- /dev/null +++ b/tests/ref/fate/jpeg2000dec-p0_02 @@ -0,0 +1,6 @@ +#tb 0: 1/25 +#media_type 0: video +#codec_id 0: rawvideo +#dimensions 0: 64x126 +#sar 0: 0/1 +0, 0, 0, 1, 8064, 0xd634c70c diff --git a/tests/ref/fate/jpeg2000dec-p0_03 b/tests/ref/fate/jpeg2000dec-p0_03 new file mode 100644 index 00000000000..e508fb61e09 --- /dev/null +++ b/tests/ref/fate/jpeg2000dec-p0_03 @@ -0,0 +1,6 @@ +#tb 0: 1/25 +#media_type 0: video +#codec_id 0: rawvideo +#dimensions 0: 256x256 +#sar 0: 0/1 +0, 0, 0, 1, 65536, 0x252408c0 diff --git a/tests/ref/fate/jpeg2000dec-p0_04 b/tests/ref/fate/jpeg2000dec-p0_04 new file mode 100644 index 00000000000..5de7880c447 --- /dev/null +++ b/tests/ref/fate/jpeg2000dec-p0_04 @@ -0,0 +1,6 @@ +#tb 0: 1/25 +#media_type 0: video +#codec_id 0: rawvideo +#dimensions 0: 640x480 +#sar 0: 0/1 +0, 0, 0, 1, 921600, 0x097d9665 diff --git a/tests/ref/fate/jpeg2000dec-p0_05 b/tests/ref/fate/jpeg2000dec-p0_05 new file mode 100644 index 00000000000..bb215043a18 --- /dev/null +++ b/tests/ref/fate/jpeg2000dec-p0_05 @@ -0,0 +1,6 @@ +#tb 0: 1/25 +#media_type 0: video +#codec_id 0: rawvideo +#dimensions 0: 1024x1024 +#sar 0: 0/1 +0, 0, 0, 1, 2621440, 0x081f5048 diff --git a/tests/ref/fate/jpeg2000dec-p0_07 b/tests/ref/fate/jpeg2000dec-p0_07 new file mode 100644 index 00000000000..e561a1b780d --- /dev/null +++ b/tests/ref/fate/jpeg2000dec-p0_07 @@ -0,0 +1,6 @@ +#tb 0: 1/25 +#media_type 0: video +#codec_id 0: rawvideo +#dimensions 0: 2048x2048 +#sar 0: 0/1 +0, 0, 0, 1, 25165824, 0x9685aad6 diff --git a/tests/ref/fate/jpeg2000dec-p0_08 b/tests/ref/fate/jpeg2000dec-p0_08 new file mode 100644 index 00000000000..5e202b741ba --- /dev/null +++ b/tests/ref/fate/jpeg2000dec-p0_08 @@ -0,0 +1,6 @@ +#tb 0: 1/25 +#media_type 0: video +#codec_id 0: rawvideo +#dimensions 0: 257x1536 +#sar 0: 0/1 +0, 0, 0, 1, 2368512, 0xece49ff9 diff --git a/tests/ref/fate/jpeg2000dec-p0_09 b/tests/ref/fate/jpeg2000dec-p0_09 new file mode 100644 index 00000000000..1755e7cc7d9 --- /dev/null +++ b/tests/ref/fate/jpeg2000dec-p0_09 @@ -0,0 +1,6 @@ +#tb 0: 1/25 +#media_type 0: video +#codec_id 0: rawvideo +#dimensions 0: 17x37 +#sar 0: 0/1 +0, 0, 0, 1, 629, 0x5c9c389d diff --git a/tests/ref/fate/jpeg2000dec-p0_11 b/tests/ref/fate/jpeg2000dec-p0_11 new file mode 100644 index 00000000000..9b15604361a --- /dev/null +++ b/tests/ref/fate/jpeg2000dec-p0_11 @@ -0,0 +1,6 @@ +#tb 0: 1/25 +#media_type 0: video +#codec_id 0: rawvideo +#dimensions 0: 128x1 +#sar 0: 0/1 +0, 0, 0, 1, 128, 0xae9630db diff --git a/tests/ref/fate/jpeg2000dec-p0_12 b/tests/ref/fate/jpeg2000dec-p0_12 new file mode 100644 index 00000000000..435c124c998 --- /dev/null +++ b/tests/ref/fate/jpeg2000dec-p0_12 @@ -0,0 +1,6 @@ +#tb 0: 1/25 +#media_type 0: video +#codec_id 0: rawvideo +#dimensions 0: 3x5 +#sar 0: 0/1 +0, 0, 0, 1, 15, 0x2a170596 diff --git a/tests/ref/fate/jpeg2000dec-p0_14 b/tests/ref/fate/jpeg2000dec-p0_14 new file mode 100644 index 00000000000..5d28e611a03 --- /dev/null +++ b/tests/ref/fate/jpeg2000dec-p0_14 @@ -0,0 +1,6 @@ +#tb 0: 1/25 +#media_type 0: video +#codec_id 0: rawvideo +#dimensions 0: 49x49 +#sar 0: 0/1 +0, 0, 0, 1, 7203, 0x61d40b41 diff --git a/tests/ref/fate/jpeg2000dec-p0_15 b/tests/ref/fate/jpeg2000dec-p0_15 new file mode 100644 index 00000000000..e508fb61e09 --- /dev/null +++ b/tests/ref/fate/jpeg2000dec-p0_15 @@ -0,0 +1,6 @@ +#tb 0: 1/25 +#media_type 0: video +#codec_id 0: rawvideo +#dimensions 0: 256x256 +#sar 0: 0/1 +0, 0, 0, 1, 65536, 0x252408c0 diff --git a/tests/ref/fate/jpeg2000dec-p0_16 b/tests/ref/fate/jpeg2000dec-p0_16 new file mode 100644 index 00000000000..d923cc21094 --- /dev/null +++ b/tests/ref/fate/jpeg2000dec-p0_16 @@ -0,0 +1,6 @@ +#tb 0: 1/25 +#media_type 0: video +#codec_id 0: rawvideo +#dimensions 0: 128x128 +#sar 0: 0/1 +0, 0, 0, 1, 16384, 0x04a3647e From b56aca9b42411da444a0b267ea1dd183cbb4fbf7 Mon Sep 17 00:00:00 2001 From: Zhao Zhili Date: Sat, 22 Apr 2023 20:56:34 +0800 Subject: [PATCH 0755/2172] fftools/ffmpeg_mux: fix reporting muxer EOF as error Fix #10327. Signed-off-by: Zhao Zhili --- fftools/ffmpeg_mux.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/fftools/ffmpeg_mux.c b/fftools/ffmpeg_mux.c index a2e8873ad27..fddb783b000 100644 --- a/fftools/ffmpeg_mux.c +++ b/fftools/ffmpeg_mux.c @@ -214,9 +214,15 @@ static void *muxer_thread(void *arg) ost = of->streams[stream_idx]; ret = sync_queue_process(mux, ost, ret < 0 ? NULL : pkt, &stream_eof); av_packet_unref(pkt); - if (ret == AVERROR_EOF && stream_eof) - tq_receive_finish(mux->tq, stream_idx); - else if (ret < 0) { + if (ret == AVERROR_EOF) { + if (stream_eof) { + tq_receive_finish(mux->tq, stream_idx); + } else { + av_log(mux, AV_LOG_VERBOSE, "Muxer returned EOF\n"); + ret = 0; + break; + } + } else if (ret < 0) { av_log(mux, AV_LOG_ERROR, "Error muxing a packet\n"); break; } From 4dd3f2098c2f66f00db9c284b3e04240012944f5 Mon Sep 17 00:00:00 2001 From: Thilo Borgmann Date: Fri, 31 Mar 2023 17:23:41 +0200 Subject: [PATCH 0756/2172] doc/developer: mention samples-request for FATE upload requests --- doc/developer.texi | 2 ++ 1 file changed, 2 insertions(+) diff --git a/doc/developer.texi b/doc/developer.texi index c625a9feed7..a7da2ce2d5d 100644 --- a/doc/developer.texi +++ b/doc/developer.texi @@ -864,6 +864,8 @@ accordingly]. @section Adding files to the fate-suite dataset +If you need a sample uploaded send a mail to samples-request. + When there is no muxer or encoder available to generate test media for a specific test then the media has to be included in the fate-suite. First please make sure that the sample file is as small as possible to test the From ef338cfd7b435703cf56ed5e6527b8f1953f90f1 Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Sun, 23 Apr 2023 23:30:42 +0200 Subject: [PATCH 0757/2172] avfilter/af_afir: fix IR switching with different lengths --- libavfilter/af_afir.c | 76 +++++++++++++---------- libavfilter/af_afir.h | 9 +-- libavfilter/afir_template.c | 116 +++++++++--------------------------- 3 files changed, 79 insertions(+), 122 deletions(-) diff --git a/libavfilter/af_afir.c b/libavfilter/af_afir.c index 0fe038972f0..fab751cb9fb 100644 --- a/libavfilter/af_afir.c +++ b/libavfilter/af_afir.c @@ -106,14 +106,20 @@ static int fir_channel(AVFilterContext *ctx, AVFrame *out, int ch) { AudioFIRContext *s = ctx->priv; const int min_part_size = s->min_part_size; + const int prev_selir = s->prev_selir; + const int selir = s->selir; for (int offset = 0; offset < out->nb_samples; offset += min_part_size) { switch (s->format) { case AV_SAMPLE_FMT_FLTP: - fir_quantum_float(ctx, out, ch, offset); + if (prev_selir != selir) + fir_quantum_float(ctx, out, ch, offset, prev_selir); + fir_quantum_float(ctx, out, ch, offset, selir); break; case AV_SAMPLE_FMT_DBLP: - fir_quantum_double(ctx, out, ch, offset); + if (prev_selir != selir) + fir_quantum_double(ctx, out, ch, offset, prev_selir); + fir_quantum_double(ctx, out, ch, offset, selir); break; } } @@ -179,10 +185,9 @@ static int init_segment(AVFilterContext *ctx, AudioFIRSegment *seg, int selir, seg->input_size = offset + s->min_part_size; seg->input_offset = offset; - seg->loading = av_calloc(ctx->inputs[0]->ch_layout.nb_channels, sizeof(*seg->loading)); seg->part_index = av_calloc(ctx->inputs[0]->ch_layout.nb_channels, sizeof(*seg->part_index)); seg->output_offset = av_calloc(ctx->inputs[0]->ch_layout.nb_channels, sizeof(*seg->output_offset)); - if (!seg->part_index || !seg->output_offset || !seg->loading) + if (!seg->part_index || !seg->output_offset) return AVERROR(ENOMEM); switch (s->format) { @@ -253,7 +258,6 @@ static void uninit_segment(AVFilterContext *ctx, AudioFIRSegment *seg) } av_freep(&seg->itx); - av_freep(&seg->loading); av_freep(&seg->output_offset); av_freep(&seg->part_index); @@ -268,7 +272,7 @@ static void uninit_segment(AVFilterContext *ctx, AudioFIRSegment *seg) seg->input_size = 0; for (int i = 0; i < MAX_IR_STREAMS; i++) - av_frame_free(&seg->coeff[i]); + av_frame_free(&seg->coeff); } static int convert_coeffs(AVFilterContext *ctx, int selir) @@ -287,7 +291,7 @@ static int convert_coeffs(AVFilterContext *ctx, int selir) if (s->minp > s->maxp) s->maxp = s->minp; - if (s->nb_segments) + if (s->nb_segments[selir]) goto skip; left = s->nb_taps[selir]; @@ -300,8 +304,8 @@ static int convert_coeffs(AVFilterContext *ctx, int selir) int step = part_size == max_part_size ? INT_MAX : 1 + (i == 0); int nb_partitions = FFMIN(step, (left + part_size - 1) / part_size); - s->nb_segments = i + 1; - ret = init_segment(ctx, &s->seg[i], selir, offset, nb_partitions, part_size, i); + s->nb_segments[selir] = i + 1; + ret = init_segment(ctx, &s->seg[selir][i], selir, offset, nb_partitions, part_size, i); if (ret < 0) return ret; offset += nb_partitions * part_size; @@ -309,6 +313,8 @@ static int convert_coeffs(AVFilterContext *ctx, int selir) part_size *= 2; part_size = FFMIN(part_size, max_part_size); } + + s->max_offset[selir] = offset; } skip: @@ -342,7 +348,7 @@ static int convert_coeffs(AVFilterContext *ctx, int selir) } av_log(ctx, AV_LOG_DEBUG, "nb_taps: %d\n", cur_nb_taps); - av_log(ctx, AV_LOG_DEBUG, "nb_segments: %d\n", s->nb_segments); + av_log(ctx, AV_LOG_DEBUG, "nb_segments: %d\n", s->nb_segments[selir]); switch (s->format) { case AV_SAMPLE_FMT_FLTP: @@ -356,12 +362,12 @@ static int convert_coeffs(AVFilterContext *ctx, int selir) get_power_float(ctx, s, nb_taps, ch, time); - for (int n = 0; n < s->nb_segments; n++) { - AudioFIRSegment *seg = &s->seg[n]; + for (int n = 0; n < s->nb_segments[selir]; n++) { + AudioFIRSegment *seg = &s->seg[selir][n]; - if (!seg->coeff[selir]) - seg->coeff[selir] = ff_get_audio_buffer(ctx->inputs[0], seg->nb_partitions * seg->coeff_size * 2); - if (!seg->coeff[selir]) + if (!seg->coeff) + seg->coeff = ff_get_audio_buffer(ctx->inputs[0], seg->nb_partitions * seg->coeff_size * 2); + if (!seg->coeff) return AVERROR(ENOMEM); for (int i = 0; i < seg->nb_partitions; i++) @@ -379,12 +385,12 @@ static int convert_coeffs(AVFilterContext *ctx, int selir) time[i] = 0; get_power_double(ctx, s, nb_taps, ch, time); - for (int n = 0; n < s->nb_segments; n++) { - AudioFIRSegment *seg = &s->seg[n]; + for (int n = 0; n < s->nb_segments[selir]; n++) { + AudioFIRSegment *seg = &s->seg[selir][n]; - if (!seg->coeff[selir]) - seg->coeff[selir] = ff_get_audio_buffer(ctx->inputs[0], seg->nb_partitions * seg->coeff_size * 2); - if (!seg->coeff[selir]) + if (!seg->coeff) + seg->coeff = ff_get_audio_buffer(ctx->inputs[0], seg->nb_partitions * seg->coeff_size * 2); + if (!seg->coeff) return AVERROR(ENOMEM); for (int i = 0; i < seg->nb_partitions; i++) @@ -449,12 +455,23 @@ static int activate(AVFilterContext *ctx) return ret; } + if (s->selir != s->prev_selir && s->loading[0] <= 0) { + for (int ch = 0; ch < s->nb_channels; ch++) + s->loading[ch] = s->max_offset[s->selir] + s->min_part_size; + } + available = ff_inlink_queued_samples(ctx->inputs[0]); wanted = FFMAX(s->min_part_size, (available / s->min_part_size) * s->min_part_size); ret = ff_inlink_consume_samples(ctx->inputs[0], wanted, wanted, &in); if (ret > 0) ret = fir_frame(s, in, outlink); + if (s->selir != s->prev_selir && s->loading[0] <= 0) { + s->prev_selir = s->selir; + for (int ch = 0; ch < s->nb_channels; ch++) + s->loading[ch] = 0; + } + if (ret < 0) return ret; @@ -571,6 +588,9 @@ FF_ENABLE_DEPRECATION_WARNINGS s->format = outlink->format; s->nb_channels = outlink->ch_layout.nb_channels; + s->loading = av_calloc(ctx->inputs[0]->ch_layout.nb_channels, sizeof(*s->loading)); + if (!s->loading) + return AVERROR(ENOMEM); return 0; } @@ -579,12 +599,13 @@ static av_cold void uninit(AVFilterContext *ctx) { AudioFIRContext *s = ctx->priv; - for (int i = 0; i < s->nb_segments; i++) - uninit_segment(ctx, &s->seg[i]); - av_freep(&s->fdsp); + av_freep(&s->loading); for (int i = 0; i < s->nb_irs; i++) { + for (int j = 0; j < s->nb_segments[i]; j++) + uninit_segment(ctx, &s->seg[i][j]); + av_frame_free(&s->ir[i]); av_frame_free(&s->norm_ir[i]); } @@ -689,15 +710,8 @@ static int process_command(AVFilterContext *ctx, return ret; s->selir = FFMIN(s->nb_irs - 1, s->selir); - if (s->selir != prev_selir) { + if (s->selir != prev_selir) s->prev_selir = prev_selir; - for (int n = 0; n < s->nb_segments; n++) { - AudioFIRSegment *seg = &s->seg[n]; - - for (int ch = 0; ch < s->nb_channels; ch++) - seg->loading[ch] = 0; - } - } return 0; } diff --git a/libavfilter/af_afir.h b/libavfilter/af_afir.h index a9f6d217f41..11564d5b122 100644 --- a/libavfilter/af_afir.h +++ b/libavfilter/af_afir.h @@ -39,7 +39,6 @@ typedef struct AudioFIRSegment { int input_size; int input_offset; - int *loading; int *output_offset; int *part_index; @@ -49,7 +48,7 @@ typedef struct AudioFIRSegment { AVFrame *tempin; AVFrame *tempout; AVFrame *buffer; - AVFrame *coeff[MAX_IR_STREAMS]; + AVFrame *coeff; AVFrame *input; AVFrame *output; @@ -82,11 +81,13 @@ typedef struct AudioFIRContext { int eof_coeffs[MAX_IR_STREAMS]; int have_coeffs[MAX_IR_STREAMS]; int nb_taps[MAX_IR_STREAMS]; + int nb_segments[MAX_IR_STREAMS]; + int max_offset[MAX_IR_STREAMS]; int nb_channels; int one2many; + int *loading; - AudioFIRSegment seg[1024]; - int nb_segments; + AudioFIRSegment seg[MAX_IR_STREAMS][1024]; AVFrame *in; AVFrame *ir[MAX_IR_STREAMS]; diff --git a/libavfilter/afir_template.c b/libavfilter/afir_template.c index 3f3778c6756..63d95de9004 100644 --- a/libavfilter/afir_template.c +++ b/libavfilter/afir_template.c @@ -251,7 +251,7 @@ static void fn(convert_channel)(AVFilterContext *ctx, AudioFIRContext *s, int ch ftype *time = (ftype *)s->norm_ir[selir]->extended_data[ch]; ftype *tempin = (ftype *)seg->tempin->extended_data[ch]; ftype *tempout = (ftype *)seg->tempout->extended_data[ch]; - ctype *coeff = (ctype *)seg->coeff[selir]->extended_data[ch]; + ctype *coeff = (ctype *)seg->coeff->extended_data[ch]; const int remaining = nb_taps - (seg->input_offset + coeff_partition * seg->part_size); const int size = remaining >= seg->part_size ? seg->part_size : remaining; @@ -285,19 +285,18 @@ static void fn(fir_fadd)(AudioFIRContext *s, ftype *dst, const ftype *src, int n } } -static int fn(fir_quantum)(AVFilterContext *ctx, AVFrame *out, int ch, int offset) +static int fn(fir_quantum)(AVFilterContext *ctx, AVFrame *out, int ch, int offset, int selir) { AudioFIRContext *s = ctx->priv; const ftype *in = (const ftype *)s->in->extended_data[ch] + offset; ftype *blockout, *ptr = (ftype *)out->extended_data[ch] + offset; const int min_part_size = s->min_part_size; const int nb_samples = FFMIN(min_part_size, out->nb_samples - offset); - const int nb_segments = s->nb_segments; + const int nb_segments = s->nb_segments[selir]; const float dry_gain = s->dry_gain; - const int selir = s->selir; for (int segment = 0; segment < nb_segments; segment++) { - AudioFIRSegment *seg = &s->seg[segment]; + AudioFIRSegment *seg = &s->seg[selir][segment]; ftype *src = (ftype *)seg->input->extended_data[ch]; ftype *dst = (ftype *)seg->output->extended_data[ch]; ftype *sumin = (ftype *)seg->sumin->extended_data[ch]; @@ -337,70 +336,18 @@ static int fn(fir_quantum)(AVFilterContext *ctx, AVFrame *out, int ch, int offse memset(sumin, 0, sizeof(*sumin) * seg->fft_length); - if (seg->loading[ch] < nb_partitions) { - j = seg->part_index[ch] <= 0 ? nb_partitions - 1 : seg->part_index[ch] - 1; - for (int i = 0; i < nb_partitions; i++) { - const int input_partition = j; - const int coeff_partition = i; - const int coffset = coeff_partition * seg->coeff_size; - const ftype *blockout = (const ftype *)seg->blockout->extended_data[ch] + input_partition * seg->block_size; - const ctype *coeff = ((const ctype *)seg->coeff[selir]->extended_data[ch]) + coffset; - - if (j == 0) - j = nb_partitions; - j--; - -#if DEPTH == 32 - s->afirdsp.fcmul_add(sumin, blockout, (const ftype *)coeff, part_size); -#else - s->afirdsp.dcmul_add(sumin, blockout, (const ftype *)coeff, part_size); -#endif - } - - seg->itx_fn(seg->itx[ch], sumout, sumin, sizeof(ctype)); - memcpy(dst + part_size, sumout + part_size, part_size * sizeof(*buf)); - memset(sumin, 0, sizeof(*sumin) * seg->fft_length); - } - blockout = (ftype *)seg->blockout->extended_data[ch] + seg->part_index[ch] * seg->block_size; memset(tempin + part_size, 0, sizeof(*tempin) * (seg->block_size - part_size)); memcpy(tempin, src, sizeof(*src) * part_size); seg->tx_fn(seg->tx[ch], blockout, tempin, sizeof(ftype)); - if (seg->loading[ch] < nb_partitions) { - const int selir = s->prev_selir; - - j = seg->part_index[ch]; - for (int i = 0; i < nb_partitions; i++) { - const int input_partition = j; - const int coeff_partition = i; - const int coffset = coeff_partition * seg->coeff_size; - const ftype *blockout = (const ftype *)seg->blockout->extended_data[ch] + input_partition * seg->block_size; - const ctype *coeff = ((const ctype *)seg->coeff[selir]->extended_data[ch]) + coffset; - - if (j == 0) - j = nb_partitions; - j--; - -#if DEPTH == 32 - s->afirdsp.fcmul_add(sumin, blockout, (const ftype *)coeff, part_size); -#else - s->afirdsp.dcmul_add(sumin, blockout, (const ftype *)coeff, part_size); -#endif - } - - seg->itx_fn(seg->itx[ch], sumout, sumin, sizeof(ctype)); - memcpy(dst + 2 * part_size, sumout, 2 * part_size * sizeof(*dst)); - memset(sumin, 0, sizeof(*sumin) * seg->fft_length); - } - j = seg->part_index[ch]; for (int i = 0; i < nb_partitions; i++) { const int input_partition = j; const int coeff_partition = i; const int coffset = coeff_partition * seg->coeff_size; const ftype *blockout = (const ftype *)seg->blockout->extended_data[ch] + input_partition * seg->block_size; - const ctype *coeff = ((const ctype *)seg->coeff[selir]->extended_data[ch]) + coffset; + const ctype *coeff = ((const ctype *)seg->coeff->extended_data[ch]) + coffset; if (j == 0) j = nb_partitions; @@ -415,45 +362,40 @@ static int fn(fir_quantum)(AVFilterContext *ctx, AVFrame *out, int ch, int offse seg->itx_fn(seg->itx[ch], sumout, sumin, sizeof(ctype)); - if (seg->loading[ch] < nb_partitions) { - ftype *ptr1 = dst + part_size; - ftype *ptr2 = dst + part_size * 2; - ftype *ptr3 = dst + part_size * 3; - ftype *ptr4 = dst + part_size * 4; - if (seg->loading[ch] == 0) - memcpy(ptr4, buf, sizeof(*ptr4) * part_size); - for (int n = 0; n < part_size; n++) - ptr2[n] += ptr4[n]; - - if (seg->loading[ch] < nb_partitions - 1) - memcpy(ptr4, ptr3, part_size * sizeof(*dst)); - for (int n = 0; n < part_size; n++) - ptr1[n] += sumout[n]; - - if (seg->loading[ch] == nb_partitions - 1) - memcpy(buf, sumout + part_size, part_size * sizeof(*buf)); - - for (int i = 0; i < part_size; i++) { - const ftype factor = (part_size * seg->loading[ch] + i) / (ftype)(part_size * nb_partitions); - const ftype ifactor = 1 - factor; - dst[i] = ptr1[i] * factor + ptr2[i] * ifactor; + fn(fir_fadd)(s, buf, sumout, part_size); + memcpy(dst, buf, part_size * sizeof(*dst)); + memcpy(buf, sumout + part_size, part_size * sizeof(*buf)); + + if (s->selir != s->prev_selir) { + if (selir == s->selir) { + if (s->loading[ch] <= min_part_size) { + for (int n = 0; n < nb_samples; n++) + ptr[n] += dst[n] * ((n + 1.f) / nb_samples); + } + } else { + fn(fir_fadd)(s, ptr, dst, nb_samples); } } else { - fn(fir_fadd)(s, buf, sumout, part_size); - memcpy(dst, buf, part_size * sizeof(*dst)); - memcpy(buf, sumout + part_size, part_size * sizeof(*buf)); + fn(fir_fadd)(s, ptr, dst, nb_samples); } - fn(fir_fadd)(s, ptr, dst, nb_samples); - if (part_size != min_part_size) memmove(src, src + min_part_size, (seg->input_size - min_part_size) * sizeof(*src)); seg->part_index[ch] = (seg->part_index[ch] + 1) % nb_partitions; - if (seg->loading[ch] < nb_partitions) - seg->loading[ch]++; } + if (selir != s->selir) { + if (s->loading[ch] <= min_part_size) { + for (int n = 0; n < nb_samples; n++) + ptr[n] *= (nb_samples - n * 1.f) / nb_samples; + } + return 0; + } + + if (s->selir != s->prev_selir) + s->loading[ch] -= min_part_size; + if (s->wet_gain == 1.f) return 0; From 9a258eefaee176b0342db00450c3bfa997e49da1 Mon Sep 17 00:00:00 2001 From: James Almer Date: Sun, 23 Apr 2023 09:48:36 -0300 Subject: [PATCH 0758/2172] fate/jpeg2000: add missing dependecy checks Signed-off-by: James Almer --- tests/fate/jpeg2000.mak | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/tests/fate/jpeg2000.mak b/tests/fate/jpeg2000.mak index b72908f7105..2969d2cf0a9 100644 --- a/tests/fate/jpeg2000.mak +++ b/tests/fate/jpeg2000.mak @@ -33,10 +33,10 @@ fate-jpeg2000dec-p0_04: CMD = framecrc -flags +bitexact -i $(TARGET_SAMPLES)/jpe FATE_JPEG2000DEC += fate-jpeg2000dec-p0_05 fate-jpeg2000dec-p0_05: CMD = framecrc -flags +bitexact -i $(TARGET_SAMPLES)/jpeg2000/itu-iso/codestreams_profile0/p0_05.j2k -FATE_JPEG2000DEC += fate-jpeg2000dec-p0_07 +FATE_JPEG2000DEC-$(CONFIG_SCALE_FILTER) += fate-jpeg2000dec-p0_07 fate-jpeg2000dec-p0_07: CMD = framecrc -flags +bitexact -auto_conversion_filters -i $(TARGET_SAMPLES)/jpeg2000/itu-iso/codestreams_profile0/p0_07.j2k -pix_fmt rgb48le -FATE_JPEG2000DEC += fate-jpeg2000dec-p0_08 +FATE_JPEG2000DEC-$(CONFIG_SCALE_FILTER) += fate-jpeg2000dec-p0_08 fate-jpeg2000dec-p0_08: CMD = framecrc -flags +bitexact -auto_conversion_filters -lowres 1 -i $(TARGET_SAMPLES)/jpeg2000/itu-iso/codestreams_profile0/p0_08.j2k -pix_fmt rgb48le FATE_JPEG2000DEC += fate-jpeg2000dec-p0_09 @@ -60,5 +60,7 @@ fate-jpeg2000dec-p0_16: CMD = framecrc -flags +bitexact -i $(TARGET_SAMPLES)/jpe FATE_JPEG2000DEC += fate-jpeg2000dec-ds0_ht_01_b11 fate-jpeg2000dec-ds0_ht_01_b11: CMD = framecrc -flags +bitexact -i $(TARGET_SAMPLES)/jpeg2000/itu-iso/htj2k_bsets_profile0/ds0_ht_01_b11.j2k -FATE_SAMPLES_FFMPEG += $(FATE_JPEG2000DEC) +FATE_JPEG2000DEC += $(FATE_JPEG2000DEC-yes) + +FATE_SAMPLES_FFMPEG-$(call FRAMECRC, IMAGE_J2K_PIPE, JPEG2000) += $(FATE_JPEG2000DEC) fate-jpeg2000dec: $(FATE_JPEG2000DEC) From 734a61d282b9cfc89a1e4e7bb174d80f4cce3d88 Mon Sep 17 00:00:00 2001 From: Wang Yaqiang Date: Mon, 10 Apr 2023 20:43:26 +0800 Subject: [PATCH 0759/2172] avformat/movenc: fixed fmp4 packets containing incorrect flags after transcoding When write multi-trun box, the MOV_TRUN_FIRST_SAMPLE_FLAGS flag need judge by first param, not 0. If the original video contains consecutive I frames, this will cause the packets of fmp4 have error sample_flags , and then incorrect keyframes were generated, and then error packet will be seeked. Signed-off-by: Wang Yaqiang Signed-off-by: Steven Liu --- libavformat/movenc.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libavformat/movenc.c b/libavformat/movenc.c index c370922c7d8..946e79c5ac8 100644 --- a/libavformat/movenc.c +++ b/libavformat/movenc.c @@ -4858,8 +4858,8 @@ static int mov_write_trun_tag(AVIOContext *pb, MOVMuxContext *mov, if (i > first && get_sample_flags(track, &track->cluster[i]) != track->default_sample_flags) flags |= MOV_TRUN_SAMPLE_FLAGS; } - if (!(flags & MOV_TRUN_SAMPLE_FLAGS) && track->entry > 0 && - get_sample_flags(track, &track->cluster[0]) != track->default_sample_flags) + if (!(flags & MOV_TRUN_SAMPLE_FLAGS) && track->entry > first && + get_sample_flags(track, &track->cluster[first]) != track->default_sample_flags) flags |= MOV_TRUN_FIRST_SAMPLE_FLAGS; if (track->flags & MOV_TRACK_CTTS) flags |= MOV_TRUN_SAMPLE_CTS; From d54127c41a81cf2078a3504f78e0e4232cfe11b7 Mon Sep 17 00:00:00 2001 From: Sil Vilerino Date: Fri, 14 Apr 2023 10:39:04 -0400 Subject: [PATCH 0760/2172] lavu/hwcontext_vaapi: Add Windows/VAAPI support with vaGetDisplayWin32 Libva 2.17+ adds a new libva-win32 node and Mesa 22.3 adds a VAAPI driver based on Direct3D 12 for Windows. Both of them are available at: https://www.nuget.org/packages/Microsoft.Direct3D.VideoAccelerationCompatibilityPack Initial review at https://github.com/intel-media-ci/ffmpeg/pull/619/ Signed-off-by: Sil Vilerino Reviewed-by: Dmitry Rogozhkin Reviewed-by: Wu, Tong1 --- Changelog | 1 + configure | 27 ++++++++++++- libavutil/hwcontext_vaapi.c | 78 ++++++++++++++++++++++++++++++++++++- libavutil/tests/hwdevice.c | 2 +- 4 files changed, 103 insertions(+), 5 deletions(-) diff --git a/Changelog b/Changelog index 4284a250a22..8268e42cbcc 100644 --- a/Changelog +++ b/Changelog @@ -4,6 +4,7 @@ releases are sorted from youngest to oldest. version : - libaribcaption decoder - Playdate video decoder and demuxer +- Extend VAAPI support for libva-win32 on Windows version 6.0: - Radiance HDR image support diff --git a/configure b/configure index 549ed1401c3..bb7be676763 100755 --- a/configure +++ b/configure @@ -2316,6 +2316,7 @@ SYSTEM_LIBRARIES=" bcrypt vaapi_drm vaapi_x11 + vaapi_win32 vdpau_x11 " @@ -3827,7 +3828,7 @@ swscale_suggest="libm stdatomic" avcodec_extralibs="pthreads_extralibs iconv_extralibs dxva2_extralibs lcms2_extralibs" avfilter_extralibs="pthreads_extralibs" -avutil_extralibs="d3d11va_extralibs mediacodec_extralibs nanosleep_extralibs pthreads_extralibs vaapi_drm_extralibs vaapi_x11_extralibs vdpau_x11_extralibs" +avutil_extralibs="d3d11va_extralibs mediacodec_extralibs nanosleep_extralibs pthreads_extralibs vaapi_drm_extralibs vaapi_x11_extralibs vaapi_win32_extralibs vdpau_x11_extralibs" # programs ffmpeg_deps="avcodec avfilter avformat threads" @@ -6948,6 +6949,21 @@ test_cpp < +#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) +#error desktop, not uwp +#else +// WINAPI_FAMILY_APP, WINAPI_FAMILY_PHONE_APP => UWP +#endif +#else +#error no family set +#endif +EOF + # mediafoundation requires linking directly to mfplat if building for uwp target enabled uwp && mediafoundation_extralibs="-lmfplat -lmfuuid -lole32 -lstrmiids" || mediafoundation_extralibs="-lmfuuid -lole32 -lstrmiids" @@ -6958,7 +6974,14 @@ enabled vaapi && check_pkg_config vaapi "libva >= 0.35.0" "va/va.h" vaInitialize if enabled vaapi; then - check_pkg_config vaapi_drm "libva-drm" "va/va_drm.h" vaGetDisplayDRM + case $target_os in + mingw32*|mingw64*|win32|win64) + check_pkg_config vaapi_win32 "libva-win32" "va/va_win32.h" vaGetDisplayWin32 + ;; + *) + check_pkg_config vaapi_drm "libva-drm" "va/va_drm.h" vaGetDisplayDRM + ;; + esac if enabled xlib_x11; then check_pkg_config vaapi_x11 "libva-x11" "va/va_x11.h" vaGetDisplay diff --git a/libavutil/hwcontext_vaapi.c b/libavutil/hwcontext_vaapi.c index 90c2c191d90..6c3a227ddd0 100644 --- a/libavutil/hwcontext_vaapi.c +++ b/libavutil/hwcontext_vaapi.c @@ -18,6 +18,15 @@ #include "config.h" +#if HAVE_VAAPI_WIN32 +# include +#define COBJMACROS +# include +# include +# include "compat/w32dlfcn.h" +# include +typedef HRESULT (WINAPI *PFN_CREATE_DXGI_FACTORY)(REFIID riid, void **ppFactory); +#endif #if HAVE_VAAPI_X11 # include #endif @@ -1663,7 +1672,7 @@ static int vaapi_device_create(AVHWDeviceContext *ctx, const char *device, VAAPIDevicePriv *priv; VADisplay display = NULL; const AVDictionaryEntry *ent; - int try_drm, try_x11, try_all; + int try_drm, try_x11, try_win32, try_all; priv = av_mallocz(sizeof(*priv)); if (!priv) @@ -1676,11 +1685,13 @@ static int vaapi_device_create(AVHWDeviceContext *ctx, const char *device, ent = av_dict_get(opts, "connection_type", NULL, 0); if (ent) { - try_all = try_drm = try_x11 = 0; + try_all = try_drm = try_x11 = try_win32 = 0; if (!strcmp(ent->value, "drm")) { try_drm = 1; } else if (!strcmp(ent->value, "x11")) { try_x11 = 1; + } else if (!strcmp(ent->value, "win32")) { + try_win32 = 1; } else { av_log(ctx, AV_LOG_ERROR, "Invalid connection type %s.\n", ent->value); @@ -1690,6 +1701,7 @@ static int vaapi_device_create(AVHWDeviceContext *ctx, const char *device, try_all = 1; try_drm = HAVE_VAAPI_DRM; try_x11 = HAVE_VAAPI_X11; + try_win32 = HAVE_VAAPI_WIN32; } #if HAVE_VAAPI_DRM @@ -1797,6 +1809,68 @@ static int vaapi_device_create(AVHWDeviceContext *ctx, const char *device, } #endif +#if HAVE_VAAPI_WIN32 + if (!display && try_win32) { + // Try to create a display from the specified device, if any. + if (!device) { + display = vaGetDisplayWin32(NULL); + } else { + IDXGIFactory2 *pDXGIFactory = NULL; + IDXGIAdapter *pAdapter = NULL; +#if !HAVE_UWP + HANDLE dxgi = dlopen("dxgi.dll", 0); + if (!dxgi) { + av_log(ctx, AV_LOG_ERROR, "Failed to load dxgi.dll\n"); + return AVERROR_UNKNOWN; + } + PFN_CREATE_DXGI_FACTORY pfnCreateDXGIFactory = + (PFN_CREATE_DXGI_FACTORY)dlsym(dxgi, "CreateDXGIFactory"); + if (!pfnCreateDXGIFactory) { + av_log(ctx, AV_LOG_ERROR, "CreateDXGIFactory load failed\n"); + dlclose(dxgi); + return AVERROR_UNKNOWN; + } +#else + // In UWP (which lacks LoadLibrary), CreateDXGIFactory isn't + // available, only CreateDXGIFactory1 + PFN_CREATE_DXGI_FACTORY pfnCreateDXGIFactory = + (PFN_CREATE_DXGI_FACTORY)CreateDXGIFactory1; +#endif + if (SUCCEEDED(pfnCreateDXGIFactory(&IID_IDXGIFactory2, + (void **)&pDXGIFactory))) { + int adapter = atoi(device); + if (SUCCEEDED(IDXGIFactory2_EnumAdapters(pDXGIFactory, + adapter, + &pAdapter))) { + DXGI_ADAPTER_DESC desc; + if (SUCCEEDED(IDXGIAdapter2_GetDesc(pAdapter, &desc))) { + av_log(ctx, AV_LOG_INFO, + "Using device %04x:%04x (%ls) - LUID %lu %ld.\n", + desc.VendorId, desc.DeviceId, desc.Description, + desc.AdapterLuid.LowPart, + desc.AdapterLuid.HighPart); + display = vaGetDisplayWin32(&desc.AdapterLuid); + } + IDXGIAdapter_Release(pAdapter); + } + IDXGIFactory2_Release(pDXGIFactory); + } +#if !HAVE_UWP + dlclose(dxgi); +#endif + } + + if (!display) { + av_log(ctx, AV_LOG_ERROR, "Cannot open a VA display " + "from Win32 display.\n"); + return AVERROR_UNKNOWN; + } + + av_log(ctx, AV_LOG_VERBOSE, "Opened VA display via " + "Win32 display.\n"); + } +#endif + if (!display) { if (device) av_log(ctx, AV_LOG_ERROR, "No VA display found for " diff --git a/libavutil/tests/hwdevice.c b/libavutil/tests/hwdevice.c index 7eb355c9882..c57586613ac 100644 --- a/libavutil/tests/hwdevice.c +++ b/libavutil/tests/hwdevice.c @@ -140,7 +140,7 @@ static const struct { { AV_HWDEVICE_TYPE_OPENCL, { "0.0", "0.1", "1.0", "1.1" } }, { AV_HWDEVICE_TYPE_VAAPI, - { "/dev/dri/renderD128", "/dev/dri/renderD129", ":0" } }, + { "/dev/dri/renderD128", "/dev/dri/renderD129", ":0", "0", "1" } }, }; static int test_device_type(enum AVHWDeviceType type) From 5ff14304524f508c429eac8322f0d70458ecd04c Mon Sep 17 00:00:00 2001 From: Sil Vilerino Date: Fri, 14 Apr 2023 10:39:05 -0400 Subject: [PATCH 0761/2172] fftools/ffmpeg_opt: Document VAAPI -device usage for DirectX Adapter Initial review at https://github.com/intel-media-ci/ffmpeg/pull/619/ Signed-off-by: Sil Vilerino Reviewed-by: Dmitry Rogozhkin Reviewed-by: Wu, Tong1 --- doc/ffmpeg.texi | 5 +++-- fftools/ffmpeg_opt.c | 2 +- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/doc/ffmpeg.texi b/doc/ffmpeg.texi index cb8aa13df27..34c413355ed 100644 --- a/doc/ffmpeg.texi +++ b/doc/ffmpeg.texi @@ -1169,9 +1169,10 @@ Choose the first device and use the primary device context. @var{device} is the number of the Direct3D 11 display adapter. @item vaapi -@var{device} is either an X11 display name or a DRM render node. +@var{device} is either an X11 display name, a DRM render node or a DirectX adapter index. If not specified, it will attempt to open the default X11 display (@emph{$DISPLAY}) -and then the first DRM render node (@emph{/dev/dri/renderD128}). +and then the first DRM render node (@emph{/dev/dri/renderD128}), or the default +DirectX adapter on Windows. @item vdpau @var{device} is an X11 display name. diff --git a/fftools/ffmpeg_opt.c b/fftools/ffmpeg_opt.c index aa9aa0e9b45..f811d38b9c8 100644 --- a/fftools/ffmpeg_opt.c +++ b/fftools/ffmpeg_opt.c @@ -1767,7 +1767,7 @@ const OptionDef options[] = { #if CONFIG_VAAPI { "vaapi_device", HAS_ARG | OPT_EXPERT, { .func_arg = opt_vaapi_device }, - "set VAAPI hardware device (DRM path or X11 display name)", "device" }, + "set VAAPI hardware device (DirectX adapter index, DRM path or X11 display name)", "device" }, #endif #if CONFIG_QSV From a9a2ddaea8318cec43ca916b6b8350f0cf14411d Mon Sep 17 00:00:00 2001 From: Sil Vilerino Date: Fri, 14 Apr 2023 10:39:06 -0400 Subject: [PATCH 0762/2172] lavu/hwcontext_qsv: Update after adding support for VAAPI on Windows - qsv_internal.h: Remove unnecessary include va_drm.h - qsv_internal.h: Enable AVCODEC_QSV_LINUX_SESSION_HANDLE on Linux/VA only - hwcontext_qsv.c: Do not allow child_device_type VAAPI for Windows until support is added, keep D3D11/DXVA2 as more prioritary defaults. Initial review at https://github.com/intel-media-ci/ffmpeg/pull/619/ Signed-off-by: Sil Vilerino Reviewed-by: Dmitry Rogozhkin Reviewed-by: Wu, Tong1 --- libavcodec/qsv_internal.h | 5 ++--- libavutil/hwcontext_qsv.c | 14 ++++++++++++-- 2 files changed, 14 insertions(+), 5 deletions(-) diff --git a/libavcodec/qsv_internal.h b/libavcodec/qsv_internal.h index 5119ef4dffa..c2d301b4a22 100644 --- a/libavcodec/qsv_internal.h +++ b/libavcodec/qsv_internal.h @@ -23,9 +23,9 @@ #include "config.h" -#if CONFIG_VAAPI +#if CONFIG_VAAPI && !defined(_WIN32) // Do not enable for libva-win32 on Windows #define AVCODEC_QSV_LINUX_SESSION_HANDLE -#endif //CONFIG_VAAPI +#endif //CONFIG_VAAPI && !defined(_WIN32) #ifdef AVCODEC_QSV_LINUX_SESSION_HANDLE #include @@ -35,7 +35,6 @@ #endif #include #include -#include #include "libavutil/hwcontext_vaapi.h" #endif diff --git a/libavutil/hwcontext_qsv.c b/libavutil/hwcontext_qsv.c index 67804288750..4ed4242ddfb 100644 --- a/libavutil/hwcontext_qsv.c +++ b/libavutil/hwcontext_qsv.c @@ -2126,8 +2126,6 @@ static int qsv_device_create(AVHWDeviceContext *ctx, const char *device, "\"%s\".\n", e->value); return AVERROR(EINVAL); } - } else if (CONFIG_VAAPI) { - child_device_type = AV_HWDEVICE_TYPE_VAAPI; #if QSV_ONEVPL } else if (CONFIG_D3D11VA) { // Use D3D11 by default if d3d11va is enabled av_log(ctx, AV_LOG_VERBOSE, @@ -2147,11 +2145,23 @@ static int qsv_device_create(AVHWDeviceContext *ctx, const char *device, } else if (CONFIG_D3D11VA) { child_device_type = AV_HWDEVICE_TYPE_D3D11VA; #endif + } else if (CONFIG_VAAPI) { + child_device_type = AV_HWDEVICE_TYPE_VAAPI; } else { av_log(ctx, AV_LOG_ERROR, "No supported child device type is enabled\n"); return AVERROR(ENOSYS); } +#if CONFIG_VAAPI && defined(_WIN32) + /* AV_HWDEVICE_TYPE_VAAPI on Windows/Libva-win32 not supported */ + /* Reject user specified child_device_type or CONFIG_VAAPI on Windows */ + if (child_device_type == AV_HWDEVICE_TYPE_VAAPI) { + av_log(ctx, AV_LOG_ERROR, "VAAPI child device type not supported for oneVPL on Windows" + "\"%s\".\n", e->value); + return AVERROR(EINVAL); + } +#endif + child_device_opts = NULL; switch (child_device_type) { #if CONFIG_VAAPI From 2aad9765efa9affbe5e1184873e839d5ffacbcd9 Mon Sep 17 00:00:00 2001 From: Haihao Xiang Date: Wed, 12 Apr 2023 10:32:51 +0800 Subject: [PATCH 0763/2172] lavfi/overlay_vaapi: set input region for overlay video to NULL Otherwise main and overlay videos share the same input region. Note NULL pointer imples the whole overlay video will be processed. Signed-off-by: Haihao Xiang --- libavfilter/vf_overlay_vaapi.c | 1 + 1 file changed, 1 insertion(+) diff --git a/libavfilter/vf_overlay_vaapi.c b/libavfilter/vf_overlay_vaapi.c index 16d1e0e2113..92227ead7ff 100644 --- a/libavfilter/vf_overlay_vaapi.c +++ b/libavfilter/vf_overlay_vaapi.c @@ -237,6 +237,7 @@ static int overlay_vaapi_blend(FFFrameSync *fs) params[1].blend_state = &blend_state; params[1].surface = (VASurfaceID)(uintptr_t)input_overlay->data[3]; + params[1].surface_region = NULL; params[1].output_region = &overlay_region; } From 87b4453ec6df4de78a9ede6abccdfefe7cfeb66a Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Wed, 19 Apr 2023 21:20:06 +0200 Subject: [PATCH 0764/2172] fftools/ffmpeg: stop printing PSNR information in status report When an encoder exports sum-of-squared-differences information in encoded packets, print_report() will print PSNR information in the status line. However, * the code computing PSNR assumes 8bit 420 video and prints incorrect values otherwise; there are no issues on trac about this * only a few encoders (namely aom, vpx, mpegvideo, snow) export this information; other often-used encoders such as libx26[45] do not export this, even though they could This suggests that this feature is not useful and it is better to remove it rather than spend effort on fixing it. --- fftools/ffmpeg.c | 30 ------------------------------ 1 file changed, 30 deletions(-) diff --git a/fftools/ffmpeg.c b/fftools/ffmpeg.c index a7e856e9e2e..c73064af9a6 100644 --- a/fftools/ffmpeg.c +++ b/fftools/ffmpeg.c @@ -767,36 +767,6 @@ static void print_report(int is_last_report, int64_t timer_start, int64_t cur_ti if (is_last_report) av_bprintf(&buf, "L"); - if (enc && (enc->flags & AV_CODEC_FLAG_PSNR) && - (ost->pict_type != AV_PICTURE_TYPE_NONE || is_last_report)) { - int j; - double error, error_sum = 0; - double scale, scale_sum = 0; - double p; - char type[3] = { 'Y','U','V' }; - av_bprintf(&buf, "PSNR="); - for (j = 0; j < 3; j++) { - if (is_last_report) { - error = enc->error[j]; - scale = enc->width * enc->height * 255.0 * 255.0 * frame_number; - } else { - error = ost->error[j]; - scale = enc->width * enc->height * 255.0 * 255.0; - } - if (j) - scale /= 4; - error_sum += error; - scale_sum += scale; - p = psnr(error / scale); - av_bprintf(&buf, "%c:%2.2f ", type[j], p); - av_bprintf(&buf_script, "stream_%d_%d_psnr_%c=%2.2f\n", - ost->file_index, ost->index, type[j] | 32, p); - } - p = psnr(error_sum / scale_sum); - av_bprintf(&buf, "*:%2.2f ", psnr(error_sum / scale_sum)); - av_bprintf(&buf_script, "stream_%d_%d_psnr_all=%2.2f\n", - ost->file_index, ost->index, p); - } vid = 1; } /* compute min output value */ From a664ec94e0b9f77a3c9598a7c509d959d4c7fcc9 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Sat, 15 Apr 2023 10:47:30 +0200 Subject: [PATCH 0765/2172] fftools/ffmpeg_filter: drop write-only FilterGraph.reconfiguration --- fftools/ffmpeg.h | 1 - fftools/ffmpeg_filter.c | 2 -- 2 files changed, 3 deletions(-) diff --git a/fftools/ffmpeg.h b/fftools/ffmpeg.h index a9302a95f0e..72020c8f3a5 100644 --- a/fftools/ffmpeg.h +++ b/fftools/ffmpeg.h @@ -325,7 +325,6 @@ typedef struct FilterGraph { const char *graph_desc; AVFilterGraph *graph; - int reconfiguration; // true when the filtergraph contains only meta filters // that do not modify the frame data int is_meta; diff --git a/fftools/ffmpeg_filter.c b/fftools/ffmpeg_filter.c index 1d88d2e3b1e..52a5d193512 100644 --- a/fftools/ffmpeg_filter.c +++ b/fftools/ffmpeg_filter.c @@ -1239,8 +1239,6 @@ int configure_filtergraph(FilterGraph *fg) goto fail; } - fg->reconfiguration = 1; - for (i = 0; i < fg->nb_inputs; i++) { AVFrame *tmp; while (av_fifo_read(fg->inputs[i]->frame_queue, &tmp, 1) >= 0) { From 385430592a891949d8c7be4fda3aa4019cd174ab Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Tue, 18 Apr 2023 09:08:27 +0200 Subject: [PATCH 0766/2172] fftools/ffmpeg_filter: drop unused AUTO_INSERT_FILTER_INPUT() --- fftools/ffmpeg_filter.c | 21 --------------------- 1 file changed, 21 deletions(-) diff --git a/fftools/ffmpeg_filter.c b/fftools/ffmpeg_filter.c index 52a5d193512..ea182089b1c 100644 --- a/fftools/ffmpeg_filter.c +++ b/fftools/ffmpeg_filter.c @@ -1035,27 +1035,6 @@ static int configure_input_audio_filter(FilterGraph *fg, InputFilter *ifilter, return ret; last_filter = ifilter->filter; -#define AUTO_INSERT_FILTER_INPUT(opt_name, filter_name, arg) do { \ - AVFilterContext *filt_ctx; \ - \ - av_log(NULL, AV_LOG_INFO, opt_name " is forwarded to lavfi " \ - "similarly to -af " filter_name "=%s.\n", arg); \ - \ - snprintf(name, sizeof(name), "graph_%d_%s_in_%d_%d", \ - fg->index, filter_name, ist->file_index, ist->st->index); \ - ret = avfilter_graph_create_filter(&filt_ctx, \ - avfilter_get_by_name(filter_name), \ - name, arg, NULL, fg->graph); \ - if (ret < 0) \ - return ret; \ - \ - ret = avfilter_link(last_filter, 0, filt_ctx, 0); \ - if (ret < 0) \ - return ret; \ - \ - last_filter = filt_ctx; \ -} while (0) - snprintf(name, sizeof(name), "trim for input stream %d:%d", ist->file_index, ist->st->index); if (copy_ts) { From cd3049277343abd336f941e07549727d6e1b3ed8 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Sat, 15 Apr 2023 09:32:16 +0200 Subject: [PATCH 0767/2172] lavfi/avf_concat: rescale frame durations --- libavfilter/avf_concat.c | 1 + 1 file changed, 1 insertion(+) diff --git a/libavfilter/avf_concat.c b/libavfilter/avf_concat.c index c85c17b51f0..af758c5292d 100644 --- a/libavfilter/avf_concat.c +++ b/libavfilter/avf_concat.c @@ -179,6 +179,7 @@ static int push_frame(AVFilterContext *ctx, unsigned in_no, AVFrame *buf) struct concat_in *in = &cat->in[in_no]; buf->pts = av_rescale_q(buf->pts, inlink->time_base, outlink->time_base); + buf->duration = av_rescale_q(buf->duration, inlink->time_base, outlink->time_base); in->pts = buf->pts; in->nb_frames++; /* add duration to input PTS */ From c94e9d03b44d21282418dfb6c84f4f7942d4db03 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Sat, 15 Apr 2023 09:46:29 +0200 Subject: [PATCH 0768/2172] fftools/ffmpeg_enc: always use video frame durations when available Previously they would only be used with trivial filtergraphs, because filters did not handle frame durations. That is no longer true - most filters process frame durations properly (there may still be some that don't - this change will help finding and fixing them). Improves output video frame durations in a number of FATE tests. --- fftools/ffmpeg_enc.c | 19 +++----- tests/ref/fate/filter-concat-vfr | 66 +++++++++++++------------- tests/ref/fate/gif-disposal-restore | 2 +- tests/ref/fate/gif-gray | 72 ++++++++++++++--------------- tests/ref/fate/quickdraw | 2 +- 5 files changed, 77 insertions(+), 84 deletions(-) diff --git a/fftools/ffmpeg_enc.c b/fftools/ffmpeg_enc.c index e3dc858bc33..9aaec277f15 100644 --- a/fftools/ffmpeg_enc.c +++ b/fftools/ffmpeg_enc.c @@ -1005,24 +1005,17 @@ static void do_video_out(OutputFile *of, AVRational frame_rate; int64_t nb_frames, nb_frames_prev, i; double duration = 0; - InputStream *ist = ost->ist; AVFilterContext *filter = ost->filter->filter; - frame_rate = av_buffersink_get_frame_rate(filter); - if (frame_rate.num > 0 && frame_rate.den > 0) - duration = 1/(av_q2d(frame_rate) * av_q2d(enc->time_base)); + if (next_picture) + duration = lrintf(next_picture->duration * av_q2d(next_picture->time_base) / av_q2d(enc->time_base)); - if(ist && ist->st->start_time != AV_NOPTS_VALUE && ist->first_dts != AV_NOPTS_VALUE && ost->frame_rate.num) + if (duration <= 0 && ost->frame_rate.num) duration = FFMIN(duration, 1/(av_q2d(ost->frame_rate) * av_q2d(enc->time_base))); - if (!ost->filters_script && - !ost->filters && - (nb_filtergraphs == 0 || !filtergraphs[0]->graph_desc) && - next_picture && - ist && - lrintf(next_picture->duration * av_q2d(ist->st->time_base) / av_q2d(enc->time_base)) > 0) { - duration = lrintf(next_picture->duration * av_q2d(ist->st->time_base) / av_q2d(enc->time_base)); - } + frame_rate = av_buffersink_get_frame_rate(filter); + if (duration <= 0 && frame_rate.num > 0 && frame_rate.den > 0) + duration = 1/(av_q2d(frame_rate) * av_q2d(enc->time_base)); if (!next_picture) { //end, flushing diff --git a/tests/ref/fate/filter-concat-vfr b/tests/ref/fate/filter-concat-vfr index 7c5e12e093e..66e9007da81 100644 --- a/tests/ref/fate/filter-concat-vfr +++ b/tests/ref/fate/filter-concat-vfr @@ -8,7 +8,7 @@ #codec_id 1: pcm_s16le #sample_rate 1: 44100 #channel_layout_name 1: mono -0, 0, 0, 0, 230400, 0x88c4d19a +0, 0, 0, 199999, 230400, 0x88c4d19a 1, 0, 0, 1024, 2048, 0xb3f10192 1, 1024, 1024, 1024, 2048, 0xb340fe4e 1, 2048, 2048, 1024, 2048, 0x0a5f0111 @@ -18,7 +18,7 @@ 1, 6144, 6144, 1024, 2048, 0x70a8fa17 1, 7168, 7168, 1024, 2048, 0x0dad072a 1, 8192, 8192, 1024, 2048, 0x5e810c51 -0, 200000, 200000, 0, 230400, 0x0d77c977 +0, 200000, 200000, 200000, 230400, 0x0d77c977 1, 9216, 9216, 1024, 2048, 0xbe5bf462 1, 10240, 10240, 1024, 2048, 0xbcd9faeb 1, 11264, 11264, 1024, 2048, 0x0d5bfe9c @@ -28,7 +28,7 @@ 1, 15360, 15360, 1024, 2048, 0x11a9fa03 1, 16384, 16384, 1024, 2048, 0x9a920378 1, 17408, 17408, 1024, 2048, 0x901b0525 -0, 400000, 400000, 0, 230400, 0x242629d7 +0, 400000, 400000, 200000, 230400, 0x242629d7 1, 18432, 18432, 1024, 2048, 0x74b2003f 1, 19456, 19456, 1024, 2048, 0xa20ef3ed 1, 20480, 20480, 1024, 2048, 0x44cef9de @@ -37,7 +37,7 @@ 1, 23552, 23552, 1024, 2048, 0xcab6f9e5 1, 24576, 24576, 1024, 2048, 0x67f8f608 1, 25600, 25600, 1024, 2048, 0x8d7f03fa -0, 600000, 600000, 0, 230400, 0x62cdc018 +0, 600000, 600000, 200000, 230400, 0x62cdc018 1, 26624, 26624, 1024, 2048, 0x3e1e0566 1, 27648, 27648, 1024, 2048, 0x2cfe0308 1, 28672, 28672, 1024, 2048, 0x1ceaf702 @@ -47,7 +47,7 @@ 1, 32768, 32768, 1024, 2048, 0x3e5afa28 1, 33792, 33792, 1024, 2048, 0x053ff47a 1, 34816, 34816, 1024, 2048, 0x0d28fed9 -0, 800000, 800000, 0, 230400, 0x248ad058 +0, 800000, 800000, 200000, 230400, 0x248ad058 1, 35840, 35840, 1024, 2048, 0x279805cc 1, 36864, 36864, 1024, 2048, 0xb16a0a12 1, 37888, 37888, 1024, 2048, 0xb45af340 @@ -57,72 +57,72 @@ 1, 41984, 41984, 1024, 2048, 0x503800ce 1, 43008, 43008, 1024, 2048, 0xa3bbf4af 1, 44032, 44032, 68, 136, 0xc8d751c7 -0, 1000000, 1000000, 0, 230400, 0x223d134f +0, 1000000, 1000000, 200000, 230400, 0x223d134f 1, 44100, 44100, 9600, 19200, 0x00000000 -0, 1200000, 1200000, 0, 230400, 0xbf1c3d34 +0, 1200000, 1200000, 200000, 230400, 0xbf1c3d34 1, 53700, 53700, 9600, 19200, 0x00000000 -0, 1400000, 1400000, 0, 230400, 0xae0efe96 +0, 1400000, 1400000, 200000, 230400, 0xae0efe96 1, 63300, 63300, 9600, 19200, 0x00000000 -0, 1600000, 1600000, 0, 230400, 0x0cd624d1 +0, 1600000, 1600000, 200000, 230400, 0x0cd624d1 1, 72900, 72900, 9600, 19200, 0x00000000 -0, 1800000, 1800000, 0, 230400, 0x6dedf2c0 +0, 1800000, 1800000, 200000, 230400, 0x6dedf2c0 1, 82500, 82500, 5700, 11400, 0x00000000 -0, 2000000, 2000000, 0, 230400, 0x88c4d19a +0, 2000000, 2000000, 66667, 230400, 0x88c4d19a 1, 88200, 88200, 1024, 2048, 0x283efb3a 1, 89224, 89224, 1024, 2048, 0x7692fb8f 1, 90248, 90248, 1024, 2048, 0xbaaafcc0 -0, 2066667, 2066667, 0, 230400, 0x5bbc2f63 +0, 2066667, 2066667, 66667, 230400, 0x5bbc2f63 1, 91272, 91272, 1024, 2048, 0xadc8017e 1, 92296, 92296, 1024, 2048, 0x4f4dffdc 1, 93320, 93320, 1024, 2048, 0x7ffbff48 -0, 2133333, 2133333, 0, 230400, 0x3becbfad +0, 2133333, 2133333, 66667, 230400, 0x3becbfad 1, 94344, 94344, 1024, 2048, 0x2f990719 1, 95368, 95368, 1024, 2048, 0xe2caf65c 1, 96392, 96392, 1024, 2048, 0x825208e4 -0, 2200000, 2200000, 0, 230400, 0x0d77c977 +0, 2200000, 2200000, 66667, 230400, 0x0d77c977 1, 97416, 97416, 1024, 2048, 0xf563f13b 1, 98440, 98440, 1024, 2048, 0x855d03e9 1, 99464, 99464, 1024, 2048, 0x0ba9fa4b -0, 2266667, 2266667, 0, 230400, 0x436cf4b2 +0, 2266667, 2266667, 66667, 230400, 0x436cf4b2 1, 100488, 100488, 1024, 2048, 0x83e1fb92 1, 101512, 101512, 1024, 2048, 0x1162f965 1, 102536, 102536, 1024, 2048, 0x0cfef73d -0, 2333333, 2333333, 0, 230400, 0x39210f27 +0, 2333333, 2333333, 66667, 230400, 0x39210f27 1, 103560, 103560, 1024, 2048, 0x5688ff75 1, 104584, 104584, 1024, 2048, 0xf6c0ede9 1, 105608, 105608, 1024, 2048, 0xfdb20602 -0, 2400000, 2400000, 0, 230400, 0x242629d7 +0, 2400000, 2400000, 66667, 230400, 0x242629d7 1, 106632, 106632, 1024, 2048, 0x40c5f17b 1, 107656, 107656, 1024, 2048, 0x559600b1 1, 108680, 108680, 1024, 2048, 0xccc3f930 -0, 2466667, 2466667, 0, 230400, 0x771c2293 +0, 2466667, 2466667, 66667, 230400, 0x771c2293 1, 109704, 109704, 1024, 2048, 0xdc800045 1, 110728, 110728, 1024, 2048, 0xdce4fb3e -0, 2533333, 2533333, 0, 230400, 0xec2af9a9 +0, 2533333, 2533333, 66667, 230400, 0xec2af9a9 1, 111752, 111752, 1024, 2048, 0x1e5efba9 1, 112776, 112776, 1024, 2048, 0x8c2e0832 1, 113800, 113800, 1024, 2048, 0x5c42f66d -0, 2600000, 2600000, 0, 230400, 0x62cdc018 +0, 2600000, 2600000, 66667, 230400, 0x62cdc018 1, 114824, 114824, 1024, 2048, 0x08e20b1e 1, 115848, 115848, 1024, 2048, 0x4cf7f903 1, 116872, 116872, 1024, 2048, 0xe6b90794 -0, 2666667, 2666667, 0, 230400, 0xf02c8693 +0, 2666667, 2666667, 66667, 230400, 0xf02c8693 1, 117896, 117896, 1024, 2048, 0x5956f8e6 1, 118920, 118920, 1024, 2048, 0x6632ff16 1, 119944, 119944, 1024, 2048, 0x46c8fe11 -0, 2733333, 2733333, 0, 230400, 0x14436efb +0, 2733333, 2733333, 66667, 230400, 0x14436efb 1, 120968, 120968, 1024, 2048, 0x7431f732 1, 121992, 121992, 1024, 2048, 0xa258049f 1, 123016, 123016, 1024, 2048, 0xdb71f00e -0, 2800000, 2800000, 0, 230400, 0x248ad058 +0, 2800000, 2800000, 66667, 230400, 0x248ad058 1, 124040, 124040, 1024, 2048, 0xa89b0359 1, 125064, 125064, 1024, 2048, 0xe0aff0f2 1, 126088, 126088, 1024, 2048, 0xc33e0085 -0, 2866667, 2866667, 0, 230400, 0xe87f6c52 +0, 2866667, 2866667, 66667, 230400, 0xe87f6c52 1, 127112, 127112, 1024, 2048, 0x9d09f379 1, 128136, 128136, 1024, 2048, 0x8c78fd06 1, 129160, 129160, 1024, 2048, 0x532bfbdd -0, 2933333, 2933333, 0, 230400, 0x6a0c196b +0, 2933333, 2933333, 66667, 230400, 0x6a0c196b 1, 130184, 130184, 1024, 2048, 0xfc36f5cd 1, 131208, 131208, 1024, 2048, 0x2e8f0699 1, 132232, 132232, 1024, 2048, 0x52382578 @@ -169,52 +169,52 @@ 1, 174216, 174216, 1024, 2048, 0xf86ff855 1, 175240, 175240, 1024, 2048, 0x6934061b 1, 176264, 176264, 136, 272, 0x4a458a45 -0, 4000000, 4000000, 0, 230400, 0x88c4d19a +0, 4000000, 4000000, 125000, 230400, 0x88c4d19a 1, 176400, 176400, 1024, 2048, 0xdb0cfe95 1, 177424, 177424, 1024, 2048, 0xcff3fdf1 1, 178448, 178448, 1024, 2048, 0x070cf585 1, 179472, 179472, 1024, 2048, 0xe9b8007f 1, 180496, 180496, 1024, 2048, 0xc51ffd64 1, 181520, 181520, 1024, 2048, 0xede2fbf9 -0, 4125000, 4125000, 0, 230400, 0x05c1b733 +0, 4125000, 4125000, 125000, 230400, 0x05c1b733 1, 182544, 182544, 1024, 2048, 0x51510410 1, 183568, 183568, 1024, 2048, 0x198af498 1, 184592, 184592, 1024, 2048, 0xae3603a2 1, 185616, 185616, 1024, 2048, 0x6200f7a1 1, 186640, 186640, 1024, 2048, 0xe6e3fe32 -0, 4250000, 4250000, 0, 230400, 0x0446ec19 +0, 4250000, 4250000, 125000, 230400, 0x0446ec19 1, 187664, 187664, 1024, 2048, 0xb2e2fd77 1, 188688, 188688, 1024, 2048, 0x063dff2f 1, 189712, 189712, 1024, 2048, 0xa89ffe21 1, 190736, 190736, 1024, 2048, 0x9e6ffa6d 1, 191760, 191760, 1024, 2048, 0x028b004e 1, 192784, 192784, 1024, 2048, 0x57edfa23 -0, 4375000, 4375000, 0, 230400, 0x0f9b1744 +0, 4375000, 4375000, 125000, 230400, 0x0f9b1744 1, 193808, 193808, 1024, 2048, 0x6d8efe1f 1, 194832, 194832, 1024, 2048, 0x774bfe54 1, 195856, 195856, 1024, 2048, 0xa931fcfb 1, 196880, 196880, 1024, 2048, 0x3505004b 1, 197904, 197904, 1024, 2048, 0x5001f576 -0, 4500000, 4500000, 0, 230400, 0x30cf070a +0, 4500000, 4500000, 125000, 230400, 0x30cf070a 1, 198928, 198928, 1024, 2048, 0x78ea049b 1, 199952, 199952, 1024, 2048, 0xd45bf733 1, 200976, 200976, 1024, 2048, 0x6395fead 1, 202000, 202000, 1024, 2048, 0xc126015e 1, 203024, 203024, 1024, 2048, 0xbecff8aa -0, 4625000, 4625000, 0, 230400, 0x9175aaa9 +0, 4625000, 4625000, 125000, 230400, 0x9175aaa9 1, 204048, 204048, 1024, 2048, 0x0fea06c3 1, 205072, 205072, 1024, 2048, 0xdea6f351 1, 206096, 206096, 1024, 2048, 0x35b808f0 1, 207120, 207120, 1024, 2048, 0x5487ee73 1, 208144, 208144, 1024, 2048, 0xac69050e 1, 209168, 209168, 1024, 2048, 0xcc5ffb00 -0, 4750000, 4750000, 0, 230400, 0x597f5628 +0, 4750000, 4750000, 125000, 230400, 0x597f5628 1, 210192, 210192, 1024, 2048, 0x328c00cb 1, 211216, 211216, 1024, 2048, 0xa707fd82 1, 212240, 212240, 1024, 2048, 0xe442f73d 1, 213264, 213264, 1024, 2048, 0x545c0418 1, 214288, 214288, 1024, 2048, 0x744ff3f7 -0, 4875000, 4875000, 0, 230400, 0x38a45a85 +0, 4875000, 4875000, 125000, 230400, 0x38a45a85 1, 215312, 215312, 1024, 2048, 0x01aa04fd 1, 216336, 216336, 1024, 2048, 0xa885f7cd 1, 217360, 217360, 1024, 2048, 0xcfca04f4 diff --git a/tests/ref/fate/gif-disposal-restore b/tests/ref/fate/gif-disposal-restore index b1282f61dec..aca80c5e6d6 100644 --- a/tests/ref/fate/gif-disposal-restore +++ b/tests/ref/fate/gif-disposal-restore @@ -4,5 +4,5 @@ #dimensions 0: 468x60 #sar 0: 0/1 0, 0, 0, 1, 112320, 0xb8afe429 -0, 1, 1, 1, 112320, 0xae588a4b +0, 1, 1, 2, 112320, 0xae588a4b 0, 3, 3, 1, 112320, 0xccdd27b7 diff --git a/tests/ref/fate/gif-gray b/tests/ref/fate/gif-gray index 18705d01fe3..aa3969212d7 100644 --- a/tests/ref/fate/gif-gray +++ b/tests/ref/fate/gif-gray @@ -3,39 +3,39 @@ #codec_id 0: rawvideo #dimensions 0: 480x360 #sar 0: 0/1 -0, 0, 0, 1, 691200, 0xef6c0f3d -0, 5, 5, 1, 691200, 0xc18b32de -0, 7, 7, 1, 691200, 0x2395a3d7 -0, 9, 9, 1, 691200, 0x81dc3cf2 -0, 11, 11, 1, 691200, 0xabe2390e -0, 13, 13, 1, 691200, 0xb2955c2a -0, 15, 15, 1, 691200, 0x868d9ca2 -0, 17, 17, 1, 691200, 0x3016c2b6 -0, 19, 19, 1, 691200, 0x4501cffa -0, 21, 21, 1, 691200, 0x8661d79e -0, 25, 25, 1, 691200, 0xbc96d02e -0, 27, 27, 1, 691200, 0x5f90bf5e -0, 29, 29, 1, 691200, 0xf18da09a -0, 31, 31, 1, 691200, 0x540467ce -0, 33, 33, 1, 691200, 0x60d24012 -0, 35, 35, 1, 691200, 0x24323d36 -0, 37, 37, 1, 691200, 0x9e07c84b -0, 39, 39, 1, 691200, 0xc18b32de -0, 41, 41, 1, 691200, 0xef6c0f3d -0, 46, 46, 1, 691200, 0xc9461045 -0, 48, 48, 1, 691200, 0x23ed4b99 -0, 50, 50, 1, 691200, 0x7e351d69 -0, 52, 52, 1, 691200, 0x0513e0aa -0, 54, 54, 1, 691200, 0x28a4b6f2 -0, 56, 56, 1, 691200, 0xce10a94e -0, 58, 58, 1, 691200, 0x63929d4e -0, 60, 60, 1, 691200, 0xd26c9bb6 -0, 62, 62, 1, 691200, 0xb2a29842 -0, 66, 66, 1, 691200, 0x9fd69a16 -0, 68, 68, 1, 691200, 0x10f99e46 -0, 70, 70, 1, 691200, 0xea95a9fa -0, 72, 72, 1, 691200, 0x97dbb9d6 -0, 74, 74, 1, 691200, 0xf4e9e2d6 -0, 76, 76, 1, 691200, 0x46b1230d -0, 78, 78, 1, 691200, 0xb4a54ccd -0, 80, 80, 1, 691200, 0x40cc103d +0, 0, 0, 4, 691200, 0xef6c0f3d +0, 5, 5, 2, 691200, 0xc18b32de +0, 7, 7, 2, 691200, 0x2395a3d7 +0, 9, 9, 2, 691200, 0x81dc3cf2 +0, 11, 11, 2, 691200, 0xabe2390e +0, 13, 13, 2, 691200, 0xb2955c2a +0, 15, 15, 2, 691200, 0x868d9ca2 +0, 17, 17, 2, 691200, 0x3016c2b6 +0, 19, 19, 2, 691200, 0x4501cffa +0, 21, 21, 4, 691200, 0x8661d79e +0, 25, 25, 2, 691200, 0xbc96d02e +0, 27, 27, 2, 691200, 0x5f90bf5e +0, 29, 29, 2, 691200, 0xf18da09a +0, 31, 31, 2, 691200, 0x540467ce +0, 33, 33, 2, 691200, 0x60d24012 +0, 35, 35, 2, 691200, 0x24323d36 +0, 37, 37, 2, 691200, 0x9e07c84b +0, 39, 39, 2, 691200, 0xc18b32de +0, 41, 41, 5, 691200, 0xef6c0f3d +0, 46, 46, 2, 691200, 0xc9461045 +0, 48, 48, 2, 691200, 0x23ed4b99 +0, 50, 50, 2, 691200, 0x7e351d69 +0, 52, 52, 2, 691200, 0x0513e0aa +0, 54, 54, 2, 691200, 0x28a4b6f2 +0, 56, 56, 2, 691200, 0xce10a94e +0, 58, 58, 2, 691200, 0x63929d4e +0, 60, 60, 2, 691200, 0xd26c9bb6 +0, 62, 62, 4, 691200, 0xb2a29842 +0, 66, 66, 2, 691200, 0x9fd69a16 +0, 68, 68, 2, 691200, 0x10f99e46 +0, 70, 70, 2, 691200, 0xea95a9fa +0, 72, 72, 2, 691200, 0x97dbb9d6 +0, 74, 74, 2, 691200, 0xf4e9e2d6 +0, 76, 76, 2, 691200, 0x46b1230d +0, 78, 78, 2, 691200, 0xb4a54ccd +0, 80, 80, 2, 691200, 0x40cc103d diff --git a/tests/ref/fate/quickdraw b/tests/ref/fate/quickdraw index 5746929502a..44610498c8f 100644 --- a/tests/ref/fate/quickdraw +++ b/tests/ref/fate/quickdraw @@ -9,7 +9,7 @@ 0, 3, 3, 1, 921600, 0xc0e68764 0, 4, 4, 1, 921600, 0xc0e68764 0, 5, 5, 1, 921600, 0xc0e68764 -0, 7, 7, 1, 921600, 0x01a16629 +0, 7, 7, 2, 921600, 0x01a16629 0, 9, 9, 1, 921600, 0x01a16629 0, 10, 10, 1, 921600, 0x01a16629 0, 11, 11, 1, 921600, 0x01a16629 From 403088cb67b0019ec1c11165a3bb9be277386b65 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Sat, 15 Apr 2023 09:53:14 +0200 Subject: [PATCH 0769/2172] fftools/ffmpeg_enc: rename next_picture to frame The name is misleading, because it is not a picture in the sense of MPEG terminology (which define "picture" as "frame or field"), but always a full frame. 'next' is also redundant and/or misleading, because it is the _current_ frame to be encoded. --- fftools/ffmpeg_enc.c | 36 +++++++++++++++++------------------- 1 file changed, 17 insertions(+), 19 deletions(-) diff --git a/fftools/ffmpeg_enc.c b/fftools/ffmpeg_enc.c index 9aaec277f15..e63da2ec974 100644 --- a/fftools/ffmpeg_enc.c +++ b/fftools/ffmpeg_enc.c @@ -873,14 +873,14 @@ static double adjust_frame_pts_to_encoder_tb(OutputFile *of, OutputStream *ost, * desired target framerate (if any). */ static void video_sync_process(OutputFile *of, OutputStream *ost, - AVFrame *next_picture, double duration, + AVFrame *frame, double duration, int64_t *nb_frames, int64_t *nb_frames_prev) { Encoder *e = ost->enc; double delta0, delta; - double sync_ipts = adjust_frame_pts_to_encoder_tb(of, ost, next_picture); - /* delta0 is the "drift" between the input frame (next_picture) and + double sync_ipts = adjust_frame_pts_to_encoder_tb(of, ost, frame); + /* delta0 is the "drift" between the input frame and * where it would fall in the output. */ delta0 = sync_ipts - e->next_pts; delta = delta0 + duration; @@ -923,18 +923,18 @@ static void video_sync_process(OutputFile *of, OutputStream *ost, if (delta0 > 1.1) *nb_frames_prev = llrintf(delta0 - 0.6); } - next_picture->duration = 1; + frame->duration = 1; break; case VSYNC_VFR: if (delta <= -0.6) *nb_frames = 0; else if (delta > 0.6) e->next_pts = llrint(sync_ipts); - next_picture->duration = duration; + frame->duration = duration; break; case VSYNC_DROP: case VSYNC_PASSTHROUGH: - next_picture->duration = duration; + frame->duration = duration; e->next_pts = llrint(sync_ipts); break; default: @@ -994,10 +994,8 @@ static enum AVPictureType forced_kf_apply(void *logctx, KeyframeForceCtx *kf, return AV_PICTURE_TYPE_I; } -/* May modify/reset next_picture */ -static void do_video_out(OutputFile *of, - OutputStream *ost, - AVFrame *next_picture) +/* May modify/reset frame */ +static void do_video_out(OutputFile *of, OutputStream *ost, AVFrame *frame) { int ret; Encoder *e = ost->enc; @@ -1007,8 +1005,8 @@ static void do_video_out(OutputFile *of, double duration = 0; AVFilterContext *filter = ost->filter->filter; - if (next_picture) - duration = lrintf(next_picture->duration * av_q2d(next_picture->time_base) / av_q2d(enc->time_base)); + if (frame) + duration = lrintf(frame->duration * av_q2d(frame->time_base) / av_q2d(enc->time_base)); if (duration <= 0 && ost->frame_rate.num) duration = FFMIN(duration, 1/(av_q2d(ost->frame_rate) * av_q2d(enc->time_base))); @@ -1017,13 +1015,13 @@ static void do_video_out(OutputFile *of, if (duration <= 0 && frame_rate.num > 0 && frame_rate.den > 0) duration = 1/(av_q2d(frame_rate) * av_q2d(enc->time_base)); - if (!next_picture) { + if (!frame) { //end, flushing nb_frames_prev = nb_frames = mid_pred(e->frames_prev_hist[0], e->frames_prev_hist[1], e->frames_prev_hist[2]); } else { - video_sync_process(of, ost, next_picture, duration, + video_sync_process(of, ost, frame, duration, &nb_frames, &nb_frames_prev); } @@ -1051,8 +1049,8 @@ static void do_video_out(OutputFile *of, dup_warning *= 10; } } - ost->last_dropped = nb_frames == nb_frames_prev && next_picture; - ost->kf.dropped_keyframe = ost->last_dropped && next_picture && next_picture->key_frame; + ost->last_dropped = nb_frames == nb_frames_prev && frame; + ost->kf.dropped_keyframe = ost->last_dropped && frame && frame->key_frame; /* duplicates frame if needed */ for (i = 0; i < nb_frames; i++) { @@ -1061,7 +1059,7 @@ static void do_video_out(OutputFile *of, if (i < nb_frames_prev && e->last_frame->buf[0]) { in_picture = e->last_frame; } else - in_picture = next_picture; + in_picture = frame; if (!in_picture) return; @@ -1085,8 +1083,8 @@ static void do_video_out(OutputFile *of, } av_frame_unref(e->last_frame); - if (next_picture) - av_frame_move_ref(e->last_frame, next_picture); + if (frame) + av_frame_move_ref(e->last_frame, frame); } void enc_frame(OutputStream *ost, AVFrame *frame) From 37547e3acd2438d5af170308f5653b48d3747425 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Sat, 15 Apr 2023 10:00:56 +0200 Subject: [PATCH 0770/2172] fftools/ffmpeg_enc: move handling final frames to video_sync_process() This code properly belongs there. --- fftools/ffmpeg_enc.c | 33 +++++++++++++++++---------------- 1 file changed, 17 insertions(+), 16 deletions(-) diff --git a/fftools/ffmpeg_enc.c b/fftools/ffmpeg_enc.c index e63da2ec974..859c7fdeeec 100644 --- a/fftools/ffmpeg_enc.c +++ b/fftools/ffmpeg_enc.c @@ -877,9 +877,16 @@ static void video_sync_process(OutputFile *of, OutputStream *ost, int64_t *nb_frames, int64_t *nb_frames_prev) { Encoder *e = ost->enc; - double delta0, delta; + double delta0, delta, sync_ipts; - double sync_ipts = adjust_frame_pts_to_encoder_tb(of, ost, frame); + if (!frame) { + *nb_frames_prev = *nb_frames = mid_pred(e->frames_prev_hist[0], + e->frames_prev_hist[1], + e->frames_prev_hist[2]); + goto finish; + } + + sync_ipts = adjust_frame_pts_to_encoder_tb(of, ost, frame); /* delta0 is the "drift" between the input frame and * where it would fall in the output. */ delta0 = sync_ipts - e->next_pts; @@ -940,6 +947,12 @@ static void video_sync_process(OutputFile *of, OutputStream *ost, default: av_assert0(0); } + +finish: + memmove(e->frames_prev_hist + 1, + e->frames_prev_hist, + sizeof(e->frames_prev_hist[0]) * (FF_ARRAY_ELEMS(e->frames_prev_hist) - 1)); + e->frames_prev_hist[0] = *nb_frames_prev; } static enum AVPictureType forced_kf_apply(void *logctx, KeyframeForceCtx *kf, @@ -1015,20 +1028,8 @@ static void do_video_out(OutputFile *of, OutputStream *ost, AVFrame *frame) if (duration <= 0 && frame_rate.num > 0 && frame_rate.den > 0) duration = 1/(av_q2d(frame_rate) * av_q2d(enc->time_base)); - if (!frame) { - //end, flushing - nb_frames_prev = nb_frames = mid_pred(e->frames_prev_hist[0], - e->frames_prev_hist[1], - e->frames_prev_hist[2]); - } else { - video_sync_process(of, ost, frame, duration, - &nb_frames, &nb_frames_prev); - } - - memmove(e->frames_prev_hist + 1, - e->frames_prev_hist, - sizeof(e->frames_prev_hist[0]) * (FF_ARRAY_ELEMS(e->frames_prev_hist) - 1)); - e->frames_prev_hist[0] = nb_frames_prev; + video_sync_process(of, ost, frame, duration, + &nb_frames, &nb_frames_prev); if (nb_frames_prev == 0 && ost->last_dropped) { nb_frames_drop++; From d8bc37f1f446d5798d77830e197f02188919a313 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Sat, 15 Apr 2023 10:18:24 +0200 Subject: [PATCH 0771/2172] fftools/ffmpeg: stop using InputStream.pts in ts_discontinuity_detect() ts_discontinuity_detect() is applied right after demuxing, while InputStream.pts is a post-decoding timestamp, which may be delayed with respect to demuxing by an arbitrary amount (e.g. depending on the thread count when frame threading is used). --- fftools/ffmpeg.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fftools/ffmpeg.c b/fftools/ffmpeg.c index c73064af9a6..a498a68b20b 100644 --- a/fftools/ffmpeg.c +++ b/fftools/ffmpeg.c @@ -2091,7 +2091,7 @@ static void ts_discontinuity_detect(InputFile *ifile, InputStream *ist, int64_t delta = pkt_dts - ist->next_dts; if (fmt_is_discont) { if (FFABS(delta) > 1LL * dts_delta_threshold * AV_TIME_BASE || - pkt_dts + AV_TIME_BASE/10 < FFMAX(ist->pts, ist->dts)) { + pkt_dts + AV_TIME_BASE/10 < ist->dts) { ifile->ts_offset_discont -= delta; av_log(NULL, AV_LOG_WARNING, "timestamp discontinuity for stream #%d:%d " From 65b1350ad482b465c984a4987317e2b15be9d939 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Sat, 15 Apr 2023 10:21:44 +0200 Subject: [PATCH 0772/2172] fftools/ffmpeg: stop setting InputStream.pts for streamcopy It is not used in that case anymore. Forgotten in d56652fdc8e1315309516be320a7250854550fa5. --- fftools/ffmpeg.c | 1 - 1 file changed, 1 deletion(-) diff --git a/fftools/ffmpeg.c b/fftools/ffmpeg.c index a498a68b20b..c55d67f8f96 100644 --- a/fftools/ffmpeg.c +++ b/fftools/ffmpeg.c @@ -1713,7 +1713,6 @@ static int process_input_packet(InputStream *ist, const AVPacket *pkt, int no_eo } break; } - ist->pts = ist->dts; } else if (!ist->decoding_needed) eof_reached = 1; From 03a465be5732e4ff72650dcaeb9bc399622417bb Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Mon, 17 Apr 2023 13:41:37 +0200 Subject: [PATCH 0773/2172] fftools/ffmpeg: replace stream timebase with packet one where appropriate --- fftools/ffmpeg.c | 36 ++++++++++++++++++------------------ 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/fftools/ffmpeg.c b/fftools/ffmpeg.c index c55d67f8f96..94c2568efb6 100644 --- a/fftools/ffmpeg.c +++ b/fftools/ffmpeg.c @@ -1116,7 +1116,7 @@ static int decode_audio(InputStream *ist, AVPacket *pkt, int *got_output, decoded_frame_tb = ist->st->time_base; } else if (pkt && pkt->pts != AV_NOPTS_VALUE) { decoded_frame->pts = pkt->pts; - decoded_frame_tb = ist->st->time_base; + decoded_frame_tb = pkt->time_base; }else { decoded_frame->pts = ist->dts; decoded_frame_tb = AV_TIME_BASE_Q; @@ -1553,7 +1553,7 @@ static int process_input_packet(InputStream *ist, const AVPacket *pkt, int no_eo ist->pts = 0; if (pkt && pkt->pts != AV_NOPTS_VALUE && !ist->decoding_needed) { ist->first_dts = - ist->dts += av_rescale_q(pkt->pts, ist->st->time_base, AV_TIME_BASE_Q); + ist->dts += av_rescale_q(pkt->pts, pkt->time_base, AV_TIME_BASE_Q); } ist->saw_first_ts = 1; } @@ -1571,7 +1571,7 @@ static int process_input_packet(InputStream *ist, const AVPacket *pkt, int no_eo } if (pkt && pkt->dts != AV_NOPTS_VALUE) { - ist->next_dts = ist->dts = av_rescale_q(pkt->dts, ist->st->time_base, AV_TIME_BASE_Q); + ist->next_dts = ist->dts = av_rescale_q(pkt->dts, pkt->time_base, AV_TIME_BASE_Q); if (par->codec_type != AVMEDIA_TYPE_VIDEO) ist->pts = ist->dts; } @@ -1597,7 +1597,7 @@ static int process_input_packet(InputStream *ist, const AVPacket *pkt, int no_eo &decode_failed); if (!repeating || !pkt || got_output) { if (pkt && pkt->duration) { - duration_dts = av_rescale_q(pkt->duration, ist->st->time_base, AV_TIME_BASE_Q); + duration_dts = av_rescale_q(pkt->duration, pkt->time_base, AV_TIME_BASE_Q); } else if(ist->dec_ctx->framerate.num != 0 && ist->dec_ctx->framerate.den != 0) { int ticks = ist->last_pkt_repeat_pict >= 0 ? ist->last_pkt_repeat_pict + 1 : @@ -1692,7 +1692,7 @@ static int process_input_packet(InputStream *ist, const AVPacket *pkt, int no_eo ist->next_dts += ((int64_t)AV_TIME_BASE * par->frame_size) / par->sample_rate; } else { - ist->next_dts += av_rescale_q(pkt->duration, ist->st->time_base, AV_TIME_BASE_Q); + ist->next_dts += av_rescale_q(pkt->duration, pkt->time_base, AV_TIME_BASE_Q); } break; case AVMEDIA_TYPE_VIDEO: @@ -1702,7 +1702,7 @@ static int process_input_packet(InputStream *ist, const AVPacket *pkt, int no_eo int64_t next_dts = av_rescale_q(ist->next_dts, time_base_q, av_inv_q(ist->framerate)); ist->next_dts = av_rescale_q(next_dts + 1, av_inv_q(ist->framerate), time_base_q); } else if (pkt->duration) { - ist->next_dts += av_rescale_q(pkt->duration, ist->st->time_base, AV_TIME_BASE_Q); + ist->next_dts += av_rescale_q(pkt->duration, pkt->time_base, AV_TIME_BASE_Q); } else if(ist->dec_ctx->framerate.num != 0) { int ticks = ist->last_pkt_repeat_pict >= 0 ? ist->last_pkt_repeat_pict + 1 : @@ -2074,13 +2074,13 @@ static void ts_discontinuity_detect(InputFile *ifile, InputStream *ist, { const int fmt_is_discont = ifile->ctx->iformat->flags & AVFMT_TS_DISCONT; int disable_discontinuity_correction = copy_ts; - int64_t pkt_dts = av_rescale_q_rnd(pkt->dts, ist->st->time_base, AV_TIME_BASE_Q, + int64_t pkt_dts = av_rescale_q_rnd(pkt->dts, pkt->time_base, AV_TIME_BASE_Q, AV_ROUND_NEAR_INF | AV_ROUND_PASS_MINMAX); if (copy_ts && ist->next_dts != AV_NOPTS_VALUE && fmt_is_discont && ist->st->pts_wrap_bits < 60) { int64_t wrap_dts = av_rescale_q_rnd(pkt->dts + (1LL<st->pts_wrap_bits), - ist->st->time_base, AV_TIME_BASE_Q, + pkt->time_base, AV_TIME_BASE_Q, AV_ROUND_NEAR_INF|AV_ROUND_PASS_MINMAX); if (FFABS(wrap_dts - ist->next_dts) < FFABS(pkt_dts - ist->next_dts)/10) disable_discontinuity_correction = 0; @@ -2098,9 +2098,9 @@ static void ts_discontinuity_detect(InputFile *ifile, InputStream *ist, ist->file_index, ist->st->index, ist->st->id, av_get_media_type_string(ist->par->codec_type), delta, ifile->ts_offset_discont); - pkt->dts -= av_rescale_q(delta, AV_TIME_BASE_Q, ist->st->time_base); + pkt->dts -= av_rescale_q(delta, AV_TIME_BASE_Q, pkt->time_base); if (pkt->pts != AV_NOPTS_VALUE) - pkt->pts -= av_rescale_q(delta, AV_TIME_BASE_Q, ist->st->time_base); + pkt->pts -= av_rescale_q(delta, AV_TIME_BASE_Q, pkt->time_base); } } else { if (FFABS(delta) > 1LL * dts_error_threshold * AV_TIME_BASE) { @@ -2108,7 +2108,7 @@ static void ts_discontinuity_detect(InputFile *ifile, InputStream *ist, pkt->dts = AV_NOPTS_VALUE; } if (pkt->pts != AV_NOPTS_VALUE){ - int64_t pkt_pts = av_rescale_q(pkt->pts, ist->st->time_base, AV_TIME_BASE_Q); + int64_t pkt_pts = av_rescale_q(pkt->pts, pkt->time_base, AV_TIME_BASE_Q); delta = pkt_pts - ist->next_dts; if (FFABS(delta) > 1LL * dts_error_threshold * AV_TIME_BASE) { av_log(NULL, AV_LOG_WARNING, "PTS %"PRId64", next:%"PRId64" invalid dropping st:%d\n", pkt->pts, ist->next_dts, pkt->stream_index); @@ -2124,20 +2124,20 @@ static void ts_discontinuity_detect(InputFile *ifile, InputStream *ist, av_log(NULL, AV_LOG_DEBUG, "Inter stream timestamp discontinuity %"PRId64", new offset= %"PRId64"\n", delta, ifile->ts_offset_discont); - pkt->dts -= av_rescale_q(delta, AV_TIME_BASE_Q, ist->st->time_base); + pkt->dts -= av_rescale_q(delta, AV_TIME_BASE_Q, pkt->time_base); if (pkt->pts != AV_NOPTS_VALUE) - pkt->pts -= av_rescale_q(delta, AV_TIME_BASE_Q, ist->st->time_base); + pkt->pts -= av_rescale_q(delta, AV_TIME_BASE_Q, pkt->time_base); } } - ifile->last_ts = av_rescale_q(pkt->dts, ist->st->time_base, AV_TIME_BASE_Q); + ifile->last_ts = av_rescale_q(pkt->dts, pkt->time_base, AV_TIME_BASE_Q); } static void ts_discontinuity_process(InputFile *ifile, InputStream *ist, AVPacket *pkt) { int64_t offset = av_rescale_q(ifile->ts_offset_discont, AV_TIME_BASE_Q, - ist->st->time_base); + pkt->time_base); // apply previously-detected timestamp-discontinuity offset // (to all streams, not just audio/video) @@ -2245,9 +2245,9 @@ static int process_input(int file_index) av_log(NULL, AV_LOG_INFO, "demuxer+ffmpeg -> ist_index:%d:%d type:%s pkt_pts:%s pkt_pts_time:%s pkt_dts:%s pkt_dts_time:%s duration:%s duration_time:%s off:%s off_time:%s\n", ifile->index, pkt->stream_index, av_get_media_type_string(ist->par->codec_type), - av_ts2str(pkt->pts), av_ts2timestr(pkt->pts, &ist->st->time_base), - av_ts2str(pkt->dts), av_ts2timestr(pkt->dts, &ist->st->time_base), - av_ts2str(pkt->duration), av_ts2timestr(pkt->duration, &ist->st->time_base), + av_ts2str(pkt->pts), av_ts2timestr(pkt->pts, &pkt->time_base), + av_ts2str(pkt->dts), av_ts2timestr(pkt->dts, &pkt->time_base), + av_ts2str(pkt->duration), av_ts2timestr(pkt->duration, &pkt->time_base), av_ts2str(input_files[ist->file_index]->ts_offset), av_ts2timestr(input_files[ist->file_index]->ts_offset, &AV_TIME_BASE_Q)); } From 0fe5eaf69dab173448de67b06b5a8ce7caf90565 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Tue, 18 Apr 2023 10:02:00 +0200 Subject: [PATCH 0774/2172] fftools/ffmpeg_mux_init: consolidate handling -filter for audio/video --- fftools/ffmpeg_mux_init.c | 68 +++++++++++++++++---------------------- 1 file changed, 30 insertions(+), 38 deletions(-) diff --git a/fftools/ffmpeg_mux_init.c b/fftools/ffmpeg_mux_init.c index 89c0ac90ea5..7c35d6b5823 100644 --- a/fftools/ffmpeg_mux_init.c +++ b/fftools/ffmpeg_mux_init.c @@ -420,33 +420,36 @@ static MuxStream *mux_stream_alloc(Muxer *mux, enum AVMediaType type) return ms; } -static char *get_ost_filters(const OptionsContext *o, AVFormatContext *oc, - OutputStream *ost) +static int ost_get_filters(const OptionsContext *o, AVFormatContext *oc, + OutputStream *ost) { + MATCH_PER_STREAM_OPT(filter_scripts, str, ost->filters_script, oc, ost->st); + MATCH_PER_STREAM_OPT(filters, str, ost->filters, oc, ost->st); + + if (!ost->enc) { + if (ost->filters_script || ost->filters) { + av_log(ost, AV_LOG_ERROR, + "%s '%s' was specified, but codec copy was selected. " + "Filtering and streamcopy cannot be used together.\n", + ost->filters ? "Filtergraph" : "Filtergraph script", + ost->filters ? ost->filters : ost->filters_script); + return AVERROR(ENOSYS); + } + return 0; + } + if (ost->filters_script && ost->filters) { av_log(ost, AV_LOG_ERROR, "Both -filter and -filter_script set\n"); exit_program(1); } if (ost->filters_script) - return file_read(ost->filters_script); + ost->avfilter = file_read(ost->filters_script); else if (ost->filters) - return av_strdup(ost->filters); - - return av_strdup(ost->type == AVMEDIA_TYPE_VIDEO ? "null" : "anull"); -} - -static void check_streamcopy_filters(const OptionsContext *o, AVFormatContext *oc, - OutputStream *ost, enum AVMediaType type) -{ - if (ost->filters_script || ost->filters) { - av_log(ost, AV_LOG_ERROR, - "%s '%s' was defined, but codec copy was selected.\n" - "Filtering and streamcopy cannot be used together.\n", - ost->filters ? "Filtergraph" : "Filtergraph script", - ost->filters ? ost->filters : ost->filters_script); - exit_program(1); - } + ost->avfilter = av_strdup(ost->filters); + else + ost->avfilter = av_strdup(ost->type == AVMEDIA_TYPE_VIDEO ? "null" : "anull"); + return ost->avfilter ? 0 : AVERROR(ENOMEM); } static void parse_matrix_coeffs(void *logctx, uint16_t *dest, const char *str) @@ -504,9 +507,6 @@ static void new_stream_video(Muxer *mux, const OptionsContext *o, ost->frame_aspect_ratio = q; } - MATCH_PER_STREAM_OPT(filter_scripts, str, ost->filters_script, oc, st); - MATCH_PER_STREAM_OPT(filters, str, ost->filters, oc, st); - if (ost->enc_ctx) { AVCodecContext *video_enc = ost->enc_ctx; const char *p = NULL, *fps_mode = NULL; @@ -692,12 +692,7 @@ static void new_stream_video(Muxer *mux, const OptionsContext *o, } } ost->is_cfr = (ost->vsync_method == VSYNC_CFR || ost->vsync_method == VSYNC_VSCFR); - - ost->avfilter = get_ost_filters(o, oc, ost); - if (!ost->avfilter) - exit_program(1); - } else - check_streamcopy_filters(o, oc, ost, AVMEDIA_TYPE_VIDEO); + } } static void new_stream_audio(Muxer *mux, const OptionsContext *o, @@ -708,10 +703,6 @@ static void new_stream_audio(Muxer *mux, const OptionsContext *o, st = ost->st; - - MATCH_PER_STREAM_OPT(filter_scripts, str, ost->filters_script, oc, st); - MATCH_PER_STREAM_OPT(filters, str, ost->filters, oc, st); - if (ost->enc_ctx) { AVCodecContext *audio_enc = ost->enc_ctx; int channels = 0; @@ -757,10 +748,6 @@ static void new_stream_audio(Muxer *mux, const OptionsContext *o, MATCH_PER_STREAM_OPT(apad, str, ost->apad, oc, st); ost->apad = av_strdup(ost->apad); - ost->avfilter = get_ost_filters(o, oc, ost); - if (!ost->avfilter) - exit_program(1); - #if FFMPEG_OPT_MAP_CHANNEL /* check for channel mapping for this audio stream */ for (int n = 0; n < o->nb_audio_channel_maps; n++) { @@ -791,8 +778,7 @@ static void new_stream_audio(Muxer *mux, const OptionsContext *o, } } #endif - } else - check_streamcopy_filters(o, oc, ost, AVMEDIA_TYPE_AUDIO); + } } static void new_stream_data(Muxer *mux, const OptionsContext *o, @@ -1223,6 +1209,12 @@ static OutputStream *ost_add(Muxer *mux, const OptionsContext *o, default: new_stream_unknown (mux, o, ost); break; } + if (type == AVMEDIA_TYPE_VIDEO || type == AVMEDIA_TYPE_AUDIO) { + ret = ost_get_filters(o, oc, ost); + if (ret < 0) + exit_program(1); + } + if (ost->ist) { if (ost->enc && (type == AVMEDIA_TYPE_VIDEO || type == AVMEDIA_TYPE_AUDIO)) { From 84e1e0fa7361579affc24030d1ae7cdc22f112c1 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Tue, 18 Apr 2023 10:31:54 +0200 Subject: [PATCH 0775/2172] fftools/ffmpeg_mux_init: move check for mixing simple/complex filters Do it in ost_get_filters() together with other similar checks. Will be useful in following commits. Also, improve the log message. --- fftools/ffmpeg_mux_init.c | 25 +++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/fftools/ffmpeg_mux_init.c b/fftools/ffmpeg_mux_init.c index 7c35d6b5823..c82556a7060 100644 --- a/fftools/ffmpeg_mux_init.c +++ b/fftools/ffmpeg_mux_init.c @@ -438,6 +438,19 @@ static int ost_get_filters(const OptionsContext *o, AVFormatContext *oc, return 0; } + if (!ost->ist) { + if (ost->filters_script || ost->filters) { + av_log(ost, AV_LOG_ERROR, + "%s '%s' was specified for a stream fed from a complex " + "filtergraph. Simple and complex filtering cannot be used " + "together for the same stream.\n", + ost->filters ? "Filtergraph" : "Filtergraph script", + ost->filters ? ost->filters : ost->filters_script); + return AVERROR(EINVAL); + } + return 0; + } + if (ost->filters_script && ost->filters) { av_log(ost, AV_LOG_ERROR, "Both -filter and -filter_script set\n"); exit_program(1); @@ -1263,18 +1276,6 @@ static void init_output_filter(OutputFilter *ofilter, const OptionsContext *o, exit_program(1); } - if (ost->avfilter && (ost->filters || ost->filters_script)) { - const char *opt = ost->filters ? "-vf/-af/-filter" : "-filter_script"; - av_log(ost, AV_LOG_ERROR, - "%s '%s' was specified through the %s option " - "for output stream %d:%d, which is fed from a complex filtergraph.\n" - "%s and -filter_complex cannot be used together for the same stream.\n", - ost->filters ? "Filtergraph" : "Filtergraph script", - ost->filters ? ost->filters : ost->filters_script, - opt, ost->file_index, ost->index, opt); - exit_program(1); - } - avfilter_inout_free(&ofilter->out_tmp); } From ecb44ca8777c0323c4ed00f64465a4072188c959 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Tue, 18 Apr 2023 10:36:38 +0200 Subject: [PATCH 0776/2172] fftools/ffmpeg_mux_init: drop OutputStream.filters[_script] They are not needed outside of ost_get_filters(), so make them stack variables there. --- fftools/ffmpeg.h | 2 -- fftools/ffmpeg_mux_init.c | 28 +++++++++++++++------------- 2 files changed, 15 insertions(+), 15 deletions(-) diff --git a/fftools/ffmpeg.h b/fftools/ffmpeg.h index 72020c8f3a5..c9d499efdd2 100644 --- a/fftools/ffmpeg.h +++ b/fftools/ffmpeg.h @@ -639,8 +639,6 @@ typedef struct OutputStream { OutputFilter *filter; char *avfilter; - char *filters; ///< filtergraph associated to the -filter option - char *filters_script; ///< filtergraph script associated to the -filter_script option AVDictionary *encoder_opts; AVDictionary *sws_dict; diff --git a/fftools/ffmpeg_mux_init.c b/fftools/ffmpeg_mux_init.c index c82556a7060..da3dccd6d71 100644 --- a/fftools/ffmpeg_mux_init.c +++ b/fftools/ffmpeg_mux_init.c @@ -423,43 +423,45 @@ static MuxStream *mux_stream_alloc(Muxer *mux, enum AVMediaType type) static int ost_get_filters(const OptionsContext *o, AVFormatContext *oc, OutputStream *ost) { - MATCH_PER_STREAM_OPT(filter_scripts, str, ost->filters_script, oc, ost->st); - MATCH_PER_STREAM_OPT(filters, str, ost->filters, oc, ost->st); + const char *filters = NULL, *filters_script = NULL; + + MATCH_PER_STREAM_OPT(filter_scripts, str, filters_script, oc, ost->st); + MATCH_PER_STREAM_OPT(filters, str, filters, oc, ost->st); if (!ost->enc) { - if (ost->filters_script || ost->filters) { + if (filters_script || filters) { av_log(ost, AV_LOG_ERROR, "%s '%s' was specified, but codec copy was selected. " "Filtering and streamcopy cannot be used together.\n", - ost->filters ? "Filtergraph" : "Filtergraph script", - ost->filters ? ost->filters : ost->filters_script); + filters ? "Filtergraph" : "Filtergraph script", + filters ? filters : filters_script); return AVERROR(ENOSYS); } return 0; } if (!ost->ist) { - if (ost->filters_script || ost->filters) { + if (filters_script || filters) { av_log(ost, AV_LOG_ERROR, "%s '%s' was specified for a stream fed from a complex " "filtergraph. Simple and complex filtering cannot be used " "together for the same stream.\n", - ost->filters ? "Filtergraph" : "Filtergraph script", - ost->filters ? ost->filters : ost->filters_script); + filters ? "Filtergraph" : "Filtergraph script", + filters ? filters : filters_script); return AVERROR(EINVAL); } return 0; } - if (ost->filters_script && ost->filters) { + if (filters_script && filters) { av_log(ost, AV_LOG_ERROR, "Both -filter and -filter_script set\n"); exit_program(1); } - if (ost->filters_script) - ost->avfilter = file_read(ost->filters_script); - else if (ost->filters) - ost->avfilter = av_strdup(ost->filters); + if (filters_script) + ost->avfilter = file_read(filters_script); + else if (filters) + ost->avfilter = av_strdup(filters); else ost->avfilter = av_strdup(ost->type == AVMEDIA_TYPE_VIDEO ? "null" : "anull"); return ost->avfilter ? 0 : AVERROR(ENOMEM); From ab0d2052a3cfd14b616d1944fe11b66aab8ce2f8 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Tue, 18 Apr 2023 10:53:12 +0200 Subject: [PATCH 0777/2172] fftools/ffmpeg: remove unused function arguments --- fftools/ffmpeg_mux.c | 4 ++-- fftools/ffmpeg_mux_init.c | 9 ++++----- 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/fftools/ffmpeg_mux.c b/fftools/ffmpeg_mux.c index fddb783b000..a19f1a1f1e4 100644 --- a/fftools/ffmpeg_mux.c +++ b/fftools/ffmpeg_mux.c @@ -261,7 +261,7 @@ static int thread_submit_packet(Muxer *mux, OutputStream *ost, AVPacket *pkt) return ret == AVERROR_EOF ? 0 : ret; } -static int queue_packet(Muxer *mux, OutputStream *ost, AVPacket *pkt) +static int queue_packet(OutputStream *ost, AVPacket *pkt) { MuxStream *ms = ms_from_ost(ost); AVPacket *tmp_pkt = NULL; @@ -311,7 +311,7 @@ static int submit_packet(Muxer *mux, AVPacket *pkt, OutputStream *ost) return thread_submit_packet(mux, ost, pkt); } else { /* the muxer is not initialized yet, buffer the packet */ - ret = queue_packet(mux, ost, pkt); + ret = queue_packet(ost, pkt); if (ret < 0) { if (pkt) av_packet_unref(pkt); diff --git a/fftools/ffmpeg_mux_init.c b/fftools/ffmpeg_mux_init.c index da3dccd6d71..59d9a12c1ae 100644 --- a/fftools/ffmpeg_mux_init.c +++ b/fftools/ffmpeg_mux_init.c @@ -839,8 +839,7 @@ static void new_stream_subtitle(Muxer *mux, const OptionsContext *o, } } -static int streamcopy_init(const Muxer *mux, const OptionsContext *o, - OutputStream *ost) +static int streamcopy_init(const Muxer *mux, OutputStream *ost) { MuxStream *ms = ms_from_ost(ost); @@ -1244,7 +1243,7 @@ static OutputStream *ost_add(Muxer *mux, const OptionsContext *o, } if (ost->ist && !ost->enc) { - ret = streamcopy_init(mux, o, ost); + ret = streamcopy_init(mux, ost); if (ret < 0) exit_program(1); } @@ -1946,7 +1945,7 @@ static int copy_chapters(InputFile *ifile, OutputFile *ofile, AVFormatContext *o static int copy_metadata(Muxer *mux, AVFormatContext *ic, const char *outspec, const char *inspec, int *metadata_global_manual, int *metadata_streams_manual, - int *metadata_chapters_manual, const OptionsContext *o) + int *metadata_chapters_manual) { AVFormatContext *oc = mux->fc; AVDictionary **meta_in = NULL; @@ -2050,7 +2049,7 @@ static void copy_meta(Muxer *mux, const OptionsContext *o) in_file_index >= 0 ? input_files[in_file_index]->ctx : NULL, o->metadata_map[i].specifier, *p ? p + 1 : p, &metadata_global_manual, &metadata_streams_manual, - &metadata_chapters_manual, o); + &metadata_chapters_manual); } /* copy chapters */ From 6cace17b0d195a5637bcfba690aab8708a946b5d Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Tue, 18 Apr 2023 11:10:08 +0200 Subject: [PATCH 0778/2172] fftools/ffmpeg_mux_init: drop useless new_stream_{data,unknown} Their only function is checking that encoding was not specified for data/unknown-type streams, but the check is broken because enc_ctx will not be created in ost_add() unless a valid encoder can be found. Add an actually working check for all types for which encoding is not supported in choose_encoder(). --- fftools/ffmpeg_mux_init.c | 38 +++++++++++++++----------------------- 1 file changed, 15 insertions(+), 23 deletions(-) diff --git a/fftools/ffmpeg_mux_init.c b/fftools/ffmpeg_mux_init.c index 59d9a12c1ae..28254cb49b7 100644 --- a/fftools/ffmpeg_mux_init.c +++ b/fftools/ffmpeg_mux_init.c @@ -113,8 +113,21 @@ static int choose_encoder(const OptionsContext *o, AVFormatContext *s, *enc = NULL; - if (type == AVMEDIA_TYPE_VIDEO || type == AVMEDIA_TYPE_AUDIO || type == AVMEDIA_TYPE_SUBTITLE) { - MATCH_PER_STREAM_OPT(codec_names, str, codec_name, s, ost->st); + MATCH_PER_STREAM_OPT(codec_names, str, codec_name, s, ost->st); + + if (type != AVMEDIA_TYPE_VIDEO && + type != AVMEDIA_TYPE_AUDIO && + type != AVMEDIA_TYPE_SUBTITLE) { + if (codec_name && strcmp(codec_name, "copy")) { + const char *type_str = av_get_media_type_string(type); + av_log(ost, AV_LOG_FATAL, + "Encoder '%s' specified, but only '-codec copy' supported " + "for %s streams\n", codec_name, type_str); + return AVERROR(ENOSYS); + } + return 0; + } + if (!codec_name) { ost->par_in->codec_id = av_guess_codec(s->oformat, NULL, s->url, NULL, ost->type); @@ -130,7 +143,6 @@ static int choose_encoder(const OptionsContext *o, AVFormatContext *s, *enc = find_codec_or_die(ost, codec_name, ost->type, 1); ost->par_in->codec_id = (*enc)->id; } - } return 0; } @@ -796,24 +808,6 @@ static void new_stream_audio(Muxer *mux, const OptionsContext *o, } } -static void new_stream_data(Muxer *mux, const OptionsContext *o, - OutputStream *ost) -{ - if (ost->enc_ctx) { - av_log(ost, AV_LOG_FATAL, "Data stream encoding not supported yet (only streamcopy)\n"); - exit_program(1); - } -} - -static void new_stream_unknown(Muxer *mux, const OptionsContext *o, - OutputStream *ost) -{ - if (ost->enc_ctx) { - av_log(ost, AV_LOG_FATAL, "Unknown stream encoding not supported yet (only streamcopy)\n"); - exit_program(1); - } -} - static void new_stream_attachment(Muxer *mux, const OptionsContext *o, OutputStream *ost) { @@ -1218,9 +1212,7 @@ static OutputStream *ost_add(Muxer *mux, const OptionsContext *o, case AVMEDIA_TYPE_VIDEO: new_stream_video (mux, o, ost); break; case AVMEDIA_TYPE_AUDIO: new_stream_audio (mux, o, ost); break; case AVMEDIA_TYPE_SUBTITLE: new_stream_subtitle (mux, o, ost); break; - case AVMEDIA_TYPE_DATA: new_stream_data (mux, o, ost); break; case AVMEDIA_TYPE_ATTACHMENT: new_stream_attachment(mux, o, ost); break; - default: new_stream_unknown (mux, o, ost); break; } if (type == AVMEDIA_TYPE_VIDEO || type == AVMEDIA_TYPE_AUDIO) { From 2104de13e93fc91c99d9c0e5cac4147b67a900d7 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Tue, 18 Apr 2023 11:13:35 +0200 Subject: [PATCH 0779/2172] fftools/ffmpeg: reindent after previous commit --- fftools/ffmpeg_mux_init.c | 29 ++++++++++++++--------------- 1 file changed, 14 insertions(+), 15 deletions(-) diff --git a/fftools/ffmpeg_mux_init.c b/fftools/ffmpeg_mux_init.c index 28254cb49b7..ad5a4515819 100644 --- a/fftools/ffmpeg_mux_init.c +++ b/fftools/ffmpeg_mux_init.c @@ -128,21 +128,20 @@ static int choose_encoder(const OptionsContext *o, AVFormatContext *s, return 0; } - if (!codec_name) { - ost->par_in->codec_id = av_guess_codec(s->oformat, NULL, s->url, - NULL, ost->type); - *enc = avcodec_find_encoder(ost->par_in->codec_id); - if (!*enc) { - av_log(ost, AV_LOG_FATAL, "Automatic encoder selection failed " - "Default encoder for format %s (codec %s) is " - "probably disabled. Please choose an encoder manually.\n", - s->oformat->name, avcodec_get_name(ost->par_in->codec_id)); - return AVERROR_ENCODER_NOT_FOUND; - } - } else if (strcmp(codec_name, "copy")) { - *enc = find_codec_or_die(ost, codec_name, ost->type, 1); - ost->par_in->codec_id = (*enc)->id; - } + if (!codec_name) { + ost->par_in->codec_id = av_guess_codec(s->oformat, NULL, s->url, NULL, ost->type); + *enc = avcodec_find_encoder(ost->par_in->codec_id); + if (!*enc) { + av_log(ost, AV_LOG_FATAL, "Automatic encoder selection failed " + "Default encoder for format %s (codec %s) is " + "probably disabled. Please choose an encoder manually.\n", + s->oformat->name, avcodec_get_name(ost->par_in->codec_id)); + return AVERROR_ENCODER_NOT_FOUND; + } + } else if (strcmp(codec_name, "copy")) { + *enc = find_codec_or_die(ost, codec_name, ost->type, 1); + ost->par_in->codec_id = (*enc)->id; + } return 0; } From 8b56480652c83603a877c8e72c20c30c7de5b9cf Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Tue, 18 Apr 2023 14:11:03 +0200 Subject: [PATCH 0780/2172] fftools/ffmpeg_filter: add a function for creating a filtergraph Code creating a new filtergraph is currently duplicated in 3 places. This commit unifies it and moves towards making filtergraphs more self-contained. --- fftools/ffmpeg.h | 8 ++++++++ fftools/ffmpeg_filter.c | 18 +++++++++++++----- fftools/ffmpeg_opt.c | 14 +++++--------- 3 files changed, 26 insertions(+), 14 deletions(-) diff --git a/fftools/ffmpeg.h b/fftools/ffmpeg.h index c9d499efdd2..b181d433b06 100644 --- a/fftools/ffmpeg.h +++ b/fftools/ffmpeg.h @@ -803,6 +803,14 @@ int ifilter_parameters_from_frame(InputFilter *ifilter, const AVFrame *frame); int ifilter_parameters_from_codecpar(InputFilter *ifilter, AVCodecParameters *par); int ifilter_has_all_input_formats(FilterGraph *fg); +/** + * Create a new filtergraph in the global filtergraph list. + * + * @param graph_desc Graph description; an av_malloc()ed string, filtergraph + * takes ownership of it. + */ +FilterGraph *fg_create(char *graph_desc); + int ffmpeg_parse_options(int argc, char **argv); void enc_stats_write(OutputStream *ost, EncStats *es, diff --git a/fftools/ffmpeg_filter.c b/fftools/ffmpeg_filter.c index ea182089b1c..7b3d9a490f8 100644 --- a/fftools/ffmpeg_filter.c +++ b/fftools/ffmpeg_filter.c @@ -188,15 +188,26 @@ static OutputFilter *ofilter_alloc(FilterGraph *fg) return ofilter; } +FilterGraph *fg_create(char *graph_desc) +{ + FilterGraph *fg; + + fg = ALLOC_ARRAY_ELEM(filtergraphs, nb_filtergraphs); + fg->index = nb_filtergraphs - 1; + fg->graph_desc = graph_desc; + + return fg; +} + int init_simple_filtergraph(InputStream *ist, OutputStream *ost) { - FilterGraph *fg = av_mallocz(sizeof(*fg)); + FilterGraph *fg; OutputFilter *ofilter; InputFilter *ifilter; + fg = fg_create(NULL); if (!fg) report_and_exit(AVERROR(ENOMEM)); - fg->index = nb_filtergraphs; ofilter = ofilter_alloc(fg); ofilter->ost = ost; @@ -212,9 +223,6 @@ int init_simple_filtergraph(InputStream *ist, OutputStream *ost) if (!ifilter->frame_queue) report_and_exit(AVERROR(ENOMEM)); - GROW_ARRAY(filtergraphs, nb_filtergraphs); - filtergraphs[nb_filtergraphs - 1] = fg; - ist_filter_add(ist, ifilter, 1); return 0; diff --git a/fftools/ffmpeg_opt.c b/fftools/ffmpeg_opt.c index f811d38b9c8..c99263b6a5c 100644 --- a/fftools/ffmpeg_opt.c +++ b/fftools/ffmpeg_opt.c @@ -1106,26 +1106,22 @@ 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); - - fg->index = nb_filtergraphs - 1; - fg->graph_desc = av_strdup(arg); - if (!fg->graph_desc) + char *graph_desc = av_strdup(arg); + if (!graph_desc) return AVERROR(ENOMEM); + fg_create(graph_desc); + return 0; } static int opt_filter_complex_script(void *optctx, const char *opt, const char *arg) { - FilterGraph *fg; char *graph_desc = file_read(arg); if (!graph_desc) return AVERROR(EINVAL); - fg = ALLOC_ARRAY_ELEM(filtergraphs, nb_filtergraphs); - fg->index = nb_filtergraphs - 1; - fg->graph_desc = graph_desc; + fg_create(graph_desc); return 0; } From ea4c42779b42a27e088f060db1fd7d768f3ce598 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Tue, 18 Apr 2023 14:45:42 +0200 Subject: [PATCH 0781/2172] fftools/ffmpeg_mux_init: drop a redundant assignment OutputFilter.format is initialized in ofilter_alloc(). --- fftools/ffmpeg_mux_init.c | 1 - 1 file changed, 1 deletion(-) diff --git a/fftools/ffmpeg_mux_init.c b/fftools/ffmpeg_mux_init.c index ad5a4515819..1a639080745 100644 --- a/fftools/ffmpeg_mux_init.c +++ b/fftools/ffmpeg_mux_init.c @@ -1259,7 +1259,6 @@ static void init_output_filter(OutputFilter *ofilter, const OptionsContext *o, ost->filter = ofilter; ofilter->ost = ost; - ofilter->format = -1; if (!ost->enc_ctx) { av_log(ost, AV_LOG_ERROR, "Streamcopy requested for output stream fed " From 4800b5025820c87d149fda260eb03bf6f66c430c Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Tue, 18 Apr 2023 14:56:46 +0200 Subject: [PATCH 0782/2172] fftools/ffmpeg: simplify init_output_filter() --- fftools/ffmpeg_mux_init.c | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/fftools/ffmpeg_mux_init.c b/fftools/ffmpeg_mux_init.c index 1a639080745..db1f9fa9a66 100644 --- a/fftools/ffmpeg_mux_init.c +++ b/fftools/ffmpeg_mux_init.c @@ -1245,16 +1245,7 @@ static OutputStream *ost_add(Muxer *mux, const OptionsContext *o, static void init_output_filter(OutputFilter *ofilter, const OptionsContext *o, Muxer *mux) { - OutputStream *ost; - - switch (ofilter->type) { - case AVMEDIA_TYPE_VIDEO: ost = ost_add(mux, o, AVMEDIA_TYPE_VIDEO, NULL); break; - case AVMEDIA_TYPE_AUDIO: ost = ost_add(mux, o, AVMEDIA_TYPE_AUDIO, NULL); break; - default: - av_log(mux, AV_LOG_FATAL, "Only video and audio filters are supported " - "currently.\n"); - exit_program(1); - } + OutputStream *ost = ost_add(mux, o, ofilter->type, NULL); ost->filter = ofilter; From 0add05bd3ad93f3672cdf1004f30e96d29a5c470 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Tue, 18 Apr 2023 15:00:11 +0200 Subject: [PATCH 0783/2172] fftools/ffmpeg_mux_init: rename init_output_filter() to ost_add_from_filter() The previous name is misleading, because the function does not actually initialize any filters - it creates a new output stream and binds a filtergraph output to it. --- fftools/ffmpeg_mux_init.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/fftools/ffmpeg_mux_init.c b/fftools/ffmpeg_mux_init.c index db1f9fa9a66..7a2db9f0e83 100644 --- a/fftools/ffmpeg_mux_init.c +++ b/fftools/ffmpeg_mux_init.c @@ -1242,7 +1242,8 @@ static OutputStream *ost_add(Muxer *mux, const OptionsContext *o, return ost; } -static void init_output_filter(OutputFilter *ofilter, const OptionsContext *o, +// add a new output stream fed by the provided filtergraph output +static void ost_add_from_filter(OutputFilter *ofilter, const OptionsContext *o, Muxer *mux) { OutputStream *ost = ost_add(mux, o, ofilter->type, NULL); @@ -1438,7 +1439,7 @@ static void map_manual(Muxer *mux, const OptionsContext *o, const StreamMap *map "in any defined filter graph, or was already used elsewhere.\n", map->linklabel); exit_program(1); } - init_output_filter(ofilter, o, mux); + ost_add_from_filter(ofilter, o, mux); } else { ist = input_files[map->file_index]->streams[map->stream_index]; if (ist->user_set_discard == AVDISCARD_ALL) { @@ -1537,7 +1538,7 @@ static void create_streams(Muxer *mux, const OptionsContext *o) case AVMEDIA_TYPE_AUDIO: auto_disable_a = 1; break; case AVMEDIA_TYPE_SUBTITLE: auto_disable_s = 1; break; } - init_output_filter(ofilter, o, mux); + ost_add_from_filter(ofilter, o, mux); } } From eb9ce9de3ba4422d781c79fb53c9f86cfddcc58b Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Tue, 18 Apr 2023 15:24:46 +0200 Subject: [PATCH 0784/2172] fftools/ffmpeg: move filtering functions to ffmpeg_filter --- fftools/ffmpeg.c | 216 +--------------------------------------- fftools/ffmpeg.h | 20 ++++ fftools/ffmpeg_filter.c | 202 +++++++++++++++++++++++++++++++++++++ 3 files changed, 223 insertions(+), 215 deletions(-) diff --git a/fftools/ffmpeg.c b/fftools/ffmpeg.c index 94c2568efb6..5bcb76ac554 100644 --- a/fftools/ffmpeg.c +++ b/fftools/ffmpeg.c @@ -651,66 +651,6 @@ void close_output_stream(OutputStream *ost) sq_send(of->sq_encode, ost->sq_idx_encode, SQFRAME(NULL)); } -/** - * Get and encode new output from any of the filtergraphs, without causing - * activity. - * - * @return 0 for success, <0 for severe errors - */ -static int reap_filters(int flush) -{ - AVFrame *filtered_frame = NULL; - - /* Reap all buffers present in the buffer sinks */ - for (OutputStream *ost = ost_iter(NULL); ost; ost = ost_iter(ost)) { - AVFilterContext *filter; - int ret = 0; - - if (!ost->filter || !ost->filter->graph->graph) - continue; - filter = ost->filter->filter; - - filtered_frame = ost->filtered_frame; - - while (1) { - ret = av_buffersink_get_frame_flags(filter, filtered_frame, - AV_BUFFERSINK_FLAG_NO_REQUEST); - if (ret < 0) { - if (ret != AVERROR(EAGAIN) && ret != AVERROR_EOF) { - av_log(NULL, AV_LOG_WARNING, - "Error in av_buffersink_get_frame_flags(): %s\n", av_err2str(ret)); - } else if (flush && ret == AVERROR_EOF) { - if (av_buffersink_get_type(filter) == AVMEDIA_TYPE_VIDEO) - enc_frame(ost, NULL); - } - break; - } - if (ost->finished) { - av_frame_unref(filtered_frame); - continue; - } - - if (filtered_frame->pts != AV_NOPTS_VALUE) { - AVRational tb = av_buffersink_get_time_base(filter); - ost->filter->last_pts = av_rescale_q(filtered_frame->pts, tb, - AV_TIME_BASE_Q); - filtered_frame->time_base = tb; - - if (debug_ts) - av_log(NULL, AV_LOG_INFO, "filter_raw -> pts:%s pts_time:%s time_base:%d/%d\n", - av_ts2str(filtered_frame->pts), - av_ts2timestr(filtered_frame->pts, &tb), - tb.num, tb.den); - } - - enc_frame(ost, filtered_frame); - av_frame_unref(filtered_frame); - } - } - - return 0; -} - static void print_report(int is_last_report, int64_t timer_start, int64_t cur_time) { AVBPrint buf, buf_script; @@ -914,112 +854,6 @@ int ifilter_has_all_input_formats(FilterGraph *fg) return 1; } -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; - - switch (ifilter->ist->par->codec_type) { - case AVMEDIA_TYPE_AUDIO: - need_reinit |= ifilter->sample_rate != frame->sample_rate || - av_channel_layout_compare(&ifilter->ch_layout, &frame->ch_layout); - break; - case AVMEDIA_TYPE_VIDEO: - need_reinit |= ifilter->width != frame->width || - ifilter->height != frame->height; - break; - } - - if (!ifilter->ist->reinit_filters && fg->graph) - need_reinit = 0; - - if (!!ifilter->hw_frames_ctx != !!frame->hw_frames_ctx || - (ifilter->hw_frames_ctx && ifilter->hw_frames_ctx->data != frame->hw_frames_ctx->data)) - need_reinit = 1; - - if (sd = av_frame_get_side_data(frame, AV_FRAME_DATA_DISPLAYMATRIX)) { - if (!ifilter->displaymatrix || memcmp(sd->data, ifilter->displaymatrix, sizeof(int32_t) * 9)) - need_reinit = 1; - } else if (ifilter->displaymatrix) - need_reinit = 1; - - if (need_reinit) { - ret = ifilter_parameters_from_frame(ifilter, frame); - if (ret < 0) - return ret; - } - - /* (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); - - ret = av_fifo_write(ifilter->frame_queue, &tmp, 1); - if (ret < 0) - av_frame_free(&tmp); - - return ret; - } - - ret = reap_filters(1); - if (ret < 0 && ret != AVERROR_EOF) { - av_log(NULL, AV_LOG_ERROR, "Error while filtering: %s\n", av_err2str(ret)); - return ret; - } - - ret = configure_filtergraph(fg); - if (ret < 0) { - av_log(NULL, AV_LOG_ERROR, "Error reinitializing filters!\n"); - return ret; - } - } - - 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)); - return ret; - } - - return 0; -} - -static int ifilter_send_eof(InputFilter *ifilter, int64_t pts) -{ - int ret; - - ifilter->eof = 1; - - if (ifilter->filter) { - ret = av_buffersrc_close(ifilter->filter, pts, AV_BUFFERSRC_FLAG_PUSH); - if (ret < 0) - return ret; - } else { - // the filtergraph was never configured - if (ifilter->format < 0) { - ret = ifilter_parameters_from_codecpar(ifilter, ifilter->ist->par); - if (ret < 0) - return ret; - } - if (ifilter->format < 0 && (ifilter->type == AVMEDIA_TYPE_AUDIO || ifilter->type == AVMEDIA_TYPE_VIDEO)) { - av_log(NULL, AV_LOG_ERROR, "Cannot determine format of input stream %d:%d after EOF\n", ifilter->ist->file_index, ifilter->ist->st->index); - return AVERROR_INVALIDDATA; - } - } - - return 0; -} - // This does not quite work like avcodec_decode_audio4/avcodec_decode_video2. // There is the following difference: if you got a frame, you must call // it again with pkt=NULL. pkt==NULL is treated differently from pkt->size==0 @@ -2262,54 +2096,6 @@ static int process_input(int file_index) return 0; } -/** - * Perform a step of transcoding for the specified filter graph. - * - * @param[in] graph filter graph to consider - * @param[out] best_ist input stream where a frame would allow to continue - * @return 0 for success, <0 for error - */ -static int transcode_from_filter(FilterGraph *graph, InputStream **best_ist) -{ - int i, ret; - int nb_requests, nb_requests_max = 0; - InputFilter *ifilter; - InputStream *ist; - - *best_ist = NULL; - ret = avfilter_graph_request_oldest(graph->graph); - if (ret >= 0) - return reap_filters(0); - - if (ret == AVERROR_EOF) { - ret = reap_filters(1); - for (i = 0; i < graph->nb_outputs; i++) - close_output_stream(graph->outputs[i]->ost); - return ret; - } - if (ret != AVERROR(EAGAIN)) - return ret; - - for (i = 0; i < graph->nb_inputs; i++) { - ifilter = graph->inputs[i]; - ist = ifilter->ist; - if (input_files[ist->file_index]->eagain || - input_files[ist->file_index]->eof_reached) - continue; - nb_requests = av_buffersrc_get_nb_failed_requests(ifilter->filter); - if (nb_requests > nb_requests_max) { - nb_requests_max = nb_requests; - *best_ist = ist; - } - } - - if (!*best_ist) - for (i = 0; i < graph->nb_outputs; i++) - graph->outputs[i]->ost->unavailable = 1; - - return 0; -} - /** * Run a single step of transcoding. * @@ -2343,7 +2129,7 @@ static int transcode_step(void) } if (ost->filter && ost->filter->graph->graph) { - if ((ret = transcode_from_filter(ost->filter->graph, &ist)) < 0) + if ((ret = fg_transcode_step(ost->filter->graph, &ist)) < 0) return ret; if (!ist) return 0; diff --git a/fftools/ffmpeg.h b/fftools/ffmpeg.h index b181d433b06..07c1fc7ed6d 100644 --- a/fftools/ffmpeg.h +++ b/fftools/ffmpeg.h @@ -799,6 +799,9 @@ int init_complex_filtergraph(FilterGraph *fg); void sub2video_update(InputStream *ist, int64_t heartbeat_pts, AVSubtitle *sub); +int ifilter_send_frame(InputFilter *ifilter, AVFrame *frame, int keep_reference); +int ifilter_send_eof(InputFilter *ifilter, int64_t pts); + int ifilter_parameters_from_frame(InputFilter *ifilter, const AVFrame *frame); int ifilter_parameters_from_codecpar(InputFilter *ifilter, AVCodecParameters *par); int ifilter_has_all_input_formats(FilterGraph *fg); @@ -811,6 +814,23 @@ int ifilter_has_all_input_formats(FilterGraph *fg); */ FilterGraph *fg_create(char *graph_desc); +/** + * Perform a step of transcoding for the specified filter graph. + * + * @param[in] graph filter graph to consider + * @param[out] best_ist input stream where a frame would allow to continue + * @return 0 for success, <0 for error + */ +int fg_transcode_step(FilterGraph *graph, InputStream **best_ist); + +/** + * Get and encode new output from any of the filtergraphs, without causing + * activity. + * + * @return 0 for success, <0 for severe errors + */ +int reap_filters(int flush); + int ffmpeg_parse_options(int argc, char **argv); void enc_stats_write(OutputStream *ost, EncStats *es, diff --git a/fftools/ffmpeg_filter.c b/fftools/ffmpeg_filter.c index 7b3d9a490f8..c39cf437749 100644 --- a/fftools/ffmpeg_filter.c +++ b/fftools/ffmpeg_filter.c @@ -36,6 +36,7 @@ #include "libavutil/pixfmt.h" #include "libavutil/imgutils.h" #include "libavutil/samplefmt.h" +#include "libavutil/timestamp.h" // FIXME: YUV420P etc. are actually supported with full color range, // yet the latter information isn't available here. @@ -1300,3 +1301,204 @@ int filtergraph_is_simple(FilterGraph *fg) { return !fg->graph_desc; } + +int reap_filters(int flush) +{ + AVFrame *filtered_frame = NULL; + + /* Reap all buffers present in the buffer sinks */ + for (OutputStream *ost = ost_iter(NULL); ost; ost = ost_iter(ost)) { + AVFilterContext *filter; + int ret = 0; + + if (!ost->filter || !ost->filter->graph->graph) + continue; + filter = ost->filter->filter; + + filtered_frame = ost->filtered_frame; + + while (1) { + ret = av_buffersink_get_frame_flags(filter, filtered_frame, + AV_BUFFERSINK_FLAG_NO_REQUEST); + if (ret < 0) { + if (ret != AVERROR(EAGAIN) && ret != AVERROR_EOF) { + av_log(NULL, AV_LOG_WARNING, + "Error in av_buffersink_get_frame_flags(): %s\n", av_err2str(ret)); + } else if (flush && ret == AVERROR_EOF) { + if (av_buffersink_get_type(filter) == AVMEDIA_TYPE_VIDEO) + enc_frame(ost, NULL); + } + break; + } + if (ost->finished) { + av_frame_unref(filtered_frame); + continue; + } + + if (filtered_frame->pts != AV_NOPTS_VALUE) { + AVRational tb = av_buffersink_get_time_base(filter); + ost->filter->last_pts = av_rescale_q(filtered_frame->pts, tb, + AV_TIME_BASE_Q); + filtered_frame->time_base = tb; + + if (debug_ts) + av_log(NULL, AV_LOG_INFO, "filter_raw -> pts:%s pts_time:%s time_base:%d/%d\n", + av_ts2str(filtered_frame->pts), + av_ts2timestr(filtered_frame->pts, &tb), + tb.num, tb.den); + } + + enc_frame(ost, filtered_frame); + av_frame_unref(filtered_frame); + } + } + + return 0; +} + +int ifilter_send_eof(InputFilter *ifilter, int64_t pts) +{ + int ret; + + ifilter->eof = 1; + + if (ifilter->filter) { + ret = av_buffersrc_close(ifilter->filter, pts, AV_BUFFERSRC_FLAG_PUSH); + if (ret < 0) + return ret; + } else { + // the filtergraph was never configured + if (ifilter->format < 0) { + ret = ifilter_parameters_from_codecpar(ifilter, ifilter->ist->par); + if (ret < 0) + return ret; + } + if (ifilter->format < 0 && (ifilter->type == AVMEDIA_TYPE_AUDIO || ifilter->type == AVMEDIA_TYPE_VIDEO)) { + av_log(NULL, AV_LOG_ERROR, "Cannot determine format of input stream %d:%d after EOF\n", ifilter->ist->file_index, ifilter->ist->st->index); + return AVERROR_INVALIDDATA; + } + } + + return 0; +} + +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; + + switch (ifilter->ist->par->codec_type) { + case AVMEDIA_TYPE_AUDIO: + need_reinit |= ifilter->sample_rate != frame->sample_rate || + av_channel_layout_compare(&ifilter->ch_layout, &frame->ch_layout); + break; + case AVMEDIA_TYPE_VIDEO: + need_reinit |= ifilter->width != frame->width || + ifilter->height != frame->height; + break; + } + + if (!ifilter->ist->reinit_filters && fg->graph) + need_reinit = 0; + + if (!!ifilter->hw_frames_ctx != !!frame->hw_frames_ctx || + (ifilter->hw_frames_ctx && ifilter->hw_frames_ctx->data != frame->hw_frames_ctx->data)) + need_reinit = 1; + + if (sd = av_frame_get_side_data(frame, AV_FRAME_DATA_DISPLAYMATRIX)) { + if (!ifilter->displaymatrix || memcmp(sd->data, ifilter->displaymatrix, sizeof(int32_t) * 9)) + need_reinit = 1; + } else if (ifilter->displaymatrix) + need_reinit = 1; + + if (need_reinit) { + ret = ifilter_parameters_from_frame(ifilter, frame); + if (ret < 0) + return ret; + } + + /* (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); + + ret = av_fifo_write(ifilter->frame_queue, &tmp, 1); + if (ret < 0) + av_frame_free(&tmp); + + return ret; + } + + ret = reap_filters(1); + if (ret < 0 && ret != AVERROR_EOF) { + av_log(NULL, AV_LOG_ERROR, "Error while filtering: %s\n", av_err2str(ret)); + return ret; + } + + ret = configure_filtergraph(fg); + if (ret < 0) { + av_log(NULL, AV_LOG_ERROR, "Error reinitializing filters!\n"); + return ret; + } + } + + 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)); + return ret; + } + + return 0; +} + +int fg_transcode_step(FilterGraph *graph, InputStream **best_ist) +{ + int i, ret; + int nb_requests, nb_requests_max = 0; + InputFilter *ifilter; + InputStream *ist; + + *best_ist = NULL; + ret = avfilter_graph_request_oldest(graph->graph); + if (ret >= 0) + return reap_filters(0); + + if (ret == AVERROR_EOF) { + ret = reap_filters(1); + for (i = 0; i < graph->nb_outputs; i++) + close_output_stream(graph->outputs[i]->ost); + return ret; + } + if (ret != AVERROR(EAGAIN)) + return ret; + + for (i = 0; i < graph->nb_inputs; i++) { + ifilter = graph->inputs[i]; + ist = ifilter->ist; + if (input_files[ist->file_index]->eagain || + input_files[ist->file_index]->eof_reached) + continue; + nb_requests = av_buffersrc_get_nb_failed_requests(ifilter->filter); + if (nb_requests > nb_requests_max) { + nb_requests_max = nb_requests; + *best_ist = ist; + } + } + + if (!*best_ist) + for (i = 0; i < graph->nb_outputs; i++) + graph->outputs[i]->ost->unavailable = 1; + + return 0; +} From cc7a8ddf56468a2d96c284a5737fd85a05811a3e Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Tue, 18 Apr 2023 19:41:48 +0200 Subject: [PATCH 0785/2172] fftools/ffmpeg: move freeing a filtergraph into a separate function --- fftools/ffmpeg.c | 42 +++------------------------------------ fftools/ffmpeg.h | 2 ++ fftools/ffmpeg_filter.c | 44 +++++++++++++++++++++++++++++++++++++++++ 3 files changed, 49 insertions(+), 39 deletions(-) diff --git a/fftools/ffmpeg.c b/fftools/ffmpeg.c index 5bcb76ac554..15fe839914f 100644 --- a/fftools/ffmpeg.c +++ b/fftools/ffmpeg.c @@ -487,51 +487,15 @@ const AVIOInterruptCB int_cb = { decode_interrupt_cb, NULL }; static void ffmpeg_cleanup(int ret) { - int i, j; + int i; if (do_benchmark) { int maxrss = getmaxrss() / 1024; av_log(NULL, AV_LOG_INFO, "bench: maxrss=%ikB\n", maxrss); } - for (i = 0; i < nb_filtergraphs; i++) { - FilterGraph *fg = filtergraphs[i]; - avfilter_graph_free(&fg->graph); - for (j = 0; j < fg->nb_inputs; j++) { - InputFilter *ifilter = fg->inputs[j]; - struct InputStream *ist = ifilter->ist; - - if (ifilter->frame_queue) { - AVFrame *frame; - while (av_fifo_read(ifilter->frame_queue, &frame, 1) >= 0) - av_frame_free(&frame); - av_fifo_freep2(&ifilter->frame_queue); - } - av_freep(&ifilter->displaymatrix); - if (ist->sub2video.sub_queue) { - AVSubtitle sub; - while (av_fifo_read(ist->sub2video.sub_queue, &sub, 1) >= 0) - avsubtitle_free(&sub); - av_fifo_freep2(&ist->sub2video.sub_queue); - } - av_buffer_unref(&ifilter->hw_frames_ctx); - av_freep(&ifilter->name); - av_freep(&fg->inputs[j]); - } - av_freep(&fg->inputs); - for (j = 0; j < fg->nb_outputs; j++) { - OutputFilter *ofilter = fg->outputs[j]; - - avfilter_inout_free(&ofilter->out_tmp); - av_freep(&ofilter->name); - av_channel_layout_uninit(&ofilter->ch_layout); - av_freep(&fg->outputs[j]); - } - av_freep(&fg->outputs); - av_freep(&fg->graph_desc); - - av_freep(&filtergraphs[i]); - } + for (i = 0; i < nb_filtergraphs; i++) + fg_free(&filtergraphs[i]); av_freep(&filtergraphs); /* close files */ diff --git a/fftools/ffmpeg.h b/fftools/ffmpeg.h index 07c1fc7ed6d..95591f4bbad 100644 --- a/fftools/ffmpeg.h +++ b/fftools/ffmpeg.h @@ -814,6 +814,8 @@ int ifilter_has_all_input_formats(FilterGraph *fg); */ FilterGraph *fg_create(char *graph_desc); +void fg_free(FilterGraph **pfg); + /** * Perform a step of transcoding for the specified filter graph. * diff --git a/fftools/ffmpeg_filter.c b/fftools/ffmpeg_filter.c index c39cf437749..cfd93a0f9df 100644 --- a/fftools/ffmpeg_filter.c +++ b/fftools/ffmpeg_filter.c @@ -189,6 +189,50 @@ static OutputFilter *ofilter_alloc(FilterGraph *fg) return ofilter; } +void fg_free(FilterGraph **pfg) +{ + FilterGraph *fg = *pfg; + + if (!fg) + return; + + avfilter_graph_free(&fg->graph); + for (int j = 0; j < fg->nb_inputs; j++) { + InputFilter *ifilter = fg->inputs[j]; + struct InputStream *ist = ifilter->ist; + + if (ifilter->frame_queue) { + AVFrame *frame; + while (av_fifo_read(ifilter->frame_queue, &frame, 1) >= 0) + av_frame_free(&frame); + av_fifo_freep2(&ifilter->frame_queue); + } + av_freep(&ifilter->displaymatrix); + if (ist->sub2video.sub_queue) { + AVSubtitle sub; + while (av_fifo_read(ist->sub2video.sub_queue, &sub, 1) >= 0) + avsubtitle_free(&sub); + av_fifo_freep2(&ist->sub2video.sub_queue); + } + av_buffer_unref(&ifilter->hw_frames_ctx); + av_freep(&ifilter->name); + av_freep(&fg->inputs[j]); + } + av_freep(&fg->inputs); + for (int j = 0; j < fg->nb_outputs; j++) { + OutputFilter *ofilter = fg->outputs[j]; + + avfilter_inout_free(&ofilter->out_tmp); + av_freep(&ofilter->name); + av_channel_layout_uninit(&ofilter->ch_layout); + av_freep(&fg->outputs[j]); + } + av_freep(&fg->outputs); + av_freep(&fg->graph_desc); + + av_freep(pfg); +} + FilterGraph *fg_create(char *graph_desc) { FilterGraph *fg; From 11872522b1c3ee3fe1e7fe2aaa4ab680a9d868fd Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Tue, 18 Apr 2023 19:43:14 +0200 Subject: [PATCH 0786/2172] fftools/ffmpeg_filter: reindent after previous commit --- fftools/ffmpeg_filter.c | 62 ++++++++++++++++++++--------------------- 1 file changed, 31 insertions(+), 31 deletions(-) diff --git a/fftools/ffmpeg_filter.c b/fftools/ffmpeg_filter.c index cfd93a0f9df..b26160b3756 100644 --- a/fftools/ffmpeg_filter.c +++ b/fftools/ffmpeg_filter.c @@ -196,39 +196,39 @@ void fg_free(FilterGraph **pfg) if (!fg) return; - avfilter_graph_free(&fg->graph); - for (int j = 0; j < fg->nb_inputs; j++) { - InputFilter *ifilter = fg->inputs[j]; - struct InputStream *ist = ifilter->ist; - - if (ifilter->frame_queue) { - AVFrame *frame; - while (av_fifo_read(ifilter->frame_queue, &frame, 1) >= 0) - av_frame_free(&frame); - av_fifo_freep2(&ifilter->frame_queue); - } - av_freep(&ifilter->displaymatrix); - if (ist->sub2video.sub_queue) { - AVSubtitle sub; - while (av_fifo_read(ist->sub2video.sub_queue, &sub, 1) >= 0) - avsubtitle_free(&sub); - av_fifo_freep2(&ist->sub2video.sub_queue); - } - av_buffer_unref(&ifilter->hw_frames_ctx); - av_freep(&ifilter->name); - av_freep(&fg->inputs[j]); + avfilter_graph_free(&fg->graph); + for (int j = 0; j < fg->nb_inputs; j++) { + InputFilter *ifilter = fg->inputs[j]; + struct InputStream *ist = ifilter->ist; + + if (ifilter->frame_queue) { + AVFrame *frame; + while (av_fifo_read(ifilter->frame_queue, &frame, 1) >= 0) + av_frame_free(&frame); + av_fifo_freep2(&ifilter->frame_queue); } - av_freep(&fg->inputs); - for (int j = 0; j < fg->nb_outputs; j++) { - OutputFilter *ofilter = fg->outputs[j]; - - avfilter_inout_free(&ofilter->out_tmp); - av_freep(&ofilter->name); - av_channel_layout_uninit(&ofilter->ch_layout); - av_freep(&fg->outputs[j]); + av_freep(&ifilter->displaymatrix); + if (ist->sub2video.sub_queue) { + AVSubtitle sub; + while (av_fifo_read(ist->sub2video.sub_queue, &sub, 1) >= 0) + avsubtitle_free(&sub); + av_fifo_freep2(&ist->sub2video.sub_queue); } - av_freep(&fg->outputs); - av_freep(&fg->graph_desc); + av_buffer_unref(&ifilter->hw_frames_ctx); + av_freep(&ifilter->name); + av_freep(&fg->inputs[j]); + } + av_freep(&fg->inputs); + for (int j = 0; j < fg->nb_outputs; j++) { + OutputFilter *ofilter = fg->outputs[j]; + + avfilter_inout_free(&ofilter->out_tmp); + av_freep(&ofilter->name); + av_channel_layout_uninit(&ofilter->ch_layout); + av_freep(&fg->outputs[j]); + } + av_freep(&fg->outputs); + av_freep(&fg->graph_desc); av_freep(pfg); } From 0b352e350e773673f11ea380f3507923c70e1175 Mon Sep 17 00:00:00 2001 From: Carl Eugen Hoyos Date: Sun, 23 Apr 2023 18:21:06 -0400 Subject: [PATCH 0787/2172] avcodec/mjpegdec: support more pixel formats Support pixel formats 0x11412100, 0x11311100, and 0x41211100, and add logic to perform 4x horizontal upsampling. This should fix various JPEG files found in Ticket #8930. Co-authored-by: --- libavcodec/mjpegdec.c | 42 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) diff --git a/libavcodec/mjpegdec.c b/libavcodec/mjpegdec.c index 9b55002c4b7..72d654080d3 100644 --- a/libavcodec/mjpegdec.c +++ b/libavcodec/mjpegdec.c @@ -545,6 +545,18 @@ int ff_mjpeg_decode_sof(MJpegDecodeContext *s) } av_assert0(s->nb_components == 4); break; + case 0x11412100: + if (s->bits > 8) + goto unk_pixfmt; + if (s->component_id[0] == 'R' && s->component_id[1] == 'G' && s->component_id[2] == 'B') { + s->avctx->pix_fmt = AV_PIX_FMT_GBRP; + s->upscale_h[0] = 4; + s->upscale_h[1] = 0; + s->upscale_h[2] = 1; + } else { + goto unk_pixfmt; + } + break; case 0x22111122: case 0x22111111: if (s->adobe_transform == 0 && s->bits <= 8) { @@ -626,6 +638,15 @@ int ff_mjpeg_decode_sof(MJpegDecodeContext *s) s->avctx->color_range = s->cs_itu601 ? AVCOL_RANGE_MPEG : AVCOL_RANGE_JPEG; } break; + case 0x11311100: + if (s->bits > 8) + goto unk_pixfmt; + if (s->component_id[0] == 'R' && s->component_id[1] == 'G' && s->component_id[2] == 'B') + s->avctx->pix_fmt = AV_PIX_FMT_GBRP; + else + goto unk_pixfmt; + s->upscale_h[0] = s->upscale_h[2] = 2; + break; case 0x31111100: if (s->bits > 8) goto unk_pixfmt; @@ -635,6 +656,7 @@ int ff_mjpeg_decode_sof(MJpegDecodeContext *s) break; case 0x22121100: case 0x22111200: + case 0x41211100: if (s->bits <= 8) s->avctx->pix_fmt = s->cs_itu601 ? AV_PIX_FMT_YUV422P : AV_PIX_FMT_YUVJ422P; else goto unk_pixfmt; @@ -2605,6 +2627,8 @@ int ff_mjpeg_decode_frame_from_buf(AVCodecContext *avctx, AVFrame *frame, avctx->pix_fmt == AV_PIX_FMT_YUVJ440P || avctx->pix_fmt == AV_PIX_FMT_YUV440P || avctx->pix_fmt == AV_PIX_FMT_YUVA444P || + avctx->pix_fmt == AV_PIX_FMT_YUVJ422P || + avctx->pix_fmt == AV_PIX_FMT_YUV422P || avctx->pix_fmt == AV_PIX_FMT_YUVJ420P || avctx->pix_fmt == AV_PIX_FMT_YUV420P || avctx->pix_fmt == AV_PIX_FMT_YUV420P16|| @@ -2654,6 +2678,24 @@ int ff_mjpeg_decode_frame_from_buf(AVCodecContext *avctx, AVFrame *frame, for (index = w - 3; index > 0; index--) { line[index] = (line[index / 3] + line[(index + 1) / 3] + line[(index + 2) / 3] + 1) / 3; } + } else if (s->upscale_h[p] == 4){ + if (is16bit) { + uint16_t *line16 = (uint16_t *) line; + line16[w - 1] = line16[(w - 1) >> 2]; + if (w > 1) + line16[w - 2] = (line16[(w - 1) >> 2] * 3 + line16[(w - 2) >> 2]) >> 2; + if (w > 2) + line16[w - 3] = (line16[(w - 1) >> 2] + line16[(w - 2) >> 2]) >> 1; + } else { + line[w - 1] = line[(w - 1) >> 2]; + if (w > 1) + line[w - 2] = (line[(w - 1) >> 2] * 3 + line[(w - 2) >> 2]) >> 2; + if (w > 2) + line[w - 3] = (line[(w - 1) >> 2] + line[(w - 2) >> 2]) >> 1; + } + for (index = w - 4; index > 0; index--) + line[index] = (line[(index + 3) >> 2] + line[(index + 2) >> 2] + + line[(index + 1) >> 2] + line[index >> 2]) >> 2; } line += s->linesize[p]; } From a0cb29261cddb2b62ee57fbeb689a0234f0cc735 Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Mon, 24 Apr 2023 17:31:18 +0200 Subject: [PATCH 0788/2172] avfilter/af_afir: cache xfade coefficients --- libavfilter/af_afir.c | 37 +++++++++++++++++++++++++++++++++++-- libavfilter/af_afir.h | 1 + libavfilter/afir_template.c | 6 ++++-- 3 files changed, 40 insertions(+), 4 deletions(-) diff --git a/libavfilter/af_afir.c b/libavfilter/af_afir.c index fab751cb9fb..4acc24ccac9 100644 --- a/libavfilter/af_afir.c +++ b/libavfilter/af_afir.c @@ -298,8 +298,6 @@ static int convert_coeffs(AVFilterContext *ctx, int selir) part_size = 1 << av_log2(s->minp); max_part_size = 1 << av_log2(s->maxp); - s->min_part_size = part_size; - for (int i = 0; left > 0; i++) { int step = part_size == max_part_size ? INT_MAX : 1 + (i == 0); int nb_partitions = FFMIN(step, (left + part_size - 1) / part_size); @@ -592,6 +590,36 @@ FF_ENABLE_DEPRECATION_WARNINGS if (!s->loading) return AVERROR(ENOMEM); + s->xfade[0] = ff_get_audio_buffer(outlink, s->min_part_size); + s->xfade[1] = ff_get_audio_buffer(outlink, s->min_part_size); + if (!s->xfade[0] || !s->xfade[1]) + return AVERROR(ENOMEM); + + switch (s->format) { + case AV_SAMPLE_FMT_FLTP: + for (int ch = 0; ch < s->nb_channels; ch++) { + float *dst0 = (float *)s->xfade[0]->extended_data[ch]; + float *dst1 = (float *)s->xfade[1]->extended_data[ch]; + + for (int n = 0; n < s->min_part_size; n++) { + dst0[n] = (n + 1.f) / s->min_part_size; + dst1[n] = 1.f - dst0[n]; + } + } + break; + case AV_SAMPLE_FMT_DBLP: + for (int ch = 0; ch < s->nb_channels; ch++) { + double *dst0 = (double *)s->xfade[0]->extended_data[ch]; + double *dst1 = (double *)s->xfade[1]->extended_data[ch]; + + for (int n = 0; n < s->min_part_size; n++) { + dst0[n] = (n + 1.0) / s->min_part_size; + dst1[n] = 1.0 - dst0[n]; + } + } + break; + } + return 0; } @@ -610,6 +638,9 @@ static av_cold void uninit(AVFilterContext *ctx) av_frame_free(&s->norm_ir[i]); } + av_frame_free(&s->xfade[0]); + av_frame_free(&s->xfade[1]); + av_frame_free(&s->video); } @@ -691,6 +722,8 @@ static av_cold int init(AVFilterContext *ctx) ff_afir_init(&s->afirdsp); + s->min_part_size = 1 << av_log2(s->minp); + return 0; } diff --git a/libavfilter/af_afir.h b/libavfilter/af_afir.h index 11564d5b122..5f2c68c5c6b 100644 --- a/libavfilter/af_afir.h +++ b/libavfilter/af_afir.h @@ -90,6 +90,7 @@ typedef struct AudioFIRContext { AudioFIRSegment seg[MAX_IR_STREAMS][1024]; AVFrame *in; + AVFrame *xfade[2]; AVFrame *ir[MAX_IR_STREAMS]; AVFrame *norm_ir[MAX_IR_STREAMS]; AVFrame *video; diff --git a/libavfilter/afir_template.c b/libavfilter/afir_template.c index 63d95de9004..5ddc79f6c13 100644 --- a/libavfilter/afir_template.c +++ b/libavfilter/afir_template.c @@ -292,6 +292,8 @@ static int fn(fir_quantum)(AVFilterContext *ctx, AVFrame *out, int ch, int offse ftype *blockout, *ptr = (ftype *)out->extended_data[ch] + offset; const int min_part_size = s->min_part_size; const int nb_samples = FFMIN(min_part_size, out->nb_samples - offset); + const ftype *xfade0 = (const ftype *)s->xfade[0]->extended_data[ch]; + const ftype *xfade1 = (const ftype *)s->xfade[1]->extended_data[ch]; const int nb_segments = s->nb_segments[selir]; const float dry_gain = s->dry_gain; @@ -370,7 +372,7 @@ static int fn(fir_quantum)(AVFilterContext *ctx, AVFrame *out, int ch, int offse if (selir == s->selir) { if (s->loading[ch] <= min_part_size) { for (int n = 0; n < nb_samples; n++) - ptr[n] += dst[n] * ((n + 1.f) / nb_samples); + ptr[n] += dst[n] * xfade0[n]; } } else { fn(fir_fadd)(s, ptr, dst, nb_samples); @@ -388,7 +390,7 @@ static int fn(fir_quantum)(AVFilterContext *ctx, AVFrame *out, int ch, int offse if (selir != s->selir) { if (s->loading[ch] <= min_part_size) { for (int n = 0; n < nb_samples; n++) - ptr[n] *= (nb_samples - n * 1.f) / nb_samples; + ptr[n] *= xfade1[n]; } return 0; } From bbb885e6a5219afb4177b78fb31c3a95e2db294a Mon Sep 17 00:00:00 2001 From: Marton Balint Date: Mon, 10 Apr 2023 21:32:41 +0200 Subject: [PATCH 0789/2172] avformat/mov: factorize reading creation time metadata Signed-off-by: Marton Balint --- libavformat/mov.c | 32 ++++++++++++-------------------- 1 file changed, 12 insertions(+), 20 deletions(-) diff --git a/libavformat/mov.c b/libavformat/mov.c index 057fd872b10..5d00ff6e8b4 100644 --- a/libavformat/mov.c +++ b/libavformat/mov.c @@ -1515,14 +1515,22 @@ static int mov_read_moof(MOVContext *c, AVIOContext *pb, MOVAtom atom) return mov_read_default(c, pb, atom); } -static void mov_metadata_creation_time(AVDictionary **metadata, int64_t time, void *logctx) +static void mov_metadata_creation_time(MOVContext *c, AVIOContext *pb, AVDictionary **metadata, int version) { + int64_t time; + if (version == 1) { + time = avio_rb64(pb); + avio_rb64(pb); + } else { + time = avio_rb32(pb); + avio_rb32(pb); /* modification time */ + } if (time) { if (time >= 2082844800) time -= 2082844800; /* seconds between 1904-01-01 and Epoch */ if ((int64_t)(time * 1000000ULL) / 1000000 != time) { - av_log(logctx, AV_LOG_DEBUG, "creation_time is not representable\n"); + av_log(c->fc, AV_LOG_DEBUG, "creation_time is not representable\n"); return; } @@ -1537,7 +1545,6 @@ static int mov_read_mdhd(MOVContext *c, AVIOContext *pb, MOVAtom atom) int version; char language[4] = {0}; unsigned lang; - int64_t creation_time; if (c->fc->nb_streams < 1) return 0; @@ -1555,14 +1562,7 @@ static int mov_read_mdhd(MOVContext *c, AVIOContext *pb, MOVAtom atom) return AVERROR_PATCHWELCOME; } avio_rb24(pb); /* flags */ - if (version == 1) { - creation_time = avio_rb64(pb); - avio_rb64(pb); - } else { - creation_time = avio_rb32(pb); - avio_rb32(pb); /* modification time */ - } - mov_metadata_creation_time(&st->metadata, creation_time, c->fc); + mov_metadata_creation_time(c, pb, &st->metadata, version); sc->time_scale = avio_rb32(pb); if (sc->time_scale <= 0) { @@ -1587,18 +1587,10 @@ static int mov_read_mdhd(MOVContext *c, AVIOContext *pb, MOVAtom atom) static int mov_read_mvhd(MOVContext *c, AVIOContext *pb, MOVAtom atom) { int i; - int64_t creation_time; int version = avio_r8(pb); /* version */ avio_rb24(pb); /* flags */ - if (version == 1) { - creation_time = avio_rb64(pb); - avio_rb64(pb); - } else { - creation_time = avio_rb32(pb); - avio_rb32(pb); /* modification time */ - } - mov_metadata_creation_time(&c->fc->metadata, creation_time, c->fc); + mov_metadata_creation_time(c, pb, &c->fc->metadata, version); c->time_scale = avio_rb32(pb); /* time scale */ if (c->time_scale <= 0) { av_log(c->fc, AV_LOG_ERROR, "Invalid mvhd time scale %d, defaulting to 1\n", c->time_scale); From 5cdbf817c978a75b1d840325727ed314b4f886a7 Mon Sep 17 00:00:00 2001 From: Marton Balint Date: Sat, 15 Apr 2023 18:25:30 +0200 Subject: [PATCH 0790/2172] avformat/mov: restrict unix timestamp hack to version 0 mdhd/mvhd Commit 23eeffcd48a15e73fb2649b712870b6d101c5471 added a hack to support invalid files where the creation date was encoded as a classic unix timestamp. Let's reduce the scope of the hack by only applying it to version 0 mdhd/mvhd atoms. Also warn the user of such possibly broken files. Signed-off-by: Marton Balint --- libavformat/mov.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/libavformat/mov.c b/libavformat/mov.c index 5d00ff6e8b4..1b3c1d76837 100644 --- a/libavformat/mov.c +++ b/libavformat/mov.c @@ -1524,10 +1524,13 @@ static void mov_metadata_creation_time(MOVContext *c, AVIOContext *pb, AVDiction } else { time = avio_rb32(pb); avio_rb32(pb); /* modification time */ + if (time > 0 && time < 2082844800) { + av_log(c->fc, AV_LOG_WARNING, "Detected creation time before 1970, parsing as unix timestamp.\n"); + time += 2082844800; + } } if (time) { - if (time >= 2082844800) - time -= 2082844800; /* seconds between 1904-01-01 and Epoch */ + time -= 2082844800; /* seconds between 1904-01-01 and Epoch */ if ((int64_t)(time * 1000000ULL) / 1000000 != time) { av_log(c->fc, AV_LOG_DEBUG, "creation_time is not representable\n"); From 8d8feea0a68e2a36b4a0556703774f5023c170ca Mon Sep 17 00:00:00 2001 From: Marton Balint Date: Sat, 15 Apr 2023 20:37:44 +0200 Subject: [PATCH 0791/2172] avformat/movenc: factorize determining mdhd/mvhd/tkhd version Also make duration check for mvhd more consistent with the others, write version 1 of mvhd if duration is at least INT32_MAX instead of UINT32_MAX. Signed-off-by: Marton Balint --- libavformat/movenc.c | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/libavformat/movenc.c b/libavformat/movenc.c index 946e79c5ac8..a9c8e104f0d 100644 --- a/libavformat/movenc.c +++ b/libavformat/movenc.c @@ -3269,14 +3269,20 @@ static int64_t calc_pts_duration(MOVMuxContext *mov, MOVTrack *track) return end - start; } +static int mov_mdhd_mvhd_tkhd_version(MOVMuxContext *mov, MOVTrack *track, int64_t duration) +{ + if (track && track->mode == MODE_ISM) + return 1; + if (duration < INT32_MAX) + return 0; + return 1; +} + static int mov_write_mdhd_tag(AVIOContext *pb, MOVMuxContext *mov, MOVTrack *track) { int64_t duration = calc_samples_pts_duration(mov, track); - int version = duration < INT32_MAX ? 0 : 1; - - if (track->mode == MODE_ISM) - version = 1; + int version = mov_mdhd_mvhd_tkhd_version(mov, track, duration); (version == 1) ? avio_wb32(pb, 44) : avio_wb32(pb, 32); /* size */ ffio_wfourcc(pb, "mdhd"); @@ -3362,8 +3368,6 @@ static int mov_write_tkhd_tag(AVIOContext *pb, MOVMuxContext *mov, else duration *= mov->avif_loop_count; - version = duration < INT32_MAX ? 0 : 1; - if (st) { if (mov->per_stream_grouping) group = st->index; @@ -3379,8 +3383,7 @@ static int mov_write_tkhd_tag(AVIOContext *pb, MOVMuxContext *mov, if (track->flags & MOV_TRACK_ENABLED) flags |= MOV_TKHD_FLAG_ENABLED; - if (track->mode == MODE_ISM) - version = 1; + version = mov_mdhd_mvhd_tkhd_version(mov, track, duration); (version == 1) ? avio_wb32(pb, 104) : avio_wb32(pb, 92); /* size */ ffio_wfourcc(pb, "tkhd"); @@ -3863,7 +3866,7 @@ static int mov_write_mvhd_tag(AVIOContext *pb, MOVMuxContext *mov) max_track_id = 1; } - version = max_track_len < UINT32_MAX ? 0 : 1; + version = mov_mdhd_mvhd_tkhd_version(mov, NULL, max_track_len); avio_wb32(pb, version == 1 ? 120 : 108); /* size */ ffio_wfourcc(pb, "mvhd"); From f2d0138f70045e17a5381148fef3b177f41e0ce9 Mon Sep 17 00:00:00 2001 From: Marton Balint Date: Sat, 15 Apr 2023 21:12:35 +0200 Subject: [PATCH 0792/2172] avformat/smoothstreamingenc: do not override movflag defaults Signed-off-by: Marton Balint --- libavformat/smoothstreamingenc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavformat/smoothstreamingenc.c b/libavformat/smoothstreamingenc.c index 66e6313934a..3c050ca54ed 100644 --- a/libavformat/smoothstreamingenc.c +++ b/libavformat/smoothstreamingenc.c @@ -340,7 +340,7 @@ static int ism_write_header(AVFormatContext *s) } av_dict_set_int(&opts, "ism_lookahead", c->lookahead_count, 0); - av_dict_set(&opts, "movflags", "frag_custom", 0); + av_dict_set(&opts, "movflags", "+frag_custom", 0); ret = avformat_write_header(ctx, &opts); av_dict_free(&opts); if (ret < 0) { From ace9459c411da62cfb6845ee179de0c5a4e2568e Mon Sep 17 00:00:00 2001 From: Marton Balint Date: Sat, 15 Apr 2023 21:13:37 +0200 Subject: [PATCH 0793/2172] tests: do not override movflags defaults It does not matter if the default is 0, but still it is cleaner that way. Signed-off-by: Marton Balint --- libavformat/tests/movenc.c | 54 +++++++++++++++++++------------------- tests/fate/subtitles.mak | 2 +- tests/fate/vcodec.mak | 2 +- 3 files changed, 29 insertions(+), 29 deletions(-) diff --git a/libavformat/tests/movenc.c b/libavformat/tests/movenc.c index 6f9d381927a..fca3213285d 100644 --- a/libavformat/tests/movenc.c +++ b/libavformat/tests/movenc.c @@ -389,7 +389,7 @@ int main(int argc, char **argv) // samples. One moov+mdat with 1 second of data and one moof+mdat with 1 // second of data. init_out("non-empty-moov"); - av_dict_set(&opts, "movflags", "frag_keyframe", 0); + av_dict_set(&opts, "movflags", "+frag_keyframe", 0); init(0, 0); mux_gops(2); finish(); @@ -398,7 +398,7 @@ int main(int argc, char **argv) // Write a similar file, but with B-frames and audio preroll, handled // via an edit list. init_out("non-empty-moov-elst"); - av_dict_set(&opts, "movflags", "frag_keyframe", 0); + av_dict_set(&opts, "movflags", "+frag_keyframe", 0); av_dict_set(&opts, "use_editlist", "1", 0); init(1, 1); mux_gops(2); @@ -410,7 +410,7 @@ int main(int argc, char **argv) // of the first audio packet is > 0, but it is set to zero since edit // lists aren't used, increasing the duration of the first packet instead. init_out("non-empty-moov-no-elst"); - av_dict_set(&opts, "movflags", "frag_keyframe", 0); + av_dict_set(&opts, "movflags", "+frag_keyframe", 0); av_dict_set(&opts, "use_editlist", "0", 0); init(1, 0); mux_gops(2); @@ -420,7 +420,7 @@ int main(int argc, char **argv) format = "ismv"; // Write an ISMV, with B-frames and audio preroll. init_out("ismv"); - av_dict_set(&opts, "movflags", "frag_keyframe", 0); + av_dict_set(&opts, "movflags", "+frag_keyframe", 0); init(1, 1); mux_gops(2); finish(); @@ -430,7 +430,7 @@ int main(int argc, char **argv) // An initial moov that doesn't contain any samples, followed by two // moof+mdat pairs. init_out("empty-moov"); - av_dict_set(&opts, "movflags", "frag_keyframe+empty_moov", 0); + av_dict_set(&opts, "movflags", "+frag_keyframe+empty_moov", 0); av_dict_set(&opts, "use_editlist", "0", 0); init(0, 0); mux_gops(2); @@ -442,7 +442,7 @@ int main(int argc, char **argv) // pts/dts 0. avoid_negative_ts behaves in the same way as // in non-empty-moov-no-elst above. init_out("empty-moov-no-elst"); - av_dict_set(&opts, "movflags", "frag_keyframe+empty_moov", 0); + av_dict_set(&opts, "movflags", "+frag_keyframe+empty_moov", 0); init(1, 0); mux_gops(2); finish(); @@ -454,7 +454,7 @@ int main(int argc, char **argv) // This should trigger a warning - we check that the warning is produced. init_count_warnings(); init_out("empty-moov-no-elst-no-adjust"); - av_dict_set(&opts, "movflags", "frag_keyframe+empty_moov", 0); + av_dict_set(&opts, "movflags", "+frag_keyframe+empty_moov", 0); av_dict_set(&opts, "avoid_negative_ts", "disabled", 0); init(1, 0); mux_gops(2); @@ -467,7 +467,7 @@ int main(int argc, char **argv) // Verify that delay_moov produces the same as empty_moov for // simple input init_out("delay-moov"); - av_dict_set(&opts, "movflags", "frag_keyframe+delay_moov", 0); + av_dict_set(&opts, "movflags", "+frag_keyframe+delay_moov", 0); av_dict_set(&opts, "use_editlist", "0", 0); init(0, 0); mux_gops(2); @@ -477,7 +477,7 @@ int main(int argc, char **argv) // Test writing content that requires an edit list using delay_moov init_out("delay-moov-elst"); - av_dict_set(&opts, "movflags", "frag_keyframe+delay_moov", 0); + av_dict_set(&opts, "movflags", "+frag_keyframe+delay_moov", 0); init(1, 1); mux_gops(2); finish(); @@ -486,7 +486,7 @@ int main(int argc, char **argv) // Test writing a file with one track lacking packets, with delay_moov. skip_write_audio = 1; init_out("delay-moov-empty-track"); - av_dict_set(&opts, "movflags", "frag_keyframe+delay_moov", 0); + av_dict_set(&opts, "movflags", "+frag_keyframe+delay_moov", 0); init(0, 0); mux_gops(2); // The automatic flushing shouldn't output anything, since we're still @@ -501,7 +501,7 @@ int main(int argc, char **argv) // Check that manually flushing still outputs things as expected. This // produces two fragments, while the one above produces only one. init_out("delay-moov-empty-track-flush"); - av_dict_set(&opts, "movflags", "frag_custom+delay_moov", 0); + av_dict_set(&opts, "movflags", "+frag_custom+delay_moov", 0); init(0, 0); mux_gops(1); av_write_frame(ctx, NULL); // Force writing the moov @@ -519,7 +519,7 @@ int main(int argc, char **argv) // Verify that the header written by delay_moov when manually flushed // is identical to the one by empty_moov. init_out("empty-moov-header"); - av_dict_set(&opts, "movflags", "frag_keyframe+empty_moov", 0); + av_dict_set(&opts, "movflags", "+frag_keyframe+empty_moov", 0); av_dict_set(&opts, "use_editlist", "0", 0); init(0, 0); close_out(); @@ -542,7 +542,7 @@ int main(int argc, char **argv) finish(); init_out("delay-moov-header"); - av_dict_set(&opts, "movflags", "frag_custom+delay_moov", 0); + av_dict_set(&opts, "movflags", "+frag_custom+delay_moov", 0); av_dict_set(&opts, "use_editlist", "0", 0); init(0, 0); check(out_size == 0, "Output written during init with delay_moov"); @@ -563,7 +563,7 @@ int main(int argc, char **argv) // Verify that we can produce an identical second fragment without // writing the first one. First write the reference fragments that // we want to reproduce. - av_dict_set(&opts, "movflags", "frag_custom+empty_moov+dash", 0); + av_dict_set(&opts, "movflags", "+frag_custom+empty_moov+dash", 0); init(0, 0); mux_gops(1); av_write_frame(ctx, NULL); // Output the first fragment @@ -576,7 +576,7 @@ int main(int argc, char **argv) // Produce the same second fragment without actually writing the first // one before. - av_dict_set(&opts, "movflags", "frag_custom+empty_moov+dash+frag_discont", 0); + av_dict_set(&opts, "movflags", "+frag_custom+empty_moov+dash+frag_discont", 0); av_dict_set(&opts, "fragment_index", "2", 0); av_dict_set(&opts, "avoid_negative_ts", "disabled", 0); av_dict_set(&opts, "use_editlist", "0", 0); @@ -591,7 +591,7 @@ int main(int argc, char **argv) // Produce the same thing by using delay_moov, which requires a slightly // different call sequence. - av_dict_set(&opts, "movflags", "frag_custom+delay_moov+dash+frag_discont", 0); + av_dict_set(&opts, "movflags", "+frag_custom+delay_moov+dash+frag_discont", 0); av_dict_set(&opts, "fragment_index", "2", 0); init(0, 0); skip_gops(1); @@ -607,7 +607,7 @@ int main(int argc, char **argv) // Test discontinuously written fragments with B-frames (where the // assumption of starting at pts=0 works) but not with audio preroll // (which can't be guessed). - av_dict_set(&opts, "movflags", "frag_custom+delay_moov+dash", 0); + av_dict_set(&opts, "movflags", "+frag_custom+delay_moov+dash", 0); init(1, 0); mux_gops(1); init_out("delay-moov-elst-init"); @@ -622,7 +622,7 @@ int main(int argc, char **argv) memcpy(content, hash, HASH_SIZE); finish(); - av_dict_set(&opts, "movflags", "frag_custom+delay_moov+dash+frag_discont", 0); + av_dict_set(&opts, "movflags", "+frag_custom+delay_moov+dash+frag_discont", 0); av_dict_set(&opts, "fragment_index", "2", 0); init(1, 0); skip_gops(1); @@ -640,7 +640,7 @@ int main(int argc, char **argv) // Test discontinuously written fragments with B-frames and audio preroll, // properly signaled. - av_dict_set(&opts, "movflags", "frag_custom+delay_moov+dash", 0); + av_dict_set(&opts, "movflags", "+frag_custom+delay_moov+dash", 0); init(1, 1); mux_gops(1); init_out("delay-moov-elst-signal-init"); @@ -655,7 +655,7 @@ int main(int argc, char **argv) memcpy(content, hash, HASH_SIZE); finish(); - av_dict_set(&opts, "movflags", "frag_custom+delay_moov+dash+frag_discont", 0); + av_dict_set(&opts, "movflags", "+frag_custom+delay_moov+dash+frag_discont", 0); av_dict_set(&opts, "fragment_index", "2", 0); init(1, 1); signal_init_ts(); @@ -673,7 +673,7 @@ int main(int argc, char **argv) // Test muxing discontinuous fragments with very large (> (1<<31)) timestamps. - av_dict_set(&opts, "movflags", "frag_custom+delay_moov+dash+frag_discont", 0); + av_dict_set(&opts, "movflags", "+frag_custom+delay_moov+dash+frag_discont", 0); av_dict_set(&opts, "fragment_index", "2", 0); init(1, 1); signal_init_ts(); @@ -700,7 +700,7 @@ int main(int argc, char **argv) // match - the input stream starts at pts=-2048, but that part is excluded // by the edit list. init_out("vfr"); - av_dict_set(&opts, "movflags", "frag_keyframe+delay_moov+dash", 0); + av_dict_set(&opts, "movflags", "+frag_keyframe+delay_moov+dash", 0); init_fps(1, 1, 3); mux_frames(gop_size/2, 0); duration /= 10; @@ -719,7 +719,7 @@ int main(int argc, char **argv) init_count_warnings(); clear_duration = 1; init_out("vfr-noduration"); - av_dict_set(&opts, "movflags", "frag_keyframe+delay_moov+dash", 0); + av_dict_set(&opts, "movflags", "+frag_keyframe+delay_moov+dash", 0); init_fps(1, 1, 3); mux_frames(gop_size/2, 0); duration /= 10; @@ -735,7 +735,7 @@ int main(int argc, char **argv) // this will cause write_data_type to be called with the type unknown. force_iobuf_size = 1500; init_out("large_frag"); - av_dict_set(&opts, "movflags", "frag_keyframe+delay_moov", 0); + av_dict_set(&opts, "movflags", "+frag_keyframe+delay_moov", 0); init_fps(1, 1, 3); mux_gops(2); finish(); @@ -748,7 +748,7 @@ int main(int argc, char **argv) // the expected, but we simulate dropped frames at one point. do_interleave = 1; init_out("vfr-noduration-interleave"); - av_dict_set(&opts, "movflags", "frag_keyframe+delay_moov", 0); + av_dict_set(&opts, "movflags", "+frag_keyframe+delay_moov", 0); av_dict_set(&opts, "frag_duration", "650000", 0); init_fps(1, 1, 30); mux_frames(gop_size/2, 0); @@ -771,7 +771,7 @@ int main(int argc, char **argv) // with negative cts values, removing the edit list for the // video track. init_out("delay-moov-elst-neg-cts"); - av_dict_set(&opts, "movflags", "frag_keyframe+delay_moov+negative_cts_offsets", 0); + av_dict_set(&opts, "movflags", "+frag_keyframe+delay_moov+negative_cts_offsets", 0); init(1, 1); mux_gops(2); finish(); @@ -781,7 +781,7 @@ int main(int argc, char **argv) // with negative cts values, avoiding any edit lists, allowing // to use empty_moov instead of delay_moov. init_out("empty-moov-neg-cts"); - av_dict_set(&opts, "movflags", "frag_keyframe+empty_moov+negative_cts_offsets", 0); + av_dict_set(&opts, "movflags", "+frag_keyframe+empty_moov+negative_cts_offsets", 0); init(1, 0); mux_gops(2); finish(); diff --git a/tests/fate/subtitles.mak b/tests/fate/subtitles.mak index e6684a814be..59595b9cc19 100644 --- a/tests/fate/subtitles.mak +++ b/tests/fate/subtitles.mak @@ -39,7 +39,7 @@ FATE_SUBTITLES_ASS-$(call DEMDEC, MOV, MOVTEXT) += fate-sub-movtext fate-sub-movtext: CMD = fmtstdout ass -i $(TARGET_SAMPLES)/sub/MovText_capability_tester.mp4 FATE_SUBTITLES-$(call ENCDEC, MOVTEXT, MOV) += fate-binsub-movtextenc -fate-binsub-movtextenc: CMD = md5 -i $(TARGET_SAMPLES)/sub/MovText_capability_tester.mp4 -map 0 -scodec mov_text -f mp4 -flags +bitexact -fflags +bitexact -movflags frag_keyframe+empty_moov +fate-binsub-movtextenc: CMD = md5 -i $(TARGET_SAMPLES)/sub/MovText_capability_tester.mp4 -map 0 -scodec mov_text -f mp4 -flags +bitexact -fflags +bitexact -movflags +frag_keyframe+empty_moov FATE_SUBTITLES_ASS-$(call DEMDEC, MPL2, MPL2) += fate-sub-mpl2 fate-sub-mpl2: CMD = fmtstdout ass -i $(TARGET_SAMPLES)/sub/MPL2_capability_tester.txt diff --git a/tests/fate/vcodec.mak b/tests/fate/vcodec.mak index bf9de0327a5..fbee264a9d7 100644 --- a/tests/fate/vcodec.mak +++ b/tests/fate/vcodec.mak @@ -111,7 +111,7 @@ fate-vsynth%-dnxhd-1080i-10bit: ENCOPTS = -s hd1080 -b 185M -flags +ildct \ -pix_fmt yuv422p10 -frames 5 -qmax 8 fate-vsynth%-dnxhd-1080i-10bit: DECOPTS = -sws_flags area+accurate_rnd+bitexact -fate-vsynth%-dnxhd-1080i-colr: ENCOPTS = -s hd1080 -b 120M -flags +ildct -movflags write_colr \ +fate-vsynth%-dnxhd-1080i-colr: ENCOPTS = -s hd1080 -b 120M -flags +ildct -movflags +write_colr \ -pix_fmt yuv422p -frames 5 -qmax 8 fate-vsynth%-dnxhd-1080i-colr: DECOPTS = -sws_flags area+accurate_rnd+bitexact From 412274c0d2b0d25febc9d80ac9dbfd1e9bf32962 Mon Sep 17 00:00:00 2001 From: Marton Balint Date: Sat, 15 Apr 2023 22:08:01 +0200 Subject: [PATCH 0794/2172] doc/muxers: reorder and cleanup mov muxer options Make various movflags grouped together similar to how it is done for other options. Signed-off-by: Marton Balint --- doc/muxers.texi | 88 +++++++++++++++++++++++++------------------------ 1 file changed, 45 insertions(+), 43 deletions(-) diff --git a/doc/muxers.texi b/doc/muxers.texi index 79dd8641825..d1e825eec59 100644 --- a/doc/muxers.texi +++ b/doc/muxers.texi @@ -1630,8 +1630,10 @@ MOV/MP4/ISMV (Smooth Streaming) muxer. The mov/mp4/ismv muxer supports fragmentation. Normally, a MOV/MP4 file has all the metadata about all packets stored in one location (written at the end of the file, it can be moved to the start for -better playback by adding @var{faststart} to the @var{movflags}, or -using the @command{qt-faststart} tool). A fragmented +better playback by adding @code{+faststart} to the @code{-movflags}, or +using the @command{qt-faststart} tool). + +A fragmented file consists of a number of fragments, where packets and metadata about these packets are stored together. Writing a fragmented file has the advantage that the file is decodable even if the @@ -1641,40 +1643,34 @@ very long files (since writing normal MOV/MP4 files stores info about every single packet in memory until the file is closed). The downside is that it is less compatible with other applications. -@subsection Options +Fragmentation is enabled by setting one of the options that define +how to cut the file into fragments: @code{-frag_duration}, @code{-frag_size}, +@code{-min_frag_duration}, @code{-movflags +frag_keyframe} and +@code{-movflags +frag_custom}. If more than one condition is specified, +fragments are cut when one of the specified conditions is fulfilled. The +exception to this is @code{-min_frag_duration}, which has to be fulfilled for +any of the other conditions to apply. -Fragmentation is enabled by setting one of the AVOptions that define -how to cut the file into fragments: +@subsection Options @table @option -@item -moov_size @var{bytes} -Reserves space for the moov atom at the beginning of the file instead of placing the -moov atom at the end. If the space reserved is insufficient, muxing will fail. -@item -movflags frag_keyframe -Start a new fragment at each video keyframe. -@item -frag_duration @var{duration} +@item frag_duration @var{duration} Create fragments that are @var{duration} microseconds long. -@item -frag_size @var{size} +@item frag_size @var{size} Create fragments that contain up to @var{size} bytes of payload data. -@item -movflags frag_custom +@item min_frag_duration @var{duration} +Don't create fragments that are shorter than @var{duration} microseconds long. +@item movflags @var{flags} +Set various muxing switches. The following flags can be used: +@table @samp +@item frag_keyframe +Start a new fragment at each video keyframe. +@item frag_custom Allow the caller to manually choose when to cut fragments, by calling @code{av_write_frame(ctx, NULL)} to write a fragment with the packets written so far. (This is only useful with other applications integrating libavformat, not from @command{ffmpeg}.) -@item -min_frag_duration @var{duration} -Don't create fragments that are shorter than @var{duration} microseconds long. -@end table - -If more than one condition is specified, fragments are cut when -one of the specified conditions is fulfilled. The exception to this is -@code{-min_frag_duration}, which has to be fulfilled for any of the other -conditions to apply. - -Additionally, the way the output file is written can be adjusted -through a few other options: - -@table @option -@item -movflags empty_moov +@item empty_moov Write an initial moov atom directly at the start of the file, without describing any samples in it. Generally, an mdat/moov pair is written at the start of the file, as a normal MOV/MP4 file, containing only @@ -1683,43 +1679,40 @@ mdat atom, and the moov atom only describes the tracks but has a zero duration. This option is implicitly set when writing ismv (Smooth Streaming) files. -@item -movflags separate_moof +@item separate_moof Write a separate moof (movie fragment) atom for each track. Normally, packets for all tracks are written in a moof atom (which is slightly more efficient), but with this option set, the muxer writes one moof/mdat pair for each track, making it easier to separate tracks. This option is implicitly set when writing ismv (Smooth Streaming) files. -@item -movflags skip_sidx +@item skip_sidx Skip writing of sidx atom. When bitrate overhead due to sidx atom is high, this option could be used for cases where sidx atom is not mandatory. When global_sidx flag is enabled, this option will be ignored. -@item -movflags faststart +@item faststart Run a second pass moving the index (moov atom) to the beginning of the file. This operation can take a while, and will not work in various situations such as fragmented output, thus it is not enabled by default. -@item -movflags rtphint +@item rtphint Add RTP hinting tracks to the output file. -@item -movflags disable_chpl +@item disable_chpl Disable Nero chapter markers (chpl atom). Normally, both Nero chapters and a QuickTime chapter track are written to the file. With this option set, only the QuickTime chapter track will be written. Nero chapters can cause failures when the file is reprocessed with certain tagging programs, like mp3Tag 2.61a and iTunes 11.3, most likely other versions are affected as well. -@item -movflags omit_tfhd_offset +@item omit_tfhd_offset Do not write any absolute base_data_offset in tfhd atoms. This avoids tying fragments to absolute byte positions in the file/streams. -@item -movflags default_base_moof +@item default_base_moof Similarly to the omit_tfhd_offset, this flag avoids writing the absolute base_data_offset field in tfhd atoms, but does so by using the new default-base-is-moof flag instead. This flag is new from 14496-12:2012. This may make the fragments easier to parse in certain circumstances (avoiding basing track fragment location calculations on the implicit end of the previous track fragment). -@item -write_tmcd -Specify @code{on} to force writing a timecode track, @code{off} to disable it -and @code{auto} to write a timecode track only for mov and mp4 output (default). -@item -movflags negative_cts_offsets +@item negative_cts_offsets Enables utilization of version 1 of the CTTS box, in which the CTS offsets can be negative. This enables the initial sample to have DTS/CTS of zero, and reduces the need for edit lists for some cases such as video tracks with @@ -1727,15 +1720,24 @@ B-frames. Additionally, eases conformance with the DASH-IF interoperability guidelines. This option is implicitly set when writing ismv (Smooth Streaming) files. +@end table + +@item moov_size @var{bytes} +Reserves space for the moov atom at the beginning of the file instead of placing the +moov atom at the end. If the space reserved is insufficient, muxing will fail. + +@item write_tmcd +Specify @code{on} to force writing a timecode track, @code{off} to disable it +and @code{auto} to write a timecode track only for mov and mp4 output (default). -@item -write_btrt @var{bool} +@item write_btrt @var{bool} Force or disable writing bitrate box inside stsd box of a track. The box contains decoding buffer size (in bytes), maximum bitrate and average bitrate for the track. The box will be skipped if none of these values can be computed. Default is @code{-1} or @code{auto}, which will write the box only in MP4 mode. -@item -write_prft +@item write_prft Write producer time reference box (PRFT) with a specified time source for the NTP field in the PRFT box. Set value as @samp{wallclock} to specify timesource as wallclock time and @samp{pts} to specify timesource as input packets' PTS @@ -1746,15 +1748,15 @@ where PTS values are set as as wallclock time at the source. For example, an encoding use case with decklink capture source where @option{video_pts} and @option{audio_pts} are set to @samp{abs_wallclock}. -@item -empty_hdlr_name @var{bool} +@item empty_hdlr_name @var{bool} Enable to skip writing the name inside a @code{hdlr} box. Default is @code{false}. -@item -movie_timescale @var{scale} +@item movie_timescale @var{scale} Set the timescale written in the movie header box (@code{mvhd}). Range is 1 to INT_MAX. Default is 1000. -@item -video_track_timescale @var{scale} +@item video_track_timescale @var{scale} Set the timescale used for video tracks. Range is 0 to INT_MAX. If set to @code{0}, the timescale is automatically set based on the native stream time base. Default is 0. From 2f8690c5d450b984640bd27dd7fd3a96d77ecc6b Mon Sep 17 00:00:00 2001 From: Marton Balint Date: Sun, 16 Apr 2023 00:08:22 +0200 Subject: [PATCH 0795/2172] avdevice/decklink_enc: fix operator precedence in create_s337_payload Signed-off-by: Marton Balint --- libavdevice/decklink_enc.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavdevice/decklink_enc.cpp b/libavdevice/decklink_enc.cpp index 92bfdb279fe..9f1a8df438e 100644 --- a/libavdevice/decklink_enc.cpp +++ b/libavdevice/decklink_enc.cpp @@ -318,7 +318,7 @@ static int create_s337_payload(AVPacket *pkt, uint8_t **outbuf, int *outsize) /* Ensure final payload is aligned on 4-byte boundary */ if (pkt->size & 1) bytestream2_put_le16u(&pb, pkt->data[pkt->size - 1] << 8); - if ((pkt->size & 3 == 1) || (pkt->size & 3 == 2)) + if ((pkt->size & 3) == 1 || (pkt->size & 3) == 2) bytestream2_put_le16u(&pb, 0); *outsize = payload_size; From 1835f884b7ae475d2079d044003966981823502e Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Tue, 25 Apr 2023 15:21:51 +0200 Subject: [PATCH 0796/2172] avfilter/af_afir: make IR switching work also with minp != maxp --- libavfilter/af_afir.c | 76 ++++++++++++++++++++++++++++++------- libavfilter/af_afir.h | 2 + libavfilter/afir_template.c | 30 ++------------- 3 files changed, 67 insertions(+), 41 deletions(-) diff --git a/libavfilter/af_afir.c b/libavfilter/af_afir.c index 4acc24ccac9..338e23063c6 100644 --- a/libavfilter/af_afir.c +++ b/libavfilter/af_afir.c @@ -112,16 +112,59 @@ static int fir_channel(AVFilterContext *ctx, AVFrame *out, int ch) for (int offset = 0; offset < out->nb_samples; offset += min_part_size) { switch (s->format) { case AV_SAMPLE_FMT_FLTP: - if (prev_selir != selir) - fir_quantum_float(ctx, out, ch, offset, prev_selir); - fir_quantum_float(ctx, out, ch, offset, selir); + if (prev_selir != selir) { + const float *xfade0 = (const float *)s->xfade[0]->extended_data[ch]; + const float *xfade1 = (const float *)s->xfade[1]->extended_data[ch]; + float *src0 = (float *)s->fadein[0]->extended_data[ch]; + float *src1 = (float *)s->fadein[1]->extended_data[ch]; + float *dst = ((float *)out->extended_data[ch]) + offset; + + memset(src0, 0, min_part_size * sizeof(float)); + memset(src1, 0, min_part_size * sizeof(float)); + + fir_quantum_float(ctx, s->fadein[0], ch, offset, 0, prev_selir); + fir_quantum_float(ctx, s->fadein[1], ch, offset, 0, selir); + + if (s->loading[ch] > 0 && s->loading[ch] <= min_part_size) { + for (int n = 0; n < min_part_size; n++) + dst[n] = xfade1[n] * src0[n] + xfade0[n] * src1[n]; + s->loading[ch] = 0; + } else { + memcpy(dst, src0, min_part_size * sizeof(float)); + } + } else { + fir_quantum_float(ctx, out, ch, offset, offset, selir); + } break; case AV_SAMPLE_FMT_DBLP: - if (prev_selir != selir) - fir_quantum_double(ctx, out, ch, offset, prev_selir); - fir_quantum_double(ctx, out, ch, offset, selir); + if (prev_selir != selir) { + const double *xfade0 = (const double *)s->xfade[0]->extended_data[ch]; + const double *xfade1 = (const double *)s->xfade[1]->extended_data[ch]; + double *src0 = (double *)s->fadein[0]->extended_data[ch]; + double *src1 = (double *)s->fadein[1]->extended_data[ch]; + double *dst = ((double *)out->extended_data[ch]) + offset; + + memset(src0, 0, min_part_size * sizeof(double)); + memset(src1, 0, min_part_size * sizeof(double)); + + fir_quantum_double(ctx, s->fadein[0], ch, offset, 0, prev_selir); + fir_quantum_double(ctx, s->fadein[1], ch, offset, 0, selir); + + if (s->loading[ch] > 0 && s->loading[ch] <= min_part_size) { + for (int n = 0; n < min_part_size; n++) + dst[n] = xfade1[n] * src0[n] + xfade0[n] * src1[n]; + s->loading[ch] = 0; + } else { + memcpy(dst, src0, min_part_size * sizeof(double)); + } + } else { + fir_quantum_double(ctx, out, ch, offset, offset, selir); + } break; } + + if (selir != prev_selir && s->loading[ch] > 0) + s->loading[ch] -= min_part_size; } return 0; @@ -299,10 +342,11 @@ static int convert_coeffs(AVFilterContext *ctx, int selir) max_part_size = 1 << av_log2(s->maxp); for (int i = 0; left > 0; i++) { - int step = part_size == max_part_size ? INT_MAX : 1 + (i == 0); + int step = (part_size == max_part_size) ? INT_MAX : 1 + (i == 0); int nb_partitions = FFMIN(step, (left + part_size - 1) / part_size); s->nb_segments[selir] = i + 1; + s->max_offset[selir] = offset; ret = init_segment(ctx, &s->seg[selir][i], selir, offset, nb_partitions, part_size, i); if (ret < 0) return ret; @@ -311,8 +355,6 @@ static int convert_coeffs(AVFilterContext *ctx, int selir) part_size *= 2; part_size = FFMIN(part_size, max_part_size); } - - s->max_offset[selir] = offset; } skip: @@ -455,7 +497,7 @@ static int activate(AVFilterContext *ctx) if (s->selir != s->prev_selir && s->loading[0] <= 0) { for (int ch = 0; ch < s->nb_channels; ch++) - s->loading[ch] = s->max_offset[s->selir] + s->min_part_size; + s->loading[ch] = s->max_offset[s->selir] + s->max_part_size; } available = ff_inlink_queued_samples(ctx->inputs[0]); @@ -464,11 +506,8 @@ static int activate(AVFilterContext *ctx) if (ret > 0) ret = fir_frame(s, in, outlink); - if (s->selir != s->prev_selir && s->loading[0] <= 0) { + if (s->selir != s->prev_selir && s->loading[0] <= 0) s->prev_selir = s->selir; - for (int ch = 0; ch < s->nb_channels; ch++) - s->loading[ch] = 0; - } if (ret < 0) return ret; @@ -590,6 +629,11 @@ FF_ENABLE_DEPRECATION_WARNINGS if (!s->loading) return AVERROR(ENOMEM); + s->fadein[0] = ff_get_audio_buffer(outlink, s->min_part_size); + s->fadein[1] = ff_get_audio_buffer(outlink, s->min_part_size); + if (!s->fadein[0] || !s->fadein[1]) + return AVERROR(ENOMEM); + s->xfade[0] = ff_get_audio_buffer(outlink, s->min_part_size); s->xfade[1] = ff_get_audio_buffer(outlink, s->min_part_size); if (!s->xfade[0] || !s->xfade[1]) @@ -638,6 +682,9 @@ static av_cold void uninit(AVFilterContext *ctx) av_frame_free(&s->norm_ir[i]); } + av_frame_free(&s->fadein[0]); + av_frame_free(&s->fadein[1]); + av_frame_free(&s->xfade[0]); av_frame_free(&s->xfade[1]); @@ -723,6 +770,7 @@ static av_cold int init(AVFilterContext *ctx) ff_afir_init(&s->afirdsp); s->min_part_size = 1 << av_log2(s->minp); + s->max_part_size = 1 << av_log2(s->maxp); return 0; } diff --git a/libavfilter/af_afir.h b/libavfilter/af_afir.h index 5f2c68c5c6b..099897d0bbf 100644 --- a/libavfilter/af_afir.h +++ b/libavfilter/af_afir.h @@ -91,10 +91,12 @@ typedef struct AudioFIRContext { AVFrame *in; AVFrame *xfade[2]; + AVFrame *fadein[2]; AVFrame *ir[MAX_IR_STREAMS]; AVFrame *norm_ir[MAX_IR_STREAMS]; AVFrame *video; int min_part_size; + int max_part_size; int64_t pts; AudioFIRDSPContext afirdsp; diff --git a/libavfilter/afir_template.c b/libavfilter/afir_template.c index 5ddc79f6c13..0f0500d8b3b 100644 --- a/libavfilter/afir_template.c +++ b/libavfilter/afir_template.c @@ -285,15 +285,13 @@ static void fn(fir_fadd)(AudioFIRContext *s, ftype *dst, const ftype *src, int n } } -static int fn(fir_quantum)(AVFilterContext *ctx, AVFrame *out, int ch, int offset, int selir) +static int fn(fir_quantum)(AVFilterContext *ctx, AVFrame *out, int ch, int ioffset, int offset, int selir) { AudioFIRContext *s = ctx->priv; - const ftype *in = (const ftype *)s->in->extended_data[ch] + offset; + const ftype *in = (const ftype *)s->in->extended_data[ch] + ioffset; ftype *blockout, *ptr = (ftype *)out->extended_data[ch] + offset; const int min_part_size = s->min_part_size; const int nb_samples = FFMIN(min_part_size, out->nb_samples - offset); - const ftype *xfade0 = (const ftype *)s->xfade[0]->extended_data[ch]; - const ftype *xfade1 = (const ftype *)s->xfade[1]->extended_data[ch]; const int nb_segments = s->nb_segments[selir]; const float dry_gain = s->dry_gain; @@ -368,18 +366,7 @@ static int fn(fir_quantum)(AVFilterContext *ctx, AVFrame *out, int ch, int offse memcpy(dst, buf, part_size * sizeof(*dst)); memcpy(buf, sumout + part_size, part_size * sizeof(*buf)); - if (s->selir != s->prev_selir) { - if (selir == s->selir) { - if (s->loading[ch] <= min_part_size) { - for (int n = 0; n < nb_samples; n++) - ptr[n] += dst[n] * xfade0[n]; - } - } else { - fn(fir_fadd)(s, ptr, dst, nb_samples); - } - } else { - fn(fir_fadd)(s, ptr, dst, nb_samples); - } + fn(fir_fadd)(s, ptr, dst, nb_samples); if (part_size != min_part_size) memmove(src, src + min_part_size, (seg->input_size - min_part_size) * sizeof(*src)); @@ -387,17 +374,6 @@ static int fn(fir_quantum)(AVFilterContext *ctx, AVFrame *out, int ch, int offse seg->part_index[ch] = (seg->part_index[ch] + 1) % nb_partitions; } - if (selir != s->selir) { - if (s->loading[ch] <= min_part_size) { - for (int n = 0; n < nb_samples; n++) - ptr[n] *= xfade1[n]; - } - return 0; - } - - if (s->selir != s->prev_selir) - s->loading[ch] -= min_part_size; - if (s->wet_gain == 1.f) return 0; From bee265e5d50a6d6057fb2cf77d55851b867a41d9 Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Tue, 25 Apr 2023 15:42:44 +0200 Subject: [PATCH 0797/2172] avfilter/af_afir: add way to control loading interval of impulses --- doc/filters.texi | 6 ++++++ libavfilter/af_afir.c | 45 +++++++++++++++++++++++++++---------------- libavfilter/af_afir.h | 1 + 3 files changed, 35 insertions(+), 17 deletions(-) diff --git a/doc/filters.texi b/doc/filters.texi index 120fe6664a3..a7972ff736d 100644 --- a/doc/filters.texi +++ b/doc/filters.texi @@ -1849,6 +1849,12 @@ Always use double-floating point precision sample format. @end table Default value is auto. + +@item irload +Set when to load IR stream. Can be @code{init} or @code{access}. +First one load and prepares all IRs on initialization, second one +once on first access of specific IR. +Default is @code{init}. @end table @subsection Examples diff --git a/libavfilter/af_afir.c b/libavfilter/af_afir.c index 338e23063c6..24fb8c1abea 100644 --- a/libavfilter/af_afir.c +++ b/libavfilter/af_afir.c @@ -472,27 +472,35 @@ static int activate(AVFilterContext *ctx) FF_FILTER_FORWARD_STATUS_BACK_ALL(ctx->outputs[0], ctx); if (s->response) FF_FILTER_FORWARD_STATUS_BACK_ALL(ctx->outputs[1], ctx); - if (!s->eof_coeffs[s->selir]) { - ret = check_ir(ctx->inputs[1 + s->selir]); - if (ret < 0) - return ret; - if (ff_outlink_get_status(ctx->inputs[1 + s->selir]) == AVERROR_EOF) - s->eof_coeffs[s->selir] = 1; + for (int i = 0; i < s->nb_irs; i++) { + const int selir = i; - if (!s->eof_coeffs[s->selir]) { - if (ff_outlink_frame_wanted(ctx->outputs[0])) - ff_inlink_request_frame(ctx->inputs[1 + s->selir]); - else if (s->response && ff_outlink_frame_wanted(ctx->outputs[1])) - ff_inlink_request_frame(ctx->inputs[1 + s->selir]); - return 0; + if (s->ir_load && selir != s->selir) + continue; + + if (!s->eof_coeffs[selir]) { + ret = check_ir(ctx->inputs[1 + selir]); + if (ret < 0) + return ret; + + if (ff_outlink_get_status(ctx->inputs[1 + selir]) == AVERROR_EOF) + s->eof_coeffs[selir] = 1; + + if (!s->eof_coeffs[selir]) { + if (ff_outlink_frame_wanted(ctx->outputs[0])) + ff_inlink_request_frame(ctx->inputs[1 + selir]); + else if (s->response && ff_outlink_frame_wanted(ctx->outputs[1])) + ff_inlink_request_frame(ctx->inputs[1 + selir]); + return 0; + } } - } - if (!s->have_coeffs[s->selir] && s->eof_coeffs[s->selir]) { - ret = convert_coeffs(ctx, s->selir); - if (ret < 0) - return ret; + if (!s->have_coeffs[selir] && s->eof_coeffs[selir]) { + ret = convert_coeffs(ctx, selir); + if (ret < 0) + return ret; + } } if (s->selir != s->prev_selir && s->loading[0] <= 0) { @@ -830,6 +838,9 @@ static const AVOption afir_options[] = { { "auto", "set auto processing precision", 0, AV_OPT_TYPE_CONST, {.i64=0}, 0, 0, AF, "precision" }, { "float", "set single-floating point processing precision", 0, AV_OPT_TYPE_CONST, {.i64=1}, 0, 0, AF, "precision" }, { "double","set double-floating point processing precision", 0, AV_OPT_TYPE_CONST, {.i64=2}, 0, 0, AF, "precision" }, + { "irload", "set IR loading type", OFFSET(ir_load), AV_OPT_TYPE_INT, {.i64=0}, 0, 1, AF, "irload" }, + { "init", "load all IRs on init", 0, AV_OPT_TYPE_CONST, {.i64=0}, 0, 0, AF, "irload" }, + { "access", "load IR on access", 0, AV_OPT_TYPE_CONST, {.i64=1}, 0, 0, AF, "irload" }, { NULL } }; diff --git a/libavfilter/af_afir.h b/libavfilter/af_afir.h index 099897d0bbf..7c9a3b3e31f 100644 --- a/libavfilter/af_afir.h +++ b/libavfilter/af_afir.h @@ -65,6 +65,7 @@ typedef struct AudioFIRContext { int gtype; float ir_gain; int ir_format; + int ir_load; float max_ir_len; int response; int w, h; From 8b0ec740cb9f6f30b4ec3d68d5bd871760fc80f3 Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Tue, 25 Apr 2023 20:33:08 +0200 Subject: [PATCH 0798/2172] avfilter/af_afir: fix remaining artifacts on IR switch --- libavfilter/af_afir.c | 27 +++++++++++++-------------- 1 file changed, 13 insertions(+), 14 deletions(-) diff --git a/libavfilter/af_afir.c b/libavfilter/af_afir.c index 24fb8c1abea..e2cb14aba5e 100644 --- a/libavfilter/af_afir.c +++ b/libavfilter/af_afir.c @@ -112,7 +112,7 @@ static int fir_channel(AVFilterContext *ctx, AVFrame *out, int ch) for (int offset = 0; offset < out->nb_samples; offset += min_part_size) { switch (s->format) { case AV_SAMPLE_FMT_FLTP: - if (prev_selir != selir) { + if (prev_selir != selir && s->loading[ch] != 0) { const float *xfade0 = (const float *)s->xfade[0]->extended_data[ch]; const float *xfade1 = (const float *)s->xfade[1]->extended_data[ch]; float *src0 = (float *)s->fadein[0]->extended_data[ch]; @@ -125,7 +125,7 @@ static int fir_channel(AVFilterContext *ctx, AVFrame *out, int ch) fir_quantum_float(ctx, s->fadein[0], ch, offset, 0, prev_selir); fir_quantum_float(ctx, s->fadein[1], ch, offset, 0, selir); - if (s->loading[ch] > 0 && s->loading[ch] <= min_part_size) { + if (s->loading[ch] > s->max_offset[selir]) { for (int n = 0; n < min_part_size; n++) dst[n] = xfade1[n] * src0[n] + xfade0[n] * src1[n]; s->loading[ch] = 0; @@ -137,7 +137,7 @@ static int fir_channel(AVFilterContext *ctx, AVFrame *out, int ch) } break; case AV_SAMPLE_FMT_DBLP: - if (prev_selir != selir) { + if (prev_selir != selir && s->loading[ch] != 0) { const double *xfade0 = (const double *)s->xfade[0]->extended_data[ch]; const double *xfade1 = (const double *)s->xfade[1]->extended_data[ch]; double *src0 = (double *)s->fadein[0]->extended_data[ch]; @@ -150,7 +150,7 @@ static int fir_channel(AVFilterContext *ctx, AVFrame *out, int ch) fir_quantum_double(ctx, s->fadein[0], ch, offset, 0, prev_selir); fir_quantum_double(ctx, s->fadein[1], ch, offset, 0, selir); - if (s->loading[ch] > 0 && s->loading[ch] <= min_part_size) { + if (s->loading[ch] > s->max_offset[selir]) { for (int n = 0; n < min_part_size; n++) dst[n] = xfade1[n] * src0[n] + xfade0[n] * src1[n]; s->loading[ch] = 0; @@ -163,8 +163,8 @@ static int fir_channel(AVFilterContext *ctx, AVFrame *out, int ch) break; } - if (selir != prev_selir && s->loading[ch] > 0) - s->loading[ch] -= min_part_size; + if (selir != prev_selir && s->loading[ch] != 0) + s->loading[ch] += min_part_size; } return 0; @@ -346,11 +346,11 @@ static int convert_coeffs(AVFilterContext *ctx, int selir) int nb_partitions = FFMIN(step, (left + part_size - 1) / part_size); s->nb_segments[selir] = i + 1; - s->max_offset[selir] = offset; ret = init_segment(ctx, &s->seg[selir][i], selir, offset, nb_partitions, part_size, i); if (ret < 0) return ret; offset += nb_partitions * part_size; + s->max_offset[selir] = offset; left -= nb_partitions * part_size; part_size *= 2; part_size = FFMIN(part_size, max_part_size); @@ -503,18 +503,13 @@ static int activate(AVFilterContext *ctx) } } - if (s->selir != s->prev_selir && s->loading[0] <= 0) { - for (int ch = 0; ch < s->nb_channels; ch++) - s->loading[ch] = s->max_offset[s->selir] + s->max_part_size; - } - available = ff_inlink_queued_samples(ctx->inputs[0]); wanted = FFMAX(s->min_part_size, (available / s->min_part_size) * s->min_part_size); ret = ff_inlink_consume_samples(ctx->inputs[0], wanted, wanted, &in); if (ret > 0) ret = fir_frame(s, in, outlink); - if (s->selir != s->prev_selir && s->loading[0] <= 0) + if (s->selir != s->prev_selir && s->loading[0] == 0) s->prev_selir = s->selir; if (ret < 0) @@ -799,9 +794,13 @@ static int process_command(AVFilterContext *ctx, return ret; s->selir = FFMIN(s->nb_irs - 1, s->selir); - if (s->selir != prev_selir) + if (s->selir != prev_selir) { s->prev_selir = prev_selir; + for (int ch = 0; ch < s->nb_channels; ch++) + s->loading[ch] = 1; + } + return 0; } From f7d64881f87d66489e1f51b48d909d044203cc42 Mon Sep 17 00:00:00 2001 From: Derek Buitenhuis Date: Thu, 20 Apr 2023 15:17:28 +0100 Subject: [PATCH 0799/2172] mov: Do not blindly disable advanced edit lists if use_mfra_for is set This was a bug/mistake in dae3679a9bfa421829ef9049ae2167089a2fdef7. use_mfra_for by defintion only has an effect on fragmented MP4 files, making the check not only redundant, but also broken if a user used the option globally (i.e. set on non-fragmented MP4s). Signed-off-by: Derek Buitenhuis --- libavformat/mov.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/libavformat/mov.c b/libavformat/mov.c index 1b3c1d76837..9fdeef057ec 100644 --- a/libavformat/mov.c +++ b/libavformat/mov.c @@ -4650,12 +4650,8 @@ static int mov_read_trak(MOVContext *c, AVIOContext *pb, MOVAtom atom) * Advanced edit list support does not work with fragemented MP4s, which * have stsc, stsz, stco, and stts with zero entries in the moov atom. * In these files, trun atoms may be streamed in. - * - * It cannot be used with use_mfra_for = {pts,dts} either, as the index - * is not complete, but filled in as more trun atoms are read, as well. */ - if (!sc->stts_count || c->use_mfra_for != FF_MOV_FLAG_MFRA_AUTO && - c->advanced_editlist) { + if (!sc->stts_count && c->advanced_editlist) { av_log(c->fc, AV_LOG_VERBOSE, "advanced_editlist does not work with fragmented " "MP4. disabling.\n"); From 4fa691b761202f5e1d71f15f3645fa4ee6e1ff84 Mon Sep 17 00:00:00 2001 From: Niklas Haas Date: Sat, 22 Apr 2023 21:29:15 +0200 Subject: [PATCH 0800/2172] doc/filters/libplacebo: remove outdated example This example being first is now misleading because round-tripping through hwdownload/hwupload is neither required nor recommended. Also, the comment about avoiding format conversion is unnecessary because `libplacebo` will now inherit the input frame format by default. --- doc/filters.texi | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/doc/filters.texi b/doc/filters.texi index a7972ff736d..011b1bbc620 100644 --- a/doc/filters.texi +++ b/doc/filters.texi @@ -16330,16 +16330,6 @@ This filter supports almost all of the above options as @ref{commands}. @subsection Examples @itemize -@item -Complete example for how to initialize the Vulkan device, upload frames to the -GPU, perform filter conversion to yuv420p, and download frames back to the CPU -for output. Note that in specific cases you can get around the need to perform -format conversion by specifying the correct @code{format} filter option -corresponding to the input frames. -@example -ffmpeg -i $INPUT -init_hw_device vulkan -vf hwupload,libplacebo=format=yuv420p,hwdownload,format=yuv420p $OUTPUT -@end example - @item Tone-map input to standard gamut BT.709 output: @example From 54126920fcbf4dd2021fedac143f83e9dc419a5f Mon Sep 17 00:00:00 2001 From: Niklas Haas Date: Sat, 22 Apr 2023 21:30:48 +0200 Subject: [PATCH 0801/2172] doc/filters/libplacebo: add vaapi interop example Some testing revealed this to be a very efficient and reliable method of ingesting GPU frames into libplacebo, so it's a good idea to give as an example. --- doc/filters.texi | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/doc/filters.texi b/doc/filters.texi index 011b1bbc620..5dde79919af 100644 --- a/doc/filters.texi +++ b/doc/filters.texi @@ -16369,6 +16369,12 @@ since otherwise the VRAM roundtrip will more than offset any expected speedup. @example ffmpeg -export_side_data +film_grain ... -vf libplacebo=apply_filmgrain=true @end example + +@item +Interop with VAAPI hwdec to avoid round-tripping through RAM: +@example +ffmpeg -init_hw_device vulkan -hwaccel vaapi -hwaccel_output_format vaapi ... -vf libplacebo +@end example @end itemize @section libvmaf From e3143703e9782b3622ed747a9c552a41b1fcaede Mon Sep 17 00:00:00 2001 From: Niklas Haas Date: Sat, 22 Apr 2023 21:36:18 +0200 Subject: [PATCH 0802/2172] avfilter/vf_libplacebo: strip ICC profiles on CSP change Not doing so is an obvious oversight - the ICC profile is tied to the original colorspace, so if we change it, we should definitely strip this information. We should probably also have an extra option to control whether the ICC profile should be stripped, ignored, or applied, but for now this fixes an existing bug. --- libavfilter/vf_libplacebo.c | 1 + 1 file changed, 1 insertion(+) diff --git a/libavfilter/vf_libplacebo.c b/libavfilter/vf_libplacebo.c index ba852de08d6..66929223dd9 100644 --- a/libavfilter/vf_libplacebo.c +++ b/libavfilter/vf_libplacebo.c @@ -535,6 +535,7 @@ static int filter_frame(AVFilterLink *link, AVFrame *in) 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); + av_frame_remove_side_data(out, AV_FRAME_DATA_ICC_PROFILE); } if (s->apply_dovi || changed_csp) { av_frame_remove_side_data(out, AV_FRAME_DATA_DOVI_RPU_BUFFER); From 97befd7fcb985b0c038fb200e2c8fea9861ba1fd Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Thu, 27 Apr 2023 10:44:20 +0200 Subject: [PATCH 0803/2172] avcodec/interplayacm: do not use NULL for av_log() --- libavcodec/interplayacm.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/libavcodec/interplayacm.c b/libavcodec/interplayacm.c index a0b9655e7a1..057ab16e85a 100644 --- a/libavcodec/interplayacm.c +++ b/libavcodec/interplayacm.c @@ -37,6 +37,7 @@ static int mul_3x5 [5 * 5 * 5]; static int mul_2x11[11 * 11]; typedef struct InterplayACMContext { + AVCodecContext *avctx; GetBitContext gb; uint8_t *bitstream; int max_framesize; @@ -77,6 +78,7 @@ static av_cold int decode_init(AVCodecContext *avctx) static AVOnce init_static_once = AV_ONCE_INIT; InterplayACMContext *s = avctx->priv_data; + s->avctx = avctx; if (avctx->extradata_size < 14) return AVERROR_INVALIDDATA; @@ -343,7 +345,7 @@ static int t15(InterplayACMContext *s, unsigned ind, unsigned col) /* b = (x1) + (x2 * 3) + (x3 * 9) */ b = get_bits(gb, 5); if (b > 26) { - av_log(NULL, AV_LOG_ERROR, "Too large b = %d > 26\n", b); + av_log(s->avctx, AV_LOG_ERROR, "Too large b = %d > 26\n", b); return AVERROR_INVALIDDATA; } @@ -372,7 +374,7 @@ static int t27(InterplayACMContext *s, unsigned ind, unsigned col) /* b = (x1) + (x2 * 5) + (x3 * 25) */ b = get_bits(gb, 7); if (b > 124) { - av_log(NULL, AV_LOG_ERROR, "Too large b = %d > 124\n", b); + av_log(s->avctx, AV_LOG_ERROR, "Too large b = %d > 124\n", b); return AVERROR_INVALIDDATA; } @@ -400,7 +402,7 @@ static int t37(InterplayACMContext *s, unsigned ind, unsigned col) /* b = (x1) + (x2 * 11) */ b = get_bits(gb, 7); if (b > 120) { - av_log(NULL, AV_LOG_ERROR, "Too large b = %d > 120\n", b); + av_log(s->avctx, AV_LOG_ERROR, "Too large b = %d > 120\n", b); return AVERROR_INVALIDDATA; } From 44c8f7df03617ce524f01e1a46b4d845527843bd Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Thu, 27 Apr 2023 10:35:33 +0200 Subject: [PATCH 0804/2172] avformat/adtsenc: do not pass NULL to av_log() --- libavformat/adtsenc.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/libavformat/adtsenc.c b/libavformat/adtsenc.c index b5e9640544b..c5765cc92ee 100644 --- a/libavformat/adtsenc.c +++ b/libavformat/adtsenc.c @@ -127,14 +127,14 @@ static int adts_write_header(AVFormatContext *s) return 0; } -static int adts_write_frame_header(ADTSContext *ctx, +static int adts_write_frame_header(AVFormatContext *s, ADTSContext *ctx, uint8_t *buf, int size, int pce_size) { PutBitContext pb; unsigned full_frame_size = (unsigned)ADTS_HEADER_SIZE + size + pce_size; if (full_frame_size > ADTS_MAX_FRAME_BYTES) { - av_log(NULL, AV_LOG_ERROR, "ADTS frame size too large: %u (max %d)\n", + av_log(s, AV_LOG_ERROR, "frame size too large: %u (max %d)\n", full_frame_size, ADTS_MAX_FRAME_BYTES); return AVERROR_INVALIDDATA; } @@ -192,7 +192,7 @@ static int adts_write_packet(AVFormatContext *s, AVPacket *pkt) } } if (adts->write_adts) { - int err = adts_write_frame_header(adts, buf, pkt->size, + int err = adts_write_frame_header(s, adts, buf, pkt->size, adts->pce_size); if (err < 0) return err; From 595f0cbb4aeac1ead7c7f887d5a06ef6a1bb0fe2 Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Thu, 27 Apr 2023 11:11:27 +0200 Subject: [PATCH 0805/2172] avcodec/smacker: do not use NULL for av_log() --- libavcodec/smacker.c | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/libavcodec/smacker.c b/libavcodec/smacker.c index ecc27e9b672..a514120b65e 100644 --- a/libavcodec/smacker.c +++ b/libavcodec/smacker.c @@ -107,16 +107,16 @@ enum SmkBlockTypes { * Can read SMKTREE_DECODE_MAX_RECURSION before the first check; * does not overread gb on success. */ -static int smacker_decode_tree(GetBitContext *gb, HuffContext *hc, int length) +static int smacker_decode_tree(AVCodecContext *avctx, GetBitContext *gb, HuffContext *hc, int length) { if (length > SMKTREE_DECODE_MAX_RECURSION || length > 3 * SMKTREE_BITS) { - av_log(NULL, AV_LOG_ERROR, "Maximum tree recursion level exceeded.\n"); + av_log(avctx, AV_LOG_ERROR, "Maximum tree recursion level exceeded.\n"); return AVERROR_INVALIDDATA; } if(!get_bits1(gb)){ //Leaf if (hc->current >= 256) { - av_log(NULL, AV_LOG_ERROR, "Tree size exceeded!\n"); + av_log(avctx, AV_LOG_ERROR, "Tree size exceeded!\n"); return AVERROR_INVALIDDATA; } if (get_bits_left(gb) < 8) @@ -126,10 +126,10 @@ static int smacker_decode_tree(GetBitContext *gb, HuffContext *hc, int length) } else { //Node int r; length++; - r = smacker_decode_tree(gb, hc, length); + r = smacker_decode_tree(avctx, gb, hc, length); if(r) return r; - return smacker_decode_tree(gb, hc, length); + return smacker_decode_tree(avctx, gb, hc, length); } } @@ -138,7 +138,7 @@ static int smacker_decode_tree(GetBitContext *gb, HuffContext *hc, int length) * * Checks before the first read, can overread by 6 * SMKTREE_BITS on success. */ -static int smacker_decode_bigtree(GetBitContext *gb, DBCtx *ctx, int length) +static int smacker_decode_bigtree(AVCodecContext *avctx, GetBitContext *gb, DBCtx *ctx, int length) { // Larger length can cause segmentation faults due to too deep recursion. if (length > SMKTREE_DECODE_BIG_MAX_RECURSION) { @@ -176,12 +176,12 @@ static int smacker_decode_bigtree(GetBitContext *gb, DBCtx *ctx, int length) int r = 0, r_new, t; t = ctx->current++; - r = smacker_decode_bigtree(gb, ctx, length + 1); + r = smacker_decode_bigtree(avctx, gb, ctx, length + 1); if(r < 0) return r; ctx->values[t] = SMK_NODE | r; r++; - r_new = smacker_decode_bigtree(gb, ctx, length + 1); + r_new = smacker_decode_bigtree(avctx, gb, ctx, length + 1); if (r_new < 0) return r_new; return r + r_new; @@ -215,7 +215,7 @@ static int smacker_decode_header_tree(SmackVContext *smk, GetBitContext *gb, int i ? "high" : "low"); continue; } - err = smacker_decode_tree(gb, &h, 0); + err = smacker_decode_tree(smk->avctx, gb, &h, 0); if (err < 0) goto error; skip_bits1(gb); @@ -253,7 +253,7 @@ static int smacker_decode_header_tree(SmackVContext *smk, GetBitContext *gb, int } *recodes = ctx.values; - err = smacker_decode_bigtree(gb, &ctx, 0); + err = smacker_decode_bigtree(smk->avctx, gb, &ctx, 0); if (err < 0) goto error; skip_bits1(gb); @@ -649,7 +649,7 @@ static int smka_decode_frame(AVCodecContext *avctx, AVFrame *frame, HuffContext h; h.current = 0; skip_bits1(&gb); - if ((ret = smacker_decode_tree(&gb, &h, 0)) < 0) + if ((ret = smacker_decode_tree(avctx, &gb, &h, 0)) < 0) goto error; skip_bits1(&gb); if (h.current > 1) { From 19148a5b9f44bed660258a5896d1d12d77d3d9ab Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Fri, 13 Jan 2023 13:32:26 +0100 Subject: [PATCH 0806/2172] avfilter: add FIR equalizer coefficients source filter --- Changelog | 1 + doc/filters.texi | 65 ++++++++ libavfilter/Makefile | 1 + libavfilter/allfilters.c | 1 + libavfilter/asrc_afirsrc.c | 295 ++++++++++++++++++++++++++++++++++++- libavfilter/version.h | 2 +- 6 files changed, 360 insertions(+), 5 deletions(-) diff --git a/Changelog b/Changelog index 8268e42cbcc..b6f6682904f 100644 --- a/Changelog +++ b/Changelog @@ -5,6 +5,7 @@ version : - libaribcaption decoder - Playdate video decoder and demuxer - Extend VAAPI support for libva-win32 on Windows +- afireqsrc audio source filter version 6.0: - Radiance HDR image support diff --git a/doc/filters.texi b/doc/filters.texi index 5dde79919af..5022f96e468 100644 --- a/doc/filters.texi +++ b/doc/filters.texi @@ -7624,6 +7624,71 @@ Specifies the channel layout, and can be a string representing a channel layout. The default value of @var{channel_layout} is "stereo". @end table +@section afireqsrc + +Generate a FIR equalizer coefficients. + +The resulting stream can be used with @ref{afir} filter for filtering the audio signal. + +The filter accepts the following options: + +@table @option +@item preset, p +Set equalizer preset. +Default preset is @code{flat}. + +Available presets are: +@table @samp +@item custom +@item flat +@item acoustic +@item bass +@item beats +@item classic +@item clear +@item deep bass +@item dubstep +@item electronic +@item hard-style +@item hip-hop +@item jazz +@item metal +@item movie +@item pop +@item r&b +@item rock +@item vocal booster +@end table + +@item gains, g +Set custom gains for each band. Only used if the preset option is set to @code{custom}. +Gains are separated by white spaces and each gain is set in dBFS. +Default is @code{0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0}. + +@item bands, b +Set the custom bands from where custon equalizer gains are set. +This must be in strictly increasing order. Only used if the preset option is set to @code{custom}. +Bands are separated by white spaces and each band represent frequency in Hz. +Default is @code{25 40 63 100 160 250 400 630 1000 1600 2500 4000 6300 10000 16000 24000}. + +@item taps, t +Set number of filter coefficents in output audio stream. +Default value is @code{4096}. + +@item sample_rate, r +Set sample rate of output audio stream, default is @code{44100}. + +@item nb_samples, n +Set number of samples per each frame in output audio stream. Default is @code{1024}. + +@item interp, i +Set interpolation method for FIR equalizer coefficients. Can be @code{linear} or @code{cubic}. + +@item phase, h +Set phase type of FIR filter. Can be @code{linear} or @code{min}: minimum-phase. +Default is minimum-phase filter. +@end table + @section afirsrc Generate a FIR coefficients using frequency sampling method. diff --git a/libavfilter/Makefile b/libavfilter/Makefile index 71e198bbf9c..3347e283d9c 100644 --- a/libavfilter/Makefile +++ b/libavfilter/Makefile @@ -172,6 +172,7 @@ OBJS-$(CONFIG_VOLUMEDETECT_FILTER) += af_volumedetect.o OBJS-$(CONFIG_AEVALSRC_FILTER) += aeval.o OBJS-$(CONFIG_AFDELAYSRC_FILTER) += asrc_afdelaysrc.o +OBJS-$(CONFIG_AFIREQSRC_FILTER) += asrc_afirsrc.o OBJS-$(CONFIG_AFIRSRC_FILTER) += asrc_afirsrc.o OBJS-$(CONFIG_ANOISESRC_FILTER) += asrc_anoisesrc.o OBJS-$(CONFIG_ANULLSRC_FILTER) += asrc_anullsrc.o diff --git a/libavfilter/allfilters.c b/libavfilter/allfilters.c index d7db46c2af9..fd353ff2cc7 100644 --- a/libavfilter/allfilters.c +++ b/libavfilter/allfilters.c @@ -160,6 +160,7 @@ extern const AVFilter ff_af_volumedetect; extern const AVFilter ff_asrc_aevalsrc; extern const AVFilter ff_asrc_afdelaysrc; +extern const AVFilter ff_asrc_afireqsrc; extern const AVFilter ff_asrc_afirsrc; extern const AVFilter ff_asrc_anoisesrc; extern const AVFilter ff_asrc_anullsrc; diff --git a/libavfilter/asrc_afirsrc.c b/libavfilter/asrc_afirsrc.c index d2ea92c41c7..2f09579c9cd 100644 --- a/libavfilter/asrc_afirsrc.c +++ b/libavfilter/asrc_afirsrc.c @@ -18,7 +18,9 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#include "libavutil/cpu.h" #include "libavutil/channel_layout.h" +#include "libavutil/ffmath.h" #include "libavutil/eval.h" #include "libavutil/opt.h" #include "libavutil/tx.h" @@ -38,6 +40,9 @@ typedef struct AudioFIRSourceContext { int sample_rate; int nb_samples; int win_func; + int preset; + int interp; + int phaset; AVComplexFloat *complexf; float *freq; @@ -54,8 +59,8 @@ typedef struct AudioFIRSourceContext { float *win; int64_t pts; - AVTXContext *tx_ctx; - av_tx_fn tx_fn; + AVTXContext *tx_ctx, *itx_ctx; + av_tx_fn tx_fn, itx_fn; } AudioFIRSourceContext; #define OFFSET(x) offsetof(AudioFIRSourceContext, x) @@ -104,6 +109,7 @@ static av_cold void uninit(AVFilterContext *ctx) av_freep(&s->phase); av_freep(&s->complexf); av_tx_uninit(&s->tx_ctx); + av_tx_uninit(&s->itx_ctx); } static av_cold int query_formats(AVFilterContext *ctx) @@ -131,7 +137,7 @@ static int parse_string(char *str, float **items, int *nb_items, int *items_size float *new_items; char *tail; - new_items = av_fast_realloc(NULL, items_size, 1 * sizeof(float)); + new_items = av_fast_realloc(NULL, items_size, sizeof(float)); if (!new_items) return AVERROR(ENOMEM); *items = new_items; @@ -142,7 +148,7 @@ static int parse_string(char *str, float **items, int *nb_items, int *items_size do { (*items)[(*nb_items)++] = av_strtod(tail, &tail); - new_items = av_fast_realloc(*items, items_size, (*nb_items + 1) * sizeof(float)); + new_items = av_fast_realloc(*items, items_size, (*nb_items + 2) * sizeof(float)); if (!new_items) return AVERROR(ENOMEM); *items = new_items; @@ -300,3 +306,284 @@ const AVFilter ff_asrc_afirsrc = { FILTER_QUERY_FUNC(query_formats), .priv_class = &afirsrc_class, }; + +#define DEFAULT_BANDS "25 40 63 100 160 250 400 630 1000 1600 2500 4000 6300 10000 16000 24000" + +typedef struct EqPreset { + char name[16]; + float gains[16]; +} EqPreset; + +static const EqPreset eq_presets[] = { + { "flat", { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } }, + { "acoustic", { 5.0, 4.5, 4.0, 3.5, 1.5, 1.0, 1.5, 1.5, 2.0, 3.0, 3.5, 4.0, 3.7, 3.0, 3.0 } }, + { "bass", { 10.0, 8.8, 8.5, 6.5, 2.5, 1.5, 0, 0, 0, 0, 0, 0, 0, 0, 0 } }, + { "beats", { -5.5, -5.0, -4.5, -4.2, -3.5, -3.0, -1.9, 0, 0, 0, 0, 0, 0, 0, 0 } }, + { "classic", { -0.3, 0.3, -3.5, -9.0, -1.0, 0.0, 1.8, 2.1, 0.0, 0.0, 0.0, 4.4, 9.0, 9.0, 9.0 } }, + { "clear", { 3.5, 5.5, 6.5, 9.5, 8.0, 6.5, 3.5, 2.5, 1.3, 5.0, 7.0, 9.0, 10.0, 11.0, 9.0 } }, + { "deep bass", { 12.0, 8.0, 0.0, -6.7, -12.0, -9.0, -3.5, -3.5, -6.1, 0.0, -3.0, -5.0, 0.0, 1.2, 3.0 } }, + { "dubstep", { 12.0, 10.0, 0.5, -1.0, -3.0, -5.0, -5.0, -4.8, -4.5, -2.5, -1.0, 0.0, -2.5, -2.5, 0.0 } }, + { "electronic", { 4.0, 4.0, 3.5, 1.0, 0.0, -0.5, -2.0, 0.0, 2.0, 0.0, 0.0, 1.0, 3.0, 4.0, 4.5 } }, + { "hardstyle", { 6.1, 7.0, 12.0, 6.1, -5.0, -12.0, -2.5, 3.0, 6.5, 0.0, -2.2, -4.5, -6.1, -9.2, -10.0 } }, + { "hip-hop", { 4.5, 4.3, 4.0, 2.5, 1.5, 3.0, -1.0, -1.5, -1.5, 1.5, 0.0, -1.0, 0.0, 1.5, 3.0 } }, + { "jazz", { 0.0, 0.0, 0.0, 2.0, 4.0, 5.9, -5.9, -4.5, -2.5, 2.5, 1.0, -0.8, -0.8, -0.8, -0.8 } }, + { "metal", { 10.5, 10.5, 7.5, 0.0, 2.0, 5.5, 0.0, 0.0, 0.0, 6.1, 0.0, 0.0, 6.1, 10.0, 12.0 } }, + { "movie", { 3.0, 3.0, 6.1, 8.5, 9.0, 7.0, 6.1, 6.1, 5.0, 8.0, 3.5, 3.5, 8.0, 10.0, 8.0 } }, + { "pop", { 0.0, 0.0, 0.0, 0.0, 0.0, 1.3, 2.0, 2.5, 5.0, -1.5, -2.0, -3.0, -3.0, -3.0, -3.0 } }, + { "r&b", { 3.0, 3.0, 7.0, 6.1, 4.5, 1.5, -1.5, -2.0, -1.5, 2.0, 2.5, 3.0, 3.5, 3.8, 4.0 } }, + { "rock", { 0.0, 0.0, 0.0, 3.0, 3.0, -10.0, -4.0, -1.0, 0.8, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0 } }, + { "vocal booster", { -1.5, -2.0, -3.0, -3.0, -0.5, 1.5, 3.5, 3.5, 3.5, 3.0, 2.0, 1.5, 0.0, 0.0, -1.5 } }, +}; + +static const AVOption afireqsrc_options[] = { + { "preset","set equalizer preset", OFFSET(preset), AV_OPT_TYPE_INT, {.i64=0}, -1, FF_ARRAY_ELEMS(eq_presets)-1, FLAGS, "preset" }, + { "p", "set equalizer preset", OFFSET(preset), AV_OPT_TYPE_INT, {.i64=0}, -1, FF_ARRAY_ELEMS(eq_presets)-1, FLAGS, "preset" }, + { "custom", NULL, 0, AV_OPT_TYPE_CONST, {.i64=-1}, 0, 0, FLAGS, "preset" }, + { eq_presets[ 0].name, NULL, 0, AV_OPT_TYPE_CONST, {.i64= 0}, 0, 0, FLAGS, "preset" }, + { eq_presets[ 1].name, NULL, 0, AV_OPT_TYPE_CONST, {.i64= 1}, 0, 0, FLAGS, "preset" }, + { eq_presets[ 2].name, NULL, 0, AV_OPT_TYPE_CONST, {.i64= 2}, 0, 0, FLAGS, "preset" }, + { eq_presets[ 3].name, NULL, 0, AV_OPT_TYPE_CONST, {.i64= 3}, 0, 0, FLAGS, "preset" }, + { eq_presets[ 4].name, NULL, 0, AV_OPT_TYPE_CONST, {.i64= 4}, 0, 0, FLAGS, "preset" }, + { eq_presets[ 5].name, NULL, 0, AV_OPT_TYPE_CONST, {.i64= 5}, 0, 0, FLAGS, "preset" }, + { eq_presets[ 6].name, NULL, 0, AV_OPT_TYPE_CONST, {.i64= 6}, 0, 0, FLAGS, "preset" }, + { eq_presets[ 7].name, NULL, 0, AV_OPT_TYPE_CONST, {.i64= 7}, 0, 0, FLAGS, "preset" }, + { eq_presets[ 8].name, NULL, 0, AV_OPT_TYPE_CONST, {.i64= 8}, 0, 0, FLAGS, "preset" }, + { eq_presets[ 9].name, NULL, 0, AV_OPT_TYPE_CONST, {.i64= 9}, 0, 0, FLAGS, "preset" }, + { eq_presets[10].name, NULL, 0, AV_OPT_TYPE_CONST, {.i64=10}, 0, 0, FLAGS, "preset" }, + { eq_presets[11].name, NULL, 0, AV_OPT_TYPE_CONST, {.i64=11}, 0, 0, FLAGS, "preset" }, + { eq_presets[12].name, NULL, 0, AV_OPT_TYPE_CONST, {.i64=12}, 0, 0, FLAGS, "preset" }, + { eq_presets[13].name, NULL, 0, AV_OPT_TYPE_CONST, {.i64=13}, 0, 0, FLAGS, "preset" }, + { eq_presets[14].name, NULL, 0, AV_OPT_TYPE_CONST, {.i64=14}, 0, 0, FLAGS, "preset" }, + { eq_presets[15].name, NULL, 0, AV_OPT_TYPE_CONST, {.i64=15}, 0, 0, FLAGS, "preset" }, + { eq_presets[16].name, NULL, 0, AV_OPT_TYPE_CONST, {.i64=16}, 0, 0, FLAGS, "preset" }, + { eq_presets[17].name, NULL, 0, AV_OPT_TYPE_CONST, {.i64=17}, 0, 0, FLAGS, "preset" }, + { "gains", "set gain values per band", OFFSET(magnitude_str), AV_OPT_TYPE_STRING, {.str="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0"}, 0, 0, FLAGS }, + { "g", "set gain values per band", OFFSET(magnitude_str), AV_OPT_TYPE_STRING, {.str="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0"}, 0, 0, FLAGS }, + { "bands", "set central frequency values per band", OFFSET(freq_points_str), AV_OPT_TYPE_STRING, {.str=DEFAULT_BANDS}, 0, 0, FLAGS }, + { "b", "set central frequency values per band", OFFSET(freq_points_str), AV_OPT_TYPE_STRING, {.str=DEFAULT_BANDS}, 0, 0, FLAGS }, + { "taps", "set number of taps", OFFSET(nb_taps), AV_OPT_TYPE_INT, {.i64=4096}, 16, UINT16_MAX, FLAGS }, + { "t", "set number of taps", OFFSET(nb_taps), AV_OPT_TYPE_INT, {.i64=4096}, 16, UINT16_MAX, FLAGS }, + { "sample_rate", "set sample rate", OFFSET(sample_rate), AV_OPT_TYPE_INT, {.i64=44100}, 1, INT_MAX, FLAGS }, + { "r", "set sample rate", OFFSET(sample_rate), AV_OPT_TYPE_INT, {.i64=44100}, 1, INT_MAX, FLAGS }, + { "nb_samples", "set the number of samples per requested frame", OFFSET(nb_samples), AV_OPT_TYPE_INT, {.i64 = 1024}, 1, INT_MAX, FLAGS }, + { "n", "set the number of samples per requested frame", OFFSET(nb_samples), AV_OPT_TYPE_INT, {.i64 = 1024}, 1, INT_MAX, FLAGS }, + { "interp","set the interpolation", OFFSET(interp), AV_OPT_TYPE_INT, {.i64=0}, 0, 1, FLAGS, "interp" }, + { "i", "set the interpolation", OFFSET(interp), AV_OPT_TYPE_INT, {.i64=0}, 0, 1, FLAGS, "interp" }, + { "linear", NULL, 0, AV_OPT_TYPE_CONST, {.i64=0}, 0, 0, FLAGS, "interp" }, + { "cubic", NULL, 0, AV_OPT_TYPE_CONST, {.i64=1}, 0, 0, FLAGS, "interp" }, + { "phase","set the phase", OFFSET(phaset), AV_OPT_TYPE_INT, {.i64=1}, 0, 1, FLAGS, "phase" }, + { "h", "set the phase", OFFSET(phaset), AV_OPT_TYPE_INT, {.i64=1}, 0, 1, FLAGS, "phase" }, + { "linear", "linear phase", 0, AV_OPT_TYPE_CONST, {.i64=0}, 0, 0, FLAGS, "phase" }, + { "min", "minimum phase", 0, AV_OPT_TYPE_CONST, {.i64=1}, 0, 0, FLAGS, "phase" }, + {NULL} +}; + +AVFILTER_DEFINE_CLASS(afireqsrc); + +static void eq_interp(AVComplexFloat *complexf, + const float *freq, + const float *magnitude, + int m, int interp, int minterp, + const float factor) +{ + for (int i = 0; i < minterp; i++) { + for (int j = 0; j < m; j++) { + const float x = factor * i; + + if (x <= freq[j+1]) { + float g; + + if (interp == 0) { + const float d = freq[j+1] - freq[j]; + const float d0 = x - freq[j]; + const float d1 = freq[j+1] - x; + const float g0 = magnitude[j]; + const float g1 = magnitude[j+1]; + + if (d0 && d1) { + g = (d0 * g1 + d1 * g0) / d; + } else if (d0) { + g = g1; + } else { + g = g0; + } + } else { + if (x <= freq[j]) { + g = magnitude[j]; + } else { + float x1, x2, x3; + float a, b, c, d; + float m0, m1, m2, msum; + const float unit = freq[j+1] - freq[j]; + + m0 = j != 0 ? unit * (magnitude[j] - magnitude[j-1]) / (freq[j] - freq[j-1]) : 0; + m1 = magnitude[j+1] - magnitude[j]; + m2 = j != minterp - 1 ? unit * (magnitude[j+2] - magnitude[j+1]) / (freq[j+2] - freq[j+1]) : 0; + + msum = fabsf(m0) + fabsf(m1); + m0 = msum > 0.f ? (fabsf(m0) * m1 + fabsf(m1) * m0) / msum : 0.f; + msum = fabsf(m1) + fabsf(m2); + m1 = msum > 0.f ? (fabsf(m1) * m2 + fabsf(m2) * m1) / msum : 0.f; + + d = magnitude[j]; + c = m0; + b = 3.f * magnitude[j+1] - m1 - 2.f * c - 3.f * d; + a = magnitude[j+1] - b - c - d; + + x1 = (x - freq[j]) / unit; + x2 = x1 * x1; + x3 = x2 * x1; + + g = a * x3 + b * x2 + c * x1 + d; + } + } + + complexf[i].re = g; + complexf[i].im = 0; + complexf[minterp * 2 - i - 1].re = g; + complexf[minterp * 2 - i - 1].im = 0; + + break; + } + } + } +} + +static av_cold int config_eq_output(AVFilterLink *outlink) +{ + AVFilterContext *ctx = outlink->src; + AudioFIRSourceContext *s = ctx->priv; + int fft_size, middle, asize, ret; + float scale, factor; + + s->nb_freq = s->nb_magnitude = 0; + if (s->preset < 0) { + ret = parse_string(s->freq_points_str, &s->freq, &s->nb_freq, &s->freq_size); + if (ret < 0) + return ret; + + ret = parse_string(s->magnitude_str, &s->magnitude, &s->nb_magnitude, &s->magnitude_size); + if (ret < 0) + return ret; + } else { + char *freq_str; + + s->nb_magnitude = FF_ARRAY_ELEMS(eq_presets[s->preset].gains); + + freq_str = av_strdup(DEFAULT_BANDS); + if (!freq_str) + return AVERROR(ENOMEM); + + ret = parse_string(freq_str, &s->freq, &s->nb_freq, &s->freq_size); + av_free(freq_str); + if (ret < 0) + return ret; + + s->magnitude = av_calloc(s->nb_magnitude, sizeof(*s->magnitude)); + if (!s->magnitude) + return AVERROR(ENOMEM); + memcpy(s->magnitude, eq_presets[s->preset].gains, sizeof(*s->magnitude) * s->nb_magnitude); + } + + if (s->nb_freq != s->nb_magnitude || s->nb_freq < 2) { + av_log(ctx, AV_LOG_ERROR, "Number of bands and gains must be same and >= 2.\n"); + return AVERROR(EINVAL); + } + + s->freq[s->nb_freq] = outlink->sample_rate * 0.5f; + s->magnitude[s->nb_freq] = s->magnitude[s->nb_freq-1]; + + fft_size = s->nb_taps * 2; + factor = FFMIN(outlink->sample_rate * 0.5f, s->freq[s->nb_freq - 1]) / (float)fft_size; + asize = FFALIGN(fft_size, av_cpu_max_align()); + s->complexf = av_calloc(asize * 2, sizeof(*s->complexf)); + if (!s->complexf) + return AVERROR(ENOMEM); + + scale = 1.f; + ret = av_tx_init(&s->itx_ctx, &s->itx_fn, AV_TX_FLOAT_FFT, 1, fft_size, &scale, 0); + if (ret < 0) + return ret; + + s->taps = av_calloc(s->nb_taps, sizeof(*s->taps)); + if (!s->taps) + return AVERROR(ENOMEM); + + eq_interp(s->complexf, s->freq, s->magnitude, s->nb_freq, s->interp, s->nb_taps, factor); + + for (int i = 0; i < fft_size; i++) + s->complexf[i].re = ff_exp10f(s->complexf[i].re / 20.f); + + if (s->phaset) { + const float threshold = powf(10.f, -100.f / 20.f); + const float logt = logf(threshold); + + scale = 1.f; + ret = av_tx_init(&s->tx_ctx, &s->tx_fn, AV_TX_FLOAT_FFT, 0, fft_size, &scale, 0); + if (ret < 0) + return ret; + + for (int i = 0; i < fft_size; i++) + s->complexf[i].re = s->complexf[i].re < threshold ? logt : logf(s->complexf[i].re); + + s->itx_fn(s->itx_ctx, s->complexf + asize, s->complexf, sizeof(float)); + for (int i = 0; i < fft_size; i++) { + s->complexf[i + asize].re /= fft_size; + s->complexf[i + asize].im /= fft_size; + } + + for (int i = 1; i < s->nb_taps; i++) { + s->complexf[asize + i].re += s->complexf[asize + fft_size - i].re; + s->complexf[asize + i].im -= s->complexf[asize + fft_size - i].im; + s->complexf[asize + fft_size - i].re = 0.f; + s->complexf[asize + fft_size - i].im = 0.f; + } + s->complexf[asize + s->nb_taps - 1].im *= -1.f; + + s->tx_fn(s->tx_ctx, s->complexf, s->complexf + asize, sizeof(float)); + + for (int i = 0; i < fft_size; i++) { + float eR = expf(s->complexf[i].re); + + s->complexf[i].re = eR * cosf(s->complexf[i].im); + s->complexf[i].im = eR * sinf(s->complexf[i].im); + } + + s->itx_fn(s->itx_ctx, s->complexf + asize, s->complexf, sizeof(float)); + + for (int i = 0; i < s->nb_taps; i++) + s->taps[i] = s->complexf[i + asize].re / fft_size; + } else { + s->itx_fn(s->itx_ctx, s->complexf + asize, s->complexf, sizeof(float)); + + middle = s->nb_taps / 2; + for (int i = 0; i < middle; i++) { + s->taps[middle - i] = s->complexf[i + asize].re / fft_size; + s->taps[middle + i] = s->complexf[i + asize].re / fft_size; + } + } + + s->pts = 0; + + return 0; +} + +static const AVFilterPad afireqsrc_outputs[] = { + { + .name = "default", + .type = AVMEDIA_TYPE_AUDIO, + .config_props = config_eq_output, + }, +}; + +const AVFilter ff_asrc_afireqsrc = { + .name = "afireqsrc", + .description = NULL_IF_CONFIG_SMALL("Generate a FIR equalizer coefficients audio stream."), + .uninit = uninit, + .activate = activate, + .priv_size = sizeof(AudioFIRSourceContext), + .inputs = NULL, + FILTER_OUTPUTS(afireqsrc_outputs), + FILTER_QUERY_FUNC(query_formats), + .priv_class = &afireqsrc_class, +}; diff --git a/libavfilter/version.h b/libavfilter/version.h index 523a7fe0a6e..f191d98883f 100644 --- a/libavfilter/version.h +++ b/libavfilter/version.h @@ -31,7 +31,7 @@ #include "version_major.h" -#define LIBAVFILTER_VERSION_MINOR 5 +#define LIBAVFILTER_VERSION_MINOR 6 #define LIBAVFILTER_VERSION_MICRO 100 From 4e57a0f35a56a4524648530ae6fd9c7f7770d8ca Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Thu, 27 Apr 2023 22:47:31 +0200 Subject: [PATCH 0807/2172] avfilter/afir_template: avoid multiplications if memcpy is enough --- libavfilter/afir_template.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/libavfilter/afir_template.c b/libavfilter/afir_template.c index 0f0500d8b3b..7c6573eeec8 100644 --- a/libavfilter/afir_template.c +++ b/libavfilter/afir_template.c @@ -294,6 +294,7 @@ static int fn(fir_quantum)(AVFilterContext *ctx, AVFrame *out, int ch, int ioffs const int nb_samples = FFMIN(min_part_size, out->nb_samples - offset); const int nb_segments = s->nb_segments[selir]; const float dry_gain = s->dry_gain; + const float wet_gain = s->wet_gain; for (int segment = 0; segment < nb_segments; segment++) { AudioFIRSegment *seg = &s->seg[selir][segment]; @@ -310,7 +311,9 @@ static int fn(fir_quantum)(AVFilterContext *ctx, AVFrame *out, int ch, int ioffs int j; seg->part_index[ch] = seg->part_index[ch] % nb_partitions; - if (min_part_size >= 8) { + if (dry_gain == 1.f) { + memcpy(src + input_offset, in, nb_samples * sizeof(*src)); + } else if (min_part_size >= 8) { #if DEPTH == 32 s->fdsp->vector_fmul_scalar(src + input_offset, in, dry_gain, FFALIGN(nb_samples, 4)); #else @@ -374,19 +377,19 @@ static int fn(fir_quantum)(AVFilterContext *ctx, AVFrame *out, int ch, int ioffs seg->part_index[ch] = (seg->part_index[ch] + 1) % nb_partitions; } - if (s->wet_gain == 1.f) + if (wet_gain == 1.f) return 0; if (min_part_size >= 8) { #if DEPTH == 32 - s->fdsp->vector_fmul_scalar(ptr, ptr, s->wet_gain, FFALIGN(nb_samples, 4)); + s->fdsp->vector_fmul_scalar(ptr, ptr, wet_gain, FFALIGN(nb_samples, 4)); #else - s->fdsp->vector_dmul_scalar(ptr, ptr, s->wet_gain, FFALIGN(nb_samples, 8)); + s->fdsp->vector_dmul_scalar(ptr, ptr, wet_gain, FFALIGN(nb_samples, 8)); #endif emms_c(); } else { for (int n = 0; n < nb_samples; n++) - ptr[n] *= s->wet_gain; + ptr[n] *= wet_gain; } return 0; From 7ed6f28a7cee1344f8ae61737cbb8364dec8cb24 Mon Sep 17 00:00:00 2001 From: Ting Fu Date: Thu, 27 Apr 2023 17:43:44 +0800 Subject: [PATCH 0808/2172] lavfi/dnn: modify dnn interface for removing native backend Native backend will be removed in following commits, so change the dnn interface and modify the error message in it first. Signed-off-by: Ting Fu --- libavfilter/dnn/dnn_interface.c | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/libavfilter/dnn/dnn_interface.c b/libavfilter/dnn/dnn_interface.c index 554a36b0dc7..5b1695a1dd2 100644 --- a/libavfilter/dnn/dnn_interface.c +++ b/libavfilter/dnn/dnn_interface.c @@ -24,7 +24,6 @@ */ #include "../dnn_interface.h" -#include "dnn_backend_native.h" #include "dnn_backend_tf.h" #include "dnn_backend_openvino.h" #include "libavutil/mem.h" @@ -39,13 +38,6 @@ DNNModule *ff_get_dnn_module(DNNBackendType backend_type) } switch(backend_type){ - case DNN_NATIVE: - dnn_module->load_model = &ff_dnn_load_model_native; - dnn_module->execute_model = &ff_dnn_execute_model_native; - dnn_module->get_result = &ff_dnn_get_result_native; - dnn_module->flush = &ff_dnn_flush_native; - dnn_module->free_model = &ff_dnn_free_model_native; - break; case DNN_TF: #if (CONFIG_LIBTENSORFLOW == 1) dnn_module->load_model = &ff_dnn_load_model_tf; @@ -71,7 +63,7 @@ DNNModule *ff_get_dnn_module(DNNBackendType backend_type) #endif break; default: - av_log(NULL, AV_LOG_ERROR, "Module backend_type is not native or tensorflow\n"); + av_log(NULL, AV_LOG_ERROR, "Module backend_type is not supported or enabled.\n"); av_freep(&dnn_module); return NULL; } From a9fb1417192d9922c891315350f96ef0f71726c4 Mon Sep 17 00:00:00 2001 From: Ting Fu Date: Thu, 27 Apr 2023 17:43:45 +0800 Subject: [PATCH 0809/2172] lavfi/dnn: Modified DNN native backend related tools and docs. Will remove native backend, so change the default backend in filters, and also remove the python scripts which generate native model file. Signed-off-by: Ting Fu --- doc/filters.texi | 39 +- libavfilter/vf_derain.c | 2 +- libavfilter/vf_dnn_processing.c | 2 +- libavfilter/vf_sr.c | 2 +- tools/python/convert.py | 56 --- tools/python/convert_from_tensorflow.py | 607 ------------------------ tools/python/convert_header.py | 26 - 7 files changed, 7 insertions(+), 727 deletions(-) delete mode 100644 tools/python/convert.py delete mode 100644 tools/python/convert_from_tensorflow.py delete mode 100644 tools/python/convert_header.py diff --git a/doc/filters.texi b/doc/filters.texi index 5022f96e468..01a71223a12 100644 --- a/doc/filters.texi +++ b/doc/filters.texi @@ -11403,9 +11403,6 @@ See @url{http://openaccess.thecvf.com/content_ECCV_2018/papers/Xia_Li_Recurrent_ Training as well as model generation scripts are provided in the repository at @url{https://github.com/XueweiMeng/derain_filter.git}. -Native model files (.model) can be generated from TensorFlow model -files (.pb) by using tools/python/convert.py - The filter accepts the following options: @table @option @@ -11426,21 +11423,16 @@ Specify which DNN backend to use for model loading and execution. This option ac the following values: @table @samp -@item native -Native implementation of DNN loading and execution. - @item tensorflow TensorFlow backend. To enable this backend you need to install the TensorFlow for C library (see @url{https://www.tensorflow.org/install/lang_c}) and configure FFmpeg with @code{--enable-libtensorflow} @end table -Default value is @samp{native}. @item model Set path to model file specifying network architecture and its parameters. -Note that different backends use different file formats. TensorFlow and native -backend can load files for only its format. +Note that different backends use different file formats. TensorFlow can load files for only its format. @end table To get full functionality (such as async execution), please use the @ref{dnn_processing} filter. @@ -11764,9 +11756,6 @@ Specify which DNN backend to use for model loading and execution. This option ac the following values: @table @samp -@item native -Native implementation of DNN loading and execution. - @item tensorflow TensorFlow backend. To enable this backend you need to install the TensorFlow for C library (see @@ -11782,14 +11771,9 @@ be needed if the header files and libraries are not installed into system path) @end table -Default value is @samp{native}. - @item model Set path to model file specifying network architecture and its parameters. -Note that different backends use different file formats. TensorFlow, OpenVINO and native -backend can load files for only its format. - -Native model file (.model) can be generated from TensorFlow model file (.pb) by using tools/python/convert.py +Note that different backends use different file formats. TensorFlow, OpenVINO backend can load files for only its format. @item input Set the input name of the dnn network. @@ -11815,12 +11799,6 @@ Remove rain in rgb24 frame with can.pb (see @ref{derain} filter): ./ffmpeg -i rain.jpg -vf format=rgb24,dnn_processing=dnn_backend=tensorflow:model=can.pb:input=x:output=y derain.jpg @end example -@item -Halve the pixel value of the frame with format gray32f: -@example -ffmpeg -i input.jpg -vf format=grayf32,dnn_processing=model=halve_gray_float.model:input=dnn_in:output=dnn_out:dnn_backend=native -y out.native.png -@end example - @item Handle the Y channel with srcnn.pb (see @ref{sr} filter) for frame with yuv420p (planar YUV formats supported): @example @@ -21878,9 +21856,6 @@ Training scripts as well as scripts for model file (.pb) saving can be found at @url{https://github.com/XueweiMeng/sr/tree/sr_dnn_native}. Original repository is at @url{https://github.com/HighVoltageRocknRoll/sr.git}. -Native model files (.model) can be generated from TensorFlow model -files (.pb) by using tools/python/convert.py - The filter accepts the following options: @table @option @@ -21889,9 +21864,6 @@ Specify which DNN backend to use for model loading and execution. This option ac the following values: @table @samp -@item native -Native implementation of DNN loading and execution. - @item tensorflow TensorFlow backend. To enable this backend you need to install the TensorFlow for C library (see @@ -21899,13 +21871,10 @@ need to install the TensorFlow for C library (see @code{--enable-libtensorflow} @end table -Default value is @samp{native}. - @item model Set path to model file specifying network architecture and its parameters. -Note that different backends use different file formats. TensorFlow backend -can load files for both formats, while native backend can load files for only -its format. +Note that different backends use different file formats. TensorFlow, OpenVINO backend +can load files for only its format. @item scale_factor Set scale factor for SRCNN model. Allowed values are @code{2}, @code{3} and @code{4}. diff --git a/libavfilter/vf_derain.c b/libavfilter/vf_derain.c index 86e9eb8752b..7e84cd65a3e 100644 --- a/libavfilter/vf_derain.c +++ b/libavfilter/vf_derain.c @@ -43,7 +43,7 @@ static const AVOption derain_options[] = { { "filter_type", "filter type(derain/dehaze)", OFFSET(filter_type), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 1, FLAGS, "type" }, { "derain", "derain filter flag", 0, AV_OPT_TYPE_CONST, { .i64 = 0 }, 0, 0, FLAGS, "type" }, { "dehaze", "dehaze filter flag", 0, AV_OPT_TYPE_CONST, { .i64 = 1 }, 0, 0, FLAGS, "type" }, - { "dnn_backend", "DNN backend", OFFSET(dnnctx.backend_type), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 1, FLAGS, "backend" }, + { "dnn_backend", "DNN backend", OFFSET(dnnctx.backend_type), AV_OPT_TYPE_INT, { .i64 = 1 }, 0, 1, FLAGS, "backend" }, { "native", "native backend flag", 0, AV_OPT_TYPE_CONST, { .i64 = 0 }, 0, 0, FLAGS, "backend" }, #if (CONFIG_LIBTENSORFLOW == 1) { "tensorflow", "tensorflow backend flag", 0, AV_OPT_TYPE_CONST, { .i64 = 1 }, 0, 0, FLAGS, "backend" }, diff --git a/libavfilter/vf_dnn_processing.c b/libavfilter/vf_dnn_processing.c index 4462915073d..968df666fc5 100644 --- a/libavfilter/vf_dnn_processing.c +++ b/libavfilter/vf_dnn_processing.c @@ -45,7 +45,7 @@ typedef struct DnnProcessingContext { #define OFFSET(x) offsetof(DnnProcessingContext, dnnctx.x) #define FLAGS AV_OPT_FLAG_FILTERING_PARAM | AV_OPT_FLAG_VIDEO_PARAM static const AVOption dnn_processing_options[] = { - { "dnn_backend", "DNN backend", OFFSET(backend_type), AV_OPT_TYPE_INT, { .i64 = 0 }, INT_MIN, INT_MAX, FLAGS, "backend" }, + { "dnn_backend", "DNN backend", OFFSET(backend_type), AV_OPT_TYPE_INT, { .i64 = 1 }, INT_MIN, INT_MAX, FLAGS, "backend" }, { "native", "native backend flag", 0, AV_OPT_TYPE_CONST, { .i64 = 0 }, 0, 0, FLAGS, "backend" }, #if (CONFIG_LIBTENSORFLOW == 1) { "tensorflow", "tensorflow backend flag", 0, AV_OPT_TYPE_CONST, { .i64 = 1 }, 0, 0, FLAGS, "backend" }, diff --git a/libavfilter/vf_sr.c b/libavfilter/vf_sr.c index cb24c096ced..e9fe746baeb 100644 --- a/libavfilter/vf_sr.c +++ b/libavfilter/vf_sr.c @@ -46,7 +46,7 @@ typedef struct SRContext { #define OFFSET(x) offsetof(SRContext, x) #define FLAGS AV_OPT_FLAG_FILTERING_PARAM | AV_OPT_FLAG_VIDEO_PARAM static const AVOption sr_options[] = { - { "dnn_backend", "DNN backend used for model execution", OFFSET(dnnctx.backend_type), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 1, FLAGS, "backend" }, + { "dnn_backend", "DNN backend used for model execution", OFFSET(dnnctx.backend_type), AV_OPT_TYPE_INT, { .i64 = 1 }, 0, 1, FLAGS, "backend" }, { "native", "native backend flag", 0, AV_OPT_TYPE_CONST, { .i64 = 0 }, 0, 0, FLAGS, "backend" }, #if (CONFIG_LIBTENSORFLOW == 1) { "tensorflow", "tensorflow backend flag", 0, AV_OPT_TYPE_CONST, { .i64 = 1 }, 0, 0, FLAGS, "backend" }, diff --git a/tools/python/convert.py b/tools/python/convert.py deleted file mode 100644 index 64cf76b2d86..00000000000 --- a/tools/python/convert.py +++ /dev/null @@ -1,56 +0,0 @@ -# Copyright (c) 2019 Guo Yejun -# -# 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 -# ============================================================================== - -# verified with Python 3.5.2 on Ubuntu 16.04 -import argparse -import os -from convert_from_tensorflow import * - -def get_arguments(): - parser = argparse.ArgumentParser(description='generate native mode model with weights from deep learning model') - parser.add_argument('--outdir', type=str, default='./', help='where to put generated files') - parser.add_argument('--infmt', type=str, default='tensorflow', help='format of the deep learning model') - parser.add_argument('infile', help='path to the deep learning model with weights') - parser.add_argument('--dump4tb', type=str, default='no', help='dump file for visualization in tensorboard') - - return parser.parse_args() - -def main(): - args = get_arguments() - - if not os.path.isfile(args.infile): - print('the specified input file %s does not exist' % args.infile) - exit(1) - - if not os.path.exists(args.outdir): - print('create output directory %s' % args.outdir) - os.mkdir(args.outdir) - - basefile = os.path.split(args.infile)[1] - basefile = os.path.splitext(basefile)[0] - outfile = os.path.join(args.outdir, basefile) + '.model' - dump4tb = False - if args.dump4tb.lower() in ('yes', 'true', 't', 'y', '1'): - dump4tb = True - - if args.infmt == 'tensorflow': - convert_from_tensorflow(args.infile, outfile, dump4tb) - -if __name__ == '__main__': - main() diff --git a/tools/python/convert_from_tensorflow.py b/tools/python/convert_from_tensorflow.py deleted file mode 100644 index 38e64c1c941..00000000000 --- a/tools/python/convert_from_tensorflow.py +++ /dev/null @@ -1,607 +0,0 @@ -# Copyright (c) 2019 Guo Yejun -# -# 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 -# ============================================================================== - -import tensorflow as tf -import numpy as np -import sys, struct -import convert_header as header - -__all__ = ['convert_from_tensorflow'] - -class Operand(object): - IOTYPE_INPUT = 1 - IOTYPE_OUTPUT = 2 - IOTYPE_INTERMEDIATE = IOTYPE_INPUT | IOTYPE_OUTPUT - DTYPE_FLOAT = 1 - DTYPE_UINT8 = 4 - index = 0 - def __init__(self, name, dtype, dims): - self.name = name - self.dtype = dtype - self.dims = dims - self.iotype = 0 - self.used_count = 0 - self.index = Operand.index - Operand.index = Operand.index + 1 - self.iotype2str = {Operand.IOTYPE_INPUT: 'in', Operand.IOTYPE_OUTPUT: 'out', Operand.IOTYPE_INTERMEDIATE: 'inout'} - self.dtype2str = {Operand.DTYPE_FLOAT: 'DT_FLOAT', Operand.DTYPE_UINT8: 'DT_UINT8'} - - def add_iotype(self, iotype): - self.iotype = self.iotype | iotype - if iotype == Operand.IOTYPE_INPUT: - self.used_count = self.used_count + 1 - - def __str__(self): - return "{}: (name: {}, iotype: {}, dtype: {}, dims: {}, used_count: {})".format(self.index, - self.name, self.iotype2str[self.iotype], self.dtype2str[self.dtype], - self.dims, self.used_count) - - def __lt__(self, other): - return self.index < other.index - -class TFConverter: - def __init__(self, graph_def, nodes, outfile, dump4tb): - self.graph_def = graph_def - self.nodes = nodes - self.outfile = outfile - self.dump4tb = dump4tb - self.layer_number = 0 - self.output_names = [] - self.name_node_dict = {} - self.edges = {} - self.conv_activations = {'Relu':0, 'Tanh':1, 'Sigmoid':2, 'None':3, 'LeakyRelu':4} - self.conv_paddings = {'VALID':0, 'SAME':1} - self.pool_paddings = {'VALID':0, 'SAME':1} - self.converted_nodes = set() - self.conv2d_scope_names = set() - self.conv2d_scopename_inputname_dict = {} - self.dense_scope_names = set() - self.dense_scopename_inputname_dict = {} - self.op2code = {'Conv2D':1, 'DepthToSpace':2, 'MirrorPad':3, 'Maximum':4, - 'MathBinary':5, 'MathUnary':6, 'AvgPool':7, 'MatMul':8} - self.mathbin2code = {'Sub':0, 'Add':1, 'Mul':2, 'RealDiv':3, 'Minimum':4, 'FloorMod':5} - self.mathun2code = {'Abs':0, 'Sin':1, 'Cos':2, 'Tan':3, 'Asin':4, - 'Acos':5, 'Atan':6, 'Sinh':7, 'Cosh':8, 'Tanh':9, 'Asinh':10, - 'Acosh':11, 'Atanh':12, 'Ceil':13, 'Floor':14, 'Round':15, - 'Exp':16} - self.mirrorpad_mode = {'CONSTANT':0, 'REFLECT':1, 'SYMMETRIC':2} - self.name_operand_dict = {} - - - def add_operand(self, name, type): - node = self.name_node_dict[name] - if name not in self.name_operand_dict: - dtype = node.attr['dtype'].type - if dtype == 0: - dtype = node.attr['T'].type - dims = [-1,-1,-1,-1] - if 'shape' in node.attr: - dims[0] = node.attr['shape'].shape.dim[0].size - dims[1] = node.attr['shape'].shape.dim[1].size - dims[2] = node.attr['shape'].shape.dim[2].size - dims[3] = node.attr['shape'].shape.dim[3].size - operand = Operand(name, dtype, dims) - self.name_operand_dict[name] = operand; - self.name_operand_dict[name].add_iotype(type) - return self.name_operand_dict[name].index - - - def dump_for_tensorboard(self): - graph = tf.get_default_graph() - tf.import_graph_def(self.graph_def, name="") - tf.summary.FileWriter('/tmp/graph', graph) - print('graph saved, run "tensorboard --logdir=/tmp/graph" to see it') - - - def get_conv2d_params(self, conv2d_scope_name): - knode = self.name_node_dict[conv2d_scope_name + '/kernel'] - bnode = self.name_node_dict[conv2d_scope_name + '/bias'] - - if conv2d_scope_name + '/dilation_rate' in self.name_node_dict: - dnode = self.name_node_dict[conv2d_scope_name + '/dilation_rate'] - else: - dnode = None - - # the BiasAdd name is possible be changed into the output name, - # if activation is None, and BiasAdd.next is the last op which is Identity - if conv2d_scope_name + '/BiasAdd' in self.edges: - anode = self.edges[conv2d_scope_name + '/BiasAdd'][0] - if anode.op not in self.conv_activations: - anode = None - else: - anode = None - return knode, bnode, dnode, anode - - - def get_dense_params(self, dense_scope_name): - knode = self.name_node_dict[dense_scope_name + '/kernel'] - bnode = self.name_node_dict.get(dense_scope_name + '/bias') - # the BiasAdd name is possible be changed into the output name, - # if activation is None, and BiasAdd.next is the last op which is Identity - anode = None - if bnode: - if dense_scope_name + '/BiasAdd' in self.edges: - anode = self.edges[dense_scope_name + '/BiasAdd'][0] - if anode.op not in self.conv_activations: - anode = None - else: - anode = None - return knode, bnode, anode - - - def dump_complex_conv2d_to_file(self, node, f): - assert(node.op == 'Conv2D') - self.layer_number = self.layer_number + 1 - self.converted_nodes.add(node.name) - - scope_name = TFConverter.get_scope_name(node.name) - #knode for kernel, bnode for bias, dnode for dilation, anode for activation - knode, bnode, dnode, anode = self.get_conv2d_params(scope_name) - - if dnode is not None: - dilation = struct.unpack('i', dnode.attr['value'].tensor.tensor_content[0:4])[0] - else: - dilation = 1 - - if anode is not None: - activation = anode.op - else: - activation = 'None' - - padding = node.attr['padding'].s.decode("utf-8") - # conv2d with dilation > 1 generates tens of nodes, not easy to parse them, so use this tricky method. - if dilation > 1 and scope_name + '/stack' in self.name_node_dict: - if self.name_node_dict[scope_name + '/stack'].op == "Const": - padding = 'SAME' - padding = self.conv_paddings[padding] - - ktensor = knode.attr['value'].tensor - filter_height = ktensor.tensor_shape.dim[0].size - filter_width = ktensor.tensor_shape.dim[1].size - in_channels = ktensor.tensor_shape.dim[2].size - out_channels = ktensor.tensor_shape.dim[3].size - kernel = np.frombuffer(ktensor.tensor_content, dtype=np.float32) - kernel = kernel.reshape(filter_height, filter_width, in_channels, out_channels) - kernel = np.transpose(kernel, [3, 0, 1, 2]) - - has_bias = 1 - np.array([self.op2code[node.op], dilation, padding, self.conv_activations[activation], in_channels, out_channels, filter_height, has_bias], dtype=np.uint32).tofile(f) - kernel.tofile(f) - - btensor = bnode.attr['value'].tensor - if btensor.tensor_shape.dim[0].size == 1: - bias = struct.pack("f", btensor.float_val[0]) - else: - bias = btensor.tensor_content - f.write(bias) - - input_name = self.conv2d_scopename_inputname_dict[scope_name] - input_operand_index = self.add_operand(input_name, Operand.IOTYPE_INPUT) - - if anode is not None: - output_operand_index = self.add_operand(anode.name, Operand.IOTYPE_OUTPUT) - else: - output_operand_index = self.add_operand(self.edges[bnode.name][0].name, Operand.IOTYPE_OUTPUT) - np.array([input_operand_index, output_operand_index], dtype=np.uint32).tofile(f) - - def dump_dense_to_file(self, node, f): - assert(node.op == 'MatMul') - self.layer_number = self.layer_number + 1 - self.converted_nodes.add(node.name) - - scope_name = TFConverter.get_scope_name(node.name) - #knode for kernel, bnode for bias, anode for activation - knode, bnode, anode = self.get_dense_params(scope_name.split('/')[0]) - - if bnode is not None: - has_bias = 1 - btensor = bnode.attr['value'].tensor - if btensor.tensor_shape.dim[0].size == 1: - bias = struct.pack("f", btensor.float_val[0]) - else: - bias = btensor.tensor_content - else: - has_bias = 0 - - if anode is not None: - activation = anode.op - else: - activation = 'None' - - ktensor = knode.attr['value'].tensor - in_channels = ktensor.tensor_shape.dim[0].size - out_channels = ktensor.tensor_shape.dim[1].size - if in_channels * out_channels == 1: - kernel = np.float32(ktensor.float_val[0]) - else: - kernel = np.frombuffer(ktensor.tensor_content, dtype=np.float32) - kernel = kernel.reshape(in_channels, out_channels) - kernel = np.transpose(kernel, [1, 0]) - - np.array([self.op2code[node.op], self.conv_activations[activation], in_channels, out_channels, has_bias], dtype=np.uint32).tofile(f) - kernel.tofile(f) - if has_bias: - f.write(bias) - - input_name = self.dense_scopename_inputname_dict[scope_name.split('/')[0]] - input_operand_index = self.add_operand(input_name, Operand.IOTYPE_INPUT) - - if anode is not None: - output_operand_index = self.add_operand(anode.name, Operand.IOTYPE_OUTPUT) - else: - if bnode is not None: - output_operand_index = self.add_operand(self.edges[bnode.name][0].name, Operand.IOTYPE_OUTPUT) - else: - output_operand_index = self.add_operand(self.edges[scope_name+'/concat_1'][0].name, Operand.IOTYPE_OUTPUT) - np.array([input_operand_index, output_operand_index], dtype=np.uint32).tofile(f) - - - def dump_simple_conv2d_to_file(self, node, f): - assert(node.op == 'Conv2D') - self.layer_number = self.layer_number + 1 - self.converted_nodes.add(node.name) - - node0 = self.name_node_dict[node.input[0]] - node1 = self.name_node_dict[node.input[1]] - if node0.op == 'Const': - knode = node0 - input_name = node.input[1] - else: - knode = node1 - input_name = node.input[0] - - ktensor = knode.attr['value'].tensor - filter_height = ktensor.tensor_shape.dim[0].size - filter_width = ktensor.tensor_shape.dim[1].size - in_channels = ktensor.tensor_shape.dim[2].size - out_channels = ktensor.tensor_shape.dim[3].size - if filter_height * filter_width * in_channels * out_channels == 1: - kernel = np.float32(ktensor.float_val[0]) - else: - kernel = np.frombuffer(ktensor.tensor_content, dtype=np.float32) - kernel = kernel.reshape(filter_height, filter_width, in_channels, out_channels) - kernel = np.transpose(kernel, [3, 0, 1, 2]) - - has_bias = 0 - dilation = 1 - padding = node.attr['padding'].s.decode("utf-8") - np.array([self.op2code[node.op], dilation, self.conv_paddings[padding], self.conv_activations['None'], - in_channels, out_channels, filter_height, has_bias], dtype=np.uint32).tofile(f) - kernel.tofile(f) - - input_operand_index = self.add_operand(input_name, Operand.IOTYPE_INPUT) - output_operand_index = self.add_operand(node.name, Operand.IOTYPE_OUTPUT) - np.array([input_operand_index, output_operand_index], dtype=np.uint32).tofile(f) - - - def dump_depth2space_to_file(self, node, f): - assert(node.op == 'DepthToSpace') - self.layer_number = self.layer_number + 1 - block_size = node.attr['block_size'].i - np.array([self.op2code[node.op], block_size], dtype=np.uint32).tofile(f) - self.converted_nodes.add(node.name) - input_operand_index = self.add_operand(node.input[0], Operand.IOTYPE_INPUT) - output_operand_index = self.add_operand(node.name, Operand.IOTYPE_OUTPUT) - np.array([input_operand_index, output_operand_index], dtype=np.uint32).tofile(f) - - - def dump_mirrorpad_to_file(self, node, f): - assert(node.op == 'MirrorPad') - self.layer_number = self.layer_number + 1 - mode = node.attr['mode'].s - mode = self.mirrorpad_mode[mode.decode("utf-8")] - np.array([self.op2code[node.op], mode], dtype=np.uint32).tofile(f) - pnode = self.name_node_dict[node.input[1]] - self.converted_nodes.add(pnode.name) - paddings = pnode.attr['value'].tensor.tensor_content - f.write(paddings) - self.converted_nodes.add(node.name) - input_operand_index = self.add_operand(node.input[0], Operand.IOTYPE_INPUT) - output_operand_index = self.add_operand(node.name, Operand.IOTYPE_OUTPUT) - np.array([input_operand_index, output_operand_index], dtype=np.uint32).tofile(f) - - - def dump_maximum_to_file(self, node, f): - assert(node.op == 'Maximum') - self.layer_number = self.layer_number + 1 - ynode = self.name_node_dict[node.input[1]] - y = ynode.attr['value'].tensor.float_val[0] - np.array([self.op2code[node.op]], dtype=np.uint32).tofile(f) - np.array([y], dtype=np.float32).tofile(f) - self.converted_nodes.add(node.name) - input_operand_index = self.add_operand(node.input[0], Operand.IOTYPE_INPUT) - output_operand_index = self.add_operand(node.name, Operand.IOTYPE_OUTPUT) - np.array([input_operand_index, output_operand_index], dtype=np.uint32).tofile(f) - - - def dump_mathbinary_to_file(self, node, f): - self.layer_number = self.layer_number + 1 - self.converted_nodes.add(node.name) - i0_node = self.name_node_dict[node.input[0]] - i1_node = self.name_node_dict[node.input[1]] - np.array([self.op2code['MathBinary'], self.mathbin2code[node.op]], dtype=np.uint32).tofile(f) - if i0_node.op == 'Const': - scalar = i0_node.attr['value'].tensor.float_val[0] - np.array([1], dtype=np.uint32).tofile(f) # broadcast: 1 - np.array([scalar], dtype=np.float32).tofile(f) - np.array([0], dtype=np.uint32).tofile(f) # broadcast: 0 - input_operand_index = self.add_operand(i1_node.name, Operand.IOTYPE_INPUT) - np.array([input_operand_index], dtype=np.uint32).tofile(f) - elif i1_node.op == 'Const': - scalar = i1_node.attr['value'].tensor.float_val[0] - np.array([0], dtype=np.uint32).tofile(f) - input_operand_index = self.add_operand(i0_node.name, Operand.IOTYPE_INPUT) - np.array([input_operand_index], dtype=np.uint32).tofile(f) - np.array([1], dtype=np.uint32).tofile(f) - np.array([scalar], dtype=np.float32).tofile(f) - else: - np.array([0], dtype=np.uint32).tofile(f) - input_operand_index = self.add_operand(i0_node.name, Operand.IOTYPE_INPUT) - np.array([input_operand_index], dtype=np.uint32).tofile(f) - np.array([0], dtype=np.uint32).tofile(f) - input_operand_index = self.add_operand(i1_node.name, Operand.IOTYPE_INPUT) - np.array([input_operand_index], dtype=np.uint32).tofile(f) - output_operand_index = self.add_operand(node.name, Operand.IOTYPE_OUTPUT) - np.array([output_operand_index], dtype=np.uint32).tofile(f) - - - def dump_mathunary_to_file(self, node, f): - self.layer_number = self.layer_number + 1 - self.converted_nodes.add(node.name) - i0_node = self.name_node_dict[node.input[0]] - np.array([self.op2code['MathUnary'], self.mathun2code[node.op]], dtype=np.uint32).tofile(f) - input_operand_index = self.add_operand(i0_node.name, Operand.IOTYPE_INPUT) - np.array([input_operand_index], dtype=np.uint32).tofile(f) - output_operand_index = self.add_operand(node.name, Operand.IOTYPE_OUTPUT) - np.array([output_operand_index],dtype=np.uint32).tofile(f) - - - def dump_avg_pool_to_file(self, node, f): - assert(node.op == 'AvgPool') - self.layer_number = self.layer_number + 1 - self.converted_nodes.add(node.name) - node0 = self.name_node_dict[node.input[0]] - strides = node.attr['strides'] - - # Tensorflow do not support pooling strides in batch dimension and - # current native NN do not support pooling strides in channel dimension, added assert() here. - assert(strides.list.i[1]==strides.list.i[2]) - assert(strides.list.i[0]==1) - assert(strides.list.i[3]==1) - strides = strides.list.i[1] - filter_node = node.attr['ksize'] - input_name = node.input[0] - - # Tensorflow do not support pooling ksize in batch dimension and channel dimension. - assert(filter_node.list.i[0]==1) - assert(filter_node.list.i[3]==1) - filter_height = filter_node.list.i[1] - filter_width = filter_node.list.i[2] - - padding = node.attr['padding'].s.decode("utf-8") - np.array([self.op2code[node.op], strides, self.pool_paddings[padding], filter_height], - dtype=np.uint32).tofile(f) - - input_operand_index = self.add_operand(input_name, Operand.IOTYPE_INPUT) - output_operand_index = self.add_operand(node.name, Operand.IOTYPE_OUTPUT) - np.array([input_operand_index, output_operand_index],dtype=np.uint32).tofile(f) - - - def dump_layers_to_file(self, f): - for node in self.nodes: - if node.name in self.converted_nodes: - continue - - # conv2d with dilation generates very complex nodes, so handle it in special - if self.in_conv2d_scope(node.name): - if node.op == 'Conv2D': - self.dump_complex_conv2d_to_file(node, f) - continue - if self.in_dense_scope(node.name): - if node.op == 'MatMul': - self.dump_dense_to_file(node, f) - continue - - - if node.op == 'Conv2D': - self.dump_simple_conv2d_to_file(node, f) - continue - if node.name in self.output_names: - input_name = self.id_different_scope_dict[node.name] - if TFConverter.get_scope_name(input_name)!=TFConverter.get_scope_name(node.name): - continue - if node.op == 'AvgPool': - self.dump_avg_pool_to_file(node, f) - elif node.op == 'DepthToSpace': - self.dump_depth2space_to_file(node, f) - elif node.op == 'MirrorPad': - self.dump_mirrorpad_to_file(node, f) - elif node.op == 'Maximum': - self.dump_maximum_to_file(node, f) - elif node.op in self.mathbin2code: - self.dump_mathbinary_to_file(node, f) - elif node.op in self.mathun2code: - self.dump_mathunary_to_file(node, f) - - - def dump_operands_to_file(self, f): - operands = sorted(self.name_operand_dict.values()) - for operand in operands: - #print('{}'.format(operand)) - np.array([operand.index, len(operand.name)], dtype=np.uint32).tofile(f) - f.write(operand.name.encode('utf-8')) - np.array([operand.iotype, operand.dtype], dtype=np.uint32).tofile(f) - np.array(operand.dims, dtype=np.uint32).tofile(f) - - - def dump_to_file(self): - with open(self.outfile, 'wb') as f: - f.write(header.str.encode('utf-8')) - np.array([header.major, header.minor], dtype=np.uint32).tofile(f) - self.dump_layers_to_file(f) - self.dump_operands_to_file(f) - np.array([self.layer_number, len(self.name_operand_dict)], dtype=np.uint32).tofile(f) - - - def generate_name_node_dict(self): - for node in self.nodes: - self.name_node_dict[node.name] = node - - - def generate_output_names(self): - used_names = [] - for node in self.nodes: - for input in node.input: - used_names.append(input) - - for node in self.nodes: - if node.name not in used_names: - self.output_names.append(node.name) - - - def remove_identity(self): - self.id_different_scope_dict = {} - id_nodes = [] - id_dict = {} - for node in self.nodes: - if node.op == 'Identity': - name = node.name - input = node.input[0] - id_nodes.append(node) - # do not change the output name - if name in self.output_names: - self.name_node_dict[input].name = name - self.name_node_dict[name] = self.name_node_dict[input] - del self.name_node_dict[input] - self.id_different_scope_dict[name] = input - else: - id_dict[name] = input - - for idnode in id_nodes: - self.nodes.remove(idnode) - - for node in self.nodes: - for i in range(len(node.input)): - input = node.input[i] - if input in id_dict: - node.input[i] = id_dict[input] - - - def generate_edges(self): - for node in self.nodes: - for input in node.input: - if input in self.edges: - self.edges[input].append(node) - else: - self.edges[input] = [node] - - - @staticmethod - def get_scope_name(name): - index = name.rfind('/') - if index == -1: - return "" - return name[0:index] - - - def in_conv2d_scope(self, name): - inner_scope = TFConverter.get_scope_name(name) - if inner_scope == "": - return False; - for scope in self.conv2d_scope_names: - index = inner_scope.find(scope) - if index == 0: - return True - return False - - - def in_dense_scope(self, name): - inner_scope = TFConverter.get_scope_name(name) - if inner_scope == "": - return False; - for scope in self.dense_scope_names: - index = inner_scope.find(scope) - if index == 0: - return True - return False - - def generate_sub_block_op_scope_info(self): - # mostly, conv2d/dense is a sub block in graph, get the scope name - for node in self.nodes: - if node.op == 'Conv2D': - scope = TFConverter.get_scope_name(node.name) - # for the case tf.nn.conv2d is called directly - if scope == '': - continue - # for the case tf.nn.conv2d is called within a scope - if scope + '/kernel' not in self.name_node_dict: - continue - self.conv2d_scope_names.add(scope) - elif node.op == 'MatMul': - scope = TFConverter.get_scope_name(node.name) - # for the case tf.nn.dense is called directly - if scope == '': - continue - # for the case tf.nn.dense is called within a scope - if scope + '/kernel' not in self.name_node_dict and scope.split('/Tensordot')[0] + '/kernel' not in self.name_node_dict: - continue - self.dense_scope_names.add(scope.split('/Tensordot')[0]) - - # get the input name to the conv2d/dense sub block - for node in self.nodes: - scope = TFConverter.get_scope_name(node.name) - if scope in self.conv2d_scope_names: - if node.op == 'Conv2D' or node.op == 'Shape': - for inp in node.input: - if TFConverter.get_scope_name(inp) != scope: - self.conv2d_scopename_inputname_dict[scope] = inp - elif scope in self.dense_scope_names: - if node.op == 'MatMul' or node.op == 'Shape': - for inp in node.input: - if TFConverter.get_scope_name(inp) != scope: - self.dense_scopename_inputname_dict[scope] = inp - elif scope.split('/Tensordot')[0] in self.dense_scope_names: - if node.op == 'Transpose': - for inp in node.input: - if TFConverter.get_scope_name(inp).find(scope)<0 and TFConverter.get_scope_name(inp).find(scope.split('/')[0])<0: - self.dense_scopename_inputname_dict[scope.split('/Tensordot')[0]] = inp - - - def run(self): - self.generate_name_node_dict() - self.generate_output_names() - self.remove_identity() - self.generate_edges() - self.generate_sub_block_op_scope_info() - - if self.dump4tb: - self.dump_for_tensorboard() - - self.dump_to_file() - - -def convert_from_tensorflow(infile, outfile, dump4tb): - with open(infile, 'rb') as f: - # read the file in .proto format - graph_def = tf.GraphDef() - graph_def.ParseFromString(f.read()) - nodes = graph_def.node - - converter = TFConverter(graph_def, nodes, outfile, dump4tb) - converter.run() diff --git a/tools/python/convert_header.py b/tools/python/convert_header.py deleted file mode 100644 index 143f92c42ee..00000000000 --- a/tools/python/convert_header.py +++ /dev/null @@ -1,26 +0,0 @@ -# Copyright (c) 2019 -# -# 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 -# ============================================================================== - -str = 'FFMPEGDNNNATIVE' - -# increase major and reset minor when we have to re-convert the model file -major = 1 - -# increase minor when we don't have to re-convert the model file -minor = 23 From 78f95f10887f7273a861268e9e6b93411f59ed20 Mon Sep 17 00:00:00 2001 From: Ting Fu Date: Thu, 27 Apr 2023 17:43:46 +0800 Subject: [PATCH 0810/2172] lavfi/dnn: Remove DNN native backend According to discussion in https://etherpad.mit.edu/p/FF_dev_meeting_20221202 and the proposal in http://ffmpeg.org/pipermail/ffmpeg-devel/2022-December/304534.html, the DNN native backend should be removed at first step. All the DNN native backend related codes are deleted. Signed-off-by: Ting Fu --- libavfilter/Makefile | 3 - libavfilter/dnn/Makefile | 10 - libavfilter/dnn/dnn_backend_native.c | 561 ------------------ libavfilter/dnn/dnn_backend_native.h | 149 ----- .../dnn/dnn_backend_native_layer_avgpool.c | 147 ----- .../dnn/dnn_backend_native_layer_avgpool.h | 69 --- .../dnn/dnn_backend_native_layer_conv2d.c | 265 --------- .../dnn/dnn_backend_native_layer_conv2d.h | 68 --- .../dnn/dnn_backend_native_layer_dense.c | 151 ----- .../dnn/dnn_backend_native_layer_dense.h | 65 -- .../dnn_backend_native_layer_depth2space.c | 102 ---- .../dnn_backend_native_layer_depth2space.h | 72 --- .../dnn/dnn_backend_native_layer_mathbinary.c | 193 ------ .../dnn/dnn_backend_native_layer_mathbinary.h | 54 -- .../dnn/dnn_backend_native_layer_mathunary.c | 156 ----- .../dnn/dnn_backend_native_layer_mathunary.h | 92 --- .../dnn/dnn_backend_native_layer_maximum.c | 83 --- .../dnn/dnn_backend_native_layer_maximum.h | 44 -- .../dnn/dnn_backend_native_layer_pad.c | 268 --------- .../dnn/dnn_backend_native_layer_pad.h | 43 -- libavfilter/dnn/dnn_backend_native_layers.c | 42 -- libavfilter/dnn/dnn_backend_native_layers.h | 38 -- libavfilter/dnn/dnn_backend_tf.c | 368 +----------- libavfilter/dnn_interface.h | 2 +- libavfilter/tests/dnn-layer-avgpool.c | 197 ------ libavfilter/tests/dnn-layer-conv2d.c | 248 -------- libavfilter/tests/dnn-layer-dense.c | 131 ---- libavfilter/tests/dnn-layer-depth2space.c | 102 ---- libavfilter/tests/dnn-layer-mathbinary.c | 214 ------- libavfilter/tests/dnn-layer-mathunary.c | 148 ----- libavfilter/tests/dnn-layer-maximum.c | 71 --- libavfilter/tests/dnn-layer-pad.c | 239 -------- libavfilter/vf_derain.c | 1 - libavfilter/vf_dnn_processing.c | 1 - libavfilter/vf_sr.c | 1 - tests/Makefile | 1 - tests/fate/dnn.mak | 45 -- 37 files changed, 4 insertions(+), 4440 deletions(-) delete mode 100644 libavfilter/dnn/dnn_backend_native.c delete mode 100644 libavfilter/dnn/dnn_backend_native.h delete mode 100644 libavfilter/dnn/dnn_backend_native_layer_avgpool.c delete mode 100644 libavfilter/dnn/dnn_backend_native_layer_avgpool.h delete mode 100644 libavfilter/dnn/dnn_backend_native_layer_conv2d.c delete mode 100644 libavfilter/dnn/dnn_backend_native_layer_conv2d.h delete mode 100644 libavfilter/dnn/dnn_backend_native_layer_dense.c delete mode 100644 libavfilter/dnn/dnn_backend_native_layer_dense.h delete mode 100644 libavfilter/dnn/dnn_backend_native_layer_depth2space.c delete mode 100644 libavfilter/dnn/dnn_backend_native_layer_depth2space.h delete mode 100644 libavfilter/dnn/dnn_backend_native_layer_mathbinary.c delete mode 100644 libavfilter/dnn/dnn_backend_native_layer_mathbinary.h delete mode 100644 libavfilter/dnn/dnn_backend_native_layer_mathunary.c delete mode 100644 libavfilter/dnn/dnn_backend_native_layer_mathunary.h delete mode 100644 libavfilter/dnn/dnn_backend_native_layer_maximum.c delete mode 100644 libavfilter/dnn/dnn_backend_native_layer_maximum.h delete mode 100644 libavfilter/dnn/dnn_backend_native_layer_pad.c delete mode 100644 libavfilter/dnn/dnn_backend_native_layer_pad.h delete mode 100644 libavfilter/dnn/dnn_backend_native_layers.c delete mode 100644 libavfilter/dnn/dnn_backend_native_layers.h delete mode 100644 libavfilter/tests/dnn-layer-avgpool.c delete mode 100644 libavfilter/tests/dnn-layer-conv2d.c delete mode 100644 libavfilter/tests/dnn-layer-dense.c delete mode 100644 libavfilter/tests/dnn-layer-depth2space.c delete mode 100644 libavfilter/tests/dnn-layer-mathbinary.c delete mode 100644 libavfilter/tests/dnn-layer-mathunary.c delete mode 100644 libavfilter/tests/dnn-layer-maximum.c delete mode 100644 libavfilter/tests/dnn-layer-pad.c delete mode 100644 tests/fate/dnn.mak diff --git a/libavfilter/Makefile b/libavfilter/Makefile index 3347e283d9c..70bfc78c321 100644 --- a/libavfilter/Makefile +++ b/libavfilter/Makefile @@ -635,9 +635,6 @@ 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/dnn/Makefile b/libavfilter/dnn/Makefile index 4cfbce0efc7..5d5697ea427 100644 --- a/libavfilter/dnn/Makefile +++ b/libavfilter/dnn/Makefile @@ -3,16 +3,6 @@ OBJS-$(CONFIG_DNN) += dnn/dnn_io_proc.o OBJS-$(CONFIG_DNN) += dnn/queue.o OBJS-$(CONFIG_DNN) += dnn/safe_queue.o OBJS-$(CONFIG_DNN) += dnn/dnn_backend_common.o -OBJS-$(CONFIG_DNN) += dnn/dnn_backend_native.o -OBJS-$(CONFIG_DNN) += dnn/dnn_backend_native_layers.o -OBJS-$(CONFIG_DNN) += dnn/dnn_backend_native_layer_avgpool.o -OBJS-$(CONFIG_DNN) += dnn/dnn_backend_native_layer_dense.o -OBJS-$(CONFIG_DNN) += dnn/dnn_backend_native_layer_pad.o -OBJS-$(CONFIG_DNN) += dnn/dnn_backend_native_layer_conv2d.o -OBJS-$(CONFIG_DNN) += dnn/dnn_backend_native_layer_depth2space.o -OBJS-$(CONFIG_DNN) += dnn/dnn_backend_native_layer_maximum.o -OBJS-$(CONFIG_DNN) += dnn/dnn_backend_native_layer_mathbinary.o -OBJS-$(CONFIG_DNN) += dnn/dnn_backend_native_layer_mathunary.o DNN-OBJS-$(CONFIG_LIBTENSORFLOW) += dnn/dnn_backend_tf.o DNN-OBJS-$(CONFIG_LIBOPENVINO) += dnn/dnn_backend_openvino.o diff --git a/libavfilter/dnn/dnn_backend_native.c b/libavfilter/dnn/dnn_backend_native.c deleted file mode 100644 index b53799f04d2..00000000000 --- a/libavfilter/dnn/dnn_backend_native.c +++ /dev/null @@ -1,561 +0,0 @@ -/* - * Copyright (c) 2018 Sergey Lavrushkin - * - * 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 - * DNN native backend implementation. - */ - -#include "dnn_backend_native.h" -#include "libavutil/avassert.h" -#include "dnn_backend_native_layer_conv2d.h" -#include "dnn_backend_native_layers.h" -#include "dnn_io_proc.h" -#include "dnn_backend_common.h" - -#define OFFSET(x) offsetof(NativeContext, x) -#define FLAGS AV_OPT_FLAG_FILTERING_PARAM -static const AVOption dnn_native_options[] = { - { "conv2d_threads", "threads num for conv2d layer", OFFSET(options.conv2d_threads), AV_OPT_TYPE_INT, { .i64 = 0 }, INT_MIN, INT_MAX, FLAGS }, - { "async", "use DNN async inference", OFFSET(options.async), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, FLAGS }, - { NULL }, -}; - -static const AVClass dnn_native_class = { - .class_name = "dnn_native", - .item_name = av_default_item_name, - .option = dnn_native_options, - .version = LIBAVUTIL_VERSION_INT, - .category = AV_CLASS_CATEGORY_FILTER, -}; - -static int execute_model_native(Queue *lltask_queue); - -static int extract_lltask_from_task(TaskItem *task, Queue *lltask_queue) -{ - NativeModel *native_model = task->model; - NativeContext *ctx = &native_model->ctx; - LastLevelTaskItem *lltask = av_malloc(sizeof(*lltask)); - - if (!lltask) { - av_log(ctx, AV_LOG_ERROR, "Unable to allocate space for LastLevelTaskItem\n"); - return AVERROR(ENOMEM); - } - task->inference_todo = 1; - task->inference_done = 0; - lltask->task = task; - - if (ff_queue_push_back(lltask_queue, lltask) < 0) { - av_log(ctx, AV_LOG_ERROR, "Failed to push back lltask_queue.\n"); - av_freep(&lltask); - return AVERROR(ENOMEM); - } - return 0; -} - -static int get_input_native(void *model, DNNData *input, const char *input_name) -{ - NativeModel *native_model = model; - NativeContext *ctx = &native_model->ctx; - - for (int i = 0; i < native_model->operands_num; ++i) { - DnnOperand *oprd = &native_model->operands[i]; - if (strcmp(oprd->name, input_name) == 0) { - if (oprd->type != DOT_INPUT) { - av_log(ctx, AV_LOG_ERROR, "Found \"%s\" in model, but it is not input node\n", input_name); - return AVERROR(EINVAL); - } - input->dt = oprd->data_type; - av_assert0(oprd->dims[0] == 1); - input->height = oprd->dims[1]; - input->width = oprd->dims[2]; - input->channels = oprd->dims[3]; - return 0; - } - } - - // do not find the input operand - av_log(ctx, AV_LOG_ERROR, "Could not find \"%s\" in model\n", input_name); - return AVERROR(EINVAL); -} - -static int get_output_native(void *model, const char *input_name, int input_width, int input_height, - const char *output_name, int *output_width, int *output_height) -{ - int ret = 0; - NativeModel *native_model = model; - NativeContext *ctx = &native_model->ctx; - TaskItem task; - DNNExecBaseParams exec_params = { - .input_name = input_name, - .output_names = &output_name, - .nb_output = 1, - .in_frame = NULL, - .out_frame = NULL, - }; - - ret = ff_dnn_fill_gettingoutput_task(&task, &exec_params, native_model, input_height, input_width, ctx); - if (ret != 0) { - goto err; - } - - ret = extract_lltask_from_task(&task, native_model->lltask_queue); - if (ret != 0) { - av_log(ctx, AV_LOG_ERROR, "unable to extract last level task from task.\n"); - goto err; - } - - ret = execute_model_native(native_model->lltask_queue); - *output_width = task.out_frame->width; - *output_height = task.out_frame->height; - -err: - av_frame_free(&task.out_frame); - av_frame_free(&task.in_frame); - return ret; -} - -// Loads model and its parameters that are stored in a binary file with following structure: -// layers_num,layer_type,layer_parameterss,layer_type,layer_parameters... -// For CONV layer: activation_function, input_num, output_num, kernel_size, kernel, biases -// For DEPTH_TO_SPACE layer: block_size -DNNModel *ff_dnn_load_model_native(const char *model_filename, DNNFunctionType func_type, const char *options, AVFilterContext *filter_ctx) -{ -#define DNN_NATIVE_MAGIC "FFMPEGDNNNATIVE" - DNNModel *model = NULL; - // sizeof - 1 to skip the terminating '\0' which is not written in the file - char buf[sizeof(DNN_NATIVE_MAGIC) - 1]; - int version, header_size, major_version_expected = 1; - NativeModel *native_model = NULL; - AVIOContext *model_file_context; - int file_size, dnn_size, parsed_size; - int32_t layer; - DNNLayerType layer_type; - - if (avio_open(&model_file_context, model_filename, AVIO_FLAG_READ) < 0){ - return NULL; - } - file_size = avio_size(model_file_context); - - model = av_mallocz(sizeof(DNNModel)); - if (!model){ - goto fail; - } - - /** - * check file header with string and version - */ - if (avio_read(model_file_context, buf, sizeof(buf)) != sizeof(buf) || - memcmp(buf, DNN_NATIVE_MAGIC, sizeof(buf))) - goto fail; - dnn_size = sizeof(buf); - - version = (int32_t)avio_rl32(model_file_context); - dnn_size += 4; - if (version != major_version_expected) { - goto fail; - } - - // currently no need to check minor version - version = (int32_t)avio_rl32(model_file_context); - dnn_size += 4; - header_size = dnn_size; - - native_model = av_mallocz(sizeof(NativeModel)); - if (!native_model){ - goto fail; - } - model->model = native_model; - - native_model->ctx.class = &dnn_native_class; - model->options = options; - if (av_opt_set_from_string(&native_model->ctx, model->options, NULL, "=", "&") < 0) - goto fail; - native_model->model = model; - - if (native_model->ctx.options.async) { - av_log(&native_model->ctx, AV_LOG_WARNING, "Async not supported. Rolling back to sync\n"); - native_model->ctx.options.async = 0; - } - -#if !HAVE_PTHREAD_CANCEL - if (native_model->ctx.options.conv2d_threads > 1){ - av_log(&native_model->ctx, AV_LOG_WARNING, "'conv2d_threads' option was set but it is not supported " - "on this build (pthread support is required)\n"); - } -#endif - - avio_seek(model_file_context, file_size - 8, SEEK_SET); - native_model->layers_num = (int32_t)avio_rl32(model_file_context); - native_model->operands_num = (int32_t)avio_rl32(model_file_context); - dnn_size += 8; - avio_seek(model_file_context, header_size, SEEK_SET); - - native_model->layers = av_mallocz(native_model->layers_num * sizeof(Layer)); - if (!native_model->layers){ - goto fail; - } - - native_model->operands = av_mallocz(native_model->operands_num * sizeof(DnnOperand)); - if (!native_model->operands){ - goto fail; - } - - native_model->task_queue = ff_queue_create(); - if (!native_model->task_queue) { - goto fail; - } - - native_model->lltask_queue = ff_queue_create(); - if (!native_model->lltask_queue) { - goto fail; - } - - for (layer = 0; layer < native_model->layers_num; ++layer){ - layer_type = (int32_t)avio_rl32(model_file_context); - dnn_size += 4; - - if (layer_type >= DLT_COUNT) { - goto fail; - } - - native_model->layers[layer].type = layer_type; - parsed_size = ff_layer_funcs[layer_type].pf_load(&native_model->layers[layer], model_file_context, file_size, native_model->operands_num); - if (!parsed_size) { - goto fail; - } - dnn_size += parsed_size; - } - - for (int32_t i = 0; i < native_model->operands_num; ++i){ - DnnOperand *oprd; - int32_t name_len; - int32_t operand_index = (int32_t)avio_rl32(model_file_context); - dnn_size += 4; - - if (operand_index >= native_model->operands_num) { - goto fail; - } - - oprd = &native_model->operands[operand_index]; - name_len = (int32_t)avio_rl32(model_file_context); - dnn_size += 4; - - avio_get_str(model_file_context, name_len, oprd->name, sizeof(oprd->name)); - dnn_size += name_len; - - oprd->type = (int32_t)avio_rl32(model_file_context); - dnn_size += 4; - - oprd->data_type = (int32_t)avio_rl32(model_file_context); - dnn_size += 4; - - for (int32_t dim = 0; dim < 4; ++dim) { - oprd->dims[dim] = (int32_t)avio_rl32(model_file_context); - dnn_size += 4; - } - if (oprd->type == DOT_INPUT && oprd->dims[0] != 1) - goto fail; - - oprd->isNHWC = 1; - } - - avio_closep(&model_file_context); - - if (dnn_size != file_size){ - ff_dnn_free_model_native(&model); - return NULL; - } - - model->get_input = &get_input_native; - model->get_output = &get_output_native; - model->filter_ctx = filter_ctx; - model->func_type = func_type; - - return model; - -fail: - ff_dnn_free_model_native(&model); - avio_closep(&model_file_context); - return NULL; -} - -static int execute_model_native(Queue *lltask_queue) -{ - NativeModel *native_model = NULL; - NativeContext *ctx = NULL; - int32_t layer; - DNNData input, output; - DnnOperand *oprd = NULL; - LastLevelTaskItem *lltask = NULL; - TaskItem *task = NULL; - int ret = 0; - - lltask = ff_queue_pop_front(lltask_queue); - if (!lltask) { - av_log(NULL, AV_LOG_ERROR, "Failed to get LastLevelTaskItem\n"); - ret = AVERROR(EINVAL); - goto err; - } - task = lltask->task; - native_model = task->model; - ctx = &native_model->ctx; - - if (native_model->layers_num <= 0 || native_model->operands_num <= 0) { - av_log(ctx, AV_LOG_ERROR, "No operands or layers in model\n"); - ret = AVERROR(EINVAL); - goto err; - } - - for (int i = 0; i < native_model->operands_num; ++i) { - oprd = &native_model->operands[i]; - if (strcmp(oprd->name, task->input_name) == 0) { - if (oprd->type != DOT_INPUT) { - av_log(ctx, AV_LOG_ERROR, "Found \"%s\" in model, but it is not input node\n", task->input_name); - ret = AVERROR(EINVAL); - goto err; - } - break; - } - oprd = NULL; - } - if (!oprd) { - av_log(ctx, AV_LOG_ERROR, "Could not find \"%s\" in model\n", task->input_name); - ret = AVERROR(EINVAL); - goto err; - } - - oprd->dims[1] = task->in_frame->height; - oprd->dims[2] = task->in_frame->width; - - av_freep(&oprd->data); - oprd->length = ff_calculate_operand_data_length(oprd); - if (oprd->length <= 0) { - av_log(ctx, AV_LOG_ERROR, "The input data length overflow\n"); - ret = AVERROR(EINVAL); - goto err; - } - oprd->data = av_malloc(oprd->length); - if (!oprd->data) { - av_log(ctx, AV_LOG_ERROR, "Failed to malloc memory for input data\n"); - ret = AVERROR(ENOMEM); - goto err; - } - - input.height = oprd->dims[1]; - input.width = oprd->dims[2]; - input.channels = oprd->dims[3]; - input.data = oprd->data; - input.dt = oprd->data_type; - if (task->do_ioproc) { - if (native_model->model->frame_pre_proc != NULL) { - native_model->model->frame_pre_proc(task->in_frame, &input, native_model->model->filter_ctx); - } else { - ff_proc_from_frame_to_dnn(task->in_frame, &input, ctx); - } - } - - if (task->nb_output != 1) { - // currently, the filter does not need multiple outputs, - // so we just pending the support until we really need it. - avpriv_report_missing_feature(ctx, "multiple outputs"); - ret = AVERROR(ENOSYS); - goto err; - } - - for (layer = 0; layer < native_model->layers_num; ++layer){ - DNNLayerType layer_type = native_model->layers[layer].type; - ret = ff_layer_funcs[layer_type].pf_exec(native_model->operands, - native_model->layers[layer].input_operand_indexes, - native_model->layers[layer].output_operand_index, - native_model->layers[layer].params, - &native_model->ctx); - if (ret != 0) { - av_log(ctx, AV_LOG_ERROR, "Failed to execute model\n"); - goto err; - } - } - - for (uint32_t i = 0; i < task->nb_output; ++i) { - DnnOperand *oprd = NULL; - const char *output_name = task->output_names[i]; - for (int j = 0; j < native_model->operands_num; ++j) { - if (strcmp(native_model->operands[j].name, output_name) == 0) { - oprd = &native_model->operands[j]; - break; - } - } - - if (oprd == NULL) { - av_log(ctx, AV_LOG_ERROR, "Could not find output in model\n"); - ret = AVERROR(EINVAL); - goto err; - } - - output.data = oprd->data; - output.height = oprd->dims[1]; - output.width = oprd->dims[2]; - output.channels = oprd->dims[3]; - output.dt = oprd->data_type; - - if (task->do_ioproc) { - if (native_model->model->frame_post_proc != NULL) { - native_model->model->frame_post_proc(task->out_frame, &output, native_model->model->filter_ctx); - } else { - ff_proc_from_dnn_to_frame(task->out_frame, &output, ctx); - } - } else { - task->out_frame->width = output.width; - task->out_frame->height = output.height; - } - } - task->inference_done++; -err: - av_freep(&lltask); - return ret; -} - -int ff_dnn_execute_model_native(const DNNModel *model, DNNExecBaseParams *exec_params) -{ - NativeModel *native_model = model->model; - NativeContext *ctx = &native_model->ctx; - TaskItem *task; - int ret = 0; - - ret = ff_check_exec_params(ctx, DNN_NATIVE, model->func_type, exec_params); - if (ret != 0) { - return ret; - } - - task = av_malloc(sizeof(*task)); - if (!task) { - av_log(ctx, AV_LOG_ERROR, "unable to alloc memory for task item.\n"); - return AVERROR(ENOMEM); - } - - ret = ff_dnn_fill_task(task, exec_params, native_model, ctx->options.async, 1); - if (ret != 0) { - av_freep(&task); - return ret; - } - - if (ff_queue_push_back(native_model->task_queue, task) < 0) { - av_freep(&task); - av_log(ctx, AV_LOG_ERROR, "unable to push back task_queue.\n"); - return AVERROR(ENOMEM); - } - - ret = extract_lltask_from_task(task, native_model->lltask_queue); - if (ret != 0) { - av_log(ctx, AV_LOG_ERROR, "unable to extract last level task from task.\n"); - return ret; - } - - return execute_model_native(native_model->lltask_queue); -} - -int ff_dnn_flush_native(const DNNModel *model) -{ - NativeModel *native_model = model->model; - - if (ff_queue_size(native_model->lltask_queue) == 0) { - // no pending task need to flush - return 0; - } - - // for now, use sync node with flush operation - // Switch to async when it is supported - return execute_model_native(native_model->lltask_queue); -} - -DNNAsyncStatusType ff_dnn_get_result_native(const DNNModel *model, AVFrame **in, AVFrame **out) -{ - NativeModel *native_model = model->model; - return ff_dnn_get_result_common(native_model->task_queue, in, out); -} - -int32_t ff_calculate_operand_dims_count(const DnnOperand *oprd) -{ - int32_t result = 1; - for (int i = 0; i < 4; ++i) - result *= oprd->dims[i]; - - return result; -} - -int32_t ff_calculate_operand_data_length(const DnnOperand* oprd) -{ - // currently, we just support DNN_FLOAT - uint64_t len = sizeof(float); - for (int i = 0; i < 4; i++) { - len *= oprd->dims[i]; - if (len > INT32_MAX) - return 0; - } - return len; -} - -void ff_dnn_free_model_native(DNNModel **model) -{ - NativeModel *native_model; - ConvolutionalParams *conv_params; - int32_t layer; - - if (*model) - { - if ((*model)->model) { - native_model = (*model)->model; - if (native_model->layers) { - for (layer = 0; layer < native_model->layers_num; ++layer){ - if (native_model->layers[layer].type == DLT_CONV2D){ - conv_params = (ConvolutionalParams *)native_model->layers[layer].params; - av_freep(&conv_params->kernel); - av_freep(&conv_params->biases); - } - av_freep(&native_model->layers[layer].params); - } - av_freep(&native_model->layers); - } - - if (native_model->operands) { - for (uint32_t operand = 0; operand < native_model->operands_num; ++operand) - av_freep(&native_model->operands[operand].data); - av_freep(&native_model->operands); - } - - while (ff_queue_size(native_model->lltask_queue) != 0) { - LastLevelTaskItem *item = ff_queue_pop_front(native_model->lltask_queue); - av_freep(&item); - } - ff_queue_destroy(native_model->lltask_queue); - - while (ff_queue_size(native_model->task_queue) != 0) { - TaskItem *item = ff_queue_pop_front(native_model->task_queue); - av_frame_free(&item->in_frame); - av_frame_free(&item->out_frame); - av_freep(&item); - } - ff_queue_destroy(native_model->task_queue); - - av_freep(&native_model); - } - av_freep(model); - } -} diff --git a/libavfilter/dnn/dnn_backend_native.h b/libavfilter/dnn/dnn_backend_native.h deleted file mode 100644 index 75bd9a44f77..00000000000 --- a/libavfilter/dnn/dnn_backend_native.h +++ /dev/null @@ -1,149 +0,0 @@ -/* - * Copyright (c) 2018 Sergey Lavrushkin - * - * 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 - * DNN inference functions interface for native backend. - */ - - -#ifndef AVFILTER_DNN_DNN_BACKEND_NATIVE_H -#define AVFILTER_DNN_DNN_BACKEND_NATIVE_H - -#include "../dnn_interface.h" -#include "libavformat/avio.h" -#include "libavutil/opt.h" -#include "queue.h" - -/** - * the enum value of DNNLayerType should not be changed, - * the same values are used in convert_from_tensorflow.py - * and, it is used to index the layer execution/load function pointer. - */ -typedef enum { - DLT_INPUT = 0, - DLT_CONV2D = 1, - DLT_DEPTH_TO_SPACE = 2, - DLT_MIRROR_PAD = 3, - DLT_MAXIMUM = 4, - DLT_MATH_BINARY = 5, - DLT_MATH_UNARY = 6, - DLT_AVG_POOL = 7, - DLT_DENSE = 8, - DLT_COUNT -} DNNLayerType; - -typedef enum {DOT_INPUT = 1, DOT_OUTPUT = 2, DOT_INTERMEDIATE = DOT_INPUT | DOT_OUTPUT} DNNOperandType; -typedef enum {VALID, SAME, SAME_CLAMP_TO_EDGE} DNNPaddingParam; -typedef enum {RELU, TANH, SIGMOID, NONE, LEAKY_RELU} DNNActivationFunc; - -typedef struct Layer{ - DNNLayerType type; - /** - * a layer can have multiple inputs and one output. - * 4 is just a big enough number for input operands (increase it if necessary), - * do not use 'int32_t *input_operand_indexes', so we don't worry about mem leaks. - */ - int32_t input_operand_indexes[4]; - int32_t output_operand_index; - void *params; -} Layer; - -typedef struct DnnOperand{ - /** - * there are two memory layouts, NHWC or NCHW, so we use dims, - * dims[0] is Number. - */ - int32_t dims[4]; - - /** - * input/output/intermediate operand of the network - */ - DNNOperandType type; - - /** - * support different kinds of data type such as float, half float, int8 etc, - * first support float now. - */ - DNNDataType data_type; - - /** - * NHWC if 1, otherwise NCHW. - * let's first support NHWC only, this flag is for extensive usage. - */ - int8_t isNHWC; - - /** - * to avoid possible memory leak, do not use char *name - */ - char name[128]; - - /** - * data pointer with data length in bytes. - * usedNumbersLeft is only valid for intermediate operand, - * it means how many layers still depend on this operand, - * todo: the memory can be reused when usedNumbersLeft is zero. - */ - void *data; - int32_t length; - int32_t usedNumbersLeft; -}DnnOperand; - -typedef struct InputParams{ - int height, width, channels; -} InputParams; - -typedef struct NativeOptions{ - uint8_t async; - uint32_t conv2d_threads; -} NativeOptions; - -typedef struct NativeContext { - const AVClass *class; - NativeOptions options; -} NativeContext; - -// Represents simple feed-forward convolutional network. -typedef struct NativeModel{ - NativeContext ctx; - DNNModel *model; - Layer *layers; - int32_t layers_num; - DnnOperand *operands; - int32_t operands_num; - Queue *task_queue; - Queue *lltask_queue; -} NativeModel; - -DNNModel *ff_dnn_load_model_native(const char *model_filename, DNNFunctionType func_type, const char *options, AVFilterContext *filter_ctx); - -int ff_dnn_execute_model_native(const DNNModel *model, DNNExecBaseParams *exec_params); - -DNNAsyncStatusType ff_dnn_get_result_native(const DNNModel *model, AVFrame **in, AVFrame **out); - -int ff_dnn_flush_native(const DNNModel *model); - -void ff_dnn_free_model_native(DNNModel **model); - -// NOTE: User must check for error (return value <= 0) to handle -// case like integer overflow. -int32_t ff_calculate_operand_data_length(const DnnOperand *oprd); -int32_t ff_calculate_operand_dims_count(const DnnOperand *oprd); -#endif diff --git a/libavfilter/dnn/dnn_backend_native_layer_avgpool.c b/libavfilter/dnn/dnn_backend_native_layer_avgpool.c deleted file mode 100644 index d6fcac8a355..00000000000 --- a/libavfilter/dnn/dnn_backend_native_layer_avgpool.c +++ /dev/null @@ -1,147 +0,0 @@ -/* - * Copyright (c) 2020 - * - * 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 - * DNN native backend implementation. - */ - -#include "libavutil/avassert.h" -#include "dnn_backend_native_layer_avgpool.h" - -int ff_dnn_load_layer_avg_pool(Layer *layer, AVIOContext *model_file_context, int file_size, int operands_num) -{ - AvgPoolParams *avgpool_params; - int dnn_size = 0; - avgpool_params = av_malloc(sizeof(*avgpool_params)); - if(!avgpool_params) - return 0; - - avgpool_params->strides = (int32_t)avio_rl32(model_file_context); - avgpool_params->padding_method = (int32_t)avio_rl32(model_file_context); - avgpool_params->kernel_size = (int32_t)avio_rl32(model_file_context); - dnn_size += 12; - - if (dnn_size > file_size || avgpool_params->kernel_size <= 0 || avgpool_params->strides <=0){ - av_freep(&avgpool_params); - return 0; - } - - layer->params = avgpool_params; - layer->input_operand_indexes[0] = (int32_t)avio_rl32(model_file_context); - layer->output_operand_index = (int32_t)avio_rl32(model_file_context); - dnn_size += 8; - - if (layer->input_operand_indexes[0] >= operands_num || layer->output_operand_index >= operands_num) { - return 0; - } - return dnn_size; -} - -int ff_dnn_execute_layer_avg_pool(DnnOperand *operands, const int32_t *input_operand_indexes, - int32_t output_operand_index, const void *parameters, NativeContext *ctx) -{ - float *output; - int height_end, width_end, height_radius, width_radius, output_height, output_width, kernel_area; - int32_t input_operand_index = input_operand_indexes[0]; - int number = operands[input_operand_index].dims[0]; - int height = operands[input_operand_index].dims[1]; - int width = operands[input_operand_index].dims[2]; - int channel = operands[input_operand_index].dims[3]; - const float *input = operands[input_operand_index].data; - const AvgPoolParams *avgpool_params = parameters; - - int kernel_strides = avgpool_params->strides; - int src_linesize = width * channel; - DnnOperand *output_operand = &operands[output_operand_index]; - - /** - * When padding_method = SAME, the tensorflow will only padding the hald number of 0 pixels - * except the remainders. - * Eg: assuming the input height = 1080, the strides = 11, so the remainders = 1080 % 11 = 2 - * and if ksize = 5: it will fill (5 - 2) >> 1 = 1 line before the first line of input image, - * and 5 - 2 - 1 = 2 lines after the last line of input image. - * and if ksize = 7: it will fill (7 - 2) >> 1 = 2 lines before the first line of input image, - * and 7 - 2 - 2 = 3 lines after the last line of input image. - */ - if (avgpool_params->padding_method == SAME) { - height_end = height; - width_end = width; - height_radius = avgpool_params->kernel_size - ((height - 1) % kernel_strides + 1); - width_radius = avgpool_params->kernel_size - ((width - 1) % kernel_strides + 1); - height_radius = height_radius < 0 ? 0 : height_radius >> 1; - width_radius = width_radius < 0 ? 0 : width_radius >> 1; - output_height = ceil(height / (kernel_strides * 1.0)); - output_width = ceil(width / (kernel_strides * 1.0)); - } else { - av_assert0(avgpool_params->padding_method == VALID); - height_end = height - avgpool_params->kernel_size + 1; - width_end = width - avgpool_params->kernel_size + 1; - height_radius = 0; - width_radius = 0; - output_height = ceil((height - avgpool_params->kernel_size + 1) / (kernel_strides * 1.0)); - output_width = ceil((width - avgpool_params->kernel_size + 1) / (kernel_strides * 1.0)); - } - - output_operand->dims[0] = number; - output_operand->dims[1] = output_height; - output_operand->dims[2] = output_width; - // not support pooling in channel dimension now - output_operand->dims[3] = channel; - output_operand->data_type = operands[input_operand_index].data_type; - output_operand->length = ff_calculate_operand_data_length(output_operand); - if (output_operand->length <= 0) { - av_log(ctx, AV_LOG_ERROR, "The output data length overflow\n"); - return AVERROR(EINVAL); - } - output_operand->data = av_realloc(output_operand->data, output_operand->length); - if (!output_operand->data) { - av_log(ctx, AV_LOG_ERROR, "Failed to reallocate memory for output\n"); - return AVERROR(ENOMEM); - } - output = output_operand->data; - - for (int y = 0; y < height_end; y += kernel_strides) { - for (int x = 0; x < width_end; x += kernel_strides) { - for (int n_channel = 0; n_channel < channel; ++n_channel) { - output[n_channel] = 0.0; - kernel_area = 0; - for (int kernel_y = 0; kernel_y < avgpool_params->kernel_size; ++kernel_y) { - for (int kernel_x = 0; kernel_x < avgpool_params->kernel_size; ++kernel_x) { - float input_pel; - int y_pos = y + (kernel_y - height_radius); - int x_pos = x + (kernel_x - width_radius); - if (x_pos < 0 || x_pos >= width || y_pos < 0 || y_pos >= height) { - input_pel = 0.0; - } else { - kernel_area++; - input_pel = input[y_pos * src_linesize + x_pos * channel + n_channel]; - } - output[n_channel] += input_pel; - } - } - output[n_channel] /= kernel_area; - } - output += channel; - } - } - - return 0; -} diff --git a/libavfilter/dnn/dnn_backend_native_layer_avgpool.h b/libavfilter/dnn/dnn_backend_native_layer_avgpool.h deleted file mode 100644 index 118a160090f..00000000000 --- a/libavfilter/dnn/dnn_backend_native_layer_avgpool.h +++ /dev/null @@ -1,69 +0,0 @@ -/* - * Copyright (c) 2020 - * - * 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 - * DNN inference functions interface for native backend. - */ - -#ifndef AVFILTER_DNN_DNN_BACKEND_NATIVE_LAYER_AVGPOOL_H -#define AVFILTER_DNN_DNN_BACKEND_NATIVE_LAYER_AVGPOOL_H - -#include "dnn_backend_native.h" - -typedef struct AvgPoolParams{ - int32_t strides, kernel_size; - DNNPaddingParam padding_method; -} AvgPoolParams; - -/** - * @brief Load Average Pooling Layer. - * - * It assigns the Average Pooling layer with AvgPoolParams - * after parsing from the model file context. - * - * @param layer pointer to the DNN layer instance - * @param model_file_context pointer to model file context - * @param file_size model file size to check if data is read - * correctly from the model file - * @param operands_num operand count of the whole model to - * check if data is read correctly from the model file - * @return number of bytes read from the model file - * @retval 0 if out of memory or an error occurs - */ -int ff_dnn_load_layer_avg_pool(Layer *layer, AVIOContext *model_file_context, int file_size, int operands_num); - -/** - * @brief Execute the Average Pooling Layer. - * Padding in channel dimensions is currently not supported. - * - * @param operands all operands for the model - * @param input_operand_indexes input operand indexes for this layer - * @param output_operand_index output operand index for this layer - * @param parameters average pooling parameters - * @param ctx pointer to Native model context for logging - * @retval 0 if the execution succeeds - * @retval AVERROR(ENOMEM) if memory allocation fails - * @retval AVERROR(EINVAL) for invalid arguments - */ -int ff_dnn_execute_layer_avg_pool(DnnOperand *operands, const int32_t *input_operand_indexes, - int32_t output_operand_index, const void *parameters, NativeContext *ctx); - -#endif diff --git a/libavfilter/dnn/dnn_backend_native_layer_conv2d.c b/libavfilter/dnn/dnn_backend_native_layer_conv2d.c deleted file mode 100644 index 2ac37d8855d..00000000000 --- a/libavfilter/dnn/dnn_backend_native_layer_conv2d.c +++ /dev/null @@ -1,265 +0,0 @@ -/* - * Copyright (c) 2018 Sergey Lavrushkin - * - * 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/avassert.h" -#include "libavutil/thread.h" -#include "libavutil/cpu.h" -#include "dnn_backend_native_layer_conv2d.h" - -#define CLAMP_TO_EDGE(x, w) ((x) < 0 ? 0 : ((x) >= (w) ? (w - 1) : (x))) - -//struct to pass parameters -typedef struct ThreadCommonParam{ - DnnOperand *operands; - const int32_t *input_operand_indexes; - int32_t output_operand_index; - const void *parameters; - NativeContext *ctx; - float *output_data; -} ThreadCommonParam; - -typedef struct ThreadParam{ - ThreadCommonParam *thread_common_param; - int thread_start, thread_end; -#if HAVE_PTHREAD_CANCEL - pthread_t thread; -#endif -} ThreadParam; - -int ff_dnn_load_layer_conv2d(Layer *layer, AVIOContext *model_file_context, int file_size, int operands_num) -{ - ConvolutionalParams *conv_params; - int kernel_size; - int dnn_size = 0; - conv_params = av_malloc(sizeof(*conv_params)); - if (!conv_params) - return 0; - - conv_params->dilation = (int32_t)avio_rl32(model_file_context); - conv_params->padding_method = (int32_t)avio_rl32(model_file_context); - conv_params->activation = (int32_t)avio_rl32(model_file_context); - conv_params->input_num = (int32_t)avio_rl32(model_file_context); - conv_params->output_num = (int32_t)avio_rl32(model_file_context); - conv_params->kernel_size = (int32_t)avio_rl32(model_file_context); - conv_params->has_bias = (int32_t)avio_rl32(model_file_context); - dnn_size += 28; - - kernel_size = conv_params->input_num * conv_params->output_num * - conv_params->kernel_size * conv_params->kernel_size; - dnn_size += kernel_size * 4; - if (conv_params->has_bias) - dnn_size += conv_params->output_num * 4; - - if (dnn_size > file_size || conv_params->input_num <= 0 || - conv_params->output_num <= 0 || conv_params->kernel_size <= 0){ - av_freep(&conv_params); - return 0; - } - - conv_params->kernel = av_malloc_array(kernel_size, sizeof(*conv_params->kernel)); - if (!conv_params->kernel) { - av_freep(&conv_params); - return 0; - } - for (int i = 0; i < kernel_size; ++i) { - conv_params->kernel[i] = av_int2float(avio_rl32(model_file_context)); - } - - conv_params->biases = NULL; - if (conv_params->has_bias) { - conv_params->biases = av_malloc_array(conv_params->output_num, sizeof(*conv_params->biases)); - if (!conv_params->biases){ - av_freep(&conv_params->kernel); - av_freep(&conv_params); - return 0; - } - for (int i = 0; i < conv_params->output_num; ++i){ - conv_params->biases[i] = av_int2float(avio_rl32(model_file_context)); - } - } - - layer->params = conv_params; - - layer->input_operand_indexes[0] = (int32_t)avio_rl32(model_file_context); - layer->output_operand_index = (int32_t)avio_rl32(model_file_context); - dnn_size += 8; - - if (layer->input_operand_indexes[0] >= operands_num || layer->output_operand_index >= operands_num) { - return 0; - } - - return dnn_size; -} - -static void * dnn_execute_layer_conv2d_thread(void *threadarg) -{ - //pass parameters - ThreadParam *thread_param = threadarg; - ThreadCommonParam *thread_common_param = thread_param->thread_common_param; - DnnOperand *operands = thread_common_param->operands; - int32_t input_operand_index = thread_common_param->input_operand_indexes[0]; - int height = operands[input_operand_index].dims[1]; - int width = operands[input_operand_index].dims[2]; - int channel = operands[input_operand_index].dims[3]; - const float *input = operands[input_operand_index].data; - const ConvolutionalParams *conv_params = thread_common_param->parameters; - - int radius = conv_params->kernel_size >> 1; - int src_linesize = width * conv_params->input_num; - int filter_linesize = conv_params->kernel_size * conv_params->input_num; - int filter_size = conv_params->kernel_size * filter_linesize; - int pad_size = (conv_params->padding_method == VALID) ? (conv_params->kernel_size - 1) / 2 * conv_params->dilation : 0; - - float *output = thread_common_param->output_data; - output += (conv_params->output_num) * (width - 2 * pad_size) * (thread_param->thread_start - pad_size); - - av_assert0(channel == conv_params->input_num); - - for (int y = thread_param->thread_start; y < thread_param->thread_end; ++y) { - for (int x = pad_size; x < width - pad_size; ++x) { - for (int n_filter = 0; n_filter < conv_params->output_num; ++n_filter) { - if (conv_params->has_bias) - output[n_filter] = conv_params->biases[n_filter]; - else - output[n_filter] = 0.f; - - for (int ch = 0; ch < conv_params->input_num; ++ch) { - for (int kernel_y = 0; kernel_y < conv_params->kernel_size; ++kernel_y) { - for (int kernel_x = 0; kernel_x < conv_params->kernel_size; ++kernel_x) { - float input_pel; - if (conv_params->padding_method == SAME_CLAMP_TO_EDGE) { - int y_pos = CLAMP_TO_EDGE(y + (kernel_y - radius) * conv_params->dilation, height); - int x_pos = CLAMP_TO_EDGE(x + (kernel_x - radius) * conv_params->dilation, width); - input_pel = input[y_pos * src_linesize + x_pos * conv_params->input_num + ch]; - } else { - int y_pos = y + (kernel_y - radius) * conv_params->dilation; - int x_pos = x + (kernel_x - radius) * conv_params->dilation; - input_pel = (x_pos < 0 || x_pos >= width || y_pos < 0 || y_pos >= height) ? 0.0 : - input[y_pos * src_linesize + x_pos * conv_params->input_num + ch]; - } - - - output[n_filter] += input_pel * conv_params->kernel[n_filter * filter_size + kernel_y * filter_linesize + - kernel_x * conv_params->input_num + ch]; - } - } - } - switch (conv_params->activation){ - case RELU: - output[n_filter] = FFMAX(output[n_filter], 0.0); - break; - case TANH: - output[n_filter] = 2.0f / (1.0f + exp(-2.0f * output[n_filter])) - 1.0f; - break; - case SIGMOID: - output[n_filter] = 1.0f / (1.0f + exp(-output[n_filter])); - break; - case NONE: - break; - case LEAKY_RELU: - output[n_filter] = FFMAX(output[n_filter], 0.0) + 0.2 * FFMIN(output[n_filter], 0.0); - } - } - output += conv_params->output_num; - } - } - return NULL; -} - - -int ff_dnn_execute_layer_conv2d(DnnOperand *operands, const int32_t *input_operand_indexes, - int32_t output_operand_index, const void *parameters, NativeContext *ctx) -{ -#if HAVE_PTHREAD_CANCEL - int thread_num = (ctx->options.conv2d_threads <= 0 || ctx->options.conv2d_threads > av_cpu_count()) - ? (av_cpu_count() + 1) : (ctx->options.conv2d_threads); - int ret = 0, thread_stride; - ThreadParam *thread_param; -#else - ThreadParam thread_param = { 0 }; -#endif - ThreadCommonParam thread_common_param; - const ConvolutionalParams *conv_params = parameters; - int height = operands[input_operand_indexes[0]].dims[1]; - int width = operands[input_operand_indexes[0]].dims[2]; - int pad_size = (conv_params->padding_method == VALID) ? (conv_params->kernel_size - 1) / 2 * conv_params->dilation : 0; - DnnOperand *output_operand = &operands[output_operand_index]; - void *tmp; - - output_operand->dims[0] = operands[input_operand_indexes[0]].dims[0]; - output_operand->dims[1] = height - pad_size * 2; - output_operand->dims[2] = width - pad_size * 2; - output_operand->dims[3] = conv_params->output_num; - output_operand->data_type = operands[input_operand_indexes[0]].data_type; - output_operand->length = ff_calculate_operand_data_length(output_operand); - if (output_operand->length <= 0) { - av_log(ctx, AV_LOG_ERROR, "The output data length overflow\n"); - return AVERROR(EINVAL); - } - tmp = av_realloc(output_operand->data, output_operand->length); - if (!tmp) { - av_log(ctx, AV_LOG_ERROR, "Failed to reallocate memory for output\n"); - return AVERROR(ENOMEM); - } - output_operand->data = tmp; - thread_common_param.output_data = output_operand->data; - thread_common_param.operands = operands; - thread_common_param.input_operand_indexes = input_operand_indexes; - thread_common_param.output_operand_index = output_operand_index; - thread_common_param.parameters = parameters; - thread_common_param.ctx = ctx; - -#if HAVE_PTHREAD_CANCEL - thread_param = av_malloc_array(thread_num, sizeof(*thread_param)); - if (!thread_param) - return AVERROR(ENOMEM); - thread_stride = (height - pad_size * 2) / thread_num; - //create threads - for (int i = 0; i < thread_num; i++){ - int thread_ret = 0; - thread_param[i].thread_common_param = &thread_common_param; - thread_param[i].thread_start = thread_stride * i + pad_size; - thread_param[i].thread_end = (i == thread_num - 1) ? (height - pad_size) : (thread_param[i].thread_start + thread_stride); - thread_ret = pthread_create(&thread_param[i].thread, NULL, - dnn_execute_layer_conv2d_thread, &thread_param[i]); - if (thread_ret) { - thread_num = i; - ret = AVERROR(thread_ret); - break; - } - } - - for (int i = 0; i < thread_num; i++){ - pthread_join(thread_param[i].thread, NULL); - } - - //release memory - av_freep(&thread_param); - - return ret; -#else - thread_param.thread_common_param = &thread_common_param; - thread_param.thread_start = pad_size; - thread_param.thread_end = height - pad_size; - dnn_execute_layer_conv2d_thread(&thread_param); - - return 0; -#endif -} diff --git a/libavfilter/dnn/dnn_backend_native_layer_conv2d.h b/libavfilter/dnn/dnn_backend_native_layer_conv2d.h deleted file mode 100644 index f754a9ba185..00000000000 --- a/libavfilter/dnn/dnn_backend_native_layer_conv2d.h +++ /dev/null @@ -1,68 +0,0 @@ -/* - * Copyright (c) 2018 Sergey Lavrushkin - * - * 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_DNN_DNN_BACKEND_NATIVE_LAYER_CONV2D_H -#define AVFILTER_DNN_DNN_BACKEND_NATIVE_LAYER_CONV2D_H - -#include "dnn_backend_native.h" - - -typedef struct ConvolutionalParams{ - int32_t input_num, output_num, kernel_size; - DNNActivationFunc activation; - DNNPaddingParam padding_method; - int32_t dilation; - int32_t has_bias; - float *kernel; - float *biases; -} ConvolutionalParams; - -/** - * @brief Load the 2D Convolution Layer. - * - * It assigns the 2D convolution layer with ConvolutionalParams - * after parsing from the model file context. - * - * @param layer pointer to the DNN layer instance - * @param model_file_context pointer to model file context - * @param file_size model file size to check if data is read - * correctly from the model file - * @param operands_num operand count of the whole model to - * check if data is read correctly from the model file - * @return number of bytes read from the model file - * @retval 0 if out of memory or an error occurs - */ -int ff_dnn_load_layer_conv2d(Layer *layer, AVIOContext *model_file_context, int file_size, int operands_num); - -/** - * @brief Execute the 2D Convolution Layer. - * - * @param operands all operands for the model - * @param input_operand_indexes input operand indexes for this layer - * @param output_operand_index output operand index for this layer - * @param parameters convolution parameters - * @param ctx pointer to Native model context for logging - * @retval 0 if the execution succeeds - * @retval AVERROR(ENOMEM) if memory allocation fails - * @retval AVERROR(EINVAL) for invalid arguments - */ -int ff_dnn_execute_layer_conv2d(DnnOperand *operands, const int32_t *input_operand_indexes, - int32_t output_operand_index, const void *parameters, NativeContext *ctx); -#endif diff --git a/libavfilter/dnn/dnn_backend_native_layer_dense.c b/libavfilter/dnn/dnn_backend_native_layer_dense.c deleted file mode 100644 index dff342c1f35..00000000000 --- a/libavfilter/dnn/dnn_backend_native_layer_dense.c +++ /dev/null @@ -1,151 +0,0 @@ -/* - * Copyright (c) 2020 - * - * 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/avassert.h" -#include "dnn_backend_native_layer_dense.h" - -int ff_dnn_load_layer_dense(Layer *layer, AVIOContext *model_file_context, int file_size, int operands_num) -{ - DenseParams *dense_params; - int kernel_size; - int dnn_size = 0; - dense_params = av_malloc(sizeof(*dense_params)); - if (!dense_params) - return 0; - - dense_params->activation = (int32_t)avio_rl32(model_file_context); - dense_params->input_num = (int32_t)avio_rl32(model_file_context); - dense_params->output_num = (int32_t)avio_rl32(model_file_context); - dense_params->has_bias = (int32_t)avio_rl32(model_file_context); - dnn_size += 16; - - kernel_size = dense_params->input_num * dense_params->output_num; - dnn_size += kernel_size * 4; - if (dense_params->has_bias) - dnn_size += dense_params->output_num * 4; - - if (dnn_size > file_size || dense_params->input_num <= 0 || - dense_params->output_num <= 0){ - av_freep(&dense_params); - return 0; - } - - dense_params->kernel = av_malloc(kernel_size * sizeof(float)); - if (!dense_params->kernel) { - av_freep(&dense_params); - return 0; - } - for (int i = 0; i < kernel_size; ++i) { - dense_params->kernel[i] = av_int2float(avio_rl32(model_file_context)); - } - - dense_params->biases = NULL; - if (dense_params->has_bias) { - dense_params->biases = av_malloc(dense_params->output_num * sizeof(float)); - if (!dense_params->biases){ - av_freep(&dense_params->kernel); - av_freep(&dense_params); - return 0; - } - for (int i = 0; i < dense_params->output_num; ++i){ - dense_params->biases[i] = av_int2float(avio_rl32(model_file_context)); - } - } - - layer->params = dense_params; - - layer->input_operand_indexes[0] = (int32_t)avio_rl32(model_file_context); - layer->output_operand_index = (int32_t)avio_rl32(model_file_context); - dnn_size += 8; - - if (layer->input_operand_indexes[0] >= operands_num || layer->output_operand_index >= operands_num) { - return 0; - } - - return dnn_size; -} - -int ff_dnn_execute_layer_dense(DnnOperand *operands, const int32_t *input_operand_indexes, - int32_t output_operand_index, const void *parameters, NativeContext *ctx) -{ - float *output; - int32_t input_operand_index = input_operand_indexes[0]; - int number = operands[input_operand_index].dims[0]; - int height = operands[input_operand_index].dims[1]; - int width = operands[input_operand_index].dims[2]; - int channel = operands[input_operand_index].dims[3]; - const float *input = operands[input_operand_index].data; - const DenseParams *dense_params = parameters; - - int src_linesize = width * channel; - DnnOperand *output_operand = &operands[output_operand_index]; - output_operand->dims[0] = number; - output_operand->dims[1] = height; - output_operand->dims[2] = width; - output_operand->dims[3] = dense_params->output_num; - output_operand->data_type = operands[input_operand_index].data_type; - output_operand->length = ff_calculate_operand_data_length(output_operand); - if (output_operand->length <= 0) { - av_log(ctx, AV_LOG_ERROR, "The output data length overflow\n"); - return AVERROR(EINVAL); - } - output_operand->data = av_realloc(output_operand->data, output_operand->length); - if (!output_operand->data) { - av_log(ctx, AV_LOG_ERROR, "Failed to reallocate memory for output\n"); - return AVERROR(ENOMEM); - } - output = output_operand->data; - - av_assert0(channel == dense_params->input_num); - - for (int y = 0; y < height; ++y) { - for (int x = 0; x < width; ++x) { - for (int n_filter = 0; n_filter < dense_params->output_num; ++n_filter) { - if (dense_params->has_bias) - output[n_filter] = dense_params->biases[n_filter]; - else - output[n_filter] = 0.f; - - for (int ch = 0; ch < dense_params->input_num; ++ch) { - float input_pel; - input_pel = input[y * src_linesize + x * dense_params->input_num + ch]; - output[n_filter] += input_pel * dense_params->kernel[n_filter*dense_params->input_num + ch]; - } - switch (dense_params->activation){ - case RELU: - output[n_filter] = FFMAX(output[n_filter], 0.0); - break; - case TANH: - output[n_filter] = 2.0f / (1.0f + exp(-2.0f * output[n_filter])) - 1.0f; - break; - case SIGMOID: - output[n_filter] = 1.0f / (1.0f + exp(-output[n_filter])); - break; - case NONE: - break; - case LEAKY_RELU: - output[n_filter] = FFMAX(output[n_filter], 0.0) + 0.2 * FFMIN(output[n_filter], 0.0); - } - } - output += dense_params->output_num; - } - } - return 0; -} diff --git a/libavfilter/dnn/dnn_backend_native_layer_dense.h b/libavfilter/dnn/dnn_backend_native_layer_dense.h deleted file mode 100644 index 607fc3e684b..00000000000 --- a/libavfilter/dnn/dnn_backend_native_layer_dense.h +++ /dev/null @@ -1,65 +0,0 @@ -/* - * Copyright (c) 2020 - * - * 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_DNN_DNN_BACKEND_NATIVE_LAYER_DENSE_H -#define AVFILTER_DNN_DNN_BACKEND_NATIVE_LAYER_DENSE_H - -#include "dnn_backend_native.h" - -typedef struct DenseParams{ - int32_t input_num, output_num; - DNNActivationFunc activation; - int32_t has_bias; - float *kernel; - float *biases; -} DenseParams; - -/** - * @brief Load the Densely-Connected Layer. - * - * It assigns the densely connected layer with DenseParams - * after parsing from the model file context. - * - * @param layer pointer to the DNN layer instance - * @param model_file_context pointer to model file context - * @param file_size model file size to check if data is read - * correctly from the model file - * @param operands_num operand count of the whole model to - * check if data is read correctly from the model file - * @return number of bytes read from the model file - * @retval 0 if out of memory or an error occurs - */ -int ff_dnn_load_layer_dense(Layer *layer, AVIOContext *model_file_context, int file_size, int operands_num); - -/** - * @brief Execute the Densely-Connected Layer. - * - * @param operands all operands for the model - * @param input_operand_indexes input operand indexes for this layer - * @param output_operand_index output operand index for this layer - * @param parameters dense layer parameters - * @param ctx pointer to Native model context for logging - * @retval 0 if the execution succeeds - * @retval AVERROR(ENOMEM) if memory allocation fails - * @retval AVERROR(EINVAL) for invalid arguments - */ -int ff_dnn_execute_layer_dense(DnnOperand *operands, const int32_t *input_operand_indexes, - int32_t output_operand_index, const void *parameters, NativeContext *ctx); -#endif diff --git a/libavfilter/dnn/dnn_backend_native_layer_depth2space.c b/libavfilter/dnn/dnn_backend_native_layer_depth2space.c deleted file mode 100644 index 358ac3bcaa2..00000000000 --- a/libavfilter/dnn/dnn_backend_native_layer_depth2space.c +++ /dev/null @@ -1,102 +0,0 @@ -/* - * Copyright (c) 2018 Sergey Lavrushkin - * - * 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 - * DNN native backend implementation. - */ - -#include "dnn_backend_native.h" -#include "dnn_backend_native_layer_depth2space.h" - -int ff_dnn_load_layer_depth2space(Layer *layer, AVIOContext *model_file_context, int file_size, int operands_num) -{ - DepthToSpaceParams *params; - int dnn_size = 0; - params = av_malloc(sizeof(*params)); - if (!params) - return 0; - - params->block_size = (int32_t)avio_rl32(model_file_context); - dnn_size += 4; - layer->input_operand_indexes[0] = (int32_t)avio_rl32(model_file_context); - layer->output_operand_index = (int32_t)avio_rl32(model_file_context); - dnn_size += 8; - layer->params = params; - - if (layer->input_operand_indexes[0] >= operands_num || layer->output_operand_index >= operands_num) { - return 0; - } - - return dnn_size; -} - -int ff_dnn_execute_layer_depth2space(DnnOperand *operands, const int32_t *input_operand_indexes, - int32_t output_operand_index, const void *parameters, NativeContext *ctx) -{ - float *output; - const DepthToSpaceParams *params = parameters; - int block_size = params->block_size; - int32_t input_operand_index = input_operand_indexes[0]; - int number = operands[input_operand_index].dims[0]; - int height = operands[input_operand_index].dims[1]; - int width = operands[input_operand_index].dims[2]; - int channels = operands[input_operand_index].dims[3]; - const float *input = operands[input_operand_index].data; - - int y, x, by, bx, ch; - int new_channels = channels / (block_size * block_size); - int output_linesize = width * channels; - int by_linesize = output_linesize / block_size; - int x_linesize = new_channels * block_size; - - DnnOperand *output_operand = &operands[output_operand_index]; - output_operand->dims[0] = number; - output_operand->dims[1] = height * block_size; - output_operand->dims[2] = width * block_size; - output_operand->dims[3] = new_channels; - output_operand->data_type = operands[input_operand_index].data_type; - output_operand->length = ff_calculate_operand_data_length(output_operand); - if (output_operand->length <= 0) { - av_log(ctx, AV_LOG_ERROR, "The output data length overflow\n"); - return AVERROR(EINVAL); - } - output_operand->data = av_realloc(output_operand->data, output_operand->length); - if (!output_operand->data) { - av_log(ctx, AV_LOG_ERROR, "Failed to reallocate memory for output\n"); - return AVERROR(ENOMEM); - } - output = output_operand->data; - - for (y = 0; y < height; ++y){ - for (x = 0; x < width; ++x){ - for (by = 0; by < block_size; ++by){ - for (bx = 0; bx < block_size; ++bx){ - for (ch = 0; ch < new_channels; ++ch){ - output[by * by_linesize + x * x_linesize + bx * new_channels + ch] = input[ch]; - } - input += new_channels; - } - } - } - output += output_linesize; - } - return 0; -} diff --git a/libavfilter/dnn/dnn_backend_native_layer_depth2space.h b/libavfilter/dnn/dnn_backend_native_layer_depth2space.h deleted file mode 100644 index aaf2df4c13e..00000000000 --- a/libavfilter/dnn/dnn_backend_native_layer_depth2space.h +++ /dev/null @@ -1,72 +0,0 @@ -/* - * Copyright (c) 2018 Sergey Lavrushkin - * - * 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 - * DNN inference functions interface for native backend. - */ - - -#ifndef AVFILTER_DNN_DNN_BACKEND_NATIVE_LAYER_DEPTH2SPACE_H -#define AVFILTER_DNN_DNN_BACKEND_NATIVE_LAYER_DEPTH2SPACE_H - -#include "../dnn_interface.h" -#include "libavformat/avio.h" - -typedef struct DepthToSpaceParams{ - int block_size; -} DepthToSpaceParams; - -/** - * @brief Load the Depth to Space Layer. - * - * It assigns the depth to space layer with DepthToSpaceParams - * after parsing from the model file context. - * - * @param layer pointer to the DNN layer instance - * @param model_file_context pointer to model file context - * @param file_size model file size to check if data is read - * correctly from the model file - * @param operands_num operand count of the whole model to - * check if data is read correctly from the model file - * @return number of bytes read from the model file - * @retval 0 if an error occurs or out of memory - */ -int ff_dnn_load_layer_depth2space(Layer *layer, AVIOContext *model_file_context, int file_size, int operands_num); - -/** - * @brief Execute the Depth to Space Layer. - * - * It rearranges the input data from depth into spatial - * form by applying Depth to Space transformation. - * - * @param operands all operands for the model - * @param input_operand_indexes input operand indexes for this layer - * @param output_operand_index output operand index for this layer - * @param parameters depth to space layer parameters - * @param ctx pointer to Native model context for logging - * @retval 0 if the execution succeeds - * @retval AVERROR(ENOMEM) if memory allocation fails - * @retval AVERROR(EINVAL) for invalid arguments - */ -int ff_dnn_execute_layer_depth2space(DnnOperand *operands, const int32_t *input_operand_indexes, - int32_t output_operand_index, const void *parameters, NativeContext *ctx); - -#endif diff --git a/libavfilter/dnn/dnn_backend_native_layer_mathbinary.c b/libavfilter/dnn/dnn_backend_native_layer_mathbinary.c deleted file mode 100644 index 1a3fa3f132f..00000000000 --- a/libavfilter/dnn/dnn_backend_native_layer_mathbinary.c +++ /dev/null @@ -1,193 +0,0 @@ -/* - * Copyright (c) 2020 - * - * 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 - * DNN native backend implementation. - */ - -#include "dnn_backend_native.h" -#include "dnn_backend_native_layer_mathbinary.h" - -typedef float (*FunType)(float src0, float src1); - -static float sub(float src0, float src1) -{ - return src0 - src1; -} -static float add(float src0, float src1) -{ - return src0 + src1; -} -static float mul(float src0, float src1) -{ - return src0 * src1; -} -static float realdiv(float src0, float src1) -{ - return src0 / src1; -} -static float minimum(float src0, float src1) -{ - return FFMIN(src0, src1); -} -static float floormod(float src0, float src1) -{ - return (float)((int)(src0) % (int)(src1)); -} - -static void math_binary_commutative(FunType pfun, const DnnLayerMathBinaryParams *params, const DnnOperand *input, DnnOperand *output, DnnOperand *operands, const int32_t *input_operand_indexes) -{ - int dims_count; - const float *src; - float *dst; - dims_count = ff_calculate_operand_dims_count(output); - src = input->data; - dst = output->data; - if (params->input0_broadcast || params->input1_broadcast) { - for (int i = 0; i < dims_count; ++i) { - dst[i] = pfun(params->v, src[i]); - } - } else { - const DnnOperand *input1 = &operands[input_operand_indexes[1]]; - const float *src1 = input1->data; - for (int i = 0; i < dims_count; ++i) { - dst[i] = pfun(src[i], src1[i]); - } - } -} -static void math_binary_not_commutative(FunType pfun, const DnnLayerMathBinaryParams *params, const DnnOperand *input, DnnOperand *output, DnnOperand *operands, const int32_t *input_operand_indexes) -{ - int dims_count; - const float *src; - float *dst; - dims_count = ff_calculate_operand_dims_count(output); - src = input->data; - dst = output->data; - if (params->input0_broadcast) { - for (int i = 0; i < dims_count; ++i) { - dst[i] = pfun(params->v, src[i]); - } - } else if (params->input1_broadcast) { - for (int i = 0; i < dims_count; ++i) { - dst[i] = pfun(src[i], params->v); - } - } else { - const DnnOperand *input1 = &operands[input_operand_indexes[1]]; - const float *src1 = input1->data; - for (int i = 0; i < dims_count; ++i) { - dst[i] = pfun(src[i], src1[i]); - } - } -} -int ff_dnn_load_layer_math_binary(Layer *layer, AVIOContext *model_file_context, int file_size, int operands_num) -{ - DnnLayerMathBinaryParams params = { 0 }; - int dnn_size = 0; - int input_index = 0; - - params.bin_op = (int32_t)avio_rl32(model_file_context); - dnn_size += 4; - - params.input0_broadcast = (int32_t)avio_rl32(model_file_context); - dnn_size += 4; - if (params.input0_broadcast) { - params.v = av_int2float(avio_rl32(model_file_context)); - } else { - layer->input_operand_indexes[input_index] = (int32_t)avio_rl32(model_file_context); - if (layer->input_operand_indexes[input_index] >= operands_num) { - return 0; - } - input_index++; - } - dnn_size += 4; - - params.input1_broadcast = (int32_t)avio_rl32(model_file_context); - dnn_size += 4; - if (params.input1_broadcast) { - params.v = av_int2float(avio_rl32(model_file_context)); - } else { - layer->input_operand_indexes[input_index] = (int32_t)avio_rl32(model_file_context); - if (layer->input_operand_indexes[input_index] >= operands_num) { - return 0; - } - input_index++; - } - dnn_size += 4; - - layer->output_operand_index = (int32_t)avio_rl32(model_file_context); - dnn_size += 4; - - if (layer->output_operand_index >= operands_num) { - return 0; - } - layer->params = av_memdup(¶ms, sizeof(params)); - if (!layer->params) - return 0; - - return dnn_size; -} - -int ff_dnn_execute_layer_math_binary(DnnOperand *operands, const int32_t *input_operand_indexes, - int32_t output_operand_index, const void *parameters, NativeContext *ctx) -{ - const DnnOperand *input = &operands[input_operand_indexes[0]]; - DnnOperand *output = &operands[output_operand_index]; - const DnnLayerMathBinaryParams *params = parameters; - - for (int i = 0; i < 4; ++i) - output->dims[i] = input->dims[i]; - - output->data_type = input->data_type; - output->length = ff_calculate_operand_data_length(output); - if (output->length <= 0) { - av_log(ctx, AV_LOG_ERROR, "The output data length overflow\n"); - return AVERROR(EINVAL); - } - output->data = av_realloc(output->data, output->length); - if (!output->data) { - av_log(ctx, AV_LOG_ERROR, "Failed to reallocate memory for output\n"); - return AVERROR(ENOMEM); - } - - switch (params->bin_op) { - case DMBO_SUB: - math_binary_not_commutative(sub, params, input, output, operands, input_operand_indexes); - return 0; - case DMBO_ADD: - math_binary_commutative(add, params, input, output, operands, input_operand_indexes); - return 0; - case DMBO_MUL: - math_binary_commutative(mul, params, input, output, operands, input_operand_indexes); - return 0; - case DMBO_REALDIV: - math_binary_not_commutative(realdiv, params, input, output, operands, input_operand_indexes); - return 0; - case DMBO_MINIMUM: - math_binary_commutative(minimum, params, input, output, operands, input_operand_indexes); - return 0; - case DMBO_FLOORMOD: - math_binary_not_commutative(floormod, params, input, output, operands, input_operand_indexes); - return 0; - default: - av_log(ctx, AV_LOG_ERROR, "Unmatch math binary operator\n"); - return AVERROR(EINVAL); - } -} diff --git a/libavfilter/dnn/dnn_backend_native_layer_mathbinary.h b/libavfilter/dnn/dnn_backend_native_layer_mathbinary.h deleted file mode 100644 index eee294b00f9..00000000000 --- a/libavfilter/dnn/dnn_backend_native_layer_mathbinary.h +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright (c) 2020 - * - * 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 - * DNN inference functions interface for native backend. - */ - - -#ifndef AVFILTER_DNN_DNN_BACKEND_NATIVE_LAYER_MATHBINARY_H -#define AVFILTER_DNN_DNN_BACKEND_NATIVE_LAYER_MATHBINARY_H - -#include "libavformat/avio.h" -#include "dnn_backend_native.h" - -typedef enum { - DMBO_SUB = 0, - DMBO_ADD = 1, - DMBO_MUL = 2, - DMBO_REALDIV = 3, - DMBO_MINIMUM = 4, - DMBO_FLOORMOD = 5, - DMBO_COUNT -} DNNMathBinaryOperation; - -typedef struct DnnLayerMathBinaryParams{ - DNNMathBinaryOperation bin_op; - int input0_broadcast; - int input1_broadcast; - float v; -} DnnLayerMathBinaryParams; - -int ff_dnn_load_layer_math_binary(Layer *layer, AVIOContext *model_file_context, int file_size, int operands_num); -int ff_dnn_execute_layer_math_binary(DnnOperand *operands, const int32_t *input_operand_indexes, - int32_t output_operand_index, const void *parameters, NativeContext *ctx); - -#endif diff --git a/libavfilter/dnn/dnn_backend_native_layer_mathunary.c b/libavfilter/dnn/dnn_backend_native_layer_mathunary.c deleted file mode 100644 index e3c5106e5e4..00000000000 --- a/libavfilter/dnn/dnn_backend_native_layer_mathunary.c +++ /dev/null @@ -1,156 +0,0 @@ -/* - * Copyright (c) 2020 - * - * 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 - * DNN native backend implementation. - */ - -#include - -#include "dnn_backend_native.h" -#include "dnn_backend_native_layer_mathunary.h" - -int ff_dnn_load_layer_math_unary(Layer *layer, AVIOContext *model_file_context, int file_size, int operands_num) -{ - DnnLayerMathUnaryParams *params; - int dnn_size = 0; - params = av_malloc(sizeof(*params)); - if(!params) - return 0; - - params->un_op = (int32_t)avio_rl32(model_file_context); - dnn_size += 4; - layer->params = params; - layer->input_operand_indexes[0] = (int32_t)avio_rl32(model_file_context); - layer->output_operand_index = (int32_t)avio_rl32(model_file_context); - dnn_size += 8; - - if (layer->input_operand_indexes[0] >= operands_num || layer->output_operand_index >= operands_num) { - return 0; - } - - return dnn_size; - -} - -int ff_dnn_execute_layer_math_unary(DnnOperand *operands, const int32_t *input_operand_indexes, - int32_t output_operand_index, const void *parameters, NativeContext *ctx) -{ - const DnnOperand *input = &operands[input_operand_indexes[0]]; - DnnOperand *output = &operands[output_operand_index]; - const DnnLayerMathUnaryParams *params = parameters; - int dims_count; - const float *src; - float *dst; - - for (int i = 0; i < 4; ++i) - output->dims[i] = input->dims[i]; - - output->data_type = input->data_type; - output->length = ff_calculate_operand_data_length(output); - if (output->length <= 0) { - av_log(ctx, AV_LOG_ERROR, "The output data length overflow\n"); - return AVERROR(EINVAL); - } - output->data = av_realloc(output->data, output->length); - if (!output->data) { - av_log(ctx, AV_LOG_ERROR, "Failed to reallocate memory for output\n"); - return AVERROR(ENOMEM); - } - - dims_count = ff_calculate_operand_dims_count(output); - src = input->data; - dst = output->data; - - switch (params->un_op) { - case DMUO_ABS: - for (int i = 0; i < dims_count; ++i) - dst[i] = FFABS(src[i]); - return 0; - case DMUO_SIN: - for (int i = 0; i < dims_count; ++i) - dst[i] = sin(src[i]); - return 0; - case DMUO_COS: - for (int i = 0; i < dims_count; ++i) - dst[i] = cos(src[i]); - return 0; - case DMUO_TAN: - for (int i = 0; i < dims_count; ++i) - dst[i] = tan(src[i]); - return 0; - case DMUO_ASIN: - for (int i = 0; i < dims_count; ++i) - dst[i] = asin(src[i]); - return 0; - case DMUO_ACOS: - for (int i = 0; i < dims_count; ++i) - dst[i] = acos(src[i]); - return 0; - case DMUO_ATAN: - for (int i = 0; i < dims_count; ++i) - dst[i] = atan(src[i]); - return 0; - case DMUO_SINH: - for (int i = 0; i < dims_count; ++i) - dst[i] = sinh(src[i]); - return 0; - case DMUO_COSH: - for (int i = 0; i < dims_count; ++i) - dst[i] = cosh(src[i]); - return 0; - case DMUO_TANH: - for (int i = 0; i < dims_count; ++i) - dst[i] = tanh(src[i]); - return 0; - case DMUO_ASINH: - for (int i = 0; i < dims_count; ++i) - dst[i] = asinh(src[i]); - return 0; - case DMUO_ACOSH: - for (int i = 0; i < dims_count; ++i) - dst[i] = acosh(src[i]); - return 0; - case DMUO_ATANH: - for (int i = 0; i < dims_count; ++i) - dst[i] = atanh(src[i]); - return 0; - case DMUO_CEIL: - for (int i = 0; i < dims_count; ++i) - dst[i] = ceil(src[i]); - return 0; - case DMUO_FLOOR: - for (int i = 0; i < dims_count; ++i) - dst[i] = floor(src[i]); - return 0; - case DMUO_ROUND: - for (int i = 0; i < dims_count; ++i) - dst[i] = round(src[i]); - return 0; - case DMUO_EXP: - for (int i = 0; i < dims_count; ++i) - dst[i] = exp(src[i]); - return 0; - default: - av_log(ctx, AV_LOG_ERROR, "Unmatch math unary operator\n"); - return AVERROR(EINVAL); - } -} diff --git a/libavfilter/dnn/dnn_backend_native_layer_mathunary.h b/libavfilter/dnn/dnn_backend_native_layer_mathunary.h deleted file mode 100644 index 806e73b29fa..00000000000 --- a/libavfilter/dnn/dnn_backend_native_layer_mathunary.h +++ /dev/null @@ -1,92 +0,0 @@ -/* - * Copyright (c) 2020 - * - * 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 - * DNN inference functions interface for native backend. - */ - -#ifndef AVFILTER_DNN_DNN_BACKEND_NATIVE_LAYER_MATHUNARY_H -#define AVFILTER_DNN_DNN_BACKEND_NATIVE_LAYER_MATHUNARY_H - -#include "libavformat/avio.h" -#include "dnn_backend_native.h" - -typedef enum { - DMUO_ABS = 0, - DMUO_SIN = 1, - DMUO_COS = 2, - DMUO_TAN = 3, - DMUO_ASIN = 4, - DMUO_ACOS = 5, - DMUO_ATAN = 6, - DMUO_SINH = 7, - DMUO_COSH = 8, - DMUO_TANH = 9, - DMUO_ASINH = 10, - DMUO_ACOSH = 11, - DMUO_ATANH = 12, - DMUO_CEIL = 13, - DMUO_FLOOR = 14, - DMUO_ROUND = 15, - DMUO_EXP = 16, - DMUO_COUNT -} DNNMathUnaryOperation; - -typedef struct DnnLayerMathUnaryParams{ - DNNMathUnaryOperation un_op; -} DnnLayerMathUnaryParams; - -/** - * @brief Load the Unary Math Layer. - * - * It assigns the unary math layer with DnnLayerMathUnaryParams - * after parsing from the model file context. - * - * @param layer pointer to the DNN layer instance - * @param model_file_context pointer to model file context - * @param file_size model file size to check if data is read - * correctly from the model file - * @param operands_num operand count of the whole model to - * check if data is read correctly from the model file - * @return number of bytes read from the model file - * @retval 0 if out of memory or an error occurs - */ -int ff_dnn_load_layer_math_unary(Layer *layer, AVIOContext *model_file_context, int file_size, int operands_num); - -/** - * @brief Execute the Unary Math Layer. - * - * It applies the unary operator parsed while - * loading to the given input operands. - * - * @param operands all operands for the model - * @param input_operand_indexes input operand indexes for this layer - * @param output_operand_index output operand index for this layer - * @param parameters unary math layer parameters - * @param ctx pointer to Native model context for logging - * @retval 0 if the execution succeeds - * @retval AVERROR(ENOMEM) if memory allocation fails - * @retval AVERROR(EINVAL) for invalid arguments - */ -int ff_dnn_execute_layer_math_unary(DnnOperand *operands, const int32_t *input_operand_indexes, - int32_t output_operand_index, const void *parameters, NativeContext *ctx); - -#endif diff --git a/libavfilter/dnn/dnn_backend_native_layer_maximum.c b/libavfilter/dnn/dnn_backend_native_layer_maximum.c deleted file mode 100644 index 667efaa3b80..00000000000 --- a/libavfilter/dnn/dnn_backend_native_layer_maximum.c +++ /dev/null @@ -1,83 +0,0 @@ -/* - * Copyright (c) 2019 Guo Yejun - * - * 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 - * DNN native backend implementation. - */ - -#include "dnn_backend_native.h" -#include "dnn_backend_native_layer_maximum.h" - -int ff_dnn_load_layer_maximum(Layer *layer, AVIOContext *model_file_context, int file_size, int operands_num) -{ - DnnLayerMaximumParams *params; - int dnn_size = 0; - params = av_malloc(sizeof(*params)); - if (!params) - return 0; - - params->val.u32 = avio_rl32(model_file_context); - dnn_size += 4; - layer->params = params; - layer->input_operand_indexes[0] = (int32_t)avio_rl32(model_file_context); - layer->output_operand_index = (int32_t)avio_rl32(model_file_context); - dnn_size += 8; - - if (layer->input_operand_indexes[0] >= operands_num || layer->output_operand_index >= operands_num) { - return 0; - } - - return dnn_size; -} - -int ff_dnn_execute_layer_maximum(DnnOperand *operands, const int32_t *input_operand_indexes, - int32_t output_operand_index, const void *parameters, NativeContext *ctx) -{ - const DnnOperand *input = &operands[input_operand_indexes[0]]; - DnnOperand *output = &operands[output_operand_index]; - const DnnLayerMaximumParams *params = parameters; - int dims_count; - const float *src; - float *dst; - - for (int i = 0; i < 4; ++i) - output->dims[i] = input->dims[i]; - - output->data_type = input->data_type; - output->length = ff_calculate_operand_data_length(output); - if (output->length <= 0) { - av_log(ctx, AV_LOG_ERROR, "The output data length overflow\n"); - return AVERROR(EINVAL); - } - output->data = av_realloc(output->data, output->length); - if (!output->data) { - av_log(ctx, AV_LOG_ERROR, "Failed to reallocate memory for output\n"); - return AVERROR(ENOMEM); - } - - dims_count = ff_calculate_operand_dims_count(output); - src = input->data; - dst = output->data; - for (int i = 0; i < dims_count; ++i) - dst[i] = FFMAX(src[i], params->val.y); - - return 0; -} diff --git a/libavfilter/dnn/dnn_backend_native_layer_maximum.h b/libavfilter/dnn/dnn_backend_native_layer_maximum.h deleted file mode 100644 index 523acbe05fc..00000000000 --- a/libavfilter/dnn/dnn_backend_native_layer_maximum.h +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Copyright (c) 2019 Guo Yejun - * - * 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 - * DNN inference functions interface for native backend. - */ - - -#ifndef AVFILTER_DNN_DNN_BACKEND_NATIVE_LAYER_MAXIMUM_H -#define AVFILTER_DNN_DNN_BACKEND_NATIVE_LAYER_MAXIMUM_H - -#include "libavformat/avio.h" -#include "dnn_backend_native.h" - -typedef struct DnnLayerMaximumParams{ - union { - uint32_t u32; - float y; - }val; -} DnnLayerMaximumParams; - -int ff_dnn_load_layer_maximum(Layer *layer, AVIOContext *model_file_context, int file_size, int operands_num); -int ff_dnn_execute_layer_maximum(DnnOperand *operands, const int32_t *input_operand_indexes, - int32_t output_operand_index, const void *parameters, NativeContext *ctx); - -#endif diff --git a/libavfilter/dnn/dnn_backend_native_layer_pad.c b/libavfilter/dnn/dnn_backend_native_layer_pad.c deleted file mode 100644 index e274fe12c60..00000000000 --- a/libavfilter/dnn/dnn_backend_native_layer_pad.c +++ /dev/null @@ -1,268 +0,0 @@ -/* - * Copyright (c) 2019 Guo Yejun - * - * 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 "dnn_backend_native_layer_pad.h" - -int ff_dnn_load_layer_pad(Layer *layer, AVIOContext *model_file_context, int file_size, int operands_num) -{ - LayerPadParams *params; - int dnn_size = 0; - params = av_malloc(sizeof(*params)); - if (!params) - return 0; - - params->mode = (int32_t)avio_rl32(model_file_context); - dnn_size += 4; - for (int i = 0; i < 4; ++i) { - params->paddings[i][0] = avio_rl32(model_file_context); - params->paddings[i][1] = avio_rl32(model_file_context); - dnn_size += 8; - } - layer->input_operand_indexes[0] = (int32_t)avio_rl32(model_file_context); - layer->output_operand_index = (int32_t)avio_rl32(model_file_context); - dnn_size += 8; - layer->params = params; - - if (layer->input_operand_indexes[0] >= operands_num || layer->output_operand_index >= operands_num) { - return 0; - } - - return dnn_size; -} - -static int before_get_buddy(int given, int paddings, LayerPadModeParam mode) -{ - if (mode == LPMP_SYMMETRIC) { - return (2 * paddings - 1 - given); - } else if (mode == LPMP_REFLECT) { - return (2 * paddings - given); - } else { - av_assert0(!"should not reach here"); - return 0; - } -} - -static int after_get_buddy(int given, int border, LayerPadModeParam mode) -{ - if (mode == LPMP_SYMMETRIC) { - int offset = given - border; - return (border - 1 - offset); - } else if (mode == LPMP_REFLECT) { - int offset = given - border; - return (border - 2 - offset); - } else { - av_assert0(!"should not reach here"); - return 0; - } -} - -int ff_dnn_execute_layer_pad(DnnOperand *operands, const int32_t *input_operand_indexes, - int32_t output_operand_index, const void *parameters, NativeContext *ctx) -{ - int32_t before_paddings; - int32_t after_paddings; - float* output; - const LayerPadParams *params = parameters; - - // suppose format is - int32_t input_operand_index = input_operand_indexes[0]; - int number = operands[input_operand_index].dims[0]; - int height = operands[input_operand_index].dims[1]; - int width = operands[input_operand_index].dims[2]; - int channel = operands[input_operand_index].dims[3]; - const float *input = operands[input_operand_index].data; - - int new_number = number + params->paddings[0][0] + params->paddings[0][1]; - int new_height = height + params->paddings[1][0] + params->paddings[1][1]; - int new_width = width + params->paddings[2][0] + params->paddings[2][1]; - int new_channel = channel + params->paddings[3][0] + params->paddings[3][1]; - - int c_stride = channel; - int wc_stride = c_stride * width; - int hwc_stride = wc_stride * height; - - int new_c_stride = new_channel; - int new_wc_stride = new_c_stride * new_width; - int new_hwc_stride = new_wc_stride * new_height; - - DnnOperand *output_operand = &operands[output_operand_index]; - output_operand->dims[0] = new_number; - output_operand->dims[1] = new_height; - output_operand->dims[2] = new_width; - output_operand->dims[3] = new_channel; - output_operand->data_type = operands[input_operand_index].data_type; - output_operand->length = ff_calculate_operand_data_length(output_operand); - if (output_operand->length <= 0) { - av_log(ctx, AV_LOG_ERROR, "The output data length overflow\n"); - return AVERROR(EINVAL); - } - output_operand->data = av_realloc(output_operand->data, output_operand->length); - if (!output_operand->data) { - av_log(ctx, AV_LOG_ERROR, "Failed to reallocate memory for output\n"); - return AVERROR(ENOMEM); - } - output = output_operand->data; - - // copy the original data - for (int n = 0; n < number; n++) { - for (int h = 0; h < height; h++) { - for (int w = 0; w < width; w++) { - const float *src = input + n * hwc_stride + h * wc_stride + w * c_stride; - float *dst = output + (n + params->paddings[0][0]) * new_hwc_stride - + (h + params->paddings[1][0]) * new_wc_stride - + (w + params->paddings[2][0]) * new_c_stride - + params->paddings[3][0]; - memcpy(dst, src, channel * sizeof(float)); - } - } - } - - // handle the first dimension - before_paddings = params->paddings[0][0]; - after_paddings = params->paddings[0][1]; - for (int n = 0; n < before_paddings; n++) { - float *dst = output + n * new_hwc_stride; - if (params->mode == LPMP_CONSTANT) { - for (int i = 0; i < new_hwc_stride; i++) { - dst[i] = params->constant_values; - } - } - else { - int buddy = before_get_buddy(n, before_paddings, params->mode); - float *src = output + buddy * new_hwc_stride; - memcpy(dst, src, new_hwc_stride * sizeof(float)); - } - } - for (int n = 0; n < after_paddings; n++) { - int given = number + before_paddings + n; - float *dst = output + given * new_hwc_stride; - if (params->mode == LPMP_CONSTANT) { - for (int i = 0; i < new_hwc_stride; i++) { - dst[i] = params->constant_values; - } - } else { - int buddy = after_get_buddy(given, number + before_paddings, params->mode); - float *src = output + buddy * new_hwc_stride; - memcpy(dst, src, new_hwc_stride * sizeof(float)); - } - } - - // handle the second dimension - before_paddings = params->paddings[1][0]; - after_paddings = params->paddings[1][1]; - for (int n = 0; n < new_number; n++) { - float *start = output + n * new_hwc_stride; - for (int h = 0; h < before_paddings; h++) { - float *dst = start + h * new_wc_stride; - if (params->mode == LPMP_CONSTANT) { - for (int i = 0; i < new_wc_stride; i++) { - dst[i] = params->constant_values; - } - } else { - int buddy = before_get_buddy(h, before_paddings, params->mode); - float *src = start + buddy * new_wc_stride; - memcpy(dst, src, new_wc_stride * sizeof(float)); - } - } - for (int h = 0; h < after_paddings; h++) { - int given = height + before_paddings + h; - float *dst = start + given * new_wc_stride; - if (params->mode == LPMP_CONSTANT) { - for (int i = 0; i < new_wc_stride; i++) { - dst[i] = params->constant_values; - } - } else { - int buddy = after_get_buddy(given, height + before_paddings, params->mode); - float *src = start + buddy * new_wc_stride; - memcpy(dst, src, new_wc_stride * sizeof(float)); - } - } - } - - // handle the third dimension - before_paddings = params->paddings[2][0]; - after_paddings = params->paddings[2][1]; - for (int n = 0; n < new_number; n++) { - for (int h = 0; h < new_height; h++) { - float *start = output + n * new_hwc_stride + h * new_wc_stride; - for (int w = 0; w < before_paddings; w++) { - float *dst = start + w * new_c_stride; - if (params->mode == LPMP_CONSTANT) { - for (int i = 0; i < new_c_stride; i++) { - dst[i] = params->constant_values; - } - } else { - int buddy = before_get_buddy(w, before_paddings, params->mode); - float *src = start + buddy * new_c_stride; - memcpy(dst, src, new_c_stride * sizeof(float)); - } - } - for (int w = 0; w < after_paddings; w++) { - int given = width + before_paddings + w; - float *dst = start + given * new_c_stride; - if (params->mode == LPMP_CONSTANT) { - for (int i = 0; i < new_c_stride; i++) { - dst[i] = params->constant_values; - } - } else { - int buddy = after_get_buddy(given, width + before_paddings, params->mode); - float *src = start + buddy * new_c_stride; - memcpy(dst, src, new_c_stride * sizeof(float)); - } - } - } - } - - // handle the fourth dimension - before_paddings = params->paddings[3][0]; - after_paddings = params->paddings[3][1]; - for (int n = 0; n < new_number; n++) { - for (int h = 0; h < new_height; h++) { - for (int w = 0; w < new_width; w++) { - float *start = output + n * new_hwc_stride + h * new_wc_stride + w * new_c_stride; - for (int c = 0; c < before_paddings; c++) { - float *dst = start + c; - if (params->mode == LPMP_CONSTANT) { - *dst = params->constant_values; - } else { - int buddy = before_get_buddy(c, before_paddings, params->mode); - float *src = start + buddy; - *dst = *src; - } - } - for (int c = 0; c < after_paddings; c++) { - int given = channel + before_paddings + c; - float *dst = start + given; - if (params->mode == LPMP_CONSTANT) { - *dst = params->constant_values; - } else { - int buddy = after_get_buddy(given, channel + before_paddings, params->mode); - float *src = start + buddy; - *dst = *src; - } - } - } - } - } - - return 0; -} diff --git a/libavfilter/dnn/dnn_backend_native_layer_pad.h b/libavfilter/dnn/dnn_backend_native_layer_pad.h deleted file mode 100644 index 4f76c67c3f6..00000000000 --- a/libavfilter/dnn/dnn_backend_native_layer_pad.h +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright (c) 2019 Guo Yejun - * - * 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 - * layer pad (equivalent to tf.pad) for native backend. - */ -#ifndef AVFILTER_DNN_DNN_BACKEND_NATIVE_LAYER_PAD_H -#define AVFILTER_DNN_DNN_BACKEND_NATIVE_LAYER_PAD_H - -#include -#include "dnn_backend_native.h" - -typedef enum {LPMP_CONSTANT, LPMP_REFLECT, LPMP_SYMMETRIC} LayerPadModeParam; - -typedef struct LayerPadParams{ - int32_t paddings[4][2]; - LayerPadModeParam mode; - float constant_values; -} LayerPadParams; - -int ff_dnn_load_layer_pad(Layer *layer, AVIOContext *model_file_context, int file_size, int operands_num); -int ff_dnn_execute_layer_pad(DnnOperand *operands, const int32_t *input_operand_indexes, - int32_t output_operand_index, const void *parameters, NativeContext *ctx); - -#endif diff --git a/libavfilter/dnn/dnn_backend_native_layers.c b/libavfilter/dnn/dnn_backend_native_layers.c deleted file mode 100644 index 492939fd366..00000000000 --- a/libavfilter/dnn/dnn_backend_native_layers.c +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright (c) 2019 Guo Yejun - * - * 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 "dnn_backend_native_layers.h" -#include "dnn_backend_native_layer_pad.h" -#include "dnn_backend_native_layer_conv2d.h" -#include "dnn_backend_native_layer_depth2space.h" -#include "dnn_backend_native_layer_maximum.h" -#include "dnn_backend_native_layer_mathbinary.h" -#include "dnn_backend_native_layer_mathunary.h" -#include "dnn_backend_native_layer_avgpool.h" -#include "dnn_backend_native_layer_dense.h" - -const LayerFunc ff_layer_funcs[DLT_COUNT] = { - {NULL, NULL}, - {ff_dnn_execute_layer_conv2d, ff_dnn_load_layer_conv2d}, - {ff_dnn_execute_layer_depth2space, ff_dnn_load_layer_depth2space}, - {ff_dnn_execute_layer_pad, ff_dnn_load_layer_pad}, - {ff_dnn_execute_layer_maximum, ff_dnn_load_layer_maximum}, - {ff_dnn_execute_layer_math_binary, ff_dnn_load_layer_math_binary}, - {ff_dnn_execute_layer_math_unary, ff_dnn_load_layer_math_unary}, - {ff_dnn_execute_layer_avg_pool, ff_dnn_load_layer_avg_pool}, - {ff_dnn_execute_layer_dense, ff_dnn_load_layer_dense}, -}; diff --git a/libavfilter/dnn/dnn_backend_native_layers.h b/libavfilter/dnn/dnn_backend_native_layers.h deleted file mode 100644 index bbd02927c2a..00000000000 --- a/libavfilter/dnn/dnn_backend_native_layers.h +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Copyright (c) 2019 Guo Yejun - * - * 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_DNN_DNN_BACKEND_NATIVE_LAYERS_H -#define AVFILTER_DNN_DNN_BACKEND_NATIVE_LAYERS_H - -#include -#include "dnn_backend_native.h" - -typedef int (*LAYER_EXEC_FUNC)(DnnOperand *operands, const int32_t *input_operand_indexes, - int32_t output_operand_index, const void *parameters, NativeContext *ctx); -typedef int (*LAYER_LOAD_FUNC)(Layer *layer, AVIOContext *model_file_context, int file_size, int operands_num); - -typedef struct LayerFunc { - LAYER_EXEC_FUNC pf_exec; - LAYER_LOAD_FUNC pf_load; -}LayerFunc; - -extern const LayerFunc ff_layer_funcs[DLT_COUNT]; - -#endif diff --git a/libavfilter/dnn/dnn_backend_tf.c b/libavfilter/dnn/dnn_backend_tf.c index 3d372a56281..486d2405b86 100644 --- a/libavfilter/dnn/dnn_backend_tf.c +++ b/libavfilter/dnn/dnn_backend_tf.c @@ -24,17 +24,13 @@ */ #include "dnn_backend_tf.h" -#include "dnn_backend_native.h" -#include "dnn_backend_native_layer_conv2d.h" -#include "dnn_backend_native_layer_depth2space.h" #include "libavformat/avio.h" #include "libavutil/avassert.h" #include "libavutil/avstring.h" #include "libavutil/cpu.h" +#include "libavutil/opt.h" #include "libavcodec/defs.h" #include "../internal.h" -#include "dnn_backend_native_layer_pad.h" -#include "dnn_backend_native_layer_maximum.h" #include "dnn_io_proc.h" #include "dnn_backend_common.h" #include "safe_queue.h" @@ -481,363 +477,6 @@ static int load_tf_model(TFModel *tf_model, const char *model_filename) #define NAME_BUFFER_SIZE 256 -static int add_conv_layer(TFModel *tf_model, TF_Operation *transpose_op, TF_Operation **cur_op, - ConvolutionalParams* params, const int layer) -{ - TFContext *ctx = &tf_model->ctx; - TF_Operation *op; - TF_OperationDescription *op_desc; - TF_Output input; - int64_t strides[] = {1, 1, 1, 1}; - TF_Tensor *kernel_tensor = NULL, *biases_tensor = NULL; - int64_t dims[4]; - int dims_len; - char name_buffer[NAME_BUFFER_SIZE]; - int32_t size; - - size = params->input_num * params->output_num * params->kernel_size * params->kernel_size; - input.index = 0; - - snprintf(name_buffer, NAME_BUFFER_SIZE, "conv_kernel%d", layer); - op_desc = TF_NewOperation(tf_model->graph, "Const", name_buffer); - TF_SetAttrType(op_desc, "dtype", TF_FLOAT); - dims[0] = params->output_num; - dims[1] = params->kernel_size; - dims[2] = params->kernel_size; - dims[3] = params->input_num; - dims_len = 4; - kernel_tensor = TF_AllocateTensor(TF_FLOAT, dims, dims_len, size * sizeof(float)); - memcpy(TF_TensorData(kernel_tensor), params->kernel, size * sizeof(float)); - TF_SetAttrTensor(op_desc, "value", kernel_tensor, tf_model->status); - if (TF_GetCode(tf_model->status) != TF_OK){ - goto err; - } - op = TF_FinishOperation(op_desc, tf_model->status); - if (TF_GetCode(tf_model->status) != TF_OK){ - goto err; - } - - snprintf(name_buffer, NAME_BUFFER_SIZE, "transpose%d", layer); - op_desc = TF_NewOperation(tf_model->graph, "Transpose", name_buffer); - input.oper = op; - TF_AddInput(op_desc, input); - input.oper = transpose_op; - TF_AddInput(op_desc, input); - TF_SetAttrType(op_desc, "T", TF_FLOAT); - TF_SetAttrType(op_desc, "Tperm", TF_INT32); - op = TF_FinishOperation(op_desc, tf_model->status); - if (TF_GetCode(tf_model->status) != TF_OK){ - goto err; - } - - snprintf(name_buffer, NAME_BUFFER_SIZE, "conv2d%d", layer); - op_desc = TF_NewOperation(tf_model->graph, "Conv2D", name_buffer); - input.oper = *cur_op; - TF_AddInput(op_desc, input); - input.oper = op; - TF_AddInput(op_desc, input); - TF_SetAttrType(op_desc, "T", TF_FLOAT); - TF_SetAttrIntList(op_desc, "strides", strides, 4); - TF_SetAttrString(op_desc, "padding", "VALID", 5); - *cur_op = TF_FinishOperation(op_desc, tf_model->status); - if (TF_GetCode(tf_model->status) != TF_OK){ - goto err; - } - - snprintf(name_buffer, NAME_BUFFER_SIZE, "conv_biases%d", layer); - op_desc = TF_NewOperation(tf_model->graph, "Const", name_buffer); - TF_SetAttrType(op_desc, "dtype", TF_FLOAT); - dims[0] = params->output_num; - dims_len = 1; - biases_tensor = TF_AllocateTensor(TF_FLOAT, dims, dims_len, params->output_num * sizeof(float)); - memcpy(TF_TensorData(biases_tensor), params->biases, params->output_num * sizeof(float)); - TF_SetAttrTensor(op_desc, "value", biases_tensor, tf_model->status); - if (TF_GetCode(tf_model->status) != TF_OK){ - goto err; - } - op = TF_FinishOperation(op_desc, tf_model->status); - if (TF_GetCode(tf_model->status) != TF_OK){ - goto err; - } - - snprintf(name_buffer, NAME_BUFFER_SIZE, "bias_add%d", layer); - op_desc = TF_NewOperation(tf_model->graph, "BiasAdd", name_buffer); - input.oper = *cur_op; - TF_AddInput(op_desc, input); - input.oper = op; - TF_AddInput(op_desc, input); - TF_SetAttrType(op_desc, "T", TF_FLOAT); - *cur_op = TF_FinishOperation(op_desc, tf_model->status); - if (TF_GetCode(tf_model->status) != TF_OK){ - goto err; - } - - snprintf(name_buffer, NAME_BUFFER_SIZE, "activation%d", layer); - switch (params->activation){ - case RELU: - op_desc = TF_NewOperation(tf_model->graph, "Relu", name_buffer); - break; - case TANH: - op_desc = TF_NewOperation(tf_model->graph, "Tanh", name_buffer); - break; - case SIGMOID: - op_desc = TF_NewOperation(tf_model->graph, "Sigmoid", name_buffer); - break; - default: - avpriv_report_missing_feature(ctx, "convolutional activation function %d", params->activation); - return AVERROR(ENOSYS); - } - input.oper = *cur_op; - TF_AddInput(op_desc, input); - TF_SetAttrType(op_desc, "T", TF_FLOAT); - *cur_op = TF_FinishOperation(op_desc, tf_model->status); - if (TF_GetCode(tf_model->status) != TF_OK){ - goto err; - } - - return 0; -err: - TF_DeleteTensor(kernel_tensor); - TF_DeleteTensor(biases_tensor); - av_log(ctx, AV_LOG_ERROR, "Failed to add conv layer %d\n", layer); - return DNN_GENERIC_ERROR; -} - -static int add_depth_to_space_layer(TFModel *tf_model, TF_Operation **cur_op, - DepthToSpaceParams *params, const int layer) -{ - TFContext *ctx = &tf_model->ctx; - TF_OperationDescription *op_desc; - TF_Output input; - char name_buffer[NAME_BUFFER_SIZE]; - - snprintf(name_buffer, NAME_BUFFER_SIZE, "depth_to_space%d", layer); - op_desc = TF_NewOperation(tf_model->graph, "DepthToSpace", name_buffer); - input.oper = *cur_op; - input.index = 0; - TF_AddInput(op_desc, input); - TF_SetAttrType(op_desc, "T", TF_FLOAT); - TF_SetAttrInt(op_desc, "block_size", params->block_size); - *cur_op = TF_FinishOperation(op_desc, tf_model->status); - if (TF_GetCode(tf_model->status) != TF_OK){ - av_log(ctx, AV_LOG_ERROR, "Failed to add depth_to_space to layer %d\n", layer); - return DNN_GENERIC_ERROR; - } - - return 0; -} - -static int add_pad_layer(TFModel *tf_model, TF_Operation **cur_op, - LayerPadParams *params, const int layer) -{ - TFContext *ctx = &tf_model->ctx; - TF_Operation *op; - TF_Tensor *tensor; - TF_OperationDescription *op_desc; - TF_Output input; - int32_t *pads; - int64_t pads_shape[] = {4, 2}; - - char name_buffer[NAME_BUFFER_SIZE]; - snprintf(name_buffer, NAME_BUFFER_SIZE, "pad%d", layer); - - op_desc = TF_NewOperation(tf_model->graph, "Const", name_buffer); - TF_SetAttrType(op_desc, "dtype", TF_INT32); - tensor = TF_AllocateTensor(TF_INT32, pads_shape, 2, 4 * 2 * sizeof(int32_t)); - pads = (int32_t *)TF_TensorData(tensor); - pads[0] = params->paddings[0][0]; - pads[1] = params->paddings[0][1]; - pads[2] = params->paddings[1][0]; - pads[3] = params->paddings[1][1]; - pads[4] = params->paddings[2][0]; - pads[5] = params->paddings[2][1]; - pads[6] = params->paddings[3][0]; - pads[7] = params->paddings[3][1]; - TF_SetAttrTensor(op_desc, "value", tensor, tf_model->status); - if (TF_GetCode(tf_model->status) != TF_OK){ - TF_DeleteTensor(tensor); - av_log(ctx, AV_LOG_ERROR, "Failed to set value for pad of layer %d\n", layer); - return DNN_GENERIC_ERROR; - } - op = TF_FinishOperation(op_desc, tf_model->status); - if (TF_GetCode(tf_model->status) != TF_OK){ - TF_DeleteTensor(tensor); - av_log(ctx, AV_LOG_ERROR, "Failed to add pad to layer %d\n", layer); - return DNN_GENERIC_ERROR; - } - - op_desc = TF_NewOperation(tf_model->graph, "MirrorPad", "mirror_pad"); - input.oper = *cur_op; - input.index = 0; - TF_AddInput(op_desc, input); - input.oper = op; - TF_AddInput(op_desc, input); - TF_SetAttrType(op_desc, "T", TF_FLOAT); - TF_SetAttrType(op_desc, "Tpaddings", TF_INT32); - TF_SetAttrString(op_desc, "mode", "SYMMETRIC", 9); - *cur_op = TF_FinishOperation(op_desc, tf_model->status); - if (TF_GetCode(tf_model->status) != TF_OK){ - TF_DeleteTensor(tensor); - av_log(ctx, AV_LOG_ERROR, "Failed to add mirror_pad to layer %d\n", layer); - return DNN_GENERIC_ERROR; - } - - return 0; -} - -static int add_maximum_layer(TFModel *tf_model, TF_Operation **cur_op, - DnnLayerMaximumParams *params, const int layer) -{ - TFContext *ctx = &tf_model->ctx; - TF_Operation *op; - TF_Tensor *tensor; - TF_OperationDescription *op_desc; - TF_Output input; - float *y; - - char name_buffer[NAME_BUFFER_SIZE]; - snprintf(name_buffer, NAME_BUFFER_SIZE, "maximum/y%d", layer); - - op_desc = TF_NewOperation(tf_model->graph, "Const", name_buffer); - TF_SetAttrType(op_desc, "dtype", TF_FLOAT); - tensor = TF_AllocateTensor(TF_FLOAT, NULL, 0, TF_DataTypeSize(TF_FLOAT)); - y = (float *)TF_TensorData(tensor); - *y = params->val.y; - TF_SetAttrTensor(op_desc, "value", tensor, tf_model->status); - if (TF_GetCode(tf_model->status) != TF_OK){ - TF_DeleteTensor(tensor); - av_log(ctx, AV_LOG_ERROR, "Failed to set value for maximum/y of layer %d", layer); - return DNN_GENERIC_ERROR; - } - op = TF_FinishOperation(op_desc, tf_model->status); - if (TF_GetCode(tf_model->status) != TF_OK){ - TF_DeleteTensor(tensor); - av_log(ctx, AV_LOG_ERROR, "Failed to add maximum/y to layer %d\n", layer); - return DNN_GENERIC_ERROR; - } - - snprintf(name_buffer, NAME_BUFFER_SIZE, "maximum%d", layer); - op_desc = TF_NewOperation(tf_model->graph, "Maximum", name_buffer); - input.oper = *cur_op; - input.index = 0; - TF_AddInput(op_desc, input); - input.oper = op; - TF_AddInput(op_desc, input); - TF_SetAttrType(op_desc, "T", TF_FLOAT); - *cur_op = TF_FinishOperation(op_desc, tf_model->status); - if (TF_GetCode(tf_model->status) != TF_OK){ - TF_DeleteTensor(tensor); - av_log(ctx, AV_LOG_ERROR, "Failed to add maximum to layer %d\n", layer); - return DNN_GENERIC_ERROR; - } - - return 0; -} - -static int load_native_model(TFModel *tf_model, const char *model_filename) -{ - TFContext *ctx = &tf_model->ctx; - int32_t layer; - TF_OperationDescription *op_desc; - TF_Operation *op; - TF_Operation *transpose_op; - TF_Tensor *tensor = NULL; - TF_Output input; - int32_t *transpose_perm; - int64_t transpose_perm_shape[] = {4}; - int64_t input_shape[] = {1, -1, -1, -1}; - int layer_add_res; - DNNModel *model = NULL; - NativeModel *native_model; - - model = ff_dnn_load_model_native(model_filename, DFT_PROCESS_FRAME, NULL, NULL); - if (!model){ - av_log(ctx, AV_LOG_ERROR, "Failed to load native model\n"); - return AVERROR(EINVAL); - } - - native_model = model->model; - tf_model->graph = TF_NewGraph(); - tf_model->status = TF_NewStatus(); - -#define CLEANUP_ON_ERROR(tf_model) \ - { \ - TF_DeleteTensor(tensor); \ - TF_DeleteGraph(tf_model->graph); \ - TF_DeleteStatus(tf_model->status); \ - av_log(ctx, AV_LOG_ERROR, "Failed to set value or add operator to layer\n"); \ - return DNN_GENERIC_ERROR; \ - } - - op_desc = TF_NewOperation(tf_model->graph, "Placeholder", "x"); - TF_SetAttrType(op_desc, "dtype", TF_FLOAT); - TF_SetAttrShape(op_desc, "shape", input_shape, 4); - op = TF_FinishOperation(op_desc, tf_model->status); - if (TF_GetCode(tf_model->status) != TF_OK){ - CLEANUP_ON_ERROR(tf_model); - } - - op_desc = TF_NewOperation(tf_model->graph, "Const", "transpose_perm"); - TF_SetAttrType(op_desc, "dtype", TF_INT32); - tensor = TF_AllocateTensor(TF_INT32, transpose_perm_shape, 1, 4 * sizeof(int32_t)); - transpose_perm = (int32_t *)TF_TensorData(tensor); - transpose_perm[0] = 1; - transpose_perm[1] = 2; - transpose_perm[2] = 3; - transpose_perm[3] = 0; - TF_SetAttrTensor(op_desc, "value", tensor, tf_model->status); - if (TF_GetCode(tf_model->status) != TF_OK){ - CLEANUP_ON_ERROR(tf_model); - } - transpose_op = TF_FinishOperation(op_desc, tf_model->status); - if (TF_GetCode(tf_model->status) != TF_OK){ - CLEANUP_ON_ERROR(tf_model); - } - - for (layer = 0; layer < native_model->layers_num; ++layer){ - switch (native_model->layers[layer].type){ - case DLT_INPUT: - layer_add_res = 0; - break; - case DLT_CONV2D: - layer_add_res = add_conv_layer(tf_model, transpose_op, &op, - (ConvolutionalParams *)native_model->layers[layer].params, layer); - break; - case DLT_DEPTH_TO_SPACE: - layer_add_res = add_depth_to_space_layer(tf_model, &op, - (DepthToSpaceParams *)native_model->layers[layer].params, layer); - break; - case DLT_MIRROR_PAD: - layer_add_res = add_pad_layer(tf_model, &op, - (LayerPadParams *)native_model->layers[layer].params, layer); - break; - case DLT_MAXIMUM: - layer_add_res = add_maximum_layer(tf_model, &op, - (DnnLayerMaximumParams *)native_model->layers[layer].params, layer); - break; - default: - CLEANUP_ON_ERROR(tf_model); - } - - if (layer_add_res != 0){ - CLEANUP_ON_ERROR(tf_model); - } - } - - op_desc = TF_NewOperation(tf_model->graph, "Identity", "y"); - input.oper = op; - input.index = 0; - TF_AddInput(op_desc, input); - TF_FinishOperation(op_desc, tf_model->status); - if (TF_GetCode(tf_model->status) != TF_OK){ - CLEANUP_ON_ERROR(tf_model); - } - - ff_dnn_free_model_native(&model); - - return 0; -} - DNNModel *ff_dnn_load_model_tf(const char *model_filename, DNNFunctionType func_type, const char *options, AVFilterContext *filter_ctx) { DNNModel *model = NULL; @@ -867,9 +506,8 @@ DNNModel *ff_dnn_load_model_tf(const char *model_filename, DNNFunctionType func_ } if (load_tf_model(tf_model, model_filename) != 0){ - if (load_native_model(tf_model, model_filename) != 0){ - goto err; - } + av_log(ctx, AV_LOG_ERROR, "Failed to load TensorFlow model: \"%s\"\n", model_filename); + goto err; } if (ctx->options.nireq <= 0) { diff --git a/libavfilter/dnn_interface.h b/libavfilter/dnn_interface.h index ef8d7ae66f7..6b64a2b55a3 100644 --- a/libavfilter/dnn_interface.h +++ b/libavfilter/dnn_interface.h @@ -32,7 +32,7 @@ #define DNN_GENERIC_ERROR FFERRTAG('D','N','N','!') -typedef enum {DNN_NATIVE, DNN_TF, DNN_OV} DNNBackendType; +typedef enum {DNN_TF = 1, DNN_OV} DNNBackendType; typedef enum {DNN_FLOAT = 1, DNN_UINT8 = 4} DNNDataType; diff --git a/libavfilter/tests/dnn-layer-avgpool.c b/libavfilter/tests/dnn-layer-avgpool.c deleted file mode 100644 index 4a925ea22af..00000000000 --- a/libavfilter/tests/dnn-layer-avgpool.c +++ /dev/null @@ -1,197 +0,0 @@ -/* - * Copyright (c) 2020 - * - * 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 "libavfilter/dnn/dnn_backend_native_layer_avgpool.h" - -#define EPSON 0.00001 - -static int test_with_same(void) -{ - // the input data and expected data are generated with below python code. - /* - import tensorflow as tf - import numpy as np - - x = tf.placeholder(tf.float32, shape=[1, None, None, 3]) - y = tf.layers.average_pooling2d(x, pool_size=[2,2], strides=[1,1], padding='VALID') - data = np.random.rand(1, 5, 6, 3); - - sess=tf.Session() - sess.run(tf.global_variables_initializer()) - - output = sess.run(y, feed_dict={x: data}) - - print("input:") - print(data.shape) - print(list(data.flatten())) - - print("output:") - print(output.shape) - print(list(output.flatten())) - */ - - AvgPoolParams params; - DnnOperand operands[2]; - int32_t input_indexes[1]; - float input[1*5*6*3] = { - 0.7461309859908424, 0.7567538372797069, 0.07662743569678687, 0.8882112610336333, 0.9720443314026668, 0.3337200343220823, 0.4421032129780248, - 0.14940809044964876, 0.6773177061961277, 0.9778844630669781, 0.6522650522626998, 0.0317651530878591, 0.31259897552911364, 0.6235936821891896, - 0.40016094349542775, 0.4599222930032276, 0.7893807222960093, 0.8475986363538283, 0.5058802717647394, 0.7827005363222633, 0.3032188123727916, - 0.8983728631302361, 0.20622408444965523, 0.22966072303869878, 0.09535751273161308, 0.8760709100995375, 0.9982324154558745, 0.7904595468621013, - 0.13883671508879347, 0.9332751439533138, 0.0010861680752152214, 0.3607210449251048, 0.6600652759586171, 0.7629572058138805, 0.29441975810476106, - 0.2683471432889405, 0.22574580829831536, 0.8893251976212904, 0.3907737043801005, 0.6421829842863968, 0.6670373870457297, 0.9383850793160277, - 0.4120458907436003, 0.3589847212711481, 0.48047736550128983, 0.6428192648418949, 0.0313661686292348, 0.429357100401472, 0.5123413386514056, - 0.8492446404097114, 0.9045286128486804, 0.8123708563814285, 0.3943245008451698, 0.9576713003177785, 0.5985610965938726, 0.9350833279543561, - 0.8010079897491659, 0.45882114217642866, 0.35275037908941487, 0.4555844661432271, 0.12352455940255314, 0.37801756635035544, 0.2824056214573083, - 0.6229462823245029, 0.7235305681391472, 0.5408259266122064, 0.12142224381781208, 0.34431198802873686, 0.7112823816321276, 0.6307144385115417, - 0.8136734589018082, 0.842095618140585, 0.8602767724004784, 0.6649236853766185, 0.5184782829419623, 0.9119607270982825, 0.3084111974561645, - 0.39460705638161364, 0.17710447526170836, 0.1715485945814199, 0.17277563576521882, 0.40188232428735704, 0.22847985411491878, 0.4135361701550696, - 0.24621846601980057, 0.6576588108454774, 0.6063336087333997, 0.6452342242996931, 0.7071689702737508, 0.1973416063225648 - }; - float expected_output[] = { - 0.75964886, 0.6794307, 0.23580676, 0.5810112, 0.5509369, 0.55973274, 0.5764512, 0.45414522, 0.6601476, 0.52050734, 0.44385415, - 0.50631666, 0.38414115, 0.5170288, 0.544043, 0.61143976, 0.5419003, 0.5579729, 0.5680455, 0.6363218, 0.4655096, 0.51198983, - 0.5270792, 0.66168886, 0.48517057, 0.3513146, 0.7103355, 0.48667657, 0.34504217, 0.7318065, 0.5221889, 0.4746775, 0.69765306, - 0.78766406, 0.34437215, 0.6130092, 0.48132777, 0.7110491, 0.6464378, 0.40914366, 0.4391975, 0.5392131, 0.45033398, 0.37297475, - 0.43326652, 0.4748823, 0.48711336, 0.64649844, 0.51921225, 0.60038865, 0.8538945, 0.7215426, 0.60399896, 0.89988345, 0.707405, - 0.5652921, 0.54241943, 0.41785273, 0.30268195, 0.3263432, 0.3313644, 0.37539417, 0.35238582, 0.34811732, 0.48849532, 0.56799453, - 0.41089734, 0.63070333, 0.5892633, 0.6379743, 0.7604212, 0.5197186, 0.88611877, 0.48666745, 0.45654267, 0.5445326, 0.2399799, - 0.28369135, 0.28949338, 0.20001422, 0.2931559, 0.3240504, 0.44306934, 0.5099349, 0.44572634, 0.68241394, 0.40183762, 0.6452342, - 0.707169, 0.1973416 - }; - float *output; - - params.strides = 1; - params.kernel_size = 2; - params.padding_method = SAME; - - operands[0].data = input; - operands[0].dims[0] = 1; - operands[0].dims[1] = 5; - operands[0].dims[2] = 6; - operands[0].dims[3] = 3; - operands[1].data = NULL; - - input_indexes[0] = 0; - ff_dnn_execute_layer_avg_pool(operands, input_indexes, 1, ¶ms, NULL); - - output = operands[1].data; - for (int i = 0; i < sizeof(expected_output) / sizeof(float); ++i) { - if (fabs(output[i] - expected_output[i]) > EPSON) { - printf("at index %d, output: %f, expected_output: %f\n", i, output[i], expected_output[i]); - av_freep(&output); - return 1; - } - } - - av_freep(&output); - return 0; -} - -static int test_with_valid(void) -{ - // the input data and expected data are generated with below python code. - /* - import tensorflow as tf - import numpy as np - - x = tf.placeholder(tf.float32, shape=[1, None, None, 3]) - y = tf.layers.average_pooling2d(x, pool_size=[2,2], strides=[1,1], padding='VALID') - data = np.random.rand(1, 5, 6, 3); - - sess=tf.Session() - sess.run(tf.global_variables_initializer()) - - output = sess.run(y, feed_dict={x: data}) - - print("input:") - print(data.shape) - print(list(data.flatten())) - - print("output:") - print(output.shape) - print(list(output.flatten())) - */ - - AvgPoolParams params; - DnnOperand operands[2]; - int32_t input_indexes[1]; - float input[1*5*6*3] = { - 0.5046741692941682, 0.9273653202485155, 0.8193878359859937, 0.1904059431360905, 0.8664919633253656, 0.7484625128286059, 0.984534184632278, - 0.31900804890072254, 0.3259426099940872, 0.05388974903570376, 0.7356610151331133, 0.46710858713311965, 0.718553768817036, 0.062478421853278676, - 0.7813224786584609, 0.4826837517658389, 0.9748095400220147, 0.8078547703898341, 0.11976750668368585, 0.8713586777195065, 0.41447321551284355, - 0.9818788239089807, 0.4335715767584073, 0.4059793452147419, 0.3677205907204525, 0.47919995923571, 0.8341395256258882, 0.7059726374074609, - 0.5478504551919791, 0.8622900484790175, 0.8343709722511167, 0.05089827275068537, 0.6465283980840416, 0.544539116066677, 0.39812057257884337, - 0.9578115576866337, 0.25012888117580145, 0.579333516024662, 0.5556732133051457, 0.6119862111181243, 0.0018736758772316398, 0.9795490254040474, - 0.4488085008883018, 0.28947489777011737, 0.4834108668633247, 0.9280490084385024, 0.9895821458049648, 0.31777618554697606, 0.42679693258977847, - 0.74447844466923, 0.9752225305081498, 0.17564130841849335, 0.22382692067314292, 0.009602884447469373, 0.5144884415025782, 0.031622570708844555, - 0.8277532752502512, 0.4111593210409763, 0.5272084646575664, 0.28856508082905297, 0.11317726946036655, 0.7203328275540273, 0.8310055019972384, - 0.8535951508685228, 0.40230347305233227, 0.2819703265132867, 0.6243143957791139, 0.7512463693822311, 0.7523056340495644, 0.8838077258040928, - 0.5472240664033092, 0.2550538284454935, 0.5560317774456567, 0.8966847087518931, 0.6728358284165321, 0.30361297147530875, 0.464343925441822, - 0.34507695659461224, 0.6333175615390685, 0.26661369038523497, 0.9926748632253231, 0.9994267301382666, 0.8684917986974414, 0.3598754806113009, - 0.49550268625464666, 0.03652458679973214, 0.13469081713137177, 0.4579424049273835, 0.48641107969110353, 0.9670250266945365 - }; - float expected_output[1*4*5*3] = { - 0.44918162, 0.7746969, 0.5970757, 0.63113487, 0.5245679, 0.578631, 0.52802926, 0.52042985, 0.6223702, 0.57819676, 0.34922206, - 0.6893124, 0.64503694, 0.37157673, 0.7983793, 0.49094033, 0.47153437, 0.5889187, 0.6025985, 0.30103004, 0.6757697, 0.6126377, - 0.5765268, 0.62440413, 0.7237974, 0.5832023, 0.7004543, 0.49533707, 0.35433105, 0.6472913, 0.44694072, 0.28500956, 0.6628852, - 0.39628282, 0.38472247, 0.6456326, 0.58590746, 0.60042334, 0.47854072, 0.7081889, 0.7219026, 0.5818187, 0.5276401, 0.56669396, - 0.49804622, 0.4463231, 0.4799649, 0.5335578, 0.36531678, 0.4946247, 0.6143306, 0.6498792, 0.5644355, 0.6163815, 0.7432098, - 0.5146416, 0.38221055, 0.6153918, 0.45535153, 0.5272688 - }; - float *output; - - params.strides = 1; - params.kernel_size = 2; - params.padding_method = VALID; - - operands[0].data = input; - operands[0].dims[0] = 1; - operands[0].dims[1] = 5; - operands[0].dims[2] = 6; - operands[0].dims[3] = 3; - operands[1].data = NULL; - - input_indexes[0] = 0; - ff_dnn_execute_layer_avg_pool(operands, input_indexes, 1, ¶ms, NULL); - - output = operands[1].data; - for (int i = 0; i < sizeof(expected_output) / sizeof(float); ++i) { - if (fabs(output[i] - expected_output[i]) > EPSON) { - printf("at index %d, output: %f, expected_output: %f\n", i, output[i], expected_output[i]); - av_freep(&output); - return 1; - } - } - - av_freep(&output); - return 0; -} - -int main(int argc, char **argv) -{ - if (test_with_same()) - return 1; - if (test_with_valid()) - return 1; - - return 0; -} diff --git a/libavfilter/tests/dnn-layer-conv2d.c b/libavfilter/tests/dnn-layer-conv2d.c deleted file mode 100644 index 5ee60eeaf0d..00000000000 --- a/libavfilter/tests/dnn-layer-conv2d.c +++ /dev/null @@ -1,248 +0,0 @@ -/* - * Copyright (c) 2019 Guo Yejun - * - * 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 "libavfilter/dnn/dnn_backend_native_layer_conv2d.h" - -#define EPSON 0.00001 - -static int test_with_same_dilate(void) -{ - // the input data and expected data are generated with below python code. - /* - x = tf.placeholder(tf.float32, shape=[1, None, None, 3]) - y = tf.layers.conv2d(x, 2, 3, activation=tf.nn.tanh, padding='same', dilation_rate=(2, 2), bias_initializer=tf.keras.initializers.he_normal()) - data = np.random.rand(1, 5, 6, 3); - - sess=tf.Session() - sess.run(tf.global_variables_initializer()) - - weights = dict([(var.name, sess.run(var)) for var in tf.trainable_variables()]) - kernel = weights['conv2d/kernel:0'] - kernel = np.transpose(kernel, [3, 0, 1, 2]) - print("kernel:") - print(kernel.shape) - print(list(kernel.flatten())) - - bias = weights['conv2d/bias:0'] - print("bias:") - print(bias.shape) - print(list(bias.flatten())) - - output = sess.run(y, feed_dict={x: data}) - - print("input:") - print(data.shape) - print(list(data.flatten())) - - print("output:") - print(output.shape) - print(list(output.flatten())) - */ - - ConvolutionalParams params; - DnnOperand operands[2]; - int32_t input_indexes[1]; - float input[1*5*6*3] = { - 0.7012556460308194, 0.4233847954643357, 0.19515900664313612, 0.16343083004926495, 0.5758261611052848, 0.9510767434014871, 0.11014085055947687, - 0.906327053637727, 0.8136794715542507, 0.45371764543639526, 0.5768443343523952, 0.19543668786046986, 0.15648326047898609, 0.2099500241141279, - 0.17658777090552413, 0.059335724777169196, 0.1729991838469117, 0.8150514704819208, 0.4435535466703049, 0.3752188477566878, 0.749936650421431, - 0.6823494635284907, 0.10776389679424747, 0.34247481674596836, 0.5147867256244629, 0.9063709728129032, 0.12423605800856818, 0.6064872945412728, - 0.5891681538551459, 0.9865836236466314, 0.9002163879294677, 0.003968273184274618, 0.8628374809643967, 0.1327176268279583, 0.8449799925703798, - 0.1937671869354366, 0.41524410152707425, 0.02038786604756837, 0.49792466069597496, 0.8881874553848784, 0.9683921035597336, 0.4122972568010813, - 0.843553550993252, 0.9588482762501964, 0.5190350762645546, 0.4283584264145317, 0.09781496073714646, 0.9501058833776156, 0.8665541760152776, - 0.31669272550095806, 0.07133074675453632, 0.606438007334886, 0.7007157020538224, 0.4827996264130444, 0.5167615606392761, 0.6385043039312651, - 0.23069664707810555, 0.058233497329354456, 0.06323892961591071, 0.24816458893245974, 0.8646369065257812, 0.24742185893094837, 0.09991225948167437, - 0.625700606979606, 0.7678541502111257, 0.6215834594679912, 0.5623003956582483, 0.07389123942681242, 0.7659100715711249, 0.486061471642225, - 0.9947455699829012, 0.9094911797643259, 0.7644355876253265, 0.05384315321492239, 0.13565394382783613, 0.9810628204953316, 0.007386389078887889, - 0.226182754156241, 0.2609021390764772, 0.24182802076928933, 0.13264782451941648, 0.2035816485767682, 0.005504188177612557, 0.7014619934040155, - 0.956215988391991, 0.5670398541013633, 0.9809764721750784, 0.6886338100487461, 0.5758152317218274, 0.7137823176776179 - }; - float expected_output[1*5*6*2] = { - -0.9480655, -0.7169147, -0.9404794, -0.5567385, -0.8991124, -0.8306558, -0.94487447, -0.8932543, -0.88238764, -0.7301602, - -0.8974813, -0.7026703, -0.8858988, -0.53203243, -0.92881465, -0.5648504, -0.8871471, -0.7000097, -0.91754407, -0.79684794, - -0.760465, -0.117928326, -0.88302773, -0.8975289, -0.70615053, 0.19231977, -0.8318776, -0.386184, -0.80698484, -0.8556624, - -0.7336671, -0.6168619, -0.7658234, -0.63449603, -0.73314047, -0.87502456, -0.58158904, -0.4184259, -0.52618927, -0.13613208, - -0.5093187, -0.21027721, -0.39455596, -0.44507834, -0.22269244, -0.73400885, -0.77655095, -0.74408925, -0.57313335, -0.15333457, - -0.74620694, -0.34858236, -0.42586932, -0.5240488, 0.1634339, -0.2447881, -0.57927346, -0.62732303, -0.82287043, -0.8474058 - }; - float *output; - float kernel[2*3*3*3] = { - 0.26025516, 0.16536498, -0.24351254, 0.33892477, -0.34005195, 0.35202783, 0.34056443, 0.01422739, 0.13799345, 0.29489166, - 0.2781723, 0.178585, 0.22122234, 0.044115514, 0.13134438, 0.31705368, 0.22527462, -0.021323413, 0.115134746, -0.18216397, - -0.21197563, -0.027848959, -0.01704529, -0.12401503, -0.23415318, -0.12661739, -0.35338148, 0.20049328, -0.076153606, - -0.23642601, -0.3125769, -0.025851756, -0.30006272, 0.050762743, 0.32003498, 0.3052225, -0.0017385483, 0.25337684, -0.25664508, - 0.27846587, -0.3112659, 0.2066065, 0.31499845, 0.113178134, 0.09449363, -0.11828774, -0.12671001, -0.36259216, 0.2710235, - -0.19676702, 0.023612618, -0.2596915, -0.34949252, -0.108270735 - }; - float bias[2] = { -1.6574852, -0.72915393 }; - - NativeContext ctx; - ctx.class = NULL; - ctx.options.conv2d_threads = 1; - - params.activation = TANH; - params.has_bias = 1; - params.biases = bias; - params.dilation = 2; - params.input_num = 3; - params.kernel = kernel; - params.kernel_size = 3; - params.output_num = 2; - params.padding_method = SAME; - - operands[0].data = input; - operands[0].dims[0] = 1; - operands[0].dims[1] = 5; - operands[0].dims[2] = 6; - operands[0].dims[3] = 3; - operands[1].data = NULL; - - input_indexes[0] = 0; - ff_dnn_execute_layer_conv2d(operands, input_indexes, 1, ¶ms, &ctx); - - output = operands[1].data; - for (int i = 0; i < sizeof(expected_output) / sizeof(float); i++) { - if (fabs(output[i] - expected_output[i]) > EPSON) { - printf("at index %d, output: %f, expected_output: %f\n", i, output[i], expected_output[i]); - av_freep(&output); - return 1; - } - } - - av_freep(&output); - return 0; -} - -static int test_with_valid(void) -{ - // the input data and expected data are generated with below python code. - /* - x = tf.placeholder(tf.float32, shape=[1, None, None, 3]) - y = tf.layers.conv2d(x, 2, 3, activation=tf.nn.tanh, padding='valid', bias_initializer=tf.keras.initializers.he_normal()) - data = np.random.rand(1, 5, 6, 3); - - sess=tf.Session() - sess.run(tf.global_variables_initializer()) - - weights = dict([(var.name, sess.run(var)) for var in tf.trainable_variables()]) - kernel = weights['conv2d/kernel:0'] - kernel = np.transpose(kernel, [3, 0, 1, 2]) - print("kernel:") - print(kernel.shape) - print(list(kernel.flatten())) - - bias = weights['conv2d/bias:0'] - print("bias:") - print(bias.shape) - print(list(bias.flatten())) - - output = sess.run(y, feed_dict={x: data}) - - print("input:") - print(data.shape) - print(list(data.flatten())) - - print("output:") - print(output.shape) - print(list(output.flatten())) - */ - - ConvolutionalParams params; - DnnOperand operands[2]; - int32_t input_indexes[1]; - float input[1*5*6*3] = { - 0.26126657468269665, 0.42762216215337556, 0.7466274030131497, 0.802550266787863, 0.3709323443076644, 0.5919817068197668, 0.49274512279324967, - 0.7170132295090351, 0.0911793215410649, 0.5134213878288361, 0.670132600785118, 0.49417034512633484, 0.03887389460089885, 0.436785102836845, - 0.1490231658611978, 0.6413606121498127, 0.8595987991375995, 0.9132593077586231, 0.7075959004873255, 0.17754995944845464, 0.5212507214937141, - 0.35379732738215475, 0.25205107358505296, 0.3928792840544273, 0.09485294189485782, 0.8685115437448666, 0.6489046799288605, 0.509253797582924, - 0.8993255536791972, 0.18740056466602373, 0.34237617336313986, 0.3871438962989183, 0.1488532571774911, 0.5187002331293636, 0.8137098818752955, - 0.521761863717401, 0.4622312310118274, 0.29038411334638825, 0.16194915718170566, 0.5175999923925211, 0.8852230040101133, 0.0218263385047206, - 0.08482355352852367, 0.3463638568376264, 0.28627127120619733, 0.9553293378948409, 0.4803391055970835, 0.841635695030805, 0.3556828280031952, - 0.06778527221541808, 0.28193560357091596, 0.8399957619031576, 0.03305536359456385, 0.6625039162109645, 0.9300552020023897, 0.8551529138204146, - 0.6133216915522418, 0.222427800857393, 0.1315422686800336, 0.6189144989185527, 0.5346184916866876, 0.8348888624532548, 0.6544834567840291, - 0.2844062293389934, 0.28780026600883324, 0.5372272015684924, 0.6250226011503823, 0.28119106062279453, 0.49655812908420094, 0.6451488959145951, - 0.7362580606834843, 0.44815578616664087, 0.6454760235835586, 0.6794062414265861, 0.045378883014935756, 0.9008388543865096, 0.7949752851269782, - 0.4179928876222264, 0.28733419007048644, 0.996902319501908, 0.5690851338677467, 0.9511814013279738, 0.025323788678181636, 0.5594359732604794, - 0.1213732595086251, 0.7172624313368294, 0.6759328959074691, 0.07252138454885071, 0.17557735158403442, 0.5988895455048769 - }; - float expected_output[1*3*4*2] = { - -0.556947, -0.42143887, -0.092070885, 0.27404794, -0.41886684, 0.0862887, -0.25001016, -0.342721, 0.020730592, 0.04016919, -0.69839877, - -0.06136704, 0.14186388, -0.11655602, -0.23489095, -0.3845829, -0.19017771, 0.1595885, -0.18308741, -0.3071209, -0.5848686, -0.22509028, - -0.6023201, -0.14448485 - }; - float *output; - float kernel[2*3*3*3] = { - -0.25291282, 0.22402048, 0.028642118, -0.14615723, -0.27362752, -0.34801802, -0.2759148, 0.19594926, -0.25029412, 0.34606284, 0.10376671, - -0.1015394, 0.23616093, 0.2134214, 0.35285157, 0.05893758, 0.0024731457, -0.17143056, 0.35758412, 0.2186206, -0.28384736, -0.21206513, - -0.20871592, 0.27070445, 0.25878823, 0.11136332, -0.33737376, 0.08353335, -0.34290665, 0.041805506, -0.09738535, 0.3284936, -0.16838405, - -0.032494456, -0.29193437, 0.033259362, -0.09272635, -0.2802651, -0.28648436, 0.3542878, 0.2432127, -0.24551713, 0.27813476, 0.21024024, - -0.013690501, -0.1350077, -0.07826337, -0.34563828, 0.3220685, -0.07571727, 0.19420576, 0.20783454, 0.18738335, 0.16672492 - }; - float bias[2] = { -0.4773722, -0.19620377 }; - - NativeContext ctx; - ctx.class = NULL; - ctx.options.conv2d_threads = 1; - - params.activation = TANH; - params.has_bias = 1; - params.biases = bias; - params.dilation = 1; - params.input_num = 3; - params.kernel = kernel; - params.kernel_size = 3; - params.output_num = 2; - params.padding_method = VALID; - - operands[0].data = input; - operands[0].dims[0] = 1; - operands[0].dims[1] = 5; - operands[0].dims[2] = 6; - operands[0].dims[3] = 3; - operands[1].data = NULL; - - input_indexes[0] = 0; - ff_dnn_execute_layer_conv2d(operands, input_indexes, 1, ¶ms, &ctx); - - output = operands[1].data; - for (int i = 0; i < sizeof(expected_output) / sizeof(float); i++) { - if (fabs(output[i] - expected_output[i]) > EPSON) { - printf("at index %d, output: %f, expected_output: %f\n", i, output[i], expected_output[i]); - av_freep(&output); - return 1; - } - } - - av_freep(&output); - return 0; -} - -int main(int argc, char **argv) -{ - if (test_with_valid()) - return 1; - if (test_with_same_dilate()) - return 1; - - return 0; -} diff --git a/libavfilter/tests/dnn-layer-dense.c b/libavfilter/tests/dnn-layer-dense.c deleted file mode 100644 index 696f7505e51..00000000000 --- a/libavfilter/tests/dnn-layer-dense.c +++ /dev/null @@ -1,131 +0,0 @@ -/* - * Copyright (c) 2020 - * - * 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 "libavfilter/dnn/dnn_backend_native_layer_dense.h" - -#define EPSON 0.00001 - -static int test(void) -{ - // the input data and expected data are generated with below python code. - /* - x = tf.placeholder(tf.float32, shape=[1, None, None, 3]) - y = tf.layers.dense(input_x, 3, activation=tf.nn.sigmoid, bias_initializer=tf.keras.initializers.he_normal()) - data = np.random.rand(1, 5, 6, 3); - - sess=tf.Session() - sess.run(tf.global_variables_initializer()) - - weights = dict([(var.name, sess.run(var)) for var in tf.trainable_variables()]) - kernel = weights['dense/kernel:0'] - kernel = np.transpose(kernel, [1, 0]) - print("kernel:") - print(kernel.shape) - print(list(kernel.flatten())) - - bias = weights['dense/bias:0'] - print("bias:") - print(bias.shape) - print(list(bias.flatten())) - - output = sess.run(y, feed_dict={x: data}) - - print("input:") - print(data.shape) - print(list(data.flatten())) - - print("output:") - print(output.shape) - print(list(output.flatten())) - */ - - DenseParams params; - DnnOperand operands[2]; - int32_t input_indexes[1]; - float input[1*5*6*3] = { - 0.5552418686576308, 0.20653189262022464, 0.31115120939398877, 0.5897014433221428, 0.37340078861060655, 0.6470921693941893, 0.8039950367872679, 0.8762700891949274, - 0.6556655583829558, 0.5911096107039339, 0.18640250865290997, 0.2803248779238966, 0.31586613136402053, 0.9447300740056483, 0.9443980824873418, 0.8158851991115941, - 0.5631010340387631, 0.9407402251929046, 0.6485434876551682, 0.5631376966470001, 0.17581924875609634, 0.7033802439103178, 0.04802402495561675, 0.9183681450194972, - 0.46059317944364, 0.07964160481596883, 0.871787076270302, 0.973743142324361, 0.15923146943258415, 0.8212946080584571, 0.5415954459227064, 0.9552813822803975, - 0.4908552668172057, 0.33723691635292274, 0.46588057864910026, 0.8994239961321776, 0.09845220457674186, 0.1713400292123486, 0.39570294912818826, 0.08018956486392803, - 0.5290478278169032, 0.7141906125920976, 0.0320878067840098, 0.6412406575332606, 0.0075712007102423096, 0.7150828462386156, 0.1311989216968138, 0.4706847944253756, - 0.5447610794883336, 0.3430923933318001, 0.536082357943209, 0.4371629342483694, 0.40227962985019927, 0.3553806249465469, 0.031806622424259245, 0.7053916426174, - 0.3261570237309813, 0.419500213292063, 0.3155691223480851, 0.05664028113178088, 0.3636491555914486, 0.8502419746667123, 0.9836596530684955, 0.1628681802975801, - 0.09410832912479894, 0.28407218939480294, 0.7983417928813697, 0.24132158596506748, 0.8154729498062224, 0.29173768373895637, 0.13407102008052096, 0.18705786678800385, - 0.7167943621295573, 0.09222004247174376, 0.2319220738766018, 0.17708964382285064, 0.1391440370249517, 0.3254088083499256, 0.4013916894718289, 0.4819742663322323, - 0.15080103744648077, 0.9302407847555013, 0.9397597961319524, 0.5719200825550793, 0.9538938024682824, 0.9583882089203861, 0.5168861091262276, 0.1926396841842669, - 0.6781176744337578, 0.719366447288566 - }; - float expected_output[1*5*6*3] = { - -0.3921688, -0.9243112, -0.29659146, -0.64000785, -0.9466343, -0.62125254, -0.71759033, -0.9171336, -0.735589, -0.34365994, - -0.92100817, -0.23903961, -0.8962277, -0.9521279, -0.90962386, -0.7488303, -0.9563761, -0.7701762, -0.40800542, -0.87684774, - -0.3339763, -0.6354543, -0.97068924, -0.6246325, -0.6992075, -0.9706726, -0.6818918, -0.51864433, -0.9592881, -0.51187396, - -0.7423632, -0.89911884, -0.7457824, -0.82009757, -0.96402895, -0.8235518, -0.61980766, -0.94494647, -0.5410502, -0.8281218, - -0.95508635, -0.8201453, -0.5937325, -0.8679507, -0.500767, -0.39430764, -0.93967676, -0.32183182, -0.58913624, -0.939717, - -0.55179894, -0.55004454, -0.9214453, -0.4889004, -0.75294703, -0.9118363, -0.7200309, -0.3248641, -0.8878874, -0.18977344, - -0.8873837, -0.9571257, -0.90145934, -0.50521654, -0.93739635, -0.39051685, -0.61143184, -0.9591179, -0.605999, -0.40008977, - -0.92219675, -0.26732883, -0.19607787, -0.9172511, -0.07068595, -0.5409857, -0.9387041, -0.44181606, -0.4705004, -0.8899935, - -0.37997037, -0.66105115, -0.89754754, -0.68141997, -0.6324047, -0.886776, -0.65066385, -0.8334821, -0.94801456, -0.83297 - }; - float *output; - float kernel[3*3] = { - 0.56611896, -0.5144603, -0.82600045, 0.19219112, 0.3835776, -0.7475352, 0.5209291, -0.6301091, -0.99442935}; - float bias[3] = {-0.3654299, -1.5711838, -0.15546428}; - - params.activation = TANH; - params.has_bias = 1; - params.biases = bias; - params.input_num = 3; - params.kernel = kernel; - params.output_num = 3; - - operands[0].data = input; - operands[0].dims[0] = 1; - operands[0].dims[1] = 5; - operands[0].dims[2] = 6; - operands[0].dims[3] = 3; - operands[1].data = NULL; - - input_indexes[0] = 0; - ff_dnn_execute_layer_dense(operands, input_indexes, 1, ¶ms, NULL); - - output = operands[1].data; - for (int i = 0; i < sizeof(expected_output) / sizeof(float); i++) { - if (fabs(output[i] - expected_output[i]) > EPSON) { - printf("at index %d, output: %f, expected_output: %f\n", i, output[i], expected_output[i]); - av_freep(&output); - return 1; - } - } - - av_freep(&output); - return 0; -} - -int main(int argc, char **argv) -{ - if (test()) - return 1; - - return 0; -} diff --git a/libavfilter/tests/dnn-layer-depth2space.c b/libavfilter/tests/dnn-layer-depth2space.c deleted file mode 100644 index 958247e6753..00000000000 --- a/libavfilter/tests/dnn-layer-depth2space.c +++ /dev/null @@ -1,102 +0,0 @@ -/* - * Copyright (c) 2019 Guo Yejun - * - * 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 "libavfilter/dnn/dnn_backend_native.h" -#include "libavfilter/dnn/dnn_backend_native_layer_depth2space.h" - -#define EPSON 0.00001 - -static int test(void) -{ - // the input data and expected data are generated with below python code. - /* - x = tf.placeholder(tf.float32, shape=[1, None, None, 4]) - y = tf.depth_to_space(x, 2) - data = np.random.rand(1, 5, 3, 4); - - sess=tf.Session() - sess.run(tf.global_variables_initializer()) - - output = sess.run(y, feed_dict={x: data}) - - print("input:") - print(data.shape) - print(list(data.flatten())) - - print("output:") - print(output.shape) - print(list(output.flatten())) - */ - - DepthToSpaceParams params; - DnnOperand operands[2]; - int32_t input_indexes[1]; - float input[1*5*3*4] = { - 0.09771065121566602, 0.6336807372403175, 0.5142416549709786, 0.8027206567330333, 0.2154276025069397, 0.12112878462616772, 0.913936596765778, - 0.38881443647542646, 0.5850447615898835, 0.9311499327398275, 0.3613660929428246, 0.5420722002125493, 0.6002131190230359, 0.44800665702299525, - 0.7271322557896777, 0.3869293511885826, 0.5144404769364138, 0.6910844856987723, 0.6142102742269762, 0.6249991371621018, 0.45663376215836626, - 0.19523477129943423, 0.2483895888532045, 0.64326768256278, 0.5485877602998981, 0.45442067849873546, 0.529374943304256, 0.30439850391811885, - 0.11961343361340993, 0.2909643484561082, 0.9810970344127848, 0.8886928489786549, 0.6112237084436409, 0.8852482695156674, 0.9110868043114374, - 0.21242780027585217, 0.7101536973207572, 0.9709717457443375, 0.2702666770969332, 0.7718295953780221, 0.3957005164588574, 0.24383544252475453, - 0.040143453532367035, 0.26358051835323115, 0.013130251443791319, 0.3016550481482074, 0.03582340459943956, 0.718025513612361, 0.09844204177633753, - 0.04433767496953056, 0.6221895044119757, 0.6190414032940228, 0.8963550834625371, 0.5642449700064629, 0.2482982014723497, 0.17824909294583013, - 0.024401882408643272, 0.21742800875253465, 0.6794724473181843, 0.4814830479242237 - }; - float expected_output[1*10*6*1] = { - 0.097710654, 0.63368076, 0.2154276, 0.12112878, 0.58504474, 0.93114996, 0.51424164, 0.80272067, 0.9139366, 0.38881445, - 0.3613661, 0.5420722, 0.6002131, 0.44800666, 0.5144405, 0.6910845, 0.45663378, 0.19523478, 0.72713226, 0.38692936, - 0.61421025, 0.62499917, 0.24838959, 0.6432677, 0.54858774, 0.4544207, 0.11961343, 0.29096434, 0.6112237, 0.88524824, - 0.52937496, 0.3043985, 0.98109704, 0.88869286, 0.9110868, 0.2124278, 0.7101537, 0.97097176, 0.3957005, 0.24383545, - 0.013130251, 0.30165505, 0.27026668, 0.7718296, 0.040143453, 0.26358053, 0.035823405, 0.7180255, 0.09844204, - 0.044337675, 0.8963551, 0.564245, 0.024401883, 0.21742801, 0.6221895, 0.6190414, 0.2482982, 0.17824909, 0.67947245, 0.48148304 - }; - float *output; - - operands[0].data = input; - operands[0].dims[0] = 1; - operands[0].dims[1] = 5; - operands[0].dims[2] = 3; - operands[0].dims[3] = 4; - operands[1].data = NULL; - - input_indexes[0] = 0; - params.block_size = 2; - ff_dnn_execute_layer_depth2space(operands, input_indexes, 1, ¶ms, NULL); - - output = operands[1].data; - for (int i = 0; i < sizeof(expected_output) / sizeof(float); i++) { - if (fabs(output[i] - expected_output[i]) > EPSON) { - printf("at index %d, output: %f, expected_output: %f\n", i, output[i], expected_output[i]); - av_freep(&output); - return 1; - } - } - - av_freep(&output); - return 0; -} - -int main(int argc, char **argv) -{ - return test(); -} diff --git a/libavfilter/tests/dnn-layer-mathbinary.c b/libavfilter/tests/dnn-layer-mathbinary.c deleted file mode 100644 index 2e41dc1ae75..00000000000 --- a/libavfilter/tests/dnn-layer-mathbinary.c +++ /dev/null @@ -1,214 +0,0 @@ -/* - * Copyright (c) 2020 - * - * 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 "libavfilter/dnn/dnn_backend_native_layer_mathbinary.h" -#include "libavutil/avassert.h" - -#define EPSON 0.00005 - -static float get_expected(float f1, float f2, DNNMathBinaryOperation op) -{ - switch (op) - { - case DMBO_SUB: - return f1 - f2; - case DMBO_ADD: - return f1 + f2; - case DMBO_MUL: - return f1 * f2; - case DMBO_REALDIV: - return f1 / f2; - case DMBO_MINIMUM: - return (f1 < f2) ? f1 : f2; - case DMBO_FLOORMOD: - return (float)((int)(f1) % (int)(f2)); - default: - av_assert0(!"not supported yet"); - return 0.f; - } -} - -static int test_broadcast_input0(DNNMathBinaryOperation op) -{ - DnnLayerMathBinaryParams params; - DnnOperand operands[2]; - int32_t input_indexes[1]; - float input[1*1*2*3] = { - -3, 2.5, 2, -2.1, 7.8, 100 - }; - float *output; - - params.bin_op = op; - params.input0_broadcast = 1; - params.input1_broadcast = 0; - params.v = 7.28; - - operands[0].data = input; - operands[0].dims[0] = 1; - operands[0].dims[1] = 1; - operands[0].dims[2] = 2; - operands[0].dims[3] = 3; - operands[1].data = NULL; - - input_indexes[0] = 0; - ff_dnn_execute_layer_math_binary(operands, input_indexes, 1, ¶ms, NULL); - - output = operands[1].data; - for (int i = 0; i < sizeof(input) / sizeof(float); i++) { - float expected_output = get_expected(params.v, input[i], op); - if (fabs(output[i] - expected_output) > EPSON) { - printf("op %d, at index %d, output: %f, expected_output: %f (%s:%d)\n", - op, i, output[i], expected_output, __FILE__, __LINE__); - av_freep(&output); - return 1; - } - } - - av_freep(&output); - return 0; -} - -static int test_broadcast_input1(DNNMathBinaryOperation op) -{ - DnnLayerMathBinaryParams params; - DnnOperand operands[2]; - int32_t input_indexes[1]; - float input[1*1*2*3] = { - -3, 2.5, 2, -2.1, 7.8, 100 - }; - float *output; - - params.bin_op = op; - params.input0_broadcast = 0; - params.input1_broadcast = 1; - params.v = 7.28; - - operands[0].data = input; - operands[0].dims[0] = 1; - operands[0].dims[1] = 1; - operands[0].dims[2] = 2; - operands[0].dims[3] = 3; - operands[1].data = NULL; - - input_indexes[0] = 0; - ff_dnn_execute_layer_math_binary(operands, input_indexes, 1, ¶ms, NULL); - - output = operands[1].data; - for (int i = 0; i < sizeof(input) / sizeof(float); i++) { - float expected_output = get_expected(input[i], params.v, op); - if (fabs(output[i] - expected_output) > EPSON) { - printf("op %d, at index %d, output: %f, expected_output: %f (%s:%d)\n", - op, i, output[i], expected_output, __FILE__, __LINE__); - av_freep(&output); - return 1; - } - } - - av_freep(&output); - return 0; -} - -static int test_no_broadcast(DNNMathBinaryOperation op) -{ - DnnLayerMathBinaryParams params; - DnnOperand operands[3]; - int32_t input_indexes[2]; - float input0[1*1*2*3] = { - -3, 2.5, 2, -2.1, 7.8, 100 - }; - float input1[1*1*2*3] = { - -1, 2, 3, -21, 8, 10.0 - }; - float *output; - - params.bin_op = op; - params.input0_broadcast = 0; - params.input1_broadcast = 0; - - operands[0].data = input0; - operands[0].dims[0] = 1; - operands[0].dims[1] = 1; - operands[0].dims[2] = 2; - operands[0].dims[3] = 3; - operands[1].data = input1; - operands[1].dims[0] = 1; - operands[1].dims[1] = 1; - operands[1].dims[2] = 2; - operands[1].dims[3] = 3; - operands[2].data = NULL; - - input_indexes[0] = 0; - input_indexes[1] = 1; - ff_dnn_execute_layer_math_binary(operands, input_indexes, 2, ¶ms, NULL); - - output = operands[2].data; - for (int i = 0; i < sizeof(input0) / sizeof(float); i++) { - float expected_output = get_expected(input0[i], input1[i], op); - if (fabs(output[i] - expected_output) > EPSON) { - printf("op %d, at index %d, output: %f, expected_output: %f (%s:%d)\n", - op, i, output[i], expected_output, __FILE__, __LINE__); - av_freep(&output); - return 1; - } - } - - av_freep(&output); - return 0; -} - -static int test(DNNMathBinaryOperation op) -{ - if (test_broadcast_input0(op)) - return 1; - - if (test_broadcast_input1(op)) - return 1; - - if (test_no_broadcast(op)) - return 1; - - return 0; -} - -int main(int argc, char **argv) -{ - if (test(DMBO_SUB)) - return 1; - - if (test(DMBO_ADD)) - return 1; - - if (test(DMBO_MUL)) - return 1; - - if (test(DMBO_REALDIV)) - return 1; - - if (test(DMBO_MINIMUM)) - return 1; - - if (test(DMBO_FLOORMOD)) - return 1; - - return 0; -} diff --git a/libavfilter/tests/dnn-layer-mathunary.c b/libavfilter/tests/dnn-layer-mathunary.c deleted file mode 100644 index 0f84c12960b..00000000000 --- a/libavfilter/tests/dnn-layer-mathunary.c +++ /dev/null @@ -1,148 +0,0 @@ -/* - * Copyright (c) 2020 - * - * 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 "libavfilter/dnn/dnn_backend_native_layer_mathunary.h" -#include "libavutil/avassert.h" - -#define EPS 0.00001 - -static float get_expected(float f, DNNMathUnaryOperation op) -{ - switch (op) - { - case DMUO_ABS: - return (f >= 0) ? f : -f; - case DMUO_SIN: - return sin(f); - case DMUO_COS: - return cos(f); - case DMUO_TAN: - return tan(f); - case DMUO_ASIN: - return asin(f); - case DMUO_ACOS: - return acos(f); - case DMUO_ATAN: - return atan(f); - case DMUO_SINH: - return sinh(f); - case DMUO_COSH: - return cosh(f); - case DMUO_TANH: - return tanh(f); - case DMUO_ASINH: - return asinh(f); - case DMUO_ACOSH: - return acosh(f); - case DMUO_ATANH: - return atanh(f); - case DMUO_CEIL: - return ceil(f); - case DMUO_FLOOR: - return floor(f); - case DMUO_ROUND: - return round(f); - case DMUO_EXP: - return exp(f); - default: - av_assert0(!"not supported yet"); - return 0.f; - } -} - -static int test(DNNMathUnaryOperation op) -{ - DnnLayerMathUnaryParams params; - DnnOperand operands[2]; - int32_t input_indexes[1]; - float input[1*1*3*3] = { - 0.1, 0.5, 0.75, -3, 2.5, 2, -2.1, 7.8, 100}; - float *output; - - params.un_op = op; - - operands[0].data = input; - operands[0].dims[0] = 1; - operands[0].dims[1] = 1; - operands[0].dims[2] = 3; - operands[0].dims[3] = 3; - operands[1].data = NULL; - - input_indexes[0] = 0; - ff_dnn_execute_layer_math_unary(operands, input_indexes, 1, ¶ms, NULL); - - output = operands[1].data; - for (int i = 0; i < sizeof(input) / sizeof(float); ++i) { - float expected_output = get_expected(input[i], op); - int output_nan = isnan(output[i]); - int expected_nan = isnan(expected_output); - if ((!output_nan && !expected_nan && fabs(output[i] - expected_output) > EPS) || - (output_nan && !expected_nan) || (!output_nan && expected_nan)) { - printf("at index %d, output: %f, expected_output: %f\n", i, output[i], expected_output); - av_freep(&output); - return 1; - } - } - - av_freep(&output); - return 0; -} - -int main(int agrc, char **argv) -{ - if (test(DMUO_ABS)) - return 1; - if (test(DMUO_SIN)) - return 1; - if (test(DMUO_COS)) - return 1; - if (test(DMUO_TAN)) - return 1; - if (test(DMUO_ASIN)) - return 1; - if (test(DMUO_ACOS)) - return 1; - if (test(DMUO_ATAN)) - return 1; - if (test(DMUO_SINH)) - return 1; - if (test(DMUO_COSH)) - return 1; - if (test(DMUO_TANH)) - return 1; - if (test(DMUO_ASINH)) - return 1; - if (test(DMUO_ACOSH)) - return 1; - if (test(DMUO_ATANH)) - return 1; - if (test(DMUO_CEIL)) - return 1; - if (test(DMUO_FLOOR)) - return 1; - if (test(DMUO_ROUND)) - return 1; - if (test(DMUO_EXP)) - return 1; - return 0; -} diff --git a/libavfilter/tests/dnn-layer-maximum.c b/libavfilter/tests/dnn-layer-maximum.c deleted file mode 100644 index bf22f3719fd..00000000000 --- a/libavfilter/tests/dnn-layer-maximum.c +++ /dev/null @@ -1,71 +0,0 @@ -/* - * Copyright (c) 2019 Guo Yejun - * - * 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 "libavfilter/dnn/dnn_backend_native_layer_maximum.h" - -#define EPSON 0.00001 - -static int test(void) -{ - DnnLayerMaximumParams params; - DnnOperand operands[2]; - int32_t input_indexes[1]; - float input[1*1*2*3] = { - -3, 2.5, 2, -2.1, 7.8, 100 - }; - float *output; - - params.val.y = 2.3; - - operands[0].data = input; - operands[0].dims[0] = 1; - operands[0].dims[1] = 1; - operands[0].dims[2] = 2; - operands[0].dims[3] = 3; - operands[1].data = NULL; - - input_indexes[0] = 0; - ff_dnn_execute_layer_maximum(operands, input_indexes, 1, ¶ms, NULL); - - output = operands[1].data; - for (int i = 0; i < sizeof(input) / sizeof(float); i++) { - float expected_output = input[i] > params.val.y ? input[i] : params.val.y; - if (fabs(output[i] - expected_output) > EPSON) { - printf("at index %d, output: %f, expected_output: %f\n", i, output[i], expected_output); - av_freep(&output); - return 1; - } - } - - av_freep(&output); - return 0; - -} - -int main(int argc, char **argv) -{ - if (test()) - return 1; - - return 0; -} diff --git a/libavfilter/tests/dnn-layer-pad.c b/libavfilter/tests/dnn-layer-pad.c deleted file mode 100644 index a8443ce3be0..00000000000 --- a/libavfilter/tests/dnn-layer-pad.c +++ /dev/null @@ -1,239 +0,0 @@ -/* - * Copyright (c) 2019 Guo Yejun - * - * 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 "libavfilter/dnn/dnn_backend_native_layer_pad.h" - -#define EPSON 0.00001 - -static int test_with_mode_symmetric(void) -{ - // the input data and expected data are generated with below python code. - /* - x = tf.placeholder(tf.float32, shape=[1, None, None, 3]) - y = tf.pad(x, [[0, 0], [2, 3], [3, 2], [0, 0]], 'SYMMETRIC') - data = np.arange(48).reshape(1, 4, 4, 3); - - sess=tf.Session() - sess.run(tf.global_variables_initializer()) - output = sess.run(y, feed_dict={x: data}) - - print(list(data.flatten())) - print(list(output.flatten())) - print(data.shape) - print(output.shape) - */ - - LayerPadParams params; - DnnOperand operands[2]; - int32_t input_indexes[1]; - float input[1*4*4*3] = { - 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47 - }; - float expected_output[1*9*9*3] = { - 18.0, 19.0, 20.0, 15.0, 16.0, 17.0, 12.0, 13.0, 14.0, 12.0, 13.0, 14.0, 15.0, 16.0, 17.0, 18.0, 19.0, 20.0, 21.0, 22.0, 23.0, 21.0, 22.0, 23.0, 18.0, 19.0, 20.0, 6.0, 7.0, 8.0, 3.0, - 4.0, 5.0, 0.0, 1.0, 2.0, 0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0, 9.0, 10.0, 11.0, 6.0, 7.0, 8.0, 6.0, 7.0, 8.0, 3.0, 4.0, 5.0, 0.0, 1.0, 2.0, 0.0, 1.0, 2.0, 3.0, - 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0, 9.0, 10.0, 11.0, 6.0, 7.0, 8.0, 18.0, 19.0, 20.0, 15.0, 16.0, 17.0, 12.0, 13.0, 14.0, 12.0, 13.0, 14.0, 15.0, 16.0, 17.0, 18.0, 19.0, 20.0, - 21.0, 22.0, 23.0, 21.0, 22.0, 23.0, 18.0, 19.0, 20.0, 30.0, 31.0, 32.0, 27.0, 28.0, 29.0, 24.0, 25.0, 26.0, 24.0, 25.0, 26.0, 27.0, 28.0, 29.0, 30.0, 31.0, 32.0, 33.0, 34.0, 35.0, 33.0, - 34.0, 35.0, 30.0, 31.0, 32.0, 42.0, 43.0, 44.0, 39.0, 40.0, 41.0, 36.0, 37.0, 38.0, 36.0, 37.0, 38.0, 39.0, 40.0, 41.0, 42.0, 43.0, 44.0, 45.0, 46.0, 47.0, 45.0, 46.0, 47.0, 42.0, 43.0, - 44.0, 42.0, 43.0, 44.0, 39.0, 40.0, 41.0, 36.0, 37.0, 38.0, 36.0, 37.0, 38.0, 39.0, 40.0, 41.0, 42.0, 43.0, 44.0, 45.0, 46.0, 47.0, 45.0, 46.0, 47.0, 42.0, 43.0, 44.0, 30.0, 31.0, 32.0, - 27.0, 28.0, 29.0, 24.0, 25.0, 26.0, 24.0, 25.0, 26.0, 27.0, 28.0, 29.0, 30.0, 31.0, 32.0, 33.0, 34.0, 35.0, 33.0, 34.0, 35.0, 30.0, 31.0, 32.0, 18.0, 19.0, 20.0, 15.0, 16.0, 17.0, 12.0, - 13.0, 14.0, 12.0, 13.0, 14.0, 15.0, 16.0, 17.0, 18.0, 19.0, 20.0, 21.0, 22.0, 23.0, 21.0, 22.0, 23.0, 18.0, 19.0, 20.0 - }; - float *output; - - params.mode = LPMP_SYMMETRIC; - params.paddings[0][0] = 0; - params.paddings[0][1] = 0; - params.paddings[1][0] = 2; - params.paddings[1][1] = 3; - params.paddings[2][0] = 3; - params.paddings[2][1] = 2; - params.paddings[3][0] = 0; - params.paddings[3][1] = 0; - - operands[0].data = input; - operands[0].dims[0] = 1; - operands[0].dims[1] = 4; - operands[0].dims[2] = 4; - operands[0].dims[3] = 3; - operands[1].data = NULL; - - input_indexes[0] = 0; - ff_dnn_execute_layer_pad(operands, input_indexes, 1, ¶ms, NULL); - - output = operands[1].data; - for (int i = 0; i < sizeof(expected_output) / sizeof(float); i++) { - if (fabs(output[i] - expected_output[i]) > EPSON) { - printf("at index %d, output: %f, expected_output: %f\n", i, output[i], expected_output[i]); - av_freep(&output); - return 1; - } - } - - av_freep(&output); - return 0; - -} - -static int test_with_mode_reflect(void) -{ - // the input data and expected data are generated with below python code. - /* - x = tf.placeholder(tf.float32, shape=[3, None, None, 3]) - y = tf.pad(x, [[1, 2], [0, 0], [0, 0], [0, 0]], 'REFLECT') - data = np.arange(36).reshape(3, 2, 2, 3); - - sess=tf.Session() - sess.run(tf.global_variables_initializer()) - output = sess.run(y, feed_dict={x: data}) - - print(list(data.flatten())) - print(list(output.flatten())) - print(data.shape) - print(output.shape) - */ - - LayerPadParams params; - DnnOperand operands[2]; - int32_t input_indexes[1]; - float input[3*2*2*3] = { - 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35 - }; - float expected_output[6*2*2*3] = { - 12.0, 13.0, 14.0, 15.0, 16.0, 17.0, 18.0, 19.0, 20.0, 21.0, 22.0, 23.0, 0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0, - 12.0, 13.0, 14.0, 15.0, 16.0, 17.0, 18.0, 19.0, 20.0, 21.0, 22.0, 23.0, 24.0, 25.0, 26.0, 27.0, 28.0, 29.0, 30.0, 31.0, 32.0, 33.0, 34.0, - 35.0, 12.0, 13.0, 14.0, 15.0, 16.0, 17.0, 18.0, 19.0, 20.0, 21.0, 22.0, 23.0, 0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0 - }; - float *output; - - params.mode = LPMP_REFLECT; - params.paddings[0][0] = 1; - params.paddings[0][1] = 2; - params.paddings[1][0] = 0; - params.paddings[1][1] = 0; - params.paddings[2][0] = 0; - params.paddings[2][1] = 0; - params.paddings[3][0] = 0; - params.paddings[3][1] = 0; - - operands[0].data = input; - operands[0].dims[0] = 3; - operands[0].dims[1] = 2; - operands[0].dims[2] = 2; - operands[0].dims[3] = 3; - operands[1].data = NULL; - - input_indexes[0] = 0; - ff_dnn_execute_layer_pad(operands, input_indexes, 1, ¶ms, NULL); - - output = operands[1].data; - for (int i = 0; i < sizeof(expected_output) / sizeof(float); i++) { - if (fabs(output[i] - expected_output[i]) > EPSON) { - printf("at index %d, output: %f, expected_output: %f\n", i, output[i], expected_output[i]); - av_freep(&output); - return 1; - } - } - - av_freep(&output); - return 0; - -} - -static int test_with_mode_constant(void) -{ - // the input data and expected data are generated with below python code. - /* - x = tf.placeholder(tf.float32, shape=[1, None, None, 3]) - y = tf.pad(x, [[0, 0], [1, 0], [0, 0], [1, 2]], 'CONSTANT', constant_values=728) - data = np.arange(12).reshape(1, 2, 2, 3); - - sess=tf.Session() - sess.run(tf.global_variables_initializer()) - output = sess.run(y, feed_dict={x: data}) - - print(list(data.flatten())) - print(list(output.flatten())) - print(data.shape) - print(output.shape) - */ - - LayerPadParams params; - DnnOperand operands[2]; - int32_t input_indexes[1]; - float input[1*2*2*3] = { - 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 - }; - float expected_output[1*3*2*6] = { - 728.0, 728.0, 728.0, 728.0, 728.0, 728.0, 728.0, 728.0, 728.0, 728.0, 728.0, - 728.0, 728.0, 0.0, 1.0, 2.0, 728.0, 728.0, 728.0, 3.0, 4.0, 5.0, 728.0, 728.0, - 728.0, 6.0, 7.0, 8.0, 728.0, 728.0, 728.0, 9.0, 10.0, 11.0, 728.0, 728.0 - }; - float *output; - - params.mode = LPMP_CONSTANT; - params.constant_values = 728; - params.paddings[0][0] = 0; - params.paddings[0][1] = 0; - params.paddings[1][0] = 1; - params.paddings[1][1] = 0; - params.paddings[2][0] = 0; - params.paddings[2][1] = 0; - params.paddings[3][0] = 1; - params.paddings[3][1] = 2; - - operands[0].data = input; - operands[0].dims[0] = 1; - operands[0].dims[1] = 2; - operands[0].dims[2] = 2; - operands[0].dims[3] = 3; - operands[1].data = NULL; - - input_indexes[0] = 0; - ff_dnn_execute_layer_pad(operands, input_indexes, 1, ¶ms, NULL); - - output = operands[1].data; - for (int i = 0; i < sizeof(expected_output) / sizeof(float); i++) { - if (fabs(output[i] - expected_output[i]) > EPSON) { - printf("at index %d, output: %f, expected_output: %f\n", i, output[i], expected_output[i]); - av_freep(&output); - return 1; - } - } - - av_freep(&output); - return 0; - -} - -int main(int argc, char **argv) -{ - if (test_with_mode_symmetric()) - return 1; - - if (test_with_mode_reflect()) - return 1; - - if (test_with_mode_constant()) - return 1; -} diff --git a/libavfilter/vf_derain.c b/libavfilter/vf_derain.c index 7e84cd65a3e..35e1ae736a4 100644 --- a/libavfilter/vf_derain.c +++ b/libavfilter/vf_derain.c @@ -44,7 +44,6 @@ static const AVOption derain_options[] = { { "derain", "derain filter flag", 0, AV_OPT_TYPE_CONST, { .i64 = 0 }, 0, 0, FLAGS, "type" }, { "dehaze", "dehaze filter flag", 0, AV_OPT_TYPE_CONST, { .i64 = 1 }, 0, 0, FLAGS, "type" }, { "dnn_backend", "DNN backend", OFFSET(dnnctx.backend_type), AV_OPT_TYPE_INT, { .i64 = 1 }, 0, 1, FLAGS, "backend" }, - { "native", "native backend flag", 0, AV_OPT_TYPE_CONST, { .i64 = 0 }, 0, 0, FLAGS, "backend" }, #if (CONFIG_LIBTENSORFLOW == 1) { "tensorflow", "tensorflow backend flag", 0, AV_OPT_TYPE_CONST, { .i64 = 1 }, 0, 0, FLAGS, "backend" }, #endif diff --git a/libavfilter/vf_dnn_processing.c b/libavfilter/vf_dnn_processing.c index 968df666fc5..18ecf111fe4 100644 --- a/libavfilter/vf_dnn_processing.c +++ b/libavfilter/vf_dnn_processing.c @@ -46,7 +46,6 @@ typedef struct DnnProcessingContext { #define FLAGS AV_OPT_FLAG_FILTERING_PARAM | AV_OPT_FLAG_VIDEO_PARAM static const AVOption dnn_processing_options[] = { { "dnn_backend", "DNN backend", OFFSET(backend_type), AV_OPT_TYPE_INT, { .i64 = 1 }, INT_MIN, INT_MAX, FLAGS, "backend" }, - { "native", "native backend flag", 0, AV_OPT_TYPE_CONST, { .i64 = 0 }, 0, 0, FLAGS, "backend" }, #if (CONFIG_LIBTENSORFLOW == 1) { "tensorflow", "tensorflow backend flag", 0, AV_OPT_TYPE_CONST, { .i64 = 1 }, 0, 0, FLAGS, "backend" }, #endif diff --git a/libavfilter/vf_sr.c b/libavfilter/vf_sr.c index e9fe746baeb..e06ae91d7c9 100644 --- a/libavfilter/vf_sr.c +++ b/libavfilter/vf_sr.c @@ -47,7 +47,6 @@ typedef struct SRContext { #define FLAGS AV_OPT_FLAG_FILTERING_PARAM | AV_OPT_FLAG_VIDEO_PARAM static const AVOption sr_options[] = { { "dnn_backend", "DNN backend used for model execution", OFFSET(dnnctx.backend_type), AV_OPT_TYPE_INT, { .i64 = 1 }, 0, 1, FLAGS, "backend" }, - { "native", "native backend flag", 0, AV_OPT_TYPE_CONST, { .i64 = 0 }, 0, 0, FLAGS, "backend" }, #if (CONFIG_LIBTENSORFLOW == 1) { "tensorflow", "tensorflow backend flag", 0, AV_OPT_TYPE_CONST, { .i64 = 1 }, 0, 0, FLAGS, "backend" }, #endif diff --git a/tests/Makefile b/tests/Makefile index d80065a9bfa..35ea824663c 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -172,7 +172,6 @@ include $(SRC_PATH)/tests/fate/cover-art.mak include $(SRC_PATH)/tests/fate/dca.mak include $(SRC_PATH)/tests/fate/demux.mak include $(SRC_PATH)/tests/fate/dfa.mak -include $(SRC_PATH)/tests/fate/dnn.mak include $(SRC_PATH)/tests/fate/dnxhd.mak include $(SRC_PATH)/tests/fate/dpcm.mak include $(SRC_PATH)/tests/fate/dvvideo.mak diff --git a/tests/fate/dnn.mak b/tests/fate/dnn.mak deleted file mode 100644 index a30a2976d91..00000000000 --- a/tests/fate/dnn.mak +++ /dev/null @@ -1,45 +0,0 @@ -DNNTESTSDIR := libavfilter/tests - -FATE_DNN += fate-dnn-layer-pad -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$(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$(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$(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$(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$(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$(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$(EXESUF) -fate-dnn-layer-avgpool: CMD = run $(DNNTESTSDIR)/dnn-layer-avgpool$(EXESUF) -fate-dnn-layer-avgpool: CMP = null - -FATE-$(CONFIG_DNN) += $(FATE_DNN) - -fate-dnn: $(FATE_DNN) From af8be7bf437ebeb10911ba30c8cf696a0da9657c Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Mon, 24 Apr 2023 10:55:43 +0200 Subject: [PATCH 0811/2172] lavf/dauddec: set timebase to 1/samplerate Prevents lavf from generating inexact timestamps with the default timebase of 1/90000. --- libavformat/dauddec.c | 4 ++++ tests/ref/fate/d-cinema-demux | 10 +++++----- tests/ref/fate/dcinema-encode | 26 +++++++++++++------------- 3 files changed, 22 insertions(+), 18 deletions(-) diff --git a/libavformat/dauddec.c b/libavformat/dauddec.c index 0cbf7e4e368..7e411091eca 100644 --- a/libavformat/dauddec.c +++ b/libavformat/dauddec.c @@ -21,6 +21,7 @@ #include "libavutil/channel_layout.h" #include "avformat.h" +#include "internal.h" static int daud_header(AVFormatContext *s) { AVStream *st = avformat_new_stream(s, NULL); @@ -34,6 +35,9 @@ static int daud_header(AVFormatContext *s) { st->codecpar->bit_rate = 3 * 6 * 96000 * 8; st->codecpar->block_align = 3 * 6; st->codecpar->bits_per_coded_sample = 24; + + avpriv_set_pts_info(st, 64, 1, st->codecpar->sample_rate); + return 0; } diff --git a/tests/ref/fate/d-cinema-demux b/tests/ref/fate/d-cinema-demux index f1e8b5f7552..e517c20e762 100644 --- a/tests/ref/fate/d-cinema-demux +++ b/tests/ref/fate/d-cinema-demux @@ -1,9 +1,9 @@ -#tb 0: 1/90000 +#tb 0: 1/96000 #media_type 0: audio #codec_id 0: pcm_s24daud #sample_rate 0: 96000 #channel_layout_name 0: 5.1(side) -0, 0, 0, 1875, 36000, 0xd592781d -0, 1875, 1875, 1875, 36000, 0xd592781d -0, 3750, 3750, 1875, 36000, 0xd592781d -0, 5625, 5625, 1200, 23056, 0xde81f0d6, F=0x3 +0, 0, 0, 2000, 36000, 0xd592781d +0, 2000, 2000, 2000, 36000, 0xd592781d +0, 4000, 4000, 2000, 36000, 0xd592781d +0, 6000, 6000, 1280, 23056, 0xde81f0d6, F=0x3 diff --git a/tests/ref/fate/dcinema-encode b/tests/ref/fate/dcinema-encode index 471820dbdac..fabbc034f09 100644 --- a/tests/ref/fate/dcinema-encode +++ b/tests/ref/fate/dcinema-encode @@ -9,21 +9,21 @@ #stream#, dts, pts, duration, size, hash 0, 0, 0, 341, 4092, 697cddfcd0e21f24782af0705b7048f3 0, 341, 341, 341, 4092, a057b18cd493923fed33c18578f61e0b -0, 683, 683, 341, 4092, f4eacfd888566040067b8e5ce7d276c6 -0, 1024, 1024, 341, 4092, 4de78d332ce2047014880a110c160dc2 +0, 682, 682, 341, 4092, f4eacfd888566040067b8e5ce7d276c6 +0, 1023, 1023, 341, 4092, 4de78d332ce2047014880a110c160dc2 0, 1364, 1364, 341, 4092, 138ee3fc206538feca6de3d6d62d08eb -0, 1706, 1706, 341, 4092, 187a2f2998aa1c0ba0130c57dd1d6c86 -0, 2047, 2047, 341, 4092, 54e6c3db8a5f8c09b47f025659a36b17 +0, 1705, 1705, 341, 4092, 187a2f2998aa1c0ba0130c57dd1d6c86 +0, 2046, 2046, 341, 4092, 54e6c3db8a5f8c09b47f025659a36b17 0, 2387, 2387, 341, 4092, 8abfdf44a24c158429c71e01cee31e20 -0, 2729, 2729, 341, 4092, bd08f5018edc5dc4520739e913ed89a3 -0, 3070, 3070, 341, 4092, 9f60ba4275646344e4a9b3c647efffe9 -0, 3411, 3411, 341, 4092, 00cefc1f27230cdd06ecd43132e16327 +0, 2728, 2728, 341, 4092, bd08f5018edc5dc4520739e913ed89a3 +0, 3069, 3069, 341, 4092, 9f60ba4275646344e4a9b3c647efffe9 +0, 3410, 3410, 341, 4092, 00cefc1f27230cdd06ecd43132e16327 0, 3751, 3751, 341, 4092, d4d13047cd639ed722a4ae1bc1f06991 -0, 4093, 4093, 341, 4092, 16b227e4f968c11cba279506f00d5172 -0, 4434, 4434, 341, 4092, 70f4046f709fdd4d80e2f2ffc862f21a +0, 4092, 4092, 341, 4092, 16b227e4f968c11cba279506f00d5172 +0, 4433, 4433, 341, 4092, 70f4046f709fdd4d80e2f2ffc862f21a 0, 4774, 4774, 341, 4092, adbef4b4ef728f0c2a31b4b0baba50a0 -0, 5116, 5116, 341, 4092, fe009b6cc96b9d1098dcc5fba0e6b3fa -0, 5457, 5457, 341, 4092, 4462b2f1654c9b31fdd7ab04ffb84192 +0, 5115, 5115, 341, 4092, fe009b6cc96b9d1098dcc5fba0e6b3fa +0, 5456, 5456, 341, 4092, 4462b2f1654c9b31fdd7ab04ffb84192 0, 5797, 5797, 341, 4092, 2e96ba3bd13de03f9cfdc2b8c3ea0620 -0, 6139, 6139, 341, 4092, 395c920f10cce6670029a98095eba027 -0, 6480, 6480, 341, 4092, 28d4c2f6364f31cb61f4aa144badc734 +0, 6138, 6138, 341, 4092, 395c920f10cce6670029a98095eba027 +0, 6479, 6479, 341, 4092, 28d4c2f6364f31cb61f4aa144badc734 From 1b7c13e1a437d7db84a206e5c55b0e0aa95760ec Mon Sep 17 00:00:00 2001 From: James Almer Date: Fri, 28 Apr 2023 13:35:19 -0300 Subject: [PATCH 0812/2172] fftools/ffmpeg_filter: fix leak of AVIOContext in read_binary() It was only being freed on failure. Reviewed-by: Anton Khirnov Signed-off-by: James Almer --- fftools/ffmpeg_filter.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/fftools/ffmpeg_filter.c b/fftools/ffmpeg_filter.c index b26160b3756..161ea9c866c 100644 --- a/fftools/ffmpeg_filter.c +++ b/fftools/ffmpeg_filter.c @@ -408,11 +408,13 @@ static int read_binary(const char *path, uint8_t **data, int *len) *len = fsize; - return 0; + ret = 0; fail: avio_close(io); - av_freep(data); - *len = 0; + if (ret < 0) { + av_freep(data); + *len = 0; + } return ret; } From 51504cf27923e60d0a8203ca8c83a14493223063 Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Fri, 28 Apr 2023 16:35:22 +0200 Subject: [PATCH 0813/2172] avfilter/af_adynamicequalizer: add dftype option Useful for filter selection for detection control. --- doc/filters.texi | 19 +++++++-- libavfilter/af_adynamicequalizer.c | 62 +++++++++++++++++++++++++----- 2 files changed, 67 insertions(+), 14 deletions(-) diff --git a/doc/filters.texi b/doc/filters.texi index 01a71223a12..50e16821445 100644 --- a/doc/filters.texi +++ b/doc/filters.texi @@ -1007,15 +1007,15 @@ 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. +Threshold detection is using detection 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. +Set the detection frequency in Hz used for detection 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. +Set the detection resonance factor for detection filter used to trigger equalization. Default value is 1. Allowed range is from 0.001 to 1000. @item tfrequency @@ -1053,7 +1053,7 @@ Set the mode of filter operation, can be one of the following: @table @samp @item listen -Output only isolated bandpass signal. +Output only isolated detection signal. @item cut Cut frequencies above detection threshold. @item boost @@ -1061,6 +1061,17 @@ Boost frequencies bellow detection threshold. @end table Default mode is @samp{cut}. +@item dftype +Set the type of detection filter, can be one of the following: + +@table @samp +@item bandpass +@item lowpass +@item highpass +@item peak +@end table +Default type is @samp{bandpass}. + @item tftype Set the type of target filter, can be one of the following: diff --git a/libavfilter/af_adynamicequalizer.c b/libavfilter/af_adynamicequalizer.c index 0e44922c1e3..594eedb4e38 100644 --- a/libavfilter/af_adynamicequalizer.c +++ b/libavfilter/af_adynamicequalizer.c @@ -41,7 +41,8 @@ typedef struct AudioDynamicEqualizerContext { int mode; int direction; int detection; - int type; + int tftype; + int dftype; AVFrame *state; } AudioDynamicEqualizerContext; @@ -105,12 +106,14 @@ static int filter_channels(AVFilterContext *ctx, void *arg, int jobnr, int nb_jo const int end = (in->ch_layout.nb_channels * (jobnr+1)) / nb_jobs; const int detection = s->detection; const int direction = s->direction; + const int dftype = s->dftype; + const int tftype = s->tftype; const int mode = s->mode; - const int type = s->type; - double da[3], dm[3]; + double k, da[3], dm[3]; - { - double k = 1. / dqfactor; + switch (dftype) { + case 0: + k = 1. / dqfactor; da[0] = 1. / (1. + dg * (dg + k)); da[1] = dg * da[0]; @@ -119,6 +122,40 @@ static int filter_channels(AVFilterContext *ctx, void *arg, int jobnr, int nb_jo dm[0] = 0.; dm[1] = k; dm[2] = 0.; + break; + case 1: + 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] = 0.; + dm[2] = 1.; + break; + case 2: + 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] = -k; + dm[2] = -1.; + break; + case 3: + 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] = -k; + dm[2] = -2.; + break; } for (int ch = start; ch < end; ch++) { @@ -169,7 +206,7 @@ static int filter_channels(AVFilterContext *ctx, void *arg, int jobnr, int nb_jo if (state[4] != detect || n == 0) { state[4] = gain = detect; - switch (type) { + switch (tftype) { case 0: k = 1. / (tqfactor * gain); @@ -279,10 +316,15 @@ static const AVOption adynamicequalizer_options[] = { { "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" }, - { "tftype", "set target filter type", OFFSET(type), AV_OPT_TYPE_INT, {.i64=0}, 0, 2, FLAGS, "type" }, - { "bell", 0, 0, AV_OPT_TYPE_CONST, {.i64=0}, 0, 0, FLAGS, "type" }, - { "lowshelf", 0, 0, AV_OPT_TYPE_CONST, {.i64=1}, 0, 0, FLAGS, "type" }, - { "highshelf",0, 0, AV_OPT_TYPE_CONST, {.i64=2}, 0, 0, FLAGS, "type" }, + { "dftype", "set detection filter type",OFFSET(dftype), AV_OPT_TYPE_INT, {.i64=0}, 0, 3, FLAGS, "dftype" }, + { "bandpass", 0, 0, AV_OPT_TYPE_CONST, {.i64=0}, 0, 0, FLAGS, "dftype" }, + { "lowpass", 0, 0, AV_OPT_TYPE_CONST, {.i64=1}, 0, 0, FLAGS, "dftype" }, + { "highpass", 0, 0, AV_OPT_TYPE_CONST, {.i64=2}, 0, 0, FLAGS, "dftype" }, + { "peak", 0, 0, AV_OPT_TYPE_CONST, {.i64=3}, 0, 0, FLAGS, "dftype" }, + { "tftype", "set target filter type", OFFSET(tftype), AV_OPT_TYPE_INT, {.i64=0}, 0, 2, FLAGS, "tftype" }, + { "bell", 0, 0, AV_OPT_TYPE_CONST, {.i64=0}, 0, 0, FLAGS, "tftype" }, + { "lowshelf", 0, 0, AV_OPT_TYPE_CONST, {.i64=1}, 0, 0, FLAGS, "tftype" }, + { "highshelf",0, 0, AV_OPT_TYPE_CONST, {.i64=2}, 0, 0, FLAGS, "tftype" }, { "direction", "set direction", OFFSET(direction), AV_OPT_TYPE_INT, {.i64=0}, 0, 1, FLAGS, "direction" }, { "downward", 0, 0, AV_OPT_TYPE_CONST, {.i64=0}, 0, 0, FLAGS, "direction" }, { "upward", 0, 0, AV_OPT_TYPE_CONST, {.i64=1}, 0, 0, FLAGS, "direction" }, From 153aaae45778589dda6573ab45da718e20334d2d Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Fri, 28 Apr 2023 22:42:30 +0200 Subject: [PATCH 0814/2172] avfilter/af_adynamicequalizer: factor detection filter code --- libavfilter/af_adynamicequalizer.c | 79 +++++++++++++++++------------- 1 file changed, 46 insertions(+), 33 deletions(-) diff --git a/libavfilter/af_adynamicequalizer.c b/libavfilter/af_adynamicequalizer.c index 594eedb4e38..77c98ed1058 100644 --- a/libavfilter/af_adynamicequalizer.c +++ b/libavfilter/af_adynamicequalizer.c @@ -44,6 +44,7 @@ typedef struct AudioDynamicEqualizerContext { int tftype; int dftype; + double da[3], dm[3]; AVFrame *state; } AudioDynamicEqualizerContext; @@ -65,7 +66,7 @@ static int config_input(AVFilterLink *inlink) return 0; } -static double get_svf(double in, double *m, double *a, double *b) +static double get_svf(double in, const double *m, const double *a, double *b) { const double v0 = in; const double v3 = v0 - b[1]; @@ -82,34 +83,25 @@ typedef struct ThreadData { AVFrame *in, *out; } ThreadData; -static int filter_channels(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) +static double get_coef(double x, double sr) +{ + return exp(-1000. / (x * sr)); +} + +static int filter_prepare(AVFilterContext *ctx) { 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 ratio = s->ratio; - const double range = s->range; + const double sample_rate = ctx->inputs[0]->sample_rate; const double dfrequency = fmin(s->dfrequency, sample_rate * 0.5); - const double tfrequency = fmin(s->tfrequency, sample_rate * 0.5); - const double release = s->release_coef; - const double irelease = 1. - release; - const double attack = s->attack_coef; - const double iattack = 1. - attack; - 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->ch_layout.nb_channels * jobnr) / nb_jobs; - const int end = (in->ch_layout.nb_channels * (jobnr+1)) / nb_jobs; - const int detection = s->detection; - const int direction = s->direction; + const double dqfactor = s->dqfactor; const int dftype = s->dftype; - const int tftype = s->tftype; - const int mode = s->mode; - double k, da[3], dm[3]; + double *da = s->da; + double *dm = s->dm; + double k; + + s->attack_coef = get_coef(s->attack, sample_rate); + s->release_coef = get_coef(s->release, sample_rate); switch (dftype) { case 0: @@ -158,6 +150,35 @@ static int filter_channels(AVFilterContext *ctx, void *arg, int jobnr, int nb_jo break; } + return 0; +} + +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 ratio = s->ratio; + const double range = s->range; + const double tfrequency = fmin(s->tfrequency, sample_rate * 0.5); + const double release = s->release_coef; + const double irelease = 1. - release; + const double attack = s->attack_coef; + const double iattack = 1. - attack; + const double tqfactor = s->tqfactor; + const double fg = tan(M_PI * tfrequency / sample_rate); + const int start = (in->ch_layout.nb_channels * jobnr) / nb_jobs; + const int end = (in->ch_layout.nb_channels * (jobnr+1)) / nb_jobs; + const int detection = s->detection; + const int direction = s->direction; + const int tftype = s->tftype; + const int mode = s->mode; + const double *da = s->da; + const double *dm = s->dm; + for (int ch = start; ch < end; ch++) { const double *src = (const double *)in->extended_data[ch]; double *dst = (double *)out->extended_data[ch]; @@ -254,16 +275,10 @@ static int filter_channels(AVFilterContext *ctx, void *arg, int jobnr, int nb_jo 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; @@ -278,11 +293,9 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in) 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; + filter_prepare(ctx); ff_filter_execute(ctx, filter_channels, &td, NULL, FFMIN(outlink->ch_layout.nb_channels, ff_filter_get_nb_threads(ctx))); From 5564ba49a16f82e3ccb98cd008d824bcbc2ada13 Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Fri, 28 Apr 2023 23:16:28 +0200 Subject: [PATCH 0815/2172] avfilter/af_adynamicequalizer: refactor code to gain small speedup --- libavfilter/af_adynamicequalizer.c | 29 +++++++++++++++++++---------- 1 file changed, 19 insertions(+), 10 deletions(-) diff --git a/libavfilter/af_adynamicequalizer.c b/libavfilter/af_adynamicequalizer.c index 77c98ed1058..e741b55eada 100644 --- a/libavfilter/af_adynamicequalizer.c +++ b/libavfilter/af_adynamicequalizer.c @@ -199,16 +199,25 @@ static int filter_channels(AVFilterContext *ctx, void *arg, int jobnr, int nb_jo if (detection > 0) state[5] = fmax(state[5], detect); - if (direction == 0 && mode == 0 && detect < threshold) - detect = 1. / av_clipd(1. + makeup + (threshold - detect) * ratio, 1., range); - else if (direction == 0 && mode == 1 && detect < threshold) - detect = av_clipd(1. + makeup + (threshold - detect) * ratio, 1., range); - else if (direction == 1 && mode == 0 && detect > threshold) - detect = 1. / av_clipd(1. + makeup + (detect - threshold) * ratio, 1., range); - else if (direction == 1 && mode == 1 && detect > threshold) - detect = av_clipd(1. + makeup + (detect - threshold) * ratio, 1., range); - else - detect = 1.; + if (direction == 0) { + if (detect < threshold) { + if (mode == 0) + detect = 1. / av_clipd(1. + makeup + (threshold - detect) * ratio, 1., range); + else + detect = av_clipd(1. + makeup + (threshold - detect) * ratio, 1., range); + } else { + detect = 1.; + } + } else { + if (detect > threshold) { + if (mode == 0) + detect = 1. / av_clipd(1. + makeup + (detect - threshold) * ratio, 1., range); + else + detect = av_clipd(1. + makeup + (detect - threshold) * ratio, 1., range); + } else { + detect = 1.; + } + } if (direction == 0) { if (detect > state[4]) { From df3fd3accd84b12720312fc0b8ec262b3f44486b Mon Sep 17 00:00:00 2001 From: James Almer Date: Thu, 27 Apr 2023 16:14:14 -0300 Subject: [PATCH 0816/2172] avcodec/hevc_ps: use get_ue_golomb() for some PPS Screen Content Coding extension fields Also remove the _minus8 part of the name to be in line with the rest of the decoder, and fix the storage type for pps_palette_predictor_initializer, to support hbd values. Signed-off-by: James Almer --- libavcodec/hevc_ps.c | 21 ++++++++++++++------- libavcodec/hevc_ps.h | 6 +++--- 2 files changed, 17 insertions(+), 10 deletions(-) diff --git a/libavcodec/hevc_ps.c b/libavcodec/hevc_ps.c index f29f783f774..289b8f7d953 100644 --- a/libavcodec/hevc_ps.c +++ b/libavcodec/hevc_ps.c @@ -1538,17 +1538,24 @@ static int pps_scc_extension(GetBitContext *gb, AVCodecContext *avctx, } if (pps->pps_palette_predictor_initializers_present_flag = get_bits1(gb)) { - if ((pps->pps_num_palette_predictor_initializers = get_ue_golomb_long(gb)) > 0) { + pps->pps_num_palette_predictor_initializers = get_ue_golomb(gb); + if (pps->pps_num_palette_predictor_initializers > 0) { + if (pps->pps_num_palette_predictor_initializers > HEVC_MAX_PALETTE_PREDICTOR_SIZE) { + av_log(avctx, AV_LOG_ERROR, + "pps_num_palette_predictor_initializers out of range: %u\n", + pps->pps_num_palette_predictor_initializers); + return AVERROR_INVALIDDATA; + } pps->monochrome_palette_flag = get_bits1(gb); - pps->luma_bit_depth_entry_minus8 = get_ue_golomb_long(gb); + pps->luma_bit_depth_entry = get_ue_golomb_31(gb) + 8; if (!pps->monochrome_palette_flag) - pps->chroma_bit_depth_entry_minus8 = get_ue_golomb_long(gb); + pps->chroma_bit_depth_entry = get_ue_golomb_31(gb) + 8; num_comps = pps->monochrome_palette_flag ? 1 : 3; - for (int comp = 0; comp < num_comps; comp++) + for (int comp = 0; comp < num_comps; comp++) { + int bit_depth = !comp ? pps->luma_bit_depth_entry : pps->chroma_bit_depth_entry; for (int i = 0; i < pps->pps_num_palette_predictor_initializers; i++) - pps->pps_palette_predictor_initializer[comp][i] = - get_bits(gb, 8 + (!comp ? pps->luma_bit_depth_entry_minus8 : - pps->chroma_bit_depth_entry_minus8)); + pps->pps_palette_predictor_initializer[comp][i] = get_bits(gb, bit_depth); + } } } diff --git a/libavcodec/hevc_ps.h b/libavcodec/hevc_ps.h index 0c9c2786628..8cd99bb1617 100644 --- a/libavcodec/hevc_ps.h +++ b/libavcodec/hevc_ps.h @@ -358,9 +358,9 @@ typedef struct HEVCPPS { uint8_t pps_palette_predictor_initializers_present_flag; uint8_t pps_num_palette_predictor_initializers; uint8_t monochrome_palette_flag; - uint8_t luma_bit_depth_entry_minus8; - uint8_t chroma_bit_depth_entry_minus8; - uint8_t pps_palette_predictor_initializer[3][HEVC_MAX_PALETTE_PREDICTOR_SIZE]; + uint8_t luma_bit_depth_entry; + uint8_t chroma_bit_depth_entry; + uint16_t pps_palette_predictor_initializer[3][HEVC_MAX_PALETTE_PREDICTOR_SIZE]; // Inferred parameters unsigned int *column_width; ///< ColumnWidth From 41dd50ad0dbbdec2225a6793758d40f0281978d9 Mon Sep 17 00:00:00 2001 From: James Almer Date: Thu, 27 Apr 2023 16:36:29 -0300 Subject: [PATCH 0817/2172] avcodec/hevc_ps: use get_{ue,se}_golomb() for some PPS Range extension fields Signed-off-by: James Almer --- libavcodec/hevc_ps.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/libavcodec/hevc_ps.c b/libavcodec/hevc_ps.c index 289b8f7d953..585b095073c 100644 --- a/libavcodec/hevc_ps.c +++ b/libavcodec/hevc_ps.c @@ -1478,33 +1478,33 @@ static int pps_range_extensions(GetBitContext *gb, AVCodecContext *avctx, HEVCPPS *pps, HEVCSPS *sps) { if (pps->transform_skip_enabled_flag) { - pps->log2_max_transform_skip_block_size = get_ue_golomb_long(gb) + 2; + pps->log2_max_transform_skip_block_size = get_ue_golomb_31(gb) + 2; } pps->cross_component_prediction_enabled_flag = get_bits1(gb); pps->chroma_qp_offset_list_enabled_flag = get_bits1(gb); if (pps->chroma_qp_offset_list_enabled_flag) { - pps->diff_cu_chroma_qp_offset_depth = get_ue_golomb_long(gb); - pps->chroma_qp_offset_list_len_minus1 = get_ue_golomb_long(gb); + pps->diff_cu_chroma_qp_offset_depth = get_ue_golomb_31(gb); + pps->chroma_qp_offset_list_len_minus1 = get_ue_golomb_31(gb); if (pps->chroma_qp_offset_list_len_minus1 > 5) { av_log(avctx, AV_LOG_ERROR, "chroma_qp_offset_list_len_minus1 shall be in the range [0, 5].\n"); return AVERROR_INVALIDDATA; } for (int i = 0; i <= pps->chroma_qp_offset_list_len_minus1; i++) { - pps->cb_qp_offset_list[i] = get_se_golomb_long(gb); + pps->cb_qp_offset_list[i] = get_se_golomb(gb); if (pps->cb_qp_offset_list[i]) { av_log(avctx, AV_LOG_WARNING, "cb_qp_offset_list not tested yet.\n"); } - pps->cr_qp_offset_list[i] = get_se_golomb_long(gb); + pps->cr_qp_offset_list[i] = get_se_golomb(gb); if (pps->cr_qp_offset_list[i]) { av_log(avctx, AV_LOG_WARNING, "cb_qp_offset_list not tested yet.\n"); } } } - pps->log2_sao_offset_scale_luma = get_ue_golomb_long(gb); - pps->log2_sao_offset_scale_chroma = get_ue_golomb_long(gb); + pps->log2_sao_offset_scale_luma = get_ue_golomb_31(gb); + pps->log2_sao_offset_scale_chroma = get_ue_golomb_31(gb); if ( pps->log2_sao_offset_scale_luma > FFMAX(sps->bit_depth - 10, 0) || pps->log2_sao_offset_scale_chroma > FFMAX(sps->bit_depth_chroma - 10, 0) From f247a3d82d9521394d71c4f95f87789af71de0cc Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Sat, 29 Apr 2023 10:40:18 +0200 Subject: [PATCH 0818/2172] avfilter/af_adynamicequalizer: add precision option --- doc/filters.texi | 14 ++ libavfilter/adynamicequalizer_template.c | 270 +++++++++++++++++++++++ libavfilter/af_adynamicequalizer.c | 270 +++++------------------ 3 files changed, 342 insertions(+), 212 deletions(-) create mode 100644 libavfilter/adynamicequalizer_template.c diff --git a/doc/filters.texi b/doc/filters.texi index 50e16821445..f89b1d0b520 100644 --- a/doc/filters.texi +++ b/doc/filters.texi @@ -1107,6 +1107,20 @@ Stop picking threshold value. @item on Start picking threshold value. @end table + +@item precision +Set which precision to use when processing samples. + +@table @option +@item auto +Auto pick internal sample format depending on other filters. + +@item float +Always use single-floating point precision sample format. + +@item double +Always use double-floating point precision sample format. +@end table @end table @subsection Commands diff --git a/libavfilter/adynamicequalizer_template.c b/libavfilter/adynamicequalizer_template.c new file mode 100644 index 00000000000..ab180a9b9da --- /dev/null +++ b/libavfilter/adynamicequalizer_template.c @@ -0,0 +1,270 @@ +/* + * 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 + */ + +#undef ftype +#undef SQRT +#undef TAN +#undef ONE +#undef TWO +#undef ZERO +#undef FMAX +#undef FMIN +#undef CLIP +#undef SAMPLE_FORMAT +#undef FABS +#if DEPTH == 32 +#define SAMPLE_FORMAT float +#define SQRT sqrtf +#define TAN tanf +#define ONE 1.f +#define TWO 2.f +#define ZERO 0.f +#define FMIN fminf +#define FMAX fmaxf +#define CLIP av_clipf +#define FABS fabsf +#define ftype float +#else +#define SAMPLE_FORMAT double +#define SQRT sqrt +#define TAN tan +#define ONE 1.0 +#define TWO 2.0 +#define ZERO 0.0 +#define FMIN fmin +#define FMAX fmax +#define CLIP av_clipd +#define FABS fabs +#define ftype double +#endif + +#define fn3(a,b) a##_##b +#define fn2(a,b) fn3(a,b) +#define fn(a) fn2(a, SAMPLE_FORMAT) + +static ftype fn(get_svf)(ftype in, const ftype *m, const ftype *a, ftype *b) +{ + const ftype v0 = in; + const ftype v3 = v0 - b[1]; + const ftype v1 = a[0] * b[0] + a[1] * v3; + const ftype v2 = b[1] + a[1] * b[0] + a[2] * v3; + + b[0] = TWO * v1 - b[0]; + b[1] = TWO * v2 - b[1]; + + return m[0] * v0 + m[1] * v1 + m[2] * v2; +} + +static int fn(filter_prepare)(AVFilterContext *ctx) +{ + AudioDynamicEqualizerContext *s = ctx->priv; + const ftype sample_rate = ctx->inputs[0]->sample_rate; + const ftype dfrequency = FMIN(s->dfrequency, sample_rate * 0.5); + const ftype dg = TAN(M_PI * dfrequency / sample_rate); + const ftype dqfactor = s->dqfactor; + const int dftype = s->dftype; + ftype *da = fn(s->da); + ftype *dm = fn(s->dm); + ftype k; + + s->attack_coef = get_coef(s->attack, sample_rate); + s->release_coef = get_coef(s->release, sample_rate); + + switch (dftype) { + case 0: + k = ONE / dqfactor; + + da[0] = ONE / (ONE + dg * (dg + k)); + da[1] = dg * da[0]; + da[2] = dg * da[1]; + + dm[0] = ZERO; + dm[1] = k; + dm[2] = ZERO; + break; + case 1: + k = ONE / dqfactor; + + da[0] = ONE / (ONE + dg * (dg + k)); + da[1] = dg * da[0]; + da[2] = dg * da[1]; + + dm[0] = ZERO; + dm[1] = ZERO; + dm[2] = ONE; + break; + case 2: + k = ONE / dqfactor; + + da[0] = ONE / (ONE + dg * (dg + k)); + da[1] = dg * da[0]; + da[2] = dg * da[1]; + + dm[0] = ZERO; + dm[1] = -k; + dm[2] = -ONE; + break; + case 3: + k = ONE / dqfactor; + + da[0] = ONE / (ONE + dg * (dg + k)); + da[1] = dg * da[0]; + da[2] = dg * da[1]; + + dm[0] = ZERO; + dm[1] = -k; + dm[2] = -TWO; + break; + } + + return 0; +} + +static int fn(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 ftype sample_rate = in->sample_rate; + const ftype makeup = s->makeup; + const ftype ratio = s->ratio; + const ftype range = s->range; + const ftype tfrequency = FMIN(s->tfrequency, sample_rate * 0.5); + const ftype release = s->release_coef; + const ftype irelease = ONE - release; + const ftype attack = s->attack_coef; + const ftype iattack = ONE - attack; + const ftype tqfactor = s->tqfactor; + const ftype itqfactor = ONE / tqfactor; + const ftype fg = TAN(M_PI * tfrequency / sample_rate); + const int start = (in->ch_layout.nb_channels * jobnr) / nb_jobs; + const int end = (in->ch_layout.nb_channels * (jobnr+1)) / nb_jobs; + const int detection = s->detection; + const int direction = s->direction; + const int tftype = s->tftype; + const int mode = s->mode; + const ftype *da = fn(s->da); + const ftype *dm = fn(s->dm); + + for (int ch = start; ch < end; ch++) { + const ftype *src = (const ftype *)in->extended_data[ch]; + ftype *dst = (ftype *)out->extended_data[ch]; + ftype *state = (ftype *)s->state->extended_data[ch]; + const ftype threshold = detection == 0 ? state[5] : s->threshold; + + if (detection < 0) + state[5] = threshold; + + for (int n = 0; n < out->nb_samples; n++) { + ftype detect, gain, v, listen; + ftype fa[3], fm[3]; + ftype k, g; + + detect = listen = fn(get_svf)(src[n], dm, da, state); + detect = FABS(detect); + + if (detection > 0) + state[5] = FMAX(state[5], detect); + + if (direction == 0) { + if (detect < threshold) { + if (mode == 0) + detect = ONE / CLIP(ONE + makeup + (threshold - detect) * ratio, ONE, range); + else + detect = CLIP(ONE + makeup + (threshold - detect) * ratio, ONE, range); + } else { + detect = ONE; + } + } else { + if (detect > threshold) { + if (mode == 0) + detect = ONE / CLIP(ONE + makeup + (detect - threshold) * ratio, ONE, range); + else + detect = CLIP(ONE + makeup + (detect - threshold) * ratio, ONE, range); + } else { + detect = ONE; + } + } + + if (direction == 0) { + if (detect > state[4]) { + detect = iattack * detect + attack * state[4]; + } else { + detect = irelease * detect + release * state[4]; + } + } else { + if (detect < state[4]) { + detect = iattack * detect + attack * state[4]; + } else { + detect = irelease * detect + release * state[4]; + } + } + + if (state[4] != detect || n == 0) { + state[4] = gain = detect; + + switch (tftype) { + case 0: + k = ONE / (tqfactor * gain); + + fa[0] = ONE / (ONE + fg * (fg + k)); + fa[1] = fg * fa[0]; + fa[2] = fg * fa[1]; + + fm[0] = ONE; + fm[1] = k * (gain * gain - ONE); + fm[2] = ZERO; + break; + case 1: + k = itqfactor; + g = fg / SQRT(gain); + + fa[0] = ONE / (ONE + g * (g + k)); + fa[1] = g * fa[0]; + fa[2] = g * fa[1]; + + fm[0] = ONE; + fm[1] = k * (gain - ONE); + fm[2] = gain * gain - ONE; + break; + case 2: + k = itqfactor; + g = fg / SQRT(gain); + + fa[0] = ONE / (ONE + g * (g + k)); + fa[1] = g * fa[0]; + fa[2] = g * fa[1]; + + fm[0] = gain * gain; + fm[1] = k * (ONE - gain) * gain; + fm[2] = ONE - gain * gain; + break; + } + } + + v = fn(get_svf)(src[n], fm, fa, &state[2]); + v = mode == -1 ? listen : v; + dst[n] = ctx->is_disabled ? src[n] : v; + } + } + + return 0; +} + + diff --git a/libavfilter/af_adynamicequalizer.c b/libavfilter/af_adynamicequalizer.c index e741b55eada..a3aeee91c5a 100644 --- a/libavfilter/af_adynamicequalizer.c +++ b/libavfilter/af_adynamicequalizer.c @@ -43,242 +43,82 @@ typedef struct AudioDynamicEqualizerContext { int detection; int tftype; int dftype; + int precision; + int format; + + int (*filter_prepare)(AVFilterContext *ctx); + int (*filter_channels)(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs); + + double da_double[3], dm_double[3]; + float da_float[3], dm_float[3]; - double da[3], dm[3]; AVFrame *state; } AudioDynamicEqualizerContext; -static int config_input(AVFilterLink *inlink) +static int query_formats(AVFilterContext *ctx) { - AVFilterContext *ctx = inlink->dst; AudioDynamicEqualizerContext *s = ctx->priv; + static const enum AVSampleFormat sample_fmts[3][3] = { + { AV_SAMPLE_FMT_FLTP, AV_SAMPLE_FMT_DBLP, AV_SAMPLE_FMT_NONE }, + { AV_SAMPLE_FMT_FLTP, AV_SAMPLE_FMT_NONE }, + { AV_SAMPLE_FMT_DBLP, AV_SAMPLE_FMT_NONE }, + }; + int ret; - s->state = ff_get_audio_buffer(inlink, 8); - if (!s->state) - return AVERROR(ENOMEM); - - for (int ch = 0; ch < inlink->ch_layout.nb_channels; ch++) { - double *state = (double *)s->state->extended_data[ch]; + if ((ret = ff_set_common_all_channel_counts(ctx)) < 0) + return ret; - state[4] = 1.; - } + if ((ret = ff_set_common_formats_from_list(ctx, sample_fmts[s->precision])) < 0) + return ret; - return 0; + return ff_set_common_all_samplerates(ctx); } -static double get_svf(double in, const double *m, const double *a, double *b) +static double get_coef(double x, double sr) { - 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; + return exp(-1000. / (x * sr)); } typedef struct ThreadData { AVFrame *in, *out; } ThreadData; -static double get_coef(double x, double sr) -{ - return exp(-1000. / (x * sr)); -} +#define DEPTH 32 +#include "adynamicequalizer_template.c" -static int filter_prepare(AVFilterContext *ctx) +#undef DEPTH +#define DEPTH 64 +#include "adynamicequalizer_template.c" + +static int config_input(AVFilterLink *inlink) { + AVFilterContext *ctx = inlink->dst; AudioDynamicEqualizerContext *s = ctx->priv; - const double sample_rate = ctx->inputs[0]->sample_rate; - const double dfrequency = fmin(s->dfrequency, sample_rate * 0.5); - const double dg = tan(M_PI * dfrequency / sample_rate); - const double dqfactor = s->dqfactor; - const int dftype = s->dftype; - double *da = s->da; - double *dm = s->dm; - double k; - - s->attack_coef = get_coef(s->attack, sample_rate); - s->release_coef = get_coef(s->release, sample_rate); - - switch (dftype) { - case 0: - 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] = k; - dm[2] = 0.; - break; - case 1: - 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] = 0.; - dm[2] = 1.; - break; - case 2: - 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] = -k; - dm[2] = -1.; - break; - case 3: - k = 1. / dqfactor; + s->format = inlink->format; + s->state = ff_get_audio_buffer(inlink, 8); + if (!s->state) + return AVERROR(ENOMEM); - da[0] = 1. / (1. + dg * (dg + k)); - da[1] = dg * da[0]; - da[2] = dg * da[1]; + switch (s->format) { + case AV_SAMPLE_FMT_DBLP: + for (int ch = 0; ch < inlink->ch_layout.nb_channels; ch++) { + double *state = (double *)s->state->extended_data[ch]; - dm[0] = 0.; - dm[1] = -k; - dm[2] = -2.; + state[4] = 1.; + } + s->filter_prepare = filter_prepare_double; + s->filter_channels = filter_channels_double; break; - } - - return 0; -} + case AV_SAMPLE_FMT_FLTP: + for (int ch = 0; ch < inlink->ch_layout.nb_channels; ch++) { + float *state = (float *)s->state->extended_data[ch]; -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 ratio = s->ratio; - const double range = s->range; - const double tfrequency = fmin(s->tfrequency, sample_rate * 0.5); - const double release = s->release_coef; - const double irelease = 1. - release; - const double attack = s->attack_coef; - const double iattack = 1. - attack; - const double tqfactor = s->tqfactor; - const double fg = tan(M_PI * tfrequency / sample_rate); - const int start = (in->ch_layout.nb_channels * jobnr) / nb_jobs; - const int end = (in->ch_layout.nb_channels * (jobnr+1)) / nb_jobs; - const int detection = s->detection; - const int direction = s->direction; - const int tftype = s->tftype; - const int mode = s->mode; - const double *da = s->da; - const double *dm = s->dm; - - 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]; - const double threshold = detection == 0 ? state[5] : s->threshold; - - if (detection < 0) - state[5] = threshold; - - for (int n = 0; n < out->nb_samples; n++) { - double detect, gain, v, listen; - double fa[3], fm[3]; - double k, g; - - detect = listen = get_svf(src[n], dm, da, state); - detect = fabs(detect); - - if (detection > 0) - state[5] = fmax(state[5], detect); - - if (direction == 0) { - if (detect < threshold) { - if (mode == 0) - detect = 1. / av_clipd(1. + makeup + (threshold - detect) * ratio, 1., range); - else - detect = av_clipd(1. + makeup + (threshold - detect) * ratio, 1., range); - } else { - detect = 1.; - } - } else { - if (detect > threshold) { - if (mode == 0) - detect = 1. / av_clipd(1. + makeup + (detect - threshold) * ratio, 1., range); - else - detect = av_clipd(1. + makeup + (detect - threshold) * ratio, 1., range); - } else { - detect = 1.; - } - } - - if (direction == 0) { - if (detect > state[4]) { - detect = iattack * detect + attack * state[4]; - } else { - detect = irelease * detect + release * state[4]; - } - } else { - if (detect < state[4]) { - detect = iattack * detect + attack * state[4]; - } else { - detect = irelease * detect + release * state[4]; - } - } - - if (state[4] != detect || n == 0) { - state[4] = gain = detect; - - switch (tftype) { - case 0: - 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.; - break; - case 1: - k = 1. / tqfactor; - g = fg / sqrt(gain); - - fa[0] = 1. / (1. + g * (g + k)); - fa[1] = g * fa[0]; - fa[2] = g * fa[1]; - - fm[0] = 1.; - fm[1] = k * (gain - 1.); - fm[2] = gain * gain - 1.; - break; - case 2: - k = 1. / tqfactor; - g = fg / sqrt(gain); - - fa[0] = 1. / (1. + g * (g + k)); - fa[1] = g * fa[0]; - fa[2] = g * fa[1]; - - fm[0] = gain * gain; - fm[1] = k * (1. - gain) * gain; - fm[2] = 1. - gain * gain; - break; - } - } - - v = get_svf(src[n], fm, fa, &state[2]); - v = mode == -1 ? listen : v; - dst[n] = ctx->is_disabled ? src[n] : v; + state[4] = 1.; } + s->filter_prepare = filter_prepare_float; + s->filter_channels = filter_channels_float; + break; } return 0; @@ -288,6 +128,7 @@ 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; @@ -304,8 +145,8 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in) td.in = in; td.out = out; - filter_prepare(ctx); - ff_filter_execute(ctx, filter_channels, &td, NULL, + s->filter_prepare(ctx); + ff_filter_execute(ctx, s->filter_channels, &td, NULL, FFMIN(outlink->ch_layout.nb_channels, ff_filter_get_nb_threads(ctx))); if (out != in) @@ -321,6 +162,7 @@ static av_cold void uninit(AVFilterContext *ctx) } #define OFFSET(x) offsetof(AudioDynamicEqualizerContext, x) +#define AF AV_OPT_FLAG_AUDIO_PARAM|AV_OPT_FLAG_FILTERING_PARAM #define FLAGS AV_OPT_FLAG_AUDIO_PARAM|AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_RUNTIME_PARAM static const AVOption adynamicequalizer_options[] = { @@ -354,6 +196,10 @@ static const AVOption adynamicequalizer_options[] = { { "disabled", 0, 0, AV_OPT_TYPE_CONST, {.i64=-1}, 0, 0, FLAGS, "auto" }, { "off", 0, 0, AV_OPT_TYPE_CONST, {.i64=0}, 0, 0, FLAGS, "auto" }, { "on", 0, 0, AV_OPT_TYPE_CONST, {.i64=1}, 0, 0, FLAGS, "auto" }, + { "precision", "set processing precision", OFFSET(precision), AV_OPT_TYPE_INT, {.i64=0}, 0, 2, AF, "precision" }, + { "auto", "set auto processing precision", 0, AV_OPT_TYPE_CONST, {.i64=0}, 0, 0, AF, "precision" }, + { "float", "set single-floating point processing precision", 0, AV_OPT_TYPE_CONST, {.i64=1}, 0, 0, AF, "precision" }, + { "double","set double-floating point processing precision", 0, AV_OPT_TYPE_CONST, {.i64=2}, 0, 0, AF, "precision" }, { NULL } }; @@ -383,7 +229,7 @@ const AVFilter ff_af_adynamicequalizer = { .uninit = uninit, FILTER_INPUTS(inputs), FILTER_OUTPUTS(outputs), - FILTER_SINGLE_SAMPLEFMT(AV_SAMPLE_FMT_DBLP), + FILTER_QUERY_FUNC(query_formats), .flags = AVFILTER_FLAG_SUPPORT_TIMELINE_INTERNAL | AVFILTER_FLAG_SLICE_THREADS, .process_command = ff_filter_process_command, From a2f4adf6803534b30283d72ddd2056e94952f387 Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Sun, 16 Apr 2023 18:53:07 +0200 Subject: [PATCH 0819/2172] avfilter: add arls filter --- Changelog | 1 + doc/filters.texi | 38 +++++ libavfilter/Makefile | 1 + libavfilter/af_arls.c | 353 +++++++++++++++++++++++++++++++++++++++ libavfilter/allfilters.c | 1 + libavfilter/version.h | 2 +- 6 files changed, 395 insertions(+), 1 deletion(-) create mode 100644 libavfilter/af_arls.c diff --git a/Changelog b/Changelog index b6f6682904f..4901ef6ad71 100644 --- a/Changelog +++ b/Changelog @@ -6,6 +6,7 @@ version : - Playdate video decoder and demuxer - Extend VAAPI support for libva-win32 on Windows - afireqsrc audio source filter +- arls filter version 6.0: - Radiance HDR image support diff --git a/doc/filters.texi b/doc/filters.texi index f89b1d0b520..6d2672063c1 100644 --- a/doc/filters.texi +++ b/doc/filters.texi @@ -2975,6 +2975,44 @@ atrim=end=5,areverse @end example @end itemize +@section arls +Apply Recursive Least Squares algorithm to the first audio stream using the second audio stream. + +This adaptive filter is used to mimic a desired filter by recursively finding the filter coefficients that +relate to producing the minimal weighted linear least squares cost function of the error signal (difference +between the desired, 2nd input audio stream and the actual signal, the 1st input audio stream). + +A description of the accepted options follows. + +@table @option +@item order +Set the filter order. + +@item lambda +Set the forgetting factor. + +@item delta +Set the coefficient to initialize internal covariance matrix. + +@item out_mode +Set the filter output samples. It accepts the following values: +@table @option +@item i +Pass the 1st input. + +@item d +Pass the 2nd input. + +@item o +Pass filtered samples. + +@item n +Pass difference between desired and filtered samples. + +Default value is @var{o}. +@end table +@end table + @section arnndn Reduce noise from speech using Recurrent Neural Networks. diff --git a/libavfilter/Makefile b/libavfilter/Makefile index 70bfc78c321..482aeaff4bf 100644 --- a/libavfilter/Makefile +++ b/libavfilter/Makefile @@ -88,6 +88,7 @@ OBJS-$(CONFIG_APULSATOR_FILTER) += af_apulsator.o OBJS-$(CONFIG_AREALTIME_FILTER) += f_realtime.o OBJS-$(CONFIG_ARESAMPLE_FILTER) += af_aresample.o OBJS-$(CONFIG_AREVERSE_FILTER) += f_reverse.o +OBJS-$(CONFIG_ARLS_FILTER) += af_arls.o OBJS-$(CONFIG_ARNNDN_FILTER) += af_arnndn.o OBJS-$(CONFIG_ASDR_FILTER) += af_asdr.o OBJS-$(CONFIG_ASEGMENT_FILTER) += f_segment.o diff --git a/libavfilter/af_arls.c b/libavfilter/af_arls.c new file mode 100644 index 00000000000..1d91954c028 --- /dev/null +++ b/libavfilter/af_arls.c @@ -0,0 +1,353 @@ +/* + * Copyright (c) 2023 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 "libavutil/common.h" +#include "libavutil/float_dsp.h" +#include "libavutil/opt.h" + +#include "audio.h" +#include "avfilter.h" +#include "formats.h" +#include "filters.h" +#include "internal.h" + +enum OutModes { + IN_MODE, + DESIRED_MODE, + OUT_MODE, + NOISE_MODE, + NB_OMODES +}; + +typedef struct AudioRLSContext { + const AVClass *class; + + int order; + float lambda; + float delta; + int output_mode; + + int kernel_size; + AVFrame *offset; + AVFrame *delay; + AVFrame *coeffs; + AVFrame *p, *dp; + AVFrame *gains; + AVFrame *u, *tmp; + + AVFrame *frame[2]; + + AVFloatDSPContext *fdsp; +} AudioRLSContext; + +#define OFFSET(x) offsetof(AudioRLSContext, x) +#define A AV_OPT_FLAG_AUDIO_PARAM|AV_OPT_FLAG_FILTERING_PARAM +#define AT AV_OPT_FLAG_AUDIO_PARAM|AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_RUNTIME_PARAM + +static const AVOption arls_options[] = { + { "order", "set the filter order", OFFSET(order), AV_OPT_TYPE_INT, {.i64=16}, 1, INT16_MAX, A }, + { "lambda", "set the filter lambda", OFFSET(lambda), AV_OPT_TYPE_FLOAT, {.dbl=1.f}, 0, 1, AT }, + { "delta", "set the filter delta", OFFSET(delta), AV_OPT_TYPE_FLOAT, {.dbl=2.f}, 0, INT16_MAX, A }, + { "out_mode", "set output mode", OFFSET(output_mode), AV_OPT_TYPE_INT, {.i64=OUT_MODE}, 0, NB_OMODES-1, AT, "mode" }, + { "i", "input", 0, AV_OPT_TYPE_CONST, {.i64=IN_MODE}, 0, 0, AT, "mode" }, + { "d", "desired", 0, AV_OPT_TYPE_CONST, {.i64=DESIRED_MODE}, 0, 0, AT, "mode" }, + { "o", "output", 0, AV_OPT_TYPE_CONST, {.i64=OUT_MODE}, 0, 0, AT, "mode" }, + { "n", "noise", 0, AV_OPT_TYPE_CONST, {.i64=NOISE_MODE}, 0, 0, AT, "mode" }, + { NULL } +}; + +AVFILTER_DEFINE_CLASS(arls); + +static float fir_sample(AudioRLSContext *s, float sample, float *delay, + float *coeffs, float *tmp, int *offset) +{ + const int order = s->order; + float output; + + delay[*offset] = sample; + + memcpy(tmp, coeffs + order - *offset, order * sizeof(float)); + + output = s->fdsp->scalarproduct_float(delay, tmp, s->kernel_size); + + if (--(*offset) < 0) + *offset = order - 1; + + return output; +} + +static float process_sample(AudioRLSContext *s, float input, float desired, int ch) +{ + float *coeffs = (float *)s->coeffs->extended_data[ch]; + float *delay = (float *)s->delay->extended_data[ch]; + float *gains = (float *)s->gains->extended_data[ch]; + float *tmp = (float *)s->tmp->extended_data[ch]; + float *u = (float *)s->u->extended_data[ch]; + float *p = (float *)s->p->extended_data[ch]; + float *dp = (float *)s->dp->extended_data[ch]; + int *offsetp = (int *)s->offset->extended_data[ch]; + const int kernel_size = s->kernel_size; + const int order = s->order; + const float lambda = s->lambda; + int offset = *offsetp; + float g = lambda; + float output, e; + + delay[offset + order] = input; + + output = fir_sample(s, input, delay, coeffs, tmp, offsetp); + e = desired - output; + + for (int i = 0, pos = offset; i < order; i++, pos++) { + const int ikernel_size = i * kernel_size; + + u[i] = 0.f; + for (int k = 0, pos = offset; k < order; k++, pos++) + u[i] += p[ikernel_size + k] * delay[pos]; + + g += u[i] * delay[pos]; + } + + g = 1.f / g; + + for (int i = 0; i < order; i++) { + const int ikernel_size = i * kernel_size; + + gains[i] = u[i] * g; + coeffs[i] = coeffs[order + i] = coeffs[i] + gains[i] * e; + tmp[i] = 0.f; + for (int k = 0, pos = offset; k < order; k++, pos++) + tmp[i] += p[ikernel_size + k] * delay[pos]; + } + + for (int i = 0; i < order; i++) { + const int ikernel_size = i * kernel_size; + + for (int k = 0; k < order; k++) + dp[ikernel_size + k] = gains[i] * tmp[k]; + } + + for (int i = 0; i < order; i++) { + const int ikernel_size = i * kernel_size; + + for (int k = 0; k < order; k++) + p[ikernel_size + k] = (p[ikernel_size + k] - (dp[ikernel_size + k] + dp[kernel_size * k + i]) * 0.5f) * lambda; + } + + switch (s->output_mode) { + case IN_MODE: output = input; break; + case DESIRED_MODE: output = desired; break; + case OUT_MODE: output = desired - output; break; + case NOISE_MODE: output = input - output; break; + } + return output; +} + +static int process_channels(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) +{ + AudioRLSContext *s = ctx->priv; + AVFrame *out = arg; + const int start = (out->ch_layout.nb_channels * jobnr) / nb_jobs; + const int end = (out->ch_layout.nb_channels * (jobnr+1)) / nb_jobs; + + for (int c = start; c < end; c++) { + const float *input = (const float *)s->frame[0]->extended_data[c]; + const float *desired = (const float *)s->frame[1]->extended_data[c]; + float *output = (float *)out->extended_data[c]; + + for (int n = 0; n < out->nb_samples; n++) { + output[n] = process_sample(s, input[n], desired[n], c); + if (ctx->is_disabled) + output[n] = input[n]; + } + } + + return 0; +} + +static int activate(AVFilterContext *ctx) +{ + AudioRLSContext *s = ctx->priv; + int i, ret, status; + int nb_samples; + int64_t pts; + + FF_FILTER_FORWARD_STATUS_BACK_ALL(ctx->outputs[0], ctx); + + nb_samples = FFMIN(ff_inlink_queued_samples(ctx->inputs[0]), + ff_inlink_queued_samples(ctx->inputs[1])); + for (i = 0; i < ctx->nb_inputs && nb_samples > 0; i++) { + if (s->frame[i]) + continue; + + if (ff_inlink_check_available_samples(ctx->inputs[i], nb_samples) > 0) { + ret = ff_inlink_consume_samples(ctx->inputs[i], nb_samples, nb_samples, &s->frame[i]); + if (ret < 0) + return ret; + } + } + + if (s->frame[0] && s->frame[1]) { + AVFrame *out; + + out = ff_get_audio_buffer(ctx->outputs[0], s->frame[0]->nb_samples); + if (!out) { + av_frame_free(&s->frame[0]); + av_frame_free(&s->frame[1]); + return AVERROR(ENOMEM); + } + + ff_filter_execute(ctx, process_channels, out, NULL, + FFMIN(ctx->outputs[0]->ch_layout.nb_channels, ff_filter_get_nb_threads(ctx))); + + out->pts = s->frame[0]->pts; + + av_frame_free(&s->frame[0]); + av_frame_free(&s->frame[1]); + + ret = ff_filter_frame(ctx->outputs[0], out); + if (ret < 0) + return ret; + } + + if (!nb_samples) { + for (i = 0; i < 2; i++) { + if (ff_inlink_acknowledge_status(ctx->inputs[i], &status, &pts)) { + ff_outlink_set_status(ctx->outputs[0], status, pts); + return 0; + } + } + } + + if (ff_outlink_frame_wanted(ctx->outputs[0])) { + for (i = 0; i < 2; i++) { + if (ff_inlink_queued_samples(ctx->inputs[i]) > 0) + continue; + ff_inlink_request_frame(ctx->inputs[i]); + return 0; + } + } + return 0; +} + +static int config_output(AVFilterLink *outlink) +{ + AVFilterContext *ctx = outlink->src; + AudioRLSContext *s = ctx->priv; + + s->kernel_size = FFALIGN(s->order, 16); + + if (!s->offset) + s->offset = ff_get_audio_buffer(outlink, 1); + if (!s->delay) + s->delay = ff_get_audio_buffer(outlink, 2 * s->kernel_size); + if (!s->coeffs) + s->coeffs = ff_get_audio_buffer(outlink, 2 * s->kernel_size); + if (!s->gains) + s->gains = ff_get_audio_buffer(outlink, s->kernel_size); + if (!s->p) + s->p = ff_get_audio_buffer(outlink, s->kernel_size * s->kernel_size); + if (!s->dp) + s->dp = ff_get_audio_buffer(outlink, s->kernel_size * s->kernel_size); + if (!s->u) + s->u = ff_get_audio_buffer(outlink, s->kernel_size); + if (!s->tmp) + s->tmp = ff_get_audio_buffer(outlink, s->kernel_size); + + if (!s->delay || !s->coeffs || !s->p || !s->dp || !s->gains || !s->offset || !s->u || !s->tmp) + return AVERROR(ENOMEM); + + for (int ch = 0; ch < s->offset->ch_layout.nb_channels; ch++) { + int *dst = (int *)s->offset->extended_data[ch]; + + for (int i = 0; i < s->kernel_size; i++) + dst[0] = s->kernel_size - 1; + } + + for (int ch = 0; ch < s->p->ch_layout.nb_channels; ch++) { + float *dst = (float *)s->p->extended_data[ch]; + + for (int i = 0; i < s->kernel_size; i++) + dst[i * s->kernel_size + i] = s->delta; + } + + return 0; +} + +static av_cold int init(AVFilterContext *ctx) +{ + AudioRLSContext *s = ctx->priv; + + s->fdsp = avpriv_float_dsp_alloc(0); + if (!s->fdsp) + return AVERROR(ENOMEM); + + return 0; +} + +static av_cold void uninit(AVFilterContext *ctx) +{ + AudioRLSContext *s = ctx->priv; + + av_freep(&s->fdsp); + av_frame_free(&s->delay); + av_frame_free(&s->coeffs); + av_frame_free(&s->gains); + av_frame_free(&s->offset); + av_frame_free(&s->p); + av_frame_free(&s->dp); + av_frame_free(&s->u); + av_frame_free(&s->tmp); +} + +static const AVFilterPad inputs[] = { + { + .name = "input", + .type = AVMEDIA_TYPE_AUDIO, + }, + { + .name = "desired", + .type = AVMEDIA_TYPE_AUDIO, + }, +}; + +static const AVFilterPad outputs[] = { + { + .name = "default", + .type = AVMEDIA_TYPE_AUDIO, + .config_props = config_output, + }, +}; + +const AVFilter ff_af_arls = { + .name = "arls", + .description = NULL_IF_CONFIG_SMALL("Apply Recursive Least Squares algorithm to first audio stream."), + .priv_size = sizeof(AudioRLSContext), + .priv_class = &arls_class, + .init = init, + .uninit = uninit, + .activate = activate, + FILTER_INPUTS(inputs), + FILTER_OUTPUTS(outputs), + FILTER_SINGLE_SAMPLEFMT(AV_SAMPLE_FMT_FLTP), + .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 fd353ff2cc7..6994124ce86 100644 --- a/libavfilter/allfilters.c +++ b/libavfilter/allfilters.c @@ -75,6 +75,7 @@ extern const AVFilter ff_af_apulsator; extern const AVFilter ff_af_arealtime; extern const AVFilter ff_af_aresample; extern const AVFilter ff_af_areverse; +extern const AVFilter ff_af_arls; extern const AVFilter ff_af_arnndn; extern const AVFilter ff_af_asdr; extern const AVFilter ff_af_asegment; diff --git a/libavfilter/version.h b/libavfilter/version.h index f191d98883f..00508741084 100644 --- a/libavfilter/version.h +++ b/libavfilter/version.h @@ -31,7 +31,7 @@ #include "version_major.h" -#define LIBAVFILTER_VERSION_MINOR 6 +#define LIBAVFILTER_VERSION_MINOR 7 #define LIBAVFILTER_VERSION_MICRO 100 From a47bd6d3d896038f265b9ff6fb4f5f3a8ef8b0fc Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Sun, 30 Apr 2023 12:16:02 +0200 Subject: [PATCH 0820/2172] avfilter/af_asdr: set output frame duration --- libavfilter/af_asdr.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/libavfilter/af_asdr.c b/libavfilter/af_asdr.c index a40246f2802..14bc0097afc 100644 --- a/libavfilter/af_asdr.c +++ b/libavfilter/af_asdr.c @@ -60,11 +60,12 @@ static void sdr(AVFilterContext *ctx, const AVFrame *u, const AVFrame *v) static int activate(AVFilterContext *ctx) { AudioSDRContext *s = ctx->priv; + AVFilterLink *outlink = ctx->outputs[0]; int ret, status; int available; int64_t pts; - FF_FILTER_FORWARD_STATUS_BACK_ALL(ctx->outputs[0], ctx); + FF_FILTER_FORWARD_STATUS_BACK_ALL(outlink, ctx); available = FFMIN(ff_inlink_queued_samples(ctx->inputs[0]), ff_inlink_queued_samples(ctx->inputs[1])); if (available > 0) { @@ -83,21 +84,22 @@ static int activate(AVFilterContext *ctx) av_frame_free(&s->cache[1]); out = s->cache[0]; out->nb_samples = available; - out->pts = s->pts; + out->pts = av_rescale_q(s->pts, av_make_q(1, outlink->sample_rate), outlink->time_base); + out->duration = av_rescale_q(out->nb_samples, av_make_q(1, outlink->sample_rate), outlink->time_base); s->pts += available; s->cache[0] = NULL; - return ff_filter_frame(ctx->outputs[0], out); + return ff_filter_frame(outlink, out); } for (int i = 0; i < 2; i++) { if (ff_inlink_acknowledge_status(ctx->inputs[i], &status, &pts)) { - ff_outlink_set_status(ctx->outputs[0], status, s->pts); + ff_outlink_set_status(outlink, status, s->pts); return 0; } } - if (ff_outlink_frame_wanted(ctx->outputs[0])) { + if (ff_outlink_frame_wanted(outlink)) { for (int i = 0; i < 2; i++) { if (ff_inlink_queued_samples(ctx->inputs[i]) > 0) continue; From 4f63e049a2358cc9a22c2344810eff389aa78d85 Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Sun, 30 Apr 2023 12:18:16 +0200 Subject: [PATCH 0821/2172] avfilter/af_asdr: add timeline support --- libavfilter/af_asdr.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/libavfilter/af_asdr.c b/libavfilter/af_asdr.c index 14bc0097afc..5c7e2bbfe46 100644 --- a/libavfilter/af_asdr.c +++ b/libavfilter/af_asdr.c @@ -79,7 +79,8 @@ static int activate(AVFilterContext *ctx) } } - sdr(ctx, s->cache[0], s->cache[1]); + if (!ctx->is_disabled) + sdr(ctx, s->cache[0], s->cache[1]); av_frame_free(&s->cache[1]); out = s->cache[0]; @@ -168,7 +169,8 @@ const AVFilter ff_af_asdr = { .priv_size = sizeof(AudioSDRContext), .activate = activate, .uninit = uninit, - .flags = AVFILTER_FLAG_METADATA_ONLY, + .flags = AVFILTER_FLAG_METADATA_ONLY | + AVFILTER_FLAG_SUPPORT_TIMELINE_INTERNAL, FILTER_INPUTS(inputs), FILTER_OUTPUTS(outputs), FILTER_SINGLE_SAMPLEFMT(AV_SAMPLE_FMT_DBLP), From 7b2851b290f12cc8a1c8110b64bc5d364109873b Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Sun, 30 Apr 2023 12:32:37 +0200 Subject: [PATCH 0822/2172] avfilter/af_asdr: add support for threads --- libavfilter/af_asdr.c | 28 +++++++++++++++++++--------- 1 file changed, 19 insertions(+), 9 deletions(-) diff --git a/libavfilter/af_asdr.c b/libavfilter/af_asdr.c index 5c7e2bbfe46..96aa80f8434 100644 --- a/libavfilter/af_asdr.c +++ b/libavfilter/af_asdr.c @@ -37,24 +37,32 @@ typedef struct AudioSDRContext { AVFrame *cache[2]; } AudioSDRContext; -static void sdr(AVFilterContext *ctx, const AVFrame *u, const AVFrame *v) +static int sdr(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) { AudioSDRContext *s = ctx->priv; - - for (int ch = 0; ch < u->ch_layout.nb_channels; ch++) { + AVFrame *u = s->cache[0]; + AVFrame *v = s->cache[1]; + const int channels = u->ch_layout.nb_channels; + const int start = (channels * jobnr) / nb_jobs; + const int end = (channels * (jobnr+1)) / nb_jobs; + const int nb_samples = u->nb_samples; + + for (int ch = start; ch < end; ch++) { const double *const us = (double *)u->extended_data[ch]; const double *const vs = (double *)v->extended_data[ch]; - double sum_uv = s->sum_uv[ch]; - double sum_u = s->sum_u[ch]; + double sum_uv = 0.; + double sum_u = 0.; - for (int n = 0; n < u->nb_samples; n++) { + for (int n = 0; n < nb_samples; n++) { sum_u += us[n] * us[n]; sum_uv += (us[n] - vs[n]) * (us[n] - vs[n]); } - s->sum_uv[ch] = sum_uv; - s->sum_u[ch] = sum_u; + s->sum_uv[ch] += sum_uv; + s->sum_u[ch] += sum_u; } + + return 0; } static int activate(AVFilterContext *ctx) @@ -80,7 +88,8 @@ static int activate(AVFilterContext *ctx) } if (!ctx->is_disabled) - sdr(ctx, s->cache[0], s->cache[1]); + ff_filter_execute(ctx, sdr, NULL, NULL, + FFMIN(outlink->ch_layout.nb_channels, ff_filter_get_nb_threads(ctx))); av_frame_free(&s->cache[1]); out = s->cache[0]; @@ -170,6 +179,7 @@ const AVFilter ff_af_asdr = { .activate = activate, .uninit = uninit, .flags = AVFILTER_FLAG_METADATA_ONLY | + AVFILTER_FLAG_SLICE_THREADS | AVFILTER_FLAG_SUPPORT_TIMELINE_INTERNAL, FILTER_INPUTS(inputs), FILTER_OUTPUTS(outputs), From 0275d994271ded88b3bf31b6d24686ecbc0e750d Mon Sep 17 00:00:00 2001 From: James Almer Date: Thu, 27 Apr 2023 12:23:53 -0300 Subject: [PATCH 0823/2172] avcodec/parser: fill avctx dimensions if unset This allows the usage of codecs in builds that have a parser but no decoders for remuxing scenarios with raw sources. Signed-off-by: James Almer --- libavcodec/parser.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/libavcodec/parser.c b/libavcodec/parser.c index 49de7e6a57a..efc28b89183 100644 --- a/libavcodec/parser.c +++ b/libavcodec/parser.c @@ -166,6 +166,10 @@ int av_parser_parse2(AVCodecParserContext *s, AVCodecContext *avctx, #define FILL(name) if(s->name > 0 && avctx->name <= 0) avctx->name = s->name if (avctx->codec_type == AVMEDIA_TYPE_VIDEO) { FILL(field_order); + FILL(coded_width); + FILL(coded_height); + FILL(width); + FILL(height); } /* update the file pointer */ From 45fc89bb14989a585be024faf1349806a1acbb9a Mon Sep 17 00:00:00 2001 From: James Almer Date: Sun, 30 Apr 2023 18:24:23 -0300 Subject: [PATCH 0824/2172] avcodec/hevc_ps: use get_ue_golomb() for some SPS Screen Content Coding extension fields Also remove the _minus1 part of the name to be in line with the rest of the decoder. Signed-off-by: James Almer --- libavcodec/hevc_ps.c | 21 ++++++++++++++------- libavcodec/hevc_ps.h | 2 +- libavcodec/vaapi_hevc.c | 2 +- 3 files changed, 16 insertions(+), 9 deletions(-) diff --git a/libavcodec/hevc_ps.c b/libavcodec/hevc_ps.c index 585b095073c..bba0ebd1dda 100644 --- a/libavcodec/hevc_ps.c +++ b/libavcodec/hevc_ps.c @@ -1140,17 +1140,24 @@ int ff_hevc_parse_sps(HEVCSPS *sps, GetBitContext *gb, unsigned int *sps_id, sps->sps_curr_pic_ref_enabled_flag = get_bits1(gb); sps->palette_mode_enabled_flag = get_bits1(gb); if (sps->palette_mode_enabled_flag) { - sps->palette_max_size = get_ue_golomb_long(gb); - sps->delta_palette_max_predictor_size = get_ue_golomb_long(gb); + sps->palette_max_size = get_ue_golomb(gb); + sps->delta_palette_max_predictor_size = get_ue_golomb(gb); sps->sps_palette_predictor_initializers_present_flag = get_bits1(gb); if (sps->sps_palette_predictor_initializers_present_flag) { - sps->sps_num_palette_predictor_initializers_minus1 = get_ue_golomb_long(gb); + sps->sps_num_palette_predictor_initializers = get_ue_golomb(gb) + 1; + if (sps->sps_num_palette_predictor_initializers > HEVC_MAX_PALETTE_PREDICTOR_SIZE) { + av_log(avctx, AV_LOG_ERROR, + "sps_num_palette_predictor_initializers out of range: %u\n", + sps->sps_num_palette_predictor_initializers); + return AVERROR_INVALIDDATA; + } num_comps = !sps->chroma_format_idc ? 1 : 3; - for (int comp = 0; comp < num_comps; comp++) - for (i = 0; i <= sps->sps_num_palette_predictor_initializers_minus1; i++) - sps->sps_palette_predictor_initializer[comp][i] = - get_bits(gb, !comp ? sps->bit_depth : sps->bit_depth_chroma); + for (int comp = 0; comp < num_comps; comp++) { + int bit_depth = !comp ? sps->bit_depth : sps->bit_depth_chroma; + for (i = 0; i < sps->sps_num_palette_predictor_initializers; i++) + sps->sps_palette_predictor_initializer[comp][i] = get_bits(gb, bit_depth); + } } } sps->motion_vector_resolution_control_idc = get_bits(gb, 2); diff --git a/libavcodec/hevc_ps.h b/libavcodec/hevc_ps.h index 8cd99bb1617..a0437815d60 100644 --- a/libavcodec/hevc_ps.h +++ b/libavcodec/hevc_ps.h @@ -219,7 +219,7 @@ typedef struct HEVCSPS { int palette_max_size; int delta_palette_max_predictor_size; int sps_palette_predictor_initializers_present_flag; - int sps_num_palette_predictor_initializers_minus1; + int sps_num_palette_predictor_initializers; int sps_palette_predictor_initializer[3][HEVC_MAX_PALETTE_PREDICTOR_SIZE]; int motion_vector_resolution_control_idc; int intra_boundary_filtering_disabled_flag; diff --git a/libavcodec/vaapi_hevc.c b/libavcodec/vaapi_hevc.c index 984af75c843..17c38963f82 100644 --- a/libavcodec/vaapi_hevc.c +++ b/libavcodec/vaapi_hevc.c @@ -259,7 +259,7 @@ static int vaapi_hevc_start_frame(AVCodecContext *avctx, pre_palette_size = pps->pps_palette_predictor_initializers_present_flag ? pps->pps_num_palette_predictor_initializers : (sps->sps_palette_predictor_initializers_present_flag ? - sps->sps_num_palette_predictor_initializers_minus1 + 1 : + sps->sps_num_palette_predictor_initializers : 0); if (avctx->profile == FF_PROFILE_HEVC_SCC) { From b614388056d0f48a13ac944ba990b3474707e54d Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Sun, 23 Apr 2023 23:11:32 +0200 Subject: [PATCH 0825/2172] tools/target_dec_fuzzer: Adjust threshold for FMVC Fixes: Timeout Fixes: 56753/clusterfuzz-testcase-minimized-ffmpeg_AV_CODEC_ID_FMVC_fuzzer-5115163557888000 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 93869db04c6..f059ddb4c77 100644 --- a/tools/target_dec_fuzzer.c +++ b/tools/target_dec_fuzzer.c @@ -233,6 +233,7 @@ int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { case AV_CODEC_ID_FLAC: maxsamples /= 1024; break; case AV_CODEC_ID_FLIC: maxpixels /= 1024; break; case AV_CODEC_ID_FLV1: maxpixels /= 1024; break; + case AV_CODEC_ID_FMVC: 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; From eb768a75f8a0b347ab0f84c2c68959f5dbde6d4b Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Sun, 23 Apr 2023 23:51:38 +0200 Subject: [PATCH 0826/2172] avcodec/apedec: Move pointer instead of copying each element in delay in long_filter_high_3800() ~1000 -> 930 cycles Signed-off-by: Michael Niedermayer --- libavcodec/apedec.c | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/libavcodec/apedec.c b/libavcodec/apedec.c index c08d13d6c23..40cd78a9919 100644 --- a/libavcodec/apedec.c +++ b/libavcodec/apedec.c @@ -944,7 +944,7 @@ static void long_filter_high_3800(int32_t *buffer, int order, int shift, int len { int i, j; int32_t dotprod, sign; - int32_t coeffs[256], delay[256]; + int32_t coeffs[256], delay[256+256], *delayp = delay; if (order >= length) return; @@ -956,13 +956,16 @@ static void long_filter_high_3800(int32_t *buffer, int order, int shift, int len dotprod = 0; sign = APESIGN(buffer[i]); for (j = 0; j < order; j++) { - dotprod += delay[j] * (unsigned)coeffs[j]; - coeffs[j] += ((delay[j] >> 31) | 1) * sign; + dotprod += delayp[j] * (unsigned)coeffs[j]; + coeffs[j] += ((delayp[j] >> 31) | 1) * sign; } buffer[i] -= (unsigned)(dotprod >> shift); - for (j = 0; j < order - 1; j++) - delay[j] = delay[j + 1]; - delay[order - 1] = buffer[i]; + delayp ++; + delayp[order - 1] = buffer[i]; + if (delayp - delay == 256) { + memcpy(delay, delayp, sizeof(*delay)*256); + delayp = delay; + } } } From b2a3279dbe1f1c6a2b9c36a6137281c828b5d0e4 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Sun, 23 Apr 2023 23:54:50 +0200 Subject: [PATCH 0827/2172] avcodec/apedec: Factor constant sign out of loop in long_filter_high_3800() 930 -> 850 cycles Signed-off-by: Michael Niedermayer --- libavcodec/apedec.c | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/libavcodec/apedec.c b/libavcodec/apedec.c index 40cd78a9919..772636afde3 100644 --- a/libavcodec/apedec.c +++ b/libavcodec/apedec.c @@ -955,9 +955,20 @@ static void long_filter_high_3800(int32_t *buffer, int order, int shift, int len for (i = order; i < length; i++) { dotprod = 0; sign = APESIGN(buffer[i]); - for (j = 0; j < order; j++) { - dotprod += delayp[j] * (unsigned)coeffs[j]; - coeffs[j] += ((delayp[j] >> 31) | 1) * sign; + if (sign == 1) { + for (j = 0; j < order; j++) { + dotprod += delayp[j] * (unsigned)coeffs[j]; + coeffs[j] += (delayp[j] >> 31) | 1; + } + } else if (sign == -1) { + for (j = 0; j < order; j++) { + dotprod += delayp[j] * (unsigned)coeffs[j]; + coeffs[j] -= (delayp[j] >> 31) | 1; + } + } else { + for (j = 0; j < order; j++) { + dotprod += delayp[j] * (unsigned)coeffs[j]; + } } buffer[i] -= (unsigned)(dotprod >> shift); delayp ++; From f6dffe6fc4d872b371e330447e77576ffc939220 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Mon, 24 Apr 2023 00:06:54 +0200 Subject: [PATCH 0828/2172] tools/target_dec_fuzzer: Adjust threshold for APE Fixes: Timeout Fixes: 57889/clusterfuzz-testcase-minimized-ffmpeg_AV_CODEC_ID_APE_fuzzer-5262308950802432 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 f059ddb4c77..87a9f6eb17d 100644 --- a/tools/target_dec_fuzzer.c +++ b/tools/target_dec_fuzzer.c @@ -211,6 +211,7 @@ int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { case AV_CODEC_ID_AASC: maxpixels /= 1024; break; case AV_CODEC_ID_AGM: maxpixels /= 1024; break; case AV_CODEC_ID_ANM: maxpixels /= 1024; break; + case AV_CODEC_ID_APE: maxsamples /= 16384; break; case AV_CODEC_ID_ARBC: maxpixels /= 1024; break; case AV_CODEC_ID_ARGO: maxpixels /= 1024; break; case AV_CODEC_ID_BETHSOFTVID: maxpixels /= 8192; break; From e734e165442b4bf1598b167c373928d993371f0d Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Mon, 24 Apr 2023 00:15:04 +0200 Subject: [PATCH 0829/2172] avcodec/cavsdec: Check bits left before picture allocation Fixes: Timeout Fixes: 57893/clusterfuzz-testcase-minimized-ffmpeg_AV_CODEC_ID_CAVS_fuzzer-5091726540013568 Found-by: continuous fuzzing process https://github.com/google/oss-fuzz/tree/master/projects/ffmpeg Signed-off-by: Michael Niedermayer --- libavcodec/cavsdec.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/libavcodec/cavsdec.c b/libavcodec/cavsdec.c index b1fa9a981d4..37071dfbc74 100644 --- a/libavcodec/cavsdec.c +++ b/libavcodec/cavsdec.c @@ -1020,6 +1020,9 @@ static int decode_pic(AVSContext *h) skip_bits(&h->gb, 1); //marker_bit } + if (get_bits_left(&h->gb) < 23) + return AVERROR_INVALIDDATA; + ret = ff_get_buffer(h->avctx, h->cur.f, h->cur.f->pict_type == AV_PICTURE_TYPE_B ? 0 : AV_GET_BUFFER_FLAG_REF); if (ret < 0) From 957106a24d2960e1d0359a1774b547c1292b4704 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Sat, 5 Nov 2022 19:33:33 +0100 Subject: [PATCH 0830/2172] avcodec/bonk: decode multiple passes in intlist_read() at once This makes the worst case much faster Fixes: Timeout Fixes: 51363/clusterfuzz-testcase-minimized-ffmpeg_AV_CODEC_ID_BONK_fuzzer-5660734784143360 Fixes: 57957/clusterfuzz-testcase-minimized-ffmpeg_AV_CODEC_ID_BONK_fuzzer-5874095467397120 Found-by: continuous fuzzing process https://github.com/google/oss-fuzz/tree/master/projects/ffmpeg Signed-off-by: Michael Niedermayer --- libavcodec/bonk.c | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/libavcodec/bonk.c b/libavcodec/bonk.c index 5f510e49103..4a002703929 100644 --- a/libavcodec/bonk.c +++ b/libavcodec/bonk.c @@ -155,6 +155,7 @@ static int intlist_read(BonkContext *s, int *buf, int entries, int base_2_part) int n_zeros = 0, step = 256, dominant = 0; int pos = 0, level = 0; BitCount *bits = s->bits; + int passes = 1; memset(buf, 0, entries * sizeof(*buf)); if (base_2_part) { @@ -216,24 +217,28 @@ static int intlist_read(BonkContext *s, int *buf, int entries, int base_2_part) x = 0; n_zeros = 0; for (i = 0; n_zeros < entries; i++) { + if (x >= max_x) + return AVERROR_INVALIDDATA; + if (pos >= entries) { pos = 0; - level += 1 << low_bits; + level += passes << low_bits; + passes = 1; + if (bits[x].bit && bits[x].count > entries - n_zeros) + passes = bits[x].count / (entries - n_zeros); } if (level > 1 << 16) return AVERROR_INVALIDDATA; - if (x >= max_x) - return AVERROR_INVALIDDATA; - if (buf[pos] >= level) { if (bits[x].bit) - buf[pos] += 1 << low_bits; + buf[pos] += passes << low_bits; else n_zeros++; - bits[x].count--; + av_assert1(bits[x].count >= passes); + bits[x].count -= passes; x += bits[x].count == 0; } From e2e34c7731372b65b41ddb11334ccaeba4a76f13 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Sun, 16 Apr 2023 17:51:02 +0200 Subject: [PATCH 0831/2172] avcodec/wavarc: Check order before using it to write the list Fixes: out of array access Fixes: 45982/clusterfuzz-testcase-minimized-ffmpeg_AV_CODEC_ID_WAVARC_fuzzer-6247711015043072 Fixes: 45982/clusterfuzz-testcase-minimized-ffmpeg_AV_CODEC_ID_WAVARC_fuzzer-6487578428964864 Fixes: 45982/clusterfuzz-testcase-minimized-ffmpeg_AV_CODEC_ID_WAVARC_fuzzer-6651587794960384 Fixes: 45982/clusterfuzz-testcase-minimized-ffmpeg_AV_CODEC_ID_WAVARC_fuzzer-6686265824378880 Found-by: continuous fuzzing process https://github.com/google/oss-fuzz/tree/master/projects/ffmpeg Signed-off-by: Michael Niedermayer --- libavcodec/wavarc.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/libavcodec/wavarc.c b/libavcodec/wavarc.c index 896972cec82..827803c91d0 100644 --- a/libavcodec/wavarc.c +++ b/libavcodec/wavarc.c @@ -343,6 +343,8 @@ static int decode_2slp(AVCodecContext *avctx, break; case 0: order = get_urice(gb, 2); + if ((unsigned)order >= FF_ARRAY_ELEMS(s->filter[ch])) + return AVERROR_INVALIDDATA; for (int o = 0; o < order; o++) s->filter[ch][o] = get_srice(gb, 2); for (int n = 0; n < s->nb_samples; n++) { From cb8180aa66839fe05e3a29504fb2f67336312227 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Sun, 16 Apr 2023 23:55:56 +0200 Subject: [PATCH 0832/2172] avcodec/hevc_ps: Check depth to be within 8 to 16 Fixes: assertion failure in bitreader Fixes: 45982/clusterfuzz-testcase-minimized-ffmpeg_IO_DEMUXER_fuzzer-627318668066816 Found-by: continuous fuzzing process https://github.com/google/oss-fuzz/tree/master/projects/ffmpeg Signed-off-by: Michael Niedermayer --- libavcodec/hevc_ps.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/libavcodec/hevc_ps.c b/libavcodec/hevc_ps.c index bba0ebd1dda..266adb6e863 100644 --- a/libavcodec/hevc_ps.c +++ b/libavcodec/hevc_ps.c @@ -1557,6 +1557,10 @@ static int pps_scc_extension(GetBitContext *gb, AVCodecContext *avctx, pps->luma_bit_depth_entry = get_ue_golomb_31(gb) + 8; if (!pps->monochrome_palette_flag) pps->chroma_bit_depth_entry = get_ue_golomb_31(gb) + 8; + + if (pps->chroma_bit_depth_entry > 16 || pps->chroma_bit_depth_entry > 16) + return AVERROR_INVALIDDATA; + num_comps = pps->monochrome_palette_flag ? 1 : 3; for (int comp = 0; comp < num_comps; comp++) { int bit_depth = !comp ? pps->luma_bit_depth_entry : pps->chroma_bit_depth_entry; From 69eb8197af1e1fbfbf54653da039720c061d54f6 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Tue, 25 Apr 2023 21:50:10 +0200 Subject: [PATCH 0833/2172] tools/target_dec_fuzzer: Adjust threshold for rka Fixes: Timeout Fixes: 57993/clusterfuzz-testcase-minimized-ffmpeg_AV_CODEC_ID_RKA_fuzzer-5825782785376256 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 87a9f6eb17d..d8e93f3a211 100644 --- a/tools/target_dec_fuzzer.c +++ b/tools/target_dec_fuzzer.c @@ -271,6 +271,7 @@ int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { 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_RKA: maxsamples /= 256; break; case AV_CODEC_ID_RSCC: maxpixels /= 256; break; case AV_CODEC_ID_RASC: maxpixels /= 16; break; case AV_CODEC_ID_SANM: maxpixels /= 16; break; From bf3f91c425b430b31e373e9eb5ffdaf1422132af Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Tue, 25 Apr 2023 22:50:55 +0200 Subject: [PATCH 0834/2172] avcodec/hevc_ps: Avoid signed overflow before check on QP Fixes: signed integer overflow: -2147483648 - 5 cannot be represented in type 'int' Fixes: 58066/clusterfuzz-testcase-minimized-ffmpeg_AV_CODEC_ID_HEVC_fuzzer-5312995835379712 Found-by: continuous fuzzing process https://github.com/google/oss-fuzz/tree/master/projects/ffmpeg Signed-off-by: Michael Niedermayer --- libavcodec/hevc_ps.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/libavcodec/hevc_ps.c b/libavcodec/hevc_ps.c index 266adb6e863..5b84e53ced7 100644 --- a/libavcodec/hevc_ps.c +++ b/libavcodec/hevc_ps.c @@ -1529,9 +1529,9 @@ static int pps_scc_extension(GetBitContext *gb, AVCodecContext *avctx, pps->pps_curr_pic_ref_enabled_flag = get_bits1(gb); if (pps->residual_adaptive_colour_transform_enabled_flag = get_bits1(gb)) { pps->pps_slice_act_qp_offsets_present_flag = get_bits1(gb); - pps->pps_act_y_qp_offset = get_se_golomb_long(gb) - 5; - pps->pps_act_cb_qp_offset = get_se_golomb_long(gb) - 5; - pps->pps_act_cr_qp_offset = get_se_golomb_long(gb) - 3; + pps->pps_act_y_qp_offset = get_se_golomb(gb) - 5; + pps->pps_act_cb_qp_offset = get_se_golomb(gb) - 5; + pps->pps_act_cr_qp_offset = get_se_golomb(gb) - 3; #define CHECK_QP_OFFSET(name) (pps->pps_act_ ## name ## _qp_offset <= -12 || \ pps->pps_act_ ## name ## _qp_offset >= 12) From e7c690a04692ac113e362ef81dd3cff8715c9ed2 Mon Sep 17 00:00:00 2001 From: James Almer Date: Sun, 30 Apr 2023 20:38:55 -0300 Subject: [PATCH 0835/2172] avcodec/hevc_ps: check for out of range bitdepth in SPS Signed-off-by: James Almer --- libavcodec/hevc_ps.c | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/libavcodec/hevc_ps.c b/libavcodec/hevc_ps.c index 5b84e53ced7..a55bced0f76 100644 --- a/libavcodec/hevc_ps.c +++ b/libavcodec/hevc_ps.c @@ -927,8 +927,18 @@ int ff_hevc_parse_sps(HEVCSPS *sps, GetBitContext *gb, unsigned int *sps_id, sps->output_window = sps->pic_conf_win; } - sps->bit_depth = get_ue_golomb_long(gb) + 8; - bit_depth_chroma = get_ue_golomb_long(gb) + 8; + sps->bit_depth = get_ue_golomb_31(gb) + 8; + if (sps->bit_depth > 16) { + av_log(avctx, AV_LOG_ERROR, "Luma bit depth (%d) is out of range\n", + sps->bit_depth); + return AVERROR_INVALIDDATA; + } + bit_depth_chroma = get_ue_golomb_31(gb) + 8; + if (bit_depth_chroma > 16) { + av_log(avctx, AV_LOG_ERROR, "Chroma bit depth (%d) is out of range\n", + bit_depth_chroma); + return AVERROR_INVALIDDATA; + } if (sps->chroma_format_idc && bit_depth_chroma != sps->bit_depth) { av_log(avctx, AV_LOG_ERROR, "Luma bit depth (%d) is different from chroma bit depth (%d), " From eaf15b5882995e5c88843539503fe4db14a2d60c Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Mon, 1 May 2023 14:52:52 +0200 Subject: [PATCH 0836/2172] avfilter/vf_waveform: cc2b3201e7 missed same for >8 bits --- libavfilter/vf_waveform.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libavfilter/vf_waveform.c b/libavfilter/vf_waveform.c index 37eb0679d0d..8872c43aeb3 100644 --- a/libavfilter/vf_waveform.c +++ b/libavfilter/vf_waveform.c @@ -745,7 +745,7 @@ static av_always_inline void lowpass16(WaveformContext *s, dst_data += dst_linesize * step; } - if (s->display != OVERLAY && column && !s->rgb) { + if (s->display != OVERLAY && column && !s->rgb && out->data[1] && out->data[2]) { const int mult = s->max / 256; const int bg = s->bg_color[0] * mult; const int t0 = s->tint[0]; @@ -769,7 +769,7 @@ static av_always_inline void lowpass16(WaveformContext *s, dst0 += dst_linesize; dst1 += dst_linesize; } - } else if (s->display != OVERLAY && !s->rgb) { + } else if (s->display != OVERLAY && !s->rgb && out->data[1] && out->data[2]) { const int mult = s->max / 256; const int bg = s->bg_color[0] * mult; const int t0 = s->tint[0]; From 159f8b8d716e62254595582c0723d41b1a52fdc3 Mon Sep 17 00:00:00 2001 From: James Almer Date: Mon, 1 May 2023 13:57:09 -0300 Subject: [PATCH 0837/2172] avfilter/audio: move a variable declaration outside of an unrelated deprecated block Signed-off-by: James Almer --- libavfilter/audio.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavfilter/audio.c b/libavfilter/audio.c index 4995047249b..36d5caa7e49 100644 --- a/libavfilter/audio.c +++ b/libavfilter/audio.c @@ -38,10 +38,10 @@ AVFrame *ff_default_get_audio_buffer(AVFilterLink *link, int nb_samples) { AVFrame *frame = NULL; int channels = link->ch_layout.nb_channels; + int align = av_cpu_max_align(); #if FF_API_OLD_CHANNEL_LAYOUT FF_DISABLE_DEPRECATION_WARNINGS int channel_layout_nb_channels = av_get_channel_layout_nb_channels(link->channel_layout); - int align = av_cpu_max_align(); av_assert0(channels == channel_layout_nb_channels || !channel_layout_nb_channels); FF_ENABLE_DEPRECATION_WARNINGS From f09280dfc47298e47a2e2576c8c37d1c8d4b03b2 Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Mon, 1 May 2023 19:38:17 +0200 Subject: [PATCH 0838/2172] avfilter/af_arls: improve documentation and extend option --- doc/filters.texi | 7 +++++-- libavfilter/af_arls.c | 3 +++ 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/doc/filters.texi b/doc/filters.texi index 6d2672063c1..48b321b6218 100644 --- a/doc/filters.texi +++ b/doc/filters.texi @@ -3004,10 +3004,13 @@ Pass the 1st input. Pass the 2nd input. @item o -Pass filtered samples. +Pass difference between desired, 2nd input and error signal estimate. @item n -Pass difference between desired and filtered samples. +Pass difference between input, 1st input and error signal estimate. + +@item e +Pass error signal estimated samples. Default value is @var{o}. @end table diff --git a/libavfilter/af_arls.c b/libavfilter/af_arls.c index 1d91954c028..9058a54583a 100644 --- a/libavfilter/af_arls.c +++ b/libavfilter/af_arls.c @@ -33,6 +33,7 @@ enum OutModes { DESIRED_MODE, OUT_MODE, NOISE_MODE, + ERROR_MODE, NB_OMODES }; @@ -70,6 +71,7 @@ static const AVOption arls_options[] = { { "d", "desired", 0, AV_OPT_TYPE_CONST, {.i64=DESIRED_MODE}, 0, 0, AT, "mode" }, { "o", "output", 0, AV_OPT_TYPE_CONST, {.i64=OUT_MODE}, 0, 0, AT, "mode" }, { "n", "noise", 0, AV_OPT_TYPE_CONST, {.i64=NOISE_MODE}, 0, 0, AT, "mode" }, + { "e", "error", 0, AV_OPT_TYPE_CONST, {.i64=ERROR_MODE}, 0, 0, AT, "mode" }, { NULL } }; @@ -156,6 +158,7 @@ static float process_sample(AudioRLSContext *s, float input, float desired, int case DESIRED_MODE: output = desired; break; case OUT_MODE: output = desired - output; break; case NOISE_MODE: output = input - output; break; + case ERROR_MODE: break; } return output; } From 561746591660b456e092324f03d393d6dd9147b1 Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Mon, 1 May 2023 20:01:50 +0200 Subject: [PATCH 0839/2172] avfilter/af_anlms: improve documentation and extend option --- doc/filters.texi | 7 +++++-- libavfilter/af_anlms.c | 11 +++++++---- 2 files changed, 12 insertions(+), 6 deletions(-) diff --git a/doc/filters.texi b/doc/filters.texi index 48b321b6218..a63304ccd9f 100644 --- a/doc/filters.texi +++ b/doc/filters.texi @@ -2674,10 +2674,13 @@ Pass the 1st input. Pass the 2nd input. @item o -Pass filtered samples. +Pass difference between desired, 2nd input and error signal estimate. @item n -Pass difference between desired and filtered samples. +Pass difference between input, 1st input and error signal estimate. + +@item e +Pass error signal estimated samples. Default value is @var{o}. @end table diff --git a/libavfilter/af_anlms.c b/libavfilter/af_anlms.c index a2c854b0b88..5b412b87cc5 100644 --- a/libavfilter/af_anlms.c +++ b/libavfilter/af_anlms.c @@ -34,6 +34,7 @@ enum OutModes { DESIRED_MODE, OUT_MODE, NOISE_MODE, + ERROR_MODE, NB_OMODES }; @@ -73,6 +74,7 @@ static const AVOption anlms_options[] = { { "d", "desired", 0, AV_OPT_TYPE_CONST, {.i64=DESIRED_MODE}, 0, 0, AT, "mode" }, { "o", "output", 0, AV_OPT_TYPE_CONST, {.i64=OUT_MODE}, 0, 0, AT, "mode" }, { "n", "noise", 0, AV_OPT_TYPE_CONST, {.i64=NOISE_MODE}, 0, 0, AT, "mode" }, + { "e", "error", 0, AV_OPT_TYPE_CONST, {.i64=ERROR_MODE}, 0, 0, AT, "mode" }, { NULL } }; @@ -102,7 +104,7 @@ static float process_sample(AudioNLMSContext *s, float input, float desired, const int order = s->order; const float leakage = s->leakage; const float mu = s->mu; - const float a = 1.f - leakage * mu; + const float a = 1.f - leakage; float sum, output, e, norm, b; int offset = *offsetp; @@ -116,7 +118,7 @@ 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; + b *= e * e; memcpy(tmp, delay + offset, order * sizeof(float)); @@ -129,8 +131,9 @@ static float process_sample(AudioNLMSContext *s, float input, float desired, switch (s->output_mode) { case IN_MODE: output = input; break; case DESIRED_MODE: output = desired; break; - case OUT_MODE: /*output = output;*/ break; - case NOISE_MODE: output = desired - output; break; + case OUT_MODE: output = desired - output; break; + case NOISE_MODE: output = input - output; break; + case ERROR_MODE: break; } return output; } From c7a852b638b88f129790af31fc47c870c329eaaa Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Wed, 24 Aug 2022 10:27:09 +0200 Subject: [PATCH 0840/2172] lavf/dv: do not set video timebase more than once Current code will call avpriv_set_pts_info() for each video frame, possibly setting a different timebase if the stream framerate changes. This violates API conventions, as the timebase is supposed to stay constant after stream creation. Change the demuxer to set a single timebase that is fine enough to handle all supported DV framerates. The seek tests change slightly because the new timebase is more granular. --- libavcodec/dv.h | 3 +++ libavformat/avidec.c | 22 +++++++++++++------ libavformat/dv.c | 36 +++++++++++++++++++++++-------- libavformat/dv.h | 2 +- tests/ref/seek/lavf-dv | 16 +++++++------- tests/ref/seek/vsynth_lena-dv | 24 ++++++++++----------- tests/ref/seek/vsynth_lena-dv-411 | 24 ++++++++++----------- tests/ref/seek/vsynth_lena-dv-50 | 24 ++++++++++----------- 8 files changed, 91 insertions(+), 60 deletions(-) diff --git a/libavcodec/dv.h b/libavcodec/dv.h index 29f97b6089a..b473bdc992d 100644 --- a/libavcodec/dv.h +++ b/libavcodec/dv.h @@ -60,6 +60,9 @@ enum DVPackType { */ #define DV_MAX_FRAME_SIZE 576000 +// LCM of video framerate numerators +#define DV_TIMESCALE_VIDEO 60000 + /** * maximum number of blocks per macroblock in any DV format */ diff --git a/libavformat/avidec.c b/libavformat/avidec.c index 7a3fad6392b..00bd7a98a9d 100644 --- a/libavformat/avidec.c +++ b/libavformat/avidec.c @@ -1869,13 +1869,20 @@ static int avi_read_seek(AVFormatContext *s, int stream_index, st = s->streams[stream_index]; sti = ffstream(st); ast = st->priv_data; - index = av_index_search_timestamp(st, - timestamp * FFMAX(ast->sample_size, 1), - flags); + + if (avi->dv_demux) { + // index entries are in the AVI scale/rate timebase, which does + // not match DV demuxer's stream timebase + timestamp = av_rescale_q(timestamp, st->time_base, + (AVRational){ ast->scale, ast->rate }); + } else + timestamp *= FFMAX(ast->sample_size, 1); + + index = av_index_search_timestamp(st, timestamp, flags); if (index < 0) { if (sti->nb_index_entries > 0) av_log(s, AV_LOG_DEBUG, "Failed to find timestamp %"PRId64 " in index %"PRId64 " .. %"PRId64 "\n", - timestamp * FFMAX(ast->sample_size, 1), + timestamp, sti->index_entries[0].timestamp, sti->index_entries[sti->nb_index_entries - 1].timestamp); return AVERROR_INVALIDDATA; @@ -1883,7 +1890,7 @@ static int avi_read_seek(AVFormatContext *s, int stream_index, /* find the position */ pos = sti->index_entries[index].pos; - timestamp = sti->index_entries[index].timestamp / FFMAX(ast->sample_size, 1); + timestamp = sti->index_entries[index].timestamp; av_log(s, AV_LOG_TRACE, "XX %"PRId64" %d %"PRId64"\n", timestamp, index, sti->index_entries[index].timestamp); @@ -1898,11 +1905,14 @@ static int avi_read_seek(AVFormatContext *s, int stream_index, /* Feed the DV video stream version of the timestamp to the */ /* DV demux so it can synthesize correct timestamps. */ - ff_dv_offset_reset(avi->dv_demux, timestamp); + ff_dv_ts_reset(avi->dv_demux, + av_rescale_q(timestamp, (AVRational){ ast->scale, ast->rate }, + st->time_base)); avi->stream_index = -1; return 0; } + timestamp /= FFMAX(ast->sample_size, 1); pos_min = pos; for (i = 0; i < s->nb_streams; i++) { diff --git a/libavformat/dv.c b/libavformat/dv.c index ffed1a7a90e..9888c10b48e 100644 --- a/libavformat/dv.c +++ b/libavformat/dv.c @@ -69,6 +69,8 @@ struct DVDemuxContext { uint8_t audio_buf[4][8192]; int ach; int frames; + + int64_t next_pts_video; }; static inline uint16_t dv_audio_12to16(uint16_t sample) @@ -314,8 +316,6 @@ static int dv_extract_video_info(DVDemuxContext *c, const uint8_t *frame) par = c->vst->codecpar; - avpriv_set_pts_info(c->vst, 64, c->sys->time_base.num, - c->sys->time_base.den); c->vst->avg_frame_rate = av_inv_q(c->vst->time_base); /* finding out SAR is a little bit messy */ @@ -360,6 +360,8 @@ static int dv_init_demux(AVFormatContext *s, DVDemuxContext *c) c->vst->codecpar->bit_rate = 25000000; c->vst->start_time = 0; + avpriv_set_pts_info(c->vst, 64, 1, DV_TIMESCALE_VIDEO); + /* Audio streams are added later as they are encountered. */ s->ctx_flags |= AVFMTCTX_NOHEADER; @@ -463,7 +465,10 @@ int avpriv_dv_produce_packet(DVDemuxContext *c, AVPacket *pkt, pkt->size = size; pkt->flags |= AV_PKT_FLAG_KEY; pkt->stream_index = c->vst->index; - pkt->pts = c->frames; + pkt->pts = c->next_pts_video; + pkt->duration = av_rescale_q(1, c->sys->time_base, c->vst->time_base); + + c->next_pts_video += pkt->duration; } c->frames++; @@ -472,28 +477,34 @@ int avpriv_dv_produce_packet(DVDemuxContext *c, AVPacket *pkt, } static int64_t dv_frame_offset(AVFormatContext *s, DVDemuxContext *c, - int64_t timestamp, int flags) + int64_t *timestamp) { // FIXME: sys may be wrong if last dv_read_packet() failed (buffer is junk) FFFormatContext *const si = ffformatcontext(s); const int frame_size = c->sys->frame_size; + int64_t frame_count = av_rescale_q(*timestamp, c->vst->time_base, c->sys->time_base); int64_t offset; int64_t size = avio_size(s->pb) - si->data_offset; int64_t max_offset = ((size - 1) / frame_size) * frame_size; - offset = frame_size * timestamp; + offset = frame_size * frame_count; if (size >= 0 && offset > max_offset) offset = max_offset; else if (offset < 0) offset = 0; + *timestamp = av_rescale_q(offset / frame_size, c->sys->time_base, c->vst->time_base); + return offset + si->data_offset; } -void ff_dv_offset_reset(DVDemuxContext *c, int64_t frame_offset) +void ff_dv_ts_reset(DVDemuxContext *c, int64_t ts) { - c->frames = frame_offset; + c->frames = !c->sys ? 0 : + av_rescale_q(ts, c->vst->time_base, c->sys->time_base); + c->next_pts_video = ts; + c->audio_pkt[0].size = c->audio_pkt[1].size = 0; c->audio_pkt[2].size = c->audio_pkt[3].size = 0; } @@ -618,12 +629,19 @@ static int dv_read_seek(AVFormatContext *s, int stream_index, { RawDVContext *r = s->priv_data; DVDemuxContext *c = &r->dv_demux; - int64_t offset = dv_frame_offset(s, c, timestamp, flags); + int64_t offset; + + // seek using the video stream + if (stream_index != c->vst->index) + timestamp = av_rescale_q(timestamp, s->streams[stream_index]->time_base, + c->vst->time_base); + + offset = dv_frame_offset(s, c, ×tamp); if (avio_seek(s->pb, offset, SEEK_SET) < 0) return -1; - ff_dv_offset_reset(c, offset / c->sys->frame_size); + ff_dv_ts_reset(c, timestamp); return 0; } diff --git a/libavformat/dv.h b/libavformat/dv.h index efced6ccf04..d21ea19e024 100644 --- a/libavformat/dv.h +++ b/libavformat/dv.h @@ -34,6 +34,6 @@ typedef struct DVDemuxContext DVDemuxContext; DVDemuxContext* avpriv_dv_init_demux(AVFormatContext* s); int avpriv_dv_get_packet(DVDemuxContext*, AVPacket *); int avpriv_dv_produce_packet(DVDemuxContext*, AVPacket*, uint8_t*, int, int64_t); -void ff_dv_offset_reset(DVDemuxContext *c, int64_t frame_offset); +void ff_dv_ts_reset(DVDemuxContext *c, int64_t ts_video); #endif /* AVFORMAT_DV_H */ diff --git a/tests/ref/seek/lavf-dv b/tests/ref/seek/lavf-dv index f63e4460be6..95f19d28f03 100644 --- a/tests/ref/seek/lavf-dv +++ b/tests/ref/seek/lavf-dv @@ -3,9 +3,9 @@ ret: 0 st:-1 flags:0 ts:-1.000000 ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 0 size:144000 ret: 0 st:-1 flags:1 ts: 1.894167 ret: 0 st: 0 flags:1 dts: 0.960000 pts: 0.960000 pos:3456000 size:144000 -ret: 0 st: 0 flags:0 ts: 0.800000 +ret: 0 st: 0 flags:0 ts: 0.788333 ret: 0 st: 0 flags:1 dts: 0.800000 pts: 0.800000 pos:2880000 size:144000 -ret: 0 st: 0 flags:1 ts:-0.320000 +ret: 0 st: 0 flags:1 ts:-0.317500 ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 0 size:144000 ret: 0 st: 1 flags:0 ts: 2.560000 ret: 0 st: 0 flags:1 dts: 0.960000 pts: 0.960000 pos:3456000 size:144000 @@ -15,9 +15,9 @@ ret: 0 st:-1 flags:0 ts: 0.365002 ret: 0 st: 0 flags:1 dts: 0.360000 pts: 0.360000 pos:1296000 size:144000 ret: 0 st:-1 flags:1 ts:-0.740831 ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 0 size:144000 -ret: 0 st: 0 flags:0 ts: 2.160000 +ret: 0 st: 0 flags:0 ts: 2.153333 ret: 0 st: 0 flags:1 dts: 0.960000 pts: 0.960000 pos:3456000 size:144000 -ret: 0 st: 0 flags:1 ts: 1.040000 +ret: 0 st: 0 flags:1 ts: 1.047500 ret: 0 st: 0 flags:1 dts: 0.960000 pts: 0.960000 pos:3456000 size:144000 ret: 0 st: 1 flags:0 ts:-0.040000 ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 0 size:144000 @@ -27,9 +27,9 @@ ret: 0 st:-1 flags:0 ts: 1.730004 ret: 0 st: 0 flags:1 dts: 0.960000 pts: 0.960000 pos:3456000 size:144000 ret: 0 st:-1 flags:1 ts: 0.624171 ret: 0 st: 0 flags:1 dts: 0.640000 pts: 0.640000 pos:2304000 size:144000 -ret: 0 st: 0 flags:0 ts:-0.480000 +ret: 0 st: 0 flags:0 ts:-0.481667 ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 0 size:144000 -ret: 0 st: 0 flags:1 ts: 2.400000 +ret: 0 st: 0 flags:1 ts: 2.412500 ret: 0 st: 0 flags:1 dts: 0.960000 pts: 0.960000 pos:3456000 size:144000 ret: 0 st: 1 flags:0 ts: 1.320000 ret: 0 st: 0 flags:1 dts: 0.960000 pts: 0.960000 pos:3456000 size:144000 @@ -39,9 +39,9 @@ ret: 0 st:-1 flags:0 ts:-0.904994 ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 0 size:144000 ret: 0 st:-1 flags:1 ts: 1.989173 ret: 0 st: 0 flags:1 dts: 0.960000 pts: 0.960000 pos:3456000 size:144000 -ret: 0 st: 0 flags:0 ts: 0.880000 +ret: 0 st: 0 flags:0 ts: 0.883333 ret: 0 st: 0 flags:1 dts: 0.880000 pts: 0.880000 pos:3168000 size:144000 -ret: 0 st: 0 flags:1 ts:-0.240000 +ret: 0 st: 0 flags:1 ts:-0.222500 ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 0 size:144000 ret: 0 st: 1 flags:0 ts: 2.680000 ret: 0 st: 0 flags:1 dts: 0.960000 pts: 0.960000 pos:3456000 size:144000 diff --git a/tests/ref/seek/vsynth_lena-dv b/tests/ref/seek/vsynth_lena-dv index d318794157b..afed1fbe727 100644 --- a/tests/ref/seek/vsynth_lena-dv +++ b/tests/ref/seek/vsynth_lena-dv @@ -3,49 +3,49 @@ ret: 0 st:-1 flags:0 ts:-1.000000 ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 0 size:144000 ret: 0 st:-1 flags:1 ts: 1.894167 ret: 0 st: 0 flags:1 dts: 1.880000 pts: 1.880000 pos:6768000 size:144000 -ret: 0 st: 0 flags:0 ts: 0.800000 +ret: 0 st: 0 flags:0 ts: 0.788333 ret: 0 st: 0 flags:1 dts: 0.800000 pts: 0.800000 pos:2880000 size:144000 -ret: 0 st: 0 flags:1 ts:-0.320000 +ret: 0 st: 0 flags:1 ts:-0.317500 ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 0 size:144000 ret: 0 st:-1 flags:0 ts: 2.576668 ret: 0 st: 0 flags:1 dts: 1.960000 pts: 1.960000 pos:7056000 size:144000 ret: 0 st:-1 flags:1 ts: 1.470835 ret: 0 st: 0 flags:1 dts: 1.480000 pts: 1.480000 pos:5328000 size:144000 -ret: 0 st: 0 flags:0 ts: 0.360000 +ret: 0 st: 0 flags:0 ts: 0.365000 ret: 0 st: 0 flags:1 dts: 0.360000 pts: 0.360000 pos:1296000 size:144000 -ret: 0 st: 0 flags:1 ts:-0.760000 +ret: 0 st: 0 flags:1 ts:-0.740833 ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 0 size:144000 ret: 0 st:-1 flags:0 ts: 2.153336 ret: 0 st: 0 flags:1 dts: 1.960000 pts: 1.960000 pos:7056000 size:144000 ret: 0 st:-1 flags:1 ts: 1.047503 ret: 0 st: 0 flags:1 dts: 1.040000 pts: 1.040000 pos:3744000 size:144000 -ret: 0 st: 0 flags:0 ts:-0.040000 +ret: 0 st: 0 flags:0 ts:-0.058333 ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 0 size:144000 -ret: 0 st: 0 flags:1 ts: 2.840000 +ret: 0 st: 0 flags:1 ts: 2.835833 ret: 0 st: 0 flags:1 dts: 1.960000 pts: 1.960000 pos:7056000 size:144000 ret: 0 st:-1 flags:0 ts: 1.730004 ret: 0 st: 0 flags:1 dts: 1.720000 pts: 1.720000 pos:6192000 size:144000 ret: 0 st:-1 flags:1 ts: 0.624171 ret: 0 st: 0 flags:1 dts: 0.640000 pts: 0.640000 pos:2304000 size:144000 -ret: 0 st: 0 flags:0 ts:-0.480000 +ret: 0 st: 0 flags:0 ts:-0.481667 ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 0 size:144000 -ret: 0 st: 0 flags:1 ts: 2.400000 +ret: 0 st: 0 flags:1 ts: 2.412500 ret: 0 st: 0 flags:1 dts: 1.960000 pts: 1.960000 pos:7056000 size:144000 ret: 0 st:-1 flags:0 ts: 1.306672 ret: 0 st: 0 flags:1 dts: 1.320000 pts: 1.320000 pos:4752000 size:144000 ret: 0 st:-1 flags:1 ts: 0.200839 ret: 0 st: 0 flags:1 dts: 0.200000 pts: 0.200000 pos: 720000 size:144000 -ret: 0 st: 0 flags:0 ts:-0.920000 +ret: 0 st: 0 flags:0 ts:-0.905000 ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 0 size:144000 -ret: 0 st: 0 flags:1 ts: 2.000000 +ret: 0 st: 0 flags:1 ts: 1.989167 ret: 0 st: 0 flags:1 dts: 1.960000 pts: 1.960000 pos:7056000 size:144000 ret: 0 st:-1 flags:0 ts: 0.883340 ret: 0 st: 0 flags:1 dts: 0.880000 pts: 0.880000 pos:3168000 size:144000 ret: 0 st:-1 flags:1 ts:-0.222493 ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 0 size:144000 -ret: 0 st: 0 flags:0 ts: 2.680000 +ret: 0 st: 0 flags:0 ts: 2.671667 ret: 0 st: 0 flags:1 dts: 1.960000 pts: 1.960000 pos:7056000 size:144000 -ret: 0 st: 0 flags:1 ts: 1.560000 +ret: 0 st: 0 flags:1 ts: 1.565833 ret: 0 st: 0 flags:1 dts: 1.560000 pts: 1.560000 pos:5616000 size:144000 ret: 0 st:-1 flags:0 ts: 0.460008 ret: 0 st: 0 flags:1 dts: 0.480000 pts: 0.480000 pos:1728000 size:144000 diff --git a/tests/ref/seek/vsynth_lena-dv-411 b/tests/ref/seek/vsynth_lena-dv-411 index d318794157b..afed1fbe727 100644 --- a/tests/ref/seek/vsynth_lena-dv-411 +++ b/tests/ref/seek/vsynth_lena-dv-411 @@ -3,49 +3,49 @@ ret: 0 st:-1 flags:0 ts:-1.000000 ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 0 size:144000 ret: 0 st:-1 flags:1 ts: 1.894167 ret: 0 st: 0 flags:1 dts: 1.880000 pts: 1.880000 pos:6768000 size:144000 -ret: 0 st: 0 flags:0 ts: 0.800000 +ret: 0 st: 0 flags:0 ts: 0.788333 ret: 0 st: 0 flags:1 dts: 0.800000 pts: 0.800000 pos:2880000 size:144000 -ret: 0 st: 0 flags:1 ts:-0.320000 +ret: 0 st: 0 flags:1 ts:-0.317500 ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 0 size:144000 ret: 0 st:-1 flags:0 ts: 2.576668 ret: 0 st: 0 flags:1 dts: 1.960000 pts: 1.960000 pos:7056000 size:144000 ret: 0 st:-1 flags:1 ts: 1.470835 ret: 0 st: 0 flags:1 dts: 1.480000 pts: 1.480000 pos:5328000 size:144000 -ret: 0 st: 0 flags:0 ts: 0.360000 +ret: 0 st: 0 flags:0 ts: 0.365000 ret: 0 st: 0 flags:1 dts: 0.360000 pts: 0.360000 pos:1296000 size:144000 -ret: 0 st: 0 flags:1 ts:-0.760000 +ret: 0 st: 0 flags:1 ts:-0.740833 ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 0 size:144000 ret: 0 st:-1 flags:0 ts: 2.153336 ret: 0 st: 0 flags:1 dts: 1.960000 pts: 1.960000 pos:7056000 size:144000 ret: 0 st:-1 flags:1 ts: 1.047503 ret: 0 st: 0 flags:1 dts: 1.040000 pts: 1.040000 pos:3744000 size:144000 -ret: 0 st: 0 flags:0 ts:-0.040000 +ret: 0 st: 0 flags:0 ts:-0.058333 ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 0 size:144000 -ret: 0 st: 0 flags:1 ts: 2.840000 +ret: 0 st: 0 flags:1 ts: 2.835833 ret: 0 st: 0 flags:1 dts: 1.960000 pts: 1.960000 pos:7056000 size:144000 ret: 0 st:-1 flags:0 ts: 1.730004 ret: 0 st: 0 flags:1 dts: 1.720000 pts: 1.720000 pos:6192000 size:144000 ret: 0 st:-1 flags:1 ts: 0.624171 ret: 0 st: 0 flags:1 dts: 0.640000 pts: 0.640000 pos:2304000 size:144000 -ret: 0 st: 0 flags:0 ts:-0.480000 +ret: 0 st: 0 flags:0 ts:-0.481667 ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 0 size:144000 -ret: 0 st: 0 flags:1 ts: 2.400000 +ret: 0 st: 0 flags:1 ts: 2.412500 ret: 0 st: 0 flags:1 dts: 1.960000 pts: 1.960000 pos:7056000 size:144000 ret: 0 st:-1 flags:0 ts: 1.306672 ret: 0 st: 0 flags:1 dts: 1.320000 pts: 1.320000 pos:4752000 size:144000 ret: 0 st:-1 flags:1 ts: 0.200839 ret: 0 st: 0 flags:1 dts: 0.200000 pts: 0.200000 pos: 720000 size:144000 -ret: 0 st: 0 flags:0 ts:-0.920000 +ret: 0 st: 0 flags:0 ts:-0.905000 ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 0 size:144000 -ret: 0 st: 0 flags:1 ts: 2.000000 +ret: 0 st: 0 flags:1 ts: 1.989167 ret: 0 st: 0 flags:1 dts: 1.960000 pts: 1.960000 pos:7056000 size:144000 ret: 0 st:-1 flags:0 ts: 0.883340 ret: 0 st: 0 flags:1 dts: 0.880000 pts: 0.880000 pos:3168000 size:144000 ret: 0 st:-1 flags:1 ts:-0.222493 ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 0 size:144000 -ret: 0 st: 0 flags:0 ts: 2.680000 +ret: 0 st: 0 flags:0 ts: 2.671667 ret: 0 st: 0 flags:1 dts: 1.960000 pts: 1.960000 pos:7056000 size:144000 -ret: 0 st: 0 flags:1 ts: 1.560000 +ret: 0 st: 0 flags:1 ts: 1.565833 ret: 0 st: 0 flags:1 dts: 1.560000 pts: 1.560000 pos:5616000 size:144000 ret: 0 st:-1 flags:0 ts: 0.460008 ret: 0 st: 0 flags:1 dts: 0.480000 pts: 0.480000 pos:1728000 size:144000 diff --git a/tests/ref/seek/vsynth_lena-dv-50 b/tests/ref/seek/vsynth_lena-dv-50 index fae6d1b225d..3b1d69ffa69 100644 --- a/tests/ref/seek/vsynth_lena-dv-50 +++ b/tests/ref/seek/vsynth_lena-dv-50 @@ -3,49 +3,49 @@ ret: 0 st:-1 flags:0 ts:-1.000000 ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 0 size:288000 ret: 0 st:-1 flags:1 ts: 1.894167 ret: 0 st: 0 flags:1 dts: 1.880000 pts: 1.880000 pos:13536000 size:288000 -ret: 0 st: 0 flags:0 ts: 0.800000 +ret: 0 st: 0 flags:0 ts: 0.788333 ret: 0 st: 0 flags:1 dts: 0.800000 pts: 0.800000 pos:5760000 size:288000 -ret: 0 st: 0 flags:1 ts:-0.320000 +ret: 0 st: 0 flags:1 ts:-0.317500 ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 0 size:288000 ret: 0 st:-1 flags:0 ts: 2.576668 ret: 0 st: 0 flags:1 dts: 1.960000 pts: 1.960000 pos:14112000 size:288000 ret: 0 st:-1 flags:1 ts: 1.470835 ret: 0 st: 0 flags:1 dts: 1.480000 pts: 1.480000 pos:10656000 size:288000 -ret: 0 st: 0 flags:0 ts: 0.360000 +ret: 0 st: 0 flags:0 ts: 0.365000 ret: 0 st: 0 flags:1 dts: 0.360000 pts: 0.360000 pos:2592000 size:288000 -ret: 0 st: 0 flags:1 ts:-0.760000 +ret: 0 st: 0 flags:1 ts:-0.740833 ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 0 size:288000 ret: 0 st:-1 flags:0 ts: 2.153336 ret: 0 st: 0 flags:1 dts: 1.960000 pts: 1.960000 pos:14112000 size:288000 ret: 0 st:-1 flags:1 ts: 1.047503 ret: 0 st: 0 flags:1 dts: 1.040000 pts: 1.040000 pos:7488000 size:288000 -ret: 0 st: 0 flags:0 ts:-0.040000 +ret: 0 st: 0 flags:0 ts:-0.058333 ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 0 size:288000 -ret: 0 st: 0 flags:1 ts: 2.840000 +ret: 0 st: 0 flags:1 ts: 2.835833 ret: 0 st: 0 flags:1 dts: 1.960000 pts: 1.960000 pos:14112000 size:288000 ret: 0 st:-1 flags:0 ts: 1.730004 ret: 0 st: 0 flags:1 dts: 1.720000 pts: 1.720000 pos:12384000 size:288000 ret: 0 st:-1 flags:1 ts: 0.624171 ret: 0 st: 0 flags:1 dts: 0.640000 pts: 0.640000 pos:4608000 size:288000 -ret: 0 st: 0 flags:0 ts:-0.480000 +ret: 0 st: 0 flags:0 ts:-0.481667 ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 0 size:288000 -ret: 0 st: 0 flags:1 ts: 2.400000 +ret: 0 st: 0 flags:1 ts: 2.412500 ret: 0 st: 0 flags:1 dts: 1.960000 pts: 1.960000 pos:14112000 size:288000 ret: 0 st:-1 flags:0 ts: 1.306672 ret: 0 st: 0 flags:1 dts: 1.320000 pts: 1.320000 pos:9504000 size:288000 ret: 0 st:-1 flags:1 ts: 0.200839 ret: 0 st: 0 flags:1 dts: 0.200000 pts: 0.200000 pos:1440000 size:288000 -ret: 0 st: 0 flags:0 ts:-0.920000 +ret: 0 st: 0 flags:0 ts:-0.905000 ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 0 size:288000 -ret: 0 st: 0 flags:1 ts: 2.000000 +ret: 0 st: 0 flags:1 ts: 1.989167 ret: 0 st: 0 flags:1 dts: 1.960000 pts: 1.960000 pos:14112000 size:288000 ret: 0 st:-1 flags:0 ts: 0.883340 ret: 0 st: 0 flags:1 dts: 0.880000 pts: 0.880000 pos:6336000 size:288000 ret: 0 st:-1 flags:1 ts:-0.222493 ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 0 size:288000 -ret: 0 st: 0 flags:0 ts: 2.680000 +ret: 0 st: 0 flags:0 ts: 2.671667 ret: 0 st: 0 flags:1 dts: 1.960000 pts: 1.960000 pos:14112000 size:288000 -ret: 0 st: 0 flags:1 ts: 1.560000 +ret: 0 st: 0 flags:1 ts: 1.565833 ret: 0 st: 0 flags:1 dts: 1.560000 pts: 1.560000 pos:11232000 size:288000 ret: 0 st:-1 flags:0 ts: 0.460008 ret: 0 st: 0 flags:1 dts: 0.480000 pts: 0.480000 pos:3456000 size:288000 From aae5ba31ca94307c15e134d98e7492cf5a208426 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Mon, 24 Apr 2023 16:00:38 +0200 Subject: [PATCH 0841/2172] lavf/dv: shorten code by using a local variable --- libavformat/dv.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/libavformat/dv.c b/libavformat/dv.c index 9888c10b48e..227caf168f9 100644 --- a/libavformat/dv.c +++ b/libavformat/dv.c @@ -437,10 +437,13 @@ int avpriv_dv_produce_packet(DVDemuxContext *c, AVPacket *pkt, return size; for (i = 0; i < c->ach; i++) { - c->audio_pkt[i].pos = pos; - c->audio_pkt[i].size = size; - c->audio_pkt[i].pts = (c->sys->height == 720) ? (c->frames & ~1) : c->frames; - c->audio_pkt[i].duration = 1; + DVPacket *dpkt = &c->audio_pkt[i]; + + dpkt->pos = pos; + dpkt->size = size; + dpkt->pts = (c->sys->height == 720) ? (c->frames & ~1) : c->frames; + dpkt->duration = 1; + ppcm[i] = c->audio_buf[i]; } if (c->ach) From 0ed1eeb74435c6d10edd251ce3529fce8ea564d6 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Mon, 24 Apr 2023 16:47:50 +0200 Subject: [PATCH 0842/2172] lavf/dv: use a more granular timebase for audio One that is fine enough to represent all DV audio sample rates. Audio packet durations are now sample-accurate. This largely undoes commit 76fbb0052df471075858c1cb82b04c8be7adba8d. To avoid breaking the issue fixed by that commit, resync audio timestamps against video if they get more than one frame apart. The sample from issue #8762 still works correctly after this commit. Slightly changes the results of the lavf-dv seektest, due to the audio timebase being more granular. --- libavcodec/dv.h | 3 +++ libavformat/dv.c | 27 ++++++++++++++++++++++++--- tests/ref/seek/lavf-dv | 16 ++++++++-------- 3 files changed, 35 insertions(+), 11 deletions(-) diff --git a/libavcodec/dv.h b/libavcodec/dv.h index b473bdc992d..abff9f1ea9a 100644 --- a/libavcodec/dv.h +++ b/libavcodec/dv.h @@ -63,6 +63,9 @@ enum DVPackType { // LCM of video framerate numerators #define DV_TIMESCALE_VIDEO 60000 +// LCM of audio sample rates +#define DV_TIMESCALE_AUDIO 14112000 + /** * maximum number of blocks per macroblock in any DV format */ diff --git a/libavformat/dv.c b/libavformat/dv.c index 227caf168f9..d01ecedc622 100644 --- a/libavformat/dv.c +++ b/libavformat/dv.c @@ -71,6 +71,7 @@ struct DVDemuxContext { int frames; int64_t next_pts_video; + int64_t next_pts_audio; }; static inline uint16_t dv_audio_12to16(uint16_t sample) @@ -282,7 +283,7 @@ static int dv_extract_audio_info(DVDemuxContext *c, const uint8_t *frame) if (!c->ast[i]) return AVERROR(ENOMEM); - avpriv_set_pts_info(c->ast[i], 64, c->sys->time_base.num, c->sys->time_base.den); + avpriv_set_pts_info(c->ast[i], 64, 1, DV_TIMESCALE_AUDIO); c->ast[i]->codecpar->codec_type = AVMEDIA_TYPE_AUDIO; c->ast[i]->codecpar->codec_id = AV_CODEC_ID_PCM_S16LE; c->ast[i]->codecpar->ch_layout = (AVChannelLayout)AV_CHANNEL_LAYOUT_STEREO; @@ -421,6 +422,7 @@ int avpriv_dv_get_packet(DVDemuxContext *c, AVPacket *pkt) int avpriv_dv_produce_packet(DVDemuxContext *c, AVPacket *pkt, uint8_t *buf, int buf_size, int64_t pos) { + int64_t pts, duration; int size, i; uint8_t *ppcm[5] = { 0 }; @@ -436,13 +438,30 @@ int avpriv_dv_produce_packet(DVDemuxContext *c, AVPacket *pkt, if (size < 0) return size; + if (c->ach) { + int64_t next_pts_video = av_rescale_q(c->next_pts_video, c->vst->time_base, + c->ast[0]->time_base); + + duration = av_rescale_q(size / 4, + (AVRational){ 1, c->audio_pkt[0].sample_rate }, + c->ast[0]->time_base); + + // if audio timestamps are more than one frame away from video, + // assume desync happened (e.g. due to dropped audio frames) and + // resynchronize + pts = (FFABS(next_pts_video - c->next_pts_audio) >= duration) ? + next_pts_video : c->next_pts_audio; + + c->next_pts_audio = pts + duration; + } + for (i = 0; i < c->ach; i++) { DVPacket *dpkt = &c->audio_pkt[i]; dpkt->pos = pos; dpkt->size = size; - dpkt->pts = (c->sys->height == 720) ? (c->frames & ~1) : c->frames; - dpkt->duration = 1; + dpkt->pts = pts; + dpkt->duration = duration; ppcm[i] = c->audio_buf[i]; } @@ -507,6 +526,8 @@ void ff_dv_ts_reset(DVDemuxContext *c, int64_t ts) c->frames = !c->sys ? 0 : av_rescale_q(ts, c->vst->time_base, c->sys->time_base); c->next_pts_video = ts; + c->next_pts_audio = (!c->sys || !c->ast[0]) ? AV_NOPTS_VALUE : + av_rescale_q(ts, c->vst->time_base, c->ast[0]->time_base); c->audio_pkt[0].size = c->audio_pkt[1].size = 0; c->audio_pkt[2].size = c->audio_pkt[3].size = 0; diff --git a/tests/ref/seek/lavf-dv b/tests/ref/seek/lavf-dv index 95f19d28f03..db46c7734c2 100644 --- a/tests/ref/seek/lavf-dv +++ b/tests/ref/seek/lavf-dv @@ -7,9 +7,9 @@ ret: 0 st: 0 flags:0 ts: 0.788333 ret: 0 st: 0 flags:1 dts: 0.800000 pts: 0.800000 pos:2880000 size:144000 ret: 0 st: 0 flags:1 ts:-0.317500 ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 0 size:144000 -ret: 0 st: 1 flags:0 ts: 2.560000 +ret: 0 st: 1 flags:0 ts: 2.576668 ret: 0 st: 0 flags:1 dts: 0.960000 pts: 0.960000 pos:3456000 size:144000 -ret: 0 st: 1 flags:1 ts: 1.480000 +ret: 0 st: 1 flags:1 ts: 1.470835 ret: 0 st: 0 flags:1 dts: 0.960000 pts: 0.960000 pos:3456000 size:144000 ret: 0 st:-1 flags:0 ts: 0.365002 ret: 0 st: 0 flags:1 dts: 0.360000 pts: 0.360000 pos:1296000 size:144000 @@ -19,9 +19,9 @@ ret: 0 st: 0 flags:0 ts: 2.153333 ret: 0 st: 0 flags:1 dts: 0.960000 pts: 0.960000 pos:3456000 size:144000 ret: 0 st: 0 flags:1 ts: 1.047500 ret: 0 st: 0 flags:1 dts: 0.960000 pts: 0.960000 pos:3456000 size:144000 -ret: 0 st: 1 flags:0 ts:-0.040000 +ret: 0 st: 1 flags:0 ts:-0.058330 ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 0 size:144000 -ret: 0 st: 1 flags:1 ts: 2.840000 +ret: 0 st: 1 flags:1 ts: 2.835837 ret: 0 st: 0 flags:1 dts: 0.960000 pts: 0.960000 pos:3456000 size:144000 ret: 0 st:-1 flags:0 ts: 1.730004 ret: 0 st: 0 flags:1 dts: 0.960000 pts: 0.960000 pos:3456000 size:144000 @@ -31,9 +31,9 @@ ret: 0 st: 0 flags:0 ts:-0.481667 ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 0 size:144000 ret: 0 st: 0 flags:1 ts: 2.412500 ret: 0 st: 0 flags:1 dts: 0.960000 pts: 0.960000 pos:3456000 size:144000 -ret: 0 st: 1 flags:0 ts: 1.320000 +ret: 0 st: 1 flags:0 ts: 1.306672 ret: 0 st: 0 flags:1 dts: 0.960000 pts: 0.960000 pos:3456000 size:144000 -ret: 0 st: 1 flags:1 ts: 0.200000 +ret: 0 st: 1 flags:1 ts: 0.200839 ret: 0 st: 0 flags:1 dts: 0.200000 pts: 0.200000 pos: 720000 size:144000 ret: 0 st:-1 flags:0 ts:-0.904994 ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 0 size:144000 @@ -43,9 +43,9 @@ ret: 0 st: 0 flags:0 ts: 0.883333 ret: 0 st: 0 flags:1 dts: 0.880000 pts: 0.880000 pos:3168000 size:144000 ret: 0 st: 0 flags:1 ts:-0.222500 ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 0 size:144000 -ret: 0 st: 1 flags:0 ts: 2.680000 +ret: 0 st: 1 flags:0 ts: 2.671674 ret: 0 st: 0 flags:1 dts: 0.960000 pts: 0.960000 pos:3456000 size:144000 -ret: 0 st: 1 flags:1 ts: 1.560000 +ret: 0 st: 1 flags:1 ts: 1.565841 ret: 0 st: 0 flags:1 dts: 0.960000 pts: 0.960000 pos:3456000 size:144000 ret: 0 st:-1 flags:0 ts: 0.460008 ret: 0 st: 0 flags:1 dts: 0.480000 pts: 0.480000 pos:1728000 size:144000 From 5a04aae82193d75b8f8814dc7e35f4cc84b1beba Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Tue, 18 Apr 2023 20:03:23 +0200 Subject: [PATCH 0843/2172] fftools/ffmpeg: deprecate -adrift_threshold This option has had no effect since -async was removed in 3d86a13b47b726e49c2d780c5f723c290e8a36b4 --- doc/ffmpeg.texi | 6 ------ fftools/ffmpeg.h | 2 +- fftools/ffmpeg_opt.c | 14 ++++++++++++-- 3 files changed, 13 insertions(+), 9 deletions(-) diff --git a/doc/ffmpeg.texi b/doc/ffmpeg.texi index 34c413355ed..0fea0bacb14 100644 --- a/doc/ffmpeg.texi +++ b/doc/ffmpeg.texi @@ -1749,12 +1749,6 @@ The default is -1.1. One possible usecase is to avoid framedrops in case of noisy timestamps or to increase frame drop precision in case of exact timestamps. -@item -adrift_threshold @var{time} -Set the minimum difference between timestamps and audio data (in seconds) to trigger -adding/dropping samples to make it match the timestamps. This option effectively is -a threshold to select between hard (add/drop) and soft (squeeze/stretch) compensation. -@code{-async} must be set to a positive value. - @item -apad @var{parameters} (@emph{output,per-stream}) Pad the output audio stream(s). This is the same as applying @code{-af apad}. Argument is a string of filter parameters composed the same as with the @code{apad} filter. diff --git a/fftools/ffmpeg.h b/fftools/ffmpeg.h index 95591f4bbad..a41bc9b518e 100644 --- a/fftools/ffmpeg.h +++ b/fftools/ffmpeg.h @@ -55,6 +55,7 @@ #define FFMPEG_OPT_MAP_SYNC 1 #define FFMPEG_ROTATION_METADATA 1 #define FFMPEG_OPT_QPHIST 1 +#define FFMPEG_OPT_ADRIFT_THRESHOLD 1 enum VideoSyncMethod { VSYNC_AUTO = -1, @@ -728,7 +729,6 @@ extern int nb_filtergraphs; extern char *vstats_filename; extern char *sdp_filename; -extern float audio_drift_threshold; extern float dts_delta_threshold; extern float dts_error_threshold; diff --git a/fftools/ffmpeg_opt.c b/fftools/ffmpeg_opt.c index c99263b6a5c..cf385c388e0 100644 --- a/fftools/ffmpeg_opt.c +++ b/fftools/ffmpeg_opt.c @@ -1347,6 +1347,14 @@ static int opt_qphist(void *optctx, const char *opt, const char *arg) } #endif +#if FFMPEG_OPT_ADRIFT_THRESHOLD +static int opt_adrift_threshold(void *optctx, const char *opt, const char *arg) +{ + av_log(NULL, AV_LOG_WARNING, "Option -%s is deprecated and has no effect\n", opt); + return 0; +} +#endif + #define OFFSET(x) offsetof(OptionsContext, x) const OptionDef options[] = { /* main options */ @@ -1453,8 +1461,10 @@ const OptionDef options[] = { "set video sync method globally; deprecated, use -fps_mode", "" }, { "frame_drop_threshold", HAS_ARG | OPT_FLOAT | OPT_EXPERT, { &frame_drop_threshold }, "frame drop threshold", "" }, - { "adrift_threshold", HAS_ARG | OPT_FLOAT | OPT_EXPERT, { &audio_drift_threshold }, - "audio drift threshold", "threshold" }, +#if FFMPEG_OPT_ADRIFT_THRESHOLD + { "adrift_threshold", HAS_ARG | OPT_EXPERT, { .func_arg = opt_adrift_threshold }, + "deprecated, does nothing", "threshold" }, +#endif { "copyts", OPT_BOOL | OPT_EXPERT, { ©_ts }, "copy timestamps" }, { "start_at_zero", OPT_BOOL | OPT_EXPERT, { &start_at_zero }, From f4a60b8ddc07b9385b601d18c00c600b50402481 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Thu, 20 Apr 2023 09:06:25 +0200 Subject: [PATCH 0844/2172] fftools/ffmpeg: reduce access to OutputStream.enc_ctx It will be made private to Encoder in the future. --- fftools/ffmpeg.c | 7 +++---- fftools/ffmpeg_mux.c | 2 +- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/fftools/ffmpeg.c b/fftools/ffmpeg.c index 15fe839914f..1ae2c5c18fb 100644 --- a/fftools/ffmpeg.c +++ b/fftools/ffmpeg.c @@ -649,8 +649,7 @@ static void print_report(int is_last_report, int64_t timer_start, int64_t cur_ti av_bprint_init(&buf, 0, AV_BPRINT_SIZE_AUTOMATIC); av_bprint_init(&buf_script, 0, AV_BPRINT_SIZE_AUTOMATIC); for (OutputStream *ost = ost_iter(NULL); ost; ost = ost_iter(ost)) { - const AVCodecContext * const enc = ost->enc_ctx; - const float q = enc ? ost->quality / (float) FF_QP2LAMBDA : -1; + const float q = ost->enc ? ost->quality / (float) FF_QP2LAMBDA : -1; if (vid && ost->type == AVMEDIA_TYPE_VIDEO) { av_bprintf(&buf, "q=%2.1f ", q); @@ -1155,7 +1154,7 @@ static int process_subtitle(InputStream *ist, AVSubtitle *subtitle, int *got_out for (int oidx = 0; oidx < ist->nb_outputs; oidx++) { OutputStream *ost = ist->outputs[oidx]; - if (!ost->enc_ctx || ost->enc_ctx->codec_type != AVMEDIA_TYPE_SUBTITLE) + if (!ost->enc || ost->type != AVMEDIA_TYPE_SUBTITLE) continue; enc_subtitle(output_files[ost->file_index], ost, subtitle); @@ -1527,7 +1526,7 @@ static int process_input_packet(InputStream *ist, const AVPacket *pkt, int no_eo for (int oidx = 0; oidx < ist->nb_outputs; oidx++) { OutputStream *ost = ist->outputs[oidx]; - if (ost->enc_ctx || (!pkt && no_eof)) + if (ost->enc || (!pkt && no_eof)) continue; if (duration_exceeded) { diff --git a/fftools/ffmpeg_mux.c b/fftools/ffmpeg_mux.c index a19f1a1f1e4..52f98fb76aa 100644 --- a/fftools/ffmpeg_mux.c +++ b/fftools/ffmpeg_mux.c @@ -742,7 +742,7 @@ static void mux_final_stats(Muxer *mux) av_log(of, AV_LOG_VERBOSE, " Output stream #%d:%d (%s): ", of->index, j, av_get_media_type_string(type)); - if (ost->enc_ctx) { + if (ost->enc) { av_log(of, AV_LOG_VERBOSE, "%"PRIu64" frames encoded", ost->frames_encoded); if (type == AVMEDIA_TYPE_AUDIO) From 52b632b65be91264543065296a6a197d2a087c70 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Thu, 20 Apr 2023 09:08:00 +0200 Subject: [PATCH 0845/2172] fftools/ffmpeg: drop OutputStream.pict_type It is no longer used outside of update_video_stats(), so make it a stack variable in that function. --- fftools/ffmpeg.h | 3 --- fftools/ffmpeg_enc.c | 5 +++-- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/fftools/ffmpeg.h b/fftools/ffmpeg.h index a41bc9b518e..c3cb365a3be 100644 --- a/fftools/ffmpeg.h +++ b/fftools/ffmpeg.h @@ -671,9 +671,6 @@ typedef struct OutputStream { /* packet quality factor */ int quality; - /* packet picture type */ - int pict_type; - /* frame encode sum of squared error values */ int64_t error[4]; diff --git a/fftools/ffmpeg_enc.c b/fftools/ffmpeg_enc.c index 859c7fdeeec..096e0ce14aa 100644 --- a/fftools/ffmpeg_enc.c +++ b/fftools/ffmpeg_enc.c @@ -587,11 +587,12 @@ static void update_video_stats(OutputStream *ost, const AVPacket *pkt, int write const uint8_t *sd = av_packet_get_side_data(pkt, AV_PKT_DATA_QUALITY_STATS, NULL); AVCodecContext *enc = ost->enc_ctx; + enum AVPictureType pict_type; int64_t frame_number; double ti1, bitrate, avg_bitrate; ost->quality = sd ? AV_RL32(sd) : -1; - ost->pict_type = sd ? sd[4] : AV_PICTURE_TYPE_NONE; + pict_type = sd ? sd[4] : AV_PICTURE_TYPE_NONE; for (int i = 0; ierror); i++) { if (sd && i < sd[5]) @@ -634,7 +635,7 @@ static void update_video_stats(OutputStream *ost, const AVPacket *pkt, int write avg_bitrate = (double)(e->data_size * 8) / ti1 / 1000.0; fprintf(vstats_file, "s_size= %8.0fkB time= %0.3f br= %7.1fkbits/s avg_br= %7.1fkbits/s ", (double)e->data_size / 1024, ti1, bitrate, avg_bitrate); - fprintf(vstats_file, "type= %c\n", av_get_picture_type_char(ost->pict_type)); + fprintf(vstats_file, "type= %c\n", av_get_picture_type_char(pict_type)); } static int encode_frame(OutputFile *of, OutputStream *ost, AVFrame *frame) From 6e487a50a10597f5bab8a4bde45f7d3a916296b4 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Thu, 20 Apr 2023 09:30:00 +0200 Subject: [PATCH 0846/2172] fftools/ffmpeg: drop OutputStream.error Only the first component is used in update_video_stats(), so make it a stack variable in that function. --- fftools/ffmpeg.h | 8 -------- fftools/ffmpeg_enc.c | 20 +++++++++++++------- 2 files changed, 13 insertions(+), 15 deletions(-) diff --git a/fftools/ffmpeg.h b/fftools/ffmpeg.h index c3cb365a3be..c4b77ab2c8c 100644 --- a/fftools/ffmpeg.h +++ b/fftools/ffmpeg.h @@ -671,9 +671,6 @@ typedef struct OutputStream { /* packet quality factor */ int quality; - /* frame encode sum of squared error values */ - int64_t error[4]; - int sq_idx_encode; int sq_idx_mux; @@ -920,11 +917,6 @@ InputStream *ist_iter(InputStream *prev); * pass NULL to start iteration */ OutputStream *ost_iter(OutputStream *prev); -static inline double psnr(double d) -{ - return -10.0 * log10(d); -} - void close_output_stream(OutputStream *ost); int trigger_fix_sub_duration_heartbeat(OutputStream *ost, const AVPacket *pkt); void update_benchmark(const char *fmt, ...); diff --git a/fftools/ffmpeg_enc.c b/fftools/ffmpeg_enc.c index 096e0ce14aa..c368097cd09 100644 --- a/fftools/ffmpeg_enc.c +++ b/fftools/ffmpeg_enc.c @@ -581,6 +581,11 @@ void enc_stats_write(OutputStream *ost, EncStats *es, avio_flush(io); } +static inline double psnr(double d) +{ + return -10.0 * log10(d); +} + static void update_video_stats(OutputStream *ost, const AVPacket *pkt, int write_vstats) { Encoder *e = ost->enc; @@ -590,15 +595,16 @@ static void update_video_stats(OutputStream *ost, const AVPacket *pkt, int write enum AVPictureType pict_type; int64_t frame_number; double ti1, bitrate, avg_bitrate; + double psnr_val = -1; ost->quality = sd ? AV_RL32(sd) : -1; pict_type = sd ? sd[4] : AV_PICTURE_TYPE_NONE; - for (int i = 0; ierror); i++) { - if (sd && i < sd[5]) - ost->error[i] = AV_RL64(sd + 8 + 8*i); - else - ost->error[i] = -1; + if ((enc->flags & AV_CODEC_FLAG_PSNR) && sd && sd[5]) { + // FIXME the scaling assumes 8bit + double error = AV_RL64(sd + 8) / (enc->width * enc->height * 255.0 * 255.0); + if (error >= 0 && error <= 1) + psnr_val = psnr(error); } if (!write_vstats) @@ -622,8 +628,8 @@ static void update_video_stats(OutputStream *ost, const AVPacket *pkt, int write ost->quality / (float)FF_QP2LAMBDA); } - if (ost->error[0]>=0 && (enc->flags & AV_CODEC_FLAG_PSNR)) - fprintf(vstats_file, "PSNR= %6.2f ", psnr(ost->error[0] / (enc->width * enc->height * 255.0 * 255.0))); + if (psnr_val >= 0) + fprintf(vstats_file, "PSNR= %6.2f ", psnr_val); fprintf(vstats_file,"f_size= %6d ", pkt->size); /* compute pts value */ From 7e3eb2412314760bff6036e6eb2d4b7bbdcde9c4 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Thu, 27 Apr 2023 16:02:30 +0200 Subject: [PATCH 0847/2172] fftools/ffmpeg: move OutputStream.packets_encoded to Encoder It is no longer used outside of ffmpeg_enc. --- fftools/ffmpeg.h | 2 -- fftools/ffmpeg_enc.c | 9 ++++++--- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/fftools/ffmpeg.h b/fftools/ffmpeg.h index c4b77ab2c8c..116087354db 100644 --- a/fftools/ffmpeg.h +++ b/fftools/ffmpeg.h @@ -665,8 +665,6 @@ typedef struct OutputStream { // number of frames/samples sent to the encoder uint64_t frames_encoded; uint64_t samples_encoded; - // number of packets received from the encoder - uint64_t packets_encoded; /* packet quality factor */ int quality; diff --git a/fftools/ffmpeg_enc.c b/fftools/ffmpeg_enc.c index c368097cd09..5707199ac52 100644 --- a/fftools/ffmpeg_enc.c +++ b/fftools/ffmpeg_enc.c @@ -59,6 +59,9 @@ struct Encoder { // combined size of all the packets received from the encoder uint64_t data_size; + + // number of packets received from the encoder + uint64_t packets_encoded; }; static uint64_t dup_warning = 1000; @@ -619,7 +622,7 @@ static void update_video_stats(OutputStream *ost, const AVPacket *pkt, int write } } - frame_number = ost->packets_encoded; + frame_number = e->packets_encoded; if (vstats_version <= 1) { fprintf(vstats_file, "frame= %5"PRId64" q= %2.1f ", frame_number, ost->quality / (float)FF_QP2LAMBDA); @@ -708,7 +711,7 @@ static int encode_frame(OutputFile *of, OutputStream *ost, AVFrame *frame) update_video_stats(ost, pkt, !!vstats_filename); if (ost->enc_stats_post.io) enc_stats_write(ost, &ost->enc_stats_post, NULL, pkt, - ost->packets_encoded); + e->packets_encoded); if (debug_ts) { av_log(ost, AV_LOG_INFO, "encoder -> type:%s " @@ -742,7 +745,7 @@ static int encode_frame(OutputFile *of, OutputStream *ost, AVFrame *frame) e->data_size += pkt->size; - ost->packets_encoded++; + e->packets_encoded++; of_output_packet(of, pkt, ost, 0); } From 38c937e8c48608fd1574729365aa991b189138cb Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Thu, 20 Apr 2023 09:36:03 +0200 Subject: [PATCH 0848/2172] fftools/ffmpeg: drop undocumented runtime debug-setting This feature is of highly questionable usefulness and - as the comment in the code says - is not actually supported by the API. --- fftools/ffmpeg.c | 35 ----------------------------------- 1 file changed, 35 deletions(-) diff --git a/fftools/ffmpeg.c b/fftools/ffmpeg.c index 1ae2c5c18fb..453d3763be3 100644 --- a/fftools/ffmpeg.c +++ b/fftools/ffmpeg.c @@ -1768,40 +1768,6 @@ static int check_keyboard_interaction(int64_t cur_time) "only %d given in string '%s'\n", n, buf); } } - if (key == 'd' || key == 'D'){ - int debug=0; - if(key == 'D') { - InputStream *ist = ist_iter(NULL); - - if (ist) - debug = ist->dec_ctx->debug << 1; - - if(!debug) debug = 1; - while (debug & FF_DEBUG_DCT_COEFF) //unsupported, would just crash - debug += debug; - }else{ - char buf[32]; - int k = 0; - i = 0; - set_tty_echo(1); - while ((k = read_key()) != '\n' && k != '\r' && i < sizeof(buf)-1) - if (k > 0) - buf[i++] = k; - buf[i] = 0; - set_tty_echo(0); - fprintf(stderr, "\n"); - if (k <= 0 || sscanf(buf, "%d", &debug)!=1) - fprintf(stderr,"error parsing debug value\n"); - } - for (InputStream *ist = ist_iter(NULL); ist; ist = ist_iter(ist)) - ist->dec_ctx->debug = debug; - for (OutputStream *ost = ost_iter(NULL); ost; ost = ost_iter(ost)) { - if (ost->enc_ctx) - ost->enc_ctx->debug = debug; - } - if(debug) av_log_set_level(AV_LOG_DEBUG); - fprintf(stderr,"debug=%d\n", debug); - } if (key == '?'){ fprintf(stderr, "key function\n" "? show this help\n" @@ -1809,7 +1775,6 @@ static int check_keyboard_interaction(int64_t cur_time) "- decrease verbosity\n" "c Send command to first matching filter supporting it\n" "C Send/Queue command to all matching filters\n" - "D cycle through available debug modes\n" "h dump packets/hex press to cycle through the 3 states\n" "q quit\n" "s Show QP histogram\n" From aee5b774bf21fdb66fbd4b9ae07109986d1a1014 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Tue, 18 Apr 2023 20:15:07 +0200 Subject: [PATCH 0849/2172] fftools/ffmpeg_filter: make ifilter_parameters_from_frame() static It is no longer used outside of this file. --- fftools/ffmpeg.h | 1 - fftools/ffmpeg_filter.c | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/fftools/ffmpeg.h b/fftools/ffmpeg.h index 116087354db..cc384b4b302 100644 --- a/fftools/ffmpeg.h +++ b/fftools/ffmpeg.h @@ -794,7 +794,6 @@ void sub2video_update(InputStream *ist, int64_t heartbeat_pts, AVSubtitle *sub); int ifilter_send_frame(InputFilter *ifilter, AVFrame *frame, int keep_reference); int ifilter_send_eof(InputFilter *ifilter, int64_t pts); -int ifilter_parameters_from_frame(InputFilter *ifilter, const AVFrame *frame); int ifilter_parameters_from_codecpar(InputFilter *ifilter, AVCodecParameters *par); int ifilter_has_all_input_formats(FilterGraph *fg); diff --git a/fftools/ffmpeg_filter.c b/fftools/ffmpeg_filter.c index 161ea9c866c..43bae9c25b3 100644 --- a/fftools/ffmpeg_filter.c +++ b/fftools/ffmpeg_filter.c @@ -1311,7 +1311,7 @@ int configure_filtergraph(FilterGraph *fg) return ret; } -int ifilter_parameters_from_frame(InputFilter *ifilter, const AVFrame *frame) +static int ifilter_parameters_from_frame(InputFilter *ifilter, const AVFrame *frame) { AVFrameSideData *sd; int ret; From 09dd9c5f4129d080ac50c4ac19b24d17ccd8a472 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Tue, 18 Apr 2023 19:44:15 +0200 Subject: [PATCH 0850/2172] fftools/ffmpeg_filter: add filtergraph private data Start by moving OutputStream.filtered_frame to it, which really belongs to the filtergraph rather than the output stream. --- fftools/ffmpeg.h | 1 - fftools/ffmpeg_filter.c | 31 ++++++++++++++++++++++++++----- fftools/ffmpeg_mux.c | 1 - fftools/ffmpeg_mux_init.c | 4 ---- 4 files changed, 26 insertions(+), 11 deletions(-) diff --git a/fftools/ffmpeg.h b/fftools/ffmpeg.h index cc384b4b302..2acbccfe2c3 100644 --- a/fftools/ffmpeg.h +++ b/fftools/ffmpeg.h @@ -604,7 +604,6 @@ typedef struct OutputStream { Encoder *enc; AVCodecContext *enc_ctx; - AVFrame *filtered_frame; AVPacket *pkt; int64_t last_dropped; diff --git a/fftools/ffmpeg_filter.c b/fftools/ffmpeg_filter.c index 43bae9c25b3..d348509ee29 100644 --- a/fftools/ffmpeg_filter.c +++ b/fftools/ffmpeg_filter.c @@ -38,6 +38,18 @@ #include "libavutil/samplefmt.h" #include "libavutil/timestamp.h" +typedef struct FilterGraphPriv { + FilterGraph fg; + + // frame for temporarily holding output from the filtergraph + AVFrame *frame; +} FilterGraphPriv; + +static FilterGraphPriv *fgp_from_fg(FilterGraph *fg) +{ + return (FilterGraphPriv*)fg; +} + // FIXME: YUV420P etc. are actually supported with full color range, // yet the latter information isn't available here. static const enum AVPixelFormat *get_compliance_normal_pix_fmts(const AVCodec *codec, const enum AVPixelFormat default_formats[]) @@ -192,9 +204,11 @@ static OutputFilter *ofilter_alloc(FilterGraph *fg) void fg_free(FilterGraph **pfg) { FilterGraph *fg = *pfg; + FilterGraphPriv *fgp; if (!fg) return; + fgp = fgp_from_fg(fg); avfilter_graph_free(&fg->graph); for (int j = 0; j < fg->nb_inputs; j++) { @@ -230,17 +244,23 @@ void fg_free(FilterGraph **pfg) av_freep(&fg->outputs); av_freep(&fg->graph_desc); + av_frame_free(&fgp->frame); + av_freep(pfg); } FilterGraph *fg_create(char *graph_desc) { - FilterGraph *fg; + FilterGraphPriv *fgp = allocate_array_elem(&filtergraphs, sizeof(*fgp), &nb_filtergraphs); + FilterGraph *fg = &fgp->fg; - fg = ALLOC_ARRAY_ELEM(filtergraphs, nb_filtergraphs); fg->index = nb_filtergraphs - 1; fg->graph_desc = graph_desc; + fgp->frame = av_frame_alloc(); + if (!fgp->frame) + report_and_exit(AVERROR(ENOMEM)); + return fg; } @@ -1350,18 +1370,19 @@ int filtergraph_is_simple(FilterGraph *fg) int reap_filters(int flush) { - AVFrame *filtered_frame = NULL; - /* Reap all buffers present in the buffer sinks */ for (OutputStream *ost = ost_iter(NULL); ost; ost = ost_iter(ost)) { + FilterGraphPriv *fgp; + AVFrame *filtered_frame; AVFilterContext *filter; int ret = 0; if (!ost->filter || !ost->filter->graph->graph) continue; filter = ost->filter->filter; + fgp = fgp_from_fg(ost->filter->graph); - filtered_frame = ost->filtered_frame; + filtered_frame = fgp->frame; while (1) { ret = av_buffersink_get_frame_flags(filter, filtered_frame, diff --git a/fftools/ffmpeg_mux.c b/fftools/ffmpeg_mux.c index 52f98fb76aa..afcd4df99b7 100644 --- a/fftools/ffmpeg_mux.c +++ b/fftools/ffmpeg_mux.c @@ -845,7 +845,6 @@ static void ost_free(OutputStream **post) av_bsf_free(&ms->bsf_ctx); - av_frame_free(&ost->filtered_frame); av_packet_free(&ost->pkt); av_dict_free(&ost->encoder_opts); diff --git a/fftools/ffmpeg_mux_init.c b/fftools/ffmpeg_mux_init.c index 7a2db9f0e83..2c0e2faf4a1 100644 --- a/fftools/ffmpeg_mux_init.c +++ b/fftools/ffmpeg_mux_init.c @@ -1026,10 +1026,6 @@ static OutputStream *ost_add(Muxer *mux, const OptionsContext *o, av_strlcat(ms->log_name, "/copy", sizeof(ms->log_name)); } - ost->filtered_frame = av_frame_alloc(); - if (!ost->filtered_frame) - report_and_exit(AVERROR(ENOMEM)); - ost->pkt = av_packet_alloc(); if (!ost->pkt) report_and_exit(AVERROR(ENOMEM)); From 87ced7aee08536551c7616c1229adc74802cf7f9 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Thu, 27 Apr 2023 15:47:04 +0200 Subject: [PATCH 0851/2172] fftools/ffmpeg_filter: make graph_desc private It is not used outside of ffmpeg_filter. --- fftools/ffmpeg.h | 1 - fftools/ffmpeg_filter.c | 22 ++++++++++++++-------- 2 files changed, 14 insertions(+), 9 deletions(-) diff --git a/fftools/ffmpeg.h b/fftools/ffmpeg.h index 2acbccfe2c3..e0e923e902b 100644 --- a/fftools/ffmpeg.h +++ b/fftools/ffmpeg.h @@ -323,7 +323,6 @@ typedef struct OutputFilter { typedef struct FilterGraph { int index; - const char *graph_desc; AVFilterGraph *graph; // true when the filtergraph contains only meta filters diff --git a/fftools/ffmpeg_filter.c b/fftools/ffmpeg_filter.c index d348509ee29..8246ffca770 100644 --- a/fftools/ffmpeg_filter.c +++ b/fftools/ffmpeg_filter.c @@ -41,6 +41,8 @@ typedef struct FilterGraphPriv { FilterGraph fg; + const char *graph_desc; + // frame for temporarily holding output from the filtergraph AVFrame *frame; } FilterGraphPriv; @@ -242,7 +244,7 @@ void fg_free(FilterGraph **pfg) av_freep(&fg->outputs[j]); } av_freep(&fg->outputs); - av_freep(&fg->graph_desc); + av_freep(&fgp->graph_desc); av_frame_free(&fgp->frame); @@ -255,7 +257,7 @@ FilterGraph *fg_create(char *graph_desc) FilterGraph *fg = &fgp->fg; fg->index = nb_filtergraphs - 1; - fg->graph_desc = graph_desc; + fgp->graph_desc = graph_desc; fgp->frame = av_frame_alloc(); if (!fgp->frame) @@ -312,6 +314,7 @@ static char *describe_filter_link(FilterGraph *fg, AVFilterInOut *inout, int in) static void init_input_filter(FilterGraph *fg, AVFilterInOut *in) { + FilterGraphPriv *fgp = fgp_from_fg(fg); InputStream *ist = NULL; enum AVMediaType type = avfilter_pad_get_type(in->filter_ctx->input_pads, in->pad_idx); InputFilter *ifilter; @@ -332,7 +335,7 @@ static void init_input_filter(FilterGraph *fg, AVFilterInOut *in) if (file_idx < 0 || file_idx >= nb_input_files) { av_log(NULL, AV_LOG_FATAL, "Invalid file index %d in filtergraph description %s.\n", - file_idx, fg->graph_desc); + file_idx, fgp->graph_desc); exit_program(1); } s = input_files[file_idx]->ctx; @@ -350,13 +353,13 @@ static void init_input_filter(FilterGraph *fg, AVFilterInOut *in) } if (!st) { av_log(NULL, AV_LOG_FATAL, "Stream specifier '%s' in filtergraph description %s " - "matches no streams.\n", p, fg->graph_desc); + "matches no streams.\n", p, fgp->graph_desc); exit_program(1); } ist = input_files[file_idx]->streams[st->index]; if (ist->user_set_discard == AVDISCARD_ALL) { av_log(NULL, AV_LOG_FATAL, "Stream specifier '%s' in filtergraph description %s " - "matches a disabled input stream.\n", p, fg->graph_desc); + "matches a disabled input stream.\n", p, fgp->graph_desc); exit_program(1); } } else { @@ -562,6 +565,7 @@ static int graph_parse(AVFilterGraph *graph, const char *desc, int init_complex_filtergraph(FilterGraph *fg) { + FilterGraphPriv *fgp = fgp_from_fg(fg); AVFilterInOut *inputs, *outputs, *cur; AVFilterGraph *graph; int ret = 0; @@ -573,7 +577,7 @@ int init_complex_filtergraph(FilterGraph *fg) return AVERROR(ENOMEM); graph->nb_threads = 1; - ret = graph_parse(graph, fg->graph_desc, &inputs, &outputs, NULL); + ret = graph_parse(graph, fgp->graph_desc, &inputs, &outputs, NULL); if (ret < 0) goto fail; @@ -1181,11 +1185,12 @@ static int graph_is_meta(AVFilterGraph *graph) int configure_filtergraph(FilterGraph *fg) { + FilterGraphPriv *fgp = fgp_from_fg(fg); AVBufferRef *hw_device; AVFilterInOut *inputs, *outputs, *cur; int ret, i, simple = filtergraph_is_simple(fg); const char *graph_desc = simple ? fg->outputs[0]->ost->avfilter : - fg->graph_desc; + fgp->graph_desc; cleanup_filtergraph(fg); if (!(fg->graph = avfilter_graph_alloc())) @@ -1365,7 +1370,8 @@ static int ifilter_parameters_from_frame(InputFilter *ifilter, const AVFrame *fr int filtergraph_is_simple(FilterGraph *fg) { - return !fg->graph_desc; + FilterGraphPriv *fgp = fgp_from_fg(fg); + return !fgp->graph_desc; } int reap_filters(int flush) From 1dcae45ecbbc489d46695b41f92edf13efdca653 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Tue, 25 Apr 2023 23:32:04 +0200 Subject: [PATCH 0852/2172] fftools/ffmpeg_filter: factorize allocating InputFilter --- fftools/ffmpeg_filter.c | 31 +++++++++++++++++-------------- 1 file changed, 17 insertions(+), 14 deletions(-) diff --git a/fftools/ffmpeg_filter.c b/fftools/ffmpeg_filter.c index 8246ffca770..a9242fcd119 100644 --- a/fftools/ffmpeg_filter.c +++ b/fftools/ffmpeg_filter.c @@ -203,6 +203,21 @@ static OutputFilter *ofilter_alloc(FilterGraph *fg) return ofilter; } +static InputFilter *ifilter_alloc(FilterGraph *fg) +{ + InputFilter *ifilter; + + ifilter = ALLOC_ARRAY_ELEM(fg->inputs, fg->nb_inputs); + ifilter->graph = fg; + ifilter->format = -1; + + ifilter->frame_queue = av_fifo_alloc2(8, sizeof(AVFrame*), AV_FIFO_FLAG_AUTO_GROW); + if (!ifilter->frame_queue) + report_and_exit(AVERROR(ENOMEM)); + + return ifilter; +} + void fg_free(FilterGraph **pfg) { FilterGraph *fg = *pfg; @@ -281,14 +296,8 @@ int init_simple_filtergraph(InputStream *ist, OutputStream *ost) ost->filter = ofilter; - ifilter = ALLOC_ARRAY_ELEM(fg->inputs, fg->nb_inputs); + ifilter = ifilter_alloc(fg); ifilter->ist = ist; - ifilter->graph = fg; - ifilter->format = -1; - - ifilter->frame_queue = av_fifo_alloc2(8, sizeof(AVFrame*), AV_FIFO_FLAG_AUTO_GROW); - if (!ifilter->frame_queue) - report_and_exit(AVERROR(ENOMEM)); ist_filter_add(ist, ifilter, 1); @@ -379,17 +388,11 @@ static void init_input_filter(FilterGraph *fg, AVFilterInOut *in) } av_assert0(ist); - ifilter = ALLOC_ARRAY_ELEM(fg->inputs, fg->nb_inputs); + ifilter = ifilter_alloc(fg); ifilter->ist = ist; - ifilter->graph = fg; - ifilter->format = -1; ifilter->type = ist->st->codecpar->codec_type; ifilter->name = describe_filter_link(fg, in, 1); - ifilter->frame_queue = av_fifo_alloc2(8, sizeof(AVFrame*), AV_FIFO_FLAG_AUTO_GROW); - if (!ifilter->frame_queue) - report_and_exit(AVERROR(ENOMEM)); - ist_filter_add(ist, ifilter, 0); } From 04f0c40c748d502059db8b4f379fbb61306de428 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Tue, 25 Apr 2023 23:44:49 +0200 Subject: [PATCH 0853/2172] fftools/ffmpeg_filter: add InputFilter private data Move InputFilter.frame_queue to it, which is not accessed outside of ffmpeg_filter. --- fftools/ffmpeg.h | 2 -- fftools/ffmpeg_filter.c | 33 ++++++++++++++++++++++++--------- 2 files changed, 24 insertions(+), 11 deletions(-) diff --git a/fftools/ffmpeg.h b/fftools/ffmpeg.h index e0e923e902b..07322fdd794 100644 --- a/fftools/ffmpeg.h +++ b/fftools/ffmpeg.h @@ -277,8 +277,6 @@ typedef struct InputFilter { uint8_t *name; enum AVMediaType type; // AVMEDIA_TYPE_SUBTITLE for sub2video - AVFifo *frame_queue; - // parameters configured for this input int format; diff --git a/fftools/ffmpeg_filter.c b/fftools/ffmpeg_filter.c index a9242fcd119..78789600bf7 100644 --- a/fftools/ffmpeg_filter.c +++ b/fftools/ffmpeg_filter.c @@ -52,6 +52,17 @@ static FilterGraphPriv *fgp_from_fg(FilterGraph *fg) return (FilterGraphPriv*)fg; } +typedef struct InputFilterPriv { + InputFilter ifilter; + + AVFifo *frame_queue; +} InputFilterPriv; + +static InputFilterPriv *ifp_from_ifilter(InputFilter *ifilter) +{ + return (InputFilterPriv*)ifilter; +} + // FIXME: YUV420P etc. are actually supported with full color range, // yet the latter information isn't available here. static const enum AVPixelFormat *get_compliance_normal_pix_fmts(const AVCodec *codec, const enum AVPixelFormat default_formats[]) @@ -205,14 +216,15 @@ static OutputFilter *ofilter_alloc(FilterGraph *fg) static InputFilter *ifilter_alloc(FilterGraph *fg) { - InputFilter *ifilter; + InputFilterPriv *ifp = allocate_array_elem(&fg->inputs, sizeof(*ifp), + &fg->nb_inputs); + InputFilter *ifilter = &ifp->ifilter; - ifilter = ALLOC_ARRAY_ELEM(fg->inputs, fg->nb_inputs); ifilter->graph = fg; ifilter->format = -1; - ifilter->frame_queue = av_fifo_alloc2(8, sizeof(AVFrame*), AV_FIFO_FLAG_AUTO_GROW); - if (!ifilter->frame_queue) + ifp->frame_queue = av_fifo_alloc2(8, sizeof(AVFrame*), AV_FIFO_FLAG_AUTO_GROW); + if (!ifp->frame_queue) report_and_exit(AVERROR(ENOMEM)); return ifilter; @@ -230,13 +242,14 @@ void fg_free(FilterGraph **pfg) avfilter_graph_free(&fg->graph); for (int j = 0; j < fg->nb_inputs; j++) { InputFilter *ifilter = fg->inputs[j]; + InputFilterPriv *ifp = ifp_from_ifilter(ifilter); struct InputStream *ist = ifilter->ist; - if (ifilter->frame_queue) { + if (ifp->frame_queue) { AVFrame *frame; - while (av_fifo_read(ifilter->frame_queue, &frame, 1) >= 0) + while (av_fifo_read(ifp->frame_queue, &frame, 1) >= 0) av_frame_free(&frame); - av_fifo_freep2(&ifilter->frame_queue); + av_fifo_freep2(&ifp->frame_queue); } av_freep(&ifilter->displaymatrix); if (ist->sub2video.sub_queue) { @@ -1302,8 +1315,9 @@ int configure_filtergraph(FilterGraph *fg) } for (i = 0; i < fg->nb_inputs; i++) { + InputFilterPriv *ifp = ifp_from_ifilter(fg->inputs[i]); AVFrame *tmp; - while (av_fifo_read(fg->inputs[i]->frame_queue, &tmp, 1) >= 0) { + while (av_fifo_read(ifp->frame_queue, &tmp, 1) >= 0) { ret = av_buffersrc_add_frame(fg->inputs[i]->filter, tmp); av_frame_free(&tmp); if (ret < 0) @@ -1460,6 +1474,7 @@ int ifilter_send_eof(InputFilter *ifilter, int64_t pts) int ifilter_send_frame(InputFilter *ifilter, AVFrame *frame, int keep_reference) { + InputFilterPriv *ifp = ifp_from_ifilter(ifilter); FilterGraph *fg = ifilter->graph; AVFrameSideData *sd; int need_reinit, ret; @@ -1508,7 +1523,7 @@ int ifilter_send_frame(InputFilter *ifilter, AVFrame *frame, int keep_reference) if (!tmp) return AVERROR(ENOMEM); - ret = av_fifo_write(ifilter->frame_queue, &tmp, 1); + ret = av_fifo_write(ifp->frame_queue, &tmp, 1); if (ret < 0) av_frame_free(&tmp); From 0aada80e732e1ecfd6df249777e3dafc423fcda4 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Tue, 25 Apr 2023 23:55:44 +0200 Subject: [PATCH 0854/2172] fftools/ffmpeg_filter: keep track of filtergraph input timebase Will be useful in following commits. --- fftools/ffmpeg_filter.c | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/fftools/ffmpeg_filter.c b/fftools/ffmpeg_filter.c index 78789600bf7..43eb8c94a5f 100644 --- a/fftools/ffmpeg_filter.c +++ b/fftools/ffmpeg_filter.c @@ -55,6 +55,8 @@ static FilterGraphPriv *fgp_from_fg(FilterGraph *fg) typedef struct InputFilterPriv { InputFilter ifilter; + AVRational time_base; + AVFifo *frame_queue; } InputFilterPriv; @@ -971,13 +973,13 @@ static int sub2video_prepare(InputStream *ist, InputFilter *ifilter) static int configure_input_video_filter(FilterGraph *fg, InputFilter *ifilter, AVFilterInOut *in) { + InputFilterPriv *ifp = ifp_from_ifilter(ifilter); + AVFilterContext *last_filter; const AVFilter *buffer_filt = avfilter_get_by_name("buffer"); const AVPixFmtDescriptor *desc; InputStream *ist = ifilter->ist; InputFile *f = input_files[ist->file_index]; - AVRational tb = ist->framerate.num ? av_inv_q(ist->framerate) : - ist->st->time_base; AVRational fr = ist->framerate; AVRational sar; AVBPrint args; @@ -1006,6 +1008,9 @@ static int configure_input_video_filter(FilterGraph *fg, InputFilter *ifilter, goto fail; } + ifp->time_base = ist->framerate.num ? av_inv_q(ist->framerate) : + ist->st->time_base; + sar = ifilter->sample_aspect_ratio; if(!sar.den) sar = (AVRational){0,1}; @@ -1014,7 +1019,7 @@ static int configure_input_video_filter(FilterGraph *fg, InputFilter *ifilter, "video_size=%dx%d:pix_fmt=%d:time_base=%d/%d:" "pixel_aspect=%d/%d", ifilter->width, ifilter->height, ifilter->format, - tb.num, tb.den, sar.num, sar.den); + ifp->time_base.num, ifp->time_base.den, sar.num, sar.den); if (fr.num && fr.den) av_bprintf(&args, ":frame_rate=%d/%d", fr.num, fr.den); snprintf(name, sizeof(name), "graph %d input from stream %d:%d", fg->index, @@ -1096,6 +1101,7 @@ static int configure_input_video_filter(FilterGraph *fg, InputFilter *ifilter, static int configure_input_audio_filter(FilterGraph *fg, InputFilter *ifilter, AVFilterInOut *in) { + InputFilterPriv *ifp = ifp_from_ifilter(ifilter); AVFilterContext *last_filter; const AVFilter *abuffer_filt = avfilter_get_by_name("abuffer"); InputStream *ist = ifilter->ist; @@ -1110,9 +1116,11 @@ static int configure_input_audio_filter(FilterGraph *fg, InputFilter *ifilter, return AVERROR(EINVAL); } + ifp->time_base = (AVRational){ 1, ifilter->sample_rate }; + av_bprint_init(&args, 0, AV_BPRINT_SIZE_AUTOMATIC); av_bprintf(&args, "time_base=%d/%d:sample_rate=%d:sample_fmt=%s", - 1, ifilter->sample_rate, + ifp->time_base.num, ifp->time_base.den, ifilter->sample_rate, av_get_sample_fmt_name(ifilter->format)); if (av_channel_layout_check(&ifilter->ch_layout) && From 5b3aeab1bd04e0c63b1c7a342874b5feefafa467 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Wed, 26 Apr 2023 00:00:02 +0200 Subject: [PATCH 0855/2172] fftools/ffmpeg_filter: use correct timebase for filter EOF timestamp It does not need to be equal to demuxer timebase. --- fftools/ffmpeg.c | 5 +---- fftools/ffmpeg.h | 2 +- fftools/ffmpeg_filter.c | 6 +++++- 3 files changed, 7 insertions(+), 6 deletions(-) diff --git a/fftools/ffmpeg.c b/fftools/ffmpeg.c index 453d3763be3..eae0093cce6 100644 --- a/fftools/ffmpeg.c +++ b/fftools/ffmpeg.c @@ -1320,12 +1320,9 @@ static int transcode_subtitles(InputStream *ist, const AVPacket *pkt, static int send_filter_eof(InputStream *ist) { int i, ret; - /* TODO keep pts also in stream time base to avoid converting back */ - int64_t pts = av_rescale_q_rnd(ist->pts, AV_TIME_BASE_Q, ist->st->time_base, - AV_ROUND_NEAR_INF | AV_ROUND_PASS_MINMAX); for (i = 0; i < ist->nb_filters; i++) { - ret = ifilter_send_eof(ist->filters[i], pts); + ret = ifilter_send_eof(ist->filters[i], ist->pts, AV_TIME_BASE_Q); if (ret < 0) return ret; } diff --git a/fftools/ffmpeg.h b/fftools/ffmpeg.h index 07322fdd794..c07a1b86b62 100644 --- a/fftools/ffmpeg.h +++ b/fftools/ffmpeg.h @@ -788,7 +788,7 @@ int init_complex_filtergraph(FilterGraph *fg); void sub2video_update(InputStream *ist, int64_t heartbeat_pts, AVSubtitle *sub); int ifilter_send_frame(InputFilter *ifilter, AVFrame *frame, int keep_reference); -int ifilter_send_eof(InputFilter *ifilter, int64_t pts); +int ifilter_send_eof(InputFilter *ifilter, int64_t pts, AVRational tb); int ifilter_parameters_from_codecpar(InputFilter *ifilter, AVCodecParameters *par); int ifilter_has_all_input_formats(FilterGraph *fg); diff --git a/fftools/ffmpeg_filter.c b/fftools/ffmpeg_filter.c index 43eb8c94a5f..8c408eb7c41 100644 --- a/fftools/ffmpeg_filter.c +++ b/fftools/ffmpeg_filter.c @@ -1454,13 +1454,17 @@ int reap_filters(int flush) return 0; } -int ifilter_send_eof(InputFilter *ifilter, int64_t pts) +int ifilter_send_eof(InputFilter *ifilter, int64_t pts, AVRational tb) { + InputFilterPriv *ifp = ifp_from_ifilter(ifilter); int ret; ifilter->eof = 1; if (ifilter->filter) { + pts = av_rescale_q_rnd(pts, tb, ifp->time_base, + AV_ROUND_NEAR_INF | AV_ROUND_PASS_MINMAX); + ret = av_buffersrc_close(ifilter->filter, pts, AV_BUFFERSRC_FLAG_PUSH); if (ret < 0) return ret; From b6e7d6439462e187e4725b611bd996d3ba939df6 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Sat, 22 Apr 2023 17:04:37 +0200 Subject: [PATCH 0856/2172] fftools/ffmpeg: stop using packet pts for decoded audio frame pts If input packets have timestamps, they will be propagated to output frames by the decoder, so at best this block does not do anything. There can also be an arbitrary amount of delay between packets sent to the decoder and decoded frames (e.g. due to decoder's intrinsic delay or frame threading), so deriving any timestamps from packet properties is wrong. --- fftools/ffmpeg.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/fftools/ffmpeg.c b/fftools/ffmpeg.c index eae0093cce6..5913a57d16b 100644 --- a/fftools/ffmpeg.c +++ b/fftools/ffmpeg.c @@ -911,9 +911,6 @@ static int decode_audio(InputStream *ist, AVPacket *pkt, int *got_output, if (decoded_frame->pts != AV_NOPTS_VALUE) { decoded_frame_tb = ist->st->time_base; - } else if (pkt && pkt->pts != AV_NOPTS_VALUE) { - decoded_frame->pts = pkt->pts; - decoded_frame_tb = pkt->time_base; }else { decoded_frame->pts = ist->dts; decoded_frame_tb = AV_TIME_BASE_Q; From 6bbea932ca9a0f124b713bef361a9e4ef19d2583 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Sat, 22 Apr 2023 16:42:12 +0200 Subject: [PATCH 0857/2172] fftools/ffmpeg: set AVFrame.time_base for decoded frames Makes it easier to keep track of the timebase the frames are in. --- fftools/ffmpeg.c | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/fftools/ffmpeg.c b/fftools/ffmpeg.c index 5913a57d16b..8829a163e02 100644 --- a/fftools/ffmpeg.c +++ b/fftools/ffmpeg.c @@ -855,6 +855,8 @@ static int decode(InputStream *ist, AVCodecContext *avctx, fd->idx = avctx->frame_num - 1; } + frame->time_base = avctx->pkt_timebase; + *got_frame = 1; } @@ -885,7 +887,6 @@ static int decode_audio(InputStream *ist, AVPacket *pkt, int *got_output, AVFrame *decoded_frame = ist->decoded_frame; AVCodecContext *avctx = ist->dec_ctx; int ret, err = 0; - AVRational decoded_frame_tb; update_benchmark(NULL); ret = decode(ist, avctx, decoded_frame, got_output, pkt); @@ -909,23 +910,24 @@ static int decode_audio(InputStream *ist, AVPacket *pkt, int *got_output, ist->next_dts += ((int64_t)AV_TIME_BASE * decoded_frame->nb_samples) / decoded_frame->sample_rate; - if (decoded_frame->pts != AV_NOPTS_VALUE) { - decoded_frame_tb = ist->st->time_base; - }else { + if (decoded_frame->pts == AV_NOPTS_VALUE) { decoded_frame->pts = ist->dts; - decoded_frame_tb = AV_TIME_BASE_Q; + decoded_frame->time_base = 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, decoded_frame->sample_rate}, - decoded_frame->nb_samples, + if (decoded_frame->pts != AV_NOPTS_VALUE) { + AVRational tb_filter = (AVRational){1, decoded_frame->sample_rate}; + decoded_frame->pts = av_rescale_delta(decoded_frame->time_base, decoded_frame->pts, + tb_filter, decoded_frame->nb_samples, &ist->filter_in_rescale_delta_last, - (AVRational){1, decoded_frame->sample_rate}); + tb_filter); + decoded_frame->time_base = tb_filter; + } + ist->nb_samples = decoded_frame->nb_samples; err = send_frame_to_filters(ist, decoded_frame); From d85c6aba0cf27db2a6c4dfa3452cfb9c248d1b4a Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Mon, 24 Apr 2023 12:28:13 +0200 Subject: [PATCH 0858/2172] fftools/ffmpeg: rework audio-decode timestamp handling Stop using InputStream.dts for generating missing timestamps for decoded frames, because it contains pre-decoding timestamps and there may be arbitrary amount of delay between input packets and output frames (e.g. dependent on the thread count when frame threading is used). It is also in AV_TIME_BASE (i.e. microseconds), which may introduce unnecessary rounding issues. New code maintains a timebase that is the inverse of the LCM of all the samplerates seen so far, and thus can accurately represent every audio sample. This timebase is used to generate missing timestamps after decoding. Changes the result of the following FATE tests * pcm_dvd-16-5.1-96000 * lavf-smjpeg * adpcm-ima-smjpeg In all of these the timestamps now better correspond to actual frame durations. --- fftools/ffmpeg.c | 98 ++++- fftools/ffmpeg.h | 8 +- fftools/ffmpeg_demux.c | 6 +- tests/ref/fate/adpcm-ima-smjpeg | 658 ++++++++++++++-------------- tests/ref/fate/pcm_dvd-16-5.1-96000 | 8 +- tests/ref/lavf/smjpeg | 2 +- 6 files changed, 423 insertions(+), 357 deletions(-) diff --git a/fftools/ffmpeg.c b/fftools/ffmpeg.c index 8829a163e02..8dcc70e879a 100644 --- a/fftools/ffmpeg.c +++ b/fftools/ffmpeg.c @@ -881,6 +881,85 @@ static int send_frame_to_filters(InputStream *ist, AVFrame *decoded_frame) return ret; } +static AVRational audio_samplerate_update(InputStream *ist, const AVFrame *frame) +{ + const int prev = ist->last_frame_tb.den; + const int sr = frame->sample_rate; + + AVRational tb_new; + int64_t gcd; + + if (frame->sample_rate == ist->last_frame_sample_rate) + goto finish; + + gcd = av_gcd(prev, sr); + + if (prev / gcd >= INT_MAX / sr) { + av_log(ist, AV_LOG_WARNING, + "Audio timestamps cannot be represented exactly after " + "sample rate change: %d -> %d\n", prev, sr); + + // LCM of 192000, 44100, allows to represent all common samplerates + tb_new = (AVRational){ 1, 28224000 }; + } else + tb_new = (AVRational){ 1, prev / gcd * sr }; + + // keep the frame timebase if it is strictly better than + // the samplerate-defined one + if (frame->time_base.num == 1 && frame->time_base.den > tb_new.den && + !(frame->time_base.den % tb_new.den)) + tb_new = frame->time_base; + + if (ist->last_frame_pts != AV_NOPTS_VALUE) + ist->last_frame_pts = av_rescale_q(ist->last_frame_pts, + ist->last_frame_tb, tb_new); + ist->last_frame_duration_est = av_rescale_q(ist->last_frame_duration_est, + ist->last_frame_tb, tb_new); + + ist->last_frame_tb = tb_new; + ist->last_frame_sample_rate = frame->sample_rate; + +finish: + return ist->last_frame_tb; +} + +static void audio_ts_process(InputStream *ist, AVFrame *frame) +{ + AVRational tb_filter = (AVRational){1, frame->sample_rate}; + AVRational tb; + int64_t pts_pred; + + // on samplerate change, choose a new internal timebase for timestamp + // generation that can represent timestamps from all the samplerates + // seen so far + tb = audio_samplerate_update(ist, frame); + pts_pred = ist->last_frame_pts == AV_NOPTS_VALUE ? 0 : + ist->last_frame_pts + ist->last_frame_duration_est; + + if (frame->pts == AV_NOPTS_VALUE) { + frame->pts = pts_pred; + frame->time_base = tb; + } else if (ist->last_frame_pts != AV_NOPTS_VALUE && + frame->pts > av_rescale_q_rnd(pts_pred, tb, frame->time_base, + AV_ROUND_UP)) { + // there was a gap in timestamps, reset conversion state + ist->filter_in_rescale_delta_last = AV_NOPTS_VALUE; + } + + frame->pts = av_rescale_delta(frame->time_base, frame->pts, + tb, frame->nb_samples, + &ist->filter_in_rescale_delta_last, tb); + + ist->last_frame_pts = frame->pts; + ist->last_frame_duration_est = av_rescale_q(frame->nb_samples, + tb_filter, tb); + + // finally convert to filtering timebase + frame->pts = av_rescale_q(frame->pts, tb, tb_filter); + frame->duration = frame->nb_samples; + frame->time_base = tb_filter; +} + static int decode_audio(InputStream *ist, AVPacket *pkt, int *got_output, int *decode_failed) { @@ -910,23 +989,7 @@ static int decode_audio(InputStream *ist, AVPacket *pkt, int *got_output, ist->next_dts += ((int64_t)AV_TIME_BASE * decoded_frame->nb_samples) / decoded_frame->sample_rate; - if (decoded_frame->pts == AV_NOPTS_VALUE) { - decoded_frame->pts = ist->dts; - decoded_frame->time_base = 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) { - AVRational tb_filter = (AVRational){1, decoded_frame->sample_rate}; - decoded_frame->pts = av_rescale_delta(decoded_frame->time_base, decoded_frame->pts, - tb_filter, decoded_frame->nb_samples, - &ist->filter_in_rescale_delta_last, - tb_filter); - decoded_frame->time_base = tb_filter; - } + audio_ts_process(ist, decoded_frame); ist->nb_samples = decoded_frame->nb_samples; err = send_frame_to_filters(ist, decoded_frame); @@ -1076,6 +1139,7 @@ static int decode_video(InputStream *ist, AVPacket *pkt, int *got_output, int64_ // update timestamp history ist->last_frame_duration_est = video_duration_estimate(ist, decoded_frame); ist->last_frame_pts = decoded_frame->pts; + ist->last_frame_tb = decoded_frame->time_base; if (debug_ts) { av_log(ist, AV_LOG_INFO, diff --git a/fftools/ffmpeg.h b/fftools/ffmpeg.h index c07a1b86b62..c4abf89b584 100644 --- a/fftools/ffmpeg.h +++ b/fftools/ffmpeg.h @@ -359,7 +359,6 @@ typedef struct InputStream { AVRational framerate_guessed; - 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) */ @@ -371,10 +370,13 @@ typedef struct InputStream { int64_t next_pts; int64_t pts; ///< current pts of the decoded frame (in AV_TIME_BASE units) - // pts/estimated duration of the last decoded video frame - // in decoder timebase + // pts/estimated duration of the last decoded frame + // * in decoder timebase for video, + // * in last_frame_tb (may change during decoding) for audio int64_t last_frame_pts; int64_t last_frame_duration_est; + AVRational last_frame_tb; + int last_frame_sample_rate; int wrap_correction_done; diff --git a/fftools/ffmpeg_demux.c b/fftools/ffmpeg_demux.c index 5afb3ff2c82..f8d95d1de67 100644 --- a/fftools/ffmpeg_demux.c +++ b/fftools/ffmpeg_demux.c @@ -864,7 +864,9 @@ static void add_input_streams(const OptionsContext *o, Demuxer *d) } ist->filter_in_rescale_delta_last = AV_NOPTS_VALUE; - ist->prev_pkt_pts = AV_NOPTS_VALUE; + + ist->last_frame_pts = AV_NOPTS_VALUE; + ist->last_frame_tb = (AVRational){ 1, 1 }; ist->dec_ctx = avcodec_alloc_context3(ist->dec); if (!ist->dec_ctx) @@ -905,8 +907,6 @@ static void add_input_streams(const OptionsContext *o, Demuxer *d) ist->framerate_guessed = av_guess_frame_rate(ic, st, NULL); - ist->last_frame_pts = AV_NOPTS_VALUE; - break; case AVMEDIA_TYPE_AUDIO: { int guess_layout_max = INT_MAX; diff --git a/tests/ref/fate/adpcm-ima-smjpeg b/tests/ref/fate/adpcm-ima-smjpeg index 723fa2336ec..b9cf1f38db4 100644 --- a/tests/ref/fate/adpcm-ima-smjpeg +++ b/tests/ref/fate/adpcm-ima-smjpeg @@ -8,348 +8,348 @@ 0, 1024, 1024, 512, 1024, 0xed2d3f6b 0, 1533, 1533, 512, 1024, 0x51f6ccb3 0, 2040, 2040, 512, 1024, 0x58bd75aa -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, 2552, 2552, 512, 1024, 0xd857a310 +0, 3064, 3064, 512, 1024, 0xc483a5b8 +0, 3576, 3576, 512, 1024, 0x923ecf67 +0, 4088, 4088, 512, 1024, 0xf87dcd53 0, 4598, 4598, 512, 1024, 0xdc32c002 -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, 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, 9206, 9206, 512, 1024, 0xb35dc9f2 -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, 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, 25590, 25590, 512, 1024, 0x51fae08e -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, 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, 30198, 30198, 512, 1024, 0xc764ce80 -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, 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, 34806, 34806, 512, 1024, 0xe009f343 -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, 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, 51190, 51190, 512, 1024, 0x6d16ea0e -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, 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, 55798, 55798, 512, 1024, 0x9399f10d -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, 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, 60406, 60406, 512, 1024, 0x50b5f1a6 -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, 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, 76790, 76790, 512, 1024, 0x7d08dd54 -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, 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, 81398, 81398, 512, 1024, 0x34f3f2bd -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, 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, 102390, 102390, 512, 1024, 0x95d5e8d9 -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, 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, 106998, 106998, 512, 1024, 0x86b6d93b -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, 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, 127990, 127990, 512, 1024, 0xd124db3e -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, 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, 132598, 132598, 512, 1024, 0xfc59d2d2 -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, 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, 153590, 153590, 512, 1024, 0x34eddc80 -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, 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, 158198, 158198, 512, 1024, 0x9cb9d040 -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 +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 diff --git a/tests/ref/fate/pcm_dvd-16-5.1-96000 b/tests/ref/fate/pcm_dvd-16-5.1-96000 index 64447a9aa58..68dce2d3a6b 100644 --- a/tests/ref/fate/pcm_dvd-16-5.1-96000 +++ b/tests/ref/fate/pcm_dvd-16-5.1-96000 @@ -13,7 +13,7 @@ d8e182dfa46524c28d1f78a4cc1f2719 *tests/data/fate/pcm_dvd-16-5.1-96000.vob 0, 835, 835, 167, 2004, 0x00000000 0, 1002, 1002, 167, 2004, 0x00000000 0, 1169, 1169, 167, 2004, 0x00000000 -0, 1337, 1337, 167, 2004, 0x00000000 +0, 1336, 1336, 167, 2004, 0x00000000 0, 1503, 1503, 167, 2004, 0x00000000 0, 1670, 1670, 167, 2004, 0x00000000 0, 1837, 1837, 167, 2004, 0x00000000 @@ -29,7 +29,7 @@ d8e182dfa46524c28d1f78a4cc1f2719 *tests/data/fate/pcm_dvd-16-5.1-96000.vob 0, 3507, 3507, 167, 2004, 0x00000000 0, 3674, 3674, 167, 2004, 0x00000000 0, 3841, 3841, 167, 2004, 0x00000000 -0, 4009, 4009, 167, 2004, 0x00000000 +0, 4008, 4008, 167, 2004, 0x00000000 0, 4175, 4175, 167, 2004, 0x00000000 0, 4342, 4342, 167, 2004, 0x00000000 0, 4509, 4509, 167, 2004, 0x00000000 @@ -45,7 +45,7 @@ d8e182dfa46524c28d1f78a4cc1f2719 *tests/data/fate/pcm_dvd-16-5.1-96000.vob 0, 6179, 6179, 167, 2004, 0x00000000 0, 6346, 6346, 167, 2004, 0x00000000 0, 6513, 6513, 167, 2004, 0x00000000 -0, 6681, 6681, 166, 1992, 0x00000000 -0, 6847, 6847, 167, 2004, 0x00000000 +0, 6680, 6680, 166, 1992, 0x00000000 +0, 6846, 6846, 167, 2004, 0x00000000 0, 7014, 7014, 167, 2004, 0x00000000 0, 7181, 7181, 101, 1212, 0x00000000 diff --git a/tests/ref/lavf/smjpeg b/tests/ref/lavf/smjpeg index 94172a6b1e4..537c0847cb8 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=0x75066147 +tests/data/lavf/lavf.smjpeg CRC=0x54bf6147 From ef69f6a9d24e5508294f4009b1011289c683284e Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Tue, 25 Apr 2023 23:11:25 +0200 Subject: [PATCH 0859/2172] fftools/ffmpeg: stop using InputStream.pts for generating video timestamps This was added in 380db569287ba99d903b7629f209b9adc7fd2723 as a temporary crutch that is not needed anymore. The only case where this code can be triggered is the very first frame, for which InputStream.pts is always equal to 0. --- fftools/ffmpeg.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/fftools/ffmpeg.c b/fftools/ffmpeg.c index 8dcc70e879a..e9b083b05a1 100644 --- a/fftools/ffmpeg.c +++ b/fftools/ffmpeg.c @@ -1122,12 +1122,9 @@ static int decode_video(InputStream *ist, AVPacket *pkt, int *got_output, int64_ best_effort_timestamp = ist->cfr_next_pts++; // no timestamp available - extrapolate from previous frame duration - if (best_effort_timestamp == AV_NOPTS_VALUE && - ist->last_frame_pts != AV_NOPTS_VALUE) - best_effort_timestamp = ist->last_frame_pts + ist->last_frame_duration_est; - if (best_effort_timestamp == AV_NOPTS_VALUE) - best_effort_timestamp = av_rescale_q(ist->pts, AV_TIME_BASE_Q, ist->st->time_base); + best_effort_timestamp = ist->last_frame_pts == AV_NOPTS_VALUE ? 0 : + ist->last_frame_pts + ist->last_frame_duration_est; if(best_effort_timestamp != AV_NOPTS_VALUE) { int64_t ts = av_rescale_q(decoded_frame->pts = best_effort_timestamp, ist->st->time_base, AV_TIME_BASE_Q); From ae95cd85dc73319a704f1092b7542978ef8869dd Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Wed, 26 Apr 2023 00:09:50 +0200 Subject: [PATCH 0860/2172] fftools/ffmpeg_filter: stop using InputStream.pts for filter EOF ts Use InputStream.last_frame_pts/duration instead, which is more accurate. --- fftools/ffmpeg.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/fftools/ffmpeg.c b/fftools/ffmpeg.c index e9b083b05a1..3a0d1b45591 100644 --- a/fftools/ffmpeg.c +++ b/fftools/ffmpeg.c @@ -1382,7 +1382,9 @@ static int send_filter_eof(InputStream *ist) int i, ret; for (i = 0; i < ist->nb_filters; i++) { - ret = ifilter_send_eof(ist->filters[i], ist->pts, AV_TIME_BASE_Q); + int64_t end_pts = ist->last_frame_pts == AV_NOPTS_VALUE ? AV_NOPTS_VALUE : + ist->last_frame_pts + ist->last_frame_duration_est; + ret = ifilter_send_eof(ist->filters[i], end_pts, ist->last_frame_tb); if (ret < 0) return ret; } From 302aecd06a07ee4eac7486167992fa18f0447232 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Wed, 26 Apr 2023 00:11:59 +0200 Subject: [PATCH 0861/2172] fftools/ffmpeg: drop InputStream.[next_]pts They are no longer used for anything. --- fftools/ffmpeg.c | 20 +------------------- fftools/ffmpeg.h | 4 ---- fftools/ffmpeg_demux.c | 1 - 3 files changed, 1 insertion(+), 24 deletions(-) diff --git a/fftools/ffmpeg.c b/fftools/ffmpeg.c index 3a0d1b45591..e766301535c 100644 --- a/fftools/ffmpeg.c +++ b/fftools/ffmpeg.c @@ -984,8 +984,6 @@ static int decode_audio(InputStream *ist, AVPacket *pkt, int *got_output, /* increment next_dts to use for the case where the input stream does not have timestamps or there are multiple frames in the packet */ - ist->next_pts += ((int64_t)AV_TIME_BASE * decoded_frame->nb_samples) / - decoded_frame->sample_rate; ist->next_dts += ((int64_t)AV_TIME_BASE * decoded_frame->nb_samples) / decoded_frame->sample_rate; @@ -1127,10 +1125,7 @@ static int decode_video(InputStream *ist, AVPacket *pkt, int *got_output, int64_ ist->last_frame_pts + ist->last_frame_duration_est; if(best_effort_timestamp != AV_NOPTS_VALUE) { - int64_t ts = av_rescale_q(decoded_frame->pts = best_effort_timestamp, ist->st->time_base, AV_TIME_BASE_Q); - - if (ts != AV_NOPTS_VALUE) - ist->next_pts = ist->pts = ts; + decoded_frame->pts = best_effort_timestamp; } // update timestamp history @@ -1406,7 +1401,6 @@ static int process_input_packet(InputStream *ist, const AVPacket *pkt, int no_eo if (!ist->saw_first_ts) { ist->first_dts = ist->dts = ist->st->avg_frame_rate.num ? - ist->dec_ctx->has_b_frames * AV_TIME_BASE / av_q2d(ist->st->avg_frame_rate) : 0; - ist->pts = 0; if (pkt && pkt->pts != AV_NOPTS_VALUE && !ist->decoding_needed) { ist->first_dts = ist->dts += av_rescale_q(pkt->pts, pkt->time_base, AV_TIME_BASE_Q); @@ -1416,8 +1410,6 @@ static int process_input_packet(InputStream *ist, const AVPacket *pkt, int no_eo if (ist->next_dts == AV_NOPTS_VALUE) ist->next_dts = ist->dts; - if (ist->next_pts == AV_NOPTS_VALUE) - ist->next_pts = ist->pts; if (pkt) { av_packet_unref(avpkt); @@ -1428,8 +1420,6 @@ static int process_input_packet(InputStream *ist, const AVPacket *pkt, int no_eo if (pkt && pkt->dts != AV_NOPTS_VALUE) { ist->next_dts = ist->dts = av_rescale_q(pkt->dts, pkt->time_base, AV_TIME_BASE_Q); - if (par->codec_type != AVMEDIA_TYPE_VIDEO) - ist->pts = ist->dts; } // while we have more to decode or while the decoder did output something on EOF @@ -1439,7 +1429,6 @@ static int process_input_packet(InputStream *ist, const AVPacket *pkt, int no_eo int got_output = 0; int decode_failed = 0; - ist->pts = ist->next_pts; ist->dts = ist->next_dts; switch (par->codec_type) { @@ -1469,13 +1458,6 @@ static int process_input_packet(InputStream *ist, const AVPacket *pkt, int no_eo ist->next_dts = AV_NOPTS_VALUE; } - if (got_output) { - if (duration_pts > 0) { - ist->next_pts += av_rescale_q(duration_pts, ist->st->time_base, AV_TIME_BASE_Q); - } else { - ist->next_pts += duration_dts; - } - } av_packet_unref(avpkt); break; case AVMEDIA_TYPE_SUBTITLE: diff --git a/fftools/ffmpeg.h b/fftools/ffmpeg.h index c4abf89b584..b6389d7f99e 100644 --- a/fftools/ffmpeg.h +++ b/fftools/ffmpeg.h @@ -366,10 +366,6 @@ typedef struct InputStream { int64_t first_dts; ///< dts of the first packet read for this stream (in AV_TIME_BASE units) int64_t dts; ///< dts of the last packet read for this stream (in AV_TIME_BASE units) - /* predicted pts of the next decoded frame, in AV_TIME_BASE */ - int64_t next_pts; - int64_t pts; ///< current pts of the decoded frame (in AV_TIME_BASE units) - // pts/estimated duration of the last decoded frame // * in decoder timebase for video, // * in last_frame_tb (may change during decoding) for audio diff --git a/fftools/ffmpeg_demux.c b/fftools/ffmpeg_demux.c index f8d95d1de67..26426c7ac16 100644 --- a/fftools/ffmpeg_demux.c +++ b/fftools/ffmpeg_demux.c @@ -744,7 +744,6 @@ static void add_input_streams(const OptionsContext *o, Demuxer *d) st->discard = AVDISCARD_ALL; ist->nb_samples = 0; ist->first_dts = AV_NOPTS_VALUE; - ist->next_pts = AV_NOPTS_VALUE; ist->next_dts = AV_NOPTS_VALUE; ds->min_pts = INT64_MAX; From 3190bed148df57740ef818764979d60dde53d3d0 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Wed, 26 Apr 2023 10:05:26 +0200 Subject: [PATCH 0862/2172] fftools/ffmpeg: constify packets passed to decode*() They are not modified by these functions. --- fftools/ffmpeg.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/fftools/ffmpeg.c b/fftools/ffmpeg.c index e766301535c..bb8c6bf00cc 100644 --- a/fftools/ffmpeg.c +++ b/fftools/ffmpeg.c @@ -822,7 +822,7 @@ int ifilter_has_all_input_formats(FilterGraph *fg) // it again with pkt=NULL. pkt==NULL is treated differently from pkt->size==0 // (pkt==NULL means get more output, pkt->size==0 is a flush/drain packet) static int decode(InputStream *ist, AVCodecContext *avctx, - AVFrame *frame, int *got_frame, AVPacket *pkt) + AVFrame *frame, int *got_frame, const AVPacket *pkt) { int ret; @@ -960,7 +960,7 @@ static void audio_ts_process(InputStream *ist, AVFrame *frame) frame->time_base = tb_filter; } -static int decode_audio(InputStream *ist, AVPacket *pkt, int *got_output, +static int decode_audio(InputStream *ist, const AVPacket *pkt, int *got_output, int *decode_failed) { AVFrame *decoded_frame = ist->decoded_frame; @@ -1048,8 +1048,8 @@ static int64_t video_duration_estimate(const InputStream *ist, const AVFrame *fr return FFMAX(ist->last_frame_duration_est, 1); } -static int decode_video(InputStream *ist, AVPacket *pkt, int *got_output, int64_t *duration_pts, int eof, - int *decode_failed) +static int decode_video(InputStream *ist, const AVPacket *pkt, int *got_output, + int64_t *duration_pts, int eof, int *decode_failed) { AVFrame *decoded_frame = ist->decoded_frame; int ret = 0, err = 0; From 129c7bf53fbe2be4f5483ecf6fc036ff9caf05cf Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Wed, 26 Apr 2023 10:51:38 +0200 Subject: [PATCH 0863/2172] fftools/ffmpeg: always use the same path for setting InputStream.[next_]dts Currently those are set in different ways depending on whether the stream is decoded or not, using some values from the decoder if it is. This is wrong, because there may be arbitrary amount of delay between input packets and output frames (depending e.g. on the thread count when frame threading is used). Always use the path that was previously used only for streamcopy. This should not cause any issues, because these values are now used only for streamcopy and discontinuity handling. This change will allow to decouple discontinuity processing from decoding and move it to ffmpeg_demux. It also makes the code simpler. Changes output in fate-cover-art-aiff-id3v2-remux and fate-cover-art-mp3-id3v2-remux, where attached pictures are now written in the correct order. This happens because InputStream.dts is no longer reset to AV_NOPTS_VALUE after decoding, so streamcopy actually sees valid dts values. --- fftools/ffmpeg.c | 34 ++++------------------- tests/ref/fate/cover-art-aiff-id3v2-remux | 34 +++++++++++------------ tests/ref/fate/cover-art-mp3-id3v2-remux | 22 +++++++-------- 3 files changed, 33 insertions(+), 57 deletions(-) diff --git a/fftools/ffmpeg.c b/fftools/ffmpeg.c index bb8c6bf00cc..be9a3b2e34a 100644 --- a/fftools/ffmpeg.c +++ b/fftools/ffmpeg.c @@ -982,11 +982,6 @@ static int decode_audio(InputStream *ist, const AVPacket *pkt, int *got_output, ist->samples_decoded += decoded_frame->nb_samples; ist->frames_decoded++; - /* increment next_dts to use for the case where the input stream does not - have timestamps or there are multiple frames in the packet */ - ist->next_dts += ((int64_t)AV_TIME_BASE * decoded_frame->nb_samples) / - decoded_frame->sample_rate; - audio_ts_process(ist, decoded_frame); ist->nb_samples = decoded_frame->nb_samples; @@ -1401,7 +1396,7 @@ static int process_input_packet(InputStream *ist, const AVPacket *pkt, int no_eo if (!ist->saw_first_ts) { ist->first_dts = ist->dts = ist->st->avg_frame_rate.num ? - ist->dec_ctx->has_b_frames * AV_TIME_BASE / av_q2d(ist->st->avg_frame_rate) : 0; - if (pkt && pkt->pts != AV_NOPTS_VALUE && !ist->decoding_needed) { + if (pkt && pkt->pts != AV_NOPTS_VALUE) { ist->first_dts = ist->dts += av_rescale_q(pkt->pts, pkt->time_base, AV_TIME_BASE_Q); } @@ -1424,13 +1419,10 @@ static int process_input_packet(InputStream *ist, const AVPacket *pkt, int no_eo // while we have more to decode or while the decoder did output something on EOF while (ist->decoding_needed) { - int64_t duration_dts = 0; int64_t duration_pts = 0; int got_output = 0; int decode_failed = 0; - ist->dts = ist->next_dts; - switch (par->codec_type) { case AVMEDIA_TYPE_AUDIO: ret = decode_audio (ist, repeating ? NULL : avpkt, &got_output, @@ -1440,23 +1432,6 @@ static int process_input_packet(InputStream *ist, const AVPacket *pkt, int no_eo case AVMEDIA_TYPE_VIDEO: ret = decode_video (ist, repeating ? NULL : avpkt, &got_output, &duration_pts, !pkt, &decode_failed); - if (!repeating || !pkt || got_output) { - if (pkt && pkt->duration) { - duration_dts = av_rescale_q(pkt->duration, pkt->time_base, AV_TIME_BASE_Q); - } else if(ist->dec_ctx->framerate.num != 0 && ist->dec_ctx->framerate.den != 0) { - int ticks = ist->last_pkt_repeat_pict >= 0 ? - ist->last_pkt_repeat_pict + 1 : - ist->dec_ctx->ticks_per_frame; - duration_dts = ((int64_t)AV_TIME_BASE * - ist->dec_ctx->framerate.den * ticks) / - ist->dec_ctx->framerate.num / ist->dec_ctx->ticks_per_frame; - } - - if(ist->dts != AV_NOPTS_VALUE && duration_dts) { - ist->next_dts += duration_dts; - }else - ist->next_dts = AV_NOPTS_VALUE; - } av_packet_unref(avpkt); break; @@ -1520,8 +1495,7 @@ static int process_input_packet(InputStream *ist, const AVPacket *pkt, int no_eo } } - /* handle stream copy */ - if (!ist->decoding_needed && pkt) { + if (pkt) { ist->dts = ist->next_dts; switch (par->codec_type) { case AVMEDIA_TYPE_AUDIO: @@ -1551,7 +1525,9 @@ static int process_input_packet(InputStream *ist, const AVPacket *pkt, int no_eo } break; } - } else if (!ist->decoding_needed) + } + + if (!pkt && !ist->decoding_needed) eof_reached = 1; duration_exceeded = 0; diff --git a/tests/ref/fate/cover-art-aiff-id3v2-remux b/tests/ref/fate/cover-art-aiff-id3v2-remux index 3ca2855eb80..a59ba37c653 100644 --- a/tests/ref/fate/cover-art-aiff-id3v2-remux +++ b/tests/ref/fate/cover-art-aiff-id3v2-remux @@ -1,4 +1,4 @@ -d4a9481090a8bab1a3f072a8108a1d6a *tests/data/fate/cover-art-aiff-id3v2-remux.aiff +330ad2bf538e91a31752b38024461df1 *tests/data/fate/cover-art-aiff-id3v2-remux.aiff 608914 tests/data/fate/cover-art-aiff-id3v2-remux.aiff #tb 0: 1/44100 #media_type 0: audio @@ -12,24 +12,24 @@ d4a9481090a8bab1a3f072a8108a1d6a *tests/data/fate/cover-art-aiff-id3v2-remux.aif #sar 1: 1/1 #tb 2: 1/90000 #media_type 2: video -#codec_id 2: mjpeg +#codec_id 2: png #dimensions 2: 350x350 #sar 2: 1/1 #tb 3: 1/90000 #media_type 3: video -#codec_id 3: png +#codec_id 3: bmp #dimensions 3: 350x350 -#sar 3: 1/1 +#sar 3: 0/1 #tb 4: 1/90000 #media_type 4: video -#codec_id 4: bmp +#codec_id 4: mjpeg #dimensions 4: 350x350 -#sar 4: 0/1 +#sar 4: 1/1 0, 0, 0, 1024, 4096, 0xdac4695d 1, 0, 0, 0, 19650, 0xd5662610 -2, 0, 0, 0, 19650, 0xd5662610 -3, 0, 0, 0, 184497, 0xc33f8d44 -4, 0, 0, 0, 368254, 0xfa7f4bd8 +2, 0, 0, 0, 184497, 0xc33f8d44 +3, 0, 0, 0, 368254, 0xfa7f4bd8 +4, 0, 0, 0, 19650, 0xd5662610 0, 1024, 1024, 1024, 4096, 0xad05c909 0, 2048, 2048, 1024, 4096, 0x97e3b8f8 0, 3072, 3072, 1024, 4096, 0xb08180fa @@ -47,25 +47,25 @@ TAG:comment=Other [/STREAM] [STREAM] index=2 -codec_name=mjpeg -DISPOSITION:attached_pic=1 -TAG:title=fourth -TAG:comment=Composer -[/STREAM] -[STREAM] -index=3 codec_name=png DISPOSITION:attached_pic=1 TAG:title=second TAG:comment=Illustration [/STREAM] [STREAM] -index=4 +index=3 codec_name=bmp DISPOSITION:attached_pic=1 TAG:title=third TAG:comment=Conductor [/STREAM] +[STREAM] +index=4 +codec_name=mjpeg +DISPOSITION:attached_pic=1 +TAG:title=fourth +TAG:comment=Composer +[/STREAM] [FORMAT] TAG:artist=Мельница TAG:RATING=0 diff --git a/tests/ref/fate/cover-art-mp3-id3v2-remux b/tests/ref/fate/cover-art-mp3-id3v2-remux index 906a6467994..52b7e72a569 100644 --- a/tests/ref/fate/cover-art-mp3-id3v2-remux +++ b/tests/ref/fate/cover-art-mp3-id3v2-remux @@ -1,4 +1,4 @@ -c1b55a9a92226cd72d3f53ccd830d127 *tests/data/fate/cover-art-mp3-id3v2-remux.mp3 +94946f0efd5f9bb0061ac1fbff7d731f *tests/data/fate/cover-art-mp3-id3v2-remux.mp3 399346 tests/data/fate/cover-art-mp3-id3v2-remux.mp3 #tb 0: 1/14112000 #media_type 0: audio @@ -7,22 +7,22 @@ c1b55a9a92226cd72d3f53ccd830d127 *tests/data/fate/cover-art-mp3-id3v2-remux.mp3 #channel_layout_name 0: stereo #tb 1: 1/90000 #media_type 1: video -#codec_id 1: mjpeg +#codec_id 1: bmp #dimensions 1: 263x263 -#sar 1: 96/96 +#sar 1: 0/1 #tb 2: 1/90000 #media_type 2: video -#codec_id 2: bmp +#codec_id 2: mjpeg #dimensions 2: 263x263 -#sar 2: 0/1 +#sar 2: 96/96 #tb 3: 1/90000 #media_type 3: video #codec_id 3: png #dimensions 3: 263x263 #sar 3: 1/1 0, -353590, -353590, 368640, 417, 0x15848290, S=1, 10 -1, 0, 0, 0, 15760, 0x71d5c418 -2, 0, 0, 0, 208350, 0x291b44d1 +1, 0, 0, 0, 208350, 0x291b44d1 +2, 0, 0, 0, 15760, 0x71d5c418 3, 0, 0, 0, 165671, 0x7c1c8070 0, 15050, 15050, 368640, 418, 0x46f684a4 0, 383690, 383690, 368640, 418, 0x46f684a4 @@ -36,15 +36,15 @@ TAG:encoder=Lavf [/STREAM] [STREAM] index=1 -codec_name=mjpeg +codec_name=bmp DISPOSITION:attached_pic=1 -TAG:comment=Other +TAG:comment=Band/Orchestra [/STREAM] [STREAM] index=2 -codec_name=bmp +codec_name=mjpeg DISPOSITION:attached_pic=1 -TAG:comment=Band/Orchestra +TAG:comment=Other [/STREAM] [STREAM] index=3 From 7dcb5e1ab09601e47447d54204c21bb2db720ef2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9mi=20Denis-Courmont?= Date: Thu, 20 Apr 2023 20:53:56 +0300 Subject: [PATCH 0864/2172] riscv/bswap: use compiler builtins av_bswapXX() are used in context that expect exact size types, notably variable arguments to av_log(). On Linux RV64, uint_fast32_t is an unsigned long, so the current inline assembler does not work properly. Since GCC and Clang gained their byte-swap built-ins before they supported RISC-V, we can simply defer to them. As an added bonus, the compiler can do instruction scheduling, which it couldn't with the Zbb inline assembler. --- libavutil/riscv/bswap.h | 52 ++++------------------------------------- 1 file changed, 5 insertions(+), 47 deletions(-) diff --git a/libavutil/riscv/bswap.h b/libavutil/riscv/bswap.h index de1429c0f7c..ce75de974e3 100644 --- a/libavutil/riscv/bswap.h +++ b/libavutil/riscv/bswap.h @@ -23,52 +23,10 @@ #include "config.h" #include "libavutil/attributes.h" -#if defined (__riscv_zbb) && (__riscv_zbb > 0) && HAVE_INLINE_ASM +#if defined (__GNUC__) || defined (__clang__) +#define av_bswap16 __builtin_bswap16 +#define av_bswap32 __builtin_bswap32 +#define av_bswap64 __builtin_bswap64 +#endif -static av_always_inline av_const uintptr_t av_bswap_xlen(uintptr_t x) -{ - uintptr_t y; - - __asm__("rev8 %0, %1" : "=r" (y) : "r" (x)); - return y; -} - -#define av_bswap16 av_bswap16 - -static av_always_inline av_const uint_fast16_t av_bswap16(uint_fast16_t x) -{ - return av_bswap_xlen(x) >> (__riscv_xlen - 16); -} - -#if (__riscv_xlen == 32) -#define av_bswap32 av_bswap_xlen -#define av_bswap64 av_bswap64 - -static av_always_inline av_const uint64_t av_bswap64(uint64_t x) -{ - return (((uint64_t)av_bswap32(x)) << 32) | av_bswap32(x >> 32); -} - -#else -#define av_bswap32 av_bswap32 - -static av_always_inline av_const uint_fast32_t av_bswap32(uint_fast32_t x) -{ - return av_bswap_xlen(x) >> (__riscv_xlen - 32); -} - -#if (__riscv_xlen == 64) -#define av_bswap64 av_bswap_xlen - -#else -#define av_bswap64 av_bswap64 - -static av_always_inline av_const uint_fast64_t av_bswap64(uint_fast64_t x) -{ - return av_bswap_xlen(x) >> (__riscv_xlen - 64); -} - -#endif /* __riscv_xlen > 64 */ -#endif /* __riscv_xlen > 32 */ -#endif /* __riscv_zbb */ #endif /* AVUTIL_RISCV_BSWAP_H */ From 0e580806d8f11ec494d74e32ff17d0068c50e1ff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9mi=20Denis-Courmont?= Date: Thu, 20 Apr 2023 20:53:57 +0300 Subject: [PATCH 0865/2172] riscv/intmath: use builtins for counting ones As with the earlier bswap change, all versions of GCC and Clang that support RISC-V support the popcount built-ins, so we can just use them instead of inline assembler. --- libavutil/riscv/intmath.h | 30 ++++-------------------------- 1 file changed, 4 insertions(+), 26 deletions(-) diff --git a/libavutil/riscv/intmath.h b/libavutil/riscv/intmath.h index 45bce9a0e7e..ae9ee7775b3 100644 --- a/libavutil/riscv/intmath.h +++ b/libavutil/riscv/intmath.h @@ -69,35 +69,13 @@ static av_always_inline av_const int av_clip_intp2_rvi(int a, int p) return b; } -#if defined (__riscv_zbb) && (__riscv_zbb > 0) && HAVE_INLINE_ASM - -#define av_popcount av_popcount_rvb -static av_always_inline av_const int av_popcount_rvb(uint32_t x) -{ - int ret; - +#if defined (__GNUC__) || defined (__clang__) +#define av_popcount __builtin_popcount #if (__riscv_xlen >= 64) - __asm__ ("cpopw %0, %1\n" : "=r" (ret) : "r" (x)); +#define av_popcount64 __builtin_popcountl #else - __asm__ ("cpop %0, %1\n" : "=r" (ret) : "r" (x)); +#define av_popcount64 __builtin_popcountll #endif - return ret; -} - -#if (__riscv_xlen >= 64) -#define av_popcount64 av_popcount64_rvb -static av_always_inline av_const int av_popcount64_rvb(uint64_t x) -{ - int ret; - -#if (__riscv_xlen >= 128) - __asm__ ("cpopd %0, %1\n" : "=r" (ret) : "r" (x)); -#else - __asm__ ("cpop %0, %1\n" : "=r" (ret) : "r" (x)); #endif - return ret; -} -#endif /* __riscv_xlen >= 64 */ -#endif /* __riscv_zbb */ #endif /* AVUTIL_RISCV_INTMATH_H */ From d94c6df975e277b6f64db865074a4b64cbf0ae7a Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Wed, 3 May 2023 20:07:39 +0200 Subject: [PATCH 0866/2172] avfilter/af_afreqshift: cache nb_coeffs value --- libavfilter/af_afreqshift.c | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/libavfilter/af_afreqshift.c b/libavfilter/af_afreqshift.c index 70bf8e419f3..4df92a499af 100644 --- a/libavfilter/af_afreqshift.c +++ b/libavfilter/af_afreqshift.c @@ -66,6 +66,7 @@ static void pfilter_channel_## name(AVFilterContext *ctx, \ type *o1 = (type *)s->o1->extended_data[ch]; \ type *i2 = (type *)s->i2->extended_data[ch]; \ type *o2 = (type *)s->o2->extended_data[ch]; \ + const int nb_coeffs = s->nb_coeffs; \ const type *c = s->cc; \ const type level = s->level; \ type shift = s->shift * M_PI; \ @@ -76,7 +77,7 @@ static void pfilter_channel_## name(AVFilterContext *ctx, \ type xn1 = src[n], xn2 = src[n]; \ type I, Q; \ \ - for (int j = 0; j < s->nb_coeffs; j++) { \ + for (int j = 0; j < nb_coeffs; j++) { \ I = c[j] * (xn1 + o2[j]) - i2[j]; \ i2[j] = i1[j]; \ i1[j] = xn1; \ @@ -85,7 +86,7 @@ static void pfilter_channel_## name(AVFilterContext *ctx, \ xn1 = I; \ } \ \ - for (int j = s->nb_coeffs; j < s->nb_coeffs*2; j++) { \ + for (int j = nb_coeffs; j < nb_coeffs*2; j++) { \ Q = c[j] * (xn2 + o2[j]) - i2[j]; \ i2[j] = i1[j]; \ i1[j] = xn2; \ @@ -93,7 +94,7 @@ static void pfilter_channel_## name(AVFilterContext *ctx, \ o1[j] = Q; \ xn2 = Q; \ } \ - Q = o2[s->nb_coeffs * 2 - 1]; \ + Q = o2[nb_coeffs * 2 - 1]; \ \ dst[n] = (I * cos_theta - Q * sin_theta) * level; \ } \ @@ -115,6 +116,7 @@ static void ffilter_channel_## name(AVFilterContext *ctx, \ type *o1 = (type *)s->o1->extended_data[ch]; \ type *i2 = (type *)s->i2->extended_data[ch]; \ type *o2 = (type *)s->o2->extended_data[ch]; \ + const int nb_coeffs = s->nb_coeffs; \ const type *c = s->cc; \ const type level = s->level; \ type ts = 1. / in->sample_rate; \ @@ -125,7 +127,7 @@ static void ffilter_channel_## name(AVFilterContext *ctx, \ type xn1 = src[n], xn2 = src[n]; \ type I, Q, theta; \ \ - for (int j = 0; j < s->nb_coeffs; j++) { \ + for (int j = 0; j < nb_coeffs; j++) { \ I = c[j] * (xn1 + o2[j]) - i2[j]; \ i2[j] = i1[j]; \ i1[j] = xn1; \ @@ -134,7 +136,7 @@ static void ffilter_channel_## name(AVFilterContext *ctx, \ xn1 = I; \ } \ \ - for (int j = s->nb_coeffs; j < s->nb_coeffs*2; j++) { \ + for (int j = nb_coeffs; j < nb_coeffs*2; j++) { \ Q = c[j] * (xn2 + o2[j]) - i2[j]; \ i2[j] = i1[j]; \ i1[j] = xn2; \ @@ -142,7 +144,7 @@ static void ffilter_channel_## name(AVFilterContext *ctx, \ o1[j] = Q; \ xn2 = Q; \ } \ - Q = o2[s->nb_coeffs * 2 - 1]; \ + Q = o2[nb_coeffs * 2 - 1]; \ \ theta = 2. * M_PI * fmod(shift * (N + n) * ts, 1.); \ dst[n] = (I * cos(theta) - Q * sin(theta)) * level; \ From 4b11a07550363e1f1d6f8e43923d9b6b327737b0 Mon Sep 17 00:00:00 2001 From: Niklas Haas Date: Mon, 1 May 2023 16:41:51 +0200 Subject: [PATCH 0867/2172] avfilter/vf_libplacebo: add fillcolor option In some circumstances, libplacebo will clear the background as a result of cropping/padding. Currently, this uses the hard-coded default fill color of black. This option makes this behavior configurable. --- doc/filters.texi | 6 ++++++ libavfilter/vf_libplacebo.c | 22 ++++++++++++++++++++++ 2 files changed, 28 insertions(+) diff --git a/doc/filters.texi b/doc/filters.texi index a63304ccd9f..34212b513d3 100644 --- a/doc/filters.texi +++ b/doc/filters.texi @@ -16024,6 +16024,12 @@ content with black borders, while a value of @code{1.0} always crops off parts of the content. Intermediate values are possible, leading to a mix of the two approaches. +@item fillcolor +Set the color used to fill the output area not covered by the output image, for +example as a result of @ref{normalize_sar}. For the general syntax of this +option, check the @ref{color syntax,,"Color" section in the ffmpeg-utils +manual,ffmpeg-utils}. Defaults to @code{black}. + @item colorspace @item color_primaries @item color_trc diff --git a/libavfilter/vf_libplacebo.c b/libavfilter/vf_libplacebo.c index 66929223dd9..fcdc97e48e2 100644 --- a/libavfilter/vf_libplacebo.c +++ b/libavfilter/vf_libplacebo.c @@ -18,6 +18,7 @@ #include "libavutil/file.h" #include "libavutil/opt.h" +#include "libavutil/parseutils.h" #include "internal.h" #include "vulkan_filter.h" #include "scale_eval.h" @@ -73,6 +74,7 @@ typedef struct LibplaceboContext { /* settings */ char *out_format_string; enum AVPixelFormat out_format; + char *fillcolor; char *w_expr; char *h_expr; AVRational target_sar; @@ -225,6 +227,24 @@ static int find_scaler(AVFilterContext *avctx, return AVERROR(EINVAL); } +static int parse_fillcolor(AVFilterContext *avctx, + struct pl_render_params *params, + const char *color_str) +{ + int err = 0; + uint8_t color_rgba[4]; + + RET(av_parse_color(color_rgba, color_str, -1, avctx)); + params->background_color[0] = (float) color_rgba[0] / UINT8_MAX; + params->background_color[1] = (float) color_rgba[1] / UINT8_MAX; + params->background_color[2] = (float) color_rgba[2] / UINT8_MAX; + params->background_transparency = 1.0f - (float) color_rgba[3] / UINT8_MAX; + return 0; + +fail: + return err; +} + static void libplacebo_uninit(AVFilterContext *avctx); static int libplacebo_init(AVFilterContext *avctx) @@ -469,6 +489,7 @@ 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)); + RET(parse_fillcolor(avctx, ¶ms, s->fillcolor)); pl_render_image(s->renderer, &image, &target, ¶ms); pl_unmap_avframe(s->gpu, &image); @@ -703,6 +724,7 @@ static const AVOption libplacebo_options[] = { { "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 = 0}, 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 }, + { "fillcolor", "Background fill color", OFFSET(fillcolor), AV_OPT_TYPE_STRING, {.str = "black"}, .flags = 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"}, From b80e43bf07ac890486e01a195abc9118ab403eb0 Mon Sep 17 00:00:00 2001 From: Niklas Haas Date: Mon, 1 May 2023 16:35:22 +0200 Subject: [PATCH 0868/2172] avfilter/vf_libplacebo: add flexible crop exprs Motivated by a desire to use vf_libplacebo as a GPU-accelerated cropping/padding/zooming filter. This commit adds support for setting the `input/target.crop` fields as dynamic expressions. Re-use the same generic variables available to other scale and crop type filters, and also add some more that we can afford as a result of being able to set these properties dynamically. It's worth pointing out that `out_t/ot` is currently redundant with `in_t/t` since it will always contain the same PTS values, but I plan on changing this in the near future. I decided to also expose `crop_w/crop_h` and `pos_w/pos_h` as variables in the expression parser itself, since this enables the fairly common use case of determining dimensions first and then placing the image appropriately, such as is done in the default behavior (which centers the cropped/placed region by default). --- doc/filters.texi | 55 ++++++++++++-- libavfilter/vf_libplacebo.c | 145 +++++++++++++++++++++++++++++++++++- 2 files changed, 192 insertions(+), 8 deletions(-) diff --git a/doc/filters.texi b/doc/filters.texi index 34212b513d3..839a1c6a9f6 100644 --- a/doc/filters.texi +++ b/doc/filters.texi @@ -15997,10 +15997,31 @@ in source frames. @table @option @item w @item h -Set the output video dimension expression. Default value is the input dimension. +Set the output video dimension expression. Default values are @code{iw} and +@code{ih}. Allows for the same expressions as the @ref{scale} filter. +@item crop_x +@item crop_y +Set the input crop x/y expressions, default values are @code{(iw-cw)/2} and +@code{(ih-ch)/2}. + +@item crop_w +@item crop_h +Set the input crop width/height expressions, default values are @code{iw} and +@code{ih}. + +@item pos_x +@item pos_y +Set the output placement x/y expressions, default values are @code{(ow-pw)/2} +and @code{(oh-ph)/2}. + +@item pos_w +@item pos_h +Set the output placement width/height expressions, default values are @code{ow} +and @code{oh}. + @item format Set the output format override. If unset (the default), frames will be output in the same format as the respective input frames. Otherwise, format conversion @@ -16012,9 +16033,9 @@ Work the same as the identical @ref{scale} filter options. @item normalize_sar If enabled, output frames will always have a pixel aspect ratio of 1:1. This -will introduce padding/cropping as necessary. If disabled (the default), any -aspect ratio mismatches, including those from e.g. anamorphic video sources, -are forwarded to the output pixel aspect ratio. +will introduce additional padding/cropping as necessary. If disabled (the +default), any aspect ratio mismatches, including those from e.g. anamorphic +video sources, are forwarded to the output pixel aspect ratio. @item pad_crop_ratio Specifies a ratio (between @code{0.0} and @code{1.0}) between padding and @@ -16026,7 +16047,7 @@ approaches. @item fillcolor Set the color used to fill the output area not covered by the output image, for -example as a result of @ref{normalize_sar}. For the general syntax of this +example as a result of @option{normalize_sar}. For the general syntax of this option, check the @ref{color syntax,,"Color" section in the ffmpeg-utils manual,ffmpeg-utils}. Defaults to @code{black}. @@ -16051,6 +16072,30 @@ BT.2020+PQ, overriding the usual input frame metadata. These will also be picked as the values of @code{auto} for the respective frame output options. @end table +In addition to the expression constants documented for the @ref{scale} filter, +the @option{crop_w}, @option{crop_h}, @option{crop_x}, @option{crop_y}, +@option{pos_w}, @option{pos_h}, @option{pos_x} and @option{pos_y} options can +also contain the following constants: + +@table @option +@item crop_w, cw +@item crop_h, ch +The computed values of @option{crop_w} and @option{crop_h}. + +@item pos_w, pw +@item pos_h, ph +The computed values of @option{pos_w} and @option{pos_h}. + +@item in_t, t +The input frame timestamp, in seconds. NAN if input timestamp is unknown. + +@item out_t, ot +The input frame timestamp, in seconds. NAN if input timestamp is unknown. + +@item n +The input frame number, starting with 0. +@end table + @subsubsection Scaling The options in this section control how libplacebo performs upscaling and (if necessary) downscaling. Note that libplacebo will always internally operate on diff --git a/libavfilter/vf_libplacebo.c b/libavfilter/vf_libplacebo.c index fcdc97e48e2..6fe3e0ea882 100644 --- a/libavfilter/vf_libplacebo.c +++ b/libavfilter/vf_libplacebo.c @@ -16,6 +16,7 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#include "libavutil/eval.h" #include "libavutil/file.h" #include "libavutil/opt.h" #include "libavutil/parseutils.h" @@ -60,6 +61,50 @@ static const struct pl_tone_map_function * const tonemapping_funcs[TONE_MAP_COUN [TONE_MAP_LINEAR] = &pl_tone_map_linear, }; +static const char *const var_names[] = { + "in_w", "iw", ///< width of the input video frame + "in_h", "ih", ///< height of the input video frame + "out_w", "ow", ///< width of the output video frame + "out_h", "oh", ///< height of the output video frame + "crop_w", "cw", ///< evaluated input crop width + "crop_h", "ch", ///< evaluated input crop height + "pos_w", "pw", ///< evaluated output placement width + "pos_h", "ph", ///< evaluated output placement height + "a", ///< iw/ih + "sar", ///< input pixel aspect ratio + "dar", ///< output pixel aspect ratio + "hsub", ///< input horizontal subsampling factor + "vsub", ///< input vertical subsampling factor + "ohsub", ///< output horizontal subsampling factor + "ovsub", ///< output vertical subsampling factor + "in_t", "t", ///< input frame pts + "out_t", "ot", ///< output frame pts + "n", ///< number of frame + 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_CROP_W, VAR_CW, + VAR_CROP_H, VAR_CH, + VAR_POS_W, VAR_PW, + VAR_POS_H, VAR_PH, + VAR_A, + VAR_SAR, + VAR_DAR, + VAR_HSUB, + VAR_VSUB, + VAR_OHSUB, + VAR_OVSUB, + VAR_IN_T, VAR_T, + VAR_OUT_T, VAR_OT, + VAR_N, + VAR_VARS_NB +}; + typedef struct LibplaceboContext { /* lavfi vulkan*/ FFVulkanContext vkctx; @@ -75,8 +120,16 @@ typedef struct LibplaceboContext { char *out_format_string; enum AVPixelFormat out_format; char *fillcolor; + double var_values[VAR_VARS_NB]; char *w_expr; char *h_expr; + char *crop_x_expr, *crop_y_expr; + char *crop_w_expr, *crop_h_expr; + char *pos_x_expr, *pos_y_expr; + char *pos_w_expr, *pos_h_expr; + // Parsed expressions for input/output crop + AVExpr *crop_x_pexpr, *crop_y_pexpr, *crop_w_pexpr, *crop_h_pexpr; + AVExpr *pos_x_pexpr, *pos_y_pexpr, *pos_w_pexpr, *pos_h_pexpr; AVRational target_sar; float pad_crop_ratio; int force_original_aspect_ratio; @@ -249,6 +302,7 @@ static void libplacebo_uninit(AVFilterContext *avctx); static int libplacebo_init(AVFilterContext *avctx) { + int err = 0; LibplaceboContext *s = avctx->priv; /* Create libplacebo log context */ @@ -273,8 +327,28 @@ static int libplacebo_init(AVFilterContext *avctx) s->out_format = AV_PIX_FMT_NONE; } + RET(av_expr_parse(&s->crop_x_pexpr, s->crop_x_expr, var_names, + NULL, NULL, NULL, NULL, 0, s)); + RET(av_expr_parse(&s->crop_y_pexpr, s->crop_y_expr, var_names, + NULL, NULL, NULL, NULL, 0, s)); + RET(av_expr_parse(&s->crop_w_pexpr, s->crop_w_expr, var_names, + NULL, NULL, NULL, NULL, 0, s)); + RET(av_expr_parse(&s->crop_h_pexpr, s->crop_h_expr, var_names, + NULL, NULL, NULL, NULL, 0, s)); + RET(av_expr_parse(&s->pos_x_pexpr, s->pos_x_expr, var_names, + NULL, NULL, NULL, NULL, 0, s)); + RET(av_expr_parse(&s->pos_y_pexpr, s->pos_y_expr, var_names, + NULL, NULL, NULL, NULL, 0, s)); + RET(av_expr_parse(&s->pos_w_pexpr, s->pos_w_expr, var_names, + NULL, NULL, NULL, NULL, 0, s)); + RET(av_expr_parse(&s->pos_h_pexpr, s->pos_h_expr, var_names, + NULL, NULL, NULL, NULL, 0, s)); + /* Note: s->vulkan etc. are initialized later, when hwctx is available */ return 0; + +fail: + return err; } static int init_vulkan(AVFilterContext *avctx) @@ -364,6 +438,15 @@ static void libplacebo_uninit(AVFilterContext *avctx) pl_log_destroy(&s->log); ff_vk_uninit(&s->vkctx); s->gpu = NULL; + + av_expr_free(s->crop_x_pexpr); + av_expr_free(s->crop_y_pexpr); + av_expr_free(s->crop_w_pexpr); + av_expr_free(s->crop_h_pexpr); + av_expr_free(s->pos_x_pexpr); + av_expr_free(s->pos_y_pexpr); + av_expr_free(s->pos_w_pexpr); + av_expr_free(s->pos_h_pexpr); } static int process_frames(AVFilterContext *avctx, AVFrame *out, AVFrame *in) @@ -398,6 +481,25 @@ static int process_frames(AVFilterContext *avctx, AVFrame *out, AVFrame *in) if (!s->apply_filmgrain) image.film_grain.type = PL_FILM_GRAIN_NONE; + s->var_values[VAR_CROP_W] = s->var_values[VAR_CW] = + av_expr_eval(s->crop_w_pexpr, s->var_values, NULL); + s->var_values[VAR_CROP_H] = s->var_values[VAR_CH] = + av_expr_eval(s->crop_h_pexpr, s->var_values, NULL); + s->var_values[VAR_POS_W] = s->var_values[VAR_PW] = + av_expr_eval(s->pos_w_pexpr, s->var_values, NULL); + s->var_values[VAR_POS_H] = s->var_values[VAR_PH] = + av_expr_eval(s->pos_h_pexpr, s->var_values, NULL); + + image.crop.x0 = av_expr_eval(s->crop_x_pexpr, s->var_values, NULL); + image.crop.y0 = av_expr_eval(s->crop_y_pexpr, s->var_values, NULL); + image.crop.x1 = image.crop.x0 + s->var_values[VAR_CROP_W]; + image.crop.y1 = image.crop.y0 + s->var_values[VAR_CROP_H]; + + target.crop.x0 = av_expr_eval(s->pos_x_pexpr, s->var_values, NULL); + target.crop.y0 = av_expr_eval(s->pos_y_pexpr, s->var_values, NULL); + target.crop.x1 = target.crop.x0 + s->var_values[VAR_POS_W]; + target.crop.y1 = target.crop.y0 + s->var_values[VAR_POS_H]; + 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); @@ -530,6 +632,18 @@ static int filter_frame(AVFilterLink *link, AVFrame *in) out->width = outlink->w; out->height = outlink->h; + /* Dynamic variables */ + s->var_values[VAR_IN_T] = s->var_values[VAR_T] = + in->pts == AV_NOPTS_VALUE ? NAN : in->pts * av_q2d(link->time_base); + s->var_values[VAR_OUT_T] = s->var_values[VAR_OT] = + out->pts == AV_NOPTS_VALUE ? NAN : out->pts * av_q2d(outlink->time_base); + s->var_values[VAR_N] = link->frame_count_out; + /* Will be evaluated/set by `process_frames` */ + s->var_values[VAR_CROP_W] = s->var_values[VAR_CW] = NAN; + s->var_values[VAR_CROP_H] = s->var_values[VAR_CH] = NAN; + s->var_values[VAR_POS_W] = s->var_values[VAR_PW] = NAN; + s->var_values[VAR_POS_H] = s->var_values[VAR_PH] = NAN; + 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 */ @@ -660,6 +774,8 @@ static int libplacebo_config_output(AVFilterLink *outlink) AVFilterContext *avctx = outlink->src; LibplaceboContext *s = avctx->priv; AVFilterLink *inlink = outlink->src->inputs[0]; + const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(inlink->format); + const AVPixFmtDescriptor *out_desc = av_pix_fmt_desc_get(outlink->format); AVHWFramesContext *hwfc; AVVulkanFramesContext *vkfc; AVRational scale_sar; @@ -687,6 +803,21 @@ static int libplacebo_config_output(AVFilterLink *outlink) outlink->sample_aspect_ratio = scale_sar; } + /* Static variables */ + s->var_values[VAR_IN_W] = s->var_values[VAR_IW] = inlink->w; + s->var_values[VAR_IN_H] = s->var_values[VAR_IH] = inlink->h; + s->var_values[VAR_OUT_W] = s->var_values[VAR_OW] = outlink->w; + s->var_values[VAR_OUT_H] = s->var_values[VAR_OH] = outlink->h; + s->var_values[VAR_A] = (double) inlink->w / inlink->h; + s->var_values[VAR_SAR] = inlink->sample_aspect_ratio.num ? + av_q2d(inlink->sample_aspect_ratio) : 1.0; + s->var_values[VAR_DAR] = outlink->sample_aspect_ratio.num ? + av_q2d(outlink->sample_aspect_ratio) : 1.0; + s->var_values[VAR_HSUB] = 1 << desc->log2_chroma_w; + s->var_values[VAR_VSUB] = 1 << desc->log2_chroma_h; + s->var_values[VAR_OHSUB] = 1 << out_desc->log2_chroma_w; + s->var_values[VAR_OVSUB] = 1 << out_desc->log2_chroma_h; + if (outlink->format != AV_PIX_FMT_VULKAN) return 0; @@ -714,15 +845,23 @@ static int libplacebo_config_output(AVFilterLink *outlink) #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 }, + { "w", "Output video frame width", OFFSET(w_expr), AV_OPT_TYPE_STRING, {.str = "iw"}, .flags = STATIC }, + { "h", "Output video frame height", OFFSET(h_expr), AV_OPT_TYPE_STRING, {.str = "ih"}, .flags = STATIC }, + { "crop_x", "Input video crop x", OFFSET(crop_x_expr), AV_OPT_TYPE_STRING, {.str = "(iw-cw)/2"}, .flags = DYNAMIC }, + { "crop_y", "Input video crop y", OFFSET(crop_y_expr), AV_OPT_TYPE_STRING, {.str = "(ih-ch)/2"}, .flags = DYNAMIC }, + { "crop_w", "Input video crop w", OFFSET(crop_w_expr), AV_OPT_TYPE_STRING, {.str = "iw"}, .flags = DYNAMIC }, + { "crop_h", "Input video crop h", OFFSET(crop_h_expr), AV_OPT_TYPE_STRING, {.str = "ih"}, .flags = DYNAMIC }, + { "pos_x", "Output video placement x", OFFSET(pos_x_expr), AV_OPT_TYPE_STRING, {.str = "(ow-pw)/2"}, .flags = DYNAMIC }, + { "pos_y", "Output video placement y", OFFSET(pos_y_expr), AV_OPT_TYPE_STRING, {.str = "(oh-ph)/2"}, .flags = DYNAMIC }, + { "pos_w", "Output video placement w", OFFSET(pos_w_expr), AV_OPT_TYPE_STRING, {.str = "ow"}, .flags = DYNAMIC }, + { "pos_h", "Output video placement h", OFFSET(pos_h_expr), AV_OPT_TYPE_STRING, {.str = "oh"}, .flags = DYNAMIC }, { "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 = 0}, 0, 1, STATIC }, + { "normalize_sar", "force SAR normalization to 1:1 by adjusting pos_x/y/w/h", OFFSET(normalize_sar), AV_OPT_TYPE_BOOL, {.i64 = 0}, 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 }, { "fillcolor", "Background fill color", OFFSET(fillcolor), AV_OPT_TYPE_STRING, {.str = "black"}, .flags = DYNAMIC }, From ad417eb5fa1c3edf3294ea8db9df87f8a7409297 Mon Sep 17 00:00:00 2001 From: Niklas Haas Date: Mon, 1 May 2023 16:56:10 +0200 Subject: [PATCH 0869/2172] doc/filters/libplacebo: fix outdated/wrong note This has not been the case since c0b93c4f8+48c385fb4c. --- doc/filters.texi | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/doc/filters.texi b/doc/filters.texi index 839a1c6a9f6..9a0fe9c0a10 100644 --- a/doc/filters.texi +++ b/doc/filters.texi @@ -15982,8 +15982,7 @@ ffmpeg -i input.mov -vf lensfun=make=Canon:model="Canon EOS 100D":lens_model="Ca @section libplacebo Flexible GPU-accelerated processing filter based on libplacebo -(@url{https://code.videolan.org/videolan/libplacebo}). Note that this filter -currently only accepts Vulkan input frames. +(@url{https://code.videolan.org/videolan/libplacebo}). @subsection Options From 36a56d3cc8dcc137df668e4f2c57d8d9f6310420 Mon Sep 17 00:00:00 2001 From: Zhao Zhili Date: Wed, 12 Apr 2023 01:49:26 +0800 Subject: [PATCH 0870/2172] avcodec/avcodec: fix UB NULL+0 Signed-off-by: Zhao Zhili --- libavcodec/avcodec.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/libavcodec/avcodec.c b/libavcodec/avcodec.c index fb1362290f5..5a96899d505 100644 --- a/libavcodec/avcodec.c +++ b/libavcodec/avcodec.c @@ -44,10 +44,11 @@ int avcodec_default_execute(AVCodecContext *c, int (*func)(AVCodecContext *c2, void *arg2), void *arg, int *ret, int count, int size) { - int i; + size_t i; for (i = 0; i < count; i++) { - int r = func(c, (char *)arg + i * size); + size_t offset = i * size; + int r = func(c, FF_PTR_ADD((char *)arg, offset)); if (ret) ret[i] = r; } From 0d40711f5974fa09ed4b9e1ff38d2c363065c092 Mon Sep 17 00:00:00 2001 From: Zhao Zhili Date: Wed, 12 Apr 2023 01:49:27 +0800 Subject: [PATCH 0871/2172] avcodec/hevcdec: remove unused variables from hls_slice_data Signed-off-by: Zhao Zhili --- libavcodec/hevcdec.c | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/libavcodec/hevcdec.c b/libavcodec/hevcdec.c index 0fa4fdd59d3..21e4d0db28f 100644 --- a/libavcodec/hevcdec.c +++ b/libavcodec/hevcdec.c @@ -2497,7 +2497,7 @@ static void hls_decode_neighbour(HEVCLocalContext *lc, int x_ctb, int y_ctb, lc->ctb_up_left_flag = ((x_ctb > 0) && (y_ctb > 0) && (ctb_addr_in_slice-1 >= s->ps.sps->ctb_width) && (s->ps.pps->tile_id[ctb_addr_ts] == s->ps.pps->tile_id[s->ps.pps->ctb_addr_rs_to_ts[ctb_addr_rs-1 - s->ps.sps->ctb_width]])); } -static int hls_decode_entry(AVCodecContext *avctxt, void *isFilterThread) +static int hls_decode_entry(AVCodecContext *avctxt, void *arg) { HEVCContext *s = avctxt->priv_data; HEVCLocalContext *const lc = s->HEVClc; @@ -2561,14 +2561,10 @@ static int hls_decode_entry(AVCodecContext *avctxt, void *isFilterThread) static int hls_slice_data(HEVCContext *s) { - int arg[2]; - int ret[2]; + int ret = 0; - arg[0] = 0; - arg[1] = 1; - - s->avctx->execute(s->avctx, hls_decode_entry, arg, ret , 1, sizeof(int)); - return ret[0]; + s->avctx->execute(s->avctx, hls_decode_entry, NULL, &ret , 1, 0); + return ret; } static int hls_decode_entry_wpp(AVCodecContext *avctxt, void *hevc_lclist, int job, int self_id) From 4006c71d19e77fbaacc5242fabf077cc84c9088c Mon Sep 17 00:00:00 2001 From: Zhao Zhili Date: Wed, 26 Apr 2023 18:48:38 +0800 Subject: [PATCH 0872/2172] avcodec/options_table: reorder nokey after nointra So the values are in ascending order. Signed-off-by: Zhao Zhili --- libavcodec/options_table.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavcodec/options_table.h b/libavcodec/options_table.h index f331ce28619..4f5918c7f67 100644 --- a/libavcodec/options_table.h +++ b/libavcodec/options_table.h @@ -259,8 +259,8 @@ static const AVOption avcodec_options[] = { {"default" , "discard useless frames", 0, AV_OPT_TYPE_CONST, {.i64 = AVDISCARD_DEFAULT }, INT_MIN, INT_MAX, V|D, "avdiscard"}, {"noref" , "discard all non-reference frames", 0, AV_OPT_TYPE_CONST, {.i64 = AVDISCARD_NONREF }, INT_MIN, INT_MAX, V|D, "avdiscard"}, {"bidir" , "discard all bidirectional frames", 0, AV_OPT_TYPE_CONST, {.i64 = AVDISCARD_BIDIR }, INT_MIN, INT_MAX, V|D, "avdiscard"}, -{"nokey" , "discard all frames except keyframes", 0, AV_OPT_TYPE_CONST, {.i64 = AVDISCARD_NONKEY }, INT_MIN, INT_MAX, V|D, "avdiscard"}, {"nointra" , "discard all frames except I frames", 0, AV_OPT_TYPE_CONST, {.i64 = AVDISCARD_NONINTRA}, INT_MIN, INT_MAX, V|D, "avdiscard"}, +{"nokey" , "discard all frames except keyframes", 0, AV_OPT_TYPE_CONST, {.i64 = AVDISCARD_NONKEY }, INT_MIN, INT_MAX, V|D, "avdiscard"}, {"all" , "discard all frames", 0, AV_OPT_TYPE_CONST, {.i64 = AVDISCARD_ALL }, INT_MIN, INT_MAX, V|D, "avdiscard"}, {"bidir_refine", "refine the two motion vectors used in bidirectional macroblocks", OFFSET(bidir_refine), AV_OPT_TYPE_INT, {.i64 = 1 }, 0, 4, V|E}, {"keyint_min", "minimum interval between IDR-frames", OFFSET(keyint_min), AV_OPT_TYPE_INT, {.i64 = 25 }, INT_MIN, INT_MAX, V|E}, From 2df4e054d4b8f69ce3c2c06aace9df9ba6d2ac2e Mon Sep 17 00:00:00 2001 From: James Almer Date: Tue, 11 Apr 2023 13:59:49 -0300 Subject: [PATCH 0873/2172] avutil/frame: add new interlaced and top_field_first flags Signed-off-by: James Almer --- libavutil/frame.h | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/libavutil/frame.h b/libavutil/frame.h index f85d630c5ce..125ba3aa358 100644 --- a/libavutil/frame.h +++ b/libavutil/frame.h @@ -586,6 +586,15 @@ typedef struct AVFrame { * A flag to mark the frames which need to be decoded, but shouldn't be output. */ #define AV_FRAME_FLAG_DISCARD (1 << 2) +/** + * A flag to mark frames whose content is interlaced. + */ +#define AV_FRAME_FLAG_INTERLACED (1 << 3) +/** + * A flag to mark frames where the top field is displayed first if the content + * is interlaced. + */ +#define AV_FRAME_FLAG_TOP_FIELD_FIRST (1 << 4) /** * @} */ From 2f561ba953e23887ddb25ab1b6739aab04ff9115 Mon Sep 17 00:00:00 2001 From: James Almer Date: Tue, 11 Apr 2023 15:02:14 -0300 Subject: [PATCH 0874/2172] avcodec: use the new AVFrame interlace flags in all decoders and encoders Signed-off-by: James Almer --- libavcodec/cfhd.c | 6 +++--- libavcodec/crystalhd.c | 4 ++-- libavcodec/cuviddec.c | 7 ++++--- libavcodec/decode.c | 2 ++ libavcodec/dnxhddec.c | 15 ++++++++------- libavcodec/dnxhdenc.c | 3 ++- libavcodec/dvdec.c | 12 ++++++------ libavcodec/dvenc.c | 4 ++-- libavcodec/encode.c | 5 +++++ libavcodec/ffv1dec.c | 14 +++++++------- libavcodec/ffv1enc.c | 4 ++-- libavcodec/h264_slice.c | 32 ++++++++++++++++---------------- libavcodec/hevc_refs.c | 7 +++++-- libavcodec/libx264.c | 6 +++--- libavcodec/m101.c | 12 +++++++----- libavcodec/mjpegdec.c | 4 ++-- libavcodec/mmaldec.c | 6 ++++-- libavcodec/mpeg12enc.c | 2 +- libavcodec/mpeg4videoenc.c | 2 +- libavcodec/mpegvideo_dec.c | 10 +++++----- libavcodec/nvenc.c | 2 +- libavcodec/pngdec.c | 2 +- libavcodec/proresdec2.c | 7 ++++--- libavcodec/proresenc_anatoliy.c | 3 ++- libavcodec/proresenc_kostya.c | 6 +++--- libavcodec/qsvdec.c | 6 +++--- libavcodec/qsvenc.c | 6 +++--- libavcodec/rawdec.c | 9 +++++---- libavcodec/rkmppdec.c | 6 ++++-- libavcodec/utvideodec.c | 3 ++- libavcodec/v210dec.c | 4 ++-- libavcodec/vaapi_hevc.c | 4 ++-- libavcodec/vc1_mc.c | 18 +++++++++--------- libavcodec/vc1dec.c | 4 ++-- 34 files changed, 130 insertions(+), 107 deletions(-) diff --git a/libavcodec/cfhd.c b/libavcodec/cfhd.c index c23eb069c65..42d7dcc3f67 100644 --- a/libavcodec/cfhd.c +++ b/libavcodec/cfhd.c @@ -1087,8 +1087,8 @@ static int cfhd_decode(AVCodecContext *avctx, AVFrame *pic, dst += dst_linesize; } } else { - av_log(avctx, AV_LOG_DEBUG, "interlaced frame ? %d", pic->interlaced_frame); - pic->interlaced_frame = 1; + av_log(avctx, AV_LOG_DEBUG, "interlaced frame ? %d", !!(pic->flags & AV_FRAME_FLAG_INTERLACED)); + pic->flags |= AV_FRAME_FLAG_INTERLACED; low = s->plane[plane].subband[0]; high = s->plane[plane].subband[7]; output = s->plane[plane].l_h[6]; @@ -1284,7 +1284,7 @@ static int cfhd_decode(AVCodecContext *avctx, AVFrame *pic, dst += dst_linesize; } } else { - pic->interlaced_frame = 1; + pic->flags |= AV_FRAME_FLAG_INTERLACED; low = s->plane[plane].l_h[7]; high = s->plane[plane].subband[14]; output = s->plane[plane].l_h[6]; diff --git a/libavcodec/crystalhd.c b/libavcodec/crystalhd.c index a48d60f123d..86f6cfa6c15 100644 --- a/libavcodec/crystalhd.c +++ b/libavcodec/crystalhd.c @@ -543,9 +543,9 @@ static inline CopyRet copy_frame(AVCodecContext *avctx, av_image_copy_plane(dst, dStride, src, sStride, bwidth, height); } - frame->interlaced_frame = interlaced; + frame->flags |= AV_FRAME_FLAG_INTERLACED * !!interlaced; if (interlaced) - frame->top_field_first = !bottom_first; + frame->flags |= AV_FRAME_FLAG_TOP_FIELD_FIRST * !bottom_first; frame->pts = pkt_pts; diff --git a/libavcodec/cuviddec.c b/libavcodec/cuviddec.c index 76e70aa6483..95d29a2e789 100644 --- a/libavcodec/cuviddec.c +++ b/libavcodec/cuviddec.c @@ -631,10 +631,11 @@ FF_DISABLE_DEPRECATION_WARNINGS FF_ENABLE_DEPRECATION_WARNINGS #endif - frame->interlaced_frame = !parsed_frame.is_deinterlacing && !parsed_frame.dispinfo.progressive_frame; + if (!parsed_frame.is_deinterlacing && !parsed_frame.dispinfo.progressive_frame) + frame->flags |= AV_FRAME_FLAG_INTERLACED; - if (frame->interlaced_frame) - frame->top_field_first = parsed_frame.dispinfo.top_field_first; + if ((frame->flags & AV_FRAME_FLAG_INTERLACED) && parsed_frame.dispinfo.top_field_first) + frame->flags |= AV_FRAME_FLAG_TOP_FIELD_FIRST; } else if (ctx->decoder_flushing) { ret = AVERROR_EOF; } else { diff --git a/libavcodec/decode.c b/libavcodec/decode.c index 40f5a3ba598..73bba99750c 100644 --- a/libavcodec/decode.c +++ b/libavcodec/decode.c @@ -570,6 +570,8 @@ static int decode_receive_frame_internal(AVCodecContext *avctx, AVFrame *frame) } if (!ret) { + frame->interlaced_frame = !!(frame->flags & AV_FRAME_FLAG_INTERLACED); + frame->top_field_first = !!(frame->flags & AV_FRAME_FLAG_TOP_FIELD_FIRST); frame->best_effort_timestamp = guess_correct_pts(avctx, frame->pts, frame->pkt_dts); diff --git a/libavcodec/dnxhddec.c b/libavcodec/dnxhddec.c index 7cc4f94c7f8..30a4e396958 100644 --- a/libavcodec/dnxhddec.c +++ b/libavcodec/dnxhddec.c @@ -195,8 +195,9 @@ static int dnxhd_decode_header(DNXHDContext *ctx, AVFrame *frame, } if (buf[5] & 2) { /* interlaced */ ctx->cur_field = first_field ? buf[5] & 1 : !ctx->cur_field; - frame->interlaced_frame = 1; - frame->top_field_first = first_field ^ ctx->cur_field; + frame->flags |= AV_FRAME_FLAG_INTERLACED; + if (first_field ^ ctx->cur_field) + frame->flags |= AV_FRAME_FLAG_TOP_FIELD_FIRST; av_log(ctx->avctx, AV_LOG_DEBUG, "interlaced %d, cur field %d\n", buf[5] & 3, ctx->cur_field); } else { @@ -298,7 +299,7 @@ static int dnxhd_decode_header(DNXHDContext *ctx, AVFrame *frame, ctx->mb_width = (ctx->width + 15)>> 4; ctx->mb_height = AV_RB16(buf + 0x16c); - if ((ctx->height + 15) >> 4 == ctx->mb_height && frame->interlaced_frame) + if ((ctx->height + 15) >> 4 == ctx->mb_height && (frame->flags & AV_FRAME_FLAG_INTERLACED)) ctx->height <<= 1; av_log(ctx->avctx, AV_LOG_VERBOSE, "%dx%d, 4:%s %d bits, MBAFF=%d ACT=%d\n", @@ -316,7 +317,7 @@ static int dnxhd_decode_header(DNXHDContext *ctx, AVFrame *frame, } ctx->data_offset = 0x280; } - if ((ctx->mb_height << frame->interlaced_frame) > (ctx->height + 15) >> 4) { + if ((ctx->mb_height << !!(frame->flags & AV_FRAME_FLAG_INTERLACED)) > (ctx->height + 15) >> 4) { av_log(ctx->avctx, AV_LOG_ERROR, "mb height too big: %d\n", ctx->mb_height); return AVERROR_INVALIDDATA; @@ -530,7 +531,7 @@ static int dnxhd_decode_macroblock(const DNXHDContext *ctx, RowContext *row, return AVERROR_INVALIDDATA; } - if (frame->interlaced_frame) { + if (frame->flags & AV_FRAME_FLAG_INTERLACED) { dct_linesize_luma <<= 1; dct_linesize_chroma <<= 1; } @@ -539,7 +540,7 @@ static int dnxhd_decode_macroblock(const DNXHDContext *ctx, RowContext *row, dest_u = frame->data[1] + ((y * dct_linesize_chroma) << 4) + (x << (3 + shift1 + ctx->is_444)); dest_v = frame->data[2] + ((y * dct_linesize_chroma) << 4) + (x << (3 + shift1 + ctx->is_444)); - if (frame->interlaced_frame && ctx->cur_field) { + if ((frame->flags & AV_FRAME_FLAG_INTERLACED) && ctx->cur_field) { dest_y += frame->linesize[0]; dest_u += frame->linesize[1]; dest_v += frame->linesize[2]; @@ -659,7 +660,7 @@ static int dnxhd_decode_frame(AVCodecContext *avctx, AVFrame *picture, ctx->buf = buf + ctx->data_offset; avctx->execute2(avctx, dnxhd_decode_row, picture, NULL, ctx->mb_height); - if (first_field && picture->interlaced_frame) { + if (first_field && (picture->flags & AV_FRAME_FLAG_INTERLACED)) { buf += ctx->cid_table->coding_unit_size; buf_size -= ctx->cid_table->coding_unit_size; first_field = 0; diff --git a/libavcodec/dnxhdenc.c b/libavcodec/dnxhdenc.c index 176bf972d81..a1852fa6b74 100644 --- a/libavcodec/dnxhdenc.c +++ b/libavcodec/dnxhdenc.c @@ -1251,7 +1251,8 @@ static void dnxhd_load_picture(DNXHDEncContext *ctx, const AVFrame *frame) ctx->thread[i]->dct_uv_offset = ctx->m.uvlinesize*8; } - ctx->cur_field = frame->interlaced_frame && !frame->top_field_first; + ctx->cur_field = (frame->flags & AV_FRAME_FLAG_INTERLACED) && + !(frame->flags & AV_FRAME_FLAG_TOP_FIELD_FIRST); } static int dnxhd_encode_picture(AVCodecContext *avctx, AVPacket *pkt, diff --git a/libavcodec/dvdec.c b/libavcodec/dvdec.c index afc4bb0bcdd..2b4d70ac3d0 100644 --- a/libavcodec/dvdec.c +++ b/libavcodec/dvdec.c @@ -670,14 +670,14 @@ static int dvvideo_decode_frame(AVCodecContext *avctx, AVFrame *frame, /* Determine the codec's field order from the packet */ if ( *vsc_pack == DV_VIDEO_CONTROL ) { if (avctx->height == 720) { - frame->interlaced_frame = 0; - frame->top_field_first = 0; + frame->flags &= ~AV_FRAME_FLAG_INTERLACED; + frame->flags &= ~AV_FRAME_FLAG_TOP_FIELD_FIRST; } else if (avctx->height == 1080) { - frame->interlaced_frame = 1; - frame->top_field_first = (vsc_pack[3] & 0x40) == 0x40; + frame->flags |= AV_FRAME_FLAG_INTERLACED; + frame->flags |= AV_FRAME_FLAG_TOP_FIELD_FIRST * ((vsc_pack[3] & 0x40) == 0x40); } else { - frame->interlaced_frame = (vsc_pack[3] & 0x10) == 0x10; - frame->top_field_first = !(vsc_pack[3] & 0x40); + frame->flags |= AV_FRAME_FLAG_INTERLACED * ((vsc_pack[3] & 0x10) == 0x10); + frame->flags |= AV_FRAME_FLAG_TOP_FIELD_FIRST * !(vsc_pack[3] & 0x40); } } diff --git a/libavcodec/dvenc.c b/libavcodec/dvenc.c index cd442b524df..7bd50174b7f 100644 --- a/libavcodec/dvenc.c +++ b/libavcodec/dvenc.c @@ -1048,9 +1048,9 @@ static inline int dv_write_pack(enum DVPackType pack_id, DVEncContext *c, int fs; if (c->avctx->height >= 720) - fs = c->avctx->height == 720 || c->frame->top_field_first ? 0x40 : 0x00; + fs = c->avctx->height == 720 || (c->frame->flags & AV_FRAME_FLAG_TOP_FIELD_FIRST) ? 0x40 : 0x00; else - fs = c->frame->top_field_first ? 0x00 : 0x40; + fs = (c->frame->flags & AV_FRAME_FLAG_TOP_FIELD_FIRST) ? 0x00 : 0x40; if (DV_PROFILE_IS_HD(c->sys) || (int)(av_q2d(c->avctx->sample_aspect_ratio) * diff --git a/libavcodec/encode.c b/libavcodec/encode.c index 0f11efc481a..dfcdce6a3c2 100644 --- a/libavcodec/encode.c +++ b/libavcodec/encode.c @@ -192,6 +192,11 @@ int ff_encode_get_frame(AVCodecContext *avctx, AVFrame *frame) av_frame_move_ref(frame, avci->buffer_frame); + if (frame->interlaced_frame) + frame->flags |= AV_FRAME_FLAG_INTERLACED; + if (frame->top_field_first) + frame->flags |= AV_FRAME_FLAG_TOP_FIELD_FIRST; + return 0; } diff --git a/libavcodec/ffv1dec.c b/libavcodec/ffv1dec.c index a3f93022334..c49db83b5cf 100644 --- a/libavcodec/ffv1dec.c +++ b/libavcodec/ffv1dec.c @@ -217,13 +217,13 @@ static int decode_slice_header(const FFV1Context *f, FFV1Context *fs) ps = get_symbol(c, state, 0); if (ps == 1) { - f->cur->interlaced_frame = 1; - f->cur->top_field_first = 1; + f->cur->flags |= AV_FRAME_FLAG_INTERLACED; + f->cur->flags |= AV_FRAME_FLAG_TOP_FIELD_FIRST; } else if (ps == 2) { - f->cur->interlaced_frame = 1; - f->cur->top_field_first = 0; + f->cur->flags |= AV_FRAME_FLAG_INTERLACED; + f->cur->flags &= ~AV_FRAME_FLAG_TOP_FIELD_FIRST; } else if (ps == 3) { - f->cur->interlaced_frame = 0; + f->cur->flags &= ~AV_FRAME_FLAG_INTERLACED; } f->cur->sample_aspect_ratio.num = get_symbol(c, state, 0); f->cur->sample_aspect_ratio.den = get_symbol(c, state, 0); @@ -881,9 +881,9 @@ static int decode_frame(AVCodecContext *avctx, AVFrame *rframe, if (f->version < 3 && avctx->field_order > AV_FIELD_PROGRESSIVE) { /* we have interlaced material flagged in container */ - p->interlaced_frame = 1; + p->flags |= AV_FRAME_FLAG_INTERLACED; if (avctx->field_order == AV_FIELD_TT || avctx->field_order == AV_FIELD_TB) - p->top_field_first = 1; + p->flags |= AV_FRAME_FLAG_TOP_FIELD_FIRST; } f->avctx = avctx; diff --git a/libavcodec/ffv1enc.c b/libavcodec/ffv1enc.c index fb12776cc29..746f7175683 100644 --- a/libavcodec/ffv1enc.c +++ b/libavcodec/ffv1enc.c @@ -916,10 +916,10 @@ static void encode_slice_header(FFV1Context *f, FFV1Context *fs) put_symbol(c, state, f->plane[j].quant_table_index, 0); av_assert0(f->plane[j].quant_table_index == f->context_model); } - if (!f->cur_enc_frame->interlaced_frame) + if (!(f->cur_enc_frame->flags & AV_FRAME_FLAG_INTERLACED)) put_symbol(c, state, 3, 0); else - put_symbol(c, state, 1 + !f->cur_enc_frame->top_field_first, 0); + put_symbol(c, state, 1 + !(f->cur_enc_frame->flags & AV_FRAME_FLAG_TOP_FIELD_FIRST), 0); put_symbol(c, state, f->cur_enc_frame->sample_aspect_ratio.num, 0); put_symbol(c, state, f->cur_enc_frame->sample_aspect_ratio.den, 0); if (f->version > 3) { diff --git a/libavcodec/h264_slice.c b/libavcodec/h264_slice.c index d05b83a1216..f44b60c6425 100644 --- a/libavcodec/h264_slice.c +++ b/libavcodec/h264_slice.c @@ -1155,9 +1155,10 @@ static int h264_export_frame_props(H264Context *h) const SPS *sps = h->ps.sps; H264Picture *cur = h->cur_pic_ptr; AVFrame *out = cur->f; + int interlaced_frame = 0, top_field_first = 0; int ret; - out->interlaced_frame = 0; + out->flags &= ~AV_FRAME_FLAG_INTERLACED; out->repeat_pict = 0; /* Signal interlacing information externally. */ @@ -1181,15 +1182,15 @@ static int h264_export_frame_props(H264Context *h) break; case H264_SEI_PIC_STRUCT_TOP_FIELD: case H264_SEI_PIC_STRUCT_BOTTOM_FIELD: - out->interlaced_frame = 1; + interlaced_frame = 1; break; case H264_SEI_PIC_STRUCT_TOP_BOTTOM: case H264_SEI_PIC_STRUCT_BOTTOM_TOP: if (FIELD_OR_MBAFF_PICTURE(h)) - out->interlaced_frame = 1; + interlaced_frame = 1; else // try to flag soft telecine progressive - out->interlaced_frame = h->prev_interlaced_frame; + interlaced_frame = !!h->prev_interlaced_frame; break; case H264_SEI_PIC_STRUCT_TOP_BOTTOM_TOP: case H264_SEI_PIC_STRUCT_BOTTOM_TOP_BOTTOM: @@ -1208,35 +1209,34 @@ static int h264_export_frame_props(H264Context *h) if ((pt->ct_type & 3) && pt->pic_struct <= H264_SEI_PIC_STRUCT_BOTTOM_TOP) - out->interlaced_frame = (pt->ct_type & (1 << 1)) != 0; + interlaced_frame = ((pt->ct_type & (1 << 1)) != 0); } else { /* Derive interlacing flag from used decoding process. */ - out->interlaced_frame = FIELD_OR_MBAFF_PICTURE(h); + interlaced_frame = !!FIELD_OR_MBAFF_PICTURE(h); } - h->prev_interlaced_frame = out->interlaced_frame; + h->prev_interlaced_frame = interlaced_frame; if (cur->field_poc[0] != cur->field_poc[1]) { /* Derive top_field_first from field pocs. */ - out->top_field_first = cur->field_poc[0] < cur->field_poc[1]; + top_field_first = (cur->field_poc[0] < cur->field_poc[1]); } else { if (sps->pic_struct_present_flag && h->sei.picture_timing.present) { /* Use picture timing SEI information. Even if it is a * information of a past frame, better than nothing. */ if (h->sei.picture_timing.pic_struct == H264_SEI_PIC_STRUCT_TOP_BOTTOM || h->sei.picture_timing.pic_struct == H264_SEI_PIC_STRUCT_TOP_BOTTOM_TOP) - out->top_field_first = 1; - else - out->top_field_first = 0; - } else if (out->interlaced_frame) { + top_field_first = 1; + } else if (interlaced_frame) { /* Default to top field first when pic_struct_present_flag * is not set but interlaced frame detected */ - out->top_field_first = 1; - } else { + top_field_first = 1; + } // else /* Most likely progressive */ - out->top_field_first = 0; - } } + out->flags |= (AV_FRAME_FLAG_INTERLACED * interlaced_frame) | + (AV_FRAME_FLAG_TOP_FIELD_FIRST * top_field_first); + ret = ff_h2645_sei_to_frame(out, &h->sei.common, AV_CODEC_ID_H264, h->avctx, &sps->vui, sps->bit_depth_luma, sps->bit_depth_chroma, cur->poc + (unsigned)(h->poc_offset << 5)); diff --git a/libavcodec/hevc_refs.c b/libavcodec/hevc_refs.c index 96153a2459f..e9be02c4892 100644 --- a/libavcodec/hevc_refs.c +++ b/libavcodec/hevc_refs.c @@ -111,8 +111,11 @@ static HEVCFrame *alloc_frame(HEVCContext *s) for (j = 0; j < frame->ctb_count; j++) frame->rpl_tab[j] = (RefPicListTab *)frame->rpl_buf->data; - frame->frame->top_field_first = s->sei.picture_timing.picture_struct == AV_PICTURE_STRUCTURE_TOP_FIELD; - frame->frame->interlaced_frame = (s->sei.picture_timing.picture_struct == AV_PICTURE_STRUCTURE_TOP_FIELD) || (s->sei.picture_timing.picture_struct == AV_PICTURE_STRUCTURE_BOTTOM_FIELD); + if (s->sei.picture_timing.picture_struct == AV_PICTURE_STRUCTURE_TOP_FIELD) + frame->frame->flags |= AV_FRAME_FLAG_TOP_FIELD_FIRST; + if ((s->sei.picture_timing.picture_struct == AV_PICTURE_STRUCTURE_TOP_FIELD) || + (s->sei.picture_timing.picture_struct == AV_PICTURE_STRUCTURE_BOTTOM_FIELD)) + frame->frame->flags |= AV_FRAME_FLAG_INTERLACED; if (s->avctx->hwaccel) { const AVHWAccel *hwaccel = s->avctx->hwaccel; diff --git a/libavcodec/libx264.c b/libavcodec/libx264.c index cfdd4222362..3aea29e9956 100644 --- a/libavcodec/libx264.c +++ b/libavcodec/libx264.c @@ -196,9 +196,9 @@ static void reconfig_encoder(AVCodecContext *ctx, const AVFrame *frame) if (x4->avcintra_class < 0) { - if (x4->params.b_interlaced && x4->params.b_tff != frame->top_field_first) { + if (x4->params.b_interlaced && x4->params.b_tff != !!(frame->flags & AV_FRAME_FLAG_TOP_FIELD_FIRST)) { - x4->params.b_tff = frame->top_field_first; + x4->params.b_tff = !!(frame->flags & AV_FRAME_FLAG_TOP_FIELD_FIRST); x264_encoder_reconfig(x4->enc, &x4->params); } if (x4->params.vui.i_sar_height*ctx->sample_aspect_ratio.num != ctx->sample_aspect_ratio.den * x4->params.vui.i_sar_width) { @@ -339,7 +339,7 @@ static int setup_roi(AVCodecContext *ctx, x264_picture_t *pic, int bit_depth, av_log(ctx, AV_LOG_WARNING, "Adaptive quantization must be enabled to use ROI encoding, skipping ROI.\n"); } return 0; - } else if (frame->interlaced_frame) { + } else if (frame->flags & AV_FRAME_FLAG_INTERLACED) { if (!x4->roi_warned) { x4->roi_warned = 1; av_log(ctx, AV_LOG_WARNING, "interlaced_frame not supported for ROI encoding yet, skipping ROI.\n"); diff --git a/libavcodec/m101.c b/libavcodec/m101.c index 3def577b746..809c89c4f3b 100644 --- a/libavcodec/m101.c +++ b/libavcodec/m101.c @@ -68,14 +68,16 @@ static int m101_decode_frame(AVCodecContext *avctx, AVFrame *frame, return ret; frame->pict_type = AV_PICTURE_TYPE_I; frame->key_frame = 1; - frame->interlaced_frame = ((avctx->extradata[3*4] & 3) != 3); - if (frame->interlaced_frame) - frame->top_field_first = avctx->extradata[3*4] & 1; + if ((avctx->extradata[3*4] & 3) != 3) { + frame->flags |= AV_FRAME_FLAG_INTERLACED; + if (avctx->extradata[3*4] & 1) + frame->flags |= AV_FRAME_FLAG_TOP_FIELD_FIRST; + } for (y = 0; y < avctx->height; y++) { int src_y = y; - if (frame->interlaced_frame) - src_y = ((y&1)^frame->top_field_first) ? y/2 : (y/2 + avctx->height/2); + if (frame->flags & AV_FRAME_FLAG_INTERLACED) + src_y = ((y&1) ^ !!(frame->flags & AV_FRAME_FLAG_TOP_FIELD_FIRST)) ? y/2 : (y/2 + avctx->height/2); if (bits == 8) { uint8_t *line = frame->data[0] + y*frame->linesize[0]; memcpy(line, buf + src_y*stride, 2*avctx->width); diff --git a/libavcodec/mjpegdec.c b/libavcodec/mjpegdec.c index 72d654080d3..acdeb68596d 100644 --- a/libavcodec/mjpegdec.c +++ b/libavcodec/mjpegdec.c @@ -441,8 +441,8 @@ int ff_mjpeg_decode_sof(MJpegDecodeContext *s) s->height < ((s->orig_height * 3) / 4)) { s->interlaced = 1; s->bottom_field = s->interlace_polarity; - s->picture_ptr->interlaced_frame = 1; - s->picture_ptr->top_field_first = !s->interlace_polarity; + s->picture_ptr->flags |= AV_FRAME_FLAG_INTERLACED; + s->picture_ptr->flags |= AV_FRAME_FLAG_TOP_FIELD_FIRST * !s->interlace_polarity; height *= 2; } diff --git a/libavcodec/mmaldec.c b/libavcodec/mmaldec.c index 3092f585107..9bfb6778b64 100644 --- a/libavcodec/mmaldec.c +++ b/libavcodec/mmaldec.c @@ -622,8 +622,10 @@ static int ffmal_copy_frame(AVCodecContext *avctx, AVFrame *frame, MMALDecodeContext *ctx = avctx->priv_data; int ret = 0; - frame->interlaced_frame = ctx->interlaced_frame; - frame->top_field_first = ctx->top_field_first; + if (ctx->interlaced_frame) + frame->flags |= AV_FRAME_FLAG_INTERLACED; + if (ctx->top_field_first) + frame->flags |= AV_FRAME_FLAG_TOP_FIELD_FIRST; if (avctx->pix_fmt == AV_PIX_FMT_MMAL) { if (!ctx->pool_out) diff --git a/libavcodec/mpeg12enc.c b/libavcodec/mpeg12enc.c index a932b59678f..c7438fbe072 100644 --- a/libavcodec/mpeg12enc.c +++ b/libavcodec/mpeg12enc.c @@ -530,7 +530,7 @@ void ff_mpeg1_encode_picture_header(MpegEncContext *s) if (s->progressive_sequence) put_bits(&s->pb, 1, 0); /* no repeat */ else - put_bits(&s->pb, 1, s->current_picture_ptr->f->top_field_first); + put_bits(&s->pb, 1, !!(s->current_picture_ptr->f->flags & AV_FRAME_FLAG_TOP_FIELD_FIRST)); /* XXX: optimize the generation of this flag with entropy measures */ s->frame_pred_frame_dct = s->progressive_sequence; diff --git a/libavcodec/mpeg4videoenc.c b/libavcodec/mpeg4videoenc.c index c3e9ebea452..777635c40cb 100644 --- a/libavcodec/mpeg4videoenc.c +++ b/libavcodec/mpeg4videoenc.c @@ -1101,7 +1101,7 @@ int ff_mpeg4_encode_picture_header(MpegEncContext *s) } put_bits(&s->pb, 3, 0); /* intra dc VLC threshold */ if (!s->progressive_sequence) { - put_bits(&s->pb, 1, s->current_picture_ptr->f->top_field_first); + put_bits(&s->pb, 1, !!(s->current_picture_ptr->f->flags & AV_FRAME_FLAG_TOP_FIELD_FIRST)); put_bits(&s->pb, 1, s->alternate_scan); } // FIXME sprite stuff diff --git a/libavcodec/mpegvideo_dec.c b/libavcodec/mpegvideo_dec.c index 522a0aada5f..482f388b993 100644 --- a/libavcodec/mpegvideo_dec.c +++ b/libavcodec/mpegvideo_dec.c @@ -331,15 +331,15 @@ FF_ENABLE_DEPRECATION_WARNINGS 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; + s->current_picture_ptr->f->flags |= AV_FRAME_FLAG_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->flags |= AV_FRAME_FLAG_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->f->flags |= AV_FRAME_FLAG_INTERLACED * (!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; diff --git a/libavcodec/nvenc.c b/libavcodec/nvenc.c index 50a4fa6f69e..b2f6253a430 100644 --- a/libavcodec/nvenc.c +++ b/libavcodec/nvenc.c @@ -2634,7 +2634,7 @@ static int nvenc_send_frame(AVCodecContext *avctx, const AVFrame *frame) pic_params.outputBitstream = in_surf->output_surface; if (avctx->flags & AV_CODEC_FLAG_INTERLACED_DCT) { - if (frame->top_field_first) + if (frame->flags & AV_FRAME_FLAG_TOP_FIELD_FIRST) pic_params.pictureStruct = NV_ENC_PIC_STRUCT_FIELD_TOP_BOTTOM; else pic_params.pictureStruct = NV_ENC_PIC_STRUCT_FIELD_BOTTOM_TOP; diff --git a/libavcodec/pngdec.c b/libavcodec/pngdec.c index 8fbb71f60f6..03b3efdabc9 100644 --- a/libavcodec/pngdec.c +++ b/libavcodec/pngdec.c @@ -841,7 +841,7 @@ static int decode_idat_chunk(AVCodecContext *avctx, PNGDecContext *s, p->pict_type = AV_PICTURE_TYPE_I; p->key_frame = 1; - p->interlaced_frame = !!s->interlace_type; + p->flags |= AV_FRAME_FLAG_INTERLACED * !!s->interlace_type; if ((ret = populate_avctx_color_fields(avctx, p)) < 0) return ret; diff --git a/libavcodec/proresdec2.c b/libavcodec/proresdec2.c index c821a078491..88f4c49ce61 100644 --- a/libavcodec/proresdec2.c +++ b/libavcodec/proresdec2.c @@ -252,8 +252,9 @@ static int decode_frame_header(ProresContext *ctx, const uint8_t *buf, ctx->scan = ctx->progressive_scan; // permuted } else { ctx->scan = ctx->interlaced_scan; // permuted - ctx->frame->interlaced_frame = 1; - ctx->frame->top_field_first = ctx->frame_type == 1; + ctx->frame->flags |= AV_FRAME_FLAG_INTERLACED; + if (ctx->frame_type == 1) + ctx->frame->flags |= AV_FRAME_FLAG_TOP_FIELD_FIRST; } if (ctx->alpha_info) { @@ -706,7 +707,7 @@ static int decode_slice_thread(AVCodecContext *avctx, void *arg, int jobnr, int dest_u = pic->data[1] + (slice->mb_y << 4) * chroma_stride + (slice->mb_x << mb_x_shift); dest_v = pic->data[2] + (slice->mb_y << 4) * chroma_stride + (slice->mb_x << mb_x_shift); - if (ctx->frame_type && ctx->first_field ^ ctx->frame->top_field_first) { + if (ctx->frame_type && ctx->first_field ^ !!(ctx->frame->flags & AV_FRAME_FLAG_TOP_FIELD_FIRST)) { dest_y += pic->linesize[0]; dest_u += pic->linesize[1]; dest_v += pic->linesize[2]; diff --git a/libavcodec/proresenc_anatoliy.c b/libavcodec/proresenc_anatoliy.c index 09196c7aa11..fc48c97d5b5 100644 --- a/libavcodec/proresenc_anatoliy.c +++ b/libavcodec/proresenc_anatoliy.c @@ -746,7 +746,8 @@ static int prores_encode_frame(AVCodecContext *avctx, AVPacket *pkt, if (avctx->profile >= FF_PROFILE_PRORES_4444) /* 4444 or 4444 Xq */ frame_flags |= 0x40; /* 444 chroma */ if (ctx->is_interlaced) { - if (pict->top_field_first || !pict->interlaced_frame) { /* tff frame or progressive frame interpret as tff */ + if ((pict->flags & AV_FRAME_FLAG_TOP_FIELD_FIRST) || !(pict->flags & AV_FRAME_FLAG_INTERLACED)) { + /* tff frame or progressive frame interpret as tff */ av_log(avctx, AV_LOG_DEBUG, "use interlaced encoding, top field first\n"); frame_flags |= 0x04; /* interlaced tff */ is_top_field_first = 1; diff --git a/libavcodec/proresenc_kostya.c b/libavcodec/proresenc_kostya.c index 1940e0378a0..77ab524046b 100644 --- a/libavcodec/proresenc_kostya.c +++ b/libavcodec/proresenc_kostya.c @@ -585,7 +585,7 @@ static int encode_slice(AVCodecContext *avctx, const AVFrame *pic, if (ctx->pictures_per_frame == 1) line_add = 0; else - line_add = ctx->cur_picture_idx ^ !pic->top_field_first; + line_add = ctx->cur_picture_idx ^ !(pic->flags & AV_FRAME_FLAG_TOP_FIELD_FIRST); if (ctx->force_quant) { qmat = ctx->quants[0]; @@ -838,7 +838,7 @@ static int find_slice_quant(AVCodecContext *avctx, if (ctx->pictures_per_frame == 1) line_add = 0; else - line_add = ctx->cur_picture_idx ^ !ctx->pic->top_field_first; + line_add = ctx->cur_picture_idx ^ !(ctx->pic->flags & AV_FRAME_FLAG_TOP_FIELD_FIRST); mbs = x + mbs_per_slice; for (i = 0; i < ctx->num_planes; i++) { @@ -1045,7 +1045,7 @@ static int encode_frame(AVCodecContext *avctx, AVPacket *pkt, frame_flags = ctx->chroma_factor << 6; if (avctx->flags & AV_CODEC_FLAG_INTERLACED_DCT) - frame_flags |= pic->top_field_first ? 0x04 : 0x08; + frame_flags |= (pic->flags & AV_FRAME_FLAG_TOP_FIELD_FIRST) ? 0x04 : 0x08; bytestream_put_byte (&buf, frame_flags); bytestream_put_byte (&buf, 0); // reserved diff --git a/libavcodec/qsvdec.c b/libavcodec/qsvdec.c index 6bc85116adf..e137a38e3c6 100644 --- a/libavcodec/qsvdec.c +++ b/libavcodec/qsvdec.c @@ -828,9 +828,9 @@ static int qsv_decode(AVCodecContext *avctx, QSVContext *q, outsurf->Info.PicStruct & MFX_PICSTRUCT_FRAME_TRIPLING ? 4 : outsurf->Info.PicStruct & MFX_PICSTRUCT_FRAME_DOUBLING ? 2 : outsurf->Info.PicStruct & MFX_PICSTRUCT_FIELD_REPEATED ? 1 : 0; - frame->top_field_first = - outsurf->Info.PicStruct & MFX_PICSTRUCT_FIELD_TFF; - frame->interlaced_frame = + frame->flags |= AV_FRAME_FLAG_TOP_FIELD_FIRST * + !!(outsurf->Info.PicStruct & MFX_PICSTRUCT_FIELD_TFF); + frame->flags |= AV_FRAME_FLAG_INTERLACED * !(outsurf->Info.PicStruct & MFX_PICSTRUCT_PROGRESSIVE); frame->pict_type = ff_qsv_map_pictype(aframe.frame->dec_info.FrameType); //Key frame is IDR frame is only suitable for H264. For HEVC, IRAPs are key frames. diff --git a/libavcodec/qsvenc.c b/libavcodec/qsvenc.c index c975302b4f2..0ed1f757d46 100644 --- a/libavcodec/qsvenc.c +++ b/libavcodec/qsvenc.c @@ -1947,8 +1947,8 @@ static int submit_frame(QSVEncContext *q, const AVFrame *frame, qf->surface.Info = q->param.mfx.FrameInfo; qf->surface.Info.PicStruct = - !frame->interlaced_frame ? MFX_PICSTRUCT_PROGRESSIVE : - frame->top_field_first ? MFX_PICSTRUCT_FIELD_TFF : + !(frame->flags & AV_FRAME_FLAG_INTERLACED) ? MFX_PICSTRUCT_PROGRESSIVE : + (frame->flags & AV_FRAME_FLAG_TOP_FIELD_FIRST) ? MFX_PICSTRUCT_FIELD_TFF : MFX_PICSTRUCT_FIELD_BFF; if (frame->repeat_pict == 1) qf->surface.Info.PicStruct |= MFX_PICSTRUCT_FIELD_REPEATED; @@ -2402,7 +2402,7 @@ static int encode_frame(AVCodecContext *avctx, QSVEncContext *q, goto free; } - if (ret == MFX_WRN_INCOMPATIBLE_VIDEO_PARAM && frame && frame->interlaced_frame) + if (ret == MFX_WRN_INCOMPATIBLE_VIDEO_PARAM && frame && (frame->flags & AV_FRAME_FLAG_INTERLACED)) print_interlace_msg(avctx, q); ret = 0; diff --git a/libavcodec/rawdec.c b/libavcodec/rawdec.c index c20c317fed8..72920d86f0d 100644 --- a/libavcodec/rawdec.c +++ b/libavcodec/rawdec.c @@ -234,8 +234,9 @@ static int raw_decode(AVCodecContext *avctx, AVFrame *frame, return res; if (context->tff >= 0) { - frame->interlaced_frame = 1; - frame->top_field_first = context->tff; + frame->flags |= AV_FRAME_FLAG_INTERLACED; + if (context->tff == 1) + frame->flags |= AV_FRAME_FLAG_TOP_FIELD_FIRST; } if ((res = av_image_check_size(avctx->width, avctx->height, 0, avctx)) < 0) @@ -459,9 +460,9 @@ static int raw_decode(AVCodecContext *avctx, AVFrame *frame, } if (avctx->field_order > AV_FIELD_PROGRESSIVE) { /* we have interlaced material flagged in container */ - frame->interlaced_frame = 1; + frame->flags |= AV_FRAME_FLAG_INTERLACED; if (avctx->field_order == AV_FIELD_TT || avctx->field_order == AV_FIELD_TB) - frame->top_field_first = 1; + frame->flags |= AV_FRAME_FLAG_TOP_FIELD_FIRST; } *got_frame = 1; diff --git a/libavcodec/rkmppdec.c b/libavcodec/rkmppdec.c index 8bf7c6ed163..5768568b002 100644 --- a/libavcodec/rkmppdec.c +++ b/libavcodec/rkmppdec.c @@ -404,8 +404,10 @@ static int rkmpp_retrieve_frame(AVCodecContext *avctx, AVFrame *frame) frame->colorspace = mpp_frame_get_colorspace(mppframe); mode = mpp_frame_get_mode(mppframe); - frame->interlaced_frame = ((mode & MPP_FRAME_FLAG_FIELD_ORDER_MASK) == MPP_FRAME_FLAG_DEINTERLACED); - frame->top_field_first = ((mode & MPP_FRAME_FLAG_FIELD_ORDER_MASK) == MPP_FRAME_FLAG_TOP_FIRST); + if ((mode & MPP_FRAME_FLAG_FIELD_ORDER_MASK) == MPP_FRAME_FLAG_DEINTERLACED) + frame->flags |= AV_FRAME_FLAG_INTERLACED; + if ((mode & MPP_FRAME_FLAG_FIELD_ORDER_MASK) == MPP_FRAME_FLAG_TOP_FIRST) + frame->flags |= AV_FRAME_FLAG_TOP_FIELD_FIRST; mppformat = mpp_frame_get_fmt(mppframe); drmformat = rkmpp_get_frameformat(mppformat); diff --git a/libavcodec/utvideodec.c b/libavcodec/utvideodec.c index 83120d1b22c..c7ef725e5ec 100644 --- a/libavcodec/utvideodec.c +++ b/libavcodec/utvideodec.c @@ -871,7 +871,8 @@ static int decode_frame(AVCodecContext *avctx, AVFrame *frame, frame->key_frame = 1; frame->pict_type = AV_PICTURE_TYPE_I; - frame->interlaced_frame = !!c->interlaced; + if (c->interlaced) + frame->flags |= AV_FRAME_FLAG_INTERLACED; *got_frame = 1; diff --git a/libavcodec/v210dec.c b/libavcodec/v210dec.c index 43b92f6ec93..26c9841d837 100644 --- a/libavcodec/v210dec.c +++ b/libavcodec/v210dec.c @@ -207,9 +207,9 @@ static int decode_frame(AVCodecContext *avctx, AVFrame *pic, if (avctx->field_order > AV_FIELD_PROGRESSIVE) { /* we have interlaced material flagged in container */ - pic->interlaced_frame = 1; + pic->flags |= AV_FRAME_FLAG_INTERLACED; if (avctx->field_order == AV_FIELD_TT || avctx->field_order == AV_FIELD_TB) - pic->top_field_first = 1; + pic->flags |= AV_FRAME_FLAG_TOP_FIELD_FIRST; } *got_frame = 1; diff --git a/libavcodec/vaapi_hevc.c b/libavcodec/vaapi_hevc.c index 17c38963f82..8b12484fff5 100644 --- a/libavcodec/vaapi_hevc.c +++ b/libavcodec/vaapi_hevc.c @@ -60,10 +60,10 @@ static void fill_vaapi_pic(VAPictureHEVC *va_pic, const HEVCFrame *pic, int rps_ if (pic->flags & HEVC_FRAME_FLAG_LONG_REF) va_pic->flags |= VA_PICTURE_HEVC_LONG_TERM_REFERENCE; - if (pic->frame->interlaced_frame) { + if (pic->frame->flags & AV_FRAME_FLAG_INTERLACED) { va_pic->flags |= VA_PICTURE_HEVC_FIELD_PIC; - if (!pic->frame->top_field_first) + if (!(pic->frame->flags & AV_FRAME_FLAG_TOP_FIELD_FIRST)) va_pic->flags |= VA_PICTURE_HEVC_BOTTOM_FIELD; } } diff --git a/libavcodec/vc1_mc.c b/libavcodec/vc1_mc.c index 1b8d8799b3c..8f0b3f6fab1 100644 --- a/libavcodec/vc1_mc.c +++ b/libavcodec/vc1_mc.c @@ -233,7 +233,7 @@ void ff_vc1_mc_1mv(VC1Context *v, int dir) luty = v->last_luty; lutuv = v->last_lutuv; use_ic = v->last_use_ic; - interlace = s->last_picture.f->interlaced_frame; + interlace = !!(s->last_picture.f->flags & AV_FRAME_FLAG_INTERLACED); } } else { srcY = s->next_picture.f->data[0]; @@ -242,7 +242,7 @@ void ff_vc1_mc_1mv(VC1Context *v, int dir) luty = v->next_luty; lutuv = v->next_lutuv; use_ic = v->next_use_ic; - interlace = s->next_picture.f->interlaced_frame; + interlace = !!(s->next_picture.f->flags & AV_FRAME_FLAG_INTERLACED); } if (!srcY || !srcU) { @@ -482,13 +482,13 @@ void ff_vc1_mc_4mv_luma(VC1Context *v, int n, int dir, int avg) srcY = s->last_picture.f->data[0]; luty = v->last_luty; use_ic = v->last_use_ic; - interlace = s->last_picture.f->interlaced_frame; + interlace = !!(s->last_picture.f->flags & AV_FRAME_FLAG_INTERLACED); } } else { srcY = s->next_picture.f->data[0]; luty = v->next_luty; use_ic = v->next_use_ic; - interlace = s->next_picture.f->interlaced_frame; + interlace = !!(s->next_picture.f->flags & AV_FRAME_FLAG_INTERLACED); } if (!srcY) { @@ -708,14 +708,14 @@ void ff_vc1_mc_4mv_chroma(VC1Context *v, int dir) srcV = s->last_picture.f->data[2]; lutuv = v->last_lutuv; use_ic = v->last_use_ic; - interlace = s->last_picture.f->interlaced_frame; + interlace = !!(s->last_picture.f->flags & AV_FRAME_FLAG_INTERLACED); } } else { srcU = s->next_picture.f->data[1]; srcV = s->next_picture.f->data[2]; lutuv = v->next_lutuv; use_ic = v->next_use_ic; - interlace = s->next_picture.f->interlaced_frame; + interlace = !!(s->next_picture.f->flags & AV_FRAME_FLAG_INTERLACED); } if (!srcU) { @@ -884,13 +884,13 @@ void ff_vc1_mc_4mv_chroma4(VC1Context *v, int dir, int dir2, int avg) srcV = s->next_picture.f->data[2]; lutuv = v->next_lutuv; use_ic = v->next_use_ic; - interlace = s->next_picture.f->interlaced_frame; + interlace = !!(s->next_picture.f->flags & AV_FRAME_FLAG_INTERLACED); } else { srcU = s->last_picture.f->data[1]; srcV = s->last_picture.f->data[2]; lutuv = v->last_lutuv; use_ic = v->last_use_ic; - interlace = s->last_picture.f->interlaced_frame; + interlace = !!(s->last_picture.f->flags & AV_FRAME_FLAG_INTERLACED); } if (!srcU) return; @@ -1034,7 +1034,7 @@ void ff_vc1_interp_mc(VC1Context *v) srcU = s->next_picture.f->data[1]; srcV = s->next_picture.f->data[2]; - interlace = s->next_picture.f->interlaced_frame; + interlace = !!(s->next_picture.f->flags & AV_FRAME_FLAG_INTERLACED); src_x = s->mb_x * 16 + (mx >> 2); src_y = s->mb_y * 16 + (my >> 2); diff --git a/libavcodec/vc1dec.c b/libavcodec/vc1dec.c index 18fb616fff5..a103a734453 100644 --- a/libavcodec/vc1dec.c +++ b/libavcodec/vc1dec.c @@ -1078,8 +1078,8 @@ static int vc1_decode_frame(AVCodecContext *avctx, AVFrame *pict, } v->s.current_picture_ptr->field_picture = v->field_mode; - v->s.current_picture_ptr->f->interlaced_frame = (v->fcm != PROGRESSIVE); - v->s.current_picture_ptr->f->top_field_first = v->tff; + v->s.current_picture_ptr->f->flags |= AV_FRAME_FLAG_INTERLACED * (v->fcm != PROGRESSIVE); + v->s.current_picture_ptr->f->flags |= AV_FRAME_FLAG_TOP_FIELD_FIRST * !!v->tff; // process pulldown flags s->current_picture_ptr->f->repeat_pict = 0; From 36827ea783afbb39e5b75e8a982e316739009773 Mon Sep 17 00:00:00 2001 From: James Almer Date: Wed, 12 Apr 2023 11:38:46 -0300 Subject: [PATCH 0875/2172] avfilter: use the new AVFrame interlace flags in all filters Signed-off-by: James Almer --- libavfilter/avfilter.c | 4 ++-- libavfilter/buffersrc.c | 5 +++++ libavfilter/f_select.c | 8 ++++---- libavfilter/phase_template.c | 4 ++-- libavfilter/qsvvpp.c | 4 ++-- libavfilter/setpts.c | 2 +- libavfilter/vf_coreimage.m | 1 + libavfilter/vf_deinterlace_vaapi.c | 5 +++-- libavfilter/vf_estdif.c | 7 ++++--- libavfilter/vf_field.c | 1 + libavfilter/vf_fieldhint.c | 2 ++ libavfilter/vf_fieldmatch.c | 15 +++++++++++---- libavfilter/vf_fieldorder.c | 10 +++++++--- libavfilter/vf_framerate.c | 2 +- libavfilter/vf_idet.c | 17 +++++++++++++---- libavfilter/vf_kerndeint.c | 1 + libavfilter/vf_nnedi.c | 7 ++++--- libavfilter/vf_pullup.c | 3 ++- libavfilter/vf_repeatfields.c | 7 ++++--- libavfilter/vf_scale.c | 3 ++- libavfilter/vf_separatefields.c | 7 ++++--- libavfilter/vf_setparams.c | 6 ++++++ libavfilter/vf_showinfo.c | 4 ++-- libavfilter/vf_telecine.c | 18 ++++++++++++++++-- libavfilter/vf_tinterlace.c | 16 ++++++++++++++-- libavfilter/vf_w3fdif.c | 7 ++++--- libavfilter/vf_weave.c | 5 +++++ libavfilter/vsrc_gradients.c | 1 + libavfilter/vsrc_testsrc.c | 1 + libavfilter/yadif_common.c | 12 +++++++----- 30 files changed, 132 insertions(+), 53 deletions(-) diff --git a/libavfilter/avfilter.c b/libavfilter/avfilter.c index d2e9ba47ef8..889808c5805 100644 --- a/libavfilter/avfilter.c +++ b/libavfilter/avfilter.c @@ -57,8 +57,8 @@ static void tlog_ref(void *ctx, AVFrame *ref, int end) ff_tlog(ctx, " a:%d/%d s:%dx%d i:%c iskey:%d type:%c", ref->sample_aspect_ratio.num, ref->sample_aspect_ratio.den, ref->width, ref->height, - !ref->interlaced_frame ? 'P' : /* Progressive */ - ref->top_field_first ? 'T' : 'B', /* Top / Bottom */ + !(ref->flags & AV_FRAME_FLAG_INTERLACED) ? 'P' : /* Progressive */ + (ref->flags & AV_FRAME_FLAG_TOP_FIELD_FIRST) ? 'T' : 'B', /* Top / Bottom */ ref->key_frame, av_get_picture_type_char(ref->pict_type)); } diff --git a/libavfilter/buffersrc.c b/libavfilter/buffersrc.c index a1740da0546..927b16ea067 100644 --- a/libavfilter/buffersrc.c +++ b/libavfilter/buffersrc.c @@ -247,6 +247,11 @@ FF_DISABLE_DEPRECATION_WARNINGS FF_ENABLE_DEPRECATION_WARNINGS #endif + if (copy->interlaced_frame) + copy->flags |= AV_FRAME_FLAG_INTERLACED; + if (copy->top_field_first) + copy->flags |= AV_FRAME_FLAG_TOP_FIELD_FIRST; + ret = ff_filter_frame(ctx->outputs[0], copy); if (ret < 0) return ret; diff --git a/libavfilter/f_select.c b/libavfilter/f_select.c index d76c248fc5b..6eab92b32fa 100644 --- a/libavfilter/f_select.c +++ b/libavfilter/f_select.c @@ -356,8 +356,8 @@ FF_ENABLE_DEPRECATION_WARNINGS case AVMEDIA_TYPE_VIDEO: select->var_values[VAR_INTERLACE_TYPE] = - !frame->interlaced_frame ? INTERLACE_TYPE_P : - frame->top_field_first ? INTERLACE_TYPE_T : INTERLACE_TYPE_B; + !(frame->flags & AV_FRAME_FLAG_INTERLACED) ? INTERLACE_TYPE_P : + (frame->flags & AV_FRAME_FLAG_TOP_FIELD_FIRST) ? INTERLACE_TYPE_T : INTERLACE_TYPE_B; select->var_values[VAR_PICT_TYPE] = frame->pict_type; if (select->do_scene_detect) { char buf[32]; @@ -380,8 +380,8 @@ FF_ENABLE_DEPRECATION_WARNINGS switch (inlink->type) { case AVMEDIA_TYPE_VIDEO: av_log(inlink->dst, AV_LOG_DEBUG, " interlace_type:%c pict_type:%c scene:%f", - (!frame->interlaced_frame) ? 'P' : - frame->top_field_first ? 'T' : 'B', + !(frame->flags & AV_FRAME_FLAG_INTERLACED) ? 'P' : + (frame->flags & AV_FRAME_FLAG_TOP_FIELD_FIRST) ? 'T' : 'B', av_get_picture_type_char(frame->pict_type), select->var_values[VAR_SCENE]); break; diff --git a/libavfilter/phase_template.c b/libavfilter/phase_template.c index 84506702342..2621a543a16 100644 --- a/libavfilter/phase_template.c +++ b/libavfilter/phase_template.c @@ -57,10 +57,10 @@ static enum PhaseMode fn(analyze_plane)(void *ctx, enum PhaseMode mode, AVFrame double bdiff, tdiff, pdiff; if (mode == AUTO) { - mode = new->interlaced_frame ? new->top_field_first ? + mode = (new->flags & AV_FRAME_FLAG_INTERLACED) ? (new->flags & AV_FRAME_FLAG_TOP_FIELD_FIRST) ? TOP_FIRST : BOTTOM_FIRST : PROGRESSIVE; } else if (mode == AUTO_ANALYZE) { - mode = new->interlaced_frame ? new->top_field_first ? + mode = (new->flags & AV_FRAME_FLAG_INTERLACED) ? (new->flags & AV_FRAME_FLAG_TOP_FIELD_FIRST) ? TOP_FIRST_ANALYZE : BOTTOM_FIRST_ANALYZE : FULL_ANALYZE; } diff --git a/libavfilter/qsvvpp.c b/libavfilter/qsvvpp.c index 54e7284234b..b233b812435 100644 --- a/libavfilter/qsvvpp.c +++ b/libavfilter/qsvvpp.c @@ -460,8 +460,8 @@ static QSVFrame *submit_frame(QSVVPPContext *s, AVFilterLink *inlink, AVFrame *p inlink->time_base, default_tb); qsv_frame->surface.Info.PicStruct = - !qsv_frame->frame->interlaced_frame ? MFX_PICSTRUCT_PROGRESSIVE : - (qsv_frame->frame->top_field_first ? MFX_PICSTRUCT_FIELD_TFF : + !(qsv_frame->frame->flags & AV_FRAME_FLAG_INTERLACED) ? MFX_PICSTRUCT_PROGRESSIVE : + ((qsv_frame->frame->flags & AV_FRAME_FLAG_TOP_FIELD_FIRST) ? MFX_PICSTRUCT_FIELD_TFF : MFX_PICSTRUCT_FIELD_BFF); if (qsv_frame->frame->repeat_pict == 1) qsv_frame->surface.Info.PicStruct |= MFX_PICSTRUCT_FIELD_REPEATED; diff --git a/libavfilter/setpts.c b/libavfilter/setpts.c index 5bcc0c2dcf2..7a5cd3ef782 100644 --- a/libavfilter/setpts.c +++ b/libavfilter/setpts.c @@ -174,7 +174,7 @@ FF_ENABLE_DEPRECATION_WARNINGS if (frame) { if (inlink->type == AVMEDIA_TYPE_VIDEO) { - setpts->var_values[VAR_INTERLACED] = frame->interlaced_frame; + setpts->var_values[VAR_INTERLACED] = !!(frame->flags & AV_FRAME_FLAG_INTERLACED); } else if (inlink->type == AVMEDIA_TYPE_AUDIO) { setpts->var_values[VAR_S] = frame->nb_samples; setpts->var_values[VAR_NB_SAMPLES] = frame->nb_samples; diff --git a/libavfilter/vf_coreimage.m b/libavfilter/vf_coreimage.m index b1959861ded..a5bfdaef6de 100644 --- a/libavfilter/vf_coreimage.m +++ b/libavfilter/vf_coreimage.m @@ -303,6 +303,7 @@ static int request_frame(AVFilterLink *link) frame->duration = 1; frame->key_frame = 1; frame->interlaced_frame = 0; + frame->flags &= ~AV_FRAME_FLAG_INTERLACED; frame->pict_type = AV_PICTURE_TYPE_I; frame->sample_aspect_ratio = ctx->sar; diff --git a/libavfilter/vf_deinterlace_vaapi.c b/libavfilter/vf_deinterlace_vaapi.c index 13045610343..d4246eb4fc9 100644 --- a/libavfilter/vf_deinterlace_vaapi.c +++ b/libavfilter/vf_deinterlace_vaapi.c @@ -252,7 +252,7 @@ static int deint_vaapi_filter_frame(AVFilterLink *inlink, AVFrame *input_frame) if (err < 0) goto fail; - if (!ctx->auto_enable || input_frame->interlaced_frame) { + if (!ctx->auto_enable || (input_frame->flags & AV_FRAME_FLAG_INTERLACED)) { vas = vaMapBuffer(vpp_ctx->hwctx->display, vpp_ctx->filter_buffers[0], &filter_params_addr); if (vas != VA_STATUS_SUCCESS) { @@ -263,7 +263,7 @@ static int deint_vaapi_filter_frame(AVFilterLink *inlink, AVFrame *input_frame) } filter_params = filter_params_addr; filter_params->flags = 0; - if (input_frame->top_field_first) { + if (input_frame->flags & AV_FRAME_FLAG_TOP_FIELD_FIRST) { filter_params->flags |= field ? VA_DEINTERLACING_BOTTOM_FIELD : 0; } else { filter_params->flags |= VA_DEINTERLACING_BOTTOM_FIELD_FIRST; @@ -304,6 +304,7 @@ static int deint_vaapi_filter_frame(AVFilterLink *inlink, AVFrame *input_frame) ctx->frame_queue[current_frame_index + 1]->pts; } output_frame->interlaced_frame = 0; + output_frame->flags &= ~AV_FRAME_FLAG_INTERLACED; av_log(avctx, AV_LOG_DEBUG, "Filter output: %s, %ux%u (%"PRId64").\n", av_get_pix_fmt_name(output_frame->format), diff --git a/libavfilter/vf_estdif.c b/libavfilter/vf_estdif.c index 0164f4638ae..d71d39e2686 100644 --- a/libavfilter/vf_estdif.c +++ b/libavfilter/vf_estdif.c @@ -345,8 +345,8 @@ static int deinterlace_slice(AVFilterContext *ctx, void *arg, const int rslope = s->rslope; const int redge = s->redge; 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 : + const int interlaced = !!(in->flags & AV_FRAME_FLAG_INTERLACED); + const int tff = (s->field == (s->parity == -1 ? interlaced ? (in->flags & AV_FRAME_FLAG_TOP_FIELD_FIRST) : 1 : s->parity ^ 1)); for (int plane = 0; plane < s->nb_planes; plane++) { @@ -444,6 +444,7 @@ static int filter(AVFilterContext *ctx, AVFrame *in, int64_t pts, int64_t durati return AVERROR(ENOMEM); av_frame_copy_props(out, in); out->interlaced_frame = 0; + out->flags &= ~AV_FRAME_FLAG_INTERLACED; out->pts = pts; out->duration = duration; @@ -502,7 +503,7 @@ static int config_input(AVFilterLink *inlink) return 0; } - if ((s->deint && !s->prev->interlaced_frame) || ctx->is_disabled) { + if ((s->deint && !(s->prev->flags & AV_FRAME_FLAG_INTERLACED)) || ctx->is_disabled) { s->prev->pts *= 2; s->prev->duration *= 2; ret = ff_filter_frame(ctx->outputs[0], s->prev); diff --git a/libavfilter/vf_field.c b/libavfilter/vf_field.c index 8d06ffe6636..66b646c72d8 100644 --- a/libavfilter/vf_field.c +++ b/libavfilter/vf_field.c @@ -74,6 +74,7 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *inpicref) inpicref->height = outlink->h; inpicref->interlaced_frame = 0; + inpicref->flags &= ~AV_FRAME_FLAG_INTERLACED; for (i = 0; i < field->nb_planes; i++) { if (field->type == FIELD_TYPE_BOTTOM) diff --git a/libavfilter/vf_fieldhint.c b/libavfilter/vf_fieldhint.c index 4af9e269255..df6fb0b8dfc 100644 --- a/libavfilter/vf_fieldhint.c +++ b/libavfilter/vf_fieldhint.c @@ -218,9 +218,11 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in) switch (hint) { case '+': out->interlaced_frame = 1; + out->flags |= AV_FRAME_FLAG_INTERLACED; break; case '-': out->interlaced_frame = 0; + out->flags &= ~AV_FRAME_FLAG_INTERLACED; break; case '=': break; diff --git a/libavfilter/vf_fieldmatch.c b/libavfilter/vf_fieldmatch.c index bf946beec90..a177cb3fd8b 100644 --- a/libavfilter/vf_fieldmatch.c +++ b/libavfilter/vf_fieldmatch.c @@ -714,7 +714,8 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in) in = fm->src; /* parity */ - order = fm->order != FM_PARITY_AUTO ? fm->order : (in->interlaced_frame ? in->top_field_first : 1); + order = fm->order != FM_PARITY_AUTO ? fm->order : ((in->flags & AV_FRAME_FLAG_INTERLACED) ? + !!(in->flags & AV_FRAME_FLAG_TOP_FIELD_FIRST) : 1); field = fm->field != FM_PARITY_AUTO ? fm->field : order; av_assert0(order == 0 || order == 1 || field == 0 || field == 1); fxo = field ^ order ? fxo1m : fxo0m; @@ -820,15 +821,21 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in) /* mark the frame we are unable to match properly as interlaced so a proper * de-interlacer can take the relay */ dst->interlaced_frame = interlaced_frame; - if (dst->interlaced_frame) { + if (interlaced_frame) { + dst->flags |= AV_FRAME_FLAG_INTERLACED; av_log(ctx, AV_LOG_WARNING, "Frame #%"PRId64" at %s is still interlaced\n", outlink->frame_count_in, av_ts2timestr(in->pts, &inlink->time_base)); dst->top_field_first = field; - } + if (field) + dst->flags |= AV_FRAME_FLAG_TOP_FIELD_FIRST; + else + dst->flags &= ~AV_FRAME_FLAG_TOP_FIELD_FIRST; + } else + dst->flags &= ~AV_FRAME_FLAG_INTERLACED; av_log(ctx, AV_LOG_DEBUG, "SC:%d | COMBS: %3d %3d %3d %3d %3d (combpel=%d)" " match=%d combed=%s\n", sc, combs[0], combs[1], combs[2], combs[3], combs[4], - fm->combpel, match, dst->interlaced_frame ? "YES" : "NO"); + fm->combpel, match, (dst->flags & AV_FRAME_FLAG_INTERLACED) ? "YES" : "NO"); fail: for (i = 0; i < FF_ARRAY_ELEMS(gen_frames); i++) diff --git a/libavfilter/vf_fieldorder.c b/libavfilter/vf_fieldorder.c index 52b4b3d8aa0..e4d0eda1a49 100644 --- a/libavfilter/vf_fieldorder.c +++ b/libavfilter/vf_fieldorder.c @@ -76,11 +76,11 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *frame) uint8_t *dst, *src; AVFrame *out; - if (!frame->interlaced_frame || - frame->top_field_first == s->dst_tff) { + if (!(frame->flags & AV_FRAME_FLAG_INTERLACED) || + !!(frame->flags & AV_FRAME_FLAG_TOP_FIELD_FIRST) == s->dst_tff) { av_log(ctx, AV_LOG_VERBOSE, "Skipping %s.\n", - frame->interlaced_frame ? + (frame->flags & AV_FRAME_FLAG_INTERLACED) ? "frame with same field order" : "progressive frame"); return ff_filter_frame(outlink, frame); } @@ -141,6 +141,10 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *frame) } } out->top_field_first = s->dst_tff; + if (s->dst_tff) + out->flags |= AV_FRAME_FLAG_TOP_FIELD_FIRST; + else + out->flags &= ~AV_FRAME_FLAG_TOP_FIELD_FIRST; if (frame != out) av_frame_free(&frame); diff --git a/libavfilter/vf_framerate.c b/libavfilter/vf_framerate.c index 49bf6cdfff2..6ef5dca27a7 100644 --- a/libavfilter/vf_framerate.c +++ b/libavfilter/vf_framerate.c @@ -318,7 +318,7 @@ static int activate(AVFilterContext *ctx) return ret; if (inpicref) { - if (inpicref->interlaced_frame) + if (inpicref->flags & AV_FRAME_FLAG_INTERLACED) av_log(ctx, AV_LOG_WARNING, "Interlaced frame found - the output will not be correct.\n"); if (inpicref->pts == AV_NOPTS_VALUE) { diff --git a/libavfilter/vf_idet.c b/libavfilter/vf_idet.c index 83d992add12..0f150a273de 100644 --- a/libavfilter/vf_idet.c +++ b/libavfilter/vf_idet.c @@ -185,11 +185,15 @@ static void filter(AVFilterContext *ctx) if (idet->last_type == TFF){ idet->cur->top_field_first = 1; idet->cur->interlaced_frame = 1; + idet->cur->flags |= (AV_FRAME_FLAG_INTERLACED | AV_FRAME_FLAG_TOP_FIELD_FIRST); }else if(idet->last_type == BFF){ idet->cur->top_field_first = 0; idet->cur->interlaced_frame = 1; + idet->cur->flags &= ~AV_FRAME_FLAG_TOP_FIELD_FIRST; + idet->cur->flags |= AV_FRAME_FLAG_INTERLACED; }else if(idet->last_type == PROGRESSIVE){ idet->cur->interlaced_frame = 0; + idet->cur->flags &= ~AV_FRAME_FLAG_INTERLACED; } for(i=0; i<3; i++) @@ -238,13 +242,15 @@ static int filter_frame(AVFilterLink *link, AVFrame *picref) // initial frame(s) and not interlaced, just pass through for // the analyze_interlaced_flag mode if (idet->analyze_interlaced_flag && - !picref->interlaced_frame && + !(picref->flags & AV_FRAME_FLAG_INTERLACED) && !idet->next) { return ff_filter_frame(ctx->outputs[0], picref); } if (idet->analyze_interlaced_flag_done) { - if (picref->interlaced_frame && idet->interlaced_flag_accuracy < 0) + if ((picref->flags & AV_FRAME_FLAG_INTERLACED) && idet->interlaced_flag_accuracy < 0) { picref->interlaced_frame = 0; + picref->flags &= ~AV_FRAME_FLAG_INTERLACED; + } return ff_filter_frame(ctx->outputs[0], picref); } @@ -282,8 +288,9 @@ static int filter_frame(AVFilterLink *link, AVFrame *picref) } if (idet->analyze_interlaced_flag) { - if (idet->cur->interlaced_frame) { + if (idet->cur->flags & AV_FRAME_FLAG_INTERLACED) { idet->cur->interlaced_frame = 0; + idet->cur->flags &= ~AV_FRAME_FLAG_INTERLACED; filter(ctx); if (idet->last_type == PROGRESSIVE) { idet->interlaced_flag_accuracy --; @@ -295,8 +302,10 @@ static int filter_frame(AVFilterLink *link, AVFrame *picref) if (idet->analyze_interlaced_flag == 1) { ff_filter_frame(ctx->outputs[0], av_frame_clone(idet->cur)); - if (idet->next->interlaced_frame && idet->interlaced_flag_accuracy < 0) + if ((idet->next->flags & AV_FRAME_FLAG_INTERLACED) && idet->interlaced_flag_accuracy < 0) { idet->next->interlaced_frame = 0; + idet->next->flags &= ~AV_FRAME_FLAG_INTERLACED; + } idet->analyze_interlaced_flag_done = 1; av_log(ctx, AV_LOG_INFO, "Final flag accuracy %d\n", idet->interlaced_flag_accuracy); return ff_filter_frame(ctx->outputs[0], av_frame_clone(idet->next)); diff --git a/libavfilter/vf_kerndeint.c b/libavfilter/vf_kerndeint.c index dd320fbebfa..e8ec1f474ab 100644 --- a/libavfilter/vf_kerndeint.c +++ b/libavfilter/vf_kerndeint.c @@ -142,6 +142,7 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *inpic) } av_frame_copy_props(outpic, inpic); outpic->interlaced_frame = 0; + outpic->flags &= ~AV_FRAME_FLAG_INTERLACED; for (plane = 0; plane < 4 && inpic->data[plane] && inpic->linesize[plane]; plane++) { h = plane == 0 ? inlink->h : AV_CEIL_RSHIFT(inlink->h, kerndeint->vsub); diff --git a/libavfilter/vf_nnedi.c b/libavfilter/vf_nnedi.c index 63b83e5efdc..39cb4f5a85f 100644 --- a/libavfilter/vf_nnedi.c +++ b/libavfilter/vf_nnedi.c @@ -540,8 +540,8 @@ static int filter_slice(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) const float in_scale = s->in_scale; const float out_scale = s->out_scale; const int depth = s->depth; - const int interlaced = in->interlaced_frame; - const int tff = s->field_n == (s->field < 0 ? interlaced ? in->top_field_first : 1 : + const int interlaced = !!(in->flags & AV_FRAME_FLAG_INTERLACED); + const int tff = s->field_n == (s->field < 0 ? interlaced ? (in->flags & AV_FRAME_FLAG_TOP_FIELD_FIRST) : 1 : (s->field & 1) ^ 1); @@ -666,6 +666,7 @@ static int get_frame(AVFilterContext *ctx, int is_second) return AVERROR(ENOMEM); av_frame_copy_props(dst, s->prev); dst->interlaced_frame = 0; + dst->flags &= ~AV_FRAME_FLAG_INTERLACED; dst->pts = s->pts; ff_filter_execute(ctx, filter_slice, dst, NULL, @@ -688,7 +689,7 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in) return 0; } - if ((s->deint && !s->prev->interlaced_frame) || ctx->is_disabled) { + if ((s->deint && !(s->prev->flags & AV_FRAME_FLAG_INTERLACED)) || ctx->is_disabled) { s->prev->pts *= 2; ret = ff_filter_frame(ctx->outputs[0], s->prev); s->prev = in; diff --git a/libavfilter/vf_pullup.c b/libavfilter/vf_pullup.c index 054e3f90a91..fcdcfc44afb 100644 --- a/libavfilter/vf_pullup.c +++ b/libavfilter/vf_pullup.c @@ -670,7 +670,8 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in) (const uint8_t**)in->data, in->linesize, inlink->format, inlink->w, inlink->h); - p = in->interlaced_frame ? !in->top_field_first : 0; + p = (in->flags & AV_FRAME_FLAG_INTERLACED) ? + !(in->flags & AV_FRAME_FLAG_TOP_FIELD_FIRST) : 0; pullup_submit_field(s, b, p ); pullup_submit_field(s, b, p^1); diff --git a/libavfilter/vf_repeatfields.c b/libavfilter/vf_repeatfields.c index 4d31f3b4f50..782b1e543f6 100644 --- a/libavfilter/vf_repeatfields.c +++ b/libavfilter/vf_repeatfields.c @@ -93,11 +93,12 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in) s->frame->pts = AV_NOPTS_VALUE; } - if ((state == 0 && !in->top_field_first) || - (state == 1 && in->top_field_first)) { + if ((state == 0 && !(in->flags & AV_FRAME_FLAG_TOP_FIELD_FIRST)) || + (state == 1 && (in->flags & AV_FRAME_FLAG_TOP_FIELD_FIRST))) { av_log(ctx, AV_LOG_WARNING, "Unexpected field flags: " "state=%d top_field_first=%d repeat_first_field=%d\n", - state, in->top_field_first, in->repeat_pict); + state, !!(in->flags & AV_FRAME_FLAG_TOP_FIELD_FIRST), + in->repeat_pict); state ^= 1; } diff --git a/libavfilter/vf_scale.c b/libavfilter/vf_scale.c index 6b827635966..b0221e85386 100644 --- a/libavfilter/vf_scale.c +++ b/libavfilter/vf_scale.c @@ -884,7 +884,8 @@ FF_ENABLE_DEPRECATION_WARNINGS (int64_t)in->sample_aspect_ratio.den * outlink->w * link->h, INT_MAX); - if (scale->interlaced>0 || (scale->interlaced<0 && in->interlaced_frame)) { + if (scale->interlaced>0 || (scale->interlaced<0 && + (in->flags & AV_FRAME_FLAG_INTERLACED))) { ret = scale_field(scale, out, in, 0); if (ret >= 0) ret = scale_field(scale, out, in, 1); diff --git a/libavfilter/vf_separatefields.c b/libavfilter/vf_separatefields.c index 7db64c54798..814ea52e212 100644 --- a/libavfilter/vf_separatefields.c +++ b/libavfilter/vf_separatefields.c @@ -71,13 +71,14 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *inpicref) inpicref->height = outlink->h; inpicref->interlaced_frame = 0; + inpicref->flags &= ~AV_FRAME_FLAG_INTERLACED; if (!s->second) { goto clone; } else { AVFrame *second = s->second; - extract_field(second, s->nb_planes, second->top_field_first); + extract_field(second, s->nb_planes, !!(second->flags & AV_FRAME_FLAG_TOP_FIELD_FIRST)); if (second->pts != AV_NOPTS_VALUE && inpicref->pts != AV_NOPTS_VALUE) @@ -94,7 +95,7 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *inpicref) return AVERROR(ENOMEM); } - extract_field(inpicref, s->nb_planes, !inpicref->top_field_first); + extract_field(inpicref, s->nb_planes, !(inpicref->flags & AV_FRAME_FLAG_TOP_FIELD_FIRST)); if (inpicref->pts != AV_NOPTS_VALUE) inpicref->pts *= 2; @@ -110,7 +111,7 @@ static int flush_frame(AVFilterLink *outlink, int64_t pts, int64_t *out_pts) if (s->second) { *out_pts = s->second->pts += pts; - extract_field(s->second, s->nb_planes, s->second->top_field_first); + extract_field(s->second, s->nb_planes, !!(s->second->flags & AV_FRAME_FLAG_TOP_FIELD_FIRST)); ret = ff_filter_frame(outlink, s->second); s->second = NULL; } diff --git a/libavfilter/vf_setparams.c b/libavfilter/vf_setparams.c index 95a2d15c02b..0165a5aaa61 100644 --- a/libavfilter/vf_setparams.c +++ b/libavfilter/vf_setparams.c @@ -128,9 +128,15 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *frame) /* set field */ if (s->field_mode == MODE_PROG) { frame->interlaced_frame = 0; + frame->flags &= ~AV_FRAME_FLAG_INTERLACED; } else if (s->field_mode != MODE_AUTO) { frame->interlaced_frame = 1; frame->top_field_first = s->field_mode; + frame->flags |= AV_FRAME_FLAG_INTERLACED; + if (s->field_mode) + frame->flags |= AV_FRAME_FLAG_TOP_FIELD_FIRST; + else + frame->flags &= ~AV_FRAME_FLAG_TOP_FIELD_FIRST; } /* set range */ diff --git a/libavfilter/vf_showinfo.c b/libavfilter/vf_showinfo.c index 9caa618b01c..6ecab2bf712 100644 --- a/libavfilter/vf_showinfo.c +++ b/libavfilter/vf_showinfo.c @@ -722,8 +722,8 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *frame) desc->name, frame->sample_aspect_ratio.num, frame->sample_aspect_ratio.den, frame->width, frame->height, - !frame->interlaced_frame ? 'P' : /* Progressive */ - frame->top_field_first ? 'T' : 'B', /* Top / Bottom */ + !(frame->flags & AV_FRAME_FLAG_INTERLACED) ? 'P' : /* Progressive */ + (frame->flags & AV_FRAME_FLAG_TOP_FIELD_FIRST) ? 'T' : 'B', /* Top / Bottom */ frame->key_frame, av_get_picture_type_char(frame->pict_type)); diff --git a/libavfilter/vf_telecine.c b/libavfilter/vf_telecine.c index 227de6f733c..d8daa259393 100644 --- a/libavfilter/vf_telecine.c +++ b/libavfilter/vf_telecine.c @@ -206,6 +206,11 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *inpicref) } s->frame[nout]->interlaced_frame = 1; s->frame[nout]->top_field_first = !s->first_field; + s->frame[nout]->flags |= AV_FRAME_FLAG_INTERLACED; + if (s->first_field) + s->frame[nout]->flags &= ~AV_FRAME_FLAG_TOP_FIELD_FIRST; + else + s->frame[nout]->flags |= AV_FRAME_FLAG_TOP_FIELD_FIRST; nout++; len--; s->occupied = 0; @@ -225,6 +230,7 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *inpicref) s->planeheight[i]); s->frame[nout]->interlaced_frame = inpicref->interlaced_frame; s->frame[nout]->top_field_first = inpicref->top_field_first; + s->frame[nout]->flags |= (inpicref->flags & (AV_FRAME_FLAG_INTERLACED | AV_FRAME_FLAG_TOP_FIELD_FIRST)); nout++; len -= 2; } @@ -241,8 +247,8 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *inpicref) for (i = 0; i < nout; i++) { AVFrame *frame = av_frame_clone(s->frame[i]); - int interlaced = frame ? frame->interlaced_frame : 0; - int tff = frame ? frame->top_field_first : 0; + int interlaced = frame ? !!(frame->flags & AV_FRAME_FLAG_INTERLACED) : 0; + int tff = frame ? !!(frame->flags & AV_FRAME_FLAG_TOP_FIELD_FIRST) : 0; if (!frame) { av_frame_free(&inpicref); @@ -252,6 +258,14 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *inpicref) av_frame_copy_props(frame, inpicref); frame->interlaced_frame = interlaced; frame->top_field_first = tff; + if (interlaced) + frame->flags |= AV_FRAME_FLAG_INTERLACED; + else + frame->flags &= ~AV_FRAME_FLAG_INTERLACED; + if (tff) + frame->flags |= AV_FRAME_FLAG_TOP_FIELD_FIRST; + else + frame->flags &= ~AV_FRAME_FLAG_TOP_FIELD_FIRST; frame->pts = ((s->start_time == AV_NOPTS_VALUE) ? 0 : s->start_time) + av_rescale(outlink->frame_count_in, s->ts_unit.num, s->ts_unit.den); diff --git a/libavfilter/vf_tinterlace.c b/libavfilter/vf_tinterlace.c index 032629279ad..742d4e195a0 100644 --- a/libavfilter/vf_tinterlace.c +++ b/libavfilter/vf_tinterlace.c @@ -393,6 +393,7 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *picref) out->height = outlink->h; out->interlaced_frame = 1; out->top_field_first = 1; + out->flags |= AV_FRAME_FLAG_INTERLACED | AV_FRAME_FLAG_TOP_FIELD_FIRST; out->sample_aspect_ratio = av_mul_q(cur->sample_aspect_ratio, av_make_q(2, 1)); /* write odd frame lines into the upper field of the new frame */ @@ -444,7 +445,7 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *picref) * halving the frame rate and preserving image height */ case MODE_INTERLEAVE_TOP: /* top field first */ case MODE_INTERLEAVE_BOTTOM: /* bottom field first */ - if ((tinterlace->flags & TINTERLACE_FLAG_BYPASS_IL) && cur->interlaced_frame) { + if ((tinterlace->flags & TINTERLACE_FLAG_BYPASS_IL) && (cur->flags & AV_FRAME_FLAG_INTERLACED)) { av_log(ctx, AV_LOG_WARNING, "video is already interlaced, adjusting framerate only\n"); out = av_frame_clone(cur); @@ -461,6 +462,11 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *picref) av_frame_copy_props(out, cur); out->interlaced_frame = 1; out->top_field_first = tff; + out->flags |= AV_FRAME_FLAG_INTERLACED; + if (tff) + out->flags |= AV_FRAME_FLAG_TOP_FIELD_FIRST; + else + out->flags &= ~AV_FRAME_FLAG_TOP_FIELD_FIRST; /* copy upper/lower field from cur */ copy_picture_field(tinterlace, out->data, out->linesize, @@ -482,6 +488,7 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *picref) if (!out) return AVERROR(ENOMEM); out->interlaced_frame = 1; + out->flags |= AV_FRAME_FLAG_INTERLACED; if (cur->pts != AV_NOPTS_VALUE) out->pts = cur->pts*2; @@ -490,13 +497,18 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *picref) return ret; /* output mix of current and next frame */ - tff = next->top_field_first; + tff = !!(next->flags & AV_FRAME_FLAG_TOP_FIELD_FIRST); out = ff_get_video_buffer(outlink, outlink->w, outlink->h); if (!out) return AVERROR(ENOMEM); av_frame_copy_props(out, next); out->interlaced_frame = 1; out->top_field_first = !tff; + out->flags |= AV_FRAME_FLAG_INTERLACED; + if (tff) + out->flags &= ~AV_FRAME_FLAG_TOP_FIELD_FIRST; + else + out->flags |= AV_FRAME_FLAG_TOP_FIELD_FIRST; if (next->pts != AV_NOPTS_VALUE && cur->pts != AV_NOPTS_VALUE) out->pts = cur->pts + next->pts; diff --git a/libavfilter/vf_w3fdif.c b/libavfilter/vf_w3fdif.c index 512c8070c7f..7c3ffbc5f05 100644 --- a/libavfilter/vf_w3fdif.c +++ b/libavfilter/vf_w3fdif.c @@ -379,8 +379,8 @@ static int deinterlace_plane_slice(AVFilterContext *ctx, void *arg, const int start = (height * jobnr) / nb_jobs; const int end = (height * (jobnr+1)) / nb_jobs; const int max = s->max; - const int interlaced = cur->interlaced_frame; - const int tff = s->field == (s->parity == -1 ? interlaced ? cur->top_field_first : 1 : + const int interlaced = !!(cur->flags & AV_FRAME_FLAG_INTERLACED); + const int tff = s->field == (s->parity == -1 ? interlaced ? !!(cur->flags & AV_FRAME_FLAG_TOP_FIELD_FIRST) : 1 : s->parity ^ 1); int j, y_in, y_out; @@ -487,6 +487,7 @@ static int filter(AVFilterContext *ctx, int is_second) return AVERROR(ENOMEM); av_frame_copy_props(out, s->cur); out->interlaced_frame = 0; + out->flags &= ~AV_FRAME_FLAG_INTERLACED; if (!is_second) { if (out->pts != AV_NOPTS_VALUE) @@ -533,7 +534,7 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *frame) if (!s->prev) return 0; - if ((s->deint && !s->cur->interlaced_frame) || ctx->is_disabled) { + if ((s->deint && !(s->cur->flags & AV_FRAME_FLAG_INTERLACED)) || ctx->is_disabled) { AVFrame *out = av_frame_clone(s->cur); if (!out) return AVERROR(ENOMEM); diff --git a/libavfilter/vf_weave.c b/libavfilter/vf_weave.c index 2bd3994e5ee..e738c9ba175 100644 --- a/libavfilter/vf_weave.c +++ b/libavfilter/vf_weave.c @@ -150,6 +150,11 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in) out->pts = s->double_weave ? s->prev->pts : in->pts / 2; out->interlaced_frame = 1; out->top_field_first = !s->first_field; + out->flags |= AV_FRAME_FLAG_INTERLACED; + if (s->first_field) + out->flags &= ~AV_FRAME_FLAG_TOP_FIELD_FIRST; + else + out->flags |= AV_FRAME_FLAG_TOP_FIELD_FIRST; if (!s->double_weave) av_frame_free(&in); diff --git a/libavfilter/vsrc_gradients.c b/libavfilter/vsrc_gradients.c index 3c524b92423..2811dd8bb63 100644 --- a/libavfilter/vsrc_gradients.c +++ b/libavfilter/vsrc_gradients.c @@ -399,6 +399,7 @@ static int activate(AVFilterContext *ctx) frame->key_frame = 1; frame->interlaced_frame = 0; + frame->flags &= ~AV_FRAME_FLAG_INTERLACED; frame->pict_type = AV_PICTURE_TYPE_I; frame->sample_aspect_ratio = (AVRational) {1, 1}; frame->pts = s->pts++; diff --git a/libavfilter/vsrc_testsrc.c b/libavfilter/vsrc_testsrc.c index 9760e5fc805..cef3a9be36d 100644 --- a/libavfilter/vsrc_testsrc.c +++ b/libavfilter/vsrc_testsrc.c @@ -186,6 +186,7 @@ static int activate(AVFilterContext *ctx) frame->duration = 1; frame->key_frame = 1; frame->interlaced_frame = 0; + frame->flags &= ~AV_FRAME_FLAG_INTERLACED; frame->pict_type = AV_PICTURE_TYPE_I; frame->sample_aspect_ratio = test->sar; if (!test->draw_once) diff --git a/libavfilter/yadif_common.c b/libavfilter/yadif_common.c index a10cf7a17fd..5b29d2e6d81 100644 --- a/libavfilter/yadif_common.c +++ b/libavfilter/yadif_common.c @@ -31,8 +31,8 @@ static int return_frame(AVFilterContext *ctx, int is_second) int tff, ret; if (yadif->parity == -1) { - tff = yadif->cur->interlaced_frame ? - yadif->cur->top_field_first : 1; + tff = (yadif->cur->flags & AV_FRAME_FLAG_INTERLACED) ? + !!(yadif->cur->flags & AV_FRAME_FLAG_TOP_FIELD_FIRST) : 1; } else { tff = yadif->parity ^ 1; } @@ -44,6 +44,7 @@ static int return_frame(AVFilterContext *ctx, int is_second) av_frame_copy_props(yadif->out, yadif->cur); yadif->out->interlaced_frame = 0; + yadif->out->flags &= ~AV_FRAME_FLAG_INTERLACED; if (yadif->current_field == YADIF_FIELD_BACK_END) yadif->current_field = YADIF_FIELD_END; } @@ -128,10 +129,10 @@ int ff_yadif_filter_frame(AVFilterLink *link, AVFrame *frame) if (!yadif->prev) return 0; - if ((yadif->deint && !yadif->cur->interlaced_frame) || + if ((yadif->deint && !(yadif->cur->flags & AV_FRAME_FLAG_INTERLACED)) || ctx->is_disabled || - (yadif->deint && !yadif->prev->interlaced_frame && yadif->prev->repeat_pict) || - (yadif->deint && !yadif->next->interlaced_frame && yadif->next->repeat_pict) + (yadif->deint && !(yadif->prev->flags & AV_FRAME_FLAG_INTERLACED) && yadif->prev->repeat_pict) || + (yadif->deint && !(yadif->next->flags & AV_FRAME_FLAG_INTERLACED) && yadif->next->repeat_pict) ) { yadif->out = av_frame_clone(yadif->cur); if (!yadif->out) @@ -149,6 +150,7 @@ int ff_yadif_filter_frame(AVFilterLink *link, AVFrame *frame) av_frame_copy_props(yadif->out, yadif->cur); yadif->out->interlaced_frame = 0; + yadif->out->flags &= ~AV_FRAME_FLAG_INTERLACED; if (yadif->out->pts != AV_NOPTS_VALUE) yadif->out->pts *= 2; From 3675dd0e0c8892151441a02ed0c5dee72a111c81 Mon Sep 17 00:00:00 2001 From: James Almer Date: Wed, 12 Apr 2023 11:42:35 -0300 Subject: [PATCH 0876/2172] fftools: use the new AVFrame interlace flags Signed-off-by: James Almer --- fftools/ffmpeg.c | 2 +- fftools/ffmpeg_enc.c | 11 +++++++---- fftools/ffprobe.c | 4 ++-- 3 files changed, 10 insertions(+), 7 deletions(-) diff --git a/fftools/ffmpeg.c b/fftools/ffmpeg.c index be9a3b2e34a..23aa343bbcb 100644 --- a/fftools/ffmpeg.c +++ b/fftools/ffmpeg.c @@ -1098,7 +1098,7 @@ static int decode_video(InputStream *ist, const AVPacket *pkt, int *got_output, return ret; if(ist->top_field_first>=0) - decoded_frame->top_field_first = ist->top_field_first; + decoded_frame->flags |= AV_FRAME_FLAG_TOP_FIELD_FIRST; ist->frames_decoded++; diff --git a/fftools/ffmpeg_enc.c b/fftools/ffmpeg_enc.c index 5707199ac52..f2af81baccb 100644 --- a/fftools/ffmpeg_enc.c +++ b/fftools/ffmpeg_enc.c @@ -257,13 +257,16 @@ int enc_open(OutputStream *ost, AVFrame *frame) if (frame) { if (enc_ctx->flags & (AV_CODEC_FLAG_INTERLACED_DCT | AV_CODEC_FLAG_INTERLACED_ME) && ost->top_field_first >= 0) - frame->top_field_first = !!ost->top_field_first; + if (ost->top_field_first) + frame->flags |= AV_FRAME_FLAG_TOP_FIELD_FIRST; + else + frame->flags &= ~AV_FRAME_FLAG_TOP_FIELD_FIRST; - if (frame->interlaced_frame) { + if (frame->flags & AV_FRAME_FLAG_INTERLACED) { if (enc->id == AV_CODEC_ID_MJPEG) - enc_ctx->field_order = frame->top_field_first ? AV_FIELD_TT:AV_FIELD_BB; + enc_ctx->field_order = (frame->flags & AV_FRAME_FLAG_TOP_FIELD_FIRST) ? AV_FIELD_TT:AV_FIELD_BB; else - enc_ctx->field_order = frame->top_field_first ? AV_FIELD_TB:AV_FIELD_BT; + enc_ctx->field_order = (frame->flags & AV_FRAME_FLAG_TOP_FIELD_FIRST) ? AV_FIELD_TB:AV_FIELD_BT; } else enc_ctx->field_order = AV_FIELD_PROGRESSIVE; } diff --git a/fftools/ffprobe.c b/fftools/ffprobe.c index 6e72c37721b..10492011d74 100644 --- a/fftools/ffprobe.c +++ b/fftools/ffprobe.c @@ -2640,8 +2640,8 @@ static void show_frame(WriterContext *w, AVFrame *frame, AVStream *stream, print_int("display_picture_number", frame->display_picture_number); ) #endif - print_int("interlaced_frame", frame->interlaced_frame); - print_int("top_field_first", frame->top_field_first); + print_int("interlaced_frame", !!(frame->flags & AV_FRAME_FLAG_INTERLACED)); + print_int("top_field_first", !!(frame->flags & AV_FRAME_FLAG_TOP_FIELD_FIRST)); print_int("repeat_pict", frame->repeat_pict); print_color_range(w, frame->color_range); From 599abc0f3a0c6a1d9746a3098cd444a45471a160 Mon Sep 17 00:00:00 2001 From: James Almer Date: Wed, 12 Apr 2023 14:18:50 -0300 Subject: [PATCH 0877/2172] avutil/frame: deprecate interlaced_frame and top_field_first Signed-off-by: James Almer --- libavcodec/decode.c | 4 ++++ libavcodec/encode.c | 4 ++++ libavfilter/buffersrc.c | 4 ++++ libavfilter/vf_coreimage.m | 2 ++ libavfilter/vf_deinterlace_vaapi.c | 4 ++++ libavfilter/vf_estdif.c | 4 ++++ libavfilter/vf_field.c | 4 ++++ libavfilter/vf_fieldhint.c | 8 ++++++++ libavfilter/vf_fieldmatch.c | 8 ++++++++ libavfilter/vf_fieldorder.c | 4 ++++ libavfilter/vf_idet.c | 24 ++++++++++++++++++++++++ libavfilter/vf_kerndeint.c | 4 ++++ libavfilter/vf_nnedi.c | 4 ++++ libavfilter/vf_separatefields.c | 4 ++++ libavfilter/vf_setparams.c | 8 ++++++++ libavfilter/vf_telecine.c | 12 ++++++++++++ libavfilter/vf_tinterlace.c | 16 ++++++++++++++++ libavfilter/vf_w3fdif.c | 4 ++++ libavfilter/vf_weave.c | 4 ++++ libavfilter/vsrc_gradients.c | 4 ++++ libavfilter/vsrc_testsrc.c | 4 ++++ libavfilter/yadif_common.c | 8 ++++++++ libavutil/frame.c | 4 ++++ libavutil/frame.h | 8 ++++++++ libavutil/version.h | 1 + 25 files changed, 155 insertions(+) diff --git a/libavcodec/decode.c b/libavcodec/decode.c index 73bba99750c..64a448b54c9 100644 --- a/libavcodec/decode.c +++ b/libavcodec/decode.c @@ -570,8 +570,12 @@ static int decode_receive_frame_internal(AVCodecContext *avctx, AVFrame *frame) } if (!ret) { +#if FF_API_INTERLACED_FRAME +FF_DISABLE_DEPRECATION_WARNINGS frame->interlaced_frame = !!(frame->flags & AV_FRAME_FLAG_INTERLACED); frame->top_field_first = !!(frame->flags & AV_FRAME_FLAG_TOP_FIELD_FIRST); +FF_ENABLE_DEPRECATION_WARNINGS +#endif frame->best_effort_timestamp = guess_correct_pts(avctx, frame->pts, frame->pkt_dts); diff --git a/libavcodec/encode.c b/libavcodec/encode.c index dfcdce6a3c2..0c4b2b0f99d 100644 --- a/libavcodec/encode.c +++ b/libavcodec/encode.c @@ -192,10 +192,14 @@ int ff_encode_get_frame(AVCodecContext *avctx, AVFrame *frame) av_frame_move_ref(frame, avci->buffer_frame); +#if FF_API_INTERLACED_FRAME +FF_DISABLE_DEPRECATION_WARNINGS if (frame->interlaced_frame) frame->flags |= AV_FRAME_FLAG_INTERLACED; if (frame->top_field_first) frame->flags |= AV_FRAME_FLAG_TOP_FIELD_FIRST; +FF_ENABLE_DEPRECATION_WARNINGS +#endif return 0; } diff --git a/libavfilter/buffersrc.c b/libavfilter/buffersrc.c index 927b16ea067..1d2f357bbc7 100644 --- a/libavfilter/buffersrc.c +++ b/libavfilter/buffersrc.c @@ -247,10 +247,14 @@ FF_DISABLE_DEPRECATION_WARNINGS FF_ENABLE_DEPRECATION_WARNINGS #endif +#if FF_API_INTERLACED_FRAME +FF_DISABLE_DEPRECATION_WARNINGS if (copy->interlaced_frame) copy->flags |= AV_FRAME_FLAG_INTERLACED; if (copy->top_field_first) copy->flags |= AV_FRAME_FLAG_TOP_FIELD_FIRST; +FF_ENABLE_DEPRECATION_WARNINGS +#endif ret = ff_filter_frame(ctx->outputs[0], copy); if (ret < 0) diff --git a/libavfilter/vf_coreimage.m b/libavfilter/vf_coreimage.m index a5bfdaef6de..a2e3dbea46c 100644 --- a/libavfilter/vf_coreimage.m +++ b/libavfilter/vf_coreimage.m @@ -302,7 +302,9 @@ static int request_frame(AVFilterLink *link) frame->pts = ctx->pts; frame->duration = 1; frame->key_frame = 1; +#if FF_API_INTERLACED_FRAME frame->interlaced_frame = 0; +#endif frame->flags &= ~AV_FRAME_FLAG_INTERLACED; frame->pict_type = AV_PICTURE_TYPE_I; frame->sample_aspect_ratio = ctx->sar; diff --git a/libavfilter/vf_deinterlace_vaapi.c b/libavfilter/vf_deinterlace_vaapi.c index d4246eb4fc9..cb4f7b32d78 100644 --- a/libavfilter/vf_deinterlace_vaapi.c +++ b/libavfilter/vf_deinterlace_vaapi.c @@ -303,7 +303,11 @@ static int deint_vaapi_filter_frame(AVFilterLink *inlink, AVFrame *input_frame) output_frame->pts = input_frame->pts + ctx->frame_queue[current_frame_index + 1]->pts; } +#if FF_API_INTERLACED_FRAME +FF_DISABLE_DEPRECATION_WARNINGS output_frame->interlaced_frame = 0; +FF_ENABLE_DEPRECATION_WARNINGS +#endif output_frame->flags &= ~AV_FRAME_FLAG_INTERLACED; av_log(avctx, AV_LOG_DEBUG, "Filter output: %s, %ux%u (%"PRId64").\n", diff --git a/libavfilter/vf_estdif.c b/libavfilter/vf_estdif.c index d71d39e2686..2bb1680f430 100644 --- a/libavfilter/vf_estdif.c +++ b/libavfilter/vf_estdif.c @@ -443,7 +443,11 @@ static int filter(AVFilterContext *ctx, AVFrame *in, int64_t pts, int64_t durati if (!out) return AVERROR(ENOMEM); av_frame_copy_props(out, in); +#if FF_API_INTERLACED_FRAME +FF_DISABLE_DEPRECATION_WARNINGS out->interlaced_frame = 0; +FF_ENABLE_DEPRECATION_WARNINGS +#endif out->flags &= ~AV_FRAME_FLAG_INTERLACED; out->pts = pts; out->duration = duration; diff --git a/libavfilter/vf_field.c b/libavfilter/vf_field.c index 66b646c72d8..5c4ff0881c1 100644 --- a/libavfilter/vf_field.c +++ b/libavfilter/vf_field.c @@ -73,7 +73,11 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *inpicref) int i; inpicref->height = outlink->h; +#if FF_API_INTERLACED_FRAME +FF_DISABLE_DEPRECATION_WARNINGS inpicref->interlaced_frame = 0; +FF_ENABLE_DEPRECATION_WARNINGS +#endif inpicref->flags &= ~AV_FRAME_FLAG_INTERLACED; for (i = 0; i < field->nb_planes; i++) { diff --git a/libavfilter/vf_fieldhint.c b/libavfilter/vf_fieldhint.c index df6fb0b8dfc..ff940a50e6f 100644 --- a/libavfilter/vf_fieldhint.c +++ b/libavfilter/vf_fieldhint.c @@ -217,11 +217,19 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in) switch (hint) { case '+': +#if FF_API_INTERLACED_FRAME +FF_DISABLE_DEPRECATION_WARNINGS out->interlaced_frame = 1; +FF_ENABLE_DEPRECATION_WARNINGS +#endif out->flags |= AV_FRAME_FLAG_INTERLACED; break; case '-': +#if FF_API_INTERLACED_FRAME +FF_DISABLE_DEPRECATION_WARNINGS out->interlaced_frame = 0; +FF_ENABLE_DEPRECATION_WARNINGS +#endif out->flags &= ~AV_FRAME_FLAG_INTERLACED; break; case '=': diff --git a/libavfilter/vf_fieldmatch.c b/libavfilter/vf_fieldmatch.c index a177cb3fd8b..71bef7b30fe 100644 --- a/libavfilter/vf_fieldmatch.c +++ b/libavfilter/vf_fieldmatch.c @@ -820,12 +820,20 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in) /* mark the frame we are unable to match properly as interlaced so a proper * de-interlacer can take the relay */ +#if FF_API_INTERLACED_FRAME +FF_DISABLE_DEPRECATION_WARNINGS dst->interlaced_frame = interlaced_frame; +FF_ENABLE_DEPRECATION_WARNINGS +#endif if (interlaced_frame) { dst->flags |= AV_FRAME_FLAG_INTERLACED; av_log(ctx, AV_LOG_WARNING, "Frame #%"PRId64" at %s is still interlaced\n", outlink->frame_count_in, av_ts2timestr(in->pts, &inlink->time_base)); +#if FF_API_INTERLACED_FRAME +FF_DISABLE_DEPRECATION_WARNINGS dst->top_field_first = field; +FF_ENABLE_DEPRECATION_WARNINGS +#endif if (field) dst->flags |= AV_FRAME_FLAG_TOP_FIELD_FIRST; else diff --git a/libavfilter/vf_fieldorder.c b/libavfilter/vf_fieldorder.c index e4d0eda1a49..cf6efa6e54b 100644 --- a/libavfilter/vf_fieldorder.c +++ b/libavfilter/vf_fieldorder.c @@ -140,7 +140,11 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *frame) } } } +#if FF_API_INTERLACED_FRAME +FF_DISABLE_DEPRECATION_WARNINGS out->top_field_first = s->dst_tff; +FF_ENABLE_DEPRECATION_WARNINGS +#endif if (s->dst_tff) out->flags |= AV_FRAME_FLAG_TOP_FIELD_FIRST; else diff --git a/libavfilter/vf_idet.c b/libavfilter/vf_idet.c index 0f150a273de..abd375230aa 100644 --- a/libavfilter/vf_idet.c +++ b/libavfilter/vf_idet.c @@ -183,16 +183,28 @@ static void filter(AVFilterContext *ctx) } if (idet->last_type == TFF){ +#if FF_API_INTERLACED_FRAME +FF_DISABLE_DEPRECATION_WARNINGS idet->cur->top_field_first = 1; idet->cur->interlaced_frame = 1; +FF_ENABLE_DEPRECATION_WARNINGS +#endif idet->cur->flags |= (AV_FRAME_FLAG_INTERLACED | AV_FRAME_FLAG_TOP_FIELD_FIRST); }else if(idet->last_type == BFF){ +#if FF_API_INTERLACED_FRAME +FF_DISABLE_DEPRECATION_WARNINGS idet->cur->top_field_first = 0; idet->cur->interlaced_frame = 1; +FF_ENABLE_DEPRECATION_WARNINGS +#endif idet->cur->flags &= ~AV_FRAME_FLAG_TOP_FIELD_FIRST; idet->cur->flags |= AV_FRAME_FLAG_INTERLACED; }else if(idet->last_type == PROGRESSIVE){ +#if FF_API_INTERLACED_FRAME +FF_DISABLE_DEPRECATION_WARNINGS idet->cur->interlaced_frame = 0; +FF_ENABLE_DEPRECATION_WARNINGS +#endif idet->cur->flags &= ~AV_FRAME_FLAG_INTERLACED; } @@ -248,7 +260,11 @@ static int filter_frame(AVFilterLink *link, AVFrame *picref) } if (idet->analyze_interlaced_flag_done) { if ((picref->flags & AV_FRAME_FLAG_INTERLACED) && idet->interlaced_flag_accuracy < 0) { +#if FF_API_INTERLACED_FRAME +FF_DISABLE_DEPRECATION_WARNINGS picref->interlaced_frame = 0; +FF_ENABLE_DEPRECATION_WARNINGS +#endif picref->flags &= ~AV_FRAME_FLAG_INTERLACED; } return ff_filter_frame(ctx->outputs[0], picref); @@ -289,7 +305,11 @@ static int filter_frame(AVFilterLink *link, AVFrame *picref) if (idet->analyze_interlaced_flag) { if (idet->cur->flags & AV_FRAME_FLAG_INTERLACED) { +#if FF_API_INTERLACED_FRAME +FF_DISABLE_DEPRECATION_WARNINGS idet->cur->interlaced_frame = 0; +FF_ENABLE_DEPRECATION_WARNINGS +#endif idet->cur->flags &= ~AV_FRAME_FLAG_INTERLACED; filter(ctx); if (idet->last_type == PROGRESSIVE) { @@ -303,7 +323,11 @@ static int filter_frame(AVFilterLink *link, AVFrame *picref) ff_filter_frame(ctx->outputs[0], av_frame_clone(idet->cur)); if ((idet->next->flags & AV_FRAME_FLAG_INTERLACED) && idet->interlaced_flag_accuracy < 0) { +#if FF_API_INTERLACED_FRAME +FF_DISABLE_DEPRECATION_WARNINGS idet->next->interlaced_frame = 0; +FF_ENABLE_DEPRECATION_WARNINGS +#endif idet->next->flags &= ~AV_FRAME_FLAG_INTERLACED; } idet->analyze_interlaced_flag_done = 1; diff --git a/libavfilter/vf_kerndeint.c b/libavfilter/vf_kerndeint.c index e8ec1f474ab..8aec5afe98f 100644 --- a/libavfilter/vf_kerndeint.c +++ b/libavfilter/vf_kerndeint.c @@ -141,7 +141,11 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *inpic) return AVERROR(ENOMEM); } av_frame_copy_props(outpic, inpic); +#if FF_API_INTERLACED_FRAME +FF_DISABLE_DEPRECATION_WARNINGS outpic->interlaced_frame = 0; +FF_ENABLE_DEPRECATION_WARNINGS +#endif outpic->flags &= ~AV_FRAME_FLAG_INTERLACED; for (plane = 0; plane < 4 && inpic->data[plane] && inpic->linesize[plane]; plane++) { diff --git a/libavfilter/vf_nnedi.c b/libavfilter/vf_nnedi.c index 39cb4f5a85f..1bb8c21e10e 100644 --- a/libavfilter/vf_nnedi.c +++ b/libavfilter/vf_nnedi.c @@ -665,7 +665,11 @@ static int get_frame(AVFilterContext *ctx, int is_second) if (!dst) return AVERROR(ENOMEM); av_frame_copy_props(dst, s->prev); +#if FF_API_INTERLACED_FRAME +FF_DISABLE_DEPRECATION_WARNINGS dst->interlaced_frame = 0; +FF_ENABLE_DEPRECATION_WARNINGS +#endif dst->flags &= ~AV_FRAME_FLAG_INTERLACED; dst->pts = s->pts; diff --git a/libavfilter/vf_separatefields.c b/libavfilter/vf_separatefields.c index 814ea52e212..723974afaa0 100644 --- a/libavfilter/vf_separatefields.c +++ b/libavfilter/vf_separatefields.c @@ -70,7 +70,11 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *inpicref) int ret; inpicref->height = outlink->h; +#if FF_API_INTERLACED_FRAME +FF_DISABLE_DEPRECATION_WARNINGS inpicref->interlaced_frame = 0; +FF_ENABLE_DEPRECATION_WARNINGS +#endif inpicref->flags &= ~AV_FRAME_FLAG_INTERLACED; if (!s->second) { diff --git a/libavfilter/vf_setparams.c b/libavfilter/vf_setparams.c index 0165a5aaa61..321a64a14eb 100644 --- a/libavfilter/vf_setparams.c +++ b/libavfilter/vf_setparams.c @@ -127,11 +127,19 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *frame) /* set field */ if (s->field_mode == MODE_PROG) { +#if FF_API_INTERLACED_FRAME +FF_DISABLE_DEPRECATION_WARNINGS frame->interlaced_frame = 0; +FF_ENABLE_DEPRECATION_WARNINGS +#endif frame->flags &= ~AV_FRAME_FLAG_INTERLACED; } else if (s->field_mode != MODE_AUTO) { +#if FF_API_INTERLACED_FRAME +FF_DISABLE_DEPRECATION_WARNINGS frame->interlaced_frame = 1; frame->top_field_first = s->field_mode; +FF_ENABLE_DEPRECATION_WARNINGS +#endif frame->flags |= AV_FRAME_FLAG_INTERLACED; if (s->field_mode) frame->flags |= AV_FRAME_FLAG_TOP_FIELD_FIRST; diff --git a/libavfilter/vf_telecine.c b/libavfilter/vf_telecine.c index d8daa259393..8343b114669 100644 --- a/libavfilter/vf_telecine.c +++ b/libavfilter/vf_telecine.c @@ -204,8 +204,12 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *inpicref) s->stride[i], (s->planeheight[i] - !s->first_field + 1) / 2); } +#if FF_API_INTERLACED_FRAME +FF_DISABLE_DEPRECATION_WARNINGS s->frame[nout]->interlaced_frame = 1; s->frame[nout]->top_field_first = !s->first_field; +FF_ENABLE_DEPRECATION_WARNINGS +#endif s->frame[nout]->flags |= AV_FRAME_FLAG_INTERLACED; if (s->first_field) s->frame[nout]->flags &= ~AV_FRAME_FLAG_TOP_FIELD_FIRST; @@ -228,8 +232,12 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *inpicref) inpicref->data[i], inpicref->linesize[i], s->stride[i], s->planeheight[i]); +#if FF_API_INTERLACED_FRAME +FF_DISABLE_DEPRECATION_WARNINGS s->frame[nout]->interlaced_frame = inpicref->interlaced_frame; s->frame[nout]->top_field_first = inpicref->top_field_first; +FF_ENABLE_DEPRECATION_WARNINGS +#endif s->frame[nout]->flags |= (inpicref->flags & (AV_FRAME_FLAG_INTERLACED | AV_FRAME_FLAG_TOP_FIELD_FIRST)); nout++; len -= 2; @@ -256,8 +264,12 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *inpicref) } av_frame_copy_props(frame, inpicref); +#if FF_API_INTERLACED_FRAME +FF_DISABLE_DEPRECATION_WARNINGS frame->interlaced_frame = interlaced; frame->top_field_first = tff; +FF_ENABLE_DEPRECATION_WARNINGS +#endif if (interlaced) frame->flags |= AV_FRAME_FLAG_INTERLACED; else diff --git a/libavfilter/vf_tinterlace.c b/libavfilter/vf_tinterlace.c index 742d4e195a0..8b0cbbcf95a 100644 --- a/libavfilter/vf_tinterlace.c +++ b/libavfilter/vf_tinterlace.c @@ -391,8 +391,12 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *picref) return AVERROR(ENOMEM); av_frame_copy_props(out, cur); out->height = outlink->h; +#if FF_API_INTERLACED_FRAME +FF_DISABLE_DEPRECATION_WARNINGS out->interlaced_frame = 1; out->top_field_first = 1; +FF_ENABLE_DEPRECATION_WARNINGS +#endif out->flags |= AV_FRAME_FLAG_INTERLACED | AV_FRAME_FLAG_TOP_FIELD_FIRST; out->sample_aspect_ratio = av_mul_q(cur->sample_aspect_ratio, av_make_q(2, 1)); @@ -460,8 +464,12 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *picref) if (!out) return AVERROR(ENOMEM); av_frame_copy_props(out, cur); +#if FF_API_INTERLACED_FRAME +FF_DISABLE_DEPRECATION_WARNINGS out->interlaced_frame = 1; out->top_field_first = tff; +FF_ENABLE_DEPRECATION_WARNINGS +#endif out->flags |= AV_FRAME_FLAG_INTERLACED; if (tff) out->flags |= AV_FRAME_FLAG_TOP_FIELD_FIRST; @@ -487,7 +495,11 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *picref) out = av_frame_clone(cur); if (!out) return AVERROR(ENOMEM); +#if FF_API_INTERLACED_FRAME +FF_DISABLE_DEPRECATION_WARNINGS out->interlaced_frame = 1; +FF_ENABLE_DEPRECATION_WARNINGS +#endif out->flags |= AV_FRAME_FLAG_INTERLACED; if (cur->pts != AV_NOPTS_VALUE) out->pts = cur->pts*2; @@ -502,8 +514,12 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *picref) if (!out) return AVERROR(ENOMEM); av_frame_copy_props(out, next); +#if FF_API_INTERLACED_FRAME +FF_DISABLE_DEPRECATION_WARNINGS out->interlaced_frame = 1; out->top_field_first = !tff; +FF_ENABLE_DEPRECATION_WARNINGS +#endif out->flags |= AV_FRAME_FLAG_INTERLACED; if (tff) out->flags &= ~AV_FRAME_FLAG_TOP_FIELD_FIRST; diff --git a/libavfilter/vf_w3fdif.c b/libavfilter/vf_w3fdif.c index 7c3ffbc5f05..f10cf06a497 100644 --- a/libavfilter/vf_w3fdif.c +++ b/libavfilter/vf_w3fdif.c @@ -486,7 +486,11 @@ static int filter(AVFilterContext *ctx, int is_second) if (!out) return AVERROR(ENOMEM); av_frame_copy_props(out, s->cur); +#if FF_API_INTERLACED_FRAME +FF_DISABLE_DEPRECATION_WARNINGS out->interlaced_frame = 0; +FF_ENABLE_DEPRECATION_WARNINGS +#endif out->flags &= ~AV_FRAME_FLAG_INTERLACED; if (!is_second) { diff --git a/libavfilter/vf_weave.c b/libavfilter/vf_weave.c index e738c9ba175..2e64d81f275 100644 --- a/libavfilter/vf_weave.c +++ b/libavfilter/vf_weave.c @@ -148,8 +148,12 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in) FFMIN(s->planeheight[1], ff_filter_get_nb_threads(ctx))); out->pts = s->double_weave ? s->prev->pts : in->pts / 2; +#if FF_API_INTERLACED_FRAME +FF_DISABLE_DEPRECATION_WARNINGS out->interlaced_frame = 1; out->top_field_first = !s->first_field; +FF_ENABLE_DEPRECATION_WARNINGS +#endif out->flags |= AV_FRAME_FLAG_INTERLACED; if (s->first_field) out->flags &= ~AV_FRAME_FLAG_TOP_FIELD_FIRST; diff --git a/libavfilter/vsrc_gradients.c b/libavfilter/vsrc_gradients.c index 2811dd8bb63..f50b4d3cc70 100644 --- a/libavfilter/vsrc_gradients.c +++ b/libavfilter/vsrc_gradients.c @@ -398,7 +398,11 @@ static int activate(AVFilterContext *ctx) return AVERROR(ENOMEM); frame->key_frame = 1; +#if FF_API_INTERLACED_FRAME +FF_DISABLE_DEPRECATION_WARNINGS frame->interlaced_frame = 0; +FF_ENABLE_DEPRECATION_WARNINGS +#endif frame->flags &= ~AV_FRAME_FLAG_INTERLACED; frame->pict_type = AV_PICTURE_TYPE_I; frame->sample_aspect_ratio = (AVRational) {1, 1}; diff --git a/libavfilter/vsrc_testsrc.c b/libavfilter/vsrc_testsrc.c index cef3a9be36d..c358f9ada26 100644 --- a/libavfilter/vsrc_testsrc.c +++ b/libavfilter/vsrc_testsrc.c @@ -185,7 +185,11 @@ static int activate(AVFilterContext *ctx) frame->pts = test->pts; frame->duration = 1; frame->key_frame = 1; +#if FF_API_INTERLACED_FRAME +FF_DISABLE_DEPRECATION_WARNINGS frame->interlaced_frame = 0; +FF_ENABLE_DEPRECATION_WARNINGS +#endif frame->flags &= ~AV_FRAME_FLAG_INTERLACED; frame->pict_type = AV_PICTURE_TYPE_I; frame->sample_aspect_ratio = test->sar; diff --git a/libavfilter/yadif_common.c b/libavfilter/yadif_common.c index 5b29d2e6d81..2bd61111401 100644 --- a/libavfilter/yadif_common.c +++ b/libavfilter/yadif_common.c @@ -43,7 +43,11 @@ static int return_frame(AVFilterContext *ctx, int is_second) return AVERROR(ENOMEM); av_frame_copy_props(yadif->out, yadif->cur); +#if FF_API_INTERLACED_FRAME +FF_DISABLE_DEPRECATION_WARNINGS yadif->out->interlaced_frame = 0; +FF_ENABLE_DEPRECATION_WARNINGS +#endif yadif->out->flags &= ~AV_FRAME_FLAG_INTERLACED; if (yadif->current_field == YADIF_FIELD_BACK_END) yadif->current_field = YADIF_FIELD_END; @@ -149,7 +153,11 @@ int ff_yadif_filter_frame(AVFilterLink *link, AVFrame *frame) return AVERROR(ENOMEM); av_frame_copy_props(yadif->out, yadif->cur); +#if FF_API_INTERLACED_FRAME +FF_DISABLE_DEPRECATION_WARNINGS yadif->out->interlaced_frame = 0; +FF_ENABLE_DEPRECATION_WARNINGS +#endif yadif->out->flags &= ~AV_FRAME_FLAG_INTERLACED; if (yadif->out->pts != AV_NOPTS_VALUE) diff --git a/libavutil/frame.c b/libavutil/frame.c index f420a6e1871..e544b690fe7 100644 --- a/libavutil/frame.c +++ b/libavutil/frame.c @@ -275,8 +275,12 @@ static int frame_copy_props(AVFrame *dst, const AVFrame *src, int force_copy) dst->pts = src->pts; dst->duration = src->duration; dst->repeat_pict = src->repeat_pict; +#if FF_API_INTERLACED_FRAME +FF_DISABLE_DEPRECATION_WARNINGS dst->interlaced_frame = src->interlaced_frame; dst->top_field_first = src->top_field_first; +FF_ENABLE_DEPRECATION_WARNINGS +#endif dst->palette_has_changed = src->palette_has_changed; dst->sample_rate = src->sample_rate; dst->opaque = src->opaque; diff --git a/libavutil/frame.h b/libavutil/frame.h index 125ba3aa358..095fc39c3f6 100644 --- a/libavutil/frame.h +++ b/libavutil/frame.h @@ -491,15 +491,23 @@ typedef struct AVFrame { */ int repeat_pict; +#if FF_API_INTERLACED_FRAME /** * The content of the picture is interlaced. + * + * @deprecated Use AV_FRAME_FLAG_INTERLACED instead */ + attribute_deprecated int interlaced_frame; /** * If the content is interlaced, is top field displayed first. + * + * @deprecated Use AV_FRAME_FLAG_TOP_FIELD_FIRST instead */ + attribute_deprecated int top_field_first; +#endif /** * Tell user application that palette has changed from previous frame. diff --git a/libavutil/version.h b/libavutil/version.h index 40f92af0550..6a5e2c48818 100644 --- a/libavutil/version.h +++ b/libavutil/version.h @@ -115,6 +115,7 @@ #define FF_API_FRAME_PICTURE_NUMBER (LIBAVUTIL_VERSION_MAJOR < 59) #define FF_API_HDR_VIVID_THREE_SPLINE (LIBAVUTIL_VERSION_MAJOR < 59) #define FF_API_FRAME_PKT (LIBAVUTIL_VERSION_MAJOR < 59) +#define FF_API_INTERLACED_FRAME (LIBAVUTIL_VERSION_MAJOR < 59) /** * @} From cc11191fda0471017b03c1434d6d8cb79f6914e5 Mon Sep 17 00:00:00 2001 From: James Almer Date: Tue, 11 Apr 2023 13:59:49 -0300 Subject: [PATCH 0878/2172] avutil/frame: add a keyframe flag to AVFrame Signed-off-by: James Almer --- libavutil/frame.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/libavutil/frame.h b/libavutil/frame.h index 095fc39c3f6..61a218268e5 100644 --- a/libavutil/frame.h +++ b/libavutil/frame.h @@ -590,6 +590,10 @@ typedef struct AVFrame { * The frame data may be corrupted, e.g. due to decoding errors. */ #define AV_FRAME_FLAG_CORRUPT (1 << 0) +/** + * A flag to mark frames that are keyframes. + */ +#define AV_FRAME_FLAG_KEY (1 << 1) /** * A flag to mark the frames which need to be decoded, but shouldn't be output. */ From dc7bd7c5a5ad5ea800dfb63cc5dd15670d065527 Mon Sep 17 00:00:00 2001 From: James Almer Date: Wed, 12 Apr 2023 13:58:54 -0300 Subject: [PATCH 0879/2172] avcodec: use the new AVFrame key_frame flag in all decoders and encoders Signed-off-by: James Almer --- libavcodec/012v.c | 2 +- libavcodec/4xm.c | 5 ++++- libavcodec/agm.c | 7 +++++-- libavcodec/aic.c | 2 +- libavcodec/aliaspixdec.c | 2 +- libavcodec/arbc.c | 5 ++++- libavcodec/argo.c | 5 ++++- libavcodec/asvdec.c | 2 +- libavcodec/av1dec.c | 5 ++++- libavcodec/avrndec.c | 2 +- libavcodec/avs.c | 4 ++-- libavcodec/avuidec.c | 2 +- libavcodec/bfi.c | 4 ++-- libavcodec/bitpacked_dec.c | 2 +- libavcodec/bmp.c | 2 +- libavcodec/brenderpix.c | 2 +- libavcodec/c93.c | 4 ++-- libavcodec/cdxl.c | 2 +- libavcodec/cinepak.c | 4 ++-- libavcodec/clearvideo.c | 4 ++-- libavcodec/cljrdec.c | 2 +- libavcodec/cllc.c | 2 +- libavcodec/cpia.c | 4 ++-- libavcodec/cri.c | 2 +- libavcodec/cscd.c | 4 ++-- libavcodec/cuviddec.c | 5 ++++- libavcodec/dds.c | 2 +- libavcodec/decode.c | 3 +++ libavcodec/diracdec.c | 5 ++++- libavcodec/dnxhddec.c | 2 +- libavcodec/dvdec.c | 2 +- libavcodec/dxa.c | 10 +++++----- libavcodec/dxtory.c | 2 +- libavcodec/dxv.c | 2 +- libavcodec/eacmv.c | 4 ++-- libavcodec/eatgq.c | 2 +- libavcodec/eatgv.c | 4 ++-- libavcodec/encode.c | 2 ++ libavcodec/ffv1dec.c | 14 +++++++------- libavcodec/fic.c | 4 ++-- libavcodec/fitsdec.c | 2 +- libavcodec/fmvc.c | 4 ++-- libavcodec/fraps.c | 2 +- libavcodec/frwu.c | 2 +- libavcodec/g2meet.c | 5 ++++- libavcodec/gemdec.c | 2 +- libavcodec/gifdec.c | 4 ++-- libavcodec/h261dec.c | 5 ++++- libavcodec/h264_slice.c | 10 +++++----- libavcodec/h264dec.c | 4 ++-- libavcodec/hapdec.c | 2 +- libavcodec/hdrdec.c | 2 +- libavcodec/hevcdec.c | 5 ++++- libavcodec/hnm4video.c | 4 ++-- libavcodec/hq_hqa.c | 2 +- libavcodec/hqx.c | 2 +- libavcodec/iff.c | 4 ++-- libavcodec/imm4.c | 10 +++++----- libavcodec/imx.c | 10 +++++----- libavcodec/jpeg2000dec.c | 2 +- libavcodec/jvdec.c | 2 +- libavcodec/kmvc.c | 4 ++-- libavcodec/lagarith.c | 2 +- libavcodec/lcldec.c | 2 +- libavcodec/libaomdec.c | 5 ++++- libavcodec/libdav1d.c | 5 ++++- libavcodec/libjxldec.c | 2 +- libavcodec/librsvgdec.c | 2 +- libavcodec/libuavs3d.c | 5 ++++- libavcodec/loco.c | 2 +- libavcodec/lscrdec.c | 13 ++++++++----- libavcodec/m101.c | 2 +- libavcodec/magicyuv.c | 2 +- libavcodec/mdec.c | 2 +- libavcodec/midivid.c | 5 ++++- libavcodec/mjpegdec.c | 4 ++-- libavcodec/mobiclip.c | 4 ++-- libavcodec/mpeg12dec.c | 12 +++++++++--- libavcodec/mpeg12enc.c | 2 +- libavcodec/mpegvideo_dec.c | 9 ++++++--- libavcodec/mpegvideo_enc.c | 18 +++++++++++++----- libavcodec/mscc.c | 2 +- libavcodec/msp2dec.c | 2 +- libavcodec/mss1.c | 4 ++-- libavcodec/mss2.c | 5 ++++- libavcodec/mss3.c | 5 ++++- libavcodec/mss4.c | 5 ++++- libavcodec/mv30.c | 6 +++--- libavcodec/mvcdec.c | 2 +- libavcodec/mvha.c | 2 +- libavcodec/mwsc.c | 9 ++++++--- libavcodec/mxpegdec.c | 4 ++-- libavcodec/notchlc.c | 2 +- libavcodec/nuv.c | 5 ++++- libavcodec/pafvideo.c | 4 ++-- libavcodec/pdvdec.c | 2 +- libavcodec/pgxdec.c | 2 +- libavcodec/photocd.c | 2 +- libavcodec/pixlet.c | 2 +- libavcodec/pngdec.c | 2 +- libavcodec/pnmdec.c | 2 +- libavcodec/proresdec2.c | 2 +- libavcodec/prosumer.c | 2 +- libavcodec/qdrw.c | 2 +- libavcodec/qoidec.c | 2 +- libavcodec/qpeg.c | 5 ++++- libavcodec/qsvdec.c | 8 ++++++-- libavcodec/r210dec.c | 2 +- libavcodec/rasc.c | 5 ++++- libavcodec/rawdec.c | 2 +- libavcodec/rscc.c | 2 +- libavcodec/sanm.c | 4 +++- libavcodec/scpr.c | 12 ++++++------ libavcodec/screenpresso.c | 2 +- libavcodec/sga.c | 2 +- libavcodec/sgidec.c | 2 +- libavcodec/sgirledec.c | 2 +- libavcodec/sheervideo.c | 2 +- libavcodec/smacker.c | 8 +++++--- libavcodec/snow.c | 7 +++++-- libavcodec/snowenc.c | 4 ++-- libavcodec/speedhqdec.c | 2 +- libavcodec/svq3.c | 5 ++++- libavcodec/targa_y216dec.c | 2 +- libavcodec/tdsc.c | 2 +- libavcodec/tiff.c | 3 ++- libavcodec/tmv.c | 2 +- libavcodec/truemotion2.c | 8 +++++--- libavcodec/truemotion2rt.c | 2 +- libavcodec/utvideodec.c | 2 +- libavcodec/v210dec.c | 2 +- libavcodec/v210x.c | 2 +- libavcodec/v308dec.c | 2 +- libavcodec/v408dec.c | 2 +- libavcodec/v410dec.c | 2 +- libavcodec/v4l2_buffers.c | 3 ++- libavcodec/vble.c | 2 +- libavcodec/vbndec.c | 2 +- libavcodec/vc1dec.c | 5 ++++- libavcodec/vcr1.c | 2 +- libavcodec/vmnc.c | 4 ++-- libavcodec/vp3.c | 5 ++++- libavcodec/vp5.c | 11 +++++++---- libavcodec/vp56.c | 11 ++++++----- libavcodec/vp6.c | 11 +++++++---- libavcodec/vp8.c | 5 ++++- libavcodec/vp9.c | 5 ++++- libavcodec/wbmpdec.c | 2 +- libavcodec/wcmv.c | 5 ++++- libavcodec/webp.c | 2 +- libavcodec/wnv1.c | 2 +- libavcodec/xbmdec.c | 2 +- libavcodec/xl.c | 2 +- libavcodec/xpmdec.c | 2 +- libavcodec/xwddec.c | 2 +- libavcodec/y41pdec.c | 2 +- libavcodec/ylc.c | 2 +- libavcodec/yuv4dec.c | 2 +- libavcodec/zerocodec.c | 4 ++-- libavcodec/zmbv.c | 4 ++-- 160 files changed, 371 insertions(+), 243 deletions(-) diff --git a/libavcodec/012v.c b/libavcodec/012v.c index f0197cd8f90..fa5eb0f95ef 100644 --- a/libavcodec/012v.c +++ b/libavcodec/012v.c @@ -65,7 +65,7 @@ static int zero12v_decode_frame(AVCodecContext *avctx, AVFrame *pic, return ret; pic->pict_type = AV_PICTURE_TYPE_I; - pic->key_frame = 1; + pic->flags |= AV_FRAME_FLAG_KEY; line_end = avpkt->data + stride; for (line = 0; line < avctx->height; line++) { diff --git a/libavcodec/4xm.c b/libavcodec/4xm.c index fab3fb5b77f..411e50da7c0 100644 --- a/libavcodec/4xm.c +++ b/libavcodec/4xm.c @@ -957,7 +957,10 @@ static int decode_frame(AVCodecContext *avctx, AVFrame *picture, return AVERROR_INVALIDDATA; } - picture->key_frame = picture->pict_type == AV_PICTURE_TYPE_I; + if (picture->pict_type == AV_PICTURE_TYPE_I) + picture->flags |= AV_FRAME_FLAG_KEY; + else + picture->flags &= ~AV_FRAME_FLAG_KEY; av_image_copy_plane(picture->data[0], picture->linesize[0], (const uint8_t*)f->frame_buffer, avctx->width * 2, diff --git a/libavcodec/agm.c b/libavcodec/agm.c index b37f1a42c96..55cf0b47c83 100644 --- a/libavcodec/agm.c +++ b/libavcodec/agm.c @@ -1100,7 +1100,10 @@ static int decode_frame(AVCodecContext *avctx, AVFrame *frame, return AVERROR_INVALIDDATA; s->key_frame = (avpkt->flags & AV_PKT_FLAG_KEY); - frame->key_frame = s->key_frame; + if (s->key_frame) + frame->flags |= AV_FRAME_FLAG_KEY; + else + frame->flags &= ~AV_FRAME_FLAG_KEY; frame->pict_type = s->key_frame ? AV_PICTURE_TYPE_I : AV_PICTURE_TYPE_P; if (!s->key_frame) { @@ -1171,7 +1174,7 @@ static int decode_frame(AVCodecContext *avctx, AVFrame *frame, if ((ret = ff_get_buffer(avctx, frame, AV_GET_BUFFER_FLAG_REF)) < 0) return ret; - if (frame->key_frame) { + if (frame->flags & AV_FRAME_FLAG_KEY) { if (!s->dct && !s->rgb) ret = decode_raw_intra(avctx, gbyte, frame); else if (!s->dct && s->rgb) diff --git a/libavcodec/aic.c b/libavcodec/aic.c index 7ba1c02fdd4..f8b0f60354c 100644 --- a/libavcodec/aic.c +++ b/libavcodec/aic.c @@ -393,7 +393,7 @@ static int aic_decode_frame(AVCodecContext *avctx, AVFrame *frame, ctx->frame = frame; ctx->frame->pict_type = AV_PICTURE_TYPE_I; - ctx->frame->key_frame = 1; + ctx->frame->flags |= AV_FRAME_FLAG_KEY; off = FFALIGN(AIC_HDR_SIZE + ctx->num_x_slices * ctx->mb_height * 2, 4); diff --git a/libavcodec/aliaspixdec.c b/libavcodec/aliaspixdec.c index 45155d79cde..72f810d408e 100644 --- a/libavcodec/aliaspixdec.c +++ b/libavcodec/aliaspixdec.c @@ -70,7 +70,7 @@ static int decode_frame(AVCodecContext *avctx, AVFrame *f, return ret; f->pict_type = AV_PICTURE_TYPE_I; - f->key_frame = 1; + f->flags |= AV_FRAME_FLAG_KEY; x = 0; y = 1; diff --git a/libavcodec/arbc.c b/libavcodec/arbc.c index 343c56695ea..1b349f4dd61 100644 --- a/libavcodec/arbc.c +++ b/libavcodec/arbc.c @@ -171,7 +171,10 @@ static int decode_frame(AVCodecContext *avctx, AVFrame *frame, return ret; frame->pict_type = prev_pixels <= 0 ? AV_PICTURE_TYPE_I : AV_PICTURE_TYPE_P; - frame->key_frame = prev_pixels <= 0; + if (prev_pixels <= 0) + frame->flags |= AV_FRAME_FLAG_KEY; + else + frame->flags &= ~AV_FRAME_FLAG_KEY; *got_frame = 1; return avpkt->size; diff --git a/libavcodec/argo.c b/libavcodec/argo.c index 9bedb1394d0..589feed4101 100644 --- a/libavcodec/argo.c +++ b/libavcodec/argo.c @@ -666,7 +666,10 @@ static int decode_frame(AVCodecContext *avctx, AVFrame *rframe, return ret; frame->pict_type = s->key ? AV_PICTURE_TYPE_I : AV_PICTURE_TYPE_P; - frame->key_frame = s->key; + if (s->key) + frame->flags |= AV_FRAME_FLAG_KEY; + else + frame->flags &= ~AV_FRAME_FLAG_KEY; *got_frame = 1; return avpkt->size; diff --git a/libavcodec/asvdec.c b/libavcodec/asvdec.c index 699aab9f8f9..62295b2dbb4 100644 --- a/libavcodec/asvdec.c +++ b/libavcodec/asvdec.c @@ -245,7 +245,7 @@ static int decode_frame(AVCodecContext *avctx, AVFrame *p, if ((ret = ff_get_buffer(avctx, p, 0)) < 0) return ret; p->pict_type = AV_PICTURE_TYPE_I; - p->key_frame = 1; + p->flags |= AV_FRAME_FLAG_KEY; if (avctx->codec_id == AV_CODEC_ID_ASV1) { av_fast_padded_malloc(&a->bitstream_buffer, &a->bitstream_buffer_size, diff --git a/libavcodec/av1dec.c b/libavcodec/av1dec.c index 807852e317e..c90c9c1a69e 100644 --- a/libavcodec/av1dec.c +++ b/libavcodec/av1dec.c @@ -846,7 +846,10 @@ static int av1_frame_alloc(AVCodecContext *avctx, AV1Frame *f) goto fail; frame = f->f; - frame->key_frame = header->frame_type == AV1_FRAME_KEY; + if (header->frame_type == AV1_FRAME_KEY) + frame->flags |= AV_FRAME_FLAG_KEY; + else + frame->flags &= ~AV_FRAME_FLAG_KEY; switch (header->frame_type) { case AV1_FRAME_KEY: diff --git a/libavcodec/avrndec.c b/libavcodec/avrndec.c index ef194058fc5..97d28246255 100644 --- a/libavcodec/avrndec.c +++ b/libavcodec/avrndec.c @@ -68,7 +68,7 @@ static int decode_frame(AVCodecContext *avctx, AVFrame *p, if ((ret = ff_get_buffer(avctx, p, 0)) < 0) return ret; p->pict_type= AV_PICTURE_TYPE_I; - p->key_frame= 1; + p->flags |= AV_FRAME_FLAG_KEY; if(a->interlace) { buf += (true_height - avctx->height)*avctx->width; diff --git a/libavcodec/avs.c b/libavcodec/avs.c index a1c9d3c436f..b53175f6400 100644 --- a/libavcodec/avs.c +++ b/libavcodec/avs.c @@ -61,7 +61,7 @@ static int avs_decode_frame(AVCodecContext * avctx, AVFrame *picture, if ((ret = ff_reget_buffer(avctx, p, 0)) < 0) return ret; p->pict_type = AV_PICTURE_TYPE_P; - p->key_frame = 0; + p->flags &= ~AV_FRAME_FLAG_KEY; out = p->data[0]; stride = p->linesize[0]; @@ -97,7 +97,7 @@ static int avs_decode_frame(AVCodecContext * avctx, AVFrame *picture, switch (sub_type) { case AVS_I_FRAME: p->pict_type = AV_PICTURE_TYPE_I; - p->key_frame = 1; + p->flags |= AV_FRAME_FLAG_KEY; case AVS_P_FRAME_3X3: vect_w = 3; vect_h = 3; diff --git a/libavcodec/avuidec.c b/libavcodec/avuidec.c index ba157e167cd..48b23d4875f 100644 --- a/libavcodec/avuidec.c +++ b/libavcodec/avuidec.c @@ -71,7 +71,7 @@ static int avui_decode_frame(AVCodecContext *avctx, AVFrame *pic, if ((ret = ff_get_buffer(avctx, pic, 0)) < 0) return ret; - pic->key_frame = 1; + pic->flags |= AV_FRAME_FLAG_KEY; pic->pict_type = AV_PICTURE_TYPE_I; if (!interlaced) { diff --git a/libavcodec/bfi.c b/libavcodec/bfi.c index c2682724515..55429d4b7c5 100644 --- a/libavcodec/bfi.c +++ b/libavcodec/bfi.c @@ -68,7 +68,7 @@ static int bfi_decode_frame(AVCodecContext *avctx, AVFrame *frame, /* Set frame parameters and palette, if necessary */ if (!avctx->frame_num) { frame->pict_type = AV_PICTURE_TYPE_I; - frame->key_frame = 1; + frame->flags |= AV_FRAME_FLAG_KEY; /* Setting the palette */ if (avctx->extradata_size > 768) { av_log(avctx, AV_LOG_ERROR, "Palette is too large.\n"); @@ -87,7 +87,7 @@ static int bfi_decode_frame(AVCodecContext *avctx, AVFrame *frame, frame->palette_has_changed = 1; } else { frame->pict_type = AV_PICTURE_TYPE_P; - frame->key_frame = 0; + frame->flags &= ~AV_FRAME_FLAG_KEY; frame->palette_has_changed = 0; memcpy(frame->data[1], bfi->pal, sizeof(bfi->pal)); } diff --git a/libavcodec/bitpacked_dec.c b/libavcodec/bitpacked_dec.c index a1ffef185ce..c88f8619938 100644 --- a/libavcodec/bitpacked_dec.c +++ b/libavcodec/bitpacked_dec.c @@ -134,7 +134,7 @@ static int bitpacked_decode(AVCodecContext *avctx, AVFrame *frame, return res; frame->pict_type = AV_PICTURE_TYPE_I; - frame->key_frame = 1; + frame->flags |= AV_FRAME_FLAG_KEY; *got_frame = 1; return buf_size; diff --git a/libavcodec/bmp.c b/libavcodec/bmp.c index d7e01f07256..d117c06cf41 100644 --- a/libavcodec/bmp.c +++ b/libavcodec/bmp.c @@ -210,7 +210,7 @@ static int bmp_decode_frame(AVCodecContext *avctx, AVFrame *p, if ((ret = ff_get_buffer(avctx, p, 0)) < 0) return ret; p->pict_type = AV_PICTURE_TYPE_I; - p->key_frame = 1; + p->flags |= AV_FRAME_FLAG_KEY; buf = buf0 + hsize; dsize = buf_size - hsize; diff --git a/libavcodec/brenderpix.c b/libavcodec/brenderpix.c index e95ab3d4afd..85eb55f50b1 100644 --- a/libavcodec/brenderpix.c +++ b/libavcodec/brenderpix.c @@ -278,7 +278,7 @@ static int pix_decode_frame(AVCodecContext *avctx, AVFrame *frame, bytes_per_scanline, hdr.height); frame->pict_type = AV_PICTURE_TYPE_I; - frame->key_frame = 1; + frame->flags |= AV_FRAME_FLAG_KEY; *got_frame = 1; return avpkt->size; diff --git a/libavcodec/c93.c b/libavcodec/c93.c index bfcbc7c1504..b872f95e9b2 100644 --- a/libavcodec/c93.c +++ b/libavcodec/c93.c @@ -147,10 +147,10 @@ static int decode_frame(AVCodecContext *avctx, AVFrame *rframe, b = bytestream2_get_byte(&gb); if (b & C93_FIRST_FRAME) { newpic->pict_type = AV_PICTURE_TYPE_I; - newpic->key_frame = 1; + newpic->flags |= AV_FRAME_FLAG_KEY; } else { newpic->pict_type = AV_PICTURE_TYPE_P; - newpic->key_frame = 0; + newpic->flags &= ~AV_FRAME_FLAG_KEY; } for (y = 0; y < HEIGHT; y += 8) { diff --git a/libavcodec/cdxl.c b/libavcodec/cdxl.c index 6b3b3e85e0f..885047af84f 100644 --- a/libavcodec/cdxl.c +++ b/libavcodec/cdxl.c @@ -305,7 +305,7 @@ static int cdxl_decode_frame(AVCodecContext *avctx, AVFrame *p, if ((ret = ff_get_buffer(avctx, p, 0)) < 0) return ret; p->pict_type = AV_PICTURE_TYPE_I; - p->key_frame = 1; + p->flags |= AV_FRAME_FLAG_KEY; if (encoding) { av_fast_padded_malloc(&c->new_video, &c->new_video_size, diff --git a/libavcodec/cinepak.c b/libavcodec/cinepak.c index 282614fd1db..e91f2f1012a 100644 --- a/libavcodec/cinepak.c +++ b/libavcodec/cinepak.c @@ -379,7 +379,7 @@ static int cinepak_decode (CinepakContext *s) num_strips = FFMIN(num_strips, MAX_STRIPS); - s->frame->key_frame = 0; + s->frame->flags &= ~AV_FRAME_FLAG_KEY; for (i=0; i < num_strips; i++) { if ((s->data + 12) > eod) @@ -395,7 +395,7 @@ static int cinepak_decode (CinepakContext *s) s->strips[i].x2 = AV_RB16 (&s->data[10]); if (s->strips[i].id == 0x10) - s->frame->key_frame = 1; + s->frame->flags |= AV_FRAME_FLAG_KEY; strip_size = AV_RB24 (&s->data[1]) - 12; if (strip_size < 0) diff --git a/libavcodec/clearvideo.c b/libavcodec/clearvideo.c index e77661d187b..f84e3e6ea4f 100644 --- a/libavcodec/clearvideo.c +++ b/libavcodec/clearvideo.c @@ -511,7 +511,7 @@ static int clv_decode_frame(AVCodecContext *avctx, AVFrame *rframe, if ((ret = ff_reget_buffer(avctx, c->pic, 0)) < 0) return ret; - c->pic->key_frame = 1; + c->pic->flags |= AV_FRAME_FLAG_KEY; c->pic->pict_type = AV_PICTURE_TYPE_I; bytestream2_get_be32(&gb); // frame size; @@ -605,7 +605,7 @@ static int clv_decode_frame(AVCodecContext *avctx, AVFrame *rframe, } extend_edges(c->pic, c->tile_size); - c->pic->key_frame = 0; + c->pic->flags &= ~AV_FRAME_FLAG_KEY; c->pic->pict_type = AV_PICTURE_TYPE_P; } diff --git a/libavcodec/cljrdec.c b/libavcodec/cljrdec.c index 914f853c8fd..a4baa015f68 100644 --- a/libavcodec/cljrdec.c +++ b/libavcodec/cljrdec.c @@ -51,7 +51,7 @@ static int decode_frame(AVCodecContext *avctx, AVFrame *p, if ((ret = ff_get_buffer(avctx, p, 0)) < 0) return ret; p->pict_type = AV_PICTURE_TYPE_I; - p->key_frame = 1; + p->flags |= AV_FRAME_FLAG_KEY; init_get_bits(&gb, buf, buf_size * 8); diff --git a/libavcodec/cllc.c b/libavcodec/cllc.c index 911717b68db..52cb86e50b4 100644 --- a/libavcodec/cllc.c +++ b/libavcodec/cllc.c @@ -460,7 +460,7 @@ static int cllc_decode_frame(AVCodecContext *avctx, AVFrame *pic, return AVERROR_INVALIDDATA; } - pic->key_frame = 1; + pic->flags |= AV_FRAME_FLAG_KEY; pic->pict_type = AV_PICTURE_TYPE_I; *got_picture_ptr = 1; diff --git a/libavcodec/cpia.c b/libavcodec/cpia.c index bfd270dae2b..f62100c4193 100644 --- a/libavcodec/cpia.c +++ b/libavcodec/cpia.c @@ -94,10 +94,10 @@ static int cpia_decode_frame(AVCodecContext *avctx, AVFrame *rframe, if (header[28] == NOT_COMPRESSED) { frame->pict_type = AV_PICTURE_TYPE_I; - frame->key_frame = 1; + frame->flags |= AV_FRAME_FLAG_KEY; } else { frame->pict_type = AV_PICTURE_TYPE_P; - frame->key_frame = 0; + frame->flags &= ~AV_FRAME_FLAG_KEY; } // Get buffer filled with previous frame diff --git a/libavcodec/cri.c b/libavcodec/cri.c index 5761152c2d5..0380a0c665b 100644 --- a/libavcodec/cri.c +++ b/libavcodec/cri.c @@ -408,7 +408,7 @@ static int cri_decode_frame(AVCodecContext *avctx, AVFrame *p, } p->pict_type = AV_PICTURE_TYPE_I; - p->key_frame = 1; + p->flags |= AV_FRAME_FLAG_KEY; *got_frame = 1; diff --git a/libavcodec/cscd.c b/libavcodec/cscd.c index b4ed3332a96..23dd2df99e8 100644 --- a/libavcodec/cscd.c +++ b/libavcodec/cscd.c @@ -110,12 +110,12 @@ static int decode_frame(AVCodecContext *avctx, AVFrame *rframe, // flip upside down, add difference frame if (buf[0] & 1) { // keyframe c->pic->pict_type = AV_PICTURE_TYPE_I; - c->pic->key_frame = 1; + c->pic->flags |= AV_FRAME_FLAG_KEY; copy_frame_default(c->pic, c->decomp_buf, c->linelen, c->height); } else { c->pic->pict_type = AV_PICTURE_TYPE_P; - c->pic->key_frame = 0; + c->pic->flags &= ~AV_FRAME_FLAG_KEY; add_frame_default(c->pic, c->decomp_buf, c->linelen, c->height); } diff --git a/libavcodec/cuviddec.c b/libavcodec/cuviddec.c index 95d29a2e789..3d43bbd466b 100644 --- a/libavcodec/cuviddec.c +++ b/libavcodec/cuviddec.c @@ -599,7 +599,10 @@ static int cuvid_output_frame(AVCodecContext *avctx, AVFrame *frame) goto error; } - frame->key_frame = ctx->key_frame[parsed_frame.dispinfo.picture_index]; + if (ctx->key_frame[parsed_frame.dispinfo.picture_index]) + frame->flags |= AV_FRAME_FLAG_KEY; + else + frame->flags &= ~AV_FRAME_FLAG_KEY; ctx->key_frame[parsed_frame.dispinfo.picture_index] = 0; frame->width = avctx->width; diff --git a/libavcodec/dds.c b/libavcodec/dds.c index 4bb425dbb3c..670a42fbf97 100644 --- a/libavcodec/dds.c +++ b/libavcodec/dds.c @@ -702,7 +702,7 @@ static int dds_decode(AVCodecContext *avctx, AVFrame *frame, /* Frame is ready to be output. */ frame->pict_type = AV_PICTURE_TYPE_I; - frame->key_frame = 1; + frame->flags |= AV_FRAME_FLAG_KEY; *got_frame = 1; return avpkt->size; diff --git a/libavcodec/decode.c b/libavcodec/decode.c index 64a448b54c9..a5a6209eaeb 100644 --- a/libavcodec/decode.c +++ b/libavcodec/decode.c @@ -570,6 +570,9 @@ static int decode_receive_frame_internal(AVCodecContext *avctx, AVFrame *frame) } if (!ret) { + if (avctx->codec_type != AVMEDIA_TYPE_VIDEO) + frame->flags |= AV_FRAME_FLAG_KEY; + frame->key_frame = !!(frame->flags & AV_FRAME_FLAG_KEY); #if FF_API_INTERLACED_FRAME FF_DISABLE_DEPRECATION_WARNINGS frame->interlaced_frame = !!(frame->flags & AV_FRAME_FLAG_INTERLACED); diff --git a/libavcodec/diracdec.c b/libavcodec/diracdec.c index 0ae582befeb..277c730cc78 100644 --- a/libavcodec/diracdec.c +++ b/libavcodec/diracdec.c @@ -2230,7 +2230,10 @@ static int dirac_decode_data_unit(AVCodecContext *avctx, const uint8_t *buf, int s->hq_picture = (parse_code & 0xF8) == 0xE8; /* [DIRAC_STD] is_hq_picture() */ s->dc_prediction = (parse_code & 0x28) == 0x08; /* [DIRAC_STD] using_dc_prediction() */ pic->reference = (parse_code & 0x0C) == 0x0C; /* [DIRAC_STD] is_reference() */ - pic->avframe->key_frame = s->num_refs == 0; /* [DIRAC_STD] is_intra() */ + if (s->num_refs == 0) /* [DIRAC_STD] is_intra() */ + pic->avframe->flags |= AV_FRAME_FLAG_KEY; + else + pic->avframe->flags &= ~AV_FRAME_FLAG_KEY; pic->avframe->pict_type = s->num_refs + 1; /* Definition of AVPictureType in avutil.h */ /* VC-2 Low Delay has a different parse code than the Dirac Low Delay */ diff --git a/libavcodec/dnxhddec.c b/libavcodec/dnxhddec.c index 30a4e396958..834390b93b3 100644 --- a/libavcodec/dnxhddec.c +++ b/libavcodec/dnxhddec.c @@ -653,7 +653,7 @@ static int dnxhd_decode_frame(AVCodecContext *avctx, AVFrame *picture, if ((ret = ff_thread_get_buffer(avctx, picture, 0)) < 0) return ret; picture->pict_type = AV_PICTURE_TYPE_I; - picture->key_frame = 1; + picture->flags |= AV_FRAME_FLAG_KEY; } ctx->buf_size = buf_size - ctx->data_offset; diff --git a/libavcodec/dvdec.c b/libavcodec/dvdec.c index 2b4d70ac3d0..750e25a4af7 100644 --- a/libavcodec/dvdec.c +++ b/libavcodec/dvdec.c @@ -646,7 +646,7 @@ static int dvvideo_decode_frame(AVCodecContext *avctx, AVFrame *frame, } s->frame = frame; - frame->key_frame = 1; + frame->flags |= AV_FRAME_FLAG_KEY; frame->pict_type = AV_PICTURE_TYPE_I; avctx->pix_fmt = s->sys->pix_fmt; avctx->framerate = av_inv_q(s->sys->time_base); diff --git a/libavcodec/dxa.c b/libavcodec/dxa.c index 8d2d2d771ba..ecb48c9d3f0 100644 --- a/libavcodec/dxa.c +++ b/libavcodec/dxa.c @@ -258,19 +258,19 @@ static int decode_frame(AVCodecContext *avctx, AVFrame *frame, switch(compr){ case -1: - frame->key_frame = 0; + frame->flags &= ~AV_FRAME_FLAG_KEY; frame->pict_type = AV_PICTURE_TYPE_P; if (c->prev->data[0]) memcpy(frame->data[0], c->prev->data[0], frame->linesize[0] * avctx->height); else{ // Should happen only when first frame is 'NULL' memset(frame->data[0], 0, frame->linesize[0] * avctx->height); - frame->key_frame = 1; + frame->flags |= AV_FRAME_FLAG_KEY; frame->pict_type = AV_PICTURE_TYPE_I; } break; case 2: case 4: - frame->key_frame = 1; + frame->flags |= AV_FRAME_FLAG_KEY; frame->pict_type = AV_PICTURE_TYPE_I; for (j = 0; j < avctx->height; j++) { memcpy(outptr, srcptr, avctx->width); @@ -285,7 +285,7 @@ static int decode_frame(AVCodecContext *avctx, AVFrame *frame, if (!(avctx->flags2 & AV_CODEC_FLAG2_SHOW_ALL)) return AVERROR_INVALIDDATA; } - frame->key_frame = 0; + frame->flags &= ~AV_FRAME_FLAG_KEY; frame->pict_type = AV_PICTURE_TYPE_P; for (j = 0; j < avctx->height; j++) { if(tmpptr){ @@ -300,7 +300,7 @@ static int decode_frame(AVCodecContext *avctx, AVFrame *frame, break; case 12: // ScummVM coding case 13: - frame->key_frame = 0; + frame->flags &= ~AV_FRAME_FLAG_KEY; frame->pict_type = AV_PICTURE_TYPE_P; if (!c->prev->data[0]) { av_log(avctx, AV_LOG_ERROR, "Missing reference frame\n"); diff --git a/libavcodec/dxtory.c b/libavcodec/dxtory.c index e13d274862e..f36420cdd9c 100644 --- a/libavcodec/dxtory.c +++ b/libavcodec/dxtory.c @@ -864,7 +864,7 @@ static int decode_frame(AVCodecContext *avctx, AVFrame *pic, return ret; pic->pict_type = AV_PICTURE_TYPE_I; - pic->key_frame = 1; + pic->flags |= AV_FRAME_FLAG_KEY; *got_frame = 1; return avpkt->size; diff --git a/libavcodec/dxv.c b/libavcodec/dxv.c index 7c84874229b..5923811b297 100644 --- a/libavcodec/dxv.c +++ b/libavcodec/dxv.c @@ -1220,7 +1220,7 @@ static int dxv_decode(AVCodecContext *avctx, AVFrame *frame, /* Frame is ready to be output. */ frame->pict_type = AV_PICTURE_TYPE_I; - frame->key_frame = 1; + frame->flags |= AV_FRAME_FLAG_KEY; *got_frame = 1; return avpkt->size; diff --git a/libavcodec/eacmv.c b/libavcodec/eacmv.c index 18f27dfdf07..e73e310c4a9 100644 --- a/libavcodec/eacmv.c +++ b/libavcodec/eacmv.c @@ -202,10 +202,10 @@ static int cmv_decode_frame(AVCodecContext *avctx, AVFrame *frame, buf += EA_PREAMBLE_SIZE; if ((buf[0]&1)) { // subtype cmv_decode_inter(s, frame, buf+2, buf_end); - frame->key_frame = 0; + frame->flags &= ~AV_FRAME_FLAG_KEY; frame->pict_type = AV_PICTURE_TYPE_P; }else{ - frame->key_frame = 1; + frame->flags |= AV_FRAME_FLAG_KEY; frame->pict_type = AV_PICTURE_TYPE_I; cmv_decode_intra(s, frame, buf+2, buf_end); } diff --git a/libavcodec/eatgq.c b/libavcodec/eatgq.c index 01e1acd4e42..0f0ed3585fa 100644 --- a/libavcodec/eatgq.c +++ b/libavcodec/eatgq.c @@ -237,7 +237,7 @@ static int tgq_decode_frame(AVCodecContext *avctx, AVFrame *frame, if ((ret = ff_get_buffer(avctx, frame, 0)) < 0) return ret; - frame->key_frame = 1; + frame->flags |= AV_FRAME_FLAG_KEY; frame->pict_type = AV_PICTURE_TYPE_I; for (y = 0; y < FFALIGN(avctx->height, 16) >> 4; y++) diff --git a/libavcodec/eatgv.c b/libavcodec/eatgv.c index 29f7ee12f5b..a2aead46ebd 100644 --- a/libavcodec/eatgv.c +++ b/libavcodec/eatgv.c @@ -310,7 +310,7 @@ static int tgv_decode_frame(AVCodecContext *avctx, AVFrame *frame, if (chunk_type == kVGT_TAG) { int y; - frame->key_frame = 1; + frame->flags |= AV_FRAME_FLAG_KEY; frame->pict_type = AV_PICTURE_TYPE_I; if (!s->frame_buffer && @@ -330,7 +330,7 @@ static int tgv_decode_frame(AVCodecContext *avctx, AVFrame *frame, av_log(avctx, AV_LOG_WARNING, "inter frame without corresponding intra frame\n"); return buf_size; } - frame->key_frame = 0; + frame->flags &= ~AV_FRAME_FLAG_KEY; frame->pict_type = AV_PICTURE_TYPE_P; if (tgv_decode_inter(s, frame, buf, buf_end) < 0) { av_log(avctx, AV_LOG_WARNING, "truncated inter frame\n"); diff --git a/libavcodec/encode.c b/libavcodec/encode.c index 0c4b2b0f99d..04ee59879ec 100644 --- a/libavcodec/encode.c +++ b/libavcodec/encode.c @@ -192,6 +192,8 @@ int ff_encode_get_frame(AVCodecContext *avctx, AVFrame *frame) av_frame_move_ref(frame, avci->buffer_frame); + if (frame->key_frame) + frame->flags |= AV_FRAME_FLAG_KEY; #if FF_API_INTERLACED_FRAME FF_DISABLE_DEPRECATION_WARNINGS if (frame->interlaced_frame) diff --git a/libavcodec/ffv1dec.c b/libavcodec/ffv1dec.c index c49db83b5cf..54cf075b8f0 100644 --- a/libavcodec/ffv1dec.c +++ b/libavcodec/ffv1dec.c @@ -264,16 +264,16 @@ static int decode_slice(AVCodecContext *c, void *arg) for( si=0; fs != f->slice_context[si]; si ++) ; - if(f->fsrc && !p->key_frame) + if(f->fsrc && !(p->flags & AV_FRAME_FLAG_KEY)) ff_thread_await_progress(&f->last_picture, si, 0); - if(f->fsrc && !p->key_frame) { + if(f->fsrc && !(p->flags & AV_FRAME_FLAG_KEY)) { FFV1Context *fssrc = f->fsrc->slice_context[si]; FFV1Context *fsdst = f->slice_context[si]; av_assert1(fsdst->plane_count == fssrc->plane_count); av_assert1(fsdst == fs); - if (!p->key_frame) + if (!(p->flags & AV_FRAME_FLAG_KEY)) fsdst->slice_damaged |= fssrc->slice_damaged; for (i = 0; i < f->plane_count; i++) { @@ -310,7 +310,7 @@ static int decode_slice(AVCodecContext *c, void *arg) } if ((ret = ff_ffv1_init_slice_state(f, fs)) < 0) return ret; - if (f->cur->key_frame || fs->slice_reset_contexts) { + if ((f->cur->flags & AV_FRAME_FLAG_KEY) || fs->slice_reset_contexts) { ff_ffv1_clear_slice_state(f, fs); } else if (fs->slice_damaged) { return AVERROR_INVALIDDATA; @@ -892,7 +892,7 @@ static int decode_frame(AVCodecContext *avctx, AVFrame *rframe, p->pict_type = AV_PICTURE_TYPE_I; //FIXME I vs. P if (get_rac(c, &keystate)) { - p->key_frame = 1; + p->flags |= AV_FRAME_FLAG_KEY; f->key_frame_ok = 0; if ((ret = read_header(f)) < 0) return ret; @@ -903,7 +903,7 @@ static int decode_frame(AVCodecContext *avctx, AVFrame *rframe, "Cannot decode non-keyframe without valid keyframe\n"); return AVERROR_INVALIDDATA; } - p->key_frame = 0; + p->flags &= ~AV_FRAME_FLAG_KEY; } if (f->ac != AC_GOLOMB_RICE) { @@ -927,7 +927,7 @@ static int decode_frame(AVCodecContext *avctx, AVFrame *rframe, if (avctx->debug & FF_DEBUG_PICT_INFO) av_log(avctx, AV_LOG_DEBUG, "ver:%d keyframe:%d coder:%d ec:%d slices:%d bps:%d\n", - f->version, p->key_frame, f->ac, f->ec, f->slice_count, f->avctx->bits_per_raw_sample); + f->version, !!(p->flags & AV_FRAME_FLAG_KEY), f->ac, f->ec, f->slice_count, f->avctx->bits_per_raw_sample); ff_thread_finish_setup(avctx); diff --git a/libavcodec/fic.c b/libavcodec/fic.c index 94cf42887f3..fb998021371 100644 --- a/libavcodec/fic.c +++ b/libavcodec/fic.c @@ -406,11 +406,11 @@ static int fic_decode_frame(AVCodecContext *avctx, AVFrame *rframe, NULL, nslices, sizeof(ctx->slice_data[0]))) < 0) return ret; - ctx->frame->key_frame = 1; + ctx->frame->flags |= AV_FRAME_FLAG_KEY; ctx->frame->pict_type = AV_PICTURE_TYPE_I; for (slice = 0; slice < nslices; slice++) { if (ctx->slice_data[slice].p_frame) { - ctx->frame->key_frame = 0; + ctx->frame->flags &= ~AV_FRAME_FLAG_KEY; ctx->frame->pict_type = AV_PICTURE_TYPE_P; break; } diff --git a/libavcodec/fitsdec.c b/libavcodec/fitsdec.c index b9c51e70c31..44135309f26 100644 --- a/libavcodec/fitsdec.c +++ b/libavcodec/fitsdec.c @@ -301,7 +301,7 @@ static int fits_decode_frame(AVCodecContext *avctx, AVFrame *p, } } - p->key_frame = 1; + p->flags |= AV_FRAME_FLAG_KEY; p->pict_type = AV_PICTURE_TYPE_I; *got_frame = 1; diff --git a/libavcodec/fmvc.c b/libavcodec/fmvc.c index 3ee915cc4cb..5e26a541ca7 100644 --- a/libavcodec/fmvc.c +++ b/libavcodec/fmvc.c @@ -433,7 +433,7 @@ static int decode_frame(AVCodecContext *avctx, AVFrame *frame, if ((ret = ff_get_buffer(avctx, frame, 0)) < 0) return ret; - frame->key_frame = 1; + frame->flags |= AV_FRAME_FLAG_KEY; frame->pict_type = AV_PICTURE_TYPE_I; src = s->buffer; @@ -519,7 +519,7 @@ static int decode_frame(AVCodecContext *avctx, AVFrame *frame, if ((ret = ff_get_buffer(avctx, frame, 0)) < 0) return ret; - frame->key_frame = 0; + frame->flags &= ~AV_FRAME_FLAG_KEY; frame->pict_type = AV_PICTURE_TYPE_P; ssrc = s->buffer; diff --git a/libavcodec/fraps.c b/libavcodec/fraps.c index 4c4c46b6027..e7a23f20fe3 100644 --- a/libavcodec/fraps.c +++ b/libavcodec/fraps.c @@ -216,7 +216,7 @@ static int decode_frame(AVCodecContext *avctx, AVFrame *f, } f->pict_type = AV_PICTURE_TYPE_I; - f->key_frame = 1; + f->flags |= AV_FRAME_FLAG_KEY; avctx->pix_fmt = version & 1 ? is_pal ? AV_PIX_FMT_PAL8 : AV_PIX_FMT_BGR24 : AV_PIX_FMT_YUVJ420P; avctx->color_range = version & 1 ? AVCOL_RANGE_UNSPECIFIED diff --git a/libavcodec/frwu.c b/libavcodec/frwu.c index cf183f84107..70bc136765b 100644 --- a/libavcodec/frwu.c +++ b/libavcodec/frwu.c @@ -63,7 +63,7 @@ static int decode_frame(AVCodecContext *avctx, AVFrame *pic, return ret; pic->pict_type = AV_PICTURE_TYPE_I; - pic->key_frame = 1; + pic->flags |= AV_FRAME_FLAG_KEY; for (field = 0; field < 2; field++) { int i; diff --git a/libavcodec/g2meet.c b/libavcodec/g2meet.c index 05b5a5124fb..2dfa73df74e 100644 --- a/libavcodec/g2meet.c +++ b/libavcodec/g2meet.c @@ -1560,7 +1560,10 @@ static int g2m_decode_frame(AVCodecContext *avctx, AVFrame *pic, if ((ret = ff_get_buffer(avctx, pic, 0)) < 0) return ret; - pic->key_frame = got_header; + if (got_header) + pic->flags |= AV_FRAME_FLAG_KEY; + else + pic->flags &= ~AV_FRAME_FLAG_KEY; pic->pict_type = got_header ? AV_PICTURE_TYPE_I : AV_PICTURE_TYPE_P; for (i = 0; i < avctx->height; i++) diff --git a/libavcodec/gemdec.c b/libavcodec/gemdec.c index c8fd8dcdcd2..73e907c0413 100644 --- a/libavcodec/gemdec.c +++ b/libavcodec/gemdec.c @@ -180,7 +180,7 @@ static int gem_decode_frame(AVCodecContext *avctx, AVFrame *p, return ret; p->pict_type = AV_PICTURE_TYPE_I; - p->key_frame = 1; + p->flags |= AV_FRAME_FLAG_KEY; p->palette_has_changed = 1; palette = (uint32_t *)p->data[1]; diff --git a/libavcodec/gifdec.c b/libavcodec/gifdec.c index f47390c3bd9..0835c5bdd0d 100644 --- a/libavcodec/gifdec.c +++ b/libavcodec/gifdec.c @@ -501,7 +501,7 @@ static int gif_decode_frame(AVCodecContext *avctx, AVFrame *rframe, return AVERROR(ENOMEM); s->frame->pict_type = AV_PICTURE_TYPE_I; - s->frame->key_frame = 1; + s->frame->flags |= AV_FRAME_FLAG_KEY; s->keyframe_ok = 1; } else { if (!s->keyframe_ok) { @@ -513,7 +513,7 @@ static int gif_decode_frame(AVCodecContext *avctx, AVFrame *rframe, return ret; s->frame->pict_type = AV_PICTURE_TYPE_P; - s->frame->key_frame = 0; + s->frame->flags &= ~AV_FRAME_FLAG_KEY; } ret = gif_parse_next_image(s, s->frame); diff --git a/libavcodec/h261dec.c b/libavcodec/h261dec.c index 84962939643..620b7eef839 100644 --- a/libavcodec/h261dec.c +++ b/libavcodec/h261dec.c @@ -643,7 +643,10 @@ static int h261_decode_frame(AVCodecContext *avctx, AVFrame *pict, // for skipping the frame s->current_picture.f->pict_type = s->pict_type; - s->current_picture.f->key_frame = s->pict_type == AV_PICTURE_TYPE_I; + if (s->pict_type == AV_PICTURE_TYPE_I) + s->current_picture.f->flags |= AV_FRAME_FLAG_KEY; + else + s->current_picture.f->flags &= ~AV_FRAME_FLAG_KEY; if ((avctx->skip_frame >= AVDISCARD_NONREF && s->pict_type == AV_PICTURE_TYPE_B) || (avctx->skip_frame >= AVDISCARD_NONKEY && s->pict_type != AV_PICTURE_TYPE_I) || diff --git a/libavcodec/h264_slice.c b/libavcodec/h264_slice.c index f44b60c6425..85267825608 100644 --- a/libavcodec/h264_slice.c +++ b/libavcodec/h264_slice.c @@ -501,7 +501,7 @@ FF_ENABLE_DEPRECATION_WARNINGS * in later. * See decode_nal_units(). */ - pic->f->key_frame = 0; + pic->f->flags &= ~AV_FRAME_FLAG_KEY; pic->mmco_reset = 0; pic->recovered = 0; pic->invalid_gap = 0; @@ -1326,7 +1326,7 @@ static int h264_select_output_frame(H264Context *h) out = h->delayed_pic[0]; out_idx = 0; for (i = 1; h->delayed_pic[i] && - !h->delayed_pic[i]->f->key_frame && + !(h->delayed_pic[i]->f->flags & AV_FRAME_FLAG_KEY) && !h->delayed_pic[i]->mmco_reset; i++) if (h->delayed_pic[i]->poc < out->poc) { @@ -1334,7 +1334,7 @@ static int h264_select_output_frame(H264Context *h) out_idx = i; } if (h->avctx->has_b_frames == 0 && - (h->delayed_pic[0]->f->key_frame || h->delayed_pic[0]->mmco_reset)) + ((h->delayed_pic[0]->f->flags & AV_FRAME_FLAG_KEY) || h->delayed_pic[0]->mmco_reset)) h->next_outputed_poc = INT_MIN; out_of_order = out->poc < h->next_outputed_poc; @@ -1345,7 +1345,7 @@ static int h264_select_output_frame(H264Context *h) } if (!out_of_order && pics > h->avctx->has_b_frames) { h->next_output_pic = out; - if (out_idx == 0 && h->delayed_pic[0] && (h->delayed_pic[0]->f->key_frame || h->delayed_pic[0]->mmco_reset)) { + if (out_idx == 0 && h->delayed_pic[0] && ((h->delayed_pic[0]->f->flags & AV_FRAME_FLAG_KEY) || h->delayed_pic[0]->mmco_reset)) { h->next_outputed_poc = INT_MIN; } else h->next_outputed_poc = out->poc; @@ -1635,7 +1635,7 @@ static int h264_field_start(H264Context *h, const H264SliceContext *sl, } } - h->cur_pic_ptr->f->key_frame |= (nal->type == H264_NAL_IDR_SLICE); + h->cur_pic_ptr->f->flags |= AV_FRAME_FLAG_KEY * !!(nal->type == H264_NAL_IDR_SLICE); if (nal->type == H264_NAL_IDR_SLICE || (h->recovery_frame == h->poc.frame_num && nal->ref_idc)) { diff --git a/libavcodec/h264dec.c b/libavcodec/h264dec.c index 2d691731c5d..cdd4b98c838 100644 --- a/libavcodec/h264dec.c +++ b/libavcodec/h264dec.c @@ -849,7 +849,7 @@ static int output_frame(H264Context *h, AVFrame *dst, H264Picture *srcp) av_dict_set(&dst->metadata, "stereo_mode", ff_h264_sei_stereo_mode(&h->sei.common.frame_packing), 0); if (srcp->sei_recovery_frame_cnt == 0) - dst->key_frame = 1; + dst->flags |= AV_FRAME_FLAG_KEY; if (h->avctx->export_side_data & AV_CODEC_EXPORT_DATA_VIDEO_ENC_PARAMS) { ret = h264_export_enc_params(dst, srcp); @@ -951,7 +951,7 @@ static int send_next_delayed_frame(H264Context *h, AVFrame *dst_frame, out_idx = 0; for (i = 1; h->delayed_pic[i] && - !h->delayed_pic[i]->f->key_frame && + !(h->delayed_pic[i]->f->flags & AV_FRAME_FLAG_KEY) && !h->delayed_pic[i]->mmco_reset; i++) if (h->delayed_pic[i]->poc < out->poc) { diff --git a/libavcodec/hapdec.c b/libavcodec/hapdec.c index 3df69e63357..fee3c04d84b 100644 --- a/libavcodec/hapdec.c +++ b/libavcodec/hapdec.c @@ -328,7 +328,7 @@ static int hap_decode(AVCodecContext *avctx, AVFrame *frame, /* Frame is ready to be output */ frame->pict_type = AV_PICTURE_TYPE_I; - frame->key_frame = 1; + frame->flags |= AV_FRAME_FLAG_KEY; *got_frame = 1; return avpkt->size; diff --git a/libavcodec/hdrdec.c b/libavcodec/hdrdec.c index 998227744b3..9b6395bb6d3 100644 --- a/libavcodec/hdrdec.c +++ b/libavcodec/hdrdec.c @@ -212,7 +212,7 @@ static int hdr_decode_frame(AVCodecContext *avctx, AVFrame *p, } } - p->key_frame = 1; + p->flags |= AV_FRAME_FLAG_KEY; p->pict_type = AV_PICTURE_TYPE_I; *got_frame = 1; diff --git a/libavcodec/hevcdec.c b/libavcodec/hevcdec.c index 21e4d0db28f..7e1bf4e9157 100644 --- a/libavcodec/hevcdec.c +++ b/libavcodec/hevcdec.c @@ -2910,7 +2910,10 @@ static int hevc_frame_start(HEVCContext *s) goto fail; } - s->ref->frame->key_frame = IS_IRAP(s); + if (IS_IRAP(s)) + s->ref->frame->flags |= AV_FRAME_FLAG_KEY; + else + s->ref->frame->flags &= ~AV_FRAME_FLAG_KEY; s->ref->needs_fg = s->sei.common.film_grain_characteristics.present && !(s->avctx->export_side_data & AV_CODEC_EXPORT_DATA_FILM_GRAIN) && diff --git a/libavcodec/hnm4video.c b/libavcodec/hnm4video.c index f223bb82fc7..51e75789d2a 100644 --- a/libavcodec/hnm4video.c +++ b/libavcodec/hnm4video.c @@ -420,7 +420,7 @@ static int hnm_decode_frame(AVCodecContext *avctx, AVFrame *frame, postprocess_current_frame(avctx); copy_processed_frame(avctx, frame); frame->pict_type = AV_PICTURE_TYPE_I; - frame->key_frame = 1; + frame->flags |= AV_FRAME_FLAG_KEY; memcpy(frame->data[1], hnm->palette, 256 * 4); *got_frame = 1; } else if (chunk_id == HNM4_CHUNK_ID_IU) { @@ -438,7 +438,7 @@ static int hnm_decode_frame(AVCodecContext *avctx, AVFrame *frame, } copy_processed_frame(avctx, frame); frame->pict_type = AV_PICTURE_TYPE_P; - frame->key_frame = 0; + frame->flags &= ~AV_FRAME_FLAG_KEY; memcpy(frame->data[1], hnm->palette, 256 * 4); *got_frame = 1; FFSWAP(uint8_t *, hnm->current, hnm->previous); diff --git a/libavcodec/hq_hqa.c b/libavcodec/hq_hqa.c index 6ce73b7ae49..db0ac7d9e4e 100644 --- a/libavcodec/hq_hqa.c +++ b/libavcodec/hq_hqa.c @@ -354,7 +354,7 @@ static int hq_hqa_decode_frame(AVCodecContext *avctx, AVFrame *pic, return ret; } - pic->key_frame = 1; + pic->flags |= AV_FRAME_FLAG_KEY; pic->pict_type = AV_PICTURE_TYPE_I; *got_frame = 1; diff --git a/libavcodec/hqx.c b/libavcodec/hqx.c index 60839465502..6554b15ec65 100644 --- a/libavcodec/hqx.c +++ b/libavcodec/hqx.c @@ -504,7 +504,7 @@ static int hqx_decode_frame(AVCodecContext *avctx, AVFrame *frame, avctx->execute2(avctx, decode_slice_thread, NULL, NULL, 16); - ctx->pic->key_frame = 1; + ctx->pic->flags |= AV_FRAME_FLAG_KEY; ctx->pic->pict_type = AV_PICTURE_TYPE_I; *got_picture_ptr = 1; diff --git a/libavcodec/iff.c b/libavcodec/iff.c index e02d2e77e53..faf4e21c428 100644 --- a/libavcodec/iff.c +++ b/libavcodec/iff.c @@ -1887,10 +1887,10 @@ static int decode_frame(AVCodecContext *avctx, AVFrame *frame, } if (avpkt->flags & AV_PKT_FLAG_KEY) { - frame->key_frame = 1; + frame->flags |= AV_FRAME_FLAG_KEY; frame->pict_type = AV_PICTURE_TYPE_I; } else { - frame->key_frame = 0; + frame->flags &= ~AV_FRAME_FLAG_KEY; frame->pict_type = AV_PICTURE_TYPE_P; } diff --git a/libavcodec/imm4.c b/libavcodec/imm4.c index ccec5dff43a..b95ad86921d 100644 --- a/libavcodec/imm4.c +++ b/libavcodec/imm4.c @@ -420,11 +420,11 @@ static int decode_frame(AVCodecContext *avctx, AVFrame *frame, switch (type) { case 0x19781977: - frame->key_frame = 1; + frame->flags |= AV_FRAME_FLAG_KEY; frame->pict_type = AV_PICTURE_TYPE_I; break; case 0x12250926: - frame->key_frame = 0; + frame->flags &= ~AV_FRAME_FLAG_KEY; frame->pict_type = AV_PICTURE_TYPE_P; break; default: @@ -434,7 +434,7 @@ static int decode_frame(AVCodecContext *avctx, AVFrame *frame, if (avctx->width != width || avctx->height != height) { - if (!frame->key_frame) { + if (!(frame->flags & AV_FRAME_FLAG_KEY)) { av_log(avctx, AV_LOG_ERROR, "Frame size change is unsupported.\n"); return AVERROR_INVALIDDATA; } @@ -445,10 +445,10 @@ static int decode_frame(AVCodecContext *avctx, AVFrame *frame, if (ret < 0) return ret; - if ((ret = ff_get_buffer(avctx, frame, frame->key_frame ? AV_GET_BUFFER_FLAG_REF : 0)) < 0) + if ((ret = ff_get_buffer(avctx, frame, (frame->flags & AV_FRAME_FLAG_KEY) ? AV_GET_BUFFER_FLAG_REF : 0)) < 0) return ret; - if (frame->key_frame) { + if (frame->flags & AV_FRAME_FLAG_KEY) { ret = decode_intra(avctx, gb, frame); if (ret < 0) return ret; diff --git a/libavcodec/imx.c b/libavcodec/imx.c index 44bab23c270..4ae68eb93c8 100644 --- a/libavcodec/imx.c +++ b/libavcodec/imx.c @@ -59,9 +59,9 @@ static int imx_decode_frame(AVCodecContext *avctx, AVFrame *rframe, if (ff_copy_palette(imx->pal, avpkt, avctx)) { frame->palette_has_changed = 1; - frame->key_frame = 1; + frame->flags |= AV_FRAME_FLAG_KEY; } else { - frame->key_frame = 0; + frame->flags &= ~AV_FRAME_FLAG_KEY; frame->palette_has_changed = 0; } @@ -92,7 +92,7 @@ static int imx_decode_frame(AVCodecContext *avctx, AVFrame *rframe, break; } - frame->key_frame = 0; + frame->flags &= ~AV_FRAME_FLAG_KEY; break; case 1: if (len == 0) { @@ -114,7 +114,7 @@ static int imx_decode_frame(AVCodecContext *avctx, AVFrame *rframe, break; } - frame->key_frame = 0; + frame->flags &= ~AV_FRAME_FLAG_KEY; } else { while (len > 0) { fill = bytestream2_get_byte(&gb); @@ -150,7 +150,7 @@ static int imx_decode_frame(AVCodecContext *avctx, AVFrame *rframe, } } - frame->pict_type = frame->key_frame ? AV_PICTURE_TYPE_I : AV_PICTURE_TYPE_P; + frame->pict_type = (frame->flags & AV_FRAME_FLAG_KEY) ? AV_PICTURE_TYPE_I : AV_PICTURE_TYPE_P; if ((ret = av_frame_ref(rframe, frame)) < 0) return ret; diff --git a/libavcodec/jpeg2000dec.c b/libavcodec/jpeg2000dec.c index 40e66501107..0e95cca64e0 100644 --- a/libavcodec/jpeg2000dec.c +++ b/libavcodec/jpeg2000dec.c @@ -2482,7 +2482,7 @@ static int jpeg2000_decode_frame(AVCodecContext *avctx, AVFrame *picture, if ((ret = ff_thread_get_buffer(avctx, picture, 0)) < 0) goto end; picture->pict_type = AV_PICTURE_TYPE_I; - picture->key_frame = 1; + picture->flags |= AV_FRAME_FLAG_KEY; if (ret = jpeg2000_read_bitstream_packets(s)) goto end; diff --git a/libavcodec/jvdec.c b/libavcodec/jvdec.c index e0287a9cb9d..f44b21af118 100644 --- a/libavcodec/jvdec.c +++ b/libavcodec/jvdec.c @@ -211,7 +211,7 @@ static int decode_frame(AVCodecContext *avctx, AVFrame *rframe, } if (video_size) { - s->frame->key_frame = 1; + s->frame->flags |= AV_FRAME_FLAG_KEY; s->frame->pict_type = AV_PICTURE_TYPE_I; s->frame->palette_has_changed = s->palette_has_changed; s->palette_has_changed = 0; diff --git a/libavcodec/kmvc.c b/libavcodec/kmvc.c index 153cea03b9c..de01f6b75be 100644 --- a/libavcodec/kmvc.c +++ b/libavcodec/kmvc.c @@ -288,10 +288,10 @@ static int decode_frame(AVCodecContext * avctx, AVFrame *frame, } if (header & KMVC_KEYFRAME) { - frame->key_frame = 1; + frame->flags |= AV_FRAME_FLAG_KEY; frame->pict_type = AV_PICTURE_TYPE_I; } else { - frame->key_frame = 0; + frame->flags &= ~AV_FRAME_FLAG_KEY; frame->pict_type = AV_PICTURE_TYPE_P; } diff --git a/libavcodec/lagarith.c b/libavcodec/lagarith.c index 78ccbc15b9c..ebc1f7613a4 100644 --- a/libavcodec/lagarith.c +++ b/libavcodec/lagarith.c @@ -550,7 +550,7 @@ static int lag_decode_frame(AVCodecContext *avctx, AVFrame *p, int i, j, planes = 3; int ret = 0; - p->key_frame = 1; + p->flags |= AV_FRAME_FLAG_KEY; p->pict_type = AV_PICTURE_TYPE_I; frametype = buf[0]; diff --git a/libavcodec/lcldec.c b/libavcodec/lcldec.c index eb5139a5c51..ed78d9d5703 100644 --- a/libavcodec/lcldec.c +++ b/libavcodec/lcldec.c @@ -478,7 +478,7 @@ static int decode_frame(AVCodecContext *avctx, AVFrame *frame, return AVERROR_INVALIDDATA; } - frame->key_frame = 1; + frame->flags |= AV_FRAME_FLAG_KEY; frame->pict_type = AV_PICTURE_TYPE_I; *got_frame = 1; diff --git a/libavcodec/libaomdec.c b/libavcodec/libaomdec.c index 53982559d93..767c216aa94 100644 --- a/libavcodec/libaomdec.c +++ b/libavcodec/libaomdec.c @@ -185,7 +185,10 @@ static int aom_decode(AVCodecContext *avctx, AVFrame *picture, aom_codec_frame_flags_t flags; ret = aom_codec_control(&ctx->decoder, AOMD_GET_FRAME_FLAGS, &flags); if (ret == AOM_CODEC_OK) { - picture->key_frame = !!(flags & AOM_FRAME_IS_KEY); + if (flags & AOM_FRAME_IS_KEY) + picture->flags |= AV_FRAME_FLAG_KEY; + else + picture->flags &= ~AV_FRAME_FLAG_KEY; if (flags & (AOM_FRAME_IS_KEY | AOM_FRAME_IS_INTRAONLY)) picture->pict_type = AV_PICTURE_TYPE_I; else if (flags & AOM_FRAME_IS_SWITCH) diff --git a/libavcodec/libdav1d.c b/libavcodec/libdav1d.c index ddf2311a41a..87aed167499 100644 --- a/libavcodec/libdav1d.c +++ b/libavcodec/libdav1d.c @@ -463,7 +463,10 @@ FF_ENABLE_DEPRECATION_WARNINGS goto fail; frame->pkt_dts = pkt->pts; - frame->key_frame = p->frame_hdr->frame_type == DAV1D_FRAME_TYPE_KEY; + if (p->frame_hdr->frame_type == DAV1D_FRAME_TYPE_KEY) + frame->flags |= AV_FRAME_FLAG_KEY; + else + frame->flags &= ~AV_FRAME_FLAG_KEY; switch (p->frame_hdr->frame_type) { case DAV1D_FRAME_TYPE_KEY: diff --git a/libavcodec/libjxldec.c b/libavcodec/libjxldec.c index 045a1535f93..65966b7b579 100644 --- a/libavcodec/libjxldec.c +++ b/libavcodec/libjxldec.c @@ -411,7 +411,7 @@ static int libjxl_decode_frame(AVCodecContext *avctx, AVFrame *frame, int *got_f /* full image is one frame, even if animated */ av_log(avctx, AV_LOG_DEBUG, "FULL_IMAGE event emitted\n"); frame->pict_type = AV_PICTURE_TYPE_I; - frame->key_frame = 1; + frame->flags |= AV_FRAME_FLAG_KEY; if (ctx->iccp) { AVFrameSideData *sd = av_frame_new_side_data_from_buf(frame, AV_FRAME_DATA_ICC_PROFILE, ctx->iccp); if (!sd) diff --git a/libavcodec/librsvgdec.c b/libavcodec/librsvgdec.c index 9c8aa2dedc8..2f160edcdf2 100644 --- a/libavcodec/librsvgdec.c +++ b/libavcodec/librsvgdec.c @@ -73,7 +73,7 @@ static int librsvg_decode_frame(AVCodecContext *avctx, AVFrame *frame, if ((ret = ff_get_buffer(avctx, frame, 0))) return ret; frame->pict_type = AV_PICTURE_TYPE_I; - frame->key_frame = 1; + frame->flags |= AV_FRAME_FLAG_KEY; image = cairo_image_surface_create_for_data(frame->data[0], CAIRO_FORMAT_ARGB32, frame->width, frame->height, diff --git a/libavcodec/libuavs3d.c b/libavcodec/libuavs3d.c index 5c08d2b8d3e..66e8d31001b 100644 --- a/libavcodec/libuavs3d.c +++ b/libavcodec/libuavs3d.c @@ -96,7 +96,10 @@ FF_ENABLE_DEPRECATION_WARNINGS av_log(NULL, AV_LOG_WARNING, "Error frame type in uavs3d: %d.\n", dec_frame->type); } else { frm->pict_type = ff_avs3_image_type[dec_frame->type]; - frm->key_frame = (frm->pict_type == AV_PICTURE_TYPE_I); + if (frm->pict_type == AV_PICTURE_TYPE_I) + frm->flags |= AV_FRAME_FLAG_KEY; + else + frm->flags &= ~AV_FRAME_FLAG_KEY; } for (i = 0; i < 3; i++) { diff --git a/libavcodec/loco.c b/libavcodec/loco.c index d57a67317a0..3d11823284a 100644 --- a/libavcodec/loco.c +++ b/libavcodec/loco.c @@ -206,7 +206,7 @@ static int decode_frame(AVCodecContext *avctx, AVFrame *p, if ((ret = ff_get_buffer(avctx, p, 0)) < 0) return ret; - p->key_frame = 1; + p->flags |= AV_FRAME_FLAG_KEY; #define ADVANCE_BY_DECODED do { \ if (decoded < 0 || decoded >= buf_size) goto buf_too_small; \ diff --git a/libavcodec/lscrdec.c b/libavcodec/lscrdec.c index 76a46751f07..415914bf0ac 100644 --- a/libavcodec/lscrdec.c +++ b/libavcodec/lscrdec.c @@ -154,10 +154,13 @@ static int decode_frame_lscr(AVCodecContext *avctx, AVFrame *rframe, size = bytestream2_get_le32(gb); - frame->key_frame = (nb_blocks == 1) && - (w == avctx->width) && - (h == avctx->height) && - (x == 0) && (y == 0); + if ((nb_blocks == 1) && + (w == avctx->width) && + (h == avctx->height) && + (x == 0) && (y == 0)) + frame->flags |= AV_FRAME_FLAG_KEY; + else + frame->flags &= ~AV_FRAME_FLAG_KEY; bytestream2_seek(gb, 2 + nb_blocks * 12 + offset, SEEK_SET); csize = bytestream2_get_be32(gb); @@ -199,7 +202,7 @@ static int decode_frame_lscr(AVCodecContext *avctx, AVFrame *rframe, } } - frame->pict_type = frame->key_frame ? AV_PICTURE_TYPE_I : AV_PICTURE_TYPE_P; + frame->pict_type = (frame->flags & AV_FRAME_FLAG_KEY) ? AV_PICTURE_TYPE_I : AV_PICTURE_TYPE_P; if ((ret = av_frame_ref(rframe, frame)) < 0) return ret; diff --git a/libavcodec/m101.c b/libavcodec/m101.c index 809c89c4f3b..43a3c7bbe5b 100644 --- a/libavcodec/m101.c +++ b/libavcodec/m101.c @@ -67,7 +67,7 @@ static int m101_decode_frame(AVCodecContext *avctx, AVFrame *frame, if ((ret = ff_get_buffer(avctx, frame, 0)) < 0) return ret; frame->pict_type = AV_PICTURE_TYPE_I; - frame->key_frame = 1; + frame->flags |= AV_FRAME_FLAG_KEY; if ((avctx->extradata[3*4] & 3) != 3) { frame->flags |= AV_FRAME_FLAG_INTERLACED; if (avctx->extradata[3*4] & 1) diff --git a/libavcodec/magicyuv.c b/libavcodec/magicyuv.c index 62263409b1e..7898cd5be45 100644 --- a/libavcodec/magicyuv.c +++ b/libavcodec/magicyuv.c @@ -637,7 +637,7 @@ static int magy_decode_frame(AVCodecContext *avctx, AVFrame *p, return ret; p->pict_type = AV_PICTURE_TYPE_I; - p->key_frame = 1; + p->flags |= AV_FRAME_FLAG_KEY; if ((ret = ff_thread_get_buffer(avctx, p, 0)) < 0) return ret; diff --git a/libavcodec/mdec.c b/libavcodec/mdec.c index 640b671a0fe..44b12471a9e 100644 --- a/libavcodec/mdec.c +++ b/libavcodec/mdec.c @@ -177,7 +177,7 @@ static int decode_frame(AVCodecContext *avctx, AVFrame *frame, if ((ret = ff_thread_get_buffer(avctx, frame, 0)) < 0) return ret; frame->pict_type = AV_PICTURE_TYPE_I; - frame->key_frame = 1; + frame->flags |= AV_FRAME_FLAG_KEY; av_fast_padded_malloc(&a->bitstream_buffer, &a->bitstream_buffer_size, buf_size); if (!a->bitstream_buffer) diff --git a/libavcodec/midivid.c b/libavcodec/midivid.c index 599d5c8f8fa..70730231b5f 100644 --- a/libavcodec/midivid.c +++ b/libavcodec/midivid.c @@ -222,7 +222,10 @@ static int decode_frame(AVCodecContext *avctx, AVFrame *rframe, return ret; frame->pict_type = key ? AV_PICTURE_TYPE_I : AV_PICTURE_TYPE_P; - frame->key_frame = key; + if (key) + frame->flags |= AV_FRAME_FLAG_KEY; + else + frame->flags &= ~AV_FRAME_FLAG_KEY; *got_frame = 1; return avpkt->size; diff --git a/libavcodec/mjpegdec.c b/libavcodec/mjpegdec.c index acdeb68596d..ab7fa73819f 100644 --- a/libavcodec/mjpegdec.c +++ b/libavcodec/mjpegdec.c @@ -745,7 +745,7 @@ int ff_mjpeg_decode_sof(MJpegDecodeContext *s) if (s->avctx->skip_frame == AVDISCARD_ALL) { s->picture_ptr->pict_type = AV_PICTURE_TYPE_I; - s->picture_ptr->key_frame = 1; + s->picture_ptr->flags |= AV_FRAME_FLAG_KEY; s->got_picture = 1; return 0; } @@ -754,7 +754,7 @@ int ff_mjpeg_decode_sof(MJpegDecodeContext *s) if (ff_get_buffer(s->avctx, s->picture_ptr, AV_GET_BUFFER_FLAG_REF) < 0) return -1; s->picture_ptr->pict_type = AV_PICTURE_TYPE_I; - s->picture_ptr->key_frame = 1; + s->picture_ptr->flags |= AV_FRAME_FLAG_KEY; s->got_picture = 1; // Lets clear the palette to avoid leaving uninitialized values in it diff --git a/libavcodec/mobiclip.c b/libavcodec/mobiclip.c index c3b2383dbc4..381b492de3a 100644 --- a/libavcodec/mobiclip.c +++ b/libavcodec/mobiclip.c @@ -1235,7 +1235,7 @@ static int mobiclip_decode(AVCodecContext *avctx, AVFrame *rframe, if (get_bits1(gb)) { frame->pict_type = AV_PICTURE_TYPE_I; - frame->key_frame = 1; + frame->flags |= AV_FRAME_FLAG_KEY; s->moflex = get_bits1(gb); s->dct_tab_idx = get_bits1(gb); @@ -1256,7 +1256,7 @@ static int mobiclip_decode(AVCodecContext *avctx, AVFrame *rframe, memset(motion, 0, s->motion_size); frame->pict_type = AV_PICTURE_TYPE_P; - frame->key_frame = 0; + frame->flags &= ~AV_FRAME_FLAG_KEY; s->dct_tab_idx = 0; ret = setup_qtables(avctx, s->quantizer + (int64_t)get_se_golomb(gb)); diff --git a/libavcodec/mpeg12dec.c b/libavcodec/mpeg12dec.c index 6c4cbccc597..ebde68a4dda 100644 --- a/libavcodec/mpeg12dec.c +++ b/libavcodec/mpeg12dec.c @@ -1343,7 +1343,10 @@ static int mpeg1_decode_picture(AVCodecContext *avctx, const uint8_t *buf, s->mpeg_f_code[1][1] = f_code; } s->current_picture.f->pict_type = s->pict_type; - s->current_picture.f->key_frame = s->pict_type == AV_PICTURE_TYPE_I; + if (s->pict_type == AV_PICTURE_TYPE_I) + s->current_picture.f->flags |= AV_FRAME_FLAG_KEY; + else + s->current_picture.f->flags &= ~AV_FRAME_FLAG_KEY; if (avctx->debug & FF_DEBUG_PICT_INFO) av_log(avctx, AV_LOG_DEBUG, @@ -1525,7 +1528,10 @@ static int mpeg_decode_picture_coding_extension(Mpeg1Context *s1) } else s->pict_type = AV_PICTURE_TYPE_B; s->current_picture.f->pict_type = s->pict_type; - s->current_picture.f->key_frame = s->pict_type == AV_PICTURE_TYPE_I; + if (s->pict_type == AV_PICTURE_TYPE_I) + s->current_picture.f->flags |= AV_FRAME_FLAG_KEY; + else + s->current_picture.f->flags &= ~AV_FRAME_FLAG_KEY; } s->intra_dc_precision = get_bits(&s->gb, 2); @@ -3046,7 +3052,7 @@ static int ipu_decode_frame(AVCodecContext *avctx, AVFrame *frame, return AVERROR_INVALIDDATA; frame->pict_type = AV_PICTURE_TYPE_I; - frame->key_frame = 1; + frame->flags |= AV_FRAME_FLAG_KEY; *got_frame = 1; return avpkt->size; diff --git a/libavcodec/mpeg12enc.c b/libavcodec/mpeg12enc.c index c7438fbe072..4aa45e9e869 100644 --- a/libavcodec/mpeg12enc.c +++ b/libavcodec/mpeg12enc.c @@ -290,7 +290,7 @@ static void mpeg1_encode_sequence_header(MpegEncContext *s) AVRational aspect_ratio = s->avctx->sample_aspect_ratio; int aspect_ratio_info; - if (!s->current_picture.f->key_frame) + if (!(s->current_picture.f->flags & AV_FRAME_FLAG_KEY)) return; if (aspect_ratio.num == 0 || aspect_ratio.den == 0) diff --git a/libavcodec/mpegvideo_dec.c b/libavcodec/mpegvideo_dec.c index 482f388b993..765ccd0ba4a 100644 --- a/libavcodec/mpegvideo_dec.c +++ b/libavcodec/mpegvideo_dec.c @@ -343,7 +343,10 @@ FF_ENABLE_DEPRECATION_WARNINGS s->current_picture_ptr->field_picture = s->picture_structure != PICT_FRAME; s->current_picture_ptr->f->pict_type = s->pict_type; - s->current_picture_ptr->f->key_frame = s->pict_type == AV_PICTURE_TYPE_I; + if (s->pict_type == AV_PICTURE_TYPE_I) + s->current_picture.f->flags |= AV_FRAME_FLAG_KEY; + else + s->current_picture.f->flags &= ~AV_FRAME_FLAG_KEY; if ((ret = ff_mpeg_ref_picture(s->avctx, &s->current_picture, s->current_picture_ptr)) < 0) @@ -382,7 +385,7 @@ FF_ENABLE_DEPRECATION_WARNINGS 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->flags &= ~AV_FRAME_FLAG_KEY; s->last_picture_ptr->f->pict_type = AV_PICTURE_TYPE_P; if (alloc_picture(s, s->last_picture_ptr) < 0) { @@ -424,7 +427,7 @@ FF_ENABLE_DEPRECATION_WARNINGS 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->flags &= ~AV_FRAME_FLAG_KEY; s->next_picture_ptr->f->pict_type = AV_PICTURE_TYPE_P; if (alloc_picture(s, s->next_picture_ptr) < 0) { diff --git a/libavcodec/mpegvideo_enc.c b/libavcodec/mpegvideo_enc.c index efd8e63aa89..9bdf5dbe079 100644 --- a/libavcodec/mpegvideo_enc.c +++ b/libavcodec/mpegvideo_enc.c @@ -1703,7 +1703,10 @@ static int frame_start(MpegEncContext *s) } s->current_picture_ptr->f->pict_type = s->pict_type; - s->current_picture_ptr->f->key_frame = s->pict_type == AV_PICTURE_TYPE_I; + if (s->pict_type == AV_PICTURE_TYPE_I) + s->current_picture.f->flags |= AV_FRAME_FLAG_KEY; + else + s->current_picture.f->flags &= ~AV_FRAME_FLAG_KEY; ff_mpeg_unref_picture(s->avctx, &s->current_picture); if ((ret = ff_mpeg_ref_picture(s->avctx, &s->current_picture, @@ -1979,7 +1982,7 @@ int ff_mpv_encode_picture(AVCodecContext *avctx, AVPacket *pkt, return ret; } - if (s->current_picture.f->key_frame) + if (s->current_picture.f->flags & AV_FRAME_FLAG_KEY) pkt->flags |= AV_PKT_FLAG_KEY; if (s->mb_info) av_packet_shrink_side_data(pkt, AV_PKT_DATA_H263_MB_INFO, s->mb_info_size); @@ -3783,12 +3786,17 @@ static int encode_picture(MpegEncContext *s) } //FIXME var duplication - s->current_picture_ptr->f->key_frame = - s->current_picture.f->key_frame = s->pict_type == AV_PICTURE_TYPE_I; //FIXME pic_ptr + if (s->pict_type == AV_PICTURE_TYPE_I) { + s->current_picture_ptr->f->flags |= AV_FRAME_FLAG_KEY; //FIXME pic_ptr + s->current_picture.f->flags |= AV_FRAME_FLAG_KEY; + } else { + s->current_picture_ptr->f->flags &= ~AV_FRAME_FLAG_KEY; //FIXME pic_ptr + s->current_picture.f->flags &= ~AV_FRAME_FLAG_KEY; + } s->current_picture_ptr->f->pict_type = s->current_picture.f->pict_type = s->pict_type; - if (s->current_picture.f->key_frame) + if (s->current_picture.f->flags & AV_FRAME_FLAG_KEY) s->picture_in_gop_number=0; s->mb_x = s->mb_y = 0; diff --git a/libavcodec/mscc.c b/libavcodec/mscc.c index e8406aa268c..18446644777 100644 --- a/libavcodec/mscc.c +++ b/libavcodec/mscc.c @@ -200,7 +200,7 @@ static int decode_frame(AVCodecContext *avctx, AVFrame *frame, s->uncomp_buf + s->bpp * j * avctx->width, s->bpp * avctx->width); } - frame->key_frame = 1; + frame->flags |= AV_FRAME_FLAG_KEY; frame->pict_type = AV_PICTURE_TYPE_I; *got_frame = 1; diff --git a/libavcodec/msp2dec.c b/libavcodec/msp2dec.c index 9c51c35c61e..30a2825e47b 100644 --- a/libavcodec/msp2dec.c +++ b/libavcodec/msp2dec.c @@ -47,7 +47,7 @@ static int msp2_decode_frame(AVCodecContext *avctx, AVFrame *p, return ret; p->pict_type = AV_PICTURE_TYPE_I; - p->key_frame = 1; + p->flags |= AV_FRAME_FLAG_KEY; bytestream2_init(&idx, buf, 2 * avctx->height); buf += 2 * avctx->height; diff --git a/libavcodec/mss1.c b/libavcodec/mss1.c index 775852102a9..dc06a9e2361 100644 --- a/libavcodec/mss1.c +++ b/libavcodec/mss1.c @@ -165,12 +165,12 @@ static int mss1_decode_frame(AVCodecContext *avctx, AVFrame *rframe, c->corrupted = 0; ff_mss12_slicecontext_reset(&ctx->sc); pal_changed = decode_pal(c, &acoder); - ctx->pic->key_frame = 1; + ctx->pic->flags |= AV_FRAME_FLAG_KEY; ctx->pic->pict_type = AV_PICTURE_TYPE_I; } else { if (c->corrupted) return AVERROR_INVALIDDATA; - ctx->pic->key_frame = 0; + ctx->pic->flags &= ~AV_FRAME_FLAG_KEY; ctx->pic->pict_type = AV_PICTURE_TYPE_P; } c->corrupted = ff_mss12_decode_rect(&ctx->sc, &acoder, 0, 0, diff --git a/libavcodec/mss2.c b/libavcodec/mss2.c index 1d1ed11f54e..98103f7fed6 100644 --- a/libavcodec/mss2.c +++ b/libavcodec/mss2.c @@ -660,7 +660,10 @@ static int mss2_decode_frame(AVCodecContext *avctx, AVFrame *frame, frame->linesize[0] * (avctx->height - 1); c->rgb_stride = -frame->linesize[0]; - frame->key_frame = keyframe; + if (keyframe) + frame->flags |= AV_FRAME_FLAG_KEY; + else + frame->flags &= ~AV_FRAME_FLAG_KEY; frame->pict_type = keyframe ? AV_PICTURE_TYPE_I : AV_PICTURE_TYPE_P; if (is_555) { diff --git a/libavcodec/mss3.c b/libavcodec/mss3.c index 023f110ec81..2701e9b912a 100644 --- a/libavcodec/mss3.c +++ b/libavcodec/mss3.c @@ -740,7 +740,10 @@ static int mss3_decode_frame(AVCodecContext *avctx, AVFrame *rframe, if ((ret = ff_reget_buffer(avctx, c->pic, 0)) < 0) return ret; - c->pic->key_frame = keyframe; + if (keyframe) + c->pic->flags |= AV_FRAME_FLAG_KEY; + else + c->pic->flags &= ~AV_FRAME_FLAG_KEY; c->pic->pict_type = keyframe ? AV_PICTURE_TYPE_I : AV_PICTURE_TYPE_P; if (!bytestream2_get_bytes_left(&gb)) { if ((ret = av_frame_ref(rframe, c->pic)) < 0) diff --git a/libavcodec/mss4.c b/libavcodec/mss4.c index dceb42da25d..75f31beda64 100644 --- a/libavcodec/mss4.c +++ b/libavcodec/mss4.c @@ -503,7 +503,10 @@ static int mss4_decode_frame(AVCodecContext *avctx, AVFrame *rframe, if ((ret = ff_reget_buffer(avctx, c->pic, 0)) < 0) return ret; - c->pic->key_frame = (frame_type == INTRA_FRAME); + if (frame_type == INTRA_FRAME) + c->pic->flags |= AV_FRAME_FLAG_KEY; + else + c->pic->flags &= ~AV_FRAME_FLAG_KEY; c->pic->pict_type = (frame_type == INTRA_FRAME) ? AV_PICTURE_TYPE_I : AV_PICTURE_TYPE_P; if (frame_type == SKIP_FRAME) { diff --git a/libavcodec/mv30.c b/libavcodec/mv30.c index 24b04400fde..c2d05470534 100644 --- a/libavcodec/mv30.c +++ b/libavcodec/mv30.c @@ -623,9 +623,8 @@ static int decode_frame(AVCodecContext *avctx, AVFrame *frame, get_qtable(s->intraq_tab[0], s->intra_quant, luma_tab); get_qtable(s->intraq_tab[1], s->intra_quant, chroma_tab); - frame->key_frame = s->is_inter == 0; - - if (frame->key_frame) { + if (s->is_inter == 0) { + frame->flags |= AV_FRAME_FLAG_KEY; ret = decode_intra(avctx, gb, frame); if (ret < 0) return ret; @@ -638,6 +637,7 @@ static int decode_frame(AVCodecContext *avctx, AVFrame *frame, return AVERROR_INVALIDDATA; } + frame->flags &= ~AV_FRAME_FLAG_KEY; ret = decode_inter(avctx, gb, frame, s->prev_frame); if (ret < 0) return ret; diff --git a/libavcodec/mvcdec.c b/libavcodec/mvcdec.c index 1e99f44a7d1..6c971f709ed 100644 --- a/libavcodec/mvcdec.c +++ b/libavcodec/mvcdec.c @@ -247,7 +247,7 @@ static int mvc_decode_frame(AVCodecContext *avctx, AVFrame *frame, return ret; frame->pict_type = AV_PICTURE_TYPE_I; - frame->key_frame = 1; + frame->flags |= AV_FRAME_FLAG_KEY; *got_frame = 1; diff --git a/libavcodec/mvha.c b/libavcodec/mvha.c index 55056c91cf4..8fb4a69e9ec 100644 --- a/libavcodec/mvha.c +++ b/libavcodec/mvha.c @@ -272,7 +272,7 @@ static int decode_frame(AVCodecContext *avctx, AVFrame *frame, } frame->pict_type = AV_PICTURE_TYPE_I; - frame->key_frame = 1; + frame->flags |= AV_FRAME_FLAG_KEY; *got_frame = 1; return avpkt->size; diff --git a/libavcodec/mwsc.c b/libavcodec/mwsc.c index f57648bb15a..c7045ac793f 100644 --- a/libavcodec/mwsc.c +++ b/libavcodec/mwsc.c @@ -119,10 +119,13 @@ static int decode_frame(AVCodecContext *avctx, AVFrame *frame, bytestream2_init(&gbp, s->prev_frame->data[0], avctx->height * s->prev_frame->linesize[0]); bytestream2_init_writer(&pb, frame->data[0], avctx->height * frame->linesize[0]); - frame->key_frame = rle_uncompress(&gb, &pb, &gbp, avctx->width, avctx->height, avctx->width * 3, - frame->linesize[0], s->prev_frame->linesize[0]); + if (rle_uncompress(&gb, &pb, &gbp, avctx->width, avctx->height, avctx->width * 3, + frame->linesize[0], s->prev_frame->linesize[0])) + frame->flags |= AV_FRAME_FLAG_KEY; + else + frame->flags &= ~AV_FRAME_FLAG_KEY; - frame->pict_type = frame->key_frame ? AV_PICTURE_TYPE_I : AV_PICTURE_TYPE_P; + frame->pict_type = (frame->flags & AV_FRAME_FLAG_KEY) ? AV_PICTURE_TYPE_I : AV_PICTURE_TYPE_P; av_frame_unref(s->prev_frame); if ((ret = av_frame_ref(s->prev_frame, frame)) < 0) diff --git a/libavcodec/mxpegdec.c b/libavcodec/mxpegdec.c index 760b12f0cce..73df2ff9ffa 100644 --- a/libavcodec/mxpegdec.c +++ b/libavcodec/mxpegdec.c @@ -286,11 +286,11 @@ static int mxpeg_decode_frame(AVCodecContext *avctx, AVFrame *rframe, AV_GET_BUFFER_FLAG_REF)) < 0) return ret; jpg->picture_ptr->pict_type = AV_PICTURE_TYPE_P; - jpg->picture_ptr->key_frame = 0; + jpg->picture_ptr->flags &= ~AV_FRAME_FLAG_KEY; jpg->got_picture = 1; } else { jpg->picture_ptr->pict_type = AV_PICTURE_TYPE_I; - jpg->picture_ptr->key_frame = 1; + jpg->picture_ptr->flags |= AV_FRAME_FLAG_KEY; } if (s->got_mxm_bitmask) { diff --git a/libavcodec/notchlc.c b/libavcodec/notchlc.c index 90704e1aeba..d973c83ac73 100644 --- a/libavcodec/notchlc.c +++ b/libavcodec/notchlc.c @@ -514,7 +514,7 @@ static int decode_frame(AVCodecContext *avctx, AVFrame *p, return ret; p->pict_type = AV_PICTURE_TYPE_I; - p->key_frame = 1; + p->flags |= AV_FRAME_FLAG_KEY; *got_frame = 1; diff --git a/libavcodec/nuv.c b/libavcodec/nuv.c index d5391eee54c..82048e93268 100644 --- a/libavcodec/nuv.c +++ b/libavcodec/nuv.c @@ -263,7 +263,10 @@ static int decode_frame(AVCodecContext *avctx, AVFrame *picture, } c->pic->pict_type = keyframe ? AV_PICTURE_TYPE_I : AV_PICTURE_TYPE_P; - c->pic->key_frame = keyframe; + if (keyframe) + c->pic->flags |= AV_FRAME_FLAG_KEY; + else + c->pic->flags &= ~AV_FRAME_FLAG_KEY; // decompress/copy/whatever data switch (comptype) { case NUV_LZO: diff --git a/libavcodec/pafvideo.c b/libavcodec/pafvideo.c index 458fe9ff47c..fa914ccbaa9 100644 --- a/libavcodec/pafvideo.c +++ b/libavcodec/pafvideo.c @@ -296,10 +296,10 @@ static int paf_video_decode(AVCodecContext *avctx, AVFrame *rframe, if (code & 0x20) { // frame is keyframe memset(c->pic->data[1], 0, AVPALETTE_SIZE); c->current_frame = 0; - c->pic->key_frame = 1; + c->pic->flags |= AV_FRAME_FLAG_KEY; c->pic->pict_type = AV_PICTURE_TYPE_I; } else { - c->pic->key_frame = 0; + c->pic->flags &= ~AV_FRAME_FLAG_KEY; c->pic->pict_type = AV_PICTURE_TYPE_P; } diff --git a/libavcodec/pdvdec.c b/libavcodec/pdvdec.c index b1fc19b1c93..3ac2f98b3d9 100644 --- a/libavcodec/pdvdec.c +++ b/libavcodec/pdvdec.c @@ -107,7 +107,7 @@ static int decode_frame(AVCodecContext *avctx, AVFrame *frame, return ret; if (avpkt->flags & AV_PKT_FLAG_KEY) { - frame->key_frame = 1; + frame->flags |= AV_FRAME_FLAG_KEY; frame->pict_type = AV_PICTURE_TYPE_I; } else { frame->pict_type = AV_PICTURE_TYPE_P; diff --git a/libavcodec/pgxdec.c b/libavcodec/pgxdec.c index e5d1df784e6..cc7cdb8c9ac 100644 --- a/libavcodec/pgxdec.c +++ b/libavcodec/pgxdec.c @@ -140,7 +140,7 @@ static int pgx_decode_frame(AVCodecContext *avctx, AVFrame *p, if ((ret = ff_get_buffer(avctx, p, 0)) < 0) return ret; p->pict_type = AV_PICTURE_TYPE_I; - p->key_frame = 1; + p->flags |= AV_FRAME_FLAG_KEY; avctx->bits_per_raw_sample = depth; if (bpp == 8) write_frame_8(p, &g, width, height, sign, depth); diff --git a/libavcodec/photocd.c b/libavcodec/photocd.c index 3030a80e0d6..3a09b81908f 100644 --- a/libavcodec/photocd.c +++ b/libavcodec/photocd.c @@ -332,7 +332,7 @@ static int photocd_decode_frame(AVCodecContext *avctx, AVFrame *p, return ret; p->pict_type = AV_PICTURE_TYPE_I; - p->key_frame = 1; + p->flags |= AV_FRAME_FLAG_KEY; bytestream2_init(gb, avpkt->data, avpkt->size); diff --git a/libavcodec/pixlet.c b/libavcodec/pixlet.c index b349d397f4c..6e925308b80 100644 --- a/libavcodec/pixlet.c +++ b/libavcodec/pixlet.c @@ -667,7 +667,7 @@ static int pixlet_decode_frame(AVCodecContext *avctx, AVFrame *p, bytestream2_skip(&ctx->gb, 8); p->pict_type = AV_PICTURE_TYPE_I; - p->key_frame = 1; + p->flags |= AV_FRAME_FLAG_KEY; p->color_range = AVCOL_RANGE_JPEG; ret = ff_thread_get_buffer(avctx, p, 0); diff --git a/libavcodec/pngdec.c b/libavcodec/pngdec.c index 03b3efdabc9..83db0ad66dd 100644 --- a/libavcodec/pngdec.c +++ b/libavcodec/pngdec.c @@ -840,7 +840,7 @@ static int decode_idat_chunk(AVCodecContext *avctx, PNGDecContext *s, } p->pict_type = AV_PICTURE_TYPE_I; - p->key_frame = 1; + p->flags |= AV_FRAME_FLAG_KEY; p->flags |= AV_FRAME_FLAG_INTERLACED * !!s->interlace_type; if ((ret = populate_avctx_color_fields(avctx, p)) < 0) diff --git a/libavcodec/pnmdec.c b/libavcodec/pnmdec.c index 978e4c037ea..72bc83b272c 100644 --- a/libavcodec/pnmdec.c +++ b/libavcodec/pnmdec.c @@ -65,7 +65,7 @@ static int pnm_decode_frame(AVCodecContext *avctx, AVFrame *p, if ((ret = ff_get_buffer(avctx, p, 0)) < 0) return ret; p->pict_type = AV_PICTURE_TYPE_I; - p->key_frame = 1; + p->flags |= AV_FRAME_FLAG_KEY; avctx->bits_per_raw_sample = av_log2(s->maxval) + 1; switch (avctx->pix_fmt) { diff --git a/libavcodec/proresdec2.c b/libavcodec/proresdec2.c index 88f4c49ce61..6445d948d99 100644 --- a/libavcodec/proresdec2.c +++ b/libavcodec/proresdec2.c @@ -793,7 +793,7 @@ static int decode_frame(AVCodecContext *avctx, AVFrame *frame, ctx->frame = frame; ctx->frame->pict_type = AV_PICTURE_TYPE_I; - ctx->frame->key_frame = 1; + ctx->frame->flags |= AV_FRAME_FLAG_KEY; ctx->first_field = 1; buf += 8; diff --git a/libavcodec/prosumer.c b/libavcodec/prosumer.c index e199d1aaa9e..a1ed6a9e538 100644 --- a/libavcodec/prosumer.c +++ b/libavcodec/prosumer.c @@ -195,7 +195,7 @@ static int decode_frame(AVCodecContext *avctx, AVFrame *frame, } frame->pict_type = AV_PICTURE_TYPE_I; - frame->key_frame = 1; + frame->flags |= AV_FRAME_FLAG_KEY; *got_frame = 1; return avpkt->size; diff --git a/libavcodec/qdrw.c b/libavcodec/qdrw.c index e41451e9a77..65e7269e5d8 100644 --- a/libavcodec/qdrw.c +++ b/libavcodec/qdrw.c @@ -503,7 +503,7 @@ static int decode_frame(AVCodecContext *avctx, AVFrame *p, if (*got_frame) { p->pict_type = AV_PICTURE_TYPE_I; - p->key_frame = 1; + p->flags |= AV_FRAME_FLAG_KEY; return avpkt->size; } else { diff --git a/libavcodec/qoidec.c b/libavcodec/qoidec.c index 9414d2fbe9a..37bc2084c06 100644 --- a/libavcodec/qoidec.c +++ b/libavcodec/qoidec.c @@ -106,7 +106,7 @@ static int qoi_decode_frame(AVCodecContext *avctx, AVFrame *p, memcpy(&dst[off_x * channels], px, channels); } - p->key_frame = 1; + p->flags |= AV_FRAME_FLAG_KEY; p->pict_type = AV_PICTURE_TYPE_I; *got_frame = 1; diff --git a/libavcodec/qpeg.c b/libavcodec/qpeg.c index 5bca338acf5..43a24fab081 100644 --- a/libavcodec/qpeg.c +++ b/libavcodec/qpeg.c @@ -304,7 +304,10 @@ static int decode_frame(AVCodecContext *avctx, AVFrame *p, if ((ret = av_frame_ref(ref, p)) < 0) return ret; - p->key_frame = intra; + if (intra) + p->flags |= AV_FRAME_FLAG_KEY; + else + p->flags &= ~AV_FRAME_FLAG_KEY; p->pict_type = intra ? AV_PICTURE_TYPE_I : AV_PICTURE_TYPE_P; *got_frame = 1; diff --git a/libavcodec/qsvdec.c b/libavcodec/qsvdec.c index e137a38e3c6..da700f25e9f 100644 --- a/libavcodec/qsvdec.c +++ b/libavcodec/qsvdec.c @@ -834,8 +834,12 @@ static int qsv_decode(AVCodecContext *avctx, QSVContext *q, !(outsurf->Info.PicStruct & MFX_PICSTRUCT_PROGRESSIVE); frame->pict_type = ff_qsv_map_pictype(aframe.frame->dec_info.FrameType); //Key frame is IDR frame is only suitable for H264. For HEVC, IRAPs are key frames. - if (avctx->codec_id == AV_CODEC_ID_H264) - frame->key_frame = !!(aframe.frame->dec_info.FrameType & MFX_FRAMETYPE_IDR); + if (avctx->codec_id == AV_CODEC_ID_H264) { + if (aframe.frame->dec_info.FrameType & MFX_FRAMETYPE_IDR) + frame->flags |= AV_FRAME_FLAG_KEY; + else + frame->flags &= ~AV_FRAME_FLAG_KEY; + } /* update the surface properties */ if (avctx->pix_fmt == AV_PIX_FMT_QSV) diff --git a/libavcodec/r210dec.c b/libavcodec/r210dec.c index ae80f46eb67..fe6a025988e 100644 --- a/libavcodec/r210dec.c +++ b/libavcodec/r210dec.c @@ -57,7 +57,7 @@ static int decode_frame(AVCodecContext *avctx, AVFrame *pic, return ret; pic->pict_type = AV_PICTURE_TYPE_I; - pic->key_frame = 1; + pic->flags |= AV_FRAME_FLAG_KEY; g_line = pic->data[0]; b_line = pic->data[1]; r_line = pic->data[2]; diff --git a/libavcodec/rasc.c b/libavcodec/rasc.c index cfa3d6b079d..4d057e80e72 100644 --- a/libavcodec/rasc.c +++ b/libavcodec/rasc.c @@ -740,7 +740,10 @@ static int decode_frame(AVCodecContext *avctx, AVFrame *frame, if (!s->skip_cursor) draw_cursor(avctx); - s->frame->key_frame = intra; + if (intra) + s->frame->flags |= AV_FRAME_FLAG_KEY; + else + s->frame->flags &= ~AV_FRAME_FLAG_KEY; s->frame->pict_type = intra ? AV_PICTURE_TYPE_I : AV_PICTURE_TYPE_P; *got_frame = 1; diff --git a/libavcodec/rawdec.c b/libavcodec/rawdec.c index 72920d86f0d..baca16c7439 100644 --- a/libavcodec/rawdec.c +++ b/libavcodec/rawdec.c @@ -227,7 +227,7 @@ static int raw_decode(AVCodecContext *avctx, AVFrame *frame, need_copy = !avpkt->buf || context->is_1_2_4_8_bpp || context->is_yuv2 || context->is_lt_16bpp; frame->pict_type = AV_PICTURE_TYPE_I; - frame->key_frame = 1; + frame->flags |= AV_FRAME_FLAG_KEY; res = ff_decode_frame_props(avctx, frame); if (res < 0) diff --git a/libavcodec/rscc.c b/libavcodec/rscc.c index 61a25df3821..2ae88999779 100644 --- a/libavcodec/rscc.c +++ b/libavcodec/rscc.c @@ -339,7 +339,7 @@ static int rscc_decode_frame(AVCodecContext *avctx, AVFrame *frame, /* Keyframe when the number of pixels updated matches the whole surface */ if (pixel_size == ctx->inflated_size) { frame->pict_type = AV_PICTURE_TYPE_I; - frame->key_frame = 1; + frame->flags |= AV_FRAME_FLAG_KEY; } else { frame->pict_type = AV_PICTURE_TYPE_P; } diff --git a/libavcodec/sanm.c b/libavcodec/sanm.c index bec3c770ec4..b70daab7ac9 100644 --- a/libavcodec/sanm.c +++ b/libavcodec/sanm.c @@ -1484,11 +1484,13 @@ static int decode_frame(AVCodecContext *avctx, AVFrame *frame, return ret; ctx->rotate_code = header.rotate_code; - if ((ctx->frame->key_frame = !header.seq_num)) { + if (!header.seq_num) { + ctx->frame->flags |= AV_FRAME_FLAG_KEY; ctx->frame->pict_type = AV_PICTURE_TYPE_I; fill_frame(ctx->frm1, ctx->npixels, header.bg_color); fill_frame(ctx->frm2, ctx->npixels, header.bg_color); } else { + ctx->frame->flags &= ~AV_FRAME_FLAG_KEY; ctx->frame->pict_type = AV_PICTURE_TYPE_P; } diff --git a/libavcodec/scpr.c b/libavcodec/scpr.c index 7630adb3e09..b096965de54 100644 --- a/libavcodec/scpr.c +++ b/libavcodec/scpr.c @@ -516,18 +516,18 @@ static int decode_frame(AVCodecContext *avctx, AVFrame *frame, s->version = 1; s->get_freq = get_freq0; s->decode = decode0; - frame->key_frame = 1; + frame->flags |= AV_FRAME_FLAG_KEY; ret = decompress_i(avctx, (uint32_t *)s->current_frame->data[0], s->current_frame->linesize[0] / 4); } else if (type == 18) { s->version = 2; s->get_freq = get_freq; s->decode = decode; - frame->key_frame = 1; + frame->flags |= AV_FRAME_FLAG_KEY; ret = decompress_i(avctx, (uint32_t *)s->current_frame->data[0], s->current_frame->linesize[0] / 4); } else if (type == 34) { - frame->key_frame = 1; + frame->flags |= AV_FRAME_FLAG_KEY; s->version = 3; ret = decompress_i3(avctx, (uint32_t *)s->current_frame->data[0], s->current_frame->linesize[0] / 4); @@ -538,7 +538,7 @@ static int decode_frame(AVCodecContext *avctx, AVFrame *frame, if (bytestream2_get_bytes_left(gb) < 3) return AVERROR_INVALIDDATA; - frame->key_frame = 1; + frame->flags |= AV_FRAME_FLAG_KEY; bytestream2_skip(gb, 1); if (avctx->bits_per_coded_sample == 16) { uint16_t value = bytestream2_get_le16(gb); @@ -557,7 +557,7 @@ static int decode_frame(AVCodecContext *avctx, AVFrame *frame, dst += s->current_frame->linesize[0] / 4; } } else if (type == 0 || type == 1) { - frame->key_frame = 0; + frame->flags &= ~AV_FRAME_FLAG_KEY; if (s->version == 1 || s->version == 2) ret = decompress_p(avctx, (uint32_t *)s->current_frame->data[0], @@ -612,7 +612,7 @@ static int decode_frame(AVCodecContext *avctx, AVFrame *frame, } } - frame->pict_type = frame->key_frame ? AV_PICTURE_TYPE_I : AV_PICTURE_TYPE_P; + frame->pict_type = (frame->flags & AV_FRAME_FLAG_KEY) ? AV_PICTURE_TYPE_I : AV_PICTURE_TYPE_P; FFSWAP(AVFrame *, s->current_frame, s->last_frame); diff --git a/libavcodec/screenpresso.c b/libavcodec/screenpresso.c index 0d9e485043a..b27154991c9 100644 --- a/libavcodec/screenpresso.c +++ b/libavcodec/screenpresso.c @@ -173,7 +173,7 @@ static int screenpresso_decode_frame(AVCodecContext *avctx, AVFrame *frame, /* Usual properties */ if (keyframe) { frame->pict_type = AV_PICTURE_TYPE_I; - frame->key_frame = 1; + frame->flags |= AV_FRAME_FLAG_KEY; } else { frame->pict_type = AV_PICTURE_TYPE_P; } diff --git a/libavcodec/sga.c b/libavcodec/sga.c index d3f49242984..16442b40be6 100644 --- a/libavcodec/sga.c +++ b/libavcodec/sga.c @@ -499,7 +499,7 @@ static int sga_decode_frame(AVCodecContext *avctx, AVFrame *frame, memcpy(frame->data[1], s->pal, AVPALETTE_SIZE); frame->palette_has_changed = 1; frame->pict_type = AV_PICTURE_TYPE_I; - frame->key_frame = 1; + frame->flags |= AV_FRAME_FLAG_KEY; *got_frame = 1; diff --git a/libavcodec/sgidec.c b/libavcodec/sgidec.c index 92083f23de9..04a347c51e1 100644 --- a/libavcodec/sgidec.c +++ b/libavcodec/sgidec.c @@ -249,7 +249,7 @@ static int decode_frame(AVCodecContext *avctx, AVFrame *p, break; } p->pict_type = AV_PICTURE_TYPE_I; - p->key_frame = 1; + p->flags |= AV_FRAME_FLAG_KEY; /* Skip header. */ bytestream2_seek(&g, SGI_HEADER_SIZE, SEEK_SET); diff --git a/libavcodec/sgirledec.c b/libavcodec/sgirledec.c index 9e3a220ad41..18bf8081fc6 100644 --- a/libavcodec/sgirledec.c +++ b/libavcodec/sgirledec.c @@ -124,7 +124,7 @@ static int sgirle_decode_frame(AVCodecContext *avctx, AVFrame *frame, return ret; frame->pict_type = AV_PICTURE_TYPE_I; - frame->key_frame = 1; + frame->flags |= AV_FRAME_FLAG_KEY; *got_frame = 1; diff --git a/libavcodec/sheervideo.c b/libavcodec/sheervideo.c index eee60147422..d9c94ea9eb1 100644 --- a/libavcodec/sheervideo.c +++ b/libavcodec/sheervideo.c @@ -1973,7 +1973,7 @@ static int decode_frame(AVCodecContext *avctx, AVFrame *p, } p->pict_type = AV_PICTURE_TYPE_I; - p->key_frame = 1; + p->flags |= AV_FRAME_FLAG_KEY; if ((ret = ff_thread_get_buffer(avctx, p, 0)) < 0) return ret; diff --git a/libavcodec/smacker.c b/libavcodec/smacker.c index a514120b65e..08841f4cce2 100644 --- a/libavcodec/smacker.c +++ b/libavcodec/smacker.c @@ -393,11 +393,13 @@ static int decode_frame(AVCodecContext *avctx, AVFrame *rframe, bytestream2_init(&gb2, avpkt->data, avpkt->size); flags = bytestream2_get_byteu(&gb2); smk->pic->palette_has_changed = flags & 1; - smk->pic->key_frame = !!(flags & 2); - if (smk->pic->key_frame) + if (flags & 2) { + smk->pic->flags |= AV_FRAME_FLAG_KEY; smk->pic->pict_type = AV_PICTURE_TYPE_I; - else + } else { + smk->pic->flags &= ~AV_FRAME_FLAG_KEY; smk->pic->pict_type = AV_PICTURE_TYPE_P; + } for(i = 0; i < 256; i++) *pal++ = 0xFFU << 24 | bytestream2_get_be24u(&gb2); diff --git a/libavcodec/snow.c b/libavcodec/snow.c index b6c8d5e2568..5eb3ee1e9e7 100644 --- a/libavcodec/snow.c +++ b/libavcodec/snow.c @@ -606,7 +606,7 @@ int ff_snow_frame_start(SnowContext *s){ }else{ int i; for(i=0; imax_ref_frames && s->last_picture[i]->data[0]; i++) - if(i && s->last_picture[i-1]->key_frame) + if(i && (s->last_picture[i-1]->flags & AV_FRAME_FLAG_KEY)) break; s->ref_frames= i; if(s->ref_frames==0){ @@ -617,7 +617,10 @@ int ff_snow_frame_start(SnowContext *s){ if ((ret = ff_snow_get_buffer(s, s->current_picture)) < 0) return ret; - s->current_picture->key_frame= s->keyframe; + if (s->keyframe) + s->current_picture->flags |= AV_FRAME_FLAG_KEY; + else + s->current_picture->flags &= ~AV_FRAME_FLAG_KEY; return 0; } diff --git a/libavcodec/snowenc.c b/libavcodec/snowenc.c index 31a48972a50..1360343aec1 100644 --- a/libavcodec/snowenc.c +++ b/libavcodec/snowenc.c @@ -1763,7 +1763,7 @@ static int encode_frame(AVCodecContext *avctx, AVPacket *pkt, ff_build_rac_states(c, (1LL<<32)/20, 256-8); pic->pict_type= AV_PICTURE_TYPE_I; s->keyframe=1; - s->current_picture->key_frame=1; + s->current_picture->flags |= AV_FRAME_FLAG_KEY; goto redo_frame; } @@ -1891,7 +1891,7 @@ static int encode_frame(AVCodecContext *avctx, AVPacket *pkt, } pkt->size = ff_rac_terminate(c, 0); - if (s->current_picture->key_frame) + if (s->current_picture->flags & AV_FRAME_FLAG_KEY) pkt->flags |= AV_PKT_FLAG_KEY; *got_packet = 1; diff --git a/libavcodec/speedhqdec.c b/libavcodec/speedhqdec.c index e1e6f9a5f54..ff106009a97 100644 --- a/libavcodec/speedhqdec.c +++ b/libavcodec/speedhqdec.c @@ -436,7 +436,7 @@ static int speedhq_decode_frame(AVCodecContext *avctx, AVFrame *frame, if ((ret = ff_get_buffer(avctx, frame, 0)) < 0) { return ret; } - frame->key_frame = 1; + frame->flags |= AV_FRAME_FLAG_KEY; if (second_field_offset == 4 || second_field_offset == (buf_size-4)) { /* diff --git a/libavcodec/svq3.c b/libavcodec/svq3.c index df514030b97..2d03dbc457b 100644 --- a/libavcodec/svq3.c +++ b/libavcodec/svq3.c @@ -1408,7 +1408,10 @@ static int svq3_decode_frame(AVCodecContext *avctx, AVFrame *rframe, /* for skipping the frame */ s->cur_pic->f->pict_type = s->pict_type; - s->cur_pic->f->key_frame = (s->pict_type == AV_PICTURE_TYPE_I); + if (s->pict_type == AV_PICTURE_TYPE_I) + s->cur_pic->f->flags |= AV_FRAME_FLAG_KEY; + else + s->cur_pic->f->flags &= ~AV_FRAME_FLAG_KEY; ret = get_buffer(avctx, s->cur_pic); if (ret < 0) diff --git a/libavcodec/targa_y216dec.c b/libavcodec/targa_y216dec.c index d5234c16ae9..2874a51aaed 100644 --- a/libavcodec/targa_y216dec.c +++ b/libavcodec/targa_y216dec.c @@ -47,7 +47,7 @@ static int y216_decode_frame(AVCodecContext *avctx, AVFrame *pic, if ((ret = ff_get_buffer(avctx, pic, 0)) < 0) return ret; - pic->key_frame = 1; + pic->flags |= AV_FRAME_FLAG_KEY; pic->pict_type = AV_PICTURE_TYPE_I; y = (uint16_t *)pic->data[0]; diff --git a/libavcodec/tdsc.c b/libavcodec/tdsc.c index b5ab2e171ba..739738d9b12 100644 --- a/libavcodec/tdsc.c +++ b/libavcodec/tdsc.c @@ -612,7 +612,7 @@ static int tdsc_decode_frame(AVCodecContext *avctx, AVFrame *frame, /* Frame is ready to be output */ if (keyframe) { frame->pict_type = AV_PICTURE_TYPE_I; - frame->key_frame = 1; + frame->flags |= AV_FRAME_FLAG_KEY; } else { frame->pict_type = AV_PICTURE_TYPE_P; } diff --git a/libavcodec/tiff.c b/libavcodec/tiff.c index 1a1879de890..560cb3e5b33 100644 --- a/libavcodec/tiff.c +++ b/libavcodec/tiff.c @@ -1036,7 +1036,7 @@ static int dng_decode_tiles(AVCodecContext *avctx, AVFrame *frame, /* Frame is ready to be output */ frame->pict_type = AV_PICTURE_TYPE_I; - frame->key_frame = 1; + frame->flags |= AV_FRAME_FLAG_KEY; return avpkt->size; } @@ -2379,6 +2379,7 @@ static int decode_frame(AVCodecContext *avctx, AVFrame *p, } } + p->flags |= AV_FRAME_FLAG_KEY; *got_frame = 1; return avpkt->size; diff --git a/libavcodec/tmv.c b/libavcodec/tmv.c index cdb83452e50..582b6ddd024 100644 --- a/libavcodec/tmv.c +++ b/libavcodec/tmv.c @@ -57,7 +57,7 @@ static int tmv_decode_frame(AVCodecContext *avctx, AVFrame *frame, } frame->pict_type = AV_PICTURE_TYPE_I; - frame->key_frame = 1; + frame->flags |= AV_FRAME_FLAG_KEY; dst = frame->data[0]; frame->palette_has_changed = 1; diff --git a/libavcodec/truemotion2.c b/libavcodec/truemotion2.c index b168b9cda14..73c93359dac 100644 --- a/libavcodec/truemotion2.c +++ b/libavcodec/truemotion2.c @@ -930,11 +930,13 @@ static int decode_frame(AVCodecContext *avctx, AVFrame *rframe, } offset += t; } - p->key_frame = tm2_decode_blocks(l, p); - if (p->key_frame) + if (tm2_decode_blocks(l, p)) { + p->flags |= AV_FRAME_FLAG_KEY; p->pict_type = AV_PICTURE_TYPE_I; - else + } else { + p->flags &= ~AV_FRAME_FLAG_KEY; p->pict_type = AV_PICTURE_TYPE_P; + } l->cur = !l->cur; *got_frame = 1; diff --git a/libavcodec/truemotion2rt.c b/libavcodec/truemotion2rt.c index c6015b278a8..4f8590fc82c 100644 --- a/libavcodec/truemotion2rt.c +++ b/libavcodec/truemotion2rt.c @@ -202,7 +202,7 @@ static int truemotion2rt_decode_frame(AVCodecContext *avctx, AVFrame *p, } p->pict_type = AV_PICTURE_TYPE_I; - p->key_frame = 1; + p->flags |= AV_FRAME_FLAG_KEY; *got_frame = 1; return avpkt->size; diff --git a/libavcodec/utvideodec.c b/libavcodec/utvideodec.c index c7ef725e5ec..1f00c58950a 100644 --- a/libavcodec/utvideodec.c +++ b/libavcodec/utvideodec.c @@ -869,7 +869,7 @@ static int decode_frame(AVCodecContext *avctx, AVFrame *frame, break; } - frame->key_frame = 1; + frame->flags |= AV_FRAME_FLAG_KEY; frame->pict_type = AV_PICTURE_TYPE_I; if (c->interlaced) frame->flags |= AV_FRAME_FLAG_INTERLACED; diff --git a/libavcodec/v210dec.c b/libavcodec/v210dec.c index 26c9841d837..814d65bbda0 100644 --- a/libavcodec/v210dec.c +++ b/libavcodec/v210dec.c @@ -187,7 +187,7 @@ static int decode_frame(AVCodecContext *avctx, AVFrame *pic, return ret; pic->pict_type = AV_PICTURE_TYPE_I; - pic->key_frame = 1; + pic->flags |= AV_FRAME_FLAG_KEY; if (stride) { td.stride = stride; diff --git a/libavcodec/v210x.c b/libavcodec/v210x.c index 96594e2a43c..55630fa2fb9 100644 --- a/libavcodec/v210x.c +++ b/libavcodec/v210x.c @@ -62,7 +62,7 @@ static int decode_frame(AVCodecContext *avctx, AVFrame *pic, vdst = (uint16_t *)pic->data[2]; yend = ydst + width; pic->pict_type = AV_PICTURE_TYPE_I; - pic->key_frame = 1; + pic->flags |= AV_FRAME_FLAG_KEY; for (;;) { uint32_t v = av_be2ne32(*src++); diff --git a/libavcodec/v308dec.c b/libavcodec/v308dec.c index a81771fc5f4..4bc4ea4e21a 100644 --- a/libavcodec/v308dec.c +++ b/libavcodec/v308dec.c @@ -48,7 +48,7 @@ static int v308_decode_frame(AVCodecContext *avctx, AVFrame *pic, if ((ret = ff_get_buffer(avctx, pic, 0)) < 0) return ret; - pic->key_frame = 1; + pic->flags |= AV_FRAME_FLAG_KEY; pic->pict_type = AV_PICTURE_TYPE_I; y = pic->data[0]; diff --git a/libavcodec/v408dec.c b/libavcodec/v408dec.c index edc9976d94f..191c050fb24 100644 --- a/libavcodec/v408dec.c +++ b/libavcodec/v408dec.c @@ -51,7 +51,7 @@ static int v408_decode_frame(AVCodecContext *avctx, AVFrame *pic, if ((ret = ff_get_buffer(avctx, pic, 0)) < 0) return ret; - pic->key_frame = 1; + pic->flags |= AV_FRAME_FLAG_KEY; pic->pict_type = AV_PICTURE_TYPE_I; y = pic->data[0]; diff --git a/libavcodec/v410dec.c b/libavcodec/v410dec.c index fb859e8cca8..35e4a8ae032 100644 --- a/libavcodec/v410dec.c +++ b/libavcodec/v410dec.c @@ -102,7 +102,7 @@ static int v410_decode_frame(AVCodecContext *avctx, AVFrame *pic, if ((ret = ff_thread_get_buffer(avctx, pic, 0)) < 0) return ret; - pic->key_frame = 1; + pic->flags |= AV_FRAME_FLAG_KEY; pic->pict_type = AV_PICTURE_TYPE_I; td.buf = src; diff --git a/libavcodec/v4l2_buffers.c b/libavcodec/v4l2_buffers.c index 3f5471067a1..22771356998 100644 --- a/libavcodec/v4l2_buffers.c +++ b/libavcodec/v4l2_buffers.c @@ -427,7 +427,8 @@ int ff_v4l2_buffer_buf_to_avframe(AVFrame *frame, V4L2Buffer *avbuf) return ret; /* 2. get frame information */ - frame->key_frame = !!(avbuf->buf.flags & V4L2_BUF_FLAG_KEYFRAME); + if (avbuf->buf.flags & V4L2_BUF_FLAG_KEYFRAME) + frame->flags |= AV_FRAME_FLAG_KEY; frame->color_primaries = v4l2_get_color_primaries(avbuf); frame->colorspace = v4l2_get_color_space(avbuf); frame->color_range = v4l2_get_color_range(avbuf); diff --git a/libavcodec/vble.c b/libavcodec/vble.c index 9307b0d165c..7711bf1bb10 100644 --- a/libavcodec/vble.c +++ b/libavcodec/vble.c @@ -135,7 +135,7 @@ static int vble_decode_frame(AVCodecContext *avctx, AVFrame *pic, return ret; /* Set flags */ - pic->key_frame = 1; + pic->flags |= AV_FRAME_FLAG_KEY; pic->pict_type = AV_PICTURE_TYPE_I; /* Version should always be 1 */ diff --git a/libavcodec/vbndec.c b/libavcodec/vbndec.c index d92dcd46b92..02ed43f874f 100644 --- a/libavcodec/vbndec.c +++ b/libavcodec/vbndec.c @@ -151,7 +151,7 @@ static int vbn_decode_frame(AVCodecContext *avctx, goto out; frame->pict_type = AV_PICTURE_TYPE_I; - frame->key_frame = 1; + frame->flags |= AV_FRAME_FLAG_KEY; if (format == VBN_FORMAT_RAW) { uint8_t *flipped = frame->data[0] + frame->linesize[0] * (frame->height - 1); diff --git a/libavcodec/vc1dec.c b/libavcodec/vc1dec.c index a103a734453..8298cefbc76 100644 --- a/libavcodec/vc1dec.c +++ b/libavcodec/vc1dec.c @@ -1060,7 +1060,10 @@ static int vc1_decode_frame(AVCodecContext *avctx, AVFrame *pict, // for skipping the frame s->current_picture.f->pict_type = s->pict_type; - s->current_picture.f->key_frame = s->pict_type == AV_PICTURE_TYPE_I; + if (s->pict_type == AV_PICTURE_TYPE_I) + s->current_picture.f->flags |= AV_FRAME_FLAG_KEY; + else + s->current_picture.f->flags &= ~AV_FRAME_FLAG_KEY; /* skip B-frames if we don't have reference frames */ if (!s->last_picture_ptr && s->pict_type == AV_PICTURE_TYPE_B) { diff --git a/libavcodec/vcr1.c b/libavcodec/vcr1.c index 853d4459a80..771337e2624 100644 --- a/libavcodec/vcr1.c +++ b/libavcodec/vcr1.c @@ -63,7 +63,7 @@ static int vcr1_decode_frame(AVCodecContext *avctx, AVFrame *p, if ((ret = ff_get_buffer(avctx, p, 0)) < 0) return ret; p->pict_type = AV_PICTURE_TYPE_I; - p->key_frame = 1; + p->flags |= AV_FRAME_FLAG_KEY; for (i = 0; i < 16; i++) { a->delta[i] = *bytestream++; diff --git a/libavcodec/vmnc.c b/libavcodec/vmnc.c index 8daaf08c5d3..17e3a2f3c18 100644 --- a/libavcodec/vmnc.c +++ b/libavcodec/vmnc.c @@ -339,7 +339,7 @@ static int decode_frame(AVCodecContext *avctx, AVFrame *rframe, if ((ret = ff_reget_buffer(avctx, c->pic, 0)) < 0) return ret; - c->pic->key_frame = 0; + c->pic->flags &= ~AV_FRAME_FLAG_KEY; c->pic->pict_type = AV_PICTURE_TYPE_P; // restore screen after cursor @@ -441,7 +441,7 @@ static int decode_frame(AVCodecContext *avctx, AVFrame *rframe, bytestream2_skip(gb, 4); break; case MAGIC_WMVi: // ServerInitialization struct - c->pic->key_frame = 1; + c->pic->flags |= AV_FRAME_FLAG_KEY; c->pic->pict_type = AV_PICTURE_TYPE_I; depth = bytestream2_get_byte(gb); if (depth != c->bpp) { diff --git a/libavcodec/vp3.c b/libavcodec/vp3.c index 22348559461..9e097c8905d 100644 --- a/libavcodec/vp3.c +++ b/libavcodec/vp3.c @@ -2677,7 +2677,10 @@ static int vp3_decode_frame(AVCodecContext *avctx, AVFrame *frame, s->current_frame.f->pict_type = s->keyframe ? AV_PICTURE_TYPE_I : AV_PICTURE_TYPE_P; - s->current_frame.f->key_frame = s->keyframe; + if (s->keyframe) + s->current_frame.f->flags |= AV_FRAME_FLAG_KEY; + else + s->current_frame.f->flags &= ~AV_FRAME_FLAG_KEY; if ((ret = ff_thread_get_ext_buffer(avctx, &s->current_frame, AV_GET_BUFFER_FLAG_REF)) < 0) goto error; diff --git a/libavcodec/vp5.c b/libavcodec/vp5.c index 579333506af..78d4b38ce3e 100644 --- a/libavcodec/vp5.c +++ b/libavcodec/vp5.c @@ -44,10 +44,13 @@ static int vp5_parse_header(VP56Context *s, const uint8_t *buf, int buf_size) ret = ff_vpx_init_range_decoder(&s->c, buf, buf_size); if (ret < 0) return ret; - s->frames[VP56_FRAME_CURRENT]->key_frame = !vpx_rac_get(c); + if (!vpx_rac_get(c)) + s->frames[VP56_FRAME_CURRENT]->flags |= AV_FRAME_FLAG_KEY; + else + s->frames[VP56_FRAME_CURRENT]->flags &= ~AV_FRAME_FLAG_KEY; vpx_rac_get(c); ff_vp56_init_dequant(s, vp56_rac_gets(c, 6)); - if (s->frames[VP56_FRAME_CURRENT]->key_frame) + if (s->frames[VP56_FRAME_CURRENT]->flags & AV_FRAME_FLAG_KEY) { int render_x, render_y; @@ -148,7 +151,7 @@ static int vp5_parse_coeff_models(VP56Context *s) if (vpx_rac_get_prob_branchy(c, vp5_dccv_pct[pt][node])) { def_prob[node] = vp56_rac_gets_nn(c, 7); model->coeff_dccv[pt][node] = def_prob[node]; - } else if (s->frames[VP56_FRAME_CURRENT]->key_frame) { + } else if (s->frames[VP56_FRAME_CURRENT]->flags & AV_FRAME_FLAG_KEY) { model->coeff_dccv[pt][node] = def_prob[node]; } @@ -159,7 +162,7 @@ static int vp5_parse_coeff_models(VP56Context *s) if (vpx_rac_get_prob_branchy(c, vp5_ract_pct[ct][pt][cg][node])) { def_prob[node] = vp56_rac_gets_nn(c, 7); model->coeff_ract[pt][ct][cg][node] = def_prob[node]; - } else if (s->frames[VP56_FRAME_CURRENT]->key_frame) { + } else if (s->frames[VP56_FRAME_CURRENT]->flags & AV_FRAME_FLAG_KEY) { model->coeff_ract[pt][ct][cg][node] = def_prob[node]; } diff --git a/libavcodec/vp56.c b/libavcodec/vp56.c index bd994428a42..a5c5b23622a 100644 --- a/libavcodec/vp56.c +++ b/libavcodec/vp56.c @@ -350,7 +350,7 @@ static void vp56_mc(VP56Context *s, int b, int plane, uint8_t *src, if (s->avctx->skip_loop_filter >= AVDISCARD_ALL || (s->avctx->skip_loop_filter >= AVDISCARD_NONKEY - && !s->frames[VP56_FRAME_CURRENT]->key_frame)) + && !(s->frames[VP56_FRAME_CURRENT]->flags & AV_FRAME_FLAG_KEY))) deblock_filtering = 0; dx = s->mv[b].x / s->vp56_coord_div[b]; @@ -493,7 +493,7 @@ static int vp56_decode_mb(VP56Context *s, int row, int col, int is_alpha) VP56mb mb_type; int ret; - if (s->frames[VP56_FRAME_CURRENT]->key_frame) + if (s->frames[VP56_FRAME_CURRENT]->flags & AV_FRAME_FLAG_KEY) mb_type = VP56_MB_INTRA; else mb_type = vp56_decode_mv(s, row, col); @@ -511,7 +511,7 @@ static int vp56_conceal_mb(VP56Context *s, int row, int col, int is_alpha) { VP56mb mb_type; - if (s->frames[VP56_FRAME_CURRENT]->key_frame) + if (s->frames[VP56_FRAME_CURRENT]->flags & AV_FRAME_FLAG_KEY) mb_type = VP56_MB_INTRA; else mb_type = vp56_conceal_mv(s, row, col); @@ -596,6 +596,7 @@ int ff_vp56_decode_frame(AVCodecContext *avctx, AVFrame *rframe, if (s->alpha_context) av_frame_unref(s->alpha_context->frames[i]); } + s->frames[VP56_FRAME_CURRENT]->flags |= AV_FRAME_FLAG_KEY; //FIXME } ret = ff_get_buffer(avctx, p, AV_GET_BUFFER_FLAG_REF); @@ -670,7 +671,7 @@ static int ff_vp56_decode_mbs(AVCodecContext *avctx, void *data, int res; int damaged = 0; - if (p->key_frame) { + if (p->flags & AV_FRAME_FLAG_KEY) { p->pict_type = AV_PICTURE_TYPE_I; s->default_models_init(s); for (block=0; blockmb_height*s->mb_width; block++) @@ -762,7 +763,7 @@ static int ff_vp56_decode_mbs(AVCodecContext *avctx, void *data, s->have_undamaged_frame = 1; next: - if (p->key_frame || s->golden_frame) { + if ((p->flags & AV_FRAME_FLAG_KEY) || s->golden_frame) { av_frame_unref(s->frames[VP56_FRAME_GOLDEN]); if ((res = av_frame_ref(s->frames[VP56_FRAME_GOLDEN], p)) < 0) return res; diff --git a/libavcodec/vp6.c b/libavcodec/vp6.c index 9bbfa0eb5d7..7a519cf10dd 100644 --- a/libavcodec/vp6.c +++ b/libavcodec/vp6.c @@ -57,10 +57,13 @@ static int vp6_parse_header(VP56Context *s, const uint8_t *buf, int buf_size) int ret; int separated_coeff = buf[0] & 1; - s->frames[VP56_FRAME_CURRENT]->key_frame = !(buf[0] & 0x80); + if (!(buf[0] & 0x80)) + s->frames[VP56_FRAME_CURRENT]->flags |= AV_FRAME_FLAG_KEY; + else + s->frames[VP56_FRAME_CURRENT]->flags &= ~AV_FRAME_FLAG_KEY; ff_vp56_init_dequant(s, (buf[0] >> 1) & 0x3F); - if (s->frames[VP56_FRAME_CURRENT]->key_frame) { + if (s->frames[VP56_FRAME_CURRENT]->flags & AV_FRAME_FLAG_KEY) { sub_version = buf[1] >> 3; if (sub_version > 8) return AVERROR_INVALIDDATA; @@ -299,7 +302,7 @@ static int vp6_parse_coeff_models(VP56Context *s) if (vpx_rac_get_prob_branchy(c, vp6_dccv_pct[pt][node])) { def_prob[node] = vp56_rac_gets_nn(c, 7); model->coeff_dccv[pt][node] = def_prob[node]; - } else if (s->frames[VP56_FRAME_CURRENT]->key_frame) { + } else if (s->frames[VP56_FRAME_CURRENT]->flags & AV_FRAME_FLAG_KEY) { model->coeff_dccv[pt][node] = def_prob[node]; } @@ -322,7 +325,7 @@ static int vp6_parse_coeff_models(VP56Context *s) if (vpx_rac_get_prob_branchy(c, vp6_ract_pct[ct][pt][cg][node])) { def_prob[node] = vp56_rac_gets_nn(c, 7); model->coeff_ract[pt][ct][cg][node] = def_prob[node]; - } else if (s->frames[VP56_FRAME_CURRENT]->key_frame) { + } else if (s->frames[VP56_FRAME_CURRENT]->flags & AV_FRAME_FLAG_KEY) { model->coeff_ract[pt][ct][cg][node] = def_prob[node]; } diff --git a/libavcodec/vp8.c b/libavcodec/vp8.c index db2419deaf7..2ab06c82939 100644 --- a/libavcodec/vp8.c +++ b/libavcodec/vp8.c @@ -2732,7 +2732,10 @@ int vp78_decode_frame(AVCodecContext *avctx, AVFrame *rframe, int *got_frame, goto err; } - curframe->tf.f->key_frame = s->keyframe; + if (s->keyframe) + curframe->tf.f->flags |= AV_FRAME_FLAG_KEY; + else + curframe->tf.f->flags &= ~AV_FRAME_FLAG_KEY; curframe->tf.f->pict_type = s->keyframe ? AV_PICTURE_TYPE_I : AV_PICTURE_TYPE_P; if ((ret = vp8_alloc_frame(s, curframe, referenced)) < 0) diff --git a/libavcodec/vp9.c b/libavcodec/vp9.c index 7ff387faf48..d8a31507fa5 100644 --- a/libavcodec/vp9.c +++ b/libavcodec/vp9.c @@ -1613,7 +1613,10 @@ static int vp9_decode_frame(AVCodecContext *avctx, AVFrame *frame, if ((ret = vp9_frame_alloc(avctx, &s->s.frames[CUR_FRAME])) < 0) return ret; f = s->s.frames[CUR_FRAME].tf.f; - f->key_frame = s->s.h.keyframe; + if (s->s.h.keyframe) + f->flags |= AV_FRAME_FLAG_KEY; + else + f->flags &= ~AV_FRAME_FLAG_KEY; f->pict_type = (s->s.h.keyframe || s->s.h.intraonly) ? AV_PICTURE_TYPE_I : AV_PICTURE_TYPE_P; if (s->s.frames[REF_FRAME_SEGMAP].tf.f->buf[0] && diff --git a/libavcodec/wbmpdec.c b/libavcodec/wbmpdec.c index 8b105bc1352..3b5753abcd0 100644 --- a/libavcodec/wbmpdec.c +++ b/libavcodec/wbmpdec.c @@ -74,7 +74,7 @@ static int wbmp_decode_frame(AVCodecContext *avctx, AVFrame *p, else readbits(p->data[0], width, height, p->linesize[0], gb.buffer, gb.buffer_end - gb.buffer); - p->key_frame = 1; + p->flags |= AV_FRAME_FLAG_KEY; p->pict_type = AV_PICTURE_TYPE_I; *got_frame = 1; diff --git a/libavcodec/wcmv.c b/libavcodec/wcmv.c index 097ac8b8e9a..b2413ee9c0e 100644 --- a/libavcodec/wcmv.c +++ b/libavcodec/wcmv.c @@ -195,7 +195,10 @@ static int decode_frame(AVCodecContext *avctx, AVFrame *frame, } } - s->prev_frame->key_frame = intra; + if (intra) + s->prev_frame->flags |= AV_FRAME_FLAG_KEY; + else + s->prev_frame->flags &= ~AV_FRAME_FLAG_KEY; s->prev_frame->pict_type = intra ? AV_PICTURE_TYPE_I : AV_PICTURE_TYPE_P; if ((ret = av_frame_ref(frame, s->prev_frame)) < 0) diff --git a/libavcodec/webp.c b/libavcodec/webp.c index b4357f95d57..d35cb66f8d4 100644 --- a/libavcodec/webp.c +++ b/libavcodec/webp.c @@ -1186,7 +1186,7 @@ static int vp8_lossless_decode_frame(AVCodecContext *avctx, AVFrame *p, *got_frame = 1; p->pict_type = AV_PICTURE_TYPE_I; - p->key_frame = 1; + p->flags |= AV_FRAME_FLAG_KEY; ret = data_size; free_and_return: diff --git a/libavcodec/wnv1.c b/libavcodec/wnv1.c index 88532ee4266..5c57db00548 100644 --- a/libavcodec/wnv1.c +++ b/libavcodec/wnv1.c @@ -69,7 +69,7 @@ static int decode_frame(AVCodecContext *avctx, AVFrame *p, if ((ret = ff_get_buffer(avctx, p, 0)) < 0) return ret; - p->key_frame = 1; + p->flags |= AV_FRAME_FLAG_KEY; if ((ret = init_get_bits8(&gb, buf + 8, buf_size - 8)) < 0) return ret; diff --git a/libavcodec/xbmdec.c b/libavcodec/xbmdec.c index a0cc1cb8c61..ecfc957a3f6 100644 --- a/libavcodec/xbmdec.c +++ b/libavcodec/xbmdec.c @@ -130,7 +130,7 @@ static int xbm_decode_frame(AVCodecContext *avctx, AVFrame *p, } } - p->key_frame = 1; + p->flags |= AV_FRAME_FLAG_KEY; p->pict_type = AV_PICTURE_TYPE_I; *got_frame = 1; diff --git a/libavcodec/xl.c b/libavcodec/xl.c index 283cd39aa74..f008d56e896 100644 --- a/libavcodec/xl.c +++ b/libavcodec/xl.c @@ -60,7 +60,7 @@ static int decode_frame(AVCodecContext *avctx, AVFrame *p, if ((ret = ff_get_buffer(avctx, p, 0)) < 0) return ret; p->pict_type = AV_PICTURE_TYPE_I; - p->key_frame = 1; + p->flags |= AV_FRAME_FLAG_KEY; Y = p->data[0]; U = p->data[1]; diff --git a/libavcodec/xpmdec.c b/libavcodec/xpmdec.c index 2550afb9d68..5bc02378c80 100644 --- a/libavcodec/xpmdec.c +++ b/libavcodec/xpmdec.c @@ -422,7 +422,7 @@ static int xpm_decode_frame(AVCodecContext *avctx, AVFrame *p, ptr += mod_strcspn(ptr, ",") + 1; } - p->key_frame = 1; + p->flags |= AV_FRAME_FLAG_KEY; p->pict_type = AV_PICTURE_TYPE_I; *got_frame = 1; diff --git a/libavcodec/xwddec.c b/libavcodec/xwddec.c index 6c5bc44a029..f691587be90 100644 --- a/libavcodec/xwddec.c +++ b/libavcodec/xwddec.c @@ -216,7 +216,7 @@ static int xwd_decode_frame(AVCodecContext *avctx, AVFrame *p, if ((ret = ff_get_buffer(avctx, p, 0)) < 0) return ret; - p->key_frame = 1; + p->flags |= AV_FRAME_FLAG_KEY; p->pict_type = AV_PICTURE_TYPE_I; if (avctx->pix_fmt == AV_PIX_FMT_PAL8) { diff --git a/libavcodec/y41pdec.c b/libavcodec/y41pdec.c index b461f349ad2..14e36dc9985 100644 --- a/libavcodec/y41pdec.c +++ b/libavcodec/y41pdec.c @@ -51,7 +51,7 @@ static int y41p_decode_frame(AVCodecContext *avctx, AVFrame *pic, if ((ret = ff_get_buffer(avctx, pic, 0)) < 0) return ret; - pic->key_frame = 1; + pic->flags |= AV_FRAME_FLAG_KEY; pic->pict_type = AV_PICTURE_TYPE_I; for (i = avctx->height - 1; i >= 0 ; i--) { diff --git a/libavcodec/ylc.c b/libavcodec/ylc.c index 29c10f05da0..c0c4d27c09f 100644 --- a/libavcodec/ylc.c +++ b/libavcodec/ylc.c @@ -427,7 +427,7 @@ static int decode_frame(AVCodecContext *avctx, AVFrame *p, } p->pict_type = AV_PICTURE_TYPE_I; - p->key_frame = 1; + p->flags |= AV_FRAME_FLAG_KEY; *got_frame = 1; return avpkt->size; diff --git a/libavcodec/yuv4dec.c b/libavcodec/yuv4dec.c index 15424b1940b..ad83a2125c0 100644 --- a/libavcodec/yuv4dec.c +++ b/libavcodec/yuv4dec.c @@ -46,7 +46,7 @@ static int yuv4_decode_frame(AVCodecContext *avctx, AVFrame *pic, if ((ret = ff_get_buffer(avctx, pic, 0)) < 0) return ret; - pic->key_frame = 1; + pic->flags |= AV_FRAME_FLAG_KEY; pic->pict_type = AV_PICTURE_TYPE_I; y = pic->data[0]; diff --git a/libavcodec/zerocodec.c b/libavcodec/zerocodec.c index 42fb24ff6c5..6c3bcebce04 100644 --- a/libavcodec/zerocodec.c +++ b/libavcodec/zerocodec.c @@ -40,7 +40,7 @@ static int zerocodec_decode_frame(AVCodecContext *avctx, AVFrame *pic, int i, j, zret, ret; if (avpkt->flags & AV_PKT_FLAG_KEY) { - pic->key_frame = 1; + pic->flags |= AV_FRAME_FLAG_KEY; pic->pict_type = AV_PICTURE_TYPE_I; } else { if (!prev) { @@ -50,7 +50,7 @@ static int zerocodec_decode_frame(AVCodecContext *avctx, AVFrame *pic, prev += (avctx->height - 1) * prev_pic->linesize[0]; - pic->key_frame = 0; + pic->flags &= ~AV_FRAME_FLAG_KEY; pic->pict_type = AV_PICTURE_TYPE_P; } diff --git a/libavcodec/zmbv.c b/libavcodec/zmbv.c index 0b44851811f..d309a8612b4 100644 --- a/libavcodec/zmbv.c +++ b/libavcodec/zmbv.c @@ -559,11 +559,11 @@ static int decode_frame(AVCodecContext *avctx, AVFrame *frame, return ret; if (c->flags & ZMBV_KEYFRAME) { - frame->key_frame = 1; + frame->flags |= AV_FRAME_FLAG_KEY; frame->pict_type = AV_PICTURE_TYPE_I; zmbv_decode_intra(c); } else { - frame->key_frame = 0; + frame->flags &= ~AV_FRAME_FLAG_KEY; frame->pict_type = AV_PICTURE_TYPE_P; if (c->decomp_len < 2LL * ((c->width + c->bw - 1) / c->bw) * ((c->height + c->bh - 1) / c->bh)) return AVERROR_INVALIDDATA; From af8db9106c27a1ef11ec69ecbbe7a57462c14367 Mon Sep 17 00:00:00 2001 From: James Almer Date: Wed, 12 Apr 2023 19:35:56 -0300 Subject: [PATCH 0880/2172] avfilter: use the new AVFrame key_frame flag in all filters Signed-off-by: James Almer --- libavfilter/avfilter.c | 2 +- libavfilter/buffersrc.c | 3 +++ libavfilter/f_select.c | 4 ++-- libavfilter/vf_blackframe.c | 2 +- libavfilter/vf_coreimage.m | 1 + libavfilter/vf_showinfo.c | 2 +- libavfilter/vsrc_gradients.c | 1 + libavfilter/vsrc_testsrc.c | 1 + 8 files changed, 11 insertions(+), 5 deletions(-) diff --git a/libavfilter/avfilter.c b/libavfilter/avfilter.c index 889808c5805..0141b64cbcf 100644 --- a/libavfilter/avfilter.c +++ b/libavfilter/avfilter.c @@ -59,7 +59,7 @@ static void tlog_ref(void *ctx, AVFrame *ref, int end) ref->width, ref->height, !(ref->flags & AV_FRAME_FLAG_INTERLACED) ? 'P' : /* Progressive */ (ref->flags & AV_FRAME_FLAG_TOP_FIELD_FIRST) ? 'T' : 'B', /* Top / Bottom */ - ref->key_frame, + !!(ref->flags & AV_FRAME_FLAG_KEY), av_get_picture_type_char(ref->pict_type)); } if (ref->nb_samples) { diff --git a/libavfilter/buffersrc.c b/libavfilter/buffersrc.c index 1d2f357bbc7..8d5a08995b0 100644 --- a/libavfilter/buffersrc.c +++ b/libavfilter/buffersrc.c @@ -256,6 +256,9 @@ FF_DISABLE_DEPRECATION_WARNINGS FF_ENABLE_DEPRECATION_WARNINGS #endif + if (copy->key_frame) + copy->flags |= AV_FRAME_FLAG_KEY; + ret = ff_filter_frame(ctx->outputs[0], copy); if (ret < 0) return ret; diff --git a/libavfilter/f_select.c b/libavfilter/f_select.c index 6eab92b32fa..49fcdc31ffe 100644 --- a/libavfilter/f_select.c +++ b/libavfilter/f_select.c @@ -346,7 +346,7 @@ FF_DISABLE_DEPRECATION_WARNINGS select->var_values[VAR_POS] = frame->pkt_pos == -1 ? NAN : frame->pkt_pos; FF_ENABLE_DEPRECATION_WARNINGS #endif - select->var_values[VAR_KEY] = frame->key_frame; + select->var_values[VAR_KEY] = !!(frame->flags & AV_FRAME_FLAG_KEY); select->var_values[VAR_CONCATDEC_SELECT] = get_concatdec_select(frame, av_rescale_q(frame->pts, inlink->time_base, AV_TIME_BASE_Q)); switch (inlink->type) { @@ -375,7 +375,7 @@ FF_ENABLE_DEPRECATION_WARNINGS select->var_values[VAR_N], select->var_values[VAR_PTS], select->var_values[VAR_T], - frame->key_frame); + !!(frame->flags & AV_FRAME_FLAG_KEY)); switch (inlink->type) { case AVMEDIA_TYPE_VIDEO: diff --git a/libavfilter/vf_blackframe.c b/libavfilter/vf_blackframe.c index e5e185dbea9..4bcec866887 100644 --- a/libavfilter/vf_blackframe.c +++ b/libavfilter/vf_blackframe.c @@ -72,7 +72,7 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *frame) p += frame->linesize[0]; } - if (frame->key_frame) + if (frame->flags & AV_FRAME_FLAG_KEY) s->last_keyframe = s->frame; pblack = s->nblack * 100 / (inlink->w * inlink->h); diff --git a/libavfilter/vf_coreimage.m b/libavfilter/vf_coreimage.m index a2e3dbea46c..aa0c90f5372 100644 --- a/libavfilter/vf_coreimage.m +++ b/libavfilter/vf_coreimage.m @@ -302,6 +302,7 @@ static int request_frame(AVFilterLink *link) frame->pts = ctx->pts; frame->duration = 1; frame->key_frame = 1; + frame->flags |= AV_FRAME_FLAG_KEY #if FF_API_INTERLACED_FRAME frame->interlaced_frame = 0; #endif diff --git a/libavfilter/vf_showinfo.c b/libavfilter/vf_showinfo.c index 6ecab2bf712..bf8580bc8d0 100644 --- a/libavfilter/vf_showinfo.c +++ b/libavfilter/vf_showinfo.c @@ -724,7 +724,7 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *frame) frame->width, frame->height, !(frame->flags & AV_FRAME_FLAG_INTERLACED) ? 'P' : /* Progressive */ (frame->flags & AV_FRAME_FLAG_TOP_FIELD_FIRST) ? 'T' : 'B', /* Top / Bottom */ - frame->key_frame, + !!(frame->flags & AV_FRAME_FLAG_KEY), av_get_picture_type_char(frame->pict_type)); if (s->calculate_checksums) { diff --git a/libavfilter/vsrc_gradients.c b/libavfilter/vsrc_gradients.c index f50b4d3cc70..bc2cfb024c6 100644 --- a/libavfilter/vsrc_gradients.c +++ b/libavfilter/vsrc_gradients.c @@ -398,6 +398,7 @@ static int activate(AVFilterContext *ctx) return AVERROR(ENOMEM); frame->key_frame = 1; + frame->flags |= AV_FRAME_FLAG_KEY; #if FF_API_INTERLACED_FRAME FF_DISABLE_DEPRECATION_WARNINGS frame->interlaced_frame = 0; diff --git a/libavfilter/vsrc_testsrc.c b/libavfilter/vsrc_testsrc.c index c358f9ada26..d4037c6da80 100644 --- a/libavfilter/vsrc_testsrc.c +++ b/libavfilter/vsrc_testsrc.c @@ -185,6 +185,7 @@ static int activate(AVFilterContext *ctx) frame->pts = test->pts; frame->duration = 1; frame->key_frame = 1; + frame->flags |= AV_FRAME_FLAG_KEY; #if FF_API_INTERLACED_FRAME FF_DISABLE_DEPRECATION_WARNINGS frame->interlaced_frame = 0; From c7a8681860d68f3ad00ef49215dbfda52c71c90b Mon Sep 17 00:00:00 2001 From: James Almer Date: Wed, 12 Apr 2023 19:54:10 -0300 Subject: [PATCH 0881/2172] fftools: use the new AVFrame keyframe flag Signed-off-by: James Almer --- fftools/ffmpeg.c | 2 +- fftools/ffmpeg_enc.c | 6 +++--- fftools/ffprobe.c | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/fftools/ffmpeg.c b/fftools/ffmpeg.c index 23aa343bbcb..8323c32ffd8 100644 --- a/fftools/ffmpeg.c +++ b/fftools/ffmpeg.c @@ -1143,7 +1143,7 @@ static int decode_video(InputStream *ist, const AVPacket *pkt, int *got_output, av_ts2timestr(best_effort_timestamp, &ist->st->time_base), av_ts2str(decoded_frame->duration), av_ts2timestr(decoded_frame->duration, &ist->st->time_base), - decoded_frame->key_frame, decoded_frame->pict_type, + !!(decoded_frame->flags & AV_FRAME_FLAG_KEY), decoded_frame->pict_type, ist->st->time_base.num, ist->st->time_base.den); } diff --git a/fftools/ffmpeg_enc.c b/fftools/ffmpeg_enc.c index f2af81baccb..53bf320afa9 100644 --- a/fftools/ffmpeg_enc.c +++ b/fftools/ffmpeg_enc.c @@ -1005,11 +1005,11 @@ static enum AVPictureType forced_kf_apply(void *logctx, KeyframeForceCtx *kf, goto force_keyframe; } } else if (kf->type == KF_FORCE_SOURCE && - in_picture->key_frame == 1 && !dup_idx) { + (in_picture->flags & AV_FRAME_FLAG_KEY) && !dup_idx) { goto force_keyframe; } else if (kf->type == KF_FORCE_SOURCE_NO_DROP && !dup_idx) { kf->dropped_keyframe = 0; - if ((in_picture->key_frame == 1) || kf->dropped_keyframe) + if ((in_picture->flags & AV_FRAME_FLAG_KEY) || kf->dropped_keyframe) goto force_keyframe; } @@ -1064,7 +1064,7 @@ static void do_video_out(OutputFile *of, OutputStream *ost, AVFrame *frame) } } ost->last_dropped = nb_frames == nb_frames_prev && frame; - ost->kf.dropped_keyframe = ost->last_dropped && frame && frame->key_frame; + ost->kf.dropped_keyframe = ost->last_dropped && frame && (frame->flags & AV_FRAME_FLAG_KEY); /* duplicates frame if needed */ for (i = 0; i < nb_frames; i++) { diff --git a/fftools/ffprobe.c b/fftools/ffprobe.c index 10492011d74..43bf10db544 100644 --- a/fftools/ffprobe.c +++ b/fftools/ffprobe.c @@ -2594,7 +2594,7 @@ static void show_frame(WriterContext *w, AVFrame *frame, AVStream *stream, if (s) print_str ("media_type", s); else print_str_opt("media_type", "unknown"); print_int("stream_index", stream->index); - print_int("key_frame", frame->key_frame); + print_int("key_frame", !!(frame->flags & AV_FRAME_FLAG_KEY)); print_ts ("pts", frame->pts); print_time("pts_time", frame->pts, &stream->time_base); print_ts ("pkt_dts", frame->pkt_dts); From 3e06f6f04020bef32fa42bc9d7f96e76a46453aa Mon Sep 17 00:00:00 2001 From: James Almer Date: Wed, 12 Apr 2023 20:07:01 -0300 Subject: [PATCH 0882/2172] avutil/frame: deprecate key_frame Signed-off-by: James Almer --- libavcodec/decode.c | 4 ++++ libavcodec/encode.c | 4 ++++ libavfilter/buffersrc.c | 4 ++++ libavfilter/vf_coreimage.m | 2 ++ libavfilter/vsrc_gradients.c | 5 +++++ libavfilter/vsrc_testsrc.c | 4 ++++ libavutil/frame.c | 5 ++++- libavutil/frame.h | 5 +++++ libavutil/version.h | 1 + 9 files changed, 33 insertions(+), 1 deletion(-) diff --git a/libavcodec/decode.c b/libavcodec/decode.c index a5a6209eaeb..4f2359f07ef 100644 --- a/libavcodec/decode.c +++ b/libavcodec/decode.c @@ -572,7 +572,11 @@ static int decode_receive_frame_internal(AVCodecContext *avctx, AVFrame *frame) if (!ret) { if (avctx->codec_type != AVMEDIA_TYPE_VIDEO) frame->flags |= AV_FRAME_FLAG_KEY; +#if FF_API_FRAME_KEY +FF_DISABLE_DEPRECATION_WARNINGS frame->key_frame = !!(frame->flags & AV_FRAME_FLAG_KEY); +FF_ENABLE_DEPRECATION_WARNINGS +#endif #if FF_API_INTERLACED_FRAME FF_DISABLE_DEPRECATION_WARNINGS frame->interlaced_frame = !!(frame->flags & AV_FRAME_FLAG_INTERLACED); diff --git a/libavcodec/encode.c b/libavcodec/encode.c index 04ee59879ec..14e28767425 100644 --- a/libavcodec/encode.c +++ b/libavcodec/encode.c @@ -192,8 +192,12 @@ int ff_encode_get_frame(AVCodecContext *avctx, AVFrame *frame) av_frame_move_ref(frame, avci->buffer_frame); +#if FF_API_FRAME_KEY +FF_DISABLE_DEPRECATION_WARNINGS if (frame->key_frame) frame->flags |= AV_FRAME_FLAG_KEY; +FF_ENABLE_DEPRECATION_WARNINGS +#endif #if FF_API_INTERLACED_FRAME FF_DISABLE_DEPRECATION_WARNINGS if (frame->interlaced_frame) diff --git a/libavfilter/buffersrc.c b/libavfilter/buffersrc.c index 8d5a08995b0..612541b8039 100644 --- a/libavfilter/buffersrc.c +++ b/libavfilter/buffersrc.c @@ -256,8 +256,12 @@ FF_DISABLE_DEPRECATION_WARNINGS FF_ENABLE_DEPRECATION_WARNINGS #endif +#if FF_API_FRAME_KEY +FF_DISABLE_DEPRECATION_WARNINGS if (copy->key_frame) copy->flags |= AV_FRAME_FLAG_KEY; +FF_ENABLE_DEPRECATION_WARNINGS +#endif ret = ff_filter_frame(ctx->outputs[0], copy); if (ret < 0) diff --git a/libavfilter/vf_coreimage.m b/libavfilter/vf_coreimage.m index aa0c90f5372..41750bfb7ec 100644 --- a/libavfilter/vf_coreimage.m +++ b/libavfilter/vf_coreimage.m @@ -301,7 +301,9 @@ static int request_frame(AVFilterLink *link) frame->pts = ctx->pts; frame->duration = 1; +#if FF_API_FRAME_KEY frame->key_frame = 1; +#endif frame->flags |= AV_FRAME_FLAG_KEY #if FF_API_INTERLACED_FRAME frame->interlaced_frame = 0; diff --git a/libavfilter/vsrc_gradients.c b/libavfilter/vsrc_gradients.c index bc2cfb024c6..98c38f85514 100644 --- a/libavfilter/vsrc_gradients.c +++ b/libavfilter/vsrc_gradients.c @@ -397,7 +397,12 @@ static int activate(AVFilterContext *ctx) if (!frame) return AVERROR(ENOMEM); +#if FF_API_FRAME_KEY +FF_DISABLE_DEPRECATION_WARNINGS frame->key_frame = 1; +FF_ENABLE_DEPRECATION_WARNINGS +#endif + frame->flags |= AV_FRAME_FLAG_KEY; #if FF_API_INTERLACED_FRAME FF_DISABLE_DEPRECATION_WARNINGS diff --git a/libavfilter/vsrc_testsrc.c b/libavfilter/vsrc_testsrc.c index d4037c6da80..f391ac02e05 100644 --- a/libavfilter/vsrc_testsrc.c +++ b/libavfilter/vsrc_testsrc.c @@ -184,7 +184,11 @@ static int activate(AVFilterContext *ctx) return AVERROR(ENOMEM); frame->pts = test->pts; frame->duration = 1; +#if FF_API_PKT_DURATION +FF_DISABLE_DEPRECATION_WARNINGS frame->key_frame = 1; +FF_ENABLE_DEPRECATION_WARNINGS +#endif frame->flags |= AV_FRAME_FLAG_KEY; #if FF_API_INTERLACED_FRAME FF_DISABLE_DEPRECATION_WARNINGS diff --git a/libavutil/frame.c b/libavutil/frame.c index e544b690fe7..97d40208c86 100644 --- a/libavutil/frame.c +++ b/libavutil/frame.c @@ -55,7 +55,6 @@ FF_DISABLE_DEPRECATION_WARNINGS FF_ENABLE_DEPRECATION_WARNINGS #endif frame->time_base = (AVRational){ 0, 1 }; - frame->key_frame = 1; frame->sample_aspect_ratio = (AVRational){ 0, 1 }; frame->format = -1; /* unknown */ frame->extended_data = frame->data; @@ -265,7 +264,11 @@ static int frame_copy_props(AVFrame *dst, const AVFrame *src, int force_copy) { int ret; +#if FF_API_FRAME_KEY +FF_DISABLE_DEPRECATION_WARNINGS dst->key_frame = src->key_frame; +FF_ENABLE_DEPRECATION_WARNINGS +#endif dst->pict_type = src->pict_type; dst->sample_aspect_ratio = src->sample_aspect_ratio; dst->crop_top = src->crop_top; diff --git a/libavutil/frame.h b/libavutil/frame.h index 61a218268e5..f2b56beebb6 100644 --- a/libavutil/frame.h +++ b/libavutil/frame.h @@ -416,10 +416,15 @@ typedef struct AVFrame { */ int format; +#if FF_API_FRAME_KEY /** * 1 -> keyframe, 0-> not + * + * @deprecated Use AV_FRAME_FLAG_KEY instead */ + attribute_deprecated int key_frame; +#endif /** * Picture type of the frame. diff --git a/libavutil/version.h b/libavutil/version.h index 6a5e2c48818..3a4b9ca77c9 100644 --- a/libavutil/version.h +++ b/libavutil/version.h @@ -116,6 +116,7 @@ #define FF_API_HDR_VIVID_THREE_SPLINE (LIBAVUTIL_VERSION_MAJOR < 59) #define FF_API_FRAME_PKT (LIBAVUTIL_VERSION_MAJOR < 59) #define FF_API_INTERLACED_FRAME (LIBAVUTIL_VERSION_MAJOR < 59) +#define FF_API_FRAME_KEY (LIBAVUTIL_VERSION_MAJOR < 59) /** * @} From 0fc9c1f6828126abc024d0e5b147fb1e21de5c50 Mon Sep 17 00:00:00 2001 From: James Almer Date: Thu, 4 May 2023 19:17:01 -0300 Subject: [PATCH 0883/2172] avutil/version: bump minor after recent changes Signed-off-by: James Almer --- doc/APIchanges | 6 ++++++ libavutil/version.h | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/doc/APIchanges b/doc/APIchanges index 0b609e3d3b2..fd01def1b27 100644 --- a/doc/APIchanges +++ b/doc/APIchanges @@ -2,6 +2,12 @@ The last version increases of all libraries were on 2023-02-09 API changes, most recent first: +2023-05-04 - xxxxxxxxxx - lavu 58.7.100 - frame.h + Deprecate AVFrame.interlaced_frame, AVFrame.top_field_first, and + AVFrame.key_frame. + Add AV_FRAME_FLAG_INTERLACED, AV_FRAME_FLAG_TOP_FIELD_FIRST, and + AV_FRAME_FLAG_KEY flags as replacement. + 2023-04-10 - xxxxxxxxxx - lavu 58.6.100 - frame.h av_frame_get_plane_buffer() now accepts const AVFrame*. diff --git a/libavutil/version.h b/libavutil/version.h index 3a4b9ca77c9..341bcbf1888 100644 --- a/libavutil/version.h +++ b/libavutil/version.h @@ -79,7 +79,7 @@ */ #define LIBAVUTIL_VERSION_MAJOR 58 -#define LIBAVUTIL_VERSION_MINOR 6 +#define LIBAVUTIL_VERSION_MINOR 7 #define LIBAVUTIL_VERSION_MICRO 100 #define LIBAVUTIL_VERSION_INT AV_VERSION_INT(LIBAVUTIL_VERSION_MAJOR, \ From 6febb2a5ffa12b443eed0b8709c17463ff684d37 Mon Sep 17 00:00:00 2001 From: James Almer Date: Thu, 4 May 2023 22:38:47 -0300 Subject: [PATCH 0884/2172] avfilter/vf_coreimage: add missing semicolon Fixes compilation after af8db9106c27a1ef11ec69ecbbe7a57462c14367. Signed-off-by: James Almer --- libavfilter/vf_coreimage.m | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavfilter/vf_coreimage.m b/libavfilter/vf_coreimage.m index 41750bfb7ec..979eab3b01a 100644 --- a/libavfilter/vf_coreimage.m +++ b/libavfilter/vf_coreimage.m @@ -304,7 +304,7 @@ static int request_frame(AVFilterLink *link) #if FF_API_FRAME_KEY frame->key_frame = 1; #endif - frame->flags |= AV_FRAME_FLAG_KEY + frame->flags |= AV_FRAME_FLAG_KEY; #if FF_API_INTERLACED_FRAME frame->interlaced_frame = 0; #endif From ecdf1ac267b1540c246666add646a6cc082a0828 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Thu, 4 May 2023 16:40:10 +0200 Subject: [PATCH 0885/2172] lavc/tak: make ff_tak_parse_streaminfo static It is not used outside of tak.c --- libavcodec/tak.c | 6 +++--- libavcodec/tak.h | 2 -- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/libavcodec/tak.c b/libavcodec/tak.c index f26574c968e..d1604dc9d25 100644 --- a/libavcodec/tak.c +++ b/libavcodec/tak.c @@ -92,7 +92,7 @@ int ff_tak_check_crc(const uint8_t *buf, unsigned int buf_size) return 0; } -void ff_tak_parse_streaminfo(TAKStreamInfo *s, GetBitContext *gb) +static void tak_parse_streaminfo(TAKStreamInfo *s, GetBitContext *gb) { uint64_t channel_mask = 0; int frame_type, i; @@ -135,7 +135,7 @@ int avpriv_tak_parse_streaminfo(TAKStreamInfo *s, const uint8_t *buf, int size) if (ret < 0) return AVERROR_INVALIDDATA; - ff_tak_parse_streaminfo(s, &gb); + tak_parse_streaminfo(s, &gb); return 0; } @@ -159,7 +159,7 @@ int ff_tak_decode_frame_header(AVCodecContext *avctx, GetBitContext *gb, } if (ti->flags & TAK_FRAME_FLAG_HAS_INFO) { - ff_tak_parse_streaminfo(ti, gb); + tak_parse_streaminfo(ti, gb); if (get_bits(gb, 6)) skip_bits(gb, 25); diff --git a/libavcodec/tak.h b/libavcodec/tak.h index 60691189710..5e43598de80 100644 --- a/libavcodec/tak.h +++ b/libavcodec/tak.h @@ -149,8 +149,6 @@ int ff_tak_check_crc(const uint8_t *buf, unsigned int buf_size); */ int avpriv_tak_parse_streaminfo(TAKStreamInfo *s, const uint8_t *buf, int size); -void ff_tak_parse_streaminfo(TAKStreamInfo *s, GetBitContext *gb); - /** * Validate and decode a frame header. * @param avctx AVCodecContext to use as av_log() context From a59b4ac71342e5644d38e8a812df67d87fddeaa7 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Thu, 4 May 2023 20:45:03 +0200 Subject: [PATCH 0886/2172] lavc/tak: do not store invalid values in stream info When tak_get_nb_samples() fails, it will currently write AVERROR_INVALIDDATA as TAKStreamInfo.frame_samples. The parser will then use this negative value as a frame duration, which leads to various breakage. Avoid this by returning the error code from tak_parse_streaminfo() directly; never store negative values in the parsed header. --- libavcodec/tak.c | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/libavcodec/tak.c b/libavcodec/tak.c index d1604dc9d25..628609b71b1 100644 --- a/libavcodec/tak.c +++ b/libavcodec/tak.c @@ -92,10 +92,10 @@ int ff_tak_check_crc(const uint8_t *buf, unsigned int buf_size) return 0; } -static void tak_parse_streaminfo(TAKStreamInfo *s, GetBitContext *gb) +static int tak_parse_streaminfo(TAKStreamInfo *s, GetBitContext *gb) { uint64_t channel_mask = 0; - int frame_type, i; + int frame_type, i, ret; s->codec = get_bits(gb, TAK_ENCODER_CODEC_BITS); skip_bits(gb, TAK_ENCODER_PROFILE_BITS); @@ -124,7 +124,13 @@ static void tak_parse_streaminfo(TAKStreamInfo *s, GetBitContext *gb) } s->ch_layout = channel_mask; - s->frame_samples = tak_get_nb_samples(s->sample_rate, frame_type); + + ret = tak_get_nb_samples(s->sample_rate, frame_type); + if (ret < 0) + return ret; + s->frame_samples = ret; + + return 0; } int avpriv_tak_parse_streaminfo(TAKStreamInfo *s, const uint8_t *buf, int size) @@ -135,9 +141,7 @@ int avpriv_tak_parse_streaminfo(TAKStreamInfo *s, const uint8_t *buf, int size) if (ret < 0) return AVERROR_INVALIDDATA; - tak_parse_streaminfo(s, &gb); - - return 0; + return tak_parse_streaminfo(s, &gb); } int ff_tak_decode_frame_header(AVCodecContext *avctx, GetBitContext *gb, @@ -159,7 +163,9 @@ int ff_tak_decode_frame_header(AVCodecContext *avctx, GetBitContext *gb, } if (ti->flags & TAK_FRAME_FLAG_HAS_INFO) { - tak_parse_streaminfo(ti, gb); + int ret = tak_parse_streaminfo(ti, gb); + if (ret < 0) + return ret; if (get_bits(gb, 6)) skip_bits(gb, 25); From e38e9f3d54f1bf7402748fba19edcaea19afd060 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Wed, 5 Apr 2023 14:01:10 +0200 Subject: [PATCH 0887/2172] lavf/demux: use avg_frame_rate for packet durations for notimestamps formats avg_frame_rate, if set, should be more reliable than stream timebase in this case. --- libavformat/demux.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/libavformat/demux.c b/libavformat/demux.c index 06de71cd6e3..45e5f5c4c2a 100644 --- a/libavformat/demux.c +++ b/libavformat/demux.c @@ -668,6 +668,11 @@ static void compute_frame_duration(AVFormatContext *s, int *pnum, int *pden, if (st->r_frame_rate.num && (!pc || !codec_framerate.num)) { *pnum = st->r_frame_rate.den; *pden = st->r_frame_rate.num; + } else if ((s->iformat->flags & AVFMT_NOTIMESTAMPS) && + !codec_framerate.num && + st->avg_frame_rate.num && st->avg_frame_rate.den) { + *pnum = st->avg_frame_rate.den; + *pden = st->avg_frame_rate.num; } else if (st->time_base.num * 1000LL > st->time_base.den) { *pnum = st->time_base.num; *pden = st->time_base.den; From 2850584876e52beaddf7a9f30e9914dad7115618 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Tue, 2 May 2023 10:51:08 +0200 Subject: [PATCH 0888/2172] lavf/rawdec: stop setting codec context framerate Demuxers are not supposed to do this. --- libavformat/rawdec.c | 1 - 1 file changed, 1 deletion(-) diff --git a/libavformat/rawdec.c b/libavformat/rawdec.c index 9126a9e53b0..6b623d366e2 100644 --- a/libavformat/rawdec.c +++ b/libavformat/rawdec.c @@ -87,7 +87,6 @@ int ff_raw_video_read_header(AVFormatContext *s) sti->need_parsing = AVSTREAM_PARSE_FULL_RAW; st->avg_frame_rate = s1->framerate; - sti->avctx->framerate = s1->framerate; avpriv_set_pts_info(st, 64, 1, 1200000); fail: From e43be84c0f3ff6d0dda6976120b33234cc5db962 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Tue, 2 May 2023 10:53:46 +0200 Subject: [PATCH 0889/2172] lavf/av1dec: mark as notimestamps --- libavformat/av1dec.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libavformat/av1dec.c b/libavformat/av1dec.c index d4b430af7e1..ba7fee60cd7 100644 --- a/libavformat/av1dec.c +++ b/libavformat/av1dec.c @@ -287,7 +287,7 @@ const AVInputFormat ff_av1_demuxer = { .read_packet = annexb_read_packet, .read_close = av1_read_close, .extensions = "obu", - .flags = AVFMT_GENERIC_INDEX, + .flags = AVFMT_GENERIC_INDEX | AVFMT_NOTIMESTAMPS, .priv_class = &av1_demuxer_class, }; #endif @@ -432,7 +432,7 @@ const AVInputFormat ff_obu_demuxer = { .read_packet = obu_read_packet, .read_close = av1_read_close, .extensions = "obu", - .flags = AVFMT_GENERIC_INDEX | AVFMT_NO_BYTE_SEEK, + .flags = AVFMT_GENERIC_INDEX | AVFMT_NO_BYTE_SEEK | AVFMT_NOTIMESTAMPS, .priv_class = &av1_demuxer_class, }; #endif From 60ecf44b037c7961ac4e69f83ff315c11c5df922 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Tue, 2 May 2023 10:51:08 +0200 Subject: [PATCH 0890/2172] lavf/av1dec: stop setting codec context framerate Demuxers are not supposed to do this. --- libavformat/av1dec.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavformat/av1dec.c b/libavformat/av1dec.c index ba7fee60cd7..216d4e22983 100644 --- a/libavformat/av1dec.c +++ b/libavformat/av1dec.c @@ -80,7 +80,7 @@ static int av1_read_header(AVFormatContext *s) st->codecpar->codec_id = AV_CODEC_ID_AV1; sti->need_parsing = AVSTREAM_PARSE_HEADERS; - sti->avctx->framerate = c->framerate; + st->avg_frame_rate = c->framerate; // taken from rawvideo demuxers avpriv_set_pts_info(st, 64, 1, 1200000); From 29190279365c02c7a879cd69c17f8bf8f4233e65 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9mi=20Denis-Courmont?= Date: Wed, 3 May 2023 19:10:12 +0300 Subject: [PATCH 0891/2172] MAINTAINERS: add vanitous self to maintain RISC-V Signed-off-by: James Almer --- MAINTAINERS | 1 + 1 file changed, 1 insertion(+) diff --git a/MAINTAINERS b/MAINTAINERS index 854ccc3fa4c..f95be01dc68 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -543,6 +543,7 @@ LoongArch Shiyou Yin Mac OS X / PowerPC Romain Dolbeau, Guillaume Poirier Amiga / PowerPC Colin Ward Linux / PowerPC Lauri Kasanen +RISC-V Rémi Denis-Courmont Windows MinGW Alex Beregszaszi, Ramiro Polla Windows Cygwin Victor Paesa Windows MSVC Matthew Oliver, Hendrik Leppkes From 6f1c82fd5bd1935b4e4ba71fc1ef4cb13730447a Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Fri, 5 May 2023 02:04:04 +0200 Subject: [PATCH 0892/2172] avfilter/af_biquads: reduce double type usage --- libavfilter/af_biquads.c | 715 ++++++++++++++++++++------------------- 1 file changed, 370 insertions(+), 345 deletions(-) diff --git a/libavfilter/af_biquads.c b/libavfilter/af_biquads.c index 49ad0a471f0..3b12aee3c0c 100644 --- a/libavfilter/af_biquads.c +++ b/libavfilter/af_biquads.c @@ -109,14 +109,6 @@ enum TransformType { NB_TTYPE, }; -typedef struct ChanCache { - double i1, i2; - double o1, o2; - double ri1, ri2; - double ro1, ro2; - int clippings; -} ChanCache; - typedef struct BiquadsContext { const AVClass *class; @@ -139,24 +131,26 @@ typedef struct BiquadsContext { int normalize; int order; - double a0, a1, a2; - double b0, b1, b2; + double a_double[3]; + double b_double[3]; + + float a_float[3]; + float b_float[3]; - double oa0, oa1, oa2; - double ob0, ob1, ob2; + double oa[3]; + double ob[3]; AVFrame *block[3]; - ChanCache *cache; + int *clip; + AVFrame *cache[2]; int block_align; int64_t pts; int nb_samples; void (*filter)(struct BiquadsContext *s, const void *ibuf, void *obuf, int len, - double *i1, double *i2, double *o1, double *o2, - double b0, double b1, double b2, double a0, double a1, double a2, int *clippings, - int disabled); + void *cache, int *clip, int disabled); } BiquadsContext; static int query_formats(AVFilterContext *ctx) @@ -202,27 +196,26 @@ static int query_formats(AVFilterContext *ctx) return ff_set_common_all_samplerates(ctx); } -#define BIQUAD_FILTER(name, type, min, max, need_clipping) \ +#define BIQUAD_FILTER(name, type, ftype, min, max, need_clipping) \ static void biquad_## name (BiquadsContext *s, \ const void *input, void *output, int len, \ - double *in1, double *in2, \ - double *out1, double *out2, \ - double b0, double b1, double b2, \ - double a0, double a1, double a2, int *clippings, \ - int disabled) \ + void *cache, int *clippings, int disabled) \ { \ const type *ibuf = input; \ type *obuf = output; \ - double i1 = *in1; \ - double i2 = *in2; \ - double o1 = *out1; \ - double o2 = *out2; \ - double wet = s->mix; \ - double dry = 1. - wet; \ - double out; \ + ftype *fcache = cache; \ + ftype i1 = fcache[0], i2 = fcache[1], o1 = fcache[2], o2 = fcache[3]; \ + ftype *a = s->a_##ftype; \ + ftype *b = s->b_##ftype; \ + ftype a1 = -a[1]; \ + ftype a2 = -a[2]; \ + ftype b0 = b[0]; \ + ftype b1 = b[1]; \ + ftype b2 = b[2]; \ + ftype wet = s->mix; \ + ftype dry = 1. - wet; \ + ftype out; \ int i; \ - a1 = -a1; \ - a2 = -a2; \ \ for (i = 0; i+1 < len; i++) { \ o2 = i2 * b2 + i1 * b1 + ibuf[i] * b0 + o2 * a2 + o1 * a1; \ @@ -256,7 +249,7 @@ static void biquad_## name (BiquadsContext *s, \ } \ } \ if (i < len) { \ - double o0 = ibuf[i] * b0 + i1 * b1 + i2 * b2 + o1 * a1 + o2 * a2; \ + ftype o0 = ibuf[i] * b0 + i1 * b1 + i2 * b2 + o1 * a1 + o2 * a2; \ i2 = i1; \ i1 = ibuf[i]; \ o2 = o1; \ @@ -274,36 +267,37 @@ static void biquad_## name (BiquadsContext *s, \ obuf[i] = out; \ } \ } \ - *in1 = i1; \ - *in2 = i2; \ - *out1 = o1; \ - *out2 = o2; \ + fcache[0] = i1; \ + fcache[1] = i2; \ + fcache[2] = o1; \ + fcache[3] = o2; \ } -BIQUAD_FILTER(s16, int16_t, INT16_MIN, INT16_MAX, 1) -BIQUAD_FILTER(s32, int32_t, INT32_MIN, INT32_MAX, 1) -BIQUAD_FILTER(flt, float, -1., 1., 0) -BIQUAD_FILTER(dbl, double, -1., 1., 0) +BIQUAD_FILTER(s16, int16_t, float, INT16_MIN, INT16_MAX, 1) +BIQUAD_FILTER(s32, int32_t, double, INT32_MIN, INT32_MAX, 1) +BIQUAD_FILTER(flt, float, float, -1.f, 1.f, 0) +BIQUAD_FILTER(dbl, double, double, -1., 1., 0) -#define BIQUAD_DII_FILTER(name, type, min, max, need_clipping) \ +#define BIQUAD_DII_FILTER(name, type, ftype, min, max, need_clipping) \ static void biquad_dii_## name (BiquadsContext *s, \ const void *input, void *output, int len, \ - double *z1, double *z2, \ - double *unused1, double *unused2, \ - double b0, double b1, double b2, \ - double a0, double a1, double a2, int *clippings, \ - int disabled) \ + void *cache, int *clippings, int disabled) \ { \ const type *ibuf = input; \ type *obuf = output; \ - double w1 = *z1; \ - double w2 = *z2; \ - double wet = s->mix; \ - double dry = 1. - wet; \ - double in, out, w0; \ - \ - a1 = -a1; \ - a2 = -a2; \ + ftype *fcache = cache; \ + ftype *a = s->a_##ftype; \ + ftype *b = s->b_##ftype; \ + ftype a1 = -a[1]; \ + ftype a2 = -a[2]; \ + ftype b0 = b[0]; \ + ftype b1 = b[1]; \ + ftype b2 = b[2]; \ + ftype w1 = fcache[0]; \ + ftype w2 = fcache[1]; \ + ftype wet = s->mix; \ + ftype dry = 1. - wet; \ + ftype in, out, w0; \ \ for (int i = 0; i < len; i++) { \ in = ibuf[i]; \ @@ -324,39 +318,40 @@ static void biquad_dii_## name (BiquadsContext *s, \ obuf[i] = out; \ } \ } \ - *z1 = w1; \ - *z2 = w2; \ + fcache[0] = w1; \ + fcache[1] = w2; \ } -BIQUAD_DII_FILTER(s16, int16_t, INT16_MIN, INT16_MAX, 1) -BIQUAD_DII_FILTER(s32, int32_t, INT32_MIN, INT32_MAX, 1) -BIQUAD_DII_FILTER(flt, float, -1., 1., 0) -BIQUAD_DII_FILTER(dbl, double, -1., 1., 0) +BIQUAD_DII_FILTER(s16, int16_t, float, INT16_MIN, INT16_MAX, 1) +BIQUAD_DII_FILTER(s32, int32_t, double, INT32_MIN, INT32_MAX, 1) +BIQUAD_DII_FILTER(flt, float, float, -1.f, 1.f, 0) +BIQUAD_DII_FILTER(dbl, double, double, -1., 1., 0) -#define BIQUAD_TDI_FILTER(name, type, min, max, need_clipping) \ +#define BIQUAD_TDI_FILTER(name, type, ftype, min, max, need_clipping) \ static void biquad_tdi_## name (BiquadsContext *s, \ const void *input, void *output, int len, \ - double *z1, double *z2, \ - double *z3, double *z4, \ - double b0, double b1, double b2, \ - double a0, double a1, double a2, int *clippings, \ - int disabled) \ + void *cache, int *clippings, int disabled) \ { \ const type *ibuf = input; \ type *obuf = output; \ - double s1 = *z1; \ - double s2 = *z2; \ - double s3 = *z3; \ - double s4 = *z4; \ - double wet = s->mix; \ - double dry = 1. - wet; \ - double in, out; \ - \ - a1 = -a1; \ - a2 = -a2; \ + ftype *fcache = cache; \ + ftype *a = s->a_##ftype; \ + ftype *b = s->b_##ftype; \ + ftype a1 = -a[1]; \ + ftype a2 = -a[2]; \ + ftype b0 = b[0]; \ + ftype b1 = b[1]; \ + ftype b2 = b[2]; \ + ftype s1 = fcache[0]; \ + ftype s2 = fcache[1]; \ + ftype s3 = fcache[2]; \ + ftype s4 = fcache[3]; \ + ftype wet = s->mix; \ + ftype dry = 1. - wet; \ + ftype in, out; \ \ for (int i = 0; i < len; i++) { \ - double t1, t2, t3, t4; \ + ftype t1, t2, t3, t4; \ in = ibuf[i] + s1; \ t1 = in * a1 + s2; \ t2 = in * a2; \ @@ -378,36 +373,37 @@ static void biquad_tdi_## name (BiquadsContext *s, \ } \ } \ \ - *z1 = s1; \ - *z2 = s2; \ - *z3 = s3; \ - *z4 = s4; \ + fcache[0] = s1; \ + fcache[1] = s2; \ + fcache[2] = s3; \ + fcache[3] = s4; \ } -BIQUAD_TDI_FILTER(s16, int16_t, INT16_MIN, INT16_MAX, 1) -BIQUAD_TDI_FILTER(s32, int32_t, INT32_MIN, INT32_MAX, 1) -BIQUAD_TDI_FILTER(flt, float, -1., 1., 0) -BIQUAD_TDI_FILTER(dbl, double, -1., 1., 0) +BIQUAD_TDI_FILTER(s16, int16_t, float, INT16_MIN, INT16_MAX, 1) +BIQUAD_TDI_FILTER(s32, int32_t, double, INT32_MIN, INT32_MAX, 1) +BIQUAD_TDI_FILTER(flt, float, float, -1.f, 1.f, 0) +BIQUAD_TDI_FILTER(dbl, double, double, -1., 1., 0) -#define BIQUAD_TDII_FILTER(name, type, min, max, need_clipping) \ +#define BIQUAD_TDII_FILTER(name, type, ftype, min, max, need_clipping) \ static void biquad_tdii_## name (BiquadsContext *s, \ const void *input, void *output, int len, \ - double *z1, double *z2, \ - double *unused1, double *unused2, \ - double b0, double b1, double b2, \ - double a0, double a1, double a2, int *clippings, \ - int disabled) \ + void *cache, int *clippings, int disabled) \ { \ const type *ibuf = input; \ type *obuf = output; \ - double w1 = *z1; \ - double w2 = *z2; \ - double wet = s->mix; \ - double dry = 1. - wet; \ - double in, out; \ - \ - a1 = -a1; \ - a2 = -a2; \ + ftype *fcache = cache; \ + ftype *a = s->a_##ftype; \ + ftype *b = s->b_##ftype; \ + ftype a1 = -a[1]; \ + ftype a2 = -a[2]; \ + ftype b0 = b[0]; \ + ftype b1 = b[1]; \ + ftype b2 = b[2]; \ + ftype w1 = fcache[0]; \ + ftype w2 = fcache[1]; \ + ftype wet = s->mix; \ + ftype dry = 1. - wet; \ + ftype in, out; \ \ for (int i = 0; i < len; i++) { \ in = ibuf[i]; \ @@ -427,33 +423,36 @@ static void biquad_tdii_## name (BiquadsContext *s, \ obuf[i] = out; \ } \ } \ - *z1 = w1; \ - *z2 = w2; \ + fcache[0] = w1; \ + fcache[1] = w2; \ } -BIQUAD_TDII_FILTER(s16, int16_t, INT16_MIN, INT16_MAX, 1) -BIQUAD_TDII_FILTER(s32, int32_t, INT32_MIN, INT32_MAX, 1) -BIQUAD_TDII_FILTER(flt, float, -1., 1., 0) -BIQUAD_TDII_FILTER(dbl, double, -1., 1., 0) +BIQUAD_TDII_FILTER(s16, int16_t, float, INT16_MIN, INT16_MAX, 1) +BIQUAD_TDII_FILTER(s32, int32_t, double, INT32_MIN, INT32_MAX, 1) +BIQUAD_TDII_FILTER(flt, float, float, -1.f, 1.f, 0) +BIQUAD_TDII_FILTER(dbl, double, double, -1., 1., 0) -#define BIQUAD_LATT_FILTER(name, type, min, max, need_clipping) \ +#define BIQUAD_LATT_FILTER(name, type, ftype, min, max, need_clipping) \ static void biquad_latt_## name (BiquadsContext *s, \ const void *input, void *output, int len, \ - double *z1, double *z2, \ - double *unused1, double *unused2, \ - double v0, double v1, double v2, \ - double unused, double k0, double k1, \ - int *clippings, \ - int disabled) \ + void *cache, int *clippings, int disabled) \ { \ const type *ibuf = input; \ type *obuf = output; \ - double s0 = *z1; \ - double s1 = *z2; \ - double wet = s->mix; \ - double dry = 1. - wet; \ - double in, out; \ - double t0, t1; \ + ftype *fcache = cache; \ + ftype *a = s->a_##ftype; \ + ftype *b = s->b_##ftype; \ + ftype k0 = a[1]; \ + ftype k1 = a[2]; \ + ftype v0 = b[0]; \ + ftype v1 = b[1]; \ + ftype v2 = b[2]; \ + ftype s0 = fcache[0]; \ + ftype s1 = fcache[1]; \ + ftype wet = s->mix; \ + ftype dry = 1. - wet; \ + ftype in, out; \ + ftype t0, t1; \ \ for (int i = 0; i < len; i++) { \ out = 0.; \ @@ -483,32 +482,36 @@ static void biquad_latt_## name (BiquadsContext *s, \ obuf[i] = out; \ } \ } \ - *z1 = s0; \ - *z2 = s1; \ + fcache[0] = s0; \ + fcache[1] = s1; \ } -BIQUAD_LATT_FILTER(s16, int16_t, INT16_MIN, INT16_MAX, 1) -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) +BIQUAD_LATT_FILTER(s16, int16_t, float, INT16_MIN, INT16_MAX, 1) +BIQUAD_LATT_FILTER(s32, int32_t, double, INT32_MIN, INT32_MAX, 1) +BIQUAD_LATT_FILTER(flt, float, float, -1.f, 1.f, 0) +BIQUAD_LATT_FILTER(dbl, double, double, -1., 1., 0) -#define BIQUAD_SVF_FILTER(name, type, min, max, need_clipping) \ +#define BIQUAD_SVF_FILTER(name, type, ftype, 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 a0, double a1, double a2, int *clippings, \ - int disabled) \ + void *cache, 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; \ + ftype *fcache = cache; \ + ftype *a = s->a_##ftype; \ + ftype *b = s->b_##ftype; \ + ftype a1 = a[1]; \ + ftype a2 = a[2]; \ + ftype b0 = b[0]; \ + ftype b1 = b[1]; \ + ftype b2 = b[2]; \ + ftype s0 = fcache[0]; \ + ftype s1 = fcache[1]; \ + ftype wet = s->mix; \ + ftype dry = 1. - wet; \ + ftype in, out; \ + ftype t0, t1; \ \ for (int i = 0; i < len; i++) { \ in = ibuf[i]; \ @@ -531,41 +534,46 @@ static void biquad_svf_## name (BiquadsContext *s, \ obuf[i] = out; \ } \ } \ - *y0 = s0; \ - *y1 = s1; \ + fcache[0] = s0; \ + fcache[1] = 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) +BIQUAD_SVF_FILTER(s16, int16_t, float, INT16_MIN, INT16_MAX, 1) +BIQUAD_SVF_FILTER(s32, int32_t, double, INT32_MIN, INT32_MAX, 1) +BIQUAD_SVF_FILTER(flt, float, float, -1.f, 1.f, 0) +BIQUAD_SVF_FILTER(dbl, double, double, -1., 1., 0) -#define BIQUAD_ZDF_FILTER(name, type, min, max, need_clipping) \ +#define BIQUAD_ZDF_FILTER(name, type, ftype, min, max, need_clipping, two) \ static void biquad_zdf_## name (BiquadsContext *s, \ const void *input, void *output, int len, \ - double *y0, double *y1, \ - double *unused1, double *unused2, \ - double m0, double m1, double m2, \ - double a0, double a1, double a2, int *clippings, \ - int disabled) \ + void *cache, int *clippings, int disabled) \ { \ const type *ibuf = input; \ type *obuf = output; \ - double b0 = *y0; \ - double b1 = *y1; \ - double wet = s->mix; \ - double dry = 1. - wet; \ - double out; \ + ftype *fcache = cache; \ + ftype *a = s->a_##ftype; \ + ftype *b = s->b_##ftype; \ + ftype m0 = b[0]; \ + ftype m1 = b[1]; \ + ftype m2 = b[2]; \ + ftype a0 = a[0]; \ + ftype a1 = a[1]; \ + ftype a2 = a[2]; \ + ftype b0 = fcache[0]; \ + ftype b1 = fcache[1]; \ + ftype wet = s->mix; \ + ftype dry = 1. - wet; \ + ftype out; \ \ for (int i = 0; i < len; i++) { \ - const double in = ibuf[i]; \ - const double v0 = in; \ - const double v3 = v0 - b1; \ - const double v1 = a0 * b0 + a1 * v3; \ - const double v2 = b1 + a1 * b0 + a2 * v3; \ + const ftype in = ibuf[i]; \ + const ftype v0 = in; \ + const ftype v3 = v0 - b1; \ + const ftype v1 = a0 * b0 + a1 * v3; \ + const ftype v2 = b1 + a1 * b0 + a2 * v3; \ \ - b0 = 2. * v1 - b0; \ - b1 = 2. * v2 - b1; \ + b0 = two * v1 - b0; \ + b1 = two * v2 - b1; \ \ out = m0 * v0 + m1 * v1 + m2 * v2; \ out = out * wet + in * dry; \ @@ -581,30 +589,30 @@ static void biquad_zdf_## name (BiquadsContext *s, \ obuf[i] = out; \ } \ } \ - *y0 = b0; \ - *y1 = b1; \ + fcache[0] = b0; \ + fcache[1] = b1; \ } -BIQUAD_ZDF_FILTER(s16, int16_t, INT16_MIN, INT16_MAX, 1) -BIQUAD_ZDF_FILTER(s32, int32_t, INT32_MIN, INT32_MAX, 1) -BIQUAD_ZDF_FILTER(flt, float, -1., 1., 0) -BIQUAD_ZDF_FILTER(dbl, double, -1., 1., 0) +BIQUAD_ZDF_FILTER(s16, int16_t, float, INT16_MIN, INT16_MAX, 1, 2.f) +BIQUAD_ZDF_FILTER(s32, int32_t, double, INT32_MIN, INT32_MAX, 1, 2.0) +BIQUAD_ZDF_FILTER(flt, float, float, -1.f, 1.f, 0, 2.f) +BIQUAD_ZDF_FILTER(dbl, double, double, -1., 1., 0, 2.0) static void convert_dir2latt(BiquadsContext *s) { double k0, k1, v0, v1, v2; - k1 = s->a2; - k0 = s->a1 / (1. + k1); - v2 = s->b2; - v1 = s->b1 - v2 * s->a1; - v0 = s->b0 - v1 * k0 - v2 * k1; - - s->a1 = k0; - s->a2 = k1; - s->b0 = v0; - s->b1 = v1; - s->b2 = v2; + k1 = s->a_double[2]; + k0 = s->a_double[1] / (1. + k1); + v2 = s->b_double[2]; + v1 = s->b_double[1] - v2 * s->a_double[1]; + v0 = s->b_double[0] - v1 * k0 - v2 * k1; + + s->a_double[1] = k0; + s->a_double[2] = k1; + s->b_double[0] = v0; + s->b_double[1] = v1; + s->b_double[2] = v2; } static void convert_dir2svf(BiquadsContext *s) @@ -612,17 +620,17 @@ 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]; + a[0] = -s->a_double[1]; + a[1] = -s->a_double[2]; + b[0] = s->b_double[1] - s->a_double[1] * s->b_double[0]; + b[1] = s->b_double[2] - s->a_double[2] * s->b_double[0]; + b[2] = s->b_double[0]; + + s->a_double[1] = a[0]; + s->a_double[2] = a[1]; + s->b_double[0] = b[0]; + s->b_double[1] = b[1]; + s->b_double[2] = b[2]; } static double convert_width2qfactor(double width, @@ -669,12 +677,12 @@ static void convert_dir2zdf(BiquadsContext *s, int sample_rate) switch (s->filter_type) { case biquad: - a[0] = s->oa0; - a[1] = s->oa1; - a[2] = s->oa2; - m[0] = s->ob0; - m[1] = s->ob1; - m[2] = s->ob2; + a[0] = s->oa[0]; + a[1] = s->oa[1]; + a[2] = s->oa[2]; + m[0] = s->ob[0]; + m[1] = s->ob[1]; + m[2] = s->ob[2]; break; case equalizer: A = ff_exp10(s->gain / 40.); @@ -776,12 +784,12 @@ static void convert_dir2zdf(BiquadsContext *s, int sample_rate) av_assert0(0); } - s->a0 = a[0]; - s->a1 = a[1]; - s->a2 = a[2]; - s->b0 = m[0]; - s->b1 = m[1]; - s->b2 = m[2]; + s->a_double[0] = a[0]; + s->a_double[1] = a[1]; + s->a_double[2] = a[2]; + s->b_double[0] = m[0]; + s->b_double[1] = m[1]; + s->b_double[2] = m[2]; } static int config_filter(AVFilterLink *outlink, int reset) @@ -831,20 +839,20 @@ static int config_filter(AVFilterLink *outlink, int reset) switch (s->filter_type) { case biquad: - s->a0 = s->oa0; - s->a1 = s->oa1; - s->a2 = s->oa2; - s->b0 = s->ob0; - s->b1 = s->ob1; - s->b2 = s->ob2; + s->a_double[0] = s->oa[0]; + s->a_double[1] = s->oa[1]; + s->a_double[2] = s->oa[2]; + s->b_double[0] = s->ob[0]; + s->b_double[1] = s->ob[1]; + s->b_double[2] = s->ob[2]; break; case equalizer: - s->a0 = 1 + alpha / A; - s->a1 = -2 * cos(w0); - s->a2 = 1 - alpha / A; - s->b0 = 1 + alpha * A; - s->b1 = -2 * cos(w0); - s->b2 = 1 - alpha * A; + s->a_double[0] = 1 + alpha / A; + s->a_double[1] = -2 * cos(w0); + s->a_double[2] = 1 - alpha / A; + s->b_double[0] = 1 + alpha * A; + s->b_double[1] = -2 * cos(w0); + s->b_double[2] = 1 - alpha * A; break; case bass: beta = sqrt((A * A + 1) - (A - 1) * (A - 1)); @@ -858,19 +866,19 @@ static int config_filter(AVFilterLink *outlink, int reset) double beta0 = ((1 + A) + (1 - A) * alpha1) * 0.5; double beta1 = ((1 - A) + (1 + A) * alpha1) * 0.5; - s->a0 = 1 + ro * alpha1; - s->a1 = -ro - alpha1; - s->a2 = 0; - s->b0 = beta0 + ro * beta1; - s->b1 = -beta1 - ro * beta0; - s->b2 = 0; + s->a_double[0] = 1 + ro * alpha1; + s->a_double[1] = -ro - alpha1; + s->a_double[2] = 0; + s->b_double[0] = beta0 + ro * beta1; + s->b_double[1] = -beta1 - ro * beta0; + s->b_double[2] = 0; } else { - s->a0 = (A + 1) + (A - 1) * cos(w0) + beta * alpha; - s->a1 = -2 * ((A - 1) + (A + 1) * cos(w0)); - s->a2 = (A + 1) + (A - 1) * cos(w0) - beta * alpha; - s->b0 = A * ((A + 1) - (A - 1) * cos(w0) + beta * alpha); - s->b1 = 2 * A * ((A - 1) - (A + 1) * cos(w0)); - s->b2 = A * ((A + 1) - (A - 1) * cos(w0) - beta * alpha); + s->a_double[0] = (A + 1) + (A - 1) * cos(w0) + beta * alpha; + s->a_double[1] = -2 * ((A - 1) + (A + 1) * cos(w0)); + s->a_double[2] = (A + 1) + (A - 1) * cos(w0) - beta * alpha; + s->b_double[0] = A * ((A + 1) - (A - 1) * cos(w0) + beta * alpha); + s->b_double[1] = 2 * A * ((A - 1) - (A + 1) * cos(w0)); + s->b_double[2] = A * ((A + 1) - (A - 1) * cos(w0) - beta * alpha); } break; case treble: @@ -884,97 +892,97 @@ static int config_filter(AVFilterLink *outlink, int reset) double beta0 = ((1 + A) + (1 - A) * alpha1) * 0.5; double beta1 = ((1 - A) + (1 + A) * alpha1) * 0.5; - s->a0 = 1 + ro * alpha1; - s->a1 = ro + alpha1; - s->a2 = 0; - s->b0 = beta0 + ro * beta1; - s->b1 = beta1 + ro * beta0; - s->b2 = 0; + s->a_double[0] = 1 + ro * alpha1; + s->a_double[1] = ro + alpha1; + s->a_double[2] = 0; + s->b_double[0] = beta0 + ro * beta1; + s->b_double[1] = beta1 + ro * beta0; + s->b_double[2] = 0; } else { - s->a0 = (A + 1) - (A - 1) * cos(w0) + beta * alpha; - s->a1 = 2 * ((A - 1) - (A + 1) * cos(w0)); - s->a2 = (A + 1) - (A - 1) * cos(w0) - beta * alpha; - s->b0 = A * ((A + 1) + (A - 1) * cos(w0) + beta * alpha); - s->b1 =-2 * A * ((A - 1) + (A + 1) * cos(w0)); - s->b2 = A * ((A + 1) + (A - 1) * cos(w0) - beta * alpha); + s->a_double[0] = (A + 1) - (A - 1) * cos(w0) + beta * alpha; + s->a_double[1] = 2 * ((A - 1) - (A + 1) * cos(w0)); + s->a_double[2] = (A + 1) - (A - 1) * cos(w0) - beta * alpha; + s->b_double[0] = A * ((A + 1) + (A - 1) * cos(w0) + beta * alpha); + s->b_double[1] =-2 * A * ((A - 1) + (A + 1) * cos(w0)); + s->b_double[2] = A * ((A + 1) + (A - 1) * cos(w0) - beta * alpha); } break; case bandpass: if (s->csg) { - s->a0 = 1 + alpha; - s->a1 = -2 * cos(w0); - s->a2 = 1 - alpha; - s->b0 = sin(w0) / 2; - s->b1 = 0; - s->b2 = -sin(w0) / 2; + s->a_double[0] = 1 + alpha; + s->a_double[1] = -2 * cos(w0); + s->a_double[2] = 1 - alpha; + s->b_double[0] = sin(w0) / 2; + s->b_double[1] = 0; + s->b_double[2] = -sin(w0) / 2; } else { - s->a0 = 1 + alpha; - s->a1 = -2 * cos(w0); - s->a2 = 1 - alpha; - s->b0 = alpha; - s->b1 = 0; - s->b2 = -alpha; + s->a_double[0] = 1 + alpha; + s->a_double[1] = -2 * cos(w0); + s->a_double[2] = 1 - alpha; + s->b_double[0] = alpha; + s->b_double[1] = 0; + s->b_double[2] = -alpha; } break; case bandreject: - s->a0 = 1 + alpha; - s->a1 = -2 * cos(w0); - s->a2 = 1 - alpha; - s->b0 = 1; - s->b1 = -2 * cos(w0); - s->b2 = 1; + s->a_double[0] = 1 + alpha; + s->a_double[1] = -2 * cos(w0); + s->a_double[2] = 1 - alpha; + s->b_double[0] = 1; + s->b_double[1] = -2 * cos(w0); + s->b_double[2] = 1; break; case lowpass: if (s->poles == 1) { - s->a0 = 1; - s->a1 = -exp(-w0); - s->a2 = 0; - s->b0 = 1 + s->a1; - s->b1 = 0; - s->b2 = 0; + s->a_double[0] = 1; + s->a_double[1] = -exp(-w0); + s->a_double[2] = 0; + s->b_double[0] = 1 + s->a_double[1]; + s->b_double[1] = 0; + s->b_double[2] = 0; } else { - s->a0 = 1 + alpha; - s->a1 = -2 * cos(w0); - s->a2 = 1 - alpha; - s->b0 = (1 - cos(w0)) / 2; - s->b1 = 1 - cos(w0); - s->b2 = (1 - cos(w0)) / 2; + s->a_double[0] = 1 + alpha; + s->a_double[1] = -2 * cos(w0); + s->a_double[2] = 1 - alpha; + s->b_double[0] = (1 - cos(w0)) / 2; + s->b_double[1] = 1 - cos(w0); + s->b_double[2] = (1 - cos(w0)) / 2; } break; case highpass: if (s->poles == 1) { - s->a0 = 1; - s->a1 = -exp(-w0); - s->a2 = 0; - s->b0 = (1 - s->a1) / 2; - s->b1 = -s->b0; - s->b2 = 0; + s->a_double[0] = 1; + s->a_double[1] = -exp(-w0); + s->a_double[2] = 0; + s->b_double[0] = (1 - s->a_double[1]) / 2; + s->b_double[1] = -s->b_double[0]; + s->b_double[2] = 0; } else { - s->a0 = 1 + alpha; - s->a1 = -2 * cos(w0); - s->a2 = 1 - alpha; - s->b0 = (1 + cos(w0)) / 2; - s->b1 = -(1 + cos(w0)); - s->b2 = (1 + cos(w0)) / 2; + s->a_double[0] = 1 + alpha; + s->a_double[1] = -2 * cos(w0); + s->a_double[2] = 1 - alpha; + s->b_double[0] = (1 + cos(w0)) / 2; + s->b_double[1] = -(1 + cos(w0)); + s->b_double[2] = (1 + cos(w0)) / 2; } break; case allpass: switch (s->order) { case 1: - s->a0 = 1.; - s->a1 = -(1. - K) / (1. + K); - s->a2 = 0.; - s->b0 = s->a1; - s->b1 = s->a0; - s->b2 = 0.; + s->a_double[0] = 1.; + s->a_double[1] = -(1. - K) / (1. + K); + s->a_double[2] = 0.; + s->b_double[0] = s->a_double[1]; + s->b_double[1] = s->a_double[0]; + s->b_double[2] = 0.; break; case 2: - s->a0 = 1 + alpha; - s->a1 = -2 * cos(w0); - s->a2 = 1 - alpha; - s->b0 = 1 - alpha; - s->b1 = -2 * cos(w0); - s->b2 = 1 + alpha; + s->a_double[0] = 1 + alpha; + s->a_double[1] = -2 * cos(w0); + s->a_double[2] = 1 - alpha; + s->b_double[0] = 1 - alpha; + s->b_double[1] = -2 * cos(w0); + s->b_double[2] = 1 + alpha; break; } break; @@ -982,40 +990,55 @@ static int config_filter(AVFilterLink *outlink, int reset) av_assert0(0); } - av_log(ctx, AV_LOG_VERBOSE, "a=%f %f %f:b=%f %f %f\n", s->a0, s->a1, s->a2, s->b0, s->b1, s->b2); + av_log(ctx, AV_LOG_VERBOSE, "a=%f %f %f:b=%f %f %f\n", + s->a_double[0], s->a_double[1], s->a_double[2], + s->b_double[0], s->b_double[1], s->b_double[2]); - s->a1 /= s->a0; - s->a2 /= s->a0; - s->b0 /= s->a0; - s->b1 /= s->a0; - s->b2 /= s->a0; - s->a0 /= s->a0; + s->a_double[1] /= s->a_double[0]; + s->a_double[2] /= s->a_double[0]; + s->b_double[0] /= s->a_double[0]; + s->b_double[1] /= s->a_double[0]; + s->b_double[2] /= s->a_double[0]; + s->a_double[0] /= s->a_double[0]; - if (s->normalize && fabs(s->b0 + s->b1 + s->b2) > 1e-6) { - double factor = (s->a0 + s->a1 + s->a2) / (s->b0 + s->b1 + s->b2); + if (s->normalize && fabs(s->b_double[0] + s->b_double[1] + s->b_double[2]) > 1e-6) { + double factor = (s->a_double[0] + s->a_double[1] + s->a_double[2]) / + (s->b_double[0] + s->b_double[1] + s->b_double[2]); - s->b0 *= factor; - s->b1 *= factor; - s->b2 *= factor; + s->b_double[0] *= factor; + s->b_double[1] *= factor; + s->b_double[2] *= factor; } switch (s->filter_type) { case tiltshelf: - s->b0 /= A; - s->b1 /= A; - s->b2 /= A; + s->b_double[0] /= A; + s->b_double[1] /= A; + s->b_double[2] /= A; break; } - s->cache = av_realloc_f(s->cache, sizeof(ChanCache), inlink->ch_layout.nb_channels); - if (!s->cache) + if (!s->cache[0]) + s->cache[0] = ff_get_audio_buffer(outlink, 4 * sizeof(double)); + if (!s->clip) + s->clip = av_calloc(outlink->ch_layout.nb_channels, sizeof(*s->clip)); + if (!s->cache[0] || !s->clip) return AVERROR(ENOMEM); - if (reset) - memset(s->cache, 0, sizeof(ChanCache) * inlink->ch_layout.nb_channels); + if (reset) { + av_samples_set_silence(s->cache[0]->extended_data, 0, s->cache[0]->nb_samples, + s->cache[0]->ch_layout.nb_channels, s->cache[0]->format); + } if (reset && s->block_samples > 0) { + if (!s->cache[1]) + s->cache[1] = ff_get_audio_buffer(outlink, 4 * sizeof(double)); + if (!s->cache[1]) + return AVERROR(ENOMEM); + av_samples_set_silence(s->cache[1]->extended_data, 0, s->cache[1]->nb_samples, + s->cache[1]->ch_layout.nb_channels, s->cache[1]->format); for (int i = 0; i < 3; i++) { - s->block[i] = ff_get_audio_buffer(outlink, s->block_samples * 2); + if (!s->block[i]) + s->block[i] = ff_get_audio_buffer(outlink, s->block_samples * 2); if (!s->block[i]) return AVERROR(ENOMEM); av_samples_set_silence(s->block[i]->extended_data, 0, s->block_samples * 2, @@ -1145,16 +1168,23 @@ static int config_filter(AVFilterLink *outlink, int reset) break; default: av_assert0(0); - } + } + + s->block_align = av_get_bytes_per_sample(inlink->format); - s->block_align = av_get_bytes_per_sample(inlink->format); + if (s->transform_type == LATT) + convert_dir2latt(s); + else if (s->transform_type == SVF) + convert_dir2svf(s); + else if (s->transform_type == ZDF) + convert_dir2zdf(s, inlink->sample_rate); - if (s->transform_type == LATT) - convert_dir2latt(s); - else if (s->transform_type == SVF) - convert_dir2svf(s); - else if (s->transform_type == ZDF) - convert_dir2zdf(s, inlink->sample_rate); + s->a_float[0] = s->a_double[0]; + s->a_float[1] = s->a_double[1]; + s->a_float[2] = s->a_double[2]; + s->b_float[0] = s->b_double[0]; + s->b_float[1] = s->b_double[1]; + s->b_float[2] = s->b_double[2]; return 0; } @@ -1227,8 +1257,7 @@ static int filter_channel(AVFilterContext *ctx, void *arg, int jobnr, int nb_job if (!s->block_samples) { s->filter(s, buf->extended_data[ch], out_buf->extended_data[ch], buf->nb_samples, - &s->cache[ch].i1, &s->cache[ch].i2, &s->cache[ch].o1, &s->cache[ch].o2, - s->b0, s->b1, s->b2, s->a0, s->a1, s->a2, &s->cache[ch].clippings, ctx->is_disabled); + s->cache[0]->extended_data[ch], s->clip+ch, ctx->is_disabled); } else if (td->eof) { memcpy(out_buf->extended_data[ch], s->block[1]->extended_data[ch] + s->block_align * s->block_samples, s->nb_samples * s->block_align); @@ -1238,25 +1267,19 @@ static int filter_channel(AVFilterContext *ctx, void *arg, int jobnr, int nb_job memset(s->block[0]->extended_data[ch] + s->block_align * (s->block_samples + buf->nb_samples), 0, (s->block_samples - buf->nb_samples) * s->block_align); s->filter(s, s->block[0]->extended_data[ch], s->block[1]->extended_data[ch], s->block_samples, - &s->cache[ch].i1, &s->cache[ch].i2, &s->cache[ch].o1, &s->cache[ch].o2, - s->b0, s->b1, s->b2, s->a0, s->a1, s->a2, &s->cache[ch].clippings, ctx->is_disabled); - s->cache[ch].ri1 = s->cache[ch].i1; - s->cache[ch].ri2 = s->cache[ch].i2; - s->cache[ch].ro1 = s->cache[ch].o1; - s->cache[ch].ro2 = s->cache[ch].o2; + s->cache[0]->extended_data[ch], s->clip+ch, ctx->is_disabled); + av_samples_copy(s->cache[1]->extended_data, s->cache[0]->extended_data, 0, 0, + s->cache[0]->nb_samples, s->cache[0]->ch_layout.nb_channels, + s->cache[0]->format); s->filter(s, s->block[0]->extended_data[ch] + s->block_samples * s->block_align, s->block[1]->extended_data[ch] + s->block_samples * s->block_align, - s->block_samples, - &s->cache[ch].ri1, &s->cache[ch].ri2, &s->cache[ch].ro1, &s->cache[ch].ro2, - s->b0, s->b1, s->b2, s->a0, s->a1, s->a2, &s->cache[ch].clippings, ctx->is_disabled); + s->block_samples, s->cache[1]->extended_data[ch], s->clip+ch, + ctx->is_disabled); reverse_samples(s->block[2], s->block[1], ch, 0, 0, 2 * s->block_samples); - s->cache[ch].ri1 = 0.; - s->cache[ch].ri2 = 0.; - s->cache[ch].ro1 = 0.; - s->cache[ch].ro2 = 0.; + av_samples_set_silence(s->cache[1]->extended_data, 0, s->cache[1]->nb_samples, + s->cache[1]->ch_layout.nb_channels, s->cache[1]->format); s->filter(s, s->block[2]->extended_data[ch], s->block[2]->extended_data[ch], 2 * s->block_samples, - &s->cache[ch].ri1, &s->cache[ch].ri2, &s->cache[ch].ro1, &s->cache[ch].ro2, - s->b0, s->b1, s->b2, s->a0, s->a1, s->a2, &s->cache[ch].clippings, ctx->is_disabled); + s->cache[1]->extended_data[ch], s->clip+ch, ctx->is_disabled); reverse_samples(s->block[1], s->block[2], ch, 0, 0, 2 * s->block_samples); memcpy(out_buf->extended_data[ch], s->block[1]->extended_data[ch], s->block_samples * s->block_align); @@ -1309,10 +1332,10 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *buf, int eof) FFMIN(outlink->ch_layout.nb_channels, ff_filter_get_nb_threads(ctx))); for (ch = 0; ch < outlink->ch_layout.nb_channels; ch++) { - if (s->cache[ch].clippings > 0) + if (s->clip[ch] > 0) av_log(ctx, AV_LOG_WARNING, "Channel %d clipping %d times. Please reduce gain.\n", - ch, s->cache[ch].clippings); - s->cache[ch].clippings = 0; + ch, s->clip[ch]); + s->clip[ch] = 0; } if (s->block_samples > 0) { @@ -1402,7 +1425,9 @@ static av_cold void uninit(AVFilterContext *ctx) for (int i = 0; i < 3; i++) av_frame_free(&s->block[i]); - av_freep(&s->cache); + av_frame_free(&s->cache[0]); + av_frame_free(&s->cache[1]); + av_freep(&s->clip); av_channel_layout_uninit(&s->ch_layout); } @@ -1657,12 +1682,12 @@ DEFINE_BIQUAD_FILTER(allpass, "Apply a two-pole all-pass filter."); #endif /* CONFIG_ALLPASS_FILTER */ #if CONFIG_BIQUAD_FILTER static const AVOption biquad_options[] = { - {"a0", NULL, OFFSET(oa0), AV_OPT_TYPE_DOUBLE, {.dbl=1}, INT32_MIN, INT32_MAX, FLAGS}, - {"a1", NULL, OFFSET(oa1), AV_OPT_TYPE_DOUBLE, {.dbl=0}, INT32_MIN, INT32_MAX, FLAGS}, - {"a2", NULL, OFFSET(oa2), AV_OPT_TYPE_DOUBLE, {.dbl=0}, INT32_MIN, INT32_MAX, FLAGS}, - {"b0", NULL, OFFSET(ob0), AV_OPT_TYPE_DOUBLE, {.dbl=0}, INT32_MIN, INT32_MAX, FLAGS}, - {"b1", NULL, OFFSET(ob1), AV_OPT_TYPE_DOUBLE, {.dbl=0}, INT32_MIN, INT32_MAX, FLAGS}, - {"b2", NULL, OFFSET(ob2), AV_OPT_TYPE_DOUBLE, {.dbl=0}, INT32_MIN, INT32_MAX, FLAGS}, + {"a0", NULL, OFFSET(oa[0]), AV_OPT_TYPE_DOUBLE, {.dbl=1}, INT32_MIN, INT32_MAX, FLAGS}, + {"a1", NULL, OFFSET(oa[1]), AV_OPT_TYPE_DOUBLE, {.dbl=0}, INT32_MIN, INT32_MAX, FLAGS}, + {"a2", NULL, OFFSET(oa[2]), AV_OPT_TYPE_DOUBLE, {.dbl=0}, INT32_MIN, INT32_MAX, FLAGS}, + {"b0", NULL, OFFSET(ob[0]), AV_OPT_TYPE_DOUBLE, {.dbl=0}, INT32_MIN, INT32_MAX, FLAGS}, + {"b1", NULL, OFFSET(ob[1]), AV_OPT_TYPE_DOUBLE, {.dbl=0}, INT32_MIN, INT32_MAX, FLAGS}, + {"b2", NULL, OFFSET(ob[2]), AV_OPT_TYPE_DOUBLE, {.dbl=0}, INT32_MIN, INT32_MAX, FLAGS}, MIX_CHANNELS_NORMALIZE_OPTION(1, "all", 0), TRANSFORM_OPTION(DI), PRECISION_OPTION(-1), From 217bb59f2e9a7eb1366496a0b3d34e2f5a26d9cc Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Fri, 5 May 2023 16:04:49 +0200 Subject: [PATCH 0893/2172] avfilter/af_amerge: set output frame duration --- libavfilter/af_amerge.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/libavfilter/af_amerge.c b/libavfilter/af_amerge.c index 8bcc0ac5be9..801e592870d 100644 --- a/libavfilter/af_amerge.c +++ b/libavfilter/af_amerge.c @@ -243,6 +243,10 @@ static int try_push_frame(AVFilterContext *ctx, int nb_samples) outbuf->pts = inbuf[0]->pts; outbuf->nb_samples = nb_samples; + outbuf->duration = av_rescale_q(outbuf->nb_samples, + av_make_q(1, outlink->sample_rate), + outlink->time_base); + if ((ret = av_channel_layout_copy(&outbuf->ch_layout, &outlink->ch_layout)) < 0) return ret; #if FF_API_OLD_CHANNEL_LAYOUT From 67ca64c24bfdb1233ed2f5343232172f8b4b20c6 Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Fri, 5 May 2023 16:49:44 +0200 Subject: [PATCH 0894/2172] avfilter/af_adelay: fix frame pts and set frame duration --- libavfilter/af_adelay.c | 58 +++++++++++++++++++++++++++++------------ 1 file changed, 42 insertions(+), 16 deletions(-) diff --git a/libavfilter/af_adelay.c b/libavfilter/af_adelay.c index 9e63e2d6184..03a4e39842a 100644 --- a/libavfilter/af_adelay.c +++ b/libavfilter/af_adelay.c @@ -44,9 +44,12 @@ typedef struct AudioDelayContext { int block_align; int64_t padding; int64_t max_delay; + int64_t offset; int64_t next_pts; int eof; + AVFrame *input; + void (*delay_channel)(ChanDelay *d, int nb_samples, const uint8_t *src, uint8_t *dst); int (*resize_channel_samples)(ChanDelay *d, int64_t new_delay); @@ -187,6 +190,7 @@ static int config_input(AVFilterLink *inlink) char *p, *saveptr = NULL; int i; + s->next_pts = AV_NOPTS_VALUE; s->chandelay = av_calloc(inlink->ch_layout.nb_channels, sizeof(*s->chandelay)); if (!s->chandelay) return AVERROR(ENOMEM); @@ -224,6 +228,10 @@ static int config_input(AVFilterLink *inlink) d->delay -= s->padding; } + + s->offset = av_rescale_q(s->padding, + av_make_q(1, inlink->sample_rate), + inlink->time_base); } for (i = 0; i < s->nb_delays; i++) { @@ -323,11 +331,16 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *frame) AVFrame *out_frame; int i; - if (ctx->is_disabled || !s->delays) + if (ctx->is_disabled || !s->delays) { + s->input = NULL; return ff_filter_frame(outlink, frame); + } + + s->next_pts = av_rescale_q(frame->pts, inlink->time_base, outlink->time_base); out_frame = ff_get_audio_buffer(outlink, frame->nb_samples); if (!out_frame) { + s->input = NULL; av_frame_free(&frame); return AVERROR(ENOMEM); } @@ -344,9 +357,11 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *frame) s->delay_channel(d, frame->nb_samples, src, dst); } - out_frame->pts = s->next_pts; - s->next_pts += av_rescale_q(frame->nb_samples, (AVRational){1, outlink->sample_rate}, outlink->time_base); + out_frame->pts = s->next_pts + s->offset; + out_frame->duration = av_rescale_q(out_frame->nb_samples, (AVRational){1, outlink->sample_rate}, outlink->time_base); + s->next_pts += out_frame->duration; av_frame_free(&frame); + s->input = NULL; return ff_filter_frame(outlink, out_frame); } @@ -361,6 +376,20 @@ static int activate(AVFilterContext *ctx) FF_FILTER_FORWARD_STATUS_BACK(outlink, inlink); + if (!s->input) { + ret = ff_inlink_consume_frame(inlink, &s->input); + if (ret < 0) + return ret; + } + + if (ff_inlink_acknowledge_status(inlink, &status, &pts)) { + if (status == AVERROR_EOF) + s->eof = 1; + } + + if (s->next_pts == AV_NOPTS_VALUE && pts != AV_NOPTS_VALUE) + s->next_pts = av_rescale_q(pts, inlink->time_base, outlink->time_base); + if (s->padding) { int nb_samples = FFMIN(s->padding, 2048); @@ -374,24 +403,17 @@ static int activate(AVFilterContext *ctx) outlink->ch_layout.nb_channels, frame->format); + frame->duration = av_rescale_q(frame->nb_samples, + (AVRational){1, outlink->sample_rate}, + outlink->time_base); frame->pts = s->next_pts; - if (s->next_pts != AV_NOPTS_VALUE) - s->next_pts += av_rescale_q(nb_samples, (AVRational){1, outlink->sample_rate}, outlink->time_base); + s->next_pts += frame->duration; return ff_filter_frame(outlink, frame); } - ret = ff_inlink_consume_frame(inlink, &frame); - if (ret < 0) - return ret; - - if (ret > 0) - return filter_frame(inlink, frame); - - if (ff_inlink_acknowledge_status(inlink, &status, &pts)) { - if (status == AVERROR_EOF) - s->eof = 1; - } + if (s->input) + return filter_frame(inlink, s->input); if (s->eof && s->max_delay) { int nb_samples = FFMIN(s->max_delay, 2048); @@ -406,7 +428,11 @@ static int activate(AVFilterContext *ctx) outlink->ch_layout.nb_channels, frame->format); + frame->duration = av_rescale_q(frame->nb_samples, + (AVRational){1, outlink->sample_rate}, + outlink->time_base); frame->pts = s->next_pts; + s->next_pts += frame->duration; return filter_frame(inlink, frame); } From 24f16b798e9bcd1090c47e64b53ec5c62c4f3f0a Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Fri, 5 May 2023 16:07:07 +0200 Subject: [PATCH 0895/2172] avfilter/af_join: set output frame duration --- libavfilter/af_join.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/libavfilter/af_join.c b/libavfilter/af_join.c index dc075a8b27d..605d73d2ccb 100644 --- a/libavfilter/af_join.c +++ b/libavfilter/af_join.c @@ -520,6 +520,10 @@ static int try_push_frame(AVFilterContext *ctx) } frame->nb_samples = nb_samples; + frame->duration = av_rescale_q(frame->nb_samples, + av_make_q(1, outlink->sample_rate), + outlink->time_base); + #if FF_API_OLD_CHANNEL_LAYOUT FF_DISABLE_DEPRECATION_WARNINGS frame->channel_layout = outlink->channel_layout; From 09b2ca93b4aa7cb24eeebdc829be61077466f021 Mon Sep 17 00:00:00 2001 From: James Almer Date: Tue, 18 Apr 2023 21:07:29 -0300 Subject: [PATCH 0896/2172] avcodec/libdav1d: support parsing multiple ITU-T T.35 entries in a picture This requires the newest libdav1d release. Signed-off-by: James Almer --- libavcodec/libdav1d.c | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/libavcodec/libdav1d.c b/libavcodec/libdav1d.c index 87aed167499..af072da6815 100644 --- a/libavcodec/libdav1d.c +++ b/libavcodec/libdav1d.c @@ -514,10 +514,16 @@ FF_ENABLE_DEPRECATION_WARNINGS light->MaxFALL = p->content_light->max_frame_average_light_level; } if (p->itut_t35) { +#if FF_DAV1D_VERSION_AT_LEAST(6,9) + for (size_t i = 0; i < p->n_itut_t35; i++) { + const Dav1dITUTT35 *itut_t35 = &p->itut_t35[i]; +#else + const Dav1dITUTT35 *itut_t35 = p->itut_t35; +#endif GetByteContext gb; int provider_code; - bytestream2_init(&gb, p->itut_t35->payload, p->itut_t35->payload_size); + bytestream2_init(&gb, itut_t35->payload, itut_t35->payload_size); provider_code = bytestream2_get_be16(&gb); switch (provider_code) { @@ -549,7 +555,7 @@ FF_ENABLE_DEPRECATION_WARNINGS int provider_oriented_code = bytestream2_get_be16(&gb); int application_identifier = bytestream2_get_byte(&gb); - if (p->itut_t35->country_code != 0xB5 || + if (itut_t35->country_code != 0xB5 || provider_oriented_code != 1 || application_identifier != 4) break; @@ -568,6 +574,9 @@ FF_ENABLE_DEPRECATION_WARNINGS default: // ignore unsupported provider codes break; } +#if FF_DAV1D_VERSION_AT_LEAST(6,9) + } +#endif } if (p->frame_hdr->film_grain.present && (!dav1d->apply_grain || (c->export_side_data & AV_CODEC_EXPORT_DATA_FILM_GRAIN))) { From ed3691338b25108517d354dda7f6c930fec5471c Mon Sep 17 00:00:00 2001 From: James Almer Date: Fri, 5 May 2023 15:26:19 -0300 Subject: [PATCH 0897/2172] doc/examples/transcode_aac: use av_samples_alloc_array_and_samples to allocate the input samples buffer and pointers Fixes -Wuse-after-free warnings and simplifies code. Signed-off-by: James Almer --- doc/examples/transcode_aac.c | 20 +++++--------------- 1 file changed, 5 insertions(+), 15 deletions(-) diff --git a/doc/examples/transcode_aac.c b/doc/examples/transcode_aac.c index bb5681a7c0a..cf6edc98907 100644 --- a/doc/examples/transcode_aac.c +++ b/doc/examples/transcode_aac.c @@ -447,26 +447,17 @@ static int init_converted_samples(uint8_t ***converted_input_samples, int error; /* Allocate as many pointers as there are audio channels. - * Each pointer will later point to the audio samples of the corresponding + * Each pointer will point to the audio samples of the corresponding * channels (although it may be NULL for interleaved formats). - */ - if (!(*converted_input_samples = calloc(output_codec_context->ch_layout.nb_channels, - sizeof(**converted_input_samples)))) { - fprintf(stderr, "Could not allocate converted input sample pointers\n"); - return AVERROR(ENOMEM); - } - - /* Allocate memory for the samples of all channels in one consecutive + * Allocate memory for the samples of all channels in one consecutive * block for convenience. */ - if ((error = av_samples_alloc(*converted_input_samples, NULL, + if ((error = av_samples_alloc_array_and_samples(converted_input_samples, NULL, output_codec_context->ch_layout.nb_channels, frame_size, output_codec_context->sample_fmt, 0)) < 0) { fprintf(stderr, "Could not allocate converted input samples (error '%s')\n", av_err2str(error)); - av_freep(&(*converted_input_samples)[0]); - free(*converted_input_samples); return error; } return 0; @@ -598,10 +589,9 @@ static int read_decode_convert_and_store(AVAudioFifo *fifo, ret = 0; cleanup: - if (converted_input_samples) { + if (converted_input_samples) av_freep(&converted_input_samples[0]); - free(converted_input_samples); - } + av_freep(&converted_input_samples); av_frame_free(&input_frame); return ret; From 5cc378cc466121fc9de1657ea76deeba9f92089a Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Tue, 2 May 2023 01:55:34 +0200 Subject: [PATCH 0898/2172] avcodec/pdvdec: Check previous frame before using it Fixes: load of null pointer of type 'uint8_t' (aka 'unsigned char') Fixes: 58256/clusterfuzz-testcase-minimized-ffmpeg_AV_CODEC_ID_PDV_fuzzer-4776436325285888 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 --- libavcodec/pdvdec.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavcodec/pdvdec.c b/libavcodec/pdvdec.c index 3ac2f98b3d9..d50c4e729c8 100644 --- a/libavcodec/pdvdec.c +++ b/libavcodec/pdvdec.c @@ -93,7 +93,7 @@ static int decode_frame(AVCodecContext *avctx, AVFrame *frame, return AVERROR_INVALIDDATA; } - if (!(avpkt->flags & AV_PKT_FLAG_KEY)) { + if (prev && !(avpkt->flags & AV_PKT_FLAG_KEY)) { for (int j = 0; j < (avctx->width + 7) >> 3; j++) dst[j] ^= prev[j]; prev += prev_frame->linesize[0]; From 6b1f68ccb04d791f0250e05687c346a99ff47ea1 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Wed, 3 May 2023 13:08:35 +0200 Subject: [PATCH 0899/2172] avformat/hls: fail on probing non hls/m3u8 file extensions Its unexpected that a .avi or other "standard" file turns into a playlist. The goal of this patch is to avoid this unexpected behavior and possible privacy or security differences. Reviewed-by: Steven Liu Signed-off-by: Michael Niedermayer --- libavformat/hls.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/libavformat/hls.c b/libavformat/hls.c index 8a96a37ff9b..11e345b2803 100644 --- a/libavformat/hls.c +++ b/libavformat/hls.c @@ -2532,8 +2532,15 @@ static int hls_probe(const AVProbeData *p) if (strstr(p->buf, "#EXT-X-STREAM-INF:") || strstr(p->buf, "#EXT-X-TARGETDURATION:") || - strstr(p->buf, "#EXT-X-MEDIA-SEQUENCE:")) + strstr(p->buf, "#EXT-X-MEDIA-SEQUENCE:")) { + + if (!av_match_ext(p->filename, "m3u8,hls,m3u")) { + av_log(NULL, AV_LOG_ERROR, "Not detecting m3u8/hls with non standard extension\n"); + return 0; + } + return AVPROBE_SCORE_MAX; + } return 0; } From 7117b380a7eb9419625aa8835edec2c3c17e638b Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Sun, 16 Apr 2023 15:05:47 +0200 Subject: [PATCH 0900/2172] avcodec/pngdec: remove AVFrame argument from decode_iccp_chunk() Signed-off-by: Michael Niedermayer --- libavcodec/pngdec.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libavcodec/pngdec.c b/libavcodec/pngdec.c index 83db0ad66dd..81c9892d35b 100644 --- a/libavcodec/pngdec.c +++ b/libavcodec/pngdec.c @@ -972,7 +972,7 @@ static int decode_trns_chunk(AVCodecContext *avctx, PNGDecContext *s, return 0; } -static int decode_iccp_chunk(PNGDecContext *s, GetByteContext *gb, AVFrame *f) +static int decode_iccp_chunk(PNGDecContext *s, GetByteContext *gb) { int ret, cnt = 0; AVBPrint bp; @@ -1466,7 +1466,7 @@ static int decode_frame_common(AVCodecContext *avctx, PNGDecContext *s, s->have_srgb = 1; break; case MKTAG('i', 'C', 'C', 'P'): { - if ((ret = decode_iccp_chunk(s, &gb_chunk, p)) < 0) + if ((ret = decode_iccp_chunk(s, &gb_chunk)) < 0) goto fail; break; } From d31d4f32283f765c79d6e127d31ee2c37a0acef7 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Sun, 16 Apr 2023 15:06:59 +0200 Subject: [PATCH 0901/2172] avcodec/pngdec: Do not pass AVFrame into global header decode The global header should not contain a frame, and decoding it would result in leaks Fixes: memleak Fixes: 45982/clusterfuzz-testcase-minimized-ffmpeg_AV_CODEC_ID_APNG_fuzzer-6603443149340672 Found-by: continuous fuzzing process https://github.com/google/oss-fuzz/tree/master/projects/ffmpeg Signed-off-by: Michael Niedermayer --- libavcodec/pngdec.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/libavcodec/pngdec.c b/libavcodec/pngdec.c index 81c9892d35b..0369d1c449f 100644 --- a/libavcodec/pngdec.c +++ b/libavcodec/pngdec.c @@ -734,6 +734,8 @@ static int decode_idat_chunk(AVCodecContext *avctx, PNGDecContext *s, int ret; size_t byte_depth = s->bit_depth > 8 ? 2 : 1; + if (!p) + return AVERROR_INVALIDDATA; if (!(s->hdr_state & PNG_IHDR)) { av_log(avctx, AV_LOG_ERROR, "IDAT without IHDR\n"); return AVERROR_INVALIDDATA; @@ -1515,6 +1517,9 @@ static int decode_frame_common(AVCodecContext *avctx, PNGDecContext *s, } exit_loop: + if (!p) + return AVERROR_INVALIDDATA; + if (avctx->codec_id == AV_CODEC_ID_PNG && avctx->skip_frame == AVDISCARD_ALL) { return 0; @@ -1727,7 +1732,7 @@ static int decode_frame_apng(AVCodecContext *avctx, AVFrame *p, if ((ret = inflateReset(&s->zstream.zstream)) != Z_OK) return AVERROR_EXTERNAL; bytestream2_init(&s->gb, avctx->extradata, avctx->extradata_size); - if ((ret = decode_frame_common(avctx, s, p, avpkt)) < 0) + if ((ret = decode_frame_common(avctx, s, NULL, avpkt)) < 0) return ret; } From 885ff3b8798791eb2b0f53360a2ab4b1f9c5f6dc Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Sun, 16 Apr 2023 15:18:45 +0200 Subject: [PATCH 0902/2172] avcodec/exr: Cleanup befor return Fixes: leaks Fixes: 45982/clusterfuzz-testcase-minimized-ffmpeg_AV_CODEC_ID_EXR_fuzzer-6703454090559488 Found-by: continuous fuzzing process https://github.com/google/oss-fuzz/tree/master/projects/ffmpeg Signed-off-by: Michael Niedermayer --- libavcodec/exr.c | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/libavcodec/exr.c b/libavcodec/exr.c index 2f1766c17bf..8cc6b056b29 100644 --- a/libavcodec/exr.c +++ b/libavcodec/exr.c @@ -1930,8 +1930,10 @@ static int decode_header(EXRContext *s, AVFrame *frame) bytestream2_get_buffer(gb, key, FFMIN(sizeof(key) - 1, var_size)); if (strncmp("scanlineimage", key, var_size) && - strncmp("tiledimage", key, var_size)) - return AVERROR_PATCHWELCOME; + strncmp("tiledimage", key, var_size)) { + ret = AVERROR_PATCHWELCOME; + goto fail; + } continue; } else if ((var_size = check_header_variable(s, "preview", @@ -1939,12 +1941,16 @@ static int decode_header(EXRContext *s, AVFrame *frame) uint32_t pw = bytestream2_get_le32(gb); uint32_t ph = bytestream2_get_le32(gb); uint64_t psize = pw * ph; - if (psize > INT64_MAX / 4) - return AVERROR_INVALIDDATA; + if (psize > INT64_MAX / 4) { + ret = AVERROR_INVALIDDATA; + goto fail; + } psize *= 4; - if ((int64_t)psize >= bytestream2_get_bytes_left(gb)) - return AVERROR_INVALIDDATA; + if ((int64_t)psize >= bytestream2_get_bytes_left(gb)) { + ret = AVERROR_INVALIDDATA; + goto fail; + } bytestream2_skip(gb, psize); From fd7352660be0211aabb11dc6d586836515772f81 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Sun, 16 Apr 2023 15:24:16 +0200 Subject: [PATCH 0903/2172] avcodec/flacdec: Fix signed integre overflow Fixes: signed integer overflow: 3011809745540902265 + 6323452730883571725 cannot be represented in type 'long' Fixes: 45982/clusterfuzz-testcase-minimized-ffmpeg_AV_CODEC_ID_FLAC_fuzzer-6687553022722048 Found-by: continuous fuzzing process https://github.com/google/oss-fuzz/tree/master/projects/ffmpeg Signed-off-by: Michael Niedermayer --- libavcodec/flacdec.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavcodec/flacdec.c b/libavcodec/flacdec.c index cc778a8dff1..524a0469495 100644 --- a/libavcodec/flacdec.c +++ b/libavcodec/flacdec.c @@ -513,7 +513,7 @@ static int decode_subframe_lpc_33bps(FLACContext *s, int64_t *decoded, for (i = pred_order; i < s->blocksize; i++, decoded++) { int64_t sum = 0; for (j = 0; j < pred_order; j++) - sum += (int64_t)coeffs[j] * decoded[j]; + sum += (int64_t)coeffs[j] * (uint64_t)decoded[j]; decoded[j] = residual[i] + (sum >> qlevel); } From 34056a94eab5f8fbc7e0b8510f7c9851931f23b7 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Sun, 16 Apr 2023 16:56:40 +0200 Subject: [PATCH 0904/2172] avcodec/utils: the IFF_ILBM implementation assumes that there are a multiple of 16 allocated Fixes: out of array access Fixes: 45982/clusterfuzz-testcase-minimized-ffmpeg_AV_CODEC_ID_IFF_ILBM_fuzzer-5124452659888128 Fixes: 45982/clusterfuzz-testcase-minimized-ffmpeg_AV_CODEC_ID_IFF_ILBM_fuzzer-6362836707442688 Found-by: continuous fuzzing process https://github.com/google/oss-fuzz/tree/master/projects/ffmpeg Signed-off-by: Michael Niedermayer --- libavcodec/utils.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavcodec/utils.c b/libavcodec/utils.c index 599da21dba2..ef1845954e8 100644 --- a/libavcodec/utils.c +++ b/libavcodec/utils.c @@ -317,7 +317,7 @@ void avcodec_align_dimensions2(AVCodecContext *s, int *width, int *height, } if (s->codec_id == AV_CODEC_ID_IFF_ILBM) { - w_align = FFMAX(w_align, 8); + w_align = FFMAX(w_align, 16); } *width = FFALIGN(*width, w_align); From 2632e9049391d820bde64d1fc138567a66464fcd Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Sun, 16 Apr 2023 17:19:10 +0200 Subject: [PATCH 0905/2172] avcodec/sonic: Fix two undefined integer overflows Fixes: signed integer overflow: 2147483372 - -148624 cannot be represented in type 'int' Fixes: 45982/clusterfuzz-testcase-minimized-ffmpeg_AV_CODEC_ID_SONIC_fuzzer-5477177805373440 Fixes: 45982/clusterfuzz-testcase-minimized-ffmpeg_AV_CODEC_ID_SONIC_fuzzer-6681622236233728 Found-by: continuous fuzzing process https://github.com/google/oss-fuzz/tree/master/projects/ffmpeg Signed-off-by: Michael Niedermayer --- libavcodec/sonic.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libavcodec/sonic.c b/libavcodec/sonic.c index 62e6193ac63..0544fecf469 100644 --- a/libavcodec/sonic.c +++ b/libavcodec/sonic.c @@ -473,7 +473,7 @@ static void predictor_init_state(int *k, int *state, int order) static int predictor_calc_error(int *k, int *state, int order, int error) { - int i, x = error - shift_down(k[order-1] * (unsigned)state[order-1], LATTICE_SHIFT); + int i, x = error - (unsigned)shift_down(k[order-1] * (unsigned)state[order-1], LATTICE_SHIFT); #if 1 int *k_ptr = &(k[order-2]), @@ -1013,7 +1013,7 @@ static int sonic_decode_frame(AVCodecContext *avctx, AVFrame *frame, if (s->lossless) quant = 1; else - quant = get_symbol(&c, state, 0) * SAMPLE_FACTOR; + quant = get_symbol(&c, state, 0) * (unsigned)SAMPLE_FACTOR; // av_log(NULL, AV_LOG_INFO, "quant: %d\n", quant); From 19b66b89da4b4ff086dc1fc79bbf540e82bdbcb4 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Sun, 16 Apr 2023 17:34:16 +0200 Subject: [PATCH 0906/2172] avcodec/tak: Check remaining bits in ff_tak_decode_frame_header() Fixes: out of array access Fixes: 45982/clusterfuzz-testcase-minimized-ffmpeg_AV_CODEC_ID_TAK_fuzzer-6682195323650048 Found-by: continuous fuzzing process https://github.com/google/oss-fuzz/tree/master/projects/ffmpeg Signed-off-by: Michael Niedermayer --- libavcodec/tak.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/libavcodec/tak.c b/libavcodec/tak.c index 628609b71b1..99678e98878 100644 --- a/libavcodec/tak.c +++ b/libavcodec/tak.c @@ -175,6 +175,9 @@ int ff_tak_decode_frame_header(AVCodecContext *avctx, GetBitContext *gb, if (ti->flags & TAK_FRAME_FLAG_HAS_METADATA) return AVERROR_INVALIDDATA; + if (get_bits_left(gb) < 24) + return AVERROR_INVALIDDATA; + skip_bits(gb, 24); return 0; From 6e98cf0280cd693ef82c4444fe15bc7aef8771b3 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Sun, 16 Apr 2023 17:38:39 +0200 Subject: [PATCH 0907/2172] avcodec/tiff: add a zero DNG_LINEARIZATION_TABLE check Fixes: index 4294967295 out of bounds for type 'uint16_t [65536]' Fixes: 45982/clusterfuzz-testcase-minimized-ffmpeg_AV_CODEC_ID_TIFF_fuzzer-5950405086674944 Fixes: 45982/clusterfuzz-testcase-minimized-ffmpeg_AV_CODEC_ID_TIFF_fuzzer-6666195176914944 Found-by: continuous fuzzing process https://github.com/google/oss-fuzz/tree/master/projects/ffmpeg Signed-off-by: Michael Niedermayer --- libavcodec/tiff.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavcodec/tiff.c b/libavcodec/tiff.c index 560cb3e5b33..148964590bc 100644 --- a/libavcodec/tiff.c +++ b/libavcodec/tiff.c @@ -1451,7 +1451,7 @@ static int tiff_decode_tag(TiffContext *s, AVFrame *frame) break; case TIFF_GRAY_RESPONSE_CURVE: case DNG_LINEARIZATION_TABLE: - if (count > FF_ARRAY_ELEMS(s->dng_lut)) + if (count < 1 || count > FF_ARRAY_ELEMS(s->dng_lut)) return AVERROR_INVALIDDATA; for (int i = 0; i < count; i++) s->dng_lut[i] = ff_tget(&s->gb, type, s->le); From 8f0e200a12c25e288acd31eff0a5000bc74aa34e Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Sun, 16 Apr 2023 17:45:41 +0200 Subject: [PATCH 0908/2172] avcodec/dpcm: fix undefined interger overflow in wady Fixes: signed integer overflow: -2147375930 + -133875 cannot be represented in type 'int' Fixes: 45982/clusterfuzz-testcase-minimized-ffmpeg_AV_CODEC_ID_WADY_DPCM_fuzzer-6703727013920768 Found-by: continuous fuzzing process https://github.com/google/oss-fuzz/tree/master/projects/ffmpeg Signed-off-by: Michael Niedermayer --- libavcodec/dpcm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavcodec/dpcm.c b/libavcodec/dpcm.c index 6ea9e2c0650..eff6587404d 100644 --- a/libavcodec/dpcm.c +++ b/libavcodec/dpcm.c @@ -444,7 +444,7 @@ static int dpcm_decode_frame(AVCodecContext *avctx, AVFrame *frame, if (n & 0x80) s->sample[idx] = sign_extend((n & 0x7f) << 9, 16); else - s->sample[idx] += s->scale * wady_table[n & 0x7f]; + s->sample[idx] += s->scale * (unsigned)wady_table[n & 0x7f]; *output_samples++ = av_clip_int16(s->sample[idx]); idx ^= stereo; } From 722ff740550769035ecc7e41fabb6801d6d7b992 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Sun, 16 Apr 2023 13:52:32 +0200 Subject: [PATCH 0909/2172] avcodec/adpcm: Fix integer overflow in intermediate in ADPCM_XMD Fixes: runtime error: signed integer overflow: 2140143616 + 254665816 cannot be represented in type 'int' Fixes: 45982/clusterfuzz-testcase-minimized-ffmpeg_AV_CODEC_ID_ADPCM_XMD_fuzzer-6690181676924928 As a sideeffect this simplifies the equation, the high bits are different after this but only the low 16bits are stored and used in later steps. 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 --- libavcodec/adpcm.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libavcodec/adpcm.c b/libavcodec/adpcm.c index 451696932d1..59b9ef34971 100644 --- a/libavcodec/adpcm.c +++ b/libavcodec/adpcm.c @@ -1579,11 +1579,11 @@ static int adpcm_decode_frame(AVCodecContext *avctx, AVFrame *frame, nibble[0] = sign_extend(byte & 15, 4); nibble[1] = sign_extend(byte >> 4, 4); - out[2+n*2] = (nibble[0]*(scale<<14) + (history[0]*29336) - (history[1]*13136)) >> 14; + out[2+n*2] = nibble[0]*scale + ((history[0]*3667 - history[1]*1642) >> 11); history[1] = history[0]; history[0] = out[2+n*2]; - out[2+n*2+1] = (nibble[1]*(scale<<14) + (history[0]*29336) - (history[1]*13136)) >> 14; + out[2+n*2+1] = nibble[1]*scale + ((history[0]*3667 - history[1]*1642) >> 11); history[1] = history[0]; history[0] = out[2+n*2+1]; } From 0c913272103633bbfb189d28f31892ccd9ea9aa5 Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Sat, 6 May 2023 17:47:36 +0200 Subject: [PATCH 0910/2172] avfilter/vsrc_gradients: fix several issues with !rgba output --- libavfilter/vsrc_gradients.c | 37 +++++++++++++++++++----------------- 1 file changed, 20 insertions(+), 17 deletions(-) diff --git a/libavfilter/vsrc_gradients.c b/libavfilter/vsrc_gradients.c index 98c38f85514..25a3d53238e 100644 --- a/libavfilter/vsrc_gradients.c +++ b/libavfilter/vsrc_gradients.c @@ -111,13 +111,13 @@ static uint64_t lerp_color16(uint8_t c0[4], uint8_t c1[4], float x) { const float y = 1.f - x; - return (llrintf((c0[0] * y + c1[0] * x) * 256)) << 0 | - (llrintf((c0[1] * y + c1[1] * x) * 256)) << 16 | - (llrintf((c0[2] * y + c1[2] * x) * 256)) << 32 | - (llrintf((c0[3] * y + c1[3] * x) * 256)) << 48; + return ((uint64_t)llrintf((c0[0] * y + c1[0] * x) * 256)) << 0 | + ((uint64_t)llrintf((c0[1] * y + c1[1] * x) * 256)) << 16 | + ((uint64_t)llrintf((c0[2] * y + c1[2] * x) * 256)) << 32 | + ((uint64_t)llrintf((c0[3] * y + c1[3] * x) * 256)) << 48; } -static uint32_t lerp_colors(uint8_t arr[3][4], int nb_colors, int nb_wrap_colors, float step) +static uint32_t lerp_colors(uint8_t arr[8][4], int nb_colors, int nb_wrap_colors, float step) { float scl; int i, j; @@ -140,7 +140,7 @@ static uint32_t lerp_colors(uint8_t arr[3][4], int nb_colors, int nb_wrap_colors return lerp_color(arr[i], arr[j], scl - i); } -static uint64_t lerp_colors16(uint8_t arr[3][4], int nb_colors, int nb_wrap_colors, float step) +static uint64_t lerp_colors16(uint8_t arr[8][4], int nb_colors, int nb_wrap_colors, float step) { float scl; int i, j; @@ -163,7 +163,7 @@ static uint64_t lerp_colors16(uint8_t arr[3][4], int nb_colors, int nb_wrap_colo return lerp_color16(arr[i], arr[j], scl - i); } -static void lerp_colors32(float arr[3][4], int nb_colors, +static void lerp_colors32(float arr[8][4], int nb_colors, int nb_wrap_colors, float step, float *r, float *g, float *b, float *a) { @@ -187,12 +187,12 @@ static void lerp_colors32(float arr[3][4], int nb_colors, scl = step * (nb_wrap_colors - 1); i = floorf(scl); - x = scl - i; j = i + 1; if (i >= nb_colors - 1) { i = nb_colors - 1; j = 0; } + x = scl - i; *r = lerpf(arr[i][0], arr[j][0], x); *g = lerpf(arr[i][1], arr[j][1], x); @@ -253,11 +253,12 @@ static int draw_gradients_slice(AVFilterContext *ctx, void *arg, int job, int nb const int end = (height * (job+1)) / nb_jobs; const int linesize = frame->linesize[0] / 4; uint32_t *dst = (uint32_t *)frame->data[0] + start * linesize; + const int type = s->type; for (int y = start; y < end; y++) { for (int x = 0; x < width; x++) { - float factor = project(s->fx0, s->fy0, s->fx1, s->fy1, x, y, s->type); - dst[x] = lerp_colors(s->color_rgba, s->nb_colors, s->nb_colors + (s->type >= 2), factor); + float factor = project(s->fx0, s->fy0, s->fx1, s->fy1, x, y, type); + dst[x] = lerp_colors(s->color_rgba, s->nb_colors, s->nb_colors + (type >= 2), factor); } dst += linesize; @@ -276,11 +277,12 @@ static int draw_gradients_slice16(AVFilterContext *ctx, void *arg, int job, int const int end = (height * (job+1)) / nb_jobs; const int linesize = frame->linesize[0] / 8; uint64_t *dst = (uint64_t *)frame->data[0] + start * linesize; + const int type = s->type; for (int y = start; y < end; y++) { for (int x = 0; x < width; x++) { - float factor = project(s->fx0, s->fy0, s->fx1, s->fy1, x, y, s->type); - dst[x] = lerp_colors16(s->color_rgba, s->nb_colors, s->nb_colors + s->type >= 2, factor); + float factor = project(s->fx0, s->fy0, s->fx1, s->fy1, x, y, type); + dst[x] = lerp_colors16(s->color_rgba, s->nb_colors, s->nb_colors + (type >= 2), factor); } dst += linesize; @@ -302,14 +304,15 @@ static int draw_gradients_slice32_planar(AVFilterContext *ctx, void *arg, int jo const int linesize_r = frame->linesize[2] / 4; const int linesize_a = frame->linesize[3] / 4; float *dst_g = (float *)frame->data[0] + start * linesize_g; - float *dst_b = (float *)frame->data[0] + start * linesize_b; - float *dst_r = (float *)frame->data[0] + start * linesize_r; - float *dst_a = (float *)frame->data[0] + start * linesize_a; + float *dst_b = (float *)frame->data[1] + start * linesize_b; + float *dst_r = (float *)frame->data[2] + start * linesize_r; + float *dst_a = (float *)frame->data[3] + start * linesize_a; + const int type = s->type; for (int y = start; y < end; y++) { for (int x = 0; x < width; x++) { - float factor = project(s->fx0, s->fy0, s->fx1, s->fy1, x, y, s->type); - lerp_colors32(s->color_rgbaf, s->nb_colors, s->nb_colors + s->type >= 2 ,factor, + float factor = project(s->fx0, s->fy0, s->fx1, s->fy1, x, y, type); + lerp_colors32(s->color_rgbaf, s->nb_colors, s->nb_colors + (type >= 2), factor, &dst_r[x], &dst_g[x], &dst_b[x], &dst_a[x]); } From 55ea1da1c0fb3d04878d38c668ec159c2f45f06e Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Sat, 6 May 2023 17:50:05 +0200 Subject: [PATCH 0911/2172] avfilter/adynamicequalizer_template: remove empty lines --- libavfilter/adynamicequalizer_template.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/libavfilter/adynamicequalizer_template.c b/libavfilter/adynamicequalizer_template.c index ab180a9b9da..a6b35aa93e3 100644 --- a/libavfilter/adynamicequalizer_template.c +++ b/libavfilter/adynamicequalizer_template.c @@ -266,5 +266,3 @@ static int fn(filter_channels)(AVFilterContext *ctx, void *arg, int jobnr, int n return 0; } - - From c2ae8e30b7f3629b097eb0db89e509756ed923e8 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Mon, 1 May 2023 13:35:18 +0200 Subject: [PATCH 0912/2172] lavc/codec_par: add AVCodecParameters.framerate This corresponds to AVCodecContext.framerate. --- doc/APIchanges | 3 +++ libavcodec/codec_par.c | 3 +++ libavcodec/codec_par.h | 12 ++++++++++++ libavcodec/version.h | 2 +- 4 files changed, 19 insertions(+), 1 deletion(-) diff --git a/doc/APIchanges b/doc/APIchanges index fd01def1b27..20ab4709e7a 100644 --- a/doc/APIchanges +++ b/doc/APIchanges @@ -2,6 +2,9 @@ The last version increases of all libraries were on 2023-02-09 API changes, most recent first: +2023-05-xx - xxxxxxxxxx - lavc 60.11.100 - codec_par.h + Add AVCodecParameters.framerate. + 2023-05-04 - xxxxxxxxxx - lavu 58.7.100 - frame.h Deprecate AVFrame.interlaced_frame, AVFrame.top_field_first, and AVFrame.key_frame. diff --git a/libavcodec/codec_par.c b/libavcodec/codec_par.c index abda649aa88..775c187073f 100644 --- a/libavcodec/codec_par.c +++ b/libavcodec/codec_par.c @@ -46,6 +46,7 @@ static void codec_parameters_reset(AVCodecParameters *par) par->color_space = AVCOL_SPC_UNSPECIFIED; par->chroma_location = AVCHROMA_LOC_UNSPECIFIED; par->sample_aspect_ratio = (AVRational){ 0, 1 }; + par->framerate = (AVRational){ 0, 1 }; par->profile = FF_PROFILE_UNKNOWN; par->level = FF_LEVEL_UNKNOWN; } @@ -126,6 +127,7 @@ int avcodec_parameters_from_context(AVCodecParameters *par, par->chroma_location = codec->chroma_sample_location; par->sample_aspect_ratio = codec->sample_aspect_ratio; par->video_delay = codec->has_b_frames; + par->framerate = codec->framerate; break; case AVMEDIA_TYPE_AUDIO: par->format = codec->sample_fmt; @@ -207,6 +209,7 @@ int avcodec_parameters_to_context(AVCodecContext *codec, codec->chroma_sample_location = par->chroma_location; codec->sample_aspect_ratio = par->sample_aspect_ratio; codec->has_b_frames = par->video_delay; + codec->framerate = par->framerate; break; case AVMEDIA_TYPE_AUDIO: codec->sample_fmt = par->format; diff --git a/libavcodec/codec_par.h b/libavcodec/codec_par.h index f51d27c5908..add90fdb1e6 100644 --- a/libavcodec/codec_par.h +++ b/libavcodec/codec_par.h @@ -211,6 +211,18 @@ typedef struct AVCodecParameters { * Audio only. The channel layout and number of channels. */ AVChannelLayout ch_layout; + + /** + * Video only. Number of frames per second, for streams with constant frame + * durations. Should be set to { 0, 1 } when some frames have differing + * durations or if the value is not known. + * + * @note This field correponds to values that are stored in codec-level + * headers and is typically overridden by container/transport-layer + * timestamps, when available. It should thus be used only as a last resort, + * when no higher-level timing information is available. + */ + AVRational framerate; } AVCodecParameters; /** diff --git a/libavcodec/version.h b/libavcodec/version.h index 80e2ae630df..8b53586be1d 100644 --- a/libavcodec/version.h +++ b/libavcodec/version.h @@ -29,7 +29,7 @@ #include "version_major.h" -#define LIBAVCODEC_VERSION_MINOR 10 +#define LIBAVCODEC_VERSION_MINOR 11 #define LIBAVCODEC_VERSION_MICRO 100 #define LIBAVCODEC_VERSION_INT AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \ From 6deaf1e40949b1daa2dfe23e9643e1758f52d29c Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Mon, 1 May 2023 14:03:56 +0200 Subject: [PATCH 0913/2172] lavf/demux: export codec-level framerate in avformat_find_stream_info() --- libavformat/demux.c | 1 + 1 file changed, 1 insertion(+) diff --git a/libavformat/demux.c b/libavformat/demux.c index 45e5f5c4c2a..2a32bde7f5e 100644 --- a/libavformat/demux.c +++ b/libavformat/demux.c @@ -2878,6 +2878,7 @@ int avformat_find_stream_info(AVFormatContext *ic, AVDictionary **options) st->r_frame_rate.den = st->time_base.num; } } + st->codecpar->framerate = avctx->framerate; if (sti->display_aspect_ratio.num && sti->display_aspect_ratio.den) { AVRational hw_ratio = { avctx->height, avctx->width }; st->sample_aspect_ratio = av_mul_q(sti->display_aspect_ratio, From 2ae16b05d62f50ba3719af3c279db1109240a74b Mon Sep 17 00:00:00 2001 From: Davy Durham Date: Tue, 2 May 2023 13:35:34 +0200 Subject: [PATCH 0914/2172] fftools/ffmpeg: add ability to set a input burst time before readrate is enforced Signed-off-by: Anton Khirnov --- Changelog | 1 + doc/ffmpeg.texi | 3 +++ fftools/ffmpeg.h | 1 + fftools/ffmpeg_demux.c | 18 +++++++++++++++++- fftools/ffmpeg_opt.c | 3 +++ 5 files changed, 25 insertions(+), 1 deletion(-) diff --git a/Changelog b/Changelog index 4901ef6ad71..2061aaf4623 100644 --- a/Changelog +++ b/Changelog @@ -7,6 +7,7 @@ version : - Extend VAAPI support for libva-win32 on Windows - afireqsrc audio source filter - arls filter +- ffmpeg CLI new option: -readrate_initial_burst version 6.0: - Radiance HDR image support diff --git a/doc/ffmpeg.texi b/doc/ffmpeg.texi index 0fea0bacb14..a12700e2f33 100644 --- a/doc/ffmpeg.texi +++ b/doc/ffmpeg.texi @@ -1708,6 +1708,9 @@ it may cause packet loss. It is useful for when flow speed of output packets is important, such as live streaming. @item -re (@emph{input}) Read input at native frame rate. This is equivalent to setting @code{-readrate 1}. +@item -readrate_initial_burst @var{seconds} +Set an initial read burst time, in seconds, after which @option{-re/-readrate} +will be enforced. @item -vsync @var{parameter} (@emph{global}) @itemx -fps_mode[:@var{stream_specifier}] @var{parameter} (@emph{output,per-stream}) Set video sync method / framerate mode. vsync is applied to all output video streams diff --git a/fftools/ffmpeg.h b/fftools/ffmpeg.h index b6389d7f99e..a03a6b0302c 100644 --- a/fftools/ffmpeg.h +++ b/fftools/ffmpeg.h @@ -126,6 +126,7 @@ typedef struct OptionsContext { int loop; int rate_emu; float readrate; + double readrate_initial_burst; int accurate_seek; int thread_queue_size; int input_sync_ref; diff --git a/fftools/ffmpeg_demux.c b/fftools/ffmpeg_demux.c index 26426c7ac16..37d7649da9f 100644 --- a/fftools/ffmpeg_demux.c +++ b/fftools/ffmpeg_demux.c @@ -81,6 +81,8 @@ typedef struct Demuxer { /* number of streams that the user was warned of */ int nb_streams_warn; + double readrate_initial_burst; + AVThreadMessageQueue *in_thread_queue; int thread_queue_size; pthread_t thread; @@ -455,6 +457,7 @@ int ifile_get_packet(InputFile *f, AVPacket **pkt) (f->start_time != AV_NOPTS_VALUE ? f->start_time : 0) ); float scale = f->rate_emu ? 1.0 : f->readrate; + int64_t burst_until = AV_TIME_BASE * d->readrate_initial_burst; for (i = 0; i < f->nb_streams; i++) { InputStream *ist = f->streams[i]; int64_t stream_ts_offset, pts, now; @@ -462,7 +465,7 @@ int ifile_get_packet(InputFile *f, AVPacket **pkt) stream_ts_offset = FFMAX(ist->first_dts != AV_NOPTS_VALUE ? ist->first_dts : 0, file_start); pts = av_rescale(ist->dts, 1000000, AV_TIME_BASE); now = (av_gettime_relative() - ist->start) * scale + stream_ts_offset; - if (pts > now) + if (pts - burst_until > now) return AVERROR(EAGAIN); } } @@ -1236,6 +1239,19 @@ int ifile_open(const OptionsContext *o, const char *filename) f->rate_emu = 0; } + if (f->readrate || f->rate_emu) { + d->readrate_initial_burst = o->readrate_initial_burst ? o->readrate_initial_burst : 0.0; + if (d->readrate_initial_burst < 0.0) { + av_log(d, AV_LOG_ERROR, + "Option -readrate_initial_burst is %0.3f; it must be non-negative.\n", + d->readrate_initial_burst); + exit_program(1); + } + } else if (o->readrate_initial_burst) { + av_log(d, AV_LOG_WARNING, "Option -readrate_initial_burst ignored " + "since neither -readrate nor -re were given\n"); + } + d->thread_queue_size = o->thread_queue_size; /* update the current parameters so that they match the one of the input stream */ diff --git a/fftools/ffmpeg_opt.c b/fftools/ffmpeg_opt.c index cf385c388e0..7f22b22604b 100644 --- a/fftools/ffmpeg_opt.c +++ b/fftools/ffmpeg_opt.c @@ -1454,6 +1454,9 @@ const OptionDef options[] = { { "readrate", HAS_ARG | OPT_FLOAT | OPT_OFFSET | OPT_EXPERT | OPT_INPUT, { .off = OFFSET(readrate) }, "read input at specified rate", "speed" }, + { "readrate_initial_burst", HAS_ARG | OPT_DOUBLE | OPT_OFFSET | + OPT_EXPERT | OPT_INPUT, { .off = OFFSET(readrate_initial_burst) }, + "The initial amount of input to burst read before imposing any readrate", "seconds" }, { "target", HAS_ARG | OPT_PERFILE | OPT_OUTPUT, { .func_arg = opt_target }, "specify target file type (\"vcd\", \"svcd\", \"dvd\", \"dv\" or \"dv50\" " "with optional prefixes \"pal-\", \"ntsc-\" or \"film-\")", "type" }, From 007ec49db8f3eb9dfc9cfc4f981f3fcda8e3335d Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Tue, 2 May 2023 15:16:44 +0200 Subject: [PATCH 0915/2172] fftools/ffmpeg: use a non-zero default for -readrate_initial_burst Use it to replace a hack added in 6f206852289. --- fftools/ffmpeg_demux.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/fftools/ffmpeg_demux.c b/fftools/ffmpeg_demux.c index 37d7649da9f..e6f700f6c3c 100644 --- a/fftools/ffmpeg_demux.c +++ b/fftools/ffmpeg_demux.c @@ -461,7 +461,7 @@ int ifile_get_packet(InputFile *f, AVPacket **pkt) for (i = 0; i < f->nb_streams; i++) { InputStream *ist = f->streams[i]; int64_t stream_ts_offset, pts, now; - if (!ist->nb_packets || (ist->decoding_needed && !ist->got_output)) continue; + if (!ist->nb_packets) continue; stream_ts_offset = FFMAX(ist->first_dts != AV_NOPTS_VALUE ? ist->first_dts : 0, file_start); pts = av_rescale(ist->dts, 1000000, AV_TIME_BASE); now = (av_gettime_relative() - ist->start) * scale + stream_ts_offset; @@ -1240,7 +1240,7 @@ int ifile_open(const OptionsContext *o, const char *filename) } if (f->readrate || f->rate_emu) { - d->readrate_initial_burst = o->readrate_initial_burst ? o->readrate_initial_burst : 0.0; + d->readrate_initial_burst = o->readrate_initial_burst ? o->readrate_initial_burst : 0.5; if (d->readrate_initial_burst < 0.0) { av_log(d, AV_LOG_ERROR, "Option -readrate_initial_burst is %0.3f; it must be non-negative.\n", From 0e00d2351003dc21532e440dd63fdec9b5aab9e9 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Tue, 2 May 2023 15:27:24 +0200 Subject: [PATCH 0916/2172] fftools/ffmpeg: reduce -re to -readrate 1 They are exactly equivalent, so there is no point in maintaining a separate flag for -re. --- fftools/ffmpeg.c | 2 +- fftools/ffmpeg.h | 1 - fftools/ffmpeg_demux.c | 16 ++++++++-------- 3 files changed, 9 insertions(+), 10 deletions(-) diff --git a/fftools/ffmpeg.c b/fftools/ffmpeg.c index 8323c32ffd8..afdb049f4ee 100644 --- a/fftools/ffmpeg.c +++ b/fftools/ffmpeg.c @@ -1564,7 +1564,7 @@ static int transcode_init(void) /* init framerate emulation */ for (int i = 0; i < nb_input_files; i++) { InputFile *ifile = input_files[i]; - if (ifile->readrate || ifile->rate_emu) + if (ifile->readrate) for (int j = 0; j < ifile->nb_streams; j++) ifile->streams[j]->start = av_gettime_relative(); } diff --git a/fftools/ffmpeg.h b/fftools/ffmpeg.h index a03a6b0302c..b30f0758ecc 100644 --- a/fftools/ffmpeg.h +++ b/fftools/ffmpeg.h @@ -484,7 +484,6 @@ typedef struct InputFile { InputStream **streams; int nb_streams; - int rate_emu; float readrate; int accurate_seek; diff --git a/fftools/ffmpeg_demux.c b/fftools/ffmpeg_demux.c index e6f700f6c3c..9eea5a4eec0 100644 --- a/fftools/ffmpeg_demux.c +++ b/fftools/ffmpeg_demux.c @@ -450,13 +450,12 @@ int ifile_get_packet(InputFile *f, AVPacket **pkt) return ret; } - if (f->readrate || f->rate_emu) { + if (f->readrate) { int i; int64_t file_start = copy_ts * ( (f->start_time_effective != AV_NOPTS_VALUE ? f->start_time_effective * !start_at_zero : 0) + (f->start_time != AV_NOPTS_VALUE ? f->start_time : 0) ); - float scale = f->rate_emu ? 1.0 : f->readrate; int64_t burst_until = AV_TIME_BASE * d->readrate_initial_burst; for (i = 0; i < f->nb_streams; i++) { InputStream *ist = f->streams[i]; @@ -464,7 +463,7 @@ int ifile_get_packet(InputFile *f, AVPacket **pkt) if (!ist->nb_packets) continue; stream_ts_offset = FFMAX(ist->first_dts != AV_NOPTS_VALUE ? ist->first_dts : 0, file_start); pts = av_rescale(ist->dts, 1000000, AV_TIME_BASE); - now = (av_gettime_relative() - ist->start) * scale + stream_ts_offset; + now = (av_gettime_relative() - ist->start) * f->readrate + stream_ts_offset; if (pts - burst_until > now) return AVERROR(EAGAIN); } @@ -1223,7 +1222,6 @@ int ifile_open(const OptionsContext *o, const char *filename) f->input_sync_ref = o->input_sync_ref; f->input_ts_offset = o->input_ts_offset; f->ts_offset = o->input_ts_offset - (copy_ts ? (start_at_zero && ic->start_time != AV_NOPTS_VALUE ? ic->start_time : 0) : timestamp); - f->rate_emu = o->rate_emu; f->accurate_seek = o->accurate_seek; d->loop = o->loop; d->duration = 0; @@ -1234,12 +1232,14 @@ int ifile_open(const OptionsContext *o, const char *filename) av_log(d, AV_LOG_ERROR, "Option -readrate is %0.3f; it must be non-negative.\n", f->readrate); exit_program(1); } - if (f->readrate && f->rate_emu) { - av_log(d, AV_LOG_WARNING, "Both -readrate and -re set. Using -readrate %0.3f.\n", f->readrate); - f->rate_emu = 0; + if (o->rate_emu) { + if (f->readrate) { + av_log(d, AV_LOG_WARNING, "Both -readrate and -re set. Using -readrate %0.3f.\n", f->readrate); + } else + f->readrate = 1.0f; } - if (f->readrate || f->rate_emu) { + if (f->readrate) { d->readrate_initial_burst = o->readrate_initial_burst ? o->readrate_initial_burst : 0.5; if (d->readrate_initial_burst < 0.0) { av_log(d, AV_LOG_ERROR, From 03800bcaf3f341de4307f47626f64c0a2545c09c Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Fri, 5 May 2023 20:48:10 +0200 Subject: [PATCH 0917/2172] avfilter/af_asetnsamples: add commands support --- libavfilter/af_asetnsamples.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libavfilter/af_asetnsamples.c b/libavfilter/af_asetnsamples.c index 74d3fde35e3..fe6d40f9ca4 100644 --- a/libavfilter/af_asetnsamples.c +++ b/libavfilter/af_asetnsamples.c @@ -39,7 +39,7 @@ typedef struct ASNSContext { } ASNSContext; #define OFFSET(x) offsetof(ASNSContext, x) -#define FLAGS AV_OPT_FLAG_AUDIO_PARAM|AV_OPT_FLAG_FILTERING_PARAM +#define FLAGS AV_OPT_FLAG_AUDIO_PARAM|AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_RUNTIME_PARAM static const AVOption asetnsamples_options[] = { { "nb_out_samples", "set the number of per-frame output samples", OFFSET(nb_out_samples), AV_OPT_TYPE_INT, {.i64=1024}, 1, INT_MAX, FLAGS }, @@ -123,4 +123,5 @@ const AVFilter ff_af_asetnsamples = { FILTER_INPUTS(asetnsamples_inputs), FILTER_OUTPUTS(asetnsamples_outputs), .activate = activate, + .process_command = ff_filter_process_command, }; From 782ea8b2e5a96bb18a45210f94fb427009e996b1 Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Fri, 5 May 2023 20:53:39 +0200 Subject: [PATCH 0918/2172] avfilter/af_asetnsamples: add timeline support --- libavfilter/af_asetnsamples.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/libavfilter/af_asetnsamples.c b/libavfilter/af_asetnsamples.c index fe6d40f9ca4..20cc70ce4af 100644 --- a/libavfilter/af_asetnsamples.c +++ b/libavfilter/af_asetnsamples.c @@ -61,12 +61,15 @@ static int activate(AVFilterContext *ctx) FF_FILTER_FORWARD_STATUS_BACK(outlink, inlink); - ret = ff_inlink_consume_samples(inlink, s->nb_out_samples, s->nb_out_samples, &frame); + if (ctx->is_disabled) + ret = ff_inlink_consume_frame(inlink, &frame); + else + ret = ff_inlink_consume_samples(inlink, s->nb_out_samples, s->nb_out_samples, &frame); if (ret < 0) return ret; if (ret > 0) { - if (!s->pad || frame->nb_samples == s->nb_out_samples) + if (!s->pad || ctx->is_disabled || frame->nb_samples == s->nb_out_samples) return ff_filter_frame(outlink, frame); pad_frame = ff_get_audio_buffer(outlink, s->nb_out_samples); @@ -123,5 +126,6 @@ const AVFilter ff_af_asetnsamples = { FILTER_INPUTS(asetnsamples_inputs), FILTER_OUTPUTS(asetnsamples_outputs), .activate = activate, + .flags = AVFILTER_FLAG_SUPPORT_TIMELINE_INTERNAL, .process_command = ff_filter_process_command, }; From 7153642992c5abe33d56ca50609706bc924cd66c Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Sat, 6 May 2023 01:50:08 +0200 Subject: [PATCH 0919/2172] avfilter/af_replaygain: export results into read-only options --- doc/filters.texi | 10 ++++++++++ libavfilter/af_replaygain.c | 37 ++++++++++++++++++++++++++++++++----- 2 files changed, 42 insertions(+), 5 deletions(-) diff --git a/doc/filters.texi b/doc/filters.texi index 9a0fe9c0a10..2f9d319b6a4 100644 --- a/doc/filters.texi +++ b/doc/filters.texi @@ -6058,6 +6058,16 @@ ReplayGain scanner filter. This filter takes an audio stream as an input and outputs it unchanged. At end of filtering it displays @code{track_gain} and @code{track_peak}. +The filter accepts the following exported read-only options: + +@table @option +@item track_gain +Exported track gain in dB at end of stream. + +@item track_peak +Exported track peak at end of stream. +@end table + @section resample Convert the audio sample format, sample rate and channel layout. It is diff --git a/libavfilter/af_replaygain.c b/libavfilter/af_replaygain.c index 53852ac8bc1..128454aa6bd 100644 --- a/libavfilter/af_replaygain.c +++ b/libavfilter/af_replaygain.c @@ -23,8 +23,11 @@ * ReplayGain scanner */ +#include + #include "libavutil/avassert.h" #include "libavutil/channel_layout.h" +#include "libavutil/opt.h" #include "audio.h" #include "avfilter.h" #include "internal.h" @@ -306,8 +309,11 @@ static const ReplayGainFreqInfo freqinfos[] = }; typedef struct ReplayGainContext { + const AVClass *class; + uint32_t histogram[HISTOGRAM_SLOTS]; float peak; + float gain; int yule_hist_i, butter_hist_i; const double *yule_coeff_a; const double *yule_coeff_b; @@ -576,13 +582,22 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in) return ff_filter_frame(outlink, in); } -static av_cold void uninit(AVFilterContext *ctx) +static int request_frame(AVFilterLink *outlink) { + AVFilterContext *ctx = outlink->src; ReplayGainContext *s = ctx->priv; - float gain = calc_replaygain(s->histogram); + int ret = 0; - av_log(ctx, AV_LOG_INFO, "track_gain = %+.2f dB\n", gain); - av_log(ctx, AV_LOG_INFO, "track_peak = %.6f\n", s->peak); + ret = ff_request_frame(ctx->inputs[0]); + + if (ret == AVERROR_EOF) { + s->gain = calc_replaygain(s->histogram); + + av_log(ctx, AV_LOG_INFO, "track_gain = %+.2f dB\n", s->gain); + av_log(ctx, AV_LOG_INFO, "track_peak = %.6f\n", s->peak); + } + + return ret; } static const AVFilterPad replaygain_inputs[] = { @@ -598,14 +613,26 @@ static const AVFilterPad replaygain_outputs[] = { { .name = "default", .type = AVMEDIA_TYPE_AUDIO, + .request_frame = request_frame, }, }; +#define OFFSET(x) offsetof(ReplayGainContext, x) +#define FLAGS AV_OPT_FLAG_AUDIO_PARAM|AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_EXPORT|AV_OPT_FLAG_READONLY + +static const AVOption replaygain_options[] = { + { "track_gain", "track gain (dB)", OFFSET(gain), AV_OPT_TYPE_FLOAT,{.dbl=0}, -FLT_MAX, FLT_MAX, FLAGS }, + { "track_peak", "track peak", OFFSET(peak), AV_OPT_TYPE_FLOAT,{.dbl=0}, -FLT_MAX, FLT_MAX, FLAGS }, + { NULL } +}; + +AVFILTER_DEFINE_CLASS(replaygain); + const AVFilter ff_af_replaygain = { .name = "replaygain", .description = NULL_IF_CONFIG_SMALL("ReplayGain scanner."), - .uninit = uninit, .priv_size = sizeof(ReplayGainContext), + .priv_class = &replaygain_class, .flags = AVFILTER_FLAG_METADATA_ONLY, FILTER_INPUTS(replaygain_inputs), FILTER_OUTPUTS(replaygain_outputs), From 1c8bf697ee1caf1fa5aaafaaea894b7f0f68af4d Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Sat, 6 May 2023 12:28:10 +0200 Subject: [PATCH 0920/2172] avfilter/f_ebur128: export results into read-only options --- doc/filters.texi | 18 ++++++++++++++++++ libavfilter/f_ebur128.c | 42 +++++++++++++++++++++++++++++------------ libavfilter/version.h | 2 +- 3 files changed, 49 insertions(+), 13 deletions(-) diff --git a/doc/filters.texi b/doc/filters.texi index 2f9d319b6a4..d71fe699d8e 100644 --- a/doc/filters.texi +++ b/doc/filters.texi @@ -28726,6 +28726,24 @@ live mixing). Sets the display scale for the loudness. Valid parameters are @code{absolute} (in LUFS) or @code{relative} (LU) relative to the target. This only affects the video output, not the summary or continuous log output. + +@item integrated +Read-only exported value for measured integrated loudness, in LUFS. + +@item range +Read-only exported value for measured loudness range, in LU. + +@item lra_low +Read-only exported value for measured LRA low, in LUFS. + +@item lra_high +Read-only exported value for measured LRA high, in LUFS. + +@item sample_peak +Read-only exported value for measured sample peak, in dBFS. + +@item true_peak +Read-only exported value for measured true peak, in dBFS. @end table @subsection Examples diff --git a/libavfilter/f_ebur128.c b/libavfilter/f_ebur128.c index 38e7e0b2954..dfa62f0a36c 100644 --- a/libavfilter/f_ebur128.c +++ b/libavfilter/f_ebur128.c @@ -26,6 +26,7 @@ * @todo implement start/stop/reset through filter command injection */ +#include #include #include "libavutil/avassert.h" @@ -80,7 +81,9 @@ typedef struct EBUR128Context { /* peak metering */ int peak_mode; ///< enabled peak modes + double true_peak; ///< global true peak double *true_peaks; ///< true peaks per channel + double sample_peak; ///< global sample peak double *sample_peaks; ///< sample peaks per channel double *true_peaks_per_frame; ///< true peaks in a frame per channel #if CONFIG_SWRESAMPLE @@ -159,6 +162,8 @@ enum { #define A AV_OPT_FLAG_AUDIO_PARAM #define V AV_OPT_FLAG_VIDEO_PARAM #define F AV_OPT_FLAG_FILTERING_PARAM +#define X AV_OPT_FLAG_EXPORT +#define R AV_OPT_FLAG_READONLY static const AVOption ebur128_options[] = { { "video", "set video output", OFFSET(do_video), AV_OPT_TYPE_BOOL, {.i64 = 0}, 0, 1, V|F }, { "size", "set video size", OFFSET(w), AV_OPT_TYPE_IMAGE_SIZE, {.str = "640x480"}, 0, 0, V|F }, @@ -185,6 +190,12 @@ static const AVOption ebur128_options[] = { { "LUFS", "display absolute values (LUFS)", 0, AV_OPT_TYPE_CONST, {.i64 = SCALE_TYPE_ABSOLUTE}, INT_MIN, INT_MAX, V|F, "scaletype" }, { "relative", "display values relative to target (LU)", 0, AV_OPT_TYPE_CONST, {.i64 = SCALE_TYPE_RELATIVE}, INT_MIN, INT_MAX, V|F, "scaletype" }, { "LU", "display values relative to target (LU)", 0, AV_OPT_TYPE_CONST, {.i64 = SCALE_TYPE_RELATIVE}, INT_MIN, INT_MAX, V|F, "scaletype" }, + { "integrated", "integrated loudness (LUFS)", OFFSET(integrated_loudness), AV_OPT_TYPE_DOUBLE, {.dbl = 0}, -DBL_MAX, DBL_MAX, A|F|X|R }, + { "range", "loudness range (LU)", OFFSET(loudness_range), AV_OPT_TYPE_DOUBLE, {.dbl = 0}, -DBL_MAX, DBL_MAX, A|F|X|R }, + { "lra_low", "LRA low (LUFS)", OFFSET(lra_low), AV_OPT_TYPE_DOUBLE, {.dbl = 0}, -DBL_MAX, DBL_MAX, A|F|X|R }, + { "lra_high", "LRA high (LUFS)", OFFSET(lra_high), AV_OPT_TYPE_DOUBLE, {.dbl = 0}, -DBL_MAX, DBL_MAX, A|F|X|R }, + { "sample_peak", "sample peak (dBFS)", OFFSET(sample_peak), AV_OPT_TYPE_DOUBLE, {.dbl = 0}, -DBL_MAX, DBL_MAX, A|F|X|R }, + { "true_peak", "true peak (dBFS)", OFFSET(true_peak), AV_OPT_TYPE_DOUBLE, {.dbl = 0}, -DBL_MAX, DBL_MAX, A|F|X|R }, { NULL }, }; @@ -701,6 +712,20 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *insamples) ebur128->i3000.cache[ch][bin_id_3000] = bin; } +#define FIND_PEAK(global, sp, ptype) do { \ + int ch; \ + double maxpeak; \ + maxpeak = 0.0; \ + if (ebur128->peak_mode & PEAK_MODE_ ## ptype ## _PEAKS) { \ + for (ch = 0; ch < ebur128->nb_channels; ch++) \ + maxpeak = FFMAX(maxpeak, sp[ch]); \ + global = DBFS(maxpeak); \ + } \ +} while (0) + + FIND_PEAK(ebur128->sample_peak, ebur128->sample_peaks, SAMPLES); + FIND_PEAK(ebur128->true_peak, ebur128->true_peaks, TRUE); + /* For integrated loudness, gating blocks are 400ms long with 75% * overlap (see BS.1770-2 p5), so a re-computation is needed each 100ms * (4800 samples at 48kHz). */ @@ -1023,7 +1048,6 @@ static int query_formats(AVFilterContext *ctx) static av_cold void uninit(AVFilterContext *ctx) { - int i; EBUR128Context *ebur128 = ctx->priv; /* dual-mono correction */ @@ -1047,21 +1071,15 @@ static av_cold void uninit(AVFilterContext *ctx) ebur128->loudness_range, ebur128->i3000.rel_threshold, ebur128->lra_low, ebur128->lra_high); -#define PRINT_PEAK_SUMMARY(str, sp, ptype) do { \ - int ch; \ - double maxpeak; \ - maxpeak = 0.0; \ +#define PRINT_PEAK_SUMMARY(str, value, ptype) do { \ if (ebur128->peak_mode & PEAK_MODE_ ## ptype ## _PEAKS) { \ - for (ch = 0; ch < ebur128->nb_channels; ch++) \ - maxpeak = FFMAX(maxpeak, sp[ch]); \ av_log(ctx, AV_LOG_INFO, "\n\n " str " peak:\n" \ - " Peak: %5.1f dBFS", \ - DBFS(maxpeak)); \ + " Peak: %5.1f dBFS", value); \ } \ } while (0) - PRINT_PEAK_SUMMARY("Sample", ebur128->sample_peaks, SAMPLES); - PRINT_PEAK_SUMMARY("True", ebur128->true_peaks, TRUE); + PRINT_PEAK_SUMMARY("Sample", ebur128->sample_peak, SAMPLES); + PRINT_PEAK_SUMMARY("True", ebur128->true_peak, TRUE); av_log(ctx, AV_LOG_INFO, "\n"); av_freep(&ebur128->y_line_ref); @@ -1076,7 +1094,7 @@ static av_cold void uninit(AVFilterContext *ctx) av_freep(&ebur128->i3000.sum); av_freep(&ebur128->i400.histogram); av_freep(&ebur128->i3000.histogram); - for (i = 0; i < ebur128->nb_channels; i++) { + for (int i = 0; i < ebur128->nb_channels; i++) { if (ebur128->i400.cache) av_freep(&ebur128->i400.cache[i]); if (ebur128->i3000.cache) diff --git a/libavfilter/version.h b/libavfilter/version.h index 00508741084..4dc176dc556 100644 --- a/libavfilter/version.h +++ b/libavfilter/version.h @@ -32,7 +32,7 @@ #include "version_major.h" #define LIBAVFILTER_VERSION_MINOR 7 -#define LIBAVFILTER_VERSION_MICRO 100 +#define LIBAVFILTER_VERSION_MICRO 101 #define LIBAVFILTER_VERSION_INT AV_VERSION_INT(LIBAVFILTER_VERSION_MAJOR, \ From 2dd9b4071cebd25af2820f26c5bc0a92ef0145fe Mon Sep 17 00:00:00 2001 From: metamuffin Date: Sun, 7 May 2023 15:45:40 +0200 Subject: [PATCH 0921/2172] avdevice/lavfi: update documentation lavfi not only supports video but also audio by now. --- doc/indevs.texi | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/doc/indevs.texi b/doc/indevs.texi index 8a198c4b441..863536a34d5 100644 --- a/doc/indevs.texi +++ b/doc/indevs.texi @@ -991,9 +991,8 @@ This input device reads data from the open output pads of a libavfilter filtergraph. For each filtergraph open output, the input device will create a -corresponding stream which is mapped to the generated output. Currently -only video data is supported. The filtergraph is specified through the -option @option{graph}. +corresponding stream which is mapped to the generated output. +The filtergraph is specified through the option @option{graph}. @subsection Options From f009f849617ab0c2015d2a748892d55b37d378c0 Mon Sep 17 00:00:00 2001 From: Jonathan Gilbert Date: Sun, 7 May 2023 23:23:48 +0200 Subject: [PATCH 0922/2172] doc/filters/colorcorrect: fix bh option description --- doc/filters.texi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/filters.texi b/doc/filters.texi index d71fe699d8e..89dd59587be 100644 --- a/doc/filters.texi +++ b/doc/filters.texi @@ -9543,7 +9543,7 @@ Set the red highlight spot. Allowed range is from -1.0 to 1.0. Default value is 0. @item bh -Set the red highlight spot. Allowed range is from -1.0 to 1.0. +Set the blue highlight spot. Allowed range is from -1.0 to 1.0. Default value is 0. @item saturation From 5673da4797a841539f323141c7e9241d15d24d9d Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Sat, 29 Apr 2023 22:35:37 +0200 Subject: [PATCH 0923/2172] fftools/ffmpeg: merge choose_output() and got_eagain() These two functions are a part of a single logical action - determining which, if any, output stream needs to be processed next. Keeping them separate is a historical artifact that obscures what is actually being done. --- fftools/ffmpeg.c | 41 +++++++++++++++++++---------------------- 1 file changed, 19 insertions(+), 22 deletions(-) diff --git a/fftools/ffmpeg.c b/fftools/ffmpeg.c index afdb049f4ee..d28536deb50 100644 --- a/fftools/ffmpeg.c +++ b/fftools/ffmpeg.c @@ -1683,9 +1683,11 @@ static int need_output(void) /** * Select the output stream to process. * - * @return selected output stream, or NULL if none available + * @retval 0 an output stream was selected + * @retval AVERROR(EAGAIN) need to wait until more input is available + * @retval AVERROR_EOF no more streams need output */ -static OutputStream *choose_output(void) +static int choose_output(OutputStream **post) { int64_t opts_min = INT64_MAX; OutputStream *ost_min = NULL; @@ -1704,15 +1706,19 @@ static OutputStream *choose_output(void) ost->initialized, ost->inputs_done, ost->finished); } - if (!ost->initialized && !ost->inputs_done && !ost->finished) - return ost->unavailable ? NULL : ost; - + if (!ost->initialized && !ost->inputs_done && !ost->finished) { + ost_min = ost; + break; + } if (!ost->finished && opts < opts_min) { opts_min = opts; - ost_min = ost->unavailable ? NULL : ost; + ost_min = ost; } } - return ost_min; + if (!ost_min) + return AVERROR_EOF; + *post = ost_min; + return ost_min->unavailable ? AVERROR(EAGAIN) : 0; } static void set_tty_echo(int on) @@ -1800,14 +1806,6 @@ static int check_keyboard_interaction(int64_t cur_time) return 0; } -static int got_eagain(void) -{ - for (OutputStream *ost = ost_iter(NULL); ost; ost = ost_iter(ost)) - if (ost->unavailable) - return 1; - return 0; -} - static void reset_eagain(void) { int i; @@ -2052,13 +2050,12 @@ static int transcode_step(void) InputStream *ist = NULL; int ret; - ost = choose_output(); - if (!ost) { - if (got_eagain()) { - reset_eagain(); - av_usleep(10000); - return 0; - } + ret = choose_output(&ost); + if (ret == AVERROR(EAGAIN)) { + reset_eagain(); + av_usleep(10000); + return 0; + } else if (ret < 0) { av_log(NULL, AV_LOG_VERBOSE, "No more inputs to read from, finishing.\n"); return AVERROR_EOF; } From f5cfb2c5dfbc949a7ed2227f868f55834d20c28b Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Sat, 29 Apr 2023 22:46:14 +0200 Subject: [PATCH 0924/2172] fftools/ffmpeg: eliminate need_output() Replace it by simply calling choose_output() earlier. --- fftools/ffmpeg.c | 38 ++++++++++---------------------------- 1 file changed, 10 insertions(+), 28 deletions(-) diff --git a/fftools/ffmpeg.c b/fftools/ffmpeg.c index d28536deb50..b1914822b40 100644 --- a/fftools/ffmpeg.c +++ b/fftools/ffmpeg.c @@ -1667,19 +1667,6 @@ static int transcode_init(void) return 0; } -/* Return 1 if there remain streams where more output is wanted, 0 otherwise. */ -static int need_output(void) -{ - for (OutputStream *ost = ost_iter(NULL); ost; ost = ost_iter(ost)) { - if (ost->finished) - continue; - - return 1; - } - - return 0; -} - /** * Select the output stream to process. * @@ -2044,22 +2031,11 @@ static int process_input(int file_index) * * @return 0 for success, <0 for error */ -static int transcode_step(void) +static int transcode_step(OutputStream *ost) { - OutputStream *ost; InputStream *ist = NULL; int ret; - ret = choose_output(&ost); - if (ret == AVERROR(EAGAIN)) { - reset_eagain(); - av_usleep(10000); - return 0; - } else if (ret < 0) { - av_log(NULL, AV_LOG_VERBOSE, "No more inputs to read from, finishing.\n"); - return AVERROR_EOF; - } - if (ost->filter && !ost->filter->graph->graph) { if (ifilter_has_all_input_formats(ost->filter->graph)) { ret = configure_filtergraph(ost->filter->graph); @@ -2126,6 +2102,7 @@ static int transcode(void) timer_start = av_gettime_relative(); while (!received_sigterm) { + OutputStream *ost; int64_t cur_time= av_gettime_relative(); /* if 'q' pressed, exits */ @@ -2133,13 +2110,18 @@ static int transcode(void) if (check_keyboard_interaction(cur_time) < 0) break; - /* check if there's any stream where output is still needed */ - if (!need_output()) { + ret = choose_output(&ost); + if (ret == AVERROR(EAGAIN)) { + reset_eagain(); + av_usleep(10000); + continue; + } else if (ret < 0) { av_log(NULL, AV_LOG_VERBOSE, "No more output streams to write to, finishing.\n"); + ret = 0; break; } - ret = transcode_step(); + ret = transcode_step(ost); if (ret < 0 && ret != AVERROR_EOF) { av_log(NULL, AV_LOG_ERROR, "Error while filtering: %s\n", av_err2str(ret)); break; From 48d8d3549a1b97d6f811b7d0bed8b0fdb6a0dc6d Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Sun, 30 Apr 2023 11:38:36 +0200 Subject: [PATCH 0925/2172] fftools/ffmpeg_enc: stop configuring filter inputs from encoder flush When no frames are ever seen by an encoder, encoder flush will do a last-ditch attempt to configure its source filtergraph in order to at least get the stream parameters. This involves extracting demuxer parameters from filtergraph source inputs, which is * a bad layering violation * probably unreachable, because decoders are flushed before encoders, which should call ifilter_send_eof(), which will also set these parameters; however due to complex control flow it is hard to be entirely sure this code can never be triggered Even if this code can actually be reached, it is probably better to return an error as the comment above it says. --- fftools/ffmpeg_enc.c | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/fftools/ffmpeg_enc.c b/fftools/ffmpeg_enc.c index 53bf320afa9..9b81d14922a 100644 --- a/fftools/ffmpeg_enc.c +++ b/fftools/ffmpeg_enc.c @@ -1140,16 +1140,6 @@ void enc_flush(void) "Finishing stream without any data written to it.\n"); if (ost->filter && !fg->graph) { - int x; - for (x = 0; x < fg->nb_inputs; x++) { - InputFilter *ifilter = fg->inputs[x]; - if (ifilter->format < 0 && - ifilter_parameters_from_codecpar(ifilter, ifilter->ist->par) < 0) { - av_log(ost, AV_LOG_ERROR, "Error copying paramerets from input stream\n"); - exit_program(1); - } - } - if (!ifilter_has_all_input_formats(fg)) continue; From c7c73a3250542dde9bb882867f1b2d9af61cc5a0 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Sun, 30 Apr 2023 12:17:16 +0200 Subject: [PATCH 0926/2172] fftools/ffmpeg_filter: take fallback parameters from decoder, not demuxer When an input stream terminates and no frames were successfully decoded, filtering code will currently configure the filtergraph using demuxer stream parameters. Use decoder parameters instead, which should be more reliable. Also, initialize them immediately when an input stream is bound to a filtergraph input, so that these parameters are always available (if at all) and filtering code does not need to reach into the decoder at some arbitrary later point. --- fftools/ffmpeg.c | 18 ------------- fftools/ffmpeg.h | 8 +++++- fftools/ffmpeg_demux.c | 7 +++++ fftools/ffmpeg_filter.c | 59 ++++++++++++++++++++++++++++++++++++----- 4 files changed, 67 insertions(+), 25 deletions(-) diff --git a/fftools/ffmpeg.c b/fftools/ffmpeg.c index b1914822b40..929470f3f34 100644 --- a/fftools/ffmpeg.c +++ b/fftools/ffmpeg.c @@ -769,24 +769,6 @@ static void print_report(int is_last_report, int64_t timer_start, int64_t cur_ti first_report = 0; } -int ifilter_parameters_from_codecpar(InputFilter *ifilter, AVCodecParameters *par) -{ - int ret; - - // We never got any input. Set a fake format, which will - // come from libavformat. - ifilter->format = par->format; - ifilter->sample_rate = par->sample_rate; - ifilter->width = par->width; - ifilter->height = par->height; - ifilter->sample_aspect_ratio = par->sample_aspect_ratio; - ret = av_channel_layout_copy(&ifilter->ch_layout, &par->ch_layout); - if (ret < 0) - return ret; - - return 0; -} - static void check_decode_result(InputStream *ist, int *got_output, int ret) { if (*got_output || ret<0) diff --git a/fftools/ffmpeg.h b/fftools/ffmpeg.h index b30f0758ecc..602005f071e 100644 --- a/fftools/ffmpeg.h +++ b/fftools/ffmpeg.h @@ -788,7 +788,13 @@ void sub2video_update(InputStream *ist, int64_t heartbeat_pts, AVSubtitle *sub); int ifilter_send_frame(InputFilter *ifilter, AVFrame *frame, int keep_reference); int ifilter_send_eof(InputFilter *ifilter, int64_t pts, AVRational tb); -int ifilter_parameters_from_codecpar(InputFilter *ifilter, AVCodecParameters *par); +/** + * Set up fallback filtering parameters from a decoder context. They will only + * be used if no frames are ever sent on this input, otherwise the actual + * parameters are taken from the frame. + */ +int ifilter_parameters_from_dec(InputFilter *ifilter, const AVCodecContext *dec); + int ifilter_has_all_input_formats(FilterGraph *fg); /** diff --git a/fftools/ffmpeg_demux.c b/fftools/ffmpeg_demux.c index 9eea5a4eec0..a0ef68a8a35 100644 --- a/fftools/ffmpeg_demux.c +++ b/fftools/ffmpeg_demux.c @@ -586,10 +586,17 @@ void ist_output_add(InputStream *ist, OutputStream *ost) void ist_filter_add(InputStream *ist, InputFilter *ifilter, int is_simple) { + int ret; + ist_use(ist, is_simple ? DECODING_FOR_OST : DECODING_FOR_FILTER); GROW_ARRAY(ist->filters, ist->nb_filters); ist->filters[ist->nb_filters - 1] = ifilter; + + // initialize fallback parameters for filtering + ret = ifilter_parameters_from_dec(ifilter, ist->dec_ctx); + if (ret < 0) + report_and_exit(ret); } static const AVCodec *choose_decoder(const OptionsContext *o, AVFormatContext *s, AVStream *st, diff --git a/fftools/ffmpeg_filter.c b/fftools/ffmpeg_filter.c index 8c408eb7c41..3fad38f782d 100644 --- a/fftools/ffmpeg_filter.c +++ b/fftools/ffmpeg_filter.c @@ -58,6 +58,19 @@ typedef struct InputFilterPriv { AVRational time_base; AVFifo *frame_queue; + + // fallback parameters to use when no input is ever sent + struct { + int format; + + int width; + int height; + AVRational sample_aspect_ratio; + + int sample_rate; + AVChannelLayout ch_layout; + } fallback; + } InputFilterPriv; static InputFilterPriv *ifp_from_ifilter(InputFilter *ifilter) @@ -225,6 +238,8 @@ static InputFilter *ifilter_alloc(FilterGraph *fg) ifilter->graph = fg; ifilter->format = -1; + ifp->fallback.format = -1; + ifp->frame_queue = av_fifo_alloc2(8, sizeof(AVFrame*), AV_FIFO_FLAG_AUTO_GROW); if (!ifp->frame_queue) report_and_exit(AVERROR(ENOMEM)); @@ -260,6 +275,9 @@ void fg_free(FilterGraph **pfg) avsubtitle_free(&sub); av_fifo_freep2(&ist->sub2video.sub_queue); } + + av_channel_layout_uninit(&ifp->fallback.ch_layout); + av_buffer_unref(&ifilter->hw_frames_ctx); av_freep(&ifilter->name); av_freep(&fg->inputs[j]); @@ -1361,6 +1379,29 @@ int configure_filtergraph(FilterGraph *fg) return ret; } +int ifilter_parameters_from_dec(InputFilter *ifilter, const AVCodecContext *dec) +{ + InputFilterPriv *ifp = ifp_from_ifilter(ifilter); + + if (dec->codec_type == AVMEDIA_TYPE_VIDEO) { + ifp->fallback.format = dec->pix_fmt; + ifp->fallback.width = dec->width; + ifp->fallback.height = dec->height; + ifp->fallback.sample_aspect_ratio = dec->sample_aspect_ratio; + } else { + int ret; + + ifp->fallback.format = dec->sample_fmt; + ifp->fallback.sample_rate = dec->sample_rate; + + ret = av_channel_layout_copy(&ifp->fallback.ch_layout, &dec->ch_layout); + if (ret < 0) + return ret; + } + + return 0; +} + static int ifilter_parameters_from_frame(InputFilter *ifilter, const AVFrame *frame) { AVFrameSideData *sd; @@ -1469,12 +1510,18 @@ int ifilter_send_eof(InputFilter *ifilter, int64_t pts, AVRational tb) if (ret < 0) return ret; } else { - // the filtergraph was never configured - if (ifilter->format < 0) { - ret = ifilter_parameters_from_codecpar(ifilter, ifilter->ist->par); - if (ret < 0) - return ret; - } + // the filtergraph was never configured, use the fallback parameters + ifilter->format = ifp->fallback.format; + ifilter->sample_rate = ifp->fallback.sample_rate; + ifilter->width = ifp->fallback.width; + ifilter->height = ifp->fallback.height; + ifilter->sample_aspect_ratio = ifp->fallback.sample_aspect_ratio; + + ret = av_channel_layout_copy(&ifilter->ch_layout, + &ifp->fallback.ch_layout); + if (ret < 0) + return ret; + if (ifilter->format < 0 && (ifilter->type == AVMEDIA_TYPE_AUDIO || ifilter->type == AVMEDIA_TYPE_VIDEO)) { av_log(NULL, AV_LOG_ERROR, "Cannot determine format of input stream %d:%d after EOF\n", ifilter->ist->file_index, ifilter->ist->st->index); return AVERROR_INVALIDDATA; From e8df737cb2305efb137e655e7f6dfd5e4c80bc5c Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Sun, 30 Apr 2023 12:24:50 +0200 Subject: [PATCH 0927/2172] fftools/ffmpeg_filter: move InputFilter.eof to private data It is not used outside of ffmpeg_filter. --- fftools/ffmpeg.h | 2 -- fftools/ffmpeg_filter.c | 7 +++++-- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/fftools/ffmpeg.h b/fftools/ffmpeg.h index 602005f071e..aa7778a58fd 100644 --- a/fftools/ffmpeg.h +++ b/fftools/ffmpeg.h @@ -289,8 +289,6 @@ typedef struct InputFilter { AVBufferRef *hw_frames_ctx; int32_t *displaymatrix; - - int eof; } InputFilter; typedef struct OutputFilter { diff --git a/fftools/ffmpeg_filter.c b/fftools/ffmpeg_filter.c index 3fad38f782d..5d9242f4762 100644 --- a/fftools/ffmpeg_filter.c +++ b/fftools/ffmpeg_filter.c @@ -55,6 +55,8 @@ static FilterGraphPriv *fgp_from_fg(FilterGraph *fg) typedef struct InputFilterPriv { InputFilter ifilter; + int eof; + AVRational time_base; AVFifo *frame_queue; @@ -1353,7 +1355,8 @@ int configure_filtergraph(FilterGraph *fg) /* send the EOFs for the finished inputs */ for (i = 0; i < fg->nb_inputs; i++) { - if (fg->inputs[i]->eof) { + InputFilterPriv *ifp = ifp_from_ifilter(fg->inputs[i]); + if (ifp->eof) { ret = av_buffersrc_add_frame(fg->inputs[i]->filter, NULL); if (ret < 0) goto fail; @@ -1500,7 +1503,7 @@ int ifilter_send_eof(InputFilter *ifilter, int64_t pts, AVRational tb) InputFilterPriv *ifp = ifp_from_ifilter(ifilter); int ret; - ifilter->eof = 1; + ifp->eof = 1; if (ifilter->filter) { pts = av_rescale_q_rnd(pts, tb, ifp->time_base, From 71d7e9bbeca9574f29b63f3d1ab6b7ad450a8e67 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Sun, 30 Apr 2023 12:26:51 +0200 Subject: [PATCH 0928/2172] fftools/ffmpeg_filter: move InputFilter.displaymatrix to private data It is not used outside of ffmpeg_filter. --- fftools/ffmpeg.h | 1 - fftools/ffmpeg_filter.c | 15 +++++++++------ 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/fftools/ffmpeg.h b/fftools/ffmpeg.h index aa7778a58fd..af1ba49771c 100644 --- a/fftools/ffmpeg.h +++ b/fftools/ffmpeg.h @@ -288,7 +288,6 @@ typedef struct InputFilter { AVChannelLayout ch_layout; AVBufferRef *hw_frames_ctx; - int32_t *displaymatrix; } InputFilter; typedef struct OutputFilter { diff --git a/fftools/ffmpeg_filter.c b/fftools/ffmpeg_filter.c index 5d9242f4762..087ef8b894e 100644 --- a/fftools/ffmpeg_filter.c +++ b/fftools/ffmpeg_filter.c @@ -61,6 +61,8 @@ typedef struct InputFilterPriv { AVFifo *frame_queue; + int32_t *displaymatrix; + // fallback parameters to use when no input is ever sent struct { int format; @@ -270,7 +272,7 @@ void fg_free(FilterGraph **pfg) av_frame_free(&frame); av_fifo_freep2(&ifp->frame_queue); } - av_freep(&ifilter->displaymatrix); + av_freep(&ifp->displaymatrix); if (ist->sub2video.sub_queue) { AVSubtitle sub; while (av_fifo_read(ist->sub2video.sub_queue, &sub, 1) >= 0) @@ -1061,7 +1063,7 @@ static int configure_input_video_filter(FilterGraph *fg, InputFilter *ifilter, // TODO: insert hwaccel enabled filters like transpose_vaapi into the graph if (ist->autorotate && !(desc->flags & AV_PIX_FMT_FLAG_HWACCEL)) { - int32_t *displaymatrix = ifilter->displaymatrix; + int32_t *displaymatrix = ifp->displaymatrix; double theta; if (!displaymatrix) @@ -1407,6 +1409,7 @@ int ifilter_parameters_from_dec(InputFilter *ifilter, const AVCodecContext *dec) static int ifilter_parameters_from_frame(InputFilter *ifilter, const AVFrame *frame) { + InputFilterPriv *ifp = ifp_from_ifilter(ifilter); AVFrameSideData *sd; int ret; @@ -1423,10 +1426,10 @@ static int ifilter_parameters_from_frame(InputFilter *ifilter, const AVFrame *fr if (ret < 0) return ret; - av_freep(&ifilter->displaymatrix); + av_freep(&ifp->displaymatrix); sd = av_frame_get_side_data(frame, AV_FRAME_DATA_DISPLAYMATRIX); if (sd) - ifilter->displaymatrix = av_memdup(sd->data, sizeof(int32_t) * 9); + ifp->displaymatrix = av_memdup(sd->data, sizeof(int32_t) * 9); if (frame->hw_frames_ctx) { ifilter->hw_frames_ctx = av_buffer_ref(frame->hw_frames_ctx); @@ -1567,9 +1570,9 @@ int ifilter_send_frame(InputFilter *ifilter, AVFrame *frame, int keep_reference) need_reinit = 1; if (sd = av_frame_get_side_data(frame, AV_FRAME_DATA_DISPLAYMATRIX)) { - if (!ifilter->displaymatrix || memcmp(sd->data, ifilter->displaymatrix, sizeof(int32_t) * 9)) + if (!ifp->displaymatrix || memcmp(sd->data, ifp->displaymatrix, sizeof(int32_t) * 9)) need_reinit = 1; - } else if (ifilter->displaymatrix) + } else if (ifp->displaymatrix) need_reinit = 1; if (need_reinit) { From 5356f5ed23677d9ed683154b03760ed003ec7f25 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Sun, 30 Apr 2023 12:26:51 +0200 Subject: [PATCH 0929/2172] fftools/ffmpeg_filter: move InputFilter.hw_frames_ctx to private data It is not used outside of ffmpeg_filter. --- fftools/ffmpeg.h | 2 -- fftools/ffmpeg_filter.c | 16 +++++++++------- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/fftools/ffmpeg.h b/fftools/ffmpeg.h index af1ba49771c..47358170e78 100644 --- a/fftools/ffmpeg.h +++ b/fftools/ffmpeg.h @@ -286,8 +286,6 @@ typedef struct InputFilter { int sample_rate; AVChannelLayout ch_layout; - - AVBufferRef *hw_frames_ctx; } InputFilter; typedef struct OutputFilter { diff --git a/fftools/ffmpeg_filter.c b/fftools/ffmpeg_filter.c index 087ef8b894e..34c51c23d9b 100644 --- a/fftools/ffmpeg_filter.c +++ b/fftools/ffmpeg_filter.c @@ -61,6 +61,8 @@ typedef struct InputFilterPriv { AVFifo *frame_queue; + AVBufferRef *hw_frames_ctx; + int32_t *displaymatrix; // fallback parameters to use when no input is ever sent @@ -282,7 +284,7 @@ void fg_free(FilterGraph **pfg) av_channel_layout_uninit(&ifp->fallback.ch_layout); - av_buffer_unref(&ifilter->hw_frames_ctx); + av_buffer_unref(&ifp->hw_frames_ctx); av_freep(&ifilter->name); av_freep(&fg->inputs[j]); } @@ -1051,7 +1053,7 @@ static int configure_input_video_filter(FilterGraph *fg, InputFilter *ifilter, if ((ret = avfilter_graph_create_filter(&ifilter->filter, buffer_filt, name, args.str, NULL, fg->graph)) < 0) goto fail; - par->hw_frames_ctx = ifilter->hw_frames_ctx; + par->hw_frames_ctx = ifp->hw_frames_ctx; ret = av_buffersrc_parameters_set(ifilter->filter, par); if (ret < 0) goto fail; @@ -1413,7 +1415,7 @@ static int ifilter_parameters_from_frame(InputFilter *ifilter, const AVFrame *fr AVFrameSideData *sd; int ret; - av_buffer_unref(&ifilter->hw_frames_ctx); + av_buffer_unref(&ifp->hw_frames_ctx); ifilter->format = frame->format; @@ -1432,8 +1434,8 @@ static int ifilter_parameters_from_frame(InputFilter *ifilter, const AVFrame *fr ifp->displaymatrix = av_memdup(sd->data, sizeof(int32_t) * 9); if (frame->hw_frames_ctx) { - ifilter->hw_frames_ctx = av_buffer_ref(frame->hw_frames_ctx); - if (!ifilter->hw_frames_ctx) + ifp->hw_frames_ctx = av_buffer_ref(frame->hw_frames_ctx); + if (!ifp->hw_frames_ctx) return AVERROR(ENOMEM); } @@ -1565,8 +1567,8 @@ int ifilter_send_frame(InputFilter *ifilter, AVFrame *frame, int keep_reference) if (!ifilter->ist->reinit_filters && fg->graph) need_reinit = 0; - if (!!ifilter->hw_frames_ctx != !!frame->hw_frames_ctx || - (ifilter->hw_frames_ctx && ifilter->hw_frames_ctx->data != frame->hw_frames_ctx->data)) + if (!!ifp->hw_frames_ctx != !!frame->hw_frames_ctx || + (ifp->hw_frames_ctx && ifp->hw_frames_ctx->data != frame->hw_frames_ctx->data)) need_reinit = 1; if (sd = av_frame_get_side_data(frame, AV_FRAME_DATA_DISPLAYMATRIX)) { From c26a6c5a523032873dc8bc7fe467b15fdcaa93ea Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Sun, 30 Apr 2023 12:32:32 +0200 Subject: [PATCH 0930/2172] fftools/ffmpeg_filter: use av_buffer_replace() to improve code It is shorter and more efficient. --- fftools/ffmpeg_filter.c | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/fftools/ffmpeg_filter.c b/fftools/ffmpeg_filter.c index 34c51c23d9b..0165be8f77e 100644 --- a/fftools/ffmpeg_filter.c +++ b/fftools/ffmpeg_filter.c @@ -1415,7 +1415,9 @@ static int ifilter_parameters_from_frame(InputFilter *ifilter, const AVFrame *fr AVFrameSideData *sd; int ret; - av_buffer_unref(&ifp->hw_frames_ctx); + ret = av_buffer_replace(&ifp->hw_frames_ctx, frame->hw_frames_ctx); + if (ret < 0) + return ret; ifilter->format = frame->format; @@ -1433,12 +1435,6 @@ static int ifilter_parameters_from_frame(InputFilter *ifilter, const AVFrame *fr if (sd) ifp->displaymatrix = av_memdup(sd->data, sizeof(int32_t) * 9); - if (frame->hw_frames_ctx) { - ifp->hw_frames_ctx = av_buffer_ref(frame->hw_frames_ctx); - if (!ifp->hw_frames_ctx) - return AVERROR(ENOMEM); - } - return 0; } From dd1c67d5393303ad23ba8cb494ddb17a2c1a002b Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Sun, 30 Apr 2023 22:50:40 +0200 Subject: [PATCH 0931/2172] fftools/ffmpeg: move unconfigured graph handling to ffmpeg_filter This code more properly belongs there. --- fftools/ffmpeg.c | 25 +------------------------ fftools/ffmpeg_filter.c | 27 +++++++++++++++++++++++++++ 2 files changed, 28 insertions(+), 24 deletions(-) diff --git a/fftools/ffmpeg.c b/fftools/ffmpeg.c index 929470f3f34..10778061217 100644 --- a/fftools/ffmpeg.c +++ b/fftools/ffmpeg.c @@ -2018,34 +2018,11 @@ static int transcode_step(OutputStream *ost) InputStream *ist = NULL; int ret; - if (ost->filter && !ost->filter->graph->graph) { - if (ifilter_has_all_input_formats(ost->filter->graph)) { - ret = configure_filtergraph(ost->filter->graph); - if (ret < 0) { - av_log(NULL, AV_LOG_ERROR, "Error reinitializing filters!\n"); - return ret; - } - } - } - - if (ost->filter && ost->filter->graph->graph) { + if (ost->filter) { if ((ret = fg_transcode_step(ost->filter->graph, &ist)) < 0) return ret; if (!ist) return 0; - } else if (ost->filter) { - int i; - for (i = 0; i < ost->filter->graph->nb_inputs; i++) { - InputFilter *ifilter = ost->filter->graph->inputs[i]; - if (!ifilter->ist->got_output && !input_files[ifilter->ist->file_index]->eof_reached) { - ist = ifilter->ist; - break; - } - } - if (!ist) { - ost->inputs_done = 1; - return 0; - } } else { ist = ost->ist; av_assert0(ist); diff --git a/fftools/ffmpeg_filter.c b/fftools/ffmpeg_filter.c index 0165be8f77e..634315fa341 100644 --- a/fftools/ffmpeg_filter.c +++ b/fftools/ffmpeg_filter.c @@ -1623,6 +1623,33 @@ int fg_transcode_step(FilterGraph *graph, InputStream **best_ist) InputFilter *ifilter; InputStream *ist; + if (!graph->graph && ifilter_has_all_input_formats(graph)) { + // graph has not been configured yet, but everything is ready; + // this can happen for graphs with no inputs, or when some input + // EOF'ed with zero frames and fallback parameters were used + ret = configure_filtergraph(graph); + if (ret < 0) { + av_log(NULL, AV_LOG_ERROR, "Error reinitializing filters!\n"); + return ret; + } + } + + if (!graph->graph) { + for (int i = 0; i < graph->nb_inputs; i++) { + InputFilter *ifilter = graph->inputs[i]; + if (!ifilter->ist->got_output && !input_files[ifilter->ist->file_index]->eof_reached) { + *best_ist = ifilter->ist; + return 0; + } + } + + // graph not configured, but all inputs are either initialized or EOF + for (int i = 0; i < graph->nb_outputs; i++) + graph->outputs[i]->ost->inputs_done = 1; + + return 0; + } + *best_ist = NULL; ret = avfilter_graph_request_oldest(graph->graph); if (ret >= 0) From a0174a235b08f1bc26c7aee25b385d2dd997f8db Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Sun, 30 Apr 2023 23:05:55 +0200 Subject: [PATCH 0932/2172] fftools/ffmpeg_filter: use InputFilterPriv.eof instead of InputFile.eof_reached The two checks using eof_reached are testing whether more input can possibly appear on this filtergraph input. InputFilterPriv.eof is the more authoritative source for this information. --- fftools/ffmpeg_filter.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/fftools/ffmpeg_filter.c b/fftools/ffmpeg_filter.c index 634315fa341..aea951a2da9 100644 --- a/fftools/ffmpeg_filter.c +++ b/fftools/ffmpeg_filter.c @@ -1620,7 +1620,6 @@ int fg_transcode_step(FilterGraph *graph, InputStream **best_ist) { int i, ret; int nb_requests, nb_requests_max = 0; - InputFilter *ifilter; InputStream *ist; if (!graph->graph && ifilter_has_all_input_formats(graph)) { @@ -1637,7 +1636,8 @@ int fg_transcode_step(FilterGraph *graph, InputStream **best_ist) if (!graph->graph) { for (int i = 0; i < graph->nb_inputs; i++) { InputFilter *ifilter = graph->inputs[i]; - if (!ifilter->ist->got_output && !input_files[ifilter->ist->file_index]->eof_reached) { + InputFilterPriv *ifp = ifp_from_ifilter(ifilter); + if (!ifilter->ist->got_output && !ifp->eof) { *best_ist = ifilter->ist; return 0; } @@ -1665,10 +1665,11 @@ int fg_transcode_step(FilterGraph *graph, InputStream **best_ist) return ret; for (i = 0; i < graph->nb_inputs; i++) { - ifilter = graph->inputs[i]; + InputFilter *ifilter = graph->inputs[i]; + InputFilterPriv *ifp = ifp_from_ifilter(ifilter); + ist = ifilter->ist; - if (input_files[ist->file_index]->eagain || - input_files[ist->file_index]->eof_reached) + if (input_files[ist->file_index]->eagain || ifp->eof) continue; nb_requests = av_buffersrc_get_nb_failed_requests(ifilter->filter); if (nb_requests > nb_requests_max) { From 2d43c23b812ade93b60f5025dd18bf55dbea5e3d Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Wed, 26 Apr 2023 14:13:58 +0200 Subject: [PATCH 0933/2172] fftools/ffmpeg: discard packets for unused streams in demuxing thread Avoids the pointless overhead of transferring them to the main thread. --- fftools/ffmpeg.c | 4 ---- fftools/ffmpeg_demux.c | 3 ++- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/fftools/ffmpeg.c b/fftools/ffmpeg.c index 10778061217..5cf6a00f50f 100644 --- a/fftools/ffmpeg.c +++ b/fftools/ffmpeg.c @@ -1961,9 +1961,6 @@ static int process_input(int file_index) ist->data_size += pkt->size; ist->nb_packets++; - if (ist->discard) - goto discard_packet; - /* add the stream-global side data to the first packet */ if (ist->nb_packets == 1) { for (i = 0; i < ist->st->nb_side_data; i++) { @@ -2002,7 +1999,6 @@ static int process_input(int file_index) process_input_packet(ist, pkt, 0); -discard_packet: av_packet_free(&pkt); return 0; diff --git a/fftools/ffmpeg_demux.c b/fftools/ffmpeg_demux.c index a0ef68a8a35..630bb1c26b2 100644 --- a/fftools/ffmpeg_demux.c +++ b/fftools/ffmpeg_demux.c @@ -318,7 +318,8 @@ static void *input_thread(void *arg) /* the following test is needed in case new streams appear dynamically in stream : we ignore them */ - if (pkt->stream_index >= f->nb_streams) { + if (pkt->stream_index >= f->nb_streams || + f->streams[pkt->stream_index]->discard) { report_new_stream(d, pkt); av_packet_unref(pkt); continue; From 63d7ea38c79cb91b40b2f238ee13e2a18a1b7a50 Mon Sep 17 00:00:00 2001 From: James Almer Date: Fri, 5 May 2023 20:18:13 -0300 Subject: [PATCH 0934/2172] fftools/ffprobe: print exported stream AVOptions Similar to the decoder AVOptions, this is useful to show values from options exported by the demuxer. Signed-off-by: James Almer --- fftools/ffprobe.c | 29 ++++++++++++++++++----------- tests/ref/fate/flv-demux | 4 ++-- tests/ref/fate/ts-demux | 6 +++--- tests/ref/fate/ts-opus-demux | 2 +- tests/ref/fate/ts-small-demux | 2 +- 5 files changed, 25 insertions(+), 18 deletions(-) diff --git a/fftools/ffprobe.c b/fftools/ffprobe.c index 43bf10db544..1ff76ce8094 100644 --- a/fftools/ffprobe.c +++ b/fftools/ffprobe.c @@ -2398,6 +2398,19 @@ static void print_pkt_side_data(WriterContext *w, writer_print_section_footer(w); } +static void print_private_data(WriterContext *w, void *priv_data) +{ + const AVOption *opt = NULL; + while (opt = av_opt_next(priv_data, opt)) { + uint8_t *str; + if (!(opt->flags & AV_OPT_FLAG_EXPORT)) continue; + if (av_opt_get(priv_data, opt->name, 0, &str) >= 0) { + print_str(opt->name, str); + av_free(str); + } + } +} + static void print_color_range(WriterContext *w, enum AVColorRange color_range) { const char *val = av_color_range_name(color_range); @@ -2448,7 +2461,6 @@ static void print_chroma_location(WriterContext *w, enum AVChromaLocation chroma } } - static void clear_log(int need_lock) { int i; @@ -3115,16 +3127,11 @@ static int show_stream(WriterContext *w, AVFormatContext *fmt_ctx, int stream_id break; } - if (dec_ctx && dec_ctx->codec->priv_class && show_private_data) { - const AVOption *opt = NULL; - while (opt = av_opt_next(dec_ctx->priv_data,opt)) { - uint8_t *str; - if (!(opt->flags & AV_OPT_FLAG_EXPORT)) continue; - if (av_opt_get(dec_ctx->priv_data, opt->name, 0, &str) >= 0) { - print_str(opt->name, str); - av_free(str); - } - } + if (show_private_data) { + if (dec_ctx && dec_ctx->codec->priv_class) + print_private_data(w, dec_ctx->priv_data); + if (fmt_ctx->iformat->priv_class) + print_private_data(w, fmt_ctx->priv_data); } if (fmt_ctx->iformat->flags & AVFMT_SHOW_IDS) print_fmt ("id", "0x%x", stream->id); diff --git a/tests/ref/fate/flv-demux b/tests/ref/fate/flv-demux index 2e9610fb4a5..bd967d904dc 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=__C|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_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|initial_padding=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 +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|missing_streams=0|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|initial_padding=0|missing_streams=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/ts-demux b/tests/ref/fate/ts-demux index 08326766646..838186729d3 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_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|initial_padding=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|initial_padding=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 +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|ts_packetsize=188|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|initial_padding=0|ts_packetsize=188|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|initial_padding=0|ts_packetsize=188|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 1d3e647f3c9..cc34ac610c7 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| 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__|data_hash=CRC32:59fc266f|side_data|side_data_type=MPEGTS Stream ID|id=189 -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|initial_padding=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 +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|initial_padding=0|ts_packetsize=188|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 0b12cdde42b..ce16e24334f 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=___|data_hash=CRC32:27b943ef|side_data|side_data_type=MPEGTS Stream ID|id=224 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 +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|ts_packetsize=188|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 bbe410a7fd912277f99b9c071f9ca095b201ef34 Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Mon, 8 May 2023 16:12:07 +0200 Subject: [PATCH 0935/2172] avfilter/vf_morpho: move structure processing in separate loop --- libavfilter/vf_morpho.c | 39 ++++++++++++++++++++++----------------- 1 file changed, 22 insertions(+), 17 deletions(-) diff --git a/libavfilter/vf_morpho.c b/libavfilter/vf_morpho.c index f91957ab810..64b199ac032 100644 --- a/libavfilter/vf_morpho.c +++ b/libavfilter/vf_morpho.c @@ -808,30 +808,13 @@ static int do_morpho(FFFrameSync *fs) av_frame_copy_props(out, in); for (int p = 0; p < s->nb_planes; p++) { - const uint8_t *src = in->data[p]; - int src_linesize = in->linesize[p]; const uint8_t *ssrc = structurepic->data[p]; const int ssrc_linesize = structurepic->linesize[p]; - uint8_t *dst = out->data[p]; - int dst_linesize = out->linesize[p]; const int swidth = s->splanewidth[p]; const int sheight = s->splaneheight[p]; - const int width = s->planewidth[p]; - const int height = s->planeheight[p]; const int depth = s->depth; int type_size = s->type_size; - if (ctx->is_disabled || !(s->planes & (1 << p))) { -copy: - av_image_copy_plane(out->data[p] + 0 * out->linesize[p], - out->linesize[p], - in->data[p] + 0 * in->linesize[p], - in->linesize[p], - width * ((s->depth + 7) / 8), - height); - continue; - } - if (!s->got_structure[p] || s->structures) { free_chord_set(&s->SE[p]); @@ -843,6 +826,28 @@ static int do_morpho(FFFrameSync *fs) goto fail; s->got_structure[p] = 1; } + } + + for (int p = 0; p < s->nb_planes; p++) { + const uint8_t *src = in->data[p]; + int src_linesize = in->linesize[p]; + uint8_t *dst = out->data[p]; + int dst_linesize = out->linesize[p]; + const int width = s->planewidth[p]; + const int height = s->planeheight[p]; + const int depth = s->depth; + int type_size = s->type_size; + + if (ctx->is_disabled || !(s->planes & (1 << p))) { +copy: + av_image_copy_plane(out->data[p] + 0 * out->linesize[p], + out->linesize[p], + in->data[p] + 0 * in->linesize[p], + in->linesize[p], + width * ((depth + 7) / 8), + height); + continue; + } if (s->SE[p].minX == INT16_MAX || s->SE[p].minY == INT16_MAX || From df886171a6bb09123986143734d104ba1ad0ed22 Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Mon, 8 May 2023 16:17:52 +0200 Subject: [PATCH 0936/2172] avfilter/vf_morpho: remove unused function's argument --- libavfilter/vf_morpho.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/libavfilter/vf_morpho.c b/libavfilter/vf_morpho.c index 64b199ac032..55886d2b8a4 100644 --- a/libavfilter/vf_morpho.c +++ b/libavfilter/vf_morpho.c @@ -318,7 +318,7 @@ static void free_lut(LUT *table) } static int alloc_lut_if_necessary(LUT *Ty, IPlane *f, chord_set *SE, - int y, int num, enum MorphModes mode) + int num, enum MorphModes mode) { if (!Ty->arr || Ty->I != SE->Lnum || Ty->X != f->w || @@ -387,7 +387,7 @@ static void update_min_lut(IPlane *f, LUT *Ty, chord_set *SE, int y, int tid, in static int compute_min_lut(LUT *Ty, IPlane *f, chord_set *SE, int y, int num) { - int ret = alloc_lut_if_necessary(Ty, f, SE, y, num, ERODE); + int ret = alloc_lut_if_necessary(Ty, f, SE, num, ERODE); if (ret < 0) return ret; @@ -428,7 +428,7 @@ static void update_max_lut(IPlane *f, LUT *Ty, chord_set *SE, int y, int tid, in static int compute_max_lut(LUT *Ty, IPlane *f, chord_set *SE, int y, int num) { - int ret = alloc_lut_if_necessary(Ty, f, SE, y, num, DILATE); + int ret = alloc_lut_if_necessary(Ty, f, SE, num, DILATE); if (ret < 0) return ret; From 1eed7f65624cd590a4acd944f9bbeb9f03634a3f Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Mon, 8 May 2023 17:17:19 +0200 Subject: [PATCH 0937/2172] avfilter/vf_morpho: add slice threading support --- libavfilter/vf_morpho.c | 257 ++++++++++++++++++++++++---------------- 1 file changed, 158 insertions(+), 99 deletions(-) diff --git a/libavfilter/vf_morpho.c b/libavfilter/vf_morpho.c index 55886d2b8a4..a218499d616 100644 --- a/libavfilter/vf_morpho.c +++ b/libavfilter/vf_morpho.c @@ -95,6 +95,8 @@ typedef struct chord_set { unsigned nb_elements; } chord_set; +#define MAX_THREADS 64 + typedef struct MorphoContext { const AVClass *class; FFFrameSync fs; @@ -102,7 +104,7 @@ typedef struct MorphoContext { chord_set SE[4]; IPlane SEimg[4]; IPlane g[4], f[4], h[4]; - LUT Ty[2][4]; + LUT Ty[MAX_THREADS][2][4]; int mode; int planes; @@ -460,14 +462,14 @@ static void line_erode(IPlane *g, LUT *Ty, chord_set *SE, int y, int tid) } } -static int dilate(IPlane *g, IPlane *f, chord_set *SE, LUT *Ty) +static int dilate(IPlane *g, IPlane *f, chord_set *SE, LUT *Ty, int y0, int y1) { - int ret = compute_max_lut(Ty, f, SE, 0, 1); + int ret = compute_max_lut(Ty, f, SE, y0, 1); if (ret < 0) return ret; - line_dilate(g, Ty, SE, 0, 0); - for (int y = 1; y < f->h; y++) { + line_dilate(g, Ty, SE, y0, 0); + for (int y = y0 + 1; y < y1; y++) { update_max_lut(f, Ty, SE, y, 0, 1); line_dilate(g, Ty, SE, y, 0); } @@ -475,14 +477,14 @@ static int dilate(IPlane *g, IPlane *f, chord_set *SE, LUT *Ty) return 0; } -static int erode(IPlane *g, IPlane *f, chord_set *SE, LUT *Ty) +static int erode(IPlane *g, IPlane *f, chord_set *SE, LUT *Ty, int y0, int y1) { - int ret = compute_min_lut(Ty, f, SE, 0, 1); + int ret = compute_min_lut(Ty, f, SE, y0, 1); if (ret < 0) return ret; - line_erode(g, Ty, SE, 0, 0); - for (int y = 1; y < f->h; y++) { + line_erode(g, Ty, SE, y0, 0); + for (int y = y0 + 1; y < y1; y++) { update_min_lut(f, Ty, SE, y, 0, 1); line_erode(g, Ty, SE, y, 0); } @@ -490,15 +492,15 @@ static int erode(IPlane *g, IPlane *f, chord_set *SE, LUT *Ty) return 0; } -static void difference(IPlane *g, IPlane *f) +static void difference(IPlane *g, IPlane *f, int y0, int y1) { - for (int y = 0; y < f->h; y++) + for (int y = y0; y < y1; y++) f->diff_in_place(g->img[y], f->img[y], f->w); } -static void difference2(IPlane *g, IPlane *f) +static void difference2(IPlane *g, IPlane *f, int y0, int y1) { - for (int y = 0; y < f->h; y++) + for (int y = y0; y < y1; y++) f->diff_rin_place(g->img[y], f->img[y], f->w); } @@ -785,12 +787,133 @@ static int activate(AVFilterContext *ctx) return ff_framesync_activate(&s->fs); } +typedef struct ThreadData { + AVFrame *in, *out; +} ThreadData; + +static int morpho_slice(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) +{ + MorphoContext *s = ctx->priv; + ThreadData *td = arg; + AVFrame *out = td->out; + AVFrame *in = td->in; + int ret; + + for (int p = 0; p < s->nb_planes; p++) { + const int width = s->planewidth[p]; + const int height = s->planeheight[p]; + const int y0 = (height * jobnr ) / nb_jobs; + const int y1 = (height * (jobnr+1)) / nb_jobs; + const int depth = s->depth; + + if (ctx->is_disabled || !(s->planes & (1 << p))) { +copy: + av_image_copy_plane(out->data[p] + y0 * out->linesize[p], + out->linesize[p], + in->data[p] + y0 * in->linesize[p], + in->linesize[p], + width * ((depth + 7) / 8), + y1 - y0); + continue; + } + + if (s->SE[p].minX == INT16_MAX || + s->SE[p].minY == INT16_MAX || + s->SE[p].maxX == INT16_MIN || + s->SE[p].maxY == INT16_MIN) + goto copy; + + switch (s->mode) { + case ERODE: + ret = erode(&s->g[p], &s->f[p], &s->SE[p], &s->Ty[jobnr][0][p], y0, y1); + break; + case DILATE: + case GRADIENT: + ret = dilate(&s->g[p], &s->f[p], &s->SE[p], &s->Ty[jobnr][0][p], y0, y1); + break; + case OPEN: + case TOPHAT: + ret = erode(&s->h[p], &s->f[p], &s->SE[p], &s->Ty[jobnr][0][p], y0, y1); + break; + case CLOSE: + case BLACKHAT: + ret = dilate(&s->h[p], &s->f[p], &s->SE[p], &s->Ty[jobnr][0][p], y0, y1); + break; + default: + av_assert0(0); + } + + if (ret < 0) + return ret; + } + + return 0; +} + +static int morpho_sliceX(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) +{ + MorphoContext *s = ctx->priv; + int ret; + + for (int p = 0; p < s->nb_planes; p++) { + const int height = s->planeheight[p]; + const int y0 = (height * jobnr ) / nb_jobs; + const int y1 = (height * (jobnr+1)) / nb_jobs; + + if (ctx->is_disabled || !(s->planes & (1 << p))) { +copy: + continue; + } + + if (s->SE[p].minX == INT16_MAX || + s->SE[p].minY == INT16_MAX || + s->SE[p].maxX == INT16_MIN || + s->SE[p].maxY == INT16_MIN) + goto copy; + + switch (s->mode) { + case OPEN: + ret = dilate(&s->g[p], &s->h[p], &s->SE[p], &s->Ty[jobnr][1][p], y0, y1); + break; + case CLOSE: + ret = erode(&s->g[p], &s->h[p], &s->SE[p], &s->Ty[jobnr][1][p], y0, y1); + break; + case GRADIENT: + ret = erode(&s->h[p], &s->f[p], &s->SE[p], &s->Ty[jobnr][1][p], y0, y1); + if (ret < 0) + break; + difference(&s->g[p], &s->h[p], y0, y1); + break; + case TOPHAT: + ret = dilate(&s->g[p], &s->h[p], &s->SE[p], &s->Ty[jobnr][1][p], y0, y1); + if (ret < 0) + break; + difference2(&s->g[p], &s->f[p], y0, y1); + break; + case BLACKHAT: + ret = erode(&s->g[p], &s->h[p], &s->SE[p], &s->Ty[jobnr][1][p], y0, y1); + if (ret < 0) + break; + difference(&s->g[p], &s->f[p], y0, y1); + break; + default: + av_assert0(0); + } + + if (ret < 0) + return ret; + } + + return 0; +} + static int do_morpho(FFFrameSync *fs) { AVFilterContext *ctx = fs->parent; AVFilterLink *outlink = ctx->outputs[0]; MorphoContext *s = ctx->priv; AVFrame *in = NULL, *structurepic = NULL; + ThreadData td; AVFrame *out; int ret; @@ -812,6 +935,12 @@ static int do_morpho(FFFrameSync *fs) const int ssrc_linesize = structurepic->linesize[p]; const int swidth = s->splanewidth[p]; const int sheight = s->splaneheight[p]; + const uint8_t *src = in->data[p]; + int src_linesize = in->linesize[p]; + uint8_t *dst = out->data[p]; + int dst_linesize = out->linesize[p]; + const int width = s->planewidth[p]; + const int height = s->planeheight[p]; const int depth = s->depth; int type_size = s->type_size; @@ -826,34 +955,6 @@ static int do_morpho(FFFrameSync *fs) goto fail; s->got_structure[p] = 1; } - } - - for (int p = 0; p < s->nb_planes; p++) { - const uint8_t *src = in->data[p]; - int src_linesize = in->linesize[p]; - uint8_t *dst = out->data[p]; - int dst_linesize = out->linesize[p]; - const int width = s->planewidth[p]; - const int height = s->planeheight[p]; - const int depth = s->depth; - int type_size = s->type_size; - - if (ctx->is_disabled || !(s->planes & (1 << p))) { -copy: - av_image_copy_plane(out->data[p] + 0 * out->linesize[p], - out->linesize[p], - in->data[p] + 0 * in->linesize[p], - in->linesize[p], - width * ((depth + 7) / 8), - height); - continue; - } - - if (s->SE[p].minX == INT16_MAX || - s->SE[p].minY == INT16_MAX || - s->SE[p].maxX == INT16_MIN || - s->SE[p].maxY == INT16_MIN) - goto copy; ret = read_iplane(&s->f[p], src, src_linesize, width, height, 1, type_size, depth); if (ret < 0) @@ -864,74 +965,29 @@ static int do_morpho(FFFrameSync *fs) goto fail; switch (s->mode) { - case ERODE: - ret = erode(&s->g[p], &s->f[p], &s->SE[p], &s->Ty[0][p]); - break; - case DILATE: - ret = dilate(&s->g[p], &s->f[p], &s->SE[p], &s->Ty[0][p]); - break; case OPEN: - ret = read_iplane(&s->h[p], s->temp->data[p], s->temp->linesize[p], width, height, 1, type_size, depth); - if (ret < 0) - break; - ret = erode(&s->h[p], &s->f[p], &s->SE[p], &s->Ty[0][p]); - if (ret < 0) - break; - ret = dilate(&s->g[p], &s->h[p], &s->SE[p], &s->Ty[1][p]); - break; case CLOSE: - ret = read_iplane(&s->h[p], s->temp->data[p], s->temp->linesize[p], width, height, 1, type_size, depth); - if (ret < 0) - break; - ret = dilate(&s->h[p], &s->f[p], &s->SE[p], &s->Ty[0][p]); - if (ret < 0) - break; - ret = erode(&s->g[p], &s->h[p], &s->SE[p], &s->Ty[1][p]); - break; case GRADIENT: - ret = read_iplane(&s->h[p], s->temp->data[p], s->temp->linesize[p], width, height, 1, type_size, depth); - if (ret < 0) - break; - ret = dilate(&s->g[p], &s->f[p], &s->SE[p], &s->Ty[0][p]); - if (ret < 0) - break; - ret = erode(&s->h[p], &s->f[p], &s->SE[p], &s->Ty[1][p]); - if (ret < 0) - break; - difference(&s->g[p], &s->h[p]); - break; case TOPHAT: - ret = read_iplane(&s->h[p], s->temp->data[p], s->temp->linesize[p], width, height, 1, type_size, depth); - if (ret < 0) - break; - ret = erode(&s->h[p], &s->f[p], &s->SE[p], &s->Ty[0][p]); - if (ret < 0) - break; - ret = dilate(&s->g[p], &s->h[p], &s->SE[p], &s->Ty[1][p]); - if (ret < 0) - break; - difference2(&s->g[p], &s->f[p]); - break; case BLACKHAT: ret = read_iplane(&s->h[p], s->temp->data[p], s->temp->linesize[p], width, height, 1, type_size, depth); - if (ret < 0) - break; - ret = dilate(&s->h[p], &s->f[p], &s->SE[p], &s->Ty[0][p]); - if (ret < 0) - break; - ret = erode(&s->g[p], &s->h[p], &s->SE[p], &s->Ty[1][p]); - if (ret < 0) - break; - difference(&s->g[p], &s->f[p]); break; - default: - av_assert0(0); } if (ret < 0) goto fail; } + td.in = in; td.out = out; + ret = ff_filter_execute(ctx, morpho_slice, &td, NULL, + FFMIN3(s->planeheight[1], s->planeheight[2], + FFMIN(MAX_THREADS, ff_filter_get_nb_threads(ctx)))); + if (ret == 0 && (s->mode != ERODE && s->mode != DILATE)) { + ff_filter_execute(ctx, morpho_sliceX, NULL, NULL, + FFMIN3(s->planeheight[1], s->planeheight[2], + FFMIN(MAX_THREADS, ff_filter_get_nb_threads(ctx)))); + } + av_frame_free(&in); out->pts = av_rescale_q(s->fs.pts, s->fs.time_base, outlink->time_base); return ff_filter_frame(outlink, out); @@ -984,8 +1040,10 @@ static av_cold void uninit(AVFilterContext *ctx) free_iplane(&s->g[p]); free_iplane(&s->h[p]); free_chord_set(&s->SE[p]); - free_lut(&s->Ty[0][p]); - free_lut(&s->Ty[1][p]); + for (int n = 0; n < MAX_THREADS; n++) { + free_lut(&s->Ty[n][0][p]); + free_lut(&s->Ty[n][1][p]); + } } ff_framesync_uninit(&s->fs); @@ -1027,6 +1085,7 @@ const AVFilter ff_vf_morpho = { FILTER_INPUTS(morpho_inputs), FILTER_OUTPUTS(morpho_outputs), FILTER_PIXFMTS_ARRAY(pix_fmts), - .flags = AVFILTER_FLAG_SUPPORT_TIMELINE_INTERNAL, + .flags = AVFILTER_FLAG_SUPPORT_TIMELINE_INTERNAL | + AVFILTER_FLAG_SLICE_THREADS, .process_command = ff_filter_process_command, }; From 21a0b6bca80192a641b09774c603bd1acbda316e Mon Sep 17 00:00:00 2001 From: Thilo Borgmann Date: Mon, 8 May 2023 14:37:26 +0200 Subject: [PATCH 0938/2172] avfilter/vf_mpdecimate: Add option to keep the first N similar frames before dropping This allows for decimating large similar portions of a video while preserving small ones. --- doc/filters.texi | 7 +++++++ libavfilter/version.h | 2 +- libavfilter/vf_mpdecimate.c | 19 +++++++++++++++++-- 3 files changed, 25 insertions(+), 3 deletions(-) diff --git a/doc/filters.texi b/doc/filters.texi index 89dd59587be..284b6d798a1 100644 --- a/doc/filters.texi +++ b/doc/filters.texi @@ -17656,6 +17656,13 @@ number of previous sequentially dropped frames. Default value is 0. +@item keep +Set the maximum number of consecutive similar frames to ignore before to start dropping them. +If the value is 0, the frame is dropped disregarding the +number of previous sequentially similar frames. + +Default value is 0. + @item hi @item lo @item frac diff --git a/libavfilter/version.h b/libavfilter/version.h index 4dc176dc556..c303f96b153 100644 --- a/libavfilter/version.h +++ b/libavfilter/version.h @@ -32,7 +32,7 @@ #include "version_major.h" #define LIBAVFILTER_VERSION_MINOR 7 -#define LIBAVFILTER_VERSION_MICRO 101 +#define LIBAVFILTER_VERSION_MICRO 102 #define LIBAVFILTER_VERSION_INT AV_VERSION_INT(LIBAVFILTER_VERSION_MAJOR, \ diff --git a/libavfilter/vf_mpdecimate.c b/libavfilter/vf_mpdecimate.c index 71f673cb646..a7b50d3973d 100644 --- a/libavfilter/vf_mpdecimate.c +++ b/libavfilter/vf_mpdecimate.c @@ -46,6 +46,9 @@ typedef struct DecimateContext { int drop_count; ///< if positive: number of frames sequentially dropped ///< if negative: number of sequential frames which were not dropped + int max_keep_count; ///< number of similar frames to ignore before to start dropping them + int keep_count; ///< number of similar frames already ignored + int hsub, vsub; ///< chroma subsampling values AVFrame *ref; ///< reference picture av_pixelutils_sad_fn sad; ///< sum of absolute difference function @@ -57,6 +60,8 @@ typedef struct DecimateContext { static const AVOption mpdecimate_options[] = { { "max", "set the maximum number of consecutive dropped frames (positive), or the minimum interval between dropped frames (negative)", OFFSET(max_drop_count), AV_OPT_TYPE_INT, {.i64=0}, INT_MIN, INT_MAX, FLAGS }, + { "keep", "set the number of similar consecutive frames to be kept before starting to drop similar frames", + OFFSET(max_keep_count), AV_OPT_TYPE_INT, {.i64=0}, 0, INT_MAX, FLAGS }, { "hi", "set high dropping threshold", OFFSET(hi), AV_OPT_TYPE_INT, {.i64=64*12}, INT_MIN, INT_MAX, FLAGS }, { "lo", "set low dropping threshold", OFFSET(lo), AV_OPT_TYPE_INT, {.i64=64*5}, INT_MIN, INT_MAX, FLAGS }, { "frac", "set fraction dropping threshold", OFFSET(frac), AV_OPT_TYPE_FLOAT, {.dbl=0.33}, 0, 1, FLAGS }, @@ -112,6 +117,12 @@ static int decimate_frame(AVFilterContext *ctx, DecimateContext *decimate = ctx->priv; int plane; + if (decimate->max_keep_count > 0 && + decimate->keep_count > -1 && + decimate->keep_count < decimate->max_keep_count) { + decimate->keep_count++; + return 0; + } if (decimate->max_drop_count > 0 && decimate->drop_count >= decimate->max_drop_count) return 0; @@ -196,20 +207,24 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *cur) if (decimate->ref && decimate_frame(inlink->dst, cur, decimate->ref)) { decimate->drop_count = FFMAX(1, decimate->drop_count+1); + decimate->keep_count = -1; // do not keep any more frames until non-similar frames are detected } else { av_frame_free(&decimate->ref); decimate->ref = cur; decimate->drop_count = FFMIN(-1, decimate->drop_count-1); + if (decimate->keep_count < 0) // re-enable counting similiar frames to ignore before dropping + decimate->keep_count = 0; if ((ret = ff_filter_frame(outlink, av_frame_clone(cur))) < 0) return ret; } av_log(inlink->dst, AV_LOG_DEBUG, - "%s pts:%s pts_time:%s drop_count:%d\n", + "%s pts:%s pts_time:%s drop_count:%d keep_count:%d\n", decimate->drop_count > 0 ? "drop" : "keep", av_ts2str(cur->pts), av_ts2timestr(cur->pts, &inlink->time_base), - decimate->drop_count); + decimate->drop_count, + decimate->keep_count); if (decimate->drop_count > 0) av_frame_free(&cur); From 90096dd04216b1bb398525631206172f07e382ca Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Tue, 9 May 2023 00:40:32 +0200 Subject: [PATCH 0939/2172] avfilter/vf_feedback: fix artifacts with subsampled chroma --- libavfilter/vf_feedback.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/libavfilter/vf_feedback.c b/libavfilter/vf_feedback.c index 15cbf95c54d..dc832c46719 100644 --- a/libavfilter/vf_feedback.c +++ b/libavfilter/vf_feedback.c @@ -163,11 +163,11 @@ static int activate(AVFilterContext *ctx) src->data[0] + y * src->linesize[0], src->width * s->max_step[0]); } - for (int i = 1; i < 3; i ++) { + for (int i = 1; i < 3; i++) { if (dst->data[i]) { for (int y = 0; y < src->height; y++) { - memmove(dst->data[i] + ((s->y + y) >> s->vsub) * dst->linesize[i] + ((s->x * s->max_step[i]) >> s->hsub), - src->data[i] + (y >> s->vsub) * src->linesize[i], (src->width * s->max_step[i]) >> s->hsub); + memmove(dst->data[i] + ((s->y + y) >> s->vsub) * dst->linesize[i] + (s->x >> s->hsub) * s->max_step[i], + src->data[i] + (y >> s->vsub) * src->linesize[i], (src->width >> s->hsub) * s->max_step[i]); } } } @@ -213,7 +213,7 @@ static int activate(AVFilterContext *ctx) for (int i = 1; i < 3; i ++) { if (frame->data[i]) { frame->data[i] += (s->y >> s->vsub) * frame->linesize[i]; - frame->data[i] += (s->x * s->max_step[i]) >> s->hsub; + frame->data[i] += (s->x >> s->hsub) * s->max_step[i]; } } From 086a0f3e5edee4d5f97c5759fbf5c893f58fb6e5 Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Mon, 8 May 2023 22:23:35 +0200 Subject: [PATCH 0940/2172] avfilter/asrc_anoisesrc: improve velvet noise output --- doc/filters.texi | 3 +++ libavfilter/asrc_anoisesrc.c | 25 +++++++++++++++---------- 2 files changed, 18 insertions(+), 10 deletions(-) diff --git a/doc/filters.texi b/doc/filters.texi index 284b6d798a1..b965f05e602 100644 --- a/doc/filters.texi +++ b/doc/filters.texi @@ -7951,6 +7951,9 @@ Specify a value used to seed the PRNG. @item nb_samples, n Set the number of samples per each output frame, default is 1024. + +@item density +Set the density (0.0 - 1.0) for the velvet noise generator, default is 0.05. @end table @subsection Examples diff --git a/libavfilter/asrc_anoisesrc.c b/libavfilter/asrc_anoisesrc.c index 96a8fd63e9b..1c8dccf689e 100644 --- a/libavfilter/asrc_anoisesrc.c +++ b/libavfilter/asrc_anoisesrc.c @@ -31,6 +31,7 @@ typedef struct ANoiseSrcContext { const AVClass *class; int sample_rate; double amplitude; + double density; int64_t duration; int color; int64_t seed; @@ -38,7 +39,7 @@ typedef struct ANoiseSrcContext { int64_t pts; int infinite; - double (*filter)(double white, double *buf, double half_amplitude); + double (*filter)(double white, double *buf); double buf[7]; AVLFG c; } ANoiseSrcContext; @@ -76,6 +77,7 @@ static const AVOption anoisesrc_options[] = { { "s", "set random seed", OFFSET(seed), AV_OPT_TYPE_INT64, {.i64 = -1}, -1, UINT_MAX, FLAGS }, { "nb_samples", "set the number of samples per requested frame", OFFSET(nb_samples), AV_OPT_TYPE_INT, {.i64 = 1024}, 1, INT_MAX, FLAGS }, { "n", "set the number of samples per requested frame", OFFSET(nb_samples), AV_OPT_TYPE_INT, {.i64 = 1024}, 1, INT_MAX, FLAGS }, + { "density", "set density", OFFSET(density), AV_OPT_TYPE_DOUBLE, {.dbl = 0.05}, 0., 1., FLAGS }, {NULL} }; @@ -101,12 +103,12 @@ static av_cold int query_formats(AVFilterContext *ctx) return ff_set_common_samplerates_from_list(ctx, sample_rates); } -static double white_filter(double white, double *buf, double ha) +static double white_filter(double white, double *buf) { return white; } -static double pink_filter(double white, double *buf, double ha) +static double pink_filter(double white, double *buf) { double pink; @@ -122,7 +124,7 @@ static double pink_filter(double white, double *buf, double ha) return pink * 0.11; } -static double blue_filter(double white, double *buf, double ha) +static double blue_filter(double white, double *buf) { double blue; @@ -138,7 +140,7 @@ static double blue_filter(double white, double *buf, double ha) return blue * 0.11; } -static double brown_filter(double white, double *buf, double ha) +static double brown_filter(double white, double *buf) { double brown; @@ -147,7 +149,7 @@ static double brown_filter(double white, double *buf, double ha) return brown * 3.5; } -static double violet_filter(double white, double *buf, double ha) +static double violet_filter(double white, double *buf) { double violet; @@ -156,9 +158,10 @@ static double violet_filter(double white, double *buf, double ha) return violet * 3.5; } -static double velvet_filter(double white, double *buf, double ha) +static double velvet_filter(double white, double *buf) { - return 2. * ha * ((white > ha) - (white < -ha)); + double awhite = fabs(white); + return FFDIFFSIGN(white, 0.0) * buf[1] * (awhite < buf[0]); } static av_cold int config_props(AVFilterLink *outlink) @@ -180,7 +183,9 @@ static av_cold int config_props(AVFilterLink *outlink) case NM_BROWN: s->filter = brown_filter; break; case NM_BLUE: s->filter = blue_filter; break; case NM_VIOLET: s->filter = violet_filter; break; - case NM_VELVET: s->filter = velvet_filter; break; + case NM_VELVET: s->buf[0] = s->amplitude * s->density; + s->buf[1] = s->amplitude; + s->filter = velvet_filter; break; } return 0; @@ -213,7 +218,7 @@ static int activate(AVFilterContext *ctx) for (i = 0; i < nb_samples; i++) { double white; white = s->amplitude * ((2 * ((double) av_lfg_get(&s->c) / 0xffffffff)) - 1); - dst[i] = s->filter(white, s->buf, s->amplitude * 0.5); + dst[i] = s->filter(white, s->buf); } if (!s->infinite) From 3475c8342c850bddff7c5bd43f608b87f7a4ded9 Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Sat, 6 May 2023 22:52:47 +0200 Subject: [PATCH 0941/2172] avfilter: add zoneplate video test source --- Changelog | 1 + doc/filters.texi | 98 ++++++++++++++++++ libavfilter/Makefile | 1 + libavfilter/allfilters.c | 1 + libavfilter/version.h | 4 +- libavfilter/vsrc_testsrc.c | 197 +++++++++++++++++++++++++++++++++++++ 6 files changed, 300 insertions(+), 2 deletions(-) diff --git a/Changelog b/Changelog index 2061aaf4623..b7ffeeff0dd 100644 --- a/Changelog +++ b/Changelog @@ -8,6 +8,7 @@ version : - afireqsrc audio source filter - arls filter - ffmpeg CLI new option: -readrate_initial_burst +- zoneplate video source filter version 6.0: - Radiance HDR image support diff --git a/doc/filters.texi b/doc/filters.texi index b965f05e602..d2f0eab6192 100644 --- a/doc/filters.texi +++ b/doc/filters.texi @@ -28083,6 +28083,104 @@ Set max jump for single pan destination. Allowed range is from 1 to 10000. Set fractal type, can be default @code{carpet} or @code{triangle}. @end table +@section zoneplate +Generate a zoneplate test video pattern. + +This source accepts the following options: + +@table @option +@item size, s +Set frame size. For the syntax of this option, check the @ref{video size syntax,,"Video +size" section in the ffmpeg-utils manual,ffmpeg-utils}. Default value is "320x240". + +@item rate, r +Set frame rate, expressed as number of frames per second. Default +value is "25". + +@item duration, d +Set the duration of the sourced video. See +@ref{time duration syntax,,the Time duration section in the ffmpeg-utils(1) manual,ffmpeg-utils} +for the accepted syntax. + +If not specified, or the expressed duration is negative, the video is +supposed to be generated forever. + +@item sar +Set the sample aspect ratio of the sourced video. + +@item precision +Set precision in bits for look-up table for sine calculations. Default value is 10. +Allowed range is from 4 to 16. + +@item xo +Set horizontal axis offset for output signal. Default value is 0. + +@item yo +Set vertical axis offset for output signal. Default value is 0. + +@item to +Set time axis offset for output signal. Default value is 0. + +@item k0 +Set 0-order, constant added to signal phase. Default value is 0. + +@item kx +Set 1-order, phase factor multiplier for horizontal axis. Default value is 0. + +@item ky +Set 1-order, phase factor multiplier for vertical axis. Default value is 0. + +@item kt +Set 1-order, phase factor multiplier for time axis. Default value is 0. + +@item kxt, kyt, kxy +Set phase factor multipliers for combination of spatial and temporal axis. +Default value is 0. + +@item kx2 +Set 2-order, phase factor multiplier for horizontal axis. Default value is 0. + +@item ky2 +Set 2-order, phase factor multiplier for vertical axis. Default value is 0. + +@item kt2 +Set 2-order, phase factor multiplier for time axis. Default value is 0. + +@item ku +Set the constant added to final phase to produce chroma-blue component of signal. +Default value is 0. + +@item kv +Set the constant added to final phase to produce chroma-red component of signal. +Default value is 0. +@end table + +@subsection Commands + +This source supports the some above options as @ref{commands}. + +@subsection Examples + +@itemize +@item +Generate horizontal color sine sweep: +@example +zoneplate=ku=512:kv=0:kt2=0:kx2=256:s=wvga:xo=-426:kt=11 +@end example + +@item +Generate vertical color sine sweep: +@example +zoneplate=ku=512:kv=0:kt2=0:ky2=156:s=wvga:yo=-240:kt=11 +@end example + +@item +Generate circular zone-plate: +@example +zoneplate=ku=512:kv=100:kt2=0:ky2=256:kx2=556:s=wvga:yo=0:kt=11 +@end example +@end itemize + @c man end VIDEO SOURCES @chapter Video Sinks diff --git a/libavfilter/Makefile b/libavfilter/Makefile index 482aeaff4bf..01f1cdfe0cd 100644 --- a/libavfilter/Makefile +++ b/libavfilter/Makefile @@ -592,6 +592,7 @@ OBJS-$(CONFIG_SMPTEHDBARS_FILTER) += vsrc_testsrc.o OBJS-$(CONFIG_TESTSRC_FILTER) += vsrc_testsrc.o OBJS-$(CONFIG_TESTSRC2_FILTER) += vsrc_testsrc.o OBJS-$(CONFIG_YUVTESTSRC_FILTER) += vsrc_testsrc.o +OBJS-$(CONFIG_ZONEPLATE_FILTER) += vsrc_testsrc.o OBJS-$(CONFIG_NULLSINK_FILTER) += vsink_nullsink.o diff --git a/libavfilter/allfilters.c b/libavfilter/allfilters.c index 6994124ce86..4083296bb29 100644 --- a/libavfilter/allfilters.c +++ b/libavfilter/allfilters.c @@ -557,6 +557,7 @@ extern const AVFilter ff_vsrc_smptehdbars; extern const AVFilter ff_vsrc_testsrc; extern const AVFilter ff_vsrc_testsrc2; extern const AVFilter ff_vsrc_yuvtestsrc; +extern const AVFilter ff_vsrc_zoneplate; extern const AVFilter ff_vsink_nullsink; diff --git a/libavfilter/version.h b/libavfilter/version.h index c303f96b153..ba8a6fdab24 100644 --- a/libavfilter/version.h +++ b/libavfilter/version.h @@ -31,8 +31,8 @@ #include "version_major.h" -#define LIBAVFILTER_VERSION_MINOR 7 -#define LIBAVFILTER_VERSION_MICRO 102 +#define LIBAVFILTER_VERSION_MINOR 8 +#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 f391ac02e05..0138e14fb9b 100644 --- a/libavfilter/vsrc_testsrc.c +++ b/libavfilter/vsrc_testsrc.c @@ -88,6 +88,15 @@ typedef struct TestSourceContext { /* only used by haldclut */ int level; + + /* only used by zoneplate */ + int k0, kx, ky, kt; + int kxt, kyt, kxy; + int kx2, ky2, kt2; + int xo, yo, to, kU, kV; + int lut_precision; + uint8_t *lut; + int (*fill_slice_fn)(AVFilterContext *ctx, void *arg, int job, int nb_jobs); } TestSourceContext; #define OFFSET(x) offsetof(TestSourceContext, x) @@ -135,6 +144,7 @@ static av_cold void uninit(AVFilterContext *ctx) TestSourceContext *test = ctx->priv; av_frame_free(&test->picref); + av_freep(&test->lut); } static int config_props(AVFilterLink *outlink) @@ -2049,3 +2059,190 @@ const AVFilter ff_vsrc_colorchart = { }; #endif /* CONFIG_COLORCHART_FILTER */ + +#if CONFIG_ZONEPLATE_FILTER + +static const AVOption zoneplate_options[] = { + COMMON_OPTIONS + { "precision", "set LUT precision", OFFSET(lut_precision), AV_OPT_TYPE_INT, {.i64=10}, 4, 16, FLAGS }, + { "xo", "set X-axis offset", OFFSET(xo), AV_OPT_TYPE_INT, {.i64=0}, INT_MIN, INT_MAX, FLAGSR }, + { "yo", "set Y-axis offset", OFFSET(yo), AV_OPT_TYPE_INT, {.i64=0}, INT_MIN, INT_MAX, FLAGSR }, + { "to", "set T-axis offset", OFFSET(to), AV_OPT_TYPE_INT, {.i64=0}, INT_MIN, INT_MAX, FLAGSR }, + { "k0", "set 0-order phase", OFFSET(k0), AV_OPT_TYPE_INT, {.i64=0}, INT_MIN, INT_MAX, FLAGSR }, + { "kx", "set 1-order X-axis phase", OFFSET(kx), AV_OPT_TYPE_INT, {.i64=0}, INT_MIN, INT_MAX, FLAGSR }, + { "ky", "set 1-order Y-axis phase", OFFSET(ky), AV_OPT_TYPE_INT, {.i64=0}, INT_MIN, INT_MAX, FLAGSR }, + { "kt", "set 1-order T-axis phase", OFFSET(kt), AV_OPT_TYPE_INT, {.i64=0}, INT_MIN, INT_MAX, FLAGSR }, + { "kxt", "set X-axis*T-axis product phase", OFFSET(kxt), AV_OPT_TYPE_INT, {.i64=0}, INT_MIN, INT_MAX, FLAGSR }, + { "kyt", "set Y-axis*T-axis product phase", OFFSET(kyt), AV_OPT_TYPE_INT, {.i64=0}, INT_MIN, INT_MAX, FLAGSR }, + { "kxy", "set X-axis*Y-axis product phase", OFFSET(kxy), AV_OPT_TYPE_INT, {.i64=0}, INT_MIN, INT_MAX, FLAGSR }, + { "kx2", "set 2-order X-axis phase", OFFSET(kx2), AV_OPT_TYPE_INT, {.i64=0}, INT_MIN, INT_MAX, FLAGSR }, + { "ky2", "set 2-order Y-axis phase", OFFSET(ky2), AV_OPT_TYPE_INT, {.i64=0}, INT_MIN, INT_MAX, FLAGSR }, + { "kt2", "set 2-order T-axis phase", OFFSET(kt2), AV_OPT_TYPE_INT, {.i64=0}, INT_MIN, INT_MAX, FLAGSR }, + { "ku", "set 0-order U-color phase", OFFSET(kU), AV_OPT_TYPE_INT, {.i64=0}, INT_MIN, INT_MAX, FLAGSR }, + { "kv", "set 0-order V-color phase", OFFSET(kV), AV_OPT_TYPE_INT, {.i64=0}, INT_MIN, INT_MAX, FLAGSR }, + { NULL } +}; + +AVFILTER_DEFINE_CLASS(zoneplate); + +#define ZONEPLATE_SLICE(name, type) \ +static int zoneplate_fill_slice_##name(AVFilterContext *ctx, \ + void *arg, int job, \ + int nb_jobs) \ +{ \ + TestSourceContext *test = ctx->priv; \ + AVFrame *frame = arg; \ + const int w = frame->width; \ + const int h = frame->height; \ + const int kxt = test->kxt, kyt = test->kyt, kx2 = test->kx2; \ + const int t = test->pts + test->to, k0 = test->k0; \ + const int kt = test->kt, kt2 = test->kt2, ky2 = test->ky2; \ + const int ky = test->ky, kx = test->kx, kxy = test->kxy; \ + const int lut_mask = (1 << test->lut_precision) - 1; \ + const int nkt2t = kt2 * t * t, nktt = kt * t; \ + const int start = (h * job ) / nb_jobs; \ + const int end = (h * (job+1)) / nb_jobs; \ + const int ylinesize = frame->linesize[0] / sizeof(type); \ + const int ulinesize = frame->linesize[1] / sizeof(type); \ + const int vlinesize = frame->linesize[2] / sizeof(type); \ + const int xreset = -(w / 2) - test->xo; \ + const int yreset = -(h / 2) - test->yo + start; \ + const int kU = test->kU, kV = test->kV; \ + const int skxy = 0xffff / (w / 2); \ + const int skx2 = 0xffff / w; \ + const int dkxt = kxt * t; \ + type *ydst = ((type *)frame->data[0]) + start * ylinesize; \ + type *udst = ((type *)frame->data[1]) + start * ulinesize; \ + type *vdst = ((type *)frame->data[2]) + start * vlinesize; \ + const type *lut = (const type *)test->lut; \ + int akx, akxt, aky, akyt; \ + \ + aky = start * ky; \ + akyt = start * kyt * t; \ + \ + for (int j = start, y = yreset; j < end; j++, y++) { \ + const int dkxy = kxy * y * skxy; \ + const int nky2kt2 = (ky2 * y * y) / h + (nkt2t >> 1); \ + int akxy = dkxy * xreset; \ + \ + akx = 0; \ + akxt = 0; \ + aky += ky; \ + akyt += kyt * t; \ + \ + for (int i = 0, x = xreset; i < w; i++, x++) { \ + int phase = k0, uphase = kU, vphase = kV; \ + \ + akx += kx; \ + phase += akx + aky + nktt; \ + \ + akxt += dkxt; \ + akxy += dkxy; \ + phase += akxt + akyt; \ + phase += akxy >> 16; \ + phase += ((kx2 * x * x * skx2) >> 16) + nky2kt2; \ + uphase += phase; \ + vphase += phase; \ + \ + ydst[i] = lut[phase & lut_mask]; \ + udst[i] = lut[uphase & lut_mask]; \ + vdst[i] = lut[vphase & lut_mask]; \ + } \ + \ + ydst += ylinesize; \ + udst += ulinesize; \ + vdst += vlinesize; \ + } \ + \ + return 0; \ +} + +ZONEPLATE_SLICE( 8, uint8_t) +ZONEPLATE_SLICE( 9, uint16_t) +ZONEPLATE_SLICE(10, uint16_t) +ZONEPLATE_SLICE(12, uint16_t) +ZONEPLATE_SLICE(14, uint16_t) +ZONEPLATE_SLICE(16, uint16_t) + +static void zoneplate_fill_picture(AVFilterContext *ctx, AVFrame *frame) +{ + TestSourceContext *test = ctx->priv; + ff_filter_execute(ctx, test->fill_slice_fn, frame, NULL, + FFMIN(frame->height, ff_filter_get_nb_threads(ctx))); +} + +static int zoneplate_config_props(AVFilterLink *outlink) +{ + AVFilterContext *ctx = outlink->src; + TestSourceContext *test = ctx->priv; + const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(outlink->format); + const int lut_size = 1 << test->lut_precision; + const int depth = desc->comp[0].depth; + uint16_t *lut16; + uint8_t *lut8; + + if (av_image_check_size(test->w, test->h, 0, ctx) < 0) + return AVERROR(EINVAL); + + test->lut = av_calloc(lut_size, sizeof(*test->lut) * ((depth + 7) / 8)); + if (!test->lut) + return AVERROR(ENOMEM); + + lut8 = test->lut; + lut16 = (uint16_t *)test->lut; + switch (depth) { + case 8: + for (int i = 0; i < lut_size; i++) + lut8[i] = lrintf(255.f * (0.5f + 0.5f * sinf((2.f * M_PI * i) / lut_size))); + break; + default: + for (int i = 0; i < lut_size; i++) + lut16[i] = lrintf(((1 << depth) - 1) * (0.5f + 0.5f * sinf((2.f * M_PI * i) / lut_size))); + break; + } + + test->draw_once = 0; + test->fill_picture_fn = zoneplate_fill_picture; + + switch (depth) { + case 8: test->fill_slice_fn = zoneplate_fill_slice_8; break; + case 9: test->fill_slice_fn = zoneplate_fill_slice_9; break; + case 10: test->fill_slice_fn = zoneplate_fill_slice_10; break; + case 12: test->fill_slice_fn = zoneplate_fill_slice_12; break; + case 14: test->fill_slice_fn = zoneplate_fill_slice_14; break; + case 16: test->fill_slice_fn = zoneplate_fill_slice_16; break; + } + return config_props(outlink); +} + +static const enum AVPixelFormat zoneplate_pix_fmts[] = { + AV_PIX_FMT_YUV444P, AV_PIX_FMT_YUV444P9, + AV_PIX_FMT_YUV444P10, AV_PIX_FMT_YUV444P12, + AV_PIX_FMT_YUV444P14, AV_PIX_FMT_YUV444P16, + AV_PIX_FMT_NONE, +}; + +static const AVFilterPad avfilter_vsrc_zoneplate_outputs[] = { + { + .name = "default", + .type = AVMEDIA_TYPE_VIDEO, + .config_props = zoneplate_config_props, + }, +}; + +const AVFilter ff_vsrc_zoneplate = { + .name = "zoneplate", + .description = NULL_IF_CONFIG_SMALL("Generate zone-plate."), + .priv_size = sizeof(TestSourceContext), + .priv_class = &zoneplate_class, + .init = init, + .uninit = uninit, + .activate = activate, + .inputs = NULL, + FILTER_OUTPUTS(avfilter_vsrc_zoneplate_outputs), + FILTER_PIXFMTS_ARRAY(zoneplate_pix_fmts), + .flags = AVFILTER_FLAG_SLICE_THREADS, + .process_command = ff_filter_process_command, +}; + +#endif /* CONFIG_ZONEPLATE_FILTER */ From 54353ce88eb5594c480d87888904d9ae8f39355d Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Tue, 9 May 2023 11:50:56 +0200 Subject: [PATCH 0942/2172] avfilter/vf_estdif: fix recently introduced regression --- libavfilter/vf_estdif.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavfilter/vf_estdif.c b/libavfilter/vf_estdif.c index 2bb1680f430..eae2650a21c 100644 --- a/libavfilter/vf_estdif.c +++ b/libavfilter/vf_estdif.c @@ -346,7 +346,7 @@ static int deinterlace_slice(AVFilterContext *ctx, void *arg, const int redge = s->redge; const int depth = s->depth; const int interlaced = !!(in->flags & AV_FRAME_FLAG_INTERLACED); - const int tff = (s->field == (s->parity == -1 ? interlaced ? (in->flags & AV_FRAME_FLAG_TOP_FIELD_FIRST) : 1 : + const int tff = (s->field == (s->parity == -1 ? interlaced ? !!(in->flags & AV_FRAME_FLAG_TOP_FIELD_FIRST) : 1 : s->parity ^ 1)); for (int plane = 0; plane < s->nb_planes; plane++) { From 16a86b443dba748ccbe174b9895a21fc8378889c Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Tue, 9 May 2023 09:40:00 +0200 Subject: [PATCH 0943/2172] avfilter/vf_estdif: remove float usage --- doc/filters.texi | 12 ++++++------ libavfilter/vf_estdif.c | 20 ++++++++++---------- 2 files changed, 16 insertions(+), 16 deletions(-) diff --git a/doc/filters.texi b/doc/filters.texi index d2f0eab6192..9fae135ec41 100644 --- a/doc/filters.texi +++ b/doc/filters.texi @@ -13069,16 +13069,16 @@ 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 1.0. -Allowed range is from 0 to 9. +Specify the edge cost for edge matching. Default value is 2. +Allowed range is from 0 to 50. @item mcost -Specify the middle cost for edge matching. Default value is 0.5. -Allowed range is from 0 to 1. +Specify the middle cost for edge matching. Default value is 1. +Allowed range is from 0 to 50. @item dcost -Specify the distance cost for edge matching. Default value is 0.5. -Allowed range is from 0 to 1. +Specify the distance cost for edge matching. Default value is 1. +Allowed range is from 0 to 50. @item interp Specify the interpolation used. Default is 4-point interpolation. It accepts one diff --git a/libavfilter/vf_estdif.c b/libavfilter/vf_estdif.c index eae2650a21c..452361d717f 100644 --- a/libavfilter/vf_estdif.c +++ b/libavfilter/vf_estdif.c @@ -35,9 +35,9 @@ 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 ecost; ///< edge cost for edge matching + int mcost; ///< middle cost for edge matching + int 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 @@ -92,11 +92,11 @@ static const AVOption estdif_options[] = { { "deint", "specify which frames to deinterlace", OFFSET(deint), AV_OPT_TYPE_INT, {.i64=0}, 0, 1, FLAGS, "deint" }, CONST("all", "deinterlace all frames", 0, "deint"), 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=1},0,9,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, }, + { "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_INT, {.i64=2}, 0, 50, FLAGS }, + { "mcost", "specify the middle cost for edge matching", OFFSET(mcost), AV_OPT_TYPE_INT, {.i64=1}, 0, 50, FLAGS }, + { "dcost", "specify the distance cost for edge matching", OFFSET(dcost), AV_OPT_TYPE_INT, {.i64=1}, 0, 50, 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"), @@ -265,10 +265,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 ecost = s->ecost; \ const int dcost = s->dcost * s->max; \ const int end = width - 1; \ - const atype mcost = s->mcost * s->redge * 4.f; \ + const int mcost = s->mcost; \ atype sd[S], sD[S], di = 0; \ atype dmin = amax; \ int k = *K; \ From 57f264e78cb06fd8686b78f93b057122afdb3d44 Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Tue, 9 May 2023 10:20:03 +0200 Subject: [PATCH 0944/2172] avfilter/vf_estdif: simplify finding minimum score --- libavfilter/vf_estdif.c | 30 +++++++++++++----------------- 1 file changed, 13 insertions(+), 17 deletions(-) diff --git a/libavfilter/vf_estdif.c b/libavfilter/vf_estdif.c index 452361d717f..91e8431e353 100644 --- a/libavfilter/vf_estdif.c +++ b/libavfilter/vf_estdif.c @@ -266,11 +266,12 @@ static void interpolate_##ss(ESTDIFContext *s, uint8_t *ddst, \ const type *const next3_line = (const type *const)nnext3_line; \ const int interp = s->interp; \ const int ecost = s->ecost; \ - const int dcost = s->dcost * s->max; \ - const int end = width - 1; \ + const int dcost = s->dcost; \ const int mcost = s->mcost; \ atype sd[S], sD[S], di = 0; \ + const int end = width - 1; \ atype dmin = amax; \ + int id = 0, iD = 0; \ int k = *K; \ \ for (int i = -rslope; i <= rslope && abs(k) > rslope; i++) { \ @@ -288,7 +289,11 @@ static void interpolate_##ss(ESTDIFContext *s, uint8_t *ddst, \ 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); \ + if (dmin > sD[i + rslope]) { \ + dmin = sD[i + rslope]; \ + di = 1; \ + iD = i; \ + } \ } \ \ for (int i = -rslope; i <= rslope; i++) { \ @@ -306,23 +311,14 @@ static void interpolate_##ss(ESTDIFContext *s, uint8_t *ddst, \ 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); \ - } \ - \ - for (int i = -rslope; i <= rslope && abs(k) > rslope; i++) { \ - if (dmin == sD[i + rslope]) { \ - di = 1; \ - k = i; \ - break; \ + if (dmin > sd[i + rslope]) { \ + dmin = sd[i + rslope]; \ + di = 0; \ + id = i; \ } \ } \ \ - for (int i = -rslope; i <= rslope && !di; i++) { \ - if (dmin == sd[i + rslope]) { \ - k += i; \ - break; \ - } \ - } \ + k = di ? iD : k + id; \ \ dst[x] = s->mid_##ss[interp](prev_line, next_line, \ prev2_line, next2_line, \ From 512bba3d1bd404627fb2799191605258654b693e Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Tue, 9 May 2023 21:44:10 +0200 Subject: [PATCH 0945/2172] avfilter/vf_varblur: add float format support --- libavfilter/vf_varblur.c | 45 +++++++++++++++++++++++++--------------- 1 file changed, 28 insertions(+), 17 deletions(-) diff --git a/libavfilter/vf_varblur.c b/libavfilter/vf_varblur.c index 3c020a8c3ec..19b8bb4dd55 100644 --- a/libavfilter/vf_varblur.c +++ b/libavfilter/vf_varblur.c @@ -39,7 +39,8 @@ typedef struct VarBlurContext { int planewidth[4]; int planeheight[4]; - AVFrame *sat; + uint8_t *sat[4]; + int sat_linesize[4]; int nb_planes; void (*compute_sat)(const uint8_t *ssrc, @@ -90,6 +91,7 @@ static const enum AVPixelFormat pix_fmts[] = { AV_PIX_FMT_GBRP12, AV_PIX_FMT_GBRP14, AV_PIX_FMT_GBRP16, AV_PIX_FMT_GBRAP, AV_PIX_FMT_GBRAP10, 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_GBRPF32, AV_PIX_FMT_GBRAPF32, AV_PIX_FMT_NONE }; @@ -104,7 +106,7 @@ static void compute_sat##depth(const uint8_t *ssrc, \ stype *dst = (stype *)dstp; \ \ linesize /= (depth / 8); \ - dst_linesize /= (depth / 2); \ + dst_linesize /= sizeof(stype); \ dst += dst_linesize; \ \ for (int y = 0; y < h; y++) { \ @@ -122,6 +124,7 @@ static void compute_sat##depth(const uint8_t *ssrc, \ COMPUTE_SAT(uint8_t, uint32_t, 8) COMPUTE_SAT(uint16_t, uint64_t, 16) +COMPUTE_SAT(float, double, 32) typedef struct ThreadData { AVFrame *in, *out, *radius; @@ -144,12 +147,12 @@ static int blur_plane##bits(AVFilterContext *ctx, \ int slice_start, int slice_end) \ { \ VarBlurContext *s = ctx->priv; \ - const int ddepth = s->depth; \ + const int ddepth = (bits == 32) ? 1 : s->depth; \ const int dst_linesize = ddst_linesize / (bits / 8); \ - const int ptr_linesize = pptr_linesize / (bits / 2); \ + const int ptr_linesize = pptr_linesize / sizeof(stype); \ const int rptr_linesize = rrptr_linesize / (bits / 8); \ - const type *rptr = (const type *)rrptr + slice_start * rptr_linesize; \ - type *dst = (type *)ddst + slice_start * dst_linesize; \ + const type *rptr = ((const type *)rrptr) + slice_start * rptr_linesize; \ + type *dst = ((type *)ddst) + slice_start * dst_linesize; \ const stype *ptr = (stype *)pptr; \ const float minr = 2.f * s->min_radius + 1.f; \ const float maxr = 2.f * s->max_radius + 1.f; \ @@ -182,7 +185,10 @@ static int blur_plane##bits(AVFilterContext *ctx, \ stype p0 = (br + tl - bl - tr) / div; \ stype n0 = (nbr + ntl - nbl - ntr) / ndiv; \ \ - dst[x] = av_clip_uintp2_c(lrintf( \ + if (bits == 32) \ + dst[x] = lerpf(p0, n0, factor); \ + else \ + dst[x] = av_clip_uintp2_c(lrintf( \ lerpf(p0, n0, factor)), \ ddepth); \ } \ @@ -196,6 +202,7 @@ static int blur_plane##bits(AVFilterContext *ctx, \ BLUR_PLANE(uint8_t, uint32_t, 8) BLUR_PLANE(uint16_t, uint64_t, 16) +BLUR_PLANE(float, double, 32) static int blur_planes(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) @@ -215,8 +222,8 @@ static int blur_planes(AVFilterContext *ctx, void *arg, const int dst_linesize = out->linesize[plane]; const uint8_t *rptr = radius->data[plane]; const int rptr_linesize = radius->linesize[plane]; - uint8_t *ptr = s->sat->data[plane]; - const int ptr_linesize = s->sat->linesize[plane]; + uint8_t *ptr = s->sat[plane]; + const int ptr_linesize = s->sat_linesize[plane]; const uint8_t *src = in->data[plane]; uint8_t *dst = out->data[plane]; @@ -263,8 +270,8 @@ static int blur_frame(AVFilterContext *ctx, AVFrame *in, AVFrame *radius) const int height = s->planeheight[plane]; const int width = s->planewidth[plane]; const int linesize = in->linesize[plane]; - uint8_t *ptr = s->sat->data[plane]; - const int ptr_linesize = s->sat->linesize[plane]; + uint8_t *ptr = s->sat[plane]; + const int ptr_linesize = s->sat_linesize[plane]; const uint8_t *src = in->data[plane]; if (!(s->planes & (1 << plane))) @@ -333,8 +340,8 @@ static int config_output(AVFilterLink *outlink) outlink->frame_rate = inlink->frame_rate; s->depth = desc->comp[0].depth; - s->blur_plane = s->depth <= 8 ? blur_plane8 : blur_plane16; - s->compute_sat = s->depth <= 8 ? compute_sat8 : compute_sat16; + s->blur_plane = s->depth <= 8 ? blur_plane8 : s->depth <= 16 ? blur_plane16 : blur_plane32; + s->compute_sat = s->depth <= 8 ? compute_sat8 : s->depth <= 16 ? compute_sat16 : compute_sat32; s->planewidth[1] = s->planewidth[2] = AV_CEIL_RSHIFT(outlink->w, desc->log2_chroma_w); s->planewidth[0] = s->planewidth[3] = outlink->w; @@ -343,9 +350,12 @@ static int config_output(AVFilterLink *outlink) s->nb_planes = av_pix_fmt_count_planes(outlink->format); - s->sat = ff_get_video_buffer(outlink, (outlink->w + 1) * 4 * ((s->depth + 7) / 8), outlink->h + 1); - if (!s->sat) - return AVERROR(ENOMEM); + for (int p = 0; p < s->nb_planes; p++) { + s->sat_linesize[p] = (outlink->w + 1) * (4 + 4 * (s->depth > 8)); + s->sat[p] = av_calloc(s->sat_linesize[p], outlink->h + 1); + if (!s->sat[p]) + return AVERROR(ENOMEM); + } s->fs.on_event = varblur_frame; if ((ret = ff_framesync_init_dualinput(&s->fs, ctx)) < 0) @@ -362,7 +372,8 @@ static av_cold void uninit(AVFilterContext *ctx) VarBlurContext *s = ctx->priv; ff_framesync_uninit(&s->fs); - av_frame_free(&s->sat); + for (int p = 0; p < 4; p++) + av_freep(&s->sat[p]); } static const AVFilterPad varblur_inputs[] = { From b5af451901e116c568442e72b8534cbd13545e73 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luk=C3=A1=C5=A1=20Lalinsk=C3=BD?= Date: Tue, 9 May 2023 08:30:03 +0200 Subject: [PATCH 0946/2172] avcodec/libmp3lame: make it possible to set copyright/original flags --- doc/encoders.texi | 7 +++++++ libavcodec/libmp3lame.c | 16 +++++++++++++--- 2 files changed, 20 insertions(+), 3 deletions(-) diff --git a/doc/encoders.texi b/doc/encoders.texi index 3cb6fc1ce72..20cb8a14217 100644 --- a/doc/encoders.texi +++ b/doc/encoders.texi @@ -864,6 +864,13 @@ Enable the encoder to use ABR when set to 1. The @command{lame} @option{--abr} sets the target bitrate, while this options only tells FFmpeg to use ABR still relies on @option{b} to set bitrate. +@item copyright (@emph{-c}) +Set MPEG audio copyright flag when set to 1. The default value is 0 +(disabled). + +@item original (@emph{-o}) +Set MPEG audio original flag when set to 1. The default value is 1 +(enabled). @end table @section libopencore-amrnb diff --git a/libavcodec/libmp3lame.c b/libavcodec/libmp3lame.c index e119189f2ae..312bc4230fa 100644 --- a/libavcodec/libmp3lame.c +++ b/libavcodec/libmp3lame.c @@ -55,6 +55,8 @@ typedef struct LAMEContext { float *samples_flt[2]; AudioFrameQueue afq; AVFloatDSPContext *fdsp; + int copyright; + int original; } LAMEContext; @@ -137,6 +139,12 @@ static av_cold int mp3lame_encode_init(AVCodecContext *avctx) /* bit reservoir usage */ lame_set_disable_reservoir(s->gfp, !s->reservoir); + /* copyright flag */ + lame_set_copyright(s->gfp, s->copyright); + + /* original flag */ + lame_set_original(s->gfp, s->original); + /* set specified parameters */ if (lame_init_params(s->gfp) < 0) { ret = AVERROR_EXTERNAL; @@ -303,9 +311,11 @@ static int mp3lame_encode_frame(AVCodecContext *avctx, AVPacket *avpkt, #define OFFSET(x) offsetof(LAMEContext, x) #define AE AV_OPT_FLAG_AUDIO_PARAM | AV_OPT_FLAG_ENCODING_PARAM static const AVOption options[] = { - { "reservoir", "use bit reservoir", OFFSET(reservoir), AV_OPT_TYPE_BOOL, { .i64 = 1 }, 0, 1, AE }, - { "joint_stereo", "use joint stereo", OFFSET(joint_stereo), AV_OPT_TYPE_BOOL, { .i64 = 1 }, 0, 1, AE }, - { "abr", "use ABR", OFFSET(abr), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, AE }, + { "reservoir", "use bit reservoir", OFFSET(reservoir), AV_OPT_TYPE_BOOL, { .i64 = 1 }, 0, 1, AE }, + { "joint_stereo", "use joint stereo", OFFSET(joint_stereo), AV_OPT_TYPE_BOOL, { .i64 = 1 }, 0, 1, AE }, + { "abr", "use ABR", OFFSET(abr), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, AE }, + { "copyright", "set copyright flag", OFFSET(copyright), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, AE}, + { "original", "set original flag", OFFSET(original), AV_OPT_TYPE_BOOL, { .i64 = 1 }, 0, 1, AE}, { NULL }, }; From 5e7042fa31c59e99969ad580d45e588d54d1f1e3 Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Wed, 10 May 2023 11:34:31 +0200 Subject: [PATCH 0947/2172] avfilter/src_avsynctest: fix beep amplitude scaling --- libavfilter/src_avsynctest.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/libavfilter/src_avsynctest.c b/libavfilter/src_avsynctest.c index 78e4a2ba506..cfdf1bc78e6 100644 --- a/libavfilter/src_avsynctest.c +++ b/libavfilter/src_avsynctest.c @@ -170,7 +170,7 @@ static av_cold int config_props(AVFilterLink *outlink) #define FPI 0x8000 -static int32_t sin32(int32_t x, int shift) +static int32_t sin32(int32_t x, AVRational scale) { const double pi = M_PI; const int32_t a = ((2.0 * pi) * (1 << 24)); @@ -194,7 +194,8 @@ static int32_t sin32(int32_t x, int shift) result = a + t2; result *= x; result += (1U << 31); - result >>= (32 - shift); + result >>= 17; + result = av_rescale(result, scale.num, scale.den); return result; } @@ -203,7 +204,7 @@ static int audio_frame(AVFilterLink *outlink) { AVFilterContext *ctx = outlink->src; AVSyncTestContext *s = ctx->priv; - const int a = lrintf(s->amplitude * 15); + const AVRational a = av_d2q(s->amplitude, 32768); int64_t duration[2]; int64_t delta; AVFrame *out; From dc1d4a8ece2ea3aa592ca1e38fad6e7a3562c4e7 Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Wed, 10 May 2023 12:14:48 +0200 Subject: [PATCH 0948/2172] avfilter/src_avsynctest: add support for commands --- doc/filters.texi | 4 ++++ libavfilter/src_avsynctest.c | 17 +++++++++++------ 2 files changed, 15 insertions(+), 6 deletions(-) diff --git a/doc/filters.texi b/doc/filters.texi index 9fae135ec41..206fb237858 100644 --- a/doc/filters.texi +++ b/doc/filters.texi @@ -31253,6 +31253,10 @@ Set stream output duration. By default duration is unlimited. Set foreground/background/additional color. @end table +@subsection Commands + +This source supports the some above options as @ref{commands}. + @anchor{movie} @section movie diff --git a/libavfilter/src_avsynctest.c b/libavfilter/src_avsynctest.c index cfdf1bc78e6..a0fef7a1cbd 100644 --- a/libavfilter/src_avsynctest.c +++ b/libavfilter/src_avsynctest.c @@ -67,6 +67,7 @@ typedef struct AVSyncTestContext { #define OFFSET(x) offsetof(AVSyncTestContext, x) #define A AV_OPT_FLAG_AUDIO_PARAM|AV_OPT_FLAG_FILTERING_PARAM #define V AV_OPT_FLAG_VIDEO_PARAM|AV_OPT_FLAG_FILTERING_PARAM +#define R AV_OPT_FLAG_RUNTIME_PARAM static const AVOption avsynctest_options[] = { {"size", "set frame size", OFFSET(w), AV_OPT_TYPE_IMAGE_SIZE, {.str="hd720"}, 0, 0, V }, @@ -75,14 +76,14 @@ static const AVOption avsynctest_options[] = { {"fr", "set frame rate", OFFSET(frame_rate), AV_OPT_TYPE_VIDEO_RATE, {.str="30"}, 0,INT_MAX, V }, {"samplerate", "set sample rate", OFFSET(sample_rate), AV_OPT_TYPE_INT, {.i64=44100},8000,384000, A }, {"sr", "set sample rate", OFFSET(sample_rate), AV_OPT_TYPE_INT, {.i64=44100},8000,384000, A }, - {"amplitude", "set beep amplitude", OFFSET(amplitude), AV_OPT_TYPE_FLOAT, {.dbl=.7}, 0., 1., A }, - {"a", "set beep amplitude", OFFSET(amplitude), AV_OPT_TYPE_FLOAT, {.dbl=.7}, 0., 1., A }, + {"amplitude", "set beep amplitude", OFFSET(amplitude), AV_OPT_TYPE_FLOAT, {.dbl=.7}, 0., 1., A|R }, + {"a", "set beep amplitude", OFFSET(amplitude), AV_OPT_TYPE_FLOAT, {.dbl=.7}, 0., 1., A|R }, {"period", "set beep period", OFFSET(period), AV_OPT_TYPE_INT, {.i64=3}, 1, 99., A }, {"p", "set beep period", OFFSET(period), AV_OPT_TYPE_INT, {.i64=3}, 1, 99., A }, - {"delay", "set flash delay", OFFSET(delay), AV_OPT_TYPE_INT, {.i64=0}, -30, 30, V }, - {"dl", "set flash delay", OFFSET(delay), AV_OPT_TYPE_INT, {.i64=0}, -30, 30, V }, - {"cycle", "set delay cycle", OFFSET(cycle), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1, V }, - {"c", "set delay cycle", OFFSET(cycle), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1, V }, + {"delay", "set flash delay", OFFSET(delay), AV_OPT_TYPE_INT, {.i64=0}, -30, 30, V|R }, + {"dl", "set flash delay", OFFSET(delay), AV_OPT_TYPE_INT, {.i64=0}, -30, 30, V|R }, + {"cycle", "set delay cycle", OFFSET(cycle), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1, V|R }, + {"c", "set delay cycle", OFFSET(cycle), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1, V|R }, {"duration", "set duration", OFFSET(duration), AV_OPT_TYPE_DURATION, {.i64=0}, 0, INT64_MAX, V|A }, {"d", "set duration", OFFSET(duration), AV_OPT_TYPE_DURATION, {.i64=0}, 0, INT64_MAX, V|A }, {"fg", "set foreground color", OFFSET(rgba[0]), AV_OPT_TYPE_COLOR, {.str="white"}, 0, 0, V }, @@ -278,6 +279,9 @@ static int video_frame(AVFilterLink *outlink) int64_t delta, temp, intpart; AVFrame *out; + if (!s->cycle) + s->vdelay = av_make_q(s->delay, 1); + delta = av_rescale_q(s->apts, s->frame_rate, av_make_q(s->sample_rate, 1)) - s->vpts; if (delta < 0) return 1; @@ -401,4 +405,5 @@ const AVFilter ff_avsrc_avsynctest = { .activate = activate, FILTER_OUTPUTS(avsynctest_outputs), FILTER_QUERY_FUNC(query_formats), + .process_command = ff_filter_process_command, }; From 5ce76506de1a7fbaf91af47a925d5ecfe13ae59c Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Wed, 10 May 2023 12:38:28 +0200 Subject: [PATCH 0949/2172] avdevice/lavfi: check that pointer is set Fixes NULL pointer dereference later. --- libavdevice/lavfi.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/libavdevice/lavfi.c b/libavdevice/lavfi.c index 9c1fcf334b5..b2cec0400bd 100644 --- a/libavdevice/lavfi.c +++ b/libavdevice/lavfi.c @@ -174,6 +174,10 @@ av_cold static int lavfi_read_header(AVFormatContext *avctx) * create a mapping between them and the streams */ for (i = 0, inout = output_links; inout; i++, inout = inout->next) { int stream_idx = 0, suffix = 0, use_subcc = 0; + if (!inout->name) { + av_log(avctx, AV_LOG_ERROR, "Missing %d outpad name\n", i); + FAIL(AVERROR(EINVAL)); + } sscanf(inout->name, "out%n%d%n", &suffix, &stream_idx, &suffix); if (!suffix) { av_log(avctx, AV_LOG_ERROR, From a4abe37fb546082b83f38254f2c22654ff2ff45d Mon Sep 17 00:00:00 2001 From: "Dai, Jianhui J" Date: Tue, 9 May 2023 05:28:26 +0000 Subject: [PATCH 0950/2172] vcodec/vp8data: Move ff_vp8_dct_cat_prob to vp8data.c Avoid compiling error if included by multiple sources. Signed-off-by: Jianhui Dai Signed-off-by: Ronald S. Bultje --- libavcodec/Makefile | 4 ++-- libavcodec/vp8data.c | 42 ++++++++++++++++++++++++++++++++++++++++++ libavcodec/vp8data.h | 20 +------------------- 3 files changed, 45 insertions(+), 21 deletions(-) create mode 100644 libavcodec/vp8data.c diff --git a/libavcodec/Makefile b/libavcodec/Makefile index b0971ce833e..3cf4444b7eb 100644 --- a/libavcodec/Makefile +++ b/libavcodec/Makefile @@ -762,8 +762,8 @@ OBJS-$(CONFIG_VP3_DECODER) += vp3.o jpegquanttables.o OBJS-$(CONFIG_VP5_DECODER) += vp5.o vp56.o vp56data.o vpx_rac.o OBJS-$(CONFIG_VP6_DECODER) += vp6.o vp56.o vp56data.o \ vp6dsp.o vpx_rac.o -OBJS-$(CONFIG_VP7_DECODER) += vp8.o vpx_rac.o -OBJS-$(CONFIG_VP8_DECODER) += vp8.o vpx_rac.o +OBJS-$(CONFIG_VP7_DECODER) += vp8.o vp8data.o vpx_rac.o +OBJS-$(CONFIG_VP8_DECODER) += vp8.o vp8data.o vpx_rac.o OBJS-$(CONFIG_VP8_CUVID_DECODER) += cuviddec.o OBJS-$(CONFIG_VP8_MEDIACODEC_DECODER) += mediacodecdec.o OBJS-$(CONFIG_VP8_QSV_DECODER) += qsvdec.o diff --git a/libavcodec/vp8data.c b/libavcodec/vp8data.c new file mode 100644 index 00000000000..a41fc872f58 --- /dev/null +++ b/libavcodec/vp8data.c @@ -0,0 +1,42 @@ +/* + * 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 "stdint.h" + +// cat 1 and 2 are defined in vp8data.h +static const uint8_t vp8_dct_cat3_prob[] = { + 173, 148, 140, 0 +}; +static const uint8_t vp8_dct_cat4_prob[] = { + 176, 155, 140, 135, 0 +}; +static const uint8_t vp8_dct_cat5_prob[] = { + 180, 157, 141, 134, 130, 0 +}; +static const uint8_t vp8_dct_cat6_prob[] = { + 254, 254, 243, 230, 196, 177, 153, 140, 133, 130, 129, 0 +}; + +// only used for cat3 and above; cat 1 and 2 are referenced directly. +const uint8_t *const ff_vp8_dct_cat_prob[] = { + vp8_dct_cat3_prob, + vp8_dct_cat4_prob, + vp8_dct_cat5_prob, + vp8_dct_cat6_prob, +}; + diff --git a/libavcodec/vp8data.h b/libavcodec/vp8data.h index 1fcce134eb2..8b8f1ed1118 100644 --- a/libavcodec/vp8data.h +++ b/libavcodec/vp8data.h @@ -339,26 +339,8 @@ static const uint8_t vp8_dct_cat1_prob[] = { static const uint8_t vp8_dct_cat2_prob[] = { 165, 145, 0 }; -static const uint8_t vp8_dct_cat3_prob[] = { - 173, 148, 140, 0 -}; -static const uint8_t vp8_dct_cat4_prob[] = { - 176, 155, 140, 135, 0 -}; -static const uint8_t vp8_dct_cat5_prob[] = { - 180, 157, 141, 134, 130, 0 -}; -static const uint8_t vp8_dct_cat6_prob[] = { - 254, 254, 243, 230, 196, 177, 153, 140, 133, 130, 129, 0 -}; -// only used for cat3 and above; cat 1 and 2 are referenced directly -const uint8_t *const ff_vp8_dct_cat_prob[] = { - vp8_dct_cat3_prob, - vp8_dct_cat4_prob, - vp8_dct_cat5_prob, - vp8_dct_cat6_prob, -}; +extern const uint8_t *const ff_vp8_dct_cat_prob[]; static const uint8_t vp8_token_default_probs[4][8][3][NUM_DCT_TOKENS - 1] = { { From ffd275a7e065e1e7fbf57c9dbbb2955dd72b8481 Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Wed, 10 May 2023 13:45:07 +0200 Subject: [PATCH 0951/2172] avfilter/af_pan: fix leaks on error case --- libavfilter/af_pan.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/libavfilter/af_pan.c b/libavfilter/af_pan.c index 4672648d467..bb33ab10c03 100644 --- a/libavfilter/af_pan.c +++ b/libavfilter/af_pan.c @@ -385,8 +385,11 @@ FF_DISABLE_DEPRECATION_WARNINGS outsamples->channels = outlink->ch_layout.nb_channels; FF_ENABLE_DEPRECATION_WARNINGS #endif - if ((ret = av_channel_layout_copy(&outsamples->ch_layout, &outlink->ch_layout)) < 0) + if ((ret = av_channel_layout_copy(&outsamples->ch_layout, &outlink->ch_layout)) < 0) { + av_frame_free(&outsamples); + av_frame_free(&insamples); return ret; + } ret = ff_filter_frame(outlink, outsamples); av_frame_free(&insamples); From 2de30e7f8cb5c26ca16a122c0ababb2a244b7ffe Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Wed, 10 May 2023 13:50:13 +0200 Subject: [PATCH 0952/2172] avfilter/af_join: fix leak on error --- libavfilter/af_join.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavfilter/af_join.c b/libavfilter/af_join.c index 605d73d2ccb..af924b7ec1f 100644 --- a/libavfilter/af_join.c +++ b/libavfilter/af_join.c @@ -531,7 +531,7 @@ FF_DISABLE_DEPRECATION_WARNINGS FF_ENABLE_DEPRECATION_WARNINGS #endif if ((ret = av_channel_layout_copy(&frame->ch_layout, &outlink->ch_layout)) < 0) - return ret; + goto fail; frame->sample_rate = outlink->sample_rate; frame->format = outlink->format; frame->pts = s->input_frames[0]->pts; From 5b300b69a6c55e79286007a751d1bc197442b253 Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Wed, 10 May 2023 13:51:46 +0200 Subject: [PATCH 0953/2172] avfilter/af_pan: free input frame once unneeded --- libavfilter/af_pan.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/libavfilter/af_pan.c b/libavfilter/af_pan.c index bb33ab10c03..167d7166af5 100644 --- a/libavfilter/af_pan.c +++ b/libavfilter/af_pan.c @@ -391,9 +391,8 @@ FF_ENABLE_DEPRECATION_WARNINGS return ret; } - ret = ff_filter_frame(outlink, outsamples); av_frame_free(&insamples); - return ret; + return ff_filter_frame(outlink, outsamples); } static av_cold void uninit(AVFilterContext *ctx) From 0412e1dc802bb70141ce50c553132dc39c4b5f00 Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Wed, 10 May 2023 15:13:43 +0200 Subject: [PATCH 0954/2172] avfilter/vsrc_testsrc: mark zoneplate as full range --- libavfilter/vsrc_testsrc.c | 1 + 1 file changed, 1 insertion(+) diff --git a/libavfilter/vsrc_testsrc.c b/libavfilter/vsrc_testsrc.c index 0138e14fb9b..d24481e6c45 100644 --- a/libavfilter/vsrc_testsrc.c +++ b/libavfilter/vsrc_testsrc.c @@ -2167,6 +2167,7 @@ ZONEPLATE_SLICE(16, uint16_t) static void zoneplate_fill_picture(AVFilterContext *ctx, AVFrame *frame) { TestSourceContext *test = ctx->priv; + frame->color_range = AVCOL_RANGE_JPEG; ff_filter_execute(ctx, test->fill_slice_fn, frame, NULL, FFMIN(frame->height, ff_filter_get_nb_threads(ctx))); } From ceb050427c4c6758e6e0ffb2b82e5a76917a1d63 Mon Sep 17 00:00:00 2001 From: Andriy Utkin Date: Thu, 11 May 2023 11:04:20 +0100 Subject: [PATCH 0955/2172] doc/filters/crop: drop unmatched quote in example Commit 55b81528a991 ("doc/filters: itemize crop examples") dropped the quotation marks from these examples, but this one remained. Quotes are actually needed to put the example into a command line or a program, but removing it here makes the example consistent with the document. --- doc/filters.texi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/filters.texi b/doc/filters.texi index 206fb237858..b6e13afdfd9 100644 --- a/doc/filters.texi +++ b/doc/filters.texi @@ -10697,7 +10697,7 @@ crop=in_w/2:in_h/2:(in_w-out_w)/2+((in_w-out_w)/2)*sin(n/10):(in_h-out_h)/2 +((i @item Apply erratic camera effect depending on timestamp: @example -crop=in_w/2:in_h/2:(in_w-out_w)/2+((in_w-out_w)/2)*sin(t*10):(in_h-out_h)/2 +((in_h-out_h)/2)*sin(t*13)" +crop=in_w/2:in_h/2:(in_w-out_w)/2+((in_w-out_w)/2)*sin(t*10):(in_h-out_h)/2 +((in_h-out_h)/2)*sin(t*13) @end example @item From 7958325a832e9dd0807e35a123da5028a521f1c7 Mon Sep 17 00:00:00 2001 From: Christopher Degawa Date: Wed, 10 May 2023 15:29:12 -0500 Subject: [PATCH 0956/2172] libavcodec/libsvtav1: Allow -1 for preset option Currently, the -1 (MR) preset is disallowed as it's taken as the preset option not set, and the only way to access it was through svtav1-params. Signed-off-by: Christopher Degawa Signed-off-by: James Almer --- libavcodec/libsvtav1.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libavcodec/libsvtav1.c b/libavcodec/libsvtav1.c index 9174e2753cd..952ed0e1e71 100644 --- a/libavcodec/libsvtav1.c +++ b/libavcodec/libsvtav1.c @@ -170,7 +170,7 @@ static int config_enc_params(EbSvtAv1EncConfiguration *param, param->look_ahead_distance = svt_enc->la_depth; #endif - if (svt_enc->enc_mode >= 0) + if (svt_enc->enc_mode >= -1) param->enc_mode = svt_enc->enc_mode; if (avctx->bit_rate) { @@ -593,7 +593,7 @@ static const AVOption options[] = { { "high", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = 1 }, 0, 0, VE, "tier" }, #endif { "preset", "Encoding preset", - OFFSET(enc_mode), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, MAX_ENC_PRESET, VE }, + OFFSET(enc_mode), AV_OPT_TYPE_INT, { .i64 = -2 }, -2, MAX_ENC_PRESET, VE }, FF_AV1_PROFILE_OPTS From 2b0e794ffc0ce9d087903a90c7e6d8c957017d98 Mon Sep 17 00:00:00 2001 From: Devin Heitmueller Date: Fri, 5 May 2023 15:09:02 -0400 Subject: [PATCH 0957/2172] avfilter/ccfifo: Properly handle CEA-708 captions through framerate conversion When transcoding video that contains 708 closed captions, the caption data is tied to the frames as side data. Simply dropping or adding frames to change the framerate will result in loss of data, so the caption data needs to be preserved and reformatted. For example, without this patch converting 720p59 to 1080i59 would result in loss of 50% of the caption bytes, resulting in garbled 608 captions and 708 probably wouldn't render at all. Further, the frames that are there will have an illegal cc_count for the target framerate, so some decoders may ignore the packets entirely. Extract the 608 and 708 tuples and insert them onto queues. Then after dropping/adding frames, re-write the tuples back into the resulting frames at the appropriate rate given the target framerate. This includes both having the correct cc_count as well as clocking out the 608 pairs at the appropriate rate. Thanks to Lance Wang , Anton Khirnov , and Michael Niedermayer for providing review/feedback. Signed-off-by: Devin Heitmueller Signed-off-by: Limin Wang --- libavfilter/Makefile | 1 + libavfilter/ccfifo.c | 224 +++++++++++++++++++++++++++++++++++++++++++ libavfilter/ccfifo.h | 110 +++++++++++++++++++++ 3 files changed, 335 insertions(+) create mode 100644 libavfilter/ccfifo.c create mode 100644 libavfilter/ccfifo.h diff --git a/libavfilter/Makefile b/libavfilter/Makefile index 01f1cdfe0cd..cf1953c3c7b 100644 --- a/libavfilter/Makefile +++ b/libavfilter/Makefile @@ -14,6 +14,7 @@ OBJS = allfilters.o \ buffersink.o \ buffersrc.o \ colorspace.o \ + ccfifo.o \ drawutils.o \ fifo.o \ formats.o \ diff --git a/libavfilter/ccfifo.c b/libavfilter/ccfifo.c new file mode 100644 index 00000000000..5fb68ce04c7 --- /dev/null +++ b/libavfilter/ccfifo.c @@ -0,0 +1,224 @@ +/* + * CEA-708 Closed Captioning FIFO + * Copyright (c) 2023 LTN Global Communications + * + * Author: Devin Heitmueller + * + * 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 "ccfifo.h" + +struct AVCCFifo { + AVFifo *cc_608_fifo; + AVFifo *cc_708_fifo; + AVRational framerate; + int expected_cc_count; + int expected_608; + int cc_detected; + int passthrough; + int passthrough_warning; + void *log_ctx; +}; + +#define MAX_CC_ELEMENTS 128 +#define CC_BYTES_PER_ENTRY 3 + +struct cc_lookup { + int num; + int den; + int cc_count; + int num_608; +}; + +const static struct cc_lookup cc_lookup_vals[] = { + { 15, 1, 40, 4 }, + { 24, 1, 25, 3 }, + { 24000, 1001, 25, 3 }, + { 30, 1, 20, 2 }, + { 30000, 1001, 20, 2}, + { 60, 1, 10, 1 }, + { 60000, 1001, 10, 1}, +}; + +void ff_ccfifo_freep(AVCCFifo **ccf) +{ + AVCCFifo *tmp = *ccf; + if (tmp) { + av_fifo_freep2(&tmp->cc_608_fifo); + av_fifo_freep2(&tmp->cc_708_fifo); + } + av_freep(ccf); +} + +AVCCFifo *ff_ccfifo_alloc(AVRational framerate, void *log_ctx) +{ + AVCCFifo *ccf; + int i; + + ccf = av_mallocz(sizeof(*ccf)); + if (!ccf) + return NULL; + + ccf->log_ctx = log_ctx; + ccf->framerate = framerate; + + if (!(ccf->cc_708_fifo = av_fifo_alloc2(MAX_CC_ELEMENTS, CC_BYTES_PER_ENTRY, 0))) + goto error; + + if (!(ccf->cc_608_fifo = av_fifo_alloc2(MAX_CC_ELEMENTS, CC_BYTES_PER_ENTRY, 0))) + goto error; + + /* Based on the target FPS, figure out the expected cc_count and number of + 608 tuples per packet. See ANSI/CTA-708-E Sec 4.3.6.1. */ + for (i = 0; i < FF_ARRAY_ELEMS(cc_lookup_vals); i++) { + if (framerate.num == cc_lookup_vals[i].num && + framerate.den == cc_lookup_vals[i].den) { + ccf->expected_cc_count = cc_lookup_vals[i].cc_count; + ccf->expected_608 = cc_lookup_vals[i].num_608; + break; + } + } + + if (ccf->expected_608 == 0) { + /* We didn't find an output frame we support. We'll let the call succeed + and the FIFO to be allocated, but the extract/inject functions will simply + leave everything the way it is */ + ccf->passthrough = 1; + } + + return ccf; + +error: + ff_ccfifo_freep(&ccf); + return NULL; +} + +int ff_ccfifo_getoutputsize(AVCCFifo *ccf) +{ + return ccf->expected_cc_count * CC_BYTES_PER_ENTRY; +} + +int ff_ccfifo_ccdetected(AVCCFifo *ccf) +{ + return ccf->cc_detected; +} + +int ff_ccfifo_injectbytes(AVCCFifo *ccf, uint8_t *cc_data, size_t len) +{ + int cc_608_tuples = 0; + int cc_708_tuples = 0; + int cc_filled = 0; + + if (ccf->passthrough) { + return 0; + } + + if (len < ff_ccfifo_getoutputsize(ccf)) { + return AVERROR(EINVAL); + } + + /* Insert any available data from the 608 FIFO */ + if (ccf->expected_608 <= av_fifo_can_read(ccf->cc_608_fifo)) + cc_608_tuples = ccf->expected_608; + else + cc_608_tuples = av_fifo_can_read(ccf->cc_608_fifo); + av_fifo_read(ccf->cc_608_fifo, cc_data, cc_608_tuples); + cc_filled += cc_608_tuples; + + /* Insert any available data from the 708 FIFO */ + if ((ccf->expected_cc_count - cc_filled) <= av_fifo_can_read(ccf->cc_708_fifo)) + cc_708_tuples = ccf->expected_cc_count - cc_filled; + else + cc_708_tuples = av_fifo_can_read(ccf->cc_708_fifo); + av_fifo_read(ccf->cc_708_fifo, &cc_data[cc_filled * CC_BYTES_PER_ENTRY], cc_708_tuples); + cc_filled += cc_708_tuples; + + /* Insert 708 padding into any remaining fields */ + while (cc_filled < ccf->expected_cc_count) { + cc_data[cc_filled * CC_BYTES_PER_ENTRY] = 0xfa; + cc_data[cc_filled * CC_BYTES_PER_ENTRY + 1] = 0x00; + cc_data[cc_filled * CC_BYTES_PER_ENTRY + 2] = 0x00; + cc_filled++; + } + + return 0; +} + +int ff_ccfifo_inject(AVCCFifo *ccf, AVFrame *frame) +{ + AVFrameSideData *sd; + int ret; + + if (ccf->passthrough == 1 || ccf->cc_detected == 0) + return 0; + + sd = av_frame_new_side_data(frame, AV_FRAME_DATA_A53_CC, + ff_ccfifo_getoutputsize(ccf)); + if (sd) { + ret = ff_ccfifo_injectbytes(ccf, sd->data, sd->size); + if (ret < 0) { + av_frame_remove_side_data(frame, AV_FRAME_DATA_A53_CC); + return ret; + } + } + + return 0; +} + +int ff_ccfifo_extractbytes(AVCCFifo *ccf, uint8_t *cc_bytes, size_t len) +{ + int cc_count = len / CC_BYTES_PER_ENTRY; + + if (ccf->passthrough == 1) { + av_log_once(ccf->log_ctx, AV_LOG_WARNING, AV_LOG_DEBUG, &ccf->passthrough_warning, + "cc_fifo cannot transcode captions fps=%d/%d\n", + ccf->framerate.num, ccf->framerate.den); + return 0; + } + + ccf->cc_detected = 1; + + for (int i = 0; i < cc_count; i++) { + /* See ANSI/CTA-708-E Sec 4.3, Table 3 */ + uint8_t cc_valid = (cc_bytes[CC_BYTES_PER_ENTRY*i] & 0x04) >> 2; + uint8_t cc_type = cc_bytes[CC_BYTES_PER_ENTRY*i] & 0x03; + if (cc_type == 0x00 || cc_type == 0x01) { + av_fifo_write(ccf->cc_608_fifo, &cc_bytes[CC_BYTES_PER_ENTRY*i], 1); + } else if (cc_valid && (cc_type == 0x02 || cc_type == 0x03)) { + av_fifo_write(ccf->cc_708_fifo, &cc_bytes[CC_BYTES_PER_ENTRY*i], 1); + } + } + return 0; +} + +/* Read the A53 side data, discard padding, and put 608/708 into + queues so we can ensure they get into the output frames at + the correct rate... */ +int ff_ccfifo_extract(AVCCFifo *ccf, AVFrame *frame) +{ + AVFrameSideData *side_data = av_frame_get_side_data(frame, AV_FRAME_DATA_A53_CC); + if (side_data) { + ff_ccfifo_extractbytes(ccf, side_data->data, side_data->size); + + /* Remove the side data, as we will re-create it on the + output as needed */ + if (!ccf->passthrough) + av_frame_remove_side_data(frame, AV_FRAME_DATA_A53_CC); + } + return 0; +} diff --git a/libavfilter/ccfifo.h b/libavfilter/ccfifo.h new file mode 100644 index 00000000000..44c924593c1 --- /dev/null +++ b/libavfilter/ccfifo.h @@ -0,0 +1,110 @@ +/* + * CEA-708 Closed Captioning FIFO + * Copyright (c) 2023 LTN Global Communications + * + * Author: Devin Heitmueller + * + * 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 + * CC FIFO Buffer + */ + +#ifndef AVFILTER_CCFIFO_H +#define AVFILTER_CCFIFO_H + +#include "libavutil/avutil.h" +#include "libavutil/frame.h" +#include "libavutil/fifo.h" + +typedef struct AVCCFifo AVCCFifo; + +/** + * Allocate an AVCCFifo. + * + * @param framerate output framerate + * @param log_ctx used for any av_log() calls + * @return newly allocated AVCCFifo, or NULL on error + */ +AVCCFifo *ff_ccfifo_alloc(AVRational framerate, void *log_ctx); + +/** + * Free an AVCCFifo + * + * @param ccf Pointer to the pointer to the AVCCFifo which should be freed + * @note `*ptr = NULL` is safe and leads to no action. + */ +void ff_ccfifo_freep(AVCCFifo **ccf); + + +/** + * Extract CC data from an AVFrame + * + * Extract CC bytes from the AVFrame, insert them into our queue, and + * remove the side data from the AVFrame. The side data is removed + * as it will be re-inserted at the appropriate rate later in the + * filter. + * + * @param af AVCCFifo to write to + * @param frame AVFrame with the video frame to operate on + * @return Zero on success, or negative AVERROR + * code on failure. + */ +int ff_ccfifo_extract(AVCCFifo *ccf, AVFrame *frame); + +/** + *Just like ff_ccfifo_extract(), but takes the raw bytes instead of an AVFrame + */ +int ff_ccfifo_extractbytes(AVCCFifo *ccf, uint8_t *data, size_t len); + +/** + * Provide the size in bytes of an output buffer to allocate + * + * Ask for how many bytes the output will contain, so the caller can allocate + * an appropriately sized buffer and pass it to ff_ccfifo_injectbytes() + * + */ +int ff_ccfifo_getoutputsize(AVCCFifo *ccf); + +/** + * Insert CC data from the FIFO into an AVFrame (as side data) + * + * Dequeue the appropriate number of CC tuples based on the + * frame rate, and insert them into the AVFrame + * + * @param af AVCCFifo to read from + * @param frame AVFrame with the video frame to operate on + * @return Zero on success, or negative AVERROR + * code on failure. + */ +int ff_ccfifo_inject(AVCCFifo *ccf, AVFrame *frame); + +/** + * Just like ff_ccfifo_inject(), but takes the raw bytes to insert the CC data + * int rather than an AVFrame + */ +int ff_ccfifo_injectbytes(AVCCFifo *ccf, uint8_t *data, size_t len); + +/** + * Returns 1 if captions have been found as a prior call + * to ff_ccfifo_extract() or ff_ccfifo_extractbytes() + */ +int ff_ccfifo_ccdetected(AVCCFifo *ccf); + +#endif /* AVFILTER_CCFIFO_H */ From 61a9f3c0ce7f74ba869f44a49e16f3cd1b79e18d Mon Sep 17 00:00:00 2001 From: Devin Heitmueller Date: Fri, 5 May 2023 15:09:03 -0400 Subject: [PATCH 0958/2172] avfilter/vf_fps: properly preserve CEA-708 captions The existing implementation made an attempt to remove duplicate captions if increasing the framerate, but made no attempt to handle reducing the framerate, nor did it rewrite the caption payloads to have the appropriate cc_count (e.g. the cc_count needs to change from 20 to 10 when going from 1080i59 to 720p59 and vice-versa). Make use of the new ccfifo mechanism to ensure that caption data is properly preserved. Signed-off-by: Devin Heitmueller Signed-off-by: Limin Wang --- libavfilter/vf_fps.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/libavfilter/vf_fps.c b/libavfilter/vf_fps.c index 051d278f54d..824e7a128df 100644 --- a/libavfilter/vf_fps.c +++ b/libavfilter/vf_fps.c @@ -34,6 +34,7 @@ #include "libavutil/mathematics.h" #include "libavutil/opt.h" #include "avfilter.h" +#include "ccfifo.h" #include "filters.h" #include "internal.h" @@ -85,6 +86,7 @@ typedef struct FPSContext { AVFrame *frames[2]; ///< buffered frames int frames_count; ///< number of buffered frames + AVCCFifo *cc_fifo; ///< closed captions int64_t next_pts; ///< pts of the next frame to output @@ -165,6 +167,7 @@ static av_cold void uninit(AVFilterContext *ctx) frame = shift_frame(ctx, s); av_frame_free(&frame); } + ff_ccfifo_freep(&s->cc_fifo); av_log(ctx, AV_LOG_VERBOSE, "%d frames in, %d frames out; %d frames dropped, " "%d frames duplicated.\n", s->frames_in, s->frames_out, s->drop, s->dup); @@ -210,6 +213,11 @@ static int config_props(AVFilterLink* outlink) s->in_pts_off, s->out_pts_off, s->start_time); } + if (!(s->cc_fifo = ff_ccfifo_alloc(outlink->frame_rate, ctx))) { + av_log(ctx, AV_LOG_ERROR, "Failure to setup CC FIFO queue\n"); + return AVERROR(ENOMEM); + } + av_log(ctx, AV_LOG_VERBOSE, "fps=%d/%d\n", outlink->frame_rate.num, outlink->frame_rate.den); return 0; @@ -242,6 +250,7 @@ static int read_frame(AVFilterContext *ctx, FPSContext *s, AVFilterLink *inlink, av_log(ctx, AV_LOG_DEBUG, "Read frame with in pts %"PRId64", out pts %"PRId64"\n", in_pts, frame->pts); + ff_ccfifo_extract(s->cc_fifo, frame); s->frames[s->frames_count++] = frame; s->frames_in++; @@ -289,7 +298,7 @@ static int write_frame(AVFilterContext *ctx, FPSContext *s, AVFilterLink *outlin if (!frame) return AVERROR(ENOMEM); // Make sure Closed Captions will not be duplicated - av_frame_remove_side_data(s->frames[0], AV_FRAME_DATA_A53_CC); + ff_ccfifo_inject(s->cc_fifo, frame); frame->pts = s->next_pts++; frame->duration = 1; From cecf35ae3e997dd884295d692aa6829462394132 Mon Sep 17 00:00:00 2001 From: Devin Heitmueller Date: Fri, 5 May 2023 15:09:04 -0400 Subject: [PATCH 0959/2172] avfilter/yadif: Properly preserve CEA-708 closed captions Various deinterlacing modes have the effect of doubling the framerate, and we need to ensure that the caption data isn't duplicated (or else you get double captions on-screen). Use the new ccfifo mechanism for yadif (and yadif_cuda and bwdif since they use the same yadif core) so that CEA-708 data is properly preserved through this filter. Signed-off-by: Devin Heitmueller Signed-off-by: Limin Wang --- libavfilter/vf_bwdif.c | 8 ++++++++ libavfilter/vf_yadif.c | 8 ++++++++ libavfilter/vf_yadif_cuda.c | 9 +++++++++ libavfilter/yadif.h | 2 ++ libavfilter/yadif_common.c | 5 +++++ 5 files changed, 32 insertions(+) diff --git a/libavfilter/vf_bwdif.c b/libavfilter/vf_bwdif.c index 34e8c5e234e..51e1e02503c 100644 --- a/libavfilter/vf_bwdif.c +++ b/libavfilter/vf_bwdif.c @@ -297,6 +297,7 @@ static av_cold void uninit(AVFilterContext *ctx) av_frame_free(&yadif->prev); av_frame_free(&yadif->cur ); av_frame_free(&yadif->next); + ff_ccfifo_freep(&yadif->cc_fifo); } static const enum AVPixelFormat pix_fmts[] = { @@ -332,6 +333,13 @@ static int config_props(AVFilterLink *link) if(yadif->mode&1) link->frame_rate = av_mul_q(link->src->inputs[0]->frame_rate, (AVRational){2,1}); + else + link->frame_rate = ctx->inputs[0]->frame_rate; + + if (!(yadif->cc_fifo = ff_ccfifo_alloc(link->frame_rate, ctx))) { + av_log(ctx, AV_LOG_ERROR, "Failure to setup CC FIFO queue\n"); + return AVERROR(ENOMEM); + } if (link->w < 3 || link->h < 4) { av_log(ctx, AV_LOG_ERROR, "Video of less than 3 columns or 4 lines is not supported\n"); diff --git a/libavfilter/vf_yadif.c b/libavfilter/vf_yadif.c index 1be02de1a94..f77f8113cac 100644 --- a/libavfilter/vf_yadif.c +++ b/libavfilter/vf_yadif.c @@ -261,6 +261,7 @@ static av_cold void uninit(AVFilterContext *ctx) av_frame_free(&yadif->prev); av_frame_free(&yadif->cur ); av_frame_free(&yadif->next); + ff_ccfifo_freep(&yadif->cc_fifo); } static const enum AVPixelFormat pix_fmts[] = { @@ -293,6 +294,13 @@ static int config_output(AVFilterLink *outlink) if(s->mode & 1) outlink->frame_rate = av_mul_q(ctx->inputs[0]->frame_rate, (AVRational){2, 1}); + else + outlink->frame_rate = ctx->inputs[0]->frame_rate; + + if (!(s->cc_fifo = ff_ccfifo_alloc(outlink->frame_rate, ctx))) { + av_log(ctx, AV_LOG_ERROR, "Failure to setup CC FIFO queue\n"); + return AVERROR(ENOMEM); + } if (outlink->w < 3 || outlink->h < 3) { av_log(ctx, AV_LOG_ERROR, "Video of less than 3 columns or lines is not supported\n"); diff --git a/libavfilter/vf_yadif_cuda.c b/libavfilter/vf_yadif_cuda.c index 685b8a20355..f3f0b567686 100644 --- a/libavfilter/vf_yadif_cuda.c +++ b/libavfilter/vf_yadif_cuda.c @@ -205,6 +205,7 @@ static av_cold void deint_cuda_uninit(AVFilterContext *ctx) av_frame_free(&y->prev); av_frame_free(&y->cur); av_frame_free(&y->next); + ff_cc_fifo_freep(&y->cc_fifo); av_buffer_unref(&s->device_ref); s->hwctx = NULL; @@ -291,6 +292,14 @@ static int config_output(AVFilterLink *link) if(y->mode & 1) link->frame_rate = av_mul_q(ctx->inputs[0]->frame_rate, (AVRational){2, 1}); + else + link->frame_rate = ctx->inputs[0]->frame_rate; + + if (!(s->cc_fifo = ff_cc_fifo_alloc(link->frame_rate, ctx))) { + av_log(ctx, AV_LOG_ERROR, "Failure to setup CC FIFO queue\n"); + ret = AVERROR(ENOMEM); + goto exit; + } 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"); diff --git a/libavfilter/yadif.h b/libavfilter/yadif.h index c928911b357..10775767e95 100644 --- a/libavfilter/yadif.h +++ b/libavfilter/yadif.h @@ -22,6 +22,7 @@ #include "libavutil/opt.h" #include "libavutil/pixdesc.h" #include "avfilter.h" +#include "ccfifo.h" enum YADIFMode { YADIF_MODE_SEND_FRAME = 0, ///< send 1 frame for each frame @@ -76,6 +77,7 @@ typedef struct YADIFContext { int eof; uint8_t *temp_line; int temp_line_size; + AVCCFifo *cc_fifo; /* * An algorithm that treats first and/or last fields in a sequence diff --git a/libavfilter/yadif_common.c b/libavfilter/yadif_common.c index 2bd61111401..49ea7cfce44 100644 --- a/libavfilter/yadif_common.c +++ b/libavfilter/yadif_common.c @@ -65,6 +65,8 @@ FF_ENABLE_DEPRECATION_WARNINGS yadif->out->pts = AV_NOPTS_VALUE; } } + + ff_ccfifo_inject(yadif->cc_fifo, yadif->out); ret = ff_filter_frame(ctx->outputs[0], yadif->out); yadif->frame_pending = (yadif->mode&1) && !is_second; @@ -101,6 +103,8 @@ int ff_yadif_filter_frame(AVFilterLink *link, AVFrame *frame) av_assert0(frame); + ff_ccfifo_extract(yadif->cc_fifo, frame); + if (yadif->frame_pending) return_frame(ctx, 1); @@ -142,6 +146,7 @@ int ff_yadif_filter_frame(AVFilterLink *link, AVFrame *frame) if (!yadif->out) return AVERROR(ENOMEM); + ff_ccfifo_inject(yadif->cc_fifo, yadif->out); av_frame_free(&yadif->prev); if (yadif->out->pts != AV_NOPTS_VALUE) yadif->out->pts *= 2; From f304c3a729b2c710de2b1bf3c1f9f1c42d17d4f1 Mon Sep 17 00:00:00 2001 From: Devin Heitmueller Date: Fri, 5 May 2023 15:09:05 -0400 Subject: [PATCH 0960/2172] avfilter/tinterlace: Properly preserve CEA-708 closed captions Because the interlacing filter halves the effective framerate, we need to ensure that no CEA-708 data is lost as frames are merged. Make use of the new ccfifo mechanism to ensure that caption data is properly preserved as frames pass through the filter. Thanks to Thomas Mundt for review and noticing a couple of missed codepaths for injection on output. Thanks to Lance Wang for pointing out a memory leak. Signed-off-by: Devin Heitmueller Signed-off-by: Limin Wang --- libavfilter/tinterlace.h | 2 ++ libavfilter/vf_tinterlace.c | 11 +++++++++++ 2 files changed, 13 insertions(+) diff --git a/libavfilter/tinterlace.h b/libavfilter/tinterlace.h index 37b6c10c08c..9f5ce7e65bf 100644 --- a/libavfilter/tinterlace.h +++ b/libavfilter/tinterlace.h @@ -32,6 +32,7 @@ #include "libavutil/pixdesc.h" #include "drawutils.h" #include "avfilter.h" +#include "ccfifo.h" #define TINTERLACE_FLAG_VLPF 01 #define TINTERLACE_FLAG_CVLPF 2 @@ -77,6 +78,7 @@ typedef struct TInterlaceContext { const AVPixFmtDescriptor *csp; void (*lowpass_line)(uint8_t *dstp, ptrdiff_t width, const uint8_t *srcp, ptrdiff_t mref, ptrdiff_t pref, int clip_max); + AVCCFifo *cc_fifo; } TInterlaceContext; void ff_tinterlace_init_x86(TInterlaceContext *interlace); diff --git a/libavfilter/vf_tinterlace.c b/libavfilter/vf_tinterlace.c index 8b0cbbcf95a..e1057ffc8ef 100644 --- a/libavfilter/vf_tinterlace.c +++ b/libavfilter/vf_tinterlace.c @@ -203,6 +203,7 @@ static av_cold void uninit(AVFilterContext *ctx) av_frame_free(&tinterlace->next); av_freep(&tinterlace->black_data[0][0]); av_freep(&tinterlace->black_data[1][0]); + ff_ccfifo_freep(&tinterlace->cc_fifo); } static int config_out_props(AVFilterLink *outlink) @@ -291,6 +292,11 @@ static int config_out_props(AVFilterLink *outlink) #endif } + if (!(tinterlace->cc_fifo = ff_ccfifo_alloc(outlink->frame_rate, ctx))) { + av_log(ctx, AV_LOG_ERROR, "Failure to setup CC FIFO queue\n"); + return AVERROR(ENOMEM); + } + av_log(ctx, AV_LOG_VERBOSE, "mode:%d filter:%s h:%d -> h:%d\n", tinterlace->mode, (tinterlace->flags & TINTERLACE_FLAG_CVLPF) ? "complex" : (tinterlace->flags & TINTERLACE_FLAG_VLPF) ? "linear" : "off", @@ -375,6 +381,8 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *picref) tinterlace->cur = tinterlace->next; tinterlace->next = picref; + ff_ccfifo_extract(tinterlace->cc_fifo, picref); + cur = tinterlace->cur; next = tinterlace->next; /* we need at least two frames */ @@ -456,6 +464,7 @@ FF_ENABLE_DEPRECATION_WARNINGS if (!out) return AVERROR(ENOMEM); out->pts /= 2; // adjust pts to new framerate + ff_ccfifo_inject(tinterlace->cc_fifo, out); ret = ff_filter_frame(outlink, out); return ret; } @@ -505,6 +514,7 @@ FF_ENABLE_DEPRECATION_WARNINGS out->pts = cur->pts*2; out->pts = av_rescale_q(out->pts, tinterlace->preout_time_base, outlink->time_base); + ff_ccfifo_inject(tinterlace->cc_fifo, out); if ((ret = ff_filter_frame(outlink, out)) < 0) return ret; @@ -549,6 +559,7 @@ FF_ENABLE_DEPRECATION_WARNINGS out->pts = av_rescale_q(out->pts, tinterlace->preout_time_base, outlink->time_base); out->duration = av_rescale_q(1, av_inv_q(outlink->frame_rate), outlink->time_base); + ff_ccfifo_inject(tinterlace->cc_fifo, out); ret = ff_filter_frame(outlink, out); return ret; From 0e12cdc69c86daa11608cfe809ba1aa848f91a09 Mon Sep 17 00:00:00 2001 From: Devin Heitmueller Date: Fri, 5 May 2023 15:09:06 -0400 Subject: [PATCH 0961/2172] avfilter/vf_ccrepack: Add new filter to repack CEA-708 side data THis filter can correct certain issues seen from upstream sources where the cc_count is not properly set or the CEA-608 tuples are not at the start of the payload as expected. Make use of the ccfifo to extract and immediately repack the CEA-708 side data, thereby removing any extra padding and ensuring the 608 tuples are at the front of the payload. Signed-off-by: Devin Heitmueller Signed-off-by: Limin Wang --- doc/filters.texi | 10 ++++ libavfilter/Makefile | 1 + libavfilter/allfilters.c | 1 + libavfilter/vf_ccrepack.c | 102 ++++++++++++++++++++++++++++++++++++++ 4 files changed, 114 insertions(+) create mode 100644 libavfilter/vf_ccrepack.c diff --git a/doc/filters.texi b/doc/filters.texi index b6e13afdfd9..7e0c87d0fa6 100644 --- a/doc/filters.texi +++ b/doc/filters.texi @@ -9083,6 +9083,16 @@ Only deinterlace frames marked as interlaced. The default value is @code{all}. @end table +@section ccrepack + +Repack CEA-708 closed captioning side data + +This filter fixes various issues seen with commerical encoders +related to upstream malformed CEA-708 payloads, specifically +incorrect number of tuples (wrong cc_count for the target FPS), +and incorrect ordering of tuples (i.e. the CEA-608 tuples are not at +the first entries in the payload). + @section cas Apply Contrast Adaptive Sharpen filter to video stream. diff --git a/libavfilter/Makefile b/libavfilter/Makefile index cf1953c3c7b..19283a71de1 100644 --- a/libavfilter/Makefile +++ b/libavfilter/Makefile @@ -214,6 +214,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_CCREPACK_FILTER) += vf_ccrepack.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 diff --git a/libavfilter/allfilters.c b/libavfilter/allfilters.c index 4083296bb29..30447a11c8d 100644 --- a/libavfilter/allfilters.c +++ b/libavfilter/allfilters.c @@ -198,6 +198,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_ccrepack; extern const AVFilter ff_vf_chromaber_vulkan; extern const AVFilter ff_vf_chromahold; extern const AVFilter ff_vf_chromakey; diff --git a/libavfilter/vf_ccrepack.c b/libavfilter/vf_ccrepack.c new file mode 100644 index 00000000000..e3fd67f1b5f --- /dev/null +++ b/libavfilter/vf_ccrepack.c @@ -0,0 +1,102 @@ +/* + * CEA-708 Closed Caption Repacker + * Copyright (c) 2023 LTN Global Communications + * + * Author: Devin Heitmueller + * + * 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 + */ + +/* + * Repackage CEA-708 arrays, which deals with incorrect cc_count for a given + * output framerate, and incorrect 708 padding. + * + * See CEA CEA-10-A "EIA-708-B Implementation Guidance", Section 26.5 + * "Grouping DTVCC Data Within user_data() Structure" + */ + +#include "avfilter.h" +#include "internal.h" +#include "ccfifo.h" +#include "libavutil/opt.h" + +typedef struct CCRepackContext +{ + const AVClass *class; + AVCCFifo *cc_fifo; +} CCRepackContext; + +static const AVOption ccrepack_options[] = { + { NULL } +}; + +AVFILTER_DEFINE_CLASS(ccrepack); + +static int config_input(AVFilterLink *link) +{ + CCRepackContext *ctx = link->dst->priv; + + if (!(ctx->cc_fifo = ff_ccfifo_alloc(link->frame_rate, ctx))) { + av_log(ctx, AV_LOG_ERROR, "Failure to setup CC FIFO queue\n"); + return AVERROR(ENOMEM); + } + + return 0; +} + +static int filter_frame(AVFilterLink *inlink, AVFrame *frame) +{ + CCRepackContext *ctx = inlink->dst->priv; + AVFilterLink *outlink = inlink->dst->outputs[0]; + + ff_ccfifo_extract(ctx->cc_fifo, frame); + ff_ccfifo_inject(ctx->cc_fifo, frame); + + return ff_filter_frame(outlink, frame); +} + +static av_cold void uninit(AVFilterContext *ctx) +{ + CCRepackContext *s = ctx->priv; + ff_ccfifo_freep(&s->cc_fifo); +} + +static const AVFilterPad avfilter_vf_ccrepack_inputs[] = { + { + .name = "default", + .type = AVMEDIA_TYPE_VIDEO, + .filter_frame = filter_frame, + .config_props = config_input, + }, +}; + +static const AVFilterPad avfilter_vf_ccrepack_outputs[] = { + { + .name = "default", + .type = AVMEDIA_TYPE_VIDEO, + }, +}; + +AVFilter ff_vf_ccrepack = { + .name = "ccrepack", + .description = NULL_IF_CONFIG_SMALL("Repack CEA-708 closed caption metadata"), + .uninit = uninit, + .priv_size = sizeof(CCRepackContext), + .priv_class = &ccrepack_class, + FILTER_INPUTS(avfilter_vf_ccrepack_inputs), + FILTER_OUTPUTS(avfilter_vf_ccrepack_outputs), +}; From 9f4df9a535c37cd63ed05dce215d37dec469e7d8 Mon Sep 17 00:00:00 2001 From: Devin Heitmueller Date: Fri, 5 May 2023 15:09:07 -0400 Subject: [PATCH 0962/2172] avdevice/decklink_enc: add support for playout of 608 captions in MOV files Unlike other cases where the closed captions are embedded in the video stream as MPEG-2 userdata or H.264 SEI data, with MOV files the captions are often found on a separate "e608" subtitle track. Add support for playout of such files, leveraging the new ccfifo mechanism to ensure that they are embedded into VANC at the correct rate (since e608 packets often contain batches of multiple 608 pairs). Note this patch includes a new file named libavdevice/ccfifo.c, which allows the ccfifo functionality in libavfilter to be reused even if doing shared builds. This is the same approach used for log2_tab.c. Signed-off-by: Devin Heitmueller Signed-off-by: Limin Wang --- libavdevice/Makefile | 1 + libavdevice/ccfifo.c | 24 +++++++++++++ libavdevice/decklink_common.h | 3 ++ libavdevice/decklink_enc.cpp | 65 +++++++++++++++++++++++++++++++++++ libavdevice/decklink_enc_c.c | 2 +- 5 files changed, 94 insertions(+), 1 deletion(-) create mode 100644 libavdevice/ccfifo.c diff --git a/libavdevice/Makefile b/libavdevice/Makefile index 8a62822b69e..c30449201d4 100644 --- a/libavdevice/Makefile +++ b/libavdevice/Makefile @@ -57,6 +57,7 @@ OBJS-$(CONFIG_LIBDC1394_INDEV) += libdc1394.o # Objects duplicated from other libraries for shared builds SHLIBOBJS-$(CONFIG_DECKLINK_INDEV) += reverse.o +SHLIBOBJS-$(CONFIG_DECKLINK_OUTDEV) += ccfifo.o # Windows resource file SHLIBOBJS-$(HAVE_GNU_WINDRES) += avdeviceres.o diff --git a/libavdevice/ccfifo.c b/libavdevice/ccfifo.c new file mode 100644 index 00000000000..9007094f0b3 --- /dev/null +++ b/libavdevice/ccfifo.c @@ -0,0 +1,24 @@ +/* + * CEA-708 Closed Captioning FIFO + * Copyright (c) 2023 LTN Global Communications + * + * Author: Devin Heitmueller + * + * 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 "libavfilter/ccfifo.c" diff --git a/libavdevice/decklink_common.h b/libavdevice/decklink_common.h index 088e165ee7c..0d33f94a6e2 100644 --- a/libavdevice/decklink_common.h +++ b/libavdevice/decklink_common.h @@ -31,6 +31,7 @@ extern "C" { #include "libavcodec/packet_internal.h" +#include "libavfilter/ccfifo.h" } #include "libavutil/thread.h" #include "decklink_common_c.h" @@ -112,6 +113,8 @@ struct decklink_ctx { /* Capture buffer queue */ AVPacketQueue queue; + AVCCFifo *cc_fifo; ///< closed captions + /* Streams present */ int audio; int video; diff --git a/libavdevice/decklink_enc.cpp b/libavdevice/decklink_enc.cpp index 9f1a8df438e..22aa80b8c22 100644 --- a/libavdevice/decklink_enc.cpp +++ b/libavdevice/decklink_enc.cpp @@ -326,6 +326,25 @@ static int create_s337_payload(AVPacket *pkt, uint8_t **outbuf, int *outsize) return 0; } +static int decklink_setup_subtitle(AVFormatContext *avctx, AVStream *st) +{ + int ret = -1; + + switch(st->codecpar->codec_id) { +#if CONFIG_LIBKLVANC + case AV_CODEC_ID_EIA_608: + /* No special setup required */ + ret = 0; + break; +#endif + default: + av_log(avctx, AV_LOG_ERROR, "Unsupported subtitle codec specified\n"); + break; + } + + return ret; +} + av_cold int ff_decklink_write_trailer(AVFormatContext *avctx) { struct decklink_cctx *cctx = (struct decklink_cctx *)avctx->priv_data; @@ -352,6 +371,7 @@ av_cold int ff_decklink_write_trailer(AVFormatContext *avctx) klvanc_context_destroy(ctx->vanc_ctx); #endif + ff_ccfifo_freep(&ctx->cc_fifo); av_freep(&cctx->ctx); return 0; @@ -503,6 +523,21 @@ static void construct_afd(AVFormatContext *avctx, struct decklink_ctx *ctx, free(afd_words); } +/* Parse any EIA-608 subtitles sitting on the queue, and write packet side data + that will later be handled by construct_cc... */ +static void parse_608subs(AVFormatContext *avctx, struct decklink_ctx *ctx, AVPacket *pkt) +{ + size_t cc_size = ff_ccfifo_getoutputsize(ctx->cc_fifo); + uint8_t *cc_data; + + if (!ff_ccfifo_ccdetected(ctx->cc_fifo)) + return; + + cc_data = av_packet_new_side_data(pkt, AV_PKT_DATA_A53_CC, cc_size); + if (cc_data) + ff_ccfifo_injectbytes(ctx->cc_fifo, cc_data, cc_size); +} + static int decklink_construct_vanc(AVFormatContext *avctx, struct decklink_ctx *ctx, AVPacket *pkt, decklink_frame *frame, AVStream *st) @@ -513,6 +548,7 @@ static int decklink_construct_vanc(AVFormatContext *avctx, struct decklink_ctx * if (!ctx->supports_vanc) return 0; + parse_608subs(avctx, ctx, pkt); construct_cc(avctx, ctx, pkt, &vanc_lines); construct_afd(avctx, ctx, pkt, &vanc_lines, st); @@ -704,6 +740,16 @@ static int decklink_write_audio_packet(AVFormatContext *avctx, AVPacket *pkt) return ret; } +static int decklink_write_subtitle_packet(AVFormatContext *avctx, AVPacket *pkt) +{ + struct decklink_cctx *cctx = (struct decklink_cctx *)avctx->priv_data; + struct decklink_ctx *ctx = (struct decklink_ctx *)cctx->ctx; + + ff_ccfifo_extractbytes(ctx->cc_fifo, pkt->data, pkt->size); + + return 0; +} + extern "C" { av_cold int ff_decklink_write_header(AVFormatContext *avctx) @@ -768,12 +814,29 @@ av_cold int ff_decklink_write_header(AVFormatContext *avctx) } else if (c->codec_type == AVMEDIA_TYPE_VIDEO) { if (decklink_setup_video(avctx, st)) goto error; + } else if (c->codec_type == AVMEDIA_TYPE_SUBTITLE) { + if (decklink_setup_subtitle(avctx, st)) + goto error; } else { av_log(avctx, AV_LOG_ERROR, "Unsupported stream type.\n"); goto error; } } + for (n = 0; n < avctx->nb_streams; n++) { + AVStream *st = avctx->streams[n]; + AVCodecParameters *c = st->codecpar; + + if(c->codec_type == AVMEDIA_TYPE_SUBTITLE) + avpriv_set_pts_info(st, 64, ctx->bmd_tb_num, ctx->bmd_tb_den); + } + + if (!(ctx->cc_fifo = ff_ccfifo_alloc(av_make_q(ctx->bmd_tb_den, ctx->bmd_tb_num), avctx))) { + av_log(ctx, AV_LOG_ERROR, "Failure to setup CC FIFO queue\n"); + ret = AVERROR(ENOMEM); + goto error; + } + return 0; error: @@ -789,6 +852,8 @@ int ff_decklink_write_packet(AVFormatContext *avctx, AVPacket *pkt) return decklink_write_video_packet(avctx, pkt); else if (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) return decklink_write_audio_packet(avctx, pkt); + else if (st->codecpar->codec_type == AVMEDIA_TYPE_SUBTITLE) + return decklink_write_subtitle_packet(avctx, pkt); return AVERROR(EIO); } diff --git a/libavdevice/decklink_enc_c.c b/libavdevice/decklink_enc_c.c index f7e315057fc..0a3984b9e23 100644 --- a/libavdevice/decklink_enc_c.c +++ b/libavdevice/decklink_enc_c.c @@ -77,7 +77,7 @@ const FFOutputFormat ff_decklink_muxer = { .p.long_name = NULL_IF_CONFIG_SMALL("Blackmagic DeckLink output"), .p.audio_codec = AV_CODEC_ID_PCM_S16LE, .p.video_codec = AV_CODEC_ID_WRAPPED_AVFRAME, - .p.subtitle_codec = AV_CODEC_ID_NONE, + .p.subtitle_codec = AV_CODEC_ID_EIA_608, .p.flags = AVFMT_NOFILE, .p.priv_class = &decklink_muxer_class, .get_device_list = ff_decklink_list_output_devices, From 23d968d55a6e00dfc46799cfd0eb2ed02379037d Mon Sep 17 00:00:00 2001 From: Pierre-Anthony Lemieux Date: Wed, 26 Apr 2023 08:09:40 -0700 Subject: [PATCH 0963/2172] avformat/imf: fix invalid resource handling --- libavformat/imf_cpl.c | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/libavformat/imf_cpl.c b/libavformat/imf_cpl.c index ad84a68b13b..a7cf5fa3600 100644 --- a/libavformat/imf_cpl.c +++ b/libavformat/imf_cpl.c @@ -608,11 +608,10 @@ static int push_main_audio_sequence(xmlNodePtr audio_sequence_elem, FFIMFCPL *cp ret = fill_trackfile_resource(resource_elem, &vt->resources[vt->resource_count], cpl); - vt->resource_count++; - if (ret) { + if (ret) av_log(NULL, AV_LOG_ERROR, "Invalid Resource\n"); - continue; - } + else + vt->resource_count++; resource_elem = xmlNextElementSibling(resource_elem); } @@ -691,11 +690,10 @@ static int push_main_image_2d_sequence(xmlNodePtr image_sequence_elem, FFIMFCPL 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) { + if (ret) av_log(NULL, AV_LOG_ERROR, "Invalid Resource\n"); - continue; - } + else + cpl->main_image_2d_track->resource_count++; resource_elem = xmlNextElementSibling(resource_elem); } From 21696f6122a91b1ae936db3c5f30138725331603 Mon Sep 17 00:00:00 2001 From: Pierre-Anthony Lemieux Date: Wed, 26 Apr 2023 09:25:13 -0700 Subject: [PATCH 0964/2172] avformat/tests/imf: add invalid resource test --- libavformat/tests/imf.c | 65 +++++++++++++++++++++++++++++++++++++++++ tests/ref/fate/imf | 2 ++ 2 files changed, 67 insertions(+) diff --git a/libavformat/tests/imf.c b/libavformat/tests/imf.c index 2cacb43f477..cfd84fb8c8d 100644 --- a/libavformat/tests/imf.c +++ b/libavformat/tests/imf.c @@ -218,6 +218,45 @@ const char *cpl_doc = "" ""; + const char *cpl_bad_resource_doc = + "" + "urn:uuid:8713c020-2489-45f5-a9f7-87be539e20b5" + "2021-07-13T17:06:22Z" + "FFMPEG" + "FFMPEG sample content" + "" + " " + " urn:uuid:8e097bb0-cff7-4969-a692-bad47bfb528f" + " " + "" + "" + "false" + "24" + "02:10:01.23" + "" + "24000 1001" + "" + "" + "urn:uuid:81fed4e5-9722-400a-b9d1-7f2bd21df4b6" + "" + "" + "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" + "" + "" + "" + "" + "" + "" + ""; + const char *cpl_bad_doc = ""; const char *asset_map_doc = @@ -366,6 +405,27 @@ static int test_bad_cpl_parsing(FFIMFCPL **cpl) return 0; } +static int test_bad_resource_cpl_parsing(FFIMFCPL **cpl) +{ + xmlDocPtr doc; + int ret; + + doc = xmlReadMemory(cpl_bad_resource_doc, strlen(cpl_bad_resource_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 ret; + } + + return 0; +} + static int check_asset_locator_attributes(IMFAssetLocator *asset, IMFAssetLocator *expected_asset) { @@ -533,5 +593,10 @@ int main(int argc, char *argv[]) } printf("#### End failing test ####\n"); + printf("#### The following should emit errors ####\n"); + if (test_bad_resource_cpl_parsing(&cpl) != 0) + ret = 1; + printf("#### End emission of errors ####\n"); + return ret; } diff --git a/tests/ref/fate/imf b/tests/ref/fate/imf index 5093167bc7b..fdfed8ac175 100644 --- a/tests/ref/fate/imf +++ b/tests/ref/fate/imf @@ -53,3 +53,5 @@ For asset: 4: #### The following should fail #### CPL parsing failed. #### End failing test #### +#### The following should emit errors #### +#### End emission of errors #### From 869c06886dfdbc5d4734bb8f4ee85f36b2f3aa2b Mon Sep 17 00:00:00 2001 From: Timo Rothenpieler Date: Thu, 11 May 2023 19:24:55 +0200 Subject: [PATCH 0965/2172] avfilter/vf_yadif_cuda: fix build Identical patches were sent by Leo Izen and Devin Heitmueller. --- libavfilter/vf_yadif_cuda.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libavfilter/vf_yadif_cuda.c b/libavfilter/vf_yadif_cuda.c index f3f0b567686..73f04126c59 100644 --- a/libavfilter/vf_yadif_cuda.c +++ b/libavfilter/vf_yadif_cuda.c @@ -205,7 +205,7 @@ static av_cold void deint_cuda_uninit(AVFilterContext *ctx) av_frame_free(&y->prev); av_frame_free(&y->cur); av_frame_free(&y->next); - ff_cc_fifo_freep(&y->cc_fifo); + ff_ccfifo_freep(&y->cc_fifo); av_buffer_unref(&s->device_ref); s->hwctx = NULL; @@ -295,7 +295,7 @@ static int config_output(AVFilterLink *link) else link->frame_rate = ctx->inputs[0]->frame_rate; - if (!(s->cc_fifo = ff_cc_fifo_alloc(link->frame_rate, ctx))) { + if (!(y->cc_fifo = ff_ccfifo_alloc(link->frame_rate, ctx))) { av_log(ctx, AV_LOG_ERROR, "Failure to setup CC FIFO queue\n"); ret = AVERROR(ENOMEM); goto exit; From f0136502433d92ce5da3db9d21aa11573764eec3 Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Thu, 11 May 2023 18:52:33 +0200 Subject: [PATCH 0966/2172] avfilter/avf_showwaves: zero whole allocated chunk --- libavfilter/avf_showwaves.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavfilter/avf_showwaves.c b/libavfilter/avf_showwaves.c index 76399ab13dd..3db192a835b 100644 --- a/libavfilter/avf_showwaves.c +++ b/libavfilter/avf_showwaves.c @@ -591,7 +591,7 @@ static int push_single_pic(AVFilterLink *outlink) av_log(ctx, AV_LOG_DEBUG, "Create frame averaging %"PRId64" samples per column\n", column_max_samples); - memset(sum, 0, nb_channels); + memset(sum, 0, nb_channels * sizeof(*sum)); for (node = showwaves->audio_frames; node; node = node->next) { int i; From d1ded7310a110b5977f6d3372047331de4e90d01 Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Thu, 11 May 2023 20:10:57 +0200 Subject: [PATCH 0967/2172] avfilter/af_surround: reduce double usage --- libavfilter/af_surround.c | 54 +++++++++++++++++++-------------------- 1 file changed, 27 insertions(+), 27 deletions(-) diff --git a/libavfilter/af_surround.c b/libavfilter/af_surround.c index 925cb6e66c8..bcc89053a4d 100644 --- a/libavfilter/af_surround.c +++ b/libavfilter/af_surround.c @@ -330,16 +330,16 @@ static void angle_transform(float *x, float *y, float angle) if (angle == 90.f) return; - reference = angle * M_PI / 180.f; + reference = angle * (float)M_PI / 180.f; r = hypotf(*x, *y); a = atan2f(*x, *y); r /= r_distance(a); - if (fabsf(a) <= M_PI_4) - a *= reference / M_PI_2; + if (fabsf(a) <= (float)M_PI_4) + a *= reference / (float)M_PI_2; else - a = M_PI + (-2.f * M_PI + reference) * (M_PI - fabsf(a)) * FFDIFFSIGN(a, 0.f) / (3.f * M_PI_2); + a = (float)M_PI + (-2.f * (float)M_PI + reference) * ((float)M_PI - fabsf(a)) * FFDIFFSIGN(a, 0.f) / (3.f * (float)M_PI_2); r *= r_distance(a); @@ -366,16 +366,16 @@ static void focus_transform(float *x, float *y, float focus) static void stereo_position(float a, float p, float *x, float *y) { av_assert2(a >= -1.f && a <= 1.f); - av_assert2(p >= 0.f && p <= M_PI); - *x = av_clipf(a+a*fmaxf(0.f, p*p-M_PI_2), -1.f, 1.f); - *y = av_clipf(cosf(a*M_PI_2+M_PI)*cosf(M_PI_2-p/M_PI)*M_LN10+1.f, -1.f, 1.f); + av_assert2(p >= 0.f && p <= (float)M_PI); + *x = av_clipf(a+a*fmaxf(0.f, p*p-(float)M_PI_2), -1.f, 1.f); + *y = av_clipf(cosf(a*(float)M_PI_2+(float)M_PI)*cosf((float)M_PI_2-p/(float)M_PI)*(float)M_LN10+1.f, -1.f, 1.f); } static inline void get_lfe(int output_lfe, int n, float lowcut, float highcut, float *lfe_mag, float c_mag, float *mag_total, int lfe_mode) { if (output_lfe && n < highcut) { - *lfe_mag = n < lowcut ? 1.f : .5f*(1.f+cosf(M_PI*(lowcut-n)/(lowcut-highcut))); + *lfe_mag = n < lowcut ? 1.f : .5f*(1.f+cosf((float)M_PI*(lowcut-n)/(lowcut-highcut))); *lfe_mag *= c_mag; if (lfe_mode) *mag_total -= *lfe_mag; @@ -413,7 +413,7 @@ static void calculate_factors(AVFilterContext *ctx, int ch, int chan) break; case AV_CHAN_LOW_FREQUENCY: for (int n = 0; n < rdft_size; n++) - factor[n] = powf(1.f - fabsf(x[n]), f_x) * powf((1.f - fabs(y[n])), f_y); + factor[n] = powf(1.f - fabsf(x[n]), f_x) * powf((1.f - fabsf(y[n])), f_y); break; case AV_CHAN_BACK_CENTER: for (int n = 0; n < rdft_size; n++) @@ -777,8 +777,8 @@ static void filter_stereo(AVFilterContext *ctx) mag_sum = mag_sum < MIN_MAG_SUM ? 1.f : mag_sum; mag_dif = (l_mag - r_mag) / mag_sum; - if (phase_dif > M_PI) - phase_dif = 2.f * M_PI - phase_dif; + if (phase_dif > (float)M_PI) + phase_dif = 2.f * (float)M_PI - phase_dif; stereo_position(mag_dif, phase_dif, &x, &y); angle_transform(&x, &y, angle); @@ -832,8 +832,8 @@ static void filter_2_1(AVFilterContext *ctx) mag_sum = mag_sum < MIN_MAG_SUM ? 1.f : mag_sum; mag_dif = (l_mag - r_mag) / mag_sum; - if (phase_dif > M_PI) - phase_dif = 2.f * M_PI - phase_dif; + if (phase_dif > (float)M_PI) + phase_dif = 2.f * (float)M_PI - phase_dif; stereo_position(mag_dif, phase_dif, &x, &y); angle_transform(&x, &y, angle); @@ -889,8 +889,8 @@ static void filter_surround(AVFilterContext *ctx) mag_sum = mag_sum < MIN_MAG_SUM ? 1.f : mag_sum; mag_dif = (l_mag - r_mag) / mag_sum; - if (phase_dif > M_PI) - phase_dif = 2.f * M_PI - phase_dif; + if (phase_dif > (float)M_PI) + phase_dif = 2.f * (float)M_PI - phase_dif; stereo_position(mag_dif, phase_dif, &x, &y); angle_transform(&x, &y, angle); @@ -946,11 +946,11 @@ static void filter_5_0_side(AVFilterContext *ctx) float xl, yl; float xr, yr; - if (phase_difl > M_PI) - phase_difl = 2.f * M_PI - phase_difl; + if (phase_difl > (float)M_PI) + phase_difl = 2.f * (float)M_PI - phase_difl; - if (phase_difr > M_PI) - phase_difr = 2.f * M_PI - phase_difr; + if (phase_difr > (float)M_PI) + phase_difr = 2.f * (float)M_PI - phase_difr; stereo_position(mag_difl, phase_difl, &xl, &yl); stereo_position(mag_difr, phase_difr, &xr, &yr); @@ -1005,11 +1005,11 @@ static void filter_5_1_side(AVFilterContext *ctx) float xl, yl; float xr, yr; - if (phase_difl > M_PI) - phase_difl = 2.f * M_PI - phase_difl; + if (phase_difl > (float)M_PI) + phase_difl = 2.f * (float)M_PI - phase_difl; - if (phase_difr > M_PI) - phase_difr = 2.f * M_PI - phase_difr; + if (phase_difr > (float)M_PI) + phase_difr = 2.f * (float)M_PI - phase_difr; stereo_position(mag_difl, phase_difl, &xl, &yl); stereo_position(mag_difr, phase_difr, &xr, &yr); @@ -1064,11 +1064,11 @@ static void filter_5_1_back(AVFilterContext *ctx) float xl, yl; float xr, yr; - if (phase_difl > M_PI) - phase_difl = 2.f * M_PI - phase_difl; + if (phase_difl > (float)M_PI) + phase_difl = 2.f * (float)M_PI - phase_difl; - if (phase_difr > M_PI) - phase_difr = 2.f * M_PI - phase_difr; + if (phase_difr > (float)M_PI) + phase_difr = 2.f * (float)M_PI - phase_difr; stereo_position(mag_difl, phase_difl, &xl, &yl); stereo_position(mag_difr, phase_difr, &xr, &yr); From 4373dadc39be32611c5366fdae89ffb3e103279c Mon Sep 17 00:00:00 2001 From: Ammon Riley Date: Wed, 26 Apr 2023 18:26:35 -0700 Subject: [PATCH 0968/2172] avformat/mxfdec: recognize AAC per SMPTE ST 381-4 This patch simply recognizes the AAC audio track during decode -- it does not add functionality to encode AAC in MXF. Signed-off-by: Ammon Riley Signed-off-by: Marton Balint --- libavformat/mxf.c | 2 ++ libavformat/mxfdec.c | 5 +++++ 2 files changed, 7 insertions(+) diff --git a/libavformat/mxf.c b/libavformat/mxf.c index 8ef928b8fc2..a73e40e514b 100644 --- a/libavformat/mxf.c +++ b/libavformat/mxf.c @@ -78,6 +78,8 @@ const MXFCodecUL ff_mxf_codec_uls[] = { { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x01,0x04,0x02,0x02,0x02,0x03,0x02,0x01,0x00 }, 15, AV_CODEC_ID_AC3 }, { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x01,0x04,0x02,0x02,0x02,0x03,0x02,0x05,0x00 }, 15, AV_CODEC_ID_MP2 }, /* MP2 or MP3 */ //{ { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x01,0x04,0x02,0x02,0x02,0x03,0x02,0x1C,0x00 }, 15, AV_CODEC_ID_DOLBY_E }, /* Dolby-E */ + { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0D,0x04,0x02,0x02,0x02,0x04,0x03,0x00,0x00 }, 14, AV_CODEC_ID_AAC }, /* MPEG-2 AAC SMPTE 381-4 */ + { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0D,0x04,0x02,0x02,0x02,0x04,0x04,0x00,0x00 }, 14, AV_CODEC_ID_AAC }, /* MPEG-4 AAC SMPTE 381-4 */ { { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, 0, AV_CODEC_ID_NONE }, }; diff --git a/libavformat/mxfdec.c b/libavformat/mxfdec.c index 8a7008b298c..34230ece980 100644 --- a/libavformat/mxfdec.c +++ b/libavformat/mxfdec.c @@ -1628,6 +1628,9 @@ static const MXFCodecUL mxf_sound_essence_container_uls[] = { { { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x01,0x0d,0x01,0x03,0x01,0x02,0x01,0x01,0x01 }, 14, AV_CODEC_ID_PCM_S16LE, NULL, 13 }, /* D-10 Mapping 50Mbps PAL Extended Template */ { { 0x06,0x0e,0x2b,0x34,0x01,0x01,0x01,0xff,0x4b,0x46,0x41,0x41,0x00,0x0d,0x4d,0x4F }, 14, AV_CODEC_ID_PCM_S16LE }, /* 0001GL00.MXF.A1.mxf_opatom.mxf */ { { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x03,0x04,0x02,0x02,0x02,0x03,0x03,0x01,0x00 }, 14, AV_CODEC_ID_AAC }, /* MPEG-2 AAC ADTS (legacy) */ + { { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x0d,0x0d,0x01,0x03,0x01,0x02,0x16,0x00,0x00 }, 14, AV_CODEC_ID_AAC, NULL, 14 }, /* AAC ADIF (SMPTE 381-4) */ + { { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x0d,0x0d,0x01,0x03,0x01,0x02,0x17,0x00,0x00 }, 14, AV_CODEC_ID_AAC, NULL, 14 }, /* AAC ADTS (SMPTE 381-4) */ + { { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x0d,0x0d,0x01,0x03,0x01,0x02,0x18,0x00,0x00 }, 14, AV_CODEC_ID_AAC, NULL, 14 }, /* AAC LATM/LOAS (SMPTE 381-4) */ { { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, 0, AV_CODEC_ID_NONE }, }; @@ -3029,6 +3032,8 @@ static int mxf_parse_structural_metadata(MXFContext *mxf) st->codecpar->codec_id = AV_CODEC_ID_PCM_S32BE; } else if (st->codecpar->codec_id == AV_CODEC_ID_MP2) { sti->need_parsing = AVSTREAM_PARSE_FULL; + } else if (st->codecpar->codec_id == AV_CODEC_ID_AAC) { + sti->need_parsing = AVSTREAM_PARSE_FULL; } st->codecpar->bits_per_coded_sample = av_get_bits_per_sample(st->codecpar->codec_id); From 4fd729a1f8a48dfb9b9a5a0ebf72f0733afe3300 Mon Sep 17 00:00:00 2001 From: Devin Heitmueller Date: Fri, 28 Apr 2023 14:40:51 -0400 Subject: [PATCH 0969/2172] avdevice/decklink: move AVPacketQueue into decklink_common and rename it to DecklinkPacketQueue Move the AVPacketQueue functionality that is currently only used for the decklink decode module into decklink_common, so it can be shared by the decklink encoder (i.e. for VANC insertion when we receive data packets separate from video). The threadsafe queue used within the decklink module was named "AVPacketQueue" which implies that it is part of the public API, which it is not. Rename the functions and the name of the queue struct to make clear it is used exclusively by decklink, per Marton Balint's suggestion. Signed-off-by: Devin Heitmueller Signed-off-by: Marton Balint --- libavdevice/decklink_common.cpp | 115 ++++++++++++++++++++++++++++ libavdevice/decklink_common.h | 13 +++- libavdevice/decklink_dec.cpp | 130 ++------------------------------ 3 files changed, 133 insertions(+), 125 deletions(-) diff --git a/libavdevice/decklink_common.cpp b/libavdevice/decklink_common.cpp index acd1f77e6c9..74e26e986d6 100644 --- a/libavdevice/decklink_common.cpp +++ b/libavdevice/decklink_common.cpp @@ -390,6 +390,121 @@ int ff_decklink_set_format(AVFormatContext *avctx, decklink_direction_t directio return ff_decklink_set_format(avctx, 0, 0, 0, 0, AV_FIELD_UNKNOWN, direction); } +void ff_decklink_packet_queue_init(AVFormatContext *avctx, DecklinkPacketQueue *q) +{ + struct decklink_cctx *ctx = (struct decklink_cctx *)avctx->priv_data; + memset(q, 0, sizeof(DecklinkPacketQueue)); + pthread_mutex_init(&q->mutex, NULL); + pthread_cond_init(&q->cond, NULL); + q->avctx = avctx; + q->max_q_size = ctx->queue_size; +} + +void ff_decklink_packet_queue_flush(DecklinkPacketQueue *q) +{ + PacketListEntry *pkt, *pkt1; + + pthread_mutex_lock(&q->mutex); + for (pkt = q->pkt_list.head; pkt != NULL; pkt = pkt1) { + pkt1 = pkt->next; + av_packet_unref(&pkt->pkt); + av_freep(&pkt); + } + q->pkt_list.head = NULL; + q->pkt_list.tail = NULL; + q->nb_packets = 0; + q->size = 0; + pthread_mutex_unlock(&q->mutex); +} + +void ff_decklink_packet_queue_end(DecklinkPacketQueue *q) +{ + ff_decklink_packet_queue_flush(q); + pthread_mutex_destroy(&q->mutex); + pthread_cond_destroy(&q->cond); +} + +unsigned long long ff_decklink_packet_queue_size(DecklinkPacketQueue *q) +{ + unsigned long long size; + pthread_mutex_lock(&q->mutex); + size = q->size; + pthread_mutex_unlock(&q->mutex); + return size; +} + +int ff_decklink_packet_queue_put(DecklinkPacketQueue *q, AVPacket *pkt) +{ + PacketListEntry *pkt1; + + // Drop Packet if queue size is > maximum queue size + if (ff_decklink_packet_queue_size(q) > (uint64_t)q->max_q_size) { + av_packet_unref(pkt); + av_log(q->avctx, AV_LOG_WARNING, "Decklink input buffer overrun!\n"); + return -1; + } + /* ensure the packet is reference counted */ + if (av_packet_make_refcounted(pkt) < 0) { + av_packet_unref(pkt); + return -1; + } + + pkt1 = (PacketListEntry *)av_malloc(sizeof(*pkt1)); + if (!pkt1) { + av_packet_unref(pkt); + return -1; + } + av_packet_move_ref(&pkt1->pkt, pkt); + pkt1->next = NULL; + + pthread_mutex_lock(&q->mutex); + + if (!q->pkt_list.tail) { + q->pkt_list.head = pkt1; + } else { + q->pkt_list.tail->next = pkt1; + } + + q->pkt_list.tail = pkt1; + q->nb_packets++; + q->size += pkt1->pkt.size + sizeof(*pkt1); + + pthread_cond_signal(&q->cond); + + pthread_mutex_unlock(&q->mutex); + return 0; +} + +int ff_decklink_packet_queue_get(DecklinkPacketQueue *q, AVPacket *pkt, int block) +{ + int ret; + + pthread_mutex_lock(&q->mutex); + + for (;; ) { + PacketListEntry *pkt1 = q->pkt_list.head; + if (pkt1) { + 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); + *pkt = pkt1->pkt; + av_free(pkt1); + ret = 1; + break; + } else if (!block) { + ret = 0; + break; + } else { + pthread_cond_wait(&q->cond, &q->mutex); + } + } + pthread_mutex_unlock(&q->mutex); + return ret; +} + int ff_decklink_list_devices(AVFormatContext *avctx, struct AVDeviceInfoList *device_list, int show_inputs, int show_outputs) diff --git a/libavdevice/decklink_common.h b/libavdevice/decklink_common.h index 0d33f94a6e2..1cc6d9c2cc2 100644 --- a/libavdevice/decklink_common.h +++ b/libavdevice/decklink_common.h @@ -78,7 +78,7 @@ static char *dup_cfstring_to_utf8(CFStringRef w) class decklink_output_callback; class decklink_input_callback; -typedef struct AVPacketQueue { +typedef struct DecklinkPacketQueue { PacketList pkt_list; int nb_packets; unsigned long long size; @@ -87,7 +87,7 @@ typedef struct AVPacketQueue { pthread_cond_t cond; AVFormatContext *avctx; int64_t max_q_size; -} AVPacketQueue; +} DecklinkPacketQueue; struct decklink_ctx { /* DeckLink SDK interfaces */ @@ -111,7 +111,7 @@ struct decklink_ctx { int supports_vanc; /* Capture buffer queue */ - AVPacketQueue queue; + DecklinkPacketQueue queue; AVCCFifo *cc_fifo; ///< closed captions @@ -235,4 +235,11 @@ int ff_decklink_list_formats(AVFormatContext *avctx, decklink_direction_t direct void ff_decklink_cleanup(AVFormatContext *avctx); int ff_decklink_init_device(AVFormatContext *avctx, const char* name); +void ff_decklink_packet_queue_init(AVFormatContext *avctx, DecklinkPacketQueue *q); +void ff_decklink_packet_queue_flush(DecklinkPacketQueue *q); +void ff_decklink_packet_queue_end(DecklinkPacketQueue *q); +unsigned long long ff_decklink_packet_queue_size(DecklinkPacketQueue *q); +int ff_decklink_packet_queue_put(DecklinkPacketQueue *q, AVPacket *pkt); +int ff_decklink_packet_queue_get(DecklinkPacketQueue *q, AVPacket *pkt, int block); + #endif /* AVDEVICE_DECKLINK_COMMON_H */ diff --git a/libavdevice/decklink_dec.cpp b/libavdevice/decklink_dec.cpp index 7bf5e3724ca..66abee12683 100644 --- a/libavdevice/decklink_dec.cpp +++ b/libavdevice/decklink_dec.cpp @@ -471,120 +471,6 @@ static uint8_t *get_metadata(AVFormatContext *avctx, uint16_t *buf, size_t width return tgt; } -static void avpacket_queue_init(AVFormatContext *avctx, AVPacketQueue *q) -{ - struct decklink_cctx *ctx = (struct decklink_cctx *)avctx->priv_data; - memset(q, 0, sizeof(AVPacketQueue)); - pthread_mutex_init(&q->mutex, NULL); - pthread_cond_init(&q->cond, NULL); - q->avctx = avctx; - q->max_q_size = ctx->queue_size; -} - -static void avpacket_queue_flush(AVPacketQueue *q) -{ - PacketListEntry *pkt, *pkt1; - - pthread_mutex_lock(&q->mutex); - for (pkt = q->pkt_list.head; pkt != NULL; pkt = pkt1) { - pkt1 = pkt->next; - av_packet_unref(&pkt->pkt); - av_freep(&pkt); - } - q->pkt_list.head = NULL; - q->pkt_list.tail = NULL; - q->nb_packets = 0; - q->size = 0; - pthread_mutex_unlock(&q->mutex); -} - -static void avpacket_queue_end(AVPacketQueue *q) -{ - avpacket_queue_flush(q); - pthread_mutex_destroy(&q->mutex); - pthread_cond_destroy(&q->cond); -} - -static unsigned long long avpacket_queue_size(AVPacketQueue *q) -{ - unsigned long long size; - pthread_mutex_lock(&q->mutex); - size = q->size; - pthread_mutex_unlock(&q->mutex); - return size; -} - -static int avpacket_queue_put(AVPacketQueue *q, AVPacket *pkt) -{ - PacketListEntry *pkt1; - - // Drop Packet if queue size is > maximum queue size - if (avpacket_queue_size(q) > (uint64_t)q->max_q_size) { - av_packet_unref(pkt); - av_log(q->avctx, AV_LOG_WARNING, "Decklink input buffer overrun!\n"); - return -1; - } - /* ensure the packet is reference counted */ - if (av_packet_make_refcounted(pkt) < 0) { - av_packet_unref(pkt); - return -1; - } - - pkt1 = (PacketListEntry *)av_malloc(sizeof(*pkt1)); - if (!pkt1) { - av_packet_unref(pkt); - return -1; - } - av_packet_move_ref(&pkt1->pkt, pkt); - pkt1->next = NULL; - - pthread_mutex_lock(&q->mutex); - - if (!q->pkt_list.tail) { - q->pkt_list.head = pkt1; - } else { - q->pkt_list.tail->next = pkt1; - } - - q->pkt_list.tail = pkt1; - q->nb_packets++; - q->size += pkt1->pkt.size + sizeof(*pkt1); - - pthread_cond_signal(&q->cond); - - pthread_mutex_unlock(&q->mutex); - return 0; -} - -static int avpacket_queue_get(AVPacketQueue *q, AVPacket *pkt, int block) -{ - int ret; - - pthread_mutex_lock(&q->mutex); - - for (;; ) { - PacketListEntry *pkt1 = q->pkt_list.head; - if (pkt1) { - 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); - *pkt = pkt1->pkt; - av_free(pkt1); - ret = 1; - break; - } else if (!block) { - ret = 0; - break; - } else { - pthread_cond_wait(&q->cond, &q->mutex); - } - } - pthread_mutex_unlock(&q->mutex); - return ret; -} static void handle_klv(AVFormatContext *avctx, decklink_ctx *ctx, IDeckLinkVideoInputFrame *videoFrame, int64_t pts) { @@ -682,7 +568,7 @@ static void handle_klv(AVFormatContext *avctx, decklink_ctx *ctx, IDeckLinkVideo klv_packet.data = klv.data(); klv_packet.size = klv.size(); - if (avpacket_queue_put(&ctx->queue, &klv_packet) < 0) { + if (ff_decklink_packet_queue_put(&ctx->queue, &klv_packet) < 0) { ++ctx->dropped; } } @@ -874,7 +760,7 @@ HRESULT decklink_input_callback::VideoInputFrameArrived( if (videoFrame) { AVPacket pkt = { 0 }; if (ctx->frameCount % 25 == 0) { - unsigned long long qsize = avpacket_queue_size(&ctx->queue); + unsigned long long qsize = ff_decklink_packet_queue_size(&ctx->queue); av_log(avctx, AV_LOG_DEBUG, "Frame received (#%lu) - Valid (%liB) - QSize %fMB\n", ctx->frameCount, @@ -1038,7 +924,7 @@ HRESULT decklink_input_callback::VideoInputFrameArrived( txt_pkt.stream_index = ctx->teletext_st->index; txt_pkt.data = txt_buf0; txt_pkt.size = txt_buf - txt_buf0; - if (avpacket_queue_put(&ctx->queue, &txt_pkt) < 0) { + if (ff_decklink_packet_queue_put(&ctx->queue, &txt_pkt) < 0) { ++ctx->dropped; } } @@ -1049,7 +935,7 @@ HRESULT decklink_input_callback::VideoInputFrameArrived( if (pkt.buf) videoFrame->AddRef(); - if (avpacket_queue_put(&ctx->queue, &pkt) < 0) { + if (ff_decklink_packet_queue_put(&ctx->queue, &pkt) < 0) { ++ctx->dropped; } } @@ -1071,7 +957,7 @@ HRESULT decklink_input_callback::VideoInputFrameArrived( pkt.stream_index = ctx->audio_st->index; pkt.data = (uint8_t *)audioFrameBytes; - if (avpacket_queue_put(&ctx->queue, &pkt) < 0) { + if (ff_decklink_packet_queue_put(&ctx->queue, &pkt) < 0) { ++ctx->dropped; } } @@ -1153,7 +1039,7 @@ av_cold int ff_decklink_read_close(AVFormatContext *avctx) } ff_decklink_cleanup(avctx); - avpacket_queue_end(&ctx->queue); + ff_decklink_packet_queue_end(&ctx->queue); av_freep(&cctx->ctx); @@ -1411,7 +1297,7 @@ av_cold int ff_decklink_read_header(AVFormatContext *avctx) goto error; } - avpacket_queue_init (avctx, &ctx->queue); + ff_decklink_packet_queue_init(avctx, &ctx->queue); if (ctx->dli->StartStreams() != S_OK) { av_log(avctx, AV_LOG_ERROR, "Cannot start input stream\n"); @@ -1431,7 +1317,7 @@ int ff_decklink_read_packet(AVFormatContext *avctx, AVPacket *pkt) struct decklink_cctx *cctx = (struct decklink_cctx *)avctx->priv_data; struct decklink_ctx *ctx = (struct decklink_ctx *)cctx->ctx; - avpacket_queue_get(&ctx->queue, pkt, 1); + ff_decklink_packet_queue_get(&ctx->queue, pkt, 1); if (ctx->tc_format && !(av_dict_get(ctx->video_st->metadata, "timecode", NULL, 0))) { size_t size; From 09cd89df27a97cb1946f0edacc4054f8dcb766b1 Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Fri, 12 May 2023 10:13:18 +0200 Subject: [PATCH 0970/2172] avfilter/af_surround: cache constant rdft_size inside loops --- libavfilter/af_surround.c | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/libavfilter/af_surround.c b/libavfilter/af_surround.c index bcc89053a4d..682c1f5dcb7 100644 --- a/libavfilter/af_surround.c +++ b/libavfilter/af_surround.c @@ -747,6 +747,7 @@ static void filter_stereo(AVFilterContext *ctx) const float *srcl = (const float *)s->input->extended_data[0]; const float *srcr = (const float *)s->input->extended_data[1]; const int output_lfe = s->output_lfe && s->create_lfe; + const int rdft_size = s->rdft_size; const int lfe_mode = s->lfe_mode; const float highcut = s->highcut; const float lowcut = s->lowcut; @@ -761,7 +762,7 @@ static void filter_stereo(AVFilterContext *ctx) float *xpos = s->x_pos; float *ypos = s->y_pos; - for (int n = 0; n < s->rdft_size; n++) { + for (int n = 0; n < rdft_size; n++) { float l_re = srcl[2 * n], r_re = srcr[2 * n]; float l_im = srcl[2 * n + 1], r_im = srcr[2 * n + 1]; float c_phase = atan2f(l_im + r_im, l_re + r_re); @@ -801,6 +802,7 @@ static void filter_2_1(AVFilterContext *ctx) const float *srcl = (const float *)s->input->extended_data[0]; const float *srcr = (const float *)s->input->extended_data[1]; const float *srclfe = (const float *)s->input->extended_data[2]; + const int rdft_size = s->rdft_size; const float angle = s->angle; const float focus = s->focus; float *magtotal = s->mag_total; @@ -813,7 +815,7 @@ static void filter_2_1(AVFilterContext *ctx) float *xpos = s->x_pos; float *ypos = s->y_pos; - for (int n = 0; n < s->rdft_size; n++) { + for (int n = 0; n < rdft_size; n++) { float l_re = srcl[2 * n], r_re = srcr[2 * n]; float l_im = srcl[2 * n + 1], r_im = srcr[2 * n + 1]; float lfe_re = srclfe[2 * n], lfe_im = srclfe[2 * n + 1]; @@ -858,6 +860,7 @@ static void filter_surround(AVFilterContext *ctx) const float *srcr = (const float *)s->input->extended_data[1]; const float *srcc = (const float *)s->input->extended_data[2]; const int output_lfe = s->output_lfe && s->create_lfe; + const int rdft_size = s->rdft_size; const int lfe_mode = s->lfe_mode; const float highcut = s->highcut; const float lowcut = s->lowcut; @@ -872,7 +875,7 @@ static void filter_surround(AVFilterContext *ctx) float *xpos = s->x_pos; float *ypos = s->y_pos; - for (int n = 0; n < s->rdft_size; n++) { + for (int n = 0; n < rdft_size; n++) { float l_re = srcl[2 * n], r_re = srcr[2 * n]; float l_im = srcl[2 * n + 1], r_im = srcr[2 * n + 1]; float c_re = srcc[2 * n], c_im = srcc[2 * n + 1]; @@ -910,6 +913,7 @@ static void filter_surround(AVFilterContext *ctx) static void filter_5_0_side(AVFilterContext *ctx) { AudioSurroundContext *s = ctx->priv; + const int rdft_size = s->rdft_size; float *srcl, *srcr, *srcc, *srcsl, *srcsr; int n; @@ -919,7 +923,7 @@ static void filter_5_0_side(AVFilterContext *ctx) srcsl = (float *)s->input->extended_data[3]; srcsr = (float *)s->input->extended_data[4]; - for (n = 0; n < s->rdft_size; n++) { + for (n = 0; n < rdft_size; n++) { float fl_re = srcl[2 * n], fr_re = srcr[2 * n]; float fl_im = srcl[2 * n + 1], fr_im = srcr[2 * n + 1]; float c_re = srcc[2 * n], c_im = srcc[2 * n + 1]; @@ -967,6 +971,7 @@ static void filter_5_0_side(AVFilterContext *ctx) static void filter_5_1_side(AVFilterContext *ctx) { AudioSurroundContext *s = ctx->priv; + const int rdft_size = s->rdft_size; float *srcl, *srcr, *srcc, *srclfe, *srcsl, *srcsr; int n; @@ -977,7 +982,7 @@ static void filter_5_1_side(AVFilterContext *ctx) srcsl = (float *)s->input->extended_data[4]; srcsr = (float *)s->input->extended_data[5]; - for (n = 0; n < s->rdft_size; n++) { + for (n = 0; n < rdft_size; n++) { float fl_re = srcl[2 * n], fr_re = srcr[2 * n]; float fl_im = srcl[2 * n + 1], fr_im = srcr[2 * n + 1]; float c_re = srcc[2 * n], c_im = srcc[2 * n + 1]; @@ -1026,6 +1031,7 @@ static void filter_5_1_side(AVFilterContext *ctx) static void filter_5_1_back(AVFilterContext *ctx) { AudioSurroundContext *s = ctx->priv; + const int rdft_size = s->rdft_size; float *srcl, *srcr, *srcc, *srclfe, *srcbl, *srcbr; int n; @@ -1036,7 +1042,7 @@ static void filter_5_1_back(AVFilterContext *ctx) srcbl = (float *)s->input->extended_data[4]; srcbr = (float *)s->input->extended_data[5]; - for (n = 0; n < s->rdft_size; n++) { + for (n = 0; n < rdft_size; n++) { float fl_re = srcl[2 * n], fr_re = srcr[2 * n]; float fl_im = srcl[2 * n + 1], fr_im = srcr[2 * n + 1]; float c_re = srcc[2 * n], c_im = srcc[2 * n + 1]; From cb4e7831e704fcb3c3eba4e7c4b3b94c81aa04e2 Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Fri, 12 May 2023 12:06:23 +0200 Subject: [PATCH 0971/2172] avfilter/af_surround: scale output gain for non-default overlap --- libavfilter/af_surround.c | 22 ++++++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) diff --git a/libavfilter/af_surround.c b/libavfilter/af_surround.c index 682c1f5dcb7..0b88ac418bd 100644 --- a/libavfilter/af_surround.c +++ b/libavfilter/af_surround.c @@ -74,6 +74,7 @@ typedef struct AudioSurroundContext { float focus; int win_size; int win_func; + float win_gain; float overlap; float all_x; @@ -637,7 +638,7 @@ static void upmix_7_1_5_0_side(AVFilterContext *ctx, { float fl_mag, fr_mag, ls_mag, rs_mag, lb_mag, rb_mag; float *dstc, *dstl, *dstr, *dstls, *dstrs, *dstlb, *dstrb, *dstlfe; - float lfe_mag, c_phase, mag_total = (mag_totall + mag_totalr) * 0.5; + float lfe_mag, c_phase, mag_total = (mag_totall + mag_totalr) * 0.5f; AudioSurroundContext *s = ctx->priv; dstl = (float *)s->output->extended_data[0]; @@ -1197,6 +1198,23 @@ static av_cold int init(AVFilterContext *ctx) s->window_func_lut[i] = sqrtf(s->window_func_lut[i] / s->win_size); s->hop_size = FFMAX(1, s->win_size * (1. - s->overlap)); + { + float max = 0.f, *temp_lut = av_calloc(s->win_size, sizeof(*temp_lut)); + if (!temp_lut) + return AVERROR(ENOMEM); + + for (int j = 0; j < s->win_size; j += s->hop_size) { + for (int i = 0; i < s->win_size; i++) + temp_lut[(i + j) % s->win_size] += s->window_func_lut[i]; + } + + for (int i = 0; i < s->win_size; i++) + max = fmaxf(temp_lut[i], max); + av_freep(&temp_lut); + + s->win_gain = 1.f / (max * sqrtf(s->win_size)); + } + allchannels_spread(ctx); return 0; @@ -1237,7 +1255,7 @@ static int fft_channels(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) static int ifft_channel(AVFilterContext *ctx, AVFrame *out, int ch) { AudioSurroundContext *s = ctx->priv; - const float level_out = s->output_levels[ch]; + const float level_out = s->output_levels[ch] * s->win_gain; float *dst, *ptr; dst = (float *)s->output_out->extended_data[ch]; From 86ee0317951d6793b83fce03942ee26177663cec Mon Sep 17 00:00:00 2001 From: Andriy Utkin Date: Thu, 11 May 2023 16:52:19 +0100 Subject: [PATCH 0972/2172] doc/muxers/image2: drop unmatched quote in example Percent sign is not a special character in popular shells, so the quoting isn't necessary. --- doc/muxers.texi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/muxers.texi b/doc/muxers.texi index d1e825eec59..31fca17dd62 100644 --- a/doc/muxers.texi +++ b/doc/muxers.texi @@ -1468,7 +1468,7 @@ ffmpeg -f v4l2 -r 1 -i /dev/video0 -f image2 -strftime 1 "%Y-%m-%d_%H-%M-%S.jpg" You can set the file name with current frame's PTS: @example -ffmpeg -f v4l2 -r 1 -i /dev/video0 -copyts -f image2 -frame_pts true %d.jpg" +ffmpeg -f v4l2 -r 1 -i /dev/video0 -copyts -f image2 -frame_pts true %d.jpg @end example A more complex example is to publish contents of your desktop directly to a From 7f890b2fbb75fa38e7b197cdd509afc7c391f998 Mon Sep 17 00:00:00 2001 From: James Almer Date: Thu, 11 May 2023 14:34:57 -0300 Subject: [PATCH 0973/2172] avfilter/ccfifo: remove unnecessary context allocations This is not public API, no it has no need for an alloc() and free() functions. The struct can reside on stack. Signed-off-by: James Almer --- libavdevice/decklink_common.h | 2 +- libavdevice/decklink_enc.cpp | 14 +++++----- libavfilter/ccfifo.c | 49 +++++++++++------------------------ libavfilter/ccfifo.h | 42 ++++++++++++++++++------------ libavfilter/tinterlace.h | 2 +- libavfilter/vf_bwdif.c | 8 +++--- libavfilter/vf_ccrepack.c | 13 +++++----- libavfilter/vf_fps.c | 13 +++++----- libavfilter/vf_tinterlace.c | 18 ++++++------- libavfilter/vf_yadif.c | 8 +++--- libavfilter/vf_yadif_cuda.c | 6 ++--- libavfilter/yadif.h | 2 +- libavfilter/yadif_common.c | 6 ++--- 13 files changed, 89 insertions(+), 94 deletions(-) diff --git a/libavdevice/decklink_common.h b/libavdevice/decklink_common.h index 1cc6d9c2cc2..ebb5b94bed1 100644 --- a/libavdevice/decklink_common.h +++ b/libavdevice/decklink_common.h @@ -113,7 +113,7 @@ struct decklink_ctx { /* Capture buffer queue */ DecklinkPacketQueue queue; - AVCCFifo *cc_fifo; ///< closed captions + CCFifo cc_fifo; ///< closed captions /* Streams present */ int audio; diff --git a/libavdevice/decklink_enc.cpp b/libavdevice/decklink_enc.cpp index 22aa80b8c22..6906cb0882c 100644 --- a/libavdevice/decklink_enc.cpp +++ b/libavdevice/decklink_enc.cpp @@ -371,7 +371,7 @@ av_cold int ff_decklink_write_trailer(AVFormatContext *avctx) klvanc_context_destroy(ctx->vanc_ctx); #endif - ff_ccfifo_freep(&ctx->cc_fifo); + ff_ccfifo_uninit(&ctx->cc_fifo); av_freep(&cctx->ctx); return 0; @@ -527,15 +527,15 @@ static void construct_afd(AVFormatContext *avctx, struct decklink_ctx *ctx, that will later be handled by construct_cc... */ static void parse_608subs(AVFormatContext *avctx, struct decklink_ctx *ctx, AVPacket *pkt) { - size_t cc_size = ff_ccfifo_getoutputsize(ctx->cc_fifo); + size_t cc_size = ff_ccfifo_getoutputsize(&ctx->cc_fifo); uint8_t *cc_data; - if (!ff_ccfifo_ccdetected(ctx->cc_fifo)) + if (!ff_ccfifo_ccdetected(&ctx->cc_fifo)) return; cc_data = av_packet_new_side_data(pkt, AV_PKT_DATA_A53_CC, cc_size); if (cc_data) - ff_ccfifo_injectbytes(ctx->cc_fifo, cc_data, cc_size); + ff_ccfifo_injectbytes(&ctx->cc_fifo, cc_data, cc_size); } static int decklink_construct_vanc(AVFormatContext *avctx, struct decklink_ctx *ctx, @@ -745,7 +745,7 @@ static int decklink_write_subtitle_packet(AVFormatContext *avctx, AVPacket *pkt) struct decklink_cctx *cctx = (struct decklink_cctx *)avctx->priv_data; struct decklink_ctx *ctx = (struct decklink_ctx *)cctx->ctx; - ff_ccfifo_extractbytes(ctx->cc_fifo, pkt->data, pkt->size); + ff_ccfifo_extractbytes(&ctx->cc_fifo, pkt->data, pkt->size); return 0; } @@ -831,9 +831,9 @@ av_cold int ff_decklink_write_header(AVFormatContext *avctx) avpriv_set_pts_info(st, 64, ctx->bmd_tb_num, ctx->bmd_tb_den); } - if (!(ctx->cc_fifo = ff_ccfifo_alloc(av_make_q(ctx->bmd_tb_den, ctx->bmd_tb_num), avctx))) { + ret = ff_ccfifo_init(&ctx->cc_fifo, av_make_q(ctx->bmd_tb_den, ctx->bmd_tb_num), avctx); + if (ret < 0) { av_log(ctx, AV_LOG_ERROR, "Failure to setup CC FIFO queue\n"); - ret = AVERROR(ENOMEM); goto error; } diff --git a/libavfilter/ccfifo.c b/libavfilter/ccfifo.c index 5fb68ce04c7..f39dbc1740c 100644 --- a/libavfilter/ccfifo.c +++ b/libavfilter/ccfifo.c @@ -23,18 +23,6 @@ #include "ccfifo.h" -struct AVCCFifo { - AVFifo *cc_608_fifo; - AVFifo *cc_708_fifo; - AVRational framerate; - int expected_cc_count; - int expected_608; - int cc_detected; - int passthrough; - int passthrough_warning; - void *log_ctx; -}; - #define MAX_CC_ELEMENTS 128 #define CC_BYTES_PER_ENTRY 3 @@ -55,25 +43,18 @@ const static struct cc_lookup cc_lookup_vals[] = { { 60000, 1001, 10, 1}, }; -void ff_ccfifo_freep(AVCCFifo **ccf) +void ff_ccfifo_uninit(CCFifo *ccf) { - AVCCFifo *tmp = *ccf; - if (tmp) { - av_fifo_freep2(&tmp->cc_608_fifo); - av_fifo_freep2(&tmp->cc_708_fifo); - } - av_freep(ccf); + av_fifo_freep2(&ccf->cc_608_fifo); + av_fifo_freep2(&ccf->cc_708_fifo); + memset(ccf, 0, sizeof(*ccf)); } -AVCCFifo *ff_ccfifo_alloc(AVRational framerate, void *log_ctx) +int ff_ccfifo_init(CCFifo *ccf, AVRational framerate, void *log_ctx) { - AVCCFifo *ccf; int i; - ccf = av_mallocz(sizeof(*ccf)); - if (!ccf) - return NULL; - + memset(ccf, 0, sizeof(*ccf)); ccf->log_ctx = log_ctx; ccf->framerate = framerate; @@ -101,24 +82,24 @@ AVCCFifo *ff_ccfifo_alloc(AVRational framerate, void *log_ctx) ccf->passthrough = 1; } - return ccf; + return 0; error: - ff_ccfifo_freep(&ccf); - return NULL; + ff_ccfifo_uninit(ccf); + return AVERROR(ENOMEM); } -int ff_ccfifo_getoutputsize(AVCCFifo *ccf) +int ff_ccfifo_getoutputsize(CCFifo *ccf) { return ccf->expected_cc_count * CC_BYTES_PER_ENTRY; } -int ff_ccfifo_ccdetected(AVCCFifo *ccf) +int ff_ccfifo_ccdetected(CCFifo *ccf) { return ccf->cc_detected; } -int ff_ccfifo_injectbytes(AVCCFifo *ccf, uint8_t *cc_data, size_t len) +int ff_ccfifo_injectbytes(CCFifo *ccf, uint8_t *cc_data, size_t len) { int cc_608_tuples = 0; int cc_708_tuples = 0; @@ -159,7 +140,7 @@ int ff_ccfifo_injectbytes(AVCCFifo *ccf, uint8_t *cc_data, size_t len) return 0; } -int ff_ccfifo_inject(AVCCFifo *ccf, AVFrame *frame) +int ff_ccfifo_inject(CCFifo *ccf, AVFrame *frame) { AVFrameSideData *sd; int ret; @@ -180,7 +161,7 @@ int ff_ccfifo_inject(AVCCFifo *ccf, AVFrame *frame) return 0; } -int ff_ccfifo_extractbytes(AVCCFifo *ccf, uint8_t *cc_bytes, size_t len) +int ff_ccfifo_extractbytes(CCFifo *ccf, uint8_t *cc_bytes, size_t len) { int cc_count = len / CC_BYTES_PER_ENTRY; @@ -209,7 +190,7 @@ int ff_ccfifo_extractbytes(AVCCFifo *ccf, uint8_t *cc_bytes, size_t len) /* Read the A53 side data, discard padding, and put 608/708 into queues so we can ensure they get into the output frames at the correct rate... */ -int ff_ccfifo_extract(AVCCFifo *ccf, AVFrame *frame) +int ff_ccfifo_extract(CCFifo *ccf, AVFrame *frame) { AVFrameSideData *side_data = av_frame_get_side_data(frame, AV_FRAME_DATA_A53_CC); if (side_data) { diff --git a/libavfilter/ccfifo.h b/libavfilter/ccfifo.h index 44c924593c1..a380f67b524 100644 --- a/libavfilter/ccfifo.h +++ b/libavfilter/ccfifo.h @@ -33,25 +33,33 @@ #include "libavutil/frame.h" #include "libavutil/fifo.h" -typedef struct AVCCFifo AVCCFifo; +typedef struct CCFifo { + AVFifo *cc_608_fifo; + AVFifo *cc_708_fifo; + AVRational framerate; + int expected_cc_count; + int expected_608; + int cc_detected; + int passthrough; + int passthrough_warning; + void *log_ctx; +} CCFifo; /** - * Allocate an AVCCFifo. + * Initialize a CCFifo. * * @param framerate output framerate * @param log_ctx used for any av_log() calls - * @return newly allocated AVCCFifo, or NULL on error + * @return Zero on success, or negative AVERROR code on failure. */ -AVCCFifo *ff_ccfifo_alloc(AVRational framerate, void *log_ctx); +int ff_ccfifo_init(CCFifo *ccf, AVRational framerate, void *log_ctx); /** - * Free an AVCCFifo + * Free all memory allocated in a CCFifo and clear the context. * - * @param ccf Pointer to the pointer to the AVCCFifo which should be freed - * @note `*ptr = NULL` is safe and leads to no action. + * @param ccf Pointer to the CCFifo which should be uninitialized */ -void ff_ccfifo_freep(AVCCFifo **ccf); - +void ff_ccfifo_uninit(CCFifo *ccf); /** * Extract CC data from an AVFrame @@ -61,17 +69,17 @@ void ff_ccfifo_freep(AVCCFifo **ccf); * as it will be re-inserted at the appropriate rate later in the * filter. * - * @param af AVCCFifo to write to + * @param af CCFifo to write to * @param frame AVFrame with the video frame to operate on * @return Zero on success, or negative AVERROR * code on failure. */ -int ff_ccfifo_extract(AVCCFifo *ccf, AVFrame *frame); +int ff_ccfifo_extract(CCFifo *ccf, AVFrame *frame); /** *Just like ff_ccfifo_extract(), but takes the raw bytes instead of an AVFrame */ -int ff_ccfifo_extractbytes(AVCCFifo *ccf, uint8_t *data, size_t len); +int ff_ccfifo_extractbytes(CCFifo *ccf, uint8_t *data, size_t len); /** * Provide the size in bytes of an output buffer to allocate @@ -80,7 +88,7 @@ int ff_ccfifo_extractbytes(AVCCFifo *ccf, uint8_t *data, size_t len); * an appropriately sized buffer and pass it to ff_ccfifo_injectbytes() * */ -int ff_ccfifo_getoutputsize(AVCCFifo *ccf); +int ff_ccfifo_getoutputsize(CCFifo *ccf); /** * Insert CC data from the FIFO into an AVFrame (as side data) @@ -88,23 +96,23 @@ int ff_ccfifo_getoutputsize(AVCCFifo *ccf); * Dequeue the appropriate number of CC tuples based on the * frame rate, and insert them into the AVFrame * - * @param af AVCCFifo to read from + * @param af CCFifo to read from * @param frame AVFrame with the video frame to operate on * @return Zero on success, or negative AVERROR * code on failure. */ -int ff_ccfifo_inject(AVCCFifo *ccf, AVFrame *frame); +int ff_ccfifo_inject(CCFifo *ccf, AVFrame *frame); /** * Just like ff_ccfifo_inject(), but takes the raw bytes to insert the CC data * int rather than an AVFrame */ -int ff_ccfifo_injectbytes(AVCCFifo *ccf, uint8_t *data, size_t len); +int ff_ccfifo_injectbytes(CCFifo *ccf, uint8_t *data, size_t len); /** * Returns 1 if captions have been found as a prior call * to ff_ccfifo_extract() or ff_ccfifo_extractbytes() */ -int ff_ccfifo_ccdetected(AVCCFifo *ccf); +int ff_ccfifo_ccdetected(CCFifo *ccf); #endif /* AVFILTER_CCFIFO_H */ diff --git a/libavfilter/tinterlace.h b/libavfilter/tinterlace.h index 9f5ce7e65bf..f9b3e630b8e 100644 --- a/libavfilter/tinterlace.h +++ b/libavfilter/tinterlace.h @@ -78,7 +78,7 @@ typedef struct TInterlaceContext { const AVPixFmtDescriptor *csp; void (*lowpass_line)(uint8_t *dstp, ptrdiff_t width, const uint8_t *srcp, ptrdiff_t mref, ptrdiff_t pref, int clip_max); - AVCCFifo *cc_fifo; + CCFifo cc_fifo; } TInterlaceContext; void ff_tinterlace_init_x86(TInterlaceContext *interlace); diff --git a/libavfilter/vf_bwdif.c b/libavfilter/vf_bwdif.c index 51e1e02503c..e278cf12176 100644 --- a/libavfilter/vf_bwdif.c +++ b/libavfilter/vf_bwdif.c @@ -297,7 +297,7 @@ static av_cold void uninit(AVFilterContext *ctx) av_frame_free(&yadif->prev); av_frame_free(&yadif->cur ); av_frame_free(&yadif->next); - ff_ccfifo_freep(&yadif->cc_fifo); + ff_ccfifo_uninit(&yadif->cc_fifo); } static const enum AVPixelFormat pix_fmts[] = { @@ -326,6 +326,7 @@ static int config_props(AVFilterLink *link) AVFilterContext *ctx = link->src; BWDIFContext *s = link->src->priv; YADIFContext *yadif = &s->yadif; + int ret; link->time_base = av_mul_q(ctx->inputs[0]->time_base, (AVRational){1, 2}); link->w = link->src->inputs[0]->w; @@ -336,9 +337,10 @@ static int config_props(AVFilterLink *link) else link->frame_rate = ctx->inputs[0]->frame_rate; - if (!(yadif->cc_fifo = ff_ccfifo_alloc(link->frame_rate, ctx))) { + ret = ff_ccfifo_init(&yadif->cc_fifo, link->frame_rate, ctx); + if (ret < 0 ) { av_log(ctx, AV_LOG_ERROR, "Failure to setup CC FIFO queue\n"); - return AVERROR(ENOMEM); + return ret; } if (link->w < 3 || link->h < 4) { diff --git a/libavfilter/vf_ccrepack.c b/libavfilter/vf_ccrepack.c index e3fd67f1b5f..61eb2128ae8 100644 --- a/libavfilter/vf_ccrepack.c +++ b/libavfilter/vf_ccrepack.c @@ -37,7 +37,7 @@ typedef struct CCRepackContext { const AVClass *class; - AVCCFifo *cc_fifo; + CCFifo cc_fifo; } CCRepackContext; static const AVOption ccrepack_options[] = { @@ -50,9 +50,10 @@ static int config_input(AVFilterLink *link) { CCRepackContext *ctx = link->dst->priv; - if (!(ctx->cc_fifo = ff_ccfifo_alloc(link->frame_rate, ctx))) { + int ret = ff_ccfifo_init(&ctx->cc_fifo, link->frame_rate, ctx); + if (ret < 0) { av_log(ctx, AV_LOG_ERROR, "Failure to setup CC FIFO queue\n"); - return AVERROR(ENOMEM); + return ret; } return 0; @@ -63,8 +64,8 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *frame) CCRepackContext *ctx = inlink->dst->priv; AVFilterLink *outlink = inlink->dst->outputs[0]; - ff_ccfifo_extract(ctx->cc_fifo, frame); - ff_ccfifo_inject(ctx->cc_fifo, frame); + ff_ccfifo_extract(&ctx->cc_fifo, frame); + ff_ccfifo_inject(&ctx->cc_fifo, frame); return ff_filter_frame(outlink, frame); } @@ -72,7 +73,7 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *frame) static av_cold void uninit(AVFilterContext *ctx) { CCRepackContext *s = ctx->priv; - ff_ccfifo_freep(&s->cc_fifo); + ff_ccfifo_uninit(&s->cc_fifo); } static const AVFilterPad avfilter_vf_ccrepack_inputs[] = { diff --git a/libavfilter/vf_fps.c b/libavfilter/vf_fps.c index 824e7a128df..2bfb6d29e71 100644 --- a/libavfilter/vf_fps.c +++ b/libavfilter/vf_fps.c @@ -86,7 +86,7 @@ typedef struct FPSContext { AVFrame *frames[2]; ///< buffered frames int frames_count; ///< number of buffered frames - AVCCFifo *cc_fifo; ///< closed captions + CCFifo cc_fifo; ///< closed captions int64_t next_pts; ///< pts of the next frame to output @@ -167,7 +167,7 @@ static av_cold void uninit(AVFilterContext *ctx) frame = shift_frame(ctx, s); av_frame_free(&frame); } - ff_ccfifo_freep(&s->cc_fifo); + ff_ccfifo_uninit(&s->cc_fifo); av_log(ctx, AV_LOG_VERBOSE, "%d frames in, %d frames out; %d frames dropped, " "%d frames duplicated.\n", s->frames_in, s->frames_out, s->drop, s->dup); @@ -213,9 +213,10 @@ static int config_props(AVFilterLink* outlink) s->in_pts_off, s->out_pts_off, s->start_time); } - if (!(s->cc_fifo = ff_ccfifo_alloc(outlink->frame_rate, ctx))) { + ret = ff_ccfifo_init(&s->cc_fifo, outlink->frame_rate, ctx); + if (ret < 0) { av_log(ctx, AV_LOG_ERROR, "Failure to setup CC FIFO queue\n"); - return AVERROR(ENOMEM); + return ret; } av_log(ctx, AV_LOG_VERBOSE, "fps=%d/%d\n", outlink->frame_rate.num, outlink->frame_rate.den); @@ -250,7 +251,7 @@ static int read_frame(AVFilterContext *ctx, FPSContext *s, AVFilterLink *inlink, av_log(ctx, AV_LOG_DEBUG, "Read frame with in pts %"PRId64", out pts %"PRId64"\n", in_pts, frame->pts); - ff_ccfifo_extract(s->cc_fifo, frame); + ff_ccfifo_extract(&s->cc_fifo, frame); s->frames[s->frames_count++] = frame; s->frames_in++; @@ -298,7 +299,7 @@ static int write_frame(AVFilterContext *ctx, FPSContext *s, AVFilterLink *outlin if (!frame) return AVERROR(ENOMEM); // Make sure Closed Captions will not be duplicated - ff_ccfifo_inject(s->cc_fifo, frame); + ff_ccfifo_inject(&s->cc_fifo, frame); frame->pts = s->next_pts++; frame->duration = 1; diff --git a/libavfilter/vf_tinterlace.c b/libavfilter/vf_tinterlace.c index e1057ffc8ef..63f1fc72f2a 100644 --- a/libavfilter/vf_tinterlace.c +++ b/libavfilter/vf_tinterlace.c @@ -203,7 +203,7 @@ static av_cold void uninit(AVFilterContext *ctx) av_frame_free(&tinterlace->next); av_freep(&tinterlace->black_data[0][0]); av_freep(&tinterlace->black_data[1][0]); - ff_ccfifo_freep(&tinterlace->cc_fifo); + ff_ccfifo_uninit(&tinterlace->cc_fifo); } static int config_out_props(AVFilterLink *outlink) @@ -212,7 +212,7 @@ static int config_out_props(AVFilterLink *outlink) AVFilterLink *inlink = outlink->src->inputs[0]; const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(outlink->format); TInterlaceContext *tinterlace = ctx->priv; - int i; + int ret, i; tinterlace->vsub = desc->log2_chroma_h; outlink->w = inlink->w; @@ -224,7 +224,6 @@ static int config_out_props(AVFilterLink *outlink) if (tinterlace->mode == MODE_PAD) { uint8_t black[4] = { 0, 0, 0, 16 }; - int ret; ff_draw_init(&tinterlace->draw, outlink->format, 0); ff_draw_color(&tinterlace->draw, &tinterlace->color, black); /* limited range */ @@ -292,9 +291,10 @@ static int config_out_props(AVFilterLink *outlink) #endif } - if (!(tinterlace->cc_fifo = ff_ccfifo_alloc(outlink->frame_rate, ctx))) { + ret = ff_ccfifo_init(&tinterlace->cc_fifo, outlink->frame_rate, ctx); + if (ret < 0) { av_log(ctx, AV_LOG_ERROR, "Failure to setup CC FIFO queue\n"); - return AVERROR(ENOMEM); + return ret; } av_log(ctx, AV_LOG_VERBOSE, "mode:%d filter:%s h:%d -> h:%d\n", tinterlace->mode, @@ -381,7 +381,7 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *picref) tinterlace->cur = tinterlace->next; tinterlace->next = picref; - ff_ccfifo_extract(tinterlace->cc_fifo, picref); + ff_ccfifo_extract(&tinterlace->cc_fifo, picref); cur = tinterlace->cur; next = tinterlace->next; @@ -464,7 +464,7 @@ FF_ENABLE_DEPRECATION_WARNINGS if (!out) return AVERROR(ENOMEM); out->pts /= 2; // adjust pts to new framerate - ff_ccfifo_inject(tinterlace->cc_fifo, out); + ff_ccfifo_inject(&tinterlace->cc_fifo, out); ret = ff_filter_frame(outlink, out); return ret; } @@ -514,7 +514,7 @@ FF_ENABLE_DEPRECATION_WARNINGS out->pts = cur->pts*2; out->pts = av_rescale_q(out->pts, tinterlace->preout_time_base, outlink->time_base); - ff_ccfifo_inject(tinterlace->cc_fifo, out); + ff_ccfifo_inject(&tinterlace->cc_fifo, out); if ((ret = ff_filter_frame(outlink, out)) < 0) return ret; @@ -559,7 +559,7 @@ FF_ENABLE_DEPRECATION_WARNINGS out->pts = av_rescale_q(out->pts, tinterlace->preout_time_base, outlink->time_base); out->duration = av_rescale_q(1, av_inv_q(outlink->frame_rate), outlink->time_base); - ff_ccfifo_inject(tinterlace->cc_fifo, out); + ff_ccfifo_inject(&tinterlace->cc_fifo, out); ret = ff_filter_frame(outlink, out); return ret; diff --git a/libavfilter/vf_yadif.c b/libavfilter/vf_yadif.c index f77f8113cac..d6fe24a3869 100644 --- a/libavfilter/vf_yadif.c +++ b/libavfilter/vf_yadif.c @@ -261,7 +261,7 @@ static av_cold void uninit(AVFilterContext *ctx) av_frame_free(&yadif->prev); av_frame_free(&yadif->cur ); av_frame_free(&yadif->next); - ff_ccfifo_freep(&yadif->cc_fifo); + ff_ccfifo_uninit(&yadif->cc_fifo); } static const enum AVPixelFormat pix_fmts[] = { @@ -286,6 +286,7 @@ static int config_output(AVFilterLink *outlink) { AVFilterContext *ctx = outlink->src; YADIFContext *s = ctx->priv; + int ret; outlink->time_base = av_mul_q(ctx->inputs[0]->time_base, (AVRational){1, 2}); outlink->w = ctx->inputs[0]->w; @@ -297,9 +298,10 @@ static int config_output(AVFilterLink *outlink) else outlink->frame_rate = ctx->inputs[0]->frame_rate; - if (!(s->cc_fifo = ff_ccfifo_alloc(outlink->frame_rate, ctx))) { + ret = ff_ccfifo_init(&s->cc_fifo, outlink->frame_rate, ctx); + if (ret < 0) { av_log(ctx, AV_LOG_ERROR, "Failure to setup CC FIFO queue\n"); - return AVERROR(ENOMEM); + return ret; } if (outlink->w < 3 || outlink->h < 3) { diff --git a/libavfilter/vf_yadif_cuda.c b/libavfilter/vf_yadif_cuda.c index 73f04126c59..b5ff84e11a8 100644 --- a/libavfilter/vf_yadif_cuda.c +++ b/libavfilter/vf_yadif_cuda.c @@ -205,7 +205,7 @@ static av_cold void deint_cuda_uninit(AVFilterContext *ctx) av_frame_free(&y->prev); av_frame_free(&y->cur); av_frame_free(&y->next); - ff_ccfifo_freep(&y->cc_fifo); + ff_ccfifo_uninit(&y->cc_fifo); av_buffer_unref(&s->device_ref); s->hwctx = NULL; @@ -295,9 +295,9 @@ static int config_output(AVFilterLink *link) else link->frame_rate = ctx->inputs[0]->frame_rate; - if (!(y->cc_fifo = ff_ccfifo_alloc(link->frame_rate, ctx))) { + ret = ff_ccfifo_init(&y->cc_fifo, link->frame_rate, ctx); + if (ret < 0) { av_log(ctx, AV_LOG_ERROR, "Failure to setup CC FIFO queue\n"); - ret = AVERROR(ENOMEM); goto exit; } diff --git a/libavfilter/yadif.h b/libavfilter/yadif.h index 10775767e95..fbb99fd46ef 100644 --- a/libavfilter/yadif.h +++ b/libavfilter/yadif.h @@ -77,7 +77,7 @@ typedef struct YADIFContext { int eof; uint8_t *temp_line; int temp_line_size; - AVCCFifo *cc_fifo; + CCFifo cc_fifo; /* * An algorithm that treats first and/or last fields in a sequence diff --git a/libavfilter/yadif_common.c b/libavfilter/yadif_common.c index 49ea7cfce44..05474a5ba93 100644 --- a/libavfilter/yadif_common.c +++ b/libavfilter/yadif_common.c @@ -66,7 +66,7 @@ FF_ENABLE_DEPRECATION_WARNINGS } } - ff_ccfifo_inject(yadif->cc_fifo, yadif->out); + ff_ccfifo_inject(&yadif->cc_fifo, yadif->out); ret = ff_filter_frame(ctx->outputs[0], yadif->out); yadif->frame_pending = (yadif->mode&1) && !is_second; @@ -103,7 +103,7 @@ int ff_yadif_filter_frame(AVFilterLink *link, AVFrame *frame) av_assert0(frame); - ff_ccfifo_extract(yadif->cc_fifo, frame); + ff_ccfifo_extract(&yadif->cc_fifo, frame); if (yadif->frame_pending) return_frame(ctx, 1); @@ -146,7 +146,7 @@ int ff_yadif_filter_frame(AVFilterLink *link, AVFrame *frame) if (!yadif->out) return AVERROR(ENOMEM); - ff_ccfifo_inject(yadif->cc_fifo, yadif->out); + ff_ccfifo_inject(&yadif->cc_fifo, yadif->out); av_frame_free(&yadif->prev); if (yadif->out->pts != AV_NOPTS_VALUE) yadif->out->pts *= 2; From e65f03ca1349b3e05ab6b7ab26e3f9a35933ea38 Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Fri, 12 May 2023 17:49:42 +0200 Subject: [PATCH 0974/2172] avfilter/af_loudnorm: simplify query_formats even more --- libavfilter/af_loudnorm.c | 20 +++++++++----------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/libavfilter/af_loudnorm.c b/libavfilter/af_loudnorm.c index 609eae797c8..c99d2f11e63 100644 --- a/libavfilter/af_loudnorm.c +++ b/libavfilter/af_loudnorm.c @@ -730,26 +730,24 @@ static int activate(AVFilterContext *ctx) static int query_formats(AVFilterContext *ctx) { LoudNormContext *s = ctx->priv; - AVFilterFormats *formats = NULL; static const int input_srate[] = {192000, -1}; + static const enum AVSampleFormat sample_fmts[] = { + AV_SAMPLE_FMT_DBL, + AV_SAMPLE_FMT_NONE + }; int ret = ff_set_common_all_channel_counts(ctx); if (ret < 0) return ret; - ret = ff_add_format(&formats, AV_SAMPLE_FMT_DBL); - if (ret) - return ret; - ret = ff_set_common_formats(ctx, formats); - if (ret) + ret = ff_set_common_formats_from_list(ctx, sample_fmts); + if (ret < 0) return ret; - if (s->frame_type != LINEAR_MODE) { - formats = ff_make_format_list(input_srate); + if (s->frame_type == LINEAR_MODE) { + return ff_set_common_all_samplerates(ctx); } else { - formats = ff_all_samplerates(); + return ff_set_common_samplerates_from_list(ctx, input_srate); } - - return ff_set_common_samplerates(ctx, formats); } static int config_input(AVFilterLink *inlink) From 8564b4ab057346cca142b69676116bcb74842161 Mon Sep 17 00:00:00 2001 From: James Almer Date: Fri, 12 May 2023 22:33:16 -0300 Subject: [PATCH 0975/2172] avfilter/ccfifo: constify some parameters Signed-off-by: James Almer --- libavfilter/ccfifo.c | 4 ++-- libavfilter/ccfifo.h | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/libavfilter/ccfifo.c b/libavfilter/ccfifo.c index f39dbc1740c..6ae61a4b15b 100644 --- a/libavfilter/ccfifo.c +++ b/libavfilter/ccfifo.c @@ -89,12 +89,12 @@ int ff_ccfifo_init(CCFifo *ccf, AVRational framerate, void *log_ctx) return AVERROR(ENOMEM); } -int ff_ccfifo_getoutputsize(CCFifo *ccf) +int ff_ccfifo_getoutputsize(const CCFifo *ccf) { return ccf->expected_cc_count * CC_BYTES_PER_ENTRY; } -int ff_ccfifo_ccdetected(CCFifo *ccf) +int ff_ccfifo_ccdetected(const CCFifo *ccf) { return ccf->cc_detected; } diff --git a/libavfilter/ccfifo.h b/libavfilter/ccfifo.h index a380f67b524..a3c302b6b29 100644 --- a/libavfilter/ccfifo.h +++ b/libavfilter/ccfifo.h @@ -88,7 +88,7 @@ int ff_ccfifo_extractbytes(CCFifo *ccf, uint8_t *data, size_t len); * an appropriately sized buffer and pass it to ff_ccfifo_injectbytes() * */ -int ff_ccfifo_getoutputsize(CCFifo *ccf); +int ff_ccfifo_getoutputsize(const CCFifo *ccf); /** * Insert CC data from the FIFO into an AVFrame (as side data) @@ -113,6 +113,6 @@ int ff_ccfifo_injectbytes(CCFifo *ccf, uint8_t *data, size_t len); * Returns 1 if captions have been found as a prior call * to ff_ccfifo_extract() or ff_ccfifo_extractbytes() */ -int ff_ccfifo_ccdetected(CCFifo *ccf); +int ff_ccfifo_ccdetected(const CCFifo *ccf); #endif /* AVFILTER_CCFIFO_H */ From ee6ef66d65730f426d25e7c942b7db4a3cb4bb1a Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Fri, 12 May 2023 21:01:41 +0200 Subject: [PATCH 0976/2172] avfilter/avfiltergraph: fix check for negative return Before this commit if allocation would fail in ff_add_channel_layout() function, function would return negative error code and this would cause wrong format pick up later. If allocation would not fail return code would be 0 and then format negotiation would simply fail as code would break from the loop but with wrong return code. Error was introduced in 6aaac24d72a7da commit. Fixes #6638 --- libavfilter/avfiltergraph.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/libavfilter/avfiltergraph.c b/libavfilter/avfiltergraph.c index 53f468494d3..744f480e1df 100644 --- a/libavfilter/avfiltergraph.c +++ b/libavfilter/avfiltergraph.c @@ -748,8 +748,10 @@ static int reduce_formats_on_filter(AVFilterContext *filter) (KNOWN(fmt) || fmts->all_counts)) { /* Turn the infinite list into a singleton */ fmts->all_layouts = fmts->all_counts = 0; - if (ff_add_channel_layout(&outlink->incfg.channel_layouts, fmt) < 0) - ret = 1; + ret = ff_add_channel_layout(&outlink->incfg.channel_layouts, fmt); + if (ret < 0) + return ret; + ret = 1; break; } From e076d8a9b3893886e7c7abd67cf715db40788a44 Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Sat, 13 May 2023 10:39:41 +0200 Subject: [PATCH 0977/2172] avfilter/af_asetrate: extend query_formats() It left some formats not defined. Causing format negotiation errors with ffplay. Fixes #9248 --- libavfilter/af_asetrate.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/libavfilter/af_asetrate.c b/libavfilter/af_asetrate.c index 76f29144e5e..f1e48b70871 100644 --- a/libavfilter/af_asetrate.c +++ b/libavfilter/af_asetrate.c @@ -49,7 +49,17 @@ AVFILTER_DEFINE_CLASS(asetrate); static av_cold int query_formats(AVFilterContext *ctx) { ASetRateContext *sr = ctx->priv; - int sample_rates[] = { sr->sample_rate, -1 }; + int ret, sample_rates[] = { sr->sample_rate, -1 }; + + if ((ret = ff_set_common_formats(ctx, ff_all_formats(AVMEDIA_TYPE_AUDIO))) < 0) + return ret; + + if ((ret = ff_set_common_all_channel_counts(ctx)) < 0) + return ret; + + if ((ret = ff_formats_ref(ff_all_samplerates(), + &ctx->inputs[0]->outcfg.samplerates)) < 0) + return ret; return ff_formats_ref(ff_make_format_list(sample_rates), &ctx->outputs[0]->incfg.samplerates); From c65e481330c937ba5839a5c0912dadd98f14f47d Mon Sep 17 00:00:00 2001 From: Niklas Haas Date: Thu, 11 May 2023 10:39:02 +0200 Subject: [PATCH 0978/2172] lavfi/vf_libplacebo: allow operation without avhwdevice Recent versions of libplacebo have required Vulkan versions incompatible with lavu Vulkan hwcontexts. While this is expected to change eventually, breaking vf_libplacebo every time there is such a transition period is obviously undesired behavior, as the following sea of bug reports shows. This commit adds a fallback path for init_vulkan failures which simply creates an internal device if there was no user-supplied Vulkan hwaccel. Useful when no interop with lavu vulkan hwframes is needed or desired, and makes using this filter easier inside certain applications. Fixes: https://github.com/haasn/libplacebo/issues/170 Fixes: https://github.com/mpv-player/mpv/issues/9589#issuecomment-1535432185 Fixes: https://github.com/mpv-player/mpv/issues/11363 Fixes: https://github.com/mpv-player/mpv/issues/11685#issuecomment-1546627082 Closes: https://code.videolan.org/videolan/libplacebo/-/issues/270 --- libavfilter/vf_libplacebo.c | 87 +++++++++++++++++++------------------ 1 file changed, 45 insertions(+), 42 deletions(-) diff --git a/libavfilter/vf_libplacebo.c b/libavfilter/vf_libplacebo.c index 6fe3e0ea882..8387f4dd47f 100644 --- a/libavfilter/vf_libplacebo.c +++ b/libavfilter/vf_libplacebo.c @@ -351,56 +351,47 @@ static int libplacebo_init(AVFilterContext *avctx) return err; } -static int init_vulkan(AVFilterContext *avctx) +static int init_vulkan(AVFilterContext *avctx, const AVVulkanDeviceContext *hwctx) { int err = 0; LibplaceboContext *s = avctx->priv; - const AVHWDeviceContext *avhwctx; - const AVVulkanDeviceContext *hwctx; uint8_t *buf = NULL; size_t buf_len; - if (!avctx->hw_device_ctx) { - av_log(s, AV_LOG_ERROR, "Missing vulkan hwdevice for vf_libplacebo.\n"); - return AVERROR(EINVAL); - } - - avhwctx = (AVHWDeviceContext *) avctx->hw_device_ctx->data; - if (avhwctx->type != AV_HWDEVICE_TYPE_VULKAN) { - av_log(s, AV_LOG_ERROR, "Expected vulkan hwdevice for vf_libplacebo, got %s.\n", - av_hwdevice_get_type_name(avhwctx->type)); - return AVERROR(EINVAL); + if (hwctx) { + /* 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, + )); + } else { + s->vulkan = pl_vulkan_create(s->log, pl_vulkan_params( + .queue_count = 0, /* enable all queues for parallelization */ + )); } - hwctx = avhwctx->hwctx; - - /* 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"); + av_log(s, AV_LOG_ERROR, "Failed %s Vulkan device!\n", + hwctx ? "importing" : "creating"); err = AVERROR_EXTERNAL; goto fail; } @@ -695,10 +686,17 @@ static int libplacebo_query_format(AVFilterContext *ctx) { int err; LibplaceboContext *s = ctx->priv; + const AVVulkanDeviceContext *vkhwctx = NULL; const AVPixFmtDescriptor *desc = NULL; AVFilterFormats *infmts = NULL, *outfmts = NULL; - RET(init_vulkan(ctx)); + if (ctx->hw_device_ctx) { + const AVHWDeviceContext *avhwctx = (void *) ctx->hw_device_ctx->data; + if (avhwctx->type == AV_HWDEVICE_TYPE_VULKAN) + vkhwctx = avhwctx->hwctx; + } + + RET(init_vulkan(ctx, vkhwctx)); while ((desc = av_pix_fmt_desc_next(desc))) { enum AVPixelFormat pixfmt = av_pix_fmt_desc_get_id(desc); @@ -710,6 +708,11 @@ static int libplacebo_query_format(AVFilterContext *ctx) continue; #endif + if (pixfmt == AV_PIX_FMT_VULKAN) { + if (!vkhwctx || vkhwctx->act_dev != s->vulkan->device) + continue; + } + if (!pl_test_pixfmt(s->gpu, pixfmt)) continue; From b446ea22e9b6d46c148bd527582a3cac4ba1ce81 Mon Sep 17 00:00:00 2001 From: James Almer Date: Sat, 13 May 2023 11:07:08 -0300 Subject: [PATCH 0979/2172] avfilter/formats: fix format negotiation when multiple channel_layouts are provided For example ffmpeg -f lavfi -i sine -af "aformat=cl=stereo|5.1|7.1,lowpass,aformat=cl=7.1|5.1|stereo" -f null - Reviewed-by: Paul B Mahol Signed-off-by: James Almer --- libavfilter/avfiltergraph.c | 2 +- libavfilter/formats.c | 39 ++++++++++++++++++++++++++++--------- 2 files changed, 31 insertions(+), 10 deletions(-) diff --git a/libavfilter/avfiltergraph.c b/libavfilter/avfiltergraph.c index 744f480e1df..a200ab856c9 100644 --- a/libavfilter/avfiltergraph.c +++ b/libavfilter/avfiltergraph.c @@ -441,7 +441,7 @@ static int query_formats(AVFilterGraph *graph, void *log_ctx) neg = ff_filter_get_negotiation(link); av_assert0(neg); - for (neg_step = 1; neg_step < neg->nb_mergers; neg_step++) { + for (neg_step = 0; neg_step < neg->nb_mergers; neg_step++) { const AVFilterFormatsMerger *m = &neg->mergers[neg_step]; void *a = FF_FIELD_AT(void *, m->offset, link->incfg); void *b = FF_FIELD_AT(void *, m->offset, link->outcfg); diff --git a/libavfilter/formats.c b/libavfilter/formats.c index e8c2888c0c0..d1c97daf642 100644 --- a/libavfilter/formats.c +++ b/libavfilter/formats.c @@ -209,11 +209,10 @@ static int merge_samplerates(void *a, void *b) /** * See merge_pix_fmts(). */ -static int merge_channel_layouts(void *va, void *vb) +static int merge_channel_layouts_internal(AVFilterChannelLayouts *a, + AVFilterChannelLayouts *b, int check) { - AVFilterChannelLayouts *a = va; - AVFilterChannelLayouts *b = vb; - AVChannelLayout *channel_layouts; + AVChannelLayout *channel_layouts = NULL; unsigned a_all = a->all_layouts + a->all_counts; unsigned b_all = b->all_layouts + b->all_counts; int ret_max, ret_nb = 0, i, j, round; @@ -231,8 +230,11 @@ static int merge_channel_layouts(void *va, void *vb) if (a_all == 1 && !b_all) { /* keep only known layouts in b; works also for b_all = 1 */ for (i = j = 0; i < b->nb_channel_layouts; i++) - if (KNOWN(&b->channel_layouts[i]) && i != j++) + if (KNOWN(&b->channel_layouts[i]) && i != j++) { + if (check) + return 1; av_channel_layout_copy(&b->channel_layouts[j], &b->channel_layouts[i]); + } /* Not optimal: the unknown layouts of b may become known after another merge. */ if (!j) @@ -244,7 +246,7 @@ static int merge_channel_layouts(void *va, void *vb) } ret_max = a->nb_channel_layouts + b->nb_channel_layouts; - if (!(channel_layouts = av_calloc(ret_max, sizeof(*channel_layouts)))) + if (!check && !(channel_layouts = av_calloc(ret_max, sizeof(*channel_layouts)))) return AVERROR(ENOMEM); /* a[known] intersect b[known] */ @@ -253,6 +255,8 @@ static int merge_channel_layouts(void *va, void *vb) continue; for (j = 0; j < b->nb_channel_layouts; j++) { if (!av_channel_layout_compare(&a->channel_layouts[i], &b->channel_layouts[j])) { + if (check) + return 1; av_channel_layout_copy(&channel_layouts[ret_nb++], &a->channel_layouts[i]); av_channel_layout_uninit(&a->channel_layouts[i]); av_channel_layout_uninit(&b->channel_layouts[j]); @@ -269,8 +273,11 @@ static int merge_channel_layouts(void *va, void *vb) continue; bfmt = FF_COUNT2LAYOUT(fmt->nb_channels); for (j = 0; j < b->nb_channel_layouts; j++) - if (!av_channel_layout_compare(&b->channel_layouts[j], &bfmt)) + if (!av_channel_layout_compare(&b->channel_layouts[j], &bfmt)) { + if (check) + return 1; av_channel_layout_copy(&channel_layouts[ret_nb++], fmt); + } } /* 1st round: swap to prepare 2nd round; 2nd round: put it back */ FFSWAP(AVFilterChannelLayouts *, a, b); @@ -280,8 +287,11 @@ static int merge_channel_layouts(void *va, void *vb) if (KNOWN(&a->channel_layouts[i])) continue; for (j = 0; j < b->nb_channel_layouts; j++) - if (!av_channel_layout_compare(&a->channel_layouts[i], &b->channel_layouts[j])) + if (!av_channel_layout_compare(&a->channel_layouts[i], &b->channel_layouts[j])) { + if (check) + return 1; av_channel_layout_copy(&channel_layouts[ret_nb++], &a->channel_layouts[i]); + } } if (!ret_nb) { @@ -300,6 +310,17 @@ static int merge_channel_layouts(void *va, void *vb) return 1; } +static int can_merge_channel_layouts(const void *a, const void *b) +{ + return merge_channel_layouts_internal((AVFilterChannelLayouts *)a, + (AVFilterChannelLayouts *)b, 1); +} + +static int merge_channel_layouts(void *a, void *b) +{ + return merge_channel_layouts_internal(a, b, 0); +} + static const AVFilterFormatsMerger mergers_video[] = { { .offset = offsetof(AVFilterFormatsConfig, formats), @@ -312,7 +333,7 @@ static const AVFilterFormatsMerger mergers_audio[] = { { .offset = offsetof(AVFilterFormatsConfig, channel_layouts), .merge = merge_channel_layouts, - .can_merge = NULL, + .can_merge = can_merge_channel_layouts, }, { .offset = offsetof(AVFilterFormatsConfig, samplerates), From fb8efa97935ebe111b644696bccad64bef7437d7 Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Sat, 13 May 2023 20:04:45 +0200 Subject: [PATCH 0980/2172] avfilter/avfiltergraph: remove no longer valid comment --- libavfilter/avfiltergraph.c | 1 - 1 file changed, 1 deletion(-) diff --git a/libavfilter/avfiltergraph.c b/libavfilter/avfiltergraph.c index a200ab856c9..68daa93e614 100644 --- a/libavfilter/avfiltergraph.c +++ b/libavfilter/avfiltergraph.c @@ -1303,7 +1303,6 @@ int avfilter_graph_request_oldest(AVFilterGraph *graph) while (graph->sink_links_count) { oldest = graph->sink_links[0]; if (oldest->dst->filter->activate) { - /* For now, buffersink is the only filter implementing activate. */ r = av_buffersink_get_frame_flags(oldest->dst, NULL, AV_BUFFERSINK_FLAG_PEEK); if (r != AVERROR_EOF) From 28a73506df9c6bcfc6f1ba5b750709f15e4c5ea0 Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Sun, 14 May 2023 00:10:57 +0200 Subject: [PATCH 0981/2172] avfilter/vf_waveform: add input option For finer control of selected formats for filtering. --- doc/filters.texi | 6 ++++++ libavfilter/vf_waveform.c | 6 +++++- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/doc/filters.texi b/doc/filters.texi index 7e0c87d0fa6..c3cf8b470bc 100644 --- a/doc/filters.texi +++ b/doc/filters.texi @@ -24950,6 +24950,12 @@ Set sample aspect ration to 1/1. Set sample aspect ratio to match input size of video @end table Default is @samp{none}. + +@item input +Set input formats for filter to pick from. +Can be @samp{all}, for selecting from all available formats, +or @samp{first}, for selecting first available format. +Default is @samp{first}. @end table @section weave, doubleweave diff --git a/libavfilter/vf_waveform.c b/libavfilter/vf_waveform.c index 8872c43aeb3..a6a8ec78e74 100644 --- a/libavfilter/vf_waveform.c +++ b/libavfilter/vf_waveform.c @@ -120,6 +120,7 @@ typedef struct WaveformContext { float ftint[2]; int tint[2]; int fitmode; + int input; int (*waveform_slice)(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs); @@ -196,6 +197,9 @@ static const AVOption waveform_options[] = { { "fm", "set fit mode", OFFSET(fitmode), AV_OPT_TYPE_INT, {.i64=0}, 0, NB_FITMODES-1, FLAGS, "fitmode" }, { "none", NULL, 0, AV_OPT_TYPE_CONST, {.i64=FM_NONE}, 0, 0, FLAGS, "fitmode" }, { "size", NULL, 0, AV_OPT_TYPE_CONST, {.i64=FM_SIZE}, 0, 0, FLAGS, "fitmode" }, + { "input", "set input formats selection", OFFSET(input), AV_OPT_TYPE_INT, {.i64=1}, 0, 1, FLAGS, "input" }, + { "all", "try to select from all available formats", 0, AV_OPT_TYPE_CONST, {.i64=0}, 0, 0, FLAGS, "input" }, + { "first", "pick first available format", 0, AV_OPT_TYPE_CONST, {.i64=1}, 0, 0, FLAGS, "input" }, { NULL } }; @@ -356,7 +360,7 @@ static int query_formats(AVFilterContext *ctx) depth2 = desc2->comp[0].depth; if (ncomp != ncomp2 || depth != depth2) return AVERROR(EAGAIN); - for (i = 1; i < avff->nb_formats; i++) { + for (i = 1; i < avff->nb_formats && !s->input; i++) { desc = av_pix_fmt_desc_get(avff->formats[i]); if (rgb != (desc->flags & AV_PIX_FMT_FLAG_RGB) || depth != desc->comp[0].depth) From 6f1368842d6d2608be32796f36b104d6ef674f15 Mon Sep 17 00:00:00 2001 From: Stefano Sabatini Date: Wed, 5 Apr 2023 01:10:37 +0200 Subject: [PATCH 0982/2172] tools/normalize: port to python3, extend syntax Also add documentation and logging. --- tools/normalize.py | 106 +++++++++++++++++++++++++++++++-------------- 1 file changed, 73 insertions(+), 33 deletions(-) diff --git a/tools/normalize.py b/tools/normalize.py index 7d87c5e154a..b36ff74ad04 100755 --- a/tools/normalize.py +++ b/tools/normalize.py @@ -1,33 +1,73 @@ -#!/usr/bin/env python2 - -import sys, subprocess - -if len(sys.argv) > 2: - ifile = sys.argv[1] - encopt = sys.argv[2:-1] - ofile = sys.argv[-1] -else: - print 'usage: %s [encode_options] ' % sys.argv[0] - sys.exit(1) - -analysis_cmd = 'ffprobe -v error -of compact=p=0:nk=1 ' -analysis_cmd += '-show_entries frame_tags=lavfi.r128.I -f lavfi ' -analysis_cmd += "amovie='%s',ebur128=metadata=1" % ifile -try: - probe_out = subprocess.check_output(analysis_cmd, shell=True) -except subprocess.CalledProcessError, e: - sys.exit(e.returncode) -loudness = ref = -23 -for line in probe_out.splitlines(): - sline = line.rstrip() - if sline: - loudness = sline -adjust = ref - float(loudness) -if abs(adjust) < 0.0001: - print 'No normalization needed for ' + ifile -else: - print "Adjust %s by %.1fdB" % (ifile, adjust) - norm_cmd = ['ffmpeg', '-i', ifile, '-af', 'volume=%fdB' % adjust] - norm_cmd += encopt + [ofile] - print ' => %s' % ' '.join(norm_cmd) - subprocess.call(norm_cmd) +#!/usr/bin/env python3 + +import argparse +import logging +import shlex +import subprocess + +HELP = ''' +Normalize audio input. + +The command uses ffprobe to analyze an input file with the ebur128 +filter, and finally run ffmpeg to normalize the input depending on the +computed adjustment. + +ffmpeg encoding arguments can be passed through the extra arguments +after options, for example as in: +normalize.py --input input.mp3 --output output.mp3 -- -loglevel debug -y +''' + +logging.basicConfig(format='normalize|%(levelname)s> %(message)s', level=logging.INFO) +log = logging.getLogger() + + +class Formatter( + argparse.ArgumentDefaultsHelpFormatter, argparse.RawDescriptionHelpFormatter +): + pass + + +def normalize(): + parser = argparse.ArgumentParser(description=HELP, formatter_class=Formatter) + parser.add_argument('--input', '-i', required=True, help='specify input file') + parser.add_argument('--output', '-o', required=True, help='specify output file') + parser.add_argument('--dry-run', '-n', help='simulate commands', action='store_true') + parser.add_argument('encode_arguments', nargs='*', help='specify encode options used for the actual encoding') + + args = parser.parse_args() + + analysis_cmd = [ + 'ffprobe', '-v', 'error', '-of', 'compact=p=0:nk=1', + '-show_entries', 'frame_tags=lavfi.r128.I', '-f', 'lavfi', + f"amovie='{args.input}',ebur128=metadata=1" + ] + + def _run_command(cmd, dry_run=False): + log.info(f"Running command:\n$ {shlex.join(cmd)}") + if not dry_run: + result = subprocess.run(cmd, check=True, stdout=subprocess.PIPE) + return result + + result = _run_command(analysis_cmd) + + loudness = ref = -23 + for line in result.stdout.splitlines(): + sline = line.rstrip() + if sline: + loudness = sline + + adjust = ref - float(loudness) + if abs(adjust) < 0.0001: + logging.info(f"No normalization needed for '{args.input}'") + return + + logging.info(f"Adjusting '{args.input}' by {adjust:.2f}dB...") + normalize_cmd = [ + 'ffmpeg', '-i', args.input, '-af', f'volume={adjust:.2f}dB' + ] + args.encode_arguments + [args.output] + + _run_command(normalize_cmd, args.dry_run) + + +if __name__ == '__main__': + normalize() From e700d87b200fe618d99dcefa9b7e041ac7f5a931 Mon Sep 17 00:00:00 2001 From: Oleg Date: Sat, 29 Apr 2023 19:56:46 +0100 Subject: [PATCH 0983/2172] avfilter/setpts: add command support Add support for changing expr on the fly. Signed-off-by: Oleg --- Changelog | 1 + doc/filters.texi | 7 +++++ libavfilter/setpts.c | 73 +++++++++++++++++++++++++++++++++----------- 3 files changed, 64 insertions(+), 17 deletions(-) diff --git a/Changelog b/Changelog index b7ffeeff0dd..55291074ec1 100644 --- a/Changelog +++ b/Changelog @@ -9,6 +9,7 @@ version : - arls filter - ffmpeg CLI new option: -readrate_initial_burst - zoneplate video source filter +- command support in the setpts and asetpts filters version 6.0: - Radiance HDR image support diff --git a/doc/filters.texi b/doc/filters.texi index c3cf8b470bc..ef48a4cf312 100644 --- a/doc/filters.texi +++ b/doc/filters.texi @@ -29644,6 +29644,9 @@ The wallclock (RTC) time at the start of the movie in microseconds. @item TB The timebase of the input timestamps. +@item T_CHANGE +Time of the first frame after command was applied or time of the first frame if no commands. + @end table @subsection Examples @@ -29699,6 +29702,10 @@ asetpts=N/SR/TB @end itemize +@subsection Commands + +Both filters support all above options as @ref{commands}. + @section setrange Force color range for the output video frame. diff --git a/libavfilter/setpts.c b/libavfilter/setpts.c index 7a5cd3ef782..6dade06e6a7 100644 --- a/libavfilter/setpts.c +++ b/libavfilter/setpts.c @@ -63,6 +63,7 @@ static const char *const var_names[] = { "S", // Number of samples in the current frame "SR", // Audio sample rate "FR", ///< defined only for constant frame-rate video + "T_CHANGE", ///< time of first frame after latest command was applied NULL }; @@ -90,7 +91,8 @@ enum var_name { VAR_S, VAR_SR, VAR_FR, - VAR_VARS_NB + VAR_T_CHANGE, + VAR_VARS_NB, }; typedef struct SetPTSContext { @@ -120,6 +122,7 @@ static av_cold int init(AVFilterContext *ctx) setpts->var_values[VAR_PREV_OUTT] = NAN; setpts->var_values[VAR_STARTPTS] = NAN; setpts->var_values[VAR_STARTT] = NAN; + setpts->var_values[VAR_T_CHANGE] = NAN; return 0; } @@ -163,6 +166,9 @@ static double eval_pts(SetPTSContext *setpts, AVFilterLink *inlink, AVFrame *fra setpts->var_values[VAR_STARTPTS] = TS2D(pts); setpts->var_values[VAR_STARTT ] = TS2T(pts, inlink->time_base); } + if (isnan(setpts->var_values[VAR_T_CHANGE])) { + setpts->var_values[VAR_T_CHANGE] = TS2T(pts, inlink->time_base); + } setpts->var_values[VAR_PTS ] = TS2D(pts); setpts->var_values[VAR_T ] = TS2T(pts, inlink->time_base); #if FF_API_FRAME_PKT @@ -269,14 +275,45 @@ static av_cold void uninit(AVFilterContext *ctx) setpts->expr = NULL; } +static int process_command(AVFilterContext *ctx, const char *cmd, const char *arg, + char *res, int res_len, int flags) +{ + SetPTSContext *setpts = ctx->priv; + AVExpr *new_expr; + int ret; + + ret = ff_filter_process_command(ctx, cmd, arg, res, res_len, flags); + + if (ret < 0) + return ret; + + if (!strcmp(cmd, "expr")) { + ret = av_expr_parse(&new_expr, arg, var_names, NULL, NULL, NULL, NULL, 0, ctx); + // Only free and replace previous expression if new one succeeds, + // otherwise defensively keep everything intact even if reporting an error. + if (ret < 0) { + av_log(ctx, AV_LOG_ERROR, "Error while parsing expression '%s'\n", arg); + } else { + av_expr_free(setpts->expr); + setpts->expr = new_expr; + setpts->var_values[VAR_T_CHANGE] = NAN; + } + } else { + ret = AVERROR(EINVAL); + } + + return ret; +} + #define OFFSET(x) offsetof(SetPTSContext, x) #define V AV_OPT_FLAG_VIDEO_PARAM #define A AV_OPT_FLAG_AUDIO_PARAM +#define R AV_OPT_FLAG_RUNTIME_PARAM #define F AV_OPT_FLAG_FILTERING_PARAM #if CONFIG_SETPTS_FILTER static const AVOption setpts_options[] = { - { "expr", "Expression determining the frame timestamp", OFFSET(expr_str), AV_OPT_TYPE_STRING, { .str = "PTS" }, .flags = V|F }, + { "expr", "Expression determining the frame timestamp", OFFSET(expr_str), AV_OPT_TYPE_STRING, { .str = "PTS" }, .flags = V|F|R }, { NULL } }; AVFILTER_DEFINE_CLASS(setpts); @@ -297,12 +334,13 @@ static const AVFilterPad avfilter_vf_setpts_outputs[] = { }; const AVFilter ff_vf_setpts = { - .name = "setpts", - .description = NULL_IF_CONFIG_SMALL("Set PTS for the output video frame."), - .init = init, - .activate = activate, - .uninit = uninit, - .flags = AVFILTER_FLAG_METADATA_ONLY, + .name = "setpts", + .description = NULL_IF_CONFIG_SMALL("Set PTS for the output video frame."), + .init = init, + .activate = activate, + .uninit = uninit, + .process_command = process_command, + .flags = AVFILTER_FLAG_METADATA_ONLY, .priv_size = sizeof(SetPTSContext), .priv_class = &setpts_class, @@ -315,7 +353,7 @@ const AVFilter ff_vf_setpts = { #if CONFIG_ASETPTS_FILTER static const AVOption asetpts_options[] = { - { "expr", "Expression determining the frame timestamp", OFFSET(expr_str), AV_OPT_TYPE_STRING, { .str = "PTS" }, .flags = A|F }, + { "expr", "Expression determining the frame timestamp", OFFSET(expr_str), AV_OPT_TYPE_STRING, { .str = "PTS" }, .flags = A|F|R }, { NULL } }; AVFILTER_DEFINE_CLASS(asetpts); @@ -336,14 +374,15 @@ static const AVFilterPad asetpts_outputs[] = { }; const AVFilter ff_af_asetpts = { - .name = "asetpts", - .description = NULL_IF_CONFIG_SMALL("Set PTS for the output audio frame."), - .init = init, - .activate = activate, - .uninit = uninit, - .priv_size = sizeof(SetPTSContext), - .priv_class = &asetpts_class, - .flags = AVFILTER_FLAG_METADATA_ONLY, + .name = "asetpts", + .description = NULL_IF_CONFIG_SMALL("Set PTS for the output audio frame."), + .init = init, + .activate = activate, + .uninit = uninit, + .process_command = process_command, + .priv_size = sizeof(SetPTSContext), + .priv_class = &asetpts_class, + .flags = AVFILTER_FLAG_METADATA_ONLY, FILTER_INPUTS(asetpts_inputs), FILTER_OUTPUTS(asetpts_outputs), }; From 482d81378fe00e620776e096c75320210efe5fa3 Mon Sep 17 00:00:00 2001 From: Niklas Haas Date: Fri, 5 May 2023 11:02:34 +0200 Subject: [PATCH 0984/2172] lavfi/vf_libplacebo: update render params on demand Only update this struct when it's expected to change, and cache it otherwise. Partially motivated by a desire to make `process_frames` smaller. --- libavfilter/vf_libplacebo.c | 228 ++++++++++++++++++++---------------- 1 file changed, 126 insertions(+), 102 deletions(-) diff --git a/libavfilter/vf_libplacebo.c b/libavfilter/vf_libplacebo.c index 8387f4dd47f..9596bed9408 100644 --- a/libavfilter/vf_libplacebo.c +++ b/libavfilter/vf_libplacebo.c @@ -143,6 +143,7 @@ typedef struct LibplaceboContext { int color_trc; /* pl_render_params */ + struct pl_render_params params; char *upscaler; char *downscaler; int lut_entries; @@ -156,6 +157,7 @@ typedef struct LibplaceboContext { int disable_fbos; /* pl_deband_params */ + struct pl_deband_params deband_params; int deband; int deband_iterations; float deband_threshold; @@ -163,6 +165,7 @@ typedef struct LibplaceboContext { float deband_grain; /* pl_color_adjustment */ + struct pl_color_adjustment color_adjustment; float brightness; float contrast; float saturation; @@ -170,6 +173,7 @@ typedef struct LibplaceboContext { float gamma; /* pl_peak_detect_params */ + struct pl_peak_detect_params peak_detect_params; int peakdetect; float smoothing; float min_peak; @@ -178,6 +182,7 @@ typedef struct LibplaceboContext { float overshoot; /* pl_color_map_params */ + struct pl_color_map_params color_map_params; int intent; int gamut_mode; int tonemapping; @@ -196,12 +201,14 @@ typedef struct LibplaceboContext { int force_icc_lut; #endif - /* pl_dither_params */ + /* pl_dither_params */ + struct pl_dither_params dither_params; int dithering; int dither_lut_size; int dither_temporal; /* pl_cone_params */ + struct pl_cone_params cone_params; int cones; float cone_str; @@ -280,18 +287,112 @@ static int find_scaler(AVFilterContext *avctx, return AVERROR(EINVAL); } -static int parse_fillcolor(AVFilterContext *avctx, - struct pl_render_params *params, - const char *color_str) +static int update_settings(AVFilterContext *ctx) { int err = 0; + LibplaceboContext *s = ctx->priv; + enum pl_tone_map_mode tonemapping_mode = s->tonemapping_mode; + enum pl_gamut_mode gamut_mode = s->gamut_mode; uint8_t color_rgba[4]; - RET(av_parse_color(color_rgba, color_str, -1, avctx)); - params->background_color[0] = (float) color_rgba[0] / UINT8_MAX; - params->background_color[1] = (float) color_rgba[1] / UINT8_MAX; - params->background_color[2] = (float) color_rgba[2] / UINT8_MAX; - params->background_transparency = 1.0f - (float) color_rgba[3] / UINT8_MAX; + RET(av_parse_color(color_rgba, s->fillcolor, -1, s)); + +#if FF_API_LIBPLACEBO_OPTS + /* backwards compatibility with older API */ + if (!tonemapping_mode && (s->desat_str >= 0.0f || s->desat_exp >= 0.0f)) { + float str = s->desat_str < 0.0f ? 0.9f : s->desat_str; + float exp = s->desat_exp < 0.0f ? 0.2f : s->desat_exp; + if (str >= 0.9f && exp <= 0.1f) { + tonemapping_mode = PL_TONE_MAP_RGB; + } else if (str > 0.1f) { + tonemapping_mode = PL_TONE_MAP_HYBRID; + } else { + tonemapping_mode = PL_TONE_MAP_LUMA; + } + } + + if (s->gamut_warning) + gamut_mode = PL_GAMUT_WARN; + if (s->gamut_clipping) + gamut_mode = PL_GAMUT_DESATURATE; +#endif + + s->deband_params = *pl_deband_params( + .iterations = s->deband_iterations, + .threshold = s->deband_threshold, + .radius = s->deband_radius, + .grain = s->deband_grain, + ); + + s->color_adjustment = (struct pl_color_adjustment) { + .brightness = s->brightness, + .contrast = s->contrast, + .saturation = s->saturation, + .hue = s->hue, + .gamma = s->gamma, + }; + + s->peak_detect_params = *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, + ); + + s->color_map_params = *pl_color_map_params( + .intent = s->intent, + .gamut_mode = gamut_mode, + .tone_mapping_function = tonemapping_funcs[s->tonemapping], + .tone_mapping_param = s->tonemapping_param, + .tone_mapping_mode = tonemapping_mode, + .inverse_tone_mapping = s->inverse_tonemapping, + .tone_mapping_crosstalk = s->crosstalk, + .lut_size = s->tonemapping_lut_size, + ); + + s->dither_params = *pl_dither_params( + .method = s->dithering, + .lut_size = s->dither_lut_size, + .temporal = s->dither_temporal, + ); + + s->cone_params = *pl_cone_params( + .cones = s->cones, + .strength = s->cone_str, + ); + + s->params = *pl_render_params( + .lut_entries = s->lut_entries, + .antiringing_strength = s->antiringing, + .background_transparency = 1.0f - (float) color_rgba[3] / UINT8_MAX, + .background_color = { + (float) color_rgba[0] / UINT8_MAX, + (float) color_rgba[1] / UINT8_MAX, + (float) color_rgba[2] / UINT8_MAX, + }, + + .deband_params = s->deband ? &s->deband_params : NULL, + .sigmoid_params = s->sigmoid ? &pl_sigmoid_default_params : NULL, + .color_adjustment = &s->color_adjustment, + .peak_detect_params = s->peakdetect ? &s->peak_detect_params : NULL, + .color_map_params = &s->color_map_params, + .dither_params = s->dithering >= 0 ? &s->dither_params : NULL, + .cone_params = s->cones ? &s->cone_params : NULL, + + .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_dither = s->force_dither, + .disable_fbos = s->disable_fbos, + ); + + RET(find_scaler(ctx, &s->params.upscaler, s->upscaler)); + RET(find_scaler(ctx, &s->params.downscaler, s->downscaler)); return 0; fail: @@ -327,6 +428,7 @@ static int libplacebo_init(AVFilterContext *avctx) s->out_format = AV_PIX_FMT_NONE; } + RET(update_settings(avctx)); RET(av_expr_parse(&s->crop_x_pexpr, s->crop_x_expr, var_names, NULL, NULL, NULL, NULL, 0, s)); RET(av_expr_parse(&s->crop_y_pexpr, s->crop_y_expr, var_names, @@ -440,14 +542,24 @@ static void libplacebo_uninit(AVFilterContext *avctx) av_expr_free(s->pos_h_pexpr); } +static int libplacebo_process_command(AVFilterContext *ctx, const char *cmd, + const char *arg, char *res, int res_len, + int flags) +{ + int err = 0; + RET(ff_filter_process_command(ctx, cmd, arg, res, res_len, flags)); + RET(update_settings(ctx)); + return 0; + +fail: + return err; +} + static int process_frames(AVFilterContext *avctx, AVFrame *out, AVFrame *in) { int err = 0, ok; LibplaceboContext *s = avctx->priv; - struct pl_render_params params; - enum pl_tone_map_mode tonemapping_mode = s->tonemapping_mode; const AVPixFmtDescriptor *outdesc = av_pix_fmt_desc_get(out->format); - enum pl_gamut_mode gamut_mode = s->gamut_mode; struct pl_frame image, target; ok = pl_map_avframe_ex(s->gpu, &image, pl_avframe_params( .frame = in, @@ -496,95 +608,7 @@ static int process_frames(AVFilterContext *avctx, AVFrame *out, AVFrame *in) pl_rect2df_aspect_set(&target.crop, aspect, s->pad_crop_ratio); } -#if FF_API_LIBPLACEBO_OPTS - /* backwards compatibility with older API */ - if (!tonemapping_mode && (s->desat_str >= 0.0f || s->desat_exp >= 0.0f)) { - float str = s->desat_str < 0.0f ? 0.9f : s->desat_str; - float exp = s->desat_exp < 0.0f ? 0.2f : s->desat_exp; - if (str >= 0.9f && exp <= 0.1f) { - tonemapping_mode = PL_TONE_MAP_RGB; - } else if (str > 0.1f) { - tonemapping_mode = PL_TONE_MAP_HYBRID; - } else { - tonemapping_mode = PL_TONE_MAP_LUMA; - } - } - - if (s->gamut_warning) - gamut_mode = PL_GAMUT_WARN; - if (s->gamut_clipping) - gamut_mode = PL_GAMUT_DESATURATE; -#endif - - /* 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, - .gamut_mode = gamut_mode, - .tone_mapping_function = tonemapping_funcs[s->tonemapping], - .tone_mapping_param = s->tonemapping_param, - .tone_mapping_mode = tonemapping_mode, - .inverse_tone_mapping = s->inverse_tonemapping, - .tone_mapping_crosstalk = s->crosstalk, - .lut_size = s->tonemapping_lut_size, - ), - - .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_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)); - RET(parse_fillcolor(avctx, ¶ms, s->fillcolor)); - - pl_render_image(s->renderer, &image, &target, ¶ms); + pl_render_image(s->renderer, &image, &target, &s->params); pl_unmap_avframe(s->gpu, &image); if (outdesc->flags & AV_PIX_FMT_FLAG_HWACCEL) { @@ -1052,7 +1076,7 @@ const AVFilter ff_vf_libplacebo = { .priv_size = sizeof(LibplaceboContext), .init = &libplacebo_init, .uninit = &libplacebo_uninit, - .process_command = &ff_filter_process_command, + .process_command = &libplacebo_process_command, FILTER_INPUTS(libplacebo_inputs), FILTER_OUTPUTS(libplacebo_outputs), FILTER_QUERY_FUNC(libplacebo_query_format), From 2d5e137207474d2702320ea50d142fce4628709f Mon Sep 17 00:00:00 2001 From: Niklas Haas Date: Fri, 5 May 2023 11:44:00 +0200 Subject: [PATCH 0985/2172] lavfi/vf_libplacebo: split and refactor logic This commit contains no functional change. The goal is merely to separate the highly intertwined `filter_frame` and `process_frames` functions into their separate concerns, specifically to separate frame uploading (which is now done directly in `filter_frame`) from emitting a frame (which is now done by a dedicated function `output_frame`). The overall idea here is to be able to ultimately call `output_frame` multiple times, to e.g. emit several output frames for a single input frame. --- libavfilter/vf_libplacebo.c | 172 +++++++++++++++++++----------------- 1 file changed, 93 insertions(+), 79 deletions(-) diff --git a/libavfilter/vf_libplacebo.c b/libavfilter/vf_libplacebo.c index 9596bed9408..0b3ef6533c8 100644 --- a/libavfilter/vf_libplacebo.c +++ b/libavfilter/vf_libplacebo.c @@ -28,6 +28,14 @@ #include #include +/* Backwards compatibility with older libplacebo */ +#if PL_API_VER < 276 +static inline AVFrame *pl_get_mapped_avframe(const struct pl_frame *frame) +{ + return frame->user_data; +} +#endif + enum { TONE_MAP_AUTO, TONE_MAP_CLIP, @@ -555,35 +563,27 @@ static int libplacebo_process_command(AVFilterContext *ctx, const char *cmd, return err; } -static int process_frames(AVFilterContext *avctx, AVFrame *out, AVFrame *in) +static void update_crops(AVFilterContext *ctx, + struct pl_frame *image, + struct pl_frame *target, + const double target_pts) { - int err = 0, ok; - LibplaceboContext *s = avctx->priv; - const AVPixFmtDescriptor *outdesc = av_pix_fmt_desc_get(out->format); - struct pl_frame image, target; - ok = pl_map_avframe_ex(s->gpu, &image, pl_avframe_params( - .frame = in, - .tex = s->tex, - .map_dovi = s->apply_dovi, - )); - - if (outdesc->flags & AV_PIX_FMT_FLAG_HWACCEL) { - ok &= pl_map_avframe_ex(s->gpu, &target, pl_avframe_params( - .frame = out, - .map_dovi = false, - )); - } else { - ok &= pl_frame_recreate_from_avframe(s->gpu, &target, s->tex + 4, out); - } + LibplaceboContext *s = ctx->priv; + const AVFrame *in = pl_get_mapped_avframe(image); + const AVFilterLink *inlink = ctx->inputs[0]; + const double in_pts = in->pts * av_q2d(inlink->time_base); - if (!ok) { - err = AVERROR_EXTERNAL; - goto fail; - } + s->var_values[VAR_IN_T] = s->var_values[VAR_T] = in_pts; + s->var_values[VAR_OUT_T] = s->var_values[VAR_OT] = target_pts; + s->var_values[VAR_N] = inlink->frame_count_out; - if (!s->apply_filmgrain) - image.film_grain.type = PL_FILM_GRAIN_NONE; + /* Clear these explicitly to avoid leaking previous frames' state */ + s->var_values[VAR_CROP_W] = s->var_values[VAR_CW] = NAN; + s->var_values[VAR_CROP_H] = s->var_values[VAR_CH] = NAN; + s->var_values[VAR_POS_W] = s->var_values[VAR_PW] = NAN; + s->var_values[VAR_POS_H] = s->var_values[VAR_PH] = NAN; + /* Evaluate crop/pos dimensions first, and placement second */ s->var_values[VAR_CROP_W] = s->var_values[VAR_CW] = av_expr_eval(s->crop_w_pexpr, s->var_values, NULL); s->var_values[VAR_CROP_H] = s->var_values[VAR_CH] = @@ -593,72 +593,39 @@ static int process_frames(AVFilterContext *avctx, AVFrame *out, AVFrame *in) s->var_values[VAR_POS_H] = s->var_values[VAR_PH] = av_expr_eval(s->pos_h_pexpr, s->var_values, NULL); - image.crop.x0 = av_expr_eval(s->crop_x_pexpr, s->var_values, NULL); - image.crop.y0 = av_expr_eval(s->crop_y_pexpr, s->var_values, NULL); - image.crop.x1 = image.crop.x0 + s->var_values[VAR_CROP_W]; - image.crop.y1 = image.crop.y0 + s->var_values[VAR_CROP_H]; + image->crop.x0 = av_expr_eval(s->crop_x_pexpr, s->var_values, NULL); + image->crop.y0 = av_expr_eval(s->crop_y_pexpr, s->var_values, NULL); + image->crop.x1 = image->crop.x0 + s->var_values[VAR_CROP_W]; + image->crop.y1 = image->crop.y0 + s->var_values[VAR_CROP_H]; - target.crop.x0 = av_expr_eval(s->pos_x_pexpr, s->var_values, NULL); - target.crop.y0 = av_expr_eval(s->pos_y_pexpr, s->var_values, NULL); - target.crop.x1 = target.crop.x0 + s->var_values[VAR_POS_W]; - target.crop.y1 = target.crop.y0 + s->var_values[VAR_POS_H]; + target->crop.x0 = av_expr_eval(s->pos_x_pexpr, s->var_values, NULL); + target->crop.y0 = av_expr_eval(s->pos_y_pexpr, s->var_values, NULL); + target->crop.x1 = target->crop.x0 + s->var_values[VAR_POS_W]; + target->crop.y1 = target->crop.y0 + s->var_values[VAR_POS_H]; 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); - } - - pl_render_image(s->renderer, &image, &target, &s->params); - pl_unmap_avframe(s->gpu, &image); - - if (outdesc->flags & AV_PIX_FMT_FLAG_HWACCEL) { - pl_unmap_avframe(s->gpu, &target); - } else if (!pl_download_avframe(s->gpu, &target, out)) { - err = AVERROR_EXTERNAL; - goto fail; + float aspect = pl_rect2df_aspect(&target->crop) * av_q2d(s->target_sar); + pl_rect2df_aspect_set(&target->crop, aspect, s->pad_crop_ratio); } - - /* Flush the command queues for performance */ - pl_gpu_flush(s->gpu); - return 0; - -fail: - pl_unmap_avframe(s->gpu, &image); - pl_unmap_avframe(s->gpu, &target); - return err; } -static int filter_frame(AVFilterLink *link, AVFrame *in) +/* Construct and emit an output frame for `image` */ +static int output_frame(AVFilterContext *ctx, struct pl_frame *image) { - int err, changed_csp; - AVFilterContext *ctx = link->dst; + int err = 0, ok, changed_csp; LibplaceboContext *s = ctx->priv; AVFilterLink *outlink = ctx->outputs[0]; - + const AVPixFmtDescriptor *outdesc = av_pix_fmt_desc_get(outlink->format); AVFrame *out = ff_get_video_buffer(outlink, outlink->w, outlink->h); - if (!out) { - err = AVERROR(ENOMEM); - goto fail; - } - - pl_log_level_update(s->log, get_log_level()); + const AVFrame *in = pl_get_mapped_avframe(image); + struct pl_frame target; + if (!out) + return AVERROR(ENOMEM); RET(av_frame_copy_props(out, in)); out->width = outlink->w; out->height = outlink->h; - /* Dynamic variables */ - s->var_values[VAR_IN_T] = s->var_values[VAR_T] = - in->pts == AV_NOPTS_VALUE ? NAN : in->pts * av_q2d(link->time_base); - s->var_values[VAR_OUT_T] = s->var_values[VAR_OT] = - out->pts == AV_NOPTS_VALUE ? NAN : out->pts * av_q2d(outlink->time_base); - s->var_values[VAR_N] = link->frame_count_out; - /* Will be evaluated/set by `process_frames` */ - s->var_values[VAR_CROP_W] = s->var_values[VAR_CW] = NAN; - s->var_values[VAR_CROP_H] = s->var_values[VAR_CH] = NAN; - s->var_values[VAR_POS_W] = s->var_values[VAR_PW] = NAN; - s->var_values[VAR_POS_H] = s->var_values[VAR_PH] = NAN; - 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 */ @@ -694,18 +661,65 @@ static int filter_frame(AVFilterLink *link, AVFrame *in) if (s->apply_filmgrain) av_frame_remove_side_data(out, AV_FRAME_DATA_FILM_GRAIN_PARAMS); - RET(process_frames(ctx, out, in)); + /* Map, render and unmap output frame */ + if (outdesc->flags & AV_PIX_FMT_FLAG_HWACCEL) { + ok = pl_map_avframe_ex(s->gpu, &target, pl_avframe_params( + .frame = out, + .map_dovi = false, + )); + } else { + ok = pl_frame_recreate_from_avframe(s->gpu, &target, s->tex + 4, out); + } + if (!ok) { + err = AVERROR_EXTERNAL; + goto fail; + } - av_frame_free(&in); + update_crops(ctx, image, &target, out->pts * av_q2d(outlink->time_base)); + pl_render_image(s->renderer, image, &target, &s->params); + if (outdesc->flags & AV_PIX_FMT_FLAG_HWACCEL) { + pl_unmap_avframe(s->gpu, &target); + } else if (!pl_download_avframe(s->gpu, &target, out)) { + err = AVERROR_EXTERNAL; + goto fail; + } return ff_filter_frame(outlink, out); fail: - av_frame_free(&in); av_frame_free(&out); return err; } +static int filter_frame(AVFilterLink *link, AVFrame *in) +{ + int ret, ok; + AVFilterContext *ctx = link->dst; + LibplaceboContext *s = ctx->priv; + struct pl_frame image; + + pl_log_level_update(s->log, get_log_level()); + + /* Map input frame */ + ok = pl_map_avframe_ex(s->gpu, &image, pl_avframe_params( + .frame = in, + .tex = s->tex, + .map_dovi = s->apply_dovi, + )); + av_frame_free(&in); + + if (!s->apply_filmgrain) + image.film_grain.type = PL_FILM_GRAIN_NONE; + + if (!ok) + return AVERROR_EXTERNAL; + + ret = output_frame(ctx, &image); + + pl_unmap_avframe(s->gpu, &image); + return ret; +} + static int libplacebo_query_format(AVFilterContext *ctx) { int err; From 9e802a47ccb2c02a04a70f04f7a68a156a8ac224 Mon Sep 17 00:00:00 2001 From: Niklas Haas Date: Fri, 5 May 2023 12:34:54 +0200 Subject: [PATCH 0986/2172] lavfi/vf_libplacebo: switch to pl_queue-based design This does not leverage any immediate benefits, but refactors and prepares the codebase for upcoming changes, which will include the ability to do deinterlacing and resampling (frame mixing). --- libavfilter/vf_libplacebo.c | 214 ++++++++++++++++++++++++------------ 1 file changed, 144 insertions(+), 70 deletions(-) diff --git a/libavfilter/vf_libplacebo.c b/libavfilter/vf_libplacebo.c index 0b3ef6533c8..7f8190d91c9 100644 --- a/libavfilter/vf_libplacebo.c +++ b/libavfilter/vf_libplacebo.c @@ -16,6 +16,7 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#include "libavutil/avassert.h" #include "libavutil/eval.h" #include "libavutil/file.h" #include "libavutil/opt.h" @@ -26,6 +27,7 @@ #include #include +#include #include /* Backwards compatibility with older libplacebo */ @@ -122,7 +124,8 @@ typedef struct LibplaceboContext { pl_vulkan vulkan; pl_gpu gpu; pl_renderer renderer; - pl_tex tex[8]; + pl_queue queue; + pl_tex tex[4]; /* settings */ char *out_format_string; @@ -392,6 +395,7 @@ static int update_settings(AVFilterContext *ctx) .num_hooks = s->num_hooks, .skip_anti_aliasing = s->skip_aa, + .skip_caching_single_frame = true, .polar_cutoff = s->polar_cutoff, .disable_linear_scaling = s->disable_linear, .disable_builtin_scalers = s->disable_builtin, @@ -509,6 +513,7 @@ static int init_vulkan(AVFilterContext *avctx, const AVVulkanDeviceContext *hwct /* Create the renderer */ s->gpu = s->vulkan->gpu; s->renderer = pl_renderer_create(s->log, s->gpu); + s->queue = pl_queue_create(s->gpu); /* Parse the user shaders, if requested */ if (s->shader_bin_len) @@ -535,6 +540,7 @@ static void libplacebo_uninit(AVFilterContext *avctx) for (int i = 0; i < s->num_hooks; i++) pl_mpv_user_shader_destroy(&s->hooks[i]); pl_renderer_destroy(&s->renderer); + pl_queue_destroy(&s->queue); pl_vulkan_destroy(&s->vulkan); pl_log_destroy(&s->log); ff_vk_uninit(&s->vkctx); @@ -564,69 +570,92 @@ static int libplacebo_process_command(AVFilterContext *ctx, const char *cmd, } static void update_crops(AVFilterContext *ctx, - struct pl_frame *image, - struct pl_frame *target, - const double target_pts) + struct pl_frame_mix *mix, struct pl_frame *target, + uint64_t ref_sig, double base_pts) { LibplaceboContext *s = ctx->priv; - const AVFrame *in = pl_get_mapped_avframe(image); - const AVFilterLink *inlink = ctx->inputs[0]; - const double in_pts = in->pts * av_q2d(inlink->time_base); - - s->var_values[VAR_IN_T] = s->var_values[VAR_T] = in_pts; - s->var_values[VAR_OUT_T] = s->var_values[VAR_OT] = target_pts; - s->var_values[VAR_N] = inlink->frame_count_out; - - /* Clear these explicitly to avoid leaking previous frames' state */ - s->var_values[VAR_CROP_W] = s->var_values[VAR_CW] = NAN; - s->var_values[VAR_CROP_H] = s->var_values[VAR_CH] = NAN; - s->var_values[VAR_POS_W] = s->var_values[VAR_PW] = NAN; - s->var_values[VAR_POS_H] = s->var_values[VAR_PH] = NAN; - - /* Evaluate crop/pos dimensions first, and placement second */ - s->var_values[VAR_CROP_W] = s->var_values[VAR_CW] = - av_expr_eval(s->crop_w_pexpr, s->var_values, NULL); - s->var_values[VAR_CROP_H] = s->var_values[VAR_CH] = - av_expr_eval(s->crop_h_pexpr, s->var_values, NULL); - s->var_values[VAR_POS_W] = s->var_values[VAR_PW] = - av_expr_eval(s->pos_w_pexpr, s->var_values, NULL); - s->var_values[VAR_POS_H] = s->var_values[VAR_PH] = - av_expr_eval(s->pos_h_pexpr, s->var_values, NULL); - - image->crop.x0 = av_expr_eval(s->crop_x_pexpr, s->var_values, NULL); - image->crop.y0 = av_expr_eval(s->crop_y_pexpr, s->var_values, NULL); - image->crop.x1 = image->crop.x0 + s->var_values[VAR_CROP_W]; - image->crop.y1 = image->crop.y0 + s->var_values[VAR_CROP_H]; - - target->crop.x0 = av_expr_eval(s->pos_x_pexpr, s->var_values, NULL); - target->crop.y0 = av_expr_eval(s->pos_y_pexpr, s->var_values, NULL); - target->crop.x1 = target->crop.x0 + s->var_values[VAR_POS_W]; - target->crop.y1 = target->crop.y0 + s->var_values[VAR_POS_H]; - - 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); + + for (int i = 0; i < mix->num_frames; i++) { + // Mutate the `pl_frame.crop` fields in-place. This is fine because we + // own the entire pl_queue, and hence, the pointed-at frames. + struct pl_frame *image = (struct pl_frame *) mix->frames[i]; + double image_pts = base_pts + mix->timestamps[i]; + + /* Update dynamic variables */ + s->var_values[VAR_IN_T] = s->var_values[VAR_T] = image_pts; + s->var_values[VAR_OUT_T] = s->var_values[VAR_OT] = base_pts; + s->var_values[VAR_N] = ctx->outputs[0]->frame_count_out; + + /* Clear these explicitly to avoid leaking previous frames' state */ + s->var_values[VAR_CROP_W] = s->var_values[VAR_CW] = NAN; + s->var_values[VAR_CROP_H] = s->var_values[VAR_CH] = NAN; + s->var_values[VAR_POS_W] = s->var_values[VAR_PW] = NAN; + s->var_values[VAR_POS_H] = s->var_values[VAR_PH] = NAN; + + /* Compute dimensions first and placement second */ + s->var_values[VAR_CROP_W] = s->var_values[VAR_CW] = + av_expr_eval(s->crop_w_pexpr, s->var_values, NULL); + s->var_values[VAR_CROP_H] = s->var_values[VAR_CH] = + av_expr_eval(s->crop_h_pexpr, s->var_values, NULL); + s->var_values[VAR_POS_W] = s->var_values[VAR_PW] = + av_expr_eval(s->pos_w_pexpr, s->var_values, NULL); + s->var_values[VAR_POS_H] = s->var_values[VAR_PH] = + av_expr_eval(s->pos_h_pexpr, s->var_values, NULL); + + image->crop.x0 = av_expr_eval(s->crop_x_pexpr, s->var_values, NULL); + image->crop.y0 = av_expr_eval(s->crop_y_pexpr, s->var_values, NULL); + image->crop.x1 = image->crop.x0 + s->var_values[VAR_CROP_W]; + image->crop.y1 = image->crop.y0 + s->var_values[VAR_CROP_H]; + + if (mix->signatures[i] == ref_sig) { + /* Only update the target crop once, for the 'reference' frame */ + target->crop.x0 = av_expr_eval(s->pos_x_pexpr, s->var_values, NULL); + target->crop.y0 = av_expr_eval(s->pos_y_pexpr, s->var_values, NULL); + target->crop.x1 = target->crop.x0 + s->var_values[VAR_POS_W]; + target->crop.y1 = target->crop.y0 + s->var_values[VAR_POS_H]; + + 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); + } + } } } -/* Construct and emit an output frame for `image` */ -static int output_frame(AVFilterContext *ctx, struct pl_frame *image) +/* Construct and emit an output frame for a given frame mix */ +static int output_frame_mix(AVFilterContext *ctx, + struct pl_frame_mix *mix, + int64_t pts) { int err = 0, ok, changed_csp; LibplaceboContext *s = ctx->priv; AVFilterLink *outlink = ctx->outputs[0]; const AVPixFmtDescriptor *outdesc = av_pix_fmt_desc_get(outlink->format); - AVFrame *out = ff_get_video_buffer(outlink, outlink->w, outlink->h); - const AVFrame *in = pl_get_mapped_avframe(image); struct pl_frame target; + const AVFrame *ref; + AVFrame *out; + uint64_t ref_sig; + if (!mix->num_frames) + return 0; + + out = ff_get_video_buffer(outlink, outlink->w, outlink->h); if (!out) return AVERROR(ENOMEM); - RET(av_frame_copy_props(out, in)); + /* Use the last frame before current PTS value as reference */ + for (int i = 0; i < mix->num_frames; i++) { + if (i && mix->timestamps[i] > 0.0f) + break; + ref = pl_get_mapped_avframe(mix->frames[i]); + ref_sig = mix->signatures[i]; + } + + RET(av_frame_copy_props(out, ref)); + out->pts = pts; out->width = outlink->w; out->height = outlink->h; - if (s->apply_dovi && av_frame_get_side_data(in, AV_FRAME_DATA_DOVI_METADATA)) { + if (s->apply_dovi && av_frame_get_side_data(ref, 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; @@ -643,10 +672,10 @@ static int output_frame(AVFilterContext *ctx, struct pl_frame *image) if (s->color_primaries >= 0) out->color_primaries = s->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; + changed_csp = ref->colorspace != out->colorspace || + ref->color_range != out->color_range || + ref->color_trc != out->color_trc || + ref->color_primaries != out->color_primaries; /* Strip side data if no longer relevant */ if (changed_csp) { @@ -668,15 +697,15 @@ static int output_frame(AVFilterContext *ctx, struct pl_frame *image) .map_dovi = false, )); } else { - ok = pl_frame_recreate_from_avframe(s->gpu, &target, s->tex + 4, out); + ok = pl_frame_recreate_from_avframe(s->gpu, &target, s->tex, out); } if (!ok) { err = AVERROR_EXTERNAL; goto fail; } - update_crops(ctx, image, &target, out->pts * av_q2d(outlink->time_base)); - pl_render_image(s->renderer, image, &target, &s->params); + update_crops(ctx, mix, &target, ref_sig, out->pts * av_q2d(outlink->time_base)); + pl_render_image_mix(s->renderer, mix, &target, &s->params); if (outdesc->flags & AV_PIX_FMT_FLAG_HWACCEL) { pl_unmap_avframe(s->gpu, &target); @@ -691,33 +720,78 @@ static int output_frame(AVFilterContext *ctx, struct pl_frame *image) return err; } +static bool map_frame(pl_gpu gpu, pl_tex *tex, + const struct pl_source_frame *src, + struct pl_frame *out) +{ + AVFrame *avframe = src->frame_data; + LibplaceboContext *s = avframe->opaque; + bool ok = pl_map_avframe_ex(gpu, out, pl_avframe_params( + .frame = avframe, + .tex = tex, + .map_dovi = s->apply_dovi, + )); + + if (!s->apply_filmgrain) + out->film_grain.type = PL_FILM_GRAIN_NONE; + + av_frame_free(&avframe); + return ok; +} + +static void unmap_frame(pl_gpu gpu, struct pl_frame *frame, + const struct pl_source_frame *src) +{ + pl_unmap_avframe(gpu, frame); +} + +static void discard_frame(const struct pl_source_frame *src) +{ + AVFrame *avframe = src->frame_data; + av_frame_free(&avframe); +} + static int filter_frame(AVFilterLink *link, AVFrame *in) { - int ret, ok; AVFilterContext *ctx = link->dst; LibplaceboContext *s = ctx->priv; - struct pl_frame image; + AVFilterLink *outlink = ctx->outputs[0]; + enum pl_queue_status status; + struct pl_frame_mix mix; pl_log_level_update(s->log, get_log_level()); - /* Map input frame */ - ok = pl_map_avframe_ex(s->gpu, &image, pl_avframe_params( - .frame = in, - .tex = s->tex, - .map_dovi = s->apply_dovi, + /* Push input frame */ + in->opaque = s; + pl_queue_push(s->queue, &(struct pl_source_frame) { + .pts = in->pts * av_q2d(link->time_base), + .duration = in->duration * av_q2d(link->time_base), + .first_field = pl_field_from_avframe(in), + .frame_data = in, + .map = map_frame, + .unmap = unmap_frame, + .discard = discard_frame, + }); + + /* Immediately return an output frame for the same PTS */ + av_assert1(!av_cmp_q(link->time_base, outlink->time_base)); + status = pl_queue_update(s->queue, &mix, pl_queue_params( + .pts = in->pts * av_q2d(outlink->time_base), + .radius = pl_frame_mix_radius(&s->params), + .vsync_duration = av_q2d(av_inv_q(outlink->frame_rate)), )); - av_frame_free(&in); - - if (!s->apply_filmgrain) - image.film_grain.type = PL_FILM_GRAIN_NONE; - if (!ok) + switch (status) { + case PL_QUEUE_MORE: // TODO: switch to activate() and handle properly + case PL_QUEUE_OK: + return output_frame_mix(ctx, &mix, in->pts); + case PL_QUEUE_EOF: + return 0; + case PL_QUEUE_ERR: return AVERROR_EXTERNAL; + } - ret = output_frame(ctx, &image); - - pl_unmap_avframe(s->gpu, &image); - return ret; + return AVERROR_BUG; } static int libplacebo_query_format(AVFilterContext *ctx) From 83b1f3f54ec43a1ab897139160884a99bbd07e71 Mon Sep 17 00:00:00 2001 From: Niklas Haas Date: Sat, 6 May 2023 15:04:43 +0200 Subject: [PATCH 0987/2172] lavfi/vf_libplacebo: switch to activate() To present compatibility with the current behavior, we keep track of a FIFO of exact frame timestamps that we want to output to the user. In practice, this is essentially equivalent to the current filter_frame() code, but this design allows us to scale to more complicated use cases in the future - for example, insertion of intermediate frames (deinterlacing, frame doubling, conversion to fixed fps, ...) --- libavfilter/vf_libplacebo.c | 113 +++++++++++++++++++++++++----------- 1 file changed, 80 insertions(+), 33 deletions(-) diff --git a/libavfilter/vf_libplacebo.c b/libavfilter/vf_libplacebo.c index 7f8190d91c9..472bbb6b2ce 100644 --- a/libavfilter/vf_libplacebo.c +++ b/libavfilter/vf_libplacebo.c @@ -18,10 +18,12 @@ #include "libavutil/avassert.h" #include "libavutil/eval.h" +#include "libavutil/fifo.h" #include "libavutil/file.h" #include "libavutil/opt.h" #include "libavutil/parseutils.h" #include "internal.h" +#include "filters.h" #include "vulkan_filter.h" #include "scale_eval.h" @@ -127,6 +129,9 @@ typedef struct LibplaceboContext { pl_queue queue; pl_tex tex[4]; + /* filter state */ + AVFifo *out_pts; ///< timestamps of wanted output frames + /* settings */ char *out_format_string; enum AVPixelFormat out_format; @@ -458,6 +463,9 @@ static int libplacebo_init(AVFilterContext *avctx) RET(av_expr_parse(&s->pos_h_pexpr, s->pos_h_expr, var_names, NULL, NULL, NULL, NULL, 0, s)); + /* Initialize dynamic filter state */ + s->out_pts = av_fifo_alloc2(1, sizeof(int64_t), AV_FIFO_FLAG_AUTO_GROW); + /* Note: s->vulkan etc. are initialized later, when hwctx is available */ return 0; @@ -554,6 +562,7 @@ static void libplacebo_uninit(AVFilterContext *avctx) av_expr_free(s->pos_y_pexpr); av_expr_free(s->pos_w_pexpr); av_expr_free(s->pos_h_pexpr); + av_fifo_freep2(&s->out_pts); } static int libplacebo_process_command(AVFilterContext *ctx, const char *cmd, @@ -751,47 +760,85 @@ static void discard_frame(const struct pl_source_frame *src) av_frame_free(&avframe); } -static int filter_frame(AVFilterLink *link, AVFrame *in) +static int libplacebo_activate(AVFilterContext *ctx) { - AVFilterContext *ctx = link->dst; + int ret, status; LibplaceboContext *s = ctx->priv; + AVFilterLink *inlink = ctx->inputs[0]; AVFilterLink *outlink = ctx->outputs[0]; - enum pl_queue_status status; - struct pl_frame_mix mix; + AVFrame *in; + int64_t pts; + FF_FILTER_FORWARD_STATUS_BACK(outlink, inlink); pl_log_level_update(s->log, get_log_level()); - /* Push input frame */ - in->opaque = s; - pl_queue_push(s->queue, &(struct pl_source_frame) { - .pts = in->pts * av_q2d(link->time_base), - .duration = in->duration * av_q2d(link->time_base), - .first_field = pl_field_from_avframe(in), - .frame_data = in, - .map = map_frame, - .unmap = unmap_frame, - .discard = discard_frame, - }); - - /* Immediately return an output frame for the same PTS */ - av_assert1(!av_cmp_q(link->time_base, outlink->time_base)); - status = pl_queue_update(s->queue, &mix, pl_queue_params( - .pts = in->pts * av_q2d(outlink->time_base), - .radius = pl_frame_mix_radius(&s->params), - .vsync_duration = av_q2d(av_inv_q(outlink->frame_rate)), - )); + while ((ret = ff_inlink_consume_frame(inlink, &in)) > 0) { + in->opaque = s; + pl_queue_push(s->queue, &(struct pl_source_frame) { + .pts = in->pts * av_q2d(inlink->time_base), + .duration = in->duration * av_q2d(inlink->time_base), + .first_field = pl_field_from_avframe(in), + .frame_data = in, + .map = map_frame, + .unmap = unmap_frame, + .discard = discard_frame, + }); + + /* Internally queue an output frame for the same PTS */ + av_assert1(!av_cmp_q(link->time_base, outlink->time_base)); + av_fifo_write(s->out_pts, &in->pts, 1); + } - switch (status) { - case PL_QUEUE_MORE: // TODO: switch to activate() and handle properly - case PL_QUEUE_OK: - return output_frame_mix(ctx, &mix, in->pts); - case PL_QUEUE_EOF: - return 0; - case PL_QUEUE_ERR: - return AVERROR_EXTERNAL; + if (ret < 0) + return ret; + + if (ff_inlink_acknowledge_status(inlink, &status, &pts)) { + pts = av_rescale_q_rnd(pts, inlink->time_base, outlink->time_base, + AV_ROUND_UP); + if (status == AVERROR_EOF) { + /* Signal EOF to pl_queue, and enqueue this output frame to + * make sure we see PL_QUEUE_EOF returned eventually */ + pl_queue_push(s->queue, NULL); + av_fifo_write(s->out_pts, &pts, 1); + } else { + ff_outlink_set_status(outlink, status, pts); + return 0; + } + } + + if (ff_outlink_frame_wanted(outlink)) { + struct pl_frame_mix mix; + enum pl_queue_status ret; + + if (av_fifo_peek(s->out_pts, &pts, 1, 0) < 0) { + ff_inlink_request_frame(inlink); + return 0; + } + + ret = pl_queue_update(s->queue, &mix, pl_queue_params( + .pts = pts * av_q2d(outlink->time_base), + .radius = pl_frame_mix_radius(&s->params), + .vsync_duration = av_q2d(av_inv_q(outlink->frame_rate)), + )); + + switch (ret) { + case PL_QUEUE_MORE: + ff_inlink_request_frame(inlink); + return 0; + case PL_QUEUE_OK: + av_fifo_drain2(s->out_pts, 1); + return output_frame_mix(ctx, &mix, pts); + case PL_QUEUE_EOF: + ff_outlink_set_status(outlink, AVERROR_EOF, pts); + return 0; + case PL_QUEUE_ERR: + return AVERROR_EXTERNAL; + } + + return AVERROR_BUG; } - return AVERROR_BUG; + return FFERROR_NOT_READY; } static int libplacebo_query_format(AVFilterContext *ctx) @@ -1145,7 +1192,6 @@ static const AVFilterPad libplacebo_inputs[] = { { .name = "default", .type = AVMEDIA_TYPE_VIDEO, - .filter_frame = &filter_frame, .config_props = &libplacebo_config_input, }, }; @@ -1164,6 +1210,7 @@ const AVFilter ff_vf_libplacebo = { .priv_size = sizeof(LibplaceboContext), .init = &libplacebo_init, .uninit = &libplacebo_uninit, + .activate = &libplacebo_activate, .process_command = &libplacebo_process_command, FILTER_INPUTS(libplacebo_inputs), FILTER_OUTPUTS(libplacebo_outputs), From 02f3b9312a99c4ea58211b1ee3d1cb41d04255b8 Mon Sep 17 00:00:00 2001 From: Niklas Haas Date: Sun, 7 May 2023 23:18:43 +0200 Subject: [PATCH 0988/2172] lavfi/vf_libplacebo: allow fps conversion This exposes libplacebo's frame mixing functionality to vf_libplacebo, by allowing users to specify a desired target fps to output at. Incoming frames will be smoothly resampled (in a manner determined by the `frame_mixer` option, to be added in the next commit). To generate a consistently timed output stream, we directly use the desired framerate as the timebase, and simply output frames in sequential order (tracked by the number of frames output so far). --- doc/filters.texi | 7 +++++++ libavfilter/vf_libplacebo.c | 38 ++++++++++++++++++++++++++++++------- 2 files changed, 38 insertions(+), 7 deletions(-) diff --git a/doc/filters.texi b/doc/filters.texi index ef48a4cf312..70bb0996d3d 100644 --- a/doc/filters.texi +++ b/doc/filters.texi @@ -16044,6 +16044,13 @@ and @code{(oh-ph)/2}. Set the output placement width/height expressions, default values are @code{ow} and @code{oh}. +@item fps +Set the output frame rate. This can be rational, e.g. @code{60000/1001}. If +set to the special string @code{none} (the default), input timestamps will +instead be passed through to the output unmodified. Otherwise, the input video +frames will be interpolated as necessary to rescale the video to the specified +target framerate, in a manner as determined by the @option{frame_mixer} option. + @item format Set the output format override. If unset (the default), frames will be output in the same format as the respective input frames. Otherwise, format conversion diff --git a/libavfilter/vf_libplacebo.c b/libavfilter/vf_libplacebo.c index 472bbb6b2ce..f8b93f975f0 100644 --- a/libavfilter/vf_libplacebo.c +++ b/libavfilter/vf_libplacebo.c @@ -139,6 +139,8 @@ typedef struct LibplaceboContext { double var_values[VAR_VARS_NB]; char *w_expr; char *h_expr; + char *fps_string; + AVRational fps; ///< parsed FPS, or 0/0 for "none" char *crop_x_expr, *crop_y_expr; char *crop_w_expr, *crop_h_expr; char *pos_x_expr, *pos_y_expr; @@ -166,6 +168,7 @@ typedef struct LibplaceboContext { float antiringing; int sigmoid; int skip_aa; + int skip_cache; float polar_cutoff; int disable_linear; int disable_builtin; @@ -400,7 +403,7 @@ static int update_settings(AVFilterContext *ctx) .num_hooks = s->num_hooks, .skip_anti_aliasing = s->skip_aa, - .skip_caching_single_frame = true, + .skip_caching_single_frame = s->skip_cache, .polar_cutoff = s->polar_cutoff, .disable_linear_scaling = s->disable_linear, .disable_builtin_scalers = s->disable_builtin, @@ -465,6 +468,8 @@ static int libplacebo_init(AVFilterContext *avctx) /* Initialize dynamic filter state */ s->out_pts = av_fifo_alloc2(1, sizeof(int64_t), AV_FIFO_FLAG_AUTO_GROW); + if (strcmp(s->fps_string, "none") != 0) + RET(av_parse_video_rate(&s->fps, s->fps_string)); /* Note: s->vulkan etc. are initialized later, when hwctx is available */ return 0; @@ -663,6 +668,8 @@ static int output_frame_mix(AVFilterContext *ctx, out->pts = pts; out->width = outlink->w; out->height = outlink->h; + if (s->fps.num) + out->duration = 1; if (s->apply_dovi && av_frame_get_side_data(ref, AV_FRAME_DATA_DOVI_METADATA)) { /* Output of dovi reshaping is always BT.2020+PQ, so infer the correct @@ -784,9 +791,11 @@ static int libplacebo_activate(AVFilterContext *ctx) .discard = discard_frame, }); - /* Internally queue an output frame for the same PTS */ - av_assert1(!av_cmp_q(link->time_base, outlink->time_base)); - av_fifo_write(s->out_pts, &in->pts, 1); + if (!s->fps.num) { + /* Internally queue an output frame for the same PTS */ + av_assert1(!av_cmp_q(link->time_base, outlink->time_base)); + av_fifo_write(s->out_pts, &in->pts, 1); + } } if (ret < 0) @@ -799,7 +808,8 @@ static int libplacebo_activate(AVFilterContext *ctx) /* Signal EOF to pl_queue, and enqueue this output frame to * make sure we see PL_QUEUE_EOF returned eventually */ pl_queue_push(s->queue, NULL); - av_fifo_write(s->out_pts, &pts, 1); + if (!s->fps.num) + av_fifo_write(s->out_pts, &pts, 1); } else { ff_outlink_set_status(outlink, status, pts); return 0; @@ -810,7 +820,9 @@ static int libplacebo_activate(AVFilterContext *ctx) struct pl_frame_mix mix; enum pl_queue_status ret; - if (av_fifo_peek(s->out_pts, &pts, 1, 0) < 0) { + if (s->fps.num) { + pts = outlink->frame_count_out; + } else if (av_fifo_peek(s->out_pts, &pts, 1, 0) < 0) { ff_inlink_request_frame(inlink); return 0; } @@ -826,7 +838,8 @@ static int libplacebo_activate(AVFilterContext *ctx) ff_inlink_request_frame(inlink); return 0; case PL_QUEUE_OK: - av_fifo_drain2(s->out_pts, 1); + if (!s->fps.num) + av_fifo_drain2(s->out_pts, 1); return output_frame_mix(ctx, &mix, pts); case PL_QUEUE_EOF: ff_outlink_set_status(outlink, AVERROR_EOF, pts); @@ -942,6 +955,7 @@ static int libplacebo_config_output(AVFilterLink *outlink) AVVulkanFramesContext *vkfc; AVRational scale_sar; + /* Frame dimensions */ RET(ff_scale_eval_dimensions(s, s->w_expr, s->h_expr, inlink, outlink, &outlink->w, &outlink->h)); @@ -965,6 +979,15 @@ static int libplacebo_config_output(AVFilterLink *outlink) outlink->sample_aspect_ratio = scale_sar; } + /* Frame rate */ + if (s->fps.num) { + outlink->frame_rate = s->fps; + outlink->time_base = av_inv_q(s->fps); + s->skip_cache = av_cmp_q(inlink->frame_rate, s->fps) > 0; + } else { + s->skip_cache = true; + } + /* Static variables */ s->var_values[VAR_IN_W] = s->var_values[VAR_IW] = inlink->w; s->var_values[VAR_IN_H] = s->var_values[VAR_IH] = inlink->h; @@ -1009,6 +1032,7 @@ static int libplacebo_config_output(AVFilterLink *outlink) static const AVOption libplacebo_options[] = { { "w", "Output video frame width", OFFSET(w_expr), AV_OPT_TYPE_STRING, {.str = "iw"}, .flags = STATIC }, { "h", "Output video frame height", OFFSET(h_expr), AV_OPT_TYPE_STRING, {.str = "ih"}, .flags = STATIC }, + { "fps", "Output video frame rate", OFFSET(fps_string), AV_OPT_TYPE_STRING, {.str = "none"}, .flags = STATIC }, { "crop_x", "Input video crop x", OFFSET(crop_x_expr), AV_OPT_TYPE_STRING, {.str = "(iw-cw)/2"}, .flags = DYNAMIC }, { "crop_y", "Input video crop y", OFFSET(crop_y_expr), AV_OPT_TYPE_STRING, {.str = "(ih-ch)/2"}, .flags = DYNAMIC }, { "crop_w", "Input video crop w", OFFSET(crop_w_expr), AV_OPT_TYPE_STRING, {.str = "iw"}, .flags = DYNAMIC }, From 30c71ef98e6b0d3b5d303388a81676a5bd963227 Mon Sep 17 00:00:00 2001 From: Niklas Haas Date: Wed, 10 May 2023 14:42:22 +0200 Subject: [PATCH 0989/2172] lavfi/vf_libplacebo: add frame_mixer option Fairly straightforward. We just need to modify the scaler handling code slightly to support looking at a different list of filter presets. --- doc/filters.texi | 31 +++++++++++++++++++++++++++++++ libavfilter/vf_libplacebo.c | 17 +++++++++++------ 2 files changed, 42 insertions(+), 6 deletions(-) diff --git a/doc/filters.texi b/doc/filters.texi index 70bb0996d3d..9ada73bab06 100644 --- a/doc/filters.texi +++ b/doc/filters.texi @@ -16177,6 +16177,31 @@ Cubic BC spline with parameters recommended by Mitchell and Netravali. Very little ringing. @end table +@item frame_mixer +Controls the kernel used for mixing frames temporally. The default value is +@code{none}, which disables frame mixing. For a full list of possible values, +pass @code{help} to this option. The most important values are: +@table @samp +@item none +Disables frame mixing, giving a result equivalent to "nearest neighbour" +semantics. + +@item oversample +Oversamples the input video to create a "Smooth Motion"-type effect: if an +output frame would exactly fall on the transition between two video frames, it +is blended according to the relative overlap. This is the recommended option +whenever preserving the original subjective appearance is desired. + +@item mitchell_clamp +Larger filter kernel that smoothly interpolates multiple frames in a manner +designed to eliminate ringing and other artefacts as much as possible. This is +the recommended option wherever maximum visual smoothness is desired. + +@item linear +Linear blend/fade between frames. Especially useful for constructing e.g. +slideshows. +@end table + @item lut_entries Configures the size of scaler LUTs, ranging from @code{1} to @code{256}. The default of @code{0} will pick libplacebo's internal default, typically @@ -16534,6 +16559,12 @@ Rescale input to fit into standard 1080p, with high quality scaling: libplacebo=w=1920:h=1080:force_original_aspect_ratio=decrease:normalize_sar=true:upscaler=ewa_lanczos:downscaler=ewa_lanczos @end example +@item +Interpolate low FPS / VFR input to smoothed constant 60 fps output: +@example +libplacebo=fps=60:frame_mixer=mitchell_clamp +@end example + @item Convert input to standard sRGB JPEG: @example diff --git a/libavfilter/vf_libplacebo.c b/libavfilter/vf_libplacebo.c index f8b93f975f0..94e49aa4652 100644 --- a/libavfilter/vf_libplacebo.c +++ b/libavfilter/vf_libplacebo.c @@ -164,6 +164,7 @@ typedef struct LibplaceboContext { struct pl_render_params params; char *upscaler; char *downscaler; + char *frame_mixer; int lut_entries; float antiringing; int sigmoid; @@ -285,17 +286,19 @@ static int parse_shader(AVFilterContext *avctx, const void *shader, size_t len) static int find_scaler(AVFilterContext *avctx, const struct pl_filter_config **opt, - const char *name) + const char *name, int frame_mixing) { - const struct pl_filter_preset *preset; + const struct pl_filter_preset *preset, *presets_avail; + presets_avail = frame_mixing ? pl_frame_mixers : pl_scale_filters; + if (!strcmp(name, "help")) { av_log(avctx, AV_LOG_INFO, "Available scaler presets:\n"); - for (preset = pl_scale_filters; preset->name; preset++) + for (preset = presets_avail; preset->name; preset++) av_log(avctx, AV_LOG_INFO, " %s\n", preset->name); return AVERROR_EXIT; } - for (preset = pl_scale_filters; preset->name; preset++) { + for (preset = presets_avail; preset->name; preset++) { if (!strcmp(name, preset->name)) { *opt = preset->filter; return 0; @@ -411,8 +414,9 @@ static int update_settings(AVFilterContext *ctx) .disable_fbos = s->disable_fbos, ); - RET(find_scaler(ctx, &s->params.upscaler, s->upscaler)); - RET(find_scaler(ctx, &s->params.downscaler, s->downscaler)); + RET(find_scaler(ctx, &s->params.upscaler, s->upscaler, 0)); + RET(find_scaler(ctx, &s->params.downscaler, s->downscaler, 0)); + RET(find_scaler(ctx, &s->params.frame_mixer, s->frame_mixer, 1)); return 0; fail: @@ -1110,6 +1114,7 @@ static const AVOption libplacebo_options[] = { { "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 }, + { "frame_mixer", "Frame mixing function", OFFSET(frame_mixer), AV_OPT_TYPE_STRING, {.str = "none"}, .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 }, From 7a63add0eaf0f890b4af990114710c6fabcfb4d7 Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Sun, 14 May 2023 12:15:20 +0200 Subject: [PATCH 0990/2172] avfilter/f_loop: add time option, for loop start in seconds --- doc/filters.texi | 8 ++++ libavfilter/f_loop.c | 89 ++++++++++++++++++++++++-------------------- 2 files changed, 57 insertions(+), 40 deletions(-) diff --git a/doc/filters.texi b/doc/filters.texi index 9ada73bab06..28acbe35095 100644 --- a/doc/filters.texi +++ b/doc/filters.texi @@ -2363,6 +2363,10 @@ Set maximal number of samples. Default is 0. @item start Set first sample of loop. Default is 0. + +@item time +Set the time of loop start in seconds. +Only used if option named @var{start} is set to @code{-1}. @end table @anchor{amerge} @@ -16759,6 +16763,10 @@ Set maximal size in number of frames. Default is 0. @item start Set first frame of loop. Default is 0. + +@item time +Set the time of loop start in seconds. +Only used if option named @var{start} is set to @code{-1}. @end table @subsection Examples diff --git a/libavfilter/f_loop.c b/libavfilter/f_loop.c index d217efe2fd0..5a91a0cbe9c 100644 --- a/libavfilter/f_loop.c +++ b/libavfilter/f_loop.c @@ -39,7 +39,7 @@ typedef struct LoopContext { AVFrame **frames; int nb_frames; int current_frame; - int64_t start_pts; + int64_t time_pts; int64_t duration; int64_t current_sample; int64_t nb_samples; @@ -49,7 +49,10 @@ typedef struct LoopContext { int eof; int64_t size; int64_t start; + int64_t time; int64_t pts; + int64_t pts_offset; + int64_t eof_pts; } LoopContext; #define AFLAGS AV_OPT_FLAG_AUDIO_PARAM|AV_OPT_FLAG_FILTERING_PARAM @@ -65,6 +68,17 @@ static void check_size(AVFilterContext *ctx) ctx->input_pads[0].type == AVMEDIA_TYPE_VIDEO ? "frames" : "samples"); } +static void update_time(AVFilterContext *ctx, AVRational tb) +{ + LoopContext *s = ctx->priv; + + if (s->time != INT64_MAX) { + int64_t time_pts = av_rescale_q(s->time, AV_TIME_BASE_Q, tb); + if (s->time_pts == AV_NOPTS_VALUE || time_pts < s->time_pts) + s->time_pts = time_pts; + } +} + #if CONFIG_ALOOP_FILTER static int aconfig_input(AVFilterLink *inlink) @@ -72,6 +86,8 @@ static int aconfig_input(AVFilterLink *inlink) AVFilterContext *ctx = inlink->dst; LoopContext *s = ctx->priv; + s->time_pts = AV_NOPTS_VALUE; + s->fifo = av_audio_fifo_alloc(inlink->format, inlink->ch_layout.nb_channels, 8192); s->left = av_audio_fifo_alloc(inlink->format, inlink->ch_layout.nb_channels, 8192); if (!s->fifo || !s->left) @@ -117,7 +133,6 @@ static int push_samples(AVFilterContext *ctx, int nb_samples) return ret; if (s->current_sample >= s->nb_samples) { - s->duration = s->pts; s->current_sample = 0; if (s->loop > 0) @@ -135,11 +150,17 @@ static int afilter_frame(AVFilterLink *inlink, AVFrame *frame) LoopContext *s = ctx->priv; int ret = 0; - if (s->ignored_samples + frame->nb_samples > s->start && s->size > 0 && s->loop != 0) { + if (((s->start >= 0 && s->ignored_samples + frame->nb_samples > s->start) || + (s->time_pts != AV_NOPTS_VALUE && + frame->pts >= s->time_pts)) && + s->size > 0 && s->loop != 0) { if (s->nb_samples < s->size) { int written = FFMIN(frame->nb_samples, s->size - s->nb_samples); int drain = 0; + if (s->start < 0) + s->start = inlink->sample_count_out - written; + ret = av_audio_fifo_write(s->fifo, (void **)frame->extended_data, written); if (ret < 0) return ret; @@ -221,10 +242,11 @@ static int aactivate(AVFilterContext *ctx) LoopContext *s = ctx->priv; AVFrame *frame = NULL; int ret, status; - int64_t pts; FF_FILTER_FORWARD_STATUS_BACK(outlink, inlink); + update_time(ctx, inlink->time_base); + if (!s->eof && (s->nb_samples < s->size || !s->loop || !s->size)) { ret = ff_inlink_consume_frame(inlink, &frame); if (ret < 0) @@ -233,7 +255,7 @@ static int aactivate(AVFilterContext *ctx) return afilter_frame(inlink, frame); } - if (!s->eof && ff_inlink_acknowledge_status(inlink, &status, &pts)) { + if (!s->eof && ff_inlink_acknowledge_status(inlink, &status, &s->eof_pts)) { if (status == AVERROR_EOF) { s->size = s->nb_samples; s->eof = 1; @@ -241,7 +263,7 @@ static int aactivate(AVFilterContext *ctx) } if (s->eof && (!s->loop || !s->size)) { - ff_outlink_set_status(outlink, AVERROR_EOF, s->duration); + ff_outlink_set_status(outlink, AVERROR_EOF, s->eof_pts + s->pts_offset); return 0; } @@ -259,7 +281,8 @@ static int aactivate(AVFilterContext *ctx) static const AVOption aloop_options[] = { { "loop", "number of loops", OFFSET(loop), AV_OPT_TYPE_INT, {.i64 = 0 }, -1, INT_MAX, AFLAGS }, { "size", "max number of samples to loop", OFFSET(size), AV_OPT_TYPE_INT64, {.i64 = 0 }, 0, INT32_MAX, AFLAGS }, - { "start", "set the loop start sample", OFFSET(start), AV_OPT_TYPE_INT64, {.i64 = 0 }, 0, INT64_MAX, AFLAGS }, + { "start", "set the loop start sample", OFFSET(start), AV_OPT_TYPE_INT64, {.i64 = 0 }, -1, INT64_MAX, AFLAGS }, + { "time", "set the loop start time", OFFSET(time), AV_OPT_TYPE_DURATION, {.i64=INT64_MAX}, INT64_MIN, INT64_MAX, AFLAGS }, { NULL } }; @@ -298,6 +321,8 @@ static av_cold int init(AVFilterContext *ctx) { LoopContext *s = ctx->priv; + s->time_pts = AV_NOPTS_VALUE; + s->frames = av_calloc(s->size, sizeof(*s->frames)); if (!s->frames) return AVERROR(ENOMEM); @@ -323,33 +348,20 @@ static int push_frame(AVFilterContext *ctx) { AVFilterLink *outlink = ctx->outputs[0]; LoopContext *s = ctx->priv; - int64_t pts, duration; + AVFrame *out; int ret; - AVFrame *out = av_frame_clone(s->frames[s->current_frame]); - + out = av_frame_clone(s->frames[s->current_frame]); if (!out) return AVERROR(ENOMEM); - out->pts += s->duration - s->start_pts; -#if FF_API_PKT_DURATION -FF_DISABLE_DEPRECATION_WARNINGS - if (out->pkt_duration) - duration = out->pkt_duration; - else -FF_ENABLE_DEPRECATION_WARNINGS -#endif - if (out->duration) - duration = out->duration; - else - duration = av_rescale_q(1, av_inv_q(outlink->frame_rate), outlink->time_base); - pts = out->pts + duration; + out->pts += s->pts_offset; ret = ff_filter_frame(outlink, out); s->current_frame++; if (s->current_frame >= s->nb_frames) { - s->duration = pts; s->current_frame = 0; + s->pts_offset += s->duration; if (s->loop > 0) s->loop--; } @@ -365,35 +377,30 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *frame) int64_t duration; int ret = 0; - if (inlink->frame_count_out >= s->start && s->size > 0 && s->loop != 0) { + if (((s->start >= 0 && inlink->frame_count_out >= s->start) || + (s->time_pts != AV_NOPTS_VALUE && + frame->pts >= s->time_pts)) && + s->size > 0 && s->loop != 0) { if (s->nb_frames < s->size) { - if (!s->nb_frames) - s->start_pts = frame->pts; s->frames[s->nb_frames] = av_frame_clone(frame); if (!s->frames[s->nb_frames]) { av_frame_free(&frame); return AVERROR(ENOMEM); } s->nb_frames++; -#if FF_API_PKT_DURATION -FF_DISABLE_DEPRECATION_WARNINGS - if (frame->pkt_duration) - duration = frame->pkt_duration; - else -FF_ENABLE_DEPRECATION_WARNINGS -#endif if (frame->duration) duration = frame->duration; else duration = av_rescale_q(1, av_inv_q(outlink->frame_rate), outlink->time_base); - s->duration = frame->pts + duration; + s->duration += duration; + s->pts_offset = s->duration; ret = ff_filter_frame(outlink, frame); } else { av_frame_free(&frame); ret = push_frame(ctx); } } else { - frame->pts += s->duration; + frame->pts += s->pts_offset - s->duration; ret = ff_filter_frame(outlink, frame); } @@ -407,10 +414,11 @@ static int activate(AVFilterContext *ctx) LoopContext *s = ctx->priv; AVFrame *frame = NULL; int ret, status; - int64_t pts; FF_FILTER_FORWARD_STATUS_BACK(outlink, inlink); + update_time(ctx, inlink->time_base); + if (!s->eof && (s->nb_frames < s->size || !s->loop || !s->size)) { ret = ff_inlink_consume_frame(inlink, &frame); if (ret < 0) @@ -419,7 +427,7 @@ static int activate(AVFilterContext *ctx) return filter_frame(inlink, frame); } - if (!s->eof && ff_inlink_acknowledge_status(inlink, &status, &pts)) { + if (!s->eof && ff_inlink_acknowledge_status(inlink, &status, &s->eof_pts)) { if (status == AVERROR_EOF) { s->size = s->nb_frames; s->eof = 1; @@ -427,7 +435,7 @@ static int activate(AVFilterContext *ctx) } if (s->eof && (!s->loop || !s->size)) { - ff_outlink_set_status(outlink, AVERROR_EOF, s->duration); + ff_outlink_set_status(outlink, AVERROR_EOF, s->eof_pts + s->pts_offset); return 0; } @@ -445,7 +453,8 @@ static int activate(AVFilterContext *ctx) static const AVOption loop_options[] = { { "loop", "number of loops", OFFSET(loop), AV_OPT_TYPE_INT, {.i64 = 0 }, -1, INT_MAX, VFLAGS }, { "size", "max number of frames to loop", OFFSET(size), AV_OPT_TYPE_INT64, {.i64 = 0 }, 0, INT16_MAX, VFLAGS }, - { "start", "set the loop start frame", OFFSET(start), AV_OPT_TYPE_INT64, {.i64 = 0 }, 0, INT64_MAX, VFLAGS }, + { "start", "set the loop start frame", OFFSET(start), AV_OPT_TYPE_INT64, {.i64 = 0 }, -1, INT64_MAX, VFLAGS }, + { "time", "set the loop start time", OFFSET(time), AV_OPT_TYPE_DURATION, {.i64=INT64_MAX}, INT64_MIN, INT64_MAX, VFLAGS }, { NULL } }; From 8041d002715bc499655c28481ed6c0bc74edc1b9 Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Sun, 14 May 2023 13:57:07 +0200 Subject: [PATCH 0991/2172] avfilter/f_loop: fix looping for aloop --- libavfilter/f_loop.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/libavfilter/f_loop.c b/libavfilter/f_loop.c index 5a91a0cbe9c..7974d266f0c 100644 --- a/libavfilter/f_loop.c +++ b/libavfilter/f_loop.c @@ -248,7 +248,11 @@ static int aactivate(AVFilterContext *ctx) update_time(ctx, inlink->time_base); if (!s->eof && (s->nb_samples < s->size || !s->loop || !s->size)) { - ret = ff_inlink_consume_frame(inlink, &frame); + const int in_nb_samples = FFMIN(1024, s->size - s->nb_samples); + if (in_nb_samples == 0) + ret = ff_inlink_consume_frame(inlink, &frame); + else + ret = ff_inlink_consume_samples(inlink, in_nb_samples, in_nb_samples, &frame); if (ret < 0) return ret; if (ret > 0) From 6eecfc577bca1cfd1f734241c438b79c6979aff5 Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Sun, 14 May 2023 14:08:36 +0200 Subject: [PATCH 0992/2172] avfilter/f_graphmonitor: rename enums --- libavfilter/f_graphmonitor.c | 105 ++++++++++++++++++----------------- 1 file changed, 53 insertions(+), 52 deletions(-) diff --git a/libavfilter/f_graphmonitor.c b/libavfilter/f_graphmonitor.c index 016a707a27a..9a569de279c 100644 --- a/libavfilter/f_graphmonitor.c +++ b/libavfilter/f_graphmonitor.c @@ -62,22 +62,22 @@ typedef struct GraphMonitorContext { } GraphMonitorContext; enum { - MODE_QUEUE = 1 << 0, - MODE_FCIN = 1 << 1, - MODE_FCOUT = 1 << 2, - MODE_PTS = 1 << 3, - MODE_TIME = 1 << 4, - MODE_TB = 1 << 5, - MODE_FMT = 1 << 6, - MODE_SIZE = 1 << 7, - MODE_RATE = 1 << 8, - MODE_EOF = 1 << 9, - MODE_SCIN = 1 << 10, - MODE_SCOUT = 1 << 11, - MODE_PTS_DELTA = 1 << 12, - MODE_TIME_DELTA = 1 << 13, - MODE_FC_DELTA = 1 << 14, - MODE_SC_DELTA = 1 << 15, + FLAG_QUEUE = 1 << 0, + FLAG_FCIN = 1 << 1, + FLAG_FCOUT = 1 << 2, + FLAG_PTS = 1 << 3, + FLAG_TIME = 1 << 4, + FLAG_TB = 1 << 5, + FLAG_FMT = 1 << 6, + FLAG_SIZE = 1 << 7, + FLAG_RATE = 1 << 8, + FLAG_EOF = 1 << 9, + FLAG_SCIN = 1 << 10, + FLAG_SCOUT = 1 << 11, + FLAG_PTS_DELTA = 1 << 12, + FLAG_TIME_DELTA = 1 << 13, + FLAG_FC_DELTA = 1 << 14, + FLAG_SC_DELTA = 1 << 15, }; #define OFFSET(x) offsetof(GraphMonitorContext, x) @@ -88,28 +88,29 @@ static const AVOption graphmonitor_options[] = { { "s", "set monitor size", OFFSET(w), AV_OPT_TYPE_IMAGE_SIZE, {.str="hd720"}, 0, 0, VF }, { "opacity", "set video opacity", OFFSET(opacity), AV_OPT_TYPE_FLOAT, {.dbl=.9}, 0, 1, VF }, { "o", "set video opacity", OFFSET(opacity), AV_OPT_TYPE_FLOAT, {.dbl=.9}, 0, 1, VF }, - { "mode", "set mode", OFFSET(mode), AV_OPT_TYPE_INT, {.i64=0}, 0, 1, VF, "mode" }, - { "m", "set mode", OFFSET(mode), AV_OPT_TYPE_INT, {.i64=0}, 0, 1, VF, "mode" }, + { "mode", "set mode", OFFSET(mode), AV_OPT_TYPE_INT, {.i64=0}, 0, 2, VF, "mode" }, + { "m", "set mode", OFFSET(mode), AV_OPT_TYPE_INT, {.i64=0}, 0, 2, VF, "mode" }, { "full", NULL, 0, AV_OPT_TYPE_CONST, {.i64=0}, 0, 0, VF, "mode" }, { "compact", NULL, 0, AV_OPT_TYPE_CONST, {.i64=1}, 0, 0, VF, "mode" }, - { "flags", "set flags", OFFSET(flags), AV_OPT_TYPE_FLAGS, {.i64=MODE_QUEUE}, 0, INT_MAX, VF, "flags" }, - { "f", "set flags", OFFSET(flags), AV_OPT_TYPE_FLAGS, {.i64=MODE_QUEUE}, 0, INT_MAX, VF, "flags" }, - { "queue", NULL, 0, AV_OPT_TYPE_CONST, {.i64=MODE_QUEUE}, 0, 0, VF, "flags" }, - { "frame_count_in", NULL, 0, AV_OPT_TYPE_CONST, {.i64=MODE_FCOUT}, 0, 0, VF, "flags" }, - { "frame_count_out", NULL, 0, AV_OPT_TYPE_CONST, {.i64=MODE_FCIN}, 0, 0, VF, "flags" }, - { "frame_count_delta",NULL, 0, AV_OPT_TYPE_CONST, {.i64=MODE_FC_DELTA},0, 0, VF, "flags" }, - { "pts", NULL, 0, AV_OPT_TYPE_CONST, {.i64=MODE_PTS}, 0, 0, VF, "flags" }, - { "pts_delta", NULL, 0, AV_OPT_TYPE_CONST, {.i64=MODE_PTS_DELTA},0,0, VF, "flags" }, - { "time", NULL, 0, AV_OPT_TYPE_CONST, {.i64=MODE_TIME}, 0, 0, VF, "flags" }, - { "time_delta", NULL, 0, AV_OPT_TYPE_CONST, {.i64=MODE_TIME_DELTA},0,0,VF, "flags" }, - { "timebase", NULL, 0, AV_OPT_TYPE_CONST, {.i64=MODE_TB}, 0, 0, VF, "flags" }, - { "format", NULL, 0, AV_OPT_TYPE_CONST, {.i64=MODE_FMT}, 0, 0, VF, "flags" }, - { "size", NULL, 0, AV_OPT_TYPE_CONST, {.i64=MODE_SIZE}, 0, 0, VF, "flags" }, - { "rate", NULL, 0, AV_OPT_TYPE_CONST, {.i64=MODE_RATE}, 0, 0, VF, "flags" }, - { "eof", NULL, 0, AV_OPT_TYPE_CONST, {.i64=MODE_EOF}, 0, 0, VF, "flags" }, - { "sample_count_in", NULL, 0, AV_OPT_TYPE_CONST, {.i64=MODE_SCOUT}, 0, 0, VF, "flags" }, - { "sample_count_out", NULL, 0, AV_OPT_TYPE_CONST, {.i64=MODE_SCIN}, 0, 0, VF, "flags" }, - { "sample_count_delta",NULL,0, AV_OPT_TYPE_CONST, {.i64=MODE_SC_DELTA},0, 0, VF, "flags" }, + { "nozero", NULL, 0, AV_OPT_TYPE_CONST, {.i64=2}, 0, 0, VF, "mode" }, + { "flags", "set flags", OFFSET(flags), AV_OPT_TYPE_FLAGS, {.i64=FLAG_QUEUE}, 0, INT_MAX, VF, "flags" }, + { "f", "set flags", OFFSET(flags), AV_OPT_TYPE_FLAGS, {.i64=FLAG_QUEUE}, 0, INT_MAX, VF, "flags" }, + { "queue", NULL, 0, AV_OPT_TYPE_CONST, {.i64=FLAG_QUEUE}, 0, 0, VF, "flags" }, + { "frame_count_in", NULL, 0, AV_OPT_TYPE_CONST, {.i64=FLAG_FCOUT}, 0, 0, VF, "flags" }, + { "frame_count_out", NULL, 0, AV_OPT_TYPE_CONST, {.i64=FLAG_FCIN}, 0, 0, VF, "flags" }, + { "frame_count_delta",NULL, 0, AV_OPT_TYPE_CONST, {.i64=FLAG_FC_DELTA},0, 0, VF, "flags" }, + { "pts", NULL, 0, AV_OPT_TYPE_CONST, {.i64=FLAG_PTS}, 0, 0, VF, "flags" }, + { "pts_delta", NULL, 0, AV_OPT_TYPE_CONST, {.i64=FLAG_PTS_DELTA},0,0, VF, "flags" }, + { "time", NULL, 0, AV_OPT_TYPE_CONST, {.i64=FLAG_TIME}, 0, 0, VF, "flags" }, + { "time_delta", NULL, 0, AV_OPT_TYPE_CONST, {.i64=FLAG_TIME_DELTA},0,0,VF, "flags" }, + { "timebase", NULL, 0, AV_OPT_TYPE_CONST, {.i64=FLAG_TB}, 0, 0, VF, "flags" }, + { "format", NULL, 0, AV_OPT_TYPE_CONST, {.i64=FLAG_FMT}, 0, 0, VF, "flags" }, + { "size", NULL, 0, AV_OPT_TYPE_CONST, {.i64=FLAG_SIZE}, 0, 0, VF, "flags" }, + { "rate", NULL, 0, AV_OPT_TYPE_CONST, {.i64=FLAG_RATE}, 0, 0, VF, "flags" }, + { "eof", NULL, 0, AV_OPT_TYPE_CONST, {.i64=FLAG_EOF}, 0, 0, VF, "flags" }, + { "sample_count_in", NULL, 0, AV_OPT_TYPE_CONST, {.i64=FLAG_SCOUT}, 0, 0, VF, "flags" }, + { "sample_count_out", NULL, 0, AV_OPT_TYPE_CONST, {.i64=FLAG_SCIN}, 0, 0, VF, "flags" }, + { "sample_count_delta",NULL,0, AV_OPT_TYPE_CONST, {.i64=FLAG_SC_DELTA},0, 0, VF, "flags" }, { "rate", "set video rate", OFFSET(frame_rate), AV_OPT_TYPE_VIDEO_RATE, {.str = "25"}, 0, INT_MAX, VF }, { "r", "set video rate", OFFSET(frame_rate), AV_OPT_TYPE_VIDEO_RATE, {.str = "25"}, 0, INT_MAX, VF }, { NULL } @@ -213,7 +214,7 @@ static int draw_items(AVFilterContext *ctx, AVFrame *out, int64_t current_pts_us = l->current_pts_us; char buffer[1024] = { 0 }; - if (s->flags & MODE_FMT) { + if (s->flags & FLAG_FMT) { if (l->type == AVMEDIA_TYPE_VIDEO) { snprintf(buffer, sizeof(buffer)-1, " | format: %s", av_get_pix_fmt_name(l->format)); @@ -224,7 +225,7 @@ static int draw_items(AVFilterContext *ctx, AVFrame *out, drawtext(out, xpos, ypos, buffer, s->white); xpos += strlen(buffer) * 8; } - if (s->flags & MODE_SIZE) { + if (s->flags & FLAG_SIZE) { if (l->type == AVMEDIA_TYPE_VIDEO) { snprintf(buffer, sizeof(buffer)-1, " | size: %dx%d", l->w, l->h); } else if (l->type == AVMEDIA_TYPE_AUDIO) { @@ -233,7 +234,7 @@ static int draw_items(AVFilterContext *ctx, AVFrame *out, drawtext(out, xpos, ypos, buffer, s->white); xpos += strlen(buffer) * 8; } - if (s->flags & MODE_RATE) { + if (s->flags & FLAG_RATE) { if (l->type == AVMEDIA_TYPE_VIDEO) { snprintf(buffer, sizeof(buffer)-1, " | fps: %d/%d", l->frame_rate.num, l->frame_rate.den); } else if (l->type == AVMEDIA_TYPE_AUDIO) { @@ -242,12 +243,12 @@ static int draw_items(AVFilterContext *ctx, AVFrame *out, drawtext(out, xpos, ypos, buffer, s->white); xpos += strlen(buffer) * 8; } - if (s->flags & MODE_TB) { + if (s->flags & FLAG_TB) { snprintf(buffer, sizeof(buffer)-1, " | tb: %d/%d", l->time_base.num, l->time_base.den); drawtext(out, xpos, ypos, buffer, s->white); xpos += strlen(buffer) * 8; } - if (s->flags & MODE_QUEUE) { + if (s->flags & FLAG_QUEUE) { snprintf(buffer, sizeof(buffer)-1, " | queue: "); drawtext(out, xpos, ypos, buffer, s->white); xpos += strlen(buffer) * 8; @@ -255,57 +256,57 @@ static int draw_items(AVFilterContext *ctx, AVFrame *out, drawtext(out, xpos, ypos, buffer, frames > 0 ? frames >= 10 ? frames >= 50 ? s->red : s->yellow : s->green : s->white); xpos += strlen(buffer) * 8; } - if (s->flags & MODE_FCIN) { + if (s->flags & FLAG_FCIN) { snprintf(buffer, sizeof(buffer)-1, " | in: %"PRId64, l->frame_count_in); drawtext(out, xpos, ypos, buffer, s->white); xpos += strlen(buffer) * 8; } - if (s->flags & MODE_FCOUT) { + if (s->flags & FLAG_FCOUT) { snprintf(buffer, sizeof(buffer)-1, " | out: %"PRId64, l->frame_count_out); drawtext(out, xpos, ypos, buffer, s->white); xpos += strlen(buffer) * 8; } - if (s->flags & MODE_FC_DELTA) { + if (s->flags & FLAG_FC_DELTA) { snprintf(buffer, sizeof(buffer)-1, " | delta: %"PRId64, l->frame_count_in - l->frame_count_out); drawtext(out, xpos, ypos, buffer, s->white); xpos += strlen(buffer) * 8; } - if (s->flags & MODE_SCIN) { + if (s->flags & FLAG_SCIN) { snprintf(buffer, sizeof(buffer)-1, " | sin: %"PRId64, l->sample_count_in); drawtext(out, xpos, ypos, buffer, s->white); xpos += strlen(buffer) * 8; } - if (s->flags & MODE_SCOUT) { + if (s->flags & FLAG_SCOUT) { snprintf(buffer, sizeof(buffer)-1, " | sout: %"PRId64, l->sample_count_out); drawtext(out, xpos, ypos, buffer, s->white); xpos += strlen(buffer) * 8; } - if (s->flags & MODE_SC_DELTA) { + if (s->flags & FLAG_SC_DELTA) { snprintf(buffer, sizeof(buffer)-1, " | sdelta: %"PRId64, l->sample_count_in - l->sample_count_out); drawtext(out, xpos, ypos, buffer, s->white); xpos += strlen(buffer) * 8; } - if (s->flags & MODE_PTS) { + if (s->flags & FLAG_PTS) { snprintf(buffer, sizeof(buffer)-1, " | pts: %s", av_ts2str(current_pts_us)); drawtext(out, xpos, ypos, buffer, s->white); xpos += strlen(buffer) * 8; } - if (s->flags & MODE_PTS_DELTA) { + if (s->flags & FLAG_PTS_DELTA) { snprintf(buffer, sizeof(buffer)-1, " | pts_delta: %s", av_ts2str(current_pts_us - previous_pts_us)); drawtext(out, xpos, ypos, buffer, s->white); xpos += strlen(buffer) * 8; } - if (s->flags & MODE_TIME) { + if (s->flags & FLAG_TIME) { snprintf(buffer, sizeof(buffer)-1, " | time: %s", av_ts2timestr(current_pts_us, &AV_TIME_BASE_Q)); drawtext(out, xpos, ypos, buffer, s->white); xpos += strlen(buffer) * 8; } - if (s->flags & MODE_TIME_DELTA) { + if (s->flags & FLAG_TIME_DELTA) { snprintf(buffer, sizeof(buffer)-1, " | time_delta: %s", av_ts2timestr(current_pts_us - previous_pts_us, &AV_TIME_BASE_Q)); drawtext(out, xpos, ypos, buffer, s->white); xpos += strlen(buffer) * 8; } - if (s->flags & MODE_EOF && ff_outlink_get_status(l)) { + if (s->flags & FLAG_EOF && ff_outlink_get_status(l)) { snprintf(buffer, sizeof(buffer)-1, " | eof"); drawtext(out, xpos, ypos, buffer, s->blue); xpos += strlen(buffer) * 8; From c27895bb9865fa274e66aa67ec7df574a104da69 Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Sun, 14 May 2023 14:31:21 +0200 Subject: [PATCH 0993/2172] avfilter/f_graphmonitor: add nozero display mode --- doc/filters.texi | 3 ++- libavfilter/f_graphmonitor.c | 45 +++++++++++++++++++++--------------- 2 files changed, 28 insertions(+), 20 deletions(-) diff --git a/doc/filters.texi b/doc/filters.texi index 28acbe35095..d935e62b3f6 100644 --- a/doc/filters.texi +++ b/doc/filters.texi @@ -14639,8 +14639,9 @@ Set video output size. Default is @var{hd720}. Set video opacity. Default is @var{0.9}. Allowed range is from @var{0} to @var{1}. @item mode, m -Set output mode, can be @var{fulll} or @var{compact}. +Set output mode, can be @var{full} or @var{compact} or @var{nozero}. In @var{compact} mode only filters with some queued frames have displayed stats. +In @var{nozero} mode only non-zero stats values are displayed. @item flags, f Set flags which enable which stats are shown in video. diff --git a/libavfilter/f_graphmonitor.c b/libavfilter/f_graphmonitor.c index 9a569de279c..de9aa395fe7 100644 --- a/libavfilter/f_graphmonitor.c +++ b/libavfilter/f_graphmonitor.c @@ -61,6 +61,13 @@ typedef struct GraphMonitorContext { unsigned int cache_index; } GraphMonitorContext; +enum { + MODE_FULL, + MODE_COMPACT, + MODE_NOZERO, + NB_MODES +}; + enum { FLAG_QUEUE = 1 << 0, FLAG_FCIN = 1 << 1, @@ -88,11 +95,11 @@ static const AVOption graphmonitor_options[] = { { "s", "set monitor size", OFFSET(w), AV_OPT_TYPE_IMAGE_SIZE, {.str="hd720"}, 0, 0, VF }, { "opacity", "set video opacity", OFFSET(opacity), AV_OPT_TYPE_FLOAT, {.dbl=.9}, 0, 1, VF }, { "o", "set video opacity", OFFSET(opacity), AV_OPT_TYPE_FLOAT, {.dbl=.9}, 0, 1, VF }, - { "mode", "set mode", OFFSET(mode), AV_OPT_TYPE_INT, {.i64=0}, 0, 2, VF, "mode" }, - { "m", "set mode", OFFSET(mode), AV_OPT_TYPE_INT, {.i64=0}, 0, 2, VF, "mode" }, - { "full", NULL, 0, AV_OPT_TYPE_CONST, {.i64=0}, 0, 0, VF, "mode" }, - { "compact", NULL, 0, AV_OPT_TYPE_CONST, {.i64=1}, 0, 0, VF, "mode" }, - { "nozero", NULL, 0, AV_OPT_TYPE_CONST, {.i64=2}, 0, 0, VF, "mode" }, + { "mode", "set mode", OFFSET(mode), AV_OPT_TYPE_INT, {.i64=0}, 0, NB_MODES-1, VF, "mode" }, + { "m", "set mode", OFFSET(mode), AV_OPT_TYPE_INT, {.i64=0}, 0, NB_MODES-1, VF, "mode" }, + { "full", NULL, 0, AV_OPT_TYPE_CONST, {.i64=MODE_FULL}, 0, 0, VF, "mode" }, + { "compact", NULL, 0, AV_OPT_TYPE_CONST, {.i64=MODE_COMPACT},0, 0, VF, "mode" }, + { "nozero", NULL, 0, AV_OPT_TYPE_CONST, {.i64=MODE_NOZERO}, 0, 0, VF, "mode" }, { "flags", "set flags", OFFSET(flags), AV_OPT_TYPE_FLAGS, {.i64=FLAG_QUEUE}, 0, INT_MAX, VF, "flags" }, { "f", "set flags", OFFSET(flags), AV_OPT_TYPE_FLAGS, {.i64=FLAG_QUEUE}, 0, INT_MAX, VF, "flags" }, { "queue", NULL, 0, AV_OPT_TYPE_CONST, {.i64=FLAG_QUEUE}, 0, 0, VF, "flags" }, @@ -248,7 +255,7 @@ static int draw_items(AVFilterContext *ctx, AVFrame *out, drawtext(out, xpos, ypos, buffer, s->white); xpos += strlen(buffer) * 8; } - if (s->flags & FLAG_QUEUE) { + if ((s->flags & FLAG_QUEUE) && (s->mode != MODE_NOZERO || frames)) { snprintf(buffer, sizeof(buffer)-1, " | queue: "); drawtext(out, xpos, ypos, buffer, s->white); xpos += strlen(buffer) * 8; @@ -256,52 +263,52 @@ static int draw_items(AVFilterContext *ctx, AVFrame *out, drawtext(out, xpos, ypos, buffer, frames > 0 ? frames >= 10 ? frames >= 50 ? s->red : s->yellow : s->green : s->white); xpos += strlen(buffer) * 8; } - if (s->flags & FLAG_FCIN) { + if ((s->flags & FLAG_FCIN) && (s->mode != MODE_NOZERO || l->frame_count_in)) { snprintf(buffer, sizeof(buffer)-1, " | in: %"PRId64, l->frame_count_in); drawtext(out, xpos, ypos, buffer, s->white); xpos += strlen(buffer) * 8; } - if (s->flags & FLAG_FCOUT) { + if ((s->flags & FLAG_FCOUT) && (s->mode != MODE_NOZERO || l->frame_count_out)) { snprintf(buffer, sizeof(buffer)-1, " | out: %"PRId64, l->frame_count_out); drawtext(out, xpos, ypos, buffer, s->white); xpos += strlen(buffer) * 8; } - if (s->flags & FLAG_FC_DELTA) { + if ((s->flags & FLAG_FC_DELTA) && (s->mode != MODE_NOZERO || (l->frame_count_in - l->frame_count_out))) { snprintf(buffer, sizeof(buffer)-1, " | delta: %"PRId64, l->frame_count_in - l->frame_count_out); drawtext(out, xpos, ypos, buffer, s->white); xpos += strlen(buffer) * 8; } - if (s->flags & FLAG_SCIN) { + if ((s->flags & FLAG_SCIN) && (s->mode != MODE_NOZERO || l->sample_count_in)) { snprintf(buffer, sizeof(buffer)-1, " | sin: %"PRId64, l->sample_count_in); drawtext(out, xpos, ypos, buffer, s->white); xpos += strlen(buffer) * 8; } - if (s->flags & FLAG_SCOUT) { + if ((s->flags & FLAG_SCOUT) && (s->mode != MODE_NOZERO || l->sample_count_out)) { snprintf(buffer, sizeof(buffer)-1, " | sout: %"PRId64, l->sample_count_out); drawtext(out, xpos, ypos, buffer, s->white); xpos += strlen(buffer) * 8; } - if (s->flags & FLAG_SC_DELTA) { + if ((s->flags & FLAG_SC_DELTA) && (s->mode != MODE_NOZERO || (l->sample_count_in - l->sample_count_out))) { snprintf(buffer, sizeof(buffer)-1, " | sdelta: %"PRId64, l->sample_count_in - l->sample_count_out); drawtext(out, xpos, ypos, buffer, s->white); xpos += strlen(buffer) * 8; } - if (s->flags & FLAG_PTS) { + if ((s->flags & FLAG_PTS) && (s->mode != MODE_NOZERO || current_pts_us)) { snprintf(buffer, sizeof(buffer)-1, " | pts: %s", av_ts2str(current_pts_us)); drawtext(out, xpos, ypos, buffer, s->white); xpos += strlen(buffer) * 8; } - if (s->flags & FLAG_PTS_DELTA) { + if ((s->flags & FLAG_PTS_DELTA) && (s->mode != MODE_NOZERO || (current_pts_us - previous_pts_us))) { snprintf(buffer, sizeof(buffer)-1, " | pts_delta: %s", av_ts2str(current_pts_us - previous_pts_us)); drawtext(out, xpos, ypos, buffer, s->white); xpos += strlen(buffer) * 8; } - if (s->flags & FLAG_TIME) { + if ((s->flags & FLAG_TIME) && (s->mode != MODE_NOZERO || current_pts_us)) { snprintf(buffer, sizeof(buffer)-1, " | time: %s", av_ts2timestr(current_pts_us, &AV_TIME_BASE_Q)); drawtext(out, xpos, ypos, buffer, s->white); xpos += strlen(buffer) * 8; } - if (s->flags & FLAG_TIME_DELTA) { + if ((s->flags & FLAG_TIME_DELTA) && (s->mode != MODE_NOZERO || (current_pts_us - previous_pts_us))) { snprintf(buffer, sizeof(buffer)-1, " | time_delta: %s", av_ts2timestr(current_pts_us - previous_pts_us, &AV_TIME_BASE_Q)); drawtext(out, xpos, ypos, buffer, s->white); xpos += strlen(buffer) * 8; @@ -345,7 +352,7 @@ static int create_frame(AVFilterContext *ctx, int64_t pts) AVFilterContext *filter = ctx->graph->filters[i]; char buffer[1024] = { 0 }; - if (s->mode && !filter_have_queued(filter)) + if (s->mode == MODE_COMPACT && !filter_have_queued(filter)) continue; xpos = 0; @@ -357,7 +364,7 @@ static int create_frame(AVFilterContext *ctx, int64_t pts) AVFilterLink *l = filter->inputs[j]; size_t frames = ff_inlink_queued_frames(l); - if (s->mode && !frames) + if (s->mode == MODE_COMPACT && !frames) continue; xpos = 10; @@ -377,7 +384,7 @@ static int create_frame(AVFilterContext *ctx, int64_t pts) AVFilterLink *l = filter->outputs[j]; size_t frames = ff_inlink_queued_frames(l); - if (s->mode && !frames) + if (s->mode == MODE_COMPACT && !frames) continue; xpos = 10; From 932ccf9e7d159887766fa9a1f3ef171b8a89a3dd Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Sun, 14 May 2023 14:41:38 +0200 Subject: [PATCH 0994/2172] avfilter/f_loop: free video frames once not needed --- libavfilter/f_loop.c | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/libavfilter/f_loop.c b/libavfilter/f_loop.c index 7974d266f0c..33b66fa534e 100644 --- a/libavfilter/f_loop.c +++ b/libavfilter/f_loop.c @@ -336,14 +336,19 @@ static av_cold int init(AVFilterContext *ctx) return 0; } -static av_cold void uninit(AVFilterContext *ctx) +static void free_frames(AVFilterContext *ctx) { LoopContext *s = ctx->priv; - int i; - for (i = 0; i < s->nb_frames; i++) + for (int i = 0; i < s->nb_frames; i++) av_frame_free(&s->frames[i]); +} +static av_cold void uninit(AVFilterContext *ctx) +{ + LoopContext *s = ctx->priv; + + free_frames(ctx); av_freep(&s->frames); s->nb_frames = 0; } @@ -368,6 +373,8 @@ static int push_frame(AVFilterContext *ctx) s->pts_offset += s->duration; if (s->loop > 0) s->loop--; + if (s->loop == 0) + free_frames(ctx); } return ret; @@ -419,7 +426,12 @@ static int activate(AVFilterContext *ctx) AVFrame *frame = NULL; int ret, status; - FF_FILTER_FORWARD_STATUS_BACK(outlink, inlink); + ret = ff_outlink_get_status(outlink); + if (ret) { + ff_inlink_set_status(inlink, ret); + free_frames(ctx); + return 0; + } update_time(ctx, inlink->time_base); @@ -440,6 +452,7 @@ static int activate(AVFilterContext *ctx) if (s->eof && (!s->loop || !s->size)) { ff_outlink_set_status(outlink, AVERROR_EOF, s->eof_pts + s->pts_offset); + free_frames(ctx); return 0; } From 66175c2dca357bc6c856249c934f96b9ca023aa4 Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Sun, 14 May 2023 20:47:08 +0200 Subject: [PATCH 0995/2172] avfilter/f_graphmonitor: set output frame duration --- libavfilter/f_graphmonitor.c | 1 + 1 file changed, 1 insertion(+) diff --git a/libavfilter/f_graphmonitor.c b/libavfilter/f_graphmonitor.c index de9aa395fe7..d48f9fd9903 100644 --- a/libavfilter/f_graphmonitor.c +++ b/libavfilter/f_graphmonitor.c @@ -402,6 +402,7 @@ static int create_frame(AVFilterContext *ctx, int64_t pts) } out->pts = pts; + out->duration = 1; s->pts = pts + 1; return ff_filter_frame(outlink, out); error: From 6759983bdce1f157a19f94e881a2bc751970a5bc Mon Sep 17 00:00:00 2001 From: James Almer Date: Sun, 14 May 2023 17:09:38 -0300 Subject: [PATCH 0996/2172] avcodec/cbs_av1: add valid range of values for num_units_in_decoding_tick The spec states "num_units_in_decoding_tick shall be greater than 0". Signed-off-by: James Almer --- libavcodec/cbs_av1_syntax_template.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavcodec/cbs_av1_syntax_template.c b/libavcodec/cbs_av1_syntax_template.c index e95925a493e..7d160474546 100644 --- a/libavcodec/cbs_av1_syntax_template.c +++ b/libavcodec/cbs_av1_syntax_template.c @@ -176,7 +176,7 @@ static int FUNC(decoder_model_info)(CodedBitstreamContext *ctx, RWContext *rw, int err; fb(5, buffer_delay_length_minus_1); - fb(32, num_units_in_decoding_tick); + fc(32, num_units_in_decoding_tick, 1, MAX_UINT_BITS(32)); fb(5, buffer_removal_time_length_minus_1); fb(5, frame_presentation_time_length_minus_1); From 2a74826b027cb031acdf1f85519ba61cca932509 Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Sun, 14 May 2023 22:33:37 +0200 Subject: [PATCH 0997/2172] avfilter/*xfade: reduce memory consumption There is no always need for new buffers. --- libavfilter/af_afade.c | 13 +++++++++++++ libavfilter/vf_xfade.c | 11 +++++++++++ 2 files changed, 24 insertions(+) diff --git a/libavfilter/af_afade.c b/libavfilter/af_afade.c index 48938384ffc..2f45b129048 100644 --- a/libavfilter/af_afade.c +++ b/libavfilter/af_afade.c @@ -672,14 +672,27 @@ static int acrossfade_config_output(AVFilterLink *outlink) return 0; } +static AVFrame *get_audio_buffer(AVFilterLink *inlink, int nb_samples) +{ + AVFilterContext *ctx = inlink->dst; + AudioFadeContext *s = ctx->priv; + + return (s->crossfade_is_over || + (ff_inlink_queued_samples(inlink) > s->nb_samples)) ? + ff_null_get_audio_buffer (inlink, nb_samples) : + ff_default_get_audio_buffer(inlink, nb_samples); +} + static const AVFilterPad avfilter_af_acrossfade_inputs[] = { { .name = "crossfade0", .type = AVMEDIA_TYPE_AUDIO, + .get_buffer.audio = get_audio_buffer, }, { .name = "crossfade1", .type = AVMEDIA_TYPE_AUDIO, + .get_buffer.audio = get_audio_buffer, }, }; diff --git a/libavfilter/vf_xfade.c b/libavfilter/vf_xfade.c index 9f669273657..5745a241733 100644 --- a/libavfilter/vf_xfade.c +++ b/libavfilter/vf_xfade.c @@ -2042,14 +2042,25 @@ static int xfade_activate(AVFilterContext *ctx) return FFERROR_NOT_READY; } +static AVFrame *get_video_buffer(AVFilterLink *inlink, int w, int h) +{ + XFadeContext *s = inlink->dst->priv; + + return s->xfade_is_over || !s->need_second ? + ff_null_get_video_buffer (inlink, w, h) : + ff_default_get_video_buffer(inlink, w, h); +} + static const AVFilterPad xfade_inputs[] = { { .name = "main", .type = AVMEDIA_TYPE_VIDEO, + .get_buffer.video = get_video_buffer, }, { .name = "xfade", .type = AVMEDIA_TYPE_VIDEO, + .get_buffer.video = get_video_buffer, }, }; From a7b06bfc5d20b12ff0122702c09517cf359fbb66 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Mon, 15 May 2023 00:54:50 +0200 Subject: [PATCH 0998/2172] avformat: add ff_match_url_ext() Match url against a list of extensions similar to av_match_ext() Signed-off-by: Michael Niedermayer --- libavformat/format.c | 25 +++++++++++++++++++++++++ libavformat/internal.h | 9 +++++++++ 2 files changed, 34 insertions(+) diff --git a/libavformat/format.c b/libavformat/format.c index 76f25ab5a67..d9135854de5 100644 --- a/libavformat/format.c +++ b/libavformat/format.c @@ -50,6 +50,31 @@ int av_match_ext(const char *filename, const char *extensions) return 0; } +int ff_match_url_ext(const char *url, const char *extensions) +{ + const char *ext; + URLComponents uc; + int ret; + char scratchpad[128]; + + if (!url) + return 0; + + ret = ff_url_decompose(&uc, url, NULL); + if (ret < 0 || !URL_COMPONENT_HAVE(uc, scheme)) + return ret; + for (ext = uc.query; *ext != '.' && ext > uc.path; ext--) + ; + + if (*ext != '.') + return 0; + if (uc.query - ext > sizeof(scratchpad)) + return AVERROR(ENOMEM); //not enough memory in our scratchpad + av_strlcpy(scratchpad, ext + 1, FFMIN(sizeof(scratchpad), uc.query - ext)); + + return av_match_name(scratchpad, extensions); +} + const AVOutputFormat *av_guess_format(const char *short_name, const char *filename, const char *mime_type) { diff --git a/libavformat/internal.h b/libavformat/internal.h index f575064e8fb..82a79d74880 100644 --- a/libavformat/internal.h +++ b/libavformat/internal.h @@ -705,6 +705,15 @@ int ff_unlock_avformat(void); */ void ff_format_set_url(AVFormatContext *s, char *url); +/** + * Return a positive value if the given url has one of the given + * extensions, negative AVERROR on error, 0 otherwise. + * + * @param url url to check against the given extensions + * @param extensions a comma-separated list of filename extensions + */ +int ff_match_url_ext(const char *url, const char *extensions); + struct FFOutputFormat; void avpriv_register_devices(const struct FFOutputFormat * const o[], const AVInputFormat * const i[]); From 954d16fa3f09a04c7917a1c69a5c3e283554cb1d Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Mon, 15 May 2023 00:56:10 +0200 Subject: [PATCH 0999/2172] avformat/hls: Try to implement RFC8216 playlist refusal This should fix the regression since 6b1f68ccb04d791f0250e05687c346a99ff47ea1 Should fix Ticket10353 (please test and report cases that still fail) Signed-off-by: Michael Niedermayer --- libavformat/hls.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/libavformat/hls.c b/libavformat/hls.c index 11e345b2803..425df3b26b9 100644 --- a/libavformat/hls.c +++ b/libavformat/hls.c @@ -2534,7 +2534,16 @@ static int hls_probe(const AVProbeData *p) strstr(p->buf, "#EXT-X-TARGETDURATION:") || strstr(p->buf, "#EXT-X-MEDIA-SEQUENCE:")) { - if (!av_match_ext(p->filename, "m3u8,hls,m3u")) { + int mime_ok = p->mime_type && !( + av_strcasecmp(p->mime_type, "application/vnd.apple.mpegurl") && + av_strcasecmp(p->mime_type, "audio/mpegurl") && + av_strcasecmp(p->mime_type, "audio/x-mpegurl") && + av_strcasecmp(p->mime_type, "application/x-mpegurl") + ); + + if (!av_match_ext (p->filename, "m3u8,hls,m3u") && + ff_match_url_ext(p->filename, "m3u8,hls,m3u") <= 0 && + !mime_ok) { av_log(NULL, AV_LOG_ERROR, "Not detecting m3u8/hls with non standard extension\n"); return 0; } From 51d6ae099f281fecaab874037225b884eeb17794 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Tue, 9 May 2023 12:16:45 +0200 Subject: [PATCH 1000/2172] lavc/decode: drop a useless warning Decoders will currently warn if an audio decoder not marked with AV_CODEC_CAP_SUBFRAMES consumes less than the whole packet, but * this happens for regular files * this has no negative consequences * there is no meeaningful action that can or should be taken in response The warning is thus useless noise. --- libavcodec/decode.c | 7 ------- libavcodec/internal.h | 2 -- 2 files changed, 9 deletions(-) diff --git a/libavcodec/decode.c b/libavcodec/decode.c index 4f2359f07ef..360837a0adb 100644 --- a/libavcodec/decode.c +++ b/libavcodec/decode.c @@ -423,13 +423,6 @@ FF_ENABLE_DEPRECATION_WARNINGS } } - if (avctx->codec->type == AVMEDIA_TYPE_AUDIO && - !avci->showed_multi_packet_warning && - ret >= 0 && ret != pkt->size && !(avctx->codec->capabilities & AV_CODEC_CAP_SUBFRAMES)) { - av_log(avctx, AV_LOG_WARNING, "Multiple frames in a packet.\n"); - avci->showed_multi_packet_warning = 1; - } - if (!got_frame) av_frame_unref(frame); diff --git a/libavcodec/internal.h b/libavcodec/internal.h index a283c52e012..dceae182c0e 100644 --- a/libavcodec/internal.h +++ b/libavcodec/internal.h @@ -148,8 +148,6 @@ typedef struct AVCodecInternal { AVFrame *buffer_frame; int draining_done; - int showed_multi_packet_warning; - /* to prevent infinite loop on errors when draining */ int nb_draining_errors; From 8b20d0dcb5cfa8dc34830acdd719fc65b8b5ef67 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Tue, 9 May 2023 12:28:10 +0200 Subject: [PATCH 1001/2172] lavc: deprecate AV_CODEC_CAP_SUBFRAMES There is nothing meaningful the caller can do with it. --- doc/APIchanges | 3 +++ libavcodec/alsdec.c | 6 +++++- libavcodec/apac.c | 6 ++++-- libavcodec/apedec.c | 6 +++++- libavcodec/atrac3.c | 12 ++++++++++-- libavcodec/atrac9dec.c | 6 +++++- libavcodec/bonk.c | 6 ++++-- libavcodec/codec.h | 3 +++ libavcodec/ftr.c | 6 +++++- libavcodec/g723_1dec.c | 6 +++++- libavcodec/g729dec.c | 12 ++++++++++-- libavcodec/libspeexdec.c | 6 +++++- libavcodec/misc4.c | 5 ++++- libavcodec/shorten.c | 6 ++++-- libavcodec/tests/avcodec.c | 3 +-- libavcodec/version_major.h | 1 + libavcodec/wavarc.c | 2 ++ libavcodec/wmalosslessdec.c | 6 +++++- libavcodec/wmaprodec.c | 18 +++++++++++++++--- libavcodec/wmavoice.c | 6 +++++- 20 files changed, 101 insertions(+), 24 deletions(-) diff --git a/doc/APIchanges b/doc/APIchanges index 20ab4709e7a..a37fe1bb8eb 100644 --- a/doc/APIchanges +++ b/doc/APIchanges @@ -2,6 +2,9 @@ The last version increases of all libraries were on 2023-02-09 API changes, most recent first: +2023-05-xx - xxxxxxxxxx - lavc 60 - codec.h + Depreate AV_CODEC_CAP_SUBFRAMES without replacement. + 2023-05-xx - xxxxxxxxxx - lavc 60.11.100 - codec_par.h Add AVCodecParameters.framerate. diff --git a/libavcodec/alsdec.c b/libavcodec/alsdec.c index 4605b2248fa..c64d1032a41 100644 --- a/libavcodec/alsdec.c +++ b/libavcodec/alsdec.c @@ -2190,6 +2190,10 @@ const FFCodec ff_als_decoder = { .close = decode_end, FF_CODEC_DECODE_CB(decode_frame), .flush = flush, - .p.capabilities = AV_CODEC_CAP_SUBFRAMES | AV_CODEC_CAP_DR1 | AV_CODEC_CAP_CHANNEL_CONF, + .p.capabilities = +#if FF_API_SUBFRAMES + AV_CODEC_CAP_SUBFRAMES | +#endif + AV_CODEC_CAP_DR1 | AV_CODEC_CAP_CHANNEL_CONF, .caps_internal = FF_CODEC_CAP_INIT_CLEANUP, }; diff --git a/libavcodec/apac.c b/libavcodec/apac.c index 3408f75292d..b6cb6c669ec 100644 --- a/libavcodec/apac.c +++ b/libavcodec/apac.c @@ -269,8 +269,10 @@ const FFCodec ff_apac_decoder = { FF_CODEC_DECODE_CB(apac_decode), .close = apac_close, .p.capabilities = AV_CODEC_CAP_DELAY | - AV_CODEC_CAP_DR1 | - AV_CODEC_CAP_SUBFRAMES, +#if FF_API_SUBFRAMES + AV_CODEC_CAP_SUBFRAMES | +#endif + AV_CODEC_CAP_DR1, .caps_internal = FF_CODEC_CAP_INIT_CLEANUP, .p.sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_U8P, AV_SAMPLE_FMT_S16P, diff --git a/libavcodec/apedec.c b/libavcodec/apedec.c index 772636afde3..613c76df0b8 100644 --- a/libavcodec/apedec.c +++ b/libavcodec/apedec.c @@ -1680,7 +1680,11 @@ const FFCodec ff_ape_decoder = { .init = ape_decode_init, .close = ape_decode_close, FF_CODEC_DECODE_CB(ape_decode_frame), - .p.capabilities = AV_CODEC_CAP_SUBFRAMES | AV_CODEC_CAP_DELAY | + .p.capabilities = +#if FF_API_SUBFRAMES + AV_CODEC_CAP_SUBFRAMES | +#endif + AV_CODEC_CAP_DELAY | AV_CODEC_CAP_DR1, .caps_internal = FF_CODEC_CAP_INIT_CLEANUP, .flush = ape_flush, diff --git a/libavcodec/atrac3.c b/libavcodec/atrac3.c index 7415da590bc..5851ee027ca 100644 --- a/libavcodec/atrac3.c +++ b/libavcodec/atrac3.c @@ -1026,7 +1026,11 @@ const FFCodec ff_atrac3_decoder = { .init = atrac3_decode_init, .close = atrac3_decode_close, FF_CODEC_DECODE_CB(atrac3_decode_frame), - .p.capabilities = AV_CODEC_CAP_SUBFRAMES | AV_CODEC_CAP_DR1, + .p.capabilities = +#if FF_API_SUBFRAMES + AV_CODEC_CAP_SUBFRAMES | +#endif + AV_CODEC_CAP_DR1, .p.sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_FLTP, AV_SAMPLE_FMT_NONE }, .caps_internal = FF_CODEC_CAP_INIT_CLEANUP, @@ -1041,7 +1045,11 @@ const FFCodec ff_atrac3al_decoder = { .init = atrac3_decode_init, .close = atrac3_decode_close, FF_CODEC_DECODE_CB(atrac3al_decode_frame), - .p.capabilities = AV_CODEC_CAP_SUBFRAMES | AV_CODEC_CAP_DR1, + .p.capabilities = +#if FF_API_SUBFRAMES + AV_CODEC_CAP_SUBFRAMES | +#endif + AV_CODEC_CAP_DR1, .p.sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_FLTP, AV_SAMPLE_FMT_NONE }, .caps_internal = FF_CODEC_CAP_INIT_CLEANUP, diff --git a/libavcodec/atrac9dec.c b/libavcodec/atrac9dec.c index 60962b16762..8a6940455d4 100644 --- a/libavcodec/atrac9dec.c +++ b/libavcodec/atrac9dec.c @@ -1003,5 +1003,9 @@ const FFCodec ff_atrac9_decoder = { FF_CODEC_DECODE_CB(atrac9_decode_frame), .flush = atrac9_decode_flush, .caps_internal = FF_CODEC_CAP_INIT_CLEANUP, - .p.capabilities = AV_CODEC_CAP_SUBFRAMES | AV_CODEC_CAP_DR1 | AV_CODEC_CAP_CHANNEL_CONF, + .p.capabilities = +#if FF_API_SUBFRAMES + AV_CODEC_CAP_SUBFRAMES | +#endif + AV_CODEC_CAP_DR1 | AV_CODEC_CAP_CHANNEL_CONF, }; diff --git a/libavcodec/bonk.c b/libavcodec/bonk.c index 4a002703929..9a91b4842e5 100644 --- a/libavcodec/bonk.c +++ b/libavcodec/bonk.c @@ -428,8 +428,10 @@ const FFCodec ff_bonk_decoder = { FF_CODEC_DECODE_CB(bonk_decode), .close = bonk_close, .p.capabilities = AV_CODEC_CAP_DELAY | - AV_CODEC_CAP_DR1 | - AV_CODEC_CAP_SUBFRAMES, +#if FF_API_SUBFRAMES + AV_CODEC_CAP_SUBFRAMES | +#endif + AV_CODEC_CAP_DR1, .caps_internal = FF_CODEC_CAP_INIT_CLEANUP, .p.sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_S16P, AV_SAMPLE_FMT_NONE }, diff --git a/libavcodec/codec.h b/libavcodec/codec.h index 3b1995bcfef..7a932d75dde 100644 --- a/libavcodec/codec.h +++ b/libavcodec/codec.h @@ -80,6 +80,7 @@ */ #define AV_CODEC_CAP_SMALL_LAST_FRAME (1 << 6) +#if FF_API_SUBFRAMES /** * Codec can output multiple frames per AVPacket * Normally demuxers return one frame at a time, demuxers which do not do @@ -92,6 +93,8 @@ * as a last resort. */ #define AV_CODEC_CAP_SUBFRAMES (1 << 8) +#endif + /** * Codec is experimental and is thus avoided in favor of non experimental * encoders diff --git a/libavcodec/ftr.c b/libavcodec/ftr.c index 74a2c10b5c8..7cf1b1586fb 100644 --- a/libavcodec/ftr.c +++ b/libavcodec/ftr.c @@ -203,6 +203,10 @@ const FFCodec ff_ftr_decoder = { .close = ftr_close, .flush = ftr_flush, .priv_data_size = sizeof(FTRContext), - .p.capabilities = AV_CODEC_CAP_SUBFRAMES | AV_CODEC_CAP_DR1, + .p.capabilities = +#if FF_API_SUBFRAMES + AV_CODEC_CAP_SUBFRAMES | +#endif + AV_CODEC_CAP_DR1, .caps_internal = FF_CODEC_CAP_INIT_CLEANUP, }; diff --git a/libavcodec/g723_1dec.c b/libavcodec/g723_1dec.c index 55e20de5b5f..5fe4a21d9b2 100644 --- a/libavcodec/g723_1dec.c +++ b/libavcodec/g723_1dec.c @@ -1118,6 +1118,10 @@ const FFCodec ff_g723_1_decoder = { .priv_data_size = sizeof(G723_1_Context), .init = g723_1_decode_init, FF_CODEC_DECODE_CB(g723_1_decode_frame), - .p.capabilities = AV_CODEC_CAP_SUBFRAMES | AV_CODEC_CAP_DR1, + .p.capabilities = +#if FF_API_SUBFRAMES + AV_CODEC_CAP_SUBFRAMES | +#endif + AV_CODEC_CAP_DR1, .p.priv_class = &g723_1dec_class, }; diff --git a/libavcodec/g729dec.c b/libavcodec/g729dec.c index f783812cc7c..33e1fb9c29d 100644 --- a/libavcodec/g729dec.c +++ b/libavcodec/g729dec.c @@ -760,7 +760,11 @@ const FFCodec ff_g729_decoder = { .init = decoder_init, FF_CODEC_DECODE_CB(decode_frame), .close = decode_close, - .p.capabilities = AV_CODEC_CAP_SUBFRAMES | AV_CODEC_CAP_DR1, + .p.capabilities = +#if FF_API_SUBFRAMES + AV_CODEC_CAP_SUBFRAMES | +#endif + AV_CODEC_CAP_DR1, }; const FFCodec ff_acelp_kelvin_decoder = { @@ -772,5 +776,9 @@ const FFCodec ff_acelp_kelvin_decoder = { .init = decoder_init, FF_CODEC_DECODE_CB(decode_frame), .close = decode_close, - .p.capabilities = AV_CODEC_CAP_SUBFRAMES | AV_CODEC_CAP_DR1, + .p.capabilities = +#if FF_API_SUBFRAMES + AV_CODEC_CAP_SUBFRAMES | +#endif + AV_CODEC_CAP_DR1, }; diff --git a/libavcodec/libspeexdec.c b/libavcodec/libspeexdec.c index 47fc5d6a4b2..84b308490a5 100644 --- a/libavcodec/libspeexdec.c +++ b/libavcodec/libspeexdec.c @@ -195,7 +195,11 @@ const FFCodec ff_libspeex_decoder = { CODEC_LONG_NAME("libspeex Speex"), .p.type = AVMEDIA_TYPE_AUDIO, .p.id = AV_CODEC_ID_SPEEX, - .p.capabilities = AV_CODEC_CAP_SUBFRAMES | AV_CODEC_CAP_DELAY | AV_CODEC_CAP_DR1 | AV_CODEC_CAP_CHANNEL_CONF, + .p.capabilities = +#if FF_API_SUBFRAMES + AV_CODEC_CAP_SUBFRAMES | +#endif + AV_CODEC_CAP_DELAY | AV_CODEC_CAP_DR1 | AV_CODEC_CAP_CHANNEL_CONF, .p.wrapper_name = "libspeex", .caps_internal = FF_CODEC_CAP_NOT_INIT_THREADSAFE, .priv_data_size = sizeof(LibSpeexContext), diff --git a/libavcodec/misc4.c b/libavcodec/misc4.c index 1bf162e1202..72ac944e54f 100644 --- a/libavcodec/misc4.c +++ b/libavcodec/misc4.c @@ -179,7 +179,10 @@ const FFCodec ff_misc4_decoder = { .priv_data_size = sizeof(MISC4Context), .init = misc4_init, FF_CODEC_DECODE_CB(misc4_decode), - .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_SUBFRAMES | + .p.capabilities = AV_CODEC_CAP_DR1 | +#if FF_API_SUBFRAMES + AV_CODEC_CAP_SUBFRAMES | +#endif AV_CODEC_CAP_CHANNEL_CONF, .p.sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_S16, AV_SAMPLE_FMT_NONE }, diff --git a/libavcodec/shorten.c b/libavcodec/shorten.c index 1b2abd76b14..eca0c4e85ad 100644 --- a/libavcodec/shorten.c +++ b/libavcodec/shorten.c @@ -814,8 +814,10 @@ const FFCodec ff_shorten_decoder = { FF_CODEC_DECODE_CB(shorten_decode_frame), .p.capabilities = AV_CODEC_CAP_CHANNEL_CONF | AV_CODEC_CAP_DELAY | - AV_CODEC_CAP_DR1 | - AV_CODEC_CAP_SUBFRAMES , +#if FF_API_SUBFRAMES + AV_CODEC_CAP_SUBFRAMES | +#endif + AV_CODEC_CAP_DR1, .p.sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_S16P, AV_SAMPLE_FMT_U8P, AV_SAMPLE_FMT_NONE }, diff --git a/libavcodec/tests/avcodec.c b/libavcodec/tests/avcodec.c index 4c1730425d7..d78447d0fc8 100644 --- a/libavcodec/tests/avcodec.c +++ b/libavcodec/tests/avcodec.c @@ -149,8 +149,7 @@ int main(void){ FF_CODEC_CAP_SETS_FRAME_PROPS) || codec->capabilities & (AV_CODEC_CAP_AVOID_PROBING | AV_CODEC_CAP_CHANNEL_CONF | - AV_CODEC_CAP_DRAW_HORIZ_BAND | - AV_CODEC_CAP_SUBFRAMES)) + AV_CODEC_CAP_DRAW_HORIZ_BAND)) ERR("Encoder %s has decoder-only capabilities set\n"); if (codec->capabilities & AV_CODEC_CAP_FRAME_THREADS && codec->capabilities & AV_CODEC_CAP_ENCODER_FLUSH) diff --git a/libavcodec/version_major.h b/libavcodec/version_major.h index 40db213499a..8c3ce431652 100644 --- a/libavcodec/version_major.h +++ b/libavcodec/version_major.h @@ -46,6 +46,7 @@ #define FF_API_VT_HWACCEL_CONTEXT (LIBAVCODEC_VERSION_MAJOR < 61) #define FF_API_AVCTX_FRAME_NUMBER (LIBAVCODEC_VERSION_MAJOR < 61) #define FF_API_SLICE_OFFSET (LIBAVCODEC_VERSION_MAJOR < 61) +#define FF_API_SUBFRAMES (LIBAVCODEC_VERSION_MAJOR < 61) // reminder to remove CrystalHD decoders on next major bump #define FF_CODEC_CRYSTAL_HD (LIBAVCODEC_VERSION_MAJOR < 61) diff --git a/libavcodec/wavarc.c b/libavcodec/wavarc.c index 827803c91d0..7bfc276df4a 100644 --- a/libavcodec/wavarc.c +++ b/libavcodec/wavarc.c @@ -499,7 +499,9 @@ const FFCodec ff_wavarc_decoder = { FF_CODEC_DECODE_CB(wavarc_decode), .close = wavarc_close, .p.capabilities = AV_CODEC_CAP_DR1 | +#if FF_API_SUBFRAMES AV_CODEC_CAP_SUBFRAMES | +#endif AV_CODEC_CAP_DELAY, .p.sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_U8P, AV_SAMPLE_FMT_S16P, diff --git a/libavcodec/wmalosslessdec.c b/libavcodec/wmalosslessdec.c index d545d848e2a..5d1c7ac66bb 100644 --- a/libavcodec/wmalosslessdec.c +++ b/libavcodec/wmalosslessdec.c @@ -1334,7 +1334,11 @@ const FFCodec ff_wmalossless_decoder = { .close = decode_close, FF_CODEC_DECODE_CB(decode_packet), .flush = flush, - .p.capabilities = AV_CODEC_CAP_SUBFRAMES | AV_CODEC_CAP_DR1 | AV_CODEC_CAP_DELAY, + .p.capabilities = +#if FF_API_SUBFRAMES + AV_CODEC_CAP_SUBFRAMES | +#endif + AV_CODEC_CAP_DR1 | AV_CODEC_CAP_DELAY, .caps_internal = FF_CODEC_CAP_INIT_CLEANUP, .p.sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_S16P, AV_SAMPLE_FMT_S32P, diff --git a/libavcodec/wmaprodec.c b/libavcodec/wmaprodec.c index 35e9caec560..f523f3637fa 100644 --- a/libavcodec/wmaprodec.c +++ b/libavcodec/wmaprodec.c @@ -2094,7 +2094,11 @@ const FFCodec ff_wmapro_decoder = { .init = wmapro_decode_init, .close = wmapro_decode_end, FF_CODEC_DECODE_CB(wmapro_decode_packet), - .p.capabilities = AV_CODEC_CAP_SUBFRAMES | AV_CODEC_CAP_DR1, + .p.capabilities = +#if FF_API_SUBFRAMES + AV_CODEC_CAP_SUBFRAMES | +#endif + AV_CODEC_CAP_DR1, .flush = wmapro_flush, .p.sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_FLTP, AV_SAMPLE_FMT_NONE }, @@ -2111,7 +2115,11 @@ const FFCodec ff_xma1_decoder = { .close = xma_decode_end, FF_CODEC_DECODE_CB(xma_decode_packet), .flush = xma_flush, - .p.capabilities = AV_CODEC_CAP_SUBFRAMES | AV_CODEC_CAP_DR1 | AV_CODEC_CAP_DELAY, + .p.capabilities = +#if FF_API_SUBFRAMES + AV_CODEC_CAP_SUBFRAMES | +#endif + AV_CODEC_CAP_DR1 | AV_CODEC_CAP_DELAY, .p.sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_FLTP, AV_SAMPLE_FMT_NONE }, .caps_internal = FF_CODEC_CAP_INIT_CLEANUP, @@ -2127,7 +2135,11 @@ const FFCodec ff_xma2_decoder = { .close = xma_decode_end, FF_CODEC_DECODE_CB(xma_decode_packet), .flush = xma_flush, - .p.capabilities = AV_CODEC_CAP_SUBFRAMES | AV_CODEC_CAP_DR1 | AV_CODEC_CAP_DELAY, + .p.capabilities = +#if FF_API_SUBFRAMES + AV_CODEC_CAP_SUBFRAMES | +#endif + AV_CODEC_CAP_DR1 | AV_CODEC_CAP_DELAY, .p.sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_FLTP, AV_SAMPLE_FMT_NONE }, .caps_internal = FF_CODEC_CAP_INIT_CLEANUP, diff --git a/libavcodec/wmavoice.c b/libavcodec/wmavoice.c index bb98f841a50..44fda0e2d68 100644 --- a/libavcodec/wmavoice.c +++ b/libavcodec/wmavoice.c @@ -2004,7 +2004,11 @@ const FFCodec ff_wmavoice_decoder = { .init = wmavoice_decode_init, .close = wmavoice_decode_end, FF_CODEC_DECODE_CB(wmavoice_decode_packet), - .p.capabilities = AV_CODEC_CAP_SUBFRAMES | AV_CODEC_CAP_DR1 | AV_CODEC_CAP_DELAY, + .p.capabilities = +#if FF_API_SUBFRAMES + AV_CODEC_CAP_SUBFRAMES | +#endif + AV_CODEC_CAP_DR1 | AV_CODEC_CAP_DELAY, .caps_internal = FF_CODEC_CAP_INIT_CLEANUP, .flush = wmavoice_flush, }; From 02823210d7f3d81c8001070efcc8e2a0612e9fa3 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Tue, 9 May 2023 12:29:22 +0200 Subject: [PATCH 1002/2172] fftools/opt_common: stop printing deprecated AV_CODEC_CAP_SUBFRAMES --- fftools/opt_common.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/fftools/opt_common.c b/fftools/opt_common.c index 8a06df82df2..f6fe9815e1e 100644 --- a/fftools/opt_common.c +++ b/fftools/opt_common.c @@ -291,8 +291,6 @@ static void print_codec(const AVCodec *c) printf("delay "); if (c->capabilities & AV_CODEC_CAP_SMALL_LAST_FRAME) printf("small "); - if (c->capabilities & AV_CODEC_CAP_SUBFRAMES) - printf("subframes "); if (c->capabilities & AV_CODEC_CAP_EXPERIMENTAL) printf("exp "); if (c->capabilities & AV_CODEC_CAP_CHANNEL_CONF) From d45a296732ed0b92d19a1cc017552cf163ccb648 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Sun, 7 May 2023 12:19:31 +0200 Subject: [PATCH 1003/2172] lavu/frame: extend AVFrame.repeat_pict documentation --- libavutil/frame.h | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/libavutil/frame.h b/libavutil/frame.h index f2b56beebb6..ed3f199ce16 100644 --- a/libavutil/frame.h +++ b/libavutil/frame.h @@ -491,8 +491,22 @@ typedef struct AVFrame { void *opaque; /** - * When decoding, this signals how much the picture must be delayed. - * extra_delay = repeat_pict / (2*fps) + * Number of fields in this frame which should be repeated, i.e. the total + * duration of this frame should be repeat_pict + 2 normal field durations. + * + * For interlaced frames this field may be set to 1, which signals that this + * frame should be presented as 3 fields: beginning with the first field (as + * determined by AV_FRAME_FLAG_TOP_FIELD_FIRST being set or not), followed + * by the second field, and then the first field again. + * + * For progressive frames this field may be set to a multiple of 2, which + * signals that this frame's duration should be (repeat_pict + 2) / 2 + * normal frame durations. + * + * @note This field is computed from MPEG2 repeat_first_field flag and its + * associated flags, H.264 pic_struct from picture timing SEI, and + * their analogues in other codecs. Typically it should only be used when + * higher-layer timing information is not available. */ int repeat_pict; From 78e84c054a2a04edeea25e9ee54d0fb172cd7053 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Fri, 5 May 2023 18:46:28 +0200 Subject: [PATCH 1004/2172] fftools/ffmpeg: fix computing video frame duration from repeat_pict This field contains the number of _field_ durations by which the standard frame duration should be extended. --- fftools/ffmpeg.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/fftools/ffmpeg.c b/fftools/ffmpeg.c index 5cf6a00f50f..9920f946dc0 100644 --- a/fftools/ffmpeg.c +++ b/fftools/ffmpeg.c @@ -990,10 +990,10 @@ static int64_t video_duration_estimate(const InputStream *ist, const AVFrame *fr return frame->duration; if (ist->dec_ctx->framerate.den && ist->dec_ctx->framerate.num) { - int ticks = frame->repeat_pict >= 0 ? - frame->repeat_pict + 1 : - ist->dec_ctx->ticks_per_frame; - codec_duration = av_rescale_q(ticks, av_inv_q(ist->dec_ctx->framerate), + int fields = frame->repeat_pict + 2; + AVRational field_rate = av_mul_q(ist->dec_ctx->framerate, + (AVRational){ 2, 1 }); + codec_duration = av_rescale_q(fields, av_inv_q(field_rate), ist->st->time_base); } From 70433abf7fbc978b5fa0d06951d61ac18ac335f8 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Fri, 5 May 2023 15:17:37 +0200 Subject: [PATCH 1005/2172] lavc/codec_desc: add a property for codecs that support field coding Multiple places currently use AVCodecContext.ticks_per_frame > 1 to identify such codecs, which * requires a codec context * requires it to be open --- doc/APIchanges | 3 +++ libavcodec/codec_desc.c | 16 ++++++++++++---- libavcodec/codec_desc.h | 6 ++++++ libavcodec/version.h | 2 +- 4 files changed, 22 insertions(+), 5 deletions(-) diff --git a/doc/APIchanges b/doc/APIchanges index a37fe1bb8eb..b0486462833 100644 --- a/doc/APIchanges +++ b/doc/APIchanges @@ -2,6 +2,9 @@ The last version increases of all libraries were on 2023-02-09 API changes, most recent first: +2023-05-xx - xxxxxxxxxx - lavc 60.12.100 - codec_desc.h + Add AV_CODEC_PROP_FIELDS. + 2023-05-xx - xxxxxxxxxx - lavc 60 - codec.h Depreate AV_CODEC_CAP_SUBFRAMES without replacement. diff --git a/libavcodec/codec_desc.c b/libavcodec/codec_desc.c index d40977d6b3b..49dddd1a496 100644 --- a/libavcodec/codec_desc.c +++ b/libavcodec/codec_desc.c @@ -38,14 +38,20 @@ static const AVCodecDescriptor codec_descriptors[] = { .type = AVMEDIA_TYPE_VIDEO, .name = "mpeg1video", .long_name = NULL_IF_CONFIG_SMALL("MPEG-1 video"), - .props = AV_CODEC_PROP_LOSSY | AV_CODEC_PROP_REORDER, + .props = AV_CODEC_PROP_LOSSY | AV_CODEC_PROP_REORDER | + // FIXME this is strigly speaking not true, as MPEG-1 does + // not allow field coding, but our mpeg12 code (decoder and + // parser) can sometimes change codec id at runtime, so + // this is safer + AV_CODEC_PROP_FIELDS, }, { .id = AV_CODEC_ID_MPEG2VIDEO, .type = AVMEDIA_TYPE_VIDEO, .name = "mpeg2video", .long_name = NULL_IF_CONFIG_SMALL("MPEG-2 video"), - .props = AV_CODEC_PROP_LOSSY | AV_CODEC_PROP_REORDER, + .props = AV_CODEC_PROP_LOSSY | AV_CODEC_PROP_REORDER | + AV_CODEC_PROP_FIELDS, .profiles = NULL_IF_CONFIG_SMALL(ff_mpeg2_video_profiles), }, { @@ -225,7 +231,8 @@ static const AVCodecDescriptor codec_descriptors[] = { .type = AVMEDIA_TYPE_VIDEO, .name = "h264", .long_name = NULL_IF_CONFIG_SMALL("H.264 / AVC / MPEG-4 AVC / MPEG-4 part 10"), - .props = AV_CODEC_PROP_LOSSY | AV_CODEC_PROP_LOSSLESS | AV_CODEC_PROP_REORDER, + .props = AV_CODEC_PROP_LOSSY | AV_CODEC_PROP_LOSSLESS | + AV_CODEC_PROP_REORDER | AV_CODEC_PROP_FIELDS, .profiles = NULL_IF_CONFIG_SMALL(ff_h264_profiles), }, { @@ -529,7 +536,8 @@ static const AVCodecDescriptor codec_descriptors[] = { .type = AVMEDIA_TYPE_VIDEO, .name = "vc1", .long_name = NULL_IF_CONFIG_SMALL("SMPTE VC-1"), - .props = AV_CODEC_PROP_LOSSY | AV_CODEC_PROP_REORDER, + .props = AV_CODEC_PROP_LOSSY | AV_CODEC_PROP_REORDER | + AV_CODEC_PROP_FIELDS, .profiles = NULL_IF_CONFIG_SMALL(ff_vc1_profiles), }, { diff --git a/libavcodec/codec_desc.h b/libavcodec/codec_desc.h index 126b52df476..dd4491112b2 100644 --- a/libavcodec/codec_desc.h +++ b/libavcodec/codec_desc.h @@ -90,6 +90,12 @@ typedef struct AVCodecDescriptor { * equal. */ #define AV_CODEC_PROP_REORDER (1 << 3) + +/** + * Video codec supports separate coding of fields in interlaced frames. + */ +#define AV_CODEC_PROP_FIELDS (1 << 4) + /** * Subtitle codec is bitmap based * Decoded AVSubtitle data can be read from the AVSubtitleRect->pict field. diff --git a/libavcodec/version.h b/libavcodec/version.h index 8b53586be1d..da2264a0972 100644 --- a/libavcodec/version.h +++ b/libavcodec/version.h @@ -29,7 +29,7 @@ #include "version_major.h" -#define LIBAVCODEC_VERSION_MINOR 11 +#define LIBAVCODEC_VERSION_MINOR 12 #define LIBAVCODEC_VERSION_MICRO 100 #define LIBAVCODEC_VERSION_INT AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \ From e930b834a928546f9cbc937f6633709053448232 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Fri, 5 May 2023 15:45:42 +0200 Subject: [PATCH 1006/2172] lavf: use AV_CODEC_PROP_FIELDS where appropriate H.264 and mpeg12 parsers need to be adjusted at the same time to stop using the value of AVCodecContext.ticks_per_frame, because it is not set correctly unless the codec has been opened. Previously this would result in both the parser and lavf seeing the same incorrect value, which would cancel out. Updating lavf and not the parsers would result in correct value in lavf, but the wrong one in parsers, which would break some tests. --- libavcodec/h264_parser.c | 4 ++-- libavcodec/mpegvideo_parser.c | 2 +- libavformat/avformat.c | 9 ++++++--- libavformat/demux.c | 35 ++++++++++++++++++++--------------- libavformat/internal.h | 3 +++ 5 files changed, 32 insertions(+), 21 deletions(-) diff --git a/libavcodec/h264_parser.c b/libavcodec/h264_parser.c index 46134a1c483..43abc45f9cd 100644 --- a/libavcodec/h264_parser.c +++ b/libavcodec/h264_parser.c @@ -568,7 +568,7 @@ static inline int parse_nal_units(AVCodecParserContext *s, if (p->sei.common.unregistered.x264_build < 44U) den *= 2; av_reduce(&avctx->framerate.den, &avctx->framerate.num, - sps->num_units_in_tick * avctx->ticks_per_frame, den, 1 << 30); + sps->num_units_in_tick * 2, den, 1 << 30); } av_freep(&rbsp.rbsp_buffer); @@ -625,7 +625,7 @@ static int h264_parse(AVCodecParserContext *s, parse_nal_units(s, avctx, buf, buf_size); if (avctx->framerate.num) - time_base = av_inv_q(av_mul_q(avctx->framerate, (AVRational){avctx->ticks_per_frame, 1})); + time_base = av_inv_q(av_mul_q(avctx->framerate, (AVRational){2, 1})); if (p->sei.picture_timing.cpb_removal_delay >= 0) { s->dts_sync_point = p->sei.buffering_period.present; s->dts_ref_dts_delta = p->sei.picture_timing.cpb_removal_delay; diff --git a/libavcodec/mpegvideo_parser.c b/libavcodec/mpegvideo_parser.c index 8e7e88ff25e..08e53169601 100644 --- a/libavcodec/mpegvideo_parser.c +++ b/libavcodec/mpegvideo_parser.c @@ -129,6 +129,7 @@ static void mpegvideo_extract_headers(AVCodecParserContext *s, s->pict_type = (buf[1] >> 3) & 7; if (bytes_left >= 4) vbv_delay = ((buf[1] & 0x07) << 13) | (buf[2] << 5) | (buf[3] >> 3); + s->repeat_pict = 1; } break; case SEQ_START_CODE: @@ -186,7 +187,6 @@ static void mpegvideo_extract_headers(AVCodecParserContext *s, progressive_frame = buf[4] & (1 << 7); /* check if we must repeat the frame */ - s->repeat_pict = 1; if (repeat_first_field) { if (pc->progressive_sequence) { if (top_field_first) diff --git a/libavformat/avformat.c b/libavformat/avformat.c index 708d90b38cc..fea905693dd 100644 --- a/libavformat/avformat.c +++ b/libavformat/avformat.c @@ -679,6 +679,7 @@ AVRational av_guess_sample_aspect_ratio(AVFormatContext *format, AVStream *strea AVRational av_guess_frame_rate(AVFormatContext *format, AVStream *st, AVFrame *frame) { AVRational fr = st->r_frame_rate; + const AVCodecDescriptor *desc = cffstream(st)->codec_desc; AVCodecContext *const avctx = ffstream(st)->avctx; AVRational codec_fr = avctx->framerate; AVRational avg_fr = st->avg_frame_rate; @@ -688,7 +689,7 @@ AVRational av_guess_frame_rate(AVFormatContext *format, AVStream *st, AVFrame *f fr = avg_fr; } - if (avctx->ticks_per_frame > 1) { + if (desc && (desc->props & AV_CODEC_PROP_FIELDS)) { if ( codec_fr.num > 0 && codec_fr.den > 0 && (fr.num == 0 || av_q2d(codec_fr) < av_q2d(fr)*0.7 && fabs(1.0 - av_q2d(av_div_q(avg_fr, fr))) > 0.1)) fr = codec_fr; @@ -701,10 +702,12 @@ int avformat_transfer_internal_stream_timing_info(const AVOutputFormat *ofmt, AVStream *ost, const AVStream *ist, enum AVTimebaseSource copy_tb) { + const AVCodecDescriptor *desc = cffstream(ist)->codec_desc; const AVCodecContext *const dec_ctx = cffstream(ist)->avctx; AVCodecContext *const enc_ctx = ffstream(ost)->avctx; - AVRational dec_ctx_tb = dec_ctx->framerate.num ? av_inv_q(av_mul_q(dec_ctx->framerate, - (AVRational){dec_ctx->ticks_per_frame, 1})) + + AVRational mul = (AVRational){ desc && (desc->props & AV_CODEC_PROP_FIELDS) ? 2 : 1, 1 }; + AVRational dec_ctx_tb = dec_ctx->framerate.num ? av_inv_q(av_mul_q(dec_ctx->framerate, mul)) : (ist->codecpar->codec_type == AVMEDIA_TYPE_AUDIO ? (AVRational){0, 1} : ist->time_base); diff --git a/libavformat/demux.c b/libavformat/demux.c index 2a32bde7f5e..dec02a1a6b0 100644 --- a/libavformat/demux.c +++ b/libavformat/demux.c @@ -213,6 +213,8 @@ FF_ENABLE_DEPRECATION_WARNINGS if (ret < 0) return ret; + sti->codec_desc = avcodec_descriptor_get(sti->avctx->codec_id); + sti->need_context_update = 0; } return 0; @@ -677,10 +679,11 @@ static void compute_frame_duration(AVFormatContext *s, int *pnum, int *pden, *pnum = st->time_base.num; *pden = st->time_base.den; } else if (codec_framerate.den * 1000LL > codec_framerate.num) { - av_assert0(sti->avctx->ticks_per_frame); + int ticks_per_frame = (sti->codec_desc && + (sti->codec_desc->props & AV_CODEC_PROP_FIELDS)) ? 2 : 1; av_reduce(pnum, pden, codec_framerate.den, - codec_framerate.num * (int64_t)sti->avctx->ticks_per_frame, + codec_framerate.num * (int64_t)ticks_per_frame, INT_MAX); if (pc && pc->repeat_pict) { @@ -692,7 +695,8 @@ static void compute_frame_duration(AVFormatContext *s, int *pnum, int *pden, /* If this codec can be interlaced or progressive then we need * a parser to compute duration of a packet. Thus if we have * no parser in such case leave duration undefined. */ - if (sti->avctx->ticks_per_frame > 1 && !pc) + if (sti->codec_desc && + (sti->codec_desc->props & AV_CODEC_PROP_FIELDS) && !pc) *pnum = *pden = 0; } break; @@ -1288,6 +1292,8 @@ static int read_frame_internal(AVFormatContext *s, AVPacket *pkt) return ret; } + sti->codec_desc = avcodec_descriptor_get(sti->avctx->codec_id); + sti->need_context_update = 0; } @@ -2164,9 +2170,10 @@ static int get_std_framerate(int i) static int tb_unreliable(AVFormatContext *ic, AVStream *st) { FFStream *const sti = ffstream(st); + const AVCodecDescriptor *desc = sti->codec_desc; AVCodecContext *c = sti->avctx; - AVRational time_base = c->framerate.num ? av_inv_q(av_mul_q(c->framerate, - (AVRational){c->ticks_per_frame, 1})) + AVRational mul = (AVRational){ desc && (desc->props & AV_CODEC_PROP_FIELDS) ? 2 : 1, 1 }; + AVRational time_base = c->framerate.num ? av_inv_q(av_mul_q(c->framerate, mul)) /* NOHEADER check added to not break existing behavior */ : (((ic->ctx_flags & AVFMTCTX_NOHEADER) || st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) ? (AVRational){0, 1} @@ -2718,13 +2725,14 @@ int avformat_find_stream_info(AVFormatContext *ic, AVDictionary **options) break; } if (pkt->duration > 0) { + const int fields = sti->codec_desc && (sti->codec_desc->props & AV_CODEC_PROP_FIELDS); if (avctx->codec_type == AVMEDIA_TYPE_SUBTITLE && pkt->pts != AV_NOPTS_VALUE && st->start_time != AV_NOPTS_VALUE && pkt->pts >= st->start_time && (uint64_t)pkt->pts - st->start_time < INT64_MAX ) { sti->info->codec_info_duration = FFMIN(pkt->pts - st->start_time, sti->info->codec_info_duration + pkt->duration); } else sti->info->codec_info_duration += pkt->duration; - sti->info->codec_info_duration_fields += sti->parser && sti->need_parsing && avctx->ticks_per_frame == 2 + sti->info->codec_info_duration_fields += sti->parser && sti->need_parsing && fields ? sti->parser->repeat_pict + 1 : 2; } } @@ -2864,15 +2872,12 @@ int avformat_find_stream_info(AVFormatContext *ic, AVDictionary **options) best_fps, 12 * 1001, INT_MAX); } if (!st->r_frame_rate.num) { - AVRational time_base = avctx->framerate.num ? av_inv_q(av_mul_q(avctx->framerate, - (AVRational){avctx->ticks_per_frame, 1})) - /* NOHEADER check added to not break existing behavior */ - : ((ic->ctx_flags & AVFMTCTX_NOHEADER) ? (AVRational){0, 1} - : st->time_base); - if ( time_base.den * (int64_t) st->time_base.num - <= time_base.num * (uint64_t)avctx->ticks_per_frame * st->time_base.den) { - av_reduce(&st->r_frame_rate.num, &st->r_frame_rate.den, - time_base.den, (int64_t)time_base.num * avctx->ticks_per_frame, INT_MAX); + const AVCodecDescriptor *desc = sti->codec_desc; + AVRational mul = (AVRational){ desc && (desc->props & AV_CODEC_PROP_FIELDS) ? 2 : 1, 1 }; + AVRational fr = av_mul_q(avctx->framerate, mul); + + if (fr.num && fr.den && av_cmp_q(st->time_base, av_inv_q(fr)) <= 0) { + st->r_frame_rate = fr; } else { st->r_frame_rate.num = st->time_base.den; st->r_frame_rate.den = st->time_base.num; diff --git a/libavformat/internal.h b/libavformat/internal.h index 82a79d74880..9fc980601f2 100644 --- a/libavformat/internal.h +++ b/libavformat/internal.h @@ -23,6 +23,7 @@ #include +#include "libavcodec/codec_desc.h" #include "libavcodec/packet_internal.h" #include "avformat.h" @@ -408,6 +409,8 @@ typedef struct FFStream { */ int64_t first_dts; int64_t cur_dts; + + const AVCodecDescriptor *codec_desc; } FFStream; static av_always_inline FFStream *ffstream(AVStream *st) From dc20baa0491d190a68d73f4da931205490e344bb Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Thu, 4 May 2023 10:59:18 +0200 Subject: [PATCH 1007/2172] lavc/ratecontrol: use AVCodecContext.framerate when available --- libavcodec/ratecontrol.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/libavcodec/ratecontrol.c b/libavcodec/ratecontrol.c index 6a40f9cbdc7..890ae33cb30 100644 --- a/libavcodec/ratecontrol.c +++ b/libavcodec/ratecontrol.c @@ -57,6 +57,9 @@ void ff_write_pass1_stats(MpegEncContext *s) static double get_fps(AVCodecContext *avctx) { + if (avctx->framerate.num > 0 && avctx->framerate.den > 0) + return av_q2d(avctx->framerate); + return 1.0 / av_q2d(avctx->time_base) / FFMAX(avctx->ticks_per_frame, 1); } From 3fabf712070cb060a01e93d70dbdf837f0efa98e Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Thu, 4 May 2023 11:45:29 +0200 Subject: [PATCH 1008/2172] lavc/msmpeg4enc: use AVCodecContext.framerate when available --- libavcodec/msmpeg4enc.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/libavcodec/msmpeg4enc.c b/libavcodec/msmpeg4enc.c index 54121438a0c..df190d376c0 100644 --- a/libavcodec/msmpeg4enc.c +++ b/libavcodec/msmpeg4enc.c @@ -280,7 +280,13 @@ void ff_msmpeg4_encode_picture_header(MpegEncContext * s) void ff_msmpeg4_encode_ext_header(MpegEncContext * s) { - unsigned fps = s->avctx->time_base.den / s->avctx->time_base.num / FFMAX(s->avctx->ticks_per_frame, 1); + unsigned fps; + + if (s->avctx->framerate.num > 0 && s->avctx->framerate.den > 0) + fps = s->avctx->framerate.num / s->avctx->framerate.den; + else + fps = s->avctx->time_base.den / s->avctx->time_base.num / FFMAX(s->avctx->ticks_per_frame, 1); + put_bits(&s->pb, 5, FFMIN(fps, 31)); //yes 29.97 -> 29 put_bits(&s->pb, 11, FFMIN(s->bit_rate / 1024, 2047)); From aa3b0f437674ebad01c01212fa7f6895b8e3a7dd Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Thu, 4 May 2023 11:13:04 +0200 Subject: [PATCH 1009/2172] libaomenc: use AVCodecContext.framerate when available --- libavcodec/libaomenc.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/libavcodec/libaomenc.c b/libavcodec/libaomenc.c index 0b88102c775..1d3a4ae64c5 100644 --- a/libavcodec/libaomenc.c +++ b/libavcodec/libaomenc.c @@ -1295,8 +1295,12 @@ static int aom_encode(AVCodecContext *avctx, AVPacket *pkt, if (frame->duration > ULONG_MAX) { av_log(avctx, AV_LOG_WARNING, "Frame duration too large: %"PRId64"\n", frame->duration); - } else - duration = frame->duration ? frame->duration : avctx->ticks_per_frame; + } else if (frame->duration) + duration = frame->duration; + else if (avctx->framerate.num > 0 && avctx->framerate.den > 0) + duration = av_rescale_q(1, av_inv_q(avctx->framerate), avctx->time_base); + else + duration = avctx->ticks_per_frame ? avctx->ticks_per_frame : 1; switch (frame->color_range) { case AVCOL_RANGE_MPEG: From 2ad468ed1f7a7c67f1a2ab37c9e304b0011f0aae Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Thu, 4 May 2023 11:16:27 +0200 Subject: [PATCH 1010/2172] lavc/libkvazaar,libopenh264enc: drop redundant checks The same check is present in encode_preinit_video(). --- libavcodec/libkvazaar.c | 5 ----- libavcodec/libopenh264enc.c | 5 ----- 2 files changed, 10 deletions(-) diff --git a/libavcodec/libkvazaar.c b/libavcodec/libkvazaar.c index 168486f4ecb..b3faa0a64bd 100644 --- a/libavcodec/libkvazaar.c +++ b/libavcodec/libkvazaar.c @@ -85,11 +85,6 @@ static av_cold int libkvazaar_init(AVCodecContext *avctx) cfg->framerate_num = avctx->framerate.num; cfg->framerate_denom = avctx->framerate.den; } else { - if (avctx->ticks_per_frame > INT_MAX / avctx->time_base.num) { - av_log(avctx, AV_LOG_ERROR, - "Could not set framerate for kvazaar: integer overflow\n"); - return AVERROR(EINVAL); - } cfg->framerate_num = avctx->time_base.den; cfg->framerate_denom = avctx->time_base.num * avctx->ticks_per_frame; } diff --git a/libavcodec/libopenh264enc.c b/libavcodec/libopenh264enc.c index 3c605fe8ea4..15c3822824b 100644 --- a/libavcodec/libopenh264enc.c +++ b/libavcodec/libopenh264enc.c @@ -139,11 +139,6 @@ static av_cold int svc_encode_init(AVCodecContext *avctx) if (avctx->framerate.num > 0 && avctx->framerate.den > 0) { param.fMaxFrameRate = av_q2d(avctx->framerate); } else { - if (avctx->ticks_per_frame > INT_MAX / avctx->time_base.num) { - av_log(avctx, AV_LOG_ERROR, - "Could not set framerate for libopenh264enc: integer overflow\n"); - return AVERROR(EINVAL); - } param.fMaxFrameRate = 1.0 / av_q2d(avctx->time_base) / FFMAX(avctx->ticks_per_frame, 1); } param.iPicWidth = avctx->width; From f618004bc1fa31f4952ea420c3969ee4999d079b Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Thu, 4 May 2023 11:35:31 +0200 Subject: [PATCH 1011/2172] lavc/libvpxenc: send frame durations to the encoder Adapt similar code from libaomenc - stop using ticks_per_frame except as a last resort. --- libavcodec/libvpxenc.c | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/libavcodec/libvpxenc.c b/libavcodec/libvpxenc.c index a20e9498429..f70cc87c411 100644 --- a/libavcodec/libvpxenc.c +++ b/libavcodec/libvpxenc.c @@ -1692,6 +1692,7 @@ static int vpx_encode(AVCodecContext *avctx, AVPacket *pkt, const struct vpx_codec_enc_cfg *enccfg = ctx->encoder.config.enc; vpx_svc_layer_id_t layer_id; int layer_id_valid = 0; + unsigned long duration = 0; if (avctx->qmax >= 0 && enccfg->rc_max_quantizer != avctx->qmax) { struct vpx_codec_enc_cfg cfg = *enccfg; @@ -1820,8 +1821,18 @@ static int vpx_encode(AVCodecContext *avctx, AVPacket *pkt, #endif } + if (frame && frame->duration > ULONG_MAX) { + av_log(avctx, AV_LOG_WARNING, + "Frame duration too large: %"PRId64"\n", frame->duration); + } else if (frame && frame->duration) + duration = frame->duration; + else if (avctx->framerate.num > 0 && avctx->framerate.den > 0) + duration = av_rescale_q(1, av_inv_q(avctx->framerate), avctx->time_base); + else + duration = avctx->ticks_per_frame ? avctx->ticks_per_frame : 1; + res = vpx_codec_encode(&ctx->encoder, rawimg, timestamp, - avctx->ticks_per_frame, flags, ctx->deadline); + duration, flags, ctx->deadline); if (res != VPX_CODEC_OK) { log_encoder_error(avctx, "Error encoding frame"); return AVERROR_INVALIDDATA; @@ -1829,7 +1840,7 @@ static int vpx_encode(AVCodecContext *avctx, AVPacket *pkt, if (ctx->is_alpha) { res = vpx_codec_encode(&ctx->encoder_alpha, rawimg_alpha, timestamp, - avctx->ticks_per_frame, flags, ctx->deadline); + duration, flags, ctx->deadline); if (res != VPX_CODEC_OK) { log_encoder_error(avctx, "Error encoding alpha frame"); return AVERROR_INVALIDDATA; From 2953ebe7b6925b045e5652420cf07146fbbb17ab Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Sat, 11 Mar 2023 17:54:46 +0100 Subject: [PATCH 1012/2172] tests/fate: add a simple test for libx264 Since this is an external encoder not under our control, we cannot test the encoded output exactly as is done for internal encoders. We can still test however that the output is decodable and produces the expected number of frames with expected dimensions, pixel formats, and timestamps. --- tests/Makefile | 1 + tests/fate-run.sh | 16 +++++++ tests/fate/enc_external.mak | 6 +++ tests/ref/fate/libx264-simple | 85 +++++++++++++++++++++++++++++++++++ 4 files changed, 108 insertions(+) create mode 100644 tests/fate/enc_external.mak create mode 100644 tests/ref/fate/libx264-simple diff --git a/tests/Makefile b/tests/Makefile index 35ea824663c..e09f30a0fc1 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -177,6 +177,7 @@ include $(SRC_PATH)/tests/fate/dpcm.mak include $(SRC_PATH)/tests/fate/dvvideo.mak include $(SRC_PATH)/tests/fate/ea.mak include $(SRC_PATH)/tests/fate/exif.mak +include $(SRC_PATH)/tests/fate/enc_external.mak # Must be included after lavf-video.mak include $(SRC_PATH)/tests/fate/ffmpeg.mak include $(SRC_PATH)/tests/fate/ffprobe.mak diff --git a/tests/fate-run.sh b/tests/fate-run.sh index 61cc59acc08..e12279e4cfe 100755 --- a/tests/fate-run.sh +++ b/tests/fate-run.sh @@ -282,6 +282,22 @@ stream_remux(){ run ffprobe${PROGSUF}${EXECSUF} -bitexact $ffprobe_opts $tencfile || return } +# this function is for testing external encoders, +# where the precise output is not controlled by us +# we can still test e.g. that the output can be decoded correctly +enc_external(){ + srcfile=$1 + enc_fmt=$2 + enc_opt=$3 + probe_opt=$4 + + srcfile=$(target_path $srcfile) + encfile=$(target_path "${outdir}/${test}.${enc_fmt}") + + ffmpeg -i $srcfile $enc_opt -f $enc_fmt -y $encfile || return + run ffprobe${PROGSUF}${EXECSUF} -bitexact $probe_opt $encfile || return +} + # FIXME: There is a certain duplication between the avconv-related helper # functions above and below that should be refactored. ffmpeg2="$target_exec ${target_path}/ffmpeg${PROGSUF}${EXECSUF}" diff --git a/tests/fate/enc_external.mak b/tests/fate/enc_external.mak new file mode 100644 index 00000000000..7eabebcc515 --- /dev/null +++ b/tests/fate/enc_external.mak @@ -0,0 +1,6 @@ +FATE_ENC_EXTERNAL-$(call ENCDEC, LIBX264 H264, MOV, H264_DEMUXER) += fate-libx264-simple +fate-libx264-simple: CMD = enc_external $(TARGET_SAMPLES)/h264-conformance/BA1_Sony_D.jsv \ + mp4 "-c:v libx264" "-show_entries frame=width,height,pix_fmt,pts,pkt_dts -of flat" + +FATE_SAMPLES_FFMPEG_FFPROBE += $(FATE_ENC_EXTERNAL-yes) +fate-enc-external: $(FATE_ENC_EXTERNAL-yes) diff --git a/tests/ref/fate/libx264-simple b/tests/ref/fate/libx264-simple new file mode 100644 index 00000000000..b7f7e67c3b7 --- /dev/null +++ b/tests/ref/fate/libx264-simple @@ -0,0 +1,85 @@ +frames.frame.0.pts=0 +frames.frame.0.pkt_dts=0 +frames.frame.0.width=176 +frames.frame.0.height=144 +frames.frame.0.pix_fmt="yuv420p" +frames.frame.1.pts=512 +frames.frame.1.pkt_dts=512 +frames.frame.1.width=176 +frames.frame.1.height=144 +frames.frame.1.pix_fmt="yuv420p" +frames.frame.2.pts=1024 +frames.frame.2.pkt_dts=1024 +frames.frame.2.width=176 +frames.frame.2.height=144 +frames.frame.2.pix_fmt="yuv420p" +frames.frame.3.pts=1536 +frames.frame.3.pkt_dts=1536 +frames.frame.3.width=176 +frames.frame.3.height=144 +frames.frame.3.pix_fmt="yuv420p" +frames.frame.4.pts=2048 +frames.frame.4.pkt_dts=2048 +frames.frame.4.width=176 +frames.frame.4.height=144 +frames.frame.4.pix_fmt="yuv420p" +frames.frame.5.pts=2560 +frames.frame.5.pkt_dts=2560 +frames.frame.5.width=176 +frames.frame.5.height=144 +frames.frame.5.pix_fmt="yuv420p" +frames.frame.6.pts=3072 +frames.frame.6.pkt_dts=3072 +frames.frame.6.width=176 +frames.frame.6.height=144 +frames.frame.6.pix_fmt="yuv420p" +frames.frame.7.pts=3584 +frames.frame.7.pkt_dts=3584 +frames.frame.7.width=176 +frames.frame.7.height=144 +frames.frame.7.pix_fmt="yuv420p" +frames.frame.8.pts=4096 +frames.frame.8.pkt_dts=4096 +frames.frame.8.width=176 +frames.frame.8.height=144 +frames.frame.8.pix_fmt="yuv420p" +frames.frame.9.pts=4608 +frames.frame.9.pkt_dts=4608 +frames.frame.9.width=176 +frames.frame.9.height=144 +frames.frame.9.pix_fmt="yuv420p" +frames.frame.10.pts=5120 +frames.frame.10.pkt_dts=5120 +frames.frame.10.width=176 +frames.frame.10.height=144 +frames.frame.10.pix_fmt="yuv420p" +frames.frame.11.pts=5632 +frames.frame.11.pkt_dts=5632 +frames.frame.11.width=176 +frames.frame.11.height=144 +frames.frame.11.pix_fmt="yuv420p" +frames.frame.12.pts=6144 +frames.frame.12.pkt_dts=6144 +frames.frame.12.width=176 +frames.frame.12.height=144 +frames.frame.12.pix_fmt="yuv420p" +frames.frame.13.pts=6656 +frames.frame.13.pkt_dts=6656 +frames.frame.13.width=176 +frames.frame.13.height=144 +frames.frame.13.pix_fmt="yuv420p" +frames.frame.14.pts=7168 +frames.frame.14.pkt_dts=7168 +frames.frame.14.width=176 +frames.frame.14.height=144 +frames.frame.14.pix_fmt="yuv420p" +frames.frame.15.pts=7680 +frames.frame.15.pkt_dts="N/A" +frames.frame.15.width=176 +frames.frame.15.height=144 +frames.frame.15.pix_fmt="yuv420p" +frames.frame.16.pts=8192 +frames.frame.16.pkt_dts="N/A" +frames.frame.16.width=176 +frames.frame.16.height=144 +frames.frame.16.pix_fmt="yuv420p" From 7d1d61cc5f57708434ba720b03234b3dd93a4d1e Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Thu, 4 May 2023 11:50:48 +0200 Subject: [PATCH 1013/2172] lavc: deprecate AVCodecContext.ticks_per_frame For encoding, this field is entirely redundant with AVCodecContext.framerate. For decoding, this field is entirely redundant with AV_CODEC_PROP_FIELDS. --- doc/APIchanges | 5 +++++ doc/codecs.texi | 1 - libavcodec/amfenc_av1.c | 8 +++++++- libavcodec/amfenc_h264.c | 8 +++++++- libavcodec/amfenc_hevc.c | 8 +++++++- libavcodec/avcodec.h | 8 ++++++++ libavcodec/encode.c | 4 ++++ libavcodec/h264_slice.c | 2 +- libavcodec/h264dec.c | 4 ++++ libavcodec/libaomenc.c | 8 +++++++- libavcodec/libkvazaar.c | 8 +++++++- libavcodec/libopenh264enc.c | 8 +++++++- libavcodec/librav1e.c | 9 +++++++-- libavcodec/libsvtav1.c | 8 +++++++- libavcodec/libvpxenc.c | 8 +++++++- libavcodec/libx264.c | 8 +++++++- libavcodec/libx265.c | 8 +++++++- libavcodec/mfenc.c | 4 ++++ libavcodec/mpeg12dec.c | 8 ++++++++ libavcodec/mpegvideo_parser.c | 8 ++++++++ libavcodec/msmpeg4enc.c | 8 +++++++- libavcodec/nvenc.c | 16 ++++++++++++++-- libavcodec/options_table.h | 2 ++ libavcodec/pthread_frame.c | 4 ++++ libavcodec/ratecontrol.c | 8 +++++++- libavcodec/vc1.c | 11 ++++++++--- libavcodec/vc1_parser.c | 3 +-- libavcodec/vc1dec.c | 1 - libavcodec/version_major.h | 1 + libavformat/avformat.c | 15 +++++++++++++-- 30 files changed, 176 insertions(+), 26 deletions(-) diff --git a/doc/APIchanges b/doc/APIchanges index b0486462833..d2255867a8c 100644 --- a/doc/APIchanges +++ b/doc/APIchanges @@ -2,6 +2,11 @@ The last version increases of all libraries were on 2023-02-09 API changes, most recent first: +2023-05-xx - xxxxxxxxxx - lavc 60 - avcodec.h + Depreate AVCodecContext.ticks_per_frame in favor of + AVCodecContext.framerate (encoding) and + AV_CODEC_PROP_FIELDS (decoding). + 2023-05-xx - xxxxxxxxxx - lavc 60.12.100 - codec_desc.h Add AV_CODEC_PROP_FIELDS. diff --git a/doc/codecs.texi b/doc/codecs.texi index 1adacd2b595..f903dad7545 100644 --- a/doc/codecs.texi +++ b/doc/codecs.texi @@ -775,7 +775,6 @@ Possible values: @end table @item rc_max_vbv_use @var{float} (@emph{encoding,video}) @item rc_min_vbv_use @var{float} (@emph{encoding,video}) -@item ticks_per_frame @var{integer} (@emph{decoding/encoding,audio,video}) @item color_primaries @var{integer} (@emph{decoding/encoding,video}) Possible values: diff --git a/libavcodec/amfenc_av1.c b/libavcodec/amfenc_av1.c index 8093cb73575..ad09b7910a2 100644 --- a/libavcodec/amfenc_av1.c +++ b/libavcodec/amfenc_av1.c @@ -117,7 +117,13 @@ static av_cold int amf_encode_init_av1(AVCodecContext* avctx) framerate = AMFConstructRate(avctx->framerate.num, avctx->framerate.den); } else { - framerate = AMFConstructRate(avctx->time_base.den, avctx->time_base.num * avctx->ticks_per_frame); +FF_DISABLE_DEPRECATION_WARNINGS + framerate = AMFConstructRate(avctx->time_base.den, avctx->time_base.num +#if FF_API_TICKS_PER_FRAME + * avctx->ticks_per_frame +#endif + ); +FF_ENABLE_DEPRECATION_WARNINGS } if ((ret = ff_amf_encode_init(avctx)) < 0) diff --git a/libavcodec/amfenc_h264.c b/libavcodec/amfenc_h264.c index eaf7f974f3c..d2fc33971b3 100644 --- a/libavcodec/amfenc_h264.c +++ b/libavcodec/amfenc_h264.c @@ -142,7 +142,13 @@ static av_cold int amf_encode_init_h264(AVCodecContext *avctx) if (avctx->framerate.num > 0 && avctx->framerate.den > 0) { framerate = AMFConstructRate(avctx->framerate.num, avctx->framerate.den); } else { - framerate = AMFConstructRate(avctx->time_base.den, avctx->time_base.num * avctx->ticks_per_frame); +FF_DISABLE_DEPRECATION_WARNINGS + framerate = AMFConstructRate(avctx->time_base.den, avctx->time_base.num +#if FF_API_TICKS_PER_FRAME + * avctx->ticks_per_frame +#endif + ); +FF_ENABLE_DEPRECATION_WARNINGS } if ((ret = ff_amf_encode_init(avctx)) != 0) diff --git a/libavcodec/amfenc_hevc.c b/libavcodec/amfenc_hevc.c index 9b46946f1ec..674a4095d6c 100644 --- a/libavcodec/amfenc_hevc.c +++ b/libavcodec/amfenc_hevc.c @@ -109,7 +109,13 @@ static av_cold int amf_encode_init_hevc(AVCodecContext *avctx) if (avctx->framerate.num > 0 && avctx->framerate.den > 0) { framerate = AMFConstructRate(avctx->framerate.num, avctx->framerate.den); } else { - framerate = AMFConstructRate(avctx->time_base.den, avctx->time_base.num * avctx->ticks_per_frame); +FF_DISABLE_DEPRECATION_WARNINGS + framerate = AMFConstructRate(avctx->time_base.den, avctx->time_base.num +#if FF_API_TICKS_PER_FRAME + * avctx->ticks_per_frame +#endif + ); +FF_ENABLE_DEPRECATION_WARNINGS } if ((ret = ff_amf_encode_init(avctx)) < 0) diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h index 1e91b9cb532..06b1a120abe 100644 --- a/libavcodec/avcodec.h +++ b/libavcodec/avcodec.h @@ -556,14 +556,22 @@ typedef struct AVCodecContext { */ AVRational time_base; +#if FF_API_TICKS_PER_FRAME /** * For some codecs, the time base is closer to the field rate than the frame rate. * Most notably, H.264 and MPEG-2 specify time_base as half of frame duration * if no telecine is used ... * * Set to time_base ticks per frame. Default 1, e.g., H.264/MPEG-2 set it to 2. + * + * @deprecated + * - decoding: Use AVCodecDescriptor.props & AV_CODEC_PROP_FIELDS + * - encoding: Set AVCodecContext.framerate instead + * */ + attribute_deprecated int ticks_per_frame; +#endif /** * Codec delay. diff --git a/libavcodec/encode.c b/libavcodec/encode.c index 14e28767425..ab5f889615e 100644 --- a/libavcodec/encode.c +++ b/libavcodec/encode.c @@ -582,6 +582,8 @@ static int encode_preinit_video(AVCodecContext *avctx) return AVERROR(EINVAL); } +#if FF_API_TICKS_PER_FRAME +FF_DISABLE_DEPRECATION_WARNINGS if (avctx->ticks_per_frame && avctx->time_base.num && avctx->ticks_per_frame > INT_MAX / avctx->time_base.num) { av_log(avctx, AV_LOG_ERROR, @@ -591,6 +593,8 @@ static int encode_preinit_video(AVCodecContext *avctx) avctx->time_base.den); return AVERROR(EINVAL); } +FF_ENABLE_DEPRECATION_WARNINGS +#endif if (avctx->hw_frames_ctx) { AVHWFramesContext *frames_ctx = (AVHWFramesContext*)avctx->hw_frames_ctx->data; diff --git a/libavcodec/h264_slice.c b/libavcodec/h264_slice.c index 85267825608..be7a8e0b5ab 100644 --- a/libavcodec/h264_slice.c +++ b/libavcodec/h264_slice.c @@ -957,7 +957,7 @@ static int h264_slice_header_init(H264Context *h) if (h->x264_build < 44U) den *= 2; av_reduce(&h->avctx->framerate.den, &h->avctx->framerate.num, - sps->num_units_in_tick * h->avctx->ticks_per_frame, den, 1 << 30); + sps->num_units_in_tick * 2, den, 1 << 30); } ff_h264_free_tables(h); diff --git a/libavcodec/h264dec.c b/libavcodec/h264dec.c index cdd4b98c838..521b1e2235d 100644 --- a/libavcodec/h264dec.c +++ b/libavcodec/h264dec.c @@ -382,7 +382,11 @@ static av_cold int h264_decode_init(AVCodecContext *avctx) return AVERROR_UNKNOWN; } +#if FF_API_TICKS_PER_FRAME +FF_DISABLE_DEPRECATION_WARNINGS avctx->ticks_per_frame = 2; +FF_ENABLE_DEPRECATION_WARNINGS +#endif if (!avctx->internal->is_copy) { if (avctx->extradata_size > 0 && avctx->extradata) { diff --git a/libavcodec/libaomenc.c b/libavcodec/libaomenc.c index 1d3a4ae64c5..16747e7e92f 100644 --- a/libavcodec/libaomenc.c +++ b/libavcodec/libaomenc.c @@ -1300,7 +1300,13 @@ static int aom_encode(AVCodecContext *avctx, AVPacket *pkt, else if (avctx->framerate.num > 0 && avctx->framerate.den > 0) duration = av_rescale_q(1, av_inv_q(avctx->framerate), avctx->time_base); else - duration = avctx->ticks_per_frame ? avctx->ticks_per_frame : 1; +FF_DISABLE_DEPRECATION_WARNINGS + duration = +#if FF_API_TICKS_PER_FRAME + avctx->ticks_per_frame ? avctx->ticks_per_frame : +#endif + 1; +FF_ENABLE_DEPRECATION_WARNINGS switch (frame->color_range) { case AVCOL_RANGE_MPEG: diff --git a/libavcodec/libkvazaar.c b/libavcodec/libkvazaar.c index b3faa0a64bd..2ef34dd82e2 100644 --- a/libavcodec/libkvazaar.c +++ b/libavcodec/libkvazaar.c @@ -86,7 +86,13 @@ static av_cold int libkvazaar_init(AVCodecContext *avctx) cfg->framerate_denom = avctx->framerate.den; } else { cfg->framerate_num = avctx->time_base.den; - cfg->framerate_denom = avctx->time_base.num * avctx->ticks_per_frame; +FF_DISABLE_DEPRECATION_WARNINGS + cfg->framerate_denom = avctx->time_base.num +#if FF_API_TICKS_PER_FRAME + * avctx->ticks_per_frame +#endif + ; +FF_ENABLE_DEPRECATION_WARNINGS } cfg->target_bitrate = avctx->bit_rate; cfg->vui.sar_width = avctx->sample_aspect_ratio.num; diff --git a/libavcodec/libopenh264enc.c b/libavcodec/libopenh264enc.c index 15c3822824b..5b59af6f947 100644 --- a/libavcodec/libopenh264enc.c +++ b/libavcodec/libopenh264enc.c @@ -139,7 +139,13 @@ static av_cold int svc_encode_init(AVCodecContext *avctx) if (avctx->framerate.num > 0 && avctx->framerate.den > 0) { param.fMaxFrameRate = av_q2d(avctx->framerate); } else { - param.fMaxFrameRate = 1.0 / av_q2d(avctx->time_base) / FFMAX(avctx->ticks_per_frame, 1); +FF_DISABLE_DEPRECATION_WARNINGS + param.fMaxFrameRate = 1.0 / av_q2d(avctx->time_base) +#if FF_API_TICKS_PER_FRAME + / FFMAX(avctx->ticks_per_frame, 1) +#endif + ; +FF_ENABLE_DEPRECATION_WARNINGS } param.iPicWidth = avctx->width; param.iPicHeight = avctx->height; diff --git a/libavcodec/librav1e.c b/libavcodec/librav1e.c index 08affabe3e0..56539435a7e 100644 --- a/libavcodec/librav1e.c +++ b/libavcodec/librav1e.c @@ -219,10 +219,15 @@ static av_cold int librav1e_encode_init(AVCodecContext *avctx) avctx->framerate.den, avctx->framerate.num }); } else { +FF_DISABLE_DEPRECATION_WARNINGS rav1e_config_set_time_base(cfg, (RaRational) { - avctx->time_base.num * avctx->ticks_per_frame, - avctx->time_base.den + avctx->time_base.num +#if FF_API_TICKS_PER_FRAME + * avctx->ticks_per_frame +#endif + , avctx->time_base.den }); +FF_ENABLE_DEPRECATION_WARNINGS } if ((avctx->flags & AV_CODEC_FLAG_PASS1 || avctx->flags & AV_CODEC_FLAG_PASS2) && !avctx->bit_rate) { diff --git a/libavcodec/libsvtav1.c b/libavcodec/libsvtav1.c index 952ed0e1e71..718a04d221a 100644 --- a/libavcodec/libsvtav1.c +++ b/libavcodec/libsvtav1.c @@ -250,7 +250,13 @@ static int config_enc_params(EbSvtAv1EncConfiguration *param, param->frame_rate_denominator = avctx->framerate.den; } else { param->frame_rate_numerator = avctx->time_base.den; - param->frame_rate_denominator = avctx->time_base.num * avctx->ticks_per_frame; +FF_DISABLE_DEPRECATION_WARNINGS + param->frame_rate_denominator = avctx->time_base.num +#if FF_API_TICKS_PER_FRAME + * avctx->ticks_per_frame +#endif + ; +FF_ENABLE_DEPRECATION_WARNINGS } /* 2 = IDR, closed GOP, 1 = CRA, open GOP */ diff --git a/libavcodec/libvpxenc.c b/libavcodec/libvpxenc.c index f70cc87c411..8833df2d68c 100644 --- a/libavcodec/libvpxenc.c +++ b/libavcodec/libvpxenc.c @@ -1829,7 +1829,13 @@ static int vpx_encode(AVCodecContext *avctx, AVPacket *pkt, else if (avctx->framerate.num > 0 && avctx->framerate.den > 0) duration = av_rescale_q(1, av_inv_q(avctx->framerate), avctx->time_base); else - duration = avctx->ticks_per_frame ? avctx->ticks_per_frame : 1; +FF_DISABLE_DEPRECATION_WARNINGS + duration = +#if FF_API_TICKS_PER_FRAME + avctx->ticks_per_frame ? avctx->ticks_per_frame : +#endif + 1; +FF_ENABLE_DEPRECATION_WARNINGS res = vpx_codec_encode(&ctx->encoder, rawimg, timestamp, duration, flags, ctx->deadline); diff --git a/libavcodec/libx264.c b/libavcodec/libx264.c index 3aea29e9956..5736f1efa7f 100644 --- a/libavcodec/libx264.c +++ b/libavcodec/libx264.c @@ -1018,7 +1018,13 @@ static av_cold int X264_init(AVCodecContext *avctx) x4->params.i_fps_den = avctx->framerate.den; } else { x4->params.i_fps_num = avctx->time_base.den; - x4->params.i_fps_den = avctx->time_base.num * avctx->ticks_per_frame; +FF_DISABLE_DEPRECATION_WARNINGS + x4->params.i_fps_den = avctx->time_base.num +#if FF_API_TICKS_PER_FRAME + * avctx->ticks_per_frame +#endif + ; +FF_ENABLE_DEPRECATION_WARNINGS } x4->params.analyse.b_psnr = avctx->flags & AV_CODEC_FLAG_PSNR; diff --git a/libavcodec/libx265.c b/libavcodec/libx265.c index 420d0953af1..873b3021eea 100644 --- a/libavcodec/libx265.c +++ b/libavcodec/libx265.c @@ -220,7 +220,13 @@ static av_cold int libx265_encode_init(AVCodecContext *avctx) ctx->params->fpsDenom = avctx->framerate.den; } else { ctx->params->fpsNum = avctx->time_base.den; - ctx->params->fpsDenom = avctx->time_base.num * avctx->ticks_per_frame; +FF_DISABLE_DEPRECATION_WARNINGS + ctx->params->fpsDenom = avctx->time_base.num +#if FF_API_TICKS_PER_FRAME + * avctx->ticks_per_frame +#endif + ; +FF_ENABLE_DEPRECATION_WARNINGS } ctx->params->sourceWidth = avctx->width; ctx->params->sourceHeight = avctx->height; diff --git a/libavcodec/mfenc.c b/libavcodec/mfenc.c index f3415df10b0..8d950a3109f 100644 --- a/libavcodec/mfenc.c +++ b/libavcodec/mfenc.c @@ -659,7 +659,11 @@ static int mf_encv_output_adjust(AVCodecContext *avctx, IMFMediaType *type) framerate = avctx->framerate; } else { framerate = av_inv_q(avctx->time_base); +#if FF_API_TICKS_PER_FRAME +FF_DISABLE_DEPRECATION_WARNINGS framerate.den *= avctx->ticks_per_frame; +FF_ENABLE_DEPRECATION_WARNINGS +#endif } ff_MFSetAttributeRatio((IMFAttributes *)type, &MF_MT_FRAME_RATE, framerate.num, framerate.den); diff --git a/libavcodec/mpeg12dec.c b/libavcodec/mpeg12dec.c index ebde68a4dda..27c862ffb22 100644 --- a/libavcodec/mpeg12dec.c +++ b/libavcodec/mpeg12dec.c @@ -1265,7 +1265,11 @@ static int mpeg_decode_postinit(AVCodecContext *avctx) if (avctx->codec_id == AV_CODEC_ID_MPEG1VIDEO) { // MPEG-1 fps avctx->framerate = ff_mpeg12_frame_rate_tab[s1->frame_rate_index]; +#if FF_API_TICKS_PER_FRAME +FF_DISABLE_DEPRECATION_WARNINGS avctx->ticks_per_frame = 1; +FF_ENABLE_DEPRECATION_WARNINGS +#endif avctx->chroma_sample_location = AVCHROMA_LOC_CENTER; } else { // MPEG-2 @@ -1275,7 +1279,11 @@ static int mpeg_decode_postinit(AVCodecContext *avctx) ff_mpeg12_frame_rate_tab[s1->frame_rate_index].num * s1->frame_rate_ext.num, ff_mpeg12_frame_rate_tab[s1->frame_rate_index].den * s1->frame_rate_ext.den, 1 << 30); +#if FF_API_TICKS_PER_FRAME +FF_DISABLE_DEPRECATION_WARNINGS avctx->ticks_per_frame = 2; +FF_ENABLE_DEPRECATION_WARNINGS +#endif switch (s->chroma_format) { case 1: avctx->chroma_sample_location = AVCHROMA_LOC_LEFT; break; diff --git a/libavcodec/mpegvideo_parser.c b/libavcodec/mpegvideo_parser.c index 08e53169601..1204789c670 100644 --- a/libavcodec/mpegvideo_parser.c +++ b/libavcodec/mpegvideo_parser.c @@ -145,7 +145,11 @@ static void mpegvideo_extract_headers(AVCodecParserContext *s, pc->frame_rate = avctx->framerate = ff_mpeg12_frame_rate_tab[frame_rate_index]; bit_rate = (buf[4]<<10) | (buf[5]<<2) | (buf[6]>>6); avctx->codec_id = AV_CODEC_ID_MPEG1VIDEO; +#if FF_API_TICKS_PER_FRAME +FF_DISABLE_DEPRECATION_WARNINGS avctx->ticks_per_frame = 1; +FF_ENABLE_DEPRECATION_WARNINGS +#endif } break; case EXT_START_CODE: @@ -177,7 +181,11 @@ static void mpegvideo_extract_headers(AVCodecParserContext *s, avctx->framerate.num = pc->frame_rate.num * (frame_rate_ext_n + 1); avctx->framerate.den = pc->frame_rate.den * (frame_rate_ext_d + 1); avctx->codec_id = AV_CODEC_ID_MPEG2VIDEO; +#if FF_API_TICKS_PER_FRAME +FF_DISABLE_DEPRECATION_WARNINGS avctx->ticks_per_frame = 2; +FF_ENABLE_DEPRECATION_WARNINGS +#endif } break; case 0x8: /* picture coding extension */ diff --git a/libavcodec/msmpeg4enc.c b/libavcodec/msmpeg4enc.c index df190d376c0..9828901beaf 100644 --- a/libavcodec/msmpeg4enc.c +++ b/libavcodec/msmpeg4enc.c @@ -285,7 +285,13 @@ void ff_msmpeg4_encode_ext_header(MpegEncContext * s) if (s->avctx->framerate.num > 0 && s->avctx->framerate.den > 0) fps = s->avctx->framerate.num / s->avctx->framerate.den; else - fps = s->avctx->time_base.den / s->avctx->time_base.num / FFMAX(s->avctx->ticks_per_frame, 1); +FF_DISABLE_DEPRECATION_WARNINGS + fps = s->avctx->time_base.den / s->avctx->time_base.num +#if FF_API_TICKS_PER_FRAME + / FFMAX(s->avctx->ticks_per_frame, 1) +#endif + ; +FF_ENABLE_DEPRECATION_WARNINGS put_bits(&s->pb, 5, FFMIN(fps, 31)); //yes 29.97 -> 29 diff --git a/libavcodec/nvenc.c b/libavcodec/nvenc.c index b2f6253a430..c1798ce564b 100644 --- a/libavcodec/nvenc.c +++ b/libavcodec/nvenc.c @@ -1571,7 +1571,13 @@ static av_cold int nvenc_setup_encoder(AVCodecContext *avctx) ctx->init_encode_params.frameRateDen = avctx->framerate.den; } else { ctx->init_encode_params.frameRateNum = avctx->time_base.den; - ctx->init_encode_params.frameRateDen = avctx->time_base.num * avctx->ticks_per_frame; +FF_DISABLE_DEPRECATION_WARNINGS + ctx->init_encode_params.frameRateDen = avctx->time_base.num +#if FF_API_TICKS_PER_FRAME + * avctx->ticks_per_frame +#endif + ; +FF_ENABLE_DEPRECATION_WARNINGS } ctx->init_encode_params.enableEncodeAsync = 0; @@ -2266,8 +2272,14 @@ static int nvenc_set_timestamp(AVCodecContext *avctx, dts = reorder_queue_dequeue(ctx->reorder_queue, avctx, pkt); if (avctx->codec_descriptor->props & AV_CODEC_PROP_REORDER) { +FF_DISABLE_DEPRECATION_WARNINGS pkt->dts = dts - - FFMAX(ctx->encode_config.frameIntervalP - 1, 0) * FFMAX(avctx->ticks_per_frame, 1) * FFMAX(avctx->time_base.num, 1); + FFMAX(ctx->encode_config.frameIntervalP - 1, 0) +#if FF_API_TICKS_PER_FRAME + * FFMAX(avctx->ticks_per_frame, 1) +#endif + * FFMAX(avctx->time_base.num, 1); +FF_ENABLE_DEPRECATION_WARNINGS } else { pkt->dts = pkt->pts; } diff --git a/libavcodec/options_table.h b/libavcodec/options_table.h index 4f5918c7f67..03059cc39c9 100644 --- a/libavcodec/options_table.h +++ b/libavcodec/options_table.h @@ -276,7 +276,9 @@ static const AVOption avcodec_options[] = { #endif {"rc_max_vbv_use", NULL, OFFSET(rc_max_available_vbv_use), AV_OPT_TYPE_FLOAT, {.dbl = 0 }, 0.0, FLT_MAX, V|E}, {"rc_min_vbv_use", NULL, OFFSET(rc_min_vbv_overflow_use), AV_OPT_TYPE_FLOAT, {.dbl = 3 }, 0.0, FLT_MAX, V|E}, +#if FF_API_TICKS_PER_FRAME {"ticks_per_frame", NULL, OFFSET(ticks_per_frame), AV_OPT_TYPE_INT, {.i64 = 1 }, 1, INT_MAX, A|V|E|D}, +#endif {"color_primaries", "color primaries", OFFSET(color_primaries), AV_OPT_TYPE_INT, {.i64 = AVCOL_PRI_UNSPECIFIED }, 1, INT_MAX, V|E|D, "color_primaries_type"}, {"bt709", "BT.709", 0, AV_OPT_TYPE_CONST, {.i64 = AVCOL_PRI_BT709 }, INT_MIN, INT_MAX, V|E|D, "color_primaries_type"}, {"unknown", "Unspecified", 0, AV_OPT_TYPE_CONST, {.i64 = AVCOL_PRI_UNSPECIFIED }, INT_MIN, INT_MAX, V|E|D, "color_primaries_type"}, diff --git a/libavcodec/pthread_frame.c b/libavcodec/pthread_frame.c index 74864e19c5a..773e78ae345 100644 --- a/libavcodec/pthread_frame.c +++ b/libavcodec/pthread_frame.c @@ -286,7 +286,11 @@ static int update_context_from_thread(AVCodecContext *dst, AVCodecContext *src, dst->level = src->level; dst->bits_per_raw_sample = src->bits_per_raw_sample; +#if FF_API_TICKS_PER_FRAME +FF_DISABLE_DEPRECATION_WARNINGS dst->ticks_per_frame = src->ticks_per_frame; +FF_ENABLE_DEPRECATION_WARNINGS +#endif dst->color_primaries = src->color_primaries; dst->color_trc = src->color_trc; diff --git a/libavcodec/ratecontrol.c b/libavcodec/ratecontrol.c index 890ae33cb30..649f570c9d9 100644 --- a/libavcodec/ratecontrol.c +++ b/libavcodec/ratecontrol.c @@ -60,7 +60,13 @@ static double get_fps(AVCodecContext *avctx) if (avctx->framerate.num > 0 && avctx->framerate.den > 0) return av_q2d(avctx->framerate); - return 1.0 / av_q2d(avctx->time_base) / FFMAX(avctx->ticks_per_frame, 1); +FF_DISABLE_DEPRECATION_WARNINGS + return 1.0 / av_q2d(avctx->time_base) +#if FF_API_TICKS_PER_FRAME + / FFMAX(avctx->ticks_per_frame, 1) +#endif + ; +FF_ENABLE_DEPRECATION_WARNINGS } static inline double qp2bits(RateControlEntry *rce, double qp) diff --git a/libavcodec/vc1.c b/libavcodec/vc1.c index d4014d25abe..795c6db5418 100644 --- a/libavcodec/vc1.c +++ b/libavcodec/vc1.c @@ -418,6 +418,14 @@ static int decode_sequence_header_adv(VC1Context *v, GetBitContext *gb) v->s.loop_filter, v->chromaformat, v->broadcast, v->interlace, v->tfcntrflag, v->finterpflag); +#if FF_API_TICKS_PER_FRAME +FF_DISABLE_DEPRECATION_WARNINGS + if (v->broadcast) { // Pulldown may be present + v->s.avctx->ticks_per_frame = 2; + } +FF_ENABLE_DEPRECATION_WARNINGS +#endif + v->psf = get_bits1(gb); if (v->psf) { //PsF, 6.1.13 av_log(v->s.avctx, AV_LOG_ERROR, "Progressive Segmented Frame mode: not supported (yet)\n"); @@ -467,9 +475,6 @@ static int decode_sequence_header_adv(VC1Context *v, GetBitContext *gb) v->s.avctx->framerate.num = ff_vc1_fps_nr[nr - 1] * 1000; } } - if (v->broadcast) { // Pulldown may be present - v->s.avctx->ticks_per_frame = 2; - } } if (get_bits1(gb)) { diff --git a/libavcodec/vc1_parser.c b/libavcodec/vc1_parser.c index 4167215fb11..ec284dca009 100644 --- a/libavcodec/vc1_parser.c +++ b/libavcodec/vc1_parser.c @@ -89,11 +89,10 @@ static void vc1_extract_header(AVCodecParserContext *s, AVCodecContext *avctx, else s->pict_type = vpc->v.s.pict_type; - if (avctx->ticks_per_frame > 1){ + if (vpc->v.broadcast){ // process pulldown flags s->repeat_pict = 1; // Pulldown flags are only valid when 'broadcast' has been set. - // So ticks_per_frame will be 2 if (vpc->v.rff){ // repeat field s->repeat_pict = 2; diff --git a/libavcodec/vc1dec.c b/libavcodec/vc1dec.c index 8298cefbc76..9e343d003f8 100644 --- a/libavcodec/vc1dec.c +++ b/libavcodec/vc1dec.c @@ -1087,7 +1087,6 @@ static int vc1_decode_frame(AVCodecContext *avctx, AVFrame *pict, // process pulldown flags s->current_picture_ptr->f->repeat_pict = 0; // Pulldown flags are only valid when 'broadcast' has been set. - // So ticks_per_frame will be 2 if (v->rff) { // repeat field s->current_picture_ptr->f->repeat_pict = 1; diff --git a/libavcodec/version_major.h b/libavcodec/version_major.h index 8c3ce431652..2f5138d0794 100644 --- a/libavcodec/version_major.h +++ b/libavcodec/version_major.h @@ -47,6 +47,7 @@ #define FF_API_AVCTX_FRAME_NUMBER (LIBAVCODEC_VERSION_MAJOR < 61) #define FF_API_SLICE_OFFSET (LIBAVCODEC_VERSION_MAJOR < 61) #define FF_API_SUBFRAMES (LIBAVCODEC_VERSION_MAJOR < 61) +#define FF_API_TICKS_PER_FRAME (LIBAVCODEC_VERSION_MAJOR < 61) // reminder to remove CrystalHD decoders on next major bump #define FF_CODEC_CRYSTAL_HD (LIBAVCODEC_VERSION_MAJOR < 61) diff --git a/libavformat/avformat.c b/libavformat/avformat.c index fea905693dd..356b4de931e 100644 --- a/libavformat/avformat.c +++ b/libavformat/avformat.c @@ -710,7 +710,6 @@ int avformat_transfer_internal_stream_timing_info(const AVOutputFormat *ofmt, AVRational dec_ctx_tb = dec_ctx->framerate.num ? av_inv_q(av_mul_q(dec_ctx->framerate, mul)) : (ist->codecpar->codec_type == AVMEDIA_TYPE_AUDIO ? (AVRational){0, 1} : ist->time_base); - enc_ctx->time_base = ist->time_base; /* * Avi is a special case here because it supports variable fps but @@ -727,7 +726,11 @@ int avformat_transfer_internal_stream_timing_info(const AVOutputFormat *ofmt, || copy_tb == AVFMT_TBCF_R_FRAMERATE) { enc_ctx->time_base.num = ist->r_frame_rate.den; enc_ctx->time_base.den = 2*ist->r_frame_rate.num; +#if FF_API_TICKS_PER_FRAME +FF_DISABLE_DEPRECATION_WARNINGS enc_ctx->ticks_per_frame = 2; +FF_ENABLE_DEPRECATION_WARNINGS +#endif } else #endif if (copy_tb == AVFMT_TBCF_AUTO && dec_ctx->framerate.num && @@ -736,9 +739,13 @@ int avformat_transfer_internal_stream_timing_info(const AVOutputFormat *ofmt, || (copy_tb == AVFMT_TBCF_DECODER && (dec_ctx->framerate.num || ist->codecpar->codec_type == AVMEDIA_TYPE_AUDIO))) { enc_ctx->time_base = dec_ctx_tb; - enc_ctx->time_base.num *= dec_ctx->ticks_per_frame; enc_ctx->time_base.den *= 2; +#if FF_API_TICKS_PER_FRAME +FF_DISABLE_DEPRECATION_WARNINGS + enc_ctx->time_base.num *= dec_ctx->ticks_per_frame; enc_ctx->ticks_per_frame = 2; +FF_ENABLE_DEPRECATION_WARNINGS +#endif } } else if (!(ofmt->flags & AVFMT_VARIABLE_FPS) && !av_match_name(ofmt->name, "mov,mp4,3gp,3g2,psp,ipod,ismv,f4v")) { @@ -748,7 +755,11 @@ int avformat_transfer_internal_stream_timing_info(const AVOutputFormat *ofmt, || (copy_tb == AVFMT_TBCF_DECODER && (dec_ctx->framerate.num || ist->codecpar->codec_type == AVMEDIA_TYPE_AUDIO))) { enc_ctx->time_base = dec_ctx_tb; +#if FF_API_TICKS_PER_FRAME +FF_DISABLE_DEPRECATION_WARNINGS enc_ctx->time_base.num *= dec_ctx->ticks_per_frame; +FF_ENABLE_DEPRECATION_WARNINGS +#endif } } From a238ba9c3c9987bccb27e9d37fcef2ae8b355aeb Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Sun, 7 May 2023 15:24:01 +0200 Subject: [PATCH 1014/2172] fftools/ffmpeg: stop using deprecated ticks_per_frame --- fftools/ffmpeg.c | 13 +++++++------ fftools/ffmpeg.h | 1 + fftools/ffmpeg_demux.c | 2 ++ 3 files changed, 10 insertions(+), 6 deletions(-) diff --git a/fftools/ffmpeg.c b/fftools/ffmpeg.c index 9920f946dc0..e2ada7a352d 100644 --- a/fftools/ffmpeg.c +++ b/fftools/ffmpeg.c @@ -1498,12 +1498,13 @@ static int process_input_packet(InputStream *ist, const AVPacket *pkt, int no_eo } else if (pkt->duration) { ist->next_dts += av_rescale_q(pkt->duration, pkt->time_base, AV_TIME_BASE_Q); } else if(ist->dec_ctx->framerate.num != 0) { - int ticks = ist->last_pkt_repeat_pict >= 0 ? - ist->last_pkt_repeat_pict + 1 : - ist->dec_ctx->ticks_per_frame; - ist->next_dts += ((int64_t)AV_TIME_BASE * - ist->dec_ctx->framerate.den * ticks) / - ist->dec_ctx->framerate.num / ist->dec_ctx->ticks_per_frame; + int fields = (ist->codec_desc && + (ist->codec_desc->props & AV_CODEC_PROP_FIELDS)) ? + ist->last_pkt_repeat_pict + 1 : 2; + AVRational field_rate = av_mul_q(ist->dec_ctx->framerate, + (AVRational){ 2, 1 }); + + ist->next_dts += av_rescale_q(fields, av_inv_q(field_rate), AV_TIME_BASE_Q); } break; } diff --git a/fftools/ffmpeg.h b/fftools/ffmpeg.h index 47358170e78..b0319f0ed09 100644 --- a/fftools/ffmpeg.h +++ b/fftools/ffmpeg.h @@ -350,6 +350,7 @@ typedef struct InputStream { AVCodecParameters *par; AVCodecContext *dec_ctx; const AVCodec *dec; + const AVCodecDescriptor *codec_desc; AVFrame *decoded_frame; AVPacket *pkt; diff --git a/fftools/ffmpeg_demux.c b/fftools/ffmpeg_demux.c index 630bb1c26b2..1872e87d571 100644 --- a/fftools/ffmpeg_demux.c +++ b/fftools/ffmpeg_demux.c @@ -951,6 +951,8 @@ static void add_input_streams(const OptionsContext *o, Demuxer *d) av_log(ist, AV_LOG_ERROR, "Error initializing the decoder context.\n"); exit_program(1); } + + ist->codec_desc = avcodec_descriptor_get(ist->par->codec_id); } } From 702ff2d281412a4652d06dd2f54e4ad079c615b6 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Wed, 26 Apr 2023 12:31:01 +0200 Subject: [PATCH 1015/2172] fftools/ffmpeg: consolidate InputStream.[next_]dts updates Move them to a separate function called right after timestamp discontinuity processing. This is now possible, since these values have no interaction with decoding anymore. --- fftools/ffmpeg.c | 105 +++++++++++++++++++++++++---------------------- 1 file changed, 55 insertions(+), 50 deletions(-) diff --git a/fftools/ffmpeg.c b/fftools/ffmpeg.c index e2ada7a352d..2bd3ce3f130 100644 --- a/fftools/ffmpeg.c +++ b/fftools/ffmpeg.c @@ -1375,19 +1375,6 @@ static int process_input_packet(InputStream *ist, const AVPacket *pkt, int no_eo AVPacket *avpkt = ist->pkt; - if (!ist->saw_first_ts) { - ist->first_dts = - ist->dts = ist->st->avg_frame_rate.num ? - ist->dec_ctx->has_b_frames * AV_TIME_BASE / av_q2d(ist->st->avg_frame_rate) : 0; - if (pkt && pkt->pts != AV_NOPTS_VALUE) { - ist->first_dts = - ist->dts += av_rescale_q(pkt->pts, pkt->time_base, AV_TIME_BASE_Q); - } - ist->saw_first_ts = 1; - } - - if (ist->next_dts == AV_NOPTS_VALUE) - ist->next_dts = ist->dts; - if (pkt) { av_packet_unref(avpkt); ret = av_packet_ref(avpkt, pkt); @@ -1395,10 +1382,6 @@ static int process_input_packet(InputStream *ist, const AVPacket *pkt, int no_eo return ret; } - if (pkt && pkt->dts != AV_NOPTS_VALUE) { - ist->next_dts = ist->dts = av_rescale_q(pkt->dts, pkt->time_base, AV_TIME_BASE_Q); - } - // while we have more to decode or while the decoder did output something on EOF while (ist->decoding_needed) { int64_t duration_pts = 0; @@ -1477,39 +1460,6 @@ static int process_input_packet(InputStream *ist, const AVPacket *pkt, int no_eo } } - if (pkt) { - ist->dts = ist->next_dts; - switch (par->codec_type) { - case AVMEDIA_TYPE_AUDIO: - av_assert1(pkt->duration >= 0); - if (par->sample_rate) { - ist->next_dts += ((int64_t)AV_TIME_BASE * par->frame_size) / - par->sample_rate; - } else { - ist->next_dts += av_rescale_q(pkt->duration, pkt->time_base, AV_TIME_BASE_Q); - } - break; - case AVMEDIA_TYPE_VIDEO: - if (ist->framerate.num) { - // TODO: Remove work-around for c99-to-c89 issue 7 - AVRational time_base_q = AV_TIME_BASE_Q; - int64_t next_dts = av_rescale_q(ist->next_dts, time_base_q, av_inv_q(ist->framerate)); - ist->next_dts = av_rescale_q(next_dts + 1, av_inv_q(ist->framerate), time_base_q); - } else if (pkt->duration) { - ist->next_dts += av_rescale_q(pkt->duration, pkt->time_base, AV_TIME_BASE_Q); - } else if(ist->dec_ctx->framerate.num != 0) { - int fields = (ist->codec_desc && - (ist->codec_desc->props & AV_CODEC_PROP_FIELDS)) ? - ist->last_pkt_repeat_pict + 1 : 2; - AVRational field_rate = av_mul_q(ist->dec_ctx->framerate, - (AVRational){ 2, 1 }); - - ist->next_dts += av_rescale_q(fields, av_inv_q(field_rate), AV_TIME_BASE_Q); - } - break; - } - } - if (!pkt && !ist->decoding_needed) eof_reached = 1; @@ -1900,6 +1850,58 @@ static void ts_discontinuity_process(InputFile *ifile, InputStream *ist, ts_discontinuity_detect(ifile, ist, pkt); } +static void ist_dts_update(InputStream *ist, AVPacket *pkt) +{ + const AVCodecParameters *par = ist->par; + + if (!ist->saw_first_ts) { + ist->first_dts = + ist->dts = ist->st->avg_frame_rate.num ? - ist->dec_ctx->has_b_frames * AV_TIME_BASE / av_q2d(ist->st->avg_frame_rate) : 0; + if (pkt->pts != AV_NOPTS_VALUE) { + ist->first_dts = + ist->dts += av_rescale_q(pkt->pts, pkt->time_base, AV_TIME_BASE_Q); + } + ist->saw_first_ts = 1; + } + + if (ist->next_dts == AV_NOPTS_VALUE) + ist->next_dts = ist->dts; + + if (pkt->dts != AV_NOPTS_VALUE) + ist->next_dts = ist->dts = av_rescale_q(pkt->dts, pkt->time_base, AV_TIME_BASE_Q); + + ist->dts = ist->next_dts; + switch (par->codec_type) { + case AVMEDIA_TYPE_AUDIO: + av_assert1(pkt->duration >= 0); + if (par->sample_rate) { + ist->next_dts += ((int64_t)AV_TIME_BASE * par->frame_size) / + par->sample_rate; + } else { + ist->next_dts += av_rescale_q(pkt->duration, pkt->time_base, AV_TIME_BASE_Q); + } + break; + case AVMEDIA_TYPE_VIDEO: + if (ist->framerate.num) { + // TODO: Remove work-around for c99-to-c89 issue 7 + AVRational time_base_q = AV_TIME_BASE_Q; + int64_t next_dts = av_rescale_q(ist->next_dts, time_base_q, av_inv_q(ist->framerate)); + ist->next_dts = av_rescale_q(next_dts + 1, av_inv_q(ist->framerate), time_base_q); + } else if (pkt->duration) { + ist->next_dts += av_rescale_q(pkt->duration, pkt->time_base, AV_TIME_BASE_Q); + } else if(ist->dec_ctx->framerate.num != 0) { + int fields = (ist->codec_desc && + (ist->codec_desc->props & AV_CODEC_PROP_FIELDS)) ? + ist->last_pkt_repeat_pict + 1 : 2; + AVRational field_rate = av_mul_q(ist->dec_ctx->framerate, + (AVRational){ 2, 1 }); + + ist->next_dts += av_rescale_q(fields, av_inv_q(field_rate), AV_TIME_BASE_Q); + } + break; + } +} + /* * Return * - 0 -- one packet was read and processed @@ -1985,6 +1987,9 @@ static int process_input(int file_index) // detect and try to correct for timestamp discontinuities ts_discontinuity_process(ifile, ist, pkt); + // update estimated/predicted dts + ist_dts_update(ist, pkt); + if (debug_ts) { av_log(NULL, AV_LOG_INFO, "demuxer+ffmpeg -> ist_index:%d:%d type:%s pkt_pts:%s pkt_pts_time:%s pkt_dts:%s pkt_dts_time:%s duration:%s duration_time:%s off:%s off_time:%s\n", ifile->index, pkt->stream_index, From 0d25b404d43cacfa6244f391da49ead9ff97bedf Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Wed, 26 Apr 2023 12:39:35 +0200 Subject: [PATCH 1016/2172] fftools/ffmpeg: reindent after previous commit --- fftools/ffmpeg.c | 58 ++++++++++++++++++++++++------------------------ 1 file changed, 29 insertions(+), 29 deletions(-) diff --git a/fftools/ffmpeg.c b/fftools/ffmpeg.c index 2bd3ce3f130..817b643c480 100644 --- a/fftools/ffmpeg.c +++ b/fftools/ffmpeg.c @@ -1870,36 +1870,36 @@ static void ist_dts_update(InputStream *ist, AVPacket *pkt) if (pkt->dts != AV_NOPTS_VALUE) ist->next_dts = ist->dts = av_rescale_q(pkt->dts, pkt->time_base, AV_TIME_BASE_Q); - ist->dts = ist->next_dts; - switch (par->codec_type) { - case AVMEDIA_TYPE_AUDIO: - av_assert1(pkt->duration >= 0); - if (par->sample_rate) { - ist->next_dts += ((int64_t)AV_TIME_BASE * par->frame_size) / - par->sample_rate; - } else { - ist->next_dts += av_rescale_q(pkt->duration, pkt->time_base, AV_TIME_BASE_Q); - } - break; - case AVMEDIA_TYPE_VIDEO: - if (ist->framerate.num) { - // TODO: Remove work-around for c99-to-c89 issue 7 - AVRational time_base_q = AV_TIME_BASE_Q; - int64_t next_dts = av_rescale_q(ist->next_dts, time_base_q, av_inv_q(ist->framerate)); - ist->next_dts = av_rescale_q(next_dts + 1, av_inv_q(ist->framerate), time_base_q); - } else if (pkt->duration) { - ist->next_dts += av_rescale_q(pkt->duration, pkt->time_base, AV_TIME_BASE_Q); - } else if(ist->dec_ctx->framerate.num != 0) { - int fields = (ist->codec_desc && - (ist->codec_desc->props & AV_CODEC_PROP_FIELDS)) ? - ist->last_pkt_repeat_pict + 1 : 2; - AVRational field_rate = av_mul_q(ist->dec_ctx->framerate, - (AVRational){ 2, 1 }); - - ist->next_dts += av_rescale_q(fields, av_inv_q(field_rate), AV_TIME_BASE_Q); - } - break; + ist->dts = ist->next_dts; + switch (par->codec_type) { + case AVMEDIA_TYPE_AUDIO: + av_assert1(pkt->duration >= 0); + if (par->sample_rate) { + ist->next_dts += ((int64_t)AV_TIME_BASE * par->frame_size) / + par->sample_rate; + } else { + ist->next_dts += av_rescale_q(pkt->duration, pkt->time_base, AV_TIME_BASE_Q); } + break; + case AVMEDIA_TYPE_VIDEO: + if (ist->framerate.num) { + // TODO: Remove work-around for c99-to-c89 issue 7 + AVRational time_base_q = AV_TIME_BASE_Q; + int64_t next_dts = av_rescale_q(ist->next_dts, time_base_q, av_inv_q(ist->framerate)); + ist->next_dts = av_rescale_q(next_dts + 1, av_inv_q(ist->framerate), time_base_q); + } else if (pkt->duration) { + ist->next_dts += av_rescale_q(pkt->duration, pkt->time_base, AV_TIME_BASE_Q); + } else if(ist->dec_ctx->framerate.num != 0) { + int fields = (ist->codec_desc && + (ist->codec_desc->props & AV_CODEC_PROP_FIELDS)) ? + ist->last_pkt_repeat_pict + 1 : 2; + AVRational field_rate = av_mul_q(ist->dec_ctx->framerate, + (AVRational){ 2, 1 }); + + ist->next_dts += av_rescale_q(fields, av_inv_q(field_rate), AV_TIME_BASE_Q); + } + break; + } } /* From 989e87b03ce6a03b288f8049dbe11a4083929747 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Wed, 26 Apr 2023 15:08:54 +0200 Subject: [PATCH 1017/2172] fftools/ffmpeg: stop using decoder properties in ist_dts_update() This code runs post-demuxing and is not synchronized with the decoder output (which may be delayed with respect to its input by arbitrary and unknowable amounts), so accessing any decoder properties is incorrect. --- fftools/ffmpeg.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/fftools/ffmpeg.c b/fftools/ffmpeg.c index 817b643c480..ca6ff780c3f 100644 --- a/fftools/ffmpeg.c +++ b/fftools/ffmpeg.c @@ -1856,7 +1856,7 @@ static void ist_dts_update(InputStream *ist, AVPacket *pkt) if (!ist->saw_first_ts) { ist->first_dts = - ist->dts = ist->st->avg_frame_rate.num ? - ist->dec_ctx->has_b_frames * AV_TIME_BASE / av_q2d(ist->st->avg_frame_rate) : 0; + ist->dts = ist->st->avg_frame_rate.num ? - ist->par->video_delay * AV_TIME_BASE / av_q2d(ist->st->avg_frame_rate) : 0; if (pkt->pts != AV_NOPTS_VALUE) { ist->first_dts = ist->dts += av_rescale_q(pkt->pts, pkt->time_base, AV_TIME_BASE_Q); @@ -1889,11 +1889,11 @@ static void ist_dts_update(InputStream *ist, AVPacket *pkt) ist->next_dts = av_rescale_q(next_dts + 1, av_inv_q(ist->framerate), time_base_q); } else if (pkt->duration) { ist->next_dts += av_rescale_q(pkt->duration, pkt->time_base, AV_TIME_BASE_Q); - } else if(ist->dec_ctx->framerate.num != 0) { + } else if (ist->par->framerate.num != 0) { int fields = (ist->codec_desc && (ist->codec_desc->props & AV_CODEC_PROP_FIELDS)) ? ist->last_pkt_repeat_pict + 1 : 2; - AVRational field_rate = av_mul_q(ist->dec_ctx->framerate, + AVRational field_rate = av_mul_q(ist->par->framerate, (AVRational){ 2, 1 }); ist->next_dts += av_rescale_q(fields, av_inv_q(field_rate), AV_TIME_BASE_Q); From abf9532bdad9d62b586b0fb5e4005a9fad2064e5 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Wed, 26 Apr 2023 14:23:42 +0200 Subject: [PATCH 1018/2172] fftools/ffmpeg_demux: move preparing DemuxMsg to separate function Will be useful in following commits, which will move more code into this function. --- fftools/ffmpeg_demux.c | 31 +++++++++++++++++++++++-------- 1 file changed, 23 insertions(+), 8 deletions(-) diff --git a/fftools/ffmpeg_demux.c b/fftools/ffmpeg_demux.c index 1872e87d571..b16a20a87b4 100644 --- a/fftools/ffmpeg_demux.c +++ b/fftools/ffmpeg_demux.c @@ -257,6 +257,26 @@ static void ts_fixup(Demuxer *d, AVPacket *pkt, int *repeat_pict) SHOW_TS_DEBUG("demuxer+tsfixup"); } +// process an input packet into a message to send to the consumer thread +// src is always cleared by this function +static int input_packet_process(Demuxer *d, DemuxMsg *msg, AVPacket *src) +{ + AVPacket *pkt; + + pkt = av_packet_alloc(); + if (!pkt) { + av_packet_unref(src); + return AVERROR(ENOMEM); + } + av_packet_move_ref(pkt, src); + + ts_fixup(d, pkt, &msg->repeat_pict); + + msg->pkt = pkt; + + return 0; +} + static void thread_set_name(InputFile *f) { char name[16]; @@ -336,15 +356,10 @@ static void *input_thread(void *arg) } } - ts_fixup(d, pkt, &msg.repeat_pict); - - msg.pkt = av_packet_alloc(); - if (!msg.pkt) { - av_packet_unref(pkt); - ret = AVERROR(ENOMEM); + ret = input_packet_process(d, &msg, pkt); + if (ret < 0) break; - } - av_packet_move_ref(msg.pkt, pkt); + ret = av_thread_message_queue_send(d->in_thread_queue, &msg, flags); if (flags && ret == AVERROR(EAGAIN)) { flags = 0; From 09c686788e3be1f343ddf64be291e6df6946323f Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Thu, 27 Apr 2023 13:54:36 +0200 Subject: [PATCH 1019/2172] fftools/ffmpeg: attach InputStream.dts to demuxed packets when needed This way computing it and using it for streamcopy does not need to happen in sync. Will be useful in following commits, where updating InputStream.dts will be moved to the demuxing thread. --- fftools/ffmpeg.c | 22 ++++++++++++++++++++-- fftools/ffmpeg.h | 7 +++++++ fftools/ffmpeg_demux.c | 1 + 3 files changed, 28 insertions(+), 2 deletions(-) diff --git a/fftools/ffmpeg.c b/fftools/ffmpeg.c index ca6ff780c3f..2a39d767cd1 100644 --- a/fftools/ffmpeg.c +++ b/fftools/ffmpeg.c @@ -1368,6 +1368,7 @@ static int process_input_packet(InputStream *ist, const AVPacket *pkt, int no_eo { InputFile *f = input_files[ist->file_index]; const AVCodecParameters *par = ist->par; + int64_t dts_est = AV_NOPTS_VALUE; int ret = 0; int repeating = 0; int eof_reached = 0; @@ -1463,6 +1464,11 @@ static int process_input_packet(InputStream *ist, const AVPacket *pkt, int no_eo if (!pkt && !ist->decoding_needed) eof_reached = 1; + if (pkt && pkt->opaque_ref) { + DemuxPktData *pd = (DemuxPktData*)pkt->opaque_ref->data; + dts_est = pd->dts_est; + } + duration_exceeded = 0; if (f->recording_time != INT64_MAX) { int64_t start_time = 0; @@ -1470,7 +1476,7 @@ static int process_input_packet(InputStream *ist, const AVPacket *pkt, int no_eo start_time += f->start_time != AV_NOPTS_VALUE ? f->start_time : 0; start_time += start_at_zero ? 0 : f->start_time_effective; } - if (ist->dts >= f->recording_time + start_time) + if (dts_est >= f->recording_time + start_time) duration_exceeded = 1; } @@ -1484,7 +1490,7 @@ static int process_input_packet(InputStream *ist, const AVPacket *pkt, int no_eo continue; } - of_streamcopy(ost, pkt, ist->dts); + of_streamcopy(ost, pkt, dts_est); } return !eof_reached; @@ -1900,6 +1906,18 @@ static void ist_dts_update(InputStream *ist, AVPacket *pkt) } break; } + + av_assert0(!pkt->opaque_ref); + if (ist->streamcopy_needed) { + DemuxPktData *pd; + + pkt->opaque_ref = av_buffer_allocz(sizeof(*pd)); + if (!pkt->opaque_ref) + report_and_exit(AVERROR(ENOMEM)); + pd = (DemuxPktData*)pkt->opaque_ref->data; + + pd->dts_est = ist->dts; + } } /* diff --git a/fftools/ffmpeg.h b/fftools/ffmpeg.h index b0319f0ed09..8a5d5b13c8f 100644 --- a/fftools/ffmpeg.h +++ b/fftools/ffmpeg.h @@ -95,6 +95,12 @@ typedef struct { } AudioChannelMap; #endif +typedef struct DemuxPktData { + // estimated dts in AV_TIME_BASE_Q, + // to be used when real dts is missing + int64_t dts_est; +} DemuxPktData; + typedef struct OptionsContext { OptionGroup *g; @@ -337,6 +343,7 @@ typedef struct InputStream { int discard; /* true if stream data should be discarded */ int user_set_discard; int decoding_needed; /* non zero if the packets must be decoded in 'raw_fifo', see DECODING_FOR_* */ + int streamcopy_needed; #define DECODING_FOR_OST 1 #define DECODING_FOR_FILTER 2 // should attach FrameData as opaque_ref after decoding diff --git a/fftools/ffmpeg_demux.c b/fftools/ffmpeg_demux.c index b16a20a87b4..eda838f84cb 100644 --- a/fftools/ffmpeg_demux.c +++ b/fftools/ffmpeg_demux.c @@ -584,6 +584,7 @@ static void ist_use(InputStream *ist, int decoding_needed) ist->discard = 0; ist->st->discard = ist->user_set_discard; ist->decoding_needed |= decoding_needed; + ist->streamcopy_needed |= !decoding_needed; if (decoding_needed && !avcodec_is_open(ist->dec_ctx)) { int ret = dec_open(ist); From 2b99c6bfd57d00e7f06cda09d60db9dbefaa117e Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Thu, 27 Apr 2023 14:11:34 +0200 Subject: [PATCH 1020/2172] fftools/ffmpeg: move post-demux packet processing to ffmpeg_demux That is a more appropriate place for this code and will allow hiding more of InputStream. The value of repeat_pict extracted from libavformat internal parser no longer needs to be trasmitted outside of the demuxing thread. Move readrate handling to the demuxer thread. This has to be done in the same commit, since it reads InputStream.dts,nb_packets, which are now set in the demuxer thread. --- fftools/ffmpeg.c | 188 ----------------------------- fftools/ffmpeg.h | 6 - fftools/ffmpeg_demux.c | 268 +++++++++++++++++++++++++++++++++++------ 3 files changed, 234 insertions(+), 228 deletions(-) diff --git a/fftools/ffmpeg.c b/fftools/ffmpeg.c index 2a39d767cd1..ee925877981 100644 --- a/fftools/ffmpeg.c +++ b/fftools/ffmpeg.c @@ -1772,154 +1772,6 @@ static void decode_flush(InputFile *ifile) } } -static void ts_discontinuity_detect(InputFile *ifile, InputStream *ist, - AVPacket *pkt) -{ - const int fmt_is_discont = ifile->ctx->iformat->flags & AVFMT_TS_DISCONT; - int disable_discontinuity_correction = copy_ts; - int64_t pkt_dts = av_rescale_q_rnd(pkt->dts, pkt->time_base, AV_TIME_BASE_Q, - AV_ROUND_NEAR_INF | AV_ROUND_PASS_MINMAX); - - if (copy_ts && ist->next_dts != AV_NOPTS_VALUE && - fmt_is_discont && ist->st->pts_wrap_bits < 60) { - int64_t wrap_dts = av_rescale_q_rnd(pkt->dts + (1LL<st->pts_wrap_bits), - pkt->time_base, AV_TIME_BASE_Q, - AV_ROUND_NEAR_INF|AV_ROUND_PASS_MINMAX); - if (FFABS(wrap_dts - ist->next_dts) < FFABS(pkt_dts - ist->next_dts)/10) - disable_discontinuity_correction = 0; - } - - if (ist->next_dts != AV_NOPTS_VALUE && !disable_discontinuity_correction) { - int64_t delta = pkt_dts - ist->next_dts; - if (fmt_is_discont) { - if (FFABS(delta) > 1LL * dts_delta_threshold * AV_TIME_BASE || - pkt_dts + AV_TIME_BASE/10 < ist->dts) { - ifile->ts_offset_discont -= delta; - av_log(NULL, AV_LOG_WARNING, - "timestamp discontinuity for stream #%d:%d " - "(id=%d, type=%s): %"PRId64", new offset= %"PRId64"\n", - ist->file_index, ist->st->index, ist->st->id, - av_get_media_type_string(ist->par->codec_type), - delta, ifile->ts_offset_discont); - pkt->dts -= av_rescale_q(delta, AV_TIME_BASE_Q, pkt->time_base); - if (pkt->pts != AV_NOPTS_VALUE) - pkt->pts -= av_rescale_q(delta, AV_TIME_BASE_Q, pkt->time_base); - } - } else { - if (FFABS(delta) > 1LL * dts_error_threshold * AV_TIME_BASE) { - av_log(NULL, AV_LOG_WARNING, "DTS %"PRId64", next:%"PRId64" st:%d invalid dropping\n", pkt->dts, ist->next_dts, pkt->stream_index); - pkt->dts = AV_NOPTS_VALUE; - } - if (pkt->pts != AV_NOPTS_VALUE){ - int64_t pkt_pts = av_rescale_q(pkt->pts, pkt->time_base, AV_TIME_BASE_Q); - delta = pkt_pts - ist->next_dts; - if (FFABS(delta) > 1LL * dts_error_threshold * AV_TIME_BASE) { - av_log(NULL, AV_LOG_WARNING, "PTS %"PRId64", next:%"PRId64" invalid dropping st:%d\n", pkt->pts, ist->next_dts, pkt->stream_index); - pkt->pts = AV_NOPTS_VALUE; - } - } - } - } else if (ist->next_dts == AV_NOPTS_VALUE && !copy_ts && - fmt_is_discont && ifile->last_ts != AV_NOPTS_VALUE) { - int64_t delta = pkt_dts - ifile->last_ts; - if (FFABS(delta) > 1LL * dts_delta_threshold * AV_TIME_BASE) { - ifile->ts_offset_discont -= delta; - av_log(NULL, AV_LOG_DEBUG, - "Inter stream timestamp discontinuity %"PRId64", new offset= %"PRId64"\n", - delta, ifile->ts_offset_discont); - pkt->dts -= av_rescale_q(delta, AV_TIME_BASE_Q, pkt->time_base); - if (pkt->pts != AV_NOPTS_VALUE) - pkt->pts -= av_rescale_q(delta, AV_TIME_BASE_Q, pkt->time_base); - } - } - - ifile->last_ts = av_rescale_q(pkt->dts, pkt->time_base, AV_TIME_BASE_Q); -} - -static void ts_discontinuity_process(InputFile *ifile, InputStream *ist, - AVPacket *pkt) -{ - int64_t offset = av_rescale_q(ifile->ts_offset_discont, AV_TIME_BASE_Q, - pkt->time_base); - - // apply previously-detected timestamp-discontinuity offset - // (to all streams, not just audio/video) - if (pkt->dts != AV_NOPTS_VALUE) - pkt->dts += offset; - if (pkt->pts != AV_NOPTS_VALUE) - pkt->pts += offset; - - // detect timestamp discontinuities for audio/video - if ((ist->par->codec_type == AVMEDIA_TYPE_VIDEO || - ist->par->codec_type == AVMEDIA_TYPE_AUDIO) && - pkt->dts != AV_NOPTS_VALUE) - ts_discontinuity_detect(ifile, ist, pkt); -} - -static void ist_dts_update(InputStream *ist, AVPacket *pkt) -{ - const AVCodecParameters *par = ist->par; - - if (!ist->saw_first_ts) { - ist->first_dts = - ist->dts = ist->st->avg_frame_rate.num ? - ist->par->video_delay * AV_TIME_BASE / av_q2d(ist->st->avg_frame_rate) : 0; - if (pkt->pts != AV_NOPTS_VALUE) { - ist->first_dts = - ist->dts += av_rescale_q(pkt->pts, pkt->time_base, AV_TIME_BASE_Q); - } - ist->saw_first_ts = 1; - } - - if (ist->next_dts == AV_NOPTS_VALUE) - ist->next_dts = ist->dts; - - if (pkt->dts != AV_NOPTS_VALUE) - ist->next_dts = ist->dts = av_rescale_q(pkt->dts, pkt->time_base, AV_TIME_BASE_Q); - - ist->dts = ist->next_dts; - switch (par->codec_type) { - case AVMEDIA_TYPE_AUDIO: - av_assert1(pkt->duration >= 0); - if (par->sample_rate) { - ist->next_dts += ((int64_t)AV_TIME_BASE * par->frame_size) / - par->sample_rate; - } else { - ist->next_dts += av_rescale_q(pkt->duration, pkt->time_base, AV_TIME_BASE_Q); - } - break; - case AVMEDIA_TYPE_VIDEO: - if (ist->framerate.num) { - // TODO: Remove work-around for c99-to-c89 issue 7 - AVRational time_base_q = AV_TIME_BASE_Q; - int64_t next_dts = av_rescale_q(ist->next_dts, time_base_q, av_inv_q(ist->framerate)); - ist->next_dts = av_rescale_q(next_dts + 1, av_inv_q(ist->framerate), time_base_q); - } else if (pkt->duration) { - ist->next_dts += av_rescale_q(pkt->duration, pkt->time_base, AV_TIME_BASE_Q); - } else if (ist->par->framerate.num != 0) { - int fields = (ist->codec_desc && - (ist->codec_desc->props & AV_CODEC_PROP_FIELDS)) ? - ist->last_pkt_repeat_pict + 1 : 2; - AVRational field_rate = av_mul_q(ist->par->framerate, - (AVRational){ 2, 1 }); - - ist->next_dts += av_rescale_q(fields, av_inv_q(field_rate), AV_TIME_BASE_Q); - } - break; - } - - av_assert0(!pkt->opaque_ref); - if (ist->streamcopy_needed) { - DemuxPktData *pd; - - pkt->opaque_ref = av_buffer_allocz(sizeof(*pd)); - if (!pkt->opaque_ref) - report_and_exit(AVERROR(ENOMEM)); - pd = (DemuxPktData*)pkt->opaque_ref->data; - - pd->dts_est = ist->dts; - } -} - /* * Return * - 0 -- one packet was read and processed @@ -1979,46 +1831,6 @@ static int process_input(int file_index) ist = ifile->streams[pkt->stream_index]; - ist->data_size += pkt->size; - ist->nb_packets++; - - /* add the stream-global side data to the first packet */ - if (ist->nb_packets == 1) { - for (i = 0; i < ist->st->nb_side_data; i++) { - AVPacketSideData *src_sd = &ist->st->side_data[i]; - uint8_t *dst_data; - - if (src_sd->type == AV_PKT_DATA_DISPLAYMATRIX) - continue; - - if (av_packet_get_side_data(pkt, src_sd->type, NULL)) - continue; - - dst_data = av_packet_new_side_data(pkt, src_sd->type, src_sd->size); - if (!dst_data) - report_and_exit(AVERROR(ENOMEM)); - - memcpy(dst_data, src_sd->data, src_sd->size); - } - } - - // detect and try to correct for timestamp discontinuities - ts_discontinuity_process(ifile, ist, pkt); - - // update estimated/predicted dts - ist_dts_update(ist, pkt); - - if (debug_ts) { - av_log(NULL, AV_LOG_INFO, "demuxer+ffmpeg -> ist_index:%d:%d type:%s pkt_pts:%s pkt_pts_time:%s pkt_dts:%s pkt_dts_time:%s duration:%s duration_time:%s off:%s off_time:%s\n", - ifile->index, pkt->stream_index, - av_get_media_type_string(ist->par->codec_type), - av_ts2str(pkt->pts), av_ts2timestr(pkt->pts, &pkt->time_base), - av_ts2str(pkt->dts), av_ts2timestr(pkt->dts, &pkt->time_base), - av_ts2str(pkt->duration), av_ts2timestr(pkt->duration, &pkt->time_base), - av_ts2str(input_files[ist->file_index]->ts_offset), - av_ts2timestr(input_files[ist->file_index]->ts_offset, &AV_TIME_BASE_Q)); - } - sub2video_heartbeat(ist, pkt->pts); process_input_packet(ist, pkt, 0); diff --git a/fftools/ffmpeg.h b/fftools/ffmpeg.h index 8a5d5b13c8f..1900f3deb6c 100644 --- a/fftools/ffmpeg.h +++ b/fftools/ffmpeg.h @@ -380,12 +380,6 @@ typedef struct InputStream { int wrap_correction_done; - // the value of AVCodecParserContext.repeat_pict from the AVStream parser - // for the last packet returned from ifile_get_packet() - // -1 if unknown - // FIXME: this is a hack, the avstream parser should not be used - int last_pkt_repeat_pict; - int64_t filter_in_rescale_delta_last; // when forcing constant input framerate through -r, diff --git a/fftools/ffmpeg_demux.c b/fftools/ffmpeg_demux.c index eda838f84cb..2d0410808b5 100644 --- a/fftools/ffmpeg_demux.c +++ b/fftools/ffmpeg_demux.c @@ -92,9 +92,6 @@ typedef struct Demuxer { typedef struct DemuxMsg { AVPacket *pkt; int looping; - - // repeat_pict from the demuxer-internal parser - int repeat_pict; } DemuxMsg; static DemuxStream *ds_from_ist(InputStream *ist) @@ -188,13 +185,167 @@ static int seek_to_start(Demuxer *d) return ret; } -static void ts_fixup(Demuxer *d, AVPacket *pkt, int *repeat_pict) +static void ts_discontinuity_detect(InputFile *ifile, InputStream *ist, + AVPacket *pkt) +{ + const int fmt_is_discont = ifile->ctx->iformat->flags & AVFMT_TS_DISCONT; + int disable_discontinuity_correction = copy_ts; + int64_t pkt_dts = av_rescale_q_rnd(pkt->dts, pkt->time_base, AV_TIME_BASE_Q, + AV_ROUND_NEAR_INF | AV_ROUND_PASS_MINMAX); + + if (copy_ts && ist->next_dts != AV_NOPTS_VALUE && + fmt_is_discont && ist->st->pts_wrap_bits < 60) { + int64_t wrap_dts = av_rescale_q_rnd(pkt->dts + (1LL<st->pts_wrap_bits), + pkt->time_base, AV_TIME_BASE_Q, + AV_ROUND_NEAR_INF|AV_ROUND_PASS_MINMAX); + if (FFABS(wrap_dts - ist->next_dts) < FFABS(pkt_dts - ist->next_dts)/10) + disable_discontinuity_correction = 0; + } + + if (ist->next_dts != AV_NOPTS_VALUE && !disable_discontinuity_correction) { + int64_t delta = pkt_dts - ist->next_dts; + if (fmt_is_discont) { + if (FFABS(delta) > 1LL * dts_delta_threshold * AV_TIME_BASE || + pkt_dts + AV_TIME_BASE/10 < ist->dts) { + ifile->ts_offset_discont -= delta; + av_log(NULL, AV_LOG_WARNING, + "timestamp discontinuity for stream #%d:%d " + "(id=%d, type=%s): %"PRId64", new offset= %"PRId64"\n", + ist->file_index, ist->st->index, ist->st->id, + av_get_media_type_string(ist->par->codec_type), + delta, ifile->ts_offset_discont); + pkt->dts -= av_rescale_q(delta, AV_TIME_BASE_Q, pkt->time_base); + if (pkt->pts != AV_NOPTS_VALUE) + pkt->pts -= av_rescale_q(delta, AV_TIME_BASE_Q, pkt->time_base); + } + } else { + if (FFABS(delta) > 1LL * dts_error_threshold * AV_TIME_BASE) { + av_log(NULL, AV_LOG_WARNING, "DTS %"PRId64", next:%"PRId64" st:%d invalid dropping\n", pkt->dts, ist->next_dts, pkt->stream_index); + pkt->dts = AV_NOPTS_VALUE; + } + if (pkt->pts != AV_NOPTS_VALUE){ + int64_t pkt_pts = av_rescale_q(pkt->pts, pkt->time_base, AV_TIME_BASE_Q); + delta = pkt_pts - ist->next_dts; + if (FFABS(delta) > 1LL * dts_error_threshold * AV_TIME_BASE) { + av_log(NULL, AV_LOG_WARNING, "PTS %"PRId64", next:%"PRId64" invalid dropping st:%d\n", pkt->pts, ist->next_dts, pkt->stream_index); + pkt->pts = AV_NOPTS_VALUE; + } + } + } + } else if (ist->next_dts == AV_NOPTS_VALUE && !copy_ts && + fmt_is_discont && ifile->last_ts != AV_NOPTS_VALUE) { + int64_t delta = pkt_dts - ifile->last_ts; + if (FFABS(delta) > 1LL * dts_delta_threshold * AV_TIME_BASE) { + ifile->ts_offset_discont -= delta; + av_log(NULL, AV_LOG_DEBUG, + "Inter stream timestamp discontinuity %"PRId64", new offset= %"PRId64"\n", + delta, ifile->ts_offset_discont); + pkt->dts -= av_rescale_q(delta, AV_TIME_BASE_Q, pkt->time_base); + if (pkt->pts != AV_NOPTS_VALUE) + pkt->pts -= av_rescale_q(delta, AV_TIME_BASE_Q, pkt->time_base); + } + } + + ifile->last_ts = av_rescale_q(pkt->dts, pkt->time_base, AV_TIME_BASE_Q); +} + +static void ts_discontinuity_process(InputFile *ifile, InputStream *ist, + AVPacket *pkt) +{ + int64_t offset = av_rescale_q(ifile->ts_offset_discont, AV_TIME_BASE_Q, + pkt->time_base); + + // apply previously-detected timestamp-discontinuity offset + // (to all streams, not just audio/video) + if (pkt->dts != AV_NOPTS_VALUE) + pkt->dts += offset; + if (pkt->pts != AV_NOPTS_VALUE) + pkt->pts += offset; + + // detect timestamp discontinuities for audio/video + if ((ist->par->codec_type == AVMEDIA_TYPE_VIDEO || + ist->par->codec_type == AVMEDIA_TYPE_AUDIO) && + pkt->dts != AV_NOPTS_VALUE) + ts_discontinuity_detect(ifile, ist, pkt); +} + +static int ist_dts_update(InputStream *ist, AVPacket *pkt) +{ + const AVCodecParameters *par = ist->par; + + if (!ist->saw_first_ts) { + ist->first_dts = + ist->dts = ist->st->avg_frame_rate.num ? - ist->par->video_delay * AV_TIME_BASE / av_q2d(ist->st->avg_frame_rate) : 0; + if (pkt->pts != AV_NOPTS_VALUE) { + ist->first_dts = + ist->dts += av_rescale_q(pkt->pts, pkt->time_base, AV_TIME_BASE_Q); + } + ist->saw_first_ts = 1; + } + + if (ist->next_dts == AV_NOPTS_VALUE) + ist->next_dts = ist->dts; + + if (pkt->dts != AV_NOPTS_VALUE) + ist->next_dts = ist->dts = av_rescale_q(pkt->dts, pkt->time_base, AV_TIME_BASE_Q); + + ist->dts = ist->next_dts; + switch (par->codec_type) { + case AVMEDIA_TYPE_AUDIO: + av_assert1(pkt->duration >= 0); + if (par->sample_rate) { + ist->next_dts += ((int64_t)AV_TIME_BASE * par->frame_size) / + par->sample_rate; + } else { + ist->next_dts += av_rescale_q(pkt->duration, pkt->time_base, AV_TIME_BASE_Q); + } + break; + case AVMEDIA_TYPE_VIDEO: + if (ist->framerate.num) { + // TODO: Remove work-around for c99-to-c89 issue 7 + AVRational time_base_q = AV_TIME_BASE_Q; + int64_t next_dts = av_rescale_q(ist->next_dts, time_base_q, av_inv_q(ist->framerate)); + ist->next_dts = av_rescale_q(next_dts + 1, av_inv_q(ist->framerate), time_base_q); + } else if (pkt->duration) { + ist->next_dts += av_rescale_q(pkt->duration, pkt->time_base, AV_TIME_BASE_Q); + } else if (ist->par->framerate.num != 0) { + AVRational field_rate = av_mul_q(ist->par->framerate, + (AVRational){ 2, 1 }); + int fields = 2; + + if (ist->codec_desc && + (ist->codec_desc->props & AV_CODEC_PROP_FIELDS) && + av_stream_get_parser(ist->st)) + fields = 1 + av_stream_get_parser(ist->st)->repeat_pict; + + ist->next_dts += av_rescale_q(fields, av_inv_q(field_rate), AV_TIME_BASE_Q); + } + break; + } + + av_assert0(!pkt->opaque_ref); + if (ist->streamcopy_needed) { + DemuxPktData *pd; + + pkt->opaque_ref = av_buffer_allocz(sizeof(*pd)); + if (!pkt->opaque_ref) + return AVERROR(ENOMEM); + pd = (DemuxPktData*)pkt->opaque_ref->data; + + pd->dts_est = ist->dts; + } + + return 0; +} + +static int ts_fixup(Demuxer *d, AVPacket *pkt) { InputFile *ifile = &d->f; InputStream *ist = ifile->streams[pkt->stream_index]; DemuxStream *ds = ds_from_ist(ist); const int64_t start_time = ifile->start_time_effective; int64_t duration; + int ret; pkt->time_base = ist->st->time_base; @@ -249,19 +400,27 @@ static void ts_fixup(Demuxer *d, AVPacket *pkt, int *repeat_pict) if (pkt->dts != AV_NOPTS_VALUE) pkt->dts += duration; - *repeat_pict = -1; - if (ist->st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO && - av_stream_get_parser(ist->st)) - *repeat_pict = av_stream_get_parser(ist->st)->repeat_pict; - SHOW_TS_DEBUG("demuxer+tsfixup"); + + // detect and try to correct for timestamp discontinuities + ts_discontinuity_process(ifile, ist, pkt); + + // update estimated/predicted dts + ret = ist_dts_update(ist, pkt); + if (ret < 0) + return ret; + + return 0; } // process an input packet into a message to send to the consumer thread // src is always cleared by this function static int input_packet_process(Demuxer *d, DemuxMsg *msg, AVPacket *src) { + InputFile *f = &d->f; + InputStream *ist = f->streams[src->stream_index]; AVPacket *pkt; + int ret = 0; pkt = av_packet_alloc(); if (!pkt) { @@ -270,11 +429,72 @@ static int input_packet_process(Demuxer *d, DemuxMsg *msg, AVPacket *src) } av_packet_move_ref(pkt, src); - ts_fixup(d, pkt, &msg->repeat_pict); + ret = ts_fixup(d, pkt); + if (ret < 0) + goto fail; + + ist->data_size += pkt->size; + ist->nb_packets++; + + /* add the stream-global side data to the first packet */ + if (ist->nb_packets == 1) { + for (int i = 0; i < ist->st->nb_side_data; i++) { + AVPacketSideData *src_sd = &ist->st->side_data[i]; + uint8_t *dst_data; + + if (src_sd->type == AV_PKT_DATA_DISPLAYMATRIX) + continue; + + if (av_packet_get_side_data(pkt, src_sd->type, NULL)) + continue; + + dst_data = av_packet_new_side_data(pkt, src_sd->type, src_sd->size); + if (!dst_data) { + ret = AVERROR(ENOMEM); + goto fail; + } + + memcpy(dst_data, src_sd->data, src_sd->size); + } + } + + if (debug_ts) { + av_log(NULL, AV_LOG_INFO, "demuxer+ffmpeg -> ist_index:%d:%d type:%s pkt_pts:%s pkt_pts_time:%s pkt_dts:%s pkt_dts_time:%s duration:%s duration_time:%s off:%s off_time:%s\n", + f->index, pkt->stream_index, + av_get_media_type_string(ist->par->codec_type), + av_ts2str(pkt->pts), av_ts2timestr(pkt->pts, &pkt->time_base), + av_ts2str(pkt->dts), av_ts2timestr(pkt->dts, &pkt->time_base), + av_ts2str(pkt->duration), av_ts2timestr(pkt->duration, &pkt->time_base), + av_ts2str(input_files[ist->file_index]->ts_offset), + av_ts2timestr(input_files[ist->file_index]->ts_offset, &AV_TIME_BASE_Q)); + } msg->pkt = pkt; + pkt = NULL; - return 0; +fail: + av_packet_free(&pkt); + + return ret; +} + +static void readrate_sleep(Demuxer *d) +{ + InputFile *f = &d->f; + int64_t file_start = copy_ts * ( + (f->start_time_effective != AV_NOPTS_VALUE ? f->start_time_effective * !start_at_zero : 0) + + (f->start_time != AV_NOPTS_VALUE ? f->start_time : 0) + ); + int64_t burst_until = AV_TIME_BASE * d->readrate_initial_burst; + for (int i = 0; i < f->nb_streams; i++) { + InputStream *ist = f->streams[i]; + int64_t stream_ts_offset, pts, now; + stream_ts_offset = FFMAX(ist->first_dts != AV_NOPTS_VALUE ? ist->first_dts : 0, file_start); + pts = av_rescale(ist->dts, 1000000, AV_TIME_BASE); + now = (av_gettime_relative() - ist->start) * f->readrate + stream_ts_offset; + if (pts - burst_until > now) + av_usleep(pts - burst_until - now); + } } static void thread_set_name(InputFile *f) @@ -360,6 +580,9 @@ static void *input_thread(void *arg) if (ret < 0) break; + if (f->readrate) + readrate_sleep(d); + ret = av_thread_message_queue_send(d->in_thread_queue, &msg, flags); if (flags && ret == AVERROR(EAGAIN)) { flags = 0; @@ -456,7 +679,6 @@ static int thread_start(Demuxer *d) int ifile_get_packet(InputFile *f, AVPacket **pkt) { Demuxer *d = demuxer_from_ifile(f); - InputStream *ist; DemuxMsg msg; int ret; @@ -466,25 +688,6 @@ int ifile_get_packet(InputFile *f, AVPacket **pkt) return ret; } - if (f->readrate) { - int i; - int64_t file_start = copy_ts * ( - (f->start_time_effective != AV_NOPTS_VALUE ? f->start_time_effective * !start_at_zero : 0) + - (f->start_time != AV_NOPTS_VALUE ? f->start_time : 0) - ); - int64_t burst_until = AV_TIME_BASE * d->readrate_initial_burst; - for (i = 0; i < f->nb_streams; i++) { - InputStream *ist = f->streams[i]; - int64_t stream_ts_offset, pts, now; - if (!ist->nb_packets) continue; - stream_ts_offset = FFMAX(ist->first_dts != AV_NOPTS_VALUE ? ist->first_dts : 0, file_start); - pts = av_rescale(ist->dts, 1000000, AV_TIME_BASE); - now = (av_gettime_relative() - ist->start) * f->readrate + stream_ts_offset; - if (pts - burst_until > now) - return AVERROR(EAGAIN); - } - } - ret = av_thread_message_queue_recv(d->in_thread_queue, &msg, d->non_blocking ? AV_THREAD_MESSAGE_NONBLOCK : 0); @@ -493,9 +696,6 @@ int ifile_get_packet(InputFile *f, AVPacket **pkt) if (msg.looping) return 1; - ist = f->streams[msg.pkt->stream_index]; - ist->last_pkt_repeat_pict = msg.repeat_pict; - *pkt = msg.pkt; return 0; } From bfd5e7ef5d99c6b8b94b9b94312ba30624001bd8 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Fri, 28 Apr 2023 18:30:38 +0200 Subject: [PATCH 1021/2172] fftools/ffmpeg_demux: reindent after previous commit --- fftools/ffmpeg_demux.c | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/fftools/ffmpeg_demux.c b/fftools/ffmpeg_demux.c index 2d0410808b5..e3150503c7d 100644 --- a/fftools/ffmpeg_demux.c +++ b/fftools/ffmpeg_demux.c @@ -481,20 +481,20 @@ static int input_packet_process(Demuxer *d, DemuxMsg *msg, AVPacket *src) static void readrate_sleep(Demuxer *d) { InputFile *f = &d->f; - int64_t file_start = copy_ts * ( - (f->start_time_effective != AV_NOPTS_VALUE ? f->start_time_effective * !start_at_zero : 0) + - (f->start_time != AV_NOPTS_VALUE ? f->start_time : 0) - ); - int64_t burst_until = AV_TIME_BASE * d->readrate_initial_burst; - for (int i = 0; i < f->nb_streams; i++) { - InputStream *ist = f->streams[i]; - int64_t stream_ts_offset, pts, now; - stream_ts_offset = FFMAX(ist->first_dts != AV_NOPTS_VALUE ? ist->first_dts : 0, file_start); - pts = av_rescale(ist->dts, 1000000, AV_TIME_BASE); - now = (av_gettime_relative() - ist->start) * f->readrate + stream_ts_offset; - if (pts - burst_until > now) - av_usleep(pts - burst_until - now); - } + int64_t file_start = copy_ts * ( + (f->start_time_effective != AV_NOPTS_VALUE ? f->start_time_effective * !start_at_zero : 0) + + (f->start_time != AV_NOPTS_VALUE ? f->start_time : 0) + ); + int64_t burst_until = AV_TIME_BASE * d->readrate_initial_burst; + for (int i = 0; i < f->nb_streams; i++) { + InputStream *ist = f->streams[i]; + int64_t stream_ts_offset, pts, now; + stream_ts_offset = FFMAX(ist->first_dts != AV_NOPTS_VALUE ? ist->first_dts : 0, file_start); + pts = av_rescale(ist->dts, 1000000, AV_TIME_BASE); + now = (av_gettime_relative() - ist->start) * f->readrate + stream_ts_offset; + if (pts - burst_until > now) + av_usleep(pts - burst_until - now); + } } static void thread_set_name(InputFile *f) From 6fcfe4307c6d7fc0ab7d15b0a0f910a9c366b31b Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Fri, 28 Apr 2023 18:48:14 +0200 Subject: [PATCH 1022/2172] fftools/ffmpeg: drop unused decode_video() parameter --- fftools/ffmpeg.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/fftools/ffmpeg.c b/fftools/ffmpeg.c index ee925877981..9cf94f2a22b 100644 --- a/fftools/ffmpeg.c +++ b/fftools/ffmpeg.c @@ -1026,7 +1026,7 @@ static int64_t video_duration_estimate(const InputStream *ist, const AVFrame *fr } static int decode_video(InputStream *ist, const AVPacket *pkt, int *got_output, - int64_t *duration_pts, int eof, int *decode_failed) + int eof, int *decode_failed) { AVFrame *decoded_frame = ist->decoded_frame; int ret = 0, err = 0; @@ -1091,7 +1091,6 @@ static int decode_video(InputStream *ist, const AVPacket *pkt, int *got_output, } best_effort_timestamp= decoded_frame->best_effort_timestamp; - *duration_pts = decoded_frame->duration; if (ist->framerate.num) best_effort_timestamp = ist->cfr_next_pts++; @@ -1385,7 +1384,6 @@ static int process_input_packet(InputStream *ist, const AVPacket *pkt, int no_eo // while we have more to decode or while the decoder did output something on EOF while (ist->decoding_needed) { - int64_t duration_pts = 0; int got_output = 0; int decode_failed = 0; @@ -1396,7 +1394,7 @@ static int process_input_packet(InputStream *ist, const AVPacket *pkt, int no_eo av_packet_unref(avpkt); break; case AVMEDIA_TYPE_VIDEO: - ret = decode_video (ist, repeating ? NULL : avpkt, &got_output, &duration_pts, !pkt, + ret = decode_video (ist, repeating ? NULL : avpkt, &got_output, !pkt, &decode_failed); av_packet_unref(avpkt); From 57a2b2f88668171a623fdfa320e36a501978f8f3 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Sun, 7 May 2023 16:19:38 +0200 Subject: [PATCH 1023/2172] fftools/ffmpeg_demux: move InputStream.{nb_packets,data_size} to private data They are no longer used outside of ffmpeg_demux. --- fftools/ffmpeg.h | 4 ---- fftools/ffmpeg_demux.c | 19 +++++++++++++------ 2 files changed, 13 insertions(+), 10 deletions(-) diff --git a/fftools/ffmpeg.h b/fftools/ffmpeg.h index 1900f3deb6c..8e96f27d5dc 100644 --- a/fftools/ffmpeg.h +++ b/fftools/ffmpeg.h @@ -436,10 +436,6 @@ typedef struct InputStream { enum AVPixelFormat hwaccel_pix_fmt; /* stats */ - // combined size of all the packets read - uint64_t data_size; - /* number of packets successfully read for this stream */ - uint64_t nb_packets; // number of frames/samples retrieved from the decoder uint64_t frames_decoded; uint64_t samples_decoded; diff --git a/fftools/ffmpeg_demux.c b/fftools/ffmpeg_demux.c index e3150503c7d..ae4a894d47d 100644 --- a/fftools/ffmpeg_demux.c +++ b/fftools/ffmpeg_demux.c @@ -62,6 +62,11 @@ typedef struct DemuxStream { int64_t min_pts; /* pts with the smallest value in a current stream */ int64_t max_pts; /* pts with the higher value in a current stream */ + + /* number of packets successfully read for this stream */ + uint64_t nb_packets; + // combined size of all the packets read + uint64_t data_size; } DemuxStream; typedef struct Demuxer { @@ -419,6 +424,7 @@ static int input_packet_process(Demuxer *d, DemuxMsg *msg, AVPacket *src) { InputFile *f = &d->f; InputStream *ist = f->streams[src->stream_index]; + DemuxStream *ds = ds_from_ist(ist); AVPacket *pkt; int ret = 0; @@ -433,11 +439,11 @@ static int input_packet_process(Demuxer *d, DemuxMsg *msg, AVPacket *src) if (ret < 0) goto fail; - ist->data_size += pkt->size; - ist->nb_packets++; + ds->data_size += pkt->size; + ds->nb_packets++; /* add the stream-global side data to the first packet */ - if (ist->nb_packets == 1) { + if (ds->nb_packets == 1) { for (int i = 0; i < ist->st->nb_side_data; i++) { AVPacketSideData *src_sd = &ist->st->side_data[i]; uint8_t *dst_data; @@ -710,15 +716,16 @@ static void demux_final_stats(Demuxer *d) for (int j = 0; j < f->nb_streams; j++) { InputStream *ist = f->streams[j]; + DemuxStream *ds = ds_from_ist(ist); enum AVMediaType type = ist->par->codec_type; - total_size += ist->data_size; - total_packets += ist->nb_packets; + total_size += ds->data_size; + total_packets += ds->nb_packets; av_log(f, AV_LOG_VERBOSE, " Input stream #%d:%d (%s): ", f->index, j, av_get_media_type_string(type)); av_log(f, AV_LOG_VERBOSE, "%"PRIu64" packets read (%"PRIu64" bytes); ", - ist->nb_packets, ist->data_size); + ds->nb_packets, ds->data_size); if (ist->decoding_needed) { av_log(f, AV_LOG_VERBOSE, "%"PRIu64" frames decoded", From 6d7b43ed449804c2e13b2f0274c0fe86dc955dac Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Sun, 7 May 2023 16:19:38 +0200 Subject: [PATCH 1024/2172] fftools/ffmpeg_demux: move InputStream.[saw_]first_d?ts to private data They are no longer used outside of ffmpeg_demux. --- fftools/ffmpeg.h | 2 -- fftools/ffmpeg_demux.c | 22 ++++++++++++++-------- 2 files changed, 14 insertions(+), 10 deletions(-) diff --git a/fftools/ffmpeg.h b/fftools/ffmpeg.h index 8e96f27d5dc..e4a697af54b 100644 --- a/fftools/ffmpeg.h +++ b/fftools/ffmpeg.h @@ -367,7 +367,6 @@ typedef struct InputStream { /* 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) */ int64_t next_dts; - int64_t first_dts; ///< dts of the first packet read for this stream (in AV_TIME_BASE units) int64_t dts; ///< dts of the last packet read for this stream (in AV_TIME_BASE units) // pts/estimated duration of the last decoded frame @@ -388,7 +387,6 @@ typedef struct InputStream { int64_t nb_samples; /* number of samples in the last decoded audio frame before looping */ - int saw_first_ts; AVDictionary *decoder_opts; AVRational framerate; /* framerate forced with -r */ int top_field_first; diff --git a/fftools/ffmpeg_demux.c b/fftools/ffmpeg_demux.c index ae4a894d47d..3f945d1fb5c 100644 --- a/fftools/ffmpeg_demux.c +++ b/fftools/ffmpeg_demux.c @@ -60,6 +60,10 @@ typedef struct DemuxStream { double ts_scale; + int saw_first_ts; + ///< dts of the first packet read for this stream (in AV_TIME_BASE units) + int64_t first_dts; + int64_t min_pts; /* pts with the smallest value in a current stream */ int64_t max_pts; /* pts with the higher value in a current stream */ @@ -274,18 +278,19 @@ static void ts_discontinuity_process(InputFile *ifile, InputStream *ist, ts_discontinuity_detect(ifile, ist, pkt); } -static int ist_dts_update(InputStream *ist, AVPacket *pkt) +static int ist_dts_update(DemuxStream *ds, AVPacket *pkt) { + InputStream *ist = &ds->ist; const AVCodecParameters *par = ist->par; - if (!ist->saw_first_ts) { - ist->first_dts = + if (!ds->saw_first_ts) { + ds->first_dts = ist->dts = ist->st->avg_frame_rate.num ? - ist->par->video_delay * AV_TIME_BASE / av_q2d(ist->st->avg_frame_rate) : 0; if (pkt->pts != AV_NOPTS_VALUE) { - ist->first_dts = + ds->first_dts = ist->dts += av_rescale_q(pkt->pts, pkt->time_base, AV_TIME_BASE_Q); } - ist->saw_first_ts = 1; + ds->saw_first_ts = 1; } if (ist->next_dts == AV_NOPTS_VALUE) @@ -411,7 +416,7 @@ static int ts_fixup(Demuxer *d, AVPacket *pkt) ts_discontinuity_process(ifile, ist, pkt); // update estimated/predicted dts - ret = ist_dts_update(ist, pkt); + ret = ist_dts_update(ds, pkt); if (ret < 0) return ret; @@ -494,8 +499,9 @@ static void readrate_sleep(Demuxer *d) int64_t burst_until = AV_TIME_BASE * d->readrate_initial_burst; for (int i = 0; i < f->nb_streams; i++) { InputStream *ist = f->streams[i]; + DemuxStream *ds = ds_from_ist(ist); int64_t stream_ts_offset, pts, now; - stream_ts_offset = FFMAX(ist->first_dts != AV_NOPTS_VALUE ? ist->first_dts : 0, file_start); + stream_ts_offset = FFMAX(ds->first_dts != AV_NOPTS_VALUE ? ds->first_dts : 0, file_start); pts = av_rescale(ist->dts, 1000000, AV_TIME_BASE); now = (av_gettime_relative() - ist->start) * f->readrate + stream_ts_offset; if (pts - burst_until > now) @@ -976,7 +982,7 @@ static void add_input_streams(const OptionsContext *o, Demuxer *d) ist->discard = 1; st->discard = AVDISCARD_ALL; ist->nb_samples = 0; - ist->first_dts = AV_NOPTS_VALUE; + ds->first_dts = AV_NOPTS_VALUE; ist->next_dts = AV_NOPTS_VALUE; ds->min_pts = INT64_MAX; From df25e21ce755878fe2f87a4dd7bed5d55c9e2594 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Sun, 7 May 2023 16:19:38 +0200 Subject: [PATCH 1025/2172] fftools/ffmpeg_demux: move InputStream.[next_]dts to private data They are no longer used outside of ffmpeg_demux. --- fftools/ffmpeg.h | 4 --- fftools/ffmpeg_demux.c | 59 +++++++++++++++++++++++++----------------- 2 files changed, 35 insertions(+), 28 deletions(-) diff --git a/fftools/ffmpeg.h b/fftools/ffmpeg.h index e4a697af54b..b8c0e7db844 100644 --- a/fftools/ffmpeg.h +++ b/fftools/ffmpeg.h @@ -364,10 +364,6 @@ typedef struct InputStream { AVRational framerate_guessed; 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) */ - int64_t next_dts; - int64_t dts; ///< dts of the last packet read for this stream (in AV_TIME_BASE units) // pts/estimated duration of the last decoded frame // * in decoder timebase for video, diff --git a/fftools/ffmpeg_demux.c b/fftools/ffmpeg_demux.c index 3f945d1fb5c..7cf32242d99 100644 --- a/fftools/ffmpeg_demux.c +++ b/fftools/ffmpeg_demux.c @@ -64,6 +64,12 @@ typedef struct DemuxStream { ///< dts of the first packet read for this stream (in AV_TIME_BASE units) int64_t first_dts; + /* 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) */ + int64_t next_dts; + ///< dts of the last packet read for this stream (in AV_TIME_BASE units) + int64_t dts; + int64_t min_pts; /* pts with the smallest value in a current stream */ int64_t max_pts; /* pts with the higher value in a current stream */ @@ -197,25 +203,26 @@ static int seek_to_start(Demuxer *d) static void ts_discontinuity_detect(InputFile *ifile, InputStream *ist, AVPacket *pkt) { + DemuxStream *ds = ds_from_ist(ist); const int fmt_is_discont = ifile->ctx->iformat->flags & AVFMT_TS_DISCONT; int disable_discontinuity_correction = copy_ts; int64_t pkt_dts = av_rescale_q_rnd(pkt->dts, pkt->time_base, AV_TIME_BASE_Q, AV_ROUND_NEAR_INF | AV_ROUND_PASS_MINMAX); - if (copy_ts && ist->next_dts != AV_NOPTS_VALUE && + if (copy_ts && ds->next_dts != AV_NOPTS_VALUE && fmt_is_discont && ist->st->pts_wrap_bits < 60) { int64_t wrap_dts = av_rescale_q_rnd(pkt->dts + (1LL<st->pts_wrap_bits), pkt->time_base, AV_TIME_BASE_Q, AV_ROUND_NEAR_INF|AV_ROUND_PASS_MINMAX); - if (FFABS(wrap_dts - ist->next_dts) < FFABS(pkt_dts - ist->next_dts)/10) + if (FFABS(wrap_dts - ds->next_dts) < FFABS(pkt_dts - ds->next_dts)/10) disable_discontinuity_correction = 0; } - if (ist->next_dts != AV_NOPTS_VALUE && !disable_discontinuity_correction) { - int64_t delta = pkt_dts - ist->next_dts; + if (ds->next_dts != AV_NOPTS_VALUE && !disable_discontinuity_correction) { + int64_t delta = pkt_dts - ds->next_dts; if (fmt_is_discont) { if (FFABS(delta) > 1LL * dts_delta_threshold * AV_TIME_BASE || - pkt_dts + AV_TIME_BASE/10 < ist->dts) { + pkt_dts + AV_TIME_BASE/10 < ds->dts) { ifile->ts_offset_discont -= delta; av_log(NULL, AV_LOG_WARNING, "timestamp discontinuity for stream #%d:%d " @@ -229,19 +236,23 @@ static void ts_discontinuity_detect(InputFile *ifile, InputStream *ist, } } else { if (FFABS(delta) > 1LL * dts_error_threshold * AV_TIME_BASE) { - av_log(NULL, AV_LOG_WARNING, "DTS %"PRId64", next:%"PRId64" st:%d invalid dropping\n", pkt->dts, ist->next_dts, pkt->stream_index); + av_log(NULL, AV_LOG_WARNING, + "DTS %"PRId64", next:%"PRId64" st:%d invalid dropping\n", + pkt->dts, ds->next_dts, pkt->stream_index); pkt->dts = AV_NOPTS_VALUE; } if (pkt->pts != AV_NOPTS_VALUE){ int64_t pkt_pts = av_rescale_q(pkt->pts, pkt->time_base, AV_TIME_BASE_Q); - delta = pkt_pts - ist->next_dts; + delta = pkt_pts - ds->next_dts; if (FFABS(delta) > 1LL * dts_error_threshold * AV_TIME_BASE) { - av_log(NULL, AV_LOG_WARNING, "PTS %"PRId64", next:%"PRId64" invalid dropping st:%d\n", pkt->pts, ist->next_dts, pkt->stream_index); + av_log(NULL, AV_LOG_WARNING, + "PTS %"PRId64", next:%"PRId64" invalid dropping st:%d\n", + pkt->pts, ds->next_dts, pkt->stream_index); pkt->pts = AV_NOPTS_VALUE; } } } - } else if (ist->next_dts == AV_NOPTS_VALUE && !copy_ts && + } else if (ds->next_dts == AV_NOPTS_VALUE && !copy_ts && fmt_is_discont && ifile->last_ts != AV_NOPTS_VALUE) { int64_t delta = pkt_dts - ifile->last_ts; if (FFABS(delta) > 1LL * dts_delta_threshold * AV_TIME_BASE) { @@ -285,39 +296,39 @@ static int ist_dts_update(DemuxStream *ds, AVPacket *pkt) if (!ds->saw_first_ts) { ds->first_dts = - ist->dts = ist->st->avg_frame_rate.num ? - ist->par->video_delay * AV_TIME_BASE / av_q2d(ist->st->avg_frame_rate) : 0; + ds->dts = ist->st->avg_frame_rate.num ? - ist->par->video_delay * AV_TIME_BASE / av_q2d(ist->st->avg_frame_rate) : 0; if (pkt->pts != AV_NOPTS_VALUE) { ds->first_dts = - ist->dts += av_rescale_q(pkt->pts, pkt->time_base, AV_TIME_BASE_Q); + ds->dts += av_rescale_q(pkt->pts, pkt->time_base, AV_TIME_BASE_Q); } ds->saw_first_ts = 1; } - if (ist->next_dts == AV_NOPTS_VALUE) - ist->next_dts = ist->dts; + if (ds->next_dts == AV_NOPTS_VALUE) + ds->next_dts = ds->dts; if (pkt->dts != AV_NOPTS_VALUE) - ist->next_dts = ist->dts = av_rescale_q(pkt->dts, pkt->time_base, AV_TIME_BASE_Q); + ds->next_dts = ds->dts = av_rescale_q(pkt->dts, pkt->time_base, AV_TIME_BASE_Q); - ist->dts = ist->next_dts; + ds->dts = ds->next_dts; switch (par->codec_type) { case AVMEDIA_TYPE_AUDIO: av_assert1(pkt->duration >= 0); if (par->sample_rate) { - ist->next_dts += ((int64_t)AV_TIME_BASE * par->frame_size) / + ds->next_dts += ((int64_t)AV_TIME_BASE * par->frame_size) / par->sample_rate; } else { - ist->next_dts += av_rescale_q(pkt->duration, pkt->time_base, AV_TIME_BASE_Q); + ds->next_dts += av_rescale_q(pkt->duration, pkt->time_base, AV_TIME_BASE_Q); } break; case AVMEDIA_TYPE_VIDEO: if (ist->framerate.num) { // TODO: Remove work-around for c99-to-c89 issue 7 AVRational time_base_q = AV_TIME_BASE_Q; - int64_t next_dts = av_rescale_q(ist->next_dts, time_base_q, av_inv_q(ist->framerate)); - ist->next_dts = av_rescale_q(next_dts + 1, av_inv_q(ist->framerate), time_base_q); + int64_t next_dts = av_rescale_q(ds->next_dts, time_base_q, av_inv_q(ist->framerate)); + ds->next_dts = av_rescale_q(next_dts + 1, av_inv_q(ist->framerate), time_base_q); } else if (pkt->duration) { - ist->next_dts += av_rescale_q(pkt->duration, pkt->time_base, AV_TIME_BASE_Q); + ds->next_dts += av_rescale_q(pkt->duration, pkt->time_base, AV_TIME_BASE_Q); } else if (ist->par->framerate.num != 0) { AVRational field_rate = av_mul_q(ist->par->framerate, (AVRational){ 2, 1 }); @@ -328,7 +339,7 @@ static int ist_dts_update(DemuxStream *ds, AVPacket *pkt) av_stream_get_parser(ist->st)) fields = 1 + av_stream_get_parser(ist->st)->repeat_pict; - ist->next_dts += av_rescale_q(fields, av_inv_q(field_rate), AV_TIME_BASE_Q); + ds->next_dts += av_rescale_q(fields, av_inv_q(field_rate), AV_TIME_BASE_Q); } break; } @@ -342,7 +353,7 @@ static int ist_dts_update(DemuxStream *ds, AVPacket *pkt) return AVERROR(ENOMEM); pd = (DemuxPktData*)pkt->opaque_ref->data; - pd->dts_est = ist->dts; + pd->dts_est = ds->dts; } return 0; @@ -502,7 +513,7 @@ static void readrate_sleep(Demuxer *d) DemuxStream *ds = ds_from_ist(ist); int64_t stream_ts_offset, pts, now; stream_ts_offset = FFMAX(ds->first_dts != AV_NOPTS_VALUE ? ds->first_dts : 0, file_start); - pts = av_rescale(ist->dts, 1000000, AV_TIME_BASE); + pts = av_rescale(ds->dts, 1000000, AV_TIME_BASE); now = (av_gettime_relative() - ist->start) * f->readrate + stream_ts_offset; if (pts - burst_until > now) av_usleep(pts - burst_until - now); @@ -983,7 +994,7 @@ static void add_input_streams(const OptionsContext *o, Demuxer *d) st->discard = AVDISCARD_ALL; ist->nb_samples = 0; ds->first_dts = AV_NOPTS_VALUE; - ist->next_dts = AV_NOPTS_VALUE; + ds->next_dts = AV_NOPTS_VALUE; ds->min_pts = INT64_MAX; ds->max_pts = INT64_MIN; From 7df3253c5a769239de16a878828ba94b15a15f8b Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Sun, 7 May 2023 16:19:38 +0200 Subject: [PATCH 1026/2172] fftools/ffmpeg_demux: move InputStream.wrap_correction_done to private data It is no longer used outside of ffmpeg_demux. --- fftools/ffmpeg.h | 2 -- fftools/ffmpeg_demux.c | 9 +++++---- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/fftools/ffmpeg.h b/fftools/ffmpeg.h index b8c0e7db844..559381531eb 100644 --- a/fftools/ffmpeg.h +++ b/fftools/ffmpeg.h @@ -373,8 +373,6 @@ typedef struct InputStream { AVRational last_frame_tb; int last_frame_sample_rate; - int wrap_correction_done; - int64_t filter_in_rescale_delta_last; // when forcing constant input framerate through -r, diff --git a/fftools/ffmpeg_demux.c b/fftools/ffmpeg_demux.c index 7cf32242d99..4a04b3e574f 100644 --- a/fftools/ffmpeg_demux.c +++ b/fftools/ffmpeg_demux.c @@ -60,6 +60,7 @@ typedef struct DemuxStream { double ts_scale; + int wrap_correction_done; int saw_first_ts; ///< dts of the first packet read for this stream (in AV_TIME_BASE units) int64_t first_dts; @@ -383,21 +384,21 @@ static int ts_fixup(Demuxer *d, AVPacket *pkt) SHOW_TS_DEBUG("demuxer"); - if (!ist->wrap_correction_done && start_time != AV_NOPTS_VALUE && + if (!ds->wrap_correction_done && start_time != AV_NOPTS_VALUE && ist->st->pts_wrap_bits < 64) { int64_t stime, stime2; stime = av_rescale_q(start_time, AV_TIME_BASE_Q, pkt->time_base); stime2= stime + (1ULL<st->pts_wrap_bits); - ist->wrap_correction_done = 1; + ds->wrap_correction_done = 1; if(stime2 > stime && pkt->dts != AV_NOPTS_VALUE && pkt->dts > stime + (1LL<<(ist->st->pts_wrap_bits-1))) { pkt->dts -= 1ULL<st->pts_wrap_bits; - ist->wrap_correction_done = 0; + ds->wrap_correction_done = 0; } if(stime2 > stime && pkt->pts != AV_NOPTS_VALUE && pkt->pts > stime + (1LL<<(ist->st->pts_wrap_bits-1))) { pkt->pts -= 1ULL<st->pts_wrap_bits; - ist->wrap_correction_done = 0; + ds->wrap_correction_done = 0; } } From 6b0c984f0dfe632ec0d59fb12c8880240c5208c0 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Sun, 7 May 2023 16:19:38 +0200 Subject: [PATCH 1027/2172] fftools/ffmpeg_demux: move InputStream.streamcopy_needed to private data It is no longer used outside of ffmpeg_demux. --- fftools/ffmpeg.h | 1 - fftools/ffmpeg_demux.c | 8 ++++++-- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/fftools/ffmpeg.h b/fftools/ffmpeg.h index 559381531eb..7eb6301c74c 100644 --- a/fftools/ffmpeg.h +++ b/fftools/ffmpeg.h @@ -343,7 +343,6 @@ typedef struct InputStream { int discard; /* true if stream data should be discarded */ int user_set_discard; int decoding_needed; /* non zero if the packets must be decoded in 'raw_fifo', see DECODING_FOR_* */ - int streamcopy_needed; #define DECODING_FOR_OST 1 #define DECODING_FOR_FILTER 2 // should attach FrameData as opaque_ref after decoding diff --git a/fftools/ffmpeg_demux.c b/fftools/ffmpeg_demux.c index 4a04b3e574f..ccf1a70d5e6 100644 --- a/fftools/ffmpeg_demux.c +++ b/fftools/ffmpeg_demux.c @@ -60,6 +60,8 @@ typedef struct DemuxStream { double ts_scale; + int streamcopy_needed; + int wrap_correction_done; int saw_first_ts; ///< dts of the first packet read for this stream (in AV_TIME_BASE units) @@ -346,7 +348,7 @@ static int ist_dts_update(DemuxStream *ds, AVPacket *pkt) } av_assert0(!pkt->opaque_ref); - if (ist->streamcopy_needed) { + if (ds->streamcopy_needed) { DemuxPktData *pd; pkt->opaque_ref = av_buffer_allocz(sizeof(*pd)); @@ -806,10 +808,12 @@ void ifile_close(InputFile **pf) static void ist_use(InputStream *ist, int decoding_needed) { + DemuxStream *ds = ds_from_ist(ist); + ist->discard = 0; ist->st->discard = ist->user_set_discard; ist->decoding_needed |= decoding_needed; - ist->streamcopy_needed |= !decoding_needed; + ds->streamcopy_needed |= !decoding_needed; if (decoding_needed && !avcodec_is_open(ist->dec_ctx)) { int ret = dec_open(ist); From f9657b7443f674c159f305a6033b985d034d0f3b Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Sun, 7 May 2023 18:01:19 +0200 Subject: [PATCH 1028/2172] fftools/ffmpeg: simplify tracking -readrate start time There is no point in having a per-stream wallclock start time, since they are all computed at the same instant. Keep a per-file start time instead, initialized when the demuxer thread starts. --- fftools/ffmpeg.c | 8 -------- fftools/ffmpeg.h | 2 -- fftools/ffmpeg_demux.c | 6 +++++- 3 files changed, 5 insertions(+), 11 deletions(-) diff --git a/fftools/ffmpeg.c b/fftools/ffmpeg.c index 9cf94f2a22b..40e97ad4862 100644 --- a/fftools/ffmpeg.c +++ b/fftools/ffmpeg.c @@ -1498,14 +1498,6 @@ static int transcode_init(void) { int ret = 0; - /* init framerate emulation */ - for (int i = 0; i < nb_input_files; i++) { - InputFile *ifile = input_files[i]; - if (ifile->readrate) - for (int j = 0; j < ifile->nb_streams; j++) - ifile->streams[j]->start = av_gettime_relative(); - } - /* discard unused programs */ for (int i = 0; i < nb_input_files; i++) { InputFile *ifile = input_files[i]; diff --git a/fftools/ffmpeg.h b/fftools/ffmpeg.h index 7eb6301c74c..d1af94590d4 100644 --- a/fftools/ffmpeg.h +++ b/fftools/ffmpeg.h @@ -362,8 +362,6 @@ typedef struct InputStream { AVRational framerate_guessed; - int64_t start; /* time when read started */ - // pts/estimated duration of the last decoded frame // * in decoder timebase for video, // * in last_frame_tb (may change during decoding) for audio diff --git a/fftools/ffmpeg_demux.c b/fftools/ffmpeg_demux.c index ccf1a70d5e6..aff80b1cd33 100644 --- a/fftools/ffmpeg_demux.c +++ b/fftools/ffmpeg_demux.c @@ -88,6 +88,8 @@ typedef struct Demuxer { // name used for logging char log_name[32]; + int64_t wallclock_start; + /* number of times input stream should be looped */ int loop; /* actual duration of the longest stream in a file at the moment when @@ -517,7 +519,7 @@ static void readrate_sleep(Demuxer *d) int64_t stream_ts_offset, pts, now; stream_ts_offset = FFMAX(ds->first_dts != AV_NOPTS_VALUE ? ds->first_dts : 0, file_start); pts = av_rescale(ds->dts, 1000000, AV_TIME_BASE); - now = (av_gettime_relative() - ist->start) * f->readrate + stream_ts_offset; + now = (av_gettime_relative() - d->wallclock_start) * f->readrate + stream_ts_offset; if (pts - burst_until > now) av_usleep(pts - burst_until - now); } @@ -546,6 +548,8 @@ static void *input_thread(void *arg) thread_set_name(f); + d->wallclock_start = av_gettime_relative(); + while (1) { DemuxMsg msg = { NULL }; From 9429624a76107020b5911f8307f366fed386b336 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Sun, 7 May 2023 18:14:46 +0200 Subject: [PATCH 1029/2172] fftools/ffmpeg: move discarding unused programs to ffmpeg_demux This is a more appropriate place for this code. --- fftools/ffmpeg.c | 16 ---------------- fftools/ffmpeg_demux.c | 17 +++++++++++++++++ 2 files changed, 17 insertions(+), 16 deletions(-) diff --git a/fftools/ffmpeg.c b/fftools/ffmpeg.c index 40e97ad4862..725ffca6310 100644 --- a/fftools/ffmpeg.c +++ b/fftools/ffmpeg.c @@ -1498,22 +1498,6 @@ static int transcode_init(void) { int ret = 0; - /* discard unused programs */ - for (int i = 0; i < nb_input_files; i++) { - InputFile *ifile = input_files[i]; - for (int j = 0; j < ifile->ctx->nb_programs; j++) { - AVProgram *p = ifile->ctx->programs[j]; - int discard = AVDISCARD_ALL; - - for (int k = 0; k < p->nb_stream_indexes; k++) - if (!ifile->streams[p->stream_index[k]]->discard) { - discard = AVDISCARD_DEFAULT; - break; - } - p->discard = discard; - } - } - /* dump the stream mapping */ av_log(NULL, AV_LOG_INFO, "Stream mapping:\n"); for (InputStream *ist = ist_iter(NULL); ist; ist = ist_iter(ist)) { diff --git a/fftools/ffmpeg_demux.c b/fftools/ffmpeg_demux.c index aff80b1cd33..579dbcbe356 100644 --- a/fftools/ffmpeg_demux.c +++ b/fftools/ffmpeg_demux.c @@ -525,6 +525,21 @@ static void readrate_sleep(Demuxer *d) } } +static void discard_unused_programs(InputFile *ifile) +{ + for (int j = 0; j < ifile->ctx->nb_programs; j++) { + AVProgram *p = ifile->ctx->programs[j]; + int discard = AVDISCARD_ALL; + + for (int k = 0; k < p->nb_stream_indexes; k++) + if (!ifile->streams[p->stream_index[k]]->discard) { + discard = AVDISCARD_DEFAULT; + break; + } + p->discard = discard; + } +} + static void thread_set_name(InputFile *f) { char name[16]; @@ -548,6 +563,8 @@ static void *input_thread(void *arg) thread_set_name(f); + discard_unused_programs(f); + d->wallclock_start = av_gettime_relative(); while (1) { From fd980b261536fbd30f2c8df42779ecb09bf1b240 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Sun, 7 May 2023 18:15:39 +0200 Subject: [PATCH 1030/2172] fftools/ffmpeg_demux: reindent after previous commit --- fftools/ffmpeg_demux.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/fftools/ffmpeg_demux.c b/fftools/ffmpeg_demux.c index 579dbcbe356..f3a6597ddf3 100644 --- a/fftools/ffmpeg_demux.c +++ b/fftools/ffmpeg_demux.c @@ -527,17 +527,17 @@ static void readrate_sleep(Demuxer *d) static void discard_unused_programs(InputFile *ifile) { - for (int j = 0; j < ifile->ctx->nb_programs; j++) { - AVProgram *p = ifile->ctx->programs[j]; - int discard = AVDISCARD_ALL; + for (int j = 0; j < ifile->ctx->nb_programs; j++) { + AVProgram *p = ifile->ctx->programs[j]; + int discard = AVDISCARD_ALL; - for (int k = 0; k < p->nb_stream_indexes; k++) - if (!ifile->streams[p->stream_index[k]]->discard) { - discard = AVDISCARD_DEFAULT; - break; - } - p->discard = discard; - } + for (int k = 0; k < p->nb_stream_indexes; k++) + if (!ifile->streams[p->stream_index[k]]->discard) { + discard = AVDISCARD_DEFAULT; + break; + } + p->discard = discard; + } } static void thread_set_name(InputFile *f) From a1002bc39c46df5d468666e6bd9f490b023d3ca2 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Sun, 7 May 2023 18:29:09 +0200 Subject: [PATCH 1031/2172] fftools/ffmpeg: replace print_error() by more meaningful messages --- fftools/ffmpeg.c | 5 ++--- fftools/ffmpeg_demux.c | 3 ++- fftools/ffmpeg_mux.c | 4 +++- 3 files changed, 7 insertions(+), 5 deletions(-) diff --git a/fftools/ffmpeg.c b/fftools/ffmpeg.c index 725ffca6310..981714d027f 100644 --- a/fftools/ffmpeg.c +++ b/fftools/ffmpeg.c @@ -1756,12 +1756,10 @@ static void decode_flush(InputFile *ifile) static int process_input(int file_index) { InputFile *ifile = input_files[file_index]; - AVFormatContext *is; InputStream *ist; AVPacket *pkt; int ret, i; - is = ifile->ctx; ret = ifile_get_packet(ifile, &pkt); if (ret == AVERROR(EAGAIN)) { @@ -1775,7 +1773,8 @@ static int process_input(int file_index) } if (ret < 0) { if (ret != AVERROR_EOF) { - print_error(is->url, ret); + av_log(ifile, AV_LOG_ERROR, + "Error retrieving a packet from demuxer: %s\n", av_err2str(ret)); if (exit_on_error) exit_program(1); } diff --git a/fftools/ffmpeg_demux.c b/fftools/ffmpeg_demux.c index f3a6597ddf3..2822f0ab7fa 100644 --- a/fftools/ffmpeg_demux.c +++ b/fftools/ffmpeg_demux.c @@ -1405,7 +1405,8 @@ int ifile_open(const OptionsContext *o, const char *filename) /* open the input file with generic avformat function */ err = avformat_open_input(&ic, filename, file_iformat, &o->g->format_opts); if (err < 0) { - print_error(filename, err); + av_log(d, AV_LOG_ERROR, + "Error opening input: %s\n", av_err2str(err)); if (err == AVERROR_PROTOCOL_NOT_FOUND) av_log(d, AV_LOG_ERROR, "Did you mean file:%s?\n", filename); exit_program(1); diff --git a/fftools/ffmpeg_mux.c b/fftools/ffmpeg_mux.c index afcd4df99b7..36ed4820720 100644 --- a/fftools/ffmpeg_mux.c +++ b/fftools/ffmpeg_mux.c @@ -139,7 +139,9 @@ static int write_packet(Muxer *mux, OutputStream *ost, AVPacket *pkt) ret = av_interleaved_write_frame(s, pkt); if (ret < 0) { - print_error("av_interleaved_write_frame()", ret); + av_log(ost, AV_LOG_ERROR, + "Error submitting a packet to the muxer: %s\n", + av_err2str(ret)); goto fail; } From 2ab9f247f7feb23bc9765dcbcc574687552fcea6 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Sun, 7 May 2023 18:46:15 +0200 Subject: [PATCH 1032/2172] fftools/ffmpeg: log corrupt-frame errors to the appropriate context --- fftools/ffmpeg.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/fftools/ffmpeg.c b/fftools/ffmpeg.c index 981714d027f..092c5e179a1 100644 --- a/fftools/ffmpeg.c +++ b/fftools/ffmpeg.c @@ -779,8 +779,8 @@ static void check_decode_result(InputStream *ist, int *got_output, int ret) if (*got_output && ist) { if (ist->decoded_frame->decode_error_flags || (ist->decoded_frame->flags & AV_FRAME_FLAG_CORRUPT)) { - av_log(NULL, exit_on_error ? AV_LOG_FATAL : AV_LOG_WARNING, - "%s: corrupt decoded frame in stream %d\n", input_files[ist->file_index]->ctx->url, ist->st->index); + av_log(ist, exit_on_error ? AV_LOG_FATAL : AV_LOG_WARNING, + "corrupt decoded frame\n"); if (exit_on_error) exit_program(1); } From ab223a4d8cdcbf3b7b6b9b6c3ecc95203a342f5c Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Sun, 7 May 2023 18:50:15 +0200 Subject: [PATCH 1033/2172] fftools/ffmpeg: stop accessing input format from decoding code Export the corresponding flag in InputFile instead. This will allow making the demuxer AVFormatContext private in future commits, similarly to what was previously done for muxers. --- fftools/ffmpeg.c | 5 ++--- fftools/ffmpeg.h | 3 +++ fftools/ffmpeg_demux.c | 2 ++ 3 files changed, 7 insertions(+), 3 deletions(-) diff --git a/fftools/ffmpeg.c b/fftools/ffmpeg.c index 092c5e179a1..45efa750472 100644 --- a/fftools/ffmpeg.c +++ b/fftools/ffmpeg.c @@ -976,7 +976,6 @@ static int decode_audio(InputStream *ist, const AVPacket *pkt, int *got_output, static int64_t video_duration_estimate(const InputStream *ist, const AVFrame *frame) { const InputFile *ifile = input_files[ist->file_index]; - const int container_nots = !!(ifile->ctx->iformat->flags & AVFMT_NOTIMESTAMPS); int64_t codec_duration = 0; // XXX lavf currently makes up frame durations when they are not provided by @@ -986,7 +985,7 @@ static int64_t video_duration_estimate(const InputStream *ist, const AVFrame *fr // durations, then this should be simplified. // prefer frame duration for containers with timestamps - if (frame->duration > 0 && !container_nots) + if (frame->duration > 0 && !ifile->format_nots) return frame->duration; if (ist->dec_ctx->framerate.den && ist->dec_ctx->framerate.num) { @@ -998,7 +997,7 @@ static int64_t video_duration_estimate(const InputStream *ist, const AVFrame *fr } // prefer codec-layer duration for containers without timestamps - if (codec_duration > 0 && container_nots) + if (codec_duration > 0 && ifile->format_nots) return codec_duration; // when timestamps are available, repeat last frame's actual duration diff --git a/fftools/ffmpeg.h b/fftools/ffmpeg.h index d1af94590d4..5863ca1fafc 100644 --- a/fftools/ffmpeg.h +++ b/fftools/ffmpeg.h @@ -442,6 +442,9 @@ typedef struct InputFile { int index; + // input format has no timestamps + int format_nots; + AVFormatContext *ctx; int eof_reached; /* true if eof reached */ int eagain; /* true if last read attempt returned EAGAIN */ diff --git a/fftools/ffmpeg_demux.c b/fftools/ffmpeg_demux.c index 2822f0ab7fa..581990fdf24 100644 --- a/fftools/ffmpeg_demux.c +++ b/fftools/ffmpeg_demux.c @@ -1504,6 +1504,8 @@ int ifile_open(const OptionsContext *o, const char *filename) d->duration = 0; d->time_base = (AVRational){ 1, 1 }; + f->format_nots = !!(ic->iformat->flags & AVFMT_NOTIMESTAMPS); + f->readrate = o->readrate ? o->readrate : 0.0; if (f->readrate < 0.0f) { av_log(d, AV_LOG_ERROR, "Option -readrate is %0.3f; it must be non-negative.\n", f->readrate); From c5d77dcbf12c241059743f001a243406b7381acb Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Sun, 7 May 2023 16:19:38 +0200 Subject: [PATCH 1034/2172] fftools/ffmpeg_demux: move InputFile.ts_offset_discont,last_ts to private data They are no longer used outside of ffmpeg_demux. --- fftools/ffmpeg.h | 5 ----- fftools/ffmpeg_demux.c | 31 +++++++++++++++++++------------ 2 files changed, 19 insertions(+), 17 deletions(-) diff --git a/fftools/ffmpeg.h b/fftools/ffmpeg.h index 5863ca1fafc..f88792d7eb4 100644 --- a/fftools/ffmpeg.h +++ b/fftools/ffmpeg.h @@ -455,11 +455,6 @@ typedef struct InputFile { */ int64_t start_time_effective; int64_t ts_offset; - /** - * Extra timestamp offset added by discontinuity handling. - */ - int64_t ts_offset_discont; - int64_t last_ts; int64_t start_time; /* user-specified start time in AV_TIME_BASE or AV_NOPTS_VALUE */ int64_t recording_time; diff --git a/fftools/ffmpeg_demux.c b/fftools/ffmpeg_demux.c index 581990fdf24..58d8fa75e59 100644 --- a/fftools/ffmpeg_demux.c +++ b/fftools/ffmpeg_demux.c @@ -90,6 +90,12 @@ typedef struct Demuxer { int64_t wallclock_start; + /** + * Extra timestamp offset added by discontinuity handling. + */ + int64_t ts_offset_discont; + int64_t last_ts; + /* number of times input stream should be looped */ int loop; /* actual duration of the longest stream in a file at the moment when @@ -205,9 +211,10 @@ static int seek_to_start(Demuxer *d) return ret; } -static void ts_discontinuity_detect(InputFile *ifile, InputStream *ist, +static void ts_discontinuity_detect(Demuxer *d, InputStream *ist, AVPacket *pkt) { + InputFile *ifile = &d->f; DemuxStream *ds = ds_from_ist(ist); const int fmt_is_discont = ifile->ctx->iformat->flags & AVFMT_TS_DISCONT; int disable_discontinuity_correction = copy_ts; @@ -228,13 +235,13 @@ static void ts_discontinuity_detect(InputFile *ifile, InputStream *ist, if (fmt_is_discont) { if (FFABS(delta) > 1LL * dts_delta_threshold * AV_TIME_BASE || pkt_dts + AV_TIME_BASE/10 < ds->dts) { - ifile->ts_offset_discont -= delta; + d->ts_offset_discont -= delta; av_log(NULL, AV_LOG_WARNING, "timestamp discontinuity for stream #%d:%d " "(id=%d, type=%s): %"PRId64", new offset= %"PRId64"\n", ist->file_index, ist->st->index, ist->st->id, av_get_media_type_string(ist->par->codec_type), - delta, ifile->ts_offset_discont); + delta, d->ts_offset_discont); pkt->dts -= av_rescale_q(delta, AV_TIME_BASE_Q, pkt->time_base); if (pkt->pts != AV_NOPTS_VALUE) pkt->pts -= av_rescale_q(delta, AV_TIME_BASE_Q, pkt->time_base); @@ -258,26 +265,26 @@ static void ts_discontinuity_detect(InputFile *ifile, InputStream *ist, } } } else if (ds->next_dts == AV_NOPTS_VALUE && !copy_ts && - fmt_is_discont && ifile->last_ts != AV_NOPTS_VALUE) { - int64_t delta = pkt_dts - ifile->last_ts; + fmt_is_discont && d->last_ts != AV_NOPTS_VALUE) { + int64_t delta = pkt_dts - d->last_ts; if (FFABS(delta) > 1LL * dts_delta_threshold * AV_TIME_BASE) { - ifile->ts_offset_discont -= delta; + d->ts_offset_discont -= delta; av_log(NULL, AV_LOG_DEBUG, "Inter stream timestamp discontinuity %"PRId64", new offset= %"PRId64"\n", - delta, ifile->ts_offset_discont); + delta, d->ts_offset_discont); pkt->dts -= av_rescale_q(delta, AV_TIME_BASE_Q, pkt->time_base); if (pkt->pts != AV_NOPTS_VALUE) pkt->pts -= av_rescale_q(delta, AV_TIME_BASE_Q, pkt->time_base); } } - ifile->last_ts = av_rescale_q(pkt->dts, pkt->time_base, AV_TIME_BASE_Q); + d->last_ts = av_rescale_q(pkt->dts, pkt->time_base, AV_TIME_BASE_Q); } -static void ts_discontinuity_process(InputFile *ifile, InputStream *ist, +static void ts_discontinuity_process(Demuxer *d, InputStream *ist, AVPacket *pkt) { - int64_t offset = av_rescale_q(ifile->ts_offset_discont, AV_TIME_BASE_Q, + int64_t offset = av_rescale_q(d->ts_offset_discont, AV_TIME_BASE_Q, pkt->time_base); // apply previously-detected timestamp-discontinuity offset @@ -291,7 +298,7 @@ static void ts_discontinuity_process(InputFile *ifile, InputStream *ist, if ((ist->par->codec_type == AVMEDIA_TYPE_VIDEO || ist->par->codec_type == AVMEDIA_TYPE_AUDIO) && pkt->dts != AV_NOPTS_VALUE) - ts_discontinuity_detect(ifile, ist, pkt); + ts_discontinuity_detect(d, ist, pkt); } static int ist_dts_update(DemuxStream *ds, AVPacket *pkt) @@ -429,7 +436,7 @@ static int ts_fixup(Demuxer *d, AVPacket *pkt) SHOW_TS_DEBUG("demuxer+tsfixup"); // detect and try to correct for timestamp discontinuities - ts_discontinuity_process(ifile, ist, pkt); + ts_discontinuity_process(d, ist, pkt); // update estimated/predicted dts ret = ist_dts_update(ds, pkt); From de6d60117e7ac3a3707cd713e269fdf39775cfa1 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Sun, 7 May 2023 19:11:15 +0200 Subject: [PATCH 1035/2172] fftools/ffmpeg_demux: stop logging to demuxer context Only the demuxer itself should do that. --- fftools/ffmpeg_demux.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/fftools/ffmpeg_demux.c b/fftools/ffmpeg_demux.c index 58d8fa75e59..0a37cc7c25e 100644 --- a/fftools/ffmpeg_demux.c +++ b/fftools/ffmpeg_demux.c @@ -641,14 +641,14 @@ static void *input_thread(void *arg) if (flags && ret == AVERROR(EAGAIN)) { flags = 0; ret = av_thread_message_queue_send(d->in_thread_queue, &msg, flags); - av_log(f->ctx, AV_LOG_WARNING, + av_log(f, AV_LOG_WARNING, "Thread message queue blocking; consider raising the " "thread_queue_size option (current value: %d)\n", d->thread_queue_size); } if (ret < 0) { if (ret != AVERROR_EOF) - av_log(f->ctx, AV_LOG_ERROR, + av_log(f, AV_LOG_ERROR, "Unable to send packet to main thread: %s\n", av_err2str(ret)); av_packet_free(&msg.pkt); From 7be945a011917f3cff0ca8d7c09e0a71fe31d2c2 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Sun, 7 May 2023 19:38:51 +0200 Subject: [PATCH 1036/2172] fftools/ffmpeg: rename transcode_init() It does no initialization anymore, except for setting transcode_init_done - the bulk of the function is printing the input/output maps. It also cannot fail anymore, so remove the useless return value. --- fftools/ffmpeg.c | 18 ++++-------------- 1 file changed, 4 insertions(+), 14 deletions(-) diff --git a/fftools/ffmpeg.c b/fftools/ffmpeg.c index 45efa750472..ebd793a98c5 100644 --- a/fftools/ffmpeg.c +++ b/fftools/ffmpeg.c @@ -1493,11 +1493,8 @@ static int process_input_packet(InputStream *ist, const AVPacket *pkt, int no_eo return !eof_reached; } -static int transcode_init(void) +static void print_stream_maps(void) { - int ret = 0; - - /* dump the stream mapping */ av_log(NULL, AV_LOG_INFO, "Stream mapping:\n"); for (InputStream *ist = ist_iter(NULL); ist; ist = ist_iter(ist)) { for (int j = 0; j < ist->nb_filters; j++) { @@ -1570,13 +1567,6 @@ static int transcode_init(void) av_log(NULL, AV_LOG_INFO, " (copy)"); av_log(NULL, AV_LOG_INFO, "\n"); } - - if (ret) - return ret; - - atomic_store(&transcode_init_done, 1); - - return 0; } /** @@ -1854,9 +1844,9 @@ static int transcode(void) InputStream *ist; int64_t timer_start; - ret = transcode_init(); - if (ret < 0) - return ret; + print_stream_maps(); + + atomic_store(&transcode_init_done, 1); if (stdin_interaction) { av_log(NULL, AV_LOG_INFO, "Press [q] to stop, [?] for help\n"); From e10a5b91bc1b138174ab2661171038431ca44213 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Thu, 4 May 2023 08:47:33 +0200 Subject: [PATCH 1037/2172] lavc/av1*: fix exporting framerate * take num_ticks_per_picture_minus_1 into account, since that is a part of the framerate computation * stop exporting num_ticks_per_picture_minus_1 into AVCodecContext.ticks_per_frame, as that field is used for other purposes (in conjunction with repeat_pict, which is not used at all by av1) --- libavcodec/Makefile | 2 +- libavcodec/av1_parse.c | 14 ++++++++++++++ libavcodec/av1_parse.h | 3 +++ libavcodec/av1_parser.c | 11 ++++++----- libavcodec/av1dec.c | 14 +++++--------- 5 files changed, 29 insertions(+), 15 deletions(-) diff --git a/libavcodec/Makefile b/libavcodec/Makefile index 3cf4444b7eb..9587e56493f 100644 --- a/libavcodec/Makefile +++ b/libavcodec/Makefile @@ -1143,7 +1143,7 @@ OBJS-$(CONFIG_AC3_PARSER) += aac_ac3_parser.o ac3tab.o \ ac3_channel_layout_tab.o OBJS-$(CONFIG_ADX_PARSER) += adx_parser.o OBJS-$(CONFIG_AMR_PARSER) += amr_parser.o -OBJS-$(CONFIG_AV1_PARSER) += av1_parser.o +OBJS-$(CONFIG_AV1_PARSER) += av1_parser.o av1_parse.o OBJS-$(CONFIG_AVS2_PARSER) += avs2.o avs2_parser.o OBJS-$(CONFIG_AVS3_PARSER) += avs3_parser.o OBJS-$(CONFIG_BMP_PARSER) += bmp_parser.o diff --git a/libavcodec/av1_parse.c b/libavcodec/av1_parse.c index 59ea0bc6e75..136ad1a58f7 100644 --- a/libavcodec/av1_parse.c +++ b/libavcodec/av1_parse.c @@ -108,3 +108,17 @@ void ff_av1_packet_uninit(AV1Packet *pkt) av_freep(&pkt->obus); pkt->obus_allocated = pkt->obus_allocated_size = 0; } + +AVRational ff_av1_framerate(int64_t ticks_per_frame, int64_t units_per_tick, + int64_t time_scale) +{ + AVRational fr; + + if (ticks_per_frame && units_per_tick && time_scale && + ticks_per_frame < INT64_MAX / units_per_tick && + av_reduce(&fr.den, &fr.num, units_per_tick * ticks_per_frame, + time_scale, INT_MAX)) + return fr; + + return (AVRational){ 0, 1 }; +} diff --git a/libavcodec/av1_parse.h b/libavcodec/av1_parse.h index f4a5d2830ec..1f3001d2a58 100644 --- a/libavcodec/av1_parse.h +++ b/libavcodec/av1_parse.h @@ -181,4 +181,7 @@ static inline int get_obu_bit_length(const uint8_t *buf, int size, int type) return size; } +AVRational ff_av1_framerate(int64_t ticks_per_frame, int64_t units_per_tick, + int64_t time_scale); + #endif /* AVCODEC_AV1_PARSE_H */ diff --git a/libavcodec/av1_parser.c b/libavcodec/av1_parser.c index 14dae92fe9f..2b79493bf8f 100644 --- a/libavcodec/av1_parser.c +++ b/libavcodec/av1_parser.c @@ -21,6 +21,8 @@ */ #include "libavutil/avassert.h" + +#include "av1_parse.h" #include "cbs.h" #include "cbs_av1.h" #include "parser.h" @@ -162,11 +164,10 @@ static int av1_parser_parse(AVCodecParserContext *ctx, avctx->color_trc = (enum AVColorTransferCharacteristic) color->transfer_characteristics; avctx->color_range = color->color_range ? AVCOL_RANGE_JPEG : AVCOL_RANGE_MPEG; - if (seq->timing_info_present_flag) { - const AV1RawTimingInfo *timing = &seq->timing_info; - av_reduce(&avctx->framerate.den, &avctx->framerate.num, - timing->num_units_in_display_tick, timing->time_scale, INT_MAX); - } + if (seq->timing_info_present_flag) + avctx->framerate = ff_av1_framerate(1LL + seq->timing_info.num_ticks_per_picture_minus_1, + seq->timing_info.num_units_in_display_tick, + seq->timing_info.time_scale); end: ff_cbs_fragment_reset(td); diff --git a/libavcodec/av1dec.c b/libavcodec/av1dec.c index c90c9c1a69e..d46ee48335f 100644 --- a/libavcodec/av1dec.c +++ b/libavcodec/av1dec.c @@ -26,6 +26,7 @@ #include "libavutil/pixdesc.h" #include "libavutil/opt.h" #include "avcodec.h" +#include "av1_parse.h" #include "av1dec.h" #include "atsc_a53.h" #include "bytestream.h" @@ -709,15 +710,10 @@ static int set_context_with_sequence(AVCodecContext *avctx, } avctx->sample_aspect_ratio = (AVRational) { 1, 1 }; - if (seq->timing_info.num_units_in_display_tick && - seq->timing_info.time_scale) { - av_reduce(&avctx->framerate.den, &avctx->framerate.num, - seq->timing_info.num_units_in_display_tick, - seq->timing_info.time_scale, - INT_MAX); - if (seq->timing_info.equal_picture_interval) - avctx->ticks_per_frame = seq->timing_info.num_ticks_per_picture_minus_1 + 1; - } + if (seq->timing_info_present_flag) + avctx->framerate = ff_av1_framerate(1LL + seq->timing_info.num_ticks_per_picture_minus_1, + seq->timing_info.num_units_in_display_tick, + seq->timing_info.time_scale); return 0; } From 9d70e74d255dbe37af52b0efffc0f93fd7cb6103 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Thu, 4 May 2023 10:54:52 +0200 Subject: [PATCH 1038/2172] lavc/libdav1d: fix exporting framerate Same issues as in the previous commit. --- libavcodec/Makefile | 2 +- libavcodec/libdav1d.c | 10 ++++------ 2 files changed, 5 insertions(+), 7 deletions(-) diff --git a/libavcodec/Makefile b/libavcodec/Makefile index 9587e56493f..4d59411662f 100644 --- a/libavcodec/Makefile +++ b/libavcodec/Makefile @@ -1086,7 +1086,7 @@ OBJS-$(CONFIG_LIBARIBCAPTION_DECODER) += libaribcaption.o ass.o OBJS-$(CONFIG_LIBCELT_DECODER) += libcelt_dec.o OBJS-$(CONFIG_LIBCODEC2_DECODER) += libcodec2.o OBJS-$(CONFIG_LIBCODEC2_ENCODER) += libcodec2.o -OBJS-$(CONFIG_LIBDAV1D_DECODER) += libdav1d.o +OBJS-$(CONFIG_LIBDAV1D_DECODER) += libdav1d.o av1_parse.o OBJS-$(CONFIG_LIBDAVS2_DECODER) += libdavs2.o OBJS-$(CONFIG_LIBFDK_AAC_DECODER) += libfdk-aacdec.o OBJS-$(CONFIG_LIBFDK_AAC_ENCODER) += libfdk-aacenc.o diff --git a/libavcodec/libdav1d.c b/libavcodec/libdav1d.c index af072da6815..4c48f0099a7 100644 --- a/libavcodec/libdav1d.c +++ b/libavcodec/libdav1d.c @@ -30,6 +30,7 @@ #include "libavutil/opt.h" #include "atsc_a53.h" +#include "av1_parse.h" #include "avcodec.h" #include "bytestream.h" #include "codec_internal.h" @@ -154,12 +155,9 @@ static void libdav1d_init_params(AVCodecContext *c, const Dav1dSequenceHeader *s else c->pix_fmt = pix_fmt[seq->layout][seq->hbd]; - if (seq->num_units_in_tick && seq->time_scale) { - av_reduce(&c->framerate.den, &c->framerate.num, - seq->num_units_in_tick, seq->time_scale, INT_MAX); - if (seq->equal_picture_interval) - c->ticks_per_frame = seq->num_ticks_per_picture; - } + c->framerate = ff_av1_framerate(seq->num_ticks_per_picture, + (unsigned)seq->num_units_in_tick, + (unsigned)seq->time_scale); if (seq->film_grain_present) c->properties |= FF_CODEC_PROPERTY_FILM_GRAIN; From af8affb77efe8e1b9cfb4a288aec8feb8c25f569 Mon Sep 17 00:00:00 2001 From: Hendrik Leppkes Date: Mon, 15 May 2023 12:49:21 +0200 Subject: [PATCH 1039/2172] avcodec/nvdec_mpeg2: fix order of quant matrix coefficients The matrix coefficients are stored permutated for the IDCT, rather then in plain raster order, and need to be un-permutated for the hardware. --- libavcodec/nvdec_mpeg12.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/libavcodec/nvdec_mpeg12.c b/libavcodec/nvdec_mpeg12.c index e10735587d4..3b9ff60734f 100644 --- a/libavcodec/nvdec_mpeg12.c +++ b/libavcodec/nvdec_mpeg12.c @@ -83,8 +83,9 @@ static int nvdec_mpeg12_start_frame(AVCodecContext *avctx, const uint8_t *buffer }; for (i = 0; i < 64; ++i) { - ppc->QuantMatrixIntra[i] = s->intra_matrix[i]; - ppc->QuantMatrixInter[i] = s->inter_matrix[i]; + int n = s->idsp.idct_permutation[i]; + ppc->QuantMatrixIntra[i] = s->intra_matrix[n]; + ppc->QuantMatrixInter[i] = s->inter_matrix[n]; } return 0; From b3e938ef8057a1c248e650a7e54ac423fe1aaf03 Mon Sep 17 00:00:00 2001 From: Hendrik Leppkes Date: Mon, 15 May 2023 13:33:18 +0200 Subject: [PATCH 1040/2172] avcodec/nvdec_mpeg4: fix order of quant matrix coefficients The matrix coefficients are stored permutated for the IDCT, rather then in plain raster order, and need to be un-permutated for the hardware. --- libavcodec/nvdec_mpeg4.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/libavcodec/nvdec_mpeg4.c b/libavcodec/nvdec_mpeg4.c index eac138cc382..c193f6b6e47 100644 --- a/libavcodec/nvdec_mpeg4.c +++ b/libavcodec/nvdec_mpeg4.c @@ -88,8 +88,9 @@ static int nvdec_mpeg4_start_frame(AVCodecContext *avctx, const uint8_t *buffer, }; for (i = 0; i < 64; ++i) { - ppc->QuantMatrixIntra[i] = s->intra_matrix[i]; - ppc->QuantMatrixInter[i] = s->inter_matrix[i]; + int n = s->idsp.idct_permutation[i]; + ppc->QuantMatrixIntra[i] = s->intra_matrix[n]; + ppc->QuantMatrixInter[i] = s->inter_matrix[n]; } // We need to pass the full frame buffer and not just the slice From 308e4ae8e3a7dee551b9167a056b8983d48bcea4 Mon Sep 17 00:00:00 2001 From: Hendrik Leppkes Date: Mon, 15 May 2023 13:35:13 +0200 Subject: [PATCH 1041/2172] avcodec/vdpau_mpeg12: fix order of quant matrix coefficients The matrix coefficients are stored permutated for the IDCT, rather then in plain raster order, and need to be un-permutated for the hardware. --- libavcodec/vdpau_mpeg12.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/libavcodec/vdpau_mpeg12.c b/libavcodec/vdpau_mpeg12.c index 354239cad54..79007aa1a8f 100644 --- a/libavcodec/vdpau_mpeg12.c +++ b/libavcodec/vdpau_mpeg12.c @@ -75,8 +75,9 @@ static int vdpau_mpeg_start_frame(AVCodecContext *avctx, info->f_code[1][0] = s->mpeg_f_code[1][0]; info->f_code[1][1] = s->mpeg_f_code[1][1]; for (i = 0; i < 64; ++i) { - info->intra_quantizer_matrix[i] = s->intra_matrix[i]; - info->non_intra_quantizer_matrix[i] = s->inter_matrix[i]; + int n = s->idsp.idct_permutation[i]; + info->intra_quantizer_matrix[i] = s->intra_matrix[n]; + info->non_intra_quantizer_matrix[i] = s->inter_matrix[n]; } return ff_vdpau_common_start_frame(pic_ctx, buffer, size); From 6b2ae90411ce8f6f90269655bf912355121c0749 Mon Sep 17 00:00:00 2001 From: Hendrik Leppkes Date: Mon, 15 May 2023 13:35:42 +0200 Subject: [PATCH 1042/2172] avcodec/vdpau_mpeg4: fix order of quant matrix coefficients The matrix coefficients are stored permutated for the IDCT, rather then in plain raster order, and need to be un-permutated for the hardware. --- libavcodec/vdpau_mpeg4.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/libavcodec/vdpau_mpeg4.c b/libavcodec/vdpau_mpeg4.c index 6e082eefc68..1211b1df2c7 100644 --- a/libavcodec/vdpau_mpeg4.c +++ b/libavcodec/vdpau_mpeg4.c @@ -74,8 +74,9 @@ static int vdpau_mpeg4_start_frame(AVCodecContext *avctx, info->alternate_vertical_scan_flag = s->alternate_scan; info->top_field_first = s->top_field_first; for (i = 0; i < 64; ++i) { - info->intra_quantizer_matrix[i] = s->intra_matrix[i]; - info->non_intra_quantizer_matrix[i] = s->inter_matrix[i]; + int n = s->idsp.idct_permutation[i]; + info->intra_quantizer_matrix[i] = s->intra_matrix[n]; + info->non_intra_quantizer_matrix[i] = s->inter_matrix[n]; } ff_vdpau_common_start_frame(pic_ctx, buffer, size); From acd37fd5667ae1f0ed988ed45d7af3a41d766d80 Mon Sep 17 00:00:00 2001 From: Samuel Mira Date: Tue, 25 Apr 2023 19:37:05 +0300 Subject: [PATCH 1043/2172] avcodec/mediacodec: Add AV1 encoder Connected FFmpeg to Mediacodec AV1 encoder Signed-off-by: Samuel Mira Signed-off-by: Zhao Zhili --- configure | 1 + libavcodec/Makefile | 1 + libavcodec/allcodecs.c | 1 + libavcodec/mediacodec_wrapper.c | 19 +++++++ libavcodec/mediacodecenc.c | 91 +++++++++++++++++++++++++++++++++ libavcodec/version.h | 2 +- 6 files changed, 114 insertions(+), 1 deletion(-) diff --git a/configure b/configure index bb7be676763..0a60deac656 100755 --- a/configure +++ b/configure @@ -3162,6 +3162,7 @@ aac_mf_encoder_deps="mediafoundation" ac3_mf_encoder_deps="mediafoundation" av1_cuvid_decoder_deps="cuvid CUVIDAV1PICPARAMS" av1_mediacodec_decoder_deps="mediacodec" +av1_mediacodec_encoder_deps="mediacodec" av1_nvenc_encoder_deps="nvenc NV_ENC_PIC_PARAMS_AV1" av1_nvenc_encoder_select="atsc_a53" h263_v4l2m2m_decoder_deps="v4l2_m2m h263_v4l2_m2m" diff --git a/libavcodec/Makefile b/libavcodec/Makefile index 4d59411662f..2288c6c2d7c 100644 --- a/libavcodec/Makefile +++ b/libavcodec/Makefile @@ -253,6 +253,7 @@ OBJS-$(CONFIG_AURA2_DECODER) += aura.o OBJS-$(CONFIG_AV1_DECODER) += av1dec.o OBJS-$(CONFIG_AV1_CUVID_DECODER) += cuviddec.o OBJS-$(CONFIG_AV1_MEDIACODEC_DECODER) += mediacodecdec.o +OBJS-$(CONFIG_AV1_MEDIACODEC_ENCODER) += mediacodecenc.o OBJS-$(CONFIG_AV1_NVENC_ENCODER) += nvenc_av1.o nvenc.o OBJS-$(CONFIG_AV1_QSV_ENCODER) += qsvenc_av1.o OBJS-$(CONFIG_AVRN_DECODER) += avrndec.o diff --git a/libavcodec/allcodecs.c b/libavcodec/allcodecs.c index 8eeed34e57b..f583aad8602 100644 --- a/libavcodec/allcodecs.c +++ b/libavcodec/allcodecs.c @@ -836,6 +836,7 @@ extern const FFCodec ff_libaom_av1_decoder; extern const FFCodec ff_av1_decoder; extern const FFCodec ff_av1_cuvid_decoder; extern const FFCodec ff_av1_mediacodec_decoder; +extern const FFCodec ff_av1_mediacodec_encoder; extern const FFCodec ff_av1_nvenc_encoder; extern const FFCodec ff_av1_qsv_decoder; extern const FFCodec ff_av1_qsv_encoder; diff --git a/libavcodec/mediacodec_wrapper.c b/libavcodec/mediacodec_wrapper.c index 1c29bb74066..eb69ad7eaf3 100644 --- a/libavcodec/mediacodec_wrapper.c +++ b/libavcodec/mediacodec_wrapper.c @@ -345,6 +345,12 @@ int ff_AMediaCodecProfile_getProfileFromAVCodecContext(AVCodecContext *avctx) static const int MPEG4ProfileAdvancedScalable = 0x4000; static const int MPEG4ProfileAdvancedSimple = 0x8000; + + static const int AV1ProfileMain8 = 0x1; + static const int AV1ProfileMain10 = 0x2; + static const int AV1ProfileMain10HDR10 = 0x1000; + static const int AV1ProfileMain10HDR10Plus = 0x2000; + // Unused yet. (void)AVCProfileConstrainedHigh; (void)HEVCProfileMain10HDR10; @@ -353,6 +359,9 @@ int ff_AMediaCodecProfile_getProfileFromAVCodecContext(AVCodecContext *avctx) (void)VP9Profile3HDR; (void)VP9Profile2HDR10Plus; (void)VP9Profile3HDR10Plus; + (void)AV1ProfileMain10; + (void)AV1ProfileMain10HDR10; + (void)AV1ProfileMain10HDR10Plus; if (avctx->codec_id == AV_CODEC_ID_H264) { switch(avctx->profile) { @@ -436,6 +445,16 @@ int ff_AMediaCodecProfile_getProfileFromAVCodecContext(AVCodecContext *avctx) default: break; } + } else if(avctx->codec_id == AV_CODEC_ID_AV1) { + switch (avctx->profile) + { + case FF_PROFILE_AV1_MAIN: + return AV1ProfileMain8; + case FF_PROFILE_AV1_HIGH: + case FF_PROFILE_AV1_PROFESSIONAL: + default: + break; + } } return -1; diff --git a/libavcodec/mediacodecenc.c b/libavcodec/mediacodecenc.c index e4b583a542f..2b7bef444ee 100644 --- a/libavcodec/mediacodecenc.c +++ b/libavcodec/mediacodecenc.c @@ -170,6 +170,9 @@ static av_cold int mediacodec_init(AVCodecContext *avctx) case AV_CODEC_ID_MPEG4: codec_mime = "video/mp4v-es"; break; + case AV_CODEC_ID_AV1: + codec_mime = "video/av01"; + break; default: av_assert0(0); } @@ -878,3 +881,91 @@ static const AVOption mpeg4_options[] = { DECLARE_MEDIACODEC_ENCODER(mpeg4, "MPEG-4", AV_CODEC_ID_MPEG4) #endif // CONFIG_MPEG4_MEDIACODEC_ENCODER + +#if CONFIG_AV1_MEDIACODEC_ENCODER + +enum MediaCodecAV1Level { + AV1Level2 = 0x1, + AV1Level21 = 0x2, + AV1Level22 = 0x4, + AV1Level23 = 0x8, + AV1Level3 = 0x10, + AV1Level31 = 0x20, + AV1Level32 = 0x40, + AV1Level33 = 0x80, + AV1Level4 = 0x100, + AV1Level41 = 0x200, + AV1Level42 = 0x400, + AV1Level43 = 0x800, + AV1Level5 = 0x1000, + AV1Level51 = 0x2000, + AV1Level52 = 0x4000, + AV1Level53 = 0x8000, + AV1Level6 = 0x10000, + AV1Level61 = 0x20000, + AV1Level62 = 0x40000, + AV1Level63 = 0x80000, + AV1Level7 = 0x100000, + AV1Level71 = 0x200000, + AV1Level72 = 0x400000, + AV1Level73 = 0x800000, +}; + +static const AVOption av1_options[] = { + COMMON_OPTION + { "level", "Specify tier and level", + OFFSET(level), AV_OPT_TYPE_INT, {.i64 = 0}, 0, INT_MAX, VE, "level" }, + { "2", "Level 2", + 0, AV_OPT_TYPE_CONST, { .i64 = AV1Level2 }, 0, 0, VE, "level" }, + { "2.1", "Level 2.1", + 0, AV_OPT_TYPE_CONST, { .i64 = AV1Level21 }, 0, 0, VE, "level" }, + { "2.2", "Level 2.2", + 0, AV_OPT_TYPE_CONST, { .i64 = AV1Level22 }, 0, 0, VE, "level" }, + { "2.3", "Level 2.3", + 0, AV_OPT_TYPE_CONST, { .i64 = AV1Level23 }, 0, 0, VE, "level" }, + { "3", "Level 3", + 0, AV_OPT_TYPE_CONST, { .i64 = AV1Level3 }, 0, 0, VE, "level" }, + { "3.1", "Level 3.1", + 0, AV_OPT_TYPE_CONST, { .i64 = AV1Level31 }, 0, 0, VE, "level" }, + { "3.2", "Level 3.2", + 0, AV_OPT_TYPE_CONST, { .i64 = AV1Level32 }, 0, 0, VE, "level" }, + { "3.3", "Level 3.3", + 0, AV_OPT_TYPE_CONST, { .i64 = AV1Level33 }, 0, 0, VE, "level" }, + { "4", "Level 4", + 0, AV_OPT_TYPE_CONST, { .i64 = AV1Level4 }, 0, 0, VE, "level" }, + { "4.1", "Level 4.1", + 0, AV_OPT_TYPE_CONST, { .i64 = AV1Level41 }, 0, 0, VE, "level" }, + { "4.2", "Level 4.2", + 0, AV_OPT_TYPE_CONST, { .i64 = AV1Level42 }, 0, 0, VE, "level" }, + { "4.3", "Level 4.3", + 0, AV_OPT_TYPE_CONST, { .i64 = AV1Level43 }, 0, 0, VE, "level" }, + { "5", "Level 5", + 0, AV_OPT_TYPE_CONST, { .i64 = AV1Level5 }, 0, 0, VE, "level" }, + { "5.1", "Level 5.1", + 0, AV_OPT_TYPE_CONST, { .i64 = AV1Level51 }, 0, 0, VE, "level" }, + { "5.2", "Level 5.2", + 0, AV_OPT_TYPE_CONST, { .i64 = AV1Level52 }, 0, 0, VE, "level" }, + { "5.3", "Level 5.3", + 0, AV_OPT_TYPE_CONST, { .i64 = AV1Level53 }, 0, 0, VE, "level" }, + { "6", "Level 6", + 0, AV_OPT_TYPE_CONST, { .i64 = AV1Level6 }, 0, 0, VE, "level" }, + { "6.1", "Level 6.1", + 0, AV_OPT_TYPE_CONST, { .i64 = AV1Level61 }, 0, 0, VE, "level" }, + { "6.2", "Level 6.2", + 0, AV_OPT_TYPE_CONST, { .i64 = AV1Level62 }, 0, 0, VE, "level" }, + { "6.3", "Level 6.3", + 0, AV_OPT_TYPE_CONST, { .i64 = AV1Level63 }, 0, 0, VE, "level" }, + { "7", "Level 7", + 0, AV_OPT_TYPE_CONST, { .i64 = AV1Level7 }, 0, 0, VE, "level" }, + { "7.1", "Level 7.1", + 0, AV_OPT_TYPE_CONST, { .i64 = AV1Level71 }, 0, 0, VE, "level" }, + { "7.2", "Level 7.2", + 0, AV_OPT_TYPE_CONST, { .i64 = AV1Level72 }, 0, 0, VE, "level" }, + { "7.3", "Level 7.3", + 0, AV_OPT_TYPE_CONST, { .i64 = AV1Level73 }, 0, 0, VE, "level" }, + { NULL, } +}; + +DECLARE_MEDIACODEC_ENCODER(av1, "AV1", AV_CODEC_ID_AV1) + +#endif // CONFIG_AV1_MEDIACODEC_ENCODER diff --git a/libavcodec/version.h b/libavcodec/version.h index da2264a0972..755c90bbc1a 100644 --- a/libavcodec/version.h +++ b/libavcodec/version.h @@ -29,7 +29,7 @@ #include "version_major.h" -#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 416fd1b43b50a8407cf7263b70daf1e0cbdc0fe9 Mon Sep 17 00:00:00 2001 From: Samuel Mira Date: Wed, 19 Apr 2023 23:29:18 +0300 Subject: [PATCH 1044/2172] avcodec/mediacodec: Add VP8 encoder Connected FFmpeg to Mediacodec VP8 encoder. Signed-off-by: Samuel Mira Signed-off-by: Zhao Zhili --- configure | 1 + libavcodec/Makefile | 1 + libavcodec/allcodecs.c | 1 + libavcodec/mediacodecenc.c | 31 +++++++++++++++++++++++++++++++ libavcodec/version.h | 2 +- 5 files changed, 35 insertions(+), 1 deletion(-) diff --git a/configure b/configure index 0a60deac656..a54398c57fa 100755 --- a/configure +++ b/configure @@ -3240,6 +3240,7 @@ vc1_qsv_decoder_select="qsvdec" vc1_v4l2m2m_decoder_deps="v4l2_m2m vc1_v4l2_m2m" vp8_cuvid_decoder_deps="cuvid" vp8_mediacodec_decoder_deps="mediacodec" +vp8_mediacodec_encoder_deps="mediacodec" vp8_qsv_decoder_select="qsvdec" vp8_rkmpp_decoder_deps="rkmpp" vp8_vaapi_encoder_deps="VAEncPictureParameterBufferVP8" diff --git a/libavcodec/Makefile b/libavcodec/Makefile index 2288c6c2d7c..9c38240025c 100644 --- a/libavcodec/Makefile +++ b/libavcodec/Makefile @@ -767,6 +767,7 @@ OBJS-$(CONFIG_VP7_DECODER) += vp8.o vp8data.o vpx_rac.o OBJS-$(CONFIG_VP8_DECODER) += vp8.o vp8data.o vpx_rac.o OBJS-$(CONFIG_VP8_CUVID_DECODER) += cuviddec.o OBJS-$(CONFIG_VP8_MEDIACODEC_DECODER) += mediacodecdec.o +OBJS-$(CONFIG_VP8_MEDIACODEC_ENCODER) += mediacodecenc.o OBJS-$(CONFIG_VP8_QSV_DECODER) += qsvdec.o OBJS-$(CONFIG_VP8_RKMPP_DECODER) += rkmppdec.o OBJS-$(CONFIG_VP8_VAAPI_ENCODER) += vaapi_encode_vp8.o diff --git a/libavcodec/allcodecs.c b/libavcodec/allcodecs.c index f583aad8602..184bb8521f0 100644 --- a/libavcodec/allcodecs.c +++ b/libavcodec/allcodecs.c @@ -881,6 +881,7 @@ extern const FFCodec ff_prores_videotoolbox_encoder; extern const FFCodec ff_vc1_cuvid_decoder; extern const FFCodec ff_vp8_cuvid_decoder; extern const FFCodec ff_vp8_mediacodec_decoder; +extern const FFCodec ff_vp8_mediacodec_encoder; extern const FFCodec ff_vp8_qsv_decoder; extern const FFCodec ff_vp8_v4l2m2m_encoder; extern const FFCodec ff_vp8_vaapi_encoder; diff --git a/libavcodec/mediacodecenc.c b/libavcodec/mediacodecenc.c index 2b7bef444ee..d23745c1c19 100644 --- a/libavcodec/mediacodecenc.c +++ b/libavcodec/mediacodecenc.c @@ -164,6 +164,9 @@ static av_cold int mediacodec_init(AVCodecContext *avctx) case AV_CODEC_ID_HEVC: codec_mime = "video/hevc"; break; + case AV_CODEC_ID_VP8: + codec_mime = "video/x-vnd.on2.vp8"; + break; case AV_CODEC_ID_VP9: codec_mime = "video/x-vnd.on2.vp9"; break; @@ -778,6 +781,34 @@ DECLARE_MEDIACODEC_ENCODER(hevc, "H.265", AV_CODEC_ID_HEVC) #endif // CONFIG_HEVC_MEDIACODEC_ENCODER +#if CONFIG_VP8_MEDIACODEC_ENCODER + +enum MediaCodecVP8Level { + VP8Level_Version0 = 0x01, + VP8Level_Version1 = 0x02, + VP8Level_Version2 = 0x04, + VP8Level_Version3 = 0x08, +}; + +static const AVOption vp8_options[] = { + COMMON_OPTION + { "level", "Specify tier and level", + OFFSET(level), AV_OPT_TYPE_INT, {.i64 = 0}, 0, INT_MAX, VE, "level" }, + { "V0", "Level Version 0", + 0, AV_OPT_TYPE_CONST, { .i64 = VP8Level_Version0 }, 0, 0, VE, "level" }, + { "V1", "Level Version 1", + 0, AV_OPT_TYPE_CONST, { .i64 = VP8Level_Version1 }, 0, 0, VE, "level" }, + { "V2", "Level Version 2", + 0, AV_OPT_TYPE_CONST, { .i64 = VP8Level_Version2 }, 0, 0, VE, "level" }, + { "V3", "Level Version 3", + 0, AV_OPT_TYPE_CONST, { .i64 = VP8Level_Version3 }, 0, 0, VE, "level" }, + { NULL, } +}; + +DECLARE_MEDIACODEC_ENCODER(vp8, "VP8", AV_CODEC_ID_VP8) + +#endif // CONFIG_VP8_MEDIACODEC_ENCODER + #if CONFIG_VP9_MEDIACODEC_ENCODER enum MediaCodecVP9Level { diff --git a/libavcodec/version.h b/libavcodec/version.h index 755c90bbc1a..7531c6c42a3 100644 --- a/libavcodec/version.h +++ b/libavcodec/version.h @@ -29,7 +29,7 @@ #include "version_major.h" -#define LIBAVCODEC_VERSION_MINOR 13 +#define LIBAVCODEC_VERSION_MINOR 14 #define LIBAVCODEC_VERSION_MICRO 100 #define LIBAVCODEC_VERSION_INT AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \ From d4c48ee7f398c58f22844513a898cf2792961c99 Mon Sep 17 00:00:00 2001 From: Leo Izen Date: Tue, 16 May 2023 10:41:26 -0400 Subject: [PATCH 1045/2172] fate/jpg: add RGB mjpeg fate tests Adds FATE tests for RGB jpegs to test commit 0b352e350e773673f11ea380f3507923c70e1175. --- tests/fate/image.mak | 11 +++++++++++ tests/ref/fate/jpg-rgb-1 | 6 ++++++ tests/ref/fate/jpg-rgb-2 | 6 ++++++ tests/ref/fate/jpg-rgb-3 | 6 ++++++ tests/ref/fate/jpg-rgb-4 | 6 ++++++ tests/ref/fate/jpg-rgb-5 | 6 ++++++ 6 files changed, 41 insertions(+) create mode 100644 tests/ref/fate/jpg-rgb-1 create mode 100644 tests/ref/fate/jpg-rgb-2 create mode 100644 tests/ref/fate/jpg-rgb-3 create mode 100644 tests/ref/fate/jpg-rgb-4 create mode 100644 tests/ref/fate/jpg-rgb-5 diff --git a/tests/fate/image.mak b/tests/fate/image.mak index 93bc715ca3c..400199c28a5 100644 --- a/tests/fate/image.mak +++ b/tests/fate/image.mak @@ -346,6 +346,17 @@ fate-jpg-rgb-progressive: CMD = framecrc -idct simple -i $(TARGET_SAMPLES)/jpg/g FATE_JPG += fate-jpg-rgb-221 fate-jpg-rgb-221: CMD = framecrc -idct simple -i $(TARGET_SAMPLES)/jpg/george-insect-rgb-xyb.jpg +FATE_JPG += fate-jpg-rgb-1 +fate-jpg-rgb-1: CMD = framecrc -idct simple -i $(TARGET_SAMPLES)/jpg/jpg-8930-1.jpg +FATE_JPG += fate-jpg-rgb-2 +fate-jpg-rgb-2: CMD = framecrc -idct simple -i $(TARGET_SAMPLES)/jpg/jpg-8930-2.jpg +FATE_JPG += fate-jpg-rgb-3 +fate-jpg-rgb-3: CMD = framecrc -idct simple -i $(TARGET_SAMPLES)/jpg/jpg-8930-3.jpg +FATE_JPG += fate-jpg-rgb-4 +fate-jpg-rgb-4: CMD = framecrc -idct simple -i $(TARGET_SAMPLES)/jpg/jpg-8930-4.jpg +FATE_JPG += fate-jpg-rgb-5 +fate-jpg-rgb-5: CMD = framecrc -idct simple -i $(TARGET_SAMPLES)/jpg/jpg-8930-5.jpg + FATE_JPG_TRANSCODE-$(call TRANSCODE, MJPEG, MJPEG IMAGE_JPEG_PIPE, IMAGE_PNG_PIPE_DEMUXER PNG_DECODER SCALE_FILTER) += fate-jpg-icc fate-jpg-icc: CMD = transcode png_pipe $(TARGET_SAMPLES)/png1/lena-int_rgb24.png mjpeg "-vf scale" "" "-show_frames" diff --git a/tests/ref/fate/jpg-rgb-1 b/tests/ref/fate/jpg-rgb-1 new file mode 100644 index 00000000000..4282f73bbd7 --- /dev/null +++ b/tests/ref/fate/jpg-rgb-1 @@ -0,0 +1,6 @@ +#tb 0: 1/25 +#media_type 0: video +#codec_id 0: rawvideo +#dimensions 0: 64x64 +#sar 0: 1/1 +0, 0, 0, 1, 12288, 0x7d04bd46 diff --git a/tests/ref/fate/jpg-rgb-2 b/tests/ref/fate/jpg-rgb-2 new file mode 100644 index 00000000000..88507f5a2d6 --- /dev/null +++ b/tests/ref/fate/jpg-rgb-2 @@ -0,0 +1,6 @@ +#tb 0: 1/25 +#media_type 0: video +#codec_id 0: rawvideo +#dimensions 0: 64x64 +#sar 0: 0/1 +0, 0, 0, 1, 12288, 0xa4986a3d diff --git a/tests/ref/fate/jpg-rgb-3 b/tests/ref/fate/jpg-rgb-3 new file mode 100644 index 00000000000..6125ed34f2e --- /dev/null +++ b/tests/ref/fate/jpg-rgb-3 @@ -0,0 +1,6 @@ +#tb 0: 1/25 +#media_type 0: video +#codec_id 0: rawvideo +#dimensions 0: 64x64 +#sar 0: 1/1 +0, 0, 0, 1, 12288, 0xfdf5876c diff --git a/tests/ref/fate/jpg-rgb-4 b/tests/ref/fate/jpg-rgb-4 new file mode 100644 index 00000000000..2a5938280c1 --- /dev/null +++ b/tests/ref/fate/jpg-rgb-4 @@ -0,0 +1,6 @@ +#tb 0: 1/25 +#media_type 0: video +#codec_id 0: rawvideo +#dimensions 0: 64x64 +#sar 0: 0/1 +0, 0, 0, 1, 12288, 0x06d7603d diff --git a/tests/ref/fate/jpg-rgb-5 b/tests/ref/fate/jpg-rgb-5 new file mode 100644 index 00000000000..aab650ca858 --- /dev/null +++ b/tests/ref/fate/jpg-rgb-5 @@ -0,0 +1,6 @@ +#tb 0: 1/25 +#media_type 0: video +#codec_id 0: rawvideo +#dimensions 0: 64x64 +#sar 0: 1/1 +0, 0, 0, 1, 8192, 0xcd87b5c6 From aa6eeb29cb397cb0de05b65b3d0303045fde6fe5 Mon Sep 17 00:00:00 2001 From: Tobias Rapp Date: Wed, 17 May 2023 11:43:47 +0200 Subject: [PATCH 1046/2172] doc/ffmpeg: Extend documentation for sws_flags option Clarify that -sws_flags are only applied to simple filtergraphs as a default, not complex filtergraphs. Add a reference to the scaler options. --- doc/ffmpeg.texi | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/doc/ffmpeg.texi b/doc/ffmpeg.texi index a12700e2f33..c0fa90f3817 100644 --- a/doc/ffmpeg.texi +++ b/doc/ffmpeg.texi @@ -1023,7 +1023,12 @@ If @var{pix_fmt} is a single @code{+}, ffmpeg selects the same pixel format as the input (or graph output) and automatic conversions are disabled. @item -sws_flags @var{flags} (@emph{input/output}) -Set SwScaler flags. +Set default flags for the libswscale library. These flags are used by +automatically inserted @code{scale} filters and those within simple +filtergraphs, if not overridden within the filtergraph definition. + +See the @ref{scaler_options,,ffmpeg-scaler manual,ffmpeg-scaler} for a list +of scaler options. @item -rc_override[:@var{stream_specifier}] @var{override} (@emph{output,per-stream}) Rate control override for specific intervals, formatted as "int,int,int" From bee912cb63d9e391818eaed698e6cc6b97b440f1 Mon Sep 17 00:00:00 2001 From: Mark Thompson Date: Tue, 24 Jan 2023 22:46:20 +0000 Subject: [PATCH 1047/2172] cbs_av1: Add tracing headers for metadata types Make it a little easier to interpret metadata in trace output. --- libavcodec/cbs_av1_syntax_template.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/libavcodec/cbs_av1_syntax_template.c b/libavcodec/cbs_av1_syntax_template.c index 7d160474546..67a0dddd705 100644 --- a/libavcodec/cbs_av1_syntax_template.c +++ b/libavcodec/cbs_av1_syntax_template.c @@ -1843,6 +1843,8 @@ static int FUNC(metadata_hdr_cll)(CodedBitstreamContext *ctx, RWContext *rw, { int err; + HEADER("HDR CLL Metadata"); + fb(16, max_cll); fb(16, max_fall); @@ -1854,6 +1856,8 @@ static int FUNC(metadata_hdr_mdcv)(CodedBitstreamContext *ctx, RWContext *rw, { int err, i; + HEADER("HDR MDCV Metadata"); + for (i = 0; i < 3; i++) { fbs(16, primary_chromaticity_x[i], 1, i); fbs(16, primary_chromaticity_y[i], 1, i); @@ -1920,6 +1924,8 @@ static int FUNC(metadata_scalability)(CodedBitstreamContext *ctx, RWContext *rw, { int err; + HEADER("Scalability Metadata"); + fb(8, scalability_mode_idc); if (current->scalability_mode_idc == AV1_SCALABILITY_SS) @@ -1934,6 +1940,8 @@ static int FUNC(metadata_itut_t35)(CodedBitstreamContext *ctx, RWContext *rw, int err; size_t i; + HEADER("ITU-T T.35 Metadata"); + fb(8, itu_t_t35_country_code); if (current->itu_t_t35_country_code == 0xff) fb(8, itu_t_t35_country_code_extension_byte); @@ -1961,6 +1969,8 @@ static int FUNC(metadata_timecode)(CodedBitstreamContext *ctx, RWContext *rw, { int err; + HEADER("Timecode Metadata"); + fb(5, counting_type); flag(full_timestamp_flag); flag(discontinuity_flag); From dce6cf2c368edae76cd78f3cbfedb8187c3cb4b7 Mon Sep 17 00:00:00 2001 From: Mark Thompson Date: Tue, 24 Jan 2023 22:46:21 +0000 Subject: [PATCH 1048/2172] cbs_av1: Don't reject unknown metadata Accept it and pass it through unchanged. The standard requires that decoders ignore unknown metadata, and indeed this is tested by some of the Argon coverage streams. --- libavcodec/cbs_av1.c | 7 +++++++ libavcodec/cbs_av1.h | 7 +++++++ libavcodec/cbs_av1_syntax_template.c | 26 ++++++++++++++++++++++++-- 3 files changed, 38 insertions(+), 2 deletions(-) diff --git a/libavcodec/cbs_av1.c b/libavcodec/cbs_av1.c index 45e1288a519..8788fee0990 100644 --- a/libavcodec/cbs_av1.c +++ b/libavcodec/cbs_av1.c @@ -1306,9 +1306,16 @@ static void cbs_av1_free_metadata(void *unit, uint8_t *content) md = &obu->obu.metadata; switch (md->metadata_type) { + case AV1_METADATA_TYPE_HDR_CLL: + case AV1_METADATA_TYPE_HDR_MDCV: + case AV1_METADATA_TYPE_SCALABILITY: + case AV1_METADATA_TYPE_TIMECODE: + break; case AV1_METADATA_TYPE_ITUT_T35: av_buffer_unref(&md->metadata.itut_t35.payload_ref); break; + default: + av_buffer_unref(&md->metadata.unknown.payload_ref); } av_free(content); } diff --git a/libavcodec/cbs_av1.h b/libavcodec/cbs_av1.h index 1fc80dcfa05..36848d4410c 100644 --- a/libavcodec/cbs_av1.h +++ b/libavcodec/cbs_av1.h @@ -370,6 +370,12 @@ typedef struct AV1RawMetadataTimecode { uint32_t time_offset_value; } AV1RawMetadataTimecode; +typedef struct AV1RawMetadataUnknown { + uint8_t *payload; + AVBufferRef *payload_ref; + size_t payload_size; +} AV1RawMetadataUnknown; + typedef struct AV1RawMetadata { uint64_t metadata_type; union { @@ -378,6 +384,7 @@ typedef struct AV1RawMetadata { AV1RawMetadataScalability scalability; AV1RawMetadataITUTT35 itut_t35; AV1RawMetadataTimecode timecode; + AV1RawMetadataUnknown unknown; } metadata; } AV1RawMetadata; diff --git a/libavcodec/cbs_av1_syntax_template.c b/libavcodec/cbs_av1_syntax_template.c index 67a0dddd705..8f4640d1af8 100644 --- a/libavcodec/cbs_av1_syntax_template.c +++ b/libavcodec/cbs_av1_syntax_template.c @@ -2004,6 +2004,29 @@ static int FUNC(metadata_timecode)(CodedBitstreamContext *ctx, RWContext *rw, return 0; } +static int FUNC(metadata_unknown)(CodedBitstreamContext *ctx, RWContext *rw, + AV1RawMetadataUnknown *current) +{ + int err; + size_t i; + + HEADER("Unknown Metadata"); + +#ifdef READ + current->payload_size = cbs_av1_get_payload_bytes_left(rw); + + current->payload_ref = av_buffer_alloc(current->payload_size); + if (!current->payload_ref) + return AVERROR(ENOMEM); + current->payload = current->payload_ref->data; +#endif + + for (i = 0; i < current->payload_size; i++) + fbs(8, payload[i], 1, i); + + return 0; +} + static int FUNC(metadata_obu)(CodedBitstreamContext *ctx, RWContext *rw, AV1RawMetadata *current) { @@ -2028,8 +2051,7 @@ static int FUNC(metadata_obu)(CodedBitstreamContext *ctx, RWContext *rw, CHECK(FUNC(metadata_timecode)(ctx, rw, ¤t->metadata.timecode)); break; default: - // Unknown metadata type. - return AVERROR_PATCHWELCOME; + CHECK(FUNC(metadata_unknown)(ctx, rw, ¤t->metadata.unknown)); } return 0; From 9c830f4f6560227a81df7b96cad8648a1dc66f62 Mon Sep 17 00:00:00 2001 From: Mark Thompson Date: Tue, 24 Jan 2023 22:46:22 +0000 Subject: [PATCH 1049/2172] av1_parse: Remove unused getbits instance --- libavcodec/av1_parse.c | 6 +----- libavcodec/av1_parse.h | 3 --- 2 files changed, 1 insertion(+), 8 deletions(-) diff --git a/libavcodec/av1_parse.c b/libavcodec/av1_parse.c index 136ad1a58f7..948e8eb62a0 100644 --- a/libavcodec/av1_parse.c +++ b/libavcodec/av1_parse.c @@ -56,7 +56,7 @@ int ff_av1_extract_obu(AV1OBU *obu, const uint8_t *buf, int length, void *logctx int ff_av1_packet_split(AV1Packet *pkt, const uint8_t *buf, int length, void *logctx) { GetByteContext bc; - int ret, consumed; + int consumed; bytestream2_init(&bc, buf, length); pkt->nb_obus = 0; @@ -94,10 +94,6 @@ int ff_av1_packet_split(AV1Packet *pkt, const uint8_t *buf, int length, void *lo } pkt->nb_obus++; - - ret = init_get_bits(&obu->gb, obu->data, obu->size_bits); - if (ret < 0) - return ret; } return 0; diff --git a/libavcodec/av1_parse.h b/libavcodec/av1_parse.h index 1f3001d2a58..d0abd7ac7c3 100644 --- a/libavcodec/av1_parse.h +++ b/libavcodec/av1_parse.h @@ -49,9 +49,6 @@ typedef struct AV1OBU { int raw_size; const uint8_t *raw_data; - /** GetBitContext initialized to the start of the payload */ - GetBitContext gb; - int type; int temporal_id; From 84505310594e61a9eba3a4abbfc00b882db33a08 Mon Sep 17 00:00:00 2001 From: Mark Thompson Date: Tue, 24 Jan 2023 22:46:23 +0000 Subject: [PATCH 1050/2172] av1_parse: Don't reject zero-size padding OBUs Padding OBUs are not required to be nonempty. --- libavcodec/av1_parse.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/libavcodec/av1_parse.c b/libavcodec/av1_parse.c index 948e8eb62a0..061636815fd 100644 --- a/libavcodec/av1_parse.c +++ b/libavcodec/av1_parse.c @@ -88,7 +88,9 @@ int ff_av1_packet_split(AV1Packet *pkt, const uint8_t *buf, int length, void *lo obu->size_bits = get_obu_bit_length(obu->data, obu->size, obu->type); - if (obu->size_bits < 0 || (!obu->size_bits && obu->type != AV1_OBU_TEMPORAL_DELIMITER)) { + if (obu->size_bits < 0 || + (obu->size_bits == 0 && (obu->type != AV1_OBU_TEMPORAL_DELIMITER && + obu->type != AV1_OBU_PADDING))) { av_log(logctx, AV_LOG_ERROR, "Invalid OBU of type %d, skipping.\n", obu->type); continue; } From 96c30affba5123bf3ba7df0ec64fee1eded3d473 Mon Sep 17 00:00:00 2001 From: Clement Lecigne Date: Wed, 17 May 2023 19:28:54 +0200 Subject: [PATCH 1051/2172] avcodec/hevc_ps: add proper bound checks around cm_ref_layer_id in colour_mapping_table. Signed-off-by: Michael Niedermayer Signed-off-by: James Almer --- libavcodec/hevc_ps.c | 20 +++++++++++++++----- libavcodec/hevc_ps.h | 4 ++-- 2 files changed, 17 insertions(+), 7 deletions(-) diff --git a/libavcodec/hevc_ps.c b/libavcodec/hevc_ps.c index a55bced0f76..043e1bf3085 100644 --- a/libavcodec/hevc_ps.c +++ b/libavcodec/hevc_ps.c @@ -1374,10 +1374,15 @@ static void colour_mapping_octants(GetBitContext *gb, HEVCPPS *pps, int inp_dept } } -static void colour_mapping_table(GetBitContext *gb, HEVCPPS *pps) +static int colour_mapping_table(GetBitContext *gb, AVCodecContext *avctx, HEVCPPS *pps) { - pps->num_cm_ref_layers_minus1 = get_ue_golomb_long(gb); - for (int i = 0; i <= pps->num_cm_ref_layers_minus1; i++) + pps->num_cm_ref_layers = get_ue_golomb(gb) + 1; + if (pps->num_cm_ref_layers > 62) { + av_log(avctx, AV_LOG_ERROR, + "num_cm_ref_layers_minus1 shall be in the range [0, 61].\n"); + return AVERROR_INVALIDDATA; + } + for (int i = 0; i < pps->num_cm_ref_layers; i++) pps->cm_ref_layer_id[i] = get_bits(gb, 6); pps->cm_octant_depth = get_bits(gb, 2); @@ -1397,6 +1402,8 @@ static void colour_mapping_table(GetBitContext *gb, HEVCPPS *pps) } colour_mapping_octants(gb, pps, 0, 0, 0, 0, 1 << pps->cm_octant_depth); + + return 0; } static int pps_multilayer_extension(GetBitContext *gb, AVCodecContext *avctx, @@ -1439,8 +1446,11 @@ static int pps_multilayer_extension(GetBitContext *gb, AVCodecContext *avctx, } pps->colour_mapping_enabled_flag = get_bits1(gb); - if (pps->colour_mapping_enabled_flag) - colour_mapping_table(gb, pps); + if (pps->colour_mapping_enabled_flag) { + int ret = colour_mapping_table(gb, avctx, pps); + if (ret < 0) + return ret; + } return 0; } diff --git a/libavcodec/hevc_ps.h b/libavcodec/hevc_ps.h index a0437815d60..2124deb953d 100644 --- a/libavcodec/hevc_ps.h +++ b/libavcodec/hevc_ps.h @@ -332,8 +332,8 @@ typedef struct HEVCPPS { int8_t phase_hor_chroma[64]; int8_t phase_ver_chroma[64]; uint8_t colour_mapping_enabled_flag; - uint16_t num_cm_ref_layers_minus1; - uint8_t cm_ref_layer_id[63]; + uint8_t num_cm_ref_layers; + uint8_t cm_ref_layer_id[62]; uint8_t cm_octant_depth; uint8_t cm_y_part_num_log2; uint8_t luma_bit_depth_cm_input; From c48eff209ccd4ffc72a34dbbb9dd2be2fab4ded8 Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Thu, 18 May 2023 11:38:10 +0200 Subject: [PATCH 1052/2172] avcodec/ccaptions_dec: correct flushing output on EOF Prevents infinite flushing same last output. --- libavcodec/ccaption_dec.c | 1 + 1 file changed, 1 insertion(+) diff --git a/libavcodec/ccaption_dec.c b/libavcodec/ccaption_dec.c index 661a4951a43..0f5b955f15d 100644 --- a/libavcodec/ccaption_dec.c +++ b/libavcodec/ccaption_dec.c @@ -900,6 +900,7 @@ static int decode(AVCodecContext *avctx, AVSubtitle *sub, ret = ff_ass_add_rect2(sub, ctx->buffer[bidx].str, ctx->readorder++, 0, NULL, NULL, &nb_rect_allocated); if (ret < 0) return ret; + av_bprint_clear(&ctx->buffer[bidx]); sub->pts = ctx->buffer_time[1]; sub->end_display_time = av_rescale_q(ctx->buffer_time[1] - ctx->buffer_time[0], AV_TIME_BASE_Q, ms_tb); From 01d9a84ef58c2d0d89958b18420483b058ac9dd1 Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Wed, 17 May 2023 09:02:11 +0200 Subject: [PATCH 1053/2172] avfilter/avf_showspectrum: check for allocation error --- libavfilter/avf_showspectrum.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/libavfilter/avf_showspectrum.c b/libavfilter/avf_showspectrum.c index 4ce964706fa..6c3d0e8c2ba 100644 --- a/libavfilter/avf_showspectrum.c +++ b/libavfilter/avf_showspectrum.c @@ -1292,6 +1292,8 @@ static int config_output(AVFilterLink *outlink) av_realloc_f(s->combine_buffer, s->w * 4, sizeof(*s->combine_buffer)); } + if (!s->combine_buffer) + return AVERROR(ENOMEM); av_log(ctx, AV_LOG_VERBOSE, "s:%dx%d FFT window size:%d\n", s->w, s->h, s->win_size); From 63767b79a570404628b2521b83104108b7b6884c Mon Sep 17 00:00:00 2001 From: James Almer Date: Wed, 17 May 2023 22:39:57 -0300 Subject: [PATCH 1054/2172] avutil/frame: deprecate palette_has_changed Not only this is information that relies on the concept of a sequence of frames, which is completely out of place as a field in AVFrame, but there are no known or intended uses of this field. Signed-off-by: James Almer --- doc/APIchanges | 3 +++ libavcodec/8bps.c | 13 ++++++++----- libavcodec/ansi.c | 8 ++++++++ libavcodec/bethsoftvideo.c | 4 ++++ libavcodec/bfi.c | 8 ++++++++ libavcodec/bintext.c | 4 ++++ libavcodec/bmvvideo.c | 4 ++++ libavcodec/brenderpix.c | 8 ++++++++ libavcodec/c93.c | 4 ++++ libavcodec/cdgraphics.c | 4 ++++ libavcodec/cdtoons.c | 4 ++++ libavcodec/cinepak.c | 9 ++++++++- libavcodec/dds.c | 8 ++++++++ libavcodec/dfa.c | 4 ++++ libavcodec/dsicinvideo.c | 4 ++++ libavcodec/dxa.c | 4 ++++ libavcodec/flicvideo.c | 4 ++++ libavcodec/gemdec.c | 4 ++++ libavcodec/idcinvideo.c | 9 ++++++++- libavcodec/imx.c | 8 ++++++++ libavcodec/interplayvideo.c | 9 ++++++++- libavcodec/jvdec.c | 8 ++++++++ libavcodec/kmvc.c | 17 ++++++++++++++++- libavcodec/mscc.c | 4 ++++ libavcodec/msrle.c | 9 ++++++++- libavcodec/mss1.c | 4 ++++ libavcodec/msvideo1.c | 9 ++++++++- libavcodec/pafvideo.c | 4 ++++ libavcodec/pictordec.c | 4 ++++ libavcodec/psd.c | 4 ++++ libavcodec/qdrw.c | 4 ++++ libavcodec/qpeg.c | 9 ++++++++- libavcodec/qtrle.c | 9 ++++++++- libavcodec/rawdec.c | 8 ++++++++ libavcodec/rscc.c | 9 ++++++++- libavcodec/sga.c | 4 ++++ libavcodec/smacker.c | 4 ++++ libavcodec/smc.c | 9 ++++++++- libavcodec/targa.c | 4 ++++ libavcodec/tiertexseqv.c | 4 ++++ libavcodec/tmv.c | 4 ++++ libavcodec/tscc.c | 4 ++++ libavcodec/vb.c | 4 ++++ libavcodec/vqavideo.c | 4 ++++ libavcodec/yop.c | 4 ++++ libavutil/frame.c | 4 ++++ libavutil/frame.h | 3 +++ libavutil/version.h | 1 + 48 files changed, 267 insertions(+), 15 deletions(-) diff --git a/doc/APIchanges b/doc/APIchanges index d2255867a8c..770d6ffc5ef 100644 --- a/doc/APIchanges +++ b/doc/APIchanges @@ -2,6 +2,9 @@ The last version increases of all libraries were on 2023-02-09 API changes, most recent first: +2023-05-xx - xxxxxxxxxx - lavu 58 - frame.h + Deprecate AVFrame.palette_has_changed without replacement. + 2023-05-xx - xxxxxxxxxx - lavc 60 - avcodec.h Depreate AVCodecContext.ticks_per_frame in favor of AVCodecContext.framerate (encoding) and diff --git a/libavcodec/8bps.c b/libavcodec/8bps.c index 90d6c96fd1b..af98f62fad7 100644 --- a/libavcodec/8bps.c +++ b/libavcodec/8bps.c @@ -47,8 +47,6 @@ typedef struct EightBpsContext { unsigned char planes; unsigned char planemap[4]; - - uint32_t pal[256]; } EightBpsContext; static int decode_frame(AVCodecContext *avctx, AVFrame *frame, @@ -123,9 +121,14 @@ static int decode_frame(AVCodecContext *avctx, AVFrame *frame, } if (avctx->bits_per_coded_sample <= 8) { - frame->palette_has_changed = ff_copy_palette(c->pal, avpkt, avctx); - - memcpy (frame->data[1], c->pal, AVPALETTE_SIZE); +#if FF_API_PALETTE_HAS_CHANGED +FF_DISABLE_DEPRECATION_WARNINGS + frame->palette_has_changed = +#endif + ff_copy_palette(frame->data[1], avpkt, avctx); +#if FF_API_PALETTE_HAS_CHANGED +FF_ENABLE_DEPRECATION_WARNINGS +#endif } *got_frame = 1; diff --git a/libavcodec/ansi.c b/libavcodec/ansi.c index c1e31266ec3..49c3770c4c8 100644 --- a/libavcodec/ansi.c +++ b/libavcodec/ansi.c @@ -262,7 +262,11 @@ static int execute_code(AVCodecContext * avctx, int c) AV_GET_BUFFER_FLAG_REF)) < 0) return ret; s->frame->pict_type = AV_PICTURE_TYPE_I; +#if FF_API_PALETTE_HAS_CHANGED +FF_DISABLE_DEPRECATION_WARNINGS s->frame->palette_has_changed = 1; +FF_ENABLE_DEPRECATION_WARNINGS +#endif set_palette((uint32_t *)s->frame->data[1]); erase_screen(avctx); } else if (c == 'l') { @@ -371,7 +375,11 @@ static int decode_frame(AVCodecContext *avctx, AVFrame *rframe, } s->frame->pict_type = AV_PICTURE_TYPE_I; +#if FF_API_PALETTE_HAS_CHANGED +FF_DISABLE_DEPRECATION_WARNINGS s->frame->palette_has_changed = 1; +FF_ENABLE_DEPRECATION_WARNINGS +#endif set_palette((uint32_t *)s->frame->data[1]); if (!s->first_frame) { erase_screen(avctx); diff --git a/libavcodec/bethsoftvideo.c b/libavcodec/bethsoftvideo.c index e095d04fa56..6de502822b1 100644 --- a/libavcodec/bethsoftvideo.c +++ b/libavcodec/bethsoftvideo.c @@ -63,7 +63,11 @@ static int set_palette(BethsoftvidContext *ctx, GetByteContext *g) palette[a] = 0xFFU << 24 | bytestream2_get_be24u(g) * 4; palette[a] |= palette[a] >> 6 & 0x30303; } +#if FF_API_PALETTE_HAS_CHANGED +FF_DISABLE_DEPRECATION_WARNINGS ctx->frame->palette_has_changed = 1; +FF_ENABLE_DEPRECATION_WARNINGS +#endif return 0; } diff --git a/libavcodec/bfi.c b/libavcodec/bfi.c index 55429d4b7c5..901669a3a99 100644 --- a/libavcodec/bfi.c +++ b/libavcodec/bfi.c @@ -84,11 +84,19 @@ static int bfi_decode_frame(AVCodecContext *avctx, AVFrame *frame, pal++; } memcpy(bfi->pal, frame->data[1], sizeof(bfi->pal)); +#if FF_API_PALETTE_HAS_CHANGED +FF_DISABLE_DEPRECATION_WARNINGS frame->palette_has_changed = 1; +FF_ENABLE_DEPRECATION_WARNINGS +#endif } else { frame->pict_type = AV_PICTURE_TYPE_P; frame->flags &= ~AV_FRAME_FLAG_KEY; +#if FF_API_PALETTE_HAS_CHANGED +FF_DISABLE_DEPRECATION_WARNINGS frame->palette_has_changed = 0; +FF_ENABLE_DEPRECATION_WARNINGS +#endif memcpy(frame->data[1], bfi->pal, sizeof(bfi->pal)); } diff --git a/libavcodec/bintext.c b/libavcodec/bintext.c index ce814f76939..b20d6ce176e 100644 --- a/libavcodec/bintext.c +++ b/libavcodec/bintext.c @@ -157,7 +157,11 @@ static int decode_frame(AVCodecContext *avctx, AVFrame *frame, if ((ret = ff_get_buffer(avctx, s->frame, 0)) < 0) return ret; s->frame->pict_type = AV_PICTURE_TYPE_I; +#if FF_API_PALETTE_HAS_CHANGED +FF_DISABLE_DEPRECATION_WARNINGS s->frame->palette_has_changed = 1; +FF_ENABLE_DEPRECATION_WARNINGS +#endif memcpy(s->frame->data[1], s->palette, 16 * 4); if (avctx->codec_id == AV_CODEC_ID_XBIN) { diff --git a/libavcodec/bmvvideo.c b/libavcodec/bmvvideo.c index 92ce41c8363..20f07ca556f 100644 --- a/libavcodec/bmvvideo.c +++ b/libavcodec/bmvvideo.c @@ -251,7 +251,11 @@ static int decode_frame(AVCodecContext *avctx, AVFrame *frame, } memcpy(frame->data[1], c->pal, AVPALETTE_SIZE); +#if FF_API_PALETTE_HAS_CHANGED +FF_DISABLE_DEPRECATION_WARNINGS frame->palette_has_changed = type & BMV_PALETTE; +FF_ENABLE_DEPRECATION_WARNINGS +#endif outptr = frame->data[0]; srcptr = c->frame; diff --git a/libavcodec/brenderpix.c b/libavcodec/brenderpix.c index 85eb55f50b1..70a3e6be2a3 100644 --- a/libavcodec/brenderpix.c +++ b/libavcodec/brenderpix.c @@ -245,7 +245,11 @@ static int pix_decode_frame(AVCodecContext *avctx, AVFrame *frame, *pal_out++ = (0xFFU << 24) | bytestream2_get_be32u(&gb); bytestream2_skip(&gb, 8); +#if FF_API_PALETTE_HAS_CHANGED +FF_DISABLE_DEPRECATION_WARNINGS frame->palette_has_changed = 1; +FF_ENABLE_DEPRECATION_WARNINGS +#endif chunk_type = bytestream2_get_be32(&gb); } else if (avctx->pix_fmt == AV_PIX_FMT_PAL8) { @@ -257,7 +261,11 @@ static int pix_decode_frame(AVCodecContext *avctx, AVFrame *frame, "Using default palette, colors might be off.\n"); memcpy(pal_out, std_pal_table, sizeof(uint32_t) * 256); +#if FF_API_PALETTE_HAS_CHANGED +FF_DISABLE_DEPRECATION_WARNINGS frame->palette_has_changed = 1; +FF_ENABLE_DEPRECATION_WARNINGS +#endif } data_len = bytestream2_get_be32(&gb); diff --git a/libavcodec/c93.c b/libavcodec/c93.c index b872f95e9b2..2a4fe459580 100644 --- a/libavcodec/c93.c +++ b/libavcodec/c93.c @@ -246,7 +246,11 @@ static int decode_frame(AVCodecContext *avctx, AVFrame *rframe, for (i = 0; i < 256; i++) { palette[i] = 0xFFU << 24 | bytestream2_get_be24(&gb); } +#if FF_API_PALETTE_HAS_CHANGED +FF_DISABLE_DEPRECATION_WARNINGS newpic->palette_has_changed = 1; +FF_ENABLE_DEPRECATION_WARNINGS +#endif } else { if (oldpic->data[1]) memcpy(newpic->data[1], oldpic->data[1], 256 * 4); diff --git a/libavcodec/cdgraphics.c b/libavcodec/cdgraphics.c index 431e99cd762..0c5022a5d68 100644 --- a/libavcodec/cdgraphics.c +++ b/libavcodec/cdgraphics.c @@ -125,7 +125,11 @@ static void cdg_load_palette(CDGraphicsContext *cc, uint8_t *data, int low) b = ((color ) & 0x000F) * 17; palette[i + array_offset] = (uint32_t)cc->alpha[i + array_offset] << 24 | r << 16 | g << 8 | b; } +#if FF_API_PALETTE_HAS_CHANGED +FF_DISABLE_DEPRECATION_WARNINGS cc->frame->palette_has_changed = 1; +FF_ENABLE_DEPRECATION_WARNINGS +#endif } static int cdg_tile_block(CDGraphicsContext *cc, uint8_t *data, int b) diff --git a/libavcodec/cdtoons.c b/libavcodec/cdtoons.c index 3ebed2267cd..94c49f0c814 100644 --- a/libavcodec/cdtoons.c +++ b/libavcodec/cdtoons.c @@ -384,7 +384,11 @@ static int cdtoons_decode_frame(AVCodecContext *avctx, AVFrame *rframe, } /* first palette entry indicates transparency */ c->pal[0] = 0; +#if FF_API_PALETTE_HAS_CHANGED +FF_DISABLE_DEPRECATION_WARNINGS c->frame->palette_has_changed = 1; +FF_ENABLE_DEPRECATION_WARNINGS +#endif } } diff --git a/libavcodec/cinepak.c b/libavcodec/cinepak.c index e91f2f1012a..2ec0ce88829 100644 --- a/libavcodec/cinepak.c +++ b/libavcodec/cinepak.c @@ -476,7 +476,14 @@ static int cinepak_decode_frame(AVCodecContext *avctx, AVFrame *rframe, return ret; if (s->palette_video) { - s->frame->palette_has_changed = ff_copy_palette(s->pal, avpkt, avctx); +#if FF_API_PALETTE_HAS_CHANGED +FF_DISABLE_DEPRECATION_WARNINGS + s->frame->palette_has_changed = +#endif + ff_copy_palette(s->pal, avpkt, avctx); +#if FF_API_PALETTE_HAS_CHANGED +FF_ENABLE_DEPRECATION_WARNINGS +#endif } if ((ret = cinepak_decode(s)) < 0) { diff --git a/libavcodec/dds.c b/libavcodec/dds.c index 670a42fbf97..31a327a579d 100644 --- a/libavcodec/dds.c +++ b/libavcodec/dds.c @@ -651,7 +651,11 @@ static int dds_decode(AVCodecContext *avctx, AVFrame *frame, ((unsigned)frame->data[1][3+i*4]<<24) ); } +#if FF_API_PALETTE_HAS_CHANGED +FF_DISABLE_DEPRECATION_WARNINGS frame->palette_has_changed = 1; +FF_ENABLE_DEPRECATION_WARNINGS +#endif if (bytestream2_get_bytes_left(gbc) < frame->height * frame->width / 2) { av_log(avctx, AV_LOG_ERROR, "Buffer is too small (%d < %d).\n", @@ -682,7 +686,11 @@ static int dds_decode(AVCodecContext *avctx, AVFrame *frame, ((unsigned)frame->data[1][3+i*4]<<24) ); +#if FF_API_PALETTE_HAS_CHANGED +FF_DISABLE_DEPRECATION_WARNINGS frame->palette_has_changed = 1; +FF_ENABLE_DEPRECATION_WARNINGS +#endif } if (bytestream2_get_bytes_left(gbc) < frame->height * linesize) { diff --git a/libavcodec/dfa.c b/libavcodec/dfa.c index 114c803f32e..9114feb0b3a 100644 --- a/libavcodec/dfa.c +++ b/libavcodec/dfa.c @@ -367,7 +367,11 @@ static int dfa_decode_frame(AVCodecContext *avctx, AVFrame *frame, s->pal[i] = bytestream2_get_be24(&gb) << 2; s->pal[i] |= 0xFFU << 24 | (s->pal[i] >> 6) & 0x30303; } +#if FF_API_PALETTE_HAS_CHANGED +FF_DISABLE_DEPRECATION_WARNINGS frame->palette_has_changed = 1; +FF_ENABLE_DEPRECATION_WARNINGS +#endif } else if (chunk_type <= 9) { if (decoder[chunk_type - 2](&gb, s->frame_buf, avctx->width, avctx->height)) { av_log(avctx, AV_LOG_ERROR, "Error decoding %s chunk\n", diff --git a/libavcodec/dsicinvideo.c b/libavcodec/dsicinvideo.c index 222044d125a..000d79e169e 100644 --- a/libavcodec/dsicinvideo.c +++ b/libavcodec/dsicinvideo.c @@ -293,7 +293,11 @@ static int cinvideo_decode_frame(AVCodecContext *avctx, AVFrame *rframe, return res; memcpy(cin->frame->data[1], cin->palette, sizeof(cin->palette)); +#if FF_API_PALETTE_HAS_CHANGED +FF_DISABLE_DEPRECATION_WARNINGS cin->frame->palette_has_changed = 1; +FF_ENABLE_DEPRECATION_WARNINGS +#endif for (y = 0; y < cin->avctx->height; ++y) memcpy(cin->frame->data[0] + (cin->avctx->height - 1 - y) * cin->frame->linesize[0], cin->bitmap_table[CIN_CUR_BMP] + y * cin->avctx->width, diff --git a/libavcodec/dxa.c b/libavcodec/dxa.c index ecb48c9d3f0..d903b7ecd46 100644 --- a/libavcodec/dxa.c +++ b/libavcodec/dxa.c @@ -230,7 +230,11 @@ static int decode_frame(AVCodecContext *avctx, AVFrame *frame, if ((ret = ff_get_buffer(avctx, frame, AV_GET_BUFFER_FLAG_REF)) < 0) return ret; memcpy(frame->data[1], c->pal, AVPALETTE_SIZE); +#if FF_API_PALETTE_HAS_CHANGED +FF_DISABLE_DEPRECATION_WARNINGS frame->palette_has_changed = pc; +FF_ENABLE_DEPRECATION_WARNINGS +#endif outptr = frame->data[0]; srcptr = c->decomp_buf; diff --git a/libavcodec/flicvideo.c b/libavcodec/flicvideo.c index 228f6527752..e4b334e10fd 100644 --- a/libavcodec/flicvideo.c +++ b/libavcodec/flicvideo.c @@ -473,7 +473,11 @@ static int flic_decode_frame_8BPP(AVCodecContext *avctx, /* make the palette available on the way out */ memcpy(s->frame->data[1], s->palette, AVPALETTE_SIZE); if (s->new_palette) { +#if FF_API_PALETTE_HAS_CHANGED +FF_DISABLE_DEPRECATION_WARNINGS s->frame->palette_has_changed = 1; +FF_ENABLE_DEPRECATION_WARNINGS +#endif s->new_palette = 0; } diff --git a/libavcodec/gemdec.c b/libavcodec/gemdec.c index 73e907c0413..9e2a50c7661 100644 --- a/libavcodec/gemdec.c +++ b/libavcodec/gemdec.c @@ -181,7 +181,11 @@ static int gem_decode_frame(AVCodecContext *avctx, AVFrame *p, p->pict_type = AV_PICTURE_TYPE_I; p->flags |= AV_FRAME_FLAG_KEY; +#if FF_API_PALETTE_HAS_CHANGED +FF_DISABLE_DEPRECATION_WARNINGS p->palette_has_changed = 1; +FF_ENABLE_DEPRECATION_WARNINGS +#endif palette = (uint32_t *)p->data[1]; if (tag == AV_RB32("STTT")) { diff --git a/libavcodec/idcinvideo.c b/libavcodec/idcinvideo.c index f6b8b3cd697..d9e46335480 100644 --- a/libavcodec/idcinvideo.c +++ b/libavcodec/idcinvideo.c @@ -224,7 +224,14 @@ static int idcin_decode_frame(AVCodecContext *avctx, AVFrame *frame, if (idcin_decode_vlcs(s, frame)) return AVERROR_INVALIDDATA; - frame->palette_has_changed = ff_copy_palette(s->pal, avpkt, avctx); +#if FF_API_PALETTE_HAS_CHANGED +FF_DISABLE_DEPRECATION_WARNINGS + frame->palette_has_changed = +#endif + ff_copy_palette(s->pal, avpkt, avctx); +#if FF_API_PALETTE_HAS_CHANGED +FF_ENABLE_DEPRECATION_WARNINGS +#endif /* make the palette available on the way out */ memcpy(frame->data[1], s->pal, AVPALETTE_SIZE); diff --git a/libavcodec/imx.c b/libavcodec/imx.c index 4ae68eb93c8..0d9d9b5bb95 100644 --- a/libavcodec/imx.c +++ b/libavcodec/imx.c @@ -58,11 +58,19 @@ static int imx_decode_frame(AVCodecContext *avctx, AVFrame *rframe, return ret; if (ff_copy_palette(imx->pal, avpkt, avctx)) { +#if FF_API_PALETTE_HAS_CHANGED +FF_DISABLE_DEPRECATION_WARNINGS frame->palette_has_changed = 1; +FF_ENABLE_DEPRECATION_WARNINGS +#endif frame->flags |= AV_FRAME_FLAG_KEY; } else { frame->flags &= ~AV_FRAME_FLAG_KEY; +#if FF_API_PALETTE_HAS_CHANGED +FF_DISABLE_DEPRECATION_WARNINGS frame->palette_has_changed = 0; +FF_ENABLE_DEPRECATION_WARNINGS +#endif } bytestream2_init(&gb, avpkt->data, avpkt->size); diff --git a/libavcodec/interplayvideo.c b/libavcodec/interplayvideo.c index 1a3461bf109..1f0414bbaff 100644 --- a/libavcodec/interplayvideo.c +++ b/libavcodec/interplayvideo.c @@ -1315,7 +1315,14 @@ static int ipvideo_decode_frame(AVCodecContext *avctx, AVFrame *frame, return ret; if (!s->is_16bpp) { - frame->palette_has_changed = ff_copy_palette(s->pal, avpkt, avctx); +#if FF_API_PALETTE_HAS_CHANGED +FF_DISABLE_DEPRECATION_WARNINGS + frame->palette_has_changed = +#endif + ff_copy_palette(s->pal, avpkt, avctx); +#if FF_API_PALETTE_HAS_CHANGED +FF_ENABLE_DEPRECATION_WARNINGS +#endif } switch (frame_format) { diff --git a/libavcodec/jvdec.c b/libavcodec/jvdec.c index f44b21af118..13ede9068a8 100644 --- a/libavcodec/jvdec.c +++ b/libavcodec/jvdec.c @@ -37,7 +37,9 @@ typedef struct JvContext { BlockDSPContext bdsp; AVFrame *frame; uint32_t palette[AVPALETTE_COUNT]; +#if FF_API_PALETTE_HAS_CHANGED int palette_has_changed; +#endif } JvContext; static av_cold int decode_init(AVCodecContext *avctx) @@ -207,14 +209,20 @@ static int decode_frame(AVCodecContext *avctx, AVFrame *rframe, s->palette[i] = 0xFFU << 24 | pal << 2 | ((pal >> 4) & 0x30303); buf += 3; } +#if FF_API_PALETTE_HAS_CHANGED s->palette_has_changed = 1; +#endif } if (video_size) { s->frame->flags |= AV_FRAME_FLAG_KEY; s->frame->pict_type = AV_PICTURE_TYPE_I; +#if FF_API_PALETTE_HAS_CHANGED +FF_DISABLE_DEPRECATION_WARNINGS s->frame->palette_has_changed = s->palette_has_changed; s->palette_has_changed = 0; +FF_ENABLE_DEPRECATION_WARNINGS +#endif memcpy(s->frame->data[1], s->palette, AVPALETTE_SIZE); if ((ret = av_frame_ref(rframe, s->frame)) < 0) diff --git a/libavcodec/kmvc.c b/libavcodec/kmvc.c index de01f6b75be..83aba4b2528 100644 --- a/libavcodec/kmvc.c +++ b/libavcodec/kmvc.c @@ -273,7 +273,14 @@ static int decode_frame(AVCodecContext * avctx, AVFrame *frame, if ((ret = ff_get_buffer(avctx, frame, 0)) < 0) return ret; - frame->palette_has_changed = ff_copy_palette(ctx->pal, avpkt, avctx); +#if FF_API_PALETTE_HAS_CHANGED +FF_DISABLE_DEPRECATION_WARNINGS + frame->palette_has_changed = +#endif + ff_copy_palette(ctx->pal, avpkt, avctx); +#if FF_API_PALETTE_HAS_CHANGED +FF_ENABLE_DEPRECATION_WARNINGS +#endif header = bytestream2_get_byte(&ctx->g); @@ -296,7 +303,11 @@ static int decode_frame(AVCodecContext * avctx, AVFrame *frame, } if (header & KMVC_PALETTE) { +#if FF_API_PALETTE_HAS_CHANGED +FF_DISABLE_DEPRECATION_WARNINGS frame->palette_has_changed = 1; +FF_ENABLE_DEPRECATION_WARNINGS +#endif // palette starts from index 1 and has 127 entries for (i = 1; i <= ctx->palsize; i++) { ctx->pal[i] = 0xFFU << 24 | bytestream2_get_be24(&ctx->g); @@ -305,7 +316,11 @@ static int decode_frame(AVCodecContext * avctx, AVFrame *frame, if (ctx->setpal) { ctx->setpal = 0; +#if FF_API_PALETTE_HAS_CHANGED +FF_DISABLE_DEPRECATION_WARNINGS frame->palette_has_changed = 1; +FF_ENABLE_DEPRECATION_WARNINGS +#endif } /* make the palette available on the way out */ diff --git a/libavcodec/mscc.c b/libavcodec/mscc.c index 18446644777..d1d23e67514 100644 --- a/libavcodec/mscc.c +++ b/libavcodec/mscc.c @@ -150,7 +150,11 @@ static int decode_frame(AVCodecContext *avctx, AVFrame *frame, const uint8_t *pal = av_packet_get_side_data(avpkt, AV_PKT_DATA_PALETTE, &size); if (pal && size == AVPALETTE_SIZE) { +#if FF_API_PALETTE_HAS_CHANGED +FF_DISABLE_DEPRECATION_WARNINGS frame->palette_has_changed = 1; +FF_ENABLE_DEPRECATION_WARNINGS +#endif for (j = 0; j < 256; j++) s->pal[j] = 0xFF000000 | AV_RL32(pal + j * 4); } else if (pal) { diff --git a/libavcodec/msrle.c b/libavcodec/msrle.c index b6fa7f7abb9..51e843e4a69 100644 --- a/libavcodec/msrle.c +++ b/libavcodec/msrle.c @@ -95,7 +95,14 @@ static int msrle_decode_frame(AVCodecContext *avctx, AVFrame *rframe, return ret; if (avctx->bits_per_coded_sample > 1 && avctx->bits_per_coded_sample <= 8) { - s->frame->palette_has_changed = ff_copy_palette(s->pal, avpkt, avctx); +#if FF_API_PALETTE_HAS_CHANGED +FF_DISABLE_DEPRECATION_WARNINGS + s->frame->palette_has_changed = +#endif + ff_copy_palette(s->pal, avpkt, avctx); +#if FF_API_PALETTE_HAS_CHANGED +FF_ENABLE_DEPRECATION_WARNINGS +#endif /* make the palette available */ memcpy(s->frame->data[1], s->pal, AVPALETTE_SIZE); diff --git a/libavcodec/mss1.c b/libavcodec/mss1.c index dc06a9e2361..fb5fc34ea14 100644 --- a/libavcodec/mss1.c +++ b/libavcodec/mss1.c @@ -178,7 +178,11 @@ static int mss1_decode_frame(AVCodecContext *avctx, AVFrame *rframe, if (c->corrupted) return AVERROR_INVALIDDATA; memcpy(ctx->pic->data[1], c->pal, AVPALETTE_SIZE); +#if FF_API_PALETTE_HAS_CHANGED +FF_DISABLE_DEPRECATION_WARNINGS ctx->pic->palette_has_changed = pal_changed; +FF_ENABLE_DEPRECATION_WARNINGS +#endif if ((ret = av_frame_ref(rframe, ctx->pic)) < 0) return ret; diff --git a/libavcodec/msvideo1.c b/libavcodec/msvideo1.c index 9903ff36a7f..ca4583d8415 100644 --- a/libavcodec/msvideo1.c +++ b/libavcodec/msvideo1.c @@ -312,7 +312,14 @@ static int msvideo1_decode_frame(AVCodecContext *avctx, AVFrame *rframe, return ret; if (s->mode_8bit) { - s->frame->palette_has_changed = ff_copy_palette(s->pal, avpkt, avctx); +#if FF_API_PALETTE_HAS_CHANGED +FF_DISABLE_DEPRECATION_WARNINGS + s->frame->palette_has_changed = +#endif + ff_copy_palette(s->pal, avpkt, avctx); +#if FF_API_PALETTE_HAS_CHANGED +FF_ENABLE_DEPRECATION_WARNINGS +#endif } if (s->mode_8bit) diff --git a/libavcodec/pafvideo.c b/libavcodec/pafvideo.c index fa914ccbaa9..14eb42435a3 100644 --- a/libavcodec/pafvideo.c +++ b/libavcodec/pafvideo.c @@ -327,7 +327,11 @@ static int paf_video_decode(AVCodecContext *avctx, AVFrame *rframe, b = b << 2 | b >> 4; *out++ = (0xFFU << 24) | (r << 16) | (g << 8) | b; } +#if FF_API_PALETTE_HAS_CHANGED +FF_DISABLE_DEPRECATION_WARNINGS c->pic->palette_has_changed = 1; +FF_ENABLE_DEPRECATION_WARNINGS +#endif } c->dirty[c->current_frame] = 1; diff --git a/libavcodec/pictordec.c b/libavcodec/pictordec.c index aef3d3de76f..5aaa725bd3e 100644 --- a/libavcodec/pictordec.c +++ b/libavcodec/pictordec.c @@ -191,7 +191,11 @@ static int decode_frame(AVCodecContext *avctx, AVFrame *frame, return ret; memset(frame->data[0], 0, s->height * frame->linesize[0]); frame->pict_type = AV_PICTURE_TYPE_I; +#if FF_API_PALETTE_HAS_CHANGED +FF_DISABLE_DEPRECATION_WARNINGS frame->palette_has_changed = 1; +FF_ENABLE_DEPRECATION_WARNINGS +#endif pos_after_pal = bytestream2_tell(&s->g) + esize; palette = (uint32_t*)frame->data[1]; diff --git a/libavcodec/psd.c b/libavcodec/psd.c index ee96bd12376..d3456e6b3dc 100644 --- a/libavcodec/psd.c +++ b/libavcodec/psd.c @@ -532,7 +532,11 @@ static int decode_frame(AVCodecContext *avctx, AVFrame *picture, } if (s->color_mode == PSD_INDEXED) { +#if FF_API_PALETTE_HAS_CHANGED +FF_DISABLE_DEPRECATION_WARNINGS picture->palette_has_changed = 1; +FF_ENABLE_DEPRECATION_WARNINGS +#endif memcpy(picture->data[1], s->palette, AVPALETTE_SIZE); } diff --git a/libavcodec/qdrw.c b/libavcodec/qdrw.c index 65e7269e5d8..21a53b8e728 100644 --- a/libavcodec/qdrw.c +++ b/libavcodec/qdrw.c @@ -384,7 +384,11 @@ static int decode_frame(AVCodecContext *avctx, AVFrame *p, ret = parse_palette(avctx, &gbc, (uint32_t *)p->data[1], colors, flags & 0x8000); if (ret < 0) return ret; +#if FF_API_PALETTE_HAS_CHANGED +FF_DISABLE_DEPRECATION_WARNINGS p->palette_has_changed = 1; +FF_ENABLE_DEPRECATION_WARNINGS +#endif /* jump to image data */ bytestream2_skip(&gbc, 18); diff --git a/libavcodec/qpeg.c b/libavcodec/qpeg.c index 43a24fab081..1f76ebc5a1f 100644 --- a/libavcodec/qpeg.c +++ b/libavcodec/qpeg.c @@ -297,7 +297,14 @@ static int decode_frame(AVCodecContext *avctx, AVFrame *p, } /* make the palette available on the way out */ - p->palette_has_changed = ff_copy_palette(a->pal, avpkt, avctx); +#if FF_API_PALETTE_HAS_CHANGED +FF_DISABLE_DEPRECATION_WARNINGS + p->palette_has_changed = +#endif + ff_copy_palette(a->pal, avpkt, avctx); +#if FF_API_PALETTE_HAS_CHANGED +FF_ENABLE_DEPRECATION_WARNINGS +#endif memcpy(p->data[1], a->pal, AVPALETTE_SIZE); av_frame_unref(ref); diff --git a/libavcodec/qtrle.c b/libavcodec/qtrle.c index 5cb18c86c2b..9b016d7e83e 100644 --- a/libavcodec/qtrle.c +++ b/libavcodec/qtrle.c @@ -537,7 +537,14 @@ static int qtrle_decode_frame(AVCodecContext *avctx, AVFrame *rframe, } if(has_palette) { - s->frame->palette_has_changed = ff_copy_palette(s->pal, avpkt, avctx); +#if FF_API_PALETTE_HAS_CHANGED +FF_DISABLE_DEPRECATION_WARNINGS + s->frame->palette_has_changed = +#endif + ff_copy_palette(s->pal, avpkt, avctx); +#if FF_API_PALETTE_HAS_CHANGED +FF_ENABLE_DEPRECATION_WARNINGS +#endif /* make the palette available on the way out */ memcpy(s->frame->data[1], s->pal, AVPALETTE_SIZE); diff --git a/libavcodec/rawdec.c b/libavcodec/rawdec.c index baca16c7439..8e9358f95d1 100644 --- a/libavcodec/rawdec.c +++ b/libavcodec/rawdec.c @@ -373,7 +373,11 @@ static int raw_decode(AVCodecContext *avctx, AVFrame *frame, } if (ff_copy_palette(context->palette->data, avpkt, avctx)) { +#if FF_API_PALETTE_HAS_CHANGED +FF_DISABLE_DEPRECATION_WARNINGS frame->palette_has_changed = 1; +FF_ENABLE_DEPRECATION_WARNINGS +#endif } else if (context->is_nut_pal8) { int vid_size = avctx->width * avctx->height; int pal_size = avpkt->size - vid_size; @@ -381,7 +385,11 @@ static int raw_decode(AVCodecContext *avctx, AVFrame *frame, if (avpkt->size > vid_size && pal_size <= AVPALETTE_SIZE) { const uint8_t *pal = avpkt->data + vid_size; memcpy(context->palette->data, pal, pal_size); +#if FF_API_PALETTE_HAS_CHANGED +FF_DISABLE_DEPRECATION_WARNINGS frame->palette_has_changed = 1; +FF_ENABLE_DEPRECATION_WARNINGS +#endif } } } diff --git a/libavcodec/rscc.c b/libavcodec/rscc.c index 2ae88999779..ace9aeeb405 100644 --- a/libavcodec/rscc.c +++ b/libavcodec/rscc.c @@ -346,7 +346,14 @@ static int rscc_decode_frame(AVCodecContext *avctx, AVFrame *frame, /* Palette handling */ if (avctx->pix_fmt == AV_PIX_FMT_PAL8) { - frame->palette_has_changed = ff_copy_palette(ctx->palette, avpkt, avctx); +#if FF_API_PALETTE_HAS_CHANGED +FF_DISABLE_DEPRECATION_WARNINGS + frame->palette_has_changed = +#endif + ff_copy_palette(ctx->palette, avpkt, avctx); +#if FF_API_PALETTE_HAS_CHANGED +FF_ENABLE_DEPRECATION_WARNINGS +#endif memcpy(frame->data[1], ctx->palette, AVPALETTE_SIZE); } // We only return a picture when enough of it is undamaged, this avoids copying nearly broken frames around diff --git a/libavcodec/sga.c b/libavcodec/sga.c index 16442b40be6..eae691adad9 100644 --- a/libavcodec/sga.c +++ b/libavcodec/sga.c @@ -497,7 +497,11 @@ static int sga_decode_frame(AVCodecContext *avctx, AVFrame *frame, } memcpy(frame->data[1], s->pal, AVPALETTE_SIZE); +#if FF_API_PALETTE_HAS_CHANGED +FF_DISABLE_DEPRECATION_WARNINGS frame->palette_has_changed = 1; +FF_ENABLE_DEPRECATION_WARNINGS +#endif frame->pict_type = AV_PICTURE_TYPE_I; frame->flags |= AV_FRAME_FLAG_KEY; diff --git a/libavcodec/smacker.c b/libavcodec/smacker.c index 08841f4cce2..b98e7275f61 100644 --- a/libavcodec/smacker.c +++ b/libavcodec/smacker.c @@ -392,7 +392,11 @@ static int decode_frame(AVCodecContext *avctx, AVFrame *rframe, pal = (uint32_t*)smk->pic->data[1]; bytestream2_init(&gb2, avpkt->data, avpkt->size); flags = bytestream2_get_byteu(&gb2); +#if FF_API_PALETTE_HAS_CHANGED +FF_DISABLE_DEPRECATION_WARNINGS smk->pic->palette_has_changed = flags & 1; +FF_ENABLE_DEPRECATION_WARNINGS +#endif if (flags & 2) { smk->pic->flags |= AV_FRAME_FLAG_KEY; smk->pic->pict_type = AV_PICTURE_TYPE_I; diff --git a/libavcodec/smc.c b/libavcodec/smc.c index 2b10e74386f..3e8a89ced13 100644 --- a/libavcodec/smc.c +++ b/libavcodec/smc.c @@ -437,7 +437,14 @@ static int smc_decode_frame(AVCodecContext *avctx, AVFrame *rframe, if ((ret = ff_reget_buffer(avctx, s->frame, 0)) < 0) return ret; - s->frame->palette_has_changed = ff_copy_palette(s->pal, avpkt, avctx); +#if FF_API_PALETTE_HAS_CHANGED +FF_DISABLE_DEPRECATION_WARNINGS + s->frame->palette_has_changed = +#endif + ff_copy_palette(s->pal, avpkt, avctx); +#if FF_API_PALETTE_HAS_CHANGED +FF_ENABLE_DEPRECATION_WARNINGS +#endif bytestream2_init(&gb, buf, buf_size); ret = smc_decode_stream(s, &gb); diff --git a/libavcodec/targa.c b/libavcodec/targa.c index 07005f2be69..59fdc428d95 100644 --- a/libavcodec/targa.c +++ b/libavcodec/targa.c @@ -249,7 +249,11 @@ static int decode_frame(AVCodecContext *avctx, AVFrame *p, } break; } +#if FF_API_PALETTE_HAS_CHANGED +FF_DISABLE_DEPRECATION_WARNINGS p->palette_has_changed = 1; +FF_ENABLE_DEPRECATION_WARNINGS +#endif } } diff --git a/libavcodec/tiertexseqv.c b/libavcodec/tiertexseqv.c index 19c0671bf6b..cdc885558b8 100644 --- a/libavcodec/tiertexseqv.c +++ b/libavcodec/tiertexseqv.c @@ -182,7 +182,11 @@ static int seqvideo_decode(SeqVideoContext *seq, const unsigned char *data, int c[j] = (*data << 2) | (*data >> 4); palette[i] = 0xFFU << 24 | AV_RB24(c); } +#if FF_API_PALETTE_HAS_CHANGED +FF_DISABLE_DEPRECATION_WARNINGS seq->frame->palette_has_changed = 1; +FF_ENABLE_DEPRECATION_WARNINGS +#endif } if (flags & 2) { diff --git a/libavcodec/tmv.c b/libavcodec/tmv.c index 582b6ddd024..2a7e1a105f1 100644 --- a/libavcodec/tmv.c +++ b/libavcodec/tmv.c @@ -60,7 +60,11 @@ static int tmv_decode_frame(AVCodecContext *avctx, AVFrame *frame, frame->flags |= AV_FRAME_FLAG_KEY; dst = frame->data[0]; +#if FF_API_PALETTE_HAS_CHANGED +FF_DISABLE_DEPRECATION_WARNINGS frame->palette_has_changed = 1; +FF_ENABLE_DEPRECATION_WARNINGS +#endif memcpy(frame->data[1], ff_cga_palette, 16 * 4); memset(frame->data[1] + 16 * 4, 0, AVPALETTE_SIZE - 16 * 4); diff --git a/libavcodec/tscc.c b/libavcodec/tscc.c index 0ebe641ab1b..346d93e1f24 100644 --- a/libavcodec/tscc.c +++ b/libavcodec/tscc.c @@ -106,7 +106,11 @@ static int decode_frame(AVCodecContext *avctx, AVFrame *rframe, /* make the palette available on the way out */ if (c->avctx->pix_fmt == AV_PIX_FMT_PAL8) { +#if FF_API_PALETTE_HAS_CHANGED +FF_DISABLE_DEPRECATION_WARNINGS frame->palette_has_changed = palette_has_changed; +FF_ENABLE_DEPRECATION_WARNINGS +#endif memcpy(frame->data[1], c->pal, AVPALETTE_SIZE); } diff --git a/libavcodec/vb.c b/libavcodec/vb.c index 8b0e2164734..5744faa983f 100644 --- a/libavcodec/vb.c +++ b/libavcodec/vb.c @@ -230,7 +230,11 @@ static int decode_frame(AVCodecContext *avctx, AVFrame *frame, } memcpy(frame->data[1], c->pal, AVPALETTE_SIZE); +#if FF_API_PALETTE_HAS_CHANGED +FF_DISABLE_DEPRECATION_WARNINGS frame->palette_has_changed = flags & VB_HAS_PALETTE; +FF_ENABLE_DEPRECATION_WARNINGS +#endif outptr = frame->data[0]; srcptr = c->frame; diff --git a/libavcodec/vqavideo.c b/libavcodec/vqavideo.c index 0573696d94d..2977cf9a526 100644 --- a/libavcodec/vqavideo.c +++ b/libavcodec/vqavideo.c @@ -809,7 +809,11 @@ static int vqa_decode_frame(AVCodecContext *avctx, AVFrame *rframe, /* make the palette available on the way out */ memcpy(s->frame->data[1], s->palette, PALETTE_COUNT * 4); +#if FF_API_PALETTE_HAS_CHANGED +FF_DISABLE_DEPRECATION_WARNINGS s->frame->palette_has_changed = 1; +FF_ENABLE_DEPRECATION_WARNINGS +#endif } else if (avctx->pix_fmt == AV_PIX_FMT_RGB555LE) { if ((res = vqa_decode_frame_hicolor(s, s->frame)) < 0) return res; diff --git a/libavcodec/yop.c b/libavcodec/yop.c index 14244c942a6..1294c5cc004 100644 --- a/libavcodec/yop.c +++ b/libavcodec/yop.c @@ -232,7 +232,11 @@ static int yop_decode_frame(AVCodecContext *avctx, AVFrame *rframe, (palette[i + firstcolor] >> 6) & 0x30303; } +#if FF_API_PALETTE_HAS_CHANGED +FF_DISABLE_DEPRECATION_WARNINGS frame->palette_has_changed = 1; +FF_ENABLE_DEPRECATION_WARNINGS +#endif for (y = 0; y < avctx->height; y += 2) { for (x = 0; x < avctx->width; x += 2) { diff --git a/libavutil/frame.c b/libavutil/frame.c index 97d40208c86..b0d8eebdded 100644 --- a/libavutil/frame.c +++ b/libavutil/frame.c @@ -284,7 +284,11 @@ FF_DISABLE_DEPRECATION_WARNINGS dst->top_field_first = src->top_field_first; FF_ENABLE_DEPRECATION_WARNINGS #endif +#if FF_API_PALETTE_HAS_CHANGED +FF_DISABLE_DEPRECATION_WARNINGS dst->palette_has_changed = src->palette_has_changed; +FF_ENABLE_DEPRECATION_WARNINGS +#endif dst->sample_rate = src->sample_rate; dst->opaque = src->opaque; dst->pkt_dts = src->pkt_dts; diff --git a/libavutil/frame.h b/libavutil/frame.h index ed3f199ce16..bb634008eab 100644 --- a/libavutil/frame.h +++ b/libavutil/frame.h @@ -528,10 +528,13 @@ typedef struct AVFrame { int top_field_first; #endif +#if FF_API_PALETTE_HAS_CHANGED /** * Tell user application that palette has changed from previous frame. */ + attribute_deprecated int palette_has_changed; +#endif #if FF_API_REORDERED_OPAQUE /** diff --git a/libavutil/version.h b/libavutil/version.h index 341bcbf1888..c41c6afeac8 100644 --- a/libavutil/version.h +++ b/libavutil/version.h @@ -117,6 +117,7 @@ #define FF_API_FRAME_PKT (LIBAVUTIL_VERSION_MAJOR < 59) #define FF_API_INTERLACED_FRAME (LIBAVUTIL_VERSION_MAJOR < 59) #define FF_API_FRAME_KEY (LIBAVUTIL_VERSION_MAJOR < 59) +#define FF_API_PALETTE_HAS_CHANGED (LIBAVUTIL_VERSION_MAJOR < 59) /** * @} From 01d444c077e562fc5b8f47f9c0c5257f8fe376bb Mon Sep 17 00:00:00 2001 From: James Almer Date: Tue, 10 Aug 2021 18:59:59 -0300 Subject: [PATCH 1055/2172] avutil/frame: add av_frame_replace Signed-off-by: James Almer --- doc/APIchanges | 3 ++ libavutil/frame.c | 125 ++++++++++++++++++++++++++++++++++++++++++++ libavutil/frame.h | 13 +++++ libavutil/version.h | 2 +- 4 files changed, 142 insertions(+), 1 deletion(-) diff --git a/doc/APIchanges b/doc/APIchanges index 770d6ffc5ef..130955ef02e 100644 --- a/doc/APIchanges +++ b/doc/APIchanges @@ -2,6 +2,9 @@ The last version increases of all libraries were on 2023-02-09 API changes, most recent first: +2023-05-xx - xxxxxxxxxx - lavu 58.8.100 - frame.h + Add av_frame_replace(). + 2023-05-xx - xxxxxxxxxx - lavu 58 - frame.h Deprecate AVFrame.palette_has_changed without replacement. diff --git a/libavutil/frame.c b/libavutil/frame.c index b0d8eebdded..4a0647cc608 100644 --- a/libavutil/frame.c +++ b/libavutil/frame.c @@ -479,6 +479,131 @@ FF_ENABLE_DEPRECATION_WARNINGS return ret; } +int av_frame_replace(AVFrame *dst, const AVFrame *src) +{ + int ret = 0; + + if (dst == src) + return AVERROR(EINVAL); + + if (!src->buf[0]) { + av_frame_unref(dst); + + /* duplicate the frame data if it's not refcounted */ + if ( src->data[0] || src->data[1] + || src->data[2] || src->data[3]) + return av_frame_ref(dst, src); + + return av_frame_copy_props(dst, src); + } + + dst->format = src->format; + dst->width = src->width; + dst->height = src->height; + dst->nb_samples = src->nb_samples; +#if FF_API_OLD_CHANNEL_LAYOUT +FF_DISABLE_DEPRECATION_WARNINGS + dst->channels = src->channels; + dst->channel_layout = src->channel_layout; + if (!av_channel_layout_check(&src->ch_layout)) { + av_channel_layout_uninit(&dst->ch_layout); + if (src->channel_layout) + av_channel_layout_from_mask(&dst->ch_layout, src->channel_layout); + else { + dst->ch_layout.nb_channels = src->channels; + dst->ch_layout.order = AV_CHANNEL_ORDER_UNSPEC; + } + } else { +#endif + ret = av_channel_layout_copy(&dst->ch_layout, &src->ch_layout); + if (ret < 0) + goto fail; +#if FF_API_OLD_CHANNEL_LAYOUT + } +FF_ENABLE_DEPRECATION_WARNINGS +#endif + + wipe_side_data(dst); + av_dict_free(&dst->metadata); + ret = frame_copy_props(dst, src, 0); + if (ret < 0) + goto fail; + + /* replace the buffers */ + for (int i = 0; i < FF_ARRAY_ELEMS(src->buf); i++) { + ret = av_buffer_replace(&dst->buf[i], src->buf[i]); + if (ret < 0) + goto fail; + } + + if (src->extended_buf) { + if (dst->nb_extended_buf != src->nb_extended_buf) { + int nb_extended_buf = FFMIN(dst->nb_extended_buf, src->nb_extended_buf); + void *tmp; + + for (int i = nb_extended_buf; i < dst->nb_extended_buf; i++) + av_buffer_unref(&dst->extended_buf[i]); + + tmp = av_realloc_array(dst->extended_buf, sizeof(*dst->extended_buf), + src->nb_extended_buf); + if (!tmp) { + ret = AVERROR(ENOMEM); + goto fail; + } + dst->extended_buf = tmp; + dst->nb_extended_buf = src->nb_extended_buf; + + memset(&dst->extended_buf[nb_extended_buf], 0, + (src->nb_extended_buf - nb_extended_buf) * sizeof(*dst->extended_buf)); + } + + for (int i = 0; i < src->nb_extended_buf; i++) { + ret = av_buffer_replace(&dst->extended_buf[i], src->extended_buf[i]); + if (ret < 0) + goto fail; + } + } else if (dst->extended_buf) { + for (int i = 0; i < dst->nb_extended_buf; i++) + av_buffer_unref(&dst->extended_buf[i]); + av_freep(&dst->extended_buf); + } + + ret = av_buffer_replace(&dst->hw_frames_ctx, src->hw_frames_ctx); + if (ret < 0) + goto fail; + + if (dst->extended_data != dst->data) + av_freep(&dst->extended_data); + + if (src->extended_data != src->data) { + int ch = dst->ch_layout.nb_channels; + + if (!ch) { + ret = AVERROR(EINVAL); + goto fail; + } + + if (ch > SIZE_MAX / sizeof(*dst->extended_data)) + goto fail; + + dst->extended_data = av_memdup(src->extended_data, sizeof(*dst->extended_data) * ch); + if (!dst->extended_data) { + ret = AVERROR(ENOMEM); + goto fail; + } + } else + dst->extended_data = dst->data; + + memcpy(dst->data, src->data, sizeof(src->data)); + memcpy(dst->linesize, src->linesize, sizeof(src->linesize)); + + return 0; + +fail: + av_frame_unref(dst); + return ret; +} + AVFrame *av_frame_clone(const AVFrame *src) { AVFrame *ret = av_frame_alloc(); diff --git a/libavutil/frame.h b/libavutil/frame.h index bb634008eab..a491315f25c 100644 --- a/libavutil/frame.h +++ b/libavutil/frame.h @@ -836,6 +836,19 @@ void av_frame_free(AVFrame **frame); */ int av_frame_ref(AVFrame *dst, const AVFrame *src); +/** + * Ensure the destination frame refers to the same data described by the source + * frame, either by creating a new reference for each AVBufferRef from src if + * they differ from those in dst, by allocating new buffers and copying data if + * src is not reference counted, or by unrefencing it if src is empty. + * + * Frame properties on dst will be replaced by those from src. + * + * @return 0 on success, a negative AVERROR on error. On error, dst is + * unreferenced. + */ +int av_frame_replace(AVFrame *dst, const AVFrame *src); + /** * Create a new frame that references the same data as src. * diff --git a/libavutil/version.h b/libavutil/version.h index c41c6afeac8..177effa9a4f 100644 --- a/libavutil/version.h +++ b/libavutil/version.h @@ -79,7 +79,7 @@ */ #define LIBAVUTIL_VERSION_MAJOR 58 -#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 3fe74c901757a8d544f2f3ace3e3228dd686925f Mon Sep 17 00:00:00 2001 From: James Almer Date: Wed, 3 Aug 2022 12:36:39 -0300 Subject: [PATCH 1056/2172] avcodec/utils: add ff_thread_replace_frame() Signed-off-by: James Almer --- libavcodec/threadframe.h | 3 +++ libavcodec/utils.c | 21 +++++++++++++++++++++ 2 files changed, 24 insertions(+) diff --git a/libavcodec/threadframe.h b/libavcodec/threadframe.h index d2f93c5cd09..d581c408a5f 100644 --- a/libavcodec/threadframe.h +++ b/libavcodec/threadframe.h @@ -84,6 +84,9 @@ void ff_thread_release_ext_buffer(AVCodecContext *avctx, ThreadFrame *f); int ff_thread_ref_frame(ThreadFrame *dst, const ThreadFrame *src); +int ff_thread_replace_frame(AVCodecContext *avctx, ThreadFrame *dst, + const ThreadFrame *src); + int ff_thread_can_start_frame(AVCodecContext *avctx); #endif diff --git a/libavcodec/utils.c b/libavcodec/utils.c index ef1845954e8..a8514ba6c17 100644 --- a/libavcodec/utils.c +++ b/libavcodec/utils.c @@ -915,6 +915,27 @@ int ff_thread_ref_frame(ThreadFrame *dst, const ThreadFrame *src) return 0; } +int ff_thread_replace_frame(AVCodecContext *avctx, ThreadFrame *dst, + const ThreadFrame *src) +{ + int ret; + + dst->owner[0] = src->owner[0]; + dst->owner[1] = src->owner[1]; + + ret = av_frame_replace(dst->f, src->f); + if (ret < 0) + return ret; + + ret = av_buffer_replace(&dst->progress, src->progress); + if (ret < 0) { + ff_thread_release_ext_buffer(dst->owner[0], dst); + return ret; + } + + return 0; +} + #if !HAVE_THREADS int ff_thread_get_buffer(AVCodecContext *avctx, AVFrame *f, int flags) From 4f9799bd88afe1c04e79af8e031b3f0198a2a344 Mon Sep 17 00:00:00 2001 From: James Almer Date: Wed, 3 Aug 2022 12:43:11 -0300 Subject: [PATCH 1057/2172] avcodec/h264_picture: use ff_thread_replace_frame() Signed-off-by: James Almer --- libavcodec/h264_picture.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/libavcodec/h264_picture.c b/libavcodec/h264_picture.c index 2661ff4698e..dcaf0fdb0a2 100644 --- a/libavcodec/h264_picture.c +++ b/libavcodec/h264_picture.c @@ -154,8 +154,7 @@ int ff_h264_replace_picture(H264Context *h, H264Picture *dst, const H264Picture av_assert0(src->tf.f == src->f); dst->tf.f = dst->f; - ff_thread_release_ext_buffer(h->avctx, &dst->tf); - ret = ff_thread_ref_frame(&dst->tf, &src->tf); + ret = ff_thread_replace_frame(h->avctx, &dst->tf, &src->tf); if (ret < 0) goto fail; From 4adb6da7a6fc504a453c0d34cddcda2923b9590d Mon Sep 17 00:00:00 2001 From: James Almer Date: Thu, 18 May 2023 11:49:02 -0300 Subject: [PATCH 1058/2172] avutil/frame: remove one layer of indirection in av_frame_replace() And don't force copy side data. Signed-off-by: James Almer --- libavutil/frame.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/libavutil/frame.c b/libavutil/frame.c index 4a0647cc608..b6cee2d8869 100644 --- a/libavutil/frame.c +++ b/libavutil/frame.c @@ -494,7 +494,9 @@ int av_frame_replace(AVFrame *dst, const AVFrame *src) || src->data[2] || src->data[3]) return av_frame_ref(dst, src); - return av_frame_copy_props(dst, src); + ret = frame_copy_props(dst, src, 0); + if (ret < 0) + goto fail; } dst->format = src->format; From 386de9319e6020bd6464a9da9b763752e248e620 Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Wed, 17 May 2023 01:32:01 +0200 Subject: [PATCH 1059/2172] avfilter/f_graphmonitor: add nozeroeof mode --- libavfilter/f_graphmonitor.c | 52 ++++++++++++++++++++++++++++-------- 1 file changed, 41 insertions(+), 11 deletions(-) diff --git a/libavfilter/f_graphmonitor.c b/libavfilter/f_graphmonitor.c index d48f9fd9903..fa213d6e798 100644 --- a/libavfilter/f_graphmonitor.c +++ b/libavfilter/f_graphmonitor.c @@ -65,6 +65,7 @@ enum { MODE_FULL, MODE_COMPACT, MODE_NOZERO, + MODE_NOZEROEOF, NB_MODES }; @@ -100,6 +101,7 @@ static const AVOption graphmonitor_options[] = { { "full", NULL, 0, AV_OPT_TYPE_CONST, {.i64=MODE_FULL}, 0, 0, VF, "mode" }, { "compact", NULL, 0, AV_OPT_TYPE_CONST, {.i64=MODE_COMPACT},0, 0, VF, "mode" }, { "nozero", NULL, 0, AV_OPT_TYPE_CONST, {.i64=MODE_NOZERO}, 0, 0, VF, "mode" }, + { "nozeroeof", NULL, 0, AV_OPT_TYPE_CONST, {.i64=MODE_NOZEROEOF}, 0, 0, VF, "mode" }, { "flags", "set flags", OFFSET(flags), AV_OPT_TYPE_FLAGS, {.i64=FLAG_QUEUE}, 0, INT_MAX, VF, "flags" }, { "f", "set flags", OFFSET(flags), AV_OPT_TYPE_FLAGS, {.i64=FLAG_QUEUE}, 0, INT_MAX, VF, "flags" }, { "queue", NULL, 0, AV_OPT_TYPE_CONST, {.i64=FLAG_QUEUE}, 0, 0, VF, "flags" }, @@ -190,6 +192,25 @@ static void drawtext(AVFrame *pic, int x, int y, const char *txt, uint8_t *color } } +static int filter_have_eof(AVFilterContext *filter) +{ + for (int j = 0; j < filter->nb_inputs; j++) { + AVFilterLink *l = filter->inputs[j]; + + if (!ff_outlink_get_status(l)) + return 0; + } + + for (int j = 0; j < filter->nb_outputs; j++) { + AVFilterLink *l = filter->outputs[j]; + + if (!ff_outlink_get_status(l)) + return 0; + } + + return 1; +} + static int filter_have_queued(AVFilterContext *filter) { for (int j = 0; j < filter->nb_inputs; j++) { @@ -255,7 +276,7 @@ static int draw_items(AVFilterContext *ctx, AVFrame *out, drawtext(out, xpos, ypos, buffer, s->white); xpos += strlen(buffer) * 8; } - if ((s->flags & FLAG_QUEUE) && (s->mode != MODE_NOZERO || frames)) { + if ((s->flags & FLAG_QUEUE) && (s->mode < MODE_NOZERO || frames)) { snprintf(buffer, sizeof(buffer)-1, " | queue: "); drawtext(out, xpos, ypos, buffer, s->white); xpos += strlen(buffer) * 8; @@ -263,52 +284,52 @@ static int draw_items(AVFilterContext *ctx, AVFrame *out, drawtext(out, xpos, ypos, buffer, frames > 0 ? frames >= 10 ? frames >= 50 ? s->red : s->yellow : s->green : s->white); xpos += strlen(buffer) * 8; } - if ((s->flags & FLAG_FCIN) && (s->mode != MODE_NOZERO || l->frame_count_in)) { + if ((s->flags & FLAG_FCIN) && (s->mode < MODE_NOZERO || l->frame_count_in)) { snprintf(buffer, sizeof(buffer)-1, " | in: %"PRId64, l->frame_count_in); drawtext(out, xpos, ypos, buffer, s->white); xpos += strlen(buffer) * 8; } - if ((s->flags & FLAG_FCOUT) && (s->mode != MODE_NOZERO || l->frame_count_out)) { + if ((s->flags & FLAG_FCOUT) && (s->mode < MODE_NOZERO || l->frame_count_out)) { snprintf(buffer, sizeof(buffer)-1, " | out: %"PRId64, l->frame_count_out); drawtext(out, xpos, ypos, buffer, s->white); xpos += strlen(buffer) * 8; } - if ((s->flags & FLAG_FC_DELTA) && (s->mode != MODE_NOZERO || (l->frame_count_in - l->frame_count_out))) { + if ((s->flags & FLAG_FC_DELTA) && (s->mode < MODE_NOZERO || (l->frame_count_in - l->frame_count_out))) { snprintf(buffer, sizeof(buffer)-1, " | delta: %"PRId64, l->frame_count_in - l->frame_count_out); drawtext(out, xpos, ypos, buffer, s->white); xpos += strlen(buffer) * 8; } - if ((s->flags & FLAG_SCIN) && (s->mode != MODE_NOZERO || l->sample_count_in)) { + if ((s->flags & FLAG_SCIN) && (s->mode < MODE_NOZERO || l->sample_count_in)) { snprintf(buffer, sizeof(buffer)-1, " | sin: %"PRId64, l->sample_count_in); drawtext(out, xpos, ypos, buffer, s->white); xpos += strlen(buffer) * 8; } - if ((s->flags & FLAG_SCOUT) && (s->mode != MODE_NOZERO || l->sample_count_out)) { + if ((s->flags & FLAG_SCOUT) && (s->mode < MODE_NOZERO || l->sample_count_out)) { snprintf(buffer, sizeof(buffer)-1, " | sout: %"PRId64, l->sample_count_out); drawtext(out, xpos, ypos, buffer, s->white); xpos += strlen(buffer) * 8; } - if ((s->flags & FLAG_SC_DELTA) && (s->mode != MODE_NOZERO || (l->sample_count_in - l->sample_count_out))) { + if ((s->flags & FLAG_SC_DELTA) && (s->mode < MODE_NOZERO || (l->sample_count_in - l->sample_count_out))) { snprintf(buffer, sizeof(buffer)-1, " | sdelta: %"PRId64, l->sample_count_in - l->sample_count_out); drawtext(out, xpos, ypos, buffer, s->white); xpos += strlen(buffer) * 8; } - if ((s->flags & FLAG_PTS) && (s->mode != MODE_NOZERO || current_pts_us)) { + if ((s->flags & FLAG_PTS) && (s->mode < MODE_NOZERO || current_pts_us)) { snprintf(buffer, sizeof(buffer)-1, " | pts: %s", av_ts2str(current_pts_us)); drawtext(out, xpos, ypos, buffer, s->white); xpos += strlen(buffer) * 8; } - if ((s->flags & FLAG_PTS_DELTA) && (s->mode != MODE_NOZERO || (current_pts_us - previous_pts_us))) { + if ((s->flags & FLAG_PTS_DELTA) && (s->mode < MODE_NOZERO || (current_pts_us - previous_pts_us))) { snprintf(buffer, sizeof(buffer)-1, " | pts_delta: %s", av_ts2str(current_pts_us - previous_pts_us)); drawtext(out, xpos, ypos, buffer, s->white); xpos += strlen(buffer) * 8; } - if ((s->flags & FLAG_TIME) && (s->mode != MODE_NOZERO || current_pts_us)) { + if ((s->flags & FLAG_TIME) && (s->mode < MODE_NOZERO || current_pts_us)) { snprintf(buffer, sizeof(buffer)-1, " | time: %s", av_ts2timestr(current_pts_us, &AV_TIME_BASE_Q)); drawtext(out, xpos, ypos, buffer, s->white); xpos += strlen(buffer) * 8; } - if ((s->flags & FLAG_TIME_DELTA) && (s->mode != MODE_NOZERO || (current_pts_us - previous_pts_us))) { + if ((s->flags & FLAG_TIME_DELTA) && (s->mode < MODE_NOZERO || (current_pts_us - previous_pts_us))) { snprintf(buffer, sizeof(buffer)-1, " | time_delta: %s", av_ts2timestr(current_pts_us - previous_pts_us, &AV_TIME_BASE_Q)); drawtext(out, xpos, ypos, buffer, s->white); xpos += strlen(buffer) * 8; @@ -355,6 +376,9 @@ static int create_frame(AVFilterContext *ctx, int64_t pts) if (s->mode == MODE_COMPACT && !filter_have_queued(filter)) continue; + if (s->mode == MODE_NOZEROEOF && filter_have_eof(filter)) + continue; + xpos = 0; drawtext(out, xpos, ypos, filter->name, s->white); xpos += strlen(filter->name) * 8 + 10; @@ -367,6 +391,9 @@ static int create_frame(AVFilterContext *ctx, int64_t pts) if (s->mode == MODE_COMPACT && !frames) continue; + if (s->mode == MODE_NOZEROEOF && ff_outlink_get_status(l)) + continue; + xpos = 10; snprintf(buffer, sizeof(buffer)-1, "in%d: ", j); drawtext(out, xpos, ypos, buffer, s->white); @@ -387,6 +414,9 @@ static int create_frame(AVFilterContext *ctx, int64_t pts) if (s->mode == MODE_COMPACT && !frames) continue; + if (s->mode == MODE_NOZEROEOF && ff_outlink_get_status(l)) + continue; + xpos = 10; snprintf(buffer, sizeof(buffer)-1, "out%d: ", j); drawtext(out, xpos, ypos, buffer, s->white); From 8cdbe3abb6bf897e1931ad7eadae8a91ac065337 Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Wed, 17 May 2023 01:35:08 +0200 Subject: [PATCH 1060/2172] avfilter/f_graphmonitor: add commands support --- libavfilter/f_graphmonitor.c | 51 +++++++++++++++++++----------------- 1 file changed, 27 insertions(+), 24 deletions(-) diff --git a/libavfilter/f_graphmonitor.c b/libavfilter/f_graphmonitor.c index fa213d6e798..e5e8d23aa19 100644 --- a/libavfilter/f_graphmonitor.c +++ b/libavfilter/f_graphmonitor.c @@ -90,36 +90,37 @@ enum { #define OFFSET(x) offsetof(GraphMonitorContext, x) #define VF AV_OPT_FLAG_VIDEO_PARAM|AV_OPT_FLAG_FILTERING_PARAM +#define VFR AV_OPT_FLAG_VIDEO_PARAM|AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_RUNTIME_PARAM static const AVOption graphmonitor_options[] = { { "size", "set monitor size", OFFSET(w), AV_OPT_TYPE_IMAGE_SIZE, {.str="hd720"}, 0, 0, VF }, { "s", "set monitor size", OFFSET(w), AV_OPT_TYPE_IMAGE_SIZE, {.str="hd720"}, 0, 0, VF }, { "opacity", "set video opacity", OFFSET(opacity), AV_OPT_TYPE_FLOAT, {.dbl=.9}, 0, 1, VF }, { "o", "set video opacity", OFFSET(opacity), AV_OPT_TYPE_FLOAT, {.dbl=.9}, 0, 1, VF }, - { "mode", "set mode", OFFSET(mode), AV_OPT_TYPE_INT, {.i64=0}, 0, NB_MODES-1, VF, "mode" }, - { "m", "set mode", OFFSET(mode), AV_OPT_TYPE_INT, {.i64=0}, 0, NB_MODES-1, VF, "mode" }, - { "full", NULL, 0, AV_OPT_TYPE_CONST, {.i64=MODE_FULL}, 0, 0, VF, "mode" }, - { "compact", NULL, 0, AV_OPT_TYPE_CONST, {.i64=MODE_COMPACT},0, 0, VF, "mode" }, - { "nozero", NULL, 0, AV_OPT_TYPE_CONST, {.i64=MODE_NOZERO}, 0, 0, VF, "mode" }, - { "nozeroeof", NULL, 0, AV_OPT_TYPE_CONST, {.i64=MODE_NOZEROEOF}, 0, 0, VF, "mode" }, - { "flags", "set flags", OFFSET(flags), AV_OPT_TYPE_FLAGS, {.i64=FLAG_QUEUE}, 0, INT_MAX, VF, "flags" }, - { "f", "set flags", OFFSET(flags), AV_OPT_TYPE_FLAGS, {.i64=FLAG_QUEUE}, 0, INT_MAX, VF, "flags" }, - { "queue", NULL, 0, AV_OPT_TYPE_CONST, {.i64=FLAG_QUEUE}, 0, 0, VF, "flags" }, - { "frame_count_in", NULL, 0, AV_OPT_TYPE_CONST, {.i64=FLAG_FCOUT}, 0, 0, VF, "flags" }, - { "frame_count_out", NULL, 0, AV_OPT_TYPE_CONST, {.i64=FLAG_FCIN}, 0, 0, VF, "flags" }, - { "frame_count_delta",NULL, 0, AV_OPT_TYPE_CONST, {.i64=FLAG_FC_DELTA},0, 0, VF, "flags" }, - { "pts", NULL, 0, AV_OPT_TYPE_CONST, {.i64=FLAG_PTS}, 0, 0, VF, "flags" }, - { "pts_delta", NULL, 0, AV_OPT_TYPE_CONST, {.i64=FLAG_PTS_DELTA},0,0, VF, "flags" }, - { "time", NULL, 0, AV_OPT_TYPE_CONST, {.i64=FLAG_TIME}, 0, 0, VF, "flags" }, - { "time_delta", NULL, 0, AV_OPT_TYPE_CONST, {.i64=FLAG_TIME_DELTA},0,0,VF, "flags" }, - { "timebase", NULL, 0, AV_OPT_TYPE_CONST, {.i64=FLAG_TB}, 0, 0, VF, "flags" }, - { "format", NULL, 0, AV_OPT_TYPE_CONST, {.i64=FLAG_FMT}, 0, 0, VF, "flags" }, - { "size", NULL, 0, AV_OPT_TYPE_CONST, {.i64=FLAG_SIZE}, 0, 0, VF, "flags" }, - { "rate", NULL, 0, AV_OPT_TYPE_CONST, {.i64=FLAG_RATE}, 0, 0, VF, "flags" }, - { "eof", NULL, 0, AV_OPT_TYPE_CONST, {.i64=FLAG_EOF}, 0, 0, VF, "flags" }, - { "sample_count_in", NULL, 0, AV_OPT_TYPE_CONST, {.i64=FLAG_SCOUT}, 0, 0, VF, "flags" }, - { "sample_count_out", NULL, 0, AV_OPT_TYPE_CONST, {.i64=FLAG_SCIN}, 0, 0, VF, "flags" }, - { "sample_count_delta",NULL,0, AV_OPT_TYPE_CONST, {.i64=FLAG_SC_DELTA},0, 0, VF, "flags" }, + { "mode", "set mode", OFFSET(mode), AV_OPT_TYPE_INT, {.i64=0}, 0, NB_MODES-1, VFR, "mode" }, + { "m", "set mode", OFFSET(mode), AV_OPT_TYPE_INT, {.i64=0}, 0, NB_MODES-1, VFR, "mode" }, + { "full", NULL, 0, AV_OPT_TYPE_CONST, {.i64=MODE_FULL}, 0, 0, VFR, "mode" }, + { "compact", NULL, 0, AV_OPT_TYPE_CONST, {.i64=MODE_COMPACT},0, 0, VFR, "mode" }, + { "nozero", NULL, 0, AV_OPT_TYPE_CONST, {.i64=MODE_NOZERO}, 0, 0, VFR, "mode" }, + { "nozeroeof", NULL, 0, AV_OPT_TYPE_CONST, {.i64=MODE_NOZEROEOF}, 0, 0, VFR, "mode" }, + { "flags", "set flags", OFFSET(flags), AV_OPT_TYPE_FLAGS, {.i64=FLAG_QUEUE}, 0, INT_MAX, VFR, "flags" }, + { "f", "set flags", OFFSET(flags), AV_OPT_TYPE_FLAGS, {.i64=FLAG_QUEUE}, 0, INT_MAX, VFR, "flags" }, + { "queue", NULL, 0, AV_OPT_TYPE_CONST, {.i64=FLAG_QUEUE}, 0, 0, VFR, "flags" }, + { "frame_count_in", NULL, 0, AV_OPT_TYPE_CONST, {.i64=FLAG_FCOUT}, 0, 0, VFR, "flags" }, + { "frame_count_out", NULL, 0, AV_OPT_TYPE_CONST, {.i64=FLAG_FCIN}, 0, 0, VFR, "flags" }, + { "frame_count_delta",NULL, 0, AV_OPT_TYPE_CONST, {.i64=FLAG_FC_DELTA},0, 0, VFR, "flags" }, + { "pts", NULL, 0, AV_OPT_TYPE_CONST, {.i64=FLAG_PTS}, 0, 0, VFR, "flags" }, + { "pts_delta", NULL, 0, AV_OPT_TYPE_CONST, {.i64=FLAG_PTS_DELTA},0,0, VFR, "flags" }, + { "time", NULL, 0, AV_OPT_TYPE_CONST, {.i64=FLAG_TIME}, 0, 0, VFR, "flags" }, + { "time_delta", NULL, 0, AV_OPT_TYPE_CONST, {.i64=FLAG_TIME_DELTA},0,0,VFR, "flags" }, + { "timebase", NULL, 0, AV_OPT_TYPE_CONST, {.i64=FLAG_TB}, 0, 0, VFR, "flags" }, + { "format", NULL, 0, AV_OPT_TYPE_CONST, {.i64=FLAG_FMT}, 0, 0, VFR, "flags" }, + { "size", NULL, 0, AV_OPT_TYPE_CONST, {.i64=FLAG_SIZE}, 0, 0, VFR, "flags" }, + { "rate", NULL, 0, AV_OPT_TYPE_CONST, {.i64=FLAG_RATE}, 0, 0, VFR, "flags" }, + { "eof", NULL, 0, AV_OPT_TYPE_CONST, {.i64=FLAG_EOF}, 0, 0, VFR, "flags" }, + { "sample_count_in", NULL, 0, AV_OPT_TYPE_CONST, {.i64=FLAG_SCOUT}, 0, 0, VFR, "flags" }, + { "sample_count_out", NULL, 0, AV_OPT_TYPE_CONST, {.i64=FLAG_SCIN}, 0, 0, VFR, "flags" }, + { "sample_count_delta",NULL,0, AV_OPT_TYPE_CONST, {.i64=FLAG_SC_DELTA},0, 0, VFR, "flags" }, { "rate", "set video rate", OFFSET(frame_rate), AV_OPT_TYPE_VIDEO_RATE, {.str = "25"}, 0, INT_MAX, VF }, { "r", "set video rate", OFFSET(frame_rate), AV_OPT_TYPE_VIDEO_RATE, {.str = "25"}, 0, INT_MAX, VF }, { NULL } @@ -537,6 +538,7 @@ const AVFilter ff_vf_graphmonitor = { FILTER_INPUTS(graphmonitor_inputs), FILTER_OUTPUTS(graphmonitor_outputs), FILTER_QUERY_FUNC(query_formats), + .process_command = ff_filter_process_command, }; #endif // CONFIG_GRAPHMONITOR_FILTER @@ -569,5 +571,6 @@ const AVFilter ff_avf_agraphmonitor = { FILTER_INPUTS(agraphmonitor_inputs), FILTER_OUTPUTS(agraphmonitor_outputs), FILTER_QUERY_FUNC(query_formats), + .process_command = ff_filter_process_command, }; #endif // CONFIG_AGRAPHMONITOR_FILTER From 4c695bfa65c92fd2f3b197383408eaa23130c3d9 Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Thu, 18 May 2023 12:37:56 +0200 Subject: [PATCH 1061/2172] avfilter/f_graphmonitor: make mode option of type flags --- doc/filters.texi | 16 +++++++++-- libavfilter/f_graphmonitor.c | 56 ++++++++++++++++++------------------ 2 files changed, 41 insertions(+), 31 deletions(-) diff --git a/doc/filters.texi b/doc/filters.texi index d935e62b3f6..c00012be268 100644 --- a/doc/filters.texi +++ b/doc/filters.texi @@ -14639,9 +14639,19 @@ Set video output size. Default is @var{hd720}. Set video opacity. Default is @var{0.9}. Allowed range is from @var{0} to @var{1}. @item mode, m -Set output mode, can be @var{full} or @var{compact} or @var{nozero}. -In @var{compact} mode only filters with some queued frames have displayed stats. -In @var{nozero} mode only non-zero stats values are displayed. +Set output mode flags. + +Available values for flags are: +@table @samp +@item full +No any filtering. Default. +@item compact +Show only filters with queued frames. +@item nozero +Show only filters with non-zero stats. +@item noeof +Show only filters with non-eof stat. +@end table @item flags, f Set flags which enable which stats are shown in video. diff --git a/libavfilter/f_graphmonitor.c b/libavfilter/f_graphmonitor.c index e5e8d23aa19..0fe14f885e4 100644 --- a/libavfilter/f_graphmonitor.c +++ b/libavfilter/f_graphmonitor.c @@ -62,11 +62,11 @@ typedef struct GraphMonitorContext { } GraphMonitorContext; enum { - MODE_FULL, - MODE_COMPACT, - MODE_NOZERO, - MODE_NOZEROEOF, - NB_MODES + MODE_FULL = 0, + MODE_COMPACT = 1, + MODE_NOZERO = 2, + MODE_NOEOF = 4, + MODE_MAX = 7 }; enum { @@ -97,12 +97,12 @@ static const AVOption graphmonitor_options[] = { { "s", "set monitor size", OFFSET(w), AV_OPT_TYPE_IMAGE_SIZE, {.str="hd720"}, 0, 0, VF }, { "opacity", "set video opacity", OFFSET(opacity), AV_OPT_TYPE_FLOAT, {.dbl=.9}, 0, 1, VF }, { "o", "set video opacity", OFFSET(opacity), AV_OPT_TYPE_FLOAT, {.dbl=.9}, 0, 1, VF }, - { "mode", "set mode", OFFSET(mode), AV_OPT_TYPE_INT, {.i64=0}, 0, NB_MODES-1, VFR, "mode" }, - { "m", "set mode", OFFSET(mode), AV_OPT_TYPE_INT, {.i64=0}, 0, NB_MODES-1, VFR, "mode" }, - { "full", NULL, 0, AV_OPT_TYPE_CONST, {.i64=MODE_FULL}, 0, 0, VFR, "mode" }, - { "compact", NULL, 0, AV_OPT_TYPE_CONST, {.i64=MODE_COMPACT},0, 0, VFR, "mode" }, - { "nozero", NULL, 0, AV_OPT_TYPE_CONST, {.i64=MODE_NOZERO}, 0, 0, VFR, "mode" }, - { "nozeroeof", NULL, 0, AV_OPT_TYPE_CONST, {.i64=MODE_NOZEROEOF}, 0, 0, VFR, "mode" }, + { "mode", "set mode", OFFSET(mode), AV_OPT_TYPE_FLAGS, {.i64=0}, 0, MODE_MAX, VFR, "mode" }, + { "m", "set mode", OFFSET(mode), AV_OPT_TYPE_FLAGS, {.i64=0}, 0, MODE_MAX, VFR, "mode" }, + { "full", NULL, 0, AV_OPT_TYPE_CONST, {.i64=MODE_FULL}, 0, 0, VFR, "mode" }, + { "compact", NULL, 0, AV_OPT_TYPE_CONST, {.i64=MODE_COMPACT},0, 0, VFR, "mode" }, + { "nozero", NULL, 0, AV_OPT_TYPE_CONST, {.i64=MODE_NOZERO}, 0, 0, VFR, "mode" }, + { "noeof", NULL, 0, AV_OPT_TYPE_CONST, {.i64=MODE_NOEOF}, 0, 0, VFR, "mode" }, { "flags", "set flags", OFFSET(flags), AV_OPT_TYPE_FLAGS, {.i64=FLAG_QUEUE}, 0, INT_MAX, VFR, "flags" }, { "f", "set flags", OFFSET(flags), AV_OPT_TYPE_FLAGS, {.i64=FLAG_QUEUE}, 0, INT_MAX, VFR, "flags" }, { "queue", NULL, 0, AV_OPT_TYPE_CONST, {.i64=FLAG_QUEUE}, 0, 0, VFR, "flags" }, @@ -277,7 +277,7 @@ static int draw_items(AVFilterContext *ctx, AVFrame *out, drawtext(out, xpos, ypos, buffer, s->white); xpos += strlen(buffer) * 8; } - if ((s->flags & FLAG_QUEUE) && (s->mode < MODE_NOZERO || frames)) { + if ((s->flags & FLAG_QUEUE) && (!(s->mode & MODE_NOZERO) || frames)) { snprintf(buffer, sizeof(buffer)-1, " | queue: "); drawtext(out, xpos, ypos, buffer, s->white); xpos += strlen(buffer) * 8; @@ -285,52 +285,52 @@ static int draw_items(AVFilterContext *ctx, AVFrame *out, drawtext(out, xpos, ypos, buffer, frames > 0 ? frames >= 10 ? frames >= 50 ? s->red : s->yellow : s->green : s->white); xpos += strlen(buffer) * 8; } - if ((s->flags & FLAG_FCIN) && (s->mode < MODE_NOZERO || l->frame_count_in)) { + if ((s->flags & FLAG_FCIN) && (!(s->mode & MODE_NOZERO) || l->frame_count_in)) { snprintf(buffer, sizeof(buffer)-1, " | in: %"PRId64, l->frame_count_in); drawtext(out, xpos, ypos, buffer, s->white); xpos += strlen(buffer) * 8; } - if ((s->flags & FLAG_FCOUT) && (s->mode < MODE_NOZERO || l->frame_count_out)) { + if ((s->flags & FLAG_FCOUT) && (!(s->mode & MODE_NOZERO) || l->frame_count_out)) { snprintf(buffer, sizeof(buffer)-1, " | out: %"PRId64, l->frame_count_out); drawtext(out, xpos, ypos, buffer, s->white); xpos += strlen(buffer) * 8; } - if ((s->flags & FLAG_FC_DELTA) && (s->mode < MODE_NOZERO || (l->frame_count_in - l->frame_count_out))) { + if ((s->flags & FLAG_FC_DELTA) && (!(s->mode & MODE_NOZERO) || (l->frame_count_in - l->frame_count_out))) { snprintf(buffer, sizeof(buffer)-1, " | delta: %"PRId64, l->frame_count_in - l->frame_count_out); drawtext(out, xpos, ypos, buffer, s->white); xpos += strlen(buffer) * 8; } - if ((s->flags & FLAG_SCIN) && (s->mode < MODE_NOZERO || l->sample_count_in)) { + if ((s->flags & FLAG_SCIN) && (!(s->mode & MODE_NOZERO) || l->sample_count_in)) { snprintf(buffer, sizeof(buffer)-1, " | sin: %"PRId64, l->sample_count_in); drawtext(out, xpos, ypos, buffer, s->white); xpos += strlen(buffer) * 8; } - if ((s->flags & FLAG_SCOUT) && (s->mode < MODE_NOZERO || l->sample_count_out)) { + if ((s->flags & FLAG_SCOUT) && (!(s->mode & MODE_NOZERO) || l->sample_count_out)) { snprintf(buffer, sizeof(buffer)-1, " | sout: %"PRId64, l->sample_count_out); drawtext(out, xpos, ypos, buffer, s->white); xpos += strlen(buffer) * 8; } - if ((s->flags & FLAG_SC_DELTA) && (s->mode < MODE_NOZERO || (l->sample_count_in - l->sample_count_out))) { + if ((s->flags & FLAG_SC_DELTA) && (!(s->mode & MODE_NOZERO) || (l->sample_count_in - l->sample_count_out))) { snprintf(buffer, sizeof(buffer)-1, " | sdelta: %"PRId64, l->sample_count_in - l->sample_count_out); drawtext(out, xpos, ypos, buffer, s->white); xpos += strlen(buffer) * 8; } - if ((s->flags & FLAG_PTS) && (s->mode < MODE_NOZERO || current_pts_us)) { + if ((s->flags & FLAG_PTS) && (!(s->mode & MODE_NOZERO) || current_pts_us)) { snprintf(buffer, sizeof(buffer)-1, " | pts: %s", av_ts2str(current_pts_us)); drawtext(out, xpos, ypos, buffer, s->white); xpos += strlen(buffer) * 8; } - if ((s->flags & FLAG_PTS_DELTA) && (s->mode < MODE_NOZERO || (current_pts_us - previous_pts_us))) { + if ((s->flags & FLAG_PTS_DELTA) && (!(s->mode & MODE_NOZERO) || (current_pts_us - previous_pts_us))) { snprintf(buffer, sizeof(buffer)-1, " | pts_delta: %s", av_ts2str(current_pts_us - previous_pts_us)); drawtext(out, xpos, ypos, buffer, s->white); xpos += strlen(buffer) * 8; } - if ((s->flags & FLAG_TIME) && (s->mode < MODE_NOZERO || current_pts_us)) { + if ((s->flags & FLAG_TIME) && (!(s->mode & MODE_NOZERO) || current_pts_us)) { snprintf(buffer, sizeof(buffer)-1, " | time: %s", av_ts2timestr(current_pts_us, &AV_TIME_BASE_Q)); drawtext(out, xpos, ypos, buffer, s->white); xpos += strlen(buffer) * 8; } - if ((s->flags & FLAG_TIME_DELTA) && (s->mode < MODE_NOZERO || (current_pts_us - previous_pts_us))) { + if ((s->flags & FLAG_TIME_DELTA) && (!(s->mode & MODE_NOZERO) || (current_pts_us - previous_pts_us))) { snprintf(buffer, sizeof(buffer)-1, " | time_delta: %s", av_ts2timestr(current_pts_us - previous_pts_us, &AV_TIME_BASE_Q)); drawtext(out, xpos, ypos, buffer, s->white); xpos += strlen(buffer) * 8; @@ -374,10 +374,10 @@ static int create_frame(AVFilterContext *ctx, int64_t pts) AVFilterContext *filter = ctx->graph->filters[i]; char buffer[1024] = { 0 }; - if (s->mode == MODE_COMPACT && !filter_have_queued(filter)) + if ((s->mode & MODE_COMPACT) && !filter_have_queued(filter)) continue; - if (s->mode == MODE_NOZEROEOF && filter_have_eof(filter)) + if ((s->mode & MODE_NOEOF) && filter_have_eof(filter)) continue; xpos = 0; @@ -389,10 +389,10 @@ static int create_frame(AVFilterContext *ctx, int64_t pts) AVFilterLink *l = filter->inputs[j]; size_t frames = ff_inlink_queued_frames(l); - if (s->mode == MODE_COMPACT && !frames) + if ((s->mode & MODE_COMPACT) && !frames) continue; - if (s->mode == MODE_NOZEROEOF && ff_outlink_get_status(l)) + if ((s->mode & MODE_NOEOF) && ff_outlink_get_status(l)) continue; xpos = 10; @@ -412,10 +412,10 @@ static int create_frame(AVFilterContext *ctx, int64_t pts) AVFilterLink *l = filter->outputs[j]; size_t frames = ff_inlink_queued_frames(l); - if (s->mode == MODE_COMPACT && !frames) + if ((s->mode & MODE_COMPACT) && !frames) continue; - if (s->mode == MODE_NOZEROEOF && ff_outlink_get_status(l)) + if ((s->mode & MODE_NOEOF) && ff_outlink_get_status(l)) continue; xpos = 10; From a2a0a81184df586d7b567d7b60d55d0e86376963 Mon Sep 17 00:00:00 2001 From: James Almer Date: Wed, 17 May 2023 11:21:52 -0300 Subject: [PATCH 1062/2172] avformat/yuvmpegenc: add support for rawvideo input The demuxer exports rawvideo, so there's no reason for the muxer to only work with wrapped_avframe. Reviewed-by: Ronald S. Bultje Signed-off-by: James Almer --- libavformat/yuv4mpegenc.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/libavformat/yuv4mpegenc.c b/libavformat/yuv4mpegenc.c index 2fa5ee2714d..968ba2fa130 100644 --- a/libavformat/yuv4mpegenc.c +++ b/libavformat/yuv4mpegenc.c @@ -189,6 +189,11 @@ static int yuv4_write_packet(AVFormatContext *s, AVPacket *pkt) avio_printf(s->pb, Y4M_FRAME_MAGIC "\n"); + if (st->codecpar->codec_id == AV_CODEC_ID_RAWVIDEO) { + avio_write(pb, pkt->data, pkt->size); + return 0; + } + width = st->codecpar->width; height = st->codecpar->height; desc = av_pix_fmt_desc_get(st->codecpar->format); @@ -218,7 +223,8 @@ static int yuv4_init(AVFormatContext *s) if (s->nb_streams != 1) return AVERROR(EIO); - if (s->streams[0]->codecpar->codec_id != AV_CODEC_ID_WRAPPED_AVFRAME) { + if (s->streams[0]->codecpar->codec_id != AV_CODEC_ID_WRAPPED_AVFRAME && + s->streams[0]->codecpar->codec_id != AV_CODEC_ID_RAWVIDEO) { av_log(s, AV_LOG_ERROR, "ERROR: Codec not supported.\n"); return AVERROR_INVALIDDATA; } From dbe43bca25b84f2c2f5f713eeff5ab2dae89fc25 Mon Sep 17 00:00:00 2001 From: Pierre-Anthony Lemieux Date: Mon, 15 May 2023 11:29:45 -0700 Subject: [PATCH 1063/2172] fate/imf: fix memory leak --- libavformat/tests/imf.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/libavformat/tests/imf.c b/libavformat/tests/imf.c index cfd84fb8c8d..c02cd87ceb8 100644 --- a/libavformat/tests/imf.c +++ b/libavformat/tests/imf.c @@ -402,6 +402,9 @@ static int test_bad_cpl_parsing(FFIMFCPL **cpl) return ret; } + ff_imf_cpl_free(*cpl); + *cpl = NULL; + return 0; } @@ -423,6 +426,9 @@ static int test_bad_resource_cpl_parsing(FFIMFCPL **cpl) return ret; } + ff_imf_cpl_free(*cpl); + *cpl = NULL; + return 0; } @@ -594,8 +600,11 @@ int main(int argc, char *argv[]) printf("#### End failing test ####\n"); printf("#### The following should emit errors ####\n"); - if (test_bad_resource_cpl_parsing(&cpl) != 0) + if (test_bad_resource_cpl_parsing(&cpl) != 0) { + if (cpl) + printf("Improper cleanup after failed CPL parsing\n"); ret = 1; + } printf("#### End emission of errors ####\n"); return ret; From 283813897519d48bfdc3acb974e82f034f8a7727 Mon Sep 17 00:00:00 2001 From: Pierre-Anthony Lemieux Date: Mon, 15 May 2023 08:10:30 -0700 Subject: [PATCH 1064/2172] fate/imf: remove redundant code --- libavformat/tests/imf.c | 52 ++++++++++------------------------------- 1 file changed, 12 insertions(+), 40 deletions(-) diff --git a/libavformat/tests/imf.c b/libavformat/tests/imf.c index c02cd87ceb8..068ee6c58ab 100644 --- a/libavformat/tests/imf.c +++ b/libavformat/tests/imf.c @@ -257,7 +257,7 @@ const char *cpl_doc = "" ""; -const char *cpl_bad_doc = ""; +const char *cpl_bad_empty_doc = ""; const char *asset_map_doc = "" @@ -384,52 +384,31 @@ static int test_cpl_parsing(void) return 0; } -static int test_bad_cpl_parsing(FFIMFCPL **cpl) -{ - xmlDocPtr doc; - int ret; - - doc = xmlReadMemory(cpl_bad_doc, strlen(cpl_bad_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 ret; - } - - ff_imf_cpl_free(*cpl); - *cpl = NULL; - - return 0; -} - -static int test_bad_resource_cpl_parsing(FFIMFCPL **cpl) -{ +static int test_cpl_from_doc(FFIMFCPL **cpl, const char* cpl_doc, int should_pass) { xmlDocPtr doc; int ret; - doc = xmlReadMemory(cpl_bad_resource_doc, strlen(cpl_bad_resource_doc), NULL, NULL, 0); + doc = xmlReadMemory(cpl_doc, strlen(cpl_doc), NULL, NULL, 0); if (doc == NULL) { printf("XML parsing failed.\n"); - return 1; + return should_pass; } ret = ff_imf_parse_cpl_from_xml_dom(doc, cpl); xmlFreeDoc(doc); if (ret) { printf("CPL parsing failed.\n"); - return ret; + if (*cpl) { + printf("Improper cleanup after failed CPL parsing\n"); + return 1; + } + return should_pass; } ff_imf_cpl_free(*cpl); *cpl = NULL; - return 0; + return !should_pass; } static int check_asset_locator_attributes(IMFAssetLocator *asset, IMFAssetLocator *expected_asset) @@ -591,20 +570,13 @@ int main(int argc, char *argv[]) ret = 1; printf("#### The following should fail ####\n"); - if (test_bad_cpl_parsing(&cpl) == 0) { + if (test_cpl_from_doc(&cpl, cpl_bad_empty_doc, 0) != 0) ret = 1; - } else if (cpl) { - printf("Improper cleanup after failed CPL parsing\n"); - ret = 1; - } printf("#### End failing test ####\n"); printf("#### The following should emit errors ####\n"); - if (test_bad_resource_cpl_parsing(&cpl) != 0) { - if (cpl) - printf("Improper cleanup after failed CPL parsing\n"); + if (test_cpl_from_doc(&cpl, cpl_bad_resource_doc, 1) != 0) ret = 1; - } printf("#### End emission of errors ####\n"); return ret; From 47430a3cb18c77f6c148eee7c528abc2e8bf3e91 Mon Sep 17 00:00:00 2001 From: Zhao Zhili Date: Sat, 13 May 2023 01:13:05 +0800 Subject: [PATCH 1065/2172] avcodec/cavs_parser: fix finding the end of a frame Use the next I/P/B or start code as the end of current frame. Before the patch, extension start code, user data start code, sequence end code and so on are treated as the start of next frame. Signed-off-by: Zhao Zhili --- libavcodec/cavs_parser.c | 11 ++++--- tests/fate/demux.mak | 3 ++ tests/ref/fate/cavs-demux | 62 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 70 insertions(+), 6 deletions(-) create mode 100644 tests/ref/fate/cavs-demux diff --git a/libavcodec/cavs_parser.c b/libavcodec/cavs_parser.c index 03f392c2e5a..4a03effd0f7 100644 --- a/libavcodec/cavs_parser.c +++ b/libavcodec/cavs_parser.c @@ -59,12 +59,11 @@ static int cavs_find_frame_end(ParseContext *pc, const uint8_t *buf, return 0; for(; i SLICE_MAX_START_CODE){ - pc->frame_start_found=0; - pc->state=-1; - return i-3; - } + if (state == PIC_I_START_CODE || state == PIC_PB_START_CODE || + state == CAVS_START_CODE) { + pc->frame_start_found=0; + pc->state=-1; + return i-3; } } } diff --git a/tests/fate/demux.mak b/tests/fate/demux.mak index 2c508a42aa7..c9387b4c0a8 100644 --- a/tests/fate/demux.mak +++ b/tests/fate/demux.mak @@ -29,6 +29,9 @@ fate-bcstm: CMD = crc -i $(TARGET_SAMPLES)/bfstm/loz-mm-mikau.bcstm -c:a copy FATE_SAMPLES_DEMUX-$(CONFIG_BRSTM_DEMUXER) += fate-brstm fate-brstm: CMD = crc -i $(TARGET_SAMPLES)/brstm/lozswd_partial.brstm -c:a copy +FATE_FFPROBE_DEMUX-$(call ALLYES, CAVSVIDEO_DEMUXER CAVSVIDEO_PARSER) += fate-cavs-demux +fate-cavs-demux: CMD = ffprobe_demux $(TARGET_SAMPLES)/cavs/bunny.cavs + FATE_SAMPLES_DEMUX-$(CONFIG_CDXL_DEMUXER) += fate-cdxl-demux fate-cdxl-demux: CMD = framecrc -i $(TARGET_SAMPLES)/cdxl/mirage.cdxl -c:v copy -c:a copy diff --git a/tests/ref/fate/cavs-demux b/tests/ref/fate/cavs-demux new file mode 100644 index 00000000000..8ad7ec2fe10 --- /dev/null +++ b/tests/ref/fate/cavs-demux @@ -0,0 +1,62 @@ +packet|codec_type=video|stream_index=0|pts=0|pts_time=0.000000|dts=0|dts_time=0.000000|duration=48000|duration_time=0.040000|size=14447|pos=0|flags=K__|data_hash=CRC32:83f257c0 +packet|codec_type=video|stream_index=0|pts=48000|pts_time=0.040000|dts=48000|dts_time=0.040000|duration=48000|duration_time=0.040000|size=483|pos=14447|flags=K__|data_hash=CRC32:5abb82f8 +packet|codec_type=video|stream_index=0|pts=96000|pts_time=0.080000|dts=96000|dts_time=0.080000|duration=48000|duration_time=0.040000|size=18|pos=14930|flags=K__|data_hash=CRC32:b8b123d8 +packet|codec_type=video|stream_index=0|pts=144000|pts_time=0.120000|dts=144000|dts_time=0.120000|duration=48000|duration_time=0.040000|size=18|pos=14948|flags=K__|data_hash=CRC32:19180fa8 +packet|codec_type=video|stream_index=0|pts=192000|pts_time=0.160000|dts=192000|dts_time=0.160000|duration=48000|duration_time=0.040000|size=18|pos=14966|flags=K__|data_hash=CRC32:cf501647 +packet|codec_type=video|stream_index=0|pts=240000|pts_time=0.200000|dts=240000|dts_time=0.200000|duration=40000|duration_time=0.033333|size=1807|pos=14984|flags=K__|data_hash=CRC32:4267e1d5 +packet|codec_type=video|stream_index=0|pts=280000|pts_time=0.233333|dts=280000|dts_time=0.233333|duration=40000|duration_time=0.033333|size=28|pos=16791|flags=K__|data_hash=CRC32:c223285a +packet|codec_type=video|stream_index=0|pts=320000|pts_time=0.266667|dts=320000|dts_time=0.266667|duration=40000|duration_time=0.033333|size=25|pos=16819|flags=K__|data_hash=CRC32:2565cc9e +packet|codec_type=video|stream_index=0|pts=360000|pts_time=0.300000|dts=360000|dts_time=0.300000|duration=40000|duration_time=0.033333|size=22|pos=16844|flags=K__|data_hash=CRC32:7fbf36ac +packet|codec_type=video|stream_index=0|pts=400000|pts_time=0.333333|dts=400000|dts_time=0.333333|duration=40000|duration_time=0.033333|size=23884|pos=16866|flags=K__|data_hash=CRC32:d61430fd +packet|codec_type=video|stream_index=0|pts=440000|pts_time=0.366667|dts=440000|dts_time=0.366667|duration=40000|duration_time=0.033333|size=265|pos=40750|flags=K__|data_hash=CRC32:d64145a0 +packet|codec_type=video|stream_index=0|pts=480000|pts_time=0.400000|dts=480000|dts_time=0.400000|duration=40000|duration_time=0.033333|size=393|pos=41015|flags=K__|data_hash=CRC32:32c020e2 +packet|codec_type=video|stream_index=0|pts=520000|pts_time=0.433333|dts=520000|dts_time=0.433333|duration=40000|duration_time=0.033333|size=656|pos=41408|flags=K__|data_hash=CRC32:965c7846 +packet|codec_type=video|stream_index=0|pts=560000|pts_time=0.466667|dts=560000|dts_time=0.466667|duration=40000|duration_time=0.033333|size=3500|pos=42064|flags=K__|data_hash=CRC32:ddf731de +packet|codec_type=video|stream_index=0|pts=600000|pts_time=0.500000|dts=600000|dts_time=0.500000|duration=40000|duration_time=0.033333|size=68|pos=45564|flags=K__|data_hash=CRC32:f8c8ba07 +packet|codec_type=video|stream_index=0|pts=640000|pts_time=0.533333|dts=640000|dts_time=0.533333|duration=40000|duration_time=0.033333|size=58|pos=45632|flags=K__|data_hash=CRC32:22adbb83 +packet|codec_type=video|stream_index=0|pts=680000|pts_time=0.566667|dts=680000|dts_time=0.566667|duration=40000|duration_time=0.033333|size=43|pos=45690|flags=K__|data_hash=CRC32:53fb136c +packet|codec_type=video|stream_index=0|pts=720000|pts_time=0.600000|dts=720000|dts_time=0.600000|duration=40000|duration_time=0.033333|size=11757|pos=45733|flags=K__|data_hash=CRC32:551e491b +packet|codec_type=video|stream_index=0|pts=760000|pts_time=0.633333|dts=760000|dts_time=0.633333|duration=40000|duration_time=0.033333|size=98|pos=57490|flags=K__|data_hash=CRC32:4e718dd4 +packet|codec_type=video|stream_index=0|pts=800000|pts_time=0.666667|dts=800000|dts_time=0.666667|duration=40000|duration_time=0.033333|size=79|pos=57588|flags=K__|data_hash=CRC32:4c5a32f5 +packet|codec_type=video|stream_index=0|pts=840000|pts_time=0.700000|dts=840000|dts_time=0.700000|duration=40000|duration_time=0.033333|size=128|pos=57667|flags=K__|data_hash=CRC32:95b8cad1 +packet|codec_type=video|stream_index=0|pts=880000|pts_time=0.733333|dts=880000|dts_time=0.733333|duration=40000|duration_time=0.033333|size=10487|pos=57795|flags=K__|data_hash=CRC32:8646f8f2 +packet|codec_type=video|stream_index=0|pts=920000|pts_time=0.766667|dts=920000|dts_time=0.766667|duration=40000|duration_time=0.033333|size=65|pos=68282|flags=K__|data_hash=CRC32:73687d19 +packet|codec_type=video|stream_index=0|pts=960000|pts_time=0.800000|dts=960000|dts_time=0.800000|duration=40000|duration_time=0.033333|size=46|pos=68347|flags=K__|data_hash=CRC32:ad381ca5 +packet|codec_type=video|stream_index=0|pts=1000000|pts_time=0.833333|dts=1000000|dts_time=0.833333|duration=40000|duration_time=0.033333|size=67|pos=68393|flags=K__|data_hash=CRC32:89069152 +packet|codec_type=video|stream_index=0|pts=1040000|pts_time=0.866667|dts=1040000|dts_time=0.866667|duration=40000|duration_time=0.033333|size=8403|pos=68460|flags=K__|data_hash=CRC32:a22913dd +packet|codec_type=video|stream_index=0|pts=1080000|pts_time=0.900000|dts=1080000|dts_time=0.900000|duration=40000|duration_time=0.033333|size=70|pos=76863|flags=K__|data_hash=CRC32:98772596 +packet|codec_type=video|stream_index=0|pts=1120000|pts_time=0.933333|dts=1120000|dts_time=0.933333|duration=40000|duration_time=0.033333|size=63|pos=76933|flags=K__|data_hash=CRC32:cfd62cc4 +packet|codec_type=video|stream_index=0|pts=1160000|pts_time=0.966667|dts=1160000|dts_time=0.966667|duration=40000|duration_time=0.033333|size=70|pos=76996|flags=K__|data_hash=CRC32:9b526357 +packet|codec_type=video|stream_index=0|pts=1200000|pts_time=1.000000|dts=1200000|dts_time=1.000000|duration=40000|duration_time=0.033333|size=7945|pos=77066|flags=K__|data_hash=CRC32:d0f46769 +packet|codec_type=video|stream_index=0|pts=1240000|pts_time=1.033333|dts=1240000|dts_time=1.033333|duration=40000|duration_time=0.033333|size=40558|pos=85011|flags=K__|data_hash=CRC32:4db0bd7d +packet|codec_type=video|stream_index=0|pts=1280000|pts_time=1.066667|dts=1280000|dts_time=1.066667|duration=40000|duration_time=0.033333|size=1260|pos=125569|flags=K__|data_hash=CRC32:3c4397d7 +packet|codec_type=video|stream_index=0|pts=1320000|pts_time=1.100000|dts=1320000|dts_time=1.100000|duration=40000|duration_time=0.033333|size=27|pos=126829|flags=K__|data_hash=CRC32:5e233c77 +packet|codec_type=video|stream_index=0|pts=1360000|pts_time=1.133333|dts=1360000|dts_time=1.133333|duration=40000|duration_time=0.033333|size=26|pos=126856|flags=K__|data_hash=CRC32:57985e7b +packet|codec_type=video|stream_index=0|pts=1400000|pts_time=1.166667|dts=1400000|dts_time=1.166667|duration=40000|duration_time=0.033333|size=18|pos=126882|flags=K__|data_hash=CRC32:f4eb01ba +packet|codec_type=video|stream_index=0|pts=1440000|pts_time=1.200000|dts=1440000|dts_time=1.200000|duration=40000|duration_time=0.033333|size=2931|pos=126900|flags=K__|data_hash=CRC32:ca20964f +packet|codec_type=video|stream_index=0|pts=1480000|pts_time=1.233333|dts=1480000|dts_time=1.233333|duration=40000|duration_time=0.033333|size=25|pos=129831|flags=K__|data_hash=CRC32:a82bd0b4 +packet|codec_type=video|stream_index=0|pts=1520000|pts_time=1.266667|dts=1520000|dts_time=1.266667|duration=40000|duration_time=0.033333|size=19|pos=129856|flags=K__|data_hash=CRC32:bc5f709d +packet|codec_type=video|stream_index=0|pts=1560000|pts_time=1.300000|dts=1560000|dts_time=1.300000|duration=40000|duration_time=0.033333|size=30|pos=129875|flags=K__|data_hash=CRC32:c1f8a4c9 +packet|codec_type=video|stream_index=0|pts=1600000|pts_time=1.333333|dts=1600000|dts_time=1.333333|duration=40000|duration_time=0.033333|size=5088|pos=129905|flags=K__|data_hash=CRC32:41ace145 +packet|codec_type=video|stream_index=0|pts=1640000|pts_time=1.366667|dts=1640000|dts_time=1.366667|duration=40000|duration_time=0.033333|size=41|pos=134993|flags=K__|data_hash=CRC32:e169b3c7 +packet|codec_type=video|stream_index=0|pts=1680000|pts_time=1.400000|dts=1680000|dts_time=1.400000|duration=40000|duration_time=0.033333|size=53|pos=135034|flags=K__|data_hash=CRC32:973c5fe3 +packet|codec_type=video|stream_index=0|pts=1720000|pts_time=1.433333|dts=1720000|dts_time=1.433333|duration=40000|duration_time=0.033333|size=54|pos=135087|flags=K__|data_hash=CRC32:665639e6 +packet|codec_type=video|stream_index=0|pts=1760000|pts_time=1.466667|dts=1760000|dts_time=1.466667|duration=40000|duration_time=0.033333|size=7150|pos=135141|flags=K__|data_hash=CRC32:cc910027 +packet|codec_type=video|stream_index=0|pts=1800000|pts_time=1.500000|dts=1800000|dts_time=1.500000|duration=40000|duration_time=0.033333|size=48|pos=142291|flags=K__|data_hash=CRC32:45658f78 +packet|codec_type=video|stream_index=0|pts=1840000|pts_time=1.533333|dts=1840000|dts_time=1.533333|duration=40000|duration_time=0.033333|size=48|pos=142339|flags=K__|data_hash=CRC32:94e359a2 +packet|codec_type=video|stream_index=0|pts=1880000|pts_time=1.566667|dts=1880000|dts_time=1.566667|duration=40000|duration_time=0.033333|size=51|pos=142387|flags=K__|data_hash=CRC32:959ccdd9 +packet|codec_type=video|stream_index=0|pts=1920000|pts_time=1.600000|dts=1920000|dts_time=1.600000|duration=40000|duration_time=0.033333|size=9379|pos=142438|flags=K__|data_hash=CRC32:a3318410 +packet|codec_type=video|stream_index=0|pts=1960000|pts_time=1.633333|dts=1960000|dts_time=1.633333|duration=40000|duration_time=0.033333|size=58|pos=151817|flags=K__|data_hash=CRC32:44b24f03 +packet|codec_type=video|stream_index=0|pts=2000000|pts_time=1.666667|dts=2000000|dts_time=1.666667|duration=40000|duration_time=0.033333|size=43|pos=151875|flags=K__|data_hash=CRC32:f4876e05 +packet|codec_type=video|stream_index=0|pts=2040000|pts_time=1.700000|dts=2040000|dts_time=1.700000|duration=40000|duration_time=0.033333|size=62|pos=151918|flags=K__|data_hash=CRC32:34dce749 +packet|codec_type=video|stream_index=0|pts=2080000|pts_time=1.733333|dts=2080000|dts_time=1.733333|duration=40000|duration_time=0.033333|size=10733|pos=151980|flags=K__|data_hash=CRC32:9012fdfb +packet|codec_type=video|stream_index=0|pts=2120000|pts_time=1.766667|dts=2120000|dts_time=1.766667|duration=40000|duration_time=0.033333|size=58|pos=162713|flags=K__|data_hash=CRC32:8a3c8760 +packet|codec_type=video|stream_index=0|pts=2160000|pts_time=1.800000|dts=2160000|dts_time=1.800000|duration=40000|duration_time=0.033333|size=41|pos=162771|flags=K__|data_hash=CRC32:28da6bf4 +packet|codec_type=video|stream_index=0|pts=2200000|pts_time=1.833333|dts=2200000|dts_time=1.833333|duration=40000|duration_time=0.033333|size=68|pos=162812|flags=K__|data_hash=CRC32:959dcc10 +packet|codec_type=video|stream_index=0|pts=2240000|pts_time=1.866667|dts=2240000|dts_time=1.866667|duration=40000|duration_time=0.033333|size=9247|pos=162880|flags=K__|data_hash=CRC32:cf1e2a1a +packet|codec_type=video|stream_index=0|pts=2280000|pts_time=1.900000|dts=2280000|dts_time=1.900000|duration=40000|duration_time=0.033333|size=58|pos=172127|flags=K__|data_hash=CRC32:2efcb7ba +packet|codec_type=video|stream_index=0|pts=2320000|pts_time=1.933333|dts=2320000|dts_time=1.933333|duration=40000|duration_time=0.033333|size=67|pos=172185|flags=K__|data_hash=CRC32:42484449 +packet|codec_type=video|stream_index=0|pts=2360000|pts_time=1.966667|dts=2360000|dts_time=1.966667|duration=40000|duration_time=0.033333|size=83|pos=172252|flags=K__|data_hash=CRC32:a941bdf0 +packet|codec_type=video|stream_index=0|pts=2400000|pts_time=2.000000|dts=2400000|dts_time=2.000000|duration=40000|duration_time=0.033333|size=5417|pos=172335|flags=K__|data_hash=CRC32:9d0d503b +stream|index=0|codec_name=cavs|profile=unknown|codec_type=video|codec_tag_string=[0][0][0][0]|codec_tag=0x0000|width=1280|height=720|coded_width=1280|coded_height=720|closed_captions=0|film_grain=0|has_b_frames=0|sample_aspect_ratio=N/A|display_aspect_ratio=N/A|pix_fmt=yuv420p|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=30/1|avg_frame_rate=25/1|time_base=1/1200000|start_pts=N/A|start_time=N/A|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=N/A|nb_read_packets=60|extradata_size=18|extradata_hash=CRC32:1255d52e|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=bunny.cavs|nb_streams=1|nb_programs=0|format_name=cavsvideo|start_time=N/A|duration=N/A|size=177752|bit_rate=N/A|probe_score=51 From 5cd304298eddbdc88d8c3c7d1bbf71aa251b096c Mon Sep 17 00:00:00 2001 From: xufuji456 <839789740@qq.com> Date: Fri, 19 May 2023 14:05:14 +0800 Subject: [PATCH 1066/2172] avcodec/videotoolboxenc: add low-latency encoding When using low-latency mode, it eliminates frame reordering and follows a one-in-one-out encoding mode Signed-off-by: xufuji456 <839789740@qq.com> Signed-off-by: Rick Kern --- libavcodec/videotoolboxenc.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/libavcodec/videotoolboxenc.c b/libavcodec/videotoolboxenc.c index c6f22723d6d..e91d17c1322 100644 --- a/libavcodec/videotoolboxenc.c +++ b/libavcodec/videotoolboxenc.c @@ -105,6 +105,7 @@ static struct{ CFStringRef kVTVideoEncoderSpecification_EnableHardwareAcceleratedVideoEncoder; CFStringRef kVTVideoEncoderSpecification_RequireHardwareAcceleratedVideoEncoder; + CFStringRef kVTVideoEncoderSpecification_EnableLowLatencyRateControl; getParameterSetAtIndex CMVideoFormatDescriptionGetHEVCParameterSetAtIndex; } compat_keys; @@ -171,6 +172,8 @@ static void loadVTEncSymbols(void){ "EnableHardwareAcceleratedVideoEncoder"); GET_SYM(kVTVideoEncoderSpecification_RequireHardwareAcceleratedVideoEncoder, "RequireHardwareAcceleratedVideoEncoder"); + GET_SYM(kVTVideoEncoderSpecification_EnableLowLatencyRateControl, + "EnableLowLatencyRateControl"); } typedef enum VT_H264Profile { @@ -1441,6 +1444,17 @@ static int vtenc_create_encoder(AVCodecContext *avctx, } } + // low-latency mode: eliminate frame reordering, follow a one-in-one-out encoding mode + if ((avctx->flags & AV_CODEC_FLAG_LOW_DELAY) && avctx->codec_id == AV_CODEC_ID_H264) { + status = VTSessionSetProperty(vtctx->session, + compat_keys.kVTVideoEncoderSpecification_EnableLowLatencyRateControl, + kCFBooleanTrue); + + if (status) { + av_log(avctx, AV_LOG_ERROR, "Error setting low latency property: %d\n", status); + } + } + status = VTCompressionSessionPrepareToEncodeFrames(vtctx->session); if (status) { av_log(avctx, AV_LOG_ERROR, "Error: cannot prepare encoder: %d\n", status); From c789a2324a6578568db947b6bf10c2dfd0011bef Mon Sep 17 00:00:00 2001 From: Rick Kern Date: Fri, 19 May 2023 09:48:26 -0400 Subject: [PATCH 1067/2172] lavc/videotoolboxenc: better compat_keys documentation Added documentation that describes when compat_keys should be used, and why it exists. Signed-off-by: Rick Kern --- libavcodec/videotoolboxenc.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/libavcodec/videotoolboxenc.c b/libavcodec/videotoolboxenc.c index e91d17c1322..b0297ec4486 100644 --- a/libavcodec/videotoolboxenc.c +++ b/libavcodec/videotoolboxenc.c @@ -63,7 +63,11 @@ typedef OSStatus (*getParameterSetAtIndex)(CMFormatDescriptionRef videoDesc, size_t *parameterSetCountOut, int *NALUnitHeaderLengthOut); -//These symbols may not be present +/* + * Keys that are not present in all versions of VideoToolbox need to be + * accessed from compat_keys, or it will cause compiler errors when compiling + * for older OS versions. + */ static struct{ CFStringRef kCVImageBufferColorPrimaries_ITU_R_2020; CFStringRef kCVImageBufferTransferFunction_ITU_R_2020; From 613f7164501ef6cb4a45e969477946dfa5fa1b00 Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Fri, 19 May 2023 19:12:37 +0200 Subject: [PATCH 1068/2172] avfilter/vf_mix: improve speed even more by avoiding using filter private context --- libavfilter/vf_mix.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/libavfilter/vf_mix.c b/libavfilter/vf_mix.c index 64d07bbbbb7..70fe90ea306 100644 --- a/libavfilter/vf_mix.c +++ b/libavfilter/vf_mix.c @@ -161,27 +161,27 @@ typedef struct ThreadData { continue; \ } \ \ - for (int i = 0; i < s->nb_inputs; i++) \ + for (int i = 0; i < nb_inputs; i++) \ linesize[i] = in[i]->linesize[p]; \ \ - for (int i = 0; i < s->nb_inputs; i++) \ + for (int i = 0; i < nb_inputs; i++) \ srcf[i] = in[i]->data[p] + slice_start * linesize[i]; \ \ for (int y = slice_start; y < slice_end; y++) { \ for (int x = 0; x < width; x++) { \ float val = 0.f; \ \ - for (int i = 0; i < s->nb_inputs; i++) { \ + for (int i = 0; i < nb_inputs; i++) { \ float src = *(type *)(srcf[i] + x * sizeof(type)); \ \ val += src * weights[i]; \ } \ \ - dst[x] = clip(fun(val * s->wfactor), 0, s->max); \ + dst[x] = clip(fun(val * wfactor), 0, max); \ } \ \ dst += dst_linesize; \ - for (int i = 0; i < s->nb_inputs; i++) \ + for (int i = 0; i < nb_inputs; i++) \ srcf[i] += linesize[i]; \ } \ } @@ -200,6 +200,9 @@ static int mix_frames(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) const float *weights = s->weights; uint8_t **srcf = s->data + jobnr * s->nb_inputs; int *linesize = s->linesize + jobnr * s->nb_inputs; + const int nb_inputs = s->nb_inputs; + const float wfactor = s->wfactor; + const int max = s->max; if (s->depth <= 8) { MIX_SLICE(uint8_t, lrintf, CLIP8) From 1b05d27346130599ea188c35f97790d95db1d55f Mon Sep 17 00:00:00 2001 From: James Almer Date: Tue, 16 May 2023 20:37:45 -0300 Subject: [PATCH 1069/2172] avcodec/libdav1d: export decoder frame delay As this is an AV_CODEC_CAP_OTHER_THREADS decoder, threading is handled by the underlying library. In this case, the frame delay is calculated by libdav1d based on the values from avctx->thread_count and the private max_frame_delay option. Export said delay reported by the library in AVCodecContext.delay Reviewed-by: Reviewed-by: Ronald S. Bultje Signed-off-by: James Almer --- libavcodec/libdav1d.c | 9 +++++++++ libavcodec/version.h | 2 +- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/libavcodec/libdav1d.c b/libavcodec/libdav1d.c index 4c48f0099a7..c15e98cbd1b 100644 --- a/libavcodec/libdav1d.c +++ b/libavcodec/libdav1d.c @@ -276,6 +276,15 @@ static av_cold int libdav1d_init(AVCodecContext *c) if (res < 0) return AVERROR(ENOMEM); +#if FF_DAV1D_VERSION_AT_LEAST(6,7) + res = dav1d_get_frame_delay(&s); + if (res < 0) // Should not happen + return AVERROR_EXTERNAL; + + // When dav1d_get_frame_delay() returns 1, there's no delay whatsoever + c->delay = res > 1 ? res : 0; +#endif + return 0; } diff --git a/libavcodec/version.h b/libavcodec/version.h index 7531c6c42a3..c20072197d5 100644 --- a/libavcodec/version.h +++ b/libavcodec/version.h @@ -30,7 +30,7 @@ #include "version_major.h" #define LIBAVCODEC_VERSION_MINOR 14 -#define LIBAVCODEC_VERSION_MICRO 100 +#define LIBAVCODEC_VERSION_MICRO 101 #define LIBAVCODEC_VERSION_INT AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \ LIBAVCODEC_VERSION_MINOR, \ From 4d885271bbbadf2e305291e2e66153ac9f7cdb37 Mon Sep 17 00:00:00 2001 From: James Almer Date: Thu, 11 May 2023 20:03:48 -0300 Subject: [PATCH 1070/2172] avutil/mathematics: add missing constants Including float variants for all of them. Signed-off-by: James Almer --- libavutil/mathematics.h | 51 +++++++++++++++++++++++++++++++++++++++++ libavutil/version.h | 2 +- 2 files changed, 52 insertions(+), 1 deletion(-) diff --git a/libavutil/mathematics.h b/libavutil/mathematics.h index e4aff1e973e..3e7b52eed6a 100644 --- a/libavutil/mathematics.h +++ b/libavutil/mathematics.h @@ -36,30 +36,81 @@ #ifndef M_E #define M_E 2.7182818284590452354 /* e */ #endif +#ifndef M_Ef +#define M_Ef 2.7182818284590452354f /* e */ +#endif #ifndef M_LN2 #define M_LN2 0.69314718055994530942 /* log_e 2 */ #endif +#ifndef M_LN2f +#define M_LN2f 0.69314718055994530942f /* log_e 2 */ +#endif #ifndef M_LN10 #define M_LN10 2.30258509299404568402 /* log_e 10 */ #endif +#ifndef M_LN10f +#define M_LN10f 2.30258509299404568402f /* log_e 10 */ +#endif #ifndef M_LOG2_10 #define M_LOG2_10 3.32192809488736234787 /* log_2 10 */ #endif +#ifndef M_LOG2_10f +#define M_LOG2_10f 3.32192809488736234787f /* log_2 10 */ +#endif #ifndef M_PHI #define M_PHI 1.61803398874989484820 /* phi / golden ratio */ #endif +#ifndef M_PHIf +#define M_PHIf 1.61803398874989484820f /* phi / golden ratio */ +#endif #ifndef M_PI #define M_PI 3.14159265358979323846 /* pi */ #endif +#ifndef M_PIf +#define M_PIf 3.14159265358979323846f /* pi */ +#endif #ifndef M_PI_2 #define M_PI_2 1.57079632679489661923 /* pi/2 */ #endif +#ifndef M_PI_2f +#define M_PI_2f 1.57079632679489661923f /* pi/2 */ +#endif +#ifndef M_PI_4 +#define M_PI_4 0.78539816339744830962 /* pi/4 */ +#endif +#ifndef M_PI_4f +#define M_PI_4f 0.78539816339744830962f /* pi/4 */ +#endif +#ifndef M_1_PI +#define M_1_PI 0.31830988618379067154 /* 1/pi */ +#endif +#ifndef M_1_PIf +#define M_1_PIf 0.31830988618379067154f /* 1/pi */ +#endif +#ifndef M_2_PI +#define M_2_PI 0.63661977236758134308 /* 2/pi */ +#endif +#ifndef M_2_PIf +#define M_2_PIf 0.63661977236758134308f /* 2/pi */ +#endif +#ifndef M_2_SQRTPI +#define M_2_SQRTPI 1.12837916709551257390 /* 2/sqrt(pi) */ +#endif +#ifndef M_2_SQRTPIf +#define M_2_SQRTPIf 1.12837916709551257390f /* 2/sqrt(pi) */ +#endif #ifndef M_SQRT1_2 #define M_SQRT1_2 0.70710678118654752440 /* 1/sqrt(2) */ #endif +#ifndef M_SQRT1_2f +#define M_SQRT1_2f 0.70710678118654752440f /* 1/sqrt(2) */ +#endif #ifndef M_SQRT2 #define M_SQRT2 1.41421356237309504880 /* sqrt(2) */ #endif +#ifndef M_SQRT2f +#define M_SQRT2f 1.41421356237309504880f /* sqrt(2) */ +#endif #ifndef NAN #define NAN av_int2float(0x7fc00000) #endif diff --git a/libavutil/version.h b/libavutil/version.h index 177effa9a4f..8c7ea1a47a6 100644 --- a/libavutil/version.h +++ b/libavutil/version.h @@ -79,7 +79,7 @@ */ #define LIBAVUTIL_VERSION_MAJOR 58 -#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 d55743c80917bc1507e639b54c9019b60213fc74 Mon Sep 17 00:00:00 2001 From: James Almer Date: Thu, 11 May 2023 20:06:12 -0300 Subject: [PATCH 1071/2172] avfilter/af_surround: replace double constants with float variants This is cleaner than the approach in d1ded7310a. Signed-off-by: James Almer --- libavfilter/af_surround.c | 52 +++++++++++++++++++-------------------- 1 file changed, 26 insertions(+), 26 deletions(-) diff --git a/libavfilter/af_surround.c b/libavfilter/af_surround.c index 0b88ac418bd..64abf1fdedf 100644 --- a/libavfilter/af_surround.c +++ b/libavfilter/af_surround.c @@ -331,16 +331,16 @@ static void angle_transform(float *x, float *y, float angle) if (angle == 90.f) return; - reference = angle * (float)M_PI / 180.f; + reference = angle * M_PIf / 180.f; r = hypotf(*x, *y); a = atan2f(*x, *y); r /= r_distance(a); - if (fabsf(a) <= (float)M_PI_4) - a *= reference / (float)M_PI_2; + if (fabsf(a) <= M_PI_4f) + a *= reference / M_PI_2f; else - a = (float)M_PI + (-2.f * (float)M_PI + reference) * ((float)M_PI - fabsf(a)) * FFDIFFSIGN(a, 0.f) / (3.f * (float)M_PI_2); + a = M_PIf + (-2.f * M_PIf + reference) * (M_PIf - fabsf(a)) * FFDIFFSIGN(a, 0.f) / (3.f * M_PI_2f); r *= r_distance(a); @@ -367,16 +367,16 @@ static void focus_transform(float *x, float *y, float focus) static void stereo_position(float a, float p, float *x, float *y) { av_assert2(a >= -1.f && a <= 1.f); - av_assert2(p >= 0.f && p <= (float)M_PI); - *x = av_clipf(a+a*fmaxf(0.f, p*p-(float)M_PI_2), -1.f, 1.f); - *y = av_clipf(cosf(a*(float)M_PI_2+(float)M_PI)*cosf((float)M_PI_2-p/(float)M_PI)*(float)M_LN10+1.f, -1.f, 1.f); + av_assert2(p >= 0.f && p <= M_PIf); + *x = av_clipf(a+a*fmaxf(0.f, p*p-M_PI_2f), -1.f, 1.f); + *y = av_clipf(cosf(a*M_PI_2f+M_PIf)*cosf(M_PI_2f-p/M_PIf)*M_LN10f+1.f, -1.f, 1.f); } static inline void get_lfe(int output_lfe, int n, float lowcut, float highcut, float *lfe_mag, float c_mag, float *mag_total, int lfe_mode) { if (output_lfe && n < highcut) { - *lfe_mag = n < lowcut ? 1.f : .5f*(1.f+cosf((float)M_PI*(lowcut-n)/(lowcut-highcut))); + *lfe_mag = n < lowcut ? 1.f : .5f*(1.f+cosf(M_PIf*(lowcut-n)/(lowcut-highcut))); *lfe_mag *= c_mag; if (lfe_mode) *mag_total -= *lfe_mag; @@ -779,8 +779,8 @@ static void filter_stereo(AVFilterContext *ctx) mag_sum = mag_sum < MIN_MAG_SUM ? 1.f : mag_sum; mag_dif = (l_mag - r_mag) / mag_sum; - if (phase_dif > (float)M_PI) - phase_dif = 2.f * (float)M_PI - phase_dif; + if (phase_dif > M_PIf) + phase_dif = 2.f * M_PIf - phase_dif; stereo_position(mag_dif, phase_dif, &x, &y); angle_transform(&x, &y, angle); @@ -835,8 +835,8 @@ static void filter_2_1(AVFilterContext *ctx) mag_sum = mag_sum < MIN_MAG_SUM ? 1.f : mag_sum; mag_dif = (l_mag - r_mag) / mag_sum; - if (phase_dif > (float)M_PI) - phase_dif = 2.f * (float)M_PI - phase_dif; + if (phase_dif > M_PIf) + phase_dif = 2.f * M_PIf - phase_dif; stereo_position(mag_dif, phase_dif, &x, &y); angle_transform(&x, &y, angle); @@ -893,8 +893,8 @@ static void filter_surround(AVFilterContext *ctx) mag_sum = mag_sum < MIN_MAG_SUM ? 1.f : mag_sum; mag_dif = (l_mag - r_mag) / mag_sum; - if (phase_dif > (float)M_PI) - phase_dif = 2.f * (float)M_PI - phase_dif; + if (phase_dif > M_PIf) + phase_dif = 2.f * M_PIf - phase_dif; stereo_position(mag_dif, phase_dif, &x, &y); angle_transform(&x, &y, angle); @@ -951,11 +951,11 @@ static void filter_5_0_side(AVFilterContext *ctx) float xl, yl; float xr, yr; - if (phase_difl > (float)M_PI) - phase_difl = 2.f * (float)M_PI - phase_difl; + if (phase_difl > M_PIf) + phase_difl = 2.f * M_PIf - phase_difl; - if (phase_difr > (float)M_PI) - phase_difr = 2.f * (float)M_PI - phase_difr; + if (phase_difr > M_PIf) + phase_difr = 2.f * M_PIf - phase_difr; stereo_position(mag_difl, phase_difl, &xl, &yl); stereo_position(mag_difr, phase_difr, &xr, &yr); @@ -1011,11 +1011,11 @@ static void filter_5_1_side(AVFilterContext *ctx) float xl, yl; float xr, yr; - if (phase_difl > (float)M_PI) - phase_difl = 2.f * (float)M_PI - phase_difl; + if (phase_difl > M_PIf) + phase_difl = 2.f * M_PIf - phase_difl; - if (phase_difr > (float)M_PI) - phase_difr = 2.f * (float)M_PI - phase_difr; + if (phase_difr > M_PIf) + phase_difr = 2.f * M_PIf - phase_difr; stereo_position(mag_difl, phase_difl, &xl, &yl); stereo_position(mag_difr, phase_difr, &xr, &yr); @@ -1071,11 +1071,11 @@ static void filter_5_1_back(AVFilterContext *ctx) float xl, yl; float xr, yr; - if (phase_difl > (float)M_PI) - phase_difl = 2.f * (float)M_PI - phase_difl; + if (phase_difl > M_PIf) + phase_difl = 2.f * M_PIf - phase_difl; - if (phase_difr > (float)M_PI) - phase_difr = 2.f * (float)M_PI - phase_difr; + if (phase_difr > M_PIf) + phase_difr = 2.f * M_PIf - phase_difr; stereo_position(mag_difl, phase_difl, &xl, &yl); stereo_position(mag_difr, phase_difr, &xr, &yr); From bd9d984c11c0057c7b504955952727f12af5c535 Mon Sep 17 00:00:00 2001 From: James Almer Date: Sat, 20 May 2023 00:10:35 -0300 Subject: [PATCH 1072/2172] fate/demux: fix fate-cavs-demux Signed-off-by: James Almer --- tests/fate/demux.mak | 2 +- tests/ref/fate/cavs-demux | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/fate/demux.mak b/tests/fate/demux.mak index c9387b4c0a8..d8fc68af886 100644 --- a/tests/fate/demux.mak +++ b/tests/fate/demux.mak @@ -30,7 +30,7 @@ FATE_SAMPLES_DEMUX-$(CONFIG_BRSTM_DEMUXER) += fate-brstm fate-brstm: CMD = crc -i $(TARGET_SAMPLES)/brstm/lozswd_partial.brstm -c:a copy FATE_FFPROBE_DEMUX-$(call ALLYES, CAVSVIDEO_DEMUXER CAVSVIDEO_PARSER) += fate-cavs-demux -fate-cavs-demux: CMD = ffprobe_demux $(TARGET_SAMPLES)/cavs/bunny.cavs +fate-cavs-demux: CMD = ffprobe_demux $(TARGET_SAMPLES)/cavs/bunny.mp4 FATE_SAMPLES_DEMUX-$(CONFIG_CDXL_DEMUXER) += fate-cdxl-demux fate-cdxl-demux: CMD = framecrc -i $(TARGET_SAMPLES)/cdxl/mirage.cdxl -c:v copy -c:a copy diff --git a/tests/ref/fate/cavs-demux b/tests/ref/fate/cavs-demux index 8ad7ec2fe10..82eec3000cc 100644 --- a/tests/ref/fate/cavs-demux +++ b/tests/ref/fate/cavs-demux @@ -59,4 +59,4 @@ packet|codec_type=video|stream_index=0|pts=2320000|pts_time=1.933333|dts=2320000 packet|codec_type=video|stream_index=0|pts=2360000|pts_time=1.966667|dts=2360000|dts_time=1.966667|duration=40000|duration_time=0.033333|size=83|pos=172252|flags=K__|data_hash=CRC32:a941bdf0 packet|codec_type=video|stream_index=0|pts=2400000|pts_time=2.000000|dts=2400000|dts_time=2.000000|duration=40000|duration_time=0.033333|size=5417|pos=172335|flags=K__|data_hash=CRC32:9d0d503b stream|index=0|codec_name=cavs|profile=unknown|codec_type=video|codec_tag_string=[0][0][0][0]|codec_tag=0x0000|width=1280|height=720|coded_width=1280|coded_height=720|closed_captions=0|film_grain=0|has_b_frames=0|sample_aspect_ratio=N/A|display_aspect_ratio=N/A|pix_fmt=yuv420p|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=30/1|avg_frame_rate=25/1|time_base=1/1200000|start_pts=N/A|start_time=N/A|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=N/A|nb_read_packets=60|extradata_size=18|extradata_hash=CRC32:1255d52e|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=bunny.cavs|nb_streams=1|nb_programs=0|format_name=cavsvideo|start_time=N/A|duration=N/A|size=177752|bit_rate=N/A|probe_score=51 +format|filename=bunny.mp4|nb_streams=1|nb_programs=0|format_name=cavsvideo|start_time=N/A|duration=N/A|size=177752|bit_rate=N/A|probe_score=51 From ff72256235aeaa2a4e197b54f69bad36d61a57d0 Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Sat, 20 May 2023 12:33:29 +0200 Subject: [PATCH 1073/2172] avformat/gif: use last frame duration --- libavformat/gif.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/libavformat/gif.c b/libavformat/gif.c index bfa7deb598c..568867cc5d5 100644 --- a/libavformat/gif.c +++ b/libavformat/gif.c @@ -88,6 +88,8 @@ static int gif_get_delay(GIFContext *gif, AVPacket *prev, AVPacket *new) gif->duration = av_clip_uint16(new->pts - prev->pts); else if (!new && gif->last_delay >= 0) gif->duration = gif->last_delay; + else if (prev->duration) + gif->duration = prev->duration; return gif->duration; } From 8980c1313b23004b1789d01ba8be423d175fd8a8 Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Sat, 20 May 2023 11:44:47 +0200 Subject: [PATCH 1074/2172] avcodec/ccaption_dec: simplify init function --- libavcodec/ccaption_dec.c | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/libavcodec/ccaption_dec.c b/libavcodec/ccaption_dec.c index 0f5b955f15d..f91c92b3733 100644 --- a/libavcodec/ccaption_dec.c +++ b/libavcodec/ccaption_dec.c @@ -262,7 +262,6 @@ typedef struct CCaptionSubContext { static av_cold int init_decoder(AVCodecContext *avctx) { - int ret; CCaptionSubContext *ctx = avctx->priv_data; av_bprint_init(&ctx->buffer[0], 0, AV_BPRINT_SIZE_UNLIMITED); @@ -272,7 +271,7 @@ static av_cold int init_decoder(AVCodecContext *avctx) ctx->bg_color = CCCOL_BLACK; ctx->rollup = 2; ctx->cursor_row = 10; - ret = ff_ass_subtitle_header(avctx, "Monospace", + return ff_ass_subtitle_header(avctx, "Monospace", ASS_DEFAULT_FONT_SIZE, ASS_DEFAULT_COLOR, ASS_DEFAULT_BACK_COLOR, @@ -281,11 +280,6 @@ static av_cold int init_decoder(AVCodecContext *avctx) ASS_DEFAULT_UNDERLINE, 3, ASS_DEFAULT_ALIGNMENT); - if (ret < 0) { - return ret; - } - - return ret; } static av_cold int close_decoder(AVCodecContext *avctx) From efdc6e8200e61b5f00c7074f0d061157b550afb2 Mon Sep 17 00:00:00 2001 From: James Almer Date: Sat, 20 May 2023 09:28:46 -0300 Subject: [PATCH 1075/2172] avformat/matroskaenc: remove accidental variable shadowing Should fix use of uninitialized value in a failure path. Signed-off-by: James Almer --- libavformat/matroskaenc.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libavformat/matroskaenc.c b/libavformat/matroskaenc.c index 492b86b8d7c..41e13b273dd 100644 --- a/libavformat/matroskaenc.c +++ b/libavformat/matroskaenc.c @@ -2697,8 +2697,8 @@ static int mkv_write_block(void *logctx, MatroskaMuxContext *mkv, if (side_data && side_data_size) { uint8_t *payload; size_t payload_size, buf_size; - int ret = av_dynamic_hdr_plus_to_t35((AVDynamicHDRPlus *)side_data, NULL, - &payload_size); + ret = av_dynamic_hdr_plus_to_t35((AVDynamicHDRPlus *)side_data, NULL, + &payload_size); if (ret < 0) return ret; From 902c949d309e3ef304775d1970ea77b04904f2bc Mon Sep 17 00:00:00 2001 From: Rick Kern Date: Sat, 20 May 2023 11:35:51 -0400 Subject: [PATCH 1076/2172] lavc/videotoolboxenc: better compat_keys docs Added more specific docs about when to use compat_keys, and how to add new constants. Signed-off-by: Rick Kern --- libavcodec/videotoolboxenc.c | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/libavcodec/videotoolboxenc.c b/libavcodec/videotoolboxenc.c index b0297ec4486..e93d45e1518 100644 --- a/libavcodec/videotoolboxenc.c +++ b/libavcodec/videotoolboxenc.c @@ -64,9 +64,19 @@ typedef OSStatus (*getParameterSetAtIndex)(CMFormatDescriptionRef videoDesc, int *NALUnitHeaderLengthOut); /* - * Keys that are not present in all versions of VideoToolbox need to be - * accessed from compat_keys, or it will cause compiler errors when compiling - * for older OS versions. + * Symbols that aren't available in MacOS 10.8 and iOS 8.0 need to be accessed + * from compat_keys, or it will cause compiler errors when compiling for older + * OS versions. + * + * For example, kVTCompressionPropertyKey_H264EntropyMode was added in + * MacOS 10.9. If this constant were used directly, a compiler would generate + * an error when it has access to the MacOS 10.8 headers, but does not have + * 10.9 headers. + * + * Runtime errors will still occur when unknown keys are set. A warning is + * logged and encoding continues where possible. + * + * When adding new symbols, they should be loaded/set in loadVTEncSymbols(). */ static struct{ CFStringRef kCVImageBufferColorPrimaries_ITU_R_2020; From 247e977953b1fb43c145d21074a7238a05220d4d Mon Sep 17 00:00:00 2001 From: Rick Kern Date: Sat, 20 May 2023 11:39:50 -0400 Subject: [PATCH 1077/2172] lavc/videotoolboxenc: warn when alpha quality not set Added a warn log when alpha quality cannot be set, but continue encoding. Signed-off-by: Rick Kern --- libavcodec/videotoolboxenc.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/libavcodec/videotoolboxenc.c b/libavcodec/videotoolboxenc.c index e93d45e1518..b017c90c363 100644 --- a/libavcodec/videotoolboxenc.c +++ b/libavcodec/videotoolboxenc.c @@ -1262,6 +1262,13 @@ static int vtenc_create_encoder(AVCodecContext *avctx, compat_keys.kVTCompressionPropertyKey_TargetQualityForAlpha, alpha_quality_num); CFRelease(alpha_quality_num); + + if (status) { + av_log(avctx, + AV_LOG_ERROR, + "Error setting alpha quality: %d\n", + status); + } } } From a62a3930c2d14acd3083af49f60741417d1d709f Mon Sep 17 00:00:00 2001 From: Lynne Date: Thu, 18 May 2023 14:42:14 +0200 Subject: [PATCH 1078/2172] swscale/ppc: remove hScale8To19_vsx Fails checkasm on a Power9 system. --- libswscale/ppc/swscale_vsx.c | 60 ------------------------------------ 1 file changed, 60 deletions(-) diff --git a/libswscale/ppc/swscale_vsx.c b/libswscale/ppc/swscale_vsx.c index 8152ce7f100..7080a16aee7 100644 --- a/libswscale/ppc/swscale_vsx.c +++ b/libswscale/ppc/swscale_vsx.c @@ -1858,64 +1858,6 @@ static void hcscale_fast_vsx(SwsContext *c, int16_t *dst1, int16_t *dst2, #undef HCSCALE -static void hScale8To19_vsx(SwsContext *c, int16_t *_dst, int dstW, - const uint8_t *src, const int16_t *filter, - const int32_t *filterPos, int filterSize) -{ - int i, j; - int32_t *dst = (int32_t *) _dst; - vec_s16 vfilter, vin; - vec_u8 vin8; - vec_s32 vout; - const vec_u8 vzero = vec_splat_u8(0); - const vec_u8 vunusedtab[8] = { - (vec_u8) {0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, - 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf}, - (vec_u8) {0x0, 0x1, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, - 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10}, - (vec_u8) {0x0, 0x1, 0x2, 0x3, 0x10, 0x10, 0x10, 0x10, - 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10}, - (vec_u8) {0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x10, 0x10, - 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10}, - (vec_u8) {0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, - 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10}, - (vec_u8) {0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, - 0x8, 0x9, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10}, - (vec_u8) {0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, - 0x8, 0x9, 0xa, 0xb, 0x10, 0x10, 0x10, 0x10}, - (vec_u8) {0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, - 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0x10, 0x10}, - }; - const vec_u8 vunused = vunusedtab[filterSize % 8]; - - if (filterSize == 1) { - for (i = 0; i < dstW; i++) { - int srcPos = filterPos[i]; - int val = 0; - for (j = 0; j < filterSize; j++) { - val += ((int)src[srcPos + j]) * filter[filterSize * i + j]; - } - dst[i] = FFMIN(val >> 3, (1 << 19) - 1); // the cubic equation does overflow ... - } - } else { - for (i = 0; i < dstW; i++) { - const int srcPos = filterPos[i]; - vout = vec_splat_s32(0); - for (j = 0; j < filterSize; j += 8) { - vin8 = vec_vsx_ld(0, &src[srcPos + j]); - vin = (vec_s16) vec_mergeh(vin8, vzero); - if (j + 8 > filterSize) // Remove the unused elements on the last round - vin = vec_perm(vin, (vec_s16) vzero, vunused); - - vfilter = vec_vsx_ld(0, &filter[filterSize * i + j]); - vout = vec_msums(vin, vfilter, vout); - } - vout = vec_sums(vout, (vec_s32) vzero); - dst[i] = FFMIN(vout[3] >> 3, (1 << 19) - 1); - } - } -} - static void hScale16To19_vsx(SwsContext *c, int16_t *_dst, int dstW, const uint8_t *_src, const int16_t *filter, const int32_t *filterPos, int filterSize) @@ -2092,8 +2034,6 @@ av_cold void ff_sws_init_swscale_vsx(SwsContext *c) c->hyscale_fast = hyscale_fast_vsx; c->hcscale_fast = hcscale_fast_vsx; } - } else { - c->hyScale = c->hcScale = hScale8To19_vsx; } } else { if (power8) { From 783270bfd12d7a524056e01f98d3472a3bb2d487 Mon Sep 17 00:00:00 2001 From: Lynne Date: Thu, 18 May 2023 16:18:16 +0200 Subject: [PATCH 1079/2172] checkasm: add h264chroma tests Checks all variants of put_h264_chroma and avg_h264_chroma. --- tests/checkasm/Makefile | 1 + tests/checkasm/checkasm.c | 3 ++ tests/checkasm/checkasm.h | 1 + tests/checkasm/h264chroma.c | 85 +++++++++++++++++++++++++++++++++++++ 4 files changed, 90 insertions(+) create mode 100644 tests/checkasm/h264chroma.c diff --git a/tests/checkasm/Makefile b/tests/checkasm/Makefile index 64d3c00168f..594db4df9d6 100644 --- a/tests/checkasm/Makefile +++ b/tests/checkasm/Makefile @@ -5,6 +5,7 @@ AVCODECOBJS-$(CONFIG_BLOCKDSP) += blockdsp.o AVCODECOBJS-$(CONFIG_BSWAPDSP) += bswapdsp.o AVCODECOBJS-$(CONFIG_FMTCONVERT) += fmtconvert.o AVCODECOBJS-$(CONFIG_G722DSP) += g722dsp.o +AVCODECOBJS-$(CONFIG_H264CHROMA) += h264chroma.o AVCODECOBJS-$(CONFIG_H264DSP) += h264dsp.o AVCODECOBJS-$(CONFIG_H264PRED) += h264pred.o AVCODECOBJS-$(CONFIG_H264QPEL) += h264qpel.o diff --git a/tests/checkasm/checkasm.c b/tests/checkasm/checkasm.c index d4df964d6bd..7389ebaee9f 100644 --- a/tests/checkasm/checkasm.c +++ b/tests/checkasm/checkasm.c @@ -105,6 +105,9 @@ static const struct { #if CONFIG_G722DSP { "g722dsp", checkasm_check_g722dsp }, #endif + #if CONFIG_H264CHROMA + { "h264chroma", checkasm_check_h264chroma }, + #endif #if CONFIG_H264DSP { "h264dsp", checkasm_check_h264dsp }, #endif diff --git a/tests/checkasm/checkasm.h b/tests/checkasm/checkasm.h index 03b27efa276..117d4dd35c4 100644 --- a/tests/checkasm/checkasm.h +++ b/tests/checkasm/checkasm.h @@ -56,6 +56,7 @@ void checkasm_check_flacdsp(void); void checkasm_check_float_dsp(void); void checkasm_check_fmtconvert(void); void checkasm_check_g722dsp(void); +void checkasm_check_h264chroma(void); void checkasm_check_h264dsp(void); void checkasm_check_h264pred(void); void checkasm_check_h264qpel(void); diff --git a/tests/checkasm/h264chroma.c b/tests/checkasm/h264chroma.c new file mode 100644 index 00000000000..1aa28c2ee19 --- /dev/null +++ b/tests/checkasm/h264chroma.c @@ -0,0 +1,85 @@ +/* + * Copyright (c) Lynne + * + * 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 +#include "checkasm.h" +#include "libavcodec/h264chroma.h" +#include "libavutil/mem_internal.h" +#include "libavutil/intreadwrite.h" + +#define SIZEOF_PIXEL ((bit_depth + 7) / 8) + +#define randomize_buffers(bit_depth) \ + do { \ + if (bit_depth == 8) { \ + for (int i = 0; i < 16*18*2; i++) \ + src[i] = rnd() & 0x3; \ + } else { \ + for (int i = 0; i < 16*18; i += 2) \ + AV_WN16(&src[i], rnd() & 0xFF); \ + } \ + } while (0) + +static void check_chroma_mc(void) +{ + H264ChromaContext h; + LOCAL_ALIGNED_32(uint8_t, src, [16 * 18 * 2]); + LOCAL_ALIGNED_32(uint8_t, dst0, [16 * 18 * 2]); + LOCAL_ALIGNED_32(uint8_t, dst1, [16 * 18 * 2]); + + declare_func_emms(AV_CPU_FLAG_MMX, void, uint8_t *dst, const uint8_t *src, + ptrdiff_t stride, int h, int x, int y); + + for (int bit_depth = 8; bit_depth <= 10; bit_depth++) { + ff_h264chroma_init(&h, bit_depth); + randomize_buffers(bit_depth); + for (int size = 0; size < 4; size++) { + +#define CHECK_CHROMA_MC(name) \ + do { \ + if (check_func(h.name## _pixels_tab[size], #name "_mc%d_%d", 1 << size, bit_depth)) { \ + for (int x = 0; x < 2; x++) { \ + for (int y = 0; y < 2; y++) { \ + memcpy(dst0, src, 16 * 18 * SIZEOF_PIXEL); \ + memcpy(dst1, src, 16 * 18 * SIZEOF_PIXEL); \ + call_ref(dst0, src, 16 * SIZEOF_PIXEL, 16, x, y); \ + call_new(dst1, src, 16 * SIZEOF_PIXEL, 16, x, y); \ + if (memcmp(dst0, dst1, 16 * 16 * SIZEOF_PIXEL)) { \ + fprintf(stderr, #name ": x:%i, y:%i\n", x, y); \ + fail(); \ + } \ + bench_new(dst1, src, 16 * SIZEOF_PIXEL, 16, x, y); \ + } \ + } \ + } \ + } while (0) + + CHECK_CHROMA_MC(put_h264_chroma); + CHECK_CHROMA_MC(avg_h264_chroma); + } + } +} + +void checkasm_check_h264chroma(void) +{ + check_chroma_mc(); + report("chroma_mc"); +} From b6066ceb8bd1e3ae1af733d22cb1b5c234c47a0b Mon Sep 17 00:00:00 2001 From: James Almer Date: Sat, 20 May 2023 18:26:13 -0300 Subject: [PATCH 1080/2172] fate/checkasm: add h264chroma test Signed-off-by: James Almer --- tests/fate/checkasm.mak | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/fate/checkasm.mak b/tests/fate/checkasm.mak index c208e2abca8..35ff1277ba7 100644 --- a/tests/fate/checkasm.mak +++ b/tests/fate/checkasm.mak @@ -11,6 +11,7 @@ FATE_CHECKASM = fate-checkasm-aacpsdsp \ fate-checkasm-float_dsp \ fate-checkasm-fmtconvert \ fate-checkasm-g722dsp \ + fate-checkasm-h264chroma \ fate-checkasm-h264dsp \ fate-checkasm-h264pred \ fate-checkasm-h264qpel \ From d81b6cbd4281baa649d75d239bf6e3423b5938a8 Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Sat, 20 May 2023 14:56:06 +0200 Subject: [PATCH 1081/2172] avcodec/gif_parser: fix possible wrong splitting of frames And properly signal keyframes. --- libavcodec/gif_parser.c | 34 ++++++++++++++++++++++------------ 1 file changed, 22 insertions(+), 12 deletions(-) diff --git a/libavcodec/gif_parser.c b/libavcodec/gif_parser.c index 4c18c00d7d8..aa07585f4cd 100644 --- a/libavcodec/gif_parser.c +++ b/libavcodec/gif_parser.c @@ -24,9 +24,6 @@ * GIF parser */ -#include "libavutil/bswap.h" -#include "libavutil/common.h" - #include "gif.h" #include "parser.h" @@ -50,11 +47,13 @@ typedef struct GIFParseContext { int block_size; int etype; int delay; + int keyframe; } GIFParseContext; static int gif_find_frame_end(GIFParseContext *g, const uint8_t *buf, int buf_size, void *logctx) { + ParseContext *pc = &g->pc; int index, next = END_NOT_FOUND; for (index = 0; index < buf_size; index++) { @@ -63,9 +62,10 @@ static int gif_find_frame_end(GIFParseContext *g, const uint8_t *buf, !memcmp(buf + index, gif89a_sig, 6)) { g->state = GIF_HEADER; g->found_sig++; + g->keyframe = 1; } else if (buf[index] == GIF_EXTENSION_INTRODUCER) { g->state = GIF_EXTENSION; - g->found_start = 1; + g->found_start = pc->frame_start_found = 1; } else if (buf[index] == GIF_IMAGE_SEPARATOR) { g->state = GIF_IMAGE; } else if (buf[index] == GIF_TRAILER) { @@ -93,7 +93,7 @@ static int gif_find_frame_end(GIFParseContext *g, const uint8_t *buf, } else if (g->state == GIF_EXTENSION) { if (g->found_start && g->found_end && g->found_sig) { next = index; - g->found_start = 0; + g->found_start = pc->frame_start_found = 0; g->found_end = 0; g->index = 0; g->gct_flag = 0; @@ -140,7 +140,7 @@ static int gif_find_frame_end(GIFParseContext *g, const uint8_t *buf, } g->index++; } else if (g->state == GIF_IMAGE) { - if (g->index == 8) { + if (g->index == 9) { g->gct_flag = !!(buf[index] & 0x80); g->gct_size = 3 * (1 << ((buf[index] & 0x07) + 1)); } @@ -165,14 +165,24 @@ static int gif_parse(AVCodecParserContext *s, AVCodecContext *avctx, GIFParseContext *g = s->priv_data; int next; - next = gif_find_frame_end(g, buf, buf_size, avctx); - if (ff_combine_frame(&g->pc, next, &buf, &buf_size) < 0) { - *poutbuf = NULL; - *poutbuf_size = 0; - return buf_size; + *poutbuf_size = 0; + *poutbuf = NULL; + + if (s->flags & PARSER_FLAG_COMPLETE_FRAMES) { + next = buf_size; + } else { + next = gif_find_frame_end(g, buf, buf_size, avctx); + if (ff_combine_frame(&g->pc, next, &buf, &buf_size) < 0) { + *poutbuf = NULL; + *poutbuf_size = 0; + return buf_size; + } } - s->duration = g->delay; + s->duration = g->delay ? g->delay : 10; + s->key_frame = g->keyframe; + s->pict_type = g->keyframe ? AV_PICTURE_TYPE_I : AV_PICTURE_TYPE_P; + g->keyframe = 0; *poutbuf = buf; *poutbuf_size = buf_size; From 3546f70410844708f8145f940be113f425e93e83 Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Mon, 15 May 2023 21:54:25 +0200 Subject: [PATCH 1082/2172] avfilter/src_movie: dr support --- libavfilter/src_movie.c | 57 +++++++++++++++++++++++++++++++++++++++-- 1 file changed, 55 insertions(+), 2 deletions(-) diff --git a/libavfilter/src_movie.c b/libavfilter/src_movie.c index 5937613d131..f0194c9a2a0 100644 --- a/libavfilter/src_movie.c +++ b/libavfilter/src_movie.c @@ -23,7 +23,6 @@ * @file * movie video source * - * @todo use direct rendering (no allocation of a new frame) * @todo support a PTS correction mechanism */ @@ -156,6 +155,56 @@ static AVStream *find_stream(void *log, AVFormatContext *avf, const char *spec) return found; } +static int get_buffer(AVCodecContext *avctx, AVFrame *frame, int flags) +{ + int linesize_align[AV_NUM_DATA_POINTERS]; + AVFilterLink *outlink = frame->opaque; + int w, h, ow, oh, copy = 0; + AVFrame *new; + + h = oh = frame->height; + w = ow = frame->width; + + copy = frame->format != outlink->format; + switch (avctx->codec_type) { + case AVMEDIA_TYPE_VIDEO: + if (w != outlink->w || h != outlink->h) + copy |= 1; + break; + case AVMEDIA_TYPE_AUDIO: + if (outlink->sample_rate != frame->sample_rate || + av_channel_layout_compare(&outlink->ch_layout, &frame->ch_layout)) + copy |= 1; + break; + } + + if (copy || !(avctx->codec->capabilities & AV_CODEC_CAP_DR1)) + return avcodec_default_get_buffer2(avctx, frame, flags); + + switch (avctx->codec_type) { + case AVMEDIA_TYPE_VIDEO: + avcodec_align_dimensions2(avctx, &w, &h, linesize_align); + new = ff_default_get_video_buffer(outlink, w, h); + break; + case AVMEDIA_TYPE_AUDIO: + new = ff_default_get_audio_buffer(outlink, frame->nb_samples); + break; + default: + return -1; + } + + av_frame_copy_props(new, frame); + av_frame_unref(frame); + av_frame_move_ref(frame, new); + av_frame_free(&new); + + frame->opaque = outlink; + frame->width = ow; + frame->height = oh; + + return 0; +} + static int open_stream(AVFilterContext *ctx, MovieStream *st, int dec_threads) { const AVCodec *codec; @@ -171,6 +220,8 @@ static int open_stream(AVFilterContext *ctx, MovieStream *st, int dec_threads) if (!st->codec_ctx) return AVERROR(ENOMEM); + st->codec_ctx->flags |= AV_CODEC_FLAG_COPY_OPAQUE; + st->codec_ctx->get_buffer2 = get_buffer; ret = avcodec_parameters_to_context(st->codec_ctx, st->st->codecpar); if (ret < 0) return ret; @@ -479,8 +530,10 @@ static int movie_decode_packet(AVFilterContext *ctx) /* send the packet to its decoder, if any */ pkt_out_id = pkt.stream_index > movie->max_stream_index ? -1 : movie->out_index[pkt.stream_index]; - if (pkt_out_id >= 0) + if (pkt_out_id >= 0) { + pkt.opaque = ctx->outputs[pkt_out_id]; ret = avcodec_send_packet(movie->st[pkt_out_id].codec_ctx, &pkt); + } av_packet_unref(&pkt); return ret; From 5fe6a0e5c74acc2cb65541e619d6aefd6ca44b07 Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Thu, 18 May 2023 00:59:31 +0200 Subject: [PATCH 1083/2172] avfilter/src_movie: switch to activate --- libavfilter/src_movie.c | 265 ++++++++++++++++++---------------------- 1 file changed, 122 insertions(+), 143 deletions(-) diff --git a/libavfilter/src_movie.c b/libavfilter/src_movie.c index f0194c9a2a0..f0d295d4bb7 100644 --- a/libavfilter/src_movie.c +++ b/libavfilter/src_movie.c @@ -45,6 +45,7 @@ #include "audio.h" #include "avfilter.h" +#include "filters.h" #include "formats.h" #include "internal.h" #include "video.h" @@ -54,6 +55,8 @@ typedef struct MovieStream { AVCodecContext *codec_ctx; int64_t discontinuity_threshold; int64_t last_pts; + AVFrame *frame; + int eof; } MovieStream; typedef struct MovieContext { @@ -70,8 +73,10 @@ typedef struct MovieContext { int64_t ts_offset; int dec_threads; + AVPacket *pkt; AVFormatContext *format_ctx; + int eof; 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 */ @@ -99,7 +104,6 @@ static const AVOption movie_options[]= { }; static int movie_config_output_props(AVFilterLink *outlink); -static int movie_request_frame(AVFilterLink *outlink); static AVStream *find_stream(void *log, AVFormatContext *avf, const char *spec) { @@ -330,6 +334,9 @@ static av_cold int movie_common_init(AVFilterContext *ctx) for (i = 0; i < movie->format_ctx->nb_streams; i++) movie->format_ctx->streams[i]->discard = AVDISCARD_ALL; + movie->pkt = av_packet_alloc(); + if (!movie->pkt) + return AVERROR(ENOMEM); movie->st = av_calloc(nb_streams, sizeof(*movie->st)); if (!movie->st) return AVERROR(ENOMEM); @@ -347,6 +354,10 @@ static av_cold int movie_common_init(AVFilterContext *ctx) movie->max_stream_index = FFMAX(movie->max_stream_index, st->index); movie->st[i].discontinuity_threshold = av_rescale_q(movie->discontinuity_threshold, AV_TIME_BASE_Q, st->time_base); + + movie->st[i].frame = av_frame_alloc(); + if (!movie->st[i].frame) + return AVERROR(ENOMEM); } if (av_strtok(NULL, "+", &cursor)) return AVERROR_BUG; @@ -365,7 +376,6 @@ static av_cold int movie_common_init(AVFilterContext *ctx) if (!pad.name) return AVERROR(ENOMEM); pad.config_props = movie_config_output_props; - pad.request_frame = movie_request_frame; if ((ret = ff_append_outpad_free_name(ctx, &pad)) < 0) return ret; if ( movie->st[i].st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO && @@ -394,7 +404,9 @@ static av_cold void movie_uninit(AVFilterContext *ctx) for (i = 0; i < ctx->nb_outputs; i++) { if (movie->st[i].st) avcodec_free_context(&movie->st[i].codec_ctx); + av_frame_free(&movie->st[i].frame); } + av_packet_free(&movie->pkt); av_freep(&movie->st); av_freep(&movie->out_index); if (movie->format_ctx) @@ -460,32 +472,6 @@ static int movie_config_output_props(AVFilterLink *outlink) return 0; } -static char *describe_frame_to_str(char *dst, size_t dst_size, - AVFrame *frame, enum AVMediaType frame_type, - AVFilterLink *link) -{ - switch (frame_type) { - case AVMEDIA_TYPE_VIDEO: - snprintf(dst, dst_size, - "video pts:%s time:%s size:%dx%d aspect:%d/%d", - av_ts2str(frame->pts), av_ts2timestr(frame->pts, &link->time_base), - frame->width, frame->height, - frame->sample_aspect_ratio.num, - frame->sample_aspect_ratio.den); - break; - case AVMEDIA_TYPE_AUDIO: - snprintf(dst, dst_size, - "audio pts:%s time:%s samples:%d", - av_ts2str(frame->pts), av_ts2timestr(frame->pts, &link->time_base), - frame->nb_samples); - break; - default: - snprintf(dst, dst_size, "%s BUG", av_get_media_type_string(frame_type)); - break; - } - return dst; -} - static int rewind_file(AVFilterContext *ctx) { MovieContext *movie = ctx->priv; @@ -507,147 +493,138 @@ static int rewind_file(AVFilterContext *ctx) return 0; } -static int movie_decode_packet(AVFilterContext *ctx) +static int flush_decoder(AVFilterContext *ctx, int i) { MovieContext *movie = ctx->priv; - AVPacket pkt = { 0 }; - int pkt_out_id, ret; - - /* read a new packet from input stream */ - ret = av_read_frame(movie->format_ctx, &pkt); - if (ret == AVERROR_EOF) { - /* EOF -> set all decoders for flushing */ - for (int i = 0; i < ctx->nb_outputs; i++) { - ret = avcodec_send_packet(movie->st[i].codec_ctx, NULL); - if (ret < 0 && ret != AVERROR_EOF) - return ret; - } - - return 0; - } else if (ret < 0) - return ret; + AVCodecContext *dec = movie->st[i].codec_ctx; - /* send the packet to its decoder, if any */ - pkt_out_id = pkt.stream_index > movie->max_stream_index ? -1 : - movie->out_index[pkt.stream_index]; - if (pkt_out_id >= 0) { - pkt.opaque = ctx->outputs[pkt_out_id]; - ret = avcodec_send_packet(movie->st[pkt_out_id].codec_ctx, &pkt); - } - av_packet_unref(&pkt); - - return ret; + return avcodec_send_packet(dec, NULL); } -/** - * Try to push a frame to the requested output. - * - * @param ctx filter context - * @param out_id number of output where a frame is wanted; - * @return 0 if a frame was pushed on the requested output, - * AVERROR(EAGAIN) if the decoder requires more input - * AVERROR(EOF) if the decoder has been completely flushed - * <0 AVERROR code - */ -static int movie_push_frame(AVFilterContext *ctx, unsigned out_id) +static int decode_packet(AVFilterContext *ctx, int i) { - MovieContext *movie = ctx->priv; - MovieStream *st = &movie->st[out_id]; - AVFilterLink *outlink = ctx->outputs[out_id]; - AVFrame *frame; - int ret; - - frame = av_frame_alloc(); - if (!frame) - return AVERROR(ENOMEM); - - ret = avcodec_receive_frame(st->codec_ctx, frame); - if (ret < 0) { - if (ret != AVERROR_EOF && ret != AVERROR(EAGAIN)) - av_log(ctx, AV_LOG_WARNING, "Decode error: %s\n", av_err2str(ret)); - - av_frame_free(&frame); - return ret; + AVFilterLink *outlink = ctx->outputs[i]; + MovieContext *movie = ctx->priv; + MovieStream *st = &movie->st[i]; + AVCodecContext *dec = movie->st[i].codec_ctx; + AVFrame *frame = movie->st[i].frame; + AVPacket *pkt = movie->pkt; + int ret = 0; + + // submit the packet to the decoder + if (!movie->eof) { + ret = avcodec_send_packet(dec, pkt); + if (ret < 0) + return ret; } - frame->pts = frame->best_effort_timestamp; - if (frame->pts != AV_NOPTS_VALUE) { - if (movie->ts_offset) - frame->pts += av_rescale_q_rnd(movie->ts_offset, AV_TIME_BASE_Q, outlink->time_base, AV_ROUND_UP); - if (st->discontinuity_threshold) { - if (st->last_pts != AV_NOPTS_VALUE) { - int64_t diff = frame->pts - st->last_pts; - if (diff < 0 || diff > st->discontinuity_threshold) { - av_log(ctx, AV_LOG_VERBOSE, "Discontinuity in stream:%d diff:%"PRId64"\n", out_id, diff); - movie->ts_offset += av_rescale_q_rnd(-diff, outlink->time_base, AV_TIME_BASE_Q, AV_ROUND_UP); - frame->pts -= diff; + // get all the available frames from the decoder + if (ret >= 0) { + ret = avcodec_receive_frame(dec, frame); + if (ret < 0) { + // those two return values are special and mean there is no output + // frame available, but there were no errors during decoding + if (ret == AVERROR_EOF || ret == AVERROR(EAGAIN)) + return 0; + return ret; + } + + frame->pts = frame->best_effort_timestamp; + if (frame->pts != AV_NOPTS_VALUE) { + if (movie->ts_offset) + frame->pts += av_rescale_q_rnd(movie->ts_offset, AV_TIME_BASE_Q, outlink->time_base, AV_ROUND_UP); + if (st->discontinuity_threshold) { + if (st->last_pts != AV_NOPTS_VALUE) { + int64_t diff = frame->pts - st->last_pts; + if (diff < 0 || diff > st->discontinuity_threshold) { + av_log(ctx, AV_LOG_VERBOSE, "Discontinuity in stream:%d diff:%"PRId64"\n", i, diff); + movie->ts_offset += av_rescale_q_rnd(-diff, outlink->time_base, AV_TIME_BASE_Q, AV_ROUND_UP); + frame->pts -= diff; + } } } + st->last_pts = frame->pts; } - st->last_pts = frame->pts; - } - ff_dlog(ctx, "movie_push_frame(): file:'%s' %s\n", movie->file_name, - describe_frame_to_str((char[1024]){0}, 1024, frame, - st->st->codecpar->codec_type, outlink)); - - if (st->st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) { - if (frame->format != outlink->format) { - av_log(ctx, AV_LOG_ERROR, "Format changed %s -> %s, discarding frame\n", - av_get_pix_fmt_name(outlink->format), - av_get_pix_fmt_name(frame->format) - ); - av_frame_free(&frame); - return 0; - } + ret = ff_filter_frame(outlink, av_frame_clone(frame)); + if (ret < 0) + return ret; + if (ret == 0) + return 1; } - ret = ff_filter_frame(outlink, frame); - if (ret < 0) - return ret; return 0; } -static int movie_request_frame(AVFilterLink *outlink) +static int activate(AVFilterContext *ctx) { - AVFilterContext *ctx = outlink->src; - MovieContext *movie = ctx->priv; - unsigned out_id = FF_OUTLINK_IDX(outlink); + MovieContext *movie = ctx->priv; + int wanted = 0, ret; - while (1) { - int got_eagain = 0, got_eof = 0; - int ret = 0; + for (int i = 0; i < ctx->nb_outputs; i++) { + if (ff_outlink_frame_wanted(ctx->outputs[i])) + wanted++; + } - /* check all decoders for available output */ - for (int i = 0; i < ctx->nb_outputs; i++) { - ret = movie_push_frame(ctx, i); - if (ret == AVERROR(EAGAIN)) - got_eagain++; - else if (ret == AVERROR_EOF) - got_eof++; - else if (ret < 0) - return ret; - else if (i == out_id) - return 0; + if (wanted == 0) + return FFERROR_NOT_READY; + + if (!movie->eof) { + ret = av_read_frame(movie->format_ctx, movie->pkt); + if (ret < 0) { + movie->eof = 1; + for (int i = 0; i < ctx->nb_outputs; i++) + flush_decoder(ctx, i); + ff_filter_set_ready(ctx, 100); + return 0; + } else { + int pkt_out_id = movie->pkt->stream_index > movie->max_stream_index ? -1 : + movie->out_index[movie->pkt->stream_index]; + + if (pkt_out_id >= 0) { + movie->pkt->opaque = ctx->outputs[pkt_out_id]; + ret = decode_packet(ctx, pkt_out_id); + } + av_packet_unref(movie->pkt); + ff_filter_set_ready(ctx, 100); + return (ret <= 0) ? ret : 0; } + } else { + int nb_eofs = 0; - if (got_eagain) { - /* all decoders require more input -> read a new packet */ - ret = movie_decode_packet(ctx); + for (int i = 0; i < ctx->nb_outputs; i++) { + if (!movie->st[i].eof) { + ret = decode_packet(ctx, i); + if (ret <= 0) + movie->st[i].eof = 1; + } + nb_eofs += movie->st[i].eof == 1; + } + if (nb_eofs == ctx->nb_outputs && movie->loop_count != 1) { + ret = rewind_file(ctx); if (ret < 0) return ret; - } else if (got_eof) { - /* all decoders flushed */ - if (movie->loop_count != 1) { - ret = rewind_file(ctx); - if (ret < 0) - return ret; - movie->loop_count -= movie->loop_count > 1; - av_log(ctx, AV_LOG_VERBOSE, "Stream finished, looping.\n"); - continue; + movie->loop_count -= movie->loop_count > 1; + av_log(ctx, AV_LOG_VERBOSE, "Stream finished, looping.\n"); + ff_filter_set_ready(ctx, 100); + for (int i = 0; i < ctx->nb_outputs; i++) + movie->st[i].eof = 0; + movie->eof = 0; + return 0; + } else { + for (int i = 0; i < ctx->nb_outputs; i++) { + if (movie->st[i].eof) { + ff_outlink_set_status(ctx->outputs[i], AVERROR_EOF, movie->st[i].last_pts); + nb_eofs++; + } } - return AVERROR_EOF; } + + if (nb_eofs < ctx->nb_outputs) + ff_filter_set_ready(ctx, 100); + return 0; } + + return FFERROR_NOT_READY; } static int process_command(AVFilterContext *ctx, const char *cmd, const char *args, @@ -702,6 +679,7 @@ const AVFilter ff_avsrc_movie = { .priv_size = sizeof(MovieContext), .priv_class = &movie_class, .init = movie_common_init, + .activate = activate, .uninit = movie_uninit, FILTER_QUERY_FUNC(movie_query_formats), @@ -721,6 +699,7 @@ const AVFilter ff_avsrc_amovie = { .priv_class = &movie_class, .priv_size = sizeof(MovieContext), .init = movie_common_init, + .activate = activate, .uninit = movie_uninit, FILTER_QUERY_FUNC(movie_query_formats), From ddc176d0eed7bd140c134c2b0923b575b13570c0 Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Fri, 12 May 2023 23:37:59 +0200 Subject: [PATCH 1084/2172] avcodec/elbg: fix integer overflows Fixes #9977 --- libavcodec/elbg.c | 56 ++++++++++++++++++++++++++++++----------------- 1 file changed, 36 insertions(+), 20 deletions(-) diff --git a/libavcodec/elbg.c b/libavcodec/elbg.c index d97a7bc3f99..7a6a84fb6ba 100644 --- a/libavcodec/elbg.c +++ b/libavcodec/elbg.c @@ -44,13 +44,13 @@ typedef struct cell_s { * ELBG internal data */ typedef struct ELBGContext { - int64_t error; + int error; int dim; int num_cb; int *codebook; cell **cells; - int64_t *utility; - int64_t *utility_inc; + int *utility; + int *utility_inc; int *nearest_cb; int *points; int *temp_points; @@ -75,9 +75,12 @@ static inline int distance_limited(int *a, int *b, int dim, int limit) { int i, dist=0; for (i=0; i limit) - return INT_MAX; + int64_t distance = a[i] - b[i]; + + distance *= distance; + if (dist >= limit - distance) + return limit; + dist += distance; } return dist; @@ -97,8 +100,12 @@ static inline void vect_division(int *res, int *vect, int div, int dim) static int eval_error_cell(ELBGContext *elbg, int *centroid, cell *cells) { int error=0; - for (; cells; cells=cells->next) - error += distance_limited(centroid, elbg->points + cells->index*elbg->dim, elbg->dim, INT_MAX); + for (; cells; cells=cells->next) { + int distance = distance_limited(centroid, elbg->points + cells->index*elbg->dim, elbg->dim, INT_MAX); + if (error >= INT_MAX - distance) + return INT_MAX; + error += distance; + } return error; } @@ -178,10 +185,13 @@ static int simple_lbg(ELBGContext *elbg, int dist[2] = {distance_limited(centroid[0], points + tempcell->index*dim, dim, INT_MAX), distance_limited(centroid[1], points + tempcell->index*dim, dim, INT_MAX)}; int idx = dist[0] > dist[1]; - newutility[idx] += dist[idx]; + if (newutility[idx] >= INT_MAX - dist[idx]) + newutility[idx] = INT_MAX; + else + newutility[idx] += dist[idx]; } - return newutility[0] + newutility[1]; + return (newutility[0] >= INT_MAX - newutility[1]) ? INT_MAX : newutility[0] + newutility[1]; } static void get_new_centroids(ELBGContext *elbg, int huc, int *newcentroid_i, @@ -253,9 +263,9 @@ static void evaluate_utility_inc(ELBGContext *elbg) int64_t inc=0; for (int i = 0; i < elbg->num_cb; i++) { - if (elbg->num_cb * elbg->utility[i] > elbg->error) + if (elbg->num_cb * (int64_t)elbg->utility[i] > elbg->error) inc += elbg->utility[i]; - elbg->utility_inc[i] = inc; + elbg->utility_inc[i] = FFMIN(inc, INT_MAX); } } @@ -278,7 +288,7 @@ static void update_utility_and_n_cb(ELBGContext *elbg, int idx, int newutility) */ static void try_shift_candidate(ELBGContext *elbg, int idx[3]) { - int j, k, cont=0; + int j, k, cont=0, tmp; int64_t olderror=0, newerror; int newutility[3]; int *newcentroid[3] = { @@ -305,12 +315,17 @@ static void try_shift_candidate(ELBGContext *elbg, int idx[3]) get_new_centroids(elbg, idx[1], newcentroid[0], newcentroid[1]); newutility[2] = eval_error_cell(elbg, newcentroid[2], elbg->cells[idx[0]]); - newutility[2] += eval_error_cell(elbg, newcentroid[2], elbg->cells[idx[2]]); + tmp = eval_error_cell(elbg, newcentroid[2], elbg->cells[idx[2]]); + newutility[2] = (tmp >= INT_MAX - newutility[2]) ? INT_MAX : newutility[2] + tmp; newerror = newutility[2]; - newerror += simple_lbg(elbg, elbg->dim, newcentroid, newutility, elbg->points, + tmp = simple_lbg(elbg, elbg->dim, newcentroid, newutility, elbg->points, elbg->cells[idx[1]]); + if (tmp >= INT_MAX - newerror) + newerror = INT_MAX; + else + newerror += tmp; if (olderror > newerror) { shift_codebook(elbg, idx, newcentroid); @@ -334,7 +349,7 @@ static void do_shiftings(ELBGContext *elbg) evaluate_utility_inc(elbg); for (idx[0]=0; idx[0] < elbg->num_cb; idx[0]++) - if (elbg->num_cb * elbg->utility[idx[0]] < elbg->error) { + if (elbg->num_cb * (int64_t)elbg->utility[idx[0]] < elbg->error) { if (elbg->utility_inc[elbg->num_cb - 1] == 0) return; @@ -352,9 +367,9 @@ static void do_elbg(ELBGContext *av_restrict elbg, int *points, int numpoints, int *const size_part = elbg->size_part; int i, j, steps = 0; int best_idx = 0; - int64_t last_error; + int last_error; - elbg->error = INT64_MAX; + elbg->error = INT_MAX; elbg->points = points; do { @@ -382,8 +397,9 @@ static void do_elbg(ELBGContext *av_restrict elbg, int *points, int numpoints, } } elbg->nearest_cb[i] = best_idx; - elbg->error += best_dist; - elbg->utility[elbg->nearest_cb[i]] += best_dist; + elbg->error = (elbg->error >= INT_MAX - best_dist) ? INT_MAX : elbg->error + best_dist; + elbg->utility[elbg->nearest_cb[i]] = (elbg->utility[elbg->nearest_cb[i]] >= INT_MAX - best_dist) ? + INT_MAX : elbg->utility[elbg->nearest_cb[i]] + best_dist; free_cells->index = i; free_cells->next = elbg->cells[elbg->nearest_cb[i]]; elbg->cells[elbg->nearest_cb[i]] = free_cells; From fcabfcbf6fb061c97cff1d5ab52e55350ad00bb8 Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Sun, 21 May 2023 11:28:27 +0200 Subject: [PATCH 1085/2172] avcodec/wavpackenc: unbreak encoding 8bit pcm Otherwise the reference decoder reports crc errors. --- libavcodec/wavpackenc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavcodec/wavpackenc.c b/libavcodec/wavpackenc.c index 3d2d45360de..9271e87990e 100644 --- a/libavcodec/wavpackenc.c +++ b/libavcodec/wavpackenc.c @@ -2824,7 +2824,7 @@ static void fill_buffer(WavPackEncodeContext *s, switch (s->avctx->sample_fmt) { case AV_SAMPLE_FMT_U8P: - COPY_SAMPLES(int8_t, 0x80, 0); + COPY_SAMPLES(uint8_t, 0x80, 0); break; case AV_SAMPLE_FMT_S16P: COPY_SAMPLES(int16_t, 0, 0); From b528e098a9345ee44fb7088027dc3945b59d65c8 Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Sun, 21 May 2023 12:33:21 +0200 Subject: [PATCH 1086/2172] avfilter/f_graphmonitor: show also current timeline status of filter --- doc/filters.texi | 5 +++++ libavfilter/f_graphmonitor.c | 26 +++++++++++++++++++++----- 2 files changed, 26 insertions(+), 5 deletions(-) diff --git a/doc/filters.texi b/doc/filters.texi index c00012be268..393297c418b 100644 --- a/doc/filters.texi +++ b/doc/filters.texi @@ -14651,6 +14651,8 @@ Show only filters with queued frames. Show only filters with non-zero stats. @item noeof Show only filters with non-eof stat. +@item nodisabled +Show only filters that are enabled in timeline. @end table @item flags, f @@ -14705,6 +14707,9 @@ Display number of samples given out from filter. @item sample_count_delta Display delta number of samples between above two values. + +@item disabled +Show the timeline filter status. @end table @item rate, r diff --git a/libavfilter/f_graphmonitor.c b/libavfilter/f_graphmonitor.c index 0fe14f885e4..68c343d75e0 100644 --- a/libavfilter/f_graphmonitor.c +++ b/libavfilter/f_graphmonitor.c @@ -54,6 +54,7 @@ typedef struct GraphMonitorContext { uint8_t red[4]; uint8_t green[4]; uint8_t blue[4]; + uint8_t gray[4]; uint8_t bg[4]; CacheItem *cache; @@ -66,7 +67,8 @@ enum { MODE_COMPACT = 1, MODE_NOZERO = 2, MODE_NOEOF = 4, - MODE_MAX = 7 + MODE_NODISABLED = 8, + MODE_MAX = 15 }; enum { @@ -86,6 +88,7 @@ enum { FLAG_TIME_DELTA = 1 << 13, FLAG_FC_DELTA = 1 << 14, FLAG_SC_DELTA = 1 << 15, + FLAG_DISABLED = 1 << 16, }; #define OFFSET(x) offsetof(GraphMonitorContext, x) @@ -103,6 +106,7 @@ static const AVOption graphmonitor_options[] = { { "compact", NULL, 0, AV_OPT_TYPE_CONST, {.i64=MODE_COMPACT},0, 0, VFR, "mode" }, { "nozero", NULL, 0, AV_OPT_TYPE_CONST, {.i64=MODE_NOZERO}, 0, 0, VFR, "mode" }, { "noeof", NULL, 0, AV_OPT_TYPE_CONST, {.i64=MODE_NOEOF}, 0, 0, VFR, "mode" }, + { "nodisabled",NULL,0,AV_OPT_TYPE_CONST, {.i64=MODE_NODISABLED},0,0,VFR,"mode" }, { "flags", "set flags", OFFSET(flags), AV_OPT_TYPE_FLAGS, {.i64=FLAG_QUEUE}, 0, INT_MAX, VFR, "flags" }, { "f", "set flags", OFFSET(flags), AV_OPT_TYPE_FLAGS, {.i64=FLAG_QUEUE}, 0, INT_MAX, VFR, "flags" }, { "queue", NULL, 0, AV_OPT_TYPE_CONST, {.i64=FLAG_QUEUE}, 0, 0, VFR, "flags" }, @@ -121,6 +125,7 @@ static const AVOption graphmonitor_options[] = { { "sample_count_in", NULL, 0, AV_OPT_TYPE_CONST, {.i64=FLAG_SCOUT}, 0, 0, VFR, "flags" }, { "sample_count_out", NULL, 0, AV_OPT_TYPE_CONST, {.i64=FLAG_SCIN}, 0, 0, VFR, "flags" }, { "sample_count_delta",NULL,0, AV_OPT_TYPE_CONST, {.i64=FLAG_SC_DELTA},0, 0, VFR, "flags" }, + { "disabled", NULL, 0, AV_OPT_TYPE_CONST, {.i64=FLAG_DISABLED},0, 0, VFR, "flags" }, { "rate", "set video rate", OFFSET(frame_rate), AV_OPT_TYPE_VIDEO_RATE, {.str = "25"}, 0, INT_MAX, VF }, { "r", "set video rate", OFFSET(frame_rate), AV_OPT_TYPE_VIDEO_RATE, {.str = "25"}, 0, INT_MAX, VF }, { NULL } @@ -233,7 +238,9 @@ static int filter_have_queued(AVFilterContext *filter) return 0; } -static int draw_items(AVFilterContext *ctx, AVFrame *out, +static int draw_items(AVFilterContext *ctx, + AVFilterContext *filter, + AVFrame *out, int xpos, int ypos, AVFilterLink *l, size_t frames) @@ -335,11 +342,16 @@ static int draw_items(AVFilterContext *ctx, AVFrame *out, drawtext(out, xpos, ypos, buffer, s->white); xpos += strlen(buffer) * 8; } - if (s->flags & FLAG_EOF && ff_outlink_get_status(l)) { + if ((s->flags & FLAG_EOF) && ff_outlink_get_status(l)) { snprintf(buffer, sizeof(buffer)-1, " | eof"); drawtext(out, xpos, ypos, buffer, s->blue); xpos += strlen(buffer) * 8; } + if ((s->flags & FLAG_DISABLED) && filter->is_disabled) { + snprintf(buffer, sizeof(buffer)-1, " | off"); + drawtext(out, xpos, ypos, buffer, s->gray); + xpos += strlen(buffer) * 8; + } s->cache[s->cache_index].previous_pts_us = l->current_pts_us; @@ -380,6 +392,9 @@ static int create_frame(AVFilterContext *ctx, int64_t pts) if ((s->mode & MODE_NOEOF) && filter_have_eof(filter)) continue; + if ((s->mode & MODE_NODISABLED) && filter->is_disabled) + continue; + xpos = 0; drawtext(out, xpos, ypos, filter->name, s->white); xpos += strlen(filter->name) * 8 + 10; @@ -401,7 +416,7 @@ static int create_frame(AVFilterContext *ctx, int64_t pts) xpos += strlen(buffer) * 8; drawtext(out, xpos, ypos, l->src->name, s->white); xpos += strlen(l->src->name) * 8 + 10; - ret = draw_items(ctx, out, xpos, ypos, l, frames); + ret = draw_items(ctx, filter, out, xpos, ypos, l, frames); if (ret < 0) goto error; ypos += 10; @@ -424,7 +439,7 @@ static int create_frame(AVFilterContext *ctx, int64_t pts) xpos += strlen(buffer) * 8; drawtext(out, xpos, ypos, l->dst->name, s->white); xpos += strlen(l->dst->name) * 8 + 10; - ret = draw_items(ctx, out, xpos, ypos, l, frames); + ret = draw_items(ctx, filter, out, xpos, ypos, l, frames); if (ret < 0) goto error; ypos += 10; @@ -489,6 +504,7 @@ static int config_output(AVFilterLink *outlink) s->red[0] = 255; s->green[1] = 255; s->blue[2] = 255; + s->gray[0] = s->gray[1] = s->gray[2] = 128; s->pts = AV_NOPTS_VALUE; s->next_pts = AV_NOPTS_VALUE; outlink->w = s->w; From 65fe18040a90ab1b206bfedec08308940436c590 Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Sun, 21 May 2023 12:39:05 +0200 Subject: [PATCH 1087/2172] avfilter/f_graphmonitor: add flags option shortcuts --- doc/filters.texi | 6 ++++++ libavfilter/f_graphmonitor.c | 4 +++- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/doc/filters.texi b/doc/filters.texi index 393297c418b..ddc8529bbe9 100644 --- a/doc/filters.texi +++ b/doc/filters.texi @@ -14660,6 +14660,12 @@ Set flags which enable which stats are shown in video. Available values for flags are: @table @samp +@item none +All flags turned off. + +@item all +All flags turned on. + @item queue Display number of queued frames in each link. diff --git a/libavfilter/f_graphmonitor.c b/libavfilter/f_graphmonitor.c index 68c343d75e0..78a365822fe 100644 --- a/libavfilter/f_graphmonitor.c +++ b/libavfilter/f_graphmonitor.c @@ -72,6 +72,7 @@ enum { }; enum { + FLAG_NONE = 0 << 0, FLAG_QUEUE = 1 << 0, FLAG_FCIN = 1 << 1, FLAG_FCOUT = 1 << 2, @@ -109,7 +110,8 @@ static const AVOption graphmonitor_options[] = { { "nodisabled",NULL,0,AV_OPT_TYPE_CONST, {.i64=MODE_NODISABLED},0,0,VFR,"mode" }, { "flags", "set flags", OFFSET(flags), AV_OPT_TYPE_FLAGS, {.i64=FLAG_QUEUE}, 0, INT_MAX, VFR, "flags" }, { "f", "set flags", OFFSET(flags), AV_OPT_TYPE_FLAGS, {.i64=FLAG_QUEUE}, 0, INT_MAX, VFR, "flags" }, - { "queue", NULL, 0, AV_OPT_TYPE_CONST, {.i64=FLAG_QUEUE}, 0, 0, VFR, "flags" }, + { "none", NULL, 0, AV_OPT_TYPE_CONST, {.i64=FLAG_NONE}, 0, 0, VFR, "flags" }, + { "all", NULL, 0, AV_OPT_TYPE_CONST, {.i64=INT_MAX}, 0, 0, VFR, "flags" }, { "frame_count_in", NULL, 0, AV_OPT_TYPE_CONST, {.i64=FLAG_FCOUT}, 0, 0, VFR, "flags" }, { "frame_count_out", NULL, 0, AV_OPT_TYPE_CONST, {.i64=FLAG_FCIN}, 0, 0, VFR, "flags" }, { "frame_count_delta",NULL, 0, AV_OPT_TYPE_CONST, {.i64=FLAG_FC_DELTA},0, 0, VFR, "flags" }, From 1aeefc4c06de5408c24bc3f5db4d10fdfd9c27c0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kacper=20Michaj=C5=82ow?= Date: Wed, 17 May 2023 21:45:03 +0200 Subject: [PATCH 1088/2172] lavfi/vf_libplacebo: allow linking to shared library with dllimport Address of dll imported variables can't be used for constant initialization in C language modes. --- libavfilter/vf_libplacebo.c | 39 ++++++++++++++++++++----------------- 1 file changed, 21 insertions(+), 18 deletions(-) diff --git a/libavfilter/vf_libplacebo.c b/libavfilter/vf_libplacebo.c index 94e49aa4652..f26d0126beb 100644 --- a/libavfilter/vf_libplacebo.c +++ b/libavfilter/vf_libplacebo.c @@ -56,23 +56,6 @@ enum { TONE_MAP_COUNT, }; -static const struct pl_tone_map_function * const tonemapping_funcs[TONE_MAP_COUNT] = { - [TONE_MAP_AUTO] = &pl_tone_map_auto, - [TONE_MAP_CLIP] = &pl_tone_map_clip, -#if PL_API_VER >= 246 - [TONE_MAP_ST2094_40] = &pl_tone_map_st2094_40, - [TONE_MAP_ST2094_10] = &pl_tone_map_st2094_10, -#endif - [TONE_MAP_BT2390] = &pl_tone_map_bt2390, - [TONE_MAP_BT2446A] = &pl_tone_map_bt2446a, - [TONE_MAP_SPLINE] = &pl_tone_map_spline, - [TONE_MAP_REINHARD] = &pl_tone_map_reinhard, - [TONE_MAP_MOBIUS] = &pl_tone_map_mobius, - [TONE_MAP_HABLE] = &pl_tone_map_hable, - [TONE_MAP_GAMMA] = &pl_tone_map_gamma, - [TONE_MAP_LINEAR] = &pl_tone_map_linear, -}; - static const char *const var_names[] = { "in_w", "iw", ///< width of the input video frame "in_h", "ih", ///< height of the input video frame @@ -269,6 +252,26 @@ static void pl_av_log(void *log_ctx, enum pl_log_level level, const char *msg) av_log(log_ctx, av_lev, "%s\n", msg); } +static const struct pl_tone_map_function *pl_get_tonemapping_func(int tm) { + switch (tm) { + case TONE_MAP_AUTO: return &pl_tone_map_auto; + case TONE_MAP_CLIP: return &pl_tone_map_clip; +#if PL_API_VER >= 246 + case TONE_MAP_ST2094_40: return &pl_tone_map_st2094_40; + case TONE_MAP_ST2094_10: return &pl_tone_map_st2094_10; +#endif + case TONE_MAP_BT2390: return &pl_tone_map_bt2390; + case TONE_MAP_BT2446A: return &pl_tone_map_bt2446a; + case TONE_MAP_SPLINE: return &pl_tone_map_spline; + case TONE_MAP_REINHARD: return &pl_tone_map_reinhard; + case TONE_MAP_MOBIUS: return &pl_tone_map_mobius; + case TONE_MAP_HABLE: return &pl_tone_map_hable; + case TONE_MAP_GAMMA: return &pl_tone_map_gamma; + case TONE_MAP_LINEAR: return &pl_tone_map_linear; + default: av_assert0(0); + } +} + static int parse_shader(AVFilterContext *avctx, const void *shader, size_t len) { LibplaceboContext *s = avctx->priv; @@ -365,7 +368,7 @@ static int update_settings(AVFilterContext *ctx) s->color_map_params = *pl_color_map_params( .intent = s->intent, .gamut_mode = gamut_mode, - .tone_mapping_function = tonemapping_funcs[s->tonemapping], + .tone_mapping_function = pl_get_tonemapping_func(s->tonemapping), .tone_mapping_param = s->tonemapping_param, .tone_mapping_mode = tonemapping_mode, .inverse_tone_mapping = s->inverse_tonemapping, From f055345595c6bbaf17525190a599f174d8587069 Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Sun, 21 May 2023 13:52:42 +0200 Subject: [PATCH 1089/2172] avfilter/f_graphmonitor: speed-up clear_image() --- libavfilter/f_graphmonitor.c | 49 +++++++++++++++++++++--------------- 1 file changed, 29 insertions(+), 20 deletions(-) diff --git a/libavfilter/f_graphmonitor.c b/libavfilter/f_graphmonitor.c index 78a365822fe..9f22cbb15bd 100644 --- a/libavfilter/f_graphmonitor.c +++ b/libavfilter/f_graphmonitor.c @@ -163,11 +163,18 @@ static int query_formats(AVFilterContext *ctx) static void clear_image(GraphMonitorContext *s, AVFrame *out, AVFilterLink *outlink) { + const int h = out->height; + const int w = out->width; + uint8_t *dst = out->data[0]; int bg = AV_RN32(s->bg); - for (int i = 0; i < out->height; i++) - for (int j = 0; j < out->width; j++) - AV_WN32(out->data[0] + i * out->linesize[0] + j * 4, bg); + for (int j = 0; j < w; j++) + AV_WN32(dst + j * 4, bg); + dst += out->linesize[0]; + for (int i = 1; i < h; i++) { + memcpy(dst, out->data[0], w * 4); + dst += out->linesize[0]; + } } static void drawtext(AVFrame *pic, int x, int y, const char *txt, uint8_t *color) @@ -250,9 +257,11 @@ static int draw_items(AVFilterContext *ctx, GraphMonitorContext *s = ctx->priv; int64_t previous_pts_us = s->cache[s->cache_index].previous_pts_us; int64_t current_pts_us = l->current_pts_us; + const int flags = s->flags; + const int mode = s->mode; char buffer[1024] = { 0 }; - if (s->flags & FLAG_FMT) { + if (flags & FLAG_FMT) { if (l->type == AVMEDIA_TYPE_VIDEO) { snprintf(buffer, sizeof(buffer)-1, " | format: %s", av_get_pix_fmt_name(l->format)); @@ -263,7 +272,7 @@ static int draw_items(AVFilterContext *ctx, drawtext(out, xpos, ypos, buffer, s->white); xpos += strlen(buffer) * 8; } - if (s->flags & FLAG_SIZE) { + if (flags & FLAG_SIZE) { if (l->type == AVMEDIA_TYPE_VIDEO) { snprintf(buffer, sizeof(buffer)-1, " | size: %dx%d", l->w, l->h); } else if (l->type == AVMEDIA_TYPE_AUDIO) { @@ -272,7 +281,7 @@ static int draw_items(AVFilterContext *ctx, drawtext(out, xpos, ypos, buffer, s->white); xpos += strlen(buffer) * 8; } - if (s->flags & FLAG_RATE) { + if (flags & FLAG_RATE) { if (l->type == AVMEDIA_TYPE_VIDEO) { snprintf(buffer, sizeof(buffer)-1, " | fps: %d/%d", l->frame_rate.num, l->frame_rate.den); } else if (l->type == AVMEDIA_TYPE_AUDIO) { @@ -281,12 +290,12 @@ static int draw_items(AVFilterContext *ctx, drawtext(out, xpos, ypos, buffer, s->white); xpos += strlen(buffer) * 8; } - if (s->flags & FLAG_TB) { + if (flags & FLAG_TB) { snprintf(buffer, sizeof(buffer)-1, " | tb: %d/%d", l->time_base.num, l->time_base.den); drawtext(out, xpos, ypos, buffer, s->white); xpos += strlen(buffer) * 8; } - if ((s->flags & FLAG_QUEUE) && (!(s->mode & MODE_NOZERO) || frames)) { + if ((flags & FLAG_QUEUE) && (!(mode & MODE_NOZERO) || frames)) { snprintf(buffer, sizeof(buffer)-1, " | queue: "); drawtext(out, xpos, ypos, buffer, s->white); xpos += strlen(buffer) * 8; @@ -294,62 +303,62 @@ static int draw_items(AVFilterContext *ctx, drawtext(out, xpos, ypos, buffer, frames > 0 ? frames >= 10 ? frames >= 50 ? s->red : s->yellow : s->green : s->white); xpos += strlen(buffer) * 8; } - if ((s->flags & FLAG_FCIN) && (!(s->mode & MODE_NOZERO) || l->frame_count_in)) { + if ((flags & FLAG_FCIN) && (!(mode & MODE_NOZERO) || l->frame_count_in)) { snprintf(buffer, sizeof(buffer)-1, " | in: %"PRId64, l->frame_count_in); drawtext(out, xpos, ypos, buffer, s->white); xpos += strlen(buffer) * 8; } - if ((s->flags & FLAG_FCOUT) && (!(s->mode & MODE_NOZERO) || l->frame_count_out)) { + if ((flags & FLAG_FCOUT) && (!(mode & MODE_NOZERO) || l->frame_count_out)) { snprintf(buffer, sizeof(buffer)-1, " | out: %"PRId64, l->frame_count_out); drawtext(out, xpos, ypos, buffer, s->white); xpos += strlen(buffer) * 8; } - if ((s->flags & FLAG_FC_DELTA) && (!(s->mode & MODE_NOZERO) || (l->frame_count_in - l->frame_count_out))) { + if ((flags & FLAG_FC_DELTA) && (!(mode & MODE_NOZERO) || (l->frame_count_in - l->frame_count_out))) { snprintf(buffer, sizeof(buffer)-1, " | delta: %"PRId64, l->frame_count_in - l->frame_count_out); drawtext(out, xpos, ypos, buffer, s->white); xpos += strlen(buffer) * 8; } - if ((s->flags & FLAG_SCIN) && (!(s->mode & MODE_NOZERO) || l->sample_count_in)) { + if ((flags & FLAG_SCIN) && (!(mode & MODE_NOZERO) || l->sample_count_in)) { snprintf(buffer, sizeof(buffer)-1, " | sin: %"PRId64, l->sample_count_in); drawtext(out, xpos, ypos, buffer, s->white); xpos += strlen(buffer) * 8; } - if ((s->flags & FLAG_SCOUT) && (!(s->mode & MODE_NOZERO) || l->sample_count_out)) { + if ((flags & FLAG_SCOUT) && (!(mode & MODE_NOZERO) || l->sample_count_out)) { snprintf(buffer, sizeof(buffer)-1, " | sout: %"PRId64, l->sample_count_out); drawtext(out, xpos, ypos, buffer, s->white); xpos += strlen(buffer) * 8; } - if ((s->flags & FLAG_SC_DELTA) && (!(s->mode & MODE_NOZERO) || (l->sample_count_in - l->sample_count_out))) { + if ((flags & FLAG_SC_DELTA) && (!(mode & MODE_NOZERO) || (l->sample_count_in - l->sample_count_out))) { snprintf(buffer, sizeof(buffer)-1, " | sdelta: %"PRId64, l->sample_count_in - l->sample_count_out); drawtext(out, xpos, ypos, buffer, s->white); xpos += strlen(buffer) * 8; } - if ((s->flags & FLAG_PTS) && (!(s->mode & MODE_NOZERO) || current_pts_us)) { + if ((flags & FLAG_PTS) && (!(mode & MODE_NOZERO) || current_pts_us)) { snprintf(buffer, sizeof(buffer)-1, " | pts: %s", av_ts2str(current_pts_us)); drawtext(out, xpos, ypos, buffer, s->white); xpos += strlen(buffer) * 8; } - if ((s->flags & FLAG_PTS_DELTA) && (!(s->mode & MODE_NOZERO) || (current_pts_us - previous_pts_us))) { + if ((flags & FLAG_PTS_DELTA) && (!(mode & MODE_NOZERO) || (current_pts_us - previous_pts_us))) { snprintf(buffer, sizeof(buffer)-1, " | pts_delta: %s", av_ts2str(current_pts_us - previous_pts_us)); drawtext(out, xpos, ypos, buffer, s->white); xpos += strlen(buffer) * 8; } - if ((s->flags & FLAG_TIME) && (!(s->mode & MODE_NOZERO) || current_pts_us)) { + if ((flags & FLAG_TIME) && (!(mode & MODE_NOZERO) || current_pts_us)) { snprintf(buffer, sizeof(buffer)-1, " | time: %s", av_ts2timestr(current_pts_us, &AV_TIME_BASE_Q)); drawtext(out, xpos, ypos, buffer, s->white); xpos += strlen(buffer) * 8; } - if ((s->flags & FLAG_TIME_DELTA) && (!(s->mode & MODE_NOZERO) || (current_pts_us - previous_pts_us))) { + if ((flags & FLAG_TIME_DELTA) && (!(mode & MODE_NOZERO) || (current_pts_us - previous_pts_us))) { snprintf(buffer, sizeof(buffer)-1, " | time_delta: %s", av_ts2timestr(current_pts_us - previous_pts_us, &AV_TIME_BASE_Q)); drawtext(out, xpos, ypos, buffer, s->white); xpos += strlen(buffer) * 8; } - if ((s->flags & FLAG_EOF) && ff_outlink_get_status(l)) { + if ((flags & FLAG_EOF) && ff_outlink_get_status(l)) { snprintf(buffer, sizeof(buffer)-1, " | eof"); drawtext(out, xpos, ypos, buffer, s->blue); xpos += strlen(buffer) * 8; } - if ((s->flags & FLAG_DISABLED) && filter->is_disabled) { + if ((flags & FLAG_DISABLED) && filter->is_disabled) { snprintf(buffer, sizeof(buffer)-1, " | off"); drawtext(out, xpos, ypos, buffer, s->gray); xpos += strlen(buffer) * 8; From 416c1e62f19fce7f2f12c3457f04d94655744303 Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Sun, 21 May 2023 14:15:15 +0200 Subject: [PATCH 1090/2172] avfilter/f_graphmonitor: cache strlen() values --- libavfilter/f_graphmonitor.c | 152 ++++++++++++++++++----------------- 1 file changed, 79 insertions(+), 73 deletions(-) diff --git a/libavfilter/f_graphmonitor.c b/libavfilter/f_graphmonitor.c index 9f22cbb15bd..a32e8b5359f 100644 --- a/libavfilter/f_graphmonitor.c +++ b/libavfilter/f_graphmonitor.c @@ -177,7 +177,8 @@ static void clear_image(GraphMonitorContext *s, AVFrame *out, AVFilterLink *outl } } -static void drawtext(AVFrame *pic, int x, int y, const char *txt, uint8_t *color) +static void drawtext(AVFrame *pic, int x, int y, const char *txt, + const int len, uint8_t *color) { const uint8_t *font; int font_height; @@ -186,7 +187,7 @@ static void drawtext(AVFrame *pic, int x, int y, const char *txt, uint8_t *color font = avpriv_cga_font, font_height = 8; if (y + 8 >= pic->height || - x + strlen(txt) * 8 >= pic->width) + x + len * 8 >= pic->width) return; for (i = 0; txt[i]; i++) { @@ -260,108 +261,109 @@ static int draw_items(AVFilterContext *ctx, const int flags = s->flags; const int mode = s->mode; char buffer[1024] = { 0 }; + int len = 0; if (flags & FLAG_FMT) { if (l->type == AVMEDIA_TYPE_VIDEO) { - snprintf(buffer, sizeof(buffer)-1, " | format: %s", + len = snprintf(buffer, sizeof(buffer)-1, " | format: %s", av_get_pix_fmt_name(l->format)); } else if (l->type == AVMEDIA_TYPE_AUDIO) { - snprintf(buffer, sizeof(buffer)-1, " | format: %s", + len = snprintf(buffer, sizeof(buffer)-1, " | format: %s", av_get_sample_fmt_name(l->format)); } - drawtext(out, xpos, ypos, buffer, s->white); - xpos += strlen(buffer) * 8; + drawtext(out, xpos, ypos, buffer, len, s->white); + xpos += len * 8; } if (flags & FLAG_SIZE) { if (l->type == AVMEDIA_TYPE_VIDEO) { - snprintf(buffer, sizeof(buffer)-1, " | size: %dx%d", l->w, l->h); + len = snprintf(buffer, sizeof(buffer)-1, " | size: %dx%d", l->w, l->h); } else if (l->type == AVMEDIA_TYPE_AUDIO) { - snprintf(buffer, sizeof(buffer)-1, " | channels: %d", l->ch_layout.nb_channels); + len = snprintf(buffer, sizeof(buffer)-1, " | channels: %d", l->ch_layout.nb_channels); } - drawtext(out, xpos, ypos, buffer, s->white); - xpos += strlen(buffer) * 8; + drawtext(out, xpos, ypos, buffer, len, s->white); + xpos += len * 8; } if (flags & FLAG_RATE) { if (l->type == AVMEDIA_TYPE_VIDEO) { - snprintf(buffer, sizeof(buffer)-1, " | fps: %d/%d", l->frame_rate.num, l->frame_rate.den); + len = snprintf(buffer, sizeof(buffer)-1, " | fps: %d/%d", l->frame_rate.num, l->frame_rate.den); } else if (l->type == AVMEDIA_TYPE_AUDIO) { - snprintf(buffer, sizeof(buffer)-1, " | samplerate: %d", l->sample_rate); + len = snprintf(buffer, sizeof(buffer)-1, " | samplerate: %d", l->sample_rate); } - drawtext(out, xpos, ypos, buffer, s->white); - xpos += strlen(buffer) * 8; + drawtext(out, xpos, ypos, buffer, len, s->white); + xpos += len * 8; } if (flags & FLAG_TB) { - snprintf(buffer, sizeof(buffer)-1, " | tb: %d/%d", l->time_base.num, l->time_base.den); - drawtext(out, xpos, ypos, buffer, s->white); - xpos += strlen(buffer) * 8; + len = snprintf(buffer, sizeof(buffer)-1, " | tb: %d/%d", l->time_base.num, l->time_base.den); + drawtext(out, xpos, ypos, buffer, len, s->white); + xpos += len * 8; } if ((flags & FLAG_QUEUE) && (!(mode & MODE_NOZERO) || frames)) { - snprintf(buffer, sizeof(buffer)-1, " | queue: "); - drawtext(out, xpos, ypos, buffer, s->white); - xpos += strlen(buffer) * 8; - snprintf(buffer, sizeof(buffer)-1, "%"SIZE_SPECIFIER, frames); - drawtext(out, xpos, ypos, buffer, frames > 0 ? frames >= 10 ? frames >= 50 ? s->red : s->yellow : s->green : s->white); - xpos += strlen(buffer) * 8; + len = snprintf(buffer, sizeof(buffer)-1, " | queue: "); + drawtext(out, xpos, ypos, buffer, len, s->white); + xpos += len * 8; + len = snprintf(buffer, sizeof(buffer)-1, "%"SIZE_SPECIFIER, frames); + drawtext(out, xpos, ypos, buffer, len, frames > 0 ? frames >= 10 ? frames >= 50 ? s->red : s->yellow : s->green : s->white); + xpos += len * 8; } if ((flags & FLAG_FCIN) && (!(mode & MODE_NOZERO) || l->frame_count_in)) { - snprintf(buffer, sizeof(buffer)-1, " | in: %"PRId64, l->frame_count_in); - drawtext(out, xpos, ypos, buffer, s->white); - xpos += strlen(buffer) * 8; + len = snprintf(buffer, sizeof(buffer)-1, " | in: %"PRId64, l->frame_count_in); + drawtext(out, xpos, ypos, buffer, len, s->white); + xpos += len * 8; } if ((flags & FLAG_FCOUT) && (!(mode & MODE_NOZERO) || l->frame_count_out)) { - snprintf(buffer, sizeof(buffer)-1, " | out: %"PRId64, l->frame_count_out); - drawtext(out, xpos, ypos, buffer, s->white); - xpos += strlen(buffer) * 8; + len = snprintf(buffer, sizeof(buffer)-1, " | out: %"PRId64, l->frame_count_out); + drawtext(out, xpos, ypos, buffer, len, s->white); + xpos += len * 8; } if ((flags & FLAG_FC_DELTA) && (!(mode & MODE_NOZERO) || (l->frame_count_in - l->frame_count_out))) { - snprintf(buffer, sizeof(buffer)-1, " | delta: %"PRId64, l->frame_count_in - l->frame_count_out); - drawtext(out, xpos, ypos, buffer, s->white); - xpos += strlen(buffer) * 8; + len = snprintf(buffer, sizeof(buffer)-1, " | delta: %"PRId64, l->frame_count_in - l->frame_count_out); + drawtext(out, xpos, ypos, buffer, len, s->white); + xpos += len * 8; } if ((flags & FLAG_SCIN) && (!(mode & MODE_NOZERO) || l->sample_count_in)) { - snprintf(buffer, sizeof(buffer)-1, " | sin: %"PRId64, l->sample_count_in); - drawtext(out, xpos, ypos, buffer, s->white); - xpos += strlen(buffer) * 8; + len = snprintf(buffer, sizeof(buffer)-1, " | sin: %"PRId64, l->sample_count_in); + drawtext(out, xpos, ypos, buffer, len, s->white); + xpos += len * 8; } if ((flags & FLAG_SCOUT) && (!(mode & MODE_NOZERO) || l->sample_count_out)) { - snprintf(buffer, sizeof(buffer)-1, " | sout: %"PRId64, l->sample_count_out); - drawtext(out, xpos, ypos, buffer, s->white); - xpos += strlen(buffer) * 8; + len = snprintf(buffer, sizeof(buffer)-1, " | sout: %"PRId64, l->sample_count_out); + drawtext(out, xpos, ypos, buffer, len, s->white); + xpos += len * 8; } if ((flags & FLAG_SC_DELTA) && (!(mode & MODE_NOZERO) || (l->sample_count_in - l->sample_count_out))) { - snprintf(buffer, sizeof(buffer)-1, " | sdelta: %"PRId64, l->sample_count_in - l->sample_count_out); - drawtext(out, xpos, ypos, buffer, s->white); - xpos += strlen(buffer) * 8; + len = snprintf(buffer, sizeof(buffer)-1, " | sdelta: %"PRId64, l->sample_count_in - l->sample_count_out); + drawtext(out, xpos, ypos, buffer, len, s->white); + xpos += len * 8; } if ((flags & FLAG_PTS) && (!(mode & MODE_NOZERO) || current_pts_us)) { - snprintf(buffer, sizeof(buffer)-1, " | pts: %s", av_ts2str(current_pts_us)); - drawtext(out, xpos, ypos, buffer, s->white); - xpos += strlen(buffer) * 8; + len = snprintf(buffer, sizeof(buffer)-1, " | pts: %s", av_ts2str(current_pts_us)); + drawtext(out, xpos, ypos, buffer, len, s->white); + xpos += len * 8; } if ((flags & FLAG_PTS_DELTA) && (!(mode & MODE_NOZERO) || (current_pts_us - previous_pts_us))) { - snprintf(buffer, sizeof(buffer)-1, " | pts_delta: %s", av_ts2str(current_pts_us - previous_pts_us)); - drawtext(out, xpos, ypos, buffer, s->white); - xpos += strlen(buffer) * 8; + len = snprintf(buffer, sizeof(buffer)-1, " | pts_delta: %s", av_ts2str(current_pts_us - previous_pts_us)); + drawtext(out, xpos, ypos, buffer, len, s->white); + xpos += len * 8; } if ((flags & FLAG_TIME) && (!(mode & MODE_NOZERO) || current_pts_us)) { - snprintf(buffer, sizeof(buffer)-1, " | time: %s", av_ts2timestr(current_pts_us, &AV_TIME_BASE_Q)); - drawtext(out, xpos, ypos, buffer, s->white); - xpos += strlen(buffer) * 8; + len = snprintf(buffer, sizeof(buffer)-1, " | time: %s", av_ts2timestr(current_pts_us, &AV_TIME_BASE_Q)); + drawtext(out, xpos, ypos, buffer, len, s->white); + xpos += len * 8; } if ((flags & FLAG_TIME_DELTA) && (!(mode & MODE_NOZERO) || (current_pts_us - previous_pts_us))) { - snprintf(buffer, sizeof(buffer)-1, " | time_delta: %s", av_ts2timestr(current_pts_us - previous_pts_us, &AV_TIME_BASE_Q)); - drawtext(out, xpos, ypos, buffer, s->white); - xpos += strlen(buffer) * 8; + len = snprintf(buffer, sizeof(buffer)-1, " | time_delta: %s", av_ts2timestr(current_pts_us - previous_pts_us, &AV_TIME_BASE_Q)); + drawtext(out, xpos, ypos, buffer, len, s->white); + xpos += len * 8; } if ((flags & FLAG_EOF) && ff_outlink_get_status(l)) { - snprintf(buffer, sizeof(buffer)-1, " | eof"); - drawtext(out, xpos, ypos, buffer, s->blue); - xpos += strlen(buffer) * 8; + len = snprintf(buffer, sizeof(buffer)-1, " | eof"); + drawtext(out, xpos, ypos, buffer, len, s->blue); + xpos += len * 8; } if ((flags & FLAG_DISABLED) && filter->is_disabled) { - snprintf(buffer, sizeof(buffer)-1, " | off"); - drawtext(out, xpos, ypos, buffer, s->gray); - xpos += strlen(buffer) * 8; + len = snprintf(buffer, sizeof(buffer)-1, " | off"); + drawtext(out, xpos, ypos, buffer, len, s->gray); + xpos += len * 8; } s->cache[s->cache_index].previous_pts_us = l->current_pts_us; @@ -383,7 +385,7 @@ static int create_frame(AVFilterContext *ctx, int64_t pts) GraphMonitorContext *s = ctx->priv; AVFilterLink *outlink = ctx->outputs[0]; AVFrame *out; - int ret, xpos, ypos = 0; + int ret, len, xpos, ypos = 0; out = ff_get_video_buffer(outlink, outlink->w, outlink->h); if (!out) @@ -407,9 +409,11 @@ static int create_frame(AVFilterContext *ctx, int64_t pts) continue; xpos = 0; - drawtext(out, xpos, ypos, filter->name, s->white); - xpos += strlen(filter->name) * 8 + 10; - drawtext(out, xpos, ypos, filter->filter->name, s->white); + len = strlen(filter->name); + drawtext(out, xpos, ypos, filter->name, len, s->white); + xpos += len * 8 + 10; + len = strlen(filter->filter->name); + drawtext(out, xpos, ypos, filter->filter->name, len, s->white); ypos += 10; for (int j = 0; j < filter->nb_inputs; j++) { AVFilterLink *l = filter->inputs[j]; @@ -422,11 +426,12 @@ static int create_frame(AVFilterContext *ctx, int64_t pts) continue; xpos = 10; - snprintf(buffer, sizeof(buffer)-1, "in%d: ", j); - drawtext(out, xpos, ypos, buffer, s->white); - xpos += strlen(buffer) * 8; - drawtext(out, xpos, ypos, l->src->name, s->white); - xpos += strlen(l->src->name) * 8 + 10; + len = snprintf(buffer, sizeof(buffer)-1, "in%d: ", j); + drawtext(out, xpos, ypos, buffer, len, s->white); + xpos += len * 8; + len = strlen(l->src->name); + drawtext(out, xpos, ypos, l->src->name, len, s->white); + xpos += len * 8 + 10; ret = draw_items(ctx, filter, out, xpos, ypos, l, frames); if (ret < 0) goto error; @@ -445,11 +450,12 @@ static int create_frame(AVFilterContext *ctx, int64_t pts) continue; xpos = 10; - snprintf(buffer, sizeof(buffer)-1, "out%d: ", j); - drawtext(out, xpos, ypos, buffer, s->white); - xpos += strlen(buffer) * 8; - drawtext(out, xpos, ypos, l->dst->name, s->white); - xpos += strlen(l->dst->name) * 8 + 10; + len = snprintf(buffer, sizeof(buffer)-1, "out%d: ", j); + drawtext(out, xpos, ypos, buffer, len, s->white); + xpos += len * 8; + len = strlen(l->dst->name); + drawtext(out, xpos, ypos, l->dst->name, len, s->white); + xpos += len * 8 + 10; ret = draw_items(ctx, filter, out, xpos, ypos, l, frames); if (ret < 0) goto error; From 08eb13c05c606fa7387f4f2e9109ba81450109fa Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Sun, 21 May 2023 14:47:30 +0200 Subject: [PATCH 1091/2172] avfilter/f_graphmonitor: add missing queue flag --- libavfilter/f_graphmonitor.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/libavfilter/f_graphmonitor.c b/libavfilter/f_graphmonitor.c index a32e8b5359f..1184ba2f7cc 100644 --- a/libavfilter/f_graphmonitor.c +++ b/libavfilter/f_graphmonitor.c @@ -112,6 +112,7 @@ static const AVOption graphmonitor_options[] = { { "f", "set flags", OFFSET(flags), AV_OPT_TYPE_FLAGS, {.i64=FLAG_QUEUE}, 0, INT_MAX, VFR, "flags" }, { "none", NULL, 0, AV_OPT_TYPE_CONST, {.i64=FLAG_NONE}, 0, 0, VFR, "flags" }, { "all", NULL, 0, AV_OPT_TYPE_CONST, {.i64=INT_MAX}, 0, 0, VFR, "flags" }, + { "queue", NULL, 0, AV_OPT_TYPE_CONST, {.i64=FLAG_QUEUE}, 0, 0, VFR, "flags" }, { "frame_count_in", NULL, 0, AV_OPT_TYPE_CONST, {.i64=FLAG_FCOUT}, 0, 0, VFR, "flags" }, { "frame_count_out", NULL, 0, AV_OPT_TYPE_CONST, {.i64=FLAG_FCIN}, 0, 0, VFR, "flags" }, { "frame_count_delta",NULL, 0, AV_OPT_TYPE_CONST, {.i64=FLAG_FC_DELTA},0, 0, VFR, "flags" }, @@ -384,8 +385,9 @@ static int create_frame(AVFilterContext *ctx, int64_t pts) { GraphMonitorContext *s = ctx->priv; AVFilterLink *outlink = ctx->outputs[0]; - AVFrame *out; int ret, len, xpos, ypos = 0; + char buffer[1024]; + AVFrame *out; out = ff_get_video_buffer(outlink, outlink->w, outlink->h); if (!out) @@ -397,7 +399,6 @@ static int create_frame(AVFilterContext *ctx, int64_t pts) for (int i = 0; i < ctx->graph->nb_filters; i++) { AVFilterContext *filter = ctx->graph->filters[i]; - char buffer[1024] = { 0 }; if ((s->mode & MODE_COMPACT) && !filter_have_queued(filter)) continue; From c4b3e882f8bac6dfb4200a372f61dbf7a1a2d143 Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Sun, 21 May 2023 14:52:18 +0200 Subject: [PATCH 1092/2172] avfilter/f_graphmonitor: make opacity runtime option --- libavfilter/f_graphmonitor.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/libavfilter/f_graphmonitor.c b/libavfilter/f_graphmonitor.c index 1184ba2f7cc..5496d4ac7ba 100644 --- a/libavfilter/f_graphmonitor.c +++ b/libavfilter/f_graphmonitor.c @@ -99,8 +99,8 @@ enum { static const AVOption graphmonitor_options[] = { { "size", "set monitor size", OFFSET(w), AV_OPT_TYPE_IMAGE_SIZE, {.str="hd720"}, 0, 0, VF }, { "s", "set monitor size", OFFSET(w), AV_OPT_TYPE_IMAGE_SIZE, {.str="hd720"}, 0, 0, VF }, - { "opacity", "set video opacity", OFFSET(opacity), AV_OPT_TYPE_FLOAT, {.dbl=.9}, 0, 1, VF }, - { "o", "set video opacity", OFFSET(opacity), AV_OPT_TYPE_FLOAT, {.dbl=.9}, 0, 1, VF }, + { "opacity", "set video opacity", OFFSET(opacity), AV_OPT_TYPE_FLOAT, {.dbl=.9}, 0, 1, VFR }, + { "o", "set video opacity", OFFSET(opacity), AV_OPT_TYPE_FLOAT, {.dbl=.9}, 0, 1, VFR }, { "mode", "set mode", OFFSET(mode), AV_OPT_TYPE_FLAGS, {.i64=0}, 0, MODE_MAX, VFR, "mode" }, { "m", "set mode", OFFSET(mode), AV_OPT_TYPE_FLAGS, {.i64=0}, 0, MODE_MAX, VFR, "mode" }, { "full", NULL, 0, AV_OPT_TYPE_CONST, {.i64=MODE_FULL}, 0, 0, VFR, "mode" }, @@ -393,6 +393,7 @@ static int create_frame(AVFilterContext *ctx, int64_t pts) if (!out) return AVERROR(ENOMEM); + s->bg[3] = 255 * s->opacity; clear_image(s, out, outlink); s->cache_index = 0; @@ -516,7 +517,6 @@ static int config_output(AVFilterLink *outlink) { GraphMonitorContext *s = outlink->src->priv; - s->bg[3] = 255 * s->opacity; s->white[0] = s->white[1] = s->white[2] = 255; s->yellow[0] = s->yellow[1] = 255; s->red[0] = 255; From 4d4aed281527224b444022d1462ec16909571700 Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Sun, 21 May 2023 20:31:46 +0200 Subject: [PATCH 1093/2172] avcodec/fitsdec: fix decoder class category --- libavcodec/fitsdec.c | 1 + 1 file changed, 1 insertion(+) diff --git a/libavcodec/fitsdec.c b/libavcodec/fitsdec.c index 44135309f26..284e945ba5b 100644 --- a/libavcodec/fitsdec.c +++ b/libavcodec/fitsdec.c @@ -319,6 +319,7 @@ static const AVClass fits_decoder_class = { .item_name = av_default_item_name, .option = fits_options, .version = LIBAVUTIL_VERSION_INT, + .category = AV_CLASS_CATEGORY_DECODER, }; const FFCodec ff_fits_decoder = { From a28df1faa9a453e2b58499f7bc3d1a8cbaa6d72f Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Sun, 21 May 2023 20:39:18 +0200 Subject: [PATCH 1094/2172] avformat/fitsdec: remove .raw_codec_id This non-raw demuxer does not have parser. --- libavformat/fitsdec.c | 1 - 1 file changed, 1 deletion(-) diff --git a/libavformat/fitsdec.c b/libavformat/fitsdec.c index 54412c60ff8..c463fc4ca15 100644 --- a/libavformat/fitsdec.c +++ b/libavformat/fitsdec.c @@ -231,5 +231,4 @@ const AVInputFormat ff_fits_demuxer = { .read_header = fits_read_header, .read_packet = fits_read_packet, .priv_class = &fits_demuxer_class, - .raw_codec_id = AV_CODEC_ID_FITS, }; From 8a4934166645e636ba1830e44a6223f8c243da8c Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Sun, 21 May 2023 20:40:57 +0200 Subject: [PATCH 1095/2172] avformat/fitsdec: fix demuxer class category --- libavformat/fitsdec.c | 1 + 1 file changed, 1 insertion(+) diff --git a/libavformat/fitsdec.c b/libavformat/fitsdec.c index c463fc4ca15..8618b9aab04 100644 --- a/libavformat/fitsdec.c +++ b/libavformat/fitsdec.c @@ -221,6 +221,7 @@ static const AVClass fits_demuxer_class = { .item_name = av_default_item_name, .option = fits_options, .version = LIBAVUTIL_VERSION_INT, + .category = AV_CLASS_CATEGORY_DEMUXER, }; const AVInputFormat ff_fits_demuxer = { From fd2ca3d4c5949e7b13b09ef00414ad4ca66881c5 Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Sun, 21 May 2023 20:43:52 +0200 Subject: [PATCH 1096/2172] avformat/fitsenc: reindent switch --- libavformat/fitsenc.c | 84 +++++++++++++++++++++---------------------- 1 file changed, 42 insertions(+), 42 deletions(-) diff --git a/libavformat/fitsenc.c b/libavformat/fitsenc.c index 1df7e2bcf2b..90bb71fd17b 100644 --- a/libavformat/fitsenc.c +++ b/libavformat/fitsenc.c @@ -84,48 +84,48 @@ static int write_image_header(AVFormatContext *s) float datamax, datamin; switch (encctx->format) { - case AV_PIX_FMT_GRAY8: - bitpix = 8; - naxis = 2; - datamin = 0; - datamax = 255; - break; - case AV_PIX_FMT_GRAY16BE: - bitpix = 16; - naxis = 2; - bzero = 32768; - datamin = 0; - datamax = 65535; - break; - case AV_PIX_FMT_GBRP: - case AV_PIX_FMT_GBRAP: - bitpix = 8; - naxis = 3; - rgb = 1; - if (encctx->format == AV_PIX_FMT_GBRP) { - naxis3 = 3; - } else { - naxis3 = 4; - } - datamin = 0; - datamax = 255; - break; - case AV_PIX_FMT_GBRP16BE: - case AV_PIX_FMT_GBRAP16BE: - bitpix = 16; - naxis = 3; - rgb = 1; - if (encctx->format == AV_PIX_FMT_GBRP16BE) { - naxis3 = 3; - } else { - naxis3 = 4; - } - bzero = 32768; - datamin = 0; - datamax = 65535; - break; - default: - return AVERROR(EINVAL); + case AV_PIX_FMT_GRAY8: + bitpix = 8; + naxis = 2; + datamin = 0; + datamax = 255; + break; + case AV_PIX_FMT_GRAY16BE: + bitpix = 16; + naxis = 2; + bzero = 32768; + datamin = 0; + datamax = 65535; + break; + case AV_PIX_FMT_GBRP: + case AV_PIX_FMT_GBRAP: + bitpix = 8; + naxis = 3; + rgb = 1; + if (encctx->format == AV_PIX_FMT_GBRP) { + naxis3 = 3; + } else { + naxis3 = 4; + } + datamin = 0; + datamax = 255; + break; + case AV_PIX_FMT_GBRP16BE: + case AV_PIX_FMT_GBRAP16BE: + bitpix = 16; + naxis = 3; + rgb = 1; + if (encctx->format == AV_PIX_FMT_GBRP16BE) { + naxis3 = 3; + } else { + naxis3 = 4; + } + bzero = 32768; + datamin = 0; + datamax = 65535; + break; + default: + return AVERROR(EINVAL); } if (fitsctx->first_image) { From d912ff19c501d1a02eb8832b863790960981ccae Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Sun, 21 May 2023 20:51:32 +0200 Subject: [PATCH 1097/2172] avcodec/fitsenc: mark output packets as keyframes --- libavcodec/fitsenc.c | 1 + 1 file changed, 1 insertion(+) diff --git a/libavcodec/fitsenc.c b/libavcodec/fitsenc.c index 12952278ac4..86ea11f0c08 100644 --- a/libavcodec/fitsenc.c +++ b/libavcodec/fitsenc.c @@ -104,6 +104,7 @@ static int fits_encode_frame(AVCodecContext *avctx, AVPacket *pkt, bytes_left = padded_data_size - data_size; memset(bytestream, 0, bytes_left); + pkt->flags |= AV_PKT_FLAG_KEY; *got_packet = 1; return 0; From 02823703f4753e10e7de14124d003d3fc23d7f39 Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Sun, 21 May 2023 20:55:32 +0200 Subject: [PATCH 1098/2172] avformat/fitsdec: stop creating pts, instead set packet duration --- libavformat/fitsdec.c | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/libavformat/fitsdec.c b/libavformat/fitsdec.c index 8618b9aab04..516579669fb 100644 --- a/libavformat/fitsdec.c +++ b/libavformat/fitsdec.c @@ -37,7 +37,6 @@ typedef struct FITSContext { const AVClass *class; AVRational framerate; int first_image; - int64_t pts; } FITSContext; static int fits_probe(const AVProbeData *p) @@ -61,7 +60,6 @@ static int fits_read_header(AVFormatContext *s) st->codecpar->codec_id = AV_CODEC_ID_FITS; avpriv_set_pts_info(st, 64, fits->framerate.den, fits->framerate.num); - fits->pts = 0; fits->first_image = 1; return 0; } @@ -196,13 +194,11 @@ static int fits_read_packet(AVFormatContext *s, AVPacket *pkt) pkt->size = avbuf.len - 80; av_freep(&buf); ret = avio_read(s->pb, pkt->data + pkt->size, size); - if (ret < 0) { + if (ret < 0) return ret; - } pkt->size += ret; - pkt->pts = fits->pts; - fits->pts++; + pkt->duration = 1; return 0; From a6068c8700d16e31a2c036adb8516c66428ae267 Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Sun, 21 May 2023 20:58:37 +0200 Subject: [PATCH 1099/2172] avformat/fits*: format does not store timestamps --- libavformat/fitsdec.c | 1 + libavformat/fitsenc.c | 5 +++-- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/libavformat/fitsdec.c b/libavformat/fitsdec.c index 516579669fb..e0f502e4e33 100644 --- a/libavformat/fitsdec.c +++ b/libavformat/fitsdec.c @@ -228,4 +228,5 @@ const AVInputFormat ff_fits_demuxer = { .read_header = fits_read_header, .read_packet = fits_read_packet, .priv_class = &fits_demuxer_class, + .flags = AVFMT_NOTIMESTAMPS, }; diff --git a/libavformat/fitsenc.c b/libavformat/fitsenc.c index 90bb71fd17b..14a4572f70a 100644 --- a/libavformat/fitsenc.c +++ b/libavformat/fitsenc.c @@ -199,6 +199,7 @@ const FFOutputFormat ff_fits_muxer = { .p.audio_codec = AV_CODEC_ID_NONE, .p.video_codec = AV_CODEC_ID_FITS, .priv_data_size = sizeof(FITSContext), - .write_header = fits_write_header, - .write_packet = fits_write_packet, + .write_header = fits_write_header, + .write_packet = fits_write_packet, + .p.flags = AVFMT_NOTIMESTAMPS, }; From e684967e744044173430f408e6787a1d5480c832 Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Sun, 21 May 2023 22:04:59 +0200 Subject: [PATCH 1100/2172] avfilter/f_graphmonitor: output one frame more after eof To easily debug eof issues. --- libavfilter/f_graphmonitor.c | 29 ++++++++++++++++++++++++++--- 1 file changed, 26 insertions(+), 3 deletions(-) diff --git a/libavfilter/f_graphmonitor.c b/libavfilter/f_graphmonitor.c index 5496d4ac7ba..a1e467bc8bd 100644 --- a/libavfilter/f_graphmonitor.c +++ b/libavfilter/f_graphmonitor.c @@ -47,6 +47,8 @@ typedef struct GraphMonitorContext { int flags; AVRational frame_rate; + int eof; + int eof_frames; int64_t pts; int64_t next_pts; uint8_t white[4]; @@ -469,6 +471,8 @@ static int create_frame(AVFilterContext *ctx, int64_t pts) out->pts = pts; out->duration = 1; s->pts = pts + 1; + if (s->eof_frames) + s->eof_frames = 0; return ff_filter_frame(outlink, out); error: av_frame_free(&out); @@ -481,10 +485,11 @@ static int activate(AVFilterContext *ctx) AVFilterLink *inlink = ctx->inputs[0]; AVFilterLink *outlink = ctx->outputs[0]; int64_t pts = AV_NOPTS_VALUE; + int status; FF_FILTER_FORWARD_STATUS_BACK(outlink, inlink); - if (ff_inlink_queued_frames(inlink)) { + if (!s->eof && ff_inlink_queued_frames(inlink)) { AVFrame *frame = NULL; int ret; @@ -502,13 +507,31 @@ static int activate(AVFilterContext *ctx) if (s->pts == AV_NOPTS_VALUE) s->pts = pts; s->next_pts = pts; + } else if (s->eof) { + s->next_pts = s->pts + 1; + } + + if (s->eof && s->eof_frames == 0) { + ff_outlink_set_status(outlink, AVERROR_EOF, s->next_pts); + return 0; } if (s->pts < s->next_pts && ff_outlink_frame_wanted(outlink)) return create_frame(ctx, s->pts); - FF_FILTER_FORWARD_STATUS(inlink, outlink); - FF_FILTER_FORWARD_WANTED(outlink, inlink); + if (!s->eof && ff_inlink_acknowledge_status(inlink, &status, &pts)) { + s->eof = 1; + s->eof_frames = 1; + ff_filter_set_ready(ctx, 100); + return 0; + } + + if (!s->eof) { + FF_FILTER_FORWARD_WANTED(outlink, inlink); + } else { + ff_filter_set_ready(ctx, 100); + return 0; + } return FFERROR_NOT_READY; } From 19a74bc794e6cf8a9a9b59df9ccff03f85d4a34f Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Mon, 15 May 2023 21:10:15 +0200 Subject: [PATCH 1101/2172] avformat/format: Remove redundant FFMIN() in ff_match_url_ext() Found-by: Leo Izen Signed-off-by: Michael Niedermayer --- libavformat/format.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavformat/format.c b/libavformat/format.c index d9135854de5..c91f71057a5 100644 --- a/libavformat/format.c +++ b/libavformat/format.c @@ -70,7 +70,7 @@ int ff_match_url_ext(const char *url, const char *extensions) return 0; if (uc.query - ext > sizeof(scratchpad)) return AVERROR(ENOMEM); //not enough memory in our scratchpad - av_strlcpy(scratchpad, ext + 1, FFMIN(sizeof(scratchpad), uc.query - ext)); + av_strlcpy(scratchpad, ext + 1, uc.query - ext); return av_match_name(scratchpad, extensions); } From a0cb5722fda9bd03b7be31a83b043966f0fd71b8 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Mon, 15 May 2023 21:28:26 +0200 Subject: [PATCH 1102/2172] avformat/hls: Check mime_ok first This should be a few nano seconds faster (not measureable) But Collectively the whole humankind watching hls will safe a minute Found-by: Leo Izen Signed-off-by: Michael Niedermayer --- libavformat/hls.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/libavformat/hls.c b/libavformat/hls.c index 425df3b26b9..fc29ef0ca98 100644 --- a/libavformat/hls.c +++ b/libavformat/hls.c @@ -2541,9 +2541,9 @@ static int hls_probe(const AVProbeData *p) av_strcasecmp(p->mime_type, "application/x-mpegurl") ); - if (!av_match_ext (p->filename, "m3u8,hls,m3u") && - ff_match_url_ext(p->filename, "m3u8,hls,m3u") <= 0 && - !mime_ok) { + if (!mime_ok && + !av_match_ext (p->filename, "m3u8,hls,m3u") && + ff_match_url_ext(p->filename, "m3u8,hls,m3u") <= 0) { av_log(NULL, AV_LOG_ERROR, "Not detecting m3u8/hls with non standard extension\n"); return 0; } From 5b630743c625669b7c6ee4a01d4e0e8b51d7e636 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Mon, 15 May 2023 21:33:03 +0200 Subject: [PATCH 1103/2172] avformat/hls: Better message from hls_probe() Found-by: Kacper Michajlow Signed-off-by: Michael Niedermayer --- libavformat/hls.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/libavformat/hls.c b/libavformat/hls.c index fc29ef0ca98..2bc142510e0 100644 --- a/libavformat/hls.c +++ b/libavformat/hls.c @@ -2536,17 +2536,23 @@ static int hls_probe(const AVProbeData *p) int mime_ok = p->mime_type && !( av_strcasecmp(p->mime_type, "application/vnd.apple.mpegurl") && - av_strcasecmp(p->mime_type, "audio/mpegurl") && + av_strcasecmp(p->mime_type, "audio/mpegurl") + ); + + int mime_x = p->mime_type && !( av_strcasecmp(p->mime_type, "audio/x-mpegurl") && av_strcasecmp(p->mime_type, "application/x-mpegurl") ); if (!mime_ok && + !mime_x && !av_match_ext (p->filename, "m3u8,hls,m3u") && ff_match_url_ext(p->filename, "m3u8,hls,m3u") <= 0) { - av_log(NULL, AV_LOG_ERROR, "Not detecting m3u8/hls with non standard extension\n"); + av_log(NULL, AV_LOG_ERROR, "Not detecting m3u8/hls with non standard extension and non standard mime type\n"); return 0; } + if (mime_x) + av_log(NULL, AV_LOG_WARNING, "mime type is not rfc8216 compliant\n"); return AVPROBE_SCORE_MAX; } From d09f50c0f5f045dec35f0ca22c2212fae2378dba Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Mon, 15 May 2023 21:39:13 +0200 Subject: [PATCH 1104/2172] avformat/hls: remove non standard hls extension Suggested-by: Kacper Michajlow Signed-off-by: Michael Niedermayer --- libavformat/hls.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libavformat/hls.c b/libavformat/hls.c index 2bc142510e0..4fff4405e8f 100644 --- a/libavformat/hls.c +++ b/libavformat/hls.c @@ -2546,8 +2546,8 @@ static int hls_probe(const AVProbeData *p) if (!mime_ok && !mime_x && - !av_match_ext (p->filename, "m3u8,hls,m3u") && - ff_match_url_ext(p->filename, "m3u8,hls,m3u") <= 0) { + !av_match_ext (p->filename, "m3u8,m3u") && + ff_match_url_ext(p->filename, "m3u8,m3u") <= 0) { av_log(NULL, AV_LOG_ERROR, "Not detecting m3u8/hls with non standard extension and non standard mime type\n"); return 0; } From a76efafdb9be966ae3ad52b32370dc644dd582bf Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Sun, 5 Mar 2023 00:51:38 +0100 Subject: [PATCH 1105/2172] avformat/wavdec: Check that smv block fits in available space Fixes: OOM Fixes: 56271/clusterfuzz-testcase-minimized-ffmpeg_dem_WAV_fuzzer-5290810045497344 Found-by: continuous fuzzing process https://github.com/google/oss-fuzz/tree/master/projects/ffmpeg Signed-off-by: Michael Niedermayer --- libavformat/wavdec.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/libavformat/wavdec.c b/libavformat/wavdec.c index e3f790fcc99..97e69ab2ee4 100644 --- a/libavformat/wavdec.c +++ b/libavformat/wavdec.c @@ -730,6 +730,10 @@ static int wav_read_packet(AVFormatContext *s, AVPacket *pkt) goto smv_out; } size = avio_rl24(s->pb); + if (size > wav->smv_block_size) { + ret = AVERROR_EOF; + goto smv_out; + } ret = av_get_packet(s->pb, pkt, size); if (ret < 0) goto smv_out; From 43e5e2e42354fafc608830e3c8c46dacd22a851b Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Sat, 18 Feb 2023 21:50:13 +0100 Subject: [PATCH 1106/2172] avcodec/bonk: Avoid undefined integer overflow in predictor_calc_error() Fixes: signed integer overflow: -159584 * 5105950 cannot be represented in type 'int' Fixes: 55165/clusterfuzz-testcase-minimized-ffmpeg_AV_CODEC_ID_BONK_fuzzer-5796023719297024 Found-by: continuous fuzzing process https://github.com/google/oss-fuzz/tree/master/projects/ffmpeg Signed-off-by: Michael Niedermayer --- libavcodec/bonk.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libavcodec/bonk.c b/libavcodec/bonk.c index 9a91b4842e5..fbea91c750f 100644 --- a/libavcodec/bonk.c +++ b/libavcodec/bonk.c @@ -270,14 +270,14 @@ static inline int shift(int a, int b) static int predictor_calc_error(int *k, int *state, int order, int error) { - int i, x = error - shift_down(k[order-1] * state[order-1], LATTICE_SHIFT); + int i, x = error - shift_down(k[order-1] * (unsigned)state[order-1], LATTICE_SHIFT); int *k_ptr = &(k[order-2]), *state_ptr = &(state[order-2]); for (i = order-2; i >= 0; i--, k_ptr--, state_ptr--) { unsigned k_value = *k_ptr, state_value = *state_ptr; - x -= shift_down(k_value * state_value, LATTICE_SHIFT); + x -= shift_down(k_value * (unsigned)state_value, LATTICE_SHIFT); state_ptr[1] = state_value + shift_down(k_value * x, LATTICE_SHIFT); } From 0709680fc46f3d518f0de376bec9d9dd3811fccc Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Mon, 22 May 2023 01:30:35 +0200 Subject: [PATCH 1107/2172] avfilter/vf_xfade: add horizontal and vertical wind transforms --- doc/filters.texi | 4 +++ libavfilter/vf_xfade.c | 74 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 78 insertions(+) diff --git a/doc/filters.texi b/doc/filters.texi index ddc8529bbe9..909288d3db8 100644 --- a/doc/filters.texi +++ b/doc/filters.texi @@ -25154,6 +25154,10 @@ Set one of available transition effects: @item zoomin @item fadefast @item fadeslow +@item hlwind +@item hrwind +@item vuwind +@item vdwind @end table Default transition effect is fade. diff --git a/libavfilter/vf_xfade.c b/libavfilter/vf_xfade.c index 5745a241733..80037ee604d 100644 --- a/libavfilter/vf_xfade.c +++ b/libavfilter/vf_xfade.c @@ -76,6 +76,10 @@ enum XFadeTransitions { ZOOMIN, FADEFAST, FADESLOW, + HLWIND, + HRWIND, + VUWIND, + VDWIND, NB_TRANSITIONS, }; @@ -197,6 +201,10 @@ static const AVOption xfade_options[] = { { "zoomin", "zoom in transition", 0, AV_OPT_TYPE_CONST, {.i64=ZOOMIN}, 0, 0, FLAGS, "transition" }, { "fadefast", "fast fade transition", 0, AV_OPT_TYPE_CONST, {.i64=FADEFAST}, 0, 0, FLAGS, "transition" }, { "fadeslow", "slow fade transition", 0, AV_OPT_TYPE_CONST, {.i64=FADESLOW}, 0, 0, FLAGS, "transition" }, + { "hlwind", "hl wind transition", 0, AV_OPT_TYPE_CONST, {.i64=HLWIND}, 0, 0, FLAGS, "transition" }, + { "hrwind", "hr wind transition", 0, AV_OPT_TYPE_CONST, {.i64=HRWIND}, 0, 0, FLAGS, "transition" }, + { "vuwind", "vu wind transition", 0, AV_OPT_TYPE_CONST, {.i64=VUWIND}, 0, 0, FLAGS, "transition" }, + { "vdwind", "vd wind transition", 0, AV_OPT_TYPE_CONST, {.i64=VDWIND}, 0, 0, FLAGS, "transition" }, { "duration", "set cross fade duration", OFFSET(duration), AV_OPT_TYPE_DURATION, {.i64=1000000}, 0, 60000000, FLAGS }, { "offset", "set cross fade start relative to first input stream", OFFSET(offset), AV_OPT_TYPE_DURATION, {.i64=0}, INT64_MIN, INT64_MAX, FLAGS }, { "expr", "set expression for custom transition", OFFSET(custom_str), AV_OPT_TYPE_STRING, {.str=NULL}, 0, 0, FLAGS }, @@ -1738,6 +1746,68 @@ static void fadeslow##name##_transition(AVFilterContext *ctx, FADESLOW_TRANSITION(8, uint8_t, 1) FADESLOW_TRANSITION(16, uint16_t, 2) +#define HWIND_TRANSITION(name, z, type, div, expr) \ +static void h##z##wind##name##_transition(AVFilterContext *ctx, \ + const AVFrame *a, const AVFrame *b, AVFrame *out, \ + float progress, \ + int slice_start, int slice_end, int jobnr) \ +{ \ + XFadeContext *s = ctx->priv; \ + const int width = out->width; \ + \ + for (int y = slice_start; y < slice_end; y++) { \ + const float r = frand(0, y); \ + for (int x = 0; x < width; x++) { \ + const float fx = expr x / (float)width; \ + for (int p = 0; p < s->nb_planes; p++) { \ + const type *xf0 = (const type *)(a->data[p] + y * a->linesize[p]); \ + const type *xf1 = (const type *)(b->data[p] + y * b->linesize[p]); \ + type *dst = (type *)(out->data[p] + y * out->linesize[p]); \ + \ + dst[x] = mix(xf1[x], xf0[x], smoothstep(0.f,-0.2f, fx * (1.f - 0.2f)\ + + 0.2f * r - (1.f - progress)\ + * (1.f + 0.2f))); \ + } \ + } \ + } \ +} + +HWIND_TRANSITION(8, l, uint8_t, 1, 1.f - ) +HWIND_TRANSITION(16, l, uint16_t, 2, 1.f - ) +HWIND_TRANSITION(8, r, uint8_t, 1, ) +HWIND_TRANSITION(16, r, uint16_t, 2, ) + +#define VWIND_TRANSITION(name, z, type, div, expr) \ +static void v##z##wind##name##_transition(AVFilterContext *ctx, \ + const AVFrame *a, const AVFrame *b, AVFrame *out, \ + float progress, \ + int slice_start, int slice_end, int jobnr) \ +{ \ + XFadeContext *s = ctx->priv; \ + const int width = out->width; \ + \ + for (int y = slice_start; y < slice_end; y++) { \ + const float fy = expr y / (float)out->height; \ + for (int x = 0; x < width; x++) { \ + const float r = frand(x, 0); \ + for (int p = 0; p < s->nb_planes; p++) { \ + const type *xf0 = (const type *)(a->data[p] + y * a->linesize[p]); \ + const type *xf1 = (const type *)(b->data[p] + y * b->linesize[p]); \ + type *dst = (type *)(out->data[p] + y * out->linesize[p]); \ + \ + dst[x] = mix(xf1[x], xf0[x], smoothstep(0.f,-0.2f, fy * (1.f - 0.2f) \ + + 0.2f * r - (1.f - progress)\ + * (1.f + 0.2f))); \ + } \ + } \ + } \ +} + +VWIND_TRANSITION(8, u, uint8_t, 1, 1.f - ) +VWIND_TRANSITION(16, u, uint16_t, 2, 1.f - ) +VWIND_TRANSITION(8, d, uint8_t, 1, ) +VWIND_TRANSITION(16, d, uint16_t, 2, ) + static inline double getpix(void *priv, double x, double y, int plane, int nb) { XFadeContext *s = priv; @@ -1886,6 +1956,10 @@ static int config_output(AVFilterLink *outlink) case ZOOMIN: s->transitionf = s->depth <= 8 ? zoomin8_transition : zoomin16_transition; break; case FADEFAST: s->transitionf = s->depth <= 8 ? fadefast8_transition : fadefast16_transition; break; case FADESLOW: s->transitionf = s->depth <= 8 ? fadeslow8_transition : fadeslow16_transition; break; + case HLWIND: s->transitionf = s->depth <= 8 ? hlwind8_transition : hlwind16_transition; break; + case HRWIND: s->transitionf = s->depth <= 8 ? hrwind8_transition : hrwind16_transition; break; + case VUWIND: s->transitionf = s->depth <= 8 ? vuwind8_transition : vuwind16_transition; break; + case VDWIND: s->transitionf = s->depth <= 8 ? vdwind8_transition : vdwind16_transition; break; default: return AVERROR_BUG; } From 6284afec07047b5110cf8e6422df7a922bbb25a4 Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Mon, 22 May 2023 08:23:26 +0200 Subject: [PATCH 1108/2172] avfilter/vf_xfade: avoid some not needed dereferencing in inner loops --- libavfilter/vf_xfade.c | 119 ++++++++++++++++++++++++++--------------- 1 file changed, 76 insertions(+), 43 deletions(-) diff --git a/libavfilter/vf_xfade.c b/libavfilter/vf_xfade.c index 80037ee604d..f52da5570b0 100644 --- a/libavfilter/vf_xfade.c +++ b/libavfilter/vf_xfade.c @@ -221,9 +221,10 @@ static void custom##name##_transition(AVFilterContext *ctx, { \ XFadeContext *s = ctx->priv; \ const int height = slice_end - slice_start; \ + const int width = out->width; \ \ double values[VAR_VARS_NB]; \ - values[VAR_W] = out->width; \ + values[VAR_W] = width; \ values[VAR_H] = out->height; \ values[VAR_PROGRESS] = progress; \ \ @@ -236,7 +237,7 @@ static void custom##name##_transition(AVFilterContext *ctx, \ for (int y = 0; y < height; y++) { \ values[VAR_Y] = slice_start + y; \ - for (int x = 0; x < out->width; x++) { \ + for (int x = 0; x < width; x++) { \ values[VAR_X] = x; \ values[VAR_A] = xf0[x]; \ values[VAR_B] = xf1[x]; \ @@ -280,6 +281,7 @@ static void fade##name##_transition(AVFilterContext *ctx, { \ XFadeContext *s = ctx->priv; \ const int height = slice_end - slice_start; \ + const int width = out->width; \ \ for (int p = 0; p < s->nb_planes; p++) { \ const type *xf0 = (const type *)(a->data[p] + slice_start * a->linesize[p]); \ @@ -287,7 +289,7 @@ static void fade##name##_transition(AVFilterContext *ctx, type *dst = (type *)(out->data[p] + slice_start * out->linesize[p]); \ \ for (int y = 0; y < height; y++) { \ - for (int x = 0; x < out->width; x++) { \ + for (int x = 0; x < width; x++) { \ dst[x] = mix(xf0[x], xf1[x], progress); \ } \ \ @@ -309,7 +311,8 @@ static void wipeleft##name##_transition(AVFilterContext *ctx, { \ XFadeContext *s = ctx->priv; \ const int height = slice_end - slice_start; \ - const int z = out->width * progress; \ + const int width = out->width; \ + const int z = width * progress; \ \ for (int p = 0; p < s->nb_planes; p++) { \ const type *xf0 = (const type *)(a->data[p] + slice_start * a->linesize[p]); \ @@ -317,7 +320,7 @@ static void wipeleft##name##_transition(AVFilterContext *ctx, type *dst = (type *)(out->data[p] + slice_start * out->linesize[p]); \ \ for (int y = 0; y < height; y++) { \ - for (int x = 0; x < out->width; x++) { \ + for (int x = 0; x < width; x++) { \ dst[x] = x > z ? xf1[x] : xf0[x]; \ } \ \ @@ -339,7 +342,8 @@ static void wiperight##name##_transition(AVFilterContext *ctx, { \ XFadeContext *s = ctx->priv; \ const int height = slice_end - slice_start; \ - const int z = out->width * (1.f - progress); \ + const int width = out->width; \ + const int z = width * (1.f - progress); \ \ for (int p = 0; p < s->nb_planes; p++) { \ const type *xf0 = (const type *)(a->data[p] + slice_start * a->linesize[p]); \ @@ -347,7 +351,7 @@ static void wiperight##name##_transition(AVFilterContext *ctx, type *dst = (type *)(out->data[p] + slice_start * out->linesize[p]); \ \ for (int y = 0; y < height; y++) { \ - for (int x = 0; x < out->width; x++) { \ + for (int x = 0; x < width; x++) { \ dst[x] = x > z ? xf0[x] : xf1[x]; \ } \ \ @@ -369,6 +373,7 @@ static void wipeup##name##_transition(AVFilterContext *ctx, { \ XFadeContext *s = ctx->priv; \ const int height = slice_end - slice_start; \ + const int width = out->width; \ const int z = out->height * progress; \ \ for (int p = 0; p < s->nb_planes; p++) { \ @@ -377,7 +382,7 @@ static void wipeup##name##_transition(AVFilterContext *ctx, type *dst = (type *)(out->data[p] + slice_start * out->linesize[p]); \ \ for (int y = 0; y < height; y++) { \ - for (int x = 0; x < out->width; x++) { \ + for (int x = 0; x < width; x++) { \ dst[x] = slice_start + y > z ? xf1[x] : xf0[x]; \ } \ \ @@ -399,6 +404,7 @@ static void wipedown##name##_transition(AVFilterContext *ctx, { \ XFadeContext *s = ctx->priv; \ const int height = slice_end - slice_start; \ + const int width = out->width; \ const int z = out->height * (1.f - progress); \ \ for (int p = 0; p < s->nb_planes; p++) { \ @@ -407,7 +413,7 @@ static void wipedown##name##_transition(AVFilterContext *ctx, type *dst = (type *)(out->data[p] + slice_start * out->linesize[p]); \ \ for (int y = 0; y < height; y++) { \ - for (int x = 0; x < out->width; x++) { \ + for (int x = 0; x < width; x++) { \ dst[x] = slice_start + y > z ? xf0[x] : xf1[x]; \ } \ \ @@ -471,7 +477,7 @@ static void slideright##name##_transition(AVFilterContext *ctx, type *dst = (type *)(out->data[p] + slice_start * out->linesize[p]); \ \ for (int y = 0; y < height; y++) { \ - for (int x = 0; x < out->width; x++) { \ + for (int x = 0; x < width; x++) { \ const int zx = z + x; \ const int zz = zx % width + width * (zx < 0); \ dst[x] = (zx >= 0) && (zx < width) ? xf1[zz] : xf0[zz]; \ @@ -495,6 +501,7 @@ static void slideup##name##_transition(AVFilterContext *ctx, { \ XFadeContext *s = ctx->priv; \ const int height = out->height; \ + const int width = out->width; \ const int z = -progress * height; \ \ for (int p = 0; p < s->nb_planes; p++) { \ @@ -506,7 +513,7 @@ static void slideup##name##_transition(AVFilterContext *ctx, const type *xf0 = (const type *)(a->data[p] + zz * a->linesize[p]); \ const type *xf1 = (const type *)(b->data[p] + zz * b->linesize[p]); \ \ - for (int x = 0; x < out->width; x++) { \ + for (int x = 0; x < width; x++) { \ dst[x] = (zy >= 0) && (zy < height) ? xf1[x] : xf0[x]; \ } \ \ @@ -526,6 +533,7 @@ static void slidedown##name##_transition(AVFilterContext *ctx, { \ XFadeContext *s = ctx->priv; \ const int height = out->height; \ + const int width = out->width; \ const int z = progress * height; \ \ for (int p = 0; p < s->nb_planes; p++) { \ @@ -537,7 +545,7 @@ static void slidedown##name##_transition(AVFilterContext *ctx, const type *xf0 = (const type *)(a->data[p] + zz * a->linesize[p]); \ const type *xf1 = (const type *)(b->data[p] + zz * b->linesize[p]); \ \ - for (int x = 0; x < out->width; x++) { \ + for (int x = 0; x < width; x++) { \ dst[x] = (zy >= 0) && (zy < height) ? xf1[x] : xf0[x]; \ } \ \ @@ -660,6 +668,7 @@ static void fadeblack##name##_transition(AVFilterContext *ctx, { \ XFadeContext *s = ctx->priv; \ const int height = slice_end - slice_start; \ + const int width = out->width; \ const float phase = 0.2f; \ \ for (int p = 0; p < s->nb_planes; p++) { \ @@ -669,7 +678,7 @@ static void fadeblack##name##_transition(AVFilterContext *ctx, const int bg = s->black[p]; \ \ for (int y = 0; y < height; y++) { \ - for (int x = 0; x < out->width; x++) { \ + for (int x = 0; x < width; x++) { \ dst[x] = mix(mix(xf0[x], bg, smoothstep(1.f-phase, 1.f, progress)), \ mix(bg, xf1[x], smoothstep(phase, 1.f, progress)), \ progress); \ @@ -693,6 +702,7 @@ static void fadewhite##name##_transition(AVFilterContext *ctx, { \ XFadeContext *s = ctx->priv; \ const int height = slice_end - slice_start; \ + const int width = out->width; \ const float phase = 0.2f; \ \ for (int p = 0; p < s->nb_planes; p++) { \ @@ -702,7 +712,7 @@ static void fadewhite##name##_transition(AVFilterContext *ctx, const int bg = s->white[p]; \ \ for (int y = 0; y < height; y++) { \ - for (int x = 0; x < out->width; x++) { \ + for (int x = 0; x < width; x++) { \ dst[x] = mix(mix(xf0[x], bg, smoothstep(1.f-phase, 1.f, progress)), \ mix(bg, xf1[x], smoothstep(phase, 1.f, progress)), \ progress); \ @@ -948,13 +958,14 @@ static void vertclose##name##_transition(AVFilterContext *ctx, int slice_start, int slice_end, int jobnr) \ { \ XFadeContext *s = ctx->priv; \ + const int nb_planes = s->nb_planes; \ const int width = out->width; \ const float w2 = out->width / 2; \ \ for (int y = slice_start; y < slice_end; y++) { \ for (int x = 0; x < width; x++) { \ const float smooth = 1.f + fabsf((x - w2) / w2) - progress * 2.f; \ - for (int p = 0; p < s->nb_planes; p++) { \ + for (int p = 0; p < nb_planes; p++) { \ const type *xf0 = (const type *)(a->data[p] + y * a->linesize[p]); \ const type *xf1 = (const type *)(b->data[p] + y * b->linesize[p]); \ type *dst = (type *)(out->data[p] + y * out->linesize[p]); \ @@ -975,13 +986,14 @@ static void horzopen##name##_transition(AVFilterContext *ctx, int slice_start, int slice_end, int jobnr) \ { \ XFadeContext *s = ctx->priv; \ + const int nb_planes = s->nb_planes; \ const int width = out->width; \ const float h2 = out->height / 2; \ \ for (int y = slice_start; y < slice_end; y++) { \ const float smooth = 2.f - fabsf((y - h2) / h2) - progress * 2.f; \ for (int x = 0; x < width; x++) { \ - for (int p = 0; p < s->nb_planes; p++) { \ + for (int p = 0; p < nb_planes; p++) { \ const type *xf0 = (const type *)(a->data[p] + y * a->linesize[p]); \ const type *xf1 = (const type *)(b->data[p] + y * b->linesize[p]); \ type *dst = (type *)(out->data[p] + y * out->linesize[p]); \ @@ -1002,13 +1014,14 @@ static void horzclose##name##_transition(AVFilterContext *ctx, int slice_start, int slice_end, int jobnr) \ { \ XFadeContext *s = ctx->priv; \ + const int nb_planes = s->nb_planes; \ const int width = out->width; \ const float h2 = out->height / 2; \ \ for (int y = slice_start; y < slice_end; y++) { \ const float smooth = 1.f + fabsf((y - h2) / h2) - progress * 2.f; \ for (int x = 0; x < width; x++) { \ - for (int p = 0; p < s->nb_planes; p++) { \ + for (int p = 0; p < nb_planes; p++) { \ const type *xf0 = (const type *)(a->data[p] + y * a->linesize[p]); \ const type *xf1 = (const type *)(b->data[p] + y * b->linesize[p]); \ type *dst = (type *)(out->data[p] + y * out->linesize[p]); \ @@ -1036,12 +1049,13 @@ static void dissolve##name##_transition(AVFilterContext *ctx, int slice_start, int slice_end, int jobnr) \ { \ XFadeContext *s = ctx->priv; \ + const int nb_planes = s->nb_planes; \ const int width = out->width; \ \ for (int y = slice_start; y < slice_end; y++) { \ for (int x = 0; x < width; x++) { \ const float smooth = frand(x, y) * 2.f + progress * 2.f - 1.5f; \ - for (int p = 0; p < s->nb_planes; p++) { \ + for (int p = 0; p < nb_planes; p++) { \ const type *xf0 = (const type *)(a->data[p] + y * a->linesize[p]); \ const type *xf1 = (const type *)(b->data[p] + y * b->linesize[p]); \ type *dst = (type *)(out->data[p] + y * out->linesize[p]); \ @@ -1062,6 +1076,7 @@ static void pixelize##name##_transition(AVFilterContext *ctx, int slice_start, int slice_end, int jobnr) \ { \ XFadeContext *s = ctx->priv; \ + const int nb_planes = s->nb_planes; \ const int w = out->width; \ const int h = out->height; \ const float d = fminf(progress, 1.f - progress); \ @@ -1073,7 +1088,7 @@ static void pixelize##name##_transition(AVFilterContext *ctx, for (int x = 0; x < w; x++) { \ int sx = dist > 0.f ? FFMIN((floorf(x / sqx) + .5f) * sqx, w - 1) : x; \ int sy = dist > 0.f ? FFMIN((floorf(y / sqy) + .5f) * sqy, h - 1) : y; \ - for (int p = 0; p < s->nb_planes; p++) { \ + for (int p = 0; p < nb_planes; p++) { \ const type *xf0 = (const type *)(a->data[p] + sy * a->linesize[p]); \ const type *xf1 = (const type *)(b->data[p] + sy * b->linesize[p]); \ type *dst = (type *)(out->data[p] + y * out->linesize[p]); \ @@ -1094,6 +1109,7 @@ static void diagtl##name##_transition(AVFilterContext *ctx, int slice_start, int slice_end, int jobnr) \ { \ XFadeContext *s = ctx->priv; \ + const int nb_planes = s->nb_planes; \ const int width = out->width; \ const float w = width; \ const float h = out->height; \ @@ -1102,7 +1118,7 @@ static void diagtl##name##_transition(AVFilterContext *ctx, for (int x = 0; x < width; x++) { \ const float smooth = 1.f + x / w * y / h - progress * 2.f; \ \ - for (int p = 0; p < s->nb_planes; p++) { \ + for (int p = 0; p < nb_planes; p++) { \ const type *xf0 = (const type *)(a->data[p] + y * a->linesize[p]); \ const type *xf1 = (const type *)(b->data[p] + y * b->linesize[p]); \ type *dst = (type *)(out->data[p] + y * out->linesize[p]); \ @@ -1123,6 +1139,7 @@ static void diagtr##name##_transition(AVFilterContext *ctx, int slice_start, int slice_end, int jobnr) \ { \ XFadeContext *s = ctx->priv; \ + const int nb_planes = s->nb_planes; \ const int width = out->width; \ const float w = width; \ const float h = out->height; \ @@ -1131,7 +1148,7 @@ static void diagtr##name##_transition(AVFilterContext *ctx, for (int x = 0; x < width; x++) { \ const float smooth = 1.f + (w - 1 - x) / w * y / h - progress * 2.f; \ \ - for (int p = 0; p < s->nb_planes; p++) { \ + for (int p = 0; p < nb_planes; p++) { \ const type *xf0 = (const type *)(a->data[p] + y * a->linesize[p]); \ const type *xf1 = (const type *)(b->data[p] + y * b->linesize[p]); \ type *dst = (type *)(out->data[p] + y * out->linesize[p]); \ @@ -1152,6 +1169,7 @@ static void diagbl##name##_transition(AVFilterContext *ctx, int slice_start, int slice_end, int jobnr) \ { \ XFadeContext *s = ctx->priv; \ + const int nb_planes = s->nb_planes; \ const int width = out->width; \ const float w = width; \ const float h = out->height; \ @@ -1160,7 +1178,7 @@ static void diagbl##name##_transition(AVFilterContext *ctx, for (int x = 0; x < width; x++) { \ const float smooth = 1.f + x / w * (h - 1 - y) / h - progress * 2.f; \ \ - for (int p = 0; p < s->nb_planes; p++) { \ + for (int p = 0; p < nb_planes; p++) { \ const type *xf0 = (const type *)(a->data[p] + y * a->linesize[p]); \ const type *xf1 = (const type *)(b->data[p] + y * b->linesize[p]); \ type *dst = (type *)(out->data[p] + y * out->linesize[p]); \ @@ -1181,6 +1199,7 @@ static void diagbr##name##_transition(AVFilterContext *ctx, int slice_start, int slice_end, int jobnr) \ { \ XFadeContext *s = ctx->priv; \ + const int nb_planes = s->nb_planes; \ const int width = out->width; \ const float w = width; \ const float h = out->height; \ @@ -1190,7 +1209,7 @@ static void diagbr##name##_transition(AVFilterContext *ctx, const float smooth = 1.f + (w - 1 - x) / w * (h - 1 - y) / h - \ progress * 2.f; \ \ - for (int p = 0; p < s->nb_planes; p++) { \ + for (int p = 0; p < nb_planes; p++) { \ const type *xf0 = (const type *)(a->data[p] + y * a->linesize[p]); \ const type *xf1 = (const type *)(b->data[p] + y * b->linesize[p]); \ type *dst = (type *)(out->data[p] + y * out->linesize[p]); \ @@ -1211,6 +1230,7 @@ static void hlslice##name##_transition(AVFilterContext *ctx, int slice_start, int slice_end, int jobnr) \ { \ XFadeContext *s = ctx->priv; \ + const int nb_planes = s->nb_planes; \ const int width = out->width; \ const float w = width; \ \ @@ -1219,7 +1239,7 @@ static void hlslice##name##_transition(AVFilterContext *ctx, const float smooth = smoothstep(-0.5f, 0.f, x / w - progress * 1.5f); \ const float ss = smooth <= fract(10.f * x / w) ? 0.f : 1.f; \ \ - for (int p = 0; p < s->nb_planes; p++) { \ + for (int p = 0; p < nb_planes; p++) { \ const type *xf0 = (const type *)(a->data[p] + y * a->linesize[p]); \ const type *xf1 = (const type *)(b->data[p] + y * b->linesize[p]); \ type *dst = (type *)(out->data[p] + y * out->linesize[p]); \ @@ -1240,6 +1260,7 @@ static void hrslice##name##_transition(AVFilterContext *ctx, int slice_start, int slice_end, int jobnr) \ { \ XFadeContext *s = ctx->priv; \ + const int nb_planes = s->nb_planes; \ const int width = out->width; \ const float w = width; \ \ @@ -1249,7 +1270,7 @@ static void hrslice##name##_transition(AVFilterContext *ctx, const float smooth = smoothstep(-0.5f, 0.f, xx - progress * 1.5f); \ const float ss = smooth <= fract(10.f * xx) ? 0.f : 1.f; \ \ - for (int p = 0; p < s->nb_planes; p++) { \ + for (int p = 0; p < nb_planes; p++) { \ const type *xf0 = (const type *)(a->data[p] + y * a->linesize[p]); \ const type *xf1 = (const type *)(b->data[p] + y * b->linesize[p]); \ type *dst = (type *)(out->data[p] + y * out->linesize[p]); \ @@ -1270,6 +1291,7 @@ static void vuslice##name##_transition(AVFilterContext *ctx, int slice_start, int slice_end, int jobnr) \ { \ XFadeContext *s = ctx->priv; \ + const int nb_planes = s->nb_planes; \ const int width = out->width; \ const float h = out->height; \ \ @@ -1278,7 +1300,7 @@ static void vuslice##name##_transition(AVFilterContext *ctx, const float ss = smooth <= fract(10.f * y / h) ? 0.f : 1.f; \ \ for (int x = 0; x < width; x++) { \ - for (int p = 0; p < s->nb_planes; p++) { \ + for (int p = 0; p < nb_planes; p++) { \ const type *xf0 = (const type *)(a->data[p] + y * a->linesize[p]); \ const type *xf1 = (const type *)(b->data[p] + y * b->linesize[p]); \ type *dst = (type *)(out->data[p] + y * out->linesize[p]); \ @@ -1299,6 +1321,7 @@ static void vdslice##name##_transition(AVFilterContext *ctx, int slice_start, int slice_end, int jobnr) \ { \ XFadeContext *s = ctx->priv; \ + const int nb_planes = s->nb_planes; \ const int width = out->width; \ const float h = out->height; \ \ @@ -1308,7 +1331,7 @@ static void vdslice##name##_transition(AVFilterContext *ctx, const float ss = smooth <= fract(10.f * yy) ? 0.f : 1.f; \ \ for (int x = 0; x < width; x++) { \ - for (int p = 0; p < s->nb_planes; p++) { \ + for (int p = 0; p < nb_planes; p++) { \ const type *xf0 = (const type *)(a->data[p] + y * a->linesize[p]); \ const type *xf1 = (const type *)(b->data[p] + y * b->linesize[p]); \ type *dst = (type *)(out->data[p] + y * out->linesize[p]); \ @@ -1329,12 +1352,13 @@ static void hblur##name##_transition(AVFilterContext *ctx, int slice_start, int slice_end, int jobnr) \ { \ XFadeContext *s = ctx->priv; \ + const int nb_planes = s->nb_planes; \ const int width = out->width; \ const float prog = progress <= 0.5f ? progress * 2.f : (1.f - progress) * 2.f; \ const int size = 1 + (width / 2) * prog; \ \ for (int y = slice_start; y < slice_end; y++) { \ - for (int p = 0; p < s->nb_planes; p++) { \ + for (int p = 0; p < nb_planes; p++) { \ const type *xf0 = (const type *)(a->data[p] + y * a->linesize[p]); \ const type *xf1 = (const type *)(b->data[p] + y * b->linesize[p]); \ type *dst = (type *)(out->data[p] + y * out->linesize[p]); \ @@ -1443,6 +1467,7 @@ static void wipetl##name##_transition(AVFilterContext *ctx, { \ XFadeContext *s = ctx->priv; \ const int height = slice_end - slice_start; \ + const int width = out->width; \ const int zw = out->width * progress; \ const int zh = out->height * progress; \ \ @@ -1452,7 +1477,7 @@ static void wipetl##name##_transition(AVFilterContext *ctx, type *dst = (type *)(out->data[p] + slice_start * out->linesize[p]); \ \ for (int y = 0; y < height; y++) { \ - for (int x = 0; x < out->width; x++) { \ + for (int x = 0; x < width; x++) { \ dst[x] = slice_start + y <= zh && \ x <= zw ? xf0[x] : xf1[x]; \ } \ @@ -1475,7 +1500,8 @@ static void wipetr##name##_transition(AVFilterContext *ctx, { \ XFadeContext *s = ctx->priv; \ const int height = slice_end - slice_start; \ - const int zw = out->width * (1.f - progress); \ + const int width = out->width; \ + const int zw = width * (1.f - progress); \ const int zh = out->height * progress; \ \ for (int p = 0; p < s->nb_planes; p++) { \ @@ -1484,7 +1510,7 @@ static void wipetr##name##_transition(AVFilterContext *ctx, type *dst = (type *)(out->data[p] + slice_start * out->linesize[p]); \ \ for (int y = 0; y < height; y++) { \ - for (int x = 0; x < out->width; x++) { \ + for (int x = 0; x < width; x++) { \ dst[x] = slice_start + y <= zh && \ x > zw ? xf0[x] : xf1[x]; \ } \ @@ -1507,7 +1533,8 @@ static void wipebl##name##_transition(AVFilterContext *ctx, { \ XFadeContext *s = ctx->priv; \ const int height = slice_end - slice_start; \ - const int zw = out->width * progress; \ + const int width = out->width; \ + const int zw = width * progress; \ const int zh = out->height * (1.f - progress); \ \ for (int p = 0; p < s->nb_planes; p++) { \ @@ -1516,7 +1543,7 @@ static void wipebl##name##_transition(AVFilterContext *ctx, type *dst = (type *)(out->data[p] + slice_start * out->linesize[p]); \ \ for (int y = 0; y < height; y++) { \ - for (int x = 0; x < out->width; x++) { \ + for (int x = 0; x < width; x++) { \ dst[x] = slice_start + y > zh && \ x <= zw ? xf0[x] : xf1[x]; \ } \ @@ -1540,7 +1567,8 @@ static void wipebr##name##_transition(AVFilterContext *ctx, XFadeContext *s = ctx->priv; \ const int height = slice_end - slice_start; \ const int zh = out->height * (1.f - progress); \ - const int zw = out->width * (1.f - progress); \ + const int width = out->width; \ + const int zw = width * (1.f - progress); \ \ for (int p = 0; p < s->nb_planes; p++) { \ const type *xf0 = (const type *)(a->data[p] + slice_start * a->linesize[p]); \ @@ -1548,7 +1576,7 @@ static void wipebr##name##_transition(AVFilterContext *ctx, type *dst = (type *)(out->data[p] + slice_start * out->linesize[p]); \ \ for (int y = 0; y < height; y++) { \ - for (int x = 0; x < out->width; x++) { \ + for (int x = 0; x < width; x++) { \ dst[x] = slice_start + y > zh && \ x > zw ? xf0[x] : xf1[x]; \ } \ @@ -1572,6 +1600,7 @@ static void squeezeh##name##_transition(AVFilterContext *ctx, XFadeContext *s = ctx->priv; \ const float h = out->height; \ const int height = slice_end - slice_start; \ + const int width = out->width; \ \ for (int p = 0; p < s->nb_planes; p++) { \ const type *xf1 = (const type *)(b->data[p] + slice_start * b->linesize[p]); \ @@ -1581,13 +1610,13 @@ static void squeezeh##name##_transition(AVFilterContext *ctx, const float z = .5f + ((slice_start + y) / h - .5f) / progress; \ \ if (z < 0.f || z > 1.f) { \ - for (int x = 0; x < out->width; x++) \ + for (int x = 0; x < width; x++) \ dst[x] = xf1[x]; \ } else { \ const int yy = lrintf(z * (h - 1.f)); \ const type *xf0 = (const type *)(a->data[p] + yy * a->linesize[p]); \ \ - for (int x = 0; x < out->width; x++) \ + for (int x = 0; x < width; x++) \ dst[x] = xf0[x]; \ } \ \ @@ -1607,7 +1636,8 @@ static void squeezev##name##_transition(AVFilterContext *ctx, int slice_start, int slice_end, int jobnr) \ { \ XFadeContext *s = ctx->priv; \ - const float w = out->width; \ + const int width = out->width; \ + const float w = width; \ const int height = slice_end - slice_start; \ \ for (int p = 0; p < s->nb_planes; p++) { \ @@ -1616,7 +1646,7 @@ static void squeezev##name##_transition(AVFilterContext *ctx, type *dst = (type *)(out->data[p] + slice_start * out->linesize[p]); \ \ for (int y = 0; y < height; y++) { \ - for (int x = 0; x < out->width; x++) { \ + for (int x = 0; x < width; x++) { \ const float z = .5f + (x / w - .5f) / progress; \ \ if (z < 0.f || z > 1.f) { \ @@ -1651,7 +1681,8 @@ static void zoomin##name##_transition(AVFilterContext *ctx, int slice_start, int slice_end, int jobnr) \ { \ XFadeContext *s = ctx->priv; \ - const float w = out->width; \ + const int width = out->width; \ + const float w = width; \ const float h = out->height; \ const float zf = smoothstep(0.5f, 1.f, progress); \ \ @@ -1661,7 +1692,7 @@ static void zoomin##name##_transition(AVFilterContext *ctx, type *dst = (type *)(out->data[p] + slice_start * out->linesize[p]); \ \ for (int y = slice_start; y < slice_end; y++) { \ - for (int x = 0; x < w; x++) { \ + for (int x = 0; x < width; x++) { \ float zv, u, v; \ int iu, iv; \ \ @@ -1690,6 +1721,7 @@ static void fadefast##name##_transition(AVFilterContext *ctx, { \ XFadeContext *s = ctx->priv; \ const int height = slice_end - slice_start; \ + const int width = out->width; \ const float imax = 1.f / s->max_value; \ \ for (int p = 0; p < s->nb_planes; p++) { \ @@ -1698,7 +1730,7 @@ static void fadefast##name##_transition(AVFilterContext *ctx, type *dst = (type *)(out->data[p] + slice_start * out->linesize[p]); \ \ for (int y = 0; y < height; y++) { \ - for (int x = 0; x < out->width; x++) { \ + for (int x = 0; x < width; x++) { \ dst[x] = mix(xf0[x], xf1[x], powf(progress, 1.f + \ logf(1.f+FFABS(xf0[x]-xf1[x])*imax)\ )); \ @@ -1722,6 +1754,7 @@ static void fadeslow##name##_transition(AVFilterContext *ctx, { \ XFadeContext *s = ctx->priv; \ const int height = slice_end - slice_start; \ + const int width = out->width; \ const float imax = 1.f / s->max_value; \ \ for (int p = 0; p < s->nb_planes; p++) { \ @@ -1730,7 +1763,7 @@ static void fadeslow##name##_transition(AVFilterContext *ctx, type *dst = (type *)(out->data[p] + slice_start * out->linesize[p]); \ \ for (int y = 0; y < height; y++) { \ - for (int x = 0; x < out->width; x++) { \ + for (int x = 0; x < width; x++) { \ dst[x] = mix(xf0[x], xf1[x], powf(progress, 1.f + \ logf(2.f-FFABS(xf0[x]-xf1[x])*imax)\ )); \ From 7428f1e8f2d1ed2d43edbb240d776a39ea205512 Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Mon, 22 May 2023 09:06:22 +0200 Subject: [PATCH 1109/2172] avfilter/vf_xfade: fix fadegrays for gbrp* formats The array elements were left uninitialized. --- libavfilter/vf_xfade.c | 1 + 1 file changed, 1 insertion(+) diff --git a/libavfilter/vf_xfade.c b/libavfilter/vf_xfade.c index f52da5570b0..a0e2e61d404 100644 --- a/libavfilter/vf_xfade.c +++ b/libavfilter/vf_xfade.c @@ -1406,6 +1406,7 @@ static void fadegrays##name##_transition(AVFilterContext *ctx, for (int x = 0; x < width; x++) { \ int bg[2][4]; \ if (is_rgb) { \ + bg[0][0] = bg[1][0] = 0; \ for (int p = 0; p < s->nb_planes; p++) { \ const type *xf0 = (const type *)(a->data[p] + \ y * a->linesize[p]); \ From c00fd025587fc8f028cda2c36f0061070fe91a35 Mon Sep 17 00:00:00 2001 From: Niklas Haas Date: Sun, 21 May 2023 12:22:56 +0200 Subject: [PATCH 1110/2172] lavfi/libplacebo: properly handle EOF The current code relied on pl_queue eventually returning EOF back to the caller, which didn't work in all situations (e.g. single frame input). Also, the current code assumed that ff_inlink_acknowledge_status only fired once, which was patently not true, as the above edge cases demonstrated. Solve both issues by keeping track of the acknowledged link status and forwarding it (instead of trying to probe the pl_queue again) in the event that we run out of queued input frames, as well as (in CFR mode) when we pass the indicated status PTS. --- libavfilter/vf_libplacebo.c | 29 +++++++++++++++++------------ 1 file changed, 17 insertions(+), 12 deletions(-) diff --git a/libavfilter/vf_libplacebo.c b/libavfilter/vf_libplacebo.c index f26d0126beb..a8904b0e6bd 100644 --- a/libavfilter/vf_libplacebo.c +++ b/libavfilter/vf_libplacebo.c @@ -114,6 +114,8 @@ typedef struct LibplaceboContext { /* filter state */ AVFifo *out_pts; ///< timestamps of wanted output frames + int64_t status_pts; + int status; /* settings */ char *out_format_string; @@ -808,19 +810,12 @@ static int libplacebo_activate(AVFilterContext *ctx) if (ret < 0) return ret; - if (ff_inlink_acknowledge_status(inlink, &status, &pts)) { + if (!s->status && ff_inlink_acknowledge_status(inlink, &status, &pts)) { pts = av_rescale_q_rnd(pts, inlink->time_base, outlink->time_base, AV_ROUND_UP); - if (status == AVERROR_EOF) { - /* Signal EOF to pl_queue, and enqueue this output frame to - * make sure we see PL_QUEUE_EOF returned eventually */ - pl_queue_push(s->queue, NULL); - if (!s->fps.num) - av_fifo_write(s->out_pts, &pts, 1); - } else { - ff_outlink_set_status(outlink, status, pts); - return 0; - } + pl_queue_push(s->queue, NULL); /* Signal EOF to pl_queue */ + s->status = status; + s->status_pts = pts; } if (ff_outlink_frame_wanted(outlink)) { @@ -830,7 +825,17 @@ static int libplacebo_activate(AVFilterContext *ctx) if (s->fps.num) { pts = outlink->frame_count_out; } else if (av_fifo_peek(s->out_pts, &pts, 1, 0) < 0) { - ff_inlink_request_frame(inlink); + /* No frames queued */ + if (s->status) { + pts = s->status_pts; + } else { + ff_inlink_request_frame(inlink); + return 0; + } + } + + if (s->status && pts >= s->status_pts) { + ff_outlink_set_status(outlink, s->status, s->status_pts); return 0; } From f66280182acb03604df2ef58c623b4fa39c56444 Mon Sep 17 00:00:00 2001 From: Niklas Haas Date: Sun, 21 May 2023 15:52:40 +0200 Subject: [PATCH 1111/2172] lavfi/vf_libplacebo: add RGB colorspace sanity Explicitly forbid using a non-RGB colorspace with RGB pixel format or vice versa. This mirrors identical logic from vf_scale. --- libavfilter/vf_libplacebo.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/libavfilter/vf_libplacebo.c b/libavfilter/vf_libplacebo.c index a8904b0e6bd..aafe69c4cb9 100644 --- a/libavfilter/vf_libplacebo.c +++ b/libavfilter/vf_libplacebo.c @@ -697,6 +697,13 @@ static int output_frame_mix(AVFilterContext *ctx, if (s->color_primaries >= 0) out->color_primaries = s->color_primaries; + /* Sanity colorspace overrides */ + if (outdesc->flags & AV_PIX_FMT_FLAG_RGB) { + out->colorspace = AVCOL_SPC_RGB; + } else if (out->colorspace == AVCOL_SPC_RGB) { + out->colorspace = AVCOL_SPC_UNSPECIFIED; + } + changed_csp = ref->colorspace != out->colorspace || ref->color_range != out->color_range || ref->color_trc != out->color_trc || From d637f20f057586a0a3976fecab3a619e3efcae92 Mon Sep 17 00:00:00 2001 From: Niklas Haas Date: Sun, 21 May 2023 13:35:35 +0200 Subject: [PATCH 1112/2172] lavfi/vf_libplacebo: switch to new gamut mapping API Upstream deprecated the old ad-hoc, enum/intent-based gamut mapping API and added a new API based on colorimetrically accurate gamut mapping functions. The relevant change for us is the addition of several new modes, as well as deprecation of the old options. Update the documentation accordingly. --- doc/filters.texi | 47 ++++++++++---------- libavfilter/vf_libplacebo.c | 86 +++++++++++++++++++++++++++++-------- 2 files changed, 92 insertions(+), 41 deletions(-) diff --git a/doc/filters.texi b/doc/filters.texi index 909288d3db8..84407067224 100644 --- a/doc/filters.texi +++ b/doc/filters.texi @@ -16353,37 +16353,36 @@ gamut-mapping when dealing with mismatches between wide-gamut or HDR content. In general, libplacebo relies on accurate source tagging and mastering display gamut information to produce the best results. @table @option -@item intent -Rendering intent to use when adapting between different primary color gamuts -(after tone-mapping). -@table @samp -@item perceptual -Perceptual gamut mapping. Currently equivalent to relative colorimetric. -@item relative -Relative colorimetric. This is the default. -@item absolute -Absolute colorimetric. -@item saturation -Saturation mapping. Forcibly stretches the source gamut to the target gamut. -@end table - @item gamut_mode How to handle out-of-gamut colors that can occur as a result of colorimetric gamut mapping. @table @samp @item clip -Do nothing, simply clip out-of-range colors to the RGB volume. This is the -default. -@item warn -Highlight out-of-gamut pixels (by coloring them pink). -@item darken -Linearly reduces content brightness to preserves saturated details, followed by -clipping the remaining out-of-gamut colors. As the name implies, this makes -everything darker, but provides a good balance between preserving details and -colors. +Do nothing, simply clip out-of-range colors to the RGB volume. Low quality but +extremely fast. +@item perceptual +Perceptually soft-clip colors to the gamut volume. This is the default. +@item relative +Relative colorimetric hard-clip. Similar to @code{perceptual} but without +the soft knee. +@item saturation +Saturation mapping, maps primaries directly to primaries in RGB space. +Not recommended except for artificial computer graphics for which a bright, +saturated display is desired. +@item absolute +Absolute colorimetric hard-clip. Performs no adjustment of the white point. @item desaturate Hard-desaturates out-of-gamut colors towards white, while preserving the -luminance. Has a tendency to shift colors. +luminance. Has a tendency to distort the visual appearance of bright objects. +@item darken +Linearly reduces content brightness to preserves saturated details, followed by +clipping the remaining out-of-gamut colors. +@item warn +Highlight out-of-gamut pixels (by inverting/marking them). +@item linear +Linearly reduces chromaticity of the entire image to make it fit within the +target color volume. Be careful when using this on BT.2020 sources without +proper mastering metadata, as doing so will lead to excessive desaturation. @end table @item tonemapping diff --git a/libavfilter/vf_libplacebo.c b/libavfilter/vf_libplacebo.c index aafe69c4cb9..9c431abe75e 100644 --- a/libavfilter/vf_libplacebo.c +++ b/libavfilter/vf_libplacebo.c @@ -56,6 +56,19 @@ enum { TONE_MAP_COUNT, }; +enum { + GAMUT_MAP_CLIP, + GAMUT_MAP_PERCEPTUAL, + GAMUT_MAP_RELATIVE, + GAMUT_MAP_SATURATION, + GAMUT_MAP_ABSOLUTE, + GAMUT_MAP_DESATURATE, + GAMUT_MAP_DARKEN, + GAMUT_MAP_HIGHLIGHT, + GAMUT_MAP_LINEAR, + GAMUT_MAP_COUNT, +}; + static const char *const var_names[] = { "in_w", "iw", ///< width of the input video frame "in_h", "ih", ///< height of the input video frame @@ -188,7 +201,6 @@ typedef struct LibplaceboContext { /* pl_color_map_params */ struct pl_color_map_params color_map_params; - int intent; int gamut_mode; int tonemapping; float tonemapping_param; @@ -204,6 +216,7 @@ typedef struct LibplaceboContext { int gamut_warning; int gamut_clipping; int force_icc_lut; + int intent; #endif /* pl_dither_params */ @@ -274,6 +287,34 @@ static const struct pl_tone_map_function *pl_get_tonemapping_func(int tm) { } } +static void set_gamut_mode(struct pl_color_map_params *p, int gamut_mode) +{ + switch (gamut_mode) { +#if PL_API_VER >= 269 + case GAMUT_MAP_CLIP: p->gamut_mapping = &pl_gamut_map_clip; return; + case GAMUT_MAP_PERCEPTUAL: p->gamut_mapping = &pl_gamut_map_perceptual; return; + case GAMUT_MAP_RELATIVE: p->gamut_mapping = &pl_gamut_map_relative; return; + case GAMUT_MAP_SATURATION: p->gamut_mapping = &pl_gamut_map_saturation; return; + case GAMUT_MAP_ABSOLUTE: p->gamut_mapping = &pl_gamut_map_absolute; return; + case GAMUT_MAP_DESATURATE: p->gamut_mapping = &pl_gamut_map_desaturate; return; + case GAMUT_MAP_DARKEN: p->gamut_mapping = &pl_gamut_map_darken; return; + case GAMUT_MAP_HIGHLIGHT: p->gamut_mapping = &pl_gamut_map_highlight; return; + case GAMUT_MAP_LINEAR: p->gamut_mapping = &pl_gamut_map_linear; return; +#else + case GAMUT_MAP_RELATIVE: p->intent = PL_INTENT_RELATIVE_COLORIMETRIC; return; + case GAMUT_MAP_SATURATION: p->intent = PL_INTENT_SATURATION; return; + case GAMUT_MAP_ABSOLUTE: p->intent = PL_INTENT_ABSOLUTE_COLORIMETRIC; return; + case GAMUT_MAP_DESATURATE: p->gamut_mode = PL_GAMUT_DESATURATE; return; + case GAMUT_MAP_DARKEN: p->gamut_mode = PL_GAMUT_DARKEN; return; + case GAMUT_MAP_HIGHLIGHT: p->gamut_mode = PL_GAMUT_WARN; return; + /* Use defaults for all other cases */ + default: return; +#endif + } + + av_assert0(0); +}; + static int parse_shader(AVFilterContext *avctx, const void *shader, size_t len) { LibplaceboContext *s = avctx->priv; @@ -319,7 +360,7 @@ static int update_settings(AVFilterContext *ctx) int err = 0; LibplaceboContext *s = ctx->priv; enum pl_tone_map_mode tonemapping_mode = s->tonemapping_mode; - enum pl_gamut_mode gamut_mode = s->gamut_mode; + int gamut_mode = s->gamut_mode; uint8_t color_rgba[4]; RET(av_parse_color(color_rgba, s->fillcolor, -1, s)); @@ -338,10 +379,16 @@ static int update_settings(AVFilterContext *ctx) } } + switch (s->intent) { + case PL_INTENT_SATURATION: gamut_mode = GAMUT_MAP_SATURATION; break; + case PL_INTENT_RELATIVE_COLORIMETRIC: gamut_mode = GAMUT_MAP_RELATIVE; break; + case PL_INTENT_ABSOLUTE_COLORIMETRIC: gamut_mode = GAMUT_MAP_ABSOLUTE; break; + } + if (s->gamut_warning) - gamut_mode = PL_GAMUT_WARN; + gamut_mode = GAMUT_MAP_HIGHLIGHT; if (s->gamut_clipping) - gamut_mode = PL_GAMUT_DESATURATE; + gamut_mode = GAMUT_MAP_DESATURATE; #endif s->deband_params = *pl_deband_params( @@ -368,8 +415,6 @@ static int update_settings(AVFilterContext *ctx) ); s->color_map_params = *pl_color_map_params( - .intent = s->intent, - .gamut_mode = gamut_mode, .tone_mapping_function = pl_get_tonemapping_func(s->tonemapping), .tone_mapping_param = s->tonemapping_param, .tone_mapping_mode = tonemapping_mode, @@ -378,6 +423,8 @@ static int update_settings(AVFilterContext *ctx) .lut_size = s->tonemapping_lut_size, ); + set_gamut_mode(&s->color_map_params, gamut_mode); + s->dither_params = *pl_dither_params( .method = s->dithering, .lut_size = s->dither_lut_size, @@ -1155,16 +1202,16 @@ static const AVOption libplacebo_options[] = { { "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" }, - { "gamut_mode", "Gamut-mapping mode", OFFSET(gamut_mode), AV_OPT_TYPE_INT, {.i64 = PL_GAMUT_CLIP}, 0, PL_GAMUT_MODE_COUNT - 1, DYNAMIC, "gamut_mode" }, - { "clip", "Hard-clip gamut boundary", 0, AV_OPT_TYPE_CONST, {.i64 = PL_GAMUT_CLIP}, 0, 0, STATIC, "gamut_mode" }, - { "warn", "Highlight out-of-gamut colors", 0, AV_OPT_TYPE_CONST, {.i64 = PL_GAMUT_WARN}, 0, 0, STATIC, "gamut_mode" }, - { "darken", "Darken image to fit gamut", 0, AV_OPT_TYPE_CONST, {.i64 = PL_GAMUT_DARKEN}, 0, 0, STATIC, "gamut_mode" }, - { "desaturate", "Colorimetrically desaturate colors", 0, AV_OPT_TYPE_CONST, {.i64 = PL_GAMUT_DESATURATE}, 0, 0, STATIC, "gamut_mode" }, + { "gamut_mode", "Gamut-mapping mode", OFFSET(gamut_mode), AV_OPT_TYPE_INT, {.i64 = GAMUT_MAP_PERCEPTUAL}, 0, GAMUT_MAP_COUNT - 1, DYNAMIC, "gamut_mode" }, + { "clip", "Hard-clip (RGB per-channel)", 0, AV_OPT_TYPE_CONST, {.i64 = GAMUT_MAP_CLIP}, 0, 0, STATIC, "gamut_mode" }, + { "perceptual", "Colorimetric soft clipping", 0, AV_OPT_TYPE_CONST, {.i64 = GAMUT_MAP_PERCEPTUAL}, 0, 0, STATIC, "gamut_mode" }, + { "relative", "Relative colorimetric clipping", 0, AV_OPT_TYPE_CONST, {.i64 = GAMUT_MAP_RELATIVE}, 0, 0, STATIC, "gamut_mode" }, + { "saturation", "Saturation mapping (RGB -> RGB)", 0, AV_OPT_TYPE_CONST, {.i64 = GAMUT_MAP_SATURATION}, 0, 0, STATIC, "gamut_mode" }, + { "absolute", "Absolute colorimetric clipping", 0, AV_OPT_TYPE_CONST, {.i64 = GAMUT_MAP_ABSOLUTE}, 0, 0, STATIC, "gamut_mode" }, + { "desaturate", "Colorimetrically desaturate colors towards white", 0, AV_OPT_TYPE_CONST, {.i64 = GAMUT_MAP_DESATURATE}, 0, 0, STATIC, "gamut_mode" }, + { "darken", "Colorimetric clip with bias towards darkening image to fit gamut", 0, AV_OPT_TYPE_CONST, {.i64 = GAMUT_MAP_DARKEN}, 0, 0, STATIC, "gamut_mode" }, + { "warn", "Highlight out-of-gamut colors", 0, AV_OPT_TYPE_CONST, {.i64 = GAMUT_MAP_HIGHLIGHT}, 0, 0, STATIC, "gamut_mode" }, + { "linear", "Linearly reduce chromaticity to fit gamut", 0, AV_OPT_TYPE_CONST, {.i64 = GAMUT_MAP_LINEAR}, 0, 0, STATIC, "gamut_mode" }, { "tonemapping", "Tone-mapping algorithm", OFFSET(tonemapping), AV_OPT_TYPE_INT, {.i64 = TONE_MAP_AUTO}, 0, TONE_MAP_COUNT - 1, DYNAMIC, "tonemap" }, { "auto", "Automatic selection", 0, AV_OPT_TYPE_CONST, {.i64 = TONE_MAP_AUTO}, 0, 0, STATIC, "tonemap" }, { "clip", "No tone mapping (clip", 0, AV_OPT_TYPE_CONST, {.i64 = TONE_MAP_CLIP}, 0, 0, STATIC, "tonemap" }, @@ -1196,7 +1243,12 @@ static const AVOption libplacebo_options[] = { { "desaturation_strength", "Desaturation strength", OFFSET(desat_str), AV_OPT_TYPE_FLOAT, {.dbl = -1.0}, -1.0, 1.0, DYNAMIC | AV_OPT_FLAG_DEPRECATED }, { "desaturation_exponent", "Desaturation exponent", OFFSET(desat_exp), AV_OPT_TYPE_FLOAT, {.dbl = -1.0}, -1.0, 10.0, DYNAMIC | AV_OPT_FLAG_DEPRECATED }, { "gamut_warning", "Highlight out-of-gamut colors", OFFSET(gamut_warning), AV_OPT_TYPE_BOOL, {.i64 = 0}, 0, 1, DYNAMIC | AV_OPT_FLAG_DEPRECATED }, - { "gamut_clipping", "Enable colorimetric gamut clipping", OFFSET(gamut_clipping), AV_OPT_TYPE_BOOL, {.i64 = 0}, 0, 1, DYNAMIC | AV_OPT_FLAG_DEPRECATED }, + { "gamut_clipping", "Enable desaturating colorimetric gamut clipping", OFFSET(gamut_clipping), AV_OPT_TYPE_BOOL, {.i64 = 0}, 0, 1, DYNAMIC | AV_OPT_FLAG_DEPRECATED }, + { "intent", "Rendering intent", OFFSET(intent), AV_OPT_TYPE_INT, {.i64 = PL_INTENT_PERCEPTUAL}, 0, 3, DYNAMIC | AV_OPT_FLAG_DEPRECATED, "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" }, #endif { "dithering", "Dither method to use", OFFSET(dithering), AV_OPT_TYPE_INT, {.i64 = PL_DITHER_BLUE_NOISE}, -1, PL_DITHER_METHOD_COUNT - 1, DYNAMIC, "dither" }, From 643cf2ec465985ff4a709906e4b6bc8f44f99547 Mon Sep 17 00:00:00 2001 From: Niklas Haas Date: Sun, 21 May 2023 13:36:54 +0200 Subject: [PATCH 1113/2172] lavfi/vf_libplacebo: update for new tone mapping API This algorithm has once again been refactored, this time leading to a dropping of the old `tone_mapping_mode` field, to be replaced by a single tunable hybrid mode with configurable strength. We can approximately map the old modes onto the new API for backwards compatibility. Replace deprecated enums by their integer equivalents to safely preserve this API until the next bump. --- doc/filters.texi | 34 +++++-------------------- libavfilter/vf_libplacebo.c | 49 ++++++++++++++++++++----------------- 2 files changed, 33 insertions(+), 50 deletions(-) diff --git a/doc/filters.texi b/doc/filters.texi index 84407067224..d6d0786832e 100644 --- a/doc/filters.texi +++ b/doc/filters.texi @@ -16461,42 +16461,20 @@ For tunable tone mapping functions, this parameter can be used to fine-tune the curve behavior. Refer to the documentation of @code{tonemapping}. The default value of @code{0.0} is replaced by the curve's preferred default setting. -@item tonemapping_mode -This option determines how the tone mapping function specified by -@code{tonemapping} is applied to the colors in a scene. Possible values are: -@table @samp -@item auto -Automatic selection based on internal heuristics. This is the default. -@item rgb -Apply the function per-channel in the RGB colorspace. -Per-channel tone-mapping in RGB. Guarantees no clipping and heavily desaturates -the output, but distorts the colors quite significantly. Very similar to the -"Hollywood" look and feel. -@item max -Tone-mapping is performed on the brightest component found in the signal. Good -at preserving details in highlights, but has a tendency to crush blacks. -@item hybrid -Tone-map per-channel for highlights and linearly (luma-based) for -midtones/shadows, based on a fixed gamma @code{2.4} coefficient curve. -@item luma -Tone-map linearly on the luma component (CIE Y), and adjust (desaturate) the -chromaticities to compensate using a simple constant factor. This is -essentially the mode used in ITU-R BT.2446 method A. -@end table - @item inverse_tonemapping If enabled, this filter will also attempt stretching SDR signals to fill HDR output color volumes. Disabled by default. -@item tonemapping_crosstalk -Extra tone-mapping crosstalk factor, between @code{0.0} and @code{0.3}. This -can help reduce issues tone-mapping certain bright spectral colors. Defaults to -@code{0.04}. - @item tonemapping_lut_size Size of the tone-mapping LUT, between @code{2} and @code{1024}. Defaults to @code{256}. Note that this figure is squared when combined with @code{peak_detect}. + +@item hybrid_mix +If nonzero, this much of the upper range of the tone-mapped result is smoothly +mixed with a per-channel (LMS) tone-mapped version. Helps avoid unnatural +blown-out highlights when tone-mapping very bright, strongly saturated colors. +Defaults to @code{0.2}. @end table @subsubsection Dithering diff --git a/libavfilter/vf_libplacebo.c b/libavfilter/vf_libplacebo.c index 9c431abe75e..a851ee3067d 100644 --- a/libavfilter/vf_libplacebo.c +++ b/libavfilter/vf_libplacebo.c @@ -204,10 +204,9 @@ typedef struct LibplaceboContext { int gamut_mode; int tonemapping; float tonemapping_param; - int tonemapping_mode; int inverse_tonemapping; - float crosstalk; int tonemapping_lut_size; + float hybrid_mix; #if FF_API_LIBPLACEBO_OPTS /* for backwards compatibility */ @@ -217,6 +216,8 @@ typedef struct LibplaceboContext { int gamut_clipping; int force_icc_lut; int intent; + int tonemapping_mode; + float crosstalk; #endif /* pl_dither_params */ @@ -359,24 +360,23 @@ static int update_settings(AVFilterContext *ctx) { int err = 0; LibplaceboContext *s = ctx->priv; - enum pl_tone_map_mode tonemapping_mode = s->tonemapping_mode; int gamut_mode = s->gamut_mode; + float hybrid_mix = s->hybrid_mix; uint8_t color_rgba[4]; RET(av_parse_color(color_rgba, s->fillcolor, -1, s)); #if FF_API_LIBPLACEBO_OPTS /* backwards compatibility with older API */ - if (!tonemapping_mode && (s->desat_str >= 0.0f || s->desat_exp >= 0.0f)) { - float str = s->desat_str < 0.0f ? 0.9f : s->desat_str; - float exp = s->desat_exp < 0.0f ? 0.2f : s->desat_exp; - if (str >= 0.9f && exp <= 0.1f) { - tonemapping_mode = PL_TONE_MAP_RGB; - } else if (str > 0.1f) { - tonemapping_mode = PL_TONE_MAP_HYBRID; - } else { - tonemapping_mode = PL_TONE_MAP_LUMA; - } + switch (s->tonemapping_mode) { + case 0: /*PL_TONE_MAP_AUTO*/ + if (s->desat_str >= 0.0f) + hybrid_mix = s->desat_str; + break; + case 1: /*PL_TONE_MAP_RGB*/ hybrid_mix = 1.0f; break; + case 2: /*PL_TONE_MAP_HYBRID*/ hybrid_mix = 0.2f; break; + case 3: /*PL_TONE_MAP_LUMA*/ hybrid_mix = 0.0f; break; + case 4: /*PL_TONE_MAP_MAX*/ hybrid_mix = 0.0f; break; } switch (s->intent) { @@ -415,11 +415,15 @@ static int update_settings(AVFilterContext *ctx) ); s->color_map_params = *pl_color_map_params( +#if PL_API_VER >= 269 + .hybrid_mix = hybrid_mix, +#elif FF_API_LIBPLACEBO_OPTS + .tone_mapping_mode = s->tonemapping_mode, + .tone_mapping_crosstalk = s->crosstalk, +#endif .tone_mapping_function = pl_get_tonemapping_func(s->tonemapping), .tone_mapping_param = s->tonemapping_param, - .tone_mapping_mode = tonemapping_mode, .inverse_tone_mapping = s->inverse_tonemapping, - .tone_mapping_crosstalk = s->crosstalk, .lut_size = s->tonemapping_lut_size, ); @@ -1228,15 +1232,9 @@ static const AVOption libplacebo_options[] = { { "gamma", "Gamma function with knee", 0, AV_OPT_TYPE_CONST, {.i64 = TONE_MAP_GAMMA}, 0, 0, STATIC, "tonemap" }, { "linear", "Perceptually linear stretch", 0, AV_OPT_TYPE_CONST, {.i64 = TONE_MAP_LINEAR}, 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 }, - { "tonemapping_mode", "Tone-mapping mode", OFFSET(tonemapping_mode), AV_OPT_TYPE_INT, {.i64 = PL_TONE_MAP_AUTO}, 0, PL_TONE_MAP_MODE_COUNT - 1, DYNAMIC, "tonemap_mode" }, - { "auto", "Automatic selection", 0, AV_OPT_TYPE_CONST, {.i64 = PL_TONE_MAP_AUTO}, 0, 0, STATIC, "tonemap_mode" }, - { "rgb", "Per-channel (RGB)", 0, AV_OPT_TYPE_CONST, {.i64 = PL_TONE_MAP_RGB}, 0, 0, STATIC, "tonemap_mode" }, - { "max", "Maximum component", 0, AV_OPT_TYPE_CONST, {.i64 = PL_TONE_MAP_MAX}, 0, 0, STATIC, "tonemap_mode" }, - { "hybrid", "Hybrid of Luma/RGB", 0, AV_OPT_TYPE_CONST, {.i64 = PL_TONE_MAP_HYBRID}, 0, 0, STATIC, "tonemap_mode" }, - { "luma", "Luminance", 0, AV_OPT_TYPE_CONST, {.i64 = PL_TONE_MAP_LUMA}, 0, 0, STATIC, "tonemap_mode" }, { "inverse_tonemapping", "Inverse tone mapping (range expansion)", OFFSET(inverse_tonemapping), AV_OPT_TYPE_BOOL, {.i64 = 0}, 0, 1, DYNAMIC }, - { "tonemapping_crosstalk", "Crosstalk factor for tone-mapping", OFFSET(crosstalk), AV_OPT_TYPE_FLOAT, {.dbl = 0.04}, 0.0, 0.30, DYNAMIC }, { "tonemapping_lut_size", "Tone-mapping LUT size", OFFSET(tonemapping_lut_size), AV_OPT_TYPE_INT, {.i64 = 256}, 2, 1024, DYNAMIC }, + { "hybrid_mix", "Tone-mapping hybrid LMS mixing coefficient", OFFSET(hybrid_mix), AV_OPT_TYPE_FLOAT, {.dbl = 0.20}, 0.0, 1.00, DYNAMIC }, #if FF_API_LIBPLACEBO_OPTS /* deprecated options for backwards compatibility, defaulting to -1 to not override the new defaults */ @@ -1249,6 +1247,13 @@ static const AVOption libplacebo_options[] = { { "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_mode", "Tone-mapping mode", OFFSET(tonemapping_mode), AV_OPT_TYPE_INT, {.i64 = 0}, 0, 4, DYNAMIC | AV_OPT_FLAG_DEPRECATED, "tonemap_mode" }, + { "auto", "Automatic selection", 0, AV_OPT_TYPE_CONST, {.i64 = 0}, 0, 0, STATIC, "tonemap_mode" }, + { "rgb", "Per-channel (RGB)", 0, AV_OPT_TYPE_CONST, {.i64 = 1}, 0, 0, STATIC, "tonemap_mode" }, + { "max", "Maximum component", 0, AV_OPT_TYPE_CONST, {.i64 = 2}, 0, 0, STATIC, "tonemap_mode" }, + { "hybrid", "Hybrid of Luma/RGB", 0, AV_OPT_TYPE_CONST, {.i64 = 3}, 0, 0, STATIC, "tonemap_mode" }, + { "luma", "Luminance", 0, AV_OPT_TYPE_CONST, {.i64 = 4}, 0, 0, STATIC, "tonemap_mode" }, + { "tonemapping_crosstalk", "Crosstalk factor for tone-mapping", OFFSET(crosstalk), AV_OPT_TYPE_FLOAT, {.dbl = 0.04}, 0.0, 0.30, DYNAMIC | AV_OPT_FLAG_DEPRECATED }, #endif { "dithering", "Dither method to use", OFFSET(dithering), AV_OPT_TYPE_INT, {.i64 = PL_DITHER_BLUE_NOISE}, -1, PL_DITHER_METHOD_COUNT - 1, DYNAMIC, "dither" }, From 21715ecff14c814227cf0b24ca7b0bac756d1568 Mon Sep 17 00:00:00 2001 From: Niklas Haas Date: Mon, 15 May 2023 10:57:42 +0200 Subject: [PATCH 1114/2172] lavfi/vf_libplacebo: update peak detection options Upstream peak detection lost one option and gained one option. Update code and documentation as required. --- doc/filters.texi | 9 +++++---- libavfilter/vf_libplacebo.c | 11 +++++++++-- 2 files changed, 14 insertions(+), 6 deletions(-) diff --git a/doc/filters.texi b/doc/filters.texi index d6d0786832e..76d9f11edc3 100644 --- a/doc/filters.texi +++ b/doc/filters.texi @@ -16341,10 +16341,11 @@ logarithmic scale between @code{0.0} and @code{100.0}. Default to @code{5.5} and @code{10.0}, respectively. Setting either to a negative value disables this functionality. -@item overshoot -Peak smoothing overshoot margin, between @code{0.0} and @code{1.0}. Provides a -safety margin to prevent clipping as a result of peak smoothing. Defaults to -@code{0.05}, corresponding to a margin of 5%. +@item percentile +Which percentile of the frame brightness histogram to use as the source peak +for tone-mapping. Defaults to @code{99.995}, a fairly conservative value. +Setting this to @code{100.0} disables frame histogram measurement and instead +uses the true peak brightness for tone-mapping. @end table @subsubsection Tone mapping diff --git a/libavfilter/vf_libplacebo.c b/libavfilter/vf_libplacebo.c index a851ee3067d..27b65cdb5b5 100644 --- a/libavfilter/vf_libplacebo.c +++ b/libavfilter/vf_libplacebo.c @@ -197,7 +197,7 @@ typedef struct LibplaceboContext { float min_peak; float scene_low; float scene_high; - float overshoot; + float percentile; /* pl_color_map_params */ struct pl_color_map_params color_map_params; @@ -218,6 +218,7 @@ typedef struct LibplaceboContext { int intent; int tonemapping_mode; float crosstalk; + float overshoot; #endif /* pl_dither_params */ @@ -411,7 +412,12 @@ static int update_settings(AVFilterContext *ctx) .minimum_peak = s->min_peak, .scene_threshold_low = s->scene_low, .scene_threshold_high = s->scene_high, +#if PL_API_VER >= 263 + .percentile = s->percentile, +#endif +#if FF_API_LIBPLACEBO_OPTS && PL_API_VER < 256 .overshoot_margin = s->overshoot, +#endif ); s->color_map_params = *pl_color_map_params( @@ -1204,7 +1210,7 @@ static const AVOption libplacebo_options[] = { { "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 }, + { "percentile", "Peak detection percentile", OFFSET(percentile), AV_OPT_TYPE_FLOAT, {.dbl = 99.995}, 0.0, 100.0, DYNAMIC }, { "gamut_mode", "Gamut-mapping mode", OFFSET(gamut_mode), AV_OPT_TYPE_INT, {.i64 = GAMUT_MAP_PERCEPTUAL}, 0, GAMUT_MAP_COUNT - 1, DYNAMIC, "gamut_mode" }, { "clip", "Hard-clip (RGB per-channel)", 0, AV_OPT_TYPE_CONST, {.i64 = GAMUT_MAP_CLIP}, 0, 0, STATIC, "gamut_mode" }, @@ -1254,6 +1260,7 @@ static const AVOption libplacebo_options[] = { { "hybrid", "Hybrid of Luma/RGB", 0, AV_OPT_TYPE_CONST, {.i64 = 3}, 0, 0, STATIC, "tonemap_mode" }, { "luma", "Luminance", 0, AV_OPT_TYPE_CONST, {.i64 = 4}, 0, 0, STATIC, "tonemap_mode" }, { "tonemapping_crosstalk", "Crosstalk factor for tone-mapping", OFFSET(crosstalk), AV_OPT_TYPE_FLOAT, {.dbl = 0.04}, 0.0, 0.30, DYNAMIC | AV_OPT_FLAG_DEPRECATED }, + { "overshoot", "Tone-mapping overshoot margin", OFFSET(overshoot), AV_OPT_TYPE_FLOAT, {.dbl = 0.05}, 0.0, 1.0, DYNAMIC | AV_OPT_FLAG_DEPRECATED }, #endif { "dithering", "Dither method to use", OFFSET(dithering), AV_OPT_TYPE_INT, {.i64 = PL_DITHER_BLUE_NOISE}, -1, PL_DITHER_METHOD_COUNT - 1, DYNAMIC, "dither" }, From 877ccaf776c92866e17493b48da49fab5b9ef11a Mon Sep 17 00:00:00 2001 From: Niklas Haas Date: Sun, 21 May 2023 13:38:42 +0200 Subject: [PATCH 1115/2172] lavfi/vf_libplacebo: don't intrude on pl_ namespace No reason to use this prefix here. --- libavfilter/vf_libplacebo.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libavfilter/vf_libplacebo.c b/libavfilter/vf_libplacebo.c index 27b65cdb5b5..65fe6ef746d 100644 --- a/libavfilter/vf_libplacebo.c +++ b/libavfilter/vf_libplacebo.c @@ -269,7 +269,7 @@ static void pl_av_log(void *log_ctx, enum pl_log_level level, const char *msg) av_log(log_ctx, av_lev, "%s\n", msg); } -static const struct pl_tone_map_function *pl_get_tonemapping_func(int tm) { +static const struct pl_tone_map_function *get_tonemapping_func(int tm) { switch (tm) { case TONE_MAP_AUTO: return &pl_tone_map_auto; case TONE_MAP_CLIP: return &pl_tone_map_clip; @@ -427,7 +427,7 @@ static int update_settings(AVFilterContext *ctx) .tone_mapping_mode = s->tonemapping_mode, .tone_mapping_crosstalk = s->crosstalk, #endif - .tone_mapping_function = pl_get_tonemapping_func(s->tonemapping), + .tone_mapping_function = get_tonemapping_func(s->tonemapping), .tone_mapping_param = s->tonemapping_param, .inverse_tone_mapping = s->inverse_tonemapping, .lut_size = s->tonemapping_lut_size, From c37cf59c5bbad7cedf288b2dc198c928acd397fa Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Mon, 22 May 2023 16:54:44 +0200 Subject: [PATCH 1116/2172] avfilter/vf_xfade: send EOF to first input early No point to consume 1st input frames any more after crossfade is over. --- libavfilter/vf_xfade.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/libavfilter/vf_xfade.c b/libavfilter/vf_xfade.c index a0e2e61d404..a13a7db627e 100644 --- a/libavfilter/vf_xfade.c +++ b/libavfilter/vf_xfade.c @@ -2067,9 +2067,13 @@ static int xfade_activate(AVFilterContext *ctx) if (s->xfade_is_over) { if (!s->eof[0]) { - ret = ff_inlink_consume_frame(ctx->inputs[0], &in); - if (ret > 0) - av_frame_free(&in); + if (ff_inlink_queued_frames(ctx->inputs[0]) > 0) { + ret = ff_inlink_consume_frame(ctx->inputs[0], &in); + if (ret > 0) + av_frame_free(&in); + } + ff_inlink_set_status(ctx->inputs[0], AVERROR_EOF); + s->eof[0] = 1; } ret = ff_inlink_consume_frame(ctx->inputs[1], &in); if (ret < 0) { From 94a96471954e41101d08883100a19bfe3cd0a17b Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Wed, 10 May 2023 08:49:21 +0200 Subject: [PATCH 1117/2172] fftools/ffmpeg: shorten a variable name There is only one frame used in decode_video() -- the one output by the decoder. So there is no point in explicitly calling it the _decoded_ frame. --- fftools/ffmpeg.c | 52 ++++++++++++++++++++++++------------------------ 1 file changed, 26 insertions(+), 26 deletions(-) diff --git a/fftools/ffmpeg.c b/fftools/ffmpeg.c index ebd793a98c5..084192f270d 100644 --- a/fftools/ffmpeg.c +++ b/fftools/ffmpeg.c @@ -1027,7 +1027,7 @@ static int64_t video_duration_estimate(const InputStream *ist, const AVFrame *fr static int decode_video(InputStream *ist, const AVPacket *pkt, int *got_output, int eof, int *decode_failed) { - AVFrame *decoded_frame = ist->decoded_frame; + AVFrame *frame = ist->decoded_frame; int ret = 0, err = 0; int64_t best_effort_timestamp; @@ -1038,7 +1038,7 @@ static int decode_video(InputStream *ist, const AVPacket *pkt, int *got_output, return 0; update_benchmark(NULL); - ret = decode(ist, ist->dec_ctx, decoded_frame, got_output, pkt); + ret = decode(ist, ist->dec_ctx, frame, got_output, pkt); update_benchmark("decode_video %d.%d", ist->file_index, ist->st->index); if (ret < 0) *decode_failed = 1; @@ -1062,13 +1062,13 @@ static int decode_video(InputStream *ist, const AVPacket *pkt, int *got_output, check_decode_result(ist, got_output, ret); if (*got_output && ret >= 0) { - if (ist->dec_ctx->width != decoded_frame->width || - ist->dec_ctx->height != decoded_frame->height || - ist->dec_ctx->pix_fmt != decoded_frame->format) { + if (ist->dec_ctx->width != frame->width || + ist->dec_ctx->height != frame->height || + ist->dec_ctx->pix_fmt != frame->format) { av_log(NULL, AV_LOG_DEBUG, "Frame parameters mismatch context %d,%d,%d != %d,%d,%d\n", - decoded_frame->width, - decoded_frame->height, - decoded_frame->format, + frame->width, + frame->height, + frame->format, ist->dec_ctx->width, ist->dec_ctx->height, ist->dec_ctx->pix_fmt); @@ -1079,17 +1079,17 @@ static int decode_video(InputStream *ist, const AVPacket *pkt, int *got_output, return ret; if(ist->top_field_first>=0) - decoded_frame->flags |= AV_FRAME_FLAG_TOP_FIELD_FIRST; + frame->flags |= AV_FRAME_FLAG_TOP_FIELD_FIRST; ist->frames_decoded++; - if (ist->hwaccel_retrieve_data && decoded_frame->format == ist->hwaccel_pix_fmt) { - err = ist->hwaccel_retrieve_data(ist->dec_ctx, decoded_frame); + if (ist->hwaccel_retrieve_data && frame->format == ist->hwaccel_pix_fmt) { + err = ist->hwaccel_retrieve_data(ist->dec_ctx, frame); if (err < 0) goto fail; } - best_effort_timestamp= decoded_frame->best_effort_timestamp; + best_effort_timestamp = frame->best_effort_timestamp; if (ist->framerate.num) best_effort_timestamp = ist->cfr_next_pts++; @@ -1100,13 +1100,13 @@ static int decode_video(InputStream *ist, const AVPacket *pkt, int *got_output, ist->last_frame_pts + ist->last_frame_duration_est; if(best_effort_timestamp != AV_NOPTS_VALUE) { - decoded_frame->pts = best_effort_timestamp; + frame->pts = best_effort_timestamp; } // update timestamp history - ist->last_frame_duration_est = video_duration_estimate(ist, decoded_frame); - ist->last_frame_pts = decoded_frame->pts; - ist->last_frame_tb = decoded_frame->time_base; + ist->last_frame_duration_est = video_duration_estimate(ist, frame); + ist->last_frame_pts = frame->pts; + ist->last_frame_tb = frame->time_base; if (debug_ts) { av_log(ist, AV_LOG_INFO, @@ -1115,25 +1115,25 @@ static int decode_video(InputStream *ist, const AVPacket *pkt, int *got_output, "best_effort_ts:%"PRId64" best_effort_ts_time:%s " "duration:%s duration_time:%s " "keyframe:%d frame_type:%d time_base:%d/%d\n", - av_ts2str(decoded_frame->pts), - av_ts2timestr(decoded_frame->pts, &ist->st->time_base), - av_ts2str(decoded_frame->pkt_dts), - av_ts2timestr(decoded_frame->pkt_dts, &ist->st->time_base), + av_ts2str(frame->pts), + av_ts2timestr(frame->pts, &ist->st->time_base), + av_ts2str(frame->pkt_dts), + av_ts2timestr(frame->pkt_dts, &ist->st->time_base), best_effort_timestamp, av_ts2timestr(best_effort_timestamp, &ist->st->time_base), - av_ts2str(decoded_frame->duration), - av_ts2timestr(decoded_frame->duration, &ist->st->time_base), - !!(decoded_frame->flags & AV_FRAME_FLAG_KEY), decoded_frame->pict_type, + av_ts2str(frame->duration), + av_ts2timestr(frame->duration, &ist->st->time_base), + !!(frame->flags & AV_FRAME_FLAG_KEY), frame->pict_type, ist->st->time_base.num, ist->st->time_base.den); } if (ist->st->sample_aspect_ratio.num) - decoded_frame->sample_aspect_ratio = ist->st->sample_aspect_ratio; + frame->sample_aspect_ratio = ist->st->sample_aspect_ratio; - err = send_frame_to_filters(ist, decoded_frame); + err = send_frame_to_filters(ist, frame); fail: - av_frame_unref(decoded_frame); + av_frame_unref(frame); return err < 0 ? err : ret; } From 1372e81aaa46e9175fdc46adea4a68177b213b93 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Wed, 10 May 2023 08:53:48 +0200 Subject: [PATCH 1118/2172] fftools/ffmpeg: drop a useless local variable Store decoded frame timestamp directly in AVFrame.pts, there is no advantage to using a separate local variable for it. --- fftools/ffmpeg.c | 18 +++++------------- 1 file changed, 5 insertions(+), 13 deletions(-) diff --git a/fftools/ffmpeg.c b/fftools/ffmpeg.c index 084192f270d..60f0ff3b124 100644 --- a/fftools/ffmpeg.c +++ b/fftools/ffmpeg.c @@ -1029,7 +1029,6 @@ static int decode_video(InputStream *ist, const AVPacket *pkt, int *got_output, { AVFrame *frame = ist->decoded_frame; int ret = 0, err = 0; - int64_t best_effort_timestamp; // With fate-indeo3-2, we're getting 0-sized packets before EOF for some // reason. This seems like a semi-critical bug. Don't trigger EOF, and @@ -1089,19 +1088,15 @@ static int decode_video(InputStream *ist, const AVPacket *pkt, int *got_output, goto fail; } - best_effort_timestamp = frame->best_effort_timestamp; + frame->pts = frame->best_effort_timestamp; if (ist->framerate.num) - best_effort_timestamp = ist->cfr_next_pts++; + frame->pts = ist->cfr_next_pts++; // no timestamp available - extrapolate from previous frame duration - if (best_effort_timestamp == AV_NOPTS_VALUE) - best_effort_timestamp = ist->last_frame_pts == AV_NOPTS_VALUE ? 0 : - ist->last_frame_pts + ist->last_frame_duration_est; - - if(best_effort_timestamp != AV_NOPTS_VALUE) { - frame->pts = best_effort_timestamp; - } + if (frame->pts == AV_NOPTS_VALUE) + frame->pts = ist->last_frame_pts == AV_NOPTS_VALUE ? 0 : + ist->last_frame_pts + ist->last_frame_duration_est; // update timestamp history ist->last_frame_duration_est = video_duration_estimate(ist, frame); @@ -1112,15 +1107,12 @@ static int decode_video(InputStream *ist, const AVPacket *pkt, int *got_output, av_log(ist, AV_LOG_INFO, "decoder -> pts:%s pts_time:%s " "pkt_dts:%s pkt_dts_time:%s " - "best_effort_ts:%"PRId64" best_effort_ts_time:%s " "duration:%s duration_time:%s " "keyframe:%d frame_type:%d time_base:%d/%d\n", av_ts2str(frame->pts), av_ts2timestr(frame->pts, &ist->st->time_base), av_ts2str(frame->pkt_dts), av_ts2timestr(frame->pkt_dts, &ist->st->time_base), - best_effort_timestamp, - av_ts2timestr(best_effort_timestamp, &ist->st->time_base), av_ts2str(frame->duration), av_ts2timestr(frame->duration, &ist->st->time_base), !!(frame->flags & AV_FRAME_FLAG_KEY), frame->pict_type, From 7b41785eb604152dd99c3e58f4999c2b0cd4c681 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Wed, 10 May 2023 09:02:43 +0200 Subject: [PATCH 1119/2172] fftools/ffmpeg: replace stream timebase with decoded frame one They are the same for now, but this may change in the future. --- fftools/ffmpeg.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/fftools/ffmpeg.c b/fftools/ffmpeg.c index 60f0ff3b124..9e5e56e9e77 100644 --- a/fftools/ffmpeg.c +++ b/fftools/ffmpeg.c @@ -993,7 +993,7 @@ static int64_t video_duration_estimate(const InputStream *ist, const AVFrame *fr AVRational field_rate = av_mul_q(ist->dec_ctx->framerate, (AVRational){ 2, 1 }); codec_duration = av_rescale_q(fields, av_inv_q(field_rate), - ist->st->time_base); + frame->time_base); } // prefer codec-layer duration for containers without timestamps @@ -1015,7 +1015,7 @@ static int64_t video_duration_estimate(const InputStream *ist, const AVFrame *fr // try average framerate if (ist->st->avg_frame_rate.num && ist->st->avg_frame_rate.den) { int64_t d = av_rescale_q(1, av_inv_q(ist->st->avg_frame_rate), - ist->st->time_base); + frame->time_base); if (d > 0) return d; } @@ -1110,13 +1110,13 @@ static int decode_video(InputStream *ist, const AVPacket *pkt, int *got_output, "duration:%s duration_time:%s " "keyframe:%d frame_type:%d time_base:%d/%d\n", av_ts2str(frame->pts), - av_ts2timestr(frame->pts, &ist->st->time_base), + av_ts2timestr(frame->pts, &frame->time_base), av_ts2str(frame->pkt_dts), - av_ts2timestr(frame->pkt_dts, &ist->st->time_base), + av_ts2timestr(frame->pkt_dts, &frame->time_base), av_ts2str(frame->duration), - av_ts2timestr(frame->duration, &ist->st->time_base), + av_ts2timestr(frame->duration, &frame->time_base), !!(frame->flags & AV_FRAME_FLAG_KEY), frame->pict_type, - ist->st->time_base.num, ist->st->time_base.den); + frame->time_base.num, frame->time_base.den); } if (ist->st->sample_aspect_ratio.num) From 14b9946967a3141768554fcc970ec423a708744a Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Wed, 10 May 2023 09:59:13 +0200 Subject: [PATCH 1120/2172] fftools/ffmpeg_filter: convert input frame timestamps Decoder timebase does not always have to match filter timebase. --- fftools/ffmpeg_filter.c | 29 ++++++++++++++++++++++++----- 1 file changed, 24 insertions(+), 5 deletions(-) diff --git a/fftools/ffmpeg_filter.c b/fftools/ffmpeg_filter.c index aea951a2da9..95ffa0f0876 100644 --- a/fftools/ffmpeg_filter.c +++ b/fftools/ffmpeg_filter.c @@ -55,6 +55,9 @@ static FilterGraphPriv *fgp_from_fg(FilterGraph *fg) typedef struct InputFilterPriv { InputFilter ifilter; + // used to hold submitted input + AVFrame *frame; + int eof; AVRational time_base; @@ -244,6 +247,10 @@ static InputFilter *ifilter_alloc(FilterGraph *fg) ifilter->graph = fg; ifilter->format = -1; + ifp->frame = av_frame_alloc(); + if (!ifp->frame) + report_and_exit(AVERROR(ENOMEM)); + ifp->fallback.format = -1; ifp->frame_queue = av_fifo_alloc2(8, sizeof(AVFrame*), AV_FIFO_FLAG_AUTO_GROW); @@ -284,6 +291,8 @@ void fg_free(FilterGraph **pfg) av_channel_layout_uninit(&ifp->fallback.ch_layout); + av_frame_free(&ifp->frame); + av_buffer_unref(&ifp->hw_frames_ctx); av_freep(&ifilter->name); av_freep(&fg->inputs[j]); @@ -1541,10 +1550,6 @@ 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; @@ -1606,8 +1611,22 @@ int ifilter_send_frame(InputFilter *ifilter, AVFrame *frame, int keep_reference) } } - ret = av_buffersrc_add_frame_flags(ifilter->filter, frame, buffersrc_flags); + if (keep_reference) { + ret = av_frame_ref(ifp->frame, frame); + if (ret < 0) + return ret; + } else + av_frame_move_ref(ifp->frame, frame); + frame = ifp->frame; + + frame->pts = av_rescale_q(frame->pts, frame->time_base, ifp->time_base); + frame->duration = av_rescale_q(frame->duration, frame->time_base, ifp->time_base); + frame->time_base = ifp->time_base; + + ret = av_buffersrc_add_frame_flags(ifilter->filter, frame, + AV_BUFFERSRC_FLAG_PUSH); if (ret < 0) { + av_frame_unref(frame); if (ret != AVERROR_EOF) av_log(NULL, AV_LOG_ERROR, "Error while filtering: %s\n", av_err2str(ret)); return ret; From 113250732723f1a2b695c64cdc03e5bf0f1311a4 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Wed, 10 May 2023 12:19:58 +0200 Subject: [PATCH 1121/2172] fftools/ffmpeg_filter: make sure pkt_duration matches duration Otherwise the two values might get desynchronized and lavfi can prefer the wrong one. --- fftools/ffmpeg_filter.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/fftools/ffmpeg_filter.c b/fftools/ffmpeg_filter.c index 95ffa0f0876..274eefe11ce 100644 --- a/fftools/ffmpeg_filter.c +++ b/fftools/ffmpeg_filter.c @@ -1622,6 +1622,11 @@ int ifilter_send_frame(InputFilter *ifilter, AVFrame *frame, int keep_reference) frame->pts = av_rescale_q(frame->pts, frame->time_base, ifp->time_base); frame->duration = av_rescale_q(frame->duration, frame->time_base, ifp->time_base); frame->time_base = ifp->time_base; +#if LIBAVUTIL_VERSION_MAJOR < 59 + AV_NOWARN_DEPRECATED( + frame->pkt_duration = frame->duration; + ) +#endif ret = av_buffersrc_add_frame_flags(ifilter->filter, frame, AV_BUFFERSRC_FLAG_PUSH); From 30a3fee24f8a5d38c59ae157ac04cf23dcb064e5 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Wed, 10 May 2023 12:21:48 +0200 Subject: [PATCH 1122/2172] fftools/ffmpeg: rework applying input -r Do not use a separate counter for CFR timestamps forced with -r used as an input option. Set durations properly and let estimation code do the rest. --- fftools/ffmpeg.c | 10 +++++++--- fftools/ffmpeg.h | 4 ---- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/fftools/ffmpeg.c b/fftools/ffmpeg.c index 9e5e56e9e77..e368f5a1485 100644 --- a/fftools/ffmpeg.c +++ b/fftools/ffmpeg.c @@ -985,7 +985,7 @@ static int64_t video_duration_estimate(const InputStream *ist, const AVFrame *fr // durations, then this should be simplified. // prefer frame duration for containers with timestamps - if (frame->duration > 0 && !ifile->format_nots) + if (frame->duration > 0 && (!ifile->format_nots || ist->framerate.num)) return frame->duration; if (ist->dec_ctx->framerate.den && ist->dec_ctx->framerate.num) { @@ -1090,8 +1090,12 @@ static int decode_video(InputStream *ist, const AVPacket *pkt, int *got_output, frame->pts = frame->best_effort_timestamp; - if (ist->framerate.num) - frame->pts = ist->cfr_next_pts++; + // forced fixed framerate + if (ist->framerate.num) { + frame->pts = AV_NOPTS_VALUE; + frame->duration = 1; + frame->time_base = av_inv_q(ist->framerate); + } // no timestamp available - extrapolate from previous frame duration if (frame->pts == AV_NOPTS_VALUE) diff --git a/fftools/ffmpeg.h b/fftools/ffmpeg.h index f88792d7eb4..3c7991c73ad 100644 --- a/fftools/ffmpeg.h +++ b/fftools/ffmpeg.h @@ -372,10 +372,6 @@ typedef struct InputStream { int64_t filter_in_rescale_delta_last; - // when forcing constant input framerate through -r, - // this contains the pts that will be given to the next decoded frame - int64_t cfr_next_pts; - int64_t nb_samples; /* number of samples in the last decoded audio frame before looping */ AVDictionary *decoder_opts; From 900bb3f8e29ad0c28bac2cae8c66a319658ec9e6 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Wed, 10 May 2023 09:09:09 +0200 Subject: [PATCH 1123/2172] tests/fate/ffmpeg: move a misplaced line --- tests/fate/ffmpeg.mak | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/tests/fate/ffmpeg.mak b/tests/fate/ffmpeg.mak index 0f33c2a0ed7..892624e5239 100644 --- a/tests/fate/ffmpeg.mak +++ b/tests/fate/ffmpeg.mak @@ -190,6 +190,7 @@ fate-copy-shortest1: CMD = framemd5 -auto_conversion_filters -fflags +bitexact - 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) +FATE_SAMPLES_FFMPEG-yes += $(FATE_STREAMCOPY-yes) FATE_SAMPLES_FFMPEG-$(call TRANSCODE, RAWVIDEO, MATROSKA, MOV_DEMUXER QTRLE_DECODER) += fate-rgb24-mkv fate-rgb24-mkv: CMD = transcode "mov" $(TARGET_SAMPLES)/qtrle/aletrek-rle.mov\ @@ -218,8 +219,6 @@ fate-ffmpeg-bsf-remove-e: CMD = transcode "mpeg" $(TARGET_SAMPLES)/mpeg2/matrixb FATE_SAMPLES_FFMPEG-$(call DEMMUX, APNG, FRAMECRC, SETTS_BSF PIPE_PROTOCOL) += fate-ffmpeg-setts-bsf fate-ffmpeg-setts-bsf: CMD = framecrc -i $(TARGET_SAMPLES)/apng/clock.png -c:v copy -bsf:v "setts=duration=if(eq(NEXT_PTS\,NOPTS)\,PREV_OUTDURATION\,(NEXT_PTS-PTS)/2):ts=PTS/2" -fflags +bitexact -FATE_SAMPLES_FFMPEG-yes += $(FATE_STREAMCOPY-yes) - FATE_TIME_BASE-$(call PARSERDEMDEC, MPEGVIDEO, MPEGPS, MPEG2VIDEO, MPEGVIDEO_DEMUXER MXF_MUXER) += fate-time_base fate-time_base: CMD = md5 -i $(TARGET_SAMPLES)/mpeg2/dvd_single_frame.vob -an -sn -c:v copy -r 25 -time_base 1001:30000 -fflags +bitexact -f mxf From 8c0f5161334aca93c97c42d4f62fde1c5de70b8a Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Wed, 10 May 2023 09:13:35 +0200 Subject: [PATCH 1124/2172] tests/fate/ffmpeg: add a test for input -r option --- tests/fate/ffmpeg.mak | 4 ++++ tests/ref/fate/ffmpeg-input-r | 12 ++++++++++++ 2 files changed, 16 insertions(+) create mode 100644 tests/ref/fate/ffmpeg-input-r diff --git a/tests/fate/ffmpeg.mak b/tests/fate/ffmpeg.mak index 892624e5239..aca949176af 100644 --- a/tests/fate/ffmpeg.mak +++ b/tests/fate/ffmpeg.mak @@ -223,3 +223,7 @@ FATE_TIME_BASE-$(call PARSERDEMDEC, MPEGVIDEO, MPEGPS, MPEG2VIDEO, MPEGVIDEO_DEM fate-time_base: CMD = md5 -i $(TARGET_SAMPLES)/mpeg2/dvd_single_frame.vob -an -sn -c:v copy -r 25 -time_base 1001:30000 -fflags +bitexact -f mxf FATE_SAMPLES_FFMPEG-yes += $(FATE_TIME_BASE-yes) + +# test -r used as an input option +fate-ffmpeg-input-r: CMD = framecrc -r 27 -i $(TARGET_SAMPLES)/mpeg2/sony-ct3.bs +FATE_SAMPLES_FFMPEG-$(call FRAMECRC, MPEGVIDEO, MPEG2VIDEO) += fate-ffmpeg-input-r diff --git a/tests/ref/fate/ffmpeg-input-r b/tests/ref/fate/ffmpeg-input-r new file mode 100644 index 00000000000..d11f870b102 --- /dev/null +++ b/tests/ref/fate/ffmpeg-input-r @@ -0,0 +1,12 @@ +#tb 0: 1/27 +#media_type 0: video +#codec_id 0: rawvideo +#dimensions 0: 720x480 +#sar 0: 8/9 +0, 0, 0, 1, 518400, 0xc1866f5f +0, 1, 1, 1, 518400, 0x9ba32764 +0, 2, 2, 1, 518400, 0xa9031bb8 +0, 3, 3, 1, 518400, 0x5e2c3502 +0, 4, 4, 1, 518400, 0xe860027a +0, 5, 5, 1, 518400, 0xa9152430 +0, 6, 6, 1, 518400, 0xb98dd9f7 From ede6794d6a31c781f680e47c20515e18db0da454 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Thu, 11 May 2023 10:40:58 +0200 Subject: [PATCH 1125/2172] fftools/ffmpeg_filter: split finding an unused stream into a function Avoids filtering code from digging in demuxer internals. --- fftools/ffmpeg.h | 5 +++++ fftools/ffmpeg_demux.c | 10 ++++++++++ fftools/ffmpeg_filter.c | 8 +------- 3 files changed, 16 insertions(+), 7 deletions(-) diff --git a/fftools/ffmpeg.h b/fftools/ffmpeg.h index 3c7991c73ad..9cb7198dfdf 100644 --- a/fftools/ffmpeg.h +++ b/fftools/ffmpeg.h @@ -882,6 +882,11 @@ int ifile_get_packet(InputFile *f, AVPacket **pkt); void ist_output_add(InputStream *ist, OutputStream *ost); void ist_filter_add(InputStream *ist, InputFilter *ifilter, int is_simple); +/** + * Find an unused input stream of given type. + */ +InputStream *ist_find_unused(enum AVMediaType type); + /* iterate over all input streams in all input files; * pass NULL to start iteration */ InputStream *ist_iter(InputStream *prev); diff --git a/fftools/ffmpeg_demux.c b/fftools/ffmpeg_demux.c index 0a37cc7c25e..b93e1710372 100644 --- a/fftools/ffmpeg_demux.c +++ b/fftools/ffmpeg_demux.c @@ -130,6 +130,16 @@ static Demuxer *demuxer_from_ifile(InputFile *f) return (Demuxer*)f; } +InputStream *ist_find_unused(enum AVMediaType type) +{ + for (InputStream *ist = ist_iter(NULL); ist; ist = ist_iter(ist)) { + if (ist->par->codec_type == type && ist->discard && + ist->user_set_discard != AVDISCARD_ALL) + return ist; + } + return NULL; +} + static void report_new_stream(Demuxer *d, const AVPacket *pkt) { AVStream *st = d->f.ctx->streams[pkt->stream_index]; diff --git a/fftools/ffmpeg_filter.c b/fftools/ffmpeg_filter.c index 274eefe11ce..8cc76209d02 100644 --- a/fftools/ffmpeg_filter.c +++ b/fftools/ffmpeg_filter.c @@ -420,13 +420,7 @@ static void init_input_filter(FilterGraph *fg, AVFilterInOut *in) exit_program(1); } } else { - /* find the first unused stream of corresponding type */ - for (ist = ist_iter(NULL); ist; ist = ist_iter(ist)) { - if (ist->user_set_discard == AVDISCARD_ALL) - continue; - if (ist->dec_ctx->codec_type == type && ist->discard) - break; - } + ist = ist_find_unused(type); if (!ist) { av_log(NULL, AV_LOG_FATAL, "Cannot find a matching stream for " "unlabeled input pad %d on filter %s\n", in->pad_idx, From dfa29ba9550797881943fa5b12a8cf5f30a3e47c Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Thu, 11 May 2023 10:51:13 +0200 Subject: [PATCH 1126/2172] fftools/ffmpeg: return error codes from ist_*_add() Will be useful in future commits. --- fftools/ffmpeg.h | 4 ++-- fftools/ffmpeg_demux.c | 26 +++++++++++++++++++------- fftools/ffmpeg_filter.c | 15 ++++++++++++--- fftools/ffmpeg_mux_init.c | 10 ++++++++-- 4 files changed, 41 insertions(+), 14 deletions(-) diff --git a/fftools/ffmpeg.h b/fftools/ffmpeg.h index 9cb7198dfdf..189454d6293 100644 --- a/fftools/ffmpeg.h +++ b/fftools/ffmpeg.h @@ -879,8 +879,8 @@ void ifile_close(InputFile **f); */ int ifile_get_packet(InputFile *f, AVPacket **pkt); -void ist_output_add(InputStream *ist, OutputStream *ost); -void ist_filter_add(InputStream *ist, InputFilter *ifilter, int is_simple); +int ist_output_add(InputStream *ist, OutputStream *ost); +int ist_filter_add(InputStream *ist, InputFilter *ifilter, int is_simple); /** * Find an unused input stream of given type. diff --git a/fftools/ffmpeg_demux.c b/fftools/ffmpeg_demux.c index b93e1710372..ae2133bdbfd 100644 --- a/fftools/ffmpeg_demux.c +++ b/fftools/ffmpeg_demux.c @@ -844,7 +844,7 @@ void ifile_close(InputFile **pf) av_freep(pf); } -static void ist_use(InputStream *ist, int decoding_needed) +static int ist_use(InputStream *ist, int decoding_needed) { DemuxStream *ds = ds_from_ist(ist); @@ -856,23 +856,33 @@ static void ist_use(InputStream *ist, int decoding_needed) if (decoding_needed && !avcodec_is_open(ist->dec_ctx)) { int ret = dec_open(ist); if (ret < 0) - report_and_exit(ret); + return ret; } + + return 0; } -void ist_output_add(InputStream *ist, OutputStream *ost) +int ist_output_add(InputStream *ist, OutputStream *ost) { - ist_use(ist, ost->enc ? DECODING_FOR_OST : 0); + int ret; + + ret = ist_use(ist, ost->enc ? DECODING_FOR_OST : 0); + if (ret < 0) + return ret; GROW_ARRAY(ist->outputs, ist->nb_outputs); ist->outputs[ist->nb_outputs - 1] = ost; + + return 0; } -void ist_filter_add(InputStream *ist, InputFilter *ifilter, int is_simple) +int ist_filter_add(InputStream *ist, InputFilter *ifilter, int is_simple) { int ret; - ist_use(ist, is_simple ? DECODING_FOR_OST : DECODING_FOR_FILTER); + ret = ist_use(ist, is_simple ? DECODING_FOR_OST : DECODING_FOR_FILTER); + if (ret < 0) + return ret; GROW_ARRAY(ist->filters, ist->nb_filters); ist->filters[ist->nb_filters - 1] = ifilter; @@ -880,7 +890,9 @@ void ist_filter_add(InputStream *ist, InputFilter *ifilter, int is_simple) // initialize fallback parameters for filtering ret = ifilter_parameters_from_dec(ifilter, ist->dec_ctx); if (ret < 0) - report_and_exit(ret); + return ret; + + return 0; } static const AVCodec *choose_decoder(const OptionsContext *o, AVFormatContext *s, AVStream *st, diff --git a/fftools/ffmpeg_filter.c b/fftools/ffmpeg_filter.c index 8cc76209d02..ca43b4803a3 100644 --- a/fftools/ffmpeg_filter.c +++ b/fftools/ffmpeg_filter.c @@ -334,6 +334,7 @@ int init_simple_filtergraph(InputStream *ist, OutputStream *ost) FilterGraph *fg; OutputFilter *ofilter; InputFilter *ifilter; + int ret; fg = fg_create(NULL); if (!fg) @@ -347,7 +348,9 @@ int init_simple_filtergraph(InputStream *ist, OutputStream *ost) ifilter = ifilter_alloc(fg); ifilter->ist = ist; - ist_filter_add(ist, ifilter, 1); + ret = ist_filter_add(ist, ifilter, 1); + if (ret < 0) + return ret; return 0; } @@ -375,7 +378,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; + int i, ret; // TODO: support other filter types if (type != AVMEDIA_TYPE_VIDEO && type != AVMEDIA_TYPE_AUDIO) { @@ -435,7 +438,13 @@ static void init_input_filter(FilterGraph *fg, AVFilterInOut *in) ifilter->type = ist->st->codecpar->codec_type; ifilter->name = describe_filter_link(fg, in, 1); - ist_filter_add(ist, ifilter, 0); + ret = ist_filter_add(ist, ifilter, 0); + if (ret < 0) { + av_log(NULL, AV_LOG_ERROR, + "Error binding an input stream to complex filtergraph input %s.\n", + in->name ? in->name : ""); + exit_program(1); + } } static int read_binary(const char *path, uint8_t **data, int *len) diff --git a/fftools/ffmpeg_mux_init.c b/fftools/ffmpeg_mux_init.c index 2c0e2faf4a1..b73791acee5 100644 --- a/fftools/ffmpeg_mux_init.c +++ b/fftools/ffmpeg_mux_init.c @@ -1225,8 +1225,14 @@ static OutputStream *ost_add(Muxer *mux, const OptionsContext *o, "Error initializing a simple filtergraph\n"); exit_program(1); } - } else - ist_output_add(ost->ist, ost); + } else { + ret = ist_output_add(ost->ist, ost); + if (ret < 0) { + av_log(ost, AV_LOG_ERROR, + "Error binding an input stream\n"); + exit_program(1); + } + } } if (ost->ist && !ost->enc) { From 65f3d042a614ed62f4bc272f3859bb092e56e35e Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Thu, 11 May 2023 11:02:36 +0200 Subject: [PATCH 1127/2172] fftools/ffmpeg_demux: disallow using disabled input streams This is less ad-hoc than checking explicitly in every place that binds an input stream to a filter or output. --- fftools/ffmpeg_demux.c | 6 ++++++ fftools/ffmpeg_filter.c | 5 ----- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/fftools/ffmpeg_demux.c b/fftools/ffmpeg_demux.c index ae2133bdbfd..df87e0f30a6 100644 --- a/fftools/ffmpeg_demux.c +++ b/fftools/ffmpeg_demux.c @@ -848,6 +848,12 @@ static int ist_use(InputStream *ist, int decoding_needed) { DemuxStream *ds = ds_from_ist(ist); + if (ist->user_set_discard == AVDISCARD_ALL) { + av_log(ist, AV_LOG_ERROR, "Cannot %s a disabled input stream\n", + decoding_needed ? "decode" : "streamcopy"); + return AVERROR(EINVAL); + } + ist->discard = 0; ist->st->discard = ist->user_set_discard; ist->decoding_needed |= decoding_needed; diff --git a/fftools/ffmpeg_filter.c b/fftools/ffmpeg_filter.c index ca43b4803a3..2c3e2a96f70 100644 --- a/fftools/ffmpeg_filter.c +++ b/fftools/ffmpeg_filter.c @@ -417,11 +417,6 @@ static void init_input_filter(FilterGraph *fg, AVFilterInOut *in) exit_program(1); } ist = input_files[file_idx]->streams[st->index]; - if (ist->user_set_discard == AVDISCARD_ALL) { - av_log(NULL, AV_LOG_FATAL, "Stream specifier '%s' in filtergraph description %s " - "matches a disabled input stream.\n", p, fgp->graph_desc); - exit_program(1); - } } else { ist = ist_find_unused(type); if (!ist) { From a16d7171d1e1ee03ab2473257e275ac2a8c265bf Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Thu, 11 May 2023 11:59:44 +0200 Subject: [PATCH 1128/2172] fftools/ffmpeg_filter: only use fallback parameters when necessary With complex filtergraphs it can happen that the filtergraph is unconfigured because some other filter than the one we just got EOF on is missing parameters. Make sure that the fallback parametes for a given input are only used when that input is unconfigured. --- fftools/ffmpeg_filter.c | 24 +++++++++++++----------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/fftools/ffmpeg_filter.c b/fftools/ffmpeg_filter.c index 2c3e2a96f70..8eca0f2caef 100644 --- a/fftools/ffmpeg_filter.c +++ b/fftools/ffmpeg_filter.c @@ -1521,17 +1521,19 @@ int ifilter_send_eof(InputFilter *ifilter, int64_t pts, AVRational tb) if (ret < 0) return ret; } else { - // the filtergraph was never configured, use the fallback parameters - ifilter->format = ifp->fallback.format; - ifilter->sample_rate = ifp->fallback.sample_rate; - ifilter->width = ifp->fallback.width; - ifilter->height = ifp->fallback.height; - ifilter->sample_aspect_ratio = ifp->fallback.sample_aspect_ratio; - - ret = av_channel_layout_copy(&ifilter->ch_layout, - &ifp->fallback.ch_layout); - if (ret < 0) - return ret; + if (ifilter->format < 0) { + // the filtergraph was never configured, use the fallback parameters + ifilter->format = ifp->fallback.format; + ifilter->sample_rate = ifp->fallback.sample_rate; + ifilter->width = ifp->fallback.width; + ifilter->height = ifp->fallback.height; + ifilter->sample_aspect_ratio = ifp->fallback.sample_aspect_ratio; + + ret = av_channel_layout_copy(&ifilter->ch_layout, + &ifp->fallback.ch_layout); + if (ret < 0) + return ret; + } if (ifilter->format < 0 && (ifilter->type == AVMEDIA_TYPE_AUDIO || ifilter->type == AVMEDIA_TYPE_VIDEO)) { av_log(NULL, AV_LOG_ERROR, "Cannot determine format of input stream %d:%d after EOF\n", ifilter->ist->file_index, ifilter->ist->st->index); From 2628c7049ec15e52f267a1a019f7cf38a6cd87b4 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Thu, 11 May 2023 12:02:49 +0200 Subject: [PATCH 1129/2172] fftools/ffmpeg_filter: try configuring graphs from input EOF When a filtergraph input receives EOF but never saw any input frames, we use the fallback parameters. Currently an attempt to actually configure the filtergraph will happen elsewhere, but there is no reason to postpone this. --- fftools/ffmpeg_filter.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/fftools/ffmpeg_filter.c b/fftools/ffmpeg_filter.c index 8eca0f2caef..6323278d155 100644 --- a/fftools/ffmpeg_filter.c +++ b/fftools/ffmpeg_filter.c @@ -1533,6 +1533,14 @@ int ifilter_send_eof(InputFilter *ifilter, int64_t pts, AVRational tb) &ifp->fallback.ch_layout); if (ret < 0) return ret; + + if (ifilter_has_all_input_formats(ifilter->graph)) { + ret = configure_filtergraph(ifilter->graph); + if (ret < 0) { + av_log(NULL, AV_LOG_ERROR, "Error initializing filters!\n"); + return ret; + } + } } if (ifilter->format < 0 && (ifilter->type == AVMEDIA_TYPE_AUDIO || ifilter->type == AVMEDIA_TYPE_VIDEO)) { From 82c75ddfade1f69e4743ce07d9d22882512d7137 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Sat, 13 May 2023 09:58:43 +0200 Subject: [PATCH 1130/2172] fftools/ffmpeg: move ifilter_has_all_input_formats() to ffmpeg_filter That is a more appropriate place for that function. --- fftools/ffmpeg.c | 12 ------------ fftools/ffmpeg_filter.c | 12 ++++++++++++ 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/fftools/ffmpeg.c b/fftools/ffmpeg.c index e368f5a1485..9d554e2fb0b 100644 --- a/fftools/ffmpeg.c +++ b/fftools/ffmpeg.c @@ -787,18 +787,6 @@ static void check_decode_result(InputStream *ist, int *got_output, int ret) } } -// Filters can be configured only if the formats of all inputs are known. -int ifilter_has_all_input_formats(FilterGraph *fg) -{ - int i; - for (i = 0; i < fg->nb_inputs; i++) { - if (fg->inputs[i]->format < 0 && (fg->inputs[i]->type == AVMEDIA_TYPE_AUDIO || - fg->inputs[i]->type == AVMEDIA_TYPE_VIDEO)) - return 0; - } - return 1; -} - // This does not quite work like avcodec_decode_audio4/avcodec_decode_video2. // There is the following difference: if you got a frame, you must call // it again with pkt=NULL. pkt==NULL is treated differently from pkt->size==0 diff --git a/fftools/ffmpeg_filter.c b/fftools/ffmpeg_filter.c index 6323278d155..d85d9e2c673 100644 --- a/fftools/ffmpeg_filter.c +++ b/fftools/ffmpeg_filter.c @@ -1445,6 +1445,18 @@ static int ifilter_parameters_from_frame(InputFilter *ifilter, const AVFrame *fr return 0; } +// Filters can be configured only if the formats of all inputs are known. +int ifilter_has_all_input_formats(FilterGraph *fg) +{ + int i; + for (i = 0; i < fg->nb_inputs; i++) { + if (fg->inputs[i]->format < 0 && (fg->inputs[i]->type == AVMEDIA_TYPE_AUDIO || + fg->inputs[i]->type == AVMEDIA_TYPE_VIDEO)) + return 0; + } + return 1; +} + int filtergraph_is_simple(FilterGraph *fg) { FilterGraphPriv *fgp = fgp_from_fg(fg); From 89b37ae70a78f3b7dd97255141b49e640f9f58b1 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Sat, 13 May 2023 10:05:02 +0200 Subject: [PATCH 1131/2172] fftools/ffmpeg_filter: make input filter configured parameters private They are not used outside of ffmpeg_filter. --- fftools/ffmpeg.h | 9 ----- fftools/ffmpeg_filter.c | 89 +++++++++++++++++++++++------------------ 2 files changed, 50 insertions(+), 48 deletions(-) diff --git a/fftools/ffmpeg.h b/fftools/ffmpeg.h index 189454d6293..9cb9f35bc2d 100644 --- a/fftools/ffmpeg.h +++ b/fftools/ffmpeg.h @@ -283,15 +283,6 @@ typedef struct InputFilter { struct FilterGraph *graph; uint8_t *name; enum AVMediaType type; // AVMEDIA_TYPE_SUBTITLE for sub2video - - // parameters configured for this input - int format; - - int width, height; - AVRational sample_aspect_ratio; - - int sample_rate; - AVChannelLayout ch_layout; } InputFilter; typedef struct OutputFilter { diff --git a/fftools/ffmpeg_filter.c b/fftools/ffmpeg_filter.c index d85d9e2c673..12e756e4892 100644 --- a/fftools/ffmpeg_filter.c +++ b/fftools/ffmpeg_filter.c @@ -60,6 +60,15 @@ typedef struct InputFilterPriv { int eof; + // parameters configured for this input + int format; + + int width, height; + AVRational sample_aspect_ratio; + + int sample_rate; + AVChannelLayout ch_layout; + AVRational time_base; AVFifo *frame_queue; @@ -245,12 +254,12 @@ static InputFilter *ifilter_alloc(FilterGraph *fg) InputFilter *ifilter = &ifp->ifilter; ifilter->graph = fg; - ifilter->format = -1; ifp->frame = av_frame_alloc(); if (!ifp->frame) report_and_exit(AVERROR(ENOMEM)); + ifp->format = -1; ifp->fallback.format = -1; ifp->frame_queue = av_fifo_alloc2(8, sizeof(AVFrame*), AV_FIFO_FLAG_AUTO_GROW); @@ -956,14 +965,15 @@ void check_filter_outputs(void) static int sub2video_prepare(InputStream *ist, InputFilter *ifilter) { + InputFilterPriv *ifp = ifp_from_ifilter(ifilter); AVFormatContext *avf = input_files[ist->file_index]->ctx; int i, w, h; /* Compute the size of the canvas for the subtitles stream. If the subtitles codecpar has set a size, use it. Otherwise use the maximum dimensions of the video streams in the same file. */ - w = ifilter->width; - h = ifilter->height; + w = ifp->width; + h = ifp->height; if (!(w && h)) { for (i = 0; i < avf->nb_streams; i++) { if (avf->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) { @@ -977,15 +987,15 @@ static int sub2video_prepare(InputStream *ist, InputFilter *ifilter) } av_log(avf, AV_LOG_INFO, "sub2video: using %dx%d canvas\n", w, h); } - ist->sub2video.w = ifilter->width = w; - ist->sub2video.h = ifilter->height = h; + ist->sub2video.w = ifp->width = w; + ist->sub2video.h = ifp->height = h; - ifilter->width = ist->dec_ctx->width ? ist->dec_ctx->width : ist->sub2video.w; - ifilter->height = ist->dec_ctx->height ? ist->dec_ctx->height : ist->sub2video.h; + ifp->width = ist->dec_ctx->width ? ist->dec_ctx->width : ist->sub2video.w; + ifp->height = ist->dec_ctx->height ? ist->dec_ctx->height : ist->sub2video.h; /* rectangles are AV_PIX_FMT_PAL8, but we have no guarantee that the palettes for all rectangles are identical or compatible */ - ifilter->format = AV_PIX_FMT_RGB32; + ifp->format = AV_PIX_FMT_RGB32; ist->sub2video.frame = av_frame_alloc(); if (!ist->sub2video.frame) @@ -1042,14 +1052,14 @@ static int configure_input_video_filter(FilterGraph *fg, InputFilter *ifilter, ifp->time_base = ist->framerate.num ? av_inv_q(ist->framerate) : ist->st->time_base; - sar = ifilter->sample_aspect_ratio; + sar = ifp->sample_aspect_ratio; if(!sar.den) sar = (AVRational){0,1}; av_bprint_init(&args, 0, AV_BPRINT_SIZE_AUTOMATIC); av_bprintf(&args, "video_size=%dx%d:pix_fmt=%d:time_base=%d/%d:" "pixel_aspect=%d/%d", - ifilter->width, ifilter->height, ifilter->format, + ifp->width, ifp->height, ifp->format, ifp->time_base.num, ifp->time_base.den, sar.num, sar.den); if (fr.num && fr.den) av_bprintf(&args, ":frame_rate=%d/%d", fr.num, fr.den); @@ -1067,7 +1077,7 @@ static int configure_input_video_filter(FilterGraph *fg, InputFilter *ifilter, av_freep(&par); last_filter = ifilter->filter; - desc = av_pix_fmt_desc_get(ifilter->format); + desc = av_pix_fmt_desc_get(ifp->format); av_assert0(desc); // TODO: insert hwaccel enabled filters like transpose_vaapi into the graph @@ -1147,19 +1157,19 @@ static int configure_input_audio_filter(FilterGraph *fg, InputFilter *ifilter, return AVERROR(EINVAL); } - ifp->time_base = (AVRational){ 1, ifilter->sample_rate }; + ifp->time_base = (AVRational){ 1, ifp->sample_rate }; av_bprint_init(&args, 0, AV_BPRINT_SIZE_AUTOMATIC); av_bprintf(&args, "time_base=%d/%d:sample_rate=%d:sample_fmt=%s", ifp->time_base.num, ifp->time_base.den, - ifilter->sample_rate, - av_get_sample_fmt_name(ifilter->format)); - if (av_channel_layout_check(&ifilter->ch_layout) && - ifilter->ch_layout.order != AV_CHANNEL_ORDER_UNSPEC) { + ifp->sample_rate, + av_get_sample_fmt_name(ifp->format)); + if (av_channel_layout_check(&ifp->ch_layout) && + ifp->ch_layout.order != AV_CHANNEL_ORDER_UNSPEC) { av_bprintf(&args, ":channel_layout="); - av_channel_layout_describe_bprint(&ifilter->ch_layout, &args); + av_channel_layout_describe_bprint(&ifp->ch_layout, &args); } else - av_bprintf(&args, ":channels=%d", ifilter->ch_layout.nb_channels); + av_bprintf(&args, ":channels=%d", ifp->ch_layout.nb_channels); snprintf(name, sizeof(name), "graph_%d_in_%d_%d", fg->index, ist->file_index, ist->st->index); @@ -1426,14 +1436,14 @@ static int ifilter_parameters_from_frame(InputFilter *ifilter, const AVFrame *fr if (ret < 0) return ret; - ifilter->format = frame->format; + ifp->format = frame->format; - ifilter->width = frame->width; - ifilter->height = frame->height; - ifilter->sample_aspect_ratio = frame->sample_aspect_ratio; + ifp->width = frame->width; + ifp->height = frame->height; + ifp->sample_aspect_ratio = frame->sample_aspect_ratio; - ifilter->sample_rate = frame->sample_rate; - ret = av_channel_layout_copy(&ifilter->ch_layout, &frame->ch_layout); + ifp->sample_rate = frame->sample_rate; + ret = av_channel_layout_copy(&ifp->ch_layout, &frame->ch_layout); if (ret < 0) return ret; @@ -1450,8 +1460,9 @@ int ifilter_has_all_input_formats(FilterGraph *fg) { int i; for (i = 0; i < fg->nb_inputs; i++) { - if (fg->inputs[i]->format < 0 && (fg->inputs[i]->type == AVMEDIA_TYPE_AUDIO || - fg->inputs[i]->type == AVMEDIA_TYPE_VIDEO)) + InputFilterPriv *ifp = ifp_from_ifilter(fg->inputs[i]); + if (ifp->format < 0 && (fg->inputs[i]->type == AVMEDIA_TYPE_AUDIO || + fg->inputs[i]->type == AVMEDIA_TYPE_VIDEO)) return 0; } return 1; @@ -1533,15 +1544,15 @@ int ifilter_send_eof(InputFilter *ifilter, int64_t pts, AVRational tb) if (ret < 0) return ret; } else { - if (ifilter->format < 0) { + if (ifp->format < 0) { // the filtergraph was never configured, use the fallback parameters - ifilter->format = ifp->fallback.format; - ifilter->sample_rate = ifp->fallback.sample_rate; - ifilter->width = ifp->fallback.width; - ifilter->height = ifp->fallback.height; - ifilter->sample_aspect_ratio = ifp->fallback.sample_aspect_ratio; + ifp->format = ifp->fallback.format; + ifp->sample_rate = ifp->fallback.sample_rate; + ifp->width = ifp->fallback.width; + ifp->height = ifp->fallback.height; + ifp->sample_aspect_ratio = ifp->fallback.sample_aspect_ratio; - ret = av_channel_layout_copy(&ifilter->ch_layout, + ret = av_channel_layout_copy(&ifp->ch_layout, &ifp->fallback.ch_layout); if (ret < 0) return ret; @@ -1555,7 +1566,7 @@ int ifilter_send_eof(InputFilter *ifilter, int64_t pts, AVRational tb) } } - if (ifilter->format < 0 && (ifilter->type == AVMEDIA_TYPE_AUDIO || ifilter->type == AVMEDIA_TYPE_VIDEO)) { + if (ifp->format < 0 && (ifilter->type == AVMEDIA_TYPE_AUDIO || ifilter->type == AVMEDIA_TYPE_VIDEO)) { av_log(NULL, AV_LOG_ERROR, "Cannot determine format of input stream %d:%d after EOF\n", ifilter->ist->file_index, ifilter->ist->st->index); return AVERROR_INVALIDDATA; } @@ -1572,16 +1583,16 @@ int ifilter_send_frame(InputFilter *ifilter, AVFrame *frame, int keep_reference) int need_reinit, ret; /* determine if the parameters for this input changed */ - need_reinit = ifilter->format != frame->format; + need_reinit = ifp->format != frame->format; switch (ifilter->ist->par->codec_type) { case AVMEDIA_TYPE_AUDIO: - need_reinit |= ifilter->sample_rate != frame->sample_rate || - av_channel_layout_compare(&ifilter->ch_layout, &frame->ch_layout); + need_reinit |= ifp->sample_rate != frame->sample_rate || + av_channel_layout_compare(&ifp->ch_layout, &frame->ch_layout); break; case AVMEDIA_TYPE_VIDEO: - need_reinit |= ifilter->width != frame->width || - ifilter->height != frame->height; + need_reinit |= ifp->width != frame->width || + ifp->height != frame->height; break; } From 0f501b2ad999a63669b6dd002544a447abd368d4 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Sat, 13 May 2023 10:26:16 +0200 Subject: [PATCH 1132/2172] fftools/ffmpeg_filter: drop a redundant error message In case no decoder is available, dec_open() called from ist_use() will fail with 'Decoding requested, but no decoder found', so this check is redundant. --- fftools/ffmpeg_filter.c | 6 ------ 1 file changed, 6 deletions(-) diff --git a/fftools/ffmpeg_filter.c b/fftools/ffmpeg_filter.c index 12e756e4892..16f29a313ff 100644 --- a/fftools/ffmpeg_filter.c +++ b/fftools/ffmpeg_filter.c @@ -1201,12 +1201,6 @@ static int configure_input_audio_filter(FilterGraph *fg, InputFilter *ifilter, static int configure_input_filter(FilterGraph *fg, InputFilter *ifilter, AVFilterInOut *in) { - if (!ifilter->ist->dec) { - av_log(NULL, AV_LOG_ERROR, - "No decoder for stream #%d:%d, filtering impossible\n", - ifilter->ist->file_index, ifilter->ist->st->index); - return AVERROR_DECODER_NOT_FOUND; - } switch (avfilter_pad_get_type(in->filter_ctx->input_pads, in->pad_idx)) { case AVMEDIA_TYPE_VIDEO: return configure_input_video_filter(fg, ifilter, in); case AVMEDIA_TYPE_AUDIO: return configure_input_audio_filter(fg, ifilter, in); From c4a3f7edb834f8359c166bc0afef2f67f231e1a9 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Sat, 13 May 2023 10:29:01 +0200 Subject: [PATCH 1133/2172] fftools/ffmpeg_filter: move InputFilter.ist to private data It is not accessed outside of ffmpeg_filter. --- fftools/ffmpeg.h | 1 - fftools/ffmpeg_filter.c | 34 +++++++++++++++++++--------------- 2 files changed, 19 insertions(+), 16 deletions(-) diff --git a/fftools/ffmpeg.h b/fftools/ffmpeg.h index 9cb9f35bc2d..c33e537faac 100644 --- a/fftools/ffmpeg.h +++ b/fftools/ffmpeg.h @@ -279,7 +279,6 @@ typedef struct OptionsContext { typedef struct InputFilter { AVFilterContext *filter; - struct InputStream *ist; struct FilterGraph *graph; uint8_t *name; enum AVMediaType type; // AVMEDIA_TYPE_SUBTITLE for sub2video diff --git a/fftools/ffmpeg_filter.c b/fftools/ffmpeg_filter.c index 16f29a313ff..e6e9e009858 100644 --- a/fftools/ffmpeg_filter.c +++ b/fftools/ffmpeg_filter.c @@ -55,6 +55,8 @@ static FilterGraphPriv *fgp_from_fg(FilterGraph *fg) typedef struct InputFilterPriv { InputFilter ifilter; + InputStream *ist; + // used to hold submitted input AVFrame *frame; @@ -247,7 +249,7 @@ static OutputFilter *ofilter_alloc(FilterGraph *fg) return ofilter; } -static InputFilter *ifilter_alloc(FilterGraph *fg) +static InputFilter *ifilter_alloc(FilterGraph *fg, InputStream *ist) { InputFilterPriv *ifp = allocate_array_elem(&fg->inputs, sizeof(*ifp), &fg->nb_inputs); @@ -261,6 +263,7 @@ static InputFilter *ifilter_alloc(FilterGraph *fg) ifp->format = -1; ifp->fallback.format = -1; + ifp->ist = ist; ifp->frame_queue = av_fifo_alloc2(8, sizeof(AVFrame*), AV_FIFO_FLAG_AUTO_GROW); if (!ifp->frame_queue) @@ -282,7 +285,7 @@ void fg_free(FilterGraph **pfg) for (int j = 0; j < fg->nb_inputs; j++) { InputFilter *ifilter = fg->inputs[j]; InputFilterPriv *ifp = ifp_from_ifilter(ifilter); - struct InputStream *ist = ifilter->ist; + InputStream *ist = ifp->ist; if (ifp->frame_queue) { AVFrame *frame; @@ -354,8 +357,7 @@ int init_simple_filtergraph(InputStream *ist, OutputStream *ost) ost->filter = ofilter; - ifilter = ifilter_alloc(fg); - ifilter->ist = ist; + ifilter = ifilter_alloc(fg, ist); ret = ist_filter_add(ist, ifilter, 1); if (ret < 0) @@ -437,8 +439,8 @@ static void init_input_filter(FilterGraph *fg, AVFilterInOut *in) } av_assert0(ist); - ifilter = ifilter_alloc(fg); - ifilter->ist = ist; + ifilter = ifilter_alloc(fg, ist); + ifilter->type = ist->st->codecpar->codec_type; ifilter->name = describe_filter_link(fg, in, 1); @@ -1019,7 +1021,7 @@ static int configure_input_video_filter(FilterGraph *fg, InputFilter *ifilter, AVFilterContext *last_filter; const AVFilter *buffer_filt = avfilter_get_by_name("buffer"); const AVPixFmtDescriptor *desc; - InputStream *ist = ifilter->ist; + InputStream *ist = ifp->ist; InputFile *f = input_files[ist->file_index]; AVRational fr = ist->framerate; AVRational sar; @@ -1145,7 +1147,7 @@ static int configure_input_audio_filter(FilterGraph *fg, InputFilter *ifilter, InputFilterPriv *ifp = ifp_from_ifilter(ifilter); AVFilterContext *last_filter; const AVFilter *abuffer_filt = avfilter_get_by_name("abuffer"); - InputStream *ist = ifilter->ist; + InputStream *ist = ifp->ist; InputFile *f = input_files[ist->file_index]; AVBPrint args; char name[255]; @@ -1380,7 +1382,7 @@ int configure_filtergraph(FilterGraph *fg) /* process queued up subtitle packets */ for (i = 0; i < fg->nb_inputs; i++) { - InputStream *ist = fg->inputs[i]->ist; + InputStream *ist = ifp_from_ifilter(fg->inputs[i])->ist; if (ist->sub2video.sub_queue && ist->sub2video.frame) { AVSubtitle tmp; while (av_fifo_read(ist->sub2video.sub_queue, &tmp, 1) >= 0) { @@ -1561,7 +1563,9 @@ int ifilter_send_eof(InputFilter *ifilter, int64_t pts, AVRational tb) } if (ifp->format < 0 && (ifilter->type == AVMEDIA_TYPE_AUDIO || ifilter->type == AVMEDIA_TYPE_VIDEO)) { - av_log(NULL, AV_LOG_ERROR, "Cannot determine format of input stream %d:%d after EOF\n", ifilter->ist->file_index, ifilter->ist->st->index); + av_log(NULL, AV_LOG_ERROR, + "Cannot determine format of input stream %d:%d after EOF\n", + ifp->ist->file_index, ifp->ist->st->index); return AVERROR_INVALIDDATA; } } @@ -1579,7 +1583,7 @@ int ifilter_send_frame(InputFilter *ifilter, AVFrame *frame, int keep_reference) /* determine if the parameters for this input changed */ need_reinit = ifp->format != frame->format; - switch (ifilter->ist->par->codec_type) { + switch (ifp->ist->par->codec_type) { case AVMEDIA_TYPE_AUDIO: need_reinit |= ifp->sample_rate != frame->sample_rate || av_channel_layout_compare(&ifp->ch_layout, &frame->ch_layout); @@ -1590,7 +1594,7 @@ int ifilter_send_frame(InputFilter *ifilter, AVFrame *frame, int keep_reference) break; } - if (!ifilter->ist->reinit_filters && fg->graph) + if (!ifp->ist->reinit_filters && fg->graph) need_reinit = 0; if (!!ifp->hw_frames_ctx != !!frame->hw_frames_ctx || @@ -1686,8 +1690,8 @@ int fg_transcode_step(FilterGraph *graph, InputStream **best_ist) for (int i = 0; i < graph->nb_inputs; i++) { InputFilter *ifilter = graph->inputs[i]; InputFilterPriv *ifp = ifp_from_ifilter(ifilter); - if (!ifilter->ist->got_output && !ifp->eof) { - *best_ist = ifilter->ist; + if (!ifp->ist->got_output && !ifp->eof) { + *best_ist = ifp->ist; return 0; } } @@ -1717,7 +1721,7 @@ int fg_transcode_step(FilterGraph *graph, InputStream **best_ist) InputFilter *ifilter = graph->inputs[i]; InputFilterPriv *ifp = ifp_from_ifilter(ifilter); - ist = ifilter->ist; + ist = ifp->ist; if (input_files[ist->file_index]->eagain || ifp->eof) continue; nb_requests = av_buffersrc_get_nb_failed_requests(ifilter->filter); From f980df2c043ae95a2b3c046c55838fed568ab925 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Sat, 13 May 2023 10:29:01 +0200 Subject: [PATCH 1134/2172] fftools/ffmpeg_filter: move InputFilter.type to private data It is not accessed outside of ffmpeg_filter. --- fftools/ffmpeg.h | 1 - fftools/ffmpeg_filter.c | 12 +++++++----- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/fftools/ffmpeg.h b/fftools/ffmpeg.h index c33e537faac..04c41a53113 100644 --- a/fftools/ffmpeg.h +++ b/fftools/ffmpeg.h @@ -281,7 +281,6 @@ typedef struct InputFilter { AVFilterContext *filter; struct FilterGraph *graph; uint8_t *name; - enum AVMediaType type; // AVMEDIA_TYPE_SUBTITLE for sub2video } InputFilter; typedef struct OutputFilter { diff --git a/fftools/ffmpeg_filter.c b/fftools/ffmpeg_filter.c index e6e9e009858..5656fa87df7 100644 --- a/fftools/ffmpeg_filter.c +++ b/fftools/ffmpeg_filter.c @@ -60,6 +60,9 @@ typedef struct InputFilterPriv { // used to hold submitted input AVFrame *frame; + // AVMEDIA_TYPE_SUBTITLE for sub2video + enum AVMediaType type; + int eof; // parameters configured for this input @@ -264,6 +267,7 @@ static InputFilter *ifilter_alloc(FilterGraph *fg, InputStream *ist) ifp->format = -1; ifp->fallback.format = -1; ifp->ist = ist; + ifp->type = ist->st->codecpar->codec_type; ifp->frame_queue = av_fifo_alloc2(8, sizeof(AVFrame*), AV_FIFO_FLAG_AUTO_GROW); if (!ifp->frame_queue) @@ -440,8 +444,6 @@ static void init_input_filter(FilterGraph *fg, AVFilterInOut *in) av_assert0(ist); ifilter = ifilter_alloc(fg, ist); - - ifilter->type = ist->st->codecpar->codec_type; ifilter->name = describe_filter_link(fg, in, 1); ret = ist_filter_add(ist, ifilter, 0); @@ -1457,8 +1459,8 @@ int ifilter_has_all_input_formats(FilterGraph *fg) int i; for (i = 0; i < fg->nb_inputs; i++) { InputFilterPriv *ifp = ifp_from_ifilter(fg->inputs[i]); - if (ifp->format < 0 && (fg->inputs[i]->type == AVMEDIA_TYPE_AUDIO || - fg->inputs[i]->type == AVMEDIA_TYPE_VIDEO)) + if (ifp->format < 0 && (ifp->type == AVMEDIA_TYPE_AUDIO || + ifp->type == AVMEDIA_TYPE_VIDEO)) return 0; } return 1; @@ -1562,7 +1564,7 @@ int ifilter_send_eof(InputFilter *ifilter, int64_t pts, AVRational tb) } } - if (ifp->format < 0 && (ifilter->type == AVMEDIA_TYPE_AUDIO || ifilter->type == AVMEDIA_TYPE_VIDEO)) { + if (ifp->format < 0 && (ifp->type == AVMEDIA_TYPE_AUDIO || ifp->type == AVMEDIA_TYPE_VIDEO)) { av_log(NULL, AV_LOG_ERROR, "Cannot determine format of input stream %d:%d after EOF\n", ifp->ist->file_index, ifp->ist->st->index); From dcfbfb417c3cc0473d887da70552026d07540232 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Sat, 13 May 2023 19:59:45 +0200 Subject: [PATCH 1135/2172] fftools/ffmpeg_filter: keep track of the real filter input type Avoid extracting it from various remote sources. --- fftools/ffmpeg_filter.c | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/fftools/ffmpeg_filter.c b/fftools/ffmpeg_filter.c index 5656fa87df7..c6994318311 100644 --- a/fftools/ffmpeg_filter.c +++ b/fftools/ffmpeg_filter.c @@ -60,8 +60,11 @@ typedef struct InputFilterPriv { // used to hold submitted input AVFrame *frame; - // AVMEDIA_TYPE_SUBTITLE for sub2video + // filter data type enum AVMediaType type; + // source data type: AVMEDIA_TYPE_SUBTITLE for sub2video, + // same as type otherwise + enum AVMediaType type_src; int eof; @@ -267,7 +270,9 @@ static InputFilter *ifilter_alloc(FilterGraph *fg, InputStream *ist) ifp->format = -1; ifp->fallback.format = -1; ifp->ist = ist; - ifp->type = ist->st->codecpar->codec_type; + ifp->type_src = ist->st->codecpar->codec_type; + ifp->type = ifp->type_src == AVMEDIA_TYPE_SUBTITLE ? + AVMEDIA_TYPE_VIDEO : ifp->type_src; ifp->frame_queue = av_fifo_alloc2(8, sizeof(AVFrame*), AV_FIFO_FLAG_AUTO_GROW); if (!ifp->frame_queue) @@ -1205,7 +1210,7 @@ static int configure_input_audio_filter(FilterGraph *fg, InputFilter *ifilter, static int configure_input_filter(FilterGraph *fg, InputFilter *ifilter, AVFilterInOut *in) { - switch (avfilter_pad_get_type(in->filter_ctx->input_pads, in->pad_idx)) { + switch (ifp_from_ifilter(ifilter)->type) { case AVMEDIA_TYPE_VIDEO: return configure_input_video_filter(fg, ifilter, in); case AVMEDIA_TYPE_AUDIO: return configure_input_audio_filter(fg, ifilter, in); default: av_assert0(0); return 0; @@ -1459,8 +1464,8 @@ int ifilter_has_all_input_formats(FilterGraph *fg) int i; for (i = 0; i < fg->nb_inputs; i++) { InputFilterPriv *ifp = ifp_from_ifilter(fg->inputs[i]); - if (ifp->format < 0 && (ifp->type == AVMEDIA_TYPE_AUDIO || - ifp->type == AVMEDIA_TYPE_VIDEO)) + if (ifp->format < 0 && (ifp->type_src == AVMEDIA_TYPE_AUDIO || + ifp->type_src == AVMEDIA_TYPE_VIDEO)) return 0; } return 1; @@ -1564,7 +1569,9 @@ int ifilter_send_eof(InputFilter *ifilter, int64_t pts, AVRational tb) } } - if (ifp->format < 0 && (ifp->type == AVMEDIA_TYPE_AUDIO || ifp->type == AVMEDIA_TYPE_VIDEO)) { + if (ifp->format < 0 && + (ifp->type_src == AVMEDIA_TYPE_AUDIO || + ifp->type_src == AVMEDIA_TYPE_VIDEO)) { av_log(NULL, AV_LOG_ERROR, "Cannot determine format of input stream %d:%d after EOF\n", ifp->ist->file_index, ifp->ist->st->index); @@ -1585,7 +1592,7 @@ int ifilter_send_frame(InputFilter *ifilter, AVFrame *frame, int keep_reference) /* determine if the parameters for this input changed */ need_reinit = ifp->format != frame->format; - switch (ifp->ist->par->codec_type) { + switch (ifp->type) { case AVMEDIA_TYPE_AUDIO: need_reinit |= ifp->sample_rate != frame->sample_rate || av_channel_layout_compare(&ifp->ch_layout, &frame->ch_layout); From 9effea016c177c44b4479524e6efd084267a2b1e Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Sat, 13 May 2023 13:36:40 +0200 Subject: [PATCH 1136/2172] fftools/ffmpeg_filter: embed displaymatrix into private context It has a small fixed size, so it is better to embed it rather than deal with dynamic allocation. --- fftools/ffmpeg_filter.c | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/fftools/ffmpeg_filter.c b/fftools/ffmpeg_filter.c index c6994318311..6f842f6b46d 100644 --- a/fftools/ffmpeg_filter.c +++ b/fftools/ffmpeg_filter.c @@ -83,7 +83,8 @@ typedef struct InputFilterPriv { AVBufferRef *hw_frames_ctx; - int32_t *displaymatrix; + int displaymatrix_present; + int32_t displaymatrix[9]; // fallback parameters to use when no input is ever sent struct { @@ -302,7 +303,6 @@ void fg_free(FilterGraph **pfg) av_frame_free(&frame); av_fifo_freep2(&ifp->frame_queue); } - av_freep(&ifp->displaymatrix); if (ist->sub2video.sub_queue) { AVSubtitle sub; while (av_fifo_read(ist->sub2video.sub_queue, &sub, 1) >= 0) @@ -1094,7 +1094,7 @@ static int configure_input_video_filter(FilterGraph *fg, InputFilter *ifilter, int32_t *displaymatrix = ifp->displaymatrix; double theta; - if (!displaymatrix) + if (!ifp->displaymatrix_present) displaymatrix = (int32_t *)av_stream_get_side_data(ist->st, AV_PKT_DATA_DISPLAYMATRIX, NULL); theta = get_rotation(displaymatrix); @@ -1450,10 +1450,10 @@ static int ifilter_parameters_from_frame(InputFilter *ifilter, const AVFrame *fr if (ret < 0) return ret; - av_freep(&ifp->displaymatrix); sd = av_frame_get_side_data(frame, AV_FRAME_DATA_DISPLAYMATRIX); if (sd) - ifp->displaymatrix = av_memdup(sd->data, sizeof(int32_t) * 9); + memcpy(ifp->displaymatrix, sd->data, sizeof(ifp->displaymatrix)); + ifp->displaymatrix_present = !!sd; return 0; } @@ -1611,9 +1611,10 @@ int ifilter_send_frame(InputFilter *ifilter, AVFrame *frame, int keep_reference) need_reinit = 1; if (sd = av_frame_get_side_data(frame, AV_FRAME_DATA_DISPLAYMATRIX)) { - if (!ifp->displaymatrix || memcmp(sd->data, ifp->displaymatrix, sizeof(int32_t) * 9)) + if (!ifp->displaymatrix_present || + memcmp(sd->data, ifp->displaymatrix, sizeof(ifp->displaymatrix))) need_reinit = 1; - } else if (ifp->displaymatrix) + } else if (ifp->displaymatrix_present) need_reinit = 1; if (need_reinit) { From 37fcbe121d97c3c7c0ddf34d0ccd866d587b6cab Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Sat, 13 May 2023 18:39:11 +0200 Subject: [PATCH 1137/2172] fftools/cmdutils: constify the argument of get_rotation() --- fftools/cmdutils.c | 2 +- fftools/cmdutils.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/fftools/cmdutils.c b/fftools/cmdutils.c index a1de621d1c2..9ec00add303 100644 --- a/fftools/cmdutils.c +++ b/fftools/cmdutils.c @@ -994,7 +994,7 @@ void *allocate_array_elem(void *ptr, size_t elem_size, int *nb_elems) return new_elem; } -double get_rotation(int32_t *displaymatrix) +double get_rotation(const int32_t *displaymatrix) { double theta = 0; if (displaymatrix) diff --git a/fftools/cmdutils.h b/fftools/cmdutils.h index 44962219839..01159402250 100644 --- a/fftools/cmdutils.h +++ b/fftools/cmdutils.h @@ -461,6 +461,6 @@ void *allocate_array_elem(void *array, size_t elem_size, int *nb_elems); char name[16];\ snprintf(name, sizeof(name), "%d", rate); -double get_rotation(int32_t *displaymatrix); +double get_rotation(const int32_t *displaymatrix); #endif /* FFTOOLS_CMDUTILS_H */ From 5fa00b38e6627578a95af9ed0cc6cd441f0903c6 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Tue, 16 May 2023 19:12:07 +0200 Subject: [PATCH 1138/2172] fftools/ffmpeg: drop an obsolete hack This special handling for decoder flushing has not been needed since af1761f7b5, as the filtergraph actually is drained after that commit. --- fftools/ffmpeg.c | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/fftools/ffmpeg.c b/fftools/ffmpeg.c index 9d554e2fb0b..49313edebc6 100644 --- a/fftools/ffmpeg.c +++ b/fftools/ffmpeg.c @@ -1418,17 +1418,6 @@ static int process_input_packet(InputStream *ist, const AVPacket *pkt, int no_eo if (!got_output) break; - // During draining, we might get multiple output frames in this loop. - // ffmpeg.c does not drain the filter chain on configuration changes, - // which means if we send multiple frames at once to the filters, and - // one of those frames changes configuration, the buffered frames will - // be lost. This can upset certain FATE tests. - // Decode only 1 frame per call on EOF to appease these FATE tests. - // The ideal solution would be to rewrite decoding to use the new - // decoding API in a better way. - if (!pkt) - break; - repeating = 1; } From 4a59dde0c72b97515582beab4ee182be09360005 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Tue, 16 May 2023 19:19:09 +0200 Subject: [PATCH 1139/2172] fftools/ffmpeg: eliminate InputStream.got_output It tracks whether the decoder for this stream ever produced any frames and its only use is for checking whether a filter input ever received a frame - those that did not are prioritized by the scheduler. This is awkward and unnecessarily complicated - checking whether the filtergraph input format is valid works just as well and does not require maintaining an extra variable. --- fftools/ffmpeg.c | 3 --- fftools/ffmpeg.h | 2 -- fftools/ffmpeg_filter.c | 2 +- 3 files changed, 1 insertion(+), 6 deletions(-) diff --git a/fftools/ffmpeg.c b/fftools/ffmpeg.c index 49313edebc6..62620bacce9 100644 --- a/fftools/ffmpeg.c +++ b/fftools/ffmpeg.c @@ -1412,9 +1412,6 @@ static int process_input_packet(InputStream *ist, const AVPacket *pkt, int no_eo break; } - if (got_output) - ist->got_output = 1; - if (!got_output) break; diff --git a/fftools/ffmpeg.h b/fftools/ffmpeg.h index 04c41a53113..3a332768df7 100644 --- a/fftools/ffmpeg.h +++ b/fftools/ffmpeg.h @@ -413,8 +413,6 @@ typedef struct InputStream { // number of frames/samples retrieved from the decoder uint64_t frames_decoded; uint64_t samples_decoded; - - int got_output; } InputStream; typedef struct LastFrameDuration { diff --git a/fftools/ffmpeg_filter.c b/fftools/ffmpeg_filter.c index 6f842f6b46d..640ecec067c 100644 --- a/fftools/ffmpeg_filter.c +++ b/fftools/ffmpeg_filter.c @@ -1700,7 +1700,7 @@ int fg_transcode_step(FilterGraph *graph, InputStream **best_ist) for (int i = 0; i < graph->nb_inputs; i++) { InputFilter *ifilter = graph->inputs[i]; InputFilterPriv *ifp = ifp_from_ifilter(ifilter); - if (!ifp->ist->got_output && !ifp->eof) { + if (ifp->format < 0 && !ifp->eof) { *best_ist = ifp->ist; return 0; } From 4fbc699ac3c9ab69b4c5474145593c809e0286f8 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Tue, 16 May 2023 19:29:14 +0200 Subject: [PATCH 1140/2172] fftools/ffmpeg: replace an unreachable return with av_assert0(0) This cannot be reached, because initialization will fail if decoding is requested for a stream but no decoder can be found. --- fftools/ffmpeg.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/fftools/ffmpeg.c b/fftools/ffmpeg.c index 62620bacce9..1fcabd123af 100644 --- a/fftools/ffmpeg.c +++ b/fftools/ffmpeg.c @@ -1390,8 +1390,7 @@ static int process_input_packet(InputStream *ist, const AVPacket *pkt, int no_eo ret = AVERROR_EOF; av_packet_unref(avpkt); break; - default: - return -1; + default: av_assert0(0); } if (ret == AVERROR_EOF) { From d064c9ded58092f82955a27fdefeab14a0907910 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Tue, 16 May 2023 19:47:12 +0200 Subject: [PATCH 1141/2172] fftools/ffmpeg: deobfuscate check_decode_result() call Passing ist=NULL is currently used to identify stream types that do not decode into AVFrames, i.e. subtitles. That is highly non-obvious - always pass a non-NULL InputStream and just check the type explicitly. --- fftools/ffmpeg.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/fftools/ffmpeg.c b/fftools/ffmpeg.c index 1fcabd123af..537f2876376 100644 --- a/fftools/ffmpeg.c +++ b/fftools/ffmpeg.c @@ -777,7 +777,7 @@ static void check_decode_result(InputStream *ist, int *got_output, int ret) if (ret < 0 && exit_on_error) exit_program(1); - if (*got_output && ist) { + if (*got_output && ist->dec_ctx->codec_type != AVMEDIA_TYPE_SUBTITLE) { if (ist->decoded_frame->decode_error_flags || (ist->decoded_frame->flags & AV_FRAME_FLAG_CORRUPT)) { av_log(ist, exit_on_error ? AV_LOG_FATAL : AV_LOG_WARNING, "corrupt decoded frame\n"); @@ -1317,7 +1317,7 @@ static int transcode_subtitles(InputStream *ist, const AVPacket *pkt, int ret = avcodec_decode_subtitle2(ist->dec_ctx, &subtitle, got_output, pkt); - check_decode_result(NULL, got_output, ret); + check_decode_result(ist, got_output, ret); if (ret < 0 || !*got_output) { *decode_failed = 1; From 4cec5ffc4568fabba0f69ac6aa95b5ee2b1005ab Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Tue, 16 May 2023 20:21:20 +0200 Subject: [PATCH 1142/2172] fftools/ffmpeg: rework handling -max_error_rate Replace the decode_error_stat global with a per-input-stream variable. Also, print an error message when the error rate is exceeded. --- fftools/ffmpeg.c | 33 +++++++++++++++++++++------------ fftools/ffmpeg.h | 1 + fftools/ffmpeg_demux.c | 5 +++-- 3 files changed, 25 insertions(+), 14 deletions(-) diff --git a/fftools/ffmpeg.c b/fftools/ffmpeg.c index 537f2876376..414bae17475 100644 --- a/fftools/ffmpeg.c +++ b/fftools/ffmpeg.c @@ -121,7 +121,6 @@ static int64_t getmaxrss(void); int64_t nb_frames_dup = 0; int64_t nb_frames_drop = 0; -static int64_t decode_error_stat[2]; unsigned nb_output_dumped = 0; static BenchmarkTimeStamps current_time; @@ -771,8 +770,8 @@ static void print_report(int is_last_report, int64_t timer_start, int64_t cur_ti static void check_decode_result(InputStream *ist, int *got_output, int ret) { - if (*got_output || ret<0) - decode_error_stat[ret<0] ++; + if (ret < 0) + ist->decode_errors++; if (ret < 0 && exit_on_error) exit_program(1); @@ -1807,14 +1806,15 @@ static int transcode_step(OutputStream *ost) /* * The following code is the main loop of the file converter */ -static int transcode(void) +static int transcode(int *err_rate_exceeded) { - int ret, i; + int ret = 0, i; InputStream *ist; int64_t timer_start; print_stream_maps(); + *err_rate_exceeded = 0; atomic_store(&transcode_init_done, 1); if (stdin_interaction) { @@ -1855,9 +1855,20 @@ static int transcode(void) /* at the end of stream, we must flush the decoder buffers */ for (ist = ist_iter(NULL); ist; ist = ist_iter(ist)) { + float err_rate; + if (!input_files[ist->file_index]->eof_reached) { process_input_packet(ist, NULL, 0); } + + err_rate = (ist->frames_decoded || ist->decode_errors) ? + ist->decode_errors / (ist->frames_decoded + ist->decode_errors) : 0.f; + if (err_rate > max_error_rate) { + av_log(ist, AV_LOG_FATAL, "Decode error rate %g exceeds maximum %g\n", + err_rate, max_error_rate); + *err_rate_exceeded = 1; + } else if (err_rate) + av_log(ist, AV_LOG_VERBOSE, "Decode error rate %g\n", err_rate); } enc_flush(); @@ -1921,7 +1932,7 @@ static int64_t getmaxrss(void) int main(int argc, char **argv) { - int ret; + int ret, err_rate_exceeded; BenchmarkTimeStamps ti; init_dynload(); @@ -1958,7 +1969,7 @@ int main(int argc, char **argv) } current_time = ti = get_benchmark_time_stamps(); - ret = transcode(); + ret = transcode(&err_rate_exceeded); if (ret >= 0 && do_benchmark) { int64_t utime, stime, rtime; current_time = get_benchmark_time_stamps(); @@ -1969,12 +1980,10 @@ int main(int argc, char **argv) "bench: utime=%0.3fs stime=%0.3fs rtime=%0.3fs\n", utime / 1000000.0, stime / 1000000.0, rtime / 1000000.0); } - av_log(NULL, AV_LOG_DEBUG, "%"PRIu64" frames successfully decoded, %"PRIu64" decoding errors\n", - decode_error_stat[0], decode_error_stat[1]); - if ((decode_error_stat[0] + decode_error_stat[1]) * max_error_rate < decode_error_stat[1]) - exit_program(69); - ret = received_nb_signals ? 255 : ret; + ret = received_nb_signals ? 255 : + err_rate_exceeded ? 69 : ret; + exit_program(ret); return ret; } diff --git a/fftools/ffmpeg.h b/fftools/ffmpeg.h index 3a332768df7..87e684a1479 100644 --- a/fftools/ffmpeg.h +++ b/fftools/ffmpeg.h @@ -413,6 +413,7 @@ typedef struct InputStream { // number of frames/samples retrieved from the decoder uint64_t frames_decoded; uint64_t samples_decoded; + uint64_t decode_errors; } InputStream; typedef struct LastFrameDuration { diff --git a/fftools/ffmpeg_demux.c b/fftools/ffmpeg_demux.c index df87e0f30a6..401ae1f850f 100644 --- a/fftools/ffmpeg_demux.c +++ b/fftools/ffmpeg_demux.c @@ -786,8 +786,9 @@ static void demux_final_stats(Demuxer *d) ds->nb_packets, ds->data_size); if (ist->decoding_needed) { - av_log(f, AV_LOG_VERBOSE, "%"PRIu64" frames decoded", - ist->frames_decoded); + av_log(f, AV_LOG_VERBOSE, + "%"PRIu64" frames decoded; %"PRIu64" decode errors", + ist->frames_decoded, ist->decode_errors); if (type == AVMEDIA_TYPE_AUDIO) av_log(f, AV_LOG_VERBOSE, " (%"PRIu64" samples)", ist->samples_decoded); av_log(f, AV_LOG_VERBOSE, "; "); From b5beff3f15bdb2ac6d3efe41defc0f030c3f08fe Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Tue, 16 May 2023 22:20:48 +0200 Subject: [PATCH 1143/2172] fftools/ffmpeg: move a block to a more appropriate place New placement requires fewer explicit conditions and is easier to understand. The logic should be exactly equivalent, since this is the only place where eof_reached is set for decoding. --- fftools/ffmpeg.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/fftools/ffmpeg.c b/fftools/ffmpeg.c index 414bae17475..b88064a2bc6 100644 --- a/fftools/ffmpeg.c +++ b/fftools/ffmpeg.c @@ -1393,6 +1393,16 @@ static int process_input_packet(InputStream *ist, const AVPacket *pkt, int no_eo } if (ret == AVERROR_EOF) { + /* after flushing, send an EOF on all the filter inputs attached to the stream */ + /* except when looping we need to flush but not to send an EOF */ + if (!no_eof) { + ret = send_filter_eof(ist); + if (ret < 0) { + av_log(NULL, AV_LOG_FATAL, "Error marking filters as finished\n"); + exit_program(1); + } + } + eof_reached = 1; break; } @@ -1416,16 +1426,6 @@ static int process_input_packet(InputStream *ist, const AVPacket *pkt, int no_eo repeating = 1; } - /* after flushing, send an EOF on all the filter inputs attached to the stream */ - /* except when looping we need to flush but not to send an EOF */ - if (!pkt && ist->decoding_needed && eof_reached && !no_eof) { - int ret = send_filter_eof(ist); - if (ret < 0) { - av_log(NULL, AV_LOG_FATAL, "Error marking filters as finished\n"); - exit_program(1); - } - } - if (!pkt && !ist->decoding_needed) eof_reached = 1; From 79c1dde5c3225e61aea064809547dd430bb83feb Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Wed, 17 May 2023 09:29:30 +0200 Subject: [PATCH 1144/2172] fftools/ffmpeg: split decoding loop out of process_input_packet() process_input_packet() contains two non-interacting pieces of nontrivial size and complexity - decoding and streamcopy. Separating them makes the code easier to read. --- fftools/ffmpeg.c | 37 ++++++++++++++++++++----------------- 1 file changed, 20 insertions(+), 17 deletions(-) diff --git a/fftools/ffmpeg.c b/fftools/ffmpeg.c index b88064a2bc6..cc134dc49d1 100644 --- a/fftools/ffmpeg.c +++ b/fftools/ffmpeg.c @@ -1344,18 +1344,10 @@ static int send_filter_eof(InputStream *ist) return 0; } -/* pkt = NULL means EOF (needed to flush decoder buffers) */ -static int process_input_packet(InputStream *ist, const AVPacket *pkt, int no_eof) +static int dec_packet(InputStream *ist, const AVPacket *pkt, int no_eof) { - InputFile *f = input_files[ist->file_index]; - const AVCodecParameters *par = ist->par; - int64_t dts_est = AV_NOPTS_VALUE; - int ret = 0; - int repeating = 0; - int eof_reached = 0; - int duration_exceeded; - AVPacket *avpkt = ist->pkt; + int ret, repeating = 0; if (pkt) { av_packet_unref(avpkt); @@ -1365,11 +1357,11 @@ static int process_input_packet(InputStream *ist, const AVPacket *pkt, int no_eo } // while we have more to decode or while the decoder did output something on EOF - while (ist->decoding_needed) { + while (1) { int got_output = 0; int decode_failed = 0; - switch (par->codec_type) { + switch (ist->par->codec_type) { case AVMEDIA_TYPE_AUDIO: ret = decode_audio (ist, repeating ? NULL : avpkt, &got_output, &decode_failed); @@ -1403,8 +1395,7 @@ static int process_input_packet(InputStream *ist, const AVPacket *pkt, int no_eo } } - eof_reached = 1; - break; + return AVERROR_EOF; } if (ret < 0) { @@ -1417,16 +1408,28 @@ static int process_input_packet(InputStream *ist, const AVPacket *pkt, int no_eo } if (!decode_failed || exit_on_error) exit_program(1); - break; + return ret; } if (!got_output) - break; + return 0; repeating = 1; } +} + +/* pkt = NULL means EOF (needed to flush decoder buffers) */ +static int process_input_packet(InputStream *ist, const AVPacket *pkt, int no_eof) +{ + InputFile *f = input_files[ist->file_index]; + int64_t dts_est = AV_NOPTS_VALUE; + int ret = 0; + int eof_reached = 0; + int duration_exceeded; - if (!pkt && !ist->decoding_needed) + if (ist->decoding_needed) + ret = dec_packet(ist, pkt, no_eof); + if (ret == AVERROR_EOF || (!pkt && !ist->decoding_needed)) eof_reached = 1; if (pkt && pkt->opaque_ref) { From dbf1c6f5f1f2cfaf4837e72d0c77f675a4318522 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Wed, 17 May 2023 09:36:14 +0200 Subject: [PATCH 1145/2172] fftools/ffmpeg: move decoding code to ffmpeg_dec --- fftools/ffmpeg.c | 534 ------------------------------------------ fftools/ffmpeg.h | 12 + fftools/ffmpeg_dec.c | 538 +++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 550 insertions(+), 534 deletions(-) diff --git a/fftools/ffmpeg.c b/fftools/ffmpeg.c index cc134dc49d1..c70d38755b0 100644 --- a/fftools/ffmpeg.c +++ b/fftools/ffmpeg.c @@ -283,20 +283,6 @@ static void sub2video_heartbeat(InputStream *ist, int64_t pts) } } -static void sub2video_flush(InputStream *ist) -{ - int i; - int ret; - - if (ist->sub2video.end_pts < INT64_MAX) - sub2video_update(ist, INT64_MAX, NULL); - for (i = 0; i < ist->nb_filters; i++) { - ret = av_buffersrc_add_frame(ist->filters[i]->filter, NULL); - if (ret != AVERROR_EOF && ret < 0) - av_log(NULL, AV_LOG_WARNING, "Flush the frame error.\n"); - } -} - /* end of sub2video hack */ static void term_exit_sigsafe(void) @@ -768,417 +754,6 @@ static void print_report(int is_last_report, int64_t timer_start, int64_t cur_ti first_report = 0; } -static void check_decode_result(InputStream *ist, int *got_output, int ret) -{ - if (ret < 0) - ist->decode_errors++; - - if (ret < 0 && exit_on_error) - exit_program(1); - - if (*got_output && ist->dec_ctx->codec_type != AVMEDIA_TYPE_SUBTITLE) { - if (ist->decoded_frame->decode_error_flags || (ist->decoded_frame->flags & AV_FRAME_FLAG_CORRUPT)) { - av_log(ist, exit_on_error ? AV_LOG_FATAL : AV_LOG_WARNING, - "corrupt decoded frame\n"); - if (exit_on_error) - exit_program(1); - } - } -} - -// This does not quite work like avcodec_decode_audio4/avcodec_decode_video2. -// There is the following difference: if you got a frame, you must call -// it again with pkt=NULL. pkt==NULL is treated differently from pkt->size==0 -// (pkt==NULL means get more output, pkt->size==0 is a flush/drain packet) -static int decode(InputStream *ist, AVCodecContext *avctx, - AVFrame *frame, int *got_frame, const AVPacket *pkt) -{ - int ret; - - *got_frame = 0; - - if (pkt) { - ret = avcodec_send_packet(avctx, pkt); - // In particular, we don't expect AVERROR(EAGAIN), because we read all - // decoded frames with avcodec_receive_frame() until done. - if (ret < 0 && ret != AVERROR_EOF) - return ret; - } - - ret = avcodec_receive_frame(avctx, frame); - if (ret < 0 && ret != AVERROR(EAGAIN)) - return ret; - if (ret >= 0) { - if (ist->want_frame_data) { - FrameData *fd; - - av_assert0(!frame->opaque_ref); - frame->opaque_ref = av_buffer_allocz(sizeof(*fd)); - if (!frame->opaque_ref) { - av_frame_unref(frame); - return AVERROR(ENOMEM); - } - fd = (FrameData*)frame->opaque_ref->data; - fd->pts = frame->pts; - fd->tb = avctx->pkt_timebase; - fd->idx = avctx->frame_num - 1; - } - - frame->time_base = avctx->pkt_timebase; - - *got_frame = 1; - } - - return 0; -} - -static int send_frame_to_filters(InputStream *ist, AVFrame *decoded_frame) -{ - int i, ret; - - av_assert1(ist->nb_filters > 0); /* ensure ret is initialized */ - for (i = 0; i < ist->nb_filters; i++) { - ret = ifilter_send_frame(ist->filters[i], decoded_frame, i < ist->nb_filters - 1); - if (ret == AVERROR_EOF) - ret = 0; /* ignore */ - if (ret < 0) { - av_log(NULL, AV_LOG_ERROR, - "Failed to inject frame into filter network: %s\n", av_err2str(ret)); - break; - } - } - return ret; -} - -static AVRational audio_samplerate_update(InputStream *ist, const AVFrame *frame) -{ - const int prev = ist->last_frame_tb.den; - const int sr = frame->sample_rate; - - AVRational tb_new; - int64_t gcd; - - if (frame->sample_rate == ist->last_frame_sample_rate) - goto finish; - - gcd = av_gcd(prev, sr); - - if (prev / gcd >= INT_MAX / sr) { - av_log(ist, AV_LOG_WARNING, - "Audio timestamps cannot be represented exactly after " - "sample rate change: %d -> %d\n", prev, sr); - - // LCM of 192000, 44100, allows to represent all common samplerates - tb_new = (AVRational){ 1, 28224000 }; - } else - tb_new = (AVRational){ 1, prev / gcd * sr }; - - // keep the frame timebase if it is strictly better than - // the samplerate-defined one - if (frame->time_base.num == 1 && frame->time_base.den > tb_new.den && - !(frame->time_base.den % tb_new.den)) - tb_new = frame->time_base; - - if (ist->last_frame_pts != AV_NOPTS_VALUE) - ist->last_frame_pts = av_rescale_q(ist->last_frame_pts, - ist->last_frame_tb, tb_new); - ist->last_frame_duration_est = av_rescale_q(ist->last_frame_duration_est, - ist->last_frame_tb, tb_new); - - ist->last_frame_tb = tb_new; - ist->last_frame_sample_rate = frame->sample_rate; - -finish: - return ist->last_frame_tb; -} - -static void audio_ts_process(InputStream *ist, AVFrame *frame) -{ - AVRational tb_filter = (AVRational){1, frame->sample_rate}; - AVRational tb; - int64_t pts_pred; - - // on samplerate change, choose a new internal timebase for timestamp - // generation that can represent timestamps from all the samplerates - // seen so far - tb = audio_samplerate_update(ist, frame); - pts_pred = ist->last_frame_pts == AV_NOPTS_VALUE ? 0 : - ist->last_frame_pts + ist->last_frame_duration_est; - - if (frame->pts == AV_NOPTS_VALUE) { - frame->pts = pts_pred; - frame->time_base = tb; - } else if (ist->last_frame_pts != AV_NOPTS_VALUE && - frame->pts > av_rescale_q_rnd(pts_pred, tb, frame->time_base, - AV_ROUND_UP)) { - // there was a gap in timestamps, reset conversion state - ist->filter_in_rescale_delta_last = AV_NOPTS_VALUE; - } - - frame->pts = av_rescale_delta(frame->time_base, frame->pts, - tb, frame->nb_samples, - &ist->filter_in_rescale_delta_last, tb); - - ist->last_frame_pts = frame->pts; - ist->last_frame_duration_est = av_rescale_q(frame->nb_samples, - tb_filter, tb); - - // finally convert to filtering timebase - frame->pts = av_rescale_q(frame->pts, tb, tb_filter); - frame->duration = frame->nb_samples; - frame->time_base = tb_filter; -} - -static int decode_audio(InputStream *ist, const AVPacket *pkt, int *got_output, - int *decode_failed) -{ - AVFrame *decoded_frame = ist->decoded_frame; - AVCodecContext *avctx = ist->dec_ctx; - int ret, err = 0; - - update_benchmark(NULL); - ret = decode(ist, avctx, decoded_frame, got_output, pkt); - update_benchmark("decode_audio %d.%d", ist->file_index, ist->st->index); - if (ret < 0) - *decode_failed = 1; - - if (ret != AVERROR_EOF) - check_decode_result(ist, got_output, ret); - - if (!*got_output || ret < 0) - return ret; - - ist->samples_decoded += decoded_frame->nb_samples; - ist->frames_decoded++; - - audio_ts_process(ist, decoded_frame); - - ist->nb_samples = decoded_frame->nb_samples; - err = send_frame_to_filters(ist, decoded_frame); - - av_frame_unref(decoded_frame); - return err < 0 ? err : ret; -} - -static int64_t video_duration_estimate(const InputStream *ist, const AVFrame *frame) -{ - const InputFile *ifile = input_files[ist->file_index]; - int64_t codec_duration = 0; - - // XXX lavf currently makes up frame durations when they are not provided by - // the container. As there is no way to reliably distinguish real container - // durations from the fake made-up ones, we use heuristics based on whether - // the container has timestamps. Eventually lavf should stop making up - // durations, then this should be simplified. - - // prefer frame duration for containers with timestamps - if (frame->duration > 0 && (!ifile->format_nots || ist->framerate.num)) - return frame->duration; - - if (ist->dec_ctx->framerate.den && ist->dec_ctx->framerate.num) { - int fields = frame->repeat_pict + 2; - AVRational field_rate = av_mul_q(ist->dec_ctx->framerate, - (AVRational){ 2, 1 }); - codec_duration = av_rescale_q(fields, av_inv_q(field_rate), - frame->time_base); - } - - // prefer codec-layer duration for containers without timestamps - if (codec_duration > 0 && ifile->format_nots) - return codec_duration; - - // when timestamps are available, repeat last frame's actual duration - // (i.e. pts difference between this and last frame) - if (frame->pts != AV_NOPTS_VALUE && ist->last_frame_pts != AV_NOPTS_VALUE && - frame->pts > ist->last_frame_pts) - return frame->pts - ist->last_frame_pts; - - // try frame/codec duration - if (frame->duration > 0) - return frame->duration; - if (codec_duration > 0) - return codec_duration; - - // try average framerate - if (ist->st->avg_frame_rate.num && ist->st->avg_frame_rate.den) { - int64_t d = av_rescale_q(1, av_inv_q(ist->st->avg_frame_rate), - frame->time_base); - if (d > 0) - return d; - } - - // last resort is last frame's estimated duration, and 1 - return FFMAX(ist->last_frame_duration_est, 1); -} - -static int decode_video(InputStream *ist, const AVPacket *pkt, int *got_output, - int eof, int *decode_failed) -{ - AVFrame *frame = ist->decoded_frame; - int ret = 0, err = 0; - - // With fate-indeo3-2, we're getting 0-sized packets before EOF for some - // reason. This seems like a semi-critical bug. Don't trigger EOF, and - // skip the packet. - if (!eof && pkt && pkt->size == 0) - return 0; - - update_benchmark(NULL); - ret = decode(ist, ist->dec_ctx, frame, got_output, pkt); - update_benchmark("decode_video %d.%d", ist->file_index, ist->st->index); - if (ret < 0) - *decode_failed = 1; - - // The following line may be required in some cases where there is no parser - // or the parser does not has_b_frames correctly - if (ist->par->video_delay < ist->dec_ctx->has_b_frames) { - if (ist->dec_ctx->codec_id == AV_CODEC_ID_H264) { - ist->par->video_delay = ist->dec_ctx->has_b_frames; - } else - av_log(ist->dec_ctx, AV_LOG_WARNING, - "video_delay is larger in decoder than demuxer %d > %d.\n" - "If you want to help, upload a sample " - "of this file to https://streams.videolan.org/upload/ " - "and contact the ffmpeg-devel mailing list. (ffmpeg-devel@ffmpeg.org)\n", - ist->dec_ctx->has_b_frames, - ist->par->video_delay); - } - - if (ret != AVERROR_EOF) - check_decode_result(ist, got_output, ret); - - if (*got_output && ret >= 0) { - if (ist->dec_ctx->width != frame->width || - ist->dec_ctx->height != frame->height || - ist->dec_ctx->pix_fmt != frame->format) { - av_log(NULL, AV_LOG_DEBUG, "Frame parameters mismatch context %d,%d,%d != %d,%d,%d\n", - frame->width, - frame->height, - frame->format, - ist->dec_ctx->width, - ist->dec_ctx->height, - ist->dec_ctx->pix_fmt); - } - } - - if (!*got_output || ret < 0) - return ret; - - if(ist->top_field_first>=0) - frame->flags |= AV_FRAME_FLAG_TOP_FIELD_FIRST; - - ist->frames_decoded++; - - if (ist->hwaccel_retrieve_data && frame->format == ist->hwaccel_pix_fmt) { - err = ist->hwaccel_retrieve_data(ist->dec_ctx, frame); - if (err < 0) - goto fail; - } - - frame->pts = frame->best_effort_timestamp; - - // forced fixed framerate - if (ist->framerate.num) { - frame->pts = AV_NOPTS_VALUE; - frame->duration = 1; - frame->time_base = av_inv_q(ist->framerate); - } - - // no timestamp available - extrapolate from previous frame duration - if (frame->pts == AV_NOPTS_VALUE) - frame->pts = ist->last_frame_pts == AV_NOPTS_VALUE ? 0 : - ist->last_frame_pts + ist->last_frame_duration_est; - - // update timestamp history - ist->last_frame_duration_est = video_duration_estimate(ist, frame); - ist->last_frame_pts = frame->pts; - ist->last_frame_tb = frame->time_base; - - if (debug_ts) { - av_log(ist, AV_LOG_INFO, - "decoder -> pts:%s pts_time:%s " - "pkt_dts:%s pkt_dts_time:%s " - "duration:%s duration_time:%s " - "keyframe:%d frame_type:%d time_base:%d/%d\n", - av_ts2str(frame->pts), - av_ts2timestr(frame->pts, &frame->time_base), - av_ts2str(frame->pkt_dts), - av_ts2timestr(frame->pkt_dts, &frame->time_base), - av_ts2str(frame->duration), - av_ts2timestr(frame->duration, &frame->time_base), - !!(frame->flags & AV_FRAME_FLAG_KEY), frame->pict_type, - frame->time_base.num, frame->time_base.den); - } - - if (ist->st->sample_aspect_ratio.num) - frame->sample_aspect_ratio = ist->st->sample_aspect_ratio; - - err = send_frame_to_filters(ist, frame); - -fail: - av_frame_unref(frame); - return err < 0 ? err : ret; -} - -static int process_subtitle(InputStream *ist, AVSubtitle *subtitle, int *got_output) -{ - int ret = 0; - int free_sub = 1; - - if (ist->fix_sub_duration) { - int end = 1; - if (ist->prev_sub.got_output) { - end = av_rescale(subtitle->pts - ist->prev_sub.subtitle.pts, - 1000, AV_TIME_BASE); - if (end < ist->prev_sub.subtitle.end_display_time) { - av_log(NULL, AV_LOG_DEBUG, - "Subtitle duration reduced from %"PRId32" to %d%s\n", - ist->prev_sub.subtitle.end_display_time, end, - end <= 0 ? ", dropping it" : ""); - ist->prev_sub.subtitle.end_display_time = end; - } - } - FFSWAP(int, *got_output, ist->prev_sub.got_output); - FFSWAP(int, ret, ist->prev_sub.ret); - FFSWAP(AVSubtitle, *subtitle, ist->prev_sub.subtitle); - if (end <= 0) - goto out; - } - - if (!*got_output) - return ret; - - if (ist->sub2video.frame) { - sub2video_update(ist, INT64_MIN, subtitle); - } else if (ist->nb_filters) { - if (!ist->sub2video.sub_queue) - ist->sub2video.sub_queue = av_fifo_alloc2(8, sizeof(AVSubtitle), AV_FIFO_FLAG_AUTO_GROW); - if (!ist->sub2video.sub_queue) - report_and_exit(AVERROR(ENOMEM)); - - ret = av_fifo_write(ist->sub2video.sub_queue, subtitle, 1); - if (ret < 0) - exit_program(1); - free_sub = 0; - } - - if (!subtitle->num_rects) - goto out; - - for (int oidx = 0; oidx < ist->nb_outputs; oidx++) { - OutputStream *ost = ist->outputs[oidx]; - if (!ost->enc || ost->type != AVMEDIA_TYPE_SUBTITLE) - continue; - - enc_subtitle(output_files[ost->file_index], ost, subtitle); - } - -out: - if (free_sub) - avsubtitle_free(subtitle); - return ret; -} - static int copy_av_subtitle(AVSubtitle *dst, AVSubtitle *src) { int ret = AVERROR_BUG; @@ -1309,115 +884,6 @@ int trigger_fix_sub_duration_heartbeat(OutputStream *ost, const AVPacket *pkt) return 0; } -static int transcode_subtitles(InputStream *ist, const AVPacket *pkt, - int *got_output, int *decode_failed) -{ - AVSubtitle subtitle; - int ret = avcodec_decode_subtitle2(ist->dec_ctx, - &subtitle, got_output, pkt); - - check_decode_result(ist, got_output, ret); - - if (ret < 0 || !*got_output) { - *decode_failed = 1; - if (!pkt->size) - sub2video_flush(ist); - return ret; - } - - ist->frames_decoded++; - - return process_subtitle(ist, &subtitle, got_output); -} - -static int send_filter_eof(InputStream *ist) -{ - int i, ret; - - for (i = 0; i < ist->nb_filters; i++) { - int64_t end_pts = ist->last_frame_pts == AV_NOPTS_VALUE ? AV_NOPTS_VALUE : - ist->last_frame_pts + ist->last_frame_duration_est; - ret = ifilter_send_eof(ist->filters[i], end_pts, ist->last_frame_tb); - if (ret < 0) - return ret; - } - return 0; -} - -static int dec_packet(InputStream *ist, const AVPacket *pkt, int no_eof) -{ - AVPacket *avpkt = ist->pkt; - int ret, repeating = 0; - - if (pkt) { - av_packet_unref(avpkt); - ret = av_packet_ref(avpkt, pkt); - if (ret < 0) - return ret; - } - - // while we have more to decode or while the decoder did output something on EOF - while (1) { - int got_output = 0; - int decode_failed = 0; - - switch (ist->par->codec_type) { - case AVMEDIA_TYPE_AUDIO: - ret = decode_audio (ist, repeating ? NULL : avpkt, &got_output, - &decode_failed); - av_packet_unref(avpkt); - break; - case AVMEDIA_TYPE_VIDEO: - ret = decode_video (ist, repeating ? NULL : avpkt, &got_output, !pkt, - &decode_failed); - - av_packet_unref(avpkt); - break; - case AVMEDIA_TYPE_SUBTITLE: - if (repeating) - break; - ret = transcode_subtitles(ist, avpkt, &got_output, &decode_failed); - if (!pkt && ret >= 0) - ret = AVERROR_EOF; - av_packet_unref(avpkt); - break; - default: av_assert0(0); - } - - if (ret == AVERROR_EOF) { - /* after flushing, send an EOF on all the filter inputs attached to the stream */ - /* except when looping we need to flush but not to send an EOF */ - if (!no_eof) { - ret = send_filter_eof(ist); - if (ret < 0) { - av_log(NULL, AV_LOG_FATAL, "Error marking filters as finished\n"); - exit_program(1); - } - } - - return AVERROR_EOF; - } - - if (ret < 0) { - if (decode_failed) { - av_log(NULL, AV_LOG_ERROR, "Error while decoding stream #%d:%d: %s\n", - ist->file_index, ist->st->index, av_err2str(ret)); - } else { - av_log(NULL, AV_LOG_FATAL, "Error while processing the decoded " - "data for stream #%d:%d\n", ist->file_index, ist->st->index); - } - if (!decode_failed || exit_on_error) - exit_program(1); - return ret; - } - - if (!got_output) - return 0; - - repeating = 1; - } -} - /* pkt = NULL means EOF (needed to flush decoder buffers) */ static int process_input_packet(InputStream *ist, const AVPacket *pkt, int no_eof) { diff --git a/fftools/ffmpeg.h b/fftools/ffmpeg.h index 87e684a1479..45be3b18231 100644 --- a/fftools/ffmpeg.h +++ b/fftools/ffmpeg.h @@ -811,6 +811,17 @@ int hwaccel_decode_init(AVCodecContext *avctx); int dec_open(InputStream *ist); +/** + * Submit a packet for decoding + * + * When pkt==NULL and no_eof=0, there will be no more input. Flush decoders and + * mark all downstreams as finished. + * + * When pkt==NULL and no_eof=1, the stream was reset (e.g. after a seek). Flush + * decoders and await further input. + */ +int dec_packet(InputStream *ist, const AVPacket *pkt, int no_eof); + int enc_alloc(Encoder **penc, const AVCodec *codec); void enc_free(Encoder **penc); @@ -885,6 +896,7 @@ OutputStream *ost_iter(OutputStream *prev); void close_output_stream(OutputStream *ost); int trigger_fix_sub_duration_heartbeat(OutputStream *ost, const AVPacket *pkt); +int process_subtitle(InputStream *ist, AVSubtitle *subtitle, int *got_output); void update_benchmark(const char *fmt, ...); /** diff --git a/fftools/ffmpeg_dec.c b/fftools/ffmpeg_dec.c index 658e7418e93..30fe75d8a69 100644 --- a/fftools/ffmpeg_dec.c +++ b/fftools/ffmpeg_dec.c @@ -16,17 +16,555 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#include "libavutil/avassert.h" #include "libavutil/dict.h" #include "libavutil/error.h" #include "libavutil/log.h" #include "libavutil/pixdesc.h" #include "libavutil/pixfmt.h" +#include "libavutil/timestamp.h" #include "libavcodec/avcodec.h" #include "libavcodec/codec.h" +#include "libavfilter/buffersrc.h" + #include "ffmpeg.h" +static void check_decode_result(InputStream *ist, int *got_output, int ret) +{ + if (ret < 0) + ist->decode_errors++; + + if (ret < 0 && exit_on_error) + exit_program(1); + + if (*got_output && ist->dec_ctx->codec_type != AVMEDIA_TYPE_SUBTITLE) { + if (ist->decoded_frame->decode_error_flags || (ist->decoded_frame->flags & AV_FRAME_FLAG_CORRUPT)) { + av_log(ist, exit_on_error ? AV_LOG_FATAL : AV_LOG_WARNING, + "corrupt decoded frame\n"); + if (exit_on_error) + exit_program(1); + } + } +} + +// This does not quite work like avcodec_decode_audio4/avcodec_decode_video2. +// There is the following difference: if you got a frame, you must call +// it again with pkt=NULL. pkt==NULL is treated differently from pkt->size==0 +// (pkt==NULL means get more output, pkt->size==0 is a flush/drain packet) +static int decode(InputStream *ist, AVCodecContext *avctx, + AVFrame *frame, int *got_frame, const AVPacket *pkt) +{ + int ret; + + *got_frame = 0; + + if (pkt) { + ret = avcodec_send_packet(avctx, pkt); + // In particular, we don't expect AVERROR(EAGAIN), because we read all + // decoded frames with avcodec_receive_frame() until done. + if (ret < 0 && ret != AVERROR_EOF) + return ret; + } + + ret = avcodec_receive_frame(avctx, frame); + if (ret < 0 && ret != AVERROR(EAGAIN)) + return ret; + if (ret >= 0) { + if (ist->want_frame_data) { + FrameData *fd; + + av_assert0(!frame->opaque_ref); + frame->opaque_ref = av_buffer_allocz(sizeof(*fd)); + if (!frame->opaque_ref) { + av_frame_unref(frame); + return AVERROR(ENOMEM); + } + fd = (FrameData*)frame->opaque_ref->data; + fd->pts = frame->pts; + fd->tb = avctx->pkt_timebase; + fd->idx = avctx->frame_num - 1; + } + + frame->time_base = avctx->pkt_timebase; + + *got_frame = 1; + } + + return 0; +} + +static int send_frame_to_filters(InputStream *ist, AVFrame *decoded_frame) +{ + int i, ret; + + av_assert1(ist->nb_filters > 0); /* ensure ret is initialized */ + for (i = 0; i < ist->nb_filters; i++) { + ret = ifilter_send_frame(ist->filters[i], decoded_frame, i < ist->nb_filters - 1); + if (ret == AVERROR_EOF) + ret = 0; /* ignore */ + if (ret < 0) { + av_log(NULL, AV_LOG_ERROR, + "Failed to inject frame into filter network: %s\n", av_err2str(ret)); + break; + } + } + return ret; +} + +static AVRational audio_samplerate_update(InputStream *ist, const AVFrame *frame) +{ + const int prev = ist->last_frame_tb.den; + const int sr = frame->sample_rate; + + AVRational tb_new; + int64_t gcd; + + if (frame->sample_rate == ist->last_frame_sample_rate) + goto finish; + + gcd = av_gcd(prev, sr); + + if (prev / gcd >= INT_MAX / sr) { + av_log(ist, AV_LOG_WARNING, + "Audio timestamps cannot be represented exactly after " + "sample rate change: %d -> %d\n", prev, sr); + + // LCM of 192000, 44100, allows to represent all common samplerates + tb_new = (AVRational){ 1, 28224000 }; + } else + tb_new = (AVRational){ 1, prev / gcd * sr }; + + // keep the frame timebase if it is strictly better than + // the samplerate-defined one + if (frame->time_base.num == 1 && frame->time_base.den > tb_new.den && + !(frame->time_base.den % tb_new.den)) + tb_new = frame->time_base; + + if (ist->last_frame_pts != AV_NOPTS_VALUE) + ist->last_frame_pts = av_rescale_q(ist->last_frame_pts, + ist->last_frame_tb, tb_new); + ist->last_frame_duration_est = av_rescale_q(ist->last_frame_duration_est, + ist->last_frame_tb, tb_new); + + ist->last_frame_tb = tb_new; + ist->last_frame_sample_rate = frame->sample_rate; + +finish: + return ist->last_frame_tb; +} + +static void audio_ts_process(InputStream *ist, AVFrame *frame) +{ + AVRational tb_filter = (AVRational){1, frame->sample_rate}; + AVRational tb; + int64_t pts_pred; + + // on samplerate change, choose a new internal timebase for timestamp + // generation that can represent timestamps from all the samplerates + // seen so far + tb = audio_samplerate_update(ist, frame); + pts_pred = ist->last_frame_pts == AV_NOPTS_VALUE ? 0 : + ist->last_frame_pts + ist->last_frame_duration_est; + + if (frame->pts == AV_NOPTS_VALUE) { + frame->pts = pts_pred; + frame->time_base = tb; + } else if (ist->last_frame_pts != AV_NOPTS_VALUE && + frame->pts > av_rescale_q_rnd(pts_pred, tb, frame->time_base, + AV_ROUND_UP)) { + // there was a gap in timestamps, reset conversion state + ist->filter_in_rescale_delta_last = AV_NOPTS_VALUE; + } + + frame->pts = av_rescale_delta(frame->time_base, frame->pts, + tb, frame->nb_samples, + &ist->filter_in_rescale_delta_last, tb); + + ist->last_frame_pts = frame->pts; + ist->last_frame_duration_est = av_rescale_q(frame->nb_samples, + tb_filter, tb); + + // finally convert to filtering timebase + frame->pts = av_rescale_q(frame->pts, tb, tb_filter); + frame->duration = frame->nb_samples; + frame->time_base = tb_filter; +} + +static int decode_audio(InputStream *ist, const AVPacket *pkt, int *got_output, + int *decode_failed) +{ + AVFrame *decoded_frame = ist->decoded_frame; + AVCodecContext *avctx = ist->dec_ctx; + int ret, err = 0; + + update_benchmark(NULL); + ret = decode(ist, avctx, decoded_frame, got_output, pkt); + update_benchmark("decode_audio %d.%d", ist->file_index, ist->st->index); + if (ret < 0) + *decode_failed = 1; + + if (ret != AVERROR_EOF) + check_decode_result(ist, got_output, ret); + + if (!*got_output || ret < 0) + return ret; + + ist->samples_decoded += decoded_frame->nb_samples; + ist->frames_decoded++; + + audio_ts_process(ist, decoded_frame); + + ist->nb_samples = decoded_frame->nb_samples; + err = send_frame_to_filters(ist, decoded_frame); + + av_frame_unref(decoded_frame); + return err < 0 ? err : ret; +} + +static int64_t video_duration_estimate(const InputStream *ist, const AVFrame *frame) +{ + const InputFile *ifile = input_files[ist->file_index]; + int64_t codec_duration = 0; + + // XXX lavf currently makes up frame durations when they are not provided by + // the container. As there is no way to reliably distinguish real container + // durations from the fake made-up ones, we use heuristics based on whether + // the container has timestamps. Eventually lavf should stop making up + // durations, then this should be simplified. + + // prefer frame duration for containers with timestamps + if (frame->duration > 0 && (!ifile->format_nots || ist->framerate.num)) + return frame->duration; + + if (ist->dec_ctx->framerate.den && ist->dec_ctx->framerate.num) { + int fields = frame->repeat_pict + 2; + AVRational field_rate = av_mul_q(ist->dec_ctx->framerate, + (AVRational){ 2, 1 }); + codec_duration = av_rescale_q(fields, av_inv_q(field_rate), + frame->time_base); + } + + // prefer codec-layer duration for containers without timestamps + if (codec_duration > 0 && ifile->format_nots) + return codec_duration; + + // when timestamps are available, repeat last frame's actual duration + // (i.e. pts difference between this and last frame) + if (frame->pts != AV_NOPTS_VALUE && ist->last_frame_pts != AV_NOPTS_VALUE && + frame->pts > ist->last_frame_pts) + return frame->pts - ist->last_frame_pts; + + // try frame/codec duration + if (frame->duration > 0) + return frame->duration; + if (codec_duration > 0) + return codec_duration; + + // try average framerate + if (ist->st->avg_frame_rate.num && ist->st->avg_frame_rate.den) { + int64_t d = av_rescale_q(1, av_inv_q(ist->st->avg_frame_rate), + frame->time_base); + if (d > 0) + return d; + } + + // last resort is last frame's estimated duration, and 1 + return FFMAX(ist->last_frame_duration_est, 1); +} + +static int decode_video(InputStream *ist, const AVPacket *pkt, int *got_output, + int eof, int *decode_failed) +{ + AVFrame *frame = ist->decoded_frame; + int ret = 0, err = 0; + + // With fate-indeo3-2, we're getting 0-sized packets before EOF for some + // reason. This seems like a semi-critical bug. Don't trigger EOF, and + // skip the packet. + if (!eof && pkt && pkt->size == 0) + return 0; + + update_benchmark(NULL); + ret = decode(ist, ist->dec_ctx, frame, got_output, pkt); + update_benchmark("decode_video %d.%d", ist->file_index, ist->st->index); + if (ret < 0) + *decode_failed = 1; + + // The following line may be required in some cases where there is no parser + // or the parser does not has_b_frames correctly + if (ist->par->video_delay < ist->dec_ctx->has_b_frames) { + if (ist->dec_ctx->codec_id == AV_CODEC_ID_H264) { + ist->par->video_delay = ist->dec_ctx->has_b_frames; + } else + av_log(ist->dec_ctx, AV_LOG_WARNING, + "video_delay is larger in decoder than demuxer %d > %d.\n" + "If you want to help, upload a sample " + "of this file to https://streams.videolan.org/upload/ " + "and contact the ffmpeg-devel mailing list. (ffmpeg-devel@ffmpeg.org)\n", + ist->dec_ctx->has_b_frames, + ist->par->video_delay); + } + + if (ret != AVERROR_EOF) + check_decode_result(ist, got_output, ret); + + if (*got_output && ret >= 0) { + if (ist->dec_ctx->width != frame->width || + ist->dec_ctx->height != frame->height || + ist->dec_ctx->pix_fmt != frame->format) { + av_log(NULL, AV_LOG_DEBUG, "Frame parameters mismatch context %d,%d,%d != %d,%d,%d\n", + frame->width, + frame->height, + frame->format, + ist->dec_ctx->width, + ist->dec_ctx->height, + ist->dec_ctx->pix_fmt); + } + } + + if (!*got_output || ret < 0) + return ret; + + if(ist->top_field_first>=0) + frame->flags |= AV_FRAME_FLAG_TOP_FIELD_FIRST; + + ist->frames_decoded++; + + if (ist->hwaccel_retrieve_data && frame->format == ist->hwaccel_pix_fmt) { + err = ist->hwaccel_retrieve_data(ist->dec_ctx, frame); + if (err < 0) + goto fail; + } + + frame->pts = frame->best_effort_timestamp; + + // forced fixed framerate + if (ist->framerate.num) { + frame->pts = AV_NOPTS_VALUE; + frame->duration = 1; + frame->time_base = av_inv_q(ist->framerate); + } + + // no timestamp available - extrapolate from previous frame duration + if (frame->pts == AV_NOPTS_VALUE) + frame->pts = ist->last_frame_pts == AV_NOPTS_VALUE ? 0 : + ist->last_frame_pts + ist->last_frame_duration_est; + + // update timestamp history + ist->last_frame_duration_est = video_duration_estimate(ist, frame); + ist->last_frame_pts = frame->pts; + ist->last_frame_tb = frame->time_base; + + if (debug_ts) { + av_log(ist, AV_LOG_INFO, + "decoder -> pts:%s pts_time:%s " + "pkt_dts:%s pkt_dts_time:%s " + "duration:%s duration_time:%s " + "keyframe:%d frame_type:%d time_base:%d/%d\n", + av_ts2str(frame->pts), + av_ts2timestr(frame->pts, &frame->time_base), + av_ts2str(frame->pkt_dts), + av_ts2timestr(frame->pkt_dts, &frame->time_base), + av_ts2str(frame->duration), + av_ts2timestr(frame->duration, &frame->time_base), + !!(frame->flags & AV_FRAME_FLAG_KEY), frame->pict_type, + frame->time_base.num, frame->time_base.den); + } + + if (ist->st->sample_aspect_ratio.num) + frame->sample_aspect_ratio = ist->st->sample_aspect_ratio; + + err = send_frame_to_filters(ist, frame); + +fail: + av_frame_unref(frame); + return err < 0 ? err : ret; +} + +static void sub2video_flush(InputStream *ist) +{ + int i; + int ret; + + if (ist->sub2video.end_pts < INT64_MAX) + sub2video_update(ist, INT64_MAX, NULL); + for (i = 0; i < ist->nb_filters; i++) { + ret = av_buffersrc_add_frame(ist->filters[i]->filter, NULL); + if (ret != AVERROR_EOF && ret < 0) + av_log(NULL, AV_LOG_WARNING, "Flush the frame error.\n"); + } +} + +int process_subtitle(InputStream *ist, AVSubtitle *subtitle, int *got_output) +{ + int ret = 0; + int free_sub = 1; + + if (ist->fix_sub_duration) { + int end = 1; + if (ist->prev_sub.got_output) { + end = av_rescale(subtitle->pts - ist->prev_sub.subtitle.pts, + 1000, AV_TIME_BASE); + if (end < ist->prev_sub.subtitle.end_display_time) { + av_log(NULL, AV_LOG_DEBUG, + "Subtitle duration reduced from %"PRId32" to %d%s\n", + ist->prev_sub.subtitle.end_display_time, end, + end <= 0 ? ", dropping it" : ""); + ist->prev_sub.subtitle.end_display_time = end; + } + } + FFSWAP(int, *got_output, ist->prev_sub.got_output); + FFSWAP(int, ret, ist->prev_sub.ret); + FFSWAP(AVSubtitle, *subtitle, ist->prev_sub.subtitle); + if (end <= 0) + goto out; + } + + if (!*got_output) + return ret; + + if (ist->sub2video.frame) { + sub2video_update(ist, INT64_MIN, subtitle); + } else if (ist->nb_filters) { + if (!ist->sub2video.sub_queue) + ist->sub2video.sub_queue = av_fifo_alloc2(8, sizeof(AVSubtitle), AV_FIFO_FLAG_AUTO_GROW); + if (!ist->sub2video.sub_queue) + report_and_exit(AVERROR(ENOMEM)); + + ret = av_fifo_write(ist->sub2video.sub_queue, subtitle, 1); + if (ret < 0) + exit_program(1); + free_sub = 0; + } + + if (!subtitle->num_rects) + goto out; + + for (int oidx = 0; oidx < ist->nb_outputs; oidx++) { + OutputStream *ost = ist->outputs[oidx]; + if (!ost->enc || ost->type != AVMEDIA_TYPE_SUBTITLE) + continue; + + enc_subtitle(output_files[ost->file_index], ost, subtitle); + } + +out: + if (free_sub) + avsubtitle_free(subtitle); + return ret; +} + +static int transcode_subtitles(InputStream *ist, const AVPacket *pkt, + int *got_output, int *decode_failed) +{ + AVSubtitle subtitle; + int ret = avcodec_decode_subtitle2(ist->dec_ctx, + &subtitle, got_output, pkt); + + check_decode_result(ist, got_output, ret); + + if (ret < 0 || !*got_output) { + *decode_failed = 1; + if (!pkt->size) + sub2video_flush(ist); + return ret; + } + + ist->frames_decoded++; + + return process_subtitle(ist, &subtitle, got_output); +} + +static int send_filter_eof(InputStream *ist) +{ + int i, ret; + + for (i = 0; i < ist->nb_filters; i++) { + int64_t end_pts = ist->last_frame_pts == AV_NOPTS_VALUE ? AV_NOPTS_VALUE : + ist->last_frame_pts + ist->last_frame_duration_est; + ret = ifilter_send_eof(ist->filters[i], end_pts, ist->last_frame_tb); + if (ret < 0) + return ret; + } + return 0; +} + +int dec_packet(InputStream *ist, const AVPacket *pkt, int no_eof) +{ + AVPacket *avpkt = ist->pkt; + int ret, repeating = 0; + + if (pkt) { + av_packet_unref(avpkt); + ret = av_packet_ref(avpkt, pkt); + if (ret < 0) + return ret; + } + + // while we have more to decode or while the decoder did output something on EOF + while (1) { + int got_output = 0; + int decode_failed = 0; + + switch (ist->par->codec_type) { + case AVMEDIA_TYPE_AUDIO: + ret = decode_audio (ist, repeating ? NULL : avpkt, &got_output, + &decode_failed); + av_packet_unref(avpkt); + break; + case AVMEDIA_TYPE_VIDEO: + ret = decode_video (ist, repeating ? NULL : avpkt, &got_output, !pkt, + &decode_failed); + + av_packet_unref(avpkt); + break; + case AVMEDIA_TYPE_SUBTITLE: + if (repeating) + break; + ret = transcode_subtitles(ist, avpkt, &got_output, &decode_failed); + if (!pkt && ret >= 0) + ret = AVERROR_EOF; + av_packet_unref(avpkt); + break; + default: av_assert0(0); + } + + if (ret == AVERROR_EOF) { + /* after flushing, send an EOF on all the filter inputs attached to the stream */ + /* except when looping we need to flush but not to send an EOF */ + if (!no_eof) { + ret = send_filter_eof(ist); + if (ret < 0) { + av_log(NULL, AV_LOG_FATAL, "Error marking filters as finished\n"); + exit_program(1); + } + } + + return AVERROR_EOF; + } + + if (ret < 0) { + if (decode_failed) { + av_log(NULL, AV_LOG_ERROR, "Error while decoding stream #%d:%d: %s\n", + ist->file_index, ist->st->index, av_err2str(ret)); + } else { + av_log(NULL, AV_LOG_FATAL, "Error while processing the decoded " + "data for stream #%d:%d\n", ist->file_index, ist->st->index); + } + if (!decode_failed || exit_on_error) + exit_program(1); + return ret; + } + + if (!got_output) + return 0; + + repeating = 1; + } +} + static enum AVPixelFormat get_format(AVCodecContext *s, const enum AVPixelFormat *pix_fmts) { InputStream *ist = s->opaque; From 172f901e3555f222852723a42a7aa93774069a48 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Wed, 17 May 2023 09:44:37 +0200 Subject: [PATCH 1146/2172] fftools/ffmpeg_dec: deobfuscate subtitle decoding It is currently handled in the same loop as audio and video, but this obscures the actual flow, because only one iteration is ever performed for subtitles. Also, avoid a pointless packet reference. --- fftools/ffmpeg_dec.c | 34 ++++++++++++++++++---------------- 1 file changed, 18 insertions(+), 16 deletions(-) diff --git a/fftools/ffmpeg_dec.c b/fftools/ffmpeg_dec.c index 30fe75d8a69..646b587f9e5 100644 --- a/fftools/ffmpeg_dec.c +++ b/fftools/ffmpeg_dec.c @@ -456,25 +456,31 @@ int process_subtitle(InputStream *ist, AVSubtitle *subtitle, int *got_output) return ret; } -static int transcode_subtitles(InputStream *ist, const AVPacket *pkt, - int *got_output, int *decode_failed) +static int transcode_subtitles(InputStream *ist, const AVPacket *pkt) { AVSubtitle subtitle; + int got_output; int ret = avcodec_decode_subtitle2(ist->dec_ctx, - &subtitle, got_output, pkt); + &subtitle, &got_output, pkt); - check_decode_result(ist, got_output, ret); + if (ret < 0) { + av_log(ist, AV_LOG_ERROR, "Error decoding subtitles: %s\n", + av_err2str(ret)); + if (exit_on_error) + exit_program(1); + } - if (ret < 0 || !*got_output) { - *decode_failed = 1; + check_decode_result(ist, &got_output, ret); + + if (ret < 0 || !got_output) { if (!pkt->size) sub2video_flush(ist); - return ret; + return ret < 0 ? ret : AVERROR_EOF; } ist->frames_decoded++; - return process_subtitle(ist, &subtitle, got_output); + return process_subtitle(ist, &subtitle, &got_output); } static int send_filter_eof(InputStream *ist) @@ -493,9 +499,13 @@ static int send_filter_eof(InputStream *ist) int dec_packet(InputStream *ist, const AVPacket *pkt, int no_eof) { + AVCodecContext *dec = ist->dec_ctx; AVPacket *avpkt = ist->pkt; int ret, repeating = 0; + if (dec->codec_type == AVMEDIA_TYPE_SUBTITLE) + return transcode_subtitles(ist, pkt ? pkt : ist->pkt); + if (pkt) { av_packet_unref(avpkt); ret = av_packet_ref(avpkt, pkt); @@ -520,14 +530,6 @@ int dec_packet(InputStream *ist, const AVPacket *pkt, int no_eof) av_packet_unref(avpkt); break; - case AVMEDIA_TYPE_SUBTITLE: - if (repeating) - break; - ret = transcode_subtitles(ist, avpkt, &got_output, &decode_failed); - if (!pkt && ret >= 0) - ret = AVERROR_EOF; - av_packet_unref(avpkt); - break; default: av_assert0(0); } From 748f2999eee82fd507da327fa57e47730f5effc1 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Wed, 17 May 2023 11:34:55 +0200 Subject: [PATCH 1147/2172] fftools/ffmpeg_dec: restructure audio/video decoding loop It currently emulates the long-removed avcodec_decode_audio4/avcodec_decode_video2 APIs, which obfuscates the actual decoding flow. Restructure the decoding calls so that they naturally follow the new avcodec_send_packet()/avcodec_receive_frame() design. This is not only significantly easier to read, but also shorter. --- fftools/ffmpeg_dec.c | 191 +++++++++++++++---------------------------- 1 file changed, 65 insertions(+), 126 deletions(-) diff --git a/fftools/ffmpeg_dec.c b/fftools/ffmpeg_dec.c index 646b587f9e5..ab8c6205c6c 100644 --- a/fftools/ffmpeg_dec.c +++ b/fftools/ffmpeg_dec.c @@ -31,7 +31,7 @@ #include "ffmpeg.h" -static void check_decode_result(InputStream *ist, int *got_output, int ret) +static void check_decode_result(InputStream *ist, int got_output, int ret) { if (ret < 0) ist->decode_errors++; @@ -39,7 +39,7 @@ static void check_decode_result(InputStream *ist, int *got_output, int ret) if (ret < 0 && exit_on_error) exit_program(1); - if (*got_output && ist->dec_ctx->codec_type != AVMEDIA_TYPE_SUBTITLE) { + if (got_output && ist->dec_ctx->codec_type != AVMEDIA_TYPE_SUBTITLE) { if (ist->decoded_frame->decode_error_flags || (ist->decoded_frame->flags & AV_FRAME_FLAG_CORRUPT)) { av_log(ist, exit_on_error ? AV_LOG_FATAL : AV_LOG_WARNING, "corrupt decoded frame\n"); @@ -49,52 +49,6 @@ static void check_decode_result(InputStream *ist, int *got_output, int ret) } } -// This does not quite work like avcodec_decode_audio4/avcodec_decode_video2. -// There is the following difference: if you got a frame, you must call -// it again with pkt=NULL. pkt==NULL is treated differently from pkt->size==0 -// (pkt==NULL means get more output, pkt->size==0 is a flush/drain packet) -static int decode(InputStream *ist, AVCodecContext *avctx, - AVFrame *frame, int *got_frame, const AVPacket *pkt) -{ - int ret; - - *got_frame = 0; - - if (pkt) { - ret = avcodec_send_packet(avctx, pkt); - // In particular, we don't expect AVERROR(EAGAIN), because we read all - // decoded frames with avcodec_receive_frame() until done. - if (ret < 0 && ret != AVERROR_EOF) - return ret; - } - - ret = avcodec_receive_frame(avctx, frame); - if (ret < 0 && ret != AVERROR(EAGAIN)) - return ret; - if (ret >= 0) { - if (ist->want_frame_data) { - FrameData *fd; - - av_assert0(!frame->opaque_ref); - frame->opaque_ref = av_buffer_allocz(sizeof(*fd)); - if (!frame->opaque_ref) { - av_frame_unref(frame); - return AVERROR(ENOMEM); - } - fd = (FrameData*)frame->opaque_ref->data; - fd->pts = frame->pts; - fd->tb = avctx->pkt_timebase; - fd->idx = avctx->frame_num - 1; - } - - frame->time_base = avctx->pkt_timebase; - - *got_frame = 1; - } - - return 0; -} - static int send_frame_to_filters(InputStream *ist, AVFrame *decoded_frame) { int i, ret; @@ -192,25 +146,10 @@ static void audio_ts_process(InputStream *ist, AVFrame *frame) frame->time_base = tb_filter; } -static int decode_audio(InputStream *ist, const AVPacket *pkt, int *got_output, - int *decode_failed) +static int decode_audio(InputStream *ist, AVFrame *decoded_frame) { - AVFrame *decoded_frame = ist->decoded_frame; - AVCodecContext *avctx = ist->dec_ctx; int ret, err = 0; - update_benchmark(NULL); - ret = decode(ist, avctx, decoded_frame, got_output, pkt); - update_benchmark("decode_audio %d.%d", ist->file_index, ist->st->index); - if (ret < 0) - *decode_failed = 1; - - if (ret != AVERROR_EOF) - check_decode_result(ist, got_output, ret); - - if (!*got_output || ret < 0) - return ret; - ist->samples_decoded += decoded_frame->nb_samples; ist->frames_decoded++; @@ -274,24 +213,10 @@ static int64_t video_duration_estimate(const InputStream *ist, const AVFrame *fr return FFMAX(ist->last_frame_duration_est, 1); } -static int decode_video(InputStream *ist, const AVPacket *pkt, int *got_output, - int eof, int *decode_failed) +static int decode_video(InputStream *ist, AVFrame *frame) { - AVFrame *frame = ist->decoded_frame; int ret = 0, err = 0; - // With fate-indeo3-2, we're getting 0-sized packets before EOF for some - // reason. This seems like a semi-critical bug. Don't trigger EOF, and - // skip the packet. - if (!eof && pkt && pkt->size == 0) - return 0; - - update_benchmark(NULL); - ret = decode(ist, ist->dec_ctx, frame, got_output, pkt); - update_benchmark("decode_video %d.%d", ist->file_index, ist->st->index); - if (ret < 0) - *decode_failed = 1; - // The following line may be required in some cases where there is no parser // or the parser does not has_b_frames correctly if (ist->par->video_delay < ist->dec_ctx->has_b_frames) { @@ -307,10 +232,6 @@ static int decode_video(InputStream *ist, const AVPacket *pkt, int *got_output, ist->par->video_delay); } - if (ret != AVERROR_EOF) - check_decode_result(ist, got_output, ret); - - if (*got_output && ret >= 0) { if (ist->dec_ctx->width != frame->width || ist->dec_ctx->height != frame->height || ist->dec_ctx->pix_fmt != frame->format) { @@ -322,10 +243,6 @@ static int decode_video(InputStream *ist, const AVPacket *pkt, int *got_output, ist->dec_ctx->height, ist->dec_ctx->pix_fmt); } - } - - if (!*got_output || ret < 0) - return ret; if(ist->top_field_first>=0) frame->flags |= AV_FRAME_FLAG_TOP_FIELD_FIRST; @@ -470,7 +387,7 @@ static int transcode_subtitles(InputStream *ist, const AVPacket *pkt) exit_program(1); } - check_decode_result(ist, &got_output, ret); + check_decode_result(ist, got_output, ret); if (ret < 0 || !got_output) { if (!pkt->size) @@ -500,40 +417,48 @@ static int send_filter_eof(InputStream *ist) int dec_packet(InputStream *ist, const AVPacket *pkt, int no_eof) { AVCodecContext *dec = ist->dec_ctx; - AVPacket *avpkt = ist->pkt; - int ret, repeating = 0; + const char *type_desc = av_get_media_type_string(dec->codec_type); + int ret; if (dec->codec_type == AVMEDIA_TYPE_SUBTITLE) return transcode_subtitles(ist, pkt ? pkt : ist->pkt); - if (pkt) { - av_packet_unref(avpkt); - ret = av_packet_ref(avpkt, pkt); - if (ret < 0) - return ret; + // With fate-indeo3-2, we're getting 0-sized packets before EOF for some + // reason. This seems like a semi-critical bug. Don't trigger EOF, and + // skip the packet. + if (pkt && pkt->size == 0) + return 0; + + ret = avcodec_send_packet(dec, pkt); + if (ret < 0 && !(ret == AVERROR_EOF && !pkt)) { + // In particular, we don't expect AVERROR(EAGAIN), because we read all + // decoded frames with avcodec_receive_frame() until done. + av_log(ist, AV_LOG_ERROR, "Error submitting %s to decoder: %s\n", + pkt ? "packet" : "EOF", av_err2str(ret)); + if (exit_on_error) + exit_program(1); + + if (ret != AVERROR_EOF) + ist->decode_errors++; + + return ret; } - // while we have more to decode or while the decoder did output something on EOF while (1) { - int got_output = 0; - int decode_failed = 0; - - switch (ist->par->codec_type) { - case AVMEDIA_TYPE_AUDIO: - ret = decode_audio (ist, repeating ? NULL : avpkt, &got_output, - &decode_failed); - av_packet_unref(avpkt); - break; - case AVMEDIA_TYPE_VIDEO: - ret = decode_video (ist, repeating ? NULL : avpkt, &got_output, !pkt, - &decode_failed); + AVFrame *frame = ist->decoded_frame; - av_packet_unref(avpkt); - break; - default: av_assert0(0); - } + update_benchmark(NULL); + ret = avcodec_receive_frame(dec, frame); + update_benchmark("decode_%s %d.%d", type_desc, + ist->file_index, ist->st->index); + + if (ret != AVERROR_EOF && ret != AVERROR(EAGAIN)) + check_decode_result(ist, ret >= 0, ret); - if (ret == AVERROR_EOF) { + if (ret == AVERROR(EAGAIN)) { + av_assert0(pkt); // should never happen during flushing + return 0; + } else if (ret == AVERROR_EOF) { /* after flushing, send an EOF on all the filter inputs attached to the stream */ /* except when looping we need to flush but not to send an EOF */ if (!no_eof) { @@ -545,25 +470,39 @@ int dec_packet(InputStream *ist, const AVPacket *pkt, int no_eof) } return AVERROR_EOF; + } else if (ret < 0) { + av_log(ist, AV_LOG_ERROR, "Decoding error: %s\n", av_err2str(ret)); + if (exit_on_error) + exit_program(1); + return ret; } - if (ret < 0) { - if (decode_failed) { - av_log(NULL, AV_LOG_ERROR, "Error while decoding stream #%d:%d: %s\n", - ist->file_index, ist->st->index, av_err2str(ret)); - } else { - av_log(NULL, AV_LOG_FATAL, "Error while processing the decoded " - "data for stream #%d:%d\n", ist->file_index, ist->st->index); + if (ist->want_frame_data) { + FrameData *fd; + + av_assert0(!frame->opaque_ref); + frame->opaque_ref = av_buffer_allocz(sizeof(*fd)); + if (!frame->opaque_ref) { + av_frame_unref(frame); + report_and_exit(AVERROR(ENOMEM)); } - if (!decode_failed || exit_on_error) - exit_program(1); - return ret; + fd = (FrameData*)frame->opaque_ref->data; + fd->pts = frame->pts; + fd->tb = dec->pkt_timebase; + fd->idx = dec->frame_num - 1; } - if (!got_output) - return 0; + frame->time_base = dec->pkt_timebase; + + ret = dec->codec_type == AVMEDIA_TYPE_AUDIO ? + decode_audio(ist, frame) : + decode_video(ist, frame); - repeating = 1; + if (ret < 0) { + av_log(NULL, AV_LOG_FATAL, "Error while processing the decoded " + "data for stream #%d:%d\n", ist->file_index, ist->st->index); + exit_program(1); + } } } From c08717adae6f9b2cf141e5c3811ab86909cc65e5 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Wed, 17 May 2023 11:46:15 +0200 Subject: [PATCH 1148/2172] fftools/ffmpeg: reindent after previous commit --- fftools/ffmpeg_dec.c | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/fftools/ffmpeg_dec.c b/fftools/ffmpeg_dec.c index ab8c6205c6c..d487678b72a 100644 --- a/fftools/ffmpeg_dec.c +++ b/fftools/ffmpeg_dec.c @@ -232,17 +232,17 @@ static int decode_video(InputStream *ist, AVFrame *frame) ist->par->video_delay); } - if (ist->dec_ctx->width != frame->width || - ist->dec_ctx->height != frame->height || - ist->dec_ctx->pix_fmt != frame->format) { - av_log(NULL, AV_LOG_DEBUG, "Frame parameters mismatch context %d,%d,%d != %d,%d,%d\n", - frame->width, - frame->height, - frame->format, - ist->dec_ctx->width, - ist->dec_ctx->height, - ist->dec_ctx->pix_fmt); - } + if (ist->dec_ctx->width != frame->width || + ist->dec_ctx->height != frame->height || + ist->dec_ctx->pix_fmt != frame->format) { + av_log(NULL, AV_LOG_DEBUG, "Frame parameters mismatch context %d,%d,%d != %d,%d,%d\n", + frame->width, + frame->height, + frame->format, + ist->dec_ctx->width, + ist->dec_ctx->height, + ist->dec_ctx->pix_fmt); + } if(ist->top_field_first>=0) frame->flags |= AV_FRAME_FLAG_TOP_FIELD_FIRST; From ab3493006f04fbd87a2672986003f5eab354b630 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Wed, 17 May 2023 11:49:01 +0200 Subject: [PATCH 1149/2172] fftools/ffmpeg_dec: merge check_decode_result() into its callers Not only is this easier to read, this also makes the code shorter. --- fftools/ffmpeg_dec.c | 32 +++++++++----------------------- 1 file changed, 9 insertions(+), 23 deletions(-) diff --git a/fftools/ffmpeg_dec.c b/fftools/ffmpeg_dec.c index d487678b72a..2609806a4a2 100644 --- a/fftools/ffmpeg_dec.c +++ b/fftools/ffmpeg_dec.c @@ -31,24 +31,6 @@ #include "ffmpeg.h" -static void check_decode_result(InputStream *ist, int got_output, int ret) -{ - if (ret < 0) - ist->decode_errors++; - - if (ret < 0 && exit_on_error) - exit_program(1); - - if (got_output && ist->dec_ctx->codec_type != AVMEDIA_TYPE_SUBTITLE) { - if (ist->decoded_frame->decode_error_flags || (ist->decoded_frame->flags & AV_FRAME_FLAG_CORRUPT)) { - av_log(ist, exit_on_error ? AV_LOG_FATAL : AV_LOG_WARNING, - "corrupt decoded frame\n"); - if (exit_on_error) - exit_program(1); - } - } -} - static int send_frame_to_filters(InputStream *ist, AVFrame *decoded_frame) { int i, ret; @@ -385,10 +367,9 @@ static int transcode_subtitles(InputStream *ist, const AVPacket *pkt) av_err2str(ret)); if (exit_on_error) exit_program(1); + ist->decode_errors++; } - check_decode_result(ist, got_output, ret); - if (ret < 0 || !got_output) { if (!pkt->size) sub2video_flush(ist); @@ -452,9 +433,6 @@ int dec_packet(InputStream *ist, const AVPacket *pkt, int no_eof) update_benchmark("decode_%s %d.%d", type_desc, ist->file_index, ist->st->index); - if (ret != AVERROR_EOF && ret != AVERROR(EAGAIN)) - check_decode_result(ist, ret >= 0, ret); - if (ret == AVERROR(EAGAIN)) { av_assert0(pkt); // should never happen during flushing return 0; @@ -474,9 +452,17 @@ int dec_packet(InputStream *ist, const AVPacket *pkt, int no_eof) av_log(ist, AV_LOG_ERROR, "Decoding error: %s\n", av_err2str(ret)); if (exit_on_error) exit_program(1); + ist->decode_errors++; return ret; } + if (frame->decode_error_flags || (frame->flags & AV_FRAME_FLAG_CORRUPT)) { + av_log(ist, exit_on_error ? AV_LOG_FATAL : AV_LOG_WARNING, + "corrupt decoded frame\n"); + if (exit_on_error) + exit_program(1); + } + if (ist->want_frame_data) { FrameData *fd; From 959a5decf28fd3c1a24e811bf4b6c7ebe710f35d Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Wed, 17 May 2023 11:55:04 +0200 Subject: [PATCH 1150/2172] fftools/ffmpeg_dec: deduplicate code in decode_audio/video() --- fftools/ffmpeg_dec.c | 28 +++++++++++----------------- 1 file changed, 11 insertions(+), 17 deletions(-) diff --git a/fftools/ffmpeg_dec.c b/fftools/ffmpeg_dec.c index 2609806a4a2..072c8f3a322 100644 --- a/fftools/ffmpeg_dec.c +++ b/fftools/ffmpeg_dec.c @@ -130,18 +130,13 @@ static void audio_ts_process(InputStream *ist, AVFrame *frame) static int decode_audio(InputStream *ist, AVFrame *decoded_frame) { - int ret, err = 0; - ist->samples_decoded += decoded_frame->nb_samples; - ist->frames_decoded++; audio_ts_process(ist, decoded_frame); ist->nb_samples = decoded_frame->nb_samples; - err = send_frame_to_filters(ist, decoded_frame); - av_frame_unref(decoded_frame); - return err < 0 ? err : ret; + return 0; } static int64_t video_duration_estimate(const InputStream *ist, const AVFrame *frame) @@ -197,8 +192,6 @@ static int64_t video_duration_estimate(const InputStream *ist, const AVFrame *fr static int decode_video(InputStream *ist, AVFrame *frame) { - int ret = 0, err = 0; - // The following line may be required in some cases where there is no parser // or the parser does not has_b_frames correctly if (ist->par->video_delay < ist->dec_ctx->has_b_frames) { @@ -229,12 +222,10 @@ static int decode_video(InputStream *ist, AVFrame *frame) if(ist->top_field_first>=0) frame->flags |= AV_FRAME_FLAG_TOP_FIELD_FIRST; - ist->frames_decoded++; - if (ist->hwaccel_retrieve_data && frame->format == ist->hwaccel_pix_fmt) { - err = ist->hwaccel_retrieve_data(ist->dec_ctx, frame); + int err = ist->hwaccel_retrieve_data(ist->dec_ctx, frame); if (err < 0) - goto fail; + return err; } frame->pts = frame->best_effort_timestamp; @@ -275,11 +266,7 @@ static int decode_video(InputStream *ist, AVFrame *frame) if (ist->st->sample_aspect_ratio.num) frame->sample_aspect_ratio = ist->st->sample_aspect_ratio; - err = send_frame_to_filters(ist, frame); - -fail: - av_frame_unref(frame); - return err < 0 ? err : ret; + return 0; } static void sub2video_flush(InputStream *ist) @@ -489,6 +476,13 @@ int dec_packet(InputStream *ist, const AVPacket *pkt, int no_eof) "data for stream #%d:%d\n", ist->file_index, ist->st->index); exit_program(1); } + + ist->frames_decoded++; + + ret = send_frame_to_filters(ist, frame); + av_frame_unref(frame); + if (ret < 0) + exit_program(1); } } From 909f5dfae15effe2e4f2fd7e0d1b490c224fde20 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Wed, 17 May 2023 11:58:50 +0200 Subject: [PATCH 1151/2172] fftools/ffmpeg_dec: inline decode_audio() into dec_packet() The former function is now trivial - it has 3 lines and cannot fail. --- fftools/ffmpeg_dec.c | 29 +++++++++++------------------ 1 file changed, 11 insertions(+), 18 deletions(-) diff --git a/fftools/ffmpeg_dec.c b/fftools/ffmpeg_dec.c index 072c8f3a322..acb56e4118b 100644 --- a/fftools/ffmpeg_dec.c +++ b/fftools/ffmpeg_dec.c @@ -128,17 +128,6 @@ static void audio_ts_process(InputStream *ist, AVFrame *frame) frame->time_base = tb_filter; } -static int decode_audio(InputStream *ist, AVFrame *decoded_frame) -{ - ist->samples_decoded += decoded_frame->nb_samples; - - audio_ts_process(ist, decoded_frame); - - ist->nb_samples = decoded_frame->nb_samples; - - return 0; -} - static int64_t video_duration_estimate(const InputStream *ist, const AVFrame *frame) { const InputFile *ifile = input_files[ist->file_index]; @@ -467,14 +456,18 @@ int dec_packet(InputStream *ist, const AVPacket *pkt, int no_eof) frame->time_base = dec->pkt_timebase; - ret = dec->codec_type == AVMEDIA_TYPE_AUDIO ? - decode_audio(ist, frame) : - decode_video(ist, frame); + if (dec->codec_type == AVMEDIA_TYPE_AUDIO) { + ist->samples_decoded += frame->nb_samples; + ist->nb_samples = frame->nb_samples; - if (ret < 0) { - av_log(NULL, AV_LOG_FATAL, "Error while processing the decoded " - "data for stream #%d:%d\n", ist->file_index, ist->st->index); - exit_program(1); + audio_ts_process(ist, frame); + } else { + ret = decode_video(ist, frame); + if (ret < 0) { + av_log(NULL, AV_LOG_FATAL, "Error while processing the decoded " + "data for stream #%d:%d\n", ist->file_index, ist->st->index); + exit_program(1); + } } ist->frames_decoded++; From c894f85f72c0bd922cf2bf746fe9c7fa5a932725 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Wed, 17 May 2023 12:08:13 +0200 Subject: [PATCH 1152/2172] fftools/ffmpeg_dec: rename decode_video() to video_frame_process() This function does not do any decoding anymore. --- fftools/ffmpeg_dec.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/fftools/ffmpeg_dec.c b/fftools/ffmpeg_dec.c index acb56e4118b..e06747d9c45 100644 --- a/fftools/ffmpeg_dec.c +++ b/fftools/ffmpeg_dec.c @@ -179,7 +179,7 @@ static int64_t video_duration_estimate(const InputStream *ist, const AVFrame *fr return FFMAX(ist->last_frame_duration_est, 1); } -static int decode_video(InputStream *ist, AVFrame *frame) +static int video_frame_process(InputStream *ist, AVFrame *frame) { // The following line may be required in some cases where there is no parser // or the parser does not has_b_frames correctly @@ -462,7 +462,7 @@ int dec_packet(InputStream *ist, const AVPacket *pkt, int no_eof) audio_ts_process(ist, frame); } else { - ret = decode_video(ist, frame); + ret = video_frame_process(ist, frame); if (ret < 0) { av_log(NULL, AV_LOG_FATAL, "Error while processing the decoded " "data for stream #%d:%d\n", ist->file_index, ist->st->index); From fa7180b827490ce1327bf60aa85b10c3e6a7f814 Mon Sep 17 00:00:00 2001 From: Marvin Scholz Date: Mon, 22 May 2023 12:14:32 +0200 Subject: [PATCH 1153/2172] avfilter/vf_tpad: use enum for start/stop_mode Reviewed-by: Thilo Borgmann Reviewed-by: Niklas Haas --- libavfilter/vf_tpad.c | 24 +++++++++++++++--------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/libavfilter/vf_tpad.c b/libavfilter/vf_tpad.c index f0c065f0c37..d0fa7df8bef 100644 --- a/libavfilter/vf_tpad.c +++ b/libavfilter/vf_tpad.c @@ -27,6 +27,12 @@ #include "formats.h" #include "drawutils.h" +enum PadMode { + MODE_ADD = 0, + MODE_CLONE, + NB_MODE +}; + typedef struct TPadContext { const AVClass *class; int pad_start; @@ -51,10 +57,10 @@ typedef struct TPadContext { static const AVOption tpad_options[] = { { "start", "set the number of frames to delay input", OFFSET(pad_start), AV_OPT_TYPE_INT, {.i64=0}, 0, INT_MAX, VF }, { "stop", "set the number of frames to add after input finished", OFFSET(pad_stop), AV_OPT_TYPE_INT, {.i64=0}, -1, INT_MAX, VF }, - { "start_mode", "set the mode of added frames to start", OFFSET(start_mode), AV_OPT_TYPE_INT, {.i64=0}, 0, 1, VF, "mode" }, - { "add", "add solid-color frames", 0, AV_OPT_TYPE_CONST, {.i64=0}, 0, 0, VF, "mode" }, - { "clone", "clone first/last frame", 0, AV_OPT_TYPE_CONST, {.i64=1}, 0, 0, VF, "mode" }, - { "stop_mode", "set the mode of added frames to end", OFFSET(stop_mode), AV_OPT_TYPE_INT, {.i64=0}, 0, 1, VF, "mode" }, + { "start_mode", "set the mode of added frames to start", OFFSET(start_mode), AV_OPT_TYPE_INT, {.i64=MODE_ADD}, 0, NB_MODE-1, VF, "mode" }, + { "add", "add solid-color frames", 0, AV_OPT_TYPE_CONST, {.i64=MODE_ADD}, 0, 0, VF, "mode" }, + { "clone", "clone first/last frame", 0, AV_OPT_TYPE_CONST, {.i64=MODE_CLONE}, 0, 0, VF, "mode" }, + { "stop_mode", "set the mode of added frames to end", OFFSET(stop_mode), AV_OPT_TYPE_INT, {.i64=MODE_ADD}, 0, NB_MODE-1, VF, "mode" }, { "start_duration", "set the duration to delay input", OFFSET(start_duration), AV_OPT_TYPE_DURATION, {.i64=0}, 0, INT64_MAX, VF }, { "stop_duration", "set the duration to pad input", OFFSET(stop_duration), AV_OPT_TYPE_DURATION, {.i64=0}, 0, INT64_MAX, VF }, { "color", "set the color of the added frames", OFFSET(rgba_color), AV_OPT_TYPE_COLOR, {.str="black"}, 0, 0, VF }, @@ -91,7 +97,7 @@ static int activate(AVFilterContext *ctx) } } - if (s->start_mode == 0 && s->pad_start > 0 && ff_outlink_frame_wanted(outlink)) { + if (s->start_mode == MODE_ADD && s->pad_start > 0 && ff_outlink_frame_wanted(outlink)) { frame = ff_get_video_buffer(outlink, outlink->w, outlink->h); if (!frame) return AVERROR(ENOMEM); @@ -106,7 +112,7 @@ static int activate(AVFilterContext *ctx) return ff_filter_frame(outlink, frame); } - if (s->start_mode == 1 && s->pad_start > 0) { + if (s->start_mode == MODE_CLONE && s->pad_start > 0) { if (s->eof) { ff_outlink_set_status(outlink, AVERROR_EOF, 0); return 0; @@ -133,7 +139,7 @@ static int activate(AVFilterContext *ctx) if (ret < 0) return ret; if (ret > 0) { - if (s->stop_mode == 1 && s->pad_stop != 0) { + if (s->stop_mode == MODE_CLONE && s->pad_stop != 0) { av_frame_free(&s->cache_stop); s->cache_stop = av_frame_clone(frame); } @@ -147,14 +153,14 @@ static int activate(AVFilterContext *ctx) ff_outlink_set_status(outlink, AVERROR_EOF, s->pts); return 0; } - if (s->stop_mode == 0) { + if (s->stop_mode == MODE_ADD) { frame = ff_get_video_buffer(outlink, outlink->w, outlink->h); if (!frame) return AVERROR(ENOMEM); ff_fill_rectangle(&s->draw, &s->color, frame->data, frame->linesize, 0, 0, frame->width, frame->height); - } else if (s->stop_mode == 1) { + } else if (s->stop_mode == MODE_CLONE) { if (!s->cache_stop) { s->pad_stop = 0; ff_outlink_set_status(outlink, AVERROR_EOF, s->pts); From 86b252ea9dee18006910e30646ad1067f2d1323f Mon Sep 17 00:00:00 2001 From: Marvin Scholz Date: Mon, 22 May 2023 12:14:33 +0200 Subject: [PATCH 1154/2172] avfilter/vf_tpad: accept hardware frames in clone-only mode When no drawing is to be performed, tpad can work fine with hardware frames, so advertise this in the query_formats callback and ensure the drawing context is never initialised when just cloning frames. Reviewed-by: Thilo Borgmann Reviewed-by: Niklas Haas --- libavfilter/vf_tpad.c | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/libavfilter/vf_tpad.c b/libavfilter/vf_tpad.c index d0fa7df8bef..c2e266cb1a4 100644 --- a/libavfilter/vf_tpad.c +++ b/libavfilter/vf_tpad.c @@ -71,7 +71,12 @@ AVFILTER_DEFINE_CLASS(tpad); static int query_formats(AVFilterContext *ctx) { - return ff_set_common_formats(ctx, ff_draw_supported_pixel_formats(0)); + TPadContext *s = ctx->priv; + if ((s->stop_mode == MODE_ADD && s->pad_stop != 0) || + (s->start_mode == MODE_ADD && s->pad_start != 0)) + return ff_set_common_formats(ctx, ff_draw_supported_pixel_formats(0)); + + return ff_set_common_formats(ctx, ff_all_formats(AVMEDIA_TYPE_VIDEO)); } static int activate(AVFilterContext *ctx) @@ -190,8 +195,11 @@ static int config_input(AVFilterLink *inlink) AVFilterContext *ctx = inlink->dst; TPadContext *s = ctx->priv; - ff_draw_init(&s->draw, inlink->format, 0); - ff_draw_color(&s->draw, &s->color, s->rgba_color); + if ((s->stop_mode == MODE_ADD && s->pad_stop != 0) || + (s->start_mode == MODE_ADD && s->pad_start != 0)) { + ff_draw_init(&s->draw, inlink->format, 0); + ff_draw_color(&s->draw, &s->color, s->rgba_color); + } if (s->start_duration) s->pad_start = av_rescale_q(s->start_duration, inlink->frame_rate, av_inv_q(AV_TIME_BASE_Q)); From 557686ac6312ba59cc09fa023cf0f7a9f2c15a3f Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Mon, 22 May 2023 20:05:53 +0200 Subject: [PATCH 1155/2172] avdevice/opengl_enc: check sscanf return value --- libavdevice/opengl_enc.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libavdevice/opengl_enc.c b/libavdevice/opengl_enc.c index 06750bbba1e..88c413ee633 100644 --- a/libavdevice/opengl_enc.c +++ b/libavdevice/opengl_enc.c @@ -594,7 +594,8 @@ static av_cold int opengl_read_limits(AVFormatContext *h) } av_log(h, AV_LOG_DEBUG, "OpenGL version: %s\n", version); - sscanf(version, "%d.%d", &major, &minor); + if (sscanf(version, "%d.%d", &major, &minor) != 2) + return AVERROR(ENOSYS); for (i = 0; required_extensions[i].extension; i++) { if (major < required_extensions[i].major && From f209614290d160c15f4ec84a4f40026441b872ba Mon Sep 17 00:00:00 2001 From: James Almer Date: Sat, 20 May 2023 10:18:29 -0300 Subject: [PATCH 1156/2172] avcodec/libdav1d: only return EAGAIN when there are no buffered packets Fixes decoding packets containing split temporal units, as generated for example by the av1_frame_split bsf. Signed-off-by: James Almer --- libavcodec/libdav1d.c | 37 ++++++++++++++++++++++++++----------- 1 file changed, 26 insertions(+), 11 deletions(-) diff --git a/libavcodec/libdav1d.c b/libavcodec/libdav1d.c index c15e98cbd1b..c263157a2a6 100644 --- a/libavcodec/libdav1d.c +++ b/libavcodec/libdav1d.c @@ -316,20 +316,14 @@ static void libdav1d_user_data_free(const uint8_t *data, void *opaque) { av_packet_free(&pkt); } -static int libdav1d_receive_frame(AVCodecContext *c, AVFrame *frame) +static int libdav1d_receive_frame_internal(AVCodecContext *c, Dav1dPicture *p) { Libdav1dContext *dav1d = c->priv_data; Dav1dData *data = &dav1d->data; - Dav1dPicture pic = { 0 }, *p = &pic; - AVPacket *pkt; - OpaqueData *od = NULL; -#if FF_DAV1D_VERSION_AT_LEAST(5,1) - enum Dav1dEventFlags event_flags = 0; -#endif int res; if (!data->sz) { - pkt = av_packet_alloc(); + AVPacket *pkt = av_packet_alloc(); if (!pkt) return AVERROR(ENOMEM); @@ -341,6 +335,8 @@ static int libdav1d_receive_frame(AVCodecContext *c, AVFrame *frame) } if (pkt->size) { + OpaqueData *od = NULL; + res = dav1d_data_wrap(data, pkt->data, pkt->size, libdav1d_data_free, pkt->buf); if (res < 0) { @@ -400,11 +396,30 @@ FF_ENABLE_DEPRECATION_WARNINGS if (res < 0) { if (res == AVERROR(EINVAL)) res = AVERROR_INVALIDDATA; - else if (res == AVERROR(EAGAIN) && c->internal->draining) - res = AVERROR_EOF; + else if (res == AVERROR(EAGAIN)) + res = c->internal->draining ? AVERROR_EOF : 1; + } + + return res; +} + +static int libdav1d_receive_frame(AVCodecContext *c, AVFrame *frame) +{ + Libdav1dContext *dav1d = c->priv_data; + Dav1dPicture pic = { 0 }, *p = &pic; + AVPacket *pkt; + OpaqueData *od = NULL; +#if FF_DAV1D_VERSION_AT_LEAST(5,1) + enum Dav1dEventFlags event_flags = 0; +#endif + int res; + do { + res = libdav1d_receive_frame_internal(c, p); + } while (res > 0); + + if (res < 0) return res; - } av_assert0(p->data[0] && p->allocator_data); From 4e521e610202a101471bb0cddd477a98617cea84 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Tue, 23 May 2023 10:28:14 +0200 Subject: [PATCH 1157/2172] fate/tests/ffmpeg: use -idct simple for fate-ffmpeg-input-r Makes the test bitexact on non-x86_64. --- tests/fate/ffmpeg.mak | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/fate/ffmpeg.mak b/tests/fate/ffmpeg.mak index aca949176af..800f3a03d2b 100644 --- a/tests/fate/ffmpeg.mak +++ b/tests/fate/ffmpeg.mak @@ -225,5 +225,5 @@ fate-time_base: CMD = md5 -i $(TARGET_SAMPLES)/mpeg2/dvd_single_frame.vob -an -s FATE_SAMPLES_FFMPEG-yes += $(FATE_TIME_BASE-yes) # test -r used as an input option -fate-ffmpeg-input-r: CMD = framecrc -r 27 -i $(TARGET_SAMPLES)/mpeg2/sony-ct3.bs +fate-ffmpeg-input-r: CMD = framecrc -r 27 -idct simple -i $(TARGET_SAMPLES)/mpeg2/sony-ct3.bs FATE_SAMPLES_FFMPEG-$(call FRAMECRC, MPEGVIDEO, MPEG2VIDEO) += fate-ffmpeg-input-r From ee13414444a02cf57c005f79c1eb13eff95e47b1 Mon Sep 17 00:00:00 2001 From: Niklas Haas Date: Tue, 23 May 2023 15:05:21 +0200 Subject: [PATCH 1158/2172] lavfi/vf_libplacebo: update settings after adding hooks Failure to do so led to the update s->hooks never getting correctly propagated to the render params. --- libavfilter/vf_libplacebo.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/libavfilter/vf_libplacebo.c b/libavfilter/vf_libplacebo.c index 65fe6ef746d..abf22a6117d 100644 --- a/libavfilter/vf_libplacebo.c +++ b/libavfilter/vf_libplacebo.c @@ -317,6 +317,8 @@ static void set_gamut_mode(struct pl_color_map_params *p, int gamut_mode) av_assert0(0); }; +static int update_settings(AVFilterContext *ctx); + static int parse_shader(AVFilterContext *avctx, const void *shader, size_t len) { LibplaceboContext *s = avctx->priv; @@ -329,7 +331,7 @@ static int parse_shader(AVFilterContext *avctx, const void *shader, size_t len) } s->hooks[s->num_hooks++] = hook; - return 0; + return update_settings(avctx); } static int find_scaler(AVFilterContext *avctx, From d815584755c8c75ac6bc3fb8a7465836b4dbcd42 Mon Sep 17 00:00:00 2001 From: Niklas Haas Date: Tue, 23 May 2023 15:06:18 +0200 Subject: [PATCH 1159/2172] lavif/vf_libplacebo: move code (cosmetic) To eliminate need for forward declaration --- libavfilter/vf_libplacebo.c | 32 +++++++++++++++----------------- 1 file changed, 15 insertions(+), 17 deletions(-) diff --git a/libavfilter/vf_libplacebo.c b/libavfilter/vf_libplacebo.c index abf22a6117d..d4b2f21328b 100644 --- a/libavfilter/vf_libplacebo.c +++ b/libavfilter/vf_libplacebo.c @@ -317,23 +317,6 @@ static void set_gamut_mode(struct pl_color_map_params *p, int gamut_mode) av_assert0(0); }; -static int update_settings(AVFilterContext *ctx); - -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 update_settings(avctx); -} - static int find_scaler(AVFilterContext *avctx, const struct pl_filter_config **opt, const char *name, int frame_mixing) @@ -487,6 +470,21 @@ static int update_settings(AVFilterContext *ctx) return err; } +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 update_settings(avctx); +} + static void libplacebo_uninit(AVFilterContext *avctx); static int libplacebo_init(AVFilterContext *avctx) From 0bce5590c3956184365d5600425e9c1dddb513ec Mon Sep 17 00:00:00 2001 From: Niklas Haas Date: Wed, 24 May 2023 14:35:49 +0200 Subject: [PATCH 1160/2172] lavfi/vf_libplacebo: fix crop expr PTS calculation mix->timestamps is expressed relative to the source timebase, which is possibly a different timescale from `base_pts`. We can't mix-and-match here. The only reason this worked in my previous testing was because I was testing on a source file which had an exactly matching timebase. Fix it by always using the exact PTS as tagged on the AVFrame. --- libavfilter/vf_libplacebo.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/libavfilter/vf_libplacebo.c b/libavfilter/vf_libplacebo.c index d4b2f21328b..adebcc45410 100644 --- a/libavfilter/vf_libplacebo.c +++ b/libavfilter/vf_libplacebo.c @@ -651,7 +651,7 @@ static int libplacebo_process_command(AVFilterContext *ctx, const char *cmd, static void update_crops(AVFilterContext *ctx, struct pl_frame_mix *mix, struct pl_frame *target, - uint64_t ref_sig, double base_pts) + uint64_t ref_sig, double target_pts) { LibplaceboContext *s = ctx->priv; @@ -659,11 +659,12 @@ static void update_crops(AVFilterContext *ctx, // Mutate the `pl_frame.crop` fields in-place. This is fine because we // own the entire pl_queue, and hence, the pointed-at frames. struct pl_frame *image = (struct pl_frame *) mix->frames[i]; - double image_pts = base_pts + mix->timestamps[i]; + const AVFrame *src = pl_get_mapped_avframe(image); + double image_pts = src->pts * av_q2d(ctx->inputs[0]->time_base); /* Update dynamic variables */ s->var_values[VAR_IN_T] = s->var_values[VAR_T] = image_pts; - s->var_values[VAR_OUT_T] = s->var_values[VAR_OT] = base_pts; + s->var_values[VAR_OUT_T] = s->var_values[VAR_OT] = target_pts; s->var_values[VAR_N] = ctx->outputs[0]->frame_count_out; /* Clear these explicitly to avoid leaking previous frames' state */ From 2b0fe529674e91bd55b52512f9a2bb0658ce0f7c Mon Sep 17 00:00:00 2001 From: Haihao Xiang Date: Mon, 15 May 2023 14:04:03 +0800 Subject: [PATCH 1161/2172] lavc/qsv: fallback to the default mfx implementation for internal session on Windows The mfx implementation based on D3D11 is expected for an internal session on Windows, however sometimes this implemntation is not supported [1]. A fallback to the default mfx implementation is added in this patch. [1] https://github.com/intel/cartwheel-ffmpeg/issues/246 Signed-off-by: Haihao Xiang --- libavcodec/qsv.c | 25 +++++++++++++++++++------ 1 file changed, 19 insertions(+), 6 deletions(-) diff --git a/libavcodec/qsv.c b/libavcodec/qsv.c index 8eabf46b451..75636256277 100644 --- a/libavcodec/qsv.c +++ b/libavcodec/qsv.c @@ -677,18 +677,31 @@ static int qsv_create_mfx_session(AVCodecContext *avctx, int ff_qsv_init_internal_session(AVCodecContext *avctx, QSVSession *qs, const char *load_plugins, int gpu_copy) { + mfxIMPL impls[] = { #if CONFIG_D3D11VA - mfxIMPL impl = MFX_IMPL_AUTO_ANY | MFX_IMPL_VIA_D3D11; -#else - mfxIMPL impl = MFX_IMPL_AUTO_ANY; + MFX_IMPL_AUTO_ANY | MFX_IMPL_VIA_D3D11, #endif + MFX_IMPL_AUTO_ANY + }; + mfxIMPL impl; mfxVersion ver = { { QSV_VERSION_MINOR, QSV_VERSION_MAJOR } }; const char *desc; - int ret = qsv_create_mfx_session(avctx, impl, &ver, gpu_copy, &qs->session, + int ret; + + for (int i = 0; i < FF_ARRAY_ELEMS(impls); i++) { + ret = qsv_create_mfx_session(avctx, impls[i], &ver, gpu_copy, &qs->session, &qs->loader); - if (ret) - return ret; + + if (ret == 0) + break; + + if (i == FF_ARRAY_ELEMS(impls) - 1) + return ret; + else + av_log(avctx, AV_LOG_ERROR, "The current mfx implementation is not " + "supported, try next mfx implementation.\n"); + } #ifdef AVCODEC_QSV_LINUX_SESSION_HANDLE ret = ff_qsv_set_display_handle(avctx, qs); From cfdfd6aa723101f4bf089dc750b8389b203533f8 Mon Sep 17 00:00:00 2001 From: Haihao Xiang Date: Thu, 18 May 2023 14:54:36 +0800 Subject: [PATCH 1162/2172] lavc/qsvenc: use the right alignment instead of hard coded value Signed-off-by: Haihao Xiang --- libavcodec/qsvenc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavcodec/qsvenc.c b/libavcodec/qsvenc.c index 0ed1f757d46..2c38fbf0dc4 100644 --- a/libavcodec/qsvenc.c +++ b/libavcodec/qsvenc.c @@ -1909,7 +1909,7 @@ static int submit_frame(QSVEncContext *q, const AVFrame *frame, } else { /* make a copy if the input is not padded as libmfx requires */ /* and to make allocation continious for data[0]/data[1] */ - if ((frame->height & 31 || frame->linesize[0] & (q->width_align - 1)) || + if ((frame->height & (q->height_align - 1) || frame->linesize[0] & (q->width_align - 1)) || (frame->data[1] - frame->data[0] != frame->linesize[0] * FFALIGN(qf->frame->height, q->height_align))) { int tmp_w, tmp_h; qf->frame->height = tmp_h = FFALIGN(frame->height, q->height_align); From cf79dab8dff4be3a875cfe0b1e1025f4eb541623 Mon Sep 17 00:00:00 2001 From: Haihao Xiang Date: Thu, 18 May 2023 14:54:37 +0800 Subject: [PATCH 1163/2172] lavc/qsvenc: avoid data copy if possible The data copy is unnecessary for packed formats when frame width and height are aligned For example: $ ffmpeg -f lavfi -i testsrc=size=1920x1088 -vf "format=yuyv422" -c:v hevc_qsv -f null - Signed-off-by: Haihao Xiang --- libavcodec/qsvenc.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libavcodec/qsvenc.c b/libavcodec/qsvenc.c index 2c38fbf0dc4..b6813b30236 100644 --- a/libavcodec/qsvenc.c +++ b/libavcodec/qsvenc.c @@ -1910,7 +1910,8 @@ static int submit_frame(QSVEncContext *q, const AVFrame *frame, /* make a copy if the input is not padded as libmfx requires */ /* and to make allocation continious for data[0]/data[1] */ if ((frame->height & (q->height_align - 1) || frame->linesize[0] & (q->width_align - 1)) || - (frame->data[1] - frame->data[0] != frame->linesize[0] * FFALIGN(qf->frame->height, q->height_align))) { + ((frame->format == AV_PIX_FMT_NV12 || frame->format == AV_PIX_FMT_P010 || frame->format == AV_PIX_FMT_P012) && + (frame->data[1] - frame->data[0] != frame->linesize[0] * FFALIGN(qf->frame->height, q->height_align)))) { int tmp_w, tmp_h; qf->frame->height = tmp_h = FFALIGN(frame->height, q->height_align); qf->frame->width = tmp_w = FFALIGN(frame->width, q->width_align); From 943a42fc54fc4eb9195151b0f8653adde009ca09 Mon Sep 17 00:00:00 2001 From: Haihao Xiang Date: Thu, 18 May 2023 14:54:38 +0800 Subject: [PATCH 1164/2172] lavc/qsvenc: make sure continuous allocation Intel MediaSDK and oneVPL expect continuous allocation for data[i], however there are mandatory padding bytes between data[i] and data[i+1]. when calling av_frame_get_buffer. This patch removes all extra padding bytes. Signed-off-by: Haihao Xiang --- libavcodec/qsvenc.c | 58 ++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 57 insertions(+), 1 deletion(-) diff --git a/libavcodec/qsvenc.c b/libavcodec/qsvenc.c index b6813b30236..4ae9a924906 100644 --- a/libavcodec/qsvenc.c +++ b/libavcodec/qsvenc.c @@ -1882,6 +1882,62 @@ static int qsvenc_fill_padding_area(AVFrame *frame, int new_w, int new_h) return 0; } +/* frame width / height have been aligned with the alignment */ +static int qsvenc_get_continuous_buffer(AVFrame *frame) +{ + int total_size; + + switch (frame->format) { + case AV_PIX_FMT_NV12: + frame->linesize[0] = frame->width; + frame->linesize[1] = frame->linesize[0]; + total_size = frame->linesize[0] * frame->height + frame->linesize[1] * frame->height / 2; + break; + + case AV_PIX_FMT_P010: + case AV_PIX_FMT_P012: + frame->linesize[0] = 2 * frame->width; + frame->linesize[1] = frame->linesize[0]; + total_size = frame->linesize[0] * frame->height + frame->linesize[1] * frame->height / 2; + break; + + case AV_PIX_FMT_YUYV422: + frame->linesize[0] = 2 * frame->width; + frame->linesize[1] = 0; + total_size = frame->linesize[0] * frame->height; + break; + + case AV_PIX_FMT_Y210: + case AV_PIX_FMT_VUYX: + case AV_PIX_FMT_XV30: + case AV_PIX_FMT_BGRA: + case AV_PIX_FMT_X2RGB10: + frame->linesize[0] = 4 * frame->width; + frame->linesize[1] = 0; + total_size = frame->linesize[0] * frame->height; + break; + + default: + // This should never be reached + av_assert0(0); + return AVERROR(EINVAL); + } + + frame->buf[0] = av_buffer_alloc(total_size); + if (!frame->buf[0]) + return AVERROR(ENOMEM); + + frame->data[0] = frame->buf[0]->data; + frame->extended_data = frame->data; + + if (frame->format == AV_PIX_FMT_NV12 || + frame->format == AV_PIX_FMT_P010 || + frame->format == AV_PIX_FMT_P012) + frame->data[1] = frame->data[0] + frame->linesize[0] * frame->height; + + return 0; +} + static int submit_frame(QSVEncContext *q, const AVFrame *frame, QSVFrame **new_frame) { @@ -1919,7 +1975,7 @@ static int submit_frame(QSVEncContext *q, const AVFrame *frame, qf->frame->format = frame->format; if (!qf->frame->data[0]) { - ret = av_frame_get_buffer(qf->frame, q->width_align); + ret = qsvenc_get_continuous_buffer(qf->frame); if (ret < 0) return ret; } From 8e2547ebb2222469a702a4962d035e8811b1d085 Mon Sep 17 00:00:00 2001 From: Haihao Xiang Date: Mon, 22 May 2023 11:36:14 +0800 Subject: [PATCH 1165/2172] lavc/qsvenc: the height is aligned to 32 for AV1 Signed-off-by: Haihao Xiang --- libavcodec/qsvenc.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/libavcodec/qsvenc.c b/libavcodec/qsvenc.c index 4ae9a924906..df63c182b0d 100644 --- a/libavcodec/qsvenc.c +++ b/libavcodec/qsvenc.c @@ -834,7 +834,9 @@ static int init_video_param(AVCodecContext *avctx, QSVEncContext *q) // for progressive video, the height should be aligned to 16 for // H.264. For HEVC, depending on the version of MFX, it should be // either 32 or 16. The lower number is better if possible. - q->height_align = avctx->codec_id == AV_CODEC_ID_HEVC ? 32 : 16; + // For AV1, it is 32 + q->height_align = (avctx->codec_id == AV_CODEC_ID_HEVC || + avctx->codec_id == AV_CODEC_ID_AV1) ? 32 : 16; } q->param.mfx.FrameInfo.Height = FFALIGN(avctx->height, q->height_align); From 43ace8f2bc29faf335e31b9893e6b8928ba3f541 Mon Sep 17 00:00:00 2001 From: Zhao Zhili Date: Tue, 23 May 2023 13:22:25 +0800 Subject: [PATCH 1166/2172] avfilter/vf_subtitles: add wrap_unicode option So CJK can be wrapped automatically. Signed-off-by: Zhao Zhili --- doc/filters.texi | 7 +++++++ libavfilter/version.h | 2 +- libavfilter/vf_subtitles.c | 18 ++++++++++++++++++ 3 files changed, 26 insertions(+), 1 deletion(-) diff --git a/doc/filters.texi b/doc/filters.texi index 76d9f11edc3..6c5b61d7636 100644 --- a/doc/filters.texi +++ b/doc/filters.texi @@ -22440,6 +22440,13 @@ Set subtitles stream index. @code{subtitles} filter only. @item force_style Override default style or script info parameters of the subtitles. It accepts a string containing ASS style format @code{KEY=VALUE} couples separated by ",". + +@item wrap_unicode +Break lines according to the Unicode Line Breaking Algorithm. Only available +since libass version 0x01600010, and whether it's usable depends on the built +of libass. + +The option is enabled by default except for native ASS. @end table If the first key is not specified, it is assumed that the first value diff --git a/libavfilter/version.h b/libavfilter/version.h index ba8a6fdab24..08779130f56 100644 --- a/libavfilter/version.h +++ b/libavfilter/version.h @@ -32,7 +32,7 @@ #include "version_major.h" #define LIBAVFILTER_VERSION_MINOR 8 -#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_subtitles.c b/libavfilter/vf_subtitles.c index 82e140e9863..3e5a19e7157 100644 --- a/libavfilter/vf_subtitles.c +++ b/libavfilter/vf_subtitles.c @@ -45,6 +45,8 @@ #include "formats.h" #include "video.h" +#define FF_ASS_FEATURE_WRAP_UNICODE (LIBASS_VERSION >= 0x01600010) + typedef struct AssContext { const AVClass *class; ASS_Library *library; @@ -61,6 +63,7 @@ typedef struct AssContext { int original_w, original_h; int shaping; FFDrawContext draw; + int wrap_unicode; } AssContext; #define OFFSET(x) offsetof(AssContext, x) @@ -271,6 +274,9 @@ static const AVOption subtitles_options[] = { {"stream_index", "set stream index", OFFSET(stream_index), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, INT_MAX, FLAGS}, {"si", "set stream index", OFFSET(stream_index), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, INT_MAX, FLAGS}, {"force_style", "force subtitle style", OFFSET(force_style), AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, FLAGS}, +#if FF_ASS_FEATURE_WRAP_UNICODE + {"wrap_unicode", "break lines according to the Unicode Line Breaking Algorithm", OFFSET(wrap_unicode), AV_OPT_TYPE_BOOL, { .i64 = -1 }, -1, 1, FLAGS }, +#endif {NULL}, }; @@ -432,6 +438,18 @@ static av_cold int init_subtitles(AVFilterContext *ctx) if (ret < 0) goto end; +#if FF_ASS_FEATURE_WRAP_UNICODE + /* Don't overwrite wrap automatically for native ASS */ + if (ass->wrap_unicode == -1) + ass->wrap_unicode = st->codecpar->codec_id != AV_CODEC_ID_ASS; + if (ass->wrap_unicode) { + ret = ass_track_set_feature(ass->track, ASS_FEATURE_WRAP_UNICODE, 1); + if (ret < 0) + av_log(ctx, AV_LOG_WARNING, + "libass wasn't built with ASS_FEATURE_WRAP_UNICODE support\n"); + } +#endif + if (ass->force_style) { char **list = NULL; char *temp = NULL; From 944243477b91ede33a61d359b9262b38aaa51d81 Mon Sep 17 00:00:00 2001 From: Gyan Doshi Date: Thu, 25 May 2023 12:40:08 +0530 Subject: [PATCH 1167/2172] doc/filters: clarify requirements for subtitles wrap_unicode option --- doc/filters.texi | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/doc/filters.texi b/doc/filters.texi index 6c5b61d7636..64719724020 100644 --- a/doc/filters.texi +++ b/doc/filters.texi @@ -22442,9 +22442,9 @@ Override default style or script info parameters of the subtitles. It accepts a string containing ASS style format @code{KEY=VALUE} couples separated by ",". @item wrap_unicode -Break lines according to the Unicode Line Breaking Algorithm. Only available -since libass version 0x01600010, and whether it's usable depends on the built -of libass. +Break lines according to the Unicode Line Breaking Algorithm. Availability requires +at least libass release 0.17.0 (or LIBASS_VERSION 0x01600010), @emph{and} libass must +have been built with libunibreak. The option is enabled by default except for native ASS. @end table From 97f4263457dd4903e51a94b74449123d3017175f Mon Sep 17 00:00:00 2001 From: James Almer Date: Fri, 19 May 2023 19:54:49 -0300 Subject: [PATCH 1168/2172] avcodec/av1dec: convert to receive_frame() This removes the overhead of inserting the av1_frame_split bsf as part of the decoding process. Signed-off-by: James Almer --- configure | 2 +- libavcodec/av1dec.c | 83 +++++++++++++++++++++++++++++++++------------ libavcodec/av1dec.h | 4 +++ 3 files changed, 66 insertions(+), 23 deletions(-) diff --git a/configure b/configure index a54398c57fa..87f7afc2e1a 100755 --- a/configure +++ b/configure @@ -2776,7 +2776,7 @@ asv1_encoder_select="aandcttables bswapdsp fdctdsp pixblockdsp" asv2_decoder_select="blockdsp bswapdsp idctdsp" asv2_encoder_select="aandcttables bswapdsp fdctdsp pixblockdsp" atrac1_decoder_select="sinewin" -av1_decoder_select="av1_frame_split_bsf cbs_av1 atsc_a53" +av1_decoder_select="cbs_av1 atsc_a53" bink_decoder_select="blockdsp hpeldsp" binkaudio_dct_decoder_select="wma_freqs" binkaudio_rdft_decoder_select="wma_freqs" diff --git a/libavcodec/av1dec.c b/libavcodec/av1dec.c index d46ee48335f..7de6ba0965c 100644 --- a/libavcodec/av1dec.c +++ b/libavcodec/av1dec.c @@ -32,6 +32,7 @@ #include "bytestream.h" #include "codec_internal.h" #include "decode.h" +#include "internal.h" #include "hwconfig.h" #include "profiles.h" #include "thread.h" @@ -765,6 +766,7 @@ static av_cold int av1_decode_init(AVCodecContext *avctx) int ret; s->avctx = avctx; + s->pkt = avctx->internal->in_pkt; s->pix_fmt = AV_PIX_FMT_NONE; for (int i = 0; i < FF_ARRAY_ELEMS(s->ref); i++) { @@ -1041,11 +1043,11 @@ static int export_film_grain(AVCodecContext *avctx, AVFrame *frame) return 0; } -static int set_output_frame(AVCodecContext *avctx, AVFrame *frame, - const AVPacket *pkt, int *got_frame) +static int set_output_frame(AVCodecContext *avctx, AVFrame *frame) { AV1DecContext *s = avctx->priv_data; const AVFrame *srcframe = s->cur_frame.f; + AVPacket *pkt = s->pkt; int ret; // TODO: all layers @@ -1076,10 +1078,11 @@ static int set_output_frame(AVCodecContext *avctx, AVFrame *frame, #if FF_API_FRAME_PKT FF_DISABLE_DEPRECATION_WARNINGS frame->pkt_size = pkt->size; + frame->pkt_pos = pkt->pos; FF_ENABLE_DEPRECATION_WARNINGS #endif - *got_frame = 1; + av_packet_unref(pkt); return 0; } @@ -1145,22 +1148,13 @@ static int get_current_frame(AVCodecContext *avctx) return ret; } -static int av1_decode_frame(AVCodecContext *avctx, AVFrame *frame, - int *got_frame, AVPacket *pkt) +static int av1_receive_frame_internal(AVCodecContext *avctx, AVFrame *frame) { AV1DecContext *s = avctx->priv_data; AV1RawTileGroup *raw_tile_group = NULL; - int ret; - - ret = ff_cbs_read_packet(s->cbc, &s->current_obu, pkt); - if (ret < 0) { - av_log(avctx, AV_LOG_ERROR, "Failed to read packet.\n"); - goto end; - } - av_log(avctx, AV_LOG_DEBUG, "Total obu for this frame:%d.\n", - s->current_obu.nb_units); + int i = 0, ret; - for (int i = 0; i < s->current_obu.nb_units; i++) { + for (i = s->nb_unit; i < s->current_obu.nb_units; i++) { CodedBitstreamUnit *unit = &s->current_obu.units[i]; AV1RawOBU *obu = unit->content; const AV1RawOBUHeader *header; @@ -1252,12 +1246,13 @@ static int av1_decode_frame(AVCodecContext *avctx, AVFrame *frame, } if (s->cur_frame.f->buf[0]) { - ret = set_output_frame(avctx, frame, pkt, got_frame); + ret = set_output_frame(avctx, frame); if (ret < 0) av_log(avctx, AV_LOG_ERROR, "Set output frame error.\n"); } s->raw_frame_header = NULL; + i++; goto end; } @@ -1361,6 +1356,7 @@ static int av1_decode_frame(AVCodecContext *avctx, AVFrame *frame, } if (raw_tile_group && (s->tile_num == raw_tile_group->tg_end + 1)) { + int show_frame = s->raw_frame_header->show_frame; if (avctx->hwaccel && s->cur_frame.f->buf[0]) { ret = avctx->hwaccel->end_frame(avctx); if (ret < 0) { @@ -1376,7 +1372,7 @@ static int av1_decode_frame(AVCodecContext *avctx, AVFrame *frame, } if (s->raw_frame_header->show_frame && s->cur_frame.f->buf[0]) { - ret = set_output_frame(avctx, frame, pkt, got_frame); + ret = set_output_frame(avctx, frame); if (ret < 0) { av_log(avctx, AV_LOG_ERROR, "Set output frame error\n"); goto end; @@ -1384,13 +1380,55 @@ static int av1_decode_frame(AVCodecContext *avctx, AVFrame *frame, } raw_tile_group = NULL; s->raw_frame_header = NULL; + if (show_frame) { + i++; + goto end; + } } } + ret = AVERROR(EAGAIN); end: - ff_cbs_fragment_reset(&s->current_obu); - if (ret < 0) - s->raw_frame_header = NULL; + av_assert0(i <= s->current_obu.nb_units); + s->nb_unit = i; + + if ((ret < 0 && ret != AVERROR(EAGAIN)) || s->current_obu.nb_units == i) { + if (ret < 0) + s->raw_frame_header = NULL; + av_packet_unref(s->pkt); + ff_cbs_fragment_reset(&s->current_obu); + s->nb_unit = 0; + } + + return ret; +} + +static int av1_receive_frame(AVCodecContext *avctx, AVFrame *frame) +{ + AV1DecContext *s = avctx->priv_data; + int ret; + + do { + if (!s->current_obu.nb_units) { + ret = ff_decode_get_packet(avctx, s->pkt); + if (ret < 0) + return ret; + + ret = ff_cbs_read_packet(s->cbc, &s->current_obu, s->pkt); + if (ret < 0) { + av_packet_unref(s->pkt); + av_log(avctx, AV_LOG_ERROR, "Failed to read packet.\n"); + return ret; + } + + s->nb_unit = 0; + av_log(avctx, AV_LOG_DEBUG, "Total OBUs on this packet: %d.\n", + s->current_obu.nb_units); + } + + ret = av1_receive_frame_internal(avctx, frame); + } while (ret == AVERROR(EAGAIN)); + return ret; } @@ -1404,6 +1442,7 @@ static void av1_decode_flush(AVCodecContext *avctx) av1_frame_unref(avctx, &s->cur_frame); s->operating_point_idc = 0; + s->nb_unit = 0; s->raw_frame_header = NULL; s->raw_seq = NULL; s->cll = NULL; @@ -1411,6 +1450,7 @@ static void av1_decode_flush(AVCodecContext *avctx) while (av_fifo_read(s->itut_t35_fifo, &itut_t35, 1) >= 0) av_buffer_unref(&itut_t35.payload_ref); + ff_cbs_fragment_reset(&s->current_obu); ff_cbs_flush(s->cbc); } @@ -1437,14 +1477,13 @@ const FFCodec ff_av1_decoder = { .priv_data_size = sizeof(AV1DecContext), .init = av1_decode_init, .close = av1_decode_free, - FF_CODEC_DECODE_CB(av1_decode_frame), + FF_CODEC_RECEIVE_FRAME_CB(av1_receive_frame), .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_AVOID_PROBING, .caps_internal = FF_CODEC_CAP_INIT_CLEANUP | FF_CODEC_CAP_SETS_PKT_DTS, .flush = av1_decode_flush, .p.profiles = NULL_IF_CONFIG_SMALL(ff_av1_profiles), .p.priv_class = &av1_class, - .bsfs = "av1_frame_split", .hw_configs = (const AVCodecHWConfigInternal *const []) { #if CONFIG_AV1_DXVA2_HWACCEL HWACCEL_DXVA2(av1), diff --git a/libavcodec/av1dec.h b/libavcodec/av1dec.h index cef899f81f7..59ffed1d9ba 100644 --- a/libavcodec/av1dec.h +++ b/libavcodec/av1dec.h @@ -28,6 +28,7 @@ #include "libavutil/frame.h" #include "libavutil/pixfmt.h" #include "avcodec.h" +#include "packet.h" #include "cbs.h" #include "cbs_av1.h" @@ -68,6 +69,7 @@ typedef struct AV1DecContext { enum AVPixelFormat pix_fmt; CodedBitstreamContext *cbc; CodedBitstreamFragment current_obu; + AVPacket *pkt; AVBufferRef *seq_ref; AV1RawSequenceHeader *raw_seq; @@ -90,6 +92,8 @@ typedef struct AV1DecContext { AV1Frame ref[AV1_NUM_REF_FRAMES]; AV1Frame cur_frame; + int nb_unit; + // AVOptions int operating_point; } AV1DecContext; From a1838c59bb866bb6d2d1ad07f7df128a1804de40 Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Thu, 25 May 2023 19:30:22 +0200 Subject: [PATCH 1169/2172] avfilter/af_astats: add abs_peak_count stat --- doc/filters.texi | 6 ++++++ libavfilter/af_astats.c | 26 +++++++++++++++++++++++++- 2 files changed, 31 insertions(+), 1 deletion(-) diff --git a/doc/filters.texi b/doc/filters.texi index 64719724020..0c3ac116b8c 100644 --- a/doc/filters.texi +++ b/doc/filters.texi @@ -3316,6 +3316,7 @@ Available keys for each channel are: @var{Number_of_NaNs} @var{Number_of_denormals} @var{Peak_count} +@var{Abs_Peak_count} @var{Peak_level} @var{RMS_difference} @var{RMS_peak} @@ -3340,6 +3341,7 @@ and for @code{Overall}: @var{Number_of_denormals} @var{Number_of_samples} @var{Peak_count} +@var{Abs_Peak_count} @var{Peak_level} @var{RMS_difference} @var{RMS_level} @@ -3433,6 +3435,10 @@ number of samples number of occasions (not the number of samples) that the signal attained either @var{Min_level} or @var{Max_level} +@item Abs_Peak_count +number of occasions that the absolute samples taken from the signal attained +max absolute value of @var{Min_level} and @var{Max_level} + @item Peak_level standard peak level measured in dBFS diff --git a/libavfilter/af_astats.c b/libavfilter/af_astats.c index f3f2bd743b5..0c94e0e963a 100644 --- a/libavfilter/af_astats.c +++ b/libavfilter/af_astats.c @@ -58,6 +58,7 @@ #define MEASURE_NOISE_FLOOR (1 << 22) #define MEASURE_NOISE_FLOOR_COUNT (1 << 23) #define MEASURE_ENTROPY (1 << 24) +#define MEASURE_ABS_PEAK_COUNT (1 << 25) #define MEASURE_MINMAXPEAK (MEASURE_MIN_LEVEL | MEASURE_MAX_LEVEL | MEASURE_PEAK_LEVEL) @@ -74,8 +75,10 @@ typedef struct ChannelStats { double min_diff, max_diff; double diff1_sum; double diff1_sum_x2; + double abs_peak; uint64_t mask, imask; uint64_t min_count, max_count; + uint64_t abs_peak_count; uint64_t noise_floor_count; uint64_t zero_runs; uint64_t nb_samples; @@ -144,6 +147,7 @@ static const AVOption astats_options[] = { { "RMS_trough" , "", 0, AV_OPT_TYPE_CONST, {.i64=MEASURE_RMS_TROUGH }, 0, 0, FLAGS, "measure" }, { "Zero_crossings" , "", 0, AV_OPT_TYPE_CONST, {.i64=MEASURE_ZERO_CROSSINGS }, 0, 0, FLAGS, "measure" }, { "Zero_crossings_rate" , "", 0, AV_OPT_TYPE_CONST, {.i64=MEASURE_ZERO_CROSSINGS_RATE }, 0, 0, FLAGS, "measure" }, + { "Abs_Peak_count" , "", 0, AV_OPT_TYPE_CONST, {.i64=MEASURE_ABS_PEAK_COUNT }, 0, 0, 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 } }; @@ -159,6 +163,7 @@ static void reset_stats(AudioStatsContext *s) p->min = p->nmin = p->min_sigma_x2 = DBL_MAX; p->max = p->nmax = p->max_sigma_x2 =-DBL_MAX; + p->abs_peak = 0; p->min_non_zero = DBL_MAX; p->min_diff = DBL_MAX; p->max_diff = 0; @@ -175,6 +180,7 @@ static void reset_stats(AudioStatsContext *s) p->imask = 0xFFFFFFFFFFFFFFFF; p->min_count = 0; p->max_count = 0; + p->abs_peak_count = 0; p->zero_runs = 0; p->nb_samples = 0; p->nb_nans = 0; @@ -264,9 +270,16 @@ static inline void update_minmax(AudioStatsContext *s, ChannelStats *p, double d static inline void update_stat(AudioStatsContext *s, ChannelStats *p, double d, double nd, int64_t i) { + double abs_d = FFABS(d); double drop; int index; + if (p->abs_peak < abs_d) { + p->abs_peak = abs_d; + p->abs_peak_count = 1; + } else if (p->abs_peak == abs_d) { + p->abs_peak_count++; + } if (d < p->min) { p->min = d; p->nmin = nd; @@ -398,6 +411,7 @@ static void set_metadata(AudioStatsContext *s, AVDictionary **metadata) { uint64_t mask = 0, imask = 0xFFFFFFFFFFFFFFFF, min_count = 0, max_count = 0, nb_samples = 0, noise_floor_count = 0; uint64_t nb_nans = 0, nb_infs = 0, nb_denormals = 0; + uint64_t abs_peak_count = 0; double min_runs = 0, max_runs = 0, min = DBL_MAX, max =-DBL_MAX, min_diff = DBL_MAX, max_diff = 0, nmin = DBL_MAX, nmax =-DBL_MAX, @@ -435,6 +449,7 @@ static void set_metadata(AudioStatsContext *s, AVDictionary **metadata) entropy += p->entropy; min_count += p->min_count; max_count += p->max_count; + abs_peak_count += p->abs_peak_count; min_runs += p->min_runs; max_runs += p->max_runs; mask |= p->mask; @@ -474,6 +489,8 @@ static void set_metadata(AudioStatsContext *s, AVDictionary **metadata) set_meta(metadata, c + 1, "Flat_factor", "%f", LINEAR_TO_DB((p->min_runs + p->max_runs) / (p->min_count + p->max_count))); if (s->measure_perchannel & MEASURE_PEAK_COUNT) set_meta(metadata, c + 1, "Peak_count", "%f", (float)(p->min_count + p->max_count)); + if (s->measure_perchannel & MEASURE_ABS_PEAK_COUNT) + set_meta(metadata, c + 1, "Peak_count", "%f", p->abs_peak_count); if (s->measure_perchannel & MEASURE_NOISE_FLOOR) set_meta(metadata, c + 1, "Noise_floor", "%f", LINEAR_TO_DB(p->noise_floor)); if (s->measure_perchannel & MEASURE_NOISE_FLOOR_COUNT) @@ -525,6 +542,8 @@ static void set_metadata(AudioStatsContext *s, AVDictionary **metadata) set_meta(metadata, 0, "Overall.Flat_factor", "%f", LINEAR_TO_DB((min_runs + max_runs) / (min_count + max_count))); if (s->measure_overall & MEASURE_PEAK_COUNT) set_meta(metadata, 0, "Overall.Peak_count", "%f", (float)(min_count + max_count) / (double)s->nb_channels); + if (s->measure_overall & MEASURE_ABS_PEAK_COUNT) + set_meta(metadata, 0, "Overall.Abs_Peak_count", "%f", (float)(abs_peak_count) / (double)s->nb_channels); if (s->measure_overall & MEASURE_NOISE_FLOOR) set_meta(metadata, 0, "Overall.Noise_floor", "%f", LINEAR_TO_DB(noise_floor)); if (s->measure_overall & MEASURE_NOISE_FLOOR_COUNT) @@ -653,7 +672,7 @@ static void print_stats(AVFilterContext *ctx) { AudioStatsContext *s = ctx->priv; uint64_t mask = 0, imask = 0xFFFFFFFFFFFFFFFF, min_count = 0, max_count = 0, nb_samples = 0, noise_floor_count = 0; - uint64_t nb_nans = 0, nb_infs = 0, nb_denormals = 0; + uint64_t nb_nans = 0, nb_infs = 0, nb_denormals = 0, abs_peak_count = 0; double min_runs = 0, max_runs = 0, min = DBL_MAX, max =-DBL_MAX, min_diff = DBL_MAX, max_diff = 0, nmin = DBL_MAX, nmax =-DBL_MAX, @@ -693,6 +712,7 @@ static void print_stats(AVFilterContext *ctx) entropy += p->entropy; min_count += p->min_count; max_count += p->max_count; + abs_peak_count += p->abs_peak_count; noise_floor_count += p->noise_floor_count; min_runs += p->min_runs; max_runs += p->max_runs; @@ -736,6 +756,8 @@ static void print_stats(AVFilterContext *ctx) av_log(ctx, AV_LOG_INFO, "Flat factor: %f\n", LINEAR_TO_DB((p->min_runs + p->max_runs) / (p->min_count + p->max_count))); if (s->measure_perchannel & MEASURE_PEAK_COUNT) av_log(ctx, AV_LOG_INFO, "Peak count: %"PRId64"\n", p->min_count + p->max_count); + if (s->measure_perchannel & MEASURE_ABS_PEAK_COUNT) + av_log(ctx, AV_LOG_INFO, "Abs Peak count: %"PRId64"\n", p->abs_peak_count); if (s->measure_perchannel & MEASURE_NOISE_FLOOR) av_log(ctx, AV_LOG_INFO, "Noise floor dB: %f\n", LINEAR_TO_DB(p->noise_floor)); if (s->measure_perchannel & MEASURE_NOISE_FLOOR_COUNT) @@ -792,6 +814,8 @@ static void print_stats(AVFilterContext *ctx) av_log(ctx, AV_LOG_INFO, "Flat factor: %f\n", LINEAR_TO_DB((min_runs + max_runs) / (min_count + max_count))); if (s->measure_overall & MEASURE_PEAK_COUNT) av_log(ctx, AV_LOG_INFO, "Peak count: %f\n", (min_count + max_count) / (double)s->nb_channels); + if (s->measure_overall & MEASURE_ABS_PEAK_COUNT) + av_log(ctx, AV_LOG_INFO, "Abs Peak count: %f\n", abs_peak_count / (double)s->nb_channels); if (s->measure_overall & MEASURE_NOISE_FLOOR) av_log(ctx, AV_LOG_INFO, "Noise floor dB: %f\n", LINEAR_TO_DB(noise_floor)); if (s->measure_overall & MEASURE_NOISE_FLOOR_COUNT) From e7cadd0ee5a3d0da64b6c9a66b6609aef8e1977d Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Sun, 21 May 2023 02:15:26 +0200 Subject: [PATCH 1170/2172] avformat/demux: add support to derive timestamps from packet durations for video --- libavformat/demux.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/libavformat/demux.c b/libavformat/demux.c index dec02a1a6b0..b3f563ccc77 100644 --- a/libavformat/demux.c +++ b/libavformat/demux.c @@ -1195,6 +1195,11 @@ static int parse_packet(AVFormatContext *s, AVPacket *pkt, st->time_base, AV_ROUND_DOWN); } + } else if ((s->iformat->flags & AVFMT_NOTIMESTAMPS) && st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) { + if (st->time_base.num > 0 && st->time_base.den > 0 && + sti->parser->duration) { + out_pkt->duration = sti->parser->duration; + } } out_pkt->stream_index = st->index; From c6b6356635f598b095606cd126f31bc6ab916225 Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Sat, 20 May 2023 14:13:27 +0200 Subject: [PATCH 1171/2172] avformat/gifdec: switch to using gif parser Update fate test, more correct as last packet is not truncated. --- libavcodec/gifdec.c | 11 +- libavformat/gifdec.c | 247 ++++++++++----------------------------- tests/ref/fate/gif-demux | 2 +- 3 files changed, 72 insertions(+), 188 deletions(-) diff --git a/libavcodec/gifdec.c b/libavcodec/gifdec.c index 0835c5bdd0d..f2ab783ef03 100644 --- a/libavcodec/gifdec.c +++ b/libavcodec/gifdec.c @@ -472,10 +472,6 @@ static int gif_decode_frame(AVCodecContext *avctx, AVFrame *rframe, bytestream2_init(&s->gb, avpkt->data, avpkt->size); - s->frame->pts = avpkt->pts; - s->frame->pkt_dts = avpkt->dts; - s->frame->duration = avpkt->duration; - if (avpkt->size >= 6) { s->keyframe = memcmp(avpkt->data, gif87a_sig, 6) == 0 || memcmp(avpkt->data, gif89a_sig, 6) == 0; @@ -522,6 +518,13 @@ static int gif_decode_frame(AVCodecContext *avctx, AVFrame *rframe, if ((ret = av_frame_ref(rframe, s->frame)) < 0) return ret; + if (s->keyframe) { + rframe->pict_type = AV_PICTURE_TYPE_I; + rframe->flags |= AV_FRAME_FLAG_KEY; + } else { + rframe->pict_type = AV_PICTURE_TYPE_P; + rframe->flags &= ~AV_FRAME_FLAG_KEY; + } *got_frame = 1; return bytestream2_tell(&s->gb); diff --git a/libavformat/gifdec.c b/libavformat/gifdec.c index 1977f46e3aa..774358e1fae 100644 --- a/libavformat/gifdec.c +++ b/libavformat/gifdec.c @@ -28,9 +28,12 @@ #include "libavutil/bprint.h" #include "libavutil/intreadwrite.h" #include "libavutil/opt.h" +#include "avio_internal.h" #include "internal.h" #include "libavcodec/gif.h" +#define GIF_PACKET_SIZE 1024 + typedef struct GIFDemuxContext { const AVClass *class; /** @@ -53,9 +56,6 @@ typedef struct GIFDemuxContext { int total_iter; int iter_count; int ignore_loop; - - int nb_frames; - int last_duration; } GIFDemuxContext; /** @@ -84,8 +84,8 @@ static int gif_probe(const AVProbeData *p) static int resync(AVIOContext *pb) { - int i; - for (i = 0; i < 6; i++) { + ffio_ensure_seekback(pb, 13); + for (int i = 0; i < 6; i++) { int b = avio_r8(pb); if (b != gif87a_sig[i] && b != gif89a_sig[i]) i = -(b != 'G'); @@ -113,11 +113,12 @@ static int gif_read_header(AVFormatContext *s) AVIOContext *pb = s->pb; AVStream *st; int type, width, height, ret, n, flags; - int64_t nb_frames = 0, duration = 0; + int64_t nb_frames = 0, duration = 0, pos; if ((ret = resync(pb)) < 0) return ret; + pos = avio_tell(pb); gdc->delay = gdc->default_delay; width = avio_rl16(pb); height = avio_rl16(pb); @@ -132,6 +133,9 @@ static int gif_read_header(AVFormatContext *s) if (!st) return AVERROR(ENOMEM); + if (!(pb->seekable & AVIO_SEEKABLE_NORMAL)) + goto skip; + if (flags & 0x80) avio_skip(pb, 3 * (1 << ((flags & 0x07) + 1))); @@ -158,15 +162,37 @@ static int gif_read_header(AVFormatContext *s) avio_skip(pb, 1); delay = avio_rl16(pb); - if (delay < gdc->min_delay) - delay = gdc->default_delay; - delay = FFMIN(delay, gdc->max_delay); + delay = delay ? delay : gdc->default_delay; duration += delay; avio_skip(pb, 1); } else { avio_skip(pb, block_size); } gif_skip_subblocks(pb); + } else if (subtype == GIF_APP_EXT_LABEL) { + uint8_t data[256]; + int sb_size; + + sb_size = avio_r8(pb); + ret = avio_read(pb, data, sb_size); + if (ret < 0 || !sb_size) + break; + + if (sb_size == strlen(NETSCAPE_EXT_STR)) { + sb_size = avio_r8(pb); + ret = avio_read(pb, data, sb_size); + if (ret < 0 || !sb_size) + break; + + if (sb_size == 3 && data[0] == 1) { + gdc->total_iter = AV_RL16(data+1); + av_log(s, AV_LOG_DEBUG, "Loop count is %d\n", gdc->total_iter); + + if (gdc->total_iter == 0) + gdc->total_iter = -1; + } + } + gif_skip_subblocks(pb); } else { gif_skip_subblocks(pb); } @@ -183,203 +209,57 @@ static int gif_read_header(AVFormatContext *s) } } +skip: + /* jump to start because gif decoder needs header data too */ + if (avio_seek(pb, pos - 6, SEEK_SET) != pos - 6) + return AVERROR(EIO); + /* GIF format operates with time in "hundredths of second", * therefore timebase is 1/100 */ avpriv_set_pts_info(st, 64, 1, 100); + ffstream(st)->need_parsing = AVSTREAM_PARSE_FULL_RAW; st->codecpar->codec_type = AVMEDIA_TYPE_VIDEO; st->codecpar->codec_id = AV_CODEC_ID_GIF; st->codecpar->width = width; st->codecpar->height = height; + if (nb_frames > 1) { + av_reduce(&st->avg_frame_rate.num, &st->avg_frame_rate.den, + 100, duration / nb_frames, INT_MAX); + } else if (duration) { + st->avg_frame_rate = (AVRational) { 100, duration }; + } st->start_time = 0; st->duration = duration; st->nb_frames = nb_frames; - if (n) { - st->codecpar->sample_aspect_ratio.num = n + 15; - st->codecpar->sample_aspect_ratio.den = 64; - } - - /* jump to start because gif decoder needs header data too */ - if (avio_seek(pb, 0, SEEK_SET) != 0) - return AVERROR(EIO); + if (n) + st->codecpar->sample_aspect_ratio = av_make_q(n + 15, 64); return 0; } -static int gif_read_ext(AVFormatContext *s) +static int gif_read_packet(AVFormatContext *s, AVPacket *pkt) { GIFDemuxContext *gdc = s->priv_data; AVIOContext *pb = s->pb; - int sb_size, ext_label = avio_r8(pb); int ret; - if (ext_label == GIF_GCE_EXT_LABEL) { - if ((sb_size = avio_r8(pb)) < 4) { - av_log(s, AV_LOG_FATAL, "Graphic Control Extension block's size less than 4.\n"); - return AVERROR_INVALIDDATA; - } - - /* skip packed fields */ - if ((ret = avio_skip(pb, 1)) < 0) - return ret; - - gdc->delay = avio_rl16(pb); - - if (gdc->delay < gdc->min_delay) - gdc->delay = gdc->default_delay; - gdc->delay = FFMIN(gdc->delay, gdc->max_delay); - - /* skip the rest of the Graphic Control Extension block */ - if ((ret = avio_skip(pb, sb_size - 3)) < 0 ) - return ret; - } else if (ext_label == GIF_APP_EXT_LABEL) { - uint8_t data[256]; - - sb_size = avio_r8(pb); - ret = avio_read(pb, data, sb_size); - if (ret < 0 || !sb_size) - return ret; - - if (sb_size == strlen(NETSCAPE_EXT_STR)) { - sb_size = avio_r8(pb); - ret = avio_read(pb, data, sb_size); - if (ret < 0 || !sb_size) - return ret; - - if (sb_size == 3 && data[0] == 1) { - gdc->total_iter = AV_RL16(data+1); - av_log(s, AV_LOG_DEBUG, "Loop count is %d\n", gdc->total_iter); - - if (gdc->total_iter == 0) - gdc->total_iter = -1; - } - } + if ((pb->seekable & AVIO_SEEKABLE_NORMAL) && + !gdc->ignore_loop && avio_feof(pb) && + (gdc->total_iter < 0 || (++gdc->iter_count < gdc->total_iter))) { + avio_seek(pb, 0, SEEK_SET); } - - if ((ret = gif_skip_subblocks(pb)) < 0) + if ((ret = av_new_packet(pkt, GIF_PACKET_SIZE)) < 0) return ret; - return 0; -} - -static int gif_read_packet(AVFormatContext *s, AVPacket *pkt) -{ - GIFDemuxContext *gdc = s->priv_data; - AVIOContext *pb = s->pb; - int packed_fields, block_label, ct_size, - keyframe, frame_parsed = 0, ret; - int64_t frame_start = avio_tell(pb), frame_end; - unsigned char buf[6]; - - if ((ret = avio_read(pb, buf, 6)) == 6) { - keyframe = memcmp(buf, gif87a_sig, 6) == 0 || - memcmp(buf, gif89a_sig, 6) == 0; - } else if (ret < 0) { + pkt->pos = avio_tell(pb); + pkt->stream_index = 0; + ret = avio_read_partial(pb, pkt->data, GIF_PACKET_SIZE); + if (ret < 0) { + av_packet_unref(pkt); return ret; - } else { - keyframe = 0; - } - - if (keyframe) { -parse_keyframe: - /* skip 2 bytes of width and 2 of height */ - if ((ret = avio_skip(pb, 4)) < 0) - return ret; - - packed_fields = avio_r8(pb); - - /* skip 1 byte of Background Color Index and 1 byte of Pixel Aspect Ratio */ - if ((ret = avio_skip(pb, 2)) < 0) - return ret; - - /* global color table presence */ - if (packed_fields & 0x80) { - ct_size = 3 * (1 << ((packed_fields & 0x07) + 1)); - - if ((ret = avio_skip(pb, ct_size)) < 0) - return ret; - } - } else { - avio_seek(pb, -ret, SEEK_CUR); - ret = AVERROR_EOF; - } - - while (GIF_TRAILER != (block_label = avio_r8(pb)) && !avio_feof(pb)) { - if (block_label == GIF_EXTENSION_INTRODUCER) { - if ((ret = gif_read_ext (s)) < 0 ) - goto resync; - } else if (block_label == GIF_IMAGE_SEPARATOR) { - /* skip to last byte of Image Descriptor header */ - if ((ret = avio_skip(pb, 8)) < 0) - return ret; - - packed_fields = avio_r8(pb); - - /* local color table presence */ - if (packed_fields & 0x80) { - ct_size = 3 * (1 << ((packed_fields & 0x07) + 1)); - - if ((ret = avio_skip(pb, ct_size)) < 0) - return ret; - } - - /* read LZW Minimum Code Size */ - if (avio_r8(pb) < 1) { - av_log(s, AV_LOG_ERROR, "lzw minimum code size must be >= 1\n"); - goto resync; - } - - if ((ret = gif_skip_subblocks(pb)) < 0) - goto resync; - - frame_end = avio_tell(pb); - - if (avio_seek(pb, frame_start, SEEK_SET) != frame_start) - return AVERROR(EIO); - - ret = av_get_packet(pb, pkt, frame_end - frame_start); - if (ret < 0) - return ret; - - if (keyframe) - pkt->flags |= AV_PKT_FLAG_KEY; - - pkt->stream_index = 0; - pkt->duration = gdc->delay; - - gdc->nb_frames ++; - gdc->last_duration = pkt->duration; - - /* Graphic Control Extension's scope is single frame. - * Remove its influence. */ - gdc->delay = gdc->default_delay; - frame_parsed = 1; - - break; - } else { - av_log(s, AV_LOG_ERROR, "invalid block label\n"); -resync: - if (!keyframe) - avio_seek(pb, frame_start, SEEK_SET); - if ((ret = resync(pb)) < 0) - return ret; - frame_start = avio_tell(pb) - 6; - keyframe = 1; - goto parse_keyframe; - } } - - if ((ret >= 0 && !frame_parsed) || ret == AVERROR_EOF) { - if (gdc->nb_frames == 1) { - s->streams[0]->r_frame_rate = (AVRational) {100, gdc->last_duration}; - } - /* This might happen when there is no image block - * between extension blocks and GIF_TRAILER or EOF */ - if (!gdc->ignore_loop && (block_label == GIF_TRAILER || avio_feof(pb)) - && (gdc->total_iter < 0 || ++gdc->iter_count < gdc->total_iter)) - return avio_seek(pb, 0, SEEK_SET); - return AVERROR_EOF; - } else - return ret; + av_shrink_packet(pkt, ret); + return ret; } static const AVOption options[] = { @@ -405,6 +285,7 @@ const AVInputFormat ff_gif_demuxer = { .read_probe = gif_probe, .read_header = gif_read_header, .read_packet = gif_read_packet, - .flags = AVFMT_GENERIC_INDEX, + .flags = AVFMT_GENERIC_INDEX | AVFMT_NOTIMESTAMPS, + .extensions = "gif", .priv_class = &demuxer_class, }; diff --git a/tests/ref/fate/gif-demux b/tests/ref/fate/gif-demux index 3d46441d8ef..a3267a0d2a6 100644 --- a/tests/ref/fate/gif-demux +++ b/tests/ref/fate/gif-demux @@ -38,4 +38,4 @@ 0, 74, 74, 2, 4633, 0x8f64fda7, F=0x0 0, 76, 76, 2, 4700, 0x45f40805, F=0x0 0, 78, 78, 2, 5117, 0x4eb4c5fb, F=0x0 -0, 80, 80, 2, 5370, 0xb10c6910, F=0x0 +0, 80, 80, 2, 5371, 0x1a66694b, F=0x0 From 90fba27743041a896bde618d99633c418ebc2a45 Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Wed, 17 May 2023 00:46:29 +0200 Subject: [PATCH 1172/2172] avfilter/trim: switch to activate This also signals EOF to filter inlink so that unnecessary extra processing that is immediately dropped by this filter is not done any more. --- libavfilter/trim.c | 214 +++++++++++++++++++++++++++------------------ 1 file changed, 131 insertions(+), 83 deletions(-) diff --git a/libavfilter/trim.c b/libavfilter/trim.c index ee6e821cd24..6bb567879da 100644 --- a/libavfilter/trim.c +++ b/libavfilter/trim.c @@ -31,6 +31,7 @@ #include "audio.h" #include "avfilter.h" #include "internal.h" +#include "filters.h" typedef struct TrimContext { const AVClass *class; @@ -68,6 +69,8 @@ typedef struct TrimContext { int64_t next_pts; int eof; + + int (*filter_frame)(AVFilterLink *inlink, AVFrame *frame); } TrimContext; static av_cold int init(AVFilterContext *ctx) @@ -79,47 +82,6 @@ static av_cold int init(AVFilterContext *ctx) return 0; } -static int config_input(AVFilterLink *inlink) -{ - AVFilterContext *ctx = inlink->dst; - TrimContext *s = ctx->priv; - AVRational tb = (inlink->type == AVMEDIA_TYPE_VIDEO) ? - inlink->time_base : (AVRational){ 1, inlink->sample_rate }; - - if (s->start_time != INT64_MAX) { - int64_t start_pts = av_rescale_q(s->start_time, AV_TIME_BASE_Q, tb); - if (s->start_pts == AV_NOPTS_VALUE || start_pts < s->start_pts) - s->start_pts = start_pts; - } - if (s->end_time != INT64_MAX) { - int64_t end_pts = av_rescale_q(s->end_time, AV_TIME_BASE_Q, tb); - if (s->end_pts == AV_NOPTS_VALUE || end_pts > s->end_pts) - s->end_pts = end_pts; - } - if (s->duration) - s->duration_tb = av_rescale_q(s->duration, AV_TIME_BASE_Q, tb); - - return 0; -} - -#define OFFSET(x) offsetof(TrimContext, x) -#define COMMON_OPTS \ - { "start", "Timestamp of the first frame that " \ - "should be passed", OFFSET(start_time), AV_OPT_TYPE_DURATION, { .i64 = INT64_MAX }, INT64_MIN, INT64_MAX, FLAGS }, \ - { "starti", "Timestamp of the first frame that " \ - "should be passed", OFFSET(start_time), AV_OPT_TYPE_DURATION, { .i64 = INT64_MAX }, INT64_MIN, INT64_MAX, FLAGS }, \ - { "end", "Timestamp of the first frame that " \ - "should be dropped again", OFFSET(end_time), AV_OPT_TYPE_DURATION, { .i64 = INT64_MAX }, INT64_MIN, INT64_MAX, FLAGS }, \ - { "endi", "Timestamp of the first frame that " \ - "should be dropped again", OFFSET(end_time), AV_OPT_TYPE_DURATION, { .i64 = INT64_MAX }, INT64_MIN, INT64_MAX, FLAGS }, \ - { "start_pts", "Timestamp of the first frame that should be " \ - " passed", OFFSET(start_pts), AV_OPT_TYPE_INT64, { .i64 = AV_NOPTS_VALUE }, INT64_MIN, INT64_MAX, FLAGS }, \ - { "end_pts", "Timestamp of the first frame that should be " \ - "dropped again", OFFSET(end_pts), AV_OPT_TYPE_INT64, { .i64 = AV_NOPTS_VALUE }, INT64_MIN, INT64_MAX, FLAGS }, \ - { "duration", "Maximum duration of the output", OFFSET(duration), AV_OPT_TYPE_DURATION, { .i64 = 0 }, 0, INT64_MAX, FLAGS }, \ - { "durationi", "Maximum duration of the output", OFFSET(duration), AV_OPT_TYPE_DURATION, { .i64 = 0 }, 0, INT64_MAX, FLAGS }, - - #if CONFIG_TRIM_FILTER static int trim_filter_frame(AVFilterLink *inlink, AVFrame *frame) { @@ -161,7 +123,8 @@ static int trim_filter_frame(AVFilterLink *inlink, AVFrame *frame) if (drop) { s->eof = 1; - ff_avfilter_link_set_out_status(inlink, AVERROR_EOF, AV_NOPTS_VALUE); + ff_inlink_set_status(inlink, AVERROR_EOF); + ff_outlink_set_status(ctx->outputs[0], AVERROR_EOF, frame->pts); goto drop; } } @@ -171,49 +134,12 @@ static int trim_filter_frame(AVFilterLink *inlink, AVFrame *frame) return ff_filter_frame(ctx->outputs[0], frame); drop: + if (!s->eof) + ff_filter_set_ready(ctx, 100); s->nb_frames++; av_frame_free(&frame); return 0; } - -#define FLAGS AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_FILTERING_PARAM -static const AVOption trim_options[] = { - COMMON_OPTS - { "start_frame", "Number of the first frame that should be passed " - "to the output", OFFSET(start_frame), AV_OPT_TYPE_INT64, { .i64 = -1 }, -1, INT64_MAX, FLAGS }, - { "end_frame", "Number of the first frame that should be dropped " - "again", OFFSET(end_frame), AV_OPT_TYPE_INT64, { .i64 = INT64_MAX }, 0, INT64_MAX, FLAGS }, - { NULL } -}; -#undef FLAGS - -AVFILTER_DEFINE_CLASS(trim); - -static const AVFilterPad trim_inputs[] = { - { - .name = "default", - .type = AVMEDIA_TYPE_VIDEO, - .filter_frame = trim_filter_frame, - .config_props = config_input, - }, -}; - -static const AVFilterPad trim_outputs[] = { - { - .name = "default", - .type = AVMEDIA_TYPE_VIDEO, - }, -}; - -const AVFilter ff_vf_trim = { - .name = "trim", - .description = NULL_IF_CONFIG_SMALL("Pick one continuous section from the input, drop the rest."), - .init = init, - .priv_size = sizeof(TrimContext), - .priv_class = &trim_class, - FILTER_INPUTS(trim_inputs), - FILTER_OUTPUTS(trim_outputs), -}; #endif // CONFIG_TRIM_FILTER #if CONFIG_ATRIM_FILTER @@ -290,7 +216,8 @@ static int atrim_filter_frame(AVFilterLink *inlink, AVFrame *frame) if (drop) { s->eof = 1; - ff_avfilter_link_set_out_status(inlink, AVERROR_EOF, AV_NOPTS_VALUE); + ff_inlink_set_status(inlink, AVERROR_EOF); + ff_outlink_set_status(ctx->outputs[0], AVERROR_EOF, frame->pts); goto drop; } } @@ -324,10 +251,131 @@ static int atrim_filter_frame(AVFilterLink *inlink, AVFrame *frame) return ff_filter_frame(ctx->outputs[0], frame); drop: + if (!s->eof) + ff_filter_set_ready(ctx, 100); s->nb_samples += frame->nb_samples; av_frame_free(&frame); return 0; } +#endif // CONFIG_ATRIM_FILTER + +static int config_input(AVFilterLink *inlink) +{ + AVFilterContext *ctx = inlink->dst; + TrimContext *s = ctx->priv; + AVRational tb = (inlink->type == AVMEDIA_TYPE_VIDEO) ? + inlink->time_base : (AVRational){ 1, inlink->sample_rate }; + +#if CONFIG_TRIM_FILTER + if (inlink->type == AVMEDIA_TYPE_VIDEO) + s->filter_frame = trim_filter_frame; +#endif +#if CONFIG_ATRIM_FILTER + if (inlink->type == AVMEDIA_TYPE_AUDIO) + s->filter_frame = atrim_filter_frame; +#endif + if (s->start_time != INT64_MAX) { + int64_t start_pts = av_rescale_q(s->start_time, AV_TIME_BASE_Q, tb); + if (s->start_pts == AV_NOPTS_VALUE || start_pts < s->start_pts) + s->start_pts = start_pts; + } + if (s->end_time != INT64_MAX) { + int64_t end_pts = av_rescale_q(s->end_time, AV_TIME_BASE_Q, tb); + if (s->end_pts == AV_NOPTS_VALUE || end_pts > s->end_pts) + s->end_pts = end_pts; + } + if (s->duration) + s->duration_tb = av_rescale_q(s->duration, AV_TIME_BASE_Q, tb); + + return 0; +} + +static int activate(AVFilterContext *ctx) +{ + TrimContext *s = ctx->priv; + AVFilterLink *inlink = ctx->inputs[0]; + AVFilterLink *outlink = ctx->outputs[0]; + + FF_FILTER_FORWARD_STATUS_BACK(outlink, inlink); + + if (!s->eof && ff_inlink_queued_frames(inlink)) { + AVFrame *frame = NULL; + int ret; + + ret = ff_inlink_consume_frame(inlink, &frame); + if (ret < 0) + return ret; + if (ret > 0) + return s->filter_frame(inlink, frame); + } + + FF_FILTER_FORWARD_STATUS(inlink, outlink); + FF_FILTER_FORWARD_WANTED(outlink, inlink); + + return FFERROR_NOT_READY; +} + +#define OFFSET(x) offsetof(TrimContext, x) +#define COMMON_OPTS \ + { "start", "Timestamp of the first frame that " \ + "should be passed", OFFSET(start_time), AV_OPT_TYPE_DURATION, { .i64 = INT64_MAX }, INT64_MIN, INT64_MAX, FLAGS }, \ + { "starti", "Timestamp of the first frame that " \ + "should be passed", OFFSET(start_time), AV_OPT_TYPE_DURATION, { .i64 = INT64_MAX }, INT64_MIN, INT64_MAX, FLAGS }, \ + { "end", "Timestamp of the first frame that " \ + "should be dropped again", OFFSET(end_time), AV_OPT_TYPE_DURATION, { .i64 = INT64_MAX }, INT64_MIN, INT64_MAX, FLAGS }, \ + { "endi", "Timestamp of the first frame that " \ + "should be dropped again", OFFSET(end_time), AV_OPT_TYPE_DURATION, { .i64 = INT64_MAX }, INT64_MIN, INT64_MAX, FLAGS }, \ + { "start_pts", "Timestamp of the first frame that should be " \ + " passed", OFFSET(start_pts), AV_OPT_TYPE_INT64, { .i64 = AV_NOPTS_VALUE }, INT64_MIN, INT64_MAX, FLAGS }, \ + { "end_pts", "Timestamp of the first frame that should be " \ + "dropped again", OFFSET(end_pts), AV_OPT_TYPE_INT64, { .i64 = AV_NOPTS_VALUE }, INT64_MIN, INT64_MAX, FLAGS }, \ + { "duration", "Maximum duration of the output", OFFSET(duration), AV_OPT_TYPE_DURATION, { .i64 = 0 }, 0, INT64_MAX, FLAGS }, \ + { "durationi", "Maximum duration of the output", OFFSET(duration), AV_OPT_TYPE_DURATION, { .i64 = 0 }, 0, INT64_MAX, FLAGS }, + + +#if CONFIG_TRIM_FILTER + +#define FLAGS AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_FILTERING_PARAM +static const AVOption trim_options[] = { + COMMON_OPTS + { "start_frame", "Number of the first frame that should be passed " + "to the output", OFFSET(start_frame), AV_OPT_TYPE_INT64, { .i64 = -1 }, -1, INT64_MAX, FLAGS }, + { "end_frame", "Number of the first frame that should be dropped " + "again", OFFSET(end_frame), AV_OPT_TYPE_INT64, { .i64 = INT64_MAX }, 0, INT64_MAX, FLAGS }, + { NULL } +}; +#undef FLAGS + +AVFILTER_DEFINE_CLASS(trim); + +static const AVFilterPad trim_inputs[] = { + { + .name = "default", + .type = AVMEDIA_TYPE_VIDEO, + .config_props = config_input, + }, +}; + +static const AVFilterPad trim_outputs[] = { + { + .name = "default", + .type = AVMEDIA_TYPE_VIDEO, + }, +}; + +const AVFilter ff_vf_trim = { + .name = "trim", + .description = NULL_IF_CONFIG_SMALL("Pick one continuous section from the input, drop the rest."), + .init = init, + .activate = activate, + .priv_size = sizeof(TrimContext), + .priv_class = &trim_class, + FILTER_INPUTS(trim_inputs), + FILTER_OUTPUTS(trim_outputs), +}; +#endif // CONFIG_TRIM_FILTER + +#if CONFIG_ATRIM_FILTER #define FLAGS AV_OPT_FLAG_AUDIO_PARAM | AV_OPT_FLAG_FILTERING_PARAM static const AVOption atrim_options[] = { @@ -346,7 +394,6 @@ static const AVFilterPad atrim_inputs[] = { { .name = "default", .type = AVMEDIA_TYPE_AUDIO, - .filter_frame = atrim_filter_frame, .config_props = config_input, }, }; @@ -362,6 +409,7 @@ const AVFilter ff_af_atrim = { .name = "atrim", .description = NULL_IF_CONFIG_SMALL("Pick one continuous section from the input, drop the rest."), .init = init, + .activate = activate, .priv_size = sizeof(TrimContext), .priv_class = &atrim_class, .flags = AVFILTER_FLAG_METADATA_ONLY, From e1b6ecd20a01c5d902cd89c034b960ddadea778e Mon Sep 17 00:00:00 2001 From: Shiyou Yin Date: Thu, 25 May 2023 15:24:26 +0800 Subject: [PATCH 1173/2172] avcodec/la: add LSX optimization for h264 idct. loongson_asm.S is LoongArch asm optimization helper. Add functions: ff_h264_idct_add_8_lsx ff_h264_idct8_add_8_lsx ff_h264_idct_dc_add_8_lsx ff_h264_idct8_dc_add_8_lsx ff_h264_idct_add16_8_lsx ff_h264_idct8_add4_8_lsx ff_h264_idct_add8_8_lsx ff_h264_idct_add8_422_8_lsx ff_h264_idct_add16_intra_8_lsx ff_h264_luma_dc_dequant_idct_8_lsx Replaced function(LSX is sufficient for these functions): ff_h264_idct_add_lasx ff_h264_idct4x4_addblk_dc_lasx ff_h264_idct_add16_lasx ff_h264_idct8_add4_lasx ff_h264_idct_add8_lasx ff_h264_idct_add8_422_lasx ff_h264_idct_add16_intra_lasx ff_h264_deq_idct_luma_dc_lasx Renamed functions: ff_h264_idct8_addblk_lasx ==> ff_h264_idct8_add_8_lasx ff_h264_idct8_dc_addblk_lasx ==> ff_h264_idct8_dc_add_8_lasx ./configure --disable-lasx ffmpeg -i 1_h264_1080p_30fps_3Mbps.mp4 -f rawvideo -y /dev/null -an before: 155fps after: 161fps Reviewed-by: Shiyou Yin Signed-off-by: Michael Niedermayer --- libavcodec/loongarch/Makefile | 3 +- libavcodec/loongarch/h264_deblock_lasx.c | 2 +- libavcodec/loongarch/h264dsp_init_loongarch.c | 39 +- libavcodec/loongarch/h264dsp_lasx.c | 2 +- .../{h264dsp_lasx.h => h264dsp_loongarch.h} | 60 +- libavcodec/loongarch/h264idct.S | 658 ++++++++++++ libavcodec/loongarch/h264idct_lasx.c | 498 --------- libavcodec/loongarch/h264idct_loongarch.c | 184 ++++ libavcodec/loongarch/loongson_asm.S | 945 ++++++++++++++++++ 9 files changed, 1848 insertions(+), 543 deletions(-) rename libavcodec/loongarch/{h264dsp_lasx.h => h264dsp_loongarch.h} (68%) create mode 100644 libavcodec/loongarch/h264idct.S delete mode 100644 libavcodec/loongarch/h264idct_lasx.c create mode 100644 libavcodec/loongarch/h264idct_loongarch.c create mode 100644 libavcodec/loongarch/loongson_asm.S diff --git a/libavcodec/loongarch/Makefile b/libavcodec/loongarch/Makefile index c1b5de5c443..34ebbbe133f 100644 --- a/libavcodec/loongarch/Makefile +++ b/libavcodec/loongarch/Makefile @@ -12,7 +12,6 @@ OBJS-$(CONFIG_HEVC_DECODER) += loongarch/hevcdsp_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 @@ -31,3 +30,5 @@ LSX-OBJS-$(CONFIG_HEVC_DECODER) += loongarch/hevcdsp_lsx.o \ loongarch/hevc_mc_bi_lsx.o \ loongarch/hevc_mc_uni_lsx.o \ loongarch/hevc_mc_uniw_lsx.o +LSX-OBJS-$(CONFIG_H264DSP) += loongarch/h264idct.o \ + loongarch/h264idct_loongarch.o diff --git a/libavcodec/loongarch/h264_deblock_lasx.c b/libavcodec/loongarch/h264_deblock_lasx.c index c89bea9a846..eead931dcf5 100644 --- a/libavcodec/loongarch/h264_deblock_lasx.c +++ b/libavcodec/loongarch/h264_deblock_lasx.c @@ -20,7 +20,7 @@ */ #include "libavcodec/bit_depth_template.c" -#include "h264dsp_lasx.h" +#include "h264dsp_loongarch.h" #include "libavutil/loongarch/loongson_intrinsics.h" #define H264_LOOP_FILTER_STRENGTH_ITERATION_LASX(edges, step, mask_mv, dir, \ diff --git a/libavcodec/loongarch/h264dsp_init_loongarch.c b/libavcodec/loongarch/h264dsp_init_loongarch.c index 37633c3e51c..cb07deb398a 100644 --- a/libavcodec/loongarch/h264dsp_init_loongarch.c +++ b/libavcodec/loongarch/h264dsp_init_loongarch.c @@ -21,13 +21,32 @@ */ #include "libavutil/loongarch/cpu.h" -#include "h264dsp_lasx.h" +#include "h264dsp_loongarch.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_lsx(cpu_flags)) { + if (bit_depth == 8) { + c->h264_idct_add = ff_h264_idct_add_8_lsx; + c->h264_idct8_add = ff_h264_idct8_add_8_lsx; + c->h264_idct_dc_add = ff_h264_idct_dc_add_8_lsx; + c->h264_idct8_dc_add = ff_h264_idct8_dc_add_8_lsx; + + if (chroma_format_idc <= 1) + c->h264_idct_add8 = ff_h264_idct_add8_8_lsx; + else + c->h264_idct_add8 = ff_h264_idct_add8_422_8_lsx; + + c->h264_idct_add16 = ff_h264_idct_add16_8_lsx; + c->h264_idct8_add4 = ff_h264_idct8_add4_8_lsx; + c->h264_luma_dc_dequant_idct = ff_h264_luma_dc_dequant_idct_8_lsx; + c->h264_idct_add16intra = ff_h264_idct_add16_intra_8_lsx; + } + } +#if HAVE_LASX if (have_lasx(cpu_flags)) { if (chroma_format_idc <= 1) c->h264_loop_filter_strength = ff_h264_loop_filter_strength_lasx; @@ -56,20 +75,10 @@ av_cold void ff_h264dsp_init_loongarch(H264DSPContext *c, const int bit_depth, 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; + c->h264_idct8_add = ff_h264_idct8_add_8_lasx; + c->h264_idct8_dc_add = ff_h264_idct8_dc_add_8_lasx; + c->h264_idct8_add4 = ff_h264_idct8_add4_8_lasx; } } +#endif // #if HAVE_LASX } diff --git a/libavcodec/loongarch/h264dsp_lasx.c b/libavcodec/loongarch/h264dsp_lasx.c index 7fd4cedf7ef..7b2b8ff0f05 100644 --- a/libavcodec/loongarch/h264dsp_lasx.c +++ b/libavcodec/loongarch/h264dsp_lasx.c @@ -23,7 +23,7 @@ */ #include "libavutil/loongarch/loongson_intrinsics.h" -#include "h264dsp_lasx.h" +#include "h264dsp_loongarch.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, \ diff --git a/libavcodec/loongarch/h264dsp_lasx.h b/libavcodec/loongarch/h264dsp_loongarch.h similarity index 68% rename from libavcodec/loongarch/h264dsp_lasx.h rename to libavcodec/loongarch/h264dsp_loongarch.h index 4cf813750bb..28dca2b537c 100644 --- a/libavcodec/loongarch/h264dsp_lasx.h +++ b/libavcodec/loongarch/h264dsp_loongarch.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Loongson Technology Corporation Limited + * Copyright (c) 2023 Loongson Technology Corporation Limited * Contributed by Shiyou Yin * Xiwei Gu * @@ -20,11 +20,34 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#ifndef AVCODEC_LOONGARCH_H264DSP_LASX_H -#define AVCODEC_LOONGARCH_H264DSP_LASX_H +#ifndef AVCODEC_LOONGARCH_H264DSP_LOONGARCH_H +#define AVCODEC_LOONGARCH_H264DSP_LOONGARCH_H #include "libavcodec/h264dec.h" +#include "config.h" +void ff_h264_idct_add_8_lsx(uint8_t *dst, int16_t *src, int dst_stride); +void ff_h264_idct8_add_8_lsx(uint8_t *dst, int16_t *src, int dst_stride); +void ff_h264_idct_dc_add_8_lsx(uint8_t *dst, int16_t *src, int dst_stride); +void ff_h264_idct8_dc_add_8_lsx(uint8_t *dst, int16_t *src, int dst_stride); +void ff_h264_luma_dc_dequant_idct_8_lsx(int16_t *_output, int16_t *_input, int qmul); +void ff_h264_idct_add16_8_lsx(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_8_lsx(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_8_lsx(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_8_lsx(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_8_lsx(uint8_t *dst, const int32_t *blk_offset, + int16_t *block, int32_t dst_stride, + const uint8_t nzc[15 * 8]); + +#if HAVE_LASX 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, @@ -65,33 +88,16 @@ 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, +void ff_h264_idct8_add_8_lasx(uint8_t *dst, int16_t *src, int32_t dst_stride); +void ff_h264_idct8_dc_add_8_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); - +void ff_h264_idct8_add4_8_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_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 // #if HAVE_LASX -#endif // #ifndef AVCODEC_LOONGARCH_H264DSP_LASX_H +#endif // #ifndef AVCODEC_LOONGARCH_H264DSP_LOONGARCH_H diff --git a/libavcodec/loongarch/h264idct.S b/libavcodec/loongarch/h264idct.S new file mode 100644 index 00000000000..f504cfb7148 --- /dev/null +++ b/libavcodec/loongarch/h264idct.S @@ -0,0 +1,658 @@ +/* + * Loongson LASX optimized h264idct + * + * Copyright (c) 2023 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 "loongson_asm.S" + +/* + * #define FUNC2(a, b, c) FUNC3(a, b, c) + * #define FUNCC(a) FUNC2(a, BIT_DEPTH, _c) + * void FUNCC(ff_h264_idct_add)(uint8_t *_dst, int16_t *_block, int stride) + * LSX optimization is enough for this function. + */ +function ff_h264_idct_add_8_lsx + fld.d f0, a1, 0 + fld.d f1, a1, 8 + fld.d f2, a1, 16 + fld.d f3, a1, 24 + vxor.v vr7, vr7, vr7 + add.d t2, a2, a2 + add.d t3, t2, a2 + vst vr7, a1, 0 + vst vr7, a1, 16 + + vadd.h vr4, vr0, vr2 + vsub.h vr5, vr0, vr2 + vsrai.h vr6, vr1, 1 + vsrai.h vr7, vr3, 1 + vsub.h vr6, vr6, vr3 + vadd.h vr7, vr1, vr7 + LSX_BUTTERFLY_4_H vr4, vr5, vr6, vr7, vr0, vr1, vr2, vr3 + LSX_TRANSPOSE4x4_H vr0, vr1, vr2, vr3, vr0, vr1, vr2, vr3, vr4, vr5 + vadd.h vr4, vr0, vr2 + vsub.h vr5, vr0, vr2 + vsrai.h vr6, vr1, 1 + vsrai.h vr7, vr3, 1 + vsub.h vr6, vr6, vr3 + vadd.h vr7, vr1, vr7 + LSX_BUTTERFLY_4_H vr4, vr5, vr6, vr7, vr0, vr1, vr2, vr3 + + fld.s f4, a0, 0 + fldx.s f5, a0, a2 + fldx.s f6, a0, t2 + fldx.s f7, a0, t3 + + vsrari.h vr0, vr0, 6 + vsrari.h vr1, vr1, 6 + vsrari.h vr2, vr2, 6 + vsrari.h vr3, vr3, 6 + + vsllwil.hu.bu vr4, vr4, 0 + vsllwil.hu.bu vr5, vr5, 0 + vsllwil.hu.bu vr6, vr6, 0 + vsllwil.hu.bu vr7, vr7, 0 + vadd.h vr0, vr0, vr4 + vadd.h vr1, vr1, vr5 + vadd.h vr2, vr2, vr6 + vadd.h vr3, vr3, vr7 + vssrarni.bu.h vr1, vr0, 0 + vssrarni.bu.h vr3, vr2, 0 + + vbsrl.v vr0, vr1, 8 + vbsrl.v vr2, vr3, 8 + fst.s f1, a0, 0 + fstx.s f0, a0, a2 + fstx.s f3, a0, t2 + fstx.s f2, a0, t3 +endfunc + +/* + * #define FUNC2(a, b, c) FUNC3(a, b, c) + * #define FUNCC(a) FUNC2(a, BIT_DEPTH, _c) + * void FUNCC(ff_h264_idct8_add)(uint8_t *_dst, int16_t *_block, int stride) + */ +function ff_h264_idct8_add_8_lsx + ld.h t0, a1, 0 + add.d t2, a2, a2 + add.d t3, t2, a2 + add.d t4, t3, a2 + add.d t5, t4, a2 + add.d t6, t5, a2 + add.d t7, t6, a2 + addi.w t0, t0, 32 + st.h t0, a1, 0 + + vld vr0, a1, 0 + vld vr1, a1, 16 + vld vr2, a1, 32 + vld vr3, a1, 48 + vld vr4, a1, 64 + vld vr5, a1, 80 + vld vr6, a1, 96 + vld vr7, a1, 112 + vxor.v vr8, vr8, vr8 + vst vr8, a1, 0 + vst vr8, a1, 16 + vst vr8, a1, 32 + vst vr8, a1, 48 + vst vr8, a1, 64 + vst vr8, a1, 80 + vst vr8, a1, 96 + vst vr8, a1, 112 + + vadd.h vr18, vr0, vr4 + vsub.h vr19, vr0, vr4 + vsrai.h vr20, vr2, 1 + vsrai.h vr21, vr6, 1 + vsub.h vr20, vr20, vr6 + vadd.h vr21, vr21, vr2 + LSX_BUTTERFLY_4_H vr18, vr19, vr20, vr21, vr10, vr12, vr14, vr16 + vsrai.h vr11, vr7, 1 + vsrai.h vr13, vr3, 1 + vsrai.h vr15, vr5, 1 + vsrai.h vr17, vr1, 1 + vsub.h vr11, vr5, vr11 + vsub.h vr13, vr7, vr13 + vadd.h vr15, vr7, vr15 + vadd.h vr17, vr5, vr17 + vsub.h vr11, vr11, vr7 + vsub.h vr13, vr13, vr3 + vadd.h vr15, vr15, vr5 + vadd.h vr17, vr17, vr1 + vsub.h vr11, vr11, vr3 + vadd.h vr13, vr13, vr1 + vsub.h vr15, vr15, vr1 + vadd.h vr17, vr17, vr3 + vsrai.h vr18, vr11, 2 + vsrai.h vr19, vr13, 2 + vsrai.h vr20, vr15, 2 + vsrai.h vr21, vr17, 2 + vadd.h vr11, vr11, vr21 + vadd.h vr13, vr13, vr20 + vsub.h vr15, vr19, vr15 + vsub.h vr17, vr17, vr18 + LSX_BUTTERFLY_8_H vr10, vr16, vr12, vr14, vr13, vr15, vr11, vr17, \ + vr0, vr3, vr1, vr2, vr5, vr6, vr4, vr7 + + LSX_TRANSPOSE8x8_H vr0, vr1, vr2, vr3, vr4, vr5, vr6, vr7, \ + vr0, vr1, vr2, vr3, vr4, vr5, vr6, vr7, \ + vr10, vr11, vr12, vr13, vr14, vr15, vr16, vr17 + vexth.w.h vr20, vr0 + vexth.w.h vr21, vr1 + vexth.w.h vr22, vr2 + vexth.w.h vr23, vr3 + vexth.w.h vr8, vr4 + vexth.w.h vr9, vr5 + vexth.w.h vr18, vr6 + vexth.w.h vr19, vr7 + vsllwil.w.h vr0, vr0, 0 + vsllwil.w.h vr1, vr1, 0 + vsllwil.w.h vr2, vr2, 0 + vsllwil.w.h vr3, vr3, 0 + vsllwil.w.h vr4, vr4, 0 + vsllwil.w.h vr5, vr5, 0 + vsllwil.w.h vr6, vr6, 0 + vsllwil.w.h vr7, vr7, 0 + + vadd.w vr11, vr0, vr4 + vsub.w vr13, vr0, vr4 + vsrai.w vr15, vr2, 1 + vsrai.w vr17, vr6, 1 + vsub.w vr15, vr15, vr6 + vadd.w vr17, vr17, vr2 + LSX_BUTTERFLY_4_W vr11, vr13, vr15, vr17, vr10, vr12, vr14, vr16 + vsrai.w vr11, vr7, 1 + vsrai.w vr13, vr3, 1 + vsrai.w vr15, vr5, 1 + vsrai.w vr17, vr1, 1 + vsub.w vr11, vr5, vr11 + vsub.w vr13, vr7, vr13 + vadd.w vr15, vr7, vr15 + vadd.w vr17, vr5, vr17 + vsub.w vr11, vr11, vr7 + vsub.w vr13, vr13, vr3 + vadd.w vr15, vr15, vr5 + vadd.w vr17, vr17, vr1 + vsub.w vr11, vr11, vr3 + vadd.w vr13, vr13, vr1 + vsub.w vr15, vr15, vr1 + vadd.w vr17, vr17, vr3 + vsrai.w vr0, vr11, 2 + vsrai.w vr1, vr13, 2 + vsrai.w vr2, vr15, 2 + vsrai.w vr3, vr17, 2 + vadd.w vr11, vr11, vr3 + vadd.w vr13, vr13, vr2 + vsub.w vr15, vr1, vr15 + vsub.w vr17, vr17, vr0 + LSX_BUTTERFLY_8_W vr10, vr12, vr14, vr16, vr11, vr13, vr15, vr17, \ + vr0, vr1, vr2, vr3, vr4, vr5, vr6, vr7 + + vadd.w vr11, vr20, vr8 + vsub.w vr13, vr20, vr8 + vsrai.w vr15, vr22, 1 + vsrai.w vr17, vr18, 1 + vsub.w vr15, vr15, vr18 + vadd.w vr17, vr17, vr22 + LSX_BUTTERFLY_4_W vr11, vr13, vr15, vr17, vr10, vr12, vr14, vr16 + vsrai.w vr11, vr19, 1 + vsrai.w vr13, vr23, 1 + vsrai.w vr15, vr9, 1 + vsrai.w vr17, vr21, 1 + vsub.w vr11, vr9, vr11 + vsub.w vr13, vr19, vr13 + vadd.w vr15, vr19, vr15 + vadd.w vr17, vr9, vr17 + vsub.w vr11, vr11, vr19 + vsub.w vr13, vr13, vr23 + vadd.w vr15, vr15, vr9 + vadd.w vr17, vr17, vr21 + vsub.w vr11, vr11, vr23 + vadd.w vr13, vr13, vr21 + vsub.w vr15, vr15, vr21 + vadd.w vr17, vr17, vr23 + vsrai.w vr20, vr11, 2 + vsrai.w vr21, vr13, 2 + vsrai.w vr22, vr15, 2 + vsrai.w vr23, vr17, 2 + vadd.w vr11, vr11, vr23 + vadd.w vr13, vr13, vr22 + vsub.w vr15, vr21, vr15 + vsub.w vr17, vr17, vr20 + LSX_BUTTERFLY_8_W vr10, vr12, vr14, vr16, vr11, vr13, vr15, vr17, \ + vr20, vr21, vr22, vr23, vr8, vr9, vr18, vr19 + + vld vr10, a0, 0 + vldx vr11, a0, a2 + vldx vr12, a0, t2 + vldx vr13, a0, t3 + vldx vr14, a0, t4 + vldx vr15, a0, t5 + vldx vr16, a0, t6 + vldx vr17, a0, t7 + vsrani.h.w vr20, vr0, 6 + vsrani.h.w vr21, vr1, 6 + vsrani.h.w vr22, vr2, 6 + vsrani.h.w vr23, vr3, 6 + vsrani.h.w vr8, vr4, 6 + vsrani.h.w vr9, vr5, 6 + vsrani.h.w vr18, vr6, 6 + vsrani.h.w vr19, vr7, 6 + vsllwil.hu.bu vr10, vr10, 0 + vsllwil.hu.bu vr11, vr11, 0 + vsllwil.hu.bu vr12, vr12, 0 + vsllwil.hu.bu vr13, vr13, 0 + vsllwil.hu.bu vr14, vr14, 0 + vsllwil.hu.bu vr15, vr15, 0 + vsllwil.hu.bu vr16, vr16, 0 + vsllwil.hu.bu vr17, vr17, 0 + + vadd.h vr0, vr20, vr10 + vadd.h vr1, vr21, vr11 + vadd.h vr2, vr22, vr12 + vadd.h vr3, vr23, vr13 + vadd.h vr4, vr8, vr14 + vadd.h vr5, vr9, vr15 + vadd.h vr6, vr18, vr16 + vadd.h vr7, vr19, vr17 + vssrarni.bu.h vr1, vr0, 0 + vssrarni.bu.h vr3, vr2, 0 + vssrarni.bu.h vr5, vr4, 0 + vssrarni.bu.h vr7, vr6, 0 + vbsrl.v vr0, vr1, 8 + vbsrl.v vr2, vr3, 8 + vbsrl.v vr4, vr5, 8 + vbsrl.v vr6, vr7, 8 + fst.d f1, a0, 0 + fstx.d f0, a0, a2 + fstx.d f3, a0, t2 + fstx.d f2, a0, t3 + fstx.d f5, a0, t4 + fstx.d f4, a0, t5 + fstx.d f7, a0, t6 + fstx.d f6, a0, t7 +endfunc + +/* + * #define FUNC2(a, b, c) FUNC3(a, b, c) + * #define FUNCC(a) FUNC2(a, BIT_DEPTH, _c) + * void FUNCC(ff_h264_idct8_add)(uint8_t *_dst, int16_t *_block, int stride) + */ +function ff_h264_idct8_add_8_lasx + ld.h t0, a1, 0 + add.d t2, a2, a2 + add.d t3, t2, a2 + add.d t4, t3, a2 + add.d t5, t4, a2 + add.d t6, t5, a2 + add.d t7, t6, a2 + addi.w t0, t0, 32 + st.h t0, a1, 0 + + vld vr0, a1, 0 + vld vr1, a1, 16 + vld vr2, a1, 32 + vld vr3, a1, 48 + vld vr4, a1, 64 + vld vr5, a1, 80 + vld vr6, a1, 96 + vld vr7, a1, 112 + xvxor.v xr8, xr8, xr8 + xvst xr8, a1, 0 + xvst xr8, a1, 32 + xvst xr8, a1, 64 + xvst xr8, a1, 96 + + vadd.h vr18, vr0, vr4 + vsub.h vr19, vr0, vr4 + vsrai.h vr20, vr2, 1 + vsrai.h vr21, vr6, 1 + vsub.h vr20, vr20, vr6 + vadd.h vr21, vr21, vr2 + LSX_BUTTERFLY_4_H vr18, vr19, vr20, vr21, vr10, vr12, vr14, vr16 + vsrai.h vr11, vr7, 1 + vsrai.h vr13, vr3, 1 + vsrai.h vr15, vr5, 1 + vsrai.h vr17, vr1, 1 + vsub.h vr11, vr5, vr11 + vsub.h vr13, vr7, vr13 + vadd.h vr15, vr7, vr15 + vadd.h vr17, vr5, vr17 + vsub.h vr11, vr11, vr7 + vsub.h vr13, vr13, vr3 + vadd.h vr15, vr15, vr5 + vadd.h vr17, vr17, vr1 + vsub.h vr11, vr11, vr3 + vadd.h vr13, vr13, vr1 + vsub.h vr15, vr15, vr1 + vadd.h vr17, vr17, vr3 + vsrai.h vr18, vr11, 2 + vsrai.h vr19, vr13, 2 + vsrai.h vr20, vr15, 2 + vsrai.h vr21, vr17, 2 + vadd.h vr11, vr11, vr21 + vadd.h vr13, vr13, vr20 + vsub.h vr15, vr19, vr15 + vsub.h vr17, vr17, vr18 + LSX_BUTTERFLY_8_H vr10, vr16, vr12, vr14, vr13, vr15, vr11, vr17, \ + vr0, vr3, vr1, vr2, vr5, vr6, vr4, vr7 + + LSX_TRANSPOSE8x8_H vr0, vr1, vr2, vr3, vr4, vr5, vr6, vr7, \ + vr0, vr1, vr2, vr3, vr4, vr5, vr6, vr7, \ + vr10, vr11, vr12, vr13, vr14, vr15, vr16, vr17 + vext2xv.w.h xr0, xr0 + vext2xv.w.h xr1, xr1 + vext2xv.w.h xr2, xr2 + vext2xv.w.h xr3, xr3 + vext2xv.w.h xr4, xr4 + vext2xv.w.h xr5, xr5 + vext2xv.w.h xr6, xr6 + vext2xv.w.h xr7, xr7 + + xvadd.w xr11, xr0, xr4 + xvsub.w xr13, xr0, xr4 + xvsrai.w xr15, xr2, 1 + xvsrai.w xr17, xr6, 1 + xvsub.w xr15, xr15, xr6 + xvadd.w xr17, xr17, xr2 + LASX_BUTTERFLY_4_W xr11, xr13, xr15, xr17, xr10, xr12, xr14, xr16 + xvsrai.w xr11, xr7, 1 + xvsrai.w xr13, xr3, 1 + xvsrai.w xr15, xr5, 1 + xvsrai.w xr17, xr1, 1 + xvsub.w xr11, xr5, xr11 + xvsub.w xr13, xr7, xr13 + xvadd.w xr15, xr7, xr15 + xvadd.w xr17, xr5, xr17 + xvsub.w xr11, xr11, xr7 + xvsub.w xr13, xr13, xr3 + xvadd.w xr15, xr15, xr5 + xvadd.w xr17, xr17, xr1 + xvsub.w xr11, xr11, xr3 + xvadd.w xr13, xr13, xr1 + xvsub.w xr15, xr15, xr1 + xvadd.w xr17, xr17, xr3 + xvsrai.w xr0, xr11, 2 + xvsrai.w xr1, xr13, 2 + xvsrai.w xr2, xr15, 2 + xvsrai.w xr3, xr17, 2 + xvadd.w xr11, xr11, xr3 + xvadd.w xr13, xr13, xr2 + xvsub.w xr15, xr1, xr15 + xvsub.w xr17, xr17, xr0 + LASX_BUTTERFLY_8_W xr10, xr12, xr14, xr16, xr11, xr13, xr15, xr17, \ + xr0, xr1, xr2, xr3, xr4, xr5, xr6, xr7 + + vld vr10, a0, 0 + vldx vr11, a0, a2 + vldx vr12, a0, t2 + vldx vr13, a0, t3 + vldx vr14, a0, t4 + vldx vr15, a0, t5 + vldx vr16, a0, t6 + vldx vr17, a0, t7 + xvldi xr8, 0x806 //"xvldi.w xr8 6" + xvsran.h.w xr0, xr0, xr8 + xvsran.h.w xr1, xr1, xr8 + xvsran.h.w xr2, xr2, xr8 + xvsran.h.w xr3, xr3, xr8 + xvsran.h.w xr4, xr4, xr8 + xvsran.h.w xr5, xr5, xr8 + xvsran.h.w xr6, xr6, xr8 + xvsran.h.w xr7, xr7, xr8 + xvpermi.d xr0, xr0, 0x08 + xvpermi.d xr1, xr1, 0x08 + xvpermi.d xr2, xr2, 0x08 + xvpermi.d xr3, xr3, 0x08 + xvpermi.d xr4, xr4, 0x08 + xvpermi.d xr5, xr5, 0x08 + xvpermi.d xr6, xr6, 0x08 + xvpermi.d xr7, xr7, 0x08 + + vsllwil.hu.bu vr10, vr10, 0 + vsllwil.hu.bu vr11, vr11, 0 + vsllwil.hu.bu vr12, vr12, 0 + vsllwil.hu.bu vr13, vr13, 0 + vsllwil.hu.bu vr14, vr14, 0 + vsllwil.hu.bu vr15, vr15, 0 + vsllwil.hu.bu vr16, vr16, 0 + vsllwil.hu.bu vr17, vr17, 0 + + vadd.h vr0, vr0, vr10 + vadd.h vr1, vr1, vr11 + vadd.h vr2, vr2, vr12 + vadd.h vr3, vr3, vr13 + vadd.h vr4, vr4, vr14 + vadd.h vr5, vr5, vr15 + vadd.h vr6, vr6, vr16 + vadd.h vr7, vr7, vr17 + vssrarni.bu.h vr1, vr0, 0 + vssrarni.bu.h vr3, vr2, 0 + vssrarni.bu.h vr5, vr4, 0 + vssrarni.bu.h vr7, vr6, 0 + vbsrl.v vr0, vr1, 8 + vbsrl.v vr2, vr3, 8 + vbsrl.v vr4, vr5, 8 + vbsrl.v vr6, vr7, 8 + fst.d f1, a0, 0 + fstx.d f0, a0, a2 + fstx.d f3, a0, t2 + fstx.d f2, a0, t3 + fstx.d f5, a0, t4 + fstx.d f4, a0, t5 + fstx.d f7, a0, t6 + fstx.d f6, a0, t7 +endfunc + +/* + * #define FUNC2(a, b, c) FUNC3(a, b, c) + * #define FUNCC(a) FUNC2(a, BIT_DEPTH, _c) + * void FUNCC(ff_h264_idct_dc_add)(uint8_t *_dst, int16_t *_block, int stride) + * LSX optimization is enough for this function. + */ +function ff_h264_idct_dc_add_8_lsx + vldrepl.h vr4, a1, 0 + add.d t2, a2, a2 + add.d t3, t2, a2 + fld.s f0, a0, 0 + fldx.s f1, a0, a2 + fldx.s f2, a0, t2 + fldx.s f3, a0, t3 + st.h zero, a1, 0 + + vsrari.h vr4, vr4, 6 + vilvl.w vr0, vr1, vr0 + vilvl.w vr1, vr3, vr2 + vsllwil.hu.bu vr0, vr0, 0 + vsllwil.hu.bu vr1, vr1, 0 + vadd.h vr0, vr0, vr4 + vadd.h vr1, vr1, vr4 + vssrarni.bu.h vr1, vr0, 0 + + vbsrl.v vr2, vr1, 4 + vbsrl.v vr3, vr1, 8 + vbsrl.v vr4, vr1, 12 + fst.s f1, a0, 0 + fstx.s f2, a0, a2 + fstx.s f3, a0, t2 + fstx.s f4, a0, t3 +endfunc + +/* + * #define FUNC2(a, b, c) FUNC3(a, b, c) + * #define FUNCC(a) FUNC2(a, BIT_DEPTH, _c) + * void FUNCC(ff_h264_idct8_dc_add)(uint8_t *_dst, int16_t *_block, int stride) + */ +function ff_h264_idct8_dc_add_8_lsx + vldrepl.h vr8, a1, 0 + add.d t2, a2, a2 + add.d t3, t2, a2 + add.d t4, t3, a2 + add.d t5, t4, a2 + add.d t6, t5, a2 + add.d t7, t6, a2 + + fld.d f0, a0, 0 + fldx.d f1, a0, a2 + fldx.d f2, a0, t2 + fldx.d f3, a0, t3 + fldx.d f4, a0, t4 + fldx.d f5, a0, t5 + fldx.d f6, a0, t6 + fldx.d f7, a0, t7 + st.h zero, a1, 0 + + vsrari.h vr8, vr8, 6 + vsllwil.hu.bu vr0, vr0, 0 + vsllwil.hu.bu vr1, vr1, 0 + vsllwil.hu.bu vr2, vr2, 0 + vsllwil.hu.bu vr3, vr3, 0 + vsllwil.hu.bu vr4, vr4, 0 + vsllwil.hu.bu vr5, vr5, 0 + vsllwil.hu.bu vr6, vr6, 0 + vsllwil.hu.bu vr7, vr7, 0 + vadd.h vr0, vr0, vr8 + vadd.h vr1, vr1, vr8 + vadd.h vr2, vr2, vr8 + vadd.h vr3, vr3, vr8 + vadd.h vr4, vr4, vr8 + vadd.h vr5, vr5, vr8 + vadd.h vr6, vr6, vr8 + vadd.h vr7, vr7, vr8 + vssrarni.bu.h vr1, vr0, 0 + vssrarni.bu.h vr3, vr2, 0 + vssrarni.bu.h vr5, vr4, 0 + vssrarni.bu.h vr7, vr6, 0 + + vbsrl.v vr0, vr1, 8 + vbsrl.v vr2, vr3, 8 + vbsrl.v vr4, vr5, 8 + vbsrl.v vr6, vr7, 8 + fst.d f1, a0, 0 + fstx.d f0, a0, a2 + fstx.d f3, a0, t2 + fstx.d f2, a0, t3 + fstx.d f5, a0, t4 + fstx.d f4, a0, t5 + fstx.d f7, a0, t6 + fstx.d f6, a0, t7 +endfunc +function ff_h264_idct8_dc_add_8_lasx + xvldrepl.h xr8, a1, 0 + add.d t2, a2, a2 + add.d t3, t2, a2 + add.d t4, t3, a2 + add.d t5, t4, a2 + add.d t6, t5, a2 + add.d t7, t6, a2 + + fld.d f0, a0, 0 + fldx.d f1, a0, a2 + fldx.d f2, a0, t2 + fldx.d f3, a0, t3 + fldx.d f4, a0, t4 + fldx.d f5, a0, t5 + fldx.d f6, a0, t6 + fldx.d f7, a0, t7 + st.h zero, a1, 0 + + xvsrari.h xr8, xr8, 6 + xvpermi.q xr1, xr0, 0x20 + xvpermi.q xr3, xr2, 0x20 + xvpermi.q xr5, xr4, 0x20 + xvpermi.q xr7, xr6, 0x20 + xvsllwil.hu.bu xr1, xr1, 0 + xvsllwil.hu.bu xr3, xr3, 0 + xvsllwil.hu.bu xr5, xr5, 0 + xvsllwil.hu.bu xr7, xr7, 0 + xvadd.h xr1, xr1, xr8 + xvadd.h xr3, xr3, xr8 + xvadd.h xr5, xr5, xr8 + xvadd.h xr7, xr7, xr8 + + xvssrarni.bu.h xr3, xr1, 0 + xvssrarni.bu.h xr7, xr5, 0 + + xvpermi.q xr1, xr3, 0x11 + xvpermi.q xr5, xr7, 0x11 + xvbsrl.v xr0, xr1, 8 + xvbsrl.v xr2, xr3, 8 + xvbsrl.v xr4, xr5, 8 + xvbsrl.v xr6, xr7, 8 + + fst.d f3, a0, 0 + fstx.d f1, a0, a2 + fstx.d f2, a0, t2 + fstx.d f0, a0, t3 + fstx.d f7, a0, t4 + fstx.d f5, a0, t5 + fstx.d f6, a0, t6 + fstx.d f4, a0, t7 +endfunc + +/** + * IDCT transforms the 16 dc values and dequantizes them. + * @param qmul quantization parameter + * void FUNCC(ff_h264_luma_dc_dequant_idct)(int16_t *_output, int16_t *_input, int qmul){ + * LSX optimization is enough for this function. + */ +function ff_h264_luma_dc_dequant_idct_8_lsx + vld vr0, a1, 0 + vld vr1, a1, 8 + vld vr2, a1, 16 + vld vr3, a1, 24 + vreplgr2vr.w vr8, a2 + LSX_TRANSPOSE4x4_H vr0, vr1, vr2, vr3, vr4, vr5, vr6, vr7, vr9, vr10 + LSX_BUTTERFLY_4_H vr4, vr6, vr7, vr5, vr0, vr3, vr2, vr1 + LSX_BUTTERFLY_4_H vr0, vr1, vr2, vr3, vr4, vr7, vr6, vr5 + LSX_TRANSPOSE4x4_H vr4, vr5, vr6, vr7, vr0, vr1, vr2, vr3, vr9, vr10 + LSX_BUTTERFLY_4_H vr0, vr1, vr3, vr2, vr4, vr7, vr6, vr5 + LSX_BUTTERFLY_4_H vr4, vr5, vr6, vr7, vr0, vr1, vr2, vr3 + vsllwil.w.h vr0, vr0, 0 + vsllwil.w.h vr1, vr1, 0 + vsllwil.w.h vr2, vr2, 0 + vsllwil.w.h vr3, vr3, 0 + vmul.w vr0, vr0, vr8 + vmul.w vr1, vr1, vr8 + vmul.w vr2, vr2, vr8 + vmul.w vr3, vr3, vr8 + vsrarni.h.w vr1, vr0, 8 + vsrarni.h.w vr3, vr2, 8 + + vstelm.h vr1, a0, 0, 0 + vstelm.h vr1, a0, 32, 4 + vstelm.h vr1, a0, 64, 1 + vstelm.h vr1, a0, 96, 5 + vstelm.h vr3, a0, 128, 0 + vstelm.h vr3, a0, 160, 4 + vstelm.h vr3, a0, 192, 1 + vstelm.h vr3, a0, 224, 5 + addi.d a0, a0, 256 + vstelm.h vr1, a0, 0, 2 + vstelm.h vr1, a0, 32, 6 + vstelm.h vr1, a0, 64, 3 + vstelm.h vr1, a0, 96, 7 + vstelm.h vr3, a0, 128, 2 + vstelm.h vr3, a0, 160, 6 + vstelm.h vr3, a0, 192, 3 + vstelm.h vr3, a0, 224, 7 +endfunc diff --git a/libavcodec/loongarch/h264idct_lasx.c b/libavcodec/loongarch/h264idct_lasx.c deleted file mode 100644 index 46bd3b74d5f..00000000000 --- a/libavcodec/loongarch/h264idct_lasx.c +++ /dev/null @@ -1,498 +0,0 @@ -/* - * 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 -} diff --git a/libavcodec/loongarch/h264idct_loongarch.c b/libavcodec/loongarch/h264idct_loongarch.c new file mode 100644 index 00000000000..26af45503f1 --- /dev/null +++ b/libavcodec/loongarch/h264idct_loongarch.c @@ -0,0 +1,184 @@ +/* + * Loongson LSX/LASX optimized h264idct + * + * Copyright (c) 2023 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 "h264dsp_loongarch.h" +#include "libavcodec/bit_depth_template.c" + +void ff_h264_idct_add16_8_lsx(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 == 1 && ((dctcoef *) block)[i * 16]) { + ff_h264_idct_dc_add_8_lsx(dst + blk_offset[i], + block + i * 16 * sizeof(pixel), + dst_stride); + } else if (nnz) { + ff_h264_idct_add_8_lsx(dst + blk_offset[i], + block + i * 16 * sizeof(pixel), + dst_stride); + } + } +} + +void ff_h264_idct8_add4_8_lsx(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 == 1 && ((dctcoef *) block)[cnt * 16]) { + ff_h264_idct8_dc_add_8_lsx(dst + blk_offset[cnt], + block + cnt * 16 * sizeof(pixel), + dst_stride); + } else if (nnz) { + ff_h264_idct8_add_8_lsx(dst + blk_offset[cnt], + block + cnt * 16 * sizeof(pixel), + dst_stride); + } + } +} + +#if HAVE_LASX +void ff_h264_idct8_add4_8_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 == 1 && ((dctcoef *) block)[cnt * 16]) { + ff_h264_idct8_dc_add_8_lasx(dst + blk_offset[cnt], + block + cnt * 16 * sizeof(pixel), + dst_stride); + } else if (nnz) { + ff_h264_idct8_add_8_lasx(dst + blk_offset[cnt], + block + cnt * 16 * sizeof(pixel), + dst_stride); + } + } +} +#endif // #if HAVE_LASX + +void ff_h264_idct_add8_8_lsx(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_8_lsx(dst[0] + blk_offset[i], + block + i * 16 * sizeof(pixel), + dst_stride); + else if (((dctcoef *) block)[i * 16]) + ff_h264_idct_dc_add_8_lsx(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_8_lsx(dst[1] + blk_offset[i], + block + i * 16 * sizeof(pixel), + dst_stride); + else if (((dctcoef *) block)[i * 16]) + ff_h264_idct_dc_add_8_lsx(dst[1] + blk_offset[i], + block + i * 16 * sizeof(pixel), + dst_stride); + } +} + +void ff_h264_idct_add8_422_8_lsx(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_8_lsx(dst[0] + blk_offset[i], + block + i * 16 * sizeof(pixel), + dst_stride); + else if (((dctcoef *) block)[i * 16]) + ff_h264_idct_dc_add_8_lsx(dst[0] + 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_8_lsx(dst[0] + blk_offset[i + 4], + block + i * 16 * sizeof(pixel), + dst_stride); + else if (((dctcoef *) block)[i * 16]) + ff_h264_idct_dc_add_8_lsx(dst[0] + blk_offset[i + 4], + block + i * 16 * sizeof(pixel), + dst_stride); + } + for (i = 32; i < 36; i++) { + if (nzc[scan8[i]]) + ff_h264_idct_add_8_lsx(dst[1] + blk_offset[i], + block + i * 16 * sizeof(pixel), + dst_stride); + else if (((dctcoef *) block)[i * 16]) + ff_h264_idct_dc_add_8_lsx(dst[1] + blk_offset[i], + block + i * 16 * sizeof(pixel), + dst_stride); + } + for (i = 36; i < 40; i++) { + if (nzc[scan8[i + 4]]) + ff_h264_idct_add_8_lsx(dst[1] + blk_offset[i + 4], + block + i * 16 * sizeof(pixel), + dst_stride); + else if (((dctcoef *) block)[i * 16]) + ff_h264_idct_dc_add_8_lsx(dst[1] + blk_offset[i + 4], + block + i * 16 * sizeof(pixel), + dst_stride); + } +} + +void ff_h264_idct_add16_intra_8_lsx(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_8_lsx(dst + blk_offset[i], + block + i * 16 * sizeof(pixel), dst_stride); + else if (((dctcoef *) block)[i * 16]) + ff_h264_idct_dc_add_8_lsx(dst + blk_offset[i], + block + i * 16 * sizeof(pixel), + dst_stride); + } +} diff --git a/libavcodec/loongarch/loongson_asm.S b/libavcodec/loongarch/loongson_asm.S new file mode 100644 index 00000000000..0a649f51c7f --- /dev/null +++ b/libavcodec/loongarch/loongson_asm.S @@ -0,0 +1,945 @@ +/* + * Loongson asm helper. + * + * Copyright (c) 2022 Loongson Technology Corporation Limited + * Contributed by Gu Xiwei(guxiwei-hf@loongson.cn) + * Shiyou Yin(yinshiyou-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 + */ + +/** + * MAJOR version: Macro usage changes. + * MINOR version: Add new functions, or bug fixes. + * MICRO version: Comment changes or implementation changes. + */ +#define LML_VERSION_MAJOR 0 +#define LML_VERSION_MINOR 2 +#define LML_VERSION_MICRO 0 + +/* + *============================================================================ + * macros for specific projetc, set them as needed. + * Following LoongML macros for your reference. + *============================================================================ + */ +#define ASM_PREF +#define DEFAULT_ALIGN 5 + +.macro function name, align=DEFAULT_ALIGN +.macro endfunc + jirl $r0, $r1, 0x0 + .size ASM_PREF\name, . - ASM_PREF\name + .purgem endfunc +.endm +.text ; +.align \align ; +.globl ASM_PREF\name ; +.type ASM_PREF\name, @function ; +ASM_PREF\name: ; +.endm + +/** + * Attention: If align is not zero, the macro will use + * t7 until the end of function + */ +.macro alloc_stack size, align=0 +.if \align + .macro clean_stack + add.d sp, sp, t7 + .endm + addi.d sp, sp, - \size + andi.d t7, sp, \align - 1 + sub.d sp, sp, t7 + addi.d t7, t7, \size +.else + .macro clean_stack + addi.d sp, sp, \size + .endm + addi.d sp, sp, - \size +.endif +.endm + +.macro const name, align=DEFAULT_ALIGN + .macro endconst + .size \name, . - \name + .purgem endconst + .endm +.section .rodata +.align \align +\name: +.endm + +/* + *============================================================================ + * LoongArch register alias + *============================================================================ + */ + +#define a0 $a0 +#define a1 $a1 +#define a2 $a2 +#define a3 $a3 +#define a4 $a4 +#define a5 $a5 +#define a6 $a6 +#define a7 $a7 + +#define t0 $t0 +#define t1 $t1 +#define t2 $t2 +#define t3 $t3 +#define t4 $t4 +#define t5 $t5 +#define t6 $t6 +#define t7 $t7 +#define t8 $t8 + +#define s0 $s0 +#define s1 $s1 +#define s2 $s2 +#define s3 $s3 +#define s4 $s4 +#define s5 $s5 +#define s6 $s6 +#define s7 $s7 +#define s8 $s8 + +#define zero $zero +#define sp $sp +#define ra $ra + +#define f0 $f0 +#define f1 $f1 +#define f2 $f2 +#define f3 $f3 +#define f4 $f4 +#define f5 $f5 +#define f6 $f6 +#define f7 $f7 +#define f8 $f8 +#define f9 $f9 +#define f10 $f10 +#define f11 $f11 +#define f12 $f12 +#define f13 $f13 +#define f14 $f14 +#define f15 $f15 +#define f16 $f16 +#define f17 $f17 +#define f18 $f18 +#define f19 $f19 +#define f20 $f20 +#define f21 $f21 +#define f22 $f22 +#define f23 $f23 +#define f24 $f24 +#define f25 $f25 +#define f26 $f26 +#define f27 $f27 +#define f28 $f28 +#define f29 $f29 +#define f30 $f30 +#define f31 $f31 + +#define vr0 $vr0 +#define vr1 $vr1 +#define vr2 $vr2 +#define vr3 $vr3 +#define vr4 $vr4 +#define vr5 $vr5 +#define vr6 $vr6 +#define vr7 $vr7 +#define vr8 $vr8 +#define vr9 $vr9 +#define vr10 $vr10 +#define vr11 $vr11 +#define vr12 $vr12 +#define vr13 $vr13 +#define vr14 $vr14 +#define vr15 $vr15 +#define vr16 $vr16 +#define vr17 $vr17 +#define vr18 $vr18 +#define vr19 $vr19 +#define vr20 $vr20 +#define vr21 $vr21 +#define vr22 $vr22 +#define vr23 $vr23 +#define vr24 $vr24 +#define vr25 $vr25 +#define vr26 $vr26 +#define vr27 $vr27 +#define vr28 $vr28 +#define vr29 $vr29 +#define vr30 $vr30 +#define vr31 $vr31 + +#define xr0 $xr0 +#define xr1 $xr1 +#define xr2 $xr2 +#define xr3 $xr3 +#define xr4 $xr4 +#define xr5 $xr5 +#define xr6 $xr6 +#define xr7 $xr7 +#define xr8 $xr8 +#define xr9 $xr9 +#define xr10 $xr10 +#define xr11 $xr11 +#define xr12 $xr12 +#define xr13 $xr13 +#define xr14 $xr14 +#define xr15 $xr15 +#define xr16 $xr16 +#define xr17 $xr17 +#define xr18 $xr18 +#define xr19 $xr19 +#define xr20 $xr20 +#define xr21 $xr21 +#define xr22 $xr22 +#define xr23 $xr23 +#define xr24 $xr24 +#define xr25 $xr25 +#define xr26 $xr26 +#define xr27 $xr27 +#define xr28 $xr28 +#define xr29 $xr29 +#define xr30 $xr30 +#define xr31 $xr31 + +/* + *============================================================================ + * LSX/LASX synthesize instructions + *============================================================================ + */ + +/* + * Description : Dot product of byte vector elements + * Arguments : Inputs - vj, vk + * Outputs - vd + * Return Type - halfword + */ +.macro vdp2.h.bu vd, vj, vk + vmulwev.h.bu \vd, \vj, \vk + vmaddwod.h.bu \vd, \vj, \vk +.endm + +.macro vdp2.h.bu.b vd, vj, vk + vmulwev.h.bu.b \vd, \vj, \vk + vmaddwod.h.bu.b \vd, \vj, \vk +.endm + +.macro vdp2.w.h vd, vj, vk + vmulwev.w.h \vd, \vj, \vk + vmaddwod.w.h \vd, \vj, \vk +.endm + +.macro xvdp2.h.bu xd, xj, xk + xvmulwev.h.bu \xd, \xj, \xk + xvmaddwod.h.bu \xd, \xj, \xk +.endm + +.macro xvdp2.h.bu.b xd, xj, xk + xvmulwev.h.bu.b \xd, \xj, \xk + xvmaddwod.h.bu.b \xd, \xj, \xk +.endm + +.macro xvdp2.w.h xd, xj, xk + xvmulwev.w.h \xd, \xj, \xk + xvmaddwod.w.h \xd, \xj, \xk +.endm + +/* + * Description : Dot product & addition of halfword vector elements + * Arguments : Inputs - vj, vk + * Outputs - vd + * Return Type - twice size of input + */ +.macro vdp2add.h.bu vd, vj, vk + vmaddwev.h.bu \vd, \vj, \vk + vmaddwod.h.bu \vd, \vj, \vk +.endm + +.macro vdp2add.h.bu.b vd, vj, vk + vmaddwev.h.bu.b \vd, \vj, \vk + vmaddwod.h.bu.b \vd, \vj, \vk +.endm + +.macro vdp2add.w.h vd, vj, vk + vmaddwev.w.h \vd, \vj, \vk + vmaddwod.w.h \vd, \vj, \vk +.endm + +.macro xvdp2add.h.bu.b xd, xj, xk + xvmaddwev.h.bu.b \xd, \xj, \xk + xvmaddwod.h.bu.b \xd, \xj, \xk +.endm + +.macro xvdp2add.w.h xd, xj, xk + xvmaddwev.w.h \xd, \xj, \xk + xvmaddwod.w.h \xd, \xj, \xk +.endm + +/* + * Description : Range each element of vector + * clip: vj > vk ? vj : vk && vj < va ? vj : va + * clip255: vj < 255 ? vj : 255 && vj > 0 ? vj : 0 + */ +.macro vclip.h vd, vj, vk, va + vmax.h \vd, \vj, \vk + vmin.h \vd, \vd, \va +.endm + +.macro vclip255.w vd, vj + vmaxi.w \vd, \vj, 0 + vsat.wu \vd, \vd, 7 +.endm + +.macro vclip255.h vd, vj + vmaxi.h \vd, \vj, 0 + vsat.hu \vd, \vd, 7 +.endm + +.macro xvclip.h xd, xj, xk, xa + xvmax.h \xd, \xj, \xk + xvmin.h \xd, \xd, \xa +.endm + +.macro xvclip255.h xd, xj + xvmaxi.h \xd, \xj, 0 + xvsat.hu \xd, \xd, 7 +.endm + +.macro xvclip255.w xd, xj + xvmaxi.w \xd, \xj, 0 + xvsat.wu \xd, \xd, 7 +.endm + +/* + * Description : Store elements of vector + * vd : Data vector to be stroed + * rk : Address of data storage + * ra : Offset of address + * si : Index of data in vd + */ +.macro vstelmx.b vd, rk, ra, si + add.d \rk, \rk, \ra + vstelm.b \vd, \rk, 0, \si +.endm + +.macro vstelmx.h vd, rk, ra, si + add.d \rk, \rk, \ra + vstelm.h \vd, \rk, 0, \si +.endm + +.macro vstelmx.w vd, rk, ra, si + add.d \rk, \rk, \ra + vstelm.w \vd, \rk, 0, \si +.endm + +.macro vstelmx.d vd, rk, ra, si + add.d \rk, \rk, \ra + vstelm.d \vd, \rk, 0, \si +.endm + +.macro vmov xd, xj + vor.v \xd, \xj, \xj +.endm + +.macro xmov xd, xj + xvor.v \xd, \xj, \xj +.endm + +.macro xvstelmx.d xd, rk, ra, si + add.d \rk, \rk, \ra + xvstelm.d \xd, \rk, 0, \si +.endm + +/* + *============================================================================ + * LSX/LASX custom macros + *============================================================================ + */ + +/* + * Load 4 float, double, V128, v256 elements with stride. + */ +.macro FLDS_LOADX_4 src, stride, stride2, stride3, out0, out1, out2, out3 + fld.s \out0, \src, 0 + fldx.s \out1, \src, \stride + fldx.s \out2, \src, \stride2 + fldx.s \out3, \src, \stride3 +.endm + +.macro FLDD_LOADX_4 src, stride, stride2, stride3, out0, out1, out2, out3 + fld.d \out0, \src, 0 + fldx.d \out1, \src, \stride + fldx.d \out2, \src, \stride2 + fldx.d \out3, \src, \stride3 +.endm + +.macro LSX_LOADX_4 src, stride, stride2, stride3, out0, out1, out2, out3 + vld \out0, \src, 0 + vldx \out1, \src, \stride + vldx \out2, \src, \stride2 + vldx \out3, \src, \stride3 +.endm + +.macro LASX_LOADX_4 src, stride, stride2, stride3, out0, out1, out2, out3 + xvld \out0, \src, 0 + xvldx \out1, \src, \stride + xvldx \out2, \src, \stride2 + xvldx \out3, \src, \stride3 +.endm + +/* + * Description : Transpose 4x4 block with half-word elements in vectors + * Arguments : Inputs - in0, in1, in2, in3 + * Outputs - out0, out1, out2, out3 + */ +.macro LSX_TRANSPOSE4x4_H in0, in1, in2, in3, out0, out1, out2, out3, \ + tmp0, tmp1 + vilvl.h \tmp0, \in1, \in0 + vilvl.h \tmp1, \in3, \in2 + vilvl.w \out0, \tmp1, \tmp0 + vilvh.w \out2, \tmp1, \tmp0 + vilvh.d \out1, \out0, \out0 + vilvh.d \out3, \out0, \out2 +.endm + +/* + * 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 + */ +.macro LSX_TRANSPOSE4x4_W _in0, _in1, _in2, _in3, _out0, _out1, _out2, _out3, \ + _tmp0, _tmp1 + + vilvl.w \_tmp0, \_in1, \_in0 + vilvh.w \_out1, \_in1, \_in0 + vilvl.w \_tmp1, \_in3, \_in2 + vilvh.w \_out3, \_in3, \_in2 + + vilvl.d \_out0, \_tmp1, \_tmp0 + vilvl.d \_out2, \_out3, \_out1 + vilvh.d \_out3, \_out3, \_out1 + vilvh.d \_out1, \_tmp1, \_tmp0 +.endm + +/* + * 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 + */ +.macro LSX_TRANSPOSE8x8_H in0, in1, in2, in3, in4, in5, in6, in7, out0, out1, \ + out2, out3, out4, out5, out6, out7, tmp0, tmp1, tmp2, \ + tmp3, tmp4, tmp5, tmp6, tmp7 + vilvl.h \tmp0, \in6, \in4 + vilvl.h \tmp1, \in7, \in5 + vilvl.h \tmp2, \in2, \in0 + vilvl.h \tmp3, \in3, \in1 + + vilvl.h \tmp4, \tmp1, \tmp0 + vilvh.h \tmp5, \tmp1, \tmp0 + vilvl.h \tmp6, \tmp3, \tmp2 + vilvh.h \tmp7, \tmp3, \tmp2 + + vilvh.h \tmp0, \in6, \in4 + vilvh.h \tmp1, \in7, \in5 + vilvh.h \tmp2, \in2, \in0 + vilvh.h \tmp3, \in3, \in1 + + vpickev.d \out0, \tmp4, \tmp6 + vpickod.d \out1, \tmp4, \tmp6 + vpickev.d \out2, \tmp5, \tmp7 + vpickod.d \out3, \tmp5, \tmp7 + + vilvl.h \tmp4, \tmp1, \tmp0 + vilvh.h \tmp5, \tmp1, \tmp0 + vilvl.h \tmp6, \tmp3, \tmp2 + vilvh.h \tmp7, \tmp3, \tmp2 + + vpickev.d \out4, \tmp4, \tmp6 + vpickod.d \out5, \tmp4, \tmp6 + vpickev.d \out6, \tmp5, \tmp7 + vpickod.d \out7, \tmp5, \tmp7 +.endm + +/* + * Description : Transpose 16x8 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 + */ +.macro 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,\ + tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7 + xvilvl.b \tmp0, \in2, \in0 + xvilvl.b \tmp1, \in3, \in1 + xvilvl.b \tmp2, \in6, \in4 + xvilvl.b \tmp3, \in7, \in5 + xvilvl.b \tmp4, \in10, \in8 + xvilvl.b \tmp5, \in11, \in9 + xvilvl.b \tmp6, \in14, \in12 + xvilvl.b \tmp7, \in15, \in13 + xvilvl.b \out0, \tmp1, \tmp0 + xvilvh.b \out1, \tmp1, \tmp0 + xvilvl.b \out2, \tmp3, \tmp2 + xvilvh.b \out3, \tmp3, \tmp2 + xvilvl.b \out4, \tmp5, \tmp4 + xvilvh.b \out5, \tmp5, \tmp4 + xvilvl.b \out6, \tmp7, \tmp6 + xvilvh.b \out7, \tmp7, \tmp6 + xvilvl.w \tmp0, \out2, \out0 + xvilvh.w \tmp2, \out2, \out0 + xvilvl.w \tmp4, \out3, \out1 + xvilvh.w \tmp6, \out3, \out1 + xvilvl.w \tmp1, \out6, \out4 + xvilvh.w \tmp3, \out6, \out4 + xvilvl.w \tmp5, \out7, \out5 + xvilvh.w \tmp7, \out7, \out5 + xvilvl.d \out0, \tmp1, \tmp0 + xvilvh.d \out1, \tmp1, \tmp0 + xvilvl.d \out2, \tmp3, \tmp2 + xvilvh.d \out3, \tmp3, \tmp2 + xvilvl.d \out4, \tmp5, \tmp4 + xvilvh.d \out5, \tmp5, \tmp4 + xvilvl.d \out6, \tmp7, \tmp6 + xvilvh.d \out7, \tmp7, \tmp6 +.endm + +/* + * Description : Transpose 16x8 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 + */ +.macro 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,\ + tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7 + vilvl.b \tmp0, \in2, \in0 + vilvl.b \tmp1, \in3, \in1 + vilvl.b \tmp2, \in6, \in4 + vilvl.b \tmp3, \in7, \in5 + vilvl.b \tmp4, \in10, \in8 + vilvl.b \tmp5, \in11, \in9 + vilvl.b \tmp6, \in14, \in12 + vilvl.b \tmp7, \in15, \in13 + + vilvl.b \out0, \tmp1, \tmp0 + vilvh.b \out1, \tmp1, \tmp0 + vilvl.b \out2, \tmp3, \tmp2 + vilvh.b \out3, \tmp3, \tmp2 + vilvl.b \out4, \tmp5, \tmp4 + vilvh.b \out5, \tmp5, \tmp4 + vilvl.b \out6, \tmp7, \tmp6 + vilvh.b \out7, \tmp7, \tmp6 + vilvl.w \tmp0, \out2, \out0 + vilvh.w \tmp2, \out2, \out0 + vilvl.w \tmp4, \out3, \out1 + vilvh.w \tmp6, \out3, \out1 + vilvl.w \tmp1, \out6, \out4 + vilvh.w \tmp3, \out6, \out4 + vilvl.w \tmp5, \out7, \out5 + vilvh.w \tmp7, \out7, \out5 + vilvl.d \out0, \tmp1, \tmp0 + vilvh.d \out1, \tmp1, \tmp0 + vilvl.d \out2, \tmp3, \tmp2 + vilvh.d \out3, \tmp3, \tmp2 + vilvl.d \out4, \tmp5, \tmp4 + vilvh.d \out5, \tmp5, \tmp4 + vilvl.d \out6, \tmp7, \tmp6 + vilvh.d \out7, \tmp7, \tmp6 +.endm + +/* + * Description : Transpose 4x4 block with half-word elements in vectors + * Arguments : Inputs - in0, in1, in2, in3 + * Outputs - out0, out1, out2, out3 + */ +.macro LASX_TRANSPOSE4x4_H in0, in1, in2, in3, out0, out1, out2, out3, \ + tmp0, tmp1 + xvilvl.h \tmp0, \in1, \in0 + xvilvl.h \tmp1, \in3, \in2 + xvilvl.w \out0, \tmp1, \tmp0 + xvilvh.w \out2, \tmp1, \tmp0 + xvilvh.d \out1, \out0, \out0 + xvilvh.d \out3, \out0, \out2 +.endm + +/* + * Description : Transpose 4x8 block with half-word elements in vectors + * Arguments : Inputs - in0, in1, in2, in3 + * Outputs - out0, out1, out2, out3 + */ +.macro LASX_TRANSPOSE4x8_H in0, in1, in2, in3, out0, out1, out2, out3, \ + tmp0, tmp1 + xvilvl.h \tmp0, \in2, \in0 + xvilvl.h \tmp1, \in3, \in1 + xvilvl.h \out2, \tmp1, \tmp0 + xvilvh.h \out3, \tmp1, \tmp0 + + xvilvl.d \out0, \out2, \out2 + xvilvh.d \out1, \out2, \out2 + xvilvl.d \out2, \out3, \out3 + xvilvh.d \out3, \out3, \out3 +.endm + +/* + * 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 + */ +.macro LASX_TRANSPOSE8x8_H in0, in1, in2, in3, in4, in5, in6, in7, \ + out0, out1, out2, out3, out4, out5, out6, out7, \ + tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7 + xvilvl.h \tmp0, \in6, \in4 + xvilvl.h \tmp1, \in7, \in5 + xvilvl.h \tmp2, \in2, \in0 + xvilvl.h \tmp3, \in3, \in1 + + xvilvl.h \tmp4, \tmp1, \tmp0 + xvilvh.h \tmp5, \tmp1, \tmp0 + xvilvl.h \tmp6, \tmp3, \tmp2 + xvilvh.h \tmp7, \tmp3, \tmp2 + + xvilvh.h \tmp0, \in6, \in4 + xvilvh.h \tmp1, \in7, \in5 + xvilvh.h \tmp2, \in2, \in0 + xvilvh.h \tmp3, \in3, \in1 + + xvpickev.d \out0, \tmp4, \tmp6 + xvpickod.d \out1, \tmp4, \tmp6 + xvpickev.d \out2, \tmp5, \tmp7 + xvpickod.d \out3, \tmp5, \tmp7 + + xvilvl.h \tmp4, \tmp1, \tmp0 + xvilvh.h \tmp5, \tmp1, \tmp0 + xvilvl.h \tmp6, \tmp3, \tmp2 + xvilvh.h \tmp7, \tmp3, \tmp2 + + xvpickev.d \out4, \tmp4, \tmp6 + xvpickod.d \out5, \tmp4, \tmp6 + xvpickev.d \out6, \tmp5, \tmp7 + xvpickod.d \out7, \tmp5, \tmp7 +.endm + +/* + * Description : Transpose 2x4x4 block with half-word elements in vectors + * Arguments : Inputs - in0, in1, in2, in3 + * Outputs - out0, out1, out2, out3 + */ +.macro LASX_TRANSPOSE2x4x4_H in0, in1, in2, in3, out0, out1, out2, out3, \ + tmp0, tmp1, tmp2 + xvilvh.h \tmp1, \in0, \in1 + xvilvl.h \out1, \in0, \in1 + xvilvh.h \tmp0, \in2, \in3 + xvilvl.h \out3, \in2, \in3 + + xvilvh.w \tmp2, \out3, \out1 + xvilvl.w \out3, \out3, \out1 + + xvilvl.w \out2, \tmp0, \tmp1 + xvilvh.w \tmp1, \tmp0, \tmp1 + + xvilvh.d \out0, \out2, \out3 + xvilvl.d \out2, \out2, \out3 + xvilvh.d \out1, \tmp1, \tmp2 + xvilvl.d \out3, \tmp1, \tmp2 +.endm + +/* + * 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, 2, 3, 4 1,5, 9,13, 1,5, 9,13 + * 5, 6, 7, 8, 5, 6, 7, 8 to 2,6,10,14, 2,6,10,14 + * 9,10,11,12, 9,10,11,12 =====> 3,7,11,15, 3,7,11,15 + * 13,14,15,16, 13,14,15,16 4,8,12,16, 4,8,12,16 + */ +.macro LASX_TRANSPOSE4x4_W _in0, _in1, _in2, _in3, _out0, _out1, _out2, _out3, \ + _tmp0, _tmp1 + + xvilvl.w \_tmp0, \_in1, \_in0 + xvilvh.w \_out1, \_in1, \_in0 + xvilvl.w \_tmp1, \_in3, \_in2 + xvilvh.w \_out3, \_in3, \_in2 + + xvilvl.d \_out0, \_tmp1, \_tmp0 + xvilvl.d \_out2, \_out3, \_out1 + xvilvh.d \_out3, \_out3, \_out1 + xvilvh.d \_out1, \_tmp1, \_tmp0 +.endm + +/* + * 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 + */ +.macro LASX_TRANSPOSE8x8_W _in0, _in1, _in2, _in3, _in4, _in5, _in6, _in7,\ + _out0, _out1, _out2, _out3, _out4, _out5, _out6, _out7,\ + _tmp0, _tmp1, _tmp2, _tmp3 + xvilvl.w \_tmp0, \_in2, \_in0 + xvilvl.w \_tmp1, \_in3, \_in1 + xvilvh.w \_tmp2, \_in2, \_in0 + xvilvh.w \_tmp3, \_in3, \_in1 + xvilvl.w \_out0, \_tmp1, \_tmp0 + xvilvh.w \_out1, \_tmp1, \_tmp0 + xvilvl.w \_out2, \_tmp3, \_tmp2 + xvilvh.w \_out3, \_tmp3, \_tmp2 + + xvilvl.w \_tmp0, \_in6, \_in4 + xvilvl.w \_tmp1, \_in7, \_in5 + xvilvh.w \_tmp2, \_in6, \_in4 + xvilvh.w \_tmp3, \_in7, \_in5 + xvilvl.w \_out4, \_tmp1, \_tmp0 + xvilvh.w \_out5, \_tmp1, \_tmp0 + xvilvl.w \_out6, \_tmp3, \_tmp2 + xvilvh.w \_out7, \_tmp3, \_tmp2 + + xmov \_tmp0, \_out0 + xmov \_tmp1, \_out1 + xmov \_tmp2, \_out2 + xmov \_tmp3, \_out3 + xvpermi.q \_out0, \_out4, 0x02 + xvpermi.q \_out1, \_out5, 0x02 + xvpermi.q \_out2, \_out6, 0x02 + xvpermi.q \_out3, \_out7, 0x02 + xvpermi.q \_out4, \_tmp0, 0x31 + xvpermi.q \_out5, \_tmp1, 0x31 + xvpermi.q \_out6, \_tmp2, 0x31 + xvpermi.q \_out7, \_tmp3, 0x31 +.endm + +/* + * 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 + */ +.macro LASX_TRANSPOSE4x4_D _in0, _in1, _in2, _in3, _out0, _out1, _out2, _out3, \ + _tmp0, _tmp1 + xvilvl.d \_tmp0, \_in1, \_in0 + xvilvh.d \_out1, \_in1, \_in0 + xvilvh.d \_tmp1, \_in3, \_in2 + xvilvl.d \_out2, \_in3, \_in2 + + xvor.v \_out0, \_tmp0, \_tmp0 + xvor.v \_out3, \_tmp1, \_tmp1 + + xvpermi.q \_out0, \_out2, 0x02 + xvpermi.q \_out2, \_tmp0, 0x31 + xvpermi.q \_out3, \_out1, 0x31 + xvpermi.q \_out1, \_tmp1, 0x02 +.endm + +/* + * Description : Butterfly of 4 input vectors + * Arguments : Inputs - _in0, _in1, _in2, _in3 + * Outputs - _out0, _out1, _out2, _out3 + * Details : Butterfly operation + * Example : LSX_BUTTERFLY_4 + * _out0 = _in0 + _in3; + * _out1 = _in1 + _in2; + * _out2 = _in1 - _in2; + * _out3 = _in0 - _in3; + */ +.macro LSX_BUTTERFLY_4_B _in0, _in1, _in2, _in3, _out0, _out1, _out2, _out3 + vadd.b \_out0, \_in0, \_in3 + vadd.b \_out1, \_in1, \_in2 + vsub.b \_out2, \_in1, \_in2 + vsub.b \_out3, \_in0, \_in3 +.endm +.macro LSX_BUTTERFLY_4_H _in0, _in1, _in2, _in3, _out0, _out1, _out2, _out3 + vadd.h \_out0, \_in0, \_in3 + vadd.h \_out1, \_in1, \_in2 + vsub.h \_out2, \_in1, \_in2 + vsub.h \_out3, \_in0, \_in3 +.endm +.macro LSX_BUTTERFLY_4_W _in0, _in1, _in2, _in3, _out0, _out1, _out2, _out3 + vadd.w \_out0, \_in0, \_in3 + vadd.w \_out1, \_in1, \_in2 + vsub.w \_out2, \_in1, \_in2 + vsub.w \_out3, \_in0, \_in3 +.endm +.macro LSX_BUTTERFLY_4_D _in0, _in1, _in2, _in3, _out0, _out1, _out2, _out3 + vadd.d \_out0, \_in0, \_in3 + vadd.d \_out1, \_in1, \_in2 + vsub.d \_out2, \_in1, \_in2 + vsub.d \_out3, \_in0, \_in3 +.endm + +.macro LASX_BUTTERFLY_4_B _in0, _in1, _in2, _in3, _out0, _out1, _out2, _out3 + xvadd.b \_out0, \_in0, \_in3 + xvadd.b \_out1, \_in1, \_in2 + xvsub.b \_out2, \_in1, \_in2 + xvsub.b \_out3, \_in0, \_in3 +.endm +.macro LASX_BUTTERFLY_4_H _in0, _in1, _in2, _in3, _out0, _out1, _out2, _out3 + xvadd.h \_out0, \_in0, \_in3 + xvadd.h \_out1, \_in1, \_in2 + xvsub.h \_out2, \_in1, \_in2 + xvsub.h \_out3, \_in0, \_in3 +.endm +.macro LASX_BUTTERFLY_4_W _in0, _in1, _in2, _in3, _out0, _out1, _out2, _out3 + xvadd.w \_out0, \_in0, \_in3 + xvadd.w \_out1, \_in1, \_in2 + xvsub.w \_out2, \_in1, \_in2 + xvsub.w \_out3, \_in0, \_in3 +.endm +.macro LASX_BUTTERFLY_4_D _in0, _in1, _in2, _in3, _out0, _out1, _out2, _out3 + xvadd.d \_out0, \_in0, \_in3 + xvadd.d \_out1, \_in1, \_in2 + xvsub.d \_out2, \_in1, \_in2 + xvsub.d \_out3, \_in0, \_in3 +.endm + +/* + * 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; + */ +.macro LSX_BUTTERFLY_8_B _in0, _in1, _in2, _in3, _in4, _in5, _in6, _in7, \ + _out0, _out1, _out2, _out3, _out4, _out5, _out6, _out7 + vadd.b \_out0, \_in0, \_in7 + vadd.b \_out1, \_in1, \_in6 + vadd.b \_out2, \_in2, \_in5 + vadd.b \_out3, \_in3, \_in4 + vsub.b \_out4, \_in3, \_in4 + vsub.b \_out5, \_in2, \_in5 + vsub.b \_out6, \_in1, \_in6 + vsub.b \_out7, \_in0, \_in7 +.endm + +.macro LSX_BUTTERFLY_8_H _in0, _in1, _in2, _in3, _in4, _in5, _in6, _in7, \ + _out0, _out1, _out2, _out3, _out4, _out5, _out6, _out7 + vadd.h \_out0, \_in0, \_in7 + vadd.h \_out1, \_in1, \_in6 + vadd.h \_out2, \_in2, \_in5 + vadd.h \_out3, \_in3, \_in4 + vsub.h \_out4, \_in3, \_in4 + vsub.h \_out5, \_in2, \_in5 + vsub.h \_out6, \_in1, \_in6 + vsub.h \_out7, \_in0, \_in7 +.endm + +.macro LSX_BUTTERFLY_8_W _in0, _in1, _in2, _in3, _in4, _in5, _in6, _in7, \ + _out0, _out1, _out2, _out3, _out4, _out5, _out6, _out7 + vadd.w \_out0, \_in0, \_in7 + vadd.w \_out1, \_in1, \_in6 + vadd.w \_out2, \_in2, \_in5 + vadd.w \_out3, \_in3, \_in4 + vsub.w \_out4, \_in3, \_in4 + vsub.w \_out5, \_in2, \_in5 + vsub.w \_out6, \_in1, \_in6 + vsub.w \_out7, \_in0, \_in7 +.endm + +.macro LSX_BUTTERFLY_8_D _in0, _in1, _in2, _in3, _in4, _in5, _in6, _in7, \ + _out0, _out1, _out2, _out3, _out4, _out5, _out6, _out7 + vadd.d \_out0, \_in0, \_in7 + vadd.d \_out1, \_in1, \_in6 + vadd.d \_out2, \_in2, \_in5 + vadd.d \_out3, \_in3, \_in4 + vsub.d \_out4, \_in3, \_in4 + vsub.d \_out5, \_in2, \_in5 + vsub.d \_out6, \_in1, \_in6 + vsub.d \_out7, \_in0, \_in7 +.endm + +.macro LASX_BUTTERFLY_8_B _in0, _in1, _in2, _in3, _in4, _in5, _in6, _in7, \ + _out0, _out1, _out2, _out3, _out4, _out5, _out6, _out7 + xvadd.b \_out0, \_in0, \_in7 + xvadd.b \_out1, \_in1, \_in6 + xvadd.b \_out2, \_in2, \_in5 + xvadd.b \_out3, \_in3, \_in4 + xvsub.b \_out4, \_in3, \_in4 + xvsub.b \_out5, \_in2, \_in5 + xvsub.b \_out6, \_in1, \_in6 + xvsub.b \_out7, \_in0, \_in7 +.endm + +.macro LASX_BUTTERFLY_8_H _in0, _in1, _in2, _in3, _in4, _in5, _in6, _in7, \ + _out0, _out1, _out2, _out3, _out4, _out5, _out6, _out7 + xvadd.h \_out0, \_in0, \_in7 + xvadd.h \_out1, \_in1, \_in6 + xvadd.h \_out2, \_in2, \_in5 + xvadd.h \_out3, \_in3, \_in4 + xvsub.h \_out4, \_in3, \_in4 + xvsub.h \_out5, \_in2, \_in5 + xvsub.h \_out6, \_in1, \_in6 + xvsub.h \_out7, \_in0, \_in7 +.endm + +.macro LASX_BUTTERFLY_8_W _in0, _in1, _in2, _in3, _in4, _in5, _in6, _in7, \ + _out0, _out1, _out2, _out3, _out4, _out5, _out6, _out7 + xvadd.w \_out0, \_in0, \_in7 + xvadd.w \_out1, \_in1, \_in6 + xvadd.w \_out2, \_in2, \_in5 + xvadd.w \_out3, \_in3, \_in4 + xvsub.w \_out4, \_in3, \_in4 + xvsub.w \_out5, \_in2, \_in5 + xvsub.w \_out6, \_in1, \_in6 + xvsub.w \_out7, \_in0, \_in7 +.endm From 7845b5ecd629d28ad71b61d81a301367db3f2e86 Mon Sep 17 00:00:00 2001 From: Hao Chen Date: Thu, 25 May 2023 15:24:27 +0800 Subject: [PATCH 1174/2172] avcodec/la: Add LSX optimization for loop filter. Replaced function(LSX is sufficient for these functions): ff_h264_v_lpf_chroma_8_lasx ff_h264_h_lpf_chroma_8_lasx ff_h264_v_lpf_chroma_intra_8_lasx ff_h264_h_lpf_chroma_intra_8_lasx ff_weight_h264_pixels4_8_lasx ff_biweight_h264_pixels4_8_lasx ./configure --disable-lasx ffmpeg -i 1_h264_1080p_30fps_3Mbps.mp4 -f rawvideo -y /dev/null -an before: 161fps after: 199fps Reviewed-by: Shiyou Yin Signed-off-by: Michael Niedermayer --- libavcodec/loongarch/Makefile | 3 +- libavcodec/loongarch/h264dsp.S | 1977 +++++++++++++++++ libavcodec/loongarch/h264dsp_init_loongarch.c | 37 +- libavcodec/loongarch/h264dsp_lasx.c | 1354 +---------- libavcodec/loongarch/h264dsp_loongarch.h | 67 +- 5 files changed, 2063 insertions(+), 1375 deletions(-) create mode 100644 libavcodec/loongarch/h264dsp.S diff --git a/libavcodec/loongarch/Makefile b/libavcodec/loongarch/Makefile index 34ebbbe133f..111bc23e4e2 100644 --- a/libavcodec/loongarch/Makefile +++ b/libavcodec/loongarch/Makefile @@ -31,4 +31,5 @@ LSX-OBJS-$(CONFIG_HEVC_DECODER) += loongarch/hevcdsp_lsx.o \ loongarch/hevc_mc_uni_lsx.o \ loongarch/hevc_mc_uniw_lsx.o LSX-OBJS-$(CONFIG_H264DSP) += loongarch/h264idct.o \ - loongarch/h264idct_loongarch.o + loongarch/h264idct_loongarch.o \ + loongarch/h264dsp.o diff --git a/libavcodec/loongarch/h264dsp.S b/libavcodec/loongarch/h264dsp.S new file mode 100644 index 00000000000..750fe49143c --- /dev/null +++ b/libavcodec/loongarch/h264dsp.S @@ -0,0 +1,1977 @@ +/* + * Loongson LSX/LASX optimized h264dsp + * + * Copyright (c) 2023 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 "loongson_asm.S" + +const vec_shuf +.rept 2 +.byte 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3 +.endr +endconst + +.macro AVC_LPF_P1_OR_Q1 _in0, _in1, _in2, _in3, _in4, _in5, _out, _tmp0, _tmp1 + vavgr.hu \_tmp0, \_in0, \_in1 + vslli.h \_tmp1, \_in2, 1 + vsub.h \_tmp0, \_tmp0, \_tmp1 + vavg.h \_tmp0, \_in3, \_tmp0 + vclip.h \_tmp0, \_tmp0, \_in4, \_in5 + vadd.h \_out, \_in2, \_tmp0 +.endm + +.macro AVC_LPF_P0Q0 _in0, _in1, _in2, _in3, _in4, _in5, _out0, \ + _out1, _tmp0, _tmp1 + vsub.h \_tmp0, \_in0, \_in1 + vsub.h \_tmp1, \_in2, \_in3 + vslli.h \_tmp0, \_tmp0, 2 + vaddi.hu \_tmp1, \_tmp1, 4 + vadd.h \_tmp0, \_tmp0, \_tmp1 + vsrai.h \_tmp0, \_tmp0, 3 + vclip.h \_tmp0, \_tmp0, \_in4, \_in5 + vadd.h \_out0, \_in1, \_tmp0 + vsub.h \_out1, \_in0, \_tmp0 + vclip255.h \_out0, \_out0 + vclip255.h \_out1, \_out1 +.endm + +.macro SAVE_REG + addi.d sp, sp, -64 + fst.d f24, sp, 0 + fst.d f25, sp, 8 + fst.d f26, sp, 16 + fst.d f27, sp, 24 + fst.d f28, sp, 32 + fst.d f29, sp, 40 + fst.d f30, sp, 48 + fst.d f31, sp, 56 +.endm + +.macro RESTORE_REG + fld.d f24, sp, 0 + fld.d f25, sp, 8 + fld.d f26, sp, 16 + fld.d f27, sp, 24 + fld.d f28, sp, 32 + fld.d f29, sp, 40 + fld.d f30, sp, 48 + fld.d f31, sp, 56 + addi.d sp, sp, 64 +.endm + +.macro load_double _in0, _in1, _in2, _in3, _src, _str0, _str1, _str2 + fld.d \_in0, \_src, 0 + fldx.d \_in1, \_src, \_str0 + fldx.d \_in2, \_src, \_str1 + fldx.d \_in3, \_src, \_str2 +.endm + +.macro store_double _in0, _in1, _in2, _in3, _dst, _str0, _str1, _str2 + fst.d \_in0, \_dst, 0 + fstx.d \_in1, \_dst, \_str0 + fstx.d \_in2, \_dst, \_str1 + fstx.d \_in3, \_dst, \_str2 +.endm + +function ff_h264_h_lpf_luma_8_lsx + slli.d t0, a1, 1 //img_width_2x + slli.d t1, a1, 2 //img_width_4x + slli.d t2, a1, 3 //img_width_8x + SAVE_REG + la.local t4, vec_shuf + add.d t3, t0, a1 //img_width_3x + vldrepl.w vr0, a4, 0 //tmp_vec0 + vld vr1, t4, 0 //tc_vec + vshuf.b vr1, vr0, vr0, vr1 //tc_vec + vslti.b vr2, vr1, 0 + vxori.b vr2, vr2, 255 + vandi.b vr2, vr2, 1 //bs_vec + vsetnez.v $fcc0, vr2 + bceqz $fcc0, .END_LUMA_8 + vldi vr0, 0 //zero + addi.d t4, a0, -4 //src + vslt.bu vr3, vr0, vr2 //is_bs_greater_than0 + add.d t5, t4, t2 //src_tmp + vld vr4, t4, 0 //row0 + vldx vr5, t4, a1 //row1 + vldx vr6, t4, t0 //row2 + vldx vr7, t4, t3 //row3 + add.d t6, t4, t1 // src += img_width_4x + vld vr8, t6, 0 //row4 + vldx vr9, t6, a1 //row5 + vldx vr10, t6, t0 //row6 + vldx vr11, t6, t3 //row7 + vld vr12, t5, 0 //row8 + vldx vr13, t5, a1 //row9 + vldx vr14, t5, t0 //row10 + vldx vr15, t5, t3 //row11 + add.d t6, t5, t1 // src_tmp += img_width_4x + vld vr16, t6, 0 //row12 + vldx vr17, t6, a1 //row13 + vldx vr18, t6, t0 //row14 + vldx vr19, t6, t3 //row15 + LSX_TRANSPOSE16X8_B vr4, vr5, vr6, vr7, vr8, vr9, vr10, vr11, \ + vr12, vr13, vr14, vr15, vr16, vr17, vr18, vr19, \ + vr10, vr11, vr12, vr13, vr14, vr15, vr16, vr17, \ + vr20, vr21, vr22, vr23, vr24, vr25, vr26, vr27 + //vr10: p3_org, vr11: p2_org, vr12: p1_org, vr13: p0_org + //vr14: q0_org, vr15: q1_org, vr16: q2_org, vr17: q3_org + vabsd.bu vr20, vr13, vr14 //p0_asub_q0 + vabsd.bu vr21, vr12, vr13 //p1_asub_p0 + vabsd.bu vr22, vr15, vr14 //q1_asub_q0 + + vreplgr2vr.b vr4, a2 //alpha + vreplgr2vr.b vr5, a3 //beta + + vslt.bu vr6, vr20, vr4 //is_less_than_alpha + vslt.bu vr7, vr21, vr5 //is_less_than_beta + vand.v vr8, vr6, vr7 //is_less_than + vslt.bu vr7, vr22, vr5 //is_less_than_beta + vand.v vr8, vr7, vr8 //is_less_than + vand.v vr8, vr8, vr3 //is_less_than + vsetnez.v $fcc0, vr8 + bceqz $fcc0, .END_LUMA_8 + vneg.b vr9, vr1 //neg_tc_h + vsllwil.hu.bu vr18, vr1, 0 //tc_h.0 + vexth.hu.bu vr19, vr1 //tc_h.1 + vexth.h.b vr2, vr9 //neg_tc_h.1 + vsllwil.h.b vr9, vr9, 0 //neg_tc_h.0 + + vsllwil.hu.bu vr23, vr12, 0 //p1_org_h.0 + vexth.hu.bu vr3, vr12 //p1_org_h.1 + vsllwil.hu.bu vr24, vr13, 0 //p0_org_h.0 + vexth.hu.bu vr4, vr13 //p0_org_h.1 + vsllwil.hu.bu vr25, vr14, 0 //q0_org_h.0 + vexth.hu.bu vr6, vr14 //q0_org_h.1 + + vabsd.bu vr0, vr11, vr13 //p2_asub_p0 + vslt.bu vr7, vr0, vr5 + vand.v vr7, vr8, vr7 //is_less_than_beta + vsetnez.v $fcc0, vr7 + bceqz $fcc0, .END_LUMA_BETA + vsllwil.hu.bu vr26, vr11, 0 //p2_org_h.0 + vexth.hu.bu vr0, vr11 //p2_org_h.1 + AVC_LPF_P1_OR_Q1 vr24, vr25, vr23, vr26, vr9, vr18, vr27, vr28, vr29 + AVC_LPF_P1_OR_Q1 vr4, vr6, vr3, vr0, vr2, vr19, vr28, vr29, vr30 + vpickev.b vr27, vr28, vr27 + vbitsel.v vr12, vr12, vr27, vr7 + vandi.b vr7, vr7, 1 + vadd.b vr1, vr1, vr7 +.END_LUMA_BETA: + vabsd.bu vr26, vr16, vr14 //q2_asub_q0 + vslt.bu vr7, vr26, vr5 + vand.v vr7, vr7, vr8 + vsllwil.hu.bu vr27, vr15, 0 //q1_org_h.0 + vexth.hu.bu vr26, vr15 //q1_org_h.1 + vsetnez.v $fcc0, vr7 + bceqz $fcc0, .END_LUMA_BETA_SEC + vsllwil.hu.bu vr28, vr16, 0 //q2_org_h.0 + vexth.hu.bu vr0, vr16 //q2_org_h.1 + AVC_LPF_P1_OR_Q1 vr24, vr25, vr27, vr28, vr9, vr18, vr29, vr30, vr31 + AVC_LPF_P1_OR_Q1 vr4, vr6, vr26, vr0, vr2, vr19, vr22, vr30, vr31 + vpickev.b vr29, vr22, vr29 + vbitsel.v vr15, vr15, vr29, vr7 + vandi.b vr7, vr7, 1 + vadd.b vr1, vr1, vr7 +.END_LUMA_BETA_SEC: + vneg.b vr22, vr1 //neg_thresh_h + vsllwil.h.b vr28, vr22, 0 //neg_thresh_h.0 + vexth.h.b vr29, vr22 //neg_thresh_h.1 + vsllwil.hu.bu vr18, vr1, 0 //tc_h.0 + vexth.hu.bu vr1, vr1 //tc_h.1 + AVC_LPF_P0Q0 vr25, vr24, vr23, vr27, vr28, vr18, vr30, vr31, vr0, vr2 + AVC_LPF_P0Q0 vr6, vr4, vr3, vr26, vr29, vr1, vr20, vr21, vr0, vr2 + vpickev.b vr30, vr20, vr30 //p0_h + vpickev.b vr31, vr21, vr31 //q0_h + vbitsel.v vr13, vr13, vr30, vr8 //p0_org + vbitsel.v vr14, vr14, vr31, vr8 //q0_org + + vilvl.b vr4, vr12, vr10 // row0.0 + vilvl.b vr5, vr16, vr14 // row0.1 + vilvl.b vr6, vr13, vr11 // row2.0 + vilvl.b vr7, vr17, vr15 // row2.1 + + vilvh.b vr8, vr12, vr10 // row1.0 + vilvh.b vr9, vr16, vr14 // row1.1 + vilvh.b vr10, vr13, vr11 // row3.0 + vilvh.b vr11, vr17, vr15 // row3.1 + + vilvl.b vr12, vr6, vr4 // row4.0 + vilvl.b vr13, vr7, vr5 // row4.1 + vilvl.b vr14, vr10, vr8 // row6.0 + vilvl.b vr15, vr11, vr9 // row6.1 + + vilvh.b vr16, vr6, vr4 // row5.0 + vilvh.b vr17, vr7, vr5 // row5.1 + vilvh.b vr18, vr10, vr8 // row7.0 + vilvh.b vr19, vr11, vr9 // row7.1 + + vilvl.w vr4, vr13, vr12 // row4: 0, 4, 1, 5 + vilvh.w vr5, vr13, vr12 // row4: 2, 6, 3, 7 + vilvl.w vr6, vr17, vr16 // row5: 0, 4, 1, 5 + vilvh.w vr7, vr17, vr16 // row5: 2, 6, 3, 7 + + vilvl.w vr8, vr15, vr14 // row6: 0, 4, 1, 5 + vilvh.w vr9, vr15, vr14 // row6: 2, 6, 3, 7 + vilvl.w vr10, vr19, vr18 // row7: 0, 4, 1, 5 + vilvh.w vr11, vr19, vr18 // row7: 2, 6, 3, 7 + + vbsrl.v vr20, vr4, 8 + vbsrl.v vr21, vr5, 8 + vbsrl.v vr22, vr6, 8 + vbsrl.v vr23, vr7, 8 + + vbsrl.v vr24, vr8, 8 + vbsrl.v vr25, vr9, 8 + vbsrl.v vr26, vr10, 8 + vbsrl.v vr27, vr11, 8 + + store_double f4, f20, f5, f21, t4, a1, t0, t3 + add.d t4, t4, t1 + store_double f6, f22, f7, f23, t4, a1, t0, t3 + add.d t4, t4, t1 + store_double f8, f24, f9, f25, t4, a1, t0, t3 + add.d t4, t4, t1 + store_double f10, f26, f11, f27, t4, a1, t0, t3 +.END_LUMA_8: + RESTORE_REG +endfunc + +function ff_h264_v_lpf_luma_8_lsx + slli.d t0, a1, 1 //img_width_2x + la.local t4, vec_shuf + vldrepl.w vr0, a4, 0 //tmp_vec0 + vld vr1, t4, 0 //tc_vec + add.d t1, t0, a1 //img_width_3x + vshuf.b vr1, vr0, vr0, vr1 //tc_vec + addi.d sp, sp, -24 + fst.d f24, sp, 0 + fst.d f25, sp, 8 + fst.d f26, sp, 16 + vslti.b vr2, vr1, 0 + vxori.b vr2, vr2, 255 + vandi.b vr2, vr2, 1 //bs_vec + vsetnez.v $fcc0, vr2 + bceqz $fcc0, .END_V_LUMA_8 + sub.d t2, a0, t1 //data - img_width_3x + vreplgr2vr.b vr4, a2 //alpha + vreplgr2vr.b vr5, a3 //beta + vldi vr0, 0 //zero + vld vr10, t2, 0 //p2_org + vldx vr11, t2, a1 //p1_org + vldx vr12, t2, t0 //p0_org + vld vr13, a0, 0 //q0_org + vldx vr14, a0, a1 //q1_org + + vslt.bu vr0, vr0, vr2 //is_bs_greater_than0 + vabsd.bu vr16, vr11, vr12 //p1_asub_p0 + vabsd.bu vr15, vr12, vr13 //p0_asub_q0 + vabsd.bu vr17, vr14, vr13 //q1_asub_q0 + + vslt.bu vr6, vr15, vr4 //is_less_than_alpha + vslt.bu vr7, vr16, vr5 //is_less_than_beta + vand.v vr8, vr6, vr7 //is_less_than + vslt.bu vr7, vr17, vr5 //is_less_than_beta + vand.v vr8, vr7, vr8 + vand.v vr8, vr8, vr0 //is_less_than + + vsetnez.v $fcc0, vr8 + bceqz $fcc0, .END_V_LUMA_8 + vldx vr15, a0, t0 //q2_org + vneg.b vr0, vr1 //neg_tc_h + vsllwil.h.b vr18, vr1, 0 //tc_h.0 + vexth.h.b vr19, vr1 //tc_h.1 + vsllwil.h.b vr9, vr0, 0 //neg_tc_h.0 + vexth.h.b vr2, vr0 //neg_tc_h.1 + + vsllwil.hu.bu vr16, vr11, 0 //p1_org_h.0 + vexth.hu.bu vr17, vr11 //p1_org_h.1 + vsllwil.hu.bu vr20, vr12, 0 //p0_org_h.0 + vexth.hu.bu vr21, vr12 //p0_org_h.1 + vsllwil.hu.bu vr22, vr13, 0 //q0_org_h.0 + vexth.hu.bu vr23, vr13 //q0_org_h.1 + + vabsd.bu vr0, vr10, vr12 //p2_asub_p0 + vslt.bu vr7, vr0, vr5 //is_less_than_beta + vand.v vr7, vr7, vr8 //is_less_than_beta + + vsetnez.v $fcc0, vr8 + bceqz $fcc0, .END_V_LESS_BETA + vsllwil.hu.bu vr3, vr10, 0 //p2_org_h.0 + vexth.hu.bu vr4, vr10 //p2_org_h.1 + AVC_LPF_P1_OR_Q1 vr20, vr22, vr16, vr3, vr9, vr18, vr24, vr0, vr26 + AVC_LPF_P1_OR_Q1 vr21, vr23, vr17, vr4, vr2, vr19, vr25, vr0, vr26 + vpickev.b vr24, vr25, vr24 + vbitsel.v vr24, vr11, vr24, vr7 + addi.d t3, t2, 16 + vstx vr24, t2, a1 + vandi.b vr7, vr7, 1 + vadd.b vr1, vr7, vr1 +.END_V_LESS_BETA: + vabsd.bu vr0, vr15, vr13 //q2_asub_q0 + vslt.bu vr7, vr0, vr5 //is_less_than_beta + vand.v vr7, vr7, vr8 //is_less_than_beta + vsllwil.hu.bu vr3, vr14, 0 //q1_org_h.0 + vexth.hu.bu vr4, vr14 //q1_org_h.1 + + vsetnez.v $fcc0, vr7 + bceqz $fcc0, .END_V_LESS_BETA_SEC + vsllwil.hu.bu vr11, vr15, 0 //q2_org_h.0 + vexth.hu.bu vr15, vr15 //q2_org_h.1 + AVC_LPF_P1_OR_Q1 vr20, vr22, vr3, vr11, vr9, vr18, vr24, vr0, vr26 + AVC_LPF_P1_OR_Q1 vr21, vr23, vr4, vr15, vr2, vr19, vr25, vr0, vr26 + vpickev.b vr24, vr25, vr24 + vbitsel.v vr24, vr14, vr24, vr7 + vstx vr24, a0, a1 + vandi.b vr7, vr7, 1 + vadd.b vr1, vr1, vr7 +.END_V_LESS_BETA_SEC: + vneg.b vr0, vr1 + vsllwil.h.b vr9, vr0, 0 //neg_thresh_h.0 + vexth.h.b vr2, vr0 //neg_thresh_h.1 + vsllwil.hu.bu vr18, vr1, 0 //tc_h.0 + vexth.hu.bu vr19, vr1 //tc_h.1 + AVC_LPF_P0Q0 vr22, vr20, vr16, vr3, vr9, vr18, vr11, vr15, vr0, vr26 + AVC_LPF_P0Q0 vr23, vr21, vr17, vr4, vr2, vr19, vr10, vr14, vr0, vr26 + vpickev.b vr11, vr10, vr11 //p0_h + vpickev.b vr15, vr14, vr15 //q0_h + vbitsel.v vr11, vr12, vr11, vr8 //p0_h + vbitsel.v vr15, vr13, vr15, vr8 //q0_h + vstx vr11, t2, t0 + vst vr15, a0, 0 +.END_V_LUMA_8: + fld.d f24, sp, 0 + fld.d f25, sp, 8 + fld.d f26, sp, 16 + addi.d sp, sp, 24 +endfunc + +const chroma_shuf +.byte 0, 0, 1, 1, 2, 2, 3, 3, 0, 0, 1, 1, 2, 2, 3, 3 +endconst + +function ff_h264_h_lpf_chroma_8_lsx + slli.d t0, a1, 1 //img_width_2x + slli.d t1, a1, 2 //img_width_4x + la.local t4, chroma_shuf + add.d t2, t0, a1 //img_width_3x + vldrepl.w vr0, a4, 0 //tmp_vec0 + vld vr1, t4, 0 //tc_vec + vshuf.b vr1, vr0, vr0, vr1 //tc_vec + vslti.b vr2, vr1, 0 + vxori.b vr2, vr2, 255 + vandi.b vr2, vr2, 1 //bs_vec + vsetnez.v $fcc0, vr2 + bceqz $fcc0, .END_CHROMA_8 + vldi vr0, 0 + addi.d t4, a0, -2 + vslt.bu vr3, vr0, vr2 //is_bs_greater_than0 + add.d t5, t4, t1 + vld vr4, t4, 0 //row0 + vldx vr5, t4, a1 //row1 + vldx vr6, t4, t0 //row2 + vldx vr7, t4, t2 //row3 + vld vr8, t5, 0 //row4 + vldx vr9, t5, a1 //row5 + vldx vr10, t5, t0 //row6 + vldx vr11, t5, t2 //row7 + vilvl.b vr12, vr6, vr4 //p1_org + vilvl.b vr13, vr7, vr5 //p0_org + vilvl.b vr14, vr10, vr8 //q0_org + vilvl.b vr15, vr11, vr9 //q1_org + vilvl.b vr4, vr13, vr12 //row0 + vilvl.b vr5, vr15, vr14 //row1 + vilvl.w vr6, vr5, vr4 //row2 + vilvh.w vr7, vr5, vr4 //row3 + vilvl.d vr12, vr6, vr6 //p1_org + vilvh.d vr13, vr6, vr6 //p0_org + vilvl.d vr14, vr7, vr7 //q0_org + vilvh.d vr15, vr7, vr7 //q1_org + + vabsd.bu vr20, vr13, vr14 //p0_asub_q0 + vabsd.bu vr21, vr12, vr13 //p1_asub_p0 + vabsd.bu vr22, vr15, vr14 //q1_asub_q0 + + vreplgr2vr.b vr4, a2 //alpha + vreplgr2vr.b vr5, a3 //beta + + vslt.bu vr6, vr20, vr4 //is_less_than_alpha + vslt.bu vr7, vr21, vr5 //is_less_than_beta + vand.v vr8, vr6, vr7 //is_less_than + vslt.bu vr7, vr22, vr5 //is_less_than_beta + vand.v vr8, vr7, vr8 //is_less_than + vand.v vr8, vr8, vr3 //is_less_than + vsetnez.v $fcc0, vr8 + bceqz $fcc0, .END_CHROMA_8 + + vneg.b vr9, vr1 //neg_tc_h + vexth.hu.bu vr3, vr12 //p1_org_h + vexth.hu.bu vr4, vr13 //p0_org_h.1 + vexth.hu.bu vr5, vr14 //q0_org_h.1 + vexth.hu.bu vr6, vr15 //q1_org_h.1 + + vexth.hu.bu vr18, vr1 //tc_h.1 + vexth.h.b vr2, vr9 //neg_tc_h.1 + + AVC_LPF_P0Q0 vr5, vr4, vr3, vr6, vr2, vr18, vr10, vr11, vr16, vr17 + vpickev.b vr10, vr10, vr10 //p0_h + vpickev.b vr11, vr11, vr11 //q0_h + vbitsel.v vr13, vr13, vr10, vr8 + vbitsel.v vr14, vr14, vr11, vr8 + vilvl.b vr15, vr14, vr13 + addi.d t4, t4, 1 + add.d t5, t4, a1 + add.d t6, t4, t0 + add.d t7, t4, t2 + vstelm.h vr15, t4, 0, 0 + vstelm.h vr15, t5, 0, 1 + vstelm.h vr15, t6, 0, 2 + vstelm.h vr15, t7, 0, 3 + add.d t4, t4, t1 + add.d t5, t4, a1 + add.d t6, t4, t0 + add.d t7, t4, t2 + vstelm.h vr15, t4, 0, 4 + vstelm.h vr15, t5, 0, 5 + vstelm.h vr15, t6, 0, 6 + vstelm.h vr15, t7, 0, 7 +.END_CHROMA_8: +endfunc + +function ff_h264_v_lpf_chroma_8_lsx + slli.d t0, a1, 1 //img_width_2x + la.local t4, chroma_shuf + vldrepl.w vr0, a4, 0 //tmp_vec0 + vld vr1, t4, 0 //tc_vec + vshuf.b vr1, vr0, vr0, vr1 //tc_vec + vslti.b vr2, vr1, 0 + vxori.b vr2, vr2, 255 + vandi.b vr2, vr2, 1 //bs_vec + vsetnez.v $fcc0, vr2 + bceqz $fcc0, .END_CHROMA_V_8 + vldi vr0, 0 + sub.d t4, a0, t0 + vslt.bu vr3, vr0, vr2 //is_bs_greater_than0 + vld vr12, t4, 0 //p1_org + vldx vr13, t4, a1 //p0_org + vld vr14, a0, 0 //q0_org + vldx vr15, a0, a1 //q1_org + + vabsd.bu vr20, vr13, vr14 //p0_asub_q0 + vabsd.bu vr21, vr12, vr13 //p1_asub_p0 + vabsd.bu vr22, vr15, vr14 //q1_asub_q0 + + vreplgr2vr.b vr4, a2 //alpha + vreplgr2vr.b vr5, a3 //beta + + vslt.bu vr6, vr20, vr4 //is_less_than_alpha + vslt.bu vr7, vr21, vr5 //is_less_than_beta + vand.v vr8, vr6, vr7 //is_less_than + vslt.bu vr7, vr22, vr5 //is_less_than_beta + vand.v vr8, vr7, vr8 //is_less_than + vand.v vr8, vr8, vr3 //is_less_than + vsetnez.v $fcc0, vr8 + bceqz $fcc0, .END_CHROMA_V_8 + + vneg.b vr9, vr1 //neg_tc_h + vsllwil.hu.bu vr3, vr12, 0 //p1_org_h + vsllwil.hu.bu vr4, vr13, 0 //p0_org_h.1 + vsllwil.hu.bu vr5, vr14, 0 //q0_org_h.1 + vsllwil.hu.bu vr6, vr15, 0 //q1_org_h.1 + + vexth.hu.bu vr18, vr1 //tc_h.1 + vexth.h.b vr2, vr9 //neg_tc_h.1 + + AVC_LPF_P0Q0 vr5, vr4, vr3, vr6, vr2, vr18, vr10, vr11, vr16, vr17 + vpickev.b vr10, vr10, vr10 //p0_h + vpickev.b vr11, vr11, vr11 //q0_h + vbitsel.v vr10, vr13, vr10, vr8 + vbitsel.v vr11, vr14, vr11, vr8 + fstx.d f10, t4, a1 + fst.d f11, a0, 0 +.END_CHROMA_V_8: +endfunc + +.macro AVC_LPF_P0P1P2_OR_Q0Q1Q2 _in0, _in1, _in2, _in3, _in4, _in5 \ + _out0, _out1, _out2, _tmp0, _const3 + vadd.h \_tmp0, \_in1, \_in2 + vadd.h \_tmp0, \_tmp0, \_in3 + vslli.h \_out2, \_in0, 1 + vslli.h \_out0, \_tmp0, 1 + vadd.h \_out0, \_out0, \_in4 + vadd.h \_out1, \_in4, \_tmp0 + vadd.h \_out0, \_out0, \_in5 + vmadd.h \_out2, \_in4, \_const3 + vsrar.h \_out0, \_out0, \_const3 + vadd.h \_out2, \_out2, \_tmp0 + vsrari.h \_out1, \_out1, 2 + vsrar.h \_out2, \_out2, \_const3 +.endm + +.macro AVC_LPF_P0_OR_Q0 _in0, _in1, _in2, _out0, _tmp0 + vslli.h \_tmp0, \_in2, 1 + vadd.h \_out0, \_in0, \_in1 + vadd.h \_out0, \_out0, \_tmp0 + vsrari.h \_out0, \_out0, 2 +.endm + +////LSX optimization is sufficient for this function. +function ff_h264_h_lpf_luma_intra_8_lsx + slli.d t0, a1, 1 //img_width_2x + slli.d t1, a1, 2 //img_width_4x + addi.d t4, a0, -4 //src + SAVE_REG + add.d t2, t0, a1 //img_width_3x + add.d t5, t4, t1 + vld vr0, t4, 0 //row0 + vldx vr1, t4, a1 //row1 + vldx vr2, t4, t0 //row2 + vldx vr3, t4, t2 //row3 + add.d t6, t5, t1 + vld vr4, t5, 0 //row4 + vldx vr5, t5, a1 //row5 + vldx vr6, t5, t0 //row6 + vldx vr7, t5, t2 //row7 + add.d t7, t6, t1 + vld vr8, t6, 0 //row8 + vldx vr9, t6, a1 //row9 + vldx vr10, t6, t0 //row10 + vldx vr11, t6, t2 //row11 + vld vr12, t7, 0 //row12 + vldx vr13, t7, a1 //row13 + vldx vr14, t7, t0 //row14 + vldx vr15, t7, t2 //row15 + LSX_TRANSPOSE16X8_B vr0, vr1, vr2, vr3, vr4, vr5, vr6, vr7, \ + vr8, vr9, vr10, vr11, vr12, vr13, vr14, vr15, \ + vr0, vr1, vr2, vr3, vr4, vr5, vr6, vr7, \ + vr16, vr17, vr18, vr19, vr20, vr21, vr22, vr23 + // vr0: p3_org, vr1: p2_org, vr2: p1_org, vr3: p0_org + // vr4: q0_org, vr5: q1_org, vr6: q2_org, vr7: q3_org + + vreplgr2vr.b vr16, a2 //alpha_in + vreplgr2vr.b vr17, a3 //beta_in + vabsd.bu vr10, vr3, vr4 //p0_asub_q0 + vabsd.bu vr11, vr2, vr3 //p1_asub_p0 + vabsd.bu vr12, vr5, vr4 //q1_asub_q0 + + vslt.bu vr8, vr10, vr16 //is_less_than_alpha + vslt.bu vr9, vr11, vr17 //is_less_than_beta + vand.v vr18, vr8, vr9 //is_less_than + vslt.bu vr9, vr12, vr17 //is_less_than_beta + vand.v vr18, vr18, vr9 //is_less_than + + vsetnez.v $fcc0, vr18 + bceqz $fcc0, .END_H_INTRA_8 + vsrli.b vr16, vr16, 2 //less_alpha_shift2_add2 + vaddi.bu vr16, vr16, 2 + vslt.bu vr16, vr10, vr16 + vsllwil.hu.bu vr10, vr2, 0 //p1_org_h.0 + vexth.hu.bu vr11, vr2 //p1_org_h.1 + vsllwil.hu.bu vr12, vr3, 0 //p0_org_h.0 + vexth.hu.bu vr13, vr3 //p0_org_h.1 + + vsllwil.hu.bu vr14, vr4, 0 //q0_org_h.0 + vexth.hu.bu vr15, vr4 //q0_org_h.1 + vsllwil.hu.bu vr19, vr5, 0 //q1_org_h.0 + vexth.hu.bu vr20, vr5 //q1_org_h.1 + + vabsd.bu vr21, vr1, vr3 //p2_asub_p0 + vslt.bu vr9, vr21, vr17 //is_less_than_beta + vand.v vr9, vr9, vr16 + vxori.b vr22, vr9, 0xff //negate_is_less_than_beta + vand.v vr9, vr9, vr18 + vand.v vr22, vr22, vr18 + + vsetnez.v $fcc0, vr9 + bceqz $fcc0, .END_H_INTRA_LESS_BETA + vsllwil.hu.bu vr23, vr1, 0 //p2_org_h.0 + vexth.hu.bu vr24, vr1 //p2_org_h.1 + vsllwil.hu.bu vr25, vr0, 0 //p3_org_h.0 + vexth.hu.bu vr26, vr0 //p3_org_h.1 + vldi vr27, 0x403 + + AVC_LPF_P0P1P2_OR_Q0Q1Q2 vr25, vr12, vr14, vr10, vr23, vr19, vr28, vr29, vr30, vr31, vr27 + AVC_LPF_P0P1P2_OR_Q0Q1Q2 vr26, vr13, vr15, vr11, vr24, vr20, vr23, vr25, vr21, vr31, vr27 + vpickev.b vr28, vr23, vr28 //p0_h + vpickev.b vr29, vr25, vr29 //p1_h + vpickev.b vr30, vr21, vr30 //p2_h + vbitsel.v vr3, vr3, vr28, vr9 + vbitsel.v vr2, vr2, vr29, vr9 + vbitsel.v vr1, vr1, vr30, vr9 +.END_H_INTRA_LESS_BETA: + AVC_LPF_P0_OR_Q0 vr12, vr19, vr10, vr23, vr25 + AVC_LPF_P0_OR_Q0 vr13, vr20, vr11, vr24, vr25 + //vr23: p0_h.0 vr24: p0_h.1 + vpickev.b vr23, vr24, vr23 + vbitsel.v vr3, vr3, vr23, vr22 + + vabsd.bu vr21, vr6, vr4 //q2_asub_q0 + vslt.bu vr9, vr21, vr17 //is_less_than_beta + vand.v vr9, vr9, vr16 + vxori.b vr22, vr9, 0xff //negate_is_less_than_beta + vand.v vr9, vr9, vr18 + vand.v vr22, vr22, vr18 + + vsetnez.v $fcc0, vr9 + bceqz $fcc0, .END_H_INTRA_LESS_BETA_SEC + vsllwil.hu.bu vr23, vr6, 0 //q2_org_h.0 + vexth.hu.bu vr24, vr6 //q2_org_h.1 + vsllwil.hu.bu vr25, vr7, 0 //q3_org_h.0 + vexth.hu.bu vr26, vr7 //q3_org_h.1 + vldi vr27, 0x403 + + AVC_LPF_P0P1P2_OR_Q0Q1Q2 vr25, vr14, vr12, vr19, vr23, vr10, vr28, vr29, vr30, vr31, vr27 + AVC_LPF_P0P1P2_OR_Q0Q1Q2 vr26, vr15, vr13, vr20, vr24, vr11, vr23, vr25, vr21, vr31, vr27 + vpickev.b vr28, vr23, vr28 //q0_h + vpickev.b vr29, vr25, vr29 //q1_h + vpickev.b vr30, vr21, vr30 //q2_h + vbitsel.v vr4, vr4, vr28, vr9 + vbitsel.v vr5, vr5, vr29, vr9 + vbitsel.v vr6, vr6, vr30, vr9 +.END_H_INTRA_LESS_BETA_SEC: + AVC_LPF_P0_OR_Q0 vr14, vr10, vr19, vr23, vr25 + AVC_LPF_P0_OR_Q0 vr15, vr11, vr20, vr24, vr25 + vpickev.b vr23, vr24, vr23 + vbitsel.v vr4, vr4, vr23, vr22 + + vilvl.b vr14, vr2, vr0 // row0.0 + vilvl.b vr15, vr6, vr4 // row0.1 + vilvl.b vr16, vr3, vr1 // row2.0 + vilvl.b vr17, vr7, vr5 // row2.1 + + vilvh.b vr18, vr2, vr0 // row1.0 + vilvh.b vr19, vr6, vr4 // row1.1 + vilvh.b vr20, vr3, vr1 // row3.0 + vilvh.b vr21, vr7, vr5 // row3.1 + + vilvl.b vr2, vr16, vr14 // row4.0 + vilvl.b vr3, vr17, vr15 // row4.1 + vilvl.b vr4, vr20, vr18 // row6.0 + vilvl.b vr5, vr21, vr19 // row6.1 + + vilvh.b vr6, vr16, vr14 // row5.0 + vilvh.b vr7, vr17, vr15 // row5.1 + vilvh.b vr8, vr20, vr18 // row7.0 + vilvh.b vr9, vr21, vr19 // row7.1 + + vilvl.w vr14, vr3, vr2 // row4: 0, 4, 1, 5 + vilvh.w vr15, vr3, vr2 // row4: 2, 6, 3, 7 + vilvl.w vr16, vr7, vr6 // row5: 0, 4, 1, 5 + vilvh.w vr17, vr7, vr6 // row5: 2, 6, 3, 7 + + vilvl.w vr18, vr5, vr4 // row6: 0, 4, 1, 5 + vilvh.w vr19, vr5, vr4 // row6: 2, 6, 3, 7 + vilvl.w vr20, vr9, vr8 // row7: 0, 4, 1, 5 + vilvh.w vr21, vr9, vr8 // row7: 2, 6, 3, 7 + + vbsrl.v vr0, vr14, 8 + vbsrl.v vr1, vr15, 8 + vbsrl.v vr2, vr16, 8 + vbsrl.v vr3, vr17, 8 + + vbsrl.v vr4, vr18, 8 + vbsrl.v vr5, vr19, 8 + vbsrl.v vr6, vr20, 8 + vbsrl.v vr7, vr21, 8 + + store_double f14, f0, f15, f1, t4, a1, t0, t2 + store_double f16, f2, f17, f3, t5, a1, t0, t2 + store_double f18, f4, f19, f5, t6, a1, t0, t2 + store_double f20, f6, f21, f7, t7, a1, t0, t2 +.END_H_INTRA_8: + RESTORE_REG +endfunc + +//LSX optimization is sufficient for this function. +function ff_h264_v_lpf_luma_intra_8_lsx + slli.d t0, a1, 1 //img_width_2x + add.d t1, t0, a1 //img_width_3x + SAVE_REG + sub.d t4, a0, t1 //src - img_width_3x + + vld vr0, a0, 0 //q0_org + vldx vr1, a0, a1 //q1_org + vldx vr2, t4, a1 //p1_org + vldx vr3, t4, t0 //p0_org + + vreplgr2vr.b vr4, a2 //alpha + vreplgr2vr.b vr5, a3 //beta + + vabsd.bu vr6, vr3, vr0 //p0_asub_q0 + vabsd.bu vr7, vr2, vr3 //p1_asub_p0 + vabsd.bu vr8, vr1, vr0 //q1_asub_q0 + + vslt.bu vr9, vr6, vr4 //is_less_than_alpha + vslt.bu vr10, vr7, vr5 //is_less_than_beta + vand.v vr11, vr9, vr10 //is_less_than + vslt.bu vr10, vr8, vr5 + vand.v vr11, vr10, vr11 + + vsetnez.v $fcc0, vr11 + bceqz $fcc0, .END_V_INTRA_8 + + vld vr12, t4, 0 //p2_org + vldx vr13, a0, t0 //q2_org + vsrli.b vr14, vr4, 2 //is_alpha_shift2_add2 + vsllwil.hu.bu vr15, vr2, 0 //p1_org_h.0 + vexth.hu.bu vr16, vr2 //p1_org_h.1 + vaddi.bu vr14, vr14, 2 + vsllwil.hu.bu vr17, vr3, 0 //p0_org_h.0 + vexth.hu.bu vr18, vr3 //p0_org_h.1 + vslt.bu vr14, vr6, vr14 + vsllwil.hu.bu vr19, vr0, 0 //q0_org_h.0 + vexth.hu.bu vr20, vr0 //q0_org_h.1 + vsllwil.hu.bu vr21, vr1, 0 //q1_org_h.0 + vexth.hu.bu vr22, vr1 //q1_org_h.1 + + vabsd.bu vr23, vr12, vr3 //p2_asub_p0 + vslt.bu vr10, vr23, vr5 //is_less_than_beta + vand.v vr10, vr10, vr14 + vxori.b vr23, vr10, 0xff //negate_is_less_than_beta + vand.v vr10, vr10, vr11 + vand.v vr23, vr23, vr11 + + vsetnez.v $fcc0, vr10 + bceqz $fcc0, .END_V_INTRA_LESS_BETA + sub.d t5, t4, a1 + vld vr24, t5, 0 //p3_org + vsllwil.hu.bu vr26, vr12, 0 //p2_org_h.0 + vexth.hu.bu vr27, vr12 //p2_org_h.1 + vsllwil.hu.bu vr28, vr24, 0 //p3_org_h.0 + vexth.hu.bu vr29, vr24 //p3_org_h.1 + vldi vr4, 0x403 + + AVC_LPF_P0P1P2_OR_Q0Q1Q2 vr28, vr17, vr19, vr15, vr26, vr21, vr25, vr30, vr31, vr24, vr4 + AVC_LPF_P0P1P2_OR_Q0Q1Q2 vr29, vr18, vr20, vr16, vr27, vr22, vr6, vr7, vr8, vr24, vr4 + + vpickev.b vr25, vr6, vr25 //p0_h + vpickev.b vr30, vr7, vr30 //p1_h + vpickev.b vr31, vr8, vr31 //p2_h + + vbitsel.v vr3, vr3, vr25, vr10 + vbitsel.v vr2, vr2, vr30, vr10 + vbitsel.v vr12, vr12, vr31, vr10 + + vstx vr2, t4, a1 + vst vr12, t4, 0 +.END_V_INTRA_LESS_BETA: + AVC_LPF_P0_OR_Q0 vr17, vr21, vr15, vr24, vr30 + AVC_LPF_P0_OR_Q0 vr18, vr22, vr16, vr25, vr30 + vpickev.b vr24, vr25, vr24 + vbitsel.v vr3, vr3, vr24, vr23 + vstx vr3, t4, t0 + + vabsd.bu vr23, vr13, vr0 //q2_asub_q0 + vslt.bu vr10, vr23, vr5 //is_less_than_beta + vand.v vr10, vr10, vr14 + vxori.b vr23, vr10, 0xff //negate_is_less_than_beta + vand.v vr10, vr10, vr11 + vand.v vr23, vr23, vr11 + + vsetnez.v $fcc0, vr10 + bceqz $fcc0, .END_V_INTRA_LESS_BETA_SEC + vldx vr24, a0, t1 //q3_org + + vsllwil.hu.bu vr26, vr13, 0 //q2_org_h.0 + vexth.hu.bu vr27, vr13 //q2_org_h.1 + vsllwil.hu.bu vr28, vr24, 0 //q3_org_h.0 + vexth.hu.bu vr29, vr24 //q3_org_h.1 + vldi vr4, 0x403 + + AVC_LPF_P0P1P2_OR_Q0Q1Q2 vr28, vr19, vr17, vr21, vr26, vr15, vr25, vr30, vr31, vr24, vr4 + AVC_LPF_P0P1P2_OR_Q0Q1Q2 vr29, vr20, vr18, vr22, vr27, vr16, vr6, vr7, vr8, vr24, vr4 + + vpickev.b vr25, vr6, vr25 + vpickev.b vr30, vr7, vr30 + vpickev.b vr31, vr8, vr31 + + vbitsel.v vr0, vr0, vr25, vr10 + vbitsel.v vr1, vr1, vr30, vr10 + vbitsel.v vr13, vr13, vr31, vr10 + vstx vr1, a0, a1 + vstx vr13, a0, t0 +.END_V_INTRA_LESS_BETA_SEC: + AVC_LPF_P0_OR_Q0 vr19, vr15, vr21, vr24, vr30 + AVC_LPF_P0_OR_Q0 vr20, vr16, vr22, vr25, vr30 + vpickev.b vr24, vr25, vr24 + vbitsel.v vr0, vr0, vr24, vr23 + vst vr0, a0, 0 +.END_V_INTRA_8: + RESTORE_REG +endfunc + +function ff_h264_h_lpf_chroma_intra_8_lsx + addi.d t4, a0, -2 + slli.d t0, a1, 1 //img_2x + slli.d t2, a1, 2 //img_4x + add.d t1, t0, a1 //img_3x + + add.d t5, t4, t2 + fld.s f0, t4, 0 //row0 + fldx.s f1, t4, a1 //row1 + fldx.s f2, t4, t0 //row2 + fldx.s f3, t4, t1 //row3 + fld.s f4, t5, 0 //row4 + fldx.s f5, t5, a1 //row5 + fldx.s f6, t5, t0 //row6 + fldx.s f7, t5, t1 //row7 + + vilvl.b vr8, vr2, vr0 //p1_org + vilvl.b vr9, vr3, vr1 //p0_org + vilvl.b vr10, vr6, vr4 //q0_org + vilvl.b vr11, vr7, vr5 //q1_org + + vilvl.b vr0, vr9, vr8 + vilvl.b vr1, vr11, vr10 + vilvl.w vr2, vr1, vr0 + vilvh.w vr3, vr1, vr0 + + vilvl.d vr8, vr2, vr2 //p1_org + vilvh.d vr9, vr2, vr2 //p0_org + vilvl.d vr10, vr3, vr3 //q0_org + vilvh.d vr11, vr3, vr3 //q1_org + + vreplgr2vr.b vr0, a2 //alpha + vreplgr2vr.b vr1, a3 //beta + + vabsd.bu vr2, vr9, vr10 //p0_asub_q0 + vabsd.bu vr3, vr8, vr9 //p1_asub_p0 + vabsd.bu vr4, vr11, vr10 //q1_asub_q0 + + vslt.bu vr5, vr2, vr0 //is_less_than_alpha + vslt.bu vr6, vr3, vr1 //is_less_than_beta + vand.v vr7, vr5, vr6 //is_less_than + vslt.bu vr6, vr4, vr1 + vand.v vr7, vr7, vr6 + + vsetnez.v $fcc0, vr7 + bceqz $fcc0, .END_H_CHROMA_INTRA_8 + + vexth.hu.bu vr12, vr8 //p1_org_h + vexth.hu.bu vr13, vr9 //p0_org_h + vexth.hu.bu vr14, vr10 //q0_org_h + vexth.hu.bu vr15, vr11 //q1_org_h + + AVC_LPF_P0_OR_Q0 vr13, vr15, vr12, vr16, vr18 + AVC_LPF_P0_OR_Q0 vr14, vr12, vr15, vr17, vr18 + + vpickev.b vr18, vr16, vr16 + vpickev.b vr19, vr17, vr17 + vbitsel.v vr9, vr9, vr18, vr7 + vbitsel.v vr10, vr10, vr19, vr7 +.END_H_CHROMA_INTRA_8: + vilvl.b vr11, vr10, vr9 + addi.d t4, t4, 1 + vstelm.h vr11, t4, 0, 0 + add.d t4, t4, a1 + vstelm.h vr11, t4, 0, 1 + add.d t4, t4, a1 + vstelm.h vr11, t4, 0, 2 + add.d t4, t4, a1 + vstelm.h vr11, t4, 0, 3 + add.d t4, t4, a1 + vstelm.h vr11, t4, 0, 4 + add.d t4, t4, a1 + vstelm.h vr11, t4, 0, 5 + add.d t4, t4, a1 + vstelm.h vr11, t4, 0, 6 + add.d t4, t4, a1 + vstelm.h vr11, t4, 0, 7 +endfunc + +function ff_h264_v_lpf_chroma_intra_8_lsx + slli.d t0, a1, 1 //img_width_2x + sub.d t2, a0, a1 + sub.d t1, a0, t0 //data - img_width_2x + + vreplgr2vr.b vr0, a2 + vreplgr2vr.b vr1, a3 + + vld vr2, t1, 0 //p1_org + vldx vr3, t1, a1 //p0_org + vld vr4, a0, 0 //q0_org + vldx vr5, a0, a1 //q1_org + + vabsd.bu vr6, vr3, vr4 //p0_asub_q0 + vabsd.bu vr7, vr2, vr3 //p1_asub_p0 + vabsd.bu vr8, vr5, vr4 //q1_asub_q0 + + vslt.bu vr9, vr6, vr0 //is_less_than_alpha + vslt.bu vr10, vr7, vr1 //is_less_than_beta + vand.v vr11, vr9, vr10 //is_less_than + vslt.bu vr10, vr8, vr1 + vand.v vr11, vr10, vr11 + + vsetnez.v $fcc0, vr11 + bceqz $fcc0, .END_V_CHROMA_INTRA_8 + + vsllwil.hu.bu vr6, vr2, 0 //p1_org_h.0 + vsllwil.hu.bu vr8, vr3, 0 //p0_org_h.0 + vsllwil.hu.bu vr13, vr4, 0 //q0_org_h.0 + vsllwil.hu.bu vr15, vr5, 0 //q1_org_h.0 + + AVC_LPF_P0_OR_Q0 vr8, vr15, vr6, vr17, vr23 + AVC_LPF_P0_OR_Q0 vr13, vr6, vr15, vr18, vr23 + + vpickev.b vr19, vr17, vr17 + vpickev.b vr20, vr18, vr18 + vbitsel.v vr3, vr3, vr19, vr11 + vbitsel.v vr4, vr4, vr20, vr11 + + vstelm.d vr3, t2, 0, 0 + vstelm.d vr4, a0, 0, 0 +.END_V_CHROMA_INTRA_8: +endfunc + +.macro biweight_calc _in0, _in1, _in2, _in3, _reg0, _reg1, _reg2,\ + _out0, _out1, _out2, _out3 + vmov \_out0, \_reg0 + vmov \_out1, \_reg0 + vmov \_out2, \_reg0 + vmov \_out3, \_reg0 + vmaddwev.h.bu.b \_out0, \_in0, \_reg1 + vmaddwev.h.bu.b \_out1, \_in1, \_reg1 + vmaddwev.h.bu.b \_out2, \_in2, \_reg1 + vmaddwev.h.bu.b \_out3, \_in3, \_reg1 + vmaddwod.h.bu.b \_out0, \_in0, \_reg1 + vmaddwod.h.bu.b \_out1, \_in1, \_reg1 + vmaddwod.h.bu.b \_out2, \_in2, \_reg1 + vmaddwod.h.bu.b \_out3, \_in3, \_reg1 + + vssran.bu.h \_out0, \_out0, \_reg2 + vssran.bu.h \_out1, \_out1, \_reg2 + vssran.bu.h \_out2, \_out2, \_reg2 + vssran.bu.h \_out3, \_out3, \_reg2 +.endm + +.macro biweight_load_8 + load_double f0, f1, f2, f3, a1, a2, t0, t1 + load_double f10, f11, f12, f13, a0, a2, t0, t1 + + vilvl.d vr0, vr1, vr0 //src0 + vilvl.d vr2, vr3, vr2 //src2 + vilvl.d vr10, vr11, vr10 //dst0 + vilvl.d vr12, vr13, vr12 //dst2 + + vilvl.b vr1, vr10, vr0 //vec0.0 + vilvh.b vr3, vr10, vr0 //vec0.1 + vilvl.b vr5, vr12, vr2 //vec1.0 + vilvh.b vr7, vr12, vr2 //vec1.1 +.endm + +.macro biweight_8 + biweight_calc vr1, vr3, vr5, vr7, vr8, vr20, vr9, vr0, vr2, vr4, vr6 + vilvl.d vr0, vr2, vr0 + vilvl.d vr2, vr6, vr4 + + vbsrl.v vr1, vr0, 8 + vbsrl.v vr3, vr2, 8 + + store_double f0, f1, f2, f3, a0, a2, t0, t1 +.endm + +.macro biweight_load2_8 + biweight_load_8 + load_double f0, f2, f4, f6, t4, a2, t0, t1 + load_double f14, f15, f16, f17, t5, a2, t0, t1 + + vilvl.d vr0, vr2, vr0 //src4 + vilvl.d vr4, vr6, vr4 //src6 + vilvl.d vr14, vr15, vr14 //dst4 + vilvl.d vr16, vr17, vr16 //dst6 + + vilvl.b vr11, vr14, vr0 //vec4.0 + vilvh.b vr13, vr14, vr0 //vec4.1 + vilvl.b vr15, vr16, vr4 //vec6.0 + vilvh.b vr17, vr16, vr4 //vec6.1 +.endm + +.macro biweight2_8 + biweight_8 + biweight_calc vr11, vr13, vr15, vr17, vr8, vr20, vr9, \ + vr10, vr12, vr14, vr16 + vilvl.d vr10, vr12, vr10 + vilvl.d vr12, vr16, vr14 + + vbsrl.v vr11, vr10, 8 + vbsrl.v vr13, vr12, 8 + + store_double f10, f11, f12, f13, t5, a2, t0, t1 +.endm + +.macro biweight_load_16 + add.d t4, a1, t2 + vld vr0, a1, 0 + vldx vr1, a1, a2 + vldx vr2, a1, t0 + vldx vr3, a1, t1 + vld vr4, t4, 0 + vldx vr5, t4, a2 + vldx vr6, t4, t0 + vldx vr7, t4, t1 + + add.d t5, a0, t2 + vld vr10, a0, 0 + vldx vr11, a0, a2 + vldx vr12, a0, t0 + vldx vr13, a0, t1 + vld vr14, t5, 0 + vldx vr15, t5, a2 + vldx vr16, t5, t0 + vldx vr17, t5, t1 + + vilvl.b vr18, vr10, vr0 + vilvl.b vr19, vr11, vr1 + vilvl.b vr21, vr12, vr2 + vilvl.b vr22, vr13, vr3 + vilvh.b vr0, vr10, vr0 + vilvh.b vr1, vr11, vr1 + vilvh.b vr2, vr12, vr2 + vilvh.b vr3, vr13, vr3 + + vilvl.b vr10, vr14, vr4 + vilvl.b vr11, vr15, vr5 + vilvl.b vr12, vr16, vr6 + vilvl.b vr13, vr17, vr7 + vilvh.b vr14, vr14, vr4 + vilvh.b vr15, vr15, vr5 + vilvh.b vr16, vr16, vr6 + vilvh.b vr17, vr17, vr7 +.endm + +.macro biweight_16 + biweight_calc vr18, vr19, vr21, vr22, vr8, vr20, vr9, vr4, vr5, vr6, vr7 + biweight_calc vr0, vr1, vr2, vr3, vr8, vr20, vr9, vr18, vr19, vr21, vr22 + biweight_calc vr10, vr11, vr12, vr13, vr8, vr20, vr9, vr0, vr1, vr2, vr3 + biweight_calc vr14, vr15, vr16, vr17, vr8, vr20, vr9, vr10, vr11, vr12, vr13 + + vilvl.d vr4, vr18, vr4 + vilvl.d vr5, vr19, vr5 + vilvl.d vr6, vr21, vr6 + vilvl.d vr7, vr22, vr7 + vilvl.d vr0, vr10, vr0 + vilvl.d vr1, vr11, vr1 + vilvl.d vr2, vr12, vr2 + vilvl.d vr3, vr13, vr3 + + vst vr4, a0, 0 + vstx vr5, a0, a2 + vstx vr6, a0, t0 + vstx vr7, a0, t1 + vst vr0, t5, 0 + vstx vr1, t5, a2 + vstx vr2, t5, t0 + vstx vr3, t5, t1 +.endm + +.macro biweight_func w +function ff_biweight_h264_pixels\w\()_8_lsx + slli.d t0, a2, 1 + slli.d t2, a2, 2 + add.d t1, t0, a2 + addi.d a7, a7, 1 + ori a7, a7, 1 + sll.d a7, a7, a4 + addi.d a4, a4, 1 + + vreplgr2vr.b vr0, a6 //tmp0 + vreplgr2vr.b vr1, a5 //tmp1 + vreplgr2vr.h vr8, a7 //offset + vreplgr2vr.h vr9, a4 //denom + vilvh.b vr20, vr1, vr0 //wgt +.endm + +biweight_func 8 + addi.d t3, zero, 8 + biweight_load_8 + biweight_8 + blt a3, t3, .END_BIWEIGHT_H264_PIXELS8 + addi.d t3, zero, 16 + add.d a1, a1, t2 + add.d a0, a0, t2 + biweight_load_8 + biweight_8 + blt a3, t3, .END_BIWEIGHT_H264_PIXELS8 + add.d a1, a1, t2 + add.d a0, a0, t2 + add.d t4, a1, t2 + add.d t5, a0, t2 + biweight_load2_8 + biweight2_8 +.END_BIWEIGHT_H264_PIXELS8: +endfunc + +biweight_func 16 + addi.d t6, zero, 16 + biweight_load_16 + biweight_16 + + bne a3, t6, .END_BIWEIGHT_PIXELS16 + add.d a1, t4, t2 + add.d a0, t5, t2 + biweight_load_16 + biweight_16 +.END_BIWEIGHT_PIXELS16: +endfunc + +.macro biweight_calc_4 _in0, _out0 + vmov \_out0, vr8 + vmaddwev.h.bu.b \_out0, \_in0, vr20 + vmaddwod.h.bu.b \_out0, \_in0, vr20 + vssran.bu.h \_out0, \_out0, vr9 +.endm + +//LSX optimization is sufficient for this function. +biweight_func 4 + addi.d t3, zero, 4 + fld.s f0, a1, 0 + fldx.s f1, a1, a2 + fld.s f10, a0, 0 + fldx.s f11, a0, a2 + vilvl.w vr2, vr1, vr0 + vilvl.w vr12, vr11, vr10 + vilvl.b vr0, vr12, vr2 + + biweight_calc_4 vr0, vr1 + vbsrl.v vr2, vr1, 4 + fst.s f1, a0, 0 + fstx.s f2, a0, a2 + + blt a3, t3, .END_BIWEIGHT_H264_PIXELS4 + addi.d t3, zero, 8 + fldx.s f0, a1, t0 + fldx.s f1, a1, t1 + fldx.s f10, a0, t0 + fldx.s f11, a0, t1 + vilvl.w vr2, vr1, vr0 + vilvl.w vr12, vr11, vr10 + vilvl.b vr0, vr12, vr2 + + biweight_calc_4 vr0, vr1 + vbsrl.v vr2, vr1, 4 + fstx.s f1, a0, t0 + fstx.s f2, a0, t1 + blt a3, t3, .END_BIWEIGHT_H264_PIXELS4 + add.d a1, a1, t2 + add.d a0, a0, t2 + fld.s f0, a1, 0 + fldx.s f1, a1, a2 + fldx.s f2, a1, t0 + fldx.s f3, a1, t1 + fld.s f10, a0, 0 + fldx.s f11, a0, a2 + fldx.s f12, a0, t0 + fldx.s f13, a0, t1 + vilvl.w vr4, vr1, vr0 + vilvl.w vr5, vr3, vr2 + vilvl.w vr14, vr11, vr10 + vilvl.w vr15, vr13, vr12 + + vilvl.b vr0, vr14, vr4 + vilvl.b vr10, vr15, vr5 + + vmov vr1, vr8 + vmov vr11, vr8 + vmaddwev.h.bu.b vr1, vr0, vr20 + vmaddwev.h.bu.b vr11, vr10, vr20 + vmaddwod.h.bu.b vr1, vr0, vr20 + vmaddwod.h.bu.b vr11, vr10, vr20 + + vssran.bu.h vr0, vr1, vr9 //vec0 + vssran.bu.h vr10, vr11, vr9 //vec0 + vbsrl.v vr2, vr0, 4 + vbsrl.v vr12, vr10, 4 + + fst.s f0, a0, 0 + fstx.s f2, a0, a2 + fstx.s f10, a0, t0 + fstx.s f12, a0, t1 +.END_BIWEIGHT_H264_PIXELS4: +endfunc + +.macro biweight_func_lasx w +function ff_biweight_h264_pixels\w\()_8_lasx + slli.d t0, a2, 1 + slli.d t2, a2, 2 + add.d t1, t0, a2 + addi.d a7, a7, 1 + ori a7, a7, 1 + sll.d a7, a7, a4 + addi.d a4, a4, 1 + + xvreplgr2vr.b xr0, a6 //tmp0 + xvreplgr2vr.b xr1, a5 //tmp1 + xvreplgr2vr.h xr8, a7 //offset + xvreplgr2vr.h xr9, a4 //denom + xvilvh.b xr20, xr1, xr0 //wgt +.endm + +.macro biweight_calc_lasx _in0, _in1, _reg0, _reg1, _reg2, _out0, _out1 + xmov \_out0, \_reg0 + xmov \_out1, \_reg0 + xvmaddwev.h.bu.b \_out0, \_in0, \_reg1 + xvmaddwev.h.bu.b \_out1, \_in1, \_reg1 + xvmaddwod.h.bu.b \_out0, \_in0, \_reg1 + xvmaddwod.h.bu.b \_out1, \_in1, \_reg1 + + xvssran.bu.h \_out0, \_out0, \_reg2 + xvssran.bu.h \_out1, \_out1, \_reg2 +.endm + +.macro biweight_load_lasx_8 + load_double f0, f1, f2, f3, a1, a2, t0, t1 + load_double f10, f11, f12, f13, a0, a2, t0, t1 + + vilvl.d vr0, vr1, vr0 //src0 + vilvl.d vr2, vr3, vr2 //src2 + vilvl.d vr10, vr11, vr10 //dst0 + vilvl.d vr12, vr13, vr12 //dst2 + + xvpermi.q xr2, xr0, 0x20 + xvpermi.q xr12, xr10, 0x20 + + xvilvl.b xr0, xr12, xr2 + xvilvh.b xr1, xr12, xr2 +.endm + +.macro biweight_lasx_8 + biweight_calc_lasx xr0, xr1, xr8, xr20, xr9, xr2, xr3 + xvilvl.d xr0, xr3, xr2 + xvpermi.d xr2, xr0, 0x4E + vbsrl.v vr1, vr0, 8 + vbsrl.v vr3, vr2, 8 + + store_double f0, f1, f2, f3, a0, a2, t0, t1 +.endm + +biweight_func_lasx 8 + addi.d t3, zero, 8 + biweight_load_lasx_8 + biweight_lasx_8 + blt a3, t3, .END_BIWEIGHT_H264_PIXELS8_LASX + addi.d t3, zero, 16 + add.d a1, a1, t2 + add.d a0, a0, t2 + biweight_load_lasx_8 + biweight_lasx_8 + blt a3, t3, .END_BIWEIGHT_H264_PIXELS8_LASX + add.d a1, a1, t2 + add.d a0, a0, t2 + add.d t4, a1, t2 + add.d t5, a0, t2 + biweight_load_lasx_8 + load_double f4, f5, f6, f7, t4, a2, t0, t1 + load_double f14, f15, f16, f17, t5, a2, t0, t1 + vilvl.d vr4, vr5, vr4 //src4 + vilvl.d vr6, vr7, vr6 //src6 + vilvl.d vr14, vr15, vr14 //dst4 + vilvl.d vr16, vr17, vr16 //dst6 + xvpermi.q xr6, xr4, 0x20 + xvpermi.q xr16, xr14, 0x20 + xvilvl.b xr10, xr16, xr6 + xvilvh.b xr11, xr16, xr6 + biweight_lasx_8 + biweight_calc_lasx xr10, xr11, xr8, xr20, xr9, xr12, xr13 + xvilvl.d xr10, xr13, xr12 + xvpermi.d xr12, xr10, 0x4E + vbsrl.v vr11, vr10, 8 + vbsrl.v vr13, vr12, 8 + store_double f10, f11, f12, f13, t5, a2, t0, t1 +.END_BIWEIGHT_H264_PIXELS8_LASX: +endfunc + +.macro biweight_load_lasx_16 + add.d t4, a1, t2 + vld vr0, a1, 0 + vldx vr1, a1, a2 + vldx vr2, a1, t0 + vldx vr3, a1, t1 + vld vr4, t4, 0 + vldx vr5, t4, a2 + vldx vr6, t4, t0 + vldx vr7, t4, t1 + + add.d t5, a0, t2 + vld vr10, a0, 0 + vldx vr11, a0, a2 + vldx vr12, a0, t0 + vldx vr13, a0, t1 + vld vr14, t5, 0 + vldx vr15, t5, a2 + vldx vr16, t5, t0 + vldx vr17, t5, t1 + + xvpermi.q xr1, xr0, 0x20 + xvpermi.q xr3, xr2, 0x20 + xvpermi.q xr5, xr4, 0x20 + xvpermi.q xr7, xr6, 0x20 + + xvpermi.q xr11, xr10, 0x20 + xvpermi.q xr13, xr12, 0x20 + xvpermi.q xr15, xr14, 0x20 + xvpermi.q xr17, xr16, 0x20 + + xvilvl.b xr0, xr11, xr1 //vec0 + xvilvl.b xr2, xr13, xr3 //vec2 + xvilvl.b xr4, xr15, xr5 //vec4 + xvilvl.b xr6, xr17, xr7 //vec6 + + xvilvh.b xr10, xr11, xr1 //vec1 + xvilvh.b xr12, xr13, xr3 //vec2 + xvilvh.b xr14, xr15, xr5 //vec5 + xvilvh.b xr16, xr17, xr7 //vec7 +.endm + +.macro biweight_lasx_16 + biweight_calc_lasx xr0, xr2, xr8, xr20, xr9, xr1, xr3 + biweight_calc_lasx xr4, xr6, xr8, xr20, xr9, xr5, xr7 + biweight_calc_lasx xr10, xr12, xr8, xr20, xr9, xr11, xr13 + biweight_calc_lasx xr14, xr16, xr8, xr20, xr9, xr15, xr17 + xvilvl.d xr0, xr11, xr1 + xvilvl.d xr2, xr13, xr3 + xvilvl.d xr4, xr15, xr5 + xvilvl.d xr6, xr17, xr7 + + xvpermi.d xr1, xr0, 0x4E + xvpermi.d xr3, xr2, 0x4E + xvpermi.d xr5, xr4, 0x4E + xvpermi.d xr7, xr6, 0x4E + vst vr0, a0, 0 + vstx vr1, a0, a2 + vstx vr2, a0, t0 + vstx vr3, a0, t1 + vst vr4, t5, 0 + vstx vr5, t5, a2 + vstx vr6, t5, t0 + vstx vr7, t5, t1 +.endm + +biweight_func_lasx 16 + addi.d t6, zero, 16 + biweight_load_lasx_16 + biweight_lasx_16 + bne a3, t6, .END_BIWEIGHT_PIXELS16_LASX + add.d a1, t4, t2 + add.d a0, t5, t2 + biweight_load_lasx_16 + biweight_lasx_16 +.END_BIWEIGHT_PIXELS16_LASX: +endfunc + +.macro weight_func w +function ff_weight_h264_pixels\w\()_8_lsx + slli.d t0, a1, 1 + slli.d t2, a1, 2 + add.d t1, t0, a1 + + sll.d a5, a5, a3 + vreplgr2vr.h vr20, a4 //weight + vreplgr2vr.h vr8, a5 //offset + vreplgr2vr.h vr9, a3 //log2_denom +.endm + +.macro weight_load_16 + add.d t4, a0, t2 + vld vr0, a0, 0 + vldx vr1, a0, a1 + vldx vr2, a0, t0 + vldx vr3, a0, t1 + vld vr4, t4, 0 + vldx vr5, t4, a1 + vldx vr6, t4, t0 + vldx vr7, t4, t1 + + vilvl.b vr10, vr23, vr0 + vilvl.b vr11, vr23, vr1 + vilvl.b vr12, vr23, vr2 + vilvl.b vr13, vr23, vr3 + vilvl.b vr14, vr23, vr4 + vilvl.b vr15, vr23, vr5 + vilvl.b vr16, vr23, vr6 + vilvl.b vr17, vr23, vr7 +.endm + +.macro weight_extend_16 + vilvl.b vr10, vr23, vr0 + vilvl.b vr11, vr23, vr1 + vilvl.b vr12, vr23, vr2 + vilvl.b vr13, vr23, vr3 + vilvl.b vr14, vr23, vr4 + vilvl.b vr15, vr23, vr5 + vilvl.b vr16, vr23, vr6 + vilvl.b vr17, vr23, vr7 + + vilvh.b vr18, vr23, vr0 + vilvh.b vr19, vr23, vr1 + vilvh.b vr21, vr23, vr2 + vilvh.b vr22, vr23, vr3 + vilvh.b vr0, vr23, vr4 + vilvh.b vr1, vr23, vr5 + vilvh.b vr2, vr23, vr6 + vilvh.b vr3, vr23, vr7 +.endm + +.macro weight_calc _in0, _in1, _in2, _in3, _reg0, _reg1, _reg2, \ + _out0, _out1, _out2, _out3 + vmul.h \_in0, \_in0, \_reg1 + vmul.h \_in1, \_in1, \_reg1 + vmul.h \_in2, \_in2, \_reg1 + vmul.h \_in3, \_in3, \_reg1 + vsadd.h \_out0, \_reg0, \_in0 + vsadd.h \_out1, \_reg0, \_in1 + vsadd.h \_out2, \_reg0, \_in2 + vsadd.h \_out3, \_reg0, \_in3 + vssrarn.bu.h \_out0, \_out0, \_reg2 + vssrarn.bu.h \_out1, \_out1, \_reg2 + vssrarn.bu.h \_out2, \_out2, \_reg2 + vssrarn.bu.h \_out3, \_out3, \_reg2 +.endm + +.macro weight_16 + weight_calc vr10, vr11, vr12, vr13, vr8, vr20, vr9, vr10, vr11, vr12, vr13 + weight_calc vr14, vr15, vr16, vr17, vr8, vr20, vr9, vr14, vr15, vr16, vr17 + weight_calc vr18, vr19, vr21, vr22, vr8, vr20, vr9, vr4, vr5, vr6, vr7 + weight_calc vr0, vr1, vr2, vr3, vr8, vr20, vr9, vr0, vr1, vr2, vr3 + + vilvl.d vr10, vr4, vr10 + vilvl.d vr11, vr5, vr11 + vilvl.d vr12, vr6, vr12 + vilvl.d vr13, vr7, vr13 + vilvl.d vr14, vr0, vr14 + vilvl.d vr15, vr1, vr15 + vilvl.d vr16, vr2, vr16 + vilvl.d vr17, vr3, vr17 + + vst vr10, a0, 0 + vstx vr11, a0, a1 + vstx vr12, a0, t0 + vstx vr13, a0, t1 + vst vr14, t4, 0 + vstx vr15, t4, a1 + vstx vr16, t4, t0 + vstx vr17, t4, t1 +.endm + +weight_func 16 + vldi vr23, 0 + addi.d t3, zero, 16 + weight_load_16 + weight_extend_16 + weight_16 + bne a2, t3, .END_WEIGHT_H264_PIXELS16_8 + add.d a0, t4, t2 + weight_load_16 + weight_extend_16 + weight_16 +.END_WEIGHT_H264_PIXELS16_8: +endfunc + +.macro weight_load_8 + load_double f0, f1, f2, f3, a0, a1, t0, t1 +.endm + +.macro weight_extend_8 + vilvl.b vr10, vr21, vr0 + vilvl.b vr11, vr21, vr1 + vilvl.b vr12, vr21, vr2 + vilvl.b vr13, vr21, vr3 +.endm + +.macro weight_8 + weight_calc vr10, vr11, vr12, vr13, vr8, vr20, vr9, vr0, vr1, vr2, vr3 + store_double f0, f1, f2, f3, a0, a1, t0, t1 +.endm + +weight_func 8 + vldi vr21, 0 + addi.d t3, zero, 8 + weight_load_8 + weight_extend_8 + weight_8 + blt a2, t3, .END_WEIGHT_H264_PIXELS8 + add.d a0, a0, t2 + addi.d t3, zero, 16 + weight_load_8 + weight_extend_8 + weight_8 + blt a2, t3, .END_WEIGHT_H264_PIXELS8 + add.d a0, a0, t2 + add.d t4, a0, t2 + weight_load_8 + load_double f4, f5, f6, f7, t4, a1, t0, t1 + weight_extend_8 + vilvl.b vr14, vr21, vr4 + vilvl.b vr15, vr21, vr5 + vilvl.b vr16, vr21, vr6 + vilvl.b vr17, vr21, vr7 + weight_8 + weight_calc vr14, vr15, vr16, vr17, vr8, vr20, vr9, vr4, vr5, vr6, vr7 + store_double f4, f5, f6, f7, t4, a1, t0, t1 +.END_WEIGHT_H264_PIXELS8: +endfunc + +.macro weight_func_lasx w +function ff_weight_h264_pixels\w\()_8_lasx + slli.d t0, a1, 1 + slli.d t2, a1, 2 + add.d t1, t0, a1 + + sll.d a5, a5, a3 + xvreplgr2vr.h xr20, a4 //weight + xvreplgr2vr.h xr8, a5 //offset + xvreplgr2vr.h xr9, a3 //log2_denom +.endm + +.macro weight_calc_lasx _in0, _in1, _reg0, _reg1, _reg2, _out0, _out1 + xvmul.h \_out0, \_in0, \_reg1 + xvmul.h \_out1, \_in1, \_reg1 + xvsadd.h \_out0, \_reg0, \_out0 + xvsadd.h \_out1, \_reg0, \_out1 + xvssrarn.bu.h \_out0, \_out0, \_reg2 + xvssrarn.bu.h \_out1, \_out1, \_reg2 +.endm + +.macro weight_load_lasx_8 + load_double f0, f1, f2, f3, a0, a1, t0, t1 + vilvl.d vr4, vr1, vr0 + vilvl.d vr5, vr3, vr2 + vext2xv.hu.bu xr6, xr4 + vext2xv.hu.bu xr7, xr5 +.endm + +.macro weight_lasx_8 + weight_calc_lasx xr6, xr7, xr8, xr20, xr9, xr1, xr3 + xvpermi.d xr2, xr1, 0x2 + xvpermi.d xr4, xr3, 0x2 + store_double f1, f2, f3, f4, a0, a1, t0, t1 +.endm + +weight_func_lasx 8 + addi.d t3, zero, 8 + weight_load_lasx_8 + weight_lasx_8 + blt a2, t3, .END_WEIGHT_H264_PIXELS8_LASX + add.d a0, a0, t2 + addi.d t3, zero, 16 + weight_load_lasx_8 + weight_lasx_8 + blt a2, t3, .END_WEIGHT_H264_PIXELS8_LASX + add.d a0, a0, t2 + add.d t4, a0, t2 + weight_load_lasx_8 + load_double f14, f15, f16, f17, t4, a1, t0, t1 + vilvl.d vr4, vr15, vr14 + vilvl.d vr5, vr17, vr16 + vext2xv.hu.bu xr10, xr4 + vext2xv.hu.bu xr11, xr5 + weight_lasx_8 + weight_calc_lasx xr10, xr11, xr8, xr20, xr9, xr4, xr6 + xvpermi.d xr5, xr4, 0x2 + xvpermi.d xr7, xr6, 0x2 + store_double f4, f5, f6, f7, t4, a1, t0, t1 +.END_WEIGHT_H264_PIXELS8_LASX: +endfunc + +.macro weight_load_lasx_16 + add.d t4, a0, t2 + vld vr0, a0, 0 + vldx vr1, a0, a1 + vldx vr2, a0, t0 + vldx vr3, a0, t1 + vld vr4, t4, 0 + vldx vr5, t4, a1 + vldx vr6, t4, t0 + vldx vr7, t4, t1 + + vext2xv.hu.bu xr0, xr0 + vext2xv.hu.bu xr1, xr1 + vext2xv.hu.bu xr2, xr2 + vext2xv.hu.bu xr3, xr3 + vext2xv.hu.bu xr4, xr4 + vext2xv.hu.bu xr5, xr5 + vext2xv.hu.bu xr6, xr6 + vext2xv.hu.bu xr7, xr7 +.endm + +.macro weight_lasx_16 + weight_calc_lasx xr0, xr1, xr8, xr20, xr9, xr10, xr11 + weight_calc_lasx xr2, xr3, xr8, xr20, xr9, xr12, xr13 + weight_calc_lasx xr4, xr5, xr8, xr20, xr9, xr14, xr15 + weight_calc_lasx xr6, xr7, xr8, xr20, xr9, xr16, xr17 + xvpermi.d xr10, xr10, 0xD8 + xvpermi.d xr11, xr11, 0xD8 + xvpermi.d xr12, xr12, 0xD8 + xvpermi.d xr13, xr13, 0xD8 + xvpermi.d xr14, xr14, 0xD8 + xvpermi.d xr15, xr15, 0xD8 + xvpermi.d xr16, xr16, 0xD8 + xvpermi.d xr17, xr17, 0xD8 + + vst vr10, a0, 0 + vstx vr11, a0, a1 + vstx vr12, a0, t0 + vstx vr13, a0, t1 + vst vr14, t4, 0 + vstx vr15, t4, a1 + vstx vr16, t4, t0 + vstx vr17, t4, t1 +.endm + +weight_func_lasx 16 + addi.d t3, zero, 16 + weight_load_lasx_16 + weight_lasx_16 + bne a2, t3, .END_WEIGHT_H264_PIXELS16_8_LASX + add.d a0, t4, t2 + weight_load_lasx_16 + weight_lasx_16 +.END_WEIGHT_H264_PIXELS16_8_LASX: +endfunc + +//LSX optimization is sufficient for this function. +function ff_weight_h264_pixels4_8_lsx + add.d t0, a0, a1 + addi.d t3, zero, 4 + + sll.d a5, a5, a3 + vreplgr2vr.h vr20, a4 //weight + vreplgr2vr.h vr8, a5 //offset + vreplgr2vr.h vr9, a3 //log2_denom + vldi vr21, 0 + + fld.s f0, a0, 0 + fldx.s f1, a0, a1 + vilvl.w vr4, vr1, vr0 + vilvl.b vr5, vr21, vr4 + vmul.h vr10, vr5, vr20 + vsadd.h vr0, vr8, vr10 + vssrarn.bu.h vr0, vr0, vr9 + + fst.s f0, a0, 0 + vstelm.w vr0, t0, 0, 1 + blt a2, t3, .END_WEIGHT_H264_PIXELS4 + add.d a0, t0, a1 + addi.d t3, zero, 8 + fld.s f0, a0, 0 + fldx.s f1, a0, a1 + add.d t0, a0, a1 + vilvl.w vr4, vr1, vr0 + vilvl.b vr5, vr21, vr4 + + vmul.h vr10, vr5, vr20 + vsadd.h vr0, vr8, vr10 + vssrarn.bu.h vr0, vr0, vr9 + + fst.s f0, a0, 0 + vstelm.w vr0, t0, 0, 1 + blt a2, t3, .END_WEIGHT_H264_PIXELS4 + add.d a0, t0, a1 + add.d t0, a0, a1 + add.d t1, t0, a1 + add.d t2, t1, a1 + + fld.s f0, a0, 0 + fld.s f1, t0, 0 + fld.s f2, t1, 0 + fld.s f3, t2, 0 + + vilvl.w vr4, vr1, vr0 + vilvl.w vr5, vr3, vr2 + vilvl.b vr6, vr21, vr4 + vilvl.b vr7, vr21, vr5 + + vmul.h vr10, vr6, vr20 + vmul.h vr11, vr7, vr20 + vsadd.h vr0, vr8, vr10 + vsadd.h vr1, vr8, vr11 + vssrarn.bu.h vr10, vr0, vr9 + vssrarn.bu.h vr11, vr1, vr9 + + fst.s f10, a0, 0 + vstelm.w vr10, t0, 0, 1 + fst.s f11, t1, 0 + vstelm.w vr11, t2, 0, 1 +.END_WEIGHT_H264_PIXELS4: +endfunc + +function ff_h264_add_pixels4_8_lsx + slli.d t0, a2, 1 + add.d t1, t0, a2 + vld vr0, a1, 0 + vld vr1, a1, 16 + vldi vr2, 0 + fld.s f3, a0, 0 + fldx.s f4, a0, a2 + fldx.s f5, a0, t0 + fldx.s f6, a0, t1 + vilvl.w vr7, vr4, vr3 + vilvl.w vr8, vr6, vr5 + vilvl.b vr9, vr2, vr7 + vilvl.b vr10, vr2, vr8 + vadd.h vr11, vr0, vr9 + vadd.h vr12, vr1, vr10 + vpickev.b vr0, vr12, vr11 + vbsrl.v vr3, vr0, 4 + vbsrl.v vr4, vr0, 8 + vbsrl.v vr5, vr0, 12 + fst.s f0, a0, 0 + fstx.s f3, a0, a2 + fstx.s f4, a0, t0 + fstx.s f5, a0, t1 + vst vr2, a1, 0 + vst vr2, a1, 16 +endfunc + +function ff_h264_add_pixels8_8_lsx + slli.d t0, a2, 1 + slli.d t2, a2, 2 + add.d t1, t0, a2 + add.d t3, a0, t2 + vldi vr0, 0 + vld vr1, a1, 0 + vld vr2, a1, 16 + vld vr3, a1, 32 + vld vr4, a1, 48 + vld vr5, a1, 64 + vld vr6, a1, 80 + vld vr7, a1, 96 + vld vr8, a1, 112 + load_double f10, f11, f12, f13, a0, a2, t0, t1 + load_double f14, f15, f16, f17, t3, a2, t0, t1 + vilvl.b vr10, vr0, vr10 + vilvl.b vr11, vr0, vr11 + vilvl.b vr12, vr0, vr12 + vilvl.b vr13, vr0, vr13 + vilvl.b vr14, vr0, vr14 + vilvl.b vr15, vr0, vr15 + vilvl.b vr16, vr0, vr16 + vilvl.b vr17, vr0, vr17 + vadd.h vr1, vr1, vr10 + vadd.h vr2, vr2, vr11 + vadd.h vr3, vr3, vr12 + vadd.h vr4, vr4, vr13 + vadd.h vr5, vr5, vr14 + vadd.h vr6, vr6, vr15 + vadd.h vr7, vr7, vr16 + vadd.h vr8, vr8, vr17 + vpickev.b vr10, vr2, vr1 + vpickev.b vr12, vr4, vr3 + vpickev.b vr14, vr6, vr5 + vpickev.b vr16, vr8, vr7 + vbsrl.v vr11, vr10, 8 + vbsrl.v vr13, vr12, 8 + vbsrl.v vr15, vr14, 8 + vbsrl.v vr17, vr16, 8 + vst vr0, a1, 0 + vst vr0, a1, 16 + vst vr0, a1, 32 + vst vr0, a1, 48 + vst vr0, a1, 64 + vst vr0, a1, 80 + vst vr0, a1, 96 + vst vr0, a1, 112 + store_double f10, f11, f12, f13, a0, a2, t0, t1 + store_double f14, f15, f16, f17, t3, a2, t0, t1 +endfunc + +const cnst_value +.byte 6, 2, 6, 2, 6, 2, 6, 2, 6, 2, 6, 2, 6, 2, 6, 2 +.byte 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1 +endconst + +function ff_h264_loop_filter_strength_lsx + vldi vr0, 0 + ldptr.w t0, sp, 0 //mask_mv1 + ldptr.w t1, sp, 8 //field + beqz t1, .FIELD + la.local t2, cnst_value + vld vr1, t2, 0 + vld vr2, t2, 16 + b .END_FIELD +.FIELD: + vldi vr1, 0x06 + vldi vr2, 0x03 +.END_FIELD: + vldi vr3, 0x01 + slli.d a6, a6, 3 //step <<= 3 + slli.d a5, a5, 3 //edges <<= 3 + move t3, zero + slli.d t4, a6, 2 + move t5, a2 + move t6, a3 + move t7, a1 + move t8, a0 + slli.d t0, t0, 3 +.ITERATION_FIR: + bge t3, a5, .END_ITERATION_FIR + vand.v vr20, vr20, vr0 + and t2, t0, t3 + bnez t2, .MASK_MV_FIR + beqz a4, .BIDIR_FIR + vld vr4, t5, 4 + vld vr5, t5, 44 + vld vr6, t5, 12 + vld vr7, t5, 52 + vilvl.w vr4, vr5, vr4 + vilvl.w vr6, vr6, vr6 + vilvl.w vr7, vr7, vr7 + vshuf4i.h vr5, vr4, 0x4e + vsub.b vr6, vr6, vr4 + vsub.b vr7, vr7, vr5 + vor.v vr6, vr6, vr7 + vld vr10, t6, 16 + vld vr11, t6, 48 + vld vr12, t6, 208 + vld vr8, t6, 176 + vsub.h vr13, vr10, vr11 + vsub.h vr14, vr10, vr12 + vsub.h vr15, vr8, vr11 + vsub.h vr16, vr8, vr12 + vssrarni.b.h vr14, vr13, 0 + vssrarni.b.h vr16, vr15, 0 + vadd.b vr14, vr2, vr14 + vadd.b vr16, vr2, vr16 + vssub.bu vr14, vr14, vr1 + vssub.bu vr16, vr16, vr1 + vssrarni.b.h vr14, vr14, 0 + vssrarni.b.h vr16, vr16, 0 + vor.v vr20, vr6, vr14 + vshuf4i.h vr16, vr16, 0x4e + vor.v vr20, vr20, vr16 + vshuf4i.h vr21, vr20, 0x4e + vmin.bu vr20, vr20, vr21 + b .MASK_MV_FIR +.BIDIR_FIR: + vld vr4, t5, 4 + vld vr5, t5, 12 + vld vr10, t6, 16 + vld vr11, t6, 48 + vsub.h vr12, vr11, vr10 + vssrarni.b.h vr12, vr12, 0 + vadd.b vr13, vr12, vr2 + vssub.bu vr14, vr13, vr1 + vsat.h vr15, vr14, 7 + vpickev.b vr20, vr15, vr15 + vsub.b vr6, vr5, vr4 + vor.v vr20, vr20, vr6 +.MASK_MV_FIR: + vld vr4, t7, 12 + vld vr5, t7, 4 + vor.v vr6, vr4, vr5 + vmin.bu vr6, vr6, vr3 + vmin.bu vr20, vr20, vr3 + vslli.h vr6, vr6, 1 + vmax.bu vr6, vr20, vr6 + vilvl.b vr7, vr0, vr6 + add.d t3, t3, a6 + fst.d f7, t8, 32 + add.d t5, t5, a6 + add.d t6, t6, t4 + add.d t7, t7, a6 + add.d t8, t8, a6 + b .ITERATION_FIR +.END_ITERATION_FIR: + move t3, zero + addi.d a5, zero, 32 + vldi vr21, 0xff + move t5, a2 + move t6, a3 + move t7, a1 + move t8, a0 + slli.d a7, a7, 3 +.ITERATION_SEC: + bge t3, a5, .END_ITERATION_SEC + vand.v vr20, vr20, vr21 + and t2, a7, t3 + bnez t2, .MASK_MV_SEC + beqz a4, .BIDIR_SEC + vld vr4, t5, 11 + vld vr5, t5, 51 + vld vr6, t5, 12 + vld vr7, t5, 52 + vilvl.w vr4, vr5, vr4 + vilvl.w vr6, vr6, vr6 + vilvl.w vr7, vr7, vr7 + vshuf4i.h vr5, vr4, 0x4e + vsub.b vr6, vr6, vr4 + vsub.b vr7, vr7, vr5 + vor.v vr6, vr6, vr7 + vld vr10, t6, 44 + vld vr11, t6, 48 + vld vr12, t6, 208 + vld vr8, t6, 204 + vsub.h vr13, vr10, vr11 + vsub.h vr14, vr10, vr12 + vsub.h vr15, vr8, vr11 + vsub.h vr16, vr8, vr12 + vssrarni.b.h vr14, vr13, 0 + vssrarni.b.h vr16, vr15, 0 + vadd.b vr14, vr2, vr14 + vadd.b vr16, vr2, vr16 + vssub.bu vr14, vr14, vr1 + vssub.bu vr16, vr16, vr1 + vssrarni.b.h vr14, vr14, 0 + vssrarni.b.h vr16, vr16, 0 + vor.v vr20, vr6, vr14 + vshuf4i.h vr16, vr16, 0x4e + vor.v vr20, vr20, vr16 + vshuf4i.h vr22, vr20, 0x4e + vmin.bu vr20, vr20, vr22 + b .MASK_MV_SEC +.BIDIR_SEC: + vld vr4, t5, 11 + vld vr5, t5, 12 + vld vr10, t6, 44 + vld vr11, t6, 48 + vsub.h vr12, vr11, vr10 + vssrarni.b.h vr12, vr12, 0 + vadd.b vr13, vr12, vr2 + vssub.bu vr14, vr13, vr1 + vssrarni.b.h vr14, vr14, 0 + vsub.b vr6, vr5, vr4 + vor.v vr20, vr14, vr6 +.MASK_MV_SEC: + vld vr4, t7, 12 + vld vr5, t7, 11 + vor.v vr6, vr4, vr5 + vmin.bu vr6, vr6, vr3 + vmin.bu vr20, vr20, vr3 + vslli.h vr6, vr6, 1 + vmax.bu vr6, vr20, vr6 + vilvl.b vr7, vr0, vr6 + addi.d t3, t3, 8 + fst.d f7, t8, 0 + addi.d t5, t5, 8 + addi.d t6, t6, 32 + addi.d t7, t7, 8 + addi.d t8, t8, 8 + b .ITERATION_SEC +.END_ITERATION_SEC: + vld vr4, a0, 0 + vld vr5, a0, 16 + vilvh.d vr6, vr4, vr4 + vilvh.d vr7, vr5, vr5 + LSX_TRANSPOSE4x4_H vr4, vr6, vr5, vr7, vr6, vr7, vr8, vr9, vr10, vr11 + vilvl.d vr4, vr7, vr6 + vilvl.d vr5, vr9, vr8 + vst vr4, a0, 0 + vst vr5, a0, 16 +endfunc diff --git a/libavcodec/loongarch/h264dsp_init_loongarch.c b/libavcodec/loongarch/h264dsp_init_loongarch.c index cb07deb398a..b70fe696d29 100644 --- a/libavcodec/loongarch/h264dsp_init_loongarch.c +++ b/libavcodec/loongarch/h264dsp_init_loongarch.c @@ -29,21 +29,44 @@ av_cold void ff_h264dsp_init_loongarch(H264DSPContext *c, const int bit_depth, int cpu_flags = av_get_cpu_flags(); if (have_lsx(cpu_flags)) { + if (chroma_format_idc <= 1) + c->h264_loop_filter_strength = ff_h264_loop_filter_strength_lsx; if (bit_depth == 8) { c->h264_idct_add = ff_h264_idct_add_8_lsx; c->h264_idct8_add = ff_h264_idct8_add_8_lsx; c->h264_idct_dc_add = ff_h264_idct_dc_add_8_lsx; c->h264_idct8_dc_add = ff_h264_idct8_dc_add_8_lsx; - if (chroma_format_idc <= 1) + if (chroma_format_idc <= 1) { c->h264_idct_add8 = ff_h264_idct_add8_8_lsx; - else + c->h264_h_loop_filter_chroma = ff_h264_h_lpf_chroma_8_lsx; + c->h264_h_loop_filter_chroma_intra = ff_h264_h_lpf_chroma_intra_8_lsx; + } else c->h264_idct_add8 = ff_h264_idct_add8_422_8_lsx; c->h264_idct_add16 = ff_h264_idct_add16_8_lsx; c->h264_idct8_add4 = ff_h264_idct8_add4_8_lsx; c->h264_luma_dc_dequant_idct = ff_h264_luma_dc_dequant_idct_8_lsx; c->h264_idct_add16intra = ff_h264_idct_add16_intra_8_lsx; + + c->h264_add_pixels4_clear = ff_h264_add_pixels4_8_lsx; + c->h264_add_pixels8_clear = ff_h264_add_pixels8_8_lsx; + c->h264_v_loop_filter_luma = ff_h264_v_lpf_luma_8_lsx; + c->h264_h_loop_filter_luma = ff_h264_h_lpf_luma_8_lsx; + c->h264_v_loop_filter_luma_intra = ff_h264_v_lpf_luma_intra_8_lsx; + c->h264_h_loop_filter_luma_intra = ff_h264_h_lpf_luma_intra_8_lsx; + c->h264_v_loop_filter_chroma = ff_h264_v_lpf_chroma_8_lsx; + + c->h264_v_loop_filter_chroma_intra = ff_h264_v_lpf_chroma_intra_8_lsx; + + c->biweight_h264_pixels_tab[0] = ff_biweight_h264_pixels16_8_lsx; + c->biweight_h264_pixels_tab[1] = ff_biweight_h264_pixels8_8_lsx; + c->biweight_h264_pixels_tab[2] = ff_biweight_h264_pixels4_8_lsx; + c->weight_h264_pixels_tab[0] = ff_weight_h264_pixels16_8_lsx; + c->weight_h264_pixels_tab[1] = ff_weight_h264_pixels8_8_lsx; + c->weight_h264_pixels_tab[2] = ff_weight_h264_pixels4_8_lsx; + c->h264_idct8_add = ff_h264_idct8_add_8_lsx; + c->h264_idct8_dc_add = ff_h264_idct8_dc_add_8_lsx; } } #if HAVE_LASX @@ -57,23 +80,13 @@ av_cold void ff_h264dsp_init_loongarch(H264DSPContext *c, const int bit_depth, 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; c->h264_idct8_add = ff_h264_idct8_add_8_lasx; c->h264_idct8_dc_add = ff_h264_idct8_dc_add_8_lasx; diff --git a/libavcodec/loongarch/h264dsp_lasx.c b/libavcodec/loongarch/h264dsp_lasx.c index 7b2b8ff0f05..5205cc849f1 100644 --- a/libavcodec/loongarch/h264dsp_lasx.c +++ b/libavcodec/loongarch/h264dsp_lasx.c @@ -67,10 +67,10 @@ 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; + int img_width_2x = img_width << 1; + int img_width_4x = img_width << 2; + int img_width_8x = img_width << 3; + int img_width_3x = img_width_2x + img_width; __m256i tmp_vec0, bs_vec; __m256i tc_vec = {0x0101010100000000, 0x0303030302020202, 0x0101010100000000, 0x0303030302020202}; @@ -244,8 +244,8 @@ void ff_h264_h_lpf_luma_8_lasx(uint8_t *data, ptrdiff_t img_width, 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; + int img_width_2x = img_width << 1; + int img_width_3x = img_width + img_width_2x; __m256i tmp_vec0, bs_vec; __m256i tc_vec = {0x0101010100000000, 0x0303030302020202, 0x0101010100000000, 0x0303030302020202}; @@ -363,184 +363,6 @@ void ff_h264_v_lpf_luma_8_lasx(uint8_t *data, ptrdiff_t img_width, } } -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, \ @@ -584,9 +406,9 @@ void ff_h264_v_lpf_chroma_8_lasx(uint8_t *data, ptrdiff_t img_width, 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; + int img_width_2x = img_width << 1; + int img_width_4x = img_width << 2; + int 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; @@ -760,8 +582,8 @@ void ff_h264_h_lpf_luma_intra_8_lasx(uint8_t *data, ptrdiff_t img_width, 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; + int img_width_2x = img_width << 1; + int 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; @@ -877,1160 +699,6 @@ void ff_h264_v_lpf_luma_intra_8_lasx(uint8_t *data, ptrdiff_t img_width, } } -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; diff --git a/libavcodec/loongarch/h264dsp_loongarch.h b/libavcodec/loongarch/h264dsp_loongarch.h index 28dca2b537c..e17522dfe04 100644 --- a/libavcodec/loongarch/h264dsp_loongarch.h +++ b/libavcodec/loongarch/h264dsp_loongarch.h @@ -47,6 +47,50 @@ void ff_h264_idct_add16_intra_8_lsx(uint8_t *dst, const int32_t *blk_offset, int16_t *block, int32_t dst_stride, const uint8_t nzc[15 * 8]); +void ff_h264_h_lpf_luma_8_lsx(uint8_t *src, ptrdiff_t stride, + int alpha, int beta, int8_t *tc0); +void ff_h264_v_lpf_luma_8_lsx(uint8_t *src, ptrdiff_t stride, + int alpha, int beta, int8_t *tc0); +void ff_h264_h_lpf_luma_intra_8_lsx(uint8_t *src, ptrdiff_t stride, + int alpha, int beta); +void ff_h264_v_lpf_luma_intra_8_lsx(uint8_t *src, ptrdiff_t stride, + int alpha, int beta); +void ff_h264_h_lpf_chroma_8_lsx(uint8_t *src, ptrdiff_t stride, + int alpha, int beta, int8_t *tc0); +void ff_h264_v_lpf_chroma_8_lsx(uint8_t *src, ptrdiff_t stride, + int alpha, int beta, int8_t *tc0); +void ff_h264_h_lpf_chroma_intra_8_lsx(uint8_t *src, ptrdiff_t stride, + int alpha, int beta); +void ff_h264_v_lpf_chroma_intra_8_lsx(uint8_t *src, ptrdiff_t stride, + int alpha, int beta); +void ff_biweight_h264_pixels16_8_lsx(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_lsx(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_lsx(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_lsx(uint8_t *src, ptrdiff_t stride, + int height, int log2_denom, + int weight_src, int offset_in); +void ff_weight_h264_pixels8_8_lsx(uint8_t *src, ptrdiff_t stride, + int height, int log2_denom, + int weight_src, int offset); +void ff_weight_h264_pixels4_8_lsx(uint8_t *src, ptrdiff_t stride, + int height, int log2_denom, + int weight_src, int offset); +void ff_h264_add_pixels4_8_lsx(uint8_t *_dst, int16_t *_src, int stride); +void ff_h264_add_pixels8_8_lsx(uint8_t *_dst, int16_t *_src, int stride); +void ff_h264_loop_filter_strength_lsx(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); + #if HAVE_LASX void ff_h264_h_lpf_luma_8_lasx(uint8_t *src, ptrdiff_t stride, int alpha, int beta, int8_t *tc0); @@ -56,24 +100,12 @@ 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, +void ff_biweight_h264_pixels16_8_lasx(unsigned char *dst, unsigned char *src, + long int 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, +void ff_biweight_h264_pixels8_8_lasx(unsigned char *dst, unsigned char *src, + long int 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, @@ -82,9 +114,6 @@ void ff_weight_h264_pixels16_8_lasx(uint8_t *src, ptrdiff_t stride, 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); From 8815a7719e8e65ee93cbfdc3293f8fb5a33ba1a5 Mon Sep 17 00:00:00 2001 From: Lu Wang Date: Thu, 25 May 2023 15:24:28 +0800 Subject: [PATCH 1175/2172] avcodec/la: Add LSX optimization for h264 chroma and intrapred. ./configure --disable-lasx ffmpeg -i 1_h264_1080p_30fps_3Mbps.mp4 -f rawvideo -y /dev/null -an before: 199fps after: 214fps Reviewed-by: Shiyou Yin Signed-off-by: Michael Niedermayer --- libavcodec/loongarch/Makefile | 4 +- .../loongarch/h264_intrapred_init_loongarch.c | 18 +- libavcodec/loongarch/h264_intrapred_lasx.c | 121 -- ...pred_lasx.h => h264_intrapred_loongarch.h} | 12 +- libavcodec/loongarch/h264chroma.S | 966 +++++++++++++ .../loongarch/h264chroma_init_loongarch.c | 10 +- libavcodec/loongarch/h264chroma_lasx.c | 1280 ----------------- libavcodec/loongarch/h264chroma_lasx.h | 36 - libavcodec/loongarch/h264chroma_loongarch.h | 41 + libavcodec/loongarch/h264intrapred.S | 299 ++++ 10 files changed, 1342 insertions(+), 1445 deletions(-) delete mode 100644 libavcodec/loongarch/h264_intrapred_lasx.c rename libavcodec/loongarch/{h264_intrapred_lasx.h => h264_intrapred_loongarch.h} (70%) create mode 100644 libavcodec/loongarch/h264chroma.S delete mode 100644 libavcodec/loongarch/h264chroma_lasx.c delete mode 100644 libavcodec/loongarch/h264chroma_lasx.h create mode 100644 libavcodec/loongarch/h264chroma_loongarch.h create mode 100644 libavcodec/loongarch/h264intrapred.S diff --git a/libavcodec/loongarch/Makefile b/libavcodec/loongarch/Makefile index 111bc23e4e2..a5630551616 100644 --- a/libavcodec/loongarch/Makefile +++ b/libavcodec/loongarch/Makefile @@ -9,11 +9,9 @@ OBJS-$(CONFIG_HPELDSP) += loongarch/hpeldsp_init_loongarch.o OBJS-$(CONFIG_IDCTDSP) += loongarch/idctdsp_init_loongarch.o OBJS-$(CONFIG_VIDEODSP) += loongarch/videodsp_init.o OBJS-$(CONFIG_HEVC_DECODER) += loongarch/hevcdsp_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/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 LASX-OBJS-$(CONFIG_IDCTDSP) += loongarch/simple_idct_lasx.o \ @@ -33,3 +31,5 @@ LSX-OBJS-$(CONFIG_HEVC_DECODER) += loongarch/hevcdsp_lsx.o \ LSX-OBJS-$(CONFIG_H264DSP) += loongarch/h264idct.o \ loongarch/h264idct_loongarch.o \ loongarch/h264dsp.o +LSX-OBJS-$(CONFIG_H264CHROMA) += loongarch/h264chroma.o +LSX-OBJS-$(CONFIG_H264PRED) += loongarch/h264intrapred.o diff --git a/libavcodec/loongarch/h264_intrapred_init_loongarch.c b/libavcodec/loongarch/h264_intrapred_init_loongarch.c index 12620bd842b..c415fa30dab 100644 --- a/libavcodec/loongarch/h264_intrapred_init_loongarch.c +++ b/libavcodec/loongarch/h264_intrapred_init_loongarch.c @@ -21,7 +21,7 @@ #include "libavutil/loongarch/cpu.h" #include "libavcodec/h264pred.h" -#include "h264_intrapred_lasx.h" +#include "h264_intrapred_loongarch.h" av_cold void ff_h264_pred_init_loongarch(H264PredContext *h, int codec_id, const int bit_depth, @@ -30,6 +30,22 @@ av_cold void ff_h264_pred_init_loongarch(H264PredContext *h, int codec_id, int cpu_flags = av_get_cpu_flags(); if (bit_depth == 8) { + if (have_lsx(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_lsx; + } else if (codec_id == AV_CODEC_ID_RV40) { + h->pred16x16[PLANE_PRED8x8] = ff_h264_pred16x16_plane_rv40_8_lsx; + } else { + h->pred16x16[PLANE_PRED8x8] = ff_h264_pred16x16_plane_h264_8_lsx; + } + } + } if (have_lasx(cpu_flags)) { if (chroma_format_idc <= 1) { } diff --git a/libavcodec/loongarch/h264_intrapred_lasx.c b/libavcodec/loongarch/h264_intrapred_lasx.c deleted file mode 100644 index c38cd611b84..00000000000 --- a/libavcodec/loongarch/h264_intrapred_lasx.c +++ /dev/null @@ -1,121 +0,0 @@ -/* - * 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_loongarch.h similarity index 70% rename from libavcodec/loongarch/h264_intrapred_lasx.h rename to libavcodec/loongarch/h264_intrapred_loongarch.h index 0c2653300c6..39be87ee9fb 100644 --- a/libavcodec/loongarch/h264_intrapred_lasx.h +++ b/libavcodec/loongarch/h264_intrapred_loongarch.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Loongson Technology Corporation Limited + * Copyright (c) 2023 Loongson Technology Corporation Limited * Contributed by Hao Chen * * This file is part of FFmpeg. @@ -19,13 +19,17 @@ * 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 +#ifndef AVCODEC_LOONGARCH_H264_INTRAPRED_LOONGARCH_H +#define AVCODEC_LOONGARCH_H264_INTRAPRED_LOONGARCH_H #include "libavcodec/avcodec.h" +void ff_h264_pred16x16_plane_h264_8_lsx(uint8_t *src, ptrdiff_t stride); +void ff_h264_pred16x16_plane_rv40_8_lsx(uint8_t *src, ptrdiff_t stride); +void ff_h264_pred16x16_plane_svq3_8_lsx(uint8_t *src, ptrdiff_t stride); + 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 +#endif // #ifndef AVCODEC_LOONGARCH_H264_INTRAPRED_LOONGARCH_H diff --git a/libavcodec/loongarch/h264chroma.S b/libavcodec/loongarch/h264chroma.S new file mode 100644 index 00000000000..353b8d004bf --- /dev/null +++ b/libavcodec/loongarch/h264chroma.S @@ -0,0 +1,966 @@ +/* + * Loongson LSX/LASX optimized h264chroma + * + * Copyright (c) 2023 Loongson Technology Corporation Limited + * Contributed by 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 + */ + +#include "loongson_asm.S" + +/* void ff_put_h264_chroma_mc8_lsx(uint8_t *dst, uint8_t *src, ptrdiff_t stride, + int h, int x, int y) */ +function ff_put_h264_chroma_mc8_lsx + li.d t8, 8 + sub.d t1, t8, a4 // 8-x + sub.d t2, t8, a5 // 8-y + mul.d t3, t1, t2 // A + mul.d t4, a4, t2 // B + mul.d t5, t1, a5 // C + mul.d t6, a4, a5 // D + add.d t0, t4, t5 // E + vreplgr2vr.b vr0, t3 + vreplgr2vr.b vr1, t4 + vreplgr2vr.b vr2, t5 + vreplgr2vr.b vr3, t6 + vreplgr2vr.b vr4, t0 + slli.d t2, a2, 1 + add.d t3, t2, a2 + slli.d t4, a2, 2 + + bge zero, t6, .ENDLOOP_D + move t1, a3 + vilvl.b vr9, vr1, vr0 + vilvl.b vr10, vr3, vr2 +.LOOP_D: + vld vr5, a1, 0 + vld vr6, a1, 1 + add.d a1, a1, a2 + vld vr7, a1, 0 + vld vr8, a1, 1 + vilvl.b vr11, vr6, vr5 + vilvl.b vr12, vr8, vr7 + vmulwev.h.bu vr13, vr9, vr11 + vmaddwod.h.bu vr13, vr9, vr11 + vmulwev.h.bu vr14, vr10, vr12 + vmaddwod.h.bu vr14, vr10, vr12 + vadd.h vr13, vr13, vr14 + vsrarni.b.h vr13, vr13, 6 + vstelm.d vr13, a0, 0, 0 + add.d a0, a0, a2 + add.d a1, a1, a2 + vld vr5, a1, 0 + vld vr6, a1, 1 + vilvl.b vr11, vr8, vr7 + vilvl.b vr12, vr6, vr5 + vmulwev.h.bu vr13, vr9, vr11 + vmaddwod.h.bu vr13, vr9, vr11 + vmulwev.h.bu vr14, vr10, vr12 + vmaddwod.h.bu vr14, vr10, vr12 + vadd.h vr13, vr13, vr14 + vsrarni.b.h vr13, vr13, 6 + vstelm.d vr13, a0, 0, 0 + add.d a0, a0, a2 + add.d a1, a1, a2 + vld vr7, a1, 0 + vld vr8, a1, 1 + vilvl.b vr11, vr6, vr5 + vilvl.b vr12, vr8, vr7 + vmulwev.h.bu vr13, vr9, vr11 + vmaddwod.h.bu vr13, vr9, vr11 + vmulwev.h.bu vr14, vr10, vr12 + vmaddwod.h.bu vr14, vr10, vr12 + vadd.h vr13, vr13, vr14 + vsrarni.b.h vr13, vr13, 6 + vstelm.d vr13, a0, 0, 0 + add.d a0, a0, a2 + add.d a1, a1, a2 + vld vr5, a1, 0 + vld vr6, a1, 1 + vilvl.b vr11, vr8, vr7 + vilvl.b vr12, vr6, vr5 + vmulwev.h.bu vr13, vr9, vr11 + vmaddwod.h.bu vr13, vr9, vr11 + vmulwev.h.bu vr14, vr10, vr12 + vmaddwod.h.bu vr14, vr10, vr12 + vadd.h vr13, vr13, vr14 + vsrarni.b.h vr13, vr13, 6 + vstelm.d vr13, a0, 0, 0 + add.d a0, a0, a2 + + addi.d t1, t1, -4 + blt zero, t1, .LOOP_D + b .ENDLOOP +.ENDLOOP_D: + + bge zero, t0, .ENDLOOP_E + move t1, a3 + li.d t7, 1 + slt t8, zero, t5 + maskeqz t5, a2, t8 + masknez t7, t7, t8 + or t7, t7, t5 + vilvl.b vr7, vr4, vr0 +.LOOP_E: + vld vr5, a1, 0 + vldx vr6, a1, t7 + vilvl.b vr5, vr6, vr5 + vmulwev.h.bu vr6, vr7, vr5 + vmaddwod.h.bu vr6, vr7, vr5 + vsrarni.b.h vr6, vr6, 6 + vstelm.d vr6, a0, 0, 0 + add.d a0, a0, a2 + add.d a1, a1, a2 + vld vr5, a1, 0 + vldx vr6, a1, t7 + vilvl.b vr5, vr6, vr5 + vmulwev.h.bu vr6, vr7, vr5 + vmaddwod.h.bu vr6, vr7, vr5 + vsrarni.b.h vr6, vr6, 6 + vstelm.d vr6, a0, 0, 0 + add.d a0, a0, a2 + add.d a1, a1, a2 + vld vr5, a1, 0 + vldx vr6, a1, t7 + vilvl.b vr5, vr6, vr5 + vmulwev.h.bu vr6, vr7, vr5 + vmaddwod.h.bu vr6, vr7, vr5 + vsrarni.b.h vr6, vr6, 6 + vstelm.d vr6, a0, 0, 0 + add.d a0, a0, a2 + add.d a1, a1, a2 + vld vr5, a1, 0 + vldx vr6, a1, t7 + vilvl.b vr5, vr6, vr5 + vmulwev.h.bu vr6, vr7, vr5 + vmaddwod.h.bu vr6, vr7, vr5 + vsrarni.b.h vr6, vr6, 6 + vstelm.d vr6, a0, 0, 0 + add.d a0, a0, a2 + add.d a1, a1, a2 + + addi.d t1, t1, -4 + blt zero, t1, .LOOP_E + b .ENDLOOP +.ENDLOOP_E: + + move t1, a3 +.LOOP: + vld vr5, a1, 0 + vmulwev.h.bu vr6, vr0, vr5 + vmulwod.h.bu vr7, vr0, vr5 + vsrarni.b.h vr6, vr6, 6 + vsrarni.b.h vr7, vr7, 6 + vilvl.b vr6, vr7, vr6 + vstelm.d vr6, a0, 0, 0 + add.d a0, a0, a2 + vldx vr5, a1, a2 + vmulwev.h.bu vr6, vr0, vr5 + vmulwod.h.bu vr7, vr0, vr5 + vsrarni.b.h vr6, vr6, 6 + vsrarni.b.h vr7, vr7, 6 + vilvl.b vr6, vr7, vr6 + vstelm.d vr6, a0, 0, 0 + add.d a0, a0, a2 + vldx vr5, a1, t2 + vmulwev.h.bu vr6, vr0, vr5 + vmulwod.h.bu vr7, vr0, vr5 + vsrarni.b.h vr6, vr6, 6 + vsrarni.b.h vr7, vr7, 6 + vilvl.b vr6, vr7, vr6 + vstelm.d vr6, a0, 0, 0 + add.d a0, a0, a2 + vldx vr5, a1, t3 + vmulwev.h.bu vr6, vr0, vr5 + vmulwod.h.bu vr7, vr0, vr5 + vsrarni.b.h vr6, vr6, 6 + vsrarni.b.h vr7, vr7, 6 + vilvl.b vr6, vr7, vr6 + vstelm.d vr6, a0, 0, 0 + add.d a0, a0, a2 + add.d a1, a1, t4 + + addi.d t1, t1, -4 + blt zero, t1, .LOOP +.ENDLOOP: +endfunc + +/* void ff_avg_h264_chroma_mc8_lsx(uint8_t *dst, uint8_t *src, ptrdiff_t stride, + int h, int x, int y) */ +function ff_avg_h264_chroma_mc8_lsx + li.d t8, 8 + sub.d t1, t8, a4 // 8-x + sub.d t2, t8, a5 // 8-y + mul.d t3, t1, t2 // A + mul.d t4, a4, t2 // B + mul.d t5, t1, a5 // C + mul.d t6, a4, a5 // D + add.d t0, t4, t5 // E + vreplgr2vr.b vr0, t3 + vreplgr2vr.b vr1, t4 + vreplgr2vr.b vr2, t5 + vreplgr2vr.b vr3, t6 + vreplgr2vr.b vr4, t0 + slli.d t2, a2, 1 + add.d t3, t2, a2 + slli.d t4, a2, 2 + + bge zero, t6, .ENDLOOPD + move t1, a3 + vilvl.b vr9, vr1, vr0 + vilvl.b vr10, vr3, vr2 +.LOOPD: + vld vr5, a1, 0 + vld vr6, a1, 1 + add.d a1, a1, a2 + vld vr7, a1, 0 + vld vr8, a1, 1 + vld vr11, a0, 0 + vilvl.b vr12, vr6, vr5 + vilvl.b vr13, vr8, vr7 + vmulwev.h.bu vr14, vr9, vr12 + vmaddwod.h.bu vr14, vr9, vr12 + vmulwev.h.bu vr15, vr10, vr13 + vmaddwod.h.bu vr15, vr10, vr13 + vadd.h vr14, vr14, vr15 + vsrari.h vr14, vr14, 6 + vsllwil.hu.bu vr11, vr11, 0 + vadd.h vr11, vr14, vr11 + vsrarni.b.h vr11, vr11, 1 + vstelm.d vr11, a0, 0, 0 + add.d a0, a0, a2 + add.d a1, a1, a2 + vld vr5, a1, 0 + vld vr6, a1, 1 + vld vr11, a0, 0 + vilvl.b vr12, vr8, vr7 + vilvl.b vr13, vr6, vr5 + vmulwev.h.bu vr14, vr9, vr12 + vmaddwod.h.bu vr14, vr9, vr12 + vmulwev.h.bu vr15, vr10, vr13 + vmaddwod.h.bu vr15, vr10, vr13 + vadd.h vr14, vr14, vr15 + vsrari.h vr14, vr14, 6 + vsllwil.hu.bu vr11, vr11, 0 + vadd.h vr11, vr14, vr11 + vsrarni.b.h vr11, vr11, 1 + vstelm.d vr11, a0, 0, 0 + add.d a0, a0, a2 + add.d a1, a1, a2 + vld vr7, a1, 0 + vld vr8, a1, 1 + vld vr11, a0, 0 + vilvl.b vr12, vr6, vr5 + vilvl.b vr13, vr8, vr7 + vmulwev.h.bu vr14, vr9, vr12 + vmaddwod.h.bu vr14, vr9, vr12 + vmulwev.h.bu vr15, vr10, vr13 + vmaddwod.h.bu vr15, vr10, vr13 + vadd.h vr14, vr14, vr15 + vsrari.h vr14, vr14, 6 + vsllwil.hu.bu vr11, vr11, 0 + vadd.h vr11, vr14, vr11 + vsrarni.b.h vr11, vr11, 1 + vstelm.d vr11, a0, 0, 0 + add.d a0, a0, a2 + add.d a1, a1, a2 + vld vr5, a1, 0 + vld vr6, a1, 1 + vld vr11, a0, 0 + vilvl.b vr12, vr8, vr7 + vilvl.b vr13, vr6, vr5 + vmulwev.h.bu vr14, vr9, vr12 + vmaddwod.h.bu vr14, vr9, vr12 + vmulwev.h.bu vr15, vr10, vr13 + vmaddwod.h.bu vr15, vr10, vr13 + vadd.h vr14, vr14, vr15 + vsrari.h vr14, vr14, 6 + vsllwil.hu.bu vr11, vr11, 0 + vadd.h vr11, vr14, vr11 + vsrarni.b.h vr11, vr11, 1 + vstelm.d vr11, a0, 0, 0 + add.d a0, a0, a2 + + addi.d t1, t1, -4 + blt zero, t1, .LOOPD + b .ENDLOOPELSE +.ENDLOOPD: + + bge zero, t0, .ENDLOOPE + move t1, a3 + li.d t7, 1 + slt t8, zero, t5 + maskeqz t5, a2, t8 + masknez t7, t7, t8 + or t7, t7, t5 + vilvl.b vr7, vr4, vr0 +.LOOPE: + vld vr5, a1, 0 + vldx vr6, a1, t7 + vld vr8, a0, 0 + vilvl.b vr5, vr6, vr5 + vmulwev.h.bu vr6, vr7, vr5 + vmaddwod.h.bu vr6, vr7, vr5 + vsrari.h vr6, vr6, 6 + vsllwil.hu.bu vr8, vr8, 0 + vadd.h vr8, vr6, vr8 + vsrarni.b.h vr8, vr8, 1 + vstelm.d vr8, a0, 0, 0 + add.d a0, a0, a2 + add.d a1, a1, a2 + vld vr5, a1, 0 + vldx vr6, a1, t7 + vld vr8, a0, 0 + vilvl.b vr5, vr6, vr5 + vmulwev.h.bu vr6, vr7, vr5 + vmaddwod.h.bu vr6, vr7, vr5 + vsrari.h vr6, vr6, 6 + vsllwil.hu.bu vr8, vr8, 0 + vadd.h vr8, vr6, vr8 + vsrarni.b.h vr8, vr8, 1 + vstelm.d vr8, a0, 0, 0 + add.d a0, a0, a2 + add.d a1, a1, a2 + vld vr5, a1, 0 + vldx vr6, a1, t7 + vld vr8, a0, 0 + vilvl.b vr5, vr6, vr5 + vmulwev.h.bu vr6, vr7, vr5 + vmaddwod.h.bu vr6, vr7, vr5 + vsrari.h vr6, vr6, 6 + vsllwil.hu.bu vr8, vr8, 0 + vadd.h vr8, vr6, vr8 + vsrarni.b.h vr8, vr8, 1 + vstelm.d vr8, a0, 0, 0 + add.d a0, a0, a2 + add.d a1, a1, a2 + vld vr5, a1, 0 + vldx vr6, a1, t7 + vld vr8, a0, 0 + vilvl.b vr5, vr6, vr5 + vmulwev.h.bu vr6, vr7, vr5 + vmaddwod.h.bu vr6, vr7, vr5 + vsrari.h vr6, vr6, 6 + vsllwil.hu.bu vr8, vr8, 0 + vadd.h vr8, vr6, vr8 + vsrarni.b.h vr8, vr8, 1 + vstelm.d vr8, a0, 0, 0 + add.d a0, a0, a2 + add.d a1, a1, a2 + + addi.d t1, t1, -4 + blt zero, t1, .LOOPE + b .ENDLOOPELSE +.ENDLOOPE: + + move t1, a3 +.LOOPELSE: + vld vr5, a1, 0 + vld vr8, a0, 0 + vmulwev.h.bu vr6, vr0, vr5 + vmulwod.h.bu vr7, vr0, vr5 + vilvl.h vr6, vr7, vr6 + vsrari.h vr6, vr6, 6 + vsllwil.hu.bu vr8, vr8, 0 + vadd.h vr8, vr6, vr8 + vsrarni.b.h vr8, vr8, 1 + vstelm.d vr8, a0, 0, 0 + add.d a0, a0, a2 + vldx vr5, a1, a2 + vld vr8, a0, 0 + vmulwev.h.bu vr6, vr0, vr5 + vmulwod.h.bu vr7, vr0, vr5 + vilvl.h vr6, vr7, vr6 + vsrari.h vr6, vr6, 6 + vsllwil.hu.bu vr8, vr8, 0 + vadd.h vr8, vr6, vr8 + vsrarni.b.h vr8, vr8, 1 + vstelm.d vr8, a0, 0, 0 + add.d a0, a0, a2 + vldx vr5, a1, t2 + vld vr8, a0, 0 + vmulwev.h.bu vr6, vr0, vr5 + vmulwod.h.bu vr7, vr0, vr5 + vilvl.h vr6, vr7, vr6 + vsrari.h vr6, vr6, 6 + vsllwil.hu.bu vr8, vr8, 0 + vadd.h vr8, vr6, vr8 + vsrarni.b.h vr8, vr8, 1 + vstelm.d vr8, a0, 0, 0 + add.d a0, a0, a2 + vldx vr5, a1, t3 + vld vr8, a0, 0 + vmulwev.h.bu vr6, vr0, vr5 + vmulwod.h.bu vr7, vr0, vr5 + vilvl.h vr6, vr7, vr6 + vsrari.h vr6, vr6, 6 + vsllwil.hu.bu vr8, vr8, 0 + vadd.h vr8, vr6, vr8 + vsrarni.b.h vr8, vr8, 1 + vstelm.d vr8, a0, 0, 0 + add.d a0, a0, a2 + add.d a1, a1, t4 + + addi.d t1, t1, -4 + blt zero, t1, .LOOPELSE +.ENDLOOPELSE: +endfunc + +/* void ff_put_h264_chroma_mc4_lsx(uint8_t *dst, uint8_t *src, ptrdiff_t stride, + int h, int x, int y) */ +function ff_put_h264_chroma_mc4_lsx + li.d t8, 8 + sub.d t1, t8, a4 // 8-x + sub.d t2, t8, a5 // 8-y + mul.d t3, t1, t2 // A + mul.d t4, a4, t2 // B + mul.d t5, t1, a5 // C + mul.d t6, a4, a5 // D + add.d t0, t4, t5 // E + slli.d t8, a2, 1 + vreplgr2vr.b vr0, t3 + vreplgr2vr.b vr1, t4 + vreplgr2vr.b vr2, t5 + vreplgr2vr.b vr3, t6 + vreplgr2vr.b vr4, t0 + + bge zero, t6, .ENDPUT_D + move t1, a3 + vilvl.b vr9, vr1, vr0 + vilvl.b vr10, vr3, vr2 +.PUT_D: + vld vr5, a1, 0 + vld vr6, a1, 1 + add.d a1, a1, a2 + vld vr7, a1, 0 + vld vr8, a1, 1 + add.d a1, a1, a2 + vld vr11, a1, 0 + vld vr12, a1, 1 + vilvl.b vr5, vr6, vr5 + vilvl.b vr7, vr8, vr7 + vilvl.b vr13, vr12, vr11 + vilvl.d vr5, vr7, vr5 + vilvl.d vr13, vr13, vr7 + vmulwev.h.bu vr14, vr9, vr5 + vmaddwod.h.bu vr14, vr9, vr5 + vmulwev.h.bu vr15, vr10, vr13 + vmaddwod.h.bu vr15, vr10, vr13 + vadd.h vr14, vr14, vr15 + vsrarni.b.h vr14, vr14, 6 + vstelm.w vr14, a0, 0, 0 + add.d a0, a0, a2 + vstelm.w vr14, a0, 0, 1 + add.d a0, a0, a2 + addi.d t1, t1, -2 + blt zero, t1, .PUT_D + b .ENDPUT +.ENDPUT_D: + + bge zero, t0, .ENDPUT_E + move t1, a3 + li.d t7, 1 + slt t8, zero, t5 + maskeqz t5, a2, t8 + masknez t7, t7, t8 + or t7, t7, t5 + vilvl.b vr7, vr4, vr0 +.PUT_E: + vld vr5, a1, 0 + vldx vr6, a1, t7 + vilvl.b vr5, vr6, vr5 + add.d a1, a1, a2 + vld vr8, a1, 0 + vldx vr9, a1, t7 + vilvl.b vr8, vr9, vr8 + vilvl.d vr5, vr8, vr5 + vmulwev.h.bu vr6, vr7, vr5 + vmaddwod.h.bu vr6, vr7, vr5 + vsrarni.b.h vr6, vr6, 6 + vstelm.w vr6, a0, 0, 0 + add.d a0, a0, a2 + vstelm.w vr6, a0, 0, 1 + add.d a0, a0, a2 + add.d a1, a1, a2 + addi.d t1, t1, -2 + blt zero, t1, .PUT_E + b .ENDPUT +.ENDPUT_E: + + move t1, a3 +.PUT: + vld vr5, a1, 0 + vldx vr8, a1, a2 + vilvl.w vr5, vr8, vr5 + vmulwev.h.bu vr6, vr0, vr5 + vmulwod.h.bu vr7, vr0, vr5 + vsrarni.b.h vr6, vr6, 6 + vsrarni.b.h vr7, vr7, 6 + vilvl.b vr6, vr7, vr6 + vstelm.w vr6, a0, 0, 0 + add.d a0, a0, a2 + vstelm.w vr6, a0, 0, 1 + add.d a0, a0, a2 + add.d a1, a1, t8 + addi.d t1, t1, -2 + blt zero, t1, .PUT +.ENDPUT: +endfunc + +/* void ff_put_h264_chroma_mc8_lasx(uint8_t *dst, uint8_t *src, ptrdiff_t stride, + int h, int x, int y) */ +function ff_put_h264_chroma_mc8_lasx + li.d t8, 8 + sub.d t1, t8, a4 // 8-x + sub.d t2, t8, a5 // 8-y + mul.d t3, t1, t2 // A + mul.d t4, a4, t2 // B + mul.d t5, t1, a5 // C + mul.d t6, a4, a5 // D + add.d t0, t4, t5 // E + xvreplgr2vr.b xr0, t3 + xvreplgr2vr.b xr1, t4 + xvreplgr2vr.b xr2, t5 + xvreplgr2vr.b xr3, t6 + xvreplgr2vr.b xr4, t0 + slli.d t2, a2, 1 + add.d t3, t2, a2 + slli.d t4, a2, 2 + + bge zero, t6, .ENDLOOP_DA + move t1, a3 + xvilvl.b xr9, xr1, xr0 + xvilvl.b xr10, xr3, xr2 +.LOOP_DA: + fld.d f5, a1, 0 + fld.d f6, a1, 1 + add.d a1, a1, a2 + fld.d f7, a1, 0 + fld.d f8, a1, 1 + add.d a1, a1, a2 + fld.d f13, a1, 0 + fld.d f14, a1, 1 + add.d a1, a1, a2 + fld.d f15, a1, 0 + fld.d f16, a1, 1 + add.d a1, a1, a2 + fld.d f17, a1, 0 + fld.d f18, a1, 1 + vilvl.b vr11, vr6, vr5 + vilvl.b vr12, vr8, vr7 + vilvl.b vr14, vr14, vr13 + vilvl.b vr15, vr16, vr15 + vilvl.b vr16, vr18, vr17 + xvpermi.q xr11, xr12, 0x02 + xvpermi.q xr12, xr14, 0x02 + xvpermi.q xr14, xr15, 0x02 + xvpermi.q xr15, xr16, 0x02 + + xvmulwev.h.bu xr19, xr9, xr11 + xvmaddwod.h.bu xr19, xr9, xr11 + xvmulwev.h.bu xr20, xr10, xr12 + xvmaddwod.h.bu xr20, xr10, xr12 + xvadd.h xr21, xr19, xr20 + xvsrarni.b.h xr21, xr21, 6 + vstelm.d vr21, a0, 0, 0 + add.d a0, a0, a2 + xvstelm.d xr21, a0, 0, 2 + add.d a0, a0, a2 + xvmulwev.h.bu xr13, xr9, xr14 + xvmaddwod.h.bu xr13, xr9, xr14 + xvmulwev.h.bu xr14, xr10, xr15 + xvmaddwod.h.bu xr14, xr10, xr15 + xvadd.h xr13, xr13, xr14 + xvsrarni.b.h xr13, xr13, 6 + vstelm.d vr13, a0, 0, 0 + add.d a0, a0, a2 + xvstelm.d xr13, a0, 0, 2 + add.d a0, a0, a2 + + addi.d t1, t1, -4 + blt zero, t1, .LOOP_DA + b .ENDLOOPA +.ENDLOOP_DA: + + bge zero, t0, .ENDLOOP_EA + move t1, a3 + li.d t7, 1 + slt t8, zero, t5 + maskeqz t5, a2, t8 + masknez t7, t7, t8 + or t7, t7, t5 + xvilvl.b xr7, xr4, xr0 +.LOOP_EA: + fld.d f5, a1, 0 + fldx.d f6, a1, t7 + add.d a1, a1, a2 + fld.d f9, a1, 0 + fldx.d f10, a1, t7 + add.d a1, a1, a2 + fld.d f11, a1, 0 + fldx.d f12, a1, t7 + add.d a1, a1, a2 + fld.d f13, a1, 0 + fldx.d f14, a1, t7 + vilvl.b vr5, vr6, vr5 + vilvl.b vr9, vr10, vr9 + vilvl.b vr11, vr12, vr11 + vilvl.b vr13, vr14, vr13 + xvpermi.q xr5, xr9, 0x02 + xvpermi.q xr11, xr13, 0x02 + + xvmulwev.h.bu xr8, xr7, xr5 + xvmaddwod.h.bu xr8, xr7, xr5 + xvmulwev.h.bu xr6, xr7, xr11 + xvmaddwod.h.bu xr6, xr7, xr11 + xvsrarni.b.h xr8, xr8, 6 + vstelm.d vr8, a0, 0, 0 + add.d a0, a0, a2 + xvstelm.d xr8, a0, 0, 2 + add.d a0, a0, a2 + xvsrarni.b.h xr6, xr6, 6 + vstelm.d vr6, a0, 0, 0 + add.d a0, a0, a2 + xvstelm.d xr6, a0, 0, 2 + add.d a0, a0, a2 + add.d a1, a1, a2 + + addi.d t1, t1, -4 + blt zero, t1, .LOOP_EA + b .ENDLOOPA +.ENDLOOP_EA: + + move t1, a3 +.LOOPA: + fld.d f5, a1, 0 + fldx.d f6, a1, a2 + fldx.d f7, a1, t2 + fldx.d f8, a1, t3 + vilvl.d vr5, vr6, vr5 + vilvl.d vr7, vr8, vr7 + xvpermi.q xr5, xr7, 0x02 + xvmulwev.h.bu xr6, xr0, xr5 + xvmulwod.h.bu xr7, xr0, xr5 + xvilvl.h xr8, xr7, xr6 + xvilvh.h xr9, xr7, xr6 + xvsrarni.b.h xr9, xr8, 6 + vstelm.d vr9, a0, 0, 0 + add.d a0, a0, a2 + vstelm.d vr9, a0, 0, 1 + add.d a0, a0, a2 + xvstelm.d xr9, a0, 0, 2 + add.d a0, a0, a2 + xvstelm.d xr9, a0, 0, 3 + add.d a0, a0, a2 + add.d a1, a1, t4 + + addi.d t1, t1, -4 + blt zero, t1, .LOOPA +.ENDLOOPA: +endfunc + +/* void ff_avg_h264_chroma_mc8_lasx(uint8_t *dst, uint8_t *src, ptrdiff_t stride, + int h, int x, int y) */ +function ff_avg_h264_chroma_mc8_lasx + li.d t8, 8 + sub.d t1, t8, a4 // 8-x + sub.d t2, t8, a5 // 8-y + mul.d t3, t1, t2 // A + mul.d t4, a4, t2 // B + mul.d t5, t1, a5 // C + mul.d t6, a4, a5 // D + add.d t0, t4, t5 // E + xvreplgr2vr.b xr0, t3 + xvreplgr2vr.b xr1, t4 + xvreplgr2vr.b xr2, t5 + xvreplgr2vr.b xr3, t6 + xvreplgr2vr.b xr4, t0 + slli.d t2, a2, 1 + add.d t3, t2, a2 + slli.d t4, a2, 2 + + bge zero, t6, .ENDLOOPDA + move t1, a3 + xvilvl.b xr9, xr1, xr0 + xvilvl.b xr10, xr3, xr2 +.LOOPDA: + fld.d f5, a1, 0 + fld.d f6, a1, 1 + add.d a1, a1, a2 + fld.d f7, a1, 0 + fld.d f8, a1, 1 + add.d a1, a1, a2 + fld.d f11, a1, 0 + fld.d f12, a1, 1 + add.d a1, a1, a2 + fld.d f13, a1, 0 + fld.d f14, a1, 1 + add.d a1, a1, a2 + fld.d f15, a1, 0 + fld.d f16, a1, 1 + fld.d f17, a0, 0 + fldx.d f18, a0, a2 + fldx.d f19, a0, t2 + fldx.d f20, a0, t3 + vilvl.b vr5, vr6, vr5 + vilvl.b vr7, vr8, vr7 + vilvl.b vr11, vr12, vr11 + vilvl.b vr13, vr14, vr13 + vilvl.b vr16, vr16, vr15 + xvpermi.q xr5, xr7, 0x02 + xvpermi.q xr7, xr11, 0x02 + xvpermi.q xr11, xr13, 0x02 + xvpermi.q xr13, xr16, 0x02 + xvpermi.q xr17, xr18, 0x02 + xvpermi.q xr19, xr20, 0x02 + + xvmulwev.h.bu xr14, xr9, xr5 + xvmaddwod.h.bu xr14, xr9, xr5 + xvmulwev.h.bu xr15, xr10, xr7 + xvmaddwod.h.bu xr15, xr10, xr7 + xvadd.h xr14, xr14, xr15 + xvsrari.h xr14, xr14, 6 + xvsllwil.hu.bu xr17, xr17, 0 + xvadd.h xr20, xr14, xr17 + xvsrarni.b.h xr20, xr20, 1 + xvstelm.d xr20, a0, 0, 0 + add.d a0, a0, a2 + xvstelm.d xr20, a0, 0, 2 + add.d a0, a0, a2 + xvmulwev.h.bu xr14, xr9, xr11 + xvmaddwod.h.bu xr14, xr9, xr11 + xvmulwev.h.bu xr15, xr10, xr13 + xvmaddwod.h.bu xr15, xr10, xr13 + xvadd.h xr14, xr14, xr15 + xvsrari.h xr14, xr14, 6 + xvsllwil.hu.bu xr19, xr19, 0 + xvadd.h xr21, xr14, xr19 + xvsrarni.b.h xr21, xr21, 1 + xvstelm.d xr21, a0, 0, 0 + add.d a0, a0, a2 + xvstelm.d xr21, a0, 0, 2 + add.d a0, a0, a2 + + addi.d t1, t1, -4 + blt zero, t1, .LOOPDA + b .ENDLOOPELSEA +.ENDLOOPDA: + + bge zero, t0, .ENDLOOPEA + move t1, a3 + li.d t7, 1 + slt t8, zero, t5 + maskeqz t5, a2, t8 + masknez t7, t7, t8 + or t7, t7, t5 + xvilvl.b xr7, xr4, xr0 +.LOOPEA: + fld.d f5, a1, 0 + fldx.d f6, a1, t7 + add.d a1, a1, a2 + fld.d f8, a1, 0 + fldx.d f9, a1, t7 + add.d a1, a1, a2 + fld.d f10, a1, 0 + fldx.d f11, a1, t7 + add.d a1, a1, a2 + fld.d f12, a1, 0 + fldx.d f13, a1, t7 + add.d a1, a1, a2 + fld.d f14, a0, 0 + fldx.d f15, a0, a2 + fldx.d f16, a0, t2 + fldx.d f17, a0, t3 + vilvl.b vr5, vr6, vr5 + vilvl.b vr8, vr9, vr8 + vilvl.b vr10, vr11, vr10 + vilvl.b vr12, vr13, vr12 + xvpermi.q xr5, xr8, 0x02 + xvpermi.q xr10, xr12, 0x02 + xvpermi.q xr14, xr15, 0x02 + xvpermi.q xr16, xr17, 0x02 + + xvmulwev.h.bu xr6, xr7, xr5 + xvmaddwod.h.bu xr6, xr7, xr5 + xvsrari.h xr6, xr6, 6 + xvsllwil.hu.bu xr14, xr14, 0 + xvadd.h xr8, xr6, xr14 + xvsrarni.b.h xr8, xr8, 1 + xvstelm.d xr8, a0, 0, 0 + add.d a0, a0, a2 + xvstelm.d xr8, a0, 0, 2 + add.d a0, a0, a2 + xvmulwev.h.bu xr6, xr7, xr10 + xvmaddwod.h.bu xr6, xr7, xr10 + xvsrari.h xr6, xr6, 6 + xvsllwil.hu.bu xr16, xr16, 0 + xvadd.h xr8, xr6, xr16 + xvsrarni.b.h xr8, xr8, 1 + xvstelm.d xr8, a0, 0, 0 + add.d a0, a0, a2 + xvstelm.d xr8, a0, 0, 2 + add.d a0, a0, a2 + + addi.d t1, t1, -4 + blt zero, t1, .LOOPEA + b .ENDLOOPELSEA +.ENDLOOPEA: + + move t1, a3 +.LOOPELSEA: + fld.d f5, a1, 0 + fldx.d f6, a1, a2 + fldx.d f7, a1, t2 + fldx.d f8, a1, t3 + fld.d f9, a0, 0 + fldx.d f10, a0, a2 + fldx.d f11, a0, t2 + fldx.d f12, a0, t3 + xvpermi.q xr5, xr6, 0x02 + xvpermi.q xr7, xr8, 0x02 + xvpermi.q xr9, xr10, 0x02 + xvpermi.q xr11, xr12, 0x02 + + xvmulwev.h.bu xr12, xr0, xr5 + xvmulwod.h.bu xr13, xr0, xr5 + xvilvl.h xr12, xr13, xr12 + xvsrari.h xr12, xr12, 6 + xvsllwil.hu.bu xr9, xr9, 0 + xvadd.h xr9, xr12, xr9 + xvsrarni.b.h xr9, xr9, 1 + xvstelm.d xr9, a0, 0, 0 + add.d a0, a0, a2 + xvstelm.d xr9, a0, 0, 2 + add.d a0, a0, a2 + xvmulwev.h.bu xr12, xr0, xr7 + xvmulwod.h.bu xr13, xr0, xr7 + xvilvl.h xr12, xr13, xr12 + xvsrari.h xr12, xr12, 6 + xvsllwil.hu.bu xr11, xr11, 0 + xvadd.h xr13, xr12, xr11 + xvsrarni.b.h xr13, xr13, 1 + xvstelm.d xr13, a0, 0, 0 + add.d a0, a0, a2 + xvstelm.d xr13, a0, 0, 2 + add.d a0, a0, a2 + add.d a1, a1, t4 + + addi.d t1, t1, -4 + blt zero, t1, .LOOPELSEA +.ENDLOOPELSEA: +endfunc + +/* void ff_put_h264_chroma_mc4_lasx(uint8_t *dst, uint8_t *src, ptrdiff_t stride, + int h, int x, int y) */ +function ff_put_h264_chroma_mc4_lasx + li.d t8, 8 + sub.d t1, t8, a4 // 8-x + sub.d t2, t8, a5 // 8-y + mul.d t3, t1, t2 // A + mul.d t4, a4, t2 // B + mul.d t5, t1, a5 // C + mul.d t6, a4, a5 // D + add.d t0, t4, t5 // E + slli.d t8, a2, 1 + vreplgr2vr.b vr0, t3 + vreplgr2vr.b vr1, t4 + vreplgr2vr.b vr2, t5 + vreplgr2vr.b vr3, t6 + vreplgr2vr.b vr4, t0 + + bge zero, t6, .ENDPUT_DA + move t1, a3 + vilvl.b vr9, vr1, vr0 + vilvl.b vr10, vr3, vr2 +.PUT_DA: + fld.d f5, a1, 0 + fld.d f6, a1, 1 + add.d a1, a1, a2 + fld.d f7, a1, 0 + fld.d f8, a1, 1 + add.d a1, a1, a2 + fld.d f11, a1, 0 + fld.d f12, a1, 1 + vilvl.b vr5, vr6, vr5 + vilvl.b vr7, vr8, vr7 + vilvl.b vr13, vr12, vr11 + vilvl.d vr5, vr7, vr5 + vilvl.d vr13, vr13, vr7 + vmulwev.h.bu vr14, vr9, vr5 + vmaddwod.h.bu vr14, vr9, vr5 + vmulwev.h.bu vr15, vr10, vr13 + vmaddwod.h.bu vr15, vr10, vr13 + xvadd.h xr14, xr14, xr15 + vsrarni.b.h vr16, vr14, 6 + vstelm.w vr16, a0, 0, 0 + add.d a0, a0, a2 + vstelm.w vr16, a0, 0, 1 + add.d a0, a0, a2 + addi.d t1, t1, -2 + blt zero, t1, .PUT_DA + b .ENDPUTA +.ENDPUT_DA: + + bge zero, t0, .ENDPUT_EA + move t1, a3 + li.d t7, 1 + slt t8, zero, t5 + maskeqz t5, a2, t8 + masknez t7, t7, t8 + or t7, t7, t5 + vilvl.b vr7, vr4, vr0 +.PUT_EA: + fld.d f5, a1, 0 + fldx.d f6, a1, t7 + vilvl.b vr5, vr6, vr5 + add.d a1, a1, a2 + fld.d f8, a1, 0 + fldx.d f9, a1, t7 + vilvl.b vr8, vr9, vr8 + vilvl.d vr5, vr8, vr5 + vmulwev.h.bu vr6, vr7, vr5 + vmaddwod.h.bu vr6, vr7, vr5 + vsrarni.b.h vr6, vr6, 6 + vstelm.w vr6, a0, 0, 0 + add.d a0, a0, a2 + vstelm.w vr6, a0, 0, 1 + add.d a0, a0, a2 + add.d a1, a1, a2 + addi.d t1, t1, -2 + blt zero, t1, .PUT_EA + b .ENDPUTA +.ENDPUT_EA: + + move t1, a3 +.PUTA: + fld.d f5, a1, 0 + fldx.d f8, a1, a2 + vilvl.w vr5, vr8, vr5 + vmulwev.h.bu vr6, vr0, vr5 + vmulwod.h.bu vr7, vr0, vr5 + vilvl.h vr6, vr7, vr6 + vsrarni.b.h vr6, vr6, 6 + vstelm.w vr6, a0, 0, 0 + add.d a0, a0, a2 + vstelm.w vr6, a0, 0, 1 + add.d a0, a0, a2 + add.d a1, a1, t8 + addi.d t1, t1, -2 + blt zero, t1, .PUTA +.ENDPUTA: +endfunc diff --git a/libavcodec/loongarch/h264chroma_init_loongarch.c b/libavcodec/loongarch/h264chroma_init_loongarch.c index 0ca24ecc477..40a957aad3e 100644 --- a/libavcodec/loongarch/h264chroma_init_loongarch.c +++ b/libavcodec/loongarch/h264chroma_init_loongarch.c @@ -19,7 +19,7 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include "h264chroma_lasx.h" +#include "h264chroma_loongarch.h" #include "libavutil/attributes.h" #include "libavutil/loongarch/cpu.h" #include "libavcodec/h264chroma.h" @@ -27,6 +27,14 @@ av_cold void ff_h264chroma_init_loongarch(H264ChromaContext *c, int bit_depth) { int cpu_flags = av_get_cpu_flags(); + if (have_lsx(cpu_flags)) { + if (bit_depth <= 8) { + c->put_h264_chroma_pixels_tab[0] = ff_put_h264_chroma_mc8_lsx; + c->avg_h264_chroma_pixels_tab[0] = ff_avg_h264_chroma_mc8_lsx; + c->put_h264_chroma_pixels_tab[1] = ff_put_h264_chroma_mc4_lsx; + } + } + if (have_lasx(cpu_flags)) { if (bit_depth <= 8) { c->put_h264_chroma_pixels_tab[0] = ff_put_h264_chroma_mc8_lasx; diff --git a/libavcodec/loongarch/h264chroma_lasx.c b/libavcodec/loongarch/h264chroma_lasx.c deleted file mode 100644 index 1c0e002bdf6..00000000000 --- a/libavcodec/loongarch/h264chroma_lasx.c +++ /dev/null @@ -1,1280 +0,0 @@ -/* - * 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(const 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(const 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(const 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(const 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(const 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(const 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(const 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(const 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(const 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(const 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(const 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(const 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(const 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(const 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(const 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(const 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(const 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(const 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(const 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(const 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(const 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(const 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(const 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(const 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(const 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(const 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, const 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, const 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(const 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(const 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(const 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(const 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(const 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(const 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(const 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(const 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(const 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(const 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(const 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(const 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, const 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 deleted file mode 100644 index 633752035e0..00000000000 --- a/libavcodec/loongarch/h264chroma_lasx.h +++ /dev/null @@ -1,36 +0,0 @@ -/* - * 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, const uint8_t *src, ptrdiff_t stride, - int h, int x, int y); -void ff_put_h264_chroma_mc8_lasx(uint8_t *dst, const uint8_t *src, ptrdiff_t stride, - int h, int x, int y); -void ff_avg_h264_chroma_mc8_lasx(uint8_t *dst, const uint8_t *src, ptrdiff_t stride, - int h, int x, int y); - -#endif /* AVCODEC_LOONGARCH_H264CHROMA_LASX_H */ diff --git a/libavcodec/loongarch/h264chroma_loongarch.h b/libavcodec/loongarch/h264chroma_loongarch.h new file mode 100644 index 00000000000..e65fcfe9f38 --- /dev/null +++ b/libavcodec/loongarch/h264chroma_loongarch.h @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2023 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_LOONGARCH_H +#define AVCODEC_LOONGARCH_H264CHROMA_LOONGARCH_H + +#include "libavcodec/h264.h" + +void ff_put_h264_chroma_mc8_lsx(unsigned char *dst, const unsigned char *src, + long int stride, int h, int x, int y); +void ff_avg_h264_chroma_mc8_lsx(unsigned char *dst, const unsigned char *src, + long int stride, int h, int x, int y); +void ff_put_h264_chroma_mc4_lsx(unsigned char *dst, const unsigned char *src, + long int stride, int h, int x, int y); + +void ff_put_h264_chroma_mc4_lasx(unsigned char *dst, const unsigned char *src, + long int stride, int h, int x, int y); +void ff_put_h264_chroma_mc8_lasx(unsigned char *dst, const unsigned char *src, + long int stride, int h, int x, int y); +void ff_avg_h264_chroma_mc8_lasx(unsigned char *dst, const unsigned char *src, + long int stride, int h, int x, int y); + +#endif /* AVCODEC_LOONGARCH_H264CHROMA_LOONGARCH_H */ diff --git a/libavcodec/loongarch/h264intrapred.S b/libavcodec/loongarch/h264intrapred.S new file mode 100644 index 00000000000..a03f467b6ef --- /dev/null +++ b/libavcodec/loongarch/h264intrapred.S @@ -0,0 +1,299 @@ +/* + * Loongson LSX optimized h264intrapred + * + * Copyright (c) 2023 Loongson Technology Corporation Limited + * Contributed by 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 + */ + +#include "loongson_asm.S" + +const shufa +.byte 6, 5, 4, 3, 2, 1, 0 +endconst + +const mulk +.byte 2, 0, 3, 0, 4, 0, 5, 0, 6, 0, 7, 0, 8, 0 +endconst + +const mulh +.byte 0, 0, 1, 0, 2, 0, 3, 0, 4, 0, 5, 0, 6, 0, 7, 0 +.byte 8, 0, 9, 0, 10, 0, 11, 0, 12, 0, 13, 0, 14, 0, 15, 0 +endconst + +.macro PRED16X16_PLANE + slli.d t6, a1, 1 + slli.d t4, a1, 3 + addi.d t0, a0, 7 + sub.d t0, t0, a1 + add.d t1, a0, t4 + addi.d t1, t1, -1 + sub.d t2, t1, t6 + + ld.bu t3, t0, 1 + ld.bu t4, t0, -1 + ld.bu t5, t1, 0 + ld.bu t7, t2, 0 + sub.d t3, t3, t4 + sub.d t4, t5, t7 + + la.local t5, mulk + vld vr0, t5, 0 + fld.d f1, t0, 2 + fld.d f2, t0, -8 + la.local t5, shufa + fld.d f3, t5, 0 + vshuf.b vr2, vr2, vr2, vr3 + vilvl.b vr1, vr1, vr2 + vhsubw.hu.bu vr1, vr1, vr1 + vmul.h vr0, vr0, vr1 + vhaddw.w.h vr1, vr0, vr0 + vhaddw.d.w vr0, vr1, vr1 + vhaddw.q.d vr1, vr0, vr0 + vpickve2gr.w t5, vr1, 0 + add.d t3, t3, t5 +//2 + sub.d t2, t2, a1 + ld.bu t8, t2, 0 + ldx.bu t7, t1, a1 + sub.d t5, t7, t8 + slli.d t5, t5, 1 + +//3&4 + add.d t1, t1, t6 + sub.d t2, t2, a1 + ld.bu t8, t2, 0 + ld.bu t7, t1, 0 + sub.d t7, t7, t8 + slli.d t8, t7, 1 + add.d t7, t7, t8 + add.d t5, t5, t7 + sub.d t2, t2, a1 + ld.bu t8, t2, 0 + ldx.bu t7, t1, a1 + sub.d t7, t7, t8 + slli.d t7, t7, 2 + add.d t5, t5, t7 + +//5&6 + add.d t1, t1, t6 + sub.d t2, t2, a1 + ld.bu t8, t2, 0 + ld.bu t7, t1, 0 + sub.d t7, t7, t8 + slli.d t8, t7, 2 + add.d t7, t7, t8 + add.d t5, t5, t7 + sub.d t2, t2, a1 + ld.bu t8, t2, 0 + ldx.bu t7, t1, a1 + sub.d t7, t7, t8 + slli.d t8, t7, 1 + slli.d t7, t7, 2 + add.d t7, t7, t8 + add.d t5, t5, t7 + +//7&8 + add.d t1, t1, t6 + sub.d t2, t2, a1 + ld.bu t8, t2, 0 + ld.bu t7, t1, 0 + sub.d t7, t7, t8 + slli.d t8, t7, 3 + sub.d t7, t8, t7 + add.d t5, t5, t7 + sub.d t2, t2, a1 + ld.bu t8, t2, 0 + ldx.bu t7, t1, a1 + sub.d t7, t7, t8 + slli.d t7, t7, 3 + add.d t5, t5, t7 + add.d t4, t4, t5 + add.d t1, t1, a1 +.endm + +.macro PRED16X16_PLANE_END + ld.bu t7, t1, 0 + ld.bu t8, t2, 16 + add.d t5, t7, t8 + addi.d t5, t5, 1 + slli.d t5, t5, 4 + add.d t7, t3, t4 + slli.d t8, t7, 3 + sub.d t7, t8, t7 + sub.d t5, t5, t7 + + la.local t8, mulh + vld vr3, t8, 0 + slli.d t8, t3, 3 + vreplgr2vr.h vr4, t3 + vreplgr2vr.h vr9, t8 + vmul.h vr5, vr3, vr4 + +.rept 16 + move t7, t5 + add.d t5, t5, t4 + vreplgr2vr.h vr6, t7 + vadd.h vr7, vr6, vr5 + vadd.h vr8, vr9, vr7 + vssrani.bu.h vr8, vr7, 5 + vst vr8, a0, 0 + add.d a0, a0, a1 +.endr +.endm + +.macro PRED16X16_PLANE_END_LASX + ld.bu t7, t1, 0 + ld.bu t8, t2, 16 + add.d t5, t7, t8 + addi.d t5, t5, 1 + slli.d t5, t5, 4 + add.d t7, t3, t4 + slli.d t8, t7, 3 + sub.d t7, t8, t7 + sub.d t5, t5, t7 + + la.local t8, mulh + xvld xr3, t8, 0 + xvreplgr2vr.h xr4, t3 + xvmul.h xr5, xr3, xr4 + +.rept 8 + move t7, t5 + add.d t5, t5, t4 + xvreplgr2vr.h xr6, t7 + xvreplgr2vr.h xr8, t5 + add.d t5, t5, t4 + xvadd.h xr7, xr6, xr5 + xvadd.h xr9, xr8, xr5 + + xvssrani.bu.h xr9, xr7, 5 + vstelm.d vr9, a0, 0, 0 + xvstelm.d xr9, a0, 8, 2 + add.d a0, a0, a1 + vstelm.d vr9, a0, 0, 1 + xvstelm.d xr9, a0, 8, 3 + add.d a0, a0, a1 +.endr +.endm + +/* void ff_h264_pred16x16_plane_h264_8_lsx(uint8_t *src, ptrdiff_t stride) + */ +function ff_h264_pred16x16_plane_h264_8_lsx + PRED16X16_PLANE + + slli.d t7, t3, 2 + add.d t3, t3, t7 + addi.d t3, t3, 32 + srai.d t3, t3, 6 + slli.d t7, t4, 2 + add.d t4, t4, t7 + addi.d t4, t4, 32 + srai.d t4, t4, 6 + + PRED16X16_PLANE_END +endfunc + +/* void ff_h264_pred16x16_plane_rv40_8_lsx(uint8_t *src, ptrdiff_t stride) + */ +function ff_h264_pred16x16_plane_rv40_8_lsx + PRED16X16_PLANE + + srai.d t7, t3, 2 + add.d t3, t3, t7 + srai.d t3, t3, 4 + srai.d t7, t4, 2 + add.d t4, t4, t7 + srai.d t4, t4, 4 + + PRED16X16_PLANE_END +endfunc + +/* void ff_h264_pred16x16_plane_svq3_8_lsx(uint8_t *src, ptrdiff_t stride) + */ +function ff_h264_pred16x16_plane_svq3_8_lsx + PRED16X16_PLANE + + li.d t6, 4 + li.d t7, 5 + li.d t8, 16 + div.d t3, t3, t6 + mul.d t3, t3, t7 + div.d t3, t3, t8 + div.d t4, t4, t6 + mul.d t4, t4, t7 + div.d t4, t4, t8 + move t7, t3 + move t3, t4 + move t4, t7 + + PRED16X16_PLANE_END +endfunc + +/* void ff_h264_pred16x16_plane_h264_8_lasx(uint8_t *src, ptrdiff_t stride) + */ +function ff_h264_pred16x16_plane_h264_8_lasx + PRED16X16_PLANE + + slli.d t7, t3, 2 + add.d t3, t3, t7 + addi.d t3, t3, 32 + srai.d t3, t3, 6 + slli.d t7, t4, 2 + add.d t4, t4, t7 + addi.d t4, t4, 32 + srai.d t4, t4, 6 + + PRED16X16_PLANE_END_LASX +endfunc + +/* void ff_h264_pred16x16_plane_rv40_8_lasx(uint8_t *src, ptrdiff_t stride) + */ +function ff_h264_pred16x16_plane_rv40_8_lasx + PRED16X16_PLANE + + srai.d t7, t3, 2 + add.d t3, t3, t7 + srai.d t3, t3, 4 + srai.d t7, t4, 2 + add.d t4, t4, t7 + srai.d t4, t4, 4 + + PRED16X16_PLANE_END_LASX +endfunc + +/* void ff_h264_pred16x16_plane_svq3_8_lasx(uint8_t *src, ptrdiff_t stride) + */ +function ff_h264_pred16x16_plane_svq3_8_lasx + PRED16X16_PLANE + + li.d t5, 4 + li.d t7, 5 + li.d t8, 16 + div.d t3, t3, t5 + mul.d t3, t3, t7 + div.d t3, t3, t8 + div.d t4, t4, t5 + mul.d t4, t4, t7 + div.d t4, t4, t8 + move t7, t3 + move t3, t4 + move t4, t7 + + PRED16X16_PLANE_END_LASX +endfunc From f6077cc666b7fdea536c1461c5582ed6ef04d1ff Mon Sep 17 00:00:00 2001 From: yuanhecai Date: Thu, 25 May 2023 15:24:29 +0800 Subject: [PATCH 1176/2172] avcodec/la: Add LSX optimization for h264 qpel. ./configure --disable-lasx ffmpeg -i 1_h264_1080p_30fps_3Mbps.mp4 -f rawvideo -y /dev/null -an before: 214fps after: 274fps Reviewed-by: Shiyou Yin Signed-off-by: Michael Niedermayer --- libavcodec/loongarch/Makefile | 2 + libavcodec/loongarch/h264qpel.S | 1686 +++++++++++++++++ .../loongarch/h264qpel_init_loongarch.c | 74 +- libavcodec/loongarch/h264qpel_lasx.c | 401 +--- libavcodec/loongarch/h264qpel_lasx.h | 158 -- libavcodec/loongarch/h264qpel_loongarch.h | 312 +++ libavcodec/loongarch/h264qpel_lsx.c | 487 +++++ 7 files changed, 2561 insertions(+), 559 deletions(-) create mode 100644 libavcodec/loongarch/h264qpel.S delete mode 100644 libavcodec/loongarch/h264qpel_lasx.h create mode 100644 libavcodec/loongarch/h264qpel_loongarch.h create mode 100644 libavcodec/loongarch/h264qpel_lsx.c diff --git a/libavcodec/loongarch/Makefile b/libavcodec/loongarch/Makefile index a5630551616..06cfab5c205 100644 --- a/libavcodec/loongarch/Makefile +++ b/libavcodec/loongarch/Makefile @@ -31,5 +31,7 @@ LSX-OBJS-$(CONFIG_HEVC_DECODER) += loongarch/hevcdsp_lsx.o \ LSX-OBJS-$(CONFIG_H264DSP) += loongarch/h264idct.o \ loongarch/h264idct_loongarch.o \ loongarch/h264dsp.o +LSX-OBJS-$(CONFIG_H264QPEL) += loongarch/h264qpel.o \ + loongarch/h264qpel_lsx.o LSX-OBJS-$(CONFIG_H264CHROMA) += loongarch/h264chroma.o LSX-OBJS-$(CONFIG_H264PRED) += loongarch/h264intrapred.o diff --git a/libavcodec/loongarch/h264qpel.S b/libavcodec/loongarch/h264qpel.S new file mode 100644 index 00000000000..3f885b6ce23 --- /dev/null +++ b/libavcodec/loongarch/h264qpel.S @@ -0,0 +1,1686 @@ +/* + * Loongson LSX optimized h264qpel + * + * Copyright (c) 2023 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 "loongson_asm.S" + +.macro VLD_QPEL8_H_SSRANI_LSX in0, in1, in2, in3, in4 + vld vr0, \in4, 0 + vldx vr1, \in4, a2 + QPEL8_H_LSX \in0, \in1 + vssrani.bu.h \in0, \in2, 5 + vssrani.bu.h \in1, \in3, 5 +.endm + +.macro VLDX_QPEL8_H_SSRANI_LSX in0, in1, in2, in3, in4 + vldx vr0, \in4, t1 + vldx vr1, \in4, t2 + QPEL8_H_LSX \in0, \in1 + vssrani.bu.h \in0, \in2, 5 + vssrani.bu.h \in1, \in3, 5 +.endm + +.macro VLD_DOUBLE_QPEL8_H_SSRANI_LSX in0, in1, in2, in3, in4, in5, in6, in7, in8 + vld vr0, \in8, 0 + vldx vr1, \in8, a2 + QPEL8_H_LSX \in0, \in1 + vssrani.bu.h \in0, \in4, 5 + vssrani.bu.h \in1, \in5, 5 + vldx vr0, \in8, t1 + vldx vr1, \in8, t2 + QPEL8_H_LSX \in2, \in3 + vssrani.bu.h \in2, \in6, 5 + vssrani.bu.h \in3, \in7, 5 +.endm + +function ff_put_h264_qpel16_mc00_lsx + slli.d t0, a2, 1 + add.d t1, t0, a2 + slli.d t2, t0, 1 +.rept 4 + vld vr0, a1, 0 + vldx vr1, a1, a2 + vldx vr2, a1, t0 + vldx vr3, a1, t1 + add.d a1, a1, t2 + vst vr0, a0, 0 + vstx vr1, a0, a2 + vstx vr2, a0, t0 + vstx vr3, a0, t1 + add.d a0, a0, t2 +.endr +endfunc + +.macro QPEL8_H_LSX out0, out1 + vbsrl.v vr2, vr0, 1 + vbsrl.v vr3, vr1, 1 + vbsrl.v vr4, vr0, 2 + vbsrl.v vr5, vr1, 2 + vbsrl.v vr6, vr0, 3 + vbsrl.v vr7, vr1, 3 + vbsrl.v vr8, vr0, 4 + vbsrl.v vr9, vr1, 4 + vbsrl.v vr10, vr0, 5 + vbsrl.v vr11, vr1, 5 + + vilvl.b vr6, vr4, vr6 + vilvl.b vr7, vr5, vr7 + vilvl.b vr8, vr2, vr8 + vilvl.b vr9, vr3, vr9 + vilvl.b vr10, vr0, vr10 + vilvl.b vr11, vr1, vr11 + vhaddw.hu.bu vr6, vr6, vr6 + vhaddw.hu.bu vr7, vr7, vr7 + vhaddw.hu.bu vr8, vr8, vr8 + vhaddw.hu.bu vr9, vr9, vr9 + vhaddw.hu.bu vr10, vr10, vr10 + vhaddw.hu.bu vr11, vr11, vr11 + vmul.h vr2, vr6, vr20 + vmul.h vr3, vr7, vr20 + vmul.h vr4, vr8, vr21 + vmul.h vr5, vr9, vr21 + vssub.h vr2, vr2, vr4 + vssub.h vr3, vr3, vr5 + vsadd.h vr2, vr2, vr10 + vsadd.h vr3, vr3, vr11 + vsadd.h \out0, vr2, vr22 + vsadd.h \out1, vr3, vr22 +.endm + +.macro VLD_DOUBLE_QPEL8_H_LSX in0, in1, in2, in3, in4 + vld vr0, \in4, 0 + vldx vr1, \in4, a2 + QPEL8_H_LSX \in0, \in1 + vldx vr0, \in4, t1 + vldx vr1, \in4, t2 + QPEL8_H_LSX \in2, \in3 +.endm + +.macro put_h264_qpel16 in0 +function ff_put_h264_qpel16_mc\in0\()_lsx +.ifc \in0, 10 + addi.d t8, a1, 0 +.else + addi.d t8, a1, 1 +.endif + vldi vr20, 0x414 + vldi vr21, 0x405 + vldi vr22, 0x410 + slli.d t1, a2, 1 + add.d t2, t1, a2 + addi.d t0, a1, -2 // t0 = src - 2 + addi.d a1, t0, 8 // a1 = t0 + 8 +.rept 4 + VLD_DOUBLE_QPEL8_H_LSX vr12, vr13, vr14, vr15, t0 + VLD_QPEL8_H_SSRANI_LSX vr2, vr3, vr12, vr13, a1 + vld vr10, t8, 0 + vldx vr11, t8, a2 + vavgr.bu vr0, vr2, vr10 + vavgr.bu vr1, vr3, vr11 + vst vr0, a0, 0 + vstx vr1, a0, a2 + VLDX_QPEL8_H_SSRANI_LSX vr4, vr5, vr14, vr15, a1 + vldx vr12, t8, t1 + vldx vr13, t8, t2 + vavgr.bu vr2, vr4, vr12 + vavgr.bu vr3, vr5, vr13 + vstx vr2, a0, t1 + vstx vr3, a0, t2 + alsl.d a0, a2, a0, 2 + alsl.d t8, a2, t8, 2 + alsl.d a1, a2, a1, 2 + alsl.d t0, a2, t0, 2 +.endr +endfunc +.endm + +put_h264_qpel16 10 +put_h264_qpel16 30 + +function ff_put_h264_qpel16_mc20_lsx + vldi vr20, 0x414 + vldi vr21, 0x405 + vldi vr22, 0x410 + slli.d t1, a2, 1 + add.d t2, t1, a2 + addi.d t0, a1, -2 // t0 = src - 2 + addi.d a1, t0, 8 // a1 = t0 + 8 +.rept 4 + VLD_DOUBLE_QPEL8_H_LSX vr12, vr13, vr14, vr15, t0 + VLD_QPEL8_H_SSRANI_LSX vr2, vr3, vr12, vr13, a1 + vst vr2, a0, 0 + vstx vr3, a0, a2 + VLDX_QPEL8_H_SSRANI_LSX vr4, vr5, vr14, vr15, a1 + vstx vr4, a0, t1 + vstx vr5, a0, t2 + alsl.d a0, a2, a0, 2 + alsl.d a1, a2, a1, 2 + alsl.d t0, a2, t0, 2 +.endr +endfunc + +.macro QPEL8_V_LSX in0, in1, in2, in3, in4, in5, in6 + vilvl.b vr7, \in3, \in2 + vilvl.b vr8, \in4, \in3 + vilvl.b vr9, \in4, \in1 + vilvl.b vr10, \in5, \in2 + vilvl.b vr11, \in5, \in0 + vilvl.b vr12, \in6, \in1 + vhaddw.hu.bu vr7, vr7, vr7 + vhaddw.hu.bu vr8, vr8, vr8 + vhaddw.hu.bu vr9, vr9, vr9 + vhaddw.hu.bu vr10, vr10, vr10 + vhaddw.hu.bu vr11, vr11, vr11 + vhaddw.hu.bu vr12, vr12, vr12 + vmul.h vr7, vr7, vr20 + vmul.h vr8, vr8, vr20 + vmul.h vr9, vr9, vr21 + vmul.h vr10, vr10, vr21 + vssub.h vr7, vr7, vr9 + vssub.h vr8, vr8, vr10 + vsadd.h vr7, vr7, vr11 + vsadd.h vr8, vr8, vr12 + vsadd.h vr7, vr7, vr22 + vsadd.h vr8, vr8, vr22 + + vilvh.b vr13, \in3, \in2 + vilvh.b vr14, \in4, \in3 + vilvh.b vr15, \in4, \in1 + vilvh.b vr16, \in5, \in2 + vilvh.b vr17, \in5, \in0 + vilvh.b vr18, \in6, \in1 + vhaddw.hu.bu vr13, vr13, vr13 + vhaddw.hu.bu vr14, vr14, vr14 + vhaddw.hu.bu vr15, vr15, vr15 + vhaddw.hu.bu vr16, vr16, vr16 + vhaddw.hu.bu vr17, vr17, vr17 + vhaddw.hu.bu vr18, vr18, vr18 + vmul.h vr13, vr13, vr20 + vmul.h vr14, vr14, vr20 + vmul.h vr15, vr15, vr21 + vmul.h vr16, vr16, vr21 + vssub.h vr13, vr13, vr15 + vssub.h vr14, vr14, vr16 + vsadd.h vr13, vr13, vr17 + vsadd.h vr14, vr14, vr18 + vsadd.h vr13, vr13, vr22 + vsadd.h vr14, vr14, vr22 + vssrani.bu.h vr13, vr7, 5 + vssrani.bu.h vr14, vr8, 5 +.endm + +.macro put_h264_qpel16_mc1 in0 +function ff_put_h264_qpel16_mc\in0\()_lsx + slli.d t0, a2, 1 + add.d t1, t0, a2 + sub.d t2, a1, t0 // t2 = src - 2 * stride + vldi vr20, 0x414 + vldi vr21, 0x405 + vldi vr22, 0x410 + + vld vr0, t2, 0 + vldx vr1, t2, a2 + vldx vr2, t2, t0 + vldx vr3, t2, t1 + alsl.d t2, a2, t2, 2 // t2 = t2 + 4 * stride + vld vr4, t2, 0 + vldx vr5, t2, a2 + vldx vr6, t2, t0 + QPEL8_V_LSX vr0, vr1, vr2, vr3, vr4, vr5, vr6 +.ifc \in0, 01 + vavgr.bu vr13, vr2, vr13 + vavgr.bu vr14, vr3, vr14 +.else + vavgr.bu vr13, vr3, vr13 + vavgr.bu vr14, vr4, vr14 +.endif + vst vr13, a0, 0 + vstx vr14, a0, a2 + + vldx vr0, t2, t1 + alsl.d t2, a2, t2, 2 // t2 = t2 + 4 *stride + vld vr1, t2, 0 + QPEL8_V_LSX vr2, vr3, vr4, vr5, vr6, vr0, vr1 +.ifc \in0, 01 + vavgr.bu vr13, vr4, vr13 + vavgr.bu vr14, vr5, vr14 +.else + vavgr.bu vr13, vr5, vr13 + vavgr.bu vr14, vr6, vr14 +.endif + vstx vr13, a0, t0 + vstx vr14, a0, t1 + + alsl.d a0, a2, a0, 2 // dst = dst + 4 * stride + + vldx vr2, t2, a2 + vldx vr3, t2, t0 + QPEL8_V_LSX vr4, vr5, vr6, vr0, vr1, vr2, vr3 +.ifc \in0, 01 + vavgr.bu vr13, vr6, vr13 + vavgr.bu vr14, vr0, vr14 +.else + vavgr.bu vr13, vr0, vr13 + vavgr.bu vr14, vr1, vr14 +.endif + vst vr13, a0, 0 + vstx vr14, a0, a2 + + vldx vr4, t2, t1 + alsl.d t2, a2, t2, 2 // t2 = t2 + 4 * stride + vld vr5, t2, 0 + QPEL8_V_LSX vr6, vr0, vr1, vr2, vr3, vr4, vr5 +.ifc \in0, 01 + vavgr.bu vr13, vr1, vr13 + vavgr.bu vr14, vr2, vr14 +.else + vavgr.bu vr13, vr2, vr13 + vavgr.bu vr14, vr3, vr14 +.endif + vstx vr13, a0, t0 + vstx vr14, a0, t1 + + alsl.d a0, a2, a0, 2 // dst = dst + 4 * stride + + vldx vr6, t2, a2 + vldx vr0, t2, t0 + QPEL8_V_LSX vr1, vr2, vr3, vr4, vr5, vr6, vr0 +.ifc \in0, 01 + vavgr.bu vr13, vr3, vr13 + vavgr.bu vr14, vr4, vr14 +.else + vavgr.bu vr13, vr4, vr13 + vavgr.bu vr14, vr5, vr14 +.endif + vst vr13, a0, 0 + vstx vr14, a0, a2 + + vldx vr1, t2, t1 + alsl.d t2, a2, t2, 2 // t2 = t2 + 4 * stride + vld vr2, t2, 0 + QPEL8_V_LSX vr3, vr4, vr5, vr6, vr0, vr1, vr2 +.ifc \in0, 01 + vavgr.bu vr13, vr5, vr13 + vavgr.bu vr14, vr6, vr14 +.else + vavgr.bu vr13, vr6, vr13 + vavgr.bu vr14, vr0, vr14 +.endif + vstx vr13, a0, t0 + vstx vr14, a0, t1 + + alsl.d a0, a2, a0, 2 // dst = dst + 4 * stride + + vldx vr3, t2, a2 + vldx vr4, t2, t0 + QPEL8_V_LSX vr5, vr6, vr0, vr1, vr2, vr3, vr4 +.ifc \in0, 01 + vavgr.bu vr13, vr0, vr13 + vavgr.bu vr14, vr1, vr14 +.else + vavgr.bu vr13, vr1, vr13 + vavgr.bu vr14, vr2, vr14 +.endif + vst vr13, a0, 0 + vstx vr14, a0, a2 + + vldx vr5, t2, t1 + alsl.d t2, a2, t2, 2 // t2 = t2 + 4 * stride + vld vr6, t2, 0 + QPEL8_V_LSX vr0, vr1, vr2, vr3, vr4, vr5, vr6 +.ifc \in0, 01 + vavgr.bu vr13, vr2, vr13 + vavgr.bu vr14, vr3, vr14 +.else + vavgr.bu vr13, vr3, vr13 + vavgr.bu vr14, vr4, vr14 +.endif + vstx vr13, a0, t0 + vstx vr14, a0, t1 +endfunc +.endm + +put_h264_qpel16_mc1 01 +put_h264_qpel16_mc1 03 + +.macro VST_QPEL8_V_LOWPASS_LSX in0, in1, in2, in3, in4, in5, in6, in7, in8 + QPEL8_V_LSX \in0, \in1, \in2, \in3, \in4, \in5, \in6 + vavgr.bu vr13, \in7, vr13 + vavgr.bu vr14, \in8, vr14 + vst vr13, a0, 0 + vstx vr14, a0, a2 +.endm + +.macro VSTX_QPEL8_V_LOWPASS_LSX in0, in1, in2, in3, in4, in5, in6, in7, in8 + QPEL8_V_LSX \in0, \in1, \in2, \in3, \in4, \in5, \in6 + vavgr.bu vr13, \in7, vr13 + vavgr.bu vr14, \in8, vr14 + vstx vr13, a0, t1 + vstx vr14, a0, t2 +.endm + +function ff_put_h264_qpel16_mc11_lsx + addi.d sp, sp, -64 + fst.d f24, sp, 0 + fst.d f25, sp, 8 + fst.d f26, sp, 16 + fst.d f27, sp, 24 + fst.d f28, sp, 32 + fst.d f29, sp, 40 + fst.d f30, sp, 48 + fst.d f31, sp, 56 + slli.d t1, a2, 1 + add.d t2, t1, a2 + slli.d t6, t1, 1 + vldi vr20, 0x414 + vldi vr21, 0x405 + vldi vr22, 0x410 + sub.d t4, a1, t1 // t4 = src - 2 * stride + addi.d t0, a1, -2 // t0 = src - 2 + addi.d a1, t0, 8 // a1 = t0 + 8 +.rept 2 + VLD_DOUBLE_QPEL8_H_LSX vr12, vr13, vr14, vr15, t0 + alsl.d t0, a2, t0, 2 + VLD_DOUBLE_QPEL8_H_LSX vr16, vr17, vr18, vr19, t0 + VLD_DOUBLE_QPEL8_H_SSRANI_LSX vr23, vr24, vr25, vr26, vr12, vr13, \ + vr14, vr15, a1 + alsl.d a1, a2, a1, 2 + VLD_DOUBLE_QPEL8_H_SSRANI_LSX vr27, vr28, vr29, vr30, vr16, vr17, \ + vr18, vr19, a1 + + vld vr0, t4, 0 // t4 = src - 2 * stride + vldx vr1, t4, a2 + vldx vr2, t4, t1 + vldx vr3, t4, t2 + alsl.d t4, a2, t4, 2 // src + 2 *stride + vld vr4, t4, 0 + vldx vr5, t4, a2 + vldx vr6, t4, t1 + VST_QPEL8_V_LOWPASS_LSX vr0, vr1, vr2, vr3, vr4, vr5, vr6, vr23, vr24 + vldx vr0, t4, t2 + alsl.d t4, a2, t4, 2 // src + 6 *stride + vld vr1, t4, 0 + VSTX_QPEL8_V_LOWPASS_LSX vr2, vr3, vr4, vr5, vr6, vr0, vr1, vr25, vr26 + alsl.d a0, a2, a0, 2 // dst = dst + 4 * stride + vldx vr2, t4, a2 + vldx vr3, t4, t1 + VST_QPEL8_V_LOWPASS_LSX vr4, vr5, vr6, vr0, vr1, vr2, vr3, vr27, vr28 + vldx vr4, t4, t2 + alsl.d t4, a2, t4, 2 // src + 10 *stride + vld vr5, t4, 0 + VSTX_QPEL8_V_LOWPASS_LSX vr6, vr0, vr1, vr2, vr3, vr4, vr5, vr29, vr30 + alsl.d t0, a2, t0, 2 + alsl.d a1, a2, a1, 2 // a1 = src + 8 * stride + alsl.d a0, a2, a0, 2 // dst = dst + 8 * stride + sub.d t4, t4, t6 +.endr + fld.d f24, sp, 0 + fld.d f25, sp, 8 + fld.d f26, sp, 16 + fld.d f27, sp, 24 + fld.d f28, sp, 32 + fld.d f29, sp, 40 + fld.d f30, sp, 48 + fld.d f31, sp, 56 + addi.d sp, sp, 64 +endfunc + +function ff_avg_h264_qpel16_mc00_lsx + slli.d t0, a2, 1 + add.d t1, t0, a2 + slli.d t2, t0, 1 + addi.d t3, a0, 0 +.rept 4 + vld vr0, a1, 0 + vldx vr1, a1, a2 + vldx vr2, a1, t0 + vldx vr3, a1, t1 + add.d a1, a1, t2 + vld vr8, t3, 0 + vldx vr9, t3, a2 + vldx vr10, t3, t0 + vldx vr11, t3, t1 + add.d t3, t3, t2 + vavgr.bu vr0, vr8, vr0 + vavgr.bu vr1, vr9, vr1 + vavgr.bu vr2, vr10, vr2 + vavgr.bu vr3, vr11, vr3 + vst vr0, a0, 0 + vstx vr1, a0, a2 + vstx vr2, a0, t0 + vstx vr3, a0, t1 + add.d a0, a0, t2 +.endr +endfunc + +.macro put_h264_qpel16_mc in0 +function ff_put_h264_qpel16_mc\in0\()_lsx + addi.d sp, sp, -64 + fst.d f24, sp, 0 + fst.d f25, sp, 8 + fst.d f26, sp, 16 + fst.d f27, sp, 24 + fst.d f28, sp, 32 + fst.d f29, sp, 40 + fst.d f30, sp, 48 + fst.d f31, sp, 56 + slli.d t1, a2, 1 + add.d t2, t1, a2 + vldi vr20, 0x414 + vldi vr21, 0x405 + vldi vr22, 0x410 + addi.d t0, a1, -2 // t0 = src - 2 + +.ifc \in0, 33 + add.d t0, t0, a2 +.endif + add.d t3, a1, zero // t3 = src + sub.d t4, a1, t1 // t4 = src - 2 * stride + addi.d t4, t4, 1 + + VLD_DOUBLE_QPEL8_H_LSX vr12, vr13, vr14, vr15, t0 + alsl.d a1, a2, t0, 2 + VLD_DOUBLE_QPEL8_H_LSX vr16, vr17, vr18, vr19, a1 + addi.d a1, t0, 8 + VLD_DOUBLE_QPEL8_H_SSRANI_LSX vr23, vr24, vr25, vr26, vr12, vr13, \ + vr14, vr15, a1 + alsl.d a1, a2, a1, 2 + VLD_DOUBLE_QPEL8_H_SSRANI_LSX vr27, vr28, vr29, vr30, vr16, vr17, \ + vr18, vr19, a1 + vld vr0, t4, 0 // t4 = src - 2 * stride + 1 + vldx vr1, t4, a2 + vldx vr2, t4, t1 + vldx vr3, t4, t2 + alsl.d t4, a2, t4, 2 + vld vr4, t4, 0 + vldx vr5, t4, a2 + vldx vr6, t4, t1 + VST_QPEL8_V_LOWPASS_LSX vr0, vr1, vr2, vr3, vr4, vr5, vr6, vr23, vr24 + vldx vr0, t4, t2 + alsl.d t4, a2, t4, 2 + vld vr1, t4, 0 + VSTX_QPEL8_V_LOWPASS_LSX vr2, vr3, vr4, vr5, vr6, vr0, vr1, vr25, vr26 + add.d t6, t4, zero // t6 = src + 6 * stride + alsl.d a0, a2, a0, 2 // dst = dst + 4 * stride + vldx vr2, t4, a2 + vldx vr3, t4, t1 + VST_QPEL8_V_LOWPASS_LSX vr4, vr5, vr6, vr0, vr1, vr2, vr3, vr27, vr28 + vldx vr4, t4, t2 + alsl.d t4, a2, t4, 2 + vld vr5, t4, 0 + VSTX_QPEL8_V_LOWPASS_LSX vr6, vr0, vr1, vr2, vr3, vr4, vr5, vr29, vr30 + alsl.d a1, a2, t0, 3 // a1 = src + 8 * stride + addi.d t5, a1, 8 // a1 = src + 8 * stride + 8 + VLD_DOUBLE_QPEL8_H_LSX vr12, vr13, vr14, vr15, a1 + alsl.d a1, a2, a1, 2 + VLD_DOUBLE_QPEL8_H_LSX vr16, vr17, vr18, vr19, a1 + VLD_DOUBLE_QPEL8_H_SSRANI_LSX vr23, vr24, vr25, vr26, vr12, vr13, \ + vr14, vr15, t5 + alsl.d t5, a2, t5, 2 + VLD_DOUBLE_QPEL8_H_SSRANI_LSX vr27, vr28, vr29, vr30, vr16, vr17, \ + vr18, vr19, t5 + alsl.d a0, a2, a0, 2 // dst = dst + 4 * stride + + // t6 = src + 6 * stride + 1 + vld vr0, t6, 0 + vldx vr1, t6, a2 + vldx vr2, t6, t1 + vldx vr3, t6, t2 + alsl.d t6, a2, t6, 2 + vld vr4, t6, 0 + vldx vr5, t6, a2 + vldx vr6, t6, t1 + VST_QPEL8_V_LOWPASS_LSX vr0, vr1, vr2, vr3, vr4, vr5, vr6, vr23, vr24 + vldx vr0, t6, t2 + alsl.d t6, a2, t6, 2 + vld vr1, t6, 0 + VSTX_QPEL8_V_LOWPASS_LSX vr2, vr3, vr4, vr5 ,vr6, vr0, vr1, vr25, vr26 + alsl.d a0, a2, a0, 2 // dst = dst + 4 *stride + vldx vr2, t6, a2 + vldx vr3, t6, t1 + VST_QPEL8_V_LOWPASS_LSX vr4, vr5, vr6, vr0, vr1, vr2, vr3, vr27, vr28 + vldx vr4, t6, t2 + alsl.d t6, a2, t6, 2 + vld vr5, t6, 0 + VSTX_QPEL8_V_LOWPASS_LSX vr6, vr0, vr1, vr2, vr3, vr4, vr5, vr29, vr30 + + fld.d f24, sp, 0 + fld.d f25, sp, 8 + fld.d f26, sp, 16 + fld.d f27, sp, 24 + fld.d f28, sp, 32 + fld.d f29, sp, 40 + fld.d f30, sp, 48 + fld.d f31, sp, 56 + addi.d sp, sp, 64 +endfunc +.endm + +put_h264_qpel16_mc 33 +put_h264_qpel16_mc 31 + +function ff_put_h264_qpel16_mc13_lsx + slli.d t1, a2, 1 + add.d t2, t1, a2 + vldi vr20, 0x414 + vldi vr21, 0x405 + vldi vr22, 0x410 + addi.d sp, sp, -64 + fst.d f24, sp, 0 + fst.d f25, sp, 8 + fst.d f26, sp, 16 + fst.d f27, sp, 24 + fst.d f28, sp, 32 + fst.d f29, sp, 40 + fst.d f30, sp, 48 + fst.d f31, sp, 56 + addi.d t0, a1, -2 // t0 = src - 2 + add.d t0, t0, a2 + add.d t3, a1, zero // t3 = src + sub.d t4, a1, t1 // t4 = src - 2 * stride + + VLD_DOUBLE_QPEL8_H_LSX vr12, vr13, vr14, vr15, t0 + alsl.d a1, a2, t0, 2 + VLD_DOUBLE_QPEL8_H_LSX vr16, vr17, vr18, vr19, a1 + addi.d a1, t0, 8 + VLD_DOUBLE_QPEL8_H_SSRANI_LSX vr23, vr24, vr25, vr26, vr12, vr13, \ + vr14, vr15, a1 + alsl.d a1, a2, a1, 2 + VLD_DOUBLE_QPEL8_H_SSRANI_LSX vr27, vr28, vr29, vr30, vr16, vr17, \ + vr18, vr19, a1 + vld vr0, t4, 0 // t4 = src - 2 * stride + 1 + vldx vr1, t4, a2 + vldx vr2, t4, t1 + vldx vr3, t4, t2 + alsl.d t4, a2, t4, 2 + vld vr4, t4, 0 + vldx vr5, t4, a2 + vldx vr6, t4, t1 + VST_QPEL8_V_LOWPASS_LSX vr0, vr1, vr2, vr3, vr4, vr5, vr6, vr23, vr24 + vldx vr0, t4, t2 + alsl.d t4, a2, t4, 2 + vld vr1, t4, 0 + VSTX_QPEL8_V_LOWPASS_LSX vr2, vr3, vr4, vr5, vr6, vr0, vr1, vr25, vr26 + add.d t6, t4, zero + alsl.d a0, a2, a0, 2 // dst = dst + 4 * stride + vldx vr2, t4, a2 + vldx vr3, t4, t1 + VST_QPEL8_V_LOWPASS_LSX vr4, vr5, vr6, vr0, vr1, vr2, vr3, vr27, vr28 + vldx vr4, t4, t2 + alsl.d t4, a2, t4, 2 + vld vr5, t4, 0 + VSTX_QPEL8_V_LOWPASS_LSX vr6, vr0, vr1, vr2, vr3, vr4, vr5, vr29, vr30 + alsl.d a1, a2, t0, 3 // a1 = src + 8 * stride + addi.d t5, a1, 8 // a1 = src + 8 * stride + 8 + VLD_DOUBLE_QPEL8_H_LSX vr12, vr13, vr14, vr15, a1 + alsl.d a1, a2, a1, 2 + VLD_DOUBLE_QPEL8_H_LSX vr16, vr17, vr18, vr19, a1 + VLD_DOUBLE_QPEL8_H_SSRANI_LSX vr23, vr24, vr25, vr26, vr12, vr13, \ + vr14, vr15, t5 + alsl.d t5, a2, t5, 2 + VLD_DOUBLE_QPEL8_H_SSRANI_LSX vr27, vr28, vr29, vr30, vr16, vr17, \ + vr18, vr19, t5 + alsl.d a0, a2, a0, 2 // dst = dst + 4 * stride + + vld vr0, t6, 0 // // t6 = src + 6 * stride + 1 + vldx vr1, t6, a2 + vldx vr2, t6, t1 + vldx vr3, t6, t2 + alsl.d t6, a2, t6, 2 + vld vr4, t6, 0 + vldx vr5, t6, a2 + vldx vr6, t6, t1 + VST_QPEL8_V_LOWPASS_LSX vr0, vr1, vr2, vr3, vr4, vr5, vr6, vr23, vr24 + vldx vr0, t6, t2 + alsl.d t6, a2, t6, 2 + vld vr1, t6, 0 + VSTX_QPEL8_V_LOWPASS_LSX vr2, vr3, vr4, vr5, vr6, vr0, vr1, vr25, vr26 + alsl.d a0, a2, a0, 2 // dst = dst + 4 *stride + vldx vr2, t6, a2 + vldx vr3, t6, t1 + VST_QPEL8_V_LOWPASS_LSX vr4, vr5, vr6, vr0, vr1, vr2, vr3, vr27, vr28 + vldx vr4, t6, t2 + alsl.d t6, a2, t6, 2 + vld vr5, t6, 0 + VSTX_QPEL8_V_LOWPASS_LSX vr6, vr0, vr1, vr2, vr3, vr4, vr5, vr29, vr30 + fld.d f24, sp, 0 + fld.d f25, sp, 8 + fld.d f26, sp, 16 + fld.d f27, sp, 24 + fld.d f28, sp, 32 + fld.d f29, sp, 40 + fld.d f30, sp, 48 + fld.d f31, sp, 56 + addi.d sp, sp, 64 +endfunc + +function ff_avg_h264_qpel16_mc10_lsx + addi.d t0, a0, 0 // t0 = dst + addi.d t4, a1, -2 // t1 = src - 2 + addi.d t5, t4, 8 + slli.d t1, a2, 1 + add.d t2, a2, t1 + vldi vr20, 0x414 + vldi vr21, 0x405 + vldi vr22, 0x410 +.rept 2 + VLD_DOUBLE_QPEL8_H_LSX vr12, vr13, vr14, vr15, t4 + alsl.d t4, a2, t4, 2 + VLD_DOUBLE_QPEL8_H_LSX vr16, vr17, vr18, vr19, t4 + VLD_QPEL8_H_SSRANI_LSX vr2, vr3, vr12, vr13, t5 + vld vr0, a1, 0 + vldx vr1, a1, a2 + vld vr12, t0, 0 + vldx vr13, t0, a2 + vavgr.bu vr0, vr0, vr2 + vavgr.bu vr1, vr1, vr3 + vavgr.bu vr0, vr0, vr12 + vavgr.bu vr1, vr1, vr13 + vst vr0, a0, 0 + vstx vr1, a0, a2 + VLDX_QPEL8_H_SSRANI_LSX vr2, vr3, vr14, vr15, t5 + vldx vr0, a1, t1 + vldx vr1, a1, t2 + vldx vr12, t0, t1 + vldx vr13, t0, t2 + vavgr.bu vr0, vr0, vr2 + vavgr.bu vr1, vr1, vr3 + vavgr.bu vr0, vr0, vr12 + vavgr.bu vr1, vr1, vr13 + vstx vr0, a0, t1 + vstx vr1, a0, t2 + alsl.d t5, a2, t5, 2 + alsl.d a1, a2, a1, 2 + alsl.d t0, a2, t0, 2 + alsl.d a0, a2, a0, 2 + VLD_QPEL8_H_SSRANI_LSX vr2, vr3, vr16, vr17, t5 + vld vr0, a1, 0 + vldx vr1, a1, a2 + vld vr12, t0, 0 + vldx vr13, t0, a2 + vavgr.bu vr0, vr0, vr2 + vavgr.bu vr1, vr1, vr3 + vavgr.bu vr0, vr0, vr12 + vavgr.bu vr1, vr1, vr13 + vst vr0, a0, 0 + vstx vr1, a0, a2 + VLDX_QPEL8_H_SSRANI_LSX vr2, vr3, vr18, vr19, t5 + vldx vr0, a1, t1 + vldx vr1, a1, t2 + vldx vr12, t0, t1 + vldx vr13, t0, t2 + vavgr.bu vr0, vr0, vr2 + vavgr.bu vr1, vr1, vr3 + vavgr.bu vr0, vr0, vr12 + vavgr.bu vr1, vr1, vr13 + vstx vr0, a0, t1 + vstx vr1, a0, t2 + alsl.d t5, a2, t5, 2 + alsl.d a1, a2, a1, 2 + alsl.d t0, a2, t0, 2 + alsl.d a0, a2, a0, 2 + alsl.d t4, a2, t4, 2 // src + 8 * stride -2 +.endr +endfunc + +function ff_avg_h264_qpel16_mc30_lsx + addi.d t0, a0, 0 // t0 = dst + addi.d t4, a1, -2 // t1 = src - 2 + addi.d t5, t4, 8 + addi.d a1, a1, 1 // a1 = a1 + 1 + slli.d t1, a2, 1 + add.d t2, a2, t1 + vldi vr20, 0x414 + vldi vr21, 0x405 + vldi vr22, 0x410 +.rept 2 + VLD_DOUBLE_QPEL8_H_LSX vr12, vr13, vr14, vr15, t4 + alsl.d t4, a2, t4, 2 + VLD_DOUBLE_QPEL8_H_LSX vr16, vr17, vr18, vr19, t4 + VLD_QPEL8_H_SSRANI_LSX vr2, vr3, vr12, vr13, t5 + vld vr0, a1, 0 + vldx vr1, a1, a2 + vld vr12, t0, 0 + vldx vr13, t0, a2 + vavgr.bu vr0, vr0, vr2 + vavgr.bu vr1, vr1, vr3 + vavgr.bu vr0, vr0, vr12 + vavgr.bu vr1, vr1, vr13 + vst vr0, a0, 0 + vstx vr1, a0, a2 + VLDX_QPEL8_H_SSRANI_LSX vr2, vr3, vr14, vr15, t5 + vldx vr0, a1, t1 + vldx vr1, a1, t2 + vldx vr12, t0, t1 + vldx vr13, t0, t2 + vavgr.bu vr0, vr0, vr2 + vavgr.bu vr1, vr1, vr3 + vavgr.bu vr0, vr0, vr12 + vavgr.bu vr1, vr1, vr13 + vstx vr0, a0, t1 + vstx vr1, a0, t2 + alsl.d t5, a2, t5, 2 + alsl.d a1, a2, a1, 2 + alsl.d t0, a2, t0, 2 + alsl.d a0, a2, a0, 2 + VLD_QPEL8_H_SSRANI_LSX vr2, vr3, vr16, vr17, t5 + vld vr0, a1, 0 + vldx vr1, a1, a2 + vld vr12, t0, 0 + vldx vr13, t0, a2 + vavgr.bu vr0, vr0, vr2 + vavgr.bu vr1, vr1, vr3 + vavgr.bu vr0, vr0, vr12 + vavgr.bu vr1, vr1, vr13 + vst vr0, a0, 0 + vstx vr1, a0, a2 + VLDX_QPEL8_H_SSRANI_LSX vr2, vr3, vr18, vr19, t5 + vldx vr0, a1, t1 + vldx vr1, a1, t2 + vldx vr12, t0, t1 + vldx vr13, t0, t2 + vavgr.bu vr0, vr0, vr2 + vavgr.bu vr1, vr1, vr3 + vavgr.bu vr0, vr0, vr12 + vavgr.bu vr1, vr1, vr13 + vstx vr0, a0, t1 + vstx vr1, a0, t2 + alsl.d t5, a2, t5, 2 + alsl.d a1, a2, a1, 2 + alsl.d t0, a2, t0, 2 + alsl.d a0, a2, a0, 2 + alsl.d t4, a2, t4, 2 // t1 = src + 8 * stride -2 +.endr +endfunc + +function ff_put_h264_qpel16_mc02_lsx + slli.d t0, a2, 1 + add.d t1, t0, a2 + sub.d t2, a1, t0 // t2 = src - 2 * stride + vldi vr20, 0x414 + vldi vr21, 0x405 + vldi vr22, 0x410 + + vld vr0, t2, 0 + vldx vr1, t2, a2 + vldx vr2, t2, t0 + vldx vr3, t2, t1 + alsl.d t2, a2, t2, 2 // t2 = t2 + 4 * stride + vld vr4, t2, 0 + vldx vr5, t2, a2 + vldx vr6, t2, t0 + QPEL8_V_LSX vr0, vr1, vr2, vr3, vr4, vr5, vr6 + vst vr13, a0, 0 + vstx vr14, a0, a2 + vldx vr0, t2, t1 + alsl.d t2, a2, t2, 2 // t2 = t2 + 4 *stride + vld vr1, t2, 0 + QPEL8_V_LSX vr2, vr3, vr4, vr5, vr6, vr0, vr1 + vstx vr13, a0, t0 + vstx vr14, a0, t1 + alsl.d a0, a2, a0, 2 // dst = dst + 4 * stride + vldx vr2, t2, a2 + vldx vr3, t2, t0 + QPEL8_V_LSX vr4, vr5, vr6, vr0, vr1, vr2, vr3 + vst vr13, a0, 0 + vstx vr14, a0, a2 + vldx vr4, t2, t1 + alsl.d t2, a2, t2, 2 // t2 = t2 + 4 * stride + vld vr5, t2, 0 + QPEL8_V_LSX vr6, vr0, vr1, vr2, vr3, vr4, vr5 + vstx vr13, a0, t0 + vstx vr14, a0, t1 + + alsl.d a0, a2, a0, 2 // dst = dst + 4 * stride + + vldx vr6, t2, a2 + vldx vr0, t2, t0 + QPEL8_V_LSX vr1, vr2, vr3, vr4, vr5, vr6, vr0 + vst vr13, a0, 0 + vstx vr14, a0, a2 + vldx vr1, t2, t1 + alsl.d t2, a2, t2, 2 // t2 = t2 + 4 * stride + vld vr2, t2, 0 + QPEL8_V_LSX vr3, vr4, vr5, vr6, vr0, vr1, vr2 + vstx vr13, a0, t0 + vstx vr14, a0, t1 + alsl.d a0, a2, a0, 2 // dst = dst + 4 * stride + vldx vr3, t2, a2 + vldx vr4, t2, t0 + QPEL8_V_LSX vr5, vr6, vr0, vr1, vr2, vr3, vr4 + vst vr13, a0, 0 + vstx vr14, a0, a2 + vldx vr5, t2, t1 + alsl.d t2, a2, t2, 2 // t2 = t2 + 4 * stride + vld vr6, t2, 0 + QPEL8_V_LSX vr0, vr1, vr2, vr3, vr4, vr5, vr6 + vstx vr13, a0, t0 + vstx vr14, a0, t1 +endfunc + +.macro avc_luma_hv_qrt_and_aver_dst_16x16_lsx + addi.d sp, sp, -64 + fst.d f24, sp, 0 + fst.d f25, sp, 8 + fst.d f26, sp, 16 + fst.d f27, sp, 24 + fst.d f28, sp, 32 + fst.d f29, sp, 40 + fst.d f30, sp, 48 + fst.d f31, sp, 56 + vldi vr20, 0x414 + vldi vr21, 0x405 + vldi vr22, 0x410 + + VLD_DOUBLE_QPEL8_H_LSX vr12, vr13, vr14, vr15, t0 + alsl.d a1, a2, t0, 2 + VLD_DOUBLE_QPEL8_H_LSX vr16, vr17, vr18, vr19, a1 + addi.d a1, t0, 8 + VLD_DOUBLE_QPEL8_H_SSRANI_LSX vr23, vr24, vr25, vr26, vr12, vr13, \ + vr14, vr15, a1 + alsl.d a1, a2, a1, 2 + VLD_DOUBLE_QPEL8_H_SSRANI_LSX vr27, vr28, vr29, vr30, vr16, vr17, \ + vr18, vr19, a1 + vld vr0, t4, 0 // t4 = src - 2 * stride + 1 + vldx vr1, t4, a2 + vldx vr2, t4, t1 + vldx vr3, t4, t2 + alsl.d t4, a2, t4, 2 + vld vr4, t4, 0 + vldx vr5, t4, a2 + vldx vr6, t4, t1 + QPEL8_V_LSX vr0, vr1, vr2, vr3, vr4, vr5, vr6 + vld vr0, t8, 0 + vldx vr1, t8, a2 + vavgr.bu vr13, vr23, vr13 + vavgr.bu vr14, vr24, vr14 + vavgr.bu vr13, vr13, vr0 + vavgr.bu vr14, vr14, vr1 + vst vr13, a0, 0 + vstx vr14, a0, a2 + vldx vr0, t4, t2 + alsl.d t4, a2, t4, 2 + vld vr1, t4, 0 + QPEL8_V_LSX vr2, vr3, vr4, vr5, vr6, vr0, vr1 + vldx vr2, t8, t1 + vldx vr3, t8, t2 + vavgr.bu vr13, vr25, vr13 + vavgr.bu vr14, vr26, vr14 + vavgr.bu vr13, vr13, vr2 + vavgr.bu vr14, vr14, vr3 + add.d t6, t4, zero // t6 = src + 6 * stride + vstx vr13, a0, t1 + vstx vr14, a0, t2 + alsl.d a0, a2, a0, 2 // dst = dst + 4 * stride + alsl.d t8, a2, t8, 2 + vldx vr2, t4, a2 + vldx vr3, t4, t1 + QPEL8_V_LSX vr4, vr5, vr6, vr0, vr1, vr2, vr3 + vld vr4, t8, 0 + vldx vr5, t8, a2 + vavgr.bu vr13, vr27, vr13 + vavgr.bu vr14, vr28, vr14 + vavgr.bu vr13, vr13, vr4 + vavgr.bu vr14, vr14, vr5 + vst vr13, a0, 0 + vstx vr14, a0, a2 + vldx vr4, t4, t2 + alsl.d t4, a2, t4, 2 + vld vr5, t4, 0 + QPEL8_V_LSX vr6, vr0, vr1, vr2, vr3, vr4, vr5 + vldx vr6, t8, t1 + vldx vr0, t8, t2 + vavgr.bu vr13, vr29, vr13 + vavgr.bu vr14, vr30, vr14 + vavgr.bu vr13, vr13, vr6 + vavgr.bu vr14, vr14, vr0 + vstx vr13, a0, t1 + vstx vr14, a0, t2 + alsl.d a1, a2, t0, 3 // a1 = src + 8 * stride + addi.d t5, a1, 8 // a1 = src + 8 * stride + 8 + VLD_DOUBLE_QPEL8_H_LSX vr12, vr13, vr14, vr15, a1 + alsl.d a1, a2, a1, 2 + VLD_DOUBLE_QPEL8_H_LSX vr16, vr17, vr18, vr19, a1 + VLD_DOUBLE_QPEL8_H_SSRANI_LSX vr23, vr24, vr25, vr26, vr12, vr13, \ + vr14, vr15, t5 + alsl.d t5, a2, t5, 2 + VLD_DOUBLE_QPEL8_H_SSRANI_LSX vr27, vr28, vr29, vr30, vr16, vr17, \ + vr18, vr19, t5 + alsl.d a0, a2, a0, 2 // dst = dst + 4 * stride + alsl.d t8, a2, t8, 2 + // t6 = src + 6 * stride + 1 + vld vr0, t6, 0 + vldx vr1, t6, a2 + vldx vr2, t6, t1 + vldx vr3, t6, t2 + alsl.d t6, a2, t6, 2 + vld vr4, t6, 0 + vldx vr5, t6, a2 + vldx vr6, t6, t1 + QPEL8_V_LSX vr0, vr1, vr2, vr3, vr4, vr5, vr6 + vld vr0, t8, 0 + vldx vr1, t8, a2 + vavgr.bu vr13, vr23, vr13 + vavgr.bu vr14, vr24, vr14 + vavgr.bu vr13, vr13, vr0 + vavgr.bu vr14, vr14, vr1 + vst vr13, a0, 0 + vstx vr14, a0, a2 + vldx vr0, t6, t2 + alsl.d t6, a2, t6, 2 + vld vr1, t6, 0 + QPEL8_V_LSX vr2, vr3, vr4, vr5, vr6, vr0, vr1 + vldx vr2, t8, t1 + vldx vr3, t8, t2 + vavgr.bu vr13, vr25, vr13 + vavgr.bu vr14, vr26, vr14 + vavgr.bu vr13, vr13, vr2 + vavgr.bu vr14, vr14, vr3 + vstx vr13, a0, t1 + vstx vr14, a0, t2 + alsl.d a0, a2, a0, 2 // dst = dst + 4 *stride + alsl.d t8, a2, t8, 2 + vldx vr2, t6, a2 + vldx vr3, t6, t1 + QPEL8_V_LSX vr4, vr5, vr6, vr0, vr1, vr2, vr3 + vld vr4, t8, 0 + vldx vr5, t8, a2 + vavgr.bu vr13, vr27, vr13 + vavgr.bu vr14, vr28, vr14 + vavgr.bu vr13, vr13, vr4 + vavgr.bu vr14, vr14, vr5 + vst vr13, a0, 0 + vstx vr14, a0, a2 + vldx vr4, t6, t2 + alsl.d t6, a2, t6, 2 + vld vr5, t6, 0 + QPEL8_V_LSX vr6, vr0, vr1, vr2, vr3, vr4, vr5 + vldx vr6, t8, t1 + vldx vr0, t8, t2 + vavgr.bu vr13, vr29, vr13 + vavgr.bu vr14, vr30, vr14 + vavgr.bu vr13, vr13, vr6 + vavgr.bu vr14, vr14, vr0 + vstx vr13, a0, t1 + vstx vr14, a0, t2 + fld.d f24, sp, 0 + fld.d f25, sp, 8 + fld.d f26, sp, 16 + fld.d f27, sp, 24 + fld.d f28, sp, 32 + fld.d f29, sp, 40 + fld.d f30, sp, 48 + fld.d f31, sp, 56 + addi.d sp, sp, 64 +.endm + +function ff_avg_h264_qpel16_mc33_lsx + slli.d t1, a2, 1 + add.d t2, t1, a2 + addi.d t0, a1, -2 // t0 = src - 2 + add.d t0, t0, a2 // t0 = src + stride - 2 + add.d t3, a1, zero // t3 = src + sub.d t4, a1, t1 // t4 = src - 2 * stride + addi.d t4, t4, 1 + addi.d t8, a0, 0 + avc_luma_hv_qrt_and_aver_dst_16x16_lsx +endfunc + +function ff_avg_h264_qpel16_mc11_lsx + slli.d t1, a2, 1 + add.d t2, t1, a2 + addi.d t0, a1, -2 // t0 = src - 2 + add.d t3, a1, zero // t3 = src + sub.d t4, a1, t1 // t4 = src - 2 * stride + addi.d t8, a0, 0 + avc_luma_hv_qrt_and_aver_dst_16x16_lsx +endfunc + +function ff_avg_h264_qpel16_mc31_lsx + slli.d t1, a2, 1 + add.d t2, t1, a2 + addi.d t0, a1, -2 // t0 = src - 2 + add.d t3, a1, zero // t3 = src + sub.d t4, a1, t1 // t4 = src - 2 * stride + addi.d t4, t4, 1 + addi.d t8, a0, 0 + avc_luma_hv_qrt_and_aver_dst_16x16_lsx +endfunc + +function ff_avg_h264_qpel16_mc13_lsx + slli.d t1, a2, 1 + add.d t2, t1, a2 + addi.d t0, a1, -2 // t0 = src - 2 + add.d t0, t0, a2 + add.d t3, a1, zero // t3 = src + sub.d t4, a1, t1 // t4 = src - 2 * stride + addi.d t8, a0, 0 + avc_luma_hv_qrt_and_aver_dst_16x16_lsx +endfunc + +function ff_avg_h264_qpel16_mc20_lsx + slli.d t1, a2, 1 + add.d t2, t1, a2 + vldi vr20, 0x414 + vldi vr21, 0x405 + vldi vr22, 0x410 + addi.d t0, a1, -2 // t0 = src - 2 + addi.d t5, a0, 0 + addi.d a1, t0, 8 +.rept 4 + VLD_DOUBLE_QPEL8_H_LSX vr12, vr13, vr14, vr15, t0 + VLD_QPEL8_H_SSRANI_LSX vr2, vr3, vr12, vr13, a1 + vld vr0, t5, 0 + vldx vr1, t5, a2 + vavgr.bu vr0, vr0, vr2 + vavgr.bu vr1, vr1, vr3 + vst vr0, a0, 0 + vstx vr1, a0, a2 + add.d a1, a1, t1 + VLD_QPEL8_H_SSRANI_LSX vr2, vr3, vr14, vr15, a1 + vldx vr0, t5, t1 + vldx vr1, t5, t2 + vavgr.bu vr0, vr0, vr2 + vavgr.bu vr1, vr1, vr3 + vstx vr0, a0, t1 + vstx vr1, a0, t2 + alsl.d t0, a2, t0, 2 + alsl.d t5, a2, t5, 2 + alsl.d a0, a2, a0, 2 + alsl.d a1, a2, a1, 1 +.endr +endfunc + +.macro QPEL8_HV_H_LSX out0, out1 + vbsrl.v vr2, vr0, 1 + vbsrl.v vr3, vr1, 1 + vbsrl.v vr4, vr0, 2 + vbsrl.v vr5, vr1, 2 + vbsrl.v vr6, vr0, 3 + vbsrl.v vr7, vr1, 3 + vbsrl.v vr8, vr0, 4 + vbsrl.v vr9, vr1, 4 + vbsrl.v vr10, vr0, 5 + vbsrl.v vr11, vr1, 5 + vilvl.b vr6, vr4, vr6 + vilvl.b vr7, vr5, vr7 + vilvl.b vr8, vr2, vr8 + vilvl.b vr9, vr3, vr9 + vilvl.b vr10, vr0, vr10 + vilvl.b vr11, vr1, vr11 + vhaddw.hu.bu vr6, vr6, vr6 + vhaddw.hu.bu vr7, vr7, vr7 + vhaddw.hu.bu vr8, vr8, vr8 + vhaddw.hu.bu vr9, vr9, vr9 + vhaddw.hu.bu vr10, vr10, vr10 + vhaddw.hu.bu vr11, vr11, vr11 + vmul.h vr2, vr6, vr20 + vmul.h vr3, vr7, vr20 + vmul.h vr4, vr8, vr21 + vmul.h vr5, vr9, vr21 + vssub.h vr2, vr2, vr4 + vssub.h vr3, vr3, vr5 + vsadd.h \out0, vr2, vr10 + vsadd.h \out1, vr3, vr11 +.endm + +.macro QPEL8_HV_V_LSX in0, in1, in2, in3, in4, in5, in6, out0, out1, out2, out3 + vilvl.h vr0, \in2, \in3 + vilvl.h vr1, \in3, \in4 // tmp0 + vilvl.h vr2, \in1, \in4 + vilvl.h vr3, \in2, \in5 // tmp2 + vilvl.h vr4, \in0, \in5 + vilvl.h vr5, \in1, \in6 // tmp4 + vhaddw.w.h vr0, vr0, vr0 + vhaddw.w.h vr1, vr1, vr1 + vhaddw.w.h vr2, vr2, vr2 + vhaddw.w.h vr3, vr3, vr3 + vhaddw.w.h vr4, vr4, vr4 + vhaddw.w.h vr5, vr5, vr5 + vmul.w vr0, vr0, vr22 + vmul.w vr1, vr1, vr22 + vmul.w vr2, vr2, vr23 + vmul.w vr3, vr3, vr23 + vssub.w vr0, vr0, vr2 + vssub.w vr1, vr1, vr3 + vsadd.w vr0, vr0, vr4 + vsadd.w vr1, vr1, vr5 + vsadd.w \out0, vr0, vr24 + vsadd.w \out1, vr1, vr24 + vilvh.h vr0, \in2, \in3 + vilvh.h vr1, \in3, \in4 // tmp0 + vilvh.h vr2, \in1, \in4 + vilvh.h vr3, \in2, \in5 // tmp2 + vilvh.h vr4, \in0, \in5 + vilvh.h vr5, \in1, \in6 // tmp4 + vhaddw.w.h vr0, vr0, vr0 + vhaddw.w.h vr1, vr1, vr1 + vhaddw.w.h vr2, vr2, vr2 + vhaddw.w.h vr3, vr3, vr3 + vhaddw.w.h vr4, vr4, vr4 + vhaddw.w.h vr5, vr5, vr5 + vmul.w vr0, vr0, vr22 + vmul.w vr1, vr1, vr22 + vmul.w vr2, vr2, vr23 + vmul.w vr3, vr3, vr23 + vssub.w vr0, vr0, vr2 + vssub.w vr1, vr1, vr3 + vsadd.w vr0, vr0, vr4 + vsadd.w vr1, vr1, vr5 + vsadd.w \out2, vr0, vr24 + vsadd.w \out3, vr1, vr24 + vssrani.hu.w \out2, \out0, 10 + vssrani.hu.w \out3, \out1, 10 + vssrani.bu.h \out3, \out2, 0 +.endm + +.macro h264_qpel8_hv_lowpass_core_lsx in0, in1, type + vld vr0, \in0, 0 + vldx vr1, \in0, a3 + QPEL8_HV_H_LSX vr12, vr13 // a b$ + vldx vr0, \in0, t1 + vldx vr1, \in0, t2 + QPEL8_HV_H_LSX vr14, vr15 // c d$ + + alsl.d \in0, a3, \in0, 2 + + vld vr0, \in0, 0 + vldx vr1, \in0, a3 + QPEL8_HV_H_LSX vr16, vr17 // e f$ + vldx vr0, \in0, t1 + vldx vr1, \in0, t2 + QPEL8_HV_H_LSX vr18, vr19 // g h$ + QPEL8_HV_V_LSX vr12, vr13, vr14, vr15, vr16, vr17, vr18, vr6, vr7, vr0, vr1 +.ifc \type, avg + fld.d f2, t3, 0 + fldx.d f3, t3, a2 + vilvl.d vr2, vr3, vr2 + vavgr.bu vr1, vr2, vr1 +.endif + vstelm.d vr1, \in1, 0, 0 + add.d \in1, \in1, a2 + vstelm.d vr1, \in1, 0, 1 + + alsl.d \in0, a3, \in0, 2 + + // tmp8 + vld vr0, \in0, 0 + vldx vr1, \in0, a3 + QPEL8_HV_H_LSX vr12, vr13 + QPEL8_HV_V_LSX vr14, vr15, vr16, vr17, vr18, vr19, vr12, vr6, vr7, vr0, vr1 +.ifc \type, avg + fldx.d f2, t3, t5 + fldx.d f3, t3, t6 + vilvl.d vr2, vr3, vr2 + vavgr.bu vr1, vr2, vr1 +.endif + add.d \in1, \in1, a2 + vstelm.d vr1, \in1, 0, 0 + add.d \in1, \in1, a2 + vstelm.d vr1, \in1, 0, 1 + + // tmp10 + vldx vr0, \in0, t1 + vldx vr1, \in0, t2 + QPEL8_HV_H_LSX vr14, vr15 + QPEL8_HV_V_LSX vr16, vr17, vr18, vr19, vr12, vr13, vr14, vr6, vr7, vr0, vr1 +.ifc \type, avg + alsl.d t3, a2, t3, 2 + fld.d f2, t3, 0 + fldx.d f3, t3, a2 + vilvl.d vr2, vr3, vr2 + vavgr.bu vr1, vr2, vr1 +.endif + add.d \in1, \in1, a2 + vstelm.d vr1, \in1, 0, 0 + add.d \in1, \in1, a2 + vstelm.d vr1, \in1, 0, 1 + + // tmp12 + alsl.d \in0, a3, \in0, 2 + + vld vr0, \in0, 0 + vldx vr1, \in0, a3 + QPEL8_HV_H_LSX vr16, vr17 + QPEL8_HV_V_LSX vr18, vr19, vr12, vr13, vr14, vr15, vr16, vr6, vr7, vr0, vr1 +.ifc \type, avg + fldx.d f2, t3, t5 + fldx.d f3, t3, t6 + vilvl.d vr2, vr3, vr2 + vavgr.bu vr1, vr2, vr1 +.endif + add.d \in1, \in1, a2 + vstelm.d vr1, \in1, 0, 0 + add.d \in1, \in1, a2 + vstelm.d vr1, \in1, 0, 1 +.endm + +function put_h264_qpel8_hv_lowpass_lsx + slli.d t1, a3, 1 + add.d t2, t1, a3 + addi.d sp, sp, -8 + fst.d f24, sp, 0 + addi.d t0, a1, -2 // t0 = src - 2 + sub.d t0, t0, t1 // t0 = t0 - 2 * stride + vldi vr20, 0x414 // h_20 + vldi vr21, 0x405 // h_5 + vldi vr22, 0x814 // w_20 + vldi vr23, 0x805 // w_5 + addi.d t4, zero, 512 + vreplgr2vr.w vr24, t4 // w_512 + h264_qpel8_hv_lowpass_core_lsx t0, a0, put + fld.d f24, sp, 0 + addi.d sp, sp, 8 +endfunc + +function put_h264_qpel8_h_lowpass_lsx + slli.d t1, a3, 1 + add.d t2, t1, a3 + vldi vr20, 0x414 + vldi vr21, 0x405 + vldi vr22, 0x410 + addi.d t0, a1, -2 // t0 = src - 2 + add.d t3, a1, zero // t3 = src +.rept 2 + vld vr0, t0, 0 + vldx vr1, t0, a3 + QPEL8_H_LSX vr12, vr13 + vssrani.bu.h vr13, vr12, 5 + vstelm.d vr13, a0, 0, 0 + add.d a0, a0, a2 + vstelm.d vr13, a0, 0, 1 + add.d a0, a0, a2 + vldx vr0, t0, t1 + vldx vr1, t0, t2 + QPEL8_H_LSX vr12, vr13 + vssrani.bu.h vr13, vr12, 5 + vstelm.d vr13, a0, 0, 0 + add.d a0, a0, a2 + vstelm.d vr13, a0, 0, 1 + add.d a0, a0, a2 + alsl.d t0, a3, t0, 2 +.endr +endfunc + +function put_pixels16_l2_8_lsx + slli.d t0, a4, 1 + add.d t1, t0, a4 + slli.d t2, t0, 1 + slli.d t3, a3, 1 + add.d t4, t3, a3 + slli.d t5, t3, 1 +.rept 4 + vld vr0, a1, 0 + vldx vr1, a1, a4 + vldx vr2, a1, t0 + vldx vr3, a1, t1 + add.d a1, a1, t2 + vld vr8, a2, 0x00 + vld vr9, a2, 0x10 + vld vr10, a2, 0x20 + vld vr11, a2, 0x30 + addi.d a2, a2, 0x40 + vavgr.bu vr0, vr8, vr0 + vavgr.bu vr1, vr9, vr1 + vavgr.bu vr2, vr10, vr2 + vavgr.bu vr3, vr11, vr3 + vst vr0, a0, 0 + vstx vr1, a0, a3 + vstx vr2, a0, t3 + vstx vr3, a0, t4 + add.d a0, a0, t5 +.endr +endfunc + +.macro QPEL8_V1_LSX in0, in1, in2, in3, in4, in5, in6 + vilvl.b vr7, \in3, \in2 + vilvl.b vr8, \in4, \in3 + vilvl.b vr9, \in4, \in1 + vilvl.b vr10, \in5, \in2 + vilvl.b vr11, \in5, \in0 + vilvl.b vr12, \in6, \in1 + vhaddw.hu.bu vr7, vr7, vr7 + vhaddw.hu.bu vr8, vr8, vr8 + vhaddw.hu.bu vr9, vr9, vr9 + vhaddw.hu.bu vr10, vr10, vr10 + vhaddw.hu.bu vr11, vr11, vr11 + vhaddw.hu.bu vr12, vr12, vr12 + vmul.h vr7, vr7, vr20 + vmul.h vr8, vr8, vr20 + vmul.h vr9, vr9, vr21 + vmul.h vr10, vr10, vr21 + vssub.h vr7, vr7, vr9 + vssub.h vr8, vr8, vr10 + vsadd.h vr7, vr7, vr11 + vsadd.h vr8, vr8, vr12 + vsadd.h vr7, vr7, vr22 + vsadd.h vr8, vr8, vr22 + vssrani.bu.h vr8, vr7, 5 +.endm + +.macro h264_qpel8_v_lowpass_lsx type +function \type\()_h264_qpel8_v_lowpass_lsx + slli.d t0, a3, 1 + add.d t1, t0, a3 + sub.d t2, a1, t0 // t2 = src - 2 * stride +.ifc \type, avg + addi.d t3, a0, 0 + slli.d t4, a2, 1 + add.d t5, t4, a2 +.endif + vldi vr20, 0x414 + vldi vr21, 0x405 + vldi vr22, 0x410 + + fld.d f0, t2, 0 + fldx.d f1, t2, a3 + fldx.d f2, t2, t0 + fldx.d f3, t2, t1 + alsl.d t2, a3, t2, 2 // t2 = t2 + 4 * stride + fld.d f4, t2, 0 + fldx.d f5, t2, a3 + fldx.d f6, t2, t0 + QPEL8_V1_LSX vr0, vr1, vr2, vr3, vr4, vr5, vr6 +.ifc \type, avg + fld.d f0, t3, 0 + fldx.d f1, t3, a2 + vilvl.d vr0, vr1, vr0 + vavgr.bu vr8, vr8, vr0 +.endif + vstelm.d vr8, a0, 0, 0 + add.d a0, a0, a2 + vstelm.d vr8, a0, 0, 1 + add.d a0, a0, a2 + + fldx.d f0, t2, t1 + alsl.d t2, a3, t2, 2 // t2 = t2 + 4 *stride + fld.d f1, t2, 0 + QPEL8_V1_LSX vr2, vr3, vr4, vr5, vr6, vr0, vr1 +.ifc \type, avg + fldx.d f2, t3, t4 + fldx.d f3, t3, t5 + vilvl.d vr2, vr3, vr2 + vavgr.bu vr8, vr8, vr2 +.endif + vstelm.d vr8, a0, 0, 0 + add.d a0, a0, a2 + vstelm.d vr8, a0, 0, 1 + add.d a0, a0, a2 + + alsl.d t3, a2, t3, 2 + + fldx.d f2, t2, a3 + fldx.d f3, t2, t0 + QPEL8_V1_LSX vr4, vr5, vr6, vr0, vr1, vr2, vr3 +.ifc \type, avg + fld.d f4, t3, 0 + fldx.d f5, t3, a2 + vilvl.d vr4, vr5, vr4 + vavgr.bu vr8, vr8, vr4 +.endif + vstelm.d vr8, a0, 0, 0 + add.d a0, a0, a2 + vstelm.d vr8, a0, 0, 1 + add.d a0, a0, a2 + + fldx.d f4, t2, t1 + alsl.d t2, a3, t2, 2 // t2 = t2 + 4 * stride + fld.d f5, t2, 0 + QPEL8_V1_LSX vr6, vr0, vr1, vr2, vr3, vr4, vr5 +.ifc \type, avg + fldx.d f6, t3, t4 + fldx.d f0, t3, t5 + vilvl.d vr6, vr0, vr6 + vavgr.bu vr8, vr8, vr6 +.endif + vstelm.d vr8, a0, 0, 0 + add.d a0, a0, a2 + vstelm.d vr8, a0, 0, 1 +endfunc +.endm + +h264_qpel8_v_lowpass_lsx put +h264_qpel8_v_lowpass_lsx avg + +function avg_pixels16_l2_8_lsx + slli.d t0, a4, 1 + add.d t1, t0, a4 + slli.d t2, t0, 1 + slli.d t3, a3, 1 + add.d t4, t3, a3 + slli.d t5, t3, 1 + addi.d t6, a0, 0 +.rept 4 + vld vr0, a1, 0 + vldx vr1, a1, a4 + vldx vr2, a1, t0 + vldx vr3, a1, t1 + add.d a1, a1, t2 + vld vr8, a2, 0x00 + vld vr9, a2, 0x10 + vld vr10, a2, 0x20 + vld vr11, a2, 0x30 + addi.d a2, a2, 0x40 + vavgr.bu vr0, vr8, vr0 + vavgr.bu vr1, vr9, vr1 + vavgr.bu vr2, vr10, vr2 + vavgr.bu vr3, vr11, vr3 + vld vr8, t6, 0 + vldx vr9, t6, a3 + vldx vr10, t6, t3 + vldx vr11, t6, t4 + add.d t6, t6, t5 + vavgr.bu vr0, vr8, vr0 + vavgr.bu vr1, vr9, vr1 + vavgr.bu vr2, vr10, vr2 + vavgr.bu vr3, vr11, vr3 + vst vr0, a0, 0 + vstx vr1, a0, a3 + vstx vr2, a0, t3 + vstx vr3, a0, t4 + add.d a0, a0, t5 +.endr +endfunc + +function avg_h264_qpel8_hv_lowpass_lsx + slli.d t1, a3, 1 + add.d t2, t1, a3 + slli.d t5, a2, 1 + add.d t6, a2, t5 + addi.d sp, sp, -8 + fst.d f24, sp, 0 + vldi vr20, 0x414 // h_20 + vldi vr21, 0x405 // h_5 + vldi vr22, 0x814 // w_20 + vldi vr23, 0x805 // w_5 + addi.d t4, zero, 512 + vreplgr2vr.w vr24, t4 // w_512 + addi.d t0, a1, -2 // t0 = src - 2 + sub.d t0, t0, t1 // t0 = t0 - 2 * stride + addi.d t3, a0, 0 // t3 = dst + h264_qpel8_hv_lowpass_core_lsx t0, a0, avg + fld.d f24, sp, 0 + addi.d sp, sp, 8 +endfunc + +function put_pixels8_l2_8_lsx + slli.d t0, a4, 1 + add.d t1, t0, a4 + slli.d t2, t0, 1 +.rept 2 + vld vr0, a1, 0 + vldx vr1, a1, a4 + vldx vr2, a1, t0 + vldx vr3, a1, t1 + add.d a1, a1, t2 + vilvl.d vr0, vr1, vr0 + vilvl.d vr2, vr3, vr2 + vld vr8, a2, 0x00 + vld vr9, a2, 0x08 + vld vr10, a2, 0x10 + vld vr11, a2, 0x18 + vilvl.d vr8, vr9, vr8 + vilvl.d vr10, vr11, vr10 + addi.d a2, a2, 32 + vavgr.bu vr0, vr8, vr0 + vavgr.bu vr2, vr10, vr2 + vstelm.d vr0, a0, 0, 0 + add.d a0, a0, a3 + vstelm.d vr0, a0, 0, 1 + add.d a0, a0, a3 + vstelm.d vr2, a0, 0, 0 + add.d a0, a0, a3 + vstelm.d vr2, a0, 0, 1 + add.d a0, a0, a3 +.endr +endfunc + +function ff_put_h264_qpel8_mc00_lsx + slli.d t0, a2, 1 + add.d t1, t0, a2 + slli.d t2, t0, 1 + ld.d t3, a1, 0x0 + ldx.d t4, a1, a2 + ldx.d t5, a1, t0 + ldx.d t6, a1, t1 + st.d t3, a0, 0x0 + stx.d t4, a0, a2 + stx.d t5, a0, t0 + stx.d t6, a0, t1 + add.d a1, a1, t2 + add.d a0, a0, t2 + ld.d t3, a1, 0x0 + ldx.d t4, a1, a2 + ldx.d t5, a1, t0 + ldx.d t6, a1, t1 + st.d t3, a0, 0x0 + stx.d t4, a0, a2 + stx.d t5, a0, t0 + stx.d t6, a0, t1 +endfunc + +function ff_avg_h264_qpel8_mc00_lsx + slli.d t0, a2, 1 + add.d t1, t0, a2 + slli.d t2, t0, 1 + addi.d t3, a0, 0 +.rept 2 + vld vr0, a1, 0 + vldx vr1, a1, a2 + vldx vr2, a1, t0 + vldx vr3, a1, t1 + add.d a1, a1, t2 + vilvl.d vr0, vr1, vr0 + vilvl.d vr2, vr3, vr2 + vld vr8, t3, 0 + vldx vr9, t3, a2 + vldx vr10, t3, t0 + vldx vr11, t3, t1 + add.d t3, t3, t2 + vilvl.d vr8, vr9, vr8 + vilvl.d vr10, vr11, vr10 + vavgr.bu vr0, vr8, vr0 + vavgr.bu vr2, vr10, vr2 + vstelm.d vr0, a0, 0, 0 + add.d a0, a0, a2 + vstelm.d vr0, a0, 0, 1 + add.d a0, a0, a2 + vstelm.d vr2, a0, 0, 0 + add.d a0, a0, a2 + vstelm.d vr2, a0, 0, 1 + add.d a0, a0, a2 +.endr +endfunc + +function avg_pixels8_l2_8_lsx + slli.d t0, a4, 1 + add.d t1, t0, a4 + slli.d t2, t0, 1 + addi.d t3, a0, 0 + slli.d t4, a3, 1 + add.d t5, t4, a3 + slli.d t6, t4, 1 +.rept 2 + vld vr0, a1, 0 + vldx vr1, a1, a4 + vldx vr2, a1, t0 + vldx vr3, a1, t1 + add.d a1, a1, t2 + vilvl.d vr0, vr1, vr0 + vilvl.d vr2, vr3, vr2 + vld vr8, a2, 0x00 + vld vr9, a2, 0x08 + vld vr10, a2, 0x10 + vld vr11, a2, 0x18 + addi.d a2, a2, 0x20 + vilvl.d vr8, vr9, vr8 + vilvl.d vr10, vr11, vr10 + vavgr.bu vr0, vr8, vr0 + vavgr.bu vr2, vr10, vr2 + vld vr8, t3, 0 + vldx vr9, t3, a3 + vldx vr10, t3, t4 + vldx vr11, t3, t5 + add.d t3, t3, t6 + vilvl.d vr8, vr9, vr8 + vilvl.d vr10, vr11, vr10 + vavgr.bu vr0, vr8, vr0 + vavgr.bu vr2, vr10, vr2 + vstelm.d vr0, a0, 0, 0 + add.d a0, a0, a3 + vstelm.d vr0, a0, 0, 1 + add.d a0, a0, a3 + vstelm.d vr2, a0, 0, 0 + add.d a0, a0, a3 + vstelm.d vr2, a0, 0, 1 + add.d a0, a0, a3 +.endr +endfunc + +function avg_h264_qpel8_h_lowpass_lsx + slli.d t1, a3, 1 + add.d t2, t1, a3 + slli.d t5, a2, 1 + add.d t6, t5, a2 + vldi vr20, 0x414 + vldi vr21, 0x405 + vldi vr22, 0x410 + addi.d t0, a1, -2 // t0 = src - 2 + add.d t3, a1, zero // t3 = src + addi.d t4, a0, 0 // t4 = dst +.rept 4 + vld vr0, t0, 0 + vldx vr1, t0, a3 + QPEL8_H_LSX vr12, vr13 + vssrani.bu.h vr13, vr12, 5 + fld.d f0, t4, 0 + fldx.d f1, t4, a2 + vilvl.d vr0, vr1, vr0 + vavgr.bu vr13, vr13, vr0 + vstelm.d vr13, a0, 0, 0 + add.d a0, a0, a2 + vstelm.d vr13, a0, 0, 1 + add.d a0, a0, a2 + add.d t0, t0, t1 + add.d t4, t4, t1 +.endr +endfunc diff --git a/libavcodec/loongarch/h264qpel_init_loongarch.c b/libavcodec/loongarch/h264qpel_init_loongarch.c index 969c9c376c6..9d3a5cb1643 100644 --- a/libavcodec/loongarch/h264qpel_init_loongarch.c +++ b/libavcodec/loongarch/h264qpel_init_loongarch.c @@ -19,7 +19,7 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include "h264qpel_lasx.h" +#include "h264qpel_loongarch.h" #include "libavutil/attributes.h" #include "libavutil/loongarch/cpu.h" #include "libavcodec/h264qpel.h" @@ -27,6 +27,77 @@ av_cold void ff_h264qpel_init_loongarch(H264QpelContext *c, int bit_depth) { int cpu_flags = av_get_cpu_flags(); + + if (have_lsx(cpu_flags)) { + if (8 == bit_depth) { + c->put_h264_qpel_pixels_tab[0][0] = ff_put_h264_qpel16_mc00_lsx; + c->put_h264_qpel_pixels_tab[0][1] = ff_put_h264_qpel16_mc10_lsx; + c->put_h264_qpel_pixels_tab[0][2] = ff_put_h264_qpel16_mc20_lsx; + c->put_h264_qpel_pixels_tab[0][3] = ff_put_h264_qpel16_mc30_lsx; + c->put_h264_qpel_pixels_tab[0][4] = ff_put_h264_qpel16_mc01_lsx; + c->put_h264_qpel_pixels_tab[0][5] = ff_put_h264_qpel16_mc11_lsx; + c->put_h264_qpel_pixels_tab[0][6] = ff_put_h264_qpel16_mc21_lsx; + c->put_h264_qpel_pixels_tab[0][7] = ff_put_h264_qpel16_mc31_lsx; + c->put_h264_qpel_pixels_tab[0][8] = ff_put_h264_qpel16_mc02_lsx; + c->put_h264_qpel_pixels_tab[0][9] = ff_put_h264_qpel16_mc12_lsx; + c->put_h264_qpel_pixels_tab[0][10] = ff_put_h264_qpel16_mc22_lsx; + c->put_h264_qpel_pixels_tab[0][11] = ff_put_h264_qpel16_mc32_lsx; + c->put_h264_qpel_pixels_tab[0][12] = ff_put_h264_qpel16_mc03_lsx; + c->put_h264_qpel_pixels_tab[0][13] = ff_put_h264_qpel16_mc13_lsx; + c->put_h264_qpel_pixels_tab[0][14] = ff_put_h264_qpel16_mc23_lsx; + c->put_h264_qpel_pixels_tab[0][15] = ff_put_h264_qpel16_mc33_lsx; + + c->avg_h264_qpel_pixels_tab[0][0] = ff_avg_h264_qpel16_mc00_lsx; + c->avg_h264_qpel_pixels_tab[0][1] = ff_avg_h264_qpel16_mc10_lsx; + c->avg_h264_qpel_pixels_tab[0][2] = ff_avg_h264_qpel16_mc20_lsx; + c->avg_h264_qpel_pixels_tab[0][3] = ff_avg_h264_qpel16_mc30_lsx; + c->avg_h264_qpel_pixels_tab[0][4] = ff_avg_h264_qpel16_mc01_lsx; + c->avg_h264_qpel_pixels_tab[0][5] = ff_avg_h264_qpel16_mc11_lsx; + c->avg_h264_qpel_pixels_tab[0][6] = ff_avg_h264_qpel16_mc21_lsx; + c->avg_h264_qpel_pixels_tab[0][7] = ff_avg_h264_qpel16_mc31_lsx; + c->avg_h264_qpel_pixels_tab[0][8] = ff_avg_h264_qpel16_mc02_lsx; + c->avg_h264_qpel_pixels_tab[0][9] = ff_avg_h264_qpel16_mc12_lsx; + c->avg_h264_qpel_pixels_tab[0][10] = ff_avg_h264_qpel16_mc22_lsx; + c->avg_h264_qpel_pixels_tab[0][11] = ff_avg_h264_qpel16_mc32_lsx; + c->avg_h264_qpel_pixels_tab[0][12] = ff_avg_h264_qpel16_mc03_lsx; + c->avg_h264_qpel_pixels_tab[0][13] = ff_avg_h264_qpel16_mc13_lsx; + c->avg_h264_qpel_pixels_tab[0][14] = ff_avg_h264_qpel16_mc23_lsx; + c->avg_h264_qpel_pixels_tab[0][15] = ff_avg_h264_qpel16_mc33_lsx; + + c->put_h264_qpel_pixels_tab[1][0] = ff_put_h264_qpel8_mc00_lsx; + c->put_h264_qpel_pixels_tab[1][1] = ff_put_h264_qpel8_mc10_lsx; + c->put_h264_qpel_pixels_tab[1][2] = ff_put_h264_qpel8_mc20_lsx; + c->put_h264_qpel_pixels_tab[1][3] = ff_put_h264_qpel8_mc30_lsx; + c->put_h264_qpel_pixels_tab[1][4] = ff_put_h264_qpel8_mc01_lsx; + c->put_h264_qpel_pixels_tab[1][5] = ff_put_h264_qpel8_mc11_lsx; + c->put_h264_qpel_pixels_tab[1][6] = ff_put_h264_qpel8_mc21_lsx; + c->put_h264_qpel_pixels_tab[1][7] = ff_put_h264_qpel8_mc31_lsx; + c->put_h264_qpel_pixels_tab[1][8] = ff_put_h264_qpel8_mc02_lsx; + c->put_h264_qpel_pixels_tab[1][9] = ff_put_h264_qpel8_mc12_lsx; + c->put_h264_qpel_pixels_tab[1][10] = ff_put_h264_qpel8_mc22_lsx; + c->put_h264_qpel_pixels_tab[1][11] = ff_put_h264_qpel8_mc32_lsx; + c->put_h264_qpel_pixels_tab[1][12] = ff_put_h264_qpel8_mc03_lsx; + c->put_h264_qpel_pixels_tab[1][13] = ff_put_h264_qpel8_mc13_lsx; + c->put_h264_qpel_pixels_tab[1][14] = ff_put_h264_qpel8_mc23_lsx; + c->put_h264_qpel_pixels_tab[1][15] = ff_put_h264_qpel8_mc33_lsx; + + c->avg_h264_qpel_pixels_tab[1][0] = ff_avg_h264_qpel8_mc00_lsx; + c->avg_h264_qpel_pixels_tab[1][1] = ff_avg_h264_qpel8_mc10_lsx; + c->avg_h264_qpel_pixels_tab[1][2] = ff_avg_h264_qpel8_mc20_lsx; + c->avg_h264_qpel_pixels_tab[1][3] = ff_avg_h264_qpel8_mc30_lsx; + c->avg_h264_qpel_pixels_tab[1][5] = ff_avg_h264_qpel8_mc11_lsx; + c->avg_h264_qpel_pixels_tab[1][6] = ff_avg_h264_qpel8_mc21_lsx; + c->avg_h264_qpel_pixels_tab[1][7] = ff_avg_h264_qpel8_mc31_lsx; + c->avg_h264_qpel_pixels_tab[1][8] = ff_avg_h264_qpel8_mc02_lsx; + c->avg_h264_qpel_pixels_tab[1][9] = ff_avg_h264_qpel8_mc12_lsx; + c->avg_h264_qpel_pixels_tab[1][10] = ff_avg_h264_qpel8_mc22_lsx; + c->avg_h264_qpel_pixels_tab[1][11] = ff_avg_h264_qpel8_mc32_lsx; + c->avg_h264_qpel_pixels_tab[1][13] = ff_avg_h264_qpel8_mc13_lsx; + c->avg_h264_qpel_pixels_tab[1][14] = ff_avg_h264_qpel8_mc23_lsx; + c->avg_h264_qpel_pixels_tab[1][15] = ff_avg_h264_qpel8_mc33_lsx; + } + } +#if HAVE_LASX if (have_lasx(cpu_flags)) { if (8 == bit_depth) { c->put_h264_qpel_pixels_tab[0][0] = ff_put_h264_qpel16_mc00_lasx; @@ -95,4 +166,5 @@ av_cold void ff_h264qpel_init_loongarch(H264QpelContext *c, int bit_depth) c->avg_h264_qpel_pixels_tab[1][15] = ff_avg_h264_qpel8_mc33_lasx; } } +#endif } diff --git a/libavcodec/loongarch/h264qpel_lasx.c b/libavcodec/loongarch/h264qpel_lasx.c index 1c142e510eb..519bb03fe64 100644 --- a/libavcodec/loongarch/h264qpel_lasx.c +++ b/libavcodec/loongarch/h264qpel_lasx.c @@ -21,7 +21,7 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include "h264qpel_lasx.h" +#include "h264qpel_loongarch.h" #include "libavutil/loongarch/loongson_intrinsics.h" #include "libavutil/attributes.h" @@ -418,157 +418,6 @@ avg_pixels8_8_lsx(uint8_t *dst, const uint8_t *src, ptrdiff_t stride) ); } -/* 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) @@ -729,254 +578,6 @@ avg_pixels16_8_lsx(uint8_t *dst, const uint8_t *src, ptrdiff_t stride) ); } -/* 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; \ diff --git a/libavcodec/loongarch/h264qpel_lasx.h b/libavcodec/loongarch/h264qpel_lasx.h deleted file mode 100644 index 32b6b509170..00000000000 --- a/libavcodec/loongarch/h264qpel_lasx.h +++ /dev/null @@ -1,158 +0,0 @@ -/* - * 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 diff --git a/libavcodec/loongarch/h264qpel_loongarch.h b/libavcodec/loongarch/h264qpel_loongarch.h new file mode 100644 index 00000000000..68232730dac --- /dev/null +++ b/libavcodec/loongarch/h264qpel_loongarch.h @@ -0,0 +1,312 @@ +/* + * Copyright (c) 2023 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_LOONGARCH_H +#define AVCODEC_LOONGARCH_H264QPEL_LOONGARCH_H + +#include +#include +#include "libavcodec/h264.h" +#include "config.h" + +void put_h264_qpel8_hv_lowpass_lsx(uint8_t *dst, const uint8_t *src, + ptrdiff_t dstStride, ptrdiff_t srcStride); +void put_h264_qpel8_h_lowpass_lsx(uint8_t *dst, const uint8_t *src, + ptrdiff_t dstStride, ptrdiff_t srcStride); +void put_h264_qpel8_v_lowpass_lsx(uint8_t *dst, const uint8_t *src, + ptrdiff_t dstStride, ptrdiff_t srcStride); +void put_pixels16_l2_8_lsx(uint8_t *dst, const uint8_t *src, uint8_t *half, + ptrdiff_t dstStride, ptrdiff_t srcStride); +void put_pixels8_l2_8_lsx(uint8_t *dst, const uint8_t *src, const uint8_t *half, + ptrdiff_t dstStride, ptrdiff_t srcStride); + +void avg_h264_qpel8_h_lowpass_lsx(uint8_t *dst, const uint8_t *src, int dstStride, + int srcStride); +void avg_h264_qpel8_v_lowpass_lsx(uint8_t *dst, uint8_t *src, int dstStride, + int srcStride); +void avg_pixels16_l2_8_lsx(uint8_t *dst, const uint8_t *src, uint8_t *half, + ptrdiff_t dstStride, ptrdiff_t srcStride); +void avg_h264_qpel8_hv_lowpass_lsx(uint8_t *dst, const uint8_t *src, + ptrdiff_t dstStride, ptrdiff_t srcStride); +void avg_pixels8_l2_8_lsx(uint8_t *dst, const uint8_t *src, const uint8_t *half, + ptrdiff_t dstStride, ptrdiff_t srcStride); + +void ff_put_h264_qpel16_mc00_lsx(uint8_t *dst, const uint8_t *src, + ptrdiff_t dst_stride); +void ff_put_h264_qpel16_mc10_lsx(uint8_t *dst, const uint8_t *src, + ptrdiff_t dst_stride); +void ff_put_h264_qpel16_mc20_lsx(uint8_t *dst, const uint8_t *src, + ptrdiff_t dst_stride); +void ff_put_h264_qpel16_mc30_lsx(uint8_t *dst, const uint8_t *src, + ptrdiff_t dst_stride); +void ff_put_h264_qpel16_mc01_lsx(uint8_t *dst, const uint8_t *src, + ptrdiff_t dst_stride); +void ff_put_h264_qpel16_mc11_lsx(uint8_t *dst, const uint8_t *src, + ptrdiff_t dst_stride); +void ff_put_h264_qpel16_mc13_lsx(uint8_t *dst, const uint8_t *src, + ptrdiff_t dst_stride); +void ff_put_h264_qpel16_mc31_lsx(uint8_t *dst, const uint8_t *src, + ptrdiff_t dst_stride); +void ff_put_h264_qpel16_mc33_lsx(uint8_t *dst, const uint8_t *src, + ptrdiff_t dst_stride); +void ff_put_h264_qpel16_mc03_lsx(uint8_t *dst, const uint8_t *src, + ptrdiff_t dst_stride); +void ff_put_h264_qpel16_mc02_lsx(uint8_t *dst, const uint8_t *src, + ptrdiff_t dst_stride); +void ff_put_h264_qpel16_mc22_lsx(uint8_t *dst, const uint8_t *src, + ptrdiff_t dst_stride); +void ff_put_h264_qpel16_mc21_lsx(uint8_t *dst, const uint8_t *src, + ptrdiff_t stride); +void ff_put_h264_qpel16_mc12_lsx(uint8_t *dst, const uint8_t *src, + ptrdiff_t stride); +void ff_put_h264_qpel16_mc32_lsx(uint8_t *dst, const uint8_t *src, + ptrdiff_t stride); +void ff_put_h264_qpel16_mc23_lsx(uint8_t *dst, const uint8_t *src, + ptrdiff_t stride); + +void ff_avg_h264_qpel16_mc00_lsx(uint8_t *dst, const uint8_t *src, + ptrdiff_t dst_stride); +void ff_avg_h264_qpel16_mc10_lsx(uint8_t *dst, const uint8_t *src, + ptrdiff_t dst_stride); +void ff_avg_h264_qpel16_mc30_lsx(uint8_t *dst, const uint8_t *src, + ptrdiff_t dst_stride); +void ff_avg_h264_qpel16_mc33_lsx(uint8_t *dst, const uint8_t *src, + ptrdiff_t dst_stride); +void ff_avg_h264_qpel16_mc11_lsx(uint8_t *dst, const uint8_t *src, + ptrdiff_t dst_stride); +void ff_avg_h264_qpel16_mc31_lsx(uint8_t *dst, const uint8_t *src, + ptrdiff_t dst_stride); +void ff_avg_h264_qpel16_mc13_lsx(uint8_t *dst, const uint8_t *src, + ptrdiff_t dst_stride); +void ff_avg_h264_qpel16_mc20_lsx(uint8_t *dst, const uint8_t *src, + ptrdiff_t dst_stride); +void ff_avg_h264_qpel16_mc02_lsx(uint8_t *dst, const uint8_t *src, + ptrdiff_t stride); +void ff_avg_h264_qpel16_mc03_lsx(uint8_t *dst, const uint8_t *src, + ptrdiff_t stride); +void ff_avg_h264_qpel16_mc23_lsx(uint8_t *dst, const uint8_t *src, + ptrdiff_t stride); +void ff_avg_h264_qpel16_mc21_lsx(uint8_t *dst, const uint8_t *src, + ptrdiff_t stride); +void ff_avg_h264_qpel16_mc01_lsx(uint8_t *dst, const uint8_t *src, + ptrdiff_t stride); +void ff_avg_h264_qpel16_mc32_lsx(uint8_t *dst, const uint8_t *src, + ptrdiff_t stride); +void ff_avg_h264_qpel16_mc12_lsx(uint8_t *dst, const uint8_t *src, + ptrdiff_t stride); +void ff_avg_h264_qpel16_mc22_lsx(uint8_t *dst, const uint8_t *src, + ptrdiff_t stride); + +void ff_put_h264_qpel8_mc03_lsx(uint8_t *dst, const uint8_t *src, + ptrdiff_t stride); +void ff_put_h264_qpel8_mc00_lsx(uint8_t *dst, const uint8_t *src, + ptrdiff_t stride); +void ff_put_h264_qpel8_mc01_lsx(uint8_t *dst, const uint8_t *src, + ptrdiff_t stride); +void ff_put_h264_qpel8_mc30_lsx(uint8_t *dst, const uint8_t *src, + ptrdiff_t stride); +void ff_put_h264_qpel8_mc10_lsx(uint8_t *dst, const uint8_t *src, + ptrdiff_t stride); +void ff_put_h264_qpel8_mc33_lsx(uint8_t *dst, const uint8_t *src, + ptrdiff_t stride); +void ff_put_h264_qpel8_mc13_lsx(uint8_t *dst, const uint8_t *src, + ptrdiff_t stride); +void ff_put_h264_qpel8_mc31_lsx(uint8_t *dst, const uint8_t *src, + ptrdiff_t stride); +void ff_put_h264_qpel8_mc11_lsx(uint8_t *dst, const uint8_t *src, + ptrdiff_t stride); +void ff_put_h264_qpel8_mc32_lsx(uint8_t *dst, const uint8_t *src, + ptrdiff_t stride); +void ff_put_h264_qpel8_mc21_lsx(uint8_t *dst, const uint8_t *src, + ptrdiff_t stride); +void ff_put_h264_qpel8_mc23_lsx(uint8_t *dst, const uint8_t *src, + ptrdiff_t stride); +void ff_put_h264_qpel8_mc12_lsx(uint8_t *dst, const uint8_t *src, + ptrdiff_t stride); +void ff_put_h264_qpel8_mc02_lsx(uint8_t *dst, const uint8_t *src, + ptrdiff_t stride); +void ff_put_h264_qpel8_mc22_lsx(uint8_t *dst, const uint8_t *src, + ptrdiff_t stride); +void ff_put_h264_qpel8_mc20_lsx(uint8_t *dst, const uint8_t *src, + ptrdiff_t stride); + +void ff_avg_h264_qpel8_mc00_lsx(uint8_t *dst, const uint8_t *src, + ptrdiff_t stride); +void ff_avg_h264_qpel8_mc10_lsx(uint8_t *dst, const uint8_t *src, + ptrdiff_t stride); +void ff_avg_h264_qpel8_mc20_lsx(uint8_t *dst, const uint8_t *src, + ptrdiff_t stride); +void ff_avg_h264_qpel8_mc30_lsx(uint8_t *dst, const uint8_t *src, + ptrdiff_t stride); +void ff_avg_h264_qpel8_mc11_lsx(uint8_t *dst, const uint8_t *src, + ptrdiff_t stride); +void ff_avg_h264_qpel8_mc21_lsx(uint8_t *dst, const uint8_t *src, + ptrdiff_t stride); +void ff_avg_h264_qpel8_mc31_lsx(uint8_t *dst, const uint8_t *src, + ptrdiff_t stride); +void ff_avg_h264_qpel8_mc02_lsx(uint8_t *dst, const uint8_t *src, + ptrdiff_t stride); +void ff_avg_h264_qpel8_mc12_lsx(uint8_t *dst, const uint8_t *src, + ptrdiff_t stride); +void ff_avg_h264_qpel8_mc22_lsx(uint8_t *dst, const uint8_t *src, + ptrdiff_t stride); +void ff_avg_h264_qpel8_mc32_lsx(uint8_t *dst, const uint8_t *src, + ptrdiff_t stride); +void ff_avg_h264_qpel8_mc13_lsx(uint8_t *dst, const uint8_t *src, + ptrdiff_t stride); +void ff_avg_h264_qpel8_mc23_lsx(uint8_t *dst, const uint8_t *src, + ptrdiff_t stride); +void ff_avg_h264_qpel8_mc33_lsx(uint8_t *dst, const uint8_t *src, + ptrdiff_t stride); + +#if HAVE_LASX +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 + +#endif // #ifndef AVCODEC_LOONGARCH_H264QPEL_LOONGARCH_H diff --git a/libavcodec/loongarch/h264qpel_lsx.c b/libavcodec/loongarch/h264qpel_lsx.c new file mode 100644 index 00000000000..12b3bae6d1c --- /dev/null +++ b/libavcodec/loongarch/h264qpel_lsx.c @@ -0,0 +1,487 @@ +/* + * Loongson LSX optimized h264qpel + * + * Copyright (c) 2023 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 "h264qpel_loongarch.h" +#include "libavutil/loongarch/loongson_intrinsics.h" +#include "libavutil/attributes.h" + +static void put_h264_qpel16_hv_lowpass_lsx(uint8_t *dst, const uint8_t *src, + ptrdiff_t dstStride, ptrdiff_t srcStride) +{ + put_h264_qpel8_hv_lowpass_lsx(dst, src, dstStride, srcStride); + put_h264_qpel8_hv_lowpass_lsx(dst + 8, src + 8, dstStride, srcStride); + src += srcStride << 3; + dst += dstStride << 3; + put_h264_qpel8_hv_lowpass_lsx(dst, src, dstStride, srcStride); + put_h264_qpel8_hv_lowpass_lsx(dst + 8, src + 8, dstStride, srcStride); +} + +void ff_put_h264_qpel16_mc22_lsx(uint8_t *dst, const uint8_t *src, + ptrdiff_t stride) +{ + put_h264_qpel16_hv_lowpass_lsx(dst, src, stride, stride); +} + +static void put_h264_qpel16_h_lowpass_lsx(uint8_t *dst, const uint8_t *src, + int dstStride, int srcStride) +{ + put_h264_qpel8_h_lowpass_lsx(dst, src, dstStride, srcStride); + put_h264_qpel8_h_lowpass_lsx(dst+8, src+8, dstStride, srcStride); + src += srcStride << 3; + dst += dstStride << 3; + put_h264_qpel8_h_lowpass_lsx(dst, src, dstStride, srcStride); + put_h264_qpel8_h_lowpass_lsx(dst+8, src+8, dstStride, srcStride); +} + +static void put_h264_qpel16_v_lowpass_lsx(uint8_t *dst, const uint8_t *src, + int dstStride, int srcStride) +{ + put_h264_qpel8_v_lowpass_lsx(dst, (uint8_t*)src, dstStride, srcStride); + put_h264_qpel8_v_lowpass_lsx(dst+8, (uint8_t*)src+8, dstStride, srcStride); + src += 8*srcStride; + dst += 8*dstStride; + put_h264_qpel8_v_lowpass_lsx(dst, (uint8_t*)src, dstStride, srcStride); + put_h264_qpel8_v_lowpass_lsx(dst+8, (uint8_t*)src+8, dstStride, srcStride); +} + +void ff_put_h264_qpel16_mc21_lsx(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_lsx(halfH, src, 16, stride); + put_h264_qpel16_hv_lowpass_lsx(halfHV, src, 16, stride); + put_pixels16_l2_8_lsx(dst, halfH, halfHV, stride, 16); +} + +void ff_put_h264_qpel16_mc12_lsx(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_lsx(halfHV, src, 16, stride); + put_h264_qpel16_v_lowpass_lsx(halfH, src, 16, stride); + put_pixels16_l2_8_lsx(dst, halfH, halfHV, stride, 16); +} + +void ff_put_h264_qpel16_mc32_lsx(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_lsx(halfHV, src, 16, stride); + put_h264_qpel16_v_lowpass_lsx(halfH, src + 1, 16, stride); + put_pixels16_l2_8_lsx(dst, halfH, halfHV, stride, 16); +} + +void ff_put_h264_qpel16_mc23_lsx(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_lsx(halfH, src + stride, 16, stride); + put_h264_qpel16_hv_lowpass_lsx(halfHV, src, 16, stride); + put_pixels16_l2_8_lsx(dst, halfH, halfHV, stride, 16); +} + +static void avg_h264_qpel16_v_lowpass_lsx(uint8_t *dst, const uint8_t *src, + int dstStride, int srcStride) +{ + avg_h264_qpel8_v_lowpass_lsx(dst, (uint8_t*)src, dstStride, srcStride); + avg_h264_qpel8_v_lowpass_lsx(dst+8, (uint8_t*)src+8, dstStride, srcStride); + src += 8*srcStride; + dst += 8*dstStride; + avg_h264_qpel8_v_lowpass_lsx(dst, (uint8_t*)src, dstStride, srcStride); + avg_h264_qpel8_v_lowpass_lsx(dst+8, (uint8_t*)src+8, dstStride, srcStride); +} + +void ff_avg_h264_qpel16_mc02_lsx(uint8_t *dst, const uint8_t *src, + ptrdiff_t stride) +{ + avg_h264_qpel16_v_lowpass_lsx(dst, src, stride, stride); +} + +void ff_avg_h264_qpel16_mc03_lsx(uint8_t *dst, const uint8_t *src, + ptrdiff_t stride) +{ + uint8_t half[256]; + + put_h264_qpel16_v_lowpass_lsx(half, src, 16, stride); + avg_pixels16_l2_8_lsx(dst, src + stride, half, stride, stride); +} + +void ff_avg_h264_qpel16_mc23_lsx(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_lsx(halfH, src + stride, 16, stride); + put_h264_qpel16_hv_lowpass_lsx(halfHV, src, 16, stride); + avg_pixels16_l2_8_lsx(dst, halfH, halfHV, stride, 16); +} + +void ff_avg_h264_qpel16_mc21_lsx(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_lsx(halfH, src, 16, stride); + put_h264_qpel16_hv_lowpass_lsx(halfHV, src, 16, stride); + avg_pixels16_l2_8_lsx(dst, halfH, halfHV, stride, 16); +} + +void ff_avg_h264_qpel16_mc01_lsx(uint8_t *dst, const uint8_t *src, + ptrdiff_t stride) +{ + uint8_t half[256]; + + put_h264_qpel16_v_lowpass_lsx(half, src, 16, stride); + avg_pixels16_l2_8_lsx(dst, src, half, stride, stride); +} + +void ff_avg_h264_qpel16_mc32_lsx(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_lsx(halfHV, src, 16, stride); + put_h264_qpel16_v_lowpass_lsx(halfH, src + 1, 16, stride); + avg_pixels16_l2_8_lsx(dst, halfH, halfHV, stride, 16); +} + +void ff_avg_h264_qpel16_mc12_lsx(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_lsx(halfHV, src, 16, stride); + put_h264_qpel16_v_lowpass_lsx(halfH, src, 16, stride); + avg_pixels16_l2_8_lsx(dst, halfH, halfHV, stride, 16); +} + +static void avg_h264_qpel16_hv_lowpass_lsx(uint8_t *dst, const uint8_t *src, + ptrdiff_t dstStride, ptrdiff_t srcStride) +{ + avg_h264_qpel8_hv_lowpass_lsx(dst, src, dstStride, srcStride); + avg_h264_qpel8_hv_lowpass_lsx(dst + 8, src + 8, dstStride, srcStride); + src += srcStride << 3; + dst += dstStride << 3; + avg_h264_qpel8_hv_lowpass_lsx(dst, src, dstStride, srcStride); + avg_h264_qpel8_hv_lowpass_lsx(dst + 8, src + 8, dstStride, srcStride); +} + +void ff_avg_h264_qpel16_mc22_lsx(uint8_t *dst, const uint8_t *src, + ptrdiff_t stride) +{ + avg_h264_qpel16_hv_lowpass_lsx(dst, src, stride, stride); +} + +void ff_put_h264_qpel8_mc03_lsx(uint8_t *dst, const uint8_t *src, + ptrdiff_t stride) +{ + uint8_t half[64]; + + put_h264_qpel8_v_lowpass_lsx(half, (uint8_t*)src, 8, stride); + put_pixels8_l2_8_lsx(dst, src + stride, half, stride, stride); +} + +void ff_put_h264_qpel8_mc01_lsx(uint8_t *dst, const uint8_t *src, + ptrdiff_t stride) +{ + uint8_t half[64]; + + put_h264_qpel8_v_lowpass_lsx(half, (uint8_t*)src, 8, stride); + put_pixels8_l2_8_lsx(dst, src, half, stride, stride); +} + +void ff_put_h264_qpel8_mc30_lsx(uint8_t *dst, const uint8_t *src, + ptrdiff_t stride) +{ + uint8_t half[64]; + + put_h264_qpel8_h_lowpass_lsx(half, src, 8, stride); + put_pixels8_l2_8_lsx(dst, src+1, half, stride, stride); +} + +void ff_put_h264_qpel8_mc10_lsx(uint8_t *dst, const uint8_t *src, + ptrdiff_t stride) +{ + uint8_t half[64]; + + put_h264_qpel8_h_lowpass_lsx(half, src, 8, stride); + put_pixels8_l2_8_lsx(dst, src, half, stride, stride); +} + +void ff_put_h264_qpel8_mc33_lsx(uint8_t *dst, const uint8_t *src, + ptrdiff_t stride) +{ + uint8_t halfH[64]; + uint8_t halfV[64]; + + put_h264_qpel8_h_lowpass_lsx(halfH, src + stride, 8, stride); + put_h264_qpel8_v_lowpass_lsx(halfV, (uint8_t*)src + 1, 8, stride); + put_pixels8_l2_8_lsx(dst, halfH, halfV, stride, 8); +} + +void ff_put_h264_qpel8_mc13_lsx(uint8_t *dst, const uint8_t *src, + ptrdiff_t stride) +{ + uint8_t halfH[64]; + uint8_t halfV[64]; + + put_h264_qpel8_h_lowpass_lsx(halfH, src + stride, 8, stride); + put_h264_qpel8_v_lowpass_lsx(halfV, (uint8_t*)src, 8, stride); + put_pixels8_l2_8_lsx(dst, halfH, halfV, stride, 8); +} + +void ff_put_h264_qpel8_mc31_lsx(uint8_t *dst, const uint8_t *src, + ptrdiff_t stride) +{ + uint8_t halfH[64]; + uint8_t halfV[64]; + + put_h264_qpel8_h_lowpass_lsx(halfH, src, 8, stride); + put_h264_qpel8_v_lowpass_lsx(halfV, (uint8_t*)src + 1, 8, stride); + put_pixels8_l2_8_lsx(dst, halfH, halfV, stride, 8); +} + +void ff_put_h264_qpel8_mc11_lsx(uint8_t *dst, const uint8_t *src, + ptrdiff_t stride) +{ + uint8_t halfH[64]; + uint8_t halfV[64]; + + put_h264_qpel8_h_lowpass_lsx(halfH, src, 8, stride); + put_h264_qpel8_v_lowpass_lsx(halfV, (uint8_t*)src, 8, stride); + put_pixels8_l2_8_lsx(dst, halfH, halfV, stride, 8); +} + +void ff_put_h264_qpel8_mc32_lsx(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_lsx(halfHV, src, 8, stride); + put_h264_qpel8_v_lowpass_lsx(halfH, (uint8_t*)src + 1, 8, stride); + put_pixels8_l2_8_lsx(dst, halfH, halfHV, stride, 8); +} + +void ff_put_h264_qpel8_mc21_lsx(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_lsx(halfH, src, 8, stride); + put_h264_qpel8_hv_lowpass_lsx(halfHV, src, 8, stride); + put_pixels8_l2_8_lsx(dst, halfH, halfHV, stride, 8); +} + +void ff_put_h264_qpel8_mc23_lsx(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_lsx(halfH, src + stride, 8, stride); + put_h264_qpel8_hv_lowpass_lsx(halfHV, src, 8, stride); + put_pixels8_l2_8_lsx(dst, halfH, halfHV, stride, 8); +} + +void ff_put_h264_qpel8_mc12_lsx(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_lsx(halfHV, src, 8, stride); + put_h264_qpel8_v_lowpass_lsx(halfH, (uint8_t*)src, 8, stride); + put_pixels8_l2_8_lsx(dst, halfH, halfHV, stride, 8); +} + +void ff_put_h264_qpel8_mc02_lsx(uint8_t *dst, const uint8_t *src, + ptrdiff_t stride) +{ + put_h264_qpel8_v_lowpass_lsx(dst, (uint8_t*)src, stride, stride); +} + +void ff_put_h264_qpel8_mc22_lsx(uint8_t *dst, const uint8_t *src, + ptrdiff_t stride) +{ + put_h264_qpel8_hv_lowpass_lsx(dst, src, stride, stride); +} + +void ff_put_h264_qpel8_mc20_lsx(uint8_t *dst, const uint8_t *src, + ptrdiff_t stride) +{ + put_h264_qpel8_h_lowpass_lsx(dst, src, stride, stride); +} + +void ff_avg_h264_qpel8_mc10_lsx(uint8_t *dst, const uint8_t *src, + ptrdiff_t stride) +{ + uint8_t half[64]; + + put_h264_qpel8_h_lowpass_lsx(half, src, 8, stride); + avg_pixels8_l2_8_lsx(dst, src, half, stride, stride); +} + +void ff_avg_h264_qpel8_mc20_lsx(uint8_t *dst, const uint8_t *src, + ptrdiff_t stride) +{ + avg_h264_qpel8_h_lowpass_lsx(dst, src, stride, stride); +} + +void ff_avg_h264_qpel8_mc30_lsx(uint8_t *dst, const uint8_t *src, + ptrdiff_t stride) +{ + uint8_t half[64]; + + put_h264_qpel8_h_lowpass_lsx(half, src, 8, stride); + avg_pixels8_l2_8_lsx(dst, src+1, half, stride, stride); +} + +void ff_avg_h264_qpel8_mc11_lsx(uint8_t *dst, const uint8_t *src, + ptrdiff_t stride) +{ + uint8_t halfH[64]; + uint8_t halfV[64]; + + put_h264_qpel8_h_lowpass_lsx(halfH, src, 8, stride); + put_h264_qpel8_v_lowpass_lsx(halfV, (uint8_t*)src, 8, stride); + avg_pixels8_l2_8_lsx(dst, halfH, halfV, stride, 8); +} + +void ff_avg_h264_qpel8_mc21_lsx(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_lsx(halfH, src, 8, stride); + put_h264_qpel8_hv_lowpass_lsx(halfHV, src, 8, stride); + avg_pixels8_l2_8_lsx(dst, halfH, halfHV, stride, 8); +} + +void ff_avg_h264_qpel8_mc31_lsx(uint8_t *dst, const uint8_t *src, + ptrdiff_t stride) +{ + uint8_t halfH[64]; + uint8_t halfV[64]; + + put_h264_qpel8_h_lowpass_lsx(halfH, src, 8, stride); + put_h264_qpel8_v_lowpass_lsx(halfV, (uint8_t*)src + 1, 8, stride); + avg_pixels8_l2_8_lsx(dst, halfH, halfV, stride, 8); +} + +void ff_avg_h264_qpel8_mc02_lsx(uint8_t *dst, const uint8_t *src, + ptrdiff_t stride) +{ + avg_h264_qpel8_v_lowpass_lsx(dst, (uint8_t*)src, stride, stride); +} + +void ff_avg_h264_qpel8_mc12_lsx(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_lsx(halfHV, src, 8, stride); + put_h264_qpel8_v_lowpass_lsx(halfH, (uint8_t*)src, 8, stride); + avg_pixels8_l2_8_lsx(dst, halfH, halfHV, stride, 8); +} + +void ff_avg_h264_qpel8_mc22_lsx(uint8_t *dst, const uint8_t *src, + ptrdiff_t stride) +{ + avg_h264_qpel8_hv_lowpass_lsx(dst, src, stride, stride); +} + +void ff_avg_h264_qpel8_mc32_lsx(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_lsx(halfHV, src, 8, stride); + put_h264_qpel8_v_lowpass_lsx(halfH, (uint8_t*)src + 1, 8, stride); + avg_pixels8_l2_8_lsx(dst, halfH, halfHV, stride, 8); +} + +void ff_avg_h264_qpel8_mc13_lsx(uint8_t *dst, const uint8_t *src, + ptrdiff_t stride) +{ + uint8_t halfH[64]; + uint8_t halfV[64]; + + put_h264_qpel8_h_lowpass_lsx(halfH, src + stride, 8, stride); + put_h264_qpel8_v_lowpass_lsx(halfV, (uint8_t*)src, 8, stride); + avg_pixels8_l2_8_lsx(dst, halfH, halfV, stride, 8); +} + +void ff_avg_h264_qpel8_mc23_lsx(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_lsx(halfH, src + stride, 8, stride); + put_h264_qpel8_hv_lowpass_lsx(halfHV, src, 8, stride); + avg_pixels8_l2_8_lsx(dst, halfH, halfHV, stride, 8); +} + +void ff_avg_h264_qpel8_mc33_lsx(uint8_t *dst, const uint8_t *src, + ptrdiff_t stride) +{ + uint8_t halfH[64]; + uint8_t halfV[64]; + + put_h264_qpel8_h_lowpass_lsx(halfH, src + stride, 8, stride); + put_h264_qpel8_v_lowpass_lsx(halfV, (uint8_t*)src + 1, 8, stride); + avg_pixels8_l2_8_lsx(dst, halfH, halfV, stride, 8); +} From 4501b1dfd7b812fdd459634a3e2b974525107592 Mon Sep 17 00:00:00 2001 From: Lu Wang Date: Thu, 25 May 2023 15:24:30 +0800 Subject: [PATCH 1177/2172] swscale/la: Optimize the functions of the swscale series with lsx. ./configure --disable-lasx ffmpeg -i ~/media/1_h264_1080p_30fps_3Mbps.mp4 -f rawvideo -s 640x480 -pix_fmt bgra -y /dev/null -an before: 91fps after: 160fps Reviewed-by: Shiyou Yin Signed-off-by: Michael Niedermayer --- libswscale/loongarch/Makefile | 5 + libswscale/loongarch/input.S | 285 +++ libswscale/loongarch/output.S | 138 ++ libswscale/loongarch/output_lasx.c | 4 +- libswscale/loongarch/output_lsx.c | 1828 ++++++++++++++++ libswscale/loongarch/swscale.S | 1868 +++++++++++++++++ libswscale/loongarch/swscale_init_loongarch.c | 32 +- libswscale/loongarch/swscale_loongarch.h | 43 +- libswscale/loongarch/swscale_lsx.c | 57 + libswscale/utils.c | 3 +- 10 files changed, 4256 insertions(+), 7 deletions(-) create mode 100644 libswscale/loongarch/input.S create mode 100644 libswscale/loongarch/output.S create mode 100644 libswscale/loongarch/output_lsx.c create mode 100644 libswscale/loongarch/swscale.S create mode 100644 libswscale/loongarch/swscale_lsx.c diff --git a/libswscale/loongarch/Makefile b/libswscale/loongarch/Makefile index 8e665e826c2..c0b6a449c0e 100644 --- a/libswscale/loongarch/Makefile +++ b/libswscale/loongarch/Makefile @@ -4,3 +4,8 @@ LASX-OBJS-$(CONFIG_SWSCALE) += loongarch/swscale_lasx.o \ loongarch/yuv2rgb_lasx.o \ loongarch/rgb2rgb_lasx.o \ loongarch/output_lasx.o +LSX-OBJS-$(CONFIG_SWSCALE) += loongarch/swscale.o \ + loongarch/swscale_lsx.o \ + loongarch/input.o \ + loongarch/output.o \ + loongarch/output_lsx.o diff --git a/libswscale/loongarch/input.S b/libswscale/loongarch/input.S new file mode 100644 index 00000000000..d01f7384b18 --- /dev/null +++ b/libswscale/loongarch/input.S @@ -0,0 +1,285 @@ +/* + * Loongson LSX optimized swscale + * + * Copyright (c) 2023 Loongson Technology Corporation Limited + * Contributed by 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 + */ + +#include "libavcodec/loongarch/loongson_asm.S" + +/* void planar_rgb_to_y_lsx(uint8_t *_dst, const uint8_t *src[4], + * int width, int32_t *rgb2yuv) + */ +function planar_rgb_to_y_lsx + ld.d a5, a1, 0 + ld.d a6, a1, 8 + ld.d a7, a1, 16 + + ld.w t1, a3, 0 // ry + ld.w t2, a3, 4 // gy + ld.w t3, a3, 8 // by + li.w t4, 9 + li.w t5, 524544 + li.w t7, 4 + li.w t8, 8 + vldi vr7, 0 + vreplgr2vr.w vr1, t1 + vreplgr2vr.w vr2, t2 + vreplgr2vr.w vr3, t3 + vreplgr2vr.w vr4, t4 + vreplgr2vr.w vr5, t5 + bge a2, t8, .WIDTH8 + bge a2, t7, .WIDTH4 + blt zero, a2, .WIDTH + b .END + +.WIDTH8: + vld vr8, a5, 0 + vld vr9, a6, 0 + vld vr10, a7, 0 + vilvl.b vr11, vr7, vr8 + vilvl.b vr12, vr7, vr9 + vilvl.b vr13, vr7, vr10 + vilvl.h vr14, vr7, vr11 + vilvl.h vr15, vr7, vr12 + vilvl.h vr16, vr7, vr13 + vilvh.h vr17, vr7, vr11 + vilvh.h vr18, vr7, vr12 + vilvh.h vr19, vr7, vr13 + vmul.w vr20, vr1, vr16 + vmul.w vr21, vr1, vr19 + vmadd.w vr20, vr2, vr14 + vmadd.w vr20, vr3, vr15 + vmadd.w vr21, vr2, vr17 + vmadd.w vr21, vr3, vr18 + vadd.w vr20, vr20, vr5 + vadd.w vr21, vr21, vr5 + vsra.w vr20, vr20, vr4 + vsra.w vr21, vr21, vr4 + vpickev.h vr20, vr21, vr20 + vst vr20, a0, 0 + addi.d a2, a2, -8 + addi.d a5, a5, 8 + addi.d a6, a6, 8 + addi.d a7, a7, 8 + addi.d a0, a0, 16 + bge a2, t8, .WIDTH8 + bge a2, t7, .WIDTH4 + blt zero, a2, .WIDTH + b .END + +.WIDTH4: + vld vr8, a5, 0 + vld vr9, a6, 0 + vld vr10, a7, 0 + vilvl.b vr11, vr7, vr8 + vilvl.b vr12, vr7, vr9 + vilvl.b vr13, vr7, vr10 + vilvl.h vr14, vr7, vr11 + vilvl.h vr15, vr7, vr12 + vilvl.h vr16, vr7, vr13 + vmul.w vr17, vr1, vr16 + vmadd.w vr17, vr2, vr14 + vmadd.w vr17, vr3, vr15 + vadd.w vr17, vr17, vr5 + vsra.w vr17, vr17, vr4 + vpickev.h vr17, vr17, vr17 + vstelm.d vr17, a0, 0, 0 + addi.d a2, a2, -4 + addi.d a5, a5, 4 + addi.d a6, a6, 4 + addi.d a7, a7, 4 + addi.d a0, a0, 8 + bge a2, t7, .WIDTH4 + blt zero, a2, .WIDTH + b .END + +.WIDTH: + ld.bu t0, a5, 0 + ld.bu t4, a6, 0 + ld.bu t6, a7, 0 + mul.w t8, t6, t1 + mul.w t7, t0, t2 + add.w t8, t8, t7 + mul.w t7, t4, t3 + add.w t8, t8, t7 + add.w t8, t8, t5 + srai.w t8, t8, 9 + st.h t8, a0, 0 + addi.d a2, a2, -1 + addi.d a5, a5, 1 + addi.d a6, a6, 1 + addi.d a7, a7, 1 + addi.d a0, a0, 2 + blt zero, a2, .WIDTH +.END: +endfunc + +/* void planar_rgb_to_uv_lsx(uint8_t *_dstU, uint8_t *_dstV, const uint8_t *src[4], + * int width, int32_t *rgb2yuv) + */ +function planar_rgb_to_uv_lsx + addi.d sp, sp, -24 + st.d s1, sp, 0 + st.d s2, sp, 8 + st.d s3, sp, 16 + + ld.d a5, a2, 0 + ld.d a6, a2, 8 + ld.d a7, a2, 16 + ld.w t1, a4, 12 // ru + ld.w t2, a4, 16 // gu + ld.w t3, a4, 20 // bu + ld.w s1, a4, 24 // rv + ld.w s2, a4, 28 // gv + ld.w s3, a4, 32 // bv + li.w t4, 9 + li.w t5, 4194560 + li.w t7, 4 + li.w t8, 8 + vldi vr0, 0 + vreplgr2vr.w vr1, t1 + vreplgr2vr.w vr2, t2 + vreplgr2vr.w vr3, t3 + vreplgr2vr.w vr4, s1 + vreplgr2vr.w vr5, s2 + vreplgr2vr.w vr6, s3 + vreplgr2vr.w vr7, t4 + vreplgr2vr.w vr8, t5 + bge a2, t8, .LOOP_WIDTH8 + bge a2, t7, .LOOP_WIDTH4 + blt zero, a2, .LOOP_WIDTH + b .LOOP_END + +.LOOP_WIDTH8: + vld vr9, a5, 0 + vld vr10, a6, 0 + vld vr11, a7, 0 + vilvl.b vr9, vr0, vr9 + vilvl.b vr10, vr0, vr10 + vilvl.b vr11, vr0, vr11 + vilvl.h vr12, vr0, vr9 + vilvl.h vr13, vr0, vr10 + vilvl.h vr14, vr0, vr11 + vilvh.h vr15, vr0, vr9 + vilvh.h vr16, vr0, vr10 + vilvh.h vr17, vr0, vr11 + vmul.w vr18, vr1, vr14 + vmul.w vr19, vr1, vr17 + vmul.w vr20, vr4, vr14 + vmul.w vr21, vr4, vr17 + vmadd.w vr18, vr2, vr12 + vmadd.w vr18, vr3, vr13 + vmadd.w vr19, vr2, vr15 + vmadd.w vr19, vr3, vr16 + vmadd.w vr20, vr5, vr12 + vmadd.w vr20, vr6, vr13 + vmadd.w vr21, vr5, vr15 + vmadd.w vr21, vr6, vr16 + vadd.w vr18, vr18, vr8 + vadd.w vr19, vr19, vr8 + vadd.w vr20, vr20, vr8 + vadd.w vr21, vr21, vr8 + vsra.w vr18, vr18, vr7 + vsra.w vr19, vr19, vr7 + vsra.w vr20, vr20, vr7 + vsra.w vr21, vr21, vr7 + vpickev.h vr18, vr19, vr18 + vpickev.h vr20, vr21, vr20 + vst vr18, a0, 0 + vst vr20, a1, 0 + addi.d a3, a3, -8 + addi.d a5, a5, 8 + addi.d a6, a6, 8 + addi.d a7, a7, 8 + addi.d a0, a0, 16 + addi.d a1, a1, 16 + bge a3, t8, .LOOP_WIDTH8 + bge a3, t7, .LOOP_WIDTH4 + blt zero, a3, .LOOP_WIDTH + b .LOOP_END + +.LOOP_WIDTH4: + vld vr9, a5, 0 + vld vr10, a6, 0 + vld vr11, a7, 0 + vilvl.b vr9, vr0, vr9 + vilvl.b vr10, vr0, vr10 + vilvl.b vr11, vr0, vr11 + vilvl.h vr12, vr0, vr9 + vilvl.h vr13, vr0, vr10 + vilvl.h vr14, vr0, vr11 + vmul.w vr18, vr1, vr14 + vmul.w vr19, vr4, vr14 + vmadd.w vr18, vr2, vr12 + vmadd.w vr18, vr3, vr13 + vmadd.w vr19, vr5, vr12 + vmadd.w vr19, vr6, vr13 + vadd.w vr18, vr18, vr8 + vadd.w vr19, vr19, vr8 + vsra.w vr18, vr18, vr7 + vsra.w vr19, vr19, vr7 + vpickev.h vr18, vr18, vr18 + vpickev.h vr19, vr19, vr19 + vstelm.d vr18, a0, 0, 0 + vstelm.d vr19, a1, 0, 0 + addi.d a3, a3, -4 + addi.d a5, a5, 4 + addi.d a6, a6, 4 + addi.d a7, a7, 4 + addi.d a0, a0, 8 + addi.d a1, a1, 8 + bge a3, t7, .LOOP_WIDTH4 + blt zero, a3, .LOOP_WIDTH + b .LOOP_END + +.LOOP_WIDTH: + ld.bu t0, a5, 0 + ld.bu t4, a6, 0 + ld.bu t6, a7, 0 + mul.w t8, t6, t1 + mul.w t7, t0, t2 + add.w t8, t8, t7 + mul.w t7, t4, t3 + add.w t8, t8, t7 + add.w t8, t8, t5 + srai.w t8, t8, 9 + st.h t8, a0, 0 + mul.w t8, t6, s1 + mul.w t7, t0, s2 + add.w t8, t8, t7 + mul.w t7, t4, s3 + add.w t8, t8, t7 + add.w t8, t8, t5 + srai.w t8, t8, 9 + st.h t8, a1, 0 + addi.d a3, a3, -1 + addi.d a5, a5, 1 + addi.d a6, a6, 1 + addi.d a7, a7, 1 + addi.d a0, a0, 2 + addi.d a1, a1, 2 + blt zero, a3, .LOOP_WIDTH + +.LOOP_END: + ld.d s1, sp, 0 + ld.d s2, sp, 8 + ld.d s3, sp, 16 + addi.d sp, sp, 24 +endfunc diff --git a/libswscale/loongarch/output.S b/libswscale/loongarch/output.S new file mode 100644 index 00000000000..b44bac502ad --- /dev/null +++ b/libswscale/loongarch/output.S @@ -0,0 +1,138 @@ +/* + * Loongson LSX optimized swscale + * + * Copyright (c) 2023 Loongson Technology Corporation Limited + * Contributed by 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 + */ + +#include "libavcodec/loongarch/loongson_asm.S" + +/* static void ff_yuv2planeX_8_lsx(const int16_t *filter, int filterSize, + * const int16_t **src, uint8_t *dest, int dstW, + * const uint8_t *dither, int offset) + */ +function ff_yuv2planeX_8_lsx + addi.w t1, a6, 1 + addi.w t2, a6, 2 + addi.w t3, a6, 3 + addi.w t4, a6, 4 + addi.w t5, a6, 5 + addi.w t6, a6, 6 + addi.w t7, a6, 7 + andi t0, a6, 7 + andi t1, t1, 7 + andi t2, t2, 7 + andi t3, t3, 7 + andi t4, t4, 7 + andi t5, t5, 7 + andi t6, t6, 7 + andi t7, t7, 7 + ldx.bu t0, a5, t0 + ldx.bu t1, a5, t1 + ldx.bu t2, a5, t2 + ldx.bu t3, a5, t3 + ldx.bu t4, a5, t4 + ldx.bu t5, a5, t5 + ldx.bu t6, a5, t6 + ldx.bu t7, a5, t7 + vreplgr2vr.w vr0, t0 + vreplgr2vr.w vr1, t1 + vreplgr2vr.w vr2, t2 + vreplgr2vr.w vr3, t3 + vreplgr2vr.w vr4, t4 + vreplgr2vr.w vr5, t5 + vreplgr2vr.w vr6, t6 + vreplgr2vr.w vr7, t7 + vilvl.w vr0, vr2, vr0 + vilvl.w vr4, vr6, vr4 + vilvl.w vr1, vr3, vr1 + vilvl.w vr5, vr7, vr5 + vilvl.d vr12, vr4, vr0 + vilvl.d vr13, vr5, vr1 + li.w t5, 0 + li.w t8, 8 + bge a4, t8, .WIDTH8 + blt zero, a4, .WIDTH + b .END + +.WIDTH8: + li.d t1, 0 + li.d t4, 0 + vslli.w vr2, vr12, 12 + vslli.w vr3, vr13, 12 + move t3, a0 + +.FILTERSIZE8: + ldx.d t2, a2, t1 + vldx vr4, t2, t5 + vldrepl.h vr5, t3, 0 + vmaddwev.w.h vr2, vr4, vr5 + vmaddwod.w.h vr3, vr4, vr5 + addi.d t1, t1, 8 + addi.d t3, t3, 2 + addi.d t4, t4, 1 + blt t4, a1, .FILTERSIZE8 + vsrai.w vr2, vr2, 19 + vsrai.w vr3, vr3, 19 + vclip255.w vr2, vr2 + vclip255.w vr3, vr3 + vpickev.h vr2, vr3, vr2 + vpickev.b vr2, vr2, vr2 + vbsrl.v vr3, vr2, 4 + vilvl.b vr2, vr3, vr2 + fst.d f2, a3, 0 + addi.d t5, t5, 16 + addi.d a4, a4, -8 + addi.d a3, a3, 8 + bge a4, t8, .WIDTH8 + blt zero, a4, .WIDTH + b .END + +.WIDTH: + li.d t1, 0 + li.d t4, 0 + vslli.w vr2, vr12, 12 + vslli.w vr3, vr13, 12 +.FILTERSIZE: + ldx.d t2, a2, t1 + vldx vr4, t2, t5 + vldrepl.h vr5, a0, 0 + vmaddwev.w.h vr2, vr4, vr5 + vmaddwod.w.h vr3, vr4, vr5 + addi.d t1, t1, 8 + addi.d a0, a0, 2 + addi.d t4, t4, 1 + blt t4, a1, .FILTERSIZE + vsrai.w vr2, vr2, 19 + vsrai.w vr3, vr3, 19 + vclip255.w vr2, vr2 + vclip255.w vr3, vr3 + vpickev.h vr2, vr3, vr2 + vpickev.b vr2, vr2, vr2 + vbsrl.v vr3, vr2, 4 + vilvl.b vr2, vr3, vr2 + +.DEST: + vstelm.b vr2, a3, 0, 0 + vbsrl.v vr2, vr2, 1 + addi.d a4, a4, -1 + addi.d a3, a3, 1 + blt zero, a4, .DEST +.END: +endfunc diff --git a/libswscale/loongarch/output_lasx.c b/libswscale/loongarch/output_lasx.c index 36a4c4503bb..277d7063e61 100644 --- a/libswscale/loongarch/output_lasx.c +++ b/libswscale/loongarch/output_lasx.c @@ -1773,11 +1773,9 @@ YUV2RGBWRAPPER(yuv2, rgb_full, bgr4_byte_full, AV_PIX_FMT_BGR4_BYTE, 0) YUV2RGBWRAPPER(yuv2, rgb_full, rgb4_byte_full, AV_PIX_FMT_RGB4_BYTE, 0) YUV2RGBWRAPPER(yuv2, rgb_full, bgr8_full, AV_PIX_FMT_BGR8, 0) YUV2RGBWRAPPER(yuv2, rgb_full, rgb8_full, AV_PIX_FMT_RGB8, 0) -#undef yuvTorgb -#undef yuvTorgb_setup -av_cold void ff_sws_init_output_loongarch(SwsContext *c) +av_cold void ff_sws_init_output_lasx(SwsContext *c) { if(c->flags & SWS_FULL_CHR_H_INT) { diff --git a/libswscale/loongarch/output_lsx.c b/libswscale/loongarch/output_lsx.c new file mode 100644 index 00000000000..768cc3abc6c --- /dev/null +++ b/libswscale/loongarch/output_lsx.c @@ -0,0 +1,1828 @@ +/* + * Copyright (C) 2023 Loongson Technology Corporation Limited + * Contributed by 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 + */ + +#include "swscale_loongarch.h" +#include "libavutil/loongarch/loongson_intrinsics.h" + + +/*Copy from libswscale/output.c*/ +static av_always_inline void +yuv2rgb_write(uint8_t *_dest, int i, int Y1, int Y2, + unsigned A1, unsigned A2, + const void *_r, const void *_g, const void *_b, int y, + enum AVPixelFormat target, int hasAlpha) +{ + if (target == AV_PIX_FMT_ARGB || target == AV_PIX_FMT_RGBA || + target == AV_PIX_FMT_ABGR || target == AV_PIX_FMT_BGRA) { + uint32_t *dest = (uint32_t *) _dest; + const uint32_t *r = (const uint32_t *) _r; + const uint32_t *g = (const uint32_t *) _g; + const uint32_t *b = (const uint32_t *) _b; + +#if CONFIG_SMALL + dest[i * 2 + 0] = r[Y1] + g[Y1] + b[Y1]; + dest[i * 2 + 1] = r[Y2] + g[Y2] + b[Y2]; +#else +#if defined(ASSERT_LEVEL) && ASSERT_LEVEL > 1 + int sh = (target == AV_PIX_FMT_RGB32_1 || + target == AV_PIX_FMT_BGR32_1) ? 0 : 24; + av_assert2((((r[Y1] + g[Y1] + b[Y1]) >> sh) & 0xFF) == 0xFF); +#endif + dest[i * 2 + 0] = r[Y1] + g[Y1] + b[Y1]; + dest[i * 2 + 1] = r[Y2] + g[Y2] + b[Y2]; +#endif + } else if (target == AV_PIX_FMT_RGB24 || target == AV_PIX_FMT_BGR24) { + uint8_t *dest = (uint8_t *) _dest; + const uint8_t *r = (const uint8_t *) _r; + const uint8_t *g = (const uint8_t *) _g; + const uint8_t *b = (const uint8_t *) _b; + +#define r_b ((target == AV_PIX_FMT_RGB24) ? r : b) +#define b_r ((target == AV_PIX_FMT_RGB24) ? b : r) + + dest[i * 6 + 0] = r_b[Y1]; + dest[i * 6 + 1] = g[Y1]; + dest[i * 6 + 2] = b_r[Y1]; + dest[i * 6 + 3] = r_b[Y2]; + dest[i * 6 + 4] = g[Y2]; + dest[i * 6 + 5] = b_r[Y2]; +#undef r_b +#undef b_r + } else if (target == AV_PIX_FMT_RGB565 || target == AV_PIX_FMT_BGR565 || + target == AV_PIX_FMT_RGB555 || target == AV_PIX_FMT_BGR555 || + target == AV_PIX_FMT_RGB444 || target == AV_PIX_FMT_BGR444) { + uint16_t *dest = (uint16_t *) _dest; + const uint16_t *r = (const uint16_t *) _r; + const uint16_t *g = (const uint16_t *) _g; + const uint16_t *b = (const uint16_t *) _b; + int dr1, dg1, db1, dr2, dg2, db2; + + if (target == AV_PIX_FMT_RGB565 || target == AV_PIX_FMT_BGR565) { + dr1 = ff_dither_2x2_8[ y & 1 ][0]; + dg1 = ff_dither_2x2_4[ y & 1 ][0]; + db1 = ff_dither_2x2_8[(y & 1) ^ 1][0]; + dr2 = ff_dither_2x2_8[ y & 1 ][1]; + dg2 = ff_dither_2x2_4[ y & 1 ][1]; + db2 = ff_dither_2x2_8[(y & 1) ^ 1][1]; + } else if (target == AV_PIX_FMT_RGB555 || target == AV_PIX_FMT_BGR555) { + dr1 = ff_dither_2x2_8[ y & 1 ][0]; + dg1 = ff_dither_2x2_8[ y & 1 ][1]; + db1 = ff_dither_2x2_8[(y & 1) ^ 1][0]; + dr2 = ff_dither_2x2_8[ y & 1 ][1]; + dg2 = ff_dither_2x2_8[ y & 1 ][0]; + db2 = ff_dither_2x2_8[(y & 1) ^ 1][1]; + } else { + dr1 = ff_dither_4x4_16[ y & 3 ][0]; + dg1 = ff_dither_4x4_16[ y & 3 ][1]; + db1 = ff_dither_4x4_16[(y & 3) ^ 3][0]; + dr2 = ff_dither_4x4_16[ y & 3 ][1]; + dg2 = ff_dither_4x4_16[ y & 3 ][0]; + db2 = ff_dither_4x4_16[(y & 3) ^ 3][1]; + } + + dest[i * 2 + 0] = r[Y1 + dr1] + g[Y1 + dg1] + b[Y1 + db1]; + dest[i * 2 + 1] = r[Y2 + dr2] + g[Y2 + dg2] + b[Y2 + db2]; + } else { /* 8/4 bits */ + uint8_t *dest = (uint8_t *) _dest; + const uint8_t *r = (const uint8_t *) _r; + const uint8_t *g = (const uint8_t *) _g; + const uint8_t *b = (const uint8_t *) _b; + int dr1, dg1, db1, dr2, dg2, db2; + + if (target == AV_PIX_FMT_RGB8 || target == AV_PIX_FMT_BGR8) { + const uint8_t * const d64 = ff_dither_8x8_73[y & 7]; + const uint8_t * const d32 = ff_dither_8x8_32[y & 7]; + dr1 = dg1 = d32[(i * 2 + 0) & 7]; + db1 = d64[(i * 2 + 0) & 7]; + dr2 = dg2 = d32[(i * 2 + 1) & 7]; + db2 = d64[(i * 2 + 1) & 7]; + } else { + const uint8_t * const d64 = ff_dither_8x8_73 [y & 7]; + const uint8_t * const d128 = ff_dither_8x8_220[y & 7]; + dr1 = db1 = d128[(i * 2 + 0) & 7]; + dg1 = d64[(i * 2 + 0) & 7]; + dr2 = db2 = d128[(i * 2 + 1) & 7]; + dg2 = d64[(i * 2 + 1) & 7]; + } + + if (target == AV_PIX_FMT_RGB4 || target == AV_PIX_FMT_BGR4) { + dest[i] = r[Y1 + dr1] + g[Y1 + dg1] + b[Y1 + db1] + + ((r[Y2 + dr2] + g[Y2 + dg2] + b[Y2 + db2]) << 4); + } else { + dest[i * 2 + 0] = r[Y1 + dr1] + g[Y1 + dg1] + b[Y1 + db1]; + dest[i * 2 + 1] = r[Y2 + dr2] + g[Y2 + dg2] + b[Y2 + db2]; + } + } +} + +#define WRITE_YUV2RGB_LSX(vec_y1, vec_y2, vec_u, vec_v, t1, t2, t3, t4) \ +{ \ + Y1 = __lsx_vpickve2gr_w(vec_y1, t1); \ + Y2 = __lsx_vpickve2gr_w(vec_y2, t2); \ + U = __lsx_vpickve2gr_w(vec_u, t3); \ + V = __lsx_vpickve2gr_w(vec_v, t4); \ + r = c->table_rV[V]; \ + g = (c->table_gU[U] + c->table_gV[V]); \ + b = c->table_bU[U]; \ + yuv2rgb_write(dest, count, Y1, Y2, 0, 0, \ + r, g, b, y, target, 0); \ + count++; \ +} + +static void +yuv2rgb_X_template_lsx(SwsContext *c, const int16_t *lumFilter, + const int16_t **lumSrc, int lumFilterSize, + const int16_t *chrFilter, const int16_t **chrUSrc, + const int16_t **chrVSrc, int chrFilterSize, + const int16_t **alpSrc, uint8_t *dest, int dstW, + int y, enum AVPixelFormat target, int hasAlpha) +{ + int i, j; + int count = 0; + int t = 1 << 18; + int len = dstW >> 5; + int res = dstW & 31; + int len_count = (dstW + 1) >> 1; + const void *r, *g, *b; + int head = YUVRGB_TABLE_HEADROOM; + __m128i headroom = __lsx_vreplgr2vr_w(head); + + for (i = 0; i < len; i++) { + int Y1, Y2, U, V, count_lum = count << 1; + __m128i l_src1, l_src2, l_src3, l_src4, u_src1, u_src2, v_src1, v_src2; + __m128i yl_ev, yl_ev1, yl_ev2, yl_od1, yl_od2, yh_ev1, yh_ev2, yh_od1, yh_od2; + __m128i u_ev1, u_ev2, u_od1, u_od2, v_ev1, v_ev2, v_od1, v_od2, temp; + + yl_ev = __lsx_vldrepl_w(&t, 0); + yl_ev1 = yl_ev; + yl_od1 = yl_ev; + yh_ev1 = yl_ev; + yh_od1 = yl_ev; + u_ev1 = yl_ev; + v_ev1 = yl_ev; + u_od1 = yl_ev; + v_od1 = yl_ev; + yl_ev2 = yl_ev; + yl_od2 = yl_ev; + yh_ev2 = yl_ev; + yh_od2 = yl_ev; + u_ev2 = yl_ev; + v_ev2 = yl_ev; + u_od2 = yl_ev; + v_od2 = yl_ev; + + for (j = 0; j < lumFilterSize; j++) { + temp = __lsx_vldrepl_h((lumFilter + j), 0); + DUP2_ARG2(__lsx_vld, lumSrc[j] + count_lum, 0, lumSrc[j] + count_lum, + 16, l_src1, l_src2); + DUP2_ARG2(__lsx_vld, lumSrc[j] + count_lum, 32, lumSrc[j] + count_lum, + 48, l_src3, l_src4); + yl_ev1 = __lsx_vmaddwev_w_h(yl_ev1, temp, l_src1); + yl_od1 = __lsx_vmaddwod_w_h(yl_od1, temp, l_src1); + yh_ev1 = __lsx_vmaddwev_w_h(yh_ev1, temp, l_src3); + yh_od1 = __lsx_vmaddwod_w_h(yh_od1, temp, l_src3); + yl_ev2 = __lsx_vmaddwev_w_h(yl_ev2, temp, l_src2); + yl_od2 = __lsx_vmaddwod_w_h(yl_od2, temp, l_src2); + yh_ev2 = __lsx_vmaddwev_w_h(yh_ev2, temp, l_src4); + yh_od2 = __lsx_vmaddwod_w_h(yh_od2, temp, l_src4); + } + for (j = 0; j < chrFilterSize; j++) { + DUP2_ARG2(__lsx_vld, chrUSrc[j] + count, 0, chrVSrc[j] + count, 0, + u_src1, v_src1); + DUP2_ARG2(__lsx_vld, chrUSrc[j] + count, 16, chrVSrc[j] + count, 16, + u_src2, v_src2); + temp = __lsx_vldrepl_h((chrFilter + j), 0); + u_ev1 = __lsx_vmaddwev_w_h(u_ev1, temp, u_src1); + u_od1 = __lsx_vmaddwod_w_h(u_od1, temp, u_src1); + v_ev1 = __lsx_vmaddwev_w_h(v_ev1, temp, v_src1); + v_od1 = __lsx_vmaddwod_w_h(v_od1, temp, v_src1); + u_ev2 = __lsx_vmaddwev_w_h(u_ev2, temp, u_src2); + u_od2 = __lsx_vmaddwod_w_h(u_od2, temp, u_src2); + v_ev2 = __lsx_vmaddwev_w_h(v_ev2, temp, v_src2); + v_od2 = __lsx_vmaddwod_w_h(v_od2, temp, v_src2); + } + yl_ev1 = __lsx_vsrai_w(yl_ev1, 19); + yh_ev1 = __lsx_vsrai_w(yh_ev1, 19); + yl_od1 = __lsx_vsrai_w(yl_od1, 19); + yh_od1 = __lsx_vsrai_w(yh_od1, 19); + u_ev1 = __lsx_vsrai_w(u_ev1, 19); + v_ev1 = __lsx_vsrai_w(v_ev1, 19); + u_od1 = __lsx_vsrai_w(u_od1, 19); + v_od1 = __lsx_vsrai_w(v_od1, 19); + yl_ev2 = __lsx_vsrai_w(yl_ev2, 19); + yh_ev2 = __lsx_vsrai_w(yh_ev2, 19); + yl_od2 = __lsx_vsrai_w(yl_od2, 19); + yh_od2 = __lsx_vsrai_w(yh_od2, 19); + u_ev2 = __lsx_vsrai_w(u_ev2, 19); + v_ev2 = __lsx_vsrai_w(v_ev2, 19); + u_od2 = __lsx_vsrai_w(u_od2, 19); + v_od2 = __lsx_vsrai_w(v_od2, 19); + u_ev1 = __lsx_vadd_w(u_ev1, headroom); + v_ev1 = __lsx_vadd_w(v_ev1, headroom); + u_od1 = __lsx_vadd_w(u_od1, headroom); + v_od1 = __lsx_vadd_w(v_od1, headroom); + u_ev2 = __lsx_vadd_w(u_ev2, headroom); + v_ev2 = __lsx_vadd_w(v_ev2, headroom); + u_od2 = __lsx_vadd_w(u_od2, headroom); + v_od2 = __lsx_vadd_w(v_od2, headroom); + + WRITE_YUV2RGB_LSX(yl_ev1, yl_od1, u_ev1, v_ev1, 0, 0, 0, 0); + WRITE_YUV2RGB_LSX(yl_ev1, yl_od1, u_od1, v_od1, 1, 1, 0, 0); + WRITE_YUV2RGB_LSX(yl_ev1, yl_od1, u_ev1, v_ev1, 2, 2, 1, 1); + WRITE_YUV2RGB_LSX(yl_ev1, yl_od1, u_od1, v_od1, 3, 3, 1, 1); + WRITE_YUV2RGB_LSX(yl_ev2, yl_od2, u_ev1, v_ev1, 0, 0, 2, 2); + WRITE_YUV2RGB_LSX(yl_ev2, yl_od2, u_od1, v_od1, 1, 1, 2, 2); + WRITE_YUV2RGB_LSX(yl_ev2, yl_od2, u_ev1, v_ev1, 2, 2, 3, 3); + WRITE_YUV2RGB_LSX(yl_ev2, yl_od2, u_od1, v_od1, 3, 3, 3, 3); + WRITE_YUV2RGB_LSX(yh_ev1, yh_od1, u_ev2, v_ev2, 0, 0, 0, 0); + WRITE_YUV2RGB_LSX(yh_ev1, yh_od1, u_od2, v_od2, 1, 1, 0, 0); + WRITE_YUV2RGB_LSX(yh_ev1, yh_od1, u_ev2, v_ev2, 2, 2, 1, 1); + WRITE_YUV2RGB_LSX(yh_ev1, yh_od1, u_od2, v_od2, 3, 3, 1, 1); + WRITE_YUV2RGB_LSX(yh_ev2, yh_od2, u_ev2, v_ev2, 0, 0, 2, 2); + WRITE_YUV2RGB_LSX(yh_ev2, yh_od2, u_od2, v_od2, 1, 1, 2, 2); + WRITE_YUV2RGB_LSX(yh_ev2, yh_od2, u_ev2, v_ev2, 2, 2, 3, 3); + WRITE_YUV2RGB_LSX(yh_ev2, yh_od2, u_od2, v_od2, 3, 3, 3, 3); + } + + if (res >= 16) { + int Y1, Y2, U, V, count_lum = count << 1; + __m128i l_src1, l_src2, u_src1, v_src1; + __m128i yl_ev, yl_ev1, yl_ev2, yl_od1, yl_od2; + __m128i u_ev1, u_od1, v_ev1, v_od1, temp; + + yl_ev = __lsx_vldrepl_w(&t, 0); + yl_ev1 = yl_ev; + yl_od1 = yl_ev; + u_ev1 = yl_ev; + v_ev1 = yl_ev; + u_od1 = yl_ev; + v_od1 = yl_ev; + yl_ev2 = yl_ev; + yl_od2 = yl_ev; + + for (j = 0; j < lumFilterSize; j++) { + temp = __lsx_vldrepl_h((lumFilter + j), 0); + DUP2_ARG2(__lsx_vld, lumSrc[j] + count_lum, 0, lumSrc[j] + count_lum, + 16, l_src1, l_src2); + yl_ev1 = __lsx_vmaddwev_w_h(yl_ev1, temp, l_src1); + yl_od1 = __lsx_vmaddwod_w_h(yl_od1, temp, l_src1); + yl_ev2 = __lsx_vmaddwev_w_h(yl_ev2, temp, l_src2); + yl_od2 = __lsx_vmaddwod_w_h(yl_od2, temp, l_src2); + } + for (j = 0; j < chrFilterSize; j++) { + DUP2_ARG2(__lsx_vld, chrUSrc[j] + count, 0, chrVSrc[j] + count, 0, + u_src1, v_src1); + temp = __lsx_vldrepl_h((chrFilter + j), 0); + u_ev1 = __lsx_vmaddwev_w_h(u_ev1, temp, u_src1); + u_od1 = __lsx_vmaddwod_w_h(u_od1, temp, u_src1); + v_ev1 = __lsx_vmaddwev_w_h(v_ev1, temp, v_src1); + v_od1 = __lsx_vmaddwod_w_h(v_od1, temp, v_src1); + } + yl_ev1 = __lsx_vsrai_w(yl_ev1, 19); + yl_od1 = __lsx_vsrai_w(yl_od1, 19); + u_ev1 = __lsx_vsrai_w(u_ev1, 19); + v_ev1 = __lsx_vsrai_w(v_ev1, 19); + u_od1 = __lsx_vsrai_w(u_od1, 19); + v_od1 = __lsx_vsrai_w(v_od1, 19); + yl_ev2 = __lsx_vsrai_w(yl_ev2, 19); + yl_od2 = __lsx_vsrai_w(yl_od2, 19); + u_ev1 = __lsx_vadd_w(u_ev1, headroom); + v_ev1 = __lsx_vadd_w(v_ev1, headroom); + u_od1 = __lsx_vadd_w(u_od1, headroom); + v_od1 = __lsx_vadd_w(v_od1, headroom); + + WRITE_YUV2RGB_LSX(yl_ev1, yl_od1, u_ev1, v_ev1, 0, 0, 0, 0); + WRITE_YUV2RGB_LSX(yl_ev1, yl_od1, u_od1, v_od1, 1, 1, 0, 0); + WRITE_YUV2RGB_LSX(yl_ev1, yl_od1, u_ev1, v_ev1, 2, 2, 1, 1); + WRITE_YUV2RGB_LSX(yl_ev1, yl_od1, u_od1, v_od1, 3, 3, 1, 1); + WRITE_YUV2RGB_LSX(yl_ev2, yl_od2, u_ev1, v_ev1, 0, 0, 2, 2); + WRITE_YUV2RGB_LSX(yl_ev2, yl_od2, u_od1, v_od1, 1, 1, 2, 2); + WRITE_YUV2RGB_LSX(yl_ev2, yl_od2, u_ev1, v_ev1, 2, 2, 3, 3); + WRITE_YUV2RGB_LSX(yl_ev2, yl_od2, u_od1, v_od1, 3, 3, 3, 3); + res -= 16; + } + + if (res >= 8) { + int Y1, Y2, U, V, count_lum = count << 1; + __m128i l_src1, u_src, v_src; + __m128i yl_ev, yl_od; + __m128i u_ev, u_od, v_ev, v_od, temp; + + yl_ev = __lsx_vldrepl_w(&t, 0); + yl_od = yl_ev; + u_ev = yl_ev; + v_ev = yl_ev; + u_od = yl_ev; + v_od = yl_ev; + for (j = 0; j < lumFilterSize; j++) { + temp = __lsx_vldrepl_h((lumFilter + j), 0); + l_src1 = __lsx_vld(lumSrc[j] + count_lum, 0); + yl_ev = __lsx_vmaddwev_w_h(yl_ev, temp, l_src1); + yl_od = __lsx_vmaddwod_w_h(yl_od, temp, l_src1); + } + for (j = 0; j < chrFilterSize; j++) { + DUP2_ARG2(__lsx_vld, chrUSrc[j] + count, 0, chrVSrc[j] + count, 0, + u_src, v_src); + temp = __lsx_vldrepl_h((chrFilter + j), 0); + u_ev = __lsx_vmaddwev_w_h(u_ev, temp, u_src); + u_od = __lsx_vmaddwod_w_h(u_od, temp, u_src); + v_ev = __lsx_vmaddwev_w_h(v_ev, temp, v_src); + v_od = __lsx_vmaddwod_w_h(v_od, temp, v_src); + } + yl_ev = __lsx_vsrai_w(yl_ev, 19); + yl_od = __lsx_vsrai_w(yl_od, 19); + u_ev = __lsx_vsrai_w(u_ev, 19); + v_ev = __lsx_vsrai_w(v_ev, 19); + u_od = __lsx_vsrai_w(u_od, 19); + v_od = __lsx_vsrai_w(v_od, 19); + u_ev = __lsx_vadd_w(u_ev, headroom); + v_ev = __lsx_vadd_w(v_ev, headroom); + u_od = __lsx_vadd_w(u_od, headroom); + v_od = __lsx_vadd_w(v_od, headroom); + WRITE_YUV2RGB_LSX(yl_ev, yl_od, u_ev, v_ev, 0, 0, 0, 0); + WRITE_YUV2RGB_LSX(yl_ev, yl_od, u_od, v_od, 1, 1, 0, 0); + WRITE_YUV2RGB_LSX(yl_ev, yl_od, u_ev, v_ev, 2, 2, 1, 1); + WRITE_YUV2RGB_LSX(yl_ev, yl_od, u_od, v_od, 3, 3, 1, 1); + res -= 8; + } + + if (res >= 4) { + int Y1, Y2, U, V, count_lum = count << 1; + __m128i l_src1, u_src, v_src; + __m128i yl_ev, yl_od; + __m128i u_ev, u_od, v_ev, v_od, temp; + + yl_ev = __lsx_vldrepl_w(&t, 0); + yl_od = yl_ev; + u_ev = yl_ev; + v_ev = yl_ev; + u_od = yl_ev; + v_od = yl_ev; + for (j = 0; j < lumFilterSize; j++) { + temp = __lsx_vldrepl_h((lumFilter + j), 0); + l_src1 = __lsx_vld(lumSrc[j] + count_lum, 0); + yl_ev = __lsx_vmaddwev_w_h(yl_ev, temp, l_src1); + yl_od = __lsx_vmaddwod_w_h(yl_od, temp, l_src1); + } + for (j = 0; j < chrFilterSize; j++) { + DUP2_ARG2(__lsx_vld, chrUSrc[j] + count, 0, chrVSrc[j] + count, 0, + u_src, v_src); + temp = __lsx_vldrepl_h((chrFilter + j), 0); + u_ev = __lsx_vmaddwev_w_h(u_ev, temp, u_src); + u_od = __lsx_vmaddwod_w_h(u_od, temp, u_src); + v_ev = __lsx_vmaddwev_w_h(v_ev, temp, v_src); + v_od = __lsx_vmaddwod_w_h(v_od, temp, v_src); + } + yl_ev = __lsx_vsrai_w(yl_ev, 19); + yl_od = __lsx_vsrai_w(yl_od, 19); + u_ev = __lsx_vsrai_w(u_ev, 19); + v_ev = __lsx_vsrai_w(v_ev, 19); + u_od = __lsx_vsrai_w(u_od, 19); + v_od = __lsx_vsrai_w(v_od, 19); + u_ev = __lsx_vadd_w(u_ev, headroom); + v_ev = __lsx_vadd_w(v_ev, headroom); + u_od = __lsx_vadd_w(u_od, headroom); + v_od = __lsx_vadd_w(v_od, headroom); + WRITE_YUV2RGB_LSX(yl_ev, yl_od, u_ev, v_ev, 0, 0, 0, 0); + WRITE_YUV2RGB_LSX(yl_ev, yl_od, u_od, v_od, 1, 1, 0, 0); + res -= 4; + } + + if (res >= 2) { + int Y1, Y2, U, V, count_lum = count << 1; + __m128i l_src1, u_src, v_src; + __m128i yl_ev, yl_od; + __m128i u_ev, u_od, v_ev, v_od, temp; + + yl_ev = __lsx_vldrepl_w(&t, 0); + yl_od = yl_ev; + u_ev = yl_ev; + v_ev = yl_ev; + u_od = yl_ev; + v_od = yl_ev; + for (j = 0; j < lumFilterSize; j++) { + temp = __lsx_vldrepl_h((lumFilter + j), 0); + l_src1 = __lsx_vld(lumSrc[j] + count_lum, 0); + yl_ev = __lsx_vmaddwev_w_h(yl_ev, temp, l_src1); + yl_od = __lsx_vmaddwod_w_h(yl_od, temp, l_src1); + } + for (j = 0; j < chrFilterSize; j++) { + DUP2_ARG2(__lsx_vld, chrUSrc[j] + count, 0, chrVSrc[j] + count, 0, + u_src, v_src); + temp = __lsx_vldrepl_h((chrFilter + j), 0); + u_ev = __lsx_vmaddwev_w_h(u_ev, temp, u_src); + u_od = __lsx_vmaddwod_w_h(u_od, temp, u_src); + v_ev = __lsx_vmaddwev_w_h(v_ev, temp, v_src); + v_od = __lsx_vmaddwod_w_h(v_od, temp, v_src); + } + yl_ev = __lsx_vsrai_w(yl_ev, 19); + yl_od = __lsx_vsrai_w(yl_od, 19); + u_ev = __lsx_vsrai_w(u_ev, 19); + v_ev = __lsx_vsrai_w(v_ev, 19); + u_od = __lsx_vsrai_w(u_od, 19); + v_od = __lsx_vsrai_w(v_od, 19); + u_ev = __lsx_vadd_w(u_ev, headroom); + v_ev = __lsx_vadd_w(v_ev, headroom); + u_od = __lsx_vadd_w(u_od, headroom); + v_od = __lsx_vadd_w(v_od, headroom); + WRITE_YUV2RGB_LSX(yl_ev, yl_od, u_ev, v_ev, 0, 0, 0, 0); + res -= 2; + } + + for (; count < len_count; count++) { + int Y1 = 1 << 18; + int Y2 = Y1; + int U = Y1; + int V = Y1; + + for (j = 0; j < lumFilterSize; j++) { + Y1 += lumSrc[j][count * 2] * lumFilter[j]; + Y2 += lumSrc[j][count * 2 + 1] * lumFilter[j]; + } + for (j = 0; j < chrFilterSize; j++) { + U += chrUSrc[j][count] * chrFilter[j]; + V += chrVSrc[j][count] * chrFilter[j]; + } + Y1 >>= 19; + Y2 >>= 19; + U >>= 19; + V >>= 19; + r = c->table_rV[V + YUVRGB_TABLE_HEADROOM]; + g = (c->table_gU[U + YUVRGB_TABLE_HEADROOM] + + c->table_gV[V + YUVRGB_TABLE_HEADROOM]); + b = c->table_bU[U + YUVRGB_TABLE_HEADROOM]; + + yuv2rgb_write(dest, count, Y1, Y2, 0, 0, + r, g, b, y, target, 0); + } +} + +static void +yuv2rgb_2_template_lsx(SwsContext *c, const int16_t *buf[2], + const int16_t *ubuf[2], const int16_t *vbuf[2], + const int16_t *abuf[2], uint8_t *dest, int dstW, + int yalpha, int uvalpha, int y, + enum AVPixelFormat target, int hasAlpha) +{ + const int16_t *buf0 = buf[0], *buf1 = buf[1], + *ubuf0 = ubuf[0], *ubuf1 = ubuf[1], + *vbuf0 = vbuf[0], *vbuf1 = vbuf[1]; + int yalpha1 = 4096 - yalpha; + int uvalpha1 = 4096 - uvalpha; + int i, count = 0; + int len = dstW - 7; + int len_count = (dstW + 1) >> 1; + const void *r, *g, *b; + int head = YUVRGB_TABLE_HEADROOM; + __m128i v_yalpha1 = __lsx_vreplgr2vr_w(yalpha1); + __m128i v_uvalpha1 = __lsx_vreplgr2vr_w(uvalpha1); + __m128i v_yalpha = __lsx_vreplgr2vr_w(yalpha); + __m128i v_uvalpha = __lsx_vreplgr2vr_w(uvalpha); + __m128i headroom = __lsx_vreplgr2vr_w(head); + __m128i zero = __lsx_vldi(0); + + for (i = 0; i < len; i += 8) { + int Y1, Y2, U, V; + int i_dex = i << 1; + int c_dex = count << 1; + __m128i y0_h, y0_l, y0, u0, v0; + __m128i y1_h, y1_l, y1, u1, v1; + __m128i y_l, y_h, u, v; + + DUP4_ARG2(__lsx_vldx, buf0, i_dex, ubuf0, c_dex, vbuf0, c_dex, + buf1, i_dex, y0, u0, v0, y1); + DUP2_ARG2(__lsx_vldx, ubuf1, c_dex, vbuf1, c_dex, u1, v1); + DUP2_ARG2(__lsx_vsllwil_w_h, y0, 0, y1, 0, y0_l, y1_l); + DUP2_ARG1(__lsx_vexth_w_h, y0, y1, y0_h, y1_h); + DUP4_ARG2(__lsx_vilvl_h, zero, u0, zero, u1, zero, v0, zero, v1, + u0, u1, v0, v1); + y0_l = __lsx_vmul_w(y0_l, v_yalpha1); + y0_h = __lsx_vmul_w(y0_h, v_yalpha1); + u0 = __lsx_vmul_w(u0, v_uvalpha1); + v0 = __lsx_vmul_w(v0, v_uvalpha1); + y_l = __lsx_vmadd_w(y0_l, v_yalpha, y1_l); + y_h = __lsx_vmadd_w(y0_h, v_yalpha, y1_h); + u = __lsx_vmadd_w(u0, v_uvalpha, u1); + v = __lsx_vmadd_w(v0, v_uvalpha, v1); + y_l = __lsx_vsrai_w(y_l, 19); + y_h = __lsx_vsrai_w(y_h, 19); + u = __lsx_vsrai_w(u, 19); + v = __lsx_vsrai_w(v, 19); + u = __lsx_vadd_w(u, headroom); + v = __lsx_vadd_w(v, headroom); + WRITE_YUV2RGB_LSX(y_l, y_l, u, v, 0, 1, 0, 0); + WRITE_YUV2RGB_LSX(y_l, y_l, u, v, 2, 3, 1, 1); + WRITE_YUV2RGB_LSX(y_h, y_h, u, v, 0, 1, 2, 2); + WRITE_YUV2RGB_LSX(y_h, y_h, u, v, 2, 3, 3, 3); + } + if (dstW - i >= 4) { + int Y1, Y2, U, V; + int i_dex = i << 1; + __m128i y0_l, y0, u0, v0; + __m128i y1_l, y1, u1, v1; + __m128i y_l, u, v; + + y0 = __lsx_vldx(buf0, i_dex); + u0 = __lsx_vldrepl_d((ubuf0 + count), 0); + v0 = __lsx_vldrepl_d((vbuf0 + count), 0); + y1 = __lsx_vldx(buf1, i_dex); + u1 = __lsx_vldrepl_d((ubuf1 + count), 0); + v1 = __lsx_vldrepl_d((vbuf1 + count), 0); + DUP2_ARG2(__lsx_vilvl_h, zero, y0, zero, y1, y0_l, y1_l); + DUP4_ARG2(__lsx_vilvl_h, zero, u0, zero, u1, zero, v0, zero, v1, + u0, u1, v0, v1); + y0_l = __lsx_vmul_w(y0_l, v_yalpha1); + u0 = __lsx_vmul_w(u0, v_uvalpha1); + v0 = __lsx_vmul_w(v0, v_uvalpha1); + y_l = __lsx_vmadd_w(y0_l, v_yalpha, y1_l); + u = __lsx_vmadd_w(u0, v_uvalpha, u1); + v = __lsx_vmadd_w(v0, v_uvalpha, v1); + y_l = __lsx_vsrai_w(y_l, 19); + u = __lsx_vsrai_w(u, 19); + v = __lsx_vsrai_w(v, 19); + u = __lsx_vadd_w(u, headroom); + v = __lsx_vadd_w(v, headroom); + WRITE_YUV2RGB_LSX(y_l, y_l, u, v, 0, 1, 0, 0); + WRITE_YUV2RGB_LSX(y_l, y_l, u, v, 2, 3, 1, 1); + i += 4; + } + for (; count < len_count; count++) { + int Y1 = (buf0[count * 2] * yalpha1 + + buf1[count * 2] * yalpha) >> 19; + int Y2 = (buf0[count * 2 + 1] * yalpha1 + + buf1[count * 2 + 1] * yalpha) >> 19; + int U = (ubuf0[count] * uvalpha1 + ubuf1[count] * uvalpha) >> 19; + int V = (vbuf0[count] * uvalpha1 + vbuf1[count] * uvalpha) >> 19; + + r = c->table_rV[V + YUVRGB_TABLE_HEADROOM], + g = (c->table_gU[U + YUVRGB_TABLE_HEADROOM] + + c->table_gV[V + YUVRGB_TABLE_HEADROOM]), + b = c->table_bU[U + YUVRGB_TABLE_HEADROOM]; + + yuv2rgb_write(dest, count, Y1, Y2, 0, 0, + r, g, b, y, target, 0); + } +} + +static void +yuv2rgb_1_template_lsx(SwsContext *c, const int16_t *buf0, + const int16_t *ubuf[2], const int16_t *vbuf[2], + const int16_t *abuf0, uint8_t *dest, int dstW, + int uvalpha, int y, enum AVPixelFormat target, + int hasAlpha) +{ + const int16_t *ubuf0 = ubuf[0], *vbuf0 = vbuf[0]; + int i; + int len = (dstW - 7); + int len_count = (dstW + 1) >> 1; + const void *r, *g, *b; + + if (uvalpha < 2048) { + int count = 0; + int head = YUVRGB_TABLE_HEADROOM; + __m128i headroom = __lsx_vreplgr2vr_h(head); + + for (i = 0; i < len; i += 8) { + int Y1, Y2, U, V; + int i_dex = i << 1; + int c_dex = count << 1; + __m128i src_y, src_u, src_v; + __m128i u, v, uv, y_l, y_h; + + src_y = __lsx_vldx(buf0, i_dex); + DUP2_ARG2(__lsx_vldx, ubuf0, c_dex, vbuf0, c_dex, src_u, src_v); + src_y = __lsx_vsrari_h(src_y, 7); + src_u = __lsx_vsrari_h(src_u, 7); + src_v = __lsx_vsrari_h(src_v, 7); + y_l = __lsx_vsllwil_w_h(src_y, 0); + y_h = __lsx_vexth_w_h(src_y); + uv = __lsx_vilvl_h(src_v, src_u); + u = __lsx_vaddwev_w_h(uv, headroom); + v = __lsx_vaddwod_w_h(uv, headroom); + WRITE_YUV2RGB_LSX(y_l, y_l, u, v, 0, 1, 0, 0); + WRITE_YUV2RGB_LSX(y_l, y_l, u, v, 2, 3, 1, 1); + WRITE_YUV2RGB_LSX(y_h, y_h, u, v, 0, 1, 2, 2); + WRITE_YUV2RGB_LSX(y_h, y_h, u, v, 2, 3, 3, 3); + } + if (dstW - i >= 4){ + int Y1, Y2, U, V; + int i_dex = i << 1; + __m128i src_y, src_u, src_v; + __m128i y_l, u, v, uv; + + src_y = __lsx_vldx(buf0, i_dex); + src_u = __lsx_vldrepl_d((ubuf0 + count), 0); + src_v = __lsx_vldrepl_d((vbuf0 + count), 0); + y_l = __lsx_vsrari_h(src_y, 7); + y_l = __lsx_vsllwil_w_h(y_l, 0); + uv = __lsx_vilvl_h(src_v, src_u); + uv = __lsx_vsrari_h(uv, 7); + u = __lsx_vaddwev_w_h(uv, headroom); + v = __lsx_vaddwod_w_h(uv, headroom); + WRITE_YUV2RGB_LSX(y_l, y_l, u, v, 0, 1, 0, 0); + WRITE_YUV2RGB_LSX(y_l, y_l, u, v, 2, 3, 1, 1); + i += 4; + } + for (; count < len_count; count++) { + int Y1 = (buf0[count * 2 ] + 64) >> 7; + int Y2 = (buf0[count * 2 + 1] + 64) >> 7; + int U = (ubuf0[count] + 64) >> 7; + int V = (vbuf0[count] + 64) >> 7; + + r = c->table_rV[V + YUVRGB_TABLE_HEADROOM], + g = (c->table_gU[U + YUVRGB_TABLE_HEADROOM] + + c->table_gV[V + YUVRGB_TABLE_HEADROOM]), + b = c->table_bU[U + YUVRGB_TABLE_HEADROOM]; + + yuv2rgb_write(dest, count, Y1, Y2, 0, 0, + r, g, b, y, target, 0); + } + } else { + const int16_t *ubuf1 = ubuf[1], *vbuf1 = vbuf[1]; + int count = 0; + int HEADROOM = YUVRGB_TABLE_HEADROOM; + __m128i headroom = __lsx_vreplgr2vr_w(HEADROOM); + + for (i = 0; i < len; i += 8) { + int Y1, Y2, U, V; + int i_dex = i << 1; + int c_dex = count << 1; + __m128i src_y, src_u0, src_v0, src_u1, src_v1; + __m128i y_l, y_h, u1, u2, v1, v2; + + DUP4_ARG2(__lsx_vldx, buf0, i_dex, ubuf0, c_dex, vbuf0, c_dex, + ubuf1, c_dex, src_y, src_u0, src_v0, src_u1); + src_v1 = __lsx_vldx(vbuf1, c_dex); + src_y = __lsx_vsrari_h(src_y, 7); + u1 = __lsx_vaddwev_w_h(src_u0, src_u1); + v1 = __lsx_vaddwod_w_h(src_u0, src_u1); + u2 = __lsx_vaddwev_w_h(src_v0, src_v1); + v2 = __lsx_vaddwod_w_h(src_v0, src_v1); + y_l = __lsx_vsllwil_w_h(src_y, 0); + y_h = __lsx_vexth_w_h(src_y); + u1 = __lsx_vsrari_w(u1, 8); + v1 = __lsx_vsrari_w(v1, 8); + u2 = __lsx_vsrari_w(u2, 8); + v2 = __lsx_vsrari_w(v2, 8); + u1 = __lsx_vadd_w(u1, headroom); + v1 = __lsx_vadd_w(v1, headroom); + u2 = __lsx_vadd_w(u2, headroom); + v2 = __lsx_vadd_w(v2, headroom); + WRITE_YUV2RGB_LSX(y_l, y_l, u1, v1, 0, 1, 0, 0); + WRITE_YUV2RGB_LSX(y_l, y_l, u2, v2, 2, 3, 0, 0); + WRITE_YUV2RGB_LSX(y_h, y_h, u1, v1, 0, 1, 1, 1); + WRITE_YUV2RGB_LSX(y_h, y_h, u2, v2, 2, 3, 1, 1); + } + if (dstW - i >= 4) { + int Y1, Y2, U, V; + int i_dex = i << 1; + __m128i src_y, src_u0, src_v0, src_u1, src_v1; + __m128i uv; + + src_y = __lsx_vldx(buf0, i_dex); + src_u0 = __lsx_vldrepl_d((ubuf0 + count), 0); + src_v0 = __lsx_vldrepl_d((vbuf0 + count), 0); + src_u1 = __lsx_vldrepl_d((ubuf1 + count), 0); + src_v1 = __lsx_vldrepl_d((vbuf1 + count), 0); + + src_u0 = __lsx_vilvl_h(src_u1, src_u0); + src_v0 = __lsx_vilvl_h(src_v1, src_v0); + src_y = __lsx_vsrari_h(src_y, 7); + src_y = __lsx_vsllwil_w_h(src_y, 0); + uv = __lsx_vilvl_h(src_v0, src_u0); + uv = __lsx_vhaddw_w_h(uv, uv); + uv = __lsx_vsrari_w(uv, 8); + uv = __lsx_vadd_w(uv, headroom); + WRITE_YUV2RGB_LSX(src_y, src_y, uv, uv, 0, 1, 0, 1); + WRITE_YUV2RGB_LSX(src_y, src_y, uv, uv, 2, 3, 2, 3); + i += 4; + } + for (; count < len_count; count++) { + int Y1 = (buf0[count * 2 ] + 64) >> 7; + int Y2 = (buf0[count * 2 + 1] + 64) >> 7; + int U = (ubuf0[count] + ubuf1[count] + 128) >> 8; + int V = (vbuf0[count] + vbuf1[count] + 128) >> 8; + + r = c->table_rV[V + YUVRGB_TABLE_HEADROOM], + g = (c->table_gU[U + YUVRGB_TABLE_HEADROOM] + + c->table_gV[V + YUVRGB_TABLE_HEADROOM]), + b = c->table_bU[U + YUVRGB_TABLE_HEADROOM]; + + yuv2rgb_write(dest, count, Y1, Y2, 0, 0, + r, g, b, y, target, 0); + } + } +} + +#define YUV2RGBWRAPPERX(name, base, ext, fmt, hasAlpha) \ +static void name ## ext ## _X_lsx(SwsContext *c, const int16_t *lumFilter, \ + const int16_t **lumSrc, int lumFilterSize, \ + const int16_t *chrFilter, const int16_t **chrUSrc, \ + const int16_t **chrVSrc, int chrFilterSize, \ + const int16_t **alpSrc, uint8_t *dest, int dstW, \ + int y) \ +{ \ + name ## base ## _X_template_lsx(c, lumFilter, lumSrc, lumFilterSize, \ + chrFilter, chrUSrc, chrVSrc, chrFilterSize, \ + alpSrc, dest, dstW, y, fmt, hasAlpha); \ +} + +#define YUV2RGBWRAPPERX2(name, base, ext, fmt, hasAlpha) \ +YUV2RGBWRAPPERX(name, base, ext, fmt, hasAlpha) \ +static void name ## ext ## _2_lsx(SwsContext *c, const int16_t *buf[2], \ + const int16_t *ubuf[2], const int16_t *vbuf[2], \ + const int16_t *abuf[2], uint8_t *dest, int dstW, \ + int yalpha, int uvalpha, int y) \ +{ \ + name ## base ## _2_template_lsx(c, buf, ubuf, vbuf, abuf, dest, \ + dstW, yalpha, uvalpha, y, fmt, hasAlpha); \ +} + +#define YUV2RGBWRAPPER(name, base, ext, fmt, hasAlpha) \ +YUV2RGBWRAPPERX2(name, base, ext, fmt, hasAlpha) \ +static void name ## ext ## _1_lsx(SwsContext *c, const int16_t *buf0, \ + const int16_t *ubuf[2], const int16_t *vbuf[2], \ + const int16_t *abuf0, uint8_t *dest, int dstW, \ + int uvalpha, int y) \ +{ \ + name ## base ## _1_template_lsx(c, buf0, ubuf, vbuf, abuf0, dest, \ + dstW, uvalpha, y, fmt, hasAlpha); \ +} + +#if CONFIG_SMALL +#else +#if CONFIG_SWSCALE_ALPHA +#endif +YUV2RGBWRAPPER(yuv2rgb,, x32_1, AV_PIX_FMT_RGB32_1, 0) +YUV2RGBWRAPPER(yuv2rgb,, x32, AV_PIX_FMT_RGB32, 0) +#endif +YUV2RGBWRAPPER(yuv2, rgb, rgb24, AV_PIX_FMT_RGB24, 0) +YUV2RGBWRAPPER(yuv2, rgb, bgr24, AV_PIX_FMT_BGR24, 0) +YUV2RGBWRAPPER(yuv2rgb,, 16, AV_PIX_FMT_RGB565, 0) +YUV2RGBWRAPPER(yuv2rgb,, 15, AV_PIX_FMT_RGB555, 0) +YUV2RGBWRAPPER(yuv2rgb,, 12, AV_PIX_FMT_RGB444, 0) +YUV2RGBWRAPPER(yuv2rgb,, 8, AV_PIX_FMT_RGB8, 0) +YUV2RGBWRAPPER(yuv2rgb,, 4, AV_PIX_FMT_RGB4, 0) +YUV2RGBWRAPPER(yuv2rgb,, 4b, AV_PIX_FMT_RGB4_BYTE, 0) + +// This function is copied from libswscale/output.c +static av_always_inline void yuv2rgb_write_full(SwsContext *c, + uint8_t *dest, int i, int R, int A, int G, int B, + int y, enum AVPixelFormat target, int hasAlpha, int err[4]) +{ + int isrgb8 = target == AV_PIX_FMT_BGR8 || target == AV_PIX_FMT_RGB8; + + if ((R | G | B) & 0xC0000000) { + R = av_clip_uintp2(R, 30); + G = av_clip_uintp2(G, 30); + B = av_clip_uintp2(B, 30); + } + + switch(target) { + case AV_PIX_FMT_ARGB: + dest[0] = hasAlpha ? A : 255; + dest[1] = R >> 22; + dest[2] = G >> 22; + dest[3] = B >> 22; + break; + case AV_PIX_FMT_RGB24: + dest[0] = R >> 22; + dest[1] = G >> 22; + dest[2] = B >> 22; + break; + case AV_PIX_FMT_RGBA: + dest[0] = R >> 22; + dest[1] = G >> 22; + dest[2] = B >> 22; + dest[3] = hasAlpha ? A : 255; + break; + case AV_PIX_FMT_ABGR: + dest[0] = hasAlpha ? A : 255; + dest[1] = B >> 22; + dest[2] = G >> 22; + dest[3] = R >> 22; + break; + case AV_PIX_FMT_BGR24: + dest[0] = B >> 22; + dest[1] = G >> 22; + dest[2] = R >> 22; + break; + case AV_PIX_FMT_BGRA: + dest[0] = B >> 22; + dest[1] = G >> 22; + dest[2] = R >> 22; + dest[3] = hasAlpha ? A : 255; + break; + case AV_PIX_FMT_BGR4_BYTE: + case AV_PIX_FMT_RGB4_BYTE: + case AV_PIX_FMT_BGR8: + case AV_PIX_FMT_RGB8: + { + int r,g,b; + + switch (c->dither) { + default: + case SWS_DITHER_AUTO: + case SWS_DITHER_ED: + R >>= 22; + G >>= 22; + B >>= 22; + R += (7*err[0] + 1*c->dither_error[0][i] + 5*c->dither_error[0][i+1] + 3*c->dither_error[0][i+2])>>4; + G += (7*err[1] + 1*c->dither_error[1][i] + 5*c->dither_error[1][i+1] + 3*c->dither_error[1][i+2])>>4; + B += (7*err[2] + 1*c->dither_error[2][i] + 5*c->dither_error[2][i+1] + 3*c->dither_error[2][i+2])>>4; + c->dither_error[0][i] = err[0]; + c->dither_error[1][i] = err[1]; + c->dither_error[2][i] = err[2]; + r = R >> (isrgb8 ? 5 : 7); + g = G >> (isrgb8 ? 5 : 6); + b = B >> (isrgb8 ? 6 : 7); + r = av_clip(r, 0, isrgb8 ? 7 : 1); + g = av_clip(g, 0, isrgb8 ? 7 : 3); + b = av_clip(b, 0, isrgb8 ? 3 : 1); + err[0] = R - r*(isrgb8 ? 36 : 255); + err[1] = G - g*(isrgb8 ? 36 : 85); + err[2] = B - b*(isrgb8 ? 85 : 255); + break; + case SWS_DITHER_A_DITHER: + if (isrgb8) { + /* see http://pippin.gimp.org/a_dither/ for details/origin */ +#define A_DITHER(u,v) (((((u)+((v)*236))*119)&0xff)) + r = (((R >> 19) + A_DITHER(i,y) -96)>>8); + g = (((G >> 19) + A_DITHER(i + 17,y) - 96)>>8); + b = (((B >> 20) + A_DITHER(i + 17*2,y) -96)>>8); + r = av_clip_uintp2(r, 3); + g = av_clip_uintp2(g, 3); + b = av_clip_uintp2(b, 2); + } else { + r = (((R >> 21) + A_DITHER(i,y)-256)>>8); + g = (((G >> 19) + A_DITHER(i + 17,y)-256)>>8); + b = (((B >> 21) + A_DITHER(i + 17*2,y)-256)>>8); + r = av_clip_uintp2(r, 1); + g = av_clip_uintp2(g, 2); + b = av_clip_uintp2(b, 1); + } + break; + case SWS_DITHER_X_DITHER: + if (isrgb8) { + /* see http://pippin.gimp.org/a_dither/ for details/origin */ +#define X_DITHER(u,v) (((((u)^((v)*237))*181)&0x1ff)/2) + r = (((R >> 19) + X_DITHER(i,y) - 96)>>8); + g = (((G >> 19) + X_DITHER(i + 17,y) - 96)>>8); + b = (((B >> 20) + X_DITHER(i + 17*2,y) - 96)>>8); + r = av_clip_uintp2(r, 3); + g = av_clip_uintp2(g, 3); + b = av_clip_uintp2(b, 2); + } else { + r = (((R >> 21) + X_DITHER(i,y)-256)>>8); + g = (((G >> 19) + X_DITHER(i + 17,y)-256)>>8); + b = (((B >> 21) + X_DITHER(i + 17*2,y)-256)>>8); + r = av_clip_uintp2(r, 1); + g = av_clip_uintp2(g, 2); + b = av_clip_uintp2(b, 1); + } + + break; + } + + if(target == AV_PIX_FMT_BGR4_BYTE) { + dest[0] = r + 2*g + 8*b; + } else if(target == AV_PIX_FMT_RGB4_BYTE) { + dest[0] = b + 2*g + 8*r; + } else if(target == AV_PIX_FMT_BGR8) { + dest[0] = r + 8*g + 64*b; + } else if(target == AV_PIX_FMT_RGB8) { + dest[0] = b + 4*g + 32*r; + } else + av_assert2(0); + break; } + } +} + +#define YUVTORGB_SETUP_LSX \ + int y_offset = c->yuv2rgb_y_offset; \ + int y_coeff = c->yuv2rgb_y_coeff; \ + int v2r_coe = c->yuv2rgb_v2r_coeff; \ + int v2g_coe = c->yuv2rgb_v2g_coeff; \ + int u2g_coe = c->yuv2rgb_u2g_coeff; \ + int u2b_coe = c->yuv2rgb_u2b_coeff; \ + __m128i offset = __lsx_vreplgr2vr_w(y_offset); \ + __m128i coeff = __lsx_vreplgr2vr_w(y_coeff); \ + __m128i v2r = __lsx_vreplgr2vr_w(v2r_coe); \ + __m128i v2g = __lsx_vreplgr2vr_w(v2g_coe); \ + __m128i u2g = __lsx_vreplgr2vr_w(u2g_coe); \ + __m128i u2b = __lsx_vreplgr2vr_w(u2b_coe); \ + +#define YUVTORGB_LSX(y, u, v, R, G, B, offset, coeff, \ + y_temp, v2r, v2g, u2g, u2b) \ +{ \ + y = __lsx_vsub_w(y, offset); \ + y = __lsx_vmul_w(y, coeff); \ + y = __lsx_vadd_w(y, y_temp); \ + R = __lsx_vmadd_w(y, v, v2r); \ + v = __lsx_vmadd_w(y, v, v2g); \ + G = __lsx_vmadd_w(v, u, u2g); \ + B = __lsx_vmadd_w(y, u, u2b); \ +} + +#define WRITE_FULL_A_LSX(r, g, b, a, t1, s) \ +{ \ + R = __lsx_vpickve2gr_w(r, t1); \ + G = __lsx_vpickve2gr_w(g, t1); \ + B = __lsx_vpickve2gr_w(b, t1); \ + A = __lsx_vpickve2gr_w(a, t1); \ + if (A & 0x100) \ + A = av_clip_uint8(A); \ + yuv2rgb_write_full(c, dest, i + s, R, A, G, B, y, target, hasAlpha, err);\ + dest += step; \ +} + +#define WRITE_FULL_LSX(r, g, b, t1, s) \ +{ \ + R = __lsx_vpickve2gr_w(r, t1); \ + G = __lsx_vpickve2gr_w(g, t1); \ + B = __lsx_vpickve2gr_w(b, t1); \ + yuv2rgb_write_full(c, dest, i + s, R, 0, G, B, y, target, hasAlpha, err); \ + dest += step; \ +} + +static void +yuv2rgb_full_X_template_lsx(SwsContext *c, const int16_t *lumFilter, + const int16_t **lumSrc, int lumFilterSize, + const int16_t *chrFilter, const int16_t **chrUSrc, + const int16_t **chrVSrc, int chrFilterSize, + const int16_t **alpSrc, uint8_t *dest, + int dstW, int y, enum AVPixelFormat target, + int hasAlpha) +{ + int i, j, B, G, R, A; + int step = (target == AV_PIX_FMT_RGB24 || + target == AV_PIX_FMT_BGR24) ? 3 : 4; + int err[4] = {0}; + int a_temp = 1 << 18; + int templ = 1 << 9; + int tempc = templ - (128 << 19); + int ytemp = 1 << 21; + int len = dstW - 7; + __m128i y_temp = __lsx_vreplgr2vr_w(ytemp); + YUVTORGB_SETUP_LSX + + if( target == AV_PIX_FMT_BGR4_BYTE || target == AV_PIX_FMT_RGB4_BYTE + || target == AV_PIX_FMT_BGR8 || target == AV_PIX_FMT_RGB8) + step = 1; + + for (i = 0; i < len; i += 8) { + __m128i l_src, u_src, v_src; + __m128i y_ev, y_od, u_ev, u_od, v_ev, v_od, temp; + __m128i R_ev, R_od, G_ev, G_od, B_ev, B_od; + int n = i << 1; + + y_ev = y_od = __lsx_vreplgr2vr_w(templ); + u_ev = u_od = v_ev = v_od = __lsx_vreplgr2vr_w(tempc); + for (j = 0; j < lumFilterSize; j++) { + temp = __lsx_vldrepl_h((lumFilter + j), 0); + l_src = __lsx_vldx(lumSrc[j], n); + y_ev = __lsx_vmaddwev_w_h(y_ev, l_src, temp); + y_od = __lsx_vmaddwod_w_h(y_od, l_src, temp); + } + for (j = 0; j < chrFilterSize; j++) { + temp = __lsx_vldrepl_h((chrFilter + j), 0); + DUP2_ARG2(__lsx_vldx, chrUSrc[j], n, chrVSrc[j], n, + u_src, v_src); + DUP2_ARG3(__lsx_vmaddwev_w_h, u_ev, u_src, temp, v_ev, + v_src, temp, u_ev, v_ev); + DUP2_ARG3(__lsx_vmaddwod_w_h, u_od, u_src, temp, v_od, + v_src, temp, u_od, v_od); + } + y_ev = __lsx_vsrai_w(y_ev, 10); + y_od = __lsx_vsrai_w(y_od, 10); + u_ev = __lsx_vsrai_w(u_ev, 10); + u_od = __lsx_vsrai_w(u_od, 10); + v_ev = __lsx_vsrai_w(v_ev, 10); + v_od = __lsx_vsrai_w(v_od, 10); + YUVTORGB_LSX(y_ev, u_ev, v_ev, R_ev, G_ev, B_ev, offset, coeff, + y_temp, v2r, v2g, u2g, u2b); + YUVTORGB_LSX(y_od, u_od, v_od, R_od, G_od, B_od, offset, coeff, + y_temp, v2r, v2g, u2g, u2b); + + if (hasAlpha) { + __m128i a_src, a_ev, a_od; + + a_ev = a_od = __lsx_vreplgr2vr_w(a_temp); + for (j = 0; j < lumFilterSize; j++) { + temp = __lsx_vldrepl_h(lumFilter + j, 0); + a_src = __lsx_vldx(alpSrc[j], n); + a_ev = __lsx_vmaddwev_w_h(a_ev, a_src, temp); + a_od = __lsx_vmaddwod_w_h(a_od, a_src, temp); + } + a_ev = __lsx_vsrai_w(a_ev, 19); + a_od = __lsx_vsrai_w(a_od, 19); + WRITE_FULL_A_LSX(R_ev, G_ev, B_ev, a_ev, 0, 0); + WRITE_FULL_A_LSX(R_od, G_od, B_od, a_od, 0, 1); + WRITE_FULL_A_LSX(R_ev, G_ev, B_ev, a_ev, 1, 2); + WRITE_FULL_A_LSX(R_od, G_od, B_od, a_od, 1, 3); + WRITE_FULL_A_LSX(R_ev, G_ev, B_ev, a_ev, 2, 4); + WRITE_FULL_A_LSX(R_od, G_od, B_od, a_od, 2, 5); + WRITE_FULL_A_LSX(R_ev, G_ev, B_ev, a_ev, 3, 6); + WRITE_FULL_A_LSX(R_od, G_od, B_od, a_od, 3, 7); + } else { + WRITE_FULL_LSX(R_ev, G_ev, B_ev, 0, 0); + WRITE_FULL_LSX(R_od, G_od, B_od, 0, 1); + WRITE_FULL_LSX(R_ev, G_ev, B_ev, 1, 2); + WRITE_FULL_LSX(R_od, G_od, B_od, 1, 3); + WRITE_FULL_LSX(R_ev, G_ev, B_ev, 2, 4); + WRITE_FULL_LSX(R_od, G_od, B_od, 2, 5); + WRITE_FULL_LSX(R_ev, G_ev, B_ev, 3, 6); + WRITE_FULL_LSX(R_od, G_od, B_od, 3, 7); + } + } + if (dstW - i >= 4) { + __m128i l_src, u_src, v_src; + __m128i y_ev, u_ev, v_ev, uv, temp; + __m128i R_ev, G_ev, B_ev; + int n = i << 1; + + y_ev = __lsx_vreplgr2vr_w(templ); + u_ev = v_ev = __lsx_vreplgr2vr_w(tempc); + for (j = 0; j < lumFilterSize; j++) { + temp = __lsx_vldrepl_h((lumFilter + j), 0); + l_src = __lsx_vldx(lumSrc[j], n); + l_src = __lsx_vilvl_h(l_src, l_src); + y_ev = __lsx_vmaddwev_w_h(y_ev, l_src, temp); + } + for (j = 0; j < chrFilterSize; j++) { + temp = __lsx_vldrepl_h((chrFilter + j), 0); + DUP2_ARG2(__lsx_vldx, chrUSrc[j], n, chrVSrc[j], n, u_src, v_src); + uv = __lsx_vilvl_h(v_src, u_src); + u_ev = __lsx_vmaddwev_w_h(u_ev, uv, temp); + v_ev = __lsx_vmaddwod_w_h(v_ev, uv, temp); + } + y_ev = __lsx_vsrai_w(y_ev, 10); + u_ev = __lsx_vsrai_w(u_ev, 10); + v_ev = __lsx_vsrai_w(v_ev, 10); + YUVTORGB_LSX(y_ev, u_ev, v_ev, R_ev, G_ev, B_ev, offset, coeff, + y_temp, v2r, v2g, u2g, u2b); + + if (hasAlpha) { + __m128i a_src, a_ev; + + a_ev = __lsx_vreplgr2vr_w(a_temp); + for (j = 0; j < lumFilterSize; j++) { + temp = __lsx_vldrepl_h(lumFilter + j, 0); + a_src = __lsx_vldx(alpSrc[j], n); + a_src = __lsx_vilvl_h(a_src, a_src); + a_ev = __lsx_vmaddwev_w_h(a_ev, a_src, temp); + } + a_ev = __lsx_vsrai_w(a_ev, 19); + WRITE_FULL_A_LSX(R_ev, G_ev, B_ev, a_ev, 0, 0); + WRITE_FULL_A_LSX(R_ev, G_ev, B_ev, a_ev, 1, 1); + WRITE_FULL_A_LSX(R_ev, G_ev, B_ev, a_ev, 2, 2); + WRITE_FULL_A_LSX(R_ev, G_ev, B_ev, a_ev, 3, 3); + } else { + WRITE_FULL_LSX(R_ev, G_ev, B_ev, 0, 0); + WRITE_FULL_LSX(R_ev, G_ev, B_ev, 1, 1); + WRITE_FULL_LSX(R_ev, G_ev, B_ev, 2, 2); + WRITE_FULL_LSX(R_ev, G_ev, B_ev, 3, 3); + } + i += 4; + } + for (; i < dstW; i++) { + int Y = templ; + int V, U = V = tempc; + + A = 0; + for (j = 0; j < lumFilterSize; j++) { + Y += lumSrc[j][i] * lumFilter[j]; + } + for (j = 0; j < chrFilterSize; j++) { + U += chrUSrc[j][i] * chrFilter[j]; + V += chrVSrc[j][i] * chrFilter[j]; + + } + Y >>= 10; + U >>= 10; + V >>= 10; + if (hasAlpha) { + A = 1 << 18; + for (j = 0; j < lumFilterSize; j++) { + A += alpSrc[j][i] * lumFilter[j]; + } + A >>= 19; + if (A & 0x100) + A = av_clip_uint8(A); + } + Y -= y_offset; + Y *= y_coeff; + Y += ytemp; + R = (unsigned)Y + V * v2r_coe; + G = (unsigned)Y + V * v2g_coe + U * u2g_coe; + B = (unsigned)Y + U * u2b_coe; + yuv2rgb_write_full(c, dest, i, R, A, G, B, y, target, hasAlpha, err); + dest += step; + } + c->dither_error[0][i] = err[0]; + c->dither_error[1][i] = err[1]; + c->dither_error[2][i] = err[2]; +} + +static void +yuv2rgb_full_2_template_lsx(SwsContext *c, const int16_t *buf[2], + const int16_t *ubuf[2], const int16_t *vbuf[2], + const int16_t *abuf[2], uint8_t *dest, int dstW, + int yalpha, int uvalpha, int y, + enum AVPixelFormat target, int hasAlpha) +{ + const int16_t *buf0 = buf[0], *buf1 = buf[1], + *ubuf0 = ubuf[0], *ubuf1 = ubuf[1], + *vbuf0 = vbuf[0], *vbuf1 = vbuf[1], + *abuf0 = hasAlpha ? abuf[0] : NULL, + *abuf1 = hasAlpha ? abuf[1] : NULL; + int yalpha1 = 4096 - yalpha; + int uvalpha1 = 4096 - uvalpha; + int uvtemp = 128 << 19; + int atemp = 1 << 18; + int err[4] = {0}; + int ytemp = 1 << 21; + int len = dstW - 7; + int i, R, G, B, A; + int step = (target == AV_PIX_FMT_RGB24 || + target == AV_PIX_FMT_BGR24) ? 3 : 4; + __m128i v_uvalpha1 = __lsx_vreplgr2vr_w(uvalpha1); + __m128i v_yalpha1 = __lsx_vreplgr2vr_w(yalpha1); + __m128i v_uvalpha = __lsx_vreplgr2vr_w(uvalpha); + __m128i v_yalpha = __lsx_vreplgr2vr_w(yalpha); + __m128i uv = __lsx_vreplgr2vr_w(uvtemp); + __m128i a_bias = __lsx_vreplgr2vr_w(atemp); + __m128i y_temp = __lsx_vreplgr2vr_w(ytemp); + YUVTORGB_SETUP_LSX + + av_assert2(yalpha <= 4096U); + av_assert2(uvalpha <= 4096U); + + if( target == AV_PIX_FMT_BGR4_BYTE || target == AV_PIX_FMT_RGB4_BYTE + || target == AV_PIX_FMT_BGR8 || target == AV_PIX_FMT_RGB8) + step = 1; + + for (i = 0; i < len; i += 8) { + __m128i b0, b1, ub0, ub1, vb0, vb1; + __m128i y0_l, y0_h, y1_l, y1_h, u0_l, u0_h; + __m128i v0_l, v0_h, u1_l, u1_h, v1_l, v1_h; + __m128i y_l, y_h, v_l, v_h, u_l, u_h; + __m128i R_l, R_h, G_l, G_h, B_l, B_h; + int n = i << 1; + + DUP4_ARG2(__lsx_vldx, buf0, n, buf1, n, ubuf0, + n, ubuf1, n, b0, b1, ub0, ub1); + DUP2_ARG2(__lsx_vldx, vbuf0, n, vbuf1, n, vb0 , vb1); + DUP2_ARG2(__lsx_vsllwil_w_h, b0, 0, b1, 0, y0_l, y1_l); + DUP4_ARG2(__lsx_vsllwil_w_h, ub0, 0, ub1, 0, vb0, 0, vb1, 0, + u0_l, u1_l, v0_l, v1_l); + DUP2_ARG1(__lsx_vexth_w_h, b0, b1, y0_h, y1_h); + DUP4_ARG1(__lsx_vexth_w_h, ub0, ub1, vb0, vb1, + u0_h, u1_h, v0_h, v1_h); + y0_l = __lsx_vmul_w(y0_l, v_yalpha1); + y0_h = __lsx_vmul_w(y0_h, v_yalpha1); + u0_l = __lsx_vmul_w(u0_l, v_uvalpha1); + u0_h = __lsx_vmul_w(u0_h, v_uvalpha1); + v0_l = __lsx_vmul_w(v0_l, v_uvalpha1); + v0_h = __lsx_vmul_w(v0_h, v_uvalpha1); + y_l = __lsx_vmadd_w(y0_l, v_yalpha, y1_l); + y_h = __lsx_vmadd_w(y0_h, v_yalpha, y1_h); + u_l = __lsx_vmadd_w(u0_l, v_uvalpha, u1_l); + u_h = __lsx_vmadd_w(u0_h, v_uvalpha, u1_h); + v_l = __lsx_vmadd_w(v0_l, v_uvalpha, v1_l); + v_h = __lsx_vmadd_w(v0_h, v_uvalpha, v1_h); + u_l = __lsx_vsub_w(u_l, uv); + u_h = __lsx_vsub_w(u_h, uv); + v_l = __lsx_vsub_w(v_l, uv); + v_h = __lsx_vsub_w(v_h, uv); + y_l = __lsx_vsrai_w(y_l, 10); + y_h = __lsx_vsrai_w(y_h, 10); + u_l = __lsx_vsrai_w(u_l, 10); + u_h = __lsx_vsrai_w(u_h, 10); + v_l = __lsx_vsrai_w(v_l, 10); + v_h = __lsx_vsrai_w(v_h, 10); + YUVTORGB_LSX(y_l, u_l, v_l, R_l, G_l, B_l, offset, coeff, + y_temp, v2r, v2g, u2g, u2b); + YUVTORGB_LSX(y_h, u_h, v_h, R_h, G_h, B_h, offset, coeff, + y_temp, v2r, v2g, u2g, u2b); + + if (hasAlpha) { + __m128i a0, a1, a0_l, a0_h; + __m128i a_l, a_h, a1_l, a1_h; + + DUP2_ARG2(__lsx_vldx, abuf0, n, abuf1, n, a0, a1); + DUP2_ARG2(__lsx_vsllwil_w_h, a0, 0, a1, 0, a0_l, a1_l); + DUP2_ARG1(__lsx_vexth_w_h, a0, a1, a0_h, a1_h); + a_l = __lsx_vmadd_w(a_bias, a0_l, v_yalpha1); + a_h = __lsx_vmadd_w(a_bias, a0_h, v_yalpha1); + a_l = __lsx_vmadd_w(a_l, v_yalpha, a1_l); + a_h = __lsx_vmadd_w(a_h, v_yalpha, a1_h); + a_l = __lsx_vsrai_w(a_l, 19); + a_h = __lsx_vsrai_w(a_h, 19); + WRITE_FULL_A_LSX(R_l, G_l, B_l, a_l, 0, 0); + WRITE_FULL_A_LSX(R_l, G_l, B_l, a_l, 1, 1); + WRITE_FULL_A_LSX(R_l, G_l, B_l, a_l, 2, 2); + WRITE_FULL_A_LSX(R_l, G_l, B_l, a_l, 3, 3); + WRITE_FULL_A_LSX(R_h, G_h, B_h, a_h, 0, 4); + WRITE_FULL_A_LSX(R_h, G_h, B_h, a_h, 1, 5); + WRITE_FULL_A_LSX(R_h, G_h, B_h, a_h, 2, 6); + WRITE_FULL_A_LSX(R_h, G_h, B_h, a_h, 3, 7); + } else { + WRITE_FULL_LSX(R_l, G_l, B_l, 0, 0); + WRITE_FULL_LSX(R_l, G_l, B_l, 1, 1); + WRITE_FULL_LSX(R_l, G_l, B_l, 2, 2); + WRITE_FULL_LSX(R_l, G_l, B_l, 3, 3); + WRITE_FULL_LSX(R_h, G_h, B_h, 0, 4); + WRITE_FULL_LSX(R_h, G_h, B_h, 1, 5); + WRITE_FULL_LSX(R_h, G_h, B_h, 2, 6); + WRITE_FULL_LSX(R_h, G_h, B_h, 3, 7); + } + } + if (dstW - i >= 4) { + __m128i b0, b1, ub0, ub1, vb0, vb1; + __m128i y0_l, y1_l, u0_l; + __m128i v0_l, u1_l, v1_l; + __m128i y_l, u_l, v_l; + __m128i R_l, G_l, B_l; + int n = i << 1; + + DUP4_ARG2(__lsx_vldx, buf0, n, buf1, n, ubuf0, n, + ubuf1, n, b0, b1, ub0, ub1); + DUP2_ARG2(__lsx_vldx, vbuf0, n, vbuf1, n, vb0, vb1); + DUP2_ARG2(__lsx_vsllwil_w_h, b0, 0, b1, 0, y0_l, y1_l); + DUP4_ARG2(__lsx_vsllwil_w_h, ub0, 0, ub1, 0, vb0, 0, vb1, 0, + u0_l, u1_l, v0_l, v1_l); + y0_l = __lsx_vmul_w(y0_l, v_yalpha1); + u0_l = __lsx_vmul_w(u0_l, v_uvalpha1); + v0_l = __lsx_vmul_w(v0_l, v_uvalpha1); + y_l = __lsx_vmadd_w(y0_l, v_yalpha, y1_l); + u_l = __lsx_vmadd_w(u0_l, v_uvalpha, u1_l); + v_l = __lsx_vmadd_w(v0_l, v_uvalpha, v1_l); + u_l = __lsx_vsub_w(u_l, uv); + v_l = __lsx_vsub_w(v_l, uv); + y_l = __lsx_vsrai_w(y_l, 10); + u_l = __lsx_vsrai_w(u_l, 10); + v_l = __lsx_vsrai_w(v_l, 10); + YUVTORGB_LSX(y_l, u_l, v_l, R_l, G_l, B_l, offset, coeff, + y_temp, v2r, v2g, u2g, u2b); + + if (hasAlpha) { + __m128i a0, a1, a0_l; + __m128i a_l, a1_l; + + DUP2_ARG2(__lsx_vldx, abuf0, n, abuf1, n, a0, a1); + DUP2_ARG2(__lsx_vsllwil_w_h, a0, 0, a1, 0, a0_l, a1_l); + a_l = __lsx_vmadd_w(a_bias, a0_l, v_yalpha1); + a_l = __lsx_vmadd_w(a_l, v_yalpha, a1_l); + a_l = __lsx_vsrai_w(a_l, 19); + WRITE_FULL_A_LSX(R_l, G_l, B_l, a_l, 0, 0); + WRITE_FULL_A_LSX(R_l, G_l, B_l, a_l, 1, 1); + WRITE_FULL_A_LSX(R_l, G_l, B_l, a_l, 2, 2); + WRITE_FULL_A_LSX(R_l, G_l, B_l, a_l, 3, 3); + } else { + WRITE_FULL_LSX(R_l, G_l, B_l, 0, 0); + WRITE_FULL_LSX(R_l, G_l, B_l, 1, 1); + WRITE_FULL_LSX(R_l, G_l, B_l, 2, 2); + WRITE_FULL_LSX(R_l, G_l, B_l, 3, 3); + } + i += 4; + } + for (; i < dstW; i++){ + int Y = ( buf0[i] * yalpha1 + buf1[i] * yalpha ) >> 10; + int U = (ubuf0[i] * uvalpha1 + ubuf1[i] * uvalpha- uvtemp) >> 10; + int V = (vbuf0[i] * uvalpha1 + vbuf1[i] * uvalpha- uvtemp) >> 10; + + A = 0; + if (hasAlpha){ + A = (abuf0[i] * yalpha1 + abuf1[i] * yalpha + atemp) >> 19; + if (A & 0x100) + A = av_clip_uint8(A); + } + + Y -= y_offset; + Y *= y_coeff; + Y += ytemp; + R = (unsigned)Y + V * v2r_coe; + G = (unsigned)Y + V * v2g_coe + U * u2g_coe; + B = (unsigned)Y + U * u2b_coe; + yuv2rgb_write_full(c, dest, i, R, A, G, B, y, target, hasAlpha, err); + dest += step; + } + c->dither_error[0][i] = err[0]; + c->dither_error[1][i] = err[1]; + c->dither_error[2][i] = err[2]; +} + +static void +yuv2rgb_full_1_template_lsx(SwsContext *c, const int16_t *buf0, + const int16_t *ubuf[2], const int16_t *vbuf[2], + const int16_t *abuf0, uint8_t *dest, int dstW, + int uvalpha, int y, enum AVPixelFormat target, + int hasAlpha) +{ + const int16_t *ubuf0 = ubuf[0], *vbuf0 = vbuf[0]; + int i, B, G, R, A; + int step = (target == AV_PIX_FMT_RGB24 || target == AV_PIX_FMT_BGR24) ? 3 : 4; + int err[4] = {0}; + int ytemp = 1 << 21; + int bias_int = 64; + int len = dstW - 7; + __m128i y_temp = __lsx_vreplgr2vr_w(ytemp); + YUVTORGB_SETUP_LSX + + if( target == AV_PIX_FMT_BGR4_BYTE || target == AV_PIX_FMT_RGB4_BYTE + || target == AV_PIX_FMT_BGR8 || target == AV_PIX_FMT_RGB8) + step = 1; + if (uvalpha < 2048) { + int uvtemp = 128 << 7; + __m128i uv = __lsx_vreplgr2vr_w(uvtemp); + __m128i bias = __lsx_vreplgr2vr_w(bias_int); + + for (i = 0; i < len; i += 8) { + __m128i b, ub, vb, ub_l, ub_h, vb_l, vb_h; + __m128i y_l, y_h, u_l, u_h, v_l, v_h; + __m128i R_l, R_h, G_l, G_h, B_l, B_h; + int n = i << 1; + + DUP2_ARG2(__lsx_vldx, buf0, n, ubuf0, n, b, ub); + vb = __lsx_vldx(vbuf0, n); + y_l = __lsx_vsllwil_w_h(b, 2); + y_h = __lsx_vexth_w_h(b); + DUP2_ARG2(__lsx_vsllwil_w_h, ub, 0, vb, 0, ub_l, vb_l); + DUP2_ARG1(__lsx_vexth_w_h, ub, vb, ub_h, vb_h); + y_h = __lsx_vslli_w(y_h, 2); + u_l = __lsx_vsub_w(ub_l, uv); + u_h = __lsx_vsub_w(ub_h, uv); + v_l = __lsx_vsub_w(vb_l, uv); + v_h = __lsx_vsub_w(vb_h, uv); + u_l = __lsx_vslli_w(u_l, 2); + u_h = __lsx_vslli_w(u_h, 2); + v_l = __lsx_vslli_w(v_l, 2); + v_h = __lsx_vslli_w(v_h, 2); + YUVTORGB_LSX(y_l, u_l, v_l, R_l, G_l, B_l, offset, coeff, + y_temp, v2r, v2g, u2g, u2b); + YUVTORGB_LSX(y_h, u_h, v_h, R_h, G_h, B_h, offset, coeff, + y_temp, v2r, v2g, u2g, u2b); + + if(hasAlpha) { + __m128i a_src; + __m128i a_l, a_h; + + a_src = __lsx_vld(abuf0 + i, 0); + a_l = __lsx_vsllwil_w_h(a_src, 0); + a_h = __lsx_vexth_w_h(a_src); + a_l = __lsx_vadd_w(a_l, bias); + a_h = __lsx_vadd_w(a_h, bias); + a_l = __lsx_vsrai_w(a_l, 7); + a_h = __lsx_vsrai_w(a_h, 7); + WRITE_FULL_A_LSX(R_l, G_l, B_l, a_l, 0, 0); + WRITE_FULL_A_LSX(R_l, G_l, B_l, a_l, 1, 1); + WRITE_FULL_A_LSX(R_l, G_l, B_l, a_l, 2, 2); + WRITE_FULL_A_LSX(R_l, G_l, B_l, a_l, 3, 3); + WRITE_FULL_A_LSX(R_h, G_h, B_h, a_h, 0, 4); + WRITE_FULL_A_LSX(R_h, G_h, B_h, a_h, 1, 5); + WRITE_FULL_A_LSX(R_h, G_h, B_h, a_h, 2, 6); + WRITE_FULL_A_LSX(R_h, G_h, B_h, a_h, 3, 7); + } else { + WRITE_FULL_LSX(R_l, G_l, B_l, 0, 0); + WRITE_FULL_LSX(R_l, G_l, B_l, 1, 1); + WRITE_FULL_LSX(R_l, G_l, B_l, 2, 2); + WRITE_FULL_LSX(R_l, G_l, B_l, 3, 3); + WRITE_FULL_LSX(R_h, G_h, B_h, 0, 4); + WRITE_FULL_LSX(R_h, G_h, B_h, 1, 5); + WRITE_FULL_LSX(R_h, G_h, B_h, 2, 6); + WRITE_FULL_LSX(R_h, G_h, B_h, 3, 7); + } + } + if (dstW - i >= 4) { + __m128i b, ub, vb, ub_l, vb_l; + __m128i y_l, u_l, v_l; + __m128i R_l, G_l, B_l; + int n = i << 1; + + DUP2_ARG2(__lsx_vldx, buf0, n, ubuf0, n, b, ub); + vb = __lsx_vldx(vbuf0, n); + y_l = __lsx_vsllwil_w_h(b, 0); + DUP2_ARG2(__lsx_vsllwil_w_h, ub, 0, vb, 0, ub_l, vb_l); + y_l = __lsx_vslli_w(y_l, 2); + u_l = __lsx_vsub_w(ub_l, uv); + v_l = __lsx_vsub_w(vb_l, uv); + u_l = __lsx_vslli_w(u_l, 2); + v_l = __lsx_vslli_w(v_l, 2); + YUVTORGB_LSX(y_l, u_l, v_l, R_l, G_l, B_l, offset, coeff, + y_temp, v2r, v2g, u2g, u2b); + + if(hasAlpha) { + __m128i a_src, a_l; + + a_src = __lsx_vldx(abuf0, n); + a_src = __lsx_vsllwil_w_h(a_src, 0); + a_l = __lsx_vadd_w(bias, a_src); + a_l = __lsx_vsrai_w(a_l, 7); + WRITE_FULL_A_LSX(R_l, G_l, B_l, a_l, 0, 0); + WRITE_FULL_A_LSX(R_l, G_l, B_l, a_l, 1, 1); + WRITE_FULL_A_LSX(R_l, G_l, B_l, a_l, 2, 2); + WRITE_FULL_A_LSX(R_l, G_l, B_l, a_l, 3, 3); + } else { + WRITE_FULL_LSX(R_l, G_l, B_l, 0, 0); + WRITE_FULL_LSX(R_l, G_l, B_l, 1, 1); + WRITE_FULL_LSX(R_l, G_l, B_l, 2, 2); + WRITE_FULL_LSX(R_l, G_l, B_l, 3, 3); + } + i += 4; + } + for (; i < dstW; i++) { + int Y = buf0[i] << 2; + int U = (ubuf0[i] - uvtemp) << 2; + int V = (vbuf0[i] - uvtemp) << 2; + + A = 0; + if(hasAlpha) { + A = (abuf0[i] + 64) >> 7; + if (A & 0x100) + A = av_clip_uint8(A); + } + Y -= y_offset; + Y *= y_coeff; + Y += ytemp; + R = (unsigned)Y + V * v2r_coe; + G = (unsigned)Y + V * v2g_coe + U * u2g_coe; + B = (unsigned)Y + U * u2b_coe; + yuv2rgb_write_full(c, dest, i, R, A, G, B, y, target, hasAlpha, err); + dest += step; + } + } else { + const int16_t *ubuf1 = ubuf[1], *vbuf1 = vbuf[1]; + int uvtemp = 128 << 8; + __m128i uv = __lsx_vreplgr2vr_w(uvtemp); + __m128i zero = __lsx_vldi(0); + __m128i bias = __lsx_vreplgr2vr_h(bias_int); + + for (i = 0; i < len; i += 8) { + __m128i b, ub0, ub1, vb0, vb1; + __m128i y_ev, y_od, u_ev, u_od, v_ev, v_od; + __m128i R_ev, R_od, G_ev, G_od, B_ev, B_od; + int n = i << 1; + + DUP4_ARG2(__lsx_vldx, buf0, n, ubuf0, n, vbuf0, n, + ubuf1, n, b, ub0, vb0, ub1); + vb1 = __lsx_vldx(vbuf, n); + y_ev = __lsx_vaddwev_w_h(b, zero); + y_od = __lsx_vaddwod_w_h(b, zero); + DUP2_ARG2(__lsx_vaddwev_w_h, ub0, vb0, ub1, vb1, u_ev, v_ev); + DUP2_ARG2(__lsx_vaddwod_w_h, ub0, vb0, ub1, vb1, u_od, v_od); + DUP2_ARG2(__lsx_vslli_w, y_ev, 2, y_od, 2, y_ev, y_od); + DUP4_ARG2(__lsx_vsub_w, u_ev, uv, u_od, uv, v_ev, uv, v_od, uv, + u_ev, u_od, v_ev, v_od); + DUP4_ARG2(__lsx_vslli_w, u_ev, 1, u_od, 1, v_ev, 1, v_od, 1, + u_ev, u_od, v_ev, v_od); + YUVTORGB_LSX(y_ev, u_ev, v_ev, R_ev, G_ev, B_ev, offset, coeff, + y_temp, v2r, v2g, u2g, u2b); + YUVTORGB_LSX(y_od, u_od, v_od, R_od, G_od, B_od, offset, coeff, + y_temp, v2r, v2g, u2g, u2b); + + if(hasAlpha) { + __m128i a_src; + __m128i a_ev, a_od; + + a_src = __lsx_vld(abuf0 + i, 0); + a_ev = __lsx_vaddwev_w_h(bias, a_src); + a_od = __lsx_vaddwod_w_h(bias, a_src); + a_ev = __lsx_vsrai_w(a_ev, 7); + a_od = __lsx_vsrai_w(a_od, 7); + WRITE_FULL_A_LSX(R_ev, G_ev, B_ev, a_ev, 0, 0); + WRITE_FULL_A_LSX(R_od, G_od, B_od, a_od, 0, 1); + WRITE_FULL_A_LSX(R_ev, G_ev, B_ev, a_ev, 1, 2); + WRITE_FULL_A_LSX(R_od, G_od, B_od, a_od, 1, 3); + WRITE_FULL_A_LSX(R_ev, G_ev, B_ev, a_ev, 2, 4); + WRITE_FULL_A_LSX(R_od, G_od, B_od, a_od, 2, 5); + WRITE_FULL_A_LSX(R_ev, G_ev, B_ev, a_ev, 3, 6); + WRITE_FULL_A_LSX(R_od, G_od, B_od, a_od, 3, 7); + } else { + WRITE_FULL_LSX(R_ev, G_ev, B_ev, 0, 0); + WRITE_FULL_LSX(R_od, G_od, B_od, 0, 1); + WRITE_FULL_LSX(R_ev, G_ev, B_ev, 1, 2); + WRITE_FULL_LSX(R_od, G_od, B_od, 1, 3); + WRITE_FULL_LSX(R_ev, G_ev, B_ev, 2, 4); + WRITE_FULL_LSX(R_od, G_od, B_od, 2, 5); + WRITE_FULL_LSX(R_ev, G_ev, B_ev, 3, 6); + WRITE_FULL_LSX(R_od, G_od, B_od, 3, 7); + } + } + if (dstW - i >= 4) { + __m128i b, ub0, ub1, vb0, vb1; + __m128i y_l, u_l, v_l; + __m128i R_l, G_l, B_l; + int n = i << 1; + + DUP4_ARG2(__lsx_vldx, buf0, n, ubuf0, n, vbuf0, n, + ubuf1, n, b, ub0, vb0, ub1); + vb1 = __lsx_vldx(vbuf1, n); + y_l = __lsx_vsllwil_w_h(b, 0); + y_l = __lsx_vslli_w(y_l, 2); + DUP4_ARG2(__lsx_vsllwil_w_h, ub0, 0, vb0, 0, ub1, 0, vb1, 0, + ub0, vb0, ub1, vb1); + DUP2_ARG2(__lsx_vadd_w, ub0, ub1, vb0, vb1, u_l, v_l); + u_l = __lsx_vsub_w(u_l, uv); + v_l = __lsx_vsub_w(v_l, uv); + u_l = __lsx_vslli_w(u_l, 1); + v_l = __lsx_vslli_w(v_l, 1); + YUVTORGB_LSX(y_l, u_l, v_l, R_l, G_l, B_l, offset, coeff, + y_temp, v2r, v2g, u2g, u2b); + + if(hasAlpha) { + __m128i a_src; + __m128i a_l; + + a_src = __lsx_vld(abuf0 + i, 0); + a_src = __lsx_vilvl_h(a_src, a_src); + a_l = __lsx_vaddwev_w_h(bias, a_l); + a_l = __lsx_vsrai_w(a_l, 7); + WRITE_FULL_A_LSX(R_l, G_l, B_l, a_l, 0, 0); + WRITE_FULL_A_LSX(R_l, G_l, B_l, a_l, 1, 1); + WRITE_FULL_A_LSX(R_l, G_l, B_l, a_l, 2, 2); + WRITE_FULL_A_LSX(R_l, G_l, B_l, a_l, 3, 3); + } else { + WRITE_FULL_LSX(R_l, G_l, B_l, 0, 0); + WRITE_FULL_LSX(R_l, G_l, B_l, 1, 1); + WRITE_FULL_LSX(R_l, G_l, B_l, 2, 2); + WRITE_FULL_LSX(R_l, G_l, B_l, 3, 3); + } + i += 4; + } + for (; i < dstW; i++) { + int Y = buf0[i] << 2; + int U = (ubuf0[i] + ubuf1[i] - uvtemp) << 1; + int V = (vbuf0[i] + vbuf1[i] - uvtemp) << 1; + + A = 0; + if(hasAlpha) { + A = (abuf0[i] + 64) >> 7; + if (A & 0x100) + A = av_clip_uint8(A); + } + Y -= y_offset; + Y *= y_coeff; + Y += ytemp; + R = (unsigned)Y + V * v2r_coe; + G = (unsigned)Y + V * v2g_coe + U * u2g_coe; + B = (unsigned)Y + U * u2b_coe; + yuv2rgb_write_full(c, dest, i, R, A, G, B, y, target, hasAlpha, err); + dest += step; + } + } + c->dither_error[0][i] = err[0]; + c->dither_error[1][i] = err[1]; + c->dither_error[2][i] = err[2]; +} + +#if CONFIG_SMALL +YUV2RGBWRAPPER(yuv2, rgb_full, bgra32_full, AV_PIX_FMT_BGRA, + CONFIG_SWSCALE_ALPHA && c->needAlpha) +YUV2RGBWRAPPER(yuv2, rgb_full, abgr32_full, AV_PIX_FMT_ABGR, + CONFIG_SWSCALE_ALPHA && c->needAlpha) +YUV2RGBWRAPPER(yuv2, rgb_full, rgba32_full, AV_PIX_FMT_RGBA, + CONFIG_SWSCALE_ALPHA && c->needAlpha) +YUV2RGBWRAPPER(yuv2, rgb_full, argb32_full, AV_PIX_FMT_ARGB, + CONFIG_SWSCALE_ALPHA && c->needAlpha) +#else +#if CONFIG_SWSCALE_ALPHA +YUV2RGBWRAPPER(yuv2, rgb_full, bgra32_full, AV_PIX_FMT_BGRA, 1) +YUV2RGBWRAPPER(yuv2, rgb_full, abgr32_full, AV_PIX_FMT_ABGR, 1) +YUV2RGBWRAPPER(yuv2, rgb_full, rgba32_full, AV_PIX_FMT_RGBA, 1) +YUV2RGBWRAPPER(yuv2, rgb_full, argb32_full, AV_PIX_FMT_ARGB, 1) +#endif +YUV2RGBWRAPPER(yuv2, rgb_full, bgrx32_full, AV_PIX_FMT_BGRA, 0) +YUV2RGBWRAPPER(yuv2, rgb_full, xbgr32_full, AV_PIX_FMT_ABGR, 0) +YUV2RGBWRAPPER(yuv2, rgb_full, rgbx32_full, AV_PIX_FMT_RGBA, 0) +YUV2RGBWRAPPER(yuv2, rgb_full, xrgb32_full, AV_PIX_FMT_ARGB, 0) +#endif +YUV2RGBWRAPPER(yuv2, rgb_full, bgr24_full, AV_PIX_FMT_BGR24, 0) +YUV2RGBWRAPPER(yuv2, rgb_full, rgb24_full, AV_PIX_FMT_RGB24, 0) + +YUV2RGBWRAPPER(yuv2, rgb_full, bgr4_byte_full, AV_PIX_FMT_BGR4_BYTE, 0) +YUV2RGBWRAPPER(yuv2, rgb_full, rgb4_byte_full, AV_PIX_FMT_RGB4_BYTE, 0) +YUV2RGBWRAPPER(yuv2, rgb_full, bgr8_full, AV_PIX_FMT_BGR8, 0) +YUV2RGBWRAPPER(yuv2, rgb_full, rgb8_full, AV_PIX_FMT_RGB8, 0) + + +av_cold void ff_sws_init_output_lsx(SwsContext *c) +{ + if(c->flags & SWS_FULL_CHR_H_INT) { + switch (c->dstFormat) { + case AV_PIX_FMT_RGBA: +#if CONFIG_SMALL + c->yuv2packedX = yuv2rgba32_full_X_lsx; + c->yuv2packed2 = yuv2rgba32_full_2_lsx; + c->yuv2packed1 = yuv2rgba32_full_1_lsx; +#else +#if CONFIG_SWSCALE_ALPHA + if (c->needAlpha) { + c->yuv2packedX = yuv2rgba32_full_X_lsx; + c->yuv2packed2 = yuv2rgba32_full_2_lsx; + c->yuv2packed1 = yuv2rgba32_full_1_lsx; + } else +#endif /* CONFIG_SWSCALE_ALPHA */ + { + c->yuv2packedX = yuv2rgbx32_full_X_lsx; + c->yuv2packed2 = yuv2rgbx32_full_2_lsx; + c->yuv2packed1 = yuv2rgbx32_full_1_lsx; + } +#endif /* !CONFIG_SMALL */ + break; + case AV_PIX_FMT_ARGB: +#if CONFIG_SMALL + c->yuv2packedX = yuv2argb32_full_X_lsx; + c->yuv2packed2 = yuv2argb32_full_2_lsx; + c->yuv2packed1 = yuv2argb32_full_1_lsx; +#else +#if CONFIG_SWSCALE_ALPHA + if (c->needAlpha) { + c->yuv2packedX = yuv2argb32_full_X_lsx; + c->yuv2packed2 = yuv2argb32_full_2_lsx; + c->yuv2packed1 = yuv2argb32_full_1_lsx; + } else +#endif /* CONFIG_SWSCALE_ALPHA */ + { + c->yuv2packedX = yuv2xrgb32_full_X_lsx; + c->yuv2packed2 = yuv2xrgb32_full_2_lsx; + c->yuv2packed1 = yuv2xrgb32_full_1_lsx; + } +#endif /* !CONFIG_SMALL */ + break; + case AV_PIX_FMT_BGRA: +#if CONFIG_SMALL + c->yuv2packedX = yuv2bgra32_full_X_lsx; + c->yuv2packed2 = yuv2bgra32_full_2_lsx; + c->yuv2packed1 = yuv2bgra32_full_1_lsx; +#else +#if CONFIG_SWSCALE_ALPHA + if (c->needAlpha) { + c->yuv2packedX = yuv2bgra32_full_X_lsx; + c->yuv2packed2 = yuv2bgra32_full_2_lsx; + c->yuv2packed1 = yuv2bgra32_full_1_lsx; + } else +#endif /* CONFIG_SWSCALE_ALPHA */ + { + c->yuv2packedX = yuv2bgrx32_full_X_lsx; + c->yuv2packed2 = yuv2bgrx32_full_2_lsx; + c->yuv2packed1 = yuv2bgrx32_full_1_lsx; + } +#endif /* !CONFIG_SMALL */ + break; + case AV_PIX_FMT_ABGR: +#if CONFIG_SMALL + c->yuv2packedX = yuv2abgr32_full_X_lsx; + c->yuv2packed2 = yuv2abgr32_full_2_lsx; + c->yuv2packed1 = yuv2abgr32_full_1_lsx; +#else +#if CONFIG_SWSCALE_ALPHA + if (c->needAlpha) { + c->yuv2packedX = yuv2abgr32_full_X_lsx; + c->yuv2packed2 = yuv2abgr32_full_2_lsx; + c->yuv2packed1 = yuv2abgr32_full_1_lsx; + } else +#endif /* CONFIG_SWSCALE_ALPHA */ + { + c->yuv2packedX = yuv2xbgr32_full_X_lsx; + c->yuv2packed2 = yuv2xbgr32_full_2_lsx; + c->yuv2packed1 = yuv2xbgr32_full_1_lsx; + } +#endif /* !CONFIG_SMALL */ + break; + case AV_PIX_FMT_RGB24: + c->yuv2packedX = yuv2rgb24_full_X_lsx; + c->yuv2packed2 = yuv2rgb24_full_2_lsx; + c->yuv2packed1 = yuv2rgb24_full_1_lsx; + break; + case AV_PIX_FMT_BGR24: + c->yuv2packedX = yuv2bgr24_full_X_lsx; + c->yuv2packed2 = yuv2bgr24_full_2_lsx; + c->yuv2packed1 = yuv2bgr24_full_1_lsx; + break; + case AV_PIX_FMT_BGR4_BYTE: + c->yuv2packedX = yuv2bgr4_byte_full_X_lsx; + c->yuv2packed2 = yuv2bgr4_byte_full_2_lsx; + c->yuv2packed1 = yuv2bgr4_byte_full_1_lsx; + break; + case AV_PIX_FMT_RGB4_BYTE: + c->yuv2packedX = yuv2rgb4_byte_full_X_lsx; + c->yuv2packed2 = yuv2rgb4_byte_full_2_lsx; + c->yuv2packed1 = yuv2rgb4_byte_full_1_lsx; + break; + case AV_PIX_FMT_BGR8: + c->yuv2packedX = yuv2bgr8_full_X_lsx; + c->yuv2packed2 = yuv2bgr8_full_2_lsx; + c->yuv2packed1 = yuv2bgr8_full_1_lsx; + break; + case AV_PIX_FMT_RGB8: + c->yuv2packedX = yuv2rgb8_full_X_lsx; + c->yuv2packed2 = yuv2rgb8_full_2_lsx; + c->yuv2packed1 = yuv2rgb8_full_1_lsx; + break; + } + } else { + switch (c->dstFormat) { + case AV_PIX_FMT_RGB32: + case AV_PIX_FMT_BGR32: +#if CONFIG_SMALL +#else +#if CONFIG_SWSCALE_ALPHA + if (c->needAlpha) { + } else +#endif /* CONFIG_SWSCALE_ALPHA */ + { + c->yuv2packed1 = yuv2rgbx32_1_lsx; + c->yuv2packed2 = yuv2rgbx32_2_lsx; + c->yuv2packedX = yuv2rgbx32_X_lsx; + } +#endif /* !CONFIG_SMALL */ + break; + case AV_PIX_FMT_RGB32_1: + case AV_PIX_FMT_BGR32_1: +#if CONFIG_SMALL +#else +#if CONFIG_SWSCALE_ALPHA + if (c->needAlpha) { + } else +#endif /* CONFIG_SWSCALE_ALPHA */ + { + c->yuv2packed1 = yuv2rgbx32_1_1_lsx; + c->yuv2packed2 = yuv2rgbx32_1_2_lsx; + c->yuv2packedX = yuv2rgbx32_1_X_lsx; + } +#endif /* !CONFIG_SMALL */ + break; + case AV_PIX_FMT_RGB24: + c->yuv2packed1 = yuv2rgb24_1_lsx; + c->yuv2packed2 = yuv2rgb24_2_lsx; + c->yuv2packedX = yuv2rgb24_X_lsx; + break; + case AV_PIX_FMT_BGR24: + c->yuv2packed1 = yuv2bgr24_1_lsx; + c->yuv2packed2 = yuv2bgr24_2_lsx; + c->yuv2packedX = yuv2bgr24_X_lsx; + break; + case AV_PIX_FMT_RGB565LE: + case AV_PIX_FMT_RGB565BE: + case AV_PIX_FMT_BGR565LE: + case AV_PIX_FMT_BGR565BE: + c->yuv2packed1 = yuv2rgb16_1_lsx; + c->yuv2packed2 = yuv2rgb16_2_lsx; + c->yuv2packedX = yuv2rgb16_X_lsx; + break; + case AV_PIX_FMT_RGB555LE: + case AV_PIX_FMT_RGB555BE: + case AV_PIX_FMT_BGR555LE: + case AV_PIX_FMT_BGR555BE: + c->yuv2packed1 = yuv2rgb15_1_lsx; + c->yuv2packed2 = yuv2rgb15_2_lsx; + c->yuv2packedX = yuv2rgb15_X_lsx; + break; + case AV_PIX_FMT_RGB444LE: + case AV_PIX_FMT_RGB444BE: + case AV_PIX_FMT_BGR444LE: + case AV_PIX_FMT_BGR444BE: + c->yuv2packed1 = yuv2rgb12_1_lsx; + c->yuv2packed2 = yuv2rgb12_2_lsx; + c->yuv2packedX = yuv2rgb12_X_lsx; + break; + case AV_PIX_FMT_RGB8: + case AV_PIX_FMT_BGR8: + c->yuv2packed1 = yuv2rgb8_1_lsx; + c->yuv2packed2 = yuv2rgb8_2_lsx; + c->yuv2packedX = yuv2rgb8_X_lsx; + break; + case AV_PIX_FMT_RGB4: + case AV_PIX_FMT_BGR4: + c->yuv2packed1 = yuv2rgb4_1_lsx; + c->yuv2packed2 = yuv2rgb4_2_lsx; + c->yuv2packedX = yuv2rgb4_X_lsx; + break; + case AV_PIX_FMT_RGB4_BYTE: + case AV_PIX_FMT_BGR4_BYTE: + c->yuv2packed1 = yuv2rgb4b_1_lsx; + c->yuv2packed2 = yuv2rgb4b_2_lsx; + c->yuv2packedX = yuv2rgb4b_X_lsx; + break; + } + } +} diff --git a/libswscale/loongarch/swscale.S b/libswscale/loongarch/swscale.S new file mode 100644 index 00000000000..aa4c5cbe280 --- /dev/null +++ b/libswscale/loongarch/swscale.S @@ -0,0 +1,1868 @@ +/* + * Loongson LSX optimized swscale + * + * Copyright (c) 2023 Loongson Technology Corporation Limited + * Contributed by 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 + */ + +#include "libavcodec/loongarch/loongson_asm.S" + +/* void ff_hscale_8_to_15_lsx(SwsContext *c, int16_t *dst, int dstW, + * const uint8_t *src, const int16_t *filter, + * const int32_t *filterPos, int filterSize) + */ +function ff_hscale_8_to_15_lsx + addi.d sp, sp, -72 + st.d s0, sp, 0 + st.d s1, sp, 8 + st.d s2, sp, 16 + st.d s3, sp, 24 + st.d s4, sp, 32 + st.d s5, sp, 40 + st.d s6, sp, 48 + st.d s7, sp, 56 + st.d s8, sp, 64 + li.w t0, 32767 + li.w t8, 8 + li.w t7, 4 + vldi vr0, 0 + vreplgr2vr.w vr20, t0 + beq a6, t7, .LOOP_DSTW4 + beq a6, t8, .LOOP_DSTW8 + blt t8, a6, .LOOP_START + b .END_DSTW4 + +.LOOP_START: + li.w t1, 0 + li.w s1, 0 + li.w s2, 0 + li.w s3, 0 + li.w s4, 0 + li.w s5, 0 + vldi vr22, 0 + addi.w s0, a6, -7 + slli.w s7, a6, 1 + slli.w s8, a6, 2 + add.w t6, s7, s8 +.LOOP_DSTW: + ld.w t2, a5, 0 + ld.w t3, a5, 4 + ld.w t4, a5, 8 + ld.w t5, a5, 12 + fldx.d f1, a3, t2 + fldx.d f2, a3, t3 + fldx.d f3, a3, t4 + fldx.d f4, a3, t5 + vld vr9, a4, 0 + vldx vr10, a4, s7 + vldx vr11, a4, s8 + vldx vr12, a4, t6 + vilvl.b vr1, vr0, vr1 + vilvl.b vr2, vr0, vr2 + vilvl.b vr3, vr0, vr3 + vilvl.b vr4, vr0, vr4 + vdp2.w.h vr17, vr1, vr9 + vdp2.w.h vr18, vr2, vr10 + vdp2.w.h vr19, vr3, vr11 + vdp2.w.h vr21, vr4, vr12 + vhaddw.d.w vr1, vr17, vr17 + vhaddw.d.w vr2, vr18, vr18 + vhaddw.d.w vr3, vr19, vr19 + vhaddw.d.w vr4, vr21, vr21 + vhaddw.q.d vr1, vr1, vr1 + vhaddw.q.d vr2, vr2, vr2 + vhaddw.q.d vr3, vr3, vr3 + vhaddw.q.d vr4, vr4, vr4 + vilvl.w vr1, vr2, vr1 + vilvl.w vr3, vr4, vr3 + vilvl.d vr1, vr3, vr1 + vadd.w vr22, vr22, vr1 + addi.w s1, s1, 8 + addi.d a3, a3, 8 + addi.d a4, a4, 16 + blt s1, s0, .LOOP_DSTW + blt s1, a6, .DSTWA + b .END_FILTER +.DSTWA: + ld.w t2, a5, 0 + li.w t3, 0 + move s6, s1 +.FILTERSIZEA: + add.w t4, t2, t3 + ldx.bu t5, a3, t4 + mul.w t6, a6, t1 + add.w t6, t6, t3 + slli.w t6, t6, 1 + ldx.h t6, a4, t6 + mul.w t6, t5, t6 + add.w s2, s2, t6 + addi.w t3, t3, 1 + addi.w s6, s6, 1 + blt s6, a6, .FILTERSIZEA + + ld.w t2, a5, 4 + li.w t3, 0 + move s6, s1 + addi.w t1, t1, 1 +.FILTERSIZEB: + add.w t4, t2, t3 + ldx.bu t5, a3, t4 + mul.w t6, a6, t1 + add.w t6, t6, t3 + slli.w t6, t6, 1 + ldx.h t6, a4, t6 + mul.w t6, t5, t6 + add.w s3, s3, t6 + addi.w t3, t3, 1 + addi.w s6, s6, 1 + blt s6, a6, .FILTERSIZEB + ld.w t2, a5, 8 + addi.w t1, t1, 1 + li.w t3, 0 + move s6, s1 +.FILTERSIZEC: + add.w t4, t2, t3 + ldx.bu t5, a3, t4 + mul.w t6, a6, t1 + add.w t6, t6, t3 + slli.w t6, t6, 1 + ldx.h t6, a4, t6 + mul.w t6, t5, t6 + add.w s4, s4, t6 + addi.w t3, t3, 1 + addi.w s6, s6, 1 + blt s6, a6, .FILTERSIZEC + ld.w t2, a5, 12 + addi.w t1, t1, 1 + move s6, s1 + li.w t3, 0 +.FILTERSIZED: + add.w t4, t2, t3 + ldx.bu t5, a3, t4 + mul.w t6, a6, t1 + add.w t6, t6, t3 + slli.w t6, t6, 1 + ldx.h t6, a4, t6 + mul.w t6, t5, t6 + add.w s5, s5, t6 + addi.w t3, t3, 1 + addi.w s6, s6, 1 + blt s6, a6, .FILTERSIZED +.END_FILTER: + vpickve2gr.w t1, vr22, 0 + vpickve2gr.w t2, vr22, 1 + vpickve2gr.w t3, vr22, 2 + vpickve2gr.w t4, vr22, 3 + add.w s2, s2, t1 + add.w s3, s3, t2 + add.w s4, s4, t3 + add.w s5, s5, t4 + srai.w s2, s2, 7 + srai.w s3, s3, 7 + srai.w s4, s4, 7 + srai.w s5, s5, 7 + slt t1, s2, t0 + slt t2, s3, t0 + slt t3, s4, t0 + slt t4, s5, t0 + maskeqz s2, s2, t1 + maskeqz s3, s3, t2 + maskeqz s4, s4, t3 + maskeqz s5, s5, t4 + masknez t1, t0, t1 + masknez t2, t0, t2 + masknez t3, t0, t3 + masknez t4, t0, t4 + or s2, s2, t1 + or s3, s3, t2 + or s4, s4, t3 + or s5, s5, t4 + st.h s2, a1, 0 + st.h s3, a1, 2 + st.h s4, a1, 4 + st.h s5, a1, 6 + + addi.d a1, a1, 8 + sub.d a3, a3, s1 + addi.d a5, a5, 16 + slli.d t3, a6, 3 + add.d a4, a4, t3 + sub.d a4, a4, s1 + sub.d a4, a4, s1 + addi.d a2, a2, -4 + bge a2, t7, .LOOP_START + blt zero, a2, .RES + b .END_LOOP +.RES: + li.w t1, 0 +.DSTW: + slli.w t2, t1, 2 + ldx.w t2, a5, t2 + li.w t3, 0 + li.w t8, 0 +.FILTERSIZE: + add.w t4, t2, t3 + ldx.bu t5, a3, t4 + mul.w t6, a6, t1 + add.w t6, t6, t3 + slli.w t7, t6, 1 + ldx.h t7, a4, t7 + mul.w t7, t5, t7 + add.w t8, t8, t7 + addi.w t3, t3, 1 + blt t3, a6, .FILTERSIZE + srai.w t8, t8, 7 + slt t5, t8, t0 + maskeqz t8, t8, t5 + masknez t5, t0, t5 + or t8, t8, t5 + slli.w t4, t1, 1 + stx.h t8, a1, t4 + addi.w t1, t1, 1 + blt t1, a2, .DSTW + b .END_LOOP + +.LOOP_DSTW8: + ld.w t1, a5, 0 + ld.w t2, a5, 4 + ld.w t3, a5, 8 + ld.w t4, a5, 12 + fldx.d f1, a3, t1 + fldx.d f2, a3, t2 + fldx.d f3, a3, t3 + fldx.d f4, a3, t4 + ld.w t1, a5, 16 + ld.w t2, a5, 20 + ld.w t3, a5, 24 + ld.w t4, a5, 28 + fldx.d f5, a3, t1 + fldx.d f6, a3, t2 + fldx.d f7, a3, t3 + fldx.d f8, a3, t4 + vld vr9, a4, 0 + vld vr10, a4, 16 + vld vr11, a4, 32 + vld vr12, a4, 48 + vld vr13, a4, 64 + vld vr14, a4, 80 + vld vr15, a4, 96 + vld vr16, a4, 112 + vilvl.b vr1, vr0, vr1 + vilvl.b vr2, vr0, vr2 + vilvl.b vr3, vr0, vr3 + vilvl.b vr4, vr0, vr4 + vilvl.b vr5, vr0, vr5 + vilvl.b vr6, vr0, vr6 + vilvl.b vr7, vr0, vr7 + vilvl.b vr8, vr0, vr8 + + vdp2.w.h vr17, vr1, vr9 + vdp2.w.h vr18, vr2, vr10 + vdp2.w.h vr19, vr3, vr11 + vdp2.w.h vr21, vr4, vr12 + vdp2.w.h vr1, vr5, vr13 + vdp2.w.h vr2, vr6, vr14 + vdp2.w.h vr3, vr7, vr15 + vdp2.w.h vr4, vr8, vr16 + vhaddw.d.w vr5, vr1, vr1 + vhaddw.d.w vr6, vr2, vr2 + vhaddw.d.w vr7, vr3, vr3 + vhaddw.d.w vr8, vr4, vr4 + vhaddw.d.w vr1, vr17, vr17 + vhaddw.d.w vr2, vr18, vr18 + vhaddw.d.w vr3, vr19, vr19 + vhaddw.d.w vr4, vr21, vr21 + vhaddw.q.d vr1, vr1, vr1 + vhaddw.q.d vr2, vr2, vr2 + vhaddw.q.d vr3, vr3, vr3 + vhaddw.q.d vr4, vr4, vr4 + vhaddw.q.d vr5, vr5, vr5 + vhaddw.q.d vr6, vr6, vr6 + vhaddw.q.d vr7, vr7, vr7 + vhaddw.q.d vr8, vr8, vr8 + vilvl.w vr1, vr2, vr1 + vilvl.w vr3, vr4, vr3 + vilvl.w vr5, vr6, vr5 + vilvl.w vr7, vr8, vr7 + vilvl.d vr1, vr3, vr1 + vilvl.d vr5, vr7, vr5 + vsrai.w vr1, vr1, 7 + vsrai.w vr5, vr5, 7 + vmin.w vr1, vr1, vr20 + vmin.w vr5, vr5, vr20 + + vpickev.h vr1, vr5, vr1 + vst vr1, a1, 0 + addi.d a1, a1, 16 + addi.d a5, a5, 32 + addi.d a4, a4, 128 + addi.d a2, a2, -8 + bge a2, t8, .LOOP_DSTW8 + blt zero, a2, .RES8 + b .END_LOOP +.RES8: + li.w t1, 0 +.DSTW8: + slli.w t2, t1, 2 + ldx.w t2, a5, t2 + li.w t3, 0 + li.w t8, 0 +.FILTERSIZE8: + add.w t4, t2, t3 + ldx.bu t5, a3, t4 + mul.w t6, a6, t1 + add.w t6, t6, t3 + slli.w t7, t6, 1 + ldx.h t7, a4, t7 + mul.w t7, t5, t7 + add.w t8, t8, t7 + addi.w t3, t3, 1 + blt t3, a6, .FILTERSIZE8 + srai.w t8, t8, 7 + slt t5, t8, t0 + maskeqz t8, t8, t5 + masknez t5, t0, t5 + or t8, t8, t5 + slli.w t4, t1, 1 + stx.h t8, a1, t4 + addi.w t1, t1, 1 + blt t1, a2, .DSTW8 + b .END_LOOP + +.LOOP_DSTW4: + ld.w t1, a5, 0 + ld.w t2, a5, 4 + ld.w t3, a5, 8 + ld.w t4, a5, 12 + fldx.s f1, a3, t1 + fldx.s f2, a3, t2 + fldx.s f3, a3, t3 + fldx.s f4, a3, t4 + ld.w t1, a5, 16 + ld.w t2, a5, 20 + ld.w t3, a5, 24 + ld.w t4, a5, 28 + fldx.s f5, a3, t1 + fldx.s f6, a3, t2 + fldx.s f7, a3, t3 + fldx.s f8, a3, t4 + vld vr9, a4, 0 + vld vr10, a4, 16 + vld vr11, a4, 32 + vld vr12, a4, 48 + vilvl.w vr1, vr2, vr1 + vilvl.w vr3, vr4, vr3 + vilvl.w vr5, vr6, vr5 + vilvl.w vr7, vr8, vr7 + vilvl.b vr1, vr0, vr1 + vilvl.b vr3, vr0, vr3 + vilvl.b vr5, vr0, vr5 + vilvl.b vr7, vr0, vr7 + + vdp2.w.h vr13, vr1, vr9 + vdp2.w.h vr14, vr3, vr10 + vdp2.w.h vr15, vr5, vr11 + vdp2.w.h vr16, vr7, vr12 + vhaddw.d.w vr13, vr13, vr13 + vhaddw.d.w vr14, vr14, vr14 + vhaddw.d.w vr15, vr15, vr15 + vhaddw.d.w vr16, vr16, vr16 + vpickev.w vr13, vr14, vr13 + vpickev.w vr15, vr16, vr15 + vsrai.w vr13, vr13, 7 + vsrai.w vr15, vr15, 7 + vmin.w vr13, vr13, vr20 + vmin.w vr15, vr15, vr20 + + vpickev.h vr13, vr15, vr13 + vst vr13, a1, 0 + addi.d a1, a1, 16 + addi.d a5, a5, 32 + addi.d a4, a4, 64 + addi.d a2, a2, -8 + bge a2, t8, .LOOP_DSTW4 + blt zero, a2, .RES4 + b .END_LOOP +.RES4: + li.w t1, 0 +.DSTW4: + slli.w t2, t1, 2 + ldx.w t2, a5, t2 + li.w t3, 0 + li.w t8, 0 +.FILTERSIZE4: + add.w t4, t2, t3 + ldx.bu t5, a3, t4 + mul.w t6, a6, t1 + add.w t6, t6, t3 + slli.w t7, t6, 1 + ldx.h t7, a4, t7 + mul.w t7, t5, t7 + add.w t8, t8, t7 + addi.w t3, t3, 1 + blt t3, a6, .FILTERSIZE4 + srai.w t8, t8, 7 + slt t5, t8, t0 + maskeqz t8, t8, t5 + masknez t5, t0, t5 + or t8, t8, t5 + slli.w t4, t1, 1 + stx.h t8, a1, t4 + addi.w t1, t1, 1 + blt t1, a2, .DSTW4 + b .END_LOOP +.END_DSTW4: + + li.w t1, 0 +.LOOP_DSTW1: + slli.w t2, t1, 2 + ldx.w t2, a5, t2 + li.w t3, 0 + li.w t8, 0 +.FILTERSIZE1: + add.w t4, t2, t3 + ldx.bu t5, a3, t4 + mul.w t6, a6, t1 + add.w t6, t6, t3 + slli.w t7, t6, 1 + ldx.h t7, a4, t7 + mul.w t7, t5, t7 + add.w t8, t8, t7 + addi.w t3, t3, 1 + blt t3, a6, .FILTERSIZE1 + srai.w t8, t8, 7 + slt t5, t8, t0 + maskeqz t8, t8, t5 + masknez t5, t0, t5 + or t8, t8, t5 + slli.w t4, t1, 1 + stx.h t8, a1, t4 + addi.w t1, t1, 1 + blt t1, a2, .LOOP_DSTW1 + b .END_LOOP +.END_LOOP: + + ld.d s0, sp, 0 + ld.d s1, sp, 8 + ld.d s2, sp, 16 + ld.d s3, sp, 24 + ld.d s4, sp, 32 + ld.d s5, sp, 40 + ld.d s6, sp, 48 + ld.d s7, sp, 56 + ld.d s8, sp, 64 + addi.d sp, sp, 72 +endfunc + +/* void ff_hscale_8_to_19_lsx(SwsContext *c, int16_t *dst, int dstW, + * const uint8_t *src, const int16_t *filter, + * const int32_t *filterPos, int filterSize) + */ +function ff_hscale_8_to_19_lsx + addi.d sp, sp, -72 + st.d s0, sp, 0 + st.d s1, sp, 8 + st.d s2, sp, 16 + st.d s3, sp, 24 + st.d s4, sp, 32 + st.d s5, sp, 40 + st.d s6, sp, 48 + st.d s7, sp, 56 + st.d s8, sp, 64 + li.w t0, 524287 + li.w t8, 8 + li.w t7, 4 + vldi vr0, 0 + vreplgr2vr.w vr20, t0 + beq a6, t7, .LOOP_DST4 + beq a6, t8, .LOOP_DST8 + blt t8, a6, .LOOP + b .END_DST4 + +.LOOP: + li.w t1, 0 + li.w s1, 0 + li.w s2, 0 + li.w s3, 0 + li.w s4, 0 + li.w s5, 0 + vldi vr22, 0 + addi.w s0, a6, -7 + slli.w s7, a6, 1 + slli.w s8, a6, 2 + add.w t6, s7, s8 +.LOOP_DST: + ld.w t2, a5, 0 + ld.w t3, a5, 4 + ld.w t4, a5, 8 + ld.w t5, a5, 12 + fldx.d f1, a3, t2 + fldx.d f2, a3, t3 + fldx.d f3, a3, t4 + fldx.d f4, a3, t5 + vld vr9, a4, 0 + vldx vr10, a4, s7 + vldx vr11, a4, s8 + vldx vr12, a4, t6 + vilvl.b vr1, vr0, vr1 + vilvl.b vr2, vr0, vr2 + vilvl.b vr3, vr0, vr3 + vilvl.b vr4, vr0, vr4 + vdp2.w.h vr17, vr1, vr9 + vdp2.w.h vr18, vr2, vr10 + vdp2.w.h vr19, vr3, vr11 + vdp2.w.h vr21, vr4, vr12 + vhaddw.d.w vr1, vr17, vr17 + vhaddw.d.w vr2, vr18, vr18 + vhaddw.d.w vr3, vr19, vr19 + vhaddw.d.w vr4, vr21, vr21 + vhaddw.q.d vr1, vr1, vr1 + vhaddw.q.d vr2, vr2, vr2 + vhaddw.q.d vr3, vr3, vr3 + vhaddw.q.d vr4, vr4, vr4 + vilvl.w vr1, vr2, vr1 + vilvl.w vr3, vr4, vr3 + vilvl.d vr1, vr3, vr1 + vadd.w vr22, vr22, vr1 + addi.w s1, s1, 8 + addi.d a3, a3, 8 + addi.d a4, a4, 16 + blt s1, s0, .LOOP_DST + blt s1, a6, .DSTA + b .END_FILTERA +.DSTA: + ld.w t2, a5, 0 + li.w t3, 0 + move s6, s1 +.FILTERA: + add.w t4, t2, t3 + ldx.bu t5, a3, t4 + mul.w t6, a6, t1 + add.w t6, t6, t3 + slli.w t6, t6, 1 + ldx.h t6, a4, t6 + mul.w t6, t5, t6 + add.w s2, s2, t6 + addi.w t3, t3, 1 + addi.w s6, s6, 1 + blt s6, a6, .FILTERA + + ld.w t2, a5, 4 + li.w t3, 0 + move s6, s1 + addi.w t1, t1, 1 +.FILTERB: + add.w t4, t2, t3 + ldx.bu t5, a3, t4 + mul.w t6, a6, t1 + add.w t6, t6, t3 + slli.w t6, t6, 1 + ldx.h t6, a4, t6 + mul.w t6, t5, t6 + add.w s3, s3, t6 + addi.w t3, t3, 1 + addi.w s6, s6, 1 + blt s6, a6, .FILTERB + ld.w t2, a5, 8 + addi.w t1, t1, 1 + li.w t3, 0 + move s6, s1 +.FILTERC: + add.w t4, t2, t3 + ldx.bu t5, a3, t4 + mul.w t6, a6, t1 + add.w t6, t6, t3 + slli.w t6, t6, 1 + ldx.h t6, a4, t6 + mul.w t6, t5, t6 + add.w s4, s4, t6 + addi.w t3, t3, 1 + addi.w s6, s6, 1 + blt s6, a6, .FILTERC + ld.w t2, a5, 12 + addi.w t1, t1, 1 + move s6, s1 + li.w t3, 0 +.FILTERD: + add.w t4, t2, t3 + ldx.bu t5, a3, t4 + mul.w t6, a6, t1 + add.w t6, t6, t3 + slli.w t6, t6, 1 + ldx.h t6, a4, t6 + mul.w t6, t5, t6 + add.w s5, s5, t6 + addi.w t3, t3, 1 + addi.w s6, s6, 1 + blt s6, a6, .FILTERD +.END_FILTERA: + vpickve2gr.w t1, vr22, 0 + vpickve2gr.w t2, vr22, 1 + vpickve2gr.w t3, vr22, 2 + vpickve2gr.w t4, vr22, 3 + add.w s2, s2, t1 + add.w s3, s3, t2 + add.w s4, s4, t3 + add.w s5, s5, t4 + srai.w s2, s2, 3 + srai.w s3, s3, 3 + srai.w s4, s4, 3 + srai.w s5, s5, 3 + slt t1, s2, t0 + slt t2, s3, t0 + slt t3, s4, t0 + slt t4, s5, t0 + maskeqz s2, s2, t1 + maskeqz s3, s3, t2 + maskeqz s4, s4, t3 + maskeqz s5, s5, t4 + masknez t1, t0, t1 + masknez t2, t0, t2 + masknez t3, t0, t3 + masknez t4, t0, t4 + or s2, s2, t1 + or s3, s3, t2 + or s4, s4, t3 + or s5, s5, t4 + st.w s2, a1, 0 + st.w s3, a1, 4 + st.w s4, a1, 8 + st.w s5, a1, 12 + + addi.d a1, a1, 16 + sub.d a3, a3, s1 + addi.d a5, a5, 16 + slli.d t3, a6, 3 + add.d a4, a4, t3 + sub.d a4, a4, s1 + sub.d a4, a4, s1 + addi.d a2, a2, -4 + bge a2, t7, .LOOP + blt zero, a2, .RESA + b .END +.RESA: + li.w t1, 0 +.DST: + slli.w t2, t1, 2 + ldx.w t2, a5, t2 + li.w t3, 0 + li.w t8, 0 +.FILTER: + add.w t4, t2, t3 + ldx.bu t5, a3, t4 + mul.w t6, a6, t1 + add.w t6, t6, t3 + slli.w t7, t6, 1 + ldx.h t7, a4, t7 + mul.w t7, t5, t7 + add.w t8, t8, t7 + addi.w t3, t3, 1 + blt t3, a6, .FILTER + srai.w t8, t8, 3 + slt t5, t8, t0 + maskeqz t8, t8, t5 + masknez t5, t0, t5 + or t8, t8, t5 + slli.w t4, t1, 2 + stx.w t8, a1, t4 + addi.w t1, t1, 1 + blt t1, a2, .DST + b .END + +.LOOP_DST8: + ld.w t1, a5, 0 + ld.w t2, a5, 4 + ld.w t3, a5, 8 + ld.w t4, a5, 12 + fldx.d f1, a3, t1 + fldx.d f2, a3, t2 + fldx.d f3, a3, t3 + fldx.d f4, a3, t4 + ld.w t1, a5, 16 + ld.w t2, a5, 20 + ld.w t3, a5, 24 + ld.w t4, a5, 28 + fldx.d f5, a3, t1 + fldx.d f6, a3, t2 + fldx.d f7, a3, t3 + fldx.d f8, a3, t4 + vld vr9, a4, 0 + vld vr10, a4, 16 + vld vr11, a4, 32 + vld vr12, a4, 48 + vld vr13, a4, 64 + vld vr14, a4, 80 + vld vr15, a4, 96 + vld vr16, a4, 112 + vilvl.b vr1, vr0, vr1 + vilvl.b vr2, vr0, vr2 + vilvl.b vr3, vr0, vr3 + vilvl.b vr4, vr0, vr4 + vilvl.b vr5, vr0, vr5 + vilvl.b vr6, vr0, vr6 + vilvl.b vr7, vr0, vr7 + vilvl.b vr8, vr0, vr8 + + vdp2.w.h vr17, vr1, vr9 + vdp2.w.h vr18, vr2, vr10 + vdp2.w.h vr19, vr3, vr11 + vdp2.w.h vr21, vr4, vr12 + vdp2.w.h vr1, vr5, vr13 + vdp2.w.h vr2, vr6, vr14 + vdp2.w.h vr3, vr7, vr15 + vdp2.w.h vr4, vr8, vr16 + vhaddw.d.w vr5, vr1, vr1 + vhaddw.d.w vr6, vr2, vr2 + vhaddw.d.w vr7, vr3, vr3 + vhaddw.d.w vr8, vr4, vr4 + vhaddw.d.w vr1, vr17, vr17 + vhaddw.d.w vr2, vr18, vr18 + vhaddw.d.w vr3, vr19, vr19 + vhaddw.d.w vr4, vr21, vr21 + vhaddw.q.d vr1, vr1, vr1 + vhaddw.q.d vr2, vr2, vr2 + vhaddw.q.d vr3, vr3, vr3 + vhaddw.q.d vr4, vr4, vr4 + vhaddw.q.d vr5, vr5, vr5 + vhaddw.q.d vr6, vr6, vr6 + vhaddw.q.d vr7, vr7, vr7 + vhaddw.q.d vr8, vr8, vr8 + vilvl.w vr1, vr2, vr1 + vilvl.w vr3, vr4, vr3 + vilvl.w vr5, vr6, vr5 + vilvl.w vr7, vr8, vr7 + vilvl.d vr1, vr3, vr1 + vilvl.d vr5, vr7, vr5 + vsrai.w vr1, vr1, 3 + vsrai.w vr5, vr5, 3 + vmin.w vr1, vr1, vr20 + vmin.w vr5, vr5, vr20 + + vst vr1, a1, 0 + vst vr5, a1, 16 + addi.d a1, a1, 32 + addi.d a5, a5, 32 + addi.d a4, a4, 128 + addi.d a2, a2, -8 + bge a2, t8, .LOOP_DST8 + blt zero, a2, .REST8 + b .END +.REST8: + li.w t1, 0 +.DST8: + slli.w t2, t1, 2 + ldx.w t2, a5, t2 + li.w t3, 0 + li.w t8, 0 +.FILTER8: + add.w t4, t2, t3 + ldx.bu t5, a3, t4 + mul.w t6, a6, t1 + add.w t6, t6, t3 + slli.w t7, t6, 1 + ldx.h t7, a4, t7 + mul.w t7, t5, t7 + add.w t8, t8, t7 + addi.w t3, t3, 1 + blt t3, a6, .FILTER8 + srai.w t8, t8, 3 + slt t5, t8, t0 + maskeqz t8, t8, t5 + masknez t5, t0, t5 + or t8, t8, t5 + slli.w t4, t1, 2 + stx.w t8, a1, t4 + addi.w t1, t1, 1 + blt t1, a2, .DST8 + b .END + +.LOOP_DST4: + ld.w t1, a5, 0 + ld.w t2, a5, 4 + ld.w t3, a5, 8 + ld.w t4, a5, 12 + fldx.s f1, a3, t1 + fldx.s f2, a3, t2 + fldx.s f3, a3, t3 + fldx.s f4, a3, t4 + ld.w t1, a5, 16 + ld.w t2, a5, 20 + ld.w t3, a5, 24 + ld.w t4, a5, 28 + fldx.s f5, a3, t1 + fldx.s f6, a3, t2 + fldx.s f7, a3, t3 + fldx.s f8, a3, t4 + vld vr9, a4, 0 + vld vr10, a4, 16 + vld vr11, a4, 32 + vld vr12, a4, 48 + vilvl.w vr1, vr2, vr1 + vilvl.w vr3, vr4, vr3 + vilvl.w vr5, vr6, vr5 + vilvl.w vr7, vr8, vr7 + vilvl.b vr1, vr0, vr1 + vilvl.b vr3, vr0, vr3 + vilvl.b vr5, vr0, vr5 + vilvl.b vr7, vr0, vr7 + + vdp2.w.h vr13, vr1, vr9 + vdp2.w.h vr14, vr3, vr10 + vdp2.w.h vr15, vr5, vr11 + vdp2.w.h vr16, vr7, vr12 + vhaddw.d.w vr13, vr13, vr13 + vhaddw.d.w vr14, vr14, vr14 + vhaddw.d.w vr15, vr15, vr15 + vhaddw.d.w vr16, vr16, vr16 + vpickev.w vr13, vr14, vr13 + vpickev.w vr15, vr16, vr15 + vsrai.w vr13, vr13, 3 + vsrai.w vr15, vr15, 3 + vmin.w vr13, vr13, vr20 + vmin.w vr15, vr15, vr20 + + vst vr13, a1, 0 + vst vr15, a1, 16 + addi.d a1, a1, 32 + addi.d a5, a5, 32 + addi.d a4, a4, 64 + addi.d a2, a2, -8 + bge a2, t8, .LOOP_DST4 + blt zero, a2, .REST4 + b .END +.REST4: + li.w t1, 0 +.DST4: + slli.w t2, t1, 2 + ldx.w t2, a5, t2 + li.w t3, 0 + li.w t8, 0 +.FILTER4: + add.w t4, t2, t3 + ldx.bu t5, a3, t4 + mul.w t6, a6, t1 + add.w t6, t6, t3 + slli.w t7, t6, 1 + ldx.h t7, a4, t7 + mul.w t7, t5, t7 + add.w t8, t8, t7 + addi.w t3, t3, 1 + blt t3, a6, .FILTER4 + srai.w t8, t8, 3 + slt t5, t8, t0 + maskeqz t8, t8, t5 + masknez t5, t0, t5 + or t8, t8, t5 + slli.w t4, t1, 2 + stx.w t8, a1, t4 + addi.w t1, t1, 1 + blt t1, a2, .DST4 + b .END +.END_DST4: + + li.w t1, 0 +.LOOP_DST1: + slli.w t2, t1, 2 + ldx.w t2, a5, t2 + li.w t3, 0 + li.w t8, 0 +.FILTER1: + add.w t4, t2, t3 + ldx.bu t5, a3, t4 + mul.w t6, a6, t1 + add.w t6, t6, t3 + slli.w t7, t6, 1 + ldx.h t7, a4, t7 + mul.w t7, t5, t7 + add.w t8, t8, t7 + addi.w t3, t3, 1 + blt t3, a6, .FILTER1 + srai.w t8, t8, 3 + slt t5, t8, t0 + maskeqz t8, t8, t5 + masknez t5, t0, t5 + or t8, t8, t5 + slli.w t4, t1, 2 + stx.w t8, a1, t4 + addi.w t1, t1, 1 + blt t1, a2, .LOOP_DST1 + b .END +.END: + + ld.d s0, sp, 0 + ld.d s1, sp, 8 + ld.d s2, sp, 16 + ld.d s3, sp, 24 + ld.d s4, sp, 32 + ld.d s5, sp, 40 + ld.d s6, sp, 48 + ld.d s7, sp, 56 + ld.d s8, sp, 64 + addi.d sp, sp, 72 +endfunc + +/* void ff_hscale_16_to_15_sub_lsx(SwsContext *c, int16_t *dst, int dstW, + * const uint8_t *src, const int16_t *filter, + * const int32_t *filterPos, int filterSize, int sh) + */ +function ff_hscale_16_to_15_sub_lsx + addi.d sp, sp, -72 + st.d s0, sp, 0 + st.d s1, sp, 8 + st.d s2, sp, 16 + st.d s3, sp, 24 + st.d s4, sp, 32 + st.d s5, sp, 40 + st.d s6, sp, 48 + st.d s7, sp, 56 + st.d s8, sp, 64 + li.w t0, 32767 + li.w t8, 8 + li.w t7, 4 + vreplgr2vr.w vr20, t0 + vreplgr2vr.w vr0, a7 + beq a6, t7, .LOOP_HS15_DST4 + beq a6, t8, .LOOP_HS15_DST8 + blt t8, a6, .LOOP_HS15 + b .END_HS15_DST4 + +.LOOP_HS15: + li.w t1, 0 + li.w s1, 0 + li.w s2, 0 + li.w s3, 0 + li.w s4, 0 + li.w s5, 0 + vldi vr22, 0 + addi.w s0, a6, -7 + slli.w s7, a6, 1 + slli.w s8, a6, 2 + add.w t6, s7, s8 +.LOOP_HS15_DST: + ld.w t2, a5, 0 + ld.w t3, a5, 4 + ld.w t4, a5, 8 + ld.w t5, a5, 12 + slli.w t2, t2, 1 + slli.w t3, t3, 1 + slli.w t4, t4, 1 + slli.w t5, t5, 1 + vldx vr1, a3, t2 + vldx vr2, a3, t3 + vldx vr3, a3, t4 + vldx vr4, a3, t5 + vld vr9, a4, 0 + vldx vr10, a4, s7 + vldx vr11, a4, s8 + vldx vr12, a4, t6 + vmulwev.w.hu.h vr17, vr1, vr9 + vmulwev.w.hu.h vr18, vr2, vr10 + vmulwev.w.hu.h vr19, vr3, vr11 + vmulwev.w.hu.h vr21, vr4, vr12 + vmaddwod.w.hu.h vr17, vr1, vr9 + vmaddwod.w.hu.h vr18, vr2, vr10 + vmaddwod.w.hu.h vr19, vr3, vr11 + vmaddwod.w.hu.h vr21, vr4, vr12 + vhaddw.d.w vr1, vr17, vr17 + vhaddw.d.w vr2, vr18, vr18 + vhaddw.d.w vr3, vr19, vr19 + vhaddw.d.w vr4, vr21, vr21 + vhaddw.q.d vr1, vr1, vr1 + vhaddw.q.d vr2, vr2, vr2 + vhaddw.q.d vr3, vr3, vr3 + vhaddw.q.d vr4, vr4, vr4 + vilvl.w vr1, vr2, vr1 + vilvl.w vr3, vr4, vr3 + vilvl.d vr1, vr3, vr1 + vadd.w vr22, vr22, vr1 + addi.w s1, s1, 8 + addi.d a3, a3, 16 + addi.d a4, a4, 16 + blt s1, s0, .LOOP_HS15_DST + blt s1, a6, .HS15_DSTA + b .END_HS15_FILTERA +.HS15_DSTA: + ld.w t2, a5, 0 + li.w t3, 0 + move s6, s1 +.HS15_FILTERA: + add.w t4, t2, t3 + slli.w t4, t4, 1 + ldx.hu t5, a3, t4 + mul.w t6, a6, t1 + add.w t6, t6, t3 + slli.w t6, t6, 1 + ldx.h t6, a4, t6 + mul.w t6, t5, t6 + add.w s2, s2, t6 + addi.w t3, t3, 1 + addi.w s6, s6, 1 + blt s6, a6, .HS15_FILTERA + + ld.w t2, a5, 4 + li.w t3, 0 + move s6, s1 + addi.w t1, t1, 1 +.HS15_FILTERB: + add.w t4, t2, t3 + slli.w t4, t4, 1 + ldx.hu t5, a3, t4 + mul.w t6, a6, t1 + add.w t6, t6, t3 + slli.w t6, t6, 1 + ldx.h t6, a4, t6 + mul.w t6, t5, t6 + add.w s3, s3, t6 + addi.w t3, t3, 1 + addi.w s6, s6, 1 + blt s6, a6, .HS15_FILTERB + ld.w t2, a5, 8 + addi.w t1, t1, 1 + li.w t3, 0 + move s6, s1 +.HS15_FILTERC: + add.w t4, t2, t3 + slli.w t4, t4, 1 + ldx.hu t5, a3, t4 + mul.w t6, a6, t1 + add.w t6, t6, t3 + slli.w t6, t6, 1 + ldx.h t6, a4, t6 + mul.w t6, t5, t6 + add.w s4, s4, t6 + addi.w t3, t3, 1 + addi.w s6, s6, 1 + blt s6, a6, .HS15_FILTERC + ld.w t2, a5, 12 + addi.w t1, t1, 1 + move s6, s1 + li.w t3, 0 +.HS15_FILTERD: + add.w t4, t2, t3 + slli.w t4, t4, 1 + ldx.hu t5, a3, t4 + mul.w t6, a6, t1 + add.w t6, t6, t3 + slli.w t6, t6, 1 + ldx.h t6, a4, t6 + mul.w t6, t5, t6 + add.w s5, s5, t6 + addi.w t3, t3, 1 + addi.w s6, s6, 1 + blt s6, a6, .HS15_FILTERD +.END_HS15_FILTERA: + vpickve2gr.w t1, vr22, 0 + vpickve2gr.w t2, vr22, 1 + vpickve2gr.w t3, vr22, 2 + vpickve2gr.w t4, vr22, 3 + add.w s2, s2, t1 + add.w s3, s3, t2 + add.w s4, s4, t3 + add.w s5, s5, t4 + sra.w s2, s2, a7 + sra.w s3, s3, a7 + sra.w s4, s4, a7 + sra.w s5, s5, a7 + slt t1, s2, t0 + slt t2, s3, t0 + slt t3, s4, t0 + slt t4, s5, t0 + maskeqz s2, s2, t1 + maskeqz s3, s3, t2 + maskeqz s4, s4, t3 + maskeqz s5, s5, t4 + masknez t1, t0, t1 + masknez t2, t0, t2 + masknez t3, t0, t3 + masknez t4, t0, t4 + or s2, s2, t1 + or s3, s3, t2 + or s4, s4, t3 + or s5, s5, t4 + st.h s2, a1, 0 + st.h s3, a1, 2 + st.h s4, a1, 4 + st.h s5, a1, 6 + + addi.d a1, a1, 8 + sub.d a3, a3, s1 + sub.d a3, a3, s1 + addi.d a5, a5, 16 + slli.d t3, a6, 3 + add.d a4, a4, t3 + sub.d a4, a4, s1 + sub.d a4, a4, s1 + addi.d a2, a2, -4 + bge a2, t7, .LOOP_HS15 + blt zero, a2, .HS15_RESA + b .HS15_END +.HS15_RESA: + li.w t1, 0 +.HS15_DST: + slli.w t2, t1, 2 + ldx.w t2, a5, t2 + li.w t3, 0 + li.w t8, 0 +.HS15_FILTER: + add.w t4, t2, t3 + slli.w t4, t4, 1 + ldx.hu t5, a3, t4 + mul.w t6, a6, t1 + add.w t6, t6, t3 + slli.w t7, t6, 1 + ldx.h t7, a4, t7 + mul.w t7, t5, t7 + add.w t8, t8, t7 + addi.w t3, t3, 1 + blt t3, a6, .HS15_FILTER + sra.w t8, t8, a7 + slt t5, t8, t0 + maskeqz t8, t8, t5 + masknez t5, t0, t5 + or t8, t8, t5 + slli.w t4, t1, 1 + stx.h t8, a1, t4 + addi.w t1, t1, 1 + blt t1, a2, .HS15_DST + b .HS15_END + +.LOOP_HS15_DST8: + ld.w t1, a5, 0 + ld.w t2, a5, 4 + ld.w t3, a5, 8 + ld.w t4, a5, 12 + slli.w t1, t1, 1 + slli.w t2, t2, 1 + slli.w t3, t3, 1 + slli.w t4, t4, 1 + vldx vr1, a3, t1 + vldx vr2, a3, t2 + vldx vr3, a3, t3 + vldx vr4, a3, t4 + ld.w t1, a5, 16 + ld.w t2, a5, 20 + ld.w t3, a5, 24 + ld.w t4, a5, 28 + slli.w t1, t1, 1 + slli.w t2, t2, 1 + slli.w t3, t3, 1 + slli.w t4, t4, 1 + vldx vr5, a3, t1 + vldx vr6, a3, t2 + vldx vr7, a3, t3 + vldx vr8, a3, t4 + vld vr9, a4, 0 + vld vr10, a4, 16 + vld vr11, a4, 32 + vld vr12, a4, 48 + vld vr13, a4, 64 + vld vr14, a4, 80 + vld vr15, a4, 96 + vld vr16, a4, 112 + + vmulwev.w.hu.h vr17, vr1, vr9 + vmulwev.w.hu.h vr18, vr2, vr10 + vmulwev.w.hu.h vr19, vr3, vr11 + vmulwev.w.hu.h vr21, vr4, vr12 + vmaddwod.w.hu.h vr17, vr1, vr9 + vmaddwod.w.hu.h vr18, vr2, vr10 + vmaddwod.w.hu.h vr19, vr3, vr11 + vmaddwod.w.hu.h vr21, vr4, vr12 + vmulwev.w.hu.h vr1, vr5, vr13 + vmulwev.w.hu.h vr2, vr6, vr14 + vmulwev.w.hu.h vr3, vr7, vr15 + vmulwev.w.hu.h vr4, vr8, vr16 + vmaddwod.w.hu.h vr1, vr5, vr13 + vmaddwod.w.hu.h vr2, vr6, vr14 + vmaddwod.w.hu.h vr3, vr7, vr15 + vmaddwod.w.hu.h vr4, vr8, vr16 + vhaddw.d.w vr5, vr1, vr1 + vhaddw.d.w vr6, vr2, vr2 + vhaddw.d.w vr7, vr3, vr3 + vhaddw.d.w vr8, vr4, vr4 + vhaddw.d.w vr1, vr17, vr17 + vhaddw.d.w vr2, vr18, vr18 + vhaddw.d.w vr3, vr19, vr19 + vhaddw.d.w vr4, vr21, vr21 + vhaddw.q.d vr1, vr1, vr1 + vhaddw.q.d vr2, vr2, vr2 + vhaddw.q.d vr3, vr3, vr3 + vhaddw.q.d vr4, vr4, vr4 + vhaddw.q.d vr5, vr5, vr5 + vhaddw.q.d vr6, vr6, vr6 + vhaddw.q.d vr7, vr7, vr7 + vhaddw.q.d vr8, vr8, vr8 + vilvl.w vr1, vr2, vr1 + vilvl.w vr3, vr4, vr3 + vilvl.w vr5, vr6, vr5 + vilvl.w vr7, vr8, vr7 + vilvl.d vr1, vr3, vr1 + vilvl.d vr5, vr7, vr5 + vsra.w vr1, vr1, vr0 + vsra.w vr5, vr5, vr0 + vmin.w vr1, vr1, vr20 + vmin.w vr5, vr5, vr20 + + vpickev.h vr1, vr5, vr1 + vst vr1, a1, 0 + addi.d a1, a1, 16 + addi.d a5, a5, 32 + addi.d a4, a4, 128 + addi.d a2, a2, -8 + bge a2, t8, .LOOP_HS15_DST8 + blt zero, a2, .HS15_REST8 + b .HS15_END +.HS15_REST8: + li.w t1, 0 +.HS15_DST8: + slli.w t2, t1, 2 + ldx.w t2, a5, t2 + li.w t3, 0 + li.w t8, 0 +.HS15_FILTER8: + add.w t4, t2, t3 + slli.w t4, t4, 1 + ldx.hu t5, a3, t4 + mul.w t6, a6, t1 + add.w t6, t6, t3 + slli.w t7, t6, 1 + ldx.h t7, a4, t7 + mul.w t7, t5, t7 + add.w t8, t8, t7 + addi.w t3, t3, 1 + blt t3, a6, .HS15_FILTER8 + sra.w t8, t8, a7 + slt t5, t8, t0 + maskeqz t8, t8, t5 + masknez t5, t0, t5 + or t8, t8, t5 + slli.w t4, t1, 1 + stx.h t8, a1, t4 + addi.w t1, t1, 1 + blt t1, a2, .HS15_DST8 + b .HS15_END + +.LOOP_HS15_DST4: + ld.w t1, a5, 0 + ld.w t2, a5, 4 + ld.w t3, a5, 8 + ld.w t4, a5, 12 + slli.w t1, t1, 1 + slli.w t2, t2, 1 + slli.w t3, t3, 1 + slli.w t4, t4, 1 + fldx.d f1, a3, t1 + fldx.d f2, a3, t2 + fldx.d f3, a3, t3 + fldx.d f4, a3, t4 + ld.w t1, a5, 16 + ld.w t2, a5, 20 + ld.w t3, a5, 24 + ld.w t4, a5, 28 + slli.w t1, t1, 1 + slli.w t2, t2, 1 + slli.w t3, t3, 1 + slli.w t4, t4, 1 + fldx.d f5, a3, t1 + fldx.d f6, a3, t2 + fldx.d f7, a3, t3 + fldx.d f8, a3, t4 + vld vr9, a4, 0 + vld vr10, a4, 16 + vld vr11, a4, 32 + vld vr12, a4, 48 + vilvl.d vr1, vr2, vr1 + vilvl.d vr3, vr4, vr3 + vilvl.d vr5, vr6, vr5 + vilvl.d vr7, vr8, vr7 + vmulwev.w.hu.h vr13, vr1, vr9 + vmulwev.w.hu.h vr14, vr3, vr10 + vmulwev.w.hu.h vr15, vr5, vr11 + vmulwev.w.hu.h vr16, vr7, vr12 + vmaddwod.w.hu.h vr13, vr1, vr9 + vmaddwod.w.hu.h vr14, vr3, vr10 + vmaddwod.w.hu.h vr15, vr5, vr11 + vmaddwod.w.hu.h vr16, vr7, vr12 + vhaddw.d.w vr13, vr13, vr13 + vhaddw.d.w vr14, vr14, vr14 + vhaddw.d.w vr15, vr15, vr15 + vhaddw.d.w vr16, vr16, vr16 + vpickev.w vr13, vr14, vr13 + vpickev.w vr15, vr16, vr15 + vsra.w vr13, vr13, vr0 + vsra.w vr15, vr15, vr0 + vmin.w vr13, vr13, vr20 + vmin.w vr15, vr15, vr20 + + vpickev.h vr13, vr15, vr13 + vst vr13, a1, 0 + addi.d a1, a1, 16 + addi.d a5, a5, 32 + addi.d a4, a4, 64 + addi.d a2, a2, -8 + bge a2, t8, .LOOP_HS15_DST4 + blt zero, a2, .HS15_REST4 + b .HS15_END +.HS15_REST4: + li.w t1, 0 +.HS15_DST4: + slli.w t2, t1, 2 + ldx.w t2, a5, t2 + li.w t3, 0 + li.w t8, 0 +.HS15_FILTER4: + add.w t4, t2, t3 + slli.w t4, t4, 1 + ldx.hu t5, a3, t4 + mul.w t6, a6, t1 + add.w t6, t6, t3 + slli.w t7, t6, 1 + ldx.h t7, a4, t7 + mul.w t7, t5, t7 + add.w t8, t8, t7 + addi.w t3, t3, 1 + blt t3, a6, .HS15_FILTER4 + sra.w t8, t8, a7 + slt t5, t8, t0 + maskeqz t8, t8, t5 + masknez t5, t0, t5 + or t8, t8, t5 + slli.w t4, t1, 1 + stx.h t8, a1, t4 + addi.w t1, t1, 1 + blt t1, a2, .HS15_DST4 + b .HS15_END +.END_HS15_DST4: + + li.w t1, 0 +.LOOP_HS15_DST1: + slli.w t2, t1, 2 + ldx.w t2, a5, t2 + li.w t3, 0 + li.w t8, 0 +.HS15_FILTER1: + add.w t4, t2, t3 + slli.w t4, t4, 1 + ldx.hu t5, a3, t4 + mul.w t6, a6, t1 + add.w t6, t6, t3 + slli.w t7, t6, 1 + ldx.h t7, a4, t7 + mul.w t7, t5, t7 + add.w t8, t8, t7 + addi.w t3, t3, 1 + blt t3, a6, .HS15_FILTER1 + sra.w t8, t8, a7 + slt t5, t8, t0 + maskeqz t8, t8, t5 + masknez t5, t0, t5 + or t8, t8, t5 + slli.w t4, t1, 1 + stx.h t8, a1, t4 + addi.w t1, t1, 1 + blt t1, a2, .LOOP_HS15_DST1 + b .HS15_END +.HS15_END: + + ld.d s0, sp, 0 + ld.d s1, sp, 8 + ld.d s2, sp, 16 + ld.d s3, sp, 24 + ld.d s4, sp, 32 + ld.d s5, sp, 40 + ld.d s6, sp, 48 + ld.d s7, sp, 56 + ld.d s8, sp, 64 + addi.d sp, sp, 72 +endfunc + +/* void ff_hscale_16_to_19_sub_lsx(SwsContext *c, int16_t *dst, int dstW, + * const uint8_t *src, const int16_t *filter, + * const int32_t *filterPos, int filterSize, int sh) + */ +function ff_hscale_16_to_19_sub_lsx + addi.d sp, sp, -72 + st.d s0, sp, 0 + st.d s1, sp, 8 + st.d s2, sp, 16 + st.d s3, sp, 24 + st.d s4, sp, 32 + st.d s5, sp, 40 + st.d s6, sp, 48 + st.d s7, sp, 56 + st.d s8, sp, 64 + + li.w t0, 524287 + li.w t8, 8 + li.w t7, 4 + vreplgr2vr.w vr20, t0 + vreplgr2vr.w vr0, a7 + beq a6, t7, .LOOP_HS19_DST4 + beq a6, t8, .LOOP_HS19_DST8 + blt t8, a6, .LOOP_HS19 + b .END_HS19_DST4 + +.LOOP_HS19: + li.w t1, 0 + li.w s1, 0 + li.w s2, 0 + li.w s3, 0 + li.w s4, 0 + li.w s5, 0 + vldi vr22, 0 + addi.w s0, a6, -7 + slli.w s7, a6, 1 + slli.w s8, a6, 2 + add.w t6, s7, s8 +.LOOP_HS19_DST: + ld.w t2, a5, 0 + ld.w t3, a5, 4 + ld.w t4, a5, 8 + ld.w t5, a5, 12 + slli.w t2, t2, 1 + slli.w t3, t3, 1 + slli.w t4, t4, 1 + slli.w t5, t5, 1 + vldx vr1, a3, t2 + vldx vr2, a3, t3 + vldx vr3, a3, t4 + vldx vr4, a3, t5 + vld vr9, a4, 0 + vldx vr10, a4, s7 + vldx vr11, a4, s8 + vldx vr12, a4, t6 + vmulwev.w.hu.h vr17, vr1, vr9 + vmulwev.w.hu.h vr18, vr2, vr10 + vmulwev.w.hu.h vr19, vr3, vr11 + vmulwev.w.hu.h vr21, vr4, vr12 + vmaddwod.w.hu.h vr17, vr1, vr9 + vmaddwod.w.hu.h vr18, vr2, vr10 + vmaddwod.w.hu.h vr19, vr3, vr11 + vmaddwod.w.hu.h vr21, vr4, vr12 + vhaddw.d.w vr1, vr17, vr17 + vhaddw.d.w vr2, vr18, vr18 + vhaddw.d.w vr3, vr19, vr19 + vhaddw.d.w vr4, vr21, vr21 + vhaddw.q.d vr1, vr1, vr1 + vhaddw.q.d vr2, vr2, vr2 + vhaddw.q.d vr3, vr3, vr3 + vhaddw.q.d vr4, vr4, vr4 + vilvl.w vr1, vr2, vr1 + vilvl.w vr3, vr4, vr3 + vilvl.d vr1, vr3, vr1 + vadd.w vr22, vr22, vr1 + addi.w s1, s1, 8 + addi.d a3, a3, 16 + addi.d a4, a4, 16 + blt s1, s0, .LOOP_HS19_DST + blt s1, a6, .HS19_DSTA + b .END_HS19_FILTERA +.HS19_DSTA: + ld.w t2, a5, 0 + li.w t3, 0 + move s6, s1 +.HS19_FILTERA: + add.w t4, t2, t3 + slli.w t4, t4, 1 + ldx.hu t5, a3, t4 + mul.w t6, a6, t1 + add.w t6, t6, t3 + slli.w t6, t6, 1 + ldx.h t6, a4, t6 + mul.w t6, t5, t6 + add.w s2, s2, t6 + addi.w t3, t3, 1 + addi.w s6, s6, 1 + blt s6, a6, .HS19_FILTERA + + ld.w t2, a5, 4 + li.w t3, 0 + move s6, s1 + addi.w t1, t1, 1 +.HS19_FILTERB: + add.w t4, t2, t3 + slli.w t4, t4, 1 + ldx.hu t5, a3, t4 + mul.w t6, a6, t1 + add.w t6, t6, t3 + slli.w t6, t6, 1 + ldx.h t6, a4, t6 + mul.w t6, t5, t6 + add.w s3, s3, t6 + addi.w t3, t3, 1 + addi.w s6, s6, 1 + blt s6, a6, .HS19_FILTERB + ld.w t2, a5, 8 + addi.w t1, t1, 1 + li.w t3, 0 + move s6, s1 +.HS19_FILTERC: + add.w t4, t2, t3 + slli.w t4, t4, 1 + ldx.hu t5, a3, t4 + mul.w t6, a6, t1 + add.w t6, t6, t3 + slli.w t6, t6, 1 + ldx.h t6, a4, t6 + mul.w t6, t5, t6 + add.w s4, s4, t6 + addi.w t3, t3, 1 + addi.w s6, s6, 1 + blt s6, a6, .HS19_FILTERC + ld.w t2, a5, 12 + addi.w t1, t1, 1 + move s6, s1 + li.w t3, 0 +.HS19_FILTERD: + add.w t4, t2, t3 + slli.w t4, t4, 1 + ldx.hu t5, a3, t4 + mul.w t6, a6, t1 + add.w t6, t6, t3 + slli.w t6, t6, 1 + ldx.h t6, a4, t6 + mul.w t6, t5, t6 + add.w s5, s5, t6 + addi.w t3, t3, 1 + addi.w s6, s6, 1 + blt s6, a6, .HS19_FILTERD +.END_HS19_FILTERA: + vpickve2gr.w t1, vr22, 0 + vpickve2gr.w t2, vr22, 1 + vpickve2gr.w t3, vr22, 2 + vpickve2gr.w t4, vr22, 3 + add.w s2, s2, t1 + add.w s3, s3, t2 + add.w s4, s4, t3 + add.w s5, s5, t4 + sra.w s2, s2, a7 + sra.w s3, s3, a7 + sra.w s4, s4, a7 + sra.w s5, s5, a7 + slt t1, s2, t0 + slt t2, s3, t0 + slt t3, s4, t0 + slt t4, s5, t0 + maskeqz s2, s2, t1 + maskeqz s3, s3, t2 + maskeqz s4, s4, t3 + maskeqz s5, s5, t4 + masknez t1, t0, t1 + masknez t2, t0, t2 + masknez t3, t0, t3 + masknez t4, t0, t4 + or s2, s2, t1 + or s3, s3, t2 + or s4, s4, t3 + or s5, s5, t4 + st.w s2, a1, 0 + st.w s3, a1, 4 + st.w s4, a1, 8 + st.w s5, a1, 12 + + addi.d a1, a1, 16 + sub.d a3, a3, s1 + sub.d a3, a3, s1 + addi.d a5, a5, 16 + slli.d t3, a6, 3 + add.d a4, a4, t3 + sub.d a4, a4, s1 + sub.d a4, a4, s1 + addi.d a2, a2, -4 + bge a2, t7, .LOOP_HS19 + blt zero, a2, .HS19_RESA + b .HS19_END +.HS19_RESA: + li.w t1, 0 +.HS19_DST: + slli.w t2, t1, 2 + ldx.w t2, a5, t2 + li.w t3, 0 + li.w t8, 0 +.HS19_FILTER: + add.w t4, t2, t3 + slli.w t4, t4, 1 + ldx.hu t5, a3, t4 + mul.w t6, a6, t1 + add.w t6, t6, t3 + slli.w t7, t6, 1 + ldx.h t7, a4, t7 + mul.w t7, t5, t7 + add.w t8, t8, t7 + addi.w t3, t3, 1 + blt t3, a6, .HS19_FILTER + sra.w t8, t8, a7 + slt t5, t8, t0 + maskeqz t8, t8, t5 + masknez t5, t0, t5 + or t8, t8, t5 + slli.w t4, t1, 2 + stx.w t8, a1, t4 + addi.w t1, t1, 1 + blt t1, a2, .HS19_DST + b .HS19_END + +.LOOP_HS19_DST8: + ld.w t1, a5, 0 + ld.w t2, a5, 4 + ld.w t3, a5, 8 + ld.w t4, a5, 12 + slli.w t1, t1, 1 + slli.w t2, t2, 1 + slli.w t3, t3, 1 + slli.w t4, t4, 1 + vldx vr1, a3, t1 + vldx vr2, a3, t2 + vldx vr3, a3, t3 + vldx vr4, a3, t4 + ld.w t1, a5, 16 + ld.w t2, a5, 20 + ld.w t3, a5, 24 + ld.w t4, a5, 28 + slli.w t1, t1, 1 + slli.w t2, t2, 1 + slli.w t3, t3, 1 + slli.w t4, t4, 1 + vldx vr5, a3, t1 + vldx vr6, a3, t2 + vldx vr7, a3, t3 + vldx vr8, a3, t4 + vld vr9, a4, 0 + vld vr10, a4, 16 + vld vr11, a4, 32 + vld vr12, a4, 48 + vld vr13, a4, 64 + vld vr14, a4, 80 + vld vr15, a4, 96 + vld vr16, a4, 112 + vmulwev.w.hu.h vr17, vr1, vr9 + vmulwev.w.hu.h vr18, vr2, vr10 + vmulwev.w.hu.h vr19, vr3, vr11 + vmulwev.w.hu.h vr21, vr4, vr12 + vmaddwod.w.hu.h vr17, vr1, vr9 + vmaddwod.w.hu.h vr18, vr2, vr10 + vmaddwod.w.hu.h vr19, vr3, vr11 + vmaddwod.w.hu.h vr21, vr4, vr12 + vmulwev.w.hu.h vr1, vr5, vr13 + vmulwev.w.hu.h vr2, vr6, vr14 + vmulwev.w.hu.h vr3, vr7, vr15 + vmulwev.w.hu.h vr4, vr8, vr16 + vmaddwod.w.hu.h vr1, vr5, vr13 + vmaddwod.w.hu.h vr2, vr6, vr14 + vmaddwod.w.hu.h vr3, vr7, vr15 + vmaddwod.w.hu.h vr4, vr8, vr16 + vhaddw.d.w vr5, vr1, vr1 + vhaddw.d.w vr6, vr2, vr2 + vhaddw.d.w vr7, vr3, vr3 + vhaddw.d.w vr8, vr4, vr4 + vhaddw.d.w vr1, vr17, vr17 + vhaddw.d.w vr2, vr18, vr18 + vhaddw.d.w vr3, vr19, vr19 + vhaddw.d.w vr4, vr21, vr21 + vhaddw.q.d vr1, vr1, vr1 + vhaddw.q.d vr2, vr2, vr2 + vhaddw.q.d vr3, vr3, vr3 + vhaddw.q.d vr4, vr4, vr4 + vhaddw.q.d vr5, vr5, vr5 + vhaddw.q.d vr6, vr6, vr6 + vhaddw.q.d vr7, vr7, vr7 + vhaddw.q.d vr8, vr8, vr8 + vilvl.w vr1, vr2, vr1 + vilvl.w vr3, vr4, vr3 + vilvl.w vr5, vr6, vr5 + vilvl.w vr7, vr8, vr7 + vilvl.d vr1, vr3, vr1 + vilvl.d vr5, vr7, vr5 + vsra.w vr1, vr1, vr0 + vsra.w vr5, vr5, vr0 + vmin.w vr1, vr1, vr20 + vmin.w vr5, vr5, vr20 + + vst vr1, a1, 0 + vst vr5, a1, 16 + addi.d a1, a1, 32 + addi.d a5, a5, 32 + addi.d a4, a4, 128 + addi.d a2, a2, -8 + bge a2, t8, .LOOP_HS19_DST8 + blt zero, a2, .HS19_REST8 + b .HS19_END +.HS19_REST8: + li.w t1, 0 +.HS19_DST8: + slli.w t2, t1, 2 + ldx.w t2, a5, t2 + li.w t3, 0 + li.w t8, 0 +.HS19_FILTER8: + add.w t4, t2, t3 + slli.w t4, t4, 1 + ldx.hu t5, a3, t4 + mul.w t6, a6, t1 + add.w t6, t6, t3 + slli.w t7, t6, 1 + ldx.h t7, a4, t7 + mul.w t7, t5, t7 + add.w t8, t8, t7 + addi.w t3, t3, 1 + blt t3, a6, .HS19_FILTER8 + sra.w t8, t8, a7 + slt t5, t8, t0 + maskeqz t8, t8, t5 + masknez t5, t0, t5 + or t8, t8, t5 + slli.w t4, t1, 2 + stx.w t8, a1, t4 + addi.w t1, t1, 1 + blt t1, a2, .HS19_DST8 + b .HS19_END + +.LOOP_HS19_DST4: + ld.w t1, a5, 0 + ld.w t2, a5, 4 + ld.w t3, a5, 8 + ld.w t4, a5, 12 + slli.w t1, t1, 1 + slli.w t2, t2, 1 + slli.w t3, t3, 1 + slli.w t4, t4, 1 + fldx.d f1, a3, t1 + fldx.d f2, a3, t2 + fldx.d f3, a3, t3 + fldx.d f4, a3, t4 + ld.w t1, a5, 16 + ld.w t2, a5, 20 + ld.w t3, a5, 24 + ld.w t4, a5, 28 + slli.w t1, t1, 1 + slli.w t2, t2, 1 + slli.w t3, t3, 1 + slli.w t4, t4, 1 + fldx.d f5, a3, t1 + fldx.d f6, a3, t2 + fldx.d f7, a3, t3 + fldx.d f8, a3, t4 + vld vr9, a4, 0 + vld vr10, a4, 16 + vld vr11, a4, 32 + vld vr12, a4, 48 + vilvl.d vr1, vr2, vr1 + vilvl.d vr3, vr4, vr3 + vilvl.d vr5, vr6, vr5 + vilvl.d vr7, vr8, vr7 + vmulwev.w.hu.h vr13, vr1, vr9 + vmulwev.w.hu.h vr14, vr3, vr10 + vmulwev.w.hu.h vr15, vr5, vr11 + vmulwev.w.hu.h vr16, vr7, vr12 + vmaddwod.w.hu.h vr13, vr1, vr9 + vmaddwod.w.hu.h vr14, vr3, vr10 + vmaddwod.w.hu.h vr15, vr5, vr11 + vmaddwod.w.hu.h vr16, vr7, vr12 + vhaddw.d.w vr13, vr13, vr13 + vhaddw.d.w vr14, vr14, vr14 + vhaddw.d.w vr15, vr15, vr15 + vhaddw.d.w vr16, vr16, vr16 + vpickev.w vr13, vr14, vr13 + vpickev.w vr15, vr16, vr15 + vsra.w vr13, vr13, vr0 + vsra.w vr15, vr15, vr0 + vmin.w vr13, vr13, vr20 + vmin.w vr15, vr15, vr20 + + vst vr13, a1, 0 + vst vr15, a1, 16 + addi.d a1, a1, 32 + addi.d a5, a5, 32 + addi.d a4, a4, 64 + addi.d a2, a2, -8 + bge a2, t8, .LOOP_HS19_DST4 + blt zero, a2, .HS19_REST4 + b .HS19_END +.HS19_REST4: + li.w t1, 0 +.HS19_DST4: + slli.w t2, t1, 2 + ldx.w t2, a5, t2 + li.w t3, 0 + li.w t8, 0 +.HS19_FILTER4: + add.w t4, t2, t3 + slli.w t4, t4, 1 + ldx.hu t5, a3, t4 + mul.w t6, a6, t1 + add.w t6, t6, t3 + slli.w t7, t6, 1 + ldx.h t7, a4, t7 + mul.w t7, t5, t7 + add.w t8, t8, t7 + addi.w t3, t3, 1 + blt t3, a6, .HS19_FILTER4 + sra.w t8, t8, a7 + slt t5, t8, t0 + maskeqz t8, t8, t5 + masknez t5, t0, t5 + or t8, t8, t5 + slli.w t4, t1, 2 + stx.w t8, a1, t4 + addi.w t1, t1, 1 + blt t1, a2, .HS19_DST4 + b .HS19_END +.END_HS19_DST4: + + li.w t1, 0 +.LOOP_HS19_DST1: + slli.w t2, t1, 2 + ldx.w t2, a5, t2 + li.w t3, 0 + li.w t8, 0 +.HS19_FILTER1: + add.w t4, t2, t3 + slli.w t4, t4, 1 + ldx.hu t5, a3, t4 + mul.w t6, a6, t1 + add.w t6, t6, t3 + slli.w t7, t6, 1 + ldx.h t7, a4, t7 + mul.w t7, t5, t7 + add.w t8, t8, t7 + addi.w t3, t3, 1 + blt t3, a6, .HS19_FILTER1 + sra.w t8, t8, a7 + slt t5, t8, t0 + maskeqz t8, t8, t5 + masknez t5, t0, t5 + or t8, t8, t5 + slli.w t4, t1, 2 + stx.w t8, a1, t4 + addi.w t1, t1, 1 + blt t1, a2, .LOOP_HS19_DST1 + b .HS19_END +.HS19_END: + + ld.d s0, sp, 0 + ld.d s1, sp, 8 + ld.d s2, sp, 16 + ld.d s3, sp, 24 + ld.d s4, sp, 32 + ld.d s5, sp, 40 + ld.d s6, sp, 48 + ld.d s7, sp, 56 + ld.d s8, sp, 64 + addi.d sp, sp, 72 +endfunc diff --git a/libswscale/loongarch/swscale_init_loongarch.c b/libswscale/loongarch/swscale_init_loongarch.c index 97fe947e2ea..c13a1662ecf 100644 --- a/libswscale/loongarch/swscale_init_loongarch.c +++ b/libswscale/loongarch/swscale_init_loongarch.c @@ -27,8 +27,33 @@ av_cold void ff_sws_init_swscale_loongarch(SwsContext *c) { int cpu_flags = av_get_cpu_flags(); + if (have_lsx(cpu_flags)) { + ff_sws_init_output_lsx(c); + if (c->srcBpc == 8) { + if (c->dstBpc <= 14) { + c->hyScale = c->hcScale = ff_hscale_8_to_15_lsx; + } else { + c->hyScale = c->hcScale = ff_hscale_8_to_19_lsx; + } + } else { + c->hyScale = c->hcScale = c->dstBpc > 14 ? ff_hscale_16_to_19_lsx + : ff_hscale_16_to_15_lsx; + } + switch (c->srcFormat) { + case AV_PIX_FMT_GBRAP: + case AV_PIX_FMT_GBRP: + { + c->readChrPlanar = planar_rgb_to_uv_lsx; + c->readLumPlanar = planar_rgb_to_y_lsx; + } + break; + } + if (c->dstBpc == 8) + c->yuv2planeX = ff_yuv2planeX_8_lsx; + } +#if HAVE_LASX if (have_lasx(cpu_flags)) { - ff_sws_init_output_loongarch(c); + ff_sws_init_output_lasx(c); if (c->srcBpc == 8) { if (c->dstBpc <= 14) { c->hyScale = c->hcScale = ff_hscale_8_to_15_lasx; @@ -51,17 +76,21 @@ av_cold void ff_sws_init_swscale_loongarch(SwsContext *c) if (c->dstBpc == 8) c->yuv2planeX = ff_yuv2planeX_8_lasx; } +#endif // #if HAVE_LASX } av_cold void rgb2rgb_init_loongarch(void) { +#if HAVE_LASX int cpu_flags = av_get_cpu_flags(); if (have_lasx(cpu_flags)) interleaveBytes = ff_interleave_bytes_lasx; +#endif // #if HAVE_LASX } av_cold SwsFunc ff_yuv2rgb_init_loongarch(SwsContext *c) { +#if HAVE_LASX int cpu_flags = av_get_cpu_flags(); if (have_lasx(cpu_flags)) { switch (c->dstFormat) { @@ -91,5 +120,6 @@ av_cold SwsFunc ff_yuv2rgb_init_loongarch(SwsContext *c) return yuv420_abgr32_lasx; } } +#endif // #if HAVE_LASX return NULL; } diff --git a/libswscale/loongarch/swscale_loongarch.h b/libswscale/loongarch/swscale_loongarch.h index c52eb1016bb..bc29913ac65 100644 --- a/libswscale/loongarch/swscale_loongarch.h +++ b/libswscale/loongarch/swscale_loongarch.h @@ -24,7 +24,45 @@ #include "libswscale/swscale.h" #include "libswscale/swscale_internal.h" +#include "config.h" +void ff_hscale_8_to_15_lsx(SwsContext *c, int16_t *dst, int dstW, + const uint8_t *src, const int16_t *filter, + const int32_t *filterPos, int filterSize); + +void ff_hscale_8_to_19_lsx(SwsContext *c, int16_t *_dst, int dstW, + const uint8_t *src, const int16_t *filter, + const int32_t *filterPos, int filterSize); + +void ff_hscale_16_to_15_lsx(SwsContext *c, int16_t *_dst, int dstW, + const uint8_t *_src, const int16_t *filter, + const int32_t *filterPos, int filterSize); + +void ff_hscale_16_to_15_sub_lsx(SwsContext *c, int16_t *_dst, int dstW, + const uint8_t *_src, const int16_t *filter, + const int32_t *filterPos, int filterSize, int sh); + +void ff_hscale_16_to_19_lsx(SwsContext *c, int16_t *_dst, int dstW, + const uint8_t *_src, const int16_t *filter, + const int32_t *filterPos, int filterSize); + +void ff_hscale_16_to_19_sub_lsx(SwsContext *c, int16_t *_dst, int dstW, + const uint8_t *_src, const int16_t *filter, + const int32_t *filterPos, int filterSize, int sh); + +void planar_rgb_to_uv_lsx(uint8_t *_dstU, uint8_t *_dstV, const uint8_t *src[4], + int width, int32_t *rgb2yuv, void *opq); + +void planar_rgb_to_y_lsx(uint8_t *_dst, const uint8_t *src[4], int width, + int32_t *rgb2yuv, void *opq); + +void ff_yuv2planeX_8_lsx(const int16_t *filter, int filterSize, + const int16_t **src, uint8_t *dest, int dstW, + const uint8_t *dither, int offset); + +av_cold void ff_sws_init_output_lsx(SwsContext *c); + +#if HAVE_LASX void ff_hscale_8_to_15_lasx(SwsContext *c, int16_t *dst, int dstW, const uint8_t *src, const int16_t *filter, const int32_t *filterPos, int filterSize); @@ -69,10 +107,11 @@ void ff_interleave_bytes_lasx(const uint8_t *src1, const uint8_t *src2, uint8_t *dest, int width, int height, int src1Stride, int src2Stride, int dstStride); -av_cold void ff_sws_init_output_loongarch(SwsContext *c); - void ff_yuv2planeX_8_lasx(const int16_t *filter, int filterSize, const int16_t **src, uint8_t *dest, int dstW, const uint8_t *dither, int offset); +av_cold void ff_sws_init_output_lasx(SwsContext *c); +#endif // #if HAVE_LASX + #endif /* SWSCALE_LOONGARCH_SWSCALE_LOONGARCH_H */ diff --git a/libswscale/loongarch/swscale_lsx.c b/libswscale/loongarch/swscale_lsx.c new file mode 100644 index 00000000000..da8eabfca3d --- /dev/null +++ b/libswscale/loongarch/swscale_lsx.c @@ -0,0 +1,57 @@ +/* + * Loongson LSX optimized swscale + * + * Copyright (c) 2023 Loongson Technology Corporation Limited + * Contributed by 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 + */ + +#include "swscale_loongarch.h" + +void ff_hscale_16_to_15_lsx(SwsContext *c, int16_t *_dst, int dstW, + const uint8_t *_src, const int16_t *filter, + const int32_t *filterPos, int filterSize) +{ + const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(c->srcFormat); + int sh = desc->comp[0].depth - 1; + + if (sh < 15) { + sh = isAnyRGB(c->srcFormat) || c->srcFormat==AV_PIX_FMT_PAL8 ? 13 : + (desc->comp[0].depth - 1); + } else if (desc->flags && AV_PIX_FMT_FLAG_FLOAT) { + sh = 15; + } + ff_hscale_16_to_15_sub_lsx(c, _dst, dstW, _src, filter, filterPos, filterSize, sh); +} + +void ff_hscale_16_to_19_lsx(SwsContext *c, int16_t *_dst, int dstW, + const uint8_t *_src, const int16_t *filter, + const int32_t *filterPos, int filterSize) +{ + const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(c->srcFormat); + int bits = desc->comp[0].depth - 1; + int sh = bits - 4; + + if ((isAnyRGB(c->srcFormat) || c->srcFormat==AV_PIX_FMT_PAL8) && desc->comp[0].depth<16) { + + sh = 9; + } else if (desc->flags & AV_PIX_FMT_FLAG_FLOAT) { /* float input are process like uint 16bpc */ + sh = 16 - 1 - 4; + } + ff_hscale_16_to_19_sub_lsx(c, _dst, dstW, _src, filter, filterPos, filterSize, sh); +} diff --git a/libswscale/utils.c b/libswscale/utils.c index 925c536bf17..b02e6cdc646 100644 --- a/libswscale/utils.c +++ b/libswscale/utils.c @@ -653,7 +653,7 @@ static av_cold int initFilter(int16_t **outFilter, int32_t **filterPos, filterAlign = 1; } - if (have_lasx(cpu_flags)) { + if (have_lasx(cpu_flags) || have_lsx(cpu_flags)) { int reNum = minFilterSize & (0x07); if (minFilterSize < 5) @@ -1806,6 +1806,7 @@ static av_cold int sws_init_single_context(SwsContext *c, SwsFilter *srcFilter, const int filterAlign = X86_MMX(cpu_flags) ? 4 : PPC_ALTIVEC(cpu_flags) ? 8 : have_neon(cpu_flags) ? 4 : + have_lsx(cpu_flags) ? 8 : have_lasx(cpu_flags) ? 8 : 1; if ((ret = initFilter(&c->hLumFilter, &c->hLumFilterPos, From cb4ae8baeefe35d01695a18f3b7671008cf13afc Mon Sep 17 00:00:00 2001 From: Jin Bo Date: Thu, 25 May 2023 15:24:31 +0800 Subject: [PATCH 1178/2172] swscale/la: Add following builtin optimized functions yuv420_rgb24_lsx yuv420_bgr24_lsx yuv420_rgba32_lsx yuv420_argb32_lsx yuv420_bgra32_lsx yuv420_abgr32_lsx ./configure --disable-lasx ffmpeg -i ~/media/1_h264_1080p_30fps_3Mbps.mp4 -f rawvideo -pix_fmt rgb24 -y /dev/null -an before: 184fps after: 207fps Reviewed-by: Shiyou Yin Signed-off-by: Michael Niedermayer --- libswscale/loongarch/Makefile | 3 +- libswscale/loongarch/swscale_init_loongarch.c | 30 +- libswscale/loongarch/swscale_loongarch.h | 18 + libswscale/loongarch/yuv2rgb_lsx.c | 361 ++++++++++++++++++ 4 files changed, 410 insertions(+), 2 deletions(-) create mode 100644 libswscale/loongarch/yuv2rgb_lsx.c diff --git a/libswscale/loongarch/Makefile b/libswscale/loongarch/Makefile index c0b6a449c0e..c35ba309a4f 100644 --- a/libswscale/loongarch/Makefile +++ b/libswscale/loongarch/Makefile @@ -8,4 +8,5 @@ LSX-OBJS-$(CONFIG_SWSCALE) += loongarch/swscale.o \ loongarch/swscale_lsx.o \ loongarch/input.o \ loongarch/output.o \ - loongarch/output_lsx.o + loongarch/output_lsx.o \ + loongarch/yuv2rgb_lsx.o diff --git a/libswscale/loongarch/swscale_init_loongarch.c b/libswscale/loongarch/swscale_init_loongarch.c index c13a1662ecf..53e4f970b64 100644 --- a/libswscale/loongarch/swscale_init_loongarch.c +++ b/libswscale/loongarch/swscale_init_loongarch.c @@ -90,8 +90,8 @@ av_cold void rgb2rgb_init_loongarch(void) av_cold SwsFunc ff_yuv2rgb_init_loongarch(SwsContext *c) { -#if HAVE_LASX int cpu_flags = av_get_cpu_flags(); +#if HAVE_LASX if (have_lasx(cpu_flags)) { switch (c->dstFormat) { case AV_PIX_FMT_RGB24: @@ -121,5 +121,33 @@ av_cold SwsFunc ff_yuv2rgb_init_loongarch(SwsContext *c) } } #endif // #if HAVE_LASX + if (have_lsx(cpu_flags)) { + switch (c->dstFormat) { + case AV_PIX_FMT_RGB24: + return yuv420_rgb24_lsx; + case AV_PIX_FMT_BGR24: + return yuv420_bgr24_lsx; + case AV_PIX_FMT_RGBA: + if (CONFIG_SWSCALE_ALPHA && isALPHA(c->srcFormat)) { + break; + } else + return yuv420_rgba32_lsx; + case AV_PIX_FMT_ARGB: + if (CONFIG_SWSCALE_ALPHA && isALPHA(c->srcFormat)) { + break; + } else + return yuv420_argb32_lsx; + case AV_PIX_FMT_BGRA: + if (CONFIG_SWSCALE_ALPHA && isALPHA(c->srcFormat)) { + break; + } else + return yuv420_bgra32_lsx; + case AV_PIX_FMT_ABGR: + if (CONFIG_SWSCALE_ALPHA && isALPHA(c->srcFormat)) { + break; + } else + return yuv420_abgr32_lsx; + } + } return NULL; } diff --git a/libswscale/loongarch/swscale_loongarch.h b/libswscale/loongarch/swscale_loongarch.h index bc29913ac65..0514abae212 100644 --- a/libswscale/loongarch/swscale_loongarch.h +++ b/libswscale/loongarch/swscale_loongarch.h @@ -62,6 +62,24 @@ void ff_yuv2planeX_8_lsx(const int16_t *filter, int filterSize, av_cold void ff_sws_init_output_lsx(SwsContext *c); +int yuv420_rgb24_lsx(SwsContext *c, const uint8_t *src[], int srcStride[], + int srcSliceY, int srcSliceH, uint8_t *dst[], int dstStride[]); + +int yuv420_bgr24_lsx(SwsContext *c, const uint8_t *src[], int srcStride[], + int srcSliceY, int srcSliceH, uint8_t *dst[], int dstStride[]); + +int yuv420_rgba32_lsx(SwsContext *c, const uint8_t *src[], int srcStride[], + int srcSliceY, int srcSliceH, uint8_t *dst[], int dstStride[]); + +int yuv420_bgra32_lsx(SwsContext *c, const uint8_t *src[], int srcStride[], + int srcSliceY, int srcSliceH, uint8_t *dst[], int dstStride[]); + +int yuv420_argb32_lsx(SwsContext *c, const uint8_t *src[], int srcStride[], + int srcSliceY, int srcSliceH, uint8_t *dst[], int dstStride[]); + +int yuv420_abgr32_lsx(SwsContext *c, const uint8_t *src[], int srcStride[], + int srcSliceY, int srcSliceH, uint8_t *dst[], int dstStride[]); + #if HAVE_LASX void ff_hscale_8_to_15_lasx(SwsContext *c, int16_t *dst, int dstW, const uint8_t *src, const int16_t *filter, diff --git a/libswscale/loongarch/yuv2rgb_lsx.c b/libswscale/loongarch/yuv2rgb_lsx.c new file mode 100644 index 00000000000..11cd2f79d9e --- /dev/null +++ b/libswscale/loongarch/yuv2rgb_lsx.c @@ -0,0 +1,361 @@ +/* + * Copyright (C) 2023 Loongson Technology Co. Ltd. + * Contributed by Bo Jin(jinbo@loongson.cn) + * All rights reserved. + * + * 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 "swscale_loongarch.h" +#include "libavutil/loongarch/loongson_intrinsics.h" + +#define YUV2RGB_LOAD_COE \ + /* Load x_offset */ \ + __m128i y_offset = __lsx_vreplgr2vr_d(c->yOffset); \ + __m128i u_offset = __lsx_vreplgr2vr_d(c->uOffset); \ + __m128i v_offset = __lsx_vreplgr2vr_d(c->vOffset); \ + /* Load x_coeff */ \ + __m128i ug_coeff = __lsx_vreplgr2vr_d(c->ugCoeff); \ + __m128i vg_coeff = __lsx_vreplgr2vr_d(c->vgCoeff); \ + __m128i y_coeff = __lsx_vreplgr2vr_d(c->yCoeff); \ + __m128i ub_coeff = __lsx_vreplgr2vr_d(c->ubCoeff); \ + __m128i vr_coeff = __lsx_vreplgr2vr_d(c->vrCoeff); \ + +#define LOAD_YUV_16 \ + m_y1 = __lsx_vld(py_1, 0); \ + m_y2 = __lsx_vld(py_2, 0); \ + m_u = __lsx_vldrepl_d(pu, 0); \ + m_v = __lsx_vldrepl_d(pv, 0); \ + DUP2_ARG2(__lsx_vilvl_b, m_u, m_u, m_v, m_v, m_u, m_v); \ + DUP2_ARG2(__lsx_vilvh_b, zero, m_u, zero, m_v, m_u_h, m_v_h); \ + DUP2_ARG2(__lsx_vilvl_b, zero, m_u, zero, m_v, m_u, m_v); \ + DUP2_ARG2(__lsx_vilvh_b, zero, m_y1, zero, m_y2, m_y1_h, m_y2_h); \ + DUP2_ARG2(__lsx_vilvl_b, zero, m_y1, zero, m_y2, m_y1, m_y2); \ + +/* YUV2RGB method + * The conversion method is as follows: + * R = Y' * y_coeff + V' * vr_coeff + * G = Y' * y_coeff + V' * vg_coeff + U' * ug_coeff + * B = Y' * y_coeff + U' * ub_coeff + * + * where X' = X * 8 - x_offset + * + */ + +#define YUV2RGB(y1, y2, u, v, r1, g1, b1, r2, g2, b2) \ +{ \ + y1 = __lsx_vslli_h(y1, 3); \ + y2 = __lsx_vslli_h(y2, 3); \ + u = __lsx_vslli_h(u, 3); \ + v = __lsx_vslli_h(v, 3); \ + y1 = __lsx_vsub_h(y1, y_offset); \ + y2 = __lsx_vsub_h(y2, y_offset); \ + u = __lsx_vsub_h(u, u_offset); \ + v = __lsx_vsub_h(v, v_offset); \ + y_1 = __lsx_vmuh_h(y1, y_coeff); \ + y_2 = __lsx_vmuh_h(y2, y_coeff); \ + u2g = __lsx_vmuh_h(u, ug_coeff); \ + u2b = __lsx_vmuh_h(u, ub_coeff); \ + v2r = __lsx_vmuh_h(v, vr_coeff); \ + v2g = __lsx_vmuh_h(v, vg_coeff); \ + r1 = __lsx_vsadd_h(y_1, v2r); \ + v2g = __lsx_vsadd_h(v2g, u2g); \ + g1 = __lsx_vsadd_h(y_1, v2g); \ + b1 = __lsx_vsadd_h(y_1, u2b); \ + r2 = __lsx_vsadd_h(y_2, v2r); \ + g2 = __lsx_vsadd_h(y_2, v2g); \ + b2 = __lsx_vsadd_h(y_2, u2b); \ + DUP4_ARG1(__lsx_vclip255_h, r1, g1, b1, r2, r1, g1, b1, r2); \ + DUP2_ARG1(__lsx_vclip255_h, g2, b2, g2, b2); \ +} + +#define RGB_PACK(r, g, b, rgb_l, rgb_h) \ +{ \ + __m128i rg; \ + rg = __lsx_vpackev_b(g, r); \ + DUP2_ARG3(__lsx_vshuf_b, b, rg, shuf2, b, rg, shuf3, rgb_l, rgb_h); \ +} + +#define RGB32_PACK(a, r, g, b, rgb_l, rgb_h) \ +{ \ + __m128i ra, bg; \ + ra = __lsx_vpackev_b(r, a); \ + bg = __lsx_vpackev_b(b, g); \ + rgb_l = __lsx_vilvl_h(bg, ra); \ + rgb_h = __lsx_vilvh_h(bg, ra); \ +} + +#define RGB_STORE(rgb_l, rgb_h, image) \ +{ \ + __lsx_vstelm_d(rgb_l, image, 0, 0); \ + __lsx_vstelm_d(rgb_l, image, 8, 1); \ + __lsx_vstelm_d(rgb_h, image, 16, 0); \ +} + +#define RGB32_STORE(rgb_l, rgb_h, image) \ +{ \ + __lsx_vst(rgb_l, image, 0); \ + __lsx_vst(rgb_h, image, 16); \ +} + +#define YUV2RGBFUNC(func_name, dst_type, alpha) \ + int func_name(SwsContext *c, const uint8_t *src[], \ + int srcStride[], int srcSliceY, int srcSliceH, \ + uint8_t *dst[], int dstStride[]) \ +{ \ + int x, y, h_size, vshift, res; \ + __m128i m_y1, m_y2, m_u, m_v; \ + __m128i m_y1_h, m_y2_h, m_u_h, m_v_h; \ + __m128i y_1, y_2, u2g, v2g, u2b, v2r, rgb1_l, rgb1_h; \ + __m128i rgb2_l, rgb2_h, r1, g1, b1, r2, g2, b2; \ + __m128i shuf2 = {0x0504120302100100, 0x0A18090816070614}; \ + __m128i shuf3 = {0x1E0F0E1C0D0C1A0B, 0x0101010101010101}; \ + __m128i zero = __lsx_vldi(0); \ + \ + YUV2RGB_LOAD_COE \ + \ + h_size = c->dstW >> 4; \ + res = (c->dstW & 15) >> 1; \ + vshift = c->srcFormat != AV_PIX_FMT_YUV422P; \ + for (y = 0; y < srcSliceH; y += 2) { \ + dst_type av_unused *r, *g, *b; \ + dst_type *image1 = (dst_type *)(dst[0] + (y + srcSliceY) * dstStride[0]);\ + dst_type *image2 = (dst_type *)(image1 + dstStride[0]);\ + 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 >> vshift) * srcStride[1]; \ + const uint8_t *pv = src[2] + (y >> vshift) * srcStride[2]; \ + for(x = 0; x < h_size; x++) { \ + +#define YUV2RGBFUNC32(func_name, dst_type, alpha) \ + int func_name(SwsContext *c, const uint8_t *src[], \ + int srcStride[], int srcSliceY, int srcSliceH, \ + uint8_t *dst[], int dstStride[]) \ +{ \ + int x, y, h_size, vshift, res; \ + __m128i m_y1, m_y2, m_u, m_v; \ + __m128i m_y1_h, m_y2_h, m_u_h, m_v_h; \ + __m128i y_1, y_2, u2g, v2g, u2b, v2r, rgb1_l, rgb1_h; \ + __m128i rgb2_l, rgb2_h, r1, g1, b1, r2, g2, b2; \ + __m128i a = __lsx_vldi(0xFF); \ + __m128i zero = __lsx_vldi(0); \ + \ + YUV2RGB_LOAD_COE \ + \ + h_size = c->dstW >> 4; \ + res = (c->dstW & 15) >> 1; \ + vshift = c->srcFormat != AV_PIX_FMT_YUV422P; \ + for (y = 0; y < srcSliceH; y += 2) { \ + int yd = y + srcSliceY; \ + dst_type av_unused *r, *g, *b; \ + dst_type *image1 = (dst_type *)(dst[0] + (yd) * dstStride[0]); \ + dst_type *image2 = (dst_type *)(dst[0] + (yd + 1) * dstStride[0]); \ + 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 >> vshift) * srcStride[1]; \ + const uint8_t *pv = src[2] + (y >> vshift) * srcStride[2]; \ + for(x = 0; x < h_size; x++) { \ + +#define DEALYUV2RGBREMAIN \ + py_1 += 16; \ + py_2 += 16; \ + pu += 8; \ + pv += 8; \ + image1 += 48; \ + image2 += 48; \ + } \ + for (x = 0; x < res; x++) { \ + int av_unused U, V, Y; \ + U = pu[0]; \ + V = pv[0]; \ + r = (void *)c->table_rV[V+YUVRGB_TABLE_HEADROOM]; \ + g = (void *)(c->table_gU[U+YUVRGB_TABLE_HEADROOM] \ + + c->table_gV[V+YUVRGB_TABLE_HEADROOM]); \ + b = (void *)c->table_bU[U+YUVRGB_TABLE_HEADROOM]; + +#define DEALYUV2RGBREMAIN32 \ + py_1 += 16; \ + py_2 += 16; \ + pu += 8; \ + pv += 8; \ + image1 += 16; \ + image2 += 16; \ + } \ + for (x = 0; x < res; x++) { \ + int av_unused U, V, Y; \ + U = pu[0]; \ + V = pv[0]; \ + r = (void *)c->table_rV[V+YUVRGB_TABLE_HEADROOM]; \ + g = (void *)(c->table_gU[U+YUVRGB_TABLE_HEADROOM] \ + + c->table_gV[V+YUVRGB_TABLE_HEADROOM]); \ + b = (void *)c->table_bU[U+YUVRGB_TABLE_HEADROOM]; \ + +#define PUTRGB24(dst, src) \ + Y = src[0]; \ + dst[0] = r[Y]; \ + dst[1] = g[Y]; \ + dst[2] = b[Y]; \ + Y = src[1]; \ + dst[3] = r[Y]; \ + dst[4] = g[Y]; \ + dst[5] = b[Y]; + +#define PUTBGR24(dst, src) \ + Y = src[0]; \ + dst[0] = b[Y]; \ + dst[1] = g[Y]; \ + dst[2] = r[Y]; \ + Y = src[1]; \ + dst[3] = b[Y]; \ + dst[4] = g[Y]; \ + dst[5] = r[Y]; + +#define PUTRGB(dst, src) \ + Y = src[0]; \ + dst[0] = r[Y] + g[Y] + b[Y]; \ + Y = src[1]; \ + dst[1] = r[Y] + g[Y] + b[Y]; \ + +#define ENDRES \ + pu += 1; \ + pv += 1; \ + py_1 += 2; \ + py_2 += 2; \ + image1 += 6; \ + image2 += 6; \ + +#define ENDRES32 \ + pu += 1; \ + pv += 1; \ + py_1 += 2; \ + py_2 += 2; \ + image1 += 2; \ + image2 += 2; \ + +#define END_FUNC() \ + } \ + } \ + return srcSliceH; \ +} + +YUV2RGBFUNC(yuv420_rgb24_lsx, uint8_t, 0) + LOAD_YUV_16 + YUV2RGB(m_y1, m_y2, m_u, m_v, r1, g1, b1, r2, g2, b2); + RGB_PACK(r1, g1, b1, rgb1_l, rgb1_h); + RGB_PACK(r2, g2, b2, rgb2_l, rgb2_h); + RGB_STORE(rgb1_l, rgb1_h, image1); + RGB_STORE(rgb2_l, rgb2_h, image2); + YUV2RGB(m_y1_h, m_y2_h, m_u_h, m_v_h, r1, g1, b1, r2, g2, b2); + RGB_PACK(r1, g1, b1, rgb1_l, rgb1_h); + RGB_PACK(r2, g2, b2, rgb2_l, rgb2_h); + RGB_STORE(rgb1_l, rgb1_h, image1 + 24); + RGB_STORE(rgb2_l, rgb2_h, image2 + 24); + DEALYUV2RGBREMAIN + PUTRGB24(image1, py_1); + PUTRGB24(image2, py_2); + ENDRES + END_FUNC() + +YUV2RGBFUNC(yuv420_bgr24_lsx, uint8_t, 0) + LOAD_YUV_16 + YUV2RGB(m_y1, m_y2, m_u, m_v, r1, g1, b1, r2, g2, b2); + RGB_PACK(b1, g1, r1, rgb1_l, rgb1_h); + RGB_PACK(b2, g2, r2, rgb2_l, rgb2_h); + RGB_STORE(rgb1_l, rgb1_h, image1); + RGB_STORE(rgb2_l, rgb2_h, image2); + YUV2RGB(m_y1_h, m_y2_h, m_u_h, m_v_h, r1, g1, b1, r2, g2, b2); + RGB_PACK(b1, g1, r1, rgb1_l, rgb1_h); + RGB_PACK(b2, g2, r2, rgb2_l, rgb2_h); + RGB_STORE(rgb1_l, rgb1_h, image1 + 24); + RGB_STORE(rgb2_l, rgb2_h, image2 + 24); + DEALYUV2RGBREMAIN + PUTBGR24(image1, py_1); + PUTBGR24(image2, py_2); + ENDRES + END_FUNC() + +YUV2RGBFUNC32(yuv420_rgba32_lsx, uint32_t, 0) + LOAD_YUV_16 + YUV2RGB(m_y1, m_y2, m_u, m_v, r1, g1, b1, r2, g2, b2); + RGB32_PACK(r1, g1, b1, a, rgb1_l, rgb1_h); + RGB32_PACK(r2, g2, b2, a, rgb2_l, rgb2_h); + RGB32_STORE(rgb1_l, rgb1_h, image1); + RGB32_STORE(rgb2_l, rgb2_h, image2); + YUV2RGB(m_y1_h, m_y2_h, m_u_h, m_v_h, r1, g1, b1, r2, g2, b2); + RGB32_PACK(r1, g1, b1, a, rgb1_l, rgb1_h); + RGB32_PACK(r2, g2, b2, a, rgb2_l, rgb2_h); + RGB32_STORE(rgb1_l, rgb1_h, image1 + 8); + RGB32_STORE(rgb2_l, rgb2_h, image2 + 8); + DEALYUV2RGBREMAIN32 + PUTRGB(image1, py_1); + PUTRGB(image2, py_2); + ENDRES32 + END_FUNC() + +YUV2RGBFUNC32(yuv420_bgra32_lsx, uint32_t, 0) + LOAD_YUV_16 + YUV2RGB(m_y1, m_y2, m_u, m_v, r1, g1, b1, r2, g2, b2); + RGB32_PACK(b1, g1, r1, a, rgb1_l, rgb1_h); + RGB32_PACK(b2, g2, r2, a, rgb2_l, rgb2_h); + RGB32_STORE(rgb1_l, rgb1_h, image1); + RGB32_STORE(rgb2_l, rgb2_h, image2); + YUV2RGB(m_y1_h, m_y2_h, m_u_h, m_v_h, r1, g1, b1, r2, g2, b2); + RGB32_PACK(b1, g1, r1, a, rgb1_l, rgb1_h); + RGB32_PACK(b2, g2, r2, a, rgb2_l, rgb2_h); + RGB32_STORE(rgb1_l, rgb1_h, image1 + 8); + RGB32_STORE(rgb2_l, rgb2_h, image2 + 8); + DEALYUV2RGBREMAIN32 + PUTRGB(image1, py_1); + PUTRGB(image2, py_2); + ENDRES32 + END_FUNC() + +YUV2RGBFUNC32(yuv420_argb32_lsx, uint32_t, 0) + LOAD_YUV_16 + YUV2RGB(m_y1, m_y2, m_u, m_v, r1, g1, b1, r2, g2, b2); + RGB32_PACK(a, r1, g1, b1, rgb1_l, rgb1_h); + RGB32_PACK(a, r2, g2, b2, rgb2_l, rgb2_h); + RGB32_STORE(rgb1_l, rgb1_h, image1); + RGB32_STORE(rgb2_l, rgb2_h, image2); + YUV2RGB(m_y1_h, m_y2_h, m_u_h, m_v_h, r1, g1, b1, r2, g2, b2); + RGB32_PACK(a, r1, g1, b1, rgb1_l, rgb1_h); + RGB32_PACK(a, r2, g2, b2, rgb2_l, rgb2_h); + RGB32_STORE(rgb1_l, rgb1_h, image1 + 8); + RGB32_STORE(rgb2_l, rgb2_h, image2 + 8); + DEALYUV2RGBREMAIN32 + PUTRGB(image1, py_1); + PUTRGB(image2, py_2); + ENDRES32 + END_FUNC() + +YUV2RGBFUNC32(yuv420_abgr32_lsx, uint32_t, 0) + LOAD_YUV_16 + YUV2RGB(m_y1, m_y2, m_u, m_v, r1, g1, b1, r2, g2, b2); + RGB32_PACK(a, b1, g1, r1, rgb1_l, rgb1_h); + RGB32_PACK(a, b2, g2, r2, rgb2_l, rgb2_h); + RGB32_STORE(rgb1_l, rgb1_h, image1); + RGB32_STORE(rgb2_l, rgb2_h, image2); + YUV2RGB(m_y1_h, m_y2_h, m_u_h, m_v_h, r1, g1, b1, r2, g2, b2); + RGB32_PACK(a, b1, g1, r1, rgb1_l, rgb1_h); + RGB32_PACK(a, b2, g2, r2, rgb2_l, rgb2_h); + RGB32_STORE(rgb1_l, rgb1_h, image1 + 8); + RGB32_STORE(rgb2_l, rgb2_h, image2 + 8); + DEALYUV2RGBREMAIN32 + PUTRGB(image1, py_1); + PUTRGB(image2, py_2); + ENDRES32 + END_FUNC() From 82278e874989b36f8f7f6b56651c12872bb40771 Mon Sep 17 00:00:00 2001 From: yuanhecai Date: Thu, 25 May 2023 15:24:32 +0800 Subject: [PATCH 1179/2172] avutil/la: Add function performance testing This patch supports the use of the "checkasm --bench" testing feature on loongarch platform. Change-Id: I42790388d057c9ade0dfa38a19d9c1fd44ca0bc3 Reviewed-by: Shiyou Yin Signed-off-by: Michael Niedermayer --- libavutil/loongarch/timer.h | 48 +++++++++++++++++++++++++++++++++++++ libavutil/timer.h | 2 ++ 2 files changed, 50 insertions(+) create mode 100644 libavutil/loongarch/timer.h diff --git a/libavutil/loongarch/timer.h b/libavutil/loongarch/timer.h new file mode 100644 index 00000000000..2f998aaba0a --- /dev/null +++ b/libavutil/loongarch/timer.h @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2023 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 AVUTIL_LOONGARCH_TIMER_H +#define AVUTIL_LOONGARCH_TIMER_H + +#include +#include "config.h" + +#if HAVE_INLINE_ASM + +#define AV_READ_TIME read_time + +static inline uint64_t read_time(void) +{ + +#if ARCH_LOONGARCH64 + uint64_t a, id; + __asm__ volatile ( "rdtime.d %0, %1" : "=r"(a), "=r"(id) :: ); + return a; +#else + uint32_t a, id; + __asm__ volatile ( "rdtimel.w %0, %1" : "=r"(a), "=r"(id) :: ); + return (uint64_t)a; +#endif +} + +#endif /* HAVE_INLINE_ASM */ + +#endif /* AVUTIL_LOONGARCH_TIMER_H */ diff --git a/libavutil/timer.h b/libavutil/timer.h index d3db5a27efa..861ba7e9d70 100644 --- a/libavutil/timer.h +++ b/libavutil/timer.h @@ -61,6 +61,8 @@ # include "riscv/timer.h" #elif ARCH_X86 # include "x86/timer.h" +#elif ARCH_LOONGARCH +# include "loongarch/timer.h" #endif #if !defined(AV_READ_TIME) From 3235de4883b694058f48ac4e13a9207c1fd94c04 Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Tue, 23 May 2023 00:30:22 +0200 Subject: [PATCH 1180/2172] avfilter/af_silenceremove: switch to activate Do full rewrite, new code is much faster for typical filter usages. Also previous code was hard to follow and basically very-hard to maintain. --- doc/filters.texi | 2 +- libavfilter/af_silenceremove.c | 965 ++++++--------------------- libavfilter/silenceremove_template.c | 293 ++++++++ 3 files changed, 496 insertions(+), 764 deletions(-) create mode 100644 libavfilter/silenceremove_template.c diff --git a/doc/filters.texi b/doc/filters.texi index 0c3ac116b8c..47b26fe92f3 100644 --- a/doc/filters.texi +++ b/doc/filters.texi @@ -6431,7 +6431,7 @@ Set the count for trimming silence from the end of audio. To remove silence from the middle of a file, specify a @var{stop_periods} that is negative. This value is then treated as a positive value and is used to indicate the effect should restart processing as specified by -@var{start_periods}, making it suitable for removing periods of silence +@var{stop_periods}, making it suitable for removing periods of silence in the middle of the audio. Default value is @code{0}. diff --git a/libavfilter/af_silenceremove.c b/libavfilter/af_silenceremove.c index d5a2ac6a410..e0592c2368c 100644 --- a/libavfilter/af_silenceremove.c +++ b/libavfilter/af_silenceremove.c @@ -23,11 +23,11 @@ #include /* DBL_MAX */ -#include "libavutil/audio_fifo.h" #include "libavutil/avassert.h" #include "libavutil/opt.h" #include "libavutil/timestamp.h" #include "audio.h" +#include "filters.h" #include "formats.h" #include "avfilter.h" #include "internal.h" @@ -42,69 +42,66 @@ enum ThresholdMode { T_ALL, }; -enum SilenceMode { - SILENCE_TRIM, - SILENCE_TRIM_FLUSH, - SILENCE_COPY, - SILENCE_COPY_FLUSH, - SILENCE_STOP -}; - typedef struct SilenceRemoveContext { const AVClass *class; - enum SilenceMode mode; - + int start_mode; int start_periods; int64_t start_duration; int64_t start_duration_opt; double start_threshold; int64_t start_silence; int64_t start_silence_opt; - int start_mode; + int stop_mode; int stop_periods; int64_t stop_duration; int64_t stop_duration_opt; double stop_threshold; int64_t stop_silence; int64_t stop_silence_opt; - int stop_mode; int64_t window_duration_opt; - AVFrame *start_holdoff; - AVFrame *start_silence_hold; - size_t start_holdoff_offset; - size_t start_holdoff_end; - size_t start_silence_offset; - size_t start_silence_end; - int start_found_periods; - - AVFrame *stop_holdoff; - AVFrame *stop_silence_hold; - size_t stop_holdoff_offset; - size_t stop_holdoff_end; - size_t stop_silence_offset; - size_t stop_silence_end; - int stop_found_periods; - - AVFrame *window; - int window_offset; + int start_found_periods; + int stop_found_periods; + + int start_sample_count; + int start_silence_count; + + int stop_sample_count; + int stop_silence_count; + + AVFrame *start_window; + AVFrame *stop_window; + int64_t window_duration; - double sum; - int one_period; + int start_window_pos; + int start_window_size; + + int stop_window_pos; + int stop_window_size; + + double *start_cache; + double *stop_cache; + + AVFrame *start_queuef; + int start_queue_pos; + int start_queue_size; + + AVFrame *stop_queuef; + int stop_queue_pos; + int stop_queue_size; + int restart; + int found_nonsilence; int64_t next_pts; int detection; - void (*update)(struct SilenceRemoveContext *s, AVFrame *frame, int ch, int offset); - double (*compute)(struct SilenceRemoveContext *s, AVFrame *frame, int ch, int offset); - void (*copy)(struct SilenceRemoveContext *s, AVFrame *out, AVFrame *in, - int ch, int out_offset, int in_offset); - AVAudioFifo *fifo; + float (*compute_flt)(float *c, float s, float ws, int size); + double (*compute_dbl)(double *c, double s, double ws, int size); } SilenceRemoveContext; #define OFFSET(x) offsetof(SilenceRemoveContext, x) @@ -119,7 +116,7 @@ static const AVOption silenceremove_options[] = { { "any", 0, 0, AV_OPT_TYPE_CONST, {.i64=T_ANY}, 0, 0, AF, "mode" }, { "all", 0, 0, AV_OPT_TYPE_CONST, {.i64=T_ALL}, 0, 0, AF, "mode" }, { "stop_periods", "set periods of silence parts to skip from end", OFFSET(stop_periods), AV_OPT_TYPE_INT, {.i64=0}, -9000, 9000, AF }, - { "stop_duration", "set stop duration of non-silence part", OFFSET(stop_duration_opt), AV_OPT_TYPE_DURATION, {.i64=0}, 0, INT32_MAX, AF }, + { "stop_duration", "set stop duration of silence part", OFFSET(stop_duration_opt), AV_OPT_TYPE_DURATION, {.i64=0}, 0, INT32_MAX, AF }, { "stop_threshold", "set threshold for stop silence detection", OFFSET(stop_threshold), AV_OPT_TYPE_DOUBLE, {.dbl=0}, 0, DBL_MAX, AF }, { "stop_silence", "set stop duration of silence part to keep", OFFSET(stop_silence_opt), AV_OPT_TYPE_DURATION, {.i64=0}, 0, INT32_MAX, AF }, { "stop_mode", "set which channel will trigger trimming from end", OFFSET(stop_mode), AV_OPT_TYPE_INT, {.i64=T_ANY}, T_ANY, T_ALL, AF, "mode" }, @@ -132,281 +129,12 @@ static const AVOption silenceremove_options[] = { AVFILTER_DEFINE_CLASS(silenceremove); -static void copy_double(SilenceRemoveContext *s, AVFrame *out, AVFrame *in, - int ch, int out_offset, int in_offset) -{ - const double *srcp = (const double *)in->data[0]; - const double src = srcp[in->ch_layout.nb_channels * in_offset + ch]; - double *dstp = (double *)out->data[0]; - - dstp[out->ch_layout.nb_channels * out_offset + ch] = src; -} - -static void copy_doublep(SilenceRemoveContext *s, AVFrame *out, AVFrame *in, - int ch, int out_offset, int in_offset) -{ - const double *srcp = (const double *)in->extended_data[ch]; - const double src = srcp[in_offset]; - double *dstp = (double *)out->extended_data[ch]; - - dstp[out_offset] = src; -} - -static void copy_float(SilenceRemoveContext *s, AVFrame *out, AVFrame *in, - int ch, int out_offset, int in_offset) -{ - const float *srcp = (const float *)in->data[0]; - const float src = srcp[in->ch_layout.nb_channels * in_offset + ch]; - float *dstp = (float *)out->data[0]; - - dstp[out->ch_layout.nb_channels * out_offset + ch] = src; -} - -static void copy_floatp(SilenceRemoveContext *s, AVFrame *out, AVFrame *in, - int ch, int out_offset, int in_offset) -{ - const float *srcp = (const float *)in->extended_data[ch]; - const float src = srcp[in_offset]; - float *dstp = (float *)out->extended_data[ch]; - - dstp[out_offset] = src; -} - -static double compute_peak_double(SilenceRemoveContext *s, AVFrame *frame, int ch, int offset) -{ - const double *samples = (const double *)frame->data[0]; - const double *wsamples = (const double *)s->window->data[0]; - double sample = samples[frame->ch_layout.nb_channels * offset + ch]; - double wsample = wsamples[frame->ch_layout.nb_channels * s->window_offset + ch]; - double new_sum; - - new_sum = s->sum; - new_sum -= wsample; - new_sum = fmax(new_sum, 0.); - new_sum += fabs(sample); - - return new_sum / s->window_duration; -} - -static void update_peak_double(SilenceRemoveContext *s, AVFrame *frame, int ch, int offset) -{ - const double *samples = (const double *)frame->data[0]; - double *wsamples = (double *)s->window->data[0]; - double sample = samples[frame->ch_layout.nb_channels * offset + ch]; - double *wsample = &wsamples[frame->ch_layout.nb_channels * s->window_offset + ch]; - - s->sum -= *wsample; - s->sum = fmax(s->sum, 0.); - *wsample = fabs(sample); - s->sum += *wsample; -} +#define DEPTH 32 +#include "silenceremove_template.c" -static double compute_peak_float(SilenceRemoveContext *s, AVFrame *frame, int ch, int offset) -{ - const float *samples = (const float *)frame->data[0]; - const float *wsamples = (const float *)s->window->data[0]; - float sample = samples[frame->ch_layout.nb_channels * offset + ch]; - float wsample = wsamples[frame->ch_layout.nb_channels * s->window_offset + ch]; - float new_sum; - - new_sum = s->sum; - new_sum -= wsample; - new_sum = fmaxf(new_sum, 0.f); - new_sum += fabsf(sample); - - return new_sum / s->window_duration; -} - -static void update_peak_float(SilenceRemoveContext *s, AVFrame *frame, int ch, int offset) -{ - const float *samples = (const float *)frame->data[0]; - float *wsamples = (float *)s->window->data[0]; - float sample = samples[frame->ch_layout.nb_channels * offset + ch]; - float *wsample = &wsamples[frame->ch_layout.nb_channels * s->window_offset + ch]; - - s->sum -= *wsample; - s->sum = fmaxf(s->sum, 0.f); - *wsample = fabsf(sample); - s->sum += *wsample; -} - -static double compute_rms_double(SilenceRemoveContext *s, AVFrame *frame, int ch, int offset) -{ - const double *samples = (const double *)frame->data[0]; - const double *wsamples = (const double *)s->window->data[0]; - double sample = samples[frame->ch_layout.nb_channels * offset + ch]; - double wsample = wsamples[frame->ch_layout.nb_channels * s->window_offset + ch]; - double new_sum; - - new_sum = s->sum; - new_sum -= wsample; - new_sum = fmax(new_sum, 0.); - new_sum += sample * sample; - - av_assert2(new_sum >= 0.); - return sqrt(new_sum / s->window_duration); -} - -static void update_rms_double(SilenceRemoveContext *s, AVFrame *frame, int ch, int offset) -{ - const double *samples = (const double *)frame->data[0]; - double *wsamples = (double *)s->window->data[0]; - double sample = samples[frame->ch_layout.nb_channels * offset + ch]; - double *wsample = &wsamples[frame->ch_layout.nb_channels * s->window_offset + ch]; - - s->sum -= *wsample; - s->sum = fmax(s->sum, 0.); - *wsample = sample * sample; - s->sum += *wsample; -} - -static double compute_rms_float(SilenceRemoveContext *s, AVFrame *frame, int ch, int offset) -{ - const float *samples = (const float *)frame->data[0]; - const float *wsamples = (const float *)s->window->data[0]; - float sample = samples[frame->ch_layout.nb_channels * offset + ch]; - float wsample = wsamples[frame->ch_layout.nb_channels * s->window_offset + ch]; - float new_sum; - - new_sum = s->sum; - new_sum -= wsample; - new_sum = fmaxf(new_sum, 0.f); - new_sum += sample * sample; - - av_assert2(new_sum >= 0.f); - return sqrtf(new_sum / s->window_duration); -} - -static void update_rms_float(SilenceRemoveContext *s, AVFrame *frame, int ch, int offset) -{ - const float *samples = (const float *)frame->data[0]; - float sample = samples[frame->ch_layout.nb_channels * offset + ch]; - float *wsamples = (float *)s->window->data[0]; - float *wsample = &wsamples[frame->ch_layout.nb_channels * s->window_offset + ch]; - - s->sum -= *wsample; - s->sum = fmaxf(s->sum, 0.f); - *wsample = sample * sample; - s->sum += *wsample; -} - -static double compute_peak_doublep(SilenceRemoveContext *s, AVFrame *frame, int ch, int offset) -{ - const double *samples = (const double *)frame->extended_data[ch]; - const double *wsamples = (const double *)s->window->extended_data[ch]; - double sample = samples[offset]; - double wsample = wsamples[s->window_offset]; - double new_sum; - - new_sum = s->sum; - new_sum -= wsample; - new_sum = fmax(new_sum, 0.); - new_sum += fabs(sample); - - return new_sum / s->window_duration; -} - -static void update_peak_doublep(SilenceRemoveContext *s, AVFrame *frame, int ch, int offset) -{ - const double *samples = (const double *)frame->extended_data[ch]; - double *wsamples = (double *)s->window->extended_data[ch]; - double sample = samples[offset]; - double *wsample = &wsamples[s->window_offset]; - - s->sum -= *wsample; - s->sum = fmax(s->sum, 0.); - *wsample = fabs(sample); - s->sum += *wsample; -} - -static double compute_peak_floatp(SilenceRemoveContext *s, AVFrame *frame, int ch, int offset) -{ - const float *samples = (const float *)frame->extended_data[ch]; - const float *wsamples = (const float *)s->window->extended_data[ch]; - float sample = samples[offset]; - float wsample = wsamples[s->window_offset]; - float new_sum; - - new_sum = s->sum; - new_sum -= wsample; - new_sum = fmaxf(new_sum, 0.f); - new_sum += fabsf(sample); - - return new_sum / s->window_duration; -} - -static void update_peak_floatp(SilenceRemoveContext *s, AVFrame *frame, int ch, int offset) -{ - const float *samples = (const float *)frame->extended_data[ch]; - float *wsamples = (float *)s->window->extended_data[ch]; - float sample = samples[offset]; - float *wsample = &wsamples[s->window_offset]; - - s->sum -= *wsample; - s->sum = fmaxf(s->sum, 0.f); - *wsample = fabsf(sample); - s->sum += *wsample; -} - -static double compute_rms_doublep(SilenceRemoveContext *s, AVFrame *frame, int ch, int offset) -{ - const double *samples = (const double *)frame->extended_data[ch]; - const double *wsamples = (const double *)s->window->extended_data[ch]; - double sample = samples[offset]; - double wsample = wsamples[s->window_offset]; - double new_sum; - - new_sum = s->sum; - new_sum -= wsample; - new_sum = fmax(new_sum, 0.); - new_sum += sample * sample; - - av_assert2(new_sum >= 0.); - return sqrt(new_sum / s->window_duration); -} - -static void update_rms_doublep(SilenceRemoveContext *s, AVFrame *frame, int ch, int offset) -{ - const double *samples = (const double *)frame->extended_data[ch]; - double *wsamples = (double *)s->window->extended_data[ch]; - double sample = samples[offset]; - double *wsample = &wsamples[s->window_offset]; - - s->sum -= *wsample; - s->sum = fmax(s->sum, 0.); - *wsample = sample * sample; - s->sum += *wsample; -} - -static double compute_rms_floatp(SilenceRemoveContext *s, AVFrame *frame, int ch, int offset) -{ - const float *samples = (const float *)frame->extended_data[ch]; - const float *wsamples = (const float *)s->window->extended_data[ch]; - float sample = samples[offset]; - float wsample = wsamples[s->window_offset]; - float new_sum; - - new_sum = s->sum; - new_sum -= wsample; - new_sum = fmaxf(new_sum, 0.f); - new_sum += sample * sample; - - av_assert2(new_sum >= 0.f); - return sqrtf(new_sum / s->window_duration); -} - -static void update_rms_floatp(SilenceRemoveContext *s, AVFrame *frame, int ch, int offset) -{ - const float *samples = (const float *)frame->extended_data[ch]; - float *wsamples = (float *)s->window->extended_data[ch]; - float sample = samples[offset]; - float *wsample = &wsamples[s->window_offset]; - - s->sum -= *wsample; - s->sum = fmaxf(s->sum, 0.f); - *wsample = sample * sample; - s->sum += *wsample; -} +#undef DEPTH +#define DEPTH 64 +#include "silenceremove_template.c" static av_cold int init(AVFilterContext *ctx) { @@ -420,13 +148,25 @@ static av_cold int init(AVFilterContext *ctx) return 0; } -static void clear_window(SilenceRemoveContext *s) +static void clear_windows(SilenceRemoveContext *s) { - av_samples_set_silence(s->window->extended_data, 0, s->window_duration, - s->window->ch_layout.nb_channels, s->window->format); - - s->window_offset = 0; - s->sum = 0; + av_samples_set_silence(s->start_window->extended_data, 0, + s->start_window->nb_samples, + s->start_window->ch_layout.nb_channels, + s->start_window->format); + av_samples_set_silence(s->stop_window->extended_data, 0, + s->stop_window->nb_samples, + s->stop_window->ch_layout.nb_channels, + s->stop_window->format); + + s->start_window_pos = 0; + s->start_window_size = 0; + s->stop_window_pos = 0; + s->stop_window_size = 0; + s->start_queue_pos = 0; + s->start_queue_size = 0; + s->stop_queue_pos = 0; + s->stop_queue_size = 0; } static int config_input(AVFilterLink *inlink) @@ -438,505 +178,204 @@ static int config_input(AVFilterLink *inlink) s->window_duration = av_rescale(s->window_duration_opt, inlink->sample_rate, AV_TIME_BASE); s->window_duration = FFMAX(1, s->window_duration); - s->window = ff_get_audio_buffer(ctx->outputs[0], s->window_duration); - if (!s->window) - return AVERROR(ENOMEM); - - clear_window(s); s->start_duration = av_rescale(s->start_duration_opt, inlink->sample_rate, AV_TIME_BASE); s->start_silence = av_rescale(s->start_silence_opt, inlink->sample_rate, AV_TIME_BASE); - s->stop_duration = av_rescale(s->stop_duration_opt, inlink->sample_rate, + s->stop_duration = av_rescale(s->stop_duration_opt, inlink->sample_rate, AV_TIME_BASE); - s->stop_silence = av_rescale(s->stop_silence_opt, inlink->sample_rate, + s->stop_silence = av_rescale(s->stop_silence_opt, inlink->sample_rate, AV_TIME_BASE); - s->start_holdoff = ff_get_audio_buffer(ctx->outputs[0], - FFMAX(s->start_duration, 1)); - if (!s->start_holdoff) - return AVERROR(ENOMEM); + s->start_found_periods = 0; + s->stop_found_periods = 0; - s->start_silence_hold = ff_get_audio_buffer(ctx->outputs[0], - FFMAX(s->start_silence, 1)); - if (!s->start_silence_hold) - return AVERROR(ENOMEM); + return 0; +} - s->start_holdoff_offset = 0; - s->start_holdoff_end = 0; - s->start_found_periods = 0; +static int config_output(AVFilterLink *outlink) +{ + AVFilterContext *ctx = outlink->src; + SilenceRemoveContext *s = ctx->priv; - s->stop_holdoff = ff_get_audio_buffer(ctx->outputs[0], - FFMAX(s->stop_duration, 1)); - if (!s->stop_holdoff) + s->start_window = ff_get_audio_buffer(outlink, s->window_duration); + s->stop_window = ff_get_audio_buffer(outlink, s->window_duration); + if (!s->start_window || !s->stop_window) return AVERROR(ENOMEM); - s->stop_silence_hold = ff_get_audio_buffer(ctx->outputs[0], - FFMAX(s->stop_silence, 1)); - if (!s->stop_silence_hold) + s->start_queuef = ff_get_audio_buffer(outlink, s->start_silence + 1); + s->stop_queuef = ff_get_audio_buffer(outlink, s->stop_silence + 1); + if (!s->start_queuef || !s->stop_queuef) return AVERROR(ENOMEM); - s->stop_holdoff_offset = 0; - s->stop_holdoff_end = 0; - s->stop_found_periods = 0; + s->start_cache = av_calloc(outlink->ch_layout.nb_channels, sizeof(*s->start_cache)); + s->stop_cache = av_calloc(outlink->ch_layout.nb_channels, sizeof(*s->stop_cache)); + if (!s->start_cache || !s->stop_cache) + return AVERROR(ENOMEM); - if (s->start_periods) { - s->mode = SILENCE_TRIM; - s->one_period = 1; - } else { - s->mode = SILENCE_COPY; - } + clear_windows(s); - switch (inlink->format) { - case AV_SAMPLE_FMT_DBL: - s->copy = copy_double; - switch (s->detection) { - case D_PEAK: - s->update = update_peak_double; - s->compute = compute_peak_double; - break; - case D_RMS: - s->update = update_rms_double; - s->compute = compute_rms_double; - break; - } - break; - case AV_SAMPLE_FMT_FLT: - s->copy = copy_float; - switch (s->detection) { - case D_PEAK: - s->update = update_peak_float; - s->compute = compute_peak_float; - break; - case D_RMS: - s->update = update_rms_float; - s->compute = compute_rms_float; - break; - } - break; - case AV_SAMPLE_FMT_DBLP: - s->copy = copy_doublep; - switch (s->detection) { - case D_PEAK: - s->update = update_peak_doublep; - s->compute = compute_peak_doublep; - break; - case D_RMS: - s->update = update_rms_doublep; - s->compute = compute_rms_doublep; - break; - } + switch (s->detection) { + case D_PEAK: + s->compute_flt = compute_peak_flt; + s->compute_dbl = compute_peak_dbl; break; - case AV_SAMPLE_FMT_FLTP: - s->copy = copy_floatp; - switch (s->detection) { - case D_PEAK: - s->update = update_peak_floatp; - s->compute = compute_peak_floatp; - break; - case D_RMS: - s->update = update_rms_floatp; - s->compute = compute_rms_floatp; - break; - } + case D_RMS: + s->compute_flt = compute_rms_flt; + s->compute_dbl = compute_rms_dbl; break; - default: - return AVERROR_BUG; } - s->fifo = av_audio_fifo_alloc(inlink->format, inlink->ch_layout.nb_channels, 1024); - if (!s->fifo) - return AVERROR(ENOMEM); - return 0; } -static void flush(SilenceRemoveContext *s, - AVFrame *out, AVFilterLink *outlink, - int *nb_samples_written, int flush_silence) +static int filter_frame(AVFilterLink *outlink, AVFrame *in) { - AVFrame *silence; - - if (*nb_samples_written) { - out->nb_samples = *nb_samples_written; - - av_audio_fifo_write(s->fifo, (void **)out->extended_data, out->nb_samples); - *nb_samples_written = 0; - } - - av_frame_free(&out); - - if (s->stop_silence_end <= 0 || !flush_silence) - return; - - silence = ff_get_audio_buffer(outlink, s->stop_silence_end); - if (!silence) - return; - - if (s->stop_silence_offset < s->stop_silence_end) { - av_samples_copy(silence->extended_data, s->stop_silence_hold->extended_data, 0, - s->stop_silence_offset, - s->stop_silence_end - s->stop_silence_offset, - outlink->ch_layout.nb_channels, outlink->format); - } - - if (s->stop_silence_offset > 0) { - av_samples_copy(silence->extended_data, s->stop_silence_hold->extended_data, - s->stop_silence_end - s->stop_silence_offset, - 0, s->stop_silence_offset, - outlink->ch_layout.nb_channels, outlink->format); - } - - s->stop_silence_offset = 0; - s->stop_silence_end = 0; - - av_audio_fifo_write(s->fifo, (void **)silence->extended_data, silence->nb_samples); - av_frame_free(&silence); -} - -static int filter_frame(AVFilterLink *inlink, AVFrame *in) -{ - AVFilterContext *ctx = inlink->dst; - AVFilterLink *outlink = ctx->outputs[0]; + const int nb_channels = outlink->ch_layout.nb_channels; + AVFilterContext *ctx = outlink->src; SilenceRemoveContext *s = ctx->priv; - int nbs, nb_samples_read, nb_samples_written; - int i, j, threshold, ret = 0; + int max_out_nb_samples; + int out_nb_samples = 0; + int in_nb_samples; + const double *srcd; + const float *srcf; AVFrame *out; - - nb_samples_read = nb_samples_written = 0; + double *dstd; + float *dstf; if (s->next_pts == AV_NOPTS_VALUE) s->next_pts = in->pts; - switch (s->mode) { - case SILENCE_TRIM: -silence_trim: - nbs = in->nb_samples - nb_samples_read; - if (!nbs) - break; - - for (i = 0; i < nbs; i++) { - if (s->start_mode == T_ANY) { - threshold = 0; - for (j = 0; j < outlink->ch_layout.nb_channels; j++) { - threshold |= s->compute(s, in, j, nb_samples_read) > s->start_threshold; - } - } else { - threshold = 1; - for (j = 0; j < outlink->ch_layout.nb_channels; j++) { - threshold &= s->compute(s, in, j, nb_samples_read) > s->start_threshold; - } - } - - if (threshold) { - for (j = 0; j < outlink->ch_layout.nb_channels; j++) { - s->update(s, in, j, nb_samples_read); - s->copy(s, s->start_holdoff, in, j, s->start_holdoff_end, nb_samples_read); - } - - s->window_offset++; - if (s->window_offset >= s->window_duration) - s->window_offset = 0; - s->start_holdoff_end++; - nb_samples_read++; - - if (s->start_holdoff_end >= s->start_duration) { - s->start_found_periods += s->one_period >= 1; - s->one_period = 0; - if (s->start_found_periods >= s->start_periods) { - s->mode = SILENCE_TRIM_FLUSH; - goto silence_trim_flush; - } - - s->start_holdoff_offset = 0; - s->start_holdoff_end = 0; - s->start_silence_offset = 0; - s->start_silence_end = 0; - } - } else { - s->start_holdoff_end = 0; - s->one_period++; - - for (j = 0; j < outlink->ch_layout.nb_channels; j++) { - s->update(s, in, j, nb_samples_read); - if (s->start_silence) - s->copy(s, s->start_silence_hold, in, j, s->start_silence_offset, nb_samples_read); - } - - s->window_offset++; - if (s->window_offset >= s->window_duration) - s->window_offset = 0; - nb_samples_read++; - s->start_silence_offset++; - - if (s->start_silence) { - s->start_silence_end = FFMIN(s->start_silence_end + 1, s->start_silence); - if (s->start_silence_offset >= s->start_silence) - s->start_silence_offset = 0; - } - } - } - break; + in_nb_samples = in->nb_samples; + max_out_nb_samples = in->nb_samples + + s->start_silence + + s->stop_silence; + if (max_out_nb_samples <= 0) { + av_frame_free(&in); + ff_filter_set_ready(ctx, 100); + return 0; + } - case SILENCE_TRIM_FLUSH: -silence_trim_flush: - nbs = s->start_holdoff_end - s->start_holdoff_offset; - if (!nbs) - break; + out = ff_get_audio_buffer(outlink, max_out_nb_samples); + if (!out) { + av_frame_free(&in); + return AVERROR(ENOMEM); + } - out = ff_get_audio_buffer(outlink, nbs + s->start_silence_end); - if (!out) { - av_frame_free(&in); - return AVERROR(ENOMEM); - } + out->pts = s->next_pts; - if (s->start_silence_end > 0) { - if (s->start_silence_offset < s->start_silence_end) { - av_samples_copy(out->extended_data, s->start_silence_hold->extended_data, 0, - s->start_silence_offset, - s->start_silence_end - s->start_silence_offset, - outlink->ch_layout.nb_channels, outlink->format); + switch (outlink->format) { + case AV_SAMPLE_FMT_FLT: + srcf = (const float *)in->data[0]; + dstf = (float *)out->data[0]; + if (s->start_periods > 0 && s->stop_periods > 0) { + for (int n = 0; n < in_nb_samples; n++) { + filter_start_flt(ctx, srcf + n * nb_channels, + dstf, &out_nb_samples, + nb_channels); } - - if (s->start_silence_offset > 0) { - av_samples_copy(out->extended_data, s->start_silence_hold->extended_data, - s->start_silence_end - s->start_silence_offset, - 0, s->start_silence_offset, - outlink->ch_layout.nb_channels, outlink->format); + in_nb_samples = out_nb_samples; + out_nb_samples = 0; + for (int n = 0; n < in_nb_samples; n++) { + filter_stop_flt(ctx, dstf + n * nb_channels, + dstf, &out_nb_samples, + nb_channels); } - } - - av_samples_copy(out->extended_data, s->start_holdoff->extended_data, - s->start_silence_end, - s->start_holdoff_offset, nbs, - outlink->ch_layout.nb_channels, outlink->format); - - s->start_holdoff_offset += nbs; - - av_audio_fifo_write(s->fifo, (void **)out->extended_data, out->nb_samples); - av_frame_free(&out); - - if (s->start_holdoff_offset == s->start_holdoff_end) { - s->start_holdoff_offset = 0; - s->start_holdoff_end = 0; - s->start_silence_offset = 0; - s->start_silence_end = 0; - s->mode = SILENCE_COPY; - goto silence_copy; - } - break; - - case SILENCE_COPY: -silence_copy: - nbs = in->nb_samples - nb_samples_read; - if (!nbs) - break; - - out = ff_get_audio_buffer(outlink, nbs); - if (!out) { - av_frame_free(&in); - return AVERROR(ENOMEM); - } - - if (s->stop_periods) { - for (i = 0; i < nbs; i++) { - if (s->stop_mode == T_ANY) { - threshold = 0; - for (j = 0; j < outlink->ch_layout.nb_channels; j++) { - threshold |= s->compute(s, in, j, nb_samples_read) > s->stop_threshold; - } - } else { - threshold = 1; - for (j = 0; j < outlink->ch_layout.nb_channels; j++) { - threshold &= s->compute(s, in, j, nb_samples_read) > s->stop_threshold; - } - } - - if (threshold && s->stop_holdoff_end && !s->stop_silence) { - s->mode = SILENCE_COPY_FLUSH; - flush(s, out, outlink, &nb_samples_written, 0); - s->one_period++; - goto silence_copy_flush; - } else if (threshold) { - for (j = 0; j < outlink->ch_layout.nb_channels; j++) { - s->update(s, in, j, nb_samples_read); - s->copy(s, out, in, j, nb_samples_written, nb_samples_read); - } - - s->window_offset++; - if (s->window_offset >= s->window_duration) - s->window_offset = 0; - nb_samples_read++; - nb_samples_written++; - s->one_period++; - } else if (!threshold) { - for (j = 0; j < outlink->ch_layout.nb_channels; j++) { - s->update(s, in, j, nb_samples_read); - if (s->stop_silence) - s->copy(s, s->stop_silence_hold, in, j, s->stop_silence_offset, nb_samples_read); - - s->copy(s, s->stop_holdoff, in, j, s->stop_holdoff_end, nb_samples_read); - } - - if (s->stop_silence) { - s->stop_silence_offset++; - s->stop_silence_end = FFMIN(s->stop_silence_end + 1, s->stop_silence); - if (s->stop_silence_offset >= s->stop_silence) { - s->stop_silence_offset = 0; - } - } - - s->window_offset++; - if (s->window_offset >= s->window_duration) - s->window_offset = 0; - nb_samples_read++; - s->stop_holdoff_end++; - - if (s->stop_holdoff_end >= s->stop_duration) { - s->stop_found_periods += s->one_period >= 1; - s->one_period = 0; - if (s->stop_found_periods >= s->stop_periods) { - s->stop_holdoff_offset = 0; - s->stop_holdoff_end = 0; - - if (!s->restart) { - s->mode = SILENCE_STOP; - flush(s, out, outlink, &nb_samples_written, 1); - goto silence_stop; - } else { - s->stop_found_periods = 0; - s->start_found_periods = 0; - s->start_holdoff_offset = 0; - s->start_holdoff_end = 0; - s->start_silence_offset = 0; - s->start_silence_end = 0; - clear_window(s); - s->mode = SILENCE_TRIM; - flush(s, out, outlink, &nb_samples_written, 1); - goto silence_trim; - } - } - s->mode = SILENCE_COPY_FLUSH; - flush(s, out, outlink, &nb_samples_written, 0); - goto silence_copy_flush; - } - } + } else if (s->start_periods > 0) { + for (int n = 0; n < in_nb_samples; n++) { + filter_start_flt(ctx, srcf + n * nb_channels, + dstf, &out_nb_samples, + nb_channels); + } + } else if (s->stop_periods > 0) { + for (int n = 0; n < in_nb_samples; n++) { + filter_stop_flt(ctx, srcf + n * nb_channels, + dstf, &out_nb_samples, + nb_channels); } - s->one_period++; - flush(s, out, outlink, &nb_samples_written, 0); - } else { - av_samples_copy(out->extended_data, in->extended_data, - nb_samples_written, - nb_samples_read, nbs, - outlink->ch_layout.nb_channels, outlink->format); - - av_audio_fifo_write(s->fifo, (void **)out->extended_data, out->nb_samples); - av_frame_free(&out); } break; - - case SILENCE_COPY_FLUSH: -silence_copy_flush: - nbs = s->stop_holdoff_end - s->stop_holdoff_offset; - if (!nbs) - break; - - out = ff_get_audio_buffer(outlink, nbs); - if (!out) { - av_frame_free(&in); - return AVERROR(ENOMEM); - } - - av_samples_copy(out->extended_data, s->stop_holdoff->extended_data, 0, - s->stop_holdoff_offset, nbs, - outlink->ch_layout.nb_channels, outlink->format); - - s->stop_holdoff_offset += nbs; - - av_audio_fifo_write(s->fifo, (void **)out->extended_data, out->nb_samples); - av_frame_free(&out); - - if (s->stop_holdoff_offset == s->stop_holdoff_end) { - s->stop_holdoff_offset = 0; - s->stop_holdoff_end = 0; - s->stop_silence_offset = 0; - s->stop_silence_end = 0; - s->mode = SILENCE_COPY; - goto silence_copy; + case AV_SAMPLE_FMT_DBL: + srcd = (const double *)in->data[0]; + dstd = (double *)out->data[0]; + if (s->start_periods > 0 && s->stop_periods > 0) { + for (int n = 0; n < in_nb_samples; n++) { + filter_start_dbl(ctx, srcd + n * nb_channels, + dstd, &out_nb_samples, + nb_channels); + } + in_nb_samples = out_nb_samples; + out_nb_samples = 0; + for (int n = 0; n < in_nb_samples; n++) { + filter_stop_dbl(ctx, dstd + n * nb_channels, + dstd, &out_nb_samples, + nb_channels); + } + } else if (s->start_periods > 0) { + for (int n = 0; n < in_nb_samples; n++) { + filter_start_dbl(ctx, srcd + n * nb_channels, + dstd, &out_nb_samples, + nb_channels); + } + } else if (s->stop_periods > 0) { + for (int n = 0; n < in_nb_samples; n++) { + filter_stop_dbl(ctx, srcd + n * nb_channels, + dstd, &out_nb_samples, + nb_channels); + } } break; - case SILENCE_STOP: -silence_stop: - break; - default: - ret = AVERROR_BUG; } av_frame_free(&in); - - if (av_audio_fifo_size(s->fifo) > 0) { - out = ff_get_audio_buffer(outlink, av_audio_fifo_size(s->fifo)); - if (!out) - return AVERROR(ENOMEM); - - av_audio_fifo_read(s->fifo, (void **)out->extended_data, out->nb_samples); - out->pts = s->next_pts; - s->next_pts += av_rescale_q(out->nb_samples, - (AVRational){1, outlink->sample_rate}, - outlink->time_base); - - ret = ff_filter_frame(outlink, out); + if (out_nb_samples > 0) { + s->next_pts += out_nb_samples; + out->nb_samples = out_nb_samples; + return ff_filter_frame(outlink, out); } - return ret; + av_frame_free(&out); + ff_filter_set_ready(ctx, 100); + + return 0; } -static int request_frame(AVFilterLink *outlink) +static int activate(AVFilterContext *ctx) { - AVFilterContext *ctx = outlink->src; + AVFilterLink *outlink = ctx->outputs[0]; + AVFilterLink *inlink = ctx->inputs[0]; SilenceRemoveContext *s = ctx->priv; + AVFrame *in; int ret; - ret = ff_request_frame(ctx->inputs[0]); - if (ret == AVERROR_EOF && (s->mode == SILENCE_COPY_FLUSH || - s->mode == SILENCE_COPY)) { - int nbs = s->stop_holdoff_end - s->stop_holdoff_offset; - if (nbs) { - AVFrame *frame; + FF_FILTER_FORWARD_STATUS_BACK(outlink, inlink); - frame = ff_get_audio_buffer(outlink, nbs); - if (!frame) - return AVERROR(ENOMEM); - - av_samples_copy(frame->extended_data, s->stop_holdoff->extended_data, 0, - s->stop_holdoff_offset, nbs, - outlink->ch_layout.nb_channels, outlink->format); + ret = ff_inlink_consume_frame(inlink, &in); + if (ret < 0) + return ret; + if (ret > 0) { + if (s->start_periods == 0 && s->stop_periods == 0) + return ff_filter_frame(outlink, in); + return filter_frame(outlink, in); + } - frame->pts = s->next_pts; - s->next_pts += av_rescale_q(frame->nb_samples, - (AVRational){1, outlink->sample_rate}, - outlink->time_base); + FF_FILTER_FORWARD_STATUS(inlink, outlink); + FF_FILTER_FORWARD_WANTED(outlink, inlink); - ret = ff_filter_frame(outlink, frame); - } - s->mode = SILENCE_STOP; - } - return ret; + return FFERROR_NOT_READY; } static av_cold void uninit(AVFilterContext *ctx) { SilenceRemoveContext *s = ctx->priv; - av_frame_free(&s->start_holdoff); - av_frame_free(&s->start_silence_hold); - av_frame_free(&s->stop_holdoff); - av_frame_free(&s->stop_silence_hold); - av_frame_free(&s->window); - - av_audio_fifo_free(s->fifo); - s->fifo = NULL; + av_frame_free(&s->start_window); + av_frame_free(&s->stop_window); + av_frame_free(&s->start_queuef); + av_frame_free(&s->stop_queuef); + av_freep(&s->start_cache); + av_freep(&s->stop_cache); } static const AVFilterPad silenceremove_inputs[] = { @@ -944,15 +383,14 @@ static const AVFilterPad silenceremove_inputs[] = { .name = "default", .type = AVMEDIA_TYPE_AUDIO, .config_props = config_input, - .filter_frame = filter_frame, }, }; static const AVFilterPad silenceremove_outputs[] = { { - .name = "default", - .type = AVMEDIA_TYPE_AUDIO, - .request_frame = request_frame, + .name = "default", + .type = AVMEDIA_TYPE_AUDIO, + .config_props = config_output, }, }; @@ -962,9 +400,10 @@ const AVFilter ff_af_silenceremove = { .priv_size = sizeof(SilenceRemoveContext), .priv_class = &silenceremove_class, .init = init, + .activate = activate, .uninit = uninit, FILTER_INPUTS(silenceremove_inputs), FILTER_OUTPUTS(silenceremove_outputs), - FILTER_SAMPLEFMTS(AV_SAMPLE_FMT_FLT, AV_SAMPLE_FMT_FLTP, - AV_SAMPLE_FMT_DBL, AV_SAMPLE_FMT_DBLP), + FILTER_SAMPLEFMTS(AV_SAMPLE_FMT_FLT, + AV_SAMPLE_FMT_DBL), }; diff --git a/libavfilter/silenceremove_template.c b/libavfilter/silenceremove_template.c new file mode 100644 index 00000000000..1a12435ee61 --- /dev/null +++ b/libavfilter/silenceremove_template.c @@ -0,0 +1,293 @@ +/* + * 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 + */ + +#undef ftype +#undef FABS +#undef FMAX +#undef SAMPLE_FORMAT +#undef SQRT +#undef ZERO +#if DEPTH == 32 +#define SAMPLE_FORMAT flt +#define SQRT sqrtf +#define FMAX fmaxf +#define FABS fabsf +#define ftype float +#define ZERO 0.f +#else +#define SAMPLE_FORMAT dbl +#define SQRT sqrt +#define FMAX fmax +#define FABS fabs +#define ftype double +#define ZERO 0.0 +#endif + +#define fn3(a,b) a##_##b +#define fn2(a,b) fn3(a,b) +#define fn(a) fn2(a, SAMPLE_FORMAT) + +static void fn(flush)(ftype *dst, const ftype *src, int src_pos, + int nb_channels, int count, int src_nb_samples, + int *out_nb_samples) +{ + int oidx, out_count = count; + int sidx = src_pos; + + if (count <= 0) + return; + + oidx = *out_nb_samples + out_count - 1; + *out_nb_samples += out_count; + while (out_count-- > 0) { + const int spos = sidx * nb_channels; + const int opos = oidx * nb_channels; + + for (int ch = 0; ch < nb_channels; ch++) + dst[opos + ch] = src[spos + ch]; + + oidx--; + sidx--; + if (sidx < 0) + sidx = src_nb_samples - 1; + } +} + +static void fn(queue_sample)(AVFilterContext *ctx, + const ftype *src, + ftype *queue, + int *queue_pos, + int *queue_size, + int *window_pos, + int *window_size, + const int nb_channels, + const int nb_samples, + const int window_nb_samples) +{ + const int pos = *queue_pos * nb_channels; + + for (int ch = 0; ch < nb_channels; ch++) + queue[pos + ch] = src[ch]; + + (*queue_pos)++; + if (*queue_pos >= nb_samples) + *queue_pos = 0; + + if (*queue_size < nb_samples) + (*queue_size)++; + + if (*window_size < window_nb_samples) + (*window_size)++; + + (*window_pos)++; + if (*window_pos >= window_nb_samples) + *window_pos = 0; +} + +static ftype fn(compute_peak)(ftype *cache, ftype sample, ftype wsample, + int window_size) +{ + ftype r; + + cache[0] += FABS(sample); + cache[0] -= FABS(wsample); + cache[0] = r = FMAX(cache[0], ZERO); + + return r / window_size; +} + +static ftype fn(compute_rms)(ftype *cache, ftype sample, ftype wsample, + int window_size) +{ + ftype r; + + cache[0] += sample * sample; + cache[0] -= wsample * wsample; + cache[0] = r = FMAX(cache[0], ZERO); + + return SQRT(r / window_size); +} + +static void fn(filter_start)(AVFilterContext *ctx, + const ftype *src, ftype *dst, + int *nb_out_samples, + const int nb_channels) +{ + SilenceRemoveContext *s = ctx->priv; + const int start_periods = s->start_periods; + int out_nb_samples = *nb_out_samples; + const int start_window_nb_samples = s->start_window->nb_samples; + const int start_nb_samples = s->start_queuef->nb_samples; + const int start_wpos = s->start_window_pos * nb_channels; + const int start_pos = s->start_queue_pos * nb_channels; + ftype *startw = (ftype *)s->start_window->data[0]; + ftype *start = (ftype *)s->start_queuef->data[0]; + const ftype start_threshold = s->start_threshold; + const int start_mode = s->start_mode; + int start_thres = (start_mode == T_ANY) ? 0 : 1; + const int start_duration = s->start_duration; + ftype *start_cache = (ftype *)s->start_cache; + const int start_silence = s->start_silence; + + fn(queue_sample)(ctx, src, start, + &s->start_queue_pos, + &s->start_queue_size, + &s->start_window_pos, + &s->start_window_size, + nb_channels, + start_nb_samples, + start_window_nb_samples); + + for (int ch = 0; ch < nb_channels; ch++) { + ftype start_sample = start[start_pos + ch]; + ftype start_ow = startw[start_wpos + ch]; + ftype tstart; + + tstart = fn(s->compute)(start_cache + ch, + start_sample, + start_ow, + s->start_window_size); + + startw[start_wpos + ch] = start_sample; + + if (start_mode == T_ANY) { + start_thres |= tstart > start_threshold; + } else { + start_thres &= tstart > start_threshold; + } + } + + if (s->start_found_periods >= 0) { + if (start_silence > 0) { + s->start_silence_count++; + if (s->start_silence_count > start_silence) + s->start_silence_count = start_silence; + } + + s->start_sample_count += start_thres; + } + + if (s->start_sample_count > start_duration) { + s->start_found_periods++; + if (s->start_found_periods >= start_periods) { + fn(flush)(dst, start, s->start_queue_pos, nb_channels, + s->start_silence_count, start_nb_samples, + &out_nb_samples); + s->start_silence_count = 0; + s->start_found_periods = -1; + } + + s->start_sample_count = 0; + } + + if (s->start_found_periods < 0) { + const int dst_pos = out_nb_samples * nb_channels; + for (int ch = 0; ch < nb_channels; ch++) + dst[dst_pos + ch] = start[start_pos + ch]; + out_nb_samples++; + } + + *nb_out_samples = out_nb_samples; +} + +static void fn(filter_stop)(AVFilterContext *ctx, + const ftype *src, ftype *dst, + int *nb_out_samples, + const int nb_channels) +{ + SilenceRemoveContext *s = ctx->priv; + const int stop_periods = s->stop_periods; + int out_nb_samples = *nb_out_samples; + const int stop_window_nb_samples = s->stop_window->nb_samples; + const int stop_nb_samples = s->stop_queuef->nb_samples; + const int stop_wpos = s->stop_window_pos * nb_channels; + const int stop_pos = s->stop_queue_pos * nb_channels; + ftype *stopw = (ftype *)s->stop_window->data[0]; + const ftype stop_threshold = s->stop_threshold; + ftype *stop = (ftype *)s->stop_queuef->data[0]; + const int stop_mode = s->stop_mode; + int stop_thres = (stop_mode == T_ANY) ? 0 : 1; + const int stop_duration = s->stop_duration; + ftype *stop_cache = (ftype *)s->stop_cache; + const int stop_silence = s->stop_silence; + const int restart = s->restart; + + fn(queue_sample)(ctx, src, stop, + &s->stop_queue_pos, + &s->stop_queue_size, + &s->stop_window_pos, + &s->stop_window_size, + nb_channels, + stop_nb_samples, + stop_window_nb_samples); + + for (int ch = 0; ch < nb_channels; ch++) { + ftype stop_sample = stop[stop_pos + ch]; + ftype stop_ow = stopw[stop_wpos + ch]; + ftype tstop; + + tstop = fn(s->compute)(stop_cache + ch, + stop_sample, + stop_ow, + s->stop_window_size); + + stopw[stop_wpos + ch] = stop_sample; + + if (stop_mode == T_ANY) { + stop_thres |= tstop <= stop_threshold; + } else { + stop_thres &= tstop <= stop_threshold; + } + } + + s->found_nonsilence = FFMAX(s->found_nonsilence, !stop_thres); + if (restart && !stop_thres) + s->stop_found_periods = 0; + + if (s->stop_found_periods >= 0) { + if (s->found_nonsilence) { + s->stop_sample_count += stop_thres; + s->stop_sample_count *= stop_thres; + } + } else if (s->stop_silence_count > 0) { + const int dst_pos = out_nb_samples * nb_channels; + for (int ch = 0; ch < nb_channels; ch++) + dst[dst_pos + ch] = stop[stop_pos + ch]; + s->stop_silence_count--; + out_nb_samples++; + } + + if (s->stop_sample_count > stop_duration) { + s->stop_found_periods++; + if (s->stop_found_periods >= stop_periods) { + s->stop_found_periods = -1; + s->stop_silence_count = stop_silence; + } + + s->stop_sample_count = 0; + } + + if (s->stop_found_periods >= 0) { + const int dst_pos = out_nb_samples * nb_channels; + for (int ch = 0; ch < nb_channels; ch++) + dst[dst_pos + ch] = stop[stop_pos + ch]; + out_nb_samples++; + } + + *nb_out_samples = out_nb_samples; +} From 2b5166addf9956f0617e6007bc02387cde9927dd Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Thu, 25 May 2023 23:06:50 +0200 Subject: [PATCH 1181/2172] avfilter/af_silenceremove: add real peak detector Rename old peak detector to more correct name one. --- doc/filters.texi | 3 +- libavfilter/af_silenceremove.c | 42 ++++++++++++---- libavfilter/silenceremove_template.c | 71 +++++++++++++++++++++++++--- tests/fate/filter-audio.mak | 2 +- 4 files changed, 98 insertions(+), 20 deletions(-) diff --git a/doc/filters.texi b/doc/filters.texi index 47b26fe92f3..6f15b54d107 100644 --- a/doc/filters.texi +++ b/doc/filters.texi @@ -6461,8 +6461,7 @@ With @var{all}, only if all channels are detected as non-silence will cause stopped trimming of silence. @item detection -Set how is silence detected. Can be @code{rms} or @code{peak}. Second is faster -and works better with digital silence which is exactly 0. +Set how is silence detected. Can be @code{avg}, @code{rms} or @code{peak}. Default value is @code{rms}. @item window diff --git a/libavfilter/af_silenceremove.c b/libavfilter/af_silenceremove.c index e0592c2368c..28c972f86f7 100644 --- a/libavfilter/af_silenceremove.c +++ b/libavfilter/af_silenceremove.c @@ -33,8 +33,10 @@ #include "internal.h" enum SilenceDetect { - D_PEAK, + D_AVG, D_RMS, + D_PEAK, + D_NB }; enum ThresholdMode { @@ -75,6 +77,12 @@ typedef struct SilenceRemoveContext { AVFrame *start_window; AVFrame *stop_window; + int *start_front; + int *start_back; + + int *stop_front; + int *stop_back; + int64_t window_duration; int start_window_pos; @@ -100,8 +108,8 @@ typedef struct SilenceRemoveContext { int detection; - float (*compute_flt)(float *c, float s, float ws, int size); - double (*compute_dbl)(double *c, double s, double ws, int size); + float (*compute_flt)(float *c, float s, float ws, int size, int *front, int *back); + double (*compute_dbl)(double *c, double s, double ws, int size, int *front, int *back); } SilenceRemoveContext; #define OFFSET(x) offsetof(SilenceRemoveContext, x) @@ -120,9 +128,10 @@ static const AVOption silenceremove_options[] = { { "stop_threshold", "set threshold for stop silence detection", OFFSET(stop_threshold), AV_OPT_TYPE_DOUBLE, {.dbl=0}, 0, DBL_MAX, AF }, { "stop_silence", "set stop duration of silence part to keep", OFFSET(stop_silence_opt), AV_OPT_TYPE_DURATION, {.i64=0}, 0, INT32_MAX, AF }, { "stop_mode", "set which channel will trigger trimming from end", OFFSET(stop_mode), AV_OPT_TYPE_INT, {.i64=T_ANY}, T_ANY, T_ALL, AF, "mode" }, - { "detection", "set how silence is detected", OFFSET(detection), AV_OPT_TYPE_INT, {.i64=D_RMS}, D_PEAK,D_RMS, AF, "detection" }, - { "peak", "use absolute values of samples", 0, AV_OPT_TYPE_CONST, {.i64=D_PEAK},0, 0, AF, "detection" }, - { "rms", "use squared values of samples", 0, AV_OPT_TYPE_CONST, {.i64=D_RMS}, 0, 0, AF, "detection" }, + { "detection", "set how silence is detected", OFFSET(detection), AV_OPT_TYPE_INT, {.i64=D_RMS}, 0, D_NB-1, AF, "detection" }, + { "avg", "use mean absolute values of samples", 0, AV_OPT_TYPE_CONST, {.i64=D_AVG}, 0, 0, AF, "detection" }, + { "rms", "use root mean squared values of samples", 0, AV_OPT_TYPE_CONST, {.i64=D_RMS}, 0, 0, AF, "detection" }, + { "peak", "use max absolute values of samples", 0, AV_OPT_TYPE_CONST, {.i64=D_PEAK},0, 0, AF, "detection" }, { "window", "set duration of window for silence detection", OFFSET(window_duration_opt), AV_OPT_TYPE_DURATION, {.i64=20000}, 0, 100000000, AF }, { NULL } }; @@ -201,7 +210,9 @@ static int config_output(AVFilterLink *outlink) s->start_window = ff_get_audio_buffer(outlink, s->window_duration); s->stop_window = ff_get_audio_buffer(outlink, s->window_duration); - if (!s->start_window || !s->stop_window) + s->start_cache = av_calloc(outlink->ch_layout.nb_channels, s->window_duration * sizeof(*s->start_cache)); + s->stop_cache = av_calloc(outlink->ch_layout.nb_channels, s->window_duration * sizeof(*s->stop_cache)); + if (!s->start_window || !s->stop_window || !s->start_cache || !s->stop_cache) return AVERROR(ENOMEM); s->start_queuef = ff_get_audio_buffer(outlink, s->start_silence + 1); @@ -209,14 +220,20 @@ static int config_output(AVFilterLink *outlink) if (!s->start_queuef || !s->stop_queuef) return AVERROR(ENOMEM); - s->start_cache = av_calloc(outlink->ch_layout.nb_channels, sizeof(*s->start_cache)); - s->stop_cache = av_calloc(outlink->ch_layout.nb_channels, sizeof(*s->stop_cache)); - if (!s->start_cache || !s->stop_cache) + s->start_front = av_calloc(outlink->ch_layout.nb_channels, sizeof(*s->start_front)); + s->start_back = av_calloc(outlink->ch_layout.nb_channels, sizeof(*s->start_back)); + s->stop_front = av_calloc(outlink->ch_layout.nb_channels, sizeof(*s->stop_front)); + s->stop_back = av_calloc(outlink->ch_layout.nb_channels, sizeof(*s->stop_back)); + if (!s->start_front || !s->start_back || !s->stop_front || !s->stop_back) return AVERROR(ENOMEM); clear_windows(s); switch (s->detection) { + case D_AVG: + s->compute_flt = compute_avg_flt; + s->compute_dbl = compute_avg_dbl; + break; case D_PEAK: s->compute_flt = compute_peak_flt; s->compute_dbl = compute_peak_dbl; @@ -374,8 +391,13 @@ static av_cold void uninit(AVFilterContext *ctx) av_frame_free(&s->stop_window); av_frame_free(&s->start_queuef); av_frame_free(&s->stop_queuef); + av_freep(&s->start_cache); av_freep(&s->stop_cache); + av_freep(&s->start_front); + av_freep(&s->start_back); + av_freep(&s->stop_front); + av_freep(&s->stop_back); } static const AVFilterPad silenceremove_inputs[] = { diff --git a/libavfilter/silenceremove_template.c b/libavfilter/silenceremove_template.c index 1a12435ee61..ef63ea1e7e3 100644 --- a/libavfilter/silenceremove_template.c +++ b/libavfilter/silenceremove_template.c @@ -99,8 +99,8 @@ static void fn(queue_sample)(AVFilterContext *ctx, *window_pos = 0; } -static ftype fn(compute_peak)(ftype *cache, ftype sample, ftype wsample, - int window_size) +static ftype fn(compute_avg)(ftype *cache, ftype sample, ftype wsample, + int window_size, int *unused, int *unused2) { ftype r; @@ -111,8 +111,49 @@ static ftype fn(compute_peak)(ftype *cache, ftype sample, ftype wsample, return r / window_size; } +static ftype fn(compute_peak)(ftype *peak, ftype sample, ftype wsample, + int size, int *ffront, int *bback) +{ + ftype r, abs_sample = FABS(sample); + int front = *ffront; + int back = *bback; + + if (front != back && abs_sample > peak[front]) { + while (front != back) { + front--; + if (front < 0) + front = size - 1; + } + } + + while (front != back && abs_sample > peak[back]) { + back++; + if (back >= size) + back = 0; + } + + if (front != back && FABS(wsample) == peak[front]) { + front--; + if (front < 0) + front = size - 1; + } + + back--; + if (back < 0) + back = size - 1; + av_assert2(back != front); + peak[back] = abs_sample; + + r = peak[front]; + + *ffront = front; + *bback = back; + + return r; +} + static ftype fn(compute_rms)(ftype *cache, ftype sample, ftype wsample, - int window_size) + int window_size, int *unused, int *unused2) { ftype r; @@ -143,6 +184,9 @@ static void fn(filter_start)(AVFilterContext *ctx, const int start_duration = s->start_duration; ftype *start_cache = (ftype *)s->start_cache; const int start_silence = s->start_silence; + int window_size = start_window_nb_samples; + int *front = s->start_front; + int *back = s->start_back; fn(queue_sample)(ctx, src, start, &s->start_queue_pos, @@ -153,15 +197,20 @@ static void fn(filter_start)(AVFilterContext *ctx, start_nb_samples, start_window_nb_samples); + if (s->detection != D_PEAK) + window_size = s->start_window_size; + for (int ch = 0; ch < nb_channels; ch++) { ftype start_sample = start[start_pos + ch]; ftype start_ow = startw[start_wpos + ch]; ftype tstart; - tstart = fn(s->compute)(start_cache + ch, + tstart = fn(s->compute)(start_cache + ch * start_window_nb_samples, start_sample, start_ow, - s->start_window_size); + window_size, + front + ch, + back + ch); startw[start_wpos + ch] = start_sample; @@ -226,6 +275,9 @@ static void fn(filter_stop)(AVFilterContext *ctx, ftype *stop_cache = (ftype *)s->stop_cache; const int stop_silence = s->stop_silence; const int restart = s->restart; + int window_size = stop_window_nb_samples; + int *front = s->stop_front; + int *back = s->stop_back; fn(queue_sample)(ctx, src, stop, &s->stop_queue_pos, @@ -236,15 +288,20 @@ static void fn(filter_stop)(AVFilterContext *ctx, stop_nb_samples, stop_window_nb_samples); + if (s->detection != D_PEAK) + window_size = s->stop_window_size; + for (int ch = 0; ch < nb_channels; ch++) { ftype stop_sample = stop[stop_pos + ch]; ftype stop_ow = stopw[stop_wpos + ch]; ftype tstop; - tstop = fn(s->compute)(stop_cache + ch, + tstop = fn(s->compute)(stop_cache + ch * stop_window_nb_samples, stop_sample, stop_ow, - s->stop_window_size); + window_size, + front + ch, + back + ch); stopw[stop_wpos + ch] = stop_sample; diff --git a/tests/fate/filter-audio.mak b/tests/fate/filter-audio.mak index eff32b9f811..445c0f92177 100644 --- a/tests/fate/filter-audio.mak +++ b/tests/fate/filter-audio.mak @@ -184,7 +184,7 @@ fate-filter-pan-downmix2: SRC = $(TARGET_PATH)/tests/data/asynth-44100-11.wav fate-filter-pan-downmix2: CMD = framecrc -ss 3.14 -i $(SRC) -frames:a 20 -filter:a "pan=5C|c0=0.7*c0+0.7*c10|c1=c9|c2=c8|c3=c7|c4=c6" FATE_AFILTER-$(call ALLYES, LAVFI_INDEV, AEVALSRC_FILTER SILENCEREMOVE_FILTER) += fate-filter-silenceremove -fate-filter-silenceremove: CMD = framecrc -auto_conversion_filters -f lavfi -i "aevalsrc=between(t\,1\,2)+between(t\,4\,5)+between(t\,7\,9):d=10:n=8192,silenceremove=start_periods=0:start_duration=0:start_threshold=0:stop_periods=-1:stop_duration=0:stop_threshold=-90dB:window=0:detection=peak" +fate-filter-silenceremove: CMD = framecrc -auto_conversion_filters -f lavfi -i "aevalsrc=between(t\,1\,2)+between(t\,4\,5)+between(t\,7\,9):d=10:n=8192,silenceremove=start_periods=0:start_duration=0:start_threshold=0:stop_periods=-1:stop_duration=0:stop_threshold=-90dB:window=0:detection=avg" FATE_AFILTER_SAMPLES-$(call FILTERDEMDECENCMUX, STEREOTOOLS, WAV, PCM_S16LE, PCM_S16LE, WAV) += fate-filter-stereotools fate-filter-stereotools: SRC = $(TARGET_SAMPLES)/audio-reference/luckynight_2ch_44kHz_s16.wav From f59d9514dae7cbdd465fbd22a64e05d679ba6ce3 Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Fri, 26 May 2023 09:24:22 +0200 Subject: [PATCH 1182/2172] avfilter/silenceremove_template: skip silence start detection after start-only trimming is over --- libavfilter/silenceremove_template.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/libavfilter/silenceremove_template.c b/libavfilter/silenceremove_template.c index ef63ea1e7e3..f5f09572407 100644 --- a/libavfilter/silenceremove_template.c +++ b/libavfilter/silenceremove_template.c @@ -197,6 +197,9 @@ static void fn(filter_start)(AVFilterContext *ctx, start_nb_samples, start_window_nb_samples); + if (s->start_found_periods < 0) + goto skip; + if (s->detection != D_PEAK) window_size = s->start_window_size; @@ -244,6 +247,7 @@ static void fn(filter_start)(AVFilterContext *ctx, s->start_sample_count = 0; } +skip: if (s->start_found_periods < 0) { const int dst_pos = out_nb_samples * nb_channels; for (int ch = 0; ch < nb_channels; ch++) From 29710dd7f2d771ca83ae3b7701b4354b5233e4f3 Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Fri, 26 May 2023 09:54:40 +0200 Subject: [PATCH 1183/2172] avfilter/af_silenceremove: speed-up start-only trimming once trim is over --- libavfilter/af_silenceremove.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/libavfilter/af_silenceremove.c b/libavfilter/af_silenceremove.c index 28c972f86f7..a3ad0eea13c 100644 --- a/libavfilter/af_silenceremove.c +++ b/libavfilter/af_silenceremove.c @@ -372,6 +372,12 @@ static int activate(AVFilterContext *ctx) if (ret < 0) return ret; if (ret > 0) { + if (s->start_periods == 1 && s->stop_periods == 0 && + s->start_found_periods < 0) { + in->pts = s->next_pts; + s->next_pts += in->nb_samples; + return ff_filter_frame(outlink, in); + } if (s->start_periods == 0 && s->stop_periods == 0) return ff_filter_frame(outlink, in); return filter_frame(outlink, in); From 68d0b881dea35960275fb168030ae1f19dcf1a0f Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Fri, 26 May 2023 22:29:31 +0200 Subject: [PATCH 1184/2172] avfilter/silenceremove_template: fix peak detector The implementation was not working correctly. --- libavfilter/silenceremove_template.c | 40 +++++++++++++++++++--------- 1 file changed, 28 insertions(+), 12 deletions(-) diff --git a/libavfilter/silenceremove_template.c b/libavfilter/silenceremove_template.c index f5f09572407..be51beb300e 100644 --- a/libavfilter/silenceremove_template.c +++ b/libavfilter/silenceremove_template.c @@ -117,33 +117,49 @@ static ftype fn(compute_peak)(ftype *peak, ftype sample, ftype wsample, ftype r, abs_sample = FABS(sample); int front = *ffront; int back = *bback; + int empty = front == back && peak[front] == ZERO; - if (front != back && abs_sample > peak[front]) { - while (front != back) { + if (!empty && FABS(wsample) == peak[front]) { + peak[front] = ZERO; + if (back != front) { front--; if (front < 0) front = size - 1; } + empty = front == back; } - while (front != back && abs_sample > peak[back]) { + if (!empty && abs_sample >= peak[front]) { + while (1) { + peak[front] = ZERO; + if (back == front) { + empty = 1; + break; + } + front--; + if (front < 0) + front = size - 1; + } + } + + while (!empty && abs_sample >= peak[back]) { + peak[back] = ZERO; + if (back == front) { + empty = 1; + break; + } back++; if (back >= size) back = 0; } - if (front != back && FABS(wsample) == peak[front]) { - front--; - if (front < 0) - front = size - 1; + if (!empty) { + back--; + if (back < 0) + back = size - 1; } - back--; - if (back < 0) - back = size - 1; - av_assert2(back != front); peak[back] = abs_sample; - r = peak[front]; *ffront = front; From 5a13b133f8effe2a2bac07b17f591d8ca7f6c1de Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Fri, 26 May 2023 14:10:38 +0200 Subject: [PATCH 1185/2172] avfilter/af_silenceremove: add median silence detector --- doc/filters.texi | 2 +- libavfilter/af_silenceremove.c | 6 +++ libavfilter/silenceremove_template.c | 69 +++++++++++++++++++++++++++- 3 files changed, 74 insertions(+), 3 deletions(-) diff --git a/doc/filters.texi b/doc/filters.texi index 6f15b54d107..ea42c127daa 100644 --- a/doc/filters.texi +++ b/doc/filters.texi @@ -6461,7 +6461,7 @@ With @var{all}, only if all channels are detected as non-silence will cause stopped trimming of silence. @item detection -Set how is silence detected. Can be @code{avg}, @code{rms} or @code{peak}. +Set how is silence detected. Can be @code{avg}, @code{rms}, @code{median} or @code{peak}. Default value is @code{rms}. @item window diff --git a/libavfilter/af_silenceremove.c b/libavfilter/af_silenceremove.c index a3ad0eea13c..fa182fc9f36 100644 --- a/libavfilter/af_silenceremove.c +++ b/libavfilter/af_silenceremove.c @@ -36,6 +36,7 @@ enum SilenceDetect { D_AVG, D_RMS, D_PEAK, + D_MEDIAN, D_NB }; @@ -132,6 +133,7 @@ static const AVOption silenceremove_options[] = { { "avg", "use mean absolute values of samples", 0, AV_OPT_TYPE_CONST, {.i64=D_AVG}, 0, 0, AF, "detection" }, { "rms", "use root mean squared values of samples", 0, AV_OPT_TYPE_CONST, {.i64=D_RMS}, 0, 0, AF, "detection" }, { "peak", "use max absolute values of samples", 0, AV_OPT_TYPE_CONST, {.i64=D_PEAK},0, 0, AF, "detection" }, + { "median", "use median of absolute values of samples", 0, AV_OPT_TYPE_CONST, {.i64=D_MEDIAN},0, 0, AF, "detection" }, { "window", "set duration of window for silence detection", OFFSET(window_duration_opt), AV_OPT_TYPE_DURATION, {.i64=20000}, 0, 100000000, AF }, { NULL } }; @@ -234,6 +236,10 @@ static int config_output(AVFilterLink *outlink) s->compute_flt = compute_avg_flt; s->compute_dbl = compute_avg_dbl; break; + case D_MEDIAN: + s->compute_flt = compute_median_flt; + s->compute_dbl = compute_median_dbl; + break; case D_PEAK: s->compute_flt = compute_peak_flt; s->compute_dbl = compute_peak_dbl; diff --git a/libavfilter/silenceremove_template.c b/libavfilter/silenceremove_template.c index be51beb300e..143d399f9ea 100644 --- a/libavfilter/silenceremove_template.c +++ b/libavfilter/silenceremove_template.c @@ -22,6 +22,7 @@ #undef SAMPLE_FORMAT #undef SQRT #undef ZERO +#undef ONE #if DEPTH == 32 #define SAMPLE_FORMAT flt #define SQRT sqrtf @@ -29,6 +30,7 @@ #define FABS fabsf #define ftype float #define ZERO 0.f +#define ONE 1.f #else #define SAMPLE_FORMAT dbl #define SQRT sqrt @@ -36,6 +38,7 @@ #define FABS fabs #define ftype double #define ZERO 0.0 +#define ONE 1.0 #endif #define fn3(a,b) a##_##b @@ -111,6 +114,68 @@ static ftype fn(compute_avg)(ftype *cache, ftype sample, ftype wsample, return r / window_size; } +static ftype fn(compute_median)(ftype *peak, ftype sample, ftype wsample, + int size, int *ffront, int *bback) +{ + ftype r, abs_sample = FABS(sample); + int front = *ffront; + int back = *bback; + int empty = front == back && peak[front] == -ONE; + int idx; + + if (!empty && FABS(wsample) == peak[front]) { + peak[front] = -ONE; + if (back != front) { + front--; + if (front < 0) + front = size - 1; + } + empty = front == back; + } + + if (!empty && abs_sample > peak[front]) { + while (1) { + peak[front] = -ONE; + if (back == front) { + empty = 1; + break; + } + front--; + if (front < 0) + front = size - 1; + } + } + + while (!empty && abs_sample > peak[back]) { + peak[back] = -ONE; + if (back == front) { + empty = 1; + break; + } + back++; + if (back >= size) + back = 0; + } + + if (!empty) { + back--; + if (back < 0) + back = size - 1; + } + + peak[back] = abs_sample; + idx = (back <= front) ? back + (front - back + 1) / 2 : back + (size + front - back + 1) / 2; + if (idx >= size) + idx -= size; + av_assert2(idx >= 0 && idx < size); + r = peak[idx]; + + *ffront = front; + *bback = back; + + return r; +} + static ftype fn(compute_peak)(ftype *peak, ftype sample, ftype wsample, int size, int *ffront, int *bback) { @@ -216,7 +281,7 @@ static void fn(filter_start)(AVFilterContext *ctx, if (s->start_found_periods < 0) goto skip; - if (s->detection != D_PEAK) + if (s->detection != D_PEAK && s->detection != D_MEDIAN) window_size = s->start_window_size; for (int ch = 0; ch < nb_channels; ch++) { @@ -308,7 +373,7 @@ static void fn(filter_stop)(AVFilterContext *ctx, stop_nb_samples, stop_window_nb_samples); - if (s->detection != D_PEAK) + if (s->detection != D_PEAK && s->detection != D_MEDIAN) window_size = s->stop_window_size; for (int ch = 0; ch < nb_channels; ch++) { From e86e2d5921a30b582619466f14f5274b1f986729 Mon Sep 17 00:00:00 2001 From: James Almer Date: Mon, 22 May 2023 19:13:25 -0300 Subject: [PATCH 1186/2172] fftools/ffmpeg_dec: abort if avcodec_send_packet() returns EAGAIN As the comment in the code mentions, EAGAIN is not an expected value here because we call avcodec_receive_frame() until all frames have been returned. avcodec_send_packet() returning EAGAIN means a packet is still buffered, which hints that the underlying decoder is buggy and not fetching packets as it should. An example of this behavior was in the libdav1d wrapper before f209614290, where feeding it split frames (or individual OBUs) would result in the CLI eventually printing the confusing "Error submitting packet to decoder: Resource temporarily unavailable" error message, and just keep going until EOF without returning new frames. Signed-off-by: James Almer --- fftools/ffmpeg_dec.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/fftools/ffmpeg_dec.c b/fftools/ffmpeg_dec.c index e06747d9c45..04b7db1e17d 100644 --- a/fftools/ffmpeg_dec.c +++ b/fftools/ffmpeg_dec.c @@ -390,6 +390,11 @@ int dec_packet(InputStream *ist, const AVPacket *pkt, int no_eof) if (ret < 0 && !(ret == AVERROR_EOF && !pkt)) { // In particular, we don't expect AVERROR(EAGAIN), because we read all // decoded frames with avcodec_receive_frame() until done. + if (ret == AVERROR(EAGAIN)) { + av_log(ist, AV_LOG_FATAL, "A decoder returned an unexpected error code. " + "This is a bug, please report it.\n"); + exit_program(1); + } av_log(ist, AV_LOG_ERROR, "Error submitting %s to decoder: %s\n", pkt ? "packet" : "EOF", av_err2str(ret)); if (exit_on_error) From 7927a96e2b8b9063592d7c609af5b7d544a9c475 Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Sat, 27 May 2023 10:12:37 +0200 Subject: [PATCH 1187/2172] avfilter/af_silenceremove: add commands support --- doc/filters.texi | 4 ++++ libavfilter/af_silenceremove.c | 14 ++++++++------ 2 files changed, 12 insertions(+), 6 deletions(-) diff --git a/doc/filters.texi b/doc/filters.texi index ea42c127daa..975a5063524 100644 --- a/doc/filters.texi +++ b/doc/filters.texi @@ -6497,6 +6497,10 @@ silenceremove=window=0:detection=peak:stop_mode=all:start_mode=all:stop_periods= @end example @end itemize +@subsection Commands + +This filter supports some above options as @ref{commands}. + @section sofalizer SOFAlizer uses head-related transfer functions (HRTFs) to create virtual diff --git a/libavfilter/af_silenceremove.c b/libavfilter/af_silenceremove.c index fa182fc9f36..755ed10bd0b 100644 --- a/libavfilter/af_silenceremove.c +++ b/libavfilter/af_silenceremove.c @@ -115,20 +115,21 @@ typedef struct SilenceRemoveContext { #define OFFSET(x) offsetof(SilenceRemoveContext, x) #define AF AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_AUDIO_PARAM +#define AFR AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_AUDIO_PARAM|AV_OPT_FLAG_RUNTIME_PARAM static const AVOption silenceremove_options[] = { { "start_periods", "set periods of silence parts to skip from start", OFFSET(start_periods), AV_OPT_TYPE_INT, {.i64=0}, 0, 9000, AF }, { "start_duration", "set start duration of non-silence part", OFFSET(start_duration_opt), AV_OPT_TYPE_DURATION, {.i64=0}, 0, INT32_MAX, AF }, - { "start_threshold", "set threshold for start silence detection", OFFSET(start_threshold), AV_OPT_TYPE_DOUBLE, {.dbl=0}, 0, DBL_MAX, AF }, + { "start_threshold", "set threshold for start silence detection", OFFSET(start_threshold), AV_OPT_TYPE_DOUBLE, {.dbl=0}, 0, DBL_MAX, AFR }, { "start_silence", "set start duration of silence part to keep", OFFSET(start_silence_opt), AV_OPT_TYPE_DURATION, {.i64=0}, 0, INT32_MAX, AF }, - { "start_mode", "set which channel will trigger trimming from start", OFFSET(start_mode), AV_OPT_TYPE_INT, {.i64=T_ANY}, T_ANY, T_ALL, AF, "mode" }, - { "any", 0, 0, AV_OPT_TYPE_CONST, {.i64=T_ANY}, 0, 0, AF, "mode" }, - { "all", 0, 0, AV_OPT_TYPE_CONST, {.i64=T_ALL}, 0, 0, AF, "mode" }, + { "start_mode", "set which channel will trigger trimming from start", OFFSET(start_mode), AV_OPT_TYPE_INT, {.i64=T_ANY}, T_ANY, T_ALL, AFR, "mode" }, + { "any", 0, 0, AV_OPT_TYPE_CONST, {.i64=T_ANY}, 0, 0, AFR, "mode" }, + { "all", 0, 0, AV_OPT_TYPE_CONST, {.i64=T_ALL}, 0, 0, AFR, "mode" }, { "stop_periods", "set periods of silence parts to skip from end", OFFSET(stop_periods), AV_OPT_TYPE_INT, {.i64=0}, -9000, 9000, AF }, { "stop_duration", "set stop duration of silence part", OFFSET(stop_duration_opt), AV_OPT_TYPE_DURATION, {.i64=0}, 0, INT32_MAX, AF }, - { "stop_threshold", "set threshold for stop silence detection", OFFSET(stop_threshold), AV_OPT_TYPE_DOUBLE, {.dbl=0}, 0, DBL_MAX, AF }, + { "stop_threshold", "set threshold for stop silence detection", OFFSET(stop_threshold), AV_OPT_TYPE_DOUBLE, {.dbl=0}, 0, DBL_MAX, AFR }, { "stop_silence", "set stop duration of silence part to keep", OFFSET(stop_silence_opt), AV_OPT_TYPE_DURATION, {.i64=0}, 0, INT32_MAX, AF }, - { "stop_mode", "set which channel will trigger trimming from end", OFFSET(stop_mode), AV_OPT_TYPE_INT, {.i64=T_ANY}, T_ANY, T_ALL, AF, "mode" }, + { "stop_mode", "set which channel will trigger trimming from end", OFFSET(stop_mode), AV_OPT_TYPE_INT, {.i64=T_ANY}, T_ANY, T_ALL, AFR, "mode" }, { "detection", "set how silence is detected", OFFSET(detection), AV_OPT_TYPE_INT, {.i64=D_RMS}, 0, D_NB-1, AF, "detection" }, { "avg", "use mean absolute values of samples", 0, AV_OPT_TYPE_CONST, {.i64=D_AVG}, 0, 0, AF, "detection" }, { "rms", "use root mean squared values of samples", 0, AV_OPT_TYPE_CONST, {.i64=D_RMS}, 0, 0, AF, "detection" }, @@ -440,4 +441,5 @@ const AVFilter ff_af_silenceremove = { FILTER_OUTPUTS(silenceremove_outputs), FILTER_SAMPLEFMTS(AV_SAMPLE_FMT_FLT, AV_SAMPLE_FMT_DBL), + .process_command = ff_filter_process_command, }; From 965f99f904a433c341c04ac992d5ab8f08f0aae2 Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Sat, 27 May 2023 11:03:18 +0200 Subject: [PATCH 1188/2172] avfilter/af_silenceremove: add timeline support --- libavfilter/af_silenceremove.c | 1 + libavfilter/silenceremove_template.c | 13 +++++++------ 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/libavfilter/af_silenceremove.c b/libavfilter/af_silenceremove.c index 755ed10bd0b..865df4d13ac 100644 --- a/libavfilter/af_silenceremove.c +++ b/libavfilter/af_silenceremove.c @@ -442,4 +442,5 @@ const AVFilter ff_af_silenceremove = { FILTER_SAMPLEFMTS(AV_SAMPLE_FMT_FLT, AV_SAMPLE_FMT_DBL), .process_command = ff_filter_process_command, + .flags = AVFILTER_FLAG_SUPPORT_TIMELINE_INTERNAL, }; diff --git a/libavfilter/silenceremove_template.c b/libavfilter/silenceremove_template.c index 143d399f9ea..e07a615ae76 100644 --- a/libavfilter/silenceremove_template.c +++ b/libavfilter/silenceremove_template.c @@ -318,9 +318,10 @@ static void fn(filter_start)(AVFilterContext *ctx, if (s->start_sample_count > start_duration) { s->start_found_periods++; if (s->start_found_periods >= start_periods) { - fn(flush)(dst, start, s->start_queue_pos, nb_channels, - s->start_silence_count, start_nb_samples, - &out_nb_samples); + if (!ctx->is_disabled) + fn(flush)(dst, start, s->start_queue_pos, nb_channels, + s->start_silence_count, start_nb_samples, + &out_nb_samples); s->start_silence_count = 0; s->start_found_periods = -1; } @@ -329,7 +330,7 @@ static void fn(filter_start)(AVFilterContext *ctx, } skip: - if (s->start_found_periods < 0) { + if (s->start_found_periods < 0 || ctx->is_disabled) { const int dst_pos = out_nb_samples * nb_channels; for (int ch = 0; ch < nb_channels; ch++) dst[dst_pos + ch] = start[start_pos + ch]; @@ -401,7 +402,7 @@ static void fn(filter_stop)(AVFilterContext *ctx, if (restart && !stop_thres) s->stop_found_periods = 0; - if (s->stop_found_periods >= 0) { + if (s->stop_found_periods >= 0 || ctx->is_disabled) { if (s->found_nonsilence) { s->stop_sample_count += stop_thres; s->stop_sample_count *= stop_thres; @@ -424,7 +425,7 @@ static void fn(filter_stop)(AVFilterContext *ctx, s->stop_sample_count = 0; } - if (s->stop_found_periods >= 0) { + if (s->stop_found_periods >= 0 || ctx->is_disabled) { const int dst_pos = out_nb_samples * nb_channels; for (int ch = 0; ch < nb_channels; ch++) dst[dst_pos + ch] = stop[stop_pos + ch]; From 8d662adcc9a28da7a9422bff8be68881692ca6bd Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Sat, 27 May 2023 11:13:48 +0200 Subject: [PATCH 1189/2172] avfilter/af_silenceremove: speed-up filtering once start-trim is over No point to call filter_start on samples that will pass them unchanged once initial trimming stopped. --- libavfilter/af_silenceremove.c | 36 +++++++++++++++++++++------------- 1 file changed, 22 insertions(+), 14 deletions(-) diff --git a/libavfilter/af_silenceremove.c b/libavfilter/af_silenceremove.c index 865df4d13ac..8398eeadb23 100644 --- a/libavfilter/af_silenceremove.c +++ b/libavfilter/af_silenceremove.c @@ -294,15 +294,19 @@ static int filter_frame(AVFilterLink *outlink, AVFrame *in) srcf = (const float *)in->data[0]; dstf = (float *)out->data[0]; if (s->start_periods > 0 && s->stop_periods > 0) { - for (int n = 0; n < in_nb_samples; n++) { - filter_start_flt(ctx, srcf + n * nb_channels, - dstf, &out_nb_samples, - nb_channels); + const float *src = srcf; + if (s->start_found_periods >= 0) { + for (int n = 0; n < in_nb_samples; n++) { + filter_start_flt(ctx, src + n * nb_channels, + dstf, &out_nb_samples, + nb_channels); + } + in_nb_samples = out_nb_samples; + out_nb_samples = 0; + src = dstf; } - in_nb_samples = out_nb_samples; - out_nb_samples = 0; for (int n = 0; n < in_nb_samples; n++) { - filter_stop_flt(ctx, dstf + n * nb_channels, + filter_stop_flt(ctx, src + n * nb_channels, dstf, &out_nb_samples, nb_channels); } @@ -324,15 +328,19 @@ static int filter_frame(AVFilterLink *outlink, AVFrame *in) srcd = (const double *)in->data[0]; dstd = (double *)out->data[0]; if (s->start_periods > 0 && s->stop_periods > 0) { - for (int n = 0; n < in_nb_samples; n++) { - filter_start_dbl(ctx, srcd + n * nb_channels, - dstd, &out_nb_samples, - nb_channels); + const double *src = srcd; + if (s->start_found_periods >= 0) { + for (int n = 0; n < in_nb_samples; n++) { + filter_start_dbl(ctx, src + n * nb_channels, + dstd, &out_nb_samples, + nb_channels); + } + in_nb_samples = out_nb_samples; + out_nb_samples = 0; + src = dstd; } - in_nb_samples = out_nb_samples; - out_nb_samples = 0; for (int n = 0; n < in_nb_samples; n++) { - filter_stop_dbl(ctx, dstd + n * nb_channels, + filter_stop_dbl(ctx, src + n * nb_channels, dstd, &out_nb_samples, nb_channels); } From e8e486332571347dd55822c842ba67276ac308e2 Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Sat, 27 May 2023 13:59:24 +0200 Subject: [PATCH 1190/2172] avfilter/af_silenceremove: fix the any/all confusion and change default 'any' stop mode is now correctly implemented for end trimming and is of limited usage. Extend examples and other documentation of this filter. --- doc/filters.texi | 62 +++++++++++++++++++++------- libavfilter/af_silenceremove.c | 2 +- libavfilter/silenceremove_template.c | 4 +- 3 files changed, 50 insertions(+), 18 deletions(-) diff --git a/doc/filters.texi b/doc/filters.texi index 975a5063524..4d9a3cf0b43 100644 --- a/doc/filters.texi +++ b/doc/filters.texi @@ -6419,15 +6419,16 @@ trimming. Default is 0, which is equal to trimming all samples detected as silence. @item start_mode -Specify mode of detection of silence end in start of multi-channel audio. +Specify mode of detection of silence end at start of multi-channel audio. Can be @var{any} or @var{all}. Default is @var{any}. -With @var{any}, any sample that is detected as non-silence will cause -stopped trimming of silence. -With @var{all}, only if all channels are detected as non-silence will cause -stopped trimming of silence. +With @var{any}, any sample from any channel that is detected as non-silence +will trigger end of silence trimming at start of audio stream. +With @var{all}, only if every sample from every channel is detected as non-silence +will trigger end of silence trimming at start of audio stream, limited usage. @item stop_periods -Set the count for trimming silence from the end of audio. +Set the count for trimming silence from the end of audio. When specifying a +positive value, it trims audio after it finds specified silence period. To remove silence from the middle of a file, specify a @var{stop_periods} that is negative. This value is then treated as a positive value and is used to indicate the effect should restart processing as specified by @@ -6453,20 +6454,34 @@ trimming. Default is 0, which is equal to trimming all samples detected as silence. @item stop_mode -Specify mode of detection of silence start in end of multi-channel audio. -Can be @var{any} or @var{all}. Default is @var{any}. -With @var{any}, any sample that is detected as non-silence will cause -stopped trimming of silence. -With @var{all}, only if all channels are detected as non-silence will cause -stopped trimming of silence. +Specify mode of detection of silence start after start of multi-channel audio. +Can be @var{any} or @var{all}. Default is @var{all}. +With @var{any}, any sample from any channel that is detected as silence +will trigger start of silence trimming after start of audio stream, limited usage. +With @var{all}, only if every sample from every channel is detected as silence +will trigger start of silence trimming after start of audio stream. @item detection -Set how is silence detected. Can be @code{avg}, @code{rms}, @code{median} or @code{peak}. +Set how is silence detected. +@table @option +@item avg +Mean of absolute values of samples in moving window. +@item rms +Root squared mean of absolute values of samples in moving window. +@item peak +Maximum of absolute values of samples in moving window. +@item median +Median of absolute values of samples in moving window. +@end table Default value is @code{rms}. @item window Set duration in number of seconds used to calculate size of window in number -of samples for detecting silence. +of samples for detecting silence. Using @code{0} will effectively disable +any windowing and use only single sample per channel for silence detection. +In that case it may be needed to also set @option{start_silence} and/or +@option{stop_silence} to nonzero values with also @option{start_duration} and/or +@option{stop_duration} to nonzero values. Default value is @code{0.02}. Allowed range is from @code{0} to @code{10}. @end table @@ -6495,6 +6510,25 @@ silence is detected in all channels at same positions in stream: @example silenceremove=window=0:detection=peak:stop_mode=all:start_mode=all:stop_periods=-1:stop_threshold=0 @end example + +@item +Trim every 2nd encountered silence period from beginning to end where there is +more than 1 second of silence per silence period in audio: +@example +silenceremove=stop_periods=-2:stop_duration=1:stop_threshold=-90dB +@end example + +@item +Similar as above, but keep maximum of 0.5 seconds of silence from each trimmed period: +@example +silenceremove=stop_periods=-2:stop_duration=1:stop_threshold=-90dB:stop_silence=0.5 +@end example + +@item +Similar as above, but keep maximum of 1.5 seconds of silence from start of audio: +@example +silenceremove=stop_periods=-2:stop_duration=1:stop_threshold=-90dB:stop_silence=0.5:start_periods=1:start_duration=1:start_silence=1.5:stop_threshold=-90dB +@end example @end itemize @subsection Commands diff --git a/libavfilter/af_silenceremove.c b/libavfilter/af_silenceremove.c index 8398eeadb23..752a362203d 100644 --- a/libavfilter/af_silenceremove.c +++ b/libavfilter/af_silenceremove.c @@ -129,7 +129,7 @@ static const AVOption silenceremove_options[] = { { "stop_duration", "set stop duration of silence part", OFFSET(stop_duration_opt), AV_OPT_TYPE_DURATION, {.i64=0}, 0, INT32_MAX, AF }, { "stop_threshold", "set threshold for stop silence detection", OFFSET(stop_threshold), AV_OPT_TYPE_DOUBLE, {.dbl=0}, 0, DBL_MAX, AFR }, { "stop_silence", "set stop duration of silence part to keep", OFFSET(stop_silence_opt), AV_OPT_TYPE_DURATION, {.i64=0}, 0, INT32_MAX, AF }, - { "stop_mode", "set which channel will trigger trimming from end", OFFSET(stop_mode), AV_OPT_TYPE_INT, {.i64=T_ANY}, T_ANY, T_ALL, AFR, "mode" }, + { "stop_mode", "set which channel will trigger trimming from end", OFFSET(stop_mode), AV_OPT_TYPE_INT, {.i64=T_ALL}, T_ANY, T_ALL, AFR, "mode" }, { "detection", "set how silence is detected", OFFSET(detection), AV_OPT_TYPE_INT, {.i64=D_RMS}, 0, D_NB-1, AF, "detection" }, { "avg", "use mean absolute values of samples", 0, AV_OPT_TYPE_CONST, {.i64=D_AVG}, 0, 0, AF, "detection" }, { "rms", "use root mean squared values of samples", 0, AV_OPT_TYPE_CONST, {.i64=D_RMS}, 0, 0, AF, "detection" }, diff --git a/libavfilter/silenceremove_template.c b/libavfilter/silenceremove_template.c index e07a615ae76..901361d7ebd 100644 --- a/libavfilter/silenceremove_template.c +++ b/libavfilter/silenceremove_template.c @@ -403,10 +403,8 @@ static void fn(filter_stop)(AVFilterContext *ctx, s->stop_found_periods = 0; if (s->stop_found_periods >= 0 || ctx->is_disabled) { - if (s->found_nonsilence) { + if (s->found_nonsilence) s->stop_sample_count += stop_thres; - s->stop_sample_count *= stop_thres; - } } else if (s->stop_silence_count > 0) { const int dst_pos = out_nb_samples * nb_channels; for (int ch = 0; ch < nb_channels; ch++) From 760a9bd306a42c0e0e0ed0828d6d5e6078e7ced0 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Wed, 17 May 2023 17:04:28 +0200 Subject: [PATCH 1191/2172] fftools/ffmpeg_hw: move hw_device_setup_for_decode() to ffmpeg_dec This function is entangled with decoder setup, so it is more decoding code rather than ffmpeg_hw code. This will allow making more decoder state private in the future. --- fftools/ffmpeg.h | 5 +- fftools/ffmpeg_dec.c | 145 ++++++++++++++++++++++++++++++++++++++++ fftools/ffmpeg_hw.c | 153 ++----------------------------------------- 3 files changed, 153 insertions(+), 150 deletions(-) diff --git a/fftools/ffmpeg.h b/fftools/ffmpeg.h index 45be3b18231..895edbd6d63 100644 --- a/fftools/ffmpeg.h +++ b/fftools/ffmpeg.h @@ -795,10 +795,13 @@ void enc_stats_write(OutputStream *ost, EncStats *es, uint64_t frame_num); HWDevice *hw_device_get_by_name(const char *name); +HWDevice *hw_device_get_by_type(enum AVHWDeviceType type); int hw_device_init_from_string(const char *arg, HWDevice **dev); +int hw_device_init_from_type(enum AVHWDeviceType type, + const char *device, + HWDevice **dev_out); void hw_device_free_all(void); -int hw_device_setup_for_decode(InputStream *ist); int hw_device_setup_for_encode(OutputStream *ost); /** * Get a hardware device to be used with this filtergraph. diff --git a/fftools/ffmpeg_dec.c b/fftools/ffmpeg_dec.c index 04b7db1e17d..8946bf538d6 100644 --- a/fftools/ffmpeg_dec.c +++ b/fftools/ffmpeg_dec.c @@ -533,6 +533,151 @@ static enum AVPixelFormat get_format(AVCodecContext *s, const enum AVPixelFormat return *p; } +static HWDevice *hw_device_match_by_codec(const AVCodec *codec) +{ + const AVCodecHWConfig *config; + HWDevice *dev; + int i; + for (i = 0;; i++) { + config = avcodec_get_hw_config(codec, i); + if (!config) + return NULL; + if (!(config->methods & AV_CODEC_HW_CONFIG_METHOD_HW_DEVICE_CTX)) + continue; + dev = hw_device_get_by_type(config->device_type); + if (dev) + return dev; + } +} + +static int hw_device_setup_for_decode(InputStream *ist) +{ + const AVCodecHWConfig *config; + enum AVHWDeviceType type; + HWDevice *dev = NULL; + int err, auto_device = 0; + + if (ist->hwaccel_device) { + dev = hw_device_get_by_name(ist->hwaccel_device); + if (!dev) { + if (ist->hwaccel_id == HWACCEL_AUTO) { + auto_device = 1; + } else if (ist->hwaccel_id == HWACCEL_GENERIC) { + type = ist->hwaccel_device_type; + err = hw_device_init_from_type(type, ist->hwaccel_device, + &dev); + } else { + // This will be dealt with by API-specific initialisation + // (using hwaccel_device), so nothing further needed here. + return 0; + } + } else { + if (ist->hwaccel_id == HWACCEL_AUTO) { + ist->hwaccel_device_type = dev->type; + } else if (ist->hwaccel_device_type != dev->type) { + av_log(NULL, AV_LOG_ERROR, "Invalid hwaccel device " + "specified for decoder: device %s of type %s is not " + "usable with hwaccel %s.\n", dev->name, + av_hwdevice_get_type_name(dev->type), + av_hwdevice_get_type_name(ist->hwaccel_device_type)); + return AVERROR(EINVAL); + } + } + } else { + if (ist->hwaccel_id == HWACCEL_AUTO) { + auto_device = 1; + } else if (ist->hwaccel_id == HWACCEL_GENERIC) { + type = ist->hwaccel_device_type; + dev = hw_device_get_by_type(type); + + // When "-qsv_device device" is used, an internal QSV device named + // as "__qsv_device" is created. Another QSV device is created too + // if "-init_hw_device qsv=name:device" is used. There are 2 QSV devices + // if both "-qsv_device device" and "-init_hw_device qsv=name:device" + // are used, hw_device_get_by_type(AV_HWDEVICE_TYPE_QSV) returns NULL. + // To keep back-compatibility with the removed ad-hoc libmfx setup code, + // call hw_device_get_by_name("__qsv_device") to select the internal QSV + // device. + if (!dev && type == AV_HWDEVICE_TYPE_QSV) + dev = hw_device_get_by_name("__qsv_device"); + + if (!dev) + err = hw_device_init_from_type(type, NULL, &dev); + } else { + dev = hw_device_match_by_codec(ist->dec); + if (!dev) { + // No device for this codec, but not using generic hwaccel + // and therefore may well not need one - ignore. + return 0; + } + } + } + + if (auto_device) { + int i; + if (!avcodec_get_hw_config(ist->dec, 0)) { + // Decoder does not support any hardware devices. + return 0; + } + for (i = 0; !dev; i++) { + config = avcodec_get_hw_config(ist->dec, i); + if (!config) + break; + type = config->device_type; + dev = hw_device_get_by_type(type); + if (dev) { + av_log(NULL, AV_LOG_INFO, "Using auto " + "hwaccel type %s with existing device %s.\n", + av_hwdevice_get_type_name(type), dev->name); + } + } + for (i = 0; !dev; i++) { + config = avcodec_get_hw_config(ist->dec, i); + if (!config) + break; + type = config->device_type; + // Try to make a new device of this type. + err = hw_device_init_from_type(type, ist->hwaccel_device, + &dev); + if (err < 0) { + // Can't make a device of this type. + continue; + } + if (ist->hwaccel_device) { + av_log(NULL, AV_LOG_INFO, "Using auto " + "hwaccel type %s with new device created " + "from %s.\n", av_hwdevice_get_type_name(type), + ist->hwaccel_device); + } else { + av_log(NULL, AV_LOG_INFO, "Using auto " + "hwaccel type %s with new default device.\n", + av_hwdevice_get_type_name(type)); + } + } + if (dev) { + ist->hwaccel_device_type = type; + } else { + av_log(NULL, AV_LOG_INFO, "Auto hwaccel " + "disabled: no device found.\n"); + ist->hwaccel_id = HWACCEL_NONE; + return 0; + } + } + + if (!dev) { + av_log(NULL, AV_LOG_ERROR, "No device available " + "for decoder: device type %s needed for codec %s.\n", + av_hwdevice_get_type_name(type), ist->dec->name); + return err; + } + + ist->dec_ctx->hw_device_ctx = av_buffer_ref(dev->device_ref); + if (!ist->dec_ctx->hw_device_ctx) + return AVERROR(ENOMEM); + + return 0; +} + int dec_open(InputStream *ist) { const AVCodec *codec = ist->dec; diff --git a/fftools/ffmpeg_hw.c b/fftools/ffmpeg_hw.c index e67145211c8..d28257a1d64 100644 --- a/fftools/ffmpeg_hw.c +++ b/fftools/ffmpeg_hw.c @@ -27,7 +27,7 @@ static int nb_hw_devices; static HWDevice **hw_devices; -static HWDevice *hw_device_get_by_type(enum AVHWDeviceType type) +HWDevice *hw_device_get_by_type(enum AVHWDeviceType type) { HWDevice *found = NULL; int i; @@ -242,9 +242,9 @@ int hw_device_init_from_string(const char *arg, HWDevice **dev_out) goto done; } -static int hw_device_init_from_type(enum AVHWDeviceType type, - const char *device, - HWDevice **dev_out) +int hw_device_init_from_type(enum AVHWDeviceType type, + const char *device, + HWDevice **dev_out) { AVBufferRef *device_ref = NULL; HWDevice *dev; @@ -297,151 +297,6 @@ void hw_device_free_all(void) nb_hw_devices = 0; } -static HWDevice *hw_device_match_by_codec(const AVCodec *codec) -{ - const AVCodecHWConfig *config; - HWDevice *dev; - int i; - for (i = 0;; i++) { - config = avcodec_get_hw_config(codec, i); - if (!config) - return NULL; - if (!(config->methods & AV_CODEC_HW_CONFIG_METHOD_HW_DEVICE_CTX)) - continue; - dev = hw_device_get_by_type(config->device_type); - if (dev) - return dev; - } -} - -int hw_device_setup_for_decode(InputStream *ist) -{ - const AVCodecHWConfig *config; - enum AVHWDeviceType type; - HWDevice *dev = NULL; - int err, auto_device = 0; - - if (ist->hwaccel_device) { - dev = hw_device_get_by_name(ist->hwaccel_device); - if (!dev) { - if (ist->hwaccel_id == HWACCEL_AUTO) { - auto_device = 1; - } else if (ist->hwaccel_id == HWACCEL_GENERIC) { - type = ist->hwaccel_device_type; - err = hw_device_init_from_type(type, ist->hwaccel_device, - &dev); - } else { - // This will be dealt with by API-specific initialisation - // (using hwaccel_device), so nothing further needed here. - return 0; - } - } else { - if (ist->hwaccel_id == HWACCEL_AUTO) { - ist->hwaccel_device_type = dev->type; - } else if (ist->hwaccel_device_type != dev->type) { - av_log(NULL, AV_LOG_ERROR, "Invalid hwaccel device " - "specified for decoder: device %s of type %s is not " - "usable with hwaccel %s.\n", dev->name, - av_hwdevice_get_type_name(dev->type), - av_hwdevice_get_type_name(ist->hwaccel_device_type)); - return AVERROR(EINVAL); - } - } - } else { - if (ist->hwaccel_id == HWACCEL_AUTO) { - auto_device = 1; - } else if (ist->hwaccel_id == HWACCEL_GENERIC) { - type = ist->hwaccel_device_type; - dev = hw_device_get_by_type(type); - - // When "-qsv_device device" is used, an internal QSV device named - // as "__qsv_device" is created. Another QSV device is created too - // if "-init_hw_device qsv=name:device" is used. There are 2 QSV devices - // if both "-qsv_device device" and "-init_hw_device qsv=name:device" - // are used, hw_device_get_by_type(AV_HWDEVICE_TYPE_QSV) returns NULL. - // To keep back-compatibility with the removed ad-hoc libmfx setup code, - // call hw_device_get_by_name("__qsv_device") to select the internal QSV - // device. - if (!dev && type == AV_HWDEVICE_TYPE_QSV) - dev = hw_device_get_by_name("__qsv_device"); - - if (!dev) - err = hw_device_init_from_type(type, NULL, &dev); - } else { - dev = hw_device_match_by_codec(ist->dec); - if (!dev) { - // No device for this codec, but not using generic hwaccel - // and therefore may well not need one - ignore. - return 0; - } - } - } - - if (auto_device) { - int i; - if (!avcodec_get_hw_config(ist->dec, 0)) { - // Decoder does not support any hardware devices. - return 0; - } - for (i = 0; !dev; i++) { - config = avcodec_get_hw_config(ist->dec, i); - if (!config) - break; - type = config->device_type; - dev = hw_device_get_by_type(type); - if (dev) { - av_log(NULL, AV_LOG_INFO, "Using auto " - "hwaccel type %s with existing device %s.\n", - av_hwdevice_get_type_name(type), dev->name); - } - } - for (i = 0; !dev; i++) { - config = avcodec_get_hw_config(ist->dec, i); - if (!config) - break; - type = config->device_type; - // Try to make a new device of this type. - err = hw_device_init_from_type(type, ist->hwaccel_device, - &dev); - if (err < 0) { - // Can't make a device of this type. - continue; - } - if (ist->hwaccel_device) { - av_log(NULL, AV_LOG_INFO, "Using auto " - "hwaccel type %s with new device created " - "from %s.\n", av_hwdevice_get_type_name(type), - ist->hwaccel_device); - } else { - av_log(NULL, AV_LOG_INFO, "Using auto " - "hwaccel type %s with new default device.\n", - av_hwdevice_get_type_name(type)); - } - } - if (dev) { - ist->hwaccel_device_type = type; - } else { - av_log(NULL, AV_LOG_INFO, "Auto hwaccel " - "disabled: no device found.\n"); - ist->hwaccel_id = HWACCEL_NONE; - return 0; - } - } - - if (!dev) { - av_log(NULL, AV_LOG_ERROR, "No device available " - "for decoder: device type %s needed for codec %s.\n", - av_hwdevice_get_type_name(type), ist->dec->name); - return err; - } - - ist->dec_ctx->hw_device_ctx = av_buffer_ref(dev->device_ref); - if (!ist->dec_ctx->hw_device_ctx) - return AVERROR(ENOMEM); - - return 0; -} - int hw_device_setup_for_encode(OutputStream *ost) { const AVCodecHWConfig *config; From f15b20628675c72e3240352ff466e3ebc55a0702 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Fri, 19 May 2023 09:20:37 +0200 Subject: [PATCH 1192/2172] fftools/ffmpeg_hw: move hw_device_setup_for_encode() to ffmpeg_enc This function is entangled with encoder setup, so it is more encoding code rather than ffmpeg_hw code. This will allow making more encoder state private in the future. --- fftools/ffmpeg.h | 1 - fftools/ffmpeg_enc.c | 55 ++++++++++++++++++++++++++++++++++++++++++++ fftools/ffmpeg_hw.c | 55 -------------------------------------------- 3 files changed, 55 insertions(+), 56 deletions(-) diff --git a/fftools/ffmpeg.h b/fftools/ffmpeg.h index 895edbd6d63..927e402f7c5 100644 --- a/fftools/ffmpeg.h +++ b/fftools/ffmpeg.h @@ -802,7 +802,6 @@ int hw_device_init_from_type(enum AVHWDeviceType type, HWDevice **dev_out); void hw_device_free_all(void); -int hw_device_setup_for_encode(OutputStream *ost); /** * Get a hardware device to be used with this filtergraph. * The returned reference is owned by the callee, the caller diff --git a/fftools/ffmpeg_enc.c b/fftools/ffmpeg_enc.c index 9b81d14922a..7d99d9270bc 100644 --- a/fftools/ffmpeg_enc.c +++ b/fftools/ffmpeg_enc.c @@ -103,6 +103,61 @@ int enc_alloc(Encoder **penc, const AVCodec *codec) return AVERROR(ENOMEM); } +static int hw_device_setup_for_encode(OutputStream *ost) +{ + const AVCodecHWConfig *config; + HWDevice *dev = NULL; + AVBufferRef *frames_ref = NULL; + int i; + + if (ost->filter) { + frames_ref = av_buffersink_get_hw_frames_ctx(ost->filter->filter); + if (frames_ref && + ((AVHWFramesContext*)frames_ref->data)->format == + ost->enc_ctx->pix_fmt) { + // Matching format, will try to use hw_frames_ctx. + } else { + frames_ref = NULL; + } + } + + for (i = 0;; i++) { + config = avcodec_get_hw_config(ost->enc_ctx->codec, i); + if (!config) + break; + + if (frames_ref && + config->methods & AV_CODEC_HW_CONFIG_METHOD_HW_FRAMES_CTX && + (config->pix_fmt == AV_PIX_FMT_NONE || + config->pix_fmt == ost->enc_ctx->pix_fmt)) { + av_log(ost->enc_ctx, AV_LOG_VERBOSE, "Using input " + "frames context (format %s) with %s encoder.\n", + av_get_pix_fmt_name(ost->enc_ctx->pix_fmt), + ost->enc_ctx->codec->name); + ost->enc_ctx->hw_frames_ctx = av_buffer_ref(frames_ref); + if (!ost->enc_ctx->hw_frames_ctx) + return AVERROR(ENOMEM); + return 0; + } + + if (!dev && + config->methods & AV_CODEC_HW_CONFIG_METHOD_HW_DEVICE_CTX) + dev = hw_device_get_by_type(config->device_type); + } + + if (dev) { + av_log(ost->enc_ctx, AV_LOG_VERBOSE, "Using device %s " + "(type %s) with %s encoder.\n", dev->name, + av_hwdevice_get_type_name(dev->type), ost->enc_ctx->codec->name); + ost->enc_ctx->hw_device_ctx = av_buffer_ref(dev->device_ref); + if (!ost->enc_ctx->hw_device_ctx) + return AVERROR(ENOMEM); + } else { + // No device required, or no device available. + } + return 0; +} + static void set_encoder_id(OutputFile *of, OutputStream *ost) { const char *cname = ost->enc_ctx->codec->name; diff --git a/fftools/ffmpeg_hw.c b/fftools/ffmpeg_hw.c index d28257a1d64..4a0b346fe1a 100644 --- a/fftools/ffmpeg_hw.c +++ b/fftools/ffmpeg_hw.c @@ -297,61 +297,6 @@ void hw_device_free_all(void) nb_hw_devices = 0; } -int hw_device_setup_for_encode(OutputStream *ost) -{ - const AVCodecHWConfig *config; - HWDevice *dev = NULL; - AVBufferRef *frames_ref = NULL; - int i; - - if (ost->filter) { - frames_ref = av_buffersink_get_hw_frames_ctx(ost->filter->filter); - if (frames_ref && - ((AVHWFramesContext*)frames_ref->data)->format == - ost->enc_ctx->pix_fmt) { - // Matching format, will try to use hw_frames_ctx. - } else { - frames_ref = NULL; - } - } - - for (i = 0;; i++) { - config = avcodec_get_hw_config(ost->enc_ctx->codec, i); - if (!config) - break; - - if (frames_ref && - config->methods & AV_CODEC_HW_CONFIG_METHOD_HW_FRAMES_CTX && - (config->pix_fmt == AV_PIX_FMT_NONE || - config->pix_fmt == ost->enc_ctx->pix_fmt)) { - av_log(ost->enc_ctx, AV_LOG_VERBOSE, "Using input " - "frames context (format %s) with %s encoder.\n", - av_get_pix_fmt_name(ost->enc_ctx->pix_fmt), - ost->enc_ctx->codec->name); - ost->enc_ctx->hw_frames_ctx = av_buffer_ref(frames_ref); - if (!ost->enc_ctx->hw_frames_ctx) - return AVERROR(ENOMEM); - return 0; - } - - if (!dev && - config->methods & AV_CODEC_HW_CONFIG_METHOD_HW_DEVICE_CTX) - dev = hw_device_get_by_type(config->device_type); - } - - if (dev) { - av_log(ost->enc_ctx, AV_LOG_VERBOSE, "Using device %s " - "(type %s) with %s encoder.\n", dev->name, - av_hwdevice_get_type_name(dev->type), ost->enc_ctx->codec->name); - ost->enc_ctx->hw_device_ctx = av_buffer_ref(dev->device_ref); - if (!ost->enc_ctx->hw_device_ctx) - return AVERROR(ENOMEM); - } else { - // No device required, or no device available. - } - return 0; -} - static int hwaccel_retrieve_data(AVCodecContext *avctx, AVFrame *input) { InputStream *ist = avctx->opaque; From 2b3905254ea1a38532278c38d2fe1b5f16ca95b9 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Fri, 19 May 2023 09:46:31 +0200 Subject: [PATCH 1193/2172] fftools/ffmpeg_enc: use AVFrame.hw_frames_ctx for encoder hw setup It should be the same as the one that can be extracted from the filter and does not require access to outside data. --- fftools/ffmpeg_enc.c | 20 ++++++++------------ 1 file changed, 8 insertions(+), 12 deletions(-) diff --git a/fftools/ffmpeg_enc.c b/fftools/ffmpeg_enc.c index 7d99d9270bc..59e94664207 100644 --- a/fftools/ffmpeg_enc.c +++ b/fftools/ffmpeg_enc.c @@ -103,22 +103,18 @@ int enc_alloc(Encoder **penc, const AVCodec *codec) return AVERROR(ENOMEM); } -static int hw_device_setup_for_encode(OutputStream *ost) +static int hw_device_setup_for_encode(OutputStream *ost, AVBufferRef *frames_ref) { const AVCodecHWConfig *config; HWDevice *dev = NULL; - AVBufferRef *frames_ref = NULL; int i; - if (ost->filter) { - frames_ref = av_buffersink_get_hw_frames_ctx(ost->filter->filter); - if (frames_ref && - ((AVHWFramesContext*)frames_ref->data)->format == - ost->enc_ctx->pix_fmt) { - // Matching format, will try to use hw_frames_ctx. - } else { - frames_ref = NULL; - } + if (frames_ref && + ((AVHWFramesContext*)frames_ref->data)->format == + ost->enc_ctx->pix_fmt) { + // Matching format, will try to use hw_frames_ctx. + } else { + frames_ref = NULL; } for (i = 0;; i++) { @@ -388,7 +384,7 @@ int enc_open(OutputStream *ost, AVFrame *frame) av_dict_set(&ost->encoder_opts, "flags", "+frame_duration", AV_DICT_MULTIKEY); - ret = hw_device_setup_for_encode(ost); + ret = hw_device_setup_for_encode(ost, frame ? frame->hw_frames_ctx : NULL); if (ret < 0) { av_log(ost, AV_LOG_ERROR, "Encoding hardware device setup failed: %s\n", av_err2str(ret)); From ec75b79fe148174fa704e09c7235e1ea9a4c2680 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Wed, 17 May 2023 17:20:11 +0200 Subject: [PATCH 1194/2172] fftools/ffmpeg: fail earlier on text/bitmap subtitles mismatch Checking whether the user requested an unsupported conversion between text and bitmap subtitles can be done immediately when creating the output stream. --- fftools/ffmpeg_enc.c | 18 ------------------ fftools/ffmpeg_mux_init.c | 17 +++++++++++++++++ 2 files changed, 17 insertions(+), 18 deletions(-) diff --git a/fftools/ffmpeg_enc.c b/fftools/ffmpeg_enc.c index 59e94664207..f023657a077 100644 --- a/fftools/ffmpeg_enc.c +++ b/fftools/ffmpeg_enc.c @@ -345,24 +345,6 @@ int enc_open(OutputStream *ost, AVFrame *frame) dec_ctx->subtitle_header_size); enc_ctx->subtitle_header_size = dec_ctx->subtitle_header_size; } - if (ist && ist->dec->type == AVMEDIA_TYPE_SUBTITLE && - enc_ctx->codec_type == AVMEDIA_TYPE_SUBTITLE) { - int input_props = 0, output_props = 0; - AVCodecDescriptor const *input_descriptor = - avcodec_descriptor_get(ist->dec->id); - AVCodecDescriptor const *output_descriptor = - avcodec_descriptor_get(enc_ctx->codec_id); - if (input_descriptor) - input_props = input_descriptor->props & (AV_CODEC_PROP_TEXT_SUB | AV_CODEC_PROP_BITMAP_SUB); - if (output_descriptor) - output_props = output_descriptor->props & (AV_CODEC_PROP_TEXT_SUB | AV_CODEC_PROP_BITMAP_SUB); - if (input_props && output_props && input_props != output_props) { - av_log(ost, AV_LOG_ERROR, - "Subtitle encoding currently only possible from text to text " - "or bitmap to bitmap"); - return AVERROR_INVALIDDATA; - } - } break; default: diff --git a/fftools/ffmpeg_mux_init.c b/fftools/ffmpeg_mux_init.c index b73791acee5..56f9d1215ca 100644 --- a/fftools/ffmpeg_mux_init.c +++ b/fftools/ffmpeg_mux_init.c @@ -822,6 +822,13 @@ static void new_stream_subtitle(Muxer *mux, const OptionsContext *o, if (ost->enc_ctx) { AVCodecContext *subtitle_enc = ost->enc_ctx; + + AVCodecDescriptor const *input_descriptor = + avcodec_descriptor_get(ost->ist->par->codec_id); + AVCodecDescriptor const *output_descriptor = + avcodec_descriptor_get(subtitle_enc->codec_id); + int input_props = 0, output_props = 0; + char *frame_size = NULL; MATCH_PER_STREAM_OPT(frame_sizes, str, frame_size, mux->fc, st); @@ -829,6 +836,16 @@ static void new_stream_subtitle(Muxer *mux, const OptionsContext *o, av_log(ost, AV_LOG_FATAL, "Invalid frame size: %s.\n", frame_size); exit_program(1); } + if (input_descriptor) + input_props = input_descriptor->props & (AV_CODEC_PROP_TEXT_SUB | AV_CODEC_PROP_BITMAP_SUB); + if (output_descriptor) + output_props = output_descriptor->props & (AV_CODEC_PROP_TEXT_SUB | AV_CODEC_PROP_BITMAP_SUB); + if (input_props && output_props && input_props != output_props) { + av_log(ost, AV_LOG_ERROR, + "Subtitle encoding currently only possible from text to text " + "or bitmap to bitmap\n"); + exit_program(1); + } } } From d9bcbf9200e4752c00d8e72ce4b5824dd6296633 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Wed, 17 May 2023 17:46:34 +0200 Subject: [PATCH 1195/2172] fftools/ffmpeg: drop outdated comments --- fftools/ffmpeg.c | 1 - fftools/ffmpeg_demux.c | 1 - 2 files changed, 2 deletions(-) diff --git a/fftools/ffmpeg.c b/fftools/ffmpeg.c index c70d38755b0..1fc13b3e29d 100644 --- a/fftools/ffmpeg.c +++ b/fftools/ffmpeg.c @@ -1431,7 +1431,6 @@ int main(int argc, char **argv) exit_program(1); } - /* file converter / grab */ if (nb_output_files <= 0) { av_log(NULL, AV_LOG_FATAL, "At least one output file must be specified\n"); exit_program(1); diff --git a/fftools/ffmpeg_demux.c b/fftools/ffmpeg_demux.c index 401ae1f850f..7318abc6d93 100644 --- a/fftools/ffmpeg_demux.c +++ b/fftools/ffmpeg_demux.c @@ -1569,7 +1569,6 @@ int ifile_open(const OptionsContext *o, const char *filename) d->thread_queue_size = o->thread_queue_size; - /* update the current parameters so that they match the one of the input stream */ add_input_streams(o, d); /* dump the file content */ From 6ee57fd2b6769725afa66d2f742d928db48ff19f Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Wed, 17 May 2023 17:56:43 +0200 Subject: [PATCH 1196/2172] fftools/ffmpeg_demux: only print demuxing stats if demuxing actually started If the transcoding process never got to reading any packets from this input then printing stats is just pointless noise. --- fftools/ffmpeg_demux.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/fftools/ffmpeg_demux.c b/fftools/ffmpeg_demux.c index 7318abc6d93..ed8d5d165a7 100644 --- a/fftools/ffmpeg_demux.c +++ b/fftools/ffmpeg_demux.c @@ -113,6 +113,8 @@ typedef struct Demuxer { int thread_queue_size; pthread_t thread; int non_blocking; + + int read_started; } Demuxer; typedef struct DemuxMsg { @@ -734,6 +736,8 @@ static int thread_start(Demuxer *d) goto fail; } + d->read_started = 1; + return 0; fail: av_thread_message_queue_free(&d->in_thread_queue); @@ -833,7 +837,7 @@ void ifile_close(InputFile **pf) thread_stop(d); - if (f->ctx) + if (d->read_started) demux_final_stats(d); for (int i = 0; i < f->nb_streams; i++) From d43ae45de0432143a32e2710ba4a4cf13e12a772 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Wed, 17 May 2023 17:59:16 +0200 Subject: [PATCH 1197/2172] fftools/ffmpeg_demux: initialize nb_streams_warn Fixes spurious new-stream warnings for unused streams after 9429624a76107020b5911f8307f366fed386b336 --- fftools/ffmpeg_demux.c | 1 + 1 file changed, 1 insertion(+) diff --git a/fftools/ffmpeg_demux.c b/fftools/ffmpeg_demux.c index ed8d5d165a7..bd267aa0ceb 100644 --- a/fftools/ffmpeg_demux.c +++ b/fftools/ffmpeg_demux.c @@ -1543,6 +1543,7 @@ int ifile_open(const OptionsContext *o, const char *filename) d->loop = o->loop; d->duration = 0; d->time_base = (AVRational){ 1, 1 }; + d->nb_streams_warn = ic->nb_streams; f->format_nots = !!(ic->iformat->flags & AVFMT_NOTIMESTAMPS); From 335688a3d3835c3b6e1364231b75e6817d7941a0 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Wed, 17 May 2023 21:20:13 +0200 Subject: [PATCH 1198/2172] fftools/ffmpeg_demux: skip unused/attachment streams in final stats No useful information can be printed for them. --- fftools/ffmpeg_demux.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/fftools/ffmpeg_demux.c b/fftools/ffmpeg_demux.c index bd267aa0ceb..33322ac5651 100644 --- a/fftools/ffmpeg_demux.c +++ b/fftools/ffmpeg_demux.c @@ -781,6 +781,9 @@ static void demux_final_stats(Demuxer *d) DemuxStream *ds = ds_from_ist(ist); enum AVMediaType type = ist->par->codec_type; + if (ist->discard || type == AVMEDIA_TYPE_ATTACHMENT) + continue; + total_size += ds->data_size; total_packets += ds->nb_packets; From dadeb28e257ef7d15695a5da57e1a7a81e716876 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Thu, 18 May 2023 05:39:39 +0200 Subject: [PATCH 1199/2172] fftools/ffmpeg_dec: add decoder private data Move InputStream.decoded_frame to it. Analogous to what has been previously done for all the other major components. --- fftools/ffmpeg.h | 5 ++++- fftools/ffmpeg_dec.c | 46 +++++++++++++++++++++++++++++++++++++++++- fftools/ffmpeg_demux.c | 7 ++----- 3 files changed, 51 insertions(+), 7 deletions(-) diff --git a/fftools/ffmpeg.h b/fftools/ffmpeg.h index 927e402f7c5..92e56ee80c5 100644 --- a/fftools/ffmpeg.h +++ b/fftools/ffmpeg.h @@ -324,6 +324,8 @@ typedef struct FilterGraph { int nb_outputs; } FilterGraph; +typedef struct Decoder Decoder; + typedef struct InputStream { const AVClass *class; @@ -343,10 +345,10 @@ typedef struct InputStream { * concurrently by the demuxing thread. */ AVCodecParameters *par; + Decoder *decoder; AVCodecContext *dec_ctx; const AVCodec *dec; const AVCodecDescriptor *codec_desc; - AVFrame *decoded_frame; AVPacket *pkt; AVRational framerate_guessed; @@ -812,6 +814,7 @@ AVBufferRef *hw_device_for_filter(void); int hwaccel_decode_init(AVCodecContext *avctx); int dec_open(InputStream *ist); +void dec_free(Decoder **pdec); /** * Submit a packet for decoding diff --git a/fftools/ffmpeg_dec.c b/fftools/ffmpeg_dec.c index 8946bf538d6..c62d10847a9 100644 --- a/fftools/ffmpeg_dec.c +++ b/fftools/ffmpeg_dec.c @@ -31,6 +31,45 @@ #include "ffmpeg.h" +struct Decoder { + AVFrame *frame; +}; + +void dec_free(Decoder **pdec) +{ + Decoder *dec = *pdec; + + if (!dec) + return; + + av_frame_free(&dec->frame); + + av_freep(pdec); +} + +static int dec_alloc(Decoder **pdec) +{ + Decoder *dec; + + *pdec = NULL; + + dec = av_mallocz(sizeof(*dec)); + if (!dec) + return AVERROR(ENOMEM); + + dec->frame = av_frame_alloc(); + if (!dec->frame) + goto fail; + + + *pdec = dec; + + return 0; +fail: + dec_free(&dec); + return AVERROR(ENOMEM); +} + static int send_frame_to_filters(InputStream *ist, AVFrame *decoded_frame) { int i, ret; @@ -373,6 +412,7 @@ static int send_filter_eof(InputStream *ist) int dec_packet(InputStream *ist, const AVPacket *pkt, int no_eof) { + Decoder *d = ist->decoder; AVCodecContext *dec = ist->dec_ctx; const char *type_desc = av_get_media_type_string(dec->codec_type); int ret; @@ -407,7 +447,7 @@ int dec_packet(InputStream *ist, const AVPacket *pkt, int no_eof) } while (1) { - AVFrame *frame = ist->decoded_frame; + AVFrame *frame = d->frame; update_benchmark(NULL); ret = avcodec_receive_frame(dec, frame); @@ -690,6 +730,10 @@ int dec_open(InputStream *ist) return AVERROR(EINVAL); } + ret = dec_alloc(&ist->decoder); + if (ret < 0) + return ret; + ist->dec_ctx->opaque = ist; ist->dec_ctx->get_format = get_format; diff --git a/fftools/ffmpeg_demux.c b/fftools/ffmpeg_demux.c index 33322ac5651..29691cf68b2 100644 --- a/fftools/ffmpeg_demux.c +++ b/fftools/ffmpeg_demux.c @@ -815,7 +815,8 @@ static void ist_free(InputStream **pist) if (!ist) return; - av_frame_free(&ist->decoded_frame); + dec_free(&ist->decoder); + av_packet_free(&ist->pkt); av_dict_free(&ist->decoder_opts); avsubtitle_free(&ist->prev_sub.subtitle); @@ -1196,10 +1197,6 @@ static void add_input_streams(const OptionsContext *o, Demuxer *d) exit_program(1); } - ist->decoded_frame = av_frame_alloc(); - if (!ist->decoded_frame) - report_and_exit(AVERROR(ENOMEM)); - ist->pkt = av_packet_alloc(); if (!ist->pkt) report_and_exit(AVERROR(ENOMEM)); From 5b05e9e32a70cbdd0a0dc2bd68a63b4afd8e12e1 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Thu, 18 May 2023 05:41:53 +0200 Subject: [PATCH 1200/2172] fftools/ffmpeg_dec: move InputStream.pkt to Decoder It is purely internal to decoding. --- fftools/ffmpeg.h | 1 - fftools/ffmpeg_dec.c | 8 +++++++- fftools/ffmpeg_demux.c | 5 ----- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/fftools/ffmpeg.h b/fftools/ffmpeg.h index 92e56ee80c5..b3778719805 100644 --- a/fftools/ffmpeg.h +++ b/fftools/ffmpeg.h @@ -349,7 +349,6 @@ typedef struct InputStream { AVCodecContext *dec_ctx; const AVCodec *dec; const AVCodecDescriptor *codec_desc; - AVPacket *pkt; AVRational framerate_guessed; diff --git a/fftools/ffmpeg_dec.c b/fftools/ffmpeg_dec.c index c62d10847a9..f2040f2d742 100644 --- a/fftools/ffmpeg_dec.c +++ b/fftools/ffmpeg_dec.c @@ -33,6 +33,7 @@ struct Decoder { AVFrame *frame; + AVPacket *pkt; }; void dec_free(Decoder **pdec) @@ -43,6 +44,7 @@ void dec_free(Decoder **pdec) return; av_frame_free(&dec->frame); + av_packet_free(&dec->pkt); av_freep(pdec); } @@ -61,6 +63,10 @@ static int dec_alloc(Decoder **pdec) if (!dec->frame) goto fail; + dec->pkt = av_packet_alloc(); + if (!dec->pkt) + goto fail; + *pdec = dec; @@ -418,7 +424,7 @@ int dec_packet(InputStream *ist, const AVPacket *pkt, int no_eof) int ret; if (dec->codec_type == AVMEDIA_TYPE_SUBTITLE) - return transcode_subtitles(ist, pkt ? pkt : ist->pkt); + return transcode_subtitles(ist, pkt ? pkt : d->pkt); // With fate-indeo3-2, we're getting 0-sized packets before EOF for some // reason. This seems like a semi-critical bug. Don't trigger EOF, and diff --git a/fftools/ffmpeg_demux.c b/fftools/ffmpeg_demux.c index 29691cf68b2..c65c72f556f 100644 --- a/fftools/ffmpeg_demux.c +++ b/fftools/ffmpeg_demux.c @@ -817,7 +817,6 @@ static void ist_free(InputStream **pist) dec_free(&ist->decoder); - av_packet_free(&ist->pkt); av_dict_free(&ist->decoder_opts); avsubtitle_free(&ist->prev_sub.subtitle); av_frame_free(&ist->sub2video.frame); @@ -1197,10 +1196,6 @@ static void add_input_streams(const OptionsContext *o, Demuxer *d) exit_program(1); } - ist->pkt = av_packet_alloc(); - if (!ist->pkt) - report_and_exit(AVERROR(ENOMEM)); - if (o->bitexact) ist->dec_ctx->flags |= AV_CODEC_FLAG_BITEXACT; From cad59cccafd07eaeae05009dbf2f7058ee9d5254 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Thu, 18 May 2023 05:52:23 +0200 Subject: [PATCH 1201/2172] fftools/ffmpeg_dec: move timestamp estimation state to Decoder It is purely internal to decoding. --- fftools/ffmpeg.h | 10 ----- fftools/ffmpeg_dec.c | 87 +++++++++++++++++++++++++----------------- fftools/ffmpeg_demux.c | 5 --- 3 files changed, 52 insertions(+), 50 deletions(-) diff --git a/fftools/ffmpeg.h b/fftools/ffmpeg.h index b3778719805..d9cac95710b 100644 --- a/fftools/ffmpeg.h +++ b/fftools/ffmpeg.h @@ -352,16 +352,6 @@ typedef struct InputStream { AVRational framerate_guessed; - // pts/estimated duration of the last decoded frame - // * in decoder timebase for video, - // * in last_frame_tb (may change during decoding) for audio - int64_t last_frame_pts; - int64_t last_frame_duration_est; - AVRational last_frame_tb; - int last_frame_sample_rate; - - int64_t filter_in_rescale_delta_last; - int64_t nb_samples; /* number of samples in the last decoded audio frame before looping */ AVDictionary *decoder_opts; diff --git a/fftools/ffmpeg_dec.c b/fftools/ffmpeg_dec.c index f2040f2d742..b750c83806c 100644 --- a/fftools/ffmpeg_dec.c +++ b/fftools/ffmpeg_dec.c @@ -34,6 +34,15 @@ struct Decoder { AVFrame *frame; AVPacket *pkt; + + // pts/estimated duration of the last decoded frame + // * in decoder timebase for video, + // * in last_frame_tb (may change during decoding) for audio + int64_t last_frame_pts; + int64_t last_frame_duration_est; + AVRational last_frame_tb; + int64_t last_filter_in_rescale_delta; + int last_frame_sample_rate; }; void dec_free(Decoder **pdec) @@ -67,6 +76,9 @@ static int dec_alloc(Decoder **pdec) if (!dec->pkt) goto fail; + dec->last_filter_in_rescale_delta = AV_NOPTS_VALUE; + dec->last_frame_pts = AV_NOPTS_VALUE; + dec->last_frame_tb = (AVRational){ 1, 1 }; *pdec = dec; @@ -94,21 +106,22 @@ static int send_frame_to_filters(InputStream *ist, AVFrame *decoded_frame) return ret; } -static AVRational audio_samplerate_update(InputStream *ist, const AVFrame *frame) +static AVRational audio_samplerate_update(void *logctx, Decoder *d, + const AVFrame *frame) { - const int prev = ist->last_frame_tb.den; + const int prev = d->last_frame_tb.den; const int sr = frame->sample_rate; AVRational tb_new; int64_t gcd; - if (frame->sample_rate == ist->last_frame_sample_rate) + if (frame->sample_rate == d->last_frame_sample_rate) goto finish; gcd = av_gcd(prev, sr); if (prev / gcd >= INT_MAX / sr) { - av_log(ist, AV_LOG_WARNING, + av_log(logctx, AV_LOG_WARNING, "Audio timestamps cannot be represented exactly after " "sample rate change: %d -> %d\n", prev, sr); @@ -123,20 +136,20 @@ static AVRational audio_samplerate_update(InputStream *ist, const AVFrame *frame !(frame->time_base.den % tb_new.den)) tb_new = frame->time_base; - if (ist->last_frame_pts != AV_NOPTS_VALUE) - ist->last_frame_pts = av_rescale_q(ist->last_frame_pts, - ist->last_frame_tb, tb_new); - ist->last_frame_duration_est = av_rescale_q(ist->last_frame_duration_est, - ist->last_frame_tb, tb_new); + if (d->last_frame_pts != AV_NOPTS_VALUE) + d->last_frame_pts = av_rescale_q(d->last_frame_pts, + d->last_frame_tb, tb_new); + d->last_frame_duration_est = av_rescale_q(d->last_frame_duration_est, + d->last_frame_tb, tb_new); - ist->last_frame_tb = tb_new; - ist->last_frame_sample_rate = frame->sample_rate; + d->last_frame_tb = tb_new; + d->last_frame_sample_rate = frame->sample_rate; finish: - return ist->last_frame_tb; + return d->last_frame_tb; } -static void audio_ts_process(InputStream *ist, AVFrame *frame) +static void audio_ts_process(void *logctx, Decoder *d, AVFrame *frame) { AVRational tb_filter = (AVRational){1, frame->sample_rate}; AVRational tb; @@ -145,27 +158,27 @@ static void audio_ts_process(InputStream *ist, AVFrame *frame) // on samplerate change, choose a new internal timebase for timestamp // generation that can represent timestamps from all the samplerates // seen so far - tb = audio_samplerate_update(ist, frame); - pts_pred = ist->last_frame_pts == AV_NOPTS_VALUE ? 0 : - ist->last_frame_pts + ist->last_frame_duration_est; + tb = audio_samplerate_update(logctx, d, frame); + pts_pred = d->last_frame_pts == AV_NOPTS_VALUE ? 0 : + d->last_frame_pts + d->last_frame_duration_est; if (frame->pts == AV_NOPTS_VALUE) { frame->pts = pts_pred; frame->time_base = tb; - } else if (ist->last_frame_pts != AV_NOPTS_VALUE && + } else if (d->last_frame_pts != AV_NOPTS_VALUE && frame->pts > av_rescale_q_rnd(pts_pred, tb, frame->time_base, AV_ROUND_UP)) { // there was a gap in timestamps, reset conversion state - ist->filter_in_rescale_delta_last = AV_NOPTS_VALUE; + d->last_filter_in_rescale_delta = AV_NOPTS_VALUE; } frame->pts = av_rescale_delta(frame->time_base, frame->pts, tb, frame->nb_samples, - &ist->filter_in_rescale_delta_last, tb); + &d->last_filter_in_rescale_delta, tb); - ist->last_frame_pts = frame->pts; - ist->last_frame_duration_est = av_rescale_q(frame->nb_samples, - tb_filter, tb); + d->last_frame_pts = frame->pts; + d->last_frame_duration_est = av_rescale_q(frame->nb_samples, + tb_filter, tb); // finally convert to filtering timebase frame->pts = av_rescale_q(frame->pts, tb, tb_filter); @@ -175,6 +188,7 @@ static void audio_ts_process(InputStream *ist, AVFrame *frame) static int64_t video_duration_estimate(const InputStream *ist, const AVFrame *frame) { + const Decoder *d = ist->decoder; const InputFile *ifile = input_files[ist->file_index]; int64_t codec_duration = 0; @@ -202,9 +216,9 @@ static int64_t video_duration_estimate(const InputStream *ist, const AVFrame *fr // when timestamps are available, repeat last frame's actual duration // (i.e. pts difference between this and last frame) - if (frame->pts != AV_NOPTS_VALUE && ist->last_frame_pts != AV_NOPTS_VALUE && - frame->pts > ist->last_frame_pts) - return frame->pts - ist->last_frame_pts; + if (frame->pts != AV_NOPTS_VALUE && d->last_frame_pts != AV_NOPTS_VALUE && + frame->pts > d->last_frame_pts) + return frame->pts - d->last_frame_pts; // try frame/codec duration if (frame->duration > 0) @@ -221,11 +235,13 @@ static int64_t video_duration_estimate(const InputStream *ist, const AVFrame *fr } // last resort is last frame's estimated duration, and 1 - return FFMAX(ist->last_frame_duration_est, 1); + return FFMAX(d->last_frame_duration_est, 1); } static int video_frame_process(InputStream *ist, AVFrame *frame) { + Decoder *d = ist->decoder; + // The following line may be required in some cases where there is no parser // or the parser does not has_b_frames correctly if (ist->par->video_delay < ist->dec_ctx->has_b_frames) { @@ -273,13 +289,13 @@ static int video_frame_process(InputStream *ist, AVFrame *frame) // no timestamp available - extrapolate from previous frame duration if (frame->pts == AV_NOPTS_VALUE) - frame->pts = ist->last_frame_pts == AV_NOPTS_VALUE ? 0 : - ist->last_frame_pts + ist->last_frame_duration_est; + frame->pts = d->last_frame_pts == AV_NOPTS_VALUE ? 0 : + d->last_frame_pts + d->last_frame_duration_est; // update timestamp history - ist->last_frame_duration_est = video_duration_estimate(ist, frame); - ist->last_frame_pts = frame->pts; - ist->last_frame_tb = frame->time_base; + d->last_frame_duration_est = video_duration_estimate(ist, frame); + d->last_frame_pts = frame->pts; + d->last_frame_tb = frame->time_base; if (debug_ts) { av_log(ist, AV_LOG_INFO, @@ -404,12 +420,13 @@ static int transcode_subtitles(InputStream *ist, const AVPacket *pkt) static int send_filter_eof(InputStream *ist) { + Decoder *d = ist->decoder; int i, ret; for (i = 0; i < ist->nb_filters; i++) { - int64_t end_pts = ist->last_frame_pts == AV_NOPTS_VALUE ? AV_NOPTS_VALUE : - ist->last_frame_pts + ist->last_frame_duration_est; - ret = ifilter_send_eof(ist->filters[i], end_pts, ist->last_frame_tb); + int64_t end_pts = d->last_frame_pts == AV_NOPTS_VALUE ? AV_NOPTS_VALUE : + d->last_frame_pts + d->last_frame_duration_est; + ret = ifilter_send_eof(ist->filters[i], end_pts, d->last_frame_tb); if (ret < 0) return ret; } @@ -511,7 +528,7 @@ int dec_packet(InputStream *ist, const AVPacket *pkt, int no_eof) ist->samples_decoded += frame->nb_samples; ist->nb_samples = frame->nb_samples; - audio_ts_process(ist, frame); + audio_ts_process(ist, ist->decoder, frame); } else { ret = video_frame_process(ist, frame); if (ret < 0) { diff --git a/fftools/ffmpeg_demux.c b/fftools/ffmpeg_demux.c index c65c72f556f..e02bdc3b96d 100644 --- a/fftools/ffmpeg_demux.c +++ b/fftools/ffmpeg_demux.c @@ -1181,11 +1181,6 @@ static void add_input_streams(const OptionsContext *o, Demuxer *d) exit_program(1); } - ist->filter_in_rescale_delta_last = AV_NOPTS_VALUE; - - ist->last_frame_pts = AV_NOPTS_VALUE; - ist->last_frame_tb = (AVRational){ 1, 1 }; - ist->dec_ctx = avcodec_alloc_context3(ist->dec); if (!ist->dec_ctx) report_and_exit(AVERROR(ENOMEM)); From 6abb4a28ef8309ff49cea2b81d3a8e8f38fbc6f7 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Fri, 19 May 2023 09:53:57 +0200 Subject: [PATCH 1202/2172] fftools/ffmpeg: add InputStream.index This allows to avoid access to the underlying AVStream in many places. --- fftools/ffmpeg.c | 6 +++--- fftools/ffmpeg.h | 2 ++ fftools/ffmpeg_dec.c | 6 +++--- fftools/ffmpeg_demux.c | 1 + fftools/ffmpeg_filter.c | 10 +++++----- fftools/ffmpeg_mux_init.c | 2 +- 6 files changed, 15 insertions(+), 12 deletions(-) diff --git a/fftools/ffmpeg.c b/fftools/ffmpeg.c index 1fc13b3e29d..0539a458564 100644 --- a/fftools/ffmpeg.c +++ b/fftools/ffmpeg.c @@ -539,7 +539,7 @@ OutputStream *ost_iter(OutputStream *prev) InputStream *ist_iter(InputStream *prev) { int if_idx = prev ? prev->file_index : 0; - int ist_idx = prev ? prev->st->index + 1 : 0; + int ist_idx = prev ? prev->index + 1 : 0; for (; if_idx < nb_input_files; if_idx++) { InputFile *f = input_files[if_idx]; @@ -937,7 +937,7 @@ static void print_stream_maps(void) for (int j = 0; j < ist->nb_filters; j++) { if (!filtergraph_is_simple(ist->filters[j]->graph)) { av_log(NULL, AV_LOG_INFO, " Stream #%d:%d (%s) -> %s", - ist->file_index, ist->st->index, ist->dec ? ist->dec->name : "?", + ist->file_index, ist->index, ist->dec ? ist->dec->name : "?", ist->filters[j]->name); if (nb_filtergraphs > 1) av_log(NULL, AV_LOG_INFO, " (graph %d)", ist->filters[j]->graph->index); @@ -967,7 +967,7 @@ static void print_stream_maps(void) av_log(NULL, AV_LOG_INFO, " Stream #%d:%d -> #%d:%d", ost->ist->file_index, - ost->ist->st->index, + ost->ist->index, ost->file_index, ost->index); if (ost->enc_ctx) { diff --git a/fftools/ffmpeg.h b/fftools/ffmpeg.h index d9cac95710b..95334825ef2 100644 --- a/fftools/ffmpeg.h +++ b/fftools/ffmpeg.h @@ -330,6 +330,8 @@ typedef struct InputStream { const AVClass *class; int file_index; + int index; + AVStream *st; int discard; /* true if stream data should be discarded */ int user_set_discard; diff --git a/fftools/ffmpeg_dec.c b/fftools/ffmpeg_dec.c index b750c83806c..c89630512a1 100644 --- a/fftools/ffmpeg_dec.c +++ b/fftools/ffmpeg_dec.c @@ -475,7 +475,7 @@ int dec_packet(InputStream *ist, const AVPacket *pkt, int no_eof) update_benchmark(NULL); ret = avcodec_receive_frame(dec, frame); update_benchmark("decode_%s %d.%d", type_desc, - ist->file_index, ist->st->index); + ist->file_index, ist->index); if (ret == AVERROR(EAGAIN)) { av_assert0(pkt); // should never happen during flushing @@ -533,7 +533,7 @@ int dec_packet(InputStream *ist, const AVPacket *pkt, int no_eof) ret = video_frame_process(ist, frame); if (ret < 0) { av_log(NULL, AV_LOG_FATAL, "Error while processing the decoded " - "data for stream #%d:%d\n", ist->file_index, ist->st->index); + "data for stream #%d:%d\n", ist->file_index, ist->index); exit_program(1); } } @@ -582,7 +582,7 @@ static enum AVPixelFormat get_format(AVCodecContext *s, const enum AVPixelFormat "%s hwaccel requested for input stream #%d:%d, " "but cannot be initialized.\n", av_hwdevice_get_type_name(config->device_type), - ist->file_index, ist->st->index); + ist->file_index, ist->index); return AV_PIX_FMT_NONE; } continue; diff --git a/fftools/ffmpeg_demux.c b/fftools/ffmpeg_demux.c index e02bdc3b96d..828a1182f08 100644 --- a/fftools/ffmpeg_demux.c +++ b/fftools/ffmpeg_demux.c @@ -1025,6 +1025,7 @@ static DemuxStream *demux_stream_alloc(Demuxer *d, AVStream *st) ds->ist.st = st; ds->ist.file_index = f->index; + ds->ist.index = st->index; ds->ist.class = &input_stream_class; snprintf(ds->log_name, sizeof(ds->log_name), "%cist#%d:%d/%s", diff --git a/fftools/ffmpeg_filter.c b/fftools/ffmpeg_filter.c index 640ecec067c..f37b867b316 100644 --- a/fftools/ffmpeg_filter.c +++ b/fftools/ffmpeg_filter.c @@ -1073,7 +1073,7 @@ static int configure_input_video_filter(FilterGraph *fg, InputFilter *ifilter, if (fr.num && fr.den) av_bprintf(&args, ":frame_rate=%d/%d", fr.num, fr.den); snprintf(name, sizeof(name), "graph %d input from stream %d:%d", fg->index, - ist->file_index, ist->st->index); + ist->file_index, ist->index); if ((ret = avfilter_graph_create_filter(&ifilter->filter, buffer_filt, name, @@ -1127,7 +1127,7 @@ static int configure_input_video_filter(FilterGraph *fg, InputFilter *ifilter, } snprintf(name, sizeof(name), "trim_in_%d_%d", - ist->file_index, ist->st->index); + ist->file_index, ist->index); if (copy_ts) { tsoffset = f->start_time == AV_NOPTS_VALUE ? 0 : f->start_time; if (!start_at_zero && f->ctx->start_time != AV_NOPTS_VALUE) @@ -1180,7 +1180,7 @@ static int configure_input_audio_filter(FilterGraph *fg, InputFilter *ifilter, } else av_bprintf(&args, ":channels=%d", ifp->ch_layout.nb_channels); snprintf(name, sizeof(name), "graph_%d_in_%d_%d", fg->index, - ist->file_index, ist->st->index); + ist->file_index, ist->index); if ((ret = avfilter_graph_create_filter(&ifilter->filter, abuffer_filt, name, args.str, NULL, @@ -1189,7 +1189,7 @@ static int configure_input_audio_filter(FilterGraph *fg, InputFilter *ifilter, last_filter = ifilter->filter; snprintf(name, sizeof(name), "trim for input stream %d:%d", - ist->file_index, ist->st->index); + ist->file_index, ist->index); if (copy_ts) { tsoffset = f->start_time == AV_NOPTS_VALUE ? 0 : f->start_time; if (!start_at_zero && f->ctx->start_time != AV_NOPTS_VALUE) @@ -1574,7 +1574,7 @@ int ifilter_send_eof(InputFilter *ifilter, int64_t pts, AVRational tb) ifp->type_src == AVMEDIA_TYPE_VIDEO)) { av_log(NULL, AV_LOG_ERROR, "Cannot determine format of input stream %d:%d after EOF\n", - ifp->ist->file_index, ifp->ist->st->index); + ifp->ist->file_index, ifp->ist->index); return AVERROR_INVALIDDATA; } } diff --git a/fftools/ffmpeg_mux_init.c b/fftools/ffmpeg_mux_init.c index 56f9d1215ca..dc33d225dfd 100644 --- a/fftools/ffmpeg_mux_init.c +++ b/fftools/ffmpeg_mux_init.c @@ -792,7 +792,7 @@ static void new_stream_audio(Muxer *mux, const OptionsContext *o, ist = ost->ist; } - if (!ist || (ist->file_index == map->file_idx && ist->st->index == map->stream_idx)) { + if (!ist || (ist->file_index == map->file_idx && ist->index == map->stream_idx)) { if (av_reallocp_array(&ost->audio_channels_map, ost->audio_channels_mapped + 1, sizeof(*ost->audio_channels_map) From 4e96a71626996c5f128655c472e3b98558023f33 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Fri, 19 May 2023 09:57:24 +0200 Subject: [PATCH 1203/2172] fftools/ffmpeg_demux: log discontinuity warnings to stream context Allows simplifying the log message. --- fftools/ffmpeg_demux.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/fftools/ffmpeg_demux.c b/fftools/ffmpeg_demux.c index 828a1182f08..561b4b00021 100644 --- a/fftools/ffmpeg_demux.c +++ b/fftools/ffmpeg_demux.c @@ -248,12 +248,10 @@ static void ts_discontinuity_detect(Demuxer *d, InputStream *ist, if (FFABS(delta) > 1LL * dts_delta_threshold * AV_TIME_BASE || pkt_dts + AV_TIME_BASE/10 < ds->dts) { d->ts_offset_discont -= delta; - av_log(NULL, AV_LOG_WARNING, - "timestamp discontinuity for stream #%d:%d " - "(id=%d, type=%s): %"PRId64", new offset= %"PRId64"\n", - ist->file_index, ist->st->index, ist->st->id, - av_get_media_type_string(ist->par->codec_type), - delta, d->ts_offset_discont); + av_log(ist, AV_LOG_WARNING, + "timestamp discontinuity " + "(stream id=%d): %"PRId64", new offset= %"PRId64"\n", + ist->st->id, delta, d->ts_offset_discont); pkt->dts -= av_rescale_q(delta, AV_TIME_BASE_Q, pkt->time_base); if (pkt->pts != AV_NOPTS_VALUE) pkt->pts -= av_rescale_q(delta, AV_TIME_BASE_Q, pkt->time_base); From e9a868e9eef5215b468244596e2103a3add7759f Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Tue, 23 May 2023 15:45:37 +0200 Subject: [PATCH 1204/2172] fftools/sync_queue: add debug logging --- fftools/ffmpeg_mux_init.c | 4 ++-- fftools/sync_queue.c | 40 ++++++++++++++++++++++++++++++++++++--- fftools/sync_queue.h | 2 +- 3 files changed, 40 insertions(+), 6 deletions(-) diff --git a/fftools/ffmpeg_mux_init.c b/fftools/ffmpeg_mux_init.c index dc33d225dfd..7878789bb4b 100644 --- a/fftools/ffmpeg_mux_init.c +++ b/fftools/ffmpeg_mux_init.c @@ -1625,7 +1625,7 @@ static int setup_sync_queues(Muxer *mux, AVFormatContext *oc, int64_t buf_size_u * - at least one audio encoder requires constant frame sizes */ if ((of->shortest && nb_av_enc > 1) || limit_frames_av_enc || nb_audio_fs) { - of->sq_encode = sq_alloc(SYNC_QUEUE_FRAMES, buf_size_us); + of->sq_encode = sq_alloc(SYNC_QUEUE_FRAMES, buf_size_us, mux); if (!of->sq_encode) return AVERROR(ENOMEM); @@ -1650,7 +1650,7 @@ static int setup_sync_queues(Muxer *mux, AVFormatContext *oc, int64_t buf_size_u /* if there are any additional interleaved streams, then ALL the streams * are also synchronized before sending them to the muxer */ if (nb_interleaved > nb_av_enc) { - mux->sq_mux = sq_alloc(SYNC_QUEUE_PACKETS, buf_size_us); + mux->sq_mux = sq_alloc(SYNC_QUEUE_PACKETS, buf_size_us, mux); if (!mux->sq_mux) return AVERROR(ENOMEM); diff --git a/fftools/sync_queue.c b/fftools/sync_queue.c index a7aac040470..c0f33e92353 100644 --- a/fftools/sync_queue.c +++ b/fftools/sync_queue.c @@ -27,6 +27,7 @@ #include "libavutil/mathematics.h" #include "libavutil/mem.h" #include "libavutil/samplefmt.h" +#include "libavutil/timestamp.h" #include "objpool.h" #include "sync_queue.h" @@ -87,6 +88,8 @@ typedef struct SyncQueueStream { struct SyncQueue { enum SyncQueueType type; + void *logctx; + /* no more frames will be sent for any stream */ int finished; /* sync head: the stream with the _smallest_ head timestamp @@ -169,6 +172,11 @@ static void finish_stream(SyncQueue *sq, unsigned int stream_idx) { SyncQueueStream *st = &sq->streams[stream_idx]; + if (!st->finished) + av_log(sq->logctx, AV_LOG_DEBUG, + "sq: finish %u; head ts %s\n", stream_idx, + av_ts2timestr(st->head_ts, &st->tb)); + st->finished = 1; if (st->limiting && st->head_ts != AV_NOPTS_VALUE) { @@ -186,8 +194,14 @@ static void finish_stream(SyncQueue *sq, unsigned int stream_idx) for (unsigned int i = 0; i < sq->nb_streams; i++) { SyncQueueStream *st1 = &sq->streams[i]; if (st != st1 && st1->head_ts != AV_NOPTS_VALUE && - av_compare_ts(st->head_ts, st->tb, st1->head_ts, st1->tb) <= 0) + av_compare_ts(st->head_ts, st->tb, st1->head_ts, st1->tb) <= 0) { + if (!st1->finished) + av_log(sq->logctx, AV_LOG_DEBUG, + "sq: finish secondary %u; head ts %s\n", i, + av_ts2timestr(st1->head_ts, &st1->tb)); + st1->finished = 1; + } } } @@ -197,6 +211,8 @@ static void finish_stream(SyncQueue *sq, unsigned int stream_idx) return; } sq->finished = 1; + + av_log(sq->logctx, AV_LOG_DEBUG, "sq: finish queue\n"); } static void queue_head_update(SyncQueue *sq) @@ -306,6 +322,9 @@ static int overflow_heartbeat(SyncQueue *sq, int stream_idx) if (st1->head_ts != AV_NOPTS_VALUE) ts = FFMAX(st1->head_ts + 1, ts); + av_log(sq->logctx, AV_LOG_DEBUG, "sq: %u overflow heardbeat %s -> %s\n", + i, av_ts2timestr(st1->head_ts, &st1->tb), av_ts2timestr(ts, &st1->tb)); + stream_update_ts(sq, i, ts); } @@ -323,6 +342,7 @@ int sq_send(SyncQueue *sq, unsigned int stream_idx, SyncQueueFrame frame) st = &sq->streams[stream_idx]; if (frame_null(sq, frame)) { + av_log(sq->logctx, AV_LOG_DEBUG, "sq: %u EOF\n", stream_idx); finish_stream(sq, stream_idx); return 0; } @@ -347,6 +367,9 @@ int sq_send(SyncQueue *sq, unsigned int stream_idx, SyncQueueFrame frame) ts = frame_end(sq, dst, 0); + av_log(sq->logctx, AV_LOG_DEBUG, "sq: send %u ts %s\n", stream_idx, + av_ts2timestr(ts, &st->tb)); + ret = av_fifo_write(st->fifo, &dst, 1); if (ret < 0) { frame_move(sq, frame, dst); @@ -364,8 +387,12 @@ int sq_send(SyncQueue *sq, unsigned int stream_idx, SyncQueueFrame frame) else st->frames_sent++; - if (st->frames_sent >= st->frames_max) + if (st->frames_sent >= st->frames_max) { + av_log(sq->logctx, AV_LOG_DEBUG, "sq: %u frames_max %"PRIu64" reached\n", + stream_idx, st->frames_max); + finish_stream(sq, stream_idx); + } return 0; } @@ -531,6 +558,12 @@ static int receive_for_stream(SyncQueue *sq, unsigned int stream_idx, st->samples_queued -= frame_samples(sq, frame); } + av_log(sq->logctx, AV_LOG_DEBUG, + "sq: receive %u ts %s queue head %d ts %s\n", stream_idx, + av_ts2timestr(frame_end(sq, frame, 0), &st->tb), + sq->head_stream, + st_head ? av_ts2timestr(st_head->head_ts, &st_head->tb) : "N/A"); + return 0; } } @@ -630,7 +663,7 @@ void sq_frame_samples(SyncQueue *sq, unsigned int stream_idx, sq->align_mask = av_cpu_max_align() - 1; } -SyncQueue *sq_alloc(enum SyncQueueType type, int64_t buf_size_us) +SyncQueue *sq_alloc(enum SyncQueueType type, int64_t buf_size_us, void *logctx) { SyncQueue *sq = av_mallocz(sizeof(*sq)); @@ -639,6 +672,7 @@ SyncQueue *sq_alloc(enum SyncQueueType type, int64_t buf_size_us) sq->type = type; sq->buf_size_us = buf_size_us; + sq->logctx = logctx; sq->head_stream = -1; sq->head_finished_stream = -1; diff --git a/fftools/sync_queue.h b/fftools/sync_queue.h index bc7cd423907..dc5acfd4991 100644 --- a/fftools/sync_queue.h +++ b/fftools/sync_queue.h @@ -50,7 +50,7 @@ typedef struct SyncQueue SyncQueue; * * @param buf_size_us maximum duration that will be buffered in microseconds */ -SyncQueue *sq_alloc(enum SyncQueueType type, int64_t buf_size_us); +SyncQueue *sq_alloc(enum SyncQueueType type, int64_t buf_size_us, void *logctx); void sq_free(SyncQueue **sq); /** From 163e3a299e1cc06f0f871d8140def974757e4a7d Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Tue, 23 May 2023 15:46:11 +0200 Subject: [PATCH 1205/2172] fftools/sync_queue: make sure non-limiting streams are not used as queue head A non-limiting stream could mistakenly end up being the queue head, which would then produce incorrect synchronization, seen e.g. in fate-matroska-flac-extradata-update for certain number of frame threads (e.g. 5). Found-By: James Almer --- fftools/sync_queue.c | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/fftools/sync_queue.c b/fftools/sync_queue.c index c0f33e92353..bc107ba4fe7 100644 --- a/fftools/sync_queue.c +++ b/fftools/sync_queue.c @@ -217,17 +217,26 @@ static void finish_stream(SyncQueue *sq, unsigned int stream_idx) static void queue_head_update(SyncQueue *sq) { + av_assert0(sq->have_limiting); + if (sq->head_stream < 0) { + unsigned first_limiting = UINT_MAX; + /* wait for one timestamp in each stream before determining * the queue head */ for (unsigned int i = 0; i < sq->nb_streams; i++) { SyncQueueStream *st = &sq->streams[i]; - if (st->limiting && st->head_ts == AV_NOPTS_VALUE) + if (!st->limiting) + continue; + if (st->head_ts == AV_NOPTS_VALUE) return; + if (first_limiting == UINT_MAX) + first_limiting = i; } // placeholder value, correct one will be found below - sq->head_stream = 0; + av_assert0(first_limiting < UINT_MAX); + sq->head_stream = first_limiting; } for (unsigned int i = 0; i < sq->nb_streams; i++) { From e53260c1f4ce478943ad0d1ec1ca29a55024ae8a Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Sat, 27 May 2023 20:52:00 +0200 Subject: [PATCH 1206/2172] avfilter/af_silenceremove: add ptp detector --- doc/filters.texi | 2 + libavfilter/af_silenceremove.c | 6 +++ libavfilter/silenceremove_template.c | 68 +++++++++++++++++++++++++++- 3 files changed, 74 insertions(+), 2 deletions(-) diff --git a/doc/filters.texi b/doc/filters.texi index 4d9a3cf0b43..1a28bd86ce8 100644 --- a/doc/filters.texi +++ b/doc/filters.texi @@ -6472,6 +6472,8 @@ Root squared mean of absolute values of samples in moving window. Maximum of absolute values of samples in moving window. @item median Median of absolute values of samples in moving window. +@item ptp +Absolute of max peak to min peak difference of samples in moving window. @end table Default value is @code{rms}. diff --git a/libavfilter/af_silenceremove.c b/libavfilter/af_silenceremove.c index 752a362203d..46f28b4be73 100644 --- a/libavfilter/af_silenceremove.c +++ b/libavfilter/af_silenceremove.c @@ -37,6 +37,7 @@ enum SilenceDetect { D_RMS, D_PEAK, D_MEDIAN, + D_PTP, D_NB }; @@ -135,6 +136,7 @@ static const AVOption silenceremove_options[] = { { "rms", "use root mean squared values of samples", 0, AV_OPT_TYPE_CONST, {.i64=D_RMS}, 0, 0, AF, "detection" }, { "peak", "use max absolute values of samples", 0, AV_OPT_TYPE_CONST, {.i64=D_PEAK},0, 0, AF, "detection" }, { "median", "use median of absolute values of samples", 0, AV_OPT_TYPE_CONST, {.i64=D_MEDIAN},0, 0, AF, "detection" }, + { "ptp", "use absolute of max peak to min peak difference", 0, AV_OPT_TYPE_CONST, {.i64=D_PTP}, 0, 0, AF, "detection" }, { "window", "set duration of window for silence detection", OFFSET(window_duration_opt), AV_OPT_TYPE_DURATION, {.i64=20000}, 0, 100000000, AF }, { NULL } }; @@ -237,6 +239,10 @@ static int config_output(AVFilterLink *outlink) s->compute_flt = compute_avg_flt; s->compute_dbl = compute_avg_dbl; break; + case D_PTP: + s->compute_flt = compute_ptp_flt; + s->compute_dbl = compute_ptp_dbl; + break; case D_MEDIAN: s->compute_flt = compute_median_flt; s->compute_dbl = compute_median_dbl; diff --git a/libavfilter/silenceremove_template.c b/libavfilter/silenceremove_template.c index 901361d7ebd..34d50fcf0ed 100644 --- a/libavfilter/silenceremove_template.c +++ b/libavfilter/silenceremove_template.c @@ -23,6 +23,7 @@ #undef SQRT #undef ZERO #undef ONE +#undef TMIN #if DEPTH == 32 #define SAMPLE_FORMAT flt #define SQRT sqrtf @@ -31,6 +32,7 @@ #define ftype float #define ZERO 0.f #define ONE 1.f +#define TMIN -FLT_MAX #else #define SAMPLE_FORMAT dbl #define SQRT sqrt @@ -39,6 +41,7 @@ #define ftype double #define ZERO 0.0 #define ONE 1.0 +#define TMIN -DBL_MAX #endif #define fn3(a,b) a##_##b @@ -233,6 +236,65 @@ static ftype fn(compute_peak)(ftype *peak, ftype sample, ftype wsample, return r; } +static ftype fn(compute_ptp)(ftype *peak, ftype sample, ftype wsample, + int size, int *ffront, int *bback) +{ + int front = *ffront; + int back = *bback; + int empty = front == back && peak[front] == TMIN; + ftype r, max, min; + + if (!empty && wsample == peak[front]) { + peak[front] = TMIN; + if (back != front) { + front--; + if (front < 0) + front = size - 1; + } + empty = front == back; + } + + if (!empty && sample >= peak[front]) { + while (1) { + peak[front] = TMIN; + if (back == front) { + empty = 1; + break; + } + front--; + if (front < 0) + front = size - 1; + } + } + + while (!empty && sample >= peak[back]) { + peak[back] = TMIN; + if (back == front) { + empty = 1; + break; + } + back++; + if (back >= size) + back = 0; + } + + if (!empty) { + back--; + if (back < 0) + back = size - 1; + } + + peak[back] = sample; + max = peak[front]; + min = (back == front) ? -sample : sample; + r = FABS(max - min); + + *ffront = front; + *bback = back; + + return r; +} + static ftype fn(compute_rms)(ftype *cache, ftype sample, ftype wsample, int window_size, int *unused, int *unused2) { @@ -281,7 +343,8 @@ static void fn(filter_start)(AVFilterContext *ctx, if (s->start_found_periods < 0) goto skip; - if (s->detection != D_PEAK && s->detection != D_MEDIAN) + if (s->detection != D_PEAK && s->detection != D_MEDIAN && + s->detection != D_PTP) window_size = s->start_window_size; for (int ch = 0; ch < nb_channels; ch++) { @@ -374,7 +437,8 @@ static void fn(filter_stop)(AVFilterContext *ctx, stop_nb_samples, stop_window_nb_samples); - if (s->detection != D_PEAK && s->detection != D_MEDIAN) + if (s->detection != D_PEAK && s->detection != D_MEDIAN && + s->detection != D_PTP) window_size = s->stop_window_size; for (int ch = 0; ch < nb_channels; ch++) { From b95d123097f10a6a3e997cf055c2d4a3bcf78b24 Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Sun, 28 May 2023 11:14:24 +0200 Subject: [PATCH 1207/2172] avfilter/silenceremove_template: revert wrong change --- libavfilter/silenceremove_template.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/libavfilter/silenceremove_template.c b/libavfilter/silenceremove_template.c index 34d50fcf0ed..c1335adb95f 100644 --- a/libavfilter/silenceremove_template.c +++ b/libavfilter/silenceremove_template.c @@ -467,8 +467,10 @@ static void fn(filter_stop)(AVFilterContext *ctx, s->stop_found_periods = 0; if (s->stop_found_periods >= 0 || ctx->is_disabled) { - if (s->found_nonsilence) + if (s->found_nonsilence) { s->stop_sample_count += stop_thres; + s->stop_sample_count *= stop_thres; + } } else if (s->stop_silence_count > 0) { const int dst_pos = out_nb_samples * nb_channels; for (int ch = 0; ch < nb_channels; ch++) From 62d4110a64e04e481b8ae27e20575bc96fbea792 Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Sun, 28 May 2023 12:01:27 +0200 Subject: [PATCH 1208/2172] avfilter/af_silenceremove: add timestamp option --- doc/filters.texi | 10 ++++++++++ libavfilter/af_silenceremove.c | 19 +++++++++++++++++-- 2 files changed, 27 insertions(+), 2 deletions(-) diff --git a/doc/filters.texi b/doc/filters.texi index 1a28bd86ce8..50505dfaa08 100644 --- a/doc/filters.texi +++ b/doc/filters.texi @@ -6485,6 +6485,16 @@ In that case it may be needed to also set @option{start_silence} and/or @option{stop_silence} to nonzero values with also @option{start_duration} and/or @option{stop_duration} to nonzero values. Default value is @code{0.02}. Allowed range is from @code{0} to @code{10}. + +@item timestamp +Set processing mode of every audio frame output timestamp. +@table @option +@item write +Full timestamps rewrite, keep only the start time for the first output frame. +@item copy +Non-dropped frames are left with same timestamp as input audio frame. +@end table +Defaults value is @code{write}. @end table @subsection Examples diff --git a/libavfilter/af_silenceremove.c b/libavfilter/af_silenceremove.c index 46f28b4be73..6f152146ded 100644 --- a/libavfilter/af_silenceremove.c +++ b/libavfilter/af_silenceremove.c @@ -41,6 +41,12 @@ enum SilenceDetect { D_NB }; +enum TimestampMode { + TS_WRITE, + TS_COPY, + TS_NB +}; + enum ThresholdMode { T_ANY, T_ALL, @@ -67,6 +73,8 @@ typedef struct SilenceRemoveContext { int64_t window_duration_opt; + int timestamp_mode; + int start_found_periods; int stop_found_periods; @@ -138,6 +146,9 @@ static const AVOption silenceremove_options[] = { { "median", "use median of absolute values of samples", 0, AV_OPT_TYPE_CONST, {.i64=D_MEDIAN},0, 0, AF, "detection" }, { "ptp", "use absolute of max peak to min peak difference", 0, AV_OPT_TYPE_CONST, {.i64=D_PTP}, 0, 0, AF, "detection" }, { "window", "set duration of window for silence detection", OFFSET(window_duration_opt), AV_OPT_TYPE_DURATION, {.i64=20000}, 0, 100000000, AF }, + { "timestamp", "set how every output frame timestamp is processed", OFFSET(timestamp_mode), AV_OPT_TYPE_INT, {.i64=TS_WRITE}, 0, TS_NB-1, AF, "timestamp" }, + { "write", "full timestamps rewrite, keep only the start time", 0, AV_OPT_TYPE_CONST, {.i64=TS_WRITE}, 0, 0, AF, "timestamp" }, + { "copy", "non-dropped frames are left with same timestamp", 0, AV_OPT_TYPE_CONST, {.i64=TS_COPY}, 0, 0, AF, "timestamp" }, { NULL } }; @@ -293,7 +304,10 @@ static int filter_frame(AVFilterLink *outlink, AVFrame *in) return AVERROR(ENOMEM); } - out->pts = s->next_pts; + if (s->timestamp_mode == TS_WRITE) + out->pts = s->next_pts; + else + out->pts = in->pts; switch (outlink->format) { case AV_SAMPLE_FMT_FLT: @@ -395,7 +409,8 @@ static int activate(AVFilterContext *ctx) if (ret > 0) { if (s->start_periods == 1 && s->stop_periods == 0 && s->start_found_periods < 0) { - in->pts = s->next_pts; + if (s->timestamp_mode == TS_WRITE) + in->pts = s->next_pts; s->next_pts += in->nb_samples; return ff_filter_frame(outlink, in); } From a4611e3170b7f5240f719465d8033ab33a34cd70 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Fri, 28 Apr 2023 11:33:38 +0200 Subject: [PATCH 1209/2172] lavc/decode: pass AVHWAccel instead of AVCodecHWConfigInternal to hwaccel_init() The only thing besides the hwaccel that this function uses from AVCodecHWConfigInternal is the pixel format, which should always match the hwaccel one. Will be useful in following commits. --- libavcodec/decode.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/libavcodec/decode.c b/libavcodec/decode.c index 360837a0adb..18d85cf46f3 100644 --- a/libavcodec/decode.c +++ b/libavcodec/decode.c @@ -1111,12 +1111,10 @@ int avcodec_get_hw_frames_parameters(AVCodecContext *avctx, } static int hwaccel_init(AVCodecContext *avctx, - const AVCodecHWConfigInternal *hw_config) + const AVHWAccel *hwaccel) { - const AVHWAccel *hwaccel; int err; - hwaccel = hw_config->hwaccel; if (hwaccel->capabilities & AV_HWACCEL_CODEC_CAP_EXPERIMENTAL && avctx->strict_std_compliance > FF_COMPLIANCE_EXPERIMENTAL) { av_log(avctx, AV_LOG_WARNING, "Ignoring experimental hwaccel: %s\n", @@ -1137,7 +1135,7 @@ static int hwaccel_init(AVCodecContext *avctx, if (err < 0) { av_log(avctx, AV_LOG_ERROR, "Failed setup for format %s: " "hwaccel initialisation returned error.\n", - av_get_pix_fmt_name(hw_config->public.pix_fmt)); + av_get_pix_fmt_name(hwaccel->pix_fmt)); av_freep(&avctx->internal->hwaccel_priv_data); avctx->hwaccel = NULL; return err; @@ -1271,7 +1269,7 @@ int ff_get_format(AVCodecContext *avctx, const enum AVPixelFormat *fmt) if (hw_config->hwaccel) { av_log(avctx, AV_LOG_DEBUG, "Format %s requires hwaccel " "initialisation.\n", desc->name); - err = hwaccel_init(avctx, hw_config); + err = hwaccel_init(avctx, hw_config->hwaccel); if (err < 0) goto try_again; } From 3d2e1aa3242d6c4dc2b3a004b316921ce7e0ba79 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Fri, 28 Apr 2023 11:48:04 +0200 Subject: [PATCH 1210/2172] lavc/decode: stop duplicating code from hwaccel_uninit() --- libavcodec/avcodec.c | 5 ++--- libavcodec/decode.c | 4 ++-- libavcodec/hwconfig.h | 1 + 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/libavcodec/avcodec.c b/libavcodec/avcodec.c index 5a96899d505..db8226f9b3d 100644 --- a/libavcodec/avcodec.c +++ b/libavcodec/avcodec.c @@ -39,6 +39,7 @@ #include "decode.h" #include "encode.h" #include "frame_thread_encoder.h" +#include "hwconfig.h" #include "internal.h" #include "thread.h" @@ -459,9 +460,7 @@ av_cold int avcodec_close(AVCodecContext *avctx) av_buffer_unref(&avci->pool); - if (avctx->hwaccel && avctx->hwaccel->uninit) - avctx->hwaccel->uninit(avctx); - av_freep(&avci->hwaccel_priv_data); + ff_hwaccel_uninit(avctx); av_bsf_free(&avci->bsf); diff --git a/libavcodec/decode.c b/libavcodec/decode.c index 18d85cf46f3..d75f831a741 100644 --- a/libavcodec/decode.c +++ b/libavcodec/decode.c @@ -1145,7 +1145,7 @@ static int hwaccel_init(AVCodecContext *avctx, return 0; } -static void hwaccel_uninit(AVCodecContext *avctx) +void ff_hwaccel_uninit(AVCodecContext *avctx) { if (avctx->hwaccel && avctx->hwaccel->uninit) avctx->hwaccel->uninit(avctx); @@ -1184,7 +1184,7 @@ int ff_get_format(AVCodecContext *avctx, const enum AVPixelFormat *fmt) for (;;) { // Remove the previous hwaccel, if there was one. - hwaccel_uninit(avctx); + ff_hwaccel_uninit(avctx); user_choice = avctx->get_format(avctx, choices); if (user_choice == AV_PIX_FMT_NONE) { diff --git a/libavcodec/hwconfig.h b/libavcodec/hwconfig.h index 721424912c4..f03b744cdf4 100644 --- a/libavcodec/hwconfig.h +++ b/libavcodec/hwconfig.h @@ -39,6 +39,7 @@ typedef struct AVCodecHWConfigInternal { const AVHWAccel *hwaccel; } AVCodecHWConfigInternal; +void ff_hwaccel_uninit(AVCodecContext *avctx); // These macros are used to simplify AVCodecHWConfigInternal definitions. From 8b23644408ef4ea98184325d7a98f43c316143a1 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Fri, 28 Apr 2023 13:37:28 +0200 Subject: [PATCH 1211/2172] lavc/pthread_frame: add support for thread-safe hwaccels --- libavcodec/avcodec.h | 6 +++ libavcodec/hwconfig.h | 1 + libavcodec/pthread_frame.c | 101 ++++++++++++++++++++++++++++++------- 3 files changed, 89 insertions(+), 19 deletions(-) diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h index 06b1a120abe..dad443c8185 100644 --- a/libavcodec/avcodec.h +++ b/libavcodec/avcodec.h @@ -2253,6 +2253,12 @@ typedef struct AVHWAccel { * that avctx->hwaccel_priv_data is invalid. */ int (*frame_params)(AVCodecContext *avctx, AVBufferRef *hw_frames_ctx); + + /** + * Copy necessary context variables from a previous thread context to the current one. + * For thread-safe hwaccels only. + */ + int (*update_thread_context)(AVCodecContext *dst, const AVCodecContext *src); } AVHWAccel; /** diff --git a/libavcodec/hwconfig.h b/libavcodec/hwconfig.h index f03b744cdf4..d88dc37c8c9 100644 --- a/libavcodec/hwconfig.h +++ b/libavcodec/hwconfig.h @@ -24,6 +24,7 @@ #define HWACCEL_CAP_ASYNC_SAFE (1 << 0) +#define HWACCEL_CAP_THREAD_SAFE (1 << 1) typedef struct AVCodecHWConfigInternal { diff --git a/libavcodec/pthread_frame.c b/libavcodec/pthread_frame.c index 773e78ae345..28335231fd7 100644 --- a/libavcodec/pthread_frame.c +++ b/libavcodec/pthread_frame.c @@ -104,6 +104,12 @@ typedef struct PerThreadContext { int hwaccel_serializing; int async_serializing; + // set to 1 in ff_thread_finish_setup() when a threadsafe hwaccel is used; + // cannot check hwaccel caps directly, because + // worked threads clear hwaccel state for thread-unsafe hwaccels + // after each decode call + int hwaccel_threadsafe; + atomic_int debug_threads; ///< Set if the FF_DEBUG_THREADS option is set. } PerThreadContext; @@ -117,8 +123,8 @@ typedef struct FrameThreadContext { unsigned pthread_init_cnt; ///< Number of successfully initialized mutexes/conditions pthread_mutex_t buffer_mutex; ///< Mutex used to protect get/release_buffer(). /** - * This lock is used for ensuring threads run in serial when hwaccel - * is used. + * This lock is used for ensuring threads run in serial when thread-unsafe + * hwaccel is used. */ pthread_mutex_t hwaccel_mutex; pthread_mutex_t async_mutex; @@ -133,13 +139,19 @@ typedef struct FrameThreadContext { * While it is set, ff_thread_en/decode_frame won't return any results. */ - /* hwaccel state is temporarily stored here in order to transfer its ownership - * to the next decoding thread without the need for extra synchronization */ + /* hwaccel state for thread-unsafe hwaccels is temporarily stored here in + * order to transfer its ownership to the next decoding thread without the + * need for extra synchronization */ const AVHWAccel *stash_hwaccel; void *stash_hwaccel_context; void *stash_hwaccel_priv; } FrameThreadContext; +static int hwaccel_serial(const AVCodecContext *avctx) +{ + return avctx->hwaccel && !(avctx->hwaccel->caps_internal & HWACCEL_CAP_THREAD_SAFE); +} + static void async_lock(FrameThreadContext *fctx) { pthread_mutex_lock(&fctx->async_mutex); @@ -202,9 +214,9 @@ static attribute_align_arg void *frame_worker_thread(void *arg) * cannot be true here. */ av_assert0(!p->hwaccel_serializing); - /* if the previous thread uses hwaccel then we take the lock to ensure - * the threads don't run concurrently */ - if (avctx->hwaccel) { + /* if the previous thread uses thread-unsafe hwaccel then we take the + * lock to ensure the threads don't run concurrently */ + if (hwaccel_serial(avctx)) { pthread_mutex_lock(&p->parent->hwaccel_mutex); p->hwaccel_serializing = 1; } @@ -220,7 +232,8 @@ static attribute_align_arg void *frame_worker_thread(void *arg) ff_thread_finish_setup(avctx); if (p->hwaccel_serializing) { - /* wipe hwaccel state to avoid stale pointers lying around; + /* wipe hwaccel state for thread-unsafe hwaccels to avoid stale + * pointers lying around; * the state was transferred to FrameThreadContext in * ff_thread_finish_setup(), so nothing is leaked */ avctx->hwaccel = NULL; @@ -230,7 +243,8 @@ static attribute_align_arg void *frame_worker_thread(void *arg) p->hwaccel_serializing = 0; pthread_mutex_unlock(&p->parent->hwaccel_mutex); } - av_assert0(!avctx->hwaccel); + av_assert0(!avctx->hwaccel || + (avctx->hwaccel->caps_internal & HWACCEL_CAP_THREAD_SAFE)); if (p->async_serializing) { p->async_serializing = 0; @@ -332,8 +346,49 @@ FF_ENABLE_DEPRECATION_WARNINGS if (codec->update_thread_context_for_user) err = codec->update_thread_context_for_user(dst, src); } else { - if (codec->update_thread_context) + const PerThreadContext *p_src = src->internal->thread_ctx; + PerThreadContext *p_dst = dst->internal->thread_ctx; + + if (codec->update_thread_context) { err = codec->update_thread_context(dst, src); + if (err < 0) + return err; + } + + // reset dst hwaccel state if needed + av_assert0(p_dst->hwaccel_threadsafe || + (!dst->hwaccel && !dst->internal->hwaccel_priv_data)); + if (p_dst->hwaccel_threadsafe && + (!p_src->hwaccel_threadsafe || dst->hwaccel != src->hwaccel)) { + ff_hwaccel_uninit(dst); + p_dst->hwaccel_threadsafe = 0; + } + + // propagate hwaccel state for threadsafe hwaccels + if (p_src->hwaccel_threadsafe) { + if (!dst->hwaccel) { + if (src->hwaccel->priv_data_size) { + av_assert0(src->hwaccel->update_thread_context); + + dst->internal->hwaccel_priv_data = + av_mallocz(src->hwaccel->priv_data_size); + if (!dst->internal->hwaccel_priv_data) + return AVERROR(ENOMEM); + } + dst->hwaccel = src->hwaccel; + } + av_assert0(dst->hwaccel == src->hwaccel); + + if (src->hwaccel->update_thread_context) { + err = src->hwaccel->update_thread_context(dst, src); + if (err < 0) { + av_log(dst, AV_LOG_ERROR, "Error propagating hwaccel state\n"); + ff_hwaccel_uninit(dst); + return err; + } + } + p_dst->hwaccel_threadsafe = 1; + } } return err; @@ -441,10 +496,12 @@ static int submit_packet(PerThreadContext *p, AVCodecContext *user_avctx, } /* transfer the stashed hwaccel state, if any */ - av_assert0(!p->avctx->hwaccel); - FFSWAP(const AVHWAccel*, p->avctx->hwaccel, fctx->stash_hwaccel); - FFSWAP(void*, p->avctx->hwaccel_context, fctx->stash_hwaccel_context); - FFSWAP(void*, p->avctx->internal->hwaccel_priv_data, fctx->stash_hwaccel_priv); + av_assert0(!p->avctx->hwaccel || p->hwaccel_threadsafe); + if (!p->hwaccel_threadsafe) { + FFSWAP(const AVHWAccel*, p->avctx->hwaccel, fctx->stash_hwaccel); + FFSWAP(void*, p->avctx->hwaccel_context, fctx->stash_hwaccel_context); + FFSWAP(void*, p->avctx->internal->hwaccel_priv_data, fctx->stash_hwaccel_priv); + } av_packet_unref(p->avpkt); ret = av_packet_ref(p->avpkt, avpkt); @@ -598,7 +655,10 @@ void ff_thread_finish_setup(AVCodecContext *avctx) { if (!(avctx->active_thread_type&FF_THREAD_FRAME)) return; - if (avctx->hwaccel && !p->hwaccel_serializing) { + p->hwaccel_threadsafe = avctx->hwaccel && + (avctx->hwaccel->caps_internal & HWACCEL_CAP_THREAD_SAFE); + + if (hwaccel_serial(avctx) && !p->hwaccel_serializing) { pthread_mutex_lock(&p->parent->hwaccel_mutex); p->hwaccel_serializing = 1; } @@ -611,13 +671,16 @@ void ff_thread_finish_setup(AVCodecContext *avctx) { async_lock(p->parent); } - /* save hwaccel state for passing to the next thread; + /* thread-unsafe hwaccels share a single private data instance, so we + * save hwaccel state for passing to the next thread; * this is done here so that this worker thread can wipe its own hwaccel * state after decoding, without requiring synchronization */ av_assert0(!p->parent->stash_hwaccel); - p->parent->stash_hwaccel = avctx->hwaccel; - p->parent->stash_hwaccel_context = avctx->hwaccel_context; - p->parent->stash_hwaccel_priv = avctx->internal->hwaccel_priv_data; + if (hwaccel_serial(avctx)) { + p->parent->stash_hwaccel = avctx->hwaccel; + p->parent->stash_hwaccel_context = avctx->hwaccel_context; + p->parent->stash_hwaccel_priv = avctx->internal->hwaccel_priv_data; + } pthread_mutex_lock(&p->progress_mutex); if(atomic_load(&p->state) == STATE_SETUP_FINISHED){ From b6a6e2b19da74c44a0f3f0821d499c032bc74647 Mon Sep 17 00:00:00 2001 From: Lynne Date: Thu, 11 May 2023 03:55:47 +0200 Subject: [PATCH 1212/2172] lavc/decode: allow to allocate hwaccel_priv_data early --- libavcodec/decode.c | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/libavcodec/decode.c b/libavcodec/decode.c index d75f831a741..9ff132a15c3 100644 --- a/libavcodec/decode.c +++ b/libavcodec/decode.c @@ -1087,6 +1087,15 @@ int avcodec_get_hw_frames_parameters(AVCodecContext *avctx, if (!frames_ref) return AVERROR(ENOMEM); + if (!avctx->internal->hwaccel_priv_data) { + avctx->internal->hwaccel_priv_data = + av_mallocz(hwa->priv_data_size); + if (!avctx->internal->hwaccel_priv_data) { + av_buffer_unref(&frames_ref); + return AVERROR(ENOMEM); + } + } + ret = hwa->frame_params(avctx, frames_ref); if (ret >= 0) { AVHWFramesContext *frames_ctx = (AVHWFramesContext*)frames_ref->data; @@ -1122,7 +1131,7 @@ static int hwaccel_init(AVCodecContext *avctx, return AVERROR_PATCHWELCOME; } - if (hwaccel->priv_data_size) { + if (!avctx->internal->hwaccel_priv_data && hwaccel->priv_data_size) { avctx->internal->hwaccel_priv_data = av_mallocz(hwaccel->priv_data_size); if (!avctx->internal->hwaccel_priv_data) @@ -1288,6 +1297,9 @@ int ff_get_format(AVCodecContext *avctx, const enum AVPixelFormat *fmt) --n; } + if (ret < 0) + ff_hwaccel_uninit(avctx); + av_freep(&choices); return ret; } From dc2694557d41d0ff276d8da268e35bea39e42602 Mon Sep 17 00:00:00 2001 From: Lynne Date: Wed, 14 Dec 2022 00:02:11 +0100 Subject: [PATCH 1213/2172] h2645_vui: expose aspect_ratio_idc --- libavcodec/h2645_vui.c | 10 +++++----- libavcodec/h2645_vui.h | 1 + 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/libavcodec/h2645_vui.c b/libavcodec/h2645_vui.c index 0633fcbddd2..93e83a9e1f7 100644 --- a/libavcodec/h2645_vui.c +++ b/libavcodec/h2645_vui.c @@ -42,15 +42,15 @@ void ff_h2645_decode_common_vui_params(GetBitContext *gb, H2645VUI *vui, void *l aspect_ratio_info_present_flag = get_bits1(gb); if (aspect_ratio_info_present_flag) { - uint8_t aspect_ratio_idc = get_bits(gb, 8); - if (aspect_ratio_idc < FF_ARRAY_ELEMS(ff_h2645_pixel_aspect)) - vui->sar = ff_h2645_pixel_aspect[aspect_ratio_idc]; - else if (aspect_ratio_idc == EXTENDED_SAR) { + vui->aspect_ratio_idc = get_bits(gb, 8); + if (vui->aspect_ratio_idc < FF_ARRAY_ELEMS(ff_h2645_pixel_aspect)) + vui->sar = ff_h2645_pixel_aspect[vui->aspect_ratio_idc]; + else if (vui->aspect_ratio_idc == EXTENDED_SAR) { vui->sar.num = get_bits(gb, 16); vui->sar.den = get_bits(gb, 16); } else av_log(logctx, AV_LOG_WARNING, - "Unknown SAR index: %u.\n", aspect_ratio_idc); + "Unknown SAR index: %u.\n", vui->aspect_ratio_idc); } else vui->sar = (AVRational){ 0, 1 }; diff --git a/libavcodec/h2645_vui.h b/libavcodec/h2645_vui.h index 638da7c3667..f1aeab77587 100644 --- a/libavcodec/h2645_vui.h +++ b/libavcodec/h2645_vui.h @@ -26,6 +26,7 @@ typedef struct H2645VUI { AVRational sar; + int aspect_ratio_idc; int overscan_info_present_flag; int overscan_appropriate_flag; From 317fa3bd1dc50268110bc95f16f09edae22d1eaa Mon Sep 17 00:00:00 2001 From: Lynne Date: Wed, 14 Dec 2022 00:03:44 +0100 Subject: [PATCH 1214/2172] h2645_vui: expose aspect_ratio_info_present_flag --- libavcodec/h2645_vui.c | 6 ++---- libavcodec/h2645_vui.h | 1 + 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/libavcodec/h2645_vui.c b/libavcodec/h2645_vui.c index 93e83a9e1f7..e5c7bf46f9b 100644 --- a/libavcodec/h2645_vui.c +++ b/libavcodec/h2645_vui.c @@ -36,12 +36,10 @@ void ff_h2645_decode_common_vui_params(GetBitContext *gb, H2645VUI *vui, void *logctx) { - int aspect_ratio_info_present_flag; - av_log(logctx, AV_LOG_DEBUG, "Decoding VUI\n"); - aspect_ratio_info_present_flag = get_bits1(gb); - if (aspect_ratio_info_present_flag) { + vui->aspect_ratio_info_present_flag = get_bits1(gb); + if (vui->aspect_ratio_info_present_flag) { vui->aspect_ratio_idc = get_bits(gb, 8); if (vui->aspect_ratio_idc < FF_ARRAY_ELEMS(ff_h2645_pixel_aspect)) vui->sar = ff_h2645_pixel_aspect[vui->aspect_ratio_idc]; diff --git a/libavcodec/h2645_vui.h b/libavcodec/h2645_vui.h index f1aeab77587..2c839f4b015 100644 --- a/libavcodec/h2645_vui.h +++ b/libavcodec/h2645_vui.h @@ -27,6 +27,7 @@ typedef struct H2645VUI { AVRational sar; int aspect_ratio_idc; + int aspect_ratio_info_present_flag; int overscan_info_present_flag; int overscan_appropriate_flag; From 02f38af2dd3acbbc6aafa627bd50c811286553f8 Mon Sep 17 00:00:00 2001 From: Lynne Date: Fri, 18 Mar 2022 15:11:02 +0100 Subject: [PATCH 1215/2172] h264_ps: expose pps_id --- libavcodec/h264_ps.c | 1 + libavcodec/h264_ps.h | 1 + 2 files changed, 2 insertions(+) diff --git a/libavcodec/h264_ps.c b/libavcodec/h264_ps.c index d0d1e659039..4ec5bd4e808 100644 --- a/libavcodec/h264_ps.c +++ b/libavcodec/h264_ps.c @@ -731,6 +731,7 @@ int ff_h264_decode_picture_parameter_set(GetBitContext *gb, AVCodecContext *avct if (!(bit_length & 7) && pps->data_size < sizeof(pps->data)) pps->data[pps->data_size++] = 0x80; + pps->pps_id = pps_id; pps->sps_id = get_ue_golomb_31(gb); if ((unsigned)pps->sps_id >= MAX_SPS_COUNT || !ps->sps_list[pps->sps_id]) { diff --git a/libavcodec/h264_ps.h b/libavcodec/h264_ps.h index 5c35761fbc8..c3f0888f245 100644 --- a/libavcodec/h264_ps.h +++ b/libavcodec/h264_ps.h @@ -103,6 +103,7 @@ typedef struct SPS { * Picture parameter set */ typedef struct PPS { + unsigned int pps_id; unsigned int sps_id; int cabac; ///< entropy_coding_mode_flag int pic_order_present; ///< pic_order_present_flag From 6718b37e5dac73868db9f595d36268e6a0752347 Mon Sep 17 00:00:00 2001 From: Lynne Date: Fri, 18 Mar 2022 16:17:33 +0100 Subject: [PATCH 1216/2172] h264_ps: set pic_scaling_matrix_present_flag --- libavcodec/h264_ps.c | 7 +++++-- libavcodec/h264_ps.h | 1 + 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/libavcodec/h264_ps.c b/libavcodec/h264_ps.c index 4ec5bd4e808..a94f5350c45 100644 --- a/libavcodec/h264_ps.c +++ b/libavcodec/h264_ps.c @@ -226,6 +226,7 @@ static int decode_scaling_list(GetBitContext *gb, uint8_t *factors, int size, /* returns non zero if the provided SPS scaling matrix has been filled */ static int decode_scaling_matrices(GetBitContext *gb, const SPS *sps, const PPS *pps, int is_sps, + int present_flag, uint8_t(*scaling_matrix4)[16], uint8_t(*scaling_matrix8)[64]) { @@ -237,7 +238,7 @@ static int decode_scaling_matrices(GetBitContext *gb, const SPS *sps, fallback_sps ? sps->scaling_matrix8[3] : default_scaling8[1] }; int ret = 0; - if (get_bits1(gb)) { + if (present_flag) { ret |= decode_scaling_list(gb, scaling_matrix4[0], 16, default_scaling4[0], fallback[0]); // Intra, Y ret |= decode_scaling_list(gb, scaling_matrix4[1], 16, default_scaling4[0], scaling_matrix4[0]); // Intra, Cr ret |= decode_scaling_list(gb, scaling_matrix4[2], 16, default_scaling4[0], scaling_matrix4[1]); // Intra, Cb @@ -368,7 +369,7 @@ int ff_h264_decode_seq_parameter_set(GetBitContext *gb, AVCodecContext *avctx, goto fail; } sps->transform_bypass = get_bits1(gb); - ret = decode_scaling_matrices(gb, sps, NULL, 1, + ret = decode_scaling_matrices(gb, sps, NULL, 1, get_bits1(gb), sps->scaling_matrix4, sps->scaling_matrix8); if (ret < 0) goto fail; @@ -803,7 +804,9 @@ int ff_h264_decode_picture_parameter_set(GetBitContext *gb, AVCodecContext *avct bits_left = bit_length - get_bits_count(gb); if (bits_left > 0 && more_rbsp_data_in_pps(sps, avctx)) { pps->transform_8x8_mode = get_bits1(gb); + pps->pic_scaling_matrix_present_flag = get_bits1(gb); ret = decode_scaling_matrices(gb, sps, pps, 0, + pps->pic_scaling_matrix_present_flag, pps->scaling_matrix4, pps->scaling_matrix8); if (ret < 0) goto fail; diff --git a/libavcodec/h264_ps.h b/libavcodec/h264_ps.h index c3f0888f245..d2413ae0f8c 100644 --- a/libavcodec/h264_ps.h +++ b/libavcodec/h264_ps.h @@ -119,6 +119,7 @@ typedef struct PPS { int constrained_intra_pred; ///< constrained_intra_pred_flag int redundant_pic_cnt_present; ///< redundant_pic_cnt_present_flag int transform_8x8_mode; ///< transform_8x8_mode_flag + int pic_scaling_matrix_present_flag; uint8_t scaling_matrix4[6][16]; uint8_t scaling_matrix8[6][64]; uint8_t chroma_qp_table[2][QP_MAX_NUM+1]; ///< pre-scaled (with chroma_qp_index_offset) version of qp_table From 1f66e3347dae2e42a723986b988b704e419c3378 Mon Sep 17 00:00:00 2001 From: Lynne Date: Wed, 23 Nov 2022 15:59:23 +0100 Subject: [PATCH 1217/2172] h264_ps: comment pic_order_present better The official name which CBS uses is bottom_field_pic_order_in_frame_present_flag. --- libavcodec/h264_ps.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavcodec/h264_ps.h b/libavcodec/h264_ps.h index d2413ae0f8c..de4529b3534 100644 --- a/libavcodec/h264_ps.h +++ b/libavcodec/h264_ps.h @@ -106,7 +106,7 @@ typedef struct PPS { unsigned int pps_id; unsigned int sps_id; int cabac; ///< entropy_coding_mode_flag - int pic_order_present; ///< pic_order_present_flag + int pic_order_present; ///< bottom_field_pic_order_in_frame_present_flag int slice_group_count; ///< num_slice_groups_minus1 + 1 int mb_slice_group_map_type; unsigned int ref_count[2]; ///< num_ref_idx_l0/1_active_minus1 + 1 From de6fce727cb8e9e4998a8ed1f13f03c88a0a6a4d Mon Sep 17 00:00:00 2001 From: Lynne Date: Wed, 14 Dec 2022 00:06:04 +0100 Subject: [PATCH 1218/2172] h264_ps: expose max_dec_frame_buffering --- libavcodec/h264_ps.c | 2 +- libavcodec/h264_ps.h | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/libavcodec/h264_ps.c b/libavcodec/h264_ps.c index a94f5350c45..d9df5707185 100644 --- a/libavcodec/h264_ps.c +++ b/libavcodec/h264_ps.c @@ -176,7 +176,7 @@ static inline int decode_vui_parameters(GetBitContext *gb, void *logctx, get_ue_golomb_31(gb); /* log2_max_mv_length_horizontal */ get_ue_golomb_31(gb); /* log2_max_mv_length_vertical */ sps->num_reorder_frames = get_ue_golomb_31(gb); - get_ue_golomb_31(gb); /*max_dec_frame_buffering*/ + sps->max_dec_frame_buffering = get_ue_golomb_31(gb); if (get_bits_left(gb) < 0) { sps->num_reorder_frames = 0; diff --git a/libavcodec/h264_ps.h b/libavcodec/h264_ps.h index de4529b3534..906bab72140 100644 --- a/libavcodec/h264_ps.h +++ b/libavcodec/h264_ps.h @@ -80,6 +80,7 @@ typedef struct SPS { int32_t offset_for_ref_frame[256]; int bitstream_restriction_flag; int num_reorder_frames; + int max_dec_frame_buffering; int scaling_matrix_present; uint8_t scaling_matrix4[6][16]; uint8_t scaling_matrix8[6][64]; From d13b1c42f6a0fb835ad1f2b7db3397cd72e30db7 Mon Sep 17 00:00:00 2001 From: Lynne Date: Wed, 14 Dec 2022 00:09:08 +0100 Subject: [PATCH 1219/2172] h264_ps: expose bit rate and CPB size fields --- libavcodec/h264_ps.c | 9 +++++---- libavcodec/h264_ps.h | 4 ++++ 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/libavcodec/h264_ps.c b/libavcodec/h264_ps.c index d9df5707185..c71330089d7 100644 --- a/libavcodec/h264_ps.c +++ b/libavcodec/h264_ps.c @@ -113,12 +113,13 @@ static inline int decode_hrd_parameters(GetBitContext *gb, void *logctx, return AVERROR_INVALIDDATA; } - get_bits(gb, 4); /* bit_rate_scale */ + sps->cpr_flag = 0x0; + sps->bit_rate_scale = get_bits(gb, 4); get_bits(gb, 4); /* cpb_size_scale */ for (i = 0; i < cpb_count; i++) { - get_ue_golomb_long(gb); /* bit_rate_value_minus1 */ - get_ue_golomb_long(gb); /* cpb_size_value_minus1 */ - get_bits1(gb); /* cbr_flag */ + sps->bit_rate_value[i] = get_ue_golomb_long(gb) + 1; /* bit_rate_value_minus1 + 1 */ + sps->cpb_size_value[i] = get_ue_golomb_long(gb) + 1; /* cpb_size_value_minus1 + 1 */ + sps->cpr_flag |= get_bits1(gb) << i; } sps->initial_cpb_removal_delay_length = get_bits(gb, 5) + 1; sps->cpb_removal_delay_length = get_bits(gb, 5) + 1; diff --git a/libavcodec/h264_ps.h b/libavcodec/h264_ps.h index 906bab72140..8adfbd710f3 100644 --- a/libavcodec/h264_ps.h +++ b/libavcodec/h264_ps.h @@ -89,6 +89,10 @@ typedef struct SPS { int pic_struct_present_flag; int time_offset_length; int cpb_cnt; ///< See H.264 E.1.2 + int bit_rate_scale; + uint32_t bit_rate_value[32]; ///< bit_rate_value_minus1 + 1 + uint32_t cpb_size_value[32]; ///< cpb_size_value_minus1 + 1 + uint32_t cpr_flag; int initial_cpb_removal_delay_length; ///< initial_cpb_removal_delay_length_minus1 + 1 int cpb_removal_delay_length; ///< cpb_removal_delay_length_minus1 + 1 int dpb_output_delay_length; ///< dpb_output_delay_length_minus1 + 1 From 20de09a6de79da0adc7b539e205878c34913b323 Mon Sep 17 00:00:00 2001 From: Lynne Date: Thu, 15 Dec 2022 17:05:35 +0100 Subject: [PATCH 1220/2172] h264_ps: expose scaling_matrix_present_mask Vulkan requires it. It technically also requires use_default_scaling_matrix_mask, but we can just be explicit and give it the matrix we fill in as-non default. --- libavcodec/h264_ps.c | 37 +++++++++++++++++++++---------------- libavcodec/h264_ps.h | 2 ++ 2 files changed, 23 insertions(+), 16 deletions(-) diff --git a/libavcodec/h264_ps.c b/libavcodec/h264_ps.c index c71330089d7..53446e9aabe 100644 --- a/libavcodec/h264_ps.c +++ b/libavcodec/h264_ps.c @@ -198,12 +198,14 @@ static inline int decode_vui_parameters(GetBitContext *gb, void *logctx, } static int decode_scaling_list(GetBitContext *gb, uint8_t *factors, int size, - const uint8_t *jvt_list, - const uint8_t *fallback_list) + const uint8_t *jvt_list, const uint8_t *fallback_list, + uint16_t *mask, int pos) { int i, last = 8, next = 8; const uint8_t *scan = size == 16 ? ff_zigzag_scan : ff_zigzag_direct; - if (!get_bits1(gb)) /* matrix not written, we use the predicted one */ + uint16_t seq_scaling_list_present_flag = get_bits1(gb); + *mask |= (seq_scaling_list_present_flag << pos); + if (!seq_scaling_list_present_flag) /* matrix not written, we use the predicted one */ memcpy(factors, fallback_list, size * sizeof(uint8_t)); else for (i = 0; i < size; i++) { @@ -227,7 +229,7 @@ static int decode_scaling_list(GetBitContext *gb, uint8_t *factors, int size, /* returns non zero if the provided SPS scaling matrix has been filled */ static int decode_scaling_matrices(GetBitContext *gb, const SPS *sps, const PPS *pps, int is_sps, - int present_flag, + int present_flag, uint16_t *mask, uint8_t(*scaling_matrix4)[16], uint8_t(*scaling_matrix8)[64]) { @@ -239,21 +241,22 @@ static int decode_scaling_matrices(GetBitContext *gb, const SPS *sps, fallback_sps ? sps->scaling_matrix8[3] : default_scaling8[1] }; int ret = 0; + *mask = 0x0; if (present_flag) { - ret |= decode_scaling_list(gb, scaling_matrix4[0], 16, default_scaling4[0], fallback[0]); // Intra, Y - ret |= decode_scaling_list(gb, scaling_matrix4[1], 16, default_scaling4[0], scaling_matrix4[0]); // Intra, Cr - ret |= decode_scaling_list(gb, scaling_matrix4[2], 16, default_scaling4[0], scaling_matrix4[1]); // Intra, Cb - ret |= decode_scaling_list(gb, scaling_matrix4[3], 16, default_scaling4[1], fallback[1]); // Inter, Y - ret |= decode_scaling_list(gb, scaling_matrix4[4], 16, default_scaling4[1], scaling_matrix4[3]); // Inter, Cr - ret |= decode_scaling_list(gb, scaling_matrix4[5], 16, default_scaling4[1], scaling_matrix4[4]); // Inter, Cb + ret |= decode_scaling_list(gb, scaling_matrix4[0], 16, default_scaling4[0], fallback[0], mask, 0); // Intra, Y + ret |= decode_scaling_list(gb, scaling_matrix4[1], 16, default_scaling4[0], scaling_matrix4[0], mask, 1); // Intra, Cr + ret |= decode_scaling_list(gb, scaling_matrix4[2], 16, default_scaling4[0], scaling_matrix4[1], mask, 2); // Intra, Cb + ret |= decode_scaling_list(gb, scaling_matrix4[3], 16, default_scaling4[1], fallback[1], mask, 3); // Inter, Y + ret |= decode_scaling_list(gb, scaling_matrix4[4], 16, default_scaling4[1], scaling_matrix4[3], mask, 4); // Inter, Cr + ret |= decode_scaling_list(gb, scaling_matrix4[5], 16, default_scaling4[1], scaling_matrix4[4], mask, 5); // Inter, Cb if (is_sps || pps->transform_8x8_mode) { - ret |= decode_scaling_list(gb, scaling_matrix8[0], 64, default_scaling8[0], fallback[2]); // Intra, Y - ret |= decode_scaling_list(gb, scaling_matrix8[3], 64, default_scaling8[1], fallback[3]); // Inter, Y + ret |= decode_scaling_list(gb, scaling_matrix8[0], 64, default_scaling8[0], fallback[2], mask, 6); // Intra, Y + ret |= decode_scaling_list(gb, scaling_matrix8[3], 64, default_scaling8[1], fallback[3], mask, 7); // Inter, Y if (sps->chroma_format_idc == 3) { - ret |= decode_scaling_list(gb, scaling_matrix8[1], 64, default_scaling8[0], scaling_matrix8[0]); // Intra, Cr - ret |= decode_scaling_list(gb, scaling_matrix8[4], 64, default_scaling8[1], scaling_matrix8[3]); // Inter, Cr - ret |= decode_scaling_list(gb, scaling_matrix8[2], 64, default_scaling8[0], scaling_matrix8[1]); // Intra, Cb - ret |= decode_scaling_list(gb, scaling_matrix8[5], 64, default_scaling8[1], scaling_matrix8[4]); // Inter, Cb + ret |= decode_scaling_list(gb, scaling_matrix8[1], 64, default_scaling8[0], scaling_matrix8[0], mask, 8); // Intra, Cr + ret |= decode_scaling_list(gb, scaling_matrix8[4], 64, default_scaling8[1], scaling_matrix8[3], mask, 9); // Inter, Cr + ret |= decode_scaling_list(gb, scaling_matrix8[2], 64, default_scaling8[0], scaling_matrix8[1], mask, 10); // Intra, Cb + ret |= decode_scaling_list(gb, scaling_matrix8[5], 64, default_scaling8[1], scaling_matrix8[4], mask, 11); // Inter, Cb } } if (!ret) @@ -371,6 +374,7 @@ int ff_h264_decode_seq_parameter_set(GetBitContext *gb, AVCodecContext *avctx, } sps->transform_bypass = get_bits1(gb); ret = decode_scaling_matrices(gb, sps, NULL, 1, get_bits1(gb), + &sps->scaling_matrix_present_mask, sps->scaling_matrix4, sps->scaling_matrix8); if (ret < 0) goto fail; @@ -808,6 +812,7 @@ int ff_h264_decode_picture_parameter_set(GetBitContext *gb, AVCodecContext *avct pps->pic_scaling_matrix_present_flag = get_bits1(gb); ret = decode_scaling_matrices(gb, sps, pps, 0, pps->pic_scaling_matrix_present_flag, + &pps->pic_scaling_matrix_present_mask, pps->scaling_matrix4, pps->scaling_matrix8); if (ret < 0) goto fail; diff --git a/libavcodec/h264_ps.h b/libavcodec/h264_ps.h index 8adfbd710f3..e6756196352 100644 --- a/libavcodec/h264_ps.h +++ b/libavcodec/h264_ps.h @@ -82,6 +82,7 @@ typedef struct SPS { int num_reorder_frames; int max_dec_frame_buffering; int scaling_matrix_present; + uint16_t scaling_matrix_present_mask; uint8_t scaling_matrix4[6][16]; uint8_t scaling_matrix8[6][64]; int nal_hrd_parameters_present_flag; @@ -125,6 +126,7 @@ typedef struct PPS { int redundant_pic_cnt_present; ///< redundant_pic_cnt_present_flag int transform_8x8_mode; ///< transform_8x8_mode_flag int pic_scaling_matrix_present_flag; + uint16_t pic_scaling_matrix_present_mask; uint8_t scaling_matrix4[6][16]; uint8_t scaling_matrix8[6][64]; uint8_t chroma_qp_table[2][QP_MAX_NUM+1]; ///< pre-scaled (with chroma_qp_index_offset) version of qp_table From fc429d785e9e24c5520ce716d4bc3b5547e581eb Mon Sep 17 00:00:00 2001 From: Lynne Date: Wed, 7 Dec 2022 01:29:57 +0100 Subject: [PATCH 1221/2172] hevc_ps: expose SPS and VPS headers --- libavcodec/hevc_ps.c | 100 ++++++++++++++++++++++--------------------- libavcodec/hevc_ps.h | 41 ++++++++++++++++++ 2 files changed, 93 insertions(+), 48 deletions(-) diff --git a/libavcodec/hevc_ps.c b/libavcodec/hevc_ps.c index 043e1bf3085..aaaca5e6c72 100644 --- a/libavcodec/hevc_ps.c +++ b/libavcodec/hevc_ps.c @@ -357,81 +357,84 @@ static int parse_ptl(GetBitContext *gb, AVCodecContext *avctx, } static void decode_sublayer_hrd(GetBitContext *gb, unsigned int nb_cpb, - int subpic_params_present) + HEVCSublayerHdrParams *par, int subpic_params_present) { int i; for (i = 0; i < nb_cpb; i++) { - get_ue_golomb_long(gb); // bit_rate_value_minus1 - get_ue_golomb_long(gb); // cpb_size_value_minus1 + par->bit_rate_value_minus1[i] = get_ue_golomb_long(gb); + par->cpb_size_value_minus1[i] = get_ue_golomb_long(gb); if (subpic_params_present) { - get_ue_golomb_long(gb); // cpb_size_du_value_minus1 - get_ue_golomb_long(gb); // bit_rate_du_value_minus1 + par->cpb_size_du_value_minus1[i] = get_ue_golomb_long(gb); + par->bit_rate_du_value_minus1[i] = get_ue_golomb_long(gb); } - skip_bits1(gb); // cbr_flag + + par->cbr_flag = get_bits1(gb); } } static int decode_hrd(GetBitContext *gb, int common_inf_present, - int max_sublayers) + HEVCHdrParams *hdr, int max_sublayers) { - int nal_params_present = 0, vcl_params_present = 0; - int subpic_params_present = 0; - int i; - if (common_inf_present) { - nal_params_present = get_bits1(gb); - vcl_params_present = get_bits1(gb); - - if (nal_params_present || vcl_params_present) { - subpic_params_present = get_bits1(gb); - - if (subpic_params_present) { - skip_bits(gb, 8); // tick_divisor_minus2 - skip_bits(gb, 5); // du_cpb_removal_delay_increment_length_minus1 - skip_bits(gb, 1); // sub_pic_cpb_params_in_pic_timing_sei_flag - skip_bits(gb, 5); // dpb_output_delay_du_length_minus1 + hdr->flags.nal_hrd_parameters_present_flag = get_bits1(gb); + hdr->flags.vcl_hrd_parameters_present_flag = get_bits1(gb); + + if (hdr->flags.nal_hrd_parameters_present_flag || + hdr->flags.vcl_hrd_parameters_present_flag) { + hdr->flags.sub_pic_hrd_params_present_flag = get_bits1(gb); + + if (hdr->flags.sub_pic_hrd_params_present_flag) { + hdr->tick_divisor_minus2 = get_bits(gb, 8); + hdr->du_cpb_removal_delay_increment_length_minus1 = get_bits(gb, 5); + hdr->flags.sub_pic_cpb_params_in_pic_timing_sei_flag = get_bits1(gb); + hdr->dpb_output_delay_du_length_minus1 = get_bits(gb, 5); } - skip_bits(gb, 4); // bit_rate_scale - skip_bits(gb, 4); // cpb_size_scale + hdr->bit_rate_scale = get_bits(gb, 4); + hdr->cpb_size_scale = get_bits(gb, 4); - if (subpic_params_present) - skip_bits(gb, 4); // cpb_size_du_scale + if (hdr->flags.sub_pic_hrd_params_present_flag) + hdr->cpb_size_du_scale = get_bits(gb, 4); - skip_bits(gb, 5); // initial_cpb_removal_delay_length_minus1 - skip_bits(gb, 5); // au_cpb_removal_delay_length_minus1 - skip_bits(gb, 5); // dpb_output_delay_length_minus1 + hdr->initial_cpb_removal_delay_length_minus1 = get_bits(gb, 5); + hdr->au_cpb_removal_delay_length_minus1 = get_bits(gb, 5); + hdr->dpb_output_delay_length_minus1 = get_bits(gb, 5); } } - for (i = 0; i < max_sublayers; i++) { - int low_delay = 0; - unsigned int nb_cpb = 1; - int fixed_rate = get_bits1(gb); + for (int i = 0; i < max_sublayers; i++) { + hdr->flags.fixed_pic_rate_general_flag = get_bits1(gb); + + hdr->cpb_cnt_minus1[i] = 1; - if (!fixed_rate) - fixed_rate = get_bits1(gb); + if (!hdr->flags.fixed_pic_rate_general_flag) + hdr->flags.fixed_pic_rate_within_cvs_flag = get_bits1(gb); - if (fixed_rate) - get_ue_golomb_long(gb); // elemental_duration_in_tc_minus1 + if (hdr->flags.fixed_pic_rate_within_cvs_flag) + hdr->elemental_duration_in_tc_minus1[i] = get_ue_golomb_long(gb); else - low_delay = get_bits1(gb); + hdr->flags.low_delay_hrd_flag = get_bits1(gb); - if (!low_delay) { - nb_cpb = get_ue_golomb_long(gb) + 1; - if (nb_cpb < 1 || nb_cpb > 32) { - av_log(NULL, AV_LOG_ERROR, "nb_cpb %d invalid\n", nb_cpb); + if (!hdr->flags.low_delay_hrd_flag) { + hdr->cpb_cnt_minus1[i] = get_ue_golomb_long(gb); + if (hdr->cpb_cnt_minus1[i] > 31) { + av_log(NULL, AV_LOG_ERROR, "nb_cpb %d invalid\n", + hdr->cpb_cnt_minus1[i]); return AVERROR_INVALIDDATA; } } - if (nal_params_present) - decode_sublayer_hrd(gb, nb_cpb, subpic_params_present); - if (vcl_params_present) - decode_sublayer_hrd(gb, nb_cpb, subpic_params_present); + if (hdr->flags.nal_hrd_parameters_present_flag) + decode_sublayer_hrd(gb, hdr->cpb_cnt_minus1[i], &hdr->nal_params[i], + hdr->flags.sub_pic_hrd_params_present_flag); + + if (hdr->flags.vcl_hrd_parameters_present_flag) + decode_sublayer_hrd(gb, hdr->cpb_cnt_minus1[i], &hdr->vcl_params[i], + hdr->flags.sub_pic_hrd_params_present_flag); } + return 0; } @@ -538,7 +541,8 @@ int ff_hevc_decode_nal_vps(GetBitContext *gb, AVCodecContext *avctx, get_ue_golomb_long(gb); // hrd_layer_set_idx if (i) common_inf_present = get_bits1(gb); - decode_hrd(gb, common_inf_present, vps->vps_max_sub_layers); + decode_hrd(gb, common_inf_present, &vps->hdr[i], + vps->vps_max_sub_layers); } } get_bits1(gb); /* vps_extension_flag */ @@ -657,7 +661,7 @@ static void decode_vui(GetBitContext *gb, AVCodecContext *avctx, vui->vui_num_ticks_poc_diff_one_minus1 = get_ue_golomb_long(gb); vui->vui_hrd_parameters_present_flag = get_bits1(gb); if (vui->vui_hrd_parameters_present_flag) - decode_hrd(gb, 1, sps->max_sub_layers); + decode_hrd(gb, 1, &sps->hdr, sps->max_sub_layers); } vui->bitstream_restriction_flag = get_bits1(gb); diff --git a/libavcodec/hevc_ps.h b/libavcodec/hevc_ps.h index 2124deb953d..0124f5d37f5 100644 --- a/libavcodec/hevc_ps.h +++ b/libavcodec/hevc_ps.h @@ -32,6 +32,43 @@ #include "h2645_vui.h" #include "hevc.h" +typedef struct HEVCSublayerHdrParams { + uint32_t bit_rate_value_minus1[HEVC_MAX_CPB_CNT]; + uint32_t cpb_size_value_minus1[HEVC_MAX_CPB_CNT]; + uint32_t cpb_size_du_value_minus1[HEVC_MAX_CPB_CNT]; + uint32_t bit_rate_du_value_minus1[HEVC_MAX_CPB_CNT]; + uint32_t cbr_flag; +} HEVCSublayerHdrParams; + +typedef struct HEVCHdrFlagParams { + uint32_t nal_hrd_parameters_present_flag; + uint32_t vcl_hrd_parameters_present_flag; + uint32_t sub_pic_hrd_params_present_flag; + uint32_t sub_pic_cpb_params_in_pic_timing_sei_flag; + uint32_t fixed_pic_rate_general_flag; + uint32_t fixed_pic_rate_within_cvs_flag; + uint32_t low_delay_hrd_flag; +} HEVCHdrFlagParams; + +typedef struct HEVCHdrParams { + HEVCHdrFlagParams flags; + + uint8_t tick_divisor_minus2; + uint8_t du_cpb_removal_delay_increment_length_minus1; + uint8_t dpb_output_delay_du_length_minus1; + uint8_t bit_rate_scale; + uint8_t cpb_size_scale; + uint8_t cpb_size_du_scale; + uint8_t initial_cpb_removal_delay_length_minus1; + uint8_t au_cpb_removal_delay_length_minus1; + uint8_t dpb_output_delay_length_minus1; + uint8_t cpb_cnt_minus1[HEVC_MAX_SUB_LAYERS]; + uint16_t elemental_duration_in_tc_minus1[HEVC_MAX_SUB_LAYERS]; + + HEVCSublayerHdrParams nal_params[HEVC_MAX_SUB_LAYERS]; + HEVCSublayerHdrParams vcl_params[HEVC_MAX_SUB_LAYERS]; +} HEVCHdrParams; + typedef struct ShortTermRPS { unsigned int num_negative_pics; int num_delta_pocs; @@ -108,6 +145,8 @@ typedef struct PTL { } PTL; typedef struct HEVCVPS { + HEVCHdrParams hdr[HEVC_MAX_LAYER_SETS]; + uint8_t vps_temporal_id_nesting_flag; int vps_max_layers; int vps_max_sub_layers; ///< vps_max_temporal_layers_minus1 + 1 @@ -146,6 +185,8 @@ typedef struct HEVCSPS { HEVCWindow pic_conf_win; + HEVCHdrParams hdr; + int bit_depth; int bit_depth_chroma; int pixel_shift; From 3bc866159ce105ab1ec35b702d92fda26fefe7df Mon Sep 17 00:00:00 2001 From: Lynne Date: Wed, 7 Dec 2022 05:33:29 +0100 Subject: [PATCH 1222/2172] hevc_ps: expose pps_id --- libavcodec/hevc_ps.c | 2 +- libavcodec/hevc_ps.h | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/libavcodec/hevc_ps.c b/libavcodec/hevc_ps.c index aaaca5e6c72..73f90b48311 100644 --- a/libavcodec/hevc_ps.c +++ b/libavcodec/hevc_ps.c @@ -1776,7 +1776,7 @@ int ff_hevc_decode_nal_pps(GetBitContext *gb, AVCodecContext *avctx, pps->log2_max_transform_skip_block_size = 2; // Coded parameters - pps_id = get_ue_golomb_long(gb); + pps_id = pps->pps_id = get_ue_golomb_long(gb); if (pps_id >= HEVC_MAX_PPS_COUNT) { av_log(avctx, AV_LOG_ERROR, "PPS id out of range: %d\n", pps_id); ret = AVERROR_INVALIDDATA; diff --git a/libavcodec/hevc_ps.h b/libavcodec/hevc_ps.h index 0124f5d37f5..e461b48943d 100644 --- a/libavcodec/hevc_ps.h +++ b/libavcodec/hevc_ps.h @@ -289,6 +289,7 @@ typedef struct HEVCSPS { } HEVCSPS; typedef struct HEVCPPS { + unsigned int pps_id; unsigned int sps_id; ///< seq_parameter_set_id uint8_t sign_data_hiding_flag; From d0b02c3affad7eba83f0eba91310e2216cf02e2b Mon Sep 17 00:00:00 2001 From: Lynne Date: Wed, 7 Dec 2022 06:42:44 +0100 Subject: [PATCH 1223/2172] hevc_ps: expose vps_id --- libavcodec/hevc_ps.c | 2 +- libavcodec/hevc_ps.h | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/libavcodec/hevc_ps.c b/libavcodec/hevc_ps.c index 73f90b48311..581c9293ab1 100644 --- a/libavcodec/hevc_ps.c +++ b/libavcodec/hevc_ps.c @@ -464,7 +464,7 @@ int ff_hevc_decode_nal_vps(GetBitContext *gb, AVCodecContext *avctx, } memcpy(vps->data, gb->buffer, vps->data_size); - vps_id = get_bits(gb, 4); + vps_id = vps->vps_id = get_bits(gb, 4); if (get_bits(gb, 2) != 3) { // vps_reserved_three_2bits av_log(avctx, AV_LOG_ERROR, "vps_reserved_three_2bits is not three\n"); diff --git a/libavcodec/hevc_ps.h b/libavcodec/hevc_ps.h index e461b48943d..eb9e6beac1e 100644 --- a/libavcodec/hevc_ps.h +++ b/libavcodec/hevc_ps.h @@ -145,6 +145,7 @@ typedef struct PTL { } PTL; typedef struct HEVCVPS { + unsigned int vps_id; HEVCHdrParams hdr[HEVC_MAX_LAYER_SETS]; uint8_t vps_temporal_id_nesting_flag; From 4e1f3ab1849616a52131a875cb772aef8312758f Mon Sep 17 00:00:00 2001 From: Lynne Date: Wed, 7 Dec 2022 12:49:45 +0100 Subject: [PATCH 1224/2172] hevc_ps: expose pps_extension_present_flag --- libavcodec/hevc_ps.c | 3 ++- libavcodec/hevc_ps.h | 1 + 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/libavcodec/hevc_ps.c b/libavcodec/hevc_ps.c index 581c9293ab1..61f4f7c1fca 100644 --- a/libavcodec/hevc_ps.c +++ b/libavcodec/hevc_ps.c @@ -1956,7 +1956,8 @@ int ff_hevc_decode_nal_pps(GetBitContext *gb, AVCodecContext *avctx, pps->slice_header_extension_present_flag = get_bits1(gb); - if (get_bits1(gb)) { // pps_extension_present_flag + pps->pps_extension_present_flag = get_bits1(gb); + if (pps->pps_extension_present_flag) { pps->pps_range_extensions_flag = get_bits1(gb); pps->pps_multilayer_extension_flag = get_bits1(gb); pps->pps_3d_extension_flag = get_bits1(gb); diff --git a/libavcodec/hevc_ps.h b/libavcodec/hevc_ps.h index eb9e6beac1e..e78018c3391 100644 --- a/libavcodec/hevc_ps.h +++ b/libavcodec/hevc_ps.h @@ -340,6 +340,7 @@ typedef struct HEVCPPS { int num_extra_slice_header_bits; uint8_t slice_header_extension_present_flag; uint8_t log2_max_transform_skip_block_size; + uint8_t pps_extension_present_flag; uint8_t pps_range_extensions_flag; uint8_t pps_multilayer_extension_flag; uint8_t pps_3d_extension_flag; From 6eaca2abd8635bc6cc0dabfc63bee8428097b991 Mon Sep 17 00:00:00 2001 From: Lynne Date: Wed, 7 Dec 2022 17:11:36 +0100 Subject: [PATCH 1225/2172] hevcdec: expose bits_used_for_short_term_rps --- libavcodec/hevcdec.c | 1 + libavcodec/hevcdec.h | 1 + 2 files changed, 2 insertions(+) diff --git a/libavcodec/hevcdec.c b/libavcodec/hevcdec.c index 7e1bf4e9157..b01563177b8 100644 --- a/libavcodec/hevcdec.c +++ b/libavcodec/hevcdec.c @@ -703,6 +703,7 @@ static int hls_slice_header(HEVCContext *s) if (ret < 0) return ret; + sh->bits_used_for_short_term_rps = pos - get_bits_left(gb); sh->short_term_rps = &sh->slice_rps; } else { int numbits, rps_idx; diff --git a/libavcodec/hevcdec.h b/libavcodec/hevcdec.h index 94609e46993..04ec25d540b 100644 --- a/libavcodec/hevcdec.h +++ b/libavcodec/hevcdec.h @@ -268,6 +268,7 @@ typedef struct SliceHeader { ///< RPS coded in the slice header itself is stored here int short_term_ref_pic_set_sps_flag; + int bits_used_for_short_term_rps; int short_term_ref_pic_set_size; ShortTermRPS slice_rps; const ShortTermRPS *short_term_rps; From abdd87d44ebafb1ee39bee183bc4fdaaa88238d3 Mon Sep 17 00:00:00 2001 From: Lynne Date: Wed, 7 Dec 2022 04:30:46 +0100 Subject: [PATCH 1226/2172] hevc_ps: expose log2_diff_max_min_transform_block_size --- libavcodec/hevc_ps.c | 20 ++++++++++---------- libavcodec/hevc_ps.h | 1 + 2 files changed, 11 insertions(+), 10 deletions(-) diff --git a/libavcodec/hevc_ps.c b/libavcodec/hevc_ps.c index 61f4f7c1fca..5b5cd9d9807 100644 --- a/libavcodec/hevc_ps.c +++ b/libavcodec/hevc_ps.c @@ -856,9 +856,8 @@ int ff_hevc_parse_sps(HEVCSPS *sps, GetBitContext *gb, unsigned int *sps_id, { HEVCWindow *ow; int ret = 0; - int log2_diff_max_min_transform_block_size; int bit_depth_chroma, start, vui_present, sublayer_ordering_info, num_comps; - int i; + int i, j; // Coded parameters @@ -993,12 +992,12 @@ int ff_hevc_parse_sps(HEVCSPS *sps, GetBitContext *gb, unsigned int *sps_id, } } - sps->log2_min_cb_size = get_ue_golomb_long(gb) + 3; - sps->log2_diff_max_min_coding_block_size = get_ue_golomb_long(gb); - sps->log2_min_tb_size = get_ue_golomb_long(gb) + 2; - log2_diff_max_min_transform_block_size = get_ue_golomb_long(gb); - sps->log2_max_trafo_size = log2_diff_max_min_transform_block_size + - sps->log2_min_tb_size; + sps->log2_min_cb_size = get_ue_golomb_long(gb) + 3; + sps->log2_diff_max_min_coding_block_size = get_ue_golomb_long(gb); + sps->log2_min_tb_size = get_ue_golomb_long(gb) + 2; + sps->log2_diff_max_min_transform_block_size = get_ue_golomb_long(gb); + sps->log2_max_trafo_size = sps->log2_diff_max_min_transform_block_size + + sps->log2_min_tb_size; if (sps->log2_min_cb_size < 3 || sps->log2_min_cb_size > 30) { av_log(avctx, AV_LOG_ERROR, "Invalid value %d for log2_min_cb_size", sps->log2_min_cb_size); @@ -1015,8 +1014,9 @@ int ff_hevc_parse_sps(HEVCSPS *sps, GetBitContext *gb, unsigned int *sps_id, return AVERROR_INVALIDDATA; } - if (log2_diff_max_min_transform_block_size < 0 || log2_diff_max_min_transform_block_size > 30) { - av_log(avctx, AV_LOG_ERROR, "Invalid value %d for log2_diff_max_min_transform_block_size", log2_diff_max_min_transform_block_size); + if (sps->log2_diff_max_min_transform_block_size > 30) { + av_log(avctx, AV_LOG_ERROR, "Invalid value %d for log2_diff_max_min_transform_block_size", + sps->log2_diff_max_min_transform_block_size); return AVERROR_INVALIDDATA; } diff --git a/libavcodec/hevc_ps.h b/libavcodec/hevc_ps.h index e78018c3391..344c5bbc7fa 100644 --- a/libavcodec/hevc_ps.h +++ b/libavcodec/hevc_ps.h @@ -237,6 +237,7 @@ typedef struct HEVCSPS { unsigned int log2_max_trafo_size; unsigned int log2_ctb_size; unsigned int log2_min_pu_size; + unsigned int log2_diff_max_min_transform_block_size; int max_transform_hierarchy_depth_inter; int max_transform_hierarchy_depth_intra; From f58db8e534b38e4a3b776ceb465d6915af641068 Mon Sep 17 00:00:00 2001 From: Lynne Date: Wed, 14 Dec 2022 00:25:48 +0100 Subject: [PATCH 1227/2172] hevc_ps: expose rps fields --- libavcodec/hevc_ps.c | 37 ++++++++++++++++++------------------- libavcodec/hevc_ps.h | 7 +++++++ 2 files changed, 25 insertions(+), 19 deletions(-) diff --git a/libavcodec/hevc_ps.c b/libavcodec/hevc_ps.c index 5b5cd9d9807..7181398e90b 100644 --- a/libavcodec/hevc_ps.c +++ b/libavcodec/hevc_ps.c @@ -100,51 +100,50 @@ static void remove_vps(HEVCParamSets *s, int id) int ff_hevc_decode_short_term_rps(GetBitContext *gb, AVCodecContext *avctx, ShortTermRPS *rps, const HEVCSPS *sps, int is_slice_header) { - uint8_t rps_predict = 0; int delta_poc; int k0 = 0; int k = 0; int i; + rps->rps_predict = 0; + if (rps != sps->st_rps && sps->nb_st_rps) - rps_predict = get_bits1(gb); + rps->rps_predict = get_bits1(gb); - if (rps_predict) { + if (rps->rps_predict) { const ShortTermRPS *rps_ridx; int delta_rps; - unsigned abs_delta_rps; - uint8_t use_delta_flag = 0; - uint8_t delta_rps_sign; if (is_slice_header) { - unsigned int delta_idx = get_ue_golomb_long(gb) + 1; - if (delta_idx > sps->nb_st_rps) { + rps->delta_idx = get_ue_golomb_long(gb) + 1; + if (rps->delta_idx > sps->nb_st_rps) { av_log(avctx, AV_LOG_ERROR, "Invalid value of delta_idx in slice header RPS: %d > %d.\n", - delta_idx, sps->nb_st_rps); + rps->delta_idx, sps->nb_st_rps); return AVERROR_INVALIDDATA; } - rps_ridx = &sps->st_rps[sps->nb_st_rps - delta_idx]; + rps_ridx = &sps->st_rps[sps->nb_st_rps - rps->delta_idx]; rps->rps_idx_num_delta_pocs = rps_ridx->num_delta_pocs; } else rps_ridx = &sps->st_rps[rps - sps->st_rps - 1]; - delta_rps_sign = get_bits1(gb); - abs_delta_rps = get_ue_golomb_long(gb) + 1; - if (abs_delta_rps < 1 || abs_delta_rps > 32768) { + rps->delta_rps_sign = get_bits1(gb); + rps->abs_delta_rps = get_ue_golomb_long(gb) + 1; + if (rps->abs_delta_rps > 32768) { av_log(avctx, AV_LOG_ERROR, "Invalid value of abs_delta_rps: %d\n", - abs_delta_rps); + rps->abs_delta_rps); return AVERROR_INVALIDDATA; } - delta_rps = (1 - (delta_rps_sign << 1)) * abs_delta_rps; + delta_rps = (1 - (rps->delta_rps_sign << 1)) * rps->abs_delta_rps; for (i = 0; i <= rps_ridx->num_delta_pocs; i++) { int used = rps->used[k] = get_bits1(gb); + rps->use_delta_flag = 0; if (!used) - use_delta_flag = get_bits1(gb); + rps->use_delta_flag = get_bits1(gb); - if (used || use_delta_flag) { + if (used || rps->use_delta_flag) { if (i < rps_ridx->num_delta_pocs) delta_poc = delta_rps + rps_ridx->delta_poc[i]; else @@ -210,7 +209,7 @@ int ff_hevc_decode_short_term_rps(GetBitContext *gb, AVCodecContext *avctx, if (rps->num_delta_pocs) { prev = 0; for (i = 0; i < rps->num_negative_pics; i++) { - delta_poc = get_ue_golomb_long(gb) + 1; + delta_poc = rps->delta_poc_s0[i] = get_ue_golomb_long(gb) + 1; if (delta_poc < 1 || delta_poc > 32768) { av_log(avctx, AV_LOG_ERROR, "Invalid value of delta_poc: %d\n", @@ -223,7 +222,7 @@ int ff_hevc_decode_short_term_rps(GetBitContext *gb, AVCodecContext *avctx, } prev = 0; for (i = 0; i < nb_positive_pics; i++) { - delta_poc = get_ue_golomb_long(gb) + 1; + delta_poc = rps->delta_poc_s1[i] = get_ue_golomb_long(gb) + 1; if (delta_poc < 1 || delta_poc > 32768) { av_log(avctx, AV_LOG_ERROR, "Invalid value of delta_poc: %d\n", diff --git a/libavcodec/hevc_ps.h b/libavcodec/hevc_ps.h index 344c5bbc7fa..2b89cdc9fd6 100644 --- a/libavcodec/hevc_ps.h +++ b/libavcodec/hevc_ps.h @@ -70,9 +70,16 @@ typedef struct HEVCHdrParams { } HEVCHdrParams; typedef struct ShortTermRPS { + uint8_t rps_predict; + unsigned int delta_idx; + uint8_t use_delta_flag; + uint8_t delta_rps_sign; + unsigned int abs_delta_rps; unsigned int num_negative_pics; int num_delta_pocs; int rps_idx_num_delta_pocs; + int32_t delta_poc_s0[32]; + int32_t delta_poc_s1[32]; int32_t delta_poc[32]; uint8_t used[32]; } ShortTermRPS; From 32fcb17e4213ddcad6d814f18ce762c3deb143e6 Mon Sep 17 00:00:00 2001 From: Lynne Date: Tue, 28 Feb 2023 20:44:06 +0100 Subject: [PATCH 1228/2172] hevc_ps: expose vui_present flag --- libavcodec/hevc_ps.c | 6 +++--- libavcodec/hevc_ps.h | 1 + 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/libavcodec/hevc_ps.c b/libavcodec/hevc_ps.c index 7181398e90b..995b70f65d2 100644 --- a/libavcodec/hevc_ps.c +++ b/libavcodec/hevc_ps.c @@ -855,7 +855,7 @@ int ff_hevc_parse_sps(HEVCSPS *sps, GetBitContext *gb, unsigned int *sps_id, { HEVCWindow *ow; int ret = 0; - int bit_depth_chroma, start, vui_present, sublayer_ordering_info, num_comps; + int bit_depth_chroma, start, sublayer_ordering_info, num_comps; int i, j; // Coded parameters @@ -1082,8 +1082,8 @@ int ff_hevc_parse_sps(HEVCSPS *sps, GetBitContext *gb, unsigned int *sps_id, sps->sps_temporal_mvp_enabled_flag = get_bits1(gb); sps->sps_strong_intra_smoothing_enable_flag = get_bits1(gb); sps->vui.common.sar = (AVRational){0, 1}; - vui_present = get_bits1(gb); - if (vui_present) + sps->vui_present = get_bits1(gb); + if (sps->vui_present) decode_vui(gb, avctx, apply_defdispwin, sps); if (get_bits1(gb)) { // sps_extension_flag diff --git a/libavcodec/hevc_ps.h b/libavcodec/hevc_ps.h index 2b89cdc9fd6..39212b43a7a 100644 --- a/libavcodec/hevc_ps.h +++ b/libavcodec/hevc_ps.h @@ -211,6 +211,7 @@ typedef struct HEVCSPS { } temporal_layer[HEVC_MAX_SUB_LAYERS]; uint8_t temporal_id_nesting_flag; + int vui_present; VUI vui; PTL ptl; From cc5fab5c48ea27a4133b8b913472dc59e19a2afb Mon Sep 17 00:00:00 2001 From: Lynne Date: Tue, 28 Feb 2023 20:44:38 +0100 Subject: [PATCH 1229/2172] hevc_ps: expose sublayer_ordering_info_flag --- libavcodec/hevc_ps.c | 8 ++++---- libavcodec/hevc_ps.h | 1 + 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/libavcodec/hevc_ps.c b/libavcodec/hevc_ps.c index 995b70f65d2..8125d9cbd3b 100644 --- a/libavcodec/hevc_ps.c +++ b/libavcodec/hevc_ps.c @@ -855,7 +855,7 @@ int ff_hevc_parse_sps(HEVCSPS *sps, GetBitContext *gb, unsigned int *sps_id, { HEVCWindow *ow; int ret = 0; - int bit_depth_chroma, start, sublayer_ordering_info, num_comps; + int bit_depth_chroma, start, num_comps; int i, j; // Coded parameters @@ -961,8 +961,8 @@ int ff_hevc_parse_sps(HEVCSPS *sps, GetBitContext *gb, unsigned int *sps_id, return AVERROR_INVALIDDATA; } - sublayer_ordering_info = get_bits1(gb); - start = sublayer_ordering_info ? 0 : sps->max_sub_layers - 1; + sps->sublayer_ordering_info_flag = get_bits1(gb); + start = sps->sublayer_ordering_info_flag ? 0 : sps->max_sub_layers - 1; for (i = start; i < sps->max_sub_layers; i++) { sps->temporal_layer[i].max_dec_pic_buffering = get_ue_golomb_long(gb) + 1; sps->temporal_layer[i].num_reorder_pics = get_ue_golomb_long(gb); @@ -983,7 +983,7 @@ int ff_hevc_parse_sps(HEVCSPS *sps, GetBitContext *gb, unsigned int *sps_id, } } - if (!sublayer_ordering_info) { + if (!sps->sublayer_ordering_info_flag) { for (i = 0; i < start; i++) { sps->temporal_layer[i].max_dec_pic_buffering = sps->temporal_layer[start].max_dec_pic_buffering; sps->temporal_layer[i].num_reorder_pics = sps->temporal_layer[start].num_reorder_pics; diff --git a/libavcodec/hevc_ps.h b/libavcodec/hevc_ps.h index 39212b43a7a..182b671ef7f 100644 --- a/libavcodec/hevc_ps.h +++ b/libavcodec/hevc_ps.h @@ -203,6 +203,7 @@ typedef struct HEVCSPS { unsigned int log2_max_poc_lsb; int pcm_enabled_flag; + uint8_t sublayer_ordering_info_flag; int max_sub_layers; struct { int max_dec_pic_buffering; From 8b2d46ee3d10c5538be5a5339cd3266f39a612ed Mon Sep 17 00:00:00 2001 From: Lynne Date: Tue, 28 Feb 2023 20:45:05 +0100 Subject: [PATCH 1230/2172] hevc_ps: expose conformance_window_flag --- libavcodec/hevc_ps.c | 3 ++- libavcodec/hevc_ps.h | 1 + 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/libavcodec/hevc_ps.c b/libavcodec/hevc_ps.c index 8125d9cbd3b..f106932d43a 100644 --- a/libavcodec/hevc_ps.c +++ b/libavcodec/hevc_ps.c @@ -904,7 +904,8 @@ int ff_hevc_parse_sps(HEVCSPS *sps, GetBitContext *gb, unsigned int *sps_id, sps->height, 0, avctx)) < 0) return ret; - if (get_bits1(gb)) { // pic_conformance_flag + sps->conformance_window_flag = get_bits1(gb); + if (sps->conformance_window_flag) { int vert_mult = hevc_sub_height_c[sps->chroma_format_idc]; int horiz_mult = hevc_sub_width_c[sps->chroma_format_idc]; sps->pic_conf_win.left_offset = get_ue_golomb_long(gb) * horiz_mult; diff --git a/libavcodec/hevc_ps.h b/libavcodec/hevc_ps.h index 182b671ef7f..a9515cdb0e2 100644 --- a/libavcodec/hevc_ps.h +++ b/libavcodec/hevc_ps.h @@ -191,6 +191,7 @@ typedef struct HEVCSPS { HEVCWindow output_window; + uint8_t conformance_window_flag; HEVCWindow pic_conf_win; HEVCHdrParams hdr; From 21719c29a2f4b881e32511f5ce9c8b92faa7047e Mon Sep 17 00:00:00 2001 From: Lynne Date: Tue, 28 Feb 2023 20:45:24 +0100 Subject: [PATCH 1231/2172] hevc_ps: expose sps_extension_present_flag --- libavcodec/hevc_ps.c | 3 ++- libavcodec/hevc_ps.h | 1 + 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/libavcodec/hevc_ps.c b/libavcodec/hevc_ps.c index f106932d43a..01b11ed42aa 100644 --- a/libavcodec/hevc_ps.c +++ b/libavcodec/hevc_ps.c @@ -1087,7 +1087,8 @@ int ff_hevc_parse_sps(HEVCSPS *sps, GetBitContext *gb, unsigned int *sps_id, if (sps->vui_present) decode_vui(gb, avctx, apply_defdispwin, sps); - if (get_bits1(gb)) { // sps_extension_flag + sps->sps_extension_present_flag = get_bits1(gb); + if (sps->sps_extension_present_flag) { sps->sps_range_extension_flag = get_bits1(gb); sps->sps_multilayer_extension_flag = get_bits1(gb); sps->sps_3d_extension_flag = get_bits1(gb); diff --git a/libavcodec/hevc_ps.h b/libavcodec/hevc_ps.h index a9515cdb0e2..ef11e51ee72 100644 --- a/libavcodec/hevc_ps.h +++ b/libavcodec/hevc_ps.h @@ -217,6 +217,7 @@ typedef struct HEVCSPS { VUI vui; PTL ptl; + uint8_t sps_extension_present_flag; uint8_t scaling_list_enable_flag; ScalingList scaling_list; From 0bda3340a32d1ed932697145be301a01dcea9687 Mon Sep 17 00:00:00 2001 From: Lynne Date: Sat, 25 Feb 2023 09:34:54 +0100 Subject: [PATCH 1232/2172] lavu: add 12-bit 2-plane 422 and 444 pixel formats --- libavutil/pixdesc.c | 48 +++++++++++++++++++++++++++++++++++++++++ libavutil/pixfmt.h | 8 +++++++ tests/ref/fate/imgutils | 4 ++++ 3 files changed, 60 insertions(+) diff --git a/libavutil/pixdesc.c b/libavutil/pixdesc.c index 62a2ae08d90..e1e0dd2a9ea 100644 --- a/libavutil/pixdesc.c +++ b/libavutil/pixdesc.c @@ -2717,6 +2717,54 @@ static const AVPixFmtDescriptor av_pix_fmt_descriptors[AV_PIX_FMT_NB] = { .flags = AV_PIX_FMT_FLAG_RGB | AV_PIX_FMT_FLAG_FLOAT | AV_PIX_FMT_FLAG_ALPHA, }, + [AV_PIX_FMT_P212BE] = { + .name = "p212be", + .nb_components = 3, + .log2_chroma_w = 1, + .log2_chroma_h = 0, + .comp = { + { 0, 2, 0, 4, 12 }, /* Y */ + { 1, 4, 0, 4, 12 }, /* U */ + { 1, 4, 2, 4, 12 }, /* V */ + }, + .flags = AV_PIX_FMT_FLAG_PLANAR | AV_PIX_FMT_FLAG_BE, + }, + [AV_PIX_FMT_P212LE] = { + .name = "p212le", + .nb_components = 3, + .log2_chroma_w = 1, + .log2_chroma_h = 0, + .comp = { + { 0, 2, 0, 4, 12 }, /* Y */ + { 1, 4, 0, 4, 12 }, /* U */ + { 1, 4, 2, 4, 12 }, /* V */ + }, + .flags = AV_PIX_FMT_FLAG_PLANAR, + }, + [AV_PIX_FMT_P412BE] = { + .name = "p412be", + .nb_components = 3, + .log2_chroma_w = 0, + .log2_chroma_h = 0, + .comp = { + { 0, 2, 0, 4, 12 }, /* Y */ + { 1, 4, 0, 4, 12 }, /* U */ + { 1, 4, 2, 4, 12 }, /* V */ + }, + .flags = AV_PIX_FMT_FLAG_PLANAR | AV_PIX_FMT_FLAG_BE, + }, + [AV_PIX_FMT_P412LE] = { + .name = "p412le", + .nb_components = 3, + .log2_chroma_w = 0, + .log2_chroma_h = 0, + .comp = { + { 0, 2, 0, 4, 12 }, /* Y */ + { 1, 4, 0, 4, 12 }, /* U */ + { 1, 4, 2, 4, 12 }, /* 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 37c2c79e014..63e07ba64f7 100644 --- a/libavutil/pixfmt.h +++ b/libavutil/pixfmt.h @@ -420,6 +420,12 @@ enum AVPixelFormat { AV_PIX_FMT_RGBAF32BE, ///< IEEE-754 single precision packed RGBA 32:32:32:32, 128bpp, RGBARGBA..., big-endian AV_PIX_FMT_RGBAF32LE, ///< IEEE-754 single precision packed RGBA 32:32:32:32, 128bpp, RGBARGBA..., little-endian + AV_PIX_FMT_P212BE, ///< interleaved chroma YUV 4:2:2, 24bpp, data in the high bits, big-endian + AV_PIX_FMT_P212LE, ///< interleaved chroma YUV 4:2:2, 24bpp, data in the high bits, little-endian + + AV_PIX_FMT_P412BE, ///< interleaved chroma YUV 4:4:4, 36bpp, data in the high bits, big-endian + AV_PIX_FMT_P412LE, ///< interleaved chroma YUV 4:4:4, 36bpp, data in the high bits, 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 }; @@ -518,6 +524,8 @@ enum AVPixelFormat { #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_P212 AV_PIX_FMT_NE(P212BE, P212LE) +#define AV_PIX_FMT_P412 AV_PIX_FMT_NE(P412BE, P412LE) #define AV_PIX_FMT_P216 AV_PIX_FMT_NE(P216BE, P216LE) #define AV_PIX_FMT_P416 AV_PIX_FMT_NE(P416BE, P416LE) diff --git a/tests/ref/fate/imgutils b/tests/ref/fate/imgutils index e79ec7e4b3d..02a755f2b76 100644 --- a/tests/ref/fate/imgutils +++ b/tests/ref/fate/imgutils @@ -262,3 +262,7 @@ rgbf32be planes: 1, linesizes: 768 0 0 0, plane_sizes: 36864 0 rgbf32le planes: 1, linesizes: 768 0 0 0, plane_sizes: 36864 0 0 0, plane_offsets: 0 0 0, total_size: 36864 rgbaf32be planes: 1, linesizes: 1024 0 0 0, plane_sizes: 49152 0 0 0, plane_offsets: 0 0 0, total_size: 49152 rgbaf32le planes: 1, linesizes: 1024 0 0 0, plane_sizes: 49152 0 0 0, plane_offsets: 0 0 0, total_size: 49152 +p212be planes: 2, linesizes: 128 128 0 0, plane_sizes: 6144 6144 0 0, plane_offsets: 6144 0 0, total_size: 12288 +p212le planes: 2, linesizes: 128 128 0 0, plane_sizes: 6144 6144 0 0, plane_offsets: 6144 0 0, total_size: 12288 +p412be planes: 2, linesizes: 128 256 0 0, plane_sizes: 6144 12288 0 0, plane_offsets: 6144 0 0, total_size: 18432 +p412le planes: 2, linesizes: 128 256 0 0, plane_sizes: 6144 12288 0 0, plane_offsets: 6144 0 0, total_size: 18432 From 934525eae0f73fe61f5d4694b6ae413ccc823d8c Mon Sep 17 00:00:00 2001 From: Lynne Date: Sat, 25 Feb 2023 09:36:58 +0100 Subject: [PATCH 1233/2172] lsws: add in/out support for the new 12-bit 2-plane 422 and 444 pixfmts --- libswscale/input.c | 8 ++++++++ libswscale/utils.c | 4 ++++ tests/ref/fate/filter-pixdesc-p212be | 1 + tests/ref/fate/filter-pixdesc-p212le | 1 + tests/ref/fate/filter-pixdesc-p412be | 1 + tests/ref/fate/filter-pixdesc-p412le | 1 + tests/ref/fate/filter-pixfmts-copy | 4 ++++ tests/ref/fate/filter-pixfmts-crop | 4 ++++ tests/ref/fate/filter-pixfmts-field | 4 ++++ tests/ref/fate/filter-pixfmts-fieldorder | 4 ++++ tests/ref/fate/filter-pixfmts-hflip | 4 ++++ tests/ref/fate/filter-pixfmts-il | 4 ++++ tests/ref/fate/filter-pixfmts-null | 4 ++++ tests/ref/fate/filter-pixfmts-pad | 2 ++ tests/ref/fate/filter-pixfmts-scale | 4 ++++ tests/ref/fate/filter-pixfmts-transpose | 2 ++ tests/ref/fate/filter-pixfmts-vflip | 4 ++++ tests/ref/fate/sws-pixdesc-query | 26 ++++++++++++++++++++++++ 18 files changed, 82 insertions(+) create mode 100644 tests/ref/fate/filter-pixdesc-p212be create mode 100644 tests/ref/fate/filter-pixdesc-p212le create mode 100644 tests/ref/fate/filter-pixdesc-p412be create mode 100644 tests/ref/fate/filter-pixdesc-p412le diff --git a/libswscale/input.c b/libswscale/input.c index d5676062a29..41795c636ee 100644 --- a/libswscale/input.c +++ b/libswscale/input.c @@ -1452,9 +1452,13 @@ av_cold void ff_sws_init_input_funcs(SwsContext *c) c->chrToYV12 = p010BEToUV_c; break; case AV_PIX_FMT_P012LE: + case AV_PIX_FMT_P212LE: + case AV_PIX_FMT_P412LE: c->chrToYV12 = p012LEToUV_c; break; case AV_PIX_FMT_P012BE: + case AV_PIX_FMT_P212BE: + case AV_PIX_FMT_P412BE: c->chrToYV12 = p012BEToUV_c; break; case AV_PIX_FMT_P016LE: @@ -1944,9 +1948,13 @@ av_cold void ff_sws_init_input_funcs(SwsContext *c) c->lumToYV12 = p010BEToY_c; break; case AV_PIX_FMT_P012LE: + case AV_PIX_FMT_P212LE: + case AV_PIX_FMT_P412LE: c->lumToYV12 = p012LEToY_c; break; case AV_PIX_FMT_P012BE: + case AV_PIX_FMT_P212BE: + case AV_PIX_FMT_P412BE: c->lumToYV12 = p012BEToY_c; break; case AV_PIX_FMT_GRAYF32LE: diff --git a/libswscale/utils.c b/libswscale/utils.c index b02e6cdc646..8fe34a34372 100644 --- a/libswscale/utils.c +++ b/libswscale/utils.c @@ -248,8 +248,12 @@ static const FormatEntry format_entries[] = { [AV_PIX_FMT_X2BGR10LE] = { 1, 1 }, [AV_PIX_FMT_P210BE] = { 1, 1 }, [AV_PIX_FMT_P210LE] = { 1, 1 }, + [AV_PIX_FMT_P212BE] = { 1, 1 }, + [AV_PIX_FMT_P212LE] = { 1, 1 }, [AV_PIX_FMT_P410BE] = { 1, 1 }, [AV_PIX_FMT_P410LE] = { 1, 1 }, + [AV_PIX_FMT_P412BE] = { 1, 1 }, + [AV_PIX_FMT_P412LE] = { 1, 1 }, [AV_PIX_FMT_P216BE] = { 1, 1 }, [AV_PIX_FMT_P216LE] = { 1, 1 }, [AV_PIX_FMT_P416BE] = { 1, 1 }, diff --git a/tests/ref/fate/filter-pixdesc-p212be b/tests/ref/fate/filter-pixdesc-p212be new file mode 100644 index 00000000000..01dd15f88ac --- /dev/null +++ b/tests/ref/fate/filter-pixdesc-p212be @@ -0,0 +1 @@ +pixdesc-p212be 3a6540d860f6befcc76f367f1c493548 diff --git a/tests/ref/fate/filter-pixdesc-p212le b/tests/ref/fate/filter-pixdesc-p212le new file mode 100644 index 00000000000..ddad0ffa3ad --- /dev/null +++ b/tests/ref/fate/filter-pixdesc-p212le @@ -0,0 +1 @@ +pixdesc-p212le 008b0b732e8f719cf2859ad106717a67 diff --git a/tests/ref/fate/filter-pixdesc-p412be b/tests/ref/fate/filter-pixdesc-p412be new file mode 100644 index 00000000000..102055c09df --- /dev/null +++ b/tests/ref/fate/filter-pixdesc-p412be @@ -0,0 +1 @@ +pixdesc-p412be b6e7d1f6049563cc3e3d3a20c437ee88 diff --git a/tests/ref/fate/filter-pixdesc-p412le b/tests/ref/fate/filter-pixdesc-p412le new file mode 100644 index 00000000000..1b2696aa60c --- /dev/null +++ b/tests/ref/fate/filter-pixdesc-p412le @@ -0,0 +1 @@ +pixdesc-p412le 4505a632dee08204171ff96908bd2149 diff --git a/tests/ref/fate/filter-pixfmts-copy b/tests/ref/fate/filter-pixfmts-copy index b28a114c7bb..27f12e8f975 100644 --- a/tests/ref/fate/filter-pixfmts-copy +++ b/tests/ref/fate/filter-pixfmts-copy @@ -68,10 +68,14 @@ p016be 7f9842d6015026136bad60d03c035cc3 p016le c453421b9f726bdaf2bacf59a492c43b p210be 847e9c6e292b17349e69570829252b3e p210le c06e4b76cf504e908128081f92b60ce2 +p212be 4df641ed058718ad27a01889f923b04f +p212le 414d3c187722afa8da718358924a9f6b p216be f5009974fc1cd5d552705eeb52de35d9 p216le 2f634e1a3cd5c9c122e0f2ebadb3503d p410be 7c2509d2df4bbb199ab653ebb6dce61e p410le 527761e1f4381007044679710a352ecc +p412be d3055624d596c30deb633f24761d6888 +p412le 1f19a675b00d8c9df499200fd80bcc10 p416be fd828e966d45ae908f5d2d4b3349b816 p416le 983064bfd506be1e26cd57bafc14ae50 pal8 ff5929f5b42075793b2c34cb441bede5 diff --git a/tests/ref/fate/filter-pixfmts-crop b/tests/ref/fate/filter-pixfmts-crop index bdb2536f7d5..7bd0cfcb891 100644 --- a/tests/ref/fate/filter-pixfmts-crop +++ b/tests/ref/fate/filter-pixfmts-crop @@ -66,10 +66,14 @@ p016be 8b2de2eb6b099bbf355bfc55a0694ddc p016le 373b50c766dfd0a8e79c9a73246d803a p210be 2947f43774352ef61f9e83777548c7c5 p210le 74fcd5a32eee687eebe002c884103963 +p212be c983aa869bae2c70e7b01810902ffc05 +p212le b7ace445c6c403a2f6ff9686f38a7045 p216be 41351128eaf636041c8987698730391a p216le e56f5e5b0d4460d56f27a5df8a4a1462 p410be e17c78ff059363177548412e6ab4e65f p410le 75f910c7282d8065d97f502ba974c481 +p412be 69b358196dffed9cbbb1342214a6d689 +p412le 87899c57e7eccbe3d08fcebd2d83f6b2 p416be 52f08b8a56a09d6e954c2eab6cf24d99 p416le ecb78b327ea5cfe1fff82945c1fca310 pal8 1f2cdc8e718f95c875dbc1034a688bfb diff --git a/tests/ref/fate/filter-pixfmts-field b/tests/ref/fate/filter-pixfmts-field index 4e5a7984713..0c40a4d90fa 100644 --- a/tests/ref/fate/filter-pixfmts-field +++ b/tests/ref/fate/filter-pixfmts-field @@ -68,10 +68,14 @@ p016be a0311a09bba7383553267d2b3b9c075e p016le ee09a18aefa3ebe97715b3a7312cb8ff p210be 58d46f566ab28e3bcfb715c7aa53cf58 p210le 8d68f7655a3d76f2f8436bd25beb3973 +p212be a8901966c5bc111e9e62d3989b0b666b +p212le 9b3df82ffdafda3163e124e38de10347 p216be dd1f3e0bb5c49775a598ab29802fc268 p216le b573c0473a1368813d077487cc9bce0e p410be 658fd0d92eb327cbd562abafc8694db7 p410le c981188c7fd9f32988a9f4732303f82b +p412be a2afab602628b8da3f0af5c235f2a30e +p412le 38cb842fef010b73d71654dc9ae4afca p416be 66616bf2320464b5e9b6372d48b6b9a9 p416le 1039b97bbe42ef0af1bc46d2c0fc819e pal8 0658c18dcd8d052d59dfbe23f5b368d9 diff --git a/tests/ref/fate/filter-pixfmts-fieldorder b/tests/ref/fate/filter-pixfmts-fieldorder index bebaf073710..8c024784e30 100644 --- a/tests/ref/fate/filter-pixfmts-fieldorder +++ b/tests/ref/fate/filter-pixfmts-fieldorder @@ -58,10 +58,14 @@ nv24 4fdbef26042c77f012df114e666efdb2 nv42 59608290fece913e6b7d61edf581a529 p210be ca2ce2c25db43dcd14729b2a72a7c604 p210le 755363012d8801b96ead2e8b1b4d2ab8 +p212be b28ae205def3434349347f8c0d94b707 +p212le 90fe12fa6ac4d8d2631c082d2b9a5d74 p216be 17741c0cdb65914ad13c5114121a175f p216le c0c888ab7bde56638732344076b3b2ba p410be b6d65b820198ca6ff0103d9794727792 p410le 2771dd3ae54a439921f51c29e79b6799 +p412be 2d0c876b68f25ac0e8326faa81d911d8 +p412le ab400cb3fa1aa16c3af8c58efa679979 p416be a0f8b5acad8fafc45fc7b2275fac1d84 p416le 2e73af44eb933580da59981176848dcc rgb0 2e3d8c91c7a83d451593dfd06607ff39 diff --git a/tests/ref/fate/filter-pixfmts-hflip b/tests/ref/fate/filter-pixfmts-hflip index fd5e9723fd1..a80b1abd5b0 100644 --- a/tests/ref/fate/filter-pixfmts-hflip +++ b/tests/ref/fate/filter-pixfmts-hflip @@ -66,10 +66,14 @@ p016be 744b13e44d39e1ff7588983fa03e0101 p016le a50b160346ab94f55a425065b57006f0 p210be 6f5a76d6467b86d55fe5589d3af8a7ea p210le b6982912b2376371edea4fccf99fe40c +p212be 9ffa4664543233ec7c9b99a627cb7003 +p212le cb4960bd87232af96bb3d6faea650cf7 p216be c1b58f61cd6df9cf01c3086786fb8a69 p216le 1f5213bebf4c99634f57290f5ad99c0d p410be 2e06214ea84595aa1294239b0f1e900f p410le 1143c811c383e4461b1192dca0c74246 +p412be a106a2e9bb534f31173dc93ac2888800 +p412le 77c33ea4dc8f94a8054f19b8b9bac491 p416be da6807d924b63a54b804d32e427524bf p416le a42b88cabc4395aa0bf1bcbbc876f48f pal8 5b7c77d99817b4f52339742a47de7797 diff --git a/tests/ref/fate/filter-pixfmts-il b/tests/ref/fate/filter-pixfmts-il index ec9d8097211..461b2b17203 100644 --- a/tests/ref/fate/filter-pixfmts-il +++ b/tests/ref/fate/filter-pixfmts-il @@ -68,10 +68,14 @@ p016be 3df51286ef66b53e3e283dbbab582263 p016le eadcd8241e97e35b2b47d5eb2eaea6cd p210be 29ec4e8912d456cd15203a96487c42e8 p210le c695064fb9f2cc4e35957d4d649cc281 +p212be ee6f88801823da3d617fb9e073e88068 +p212le 8fb9e5664b18c94f37d29e5b1cb834ab p216be ad85bdc59755608602608a9438bb82ea p216le 77757390da383a90981e461d128d8789 p410be 2128861337e660232e6fb664cc4de3e6 p410le 6cf3a3e199b327f4f013e0346410d7a8 +p412be 481cb1d4c7b125d0148f5aa132ddcdd5 +p412le 6a7cf1156ee98f00ec31c863b9fb5ded p416be 47dec75cefeb6220be7731bc25b7be9c p416le 4990b51ff889d9ee23e68997f81c09f1 rgb0 cfaf68671e43248267d8cd50cae8c13f diff --git a/tests/ref/fate/filter-pixfmts-null b/tests/ref/fate/filter-pixfmts-null index b28a114c7bb..27f12e8f975 100644 --- a/tests/ref/fate/filter-pixfmts-null +++ b/tests/ref/fate/filter-pixfmts-null @@ -68,10 +68,14 @@ p016be 7f9842d6015026136bad60d03c035cc3 p016le c453421b9f726bdaf2bacf59a492c43b p210be 847e9c6e292b17349e69570829252b3e p210le c06e4b76cf504e908128081f92b60ce2 +p212be 4df641ed058718ad27a01889f923b04f +p212le 414d3c187722afa8da718358924a9f6b p216be f5009974fc1cd5d552705eeb52de35d9 p216le 2f634e1a3cd5c9c122e0f2ebadb3503d p410be 7c2509d2df4bbb199ab653ebb6dce61e p410le 527761e1f4381007044679710a352ecc +p412be d3055624d596c30deb633f24761d6888 +p412le 1f19a675b00d8c9df499200fd80bcc10 p416be fd828e966d45ae908f5d2d4b3349b816 p416le 983064bfd506be1e26cd57bafc14ae50 pal8 ff5929f5b42075793b2c34cb441bede5 diff --git a/tests/ref/fate/filter-pixfmts-pad b/tests/ref/fate/filter-pixfmts-pad index 57ccc4ae4d7..83946222572 100644 --- a/tests/ref/fate/filter-pixfmts-pad +++ b/tests/ref/fate/filter-pixfmts-pad @@ -31,8 +31,10 @@ p010le fbbc23cc1d764a5e6fb71883d985f3ed p012le 3a92c1bd3e9de050bf6abcc3fd911ab7 p016le fbbc23cc1d764a5e6fb71883d985f3ed p210le 680912c059de39c3401cac856bd1b0c1 +p212le a2f88017bcce2383ba60bc4872e639ba p216le 8718662e226a4581561e7bb532af2d83 p410le 5ca28f2bcc849987810e1f3437b12feb +p412le 2a619fca8166dcd09251a577ed36ab53 p416le fa4e023d0bf4b03b0ffef3d4d35abf7e rgb0 0984eb985dabbe757ed6beb53db84eff rgb24 17f9e2e0c609009acaf2175c42d4a2a5 diff --git a/tests/ref/fate/filter-pixfmts-scale b/tests/ref/fate/filter-pixfmts-scale index 525306ec122..6435cc6ef2c 100644 --- a/tests/ref/fate/filter-pixfmts-scale +++ b/tests/ref/fate/filter-pixfmts-scale @@ -68,10 +68,14 @@ p016be 31e204018cbb53f8988c4e1174ea8ce9 p016le d5afe557f492a09317e525d7cb782f5b p210be 2cc6dfcf5e006c8ed5238988a06fd45e p210le 04efb8f14a9d98417af40954a06aa187 +p212be 611c6e267e7a694ce89467779e44060b +p212le 3d060f9f294b484ebe1ee120c808af03 p216be 2f649a226812c8e5a553c4e22d301684 p216le c8f65811f717a12706a598561c6df46d p410be 354cd1324ad382df1a3d573833323cce p410le 90fdd95ec4482c127d98307550a885c6 +p412be dc04d91115bcd4100bfb61c103e0877c +p412le b01358e9c0fa99a98dadd28769f949e8 p416be aa54294859a8e6cb2c9cf64d343fdb60 p416le d91a0858ea8d2cf1ed29f179c9ad9666 pal8 29e10892009b2cfe431815ec3052ed3b diff --git a/tests/ref/fate/filter-pixfmts-transpose b/tests/ref/fate/filter-pixfmts-transpose index 24f4249639f..169f2708ece 100644 --- a/tests/ref/fate/filter-pixfmts-transpose +++ b/tests/ref/fate/filter-pixfmts-transpose @@ -65,6 +65,8 @@ p016be ad0de2cc9bff81688b182a870fcf7000 p016le e7ff5143595021246733ce6bd0a769e8 p410be 8b3e0ccb31b6a20ff00a29253fb2dec3 p410le 4e5f78dfccda9a6387e81354a56a033a +p412be 88e4578d2c6d99399a6cf1db9e4c0553 +p412le 7905a6e5a0c29b68e025824c7e29adb8 p416be 350a90bda53349435d89ec13533726b7 p416le 7bb46e2aec65669a27502ec452941237 rgb0 31ea5da7fe779c6ea0a33f1d28aad918 diff --git a/tests/ref/fate/filter-pixfmts-vflip b/tests/ref/fate/filter-pixfmts-vflip index b7b0526588a..705ab1a0509 100644 --- a/tests/ref/fate/filter-pixfmts-vflip +++ b/tests/ref/fate/filter-pixfmts-vflip @@ -68,10 +68,14 @@ p016be 06e9354b6e0e38ba41736352cedc0bd5 p016le fd18d322bffbf5816902c13102872e22 p210be ca886ab2b3ea5c153f1954b3709f7249 p210le d71c2d4e483030ffd87fa6a68c83fce0 +p212be 1734e5840d4e75defe7a28683c3f8856 +p212le dec72e3481e123f127a6179b3dcd3a1d p216be 7f268f755ed02592b3a49fd5f7bd48bb p216le 2c0a660762527706799c4705ca50a9c5 p410be 4c603e4464ed3f34cc432b4d1f912082 p410le 849308a1cdf41e055019cf311d1b2201 +p412be 8e641f154aa2151c9e87b377b4f8b213 +p412le 1b22d5b9893b25a8b8836c5fb5aeb43d p416be 7e7657ab40cf953351a14ea76e296519 p416le 0991d7fff4e2caf36be219ecdd9619d4 pal8 450b0155d0f2d5628bf95a442db5f817 diff --git a/tests/ref/fate/sws-pixdesc-query b/tests/ref/fate/sws-pixdesc-query index 14156a383cc..fd7f2aefc0f 100644 --- a/tests/ref/fate/sws-pixdesc-query +++ b/tests/ref/fate/sws-pixdesc-query @@ -67,8 +67,12 @@ isNBPS: p012le p210be p210le + p212be + p212le p410be p410le + p412be + p412le x2bgr10be x2bgr10le x2rgb10be @@ -160,8 +164,10 @@ isBE: p012be p016be p210be + p212be p216be p410be + p412be p416be rgb444be rgb48be @@ -226,10 +232,14 @@ isYUV: p016le p210be p210le + p212be + p212le p216be p216le p410be p410le + p412be + p412le p416be p416le uyvy422 @@ -338,10 +348,14 @@ isPlanarYUV: p016le p210be p210le + p212be + p212le p216be p216le p410be p410le + p412be + p412le p416be p416le yuv410p @@ -431,10 +445,14 @@ isSemiPlanarYUV: p016le p210be p210le + p212be + p212le p216be p216le p410be p410le + p412be + p412le p416be p416le @@ -853,10 +871,14 @@ Planar: p016le p210be p210le + p212be + p212le p216be p216le p410be p410le + p412be + p412le p416be p416le yuv410p @@ -1029,8 +1051,12 @@ DataInHighBits: p012le p210be p210le + p212be + p212le p410be p410le + p412be + p412le xv36be xv36le xyz12be From 59707cc485c7fcc1c06b96648ce605ed558da4ac Mon Sep 17 00:00:00 2001 From: Lynne Date: Wed, 23 Nov 2022 15:15:04 +0100 Subject: [PATCH 1234/2172] hwcontext_vulkan: initialize and require instance version 1.3 This just bumps the required loader library version (libvulkan). All device-related features, such as video decoding, atomics, etc. are still optional and the code deals with their loss on a local level (e.g. the decoder or filter checks for the features it needs, not the hwcontext). Bumping the required version essentially packs all maintenance extensions which correct the spec rather than requiring to enable them individually. --- configure | 4 ++-- libavutil/hwcontext_vulkan.c | 2 +- libavutil/hwcontext_vulkan.h | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/configure b/configure index 87f7afc2e1a..201efd4f945 100755 --- a/configure +++ b/configure @@ -7040,8 +7040,8 @@ enabled crystalhd && check_lib crystalhd "stdint.h libcrystalhd/libcrystalhd_if. "in maintaining it." 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_3) || (defined(VK_VERSION_1_2) && VK_HEADER_VERSION >= 189)" + check_pkg_config_header_only vulkan "vulkan >= 1.3.238" "vulkan/vulkan.h" "defined VK_VERSION_1_3" || + check_cpp_condition vulkan "vulkan/vulkan.h" "defined(VK_VERSION_1_4) || (defined(VK_VERSION_1_3) && VK_HEADER_VERSION >= 238)" fi if enabled x86; then diff --git a/libavutil/hwcontext_vulkan.c b/libavutil/hwcontext_vulkan.c index ffd4f5dec4e..4185fb6110f 100644 --- a/libavutil/hwcontext_vulkan.c +++ b/libavutil/hwcontext_vulkan.c @@ -673,7 +673,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_2, + .apiVersion = VK_API_VERSION_1_3, .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 df86c85b3ce..70c8379dc36 100644 --- a/libavutil/hwcontext_vulkan.h +++ b/libavutil/hwcontext_vulkan.h @@ -53,7 +53,7 @@ typedef struct AVVulkanDeviceContext { PFN_vkGetInstanceProcAddr get_proc_addr; /** - * Vulkan instance. Must be at least version 1.2. + * Vulkan instance. Must be at least version 1.3. */ VkInstance inst; From fddfb0ebf893c8b09bbad8dd722037828c5463c1 Mon Sep 17 00:00:00 2001 From: Lynne Date: Wed, 23 Nov 2022 02:37:14 +0100 Subject: [PATCH 1235/2172] hwcontext_vulkan: enable support for YCbCr samplers --- libavutil/hwcontext_vulkan.c | 1 + libavutil/vulkan_functions.h | 2 ++ 2 files changed, 3 insertions(+) diff --git a/libavutil/hwcontext_vulkan.c b/libavutil/hwcontext_vulkan.c index 4185fb6110f..f8cc2d9dbd5 100644 --- a/libavutil/hwcontext_vulkan.c +++ b/libavutil/hwcontext_vulkan.c @@ -1378,6 +1378,7 @@ static int vulkan_device_create_internal(AVHWDeviceContext *ctx, goto end; } p->device_features_1_2.timelineSemaphore = 1; + p->device_features_1_1.samplerYcbcrConversion = dev_features_1_1.samplerYcbcrConversion; /* Setup queue family */ if ((err = setup_queue_families(ctx, &dev_info))) diff --git a/libavutil/vulkan_functions.h b/libavutil/vulkan_functions.h index d15a5d9a425..deb77495a2f 100644 --- a/libavutil/vulkan_functions.h +++ b/libavutil/vulkan_functions.h @@ -155,6 +155,8 @@ typedef enum FFVulkanExtensions { MACRO(1, 1, FF_VK_EXT_NO_FLAG, DestroyPipeline) \ \ /* Sampler */ \ + MACRO(1, 1, FF_VK_EXT_NO_FLAG, CreateSamplerYcbcrConversion) \ + MACRO(1, 1, FF_VK_EXT_NO_FLAG, DestroySamplerYcbcrConversion) \ MACRO(1, 1, FF_VK_EXT_NO_FLAG, CreateSampler) \ MACRO(1, 1, FF_VK_EXT_NO_FLAG, DestroySampler) \ \ From 74b202b8395e7ce7150a51d682c342dbd83262bc Mon Sep 17 00:00:00 2001 From: Lynne Date: Sun, 13 Mar 2022 09:06:06 +0100 Subject: [PATCH 1236/2172] hwcontext_vulkan: enable VK_KHR_synchronization2 if supported --- libavutil/hwcontext_vulkan.c | 16 ++++++++++++---- libavutil/vulkan_functions.h | 5 ++++- 2 files changed, 16 insertions(+), 5 deletions(-) diff --git a/libavutil/hwcontext_vulkan.c b/libavutil/hwcontext_vulkan.c index f8cc2d9dbd5..ae28a110930 100644 --- a/libavutil/hwcontext_vulkan.c +++ b/libavutil/hwcontext_vulkan.c @@ -89,6 +89,7 @@ typedef struct VulkanDevicePriv { /* Features */ VkPhysicalDeviceVulkan11Features device_features_1_1; VkPhysicalDeviceVulkan12Features device_features_1_2; + VkPhysicalDeviceVulkan13Features device_features_1_3; /* Queues */ uint32_t qfs[5]; @@ -346,7 +347,6 @@ static const VulkanOptExtension optional_device_exts[] = { /* Misc or required by other extensions */ { VK_KHR_PUSH_DESCRIPTOR_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, FF_VK_EXT_EXTERNAL_FD_MEMORY }, @@ -1326,9 +1326,13 @@ static int vulkan_device_create_internal(AVHWDeviceContext *ctx, VkPhysicalDeviceTimelineSemaphoreFeatures timeline_features = { .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TIMELINE_SEMAPHORE_FEATURES, }; + VkPhysicalDeviceVulkan13Features dev_features_1_3 = { + .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_3_FEATURES, + .pNext = &timeline_features, + }; VkPhysicalDeviceVulkan12Features dev_features_1_2 = { .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_2_FEATURES, - .pNext = &timeline_features, + .pNext = &dev_features_1_3, }; VkPhysicalDeviceVulkan11Features dev_features_1_1 = { .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_1_FEATURES, @@ -1340,8 +1344,7 @@ static int vulkan_device_create_internal(AVHWDeviceContext *ctx, }; VkDeviceCreateInfo dev_info = { - .sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO, - .pNext = &hwctx->device_features, + .sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO, }; hwctx->device_features.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2; @@ -1349,6 +1352,8 @@ static int vulkan_device_create_internal(AVHWDeviceContext *ctx, 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; + p->device_features_1_2.pNext = &p->device_features_1_3; + p->device_features_1_3.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_3_FEATURES; ctx->free = vulkan_device_free; /* Create an instance if not given one */ @@ -1379,6 +1384,9 @@ static int vulkan_device_create_internal(AVHWDeviceContext *ctx, } p->device_features_1_2.timelineSemaphore = 1; p->device_features_1_1.samplerYcbcrConversion = dev_features_1_1.samplerYcbcrConversion; + p->device_features_1_3.synchronization2 = dev_features_1_3.synchronization2; + + dev_info.pNext = &hwctx->device_features; /* Setup queue family */ if ((err = setup_queue_families(ctx, &dev_info))) diff --git a/libavutil/vulkan_functions.h b/libavutil/vulkan_functions.h index deb77495a2f..b18d73b5bbf 100644 --- a/libavutil/vulkan_functions.h +++ b/libavutil/vulkan_functions.h @@ -145,7 +145,10 @@ typedef enum FFVulkanExtensions { 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) \ - \ + \ + /* sync2 */ \ + MACRO(1, 1, FF_VK_EXT_NO_FLAG, CmdPipelineBarrier2) \ + \ /* Pipeline */ \ MACRO(1, 1, FF_VK_EXT_NO_FLAG, CreatePipelineLayout) \ MACRO(1, 1, FF_VK_EXT_NO_FLAG, DestroyPipelineLayout) \ From 2a1fd2814f7c92a9c10b58ff584381da64a57189 Mon Sep 17 00:00:00 2001 From: Lynne Date: Sat, 29 Apr 2023 12:41:53 +0200 Subject: [PATCH 1237/2172] hwcontext_vulkan: use portability subset if available --- libavutil/hwcontext_vulkan.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/libavutil/hwcontext_vulkan.c b/libavutil/hwcontext_vulkan.c index ae28a110930..2434a800906 100644 --- a/libavutil/hwcontext_vulkan.c +++ b/libavutil/hwcontext_vulkan.c @@ -340,11 +340,13 @@ typedef struct VulkanOptExtension { } VulkanOptExtension; static const VulkanOptExtension optional_instance_exts[] = { - /* For future use */ + /* Pointless, here avoid zero-sized structs */ + { VK_KHR_PORTABILITY_ENUMERATION_EXTENSION_NAME, FF_VK_EXT_NO_FLAG }, }; static const VulkanOptExtension optional_device_exts[] = { /* Misc or required by other extensions */ + { VK_KHR_PORTABILITY_SUBSET_EXTENSION_NAME, FF_VK_EXT_NO_FLAG }, { VK_KHR_PUSH_DESCRIPTOR_EXTENSION_NAME, FF_VK_EXT_NO_FLAG }, { VK_KHR_SAMPLER_YCBCR_CONVERSION_EXTENSION_NAME, FF_VK_EXT_NO_FLAG }, From 46a77c6496a54d0079e6a2108a0dfffead861ac8 Mon Sep 17 00:00:00 2001 From: Lynne Date: Tue, 15 Mar 2022 23:00:32 +0100 Subject: [PATCH 1238/2172] hwcontext_vulkan: support threadsafe queue and frame operations --- libavutil/hwcontext_vulkan.c | 191 ++++++++++++++++++++++++++--------- libavutil/hwcontext_vulkan.h | 38 ++++++- 2 files changed, 180 insertions(+), 49 deletions(-) diff --git a/libavutil/hwcontext_vulkan.c b/libavutil/hwcontext_vulkan.c index 2434a800906..b511836b7bb 100644 --- a/libavutil/hwcontext_vulkan.c +++ b/libavutil/hwcontext_vulkan.c @@ -27,6 +27,7 @@ #include #endif +#include "thread.h" #include #include "config.h" @@ -92,8 +93,10 @@ typedef struct VulkanDevicePriv { VkPhysicalDeviceVulkan13Features device_features_1_3; /* Queues */ - uint32_t qfs[5]; - int num_qfs; + pthread_mutex_t **qf_mutex; + uint32_t nb_tot_qfs; + uint32_t img_qfs[5]; + uint32_t nb_img_qfs; /* Debug callback */ VkDebugUtilsMessengerEXT debug_ctx; @@ -127,6 +130,8 @@ typedef struct VulkanFramesPriv { } VulkanFramesPriv; typedef struct AVVkFrameInternal { + pthread_mutex_t update_mutex; + #if CONFIG_CUDA /* Importing external memory into cuda is really expensive so we keep the * memory imported all the time */ @@ -1305,6 +1310,12 @@ static void vulkan_device_free(AVHWDeviceContext *ctx) if (p->libvulkan) dlclose(p->libvulkan); + for (uint32_t i = 0; i < p->nb_tot_qfs; i++) { + pthread_mutex_destroy(p->qf_mutex[i]); + av_freep(&p->qf_mutex[i]); + } + av_freep(&p->qf_mutex); + RELEASE_PROPS(hwctx->enabled_inst_extensions, hwctx->nb_enabled_inst_extensions); RELEASE_PROPS(hwctx->enabled_dev_extensions, hwctx->nb_enabled_dev_extensions); } @@ -1437,13 +1448,26 @@ static int vulkan_device_create_internal(AVHWDeviceContext *ctx, return err; } +static void lock_queue(AVHWDeviceContext *ctx, uint32_t queue_family, uint32_t index) +{ + VulkanDevicePriv *p = ctx->internal->priv; + pthread_mutex_lock(&p->qf_mutex[queue_family][index]); +} + +static void unlock_queue(AVHWDeviceContext *ctx, uint32_t queue_family, uint32_t index) +{ + VulkanDevicePriv *p = ctx->internal->priv; + pthread_mutex_unlock(&p->qf_mutex[queue_family][index]); +} + static int vulkan_device_init(AVHWDeviceContext *ctx) { int err; - uint32_t queue_num; + uint32_t qf_num; AVVulkanDeviceContext *hwctx = ctx->hwctx; VulkanDevicePriv *p = ctx->internal->priv; FFVulkanFunctions *vk = &p->vkfn; + VkQueueFamilyProperties *qf; int graph_index, comp_index, tx_index, enc_index, dec_index; /* Set device extension flags */ @@ -1482,12 +1506,37 @@ static int vulkan_device_init(AVHWDeviceContext *ctx) 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) { + vk->GetPhysicalDeviceQueueFamilyProperties(hwctx->phys_dev, &qf_num, NULL); + if (!qf_num) { av_log(ctx, AV_LOG_ERROR, "Failed to get queues!\n"); return AVERROR_EXTERNAL; } + qf = av_malloc_array(qf_num, sizeof(VkQueueFamilyProperties)); + if (!qf) + return AVERROR(ENOMEM); + + vk->GetPhysicalDeviceQueueFamilyProperties(hwctx->phys_dev, &qf_num, qf); + + p->qf_mutex = av_calloc(qf_num, sizeof(*p->qf_mutex)); + if (!p->qf_mutex) + return AVERROR(ENOMEM); + p->nb_tot_qfs = qf_num; + + for (uint32_t i = 0; i < qf_num; i++) { + p->qf_mutex[i] = av_calloc(qf[i].queueCount, sizeof(**p->qf_mutex)); + if (!p->qf_mutex[i]) + return AVERROR(ENOMEM); + for (uint32_t j = 0; j < qf[i].queueCount; j++) { + err = pthread_mutex_init(&p->qf_mutex[i][j], NULL); + if (err != 0) { + av_log(ctx, AV_LOG_ERROR, "pthread_mutex_init failed : %s\n", + av_err2str(err)); + return AVERROR(err); + } + } + } + graph_index = hwctx->queue_family_index; comp_index = hwctx->queue_family_comp_index; tx_index = hwctx->queue_family_tx_index; @@ -1502,9 +1551,9 @@ static int vulkan_device_init(AVHWDeviceContext *ctx) return AVERROR(EINVAL); \ } else if (fidx < 0 || ctx_qf < 0) { \ break; \ - } else if (ctx_qf >= queue_num) { \ + } else if (ctx_qf >= qf_num) { \ av_log(ctx, AV_LOG_ERROR, "Invalid %s family index %i (device has %i families)!\n", \ - type, ctx_qf, queue_num); \ + type, ctx_qf, qf_num); \ return AVERROR(EINVAL); \ } \ \ @@ -1521,7 +1570,7 @@ static int vulkan_device_init(AVHWDeviceContext *ctx) 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; \ + p->img_qfs[p->nb_img_qfs++] = ctx_qf; \ } while (0) CHECK_QUEUE("graphics", 0, graph_index, hwctx->queue_family_index, hwctx->nb_graphics_queues); @@ -1532,6 +1581,11 @@ static int vulkan_device_init(AVHWDeviceContext *ctx) #undef CHECK_QUEUE + if (!hwctx->lock_queue) + hwctx->lock_queue = lock_queue; + if (!hwctx->unlock_queue) + hwctx->unlock_queue = unlock_queue; + /* Get device capabilities */ vk->GetPhysicalDeviceMemoryProperties(hwctx->phys_dev, &p->mprops); @@ -1733,9 +1787,6 @@ static void vulkan_free_internal(AVVkFrame *f) { AVVkFrameInternal *internal = f->internal; - if (!internal) - return; - #if CONFIG_CUDA if (internal->cuda_fc_ref) { AVHWFramesContext *cuda_fc = (AVHWFramesContext *)internal->cuda_fc_ref->data; @@ -1764,6 +1815,7 @@ static void vulkan_free_internal(AVVkFrame *f) } #endif + pthread_mutex_destroy(&internal->update_mutex); av_freep(&f->internal); } @@ -1924,9 +1976,11 @@ static int prepare_frame(AVHWFramesContext *hwfc, VulkanExecCtx *ectx, uint32_t src_qf, dst_qf; VkImageLayout new_layout; VkAccessFlags new_access; + AVVulkanFramesContext *vkfc = hwfc->hwctx; const int planes = av_pix_fmt_count_planes(hwfc->sw_format); VulkanDevicePriv *p = hwfc->device_ctx->internal->priv; FFVulkanFunctions *vk = &p->vkfn; + AVFrame tmp = { .data[0] = (uint8_t *)frame }; uint64_t sem_sig_val[AV_NUM_DATA_POINTERS]; VkImageMemoryBarrier img_bar[AV_NUM_DATA_POINTERS] = { 0 }; @@ -1945,6 +1999,12 @@ static int prepare_frame(AVHWFramesContext *hwfc, VulkanExecCtx *ectx, }; VkPipelineStageFlagBits wait_st[AV_NUM_DATA_POINTERS]; + + if ((err = wait_start_exec_ctx(hwfc, ectx))) + return err; + + vkfc->lock_frame(hwfc, frame); + 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; @@ -1981,9 +2041,6 @@ static int prepare_frame(AVHWFramesContext *hwfc, VulkanExecCtx *ectx, break; } - if ((err = wait_start_exec_ctx(hwfc, ectx))) - return err; - /* Change the image layout to something more optimal for writes. * This also signals the newly created semaphore, making it usable * for synchronization */ @@ -2009,7 +2066,10 @@ 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, frame, 0); + err = submit_exec_ctx(hwfc, ectx, &s_info, frame, 0); + vkfc->unlock_frame(hwfc, frame); + + return err; } static inline void get_plane_wh(int *w, int *h, enum AVPixelFormat format, @@ -2091,10 +2151,10 @@ static int create_frame(AVHWFramesContext *hwfc, AVVkFrame **frame, .initialLayout = VK_IMAGE_LAYOUT_UNDEFINED, .usage = usage, .samples = VK_SAMPLE_COUNT_1_BIT, - .pQueueFamilyIndices = p->qfs, - .queueFamilyIndexCount = p->num_qfs, - .sharingMode = p->num_qfs > 1 ? VK_SHARING_MODE_CONCURRENT : - VK_SHARING_MODE_EXCLUSIVE, + .pQueueFamilyIndices = p->img_qfs, + .queueFamilyIndexCount = p->nb_img_qfs, + .sharingMode = p->nb_img_qfs > 1 ? VK_SHARING_MODE_CONCURRENT : + VK_SHARING_MODE_EXCLUSIVE, }; get_plane_wh(&create_info.extent.width, &create_info.extent.height, @@ -2118,6 +2178,7 @@ static int create_frame(AVHWFramesContext *hwfc, AVVkFrame **frame, return AVERROR_EXTERNAL; } + f->queue_family[i] = p->nb_img_qfs > 1 ? VK_QUEUE_FAMILY_IGNORED : p->img_qfs[0]; f->layout[i] = create_info.initialLayout; f->access[i] = 0x0; f->sem_value[i] = 0; @@ -2162,10 +2223,10 @@ static void try_export_flags(AVHWFramesContext *hwfc, 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, + .pQueueFamilyIndices = p->img_qfs, + .queueFamilyIndexCount = p->nb_img_qfs, + .sharingMode = p->nb_img_qfs > 1 ? VK_SHARING_MODE_CONCURRENT : + VK_SHARING_MODE_EXCLUSIVE, }; VkPhysicalDeviceExternalImageFormatInfo enext = { .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_IMAGE_FORMAT_INFO, @@ -2260,6 +2321,16 @@ static AVBufferRef *vulkan_pool_alloc(void *opaque, size_t size) return NULL; } +static void lock_frame(AVHWFramesContext *fc, AVVkFrame *vkf) +{ + pthread_mutex_lock(&vkf->internal->update_mutex); +} + +static void unlock_frame(AVHWFramesContext *fc, AVVkFrame *vkf) +{ + pthread_mutex_unlock(&vkf->internal->update_mutex); +} + static void vulkan_frames_uninit(AVHWFramesContext *hwfc) { VulkanFramesPriv *fp = hwfc->internal->priv; @@ -2422,6 +2493,11 @@ static int vulkan_frames_init(AVHWFramesContext *hwfc) return AVERROR(ENOMEM); } + if (!hwctx->lock_frame) + hwctx->lock_frame = lock_frame; + if (!hwctx->unlock_frame) + hwctx->unlock_frame = unlock_frame; + return 0; } @@ -2728,10 +2804,10 @@ static int vulkan_map_from_drm_frame_desc(AVHWFramesContext *hwfc, AVVkFrame **f .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, - .sharingMode = p->num_qfs > 1 ? VK_SHARING_MODE_CONCURRENT : - VK_SHARING_MODE_EXCLUSIVE, + .pQueueFamilyIndices = p->img_qfs, + .queueFamilyIndexCount = p->nb_img_qfs, + .sharingMode = p->nb_img_qfs > 1 ? VK_SHARING_MODE_CONCURRENT : + VK_SHARING_MODE_EXCLUSIVE, }; /* Image format verification */ @@ -2810,6 +2886,7 @@ static int vulkan_map_from_drm_frame_desc(AVHWFramesContext *hwfc, AVVkFrame **f * offer us anything we could import and sync with, so instead * just signal the semaphore we created. */ + f->queue_family[i] = p->nb_img_qfs > 1 ? VK_QUEUE_FAMILY_IGNORED : p->img_qfs[0]; f->layout[i] = create_info.initialLayout; f->access[i] = 0x0; f->sem_value[i] = 0; @@ -3018,20 +3095,12 @@ static int vulkan_export_to_cuda(AVHWFramesContext *hwfc, CU_AD_FORMAT_UNSIGNED_INT8; dst_f = (AVVkFrame *)frame->data[0]; - dst_int = dst_f->internal; - if (!dst_int || !dst_int->cuda_fc_ref) { - if (!dst_f->internal) - dst_f->internal = dst_int = av_mallocz(sizeof(*dst_f->internal)); - - if (!dst_int) - return AVERROR(ENOMEM); + if (!dst_int->cuda_fc_ref) { dst_int->cuda_fc_ref = av_buffer_ref(cuda_hwfc); - if (!dst_int->cuda_fc_ref) { - av_freep(&dst_f->internal); + if (!dst_int->cuda_fc_ref) return AVERROR(ENOMEM); - } for (int i = 0; i < planes; i++) { CUDA_EXTERNAL_MEMORY_MIPMAPPED_ARRAY_DESC tex_desc = { @@ -3705,13 +3774,14 @@ static int unmap_buffers(AVHWDeviceContext *ctx, AVBufferRef **bufs, return err; } -static int transfer_image_buf(AVHWFramesContext *hwfc, const AVFrame *f, +static int transfer_image_buf(AVHWFramesContext *hwfc, AVFrame *f, AVBufferRef **bufs, size_t *buf_offsets, const int *buf_stride, int w, int h, enum AVPixelFormat pix_fmt, int to_buf) { int err; AVVkFrame *frame = (AVVkFrame *)f->data[0]; + AVVulkanFramesContext *vkfc = hwfc->hwctx; VulkanFramesPriv *fp = hwfc->internal->priv; VulkanDevicePriv *p = hwfc->device_ctx->internal->priv; FFVulkanFunctions *vk = &p->vkfn; @@ -3746,11 +3816,13 @@ 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; + vkfc->lock_frame(hwfc, frame); if ((err = wait_start_exec_ctx(hwfc, ectx))) - return err; + goto end; + + for (int i = 0; i < planes; i++) + sem_signal_values[i] = frame->sem_value[i] + 1; /* Change the image layout to something more optimal for transfers */ for (int i = 0; i < planes; i++) { @@ -3825,14 +3897,18 @@ static int transfer_image_buf(AVHWFramesContext *hwfc, const AVFrame *f, if (!f->buf[ref]) break; if ((err = add_buf_dep_exec_ctx(hwfc, ectx, &f->buf[ref], 1))) - return err; + goto end; } if (ref && (err = add_buf_dep_exec_ctx(hwfc, ectx, bufs, planes))) - return err; - return submit_exec_ctx(hwfc, ectx, &s_info, frame, !ref); + goto end; + err = submit_exec_ctx(hwfc, ectx, &s_info, frame, !ref); } else { - return submit_exec_ctx(hwfc, ectx, &s_info, frame, 1); + err = submit_exec_ctx(hwfc, ectx, &s_info, frame, 1); } + +end: + vkfc->unlock_frame(hwfc, frame); + return err; } static int vulkan_transfer_data(AVHWFramesContext *hwfc, const AVFrame *vkf, @@ -3961,8 +4037,9 @@ static int vulkan_transfer_data(AVHWFramesContext *hwfc, const AVFrame *vkf, } /* Copy buffers into/from image */ - err = transfer_image_buf(hwfc, vkf, bufs, buf_offsets, tmp.linesize, - swf->width, swf->height, swf->format, from); + err = transfer_image_buf(hwfc, (AVFrame *)vkf, bufs, buf_offsets, + tmp.linesize, swf->width, swf->height, swf->format, + from); if (from) { /* Map, copy buffer (which came FROM the VkImage) to the frame, unmap */ @@ -4143,7 +4220,25 @@ static int vulkan_frames_derive_to(AVHWFramesContext *dst_fc, AVVkFrame *av_vk_frame_alloc(void) { - return av_mallocz(sizeof(AVVkFrame)); + int err; + AVVkFrame *f = av_mallocz(sizeof(AVVkFrame)); + if (!f) + return NULL; + + f->internal = av_mallocz(sizeof(*f->internal)); + if (!f->internal) { + av_free(f); + return NULL; + } + + err = pthread_mutex_init(&f->internal->update_mutex, NULL); + if (err != 0) { + av_free(f->internal); + av_free(f); + return NULL; + } + + return f; } const HWContextType ff_hwcontext_type_vulkan = { diff --git a/libavutil/hwcontext_vulkan.h b/libavutil/hwcontext_vulkan.h index 70c8379dc36..9fbf4b2160d 100644 --- a/libavutil/hwcontext_vulkan.h +++ b/libavutil/hwcontext_vulkan.h @@ -27,6 +27,8 @@ #include "pixfmt.h" #include "frame.h" +typedef struct AVVkFrame AVVkFrame; + /** * @file * API-specific header for AV_HWDEVICE_TYPE_VULKAN. @@ -135,6 +137,19 @@ typedef struct AVVulkanDeviceContext { */ int queue_family_decode_index; int nb_decode_queues; + + /** + * Locks a queue, preventing other threads from submitting any command + * buffers to this queue. + * If set to NULL, will be set to lavu-internal functions that utilize a + * mutex. + */ + void (*lock_queue)(struct AVHWDeviceContext *ctx, uint32_t queue_family, uint32_t index); + + /** + * Similar to lock_queue(), unlocks a queue. Must only be called after locking. + */ + void (*unlock_queue)(struct AVHWDeviceContext *ctx, uint32_t queue_family, uint32_t index); } AVVulkanDeviceContext; /** @@ -195,6 +210,21 @@ typedef struct AVVulkanFramesContext { * av_hwframe_ctx_init(). */ AVVkFrameFlags flags; + + /** + * Locks a frame, preventing other threads from changing frame properties. + * Users SHOULD only ever lock just before command submission in order + * to get accurate frame properties, and unlock immediately after command + * submission without waiting for it to finish. + * + * If unset, will be set to lavu-internal functions that utilize a mutex. + */ + void (*lock_frame)(struct AVHWFramesContext *fc, AVVkFrame *vkf); + + /** + * Similar to lock_frame(), unlocks a frame. Must only be called after locking. + */ + void (*unlock_frame)(struct AVHWFramesContext *fc, AVVkFrame *vkf); } AVVulkanFramesContext; /* @@ -210,7 +240,7 @@ typedef struct AVVulkanFramesContext { * @note the size of this structure is not part of the ABI, to allocate * you must use @av_vk_frame_alloc(). */ -typedef struct AVVkFrame { +struct AVVkFrame { /** * Vulkan images to which the memory is bound to. */ @@ -264,6 +294,12 @@ typedef struct AVVkFrame { * Describes the binding offset of each plane to the VkDeviceMemory. */ ptrdiff_t offset[AV_NUM_DATA_POINTERS]; + + /** + * Queue family of the images. Must be VK_QUEUE_FAMILY_IGNORED if + * the image was allocated with the CONCURRENT concurrency option. + */ + uint32_t queue_family[AV_NUM_DATA_POINTERS]; } AVVkFrame; /** From e0f2d2e70228d022195afccc057bd6dc8b688c21 Mon Sep 17 00:00:00 2001 From: Lynne Date: Wed, 23 Nov 2022 20:32:49 +0100 Subject: [PATCH 1239/2172] hwcontext_vulkan: remove contiguous memory path/mode The hack was added to enable exporting of vulkan images to DRM. On Intel hardware, specifically for DRM images, all planes must be allocated next to each other, due to hardware limitation, so the hack used a single large allocation and suballocated all planes from it. By natively supporting multiplane images, the driver is what decides the layout, so exporting just works. It's a hack because it conflicted heavily with image allocation, and with the whole ecosystem in general, before multiplane images were supported, which just made it redundant. This is also the commit which broke the hwcontext hardest and prompted the entire rewrite in the first place. --- libavutil/hwcontext_vulkan.c | 12 ------------ libavutil/hwcontext_vulkan.h | 6 +++--- libavutil/version.h | 1 + 3 files changed, 4 insertions(+), 15 deletions(-) diff --git a/libavutil/hwcontext_vulkan.c b/libavutil/hwcontext_vulkan.c index b511836b7bb..9eb872ca783 100644 --- a/libavutil/hwcontext_vulkan.c +++ b/libavutil/hwcontext_vulkan.c @@ -112,9 +112,6 @@ typedef struct VulkanDevicePriv { /* Nvidia */ int dev_is_nvidia; - - /* Intel */ - int dev_is_intel; } VulkanDevicePriv; typedef struct VulkanFramesPriv { @@ -1504,7 +1501,6 @@ 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, &qf_num, NULL); if (!qf_num) { @@ -1629,8 +1625,6 @@ static int vulkan_device_derive(AVHWDeviceContext *ctx, return AVERROR_EXTERNAL; } - if (strstr(vendor, "Intel")) - dev_select.vendor_id = 0x8086; if (strstr(vendor, "AMD")) dev_select.vendor_id = 0x1002; @@ -2366,12 +2360,6 @@ 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; - } - modifier_info = vk_find_struct(hwctx->create_pnext, VK_STRUCTURE_TYPE_IMAGE_DRM_FORMAT_MODIFIER_LIST_CREATE_INFO_EXT); diff --git a/libavutil/hwcontext_vulkan.h b/libavutil/hwcontext_vulkan.h index 9fbf4b2160d..60254b24063 100644 --- a/libavutil/hwcontext_vulkan.h +++ b/libavutil/hwcontext_vulkan.h @@ -160,10 +160,10 @@ typedef enum AVVkFrameFlags { * 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. */ +#if FF_API_VULKAN_CONTIGUOUS_MEMORY + /* DEPRECATED: does nothing. Replaced by multiplane images. */ AV_VK_FRAME_FLAG_CONTIGUOUS_MEMORY = (1ULL << 1), +#endif } AVVkFrameFlags; /** diff --git a/libavutil/version.h b/libavutil/version.h index 8c7ea1a47a6..fa53fae768e 100644 --- a/libavutil/version.h +++ b/libavutil/version.h @@ -118,6 +118,7 @@ #define FF_API_INTERLACED_FRAME (LIBAVUTIL_VERSION_MAJOR < 59) #define FF_API_FRAME_KEY (LIBAVUTIL_VERSION_MAJOR < 59) #define FF_API_PALETTE_HAS_CHANGED (LIBAVUTIL_VERSION_MAJOR < 59) +#define FF_API_VULKAN_CONTIGUOUS_MEMORY (LIBAVUTIL_VERSION_MAJOR < 59) /** * @} From 211c910aca6f1be57a73849a923a3a12863a82f4 Mon Sep 17 00:00:00 2001 From: Lynne Date: Wed, 23 Nov 2022 20:35:51 +0100 Subject: [PATCH 1240/2172] hwcontext_vulkan: rename and expand vk_pixfmt_map to append VK_NULL_FORMAT --- libavutil/hwcontext_vulkan.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/libavutil/hwcontext_vulkan.c b/libavutil/hwcontext_vulkan.c index 9eb872ca783..82790cb014c 100644 --- a/libavutil/hwcontext_vulkan.c +++ b/libavutil/hwcontext_vulkan.c @@ -167,8 +167,8 @@ typedef struct AVVkFrameInternal { static const struct { enum AVPixelFormat pixfmt; - const VkFormat vkfmts[4]; -} vk_pixfmt_map[] = { + const VkFormat vkfmts[5]; +} vk_pixfmt_planar_map[] = { { AV_PIX_FMT_GRAY8, { VK_FORMAT_R8_UNORM } }, { AV_PIX_FMT_GRAY16, { VK_FORMAT_R16_UNORM } }, { AV_PIX_FMT_GRAYF32, { VK_FORMAT_R32_SFLOAT } }, @@ -244,9 +244,9 @@ static const struct { const VkFormat *av_vkfmt_from_pixfmt(enum AVPixelFormat p) { - for (enum AVPixelFormat i = 0; i < FF_ARRAY_ELEMS(vk_pixfmt_map); i++) - if (vk_pixfmt_map[i].pixfmt == p) - return vk_pixfmt_map[i].vkfmts; + for (enum AVPixelFormat i = 0; i < FF_ARRAY_ELEMS(vk_pixfmt_planar_map); i++) + if (vk_pixfmt_planar_map[i].pixfmt == p) + return vk_pixfmt_planar_map[i].vkfmts; return NULL; } From b0af92572fe55a1b396a19a673dfa9ee5d986c2e Mon Sep 17 00:00:00 2001 From: Lynne Date: Wed, 14 Dec 2022 00:52:15 +0100 Subject: [PATCH 1241/2172] hwcontext_vulkan: fix minor type issue in VulkanQueueCtx.buf_deps_alloc_size --- 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 82790cb014c..f796cbd689c 100644 --- a/libavutil/hwcontext_vulkan.c +++ b/libavutil/hwcontext_vulkan.c @@ -66,7 +66,7 @@ typedef struct VulkanQueueCtx { /* Buffer dependencies */ AVBufferRef **buf_deps; int nb_buf_deps; - int buf_deps_alloc_size; + unsigned int buf_deps_alloc_size; } VulkanQueueCtx; typedef struct VulkanExecCtx { From c5702abf71d3edf41cbde7bf37093788bba183ee Mon Sep 17 00:00:00 2001 From: Lynne Date: Wed, 28 Dec 2022 05:55:17 +0100 Subject: [PATCH 1242/2172] hwcontext_vulkan: report nonCoherentAtomSize --- libavutil/hwcontext_vulkan.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/libavutil/hwcontext_vulkan.c b/libavutil/hwcontext_vulkan.c index f796cbd689c..8f80cc8e21d 100644 --- a/libavutil/hwcontext_vulkan.c +++ b/libavutil/hwcontext_vulkan.c @@ -1496,6 +1496,8 @@ 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); + av_log(ctx, AV_LOG_VERBOSE, " nonCoherentAtomSize: %"PRIu64"\n", + p->props.properties.limits.nonCoherentAtomSize); if (p->extensions & FF_VK_EXT_EXTERNAL_HOST_MEMORY) av_log(ctx, AV_LOG_VERBOSE, " minImportedHostPointerAlignment: %"PRIu64"\n", p->hprops.minImportedHostPointerAlignment); From f50bc930a4fc83c7b222fcbf97e05ff9f6096c8b Mon Sep 17 00:00:00 2001 From: Lynne Date: Fri, 17 Feb 2023 03:15:02 +0100 Subject: [PATCH 1243/2172] hwcontext_vulkan: add support for descriptor buffers --- libavutil/hwcontext_vulkan.c | 13 ++++++++++++- libavutil/vulkan_functions.h | 9 +++++++++ libavutil/vulkan_loader.h | 1 + 3 files changed, 22 insertions(+), 1 deletion(-) diff --git a/libavutil/hwcontext_vulkan.c b/libavutil/hwcontext_vulkan.c index 8f80cc8e21d..e68c4e3535f 100644 --- a/libavutil/hwcontext_vulkan.c +++ b/libavutil/hwcontext_vulkan.c @@ -91,6 +91,7 @@ typedef struct VulkanDevicePriv { VkPhysicalDeviceVulkan11Features device_features_1_1; VkPhysicalDeviceVulkan12Features device_features_1_2; VkPhysicalDeviceVulkan13Features device_features_1_3; + VkPhysicalDeviceDescriptorBufferFeaturesEXT desc_buf_features; /* Queues */ pthread_mutex_t **qf_mutex; @@ -351,6 +352,7 @@ static const VulkanOptExtension optional_device_exts[] = { { VK_KHR_PORTABILITY_SUBSET_EXTENSION_NAME, FF_VK_EXT_NO_FLAG }, { VK_KHR_PUSH_DESCRIPTOR_EXTENSION_NAME, FF_VK_EXT_NO_FLAG }, { VK_KHR_SAMPLER_YCBCR_CONVERSION_EXTENSION_NAME, FF_VK_EXT_NO_FLAG }, + { VK_EXT_DESCRIPTOR_BUFFER_EXTENSION_NAME, FF_VK_EXT_DESCRIPTOR_BUFFER, }, /* Imports/exports */ { VK_KHR_EXTERNAL_MEMORY_FD_EXTENSION_NAME, FF_VK_EXT_EXTERNAL_FD_MEMORY }, @@ -1336,9 +1338,13 @@ static int vulkan_device_create_internal(AVHWDeviceContext *ctx, VkPhysicalDeviceTimelineSemaphoreFeatures timeline_features = { .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TIMELINE_SEMAPHORE_FEATURES, }; + VkPhysicalDeviceDescriptorBufferFeaturesEXT desc_buf_features = { + .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DESCRIPTOR_BUFFER_FEATURES_EXT, + .pNext = &timeline_features, + }; VkPhysicalDeviceVulkan13Features dev_features_1_3 = { .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_3_FEATURES, - .pNext = &timeline_features, + .pNext = &desc_buf_features, }; VkPhysicalDeviceVulkan12Features dev_features_1_2 = { .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_2_FEATURES, @@ -1364,6 +1370,8 @@ static int vulkan_device_create_internal(AVHWDeviceContext *ctx, p->device_features_1_2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_2_FEATURES; p->device_features_1_2.pNext = &p->device_features_1_3; p->device_features_1_3.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_3_FEATURES; + p->device_features_1_3.pNext = &p->desc_buf_features; + p->desc_buf_features.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DESCRIPTOR_BUFFER_FEATURES_EXT; ctx->free = vulkan_device_free; /* Create an instance if not given one */ @@ -1393,8 +1401,11 @@ static int vulkan_device_create_internal(AVHWDeviceContext *ctx, goto end; } p->device_features_1_2.timelineSemaphore = 1; + p->device_features_1_2.bufferDeviceAddress = dev_features_1_2.bufferDeviceAddress; p->device_features_1_1.samplerYcbcrConversion = dev_features_1_1.samplerYcbcrConversion; p->device_features_1_3.synchronization2 = dev_features_1_3.synchronization2; + p->desc_buf_features.descriptorBuffer = desc_buf_features.descriptorBuffer; + p->desc_buf_features.descriptorBufferPushDescriptors = desc_buf_features.descriptorBufferPushDescriptors; dev_info.pNext = &hwctx->device_features; diff --git a/libavutil/vulkan_functions.h b/libavutil/vulkan_functions.h index b18d73b5bbf..4eccdad3c41 100644 --- a/libavutil/vulkan_functions.h +++ b/libavutil/vulkan_functions.h @@ -37,6 +37,7 @@ typedef enum FFVulkanExtensions { 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_DESCRIPTOR_BUFFER = 1ULL << 8, /* VK_EXT_descriptor_buffer */ FF_VK_EXT_NO_FLAG = 1ULL << 31, } FFVulkanExtensions; @@ -120,6 +121,7 @@ typedef enum FFVulkanExtensions { 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, GetBufferDeviceAddress) \ MACRO(1, 1, FF_VK_EXT_NO_FLAG, DestroyBuffer) \ \ /* Image */ \ @@ -141,6 +143,13 @@ typedef enum FFVulkanExtensions { MACRO(1, 1, FF_VK_EXT_NO_FLAG, DestroyDescriptorPool) \ MACRO(1, 1, FF_VK_EXT_NO_FLAG, DestroyDescriptorSetLayout) \ \ + /* Descriptor buffers */ \ + MACRO(1, 1, FF_VK_EXT_DESCRIPTOR_BUFFER, GetDescriptorSetLayoutSizeEXT) \ + MACRO(1, 1, FF_VK_EXT_DESCRIPTOR_BUFFER, GetDescriptorSetLayoutBindingOffsetEXT) \ + MACRO(1, 1, FF_VK_EXT_DESCRIPTOR_BUFFER, GetDescriptorEXT) \ + MACRO(1, 1, FF_VK_EXT_DESCRIPTOR_BUFFER, CmdBindDescriptorBuffersEXT) \ + MACRO(1, 1, FF_VK_EXT_DESCRIPTOR_BUFFER, CmdSetDescriptorBufferOffsetsEXT) \ + \ /* DescriptorUpdateTemplate */ \ MACRO(1, 1, FF_VK_EXT_NO_FLAG, UpdateDescriptorSetWithTemplate) \ MACRO(1, 1, FF_VK_EXT_NO_FLAG, CreateDescriptorUpdateTemplate) \ diff --git a/libavutil/vulkan_loader.h b/libavutil/vulkan_loader.h index 3f1ee6aa467..e08777db177 100644 --- a/libavutil/vulkan_loader.h +++ b/libavutil/vulkan_loader.h @@ -48,6 +48,7 @@ static inline uint64_t ff_vk_extensions_to_mask(const char * const *extensions, { 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 + { VK_EXT_DESCRIPTOR_BUFFER_EXTENSION_NAME, FF_VK_EXT_DESCRIPTOR_BUFFER, }, }; FFVulkanExtensions mask = 0x0; From e11fd1abdba10df572e9ef0281068983c024ba8e Mon Sep 17 00:00:00 2001 From: Lynne Date: Tue, 14 Mar 2023 22:10:05 +0100 Subject: [PATCH 1244/2172] hwcontext_vulkan: do not require libdrm to map VAAPI devices VAAPI is sadly on the way of becoming multiplaform. --- libavutil/hwcontext_vulkan.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/libavutil/hwcontext_vulkan.c b/libavutil/hwcontext_vulkan.c index e68c4e3535f..7051c5dda84 100644 --- a/libavutil/hwcontext_vulkan.c +++ b/libavutil/hwcontext_vulkan.c @@ -42,14 +42,17 @@ #include "vulkan.h" #include "vulkan_loader.h" +#if CONFIG_VAAPI +#include "hwcontext_vaapi.h" +#endif + #if CONFIG_LIBDRM -#include -#include -#include "hwcontext_drm.h" #if CONFIG_VAAPI #include -#include "hwcontext_vaapi.h" #endif +#include +#include +#include "hwcontext_drm.h" #endif #if CONFIG_CUDA @@ -1627,7 +1630,6 @@ static int vulkan_device_derive(AVHWDeviceContext *ctx, * by the following checks (e.g. non-PCIe ARM GPU), having an empty * dev_select will mean it'll get picked. */ switch(src_ctx->type) { -#if CONFIG_LIBDRM #if CONFIG_VAAPI case AV_HWDEVICE_TYPE_VAAPI: { AVVAAPIDeviceContext *src_hwctx = src_ctx->hwctx; @@ -1644,6 +1646,7 @@ static int vulkan_device_derive(AVHWDeviceContext *ctx, return vulkan_device_create_internal(ctx, &dev_select, opts, flags); } #endif +#if CONFIG_LIBDRM case AV_HWDEVICE_TYPE_DRM: { AVDRMDeviceContext *src_hwctx = src_ctx->hwctx; From 571756bf2fe255a4108360c305cae94866bd6e9f Mon Sep 17 00:00:00 2001 From: Lynne Date: Tue, 14 Mar 2023 22:30:18 +0100 Subject: [PATCH 1245/2172] hwcontext_vulkan: use VK_EXT_physical_device_drm to derive DRM to Vulkan Finally, a way to directly identify a Vulkan device from a DRM device! --- libavutil/hwcontext_vulkan.c | 58 ++++++++++++++++++++++++++++++++---- libavutil/vulkan_functions.h | 1 + libavutil/vulkan_loader.h | 1 + 3 files changed, 55 insertions(+), 5 deletions(-) diff --git a/libavutil/hwcontext_vulkan.c b/libavutil/hwcontext_vulkan.c index 7051c5dda84..8cb55b98cc0 100644 --- a/libavutil/hwcontext_vulkan.c +++ b/libavutil/hwcontext_vulkan.c @@ -50,6 +50,8 @@ #if CONFIG_VAAPI #include #endif +#include +#include #include #include #include "hwcontext_drm.h" @@ -356,6 +358,7 @@ static const VulkanOptExtension optional_device_exts[] = { { VK_KHR_PUSH_DESCRIPTOR_EXTENSION_NAME, FF_VK_EXT_NO_FLAG }, { VK_KHR_SAMPLER_YCBCR_CONVERSION_EXTENSION_NAME, FF_VK_EXT_NO_FLAG }, { VK_EXT_DESCRIPTOR_BUFFER_EXTENSION_NAME, FF_VK_EXT_DESCRIPTOR_BUFFER, }, + { VK_EXT_PHYSICAL_DEVICE_DRM_EXTENSION_NAME, FF_VK_EXT_DEVICE_DRM }, /* Imports/exports */ { VK_KHR_EXTERNAL_MEMORY_FD_EXTENSION_NAME, FF_VK_EXT_EXTERNAL_FD_MEMORY }, @@ -762,8 +765,11 @@ static int create_instance(AVHWDeviceContext *ctx, AVDictionary *opts) typedef struct VulkanDeviceSelection { uint8_t uuid[VK_UUID_SIZE]; /* Will use this first unless !has_uuid */ int has_uuid; - const char *name; /* Will use this second unless NULL */ - uint32_t pci_device; /* Will use this third unless 0x0 */ + uint32_t drm_major; /* Will use this second unless !has_drm */ + uint32_t drm_minor; /* Will use this second unless !has_drm */ + uint32_t has_drm; /* has drm node info */ + const char *name; /* Will use this third unless NULL */ + uint32_t pci_device; /* Will use this fourth unless 0x0 */ uint32_t vendor_id; /* Last resort to find something deterministic */ int index; /* Finally fall back to index */ } VulkanDeviceSelection; @@ -790,6 +796,7 @@ static int find_device(AVHWDeviceContext *ctx, VulkanDeviceSelection *select) VkPhysicalDevice *devices = NULL; VkPhysicalDeviceIDProperties *idp = NULL; VkPhysicalDeviceProperties2 *prop = NULL; + VkPhysicalDeviceDrmPropertiesEXT *drm_prop = NULL; AVVulkanDeviceContext *hwctx = ctx->hwctx; ret = vk->EnumeratePhysicalDevices(hwctx->inst, &num, NULL); @@ -822,8 +829,20 @@ static int find_device(AVHWDeviceContext *ctx, VulkanDeviceSelection *select) goto end; } + if (p->vkctx.extensions & FF_VK_EXT_DEVICE_DRM) { + drm_prop = av_calloc(num, sizeof(*drm_prop)); + if (!drm_prop) { + err = AVERROR(ENOMEM); + goto end; + } + } + av_log(ctx, AV_LOG_VERBOSE, "GPU listing:\n"); for (int i = 0; i < num; i++) { + if (p->vkctx.extensions & FF_VK_EXT_DEVICE_DRM) { + drm_prop[i].sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DRM_PROPERTIES_EXT; + idp[i].pNext = &drm_prop[i]; + } idp[i].sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ID_PROPERTIES; prop[i].sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2; prop[i].pNext = &idp[i]; @@ -845,6 +864,20 @@ static int find_device(AVHWDeviceContext *ctx, VulkanDeviceSelection *select) av_log(ctx, AV_LOG_ERROR, "Unable to find device by given UUID!\n"); err = AVERROR(ENODEV); goto end; + } else if ((p->vkctx.extensions & FF_VK_EXT_DEVICE_DRM) && select->has_drm) { + for (int i = 0; i < num; i++) { + if ((select->drm_major == drm_prop[i].primaryMajor && + select->drm_minor == drm_prop[i].primaryMinor) || + (select->drm_major == drm_prop[i].renderMajor && + select->drm_minor == drm_prop[i].renderMinor)) { + choice = i; + goto end; + } + } + av_log(ctx, AV_LOG_ERROR, "Unable to find device by given DRM node numbers %i:%i!\n", + select->drm_major, select->drm_minor); + err = AVERROR(ENODEV); + goto end; } else if (select->name) { av_log(ctx, AV_LOG_VERBOSE, "Requested device: %s\n", select->name); for (int i = 0; i < num; i++) { @@ -904,6 +937,7 @@ static int find_device(AVHWDeviceContext *ctx, VulkanDeviceSelection *select) av_free(devices); av_free(prop); av_free(idp); + av_free(drm_prop); return err; } @@ -1648,12 +1682,26 @@ static int vulkan_device_derive(AVHWDeviceContext *ctx, #endif #if CONFIG_LIBDRM case AV_HWDEVICE_TYPE_DRM: { + int err; + struct stat drm_node_info; + drmDevice *drm_dev_info; AVDRMDeviceContext *src_hwctx = src_ctx->hwctx; - drmDevice *drm_dev_info; - int err = drmGetDevice(src_hwctx->fd, &drm_dev_info); + err = fstat(src_hwctx->fd, &drm_node_info); + if (err) { + av_log(ctx, AV_LOG_ERROR, "Unable to get node info from DRM fd: %s!\n", + av_err2str(AVERROR(errno))); + return AVERROR_EXTERNAL; + } + + dev_select.drm_major = major(drm_node_info.st_dev); + dev_select.drm_minor = minor(drm_node_info.st_dev); + dev_select.has_drm = 1; + + err = drmGetDevice(src_hwctx->fd, &drm_dev_info); if (err) { - av_log(ctx, AV_LOG_ERROR, "Unable to get device info from DRM fd!\n"); + av_log(ctx, AV_LOG_ERROR, "Unable to get device info from DRM fd: %s!\n", + av_err2str(AVERROR(errno))); return AVERROR_EXTERNAL; } diff --git a/libavutil/vulkan_functions.h b/libavutil/vulkan_functions.h index 4eccdad3c41..ee0adf427ca 100644 --- a/libavutil/vulkan_functions.h +++ b/libavutil/vulkan_functions.h @@ -38,6 +38,7 @@ typedef enum FFVulkanExtensions { FF_VK_EXT_EXTERNAL_WIN32_SEM = 1ULL << 7, /* VK_KHR_external_semaphore_win32 */ #endif FF_VK_EXT_DESCRIPTOR_BUFFER = 1ULL << 8, /* VK_EXT_descriptor_buffer */ + FF_VK_EXT_DEVICE_DRM = 1ULL << 9, /* VK_EXT_physical_device_drm */ FF_VK_EXT_NO_FLAG = 1ULL << 31, } FFVulkanExtensions; diff --git a/libavutil/vulkan_loader.h b/libavutil/vulkan_loader.h index e08777db177..2e6dfb4f4f5 100644 --- a/libavutil/vulkan_loader.h +++ b/libavutil/vulkan_loader.h @@ -44,6 +44,7 @@ static inline uint64_t ff_vk_extensions_to_mask(const char * const *extensions, { 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_PHYSICAL_DEVICE_DRM_EXTENSION_NAME, FF_VK_EXT_DEVICE_DRM }, #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 }, From 6dfa29a58dbac9662e330617a09a09461fbc2560 Mon Sep 17 00:00:00 2001 From: Lynne Date: Wed, 23 Nov 2022 13:34:36 +0100 Subject: [PATCH 1246/2172] hwcontext_vulkan: add functions for video decoding --- libavutil/hwcontext_vulkan.c | 6 ++++++ libavutil/vulkan.c | 8 +++++--- libavutil/vulkan_functions.h | 20 ++++++++++++++++++++ libavutil/vulkan_loader.h | 4 ++++ 4 files changed, 35 insertions(+), 3 deletions(-) diff --git a/libavutil/hwcontext_vulkan.c b/libavutil/hwcontext_vulkan.c index 8cb55b98cc0..97845ec8248 100644 --- a/libavutil/hwcontext_vulkan.c +++ b/libavutil/hwcontext_vulkan.c @@ -370,6 +370,12 @@ static const VulkanOptExtension optional_device_exts[] = { { 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_VIDEO_QUEUE }, + { VK_KHR_VIDEO_DECODE_QUEUE_EXTENSION_NAME, FF_VK_EXT_VIDEO_DECODE_QUEUE }, + { VK_KHR_VIDEO_DECODE_H264_EXTENSION_NAME, FF_VK_EXT_VIDEO_DECODE_H264 }, + { VK_KHR_VIDEO_DECODE_H265_EXTENSION_NAME, FF_VK_EXT_VIDEO_DECODE_H265 }, }; /* Converts return values to strings */ diff --git a/libavutil/vulkan.c b/libavutil/vulkan.c index 403f0b1f276..6bf2c214b70 100644 --- a/libavutil/vulkan.c +++ b/libavutil/vulkan.c @@ -85,9 +85,11 @@ const char *ff_vk_ret2str(VkResult res) 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); + CASE(VK_ERROR_VIDEO_PICTURE_LAYOUT_NOT_SUPPORTED_KHR); + CASE(VK_ERROR_VIDEO_PROFILE_OPERATION_NOT_SUPPORTED_KHR); + CASE(VK_ERROR_VIDEO_PROFILE_FORMAT_NOT_SUPPORTED_KHR); + CASE(VK_ERROR_VIDEO_PROFILE_CODEC_NOT_SUPPORTED_KHR); + CASE(VK_ERROR_VIDEO_STD_VERSION_NOT_SUPPORTED_KHR); default: return "Unknown error"; } #undef CASE diff --git a/libavutil/vulkan_functions.h b/libavutil/vulkan_functions.h index ee0adf427ca..403382fe7f2 100644 --- a/libavutil/vulkan_functions.h +++ b/libavutil/vulkan_functions.h @@ -39,6 +39,10 @@ typedef enum FFVulkanExtensions { #endif FF_VK_EXT_DESCRIPTOR_BUFFER = 1ULL << 8, /* VK_EXT_descriptor_buffer */ FF_VK_EXT_DEVICE_DRM = 1ULL << 9, /* VK_EXT_physical_device_drm */ + FF_VK_EXT_VIDEO_QUEUE = 1ULL << 10, /* VK_KHR_video_queue */ + FF_VK_EXT_VIDEO_DECODE_QUEUE = 1ULL << 11, /* VK_KHR_video_decode_queue */ + FF_VK_EXT_VIDEO_DECODE_H264 = 1ULL << 12, /* VK_EXT_video_decode_h264 */ + FF_VK_EXT_VIDEO_DECODE_H265 = 1ULL << 13, /* VK_EXT_video_decode_h265 */ FF_VK_EXT_NO_FLAG = 1ULL << 31, } FFVulkanExtensions; @@ -60,6 +64,8 @@ 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_VIDEO_QUEUE, GetPhysicalDeviceVideoCapabilitiesKHR) \ + MACRO(1, 0, FF_VK_EXT_VIDEO_QUEUE, GetPhysicalDeviceVideoFormatPropertiesKHR) \ MACRO(1, 0, FF_VK_EXT_NO_FLAG, DeviceWaitIdle) \ MACRO(1, 0, FF_VK_EXT_NO_FLAG, DestroyDevice) \ \ @@ -159,6 +165,20 @@ typedef enum FFVulkanExtensions { /* sync2 */ \ MACRO(1, 1, FF_VK_EXT_NO_FLAG, CmdPipelineBarrier2) \ \ + /* Video queue */ \ + MACRO(1, 1, FF_VK_EXT_VIDEO_QUEUE, CreateVideoSessionKHR) \ + MACRO(1, 1, FF_VK_EXT_VIDEO_QUEUE, CreateVideoSessionParametersKHR) \ + MACRO(1, 1, FF_VK_EXT_VIDEO_QUEUE, GetVideoSessionMemoryRequirementsKHR) \ + MACRO(1, 1, FF_VK_EXT_VIDEO_QUEUE, BindVideoSessionMemoryKHR) \ + MACRO(1, 1, FF_VK_EXT_VIDEO_QUEUE, CmdBeginVideoCodingKHR) \ + MACRO(1, 1, FF_VK_EXT_VIDEO_QUEUE, CmdControlVideoCodingKHR) \ + MACRO(1, 1, FF_VK_EXT_VIDEO_QUEUE, CmdEndVideoCodingKHR) \ + MACRO(1, 1, FF_VK_EXT_VIDEO_QUEUE, DestroyVideoSessionParametersKHR) \ + MACRO(1, 1, FF_VK_EXT_VIDEO_QUEUE, DestroyVideoSessionKHR) \ + \ + /* Video decoding */ \ + MACRO(1, 1, FF_VK_EXT_VIDEO_DECODE_QUEUE, CmdDecodeVideoKHR) \ + \ /* Pipeline */ \ MACRO(1, 1, FF_VK_EXT_NO_FLAG, CreatePipelineLayout) \ MACRO(1, 1, FF_VK_EXT_NO_FLAG, DestroyPipelineLayout) \ diff --git a/libavutil/vulkan_loader.h b/libavutil/vulkan_loader.h index 2e6dfb4f4f5..5380e213030 100644 --- a/libavutil/vulkan_loader.h +++ b/libavutil/vulkan_loader.h @@ -50,6 +50,10 @@ static inline uint64_t ff_vk_extensions_to_mask(const char * const *extensions, { VK_KHR_EXTERNAL_SEMAPHORE_WIN32_EXTENSION_NAME, FF_VK_EXT_EXTERNAL_WIN32_SEM }, #endif { VK_EXT_DESCRIPTOR_BUFFER_EXTENSION_NAME, FF_VK_EXT_DESCRIPTOR_BUFFER, }, + { VK_KHR_VIDEO_QUEUE_EXTENSION_NAME, FF_VK_EXT_VIDEO_QUEUE }, + { VK_KHR_VIDEO_DECODE_QUEUE_EXTENSION_NAME, FF_VK_EXT_VIDEO_DECODE_QUEUE }, + { VK_KHR_VIDEO_DECODE_H264_EXTENSION_NAME, FF_VK_EXT_VIDEO_DECODE_H264 }, + { VK_KHR_VIDEO_DECODE_H265_EXTENSION_NAME, FF_VK_EXT_VIDEO_DECODE_H265 }, }; FFVulkanExtensions mask = 0x0; From d4cb48dd003f23c32cd9b2dacf6847ded84f9e36 Mon Sep 17 00:00:00 2001 From: Lynne Date: Wed, 23 Nov 2022 15:18:21 +0100 Subject: [PATCH 1247/2172] hwcontext_vulkan: support PREP_MODE_DECODING in prepare_frame() --- libavutil/hwcontext_vulkan.c | 67 ++++++++++++++++++++++++++---------- 1 file changed, 48 insertions(+), 19 deletions(-) diff --git a/libavutil/hwcontext_vulkan.c b/libavutil/hwcontext_vulkan.c index 97845ec8248..3d3b82af4c9 100644 --- a/libavutil/hwcontext_vulkan.c +++ b/libavutil/hwcontext_vulkan.c @@ -2030,7 +2030,9 @@ static int alloc_bind_mem(AVHWFramesContext *hwfc, AVVkFrame *f, enum PrepMode { PREP_MODE_WRITE, PREP_MODE_EXTERNAL_EXPORT, - PREP_MODE_EXTERNAL_IMPORT + PREP_MODE_EXTERNAL_IMPORT, + PREP_MODE_DECODING_DST, + PREP_MODE_DECODING_DPB, }; static int prepare_frame(AVHWFramesContext *hwfc, VulkanExecCtx *ectx, @@ -2039,7 +2041,7 @@ static int prepare_frame(AVHWFramesContext *hwfc, VulkanExecCtx *ectx, int err; uint32_t src_qf, dst_qf; VkImageLayout new_layout; - VkAccessFlags new_access; + VkAccessFlags2 new_access; AVVulkanFramesContext *vkfc = hwfc->hwctx; const int planes = av_pix_fmt_count_planes(hwfc->sw_format); VulkanDevicePriv *p = hwfc->device_ctx->internal->priv; @@ -2047,7 +2049,8 @@ static int prepare_frame(AVHWFramesContext *hwfc, VulkanExecCtx *ectx, AVFrame tmp = { .data[0] = (uint8_t *)frame }; uint64_t sem_sig_val[AV_NUM_DATA_POINTERS]; - VkImageMemoryBarrier img_bar[AV_NUM_DATA_POINTERS] = { 0 }; + VkImageMemoryBarrier2 img_bar[AV_NUM_DATA_POINTERS] = { 0 }; + VkDependencyInfo dep_info; VkTimelineSemaphoreSubmitInfo s_timeline_sem_info = { .sType = VK_STRUCTURE_TYPE_TIMELINE_SEMAPHORE_SUBMIT_INFO, @@ -2103,32 +2106,52 @@ static int prepare_frame(AVHWFramesContext *hwfc, VulkanExecCtx *ectx, s_info.pWaitDstStageMask = wait_st; s_info.waitSemaphoreCount = planes; break; + case PREP_MODE_DECODING_DST: + new_layout = VK_IMAGE_LAYOUT_VIDEO_DECODE_DST_KHR; + new_access = VK_ACCESS_TRANSFER_WRITE_BIT; + src_qf = VK_QUEUE_FAMILY_IGNORED; + dst_qf = VK_QUEUE_FAMILY_IGNORED; + break; + case PREP_MODE_DECODING_DPB: + new_layout = VK_IMAGE_LAYOUT_VIDEO_DECODE_DPB_KHR; + new_access = VK_ACCESS_TRANSFER_READ_BIT | VK_ACCESS_TRANSFER_WRITE_BIT; + src_qf = VK_QUEUE_FAMILY_IGNORED; + dst_qf = VK_QUEUE_FAMILY_IGNORED; + break; } /* Change the image layout to something more optimal for writes. * This also signals the newly created semaphore, making it usable * for synchronization */ for (int i = 0; i < planes; i++) { - img_bar[i].sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER; - img_bar[i].srcAccessMask = 0x0; - img_bar[i].dstAccessMask = new_access; - img_bar[i].oldLayout = frame->layout[i]; - img_bar[i].newLayout = new_layout; - 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; - img_bar[i].subresourceRange.layerCount = 1; - img_bar[i].subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; + img_bar[i] = (VkImageMemoryBarrier2) { + .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER_2, + .pNext = NULL, + .srcStageMask = VK_PIPELINE_STAGE_2_TOP_OF_PIPE_BIT, + .srcAccessMask = 0x0, + .dstStageMask = VK_PIPELINE_STAGE_TRANSFER_BIT, + .dstAccessMask = new_access, + .oldLayout = frame->layout[i], + .newLayout = new_layout, + .srcQueueFamilyIndex = src_qf, + .dstQueueFamilyIndex = dst_qf, + .image = frame->img[i], + .subresourceRange = (VkImageSubresourceRange) { + .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT, + .levelCount = 1, + .layerCount = 1, + }, + }; frame->layout[i] = img_bar[i].newLayout; frame->access[i] = img_bar[i].dstAccessMask; } - vk->CmdPipelineBarrier(get_buf_exec_ctx(hwfc, ectx), - VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, - VK_PIPELINE_STAGE_TRANSFER_BIT, - 0, 0, NULL, 0, NULL, planes, img_bar); + vk->CmdPipelineBarrier2(get_buf_exec_ctx(hwfc, ectx), &(VkDependencyInfo) { + .sType = VK_STRUCTURE_TYPE_DEPENDENCY_INFO, + .pImageMemoryBarriers = img_bar, + .imageMemoryBarrierCount = planes, + }); err = submit_exec_ctx(hwfc, ectx, &s_info, frame, 0); vkfc->unlock_frame(hwfc, frame); @@ -2369,7 +2392,13 @@ static AVBufferRef *vulkan_pool_alloc(void *opaque, size_t size) if (err) goto fail; - err = prepare_frame(hwfc, &fp->conv_ctx, f, PREP_MODE_WRITE); + if ( (hwctx->usage & VK_IMAGE_USAGE_VIDEO_DECODE_DPB_BIT_KHR) && + !(hwctx->usage & VK_IMAGE_USAGE_VIDEO_DECODE_DST_BIT_KHR)) + err = prepare_frame(hwfc, &fp->conv_ctx, f, PREP_MODE_DECODING_DPB); + else if (hwctx->usage & VK_IMAGE_USAGE_VIDEO_DECODE_DST_BIT_KHR) + err = prepare_frame(hwfc, &fp->conv_ctx, f, PREP_MODE_DECODING_DST); + else + err = prepare_frame(hwfc, &fp->conv_ctx, f, PREP_MODE_WRITE); if (err) goto fail; From e5e12c5078ab1a4ad04d03ed65749f584f96fd00 Mon Sep 17 00:00:00 2001 From: Lynne Date: Fri, 17 Feb 2023 10:09:34 +0100 Subject: [PATCH 1248/2172] hwcontext_vulkan: load query-related functions Needed for both encoding and decoding. --- libavutil/vulkan_functions.h | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/libavutil/vulkan_functions.h b/libavutil/vulkan_functions.h index 403382fe7f2..2a7c383dc13 100644 --- a/libavutil/vulkan_functions.h +++ b/libavutil/vulkan_functions.h @@ -162,6 +162,15 @@ typedef enum FFVulkanExtensions { MACRO(1, 1, FF_VK_EXT_NO_FLAG, CreateDescriptorUpdateTemplate) \ MACRO(1, 1, FF_VK_EXT_NO_FLAG, DestroyDescriptorUpdateTemplate) \ \ + /* Queries */ \ + MACRO(1, 1, FF_VK_EXT_NO_FLAG, CreateQueryPool) \ + MACRO(1, 1, FF_VK_EXT_NO_FLAG, GetQueryPoolResults) \ + MACRO(1, 1, FF_VK_EXT_NO_FLAG, ResetQueryPool) \ + MACRO(1, 1, FF_VK_EXT_NO_FLAG, CmdBeginQuery) \ + MACRO(1, 1, FF_VK_EXT_NO_FLAG, CmdEndQuery) \ + MACRO(1, 1, FF_VK_EXT_NO_FLAG, CmdResetQueryPool) \ + MACRO(1, 1, FF_VK_EXT_NO_FLAG, DestroyQueryPool) \ + \ /* sync2 */ \ MACRO(1, 1, FF_VK_EXT_NO_FLAG, CmdPipelineBarrier2) \ \ From 9b385b480f5aad0d628424841dbc9e5dca106738 Mon Sep 17 00:00:00 2001 From: Lynne Date: Tue, 14 Mar 2023 20:45:45 +0100 Subject: [PATCH 1249/2172] hwcontext_vulkan: enable GPU-assisted validation when debugging --- libavutil/hwcontext_vulkan.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/libavutil/hwcontext_vulkan.c b/libavutil/hwcontext_vulkan.c index 3d3b82af4c9..28255929255 100644 --- a/libavutil/hwcontext_vulkan.c +++ b/libavutil/hwcontext_vulkan.c @@ -696,6 +696,9 @@ static int create_instance(AVHWDeviceContext *ctx, AVDictionary *opts) LIBAVUTIL_VERSION_MINOR, LIBAVUTIL_VERSION_MICRO), }; + VkValidationFeaturesEXT validation_features = { + .sType = VK_STRUCTURE_TYPE_VALIDATION_FEATURES_EXT, + }; VkInstanceCreateInfo inst_props = { .sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO, .pApplicationInfo = &application_info, @@ -726,6 +729,17 @@ static int create_instance(AVHWDeviceContext *ctx, AVDictionary *opts) if (err < 0) goto fail; + if (debug_mode) { + VkValidationFeatureEnableEXT feat_list[] = { + VK_VALIDATION_FEATURE_ENABLE_GPU_ASSISTED_EXT, + VK_VALIDATION_FEATURE_ENABLE_GPU_ASSISTED_RESERVE_BINDING_SLOT_EXT, + VK_VALIDATION_FEATURE_ENABLE_SYNCHRONIZATION_VALIDATION_EXT, + }; + validation_features.pEnabledValidationFeatures = feat_list; + validation_features.enabledValidationFeatureCount = FF_ARRAY_ELEMS(feat_list); + inst_props.pNext = &validation_features; + } + /* Try to create the instance */ ret = vk->CreateInstance(&inst_props, hwctx->alloc, &hwctx->inst); From 92ddd415bc774e50cbf1ffef89e25f445514c511 Mon Sep 17 00:00:00 2001 From: Lynne Date: Wed, 23 Nov 2022 14:04:28 +0100 Subject: [PATCH 1250/2172] vulkan: lock queues before submitting operations --- libavutil/vulkan.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/libavutil/vulkan.c b/libavutil/vulkan.c index 6bf2c214b70..ad13b8f3cb9 100644 --- a/libavutil/vulkan.c +++ b/libavutil/vulkan.c @@ -625,7 +625,14 @@ int ff_vk_submit_exec_queue(FFVulkanContext *s, FFVkExecContext *e) return AVERROR_EXTERNAL; } + s->hwctx->lock_queue((AVHWDeviceContext *)s->device_ref->data, + e->qf->queue_family, e->qf->cur_queue % e->qf->actual_queues); + ret = vk->QueueSubmit(q->queue, 1, &s_info, q->fence); + + s->hwctx->unlock_queue((AVHWDeviceContext *)s->device_ref->data, + e->qf->queue_family, e->qf->cur_queue % e->qf->actual_queues); + if (ret != VK_SUCCESS) { av_log(s, AV_LOG_ERROR, "Unable to submit command buffer: %s\n", ff_vk_ret2str(ret)); From 0c9c0e40fb643a482d548d0c39bba03234ab4658 Mon Sep 17 00:00:00 2001 From: Lynne Date: Wed, 23 Nov 2022 14:04:48 +0100 Subject: [PATCH 1251/2172] vulkan: define VK_NO_PROTOTYPES This just disables the vulkan headers from defining any symbols like vkCmdPipelineBarrier2(). Instead, all functions must be loaded via the loader and used as function pointers as vk->CmdPipelineBarrier2. Mostly just forces developers to write correct code, as using the symbols can be undesirable in case API users define their own function wrappers via the loader API. --- libavutil/vulkan.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/libavutil/vulkan.h b/libavutil/vulkan.h index 90922c6cf3d..11ea8d609e2 100644 --- a/libavutil/vulkan.h +++ b/libavutil/vulkan.h @@ -19,6 +19,8 @@ #ifndef AVUTIL_VULKAN_H #define AVUTIL_VULKAN_H +#define VK_NO_PROTOTYPES + #include "pixdesc.h" #include "bprint.h" #include "hwcontext.h" From 619b1265a2567dc0bd8daac3c6aba8976e25d907 Mon Sep 17 00:00:00 2001 From: Lynne Date: Wed, 23 Nov 2022 13:54:35 +0100 Subject: [PATCH 1252/2172] vulkan: add additional error codes --- libavutil/vulkan.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/libavutil/vulkan.c b/libavutil/vulkan.c index ad13b8f3cb9..f2846e628a2 100644 --- a/libavutil/vulkan.c +++ b/libavutil/vulkan.c @@ -78,6 +78,12 @@ const char *ff_vk_ret2str(VkResult res) CASE(VK_ERROR_TOO_MANY_OBJECTS); CASE(VK_ERROR_FORMAT_NOT_SUPPORTED); CASE(VK_ERROR_FRAGMENTED_POOL); + CASE(VK_ERROR_UNKNOWN); + CASE(VK_ERROR_OUT_OF_POOL_MEMORY); + CASE(VK_ERROR_INVALID_EXTERNAL_HANDLE); + CASE(VK_ERROR_FRAGMENTATION); + CASE(VK_ERROR_INVALID_OPAQUE_CAPTURE_ADDRESS); + CASE(VK_PIPELINE_COMPILE_REQUIRED); CASE(VK_ERROR_SURFACE_LOST_KHR); CASE(VK_ERROR_NATIVE_WINDOW_IN_USE_KHR); CASE(VK_SUBOPTIMAL_KHR); @@ -90,6 +96,13 @@ const char *ff_vk_ret2str(VkResult res) CASE(VK_ERROR_VIDEO_PROFILE_FORMAT_NOT_SUPPORTED_KHR); CASE(VK_ERROR_VIDEO_PROFILE_CODEC_NOT_SUPPORTED_KHR); CASE(VK_ERROR_VIDEO_STD_VERSION_NOT_SUPPORTED_KHR); + CASE(VK_ERROR_INVALID_DRM_FORMAT_MODIFIER_PLANE_LAYOUT_EXT); + CASE(VK_ERROR_NOT_PERMITTED_KHR); + CASE(VK_ERROR_FULL_SCREEN_EXCLUSIVE_MODE_LOST_EXT); + CASE(VK_THREAD_IDLE_KHR); + CASE(VK_THREAD_DONE_KHR); + CASE(VK_OPERATION_DEFERRED_KHR); + CASE(VK_OPERATION_NOT_DEFERRED_KHR); default: return "Unknown error"; } #undef CASE From a0d47a2ad99122fd21b78de78e335d06a12f00a4 Mon Sep 17 00:00:00 2001 From: Lynne Date: Thu, 10 Mar 2022 21:41:59 +0100 Subject: [PATCH 1253/2172] vulkan: fix comment statement about exec_queue blocking --- libavutil/vulkan.h | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/libavutil/vulkan.h b/libavutil/vulkan.h index 11ea8d609e2..107c12a7468 100644 --- a/libavutil/vulkan.h +++ b/libavutil/vulkan.h @@ -390,9 +390,7 @@ 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. + * Submits a command buffer to the queue for execution. Will not block. */ int ff_vk_submit_exec_queue(FFVulkanContext *s, FFVkExecContext *e); From b5e333bba7cd0657c48b4ec996bc91fffec9d3e7 Mon Sep 17 00:00:00 2001 From: Lynne Date: Thu, 17 Mar 2022 12:23:56 +0100 Subject: [PATCH 1254/2172] vulkan: add pNext argument to ff_vk_create_buf() --- libavfilter/vf_gblur_vulkan.c | 2 +- libavfilter/vf_overlay_vulkan.c | 2 +- libavfilter/vf_scale_vulkan.c | 2 +- libavutil/vulkan.c | 4 ++-- libavutil/vulkan.h | 2 +- 5 files changed, 6 insertions(+), 6 deletions(-) diff --git a/libavfilter/vf_gblur_vulkan.c b/libavfilter/vf_gblur_vulkan.c index e6ffc8c0735..80d1dc61c06 100644 --- a/libavfilter/vf_gblur_vulkan.c +++ b/libavfilter/vf_gblur_vulkan.c @@ -174,7 +174,7 @@ static int init_gblur_pipeline(GBlurVulkanContext *s, FFVulkanPipeline *pl, FFVk RET(ff_vk_init_pipeline_layout(&s->vkctx, pl)); RET(ff_vk_init_compute_pipeline(&s->vkctx, pl)); - RET(ff_vk_create_buf(&s->vkctx, params_buf, sizeof(float) * ksize, + RET(ff_vk_create_buf(&s->vkctx, params_buf, sizeof(float) * ksize, NULL, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT)); RET(ff_vk_map_buffers(&s->vkctx, params_buf, &kernel_mapped, 1, 0)); diff --git a/libavfilter/vf_overlay_vulkan.c b/libavfilter/vf_overlay_vulkan.c index 6db7baddfdd..7a66cf12ad6 100644 --- a/libavfilter/vf_overlay_vulkan.c +++ b/libavfilter/vf_overlay_vulkan.c @@ -181,7 +181,7 @@ static av_cold int init_filter(AVFilterContext *ctx) } *par; err = ff_vk_create_buf(vkctx, &s->params_buf, - sizeof(*par), + sizeof(*par), NULL, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT); if (err) diff --git a/libavfilter/vf_scale_vulkan.c b/libavfilter/vf_scale_vulkan.c index 3b09f0dcc12..d14b32277d3 100644 --- a/libavfilter/vf_scale_vulkan.c +++ b/libavfilter/vf_scale_vulkan.c @@ -253,7 +253,7 @@ static av_cold int init_filter(AVFilterContext *ctx, AVFrame *in) } RET(ff_vk_create_buf(vkctx, &s->params_buf, - sizeof(*par), + sizeof(*par), NULL, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT)); diff --git a/libavutil/vulkan.c b/libavutil/vulkan.c index f2846e628a2..ae6adc5104d 100644 --- a/libavutil/vulkan.c +++ b/libavutil/vulkan.c @@ -205,7 +205,7 @@ static int vk_alloc_mem(FFVulkanContext *s, VkMemoryRequirements *req, return 0; } -int ff_vk_create_buf(FFVulkanContext *s, FFVkBuffer *buf, size_t size, +int ff_vk_create_buf(FFVulkanContext *s, FFVkBuffer *buf, size_t size, void *pNext, VkBufferUsageFlags usage, VkMemoryPropertyFlagBits flags) { int err; @@ -215,7 +215,7 @@ int ff_vk_create_buf(FFVulkanContext *s, FFVkBuffer *buf, size_t size, VkBufferCreateInfo buf_spawn = { .sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, - .pNext = NULL, + .pNext = pNext, .usage = usage, .sharingMode = VK_SHARING_MODE_EXCLUSIVE, .size = size, /* Gets FFALIGNED during alloc if host visible diff --git a/libavutil/vulkan.h b/libavutil/vulkan.h index 107c12a7468..c6cfb779fcd 100644 --- a/libavutil/vulkan.h +++ b/libavutil/vulkan.h @@ -397,7 +397,7 @@ 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, +int ff_vk_create_buf(FFVulkanContext *s, FFVkBuffer *buf, size_t size, void *pNext, VkBufferUsageFlags usage, VkMemoryPropertyFlagBits flags); /** From e8fce74abfd1aa4ad13f4daf103e7f71954459ba Mon Sep 17 00:00:00 2001 From: Lynne Date: Wed, 23 Nov 2022 13:03:58 +0100 Subject: [PATCH 1255/2172] vulkan: add ff_vk_qf_fill() --- libavutil/vulkan.c | 25 +++++++++++++++++++++++++ libavutil/vulkan.h | 9 +++++++++ 2 files changed, 34 insertions(+) diff --git a/libavutil/vulkan.c b/libavutil/vulkan.c index ae6adc5104d..eceef295a84 100644 --- a/libavutil/vulkan.c +++ b/libavutil/vulkan.c @@ -108,6 +108,31 @@ const char *ff_vk_ret2str(VkResult res) #undef CASE } +void ff_vk_qf_fill(FFVulkanContext *s) +{ + s->nb_qfs = 0; + + /* Simply fills in all unique queues into s->qfs */ + if (s->hwctx->queue_family_index >= 0) + s->qfs[s->nb_qfs++] = s->hwctx->queue_family_index; + if (!s->nb_qfs || s->qfs[0] != s->hwctx->queue_family_tx_index) + s->qfs[s->nb_qfs++] = s->hwctx->queue_family_tx_index; + if (!s->nb_qfs || (s->qfs[0] != s->hwctx->queue_family_comp_index && + s->qfs[1] != s->hwctx->queue_family_comp_index)) + s->qfs[s->nb_qfs++] = s->hwctx->queue_family_comp_index; + if (s->hwctx->queue_family_decode_index >= 0 && + (s->qfs[0] != s->hwctx->queue_family_decode_index && + s->qfs[1] != s->hwctx->queue_family_decode_index && + s->qfs[2] != s->hwctx->queue_family_decode_index)) + s->qfs[s->nb_qfs++] = s->hwctx->queue_family_decode_index; + if (s->hwctx->queue_family_encode_index >= 0 && + (s->qfs[0] != s->hwctx->queue_family_encode_index && + s->qfs[1] != s->hwctx->queue_family_encode_index && + s->qfs[2] != s->hwctx->queue_family_encode_index && + s->qfs[3] != s->hwctx->queue_family_encode_index)) + s->qfs[s->nb_qfs++] = s->hwctx->queue_family_encode_index; +} + void ff_vk_qf_init(FFVulkanContext *s, FFVkQueueFamilyCtx *qf, VkQueueFlagBits dev_family, int nb_queues) { diff --git a/libavutil/vulkan.h b/libavutil/vulkan.h index c6cfb779fcd..4540c3eda11 100644 --- a/libavutil/vulkan.h +++ b/libavutil/vulkan.h @@ -207,6 +207,9 @@ typedef struct FFVulkanContext { AVHWFramesContext *frames; AVVulkanFramesContext *hwfc; + uint32_t qfs[5]; + int nb_qfs; + FFVkSPIRVCompiler *spirv_compiler; /* Properties */ @@ -249,6 +252,12 @@ int ff_vk_mt_is_np_rgb(enum AVPixelFormat pix_fmt); */ const char *ff_vk_shader_rep_fmt(enum AVPixelFormat pixfmt); +/** + * Setup the queue families from the hardware device context. + * Necessary for image creation to work. + */ +void ff_vk_qf_fill(FFVulkanContext *s); + /** * Initialize a queue family with a specific number of queues. * If nb_queues == 0, use however many queues the queue family has. From fa67ccee3735c400bb0f93d56140a93e249b5ddd Mon Sep 17 00:00:00 2001 From: Lynne Date: Wed, 23 Nov 2022 13:05:59 +0100 Subject: [PATCH 1256/2172] vulkan: add ff_vk_image_create() --- libavutil/vulkan.c | 89 ++++++++++++++++++++++++++++++++++++++++++++++ libavutil/vulkan.h | 11 ++++++ 2 files changed, 100 insertions(+) diff --git a/libavutil/vulkan.c b/libavutil/vulkan.c index eceef295a84..212f1344667 100644 --- a/libavutil/vulkan.c +++ b/libavutil/vulkan.c @@ -401,6 +401,95 @@ void ff_vk_free_buf(FFVulkanContext *s, FFVkBuffer *buf) vk->FreeMemory(s->hwctx->act_dev, buf->mem, s->hwctx->alloc); } +int ff_vk_image_create(FFVulkanContext *s, AVVkFrame *f, int idx, + int width, int height, VkFormat fmt, VkImageTiling tiling, + VkImageUsageFlagBits usage, VkImageCreateFlags flags, + void *create_pnext, VkDeviceMemory *mem, void *alloc_pnext) +{ + int err; + VkResult ret; + FFVulkanFunctions *vk = &s->vkfn; + AVVulkanDeviceContext *hwctx = s->hwctx; + + 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 = s->extensions & FF_VK_EXT_EXTERNAL_WIN32_SEM ? &ext_sem_info : NULL, +#else + .pNext = s->extensions & FF_VK_EXT_EXTERNAL_FD_SEM ? &ext_sem_info : NULL, +#endif + .semaphoreType = VK_SEMAPHORE_TYPE_TIMELINE, + .initialValue = 0, + }; + + VkSemaphoreCreateInfo sem_spawn = { + .sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO, + .pNext = &sem_type_info, + }; + + /* Create the image */ + VkImageCreateInfo create_info = { + .sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, + .pNext = create_pnext, + .imageType = VK_IMAGE_TYPE_2D, + .format = fmt, + .extent.depth = 1, + .mipLevels = 1, + .arrayLayers = 1, + .flags = flags, + .tiling = tiling, + .initialLayout = VK_IMAGE_LAYOUT_UNDEFINED, + .usage = usage, + .samples = VK_SAMPLE_COUNT_1_BIT, + .pQueueFamilyIndices = s->qfs, + .queueFamilyIndexCount = s->nb_qfs, + .sharingMode = s->nb_qfs > 1 ? VK_SHARING_MODE_CONCURRENT : + VK_SHARING_MODE_EXCLUSIVE, + }; + + ret = vk->CreateImage(hwctx->act_dev, &create_info, + hwctx->alloc, &f->img[0]); + if (ret != VK_SUCCESS) { + av_log(s, AV_LOG_ERROR, "Image creation failure: %s\n", + ff_vk_ret2str(ret)); + err = AVERROR(EINVAL); + goto fail; + } + + /* Create semaphore */ + ret = vk->CreateSemaphore(hwctx->act_dev, &sem_spawn, + hwctx->alloc, &f->sem[0]); + if (ret != VK_SUCCESS) { + av_log(s, AV_LOG_ERROR, "Failed to create semaphore: %s\n", + ff_vk_ret2str(ret)); + return AVERROR_EXTERNAL; + } + + f->queue_family[0] = s->nb_qfs > 1 ? VK_QUEUE_FAMILY_IGNORED : s->qfs[0]; + f->layout[0] = create_info.initialLayout; + f->access[0] = 0x0; + f->sem_value[0] = 0; + + f->flags = 0x0; + f->tiling = tiling; + + return 0; + +fail: + return err; +} + int ff_vk_add_push_constant(FFVulkanPipeline *pl, int offset, int size, VkShaderStageFlagBits stage) { diff --git a/libavutil/vulkan.h b/libavutil/vulkan.h index 4540c3eda11..a0baba7fc8d 100644 --- a/libavutil/vulkan.h +++ b/libavutil/vulkan.h @@ -427,6 +427,17 @@ int ff_vk_unmap_buffers(FFVulkanContext *s, FFVkBuffer *buf, int nb_buffers, */ void ff_vk_free_buf(FFVulkanContext *s, FFVkBuffer *buf); +/** + * Creates an image, allocates and binds memory in the given + * idx value of the dst frame. If mem is non-NULL, then no memory will be + * allocated, but instead the given memory will be bound to the image. + */ +int ff_vk_image_create(FFVulkanContext *s, AVVkFrame *dst, int idx, + int width, int height, VkFormat fmt, VkImageTiling tiling, + VkImageUsageFlagBits usage, VkImageCreateFlags flags, + void *create_pnext, + VkDeviceMemory *mem, void *alloc_pnext); + /** * Frees the main Vulkan context. */ From 3c2f43d8eef0c181a002cb87f1c65b1c419ba1e4 Mon Sep 17 00:00:00 2001 From: Lynne Date: Wed, 23 Nov 2022 14:03:34 +0100 Subject: [PATCH 1257/2172] vulkan: expose ff_vk_alloc_mem() --- libavutil/vulkan.c | 15 ++++++++------- libavutil/vulkan.h | 7 +++++++ 2 files changed, 15 insertions(+), 7 deletions(-) diff --git a/libavutil/vulkan.c b/libavutil/vulkan.c index 212f1344667..7870de351d1 100644 --- a/libavutil/vulkan.c +++ b/libavutil/vulkan.c @@ -174,9 +174,9 @@ 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) +int ff_vk_alloc_mem(FFVulkanContext *s, VkMemoryRequirements *req, + VkMemoryPropertyFlagBits req_flags, void *alloc_extension, + VkMemoryPropertyFlagBits *mem_flags, VkDeviceMemory *mem) { VkResult ret; int index = -1; @@ -225,7 +225,8 @@ static int vk_alloc_mem(FFVulkanContext *s, VkMemoryRequirements *req, return AVERROR(ENOMEM); } - *mem_flags |= s->mprops.memoryTypes[index].propertyFlags; + if (mem_flags) + *mem_flags |= s->mprops.memoryTypes[index].propertyFlags; return 0; } @@ -279,9 +280,9 @@ int ff_vk_create_buf(FFVulkanContext *s, FFVkBuffer *buf, size_t size, void *pNe 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); + err = ff_vk_alloc_mem(s, &req.memoryRequirements, flags, + use_ded_mem ? &ded_alloc : (void *)ded_alloc.pNext, + &buf->flags, &buf->mem); if (err) return err; diff --git a/libavutil/vulkan.h b/libavutil/vulkan.h index a0baba7fc8d..85836a78075 100644 --- a/libavutil/vulkan.h +++ b/libavutil/vulkan.h @@ -258,6 +258,13 @@ const char *ff_vk_shader_rep_fmt(enum AVPixelFormat pixfmt); */ void ff_vk_qf_fill(FFVulkanContext *s); +/** + * Allocate device memory. + */ +int ff_vk_alloc_mem(FFVulkanContext *s, VkMemoryRequirements *req, + VkMemoryPropertyFlagBits req_flags, void *alloc_extension, + VkMemoryPropertyFlagBits *mem_flags, VkDeviceMemory *mem); + /** * Initialize a queue family with a specific number of queues. * If nb_queues == 0, use however many queues the queue family has. From af487904655ca45824fb4198b5ddfc00c906897a Mon Sep 17 00:00:00 2001 From: Lynne Date: Tue, 29 Nov 2022 00:43:19 +0000 Subject: [PATCH 1258/2172] vulkan: support ignoring memory properties when allocating --- libavutil/vulkan.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/libavutil/vulkan.c b/libavutil/vulkan.c index 7870de351d1..b1553c6537d 100644 --- a/libavutil/vulkan.c +++ b/libavutil/vulkan.c @@ -188,7 +188,7 @@ int ff_vk_alloc_mem(FFVulkanContext *s, VkMemoryRequirements *req, }; /* Align if we need to */ - if (req_flags & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) + if ((req_flags != UINT32_MAX) && req_flags & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) req->size = FFALIGN(req->size, s->props.limits.minMemoryMapAlignment); alloc_info.allocationSize = req->size; @@ -201,7 +201,8 @@ int ff_vk_alloc_mem(FFVulkanContext *s, VkMemoryRequirements *req, continue; /* The memory type flags must include our properties */ - if ((s->mprops.memoryTypes[i].propertyFlags & req_flags) != req_flags) + if ((req_flags != UINT32_MAX) && + ((s->mprops.memoryTypes[i].propertyFlags & req_flags) != req_flags)) continue; /* Found a suitable memory type */ @@ -210,7 +211,7 @@ int ff_vk_alloc_mem(FFVulkanContext *s, VkMemoryRequirements *req, } if (index < 0) { - av_log(s, AV_LOG_ERROR, "No memory type found for flags 0x%x\n", + av_log(s->device, AV_LOG_ERROR, "No memory type found for flags 0x%x\n", req_flags); return AVERROR(EINVAL); } From 15de0af8f0f620d4c38ca5fe88dc5c1412ea8354 Mon Sep 17 00:00:00 2001 From: Lynne Date: Thu, 15 Dec 2022 17:43:27 +0100 Subject: [PATCH 1259/2172] vulkan: allow alloc pNext in ff_vk_create_buf --- libavfilter/vf_gblur_vulkan.c | 2 +- libavfilter/vf_scale_vulkan.c | 2 +- libavutil/vulkan.c | 5 +++-- libavutil/vulkan.h | 3 ++- 4 files changed, 7 insertions(+), 5 deletions(-) diff --git a/libavfilter/vf_gblur_vulkan.c b/libavfilter/vf_gblur_vulkan.c index 80d1dc61c06..a6037e08888 100644 --- a/libavfilter/vf_gblur_vulkan.c +++ b/libavfilter/vf_gblur_vulkan.c @@ -174,7 +174,7 @@ static int init_gblur_pipeline(GBlurVulkanContext *s, FFVulkanPipeline *pl, FFVk RET(ff_vk_init_pipeline_layout(&s->vkctx, pl)); RET(ff_vk_init_compute_pipeline(&s->vkctx, pl)); - RET(ff_vk_create_buf(&s->vkctx, params_buf, sizeof(float) * ksize, NULL, + RET(ff_vk_create_buf(&s->vkctx, params_buf, sizeof(float) * ksize, NULL, NULL, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT)); RET(ff_vk_map_buffers(&s->vkctx, params_buf, &kernel_mapped, 1, 0)); diff --git a/libavfilter/vf_scale_vulkan.c b/libavfilter/vf_scale_vulkan.c index d14b32277d3..cd37a861b1a 100644 --- a/libavfilter/vf_scale_vulkan.c +++ b/libavfilter/vf_scale_vulkan.c @@ -253,7 +253,7 @@ static av_cold int init_filter(AVFilterContext *ctx, AVFrame *in) } RET(ff_vk_create_buf(vkctx, &s->params_buf, - sizeof(*par), NULL, + sizeof(*par), NULL, NULL, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT)); diff --git a/libavutil/vulkan.c b/libavutil/vulkan.c index b1553c6537d..0bb5b1eebf4 100644 --- a/libavutil/vulkan.c +++ b/libavutil/vulkan.c @@ -232,7 +232,8 @@ int ff_vk_alloc_mem(FFVulkanContext *s, VkMemoryRequirements *req, return 0; } -int ff_vk_create_buf(FFVulkanContext *s, FFVkBuffer *buf, size_t size, void *pNext, +int ff_vk_create_buf(FFVulkanContext *s, FFVkBuffer *buf, size_t size, + void *pNext, void *alloc_pNext, VkBufferUsageFlags usage, VkMemoryPropertyFlagBits flags) { int err; @@ -254,7 +255,7 @@ int ff_vk_create_buf(FFVulkanContext *s, FFVkBuffer *buf, size_t size, void *pNe }; VkMemoryDedicatedAllocateInfo ded_alloc = { .sType = VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO, - .pNext = NULL, + .pNext = alloc_pNext, }; VkMemoryDedicatedRequirements ded_req = { .sType = VK_STRUCTURE_TYPE_MEMORY_DEDICATED_REQUIREMENTS, diff --git a/libavutil/vulkan.h b/libavutil/vulkan.h index 85836a78075..d75be269771 100644 --- a/libavutil/vulkan.h +++ b/libavutil/vulkan.h @@ -413,7 +413,8 @@ 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, void *pNext, +int ff_vk_create_buf(FFVulkanContext *s, FFVkBuffer *buf, size_t size, + void *pNext, void *alloc_pNext, VkBufferUsageFlags usage, VkMemoryPropertyFlagBits flags); /** From b18e20a4ee8d6c5fe540499ab17267d55e93d296 Mon Sep 17 00:00:00 2001 From: Lynne Date: Fri, 16 Dec 2022 00:37:53 +0100 Subject: [PATCH 1260/2172] vulkan: do not wait for device idle when destroying buffers This should be done explicitly. --- libavutil/vulkan.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/libavutil/vulkan.c b/libavutil/vulkan.c index 0bb5b1eebf4..0250f5aa396 100644 --- a/libavutil/vulkan.c +++ b/libavutil/vulkan.c @@ -396,8 +396,6 @@ void ff_vk_free_buf(FFVulkanContext *s, FFVkBuffer *buf) if (!buf || !s->hwctx) 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) From bf69a641355771106b4836e0558d5c34e48870b9 Mon Sep 17 00:00:00 2001 From: Lynne Date: Fri, 16 Dec 2022 01:47:42 +0100 Subject: [PATCH 1261/2172] vulkan: add size tracking to buffer structs --- libavutil/vulkan.c | 2 ++ libavutil/vulkan.h | 1 + 2 files changed, 3 insertions(+) diff --git a/libavutil/vulkan.c b/libavutil/vulkan.c index 0250f5aa396..faf5cd55084 100644 --- a/libavutil/vulkan.c +++ b/libavutil/vulkan.c @@ -295,6 +295,8 @@ int ff_vk_create_buf(FFVulkanContext *s, FFVkBuffer *buf, size_t size, return AVERROR_EXTERNAL; } + buf->size = size; + return 0; } diff --git a/libavutil/vulkan.h b/libavutil/vulkan.h index d75be269771..f2c4a791021 100644 --- a/libavutil/vulkan.h +++ b/libavutil/vulkan.h @@ -94,6 +94,7 @@ typedef struct FFVkBuffer { VkBuffer buf; VkDeviceMemory mem; VkMemoryPropertyFlagBits flags; + size_t size; } FFVkBuffer; typedef struct FFVkQueueFamilyCtx { From d386988c39670aadb4fa9d22bc1e0f3be8373b5c Mon Sep 17 00:00:00 2001 From: Lynne Date: Mon, 19 Dec 2022 07:57:22 +0100 Subject: [PATCH 1262/2172] vulkan: use device properties 2 and add a convenience loader function --- libavutil/vulkan.c | 18 +++++++++++++++++- libavutil/vulkan.h | 8 +++++++- 2 files changed, 24 insertions(+), 2 deletions(-) diff --git a/libavutil/vulkan.c b/libavutil/vulkan.c index faf5cd55084..8a583248d16 100644 --- a/libavutil/vulkan.c +++ b/libavutil/vulkan.c @@ -108,6 +108,22 @@ const char *ff_vk_ret2str(VkResult res) #undef CASE } +void ff_vk_load_props(FFVulkanContext *s) +{ + FFVulkanFunctions *vk = &s->vkfn; + + s->driver_props = (VkPhysicalDeviceDriverProperties) { + .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DRIVER_PROPERTIES, + }; + s->props = (VkPhysicalDeviceProperties2) { + .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2, + .pNext = &s->driver_props, + }; + + vk->GetPhysicalDeviceProperties2(s->hwctx->phys_dev, &s->props); + vk->GetPhysicalDeviceMemoryProperties(s->hwctx->phys_dev, &s->mprops); +} + void ff_vk_qf_fill(FFVulkanContext *s) { s->nb_qfs = 0; @@ -189,7 +205,7 @@ int ff_vk_alloc_mem(FFVulkanContext *s, VkMemoryRequirements *req, /* Align if we need to */ if ((req_flags != UINT32_MAX) && req_flags & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) - req->size = FFALIGN(req->size, s->props.limits.minMemoryMapAlignment); + req->size = FFALIGN(req->size, s->props.properties.limits.minMemoryMapAlignment); alloc_info.allocationSize = req->size; diff --git a/libavutil/vulkan.h b/libavutil/vulkan.h index f2c4a791021..2cd2c1f8fa8 100644 --- a/libavutil/vulkan.h +++ b/libavutil/vulkan.h @@ -197,7 +197,8 @@ typedef struct FFVulkanContext { FFVulkanFunctions vkfn; FFVulkanExtensions extensions; - VkPhysicalDeviceProperties props; + VkPhysicalDeviceProperties2 props; + VkPhysicalDeviceDriverProperties driver_props; VkPhysicalDeviceMemoryProperties mprops; AVBufferRef *device_ref; @@ -243,6 +244,11 @@ extern const VkComponentMapping ff_comp_identity_map; */ const char *ff_vk_ret2str(VkResult res); +/** + * Loads props/mprops/driver_props + */ +void ff_vk_load_props(FFVulkanContext *s); + /** * Returns 1 if the image is any sort of supported RGB */ From f3fb1b50bba09d0a3e8583102b663a348cd92220 Mon Sep 17 00:00:00 2001 From: Lynne Date: Thu, 22 Dec 2022 05:02:50 +0100 Subject: [PATCH 1263/2172] vulkan: minor indent fix, add support for synchronous submission/waiting --- libavutil/vulkan.c | 20 ++++++++++++++++++-- libavutil/vulkan.h | 9 +++++++++ 2 files changed, 27 insertions(+), 2 deletions(-) diff --git a/libavutil/vulkan.c b/libavutil/vulkan.c index 8a583248d16..b5e08ecc469 100644 --- a/libavutil/vulkan.c +++ b/libavutil/vulkan.c @@ -564,7 +564,7 @@ int ff_vk_create_exec_ctx(FFVulkanContext *s, FFVkExecContext **ctx, /* Create command pool */ ret = vk->CreateCommandPool(s->hwctx->act_dev, &cqueue_create, - s->hwctx->alloc, &e->pool); + 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)); @@ -631,11 +631,13 @@ int ff_vk_start_exec_recording(FFVulkanContext *s, FFVkExecContext *e) ff_vk_ret2str(ret)); return AVERROR_EXTERNAL; } - } else { + } else if (!q->synchronous) { vk->WaitForFences(s->hwctx->act_dev, 1, &q->fence, VK_TRUE, UINT64_MAX); vk->ResetFences(s->hwctx->act_dev, 1, &q->fence); } + q->synchronous = 0; + /* Discard queue dependencies */ ff_vk_discard_exec_deps(e); @@ -788,9 +790,23 @@ int ff_vk_submit_exec_queue(FFVulkanContext *s, FFVkExecContext *e) for (int i = 0; i < e->sem_sig_cnt; i++) *e->sem_sig_val_dst[i] += 1; + q->submitted = 1; + return 0; } +void ff_vk_wait_on_exec_ctx(FFVulkanContext *s, FFVkExecContext *e) +{ + FFVulkanFunctions *vk = &s->vkfn; + FFVkQueueCtx *q = &e->queues[e->qf->cur_queue]; + if (!q->submitted) + return; + + vk->WaitForFences(s->hwctx->act_dev, 1, &q->fence, VK_TRUE, UINT64_MAX); + vk->ResetFences(s->hwctx->act_dev, 1, &q->fence); + q->synchronous = 1; +} + int ff_vk_add_dep_exec_ctx(FFVulkanContext *s, FFVkExecContext *e, AVBufferRef **deps, int nb_deps) { diff --git a/libavutil/vulkan.h b/libavutil/vulkan.h index 2cd2c1f8fa8..a17cc4a34ef 100644 --- a/libavutil/vulkan.h +++ b/libavutil/vulkan.h @@ -147,6 +147,9 @@ typedef struct FFVkQueueCtx { VkFence fence; VkQueue queue; + int synchronous; + int submitted; + /* Buffer dependencies */ AVBufferRef **buf_deps; int nb_buf_deps; @@ -417,6 +420,12 @@ int ff_vk_add_exec_dep(FFVulkanContext *s, FFVkExecContext *e, AVFrame *frame, */ int ff_vk_submit_exec_queue(FFVulkanContext *s, FFVkExecContext *e); +/** + * Wait on a command buffer's execution. Mainly useful for debugging and + * development. + */ +void ff_vk_wait_on_exec_ctx(FFVulkanContext *s, FFVkExecContext *e); + /** * Create a VkBuffer with the specified parameters. */ From 6eaf3fe69cc18739e9f2cc54418cf29c1d2c113c Mon Sep 17 00:00:00 2001 From: Lynne Date: Thu, 22 Dec 2022 05:03:32 +0100 Subject: [PATCH 1264/2172] vulkan: add support for queries --- libavutil/vulkan.c | 118 +++++++++++++++++++++++++++++++++++++++++++++ libavutil/vulkan.h | 30 ++++++++++++ 2 files changed, 148 insertions(+) diff --git a/libavutil/vulkan.c b/libavutil/vulkan.c index b5e08ecc469..de0c300c0e4 100644 --- a/libavutil/vulkan.c +++ b/libavutil/vulkan.c @@ -592,6 +592,114 @@ int ff_vk_create_exec_ctx(FFVulkanContext *s, FFVkExecContext **ctx, return 0; } +int ff_vk_create_exec_ctx_query_pool(FFVulkanContext *s, FFVkExecContext *e, + int nb_queries, VkQueryType type, + int elem_64bits, void *create_pnext) +{ + VkResult ret; + size_t qd_size; + int nb_results = nb_queries; + int nb_statuses = 0 /* Once RADV has support, = nb_queries */; + int status_stride = 2; + int result_elem_size = elem_64bits ? 8 : 4; + FFVulkanFunctions *vk = &s->vkfn; + VkQueryPoolCreateInfo query_pool_info = { + .sType = VK_STRUCTURE_TYPE_QUERY_POOL_CREATE_INFO, + .pNext = create_pnext, + .queryType = type, + .queryCount = nb_queries*e->qf->nb_queues, + }; + + if (e->query.pool) + return AVERROR(EINVAL); + + /* Video encode quieries produce two results per query */ + if (type == VK_QUERY_TYPE_VIDEO_ENCODE_BITSTREAM_BUFFER_RANGE_KHR) { + status_stride = 3; /* skip,skip,result,skip,skip,result */ + nb_results *= 2; + } else if (type == VK_QUERY_TYPE_RESULT_STATUS_ONLY_KHR) { + status_stride = 1; + nb_results *= 0; + } + + qd_size = nb_results*result_elem_size + nb_statuses*result_elem_size; + + e->query.data = av_mallocz(e->qf->nb_queues*qd_size); + if (!e->query.data) + return AVERROR(ENOMEM); + + ret = vk->CreateQueryPool(s->hwctx->act_dev, &query_pool_info, + s->hwctx->alloc, &e->query.pool); + if (ret != VK_SUCCESS) + return AVERROR_EXTERNAL; + + e->query.data_per_queue = qd_size; + e->query.nb_queries = nb_queries; + e->query.nb_results = nb_results; + e->query.nb_statuses = nb_statuses; + e->query.elem_64bits = elem_64bits; + e->query.status_stride = status_stride; + + return 0; +} + +int ff_vk_get_exec_ctx_query_results(FFVulkanContext *s, FFVkExecContext *e, + int query_idx, void **data, int64_t *status) +{ + VkResult ret; + FFVulkanFunctions *vk = &s->vkfn; + uint8_t *qd; + int32_t *res32; + int64_t *res64; + int64_t res = 0; + VkQueryResultFlags qf = 0; + FFVkQueueCtx *q = &e->queues[e->qf->cur_queue]; + + if (!q->submitted) { + *data = NULL; + return 0; + } + + qd = e->query.data + e->qf->cur_queue*e->query.data_per_queue; + qf |= e->query.nb_results && e->query.nb_statuses ? + VK_QUERY_RESULT_WITH_STATUS_BIT_KHR : 0x0; + qf |= e->query.elem_64bits ? VK_QUERY_RESULT_64_BIT : 0x0; + res32 = (int32_t *)(qd + e->query.nb_results*4); + res64 = (int64_t *)(qd + e->query.nb_results*8); + + ret = vk->GetQueryPoolResults(s->hwctx->act_dev, e->query.pool, + query_idx, + e->query.nb_queries, + e->query.data_per_queue, qd, + e->query.elem_64bits ? 8 : 4, qf); + if (ret != VK_SUCCESS) { + av_log(s, AV_LOG_ERROR, "Unable to perform query: %s!\n", + ff_vk_ret2str(ret)); + return AVERROR_EXTERNAL; + } + + if (e->query.nb_statuses && e->query.elem_64bits) { + for (int i = 0; i < e->query.nb_queries; i++) { + res = (res64[i] < res) || (res >= 0 && res64[i] > res) ? + res64[i] : res; + res64 += e->query.status_stride; + } + } else if (e->query.nb_statuses) { + for (int i = 0; i < e->query.nb_queries; i++) { + res = (res32[i] < res) || (res >= 0 && res32[i] > res) ? + res32[i] : res; + res32 += e->query.status_stride; + } + } + + if (data) + *data = qd; + if (status) + *status = res; + + return 0; +} + void ff_vk_discard_exec_deps(FFVkExecContext *e) { FFVkQueueCtx *q = &e->queues[e->qf->cur_queue]; @@ -648,6 +756,12 @@ int ff_vk_start_exec_recording(FFVulkanContext *s, FFVkExecContext *e) return AVERROR_EXTERNAL; } + if (e->query.pool) { + e->query.idx = e->qf->cur_queue*e->query.nb_queries; + vk->CmdResetQueryPool(e->bufs[e->qf->cur_queue], e->query.pool, + e->query.idx, e->query.nb_queries); + } + return 0; } @@ -790,6 +904,7 @@ int ff_vk_submit_exec_queue(FFVulkanContext *s, FFVkExecContext *e) for (int i = 0; i < e->sem_sig_cnt; i++) *e->sem_sig_val_dst[i] += 1; + e->query.idx = e->qf->cur_queue*e->query.nb_queries; q->submitted = 1; return 0; @@ -1483,7 +1598,10 @@ static void free_exec_ctx(FFVulkanContext *s, FFVkExecContext *e) 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); + if (e->query.pool) + vk->DestroyQueryPool(s->hwctx->act_dev, e->query.pool, s->hwctx->alloc); + av_freep(&e->query.data); av_freep(&e->bufs); av_freep(&e->queues); av_freep(&e->sem_sig); diff --git a/libavutil/vulkan.h b/libavutil/vulkan.h index a17cc4a34ef..4bd1c9fc004 100644 --- a/libavutil/vulkan.h +++ b/libavutil/vulkan.h @@ -168,6 +168,19 @@ typedef struct FFVkExecContext { VkCommandBuffer *bufs; FFVkQueueCtx *queues; + struct { + int idx; + VkQueryPool pool; + uint8_t *data; + + int nb_queries; + int nb_results; + int nb_statuses; + int elem_64bits; + size_t data_per_queue; + int status_stride; + } query; + AVBufferRef ***deps; int *nb_deps; int *dep_alloc_size; @@ -371,6 +384,23 @@ void ff_vk_update_descriptor_set(FFVulkanContext *s, FFVulkanPipeline *pl, int ff_vk_create_exec_ctx(FFVulkanContext *s, FFVkExecContext **ctx, FFVkQueueFamilyCtx *qf); +/** + * Create a query pool for a command context. + * elem_64bits exists to troll driver devs for compliance. All results + * and statuses returned should be 32 bits, unless this is set, then it's 64bits. + */ +int ff_vk_create_exec_ctx_query_pool(FFVulkanContext *s, FFVkExecContext *e, + int nb_queries, VkQueryType type, + int elem_64bits, void *create_pnext); + +/** + * Get results for query. + * Returns the status of the query. + * Sets *res to the status of the queries. + */ +int ff_vk_get_exec_ctx_query_results(FFVulkanContext *s, FFVkExecContext *e, + int query_idx, void **data, int64_t *status); + /** * Begin recording to the command buffer. Previous execution must have been * completed, which ff_vk_submit_exec_queue() will ensure. From b15104ed97185e3e66d7a29322f656b358f54252 Mon Sep 17 00:00:00 2001 From: Lynne Date: Thu, 22 Dec 2022 17:37:51 +0100 Subject: [PATCH 1265/2172] vulkan: add support for retrieving queue, query and video properties --- libavutil/vulkan.c | 87 ++++++++++++++++++++++++++++++------ libavutil/vulkan.h | 14 ++++-- libavutil/vulkan_functions.h | 1 + 3 files changed, 85 insertions(+), 17 deletions(-) diff --git a/libavutil/vulkan.c b/libavutil/vulkan.c index de0c300c0e4..6c9f91c7ef3 100644 --- a/libavutil/vulkan.c +++ b/libavutil/vulkan.c @@ -108,8 +108,9 @@ const char *ff_vk_ret2str(VkResult res) #undef CASE } -void ff_vk_load_props(FFVulkanContext *s) +int ff_vk_load_props(FFVulkanContext *s) { + uint32_t qc = 0; FFVulkanFunctions *vk = &s->vkfn; s->driver_props = (VkPhysicalDeviceDriverProperties) { @@ -120,8 +121,48 @@ void ff_vk_load_props(FFVulkanContext *s) .pNext = &s->driver_props, }; + vk->GetPhysicalDeviceProperties2(s->hwctx->phys_dev, &s->props); vk->GetPhysicalDeviceMemoryProperties(s->hwctx->phys_dev, &s->mprops); + vk->GetPhysicalDeviceQueueFamilyProperties2(s->hwctx->phys_dev, &qc, s->qf_props); + + if (s->qf_props) + return 0; + + s->qf_props = av_calloc(qc, sizeof(*s->qf_props)); + if (!s->qf_props) + return AVERROR(ENOMEM); + + s->query_props = av_calloc(qc, sizeof(*s->query_props)); + if (!s->qf_props) { + av_freep(&s->qf_props); + return AVERROR(ENOMEM); + } + + s->video_props = av_calloc(qc, sizeof(*s->video_props)); + if (!s->video_props) { + av_freep(&s->qf_props); + av_freep(&s->query_props); + return AVERROR(ENOMEM); + } + + for (uint32_t i = 0; i < qc; i++) { + s->query_props[i] = (VkQueueFamilyQueryResultStatusPropertiesKHR) { + .sType = VK_STRUCTURE_TYPE_QUEUE_FAMILY_QUERY_RESULT_STATUS_PROPERTIES_KHR, + }; + s->video_props[i] = (VkQueueFamilyVideoPropertiesKHR) { + .sType = VK_STRUCTURE_TYPE_QUEUE_FAMILY_VIDEO_PROPERTIES_KHR, + .pNext = &s->query_props[i], + }; + s->qf_props[i] = (VkQueueFamilyProperties2) { + .sType = VK_STRUCTURE_TYPE_QUEUE_FAMILY_PROPERTIES_2, + .pNext = &s->video_props[i], + }; + } + + vk->GetPhysicalDeviceQueueFamilyProperties2(s->hwctx->phys_dev, &qc, s->qf_props); + + return 0; } void ff_vk_qf_fill(FFVulkanContext *s) @@ -149,40 +190,54 @@ void ff_vk_qf_fill(FFVulkanContext *s) s->qfs[s->nb_qfs++] = s->hwctx->queue_family_encode_index; } -void ff_vk_qf_init(FFVulkanContext *s, FFVkQueueFamilyCtx *qf, - VkQueueFlagBits dev_family, int nb_queues) +int ff_vk_qf_get_index(FFVulkanContext *s, VkQueueFlagBits dev_family, int *nb) { + int ret, num; + switch (dev_family) { case VK_QUEUE_GRAPHICS_BIT: - qf->queue_family = s->hwctx->queue_family_index; - qf->actual_queues = s->hwctx->nb_graphics_queues; + ret = s->hwctx->queue_family_index; + num = 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; + ret = s->hwctx->queue_family_comp_index; + num = 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; + ret = s->hwctx->queue_family_tx_index; + num = 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; + ret = s->hwctx->queue_family_encode_index; + num = 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; + ret = s->hwctx->queue_family_decode_index; + num = s->hwctx->nb_decode_queues; break; default: av_assert0(0); /* Should never happen */ } + if (nb) + *nb = num; + + return ret; +} + +int ff_vk_qf_init(FFVulkanContext *s, FFVkQueueFamilyCtx *qf, + VkQueueFlagBits dev_family, int nb_queues) +{ + int ret; + + ret = qf->queue_family = ff_vk_qf_get_index(s, dev_family, &qf->actual_queues); + if (!nb_queues) qf->nb_queues = qf->actual_queues; else qf->nb_queues = nb_queues; - return; + return ret; } void ff_vk_qf_rotate(FFVkQueueFamilyCtx *qf) @@ -1669,6 +1724,10 @@ void ff_vk_uninit(FFVulkanContext *s) { FFVulkanFunctions *vk = &s->vkfn; + av_freep(&s->query_props); + av_freep(&s->qf_props); + av_freep(&s->video_props); + if (s->spirv_compiler) s->spirv_compiler->uninit(&s->spirv_compiler); diff --git a/libavutil/vulkan.h b/libavutil/vulkan.h index 4bd1c9fc004..4c38dbc2e6a 100644 --- a/libavutil/vulkan.h +++ b/libavutil/vulkan.h @@ -216,6 +216,9 @@ typedef struct FFVulkanContext { VkPhysicalDeviceProperties2 props; VkPhysicalDeviceDriverProperties driver_props; VkPhysicalDeviceMemoryProperties mprops; + VkQueueFamilyQueryResultStatusPropertiesKHR *query_props; + VkQueueFamilyVideoPropertiesKHR *video_props; + VkQueueFamilyProperties2 *qf_props; AVBufferRef *device_ref; AVHWDeviceContext *device; @@ -263,7 +266,7 @@ const char *ff_vk_ret2str(VkResult res); /** * Loads props/mprops/driver_props */ -void ff_vk_load_props(FFVulkanContext *s); +int ff_vk_load_props(FFVulkanContext *s); /** * Returns 1 if the image is any sort of supported RGB @@ -288,12 +291,17 @@ int ff_vk_alloc_mem(FFVulkanContext *s, VkMemoryRequirements *req, VkMemoryPropertyFlagBits req_flags, void *alloc_extension, VkMemoryPropertyFlagBits *mem_flags, VkDeviceMemory *mem); +/** + * Get a queue family index and the number of queues. nb is optional. + */ +int ff_vk_qf_get_index(FFVulkanContext *s, VkQueueFlagBits dev_family, int *nb); + /** * 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); +int ff_vk_qf_init(FFVulkanContext *s, FFVkQueueFamilyCtx *qf, + VkQueueFlagBits dev_family, int nb_queues); /** * Rotate through the queues in a queue family. diff --git a/libavutil/vulkan_functions.h b/libavutil/vulkan_functions.h index 2a7c383dc13..e06d0978078 100644 --- a/libavutil/vulkan_functions.h +++ b/libavutil/vulkan_functions.h @@ -77,6 +77,7 @@ typedef enum FFVulkanExtensions { 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) \ + MACRO(1, 0, FF_VK_EXT_NO_FLAG, GetPhysicalDeviceQueueFamilyProperties2) \ \ /* Command pool */ \ MACRO(1, 1, FF_VK_EXT_NO_FLAG, CreateCommandPool) \ From 721b71da4aac9396a0788b9aaae4b05824a4a302 Mon Sep 17 00:00:00 2001 From: Lynne Date: Wed, 28 Dec 2022 05:55:53 +0100 Subject: [PATCH 1266/2172] vulkan: return current queue index from ff_vk_qf_rotate() --- libavutil/vulkan.c | 3 ++- libavutil/vulkan.h | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/libavutil/vulkan.c b/libavutil/vulkan.c index 6c9f91c7ef3..0a92f894fa1 100644 --- a/libavutil/vulkan.c +++ b/libavutil/vulkan.c @@ -240,9 +240,10 @@ int ff_vk_qf_init(FFVulkanContext *s, FFVkQueueFamilyCtx *qf, return ret; } -void ff_vk_qf_rotate(FFVkQueueFamilyCtx *qf) +int ff_vk_qf_rotate(FFVkQueueFamilyCtx *qf) { qf->cur_queue = (qf->cur_queue + 1) % qf->nb_queues; + return qf->cur_queue; } int ff_vk_alloc_mem(FFVulkanContext *s, VkMemoryRequirements *req, diff --git a/libavutil/vulkan.h b/libavutil/vulkan.h index 4c38dbc2e6a..3f887a782e0 100644 --- a/libavutil/vulkan.h +++ b/libavutil/vulkan.h @@ -306,7 +306,7 @@ int ff_vk_qf_init(FFVulkanContext *s, FFVkQueueFamilyCtx *qf, /** * Rotate through the queues in a queue family. */ -void ff_vk_qf_rotate(FFVkQueueFamilyCtx *qf); +int ff_vk_qf_rotate(FFVkQueueFamilyCtx *qf); /** * Create a Vulkan sampler, will be auto-freed in ff_vk_filter_uninit() From b5eaeb1f134d973836d6e3dced271713fb97f234 Mon Sep 17 00:00:00 2001 From: Lynne Date: Thu, 29 Dec 2022 21:16:21 +0100 Subject: [PATCH 1267/2172] vulkan: rewrite to support all necessary features This commit rewrites the majority of vulkan.c to enable its use as a general-purpose high-level utility code, usable for decoding, encoding, and filtering of video frames. The dependency system was rewritten to simplify management of execution. The image handling system was rewritten to accomodate multiplane images. Due to how related all the new features were, this is a single commit. --- libavutil/vulkan.c | 2163 ++++++++++++++++++---------------- libavutil/vulkan.h | 516 ++++---- libavutil/vulkan_functions.h | 1 + 3 files changed, 1357 insertions(+), 1323 deletions(-) diff --git a/libavutil/vulkan.c b/libavutil/vulkan.c index 0a92f894fa1..6dd4de0343b 100644 --- a/libavutil/vulkan.c +++ b/libavutil/vulkan.c @@ -1,4 +1,6 @@ /* + * Copyright (c) Lynne + * * This file is part of FFmpeg. * * FFmpeg is free software; you can redistribute it and/or @@ -21,33 +23,6 @@ #include "vulkan.h" #include "vulkan_loader.h" -#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 - * 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, @@ -110,43 +85,50 @@ const char *ff_vk_ret2str(VkResult res) int ff_vk_load_props(FFVulkanContext *s) { - uint32_t qc = 0; FFVulkanFunctions *vk = &s->vkfn; + s->hprops = (VkPhysicalDeviceExternalMemoryHostPropertiesEXT) { + .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_MEMORY_HOST_PROPERTIES_EXT, + }; + s->desc_buf_props = (VkPhysicalDeviceDescriptorBufferPropertiesEXT) { + .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DESCRIPTOR_BUFFER_PROPERTIES_EXT, + .pNext = &s->hprops, + }; s->driver_props = (VkPhysicalDeviceDriverProperties) { .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DRIVER_PROPERTIES, + .pNext = &s->desc_buf_props, }; s->props = (VkPhysicalDeviceProperties2) { .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2, .pNext = &s->driver_props, }; - vk->GetPhysicalDeviceProperties2(s->hwctx->phys_dev, &s->props); vk->GetPhysicalDeviceMemoryProperties(s->hwctx->phys_dev, &s->mprops); - vk->GetPhysicalDeviceQueueFamilyProperties2(s->hwctx->phys_dev, &qc, s->qf_props); if (s->qf_props) return 0; - s->qf_props = av_calloc(qc, sizeof(*s->qf_props)); + vk->GetPhysicalDeviceQueueFamilyProperties2(s->hwctx->phys_dev, &s->tot_nb_qfs, NULL); + + s->qf_props = av_calloc(s->tot_nb_qfs, sizeof(*s->qf_props)); if (!s->qf_props) return AVERROR(ENOMEM); - s->query_props = av_calloc(qc, sizeof(*s->query_props)); + s->query_props = av_calloc(s->tot_nb_qfs, sizeof(*s->query_props)); if (!s->qf_props) { av_freep(&s->qf_props); return AVERROR(ENOMEM); } - s->video_props = av_calloc(qc, sizeof(*s->video_props)); + s->video_props = av_calloc(s->tot_nb_qfs, sizeof(*s->video_props)); if (!s->video_props) { av_freep(&s->qf_props); av_freep(&s->query_props); return AVERROR(ENOMEM); } - for (uint32_t i = 0; i < qc; i++) { + for (uint32_t i = 0; i < s->tot_nb_qfs; i++) { s->query_props[i] = (VkQueueFamilyQueryResultStatusPropertiesKHR) { .sType = VK_STRUCTURE_TYPE_QUEUE_FAMILY_QUERY_RESULT_STATUS_PROPERTIES_KHR, }; @@ -160,37 +142,12 @@ int ff_vk_load_props(FFVulkanContext *s) }; } - vk->GetPhysicalDeviceQueueFamilyProperties2(s->hwctx->phys_dev, &qc, s->qf_props); + vk->GetPhysicalDeviceQueueFamilyProperties2(s->hwctx->phys_dev, &s->tot_nb_qfs, s->qf_props); return 0; } -void ff_vk_qf_fill(FFVulkanContext *s) -{ - s->nb_qfs = 0; - - /* Simply fills in all unique queues into s->qfs */ - if (s->hwctx->queue_family_index >= 0) - s->qfs[s->nb_qfs++] = s->hwctx->queue_family_index; - if (!s->nb_qfs || s->qfs[0] != s->hwctx->queue_family_tx_index) - s->qfs[s->nb_qfs++] = s->hwctx->queue_family_tx_index; - if (!s->nb_qfs || (s->qfs[0] != s->hwctx->queue_family_comp_index && - s->qfs[1] != s->hwctx->queue_family_comp_index)) - s->qfs[s->nb_qfs++] = s->hwctx->queue_family_comp_index; - if (s->hwctx->queue_family_decode_index >= 0 && - (s->qfs[0] != s->hwctx->queue_family_decode_index && - s->qfs[1] != s->hwctx->queue_family_decode_index && - s->qfs[2] != s->hwctx->queue_family_decode_index)) - s->qfs[s->nb_qfs++] = s->hwctx->queue_family_decode_index; - if (s->hwctx->queue_family_encode_index >= 0 && - (s->qfs[0] != s->hwctx->queue_family_encode_index && - s->qfs[1] != s->hwctx->queue_family_encode_index && - s->qfs[2] != s->hwctx->queue_family_encode_index && - s->qfs[3] != s->hwctx->queue_family_encode_index)) - s->qfs[s->nb_qfs++] = s->hwctx->queue_family_encode_index; -} - -int ff_vk_qf_get_index(FFVulkanContext *s, VkQueueFlagBits dev_family, int *nb) +static int vk_qf_get_index(FFVulkanContext *s, VkQueueFlagBits dev_family, int *nb) { int ret, num; @@ -226,24 +183,552 @@ int ff_vk_qf_get_index(FFVulkanContext *s, VkQueueFlagBits dev_family, int *nb) } int ff_vk_qf_init(FFVulkanContext *s, FFVkQueueFamilyCtx *qf, - VkQueueFlagBits dev_family, int nb_queues) + VkQueueFlagBits dev_family) +{ + /* Fill in queue families from context if not done yet */ + if (!s->nb_qfs) { + s->nb_qfs = 0; + + /* Simply fills in all unique queues into s->qfs */ + if (s->hwctx->queue_family_index >= 0) + s->qfs[s->nb_qfs++] = s->hwctx->queue_family_index; + if (!s->nb_qfs || s->qfs[0] != s->hwctx->queue_family_tx_index) + s->qfs[s->nb_qfs++] = s->hwctx->queue_family_tx_index; + if (!s->nb_qfs || (s->qfs[0] != s->hwctx->queue_family_comp_index && + s->qfs[1] != s->hwctx->queue_family_comp_index)) + s->qfs[s->nb_qfs++] = s->hwctx->queue_family_comp_index; + if (s->hwctx->queue_family_decode_index >= 0 && + (s->qfs[0] != s->hwctx->queue_family_decode_index && + s->qfs[1] != s->hwctx->queue_family_decode_index && + s->qfs[2] != s->hwctx->queue_family_decode_index)) + s->qfs[s->nb_qfs++] = s->hwctx->queue_family_decode_index; + if (s->hwctx->queue_family_encode_index >= 0 && + (s->qfs[0] != s->hwctx->queue_family_encode_index && + s->qfs[1] != s->hwctx->queue_family_encode_index && + s->qfs[2] != s->hwctx->queue_family_encode_index && + s->qfs[3] != s->hwctx->queue_family_encode_index)) + s->qfs[s->nb_qfs++] = s->hwctx->queue_family_encode_index; + } + + return (qf->queue_family = vk_qf_get_index(s, dev_family, &qf->nb_queues)); +} + +void ff_vk_exec_pool_free(FFVulkanContext *s, FFVkExecPool *pool) { - int ret; + FFVulkanFunctions *vk = &s->vkfn; - ret = qf->queue_family = ff_vk_qf_get_index(s, dev_family, &qf->actual_queues); + for (int i = 0; i < pool->pool_size; i++) { + FFVkExecContext *e = &pool->contexts[i]; - if (!nb_queues) - qf->nb_queues = qf->actual_queues; - else - qf->nb_queues = nb_queues; + if (e->fence) { + vk->WaitForFences(s->hwctx->act_dev, 1, &e->fence, VK_TRUE, UINT64_MAX); + vk->DestroyFence(s->hwctx->act_dev, e->fence, s->hwctx->alloc); + } - return ret; + ff_vk_exec_discard_deps(s, e); + + av_free(e->frame_deps); + av_free(e->buf_deps); + av_free(e->queue_family_dst); + av_free(e->layout_dst); + av_free(e->access_dst); + av_free(e->frame_update); + av_free(e->frame_locked); + av_free(e->sem_sig); + av_free(e->sem_sig_val_dst); + av_free(e->sem_wait); + } + + if (pool->cmd_bufs) + vk->FreeCommandBuffers(s->hwctx->act_dev, pool->cmd_buf_pool, + pool->pool_size, pool->cmd_bufs); + if (pool->cmd_buf_pool) + vk->DestroyCommandPool(s->hwctx->act_dev, pool->cmd_buf_pool, s->hwctx->alloc); + if (pool->query_pool) + vk->DestroyQueryPool(s->hwctx->act_dev, pool->query_pool, s->hwctx->alloc); + + av_free(pool->query_data); + av_free(pool->cmd_bufs); + av_free(pool->contexts); +} + +int ff_vk_exec_pool_init(FFVulkanContext *s, FFVkQueueFamilyCtx *qf, + FFVkExecPool *pool, int nb_contexts, + int nb_queries, VkQueryType query_type, int query_64bit, + const void *query_create_pnext) +{ + int err; + VkResult ret; + FFVulkanFunctions *vk = &s->vkfn; + + VkCommandPoolCreateInfo cqueue_create; + VkCommandBufferAllocateInfo cbuf_create; + + atomic_init(&pool->idx, 0); + + /* Create command pool */ + cqueue_create = (VkCommandPoolCreateInfo) { + .sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO, + .flags = VK_COMMAND_POOL_CREATE_TRANSIENT_BIT | + VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, + .queueFamilyIndex = qf->queue_family, + }; + ret = vk->CreateCommandPool(s->hwctx->act_dev, &cqueue_create, + s->hwctx->alloc, &pool->cmd_buf_pool); + if (ret != VK_SUCCESS) { + av_log(s, AV_LOG_ERROR, "Command pool creation failure: %s\n", + ff_vk_ret2str(ret)); + err = AVERROR_EXTERNAL; + goto fail; + } + + /* Allocate space for command buffers */ + pool->cmd_bufs = av_malloc(nb_contexts*sizeof(*pool->cmd_bufs)); + if (!pool->cmd_bufs) { + err = AVERROR(ENOMEM); + goto fail; + } + + /* Allocate command buffer */ + cbuf_create = (VkCommandBufferAllocateInfo) { + .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, + .level = VK_COMMAND_BUFFER_LEVEL_PRIMARY, + .commandPool = pool->cmd_buf_pool, + .commandBufferCount = nb_contexts, + }; + ret = vk->AllocateCommandBuffers(s->hwctx->act_dev, &cbuf_create, + pool->cmd_bufs); + if (ret != VK_SUCCESS) { + av_log(s, AV_LOG_ERROR, "Command buffer alloc failure: %s\n", + ff_vk_ret2str(ret)); + err = AVERROR_EXTERNAL; + goto fail; + } + + /* Query pool */ + if (nb_queries) { + VkQueryPoolCreateInfo query_pool_info = { + .sType = VK_STRUCTURE_TYPE_QUERY_POOL_CREATE_INFO, + .pNext = query_create_pnext, + .queryType = query_type, + .queryCount = nb_queries*nb_contexts, + }; + ret = vk->CreateQueryPool(s->hwctx->act_dev, &query_pool_info, + s->hwctx->alloc, &pool->query_pool); + if (ret != VK_SUCCESS) { + av_log(s, AV_LOG_ERROR, "Query pool alloc failure: %s\n", + ff_vk_ret2str(ret)); + err = AVERROR_EXTERNAL; + goto fail; + } + + pool->nb_queries = nb_queries; + pool->query_status_stride = 2; + pool->query_results = nb_queries; + pool->query_statuses = 0; /* if radv supports it, nb_queries; */ + +#if 0 /* CONFIG_VULKAN_ENCODE */ + /* Video encode quieries produce two results per query */ + if (query_type == VK_QUERY_TYPE_VIDEO_ENCODE_FEEDBACK_KHR) { + pool->query_status_stride = 3; /* skip,skip,result,skip,skip,result */ + pool->query_results *= 2; + } else +#endif + if (query_type == VK_QUERY_TYPE_RESULT_STATUS_ONLY_KHR) { + pool->query_status_stride = 1; + pool->query_results = 0; + pool->query_statuses = nb_queries; + } + + pool->qd_size = (pool->query_results + pool->query_statuses)*(query_64bit ? 8 : 4); + + /* Allocate space for the query data */ + pool->query_data = av_calloc(nb_contexts, pool->qd_size); + if (!pool->query_data) { + err = AVERROR(ENOMEM); + goto fail; + } + } + + /* Allocate space for the contexts */ + pool->contexts = av_calloc(nb_contexts, sizeof(*pool->contexts)); + if (!pool->contexts) { + err = AVERROR(ENOMEM); + goto fail; + } + + pool->pool_size = nb_contexts; + + /* Init contexts */ + for (int i = 0; i < pool->pool_size; i++) { + FFVkExecContext *e = &pool->contexts[i]; + + /* Fence */ + VkFenceCreateInfo fence_create = { + .sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO, + .flags = VK_FENCE_CREATE_SIGNALED_BIT, + }; + ret = vk->CreateFence(s->hwctx->act_dev, &fence_create, s->hwctx->alloc, + &e->fence); + if (ret != VK_SUCCESS) { + av_log(s, AV_LOG_ERROR, "Failed to create submission fence: %s\n", + ff_vk_ret2str(ret)); + return AVERROR_EXTERNAL; + } + + e->idx = i; + e->parent = pool; + + /* Query data */ + e->query_data = ((uint8_t *)pool->query_data) + pool->qd_size*i; + e->query_idx = nb_queries*i; + + /* Command buffer */ + e->buf = pool->cmd_bufs[i]; + + /* Queue index distribution */ + e->qi = i % qf->nb_queues; + e->qf = qf->queue_family; + vk->GetDeviceQueue(s->hwctx->act_dev, qf->queue_family, + e->qi, &e->queue); + } + + return 0; + +fail: + ff_vk_exec_pool_free(s, pool); + return err; +} + +VkResult ff_vk_exec_get_query(FFVulkanContext *s, FFVkExecContext *e, + void **data, int64_t *status) +{ + VkResult ret; + FFVulkanFunctions *vk = &s->vkfn; + const FFVkExecPool *pool = e->parent; + + int32_t *res32 = e->query_data; + int64_t *res64 = e->query_data; + int64_t res = 0; + VkQueryResultFlags qf = 0; + + qf |= pool->query_64bit ? + VK_QUERY_RESULT_64_BIT : 0x0; + qf |= pool->query_statuses ? + VK_QUERY_RESULT_WITH_STATUS_BIT_KHR : 0x0; + + ret = vk->GetQueryPoolResults(s->hwctx->act_dev, pool->query_pool, + e->query_idx, + pool->nb_queries, + pool->qd_size, e->query_data, + pool->query_64bit ? 8 : 4, qf); + if (ret != VK_SUCCESS) + return ret; + + if (pool->query_statuses && pool->query_64bit) { + for (int i = 0; i < pool->query_statuses; i++) { + res = (res64[i] < res) || (res >= 0 && res64[i] > res) ? + res64[i] : res; + res64 += pool->query_status_stride; + } + } else if (pool->query_statuses) { + for (int i = 0; i < pool->query_statuses; i++) { + res = (res32[i] < res) || (res >= 0 && res32[i] > res) ? + res32[i] : res; + res32 += pool->query_status_stride; + } + } + + if (data) + *data = e->query_data; + if (status) + *status = res; + + return VK_SUCCESS; +} + +FFVkExecContext *ff_vk_exec_get(FFVkExecPool *pool) +{ + int idx = atomic_fetch_add_explicit(&pool->idx, 1, memory_order_relaxed); + idx %= pool->pool_size; + return &pool->contexts[idx]; +} + +void ff_vk_exec_wait(FFVulkanContext *s, FFVkExecContext *e) +{ + FFVulkanFunctions *vk = &s->vkfn; + vk->WaitForFences(s->hwctx->act_dev, 1, &e->fence, VK_TRUE, UINT64_MAX); +} + +int ff_vk_exec_start(FFVulkanContext *s, FFVkExecContext *e) +{ + VkResult ret; + FFVulkanFunctions *vk = &s->vkfn; + const FFVkExecPool *pool = e->parent; + + 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 */ + vk->WaitForFences(s->hwctx->act_dev, 1, &e->fence, VK_TRUE, UINT64_MAX); + vk->ResetFences(s->hwctx->act_dev, 1, &e->fence); + + /* Discard queue dependencies */ + ff_vk_exec_discard_deps(s, e); + + ret = vk->BeginCommandBuffer(e->buf, &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; + } + + if (pool->nb_queries) + vk->CmdResetQueryPool(e->buf, pool->query_pool, + e->query_idx, pool->nb_queries); + + return 0; +} + +void ff_vk_exec_discard_deps(FFVulkanContext *s, FFVkExecContext *e) +{ + for (int j = 0; j < e->nb_buf_deps; j++) + av_buffer_unref(&e->buf_deps[j]); + e->nb_buf_deps = 0; + + for (int j = 0; j < e->nb_frame_deps; j++) { + AVFrame *f = e->frame_deps[j]; + if (e->frame_locked[j]) { + AVHWFramesContext *hwfc = (AVHWFramesContext *)f->hw_frames_ctx->data; + AVVulkanFramesContext *vkfc = hwfc->hwctx; + AVVkFrame *vkf = (AVVkFrame *)f->data[0]; + vkfc->unlock_frame(hwfc, vkf); + e->frame_locked[j] = 0; + } + e->frame_update[j] = 0; + if (f->buf[0]) + av_frame_free(&e->frame_deps[j]); + } + e->nb_frame_deps = 0; + + e->sem_wait_cnt = 0; + e->sem_sig_cnt = 0; + e->sem_sig_val_dst_cnt = 0; +} + +int ff_vk_exec_add_dep_buf(FFVulkanContext *s, FFVkExecContext *e, + AVBufferRef **deps, int nb_deps, int ref) +{ + AVBufferRef **dst = av_fast_realloc(e->buf_deps, &e->buf_deps_alloc_size, + (e->nb_buf_deps + nb_deps) * sizeof(*dst)); + if (!dst) { + ff_vk_exec_discard_deps(s, e); + return AVERROR(ENOMEM); + } + + e->buf_deps = dst; + + for (int i = 0; i < nb_deps; i++) { + e->buf_deps[e->nb_buf_deps] = ref ? av_buffer_ref(deps[i]) : deps[i]; + if (!e->buf_deps[e->nb_buf_deps]) { + ff_vk_exec_discard_deps(s, e); + return AVERROR(ENOMEM); + } + e->nb_buf_deps++; + } + + return 0; +} + +int ff_vk_exec_add_dep_frame(FFVulkanContext *s, FFVkExecContext *e, AVFrame *f, + VkPipelineStageFlagBits2 wait_stage, + VkPipelineStageFlagBits2 signal_stage) +{ + uint8_t *frame_locked; + uint8_t *frame_update; + AVFrame **frame_deps; + VkImageLayout *layout_dst; + uint32_t *queue_family_dst; + VkAccessFlagBits *access_dst; + + AVHWFramesContext *hwfc = (AVHWFramesContext *)f->hw_frames_ctx->data; + AVVulkanFramesContext *vkfc = hwfc->hwctx; + AVVkFrame *vkf = (AVVkFrame *)f->data[0]; + int nb_images = ff_vk_count_images(vkf); + + /* Don't add duplicates */ + for (int i = 0; i < e->nb_frame_deps; i++) + if (e->frame_deps[i]->data[0] == f->data[0]) + return 1; + +#define ARR_REALLOC(str, arr, alloc_s, cnt) \ + do { \ + arr = av_fast_realloc(str->arr, alloc_s, (cnt + 1)*sizeof(*arr)); \ + if (!arr) { \ + ff_vk_exec_discard_deps(s, e); \ + return AVERROR(ENOMEM); \ + } \ + str->arr = arr; \ + } while (0) + + ARR_REALLOC(e, layout_dst, &e->layout_dst_alloc, e->nb_frame_deps); + ARR_REALLOC(e, queue_family_dst, &e->queue_family_dst_alloc, e->nb_frame_deps); + ARR_REALLOC(e, access_dst, &e->access_dst_alloc, e->nb_frame_deps); + + ARR_REALLOC(e, frame_locked, &e->frame_locked_alloc_size, e->nb_frame_deps); + ARR_REALLOC(e, frame_update, &e->frame_update_alloc_size, e->nb_frame_deps); + ARR_REALLOC(e, frame_deps, &e->frame_deps_alloc_size, e->nb_frame_deps); + + e->frame_deps[e->nb_frame_deps] = f->buf[0] ? av_frame_clone(f) : f; + if (!e->frame_deps[e->nb_frame_deps]) { + ff_vk_exec_discard_deps(s, e); + return AVERROR(ENOMEM); + } + + vkfc->lock_frame(hwfc, vkf); + e->frame_locked[e->nb_frame_deps] = 1; + e->frame_update[e->nb_frame_deps] = 0; + e->nb_frame_deps++; + + for (int i = 0; i < nb_images; i++) { + VkSemaphoreSubmitInfo *sem_wait; + VkSemaphoreSubmitInfo *sem_sig; + uint64_t **sem_sig_val_dst; + + ARR_REALLOC(e, sem_wait, &e->sem_wait_alloc, e->sem_wait_cnt); + ARR_REALLOC(e, sem_sig, &e->sem_sig_alloc, e->sem_sig_cnt); + ARR_REALLOC(e, sem_sig_val_dst, &e->sem_sig_val_dst_alloc, e->sem_sig_val_dst_cnt); + + e->sem_wait[e->sem_wait_cnt++] = (VkSemaphoreSubmitInfo) { + .sType = VK_STRUCTURE_TYPE_SEMAPHORE_SUBMIT_INFO, + .semaphore = vkf->sem[i], + .value = vkf->sem_value[i], + .stageMask = wait_stage, + }; + + e->sem_sig[e->sem_sig_cnt++] = (VkSemaphoreSubmitInfo) { + .sType = VK_STRUCTURE_TYPE_SEMAPHORE_SUBMIT_INFO, + .semaphore = vkf->sem[i], + .value = vkf->sem_value[i] + 1, + .stageMask = signal_stage, + }; + + e->sem_sig_val_dst[e->sem_sig_val_dst_cnt] = &vkf->sem_value[i]; + e->sem_sig_val_dst_cnt++; + } + + return 0; +} + +void ff_vk_exec_update_frame(FFVulkanContext *s, FFVkExecContext *e, AVFrame *f, + VkImageMemoryBarrier2 *bar, uint32_t *nb_img_bar) +{ + int i; + for (i = 0; i < e->nb_frame_deps; i++) + if (e->frame_deps[i]->data[0] == f->data[0]) + break; + av_assert0(i < e->nb_frame_deps); + + /* Don't update duplicates */ + if (nb_img_bar && !e->frame_update[i]) + (*nb_img_bar)++; + + e->queue_family_dst[i] = bar->dstQueueFamilyIndex; + e->access_dst[i] = bar->dstAccessMask; + e->layout_dst[i] = bar->newLayout; + e->frame_update[i] = 1; +} + +int ff_vk_exec_mirror_sem_value(FFVulkanContext *s, FFVkExecContext *e, + VkSemaphore *dst, uint64_t *dst_val, + AVFrame *f) +{ + uint64_t **sem_sig_val_dst; + AVVkFrame *vkf = (AVVkFrame *)f->data[0]; + + /* Reject unknown frames */ + int i; + for (i = 0; i < e->nb_frame_deps; i++) + if (e->frame_deps[i]->data[0] == f->data[0]) + break; + if (i == e->nb_frame_deps) + return AVERROR(EINVAL); + + ARR_REALLOC(e, sem_sig_val_dst, &e->sem_sig_val_dst_alloc, e->sem_sig_val_dst_cnt); + + *dst = vkf->sem[0]; + *dst_val = vkf->sem_value[0]; + + e->sem_sig_val_dst[e->sem_sig_val_dst_cnt] = dst_val; + e->sem_sig_val_dst_cnt++; + + return 0; } -int ff_vk_qf_rotate(FFVkQueueFamilyCtx *qf) +int ff_vk_exec_submit(FFVulkanContext *s, FFVkExecContext *e) { - qf->cur_queue = (qf->cur_queue + 1) % qf->nb_queues; - return qf->cur_queue; + VkResult ret; + FFVulkanFunctions *vk = &s->vkfn; + VkCommandBufferSubmitInfo cmd_buf_info = (VkCommandBufferSubmitInfo) { + .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_SUBMIT_INFO, + .commandBuffer = e->buf, + }; + VkSubmitInfo2 submit_info = (VkSubmitInfo2) { + .sType = VK_STRUCTURE_TYPE_SUBMIT_INFO_2, + .pCommandBufferInfos = &cmd_buf_info, + .commandBufferInfoCount = 1, + .pWaitSemaphoreInfos = e->sem_wait, + .waitSemaphoreInfoCount = e->sem_wait_cnt, + .pSignalSemaphoreInfos = e->sem_sig, + .signalSemaphoreInfoCount = e->sem_sig_cnt, + }; + + ret = vk->EndCommandBuffer(e->buf); + if (ret != VK_SUCCESS) { + av_log(s, AV_LOG_ERROR, "Unable to finish command buffer: %s\n", + ff_vk_ret2str(ret)); + ff_vk_exec_discard_deps(s, e); + return AVERROR_EXTERNAL; + } + + s->hwctx->lock_queue(s->device, e->qf, e->qi); + ret = vk->QueueSubmit2(e->queue, 1, &submit_info, e->fence); + s->hwctx->unlock_queue(s->device, e->qf, e->qi); + + if (ret != VK_SUCCESS) { + av_log(s, AV_LOG_ERROR, "Unable to submit command buffer: %s\n", + ff_vk_ret2str(ret)); + ff_vk_exec_discard_deps(s, e); + return AVERROR_EXTERNAL; + } + + for (int i = 0; i < e->sem_sig_val_dst_cnt; i++) + *e->sem_sig_val_dst[i] += 1; + + /* Unlock all frames */ + for (int j = 0; j < e->nb_frame_deps; j++) { + if (e->frame_locked[j]) { + AVFrame *f = e->frame_deps[j]; + AVHWFramesContext *hwfc = (AVHWFramesContext *)f->hw_frames_ctx->data; + AVVulkanFramesContext *vkfc = hwfc->hwctx; + AVVkFrame *vkf = (AVVkFrame *)f->data[0]; + + if (e->frame_update[j]) { + int nb_images = ff_vk_count_images(vkf); + for (int i = 0; i < nb_images; i++) { + vkf->layout[i] = e->layout_dst[j]; + vkf->access[i] = e->access_dst[j]; + vkf->queue_family[i] = e->queue_family_dst[j]; + } + } + vkfc->unlock_frame(hwfc, vkf); + e->frame_locked[j] = 0; + } + } + + return 0; } int ff_vk_alloc_mem(FFVulkanContext *s, VkMemoryRequirements *req, @@ -322,6 +807,10 @@ int ff_vk_create_buf(FFVulkanContext *s, FFVkBuffer *buf, size_t size, but should be ok */ }; + VkMemoryAllocateFlagsInfo alloc_flags = { + .sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_FLAGS_INFO, + .flags = VK_MEMORY_ALLOCATE_DEVICE_ADDRESS_BIT, + }; VkBufferMemoryRequirementsInfo2 req_desc = { .sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_REQUIREMENTS_INFO_2, }; @@ -351,11 +840,18 @@ int ff_vk_create_buf(FFVulkanContext *s, FFVkBuffer *buf, size_t size, /* In case the implementation prefers/requires dedicated allocation */ use_ded_mem = ded_req.prefersDedicatedAllocation | ded_req.requiresDedicatedAllocation; - if (use_ded_mem) + if (use_ded_mem) { ded_alloc.buffer = buf->buf; + ded_alloc.pNext = alloc_pNext; + alloc_pNext = &ded_alloc; + } + + if (usage & VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT) { + alloc_flags.pNext = alloc_pNext; + alloc_pNext = &alloc_flags; + } - err = ff_vk_alloc_mem(s, &req.memoryRequirements, flags, - use_ded_mem ? &ded_alloc : (void *)ded_alloc.pNext, + err = ff_vk_alloc_mem(s, &req.memoryRequirements, flags, alloc_pNext, &buf->flags, &buf->mem); if (err) return err; @@ -367,27 +863,72 @@ int ff_vk_create_buf(FFVulkanContext *s, FFVkBuffer *buf, size_t size, return AVERROR_EXTERNAL; } + if (usage & VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT) { + VkBufferDeviceAddressInfo address_info = { + .sType = VK_STRUCTURE_TYPE_BUFFER_DEVICE_ADDRESS_INFO, + .buffer = buf->buf, + }; + buf->address = vk->GetBufferDeviceAddress(s->hwctx->act_dev, &address_info); + } + buf->size = size; return 0; } -int ff_vk_map_buffers(FFVulkanContext *s, FFVkBuffer *buf, uint8_t *mem[], +static void destroy_avvkbuf(void *opaque, uint8_t *data) +{ + FFVulkanContext *s = opaque; + FFVkBuffer *buf = (FFVkBuffer *)data; + ff_vk_free_buf(s, buf); + av_free(buf); +} + +int ff_vk_create_avbuf(FFVulkanContext *s, AVBufferRef **ref, size_t size, + void *pNext, void *alloc_pNext, + VkBufferUsageFlags usage, VkMemoryPropertyFlagBits flags) +{ + int err; + AVBufferRef *buf; + FFVkBuffer *vkb = av_mallocz(sizeof(*vkb)); + if (!vkb) + return AVERROR(ENOMEM); + + err = ff_vk_create_buf(s, vkb, size, pNext, alloc_pNext, usage, flags); + if (err < 0) { + av_free(vkb); + return err; + } + + buf = av_buffer_create((uint8_t *)vkb, sizeof(*vkb), destroy_avvkbuf, s, 0); + if (!buf) { + destroy_avvkbuf(s, (uint8_t *)vkb); + return AVERROR(ENOMEM); + } + + *ref = buf; + + 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; + VkMappedMemoryRange inval_list[64]; 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]); + void *dst; + ret = vk->MapMemory(s->hwctx->act_dev, buf[i]->mem, 0, + VK_WHOLE_SIZE, 0, &dst); if (ret != VK_SUCCESS) { av_log(s, AV_LOG_ERROR, "Failed to map buffer memory: %s\n", ff_vk_ret2str(ret)); return AVERROR_EXTERNAL; } + mem[i] = dst; } if (!invalidate) @@ -396,16 +937,12 @@ int ff_vk_map_buffers(FFVulkanContext *s, FFVkBuffer *buf, uint8_t *mem[], for (int i = 0; i < nb_buffers; i++) { const VkMappedMemoryRange ival_buf = { .sType = VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE, - .memory = buf[i].mem, + .memory = buf[i]->mem, .size = VK_WHOLE_SIZE, }; - if (buf[i].flags & VK_MEMORY_PROPERTY_HOST_COHERENT_BIT) + 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; + inval_list[inval_count++] = ival_buf; } if (inval_count) { @@ -421,29 +958,25 @@ int ff_vk_map_buffers(FFVulkanContext *s, FFVkBuffer *buf, uint8_t *mem[], return 0; } -int ff_vk_unmap_buffers(FFVulkanContext *s, FFVkBuffer *buf, int nb_buffers, +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; + VkMappedMemoryRange flush_list[64]; 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, + .memory = buf[i]->mem, .size = VK_WHOLE_SIZE, }; - if (buf[i].flags & VK_MEMORY_PROPERTY_HOST_COHERENT_BIT) + 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; + flush_list[flush_count++] = flush_buf; } } @@ -458,7 +991,7 @@ int ff_vk_unmap_buffers(FFVulkanContext *s, FFVkBuffer *buf, int nb_buffers, } for (int i = 0; i < nb_buffers; i++) - vk->UnmapMemory(s->hwctx->act_dev, buf[i].mem); + vk->UnmapMemory(s->hwctx->act_dev, buf[i]->mem); return err; } @@ -470,547 +1003,109 @@ void ff_vk_free_buf(FFVulkanContext *s, FFVkBuffer *buf) if (!buf || !s->hwctx) return; + if (buf->mapped_mem) + ff_vk_unmap_buffer(s, buf, 0); 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_image_create(FFVulkanContext *s, AVVkFrame *f, int idx, - int width, int height, VkFormat fmt, VkImageTiling tiling, - VkImageUsageFlagBits usage, VkImageCreateFlags flags, - void *create_pnext, VkDeviceMemory *mem, void *alloc_pnext) +static void free_data_buf(void *opaque, uint8_t *data) { - int err; - VkResult ret; - FFVulkanFunctions *vk = &s->vkfn; - AVVulkanDeviceContext *hwctx = s->hwctx; - - 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 = s->extensions & FF_VK_EXT_EXTERNAL_WIN32_SEM ? &ext_sem_info : NULL, -#else - .pNext = s->extensions & FF_VK_EXT_EXTERNAL_FD_SEM ? &ext_sem_info : NULL, -#endif - .semaphoreType = VK_SEMAPHORE_TYPE_TIMELINE, - .initialValue = 0, - }; - - VkSemaphoreCreateInfo sem_spawn = { - .sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO, - .pNext = &sem_type_info, - }; - - /* Create the image */ - VkImageCreateInfo create_info = { - .sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, - .pNext = create_pnext, - .imageType = VK_IMAGE_TYPE_2D, - .format = fmt, - .extent.depth = 1, - .mipLevels = 1, - .arrayLayers = 1, - .flags = flags, - .tiling = tiling, - .initialLayout = VK_IMAGE_LAYOUT_UNDEFINED, - .usage = usage, - .samples = VK_SAMPLE_COUNT_1_BIT, - .pQueueFamilyIndices = s->qfs, - .queueFamilyIndexCount = s->nb_qfs, - .sharingMode = s->nb_qfs > 1 ? VK_SHARING_MODE_CONCURRENT : - VK_SHARING_MODE_EXCLUSIVE, - }; - - ret = vk->CreateImage(hwctx->act_dev, &create_info, - hwctx->alloc, &f->img[0]); - if (ret != VK_SUCCESS) { - av_log(s, AV_LOG_ERROR, "Image creation failure: %s\n", - ff_vk_ret2str(ret)); - err = AVERROR(EINVAL); - goto fail; - } - - /* Create semaphore */ - ret = vk->CreateSemaphore(hwctx->act_dev, &sem_spawn, - hwctx->alloc, &f->sem[0]); - if (ret != VK_SUCCESS) { - av_log(s, AV_LOG_ERROR, "Failed to create semaphore: %s\n", - ff_vk_ret2str(ret)); - return AVERROR_EXTERNAL; - } - - f->queue_family[0] = s->nb_qfs > 1 ? VK_QUEUE_FAMILY_IGNORED : s->qfs[0]; - f->layout[0] = create_info.initialLayout; - f->access[0] = 0x0; - f->sem_value[0] = 0; - - f->flags = 0x0; - f->tiling = tiling; - - return 0; - -fail: - return err; -} - -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; + FFVulkanContext *ctx = opaque; + FFVkBuffer *buf = (FFVkBuffer *)data; + ff_vk_free_buf(ctx, buf); + av_free(data); } -FN_CREATING(FFVulkanContext, FFVkExecContext, exec_ctx, exec_ctx, exec_ctx_num) -int ff_vk_create_exec_ctx(FFVulkanContext *s, FFVkExecContext **ctx, - FFVkQueueFamilyCtx *qf) +static AVBufferRef *alloc_data_buf(void *opaque, size_t size) { - 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; + AVBufferRef *ref; + uint8_t *buf = av_mallocz(size); + if (!buf) + return NULL; - return 0; + ref = av_buffer_create(buf, size, free_data_buf, opaque, 0); + if (!ref) + av_free(buf); + return ref; } -int ff_vk_create_exec_ctx_query_pool(FFVulkanContext *s, FFVkExecContext *e, - int nb_queries, VkQueryType type, - int elem_64bits, void *create_pnext) +int ff_vk_get_pooled_buffer(FFVulkanContext *ctx, AVBufferPool **buf_pool, + AVBufferRef **buf, VkBufferUsageFlags usage, + void *create_pNext, size_t size, + VkMemoryPropertyFlagBits mem_props) { - VkResult ret; - size_t qd_size; - int nb_results = nb_queries; - int nb_statuses = 0 /* Once RADV has support, = nb_queries */; - int status_stride = 2; - int result_elem_size = elem_64bits ? 8 : 4; - FFVulkanFunctions *vk = &s->vkfn; - VkQueryPoolCreateInfo query_pool_info = { - .sType = VK_STRUCTURE_TYPE_QUERY_POOL_CREATE_INFO, - .pNext = create_pnext, - .queryType = type, - .queryCount = nb_queries*e->qf->nb_queues, - }; - - if (e->query.pool) - return AVERROR(EINVAL); + int err; + AVBufferRef *ref; + FFVkBuffer *data; - /* Video encode quieries produce two results per query */ - if (type == VK_QUERY_TYPE_VIDEO_ENCODE_BITSTREAM_BUFFER_RANGE_KHR) { - status_stride = 3; /* skip,skip,result,skip,skip,result */ - nb_results *= 2; - } else if (type == VK_QUERY_TYPE_RESULT_STATUS_ONLY_KHR) { - status_stride = 1; - nb_results *= 0; + if (!(*buf_pool)) { + *buf_pool = av_buffer_pool_init2(sizeof(FFVkBuffer), ctx, + alloc_data_buf, NULL); + if (!(*buf_pool)) + return AVERROR(ENOMEM); } - qd_size = nb_results*result_elem_size + nb_statuses*result_elem_size; - - e->query.data = av_mallocz(e->qf->nb_queues*qd_size); - if (!e->query.data) + *buf = ref = av_buffer_pool_get(*buf_pool); + if (!ref) return AVERROR(ENOMEM); - ret = vk->CreateQueryPool(s->hwctx->act_dev, &query_pool_info, - s->hwctx->alloc, &e->query.pool); - if (ret != VK_SUCCESS) - return AVERROR_EXTERNAL; - - e->query.data_per_queue = qd_size; - e->query.nb_queries = nb_queries; - e->query.nb_results = nb_results; - e->query.nb_statuses = nb_statuses; - e->query.elem_64bits = elem_64bits; - e->query.status_stride = status_stride; - - return 0; -} - -int ff_vk_get_exec_ctx_query_results(FFVulkanContext *s, FFVkExecContext *e, - int query_idx, void **data, int64_t *status) -{ - VkResult ret; - FFVulkanFunctions *vk = &s->vkfn; - uint8_t *qd; - int32_t *res32; - int64_t *res64; - int64_t res = 0; - VkQueryResultFlags qf = 0; - FFVkQueueCtx *q = &e->queues[e->qf->cur_queue]; + data = (FFVkBuffer *)ref->data; + data->stage = VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT; + data->access = VK_ACCESS_2_NONE; - if (!q->submitted) { - *data = NULL; + if (data->size >= size) return 0; - } - qd = e->query.data + e->qf->cur_queue*e->query.data_per_queue; - qf |= e->query.nb_results && e->query.nb_statuses ? - VK_QUERY_RESULT_WITH_STATUS_BIT_KHR : 0x0; - qf |= e->query.elem_64bits ? VK_QUERY_RESULT_64_BIT : 0x0; - res32 = (int32_t *)(qd + e->query.nb_results*4); - res64 = (int64_t *)(qd + e->query.nb_results*8); - - ret = vk->GetQueryPoolResults(s->hwctx->act_dev, e->query.pool, - query_idx, - e->query.nb_queries, - e->query.data_per_queue, qd, - e->query.elem_64bits ? 8 : 4, qf); - if (ret != VK_SUCCESS) { - av_log(s, AV_LOG_ERROR, "Unable to perform query: %s!\n", - ff_vk_ret2str(ret)); - return AVERROR_EXTERNAL; - } + ff_vk_free_buf(ctx, data); + memset(data, 0, sizeof(*data)); - if (e->query.nb_statuses && e->query.elem_64bits) { - for (int i = 0; i < e->query.nb_queries; i++) { - res = (res64[i] < res) || (res >= 0 && res64[i] > res) ? - res64[i] : res; - res64 += e->query.status_stride; - } - } else if (e->query.nb_statuses) { - for (int i = 0; i < e->query.nb_queries; i++) { - res = (res32[i] < res) || (res >= 0 && res32[i] > res) ? - res32[i] : res; - res32 += e->query.status_stride; - } - } + av_log(ctx, AV_LOG_DEBUG, "Allocating buffer of %lu bytes for pool %p\n", + size, *buf_pool); - if (data) - *data = qd; - if (status) - *status = res; - - 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 if (!q->synchronous) { - vk->WaitForFences(s->hwctx->act_dev, 1, &q->fence, VK_TRUE, UINT64_MAX); - vk->ResetFences(s->hwctx->act_dev, 1, &q->fence); - } - - q->synchronous = 0; - - /* 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; - } - - if (e->query.pool) { - e->query.idx = e->qf->cur_queue*e->query.nb_queries; - vk->CmdResetQueryPool(e->bufs[e->qf->cur_queue], e->query.pool, - e->query.idx, e->query.nb_queries); + err = ff_vk_create_buf(ctx, data, size, + create_pNext, NULL, usage, + mem_props); + if (err < 0) { + av_buffer_unref(&ref); + return err; } - 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); + if (mem_props & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) { + err = ff_vk_map_buffer(ctx, data, &data->mapped_mem, 0); + if (err < 0) { + av_buffer_unref(&ref); + return err; } - - 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; - } - - s->hwctx->lock_queue((AVHWDeviceContext *)s->device_ref->data, - e->qf->queue_family, e->qf->cur_queue % e->qf->actual_queues); - - ret = vk->QueueSubmit(q->queue, 1, &s_info, q->fence); - - s->hwctx->unlock_queue((AVHWDeviceContext *)s->device_ref->data, - e->qf->queue_family, e->qf->cur_queue % e->qf->actual_queues); - - 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; - - e->query.idx = e->qf->cur_queue*e->query.nb_queries; - q->submitted = 1; - - return 0; -} - -void ff_vk_wait_on_exec_ctx(FFVulkanContext *s, FFVkExecContext *e) -{ - FFVulkanFunctions *vk = &s->vkfn; - FFVkQueueCtx *q = &e->queues[e->qf->cur_queue]; - if (!q->submitted) - return; - - vk->WaitForFences(s->hwctx->act_dev, 1, &q->fence, VK_TRUE, UINT64_MAX); - vk->ResetFences(s->hwctx->act_dev, 1, &q->fence); - q->synchronous = 1; -} - -int ff_vk_add_dep_exec_ctx(FFVulkanContext *s, FFVkExecContext *e, - AVBufferRef **deps, int nb_deps) +int ff_vk_add_push_constant(FFVulkanPipeline *pl, int offset, int size, + VkShaderStageFlagBits stage) { - AVBufferRef **dst; - FFVkQueueCtx *q = &e->queues[e->qf->cur_queue]; - - if (!deps || !nb_deps) - return 0; + VkPushConstantRange *pc; - dst = av_fast_realloc(q->buf_deps, &q->buf_deps_alloc_size, - (q->nb_buf_deps + nb_deps) * sizeof(*dst)); - if (!dst) - goto err; + 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); - q->buf_deps = dst; + pc = &pl->push_consts[pl->push_consts_num++]; + memset(pc, 0, sizeof(*pc)); - 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++; - } + pc->stageFlags = stage; + pc->offset = offset; + pc->size = size; 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) +int ff_vk_init_sampler(FFVulkanContext *s, VkSampler *sampler, + int unnorm_coords, VkFilter filt) { VkResult ret; FFVulkanFunctions *vk = &s->vkfn; @@ -1030,22 +1125,15 @@ FFVkSampler *ff_vk_init_sampler(FFVulkanContext *s, .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]); + s->hwctx->alloc, sampler); if (ret != VK_SUCCESS) { av_log(s, AV_LOG_ERROR, "Unable to init sampler: %s\n", ff_vk_ret2str(ret)); - return NULL; + return AVERROR_EXTERNAL; } - for (int i = 1; i < 4; i++) - sctx->sampler[i] = sctx->sampler[0]; - - return sctx; + return 0; } int ff_vk_mt_is_np_rgb(enum AVPixelFormat pix_fmt) @@ -1068,79 +1156,139 @@ const char *ff_vk_shader_rep_fmt(enum AVPixelFormat pixfmt) } typedef struct ImageViewCtx { - VkImageView view; + VkImageView views[AV_NUM_DATA_POINTERS]; + int nb_views; } ImageViewCtx; -static void destroy_imageview(void *opaque, uint8_t *data) +static void destroy_imageviews(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); + for (int i = 0; i < iv->nb_views; i++) + vk->DestroyImageView(s->hwctx->act_dev, iv->views[i], 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 ff_vk_create_imageviews(FFVulkanContext *s, FFVkExecContext *e, + VkImageView views[AV_NUM_DATA_POINTERS], + AVFrame *f) { int err; + VkResult ret; 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, - }, - }; + AVHWFramesContext *hwfc = (AVHWFramesContext *)f->hw_frames_ctx->data; + const VkFormat *rep_fmts = av_vkfmt_from_pixfmt(hwfc->sw_format); + AVVkFrame *vkf = (AVVkFrame *)f->data[0]; + const int nb_images = ff_vk_count_images(vkf); + const int nb_planes = av_pix_fmt_count_planes(hwfc->sw_format); ImageViewCtx *iv = av_mallocz(sizeof(*iv)); + if (!iv) + return AVERROR(ENOMEM); - 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; + for (int i = 0; i < nb_planes; i++) { + VkImageAspectFlags plane_aspect[] = { VK_IMAGE_ASPECT_COLOR_BIT, + VK_IMAGE_ASPECT_PLANE_0_BIT, + VK_IMAGE_ASPECT_PLANE_1_BIT, + VK_IMAGE_ASPECT_PLANE_2_BIT, }; + + VkImageViewCreateInfo view_create_info = { + .sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, + .pNext = NULL, + .image = vkf->img[FFMIN(i, nb_images - 1)], + .viewType = VK_IMAGE_VIEW_TYPE_2D, + .format = rep_fmts[i], + .components = ff_comp_identity_map, + .subresourceRange = { + .aspectMask = plane_aspect[(nb_planes != nb_images) + + i*(nb_planes != nb_images)], + .levelCount = 1, + .layerCount = 1, + }, + }; + + ret = vk->CreateImageView(s->hwctx->act_dev, &view_create_info, + s->hwctx->alloc, &iv->views[i]); + if (ret != VK_SUCCESS) { + av_log(s, AV_LOG_ERROR, "Failed to create imageview: %s\n", + ff_vk_ret2str(ret)); + err = AVERROR_EXTERNAL; + goto fail; + } + + iv->nb_views++; } - buf = av_buffer_create((uint8_t *)iv, sizeof(*iv), destroy_imageview, s, 0); + buf = av_buffer_create((uint8_t *)iv, sizeof(*iv), destroy_imageviews, s, 0); if (!buf) { - destroy_imageview(s, (uint8_t *)iv); - return AVERROR(ENOMEM); + err = AVERROR(ENOMEM); + goto fail; } /* Add to queue dependencies */ - err = ff_vk_add_dep_exec_ctx(s, e, &buf, 1); - if (err) { + err = ff_vk_exec_add_dep_buf(s, e, &buf, 1, 0); + if (err < 0) av_buffer_unref(&buf); - return err; - } - *v = iv->view; + memcpy(views, iv->views, nb_planes*sizeof(*views)); - return 0; + return err; + +fail: + for (int i = 0; i < iv->nb_views; i++) + vk->DestroyImageView(s->hwctx->act_dev, iv->views[i], s->hwctx->alloc); + av_free(iv); + return err; } -FN_CREATING(FFVulkanPipeline, FFVkSPIRVShader, shader, shaders, shaders_num) -FFVkSPIRVShader *ff_vk_init_shader(FFVulkanPipeline *pl, const char *name, - VkShaderStageFlags stage) +void ff_vk_frame_barrier(FFVulkanContext *s, FFVkExecContext *e, + AVFrame *pic, VkImageMemoryBarrier2 *bar, int *nb_bar, + VkPipelineStageFlags src_stage, + VkPipelineStageFlags dst_stage, + VkAccessFlagBits new_access, + VkImageLayout new_layout, + uint32_t new_qf) { - FFVkSPIRVShader *shd = create_shader(pl); - if (!shd) - return NULL; + int i, found; + AVVkFrame *vkf = (AVVkFrame *)pic->data[0]; + const int nb_images = ff_vk_count_images(vkf); + for (i = 0; i < e->nb_frame_deps; i++) + if (e->frame_deps[i]->data[0] == pic->data[0]) + break; + found = (i < e->nb_frame_deps) && (e->frame_update[i]) ? i : -1; + + for (int i = 0; i < nb_images; i++) { + bar[*nb_bar] = (VkImageMemoryBarrier2) { + .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER_2, + .pNext = NULL, + .srcStageMask = src_stage, + .dstStageMask = dst_stage, + .srcAccessMask = found >= 0 ? e->access_dst[found] : vkf->access[i], + .dstAccessMask = new_access, + .oldLayout = found >= 0 ? e->layout_dst[found] : vkf->layout[0], + .newLayout = new_layout, + .srcQueueFamilyIndex = found >= 0 ? e->queue_family_dst[found] : vkf->queue_family[0], + .dstQueueFamilyIndex = new_qf, + .image = vkf->img[i], + .subresourceRange = (VkImageSubresourceRange) { + .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT, + .layerCount = 1, + .levelCount = 1, + }, + }; + *nb_bar += 1; + } + + ff_vk_exec_update_frame(s, e, pic, &bar[*nb_bar - nb_images], NULL); +} +int ff_vk_shader_init(FFVulkanPipeline *pl, FFVkSPIRVShader *shd, const char *name, + VkShaderStageFlags stage) +{ av_bprint_init(&shd->src, 0, AV_BPRINT_SIZE_UNLIMITED); shd->shader.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO; @@ -1151,22 +1299,24 @@ FFVkSPIRVShader *ff_vk_init_shader(FFVulkanPipeline *pl, const char *name, GLSLF(0, #version %i ,460); GLSLC(0, #define IS_WITHIN(v1, v2) ((v1.x < v2.x) && (v1.y < v2.y)) ); GLSLC(0, ); + GLSLC(0, #extension GL_EXT_buffer_reference : require ); + GLSLC(0, #extension GL_EXT_buffer_reference2 : require ); - return shd; + return 0; } -void ff_vk_set_compute_shader_sizes(FFVkSPIRVShader *shd, int local_size[3]) +void ff_vk_shader_set_compute_sizes(FFVkSPIRVShader *shd, int x, int y, int z) { - shd->local_size[0] = local_size[0]; - shd->local_size[1] = local_size[1]; - shd->local_size[2] = local_size[2]; + shd->local_size[0] = x; + shd->local_size[1] = y; + shd->local_size[2] = z; 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) +void ff_vk_shader_print(void *ctx, FFVkSPIRVShader *shd, int prio) { int line = 0; const char *p = shd->src.str; @@ -1188,36 +1338,24 @@ void ff_vk_print_shader(void *ctx, FFVkSPIRVShader *shd, int prio) av_bprint_finalize(&buf, NULL); } -int ff_vk_compile_shader(FFVulkanContext *s, FFVkSPIRVShader *shd, - const char *entrypoint) +void ff_vk_shader_free(FFVulkanContext *s, FFVkSPIRVShader *shd) +{ + FFVulkanFunctions *vk = &s->vkfn; + av_bprint_finalize(&shd->src, NULL); + + if (shd->shader.module) + vk->DestroyShaderModule(s->hwctx->act_dev, shd->shader.module, s->hwctx->alloc); +} + +int ff_vk_shader_create(FFVulkanContext *s, FFVkSPIRVShader *shd, + uint8_t *spirv, size_t spirv_size, const char *entrypoint) { - int err; VkResult ret; FFVulkanFunctions *vk = &s->vkfn; VkShaderModuleCreateInfo shader_create; - uint8_t *spirv; - size_t spirv_size; - void *priv; shd->shader.pName = entrypoint; - 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 - 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; - av_log(s, AV_LOG_VERBOSE, "Shader %s compiled! Size: %zu bytes\n", shd->name, spirv_size); @@ -1229,11 +1367,8 @@ int ff_vk_compile_shader(FFVulkanContext *s, FFVkSPIRVShader *shd, ret = vk->CreateShaderModule(s->hwctx->act_dev, &shader_create, NULL, &shd->shader.module); - - 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", + av_log(s, AV_LOG_VERBOSE, "Error creating shader module: %s\n", ff_vk_ret2str(ret)); return AVERROR_EXTERNAL; } @@ -1262,132 +1397,88 @@ static const struct descriptor_props { [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) +int ff_vk_pipeline_descriptor_set_add(FFVulkanContext *s, FFVulkanPipeline *pl, + FFVkSPIRVShader *shd, + FFVulkanDescriptorSetBinding *desc, int nb, + int read_only, int print_to_shader_only) { VkResult ret; - VkDescriptorSetLayout *layout; + int has_sampler = 0; FFVulkanFunctions *vk = &s->vkfn; + FFVulkanDescriptorSet *set; + VkDescriptorSetLayoutCreateInfo desc_create_layout; - if (only_print_to_shader) + if (print_to_shader_only) 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) + /* Actual layout allocated for the pipeline */ + set = av_realloc_array(pl->desc_set, sizeof(*pl->desc_set), + pl->nb_descriptor_sets + 1); + if (!set) return AVERROR(ENOMEM); + pl->desc_set = set; + set = &set[pl->nb_descriptor_sets]; + memset(set, 0, sizeof(*set)); - 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) + set->binding = av_calloc(nb, sizeof(*set->binding)); + if (!set->binding) 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); + set->binding_offset = av_calloc(nb, sizeof(*set->binding_offset)); + if (!set->binding_offset) { + av_freep(&set->binding); + return AVERROR(ENOMEM); } - { /* 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; - } - } + desc_create_layout = (VkDescriptorSetLayoutCreateInfo) { + .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO, + .bindingCount = nb, + .pBindings = set->binding, + .flags = VK_DESCRIPTOR_SET_LAYOUT_CREATE_DESCRIPTOR_BUFFER_BIT_EXT, + }; - { /* Create template creation struct */ - VkDescriptorUpdateTemplateCreateInfo *dt; - VkDescriptorUpdateTemplateEntry *des_entries; + for (int i = 0; i < nb; i++) { + set->binding[i].binding = i; + set->binding[i].descriptorType = desc[i].type; + set->binding[i].descriptorCount = FFMAX(desc[i].elems, 1); + set->binding[i].stageFlags = desc[i].stages; + set->binding[i].pImmutableSamplers = desc[i].samplers; - /* Freed after descriptor set initialization */ - des_entries = av_mallocz(num*sizeof(VkDescriptorUpdateTemplateEntry)); - if (!des_entries) - return AVERROR(ENOMEM); + if (desc[i].type == VK_DESCRIPTOR_TYPE_SAMPLER || + desc[i].type == VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER) + has_sampler |= 1; + } - 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; - } + set->usage = VK_BUFFER_USAGE_RESOURCE_DESCRIPTOR_BUFFER_BIT_EXT | + VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT; + if (has_sampler) + set->usage |= VK_BUFFER_USAGE_SAMPLER_DESCRIPTOR_BUFFER_BIT_EXT; - 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); + ret = vk->CreateDescriptorSetLayout(s->hwctx->act_dev, &desc_create_layout, + s->hwctx->alloc, &set->layout); + if (ret != VK_SUCCESS) { + av_log(s, AV_LOG_ERROR, "Unable to init descriptor set layout: %s", + ff_vk_ret2str(ret)); + return AVERROR_EXTERNAL; + } - dt = &pl->desc_template_info[pl->total_descriptor_sets]; - memset(dt, 0, sizeof(*dt)*pl->qf->nb_queues); + vk->GetDescriptorSetLayoutSizeEXT(s->hwctx->act_dev, set->layout, &set->layout_size); - 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; - } - } + set->aligned_size = FFALIGN(set->layout_size, s->desc_buf_props.descriptorBufferOffsetAlignment); - pl->descriptor_sets_num++; + for (int i = 0; i < nb; i++) + vk->GetDescriptorSetLayoutBindingOffsetEXT(s->hwctx->act_dev, set->layout, + i, &set->binding_offset[i]); - pl->desc_layout_num += pl->qf->nb_queues; - pl->total_descriptor_sets += pl->qf->nb_queues; + set->read_only = read_only; + set->nb_bindings = nb; + pl->nb_descriptor_sets++; print: /* Write shader info */ - for (int i = 0; i < num; i++) { + for (int i = 0; i < nb; i++) { const struct descriptor_props *prop = &descriptor_props[desc[i].type]; - GLSLA("layout (set = %i, binding = %i", pl->descriptor_sets_num - 1, i); + GLSLA("layout (set = %i, binding = %i", pl->nb_descriptor_sets - 1, i); if (desc[i].mem_layout) GLSLA(", %s", desc[i].mem_layout); @@ -1412,185 +1503,268 @@ int ff_vk_add_descriptor_set(FFVulkanContext *s, FFVulkanPipeline *pl, else if (desc[i].elems > 0) GLSLA("[%i]", desc[i].elems); - GLSLA(";\n"); + GLSLA(";"); + GLSLA("\n"); } GLSLA("\n"); return 0; } -void ff_vk_update_descriptor_set(FFVulkanContext *s, FFVulkanPipeline *pl, - int set_id) +int ff_vk_exec_pipeline_register(FFVulkanContext *s, FFVkExecPool *pool, + FFVulkanPipeline *pl) { - FFVulkanFunctions *vk = &s->vkfn; + int err; - /* 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; - } + pl->desc_bind = av_calloc(pl->nb_descriptor_sets, sizeof(*pl->desc_bind)); + if (!pl->desc_bind) + return AVERROR(ENOMEM); + + pl->bound_buffer_indices = av_calloc(pl->nb_descriptor_sets, + sizeof(*pl->bound_buffer_indices)); + if (!pl->bound_buffer_indices) + return AVERROR(ENOMEM); - set_id = set_id*pl->qf->nb_queues + pl->qf->cur_queue; + for (int i = 0; i < pl->nb_descriptor_sets; i++) { + FFVulkanDescriptorSet *set = &pl->desc_set[i]; + int nb = set->read_only ? 1 : pool->pool_size; + + err = ff_vk_create_buf(s, &set->buf, set->aligned_size*nb, + NULL, NULL, set->usage, + VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | + VK_MEMORY_PROPERTY_HOST_COHERENT_BIT); + if (err < 0) + return err; + + err = ff_vk_map_buffer(s, &set->buf, &set->desc_mem, 0); + if (err < 0) + return err; + + pl->desc_bind[i] = (VkDescriptorBufferBindingInfoEXT) { + .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_BUFFER_BINDING_INFO_EXT, + .usage = set->usage, + .address = set->buf.address, + }; + + pl->bound_buffer_indices[i] = i; + } - vk->UpdateDescriptorSetWithTemplate(s->hwctx->act_dev, - pl->desc_set[set_id], - pl->desc_template[set_id], - s); + return 0; } -void ff_vk_update_push_exec(FFVulkanContext *s, FFVkExecContext *e, - VkShaderStageFlagBits stage, int offset, - size_t size, void *src) +static inline void update_set_descriptor(FFVulkanContext *s, FFVkExecContext *e, + FFVulkanDescriptorSet *set, + int bind_idx, int array_idx, + VkDescriptorGetInfoEXT *desc_get_info, + size_t desc_size) { FFVulkanFunctions *vk = &s->vkfn; + const size_t exec_offset = set->read_only ? 0 : set->aligned_size*e->idx; + void *desc = set->desc_mem + /* Base */ + exec_offset + /* Execution context */ + set->binding_offset[bind_idx] + /* Descriptor binding */ + array_idx*desc_size; /* Array position */ - vk->CmdPushConstants(e->bufs[e->qf->cur_queue], e->bound_pl->pipeline_layout, - stage, offset, size, src); + vk->GetDescriptorEXT(s->hwctx->act_dev, desc_get_info, desc_size, desc); } -int ff_vk_init_pipeline_layout(FFVulkanContext *s, FFVulkanPipeline *pl) +int ff_vk_set_descriptor_sampler(FFVulkanContext *s, FFVulkanPipeline *pl, + FFVkExecContext *e, int set, int bind, int offs, + VkSampler *sampler) { - 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); + FFVulkanDescriptorSet *desc_set = &pl->desc_set[set]; + VkDescriptorGetInfoEXT desc_get_info = { + .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_GET_INFO_EXT, + .type = desc_set->binding[bind].descriptorType, + }; - { /* 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, - }; + switch (desc_get_info.type) { + case VK_DESCRIPTOR_TYPE_SAMPLER: + desc_get_info.data.pSampler = sampler; + break; + default: + av_log(s, AV_LOG_ERROR, "Invalid descriptor type at set %i binding %i: %i!\n", + set, bind, desc_get_info.type); + return AVERROR(EINVAL); + break; + }; - 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; - } - } + update_set_descriptor(s, e, desc_set, bind, offs, &desc_get_info, + s->desc_buf_props.samplerDescriptorSize); - { /* 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, - }; + return 0; +} - pl->desc_set = av_malloc(pl->total_descriptor_sets*sizeof(*pl->desc_set)); - if (!pl->desc_set) - return AVERROR(ENOMEM); +int ff_vk_set_descriptor_image(FFVulkanContext *s, FFVulkanPipeline *pl, + FFVkExecContext *e, int set, int bind, int offs, + VkImageView view, VkImageLayout layout, VkSampler sampler) +{ + FFVulkanDescriptorSet *desc_set = &pl->desc_set[set]; + VkDescriptorGetInfoEXT desc_get_info = { + .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_GET_INFO_EXT, + .type = desc_set->binding[bind].descriptorType, + }; + VkDescriptorImageInfo desc_img_info = { + .imageView = view, + .sampler = sampler, + .imageLayout = layout, + }; + size_t desc_size; - 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; - } - } + switch (desc_get_info.type) { + case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE: + desc_get_info.data.pSampledImage = &desc_img_info; + desc_size = s->desc_buf_props.sampledImageDescriptorSize; + break; + case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE: + desc_get_info.data.pStorageImage = &desc_img_info; + desc_size = s->desc_buf_props.storageImageDescriptorSize; + break; + case VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT: + desc_get_info.data.pInputAttachmentImage = &desc_img_info; + desc_size = s->desc_buf_props.inputAttachmentDescriptorSize; + break; + case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER: + desc_get_info.data.pCombinedImageSampler = &desc_img_info; + desc_size = s->desc_buf_props.combinedImageSamplerDescriptorSize; + break; + default: + av_log(s, AV_LOG_ERROR, "Invalid descriptor type at set %i binding %i: %i!\n", + set, bind, desc_get_info.type); + return AVERROR(EINVAL); + break; + }; - { /* 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, - }; + update_set_descriptor(s, e, desc_set, bind, offs, &desc_get_info, desc_size); - 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]; + return 0; +} - 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; - } - } +int ff_vk_set_descriptor_buffer(FFVulkanContext *s, FFVulkanPipeline *pl, + FFVkExecContext *e, int set, int bind, int offs, + VkDeviceAddress addr, VkDeviceSize len, VkFormat fmt) +{ + FFVulkanDescriptorSet *desc_set = &pl->desc_set[set]; + VkDescriptorGetInfoEXT desc_get_info = { + .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_GET_INFO_EXT, + .type = desc_set->binding[bind].descriptorType, + }; + VkDescriptorAddressInfoEXT desc_buf_info = { + .address = addr, + .range = len, + .format = fmt, + }; + size_t desc_size; - { /* Descriptor template (for tightly packed descriptors) */ - VkDescriptorUpdateTemplateCreateInfo *dt; + switch (desc_get_info.type) { + case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER: + desc_get_info.data.pUniformBuffer = &desc_buf_info; + desc_size = s->desc_buf_props.uniformBufferDescriptorSize; + break; + case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER: + desc_get_info.data.pStorageBuffer = &desc_buf_info; + desc_size = s->desc_buf_props.storageBufferDescriptorSize; + break; + case VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER: + desc_get_info.data.pUniformTexelBuffer = &desc_buf_info; + desc_size = s->desc_buf_props.uniformTexelBufferDescriptorSize; + break; + case VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER: + desc_get_info.data.pStorageTexelBuffer = &desc_buf_info; + desc_size = s->desc_buf_props.storageTexelBufferDescriptorSize; + break; + default: + av_log(s, AV_LOG_ERROR, "Invalid descriptor type at set %i binding %i: %i!\n", + set, bind, desc_get_info.type); + return AVERROR(EINVAL); + break; + }; - pl->desc_template = av_malloc(pl->total_descriptor_sets*sizeof(*pl->desc_template)); - if (!pl->desc_template) - return AVERROR(ENOMEM); + update_set_descriptor(s, e, desc_set, bind, offs, &desc_get_info, desc_size); - /* 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; - } - } + return 0; +} - /* 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); - } +void ff_vk_update_descriptor_img_array(FFVulkanContext *s, FFVulkanPipeline *pl, + FFVkExecContext *e, AVFrame *f, + VkImageView *views, int set, int binding, + VkImageLayout layout, VkSampler sampler) +{ + AVHWFramesContext *hwfc = (AVHWFramesContext *)f->hw_frames_ctx->data; + const int nb_planes = av_pix_fmt_count_planes(hwfc->sw_format); - av_freep(&pl->desc_template_info); - } + for (int i = 0; i < nb_planes; i++) + ff_vk_set_descriptor_image(s, pl, e, set, binding, i, + views[i], layout, sampler); +} - return 0; +void ff_vk_update_push_exec(FFVulkanContext *s, FFVkExecContext *e, + FFVulkanPipeline *pl, + VkShaderStageFlagBits stage, + int offset, size_t size, void *src) +{ + FFVulkanFunctions *vk = &s->vkfn; + vk->CmdPushConstants(e->buf, pl->pipeline_layout, + stage, offset, size, src); } -FN_CREATING(FFVulkanContext, FFVulkanPipeline, pipeline, pipelines, pipelines_num) -FFVulkanPipeline *ff_vk_create_pipeline(FFVulkanContext *s, FFVkQueueFamilyCtx *qf) +static int init_pipeline_layout(FFVulkanContext *s, FFVulkanPipeline *pl) { - FFVulkanPipeline *pl = create_pipeline(s); - if (pl) - pl->qf = qf; + VkResult ret; + FFVulkanFunctions *vk = &s->vkfn; + VkPipelineLayoutCreateInfo pipeline_layout_info; + + VkDescriptorSetLayout *desc_layouts = av_malloc(pl->nb_descriptor_sets* + sizeof(desc_layouts)); + if (!desc_layouts) + return AVERROR(ENOMEM); + + for (int i = 0; i < pl->nb_descriptor_sets; i++) + desc_layouts[i] = pl->desc_set[i].layout; + + /* Finally create the pipeline layout */ + pipeline_layout_info = (VkPipelineLayoutCreateInfo) { + .sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, + .pSetLayouts = desc_layouts, + .setLayoutCount = pl->nb_descriptor_sets, + .pushConstantRangeCount = pl->push_consts_num, + .pPushConstantRanges = pl->push_consts, + }; + + ret = vk->CreatePipelineLayout(s->hwctx->act_dev, &pipeline_layout_info, + s->hwctx->alloc, &pl->pipeline_layout); + av_free(desc_layouts); + if (ret != VK_SUCCESS) { + av_log(s, AV_LOG_ERROR, "Unable to init pipeline layout: %s\n", + ff_vk_ret2str(ret)); + return AVERROR_EXTERNAL; + } - return pl; + return 0; } -int ff_vk_init_compute_pipeline(FFVulkanContext *s, FFVulkanPipeline *pl) +int ff_vk_init_compute_pipeline(FFVulkanContext *s, FFVulkanPipeline *pl, + FFVkSPIRVShader *shd) { - int i; + int err; VkResult ret; FFVulkanFunctions *vk = &s->vkfn; - VkComputePipelineCreateInfo pipe = { + VkComputePipelineCreateInfo pipeline_create_info; + + err = init_pipeline_layout(s, pl); + if (err < 0) + return err; + + pipeline_create_info = (VkComputePipelineCreateInfo) { .sType = VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO, + .flags = VK_PIPELINE_CREATE_DESCRIPTOR_BUFFER_BIT_EXT, .layout = pl->pipeline_layout, + .stage = shd->shader, }; - 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, + ret = vk->CreateComputePipelines(s->hwctx->act_dev, VK_NULL_HANDLE, 1, + &pipeline_create_info, s->hwctx->alloc, &pl->pipeline); if (ret != VK_SUCCESS) { av_log(s, AV_LOG_ERROR, "Unable to init compute pipeline: %s\n", @@ -1599,157 +1773,68 @@ int ff_vk_init_compute_pipeline(FFVulkanContext *s, FFVulkanPipeline *pl) } pl->bind_point = VK_PIPELINE_BIND_POINT_COMPUTE; + pl->wg_size[0] = shd->local_size[0]; + pl->wg_size[1] = shd->local_size[1]; + pl->wg_size[2] = shd->local_size[2]; return 0; } -void ff_vk_bind_pipeline_exec(FFVulkanContext *s, FFVkExecContext *e, +void ff_vk_exec_bind_pipeline(FFVulkanContext *s, FFVkExecContext *e, FFVulkanPipeline *pl) { FFVulkanFunctions *vk = &s->vkfn; + VkDeviceSize offsets[1024]; - 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]; + /* Bind pipeline */ + vk->CmdBindPipeline(e->buf, pl->bind_point, pl->pipeline); - 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); + if (pl->nb_descriptor_sets) { + for (int i = 0; i < pl->nb_descriptor_sets; i++) + offsets[i] = pl->desc_set[i].read_only ? 0 : pl->desc_set[i].aligned_size*e->idx; - 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); + /* Bind descriptor buffers */ + vk->CmdBindDescriptorBuffersEXT(e->buf, pl->nb_descriptor_sets, pl->desc_bind); + /* Binding offsets */ + vk->CmdSetDescriptorBufferOffsetsEXT(e->buf, pl->bind_point, pl->pipeline_layout, + 0, pl->nb_descriptor_sets, + pl->bound_buffer_indices, offsets); } - - 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); - if (e->query.pool) - vk->DestroyQueryPool(s->hwctx->act_dev, e->query.pool, s->hwctx->alloc); - - av_freep(&e->query.data); - 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) +void ff_vk_pipeline_free(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); + if (pl->pipeline) + vk->DestroyPipeline(s->hwctx->act_dev, pl->pipeline, s->hwctx->alloc); + if (pl->pipeline_layout) + 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], + for (int i = 0; i < pl->nb_descriptor_sets; i++) { + FFVulkanDescriptorSet *set = &pl->desc_set[i]; + if (set->buf.mem) + ff_vk_unmap_buffer(s, &set->buf, 0); + ff_vk_free_buf(s, &set->buf); + if (set->layout) + vk->DestroyDescriptorSetLayout(s->hwctx->act_dev, set->layout, s->hwctx->alloc); + av_free(set->binding); + av_free(set->binding_offset); } - /* 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->desc_bind); 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; - av_freep(&s->query_props); av_freep(&s->qf_props); av_freep(&s->video_props); - 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]); - 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 index 3f887a782e0..7f31ced41dd 100644 --- a/libavutil/vulkan.h +++ b/libavutil/vulkan.h @@ -21,6 +21,8 @@ #define VK_NO_PROTOTYPES +#include + #include "pixdesc.h" #include "bprint.h" #include "hwcontext.h" @@ -28,11 +30,6 @@ #include "hwcontext_vulkan.h" #include "vulkan_loader.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 @@ -57,6 +54,8 @@ goto fail; \ } while (0) +#define DUP_SAMPLER(x) { x, x, x, x } + typedef struct FFVkSPIRVShader { const char *name; /* Name for id/debugging purposes */ AVBPrint src; @@ -64,19 +63,6 @@ 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; - typedef struct FFVulkanDescriptorSetBinding { const char *name; VkDescriptorType type; @@ -86,8 +72,7 @@ typedef struct FFVulkanDescriptorSetBinding { 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 */ + VkSampler samplers[4]; /* Sampler to use for all elems */ } FFVulkanDescriptorSetBinding; typedef struct FFVkBuffer { @@ -95,119 +80,133 @@ typedef struct FFVkBuffer { VkDeviceMemory mem; VkMemoryPropertyFlagBits flags; size_t size; + VkDeviceAddress address; + + /* Local use only */ + VkPipelineStageFlags2 stage; + VkAccessFlags2 access; + + /* Only valid when allocated via ff_vk_get_pooled_buffer with HOST_VISIBLE */ + uint8_t *mapped_mem; } FFVkBuffer; typedef struct FFVkQueueFamilyCtx { int queue_family; int nb_queues; - int cur_queue; - int actual_queues; } FFVkQueueFamilyCtx; -typedef struct FFVulkanPipeline { - FFVkQueueFamilyCtx *qf; +typedef struct FFVulkanDescriptorSet { + VkDescriptorSetLayout layout; + FFVkBuffer buf; + uint8_t *desc_mem; + VkDeviceSize layout_size; + VkDeviceSize aligned_size; /* descriptorBufferOffsetAlignment */ + VkDeviceSize total_size; /* Once registered to an exec context */ + VkBufferUsageFlags usage; + + VkDescriptorSetLayoutBinding *binding; + VkDeviceSize *binding_offset; + int nb_bindings; + int read_only; +} FFVulkanDescriptorSet; + +typedef struct FFVulkanPipeline { VkPipelineBindPoint bind_point; /* Contexts */ VkPipelineLayout pipeline_layout; VkPipeline pipeline; - /* Shaders */ - FFVkSPIRVShader **shaders; - int shaders_num; - /* Push consts */ VkPushConstantRange *push_consts; int push_consts_num; + /* Workgroup */ + int wg_size[3]; + /* Descriptors */ - VkDescriptorSetLayout *desc_layout; - VkDescriptorPool desc_pool; - VkDescriptorSet *desc_set; -#if VK_USE_64_BIT_PTR_DEFINES == 1 - void **desc_staging; -#else - uint64_t *desc_staging; -#endif - 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; + FFVulkanDescriptorSet *desc_set; + VkDescriptorBufferBindingInfoEXT *desc_bind; + uint32_t *bound_buffer_indices; + int nb_descriptor_sets; } FFVulkanPipeline; -typedef struct FFVkQueueCtx { - VkFence fence; +typedef struct FFVkExecContext { + int idx; + const struct FFVkExecPool *parent; + + /* Queue for the execution context */ VkQueue queue; + int qf; + int qi; + + /* Command buffer for the context */ + VkCommandBuffer buf; + + /* Fence for the command buffer */ + VkFence fence; - int synchronous; - int submitted; + void *query_data; + int query_idx; /* Buffer dependencies */ AVBufferRef **buf_deps; int nb_buf_deps; - int buf_deps_alloc_size; + unsigned int buf_deps_alloc_size; /* Frame dependencies */ AVFrame **frame_deps; + unsigned int frame_deps_alloc_size; int nb_frame_deps; - int frame_deps_alloc_size; -} FFVkQueueCtx; - -typedef struct FFVkExecContext { - FFVkQueueFamilyCtx *qf; - VkCommandPool pool; - VkCommandBuffer *bufs; - FFVkQueueCtx *queues; - - struct { - int idx; - VkQueryPool pool; - uint8_t *data; - - int nb_queries; - int nb_results; - int nb_statuses; - int elem_64bits; - size_t data_per_queue; - int status_stride; - } query; + VkSemaphoreSubmitInfo *sem_wait; + unsigned int sem_wait_alloc; + int sem_wait_cnt; - AVBufferRef ***deps; - int *nb_deps; - int *dep_alloc_size; + VkSemaphoreSubmitInfo *sem_sig; + unsigned int sem_sig_alloc; + int sem_sig_cnt; - FFVulkanPipeline *bound_pl; + uint64_t **sem_sig_val_dst; + unsigned int sem_sig_val_dst_alloc; + int sem_sig_val_dst_cnt; - VkSemaphore *sem_wait; - int sem_wait_alloc; /* Allocated sem_wait */ - int sem_wait_cnt; + uint8_t *frame_locked; + unsigned int frame_locked_alloc_size; - uint64_t *sem_wait_val; - int sem_wait_val_alloc; + VkAccessFlagBits *access_dst; + unsigned int access_dst_alloc; - VkPipelineStageFlagBits *sem_wait_dst; - int sem_wait_dst_alloc; /* Allocated sem_wait_dst */ + VkImageLayout *layout_dst; + unsigned int layout_dst_alloc; - VkSemaphore *sem_sig; - int sem_sig_alloc; /* Allocated sem_sig */ - int sem_sig_cnt; + uint32_t *queue_family_dst; + unsigned int queue_family_dst_alloc; - uint64_t *sem_sig_val; - int sem_sig_val_alloc; - - uint64_t **sem_sig_val_dst; - int sem_sig_val_dst_alloc; + uint8_t *frame_update; + unsigned int frame_update_alloc_size; } FFVkExecContext; +typedef struct FFVkExecPool { + FFVkQueueFamilyCtx *qf; + FFVkExecContext *contexts; + atomic_int_least64_t idx; + + VkCommandPool cmd_buf_pool; + VkCommandBuffer *cmd_bufs; + int pool_size; + + VkQueryPool query_pool; + void *query_data; + int query_results; + int query_statuses; + int query_64bit; + int query_status_stride; + int nb_queries; + size_t qd_size; +} FFVkExecPool; + typedef struct FFVulkanContext { const AVClass *class; /* Filters and encoders use this */ @@ -216,14 +215,17 @@ typedef struct FFVulkanContext { VkPhysicalDeviceProperties2 props; VkPhysicalDeviceDriverProperties driver_props; VkPhysicalDeviceMemoryProperties mprops; + VkPhysicalDeviceExternalMemoryHostPropertiesEXT hprops; + VkPhysicalDeviceDescriptorBufferPropertiesEXT desc_buf_props; VkQueueFamilyQueryResultStatusPropertiesKHR *query_props; VkQueueFamilyVideoPropertiesKHR *video_props; VkQueueFamilyProperties2 *qf_props; + int tot_nb_qfs; - AVBufferRef *device_ref; AVHWDeviceContext *device; AVVulkanDeviceContext *hwctx; + AVBufferRef *input_frames_ref; AVBufferRef *frames_ref; AVHWFramesContext *frames; AVVulkanFramesContext *hwfc; @@ -231,28 +233,11 @@ typedef struct FFVulkanContext { uint32_t qfs[5]; int nb_qfs; - FFVkSPIRVCompiler *spirv_compiler; - /* 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 */ @@ -264,244 +249,207 @@ extern const VkComponentMapping ff_comp_identity_map; const char *ff_vk_ret2str(VkResult res); /** - * Loads props/mprops/driver_props - */ -int ff_vk_load_props(FFVulkanContext *s); - -/** - * Returns 1 if the image is any sort of supported RGB + * Returns 1 if pixfmt is a usable RGB format. */ int ff_vk_mt_is_np_rgb(enum AVPixelFormat pix_fmt); /** - * Gets the glsl format string for a pixel format + * Returns the format to use for images in shaders. */ const char *ff_vk_shader_rep_fmt(enum AVPixelFormat pixfmt); /** - * Setup the queue families from the hardware device context. - * Necessary for image creation to work. - */ -void ff_vk_qf_fill(FFVulkanContext *s); - -/** - * Allocate device memory. - */ -int ff_vk_alloc_mem(FFVulkanContext *s, VkMemoryRequirements *req, - VkMemoryPropertyFlagBits req_flags, void *alloc_extension, - VkMemoryPropertyFlagBits *mem_flags, VkDeviceMemory *mem); - -/** - * Get a queue family index and the number of queues. nb is optional. + * Loads props/mprops/driver_props */ -int ff_vk_qf_get_index(FFVulkanContext *s, VkQueueFlagBits dev_family, int *nb); +int ff_vk_load_props(FFVulkanContext *s); /** - * Initialize a queue family with a specific number of queues. - * If nb_queues == 0, use however many queues the queue family has. + * Chooses a QF and loads it into a context. */ int ff_vk_qf_init(FFVulkanContext *s, FFVkQueueFamilyCtx *qf, - VkQueueFlagBits dev_family, int nb_queues); - -/** - * Rotate through the queues in a queue family. - */ -int 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); + VkQueueFlagBits dev_family); /** - * Create an imageview. - * Guaranteed to remain alive until the queue submission has finished executing, - * and will be destroyed after that. + * Allocates/frees an execution pool. + * ff_vk_exec_pool_init_desc() MUST be called if ff_vk_exec_descriptor_set_add() + * has been called. */ -int ff_vk_create_imageview(FFVulkanContext *s, FFVkExecContext *e, - VkImageView *v, VkImage img, VkFormat fmt, - const VkComponentMapping map); +int ff_vk_exec_pool_init(FFVulkanContext *s, FFVkQueueFamilyCtx *qf, + FFVkExecPool *pool, int nb_contexts, + int nb_queries, VkQueryType query_type, int query_64bit, + const void *query_create_pnext); +void ff_vk_exec_pool_free(FFVulkanContext *s, FFVkExecPool *pool); /** - * Define a push constant for a given stage into a pipeline. - * Must be called before the pipeline layout has been initialized. + * Retrieve an execution pool. Threadsafe. */ -int ff_vk_add_push_constant(FFVulkanPipeline *pl, int offset, int size, - VkShaderStageFlagBits stage); +FFVkExecContext *ff_vk_exec_get(FFVkExecPool *pool); /** - * Inits a pipeline. Everything in it will be auto-freed when calling - * ff_vk_filter_uninit(). + * Performs nb_queries queries and returns their results and statuses. + * Execution must have been waited on to produce valid results. */ -FFVulkanPipeline *ff_vk_create_pipeline(FFVulkanContext *s, FFVkQueueFamilyCtx *qf); +VkResult ff_vk_exec_get_query(FFVulkanContext *s, FFVkExecContext *e, + void **data, int64_t *status); /** - * Inits a shader for a specific pipeline. Will be auto-freed on uninit. + * Start/submit/wait an execution. + * ff_vk_exec_start() always waits on a submission, so using ff_vk_exec_wait() + * is not necessary (unless using it is just better). */ -FFVkSPIRVShader *ff_vk_init_shader(FFVulkanPipeline *pl, const char *name, - VkShaderStageFlags stage); +int ff_vk_exec_start(FFVulkanContext *s, FFVkExecContext *e); +int ff_vk_exec_submit(FFVulkanContext *s, FFVkExecContext *e); +void ff_vk_exec_wait(FFVulkanContext *s, FFVkExecContext *e); /** - * Writes the workgroup size for a shader. + * Execution dependency management. + * Can attach buffers to executions that will only be unref'd once the + * buffer has finished executing. + * Adding a frame dep will *lock the frame*, until either the dependencies + * are discarded, the execution is submitted, or a failure happens. + * update_frame will update the frame's properties before it is unlocked, + * only if submission was successful. */ -void ff_vk_set_compute_shader_sizes(FFVkSPIRVShader *shd, int local_size[3]); +int ff_vk_exec_add_dep_buf(FFVulkanContext *s, FFVkExecContext *e, + AVBufferRef **deps, int nb_deps, int ref); +int ff_vk_exec_add_dep_frame(FFVulkanContext *s, FFVkExecContext *e, AVFrame *f, + VkPipelineStageFlagBits2 wait_stage, + VkPipelineStageFlagBits2 signal_stage); +void ff_vk_exec_update_frame(FFVulkanContext *s, FFVkExecContext *e, AVFrame *f, + VkImageMemoryBarrier2 *bar, uint32_t *nb_img_bar); +int ff_vk_exec_mirror_sem_value(FFVulkanContext *s, FFVkExecContext *e, + VkSemaphore *dst, uint64_t *dst_val, + AVFrame *f); +void ff_vk_exec_discard_deps(FFVulkanContext *s, FFVkExecContext *e); /** - * Adds a descriptor set to the shader and registers them in the pipeline. + * Create an imageview and add it as a dependency to an execution. */ -int ff_vk_add_descriptor_set(FFVulkanContext *s, FFVulkanPipeline *pl, - FFVkSPIRVShader *shd, FFVulkanDescriptorSetBinding *desc, - int num, int only_print_to_shader); +int ff_vk_create_imageviews(FFVulkanContext *s, FFVkExecContext *e, + VkImageView views[AV_NUM_DATA_POINTERS], + AVFrame *f); -/** - * Compiles the shader, entrypoint must be set to "main". - */ -int ff_vk_compile_shader(FFVulkanContext *s, FFVkSPIRVShader *shd, - const char *entrypoint); +void ff_vk_frame_barrier(FFVulkanContext *s, FFVkExecContext *e, + AVFrame *pic, VkImageMemoryBarrier2 *bar, int *nb_bar, + VkPipelineStageFlags src_stage, + VkPipelineStageFlags dst_stage, + VkAccessFlagBits new_access, + VkImageLayout new_layout, + uint32_t new_qf); /** - * Pretty print shader, mainly used by shader compilers. + * Memory/buffer/image allocation helpers. */ -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); +int ff_vk_alloc_mem(FFVulkanContext *s, VkMemoryRequirements *req, + VkMemoryPropertyFlagBits req_flags, void *alloc_extension, + VkMemoryPropertyFlagBits *mem_flags, VkDeviceMemory *mem); +int ff_vk_create_buf(FFVulkanContext *s, FFVkBuffer *buf, size_t size, + void *pNext, void *alloc_pNext, + VkBufferUsageFlags usage, VkMemoryPropertyFlagBits flags); +int ff_vk_create_avbuf(FFVulkanContext *s, AVBufferRef **ref, size_t size, + void *pNext, void *alloc_pNext, + VkBufferUsageFlags usage, VkMemoryPropertyFlagBits flags); /** - * Initializes a compute pipeline. Will pick the first shader with the - * COMPUTE flag set. + * Buffer management code. */ -int ff_vk_init_compute_pipeline(FFVulkanContext *s, FFVulkanPipeline *pl); +int ff_vk_map_buffers(FFVulkanContext *s, FFVkBuffer **buf, uint8_t *mem[], + int nb_buffers, int invalidate); +int ff_vk_unmap_buffers(FFVulkanContext *s, FFVkBuffer **buf, int nb_buffers, + int flush); -/** - * 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); +static inline int ff_vk_map_buffer(FFVulkanContext *s, FFVkBuffer *buf, uint8_t **mem, + int invalidate) +{ + return ff_vk_map_buffers(s, (FFVkBuffer *[]){ buf }, mem, + 1, invalidate); +} -/** - * 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); +static inline int ff_vk_unmap_buffer(FFVulkanContext *s, FFVkBuffer *buf, int flush) +{ + return ff_vk_unmap_buffers(s, (FFVkBuffer *[]){ buf }, 1, flush); +} -/** - * Create a query pool for a command context. - * elem_64bits exists to troll driver devs for compliance. All results - * and statuses returned should be 32 bits, unless this is set, then it's 64bits. - */ -int ff_vk_create_exec_ctx_query_pool(FFVulkanContext *s, FFVkExecContext *e, - int nb_queries, VkQueryType type, - int elem_64bits, void *create_pnext); +void ff_vk_free_buf(FFVulkanContext *s, FFVkBuffer *buf); -/** - * Get results for query. - * Returns the status of the query. - * Sets *res to the status of the queries. - */ -int ff_vk_get_exec_ctx_query_results(FFVulkanContext *s, FFVkExecContext *e, - int query_idx, void **data, int64_t *status); +/** Initialize a pool and create AVBufferRefs containing FFVkBuffer. + * Threadsafe to use. Buffers are automatically mapped on creation if + * VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT is set in mem_props. Users should + * synchronize access themselvesd. Mainly meant for device-local buffers. */ +int ff_vk_get_pooled_buffer(FFVulkanContext *ctx, AVBufferPool **buf_pool, + AVBufferRef **buf, VkBufferUsageFlags usage, + void *create_pNext, size_t size, + VkMemoryPropertyFlagBits mem_props); /** - * Begin recording to the command buffer. Previous execution must have been - * completed, which ff_vk_submit_exec_queue() will ensure. + * Create a sampler. */ -int ff_vk_start_exec_recording(FFVulkanContext *s, FFVkExecContext *e); +int ff_vk_init_sampler(FFVulkanContext *s, VkSampler *sampler, + int unnorm_coords, VkFilter filt); /** - * Add a command to bind the completed pipeline and its descriptor sets. - * Must be called after ff_vk_start_exec_recording() and before submission. + * Shader management. */ -void ff_vk_bind_pipeline_exec(FFVulkanContext *s, FFVkExecContext *e, - FFVulkanPipeline *pl); +int ff_vk_shader_init(FFVulkanPipeline *pl, FFVkSPIRVShader *shd, const char *name, + VkShaderStageFlags stage); +void ff_vk_shader_set_compute_sizes(FFVkSPIRVShader *shd, int x, int y, int z); +void ff_vk_shader_print(void *ctx, FFVkSPIRVShader *shd, int prio); +int ff_vk_shader_create(FFVulkanContext *s, FFVkSPIRVShader *shd, + uint8_t *spirv, size_t spirv_size, const char *entrypoint); +void ff_vk_shader_free(FFVulkanContext *s, FFVkSPIRVShader *shd); /** - * Updates push constants. - * Must be called after binding a pipeline if any push constants were defined. + * Add/update push constants for execution. */ +int ff_vk_add_push_constant(FFVulkanPipeline *pl, int offset, int size, + VkShaderStageFlagBits stage); void ff_vk_update_push_exec(FFVulkanContext *s, FFVkExecContext *e, - VkShaderStageFlagBits stage, int offset, - size_t size, void *src); + FFVulkanPipeline *pl, + VkShaderStageFlagBits stage, + int offset, size_t size, void *src); /** - * Gets the command buffer to use for this submission from the exe context. + * Add descriptor to a pipeline. Must be called before pipeline init. */ -VkCommandBuffer ff_vk_get_exec_buf(FFVkExecContext *e); +int ff_vk_pipeline_descriptor_set_add(FFVulkanContext *s, FFVulkanPipeline *pl, + FFVkSPIRVShader *shd, + FFVulkanDescriptorSetBinding *desc, int nb, + int read_only, int print_to_shader_only); -/** - * 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); +/* Initialize/free a pipeline. */ +int ff_vk_init_compute_pipeline(FFVulkanContext *s, FFVulkanPipeline *pl, + FFVkSPIRVShader *shd); +void ff_vk_pipeline_free(FFVulkanContext *s, FFVulkanPipeline *pl); /** - * Adds a frame as a queue dependency. This also manages semaphore signalling. - * Must be called before submission. + * Register a pipeline with an exec pool. + * Pool may be NULL if all descriptor sets are read-only. */ -int ff_vk_add_exec_dep(FFVulkanContext *s, FFVkExecContext *e, AVFrame *frame, - VkPipelineStageFlagBits in_wait_dst_flag); +int ff_vk_exec_pipeline_register(FFVulkanContext *s, FFVkExecPool *pool, + FFVulkanPipeline *pl); -/** - * Submits a command buffer to the queue for execution. Will not block. - */ -int ff_vk_submit_exec_queue(FFVulkanContext *s, FFVkExecContext *e); - -/** - * Wait on a command buffer's execution. Mainly useful for debugging and - * development. - */ -void ff_vk_wait_on_exec_ctx(FFVulkanContext *s, FFVkExecContext *e); - -/** - * Create a VkBuffer with the specified parameters. - */ -int ff_vk_create_buf(FFVulkanContext *s, FFVkBuffer *buf, size_t size, - void *pNext, void *alloc_pNext, - 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); +/* Bind pipeline */ +void ff_vk_exec_bind_pipeline(FFVulkanContext *s, FFVkExecContext *e, + FFVulkanPipeline *pl); -/** - * Frees a buffer. - */ -void ff_vk_free_buf(FFVulkanContext *s, FFVkBuffer *buf); +/* Update sampler/image/buffer descriptors. e may be NULL for read-only descriptors. */ +int ff_vk_set_descriptor_sampler(FFVulkanContext *s, FFVulkanPipeline *pl, + FFVkExecContext *e, int set, int bind, int offs, + VkSampler *sampler); +int ff_vk_set_descriptor_image(FFVulkanContext *s, FFVulkanPipeline *pl, + FFVkExecContext *e, int set, int bind, int offs, + VkImageView view, VkImageLayout layout, VkSampler sampler); +int ff_vk_set_descriptor_buffer(FFVulkanContext *s, FFVulkanPipeline *pl, + FFVkExecContext *e, int set, int bind, int offs, + VkDeviceAddress addr, VkDeviceSize len, VkFormat fmt); -/** - * Creates an image, allocates and binds memory in the given - * idx value of the dst frame. If mem is non-NULL, then no memory will be - * allocated, but instead the given memory will be bound to the image. - */ -int ff_vk_image_create(FFVulkanContext *s, AVVkFrame *dst, int idx, - int width, int height, VkFormat fmt, VkImageTiling tiling, - VkImageUsageFlagBits usage, VkImageCreateFlags flags, - void *create_pnext, - VkDeviceMemory *mem, void *alloc_pnext); +void ff_vk_update_descriptor_img_array(FFVulkanContext *s, FFVulkanPipeline *pl, + FFVkExecContext *e, AVFrame *f, + VkImageView *views, int set, int binding, + VkImageLayout layout, VkSampler sampler); /** - * Frees the main Vulkan context. + * Frees main context. */ void ff_vk_uninit(FFVulkanContext *s); diff --git a/libavutil/vulkan_functions.h b/libavutil/vulkan_functions.h index e06d0978078..c81e12f27ec 100644 --- a/libavutil/vulkan_functions.h +++ b/libavutil/vulkan_functions.h @@ -93,6 +93,7 @@ typedef enum FFVulkanExtensions { /* Queue */ \ MACRO(1, 1, FF_VK_EXT_NO_FLAG, GetDeviceQueue) \ MACRO(1, 1, FF_VK_EXT_NO_FLAG, QueueSubmit) \ + MACRO(1, 1, FF_VK_EXT_NO_FLAG, QueueSubmit2) \ \ /* Fences */ \ MACRO(1, 1, FF_VK_EXT_NO_FLAG, CreateFence) \ From 758f8b26b9592438027c43533bf662e5c407ae6a Mon Sep 17 00:00:00 2001 From: Lynne Date: Wed, 11 Jan 2023 09:37:18 +0100 Subject: [PATCH 1268/2172] vulkan: add ff_vk_count_images() --- libavutil/vulkan.h | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/libavutil/vulkan.h b/libavutil/vulkan.h index 7f31ced41dd..8ea009e4dab 100644 --- a/libavutil/vulkan.h +++ b/libavutil/vulkan.h @@ -240,6 +240,15 @@ typedef struct FFVulkanContext { enum AVPixelFormat input_format; } FFVulkanContext; +static inline int ff_vk_count_images(AVVkFrame *f) +{ + int cnt = 0; + while (f->img[cnt]) + cnt++; + + return cnt; +} + /* Identity mapping - r = r, b = b, g = g, a = a */ extern const VkComponentMapping ff_comp_identity_map; From 83024beec226222334d7e4166da5e4cd0869e7cc Mon Sep 17 00:00:00 2001 From: Lynne Date: Mon, 6 Mar 2023 00:19:12 +0100 Subject: [PATCH 1269/2172] vulkan: enable forcing of full subgroups --- libavutil/vulkan.c | 15 +++++++++++++-- libavutil/vulkan.h | 4 +++- 2 files changed, 16 insertions(+), 3 deletions(-) diff --git a/libavutil/vulkan.c b/libavutil/vulkan.c index 6dd4de0343b..8a1233662f6 100644 --- a/libavutil/vulkan.c +++ b/libavutil/vulkan.c @@ -90,9 +90,13 @@ int ff_vk_load_props(FFVulkanContext *s) s->hprops = (VkPhysicalDeviceExternalMemoryHostPropertiesEXT) { .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_MEMORY_HOST_PROPERTIES_EXT, }; + s->subgroup_props = (VkPhysicalDeviceSubgroupSizeControlProperties) { + .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SUBGROUP_SIZE_CONTROL_PROPERTIES, + .pNext = &s->hprops, + }; s->desc_buf_props = (VkPhysicalDeviceDescriptorBufferPropertiesEXT) { .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DESCRIPTOR_BUFFER_PROPERTIES_EXT, - .pNext = &s->hprops, + .pNext = &s->subgroup_props, }; s->driver_props = (VkPhysicalDeviceDriverProperties) { .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DRIVER_PROPERTIES, @@ -1287,13 +1291,20 @@ void ff_vk_frame_barrier(FFVulkanContext *s, FFVkExecContext *e, } int ff_vk_shader_init(FFVulkanPipeline *pl, FFVkSPIRVShader *shd, const char *name, - VkShaderStageFlags stage) + VkShaderStageFlags stage, uint32_t required_subgroup_size) { 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; + if (required_subgroup_size) { + shd->shader.flags |= VK_PIPELINE_SHADER_STAGE_CREATE_REQUIRE_FULL_SUBGROUPS_BIT; + shd->shader.pNext = &shd->subgroup_info; + shd->subgroup_info.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_REQUIRED_SUBGROUP_SIZE_CREATE_INFO; + shd->subgroup_info.requiredSubgroupSize = required_subgroup_size; + } + shd->name = name; GLSLF(0, #version %i ,460); diff --git a/libavutil/vulkan.h b/libavutil/vulkan.h index 8ea009e4dab..1dc7a61d977 100644 --- a/libavutil/vulkan.h +++ b/libavutil/vulkan.h @@ -61,6 +61,7 @@ typedef struct FFVkSPIRVShader { AVBPrint src; int local_size[3]; /* Compute shader workgroup sizes */ VkPipelineShaderStageCreateInfo shader; + VkPipelineShaderStageRequiredSubgroupSizeCreateInfo subgroup_info; } FFVkSPIRVShader; typedef struct FFVulkanDescriptorSetBinding { @@ -217,6 +218,7 @@ typedef struct FFVulkanContext { VkPhysicalDeviceMemoryProperties mprops; VkPhysicalDeviceExternalMemoryHostPropertiesEXT hprops; VkPhysicalDeviceDescriptorBufferPropertiesEXT desc_buf_props; + VkPhysicalDeviceSubgroupSizeControlProperties subgroup_props; VkQueueFamilyQueryResultStatusPropertiesKHR *query_props; VkQueueFamilyVideoPropertiesKHR *video_props; VkQueueFamilyProperties2 *qf_props; @@ -400,7 +402,7 @@ int ff_vk_init_sampler(FFVulkanContext *s, VkSampler *sampler, * Shader management. */ int ff_vk_shader_init(FFVulkanPipeline *pl, FFVkSPIRVShader *shd, const char *name, - VkShaderStageFlags stage); + VkShaderStageFlags stage, uint32_t required_subgroup_size); void ff_vk_shader_set_compute_sizes(FFVkSPIRVShader *shd, int x, int y, int z); void ff_vk_shader_print(void *ctx, FFVkSPIRVShader *shd, int prio); int ff_vk_shader_create(FFVulkanContext *s, FFVkSPIRVShader *shd, From a4d63b46d9a0ae8efeda66cd9e3e810c9fc26470 Mon Sep 17 00:00:00 2001 From: Lynne Date: Fri, 24 Mar 2023 02:22:06 +0100 Subject: [PATCH 1270/2172] vulkan: make GLSL macro functions semicolumn-safe --- libavutil/vulkan.h | 28 ++++++++++++++++++++++------ 1 file changed, 22 insertions(+), 6 deletions(-) diff --git a/libavutil/vulkan.h b/libavutil/vulkan.h index 1dc7a61d977..0831219d8fd 100644 --- a/libavutil/vulkan.h +++ b/libavutil/vulkan.h @@ -40,12 +40,28 @@ #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, ) + +#define GLSLC(N, S) \ + do { \ + av_bprintf(&shd->src, C(N, S)); \ + } while (0) + +#define GLSLA(...) \ + do { \ + av_bprintf(&shd->src, __VA_ARGS__); \ + } while (0) + +#define GLSLF(N, S, ...) \ + do { \ + av_bprintf(&shd->src, C(N, S), __VA_ARGS__); \ + } while (0) + +#define GLSLD(D) \ + do { \ + av_bprintf(&shd->src, "\n"); \ + av_bprint_append_data(&shd->src, D, strlen(D)); \ + av_bprintf(&shd->src, "\n"); \ + } while (0) /* Helper, pretty much every Vulkan return value needs to be checked */ #define RET(x) \ From 48f85de0e712af5496974ac3804928dc0838e029 Mon Sep 17 00:00:00 2001 From: Lynne Date: Wed, 11 Jan 2023 09:37:35 +0100 Subject: [PATCH 1271/2172] hwcontext_vulkan: rewrite to support multiplane surfaces This commit adds proper handling of multiplane images throughout all of the hwcontext code. To avoid breakage of individual components, the change is performed as a single commit. --- libavutil/hwcontext_vulkan.c | 791 +++++++++++++++++++---------------- libavutil/hwcontext_vulkan.h | 82 ++-- 2 files changed, 480 insertions(+), 393 deletions(-) diff --git a/libavutil/hwcontext_vulkan.c b/libavutil/hwcontext_vulkan.c index 28255929255..622dd811de1 100644 --- a/libavutil/hwcontext_vulkan.c +++ b/libavutil/hwcontext_vulkan.c @@ -1,4 +1,6 @@ /* + * Copyright (c) Lynne + * * This file is part of FFmpeg. * * FFmpeg is free software; you can redistribute it and/or @@ -67,6 +69,8 @@ typedef struct VulkanQueueCtx { VkFence fence; VkQueue queue; int was_synchronous; + int qf; + int qidx; /* Buffer dependencies */ AVBufferRef **buf_deps; @@ -116,6 +120,9 @@ typedef struct VulkanDevicePriv { /* Option to allocate all image planes in a single allocation */ int contiguous_planes; + /* Disable multiplane images */ + int disable_multiplane; + /* Nvidia */ int dev_is_nvidia; } VulkanDevicePriv; @@ -150,112 +157,207 @@ typedef struct AVVkFrameInternal { #endif } AVVkFrameInternal; -#define ADD_VAL_TO_LIST(list, count, val) \ - do { \ - list = av_realloc_array(list, sizeof(*list), ++count); \ - if (!list) { \ - err = AVERROR(ENOMEM); \ - goto fail; \ - } \ - list[count - 1] = av_strdup(val); \ - if (!list[count - 1]) { \ - err = AVERROR(ENOMEM); \ - goto fail; \ - } \ - } while(0) +#define ASPECT_2PLANE (VK_IMAGE_ASPECT_PLANE_0_BIT | VK_IMAGE_ASPECT_PLANE_1_BIT) +#define ASPECT_3PLANE (VK_IMAGE_ASPECT_PLANE_0_BIT | VK_IMAGE_ASPECT_PLANE_1_BIT | VK_IMAGE_ASPECT_PLANE_2_BIT) -#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 { +static const struct FFVkFormatEntry { + VkFormat vkf; enum AVPixelFormat pixfmt; - const VkFormat vkfmts[5]; -} vk_pixfmt_planar_map[] = { - { AV_PIX_FMT_GRAY8, { VK_FORMAT_R8_UNORM } }, - { AV_PIX_FMT_GRAY16, { VK_FORMAT_R16_UNORM } }, - { AV_PIX_FMT_GRAYF32, { VK_FORMAT_R32_SFLOAT } }, - - { AV_PIX_FMT_NV12, { VK_FORMAT_R8_UNORM, VK_FORMAT_R8G8_UNORM } }, - { AV_PIX_FMT_NV21, { VK_FORMAT_R8_UNORM, VK_FORMAT_R8G8_UNORM } }, - { AV_PIX_FMT_P010, { VK_FORMAT_R16_UNORM, VK_FORMAT_R16G16_UNORM } }, - { AV_PIX_FMT_P012, { VK_FORMAT_R16_UNORM, VK_FORMAT_R16G16_UNORM } }, - { AV_PIX_FMT_P016, { VK_FORMAT_R16_UNORM, VK_FORMAT_R16G16_UNORM } }, - - { AV_PIX_FMT_NV16, { VK_FORMAT_R8_UNORM, VK_FORMAT_R8G8_UNORM } }, - - { AV_PIX_FMT_NV24, { VK_FORMAT_R8_UNORM, VK_FORMAT_R8G8_UNORM } }, - { AV_PIX_FMT_NV42, { VK_FORMAT_R8_UNORM, VK_FORMAT_R8G8_UNORM } }, - - { AV_PIX_FMT_YUV420P, { VK_FORMAT_R8_UNORM, VK_FORMAT_R8_UNORM, VK_FORMAT_R8_UNORM } }, - { AV_PIX_FMT_YUV420P10, { VK_FORMAT_R16_UNORM, VK_FORMAT_R16_UNORM, VK_FORMAT_R16_UNORM } }, - { AV_PIX_FMT_YUV420P12, { VK_FORMAT_R16_UNORM, VK_FORMAT_R16_UNORM, VK_FORMAT_R16_UNORM } }, - { AV_PIX_FMT_YUV420P16, { VK_FORMAT_R16_UNORM, VK_FORMAT_R16_UNORM, VK_FORMAT_R16_UNORM } }, - - { AV_PIX_FMT_YUV422P, { VK_FORMAT_R8_UNORM, VK_FORMAT_R8_UNORM, VK_FORMAT_R8_UNORM } }, - { AV_PIX_FMT_YUV422P10, { VK_FORMAT_R16_UNORM, VK_FORMAT_R16_UNORM, VK_FORMAT_R16_UNORM } }, - { AV_PIX_FMT_YUV422P12, { VK_FORMAT_R16_UNORM, VK_FORMAT_R16_UNORM, VK_FORMAT_R16_UNORM } }, - { AV_PIX_FMT_YUV422P16, { VK_FORMAT_R16_UNORM, VK_FORMAT_R16_UNORM, VK_FORMAT_R16_UNORM } }, - - { AV_PIX_FMT_YUV444P, { VK_FORMAT_R8_UNORM, VK_FORMAT_R8_UNORM, VK_FORMAT_R8_UNORM } }, - { AV_PIX_FMT_YUV444P10, { VK_FORMAT_R16_UNORM, VK_FORMAT_R16_UNORM, VK_FORMAT_R16_UNORM } }, - { AV_PIX_FMT_YUV444P12, { VK_FORMAT_R16_UNORM, VK_FORMAT_R16_UNORM, VK_FORMAT_R16_UNORM } }, - { AV_PIX_FMT_YUV444P16, { VK_FORMAT_R16_UNORM, VK_FORMAT_R16_UNORM, VK_FORMAT_R16_UNORM } }, - - { AV_PIX_FMT_YUVA420P, { VK_FORMAT_R8_UNORM, VK_FORMAT_R8_UNORM, VK_FORMAT_R8_UNORM, VK_FORMAT_R8_UNORM } }, - { AV_PIX_FMT_YUVA420P10, { VK_FORMAT_R16_UNORM, VK_FORMAT_R16_UNORM, VK_FORMAT_R16_UNORM, VK_FORMAT_R16_UNORM } }, - /* There is no AV_PIX_FMT_YUVA420P12 */ - { AV_PIX_FMT_YUVA420P16, { VK_FORMAT_R16_UNORM, VK_FORMAT_R16_UNORM, VK_FORMAT_R16_UNORM, VK_FORMAT_R16_UNORM } }, - - { AV_PIX_FMT_YUVA422P, { VK_FORMAT_R8_UNORM, VK_FORMAT_R8_UNORM, VK_FORMAT_R8_UNORM, VK_FORMAT_R8_UNORM } }, - { AV_PIX_FMT_YUVA422P10, { VK_FORMAT_R16_UNORM, VK_FORMAT_R16_UNORM, VK_FORMAT_R16_UNORM, VK_FORMAT_R16_UNORM } }, - { AV_PIX_FMT_YUVA422P12, { VK_FORMAT_R16_UNORM, VK_FORMAT_R16_UNORM, VK_FORMAT_R16_UNORM, VK_FORMAT_R16_UNORM } }, - { AV_PIX_FMT_YUVA422P16, { VK_FORMAT_R16_UNORM, VK_FORMAT_R16_UNORM, VK_FORMAT_R16_UNORM, VK_FORMAT_R16_UNORM } }, - - { AV_PIX_FMT_YUVA444P, { VK_FORMAT_R8_UNORM, VK_FORMAT_R8_UNORM, VK_FORMAT_R8_UNORM, VK_FORMAT_R8_UNORM } }, - { AV_PIX_FMT_YUVA444P10, { VK_FORMAT_R16_UNORM, VK_FORMAT_R16_UNORM, VK_FORMAT_R16_UNORM, VK_FORMAT_R16_UNORM } }, - { AV_PIX_FMT_YUVA444P12, { VK_FORMAT_R16_UNORM, VK_FORMAT_R16_UNORM, VK_FORMAT_R16_UNORM, VK_FORMAT_R16_UNORM } }, - { AV_PIX_FMT_YUVA444P16, { VK_FORMAT_R16_UNORM, VK_FORMAT_R16_UNORM, VK_FORMAT_R16_UNORM, VK_FORMAT_R16_UNORM } }, - - { AV_PIX_FMT_VUYX, { VK_FORMAT_R8G8B8A8_UNORM } }, - { AV_PIX_FMT_XV36, { VK_FORMAT_R16G16B16A16_UNORM } }, - - { AV_PIX_FMT_BGRA, { VK_FORMAT_B8G8R8A8_UNORM } }, - { AV_PIX_FMT_RGBA, { VK_FORMAT_R8G8B8A8_UNORM } }, - { AV_PIX_FMT_RGB24, { VK_FORMAT_R8G8B8_UNORM } }, - { AV_PIX_FMT_BGR24, { VK_FORMAT_B8G8R8_UNORM } }, - { AV_PIX_FMT_RGB48, { VK_FORMAT_R16G16B16_UNORM } }, - { AV_PIX_FMT_RGBA64, { VK_FORMAT_R16G16B16A16_UNORM } }, - { AV_PIX_FMT_RGBA64, { VK_FORMAT_R16G16B16A16_UNORM } }, - { AV_PIX_FMT_RGB565, { VK_FORMAT_R5G6B5_UNORM_PACK16 } }, - { AV_PIX_FMT_BGR565, { VK_FORMAT_B5G6R5_UNORM_PACK16 } }, - { AV_PIX_FMT_BGR0, { VK_FORMAT_B8G8R8A8_UNORM } }, - { AV_PIX_FMT_RGB0, { VK_FORMAT_R8G8B8A8_UNORM } }, - - /* Lower priority as there's an endianess-dependent overlap between these - * and rgba/bgr0, and PACK32 formats are more limited */ - { AV_PIX_FMT_BGR32, { VK_FORMAT_A8B8G8R8_UNORM_PACK32 } }, - { AV_PIX_FMT_0BGR32, { VK_FORMAT_A8B8G8R8_UNORM_PACK32 } }, - - { AV_PIX_FMT_X2RGB10, { VK_FORMAT_A2R10G10B10_UNORM_PACK32 } }, - - { AV_PIX_FMT_GBRAP, { VK_FORMAT_R8_UNORM, VK_FORMAT_R8_UNORM, VK_FORMAT_R8_UNORM, VK_FORMAT_R8_UNORM } }, - { AV_PIX_FMT_GBRAP16, { VK_FORMAT_R16_UNORM, VK_FORMAT_R16_UNORM, VK_FORMAT_R16_UNORM, VK_FORMAT_R16_UNORM } }, - { AV_PIX_FMT_GBRPF32, { VK_FORMAT_R32_SFLOAT, VK_FORMAT_R32_SFLOAT, VK_FORMAT_R32_SFLOAT } }, - { AV_PIX_FMT_GBRAPF32, { VK_FORMAT_R32_SFLOAT, VK_FORMAT_R32_SFLOAT, VK_FORMAT_R32_SFLOAT, VK_FORMAT_R32_SFLOAT } }, + VkImageAspectFlags aspect; + int vk_planes; + int nb_images; + int nb_images_fallback; + const VkFormat fallback[5]; +} vk_formats_list[] = { + /* Gray formats */ + { VK_FORMAT_R8_UNORM, AV_PIX_FMT_GRAY8, VK_IMAGE_ASPECT_COLOR_BIT, 1, 1, 1, { VK_FORMAT_R8_UNORM } }, + { VK_FORMAT_R16_UNORM, AV_PIX_FMT_GRAY16, VK_IMAGE_ASPECT_COLOR_BIT, 1, 1, 1, { VK_FORMAT_R16_UNORM } }, + { VK_FORMAT_R32_SFLOAT, AV_PIX_FMT_GRAYF32, VK_IMAGE_ASPECT_COLOR_BIT, 1, 1, 1, { VK_FORMAT_R32_SFLOAT } }, + + /* RGB formats */ + { VK_FORMAT_R16G16B16A16_UNORM, AV_PIX_FMT_XV36, VK_IMAGE_ASPECT_COLOR_BIT, 1, 1, 1, { VK_FORMAT_R16G16B16A16_UNORM } }, + { VK_FORMAT_B8G8R8A8_UNORM, AV_PIX_FMT_BGRA, VK_IMAGE_ASPECT_COLOR_BIT, 1, 1, 1, { VK_FORMAT_B8G8R8A8_UNORM } }, + { VK_FORMAT_R8G8B8A8_UNORM, AV_PIX_FMT_RGBA, VK_IMAGE_ASPECT_COLOR_BIT, 1, 1, 1, { VK_FORMAT_R8G8B8A8_UNORM } }, + { VK_FORMAT_R8G8B8_UNORM, AV_PIX_FMT_RGB24, VK_IMAGE_ASPECT_COLOR_BIT, 1, 1, 1, { VK_FORMAT_R8G8B8_UNORM } }, + { VK_FORMAT_B8G8R8_UNORM, AV_PIX_FMT_BGR24, VK_IMAGE_ASPECT_COLOR_BIT, 1, 1, 1, { VK_FORMAT_B8G8R8_UNORM } }, + { VK_FORMAT_R16G16B16_UNORM, AV_PIX_FMT_RGB48, VK_IMAGE_ASPECT_COLOR_BIT, 1, 1, 1, { VK_FORMAT_R16G16B16_UNORM } }, + { VK_FORMAT_R16G16B16A16_UNORM, AV_PIX_FMT_RGBA64, VK_IMAGE_ASPECT_COLOR_BIT, 1, 1, 1, { VK_FORMAT_R16G16B16A16_UNORM } }, + { VK_FORMAT_R5G6B5_UNORM_PACK16, AV_PIX_FMT_RGB565, VK_IMAGE_ASPECT_COLOR_BIT, 1, 1, 1, { VK_FORMAT_R5G6B5_UNORM_PACK16 } }, + { VK_FORMAT_B5G6R5_UNORM_PACK16, AV_PIX_FMT_BGR565, VK_IMAGE_ASPECT_COLOR_BIT, 1, 1, 1, { VK_FORMAT_B5G6R5_UNORM_PACK16 } }, + { VK_FORMAT_B8G8R8A8_UNORM, AV_PIX_FMT_BGR0, VK_IMAGE_ASPECT_COLOR_BIT, 1, 1, 1, { VK_FORMAT_B8G8R8A8_UNORM } }, + { VK_FORMAT_R8G8B8A8_UNORM, AV_PIX_FMT_RGB0, VK_IMAGE_ASPECT_COLOR_BIT, 1, 1, 1, { VK_FORMAT_R8G8B8A8_UNORM } }, + { VK_FORMAT_A2R10G10B10_UNORM_PACK32, AV_PIX_FMT_X2RGB10, VK_IMAGE_ASPECT_COLOR_BIT, 1, 1, 1, { VK_FORMAT_A2R10G10B10_UNORM_PACK32 } }, + + /* Planar RGB */ + { VK_FORMAT_R8_UNORM, AV_PIX_FMT_GBRAP, VK_IMAGE_ASPECT_COLOR_BIT, 1, 4, 4, { VK_FORMAT_R8_UNORM, VK_FORMAT_R8_UNORM, VK_FORMAT_R8_UNORM, VK_FORMAT_R8_UNORM } }, + { VK_FORMAT_R16_UNORM, AV_PIX_FMT_GBRAP16, VK_IMAGE_ASPECT_COLOR_BIT, 1, 4, 4, { VK_FORMAT_R16_UNORM, VK_FORMAT_R16_UNORM, VK_FORMAT_R16_UNORM, VK_FORMAT_R16_UNORM } }, + { VK_FORMAT_R32_SFLOAT, AV_PIX_FMT_GBRPF32, VK_IMAGE_ASPECT_COLOR_BIT, 1, 3, 3, { VK_FORMAT_R32_SFLOAT, VK_FORMAT_R32_SFLOAT, VK_FORMAT_R32_SFLOAT } }, + { VK_FORMAT_R32_SFLOAT, AV_PIX_FMT_GBRAPF32, VK_IMAGE_ASPECT_COLOR_BIT, 1, 4, 4, { VK_FORMAT_R32_SFLOAT, VK_FORMAT_R32_SFLOAT, VK_FORMAT_R32_SFLOAT, VK_FORMAT_R32_SFLOAT } }, + + /* Two-plane 420 YUV at 8, 10, 12 and 16 bits */ + { VK_FORMAT_G8_B8R8_2PLANE_420_UNORM, AV_PIX_FMT_NV12, ASPECT_2PLANE, 2, 1, 2, { VK_FORMAT_R8_UNORM, VK_FORMAT_R8G8_UNORM } }, + { VK_FORMAT_G10X6_B10X6R10X6_2PLANE_420_UNORM_3PACK16, AV_PIX_FMT_P010, ASPECT_2PLANE, 2, 1, 2, { VK_FORMAT_R16_UNORM, VK_FORMAT_R16G16_UNORM } }, + { VK_FORMAT_G12X4_B12X4R12X4_2PLANE_420_UNORM_3PACK16, AV_PIX_FMT_P012, ASPECT_2PLANE, 2, 1, 2, { VK_FORMAT_R16_UNORM, VK_FORMAT_R16G16_UNORM } }, + { VK_FORMAT_G16_B16R16_2PLANE_420_UNORM, AV_PIX_FMT_P016, ASPECT_2PLANE, 2, 1, 2, { VK_FORMAT_R16_UNORM, VK_FORMAT_R16G16_UNORM } }, + + /* Two-plane 422 YUV at 8, 10 and 16 bits */ + { VK_FORMAT_G8_B8R8_2PLANE_422_UNORM, AV_PIX_FMT_NV16, ASPECT_2PLANE, 2, 1, 2, { VK_FORMAT_R8_UNORM, VK_FORMAT_R8G8_UNORM } }, + { VK_FORMAT_G10X6_B10X6R10X6_2PLANE_422_UNORM_3PACK16, AV_PIX_FMT_P210, ASPECT_2PLANE, 2, 1, 2, { VK_FORMAT_R16_UNORM, VK_FORMAT_R16G16_UNORM } }, + { VK_FORMAT_G12X4_B12X4R12X4_2PLANE_422_UNORM_3PACK16, AV_PIX_FMT_P212, ASPECT_2PLANE, 2, 1, 2, { VK_FORMAT_R16_UNORM, VK_FORMAT_R16G16_UNORM } }, + { VK_FORMAT_G16_B16R16_2PLANE_422_UNORM, AV_PIX_FMT_P216, ASPECT_2PLANE, 2, 1, 2, { VK_FORMAT_R16_UNORM, VK_FORMAT_R16G16_UNORM } }, + + /* Two-plane 444 YUV at 8, 10 and 16 bits */ + { VK_FORMAT_G8_B8R8_2PLANE_444_UNORM, AV_PIX_FMT_NV24, ASPECT_2PLANE, 2, 1, 2, { VK_FORMAT_R8_UNORM, VK_FORMAT_R8G8_UNORM } }, + { VK_FORMAT_G10X6_B10X6R10X6_2PLANE_444_UNORM_3PACK16, AV_PIX_FMT_P410, ASPECT_2PLANE, 2, 1, 2, { VK_FORMAT_R16_UNORM, VK_FORMAT_R16G16_UNORM } }, + { VK_FORMAT_G12X4_B12X4R12X4_2PLANE_444_UNORM_3PACK16, AV_PIX_FMT_P412, ASPECT_2PLANE, 2, 1, 2, { VK_FORMAT_R16_UNORM, VK_FORMAT_R16G16_UNORM } }, + { VK_FORMAT_G16_B16R16_2PLANE_444_UNORM, AV_PIX_FMT_P416, ASPECT_2PLANE, 2, 1, 2, { VK_FORMAT_R16_UNORM, VK_FORMAT_R16G16_UNORM } }, + + /* Three-plane 420, 422, 444 at 8, 10, 12 and 16 bits */ + { VK_FORMAT_G8_B8_R8_3PLANE_420_UNORM, AV_PIX_FMT_YUV420P, ASPECT_3PLANE, 3, 1, 3, { VK_FORMAT_R8_UNORM, VK_FORMAT_R8_UNORM, VK_FORMAT_R8_UNORM } }, + { VK_FORMAT_G16_B16_R16_3PLANE_420_UNORM, AV_PIX_FMT_YUV420P10, ASPECT_3PLANE, 3, 1, 3, { VK_FORMAT_R16_UNORM, VK_FORMAT_R16_UNORM, VK_FORMAT_R16_UNORM } }, + { VK_FORMAT_G16_B16_R16_3PLANE_420_UNORM, AV_PIX_FMT_YUV420P12, ASPECT_3PLANE, 3, 1, 3, { VK_FORMAT_R16_UNORM, VK_FORMAT_R16_UNORM, VK_FORMAT_R16_UNORM } }, + { VK_FORMAT_G16_B16_R16_3PLANE_420_UNORM, AV_PIX_FMT_YUV420P16, ASPECT_3PLANE, 3, 1, 3, { VK_FORMAT_R16_UNORM, VK_FORMAT_R16_UNORM, VK_FORMAT_R16_UNORM } }, + { VK_FORMAT_G8_B8_R8_3PLANE_422_UNORM, AV_PIX_FMT_YUV422P, ASPECT_3PLANE, 3, 1, 3, { VK_FORMAT_R8_UNORM, VK_FORMAT_R8_UNORM, VK_FORMAT_R8_UNORM } }, + { VK_FORMAT_G16_B16_R16_3PLANE_422_UNORM, AV_PIX_FMT_YUV422P10, ASPECT_3PLANE, 3, 1, 3, { VK_FORMAT_R16_UNORM, VK_FORMAT_R16_UNORM, VK_FORMAT_R16_UNORM } }, + { VK_FORMAT_G16_B16_R16_3PLANE_422_UNORM, AV_PIX_FMT_YUV422P12, ASPECT_3PLANE, 3, 1, 3, { VK_FORMAT_R16_UNORM, VK_FORMAT_R16_UNORM, VK_FORMAT_R16_UNORM } }, + { VK_FORMAT_G16_B16_R16_3PLANE_422_UNORM, AV_PIX_FMT_YUV422P16, ASPECT_3PLANE, 3, 1, 3, { VK_FORMAT_R16_UNORM, VK_FORMAT_R16_UNORM, VK_FORMAT_R16_UNORM } }, + { VK_FORMAT_G8_B8_R8_3PLANE_444_UNORM, AV_PIX_FMT_YUV444P, ASPECT_3PLANE, 3, 1, 3, { VK_FORMAT_R8_UNORM, VK_FORMAT_R8_UNORM, VK_FORMAT_R8_UNORM } }, + { VK_FORMAT_G16_B16_R16_3PLANE_444_UNORM, AV_PIX_FMT_YUV444P10, ASPECT_3PLANE, 3, 1, 3, { VK_FORMAT_R16_UNORM, VK_FORMAT_R16_UNORM, VK_FORMAT_R16_UNORM } }, + { VK_FORMAT_G16_B16_R16_3PLANE_444_UNORM, AV_PIX_FMT_YUV444P12, ASPECT_3PLANE, 3, 1, 3, { VK_FORMAT_R16_UNORM, VK_FORMAT_R16_UNORM, VK_FORMAT_R16_UNORM } }, + { VK_FORMAT_G16_B16_R16_3PLANE_444_UNORM, AV_PIX_FMT_YUV444P16, ASPECT_3PLANE, 3, 1, 3, { VK_FORMAT_R16_UNORM, VK_FORMAT_R16_UNORM, VK_FORMAT_R16_UNORM } }, + + /* Single plane 422 at 8, 10 and 12 bits */ + { VK_FORMAT_G8B8G8R8_422_UNORM, AV_PIX_FMT_YUYV422, VK_IMAGE_ASPECT_COLOR_BIT, 1, 1, 1, { VK_FORMAT_R8G8B8A8_UNORM } }, + { VK_FORMAT_B8G8R8G8_422_UNORM, AV_PIX_FMT_UYVY422, VK_IMAGE_ASPECT_COLOR_BIT, 1, 1, 1, { VK_FORMAT_R8G8B8A8_UNORM } }, + { VK_FORMAT_G10X6B10X6G10X6R10X6_422_UNORM_4PACK16, AV_PIX_FMT_Y210, VK_IMAGE_ASPECT_COLOR_BIT, 1, 1, 1, { VK_FORMAT_R16G16B16A16_UNORM } }, + { VK_FORMAT_G12X4B12X4G12X4R12X4_422_UNORM_4PACK16, AV_PIX_FMT_Y212, VK_IMAGE_ASPECT_COLOR_BIT, 1, 1, 1, { VK_FORMAT_R16G16B16A16_UNORM } }, }; +static const int nb_vk_formats_list = FF_ARRAY_ELEMS(vk_formats_list); const VkFormat *av_vkfmt_from_pixfmt(enum AVPixelFormat p) { - for (enum AVPixelFormat i = 0; i < FF_ARRAY_ELEMS(vk_pixfmt_planar_map); i++) - if (vk_pixfmt_planar_map[i].pixfmt == p) - return vk_pixfmt_planar_map[i].vkfmts; + for (int i = 0; i < nb_vk_formats_list; i++) + if (vk_formats_list[i].pixfmt == p) + return vk_formats_list[i].fallback; return NULL; } +static const struct FFVkFormatEntry *vk_find_format_entry(enum AVPixelFormat p) +{ + for (int i = 0; i < nb_vk_formats_list; i++) + if (vk_formats_list[i].pixfmt == p) + return &vk_formats_list[i]; + return NULL; +} + +/* Malitia pura, Khronos */ +#define FN_MAP_TO(dst_t, dst_name, src_t, src_name) \ + static av_unused dst_t map_ ##src_name## _to_ ##dst_name(src_t src) \ + { \ + dst_t dst = 0x0; \ + MAP_TO(VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_BIT, \ + VK_IMAGE_USAGE_SAMPLED_BIT); \ + MAP_TO(VK_FORMAT_FEATURE_2_TRANSFER_SRC_BIT, \ + VK_IMAGE_USAGE_TRANSFER_SRC_BIT); \ + MAP_TO(VK_FORMAT_FEATURE_2_TRANSFER_DST_BIT, \ + VK_IMAGE_USAGE_TRANSFER_DST_BIT); \ + MAP_TO(VK_FORMAT_FEATURE_2_STORAGE_IMAGE_BIT, \ + VK_IMAGE_USAGE_STORAGE_BIT); \ + MAP_TO(VK_FORMAT_FEATURE_2_COLOR_ATTACHMENT_BIT, \ + VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT); \ + MAP_TO(VK_FORMAT_FEATURE_2_VIDEO_DECODE_OUTPUT_BIT_KHR, \ + VK_IMAGE_USAGE_VIDEO_DECODE_DST_BIT_KHR); \ + MAP_TO(VK_FORMAT_FEATURE_2_VIDEO_DECODE_DPB_BIT_KHR, \ + VK_IMAGE_USAGE_VIDEO_DECODE_DPB_BIT_KHR); \ + MAP_TO(VK_FORMAT_FEATURE_2_VIDEO_ENCODE_DPB_BIT_KHR, \ + VK_IMAGE_USAGE_VIDEO_ENCODE_DPB_BIT_KHR); \ + MAP_TO(VK_FORMAT_FEATURE_2_VIDEO_ENCODE_INPUT_BIT_KHR, \ + VK_IMAGE_USAGE_VIDEO_ENCODE_SRC_BIT_KHR); \ + return dst; \ + } + +#define MAP_TO(flag1, flag2) if (src & flag2) dst |= flag1; +FN_MAP_TO(VkFormatFeatureFlagBits2, feats, VkImageUsageFlags, usage) +#undef MAP_TO +#define MAP_TO(flag1, flag2) if (src & flag1) dst |= flag2; +FN_MAP_TO(VkImageUsageFlags, usage, VkFormatFeatureFlagBits2, feats) +#undef MAP_TO +#undef FN_MAP_TO + +static int vkfmt_from_pixfmt2(AVHWDeviceContext *dev_ctx, enum AVPixelFormat p, + VkImageTiling tiling, + VkFormat fmts[AV_NUM_DATA_POINTERS], + int *nb_images, VkImageAspectFlags *aspect, + VkImageUsageFlags *supported_usage, int disable_multiplane) +{ + AVVulkanDeviceContext *hwctx = dev_ctx->hwctx; + VulkanDevicePriv *priv = dev_ctx->internal->priv; + FFVulkanFunctions *vk = &priv->vkfn; + + const VkFormatFeatureFlagBits2 basic_flags = VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_BIT | + VK_FORMAT_FEATURE_2_TRANSFER_SRC_BIT | + VK_FORMAT_FEATURE_2_TRANSFER_DST_BIT; + + for (int i = 0; i < nb_vk_formats_list; i++) { + if (vk_formats_list[i].pixfmt == p) { + VkFormatProperties2 prop = { + .sType = VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2, + }; + VkFormatFeatureFlagBits2 feats_primary, feats_secondary; + int basics_primary = 0, basics_secondary = 0; + + vk->GetPhysicalDeviceFormatProperties2(hwctx->phys_dev, + vk_formats_list[i].vkf, + &prop); + + feats_primary = tiling == VK_IMAGE_TILING_LINEAR ? + prop.formatProperties.linearTilingFeatures : + prop.formatProperties.optimalTilingFeatures; + basics_primary = (feats_primary & basic_flags) == basic_flags; + + if (vk_formats_list[i].vkf != vk_formats_list[i].fallback[0]) { + vk->GetPhysicalDeviceFormatProperties2(hwctx->phys_dev, + vk_formats_list[i].fallback[0], + &prop); + feats_secondary = tiling == VK_IMAGE_TILING_LINEAR ? + prop.formatProperties.linearTilingFeatures : + prop.formatProperties.optimalTilingFeatures; + basics_secondary = (feats_secondary & basic_flags) == basic_flags; + } else { + basics_secondary = basics_primary; + } + + if (basics_primary && !(disable_multiplane && vk_formats_list[i].vk_planes > 1)) { + if (fmts) + fmts[0] = vk_formats_list[i].vkf; + if (nb_images) + *nb_images = 1; + if (aspect) + *aspect = vk_formats_list[i].aspect; + if (supported_usage) + *supported_usage = map_feats_to_usage(feats_primary); + return 0; + } else if (basics_secondary) { + if (fmts) { + for (int j = 0; j < vk_formats_list[i].nb_images_fallback; j++) + fmts[j] = vk_formats_list[i].fallback[j]; + } + if (nb_images) + *nb_images = vk_formats_list[i].nb_images_fallback; + if (aspect) + *aspect = vk_formats_list[i].aspect; + if (supported_usage) + *supported_usage = map_feats_to_usage(feats_secondary); + return 0; + } else { + return AVERROR(ENOTSUP); + } + } + } + + return AVERROR(EINVAL); +} + static const void *vk_find_struct(const void *chain, VkStructureType stype) { const VkBaseInStructure *in = chain; @@ -281,33 +383,6 @@ static void vk_link_struct(void *chain, void *in) out->pNext = in; } -static int pixfmt_is_supported(AVHWDeviceContext *dev_ctx, enum AVPixelFormat p, - int linear) -{ - AVVulkanDeviceContext *hwctx = dev_ctx->hwctx; - VulkanDevicePriv *priv = dev_ctx->internal->priv; - FFVulkanFunctions *vk = &priv->vkfn; - const VkFormat *fmt = av_vkfmt_from_pixfmt(p); - int planes = av_pix_fmt_count_planes(p); - - if (!fmt) - return 0; - - for (int i = 0; i < planes; i++) { - VkFormatFeatureFlags flags; - VkFormatProperties2 prop = { - .sType = VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2, - }; - vk->GetPhysicalDeviceFormatProperties2(hwctx->phys_dev, fmt[i], &prop); - flags = linear ? prop.formatProperties.linearTilingFeatures : - prop.formatProperties.optimalTilingFeatures; - if (!(flags & FF_VK_DEFAULT_USAGE_FLAGS)) - return 0; - } - - return 1; -} - static int load_libvulkan(AVHWDeviceContext *ctx) { AVVulkanDeviceContext *hwctx = ctx->hwctx; @@ -442,6 +517,27 @@ static VkBool32 VKAPI_CALL vk_dbg_callback(VkDebugUtilsMessageSeverityFlagBitsEX return 0; } +#define ADD_VAL_TO_LIST(list, count, val) \ + do { \ + list = av_realloc_array(list, sizeof(*list), ++count); \ + if (!list) { \ + err = AVERROR(ENOMEM); \ + goto fail; \ + } \ + list[count - 1] = av_strdup(val); \ + if (!list[count - 1]) { \ + err = AVERROR(ENOMEM); \ + goto fail; \ + } \ + } 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 int check_extensions(AVHWDeviceContext *ctx, int dev, AVDictionary *opts, const char * const **dst, uint32_t *num, int debug) { @@ -690,6 +786,10 @@ static int create_instance(AVHWDeviceContext *ctx, AVDictionary *opts) AVVulkanDeviceContext *hwctx = ctx->hwctx; VkApplicationInfo application_info = { .sType = VK_STRUCTURE_TYPE_APPLICATION_INFO, + .pApplicationName = "ffmpeg", + .applicationVersion = VK_MAKE_VERSION(LIBAVUTIL_VERSION_MAJOR, + LIBAVUTIL_VERSION_MINOR, + LIBAVUTIL_VERSION_MICRO), .pEngineName = "libavutil", .apiVersion = VK_API_VERSION_1_3, .engineVersion = VK_MAKE_VERSION(LIBAVUTIL_VERSION_MAJOR, @@ -1173,6 +1273,8 @@ static int create_exec_ctx(AVHWFramesContext *hwfc, VulkanExecCtx *cmd, VulkanQueueCtx *q = &cmd->queues[i]; vk->GetDeviceQueue(hwctx->act_dev, queue_family_index, i, &q->queue); q->was_synchronous = 1; + q->qf = queue_family_index; + q->qidx = i; } return 0; @@ -1308,6 +1410,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; + AVVulkanDeviceContext *hwctx = hwfc->device_ctx->hwctx; FFVulkanFunctions *vk = &p->vkfn; ret = vk->EndCommandBuffer(cmd->bufs[cmd->cur_queue_idx]); @@ -1321,7 +1424,9 @@ static int submit_exec_ctx(AVHWFramesContext *hwfc, VulkanExecCtx *cmd, s_info->pCommandBuffers = &cmd->bufs[cmd->cur_queue_idx]; s_info->commandBufferCount = 1; + hwctx->lock_queue(hwfc->device_ctx, q->qf, q->qidx); ret = vk->QueueSubmit(q->queue, 1, s_info, q->fence); + hwctx->unlock_queue(hwfc->device_ctx, q->qf, q->qidx); if (ret != VK_SUCCESS) { av_log(hwfc, AV_LOG_ERROR, "Queue submission failure: %s\n", vk_ret2str(ret)); @@ -1336,7 +1441,6 @@ static int submit_exec_ctx(AVHWFramesContext *hwfc, VulkanExecCtx *cmd, q->was_synchronous = synchronous; if (synchronous) { - AVVulkanDeviceContext *hwctx = hwfc->device_ctx->hwctx; vk->WaitForFences(hwctx->act_dev, 1, &q->fence, VK_TRUE, UINT64_MAX); vk->ResetFences(hwctx->act_dev, 1, &q->fence); unref_exec_ctx_deps(hwfc, cmd); @@ -1500,11 +1604,9 @@ 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); + opt_d = av_dict_get(opts, "disable_multiplane", NULL, 0); if (opt_d) - p->contiguous_planes = strtol(opt_d->value, NULL, 10); - else - p->contiguous_planes = -1; + p->disable_multiplane = strtol(opt_d->value, NULL, 10); hwctx->enabled_dev_extensions = dev_info.ppEnabledExtensionNames; hwctx->nb_enabled_dev_extensions = dev_info.enabledExtensionCount; @@ -1764,8 +1866,12 @@ static int vulkan_frames_get_constraints(AVHWDeviceContext *ctx, int count = 0; VulkanDevicePriv *p = ctx->internal->priv; - for (enum AVPixelFormat i = 0; i < AV_PIX_FMT_NB; i++) - count += pixfmt_is_supported(ctx, i, p->use_linear_images); + for (enum AVPixelFormat i = 0; i < nb_vk_formats_list; i++) { + count += vkfmt_from_pixfmt2(ctx, vk_formats_list[i].pixfmt, + p->use_linear_images ? VK_IMAGE_TILING_LINEAR : + VK_IMAGE_TILING_OPTIMAL, + NULL, NULL, NULL, NULL, 0) >= 0; + } #if CONFIG_CUDA if (p->dev_is_nvidia) @@ -1778,9 +1884,14 @@ static int vulkan_frames_get_constraints(AVHWDeviceContext *ctx, return AVERROR(ENOMEM); count = 0; - for (enum AVPixelFormat i = 0; i < AV_PIX_FMT_NB; i++) - if (pixfmt_is_supported(ctx, i, p->use_linear_images)) - constraints->valid_sw_formats[count++] = i; + for (enum AVPixelFormat i = 0; i < nb_vk_formats_list; i++) { + if (vkfmt_from_pixfmt2(ctx, vk_formats_list[i].pixfmt, + p->use_linear_images ? VK_IMAGE_TILING_LINEAR : + VK_IMAGE_TILING_OPTIMAL, + NULL, NULL, NULL, NULL, 0) >= 0) { + constraints->valid_sw_formats[count++] = vk_formats_list[i].pixfmt; + } + } #if CONFIG_CUDA if (p->dev_is_nvidia) @@ -1788,8 +1899,8 @@ static int vulkan_frames_get_constraints(AVHWDeviceContext *ctx, #endif constraints->valid_sw_formats[count++] = AV_PIX_FMT_NONE; - constraints->min_width = 0; - constraints->min_height = 0; + constraints->min_width = 1; + constraints->min_height = 1; constraints->max_width = p->props.properties.limits.maxImageDimension2D; constraints->max_height = p->props.properties.limits.maxImageDimension2D; @@ -1863,7 +1974,7 @@ static int alloc_mem(AVHWDeviceContext *ctx, VkMemoryRequirements *req, static void vulkan_free_internal(AVVkFrame *f) { - AVVkFrameInternal *internal = f->internal; + av_unused AVVkFrameInternal *internal = f->internal; #if CONFIG_CUDA if (internal->cuda_fc_ref) { @@ -1904,17 +2015,22 @@ static void vulkan_frame_free(void *opaque, uint8_t *data) AVVulkanDeviceContext *hwctx = hwfc->device_ctx->hwctx; VulkanDevicePriv *p = hwfc->device_ctx->internal->priv; FFVulkanFunctions *vk = &p->vkfn; - int planes = av_pix_fmt_count_planes(hwfc->sw_format); + int nb_images = ff_vk_count_images(f); - /* We could use vkWaitSemaphores, but the validation layer seems to have - * issues tracking command buffer execution state on uninit. */ - vk->DeviceWaitIdle(hwctx->act_dev); + VkSemaphoreWaitInfo sem_wait = { + .sType = VK_STRUCTURE_TYPE_SEMAPHORE_WAIT_INFO, + .pSemaphores = f->sem, + .pValues = f->sem_value, + .semaphoreCount = nb_images, + }; + + vk->WaitSemaphores(hwctx->act_dev, &sem_wait, UINT64_MAX); vulkan_free_internal(f); - for (int i = 0; i < planes; i++) { - vk->DestroyImage(hwctx->act_dev, f->img[i], hwctx->alloc); - vk->FreeMemory(hwctx->act_dev, f->mem[i], hwctx->alloc); + for (int i = 0; i < nb_images; i++) { + 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); } @@ -1924,30 +2040,25 @@ static void vulkan_frame_free(void *opaque, uint8_t *data) static int alloc_bind_mem(AVHWFramesContext *hwfc, AVVkFrame *f, void *alloc_pnext, size_t alloc_pnext_stride) { - int err; + int img_cnt = 0, err; VkResult ret; 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++) { + while (f->img[img_cnt]) { int use_ded_mem; VkImageMemoryRequirementsInfo2 req_desc = { .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_REQUIREMENTS_INFO_2, - .image = f->img[i], + .image = f->img[img_cnt], }; VkMemoryDedicatedAllocateInfo ded_alloc = { .sType = VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO, - .pNext = (void *)(((uint8_t *)alloc_pnext) + i*alloc_pnext_stride), + .pNext = (void *)(((uint8_t *)alloc_pnext) + img_cnt*alloc_pnext_stride), }; VkMemoryDedicatedRequirements ded_req = { .sType = VK_STRUCTURE_TYPE_MEMORY_DEDICATED_REQUIREMENTS, @@ -1963,32 +2074,11 @@ 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; if (use_ded_mem) - ded_alloc.image = f->img[i]; + ded_alloc.image = f->img[img_cnt]; /* Allocate memory */ if ((err = alloc_mem(ctx, &req.memoryRequirements, @@ -1996,42 +2086,19 @@ static int alloc_bind_mem(AVHWFramesContext *hwfc, AVVkFrame *f, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT : VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, use_ded_mem ? &ded_alloc : (void *)ded_alloc.pNext, - &f->flags, &f->mem[i]))) + &f->flags, &f->mem[img_cnt]))) return err; - f->size[i] = req.memoryRequirements.size; - bind_info[i].sType = VK_STRUCTURE_TYPE_BIND_IMAGE_MEMORY_INFO; - bind_info[i].image = f->img[i]; - bind_info[i].memory = f->mem[i]; - } - - if (hwfctx->flags & AV_VK_FRAME_FLAG_CONTIGUOUS_MEMORY) { - cont_memory_requirements.size = cont_mem_size; + f->size[img_cnt] = req.memoryRequirements.size; + bind_info[img_cnt].sType = VK_STRUCTURE_TYPE_BIND_IMAGE_MEMORY_INFO; + bind_info[img_cnt].image = f->img[img_cnt]; + bind_info[img_cnt].memory = f->mem[img_cnt]; - /* 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, 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]; - } + img_cnt++; } /* Bind the allocated memory to the images */ - ret = vk->BindImageMemory2(hwctx->act_dev, planes, bind_info); + ret = vk->BindImageMemory2(hwctx->act_dev, img_cnt, bind_info); if (ret != VK_SUCCESS) { av_log(ctx, AV_LOG_ERROR, "Failed to bind memory: %s\n", vk_ret2str(ret)); @@ -2057,11 +2124,10 @@ static int prepare_frame(AVHWFramesContext *hwfc, VulkanExecCtx *ectx, VkImageLayout new_layout; VkAccessFlags2 new_access; AVVulkanFramesContext *vkfc = hwfc->hwctx; - const int planes = av_pix_fmt_count_planes(hwfc->sw_format); VulkanDevicePriv *p = hwfc->device_ctx->internal->priv; FFVulkanFunctions *vk = &p->vkfn; - AVFrame tmp = { .data[0] = (uint8_t *)frame }; uint64_t sem_sig_val[AV_NUM_DATA_POINTERS]; + int nb_images = ff_vk_count_images(frame); VkImageMemoryBarrier2 img_bar[AV_NUM_DATA_POINTERS] = { 0 }; VkDependencyInfo dep_info; @@ -2069,14 +2135,14 @@ static int prepare_frame(AVHWFramesContext *hwfc, VulkanExecCtx *ectx, VkTimelineSemaphoreSubmitInfo s_timeline_sem_info = { .sType = VK_STRUCTURE_TYPE_TIMELINE_SEMAPHORE_SUBMIT_INFO, .pSignalSemaphoreValues = sem_sig_val, - .signalSemaphoreValueCount = planes, + .signalSemaphoreValueCount = nb_images, }; VkSubmitInfo s_info = { .sType = VK_STRUCTURE_TYPE_SUBMIT_INFO, .pNext = &s_timeline_sem_info, .pSignalSemaphores = frame->sem, - .signalSemaphoreCount = planes, + .signalSemaphoreCount = nb_images, }; VkPipelineStageFlagBits wait_st[AV_NUM_DATA_POINTERS]; @@ -2086,7 +2152,7 @@ static int prepare_frame(AVHWFramesContext *hwfc, VulkanExecCtx *ectx, vkfc->lock_frame(hwfc, frame); - for (int i = 0; i < planes; i++) { + for (int i = 0; i < nb_images; i++) { wait_st[i] = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT; sem_sig_val[i] = frame->sem_value[i] + 1; } @@ -2104,10 +2170,10 @@ static int prepare_frame(AVHWFramesContext *hwfc, VulkanExecCtx *ectx, 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_timeline_sem_info.waitSemaphoreValueCount = nb_images; s_info.pWaitSemaphores = frame->sem; s_info.pWaitDstStageMask = wait_st; - s_info.waitSemaphoreCount = planes; + s_info.waitSemaphoreCount = nb_images; break; case PREP_MODE_EXTERNAL_EXPORT: new_layout = VK_IMAGE_LAYOUT_GENERAL; @@ -2115,10 +2181,10 @@ static int prepare_frame(AVHWFramesContext *hwfc, VulkanExecCtx *ectx, 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; + s_timeline_sem_info.waitSemaphoreValueCount = nb_images; s_info.pWaitSemaphores = frame->sem; s_info.pWaitDstStageMask = wait_st; - s_info.waitSemaphoreCount = planes; + s_info.waitSemaphoreCount = nb_images; break; case PREP_MODE_DECODING_DST: new_layout = VK_IMAGE_LAYOUT_VIDEO_DECODE_DST_KHR; @@ -2137,7 +2203,7 @@ static int prepare_frame(AVHWFramesContext *hwfc, VulkanExecCtx *ectx, /* Change the image layout to something more optimal for writes. * This also signals the newly created semaphore, making it usable * for synchronization */ - for (int i = 0; i < planes; i++) { + for (int i = 0; i < nb_images; i++) { img_bar[i] = (VkImageMemoryBarrier2) { .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER_2, .pNext = NULL, @@ -2152,8 +2218,8 @@ static int prepare_frame(AVHWFramesContext *hwfc, VulkanExecCtx *ectx, .image = frame->img[i], .subresourceRange = (VkImageSubresourceRange) { .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT, + .layerCount = VK_REMAINING_ARRAY_LAYERS, .levelCount = 1, - .layerCount = 1, }, }; @@ -2164,7 +2230,7 @@ static int prepare_frame(AVHWFramesContext *hwfc, VulkanExecCtx *ectx, vk->CmdPipelineBarrier2(get_buf_exec_ctx(hwfc, ectx), &(VkDependencyInfo) { .sType = VK_STRUCTURE_TYPE_DEPENDENCY_INFO, .pImageMemoryBarriers = img_bar, - .imageMemoryBarrierCount = planes, + .imageMemoryBarrierCount = nb_images, }); err = submit_exec_ctx(hwfc, ectx, &s_info, frame, 0); @@ -2173,7 +2239,7 @@ static int prepare_frame(AVHWFramesContext *hwfc, VulkanExecCtx *ectx, return err; } -static inline void get_plane_wh(int *w, int *h, enum AVPixelFormat format, +static inline void get_plane_wh(uint32_t *w, uint32_t *h, enum AVPixelFormat format, int frame_w, int frame_h, int plane) { const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(format); @@ -2192,17 +2258,17 @@ static inline void get_plane_wh(int *w, int *h, enum AVPixelFormat format, static int create_frame(AVHWFramesContext *hwfc, AVVkFrame **frame, VkImageTiling tiling, VkImageUsageFlagBits usage, + VkImageCreateFlags flags, int nb_layers, void *create_pnext) { int err; VkResult ret; + AVVulkanFramesContext *hwfc_vk = hwfc->hwctx; AVHWDeviceContext *ctx = hwfc->device_ctx; VulkanDevicePriv *p = ctx->internal->priv; FFVulkanFunctions *vk = &p->vkfn; AVVulkanDeviceContext *hwctx = ctx->hwctx; - enum AVPixelFormat format = hwfc->sw_format; - const VkFormat *img_fmts = av_vkfmt_from_pixfmt(format); - const int planes = av_pix_fmt_count_planes(format); + AVVulkanFramesContext *frames = hwfc->hwctx; VkExportSemaphoreCreateInfo ext_sem_info = { .sType = VK_STRUCTURE_TYPE_EXPORT_SEMAPHORE_CREATE_INFO, @@ -2237,17 +2303,19 @@ static int create_frame(AVHWFramesContext *hwfc, AVVkFrame **frame, return AVERROR(ENOMEM); } + // TODO: check witdh and height for alignment in case of multiplanar (must be mod-2 if subsampled) + /* Create the images */ - for (int i = 0; i < planes; i++) { + for (int i = 0; (hwfc_vk->format[i] != VK_FORMAT_UNDEFINED); i++) { VkImageCreateInfo create_info = { .sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, .pNext = create_pnext, .imageType = VK_IMAGE_TYPE_2D, - .format = img_fmts[i], + .format = hwfc_vk->format[i], .extent.depth = 1, .mipLevels = 1, - .arrayLayers = 1, - .flags = VK_IMAGE_CREATE_ALIAS_BIT, + .arrayLayers = nb_layers, + .flags = flags, .tiling = tiling, .initialLayout = VK_IMAGE_LAYOUT_UNDEFINED, .usage = usage, @@ -2259,7 +2327,7 @@ static int create_frame(AVHWFramesContext *hwfc, AVVkFrame **frame, }; get_plane_wh(&create_info.extent.width, &create_info.extent.height, - format, hwfc->width, hwfc->height, i); + hwfc->sw_format, hwfc->width, hwfc->height, i); ret = vk->CreateImage(hwctx->act_dev, &create_info, hwctx->alloc, &f->img[i]); @@ -2368,8 +2436,8 @@ static AVBufferRef *vulkan_pool_alloc(void *opaque, size_t size) AVVulkanFramesContext *hwctx = hwfc->hwctx; VulkanDevicePriv *p = hwfc->device_ctx->internal->priv; VulkanFramesPriv *fp = hwfc->internal->priv; - VkExportMemoryAllocateInfo eminfo[AV_NUM_DATA_POINTERS]; VkExternalMemoryHandleTypeFlags e = 0x0; + VkExportMemoryAllocateInfo eminfo[AV_NUM_DATA_POINTERS]; VkExternalMemoryImageCreateInfo eiinfo = { .sType = VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_IMAGE_CREATE_INFO, @@ -2385,10 +2453,6 @@ static AVBufferRef *vulkan_pool_alloc(void *opaque, size_t size) 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 & (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++) { @@ -2397,8 +2461,8 @@ static AVBufferRef *vulkan_pool_alloc(void *opaque, size_t size) eminfo[i].handleTypes = e; } - err = create_frame(hwfc, &f, hwctx->tiling, hwctx->usage, - eiinfo.handleTypes ? &eiinfo : NULL); + err = create_frame(hwfc, &f, hwctx->tiling, hwctx->usage, hwctx->img_flags, + hwctx->nb_layers, eiinfo.handleTypes ? &eiinfo : NULL); if (err) return NULL; @@ -2461,104 +2525,89 @@ 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 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; - - 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); + VkImageUsageFlagBits supported_usage; + const struct FFVkFormatEntry *fmt; + int disable_multiplane = p->disable_multiplane || + (hwctx->flags & AV_VK_FRAME_FLAG_DISABLE_MULTIPLANE); - /* Backup the allocated struct to be freed later */ - fp->modifier_info = modifier_info; + /* Defaults */ + if (!hwctx->nb_layers) + hwctx->nb_layers = 1; - /* 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; + /* VK_IMAGE_TILING_OPTIMAL == 0, can't check for it really */ + if (p->use_linear_images && + (hwctx->tiling != VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT)) + hwctx->tiling = VK_IMAGE_TILING_LINEAR; - /* 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; + fmt = vk_find_format_entry(hwfc->sw_format); + if (!fmt) { + av_log(hwfc, AV_LOG_ERROR, "Unsupported pixel format: %s!\n", + av_get_pix_fmt_name(hwfc->sw_format)); + return AVERROR(EINVAL); + } - modifiers[modifier_count++] = mod_props[i].drmFormatModifier; + if (hwctx->format[0] != VK_FORMAT_UNDEFINED) { + if (hwctx->format[0] != fmt->vkf) { + for (int i = 0; i < fmt->nb_images_fallback; i++) { + if (hwctx->format[i] != fmt->fallback[i]) { + av_log(hwfc, AV_LOG_ERROR, "Incompatible Vulkan format given " + "for the current sw_format %s!\n", + av_get_pix_fmt_name(hwfc->sw_format)); + return AVERROR(EINVAL); + } + } } - if (!modifier_count) { - av_log(hwfc, AV_LOG_ERROR, "None of the given modifiers supports" - " the usage flags!\n"); - av_freep(&mod_props); + /* Check if the sw_format itself is supported */ + err = vkfmt_from_pixfmt2(hwfc->device_ctx, hwfc->sw_format, + hwctx->tiling, NULL, + NULL, NULL, &supported_usage, 0); + if (err < 0) { + av_log(hwfc, AV_LOG_ERROR, "Unsupported sw format: %s!\n", + av_get_pix_fmt_name(hwfc->sw_format)); return AVERROR(EINVAL); } + } else { + err = vkfmt_from_pixfmt2(hwfc->device_ctx, hwfc->sw_format, + hwctx->tiling, hwctx->format, NULL, + NULL, &supported_usage, + disable_multiplane); + if (err < 0) + return err; + } - modifier_info->drmFormatModifierCount = modifier_count; - av_freep(&mod_props); + /* Image usage flags */ + if (!hwctx->usage) { + hwctx->usage = supported_usage & (VK_BUFFER_USAGE_TRANSFER_DST_BIT | + VK_BUFFER_USAGE_TRANSFER_SRC_BIT | + VK_IMAGE_USAGE_STORAGE_BIT | + VK_IMAGE_USAGE_SAMPLED_BIT | + VK_IMAGE_USAGE_VIDEO_ENCODE_SRC_BIT_KHR); + } + + /* Image creation flags. + * Only fill them in automatically if the image is not going to be used as + * a DPB-only image, and we have SAMPLED/STORAGE bits set. */ + if (!hwctx->img_flags) { + int is_lone_dpb = (hwctx->usage & VK_IMAGE_USAGE_VIDEO_DECODE_DPB_BIT_KHR) && + !(hwctx->usage & VK_IMAGE_USAGE_VIDEO_DECODE_DST_BIT_KHR); + int sampleable = hwctx->usage & (VK_IMAGE_USAGE_SAMPLED_BIT | + VK_IMAGE_USAGE_STORAGE_BIT); + if (sampleable && !is_lone_dpb) { + hwctx->img_flags = VK_IMAGE_CREATE_ALIAS_BIT; + if ((fmt->vk_planes > 1) && (hwctx->format[0] == fmt->vkf)) + hwctx->img_flags |= VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT | + VK_IMAGE_CREATE_EXTENDED_USAGE_BIT; + } } + if (!hwctx->lock_frame) + hwctx->lock_frame = lock_frame; + + if (!hwctx->unlock_frame) + hwctx->unlock_frame = unlock_frame; + err = create_exec_ctx(hwfc, &fp->conv_ctx, dev_hwctx->queue_family_comp_index, dev_hwctx->nb_comp_queues); @@ -2577,8 +2626,8 @@ static int vulkan_frames_init(AVHWFramesContext *hwfc) return err; /* Test to see if allocation will fail */ - err = create_frame(hwfc, &f, hwctx->tiling, hwctx->usage, - hwctx->create_pnext); + err = create_frame(hwfc, &f, hwctx->tiling, hwctx->usage, hwctx->img_flags, + hwctx->nb_layers, hwctx->create_pnext); if (err) return err; @@ -2594,11 +2643,6 @@ static int vulkan_frames_init(AVHWFramesContext *hwfc) return AVERROR(ENOMEM); } - if (!hwctx->lock_frame) - hwctx->lock_frame = lock_frame; - if (!hwctx->unlock_frame) - hwctx->unlock_frame = unlock_frame; - return 0; } @@ -2674,7 +2718,7 @@ static int vulkan_map_frame_to_mem(AVHWFramesContext *hwfc, AVFrame *dst, const AVFrame *src, int flags) { VkResult ret; - int err, mapped_mem_count = 0, mem_planes = 0; + int err, nb_mem = 0, mapped_mem_count = 0, mem_planes = 0; AVVkFrame *f = (AVVkFrame *)src->data[0]; AVVulkanDeviceContext *hwctx = hwfc->device_ctx->hwctx; AVVulkanFramesContext *hwfctx = hwfc->hwctx; @@ -2694,7 +2738,7 @@ static int vulkan_map_frame_to_mem(AVHWFramesContext *hwfc, AVFrame *dst, } if (!(f->flags & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) || - !(f->tiling == VK_IMAGE_TILING_LINEAR)) { + !(hwfctx->tiling == VK_IMAGE_TILING_LINEAR)) { av_log(hwfc, AV_LOG_ERROR, "Unable to map frame, not host visible " "and linear!\n"); err = AVERROR(EINVAL); @@ -2704,35 +2748,35 @@ static int vulkan_map_frame_to_mem(AVHWFramesContext *hwfc, AVFrame *dst, dst->width = src->width; dst->height = src->height; - mem_planes = hwfctx->flags & AV_VK_FRAME_FLAG_CONTIGUOUS_MEMORY ? 1 : planes; - for (int i = 0; i < mem_planes; i++) { + for (int i = 0; i < AV_NUM_DATA_POINTERS; i++) + nb_mem += !!f->mem[i]; + + for (int i = 0; i < nb_mem; i++) { ret = vk->MapMemory(hwctx->act_dev, f->mem[i], 0, VK_WHOLE_SIZE, 0, (void **)&dst->data[i]); if (ret != VK_SUCCESS) { - av_log(hwfc, AV_LOG_ERROR, "Failed to map image memory: %s\n", - vk_ret2str(ret)); + av_log(hwfc, AV_LOG_ERROR, "Failed to map %ith frame memory: %s\n", + i, vk_ret2str(ret)); err = AVERROR_EXTERNAL; goto fail; } 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]; - } + for (int i = 0; i < planes; i++) + dst->data[i] = dst->data[i] + 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)) { VkMappedMemoryRange map_mem_ranges[AV_NUM_DATA_POINTERS] = { { 0 } }; - for (int i = 0; i < planes; i++) { + for (int i = 0; i < nb_mem; i++) { map_mem_ranges[i].sType = VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE; map_mem_ranges[i].size = VK_WHOLE_SIZE; map_mem_ranges[i].memory = f->mem[i]; } - ret = vk->InvalidateMappedMemoryRanges(hwctx->act_dev, planes, + ret = vk->InvalidateMappedMemoryRanges(hwctx->act_dev, nb_mem, map_mem_ranges); if (ret != VK_SUCCESS) { av_log(hwfc, AV_LOG_ERROR, "Failed to invalidate memory: %s\n", @@ -2774,25 +2818,25 @@ static void vulkan_unmap_from_drm(AVHWFramesContext *hwfc, HWMapDescriptor *hwma { 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; FFVulkanFunctions *vk = &p->vkfn; + const int nb_images = ff_vk_count_images(f); VkSemaphoreWaitInfo wait_info = { .sType = VK_STRUCTURE_TYPE_SEMAPHORE_WAIT_INFO, .flags = 0x0, .pSemaphores = f->sem, .pValues = f->sem_value, - .semaphoreCount = planes, + .semaphoreCount = nb_images, }; 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, f->img[i], hwctx->alloc); - vk->FreeMemory(hwctx->act_dev, f->mem[i], hwctx->alloc); + for (int i = 0; i < nb_images; i++) { + 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); } @@ -2843,6 +2887,7 @@ static int vulkan_map_from_drm_frame_desc(AVHWFramesContext *hwfc, AVVkFrame **f AVVulkanDeviceContext *hwctx = ctx->hwctx; VulkanDevicePriv *p = ctx->internal->priv; FFVulkanFunctions *vk = &p->vkfn; + AVVulkanFramesContext *hwfctx = hwfc->hwctx; VulkanFramesPriv *fp = hwfc->internal->priv; const AVDRMFrameDescriptor *desc = (AVDRMFrameDescriptor *)src->data[0]; VkBindImageMemoryInfo bind_info[AV_DRM_MAX_PLANES]; @@ -2899,8 +2944,8 @@ static int vulkan_map_from_drm_frame_desc(AVHWFramesContext *hwfc, AVVkFrame **f .extent.depth = 1, .mipLevels = 1, .arrayLayers = 1, - .flags = 0x0, /* ALIAS flag is implicit for imported images */ - .tiling = f->tiling, + .flags = 0x0, + .tiling = VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT, .initialLayout = VK_IMAGE_LAYOUT_UNDEFINED, /* specs say so */ .usage = VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT, @@ -2993,7 +3038,7 @@ static int vulkan_map_from_drm_frame_desc(AVHWFramesContext *hwfc, AVVkFrame **f f->sem_value[i] = 0; } - for (int i = 0; i < desc->nb_objects; i++) { + for (int i = 0; i < desc->nb_layers; i++) { /* Memory requirements */ VkImageMemoryRequirementsInfo2 req_desc = { .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_REQUIREMENTS_INFO_2, @@ -3011,9 +3056,13 @@ static int vulkan_map_from_drm_frame_desc(AVHWFramesContext *hwfc, AVVkFrame **f VkMemoryFdPropertiesKHR fdmp = { .sType = VK_STRUCTURE_TYPE_MEMORY_FD_PROPERTIES_KHR, }; + /* This assumes that a layer will never be constructed from multiple + * objects. If that was to happen in the real world, this code would + * need to import each plane separately. + */ VkImportMemoryFdInfoKHR idesc = { .sType = VK_STRUCTURE_TYPE_IMPORT_MEMORY_FD_INFO_KHR, - .fd = dup(desc->objects[i].fd), + .fd = dup(desc->objects[desc->layers[i].planes[0].object_index].fd), .handleType = VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT, }; VkMemoryDedicatedAllocateInfo ded_alloc = { @@ -3067,7 +3116,7 @@ static int vulkan_map_from_drm_frame_desc(AVHWFramesContext *hwfc, AVVkFrame **f bind_info[bind_counts].sType = VK_STRUCTURE_TYPE_BIND_IMAGE_MEMORY_INFO; 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].memory = f->mem[i]; /* Offset is already signalled via pPlaneLayouts above */ bind_info[bind_counts].memoryOffset = 0; @@ -3444,13 +3493,13 @@ static int vulkan_map_to(AVHWFramesContext *hwfc, AVFrame *dst, #if CONFIG_LIBDRM #if CONFIG_VAAPI case AV_PIX_FMT_VAAPI: - if (p->extensions & (FF_VK_EXT_EXTERNAL_DMABUF_MEMORY | FF_VK_EXT_DRM_MODIFIER_FLAGS)) + if (p->extensions & 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 & (FF_VK_EXT_EXTERNAL_DMABUF_MEMORY | FF_VK_EXT_DRM_MODIFIER_FLAGS)) + if (p->extensions & FF_VK_EXT_DRM_MODIFIER_FLAGS) return vulkan_map_from_drm(hwfc, dst, src, flags); else return AVERROR(ENOSYS); @@ -3630,13 +3679,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 & (FF_VK_EXT_EXTERNAL_DMABUF_MEMORY | FF_VK_EXT_DRM_MODIFIER_FLAGS)) + if (p->extensions & 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 & (FF_VK_EXT_EXTERNAL_DMABUF_MEMORY | FF_VK_EXT_DRM_MODIFIER_FLAGS)) + if (p->extensions & FF_VK_EXT_DRM_MODIFIER_FLAGS) return vulkan_map_to_vaapi(hwfc, dst, src, flags); else return AVERROR(ENOSYS); @@ -3890,7 +3939,9 @@ static int transfer_image_buf(AVHWFramesContext *hwfc, AVFrame *f, int bar_num = 0; VkPipelineStageFlagBits sem_wait_dst[AV_NUM_DATA_POINTERS]; - const int planes = av_pix_fmt_count_planes(pix_fmt); + const int nb_images = ff_vk_count_images(frame); + int pixfmt_planes = av_pix_fmt_count_planes(pix_fmt); + const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(pix_fmt); VkImageMemoryBarrier img_bar[AV_NUM_DATA_POINTERS] = { 0 }; @@ -3903,8 +3954,8 @@ static int transfer_image_buf(AVHWFramesContext *hwfc, AVFrame *f, .sType = VK_STRUCTURE_TYPE_TIMELINE_SEMAPHORE_SUBMIT_INFO, .pWaitSemaphoreValues = frame->sem_value, .pSignalSemaphoreValues = sem_signal_values, - .waitSemaphoreValueCount = planes, - .signalSemaphoreValueCount = planes, + .waitSemaphoreValueCount = nb_images, + .signalSemaphoreValueCount = nb_images, }; VkSubmitInfo s_info = { @@ -3913,8 +3964,8 @@ static int transfer_image_buf(AVHWFramesContext *hwfc, AVFrame *f, .pSignalSemaphores = frame->sem, .pWaitSemaphores = frame->sem, .pWaitDstStageMask = sem_wait_dst, - .signalSemaphoreCount = planes, - .waitSemaphoreCount = planes, + .signalSemaphoreCount = nb_images, + .waitSemaphoreCount = nb_images, }; vkfc->lock_frame(hwfc, frame); @@ -3922,11 +3973,11 @@ static int transfer_image_buf(AVHWFramesContext *hwfc, AVFrame *f, if ((err = wait_start_exec_ctx(hwfc, ectx))) goto end; - for (int i = 0; i < planes; i++) + for (int i = 0; i < nb_images; i++) sem_signal_values[i] = frame->sem_value[i] + 1; /* Change the image layout to something more optimal for transfers */ - for (int i = 0; i < planes; i++) { + for (int i = 0; i < nb_images; i++) { VkImageLayout new_layout = to_buf ? VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL : VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL; VkAccessFlags new_access = to_buf ? VK_ACCESS_TRANSFER_READ_BIT : @@ -3962,13 +4013,20 @@ static int transfer_image_buf(AVHWFramesContext *hwfc, AVFrame *f, 0, NULL, 0, NULL, bar_num, img_bar); /* Schedule a copy for each plane */ - for (int i = 0; i < planes; i++) { + for (int i = 0; i < pixfmt_planes; i++) { + int idx = FFMIN(i, nb_images - 1); + VkImageAspectFlags plane_aspect[] = { VK_IMAGE_ASPECT_COLOR_BIT, + VK_IMAGE_ASPECT_PLANE_0_BIT, + VK_IMAGE_ASPECT_PLANE_1_BIT, + VK_IMAGE_ASPECT_PLANE_2_BIT, }; + ImageBuffer *vkbuf = (ImageBuffer *)bufs[i]->data; VkBufferImageCopy buf_reg = { .bufferOffset = buf_offsets[i], .bufferRowLength = buf_stride[i] / desc->comp[i].step, .imageSubresource.layerCount = 1, - .imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT, + .imageSubresource.aspectMask = plane_aspect[(pixfmt_planes != nb_images) + + i*(pixfmt_planes != nb_images)], .imageOffset = { 0, 0, 0, }, }; @@ -3979,11 +4037,11 @@ static int transfer_image_buf(AVHWFramesContext *hwfc, AVFrame *f, buf_reg.imageExtent = (VkExtent3D){ p_w, p_h, 1, }; if (to_buf) - vk->CmdCopyImageToBuffer(cmd_buf, frame->img[i], frame->layout[i], + vk->CmdCopyImageToBuffer(cmd_buf, frame->img[idx], frame->layout[idx], vkbuf->buf, 1, &buf_reg); else - vk->CmdCopyBufferToImage(cmd_buf, vkbuf->buf, frame->img[i], - frame->layout[i], 1, &buf_reg); + vk->CmdCopyBufferToImage(cmd_buf, vkbuf->buf, frame->img[idx], + frame->layout[idx], 1, &buf_reg); } /* When uploading, do this asynchronously if the source is refcounted by @@ -4000,7 +4058,7 @@ static int transfer_image_buf(AVHWFramesContext *hwfc, AVFrame *f, if ((err = add_buf_dep_exec_ctx(hwfc, ectx, &f->buf[ref], 1))) goto end; } - if (ref && (err = add_buf_dep_exec_ctx(hwfc, ectx, bufs, planes))) + if (ref && (err = add_buf_dep_exec_ctx(hwfc, ectx, bufs, pixfmt_planes))) goto end; err = submit_exec_ctx(hwfc, ectx, &s_info, frame, !ref); } else { @@ -4020,6 +4078,7 @@ static int vulkan_transfer_data(AVHWFramesContext *hwfc, const AVFrame *vkf, AVVkFrame *f = (AVVkFrame *)vkf->data[0]; AVHWDeviceContext *dev_ctx = hwfc->device_ctx; AVVulkanDeviceContext *hwctx = dev_ctx->hwctx; + AVVulkanFramesContext *fc = hwfc->hwctx; VulkanDevicePriv *p = hwfc->device_ctx->internal->priv; FFVulkanFunctions *vk = &p->vkfn; @@ -4042,7 +4101,7 @@ static int vulkan_transfer_data(AVHWFramesContext *hwfc, const AVFrame *vkf, return AVERROR(EINVAL); /* For linear, host visiable images */ - if (f->tiling == VK_IMAGE_TILING_LINEAR && + if (fc->tiling == VK_IMAGE_TILING_LINEAR && f->flags & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) { AVFrame *map = av_frame_alloc(); if (!map) diff --git a/libavutil/hwcontext_vulkan.h b/libavutil/hwcontext_vulkan.h index 60254b24063..895794c8679 100644 --- a/libavutil/hwcontext_vulkan.h +++ b/libavutil/hwcontext_vulkan.h @@ -164,6 +164,10 @@ typedef enum AVVkFrameFlags { /* DEPRECATED: does nothing. Replaced by multiplane images. */ AV_VK_FRAME_FLAG_CONTIGUOUS_MEMORY = (1ULL << 1), #endif + + /* Disables multiplane images. + * This is required to export/import images from CUDA. */ + AV_VK_FRAME_FLAG_DISABLE_MULTIPLANE = (1ULL << 2), } AVVkFrameFlags; /** @@ -171,26 +175,32 @@ typedef enum AVVkFrameFlags { */ typedef struct AVVulkanFramesContext { /** - * 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. + * Controls the tiling of allocated frames. + * If left as VK_IMAGE_TILING_OPTIMAL (0), will use optimal tiling. + * Can be set to VK_IMAGE_TILING_LINEAR to force linear images, + * or VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT to force DMABUF-backed + * images. + * @note Imported frames from other APIs ignore this. */ VkImageTiling tiling; /** - * Defines extra usage of output frames. If left as 0, the following bits - * are set: TRANSFER_SRC, TRANSFER_DST. SAMPLED and STORAGE. + * Defines extra usage of output frames. If non-zero, all flags MUST be + * supported by the VkFormat. Otherwise, will use supported flags amongst: + * - VK_IMAGE_USAGE_SAMPLED_BIT + * - VK_IMAGE_USAGE_STORAGE_BIT + * - VK_IMAGE_USAGE_TRANSFER_SRC_BIT + * - VK_IMAGE_USAGE_TRANSFER_DST_BIT */ VkImageUsageFlagBits usage; /** * 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. + * If DRM tiling is used, a VkImageDrmFormatModifierListCreateInfoEXT structure + * can be added to specify the exact modifier to use. + * * Additional structures may be added at av_hwframe_ctx_init() time, - * which will be freed automatically on uninit(), so users need only free + * which will be freed automatically on uninit(), so users must only free * any structures they've allocated themselves. */ void *create_pnext; @@ -211,6 +221,25 @@ typedef struct AVVulkanFramesContext { */ AVVkFrameFlags flags; + /** + * Flags to set during image creation. If unset, defaults to + * VK_IMAGE_CREATE_ALIAS_BIT. + */ + VkImageCreateFlags img_flags; + + /** + * Vulkan format for each image. MUST be compatible with the pixel format. + * If unset, will be automatically set. + * There are at most two compatible formats for a frame - a multiplane + * format, and a single-plane multi-image format. + */ + VkFormat format[AV_NUM_DATA_POINTERS]; + + /** + * Number of layers each image will have. + */ + int nb_layers; + /** * Locks a frame, preventing other threads from changing frame properties. * Users SHOULD only ever lock just before command submission in order @@ -228,14 +257,7 @@ typedef struct AVVulkanFramesContext { } AVVulkanFramesContext; /* - * Frame structure, the VkFormat of the image will always match - * the pool's sw_format. - * 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 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. + * Frame structure. * * @note the size of this structure is not part of the ABI, to allocate * you must use @av_vk_frame_alloc(). @@ -243,18 +265,20 @@ typedef struct AVVulkanFramesContext { struct AVVkFrame { /** * Vulkan images to which the memory is bound to. + * May be one for multiplane formats, or multiple. */ VkImage img[AV_NUM_DATA_POINTERS]; /** - * The same tiling must be used for all images in the frame. + * Tiling for the frame. */ VkImageTiling tiling; /** - * 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. + * Memory backing the images. Either one, or as many as there are planes + * in the sw_format. + * In case of having multiple VkImages, but one memory, the offset field + * will indicate the bound offset for each image. */ VkDeviceMemory mem[AV_NUM_DATA_POINTERS]; size_t size[AV_NUM_DATA_POINTERS]; @@ -265,13 +289,13 @@ struct AVVkFrame { VkMemoryPropertyFlagBits flags; /** - * Updated after every barrier + * Updated after every barrier. One per VkImage. */ VkAccessFlagBits access[AV_NUM_DATA_POINTERS]; VkImageLayout layout[AV_NUM_DATA_POINTERS]; /** - * Synchronization timeline semaphores, one for each sw_format plane. + * Synchronization timeline semaphores, one for each VkImage. * 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. @@ -280,6 +304,7 @@ struct AVVkFrame { /** * Up to date semaphore value at which each image becomes accessible. + * One per VkImage. * Clients must wait on this value when submitting a command queue, * and increment it when signalling. */ @@ -291,16 +316,18 @@ struct AVVkFrame { struct AVVkFrameInternal *internal; /** - * Describes the binding offset of each plane to the VkDeviceMemory. + * Describes the binding offset of each image to the VkDeviceMemory. + * One per VkImage. */ ptrdiff_t offset[AV_NUM_DATA_POINTERS]; /** * Queue family of the images. Must be VK_QUEUE_FAMILY_IGNORED if * the image was allocated with the CONCURRENT concurrency option. + * One per VkImage. */ uint32_t queue_family[AV_NUM_DATA_POINTERS]; -} AVVkFrame; +}; /** * Allocates a single AVVkFrame and initializes everything as 0. @@ -309,7 +336,8 @@ struct AVVkFrame { AVVkFrame *av_vk_frame_alloc(void); /** - * Returns the format of each image up to the number of planes for a given sw_format. + * Returns the optimal per-plane Vulkan format for a given sw_format, + * one for each plane. * Returns NULL on unsupported formats. */ const VkFormat *av_vkfmt_from_pixfmt(enum AVPixelFormat p); From 32fc36ee6168e0e8fb36f69c97d5198603ae8ba5 Mon Sep 17 00:00:00 2001 From: Lynne Date: Sat, 18 Feb 2023 14:55:14 +0100 Subject: [PATCH 1272/2172] hwcontext_vulkan: remove linear+host_visible "fast" path The idea was that it's faster to map linear images and copy them via regular memcpy. This is a very niche use, plus very inconsistently useful, as it would only really be faster on a few Intel GPUs. Even then, using the non-cached memcpy would've been better. Instead, scrap this code. Drivers are better at figuring out what copy to use, and if we're host-mapping, it should actually be just as fast, if not faster. --- libavutil/hwcontext_vulkan.c | 158 +---------------------------------- 1 file changed, 2 insertions(+), 156 deletions(-) diff --git a/libavutil/hwcontext_vulkan.c b/libavutil/hwcontext_vulkan.c index 622dd811de1..a0139871c9f 100644 --- a/libavutil/hwcontext_vulkan.c +++ b/libavutil/hwcontext_vulkan.c @@ -2675,144 +2675,6 @@ static int vulkan_transfer_get_formats(AVHWFramesContext *hwfc, return 0; } -typedef struct VulkanMapping { - AVVkFrame *frame; - int flags; -} VulkanMapping; - -static void vulkan_unmap_frame(AVHWFramesContext *hwfc, HWMapDescriptor *hwmap) -{ - VulkanMapping *map = 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; - FFVulkanFunctions *vk = &p->vkfn; - - /* Check if buffer needs flushing */ - if ((map->flags & AV_HWFRAME_MAP_WRITE) && - !(map->frame->flags & VK_MEMORY_PROPERTY_HOST_COHERENT_BIT)) { - VkResult ret; - VkMappedMemoryRange flush_ranges[AV_NUM_DATA_POINTERS] = { { 0 } }; - - for (int i = 0; i < planes; i++) { - flush_ranges[i].sType = VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE; - flush_ranges[i].memory = map->frame->mem[i]; - flush_ranges[i].size = VK_WHOLE_SIZE; - } - - ret = vk->FlushMappedMemoryRanges(hwctx->act_dev, planes, - flush_ranges); - if (ret != VK_SUCCESS) { - av_log(hwfc, AV_LOG_ERROR, "Failed to flush memory: %s\n", - vk_ret2str(ret)); - } - } - - for (int i = 0; i < planes; i++) - vk->UnmapMemory(hwctx->act_dev, map->frame->mem[i]); - - av_free(map); -} - -static int vulkan_map_frame_to_mem(AVHWFramesContext *hwfc, AVFrame *dst, - const AVFrame *src, int flags) -{ - VkResult ret; - int err, nb_mem = 0, 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; - - VulkanMapping *map = av_mallocz(sizeof(VulkanMapping)); - if (!map) - return AVERROR(EINVAL); - - if (src->format != AV_PIX_FMT_VULKAN) { - av_log(hwfc, AV_LOG_ERROR, "Cannot map from pixel format %s!\n", - av_get_pix_fmt_name(src->format)); - err = AVERROR(EINVAL); - goto fail; - } - - if (!(f->flags & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) || - !(hwfctx->tiling == VK_IMAGE_TILING_LINEAR)) { - av_log(hwfc, AV_LOG_ERROR, "Unable to map frame, not host visible " - "and linear!\n"); - err = AVERROR(EINVAL); - goto fail; - } - - dst->width = src->width; - dst->height = src->height; - - for (int i = 0; i < AV_NUM_DATA_POINTERS; i++) - nb_mem += !!f->mem[i]; - - for (int i = 0; i < nb_mem; i++) { - ret = vk->MapMemory(hwctx->act_dev, f->mem[i], 0, - VK_WHOLE_SIZE, 0, (void **)&dst->data[i]); - if (ret != VK_SUCCESS) { - av_log(hwfc, AV_LOG_ERROR, "Failed to map %ith frame memory: %s\n", - i, vk_ret2str(ret)); - err = AVERROR_EXTERNAL; - goto fail; - } - mapped_mem_count++; - } - - for (int i = 0; i < planes; i++) - dst->data[i] = dst->data[i] + 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)) { - VkMappedMemoryRange map_mem_ranges[AV_NUM_DATA_POINTERS] = { { 0 } }; - for (int i = 0; i < nb_mem; i++) { - map_mem_ranges[i].sType = VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE; - map_mem_ranges[i].size = VK_WHOLE_SIZE; - map_mem_ranges[i].memory = f->mem[i]; - } - - ret = vk->InvalidateMappedMemoryRanges(hwctx->act_dev, nb_mem, - map_mem_ranges); - if (ret != VK_SUCCESS) { - av_log(hwfc, AV_LOG_ERROR, "Failed to invalidate memory: %s\n", - vk_ret2str(ret)); - err = AVERROR_EXTERNAL; - goto fail; - } - } - - for (int i = 0; i < planes; i++) { - VkImageSubresource sub = { - .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT, - }; - VkSubresourceLayout layout; - vk->GetImageSubresourceLayout(hwctx->act_dev, f->img[i], &sub, &layout); - dst->linesize[i] = layout.rowPitch; - } - - map->frame = f; - map->flags = flags; - - err = ff_hwframe_map_create(src->hw_frames_ctx, dst, src, - &vulkan_unmap_frame, map); - if (err < 0) - goto fail; - - return 0; - -fail: - for (int i = 0; i < mapped_mem_count; i++) - vk->UnmapMemory(hwctx->act_dev, f->mem[i]); - - av_free(map); - return err; -} - #if CONFIG_LIBDRM static void vulkan_unmap_from_drm(AVHWFramesContext *hwfc, HWMapDescriptor *hwmap) { @@ -3692,8 +3554,9 @@ static int vulkan_map_from(AVHWFramesContext *hwfc, AVFrame *dst, #endif #endif default: - return vulkan_map_frame_to_mem(hwfc, dst, src, flags); + break; } + return AVERROR(ENOSYS); } typedef struct ImageBuffer { @@ -4100,23 +3963,6 @@ static int vulkan_transfer_data(AVHWFramesContext *hwfc, const AVFrame *vkf, if (swf->width > hwfc->width || swf->height > hwfc->height) return AVERROR(EINVAL); - /* For linear, host visiable images */ - if (fc->tiling == VK_IMAGE_TILING_LINEAR && - f->flags & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) { - AVFrame *map = av_frame_alloc(); - if (!map) - return AVERROR(ENOMEM); - map->format = swf->format; - - err = vulkan_map_frame_to_mem(hwfc, map, vkf, AV_HWFRAME_MAP_WRITE); - if (err) - return err; - - err = av_frame_copy((AVFrame *)(from ? swf : map), from ? map : swf); - av_frame_free(&map); - return err; - } - /* Create buffers */ for (int i = 0; i < planes; i++) { size_t req_size; From 94e17a63a446d1c1dc5ae36fcf58fb43a6ef22fe Mon Sep 17 00:00:00 2001 From: Lynne Date: Fri, 17 Feb 2023 04:14:08 +0100 Subject: [PATCH 1273/2172] hwcontext_vulkan: don't change properties if prepare_frame fails --- libavutil/hwcontext_vulkan.c | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/libavutil/hwcontext_vulkan.c b/libavutil/hwcontext_vulkan.c index a0139871c9f..4eab89e93cf 100644 --- a/libavutil/hwcontext_vulkan.c +++ b/libavutil/hwcontext_vulkan.c @@ -2200,16 +2200,13 @@ static int prepare_frame(AVHWFramesContext *hwfc, VulkanExecCtx *ectx, break; } - /* Change the image layout to something more optimal for writes. - * This also signals the newly created semaphore, making it usable - * for synchronization */ for (int i = 0; i < nb_images; i++) { img_bar[i] = (VkImageMemoryBarrier2) { .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER_2, .pNext = NULL, - .srcStageMask = VK_PIPELINE_STAGE_2_TOP_OF_PIPE_BIT, - .srcAccessMask = 0x0, - .dstStageMask = VK_PIPELINE_STAGE_TRANSFER_BIT, + .srcStageMask = VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT, + .dstStageMask = VK_PIPELINE_STAGE_2_TRANSFER_BIT, + .srcAccessMask = frame->access[i], .dstAccessMask = new_access, .oldLayout = frame->layout[i], .newLayout = new_layout, @@ -2222,9 +2219,6 @@ static int prepare_frame(AVHWFramesContext *hwfc, VulkanExecCtx *ectx, .levelCount = 1, }, }; - - frame->layout[i] = img_bar[i].newLayout; - frame->access[i] = img_bar[i].dstAccessMask; } vk->CmdPipelineBarrier2(get_buf_exec_ctx(hwfc, ectx), &(VkDependencyInfo) { @@ -2234,6 +2228,13 @@ static int prepare_frame(AVHWFramesContext *hwfc, VulkanExecCtx *ectx, }); err = submit_exec_ctx(hwfc, ectx, &s_info, frame, 0); + if (err >= 0) { + for (int i = 0; i < nb_images; i++) { + frame->layout[i] = img_bar[i].newLayout; + frame->access[i] = img_bar[i].dstAccessMask; + frame->queue_family[i] = img_bar[i].dstQueueFamilyIndex; + } + } vkfc->unlock_frame(hwfc, frame); return err; From 33fc919bb7b5779cacabfb817fe6dd68a0454c8f Mon Sep 17 00:00:00 2001 From: Lynne Date: Thu, 2 Mar 2023 13:02:25 +0100 Subject: [PATCH 1274/2172] hwcontext_vulkan: remove duplicate code, port to use generic vulkan utils The temporary AVFrame on staack enables us to use the common dependency/dispatch code in prepare_frame(). The prepare_frame() function is used for both frame initialization and frame import/export queue family transfer operations. In the former case, no AVFrame exists yet, so, as this is purely libavutil code, we create a temporary frame on stack. Otherwise, we'd need to allocate multiple frames somewhere, one for each possible command buffer dispatch. --- libavutil/Makefile | 2 +- libavutil/hwcontext_vulkan.c | 1005 +++++++--------------------------- libavutil/vulkan.h | 13 + 3 files changed, 209 insertions(+), 811 deletions(-) diff --git a/libavutil/Makefile b/libavutil/Makefile index dc9012f9a83..bd9c6f9e327 100644 --- a/libavutil/Makefile +++ b/libavutil/Makefile @@ -195,7 +195,7 @@ OBJS-$(CONFIG_QSV) += hwcontext_qsv.o OBJS-$(CONFIG_VAAPI) += hwcontext_vaapi.o OBJS-$(CONFIG_VIDEOTOOLBOX) += hwcontext_videotoolbox.o OBJS-$(CONFIG_VDPAU) += hwcontext_vdpau.o -OBJS-$(CONFIG_VULKAN) += hwcontext_vulkan.o +OBJS-$(CONFIG_VULKAN) += hwcontext_vulkan.o vulkan.o OBJS-$(!CONFIG_VULKAN) += hwcontext_stub.o diff --git a/libavutil/hwcontext_vulkan.c b/libavutil/hwcontext_vulkan.c index 4eab89e93cf..ff2cde2dd65 100644 --- a/libavutil/hwcontext_vulkan.c +++ b/libavutil/hwcontext_vulkan.c @@ -78,18 +78,13 @@ typedef struct VulkanQueueCtx { unsigned int buf_deps_alloc_size; } VulkanQueueCtx; -typedef struct VulkanExecCtx { - VkCommandPool pool; - VkCommandBuffer *bufs; - VulkanQueueCtx *queues; - int nb_queues; - int cur_queue_idx; -} VulkanExecCtx; - typedef struct VulkanDevicePriv { /* Vulkan library and loader functions */ void *libvulkan; - FFVulkanFunctions vkfn; + + FFVulkanContext vkctx; + FFVkQueueFamilyCtx compute_qf; + FFVkQueueFamilyCtx transfer_qf; /* Properties */ VkPhysicalDeviceProperties2 props; @@ -111,9 +106,6 @@ typedef struct VulkanDevicePriv { /* Debug callback */ VkDebugUtilsMessengerEXT debug_ctx; - /* Extensions */ - FFVulkanExtensions extensions; - /* Settings */ int use_linear_images; @@ -129,11 +121,11 @@ typedef struct VulkanDevicePriv { typedef struct VulkanFramesPriv { /* Image conversions */ - VulkanExecCtx conv_ctx; + FFVkExecPool compute_exec; /* Image transfers */ - VulkanExecCtx upload_ctx; - VulkanExecCtx download_ctx; + FFVkExecPool upload_exec; + FFVkExecPool download_exec; /* Modifier info list to free at uninit */ VkImageDrmFormatModifierListCreateInfoEXT *modifier_info; @@ -292,7 +284,7 @@ static int vkfmt_from_pixfmt2(AVHWDeviceContext *dev_ctx, enum AVPixelFormat p, { AVVulkanDeviceContext *hwctx = dev_ctx->hwctx; VulkanDevicePriv *priv = dev_ctx->internal->priv; - FFVulkanFunctions *vk = &priv->vkfn; + FFVulkanFunctions *vk = &priv->vkctx.vkfn; const VkFormatFeatureFlagBits2 basic_flags = VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_2_TRANSFER_SRC_BIT | @@ -358,31 +350,6 @@ static int vkfmt_from_pixfmt2(AVHWDeviceContext *dev_ctx, enum AVPixelFormat p, return AVERROR(EINVAL); } -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 load_libvulkan(AVHWDeviceContext *ctx) { AVVulkanDeviceContext *hwctx = ctx->hwctx; @@ -453,47 +420,6 @@ static const VulkanOptExtension optional_device_exts[] = { { VK_KHR_VIDEO_DECODE_H265_EXTENSION_NAME, FF_VK_EXT_VIDEO_DECODE_H265 }, }; -/* Converts return values to strings */ -static const char *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); - CASE(VK_ERROR_INVALID_DRM_FORMAT_MODIFIER_PLANE_LAYOUT_EXT); - CASE(VK_ERROR_INVALID_DEVICE_ADDRESS_EXT); - CASE(VK_ERROR_FULL_SCREEN_EXCLUSIVE_MODE_LOST_EXT); - default: return "Unknown error"; - } -#undef CASE -} - static VkBool32 VKAPI_CALL vk_dbg_callback(VkDebugUtilsMessageSeverityFlagBitsEXT severity, VkDebugUtilsMessageTypeFlagsEXT messageType, const VkDebugUtilsMessengerCallbackDataEXT *data, @@ -544,7 +470,7 @@ static int check_extensions(AVHWDeviceContext *ctx, int dev, AVDictionary *opts, const char *tstr; const char **extension_names = NULL; VulkanDevicePriv *p = ctx->internal->priv; - FFVulkanFunctions *vk = &p->vkfn; + FFVulkanFunctions *vk = &p->vkctx.vkfn; AVVulkanDeviceContext *hwctx = ctx->hwctx; int err = 0, found, extensions_found = 0; @@ -607,7 +533,7 @@ static int check_extensions(AVHWDeviceContext *ctx, int dev, AVDictionary *opts, continue; av_log(ctx, AV_LOG_VERBOSE, "Using %s extension %s\n", mod, tstr); - p->extensions |= optional_exts[i].flag; + p->vkctx.extensions |= optional_exts[i].flag; ADD_VAL_TO_LIST(extension_names, extensions_found, tstr); } @@ -623,7 +549,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 |= FF_VK_EXT_DEBUG_UTILS; + p->vkctx.extensions |= FF_VK_EXT_DEBUG_UTILS; } else { av_log(ctx, AV_LOG_ERROR, "Debug extension \"%s\" not found!\n", tstr); @@ -675,7 +601,7 @@ static int check_validation_layers(AVHWDeviceContext *ctx, AVDictionary *opts, int found = 0, err = 0; VulkanDevicePriv *priv = ctx->internal->priv; - FFVulkanFunctions *vk = &priv->vkfn; + FFVulkanFunctions *vk = &priv->vkctx.vkfn; uint32_t sup_layer_count; VkLayerProperties *sup_layers; @@ -782,7 +708,7 @@ static int create_instance(AVHWDeviceContext *ctx, AVDictionary *opts) int err = 0, debug_mode = 0; VkResult ret; VulkanDevicePriv *p = ctx->internal->priv; - FFVulkanFunctions *vk = &p->vkfn; + FFVulkanFunctions *vk = &p->vkctx.vkfn; AVVulkanDeviceContext *hwctx = ctx->hwctx; VkApplicationInfo application_info = { .sType = VK_STRUCTURE_TYPE_APPLICATION_INFO, @@ -810,7 +736,7 @@ static int create_instance(AVHWDeviceContext *ctx, AVDictionary *opts) return err; } - err = ff_vk_load_functions(ctx, vk, p->extensions, 0, 0); + err = ff_vk_load_functions(ctx, vk, p->vkctx.extensions, 0, 0); if (err < 0) { av_log(ctx, AV_LOG_ERROR, "Unable to load instance enumeration functions!\n"); return err; @@ -846,12 +772,12 @@ static int create_instance(AVHWDeviceContext *ctx, AVDictionary *opts) /* Check for errors */ if (ret != VK_SUCCESS) { av_log(ctx, AV_LOG_ERROR, "Instance creation failure: %s\n", - vk_ret2str(ret)); + ff_vk_ret2str(ret)); err = AVERROR_EXTERNAL; goto fail; } - err = ff_vk_load_functions(ctx, vk, p->extensions, 1, 0); + err = ff_vk_load_functions(ctx, vk, p->vkctx.extensions, 1, 0); if (err < 0) { av_log(ctx, AV_LOG_ERROR, "Unable to load instance functions!\n"); goto fail; @@ -912,7 +838,7 @@ static int find_device(AVHWDeviceContext *ctx, VulkanDeviceSelection *select) uint32_t num; VkResult ret; VulkanDevicePriv *p = ctx->internal->priv; - FFVulkanFunctions *vk = &p->vkfn; + FFVulkanFunctions *vk = &p->vkctx.vkfn; VkPhysicalDevice *devices = NULL; VkPhysicalDeviceIDProperties *idp = NULL; VkPhysicalDeviceProperties2 *prop = NULL; @@ -921,7 +847,7 @@ static int find_device(AVHWDeviceContext *ctx, VulkanDeviceSelection *select) ret = vk->EnumeratePhysicalDevices(hwctx->inst, &num, NULL); if (ret != VK_SUCCESS || !num) { - av_log(ctx, AV_LOG_ERROR, "No devices found: %s!\n", vk_ret2str(ret)); + av_log(ctx, AV_LOG_ERROR, "No devices found: %s!\n", ff_vk_ret2str(ret)); return AVERROR(ENODEV); } @@ -932,7 +858,7 @@ static int find_device(AVHWDeviceContext *ctx, VulkanDeviceSelection *select) ret = vk->EnumeratePhysicalDevices(hwctx->inst, &num, devices); if (ret != VK_SUCCESS) { av_log(ctx, AV_LOG_ERROR, "Failed enumerating devices: %s\n", - vk_ret2str(ret)); + ff_vk_ret2str(ret)); err = AVERROR(ENODEV); goto end; } @@ -1092,7 +1018,7 @@ static int setup_queue_families(AVHWDeviceContext *ctx, VkDeviceCreateInfo *cd) float *weights; VkQueueFamilyProperties *qf = NULL; VulkanDevicePriv *p = ctx->internal->priv; - FFVulkanFunctions *vk = &p->vkfn; + FFVulkanFunctions *vk = &p->vkctx.vkfn; AVVulkanDeviceContext *hwctx = ctx->hwctx; int graph_index, comp_index, tx_index, enc_index, dec_index; @@ -1220,241 +1146,10 @@ static int setup_queue_families(AVHWDeviceContext *ctx, VkDeviceCreateInfo *cd) return 0; } -static int create_exec_ctx(AVHWFramesContext *hwfc, VulkanExecCtx *cmd, - int queue_family_index, int num_queues) -{ - VkResult ret; - AVVulkanDeviceContext *hwctx = hwfc->device_ctx->hwctx; - VulkanDevicePriv *p = hwfc->device_ctx->internal->priv; - FFVulkanFunctions *vk = &p->vkfn; - - VkCommandPoolCreateInfo cqueue_create = { - .sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO, - .flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, - .queueFamilyIndex = queue_family_index, - }; - VkCommandBufferAllocateInfo cbuf_create = { - .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, - .level = VK_COMMAND_BUFFER_LEVEL_PRIMARY, - .commandBufferCount = num_queues, - }; - - cmd->nb_queues = num_queues; - - /* Create command pool */ - ret = vk->CreateCommandPool(hwctx->act_dev, &cqueue_create, - hwctx->alloc, &cmd->pool); - if (ret != VK_SUCCESS) { - av_log(hwfc, AV_LOG_ERROR, "Command pool creation failure: %s\n", - vk_ret2str(ret)); - return AVERROR_EXTERNAL; - } - - cmd->bufs = av_mallocz(num_queues * sizeof(*cmd->bufs)); - if (!cmd->bufs) - return AVERROR(ENOMEM); - - cbuf_create.commandPool = cmd->pool; - - /* Allocate command buffer */ - ret = vk->AllocateCommandBuffers(hwctx->act_dev, &cbuf_create, cmd->bufs); - if (ret != VK_SUCCESS) { - av_log(hwfc, AV_LOG_ERROR, "Command buffer alloc failure: %s\n", - vk_ret2str(ret)); - av_freep(&cmd->bufs); - return AVERROR_EXTERNAL; - } - - cmd->queues = av_mallocz(num_queues * sizeof(*cmd->queues)); - if (!cmd->queues) - return AVERROR(ENOMEM); - - for (int i = 0; i < num_queues; i++) { - VulkanQueueCtx *q = &cmd->queues[i]; - vk->GetDeviceQueue(hwctx->act_dev, queue_family_index, i, &q->queue); - q->was_synchronous = 1; - q->qf = queue_family_index; - q->qidx = i; - } - - return 0; -} - -static void free_exec_ctx(AVHWFramesContext *hwfc, VulkanExecCtx *cmd) -{ - AVVulkanDeviceContext *hwctx = hwfc->device_ctx->hwctx; - VulkanDevicePriv *p = hwfc->device_ctx->internal->priv; - FFVulkanFunctions *vk = &p->vkfn; - - if (cmd->queues) { - for (int i = 0; i < cmd->nb_queues; i++) { - VulkanQueueCtx *q = &cmd->queues[i]; - - /* Make sure all queues have finished executing */ - if (q->fence && !q->was_synchronous) { - vk->WaitForFences(hwctx->act_dev, 1, &q->fence, VK_TRUE, UINT64_MAX); - vk->ResetFences(hwctx->act_dev, 1, &q->fence); - } - - /* Free the fence */ - if (q->fence) - vk->DestroyFence(hwctx->act_dev, q->fence, 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); - } - } - - if (cmd->bufs) - vk->FreeCommandBuffers(hwctx->act_dev, cmd->pool, cmd->nb_queues, cmd->bufs); - if (cmd->pool) - vk->DestroyCommandPool(hwctx->act_dev, cmd->pool, hwctx->alloc); - - av_freep(&cmd->queues); - av_freep(&cmd->bufs); - cmd->pool = VK_NULL_HANDLE; -} - -static VkCommandBuffer get_buf_exec_ctx(AVHWFramesContext *hwfc, VulkanExecCtx *cmd) -{ - return cmd->bufs[cmd->cur_queue_idx]; -} - -static void unref_exec_ctx_deps(AVHWFramesContext *hwfc, VulkanExecCtx *cmd) -{ - VulkanQueueCtx *q = &cmd->queues[cmd->cur_queue_idx]; - - for (int j = 0; j < q->nb_buf_deps; j++) - av_buffer_unref(&q->buf_deps[j]); - q->nb_buf_deps = 0; -} - -static int wait_start_exec_ctx(AVHWFramesContext *hwfc, VulkanExecCtx *cmd) -{ - VkResult ret; - AVVulkanDeviceContext *hwctx = hwfc->device_ctx->hwctx; - VulkanQueueCtx *q = &cmd->queues[cmd->cur_queue_idx]; - VulkanDevicePriv *p = hwfc->device_ctx->internal->priv; - FFVulkanFunctions *vk = &p->vkfn; - - 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(hwctx->act_dev, &fence_spawn, hwctx->alloc, - &q->fence); - if (ret != VK_SUCCESS) { - av_log(hwfc, AV_LOG_ERROR, "Failed to queue frame fence: %s\n", - vk_ret2str(ret)); - return AVERROR_EXTERNAL; - } - } else if (!q->was_synchronous) { - vk->WaitForFences(hwctx->act_dev, 1, &q->fence, VK_TRUE, UINT64_MAX); - vk->ResetFences(hwctx->act_dev, 1, &q->fence); - } - - /* Discard queue dependencies */ - unref_exec_ctx_deps(hwfc, cmd); - - ret = vk->BeginCommandBuffer(cmd->bufs[cmd->cur_queue_idx], &cmd_start); - if (ret != VK_SUCCESS) { - av_log(hwfc, AV_LOG_ERROR, "Unable to init command buffer: %s\n", - vk_ret2str(ret)); - return AVERROR_EXTERNAL; - } - - return 0; -} - -static int add_buf_dep_exec_ctx(AVHWFramesContext *hwfc, VulkanExecCtx *cmd, - AVBufferRef * const *deps, int nb_deps) -{ - AVBufferRef **dst; - VulkanQueueCtx *q = &cmd->queues[cmd->cur_queue_idx]; - - 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] = av_buffer_ref(deps[i]); - if (!q->buf_deps[q->nb_buf_deps]) - goto err; - q->nb_buf_deps++; - } - - return 0; - -err: - unref_exec_ctx_deps(hwfc, cmd); - return AVERROR(ENOMEM); -} - -static int submit_exec_ctx(AVHWFramesContext *hwfc, VulkanExecCtx *cmd, - VkSubmitInfo *s_info, AVVkFrame *f, int synchronous) -{ - VkResult ret; - VulkanQueueCtx *q = &cmd->queues[cmd->cur_queue_idx]; - VulkanDevicePriv *p = hwfc->device_ctx->internal->priv; - AVVulkanDeviceContext *hwctx = hwfc->device_ctx->hwctx; - FFVulkanFunctions *vk = &p->vkfn; - - ret = vk->EndCommandBuffer(cmd->bufs[cmd->cur_queue_idx]); - if (ret != VK_SUCCESS) { - av_log(hwfc, AV_LOG_ERROR, "Unable to finish command buffer: %s\n", - vk_ret2str(ret)); - unref_exec_ctx_deps(hwfc, cmd); - return AVERROR_EXTERNAL; - } - - s_info->pCommandBuffers = &cmd->bufs[cmd->cur_queue_idx]; - s_info->commandBufferCount = 1; - - hwctx->lock_queue(hwfc->device_ctx, q->qf, q->qidx); - ret = vk->QueueSubmit(q->queue, 1, s_info, q->fence); - hwctx->unlock_queue(hwfc->device_ctx, q->qf, q->qidx); - 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; - } - - if (f) - for (int i = 0; i < s_info->signalSemaphoreCount; i++) - f->sem_value[i]++; - - q->was_synchronous = synchronous; - - if (synchronous) { - vk->WaitForFences(hwctx->act_dev, 1, &q->fence, VK_TRUE, UINT64_MAX); - vk->ResetFences(hwctx->act_dev, 1, &q->fence); - unref_exec_ctx_deps(hwfc, cmd); - } else { /* Rotate queues */ - cmd->cur_queue_idx = (cmd->cur_queue_idx + 1) % cmd->nb_queues; - } - - return 0; -} - static void vulkan_device_free(AVHWDeviceContext *ctx) { VulkanDevicePriv *p = ctx->internal->priv; - FFVulkanFunctions *vk = &p->vkfn; + FFVulkanFunctions *vk = &p->vkctx.vkfn; AVVulkanDeviceContext *hwctx = ctx->hwctx; if (hwctx->act_dev) @@ -1488,7 +1183,7 @@ static int vulkan_device_create_internal(AVHWDeviceContext *ctx, VkResult ret; AVDictionaryEntry *opt_d; VulkanDevicePriv *p = ctx->internal->priv; - FFVulkanFunctions *vk = &p->vkfn; + FFVulkanFunctions *vk = &p->vkctx.vkfn; AVVulkanDeviceContext *hwctx = ctx->hwctx; /* @@ -1591,7 +1286,7 @@ static int vulkan_device_create_internal(AVHWDeviceContext *ctx, if (ret != VK_SUCCESS) { av_log(ctx, AV_LOG_ERROR, "Device creation failure: %s\n", - vk_ret2str(ret)); + ff_vk_ret2str(ret)); for (int i = 0; i < dev_info.enabledExtensionCount; i++) av_free((void *)dev_info.ppEnabledExtensionNames[i]); av_free((void *)dev_info.ppEnabledExtensionNames); @@ -1633,7 +1328,7 @@ static int vulkan_device_init(AVHWDeviceContext *ctx) uint32_t qf_num; AVVulkanDeviceContext *hwctx = ctx->hwctx; VulkanDevicePriv *p = ctx->internal->priv; - FFVulkanFunctions *vk = &p->vkfn; + FFVulkanFunctions *vk = &p->vkctx.vkfn; VkQueueFamilyProperties *qf; int graph_index, comp_index, tx_index, enc_index, dec_index; @@ -1642,13 +1337,13 @@ 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)) { - p->extensions |= optional_device_exts[j].flag; + p->vkctx.extensions |= optional_device_exts[j].flag; break; } } } - err = ff_vk_load_functions(ctx, vk, p->extensions, 1, 1); + err = ff_vk_load_functions(ctx, vk, p->vkctx.extensions, 1, 1); if (err < 0) { av_log(ctx, AV_LOG_ERROR, "Unable to load functions!\n"); return err; @@ -1668,7 +1363,7 @@ static int vulkan_device_init(AVHWDeviceContext *ctx) p->props.properties.limits.minMemoryMapAlignment); av_log(ctx, AV_LOG_VERBOSE, " nonCoherentAtomSize: %"PRIu64"\n", p->props.properties.limits.nonCoherentAtomSize); - if (p->extensions & FF_VK_EXT_EXTERNAL_HOST_MEMORY) + if (p->vkctx.extensions & FF_VK_EXT_EXTERNAL_HOST_MEMORY) av_log(ctx, AV_LOG_VERBOSE, " minImportedHostPointerAlignment: %"PRIu64"\n", p->hprops.minImportedHostPointerAlignment); @@ -1757,6 +1452,13 @@ static int vulkan_device_init(AVHWDeviceContext *ctx) /* Get device capabilities */ vk->GetPhysicalDeviceMemoryProperties(hwctx->phys_dev, &p->mprops); + p->vkctx.device = ctx; + p->vkctx.hwctx = hwctx; + + ff_vk_load_props(&p->vkctx); + ff_vk_qf_init(&p->vkctx, &p->compute_qf, VK_QUEUE_COMPUTE_BIT); + ff_vk_qf_init(&p->vkctx, &p->transfer_qf, VK_QUEUE_TRANSFER_BIT); + return 0; } @@ -1921,7 +1623,7 @@ static int alloc_mem(AVHWDeviceContext *ctx, VkMemoryRequirements *req, VkResult ret; int index = -1; VulkanDevicePriv *p = ctx->internal->priv; - FFVulkanFunctions *vk = &p->vkfn; + FFVulkanFunctions *vk = &p->vkctx.vkfn; AVVulkanDeviceContext *dev_hwctx = ctx->hwctx; VkMemoryAllocateInfo alloc_info = { .sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO, @@ -1963,7 +1665,7 @@ static int alloc_mem(AVHWDeviceContext *ctx, VkMemoryRequirements *req, dev_hwctx->alloc, mem); if (ret != VK_SUCCESS) { av_log(ctx, AV_LOG_ERROR, "Failed to allocate memory: %s\n", - vk_ret2str(ret)); + ff_vk_ret2str(ret)); return AVERROR(ENOMEM); } @@ -2014,7 +1716,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; - FFVulkanFunctions *vk = &p->vkfn; + FFVulkanFunctions *vk = &p->vkctx.vkfn; int nb_images = ff_vk_count_images(f); VkSemaphoreWaitInfo sem_wait = { @@ -2044,8 +1746,7 @@ static int alloc_bind_mem(AVHWFramesContext *hwfc, AVVkFrame *f, VkResult ret; AVHWDeviceContext *ctx = hwfc->device_ctx; VulkanDevicePriv *p = ctx->internal->priv; - FFVulkanFunctions *vk = &p->vkfn; - AVVulkanFramesContext *hwfctx = hwfc->hwctx; + FFVulkanFunctions *vk = &p->vkctx.vkfn; VkBindImageMemoryInfo bind_info[AV_NUM_DATA_POINTERS] = { { 0 } }; AVVulkanDeviceContext *hwctx = ctx->hwctx; @@ -2101,7 +1802,7 @@ static int alloc_bind_mem(AVHWFramesContext *hwfc, AVVkFrame *f, ret = vk->BindImageMemory2(hwctx->act_dev, img_cnt, bind_info); if (ret != VK_SUCCESS) { av_log(ctx, AV_LOG_ERROR, "Failed to bind memory: %s\n", - vk_ret2str(ret)); + ff_vk_ret2str(ret)); return AVERROR_EXTERNAL; } @@ -2116,128 +1817,86 @@ enum PrepMode { PREP_MODE_DECODING_DPB, }; -static int prepare_frame(AVHWFramesContext *hwfc, VulkanExecCtx *ectx, +static int prepare_frame(AVHWFramesContext *hwfc, FFVkExecPool *ectx, AVVkFrame *frame, enum PrepMode pmode) { int err; - uint32_t src_qf, dst_qf; - VkImageLayout new_layout; - VkAccessFlags2 new_access; - AVVulkanFramesContext *vkfc = hwfc->hwctx; VulkanDevicePriv *p = hwfc->device_ctx->internal->priv; - FFVulkanFunctions *vk = &p->vkfn; - uint64_t sem_sig_val[AV_NUM_DATA_POINTERS]; - int nb_images = ff_vk_count_images(frame); + FFVulkanFunctions *vk = &p->vkctx.vkfn; + VkImageMemoryBarrier2 img_bar[AV_NUM_DATA_POINTERS]; + int nb_img_bar = 0; - VkImageMemoryBarrier2 img_bar[AV_NUM_DATA_POINTERS] = { 0 }; - VkDependencyInfo dep_info; + uint32_t dst_qf = VK_QUEUE_FAMILY_IGNORED; + VkImageLayout new_layout; + VkAccessFlags2 new_access; + VkPipelineStageFlagBits2 src_stage = VK_PIPELINE_STAGE_2_NONE; - VkTimelineSemaphoreSubmitInfo s_timeline_sem_info = { - .sType = VK_STRUCTURE_TYPE_TIMELINE_SEMAPHORE_SUBMIT_INFO, - .pSignalSemaphoreValues = sem_sig_val, - .signalSemaphoreValueCount = nb_images, + /* This is dirty - but it works. The vulkan.c dependency system doesn't + * free non-refcounted frames, and non-refcounted hardware frames cannot + * happen anywhere outside of here. */ + AVBufferRef tmp_ref = { + .data = (uint8_t *)hwfc, }; - - VkSubmitInfo s_info = { - .sType = VK_STRUCTURE_TYPE_SUBMIT_INFO, - .pNext = &s_timeline_sem_info, - .pSignalSemaphores = frame->sem, - .signalSemaphoreCount = nb_images, + AVFrame tmp_frame = { + .data[0] = (uint8_t *)frame, + .hw_frames_ctx = &tmp_ref, }; - VkPipelineStageFlagBits wait_st[AV_NUM_DATA_POINTERS]; + VkCommandBuffer cmd_buf; + FFVkExecContext *exec = ff_vk_exec_get(ectx); + cmd_buf = exec->buf; + ff_vk_exec_start(&p->vkctx, exec); - if ((err = wait_start_exec_ctx(hwfc, ectx))) + err = ff_vk_exec_add_dep_frame(&p->vkctx, exec, &tmp_frame, + VK_PIPELINE_STAGE_2_NONE, + VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT); + if (err < 0) return err; - vkfc->lock_frame(hwfc, frame); - - for (int i = 0; i < nb_images; 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: 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_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 = nb_images; - s_info.pWaitSemaphores = frame->sem; - s_info.pWaitDstStageMask = wait_st; - s_info.waitSemaphoreCount = nb_images; 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 = nb_images; - s_info.pWaitSemaphores = frame->sem; - s_info.pWaitDstStageMask = wait_st; - s_info.waitSemaphoreCount = nb_images; + src_stage = VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT; break; case PREP_MODE_DECODING_DST: new_layout = VK_IMAGE_LAYOUT_VIDEO_DECODE_DST_KHR; new_access = VK_ACCESS_TRANSFER_WRITE_BIT; - src_qf = VK_QUEUE_FAMILY_IGNORED; - dst_qf = VK_QUEUE_FAMILY_IGNORED; break; case PREP_MODE_DECODING_DPB: new_layout = VK_IMAGE_LAYOUT_VIDEO_DECODE_DPB_KHR; new_access = VK_ACCESS_TRANSFER_READ_BIT | VK_ACCESS_TRANSFER_WRITE_BIT; - src_qf = VK_QUEUE_FAMILY_IGNORED; - dst_qf = VK_QUEUE_FAMILY_IGNORED; break; } - for (int i = 0; i < nb_images; i++) { - img_bar[i] = (VkImageMemoryBarrier2) { - .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER_2, - .pNext = NULL, - .srcStageMask = VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT, - .dstStageMask = VK_PIPELINE_STAGE_2_TRANSFER_BIT, - .srcAccessMask = frame->access[i], - .dstAccessMask = new_access, - .oldLayout = frame->layout[i], - .newLayout = new_layout, - .srcQueueFamilyIndex = src_qf, - .dstQueueFamilyIndex = dst_qf, - .image = frame->img[i], - .subresourceRange = (VkImageSubresourceRange) { - .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT, - .layerCount = VK_REMAINING_ARRAY_LAYERS, - .levelCount = 1, - }, - }; - } + ff_vk_frame_barrier(&p->vkctx, exec, &tmp_frame, img_bar, &nb_img_bar, + src_stage, + VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT, + new_access, new_layout, dst_qf); - vk->CmdPipelineBarrier2(get_buf_exec_ctx(hwfc, ectx), &(VkDependencyInfo) { + vk->CmdPipelineBarrier2(cmd_buf, &(VkDependencyInfo) { .sType = VK_STRUCTURE_TYPE_DEPENDENCY_INFO, .pImageMemoryBarriers = img_bar, - .imageMemoryBarrierCount = nb_images, + .imageMemoryBarrierCount = nb_img_bar, }); - err = submit_exec_ctx(hwfc, ectx, &s_info, frame, 0); - if (err >= 0) { - for (int i = 0; i < nb_images; i++) { - frame->layout[i] = img_bar[i].newLayout; - frame->access[i] = img_bar[i].dstAccessMask; - frame->queue_family[i] = img_bar[i].dstQueueFamilyIndex; - } - } - vkfc->unlock_frame(hwfc, frame); + err = ff_vk_exec_submit(&p->vkctx, exec); + if (err < 0) + return err; - return err; + /* We can do this because there are no real dependencies */ + ff_vk_exec_discard_deps(&p->vkctx, exec); + + return 0; } static inline void get_plane_wh(uint32_t *w, uint32_t *h, enum AVPixelFormat format, @@ -2267,9 +1926,8 @@ static int create_frame(AVHWFramesContext *hwfc, AVVkFrame **frame, AVVulkanFramesContext *hwfc_vk = hwfc->hwctx; AVHWDeviceContext *ctx = hwfc->device_ctx; VulkanDevicePriv *p = ctx->internal->priv; - FFVulkanFunctions *vk = &p->vkfn; + FFVulkanFunctions *vk = &p->vkctx.vkfn; AVVulkanDeviceContext *hwctx = ctx->hwctx; - AVVulkanFramesContext *frames = hwfc->hwctx; VkExportSemaphoreCreateInfo ext_sem_info = { .sType = VK_STRUCTURE_TYPE_EXPORT_SEMAPHORE_CREATE_INFO, @@ -2285,9 +1943,9 @@ static int create_frame(AVHWFramesContext *hwfc, AVVkFrame **frame, 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, + .pNext = p->vkctx.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, + .pNext = p->vkctx.extensions & FF_VK_EXT_EXTERNAL_FD_SEM ? &ext_sem_info : NULL, #endif .semaphoreType = VK_SEMAPHORE_TYPE_TIMELINE, .initialValue = 0, @@ -2334,7 +1992,7 @@ static int create_frame(AVHWFramesContext *hwfc, AVVkFrame **frame, hwctx->alloc, &f->img[i]); if (ret != VK_SUCCESS) { av_log(ctx, AV_LOG_ERROR, "Image creation failure: %s\n", - vk_ret2str(ret)); + ff_vk_ret2str(ret)); err = AVERROR(EINVAL); goto fail; } @@ -2344,7 +2002,7 @@ static int create_frame(AVHWFramesContext *hwfc, AVVkFrame **frame, hwctx->alloc, &f->sem[i]); if (ret != VK_SUCCESS) { av_log(hwctx, AV_LOG_ERROR, "Failed to create semaphore: %s\n", - vk_ret2str(ret)); + ff_vk_ret2str(ret)); return AVERROR_EXTERNAL; } @@ -2375,11 +2033,11 @@ 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; - FFVulkanFunctions *vk = &p->vkfn; + FFVulkanFunctions *vk = &p->vkctx.vkfn; const VkImageDrmFormatModifierListCreateInfoEXT *drm_mod_info = - vk_find_struct(hwctx->create_pnext, - VK_STRUCTURE_TYPE_IMAGE_DRM_FORMAT_MODIFIER_LIST_CREATE_INFO_EXT); + ff_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; @@ -2446,12 +2104,12 @@ static AVBufferRef *vulkan_pool_alloc(void *opaque, size_t size) }; #ifdef _WIN32 - if (p->extensions & FF_VK_EXT_EXTERNAL_WIN32_MEMORY) + if (p->vkctx.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) + if (p->vkctx.extensions & FF_VK_EXT_EXTERNAL_FD_MEMORY) try_export_flags(hwfc, &eiinfo.handleTypes, &e, VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT); #endif @@ -2473,11 +2131,11 @@ static AVBufferRef *vulkan_pool_alloc(void *opaque, size_t size) if ( (hwctx->usage & VK_IMAGE_USAGE_VIDEO_DECODE_DPB_BIT_KHR) && !(hwctx->usage & VK_IMAGE_USAGE_VIDEO_DECODE_DST_BIT_KHR)) - err = prepare_frame(hwfc, &fp->conv_ctx, f, PREP_MODE_DECODING_DPB); + err = prepare_frame(hwfc, &fp->compute_exec, f, PREP_MODE_DECODING_DPB); else if (hwctx->usage & VK_IMAGE_USAGE_VIDEO_DECODE_DST_BIT_KHR) - err = prepare_frame(hwfc, &fp->conv_ctx, f, PREP_MODE_DECODING_DST); + err = prepare_frame(hwfc, &fp->compute_exec, f, PREP_MODE_DECODING_DST); else - err = prepare_frame(hwfc, &fp->conv_ctx, f, PREP_MODE_WRITE); + err = prepare_frame(hwfc, &fp->compute_exec, f, PREP_MODE_WRITE); if (err) goto fail; @@ -2505,6 +2163,7 @@ static void unlock_frame(AVHWFramesContext *fc, AVVkFrame *vkf) static void vulkan_frames_uninit(AVHWFramesContext *hwfc) { + VulkanDevicePriv *p = hwfc->device_ctx->internal->priv; VulkanFramesPriv *fp = hwfc->internal->priv; if (fp->modifier_info) { @@ -2513,9 +2172,9 @@ static void vulkan_frames_uninit(AVHWFramesContext *hwfc) 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); + ff_vk_exec_pool_free(&p->vkctx, &fp->compute_exec); + ff_vk_exec_pool_free(&p->vkctx, &fp->upload_exec); + ff_vk_exec_pool_free(&p->vkctx, &fp->download_exec); } static int vulkan_frames_init(AVHWFramesContext *hwfc) @@ -2524,7 +2183,6 @@ static int vulkan_frames_init(AVHWFramesContext *hwfc) AVVkFrame *f; AVVulkanFramesContext *hwctx = hwfc->hwctx; VulkanFramesPriv *fp = hwfc->internal->priv; - AVVulkanDeviceContext *dev_hwctx = hwfc->device_ctx->hwctx; VulkanDevicePriv *p = hwfc->device_ctx->internal->priv; VkImageUsageFlagBits supported_usage; const struct FFVkFormatEntry *fmt; @@ -2609,20 +2267,18 @@ static int vulkan_frames_init(AVHWFramesContext *hwfc) if (!hwctx->unlock_frame) hwctx->unlock_frame = unlock_frame; - err = create_exec_ctx(hwfc, &fp->conv_ctx, - dev_hwctx->queue_family_comp_index, - dev_hwctx->nb_comp_queues); + err = ff_vk_exec_pool_init(&p->vkctx, &p->compute_qf, &fp->compute_exec, + p->compute_qf.nb_queues*4, 0, 0, 0, NULL); if (err) return err; - err = create_exec_ctx(hwfc, &fp->upload_ctx, - dev_hwctx->queue_family_tx_index, - dev_hwctx->nb_tx_queues); + err = ff_vk_exec_pool_init(&p->vkctx, &p->transfer_qf, &fp->upload_exec, + p->transfer_qf.nb_queues*4, 0, 0, 0, NULL); if (err) return err; - err = create_exec_ctx(hwfc, &fp->download_ctx, - dev_hwctx->queue_family_tx_index, 1); + err = ff_vk_exec_pool_init(&p->vkctx, &p->transfer_qf, &fp->download_exec, + p->transfer_qf.nb_queues*4, 0, 0, 0, NULL); if (err) return err; @@ -2682,7 +2338,7 @@ static void vulkan_unmap_from_drm(AVHWFramesContext *hwfc, HWMapDescriptor *hwma AVVkFrame *f = hwmap->priv; AVVulkanDeviceContext *hwctx = hwfc->device_ctx->hwctx; VulkanDevicePriv *p = hwfc->device_ctx->internal->priv; - FFVulkanFunctions *vk = &p->vkfn; + FFVulkanFunctions *vk = &p->vkctx.vkfn; const int nb_images = ff_vk_count_images(f); VkSemaphoreWaitInfo wait_info = { @@ -2749,8 +2405,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; - FFVulkanFunctions *vk = &p->vkfn; - AVVulkanFramesContext *hwfctx = hwfc->hwctx; + FFVulkanFunctions *vk = &p->vkctx.vkfn; VulkanFramesPriv *fp = hwfc->internal->priv; const AVDRMFrameDescriptor *desc = (AVDRMFrameDescriptor *)src->data[0]; VkBindImageMemoryInfo bind_info[AV_DRM_MAX_PLANES]; @@ -2854,7 +2509,7 @@ static int vulkan_map_from_drm_frame_desc(AVHWFramesContext *hwfc, AVVkFrame **f &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)); + ff_vk_ret2str(ret)); err = AVERROR_EXTERNAL; goto fail; } @@ -2877,7 +2532,7 @@ static int vulkan_map_from_drm_frame_desc(AVHWFramesContext *hwfc, AVVkFrame **f hwctx->alloc, &f->img[i]); if (ret != VK_SUCCESS) { av_log(ctx, AV_LOG_ERROR, "Image creation failure: %s\n", - vk_ret2str(ret)); + ff_vk_ret2str(ret)); err = AVERROR(EINVAL); goto fail; } @@ -2886,7 +2541,7 @@ static int vulkan_map_from_drm_frame_desc(AVHWFramesContext *hwfc, AVVkFrame **f hwctx->alloc, &f->sem[i]); if (ret != VK_SUCCESS) { av_log(hwctx, AV_LOG_ERROR, "Failed to create semaphore: %s\n", - vk_ret2str(ret)); + ff_vk_ret2str(ret)); return AVERROR_EXTERNAL; } @@ -2940,7 +2595,7 @@ static int vulkan_map_from_drm_frame_desc(AVHWFramesContext *hwfc, AVVkFrame **f idesc.fd, &fdmp); if (ret != VK_SUCCESS) { av_log(hwfc, AV_LOG_ERROR, "Failed to get FD properties: %s\n", - vk_ret2str(ret)); + ff_vk_ret2str(ret)); err = AVERROR_EXTERNAL; close(idesc.fd); goto fail; @@ -2992,12 +2647,12 @@ static int vulkan_map_from_drm_frame_desc(AVHWFramesContext *hwfc, AVVkFrame **f ret = vk->BindImageMemory2(hwctx->act_dev, bind_counts, bind_info); if (ret != VK_SUCCESS) { av_log(ctx, AV_LOG_ERROR, "Failed to bind memory: %s\n", - vk_ret2str(ret)); + ff_vk_ret2str(ret)); err = AVERROR_EXTERNAL; goto fail; } - err = prepare_frame(hwfc, &fp->conv_ctx, f, PREP_MODE_EXTERNAL_IMPORT); + err = prepare_frame(hwfc, &fp->compute_exec, f, PREP_MODE_EXTERNAL_IMPORT); if (err) goto fail; @@ -3097,7 +2752,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; - FFVulkanFunctions *vk = &p->vkfn; + FFVulkanFunctions *vk = &p->vkctx.vkfn; AVHWFramesContext *cuda_fc = (AVHWFramesContext*)cuda_hwfc->data; AVHWDeviceContext *cuda_cu = cuda_fc->device_ctx; @@ -3157,7 +2812,7 @@ static int vulkan_export_to_cuda(AVHWFramesContext *hwfc, &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)); + ff_vk_ret2str(ret)); err = AVERROR_EXTERNAL; goto fail; } @@ -3185,7 +2840,7 @@ static int vulkan_export_to_cuda(AVHWFramesContext *hwfc, &ext_desc.handle.fd); if (ret != VK_SUCCESS) { av_log(hwfc, AV_LOG_ERROR, "Unable to export the image as a FD: %s!\n", - vk_ret2str(ret)); + ff_vk_ret2str(ret)); err = AVERROR_EXTERNAL; goto fail; } @@ -3228,7 +2883,7 @@ static int vulkan_export_to_cuda(AVHWFramesContext *hwfc, #endif if (ret != VK_SUCCESS) { av_log(ctx, AV_LOG_ERROR, "Failed to export semaphore: %s\n", - vk_ret2str(ret)); + ff_vk_ret2str(ret)); err = AVERROR_EXTERNAL; goto fail; } @@ -3276,7 +2931,7 @@ static int vulkan_transfer_data_from_cuda(AVHWFramesContext *hwfc, dst_f = (AVVkFrame *)dst->data[0]; - err = prepare_frame(hwfc, &fp->upload_ctx, dst_f, PREP_MODE_EXTERNAL_EXPORT); + err = prepare_frame(hwfc, &fp->upload_exec, dst_f, PREP_MODE_EXTERNAL_EXPORT); if (err < 0) return err; @@ -3336,7 +2991,7 @@ static int vulkan_transfer_data_from_cuda(AVHWFramesContext *hwfc, av_log(hwfc, AV_LOG_VERBOSE, "Transfered CUDA image to Vulkan!\n"); - return err = prepare_frame(hwfc, &fp->upload_ctx, dst_f, PREP_MODE_EXTERNAL_IMPORT); + return err = prepare_frame(hwfc, &fp->upload_exec, dst_f, PREP_MODE_EXTERNAL_IMPORT); fail: CHECK_CU(cu->cuCtxPopCurrent(&dummy)); @@ -3356,13 +3011,13 @@ static int vulkan_map_to(AVHWFramesContext *hwfc, AVFrame *dst, #if CONFIG_LIBDRM #if CONFIG_VAAPI case AV_PIX_FMT_VAAPI: - if (p->extensions & FF_VK_EXT_DRM_MODIFIER_FLAGS) + if (p->vkctx.extensions & 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 & FF_VK_EXT_DRM_MODIFIER_FLAGS) + if (p->vkctx.extensions & FF_VK_EXT_DRM_MODIFIER_FLAGS) return vulkan_map_from_drm(hwfc, dst, src, flags); else return AVERROR(ENOSYS); @@ -3403,7 +3058,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; - FFVulkanFunctions *vk = &p->vkfn; + FFVulkanFunctions *vk = &p->vkctx.vkfn; VulkanFramesPriv *fp = hwfc->internal->priv; AVVulkanDeviceContext *hwctx = hwfc->device_ctx->hwctx; AVVulkanFramesContext *hwfctx = hwfc->hwctx; @@ -3421,7 +3076,7 @@ static int vulkan_map_to_drm(AVHWFramesContext *hwfc, AVFrame *dst, if (!drm_desc) return AVERROR(ENOMEM); - err = prepare_frame(hwfc, &fp->conv_ctx, f, PREP_MODE_EXTERNAL_EXPORT); + err = prepare_frame(hwfc, &fp->compute_exec, f, PREP_MODE_EXTERNAL_EXPORT); if (err < 0) goto end; @@ -3542,13 +3197,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 & FF_VK_EXT_DRM_MODIFIER_FLAGS) + if (p->vkctx.extensions & 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 & FF_VK_EXT_DRM_MODIFIER_FLAGS) + if (p->vkctx.extensions & FF_VK_EXT_DRM_MODIFIER_FLAGS) return vulkan_map_to_vaapi(hwfc, dst, src, flags); else return AVERROR(ENOSYS); @@ -3560,29 +3215,6 @@ static int vulkan_map_from(AVHWFramesContext *hwfc, AVFrame *dst, return AVERROR(ENOSYS); } -typedef struct ImageBuffer { - VkBuffer buf; - VkDeviceMemory mem; - VkMemoryPropertyFlagBits flags; - int mapped_mem; -} ImageBuffer; - -static void free_buf(void *opaque, uint8_t *data) -{ - AVHWDeviceContext *ctx = opaque; - AVVulkanDeviceContext *hwctx = ctx->hwctx; - VulkanDevicePriv *p = ctx->internal->priv; - FFVulkanFunctions *vk = &p->vkfn; - ImageBuffer *vkbuf = (ImageBuffer *)data; - - if (vkbuf->buf) - vk->DestroyBuffer(hwctx->act_dev, vkbuf->buf, hwctx->alloc); - if (vkbuf->mem) - vk->FreeMemory(hwctx->act_dev, vkbuf->mem, hwctx->alloc); - - av_free(data); -} - static size_t get_req_buffer_size(VulkanDevicePriv *p, int *stride, int height) { size_t size; @@ -3592,202 +3224,6 @@ static size_t get_req_buffer_size(VulkanDevicePriv *p, int *stride, int height) return size; } -static int create_buf(AVHWDeviceContext *ctx, AVBufferRef **buf, - VkBufferUsageFlags usage, VkMemoryPropertyFlagBits flags, - size_t size, uint32_t req_memory_bits, int host_mapped, - void *create_pnext, void *alloc_pnext) -{ - int err; - VkResult ret; - int use_ded_mem; - AVVulkanDeviceContext *hwctx = ctx->hwctx; - VulkanDevicePriv *p = ctx->internal->priv; - FFVulkanFunctions *vk = &p->vkfn; - - VkBufferCreateInfo buf_spawn = { - .sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, - .pNext = create_pnext, - .usage = usage, - .size = size, - .sharingMode = VK_SHARING_MODE_EXCLUSIVE, - }; - - VkBufferMemoryRequirementsInfo2 req_desc = { - .sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_REQUIREMENTS_INFO_2, - }; - VkMemoryDedicatedAllocateInfo ded_alloc = { - .sType = VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO, - .pNext = alloc_pnext, - }; - VkMemoryDedicatedRequirements ded_req = { - .sType = VK_STRUCTURE_TYPE_MEMORY_DEDICATED_REQUIREMENTS, - }; - VkMemoryRequirements2 req = { - .sType = VK_STRUCTURE_TYPE_MEMORY_REQUIREMENTS_2, - .pNext = &ded_req, - }; - - ImageBuffer *vkbuf = av_mallocz(sizeof(*vkbuf)); - if (!vkbuf) - return AVERROR(ENOMEM); - - vkbuf->mapped_mem = host_mapped; - - ret = vk->CreateBuffer(hwctx->act_dev, &buf_spawn, NULL, &vkbuf->buf); - if (ret != VK_SUCCESS) { - av_log(ctx, AV_LOG_ERROR, "Failed to create buffer: %s\n", - vk_ret2str(ret)); - err = AVERROR_EXTERNAL; - goto fail; - } - - req_desc.buffer = vkbuf->buf; - - vk->GetBufferMemoryRequirements2(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 = vkbuf->buf; - - /* Additional requirements imposed on us */ - if (req_memory_bits) - req.memoryRequirements.memoryTypeBits &= req_memory_bits; - - err = alloc_mem(ctx, &req.memoryRequirements, flags, - use_ded_mem ? &ded_alloc : (void *)ded_alloc.pNext, - &vkbuf->flags, &vkbuf->mem); - if (err) - goto fail; - - ret = vk->BindBufferMemory(hwctx->act_dev, vkbuf->buf, vkbuf->mem, 0); - if (ret != VK_SUCCESS) { - av_log(ctx, AV_LOG_ERROR, "Failed to bind memory to buffer: %s\n", - vk_ret2str(ret)); - err = AVERROR_EXTERNAL; - goto fail; - } - - *buf = av_buffer_create((uint8_t *)vkbuf, sizeof(*vkbuf), free_buf, ctx, 0); - if (!(*buf)) { - err = AVERROR(ENOMEM); - goto fail; - } - - return 0; - -fail: - free_buf(ctx, (uint8_t *)vkbuf); - return err; -} - -/* Skips mapping of host mapped buffers but still invalidates them */ -static int map_buffers(AVHWDeviceContext *ctx, AVBufferRef **bufs, uint8_t *mem[], - int nb_buffers, int invalidate) -{ - VkResult ret; - AVVulkanDeviceContext *hwctx = ctx->hwctx; - VulkanDevicePriv *p = ctx->internal->priv; - FFVulkanFunctions *vk = &p->vkfn; - VkMappedMemoryRange invalidate_ctx[AV_NUM_DATA_POINTERS]; - int invalidate_count = 0; - - for (int i = 0; i < nb_buffers; i++) { - ImageBuffer *vkbuf = (ImageBuffer *)bufs[i]->data; - if (vkbuf->mapped_mem) - continue; - - ret = vk->MapMemory(hwctx->act_dev, vkbuf->mem, 0, - VK_WHOLE_SIZE, 0, (void **)&mem[i]); - if (ret != VK_SUCCESS) { - av_log(ctx, AV_LOG_ERROR, "Failed to map buffer memory: %s\n", - vk_ret2str(ret)); - return AVERROR_EXTERNAL; - } - } - - if (!invalidate) - return 0; - - for (int i = 0; i < nb_buffers; i++) { - ImageBuffer *vkbuf = (ImageBuffer *)bufs[i]->data; - const VkMappedMemoryRange ival_buf = { - .sType = VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE, - .memory = vkbuf->mem, - .size = VK_WHOLE_SIZE, - }; - - /* For host imported memory Vulkan says to use platform-defined - * sync methods, but doesn't really say not to call flush or invalidate - * on original host pointers. It does explicitly allow to do that on - * host-mapped pointers which are then mapped again using vkMapMemory, - * but known implementations return the original pointers when mapped - * again. */ - if (vkbuf->flags & VK_MEMORY_PROPERTY_HOST_COHERENT_BIT) - continue; - - invalidate_ctx[invalidate_count++] = ival_buf; - } - - if (invalidate_count) { - ret = vk->InvalidateMappedMemoryRanges(hwctx->act_dev, invalidate_count, - invalidate_ctx); - if (ret != VK_SUCCESS) - av_log(ctx, AV_LOG_WARNING, "Failed to invalidate memory: %s\n", - vk_ret2str(ret)); - } - - return 0; -} - -static int unmap_buffers(AVHWDeviceContext *ctx, AVBufferRef **bufs, - int nb_buffers, int flush) -{ - int err = 0; - VkResult ret; - AVVulkanDeviceContext *hwctx = ctx->hwctx; - VulkanDevicePriv *p = ctx->internal->priv; - FFVulkanFunctions *vk = &p->vkfn; - VkMappedMemoryRange flush_ctx[AV_NUM_DATA_POINTERS]; - int flush_count = 0; - - if (flush) { - for (int i = 0; i < nb_buffers; i++) { - ImageBuffer *vkbuf = (ImageBuffer *)bufs[i]->data; - const VkMappedMemoryRange flush_buf = { - .sType = VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE, - .memory = vkbuf->mem, - .size = VK_WHOLE_SIZE, - }; - - if (vkbuf->flags & VK_MEMORY_PROPERTY_HOST_COHERENT_BIT) - continue; - - flush_ctx[flush_count++] = flush_buf; - } - } - - if (flush_count) { - ret = vk->FlushMappedMemoryRanges(hwctx->act_dev, flush_count, flush_ctx); - if (ret != VK_SUCCESS) { - av_log(ctx, AV_LOG_ERROR, "Failed to flush memory: %s\n", - vk_ret2str(ret)); - err = AVERROR_EXTERNAL; /* We still want to try to unmap them */ - } - } - - for (int i = 0; i < nb_buffers; i++) { - ImageBuffer *vkbuf = (ImageBuffer *)bufs[i]->data; - if (vkbuf->mapped_mem) - continue; - - vk->UnmapMemory(hwctx->act_dev, vkbuf->mem); - } - - return err; -} - static int transfer_image_buf(AVHWFramesContext *hwfc, AVFrame *f, AVBufferRef **bufs, size_t *buf_offsets, const int *buf_stride, int w, @@ -3795,86 +3231,46 @@ static int transfer_image_buf(AVHWFramesContext *hwfc, AVFrame *f, { int err; AVVkFrame *frame = (AVVkFrame *)f->data[0]; - AVVulkanFramesContext *vkfc = hwfc->hwctx; VulkanFramesPriv *fp = hwfc->internal->priv; VulkanDevicePriv *p = hwfc->device_ctx->internal->priv; - FFVulkanFunctions *vk = &p->vkfn; - - int bar_num = 0; - VkPipelineStageFlagBits sem_wait_dst[AV_NUM_DATA_POINTERS]; + FFVulkanFunctions *vk = &p->vkctx.vkfn; + VkImageMemoryBarrier2 img_bar[AV_NUM_DATA_POINTERS]; + int nb_img_bar = 0; const int nb_images = ff_vk_count_images(frame); int pixfmt_planes = av_pix_fmt_count_planes(pix_fmt); - const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(pix_fmt); - VkImageMemoryBarrier img_bar[AV_NUM_DATA_POINTERS] = { 0 }; - 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]; + VkCommandBuffer cmd_buf; + FFVkExecContext *exec = ff_vk_exec_get(to_buf ? &fp->download_exec : + &fp->upload_exec); + cmd_buf = exec->buf; + ff_vk_exec_start(&p->vkctx, exec); - VkTimelineSemaphoreSubmitInfo s_timeline_sem_info = { - .sType = VK_STRUCTURE_TYPE_TIMELINE_SEMAPHORE_SUBMIT_INFO, - .pWaitSemaphoreValues = frame->sem_value, - .pSignalSemaphoreValues = sem_signal_values, - .waitSemaphoreValueCount = nb_images, - .signalSemaphoreValueCount = nb_images, - }; - - VkSubmitInfo s_info = { - .sType = VK_STRUCTURE_TYPE_SUBMIT_INFO, - .pNext = &s_timeline_sem_info, - .pSignalSemaphores = frame->sem, - .pWaitSemaphores = frame->sem, - .pWaitDstStageMask = sem_wait_dst, - .signalSemaphoreCount = nb_images, - .waitSemaphoreCount = nb_images, - }; - - vkfc->lock_frame(hwfc, frame); - - if ((err = wait_start_exec_ctx(hwfc, ectx))) - goto end; - - for (int i = 0; i < nb_images; i++) - sem_signal_values[i] = frame->sem_value[i] + 1; - - /* Change the image layout to something more optimal for transfers */ - for (int i = 0; i < nb_images; i++) { - VkImageLayout new_layout = to_buf ? VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL : - VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL; - VkAccessFlags new_access = to_buf ? VK_ACCESS_TRANSFER_READ_BIT : - VK_ACCESS_TRANSFER_WRITE_BIT; - - sem_wait_dst[i] = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT; + err = ff_vk_exec_add_dep_buf(&p->vkctx, exec, bufs, pixfmt_planes, 1); + if (err < 0) + return err; - /* If the layout matches and we have read access skip the barrier */ - if ((frame->layout[i] == new_layout) && (frame->access[i] & new_access)) - continue; + err = ff_vk_exec_add_dep_frame(&p->vkctx, exec, f, + VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT, + VK_PIPELINE_STAGE_2_TRANSFER_BIT); + if (err < 0) + return err; - img_bar[bar_num].sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER; - img_bar[bar_num].srcAccessMask = 0x0; - img_bar[bar_num].dstAccessMask = new_access; - img_bar[bar_num].oldLayout = frame->layout[i]; - img_bar[bar_num].newLayout = new_layout; - img_bar[bar_num].srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; - img_bar[bar_num].dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; - img_bar[bar_num].image = frame->img[i]; - img_bar[bar_num].subresourceRange.levelCount = 1; - img_bar[bar_num].subresourceRange.layerCount = 1; - img_bar[bar_num].subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - - frame->layout[i] = img_bar[bar_num].newLayout; - frame->access[i] = img_bar[bar_num].dstAccessMask; - - bar_num++; - } + ff_vk_frame_barrier(&p->vkctx, exec, f, img_bar, &nb_img_bar, + VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT, + VK_PIPELINE_STAGE_2_TRANSFER_BIT_KHR, + to_buf ? VK_ACCESS_TRANSFER_READ_BIT : + VK_ACCESS_TRANSFER_WRITE_BIT, + to_buf ? VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL : + VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, + VK_QUEUE_FAMILY_IGNORED); - if (bar_num) - vk->CmdPipelineBarrier(cmd_buf, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, - VK_PIPELINE_STAGE_TRANSFER_BIT, 0, - 0, NULL, 0, NULL, bar_num, img_bar); + vk->CmdPipelineBarrier2(cmd_buf, &(VkDependencyInfo) { + .sType = VK_STRUCTURE_TYPE_DEPENDENCY_INFO, + .pImageMemoryBarriers = img_bar, + .imageMemoryBarrierCount = nb_img_bar, + }); /* Schedule a copy for each plane */ for (int i = 0; i < pixfmt_planes; i++) { @@ -3884,7 +3280,7 @@ static int transfer_image_buf(AVHWFramesContext *hwfc, AVFrame *f, VK_IMAGE_ASPECT_PLANE_1_BIT, VK_IMAGE_ASPECT_PLANE_2_BIT, }; - ImageBuffer *vkbuf = (ImageBuffer *)bufs[i]->data; + FFVkBuffer *vkbuf = (FFVkBuffer *)bufs[i]->data; VkBufferImageCopy buf_reg = { .bufferOffset = buf_offsets[i], .bufferRowLength = buf_stride[i] / desc->comp[i].step, @@ -3894,44 +3290,32 @@ static int transfer_image_buf(AVHWFramesContext *hwfc, AVFrame *f, .imageOffset = { 0, 0, 0, }, }; - int p_w, p_h; + uint32_t p_w, p_h; get_plane_wh(&p_w, &p_h, pix_fmt, w, h, i); buf_reg.bufferImageHeight = p_h; buf_reg.imageExtent = (VkExtent3D){ p_w, p_h, 1, }; if (to_buf) - vk->CmdCopyImageToBuffer(cmd_buf, frame->img[idx], frame->layout[idx], - vkbuf->buf, 1, &buf_reg); + vk->CmdCopyImageToBuffer(cmd_buf, frame->img[idx], + img_bar[0].newLayout, + vkbuf->buf, + 1, &buf_reg); else vk->CmdCopyBufferToImage(cmd_buf, vkbuf->buf, frame->img[idx], - frame->layout[idx], 1, &buf_reg); + img_bar[0].newLayout, + 1, &buf_reg); } - /* When uploading, do this asynchronously if the source is refcounted by - * keeping the buffers as a submission dependency. - * The hwcontext is guaranteed to not be freed until all frames are freed - * in the frames_unint function. - * When downloading to buffer, do this synchronously and wait for the - * queue submission to finish executing */ - if (!to_buf) { - int ref; - for (ref = 0; ref < AV_NUM_DATA_POINTERS; ref++) { - if (!f->buf[ref]) - break; - if ((err = add_buf_dep_exec_ctx(hwfc, ectx, &f->buf[ref], 1))) - goto end; - } - if (ref && (err = add_buf_dep_exec_ctx(hwfc, ectx, bufs, pixfmt_planes))) - goto end; - err = submit_exec_ctx(hwfc, ectx, &s_info, frame, !ref); - } else { - err = submit_exec_ctx(hwfc, ectx, &s_info, frame, 1); - } + err = ff_vk_exec_submit(&p->vkctx, exec); + if (err < 0) + return err; -end: - vkfc->unlock_frame(hwfc, frame); - return err; + /* Wait for the operation to complete when downloading */ + if (to_buf) + ff_vk_exec_wait(&p->vkctx, exec); + + return 0; } static int vulkan_transfer_data(AVHWFramesContext *hwfc, const AVFrame *vkf, @@ -3939,22 +3323,21 @@ static int vulkan_transfer_data(AVHWFramesContext *hwfc, const AVFrame *vkf, { int err = 0; VkResult ret; - AVVkFrame *f = (AVVkFrame *)vkf->data[0]; AVHWDeviceContext *dev_ctx = hwfc->device_ctx; AVVulkanDeviceContext *hwctx = dev_ctx->hwctx; - AVVulkanFramesContext *fc = hwfc->hwctx; VulkanDevicePriv *p = hwfc->device_ctx->internal->priv; - FFVulkanFunctions *vk = &p->vkfn; + FFVulkanFunctions *vk = &p->vkctx.vkfn; AVFrame tmp; + FFVkBuffer *vkbufs[AV_NUM_DATA_POINTERS]; AVBufferRef *bufs[AV_NUM_DATA_POINTERS] = { 0 }; size_t buf_offsets[AV_NUM_DATA_POINTERS] = { 0 }; - int p_w, p_h; + uint32_t p_w, p_h; const int planes = av_pix_fmt_count_planes(swf->format); int host_mapped[AV_NUM_DATA_POINTERS] = { 0 }; - const int map_host = !!(p->extensions & FF_VK_EXT_EXTERNAL_HOST_MEMORY); + const int map_host = !!(p->vkctx.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"); @@ -4001,8 +3384,7 @@ static int vulkan_transfer_data(AVHWFramesContext *hwfc, const AVFrame *vkf, import_desc.handleType, import_desc.pHostPointer, &p_props); - - if (ret == VK_SUCCESS) { + if (ret == VK_SUCCESS && p_props.memoryTypeBits) { host_mapped[i] = 1; buf_offsets[i] = offs; } @@ -4011,20 +3393,23 @@ static int vulkan_transfer_data(AVHWFramesContext *hwfc, const AVFrame *vkf, if (!host_mapped[i]) req_size = get_req_buffer_size(p, &tmp.linesize[i], p_h); - err = create_buf(dev_ctx, &bufs[i], - from ? VK_BUFFER_USAGE_TRANSFER_DST_BIT : - VK_BUFFER_USAGE_TRANSFER_SRC_BIT, - VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT, - req_size, p_props.memoryTypeBits, host_mapped[i], - host_mapped[i] ? &create_desc : NULL, - host_mapped[i] ? &import_desc : NULL); - if (err) + err = ff_vk_create_avbuf(&p->vkctx, &bufs[i], req_size, + host_mapped[i] ? &create_desc : NULL, + host_mapped[i] ? &import_desc : NULL, + from ? VK_BUFFER_USAGE_TRANSFER_DST_BIT : + VK_BUFFER_USAGE_TRANSFER_SRC_BIT, + VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | + (host_mapped[i] ? + VK_MEMORY_PROPERTY_HOST_COHERENT_BIT : 0x0)); + if (err < 0) goto end; + + vkbufs[i] = (FFVkBuffer *)bufs[i]->data; } if (!from) { /* Map, copy image TO buffer (which then goes to the VkImage), unmap */ - if ((err = map_buffers(dev_ctx, bufs, tmp.data, planes, 0))) + if ((err = ff_vk_map_buffers(&p->vkctx, vkbufs, tmp.data, planes, 0))) goto end; for (int i = 0; i < planes; i++) { @@ -4039,7 +3424,7 @@ static int vulkan_transfer_data(AVHWFramesContext *hwfc, const AVFrame *vkf, p_h); } - if ((err = unmap_buffers(dev_ctx, bufs, planes, 1))) + if ((err = ff_vk_unmap_buffers(&p->vkctx, vkbufs, planes, 1))) goto end; } @@ -4050,7 +3435,7 @@ static int vulkan_transfer_data(AVHWFramesContext *hwfc, const AVFrame *vkf, if (from) { /* Map, copy buffer (which came FROM the VkImage) to the frame, unmap */ - if ((err = map_buffers(dev_ctx, bufs, tmp.data, planes, 0))) + if ((err = ff_vk_map_buffers(&p->vkctx, vkbufs, tmp.data, planes, 0))) goto end; for (int i = 0; i < planes; i++) { @@ -4065,7 +3450,7 @@ static int vulkan_transfer_data(AVHWFramesContext *hwfc, const AVFrame *vkf, p_h); } - if ((err = unmap_buffers(dev_ctx, bufs, planes, 1))) + if ((err = ff_vk_unmap_buffers(&p->vkctx, vkbufs, planes, 1))) goto end; } @@ -4085,11 +3470,11 @@ static int vulkan_transfer_data_to(AVHWFramesContext *hwfc, AVFrame *dst, #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)) + if ((p->vkctx.extensions & FF_VK_EXT_EXTERNAL_WIN32_MEMORY) && + (p->vkctx.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)) + if ((p->vkctx.extensions & FF_VK_EXT_EXTERNAL_FD_MEMORY) && + (p->vkctx.extensions & FF_VK_EXT_EXTERNAL_FD_SEM)) #endif return vulkan_transfer_data_from_cuda(hwfc, dst, src); #endif @@ -4123,7 +3508,7 @@ static int vulkan_transfer_data_to_cuda(AVHWFramesContext *hwfc, AVFrame *dst, dst_f = (AVVkFrame *)src->data[0]; - err = prepare_frame(hwfc, &fp->upload_ctx, dst_f, PREP_MODE_EXTERNAL_EXPORT); + err = prepare_frame(hwfc, &fp->upload_exec, dst_f, PREP_MODE_EXTERNAL_EXPORT); if (err < 0) return err; @@ -4183,7 +3568,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 prepare_frame(hwfc, &fp->upload_ctx, dst_f, PREP_MODE_EXTERNAL_IMPORT); + return prepare_frame(hwfc, &fp->upload_exec, dst_f, PREP_MODE_EXTERNAL_IMPORT); fail: CHECK_CU(cu->cuCtxPopCurrent(&dummy)); @@ -4203,11 +3588,11 @@ static int vulkan_transfer_data_from(AVHWFramesContext *hwfc, AVFrame *dst, #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)) + if ((p->vkctx.extensions & FF_VK_EXT_EXTERNAL_WIN32_MEMORY) && + (p->vkctx.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)) + if ((p->vkctx.extensions & FF_VK_EXT_EXTERNAL_FD_MEMORY) && + (p->vkctx.extensions & FF_VK_EXT_EXTERNAL_FD_SEM)) #endif return vulkan_transfer_data_to_cuda(hwfc, dst, src); #endif diff --git a/libavutil/vulkan.h b/libavutil/vulkan.h index 0831219d8fd..ec03ba8b717 100644 --- a/libavutil/vulkan.h +++ b/libavutil/vulkan.h @@ -267,6 +267,19 @@ static inline int ff_vk_count_images(AVVkFrame *f) return cnt; } +static inline const void *ff_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; +} + /* Identity mapping - r = r, b = b, g = g, a = a */ extern const VkComponentMapping ff_comp_identity_map; From 51b7fe81be5892b0c2590443b3ff2d684878a83c Mon Sep 17 00:00:00 2001 From: Lynne Date: Tue, 14 Mar 2023 21:38:55 +0100 Subject: [PATCH 1275/2172] hwcontext_vulkan: enable additional device properties --- libavutil/hwcontext_vulkan.c | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/libavutil/hwcontext_vulkan.c b/libavutil/hwcontext_vulkan.c index ff2cde2dd65..93b6c6de4b5 100644 --- a/libavutil/hwcontext_vulkan.c +++ b/libavutil/hwcontext_vulkan.c @@ -1248,6 +1248,8 @@ static int vulkan_device_create_internal(AVHWDeviceContext *ctx, COPY_FEATURE(hwctx->device_features, fragmentStoresAndAtomics) COPY_FEATURE(hwctx->device_features, vertexPipelineStoresAndAtomics) COPY_FEATURE(hwctx->device_features, shaderInt64) + COPY_FEATURE(hwctx->device_features, shaderInt16) + COPY_FEATURE(hwctx->device_features, shaderFloat64) #undef COPY_FEATURE /* We require timeline semaphores */ @@ -1256,10 +1258,27 @@ static int vulkan_device_create_internal(AVHWDeviceContext *ctx, err = AVERROR(ENOSYS); goto end; } + + p->device_features_1_1.samplerYcbcrConversion = dev_features_1_1.samplerYcbcrConversion; + p->device_features_1_1.storagePushConstant16 = dev_features_1_1.storagePushConstant16; + p->device_features_1_2.timelineSemaphore = 1; p->device_features_1_2.bufferDeviceAddress = dev_features_1_2.bufferDeviceAddress; - p->device_features_1_1.samplerYcbcrConversion = dev_features_1_1.samplerYcbcrConversion; + p->device_features_1_2.storagePushConstant8 = dev_features_1_2.storagePushConstant8; + p->device_features_1_2.shaderInt8 = dev_features_1_2.shaderInt8; + p->device_features_1_2.storageBuffer8BitAccess = dev_features_1_2.storageBuffer8BitAccess; + p->device_features_1_2.uniformAndStorageBuffer8BitAccess = dev_features_1_2.uniformAndStorageBuffer8BitAccess; + p->device_features_1_2.shaderFloat16 = dev_features_1_2.shaderFloat16; + p->device_features_1_2.shaderSharedInt64Atomics = dev_features_1_2.shaderSharedInt64Atomics; + p->device_features_1_2.vulkanMemoryModel = dev_features_1_2.vulkanMemoryModel; + p->device_features_1_2.vulkanMemoryModelDeviceScope = dev_features_1_2.vulkanMemoryModelDeviceScope; + p->device_features_1_2.hostQueryReset = dev_features_1_2.hostQueryReset; + p->device_features_1_3.synchronization2 = dev_features_1_3.synchronization2; + p->device_features_1_3.computeFullSubgroups = dev_features_1_3.computeFullSubgroups; + p->device_features_1_3.shaderZeroInitializeWorkgroupMemory = dev_features_1_3.shaderZeroInitializeWorkgroupMemory; + p->device_features_1_3.dynamicRendering = dev_features_1_3.dynamicRendering; + p->desc_buf_features.descriptorBuffer = desc_buf_features.descriptorBuffer; p->desc_buf_features.descriptorBufferPushDescriptors = desc_buf_features.descriptorBufferPushDescriptors; From 05ce6473acb34c2b79311e314dd15867863b56b8 Mon Sep 17 00:00:00 2001 From: Lynne Date: Fri, 17 Feb 2023 03:10:58 +0100 Subject: [PATCH 1276/2172] lavfi: add lavfi-only Vulkan infrastructure --- libavfilter/Makefile | 6 + libavfilter/vulkan_filter.c | 480 +++++++++++++++----- libavfilter/vulkan_filter.h | 39 +- {libavutil => libavfilter}/vulkan_glslang.c | 19 +- {libavutil => libavfilter}/vulkan_shaderc.c | 8 +- libavfilter/vulkan_spirv.h | 45 ++ 6 files changed, 473 insertions(+), 124 deletions(-) rename {libavutil => libavfilter}/vulkan_glslang.c (95%) rename {libavutil => libavfilter}/vulkan_shaderc.c (96%) create mode 100644 libavfilter/vulkan_spirv.h diff --git a/libavfilter/Makefile b/libavfilter/Makefile index 19283a71de1..c4b52d02575 100644 --- a/libavfilter/Makefile +++ b/libavfilter/Makefile @@ -623,6 +623,10 @@ OBJS-$(CONFIG_AVSYNCTEST_FILTER) += src_avsynctest.o OBJS-$(CONFIG_AMOVIE_FILTER) += src_movie.o OBJS-$(CONFIG_MOVIE_FILTER) += src_movie.o +# vulkan libs +OBJS-$(CONFIG_LIBGLSLANG) += vulkan_glslang.o +OBJS-$(CONFIG_LIBSHADERC) += vulkan_shaderc.o + # Objects duplicated from other libraries for shared builds SHLIBOBJS += log2_tab.o @@ -636,6 +640,8 @@ SKIPHEADERS-$(CONFIG_QSVVPP) += qsvvpp.h stack_internal.h SKIPHEADERS-$(CONFIG_OPENCL) += opencl.h SKIPHEADERS-$(CONFIG_VAAPI) += vaapi_vpp.h stack_internal.h SKIPHEADERS-$(CONFIG_VULKAN) += vulkan.h vulkan_filter.h +SKIPHEADERS-$(CONFIG_LIBSHADERC) += vulkan_spirv.h +SKIPHEADERS-$(CONFIG_LIBGLSLANG) += vulkan_spirv.h TOOLS = graph2dot TESTPROGS = drawutils filtfmts formats integral diff --git a/libavfilter/vulkan_filter.c b/libavfilter/vulkan_filter.c index e22541bd23a..b4d8f952b53 100644 --- a/libavfilter/vulkan_filter.c +++ b/libavfilter/vulkan_filter.c @@ -1,4 +1,6 @@ /* + * Copyright (c) Lynne + * * This file is part of FFmpeg. * * FFmpeg is free software; you can redistribute it and/or @@ -18,107 +20,186 @@ #include "vulkan_filter.h" -static int vulkan_filter_set_device(AVFilterContext *avctx, - AVBufferRef *device) +int ff_vk_filter_init_context(AVFilterContext *avctx, FFVulkanContext *s, + AVBufferRef *frames_ref, + int width, int height, enum AVPixelFormat sw_format) { - FFVulkanContext *s = avctx->priv; + int err; + AVHWFramesContext *frames_ctx; + AVHWDeviceContext *device_ctx; + AVVulkanFramesContext *vk_frames; + AVVulkanDeviceContext *vk_dev; + AVBufferRef *device_ref = avctx->hw_device_ctx; + + /* Check if context is reusable as-is */ + if (frames_ref) { + int no_storage = 0; + FFVulkanFunctions *vk; + const VkFormat *sub = av_vkfmt_from_pixfmt(sw_format); + + frames_ctx = (AVHWFramesContext *)frames_ref->data; + device_ctx = (AVHWDeviceContext *)frames_ctx->device_ref->data; + vk_frames = frames_ctx->hwctx; + vk_dev = device_ctx->hwctx; + + /* Basic format validation */ + if (width != frames_ctx->width || + height != frames_ctx->height || + sw_format != frames_ctx->sw_format || + (vk_frames->tiling != VK_IMAGE_TILING_LINEAR && + vk_frames->tiling != VK_IMAGE_TILING_OPTIMAL) || + !(vk_frames->usage & VK_IMAGE_USAGE_SAMPLED_BIT)) { + goto skip; + } - av_buffer_unref(&s->device_ref); + if (vk_frames->usage & VK_IMAGE_USAGE_STORAGE_BIT) + goto accept; - s->device_ref = av_buffer_ref(device); - if (!s->device_ref) - return AVERROR(ENOMEM); + s->extensions = ff_vk_extensions_to_mask(vk_dev->enabled_dev_extensions, + vk_dev->nb_enabled_dev_extensions); + err = ff_vk_load_functions(device_ctx, &s->vkfn, s->extensions, 1, 1); + if (err < 0) + return err; + vk = &s->vkfn; + + /* Check if the subformats can do storage */ + for (int i = 0; sub[i] != VK_FORMAT_UNDEFINED; i++) { + VkFormatProperties2 prop = { + .sType = VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2, + }; + vk->GetPhysicalDeviceFormatProperties2(vk_dev->phys_dev, sub[i], + &prop); + + if (vk_frames->tiling == VK_IMAGE_TILING_LINEAR) { + no_storage |= !(prop.formatProperties.linearTilingFeatures & + VK_FORMAT_FEATURE_2_STORAGE_IMAGE_BIT); + } else { + no_storage |= !(prop.formatProperties.optimalTilingFeatures & + VK_FORMAT_FEATURE_2_STORAGE_IMAGE_BIT); + } + } - s->device = (AVHWDeviceContext*)s->device_ref->data; - s->hwctx = s->device->hwctx; + /* Check if it's usable */ + if (no_storage) { +skip: + device_ref = frames_ctx->device_ref; + frames_ref = NULL; + } else { +accept: + frames_ref = av_buffer_ref(frames_ref); + if (!frames_ref) + return AVERROR(ENOMEM); + } + } - return 0; -} + if (!frames_ref) { + if (!device_ref) { + av_log(avctx, AV_LOG_ERROR, + "Vulkan filtering requires a device context!\n"); + return AVERROR(EINVAL); + } -static int vulkan_filter_set_frames(AVFilterContext *avctx, - AVBufferRef *frames) -{ - FFVulkanContext *s = avctx->priv; + frames_ref = av_hwframe_ctx_alloc(device_ref); - av_buffer_unref(&s->frames_ref); + frames_ctx = (AVHWFramesContext *)frames_ref->data; + frames_ctx->format = AV_PIX_FMT_VULKAN; + frames_ctx->sw_format = sw_format; + frames_ctx->width = width; + frames_ctx->height = height; - s->frames_ref = av_buffer_ref(frames); - if (!s->frames_ref) - return AVERROR(ENOMEM); + vk_frames = frames_ctx->hwctx; + vk_frames->tiling = VK_IMAGE_TILING_OPTIMAL; + vk_frames->usage = VK_IMAGE_USAGE_SAMPLED_BIT | + VK_IMAGE_USAGE_TRANSFER_SRC_BIT | + VK_IMAGE_USAGE_TRANSFER_DST_BIT; - return 0; + err = av_hwframe_ctx_init(frames_ref); + if (err < 0) { + av_buffer_unref(&frames_ref); + return err; + } + + device_ctx = (AVHWDeviceContext *)frames_ctx->device_ref->data; + vk_dev = device_ctx->hwctx; + } + + s->extensions = ff_vk_extensions_to_mask(vk_dev->enabled_dev_extensions, + vk_dev->nb_enabled_dev_extensions); + + /** + * libplacebo does not use descriptor buffers. + */ + if (!(s->extensions & FF_VK_EXT_DESCRIPTOR_BUFFER) && + strcmp(avctx->filter->name, "libplacebo")) { + av_log(avctx, AV_LOG_ERROR, "Vulkan filtering requires that " + "the %s extension is supported!\n", + VK_EXT_DESCRIPTOR_BUFFER_EXTENSION_NAME); + av_buffer_unref(&frames_ref); + return AVERROR(EINVAL); + } + + err = ff_vk_load_functions(device_ctx, &s->vkfn, s->extensions, 1, 1); + if (err < 0) { + av_buffer_unref(&frames_ref); + return err; + } + + s->frames_ref = frames_ref; + s->frames = frames_ctx; + s->hwfc = vk_frames; + s->device = device_ctx; + s->hwctx = device_ctx->hwctx; + + err = ff_vk_load_props(s); + if (err < 0) + av_buffer_unref(&s->frames_ref); + + return err; } 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; + AVFilterContext *avctx = inlink->dst; + FFVulkanContext *s = inlink->dst->priv; if (!inlink->hw_frames_ctx) { - av_log(avctx, AV_LOG_ERROR, "Vulkan filtering requires a " + av_log(inlink->dst, 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; + /* Extract the device and default output format from the first input. */ + if (avctx->inputs[0] != inlink) + return 0; - vk->GetPhysicalDeviceProperties(s->hwctx->phys_dev, &s->props); - vk->GetPhysicalDeviceMemoryProperties(s->hwctx->phys_dev, &s->mprops); + /* Save the ref, without reffing it */ + s->input_frames_ref = inlink->hw_frames_ctx; - /* 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; + /* Defaults */ + s->output_format = input_frames->sw_format; + s->output_width = inlink->w; + s->output_height = inlink->h; return 0; } -int ff_vk_filter_config_output_inplace(AVFilterLink *outlink) +int ff_vk_filter_config_output(AVFilterLink *outlink) { int err; - AVFilterContext *avctx = outlink->src; - FFVulkanContext *s = avctx->priv; + FFVulkanContext *s = outlink->src->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; - } + err = ff_vk_filter_init_context(outlink->src, s, s->input_frames_ref, + s->output_width, s->output_height, + s->output_format); + if (err < 0) + return err; outlink->hw_frames_ctx = av_buffer_ref(s->frames_ref); if (!outlink->hw_frames_ctx) @@ -127,65 +208,246 @@ int ff_vk_filter_config_output_inplace(AVFilterLink *outlink) outlink->w = s->output_width; outlink->h = s->output_height; - return 0; + return err; } -int ff_vk_filter_config_output(AVFilterLink *outlink) +int ff_vk_filter_init(AVFilterContext *avctx) { - 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); - } + s->output_format = AV_PIX_FMT_NONE; - err = vulkan_filter_set_device(avctx, avctx->hw_device_ctx); - if (err < 0) - return err; - } + return 0; +} - output_frames_ref = av_hwframe_ctx_alloc(s->device_ref); - if (!output_frames_ref) { - err = AVERROR(ENOMEM); - goto fail; +int ff_vk_filter_process_simple(FFVulkanContext *vkctx, FFVkExecPool *e, + FFVulkanPipeline *pl, AVFrame *out_f, AVFrame *in_f, + VkSampler sampler, void *push_src, size_t push_size) +{ + int err = 0; + FFVulkanFunctions *vk = &vkctx->vkfn; + VkImageView in_views[AV_NUM_DATA_POINTERS]; + VkImageView out_views[AV_NUM_DATA_POINTERS]; + VkImageMemoryBarrier2 img_bar[37]; + int nb_img_bar = 0; + + /* Update descriptors and init the exec context */ + FFVkExecContext *exec = ff_vk_exec_get(e); + ff_vk_exec_start(vkctx, exec); + + ff_vk_exec_bind_pipeline(vkctx, exec, pl); + + if (push_src) + ff_vk_update_push_exec(vkctx, exec, pl, VK_SHADER_STAGE_COMPUTE_BIT, + 0, push_size, push_src); + + if (in_f) { + RET(ff_vk_exec_add_dep_frame(vkctx, exec, in_f, + VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT, + VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT)); + RET(ff_vk_create_imageviews(vkctx, exec, in_views, in_f)); + ff_vk_update_descriptor_img_array(vkctx, pl, exec, in_f, in_views, 0, 0, + VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, + sampler); + ff_vk_frame_barrier(vkctx, exec, in_f, img_bar, &nb_img_bar, + VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT, + VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT, + VK_ACCESS_SHADER_READ_BIT, + VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, + VK_QUEUE_FAMILY_IGNORED); } - 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; + RET(ff_vk_exec_add_dep_frame(vkctx, exec, out_f, + VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT, + VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT)); + RET(ff_vk_create_imageviews(vkctx, exec, out_views, out_f)); + ff_vk_update_descriptor_img_array(vkctx, pl, exec, out_f, out_views, 0, !!in_f, + VK_IMAGE_LAYOUT_GENERAL, + VK_NULL_HANDLE); + ff_vk_frame_barrier(vkctx, exec, out_f, img_bar, &nb_img_bar, + VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT, + VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT, + VK_ACCESS_SHADER_WRITE_BIT, + VK_IMAGE_LAYOUT_GENERAL, + VK_QUEUE_FAMILY_IGNORED); + + vk->CmdPipelineBarrier2(exec->buf, &(VkDependencyInfo) { + .sType = VK_STRUCTURE_TYPE_DEPENDENCY_INFO, + .pImageMemoryBarriers = img_bar, + .imageMemoryBarrierCount = nb_img_bar, + }); + + vk->CmdDispatch(exec->buf, + FFALIGN(vkctx->output_width, pl->wg_size[0])/pl->wg_size[0], + FFALIGN(vkctx->output_height, pl->wg_size[1])/pl->wg_size[1], + pl->wg_size[2]); + + return ff_vk_exec_submit(vkctx, exec); +fail: + ff_vk_exec_discard_deps(vkctx, exec); + return err; +} - 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; +int ff_vk_filter_process_2pass(FFVulkanContext *vkctx, FFVkExecPool *e, + FFVulkanPipeline *pls[2], + AVFrame *out, AVFrame *tmp, AVFrame *in, + VkSampler sampler, void *push_src, size_t push_size) +{ + int err = 0; + FFVulkanFunctions *vk = &vkctx->vkfn; + VkImageView in_views[AV_NUM_DATA_POINTERS]; + VkImageView tmp_views[AV_NUM_DATA_POINTERS]; + VkImageView out_views[AV_NUM_DATA_POINTERS]; + VkImageMemoryBarrier2 img_bar[37]; + int nb_img_bar = 0; + + /* Update descriptors and init the exec context */ + FFVkExecContext *exec = ff_vk_exec_get(e); + ff_vk_exec_start(vkctx, exec); + + RET(ff_vk_exec_add_dep_frame(vkctx, exec, in, + VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT, + VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT)); + RET(ff_vk_exec_add_dep_frame(vkctx, exec, tmp, + VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT, + VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT)); + RET(ff_vk_exec_add_dep_frame(vkctx, exec, out, + VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT, + VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT)); + + RET(ff_vk_create_imageviews(vkctx, exec, in_views, in)); + RET(ff_vk_create_imageviews(vkctx, exec, tmp_views, tmp)); + RET(ff_vk_create_imageviews(vkctx, exec, out_views, out)); + + ff_vk_frame_barrier(vkctx, exec, in, img_bar, &nb_img_bar, + VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT, + VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT, + VK_ACCESS_SHADER_READ_BIT, + VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, + VK_QUEUE_FAMILY_IGNORED); + ff_vk_frame_barrier(vkctx, exec, tmp, img_bar, &nb_img_bar, + VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT, + VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT, + VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT, + VK_IMAGE_LAYOUT_GENERAL, + VK_QUEUE_FAMILY_IGNORED); + ff_vk_frame_barrier(vkctx, exec, out, img_bar, &nb_img_bar, + VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT, + VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT, + VK_ACCESS_SHADER_WRITE_BIT, + VK_IMAGE_LAYOUT_GENERAL, + VK_QUEUE_FAMILY_IGNORED); + + vk->CmdPipelineBarrier2(exec->buf, &(VkDependencyInfo) { + .sType = VK_STRUCTURE_TYPE_DEPENDENCY_INFO, + .pImageMemoryBarriers = img_bar, + .imageMemoryBarrierCount = nb_img_bar, + }); + + for (int i = 0; i < 2; i++) { + FFVulkanPipeline *pl = pls[i]; + AVFrame *src_f = !i ? in : tmp; + AVFrame *dst_f = !i ? tmp : out; + VkImageView *src_views = !i ? in_views : tmp_views; + VkImageView *dst_views = !i ? tmp_views : out_views; + + ff_vk_exec_bind_pipeline(vkctx, exec, pl); + + if (push_src) + ff_vk_update_push_exec(vkctx, exec, pl, VK_SHADER_STAGE_COMPUTE_BIT, + 0, push_size, push_src); + + ff_vk_update_descriptor_img_array(vkctx, pl, exec, src_f, src_views, 0, 0, + !i ? VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL : + VK_IMAGE_LAYOUT_GENERAL, + sampler); + ff_vk_update_descriptor_img_array(vkctx, pl, exec, dst_f, dst_views, 0, 1, + VK_IMAGE_LAYOUT_GENERAL, + VK_NULL_HANDLE); + + vk->CmdDispatch(exec->buf, + FFALIGN(vkctx->output_width, pl->wg_size[0])/pl->wg_size[0], + FFALIGN(vkctx->output_height, pl->wg_size[1])/pl->wg_size[1], + pl->wg_size[2]); } - outlink->hw_frames_ctx = output_frames_ref; - outlink->w = s->output_width; - outlink->h = s->output_height; - - return 0; + return ff_vk_exec_submit(vkctx, exec); fail: - av_buffer_unref(&output_frames_ref); + ff_vk_exec_discard_deps(vkctx, exec); return err; } -int ff_vk_filter_init(AVFilterContext *avctx) +int ff_vk_filter_process_Nin(FFVulkanContext *vkctx, FFVkExecPool *e, + FFVulkanPipeline *pl, + AVFrame *out, AVFrame *in[], int nb_in, + VkSampler sampler, void *push_src, size_t push_size) { - FFVulkanContext *s = avctx->priv; - - s->output_format = AV_PIX_FMT_NONE; + int err = 0; + FFVulkanFunctions *vk = &vkctx->vkfn; + VkImageView in_views[16][AV_NUM_DATA_POINTERS]; + VkImageView out_views[AV_NUM_DATA_POINTERS]; + VkImageMemoryBarrier2 img_bar[128]; + int nb_img_bar = 0; + + /* Update descriptors and init the exec context */ + FFVkExecContext *exec = ff_vk_exec_get(e); + ff_vk_exec_start(vkctx, exec); + + /* Inputs */ + for (int i = 0; i < nb_in; i++) { + RET(ff_vk_exec_add_dep_frame(vkctx, exec, in[i], + VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT, + VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT)); + RET(ff_vk_create_imageviews(vkctx, exec, in_views[i], in[i])); + + ff_vk_frame_barrier(vkctx, exec, in[i], img_bar, &nb_img_bar, + VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT, + VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT, + VK_ACCESS_SHADER_READ_BIT, + VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, + VK_QUEUE_FAMILY_IGNORED); + } - return 0; + /* Output */ + RET(ff_vk_exec_add_dep_frame(vkctx, exec, out, + VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT, + VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT)); + RET(ff_vk_create_imageviews(vkctx, exec, out_views, out)); + ff_vk_frame_barrier(vkctx, exec, out, img_bar, &nb_img_bar, + VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT, + VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT, + VK_ACCESS_SHADER_WRITE_BIT, + VK_IMAGE_LAYOUT_GENERAL, + VK_QUEUE_FAMILY_IGNORED); + + vk->CmdPipelineBarrier2(exec->buf, &(VkDependencyInfo) { + .sType = VK_STRUCTURE_TYPE_DEPENDENCY_INFO, + .pImageMemoryBarriers = img_bar, + .imageMemoryBarrierCount = nb_img_bar, + }); + + ff_vk_exec_bind_pipeline(vkctx, exec, pl); + + if (push_src) + ff_vk_update_push_exec(vkctx, exec, pl, VK_SHADER_STAGE_COMPUTE_BIT, + 0, push_size, push_src); + + for (int i = 0; i < nb_in; i++) + ff_vk_update_descriptor_img_array(vkctx, pl, exec, in[i], in_views[i], 0, i, + VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, + sampler); + + ff_vk_update_descriptor_img_array(vkctx, pl, exec, out, out_views, 0, nb_in, + VK_IMAGE_LAYOUT_GENERAL, + VK_NULL_HANDLE); + + vk->CmdDispatch(exec->buf, + FFALIGN(vkctx->output_width, pl->wg_size[0])/pl->wg_size[0], + FFALIGN(vkctx->output_height, pl->wg_size[1])/pl->wg_size[1], + pl->wg_size[2]); + + return ff_vk_exec_submit(vkctx, exec); +fail: + ff_vk_exec_discard_deps(vkctx, exec); + return err; } diff --git a/libavfilter/vulkan_filter.h b/libavfilter/vulkan_filter.h index bfdb9b2d7d8..d2c14601d94 100644 --- a/libavfilter/vulkan_filter.h +++ b/libavfilter/vulkan_filter.h @@ -1,4 +1,6 @@ /* + * Copyright (c) Lynne + * * This file is part of FFmpeg. * * FFmpeg is free software; you can redistribute it and/or @@ -26,9 +28,38 @@ /** * 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); +int ff_vk_filter_init (AVFilterContext *avctx); +int ff_vk_filter_config_input (AVFilterLink *inlink); +int ff_vk_filter_config_output(AVFilterLink *outlink); + +/** + * Can be called manually, if not using ff_vk_filter_config_output. + */ +int ff_vk_filter_init_context(AVFilterContext *avctx, FFVulkanContext *s, + AVBufferRef *frames_ref, + int width, int height, enum AVPixelFormat sw_format); + +/** + * Submit a compute shader with a zero/one input and single out for execution. + */ +int ff_vk_filter_process_simple(FFVulkanContext *vkctx, FFVkExecPool *e, + FFVulkanPipeline *pl, AVFrame *out_f, AVFrame *in_f, + VkSampler sampler, void *push_src, size_t push_size); + +/** + * Submit a compute shader with a single in and single out with 2 stages. + */ +int ff_vk_filter_process_2pass(FFVulkanContext *vkctx, FFVkExecPool *e, + FFVulkanPipeline *pls[2], + AVFrame *out, AVFrame *tmp, AVFrame *in, + VkSampler sampler, void *push_src, size_t push_size); + +/** + * Up to 16 inputs, one output + */ +int ff_vk_filter_process_Nin(FFVulkanContext *vkctx, FFVkExecPool *e, + FFVulkanPipeline *pl, + AVFrame *out, AVFrame *in[], int nb_in, + VkSampler sampler, void *push_src, size_t push_size); #endif /* AVFILTER_VULKAN_FILTER_H */ diff --git a/libavutil/vulkan_glslang.c b/libavfilter/vulkan_glslang.c similarity index 95% rename from libavutil/vulkan_glslang.c rename to libavfilter/vulkan_glslang.c index e7785f6d405..845a530ee0d 100644 --- a/libavutil/vulkan_glslang.c +++ b/libavfilter/vulkan_glslang.c @@ -21,8 +21,9 @@ #include #include -#include "mem.h" -#include "avassert.h" +#include "vulkan_spirv.h" +#include "libavutil/mem.h" +#include "libavutil/avassert.h" static pthread_mutex_t glslc_mutex = PTHREAD_MUTEX_INITIALIZER; static int glslc_refcount = 0; @@ -176,11 +177,13 @@ static int glslc_shader_compile(FFVkSPIRVCompiler *ctx, void *avctx, av_assert0(glslc_refcount); + *opaque = NULL; + 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); + ff_vk_shader_print(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)); @@ -189,7 +192,7 @@ static int glslc_shader_compile(FFVkSPIRVCompiler *ctx, void *avctx, } if (!glslang_shader_parse(glslc_shader, &glslc_input)) { - ff_vk_print_shader(avctx, shd, AV_LOG_WARNING); + ff_vk_shader_print(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)); @@ -206,7 +209,7 @@ static int glslc_shader_compile(FFVkSPIRVCompiler *ctx, void *avctx, 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); + ff_vk_shader_print(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)); @@ -219,10 +222,10 @@ static int glslc_shader_compile(FFVkSPIRVCompiler *ctx, void *avctx, messages = glslang_program_SPIRV_get_messages(glslc_program); if (messages) { - ff_vk_print_shader(avctx, shd, AV_LOG_WARNING); + ff_vk_shader_print(avctx, shd, AV_LOG_WARNING); av_log(avctx, AV_LOG_WARNING, "%s\n", messages); } else { - ff_vk_print_shader(avctx, shd, AV_LOG_VERBOSE); + ff_vk_shader_print(avctx, shd, AV_LOG_VERBOSE); } glslang_shader_delete(glslc_shader); @@ -257,7 +260,7 @@ static void glslc_uninit(FFVkSPIRVCompiler **ctx) av_freep(ctx); } -static FFVkSPIRVCompiler *ff_vk_glslang_init(void) +FFVkSPIRVCompiler *ff_vk_glslang_init(void) { FFVkSPIRVCompiler *ret = av_mallocz(sizeof(*ret)); if (!ret) diff --git a/libavutil/vulkan_shaderc.c b/libavfilter/vulkan_shaderc.c similarity index 96% rename from libavutil/vulkan_shaderc.c rename to libavfilter/vulkan_shaderc.c index bd40edf1876..38be1030ad2 100644 --- a/libavutil/vulkan_shaderc.c +++ b/libavfilter/vulkan_shaderc.c @@ -18,7 +18,8 @@ #include -#include "mem.h" +#include "libavutil/mem.h" +#include "vulkan_spirv.h" static int shdc_shader_compile(FFVkSPIRVCompiler *ctx, void *avctx, FFVkSPIRVShader *shd, uint8_t **data, @@ -43,6 +44,7 @@ static int shdc_shader_compile(FFVkSPIRVCompiler *ctx, void *avctx, }; shaderc_compile_options_t opts = shaderc_compile_options_initialize(); + *opaque = NULL; if (!opts) return AVERROR(ENOMEM); @@ -65,7 +67,7 @@ static int shdc_shader_compile(FFVkSPIRVCompiler *ctx, void *avctx, loglevel = err ? AV_LOG_ERROR : warn ? AV_LOG_WARNING : AV_LOG_VERBOSE; - ff_vk_print_shader(avctx, shd, loglevel); + ff_vk_shader_print(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"; @@ -104,7 +106,7 @@ static void shdc_uninit(FFVkSPIRVCompiler **ctx) av_freep(ctx); } -static FFVkSPIRVCompiler *ff_vk_shaderc_init(void) +FFVkSPIRVCompiler *ff_vk_shaderc_init(void) { FFVkSPIRVCompiler *ret = av_mallocz(sizeof(*ret)); if (!ret) diff --git a/libavfilter/vulkan_spirv.h b/libavfilter/vulkan_spirv.h new file mode 100644 index 00000000000..5638cd9696a --- /dev/null +++ b/libavfilter/vulkan_spirv.h @@ -0,0 +1,45 @@ +/* + * 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_SPIRV_H +#define AVFILTER_VULKAN_SPIRV_H + +#include "libavutil/vulkan.h" + +#include "vulkan.h" +#include "config.h" + +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; + +#if CONFIG_LIBGLSLANG +FFVkSPIRVCompiler *ff_vk_glslang_init(void); +#define ff_vk_spirv_init ff_vk_glslang_init +#endif +#if CONFIG_LIBSHADERC +FFVkSPIRVCompiler *ff_vk_shaderc_init(void); +#define ff_vk_spirv_init ff_vk_shaderc_init +#endif + +#endif /* AVFILTER_VULKAN_H */ From f29850e98fc754086c4df14d8c14d9351f8e02fc Mon Sep 17 00:00:00 2001 From: Lynne Date: Fri, 17 Feb 2023 03:11:19 +0100 Subject: [PATCH 1277/2172] avgblur_vulkan: port for the rewrite --- libavfilter/vf_avgblur_vulkan.c | 365 +++++++++--------------------- libavfilter/vf_chromaber_vulkan.c | 2 +- 2 files changed, 102 insertions(+), 265 deletions(-) diff --git a/libavfilter/vf_avgblur_vulkan.c b/libavfilter/vf_avgblur_vulkan.c index 6a54d158ce1..44c4854b35a 100644 --- a/libavfilter/vf_avgblur_vulkan.c +++ b/libavfilter/vf_avgblur_vulkan.c @@ -1,4 +1,6 @@ /* + * Copyright (c) Lynne + * * This file is part of FFmpeg. * * FFmpeg is free software; you can redistribute it and/or @@ -19,23 +21,24 @@ #include "libavutil/random_seed.h" #include "libavutil/opt.h" #include "vulkan_filter.h" +#include "vulkan_spirv.h" #include "internal.h" -#define CGS 32 - typedef struct AvgBlurVulkanContext { FFVulkanContext vkctx; int initialized; + FFVkExecPool e; FFVkQueueFamilyCtx qf; - FFVkExecContext *exec; - FFVulkanPipeline *pl_hor; - FFVulkanPipeline *pl_ver; + VkSampler sampler; + FFVulkanPipeline pl; + FFVkSPIRVShader shd; - /* Shader updators, must be in the main filter struct */ - VkDescriptorImageInfo input_images[3]; - VkDescriptorImageInfo tmp_images[3]; - VkDescriptorImageInfo output_images[3]; + /* Push constants / options */ + struct { + float filter_norm[4]; + int32_t filter_len[2]; + } opts; int size_x; int size_y; @@ -43,46 +46,53 @@ typedef struct AvgBlurVulkanContext { } AvgBlurVulkanContext; static const char blur_kernel[] = { - C(0, shared vec4 cache[DIR(gl_WorkGroupSize) + FILTER_RADIUS*2 + 1]; ) - C(0, ) - C(0, void distort(const ivec2 pos, const int idx) ) - C(0, { ) - C(1, const uint cp = DIR(gl_LocalInvocationID) + FILTER_RADIUS; ) - C(0, ) - C(1, cache[cp] = texture(input_img[idx], pos); ) - C(0, ) - C(1, const ivec2 loc_l = pos - INC(FILTER_RADIUS); ) - C(1, cache[cp - FILTER_RADIUS] = texture(input_img[idx], loc_l); ) - C(0, ) - C(1, const ivec2 loc_h = pos + INC(DIR(gl_WorkGroupSize)); ) - C(1, cache[cp + DIR(gl_WorkGroupSize)] = texture(input_img[idx], loc_h); ) - C(0, ) - C(1, barrier(); ) - C(0, ) - C(1, vec4 sum = vec4(0); ) - C(1, for (int p = -FILTER_RADIUS; p <= FILTER_RADIUS; p++) ) - C(2, sum += cache[cp + p]; ) - C(0, ) - C(1, sum /= vec4(FILTER_RADIUS*2 + 1); ) - C(1, imageStore(output_img[idx], pos, sum); ) - C(0, } ) + C(0, void distort(const ivec2 pos, const int idx) ) + C(0, { ) + C(1, vec4 sum = vec4(0); ) + C(1, for (int y = -filter_len.y; y <= filter_len.y; y++) ) + C(1, for (int x = -filter_len.x; x <= filter_len.x; x++) ) + C(2, sum += texture(input_img[idx], pos + ivec2(x, y)); ) + C(0, ) + C(1, imageStore(output_img[idx], pos, sum * filter_norm); ) + C(0, } ) }; static av_cold int init_filter(AVFilterContext *ctx, AVFrame *in) { int err; - FFVkSPIRVShader *shd; + uint8_t *spv_data; + size_t spv_len; + void *spv_opaque = NULL; AvgBlurVulkanContext *s = ctx->priv; FFVulkanContext *vkctx = &s->vkctx; const int planes = av_pix_fmt_count_planes(s->vkctx.output_format); + FFVkSPIRVShader *shd; + FFVkSPIRVCompiler *spv; + FFVulkanDescriptorSetBinding *desc; + + spv = ff_vk_spirv_init(); + if (!spv) { + av_log(ctx, AV_LOG_ERROR, "Unable to initialize SPIR-V compiler!\n"); + return AVERROR_EXTERNAL; + } - FFVulkanDescriptorSetBinding desc_i[2] = { + ff_vk_qf_init(vkctx, &s->qf, VK_QUEUE_COMPUTE_BIT); + RET(ff_vk_exec_pool_init(vkctx, &s->qf, &s->e, s->qf.nb_queues*4, 0, 0, 0, NULL)); + RET(ff_vk_init_sampler(vkctx, &s->sampler, 1, VK_FILTER_LINEAR)); + RET(ff_vk_shader_init(&s->pl, &s->shd, "avgblur_compute", + VK_SHADER_STAGE_COMPUTE_BIT, 0)); + shd = &s->shd; + + ff_vk_shader_set_compute_sizes(shd, 32, 1, 1); + + desc = (FFVulkanDescriptorSetBinding []) { { .name = "input_img", .type = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, .dimensions = 2, .elems = planes, .stages = VK_SHADER_STAGE_COMPUTE_BIT, + .samplers = DUP_SAMPLER(s->sampler), }, { .name = "output_img", @@ -95,244 +105,68 @@ static av_cold int init_filter(AVFilterContext *ctx, AVFrame *in) }, }; - ff_vk_qf_init(vkctx, &s->qf, VK_QUEUE_COMPUTE_BIT, 0); + RET(ff_vk_pipeline_descriptor_set_add(vkctx, &s->pl, shd, desc, 2, 0, 0)); - desc_i[0].sampler = ff_vk_init_sampler(vkctx, 1, VK_FILTER_LINEAR); - if (!desc_i[0].sampler) - return AVERROR_EXTERNAL; + GLSLC(0, layout(push_constant, std430) uniform pushConstants { ); + GLSLC(1, vec4 filter_norm; ); + GLSLC(1, ivec2 filter_len; ); + GLSLC(0, }; ); + GLSLC(0, ); - { /* 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(vkctx, &s->qf); - if (!s->pl_hor) - return AVERROR(ENOMEM); - - 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 }); - - 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)) ); - GLSLC(0, #define DIR(var) (var.x) ); - GLSLD( blur_kernel ); - 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_img[%i]); ,i); - GLSLC(1, if (IS_WITHIN(pos, size)) { ); - if (s->planes & (1 << i)) { - GLSLF(2, distort(pos, %i); ,i); - } else { - GLSLF(2, vec4 res = texture(input_img[%i], pos); ,i); - GLSLF(2, imageStore(output_img[%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_hor)); - RET(ff_vk_init_compute_pipeline(vkctx, s->pl_hor)); - } + ff_vk_add_push_constant(&s->pl, 0, sizeof(s->opts), + VK_SHADER_STAGE_COMPUTE_BIT); - { /* 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(vkctx, &s->qf); - if (!s->pl_ver) - return AVERROR(ENOMEM); - - 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 }); - - 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)) ); - GLSLC(0, #define DIR(var) (var.y) ); - GLSLD( blur_kernel ); - 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_img[%i]); ,i); - GLSLC(1, if (IS_WITHIN(pos, size)) { ); - if (s->planes & (1 << i)) { - GLSLF(2, distort(pos, %i); ,i); - } else { - GLSLF(2, vec4 res = texture(input_img[%i], pos); ,i); - GLSLF(2, imageStore(output_img[%i], pos, res); ,i); - } - GLSLC(1, } ); + GLSLD( blur_kernel ); + 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_img[%i]); ,i); + GLSLC(1, if (!IS_WITHIN(pos, size)) ); + GLSLC(2, return; ); + if (s->planes & (1 << i)) { + GLSLF(1, distort(pos, %i); ,i); + } else { + GLSLF(1, vec4 res = texture(input_img[%i], pos); ,i); + GLSLF(1, imageStore(output_img[%i], pos, res); ,i); } - GLSLC(0, } ); - - RET(ff_vk_compile_shader(vkctx, shd, "main")); - - RET(ff_vk_init_pipeline_layout(vkctx, s->pl_ver)); - RET(ff_vk_init_compute_pipeline(vkctx, s->pl_ver)); } + GLSLC(0, } ); + + RET(spv->compile_shader(spv, ctx, &s->shd, &spv_data, &spv_len, "main", + &spv_opaque)); + RET(ff_vk_shader_create(vkctx, &s->shd, spv_data, spv_len, "main")); - /* Execution context */ - RET(ff_vk_create_exec_ctx(vkctx, &s->exec, &s->qf)); + RET(ff_vk_init_compute_pipeline(vkctx, &s->pl, &s->shd)); + RET(ff_vk_exec_pipeline_register(vkctx, &s->e, &s->pl)); s->initialized = 1; + s->opts.filter_len[0] = s->size_x - 1; + s->opts.filter_len[1] = s->size_y - 1; + + s->opts.filter_norm[0] = s->opts.filter_len[0]*2 + 1; + s->opts.filter_norm[0] = 1.0/(s->opts.filter_norm[0]*s->opts.filter_norm[0]); + s->opts.filter_norm[1] = s->opts.filter_norm[0]; + s->opts.filter_norm[2] = s->opts.filter_norm[0]; + s->opts.filter_norm[3] = s->opts.filter_norm[0]; return 0; fail: - return err; -} - -static int process_frames(AVFilterContext *avctx, AVFrame *out_f, AVFrame *tmp_f, AVFrame *in_f) -{ - int err; - VkCommandBuffer cmd_buf; - AvgBlurVulkanContext *s = avctx->priv; - 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]; - - 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 */ - 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->tmp_images[i].imageView, tmp->img[i], - output_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->tmp_images[i].imageLayout = VK_IMAGE_LAYOUT_GENERAL; - s->output_images[i].imageLayout = VK_IMAGE_LAYOUT_GENERAL; - } - - 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[] = { - { - .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(bar), bar); - - in->layout[i] = bar[0].newLayout; - in->access[i] = bar[0].dstAccessMask; - - tmp->layout[i] = bar[1].newLayout; - tmp->access[i] = bar[1].dstAccessMask; - - out->layout[i] = bar[2].newLayout; - out->access[i] = bar[2].dstAccessMask; - } - - 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(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(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(vkctx,s->exec); - if (err) - return err; - - ff_vk_qf_rotate(&s->qf); + if (spv_opaque) + spv->free_shader(spv, &spv_opaque); + if (spv) + spv->uninit(&spv); return err; - -fail: - ff_vk_discard_exec_deps(s->exec); - return err; } static int avgblur_vulkan_filter_frame(AVFilterLink *link, AVFrame *in) { int err; - AVFrame *tmp = NULL, *out = NULL; + AVFrame *out = NULL; AVFilterContext *ctx = link->dst; AvgBlurVulkanContext *s = ctx->priv; AVFilterLink *outlink = ctx->outputs[0]; @@ -343,29 +177,22 @@ static int avgblur_vulkan_filter_frame(AVFilterLink *link, AVFrame *in) goto fail; } - tmp = ff_get_video_buffer(outlink, outlink->w, outlink->h); - if (!tmp) { - err = AVERROR(ENOMEM); - goto fail; - } - if (!s->initialized) RET(init_filter(ctx, in)); - RET(process_frames(ctx, out, tmp, in)); + RET(ff_vk_filter_process_simple(&s->vkctx, &s->e, &s->pl, + out, in, s->sampler, &s->opts, sizeof(s->opts))); err = av_frame_copy_props(out, in); if (err < 0) goto fail; av_frame_free(&in); - av_frame_free(&tmp); return ff_filter_frame(outlink, out); fail: av_frame_free(&in); - av_frame_free(&tmp); av_frame_free(&out); return err; } @@ -373,6 +200,16 @@ static int avgblur_vulkan_filter_frame(AVFilterLink *link, AVFrame *in) static void avgblur_vulkan_uninit(AVFilterContext *avctx) { AvgBlurVulkanContext *s = avctx->priv; + FFVulkanContext *vkctx = &s->vkctx; + FFVulkanFunctions *vk = &vkctx->vkfn; + + ff_vk_exec_pool_free(vkctx, &s->e); + ff_vk_pipeline_free(vkctx, &s->pl); + ff_vk_shader_free(vkctx, &s->shd); + + if (s->sampler) + vk->DestroySampler(vkctx->hwctx->act_dev, s->sampler, + vkctx->hwctx->alloc); ff_vk_uninit(&s->vkctx); @@ -382,9 +219,9 @@ static void avgblur_vulkan_uninit(AVFilterContext *avctx) #define OFFSET(x) offsetof(AvgBlurVulkanContext, x) #define FLAGS (AV_OPT_FLAG_FILTERING_PARAM | AV_OPT_FLAG_VIDEO_PARAM) static const AVOption avgblur_vulkan_options[] = { - { "sizeX", "Set horizontal radius", OFFSET(size_x), AV_OPT_TYPE_INT, {.i64 = 3}, 1, 32, .flags = FLAGS }, + { "sizeX", "Set horizontal radius", OFFSET(size_x), AV_OPT_TYPE_INT, { .i64 = 3 }, 1, 32, .flags = FLAGS }, + { "sizeY", "Set vertical radius", OFFSET(size_y), AV_OPT_TYPE_INT, { .i64 = 3 }, 1, 32, .flags = FLAGS }, { "planes", "Set planes to filter (bitmask)", OFFSET(planes), AV_OPT_TYPE_INT, {.i64 = 0xF}, 0, 0xF, .flags = FLAGS }, - { "sizeY", "Set vertical radius", OFFSET(size_y), AV_OPT_TYPE_INT, {.i64 = 3}, 1, 32, .flags = FLAGS }, { NULL }, }; diff --git a/libavfilter/vf_chromaber_vulkan.c b/libavfilter/vf_chromaber_vulkan.c index 62b99cc4d91..5ebdaf4e434 100644 --- a/libavfilter/vf_chromaber_vulkan.c +++ b/libavfilter/vf_chromaber_vulkan.c @@ -59,7 +59,7 @@ static const char distort_chroma_kernel[] = { C(0, { ) C(1, vec2 p = ((vec2(pos)/vec2(size)) - 0.5f)*2.0f; ) C(1, float d = sqrt(p.x*p.x + p.y*p.y); ) - C(1, p *= d / (d* dist); ) + C(1, p *= d / (d*dist); ) C(1, vec4 res = texture(input_img[idx], (p/2.0f) + 0.5f); ) C(1, imageStore(output_img[idx], pos, res); ) C(0, } ) From 40bf1d525eb560137f7f8de674e70c3a9daa59ff Mon Sep 17 00:00:00 2001 From: Lynne Date: Fri, 17 Feb 2023 03:11:43 +0100 Subject: [PATCH 1278/2172] blend_vulkan: port for the rewrite --- libavfilter/vf_blend_vulkan.c | 316 +++++++++++----------------------- 1 file changed, 103 insertions(+), 213 deletions(-) diff --git a/libavfilter/vf_blend_vulkan.c b/libavfilter/vf_blend_vulkan.c index 4cee688a22f..530f4981c24 100644 --- a/libavfilter/vf_blend_vulkan.c +++ b/libavfilter/vf_blend_vulkan.c @@ -1,5 +1,7 @@ /* * copyright (c) 2021-2022 Wu Jianhua + * Copyright (c) Lynne + * * The blend modes are based on the blend.c. * * This file is part of FFmpeg. @@ -22,12 +24,11 @@ #include "libavutil/random_seed.h" #include "libavutil/opt.h" #include "vulkan_filter.h" +#include "vulkan_spirv.h" #include "internal.h" #include "framesync.h" #include "blend.h" -#define CGS 32 - #define IN_TOP 0 #define IN_BOTTOM 1 @@ -40,20 +41,18 @@ typedef struct 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]; + int initialized; + FFVulkanPipeline pl; + FFVkExecPool e; + FFVkQueueFamilyCtx qf; + FFVkSPIRVShader shd; + VkSampler sampler; FilterParamsVulkan params[4]; double all_opacity; enum BlendMode all_mode; - - int initialized; } BlendVulkanContext; #define DEFINE_BLEND_MODE(MODE, EXPR) \ @@ -125,223 +124,103 @@ static int process_command(AVFilterContext *ctx, const char *cmd, const char *ar static av_cold int init_filter(AVFilterContext *avctx) { int err = 0; - FFVkSampler *sampler; - FFVkSPIRVShader *shd; + uint8_t *spv_data; + size_t spv_len; + void *spv_opaque = NULL; BlendVulkanContext *s = avctx->priv; FFVulkanContext *vkctx = &s->vkctx; const int planes = av_pix_fmt_count_planes(s->vkctx.output_format); + FFVkSPIRVShader *shd = &s->shd; + FFVkSPIRVCompiler *spv; + FFVulkanDescriptorSetBinding *desc; - ff_vk_qf_init(vkctx, &s->qf, VK_QUEUE_COMPUTE_BIT, 0); - - sampler = ff_vk_init_sampler(vkctx, 1, VK_FILTER_LINEAR); - if (!sampler) + spv = ff_vk_spirv_init(); + if (!spv) { + av_log(avctx, AV_LOG_ERROR, "Unable to initialize SPIR-V compiler!\n"); 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_qf_init(vkctx, &s->qf, VK_QUEUE_COMPUTE_BIT); + RET(ff_vk_exec_pool_init(vkctx, &s->qf, &s->e, s->qf.nb_queues*4, 0, 0, 0, NULL)); + RET(ff_vk_init_sampler(vkctx, &s->sampler, 1, VK_FILTER_NEAREST)); + RET(ff_vk_shader_init(&s->pl, &s->shd, "blend_compute", + VK_SHADER_STAGE_COMPUTE_BIT, 0)); + + ff_vk_shader_set_compute_sizes(&s->shd, 32, 32, 1); + + desc = (FFVulkanDescriptorSetBinding []) { + { + .name = "top_images", + .type = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, + .dimensions = 2, + .elems = planes, + .stages = VK_SHADER_STAGE_COMPUTE_BIT, + .samplers = DUP_SAMPLER(s->sampler), + }, + { + .name = "bottom_images", + .type = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, + .dimensions = 2, + .elems = planes, + .stages = VK_SHADER_STAGE_COMPUTE_BIT, + .samplers = DUP_SAMPLER(s->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, + }, + }; + + RET(ff_vk_pipeline_descriptor_set_add(vkctx, &s->pl, shd, desc, 3, 0, 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); + } } - ff_vk_update_descriptor_set(vkctx, s->pl, 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++) { - 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; + 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, } ); - 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); + RET(spv->compile_shader(spv, avctx, shd, &spv_data, &spv_len, "main", + &spv_opaque)); + RET(ff_vk_shader_create(vkctx, shd, spv_data, spv_len, "main")); - err = ff_vk_submit_exec_queue(vkctx, s->exec); - if (err) - return err; + RET(ff_vk_init_compute_pipeline(vkctx, &s->pl, shd)); + RET(ff_vk_exec_pipeline_register(vkctx, &s->e, &s->pl)); - ff_vk_qf_rotate(&s->qf); - - return 0; + s->initialized = 1; fail: - ff_vk_discard_exec_deps(s->exec); + if (spv_opaque) + spv->free_shader(spv, &spv_opaque); + if (spv) + spv->uninit(&spv); + return err; } @@ -375,7 +254,9 @@ static int blend_frame(FFFrameSync *fs) RET(init_filter(avctx)); } - RET(process_frames(avctx, out, top, bottom)); + RET(ff_vk_filter_process_Nin(&s->vkctx, &s->e, &s->pl, + out, (AVFrame *[]){ top, bottom }, 2, + s->sampler, NULL, 0)); return ff_filter_frame(outlink, out); @@ -396,10 +277,19 @@ static av_cold int init(AVFilterContext *avctx) static av_cold void uninit(AVFilterContext *avctx) { BlendVulkanContext *s = avctx->priv; + FFVulkanContext *vkctx = &s->vkctx; + FFVulkanFunctions *vk = &vkctx->vkfn; - ff_framesync_uninit(&s->fs); + ff_vk_exec_pool_free(vkctx, &s->e); + ff_vk_pipeline_free(vkctx, &s->pl); + ff_vk_shader_free(vkctx, &s->shd); + + if (s->sampler) + vk->DestroySampler(vkctx->hwctx->act_dev, s->sampler, + vkctx->hwctx->alloc); ff_vk_uninit(&s->vkctx); + ff_framesync_uninit(&s->fs); s->initialized = 0; } From 125636608ddc0c86d167b46a8e5415e65ed5850b Mon Sep 17 00:00:00 2001 From: Lynne Date: Fri, 17 Feb 2023 03:11:53 +0100 Subject: [PATCH 1279/2172] chromaber_vulkan: port for the rewrite --- libavfilter/vf_chromaber_vulkan.c | 285 ++++++++++-------------------- 1 file changed, 96 insertions(+), 189 deletions(-) diff --git a/libavfilter/vf_chromaber_vulkan.c b/libavfilter/vf_chromaber_vulkan.c index 5ebdaf4e434..259232ab4db 100644 --- a/libavfilter/vf_chromaber_vulkan.c +++ b/libavfilter/vf_chromaber_vulkan.c @@ -1,4 +1,6 @@ /* + * Copyright (c) Lynne + * * This file is part of FFmpeg. * * FFmpeg is free software; you can redistribute it and/or @@ -19,21 +21,18 @@ #include "libavutil/random_seed.h" #include "libavutil/opt.h" #include "vulkan_filter.h" +#include "vulkan_spirv.h" #include "internal.h" -#define CGROUPS (int [3]){ 32, 32, 1 } - typedef struct ChromaticAberrationVulkanContext { FFVulkanContext vkctx; int initialized; + FFVulkanPipeline pl; + FFVkExecPool e; FFVkQueueFamilyCtx qf; - FFVkExecContext *exec; - FFVulkanPipeline *pl; - - /* Shader updators, must be in the main filter struct */ - VkDescriptorImageInfo input_images[3]; - VkDescriptorImageInfo output_images[3]; + FFVkSPIRVShader shd; + VkSampler sampler; /* Push constants / options */ struct { @@ -68,205 +67,102 @@ static const char distort_chroma_kernel[] = { static av_cold int init_filter(AVFilterContext *ctx, AVFrame *in) { int err; - FFVkSampler *sampler; + uint8_t *spv_data; + size_t spv_len; + void *spv_opaque = NULL; ChromaticAberrationVulkanContext *s = ctx->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); - - /* Create a sampler */ - sampler = ff_vk_init_sampler(vkctx, 0, VK_FILTER_LINEAR); - if (!sampler) - return AVERROR_EXTERNAL; - - s->pl = ff_vk_create_pipeline(vkctx, &s->qf); - if (!s->pl) - return AVERROR(ENOMEM); + FFVkSPIRVShader *shd = &s->shd; + FFVkSPIRVCompiler *spv; + FFVulkanDescriptorSetBinding *desc; /* Normalize options */ s->opts.dist[0] = (s->opts.dist[0] / 100.0f) + 1.0f; s->opts.dist[1] = (s->opts.dist[1] / 100.0f) + 1.0f; - { /* Create the shader */ - FFVulkanDescriptorSetBinding desc_i[2] = { - { - .name = "input_img", - .type = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, - .dimensions = 2, - .elems = planes, - .stages = VK_SHADER_STAGE_COMPUTE_BIT, - .updater = s->input_images, - .sampler = sampler, - }, - { - .name = "output_img", - .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, - }, - }; - - 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(shd, CGROUPS); - - GLSLC(0, layout(push_constant, std430) uniform pushConstants { ); - GLSLC(1, vec2 dist; ); - GLSLC(0, }; ); - GLSLC(0, ); - - 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, FF_ARRAY_ELEMS(desc_i), 0)); /* set 0 */ - - GLSLD( distort_chroma_kernel ); - GLSLC(0, void main() ); - GLSLC(0, { ); - GLSLC(1, ivec2 pos = ivec2(gl_GlobalInvocationID.xy); ); - if (planes == 1) { - GLSLC(1, distort_rgb(imageSize(output_img[0]), pos); ); - } else { - GLSLC(1, ivec2 size = imageSize(output_img[0]); ); - GLSLC(1, vec2 npos = vec2(pos)/vec2(size); ); - GLSLC(1, vec4 res = texture(input_img[0], npos); ); - GLSLC(1, imageStore(output_img[0], pos, res); ); - for (int i = 1; i < planes; i++) { - GLSLC(0, ); - GLSLF(1, size = imageSize(output_img[%i]); ,i); - GLSLC(1, if (IS_WITHIN(pos, size)) { ); - GLSLF(2, distort_chroma(%i, size, pos); ,i); - GLSLC(1, } else { ); - GLSLC(2, npos = vec2(pos)/vec2(size); ); - GLSLF(2, res = texture(input_img[%i], npos); ,i); - GLSLF(2, imageStore(output_img[%i], pos, res); ,i); - GLSLC(1, } ); - } - } - GLSLC(0, } ); + spv = ff_vk_spirv_init(); + if (!spv) { + av_log(ctx, AV_LOG_ERROR, "Unable to initialize SPIR-V compiler!\n"); + return AVERROR_EXTERNAL; + } - RET(ff_vk_compile_shader(vkctx, shd, "main")); + ff_vk_qf_init(vkctx, &s->qf, VK_QUEUE_COMPUTE_BIT); + RET(ff_vk_exec_pool_init(vkctx, &s->qf, &s->e, s->qf.nb_queues*4, 0, 0, 0, NULL)); + RET(ff_vk_init_sampler(vkctx, &s->sampler, 0, VK_FILTER_LINEAR)); + RET(ff_vk_shader_init(&s->pl, &s->shd, "chromaber_compute", + VK_SHADER_STAGE_COMPUTE_BIT, 0)); + + ff_vk_shader_set_compute_sizes(&s->shd, 32, 32, 1); + + GLSLC(0, layout(push_constant, std430) uniform pushConstants { ); + GLSLC(1, vec2 dist; ); + GLSLC(0, }; ); + GLSLC(0, ); + + ff_vk_add_push_constant(&s->pl, 0, sizeof(s->opts), + VK_SHADER_STAGE_COMPUTE_BIT); + + desc = (FFVulkanDescriptorSetBinding []) { + { + .name = "input_img", + .type = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, + .dimensions = 2, + .elems = planes, + .stages = VK_SHADER_STAGE_COMPUTE_BIT, + .samplers = DUP_SAMPLER(s->sampler), + }, + { + .name = "output_img", + .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, + }, + }; + + RET(ff_vk_pipeline_descriptor_set_add(vkctx, &s->pl, shd, desc, 2, 0, 0)); + + GLSLD( distort_chroma_kernel ); + GLSLC(0, void main() ); + GLSLC(0, { ); + GLSLC(1, ivec2 pos = ivec2(gl_GlobalInvocationID.xy); ); + if (planes == 1) { + GLSLC(1, distort_rgb(imageSize(output_img[0]), pos); ); + } else { + GLSLC(1, ivec2 size = imageSize(output_img[0]); ); + GLSLC(1, vec2 npos = vec2(pos)/vec2(size); ); + GLSLC(1, vec4 res = texture(input_img[0], npos); ); + GLSLC(1, imageStore(output_img[0], pos, res); ); + for (int i = 1; i < planes; i++) { + GLSLC(0, ); + GLSLF(1, size = imageSize(output_img[%i]); ,i); + GLSLC(1, if (!IS_WITHIN(pos, size)) ); + GLSLC(2, return; ); + GLSLF(1, distort_chroma(%i, size, pos); ,i); + } } + GLSLC(0, } ); - RET(ff_vk_init_pipeline_layout(vkctx, s->pl)); - RET(ff_vk_init_compute_pipeline(vkctx, s->pl)); + RET(spv->compile_shader(spv, ctx, shd, &spv_data, &spv_len, "main", + &spv_opaque)); + RET(ff_vk_shader_create(vkctx, shd, spv_data, spv_len, "main")); - /* Execution context */ - RET(ff_vk_create_exec_ctx(vkctx, &s->exec, &s->qf)); + RET(ff_vk_init_compute_pipeline(vkctx, &s->pl, shd)); + RET(ff_vk_exec_pipeline_register(vkctx, &s->e, &s->pl)); s->initialized = 1; return 0; fail: - return err; -} - -static int process_frames(AVFilterContext *avctx, AVFrame *out_f, AVFrame *in_f) -{ - int err = 0; - VkCommandBuffer cmd_buf; - ChromaticAberrationVulkanContext *s = avctx->priv; - 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); - 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); - 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], - ouput_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 bar[2] = { - { - .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(bar), bar); - - in->layout[i] = bar[0].newLayout; - in->access[i] = bar[0].dstAccessMask; - - out->layout[i] = bar[1].newLayout; - out->access[i] = bar[1].dstAccessMask; - } - - ff_vk_bind_pipeline_exec(vkctx, s->exec, s->pl); - - 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(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(vkctx, s->exec); - if (err) - return err; + if (spv_opaque) + spv->free_shader(spv, &spv_opaque); + if (spv) + spv->uninit(&spv); - ff_vk_qf_rotate(&s->qf); - - return err; - -fail: - ff_vk_discard_exec_deps(s->exec); return err; } @@ -286,7 +182,8 @@ static int chromaber_vulkan_filter_frame(AVFilterLink *link, AVFrame *in) if (!s->initialized) RET(init_filter(ctx, in)); - RET(process_frames(ctx, out, in)); + RET(ff_vk_filter_process_simple(&s->vkctx, &s->e, &s->pl, out, in, + s->sampler, &s->opts, sizeof(s->opts))); err = av_frame_copy_props(out, in); if (err < 0) @@ -305,6 +202,16 @@ static int chromaber_vulkan_filter_frame(AVFilterLink *link, AVFrame *in) static void chromaber_vulkan_uninit(AVFilterContext *avctx) { ChromaticAberrationVulkanContext *s = avctx->priv; + FFVulkanContext *vkctx = &s->vkctx; + FFVulkanFunctions *vk = &vkctx->vkfn; + + ff_vk_exec_pool_free(vkctx, &s->e); + ff_vk_pipeline_free(vkctx, &s->pl); + ff_vk_shader_free(vkctx, &s->shd); + + if (s->sampler) + vk->DestroySampler(vkctx->hwctx->act_dev, s->sampler, + vkctx->hwctx->alloc); ff_vk_uninit(&s->vkctx); From d26cbae3e18afb22e170baf1af17392c975353c7 Mon Sep 17 00:00:00 2001 From: Lynne Date: Fri, 17 Feb 2023 03:12:42 +0100 Subject: [PATCH 1280/2172] flip_vulkan: port for the rewrite --- libavfilter/vf_flip_vulkan.c | 230 ++++++++++++----------------------- 1 file changed, 79 insertions(+), 151 deletions(-) diff --git a/libavfilter/vf_flip_vulkan.c b/libavfilter/vf_flip_vulkan.c index 6868e39ee63..d7790c33086 100644 --- a/libavfilter/vf_flip_vulkan.c +++ b/libavfilter/vf_flip_vulkan.c @@ -1,5 +1,7 @@ /* * copyright (c) 2021 Wu Jianhua + * Copyright (c) Lynne + * * This file is part of FFmpeg. * * FFmpeg is free software; you can redistribute it and/or @@ -20,10 +22,9 @@ #include "libavutil/random_seed.h" #include "libavutil/opt.h" #include "vulkan_filter.h" +#include "vulkan_spirv.h" #include "internal.h" -#define CGS 32 - enum FlipType { FLIP_VERTICAL, FLIP_HORIZONTAL, @@ -32,32 +33,50 @@ enum FlipType { typedef struct FlipVulkanContext { FFVulkanContext vkctx; - FFVkQueueFamilyCtx qf; - FFVkExecContext *exec; - FFVulkanPipeline *pl; - - VkDescriptorImageInfo input_images[3]; - VkDescriptorImageInfo output_images[3]; int initialized; + FFVulkanPipeline pl; + FFVkExecPool e; + FFVkQueueFamilyCtx qf; + FFVkSPIRVShader shd; + VkSampler sampler; } FlipVulkanContext; static av_cold int init_filter(AVFilterContext *ctx, AVFrame *in, enum FlipType type) { int err = 0; - FFVkSPIRVShader *shd; + uint8_t *spv_data; + size_t spv_len; + void *spv_opaque = NULL; FlipVulkanContext *s = ctx->priv; FFVulkanContext *vkctx = &s->vkctx; const int planes = av_pix_fmt_count_planes(s->vkctx.output_format); + FFVkSPIRVShader *shd = &s->shd; + FFVkSPIRVCompiler *spv; + FFVulkanDescriptorSetBinding *desc; + + spv = ff_vk_spirv_init(); + if (!spv) { + av_log(ctx, AV_LOG_ERROR, "Unable to initialize SPIR-V compiler!\n"); + return AVERROR_EXTERNAL; + } + + ff_vk_qf_init(vkctx, &s->qf, VK_QUEUE_COMPUTE_BIT); + RET(ff_vk_exec_pool_init(vkctx, &s->qf, &s->e, s->qf.nb_queues*4, 0, 0, 0, NULL)); + RET(ff_vk_init_sampler(vkctx, &s->sampler, 1, VK_FILTER_LINEAR)); + RET(ff_vk_shader_init(&s->pl, &s->shd, "flip_compute", + VK_SHADER_STAGE_COMPUTE_BIT, 0)); + + ff_vk_shader_set_compute_sizes(&s->shd, 32, 32, 1); - FFVulkanDescriptorSetBinding image_descs[] = { + desc = (FFVulkanDescriptorSetBinding []) { { .name = "input_image", .type = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, .dimensions = 2, .elems = planes, .stages = VK_SHADER_STAGE_COMPUTE_BIT, - .updater = s->input_images, + .samplers = DUP_SAMPLER(s->sampler), }, { .name = "output_image", @@ -67,167 +86,75 @@ static av_cold int init_filter(AVFilterContext *ctx, AVFrame *in, enum FlipType .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; + RET(ff_vk_pipeline_descriptor_set_add(vkctx, &s->pl, shd, desc, 2, 0, 0)); - 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, "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); ); - for (int i = 0; i < planes; i++) { - 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; - 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; - } - GLSLF(2, imageStore(output_image[%i], pos, res); ,i); - GLSLC(1, } ); + 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)) { ); + 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; + 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; } - 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)); + GLSLF(2, imageStore(output_image[%i], pos, res); ,i); + GLSLC(1, } ); } + GLSLC(0, } ); + + RET(spv->compile_shader(spv, ctx, shd, &spv_data, &spv_len, "main", + &spv_opaque)); + RET(ff_vk_shader_create(vkctx, shd, spv_data, spv_len, "main")); + + RET(ff_vk_init_compute_pipeline(vkctx, &s->pl, shd)); + RET(ff_vk_exec_pipeline_register(vkctx, &s->e, &s->pl)); - RET(ff_vk_create_exec_ctx(vkctx, &s->exec, &s->qf)); s->initialized = 1; fail: + if (spv_opaque) + spv->free_shader(spv, &spv_opaque); + if (spv) + spv->uninit(&spv); + return err; } static av_cold void flip_vulkan_uninit(AVFilterContext *avctx) { FlipVulkanContext *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; - FlipVulkanContext *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; - } + FFVulkanFunctions *vk = &vkctx->vkfn; - ff_vk_update_descriptor_set(vkctx, s->pl, 0); + ff_vk_exec_pool_free(vkctx, &s->e); + ff_vk_pipeline_free(vkctx, &s->pl); + ff_vk_shader_free(vkctx, &s->shd); - 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; + if (s->sampler) + vk->DestroySampler(vkctx->hwctx->act_dev, s->sampler, + vkctx->hwctx->alloc); - ff_vk_qf_rotate(&s->qf); + ff_vk_uninit(&s->vkctx); - return 0; -fail: - ff_vk_discard_exec_deps(s->exec); - return err; + s->initialized = 0; } static int filter_frame(AVFilterLink *link, AVFrame *in, enum FlipType type) @@ -247,7 +174,8 @@ static int filter_frame(AVFilterLink *link, AVFrame *in, enum FlipType type) if (!s->initialized) RET(init_filter(ctx, in, type)); - RET(process_frames(ctx, out, in)); + RET(ff_vk_filter_process_simple(&s->vkctx, &s->e, &s->pl, out, in, + s->sampler, NULL, 0)); RET(av_frame_copy_props(out, in)); From 59f21c051d653cdaf22eae4df9591daa89dba641 Mon Sep 17 00:00:00 2001 From: Lynne Date: Fri, 17 Feb 2023 03:12:55 +0100 Subject: [PATCH 1281/2172] gblur_vulkan: port for the rewrite --- libavfilter/vf_gblur_vulkan.c | 328 +++++++++++----------------------- 1 file changed, 102 insertions(+), 226 deletions(-) diff --git a/libavfilter/vf_gblur_vulkan.c b/libavfilter/vf_gblur_vulkan.c index a6037e08888..6f7532c1d4d 100644 --- a/libavfilter/vf_gblur_vulkan.c +++ b/libavfilter/vf_gblur_vulkan.c @@ -1,5 +1,7 @@ /* * copyright (c) 2021-2022 Wu Jianhua + * Copyright (c) Lynne + * * This file is part of FFmpeg. * * FFmpeg is free software; you can redistribute it and/or @@ -20,6 +22,7 @@ #include "libavutil/random_seed.h" #include "libavutil/opt.h" #include "vulkan_filter.h" +#include "vulkan_spirv.h" #include "internal.h" #define CGS 32 @@ -27,26 +30,23 @@ 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; + FFVkExecPool e; + FFVkQueueFamilyCtx qf; + VkSampler sampler; + FFVulkanPipeline pl_hor; + FFVkSPIRVShader shd_hor; + FFVkBuffer params_hor; + FFVulkanPipeline pl_ver; + FFVkSPIRVShader shd_ver; + FFVkBuffer params_ver; + int size; int sizeV; int planes; float sigma; float sigmaV; - AVFrame *tmpframe; } GBlurVulkanContext; static const char gblur_func[] = { @@ -118,16 +118,17 @@ static av_cold void init_gaussian_params(GBlurVulkanContext *s) s->sizeV = s->size; else init_kernel_size(s, &s->sizeV); - - s->tmpframe = NULL; } -static int init_gblur_pipeline(GBlurVulkanContext *s, FFVulkanPipeline *pl, FFVkSPIRVShader *shd, - FFVkBuffer *params_buf, VkDescriptorBufferInfo *params_desc, - int ksize, float sigma) +static int init_gblur_pipeline(GBlurVulkanContext *s, FFVulkanPipeline *pl, + FFVkSPIRVShader *shd, FFVkBuffer *params_buf, + int ksize, float sigma, FFVkSPIRVCompiler *spv) { int err = 0; uint8_t *kernel_mapped; + uint8_t *spv_data; + size_t spv_len; + void *spv_opaque = NULL; const int planes = av_pix_fmt_count_planes(s->vkctx.output_format); @@ -137,7 +138,6 @@ static int init_gblur_pipeline(GBlurVulkanContext *s, FFVulkanPipeline *pl, FFVk .mem_quali = "readonly", .mem_layout = "std430", .stages = VK_SHADER_STAGE_COMPUTE_BIT, - .updater = NULL, .buf_content = NULL, }; @@ -145,10 +145,9 @@ static int init_gblur_pipeline(GBlurVulkanContext *s, FFVulkanPipeline *pl, FFVk if (!kernel_def) return AVERROR(ENOMEM); - buf_desc.updater = params_desc; buf_desc.buf_content = kernel_def; - RET(ff_vk_add_descriptor_set(&s->vkctx, pl, shd, &buf_desc, 1, 0)); + RET(ff_vk_pipeline_descriptor_set_add(&s->vkctx, pl, shd, &buf_desc, 1, 1, 0)); GLSLD( gblur_func ); GLSLC(0, void main() ); @@ -157,38 +156,43 @@ static int init_gblur_pipeline(GBlurVulkanContext *s, FFVulkanPipeline *pl, FFVk 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(1, size = imageSize(output_images[%i]); ,i); + GLSLC(1, if (!IS_WITHIN(pos, size)) ); + GLSLC(2, return; ); if (s->planes & (1 << i)) { - GLSLF(2, gblur(pos, %i); ,i); + GLSLF(1, gblur(pos, %i); ,i); } else { - GLSLF(2, vec4 res = texture(input_images[%i], pos); ,i); - GLSLF(2, imageStore(output_images[%i], pos, res); ,i); + GLSLF(1, vec4 res = texture(input_images[%i], pos); ,i); + GLSLF(1, imageStore(output_images[%i], pos, res); ,i); } - GLSLC(1, } ); } GLSLC(0, } ); - RET(ff_vk_compile_shader(&s->vkctx, shd, "main")); + RET(spv->compile_shader(spv, s, shd, &spv_data, &spv_len, "main", + &spv_opaque)); + RET(ff_vk_shader_create(&s->vkctx, shd, spv_data, spv_len, "main")); - RET(ff_vk_init_pipeline_layout(&s->vkctx, pl)); - RET(ff_vk_init_compute_pipeline(&s->vkctx, pl)); + RET(ff_vk_init_compute_pipeline(&s->vkctx, pl, shd)); + RET(ff_vk_exec_pipeline_register(&s->vkctx, &s->e, pl)); RET(ff_vk_create_buf(&s->vkctx, params_buf, sizeof(float) * ksize, NULL, NULL, - VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT)); - RET(ff_vk_map_buffers(&s->vkctx, params_buf, &kernel_mapped, 1, 0)); + VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT | + VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, + VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT)); + RET(ff_vk_map_buffer(&s->vkctx, params_buf, &kernel_mapped, 0)); init_gaussian_kernel((float *)kernel_mapped, sigma, ksize); - RET(ff_vk_unmap_buffers(&s->vkctx, params_buf, 1, 1)); - - params_desc->buffer = params_buf->buf; - params_desc->range = VK_WHOLE_SIZE; + RET(ff_vk_unmap_buffer(&s->vkctx, params_buf, 1)); - ff_vk_update_descriptor_set(&s->vkctx, pl, 1); + RET(ff_vk_set_descriptor_buffer(&s->vkctx, pl, NULL, 1, 0, 0, + params_buf->address, params_buf->size, + VK_FORMAT_UNDEFINED)); fail: av_free(kernel_def); + if (spv_opaque) + spv->free_shader(spv, &spv_opaque); return err; } @@ -196,16 +200,35 @@ static av_cold int init_filter(AVFilterContext *ctx, AVFrame *in) { int err = 0; GBlurVulkanContext *s = ctx->priv; - FFVkSPIRVShader *shd; + FFVulkanContext *vkctx = &s->vkctx; const int planes = av_pix_fmt_count_planes(s->vkctx.output_format); - FFVulkanDescriptorSetBinding image_descs[] = { + FFVkSPIRVShader *shd; + FFVkSPIRVCompiler *spv; + FFVulkanDescriptorSetBinding *desc; + + spv = ff_vk_spirv_init(); + if (!spv) { + av_log(ctx, AV_LOG_ERROR, "Unable to initialize SPIR-V compiler!\n"); + return AVERROR_EXTERNAL; + } + + ff_vk_qf_init(vkctx, &s->qf, VK_QUEUE_COMPUTE_BIT); + RET(ff_vk_exec_pool_init(vkctx, &s->qf, &s->e, s->qf.nb_queues*4, 0, 0, 0, NULL)); + RET(ff_vk_init_sampler(vkctx, &s->sampler, 1, VK_FILTER_LINEAR)); + RET(ff_vk_shader_init(&s->pl_hor, &s->shd_hor, "gblur_hor_compute", + VK_SHADER_STAGE_COMPUTE_BIT, 0)); + RET(ff_vk_shader_init(&s->pl_ver, &s->shd_ver, "gblur_ver_compute", + VK_SHADER_STAGE_COMPUTE_BIT, 0)); + + desc = (FFVulkanDescriptorSetBinding []) { { .name = "input_images", .type = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, .dimensions = 2, .elems = planes, .stages = VK_SHADER_STAGE_COMPUTE_BIT, + .samplers = DUP_SAMPLER(s->sampler), }, { .name = "output_images", @@ -218,215 +241,64 @@ static av_cold int init_filter(AVFilterContext *ctx, AVFrame *in) }, }; - image_descs[0].sampler = ff_vk_init_sampler(&s->vkctx, 1, VK_FILTER_LINEAR); - if (!image_descs[0].sampler) - return AVERROR_EXTERNAL; - init_gaussian_params(s); - 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; - - 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(s->pl_hor, "gblur_compute_hor", image_descs[0].stages); - if (!shd) { - err = AVERROR(ENOMEM); - goto fail; - } + shd = &s->shd_hor; + ff_vk_shader_set_compute_sizes(shd, 32, 1, 1); - ff_vk_set_compute_shader_sizes(shd, (int [3]){ CGS, 1, 1 }); - RET(ff_vk_add_descriptor_set(&s->vkctx, s->pl_hor, shd, image_descs, FF_ARRAY_ELEMS(image_descs), 0)); + RET(ff_vk_pipeline_descriptor_set_add(vkctx, &s->pl_hor, shd, desc, 2, 0, 0)); GLSLC(0, #define OFFSET (vec2(i, 0.0))); - RET(init_gblur_pipeline(s, s->pl_hor, shd, &s->params_buf_hor, &s->params_desc_hor, - s->size, s->sigma)); + RET(init_gblur_pipeline(s, &s->pl_hor, shd, &s->params_hor, s->size, s->sigma, spv)); } { - /* Create shader for the vertical pass */ - image_descs[0].updater = s->tmp_images; - image_descs[1].updater = s->output_images; - - s->pl_ver = ff_vk_create_pipeline(&s->vkctx, &s->qf); - if (!s->pl_ver) { - err = AVERROR(ENOMEM); - goto fail; - } + shd = &s->shd_ver; + ff_vk_shader_set_compute_sizes(shd, 1, 32, 1); - 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(shd, (int [3]){ 1, 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_pipeline_descriptor_set_add(vkctx, &s->pl_ver, shd, desc, 2, 0, 0)); GLSLC(0, #define OFFSET (vec2(0.0, i))); - RET(init_gblur_pipeline(s, s->pl_ver, shd, &s->params_buf_ver, &s->params_desc_ver, - s->sizeV, s->sigmaV)); + RET(init_gblur_pipeline(s, &s->pl_ver, shd, &s->params_ver, s->sizeV, s->sigmaV, spv)); } - RET(ff_vk_create_exec_ctx(&s->vkctx, &s->exec, &s->qf)); - s->initialized = 1; fail: + if (spv) + spv->uninit(&spv); + return err; } static av_cold void gblur_vulkan_uninit(AVFilterContext *avctx) { GBlurVulkanContext *s = avctx->priv; + FFVulkanContext *vkctx = &s->vkctx; + FFVulkanFunctions *vk = &vkctx->vkfn; - av_frame_free(&s->tmpframe); + ff_vk_exec_pool_free(vkctx, &s->e); + ff_vk_pipeline_free(vkctx, &s->pl_hor); + ff_vk_pipeline_free(vkctx, &s->pl_ver); + ff_vk_shader_free(vkctx, &s->shd_hor); + ff_vk_shader_free(vkctx, &s->shd_ver); + ff_vk_free_buf(vkctx, &s->params_hor); + ff_vk_free_buf(vkctx, &s->params_ver); + + if (s->sampler) + vk->DestroySampler(vkctx->hwctx->act_dev, s->sampler, + vkctx->hwctx->alloc); - 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; } -static int process_frames(AVFilterContext *avctx, AVFrame *outframe, AVFrame *inframe) -{ - int err; - VkCommandBuffer cmd_buf; - GBlurVulkanContext *s = avctx->priv; - 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]; - AVVkFrame *tmp = (AVVkFrame *)s->tmpframe->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(&s->vkctx, s->exec); - cmd_buf = ff_vk_get_exec_buf(s->exec); - - for (int i = 0; i < planes; i++) { - 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(&s->vkctx, s->exec, &s->tmp_images[i].imageView, - tmp->img[i], - output_formats[i], - ff_comp_identity_map)); - - RET(ff_vk_create_imageview(&s->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->tmp_images[i].imageLayout = VK_IMAGE_LAYOUT_GENERAL; - s->output_images[i].imageLayout = VK_IMAGE_LAYOUT_GENERAL; - } - - 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[] = { - { - .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(&s->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(&s->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(&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(&s->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 gblur_vulkan_filter_frame(AVFilterLink *link, AVFrame *in) { int err; - AVFrame *out = NULL; + AVFrame *tmp = NULL, *out = NULL; AVFilterContext *ctx = link->dst; GBlurVulkanContext *s = ctx->priv; AVFilterLink *outlink = ctx->outputs[0]; @@ -437,28 +309,32 @@ static int gblur_vulkan_filter_frame(AVFilterLink *link, AVFrame *in) 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; - } + tmp = ff_get_video_buffer(outlink, outlink->w, outlink->h); + if (!tmp) { + err = AVERROR(ENOMEM); + goto fail; } - RET(process_frames(ctx, out, in)); + if (!s->initialized) + RET(init_filter(ctx, in)); - RET(av_frame_copy_props(out, in)); + RET(ff_vk_filter_process_2pass(&s->vkctx, &s->e, + (FFVulkanPipeline *[2]){ &s->pl_hor, &s->pl_ver }, + out, tmp, in, s->sampler, NULL, 0)); + + err = av_frame_copy_props(out, in); + if (err < 0) + goto fail; av_frame_free(&in); + av_frame_free(&tmp); return ff_filter_frame(outlink, out); fail: av_frame_free(&in); + av_frame_free(&tmp); av_frame_free(&out); - av_frame_free(&s->tmpframe); - return err; } From 8e9ceb1efb3edefcac2d523bb99b0a92161d0f6f Mon Sep 17 00:00:00 2001 From: Lynne Date: Fri, 17 Feb 2023 03:13:05 +0100 Subject: [PATCH 1282/2172] overlay_vulkan: port for the rewrite --- libavfilter/vf_overlay_vulkan.c | 398 ++++++++++---------------------- 1 file changed, 123 insertions(+), 275 deletions(-) diff --git a/libavfilter/vf_overlay_vulkan.c b/libavfilter/vf_overlay_vulkan.c index 7a66cf12ad6..ef8e9fd59bc 100644 --- a/libavfilter/vf_overlay_vulkan.c +++ b/libavfilter/vf_overlay_vulkan.c @@ -1,4 +1,6 @@ /* + * Copyright (c) Lynne + * * This file is part of FFmpeg. * * FFmpeg is free software; you can redistribute it and/or @@ -19,26 +21,26 @@ #include "libavutil/random_seed.h" #include "libavutil/opt.h" #include "vulkan_filter.h" +#include "vulkan_spirv.h" #include "internal.h" #include "framesync.h" -#define CGROUPS (int [3]){ 32, 32, 1 } - typedef struct OverlayVulkanContext { FFVulkanContext vkctx; + FFFrameSync fs; int initialized; + FFVulkanPipeline pl; + FFVkExecPool e; FFVkQueueFamilyCtx qf; - FFVkExecContext *exec; - FFVulkanPipeline *pl; - FFFrameSync fs; - FFVkBuffer params_buf; + FFVkSPIRVShader shd; + VkSampler sampler; - /* Shader updators, must be in the main filter struct */ - VkDescriptorImageInfo main_images[3]; - VkDescriptorImageInfo overlay_images[3]; - VkDescriptorImageInfo output_images[3]; - VkDescriptorBufferInfo params_desc; + /* Push constants / options */ + struct { + int32_t o_offset[2*3]; + int32_t o_size[2*3]; + } opts; int overlay_x; int overlay_y; @@ -80,279 +82,114 @@ static const char overlay_alpha[] = { static av_cold int init_filter(AVFilterContext *ctx) { int err; - FFVkSampler *sampler; + uint8_t *spv_data; + size_t spv_len; + void *spv_opaque = NULL; OverlayVulkanContext *s = ctx->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_NEAREST); - if (!sampler) + const int ialpha = av_pix_fmt_desc_get(s->vkctx.input_format)->flags & AV_PIX_FMT_FLAG_ALPHA; + const AVPixFmtDescriptor *pix_desc = av_pix_fmt_desc_get(s->vkctx.output_format); + FFVkSPIRVShader *shd = &s->shd; + FFVkSPIRVCompiler *spv; + FFVulkanDescriptorSetBinding *desc; + + spv = ff_vk_spirv_init(); + if (!spv) { + av_log(ctx, AV_LOG_ERROR, "Unable to initialize SPIR-V compiler!\n"); return AVERROR_EXTERNAL; - - s->pl = ff_vk_create_pipeline(vkctx, &s->qf); - if (!s->pl) - return AVERROR(ENOMEM); - - { /* Create the shader */ - const int ialpha = av_pix_fmt_desc_get(s->vkctx.input_format)->flags & AV_PIX_FMT_FLAG_ALPHA; - - FFVulkanDescriptorSetBinding desc_i[3] = { - { - .name = "main_img", - .type = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, - .dimensions = 2, - .elems = planes, - .stages = VK_SHADER_STAGE_COMPUTE_BIT, - .updater = s->main_images, - .sampler = sampler, - }, - { - .name = "overlay_img", - .type = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, - .dimensions = 2, - .elems = planes, - .stages = VK_SHADER_STAGE_COMPUTE_BIT, - .updater = s->overlay_images, - .sampler = sampler, - }, - { - .name = "output_img", - .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, - }, - }; - - FFVulkanDescriptorSetBinding desc_b = { - .name = "params", - .type = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, - .mem_quali = "readonly", - .mem_layout = "std430", - .stages = VK_SHADER_STAGE_COMPUTE_BIT, - .updater = &s->params_desc, - .buf_content = "ivec2 o_offset[3], o_size[3];", - }; - - 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(shd, CGROUPS); - - 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 ); - GLSLD( overlay_alpha ); - GLSLC(0, void main() ); - GLSLC(0, { ); - GLSLC(1, ivec2 pos = ivec2(gl_GlobalInvocationID.xy); ); - GLSLF(1, int planes = %i; ,planes); - GLSLC(1, for (int i = 0; i < planes; i++) { ); - if (ialpha) - GLSLC(2, overlay_alpha_opaque(i, pos); ); - else - GLSLC(2, overlay_noalpha(i, pos); ); - 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)); - - { /* Create and update buffer */ - const AVPixFmtDescriptor *desc; - - /* NOTE: std430 requires the same identical struct layout, padding and - * alignment as C, so we're allowed to do this, as this will map - * exactly to what the shader recieves */ - struct { - int32_t o_offset[2*3]; - int32_t o_size[2*3]; - } *par; - - err = ff_vk_create_buf(vkctx, &s->params_buf, - sizeof(*par), NULL, - VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, - VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT); - if (err) - return err; - - err = ff_vk_map_buffers(vkctx, &s->params_buf, (uint8_t **)&par, 1, 0); - if (err) - return err; - - desc = av_pix_fmt_desc_get(s->vkctx.output_format); - - par->o_offset[0] = s->overlay_x; - par->o_offset[1] = s->overlay_y; - par->o_offset[2] = par->o_offset[0] >> desc->log2_chroma_w; - par->o_offset[3] = par->o_offset[1] >> desc->log2_chroma_h; - par->o_offset[4] = par->o_offset[0] >> desc->log2_chroma_w; - par->o_offset[5] = par->o_offset[1] >> desc->log2_chroma_h; - - par->o_size[0] = s->overlay_w; - par->o_size[1] = s->overlay_h; - par->o_size[2] = par->o_size[0] >> desc->log2_chroma_w; - par->o_size[3] = par->o_size[1] >> desc->log2_chroma_h; - 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(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(vkctx, s->pl, 1); } - /* Execution context */ - RET(ff_vk_create_exec_ctx(vkctx, &s->exec, &s->qf)); + ff_vk_qf_init(vkctx, &s->qf, VK_QUEUE_COMPUTE_BIT); + RET(ff_vk_exec_pool_init(vkctx, &s->qf, &s->e, s->qf.nb_queues*4, 0, 0, 0, NULL)); + RET(ff_vk_init_sampler(vkctx, &s->sampler, 1, VK_FILTER_NEAREST)); + RET(ff_vk_shader_init(&s->pl, &s->shd, "overlay_compute", + VK_SHADER_STAGE_COMPUTE_BIT, 0)); + + ff_vk_shader_set_compute_sizes(&s->shd, 32, 32, 1); + + GLSLC(0, layout(push_constant, std430) uniform pushConstants { ); + GLSLC(1, ivec2 o_offset[3]; ); + GLSLC(1, ivec2 o_size[3]; ); + GLSLC(0, }; ); + GLSLC(0, ); + + ff_vk_add_push_constant(&s->pl, 0, sizeof(s->opts), + VK_SHADER_STAGE_COMPUTE_BIT); + + desc = (FFVulkanDescriptorSetBinding []) { + { + .name = "main_img", + .type = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, + .dimensions = 2, + .elems = planes, + .stages = VK_SHADER_STAGE_COMPUTE_BIT, + .samplers = DUP_SAMPLER(s->sampler), + }, + { + .name = "overlay_img", + .type = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, + .dimensions = 2, + .elems = planes, + .stages = VK_SHADER_STAGE_COMPUTE_BIT, + .samplers = DUP_SAMPLER(s->sampler), + }, + { + .name = "output_img", + .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, + }, + }; + + RET(ff_vk_pipeline_descriptor_set_add(vkctx, &s->pl, shd, desc, 3, 0, 0)); + + GLSLD( overlay_noalpha ); + GLSLD( overlay_alpha ); + GLSLC(0, void main() ); + GLSLC(0, { ); + GLSLC(1, ivec2 pos = ivec2(gl_GlobalInvocationID.xy); ); + GLSLF(1, int planes = %i; ,planes); + GLSLC(1, for (int i = 0; i < planes; i++) { ); + if (ialpha) + GLSLC(2, overlay_alpha_opaque(i, pos); ); + else + GLSLC(2, overlay_noalpha(i, pos); ); + GLSLC(1, } ); + GLSLC(0, } ); + + RET(spv->compile_shader(spv, ctx, shd, &spv_data, &spv_len, "main", + &spv_opaque)); + RET(ff_vk_shader_create(vkctx, shd, spv_data, spv_len, "main")); + + RET(ff_vk_init_compute_pipeline(vkctx, &s->pl, shd)); + RET(ff_vk_exec_pipeline_register(vkctx, &s->e, &s->pl)); + + s->opts.o_offset[0] = s->overlay_x; + s->opts.o_offset[1] = s->overlay_y; + s->opts.o_offset[2] = s->opts.o_offset[0] >> pix_desc->log2_chroma_w; + s->opts.o_offset[3] = s->opts.o_offset[1] >> pix_desc->log2_chroma_h; + s->opts.o_offset[4] = s->opts.o_offset[0] >> pix_desc->log2_chroma_w; + s->opts.o_offset[5] = s->opts.o_offset[1] >> pix_desc->log2_chroma_h; + + s->opts.o_size[0] = s->overlay_w; + s->opts.o_size[1] = s->overlay_h; + s->opts.o_size[2] = s->opts.o_size[0] >> pix_desc->log2_chroma_w; + s->opts.o_size[3] = s->opts.o_size[1] >> pix_desc->log2_chroma_h; + s->opts.o_size[4] = s->opts.o_size[0] >> pix_desc->log2_chroma_w; + s->opts.o_size[5] = s->opts.o_size[1] >> pix_desc->log2_chroma_h; s->initialized = 1; - return 0; - fail: - return err; -} - -static int process_frames(AVFilterContext *avctx, AVFrame *out_f, - AVFrame *main_f, AVFrame *overlay_f) -{ - int err; - VkCommandBuffer cmd_buf; - OverlayVulkanContext *s = avctx->priv; - 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]; - 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 *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); - - for (int i = 0; i < planes; i++) { - RET(ff_vk_create_imageview(vkctx, s->exec, - &s->main_images[i].imageView, main->img[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], - overlay_sw_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->main_images[i].imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; - s->overlay_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 bar[3] = { - { - .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, - .srcAccessMask = 0, - .dstAccessMask = VK_ACCESS_SHADER_READ_BIT, - .oldLayout = main->layout[i], - .newLayout = s->main_images[i].imageLayout, - .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, - .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, - .image = main->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 = overlay->layout[i], - .newLayout = s->overlay_images[i].imageLayout, - .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, - .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, - .image = overlay->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(bar), bar); - - main->layout[i] = bar[0].newLayout; - main->access[i] = bar[0].dstAccessMask; - - overlay->layout[i] = bar[1].newLayout; - overlay->access[i] = bar[1].dstAccessMask; - - out->layout[i] = bar[2].newLayout; - out->access[i] = bar[2].dstAccessMask; - } - - 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(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(vkctx, s->exec); - if (err) - return err; + if (spv_opaque) + spv->free_shader(spv, &spv_opaque); + if (spv) + spv->uninit(&spv); - ff_vk_qf_rotate(&s->qf); - - return err; - -fail: - ff_vk_discard_exec_deps(s->exec); return err; } @@ -394,7 +231,9 @@ static int overlay_vulkan_blend(FFFrameSync *fs) goto fail; } - RET(process_frames(ctx, out, input_main, input_overlay)); + RET(ff_vk_filter_process_Nin(&s->vkctx, &s->e, &s->pl, + out, (AVFrame *[]){ input_main, input_overlay }, 2, + s->sampler, &s->opts, sizeof(s->opts))); err = av_frame_copy_props(out, input_main); if (err < 0) @@ -443,8 +282,17 @@ static av_cold int overlay_vulkan_init(AVFilterContext *avctx) static void overlay_vulkan_uninit(AVFilterContext *avctx) { OverlayVulkanContext *s = avctx->priv; + FFVulkanContext *vkctx = &s->vkctx; + FFVulkanFunctions *vk = &vkctx->vkfn; + + ff_vk_exec_pool_free(vkctx, &s->e); + ff_vk_pipeline_free(vkctx, &s->pl); + ff_vk_shader_free(vkctx, &s->shd); + + if (s->sampler) + vk->DestroySampler(vkctx->hwctx->act_dev, s->sampler, + vkctx->hwctx->alloc); - ff_vk_free_buf(&s->vkctx, &s->params_buf); ff_vk_uninit(&s->vkctx); ff_framesync_uninit(&s->fs); From d4b51b50856d4f3743da8f4e9a1bb4e11271fdb6 Mon Sep 17 00:00:00 2001 From: Lynne Date: Fri, 17 Feb 2023 03:13:32 +0100 Subject: [PATCH 1283/2172] scale_vulkan: port for the rewrite --- libavfilter/vf_scale_vulkan.c | 366 ++++++++++++---------------------- 1 file changed, 125 insertions(+), 241 deletions(-) diff --git a/libavfilter/vf_scale_vulkan.c b/libavfilter/vf_scale_vulkan.c index cd37a861b1a..3029cf2b420 100644 --- a/libavfilter/vf_scale_vulkan.c +++ b/libavfilter/vf_scale_vulkan.c @@ -1,4 +1,6 @@ /* + * Copyright (c) Lynne + * * This file is part of FFmpeg. * * FFmpeg is free software; you can redistribute it and/or @@ -19,12 +21,11 @@ #include "libavutil/random_seed.h" #include "libavutil/opt.h" #include "vulkan_filter.h" +#include "vulkan_spirv.h" #include "scale_eval.h" #include "internal.h" #include "colorspace.h" -#define CGROUPS (int [3]){ 32, 32, 1 } - enum ScalerFunc { F_BILINEAR = 0, F_NEAREST, @@ -35,15 +36,17 @@ enum ScalerFunc { typedef struct ScaleVulkanContext { FFVulkanContext vkctx; + int initialized; + FFVulkanPipeline pl; + FFVkExecPool e; FFVkQueueFamilyCtx qf; - FFVkExecContext *exec; - FFVulkanPipeline *pl; - FFVkBuffer params_buf; + FFVkSPIRVShader shd; + VkSampler sampler; - /* Shader updators, must be in the main filter struct */ - VkDescriptorImageInfo input_images[3]; - VkDescriptorImageInfo output_images[3]; - VkDescriptorBufferInfo params_desc; + /* Push constants / options */ + struct { + float yuv_matrix[4][4]; + } opts; char *out_format_string; char *w_expr; @@ -51,8 +54,6 @@ typedef struct ScaleVulkanContext { enum ScalerFunc scaler; enum AVColorRange out_range; - - int initialized; } ScaleVulkanContext; static const char scale_bilinear[] = { @@ -110,10 +111,15 @@ static const char write_444[] = { static av_cold int init_filter(AVFilterContext *ctx, AVFrame *in) { int err; - FFVkSampler *sampler; + uint8_t *spv_data; + size_t spv_len; + void *spv_opaque = NULL; VkFilter sampler_mode; ScaleVulkanContext *s = ctx->priv; FFVulkanContext *vkctx = &s->vkctx; + FFVkSPIRVShader *shd = &s->shd; + FFVkSPIRVCompiler *spv; + FFVulkanDescriptorSetBinding *desc; int crop_x = in->crop_left; int crop_y = in->crop_top; @@ -121,8 +127,6 @@ 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(vkctx, &s->qf, VK_QUEUE_COMPUTE_BIT, 0); - switch (s->scaler) { case F_NEAREST: sampler_mode = VK_FILTER_NEAREST; @@ -132,264 +136,134 @@ static av_cold int init_filter(AVFilterContext *ctx, AVFrame *in) break; }; - /* Create a sampler */ - sampler = ff_vk_init_sampler(vkctx, 0, sampler_mode); - if (!sampler) + spv = ff_vk_spirv_init(); + if (!spv) { + av_log(ctx, AV_LOG_ERROR, "Unable to initialize SPIR-V compiler!\n"); return AVERROR_EXTERNAL; + } - s->pl = ff_vk_create_pipeline(vkctx, &s->qf); - if (!s->pl) - return AVERROR(ENOMEM); - - { /* Create the shader */ - FFVulkanDescriptorSetBinding desc_i[2] = { - { - .name = "input_img", - .type = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, - .dimensions = 2, - .elems = in_planes, - .stages = VK_SHADER_STAGE_COMPUTE_BIT, - .updater = s->input_images, - .sampler = sampler, - }, - { - .name = "output_img", - .type = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, - .mem_layout = ff_vk_shader_rep_fmt(s->vkctx.output_format), - .mem_quali = "writeonly", - .dimensions = 2, - .elems = av_pix_fmt_count_planes(s->vkctx.output_format), - .stages = VK_SHADER_STAGE_COMPUTE_BIT, - .updater = s->output_images, - }, - }; - - FFVulkanDescriptorSetBinding desc_b = { - .name = "params", - .type = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, - .mem_quali = "readonly", - .mem_layout = "std430", - .stages = VK_SHADER_STAGE_COMPUTE_BIT, - .updater = &s->params_desc, - .buf_content = "mat4 yuv_matrix;", - }; - - 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(shd, CGROUPS); - - 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 ); - - if (s->vkctx.output_format != s->vkctx.input_format) { - GLSLD( rgb2yuv ); - } + ff_vk_qf_init(vkctx, &s->qf, VK_QUEUE_COMPUTE_BIT); + RET(ff_vk_exec_pool_init(vkctx, &s->qf, &s->e, s->qf.nb_queues*4, 0, 0, 0, NULL)); + RET(ff_vk_init_sampler(vkctx, &s->sampler, 0, sampler_mode)); + RET(ff_vk_shader_init(&s->pl, &s->shd, "scale_compute", + VK_SHADER_STAGE_COMPUTE_BIT, 0)); + + ff_vk_shader_set_compute_sizes(&s->shd, 32, 32, 1); + + GLSLC(0, layout(push_constant, std430) uniform pushConstants { ); + GLSLC(1, mat4 yuv_matrix; ); + GLSLC(0, }; ); + GLSLC(0, ); + + ff_vk_add_push_constant(&s->pl, 0, sizeof(s->opts), + VK_SHADER_STAGE_COMPUTE_BIT); + + desc = (FFVulkanDescriptorSetBinding []) { + { + .name = "input_img", + .type = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, + .dimensions = 2, + .elems = in_planes, + .stages = VK_SHADER_STAGE_COMPUTE_BIT, + .samplers = DUP_SAMPLER(s->sampler), + }, + { + .name = "output_img", + .type = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, + .mem_layout = ff_vk_shader_rep_fmt(s->vkctx.output_format), + .mem_quali = "writeonly", + .dimensions = 2, + .elems = av_pix_fmt_count_planes(s->vkctx.output_format), + .stages = VK_SHADER_STAGE_COMPUTE_BIT, + }, + }; - switch (s->vkctx.output_format) { - case AV_PIX_FMT_NV12: GLSLD(write_nv12); break; - case AV_PIX_FMT_YUV420P: GLSLD( write_420); break; - case AV_PIX_FMT_YUV444P: GLSLD( write_444); break; - default: break; - } + RET(ff_vk_pipeline_descriptor_set_add(vkctx, &s->pl, shd, desc, 2, 0, 0)); - GLSLC(0, void main() ); - GLSLC(0, { ); - GLSLC(1, ivec2 size; ); - GLSLC(1, ivec2 pos = ivec2(gl_GlobalInvocationID.xy); ); - GLSLF(1, vec2 in_d = vec2(%i, %i); ,in->width, in->height); - GLSLF(1, vec2 c_r = vec2(%i, %i) / in_d; ,crop_w, crop_h); - GLSLF(1, vec2 c_o = vec2(%i, %i) / in_d; ,crop_x,crop_y); - GLSLC(0, ); - - if (s->vkctx.output_format == s->vkctx.input_format) { - for (int i = 0; i < desc_i[1].elems; i++) { - GLSLF(1, size = imageSize(output_img[%i]); ,i); - GLSLC(1, if (IS_WITHIN(pos, size)) { ); - switch (s->scaler) { - case F_NEAREST: - case F_BILINEAR: - GLSLF(2, vec4 res = scale_bilinear(%i, pos, c_r, c_o); ,i); - GLSLF(2, imageStore(output_img[%i], pos, res); ,i); - break; - }; - GLSLC(1, } ); - } - } else { - GLSLC(1, vec4 res = scale_bilinear(0, pos, c_r, c_o); ); - GLSLF(1, res = rgb2yuv(res, %i); ,s->out_range == AVCOL_RANGE_JPEG); - switch (s->vkctx.output_format) { - case AV_PIX_FMT_NV12: GLSLC(1, write_nv12(res, pos); ); break; - case AV_PIX_FMT_YUV420P: GLSLC(1, write_420(res, pos); ); break; - case AV_PIX_FMT_YUV444P: GLSLC(1, write_444(res, pos); ); break; - default: return AVERROR(EINVAL); - } - } + GLSLD( scale_bilinear ); + + if (s->vkctx.output_format != s->vkctx.input_format) { + GLSLD( rgb2yuv ); + } - GLSLC(0, } ); + switch (s->vkctx.output_format) { + case AV_PIX_FMT_NV12: GLSLD(write_nv12); break; + case AV_PIX_FMT_YUV420P: GLSLD( write_420); break; + case AV_PIX_FMT_YUV444P: GLSLD( write_444); break; + default: break; + } - RET(ff_vk_compile_shader(vkctx, shd, "main")); + GLSLC(0, void main() ); + GLSLC(0, { ); + GLSLC(1, ivec2 size; ); + GLSLC(1, ivec2 pos = ivec2(gl_GlobalInvocationID.xy); ); + GLSLF(1, vec2 in_d = vec2(%i, %i); ,in->width, in->height); + GLSLF(1, vec2 c_r = vec2(%i, %i) / in_d; ,crop_w, crop_h); + GLSLF(1, vec2 c_o = vec2(%i, %i) / in_d; ,crop_x,crop_y); + GLSLC(0, ); + + if (s->vkctx.output_format == s->vkctx.input_format) { + for (int i = 0; i < desc[i].elems; i++) { + GLSLF(1, size = imageSize(output_img[%i]); ,i); + GLSLC(1, if (IS_WITHIN(pos, size)) { ); + switch (s->scaler) { + case F_NEAREST: + case F_BILINEAR: + GLSLF(2, vec4 res = scale_bilinear(%i, pos, c_r, c_o); ,i); + GLSLF(2, imageStore(output_img[%i], pos, res); ,i); + break; + }; + GLSLC(1, } ); + } + } else { + GLSLC(1, vec4 res = scale_bilinear(0, pos, c_r, c_o); ); + GLSLF(1, res = rgb2yuv(res, %i); ,s->out_range == AVCOL_RANGE_JPEG); + switch (s->vkctx.output_format) { + case AV_PIX_FMT_NV12: GLSLC(1, write_nv12(res, pos); ); break; + case AV_PIX_FMT_YUV420P: GLSLC(1, write_420(res, pos); ); break; + case AV_PIX_FMT_YUV444P: GLSLC(1, write_444(res, pos); ); break; + default: return AVERROR(EINVAL); + } } - RET(ff_vk_init_pipeline_layout(vkctx, s->pl)); - RET(ff_vk_init_compute_pipeline(vkctx, s->pl)); + GLSLC(0, } ); if (s->vkctx.output_format != s->vkctx.input_format) { const AVLumaCoefficients *lcoeffs; double tmp_mat[3][3]; - struct { - float yuv_matrix[4][4]; - } *par; - lcoeffs = av_csp_luma_coeffs_from_avcsp(in->colorspace); if (!lcoeffs) { av_log(ctx, AV_LOG_ERROR, "Unsupported colorspace\n"); return AVERROR(EINVAL); } - RET(ff_vk_create_buf(vkctx, &s->params_buf, - sizeof(*par), NULL, NULL, - VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, - VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT)); - - RET(ff_vk_map_buffers(vkctx, &s->params_buf, (uint8_t **)&par, 1, 0)); - ff_fill_rgb2yuv_table(lcoeffs, tmp_mat); - memset(par, 0, sizeof(*par)); - for (int y = 0; y < 3; y++) for (int x = 0; x < 3; x++) - par->yuv_matrix[x][y] = tmp_mat[x][y]; - - par->yuv_matrix[3][3] = 1.0; - - RET(ff_vk_unmap_buffers(vkctx, &s->params_buf, 1, 1)); - - s->params_desc.buffer = s->params_buf.buf; - s->params_desc.range = VK_WHOLE_SIZE; - - ff_vk_update_descriptor_set(vkctx, s->pl, 1); + s->opts.yuv_matrix[x][y] = tmp_mat[x][y]; + s->opts.yuv_matrix[3][3] = 1.0; } - /* Execution context */ - RET(ff_vk_create_exec_ctx(vkctx, &s->exec, &s->qf)); + RET(spv->compile_shader(spv, ctx, shd, &spv_data, &spv_len, "main", + &spv_opaque)); + RET(ff_vk_shader_create(vkctx, shd, spv_data, spv_len, "main")); + + RET(ff_vk_init_compute_pipeline(vkctx, &s->pl, shd)); + RET(ff_vk_exec_pipeline_register(vkctx, &s->e, &s->pl)); s->initialized = 1; return 0; fail: - return err; -} - -static int process_frames(AVFilterContext *avctx, AVFrame *out_f, AVFrame *in_f) -{ - int err = 0; - VkCommandBuffer cmd_buf; - ScaleVulkanContext *s = avctx->priv; - 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; - 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); - 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 bar = { - .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, - }; - - memcpy(&barriers[barrier_count++], &bar, sizeof(VkImageMemoryBarrier)); - - in->layout[i] = bar.newLayout; - in->access[i] = bar.dstAccessMask; - } - - for (int i = 0; i < av_pix_fmt_count_planes(s->vkctx.output_format); i++) { - VkImageMemoryBarrier bar = { - .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, - }; - - memcpy(&barriers[barrier_count++], &bar, sizeof(VkImageMemoryBarrier)); - - out->layout[i] = bar.newLayout; - out->access[i] = bar.dstAccessMask; - } - - 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(vkctx, s->exec, s->pl); - - vk->CmdDispatch(cmd_buf, - FFALIGN(vkctx->output_width, CGROUPS[0])/CGROUPS[0], - FFALIGN(vkctx->output_height, CGROUPS[1])/CGROUPS[1], 1); - - 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(vkctx, s->exec); - if (err) - return err; - - ff_vk_qf_rotate(&s->qf); + if (spv_opaque) + spv->free_shader(spv, &spv_opaque); + if (spv) + spv->uninit(&spv); return err; - -fail: - ff_vk_discard_exec_deps(s->exec); - return err; } static int scale_vulkan_filter_frame(AVFilterLink *link, AVFrame *in) @@ -408,7 +282,8 @@ static int scale_vulkan_filter_frame(AVFilterLink *link, AVFrame *in) if (!s->initialized) RET(init_filter(ctx, in)); - RET(process_frames(ctx, out, in)); + RET(ff_vk_filter_process_simple(&s->vkctx, &s->e, &s->pl, out, in, + s->sampler, &s->opts, sizeof(s->opts))); err = av_frame_copy_props(out, in); if (err < 0) @@ -475,8 +350,17 @@ static int scale_vulkan_config_output(AVFilterLink *outlink) static void scale_vulkan_uninit(AVFilterContext *avctx) { ScaleVulkanContext *s = avctx->priv; + FFVulkanContext *vkctx = &s->vkctx; + FFVulkanFunctions *vk = &vkctx->vkfn; + + ff_vk_exec_pool_free(vkctx, &s->e); + ff_vk_pipeline_free(vkctx, &s->pl); + ff_vk_shader_free(vkctx, &s->shd); + + if (s->sampler) + vk->DestroySampler(vkctx->hwctx->act_dev, s->sampler, + vkctx->hwctx->alloc); - ff_vk_free_buf(&s->vkctx, &s->params_buf); ff_vk_uninit(&s->vkctx); s->initialized = 0; From f70f873272c800feb8676650c8ce8dcfdf94108c Mon Sep 17 00:00:00 2001 From: Lynne Date: Fri, 17 Feb 2023 03:13:43 +0100 Subject: [PATCH 1284/2172] transpose_vulkan: port for the rewrite --- libavfilter/vf_transpose_vulkan.c | 224 ++++++++++-------------------- 1 file changed, 76 insertions(+), 148 deletions(-) diff --git a/libavfilter/vf_transpose_vulkan.c b/libavfilter/vf_transpose_vulkan.c index 3b2ce4fb693..a8184cb6a4f 100644 --- a/libavfilter/vf_transpose_vulkan.c +++ b/libavfilter/vf_transpose_vulkan.c @@ -1,5 +1,7 @@ /* * copyright (c) 2021 Wu Jianhua + * Copyright (c) Lynne + * * This file is part of FFmpeg. * * FFmpeg is free software; you can redistribute it and/or @@ -20,41 +22,60 @@ #include "libavutil/random_seed.h" #include "libavutil/opt.h" #include "vulkan_filter.h" +#include "vulkan_spirv.h" #include "internal.h" #include "transpose.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; + FFVulkanPipeline pl; + FFVkExecPool e; + FFVkQueueFamilyCtx qf; + FFVkSPIRVShader shd; + VkSampler sampler; int dir; int passthrough; - int initialized; } TransposeVulkanContext; static av_cold int init_filter(AVFilterContext *ctx, AVFrame *in) { - int err = 0; - FFVkSPIRVShader *shd; + int err; + uint8_t *spv_data; + size_t spv_len; + void *spv_opaque = NULL; TransposeVulkanContext *s = ctx->priv; FFVulkanContext *vkctx = &s->vkctx; + const int planes = av_pix_fmt_count_planes(s->vkctx.output_format); + FFVkSPIRVShader *shd = &s->shd; + FFVkSPIRVCompiler *spv; + FFVulkanDescriptorSetBinding *desc; + + spv = ff_vk_spirv_init(); + if (!spv) { + av_log(ctx, AV_LOG_ERROR, "Unable to initialize SPIR-V compiler!\n"); + return AVERROR_EXTERNAL; + } + + ff_vk_qf_init(vkctx, &s->qf, VK_QUEUE_COMPUTE_BIT); + RET(ff_vk_exec_pool_init(vkctx, &s->qf, &s->e, s->qf.nb_queues*4, 0, 0, 0, NULL)); + RET(ff_vk_init_sampler(vkctx, &s->sampler, 1, VK_FILTER_LINEAR)); + RET(ff_vk_shader_init(&s->pl, &s->shd, "transpose_compute", + VK_SHADER_STAGE_COMPUTE_BIT, 0)); - FFVulkanDescriptorSetBinding image_descs[] = { + ff_vk_shader_set_compute_sizes(&s->shd, 32, 1, 1); + + desc = (FFVulkanDescriptorSetBinding []) { { .name = "input_images", .type = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, .dimensions = 2, .elems = planes, .stages = VK_SHADER_STAGE_COMPUTE_BIT, - .updater = s->input_images, + .samplers = DUP_SAMPLER(s->sampler), }, { .name = "output_images", @@ -64,154 +85,49 @@ static av_cold int init_filter(AVFilterContext *ctx, AVFrame *in) .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, 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)) { ); - 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, } ); - - 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); + RET(ff_vk_pipeline_descriptor_set_add(vkctx, &s->pl, shd, desc, 2, 0, 0)); + GLSLC(0, void main() ); + GLSLC(0, { ); + GLSLC(1, ivec2 size; ); + GLSLC(1, ivec2 pos = ivec2(gl_GlobalInvocationID.xy); ); 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; + GLSLC(0, ); + GLSLF(1, size = imageSize(output_images[%i]); ,i); + GLSLC(1, if (IS_WITHIN(pos, size)) { ); + 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, } ); - 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); + RET(spv->compile_shader(spv, ctx, shd, &spv_data, &spv_len, "main", + &spv_opaque)); + RET(ff_vk_shader_create(vkctx, shd, spv_data, spv_len, "main")); - 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); + RET(ff_vk_init_compute_pipeline(vkctx, &s->pl, shd)); + RET(ff_vk_exec_pipeline_register(vkctx, &s->e, &s->pl)); - err = ff_vk_submit_exec_queue(vkctx, s->exec); - if (err) - return err; - - ff_vk_qf_rotate(&s->qf); + s->initialized = 1; return 0; fail: - ff_vk_discard_exec_deps(s->exec); + if (spv_opaque) + spv->free_shader(spv, &spv_opaque); + if (spv) + spv->uninit(&spv); + return err; } @@ -235,7 +151,8 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in) if (!s->initialized) RET(init_filter(ctx, in)); - RET(process_frames(ctx, out, in)); + RET(ff_vk_filter_process_simple(&s->vkctx, &s->e, &s->pl, out, in, + s->sampler, NULL, 0)); RET(av_frame_copy_props(out, in)); @@ -259,6 +176,17 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in) static av_cold void transpose_vulkan_uninit(AVFilterContext *avctx) { TransposeVulkanContext *s = avctx->priv; + FFVulkanContext *vkctx = &s->vkctx; + FFVulkanFunctions *vk = &vkctx->vkfn; + + ff_vk_exec_pool_free(vkctx, &s->e); + ff_vk_pipeline_free(vkctx, &s->pl); + ff_vk_shader_free(vkctx, &s->shd); + + if (s->sampler) + vk->DestroySampler(vkctx->hwctx->act_dev, s->sampler, + vkctx->hwctx->alloc); + ff_vk_uninit(&s->vkctx); s->initialized = 0; From 661db605db412681d18e6b44801cf4ea5e2aa13e Mon Sep 17 00:00:00 2001 From: Niklas Haas Date: Mon, 30 Jan 2023 14:18:34 +0100 Subject: [PATCH 1285/2172] avfilter/vf_libplacebo: forward queue locking primitives For thread safety. --- libavfilter/vf_libplacebo.c | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/libavfilter/vf_libplacebo.c b/libavfilter/vf_libplacebo.c index adebcc45410..e28dddef4f3 100644 --- a/libavfilter/vf_libplacebo.c +++ b/libavfilter/vf_libplacebo.c @@ -544,6 +544,30 @@ static int libplacebo_init(AVFilterContext *avctx) return err; } +#if PL_API_VER >= 201 +# if PL_API_VER >= 278 +static void lock_queue(void *priv, uint32_t qf, uint32_t qidx) +# else +static void lock_queue(void *priv, int qf, int qidx) +# endif +{ + AVHWDeviceContext *avhwctx = priv; + const AVVulkanDeviceContext *hwctx = avhwctx->hwctx; + hwctx->lock_queue(avhwctx, qf, qidx); +} + +# if PL_API_VER >= 278 +static void unlock_queue(void *priv, uint32_t qf, uint32_t qidx) +# else +static void unlock_queue(void *priv, int qf, int qidx) +# endif +{ + AVHWDeviceContext *avhwctx = priv; + const AVVulkanDeviceContext *hwctx = avhwctx->hwctx; + hwctx->unlock_queue(avhwctx, qf, qidx); +} +#endif + static int init_vulkan(AVFilterContext *avctx, const AVVulkanDeviceContext *hwctx) { int err = 0; @@ -561,6 +585,11 @@ static int init_vulkan(AVFilterContext *avctx, const AVVulkanDeviceContext *hwct .extensions = hwctx->enabled_dev_extensions, .num_extensions = hwctx->nb_enabled_dev_extensions, .features = &hwctx->device_features, +#if PL_API_VER >= 201 + .lock_queue = lock_queue, + .unlock_queue = unlock_queue, + .queue_ctx = avctx->hw_device_ctx->data, +#endif .queue_graphics = { .index = hwctx->queue_family_index, .count = hwctx->nb_graphics_queues, From b41ea8c6c38951b421f5ee717d4b9e2284c2a264 Mon Sep 17 00:00:00 2001 From: Niklas Haas Date: Mon, 24 Apr 2023 13:22:23 +0200 Subject: [PATCH 1286/2172] avfilter/vf_libplacebo: bump max vk version For two reasons: 1. We now create a vulkan 1.3 device 2. libplacebo master currently requires a vulkan 1.3 device --- libavfilter/vf_libplacebo.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavfilter/vf_libplacebo.c b/libavfilter/vf_libplacebo.c index e28dddef4f3..2b8dac09b06 100644 --- a/libavfilter/vf_libplacebo.c +++ b/libavfilter/vf_libplacebo.c @@ -603,7 +603,7 @@ static int init_vulkan(AVFilterContext *avctx, const AVVulkanDeviceContext *hwct .count = hwctx->nb_tx_queues, }, /* This is the highest version created by hwcontext_vulkan.c */ - .max_api_version = VK_API_VERSION_1_2, + .max_api_version = VK_API_VERSION_1_3, )); } else { s->vulkan = pl_vulkan_create(s->log, pl_vulkan_params( From 9675e54b02acb7cdd6c3d655c9f09eba9f23ec6f Mon Sep 17 00:00:00 2001 From: Niklas Haas Date: Mon, 24 Apr 2023 17:31:21 +0200 Subject: [PATCH 1287/2172] avutil/hwcontext_vulkan: add libplacebo required features For compatibility with vf_libplacebo --- libavutil/hwcontext_vulkan.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/libavutil/hwcontext_vulkan.c b/libavutil/hwcontext_vulkan.c index 93b6c6de4b5..44a07cb61bc 100644 --- a/libavutil/hwcontext_vulkan.c +++ b/libavutil/hwcontext_vulkan.c @@ -1264,6 +1264,7 @@ static int vulkan_device_create_internal(AVHWDeviceContext *ctx, p->device_features_1_2.timelineSemaphore = 1; p->device_features_1_2.bufferDeviceAddress = dev_features_1_2.bufferDeviceAddress; + p->device_features_1_2.hostQueryReset = dev_features_1_2.hostQueryReset; p->device_features_1_2.storagePushConstant8 = dev_features_1_2.storagePushConstant8; p->device_features_1_2.shaderInt8 = dev_features_1_2.shaderInt8; p->device_features_1_2.storageBuffer8BitAccess = dev_features_1_2.storageBuffer8BitAccess; @@ -1274,6 +1275,8 @@ static int vulkan_device_create_internal(AVHWDeviceContext *ctx, p->device_features_1_2.vulkanMemoryModelDeviceScope = dev_features_1_2.vulkanMemoryModelDeviceScope; p->device_features_1_2.hostQueryReset = dev_features_1_2.hostQueryReset; + p->device_features_1_3.dynamicRendering = dev_features_1_3.dynamicRendering; + p->device_features_1_3.maintenance4 = dev_features_1_3.maintenance4; p->device_features_1_3.synchronization2 = dev_features_1_3.synchronization2; p->device_features_1_3.computeFullSubgroups = dev_features_1_3.computeFullSubgroups; p->device_features_1_3.shaderZeroInitializeWorkgroupMemory = dev_features_1_3.shaderZeroInitializeWorkgroupMemory; From 09dc9193ea527f32e473456433c4e0c317a8f513 Mon Sep 17 00:00:00 2001 From: Lynne Date: Sun, 26 Feb 2023 22:36:51 +0100 Subject: [PATCH 1288/2172] lavfi: add bwdif_vulkan --- configure | 1 + libavfilter/Makefile | 1 + libavfilter/allfilters.c | 1 + libavfilter/vf_bwdif_vulkan.c | 419 ++++++++++++++++++++++++++++++++++ 4 files changed, 422 insertions(+) create mode 100644 libavfilter/vf_bwdif_vulkan.c diff --git a/configure b/configure index 201efd4f945..84668dd4f9d 100755 --- a/configure +++ b/configure @@ -3640,6 +3640,7 @@ blend_vulkan_filter_deps="vulkan spirv_compiler" boxblur_filter_deps="gpl" boxblur_opencl_filter_deps="opencl gpl" bs2b_filter_deps="libbs2b" +bwdif_vulkan_filter_deps="vulkan spirv_compiler" chromaber_vulkan_filter_deps="vulkan spirv_compiler" colorkey_opencl_filter_deps="opencl" colormatrix_filter_deps="gpl" diff --git a/libavfilter/Makefile b/libavfilter/Makefile index c4b52d02575..4bc30c37f88 100644 --- a/libavfilter/Makefile +++ b/libavfilter/Makefile @@ -213,6 +213,7 @@ OBJS-$(CONFIG_BOXBLUR_FILTER) += vf_boxblur.o boxblur.o 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_BWDIF_VULKAN_FILTER) += vf_bwdif_vulkan.o yadif_common.o vulkan.o vulkan_filter.o OBJS-$(CONFIG_CAS_FILTER) += vf_cas.o OBJS-$(CONFIG_CCREPACK_FILTER) += vf_ccrepack.o OBJS-$(CONFIG_CHROMABER_VULKAN_FILTER) += vf_chromaber_vulkan.o vulkan.o vulkan_filter.o diff --git a/libavfilter/allfilters.c b/libavfilter/allfilters.c index 30447a11c8d..8f88c1443f2 100644 --- a/libavfilter/allfilters.c +++ b/libavfilter/allfilters.c @@ -197,6 +197,7 @@ extern const AVFilter ff_vf_bm3d; extern const AVFilter ff_vf_boxblur; extern const AVFilter ff_vf_boxblur_opencl; extern const AVFilter ff_vf_bwdif; +extern const AVFilter ff_vf_bwdif_vulkan; extern const AVFilter ff_vf_cas; extern const AVFilter ff_vf_ccrepack; extern const AVFilter ff_vf_chromaber_vulkan; diff --git a/libavfilter/vf_bwdif_vulkan.c b/libavfilter/vf_bwdif_vulkan.c new file mode 100644 index 00000000000..1fc74d15442 --- /dev/null +++ b/libavfilter/vf_bwdif_vulkan.c @@ -0,0 +1,419 @@ +/* + * Copyright (c) Lynne + * Copyright (C) 2018 Philip Langdale + * Copyright (C) 2016 Thomas Mundt + * + * 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 "vulkan_spirv.h" +#include "yadif.h" +#include "internal.h" + +typedef struct BWDIFVulkanContext { + YADIFContext yadif; + FFVulkanContext vkctx; + + int initialized; + FFVkExecPool e; + FFVkQueueFamilyCtx qf; + VkSampler sampler; + FFVulkanPipeline pl; + FFVkSPIRVShader shd; +} BWDIFVulkanContext; + +typedef struct BWDIFParameters { + int parity; + int tff; + int current_field; +} BWDIFParameters; + +static const char filter_fn[] = { + "const vec4 coef_lf[2] = { vec4(4309), vec4(213), };\n" + "const vec4 coef_hf[3] = { vec4(5570), vec4(3801), vec4(1016) };\n" + "const vec4 coef_sp[2] = { vec4(5077), vec4(981), };\n" + C(0, ) + C(0, vec4 process_intra(vec4 cur[4]) ) + C(0, { ) + C(1, return (coef_sp[0]*(cur[1] + cur[2]) - coef_sp[1]*(cur[0] + cur[3])) / (1 << 13); ) + C(0, } ) + C(0, ) + C(0, vec4 process_line(vec4 prev2[5], vec4 prev1[2], vec4 cur[4], vec4 next1[2], vec4 next2[5]) ) + C(0, { ) + C(1, vec4 fc = cur[1]; ) + C(1, vec4 fe = cur[2]; ) + C(1, vec4 fs = prev2[2] + next2[2]; ) + C(1, vec4 fd = fs / 2; ) + C(0, ) + C(1, vec4 temp_diff[3]; ) + C(1, temp_diff[0] = abs(prev2[2] - next2[2]); ) + C(1, temp_diff[1] = (abs(prev1[0] - fc) + abs(prev1[1] - fe)) / 2; ) + C(1, temp_diff[1] = (abs(next1[0] - fc) + abs(next1[1] - fe)) / 2; ) + C(1, vec4 diff = max(temp_diff[0] / 2, max(temp_diff[1], temp_diff[2])); ) + C(1, bvec4 diff_mask = equal(diff, vec4(0)); ) + C(0, ) + C(1, vec4 fbs = prev2[1] + next2[1]; ) + C(1, vec4 ffs = prev2[3] + next2[3]; ) + C(1, vec4 fb = (fbs / 2) - fc; ) + C(1, vec4 ff = (ffs / 2) - fe; ) + C(1, vec4 dc = fd - fc; ) + C(1, vec4 de = fd - fe; ) + C(1, vec4 mmax = max(de, max(dc, min(fb, ff))); ) + C(1, vec4 mmin = min(de, min(dc, max(fb, ff))); ) + C(1, diff = max(diff, max(mmin, -mmax)); ) + C(0, ) +" vec4 interpolate_all = (((coef_hf[0]*(fs) - coef_hf[1]*(fbs + ffs) +\n" +" coef_hf[2]*(prev2[0] + next2[0] + prev2[4] + next2[4])) / 4) +\n" +" coef_lf[0]*(fc + fe) - coef_lf[1]*(cur[0] + cur[3])) / (1 << 13);\n" +" vec4 interpolate_cur = (coef_sp[0]*(fc + fe) - coef_sp[1]*(cur[0] + cur[3])) / (1 << 13);\n" + C(0, ) + C(1, bvec4 interpolate_cnd1 = greaterThan(abs(fc - fe), temp_diff[0]); ) + C(1, vec4 interpol = mix(interpolate_cur, interpolate_all, interpolate_cnd1); ) + /* Cliping interpol between [fd - diff, fd + diff] is intentionally left out. + * Removing the clipping increases quality. TODO: research and fix the C version to match this. */ + C(1, return mix(interpol, fd, diff_mask); ) + C(0, } ) +}; + +static av_cold int init_filter(AVFilterContext *ctx) +{ + int err; + uint8_t *spv_data; + size_t spv_len; + void *spv_opaque = NULL; + BWDIFVulkanContext *s = ctx->priv; + FFVulkanContext *vkctx = &s->vkctx; + const int planes = av_pix_fmt_count_planes(s->vkctx.output_format); + FFVkSPIRVShader *shd; + FFVkSPIRVCompiler *spv; + FFVulkanDescriptorSetBinding *desc; + + spv = ff_vk_spirv_init(); + if (!spv) { + av_log(ctx, AV_LOG_ERROR, "Unable to initialize SPIR-V compiler!\n"); + return AVERROR_EXTERNAL; + } + + ff_vk_qf_init(vkctx, &s->qf, VK_QUEUE_COMPUTE_BIT); + RET(ff_vk_exec_pool_init(vkctx, &s->qf, &s->e, s->qf.nb_queues*4, 0, 0, 0, NULL)); + RET(ff_vk_init_sampler(vkctx, &s->sampler, 1, VK_FILTER_NEAREST)); + RET(ff_vk_shader_init(&s->pl, &s->shd, "bwdif_compute", + VK_SHADER_STAGE_COMPUTE_BIT, 0)); + shd = &s->shd; + + ff_vk_shader_set_compute_sizes(shd, 1, 64, 1); + + desc = (FFVulkanDescriptorSetBinding []) { + { + .name = "prev", + .type = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, + .dimensions = 2, + .elems = planes, + .stages = VK_SHADER_STAGE_COMPUTE_BIT, + .samplers = DUP_SAMPLER(s->sampler), + }, + { + .name = "cur", + .type = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, + .dimensions = 2, + .elems = planes, + .stages = VK_SHADER_STAGE_COMPUTE_BIT, + .samplers = DUP_SAMPLER(s->sampler), + }, + { + .name = "next", + .type = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, + .dimensions = 2, + .elems = planes, + .stages = VK_SHADER_STAGE_COMPUTE_BIT, + .samplers = DUP_SAMPLER(s->sampler), + }, + { + .name = "dst", + .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, + }, + }; + + RET(ff_vk_pipeline_descriptor_set_add(vkctx, &s->pl, shd, desc, 4, 0, 0)); + + GLSLC(0, layout(push_constant, std430) uniform pushConstants { ); + GLSLC(1, int parity; ); + GLSLC(1, int tff; ); + GLSLC(1, int current_field; ); + GLSLC(0, }; ); + + ff_vk_add_push_constant(&s->pl, 0, sizeof(BWDIFParameters), + VK_SHADER_STAGE_COMPUTE_BIT); + + GLSLD( filter_fn ); + GLSLC(0, void main() ); + GLSLC(0, { ); + GLSLC(1, vec4 res; ); + GLSLC(1, ivec2 size; ); + GLSLC(1, vec4 dcur[4]; ); + GLSLC(1, vec4 prev1[2]; ); + GLSLC(1, vec4 next1[2]; ); + GLSLC(1, vec4 prev2[5]; ); + GLSLC(1, vec4 next2[5]; ); + GLSLC(1, const ivec2 pos = ivec2(gl_GlobalInvocationID.xy); ); + GLSLC(1, bool filter_field = ((pos.y ^ parity) & 1) == 1; ); + GLSLF(1, bool is_intra = filter_field && (current_field == %i); ,YADIF_FIELD_END); + GLSLC(1, bool field_parity = (parity ^ tff) != 0; ); + GLSLC(0, ); + + for (int i = 0; i < planes; i++) { + GLSLC(0, ); + GLSLF(1, size = imageSize(dst[%i]); ,i); + GLSLC(1, if (!IS_WITHIN(pos, size)) { ); + GLSLC(2, return; ); + GLSLC(1, } else if (is_intra) { ); + GLSLF(2, dcur[0] = texture(cur[%i], pos - ivec2(0, 3)); ,i); + GLSLF(2, dcur[1] = texture(cur[%i], pos - ivec2(0, 1)); ,i); + GLSLF(2, dcur[2] = texture(cur[%i], pos + ivec2(0, 1)); ,i); + GLSLF(2, dcur[3] = texture(cur[%i], pos + ivec2(0, 3)); ,i); + GLSLC(0, ); + GLSLC(2, res = process_intra(dcur); ); + GLSLF(2, imageStore(dst[%i], pos, res); ,i); + GLSLC(1, } else if (filter_field) { ); + GLSLF(2, dcur[0] = texture(cur[%i], pos - ivec2(0, 3)); ,i); + GLSLF(2, dcur[1] = texture(cur[%i], pos - ivec2(0, 1)); ,i); + GLSLF(2, dcur[2] = texture(cur[%i], pos + ivec2(0, 1)); ,i); + GLSLF(2, dcur[3] = texture(cur[%i], pos + ivec2(0, 3)); ,i); + GLSLC(0, ); + GLSLF(2, prev1[0] = texture(prev[%i], pos - ivec2(0, 1)); ,i); + GLSLF(2, prev1[1] = texture(prev[%i], pos + ivec2(0, 1)); ,i); + GLSLC(0, ); + GLSLF(2, next1[0] = texture(next[%i], pos - ivec2(0, 1)); ,i); + GLSLF(2, next1[1] = texture(next[%i], pos + ivec2(0, 1)); ,i); + GLSLC(0, ); + GLSLC(2, if (field_parity) { ); + GLSLF(3, prev2[0] = texture(prev[%i], pos - ivec2(0, 4)); ,i); + GLSLF(3, prev2[1] = texture(prev[%i], pos - ivec2(0, 2)); ,i); + GLSLF(3, prev2[2] = texture(prev[%i], pos); ,i); + GLSLF(3, prev2[3] = texture(prev[%i], pos + ivec2(0, 2)); ,i); + GLSLF(3, prev2[4] = texture(prev[%i], pos + ivec2(0, 4)); ,i); + GLSLC(0, ); + GLSLF(3, next2[0] = texture(cur[%i], pos - ivec2(0, 4)); ,i); + GLSLF(3, next2[1] = texture(cur[%i], pos - ivec2(0, 2)); ,i); + GLSLF(3, next2[2] = texture(cur[%i], pos); ,i); + GLSLF(3, next2[3] = texture(cur[%i], pos + ivec2(0, 2)); ,i); + GLSLF(3, next2[4] = texture(cur[%i], pos + ivec2(0, 4)); ,i); + GLSLC(2, } else { ); + GLSLF(3, prev2[0] = texture(cur[%i], pos - ivec2(0, 4)); ,i); + GLSLF(3, prev2[1] = texture(cur[%i], pos - ivec2(0, 2)); ,i); + GLSLF(3, prev2[2] = texture(cur[%i], pos); ,i); + GLSLF(3, prev2[3] = texture(cur[%i], pos + ivec2(0, 2)); ,i); + GLSLF(3, prev2[4] = texture(cur[%i], pos + ivec2(0, 4)); ,i); + GLSLC(0, ); + GLSLF(3, next2[0] = texture(next[%i], pos - ivec2(0, 4)); ,i); + GLSLF(3, next2[1] = texture(next[%i], pos - ivec2(0, 2)); ,i); + GLSLF(3, next2[2] = texture(next[%i], pos); ,i); + GLSLF(3, next2[3] = texture(next[%i], pos + ivec2(0, 2)); ,i); + GLSLF(3, next2[4] = texture(next[%i], pos + ivec2(0, 4)); ,i); + GLSLC(2, } ); + GLSLC(0, ); + GLSLC(2, res = process_line(prev2, prev1, dcur, next1, next2); ); + GLSLF(2, imageStore(dst[%i], pos, res); ,i); + GLSLC(1, } else { ); + GLSLF(2, res = texture(cur[%i], pos); ,i); + GLSLF(2, imageStore(dst[%i], pos, res); ,i); + GLSLC(1, } ); + } + + GLSLC(0, } ); + + RET(spv->compile_shader(spv, ctx, &s->shd, &spv_data, &spv_len, "main", + &spv_opaque)); + RET(ff_vk_shader_create(vkctx, &s->shd, spv_data, spv_len, "main")); + + RET(ff_vk_init_compute_pipeline(vkctx, &s->pl, &s->shd)); + RET(ff_vk_exec_pipeline_register(vkctx, &s->e, &s->pl)); + + s->initialized = 1; + + return 0; + +fail: + if (spv_opaque) + spv->free_shader(spv, &spv_opaque); + if (spv) + spv->uninit(&spv); + + return err; +} + +static void bwdif_vulkan_filter_frame(AVFilterContext *ctx, AVFrame *dst, + int parity, int tff) +{ + BWDIFVulkanContext *s = ctx->priv; + YADIFContext *y = &s->yadif; + BWDIFParameters params = { + .parity = parity, + .tff = tff, + .current_field = y->current_field, + }; + + ff_vk_filter_process_Nin(&s->vkctx, &s->e, &s->pl, dst, + (AVFrame *[]){ y->prev, y->cur, y->next }, 3, + s->sampler, ¶ms, sizeof(params)); + + if (y->current_field == YADIF_FIELD_END) + y->current_field = YADIF_FIELD_NORMAL; +} + +static void bwdif_vulkan_uninit(AVFilterContext *avctx) +{ + BWDIFVulkanContext *s = avctx->priv; + FFVulkanContext *vkctx = &s->vkctx; + FFVulkanFunctions *vk = &vkctx->vkfn; + + ff_vk_exec_pool_free(vkctx, &s->e); + ff_vk_pipeline_free(vkctx, &s->pl); + ff_vk_shader_free(vkctx, &s->shd); + + if (s->sampler) + vk->DestroySampler(vkctx->hwctx->act_dev, s->sampler, + vkctx->hwctx->alloc); + + ff_vk_uninit(&s->vkctx); + + s->initialized = 0; +} + +static int bwdif_vulkan_config_input(AVFilterLink *inlink) +{ + AVHWFramesContext *input_frames; + AVFilterContext *avctx = inlink->dst; + BWDIFVulkanContext *s = avctx->priv; + FFVulkanContext *vkctx = &s->vkctx; + + if (!inlink->hw_frames_ctx) { + av_log(inlink->dst, AV_LOG_ERROR, "Vulkan filtering requires a " + "hardware frames context on the input.\n"); + return AVERROR(EINVAL); + } + + input_frames = (AVHWFramesContext *)inlink->hw_frames_ctx->data; + if (input_frames->format != AV_PIX_FMT_VULKAN) + return AVERROR(EINVAL); + + /* Extract the device and default output format from the first input. */ + if (avctx->inputs[0] != inlink) + return 0; + + /* Save the ref, without reffing it */ + vkctx->input_frames_ref = inlink->hw_frames_ctx; + + /* Defaults */ + vkctx->output_format = input_frames->sw_format; + vkctx->output_width = input_frames->width; + vkctx->output_height = input_frames->height; + + return 0; +} + +static int bwdif_vulkan_config_output(AVFilterLink *outlink) +{ + int err; + AVFilterContext *avctx = outlink->src; + BWDIFVulkanContext *s = avctx->priv; + YADIFContext *y = &s->yadif; + FFVulkanContext *vkctx = &s->vkctx; + + av_buffer_unref(&outlink->hw_frames_ctx); + + err = ff_vk_filter_init_context(avctx, vkctx, vkctx->input_frames_ref, + vkctx->output_width, vkctx->output_height, + vkctx->output_format); + if (err < 0) + return err; + + /* For logging */ + vkctx->class = y->class; + + outlink->hw_frames_ctx = av_buffer_ref(vkctx->frames_ref); + if (!outlink->hw_frames_ctx) + return AVERROR(ENOMEM); + + outlink->time_base = av_mul_q(avctx->inputs[0]->time_base, (AVRational){1, 2}); + outlink->w = vkctx->output_width; + outlink->h = vkctx->output_height; + + if (y->mode & 1) + outlink->frame_rate = av_mul_q(avctx->inputs[0]->frame_rate, + (AVRational){2, 1}); + + if (outlink->w < 4 || outlink->h < 4) { + av_log(avctx, AV_LOG_ERROR, "Video of less than 4 columns or lines is not " + "supported\n"); + return AVERROR(EINVAL); + } + + y->csp = av_pix_fmt_desc_get(vkctx->frames->sw_format); + y->filter = bwdif_vulkan_filter_frame; + + return init_filter(avctx); +} + +static const AVClass bwdif_vulkan_class = { + .class_name = "bwdif_vulkan", + .item_name = av_default_item_name, + .option = ff_yadif_options, + .version = LIBAVUTIL_VERSION_INT, + .category = AV_CLASS_CATEGORY_FILTER, +}; + +static const AVFilterPad bwdif_vulkan_inputs[] = { + { + .name = "default", + .type = AVMEDIA_TYPE_VIDEO, + .filter_frame = ff_yadif_filter_frame, + .config_props = &bwdif_vulkan_config_input, + }, +}; + +static const AVFilterPad bwdif_vulkan_outputs[] = { + { + .name = "default", + .type = AVMEDIA_TYPE_VIDEO, + .request_frame = ff_yadif_request_frame, + .config_props = &bwdif_vulkan_config_output, + }, +}; + +const AVFilter ff_vf_bwdif_vulkan = { + .name = "bwdif_vulkan", + .description = NULL_IF_CONFIG_SMALL("Deinterlace Vulkan frames via bwdif"), + .priv_size = sizeof(BWDIFVulkanContext), + .init = &ff_vk_filter_init, + .uninit = &bwdif_vulkan_uninit, + FILTER_INPUTS(bwdif_vulkan_inputs), + FILTER_OUTPUTS(bwdif_vulkan_outputs), + FILTER_SINGLE_PIXFMT(AV_PIX_FMT_VULKAN), + .priv_class = &bwdif_vulkan_class, + .flags = AVFILTER_FLAG_HWDEVICE | + AVFILTER_FLAG_SUPPORT_TIMELINE_INTERNAL, + .flags_internal = FF_FILTER_FLAG_HWFRAME_AWARE, +}; From be07145109074e128bd7a8255d81a2b9fdcdf10b Mon Sep 17 00:00:00 2001 From: Lynne Date: Thu, 10 Mar 2022 18:03:05 +0100 Subject: [PATCH 1289/2172] avcodec: add AVHWAccel.free_frame_priv callback --- libavcodec/av1dec.c | 4 ++-- libavcodec/avcodec.h | 8 ++++++++ libavcodec/decode.c | 20 ++++++++++++++++++++ libavcodec/decode.h | 11 +++++++++++ libavcodec/h264_slice.c | 3 ++- libavcodec/hevc_refs.c | 3 ++- libavcodec/mpegpicture.c | 4 +++- libavcodec/vp8.c | 2 +- libavcodec/vp9.c | 2 +- 9 files changed, 50 insertions(+), 7 deletions(-) diff --git a/libavcodec/av1dec.c b/libavcodec/av1dec.c index 7de6ba0965c..3ab1a47d190 100644 --- a/libavcodec/av1dec.c +++ b/libavcodec/av1dec.c @@ -27,6 +27,7 @@ #include "libavutil/opt.h" #include "avcodec.h" #include "av1_parse.h" +#include "decode.h" #include "av1dec.h" #include "atsc_a53.h" #include "bytestream.h" @@ -865,8 +866,7 @@ static int av1_frame_alloc(AVCodecContext *avctx, AV1Frame *f) if (avctx->hwaccel) { const AVHWAccel *hwaccel = avctx->hwaccel; if (hwaccel->frame_priv_data_size) { - f->hwaccel_priv_buf = - av_buffer_allocz(hwaccel->frame_priv_data_size); + f->hwaccel_priv_buf = ff_hwaccel_frame_priv_alloc(avctx, hwaccel); if (!f->hwaccel_priv_buf) { ret = AVERROR(ENOMEM); goto fail; diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h index dad443c8185..82c9aaab534 100644 --- a/libavcodec/avcodec.h +++ b/libavcodec/avcodec.h @@ -2259,6 +2259,14 @@ typedef struct AVHWAccel { * For thread-safe hwaccels only. */ int (*update_thread_context)(AVCodecContext *dst, const AVCodecContext *src); + + /** + * Callback to free the hwaccel-specific frame data. + * + * @param hwctx a pointer to an AVHWDeviceContext. + * @param data the per-frame hardware accelerator private data to be freed. + */ + void (*free_frame_priv)(void *hwctx, uint8_t *data); } AVHWAccel; /** diff --git a/libavcodec/decode.c b/libavcodec/decode.c index 9ff132a15c3..a7c130207c1 100644 --- a/libavcodec/decode.c +++ b/libavcodec/decode.c @@ -1718,3 +1718,23 @@ int ff_copy_palette(void *dst, const AVPacket *src, void *logctx) } return 0; } + +AVBufferRef *ff_hwaccel_frame_priv_alloc(AVCodecContext *avctx, + const AVHWAccel *hwaccel) +{ + AVBufferRef *ref; + AVHWFramesContext *frames_ctx = (AVHWFramesContext *)avctx->hw_frames_ctx->data; + uint8_t *data = av_mallocz(hwaccel->frame_priv_data_size); + if (!data) + return NULL; + + ref = av_buffer_create(data, hwaccel->frame_priv_data_size, + hwaccel->free_frame_priv, + frames_ctx->device_ctx, 0); + if (!ref) { + av_free(data); + return NULL; + } + + return ref; +} diff --git a/libavcodec/decode.h b/libavcodec/decode.h index 8430ffbd664..aaa29bc7f52 100644 --- a/libavcodec/decode.h +++ b/libavcodec/decode.h @@ -150,4 +150,15 @@ int ff_reget_buffer(AVCodecContext *avctx, AVFrame *frame, int flags); int ff_side_data_update_matrix_encoding(AVFrame *frame, enum AVMatrixEncoding matrix_encoding); +/** + * Allocate a hwaccel frame private data and create an AVBufferRef + * from it. + * + * @param avctx The codec context which to attach as an opaque value + * @param hwaccel The hwaccel for which to allocate + * @return The allocated buffer + */ +AVBufferRef *ff_hwaccel_frame_priv_alloc(AVCodecContext *avctx, + const AVHWAccel *hwaccel); + #endif /* AVCODEC_DECODE_H */ diff --git a/libavcodec/h264_slice.c b/libavcodec/h264_slice.c index be7a8e0b5ab..d715cbb002a 100644 --- a/libavcodec/h264_slice.c +++ b/libavcodec/h264_slice.c @@ -33,6 +33,7 @@ #include "libavutil/pixdesc.h" #include "libavutil/timecode.h" #include "internal.h" +#include "decode.h" #include "cabac.h" #include "cabac_functions.h" #include "decode.h" @@ -212,7 +213,7 @@ static int alloc_picture(H264Context *h, H264Picture *pic) const AVHWAccel *hwaccel = h->avctx->hwaccel; av_assert0(!pic->hwaccel_picture_private); if (hwaccel->frame_priv_data_size) { - pic->hwaccel_priv_buf = av_buffer_allocz(hwaccel->frame_priv_data_size); + pic->hwaccel_priv_buf = ff_hwaccel_frame_priv_alloc(h->avctx, hwaccel); if (!pic->hwaccel_priv_buf) return AVERROR(ENOMEM); pic->hwaccel_picture_private = pic->hwaccel_priv_buf->data; diff --git a/libavcodec/hevc_refs.c b/libavcodec/hevc_refs.c index e9be02c4892..a4af6ca6568 100644 --- a/libavcodec/hevc_refs.c +++ b/libavcodec/hevc_refs.c @@ -23,6 +23,7 @@ #include "libavutil/avassert.h" +#include "decode.h" #include "thread.h" #include "hevc.h" #include "hevcdec.h" @@ -121,7 +122,7 @@ static HEVCFrame *alloc_frame(HEVCContext *s) const AVHWAccel *hwaccel = s->avctx->hwaccel; av_assert0(!frame->hwaccel_picture_private); if (hwaccel->frame_priv_data_size) { - frame->hwaccel_priv_buf = av_buffer_allocz(hwaccel->frame_priv_data_size); + frame->hwaccel_priv_buf = ff_hwaccel_frame_priv_alloc(s->avctx, hwaccel); if (!frame->hwaccel_priv_buf) goto fail; frame->hwaccel_picture_private = frame->hwaccel_priv_buf->data; diff --git a/libavcodec/mpegpicture.c b/libavcodec/mpegpicture.c index 3204a70578c..71c7a3fd706 100644 --- a/libavcodec/mpegpicture.c +++ b/libavcodec/mpegpicture.c @@ -27,6 +27,8 @@ #include "avcodec.h" #include "encode.h" +#include "internal.h" +#include "decode.h" #include "motion_est.h" #include "mpegpicture.h" #include "mpegutils.h" @@ -172,7 +174,7 @@ static int alloc_frame_buffer(AVCodecContext *avctx, Picture *pic, if (avctx->hwaccel) { assert(!pic->hwaccel_picture_private); if (avctx->hwaccel->frame_priv_data_size) { - pic->hwaccel_priv_buf = av_buffer_allocz(avctx->hwaccel->frame_priv_data_size); + pic->hwaccel_priv_buf = ff_hwaccel_frame_priv_alloc(avctx, avctx->hwaccel); if (!pic->hwaccel_priv_buf) { av_log(avctx, AV_LOG_ERROR, "alloc_frame_buffer() failed (hwaccel private data allocation)\n"); return -1; diff --git a/libavcodec/vp8.c b/libavcodec/vp8.c index 2ab06c82939..b410e0eb79f 100644 --- a/libavcodec/vp8.c +++ b/libavcodec/vp8.c @@ -109,7 +109,7 @@ static int vp8_alloc_frame(VP8Context *s, VP8Frame *f, int ref) if (s->avctx->hwaccel) { const AVHWAccel *hwaccel = s->avctx->hwaccel; if (hwaccel->frame_priv_data_size) { - f->hwaccel_priv_buf = av_buffer_allocz(hwaccel->frame_priv_data_size); + f->hwaccel_priv_buf = ff_hwaccel_frame_priv_alloc(s->avctx, hwaccel); if (!f->hwaccel_priv_buf) goto fail; f->hwaccel_picture_private = f->hwaccel_priv_buf->data; diff --git a/libavcodec/vp9.c b/libavcodec/vp9.c index d8a31507fa5..03883d254b9 100644 --- a/libavcodec/vp9.c +++ b/libavcodec/vp9.c @@ -136,7 +136,7 @@ static int vp9_frame_alloc(AVCodecContext *avctx, VP9Frame *f) const AVHWAccel *hwaccel = avctx->hwaccel; av_assert0(!f->hwaccel_picture_private); if (hwaccel->frame_priv_data_size) { - f->hwaccel_priv_buf = av_buffer_allocz(hwaccel->frame_priv_data_size); + f->hwaccel_priv_buf = ff_hwaccel_frame_priv_alloc(avctx, hwaccel); if (!f->hwaccel_priv_buf) goto fail; f->hwaccel_picture_private = f->hwaccel_priv_buf->data; From 6733a1a456b1720ec58f83c21352d54406229102 Mon Sep 17 00:00:00 2001 From: Lynne Date: Fri, 6 Jan 2023 03:32:56 +0100 Subject: [PATCH 1290/2172] avcodec: add AVHWAccel.flush callback --- libavcodec/av1dec.c | 3 +++ libavcodec/avcodec.h | 5 +++++ libavcodec/h264dec.c | 3 +++ libavcodec/hevcdec.c | 3 +++ libavcodec/vp8.c | 3 +++ libavcodec/vp9.c | 3 +++ 6 files changed, 20 insertions(+) diff --git a/libavcodec/av1dec.c b/libavcodec/av1dec.c index 3ab1a47d190..7e423427b2f 100644 --- a/libavcodec/av1dec.c +++ b/libavcodec/av1dec.c @@ -1452,6 +1452,9 @@ static void av1_decode_flush(AVCodecContext *avctx) ff_cbs_fragment_reset(&s->current_obu); ff_cbs_flush(s->cbc); + + if (avctx->hwaccel && avctx->hwaccel->flush) + avctx->hwaccel->flush(avctx); } #define OFFSET(x) offsetof(AV1DecContext, x) diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h index 82c9aaab534..84e29a02dbc 100644 --- a/libavcodec/avcodec.h +++ b/libavcodec/avcodec.h @@ -2267,6 +2267,11 @@ typedef struct AVHWAccel { * @param data the per-frame hardware accelerator private data to be freed. */ void (*free_frame_priv)(void *hwctx, uint8_t *data); + + /** + * Callback to flush the hwaccel state. + */ + void (*flush)(AVCodecContext *avctx); } AVHWAccel; /** diff --git a/libavcodec/h264dec.c b/libavcodec/h264dec.c index 521b1e2235d..a10b4bb85cf 100644 --- a/libavcodec/h264dec.c +++ b/libavcodec/h264dec.c @@ -484,6 +484,9 @@ static void h264_decode_flush(AVCodecContext *avctx) ff_h264_free_tables(h); h->context_initialized = 0; + + if (avctx->hwaccel && avctx->hwaccel->flush) + avctx->hwaccel->flush(avctx); } static int get_last_needed_nal(H264Context *h) diff --git a/libavcodec/hevcdec.c b/libavcodec/hevcdec.c index b01563177b8..8764e0bd83e 100644 --- a/libavcodec/hevcdec.c +++ b/libavcodec/hevcdec.c @@ -3708,6 +3708,9 @@ static void hevc_decode_flush(AVCodecContext *avctx) av_buffer_unref(&s->rpu_buf); s->max_ra = INT_MAX; s->eos = 1; + + if (avctx->hwaccel && avctx->hwaccel->flush) + avctx->hwaccel->flush(avctx); } #define OFFSET(x) offsetof(HEVCContext, x) diff --git a/libavcodec/vp8.c b/libavcodec/vp8.c index b410e0eb79f..50afe19b7a5 100644 --- a/libavcodec/vp8.c +++ b/libavcodec/vp8.c @@ -167,6 +167,9 @@ static void vp8_decode_flush_impl(AVCodecContext *avctx, int free_mem) if (free_mem) free_buffers(s); + + if (avctx->hwaccel && avctx->hwaccel->flush) + avctx->hwaccel->flush(avctx); } static void vp8_decode_flush(AVCodecContext *avctx) diff --git a/libavcodec/vp9.c b/libavcodec/vp9.c index 03883d254b9..4f704ec0dd1 100644 --- a/libavcodec/vp9.c +++ b/libavcodec/vp9.c @@ -1801,6 +1801,9 @@ static void vp9_decode_flush(AVCodecContext *avctx) vp9_frame_unref(avctx, &s->s.frames[i]); for (i = 0; i < 8; i++) ff_thread_release_ext_buffer(avctx, &s->s.refs[i]); + + if (avctx->hwaccel && avctx->hwaccel->flush) + avctx->hwaccel->flush(avctx); } static av_cold int vp9_decode_init(AVCodecContext *avctx) From 023ae6103f0e0db1610ef3988290e37fea47661d Mon Sep 17 00:00:00 2001 From: Lynne Date: Sun, 18 Dec 2022 08:31:03 +0100 Subject: [PATCH 1291/2172] libavcodec: add Vulkan common video code --- configure | 2 +- libavcodec/Makefile | 2 + libavcodec/hwconfig.h | 2 + libavcodec/vulkan.c | 19 ++ libavcodec/vulkan.h | 24 +++ libavcodec/vulkan_video.c | 361 ++++++++++++++++++++++++++++++++++++++ libavcodec/vulkan_video.h | 97 ++++++++++ 7 files changed, 506 insertions(+), 1 deletion(-) create mode 100644 libavcodec/vulkan.c create mode 100644 libavcodec/vulkan.h create mode 100644 libavcodec/vulkan_video.c create mode 100644 libavcodec/vulkan_video.h diff --git a/configure b/configure index 84668dd4f9d..43c02ecb220 100755 --- a/configure +++ b/configure @@ -327,7 +327,6 @@ 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] - --disable-vulkan disable Vulkan code [autodetect] --disable-xlib disable xlib [autodetect] --disable-zlib disable zlib [autodetect] @@ -354,6 +353,7 @@ External library support: --disable-vaapi disable Video Acceleration API (mainly Unix/Intel) code [autodetect] --disable-vdpau disable Nvidia Video Decode and Presentation API for Unix code [autodetect] --disable-videotoolbox disable VideoToolbox code [autodetect] + --disable-vulkan disable Vulkan code [autodetect] Toolchain options: --arch=ARCH select architecture [$arch] diff --git a/libavcodec/Makefile b/libavcodec/Makefile index 9c38240025c..8580d4ca1d7 100644 --- a/libavcodec/Makefile +++ b/libavcodec/Makefile @@ -982,6 +982,7 @@ OBJS-$(CONFIG_NVDEC) += nvdec.o OBJS-$(CONFIG_VAAPI) += vaapi_decode.o OBJS-$(CONFIG_VIDEOTOOLBOX) += videotoolbox.o OBJS-$(CONFIG_VDPAU) += vdpau.o +OBJS-$(CONFIG_VULKAN) += vulkan.o vulkan_video.o OBJS-$(CONFIG_AV1_D3D11VA_HWACCEL) += dxva2_av1.o OBJS-$(CONFIG_AV1_DXVA2_HWACCEL) += dxva2_av1.o @@ -1290,6 +1291,7 @@ SKIPHEADERS-$(CONFIG_XVMC) += xvmc.h SKIPHEADERS-$(CONFIG_VAAPI) += vaapi_decode.h vaapi_hevc.h vaapi_encode.h SKIPHEADERS-$(CONFIG_VDPAU) += vdpau.h vdpau_internal.h SKIPHEADERS-$(CONFIG_VIDEOTOOLBOX) += videotoolbox.h vt_internal.h +SKIPHEADERS-$(CONFIG_VULKAN) += vulkan.h vulkan_video.h SKIPHEADERS-$(CONFIG_V4L2_M2M) += v4l2_buffers.h v4l2_context.h v4l2_m2m.h SKIPHEADERS-$(CONFIG_ZLIB) += zlib_wrapper.h diff --git a/libavcodec/hwconfig.h b/libavcodec/hwconfig.h index d88dc37c8c9..e8c6186151d 100644 --- a/libavcodec/hwconfig.h +++ b/libavcodec/hwconfig.h @@ -78,6 +78,8 @@ void ff_hwaccel_uninit(AVCodecContext *avctx); HW_CONFIG_HWACCEL(1, 1, 1, VDPAU, VDPAU, ff_ ## codec ## _vdpau_hwaccel) #define HWACCEL_VIDEOTOOLBOX(codec) \ HW_CONFIG_HWACCEL(1, 1, 1, VIDEOTOOLBOX, VIDEOTOOLBOX, ff_ ## codec ## _videotoolbox_hwaccel) +#define HWACCEL_VULKAN(codec) \ + HW_CONFIG_HWACCEL(1, 1, 1, VULKAN, VULKAN, ff_ ## codec ## _vulkan_hwaccel) #define HWACCEL_D3D11VA(codec) \ HW_CONFIG_HWACCEL(0, 0, 1, D3D11VA_VLD, NONE, ff_ ## codec ## _d3d11va_hwaccel) diff --git a/libavcodec/vulkan.c b/libavcodec/vulkan.c new file mode 100644 index 00000000000..fc8a1fa47ba --- /dev/null +++ b/libavcodec/vulkan.c @@ -0,0 +1,19 @@ +/* + * 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.c" diff --git a/libavcodec/vulkan.h b/libavcodec/vulkan.h new file mode 100644 index 00000000000..b15efd4addb --- /dev/null +++ b/libavcodec/vulkan.h @@ -0,0 +1,24 @@ +/* + * 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_VULKAN_H +#define AVCODEC_VULKAN_H + +#include "libavutil/vulkan.h" + +#endif /* AVCODEC_VULKAN_H */ diff --git a/libavcodec/vulkan_video.c b/libavcodec/vulkan_video.c new file mode 100644 index 00000000000..5fb867df874 --- /dev/null +++ b/libavcodec/vulkan_video.c @@ -0,0 +1,361 @@ +/* + * 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 "codec_id.h" + +#include "vulkan_video.h" + +const FFVkCodecMap ff_vk_codec_map[AV_CODEC_ID_FIRST_AUDIO] = { + [AV_CODEC_ID_H264] = { + 0, + 0, + FF_VK_EXT_VIDEO_DECODE_H264, + VK_VIDEO_CODEC_OPERATION_DECODE_H264_BIT_KHR, + }, + [AV_CODEC_ID_HEVC] = { + 0, + 0, + FF_VK_EXT_VIDEO_DECODE_H265, + VK_VIDEO_CODEC_OPERATION_DECODE_H265_BIT_KHR + }, +}; + +#define ASPECT_2PLANE (VK_IMAGE_ASPECT_PLANE_0_BIT | VK_IMAGE_ASPECT_PLANE_1_BIT) +#define ASPECT_3PLANE (VK_IMAGE_ASPECT_PLANE_0_BIT | VK_IMAGE_ASPECT_PLANE_1_BIT | VK_IMAGE_ASPECT_PLANE_2_BIT) + +static const struct FFVkFormatMapEntry { + VkFormat vkf; + enum AVPixelFormat pixfmt; + VkImageAspectFlags aspect; +} vk_format_map[] = { + /* Gray formats */ + { VK_FORMAT_R8_UNORM, AV_PIX_FMT_GRAY8, VK_IMAGE_ASPECT_COLOR_BIT }, + { VK_FORMAT_R16_UNORM, AV_PIX_FMT_GRAY16, VK_IMAGE_ASPECT_COLOR_BIT }, + { VK_FORMAT_R32_SFLOAT, AV_PIX_FMT_GRAYF32, VK_IMAGE_ASPECT_COLOR_BIT }, + + /* RGB formats */ + { VK_FORMAT_R16G16B16A16_UNORM, AV_PIX_FMT_XV36, VK_IMAGE_ASPECT_COLOR_BIT }, + { VK_FORMAT_B8G8R8A8_UNORM, AV_PIX_FMT_BGRA, VK_IMAGE_ASPECT_COLOR_BIT }, + { VK_FORMAT_R8G8B8A8_UNORM, AV_PIX_FMT_RGBA, VK_IMAGE_ASPECT_COLOR_BIT }, + { VK_FORMAT_R8G8B8_UNORM, AV_PIX_FMT_RGB24, VK_IMAGE_ASPECT_COLOR_BIT }, + { VK_FORMAT_B8G8R8_UNORM, AV_PIX_FMT_BGR24, VK_IMAGE_ASPECT_COLOR_BIT }, + { VK_FORMAT_R16G16B16_UNORM, AV_PIX_FMT_RGB48, VK_IMAGE_ASPECT_COLOR_BIT }, + { VK_FORMAT_R16G16B16A16_UNORM, AV_PIX_FMT_RGBA64, VK_IMAGE_ASPECT_COLOR_BIT }, + { VK_FORMAT_R5G6B5_UNORM_PACK16, AV_PIX_FMT_RGB565, VK_IMAGE_ASPECT_COLOR_BIT }, + { VK_FORMAT_B5G6R5_UNORM_PACK16, AV_PIX_FMT_BGR565, VK_IMAGE_ASPECT_COLOR_BIT }, + { VK_FORMAT_B8G8R8A8_UNORM, AV_PIX_FMT_BGR0, VK_IMAGE_ASPECT_COLOR_BIT }, + { VK_FORMAT_R8G8B8A8_UNORM, AV_PIX_FMT_RGB0, VK_IMAGE_ASPECT_COLOR_BIT }, + { VK_FORMAT_A2R10G10B10_UNORM_PACK32, AV_PIX_FMT_X2RGB10, VK_IMAGE_ASPECT_COLOR_BIT }, + + /* Planar RGB */ + { VK_FORMAT_R8_UNORM, AV_PIX_FMT_GBRAP, VK_IMAGE_ASPECT_COLOR_BIT }, + { VK_FORMAT_R16_UNORM, AV_PIX_FMT_GBRAP16, VK_IMAGE_ASPECT_COLOR_BIT }, + { VK_FORMAT_R32_SFLOAT, AV_PIX_FMT_GBRPF32, VK_IMAGE_ASPECT_COLOR_BIT }, + { VK_FORMAT_R32_SFLOAT, AV_PIX_FMT_GBRAPF32, VK_IMAGE_ASPECT_COLOR_BIT }, + + /* Two-plane 420 YUV at 8, 10, 12 and 16 bits */ + { VK_FORMAT_G8_B8R8_2PLANE_420_UNORM, AV_PIX_FMT_NV12, ASPECT_2PLANE }, + { VK_FORMAT_G10X6_B10X6R10X6_2PLANE_420_UNORM_3PACK16, AV_PIX_FMT_P010, ASPECT_2PLANE }, + { VK_FORMAT_G12X4_B12X4R12X4_2PLANE_420_UNORM_3PACK16, AV_PIX_FMT_P012, ASPECT_2PLANE }, + { VK_FORMAT_G16_B16R16_2PLANE_420_UNORM, AV_PIX_FMT_P016, ASPECT_2PLANE }, + + /* Two-plane 422 YUV at 8, 10 and 16 bits */ + { VK_FORMAT_G8_B8R8_2PLANE_422_UNORM, AV_PIX_FMT_NV16, ASPECT_2PLANE }, + { VK_FORMAT_G10X6_B10X6R10X6_2PLANE_422_UNORM_3PACK16, AV_PIX_FMT_P210, ASPECT_2PLANE }, + { VK_FORMAT_G12X4_B12X4R12X4_2PLANE_422_UNORM_3PACK16, AV_PIX_FMT_P212, ASPECT_2PLANE }, + { VK_FORMAT_G16_B16R16_2PLANE_422_UNORM, AV_PIX_FMT_P216, ASPECT_2PLANE }, + + /* Two-plane 444 YUV at 8, 10 and 16 bits */ + { VK_FORMAT_G8_B8R8_2PLANE_444_UNORM, AV_PIX_FMT_NV24, ASPECT_2PLANE }, + { VK_FORMAT_G10X6_B10X6R10X6_2PLANE_444_UNORM_3PACK16, AV_PIX_FMT_P410, ASPECT_2PLANE }, + { VK_FORMAT_G12X4_B12X4R12X4_2PLANE_444_UNORM_3PACK16, AV_PIX_FMT_P412, ASPECT_2PLANE }, + { VK_FORMAT_G16_B16R16_2PLANE_444_UNORM, AV_PIX_FMT_P416, ASPECT_2PLANE }, + + /* Three-plane 420, 422, 444 at 8, 10, 12 and 16 bits */ + { VK_FORMAT_G8_B8_R8_3PLANE_420_UNORM, AV_PIX_FMT_YUV420P, ASPECT_3PLANE }, + { VK_FORMAT_G16_B16_R16_3PLANE_420_UNORM, AV_PIX_FMT_YUV420P10, ASPECT_3PLANE }, + { VK_FORMAT_G16_B16_R16_3PLANE_420_UNORM, AV_PIX_FMT_YUV420P12, ASPECT_3PLANE }, + { VK_FORMAT_G16_B16_R16_3PLANE_420_UNORM, AV_PIX_FMT_YUV420P16, ASPECT_3PLANE }, + { VK_FORMAT_G8_B8_R8_3PLANE_422_UNORM, AV_PIX_FMT_YUV422P, ASPECT_3PLANE }, + { VK_FORMAT_G16_B16_R16_3PLANE_422_UNORM, AV_PIX_FMT_YUV422P10, ASPECT_3PLANE }, + { VK_FORMAT_G16_B16_R16_3PLANE_422_UNORM, AV_PIX_FMT_YUV422P12, ASPECT_3PLANE }, + { VK_FORMAT_G16_B16_R16_3PLANE_422_UNORM, AV_PIX_FMT_YUV422P16, ASPECT_3PLANE }, + { VK_FORMAT_G8_B8_R8_3PLANE_444_UNORM, AV_PIX_FMT_YUV444P, ASPECT_3PLANE }, + { VK_FORMAT_G16_B16_R16_3PLANE_444_UNORM, AV_PIX_FMT_YUV444P10, ASPECT_3PLANE }, + { VK_FORMAT_G16_B16_R16_3PLANE_444_UNORM, AV_PIX_FMT_YUV444P12, ASPECT_3PLANE }, + { VK_FORMAT_G16_B16_R16_3PLANE_444_UNORM, AV_PIX_FMT_YUV444P16, ASPECT_3PLANE }, + + /* Single plane 422 at 8, 10 and 12 bits */ + { VK_FORMAT_G8B8G8R8_422_UNORM, AV_PIX_FMT_YUYV422, VK_IMAGE_ASPECT_COLOR_BIT }, + { VK_FORMAT_B8G8R8G8_422_UNORM, AV_PIX_FMT_UYVY422, VK_IMAGE_ASPECT_COLOR_BIT }, + { VK_FORMAT_G10X6B10X6G10X6R10X6_422_UNORM_4PACK16, AV_PIX_FMT_Y210, VK_IMAGE_ASPECT_COLOR_BIT }, + { VK_FORMAT_G12X4B12X4G12X4R12X4_422_UNORM_4PACK16, AV_PIX_FMT_Y212, VK_IMAGE_ASPECT_COLOR_BIT }, +}; +static const int nb_vk_format_map = FF_ARRAY_ELEMS(vk_format_map); + +enum AVPixelFormat ff_vk_pix_fmt_from_vkfmt(VkFormat vkf) +{ + for (int i = 0; i < nb_vk_format_map; i++) + if (vk_format_map[i].vkf == vkf) + return vk_format_map[i].pixfmt; + return AV_PIX_FMT_NONE; +} + +VkImageAspectFlags ff_vk_aspect_bits_from_vkfmt(VkFormat vkf) +{ + for (int i = 0; i < nb_vk_format_map; i++) + if (vk_format_map[i].vkf == vkf) + return vk_format_map[i].aspect; + return VK_IMAGE_ASPECT_NONE; +} + +VkVideoChromaSubsamplingFlagBitsKHR ff_vk_subsampling_from_av_desc(const AVPixFmtDescriptor *desc) +{ + if (desc->nb_components == 1) + return VK_VIDEO_CHROMA_SUBSAMPLING_MONOCHROME_BIT_KHR; + else if (!desc->log2_chroma_w && !desc->log2_chroma_h) + return VK_VIDEO_CHROMA_SUBSAMPLING_444_BIT_KHR; + else if (!desc->log2_chroma_w && desc->log2_chroma_h == 1) + return VK_VIDEO_CHROMA_SUBSAMPLING_422_BIT_KHR; + else if (desc->log2_chroma_w == 1 && desc->log2_chroma_h == 1) + return VK_VIDEO_CHROMA_SUBSAMPLING_420_BIT_KHR; + return VK_VIDEO_CHROMA_SUBSAMPLING_INVALID_KHR; +} + +VkVideoComponentBitDepthFlagBitsKHR ff_vk_depth_from_av_depth(int depth) +{ + switch (depth) { + case 8: return VK_VIDEO_COMPONENT_BIT_DEPTH_8_BIT_KHR; + case 10: return VK_VIDEO_COMPONENT_BIT_DEPTH_10_BIT_KHR; + case 12: return VK_VIDEO_COMPONENT_BIT_DEPTH_12_BIT_KHR; + default: break; + } + return VK_VIDEO_COMPONENT_BIT_DEPTH_INVALID_KHR; +} + +static void free_data_buf(void *opaque, uint8_t *data) +{ + FFVulkanContext *ctx = opaque; + FFVkVideoBuffer *buf = (FFVkVideoBuffer *)data; + ff_vk_unmap_buffer(ctx, &buf->buf, 0); + ff_vk_free_buf(ctx, &buf->buf); + av_free(data); +} + +static AVBufferRef *alloc_data_buf(void *opaque, size_t size) +{ + AVBufferRef *ref; + uint8_t *buf = av_mallocz(size); + if (!buf) + return NULL; + + ref = av_buffer_create(buf, size, free_data_buf, opaque, 0); + if (!ref) + av_free(buf); + return ref; +} + +int ff_vk_video_get_buffer(FFVulkanContext *ctx, FFVkVideoCommon *s, + AVBufferRef **buf, VkBufferUsageFlags usage, + void *create_pNext, size_t size) +{ + int err; + AVBufferRef *ref; + FFVkVideoBuffer *data; + + if (!s->buf_pool) { + s->buf_pool = av_buffer_pool_init2(sizeof(FFVkVideoBuffer), ctx, + alloc_data_buf, NULL); + if (!s->buf_pool) + return AVERROR(ENOMEM); + } + + *buf = ref = av_buffer_pool_get(s->buf_pool); + if (!ref) + return AVERROR(ENOMEM); + + data = (FFVkVideoBuffer *)ref->data; + + if (data->buf.size >= size) + return 0; + + /* No point in requesting anything smaller. */ + size = FFMAX(size, 1024*1024); + + /* Align buffer to nearest power of two. Makes fragmentation management + * easier, and gives us ample headroom. */ + size--; + size |= size >> 1; + size |= size >> 2; + size |= size >> 4; + size |= size >> 8; + size |= size >> 16; + size++; + + ff_vk_free_buf(ctx, &data->buf); + memset(data, 0, sizeof(FFVkVideoBuffer)); + + err = ff_vk_create_buf(ctx, &data->buf, size, + create_pNext, NULL, usage, + VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT); + if (err < 0) { + av_buffer_unref(&ref); + return err; + } + + /* Map the buffer */ + err = ff_vk_map_buffer(ctx, &data->buf, &data->mem, 0); + if (err < 0) { + av_buffer_unref(&ref); + return err; + } + + return 0; +} + +av_cold void ff_vk_video_common_uninit(FFVulkanContext *s, + FFVkVideoCommon *common) +{ + FFVulkanFunctions *vk = &s->vkfn; + + if (common->session) { + vk->DestroyVideoSessionKHR(s->hwctx->act_dev, common->session, + s->hwctx->alloc); + common->session = NULL; + } + + if (common->nb_mem && common->mem) + for (int i = 0; i < common->nb_mem; i++) + vk->FreeMemory(s->hwctx->act_dev, common->mem[i], s->hwctx->alloc); + + av_freep(&common->mem); + + av_buffer_pool_uninit(&common->buf_pool); +} + +av_cold int ff_vk_video_common_init(void *log, FFVulkanContext *s, + FFVkVideoCommon *common, + VkVideoSessionCreateInfoKHR *session_create) +{ + int err; + VkResult ret; + FFVulkanFunctions *vk = &s->vkfn; + VkMemoryRequirements2 *mem_req = NULL; + VkVideoSessionMemoryRequirementsKHR *mem = NULL; + VkBindVideoSessionMemoryInfoKHR *bind_mem = NULL; + + /* Create session */ + ret = vk->CreateVideoSessionKHR(s->hwctx->act_dev, session_create, + s->hwctx->alloc, &common->session); + if (ret != VK_SUCCESS) + return AVERROR_EXTERNAL; + + /* Get memory requirements */ + ret = vk->GetVideoSessionMemoryRequirementsKHR(s->hwctx->act_dev, + common->session, + &common->nb_mem, + NULL); + if (ret != VK_SUCCESS) { + err = AVERROR_EXTERNAL; + goto fail; + } + + /* Allocate all memory needed to actually allocate memory */ + common->mem = av_mallocz(sizeof(*common->mem)*common->nb_mem); + if (!common->mem) { + err = AVERROR(ENOMEM); + goto fail; + } + mem = av_mallocz(sizeof(*mem)*common->nb_mem); + if (!mem) { + err = AVERROR(ENOMEM); + goto fail; + } + mem_req = av_mallocz(sizeof(*mem_req)*common->nb_mem); + if (!mem_req) { + err = AVERROR(ENOMEM); + goto fail; + } + bind_mem = av_mallocz(sizeof(*bind_mem)*common->nb_mem); + if (!bind_mem) { + err = AVERROR(ENOMEM); + goto fail; + } + + /* Set the needed fields to get the memory requirements */ + for (int i = 0; i < common->nb_mem; i++) { + mem_req[i] = (VkMemoryRequirements2) { + .sType = VK_STRUCTURE_TYPE_MEMORY_REQUIREMENTS_2, + }; + mem[i] = (VkVideoSessionMemoryRequirementsKHR) { + .sType = VK_STRUCTURE_TYPE_VIDEO_SESSION_MEMORY_REQUIREMENTS_KHR, + .memoryRequirements = mem_req[i].memoryRequirements, + }; + } + + /* Finally get the memory requirements */ + ret = vk->GetVideoSessionMemoryRequirementsKHR(s->hwctx->act_dev, + common->session, &common->nb_mem, + mem); + if (ret != VK_SUCCESS) { + err = AVERROR_EXTERNAL; + goto fail; + } + + /* Now allocate each requested memory. + * For ricing, could pool together memory that ends up in the same index. */ + for (int i = 0; i < common->nb_mem; i++) { + err = ff_vk_alloc_mem(s, &mem[i].memoryRequirements, + UINT32_MAX, NULL, NULL, &common->mem[i]); + if (err < 0) + goto fail; + + bind_mem[i] = (VkBindVideoSessionMemoryInfoKHR) { + .sType = VK_STRUCTURE_TYPE_BIND_VIDEO_SESSION_MEMORY_INFO_KHR, + .memory = common->mem[i], + .memoryBindIndex = mem[i].memoryBindIndex, + .memoryOffset = 0, + .memorySize = mem[i].memoryRequirements.size, + }; + + av_log(log, AV_LOG_VERBOSE, "Allocating %lu bytes in bind index %i for video session\n", + bind_mem[i].memorySize, bind_mem[i].memoryBindIndex); + } + + /* Bind the allocated memory */ + ret = vk->BindVideoSessionMemoryKHR(s->hwctx->act_dev, common->session, + common->nb_mem, bind_mem); + if (ret != VK_SUCCESS) { + err = AVERROR_EXTERNAL; + goto fail; + } + + av_freep(&mem); + av_freep(&mem_req); + av_freep(&bind_mem); + + return 0; + +fail: + av_freep(&mem); + av_freep(&mem_req); + av_freep(&bind_mem); + + ff_vk_video_common_uninit(s, common); + return err; +} diff --git a/libavcodec/vulkan_video.h b/libavcodec/vulkan_video.h new file mode 100644 index 00000000000..b4adde4ec1f --- /dev/null +++ b/libavcodec/vulkan_video.h @@ -0,0 +1,97 @@ +/* + * 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_VULKAN_VIDEO_H +#define AVCODEC_VULKAN_VIDEO_H + +#include "codec_id.h" +#include "vulkan.h" + +#include + +#define CODEC_VER_MAJ(ver) (ver >> 22) +#define CODEC_VER_MIN(ver) ((ver >> 12) & ((1 << 10) - 1)) +#define CODEC_VER_PAT(ver) (ver & ((1 << 12) - 1)) +#define CODEC_VER(ver) CODEC_VER_MAJ(ver), CODEC_VER_MIN(ver), CODEC_VER_PAT(ver) + +typedef struct FFVkCodecMap { + FFVulkanExtensions encode_extension; + VkVideoCodecOperationFlagBitsKHR encode_op; + FFVulkanExtensions decode_extension; + VkVideoCodecOperationFlagBitsKHR decode_op; +} FFVkCodecMap; + +typedef struct FFVkVideoSession { + VkVideoSessionKHR session; + VkDeviceMemory *mem; + uint32_t nb_mem; + + AVBufferPool *buf_pool; +} FFVkVideoCommon; + +/** + * Index is codec_id. + */ +extern const FFVkCodecMap ff_vk_codec_map[AV_CODEC_ID_FIRST_AUDIO]; + +/** + * Get pixfmt from a Vulkan format. + */ +enum AVPixelFormat ff_vk_pix_fmt_from_vkfmt(VkFormat vkf); + +/** + * Get aspect bits which include all planes from a VkFormat. + */ +VkImageAspectFlags ff_vk_aspect_bits_from_vkfmt(VkFormat vkf); + +/** + * Get Vulkan's chroma subsampling from a pixfmt descriptor. + */ +VkVideoChromaSubsamplingFlagBitsKHR ff_vk_subsampling_from_av_desc(const AVPixFmtDescriptor *desc); + +/** + * Get Vulkan's bit depth from an [8:12] integer. + */ +VkVideoComponentBitDepthFlagBitsKHR ff_vk_depth_from_av_depth(int depth); + +typedef struct FFVkVideoBuffer { + FFVkBuffer buf; + uint8_t *mem; +} FFVkVideoBuffer; + +/** + * Get a mapped FFVkPooledBuffer with a specific guaranteed minimum size + * from a pool. + */ +int ff_vk_video_get_buffer(FFVulkanContext *ctx, FFVkVideoCommon *s, + AVBufferRef **buf, VkBufferUsageFlags usage, + void *create_pNext, size_t size); + +/** + * Initialize video session, allocating and binding necessary memory. + */ +int ff_vk_video_common_init(void *log, FFVulkanContext *s, + FFVkVideoCommon *common, + VkVideoSessionCreateInfoKHR *session_create); + +/** + * Free video session and required resources. + */ +void ff_vk_video_common_uninit(FFVulkanContext *s, FFVkVideoCommon *common); + +#endif /* AVCODEC_VULKAN_VIDEO_H */ From 1e8fefff936d10a6126070382059daf668d5f5d5 Mon Sep 17 00:00:00 2001 From: Lynne Date: Mon, 16 Jan 2023 07:23:27 +0100 Subject: [PATCH 1292/2172] libavcodec: add Vulkan common video decoding code --- libavcodec/Makefile | 2 +- libavcodec/vulkan_decode.c | 1167 ++++++++++++++++++++++++++++++++++++ libavcodec/vulkan_decode.h | 176 ++++++ 3 files changed, 1344 insertions(+), 1 deletion(-) create mode 100644 libavcodec/vulkan_decode.c create mode 100644 libavcodec/vulkan_decode.h diff --git a/libavcodec/Makefile b/libavcodec/Makefile index 8580d4ca1d7..5bc3d6ffabf 100644 --- a/libavcodec/Makefile +++ b/libavcodec/Makefile @@ -1291,7 +1291,7 @@ SKIPHEADERS-$(CONFIG_XVMC) += xvmc.h SKIPHEADERS-$(CONFIG_VAAPI) += vaapi_decode.h vaapi_hevc.h vaapi_encode.h SKIPHEADERS-$(CONFIG_VDPAU) += vdpau.h vdpau_internal.h SKIPHEADERS-$(CONFIG_VIDEOTOOLBOX) += videotoolbox.h vt_internal.h -SKIPHEADERS-$(CONFIG_VULKAN) += vulkan.h vulkan_video.h +SKIPHEADERS-$(CONFIG_VULKAN) += vulkan.h vulkan_video.h vulkan_decode.h SKIPHEADERS-$(CONFIG_V4L2_M2M) += v4l2_buffers.h v4l2_context.h v4l2_m2m.h SKIPHEADERS-$(CONFIG_ZLIB) += zlib_wrapper.h diff --git a/libavcodec/vulkan_decode.c b/libavcodec/vulkan_decode.c new file mode 100644 index 00000000000..a2900d95622 --- /dev/null +++ b/libavcodec/vulkan_decode.c @@ -0,0 +1,1167 @@ +/* + * 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_video.h" +#include "vulkan_decode.h" +#include "config_components.h" + +#if CONFIG_H264_VULKAN_HWACCEL +extern const VkExtensionProperties ff_vk_dec_h264_ext; +#endif +#if CONFIG_HEVC_VULKAN_HWACCEL +extern const VkExtensionProperties ff_vk_dec_hevc_ext; +#endif + +static const VkExtensionProperties *dec_ext[] = { +#if CONFIG_H264_VULKAN_HWACCEL + [AV_CODEC_ID_H264] = &ff_vk_dec_h264_ext, +#endif +#if CONFIG_HEVC_VULKAN_HWACCEL + [AV_CODEC_ID_HEVC] = &ff_vk_dec_hevc_ext, +#endif +}; + +int ff_vk_update_thread_context(AVCodecContext *dst, const AVCodecContext *src) +{ + int err; + FFVulkanDecodeContext *src_ctx = src->internal->hwaccel_priv_data; + FFVulkanDecodeContext *dst_ctx = dst->internal->hwaccel_priv_data; + + err = av_buffer_replace(&dst_ctx->shared_ref, src_ctx->shared_ref); + if (err < 0) + return err; + + if (src_ctx->session_params) { + err = av_buffer_replace(&dst_ctx->session_params, src_ctx->session_params); + if (err < 0) + return err; + } + + dst_ctx->dedicated_dpb = src_ctx->dedicated_dpb; + dst_ctx->layered_dpb = src_ctx->layered_dpb; + + return 0; +} + +int ff_vk_params_changed(AVCodecContext *avctx, int t, const uint8_t *b, uint32_t s) +{ + FFVulkanDecodeContext *dec = avctx->internal->hwaccel_priv_data; + dec->params_changed = 1; + return 0; +} + +static int vk_decode_create_view(FFVulkanDecodeShared *ctx, VkImageView *dst_view, + VkImageAspectFlags *aspect, AVVkFrame *src, + VkFormat vkf) +{ + VkResult ret; + FFVulkanFunctions *vk = &ctx->s.vkfn; + VkImageAspectFlags aspect_mask = ff_vk_aspect_bits_from_vkfmt(vkf); + + VkSamplerYcbcrConversionInfo yuv_sampler_info = { + .sType = VK_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_INFO, + .conversion = ctx->yuv_sampler, + }; + VkImageViewCreateInfo img_view_create_info = { + .sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, + .pNext = &yuv_sampler_info, + .viewType = VK_IMAGE_VIEW_TYPE_2D, + .format = vkf, + .image = src->img[0], + .components = (VkComponentMapping) { + .r = VK_COMPONENT_SWIZZLE_IDENTITY, + .g = VK_COMPONENT_SWIZZLE_IDENTITY, + .b = VK_COMPONENT_SWIZZLE_IDENTITY, + .a = VK_COMPONENT_SWIZZLE_IDENTITY, + }, + .subresourceRange = (VkImageSubresourceRange) { + .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT, + .baseArrayLayer = 0, + .layerCount = VK_REMAINING_ARRAY_LAYERS, + .levelCount = 1, + }, + }; + + ret = vk->CreateImageView(ctx->s.hwctx->act_dev, &img_view_create_info, + ctx->s.hwctx->alloc, dst_view); + if (ret != VK_SUCCESS) + return AVERROR_EXTERNAL; + + *aspect = aspect_mask; + + return 0; +} + +static AVFrame *vk_get_dpb_pool(FFVulkanDecodeShared *ctx) +{ + int err; + AVFrame *avf = av_frame_alloc(); + if (!avf) + return NULL; + + err = av_hwframe_get_buffer(ctx->dpb_hwfc_ref, avf, 0x0); + if (err < 0) + av_frame_free(&avf); + + return avf; +} + +int ff_vk_decode_prepare_frame(FFVulkanDecodeContext *dec, AVFrame *pic, + FFVulkanDecodePicture *vkpic, int is_current, + int alloc_dpb) +{ + int err; + FFVulkanDecodeShared *ctx = (FFVulkanDecodeShared *)dec->shared_ref->data; + + vkpic->nb_slices = 0; + vkpic->slices_size = 0; + + /* If the decoder made a blank frame to make up for a missing ref, or the + * frame is the current frame so it's missing one, create a re-representation */ + if (vkpic->img_view_ref) + return 0; + + vkpic->dpb_frame = NULL; + vkpic->img_view_ref = NULL; + vkpic->img_view_out = NULL; + vkpic->img_view_dest = NULL; + + if (dec->layered_dpb && alloc_dpb) { + vkpic->img_view_ref = ctx->layered_view; + vkpic->img_aspect_ref = ctx->layered_aspect; + } else if (alloc_dpb) { + AVHWFramesContext *dpb_frames = (AVHWFramesContext *)ctx->dpb_hwfc_ref->data; + AVVulkanFramesContext *dpb_hwfc = dpb_frames->hwctx; + + vkpic->dpb_frame = vk_get_dpb_pool(ctx); + if (!vkpic->dpb_frame) + return AVERROR(ENOMEM); + + err = vk_decode_create_view(ctx, &vkpic->img_view_ref, + &vkpic->img_aspect_ref, + (AVVkFrame *)vkpic->dpb_frame->data[0], + dpb_hwfc->format[0]); + if (err < 0) + return err; + + vkpic->img_view_dest = vkpic->img_view_ref; + } + + if (!alloc_dpb || is_current) { + AVHWFramesContext *frames = (AVHWFramesContext *)pic->hw_frames_ctx->data; + AVVulkanFramesContext *hwfc = frames->hwctx; + + err = vk_decode_create_view(ctx, &vkpic->img_view_out, + &vkpic->img_aspect, + (AVVkFrame *)pic->data[0], + hwfc->format[0]); + if (err < 0) + return err; + + if (!alloc_dpb) { + vkpic->img_view_ref = vkpic->img_view_out; + vkpic->img_aspect_ref = vkpic->img_aspect; + } + } + + return 0; +} + +int ff_vk_decode_add_slice(AVCodecContext *avctx, FFVulkanDecodePicture *vp, + const uint8_t *data, size_t size, int add_startcode, + uint32_t *nb_slices, const uint32_t **offsets) +{ + FFVulkanDecodeContext *dec = avctx->internal->hwaccel_priv_data; + FFVulkanDecodeShared *ctx = (FFVulkanDecodeShared *)dec->shared_ref->data; + FFVulkanDecodeProfileData *prof = &ctx->profile_data; + + static const uint8_t startcode_prefix[3] = { 0x0, 0x0, 0x1 }; + const size_t startcode_len = add_startcode ? sizeof(startcode_prefix) : 0; + const int nb = *nb_slices; + uint8_t *slices; + uint32_t *slice_off; + FFVkVideoBuffer *vkbuf; + + size_t new_size = vp->slices_size + startcode_len + size + + prof->caps.minBitstreamBufferSizeAlignment; + new_size = FFALIGN(new_size, prof->caps.minBitstreamBufferSizeAlignment); + + slice_off = av_fast_realloc(vp->slice_off, &vp->slice_off_max, + (nb + 1)*sizeof(slice_off)); + if (!slice_off) + return AVERROR(ENOMEM); + + *offsets = vp->slice_off = slice_off; + slice_off[nb] = vp->slices_size; + + vkbuf = vp->slices_buf ? (FFVkVideoBuffer *)vp->slices_buf->data : NULL; + if (!vkbuf || vkbuf->buf.size < new_size) { + int err; + AVBufferRef *new_ref; + FFVkVideoBuffer *new_buf; + err = ff_vk_video_get_buffer(&ctx->s, &ctx->common, &new_ref, + VK_BUFFER_USAGE_VIDEO_DECODE_SRC_BIT_KHR, + ctx->s.hwfc->create_pnext, new_size); + if (err < 0) + return err; + + new_buf = (FFVkVideoBuffer *)new_ref->data; + + /* Copy data from the old buffer */ + if (vkbuf) { + memcpy(new_buf->mem, vkbuf->mem, vp->slices_size); + av_buffer_unref(&vp->slices_buf); + } + + vp->slices_buf = new_ref; + vkbuf = new_buf; + } + slices = vkbuf->mem; + + /* Startcode */ + memcpy(slices + vp->slices_size, startcode_prefix, startcode_len); + + /* Slice data */ + memcpy(slices + vp->slices_size + startcode_len, data, size); + + *nb_slices = nb + 1; + vp->nb_slices++; + vp->slices_size += startcode_len + size; + + return 0; +} + +void ff_vk_decode_flush(AVCodecContext *avctx) +{ + FFVulkanDecodeContext *dec = avctx->internal->hwaccel_priv_data; + FFVulkanDecodeShared *ctx = (FFVulkanDecodeShared *)dec->shared_ref->data; + + FFVulkanFunctions *vk = &ctx->s.vkfn; + VkVideoBeginCodingInfoKHR decode_start = { + .sType = VK_STRUCTURE_TYPE_VIDEO_BEGIN_CODING_INFO_KHR, + .videoSession = ctx->common.session, + .videoSessionParameters = ctx->empty_session_params, + }; + VkVideoCodingControlInfoKHR decode_ctrl = { + .sType = VK_STRUCTURE_TYPE_VIDEO_CODING_CONTROL_INFO_KHR, + .flags = VK_VIDEO_CODING_CONTROL_RESET_BIT_KHR, + }; + VkVideoEndCodingInfoKHR decode_end = { + .sType = VK_STRUCTURE_TYPE_VIDEO_END_CODING_INFO_KHR, + }; + + VkCommandBuffer cmd_buf; + FFVkExecContext *exec = ff_vk_exec_get(&ctx->exec_pool); + ff_vk_exec_start(&ctx->s, exec); + cmd_buf = exec->buf; + + vk->CmdBeginVideoCodingKHR(cmd_buf, &decode_start); + vk->CmdControlVideoCodingKHR(cmd_buf, &decode_ctrl); + vk->CmdEndVideoCodingKHR(cmd_buf, &decode_end); + ff_vk_exec_submit(&ctx->s, exec); +} + +int ff_vk_decode_frame(AVCodecContext *avctx, + AVFrame *pic, FFVulkanDecodePicture *vp, + AVFrame *rpic[], FFVulkanDecodePicture *rvkp[]) +{ + int err; + VkResult ret; + VkCommandBuffer cmd_buf; + FFVkVideoBuffer *sd_buf; + + FFVulkanDecodeContext *dec = avctx->internal->hwaccel_priv_data; + FFVulkanDecodeShared *ctx = (FFVulkanDecodeShared *)dec->shared_ref->data; + FFVulkanDecodeProfileData *prof = &ctx->profile_data; + FFVulkanFunctions *vk = &ctx->s.vkfn; + + /* Output */ + AVVkFrame *vkf = (AVVkFrame *)pic->buf[0]->data; + + /* Quirks */ + const int layered_dpb = dec->layered_dpb; + + VkVideoSessionParametersKHR *par = (VkVideoSessionParametersKHR *)dec->session_params->data; + VkVideoBeginCodingInfoKHR decode_start = { + .sType = VK_STRUCTURE_TYPE_VIDEO_BEGIN_CODING_INFO_KHR, + .videoSession = ctx->common.session, + .videoSessionParameters = *par, + .referenceSlotCount = vp->decode_info.referenceSlotCount, + .pReferenceSlots = vp->decode_info.pReferenceSlots, + }; + VkVideoEndCodingInfoKHR decode_end = { + .sType = VK_STRUCTURE_TYPE_VIDEO_END_CODING_INFO_KHR, + }; + + VkImageMemoryBarrier2 img_bar[37]; + int nb_img_bar = 0; + size_t data_size = FFALIGN(vp->slices_size, + prof->caps.minBitstreamBufferSizeAlignment); + + FFVkExecContext *exec = ff_vk_exec_get(&ctx->exec_pool); + + /* The current decoding reference has to be bound as an inactive reference */ + VkVideoReferenceSlotInfoKHR *cur_vk_ref; + cur_vk_ref = (void *)&decode_start.pReferenceSlots[decode_start.referenceSlotCount]; + cur_vk_ref[0] = vp->ref_slot; + cur_vk_ref[0].slotIndex = -1; + decode_start.referenceSlotCount++; + + if (ctx->exec_pool.nb_queries) { + int64_t prev_sub_res = 0; + ff_vk_exec_wait(&ctx->s, exec); + ret = ff_vk_exec_get_query(&ctx->s, exec, NULL, &prev_sub_res); + if (ret != VK_NOT_READY && ret != VK_SUCCESS) { + av_log(avctx, AV_LOG_ERROR, "Unable to perform query: %s!\n", + ff_vk_ret2str(ret)); + return AVERROR_EXTERNAL; + } + + if (ret == VK_SUCCESS) + av_log(avctx, prev_sub_res < 0 ? AV_LOG_ERROR : AV_LOG_DEBUG, + "Result of previous frame decoding: %li\n", prev_sub_res); + } + + sd_buf = (FFVkVideoBuffer *)vp->slices_buf->data; + + /* Flush if needed */ + if (!(sd_buf->buf.flags & VK_MEMORY_PROPERTY_HOST_COHERENT_BIT)) { + VkMappedMemoryRange flush_buf = { + .sType = VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE, + .memory = sd_buf->buf.mem, + .offset = 0, + .size = FFALIGN(vp->slices_size, + ctx->s.props.properties.limits.nonCoherentAtomSize), + }; + + ret = vk->FlushMappedMemoryRanges(ctx->s.hwctx->act_dev, 1, &flush_buf); + if (ret != VK_SUCCESS) { + av_log(avctx, AV_LOG_ERROR, "Failed to flush memory: %s\n", + ff_vk_ret2str(ret)); + return AVERROR_EXTERNAL; + } + } + + vp->decode_info.srcBuffer = sd_buf->buf.buf; + vp->decode_info.srcBufferOffset = 0; + vp->decode_info.srcBufferRange = data_size; + + /* Start command buffer recording */ + err = ff_vk_exec_start(&ctx->s, exec); + if (err < 0) + return err; + cmd_buf = exec->buf; + + /* Slices */ + err = ff_vk_exec_add_dep_buf(&ctx->s, exec, &vp->slices_buf, 1, 0); + if (err < 0) + return err; + vp->slices_buf = NULL; /* Owned by the exec buffer from now on */ + + /* Parameters */ + err = ff_vk_exec_add_dep_buf(&ctx->s, exec, &dec->session_params, 1, 1); + if (err < 0) + return err; + + err = ff_vk_exec_add_dep_frame(&ctx->s, exec, pic, + VK_PIPELINE_STAGE_2_VIDEO_DECODE_BIT_KHR, + VK_PIPELINE_STAGE_2_VIDEO_DECODE_BIT_KHR); + if (err < 0) + return err; + + err = ff_vk_exec_mirror_sem_value(&ctx->s, exec, &vp->sem, &vp->sem_value, + pic); + if (err < 0) + return err; + + /* Output image - change layout, as it comes from a pool */ + img_bar[nb_img_bar] = (VkImageMemoryBarrier2) { + .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER_2, + .pNext = NULL, + .srcStageMask = VK_PIPELINE_STAGE_2_VIDEO_DECODE_BIT_KHR, + .dstStageMask = VK_PIPELINE_STAGE_2_VIDEO_DECODE_BIT_KHR, + .srcAccessMask = VK_ACCESS_2_NONE, + .dstAccessMask = VK_ACCESS_2_VIDEO_DECODE_WRITE_BIT_KHR, + .oldLayout = vkf->layout[0], + .newLayout = vp->dpb_frame ? VK_IMAGE_LAYOUT_VIDEO_DECODE_DST_KHR : + VK_IMAGE_LAYOUT_VIDEO_DECODE_DPB_KHR, /* Spec, 07252 utter madness */ + .srcQueueFamilyIndex = vkf->queue_family[0], + .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, + .image = vkf->img[0], + .subresourceRange = (VkImageSubresourceRange) { + .aspectMask = vp->img_aspect, + .layerCount = 1, + .levelCount = 1, + }, + }; + ff_vk_exec_update_frame(&ctx->s, exec, pic, + &img_bar[nb_img_bar], &nb_img_bar); + + /* Reference for the current image, if existing and not layered */ + if (vp->dpb_frame) { + err = ff_vk_exec_add_dep_frame(&ctx->s, exec, vp->dpb_frame, + VK_PIPELINE_STAGE_2_VIDEO_DECODE_BIT_KHR, + VK_PIPELINE_STAGE_2_VIDEO_DECODE_BIT_KHR); + if (err < 0) + return err; + } + + if (!layered_dpb) { + /* All references (apart from the current) for non-layered refs */ + + for (int i = 0; i < vp->decode_info.referenceSlotCount; i++) { + AVFrame *ref_frame = rpic[i]; + FFVulkanDecodePicture *rvp = rvkp[i]; + AVFrame *ref = rvp->dpb_frame ? rvp->dpb_frame : ref_frame; + + err = ff_vk_exec_add_dep_frame(&ctx->s, exec, ref, + VK_PIPELINE_STAGE_2_VIDEO_DECODE_BIT_KHR, + VK_PIPELINE_STAGE_2_VIDEO_DECODE_BIT_KHR); + if (err < 0) + return err; + + if (err == 0) { + err = ff_vk_exec_mirror_sem_value(&ctx->s, exec, + &rvp->sem, &rvp->sem_value, + ref); + if (err < 0) + return err; + } + + if (!rvp->dpb_frame) { + AVVkFrame *rvkf = (AVVkFrame *)ref->data[0]; + + img_bar[nb_img_bar] = (VkImageMemoryBarrier2) { + .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER_2, + .pNext = NULL, + .srcStageMask = VK_PIPELINE_STAGE_2_VIDEO_DECODE_BIT_KHR, + .dstStageMask = VK_PIPELINE_STAGE_2_VIDEO_DECODE_BIT_KHR, + .srcAccessMask = VK_ACCESS_2_NONE, + .dstAccessMask = VK_ACCESS_2_VIDEO_DECODE_READ_BIT_KHR | + VK_ACCESS_2_VIDEO_DECODE_WRITE_BIT_KHR, + .oldLayout = rvkf->layout[0], + .newLayout = VK_IMAGE_LAYOUT_VIDEO_DECODE_DPB_KHR, + .srcQueueFamilyIndex = rvkf->queue_family[0], + .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, + .image = rvkf->img[0], + .subresourceRange = (VkImageSubresourceRange) { + .aspectMask = rvp->img_aspect_ref, + .layerCount = 1, + .levelCount = 1, + }, + }; + ff_vk_exec_update_frame(&ctx->s, exec, ref, + &img_bar[nb_img_bar], &nb_img_bar); + } + } + } else if (vp->decode_info.referenceSlotCount || + vp->img_view_out != vp->img_view_ref) { + /* Single barrier for a single layered ref */ + err = ff_vk_exec_add_dep_frame(&ctx->s, exec, ctx->layered_frame, + VK_PIPELINE_STAGE_2_VIDEO_DECODE_BIT_KHR, + VK_PIPELINE_STAGE_2_VIDEO_DECODE_BIT_KHR); + if (err < 0) + return err; + } + + /* Change image layout */ + vk->CmdPipelineBarrier2(cmd_buf, &(VkDependencyInfo) { + .sType = VK_STRUCTURE_TYPE_DEPENDENCY_INFO, + .dependencyFlags = VK_DEPENDENCY_BY_REGION_BIT, + .pImageMemoryBarriers = img_bar, + .imageMemoryBarrierCount = nb_img_bar, + }); + + /* Start, use parameters, decode and end decoding */ + vk->CmdBeginVideoCodingKHR(cmd_buf, &decode_start); + + /* Start status query */ + if (ctx->exec_pool.nb_queries) + vk->CmdBeginQuery(cmd_buf, ctx->exec_pool.query_pool, exec->query_idx + 0, 0); + + vk->CmdDecodeVideoKHR(cmd_buf, &vp->decode_info); + + /* End status query */ + if (ctx->exec_pool.nb_queries) + vk->CmdEndQuery(cmd_buf, ctx->exec_pool.query_pool, exec->query_idx + 0); + + vk->CmdEndVideoCodingKHR(cmd_buf, &decode_end); + + /* End recording and submit for execution */ + return ff_vk_exec_submit(&ctx->s, exec); +} + +void ff_vk_decode_free_frame(AVHWDeviceContext *dev_ctx, FFVulkanDecodePicture *vp) +{ + AVVulkanDeviceContext *hwctx = dev_ctx->hwctx; + PFN_vkGetDeviceProcAddr device_proc_addr; + PFN_vkWaitSemaphores wait_semaphores; + PFN_vkDestroyImageView destroy_image_view; + + VkSemaphoreWaitInfo sem_wait = (VkSemaphoreWaitInfo) { + .sType = VK_STRUCTURE_TYPE_SEMAPHORE_WAIT_INFO, + .pSemaphores = &vp->sem, + .pValues = &vp->sem_value, + .semaphoreCount = 1, + }; + + /* Guaranteed to exist */ + device_proc_addr = (PFN_vkGetDeviceProcAddr)hwctx->get_proc_addr(hwctx->inst, "vkGetDeviceProcAddr"); + destroy_image_view = (PFN_vkDestroyImageView)device_proc_addr(hwctx->act_dev, "vkDestroyImageView"); + wait_semaphores = (PFN_vkWaitSemaphores)device_proc_addr(hwctx->act_dev, "vkWaitSemaphores"); + + /* We do not have to lock the frame here because we're not interested + * in the actual current semaphore value, but only that it's later than + * the time we submitted the image for decoding. */ + if (vp->sem) + wait_semaphores(hwctx->act_dev, &sem_wait, UINT64_MAX); + + /* Free slices data */ + av_buffer_unref(&vp->slices_buf); + + /* TODO: use a pool in the decode context instead to avoid per-frame allocs. */ + av_freep(&vp->slice_off); + + /* Destroy image view (out) */ + if (vp->img_view_out && vp->img_view_out != vp->img_view_dest) + destroy_image_view(hwctx->act_dev, vp->img_view_out, hwctx->alloc); + + /* Destroy image view (ref, unlayered) */ + if (vp->img_view_dest) + destroy_image_view(hwctx->act_dev, vp->img_view_dest, hwctx->alloc); + + av_frame_free(&vp->dpb_frame); +} + +static void free_common(void *opaque, uint8_t *data) +{ + FFVulkanDecodeShared *ctx = (FFVulkanDecodeShared *)data; + FFVulkanContext *s = &ctx->s; + FFVulkanFunctions *vk = &ctx->s.vkfn; + + /* Wait on and free execution pool */ + ff_vk_exec_pool_free(s, &ctx->exec_pool); + + /* Destroy layered view */ + if (ctx->layered_view) + vk->DestroyImageView(s->hwctx->act_dev, ctx->layered_view, s->hwctx->alloc); + + /* This also frees all references from this pool */ + av_frame_free(&ctx->layered_frame); + av_buffer_unref(&ctx->dpb_hwfc_ref); + + /* Destroy parameters */ + if (ctx->empty_session_params) + vk->DestroyVideoSessionParametersKHR(s->hwctx->act_dev, + ctx->empty_session_params, + s->hwctx->alloc); + + ff_vk_video_common_uninit(s, &ctx->common); + + vk->DestroySamplerYcbcrConversion(s->hwctx->act_dev, ctx->yuv_sampler, + s->hwctx->alloc); + + ff_vk_uninit(s); +} + +static int vulkan_decode_bootstrap(AVCodecContext *avctx, AVBufferRef *frames_ref) +{ + int err; + FFVulkanDecodeContext *dec = avctx->internal->hwaccel_priv_data; + AVHWFramesContext *frames = (AVHWFramesContext *)frames_ref->data; + AVHWDeviceContext *device = (AVHWDeviceContext *)frames->device_ref->data; + AVVulkanDeviceContext *hwctx = device->hwctx; + FFVulkanDecodeShared *ctx; + + if (dec->shared_ref) + return 0; + + ctx = av_mallocz(sizeof(*ctx)); + if (!ctx) + return AVERROR(ENOMEM); + + dec->shared_ref = av_buffer_create((uint8_t *)ctx, sizeof(*ctx), + free_common, NULL, 0); + if (!dec->shared_ref) { + av_free(ctx); + return AVERROR(ENOMEM); + } + + ctx = (FFVulkanDecodeShared *)dec->shared_ref->data; + + ctx->s.extensions = ff_vk_extensions_to_mask(hwctx->enabled_dev_extensions, + hwctx->nb_enabled_dev_extensions); + + if (!(ctx->s.extensions & FF_VK_EXT_VIDEO_DECODE_QUEUE)) { + av_log(avctx, AV_LOG_ERROR, "Device does not support the %s extension!\n", + VK_KHR_VIDEO_DECODE_QUEUE_EXTENSION_NAME); + av_buffer_unref(&dec->shared_ref); + return AVERROR(ENOSYS); + } + + err = ff_vk_load_functions(device, &ctx->s.vkfn, ctx->s.extensions, 1, 1); + if (err < 0) { + av_buffer_unref(&dec->shared_ref); + return err; + } + + return 0; +} + +static VkResult vulkan_setup_profile(AVCodecContext *avctx, + FFVulkanDecodeProfileData *prof, + AVVulkanDeviceContext *hwctx, + FFVulkanFunctions *vk, + const struct FFVkCodecMap *vk_codec, + VkVideoDecodeH264CapabilitiesKHR *h264_caps, + VkVideoDecodeH265CapabilitiesKHR *h265_caps, + int cur_profile) +{ + VkVideoCapabilitiesKHR *caps = &prof->caps; + VkVideoDecodeCapabilitiesKHR *dec_caps = &prof->dec_caps; + VkVideoDecodeUsageInfoKHR *usage = &prof->usage; + VkVideoProfileInfoKHR *profile = &prof->profile; + VkVideoProfileListInfoKHR *profile_list = &prof->profile_list; + + VkVideoDecodeH264ProfileInfoKHR *h264_profile = &prof->h264_profile; + VkVideoDecodeH264ProfileInfoKHR *h265_profile = &prof->h265_profile; + + const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(avctx->sw_pix_fmt); + if (!desc) + return AVERROR(EINVAL); + + if (avctx->codec_id == AV_CODEC_ID_H264) { + dec_caps->pNext = h264_caps; + usage->pNext = h264_profile; + h264_profile->sType = VK_STRUCTURE_TYPE_VIDEO_DECODE_H264_PROFILE_INFO_KHR; + h264_profile->stdProfileIdc = cur_profile; + h264_profile->pictureLayout = avctx->field_order == AV_FIELD_UNKNOWN || + avctx->field_order == AV_FIELD_PROGRESSIVE ? + VK_VIDEO_DECODE_H264_PICTURE_LAYOUT_PROGRESSIVE_KHR : + VK_VIDEO_DECODE_H264_PICTURE_LAYOUT_INTERLACED_INTERLEAVED_LINES_BIT_KHR; + } else if (avctx->codec_id == AV_CODEC_ID_H265) { + dec_caps->pNext = h265_caps; + usage->pNext = h265_profile; + h265_profile->sType = VK_STRUCTURE_TYPE_VIDEO_DECODE_H265_PROFILE_INFO_KHR; + h265_profile->stdProfileIdc = cur_profile; + } + + usage->sType = VK_STRUCTURE_TYPE_VIDEO_DECODE_USAGE_INFO_KHR; + usage->videoUsageHints = VK_VIDEO_DECODE_USAGE_DEFAULT_KHR; + + profile->sType = VK_STRUCTURE_TYPE_VIDEO_PROFILE_INFO_KHR; + profile->pNext = usage; + profile->videoCodecOperation = vk_codec->decode_op; + profile->chromaSubsampling = ff_vk_subsampling_from_av_desc(desc); + profile->lumaBitDepth = ff_vk_depth_from_av_depth(desc->comp[0].depth); + profile->chromaBitDepth = profile->lumaBitDepth; + + profile_list->sType = VK_STRUCTURE_TYPE_VIDEO_PROFILE_LIST_INFO_KHR; + profile_list->profileCount = 1; + profile_list->pProfiles = profile; + + /* Get the capabilities of the decoder for the given profile */ + caps->sType = VK_STRUCTURE_TYPE_VIDEO_CAPABILITIES_KHR; + caps->pNext = dec_caps; + dec_caps->sType = VK_STRUCTURE_TYPE_VIDEO_DECODE_CAPABILITIES_KHR; + /* dec_caps->pNext already filled in */ + + return vk->GetPhysicalDeviceVideoCapabilitiesKHR(hwctx->phys_dev, profile, + caps); +} + +static int vulkan_decode_get_profile(AVCodecContext *avctx, AVBufferRef *frames_ref, + int *width_align, int *height_align, + enum AVPixelFormat *pix_fmt, VkFormat *vk_fmt, + int *dpb_dedicate) +{ + VkResult ret; + int max_level, base_profile, cur_profile; + const struct FFVkCodecMap *vk_codec = &ff_vk_codec_map[avctx->codec_id]; + AVHWFramesContext *frames = (AVHWFramesContext *)frames_ref->data; + AVHWDeviceContext *device = (AVHWDeviceContext *)frames->device_ref->data; + AVVulkanDeviceContext *hwctx = device->hwctx; + enum AVPixelFormat source_format; + enum AVPixelFormat best_format; + VkFormat best_vkfmt; + + FFVulkanDecodeContext *dec = avctx->internal->hwaccel_priv_data; + FFVulkanDecodeShared *ctx = (FFVulkanDecodeShared *)dec->shared_ref->data; + FFVulkanFunctions *vk = &ctx->s.vkfn; + + FFVulkanDecodeProfileData *prof = &ctx->profile_data; + VkVideoCapabilitiesKHR *caps = &prof->caps; + VkVideoDecodeCapabilitiesKHR *dec_caps = &prof->dec_caps; + + VkVideoDecodeH264CapabilitiesKHR h264_caps = { + .sType = VK_STRUCTURE_TYPE_VIDEO_DECODE_H264_CAPABILITIES_KHR, + }; + VkVideoDecodeH265CapabilitiesKHR h265_caps = { + .sType = VK_STRUCTURE_TYPE_VIDEO_DECODE_H265_CAPABILITIES_KHR, + }; + + VkPhysicalDeviceVideoFormatInfoKHR fmt_info = { + .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VIDEO_FORMAT_INFO_KHR, + .pNext = &prof->profile_list, + }; + VkVideoFormatPropertiesKHR *ret_info; + uint32_t nb_out_fmts = 0; + + if (!vk_codec->decode_op || !vk_codec->decode_extension) { + av_log(avctx, AV_LOG_ERROR, "Unsupported codec for Vulkan decoding: %s!\n", + avcodec_get_name(avctx->codec_id)); + return AVERROR(ENOSYS); + } else if (!(vk_codec->decode_extension & ctx->s.extensions)) { + av_log(avctx, AV_LOG_ERROR, "Device does not support decoding %s!\n", + avcodec_get_name(avctx->codec_id)); + return AVERROR(ENOSYS); + } + + cur_profile = avctx->profile; + base_profile = avctx->codec_id == AV_CODEC_ID_H264 ? FF_PROFILE_H264_CONSTRAINED_BASELINE : + avctx->codec_id == AV_CODEC_ID_H265 ? FF_PROFILE_HEVC_MAIN : + 0; + + ret = vulkan_setup_profile(avctx, prof, hwctx, vk, vk_codec, + &h264_caps, + &h265_caps, + cur_profile); + if (ret == VK_ERROR_VIDEO_PROFILE_OPERATION_NOT_SUPPORTED_KHR && + avctx->flags & AV_HWACCEL_FLAG_ALLOW_PROFILE_MISMATCH && + avctx->profile != base_profile) { + av_log(avctx, AV_LOG_VERBOSE, "%s profile %s not supported, attempting " + "again with profile %s\n", + avcodec_get_name(avctx->codec_id), + avcodec_profile_name(avctx->codec_id, cur_profile), + avcodec_profile_name(avctx->codec_id, base_profile)); + cur_profile = base_profile; + ret = vulkan_setup_profile(avctx, prof, hwctx, vk, vk_codec, + &h264_caps, + &h265_caps, + cur_profile); + } + + if (ret == VK_ERROR_VIDEO_PROFILE_OPERATION_NOT_SUPPORTED_KHR) { + av_log(avctx, AV_LOG_VERBOSE, "Unable to initialize video session: " + "%s profile \"%s\" not supported!\n", + avcodec_get_name(avctx->codec_id), + avcodec_profile_name(avctx->codec_id, cur_profile)); + return AVERROR(EINVAL); + } else if (ret == VK_ERROR_VIDEO_PROFILE_FORMAT_NOT_SUPPORTED_KHR) { + av_log(avctx, AV_LOG_VERBOSE, "Unable to initialize video session: " + "format (%s) not supported!\n", + av_get_pix_fmt_name(avctx->sw_pix_fmt)); + return AVERROR(EINVAL); + } else if (ret == VK_ERROR_FEATURE_NOT_PRESENT || + ret == VK_ERROR_FORMAT_NOT_SUPPORTED) { + return AVERROR(EINVAL); + } else if (ret != VK_SUCCESS) { + return AVERROR_EXTERNAL; + } + + max_level = avctx->codec_id == AV_CODEC_ID_H264 ? h264_caps.maxLevelIdc : + avctx->codec_id == AV_CODEC_ID_H265 ? h265_caps.maxLevelIdc : + 0; + + av_log(avctx, AV_LOG_VERBOSE, "Decoder capabilities for %s profile \"%s\":\n", + avcodec_get_name(avctx->codec_id), + avcodec_profile_name(avctx->codec_id, cur_profile)); + av_log(avctx, AV_LOG_VERBOSE, " Maximum level: %i (stream %i)\n", + max_level, avctx->level); + av_log(avctx, AV_LOG_VERBOSE, " Width: from %i to %i\n", + caps->minCodedExtent.width, caps->maxCodedExtent.width); + av_log(avctx, AV_LOG_VERBOSE, " Height: from %i to %i\n", + caps->minCodedExtent.height, caps->maxCodedExtent.height); + av_log(avctx, AV_LOG_VERBOSE, " Width alignment: %i\n", + caps->pictureAccessGranularity.width); + av_log(avctx, AV_LOG_VERBOSE, " Height alignment: %i\n", + caps->pictureAccessGranularity.height); + av_log(avctx, AV_LOG_VERBOSE, " Bitstream offset alignment: %"PRIu64"\n", + caps->minBitstreamBufferOffsetAlignment); + av_log(avctx, AV_LOG_VERBOSE, " Bitstream size alignment: %"PRIu64"\n", + caps->minBitstreamBufferSizeAlignment); + av_log(avctx, AV_LOG_VERBOSE, " Maximum references: %u\n", + caps->maxDpbSlots); + av_log(avctx, AV_LOG_VERBOSE, " Maximum active references: %u\n", + caps->maxActiveReferencePictures); + av_log(avctx, AV_LOG_VERBOSE, " Codec header version: %i.%i.%i (driver), %i.%i.%i (compiled)\n", + CODEC_VER(caps->stdHeaderVersion.specVersion), + CODEC_VER(dec_ext[avctx->codec_id]->specVersion)); + av_log(avctx, AV_LOG_VERBOSE, " Decode modes:%s%s%s\n", + dec_caps->flags ? "" : + " invalid", + dec_caps->flags & VK_VIDEO_DECODE_CAPABILITY_DPB_AND_OUTPUT_COINCIDE_BIT_KHR ? + " reuse_dst_dpb" : "", + dec_caps->flags & VK_VIDEO_DECODE_CAPABILITY_DPB_AND_OUTPUT_DISTINCT_BIT_KHR ? + " dedicated_dpb" : ""); + av_log(avctx, AV_LOG_VERBOSE, " Capability flags:%s%s%s\n", + caps->flags ? "" : + " none", + caps->flags & VK_VIDEO_CAPABILITY_PROTECTED_CONTENT_BIT_KHR ? + " protected" : "", + caps->flags & VK_VIDEO_CAPABILITY_SEPARATE_REFERENCE_IMAGES_BIT_KHR ? + " separate_references" : ""); + + /* Check if decoding is possible with the given parameters */ + if (avctx->coded_width < caps->minCodedExtent.width || + avctx->coded_height < caps->minCodedExtent.height || + avctx->coded_width > caps->maxCodedExtent.width || + avctx->coded_height > caps->maxCodedExtent.height) + return AVERROR(EINVAL); + + if (!(avctx->hwaccel_flags & AV_HWACCEL_FLAG_IGNORE_LEVEL) && + avctx->level > max_level) + return AVERROR(EINVAL); + + /* Some basic sanity checking */ + if (!(dec_caps->flags & (VK_VIDEO_DECODE_CAPABILITY_DPB_AND_OUTPUT_COINCIDE_BIT_KHR | + VK_VIDEO_DECODE_CAPABILITY_DPB_AND_OUTPUT_DISTINCT_BIT_KHR))) { + av_log(avctx, AV_LOG_ERROR, "Buggy driver signals invalid decoding mode: neither " + "VK_VIDEO_DECODE_CAPABILITY_DPB_AND_OUTPUT_COINCIDE_BIT_KHR nor " + "VK_VIDEO_DECODE_CAPABILITY_DPB_AND_OUTPUT_DISTINCT_BIT_KHR are set!\n"); + return AVERROR_EXTERNAL; + } else if ((dec_caps->flags & (VK_VIDEO_DECODE_CAPABILITY_DPB_AND_OUTPUT_COINCIDE_BIT_KHR | + VK_VIDEO_DECODE_CAPABILITY_DPB_AND_OUTPUT_DISTINCT_BIT_KHR) == + VK_VIDEO_DECODE_CAPABILITY_DPB_AND_OUTPUT_COINCIDE_BIT_KHR) && + !(caps->flags & VK_VIDEO_CAPABILITY_SEPARATE_REFERENCE_IMAGES_BIT_KHR)) { + av_log(avctx, AV_LOG_ERROR, "Cannot initialize Vulkan decoding session, buggy driver: " + "VK_VIDEO_DECODE_CAPABILITY_DPB_AND_OUTPUT_COINCIDE_BIT_KHR set " + "but VK_VIDEO_CAPABILITY_SEPARATE_REFERENCE_IMAGES_BIT_KHR is unset!\n"); + return AVERROR_EXTERNAL; + } + + /* TODO: make dedicated_dpb tunable */ + dec->dedicated_dpb = !(dec_caps->flags & VK_VIDEO_DECODE_CAPABILITY_DPB_AND_OUTPUT_COINCIDE_BIT_KHR); + dec->layered_dpb = !(caps->flags & VK_VIDEO_CAPABILITY_SEPARATE_REFERENCE_IMAGES_BIT_KHR); + + if (dec->dedicated_dpb) { + fmt_info.imageUsage = VK_IMAGE_USAGE_VIDEO_DECODE_DPB_BIT_KHR; + } else { + fmt_info.imageUsage = VK_IMAGE_USAGE_VIDEO_DECODE_DPB_BIT_KHR | + VK_IMAGE_USAGE_VIDEO_DECODE_DST_BIT_KHR | + VK_IMAGE_USAGE_TRANSFER_SRC_BIT | + VK_IMAGE_USAGE_SAMPLED_BIT; + } + + /* Get the format of the images necessary */ + ret = vk->GetPhysicalDeviceVideoFormatPropertiesKHR(hwctx->phys_dev, + &fmt_info, + &nb_out_fmts, NULL); + if (ret == VK_ERROR_FORMAT_NOT_SUPPORTED || + (!nb_out_fmts && ret == VK_SUCCESS)) { + return AVERROR(EINVAL); + } else if (ret != VK_SUCCESS) { + av_log(avctx, AV_LOG_ERROR, "Unable to get Vulkan format properties: %s!\n", + ff_vk_ret2str(ret)); + return AVERROR_EXTERNAL; + } + + ret_info = av_mallocz(sizeof(*ret_info)*nb_out_fmts); + if (!ret_info) + return AVERROR(ENOMEM); + + for (int i = 0; i < nb_out_fmts; i++) + ret_info[i].sType = VK_STRUCTURE_TYPE_VIDEO_FORMAT_PROPERTIES_KHR; + + ret = vk->GetPhysicalDeviceVideoFormatPropertiesKHR(hwctx->phys_dev, + &fmt_info, + &nb_out_fmts, ret_info); + if (ret == VK_ERROR_FORMAT_NOT_SUPPORTED || + (!nb_out_fmts && ret == VK_SUCCESS)) { + av_free(ret_info); + return AVERROR(EINVAL); + } else if (ret != VK_SUCCESS) { + av_log(avctx, AV_LOG_ERROR, "Unable to get Vulkan format properties: %s!\n", + ff_vk_ret2str(ret)); + av_free(ret_info); + return AVERROR_EXTERNAL; + } + + /* Find a format to use */ + *pix_fmt = best_format = AV_PIX_FMT_NONE; + *vk_fmt = best_vkfmt = VK_FORMAT_UNDEFINED; + source_format = avctx->sw_pix_fmt; + + av_log(avctx, AV_LOG_DEBUG, "Choosing best pixel format for decoding from %i:\n", nb_out_fmts); + for (int i = 0; i < nb_out_fmts; i++) { + enum AVPixelFormat tmp = ff_vk_pix_fmt_from_vkfmt(ret_info[i].format); + if (tmp == AV_PIX_FMT_NONE) { + av_log(avctx, AV_LOG_WARNING, "Invalid/unknown Vulkan format %i!\n", ret_info[i].format); + continue; + } + + best_format = av_find_best_pix_fmt_of_2(tmp, best_format, source_format, 0, NULL); + if (tmp == best_format) + best_vkfmt = ret_info[i].format; + + av_log(avctx, AV_LOG_DEBUG, " %s%s (Vulkan ID: %i)\n", + av_get_pix_fmt_name(tmp), tmp == best_format ? "*" : "", + ret_info[i].format); + } + + av_free(ret_info); + + if (best_format == AV_PIX_FMT_NONE) { + av_log(avctx, AV_LOG_ERROR, "No valid/compatible pixel format found for decoding!\n"); + return AVERROR(EINVAL); + } else { + av_log(avctx, AV_LOG_VERBOSE, "Chosen frame pixfmt: %s (Vulkan ID: %i)\n", + av_get_pix_fmt_name(best_format), best_vkfmt); + } + + *pix_fmt = best_format; + *vk_fmt = best_vkfmt; + + *width_align = caps->pictureAccessGranularity.width; + *height_align = caps->pictureAccessGranularity.height; + *dpb_dedicate = dec->dedicated_dpb; + + return 0; +} + +int ff_vk_frame_params(AVCodecContext *avctx, AVBufferRef *hw_frames_ctx) +{ + VkFormat vkfmt; + int err, width_align, height_align, dedicated_dpb; + AVHWFramesContext *frames_ctx = (AVHWFramesContext*)hw_frames_ctx->data; + AVVulkanFramesContext *hwfc = frames_ctx->hwctx; + FFVulkanDecodeContext *dec = avctx->internal->hwaccel_priv_data; + FFVulkanDecodeShared *ctx; + FFVulkanDecodeProfileData *prof; + + frames_ctx->sw_format = AV_PIX_FMT_NONE; + + err = vulkan_decode_bootstrap(avctx, hw_frames_ctx); + if (err < 0) + return err; + + ctx = (FFVulkanDecodeShared *)dec->shared_ref->data; + prof = &ctx->profile_data; + + err = vulkan_decode_get_profile(avctx, hw_frames_ctx, + &width_align, &height_align, + &frames_ctx->sw_format, &vkfmt, + &dedicated_dpb); + if (err < 0) + return err; + + frames_ctx->width = FFALIGN(avctx->coded_width, width_align); + frames_ctx->height = FFALIGN(avctx->coded_height, height_align); + frames_ctx->format = AV_PIX_FMT_VULKAN; + + hwfc->format[0] = vkfmt; + hwfc->create_pnext = &prof->profile_list; + hwfc->tiling = VK_IMAGE_TILING_OPTIMAL; + hwfc->usage = VK_IMAGE_USAGE_TRANSFER_SRC_BIT | + VK_IMAGE_USAGE_SAMPLED_BIT | + VK_IMAGE_USAGE_VIDEO_DECODE_DST_BIT_KHR; + + if (!dec->dedicated_dpb) + hwfc->usage |= VK_IMAGE_USAGE_VIDEO_DECODE_DPB_BIT_KHR; + + return err; +} + +void ff_vk_decode_free_params(void *opaque, uint8_t *data) +{ + FFVulkanDecodeShared *ctx = opaque; + FFVulkanFunctions *vk = &ctx->s.vkfn; + VkVideoSessionParametersKHR *par = (VkVideoSessionParametersKHR *)data; + vk->DestroyVideoSessionParametersKHR(ctx->s.hwctx->act_dev, *par, + ctx->s.hwctx->alloc); + av_free(par); +} + +int ff_vk_decode_uninit(AVCodecContext *avctx) +{ + FFVulkanDecodeContext *dec = avctx->internal->hwaccel_priv_data; + av_buffer_pool_uninit(&dec->tmp_pool); + av_buffer_unref(&dec->session_params); + av_buffer_unref(&dec->shared_ref); + return 0; +} + +int ff_vk_decode_init(AVCodecContext *avctx) +{ + int err, qf, cxpos = 0, cypos = 0, nb_q = 0; + VkResult ret; + FFVulkanDecodeContext *dec = avctx->internal->hwaccel_priv_data; + FFVulkanDecodeShared *ctx; + FFVulkanDecodeProfileData *prof; + FFVulkanContext *s; + FFVulkanFunctions *vk; + FFVkQueueFamilyCtx qf_dec; + + VkVideoDecodeH264SessionParametersCreateInfoKHR h264_params = { + .sType = VK_STRUCTURE_TYPE_VIDEO_DECODE_H264_SESSION_PARAMETERS_CREATE_INFO_KHR, + }; + VkVideoDecodeH265SessionParametersCreateInfoKHR h265_params = { + .sType = VK_STRUCTURE_TYPE_VIDEO_DECODE_H265_SESSION_PARAMETERS_CREATE_INFO_KHR, + }; + VkVideoSessionParametersCreateInfoKHR session_params_create = { + .sType = VK_STRUCTURE_TYPE_VIDEO_SESSION_PARAMETERS_CREATE_INFO_KHR, + .pNext = avctx->codec_id == AV_CODEC_ID_H264 ? (void *)&h264_params : + avctx->codec_id == AV_CODEC_ID_HEVC ? (void *)&h265_params : + NULL, + }; + VkVideoSessionCreateInfoKHR session_create = { + .sType = VK_STRUCTURE_TYPE_VIDEO_SESSION_CREATE_INFO_KHR, + }; + VkSamplerYcbcrConversionCreateInfo yuv_sampler_info = { + .sType = VK_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_CREATE_INFO, + .components = ff_comp_identity_map, + .ycbcrModel = VK_SAMPLER_YCBCR_MODEL_CONVERSION_RGB_IDENTITY, + .ycbcrRange = avctx->color_range == AVCOL_RANGE_MPEG, /* Ignored */ + }; + + err = ff_decode_get_hw_frames_ctx(avctx, AV_HWDEVICE_TYPE_VULKAN); + if (err < 0) + return err; + + /* Initialize contexts */ + ctx = (FFVulkanDecodeShared *)dec->shared_ref->data; + prof = &ctx->profile_data; + s = &ctx->s; + vk = &ctx->s.vkfn; + + s->frames_ref = av_buffer_ref(avctx->hw_frames_ctx); + s->frames = (AVHWFramesContext *)s->frames_ref->data; + s->hwfc = s->frames->hwctx; + + s->device = (AVHWDeviceContext *)s->frames->device_ref->data; + s->hwctx = s->device->hwctx; + + err = ff_vk_load_props(s); + if (err < 0) + goto fail; + + /* Create queue context */ + qf = ff_vk_qf_init(s, &qf_dec, VK_QUEUE_VIDEO_DECODE_BIT_KHR); + + /* Check for support */ + if (!(s->video_props[qf].videoCodecOperations & + ff_vk_codec_map[avctx->codec_id].decode_op)) { + av_log(avctx, AV_LOG_ERROR, "Decoding %s not supported on the given " + "queue family %i!\n", avcodec_get_name(avctx->codec_id), qf); + return AVERROR(EINVAL); + } + + /* Enable queries if supported */ + if (s->query_props[qf].queryResultStatusSupport) + nb_q = 1; + + session_create.flags = 0x0; + session_create.queueFamilyIndex = s->hwctx->queue_family_decode_index; + session_create.maxCodedExtent = prof->caps.maxCodedExtent; + session_create.maxDpbSlots = prof->caps.maxDpbSlots; + session_create.maxActiveReferencePictures = prof->caps.maxActiveReferencePictures; + session_create.pictureFormat = s->hwfc->format[0]; + session_create.referencePictureFormat = session_create.pictureFormat; + session_create.pStdHeaderVersion = dec_ext[avctx->codec_id]; + session_create.pVideoProfile = &prof->profile_list.pProfiles[0]; + + /* Create decode exec context. + * 4 async contexts per thread seems like a good number. */ + err = ff_vk_exec_pool_init(s, &qf_dec, &ctx->exec_pool, 4*avctx->thread_count, + nb_q, VK_QUERY_TYPE_RESULT_STATUS_ONLY_KHR, 0, + session_create.pVideoProfile); + if (err < 0) + goto fail; + + err = ff_vk_video_common_init(avctx, s, &ctx->common, &session_create); + if (err < 0) + goto fail; + + /* Get sampler */ + av_chroma_location_enum_to_pos(&cxpos, &cypos, avctx->chroma_sample_location); + yuv_sampler_info.xChromaOffset = cxpos >> 7; + yuv_sampler_info.yChromaOffset = cypos >> 7; + yuv_sampler_info.format = s->hwfc->format[0]; + ret = vk->CreateSamplerYcbcrConversion(s->hwctx->act_dev, &yuv_sampler_info, + s->hwctx->alloc, &ctx->yuv_sampler); + if (ret != VK_SUCCESS) { + err = AVERROR_EXTERNAL; + goto fail; + } + + /* If doing an out-of-place decoding, create a DPB pool */ + if (dec->dedicated_dpb) { + AVHWFramesContext *dpb_frames; + AVVulkanFramesContext *dpb_hwfc; + + ctx->dpb_hwfc_ref = av_hwframe_ctx_alloc(s->frames->device_ref); + if (!ctx->dpb_hwfc_ref) { + err = AVERROR(ENOMEM); + goto fail; + } + + dpb_frames = (AVHWFramesContext *)ctx->dpb_hwfc_ref->data; + dpb_frames->format = s->frames->format; + dpb_frames->sw_format = s->frames->sw_format; + dpb_frames->width = s->frames->width; + dpb_frames->height = s->frames->height; + + dpb_hwfc = dpb_frames->hwctx; + dpb_hwfc->create_pnext = (void *)&prof->profile_list; + dpb_hwfc->format[0] = s->hwfc->format[0]; + dpb_hwfc->tiling = VK_IMAGE_TILING_OPTIMAL; + dpb_hwfc->usage = VK_IMAGE_USAGE_VIDEO_DECODE_DPB_BIT_KHR | + VK_IMAGE_USAGE_SAMPLED_BIT; /* Shuts validator up. */ + + if (dec->layered_dpb) + dpb_hwfc->nb_layers = prof->caps.maxDpbSlots; + + err = av_hwframe_ctx_init(ctx->dpb_hwfc_ref); + if (err < 0) + goto fail; + + if (dec->layered_dpb) { + ctx->layered_frame = vk_get_dpb_pool(ctx); + if (!ctx->layered_frame) { + err = AVERROR(ENOMEM); + goto fail; + } + + err = vk_decode_create_view(ctx, &ctx->layered_view, &ctx->layered_aspect, + (AVVkFrame *)ctx->layered_frame->data[0], + s->hwfc->format[0]); + if (err < 0) + goto fail; + } + } + + session_params_create.videoSession = ctx->common.session; + ret = vk->CreateVideoSessionParametersKHR(s->hwctx->act_dev, &session_params_create, + s->hwctx->alloc, &ctx->empty_session_params); + if (ret != VK_SUCCESS) { + av_log(avctx, AV_LOG_ERROR, "Unable to create empty Vulkan video session parameters: %s!\n", + ff_vk_ret2str(ret)); + return AVERROR_EXTERNAL; + } + + ff_vk_decode_flush(avctx); + + av_log(avctx, AV_LOG_VERBOSE, "Vulkan decoder initialization sucessful\n"); + + return 0; + +fail: + ff_vk_decode_uninit(avctx); + + return err; +} diff --git a/libavcodec/vulkan_decode.h b/libavcodec/vulkan_decode.h new file mode 100644 index 00000000000..bfde86e45f9 --- /dev/null +++ b/libavcodec/vulkan_decode.h @@ -0,0 +1,176 @@ +/* + * 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_VULKAN_DECODE_H +#define AVCODEC_VULKAN_DECODE_H + +#include "decode.h" +#include "hwconfig.h" +#include "internal.h" + +#include "vulkan_video.h" + +typedef struct FFVulkanDecodeProfileData { + VkVideoCapabilitiesKHR caps; + VkVideoDecodeCapabilitiesKHR dec_caps; + VkVideoDecodeH264ProfileInfoKHR h264_profile; + VkVideoDecodeH264ProfileInfoKHR h265_profile; + VkVideoDecodeAV1ProfileInfoMESA av1_profile; + VkVideoDecodeUsageInfoKHR usage; + VkVideoProfileInfoKHR profile; + VkVideoProfileListInfoKHR profile_list; +} FFVulkanDecodeProfileData; + +typedef struct FFVulkanDecodeShared { + FFVulkanContext s; + FFVkVideoCommon common; + FFVkExecPool exec_pool; + FFVulkanDecodeProfileData profile_data; + + AVBufferRef *dpb_hwfc_ref; /* Only used for dedicated_dpb */ + + AVFrame *layered_frame; /* Only used for layered_dpb */ + VkImageView layered_view; + VkImageAspectFlags layered_aspect; + + VkVideoSessionParametersKHR empty_session_params; + + VkSamplerYcbcrConversion yuv_sampler; +} FFVulkanDecodeShared; + +typedef struct FFVulkanDecodeContext { + AVBufferRef *shared_ref; + AVBufferRef *session_params; + + int dedicated_dpb; /* Oddity #1 - separate DPB images */ + int layered_dpb; /* Madness #1 - layered DPB images */ + + /* Thread-local state below */ + AVBufferPool *tmp_pool; /* Pool for temporary data, if needed (HEVC) */ + size_t tmp_pool_ele_size; + int params_changed; +} FFVulkanDecodeContext; + +typedef struct FFVulkanDecodePicture { + AVFrame *dpb_frame; /* Only used for out-of-place decoding. */ + + VkImageView img_view_ref; /* Image representation view (reference) */ + VkImageView img_view_out; /* Image representation view (output-only) */ + VkImageView img_view_dest; /* Set to img_view_out if no layered refs are used */ + VkImageAspectFlags img_aspect; /* Image plane mask bits */ + VkImageAspectFlags img_aspect_ref; /* Only used for out-of-place decoding */ + + VkSemaphore sem; + uint64_t sem_value; + + /* State */ + int update_params; + AVBufferRef *session_params; + + /* Current picture */ + VkVideoPictureResourceInfoKHR ref; + VkVideoReferenceSlotInfoKHR ref_slot; + + /* Picture refs. H264 has the maximum number of refs (36) of any supported codec. */ + VkVideoPictureResourceInfoKHR refs [36]; + VkVideoReferenceSlotInfoKHR ref_slots[36]; + + /* Main decoding struct */ + AVBufferRef *params_buf; + VkVideoDecodeInfoKHR decode_info; + + /* Slice data */ + AVBufferRef *slices_buf; + size_t slices_size; + uint32_t *slice_off; + unsigned int slice_off_max; + uint32_t nb_slices; +} FFVulkanDecodePicture; + +/** + * Initialize decoder. + */ +int ff_vk_decode_init(AVCodecContext *avctx); + +/** + * Synchronize the contexts between 2 threads. + */ +int ff_vk_update_thread_context(AVCodecContext *dst, const AVCodecContext *src); + +/** + * Initialize hw_frames_ctx with the parameters needed to decode the stream + * using the parameters from avctx. + * + * NOTE: if avctx->internal->hwaccel_priv_data exists, will partially initialize + * the context. + */ +int ff_vk_frame_params(AVCodecContext *avctx, AVBufferRef *hw_frames_ctx); + +/** + * Sets FFVulkanDecodeContext.params_changed to 1. + */ +int ff_vk_params_changed(AVCodecContext *avctx, int t, const uint8_t *b, uint32_t s); + +/** + * Prepare a frame, creates the image view, and sets up the dpb fields. + */ +int ff_vk_decode_prepare_frame(FFVulkanDecodeContext *dec, AVFrame *pic, + FFVulkanDecodePicture *vkpic, int is_current, + int alloc_dpb); + +/** + * Add slice data to frame. + */ +int ff_vk_decode_add_slice(AVCodecContext *avctx, FFVulkanDecodePicture *vp, + const uint8_t *data, size_t size, int add_startcode, + uint32_t *nb_slices, const uint32_t **offsets); + +/** + * Decode a frame. + */ +int ff_vk_decode_frame(AVCodecContext *avctx, + AVFrame *pic, FFVulkanDecodePicture *vp, + AVFrame *rpic[], FFVulkanDecodePicture *rvkp[]); + +/** + * Free a frame and its state. + */ +void ff_vk_decode_free_frame(AVHWDeviceContext *dev_ctx, FFVulkanDecodePicture *vp); + +/** + * Get an FFVkBuffer suitable for decoding from. + */ +int ff_vk_get_decode_buffer(FFVulkanDecodeContext *ctx, AVBufferRef **buf, + void *create_pNext, size_t size); + +/** + * Free VkVideoSessionParametersKHR. + */ +void ff_vk_decode_free_params(void *opaque, uint8_t *data); + +/** + * Flush decoder. + */ +void ff_vk_decode_flush(AVCodecContext *avctx); + +/** + * Free decoder. + */ +int ff_vk_decode_uninit(AVCodecContext *avctx); + +#endif /* AVCODEC_VULKAN_DECODE_H */ From a9fbe8b47269e86a38f73d705426c6e853cdd887 Mon Sep 17 00:00:00 2001 From: Lynne Date: Wed, 14 Dec 2022 01:13:01 +0100 Subject: [PATCH 1293/2172] h264dec: add Vulkan hwaccel Thanks to Dave Airlie for figuring out a lot of the parameters. --- configure | 2 + libavcodec/Makefile | 1 + libavcodec/h264_slice.c | 12 +- libavcodec/h264dec.c | 3 + libavcodec/hwaccels.h | 1 + libavcodec/vulkan_h264.c | 559 +++++++++++++++++++++++++++++++++++++++ 6 files changed, 577 insertions(+), 1 deletion(-) create mode 100644 libavcodec/vulkan_h264.c diff --git a/configure b/configure index 43c02ecb220..c149ae1291f 100755 --- a/configure +++ b/configure @@ -3038,6 +3038,8 @@ h264_vdpau_hwaccel_deps="vdpau" h264_vdpau_hwaccel_select="h264_decoder" h264_videotoolbox_hwaccel_deps="videotoolbox" h264_videotoolbox_hwaccel_select="h264_decoder" +h264_vulkan_hwaccel_deps="vulkan" +h264_vulkan_hwaccel_select="h264_decoder" hevc_d3d11va_hwaccel_deps="d3d11va DXVA_PicParams_HEVC" hevc_d3d11va_hwaccel_select="hevc_decoder" hevc_d3d11va2_hwaccel_deps="d3d11va DXVA_PicParams_HEVC" diff --git a/libavcodec/Makefile b/libavcodec/Makefile index 5bc3d6ffabf..62b24630bf9 100644 --- a/libavcodec/Makefile +++ b/libavcodec/Makefile @@ -998,6 +998,7 @@ OBJS-$(CONFIG_H264_QSV_HWACCEL) += qsvdec.o OBJS-$(CONFIG_H264_VAAPI_HWACCEL) += vaapi_h264.o OBJS-$(CONFIG_H264_VDPAU_HWACCEL) += vdpau_h264.o OBJS-$(CONFIG_H264_VIDEOTOOLBOX_HWACCEL) += videotoolbox.o +OBJS-$(CONFIG_H264_VULKAN_HWACCEL) += vulkan_decode.o vulkan_h264.o OBJS-$(CONFIG_HEVC_D3D11VA_HWACCEL) += dxva2_hevc.o OBJS-$(CONFIG_HEVC_DXVA2_HWACCEL) += dxva2_hevc.o OBJS-$(CONFIG_HEVC_NVDEC_HWACCEL) += nvdec_hevc.o diff --git a/libavcodec/h264_slice.c b/libavcodec/h264_slice.c index d715cbb002a..41bf30eefca 100644 --- a/libavcodec/h264_slice.c +++ b/libavcodec/h264_slice.c @@ -781,7 +781,8 @@ static enum AVPixelFormat get_pixel_format(H264Context *h, int force_callback) CONFIG_H264_NVDEC_HWACCEL + \ CONFIG_H264_VAAPI_HWACCEL + \ CONFIG_H264_VIDEOTOOLBOX_HWACCEL + \ - CONFIG_H264_VDPAU_HWACCEL) + CONFIG_H264_VDPAU_HWACCEL + \ + CONFIG_H264_VULKAN_HWACCEL) enum AVPixelFormat pix_fmts[HWACCEL_MAX + 2], *fmt = pix_fmts; const enum AVPixelFormat *choices = pix_fmts; int i; @@ -802,6 +803,9 @@ static enum AVPixelFormat get_pixel_format(H264Context *h, int force_callback) #if CONFIG_H264_VIDEOTOOLBOX_HWACCEL if (h->avctx->colorspace != AVCOL_SPC_RGB) *fmt++ = AV_PIX_FMT_VIDEOTOOLBOX; +#endif +#if CONFIG_H264_VULKAN_HWACCEL + *fmt++ = AV_PIX_FMT_VULKAN; #endif if (CHROMA444(h)) { if (h->avctx->colorspace == AVCOL_SPC_RGB) { @@ -821,6 +825,9 @@ static enum AVPixelFormat get_pixel_format(H264Context *h, int force_callback) } break; case 12: +#if CONFIG_H264_VULKAN_HWACCEL + *fmt++ = AV_PIX_FMT_VULKAN; +#endif if (CHROMA444(h)) { if (h->avctx->colorspace == AVCOL_SPC_RGB) { *fmt++ = AV_PIX_FMT_GBRP12; @@ -846,6 +853,9 @@ static enum AVPixelFormat get_pixel_format(H264Context *h, int force_callback) #if CONFIG_H264_VDPAU_HWACCEL *fmt++ = AV_PIX_FMT_VDPAU; #endif +#if CONFIG_H264_VULKAN_HWACCEL + *fmt++ = AV_PIX_FMT_VULKAN; +#endif #if CONFIG_H264_NVDEC_HWACCEL *fmt++ = AV_PIX_FMT_CUDA; #endif diff --git a/libavcodec/h264dec.c b/libavcodec/h264dec.c index a10b4bb85cf..19f8dba1317 100644 --- a/libavcodec/h264dec.c +++ b/libavcodec/h264dec.c @@ -1100,6 +1100,9 @@ const FFCodec ff_h264_decoder = { #endif #if CONFIG_H264_VIDEOTOOLBOX_HWACCEL HWACCEL_VIDEOTOOLBOX(h264), +#endif +#if CONFIG_H264_VULKAN_HWACCEL + HWACCEL_VULKAN(h264), #endif NULL }, diff --git a/libavcodec/hwaccels.h b/libavcodec/hwaccels.h index aca55831f32..23d0843c76f 100644 --- a/libavcodec/hwaccels.h +++ b/libavcodec/hwaccels.h @@ -36,6 +36,7 @@ extern const AVHWAccel ff_h264_nvdec_hwaccel; extern const AVHWAccel ff_h264_vaapi_hwaccel; extern const AVHWAccel ff_h264_vdpau_hwaccel; extern const AVHWAccel ff_h264_videotoolbox_hwaccel; +extern const AVHWAccel ff_h264_vulkan_hwaccel; extern const AVHWAccel ff_hevc_d3d11va_hwaccel; extern const AVHWAccel ff_hevc_d3d11va2_hwaccel; extern const AVHWAccel ff_hevc_dxva2_hwaccel; diff --git a/libavcodec/vulkan_h264.c b/libavcodec/vulkan_h264.c new file mode 100644 index 00000000000..3d86255966b --- /dev/null +++ b/libavcodec/vulkan_h264.c @@ -0,0 +1,559 @@ +/* + * 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 "h264dec.h" +#include "h264_ps.h" + +#include "vulkan_decode.h" + +const VkExtensionProperties ff_vk_dec_h264_ext = { + .extensionName = VK_STD_VULKAN_VIDEO_CODEC_H264_DECODE_EXTENSION_NAME, + .specVersion = VK_STD_VULKAN_VIDEO_CODEC_H264_DECODE_SPEC_VERSION, +}; + +typedef struct H264VulkanDecodePicture { + FFVulkanDecodePicture vp; + + /* Current picture */ + StdVideoDecodeH264ReferenceInfo h264_ref; + VkVideoDecodeH264DpbSlotInfoKHR vkh264_ref; + + /* Picture refs */ + H264Picture *ref_src [H264_MAX_PICTURE_COUNT]; + StdVideoDecodeH264ReferenceInfo h264_refs [H264_MAX_PICTURE_COUNT]; + VkVideoDecodeH264DpbSlotInfoKHR vkh264_refs[H264_MAX_PICTURE_COUNT]; + + /* Current picture (contd.) */ + StdVideoDecodeH264PictureInfo h264pic; + VkVideoDecodeH264PictureInfoKHR h264_pic_info; +} H264VulkanDecodePicture; + +static int vk_h264_fill_pict(AVCodecContext *avctx, H264Picture **ref_src, + VkVideoReferenceSlotInfoKHR *ref_slot, /* Main structure */ + VkVideoPictureResourceInfoKHR *ref, /* Goes in ^ */ + VkVideoDecodeH264DpbSlotInfoKHR *vkh264_ref, /* Goes in ^ */ + StdVideoDecodeH264ReferenceInfo *h264_ref, /* Goes in ^ */ + H264Picture *pic, int is_current, + int is_field, int picture_structure, + int dpb_slot_index) +{ + FFVulkanDecodeContext *dec = avctx->internal->hwaccel_priv_data; + H264VulkanDecodePicture *hp = pic->hwaccel_picture_private; + FFVulkanDecodePicture *vkpic = &hp->vp; + + int err = ff_vk_decode_prepare_frame(dec, pic->f, vkpic, is_current, + dec->dedicated_dpb); + if (err < 0) + return err; + + *h264_ref = (StdVideoDecodeH264ReferenceInfo) { + .FrameNum = pic->long_ref ? pic->pic_id : pic->frame_num, + .PicOrderCnt = { pic->field_poc[0], pic->field_poc[1] }, + .flags = (StdVideoDecodeH264ReferenceInfoFlags) { + .top_field_flag = is_field ? !!(picture_structure & PICT_TOP_FIELD) : 0, + .bottom_field_flag = is_field ? !!(picture_structure & PICT_BOTTOM_FIELD) : 0, + .used_for_long_term_reference = pic->reference && pic->long_ref, + .is_non_existing = 0, + }, + }; + + *vkh264_ref = (VkVideoDecodeH264DpbSlotInfoKHR) { + .sType = VK_STRUCTURE_TYPE_VIDEO_DECODE_H264_DPB_SLOT_INFO_KHR, + .pStdReferenceInfo = h264_ref, + }; + + *ref = (VkVideoPictureResourceInfoKHR) { + .sType = VK_STRUCTURE_TYPE_VIDEO_PICTURE_RESOURCE_INFO_KHR, + .codedOffset = (VkOffset2D){ 0, 0 }, + .codedExtent = (VkExtent2D){ pic->f->width, pic->f->height }, + .baseArrayLayer = dec->layered_dpb ? dpb_slot_index : 0, + .imageViewBinding = vkpic->img_view_ref, + }; + + *ref_slot = (VkVideoReferenceSlotInfoKHR) { + .sType = VK_STRUCTURE_TYPE_VIDEO_REFERENCE_SLOT_INFO_KHR, + .pNext = vkh264_ref, + .slotIndex = dpb_slot_index, + .pPictureResource = ref, + }; + + if (ref_src) + *ref_src = pic; + + return 0; +} + +static StdVideoH264LevelIdc convert_to_vk_level_idc(int level_idc) +{ + switch (level_idc) { + case 10: return STD_VIDEO_H264_LEVEL_IDC_1_0; + case 11: return STD_VIDEO_H264_LEVEL_IDC_1_1; + case 12: return STD_VIDEO_H264_LEVEL_IDC_1_2; + case 13: return STD_VIDEO_H264_LEVEL_IDC_1_3; + case 20: return STD_VIDEO_H264_LEVEL_IDC_2_0; + case 21: return STD_VIDEO_H264_LEVEL_IDC_2_1; + case 22: return STD_VIDEO_H264_LEVEL_IDC_2_2; + case 30: return STD_VIDEO_H264_LEVEL_IDC_3_0; + case 31: return STD_VIDEO_H264_LEVEL_IDC_3_1; + case 32: return STD_VIDEO_H264_LEVEL_IDC_3_2; + case 40: return STD_VIDEO_H264_LEVEL_IDC_4_0; + case 41: return STD_VIDEO_H264_LEVEL_IDC_4_1; + case 42: return STD_VIDEO_H264_LEVEL_IDC_4_2; + case 50: return STD_VIDEO_H264_LEVEL_IDC_5_0; + case 51: return STD_VIDEO_H264_LEVEL_IDC_5_1; + case 52: return STD_VIDEO_H264_LEVEL_IDC_5_2; + case 60: return STD_VIDEO_H264_LEVEL_IDC_6_0; + case 61: return STD_VIDEO_H264_LEVEL_IDC_6_1; + default: + case 62: return STD_VIDEO_H264_LEVEL_IDC_6_2; + } +} + +static void set_sps(const SPS *sps, + StdVideoH264ScalingLists *vksps_scaling, + StdVideoH264HrdParameters *vksps_vui_header, + StdVideoH264SequenceParameterSetVui *vksps_vui, + StdVideoH264SequenceParameterSet *vksps) +{ + *vksps_scaling = (StdVideoH264ScalingLists) { + .scaling_list_present_mask = sps->scaling_matrix_present_mask, + .use_default_scaling_matrix_mask = 0, /* We already fill in the default matrix */ + }; + + for (int i = 0; i < STD_VIDEO_H264_SCALING_LIST_4X4_NUM_LISTS; i++) + memcpy(vksps_scaling->ScalingList4x4[i], sps->scaling_matrix4[i], + STD_VIDEO_H264_SCALING_LIST_4X4_NUM_ELEMENTS * sizeof(**sps->scaling_matrix4)); + + for (int i = 0; i < STD_VIDEO_H264_SCALING_LIST_8X8_NUM_LISTS; i++) + memcpy(vksps_scaling->ScalingList8x8[i], sps->scaling_matrix8[i], + STD_VIDEO_H264_SCALING_LIST_8X8_NUM_ELEMENTS * sizeof(**sps->scaling_matrix8)); + + *vksps_vui_header = (StdVideoH264HrdParameters) { + .cpb_cnt_minus1 = sps->cpb_cnt - 1, + .bit_rate_scale = sps->bit_rate_scale, + .initial_cpb_removal_delay_length_minus1 = sps->initial_cpb_removal_delay_length - 1, + .cpb_removal_delay_length_minus1 = sps->cpb_removal_delay_length - 1, + .dpb_output_delay_length_minus1 = sps->dpb_output_delay_length - 1, + .time_offset_length = sps->time_offset_length, + }; + + for (int i = 0; i < sps->cpb_cnt; i++) { + vksps_vui_header->bit_rate_value_minus1[i] = sps->bit_rate_value[i] - 1; + vksps_vui_header->cpb_size_value_minus1[i] = sps->cpb_size_value[i] - 1; + vksps_vui_header->cbr_flag[i] = (sps->cpr_flag >> i) & 0x1; + } + + *vksps_vui = (StdVideoH264SequenceParameterSetVui) { + .aspect_ratio_idc = sps->vui.aspect_ratio_idc, + .sar_width = sps->vui.sar.num, + .sar_height = sps->vui.sar.den, + .video_format = sps->vui.video_format, + .colour_primaries = sps->vui.colour_primaries, + .transfer_characteristics = sps->vui.transfer_characteristics, + .matrix_coefficients = sps->vui.matrix_coeffs, + .num_units_in_tick = sps->num_units_in_tick, + .time_scale = sps->time_scale, + .pHrdParameters = vksps_vui_header, + .max_num_reorder_frames = sps->num_reorder_frames, + .max_dec_frame_buffering = sps->max_dec_frame_buffering, + .flags = (StdVideoH264SpsVuiFlags) { + .aspect_ratio_info_present_flag = sps->vui.aspect_ratio_info_present_flag, + .overscan_info_present_flag = sps->vui.overscan_info_present_flag, + .overscan_appropriate_flag = sps->vui.overscan_appropriate_flag, + .video_signal_type_present_flag = sps->vui.video_signal_type_present_flag, + .video_full_range_flag = sps->vui.video_full_range_flag, + .color_description_present_flag = sps->vui.colour_description_present_flag, + .chroma_loc_info_present_flag = sps->vui.chroma_location, + .timing_info_present_flag = sps->timing_info_present_flag, + .fixed_frame_rate_flag = sps->fixed_frame_rate_flag, + .bitstream_restriction_flag = sps->bitstream_restriction_flag, + .nal_hrd_parameters_present_flag = sps->nal_hrd_parameters_present_flag, + .vcl_hrd_parameters_present_flag = sps->vcl_hrd_parameters_present_flag, + }, + }; + + *vksps = (StdVideoH264SequenceParameterSet) { + .profile_idc = sps->profile_idc, + .level_idc = convert_to_vk_level_idc(sps->level_idc), + .seq_parameter_set_id = sps->sps_id, + .chroma_format_idc = sps->chroma_format_idc, + .bit_depth_luma_minus8 = sps->bit_depth_luma - 8, + .bit_depth_chroma_minus8 = sps->bit_depth_chroma - 8, + .log2_max_frame_num_minus4 = sps->log2_max_frame_num - 4, + .pic_order_cnt_type = sps->poc_type, + .log2_max_pic_order_cnt_lsb_minus4 = sps->poc_type ? 0 : sps->log2_max_poc_lsb - 4, + .offset_for_non_ref_pic = sps->offset_for_non_ref_pic, + .offset_for_top_to_bottom_field = sps->offset_for_top_to_bottom_field, + .num_ref_frames_in_pic_order_cnt_cycle = sps->poc_cycle_length, + .max_num_ref_frames = sps->ref_frame_count, + .pic_width_in_mbs_minus1 = sps->mb_width - 1, + .pic_height_in_map_units_minus1 = (sps->mb_height/(2 - sps->frame_mbs_only_flag)) - 1, + .frame_crop_left_offset = sps->crop_left, + .frame_crop_right_offset = sps->crop_right, + .frame_crop_top_offset = sps->crop_top, + .frame_crop_bottom_offset = sps->crop_bottom, + .flags = (StdVideoH264SpsFlags) { + .constraint_set0_flag = (sps->constraint_set_flags >> 0) & 0x1, + .constraint_set1_flag = (sps->constraint_set_flags >> 1) & 0x1, + .constraint_set2_flag = (sps->constraint_set_flags >> 2) & 0x1, + .constraint_set3_flag = (sps->constraint_set_flags >> 3) & 0x1, + .constraint_set4_flag = (sps->constraint_set_flags >> 4) & 0x1, + .constraint_set5_flag = (sps->constraint_set_flags >> 5) & 0x1, + .direct_8x8_inference_flag = sps->direct_8x8_inference_flag, + .mb_adaptive_frame_field_flag = sps->mb_aff, + .frame_mbs_only_flag = sps->frame_mbs_only_flag, + .delta_pic_order_always_zero_flag = sps->delta_pic_order_always_zero_flag, + .separate_colour_plane_flag = sps->residual_color_transform_flag, + .gaps_in_frame_num_value_allowed_flag = sps->gaps_in_frame_num_allowed_flag, + .qpprime_y_zero_transform_bypass_flag = sps->transform_bypass, + .frame_cropping_flag = sps->crop, + .seq_scaling_matrix_present_flag = sps->scaling_matrix_present, + .vui_parameters_present_flag = sps->vui_parameters_present_flag, + }, + .pOffsetForRefFrame = sps->offset_for_ref_frame, + .pScalingLists = vksps_scaling, + .pSequenceParameterSetVui = vksps_vui, + }; +} + +static void set_pps(const PPS *pps, const SPS *sps, + StdVideoH264ScalingLists *vkpps_scaling, + StdVideoH264PictureParameterSet *vkpps) +{ + *vkpps_scaling = (StdVideoH264ScalingLists) { + .scaling_list_present_mask = pps->pic_scaling_matrix_present_mask, + .use_default_scaling_matrix_mask = 0, /* We already fill in the default matrix */ + }; + + for (int i = 0; i < STD_VIDEO_H264_SCALING_LIST_4X4_NUM_LISTS; i++) + memcpy(vkpps_scaling->ScalingList4x4[i], pps->scaling_matrix4[i], + STD_VIDEO_H264_SCALING_LIST_4X4_NUM_ELEMENTS * sizeof(**pps->scaling_matrix4)); + + for (int i = 0; i < STD_VIDEO_H264_SCALING_LIST_8X8_NUM_LISTS; i++) + memcpy(vkpps_scaling->ScalingList8x8[i], pps->scaling_matrix8[i], + STD_VIDEO_H264_SCALING_LIST_8X8_NUM_ELEMENTS * sizeof(**pps->scaling_matrix8)); + + *vkpps = (StdVideoH264PictureParameterSet) { + .seq_parameter_set_id = pps->sps_id, + .pic_parameter_set_id = pps->pps_id, + .num_ref_idx_l0_default_active_minus1 = pps->ref_count[0] - 1, + .num_ref_idx_l1_default_active_minus1 = pps->ref_count[1] - 1, + .weighted_bipred_idc = pps->weighted_bipred_idc, + .pic_init_qp_minus26 = pps->init_qp - 26, + .pic_init_qs_minus26 = pps->init_qs - 26, + .chroma_qp_index_offset = pps->chroma_qp_index_offset[0], + .second_chroma_qp_index_offset = pps->chroma_qp_index_offset[1], + .flags = (StdVideoH264PpsFlags) { + .transform_8x8_mode_flag = pps->transform_8x8_mode, + .redundant_pic_cnt_present_flag = pps->redundant_pic_cnt_present, + .constrained_intra_pred_flag = pps->constrained_intra_pred, + .deblocking_filter_control_present_flag = pps->deblocking_filter_parameters_present, + .weighted_pred_flag = pps->weighted_pred, + .bottom_field_pic_order_in_frame_present_flag = pps->pic_order_present, + .entropy_coding_mode_flag = pps->cabac, + .pic_scaling_matrix_present_flag = pps->pic_scaling_matrix_present_flag, + }, + .pScalingLists = vkpps_scaling, + }; +} + +static int vk_h264_create_params(AVCodecContext *avctx, AVBufferRef **buf) +{ + VkResult ret; + FFVulkanDecodeContext *dec = avctx->internal->hwaccel_priv_data; + FFVulkanDecodeShared *ctx = (FFVulkanDecodeShared *)dec->shared_ref->data; + FFVulkanFunctions *vk = &ctx->s.vkfn; + const H264Context *h = avctx->priv_data; + + /* SPS */ + StdVideoH264ScalingLists vksps_scaling[MAX_SPS_COUNT]; + StdVideoH264HrdParameters vksps_vui_header[MAX_SPS_COUNT]; + StdVideoH264SequenceParameterSetVui vksps_vui[MAX_SPS_COUNT]; + StdVideoH264SequenceParameterSet vksps[MAX_SPS_COUNT]; + + /* PPS */ + StdVideoH264ScalingLists vkpps_scaling[MAX_PPS_COUNT]; + StdVideoH264PictureParameterSet vkpps[MAX_PPS_COUNT]; + + VkVideoDecodeH264SessionParametersAddInfoKHR h264_params_info = { + .sType = VK_STRUCTURE_TYPE_VIDEO_DECODE_H264_SESSION_PARAMETERS_ADD_INFO_KHR, + .pStdSPSs = vksps, + .stdSPSCount = 0, + .pStdPPSs = vkpps, + .stdPPSCount = 0, + }; + VkVideoDecodeH264SessionParametersCreateInfoKHR h264_params = { + .sType = VK_STRUCTURE_TYPE_VIDEO_DECODE_H264_SESSION_PARAMETERS_CREATE_INFO_KHR, + .pParametersAddInfo = &h264_params_info, + }; + VkVideoSessionParametersCreateInfoKHR session_params_create = { + .sType = VK_STRUCTURE_TYPE_VIDEO_SESSION_PARAMETERS_CREATE_INFO_KHR, + .pNext = &h264_params, + .videoSession = ctx->common.session, + .videoSessionParametersTemplate = NULL, + }; + + AVBufferRef *tmp; + VkVideoSessionParametersKHR *par = av_malloc(sizeof(*par)); + if (!par) + return AVERROR(ENOMEM); + + /* SPS list */ + for (int i = 0; i < FF_ARRAY_ELEMS(h->ps.sps_list); i++) { + if (h->ps.sps_list[i]) { + const SPS *sps_l = (const SPS *)h->ps.sps_list[i]->data; + int idx = h264_params_info.stdSPSCount; + set_sps(sps_l, &vksps_scaling[idx], &vksps_vui_header[idx], &vksps_vui[idx], &vksps[idx]); + h264_params_info.stdSPSCount++; + } + } + + /* PPS list */ + for (int i = 0; i < FF_ARRAY_ELEMS(h->ps.pps_list); i++) { + if (h->ps.pps_list[i]) { + const PPS *pps_l = (const PPS *)h->ps.pps_list[i]->data; + int idx = h264_params_info.stdPPSCount; + set_pps(pps_l, pps_l->sps, &vkpps_scaling[idx], &vkpps[idx]); + h264_params_info.stdPPSCount++; + } + } + + h264_params.maxStdSPSCount = h264_params_info.stdSPSCount; + h264_params.maxStdPPSCount = h264_params_info.stdPPSCount; + + /* Create session parameters */ + ret = vk->CreateVideoSessionParametersKHR(ctx->s.hwctx->act_dev, &session_params_create, + ctx->s.hwctx->alloc, par); + if (ret != VK_SUCCESS) { + av_log(avctx, AV_LOG_ERROR, "Unable to create Vulkan video session parameters: %s!\n", + ff_vk_ret2str(ret)); + return AVERROR_EXTERNAL; + } + + tmp = av_buffer_create((uint8_t *)par, sizeof(*par), ff_vk_decode_free_params, + ctx, 0); + if (!tmp) { + ff_vk_decode_free_params(ctx, (uint8_t *)par); + return AVERROR(ENOMEM); + } + + av_log(avctx, AV_LOG_DEBUG, "Created frame parameters: %i SPS %i PPS\n", + h264_params_info.stdSPSCount, h264_params_info.stdPPSCount); + + *buf = tmp; + + return 0; +} + +static int vk_h264_start_frame(AVCodecContext *avctx, + av_unused const uint8_t *buffer, + av_unused uint32_t size) +{ + int err; + int dpb_slot_index = 0; + H264Context *h = avctx->priv_data; + H264Picture *pic = h->cur_pic_ptr; + FFVulkanDecodeContext *dec = avctx->internal->hwaccel_priv_data; + H264VulkanDecodePicture *hp = pic->hwaccel_picture_private; + FFVulkanDecodePicture *vp = &hp->vp; + + if (!dec->session_params || dec->params_changed) { + av_buffer_unref(&dec->session_params); + err = vk_h264_create_params(avctx, &dec->session_params); + if (err < 0) + return err; + dec->params_changed = 0; + } + + /* Fill in main slot */ + dpb_slot_index = 0; + for (unsigned slot = 0; slot < H264_MAX_PICTURE_COUNT; slot++) { + if (pic == &h->DPB[slot]) { + dpb_slot_index = slot; + break; + } + } + + err = vk_h264_fill_pict(avctx, NULL, &vp->ref_slot, &vp->ref, + &hp->vkh264_ref, &hp->h264_ref, pic, 1, + h->DPB[dpb_slot_index].field_picture, + h->DPB[dpb_slot_index].reference, + dpb_slot_index); + if (err < 0) + return err; + + /* Fill in short-term references */ + for (int i = 0; i < h->short_ref_count; i++) { + dpb_slot_index = 0; + for (unsigned slot = 0; slot < H264_MAX_PICTURE_COUNT; slot++) { + if (h->short_ref[i] == &h->DPB[slot]) { + dpb_slot_index = slot; + break; + } + } + err = vk_h264_fill_pict(avctx, &hp->ref_src[i], &vp->ref_slots[i], + &vp->refs[i], &hp->vkh264_refs[i], + &hp->h264_refs[i], h->short_ref[i], 0, + h->DPB[dpb_slot_index].field_picture, + h->DPB[dpb_slot_index].reference, + dpb_slot_index); + if (err < 0) + return err; + } + + /* Fill in long-term refs */ + for (int r = 0, i = h->short_ref_count; i < h->short_ref_count + h->long_ref_count; i++, r++) { + dpb_slot_index = 0; + for (unsigned slot = 0; slot < H264_MAX_PICTURE_COUNT; slot++) { + if (h->long_ref[i] == &h->DPB[slot]) { + dpb_slot_index = slot; + break; + } + } + err = vk_h264_fill_pict(avctx, &hp->ref_src[i], &vp->ref_slots[i], + &vp->refs[i], &hp->vkh264_refs[i], + &hp->h264_refs[i], h->long_ref[r], 0, + h->DPB[dpb_slot_index].field_picture, + h->DPB[dpb_slot_index].reference, + dpb_slot_index); + if (err < 0) + return err; + } + + hp->h264pic = (StdVideoDecodeH264PictureInfo) { + .seq_parameter_set_id = pic->pps->sps_id, + .pic_parameter_set_id = pic->pps->pps_id, + .frame_num = 0, /* Set later */ + .idr_pic_id = 0, /* Set later */ + .PicOrderCnt[0] = pic->field_poc[0], + .PicOrderCnt[1] = pic->field_poc[1], + .flags = (StdVideoDecodeH264PictureInfoFlags) { + .field_pic_flag = FIELD_PICTURE(h), + .is_intra = 1, /* Set later */ + .IdrPicFlag = h->picture_idr, + .bottom_field_flag = h->picture_structure != PICT_FRAME && + h->picture_structure & PICT_BOTTOM_FIELD, + .is_reference = h->nal_ref_idc != 0, + .complementary_field_pair = h->first_field && FIELD_PICTURE(h), + }, + }; + + hp->h264_pic_info = (VkVideoDecodeH264PictureInfoKHR) { + .sType = VK_STRUCTURE_TYPE_VIDEO_DECODE_H264_PICTURE_INFO_KHR, + .pStdPictureInfo = &hp->h264pic, + .sliceCount = 0, + }; + + vp->decode_info = (VkVideoDecodeInfoKHR) { + .sType = VK_STRUCTURE_TYPE_VIDEO_DECODE_INFO_KHR, + .pNext = &hp->h264_pic_info, + .flags = 0x0, + .pSetupReferenceSlot = &vp->ref_slot, + .referenceSlotCount = h->short_ref_count + h->long_ref_count, + .pReferenceSlots = vp->ref_slots, + .dstPictureResource = (VkVideoPictureResourceInfoKHR) { + .sType = VK_STRUCTURE_TYPE_VIDEO_PICTURE_RESOURCE_INFO_KHR, + .codedOffset = (VkOffset2D){ 0, 0 }, + .codedExtent = (VkExtent2D){ pic->f->width, pic->f->height }, + .baseArrayLayer = 0, + .imageViewBinding = vp->img_view_out, + }, + }; + + return 0; +} + +static int vk_h264_decode_slice(AVCodecContext *avctx, + const uint8_t *data, + uint32_t size) +{ + const H264Context *h = avctx->priv_data; + const H264SliceContext *sl = &h->slice_ctx[0]; + H264VulkanDecodePicture *hp = h->cur_pic_ptr->hwaccel_picture_private; + FFVulkanDecodePicture *vp = &hp->vp; + + int err = ff_vk_decode_add_slice(avctx, vp, data, size, 1, + &hp->h264_pic_info.sliceCount, + &hp->h264_pic_info.pSliceOffsets); + if (err < 0) + return err; + + hp->h264pic.frame_num = sl->frame_num; + hp->h264pic.idr_pic_id = sl->idr_pic_id; + + /* Frame is only intra of all slices are marked as intra */ + if (sl->slice_type != AV_PICTURE_TYPE_I && sl->slice_type != AV_PICTURE_TYPE_SI) + hp->h264pic.flags.is_intra = 0; + + return 0; +} + +static int vk_h264_end_frame(AVCodecContext *avctx) +{ + const H264Context *h = avctx->priv_data; + H264Picture *pic = h->cur_pic_ptr; + H264VulkanDecodePicture *hp = pic->hwaccel_picture_private; + FFVulkanDecodePicture *vp = &hp->vp; + FFVulkanDecodePicture *rvp[H264_MAX_PICTURE_COUNT] = { 0 }; + AVFrame *rav[H264_MAX_PICTURE_COUNT] = { 0 }; + + for (int i = 0; i < vp->decode_info.referenceSlotCount; i++) { + H264Picture *rp = hp->ref_src[i]; + H264VulkanDecodePicture *rhp = rp->hwaccel_picture_private; + + rvp[i] = &rhp->vp; + rav[i] = hp->ref_src[i]->f; + } + + av_log(avctx, AV_LOG_VERBOSE, "Decoding frame, %lu bytes, %i slices\n", + vp->slices_size, hp->h264_pic_info.sliceCount); + + return ff_vk_decode_frame(avctx, pic->f, vp, rav, rvp); +} + +static void vk_h264_free_frame_priv(void *_hwctx, uint8_t *data) +{ + AVHWDeviceContext *hwctx = _hwctx; + H264VulkanDecodePicture *hp = (H264VulkanDecodePicture *)data; + + /* Free frame resources, this also destroys the session parameters. */ + ff_vk_decode_free_frame(hwctx, &hp->vp); + + /* Free frame context */ + av_free(hp); +} + +const AVHWAccel ff_h264_vulkan_hwaccel = { + .name = "h264_vulkan", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_H264, + .pix_fmt = AV_PIX_FMT_VULKAN, + .start_frame = &vk_h264_start_frame, + .decode_slice = &vk_h264_decode_slice, + .end_frame = &vk_h264_end_frame, + .free_frame_priv = &vk_h264_free_frame_priv, + .frame_priv_data_size = sizeof(H264VulkanDecodePicture), + .init = &ff_vk_decode_init, + .update_thread_context = &ff_vk_update_thread_context, + .decode_params = &ff_vk_params_changed, + .flush = &ff_vk_decode_flush, + .uninit = &ff_vk_decode_uninit, + .frame_params = &ff_vk_frame_params, + .priv_data_size = sizeof(FFVulkanDecodeContext), + .caps_internal = HWACCEL_CAP_ASYNC_SAFE | HWACCEL_CAP_THREAD_SAFE, +}; From 36c16a06b2e31a39c236d724c2fd5d457f02493a Mon Sep 17 00:00:00 2001 From: Lynne Date: Wed, 14 Dec 2022 08:27:18 +0100 Subject: [PATCH 1294/2172] hevcdec: add Vulkan hwaccel Thanks to Dave Airlie for figuring out a lot of the parameters. --- configure | 2 + libavcodec/Makefile | 1 + libavcodec/hevcdec.c | 25 +- libavcodec/hwaccels.h | 1 + libavcodec/vulkan_hevc.c | 948 +++++++++++++++++++++++++++++++++++++++ 5 files changed, 976 insertions(+), 1 deletion(-) create mode 100644 libavcodec/vulkan_hevc.c diff --git a/configure b/configure index c149ae1291f..61916fc2bc9 100755 --- a/configure +++ b/configure @@ -3054,6 +3054,8 @@ hevc_vdpau_hwaccel_deps="vdpau VdpPictureInfoHEVC" hevc_vdpau_hwaccel_select="hevc_decoder" hevc_videotoolbox_hwaccel_deps="videotoolbox" hevc_videotoolbox_hwaccel_select="hevc_decoder" +hevc_vulkan_hwaccel_deps="vulkan" +hevc_vulkan_hwaccel_select="hevc_decoder" mjpeg_nvdec_hwaccel_deps="nvdec" mjpeg_nvdec_hwaccel_select="mjpeg_decoder" mjpeg_vaapi_hwaccel_deps="vaapi" diff --git a/libavcodec/Makefile b/libavcodec/Makefile index 62b24630bf9..d4218449031 100644 --- a/libavcodec/Makefile +++ b/libavcodec/Makefile @@ -1005,6 +1005,7 @@ OBJS-$(CONFIG_HEVC_NVDEC_HWACCEL) += nvdec_hevc.o OBJS-$(CONFIG_HEVC_QSV_HWACCEL) += qsvdec.o OBJS-$(CONFIG_HEVC_VAAPI_HWACCEL) += vaapi_hevc.o h265_profile_level.o OBJS-$(CONFIG_HEVC_VDPAU_HWACCEL) += vdpau_hevc.o h265_profile_level.o +OBJS-$(CONFIG_HEVC_VULKAN_HWACCEL) += vulkan_decode.o vulkan_hevc.o OBJS-$(CONFIG_MJPEG_NVDEC_HWACCEL) += nvdec_mjpeg.o OBJS-$(CONFIG_MJPEG_VAAPI_HWACCEL) += vaapi_mjpeg.o OBJS-$(CONFIG_MPEG1_NVDEC_HWACCEL) += nvdec_mpeg12.o diff --git a/libavcodec/hevcdec.c b/libavcodec/hevcdec.c index 8764e0bd83e..eee77ec4dbb 100644 --- a/libavcodec/hevcdec.c +++ b/libavcodec/hevcdec.c @@ -405,7 +405,8 @@ static enum AVPixelFormat get_format(HEVCContext *s, const HEVCSPS *sps) CONFIG_HEVC_NVDEC_HWACCEL + \ CONFIG_HEVC_VAAPI_HWACCEL + \ CONFIG_HEVC_VIDEOTOOLBOX_HWACCEL + \ - CONFIG_HEVC_VDPAU_HWACCEL) + CONFIG_HEVC_VDPAU_HWACCEL + \ + CONFIG_HEVC_VULKAN_HWACCEL) enum AVPixelFormat pix_fmts[HWACCEL_MAX + 2], *fmt = pix_fmts; switch (sps->pix_fmt) { @@ -429,6 +430,9 @@ static enum AVPixelFormat get_format(HEVCContext *s, const HEVCSPS *sps) #endif #if CONFIG_HEVC_VIDEOTOOLBOX_HWACCEL *fmt++ = AV_PIX_FMT_VIDEOTOOLBOX; +#endif +#if CONFIG_HEVC_VULKAN_HWACCEL + *fmt++ = AV_PIX_FMT_VULKAN; #endif break; case AV_PIX_FMT_YUV420P10: @@ -445,6 +449,9 @@ static enum AVPixelFormat get_format(HEVCContext *s, const HEVCSPS *sps) #if CONFIG_HEVC_VIDEOTOOLBOX_HWACCEL *fmt++ = AV_PIX_FMT_VIDEOTOOLBOX; #endif +#if CONFIG_HEVC_VULKAN_HWACCEL + *fmt++ = AV_PIX_FMT_VULKAN; +#endif #if CONFIG_HEVC_VDPAU_HWACCEL *fmt++ = AV_PIX_FMT_VDPAU; #endif @@ -464,6 +471,9 @@ static enum AVPixelFormat get_format(HEVCContext *s, const HEVCSPS *sps) #endif #if CONFIG_HEVC_VIDEOTOOLBOX_HWACCEL *fmt++ = AV_PIX_FMT_VIDEOTOOLBOX; +#endif +#if CONFIG_HEVC_VULKAN_HWACCEL + *fmt++ = AV_PIX_FMT_VULKAN; #endif break; case AV_PIX_FMT_YUV422P: @@ -473,12 +483,16 @@ static enum AVPixelFormat get_format(HEVCContext *s, const HEVCSPS *sps) #endif #if CONFIG_HEVC_VIDEOTOOLBOX_HWACCEL *fmt++ = AV_PIX_FMT_VIDEOTOOLBOX; +#endif +#if CONFIG_HEVC_VULKAN_HWACCEL + *fmt++ = AV_PIX_FMT_VULKAN; #endif break; case AV_PIX_FMT_YUV444P10: #if CONFIG_HEVC_VIDEOTOOLBOX_HWACCEL *fmt++ = AV_PIX_FMT_VIDEOTOOLBOX; #endif + /* NOTE: fallthrough */ case AV_PIX_FMT_YUV420P12: case AV_PIX_FMT_YUV444P12: #if CONFIG_HEVC_VAAPI_HWACCEL @@ -487,6 +501,9 @@ static enum AVPixelFormat get_format(HEVCContext *s, const HEVCSPS *sps) #if CONFIG_HEVC_VDPAU_HWACCEL *fmt++ = AV_PIX_FMT_VDPAU; #endif +#if CONFIG_HEVC_VULKAN_HWACCEL + *fmt++ = AV_PIX_FMT_VULKAN; +#endif #if CONFIG_HEVC_NVDEC_HWACCEL *fmt++ = AV_PIX_FMT_CUDA; #endif @@ -494,6 +511,9 @@ static enum AVPixelFormat get_format(HEVCContext *s, const HEVCSPS *sps) case AV_PIX_FMT_YUV422P12: #if CONFIG_HEVC_VAAPI_HWACCEL *fmt++ = AV_PIX_FMT_VAAPI; +#endif +#if CONFIG_HEVC_VULKAN_HWACCEL + *fmt++ = AV_PIX_FMT_VULKAN; #endif break; } @@ -3769,6 +3789,9 @@ const FFCodec ff_hevc_decoder = { #endif #if CONFIG_HEVC_VIDEOTOOLBOX_HWACCEL HWACCEL_VIDEOTOOLBOX(hevc), +#endif +#if CONFIG_HEVC_VULKAN_HWACCEL + HWACCEL_VULKAN(hevc), #endif NULL }, diff --git a/libavcodec/hwaccels.h b/libavcodec/hwaccels.h index 23d0843c76f..a7c74d07cbd 100644 --- a/libavcodec/hwaccels.h +++ b/libavcodec/hwaccels.h @@ -44,6 +44,7 @@ extern const AVHWAccel ff_hevc_nvdec_hwaccel; extern const AVHWAccel ff_hevc_vaapi_hwaccel; extern const AVHWAccel ff_hevc_vdpau_hwaccel; extern const AVHWAccel ff_hevc_videotoolbox_hwaccel; +extern const AVHWAccel ff_hevc_vulkan_hwaccel; extern const AVHWAccel ff_mjpeg_nvdec_hwaccel; extern const AVHWAccel ff_mjpeg_vaapi_hwaccel; extern const AVHWAccel ff_mpeg1_nvdec_hwaccel; diff --git a/libavcodec/vulkan_hevc.c b/libavcodec/vulkan_hevc.c new file mode 100644 index 00000000000..592b2526e86 --- /dev/null +++ b/libavcodec/vulkan_hevc.c @@ -0,0 +1,948 @@ +/* + * 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 "hevcdec.h" +#include "hevc_ps.h" + +#include "vulkan_decode.h" + +const VkExtensionProperties ff_vk_dec_hevc_ext = { + .extensionName = VK_STD_VULKAN_VIDEO_CODEC_H265_DECODE_EXTENSION_NAME, + .specVersion = VK_STD_VULKAN_VIDEO_CODEC_H265_DECODE_SPEC_VERSION, +}; + +typedef struct HEVCHeaderSPS { + StdVideoH265ScalingLists scaling; + StdVideoH265HrdParameters vui_header; + StdVideoH265SequenceParameterSetVui vui; + StdVideoH265ProfileTierLevel ptl; + StdVideoH265DecPicBufMgr dpbm; + StdVideoH265PredictorPaletteEntries pal; + StdVideoH265SubLayerHrdParameters nal_hdr[HEVC_MAX_SUB_LAYERS]; + StdVideoH265SubLayerHrdParameters vcl_hdr[HEVC_MAX_SUB_LAYERS]; + StdVideoH265ShortTermRefPicSet str[HEVC_MAX_SHORT_TERM_REF_PIC_SETS]; + StdVideoH265LongTermRefPicsSps ltr; +} HEVCHeaderSPS; + +typedef struct HEVCHeaderPPS { + StdVideoH265ScalingLists scaling; + StdVideoH265PredictorPaletteEntries pal; +} HEVCHeaderPPS; + +typedef struct HEVCHeaderVPSSet { + StdVideoH265SubLayerHrdParameters nal_hdr[HEVC_MAX_SUB_LAYERS]; + StdVideoH265SubLayerHrdParameters vcl_hdr[HEVC_MAX_SUB_LAYERS]; +} HEVCHeaderVPSSet; + +typedef struct HEVCHeaderVPS { + StdVideoH265ProfileTierLevel ptl; + StdVideoH265DecPicBufMgr dpbm; + StdVideoH265HrdParameters hdr[HEVC_MAX_LAYER_SETS]; + HEVCHeaderVPSSet *sls; +} HEVCHeaderVPS; + +typedef struct HEVCHeaderSet { + StdVideoH265SequenceParameterSet sps[HEVC_MAX_SPS_COUNT]; + HEVCHeaderSPS hsps[HEVC_MAX_SPS_COUNT]; + + StdVideoH265PictureParameterSet pps[HEVC_MAX_PPS_COUNT]; + HEVCHeaderPPS hpps[HEVC_MAX_PPS_COUNT]; + + StdVideoH265VideoParameterSet vps[HEVC_MAX_PPS_COUNT]; + HEVCHeaderVPS *hvps; +} HEVCHeaderSet; + +static int get_data_set_buf(FFVulkanDecodeContext *s, AVBufferRef **data_buf, + int nb_vps, AVBufferRef * const vps_list[HEVC_MAX_VPS_COUNT]) +{ + uint8_t *data_ptr; + HEVCHeaderSet *hdr; + + size_t base_size = sizeof(StdVideoH265SequenceParameterSet)*HEVC_MAX_SPS_COUNT + + sizeof(HEVCHeaderSPS)*HEVC_MAX_SPS_COUNT + + sizeof(StdVideoH265PictureParameterSet)*HEVC_MAX_PPS_COUNT + + sizeof(HEVCHeaderPPS)*HEVC_MAX_PPS_COUNT + + sizeof(StdVideoH265VideoParameterSet)*HEVC_MAX_VPS_COUNT + + sizeof(HEVCHeaderVPS *); + + size_t vps_size = sizeof(StdVideoH265ProfileTierLevel) + + sizeof(StdVideoH265DecPicBufMgr) + + sizeof(StdVideoH265HrdParameters)*HEVC_MAX_LAYER_SETS + + sizeof(HEVCHeaderVPSSet *); + + size_t buf_size = base_size + vps_size*nb_vps; + + for (int i = 0; i < nb_vps; i++) { + const HEVCVPS *vps = (const HEVCVPS *)vps_list[i]->data; + buf_size += sizeof(HEVCHeaderVPSSet)*vps->vps_num_hrd_parameters; + } + + if (buf_size > s->tmp_pool_ele_size) { + av_buffer_pool_uninit(&s->tmp_pool); + s->tmp_pool_ele_size = 0; + s->tmp_pool = av_buffer_pool_init(buf_size, NULL); + if (!s->tmp_pool) + return AVERROR(ENOMEM); + s->tmp_pool_ele_size = buf_size; + } + + *data_buf = av_buffer_pool_get(s->tmp_pool); + if (!(*data_buf)) + return AVERROR(ENOMEM); + + /* Setup pointers */ + data_ptr = (*data_buf)->data; + hdr = (HEVCHeaderSet *)data_ptr; + hdr->hvps = (HEVCHeaderVPS *)(data_ptr + base_size); + data_ptr += base_size + vps_size*nb_vps; + for (int i = 0; i < nb_vps; i++) { + const HEVCVPS *vps = (const HEVCVPS *)vps_list[i]->data; + hdr->hvps[i].sls = (HEVCHeaderVPSSet *)data_ptr; + data_ptr += sizeof(HEVCHeaderVPSSet)*vps->vps_num_hrd_parameters; + } + + return 0; +} + +typedef struct HEVCVulkanDecodePicture { + FFVulkanDecodePicture vp; + + /* Current picture */ + StdVideoDecodeH265ReferenceInfo h265_ref; + VkVideoDecodeH265DpbSlotInfoKHR vkh265_ref; + + /* Picture refs */ + HEVCFrame *ref_src [HEVC_MAX_REFS]; + StdVideoDecodeH265ReferenceInfo h265_refs [HEVC_MAX_REFS]; + VkVideoDecodeH265DpbSlotInfoKHR vkh265_refs[HEVC_MAX_REFS]; + + /* Current picture (contd.) */ + StdVideoDecodeH265PictureInfo h265pic; + VkVideoDecodeH265PictureInfoKHR h265_pic_info; +} HEVCVulkanDecodePicture; + +static int vk_hevc_fill_pict(AVCodecContext *avctx, HEVCFrame **ref_src, + VkVideoReferenceSlotInfoKHR *ref_slot, /* Main structure */ + VkVideoPictureResourceInfoKHR *ref, /* Goes in ^ */ + VkVideoDecodeH265DpbSlotInfoKHR *vkh265_ref, /* Goes in ^ */ + StdVideoDecodeH265ReferenceInfo *h265_ref, /* Goes in ^ */ + HEVCFrame *pic, int is_current, int pic_id) +{ + FFVulkanDecodeContext *dec = avctx->internal->hwaccel_priv_data; + HEVCVulkanDecodePicture *hp = pic->hwaccel_picture_private; + FFVulkanDecodePicture *vkpic = &hp->vp; + + int err = ff_vk_decode_prepare_frame(dec, pic->frame, vkpic, is_current, + dec->dedicated_dpb); + if (err < 0) + return err; + + *h265_ref = (StdVideoDecodeH265ReferenceInfo) { + .flags = (StdVideoDecodeH265ReferenceInfoFlags) { + .used_for_long_term_reference = pic->flags & HEVC_FRAME_FLAG_LONG_REF, + .unused_for_reference = 0, + }, + .PicOrderCntVal = pic->poc, + }; + + *vkh265_ref = (VkVideoDecodeH265DpbSlotInfoKHR) { + .sType = VK_STRUCTURE_TYPE_VIDEO_DECODE_H265_DPB_SLOT_INFO_KHR, + .pStdReferenceInfo = h265_ref, + }; + + *ref = (VkVideoPictureResourceInfoKHR) { + .sType = VK_STRUCTURE_TYPE_VIDEO_PICTURE_RESOURCE_INFO_KHR, + .codedOffset = (VkOffset2D){ 0, 0 }, + .codedExtent = (VkExtent2D){ pic->frame->width, pic->frame->height }, + .baseArrayLayer = dec->layered_dpb ? pic_id : 0, + .imageViewBinding = vkpic->img_view_ref, + }; + + *ref_slot = (VkVideoReferenceSlotInfoKHR) { + .sType = VK_STRUCTURE_TYPE_VIDEO_REFERENCE_SLOT_INFO_KHR, + .pNext = vkh265_ref, + .slotIndex = pic_id, + .pPictureResource = ref, + }; + + if (ref_src) + *ref_src = pic; + + return 0; +} + +static StdVideoH265LevelIdc convert_to_vk_level_idc(int level_idc) +{ + switch (level_idc) { + case 10: return STD_VIDEO_H265_LEVEL_IDC_1_0; + case 20: return STD_VIDEO_H265_LEVEL_IDC_2_0; + case 21: return STD_VIDEO_H265_LEVEL_IDC_2_1; + case 30: return STD_VIDEO_H265_LEVEL_IDC_3_0; + case 31: return STD_VIDEO_H265_LEVEL_IDC_3_1; + case 40: return STD_VIDEO_H265_LEVEL_IDC_4_0; + case 41: return STD_VIDEO_H265_LEVEL_IDC_4_1; + case 50: return STD_VIDEO_H265_LEVEL_IDC_5_0; + case 51: return STD_VIDEO_H265_LEVEL_IDC_5_1; + case 60: return STD_VIDEO_H265_LEVEL_IDC_6_0; + case 61: return STD_VIDEO_H265_LEVEL_IDC_6_1; + default: + case 62: return STD_VIDEO_H265_LEVEL_IDC_6_2; + } +} + +static void set_sps(const HEVCSPS *sps, int sps_idx, + StdVideoH265ScalingLists *vksps_scaling, + StdVideoH265HrdParameters *vksps_vui_header, + StdVideoH265SequenceParameterSetVui *vksps_vui, + StdVideoH265SequenceParameterSet *vksps, + StdVideoH265SubLayerHrdParameters *slhdrnal, + StdVideoH265SubLayerHrdParameters *slhdrvcl, + StdVideoH265ProfileTierLevel *ptl, + StdVideoH265DecPicBufMgr *dpbm, + StdVideoH265PredictorPaletteEntries *pal, + StdVideoH265ShortTermRefPicSet *str, + StdVideoH265LongTermRefPicsSps *ltr) +{ + for (int i = 0; i < STD_VIDEO_H265_SCALING_LIST_4X4_NUM_LISTS; i++) + memcpy(vksps_scaling->ScalingList4x4[i], sps->scaling_list.sl[0][i], + STD_VIDEO_H265_SCALING_LIST_4X4_NUM_ELEMENTS * sizeof(**vksps_scaling->ScalingList4x4)); + + for (int i = 0; i < STD_VIDEO_H265_SCALING_LIST_8X8_NUM_LISTS; i++) + memcpy(vksps_scaling->ScalingList8x8[i], sps->scaling_list.sl[1][i], + STD_VIDEO_H265_SCALING_LIST_8X8_NUM_ELEMENTS * sizeof(**vksps_scaling->ScalingList8x8)); + + for (int i = 0; i < STD_VIDEO_H265_SCALING_LIST_16X16_NUM_LISTS; i++) + memcpy(vksps_scaling->ScalingList16x16[i], sps->scaling_list.sl[2][i], + STD_VIDEO_H265_SCALING_LIST_4X4_NUM_ELEMENTS * sizeof(**vksps_scaling->ScalingList16x16)); + + for (int i = 0; i < STD_VIDEO_H265_SCALING_LIST_32X32_NUM_LISTS; i++) + memcpy(vksps_scaling->ScalingList32x32[i], sps->scaling_list.sl[3][i], + STD_VIDEO_H265_SCALING_LIST_32X32_NUM_ELEMENTS * sizeof(**vksps_scaling->ScalingList32x32)); + + memcpy(vksps_scaling->ScalingListDCCoef16x16, sps->scaling_list.sl_dc[0], + STD_VIDEO_H265_SCALING_LIST_4X4_NUM_ELEMENTS * sizeof(*vksps_scaling->ScalingListDCCoef16x16)); + + memcpy(vksps_scaling->ScalingListDCCoef32x32, sps->scaling_list.sl_dc[1], + STD_VIDEO_H265_SCALING_LIST_32X32_NUM_ELEMENTS * sizeof(*vksps_scaling->ScalingListDCCoef32x32)); + + *vksps_vui_header = (StdVideoH265HrdParameters) { + .flags = (StdVideoH265HrdFlags) { + .nal_hrd_parameters_present_flag = sps->hdr.flags.nal_hrd_parameters_present_flag, + .vcl_hrd_parameters_present_flag = sps->hdr.flags.vcl_hrd_parameters_present_flag, + .sub_pic_hrd_params_present_flag = sps->hdr.flags.sub_pic_hrd_params_present_flag, + .sub_pic_cpb_params_in_pic_timing_sei_flag = sps->hdr.flags.sub_pic_cpb_params_in_pic_timing_sei_flag, + .fixed_pic_rate_general_flag = sps->hdr.flags.fixed_pic_rate_general_flag, + .fixed_pic_rate_within_cvs_flag = sps->hdr.flags.fixed_pic_rate_within_cvs_flag, + .low_delay_hrd_flag = sps->hdr.flags.low_delay_hrd_flag, + }, + .tick_divisor_minus2 = sps->hdr.tick_divisor_minus2, + .du_cpb_removal_delay_increment_length_minus1 = sps->hdr.du_cpb_removal_delay_increment_length_minus1, + .dpb_output_delay_du_length_minus1 = sps->hdr.dpb_output_delay_du_length_minus1, + .bit_rate_scale = sps->hdr.bit_rate_scale, + .cpb_size_scale = sps->hdr.cpb_size_scale, + .cpb_size_du_scale = sps->hdr.cpb_size_du_scale, + .initial_cpb_removal_delay_length_minus1 = sps->hdr.initial_cpb_removal_delay_length_minus1, + .au_cpb_removal_delay_length_minus1 = sps->hdr.au_cpb_removal_delay_length_minus1, + .dpb_output_delay_length_minus1 = sps->hdr.dpb_output_delay_length_minus1, + /* Reserved - 3*16 bits */ + .pSubLayerHrdParametersNal = slhdrnal, + .pSubLayerHrdParametersVcl = slhdrvcl, + }; + + memcpy(vksps_vui_header->cpb_cnt_minus1, sps->hdr.cpb_cnt_minus1, + STD_VIDEO_H265_SUBLAYERS_LIST_SIZE*sizeof(*vksps_vui_header->cpb_cnt_minus1)); + memcpy(vksps_vui_header->elemental_duration_in_tc_minus1, sps->hdr.elemental_duration_in_tc_minus1, + STD_VIDEO_H265_SUBLAYERS_LIST_SIZE*sizeof(*vksps_vui_header->elemental_duration_in_tc_minus1)); + + memcpy(slhdrnal, sps->hdr.nal_params, HEVC_MAX_SUB_LAYERS*sizeof(*slhdrnal)); + memcpy(slhdrvcl, sps->hdr.vcl_params, HEVC_MAX_SUB_LAYERS*sizeof(*slhdrvcl)); + + *vksps_vui = (StdVideoH265SequenceParameterSetVui) { + .flags = (StdVideoH265SpsVuiFlags) { + .aspect_ratio_info_present_flag = sps->vui.common.aspect_ratio_info_present_flag, + .overscan_info_present_flag = sps->vui.common.overscan_info_present_flag, + .overscan_appropriate_flag = sps->vui.common.overscan_appropriate_flag, + .video_signal_type_present_flag = sps->vui.common.video_signal_type_present_flag, + .video_full_range_flag = sps->vui.common.video_full_range_flag, + .colour_description_present_flag = sps->vui.common.colour_description_present_flag, + .chroma_loc_info_present_flag = sps->vui.common.chroma_loc_info_present_flag, + .neutral_chroma_indication_flag = sps->vui.neutra_chroma_indication_flag, + .field_seq_flag = sps->vui.field_seq_flag, + .frame_field_info_present_flag = sps->vui.frame_field_info_present_flag, + .default_display_window_flag = sps->vui.default_display_window_flag, + .vui_timing_info_present_flag = sps->vui.vui_timing_info_present_flag, + .vui_poc_proportional_to_timing_flag = sps->vui.vui_poc_proportional_to_timing_flag, + .vui_hrd_parameters_present_flag = sps->vui.vui_hrd_parameters_present_flag, + .bitstream_restriction_flag = sps->vui.bitstream_restriction_flag, + .tiles_fixed_structure_flag = sps->vui.tiles_fixed_structure_flag, + .motion_vectors_over_pic_boundaries_flag = sps->vui.motion_vectors_over_pic_boundaries_flag, + .restricted_ref_pic_lists_flag = sps->vui.restricted_ref_pic_lists_flag, + }, + .aspect_ratio_idc = sps->vui.common.aspect_ratio_idc, + .sar_width = sps->vui.common.sar.num, + .sar_height = sps->vui.common.sar.den, + .video_format = sps->vui.common.video_format, + .colour_primaries = sps->vui.common.colour_primaries, + .transfer_characteristics = sps->vui.common.transfer_characteristics, + .matrix_coeffs = sps->vui.common.matrix_coeffs, + .chroma_sample_loc_type_top_field = sps->vui.common.chroma_sample_loc_type_top_field, + .chroma_sample_loc_type_bottom_field = sps->vui.common.chroma_sample_loc_type_bottom_field, + /* Reserved */ + /* Reserved */ + .def_disp_win_left_offset = sps->vui.def_disp_win.left_offset, + .def_disp_win_right_offset = sps->vui.def_disp_win.right_offset, + .def_disp_win_top_offset = sps->vui.def_disp_win.top_offset, + .def_disp_win_bottom_offset = sps->vui.def_disp_win.bottom_offset, + .vui_num_units_in_tick = sps->vui.vui_num_units_in_tick, + .vui_time_scale = sps->vui.vui_time_scale, + .vui_num_ticks_poc_diff_one_minus1 = sps->vui.vui_num_ticks_poc_diff_one_minus1, + .min_spatial_segmentation_idc = sps->vui.min_spatial_segmentation_idc, + .max_bytes_per_pic_denom = sps->vui.max_bytes_per_pic_denom, + .max_bits_per_min_cu_denom = sps->vui.max_bits_per_min_cu_denom, + .log2_max_mv_length_horizontal = sps->vui.log2_max_mv_length_horizontal, + .log2_max_mv_length_vertical = sps->vui.log2_max_mv_length_vertical, + .pHrdParameters = vksps_vui_header, + }; + + *ptl = (StdVideoH265ProfileTierLevel) { + .flags = (StdVideoH265ProfileTierLevelFlags) { + .general_tier_flag = sps->ptl.general_ptl.tier_flag, + .general_progressive_source_flag = sps->ptl.general_ptl.progressive_source_flag, + .general_interlaced_source_flag = sps->ptl.general_ptl.interlaced_source_flag, + .general_non_packed_constraint_flag = sps->ptl.general_ptl.non_packed_constraint_flag, + .general_frame_only_constraint_flag = sps->ptl.general_ptl.frame_only_constraint_flag, + }, + .general_profile_idc = sps->ptl.general_ptl.profile_idc, + .general_level_idc = convert_to_vk_level_idc(sps->ptl.general_ptl.level_idc), + }; + + for (int i = 0; i < sps->max_sub_layers; i++) { + dpbm->max_latency_increase_plus1[i] = sps->temporal_layer[i].max_latency_increase + 1; + dpbm->max_dec_pic_buffering_minus1[i] = sps->temporal_layer[i].max_dec_pic_buffering - 1; + dpbm->max_num_reorder_pics[i] = sps->temporal_layer[i].num_reorder_pics; + } + + for (int i = 0; i < (sps->chroma_format_idc ? 3 : 1); i++) + for (int j = 0; j < sps->sps_num_palette_predictor_initializers; j++) + pal->PredictorPaletteEntries[i][j] = sps->sps_palette_predictor_initializer[i][j]; + + for (int i = 0; i < sps->nb_st_rps; i++) { + str[i] = (StdVideoH265ShortTermRefPicSet) { + .flags = (StdVideoH265ShortTermRefPicSetFlags) { + .inter_ref_pic_set_prediction_flag = sps->st_rps[i].rps_predict, + .delta_rps_sign = sps->st_rps[i].delta_rps_sign, + }, + .delta_idx_minus1 = sps->st_rps[i].delta_idx - 1, + .use_delta_flag = sps->st_rps[i].use_delta_flag, + .abs_delta_rps_minus1 = sps->st_rps[i].abs_delta_rps - 1, + .used_by_curr_pic_flag = 0x0, + .used_by_curr_pic_s0_flag = 0x0, + .used_by_curr_pic_s1_flag = 0x0, + /* Reserved */ + /* Reserved */ + /* Reserved */ + .num_negative_pics = sps->st_rps[i].num_negative_pics, + .num_positive_pics = sps->st_rps[i].num_delta_pocs - sps->st_rps[i].num_negative_pics, + }; + + /* NOTE: This is the predicted, and *reordered* version. + * Probably incorrect, but the spec doesn't say which version to use. */ + for (int j = 0; j < sps->st_rps[i].num_delta_pocs; j++) + str[i].used_by_curr_pic_flag |= sps->st_rps[i].used[j] << j; + + for (int j = 0; j < str[i].num_negative_pics; j++) { + str[i].delta_poc_s0_minus1[j] = sps->st_rps[i].delta_poc_s0[j] - 1; + str[i].used_by_curr_pic_s0_flag |= sps->st_rps[i].used[j] << j; + } + + for (int j = 0; j < str[i].num_positive_pics; j++) { + str[i].delta_poc_s1_minus1[j] = sps->st_rps[i].delta_poc_s1[j] - 1; + str[i].used_by_curr_pic_s0_flag |= sps->st_rps[i].used[str[i].num_negative_pics + j] << j; + } + } + + *ltr = (StdVideoH265LongTermRefPicsSps) { + .used_by_curr_pic_lt_sps_flag = 0x0, + }; + + for (int i = 0; i < sps->num_long_term_ref_pics_sps; i++) { + ltr->used_by_curr_pic_lt_sps_flag |= sps->used_by_curr_pic_lt_sps_flag[i] << i; + ltr->lt_ref_pic_poc_lsb_sps[i] = sps->lt_ref_pic_poc_lsb_sps[i]; + } + + *vksps = (StdVideoH265SequenceParameterSet) { + .flags = (StdVideoH265SpsFlags) { + .sps_temporal_id_nesting_flag = sps->temporal_id_nesting_flag, + .separate_colour_plane_flag = sps->separate_colour_plane_flag, + .conformance_window_flag = sps->conformance_window_flag, + .sps_sub_layer_ordering_info_present_flag = sps->sublayer_ordering_info_flag, + .scaling_list_enabled_flag = sps->scaling_list_enable_flag, + .sps_scaling_list_data_present_flag = sps->scaling_list_enable_flag, + .amp_enabled_flag = sps->amp_enabled_flag, + .sample_adaptive_offset_enabled_flag = sps->sao_enabled, + .pcm_enabled_flag = sps->pcm_enabled_flag, + .pcm_loop_filter_disabled_flag = sps->pcm.loop_filter_disable_flag, + .long_term_ref_pics_present_flag = sps->long_term_ref_pics_present_flag, + .sps_temporal_mvp_enabled_flag = sps->sps_temporal_mvp_enabled_flag, + .strong_intra_smoothing_enabled_flag = sps->sps_strong_intra_smoothing_enable_flag, + .vui_parameters_present_flag = sps->vui_present, + .sps_extension_present_flag = sps->sps_extension_present_flag, + .sps_range_extension_flag = sps->sps_range_extension_flag, + .transform_skip_rotation_enabled_flag = sps->transform_skip_rotation_enabled_flag, + .transform_skip_context_enabled_flag = sps->transform_skip_context_enabled_flag, + .implicit_rdpcm_enabled_flag = sps->implicit_rdpcm_enabled_flag, + .explicit_rdpcm_enabled_flag = sps->explicit_rdpcm_enabled_flag, + .extended_precision_processing_flag = sps->extended_precision_processing_flag, + .intra_smoothing_disabled_flag = sps->intra_smoothing_disabled_flag, + .high_precision_offsets_enabled_flag = sps->high_precision_offsets_enabled_flag, + .persistent_rice_adaptation_enabled_flag = sps->persistent_rice_adaptation_enabled_flag, + .cabac_bypass_alignment_enabled_flag = sps->cabac_bypass_alignment_enabled_flag, + .sps_scc_extension_flag = sps->sps_scc_extension_flag, + .sps_curr_pic_ref_enabled_flag = sps->sps_curr_pic_ref_enabled_flag, + .palette_mode_enabled_flag = sps->palette_mode_enabled_flag, + .sps_palette_predictor_initializers_present_flag = sps->sps_palette_predictor_initializers_present_flag, + .intra_boundary_filtering_disabled_flag = sps->intra_boundary_filtering_disabled_flag, + }, + .chroma_format_idc = sps->chroma_format_idc, + .pic_width_in_luma_samples = sps->width, + .pic_height_in_luma_samples = sps->height, + .sps_video_parameter_set_id = sps->vps_id, + .sps_max_sub_layers_minus1 = sps->max_sub_layers - 1, + .sps_seq_parameter_set_id = sps_idx, + .bit_depth_luma_minus8 = sps->bit_depth - 8, + .bit_depth_chroma_minus8 = sps->bit_depth_chroma - 8, + .log2_max_pic_order_cnt_lsb_minus4 = sps->log2_max_poc_lsb - 4, + .log2_min_luma_coding_block_size_minus3 = sps->log2_min_cb_size - 3, + .log2_diff_max_min_luma_coding_block_size = sps->log2_diff_max_min_coding_block_size, + .log2_min_luma_transform_block_size_minus2 = sps->log2_min_tb_size - 2, + .log2_diff_max_min_luma_transform_block_size = sps->log2_diff_max_min_transform_block_size, + .max_transform_hierarchy_depth_inter = sps->max_transform_hierarchy_depth_inter, + .max_transform_hierarchy_depth_intra = sps->max_transform_hierarchy_depth_intra, + .num_short_term_ref_pic_sets = sps->nb_st_rps, + .num_long_term_ref_pics_sps = sps->num_long_term_ref_pics_sps, + .pcm_sample_bit_depth_luma_minus1 = sps->pcm.bit_depth - 1, + .pcm_sample_bit_depth_chroma_minus1 = sps->pcm.bit_depth_chroma - 1, + .log2_min_pcm_luma_coding_block_size_minus3 = sps->pcm.log2_min_pcm_cb_size - 3, + .log2_diff_max_min_pcm_luma_coding_block_size = sps->pcm.log2_max_pcm_cb_size - sps->pcm.log2_min_pcm_cb_size, + /* Reserved */ + /* Reserved */ + .palette_max_size = sps->palette_max_size, + .delta_palette_max_predictor_size = sps->delta_palette_max_predictor_size, + .motion_vector_resolution_control_idc = sps->motion_vector_resolution_control_idc, + .sps_num_palette_predictor_initializers_minus1 = sps->sps_num_palette_predictor_initializers - 1, + .conf_win_left_offset = sps->pic_conf_win.left_offset, + .conf_win_right_offset = sps->pic_conf_win.right_offset, + .conf_win_top_offset = sps->pic_conf_win.top_offset, + .conf_win_bottom_offset = sps->pic_conf_win.bottom_offset, + .pProfileTierLevel = ptl, + .pDecPicBufMgr = dpbm, + .pScalingLists = vksps_scaling, + .pShortTermRefPicSet = str, + .pLongTermRefPicsSps = ltr, + .pSequenceParameterSetVui = vksps_vui, + .pPredictorPaletteEntries = pal, + }; +} + +static void set_pps(const HEVCPPS *pps, const HEVCSPS *sps, + StdVideoH265ScalingLists *vkpps_scaling, + StdVideoH265PictureParameterSet *vkpps, + StdVideoH265PredictorPaletteEntries *pal) +{ + for (int i = 0; i < STD_VIDEO_H265_SCALING_LIST_4X4_NUM_LISTS; i++) + memcpy(vkpps_scaling->ScalingList4x4[i], pps->scaling_list.sl[0][i], + STD_VIDEO_H265_SCALING_LIST_4X4_NUM_ELEMENTS * sizeof(**vkpps_scaling->ScalingList4x4)); + + for (int i = 0; i < STD_VIDEO_H265_SCALING_LIST_8X8_NUM_LISTS; i++) + memcpy(vkpps_scaling->ScalingList8x8[i], pps->scaling_list.sl[1][i], + STD_VIDEO_H265_SCALING_LIST_8X8_NUM_ELEMENTS * sizeof(**vkpps_scaling->ScalingList8x8)); + + for (int i = 0; i < STD_VIDEO_H265_SCALING_LIST_16X16_NUM_LISTS; i++) + memcpy(vkpps_scaling->ScalingList16x16[i], pps->scaling_list.sl[2][i], + STD_VIDEO_H265_SCALING_LIST_4X4_NUM_ELEMENTS * sizeof(**vkpps_scaling->ScalingList16x16)); + + for (int i = 0; i < STD_VIDEO_H265_SCALING_LIST_32X32_NUM_LISTS; i++) + memcpy(vkpps_scaling->ScalingList32x32[i], pps->scaling_list.sl[3][i], + STD_VIDEO_H265_SCALING_LIST_32X32_NUM_ELEMENTS * sizeof(**vkpps_scaling->ScalingList32x32)); + + memcpy(vkpps_scaling->ScalingListDCCoef16x16, pps->scaling_list.sl_dc[0], + STD_VIDEO_H265_SCALING_LIST_4X4_NUM_ELEMENTS * sizeof(*vkpps_scaling->ScalingListDCCoef16x16)); + + memcpy(vkpps_scaling->ScalingListDCCoef32x32, pps->scaling_list.sl_dc[1], + STD_VIDEO_H265_SCALING_LIST_32X32_NUM_ELEMENTS * sizeof(*vkpps_scaling->ScalingListDCCoef32x32)); + + *vkpps = (StdVideoH265PictureParameterSet) { + .flags = (StdVideoH265PpsFlags) { + .dependent_slice_segments_enabled_flag = pps->dependent_slice_segments_enabled_flag, + .output_flag_present_flag = pps->output_flag_present_flag, + .sign_data_hiding_enabled_flag = pps->sign_data_hiding_flag, + .cabac_init_present_flag = pps->cabac_init_present_flag, + .constrained_intra_pred_flag = pps->constrained_intra_pred_flag, + .transform_skip_enabled_flag = pps->transform_skip_enabled_flag, + .cu_qp_delta_enabled_flag = pps->cu_qp_delta_enabled_flag, + .pps_slice_chroma_qp_offsets_present_flag = pps->pic_slice_level_chroma_qp_offsets_present_flag, + .weighted_pred_flag = pps->weighted_pred_flag, + .weighted_bipred_flag = pps->weighted_bipred_flag, + .transquant_bypass_enabled_flag = pps->transquant_bypass_enable_flag, + .tiles_enabled_flag = pps->tiles_enabled_flag, + .entropy_coding_sync_enabled_flag = pps->entropy_coding_sync_enabled_flag, + .uniform_spacing_flag = pps->uniform_spacing_flag, + .loop_filter_across_tiles_enabled_flag = pps->loop_filter_across_tiles_enabled_flag, + .pps_loop_filter_across_slices_enabled_flag = pps->seq_loop_filter_across_slices_enabled_flag, + .deblocking_filter_control_present_flag = pps->deblocking_filter_control_present_flag, + .deblocking_filter_override_enabled_flag = pps->deblocking_filter_override_enabled_flag, + .pps_deblocking_filter_disabled_flag = pps->disable_dbf, + .pps_scaling_list_data_present_flag = pps->scaling_list_data_present_flag, + .lists_modification_present_flag = pps->lists_modification_present_flag, + .slice_segment_header_extension_present_flag = pps->slice_header_extension_present_flag, + .pps_extension_present_flag = pps->pps_extension_present_flag, + .cross_component_prediction_enabled_flag = pps->cross_component_prediction_enabled_flag, + .chroma_qp_offset_list_enabled_flag = pps->chroma_qp_offset_list_enabled_flag, + .pps_curr_pic_ref_enabled_flag = pps->pps_curr_pic_ref_enabled_flag, + .residual_adaptive_colour_transform_enabled_flag = pps->residual_adaptive_colour_transform_enabled_flag, + .pps_slice_act_qp_offsets_present_flag = pps->pps_slice_act_qp_offsets_present_flag, + .pps_palette_predictor_initializers_present_flag = pps->pps_palette_predictor_initializers_present_flag, + .monochrome_palette_flag = pps->monochrome_palette_flag, + .pps_range_extension_flag = pps->pps_range_extensions_flag, + }, + .pps_pic_parameter_set_id = pps->pps_id, + .pps_seq_parameter_set_id = pps->sps_id, + .sps_video_parameter_set_id = sps->vps_id, + .num_extra_slice_header_bits = pps->num_extra_slice_header_bits, + .num_ref_idx_l0_default_active_minus1 = pps->num_ref_idx_l0_default_active - 1, + .num_ref_idx_l1_default_active_minus1 = pps->num_ref_idx_l1_default_active - 1, + .init_qp_minus26 = pps->pic_init_qp_minus26, + .diff_cu_qp_delta_depth = pps->diff_cu_qp_delta_depth, + .pps_cb_qp_offset = pps->cb_qp_offset, + .pps_cr_qp_offset = pps->cr_qp_offset, + .pps_beta_offset_div2 = pps->beta_offset >> 1, + .pps_tc_offset_div2 = pps->tc_offset >> 1, + .log2_parallel_merge_level_minus2 = pps->log2_parallel_merge_level - 2, + .log2_max_transform_skip_block_size_minus2 = pps->log2_max_transform_skip_block_size - 2, + .diff_cu_chroma_qp_offset_depth = pps->diff_cu_chroma_qp_offset_depth, + .chroma_qp_offset_list_len_minus1 = pps->chroma_qp_offset_list_len_minus1, + .log2_sao_offset_scale_luma = pps->log2_sao_offset_scale_luma, + .log2_sao_offset_scale_chroma = pps->log2_sao_offset_scale_chroma, + .pps_act_y_qp_offset_plus5 = pps->pps_act_y_qp_offset + 5, + .pps_act_cb_qp_offset_plus5 = pps->pps_act_cb_qp_offset + 5, + .pps_act_cr_qp_offset_plus3 = pps->pps_act_cr_qp_offset + 3, + .pps_num_palette_predictor_initializers = pps->pps_num_palette_predictor_initializers, + .luma_bit_depth_entry_minus8 = pps->luma_bit_depth_entry - 8, + .chroma_bit_depth_entry_minus8 = pps->chroma_bit_depth_entry - 8, + .num_tile_columns_minus1 = pps->num_tile_columns - 1, + .num_tile_rows_minus1 = pps->num_tile_rows - 1, + .pScalingLists = vkpps_scaling, + .pPredictorPaletteEntries = pal, + }; + + for (int i = 0; i < (pps->monochrome_palette_flag ? 1 : 3); i++) { + for (int j = 0; j < pps->pps_num_palette_predictor_initializers; j++) + pal->PredictorPaletteEntries[i][j] = pps->pps_palette_predictor_initializer[i][j]; + } + + for (int i = 0; i < pps->num_tile_columns - 1; i++) + vkpps->column_width_minus1[i] = pps->column_width[i] - 1; + + for (int i = 0; i < pps->num_tile_rows - 1; i++) + vkpps->row_height_minus1[i] = pps->row_height[i] - 1; + + for (int i = 0; i <= pps->chroma_qp_offset_list_len_minus1; i++) { + vkpps->cb_qp_offset_list[i] = pps->cb_qp_offset_list[i]; + vkpps->cr_qp_offset_list[i] = pps->cr_qp_offset_list[i]; + } +} + +static void set_vps(const HEVCVPS *vps, + StdVideoH265VideoParameterSet *vkvps, + StdVideoH265ProfileTierLevel *ptl, + StdVideoH265DecPicBufMgr *dpbm, + StdVideoH265HrdParameters *sls_hdr, + HEVCHeaderVPSSet sls[]) +{ + for (int i = 0; i < vps->vps_num_hrd_parameters; i++) { + const HEVCHdrParams *src = &vps->hdr[i]; + + sls_hdr[i] = (StdVideoH265HrdParameters) { + .flags = (StdVideoH265HrdFlags) { + .nal_hrd_parameters_present_flag = src->flags.nal_hrd_parameters_present_flag, + .vcl_hrd_parameters_present_flag = src->flags.vcl_hrd_parameters_present_flag, + .sub_pic_hrd_params_present_flag = src->flags.sub_pic_hrd_params_present_flag, + .sub_pic_cpb_params_in_pic_timing_sei_flag = src->flags.sub_pic_cpb_params_in_pic_timing_sei_flag, + .fixed_pic_rate_general_flag = src->flags.fixed_pic_rate_general_flag, + .fixed_pic_rate_within_cvs_flag = src->flags.fixed_pic_rate_within_cvs_flag, + .low_delay_hrd_flag = src->flags.low_delay_hrd_flag, + }, + .tick_divisor_minus2 = src->tick_divisor_minus2, + .du_cpb_removal_delay_increment_length_minus1 = src->du_cpb_removal_delay_increment_length_minus1, + .dpb_output_delay_du_length_minus1 = src->dpb_output_delay_du_length_minus1, + .bit_rate_scale = src->bit_rate_scale, + .cpb_size_scale = src->cpb_size_scale, + .cpb_size_du_scale = src->cpb_size_du_scale, + .initial_cpb_removal_delay_length_minus1 = src->initial_cpb_removal_delay_length_minus1, + .au_cpb_removal_delay_length_minus1 = src->au_cpb_removal_delay_length_minus1, + .dpb_output_delay_length_minus1 = src->dpb_output_delay_length_minus1, + /* Reserved - 3*16 bits */ + .pSubLayerHrdParametersNal = sls[i].nal_hdr, + .pSubLayerHrdParametersVcl = sls[i].vcl_hdr, + }; + + memcpy(sls_hdr[i].cpb_cnt_minus1, src->cpb_cnt_minus1, + STD_VIDEO_H265_SUBLAYERS_LIST_SIZE*sizeof(*sls_hdr[i].cpb_cnt_minus1)); + memcpy(sls_hdr[i].elemental_duration_in_tc_minus1, src->elemental_duration_in_tc_minus1, + STD_VIDEO_H265_SUBLAYERS_LIST_SIZE*sizeof(*sls_hdr[i].elemental_duration_in_tc_minus1)); + + memcpy(sls[i].nal_hdr, src->nal_params, HEVC_MAX_SUB_LAYERS*sizeof(*sls[i].nal_hdr)); + memcpy(sls[i].vcl_hdr, src->vcl_params, HEVC_MAX_SUB_LAYERS*sizeof(*sls[i].vcl_hdr)); + } + + *ptl = (StdVideoH265ProfileTierLevel) { + .flags = (StdVideoH265ProfileTierLevelFlags) { + .general_tier_flag = vps->ptl.general_ptl.tier_flag, + .general_progressive_source_flag = vps->ptl.general_ptl.progressive_source_flag, + .general_interlaced_source_flag = vps->ptl.general_ptl.interlaced_source_flag, + .general_non_packed_constraint_flag = vps->ptl.general_ptl.non_packed_constraint_flag, + .general_frame_only_constraint_flag = vps->ptl.general_ptl.frame_only_constraint_flag, + }, + .general_profile_idc = vps->ptl.general_ptl.profile_idc, + .general_level_idc = convert_to_vk_level_idc(vps->ptl.general_ptl.level_idc), + }; + + for (int i = 0; i < vps->vps_max_sub_layers; i++) { + dpbm->max_latency_increase_plus1[i] = vps->vps_max_latency_increase[i] + 1; + dpbm->max_dec_pic_buffering_minus1[i] = vps->vps_max_dec_pic_buffering[i] - 1; + dpbm->max_num_reorder_pics[i] = vps->vps_num_reorder_pics[i]; + } + + *vkvps = (StdVideoH265VideoParameterSet) { + .flags = (StdVideoH265VpsFlags) { + .vps_temporal_id_nesting_flag = vps->vps_temporal_id_nesting_flag, + .vps_sub_layer_ordering_info_present_flag = vps->vps_sub_layer_ordering_info_present_flag, + .vps_timing_info_present_flag = vps->vps_timing_info_present_flag, + .vps_poc_proportional_to_timing_flag = vps->vps_poc_proportional_to_timing_flag, + }, + .vps_video_parameter_set_id = vps->vps_id, + .vps_max_sub_layers_minus1 = vps->vps_max_sub_layers - 1, + /* Reserved */ + /* Reserved */ + .vps_num_units_in_tick = vps->vps_num_units_in_tick, + .vps_time_scale = vps->vps_time_scale, + .vps_num_ticks_poc_diff_one_minus1 = vps->vps_num_ticks_poc_diff_one - 1, + /* Reserved */ + .pDecPicBufMgr = dpbm, + .pHrdParameters = sls_hdr, + .pProfileTierLevel = ptl, + }; +} + +static int vk_hevc_create_params(AVCodecContext *avctx, AVBufferRef **buf) +{ + int err; + VkResult ret; + const HEVCContext *h = avctx->priv_data; + FFVulkanDecodeContext *dec = avctx->internal->hwaccel_priv_data; + FFVulkanDecodeShared *ctx = (FFVulkanDecodeShared *)dec->shared_ref->data; + FFVulkanFunctions *vk = &ctx->s.vkfn; + + VkVideoDecodeH265SessionParametersAddInfoKHR h265_params_info = { + .sType = VK_STRUCTURE_TYPE_VIDEO_DECODE_H265_SESSION_PARAMETERS_ADD_INFO_KHR, + .stdSPSCount = 0, + .stdPPSCount = 0, + .stdVPSCount = 0, + }; + VkVideoDecodeH265SessionParametersCreateInfoKHR h265_params = { + .sType = VK_STRUCTURE_TYPE_VIDEO_DECODE_H265_SESSION_PARAMETERS_CREATE_INFO_KHR, + .pParametersAddInfo = &h265_params_info, + }; + VkVideoSessionParametersCreateInfoKHR session_params_create = { + .sType = VK_STRUCTURE_TYPE_VIDEO_SESSION_PARAMETERS_CREATE_INFO_KHR, + .pNext = &h265_params, + .videoSession = ctx->common.session, + .videoSessionParametersTemplate = NULL, + }; + + int nb_vps = 0; + AVBufferRef *data_set; + HEVCHeaderSet *hdr; + + AVBufferRef *tmp; + VkVideoSessionParametersKHR *par = av_malloc(sizeof(*par)); + if (!par) + return AVERROR(ENOMEM); + + for (int i = 0; h->ps.vps_list[i]; i++) + nb_vps++; + + err = get_data_set_buf(dec, &data_set, nb_vps, h->ps.vps_list); + if (err < 0) + return err; + + hdr = (HEVCHeaderSet *)data_set->data; + + h265_params_info.pStdSPSs = hdr->sps; + h265_params_info.pStdPPSs = hdr->pps; + h265_params_info.pStdVPSs = hdr->vps; + + /* SPS list */ + for (int i = 0; h->ps.sps_list[i]; i++) { + const HEVCSPS *sps_l = (const HEVCSPS *)h->ps.sps_list[i]->data; + set_sps(sps_l, i, &hdr->hsps[i].scaling, &hdr->hsps[i].vui_header, + &hdr->hsps[i].vui, &hdr->sps[i], hdr->hsps[i].nal_hdr, + hdr->hsps[i].vcl_hdr, &hdr->hsps[i].ptl, &hdr->hsps[i].dpbm, + &hdr->hsps[i].pal, hdr->hsps[i].str, &hdr->hsps[i].ltr); + h265_params_info.stdSPSCount++; + } + + /* PPS list */ + for (int i = 0; h->ps.pps_list[i]; i++) { + const HEVCPPS *pps_l = (const HEVCPPS *)h->ps.pps_list[i]->data; + const HEVCSPS *sps_l = (const HEVCSPS *)h->ps.sps_list[pps_l->sps_id]->data; + set_pps(pps_l, sps_l, &hdr->hpps[i].scaling, &hdr->pps[i], &hdr->hpps[i].pal); + h265_params_info.stdPPSCount++; + } + + /* VPS list */ + for (int i = 0; i < nb_vps; i++) { + const HEVCVPS *vps_l = (const HEVCVPS *)h->ps.vps_list[i]->data; + set_vps(vps_l, &hdr->vps[i], &hdr->hvps[i].ptl, &hdr->hvps[i].dpbm, + hdr->hvps[i].hdr, hdr->hvps[i].sls); + h265_params_info.stdVPSCount++; + } + + h265_params.maxStdSPSCount = h265_params_info.stdSPSCount; + h265_params.maxStdPPSCount = h265_params_info.stdPPSCount; + h265_params.maxStdVPSCount = h265_params_info.stdVPSCount; + + /* Create session parameters */ + ret = vk->CreateVideoSessionParametersKHR(ctx->s.hwctx->act_dev, &session_params_create, + ctx->s.hwctx->alloc, par); + av_buffer_unref(&data_set); + if (ret != VK_SUCCESS) { + av_log(avctx, AV_LOG_ERROR, "Unable to create Vulkan video session parameters: %s!\n", + ff_vk_ret2str(ret)); + return AVERROR_EXTERNAL; + } + + tmp = av_buffer_create((uint8_t *)par, sizeof(*par), ff_vk_decode_free_params, + ctx, 0); + if (!tmp) { + ff_vk_decode_free_params(ctx, (uint8_t *)par); + return AVERROR(ENOMEM); + } + + av_log(avctx, AV_LOG_DEBUG, "Created frame parameters: %i SPS %i PPS %i VPS\n", + h265_params_info.stdSPSCount, h265_params_info.stdPPSCount, + h265_params_info.stdVPSCount); + + *buf = tmp; + + return 0; +} + +static int vk_hevc_start_frame(AVCodecContext *avctx, + av_unused const uint8_t *buffer, + av_unused uint32_t size) +{ + int err; + HEVCContext *h = avctx->priv_data; + HEVCFrame *pic = h->ref; + FFVulkanDecodeContext *dec = avctx->internal->hwaccel_priv_data; + HEVCVulkanDecodePicture *hp = pic->hwaccel_picture_private; + FFVulkanDecodePicture *vp = &hp->vp; + const HEVCSPS *sps = h->ps.sps; + const HEVCPPS *pps = h->ps.pps; + int nb_refs = 0; + + if (!dec->session_params || dec->params_changed) { + av_buffer_unref(&dec->session_params); + err = vk_hevc_create_params(avctx, &dec->session_params); + if (err < 0) + return err; + dec->params_changed = 0; + } + + hp->h265pic = (StdVideoDecodeH265PictureInfo) { + .flags = (StdVideoDecodeH265PictureInfoFlags) { + .IrapPicFlag = IS_IRAP(h), + .IdrPicFlag = IS_IDR(h), + .IsReference = h->nal_unit_type < 16 ? h->nal_unit_type & 1 : 1, + .short_term_ref_pic_set_sps_flag = h->sh.short_term_ref_pic_set_sps_flag, + }, + .sps_video_parameter_set_id = sps->vps_id, + .pps_seq_parameter_set_id = pps->sps_id, + .pps_pic_parameter_set_id = pps->pps_id, + .NumDeltaPocsOfRefRpsIdx = h->sh.short_term_rps ? h->sh.short_term_rps->rps_idx_num_delta_pocs : 0, + .PicOrderCntVal = h->poc, + .NumBitsForSTRefPicSetInSlice = !h->sh.short_term_ref_pic_set_sps_flag ? + h->sh.bits_used_for_short_term_rps : 0, + }; + + /* Fill in references */ + for (int i = 0; i < FF_ARRAY_ELEMS(h->DPB); i++) { + const HEVCFrame *ref = &h->DPB[i]; + int idx = nb_refs; + + if (!(ref->flags & (HEVC_FRAME_FLAG_SHORT_REF | HEVC_FRAME_FLAG_LONG_REF))) + continue; + + if (ref == pic) { + err = vk_hevc_fill_pict(avctx, NULL, &vp->ref_slot, &vp->ref, + &hp->vkh265_ref, &hp->h265_ref, pic, 1, i); + if (err < 0) + return err; + + continue; + } + + err = vk_hevc_fill_pict(avctx, &hp->ref_src[idx], &vp->ref_slots[idx], + &vp->refs[idx], &hp->vkh265_refs[idx], + &hp->h265_refs[idx], (HEVCFrame *)ref, 0, i); + if (err < 0) + return err; + + nb_refs++; + } + + memset(hp->h265pic.RefPicSetStCurrBefore, 0xff, 8); + for (int i = 0; i < h->rps[ST_CURR_BEF].nb_refs; i++) { + HEVCFrame *frame = h->rps[ST_CURR_BEF].ref[i]; + for (int j = 0; j < FF_ARRAY_ELEMS(h->DPB); j++) { + const HEVCFrame *ref = &h->DPB[j]; + if (ref == frame) { + hp->h265pic.RefPicSetStCurrBefore[i] = j; + break; + } + } + } + memset(hp->h265pic.RefPicSetStCurrAfter, 0xff, 8); + for (int i = 0; i < h->rps[ST_CURR_AFT].nb_refs; i++) { + HEVCFrame *frame = h->rps[ST_CURR_AFT].ref[i]; + for (int j = 0; j < FF_ARRAY_ELEMS(h->DPB); j++) { + const HEVCFrame *ref = &h->DPB[j]; + if (ref == frame) { + hp->h265pic.RefPicSetStCurrAfter[i] = j; + break; + } + } + } + memset(hp->h265pic.RefPicSetLtCurr, 0xff, 8); + for (int i = 0; i < h->rps[LT_CURR].nb_refs; i++) { + HEVCFrame *frame = h->rps[LT_CURR].ref[i]; + for (int j = 0; j < FF_ARRAY_ELEMS(h->DPB); j++) { + const HEVCFrame *ref = &h->DPB[j]; + if (ref == frame) { + hp->h265pic.RefPicSetLtCurr[i] = j; + break; + } + } + } + + hp->h265_pic_info = (VkVideoDecodeH265PictureInfoKHR) { + .sType = VK_STRUCTURE_TYPE_VIDEO_DECODE_H265_PICTURE_INFO_KHR, + .pStdPictureInfo = &hp->h265pic, + .sliceSegmentCount = 0, + .pSliceSegmentOffsets = vp->slice_off, + }; + + vp->decode_info = (VkVideoDecodeInfoKHR) { + .sType = VK_STRUCTURE_TYPE_VIDEO_DECODE_INFO_KHR, + .pNext = &hp->h265_pic_info, + .flags = 0x0, + .pSetupReferenceSlot = &vp->ref_slot, + .referenceSlotCount = nb_refs, + .pReferenceSlots = vp->ref_slots, + .dstPictureResource = (VkVideoPictureResourceInfoKHR) { + .sType = VK_STRUCTURE_TYPE_VIDEO_PICTURE_RESOURCE_INFO_KHR, + .codedOffset = (VkOffset2D){ 0, 0 }, + .codedExtent = (VkExtent2D){ pic->frame->width, pic->frame->height }, + .baseArrayLayer = 0, + .imageViewBinding = vp->img_view_out, + }, + }; + + return 0; +} + +static int vk_hevc_decode_slice(AVCodecContext *avctx, + const uint8_t *data, + uint32_t size) +{ + const HEVCContext *h = avctx->priv_data; + HEVCVulkanDecodePicture *hp = h->ref->hwaccel_picture_private; + FFVulkanDecodePicture *vp = &hp->vp; + + int err = ff_vk_decode_add_slice(avctx, vp, data, size, 1, + &hp->h265_pic_info.sliceSegmentCount, + &hp->h265_pic_info.pSliceSegmentOffsets); + if (err < 0) + return err; + + return 0; +} + +static int vk_hevc_end_frame(AVCodecContext *avctx) +{ + const HEVCContext *h = avctx->priv_data; + HEVCFrame *pic = h->ref; + HEVCVulkanDecodePicture *hp = pic->hwaccel_picture_private; + FFVulkanDecodePicture *vp = &hp->vp; + FFVulkanDecodePicture *rvp[HEVC_MAX_REFS] = { 0 }; + AVFrame *rav[HEVC_MAX_REFS] = { 0 }; + + for (int i = 0; i < vp->decode_info.referenceSlotCount; i++) { + HEVCVulkanDecodePicture *rfhp = hp->ref_src[i]->hwaccel_picture_private; + rav[i] = hp->ref_src[i]->frame; + rvp[i] = &rfhp->vp; + } + + av_log(avctx, AV_LOG_VERBOSE, "Decoding frame, %lu bytes, %i slices\n", + vp->slices_size, hp->h265_pic_info.sliceSegmentCount); + + return ff_vk_decode_frame(avctx, pic->frame, vp, rav, rvp); +} + +static void vk_hevc_free_frame_priv(void *_hwctx, uint8_t *data) +{ + AVHWDeviceContext *hwctx = _hwctx; + HEVCVulkanDecodePicture *hp = (HEVCVulkanDecodePicture *)data; + + /* Free frame resources */ + ff_vk_decode_free_frame(hwctx, &hp->vp); + + /* Free frame context */ + av_free(hp); +} + +const AVHWAccel ff_hevc_vulkan_hwaccel = { + .name = "hevc_vulkan", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_HEVC, + .pix_fmt = AV_PIX_FMT_VULKAN, + .start_frame = &vk_hevc_start_frame, + .decode_slice = &vk_hevc_decode_slice, + .end_frame = &vk_hevc_end_frame, + .free_frame_priv = &vk_hevc_free_frame_priv, + .frame_priv_data_size = sizeof(HEVCVulkanDecodePicture), + .init = &ff_vk_decode_init, + .update_thread_context = &ff_vk_update_thread_context, + .decode_params = &ff_vk_params_changed, + .flush = &ff_vk_decode_flush, + .uninit = &ff_vk_decode_uninit, + .frame_params = &ff_vk_frame_params, + .priv_data_size = sizeof(FFVulkanDecodeContext), + .caps_internal = HWACCEL_CAP_ASYNC_SAFE | HWACCEL_CAP_THREAD_SAFE, +}; From e49b8b48cd4362392d28c7e0dcf04744aaf1ace7 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Mon, 27 Feb 2023 11:57:54 +1000 Subject: [PATCH 1295/2172] av1: set skip mode frames properly There are circumstances where the flag isn't set but the skip mode frames are. So don't use the inferred bit which has other inputs when deciding to pass the skip mode frames to the device. This fixes some decoding bugs on intel av1 --- libavcodec/av1dec.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/libavcodec/av1dec.c b/libavcodec/av1dec.c index 7e423427b2f..47fa919e628 100644 --- a/libavcodec/av1dec.c +++ b/libavcodec/av1dec.c @@ -270,7 +270,9 @@ static void skip_mode_params(AV1DecContext *s) int second_forward_idx, second_forward_hint; int ref_hint, dist, i; - if (!header->skip_mode_present) + if (header->frame_type == AV1_FRAME_KEY || + header->frame_type == AV1_FRAME_INTRA_ONLY || + !header->reference_select || !seq->enable_order_hint) return; forward_idx = -1; From 6ec58ff820529052bca87f5b05292197d7c51cf3 Mon Sep 17 00:00:00 2001 From: Lynne Date: Thu, 23 Feb 2023 02:46:13 +0100 Subject: [PATCH 1296/2172] cbs_av1: expose tile col/row starts in SBs --- libavcodec/cbs_av1.h | 2 ++ libavcodec/cbs_av1_syntax_template.c | 10 ++++++++++ 2 files changed, 12 insertions(+) diff --git a/libavcodec/cbs_av1.h b/libavcodec/cbs_av1.h index 36848d4410c..64dfdce9c4e 100644 --- a/libavcodec/cbs_av1.h +++ b/libavcodec/cbs_av1.h @@ -215,6 +215,8 @@ typedef struct AV1RawFrameHeader { uint8_t uniform_tile_spacing_flag; uint8_t tile_cols_log2; uint8_t tile_rows_log2; + uint8_t tile_start_col_sb[AV1_MAX_TILE_COLS]; + uint8_t tile_start_row_sb[AV1_MAX_TILE_COLS]; uint8_t width_in_sbs_minus_1[AV1_MAX_TILE_COLS]; uint8_t height_in_sbs_minus_1[AV1_MAX_TILE_ROWS]; uint16_t context_update_tile_id; diff --git a/libavcodec/cbs_av1_syntax_template.c b/libavcodec/cbs_av1_syntax_template.c index 8f4640d1af8..a747e17784f 100644 --- a/libavcodec/cbs_av1_syntax_template.c +++ b/libavcodec/cbs_av1_syntax_template.c @@ -626,6 +626,10 @@ static int FUNC(tile_info)(CodedBitstreamContext *ctx, RWContext *rw, tile_width_sb = (sb_cols + (1 << current->tile_cols_log2) - 1) >> current->tile_cols_log2; + + for (int off = 0, i = 0; off < sb_cols; off += tile_width_sb) + current->tile_start_col_sb[i++] = off; + current->tile_cols = (sb_cols + tile_width_sb - 1) / tile_width_sb; min_log2_tile_rows = FFMAX(min_log2_tiles - current->tile_cols_log2, 0); @@ -634,6 +638,10 @@ static int FUNC(tile_info)(CodedBitstreamContext *ctx, RWContext *rw, tile_height_sb = (sb_rows + (1 << current->tile_rows_log2) - 1) >> current->tile_rows_log2; + + for (int off = 0, i = 0; off < sb_rows; off += tile_height_sb) + current->tile_start_row_sb[i++] = off; + current->tile_rows = (sb_rows + tile_height_sb - 1) / tile_height_sb; for (i = 0; i < current->tile_cols - 1; i++) @@ -652,6 +660,7 @@ static int FUNC(tile_info)(CodedBitstreamContext *ctx, RWContext *rw, start_sb = 0; for (i = 0; start_sb < sb_cols && i < AV1_MAX_TILE_COLS; i++) { + current->tile_start_col_sb[i] = start_sb; max_width = FFMIN(sb_cols - start_sb, max_tile_width_sb); ns(max_width, width_in_sbs_minus_1[i], 1, i); size_sb = current->width_in_sbs_minus_1[i] + 1; @@ -669,6 +678,7 @@ static int FUNC(tile_info)(CodedBitstreamContext *ctx, RWContext *rw, start_sb = 0; for (i = 0; start_sb < sb_rows && i < AV1_MAX_TILE_ROWS; i++) { + current->tile_start_row_sb[i] = start_sb; max_height = FFMIN(sb_rows - start_sb, max_tile_height_sb); ns(max_height, height_in_sbs_minus_1[i], 1, i); size_sb = current->height_in_sbs_minus_1[i] + 1; From 5dc047716ab62945e30e490e88b4f2faad3ddb3d Mon Sep 17 00:00:00 2001 From: Lynne Date: Sun, 28 May 2023 05:02:31 +0200 Subject: [PATCH 1297/2172] fate-source: exclude Apache-2 licensed files --- tests/fate/source-check.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/fate/source-check.sh b/tests/fate/source-check.sh index 5f3fd8960e8..658823fc0b4 100755 --- a/tests/fate/source-check.sh +++ b/tests/fate/source-check.sh @@ -14,6 +14,7 @@ git grep -L -E "This file is part of FFmpeg|This file is part of libswresample|" "Redistribution and use in source and binary forms, with or without modification|"\ "This library is free software; you can redistribute it and/or|"\ "This program is free software; you can redistribute it and/or modify|"\ +"Licensed under the Apache License|"\ "This file is placed in the public domain" | grep -E '\.c$|\.h$|\.S$|\.asm$' echo Headers without standard inclusion guards: From 77478f6793fad61a29ce92e56ee6116dd99ceca4 Mon Sep 17 00:00:00 2001 From: Lynne Date: Fri, 17 Feb 2023 04:09:16 +0100 Subject: [PATCH 1298/2172] av1dec: add Vulkan hwaccel --- configure | 2 + libavcodec/Makefile | 3 +- libavcodec/av1dec.c | 47 +- libavcodec/hwaccels.h | 1 + libavcodec/vulkan_av1.c | 597 ++++++++++++++++++ libavcodec/vulkan_decode.c | 34 +- libavcodec/vulkan_decode.h | 2 + libavcodec/vulkan_video.c | 6 + libavcodec/vulkan_video.h | 2 + libavcodec/vulkan_video_codec_av1std.h | 403 ++++++++++++ libavcodec/vulkan_video_codec_av1std_decode.h | 36 ++ libavutil/hwcontext_vulkan.c | 1 + libavutil/vulkan_functions.h | 1 + libavutil/vulkan_loader.h | 1 + tests/ref/fate/source | 2 + 15 files changed, 1135 insertions(+), 3 deletions(-) create mode 100644 libavcodec/vulkan_av1.c create mode 100644 libavcodec/vulkan_video_codec_av1std.h create mode 100644 libavcodec/vulkan_video_codec_av1std_decode.h diff --git a/configure b/configure index 61916fc2bc9..ed122b53ad6 100755 --- a/configure +++ b/configure @@ -3020,6 +3020,8 @@ av1_vaapi_hwaccel_deps="vaapi VADecPictureParameterBufferAV1_bit_depth_idx" av1_vaapi_hwaccel_select="av1_decoder" av1_vdpau_hwaccel_deps="vdpau VdpPictureInfoAV1" av1_vdpau_hwaccel_select="av1_decoder" +av1_vulkan_hwaccel_deps="vulkan" +av1_vulkan_hwaccel_select="av1_decoder" h263_vaapi_hwaccel_deps="vaapi" h263_vaapi_hwaccel_select="h263_decoder" h263_videotoolbox_hwaccel_deps="videotoolbox" diff --git a/libavcodec/Makefile b/libavcodec/Makefile index d4218449031..9aacc1d4774 100644 --- a/libavcodec/Makefile +++ b/libavcodec/Makefile @@ -989,6 +989,7 @@ OBJS-$(CONFIG_AV1_DXVA2_HWACCEL) += dxva2_av1.o OBJS-$(CONFIG_AV1_NVDEC_HWACCEL) += nvdec_av1.o OBJS-$(CONFIG_AV1_VAAPI_HWACCEL) += vaapi_av1.o OBJS-$(CONFIG_AV1_VDPAU_HWACCEL) += vdpau_av1.o +OBJS-$(CONFIG_AV1_VULKAN_HWACCEL) += vulkan_av1.o OBJS-$(CONFIG_H263_VAAPI_HWACCEL) += vaapi_mpeg4.o OBJS-$(CONFIG_H263_VIDEOTOOLBOX_HWACCEL) += videotoolbox.o OBJS-$(CONFIG_H264_D3D11VA_HWACCEL) += dxva2_h264.o @@ -1293,7 +1294,7 @@ SKIPHEADERS-$(CONFIG_XVMC) += xvmc.h SKIPHEADERS-$(CONFIG_VAAPI) += vaapi_decode.h vaapi_hevc.h vaapi_encode.h SKIPHEADERS-$(CONFIG_VDPAU) += vdpau.h vdpau_internal.h SKIPHEADERS-$(CONFIG_VIDEOTOOLBOX) += videotoolbox.h vt_internal.h -SKIPHEADERS-$(CONFIG_VULKAN) += vulkan.h vulkan_video.h vulkan_decode.h +SKIPHEADERS-$(CONFIG_VULKAN) += vulkan.h vulkan_video.h vulkan_decode.h vulkan_video_codec_av1std.h vulkan_video_codec_av1std_decode.h SKIPHEADERS-$(CONFIG_V4L2_M2M) += v4l2_buffers.h v4l2_context.h v4l2_m2m.h SKIPHEADERS-$(CONFIG_ZLIB) += zlib_wrapper.h diff --git a/libavcodec/av1dec.c b/libavcodec/av1dec.c index 47fa919e628..5cc5d87c648 100644 --- a/libavcodec/av1dec.c +++ b/libavcodec/av1dec.c @@ -450,7 +450,8 @@ static int get_pixel_format(AVCodecContext *avctx) CONFIG_AV1_D3D11VA_HWACCEL * 2 + \ CONFIG_AV1_NVDEC_HWACCEL + \ CONFIG_AV1_VAAPI_HWACCEL + \ - CONFIG_AV1_VDPAU_HWACCEL) + CONFIG_AV1_VDPAU_HWACCEL + \ + CONFIG_AV1_VULKAN_HWACCEL) enum AVPixelFormat pix_fmts[HWACCEL_MAX + 2], *fmtp = pix_fmts; if (seq->seq_profile == 2 && seq->color_config.high_bitdepth) @@ -530,6 +531,9 @@ static int get_pixel_format(AVCodecContext *avctx) #endif #if CONFIG_AV1_VDPAU_HWACCEL *fmtp++ = AV_PIX_FMT_VDPAU; +#endif +#if CONFIG_AV1_VULKAN_HWACCEL + *fmtp++ = AV_PIX_FMT_VULKAN; #endif break; case AV_PIX_FMT_YUV420P10: @@ -548,6 +552,44 @@ static int get_pixel_format(AVCodecContext *avctx) #endif #if CONFIG_AV1_VDPAU_HWACCEL *fmtp++ = AV_PIX_FMT_VDPAU; +#endif +#if CONFIG_AV1_VULKAN_HWACCEL + *fmtp++ = AV_PIX_FMT_VULKAN; +#endif + break; + case AV_PIX_FMT_YUV420P12: +#if CONFIG_AV1_VULKAN_HWACCEL + *fmtp++ = AV_PIX_FMT_VULKAN; +#endif + break; + case AV_PIX_FMT_YUV422P: +#if CONFIG_AV1_VULKAN_HWACCEL + *fmtp++ = AV_PIX_FMT_VULKAN; +#endif + break; + case AV_PIX_FMT_YUV422P10: +#if CONFIG_AV1_VULKAN_HWACCEL + *fmtp++ = AV_PIX_FMT_VULKAN; +#endif + break; + case AV_PIX_FMT_YUV422P12: +#if CONFIG_AV1_VULKAN_HWACCEL + *fmtp++ = AV_PIX_FMT_VULKAN; +#endif + break; + case AV_PIX_FMT_YUV444P: +#if CONFIG_AV1_VULKAN_HWACCEL + *fmtp++ = AV_PIX_FMT_VULKAN; +#endif + break; + case AV_PIX_FMT_YUV444P10: +#if CONFIG_AV1_VULKAN_HWACCEL + *fmtp++ = AV_PIX_FMT_VULKAN; +#endif + break; + case AV_PIX_FMT_YUV444P12: +#if CONFIG_AV1_VULKAN_HWACCEL + *fmtp++ = AV_PIX_FMT_VULKAN; #endif break; case AV_PIX_FMT_GRAY8: @@ -1508,6 +1550,9 @@ const FFCodec ff_av1_decoder = { #if CONFIG_AV1_VDPAU_HWACCEL HWACCEL_VDPAU(av1), #endif +#if CONFIG_AV1_VULKAN_HWACCEL + HWACCEL_VULKAN(av1), +#endif NULL }, diff --git a/libavcodec/hwaccels.h b/libavcodec/hwaccels.h index a7c74d07cbd..48dfc17f72b 100644 --- a/libavcodec/hwaccels.h +++ b/libavcodec/hwaccels.h @@ -27,6 +27,7 @@ extern const AVHWAccel ff_av1_dxva2_hwaccel; extern const AVHWAccel ff_av1_nvdec_hwaccel; extern const AVHWAccel ff_av1_vaapi_hwaccel; extern const AVHWAccel ff_av1_vdpau_hwaccel; +extern const AVHWAccel ff_av1_vulkan_hwaccel; extern const AVHWAccel ff_h263_vaapi_hwaccel; extern const AVHWAccel ff_h263_videotoolbox_hwaccel; extern const AVHWAccel ff_h264_d3d11va_hwaccel; diff --git a/libavcodec/vulkan_av1.c b/libavcodec/vulkan_av1.c new file mode 100644 index 00000000000..5dc3e8919cc --- /dev/null +++ b/libavcodec/vulkan_av1.c @@ -0,0 +1,597 @@ +/* + * 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 "av1dec.h" + +#include "vulkan_decode.h" + +/* Maximum number of tiles specified by any defined level */ +#define MAX_TILES 256 + +const VkExtensionProperties ff_vk_dec_av1_ext = { + .extensionName = VK_STD_VULKAN_VIDEO_CODEC_AV1_DECODE_EXTENSION_NAME, + .specVersion = VK_STD_VULKAN_VIDEO_CODEC_AV1_DECODE_SPEC_VERSION, +}; + +typedef struct AV1VulkanDecodePicture { + FFVulkanDecodePicture vp; + + /* Workaround for a spec issue. + *Can be removed once no longer needed, and threading can be enabled. */ + FFVulkanDecodeContext *dec; + + StdVideoAV1MESATile tiles[MAX_TILES]; + StdVideoAV1MESATileList tile_list; + const uint32_t *tile_offsets; + + /* Current picture */ + VkVideoDecodeAV1DpbSlotInfoMESA vkav1_ref; + StdVideoAV1MESAFrameHeader av1_frame_header; + VkVideoDecodeAV1PictureInfoMESA av1_pic_info; + + /* Picture refs */ + const AV1Frame *ref_src [AV1_NUM_REF_FRAMES]; + VkVideoDecodeAV1DpbSlotInfoMESA vkav1_refs[AV1_NUM_REF_FRAMES]; + + uint8_t frame_id_set; + uint8_t frame_id; +} AV1VulkanDecodePicture; + +static int vk_av1_fill_pict(AVCodecContext *avctx, const AV1Frame **ref_src, + VkVideoReferenceSlotInfoKHR *ref_slot, /* Main structure */ + VkVideoPictureResourceInfoKHR *ref, /* Goes in ^ */ + VkVideoDecodeAV1DpbSlotInfoMESA *vkav1_ref, /* Goes in ^ */ + const AV1Frame *pic, int is_current, int has_grain, + int dpb_slot_index) +{ + FFVulkanDecodeContext *dec = avctx->internal->hwaccel_priv_data; + AV1VulkanDecodePicture *hp = pic->hwaccel_picture_private; + FFVulkanDecodePicture *vkpic = &hp->vp; + + int err = ff_vk_decode_prepare_frame(dec, pic->f, vkpic, is_current, + has_grain || dec->dedicated_dpb); + if (err < 0) + return err; + + *vkav1_ref = (VkVideoDecodeAV1DpbSlotInfoMESA) { + .sType = VK_STRUCTURE_TYPE_VIDEO_DECODE_AV1_DPB_SLOT_INFO_MESA, + .frameIdx = hp->frame_id, + }; + + for (unsigned i = 0; i < 7; i++) { + const int idx = pic->raw_frame_header->ref_frame_idx[i]; + vkav1_ref->ref_order_hint[i] = pic->raw_frame_header->ref_order_hint[idx]; + } + + vkav1_ref->disable_frame_end_update_cdf = pic->raw_frame_header->disable_frame_end_update_cdf; + + *ref = (VkVideoPictureResourceInfoKHR) { + .sType = VK_STRUCTURE_TYPE_VIDEO_PICTURE_RESOURCE_INFO_KHR, + .codedOffset = (VkOffset2D){ 0, 0 }, + .codedExtent = (VkExtent2D){ pic->f->width, pic->f->height }, + .baseArrayLayer = ((has_grain || dec->dedicated_dpb) && dec->layered_dpb) ? + dpb_slot_index : 0, + .imageViewBinding = vkpic->img_view_ref, + }; + + *ref_slot = (VkVideoReferenceSlotInfoKHR) { + .sType = VK_STRUCTURE_TYPE_VIDEO_REFERENCE_SLOT_INFO_KHR, + .pNext = vkav1_ref, + .slotIndex = dpb_slot_index, + .pPictureResource = ref, + }; + + if (ref_src) + *ref_src = pic; + + return 0; +} + +static int vk_av1_create_params(AVCodecContext *avctx, AVBufferRef **buf) +{ + VkResult ret; + + const AV1DecContext *s = avctx->priv_data; + FFVulkanDecodeContext *dec = avctx->internal->hwaccel_priv_data; + FFVulkanDecodeShared *ctx = (FFVulkanDecodeShared *)dec->shared_ref->data; + FFVulkanFunctions *vk = &ctx->s.vkfn; + + const AV1RawSequenceHeader *seq = s->raw_seq; + + StdVideoAV1MESASequenceHeader av1_sequence_header; + VkVideoDecodeAV1SessionParametersAddInfoMESA av1_params_info; + VkVideoDecodeAV1SessionParametersCreateInfoMESA av1_params; + VkVideoSessionParametersCreateInfoKHR session_params_create; + + AVBufferRef *tmp; + VkVideoSessionParametersKHR *par = av_malloc(sizeof(*par)); + if (!par) + return AVERROR(ENOMEM); + + av1_sequence_header = (StdVideoAV1MESASequenceHeader) { + .flags = (StdVideoAV1MESASequenceHeaderFlags) { + .still_picture = seq->still_picture, + .reduced_still_picture_header = seq->reduced_still_picture_header, + .use_128x128_superblock = seq->use_128x128_superblock, + .enable_filter_intra = seq->enable_filter_intra, + .enable_intra_edge_filter = seq->enable_intra_edge_filter, + .enable_interintra_compound = seq->enable_interintra_compound, + .enable_masked_compound = seq->enable_masked_compound, + .enable_warped_motion = seq->enable_warped_motion, + .enable_dual_filter = seq->enable_dual_filter, + .enable_order_hint = seq->enable_order_hint, + .enable_jnt_comp = seq->enable_jnt_comp, + .enable_ref_frame_mvs = seq->enable_ref_frame_mvs, + .frame_id_numbers_present_flag = seq->frame_id_numbers_present_flag, + .enable_superres = seq->enable_superres, + .enable_cdef = seq->enable_cdef, + .enable_restoration = seq->enable_restoration, + .film_grain_params_present = seq->film_grain_params_present, + .timing_info_present_flag = seq->timing_info_present_flag, + .initial_display_delay_present_flag = seq->initial_display_delay_present_flag, + }, + .seq_profile = seq->seq_profile, + .frame_width_bits_minus_1 = seq->frame_width_bits_minus_1, + .frame_height_bits_minus_1 = seq->frame_height_bits_minus_1, + .max_frame_width_minus_1 = seq->max_frame_width_minus_1, + .max_frame_height_minus_1 = seq->max_frame_height_minus_1, + .delta_frame_id_length_minus_2 = seq->delta_frame_id_length_minus_2, + .additional_frame_id_length_minus_1 = seq->additional_frame_id_length_minus_1, + .order_hint_bits_minus_1 = seq->order_hint_bits_minus_1, + .timing_info = (StdVideoAV1MESATimingInfo) { + .flags = (StdVideoAV1MESATimingInfoFlags) { + .equal_picture_interval = seq->timing_info.equal_picture_interval, + }, + .num_units_in_display_tick = seq->timing_info.num_units_in_display_tick, + .time_scale = seq->timing_info.time_scale, + .num_ticks_per_picture_minus_1 = seq->timing_info.num_ticks_per_picture_minus_1, + }, + .color_config = (StdVideoAV1MESAColorConfig) { + .flags = (StdVideoAV1MESAColorConfigFlags) { + .mono_chrome = seq->color_config.mono_chrome, + .color_range = seq->color_config.color_range, + .separate_uv_delta_q = seq->color_config.separate_uv_delta_q, + }, + .bit_depth = seq->color_config.twelve_bit ? 12 : + seq->color_config.high_bitdepth ? 10 : 8, + .subsampling_x = seq->color_config.subsampling_x, + .subsampling_y = seq->color_config.subsampling_y, + }, + }; + + av1_params_info = (VkVideoDecodeAV1SessionParametersAddInfoMESA) { + .sType = VK_STRUCTURE_TYPE_VIDEO_DECODE_AV1_SESSION_PARAMETERS_ADD_INFO_MESA, + .sequence_header = &av1_sequence_header, + }; + av1_params = (VkVideoDecodeAV1SessionParametersCreateInfoMESA) { + .sType = VK_STRUCTURE_TYPE_VIDEO_DECODE_AV1_SESSION_PARAMETERS_CREATE_INFO_MESA, + .pParametersAddInfo = &av1_params_info, + }; + session_params_create = (VkVideoSessionParametersCreateInfoKHR) { + .sType = VK_STRUCTURE_TYPE_VIDEO_SESSION_PARAMETERS_CREATE_INFO_KHR, + .pNext = &av1_params, + .videoSession = ctx->common.session, + .videoSessionParametersTemplate = NULL, + }; + + /* Create session parameters */ + ret = vk->CreateVideoSessionParametersKHR(ctx->s.hwctx->act_dev, &session_params_create, + ctx->s.hwctx->alloc, par); + if (ret != VK_SUCCESS) { + av_log(avctx, AV_LOG_ERROR, "Unable to create Vulkan video session parameters: %s!\n", + ff_vk_ret2str(ret)); + return AVERROR_EXTERNAL; + } + + tmp = av_buffer_create((uint8_t *)par, sizeof(*par), ff_vk_decode_free_params, + ctx, 0); + if (!tmp) { + ff_vk_decode_free_params(ctx, (uint8_t *)par); + return AVERROR(ENOMEM); + } + + av_log(avctx, AV_LOG_DEBUG, "Created frame parameters\n"); + + *buf = tmp; + + return 0; +} + +static int vk_av1_start_frame(AVCodecContext *avctx, + av_unused const uint8_t *buffer, + av_unused uint32_t size) +{ + int err; + int ref_count = 0; + AV1DecContext *s = avctx->priv_data; + const AV1Frame *pic = &s->cur_frame; + FFVulkanDecodeContext *dec = avctx->internal->hwaccel_priv_data; + AV1VulkanDecodePicture *ap = pic->hwaccel_picture_private; + FFVulkanDecodePicture *vp = &ap->vp; + + const AV1RawFrameHeader *frame_header = s->raw_frame_header; + const AV1RawFilmGrainParams *film_grain = &s->cur_frame.film_grain; + const int apply_grain = !(avctx->export_side_data & AV_CODEC_EXPORT_DATA_FILM_GRAIN) && + film_grain->apply_grain; + + if (!dec->session_params || dec->params_changed) { + av_buffer_unref(&dec->session_params); + err = vk_av1_create_params(avctx, &dec->session_params); + if (err < 0) + return err; + dec->params_changed = 0; + } + + if (!ap->frame_id_set) { + unsigned slot_idx = 0; + for (unsigned i = 0; i < 32; i++) { + if (!(dec->frame_id_alloc_mask & (1 << i))) { + slot_idx = i; + break; + } + } + ap->frame_id = slot_idx; + ap->frame_id_set = 1; + dec->frame_id_alloc_mask |= (1 << slot_idx); + } + + /* Fill in references */ + for (int i = 0; i < AV1_NUM_REF_FRAMES; i++) { + const AV1Frame *ref_frame = &s->ref[i]; + if (s->ref[i].f->pict_type == AV_PICTURE_TYPE_NONE) + continue; + + err = vk_av1_fill_pict(avctx, &ap->ref_src[i], &vp->ref_slots[i], + &vp->refs[i], &ap->vkav1_refs[i], + ref_frame, 0, 0, i); + if (err < 0) + return err; + + ref_count++; + } + + err = vk_av1_fill_pict(avctx, NULL, &vp->ref_slot, &vp->ref, + &ap->vkav1_ref, + pic, 1, apply_grain, 8); + if (err < 0) + return err; + + ap->tile_list.nb_tiles = 0; + ap->tile_list.tile_list = ap->tiles; + + ap->av1_pic_info = (VkVideoDecodeAV1PictureInfoMESA) { + .sType = VK_STRUCTURE_TYPE_VIDEO_DECODE_AV1_PICTURE_INFO_MESA, + .frame_header = &ap->av1_frame_header, + .tile_list = &ap->tile_list, + }; + + vp->decode_info = (VkVideoDecodeInfoKHR) { + .sType = VK_STRUCTURE_TYPE_VIDEO_DECODE_INFO_KHR, + .pNext = &ap->av1_pic_info, + .flags = 0x0, + .pSetupReferenceSlot = &vp->ref_slot, + .referenceSlotCount = ref_count, + .pReferenceSlots = vp->ref_slots, + .dstPictureResource = (VkVideoPictureResourceInfoKHR) { + .sType = VK_STRUCTURE_TYPE_VIDEO_PICTURE_RESOURCE_INFO_KHR, + .codedOffset = (VkOffset2D){ 0, 0 }, + .codedExtent = (VkExtent2D){ pic->f->width, pic->f->height }, + .baseArrayLayer = 0, + .imageViewBinding = vp->img_view_out, + }, + }; + + /* Setup frame header */ + ap->av1_frame_header = (StdVideoAV1MESAFrameHeader) { + .flags = (StdVideoAV1MESAFrameHeaderFlags) { + .error_resilient_mode = frame_header->error_resilient_mode, + .disable_cdf_update = frame_header->disable_cdf_update, + .use_superres = frame_header->use_superres, + .render_and_frame_size_different = frame_header->render_and_frame_size_different, + .allow_screen_content_tools = frame_header->allow_screen_content_tools, + .is_filter_switchable = frame_header->is_filter_switchable, + .force_integer_mv = frame_header->force_integer_mv, + .frame_size_override_flag = frame_header->frame_size_override_flag, + .buffer_removal_time_present_flag = frame_header->buffer_removal_time_present_flag, + .allow_intrabc = frame_header->allow_intrabc, + .frame_refs_short_signaling = frame_header->frame_refs_short_signaling, + .allow_high_precision_mv = frame_header->allow_high_precision_mv, + .is_motion_mode_switchable = frame_header->is_motion_mode_switchable, + .use_ref_frame_mvs = frame_header->use_ref_frame_mvs, + .disable_frame_end_update_cdf = frame_header->disable_frame_end_update_cdf, + .allow_warped_motion = frame_header->allow_warped_motion, + .reduced_tx_set = frame_header->reduced_tx_set, + .reference_select = frame_header->reference_select, + .skip_mode_present = frame_header->skip_mode_present, + .delta_q_present = frame_header->delta_q_present, + }, + .frame_to_show_map_idx = frame_header->frame_to_show_map_idx, + .frame_presentation_time = frame_header->frame_presentation_time, + .display_frame_id = frame_header->display_frame_id, + .frame_type = frame_header->frame_type, + .current_frame_id = frame_header->current_frame_id, + .order_hint = frame_header->order_hint, + .primary_ref_frame = frame_header->primary_ref_frame, + .frame_width_minus_1 = frame_header->frame_width_minus_1, + .frame_height_minus_1 = frame_header->frame_height_minus_1, + .coded_denom = frame_header->coded_denom, + .render_width_minus_1 = frame_header->render_width_minus_1, + .render_height_minus_1 = frame_header->render_height_minus_1, + .refresh_frame_flags = frame_header->refresh_frame_flags, + .interpolation_filter = frame_header->interpolation_filter, + .tx_mode = frame_header->tx_mode, + .tiling = (StdVideoAV1MESATileInfo) { + .flags = (StdVideoAV1MESATileInfoFlags) { + .uniform_tile_spacing_flag = frame_header->uniform_tile_spacing_flag, + }, + .tile_cols = frame_header->tile_cols, + .tile_rows = frame_header->tile_rows, + .context_update_tile_id = frame_header->context_update_tile_id, + .tile_size_bytes_minus1 = frame_header->tile_size_bytes_minus1, + }, + .quantization = (StdVideoAV1MESAQuantization) { + .flags.using_qmatrix = frame_header->using_qmatrix, + .base_q_idx = frame_header->base_q_idx, + .delta_q_y_dc = frame_header->delta_q_y_dc, + .diff_uv_delta = frame_header->diff_uv_delta, + .delta_q_u_dc = frame_header->delta_q_u_dc, + .delta_q_u_ac = frame_header->delta_q_u_ac, + .delta_q_v_dc = frame_header->delta_q_v_dc, + .delta_q_v_ac = frame_header->delta_q_v_ac, + .qm_y = frame_header->qm_y, + .qm_u = frame_header->qm_u, + .qm_v = frame_header->qm_v, + }, + .delta_q = (StdVideoAV1MESADeltaQ) { + .flags = (StdVideoAV1MESADeltaQFlags) { + .delta_lf_present = frame_header->delta_lf_present, + .delta_lf_multi = frame_header->delta_lf_multi, + }, + .delta_q_res = frame_header->delta_q_res, + .delta_lf_res = frame_header->delta_lf_res, + }, + .loop_filter = (StdVideoAV1MESALoopFilter) { + .flags = (StdVideoAV1MESALoopFilterFlags) { + .delta_enabled = frame_header->loop_filter_delta_enabled, + .delta_update = frame_header->loop_filter_delta_update, + }, + .level = { + frame_header->loop_filter_level[0], frame_header->loop_filter_level[1], + frame_header->loop_filter_level[2], frame_header->loop_filter_level[3], + }, + .sharpness = frame_header->loop_filter_sharpness, + .mode_deltas = { + frame_header->loop_filter_mode_deltas[0], frame_header->loop_filter_mode_deltas[1], + }, + }, + .cdef = (StdVideoAV1MESACDEF) { + .damping_minus_3 = frame_header->cdef_damping_minus_3, + .bits = frame_header->cdef_bits, + }, + .lr = (StdVideoAV1MESALoopRestoration) { + .lr_unit_shift = frame_header->lr_unit_shift, + .lr_uv_shift = frame_header->lr_uv_shift, + .lr_type = { frame_header->lr_type[0], frame_header->lr_type[1], frame_header->lr_type[2] }, + }, + .segmentation = (StdVideoAV1MESASegmentation) { + .flags = (StdVideoAV1MESASegmentationFlags) { + .enabled = frame_header->segmentation_enabled, + .update_map = frame_header->segmentation_update_map, + .temporal_update = frame_header->segmentation_temporal_update, + .update_data = frame_header->segmentation_update_data, + }, + }, + .film_grain = (StdVideoAV1MESAFilmGrainParameters) { + .flags = (StdVideoAV1MESAFilmGrainFlags) { + .apply_grain = apply_grain, + .chroma_scaling_from_luma = film_grain->chroma_scaling_from_luma, + .overlap_flag = film_grain->overlap_flag, + .clip_to_restricted_range = film_grain->clip_to_restricted_range, + }, + .grain_scaling_minus_8 = film_grain->grain_scaling_minus_8, + .ar_coeff_lag = film_grain->ar_coeff_lag, + .ar_coeff_shift_minus_6 = film_grain->ar_coeff_shift_minus_6, + .grain_scale_shift = film_grain->grain_scale_shift, + .grain_seed = film_grain->grain_seed, + .num_y_points = film_grain->num_y_points, + .num_cb_points = film_grain->num_cb_points, + .num_cr_points = film_grain->num_cr_points, + .cb_mult = film_grain->cb_mult, + .cb_luma_mult = film_grain->cb_luma_mult, + .cb_offset = film_grain->cb_offset, + .cr_mult = film_grain->cr_mult, + .cr_luma_mult = film_grain->cr_luma_mult, + .cr_offset = film_grain->cr_offset, + }, + }; + + for (int i = 0; i < 64; i++) { + ap->av1_frame_header.tiling.width_in_sbs_minus_1[i] = frame_header->width_in_sbs_minus_1[i]; + ap->av1_frame_header.tiling.height_in_sbs_minus_1[i] = frame_header->height_in_sbs_minus_1[i]; + ap->av1_frame_header.tiling.tile_start_col_sb[i] = frame_header->tile_start_col_sb[i]; + ap->av1_frame_header.tiling.tile_start_row_sb[i] = frame_header->tile_start_row_sb[i]; + } + + for (int i = 0; i < 8; i++) { + ap->av1_frame_header.segmentation.feature_enabled_bits[i] = 0; + for (int j = 0; j < 8; j++) { + ap->av1_frame_header.segmentation.feature_enabled_bits[i] |= (frame_header->feature_enabled[i][j] << j); + ap->av1_frame_header.segmentation.feature_data[i][j] = frame_header->feature_value[i][j]; + } + + ap->av1_frame_header.loop_filter.ref_deltas[i] = frame_header->loop_filter_ref_deltas[i]; + + ap->av1_frame_header.cdef.y_pri_strength[i] = frame_header->cdef_y_pri_strength[i]; + ap->av1_frame_header.cdef.y_sec_strength[i] = frame_header->cdef_y_sec_strength[i]; + ap->av1_frame_header.cdef.uv_pri_strength[i] = frame_header->cdef_uv_pri_strength[i]; + ap->av1_frame_header.cdef.uv_sec_strength[i] = frame_header->cdef_uv_sec_strength[i]; + + ap->av1_frame_header.ref_order_hint[i] = frame_header->ref_order_hint[i]; + ap->av1_frame_header.global_motion[i] = (StdVideoAV1MESAGlobalMotion) { + .flags = (StdVideoAV1MESAGlobalMotionFlags) { + .gm_invalid = s->cur_frame.gm_invalid[i], + }, + .gm_type = s->cur_frame.gm_type[i], + .gm_params = { + frame_header->gm_params[i][0], frame_header->gm_params[i][1], + frame_header->gm_params[i][2], frame_header->gm_params[i][3], + frame_header->gm_params[i][4], frame_header->gm_params[i][5], + }, + }; + } + + for (int i = 0; i < 7; i++) { + ap->av1_frame_header.ref_frame_idx[i] = frame_header->ref_frame_idx[i]; + ap->av1_frame_header.delta_frame_id_minus1[i] = frame_header->delta_frame_id_minus1[i]; + } + + ap->av1_pic_info.skip_mode_frame_idx[0] = s->cur_frame.skip_mode_frame_idx[0]; + ap->av1_pic_info.skip_mode_frame_idx[1] = s->cur_frame.skip_mode_frame_idx[1]; + + if (apply_grain) { + for (int i = 0; i < 14; i++) { + ap->av1_frame_header.film_grain.point_y_value[i] = film_grain->point_y_value[i]; + ap->av1_frame_header.film_grain.point_y_scaling[i] = film_grain->point_y_scaling[i]; + } + + for (int i = 0; i < 10; i++) { + ap->av1_frame_header.film_grain.point_cb_value[i] = film_grain->point_cb_value[i]; + ap->av1_frame_header.film_grain.point_cb_scaling[i] = film_grain->point_cb_scaling[i]; + ap->av1_frame_header.film_grain.point_cr_value[i] = film_grain->point_cr_value[i]; + ap->av1_frame_header.film_grain.point_cr_scaling[i] = film_grain->point_cr_scaling[i]; + } + + for (int i = 0; i < 24; i++) { + ap->av1_frame_header.film_grain.ar_coeffs_y_plus_128[i] = film_grain->ar_coeffs_y_plus_128[i]; + ap->av1_frame_header.film_grain.ar_coeffs_cb_plus_128[i] = film_grain->ar_coeffs_cb_plus_128[i]; + ap->av1_frame_header.film_grain.ar_coeffs_cr_plus_128[i] = film_grain->ar_coeffs_cr_plus_128[i]; + } + + ap->av1_frame_header.film_grain.ar_coeffs_cb_plus_128[24] = film_grain->ar_coeffs_cb_plus_128[24]; + ap->av1_frame_header.film_grain.ar_coeffs_cr_plus_128[24] = film_grain->ar_coeffs_cr_plus_128[24]; + } + + av_log(avctx, AV_LOG_DEBUG, "Created frame parameters"); + + /* Workaround for a spec issue. */ + ap->dec = dec; + + return 0; +} + +static int vk_av1_decode_slice(AVCodecContext *avctx, + const uint8_t *data, + uint32_t size) +{ + int err; + const AV1DecContext *s = avctx->priv_data; + AV1VulkanDecodePicture *ap = s->cur_frame.hwaccel_picture_private; + FFVulkanDecodePicture *vp = &ap->vp; + + for (int i = s->tg_start; i <= s->tg_end; i++) { + ap->tiles[ap->tile_list.nb_tiles] = (StdVideoAV1MESATile) { + .size = s->tile_group_info[i].tile_size, + .offset = s->tile_group_info[i].tile_offset, + .row = s->tile_group_info[i].tile_row, + .column = s->tile_group_info[i].tile_column, + .tg_start = s->tg_start, + .tg_end = s->tg_end, + }; + + err = ff_vk_decode_add_slice(avctx, vp, data, size, 0, + &ap->tile_list.nb_tiles, + &ap->tile_offsets); + if (err < 0) + return err; + +// ap->tiles[ap->tile_list.nb_tiles - 1].offset = ap->tile_offsets[ap->tile_list.nb_tiles - 1]; + } + + return 0; +} + +static int vk_av1_end_frame(AVCodecContext *avctx) +{ + const AV1DecContext *s = avctx->priv_data; + const AV1Frame *pic = &s->cur_frame; + AV1VulkanDecodePicture *ap = pic->hwaccel_picture_private; + FFVulkanDecodePicture *vp = &ap->vp; + FFVulkanDecodePicture *rvp[AV1_NUM_REF_FRAMES] = { 0 }; + AVFrame *rav[AV1_NUM_REF_FRAMES] = { 0 }; + + for (int i = 0; i < vp->decode_info.referenceSlotCount; i++) { + const AV1Frame *rp = ap->ref_src[i]; + AV1VulkanDecodePicture *rhp = rp->hwaccel_picture_private; + + rvp[i] = &rhp->vp; + rav[i] = ap->ref_src[i]->f; + } + + av_log(avctx, AV_LOG_VERBOSE, "Decoding frame, %lu bytes, %i tiles\n", + vp->slices_size, ap->tile_list.nb_tiles); + + return ff_vk_decode_frame(avctx, pic->f, vp, rav, rvp); +} + +static void vk_av1_free_frame_priv(void *_hwctx, uint8_t *data) +{ + AVHWDeviceContext *hwctx = _hwctx; + AV1VulkanDecodePicture *ap = (AV1VulkanDecodePicture *)data; + + /* Workaround for a spec issue. */ + if (ap->frame_id_set) + ap->dec->frame_id_alloc_mask &= ~(1 << ap->frame_id); + + /* Free frame resources, this also destroys the session parameters. */ + ff_vk_decode_free_frame(hwctx, &ap->vp); + + /* Free frame context */ + av_free(ap); +} + +const AVHWAccel ff_av1_vulkan_hwaccel = { + .name = "av1_vulkan", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_AV1, + .pix_fmt = AV_PIX_FMT_VULKAN, + .start_frame = &vk_av1_start_frame, + .decode_slice = &vk_av1_decode_slice, + .end_frame = &vk_av1_end_frame, + .free_frame_priv = &vk_av1_free_frame_priv, + .frame_priv_data_size = sizeof(AV1VulkanDecodePicture), + .init = &ff_vk_decode_init, + .update_thread_context = &ff_vk_update_thread_context, + .decode_params = &ff_vk_params_changed, + .flush = &ff_vk_decode_flush, + .uninit = &ff_vk_decode_uninit, + .frame_params = &ff_vk_frame_params, + .priv_data_size = sizeof(FFVulkanDecodeContext), + + /* NOTE: Threading is intentionally disabled here. Due to the design of Vulkan, + * where frames are opaque to users, and mostly opaque for driver developers, + * there's an issue with current hardware accelerator implementations of AV1, + * where they require an internal index. With regular hwaccel APIs, this index + * is given to users as an opaque handle directly. With Vulkan, due to increased + * flexibility, this index cannot be present anywhere. + * The current implementation tracks the index for the driver and submits it + * as necessary information. Due to needing to modify the decoding context, + * which is not thread-safe, on frame free, threading is disabled. + * In the future, once this is fixed in the spec, the workarounds may be removed + * and threading enabled. */ + .caps_internal = HWACCEL_CAP_ASYNC_SAFE, +}; diff --git a/libavcodec/vulkan_decode.c b/libavcodec/vulkan_decode.c index a2900d95622..1d1fb9ad974 100644 --- a/libavcodec/vulkan_decode.c +++ b/libavcodec/vulkan_decode.c @@ -26,6 +26,9 @@ extern const VkExtensionProperties ff_vk_dec_h264_ext; #if CONFIG_HEVC_VULKAN_HWACCEL extern const VkExtensionProperties ff_vk_dec_hevc_ext; #endif +#if CONFIG_AV1_VULKAN_HWACCEL +extern const VkExtensionProperties ff_vk_dec_av1_ext; +#endif static const VkExtensionProperties *dec_ext[] = { #if CONFIG_H264_VULKAN_HWACCEL @@ -34,6 +37,9 @@ static const VkExtensionProperties *dec_ext[] = { #if CONFIG_HEVC_VULKAN_HWACCEL [AV_CODEC_ID_HEVC] = &ff_vk_dec_hevc_ext, #endif +#if CONFIG_AV1_VULKAN_HWACCEL + [AV_CODEC_ID_AV1] = &ff_vk_dec_av1_ext, +#endif }; int ff_vk_update_thread_context(AVCodecContext *dst, const AVCodecContext *src) @@ -54,6 +60,8 @@ int ff_vk_update_thread_context(AVCodecContext *dst, const AVCodecContext *src) dst_ctx->dedicated_dpb = src_ctx->dedicated_dpb; dst_ctx->layered_dpb = src_ctx->layered_dpb; + dst_ctx->external_fg = src_ctx->external_fg; + dst_ctx->frame_id_alloc_mask = src_ctx->frame_id_alloc_mask; return 0; } @@ -630,6 +638,7 @@ static VkResult vulkan_setup_profile(AVCodecContext *avctx, const struct FFVkCodecMap *vk_codec, VkVideoDecodeH264CapabilitiesKHR *h264_caps, VkVideoDecodeH265CapabilitiesKHR *h265_caps, + VkVideoDecodeAV1CapabilitiesMESA *av1_caps, int cur_profile) { VkVideoCapabilitiesKHR *caps = &prof->caps; @@ -640,6 +649,7 @@ static VkResult vulkan_setup_profile(AVCodecContext *avctx, VkVideoDecodeH264ProfileInfoKHR *h264_profile = &prof->h264_profile; VkVideoDecodeH264ProfileInfoKHR *h265_profile = &prof->h265_profile; + VkVideoDecodeAV1ProfileInfoMESA *av1_profile = &prof->av1_profile; const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(avctx->sw_pix_fmt); if (!desc) @@ -659,6 +669,11 @@ static VkResult vulkan_setup_profile(AVCodecContext *avctx, usage->pNext = h265_profile; h265_profile->sType = VK_STRUCTURE_TYPE_VIDEO_DECODE_H265_PROFILE_INFO_KHR; h265_profile->stdProfileIdc = cur_profile; + } else if (avctx->codec_id == AV_CODEC_ID_AV1) { + dec_caps->pNext = &av1_caps; + usage->pNext = av1_profile; + av1_profile->sType = VK_STRUCTURE_TYPE_VIDEO_DECODE_AV1_PROFILE_INFO_MESA; + av1_profile->stdProfileIdc = cur_profile; } usage->sType = VK_STRUCTURE_TYPE_VIDEO_DECODE_USAGE_INFO_KHR; @@ -714,6 +729,9 @@ static int vulkan_decode_get_profile(AVCodecContext *avctx, AVBufferRef *frames_ VkVideoDecodeH265CapabilitiesKHR h265_caps = { .sType = VK_STRUCTURE_TYPE_VIDEO_DECODE_H265_CAPABILITIES_KHR, }; + VkVideoDecodeAV1CapabilitiesMESA av1_caps = { + .sType = VK_STRUCTURE_TYPE_VIDEO_DECODE_AV1_CAPABILITIES_MESA, + }; VkPhysicalDeviceVideoFormatInfoKHR fmt_info = { .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VIDEO_FORMAT_INFO_KHR, @@ -735,11 +753,13 @@ static int vulkan_decode_get_profile(AVCodecContext *avctx, AVBufferRef *frames_ cur_profile = avctx->profile; base_profile = avctx->codec_id == AV_CODEC_ID_H264 ? FF_PROFILE_H264_CONSTRAINED_BASELINE : avctx->codec_id == AV_CODEC_ID_H265 ? FF_PROFILE_HEVC_MAIN : + avctx->codec_id == AV_CODEC_ID_AV1 ? STD_VIDEO_AV1_MESA_PROFILE_MAIN : 0; ret = vulkan_setup_profile(avctx, prof, hwctx, vk, vk_codec, &h264_caps, &h265_caps, + &av1_caps, cur_profile); if (ret == VK_ERROR_VIDEO_PROFILE_OPERATION_NOT_SUPPORTED_KHR && avctx->flags & AV_HWACCEL_FLAG_ALLOW_PROFILE_MISMATCH && @@ -753,6 +773,7 @@ static int vulkan_decode_get_profile(AVCodecContext *avctx, AVBufferRef *frames_ ret = vulkan_setup_profile(avctx, prof, hwctx, vk, vk_codec, &h264_caps, &h265_caps, + &av1_caps, cur_profile); } @@ -776,6 +797,7 @@ static int vulkan_decode_get_profile(AVCodecContext *avctx, AVBufferRef *frames_ max_level = avctx->codec_id == AV_CODEC_ID_H264 ? h264_caps.maxLevelIdc : avctx->codec_id == AV_CODEC_ID_H265 ? h265_caps.maxLevelIdc : + avctx->codec_id == AV_CODEC_ID_AV1 ? av1_caps.maxLevelIdc : 0; av_log(avctx, AV_LOG_VERBOSE, "Decoder capabilities for %s profile \"%s\":\n", @@ -843,11 +865,17 @@ static int vulkan_decode_get_profile(AVCodecContext *avctx, AVBufferRef *frames_ "VK_VIDEO_DECODE_CAPABILITY_DPB_AND_OUTPUT_COINCIDE_BIT_KHR set " "but VK_VIDEO_CAPABILITY_SEPARATE_REFERENCE_IMAGES_BIT_KHR is unset!\n"); return AVERROR_EXTERNAL; + } else if (!(dec_caps->flags & VK_VIDEO_DECODE_CAPABILITY_DPB_AND_OUTPUT_DISTINCT_BIT_KHR) && + avctx->codec_id == AV_CODEC_ID_AV1) { + av_log(avctx, AV_LOG_ERROR, "Cannot initialize Vulkan decoding session, buggy driver: " + "codec is AV1, but VK_VIDEO_DECODE_CAPABILITY_DPB_AND_OUTPUT_DISTINCT_BIT_KHR isn't set!\n"); + return AVERROR_EXTERNAL; } /* TODO: make dedicated_dpb tunable */ dec->dedicated_dpb = !(dec_caps->flags & VK_VIDEO_DECODE_CAPABILITY_DPB_AND_OUTPUT_COINCIDE_BIT_KHR); dec->layered_dpb = !(caps->flags & VK_VIDEO_CAPABILITY_SEPARATE_REFERENCE_IMAGES_BIT_KHR); + dec->external_fg = av1_caps.flags & VK_VIDEO_DECODE_AV1_CAPABILITY_EXTERNAL_FILM_GRAIN_MESA; if (dec->dedicated_dpb) { fmt_info.imageUsage = VK_IMAGE_USAGE_VIDEO_DECODE_DPB_BIT_KHR; @@ -1013,10 +1041,14 @@ int ff_vk_decode_init(AVCodecContext *avctx) VkVideoDecodeH265SessionParametersCreateInfoKHR h265_params = { .sType = VK_STRUCTURE_TYPE_VIDEO_DECODE_H265_SESSION_PARAMETERS_CREATE_INFO_KHR, }; + VkVideoDecodeAV1SessionParametersCreateInfoMESA av1_params = { + .sType = VK_STRUCTURE_TYPE_VIDEO_DECODE_AV1_SESSION_PARAMETERS_CREATE_INFO_MESA, + }; VkVideoSessionParametersCreateInfoKHR session_params_create = { .sType = VK_STRUCTURE_TYPE_VIDEO_SESSION_PARAMETERS_CREATE_INFO_KHR, .pNext = avctx->codec_id == AV_CODEC_ID_H264 ? (void *)&h264_params : avctx->codec_id == AV_CODEC_ID_HEVC ? (void *)&h265_params : + avctx->codec_id == AV_CODEC_ID_AV1 ? (void *)&av1_params : NULL, }; VkVideoSessionCreateInfoKHR session_create = { @@ -1100,7 +1132,7 @@ int ff_vk_decode_init(AVCodecContext *avctx) } /* If doing an out-of-place decoding, create a DPB pool */ - if (dec->dedicated_dpb) { + if (dec->dedicated_dpb || avctx->codec_id == AV_CODEC_ID_AV1) { AVHWFramesContext *dpb_frames; AVVulkanFramesContext *dpb_hwfc; diff --git a/libavcodec/vulkan_decode.h b/libavcodec/vulkan_decode.h index bfde86e45f9..681d2476cdb 100644 --- a/libavcodec/vulkan_decode.h +++ b/libavcodec/vulkan_decode.h @@ -59,6 +59,8 @@ typedef struct FFVulkanDecodeContext { int dedicated_dpb; /* Oddity #1 - separate DPB images */ int layered_dpb; /* Madness #1 - layered DPB images */ + int external_fg; /* Oddity #2 - hardware can't apply film grain */ + uint32_t frame_id_alloc_mask; /* For AV1 only */ /* Thread-local state below */ AVBufferPool *tmp_pool; /* Pool for temporary data, if needed (HEVC) */ diff --git a/libavcodec/vulkan_video.c b/libavcodec/vulkan_video.c index 5fb867df874..24ef73ddf90 100644 --- a/libavcodec/vulkan_video.c +++ b/libavcodec/vulkan_video.c @@ -33,6 +33,12 @@ const FFVkCodecMap ff_vk_codec_map[AV_CODEC_ID_FIRST_AUDIO] = { FF_VK_EXT_VIDEO_DECODE_H265, VK_VIDEO_CODEC_OPERATION_DECODE_H265_BIT_KHR }, + [AV_CODEC_ID_AV1] = { + 0, + 0, + FF_VK_EXT_VIDEO_DECODE_AV1, + 0x01000000 /* TODO fix this */ + }, }; #define ASPECT_2PLANE (VK_IMAGE_ASPECT_PLANE_0_BIT | VK_IMAGE_ASPECT_PLANE_1_BIT) diff --git a/libavcodec/vulkan_video.h b/libavcodec/vulkan_video.h index b4adde4ec1f..183ce89bf0a 100644 --- a/libavcodec/vulkan_video.h +++ b/libavcodec/vulkan_video.h @@ -23,6 +23,8 @@ #include "vulkan.h" #include +#include "vulkan_video_codec_av1std.h" +#include "vulkan_video_codec_av1std_decode.h" #define CODEC_VER_MAJ(ver) (ver >> 22) #define CODEC_VER_MIN(ver) ((ver >> 12) & ((1 << 10) - 1)) diff --git a/libavcodec/vulkan_video_codec_av1std.h b/libavcodec/vulkan_video_codec_av1std.h new file mode 100644 index 00000000000..c46236c4572 --- /dev/null +++ b/libavcodec/vulkan_video_codec_av1std.h @@ -0,0 +1,403 @@ +/* Copyright 2023 Lynne + * Copyright 2023 Dave Airlie + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef VULKAN_VIDEO_CODEC_AV1STD_H_ +#define VULKAN_VIDEO_CODEC_AV1STD_H_ 1 + +/* +** This header is NOT YET generated from the Khronos Vulkan XML API Registry. +** +*/ + +#ifdef __cplusplus +extern "C" { +#endif +#define vulkan_video_codec_av1std 1 + +#define VK_MAKE_VIDEO_STD_VERSION(major, minor, patch) \ + ((((uint32_t)(major)) << 22) | (((uint32_t)(minor)) << 12) | ((uint32_t)(patch))) +#define VK_STD_VULKAN_VIDEO_CODEC_AV1_DECODE_API_VERSION_0_1_0 VK_MAKE_VIDEO_STD_VERSION(0, 1, 0) +#define VK_STD_VULKAN_VIDEO_CODEC_AV1_DECODE_SPEC_VERSION VK_STD_VULKAN_VIDEO_CODEC_AV1_DECODE_API_VERSION_0_1_0 +#define VK_STD_VULKAN_VIDEO_CODEC_AV1_DECODE_EXTENSION_NAME "VK_STD_vulkan_video_codec_av1_decode" + +typedef enum StdVideoAV1MESAProfile { + STD_VIDEO_AV1_MESA_PROFILE_MAIN = 0, + STD_VIDEO_AV1_MESA_PROFILE_HIGH = 1, + STD_VIDEO_AV1_MESA_PROFILE_PROFESSIONAL = 2, +} StdVideoAV1MESAProfile; + +typedef enum StdVideoAV1MESALevel { + STD_VIDEO_AV1_MESA_LEVEL_2_0 = 0, + STD_VIDEO_AV1_MESA_LEVEL_2_1 = 1, + STD_VIDEO_AV1_MESA_LEVEL_2_2 = 2, + STD_VIDEO_AV1_MESA_LEVEL_2_3 = 3, + STD_VIDEO_AV1_MESA_LEVEL_3_0 = 4, + STD_VIDEO_AV1_MESA_LEVEL_3_1 = 5, + STD_VIDEO_AV1_MESA_LEVEL_3_2 = 6, + STD_VIDEO_AV1_MESA_LEVEL_3_3 = 7, + STD_VIDEO_AV1_MESA_LEVEL_4_0 = 8, + STD_VIDEO_AV1_MESA_LEVEL_4_1 = 9, + STD_VIDEO_AV1_MESA_LEVEL_4_2 = 10, + STD_VIDEO_AV1_MESA_LEVEL_4_3 = 11, + STD_VIDEO_AV1_MESA_LEVEL_5_0 = 12, + STD_VIDEO_AV1_MESA_LEVEL_5_1 = 13, + STD_VIDEO_AV1_MESA_LEVEL_5_2 = 14, + STD_VIDEO_AV1_MESA_LEVEL_5_3 = 15, + STD_VIDEO_AV1_MESA_LEVEL_6_0 = 16, + STD_VIDEO_AV1_MESA_LEVEL_6_1 = 17, + STD_VIDEO_AV1_MESA_LEVEL_6_2 = 18, + STD_VIDEO_AV1_MESA_LEVEL_6_3 = 19, + STD_VIDEO_AV1_MESA_LEVEL_7_0 = 20, + STD_VIDEO_AV1_MESA_LEVEL_7_1 = 21, + STD_VIDEO_AV1_MESA_LEVEL_7_2 = 22, + STD_VIDEO_AV1_MESA_LEVEL_7_3 = 23, + STD_VIDEO_AV1_MESA_LEVEL_MAX = 31, +} StdVideoAV1MESALevel; + +typedef struct StdVideoAV1MESAFilmGrainFlags { + uint8_t apply_grain; + uint8_t chroma_scaling_from_luma; + uint8_t overlap_flag; + uint8_t clip_to_restricted_range; +} StdVideoAV1MESAFilmGrainFlags; + +typedef struct StdVideoAV1MESAFilmGrainParameters { + StdVideoAV1MESAFilmGrainFlags flags; + uint32_t grain_scaling_minus_8; + uint32_t ar_coeff_lag; + uint32_t ar_coeff_shift_minus_6; + uint32_t grain_scale_shift; + + uint16_t grain_seed; + uint8_t num_y_points; + uint8_t point_y_value[14]; + uint8_t point_y_scaling[14]; + + uint8_t num_cb_points; + uint8_t point_cb_value[10]; + uint8_t point_cb_scaling[10]; + + uint8_t num_cr_points; + uint8_t point_cr_value[10]; + uint8_t point_cr_scaling[10]; + + int8_t ar_coeffs_y_plus_128[24]; + int8_t ar_coeffs_cb_plus_128[25]; + int8_t ar_coeffs_cr_plus_128[25]; + uint8_t cb_mult; + uint8_t cb_luma_mult; + uint16_t cb_offset; + uint8_t cr_mult; + uint8_t cr_luma_mult; + uint16_t cr_offset; +} StdVideoAV1MESAFilmGrainParameters; + +typedef struct StdVideoAV1MESAGlobalMotionFlags { + uint8_t gm_invalid; +} StdVideoAV1MESAGlobalMotionFlags; + +typedef struct StdVideoAV1MESAGlobalMotion { + StdVideoAV1MESAGlobalMotionFlags flags; + uint8_t gm_type; + uint32_t gm_params[6]; +} StdVideoAV1MESAGlobalMotion; + +typedef struct StdVideoAV1MESALoopRestoration { + uint8_t lr_type[3]; + uint8_t lr_unit_shift; + uint8_t lr_uv_shift; +} StdVideoAV1MESALoopRestoration; + +typedef struct StdVideoAV1MESATileInfoFlags { + uint8_t uniform_tile_spacing_flag; +} StdVideoAV1MESATileInfoFlags; + +typedef struct StdVideoAV1MESATileInfo { + StdVideoAV1MESATileInfoFlags flags; + uint8_t tile_cols; + uint8_t tile_rows; + uint8_t tile_start_col_sb[64]; + uint8_t tile_start_row_sb[64]; + uint8_t width_in_sbs_minus_1[64]; + uint8_t height_in_sbs_minus_1[64]; + uint16_t context_update_tile_id; + uint8_t tile_size_bytes_minus1; +} StdVideoAV1MESATileInfo; + +typedef struct StdVideoAV1MESAQuantizationFlags { + uint8_t using_qmatrix; +} StdVideoAV1MESAQuantizationFlags; + +typedef struct StdVideoAV1MESAQuantization { + StdVideoAV1MESAQuantizationFlags flags; + uint8_t base_q_idx; + int8_t delta_q_y_dc; + uint8_t diff_uv_delta; + int8_t delta_q_u_dc; + int8_t delta_q_u_ac; + int8_t delta_q_v_dc; + int8_t delta_q_v_ac; + uint8_t qm_y; + uint8_t qm_u; + uint8_t qm_v; +} StdVideoAV1MESAQuantization; + +typedef struct StdVideoAV1MESACDEF { + uint8_t damping_minus_3; + uint8_t bits; + uint8_t y_pri_strength[8]; + uint8_t y_sec_strength[8]; + uint8_t uv_pri_strength[8]; + uint8_t uv_sec_strength[8]; +} StdVideoAV1MESACDEF; + +typedef struct StdVideoAV1MESADeltaQFlags { + uint8_t delta_lf_present; + uint8_t delta_lf_multi; +} StdVideoAV1MESADeltaQFlags; + +typedef struct StdVideoAV1MESADeltaQ { + StdVideoAV1MESADeltaQFlags flags; + uint8_t delta_q_res; + uint8_t delta_lf_res; +} StdVideoAV1MESADeltaQ; + +typedef struct StdVideoAV1MESASegmentationFlags { + uint8_t enabled; + uint8_t update_map; + uint8_t temporal_update; + uint8_t update_data; +} StdVideoAV1MESASegmentationFlags; + +typedef struct StdVideoAV1MESASegmentation { + StdVideoAV1MESASegmentationFlags flags; + uint8_t feature_enabled_bits[8]; + int16_t feature_data[8][8]; +} StdVideoAV1MESASegmentation; + +typedef struct StdVideoAV1MESALoopFilterFlags { + uint8_t delta_enabled; + uint8_t delta_update; +} StdVideoAV1MESALoopFilterFlags; + +typedef struct StdVideoAV1MESALoopFilter { + StdVideoAV1MESALoopFilterFlags flags; + uint8_t level[4]; + uint8_t sharpness; + int8_t ref_deltas[8]; + int8_t mode_deltas[2]; +} StdVideoAV1MESALoopFilter; + +typedef struct StdVideoAV1MESAFrameHeaderFlags { + uint8_t error_resilient_mode; + uint8_t disable_cdf_update; + uint8_t use_superres; + uint8_t render_and_frame_size_different; + uint8_t allow_screen_content_tools; + uint8_t is_filter_switchable; + uint8_t force_integer_mv; + uint8_t frame_size_override_flag; + uint8_t buffer_removal_time_present_flag; + uint8_t allow_intrabc; + uint8_t frame_refs_short_signaling; + uint8_t allow_high_precision_mv; + uint8_t is_motion_mode_switchable; + uint8_t use_ref_frame_mvs; + uint8_t disable_frame_end_update_cdf; + uint8_t allow_warped_motion; + uint8_t reduced_tx_set; + uint8_t reference_select; + uint8_t skip_mode_present; + uint8_t delta_q_present; + uint8_t UsesLr; +} StdVideoAV1MESAFrameHeaderFlags; + +typedef struct StdVideoAV1MESAFrameHeader { + StdVideoAV1MESAFrameHeaderFlags flags; + + uint32_t frame_presentation_time; + uint32_t display_frame_id; + uint32_t current_frame_id; + uint8_t frame_to_show_map_idx; + uint8_t frame_type; + uint8_t order_hint; + uint8_t primary_ref_frame; + uint16_t frame_width_minus_1; + uint16_t frame_height_minus_1; + uint16_t render_width_minus_1; + uint16_t render_height_minus_1; + uint8_t coded_denom; + + uint8_t refresh_frame_flags; + uint8_t ref_order_hint[8]; + int8_t ref_frame_idx[7]; + uint32_t delta_frame_id_minus1[7]; + + uint8_t interpolation_filter; + uint8_t tx_mode; + + StdVideoAV1MESATileInfo tiling; + StdVideoAV1MESAQuantization quantization; + StdVideoAV1MESASegmentation segmentation; + StdVideoAV1MESADeltaQ delta_q; + StdVideoAV1MESALoopFilter loop_filter; + StdVideoAV1MESACDEF cdef; + StdVideoAV1MESALoopRestoration lr; + StdVideoAV1MESAGlobalMotion global_motion[8]; // One per ref frame + StdVideoAV1MESAFilmGrainParameters film_grain; +} StdVideoAV1MESAFrameHeader; + +typedef struct StdVideoAV1MESAScreenCoding { + uint8_t seq_force_screen_content_tools; +} StdVideoAV1MESAScreenCoding; + +typedef struct StdVideoAV1MESATimingInfoFlags { + uint8_t equal_picture_interval; +} StdVideoAV1MESATimingInfoFlags; + +typedef struct StdVideoAV1MESATimingInfo { + StdVideoAV1MESATimingInfoFlags flags; + uint32_t num_units_in_display_tick; + uint32_t time_scale; + uint32_t num_ticks_per_picture_minus_1; +} StdVideoAV1MESATimingInfo; + +typedef struct StdVideoAV1MESAColorConfigFlags { + uint8_t mono_chrome; + uint8_t color_range; + uint8_t separate_uv_delta_q; +} StdVideoAV1MESAColorConfigFlags; + +typedef struct StdVideoAV1MESAColorConfig { + StdVideoAV1MESAColorConfigFlags flags; + uint8_t bit_depth; + uint8_t subsampling_x; + uint8_t subsampling_y; +} StdVideoAV1MESAColorConfig; + +typedef struct StdVideoAV1MESASequenceHeaderFlags { + uint8_t still_picture; + uint8_t reduced_still_picture_header; + uint8_t use_128x128_superblock; + uint8_t enable_filter_intra; + uint8_t enable_intra_edge_filter; + uint8_t enable_interintra_compound; + uint8_t enable_masked_compound; + uint8_t enable_warped_motion; + uint8_t enable_dual_filter; + uint8_t enable_order_hint; + uint8_t enable_jnt_comp; + uint8_t enable_ref_frame_mvs; + uint8_t frame_id_numbers_present_flag; + uint8_t enable_superres; + uint8_t enable_cdef; + uint8_t enable_restoration; + uint8_t film_grain_params_present; + uint8_t timing_info_present_flag; + uint8_t initial_display_delay_present_flag; +} StdVideoAV1MESASequenceHeaderFlags; + +typedef struct StdVideoAV1MESASequenceHeader { + StdVideoAV1MESASequenceHeaderFlags flags; + + StdVideoAV1MESAProfile seq_profile; + uint8_t frame_width_bits_minus_1; + uint8_t frame_height_bits_minus_1; + uint16_t max_frame_width_minus_1; + uint16_t max_frame_height_minus_1; + uint8_t delta_frame_id_length_minus_2; + uint8_t additional_frame_id_length_minus_1; + uint8_t order_hint_bits_minus_1; + uint8_t seq_choose_integer_mv; + uint8_t seq_force_integer_mv; + + StdVideoAV1MESATimingInfo timing_info; + StdVideoAV1MESAColorConfig color_config; +} StdVideoAV1MESASequenceHeader; + +typedef struct StdVideoAV1MESATile { + uint16_t tg_start; + uint16_t tg_end; + uint16_t row; + uint16_t column; + uint32_t size; + uint32_t offset; +} StdVideoAV1MESATile; + +typedef struct StdVideoAV1MESATileList { + StdVideoAV1MESATile *tile_list; + uint32_t nb_tiles; +} StdVideoAV1MESATileList; + +typedef struct VkVideoDecodeAV1PictureInfoMESA { + VkStructureType sType; + const void *pNext; + StdVideoAV1MESAFrameHeader *frame_header; + StdVideoAV1MESATileList *tile_list; + uint8_t skip_mode_frame_idx[2]; +} VkVideoDecodeAV1PictureInfoMESA; + +typedef struct VkVideoDecodeAV1DpbSlotInfoMESA { + VkStructureType sType; + const void *pNext; + uint8_t frameIdx; + uint8_t ref_order_hint[7]; + uint8_t disable_frame_end_update_cdf; +} VkVideoDecodeAV1DpbSlotInfoMESA; + +typedef struct VkVideoDecodeAV1SessionParametersAddInfoMESA { + VkStructureType sType; + const void *pNext; + StdVideoAV1MESASequenceHeader *sequence_header; +} VkVideoDecodeAV1SessionParametersAddInfoMESA; + +typedef struct VkVideoDecodeAV1SessionParametersCreateInfoMESA { + VkStructureType sType; + const void *pNext; + const VkVideoDecodeAV1SessionParametersAddInfoMESA *pParametersAddInfo; +} VkVideoDecodeAV1SessionParametersCreateInfoMESA; + +typedef struct VkVideoDecodeAV1ProfileInfoMESA { + VkStructureType sType; + const void *pNext; + StdVideoAV1MESAProfile stdProfileIdc; +} VkVideoDecodeAV1ProfileInfoMESA; + +typedef enum VkVideoDecodeAV1CapabilityFlagBitsMESA { + VK_VIDEO_DECODE_AV1_CAPABILITY_EXTERNAL_FILM_GRAIN_MESA = 0x00000001, + VK_VIDEO_DECODE_AV1_CAPABILITY_FLAG_BITS_MAX_ENUM_MESA = 0x7FFFFFFF +} VkVideoDecodeAV1CapabilityFlagBitsMESA; +typedef VkFlags VkVideoDecodeAV1CapabilityFlagsMESA; + +typedef struct VkVideoDecodeAV1CapabilitiesMESA { + VkStructureType sType; + const void *pNext; + VkVideoDecodeAV1CapabilityFlagsMESA flags; + StdVideoAV1MESALevel maxLevelIdc; +} VkVideoDecodeAV1CapabilitiesMESA; + +#define VK_STRUCTURE_TYPE_VIDEO_DECODE_AV1_PICTURE_INFO_MESA 1000509000 +#define VK_STRUCTURE_TYPE_VIDEO_DECODE_AV1_SESSION_PARAMETERS_CREATE_INFO_MESA 1000509001 +#define VK_STRUCTURE_TYPE_VIDEO_DECODE_AV1_SESSION_PARAMETERS_ADD_INFO_MESA 1000509002 +#define VK_STRUCTURE_TYPE_VIDEO_DECODE_AV1_DPB_SLOT_INFO_MESA 1000509003 +#define VK_STRUCTURE_TYPE_VIDEO_DECODE_AV1_CAPABILITIES_MESA 1000509004 +#define VK_STRUCTURE_TYPE_VIDEO_DECODE_AV1_PROFILE_INFO_MESA 1000509005 + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/libavcodec/vulkan_video_codec_av1std_decode.h b/libavcodec/vulkan_video_codec_av1std_decode.h new file mode 100644 index 00000000000..a697c00593c --- /dev/null +++ b/libavcodec/vulkan_video_codec_av1std_decode.h @@ -0,0 +1,36 @@ +/* Copyright 2023 Lynne + * Copyright 2023 Dave Airlie + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef VULKAN_VIDEO_CODEC_AV1STD_DECODE_H_ +#define VULKAN_VIDEO_CODEC_AV1STD_DECODE_H_ 1 + +/* +** This header is NOT YET generated from the Khronos Vulkan XML API Registry. +** +*/ + +#ifdef __cplusplus +extern "C" { +#endif +#define vulkan_video_codec_av1std_decode 1 + + + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/libavutil/hwcontext_vulkan.c b/libavutil/hwcontext_vulkan.c index 44a07cb61bc..ef7b00376a4 100644 --- a/libavutil/hwcontext_vulkan.c +++ b/libavutil/hwcontext_vulkan.c @@ -418,6 +418,7 @@ static const VulkanOptExtension optional_device_exts[] = { { VK_KHR_VIDEO_DECODE_QUEUE_EXTENSION_NAME, FF_VK_EXT_VIDEO_DECODE_QUEUE }, { VK_KHR_VIDEO_DECODE_H264_EXTENSION_NAME, FF_VK_EXT_VIDEO_DECODE_H264 }, { VK_KHR_VIDEO_DECODE_H265_EXTENSION_NAME, FF_VK_EXT_VIDEO_DECODE_H265 }, + { "VK_MESA_video_decode_av1", FF_VK_EXT_VIDEO_DECODE_AV1 }, }; static VkBool32 VKAPI_CALL vk_dbg_callback(VkDebugUtilsMessageSeverityFlagBitsEXT severity, diff --git a/libavutil/vulkan_functions.h b/libavutil/vulkan_functions.h index c81e12f27ec..2028c76122b 100644 --- a/libavutil/vulkan_functions.h +++ b/libavutil/vulkan_functions.h @@ -43,6 +43,7 @@ typedef enum FFVulkanExtensions { FF_VK_EXT_VIDEO_DECODE_QUEUE = 1ULL << 11, /* VK_KHR_video_decode_queue */ FF_VK_EXT_VIDEO_DECODE_H264 = 1ULL << 12, /* VK_EXT_video_decode_h264 */ FF_VK_EXT_VIDEO_DECODE_H265 = 1ULL << 13, /* VK_EXT_video_decode_h265 */ + FF_VK_EXT_VIDEO_DECODE_AV1 = 1ULL << 14, /* VK_MESA_video_decode_av1 */ FF_VK_EXT_NO_FLAG = 1ULL << 31, } FFVulkanExtensions; diff --git a/libavutil/vulkan_loader.h b/libavutil/vulkan_loader.h index 5380e213030..580100e2c3b 100644 --- a/libavutil/vulkan_loader.h +++ b/libavutil/vulkan_loader.h @@ -54,6 +54,7 @@ static inline uint64_t ff_vk_extensions_to_mask(const char * const *extensions, { VK_KHR_VIDEO_DECODE_QUEUE_EXTENSION_NAME, FF_VK_EXT_VIDEO_DECODE_QUEUE }, { VK_KHR_VIDEO_DECODE_H264_EXTENSION_NAME, FF_VK_EXT_VIDEO_DECODE_H264 }, { VK_KHR_VIDEO_DECODE_H265_EXTENSION_NAME, FF_VK_EXT_VIDEO_DECODE_H265 }, + { "VK_MESA_video_decode_av1", FF_VK_EXT_VIDEO_DECODE_AV1 }, }; FFVulkanExtensions mask = 0x0; diff --git a/tests/ref/fate/source b/tests/ref/fate/source index 7b5f14b4f02..c575789dd55 100644 --- a/tests/ref/fate/source +++ b/tests/ref/fate/source @@ -23,6 +23,8 @@ compat/djgpp/math.h compat/float/float.h compat/float/limits.h libavcodec/bitstream_template.h +libavcodec/vulkan_video_codec_av1std.h +libavcodec/vulkan_video_codec_av1std_decode.h tools/decode_simple.h Use of av_clip() where av_clip_uintp2() could be used: Use of av_clip() where av_clip_intp2() could be used: From 7cfd7e4af4b1c0f280f0c64a8088d362a2917e79 Mon Sep 17 00:00:00 2001 From: Lynne Date: Wed, 22 Feb 2023 22:21:43 +0100 Subject: [PATCH 1299/2172] lavfi: add color_vulkan filter --- configure | 1 + libavfilter/Makefile | 1 + libavfilter/allfilters.c | 1 + libavfilter/vsrc_testsrc_vulkan.c | 377 ++++++++++++++++++++++++++++++ 4 files changed, 380 insertions(+) create mode 100644 libavfilter/vsrc_testsrc_vulkan.c diff --git a/configure b/configure index ed122b53ad6..a798f692447 100755 --- a/configure +++ b/configure @@ -3648,6 +3648,7 @@ boxblur_opencl_filter_deps="opencl gpl" bs2b_filter_deps="libbs2b" bwdif_vulkan_filter_deps="vulkan spirv_compiler" chromaber_vulkan_filter_deps="vulkan spirv_compiler" +color_vulkan_filter_deps="vulkan spirv_compiler" colorkey_opencl_filter_deps="opencl" colormatrix_filter_deps="gpl" convolution_opencl_filter_deps="opencl" diff --git a/libavfilter/Makefile b/libavfilter/Makefile index 4bc30c37f88..aa1d9c04976 100644 --- a/libavfilter/Makefile +++ b/libavfilter/Makefile @@ -592,6 +592,7 @@ OBJS-$(CONFIG_RGBTESTSRC_FILTER) += vsrc_testsrc.o OBJS-$(CONFIG_SIERPINSKI_FILTER) += vsrc_sierpinski.o OBJS-$(CONFIG_SMPTEBARS_FILTER) += vsrc_testsrc.o OBJS-$(CONFIG_SMPTEHDBARS_FILTER) += vsrc_testsrc.o +OBJS-$(CONFIG_COLOR_VULKAN_FILTER) += vsrc_testsrc_vulkan.o vulkan.o vulkan_filter.o OBJS-$(CONFIG_TESTSRC_FILTER) += vsrc_testsrc.o OBJS-$(CONFIG_TESTSRC2_FILTER) += vsrc_testsrc.o OBJS-$(CONFIG_YUVTESTSRC_FILTER) += vsrc_testsrc.o diff --git a/libavfilter/allfilters.c b/libavfilter/allfilters.c index 8f88c1443f2..30a8830f686 100644 --- a/libavfilter/allfilters.c +++ b/libavfilter/allfilters.c @@ -538,6 +538,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_color_vulkan; extern const AVFilter ff_vsrc_colorchart; extern const AVFilter ff_vsrc_colorspectrum; extern const AVFilter ff_vsrc_coreimagesrc; diff --git a/libavfilter/vsrc_testsrc_vulkan.c b/libavfilter/vsrc_testsrc_vulkan.c new file mode 100644 index 00000000000..7eacb57c809 --- /dev/null +++ b/libavfilter/vsrc_testsrc_vulkan.c @@ -0,0 +1,377 @@ +/* + * Copyright (c) Lynne + * + * 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/csp.h" +#include "libavutil/opt.h" +#include "vulkan_filter.h" +#include "vulkan_spirv.h" +#include "internal.h" +#include "filters.h" +#include "colorspace.h" + +enum TestSrcVulkanMode { + TESTSRC_COLOR, +}; + +typedef struct TestSrcVulkanPushData { + float color_comp[4]; +} TestSrcVulkanPushData; + +typedef struct TestSrcVulkanContext { + FFVulkanContext vkctx; + + int initialized; + FFVulkanPipeline pl; + FFVkExecPool e; + FFVkQueueFamilyCtx qf; + FFVkSPIRVShader shd; + + /* Only used by color_vulkan */ + uint8_t color_rgba[4]; + + TestSrcVulkanPushData opts; + + int w, h; + int pw, ph; + char *out_format_string; + enum AVColorRange out_range; + unsigned int nb_frame; + AVRational time_base, frame_rate; + int64_t pts; + int64_t duration; ///< duration expressed in microseconds + AVRational sar; ///< sample aspect ratio + int draw_once; ///< draw only the first frame, always put out the same picture + int draw_once_reset; ///< draw only the first frame or in case of reset + AVFrame *picref; ///< cached reference containing the painted picture +} TestSrcVulkanContext; + +static av_cold int init_filter(AVFilterContext *ctx, enum TestSrcVulkanMode mode) +{ + int err; + uint8_t *spv_data; + size_t spv_len; + void *spv_opaque = NULL; + TestSrcVulkanContext *s = ctx->priv; + FFVulkanContext *vkctx = &s->vkctx; + const int planes = av_pix_fmt_count_planes(s->vkctx.output_format); + FFVkSPIRVShader *shd = &s->shd; + FFVkSPIRVCompiler *spv; + FFVulkanDescriptorSetBinding *desc_set; + const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(s->vkctx.output_format); + + spv = ff_vk_spirv_init(); + if (!spv) { + av_log(ctx, AV_LOG_ERROR, "Unable to initialize SPIR-V compiler!\n"); + return AVERROR_EXTERNAL; + } + + ff_vk_qf_init(vkctx, &s->qf, VK_QUEUE_COMPUTE_BIT); + RET(ff_vk_exec_pool_init(vkctx, &s->qf, &s->e, s->qf.nb_queues*4, 0, 0, 0, NULL)); + RET(ff_vk_shader_init(&s->pl, &s->shd, "testsrc_compute", + VK_SHADER_STAGE_COMPUTE_BIT, 0)); + + ff_vk_shader_set_compute_sizes(&s->shd, 32, 32, 1); + + GLSLC(0, layout(push_constant, std430) uniform pushConstants { ); + GLSLC(1, vec4 color_comp; ); + GLSLC(0, }; ); + GLSLC(0, ); + + ff_vk_add_push_constant(&s->pl, 0, sizeof(s->opts), + VK_SHADER_STAGE_COMPUTE_BIT); + + desc_set = (FFVulkanDescriptorSetBinding []) { + { + .name = "output_img", + .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, + }, + }; + + RET(ff_vk_pipeline_descriptor_set_add(vkctx, &s->pl, shd, desc_set, 1, 0, 0)); + + GLSLC(0, void main() ); + GLSLC(0, { ); + GLSLC(1, ivec2 pos = ivec2(gl_GlobalInvocationID.xy); ); + if (mode == TESTSRC_COLOR) { + double rgb2yuv[3][3]; + double rgbad[4]; + double yuvad[4]; + + enum AVColorSpace csp; + const AVLumaCoefficients *luma = NULL; + + s->draw_once = 1; + + if (desc->flags & AV_PIX_FMT_FLAG_RGB) + csp = AVCOL_SPC_RGB; + else + csp = AVCOL_SPC_SMPTE170M; + + if (!(desc->flags & AV_PIX_FMT_FLAG_RGB) && !(luma = av_csp_luma_coeffs_from_avcsp(csp))) + return AVERROR(EINVAL); + else if (!(desc->flags & AV_PIX_FMT_FLAG_RGB)) + ff_fill_rgb2yuv_table(luma, rgb2yuv); + + for (int i = 0; i < 4; i++) + rgbad[i] = s->color_rgba[i] / 255.0; + + if (!(desc->flags & AV_PIX_FMT_FLAG_RGB)) + ff_matrix_mul_3x3_vec(yuvad, rgbad, rgb2yuv); + else + memcpy(yuvad, rgbad, sizeof(rgbad)); + + yuvad[3] = rgbad[3]; + + if (!(desc->flags & AV_PIX_FMT_FLAG_RGB)) { + for (int i = 0; i < 3; i++) { + int chroma = (!(desc->flags & AV_PIX_FMT_FLAG_RGB) && i > 0); + if (s->out_range == AVCOL_RANGE_MPEG) { + yuvad[i] *= (chroma ? 224.0 : 219.0) / 255.0; + yuvad[i] += (chroma ? 128.0 : 16.0) / 255.0; + } else if (chroma) { + yuvad[i] += 0.5; + } + } + } + + /* Ensure we place the alpha appropriately for gray formats */ + if (desc->nb_components <= 2) + yuvad[1] = yuvad[3]; + + for (int i = 0; i < 4; i++) + s->opts.color_comp[i] = yuvad[i]; + + GLSLC(1, vec4 r; ); + GLSLC(0, ); + for (int i = 0, c_off = 0; i < planes; i++) { + for (int c = 0; c < desc->nb_components; c++) { + if (desc->comp[c].plane == i) { + int off = desc->comp[c].offset / (FFALIGN(desc->comp[c].depth, 8)/8); + GLSLF(1, r[%i] = color_comp[%i]; ,off, c_off++); + } + } + GLSLF(1, imageStore(output_img[%i], pos, r); ,i); + GLSLC(0, ); + } + } + GLSLC(0, } ); + + RET(spv->compile_shader(spv, ctx, shd, &spv_data, &spv_len, "main", + &spv_opaque)); + RET(ff_vk_shader_create(vkctx, shd, spv_data, spv_len, "main")); + + RET(ff_vk_init_compute_pipeline(vkctx, &s->pl, shd)); + RET(ff_vk_exec_pipeline_register(vkctx, &s->e, &s->pl)); + + s->initialized = 1; + + return 0; + +fail: + if (spv_opaque) + spv->free_shader(spv, &spv_opaque); + if (spv) + spv->uninit(&spv); + + return err; +} + +static int testsrc_vulkan_activate(AVFilterContext *ctx) +{ + int err; + AVFilterLink *outlink = ctx->outputs[0]; + TestSrcVulkanContext *s = ctx->priv; + AVFrame *frame; + + if (!s->initialized) { + enum TestSrcVulkanMode mode = TESTSRC_COLOR; + err = init_filter(ctx, mode); + if (err < 0) + return err; + } + + if (!ff_outlink_frame_wanted(outlink)) + return FFERROR_NOT_READY; + if (s->duration >= 0 && + av_rescale_q(s->pts, s->time_base, AV_TIME_BASE_Q) >= s->duration) { + ff_outlink_set_status(outlink, AVERROR_EOF, s->pts); + return 0; + } + + if (s->draw_once) { + if (s->draw_once_reset) { + av_frame_free(&s->picref); + s->draw_once_reset = 0; + } + if (!s->picref) { + s->picref = ff_get_video_buffer(outlink, s->w, s->h); + if (!s->picref) + return AVERROR(ENOMEM); + + err = ff_vk_filter_process_simple(&s->vkctx, &s->e, &s->pl, s->picref, NULL, + NULL, &s->opts, sizeof(s->opts)); + if (err < 0) + return err; + } + frame = av_frame_clone(s->picref); + } else { + frame = ff_get_video_buffer(outlink, s->w, s->h); + } + + if (!frame) + return AVERROR(ENOMEM); + + frame->pts = s->pts; + frame->duration = 1; + frame->flags = AV_FRAME_FLAG_KEY; + frame->pict_type = AV_PICTURE_TYPE_I; + frame->sample_aspect_ratio = s->sar; + if (!s->draw_once) { + err = ff_vk_filter_process_simple(&s->vkctx, &s->e, &s->pl, frame, NULL, + NULL, &s->opts, sizeof(s->opts)); + if (err < 0) { + av_frame_free(&frame); + return err; + } + } + + s->pts++; + s->nb_frame++; + + return ff_filter_frame(outlink, frame); +} + +static int testsrc_vulkan_config_props(AVFilterLink *outlink) +{ + int err; + TestSrcVulkanContext *s = outlink->src->priv; + FFVulkanContext *vkctx = &s->vkctx; + + if (!s->out_format_string) { + vkctx->output_format = AV_PIX_FMT_YUV444P; + } else { + vkctx->output_format = av_get_pix_fmt(s->out_format_string); + if (vkctx->output_format == AV_PIX_FMT_NONE) { + av_log(vkctx, AV_LOG_ERROR, "Invalid output format.\n"); + return AVERROR(EINVAL); + } + } + + err = ff_vk_filter_init_context(outlink->src, vkctx, NULL, + s->w, s->h, vkctx->output_format); + if (err < 0) + return err; + + outlink->hw_frames_ctx = av_buffer_ref(vkctx->frames_ref); + if (!outlink->hw_frames_ctx) + return AVERROR(ENOMEM); + + s->time_base = av_inv_q(s->frame_rate); + s->nb_frame = 0; + s->pts = 0; + + s->vkctx.output_width = s->w; + s->vkctx.output_height = s->h; + outlink->w = s->w; + outlink->h = s->h; + outlink->sample_aspect_ratio = s->sar; + outlink->frame_rate = s->frame_rate; + outlink->time_base = s->time_base; + + return 0; +} + +static void testsrc_vulkan_uninit(AVFilterContext *avctx) +{ + TestSrcVulkanContext *s = avctx->priv; + FFVulkanContext *vkctx = &s->vkctx; + + av_frame_free(&s->picref); + + ff_vk_exec_pool_free(vkctx, &s->e); + ff_vk_pipeline_free(vkctx, &s->pl); + ff_vk_shader_free(vkctx, &s->shd); + + ff_vk_uninit(&s->vkctx); + + s->initialized = 0; +} + +#define OFFSET(x) offsetof(TestSrcVulkanContext, x) +#define FLAGS (AV_OPT_FLAG_FILTERING_PARAM | AV_OPT_FLAG_VIDEO_PARAM) + +#define COMMON_OPTS \ + { "size", "set video size", OFFSET(w), AV_OPT_TYPE_IMAGE_SIZE, { .str = "1920x1080" }, 0, 0, FLAGS }, \ + { "s", "set video size", OFFSET(w), AV_OPT_TYPE_IMAGE_SIZE, { .str = "1920x1080" }, 0, 0, FLAGS }, \ + \ + { "rate", "set video rate", OFFSET(frame_rate), AV_OPT_TYPE_VIDEO_RATE, { .str = "60" }, 0, INT_MAX, FLAGS }, \ + { "r", "set video rate", OFFSET(frame_rate), AV_OPT_TYPE_VIDEO_RATE, { .str = "60" }, 0, INT_MAX, FLAGS }, \ + \ + { "duration", "set video duration", OFFSET(duration), AV_OPT_TYPE_DURATION, { .i64 = -1 }, -1, INT64_MAX, FLAGS }, \ + { "d", "set video duration", OFFSET(duration), AV_OPT_TYPE_DURATION, { .i64 = -1 }, -1, INT64_MAX, FLAGS }, \ + \ + { "sar", "set video sample aspect ratio", OFFSET(sar), AV_OPT_TYPE_RATIONAL, { .dbl = 1 }, 0, INT_MAX, FLAGS }, \ + \ + { "format", "Output video format (software format of hardware frames)", OFFSET(out_format_string), AV_OPT_TYPE_STRING, .flags = FLAGS }, + +static const AVOption color_vulkan_options[] = { + { "color", "set color", OFFSET(color_rgba), AV_OPT_TYPE_COLOR, {.str = "black"}, 0, 0, FLAGS }, + { "c", "set color", OFFSET(color_rgba), AV_OPT_TYPE_COLOR, {.str = "black"}, 0, 0, FLAGS }, + COMMON_OPTS + { "out_range", "Output colour range (from 0 to 2) (default 0)", OFFSET(out_range), AV_OPT_TYPE_INT, {.i64 = AVCOL_RANGE_UNSPECIFIED}, AVCOL_RANGE_UNSPECIFIED, AVCOL_RANGE_JPEG, .flags = FLAGS, "range" }, + { "full", "Full range", 0, AV_OPT_TYPE_CONST, { .i64 = AVCOL_RANGE_JPEG }, 0, 0, FLAGS, "range" }, + { "limited", "Limited range", 0, AV_OPT_TYPE_CONST, { .i64 = AVCOL_RANGE_MPEG }, 0, 0, FLAGS, "range" }, + { "jpeg", "Full range", 0, AV_OPT_TYPE_CONST, { .i64 = AVCOL_RANGE_JPEG }, 0, 0, FLAGS, "range" }, + { "mpeg", "Limited range", 0, AV_OPT_TYPE_CONST, { .i64 = AVCOL_RANGE_MPEG }, 0, 0, FLAGS, "range" }, + { "tv", "Limited range", 0, AV_OPT_TYPE_CONST, { .i64 = AVCOL_RANGE_MPEG }, 0, 0, FLAGS, "range" }, + { "pc", "Full range", 0, AV_OPT_TYPE_CONST, { .i64 = AVCOL_RANGE_JPEG }, 0, 0, FLAGS, "range" }, + { NULL }, +}; + +AVFILTER_DEFINE_CLASS(color_vulkan); + +static const AVFilterPad testsrc_vulkan_outputs[] = { + { + .name = "default", + .type = AVMEDIA_TYPE_VIDEO, + .config_props = testsrc_vulkan_config_props, + }, +}; + +const AVFilter ff_vsrc_color_vulkan = { + .name = "color_vulkan", + .description = NULL_IF_CONFIG_SMALL("Generate a constant color (Vulkan)"), + .priv_size = sizeof(TestSrcVulkanContext), + .init = &ff_vk_filter_init, + .uninit = &testsrc_vulkan_uninit, + .inputs = NULL, + .flags = AVFILTER_FLAG_HWDEVICE, + .activate = testsrc_vulkan_activate, + FILTER_OUTPUTS(testsrc_vulkan_outputs), + FILTER_SINGLE_PIXFMT(AV_PIX_FMT_VULKAN), + .priv_class = &color_vulkan_class, + .flags_internal = FF_FILTER_FLAG_HWFRAME_AWARE, +}; From 88e2cca3dbd1f509982778804ba2463058bb729a Mon Sep 17 00:00:00 2001 From: Lynne Date: Sat, 18 Mar 2023 19:15:41 +0100 Subject: [PATCH 1300/2172] tools/cl2c: change to tools/source2c and allow non-OpenCL source files --- libavfilter/Makefile | 11 +++++++++-- libavfilter/opencl_source.h | 28 ++++++++++++++-------------- libavfilter/vf_avgblur_opencl.c | 2 +- libavfilter/vf_colorkey_opencl.c | 2 +- libavfilter/vf_convolution_opencl.c | 2 +- libavfilter/vf_deshake_opencl.c | 2 +- libavfilter/vf_neighbor_opencl.c | 2 +- libavfilter/vf_nlmeans_opencl.c | 2 +- libavfilter/vf_overlay_opencl.c | 2 +- libavfilter/vf_pad_opencl.c | 2 +- libavfilter/vf_remap_opencl.c | 2 +- libavfilter/vf_tonemap_opencl.c | 4 ++-- libavfilter/vf_transpose_opencl.c | 2 +- libavfilter/vf_unsharp_opencl.c | 2 +- libavfilter/vf_xfade_opencl.c | 2 +- libavfilter/vulkan/.gitignore | 1 + tools/{cl2c => source2c} | 10 ++++------ 17 files changed, 42 insertions(+), 36 deletions(-) create mode 100644 libavfilter/vulkan/.gitignore rename tools/{cl2c => source2c} (78%) diff --git a/libavfilter/Makefile b/libavfilter/Makefile index aa1d9c04976..01c083e77dc 100644 --- a/libavfilter/Makefile +++ b/libavfilter/Makefile @@ -651,10 +651,17 @@ TESTPROGS = drawutils filtfmts formats integral TOOLS-$(CONFIG_LIBZMQ) += zmqsend clean:: - $(RM) $(CLEANSUFFIXES:%=libavfilter/dnn/%) $(CLEANSUFFIXES:%=libavfilter/opencl/%) + $(RM) $(CLEANSUFFIXES:%=libavfilter/dnn/%) $(CLEANSUFFIXES:%=libavfilter/opencl/%) \ + $(CLEANSUFFIXES:%=libavfilter/vulkan/%) OPENCL = $(subst $(SRC_PATH)/,,$(wildcard $(SRC_PATH)/libavfilter/opencl/*.cl)) .SECONDARY: $(OPENCL:.cl=.c) libavfilter/opencl/%.c: TAG = OPENCL libavfilter/opencl/%.c: $(SRC_PATH)/libavfilter/opencl/%.cl - $(M)$(SRC_PATH)/tools/cl2c $< $@ + $(M)$(SRC_PATH)/tools/source2c $< $@ + +VULKAN = $(subst $(SRC_PATH)/,,$(wildcard $(SRC_PATH)/libavfilter/vulkan/*.comp)) +.SECONDARY: $(VULKAN:.comp=.c) +libavfilter/vulkan/%.c: TAG = OPENCL +libavfilter/vulkan/%.c: $(SRC_PATH)/libavfilter/vulkan/%.comp + $(M)$(SRC_PATH)/tools/source2c $< $@ diff --git a/libavfilter/opencl_source.h b/libavfilter/opencl_source.h index 9eac2dc516a..b6930fb686d 100644 --- a/libavfilter/opencl_source.h +++ b/libavfilter/opencl_source.h @@ -19,19 +19,19 @@ #ifndef AVFILTER_OPENCL_SOURCE_H #define AVFILTER_OPENCL_SOURCE_H -extern const char *ff_opencl_source_avgblur; -extern const char *ff_opencl_source_colorkey; -extern const char *ff_opencl_source_colorspace_common; -extern const char *ff_opencl_source_convolution; -extern const char *ff_opencl_source_deshake; -extern const char *ff_opencl_source_neighbor; -extern const char *ff_opencl_source_nlmeans; -extern const char *ff_opencl_source_overlay; -extern const char *ff_opencl_source_pad; -extern const char *ff_opencl_source_remap; -extern const char *ff_opencl_source_tonemap; -extern const char *ff_opencl_source_transpose; -extern const char *ff_opencl_source_unsharp; -extern const char *ff_opencl_source_xfade; +extern const char *ff_source_avgblur_cl; +extern const char *ff_source_colorkey_cl; +extern const char *ff_source_colorspace_common_cl; +extern const char *ff_source_convolution_cl; +extern const char *ff_source_deshake_cl; +extern const char *ff_source_neighbor_cl; +extern const char *ff_source_nlmeans_cl; +extern const char *ff_source_overlay_cl; +extern const char *ff_source_pad_cl; +extern const char *ff_source_remap_cl; +extern const char *ff_source_tonemap_cl; +extern const char *ff_source_transpose_cl; +extern const char *ff_source_unsharp_cl; +extern const char *ff_source_xfade_cl; #endif /* AVFILTER_OPENCL_SOURCE_H */ diff --git a/libavfilter/vf_avgblur_opencl.c b/libavfilter/vf_avgblur_opencl.c index 68f3a632492..c00d2f6363c 100644 --- a/libavfilter/vf_avgblur_opencl.c +++ b/libavfilter/vf_avgblur_opencl.c @@ -59,7 +59,7 @@ static int avgblur_opencl_init(AVFilterContext *avctx) cl_int cle; int err; - err = ff_opencl_filter_load_program(avctx, &ff_opencl_source_avgblur, 1); + err = ff_opencl_filter_load_program(avctx, &ff_source_avgblur_cl, 1); if (err < 0) goto fail; diff --git a/libavfilter/vf_colorkey_opencl.c b/libavfilter/vf_colorkey_opencl.c index 2b019b290c1..94361df88fe 100644 --- a/libavfilter/vf_colorkey_opencl.c +++ b/libavfilter/vf_colorkey_opencl.c @@ -52,7 +52,7 @@ static int colorkey_opencl_init(AVFilterContext *avctx) cl_int cle; int err; - err = ff_opencl_filter_load_program(avctx, &ff_opencl_source_colorkey, 1); + err = ff_opencl_filter_load_program(avctx, &ff_source_colorkey_cl, 1); if (err < 0) goto fail; diff --git a/libavfilter/vf_convolution_opencl.c b/libavfilter/vf_convolution_opencl.c index bf721a7416b..0eff9f40d3b 100644 --- a/libavfilter/vf_convolution_opencl.c +++ b/libavfilter/vf_convolution_opencl.c @@ -62,7 +62,7 @@ static int convolution_opencl_init(AVFilterContext *avctx) cl_int cle; int err; - err = ff_opencl_filter_load_program(avctx, &ff_opencl_source_convolution, 1); + err = ff_opencl_filter_load_program(avctx, &ff_source_convolution_cl, 1); if (err < 0) goto fail; diff --git a/libavfilter/vf_deshake_opencl.c b/libavfilter/vf_deshake_opencl.c index e670a4cc234..8db59767bdc 100644 --- a/libavfilter/vf_deshake_opencl.c +++ b/libavfilter/vf_deshake_opencl.c @@ -1251,7 +1251,7 @@ static int deshake_opencl_init(AVFilterContext *avctx) } ctx->sw_format = hw_frames_ctx->sw_format; - err = ff_opencl_filter_load_program(avctx, &ff_opencl_source_deshake, 1); + err = ff_opencl_filter_load_program(avctx, &ff_source_deshake_cl, 1); if (err < 0) goto fail; diff --git a/libavfilter/vf_neighbor_opencl.c b/libavfilter/vf_neighbor_opencl.c index d2d93cd2405..b2939f841a2 100644 --- a/libavfilter/vf_neighbor_opencl.c +++ b/libavfilter/vf_neighbor_opencl.c @@ -55,7 +55,7 @@ static int neighbor_opencl_init(AVFilterContext *avctx) cl_int cle; int err; - err = ff_opencl_filter_load_program(avctx, &ff_opencl_source_neighbor, 1); + err = ff_opencl_filter_load_program(avctx, &ff_source_neighbor_cl, 1); if (err < 0) goto fail; diff --git a/libavfilter/vf_nlmeans_opencl.c b/libavfilter/vf_nlmeans_opencl.c index ca3ec45d7a3..5149be02ca4 100644 --- a/libavfilter/vf_nlmeans_opencl.c +++ b/libavfilter/vf_nlmeans_opencl.c @@ -98,7 +98,7 @@ static int nlmeans_opencl_init(AVFilterContext *avctx, int width, int height) if (!ctx->patch_size_uv) ctx->patch_size_uv = ctx->patch_size; - err = ff_opencl_filter_load_program(avctx, &ff_opencl_source_nlmeans, 1); + err = ff_opencl_filter_load_program(avctx, &ff_source_nlmeans_cl, 1); if (err < 0) goto fail; diff --git a/libavfilter/vf_overlay_opencl.c b/libavfilter/vf_overlay_opencl.c index 38a3fc8795a..9beb09f05a1 100644 --- a/libavfilter/vf_overlay_opencl.c +++ b/libavfilter/vf_overlay_opencl.c @@ -51,7 +51,7 @@ static int overlay_opencl_load(AVFilterContext *avctx, { OverlayOpenCLContext *ctx = avctx->priv; cl_int cle; - const char *source = ff_opencl_source_overlay; + const char *source = ff_source_overlay_cl; const char *kernel; const AVPixFmtDescriptor *main_desc, *overlay_desc; int err, i, main_planes, overlay_planes; diff --git a/libavfilter/vf_pad_opencl.c b/libavfilter/vf_pad_opencl.c index d6b71765eeb..b4b10397a4d 100644 --- a/libavfilter/vf_pad_opencl.c +++ b/libavfilter/vf_pad_opencl.c @@ -93,7 +93,7 @@ static int pad_opencl_init(AVFilterContext *avctx, AVFrame *input_frame) ctx->hsub = desc->log2_chroma_w; ctx->vsub = desc->log2_chroma_h; - err = ff_opencl_filter_load_program(avctx, &ff_opencl_source_pad, 1); + err = ff_opencl_filter_load_program(avctx, &ff_source_pad_cl, 1); if (err < 0) goto fail; diff --git a/libavfilter/vf_remap_opencl.c b/libavfilter/vf_remap_opencl.c index eeb1eb5d69d..89d47426c01 100644 --- a/libavfilter/vf_remap_opencl.c +++ b/libavfilter/vf_remap_opencl.c @@ -73,7 +73,7 @@ static int remap_opencl_load(AVFilterContext *avctx, { RemapOpenCLContext *ctx = avctx->priv; cl_int cle; - const char *source = ff_opencl_source_remap; + const char *source = ff_source_remap_cl; const char *kernel = kernels[ctx->interp]; const AVPixFmtDescriptor *main_desc; int err, main_planes; diff --git a/libavfilter/vf_tonemap_opencl.c b/libavfilter/vf_tonemap_opencl.c index 883eb043427..84bf394e75a 100644 --- a/libavfilter/vf_tonemap_opencl.c +++ b/libavfilter/vf_tonemap_opencl.c @@ -240,8 +240,8 @@ static int tonemap_opencl_init(AVFilterContext *avctx) av_log(avctx, AV_LOG_DEBUG, "Generated OpenCL header:\n%s\n", header.str); opencl_sources[0] = header.str; - opencl_sources[1] = ff_opencl_source_tonemap; - opencl_sources[2] = ff_opencl_source_colorspace_common; + opencl_sources[1] = ff_source_tonemap_cl; + opencl_sources[2] = ff_source_colorspace_common_cl; err = ff_opencl_filter_load_program(avctx, opencl_sources, OPENCL_SOURCE_NB); av_bprint_finalize(&header, NULL); diff --git a/libavfilter/vf_transpose_opencl.c b/libavfilter/vf_transpose_opencl.c index 56d34d193bc..b2128049537 100644 --- a/libavfilter/vf_transpose_opencl.c +++ b/libavfilter/vf_transpose_opencl.c @@ -44,7 +44,7 @@ static int transpose_opencl_init(AVFilterContext *avctx) cl_int cle; int err; - err = ff_opencl_filter_load_program(avctx, &ff_opencl_source_transpose, 1); + err = ff_opencl_filter_load_program(avctx, &ff_source_transpose_cl, 1); if (err < 0) goto fail; diff --git a/libavfilter/vf_unsharp_opencl.c b/libavfilter/vf_unsharp_opencl.c index 2c3ac14050d..09398464ca3 100644 --- a/libavfilter/vf_unsharp_opencl.c +++ b/libavfilter/vf_unsharp_opencl.c @@ -69,7 +69,7 @@ static int unsharp_opencl_init(AVFilterContext *avctx) cl_int cle; int err; - err = ff_opencl_filter_load_program(avctx, &ff_opencl_source_unsharp, 1); + err = ff_opencl_filter_load_program(avctx, &ff_source_unsharp_cl, 1); if (err < 0) goto fail; diff --git a/libavfilter/vf_xfade_opencl.c b/libavfilter/vf_xfade_opencl.c index 415cf7ac35d..fb567aa7fd8 100644 --- a/libavfilter/vf_xfade_opencl.c +++ b/libavfilter/vf_xfade_opencl.c @@ -93,7 +93,7 @@ static int xfade_opencl_load(AVFilterContext *avctx, if (ctx->transition == CUSTOM) { err = ff_opencl_filter_load_program_from_file(avctx, ctx->source_file); } else { - err = ff_opencl_filter_load_program(avctx, &ff_opencl_source_xfade, 1); + err = ff_opencl_filter_load_program(avctx, &ff_source_xfade_cl, 1); } if (err < 0) return err; diff --git a/libavfilter/vulkan/.gitignore b/libavfilter/vulkan/.gitignore new file mode 100644 index 00000000000..064a8d8ef55 --- /dev/null +++ b/libavfilter/vulkan/.gitignore @@ -0,0 +1 @@ +*.c diff --git a/tools/cl2c b/tools/source2c similarity index 78% rename from tools/cl2c rename to tools/source2c index e3f92bab1c6..6e5f123144a 100755 --- a/tools/cl2c +++ b/tools/source2c @@ -1,7 +1,6 @@ #!/bin/sh -# Convert an OpenCL source file into a C source file containing the -# OpenCL source as a C string. Also adds a #line directive so that -# compiler messages are useful. +# Convert a source file into a C source file containing the +# source code as a C string. # This file is part of FFmpeg. # @@ -22,12 +21,11 @@ input="$1" output="$2" -name=$(basename "$input" | sed 's/.cl$//') +name=$(basename "$input" | sed 's/\./_/') cat >$output < Date: Thu, 13 Apr 2023 12:18:12 +0200 Subject: [PATCH 1301/2172] vulkan: add support for the atomic float ops extension --- libavutil/hwcontext_vulkan.c | 15 ++++++++++++++- libavutil/vulkan.c | 13 +++++++++++++ libavutil/vulkan.h | 4 ++++ libavutil/vulkan_functions.h | 1 + libavutil/vulkan_loader.h | 1 + 5 files changed, 33 insertions(+), 1 deletion(-) diff --git a/libavutil/hwcontext_vulkan.c b/libavutil/hwcontext_vulkan.c index ef7b00376a4..e8241638d91 100644 --- a/libavutil/hwcontext_vulkan.c +++ b/libavutil/hwcontext_vulkan.c @@ -96,6 +96,7 @@ typedef struct VulkanDevicePriv { VkPhysicalDeviceVulkan12Features device_features_1_2; VkPhysicalDeviceVulkan13Features device_features_1_3; VkPhysicalDeviceDescriptorBufferFeaturesEXT desc_buf_features; + VkPhysicalDeviceShaderAtomicFloatFeaturesEXT atomic_float_features; /* Queues */ pthread_mutex_t **qf_mutex; @@ -401,6 +402,7 @@ static const VulkanOptExtension optional_device_exts[] = { { VK_KHR_SAMPLER_YCBCR_CONVERSION_EXTENSION_NAME, FF_VK_EXT_NO_FLAG }, { VK_EXT_DESCRIPTOR_BUFFER_EXTENSION_NAME, FF_VK_EXT_DESCRIPTOR_BUFFER, }, { VK_EXT_PHYSICAL_DEVICE_DRM_EXTENSION_NAME, FF_VK_EXT_DEVICE_DRM }, + { VK_EXT_SHADER_ATOMIC_FLOAT_EXTENSION_NAME, FF_VK_EXT_ATOMIC_FLOAT }, /* Imports/exports */ { VK_KHR_EXTERNAL_MEMORY_FD_EXTENSION_NAME, FF_VK_EXT_EXTERNAL_FD_MEMORY }, @@ -1195,9 +1197,13 @@ static int vulkan_device_create_internal(AVHWDeviceContext *ctx, VkPhysicalDeviceTimelineSemaphoreFeatures timeline_features = { .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TIMELINE_SEMAPHORE_FEATURES, }; + VkPhysicalDeviceShaderAtomicFloatFeaturesEXT atomic_float_features = { + .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_ATOMIC_FLOAT_FEATURES_EXT, + .pNext = &timeline_features, + }; VkPhysicalDeviceDescriptorBufferFeaturesEXT desc_buf_features = { .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DESCRIPTOR_BUFFER_FEATURES_EXT, - .pNext = &timeline_features, + .pNext = &atomic_float_features, }; VkPhysicalDeviceVulkan13Features dev_features_1_3 = { .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_3_FEATURES, @@ -1229,6 +1235,10 @@ static int vulkan_device_create_internal(AVHWDeviceContext *ctx, p->device_features_1_3.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_3_FEATURES; p->device_features_1_3.pNext = &p->desc_buf_features; p->desc_buf_features.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DESCRIPTOR_BUFFER_FEATURES_EXT; + p->desc_buf_features.pNext = &p->atomic_float_features; + p->atomic_float_features.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_ATOMIC_FLOAT_FEATURES_EXT; + p->atomic_float_features.pNext = NULL; + ctx->free = vulkan_device_free; /* Create an instance if not given one */ @@ -1286,6 +1296,9 @@ static int vulkan_device_create_internal(AVHWDeviceContext *ctx, p->desc_buf_features.descriptorBuffer = desc_buf_features.descriptorBuffer; p->desc_buf_features.descriptorBufferPushDescriptors = desc_buf_features.descriptorBufferPushDescriptors; + p->atomic_float_features.shaderBufferFloat32Atomics = atomic_float_features.shaderBufferFloat32Atomics; + p->atomic_float_features.shaderBufferFloat32AtomicAdd = atomic_float_features.shaderBufferFloat32AtomicAdd; + dev_info.pNext = &hwctx->device_features; /* Setup queue family */ diff --git a/libavutil/vulkan.c b/libavutil/vulkan.c index 8a1233662f6..31e0df494b0 100644 --- a/libavutil/vulkan.c +++ b/libavutil/vulkan.c @@ -107,8 +107,21 @@ int ff_vk_load_props(FFVulkanContext *s) .pNext = &s->driver_props, }; + s->atomic_float_feats = (VkPhysicalDeviceShaderAtomicFloatFeaturesEXT) { + .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_ATOMIC_FLOAT_FEATURES_EXT, + }; + s->feats_12 = (VkPhysicalDeviceVulkan12Features) { + .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_2_FEATURES, + .pNext = &s->atomic_float_feats, + }; + s->feats = (VkPhysicalDeviceFeatures2) { + .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2, + .pNext = &s->feats_12, + }; + vk->GetPhysicalDeviceProperties2(s->hwctx->phys_dev, &s->props); vk->GetPhysicalDeviceMemoryProperties(s->hwctx->phys_dev, &s->mprops); + vk->GetPhysicalDeviceFeatures2(s->hwctx->phys_dev, &s->feats); if (s->qf_props) return 0; diff --git a/libavutil/vulkan.h b/libavutil/vulkan.h index ec03ba8b717..58da720a1cf 100644 --- a/libavutil/vulkan.h +++ b/libavutil/vulkan.h @@ -240,6 +240,10 @@ typedef struct FFVulkanContext { VkQueueFamilyProperties2 *qf_props; int tot_nb_qfs; + VkPhysicalDeviceShaderAtomicFloatFeaturesEXT atomic_float_feats; + VkPhysicalDeviceVulkan12Features feats_12; + VkPhysicalDeviceFeatures2 feats; + AVHWDeviceContext *device; AVVulkanDeviceContext *hwctx; diff --git a/libavutil/vulkan_functions.h b/libavutil/vulkan_functions.h index 2028c76122b..32f466a9334 100644 --- a/libavutil/vulkan_functions.h +++ b/libavutil/vulkan_functions.h @@ -44,6 +44,7 @@ typedef enum FFVulkanExtensions { FF_VK_EXT_VIDEO_DECODE_H264 = 1ULL << 12, /* VK_EXT_video_decode_h264 */ FF_VK_EXT_VIDEO_DECODE_H265 = 1ULL << 13, /* VK_EXT_video_decode_h265 */ FF_VK_EXT_VIDEO_DECODE_AV1 = 1ULL << 14, /* VK_MESA_video_decode_av1 */ + FF_VK_EXT_ATOMIC_FLOAT = 1ULL << 15, /* VK_EXT_shader_atomic_float */ FF_VK_EXT_NO_FLAG = 1ULL << 31, } FFVulkanExtensions; diff --git a/libavutil/vulkan_loader.h b/libavutil/vulkan_loader.h index 580100e2c3b..c45c674eafb 100644 --- a/libavutil/vulkan_loader.h +++ b/libavutil/vulkan_loader.h @@ -45,6 +45,7 @@ static inline uint64_t ff_vk_extensions_to_mask(const char * const *extensions, { 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_PHYSICAL_DEVICE_DRM_EXTENSION_NAME, FF_VK_EXT_DEVICE_DRM }, + { VK_EXT_SHADER_ATOMIC_FLOAT_EXTENSION_NAME, FF_VK_EXT_ATOMIC_FLOAT }, #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 }, From 160a415e22af417d81072dc3cb616649aea2388b Mon Sep 17 00:00:00 2001 From: Lynne Date: Thu, 13 Apr 2023 12:15:13 +0200 Subject: [PATCH 1302/2172] lavfi: add nlmeans_vulkan filter --- configure | 1 + libavfilter/Makefile | 2 + libavfilter/allfilters.c | 1 + libavfilter/vf_nlmeans_vulkan.c | 1122 ++++++++++++++++++++++++++++ libavfilter/vulkan/prefix_sum.comp | 151 ++++ libavutil/vulkan_functions.h | 1 + 6 files changed, 1278 insertions(+) create mode 100644 libavfilter/vf_nlmeans_vulkan.c create mode 100644 libavfilter/vulkan/prefix_sum.comp diff --git a/configure b/configure index a798f692447..495493aa0e8 100755 --- a/configure +++ b/configure @@ -3705,6 +3705,7 @@ minterpolate_filter_select="scene_sad" mptestsrc_filter_deps="gpl" negate_filter_deps="lut_filter" nlmeans_opencl_filter_deps="opencl" +nlmeans_vulkan_filter_deps="vulkan spirv_compiler" nnedi_filter_deps="gpl" ocr_filter_deps="libtesseract" ocv_filter_deps="libopencv" diff --git a/libavfilter/Makefile b/libavfilter/Makefile index 01c083e77dc..18935b16169 100644 --- a/libavfilter/Makefile +++ b/libavfilter/Makefile @@ -390,6 +390,8 @@ OBJS-$(CONFIG_MULTIPLY_FILTER) += vf_multiply.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_NLMEANS_VULKAN_FILTER) += vf_nlmeans_vulkan.o vulkan.o vulkan_filter.o \ + vulkan/prefix_sum.o OBJS-$(CONFIG_NNEDI_FILTER) += vf_nnedi.o OBJS-$(CONFIG_NOFORMAT_FILTER) += vf_format.o OBJS-$(CONFIG_NOISE_FILTER) += vf_noise.o diff --git a/libavfilter/allfilters.c b/libavfilter/allfilters.c index 30a8830f686..f1f781101be 100644 --- a/libavfilter/allfilters.c +++ b/libavfilter/allfilters.c @@ -368,6 +368,7 @@ extern const AVFilter ff_vf_multiply; extern const AVFilter ff_vf_negate; extern const AVFilter ff_vf_nlmeans; extern const AVFilter ff_vf_nlmeans_opencl; +extern const AVFilter ff_vf_nlmeans_vulkan; extern const AVFilter ff_vf_nnedi; extern const AVFilter ff_vf_noformat; extern const AVFilter ff_vf_noise; diff --git a/libavfilter/vf_nlmeans_vulkan.c b/libavfilter/vf_nlmeans_vulkan.c new file mode 100644 index 00000000000..97d894c9bbc --- /dev/null +++ b/libavfilter/vf_nlmeans_vulkan.c @@ -0,0 +1,1122 @@ +/* + * Copyright (c) Lynne + * + * 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 "vulkan_spirv.h" +#include "internal.h" + +#define TYPE_NAME "vec4" +#define TYPE_ELEMS 4 +#define TYPE_SIZE (TYPE_ELEMS*4) + +typedef struct NLMeansVulkanContext { + FFVulkanContext vkctx; + + int initialized; + FFVkExecPool e; + FFVkQueueFamilyCtx qf; + VkSampler sampler; + + AVBufferPool *integral_buf_pool; + AVBufferPool *state_buf_pool; + AVBufferPool *ws_buf_pool; + + int pl_weights_rows; + FFVulkanPipeline pl_weights; + FFVkSPIRVShader shd_weights; + + FFVulkanPipeline pl_denoise; + FFVkSPIRVShader shd_denoise; + + int *xoffsets; + int *yoffsets; + int nb_offsets; + float strength[4]; + int patch[4]; + + struct nlmeans_opts { + int r; + double s; + double sc[4]; + int p; + int pc[4]; + int t; + } opts; +} NLMeansVulkanContext; + +extern const char *ff_source_prefix_sum_comp; + +static void insert_first(FFVkSPIRVShader *shd, int r, int horiz, int plane, int comp) +{ + GLSLF(2, s1 = texture(input_img[%i], ivec2(x + %i, y + %i))[%i]; + ,plane, horiz ? r : 0, !horiz ? r : 0, comp); + + if (TYPE_ELEMS == 4) { + GLSLF(2, s2[0] = texture(input_img[%i], ivec2(x + %i + xoffs[0], y + %i + yoffs[0]))[%i]; + ,plane, horiz ? r : 0, !horiz ? r : 0, comp); + GLSLF(2, s2[1] = texture(input_img[%i], ivec2(x + %i + xoffs[1], y + %i + yoffs[1]))[%i]; + ,plane, horiz ? r : 0, !horiz ? r : 0, comp); + GLSLF(2, s2[2] = texture(input_img[%i], ivec2(x + %i + xoffs[2], y + %i + yoffs[2]))[%i]; + ,plane, horiz ? r : 0, !horiz ? r : 0, comp); + GLSLF(2, s2[3] = texture(input_img[%i], ivec2(x + %i + xoffs[3], y + %i + yoffs[3]))[%i]; + ,plane, horiz ? r : 0, !horiz ? r : 0, comp); + } else { + for (int i = 0; i < 16; i++) { + GLSLF(2, s2[%i][%i] = texture(input_img[%i], ivec2(x + %i + xoffs[%i], y + %i + yoffs[%i]))[%i]; + ,i / 4, i % 4, plane, horiz ? r : 0, i, !horiz ? r : 0, i, comp); + } + } + + GLSLC(2, s2 = (s1 - s2) * (s1 - s2); ); +} + +static void insert_horizontal_pass(FFVkSPIRVShader *shd, int nb_rows, int first, int plane, int comp) +{ + GLSLF(1, x = int(gl_GlobalInvocationID.x) * %i; ,nb_rows); + if (!first) { + GLSLC(1, controlBarrier(gl_ScopeWorkgroup, gl_ScopeWorkgroup, + gl_StorageSemanticsBuffer, + gl_SemanticsAcquireRelease | + gl_SemanticsMakeAvailable | + gl_SemanticsMakeVisible); ); + } + GLSLC(1, for (y = 0; y < height[0]; y++) { ); + GLSLC(2, offset = uint64_t(int_stride)*y*T_ALIGN; ); + GLSLC(2, dst = DataBuffer(uint64_t(integral_data) + offset); ); + GLSLC(0, ); + if (first) { + for (int r = 0; r < nb_rows; r++) { + insert_first(shd, r, 1, plane, comp); + GLSLF(2, dst.v[x + %i] = s2; ,r); + GLSLC(0, ); + } + } + GLSLC(2, barrier(); ); + GLSLC(2, prefix_sum(dst, 1, dst, 1); ); + GLSLC(1, } ); + GLSLC(0, ); +} + +static void insert_vertical_pass(FFVkSPIRVShader *shd, int nb_rows, int first, int plane, int comp) +{ + GLSLF(1, y = int(gl_GlobalInvocationID.x) * %i; ,nb_rows); + if (!first) { + GLSLC(1, controlBarrier(gl_ScopeWorkgroup, gl_ScopeWorkgroup, + gl_StorageSemanticsBuffer, + gl_SemanticsAcquireRelease | + gl_SemanticsMakeAvailable | + gl_SemanticsMakeVisible); ); + } + GLSLC(1, for (x = 0; x < width[0]; x++) { ); + GLSLC(2, dst = DataBuffer(uint64_t(integral_data) + x*T_ALIGN); ); + + for (int r = 0; r < nb_rows; r++) { + if (first) { + insert_first(shd, r, 0, plane, comp); + GLSLF(2, integral_data.v[(y + %i)*int_stride + x] = s2; ,r); + GLSLC(0, ); + } + } + + GLSLC(2, barrier(); ); + GLSLC(2, prefix_sum(dst, int_stride, dst, int_stride); ); + GLSLC(1, } ); + GLSLC(0, ); +} + +static void insert_weights_pass(FFVkSPIRVShader *shd, int nb_rows, int vert, + int t, int dst_comp, int plane, int comp) +{ + GLSLF(1, p = patch_size[%i]; ,dst_comp); + GLSLC(0, ); + GLSLC(1, controlBarrier(gl_ScopeWorkgroup, gl_ScopeWorkgroup, + gl_StorageSemanticsBuffer, + gl_SemanticsAcquireRelease | + gl_SemanticsMakeAvailable | + gl_SemanticsMakeVisible); ); + GLSLC(1, barrier(); ); + if (!vert) { + GLSLC(1, for (y = 0; y < height[0]; y++) { ); + GLSLF(2, if (gl_GlobalInvocationID.x*%i >= width[%i]) ,nb_rows, plane); + GLSLC(3, break; ); + GLSLF(2, for (r = 0; r < %i; r++) { ,nb_rows); + GLSLF(3, x = int(gl_GlobalInvocationID.x) * %i + r; ,nb_rows); + } else { + GLSLC(1, for (x = 0; x < width[0]; x++) { ); + GLSLF(2, if (gl_GlobalInvocationID.x*%i >= height[%i]) ,nb_rows, plane); + GLSLC(3, break; ); + GLSLF(2, for (r = 0; r < %i; r++) { ,nb_rows); + GLSLF(3, y = int(gl_GlobalInvocationID.x) * %i + r; ,nb_rows); + } + GLSLC(0, ); + GLSLC(3, a = DTYPE(0); ); + GLSLC(3, b = DTYPE(0); ); + GLSLC(3, c = DTYPE(0); ); + GLSLC(3, d = DTYPE(0); ); + GLSLC(0, ); + GLSLC(3, lt = ((x - p) < 0) || ((y - p) < 0); ); + GLSLC(0, ); + if (TYPE_ELEMS == 4) { + GLSLF(3, src[0] = texture(input_img[%i], ivec2(x + xoffs[0], y + yoffs[0]))[%i]; ,plane, comp); + GLSLF(3, src[1] = texture(input_img[%i], ivec2(x + xoffs[1], y + yoffs[1]))[%i]; ,plane, comp); + GLSLF(3, src[2] = texture(input_img[%i], ivec2(x + xoffs[2], y + yoffs[2]))[%i]; ,plane, comp); + GLSLF(3, src[3] = texture(input_img[%i], ivec2(x + xoffs[3], y + yoffs[3]))[%i]; ,plane, comp); + } else { + for (int i = 0; i < 16; i++) + GLSLF(3, src[%i][%i] = texture(input_img[%i], ivec2(x + xoffs[%i], y + yoffs[%i]))[%i]; + ,i / 4, i % 4, plane, i, i, comp); + + } + GLSLC(0, ); + GLSLC(3, if (lt == false) { ); + GLSLC(4, a = integral_data.v[(y - p)*int_stride + x - p]; ); + GLSLC(4, c = integral_data.v[(y - p)*int_stride + x + p]; ); + GLSLC(4, b = integral_data.v[(y + p)*int_stride + x - p]; ); + GLSLC(4, d = integral_data.v[(y + p)*int_stride + x + p]; ); + GLSLC(3, } ); + GLSLC(0, ); + GLSLC(3, patch_diff = d + a - b - c; ); + if (TYPE_ELEMS == 4) { + GLSLF(3, w = exp(patch_diff * strength[%i]); ,dst_comp); + GLSLC(3, w_sum = w[0] + w[1] + w[2] + w[3]; ); + GLSLC(3, sum = dot(w, src*255); ); + } else { + for (int i = 0; i < 4; i++) + GLSLF(3, w[%i] = exp(patch_diff[%i] * strength[%i]); ,i,i,dst_comp); + for (int i = 0; i < 4; i++) + GLSLF(3, w_sum %s w[%i][0] + w[%i][1] + w[%i][2] + w[%i][3]; + ,!i ? "=" : "+=", i, i, i, i); + for (int i = 0; i < 4; i++) + GLSLF(3, sum %s dot(w[%i], src[%i]*255); + ,!i ? "=" : "+=", i, i); + } + GLSLC(0, ); + if (t > 1) { + GLSLF(3, atomicAdd(weights_%i[y*ws_stride[%i] + x], w_sum); ,dst_comp, dst_comp); + GLSLF(3, atomicAdd(sums_%i[y*ws_stride[%i] + x], sum); ,dst_comp, dst_comp); + } else { + GLSLF(3, weights_%i[y*ws_stride[%i] + x] += w_sum; ,dst_comp, dst_comp); + GLSLF(3, sums_%i[y*ws_stride[%i] + x] += sum; ,dst_comp, dst_comp); + } + GLSLC(2, } ); + GLSLC(1, } ); +} + +typedef struct HorizontalPushData { + VkDeviceAddress integral_data; + VkDeviceAddress state_data; + int32_t xoffs[TYPE_ELEMS]; + int32_t yoffs[TYPE_ELEMS]; + uint32_t width[4]; + uint32_t height[4]; + uint32_t ws_stride[4]; + int32_t patch_size[4]; + float strength[4]; + uint32_t int_stride; +} HorizontalPushData; + +static av_cold int init_weights_pipeline(FFVulkanContext *vkctx, FFVkExecPool *exec, + FFVulkanPipeline *pl, FFVkSPIRVShader *shd, + VkSampler sampler, FFVkSPIRVCompiler *spv, + int width, int height, int t, + const AVPixFmtDescriptor *desc, + int planes, int *nb_rows) +{ + int err; + uint8_t *spv_data; + size_t spv_len; + void *spv_opaque = NULL; + FFVulkanDescriptorSetBinding *desc_set; + int max_dim = FFMAX(width, height); + uint32_t max_wg = vkctx->props.properties.limits.maxComputeWorkGroupSize[0]; + int max_shm = vkctx->props.properties.limits.maxComputeSharedMemorySize; + int wg_size, wg_rows; + + /* Round the max workgroup size to the previous power of two */ + max_wg = 1 << (31 - ff_clz(max_wg)); + wg_size = max_wg; + wg_rows = 1; + + if (max_wg > max_dim) { + wg_size = max_wg / (max_wg / max_dim); + } else if (max_wg < max_dim) { + /* First, make it fit */ + while (wg_size*wg_rows < max_dim) + wg_rows++; + + /* Second, make sure there's enough shared memory */ + while ((wg_size * TYPE_SIZE + TYPE_SIZE + 2*4) > max_shm) { + wg_size >>= 1; + wg_rows++; + } + } + + RET(ff_vk_shader_init(pl, shd, "nlmeans_weights", VK_SHADER_STAGE_COMPUTE_BIT, 0)); + ff_vk_shader_set_compute_sizes(shd, wg_size, 1, 1); + *nb_rows = wg_rows; + + if (t > 1) + GLSLC(0, #extension GL_EXT_shader_atomic_float : require ); + GLSLC(0, #extension GL_ARB_gpu_shader_int64 : require ); + GLSLC(0, #pragma use_vulkan_memory_model ); + GLSLC(0, #extension GL_KHR_memory_scope_semantics : enable ); + GLSLC(0, ); + GLSLF(0, #define N_ROWS %i ,*nb_rows); + GLSLC(0, #define WG_SIZE (gl_WorkGroupSize.x) ); + GLSLF(0, #define LG_WG_SIZE %i ,ff_log2(shd->local_size[0])); + GLSLC(0, #define PARTITION_SIZE (N_ROWS*WG_SIZE) ); + GLSLF(0, #define DTYPE %s ,TYPE_NAME); + GLSLF(0, #define T_ALIGN %i ,TYPE_SIZE); + GLSLC(0, ); + GLSLC(0, layout(buffer_reference, buffer_reference_align = T_ALIGN) coherent buffer DataBuffer { ); + GLSLC(1, DTYPE v[]; ); + GLSLC(0, }; ); + GLSLC(0, ); + GLSLC(0, layout(buffer_reference) buffer StateData; ); + GLSLC(0, ); + GLSLC(0, layout(push_constant, std430) uniform pushConstants { ); + GLSLC(1, coherent DataBuffer integral_data; ); + GLSLC(1, StateData state; ); + GLSLF(1, uint xoffs[%i]; ,TYPE_ELEMS); + GLSLF(1, uint yoffs[%i]; ,TYPE_ELEMS); + GLSLC(1, uvec4 width; ); + GLSLC(1, uvec4 height; ); + GLSLC(1, uvec4 ws_stride; ); + GLSLC(1, ivec4 patch_size; ); + GLSLC(1, vec4 strength; ); + GLSLC(1, uint int_stride; ); + GLSLC(0, }; ); + GLSLC(0, ); + + ff_vk_add_push_constant(pl, 0, sizeof(HorizontalPushData), VK_SHADER_STAGE_COMPUTE_BIT); + + desc_set = (FFVulkanDescriptorSetBinding []) { + { + .name = "input_img", + .type = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, + .dimensions = 2, + .elems = planes, + .stages = VK_SHADER_STAGE_COMPUTE_BIT, + .samplers = DUP_SAMPLER(sampler), + }, + { + .name = "weights_buffer_0", + .type = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, + .stages = VK_SHADER_STAGE_COMPUTE_BIT, + .buf_content = "float weights_0[];", + }, + { + .name = "sums_buffer_0", + .type = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, + .stages = VK_SHADER_STAGE_COMPUTE_BIT, + .buf_content = "float sums_0[];", + }, + { + .name = "weights_buffer_1", + .type = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, + .stages = VK_SHADER_STAGE_COMPUTE_BIT, + .buf_content = "float weights_1[];", + }, + { + .name = "sums_buffer_1", + .type = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, + .stages = VK_SHADER_STAGE_COMPUTE_BIT, + .buf_content = "float sums_1[];", + }, + { + .name = "weights_buffer_2", + .type = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, + .stages = VK_SHADER_STAGE_COMPUTE_BIT, + .buf_content = "float weights_2[];", + }, + { + .name = "sums_buffer_2", + .type = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, + .stages = VK_SHADER_STAGE_COMPUTE_BIT, + .buf_content = "float sums_2[];", + }, + { + .name = "weights_buffer_3", + .type = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, + .stages = VK_SHADER_STAGE_COMPUTE_BIT, + .buf_content = "float weights_3[];", + }, + { + .name = "sums_buffer_3", + .type = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, + .stages = VK_SHADER_STAGE_COMPUTE_BIT, + .buf_content = "float sums_3[];", + }, + }; + RET(ff_vk_pipeline_descriptor_set_add(vkctx, pl, shd, desc_set, 1 + 2*desc->nb_components, 0, 0)); + + GLSLD( ff_source_prefix_sum_comp ); + GLSLC(0, ); + GLSLC(0, void main() ); + GLSLC(0, { ); + GLSLC(1, uint64_t offset; ); + GLSLC(1, DataBuffer dst; ); + GLSLC(1, float s1; ); + GLSLC(1, DTYPE s2; ); + GLSLC(1, int r; ); + GLSLC(1, int x; ); + GLSLC(1, int y; ); + GLSLC(1, int p; ); + GLSLC(0, ); + GLSLC(1, DTYPE a; ); + GLSLC(1, DTYPE b; ); + GLSLC(1, DTYPE c; ); + GLSLC(1, DTYPE d; ); + GLSLC(0, ); + GLSLC(1, DTYPE patch_diff; ); + if (TYPE_ELEMS == 4) { + GLSLC(1, vec4 src; ); + GLSLC(1, vec4 w; ); + } else { + GLSLC(1, vec4 src[4]; ); + GLSLC(1, vec4 w[4]; ); + } + GLSLC(1, float w_sum; ); + GLSLC(1, float sum; ); + GLSLC(0, ); + GLSLC(1, bool lt; ); + GLSLC(1, bool gt; ); + GLSLC(0, ); + + for (int i = 0; i < desc->nb_components; i++) { + int off = desc->comp[i].offset / (FFALIGN(desc->comp[i].depth, 8)/8); + if (width > height) { + insert_horizontal_pass(shd, *nb_rows, 1, desc->comp[i].plane, off); + insert_vertical_pass(shd, *nb_rows, 0, desc->comp[i].plane, off); + insert_weights_pass(shd, *nb_rows, 0, t, i, desc->comp[i].plane, off); + } else { + insert_vertical_pass(shd, *nb_rows, 1, desc->comp[i].plane, off); + insert_horizontal_pass(shd, *nb_rows, 0, desc->comp[i].plane, off); + insert_weights_pass(shd, *nb_rows, 1, t, i, desc->comp[i].plane, off); + } + } + + GLSLC(0, } ); + + RET(spv->compile_shader(spv, vkctx, shd, &spv_data, &spv_len, "main", &spv_opaque)); + RET(ff_vk_shader_create(vkctx, shd, spv_data, spv_len, "main")); + + RET(ff_vk_init_compute_pipeline(vkctx, pl, shd)); + RET(ff_vk_exec_pipeline_register(vkctx, exec, pl)); + + return 0; + +fail: + if (spv_opaque) + spv->free_shader(spv, &spv_opaque); + + return err; +} + +typedef struct DenoisePushData { + uint32_t ws_stride[4]; +} DenoisePushData; + +static av_cold int init_denoise_pipeline(FFVulkanContext *vkctx, FFVkExecPool *exec, + FFVulkanPipeline *pl, FFVkSPIRVShader *shd, + VkSampler sampler, FFVkSPIRVCompiler *spv, + const AVPixFmtDescriptor *desc, int planes) +{ + int err; + uint8_t *spv_data; + size_t spv_len; + void *spv_opaque = NULL; + FFVulkanDescriptorSetBinding *desc_set; + + RET(ff_vk_shader_init(pl, shd, "nlmeans_denoise", + VK_SHADER_STAGE_COMPUTE_BIT, 0)); + + ff_vk_shader_set_compute_sizes(shd, 32, 32, 1); + + GLSLC(0, layout(push_constant, std430) uniform pushConstants { ); + GLSLC(1, uvec4 ws_stride; ); + GLSLC(0, }; ); + + ff_vk_add_push_constant(pl, 0, sizeof(DenoisePushData), VK_SHADER_STAGE_COMPUTE_BIT); + + desc_set = (FFVulkanDescriptorSetBinding []) { + { + .name = "input_img", + .type = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, + .dimensions = 2, + .elems = planes, + .stages = VK_SHADER_STAGE_COMPUTE_BIT, + .samplers = DUP_SAMPLER(sampler), + }, + { + .name = "output_img", + .type = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, + .mem_layout = ff_vk_shader_rep_fmt(vkctx->output_format), + .mem_quali = "writeonly", + .dimensions = 2, + .elems = planes, + .stages = VK_SHADER_STAGE_COMPUTE_BIT, + }, + { + .name = "weights_buffer_0", + .type = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, + .mem_quali = "readonly", + .stages = VK_SHADER_STAGE_COMPUTE_BIT, + .buf_content = "float weights_0[];", + }, + { + .name = "sums_buffer_0", + .type = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, + .mem_quali = "readonly", + .stages = VK_SHADER_STAGE_COMPUTE_BIT, + .buf_content = "float sums_0[];", + }, + { + .name = "weights_buffer_1", + .type = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, + .mem_quali = "readonly", + .stages = VK_SHADER_STAGE_COMPUTE_BIT, + .buf_content = "float weights_1[];", + }, + { + .name = "sums_buffer_1", + .type = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, + .mem_quali = "readonly", + .stages = VK_SHADER_STAGE_COMPUTE_BIT, + .buf_content = "float sums_1[];", + }, + { + .name = "weights_buffer_2", + .type = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, + .mem_quali = "readonly", + .stages = VK_SHADER_STAGE_COMPUTE_BIT, + .buf_content = "float weights_2[];", + }, + { + .name = "sums_buffer_2", + .type = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, + .mem_quali = "readonly", + .stages = VK_SHADER_STAGE_COMPUTE_BIT, + .buf_content = "float sums_2[];", + }, + { + .name = "weights_buffer_3", + .type = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, + .mem_quali = "readonly", + .stages = VK_SHADER_STAGE_COMPUTE_BIT, + .buf_content = "float weights_3[];", + }, + { + .name = "sums_buffer_3", + .type = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, + .mem_quali = "readonly", + .stages = VK_SHADER_STAGE_COMPUTE_BIT, + .buf_content = "float sums_3[];", + }, + }; + RET(ff_vk_pipeline_descriptor_set_add(vkctx, pl, shd, desc_set, 2 + 2*desc->nb_components, 0, 0)); + + GLSLC(0, void main() ); + GLSLC(0, { ); + GLSLC(1, ivec2 size; ); + GLSLC(1, const ivec2 pos = ivec2(gl_GlobalInvocationID.xy); ); + GLSLC(0, ); + GLSLC(1, float w_sum; ); + GLSLC(1, float sum; ); + GLSLC(1, vec4 src; ); + GLSLC(1, vec4 r; ); + GLSLC(0, ); + + for (int i = 0; i < planes; i++) { + GLSLF(1, src = texture(input_img[%i], pos); ,i); + for (int c = 0; c < desc->nb_components; c++) { + if (desc->comp[c].plane == i) { + int off = desc->comp[c].offset / (FFALIGN(desc->comp[c].depth, 8)/8); + GLSLF(1, w_sum = weights_%i[pos.y*ws_stride[%i] + pos.x]; ,c, c); + GLSLF(1, sum = sums_%i[pos.y*ws_stride[%i] + pos.x]; ,c, c); + GLSLF(1, r[%i] = (sum + src[%i]*255) / (1.0 + w_sum) / 255; ,off, off); + GLSLC(0, ); + } + } + GLSLF(1, imageStore(output_img[%i], pos, r); ,i); + GLSLC(0, ); + } + + GLSLC(0, } ); + + RET(spv->compile_shader(spv, vkctx, shd, &spv_data, &spv_len, "main", &spv_opaque)); + RET(ff_vk_shader_create(vkctx, shd, spv_data, spv_len, "main")); + + RET(ff_vk_init_compute_pipeline(vkctx, pl, shd)); + RET(ff_vk_exec_pipeline_register(vkctx, exec, pl)); + + return 0; + +fail: + if (spv_opaque) + spv->free_shader(spv, &spv_opaque); + + return err; +} + +static av_cold int init_filter(AVFilterContext *ctx) +{ + int rad, err; + int xcnt = 0, ycnt = 0; + NLMeansVulkanContext *s = ctx->priv; + FFVulkanContext *vkctx = &s->vkctx; + const int planes = av_pix_fmt_count_planes(s->vkctx.output_format); + FFVkSPIRVCompiler *spv; + + const AVPixFmtDescriptor *desc; + desc = av_pix_fmt_desc_get(vkctx->output_format); + if (!desc) + return AVERROR(EINVAL); + + if (!(s->opts.r & 1)) { + s->opts.r |= 1; + av_log(ctx, AV_LOG_WARNING, "Research size should be odd, setting to %i", + s->opts.r); + } + + if (!(s->opts.p & 1)) { + s->opts.p |= 1; + av_log(ctx, AV_LOG_WARNING, "Patch size should be odd, setting to %i", + s->opts.p); + } + + for (int i = 0; i < 4; i++) { + double str = (s->opts.sc[i] > 1.0) ? s->opts.sc[i] : s->opts.s; + int ps = (s->opts.pc[i] ? s->opts.pc[i] : s->opts.p); + str = 10.0f*str; + str *= -str; + str = 255.0*255.0 / str; + s->strength[i] = str; + if (!(ps & 1)) { + ps |= 1; + av_log(ctx, AV_LOG_WARNING, "Patch size should be odd, setting to %i", + ps); + } + s->patch[i] = ps / 2; + } + + rad = s->opts.r/2; + s->nb_offsets = (2*rad + 1)*(2*rad + 1) - 1; + s->xoffsets = av_malloc(s->nb_offsets*sizeof(*s->xoffsets)); + s->yoffsets = av_malloc(s->nb_offsets*sizeof(*s->yoffsets)); + s->nb_offsets = 0; + + for (int x = -rad; x <= rad; x++) { + for (int y = -rad; y <= rad; y++) { + if (!x && !y) + continue; + + s->xoffsets[xcnt++] = x; + s->yoffsets[ycnt++] = y; + s->nb_offsets++; + } + } + + s->opts.t = FFMIN(s->opts.t, (FFALIGN(s->nb_offsets, TYPE_ELEMS) / TYPE_ELEMS)); + if (!vkctx->atomic_float_feats.shaderBufferFloat32AtomicAdd) { + av_log(ctx, AV_LOG_WARNING, "Device doesn't support atomic float adds, " + "disabling dispatch parallelism\n"); + s->opts.t = 1; + } + + if (!vkctx->feats_12.vulkanMemoryModel) { + av_log(ctx, AV_LOG_ERROR, "Device doesn't support the Vulkan memory model!"); + return AVERROR(EINVAL);; + } + + spv = ff_vk_spirv_init(); + if (!spv) { + av_log(ctx, AV_LOG_ERROR, "Unable to initialize SPIR-V compiler!\n"); + return AVERROR_EXTERNAL; + } + + ff_vk_qf_init(vkctx, &s->qf, VK_QUEUE_COMPUTE_BIT); + RET(ff_vk_exec_pool_init(vkctx, &s->qf, &s->e, 1, 0, 0, 0, NULL)); + RET(ff_vk_init_sampler(vkctx, &s->sampler, 1, VK_FILTER_NEAREST)); + + RET(init_weights_pipeline(vkctx, &s->e, &s->pl_weights, &s->shd_weights, s->sampler, + spv, s->vkctx.output_width, s->vkctx.output_height, + s->opts.t, desc, planes, &s->pl_weights_rows)); + + RET(init_denoise_pipeline(vkctx, &s->e, &s->pl_denoise, &s->shd_denoise, s->sampler, + spv, desc, planes)); + + av_log(ctx, AV_LOG_VERBOSE, "Filter initialized, %i x/y offsets, %i dispatches, %i parallel\n", + s->nb_offsets, (FFALIGN(s->nb_offsets, TYPE_ELEMS) / TYPE_ELEMS) + 1, s->opts.t); + + s->initialized = 1; + + return 0; + +fail: + if (spv) + spv->uninit(&spv); + + return err; +} + +static int denoise_pass(NLMeansVulkanContext *s, FFVkExecContext *exec, + FFVkBuffer *ws_vk, uint32_t ws_stride[4]) +{ + FFVulkanContext *vkctx = &s->vkctx; + FFVulkanFunctions *vk = &vkctx->vkfn; + VkBufferMemoryBarrier2 buf_bar[8]; + int nb_buf_bar = 0; + + /* Denoise pass pipeline */ + ff_vk_exec_bind_pipeline(vkctx, exec, &s->pl_denoise); + + /* Push data */ + ff_vk_update_push_exec(vkctx, exec, &s->pl_denoise, VK_SHADER_STAGE_COMPUTE_BIT, + 0, sizeof(DenoisePushData), &(DenoisePushData) { + { ws_stride[0], ws_stride[1], ws_stride[2], ws_stride[3] }, + }); + + buf_bar[nb_buf_bar++] = (VkBufferMemoryBarrier2) { + .sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER_2, + .srcStageMask = ws_vk->stage, + .dstStageMask = VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT, + .srcAccessMask = ws_vk->access, + .dstAccessMask = VK_ACCESS_2_SHADER_STORAGE_READ_BIT, + .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, + .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, + .buffer = ws_vk->buf, + .size = ws_vk->size, + .offset = 0, + }; + + vk->CmdPipelineBarrier2(exec->buf, &(VkDependencyInfo) { + .sType = VK_STRUCTURE_TYPE_DEPENDENCY_INFO, + .pBufferMemoryBarriers = buf_bar, + .bufferMemoryBarrierCount = nb_buf_bar, + }); + ws_vk->stage = buf_bar[0].dstStageMask; + ws_vk->access = buf_bar[0].dstAccessMask; + + /* End of denoise pass */ + vk->CmdDispatch(exec->buf, + FFALIGN(vkctx->output_width, s->pl_denoise.wg_size[0])/s->pl_denoise.wg_size[0], + FFALIGN(vkctx->output_height, s->pl_denoise.wg_size[1])/s->pl_denoise.wg_size[1], + 1); + + return 0; +} + +static int nlmeans_vulkan_filter_frame(AVFilterLink *link, AVFrame *in) +{ + int err; + AVFrame *out = NULL; + AVFilterContext *ctx = link->dst; + NLMeansVulkanContext *s = ctx->priv; + AVFilterLink *outlink = ctx->outputs[0]; + FFVulkanContext *vkctx = &s->vkctx; + FFVulkanFunctions *vk = &vkctx->vkfn; + + const AVPixFmtDescriptor *desc; + int plane_widths[4]; + int plane_heights[4]; + + /* Integral */ + AVBufferRef *state_buf; + FFVkBuffer *state_vk; + AVBufferRef *integral_buf; + FFVkBuffer *integral_vk; + uint32_t int_stride; + size_t int_size; + size_t state_size; + int t_offset = 0; + + /* Weights/sums */ + AVBufferRef *ws_buf; + FFVkBuffer *ws_vk; + VkDeviceAddress weights_addr[4]; + VkDeviceAddress sums_addr[4]; + uint32_t ws_stride[4]; + size_t ws_size[4]; + size_t ws_total_size = 0; + + FFVkExecContext *exec; + VkImageView in_views[AV_NUM_DATA_POINTERS]; + VkImageView out_views[AV_NUM_DATA_POINTERS]; + VkImageMemoryBarrier2 img_bar[8]; + int nb_img_bar = 0; + VkBufferMemoryBarrier2 buf_bar[8]; + int nb_buf_bar = 0; + + if (!s->initialized) + RET(init_filter(ctx)); + + desc = av_pix_fmt_desc_get(vkctx->output_format); + if (!desc) + return AVERROR(EINVAL); + + /* Integral image */ + int_stride = s->pl_weights.wg_size[0]*s->pl_weights_rows; + int_size = int_stride * int_stride * TYPE_SIZE; + state_size = int_stride * 3 *TYPE_SIZE; + + /* Plane dimensions */ + for (int i = 0; i < desc->nb_components; i++) { + plane_widths[i] = !i || (i == 3) ? vkctx->output_width : AV_CEIL_RSHIFT(vkctx->output_width, desc->log2_chroma_w); + plane_heights[i] = !i || (i == 3) ? vkctx->output_height : AV_CEIL_RSHIFT(vkctx->output_height, desc->log2_chroma_w); + plane_widths[i] = FFALIGN(plane_widths[i], s->pl_denoise.wg_size[0]); + plane_heights[i] = FFALIGN(plane_heights[i], s->pl_denoise.wg_size[1]); + + ws_stride[i] = plane_widths[i]; + ws_size[i] = ws_stride[i] * plane_heights[i] * sizeof(float); + ws_total_size += ws_size[i]; + } + + /* Buffers */ + err = ff_vk_get_pooled_buffer(&s->vkctx, &s->integral_buf_pool, &integral_buf, + VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | + VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT, + NULL, + s->opts.t * int_size, + VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT); + if (err < 0) + return err; + integral_vk = (FFVkBuffer *)integral_buf->data; + + err = ff_vk_get_pooled_buffer(&s->vkctx, &s->state_buf_pool, &state_buf, + VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | + VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT, + NULL, + s->opts.t * state_size, + VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT); + if (err < 0) + return err; + state_vk = (FFVkBuffer *)state_buf->data; + + err = ff_vk_get_pooled_buffer(&s->vkctx, &s->ws_buf_pool, &ws_buf, + VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | + VK_BUFFER_USAGE_TRANSFER_DST_BIT | + VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT, + NULL, + ws_total_size * 2, + VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT); + if (err < 0) + return err; + ws_vk = (FFVkBuffer *)ws_buf->data; + + weights_addr[0] = ws_vk->address; + sums_addr[0] = ws_vk->address + ws_total_size; + for (int i = 1; i < desc->nb_components; i++) { + weights_addr[i] = weights_addr[i - 1] + ws_size[i - 1]; + sums_addr[i] = sums_addr[i - 1] + ws_size[i - 1]; + } + + /* Output frame */ + out = ff_get_video_buffer(outlink, outlink->w, outlink->h); + if (!out) { + err = AVERROR(ENOMEM); + goto fail; + } + + /* Execution context */ + exec = ff_vk_exec_get(&s->e); + ff_vk_exec_start(vkctx, exec); + + /* Dependencies */ + RET(ff_vk_exec_add_dep_frame(vkctx, exec, in, + VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT, + VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT)); + RET(ff_vk_exec_add_dep_frame(vkctx, exec, out, + VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT, + VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT)); + RET(ff_vk_exec_add_dep_buf(vkctx, exec, &integral_buf, 1, 0)); + RET(ff_vk_exec_add_dep_buf(vkctx, exec, &state_buf, 1, 0)); + RET(ff_vk_exec_add_dep_buf(vkctx, exec, &ws_buf, 1, 0)); + + /* Input frame prep */ + RET(ff_vk_create_imageviews(vkctx, exec, in_views, in)); + ff_vk_update_descriptor_img_array(vkctx, &s->pl_weights, exec, in, in_views, 0, 0, + VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, + s->sampler); + ff_vk_frame_barrier(vkctx, exec, in, img_bar, &nb_img_bar, + VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT, + VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT, + VK_ACCESS_SHADER_READ_BIT, + VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, + VK_QUEUE_FAMILY_IGNORED); + + /* Output frame prep */ + RET(ff_vk_create_imageviews(vkctx, exec, out_views, out)); + ff_vk_frame_barrier(vkctx, exec, out, img_bar, &nb_img_bar, + VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT, + VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT, + VK_ACCESS_SHADER_WRITE_BIT, + VK_IMAGE_LAYOUT_GENERAL, + VK_QUEUE_FAMILY_IGNORED); + + buf_bar[nb_buf_bar++] = (VkBufferMemoryBarrier2) { + .sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER_2, + .srcStageMask = ws_vk->stage, + .dstStageMask = VK_PIPELINE_STAGE_2_TRANSFER_BIT, + .srcAccessMask = ws_vk->access, + .dstAccessMask = VK_ACCESS_2_TRANSFER_WRITE_BIT, + .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, + .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, + .buffer = ws_vk->buf, + .size = ws_vk->size, + .offset = 0, + }; + + vk->CmdPipelineBarrier2(exec->buf, &(VkDependencyInfo) { + .sType = VK_STRUCTURE_TYPE_DEPENDENCY_INFO, + .pImageMemoryBarriers = img_bar, + .imageMemoryBarrierCount = nb_img_bar, + .pBufferMemoryBarriers = buf_bar, + .bufferMemoryBarrierCount = nb_buf_bar, + }); + ws_vk->stage = buf_bar[0].dstStageMask; + ws_vk->access = buf_bar[0].dstAccessMask; + + /* Weights/sums buffer zeroing */ + vk->CmdFillBuffer(exec->buf, ws_vk->buf, 0, ws_vk->size, 0x0); + + buf_bar[nb_buf_bar++] = (VkBufferMemoryBarrier2) { + .sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER_2, + .srcStageMask = ws_vk->stage, + .dstStageMask = VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT, + .srcAccessMask = ws_vk->access, + .dstAccessMask = VK_ACCESS_2_SHADER_STORAGE_READ_BIT | + VK_ACCESS_2_SHADER_STORAGE_WRITE_BIT, + .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, + .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, + .buffer = ws_vk->buf, + .size = ws_vk->size, + .offset = 0, + }; + + vk->CmdPipelineBarrier2(exec->buf, &(VkDependencyInfo) { + .sType = VK_STRUCTURE_TYPE_DEPENDENCY_INFO, + .pBufferMemoryBarriers = buf_bar, + .bufferMemoryBarrierCount = nb_buf_bar, + }); + ws_vk->stage = buf_bar[0].dstStageMask; + ws_vk->access = buf_bar[0].dstAccessMask; + + /* Update weights descriptors */ + ff_vk_update_descriptor_img_array(vkctx, &s->pl_weights, exec, in, in_views, 0, 0, + VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, + s->sampler); + for (int i = 0; i < desc->nb_components; i++) { + RET(ff_vk_set_descriptor_buffer(&s->vkctx, &s->pl_weights, exec, 0, 1 + i*2 + 0, 0, + weights_addr[i], ws_size[i], + VK_FORMAT_UNDEFINED)); + RET(ff_vk_set_descriptor_buffer(&s->vkctx, &s->pl_weights, exec, 0, 1 + i*2 + 1, 0, + sums_addr[i], ws_size[i], + VK_FORMAT_UNDEFINED)); + } + + /* Update denoise descriptors */ + ff_vk_update_descriptor_img_array(vkctx, &s->pl_denoise, exec, in, in_views, 0, 0, + VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, + s->sampler); + ff_vk_update_descriptor_img_array(vkctx, &s->pl_denoise, exec, out, out_views, 0, 1, + VK_IMAGE_LAYOUT_GENERAL, s->sampler); + for (int i = 0; i < desc->nb_components; i++) { + RET(ff_vk_set_descriptor_buffer(&s->vkctx, &s->pl_denoise, exec, 0, 2 + i*2 + 0, 0, + weights_addr[i], ws_size[i], + VK_FORMAT_UNDEFINED)); + RET(ff_vk_set_descriptor_buffer(&s->vkctx, &s->pl_denoise, exec, 0, 2 + i*2 + 1, 0, + sums_addr[i], ws_size[i], + VK_FORMAT_UNDEFINED)); + } + + /* Weights pipeline */ + ff_vk_exec_bind_pipeline(vkctx, exec, &s->pl_weights); + + for (int i = 0; i < s->nb_offsets; i += TYPE_ELEMS) { + int *xoffs = s->xoffsets + i; + int *yoffs = s->yoffsets + i; + HorizontalPushData pd = { + integral_vk->address + t_offset*int_size, + state_vk->address + t_offset*state_size, + { 0 }, + { 0 }, + { plane_widths[0], plane_widths[1], plane_widths[2], plane_widths[3] }, + { plane_heights[0], plane_heights[1], plane_heights[2], plane_heights[3] }, + { ws_stride[0], ws_stride[1], ws_stride[2], ws_stride[3] }, + { s->patch[0], s->patch[1], s->patch[2], s->patch[3] }, + { s->strength[0], s->strength[1], s->strength[2], s->strength[2], }, + int_stride, + }; + + memcpy(pd.xoffs, xoffs, sizeof(pd.xoffs)); + memcpy(pd.yoffs, yoffs, sizeof(pd.yoffs)); + + /* Put a barrier once we run out of parallelism buffers */ + if (!t_offset) { + nb_buf_bar = 0; + /* Buffer prep/sync */ + buf_bar[nb_buf_bar++] = (VkBufferMemoryBarrier2) { + .sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER_2, + .srcStageMask = integral_vk->stage, + .dstStageMask = VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT, + .srcAccessMask = integral_vk->access, + .dstAccessMask = VK_ACCESS_2_SHADER_STORAGE_READ_BIT | + VK_ACCESS_2_SHADER_STORAGE_WRITE_BIT, + .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, + .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, + .buffer = integral_vk->buf, + .size = integral_vk->size, + .offset = 0, + }; + buf_bar[nb_buf_bar++] = (VkBufferMemoryBarrier2) { + .sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER_2, + .srcStageMask = state_vk->stage, + .dstStageMask = VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT, + .srcAccessMask = state_vk->access, + .dstAccessMask = VK_ACCESS_2_SHADER_STORAGE_READ_BIT | + VK_ACCESS_2_SHADER_STORAGE_WRITE_BIT, + .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, + .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, + .buffer = state_vk->buf, + .size = state_vk->size, + .offset = 0, + }; + + vk->CmdPipelineBarrier2(exec->buf, &(VkDependencyInfo) { + .sType = VK_STRUCTURE_TYPE_DEPENDENCY_INFO, + .pBufferMemoryBarriers = buf_bar, + .bufferMemoryBarrierCount = nb_buf_bar, + }); + integral_vk->stage = buf_bar[0].dstStageMask; + integral_vk->access = buf_bar[0].dstAccessMask; + state_vk->stage = buf_bar[1].dstStageMask; + state_vk->access = buf_bar[1].dstAccessMask; + } + t_offset = (t_offset + 1) % s->opts.t; + + /* Push data */ + ff_vk_update_push_exec(vkctx, exec, &s->pl_weights, VK_SHADER_STAGE_COMPUTE_BIT, + 0, sizeof(pd), &pd); + + /* End of horizontal pass */ + vk->CmdDispatch(exec->buf, 1, 1, 1); + } + + RET(denoise_pass(s, exec, ws_vk, ws_stride)); + + err = ff_vk_exec_submit(vkctx, exec); + if (err < 0) + return err; + + err = av_frame_copy_props(out, in); + if (err < 0) + goto fail; + + av_frame_free(&in); + + return ff_filter_frame(outlink, out); + +fail: + av_frame_free(&in); + av_frame_free(&out); + return err; +} + +static void nlmeans_vulkan_uninit(AVFilterContext *avctx) +{ + NLMeansVulkanContext *s = avctx->priv; + FFVulkanContext *vkctx = &s->vkctx; + FFVulkanFunctions *vk = &vkctx->vkfn; + + ff_vk_exec_pool_free(vkctx, &s->e); + ff_vk_pipeline_free(vkctx, &s->pl_weights); + ff_vk_shader_free(vkctx, &s->shd_weights); + ff_vk_pipeline_free(vkctx, &s->pl_denoise); + ff_vk_shader_free(vkctx, &s->shd_denoise); + + av_buffer_pool_uninit(&s->integral_buf_pool); + av_buffer_pool_uninit(&s->state_buf_pool); + av_buffer_pool_uninit(&s->ws_buf_pool); + + if (s->sampler) + vk->DestroySampler(vkctx->hwctx->act_dev, s->sampler, + vkctx->hwctx->alloc); + + ff_vk_uninit(&s->vkctx); + + s->initialized = 0; +} + +#define OFFSET(x) offsetof(NLMeansVulkanContext, x) +#define FLAGS (AV_OPT_FLAG_FILTERING_PARAM | AV_OPT_FLAG_VIDEO_PARAM) +static const AVOption nlmeans_vulkan_options[] = { + { "s", "denoising strength for all components", OFFSET(opts.s), AV_OPT_TYPE_DOUBLE, { .dbl = 1.0 }, 1.0, 100.0, FLAGS }, + { "p", "patch size for all components", OFFSET(opts.p), AV_OPT_TYPE_INT, { .i64 = 3*2+1 }, 0, 99, FLAGS }, + { "r", "research window radius", OFFSET(opts.r), AV_OPT_TYPE_INT, { .i64 = 7*2+1 }, 0, 99, FLAGS }, + { "t", "parallelism", OFFSET(opts.t), AV_OPT_TYPE_INT, { .i64 = 36 }, 1, 168, FLAGS }, + + { "s1", "denoising strength for component 1", OFFSET(opts.sc[0]), AV_OPT_TYPE_DOUBLE, { .dbl = 1.0 }, 1.0, 100.0, FLAGS }, + { "s2", "denoising strength for component 2", OFFSET(opts.sc[1]), AV_OPT_TYPE_DOUBLE, { .dbl = 1.0 }, 1.0, 100.0, FLAGS }, + { "s3", "denoising strength for component 3", OFFSET(opts.sc[2]), AV_OPT_TYPE_DOUBLE, { .dbl = 1.0 }, 1.0, 100.0, FLAGS }, + { "s4", "denoising strength for component 4", OFFSET(opts.sc[3]), AV_OPT_TYPE_DOUBLE, { .dbl = 1.0 }, 1.0, 100.0, FLAGS }, + + { "p1", "patch size for component 1", OFFSET(opts.pc[0]), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 99, FLAGS }, + { "p2", "patch size for component 2", OFFSET(opts.pc[1]), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 99, FLAGS }, + { "p3", "patch size for component 3", OFFSET(opts.pc[2]), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 99, FLAGS }, + { "p4", "patch size for component 4", OFFSET(opts.pc[3]), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 99, FLAGS }, + + { NULL } +}; + +AVFILTER_DEFINE_CLASS(nlmeans_vulkan); + +static const AVFilterPad nlmeans_vulkan_inputs[] = { + { + .name = "default", + .type = AVMEDIA_TYPE_VIDEO, + .filter_frame = &nlmeans_vulkan_filter_frame, + .config_props = &ff_vk_filter_config_input, + }, +}; + +static const AVFilterPad nlmeans_vulkan_outputs[] = { + { + .name = "default", + .type = AVMEDIA_TYPE_VIDEO, + .config_props = &ff_vk_filter_config_output, + }, +}; + +const AVFilter ff_vf_nlmeans_vulkan = { + .name = "nlmeans_vulkan", + .description = NULL_IF_CONFIG_SMALL("Non-local means denoiser (Vulkan)"), + .priv_size = sizeof(NLMeansVulkanContext), + .init = &ff_vk_filter_init, + .uninit = &nlmeans_vulkan_uninit, + FILTER_INPUTS(nlmeans_vulkan_inputs), + FILTER_OUTPUTS(nlmeans_vulkan_outputs), + FILTER_SINGLE_PIXFMT(AV_PIX_FMT_VULKAN), + .priv_class = &nlmeans_vulkan_class, + .flags = AVFILTER_FLAG_HWDEVICE, + .flags_internal = FF_FILTER_FLAG_HWFRAME_AWARE, +}; diff --git a/libavfilter/vulkan/prefix_sum.comp b/libavfilter/vulkan/prefix_sum.comp new file mode 100644 index 00000000000..9147cd82fbd --- /dev/null +++ b/libavfilter/vulkan/prefix_sum.comp @@ -0,0 +1,151 @@ +#extension GL_EXT_buffer_reference : require +#extension GL_EXT_buffer_reference2 : require + +#define ACQUIRE gl_StorageSemanticsBuffer, gl_SemanticsAcquire +#define RELEASE gl_StorageSemanticsBuffer, gl_SemanticsRelease + +// These correspond to X, A, P respectively in the prefix sum paper. +#define FLAG_NOT_READY 0u +#define FLAG_AGGREGATE_READY 1u +#define FLAG_PREFIX_READY 2u + +layout(buffer_reference, buffer_reference_align = T_ALIGN) nonprivate buffer StateData { + DTYPE aggregate; + DTYPE prefix; + uint flag; +}; + +shared DTYPE sh_scratch[WG_SIZE]; +shared DTYPE sh_prefix; +shared uint sh_part_ix; +shared uint sh_flag; + +void prefix_sum(DataBuffer dst, uint dst_stride, DataBuffer src, uint src_stride) +{ + DTYPE local[N_ROWS]; + // Determine partition to process by atomic counter (described in Section 4.4 of prefix sum paper). + if (gl_GlobalInvocationID.x == 0) + sh_part_ix = gl_WorkGroupID.x; +// sh_part_ix = atomicAdd(part_counter, 1); + + barrier(); + uint part_ix = sh_part_ix; + + uint ix = part_ix * PARTITION_SIZE + gl_LocalInvocationID.x * N_ROWS; + + // TODO: gate buffer read? (evaluate whether shader check or CPU-side padding is better) + local[0] = src.v[ix*src_stride]; + for (uint i = 1; i < N_ROWS; i++) + local[i] = local[i - 1] + src.v[(ix + i)*src_stride]; + + DTYPE agg = local[N_ROWS - 1]; + sh_scratch[gl_LocalInvocationID.x] = agg; + for (uint i = 0; i < LG_WG_SIZE; i++) { + barrier(); + if (gl_LocalInvocationID.x >= (1u << i)) + agg += sh_scratch[gl_LocalInvocationID.x - (1u << i)]; + barrier(); + + sh_scratch[gl_LocalInvocationID.x] = agg; + } + + // Publish aggregate for this partition + if (gl_LocalInvocationID.x == WG_SIZE - 1) { + state[part_ix].aggregate = agg; + if (part_ix == 0) + state[0].prefix = agg; + } + + // Write flag with release semantics + if (gl_LocalInvocationID.x == WG_SIZE - 1) { + uint flag = part_ix == 0 ? FLAG_PREFIX_READY : FLAG_AGGREGATE_READY; + atomicStore(state[part_ix].flag, flag, gl_ScopeDevice, RELEASE); + } + + DTYPE exclusive = DTYPE(0); + if (part_ix != 0) { + // step 4 of paper: decoupled lookback + uint look_back_ix = part_ix - 1; + + DTYPE their_agg; + uint their_ix = 0; + while (true) { + // Read flag with acquire semantics. + if (gl_LocalInvocationID.x == WG_SIZE - 1) + sh_flag = atomicLoad(state[look_back_ix].flag, gl_ScopeDevice, ACQUIRE); + + // The flag load is done only in the last thread. However, because the + // translation of memoryBarrierBuffer to Metal requires uniform control + // flow, we broadcast it to all threads. + barrier(); + + uint flag = sh_flag; + barrier(); + + if (flag == FLAG_PREFIX_READY) { + if (gl_LocalInvocationID.x == WG_SIZE - 1) { + DTYPE their_prefix = state[look_back_ix].prefix; + exclusive = their_prefix + exclusive; + } + break; + } else if (flag == FLAG_AGGREGATE_READY) { + if (gl_LocalInvocationID.x == WG_SIZE - 1) { + their_agg = state[look_back_ix].aggregate; + exclusive = their_agg + exclusive; + } + look_back_ix--; + their_ix = 0; + continue; + } // else spins + + if (gl_LocalInvocationID.x == WG_SIZE - 1) { + // Unfortunately there's no guarantee of forward progress of other + // workgroups, so compute a bit of the aggregate before trying again. + // In the worst case, spinning stops when the aggregate is complete. + DTYPE m = src.v[(look_back_ix * PARTITION_SIZE + their_ix)*src_stride]; + if (their_ix == 0) + their_agg = m; + else + their_agg += m; + + their_ix++; + if (their_ix == PARTITION_SIZE) { + exclusive = their_agg + exclusive; + if (look_back_ix == 0) { + sh_flag = FLAG_PREFIX_READY; + } else { + look_back_ix--; + their_ix = 0; + } + } + } + barrier(); + flag = sh_flag; + barrier(); + if (flag == FLAG_PREFIX_READY) + break; + } + + // step 5 of paper: compute inclusive prefix + if (gl_LocalInvocationID.x == WG_SIZE - 1) { + DTYPE inclusive_prefix = exclusive + agg; + sh_prefix = exclusive; + state[part_ix].prefix = inclusive_prefix; + } + + if (gl_LocalInvocationID.x == WG_SIZE - 1) + atomicStore(state[part_ix].flag, FLAG_PREFIX_READY, gl_ScopeDevice, RELEASE); + } + + barrier(); + if (part_ix != 0) + exclusive = sh_prefix; + + DTYPE row = exclusive; + if (gl_LocalInvocationID.x > 0) + row += sh_scratch[gl_LocalInvocationID.x - 1]; + + // note - may overwrite + for (uint i = 0; i < N_ROWS; i++) + dst.v[(ix + i)*dst_stride] = row + local[i]; +} diff --git a/libavutil/vulkan_functions.h b/libavutil/vulkan_functions.h index 32f466a9334..58a625dd650 100644 --- a/libavutil/vulkan_functions.h +++ b/libavutil/vulkan_functions.h @@ -133,6 +133,7 @@ typedef enum FFVulkanExtensions { 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, GetBufferDeviceAddress) \ + MACRO(1, 1, FF_VK_EXT_NO_FLAG, CmdFillBuffer) \ MACRO(1, 1, FF_VK_EXT_NO_FLAG, DestroyBuffer) \ \ /* Image */ \ From f701f088f4eedf86a51920cdbdddcd9895615d40 Mon Sep 17 00:00:00 2001 From: Lynne Date: Sat, 20 May 2023 15:49:01 +0200 Subject: [PATCH 1303/2172] vulkan_h264: reject end_frame being called without valid session parameters When seeking through MBAFF-coded H264, this can happen. Decoding calls end_frame without calling start_frame. We are unable to decode this, as no frame state has been set. Happens for both VAAPI and Vulkan. Could be an issue elsewhere, hence the individual commit. --- libavcodec/vulkan_h264.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/libavcodec/vulkan_h264.c b/libavcodec/vulkan_h264.c index 3d86255966b..7df2e99617a 100644 --- a/libavcodec/vulkan_h264.c +++ b/libavcodec/vulkan_h264.c @@ -508,10 +508,14 @@ static int vk_h264_end_frame(AVCodecContext *avctx) const H264Context *h = avctx->priv_data; H264Picture *pic = h->cur_pic_ptr; H264VulkanDecodePicture *hp = pic->hwaccel_picture_private; + FFVulkanDecodeContext *dec = avctx->internal->hwaccel_priv_data; FFVulkanDecodePicture *vp = &hp->vp; FFVulkanDecodePicture *rvp[H264_MAX_PICTURE_COUNT] = { 0 }; AVFrame *rav[H264_MAX_PICTURE_COUNT] = { 0 }; + if (!dec->session_params) + return AVERROR(EINVAL); + for (int i = 0; i < vp->decode_info.referenceSlotCount; i++) { H264Picture *rp = hp->ref_src[i]; H264VulkanDecodePicture *rhp = rp->hwaccel_picture_private; From b3fb73af6b414a9ef1f9b37fd49f302e39f31cf2 Mon Sep 17 00:00:00 2001 From: Lynne Date: Sun, 28 May 2023 04:43:55 +0200 Subject: [PATCH 1304/2172] swscale: bump minor for implementing support for the new pixfmts --- libswscale/version.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libswscale/version.h b/libswscale/version.h index 79f5c69f1c5..51eb013a29f 100644 --- a/libswscale/version.h +++ b/libswscale/version.h @@ -28,7 +28,7 @@ #include "version_major.h" -#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 bef86ba86ccec65e30ca6caedea861475732d108 Mon Sep 17 00:00:00 2001 From: Lynne Date: Thu, 25 May 2023 02:10:36 +0200 Subject: [PATCH 1305/2172] APIchanges: add new pixel formats supported and bump lavu minor --- doc/APIchanges | 4 ++++ libavutil/version.h | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/doc/APIchanges b/doc/APIchanges index 130955ef02e..2f7d4386524 100644 --- a/doc/APIchanges +++ b/doc/APIchanges @@ -2,6 +2,10 @@ The last version increases of all libraries were on 2023-02-09 API changes, most recent first: +2023-05-xx - xxxxxxxxxx - lavu 58.10.100 - pixfmt.h + Add AV_PIX_FMT_P212BE, AV_PIX_FMT_P212LE, AV_PIX_FMT_P412BE, + AV_PIX_FMT_P412LE. + 2023-05-xx - xxxxxxxxxx - lavu 58.8.100 - frame.h Add av_frame_replace(). diff --git a/libavutil/version.h b/libavutil/version.h index fa53fae768e..cb237605bae 100644 --- a/libavutil/version.h +++ b/libavutil/version.h @@ -79,7 +79,7 @@ */ #define LIBAVUTIL_VERSION_MAJOR 58 -#define LIBAVUTIL_VERSION_MINOR 9 +#define LIBAVUTIL_VERSION_MINOR 10 #define LIBAVUTIL_VERSION_MICRO 100 #define LIBAVUTIL_VERSION_INT AV_VERSION_INT(LIBAVUTIL_VERSION_MAJOR, \ From db1d0227812e4f536c2913ddaf290d288d69a48f Mon Sep 17 00:00:00 2001 From: Lynne Date: Thu, 25 May 2023 02:15:28 +0200 Subject: [PATCH 1306/2172] APIchanges: add hwcontext_vulkan changes and bump lavu minor --- doc/APIchanges | 6 ++++++ libavutil/version.h | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/doc/APIchanges b/doc/APIchanges index 2f7d4386524..d092b2ade12 100644 --- a/doc/APIchanges +++ b/doc/APIchanges @@ -2,6 +2,12 @@ The last version increases of all libraries were on 2023-02-09 API changes, most recent first: +2023-05-xx - xxxxxxxxxx - lavu 58.11.100 - hwcontext_vulkan.h + Add AVVulkanDeviceContext.lock_queue, AVVulkanDeviceContext.unlock_queue, + AVVulkanFramesContext.format, AVVulkanFramesContext.lock_frame, + AVVulkanFramesContext.unlock_frame, AVVkFrame.queue_family. + Deprecate AV_VK_FRAME_FLAG_CONTIGUOUS_MEMORY (use multiplane images instead). + 2023-05-xx - xxxxxxxxxx - lavu 58.10.100 - pixfmt.h Add AV_PIX_FMT_P212BE, AV_PIX_FMT_P212LE, AV_PIX_FMT_P412BE, AV_PIX_FMT_P412LE. diff --git a/libavutil/version.h b/libavutil/version.h index cb237605bae..032d0c294d0 100644 --- a/libavutil/version.h +++ b/libavutil/version.h @@ -79,7 +79,7 @@ */ #define LIBAVUTIL_VERSION_MAJOR 58 -#define LIBAVUTIL_VERSION_MINOR 10 +#define LIBAVUTIL_VERSION_MINOR 11 #define LIBAVUTIL_VERSION_MICRO 100 #define LIBAVUTIL_VERSION_INT AV_VERSION_INT(LIBAVUTIL_VERSION_MAJOR, \ From f3795e1857484d4e73aeb174fae03224c8d0beea Mon Sep 17 00:00:00 2001 From: Lynne Date: Thu, 25 May 2023 02:19:51 +0200 Subject: [PATCH 1307/2172] APIchanges: add AVHWAccel changes and bump lavc minor --- doc/APIchanges | 4 ++++ libavcodec/version.h | 4 ++-- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/doc/APIchanges b/doc/APIchanges index d092b2ade12..2706afcf9d8 100644 --- a/doc/APIchanges +++ b/doc/APIchanges @@ -2,6 +2,10 @@ The last version increases of all libraries were on 2023-02-09 API changes, most recent first: +2023-05-xx - xxxxxxxxxx - lavc 60.15.100 - avcodec.h + Add AVHWAccel.update_thread_context, AVHWAccel.free_frame_priv, + AVHWAccel.flush. + 2023-05-xx - xxxxxxxxxx - lavu 58.11.100 - hwcontext_vulkan.h Add AVVulkanDeviceContext.lock_queue, AVVulkanDeviceContext.unlock_queue, AVVulkanFramesContext.format, AVVulkanFramesContext.lock_frame, diff --git a/libavcodec/version.h b/libavcodec/version.h index c20072197d5..9b8c2675291 100644 --- a/libavcodec/version.h +++ b/libavcodec/version.h @@ -29,8 +29,8 @@ #include "version_major.h" -#define LIBAVCODEC_VERSION_MINOR 14 -#define LIBAVCODEC_VERSION_MICRO 101 +#define LIBAVCODEC_VERSION_MINOR 15 +#define LIBAVCODEC_VERSION_MICRO 100 #define LIBAVCODEC_VERSION_INT AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \ LIBAVCODEC_VERSION_MINOR, \ From ea0394fd244eadcfaadef3e37c341faf7e094fde Mon Sep 17 00:00:00 2001 From: Lynne Date: Sun, 28 May 2023 04:32:14 +0200 Subject: [PATCH 1308/2172] changelog: add new Vulkan features --- Changelog | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Changelog b/Changelog index 55291074ec1..3d197f2b944 100644 --- a/Changelog +++ b/Changelog @@ -10,6 +10,10 @@ version : - ffmpeg CLI new option: -readrate_initial_burst - zoneplate video source filter - command support in the setpts and asetpts filters +- Vulkan decode hwaccel, supporting H264, HEVC and AV1 +- color_vulkan filter +- bwdif_vulkan filter +- nlmeans_vulkan filter version 6.0: - Radiance HDR image support From 6018f8759971c622b77b95c5795e855b35a5684f Mon Sep 17 00:00:00 2001 From: Lynne Date: Sun, 28 May 2023 17:34:29 +0200 Subject: [PATCH 1309/2172] doc/filtering: add documentation for Vulkan filters This commit documents most of the Vulkan filters. Some of this was copy-pasted from equivalent OpenCL filters. --- doc/filters.texi | 346 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 346 insertions(+) diff --git a/doc/filters.texi b/doc/filters.texi index 50505dfaa08..2333cfaf7a6 100644 --- a/doc/filters.texi +++ b/doc/filters.texi @@ -9089,6 +9089,7 @@ boxblur=luma_radius=min(h\,w)/10:luma_power=1:chroma_radius=min(cw\,ch)/10:chrom @end example @end itemize +@anchor{bwdif} @section bwdif Deinterlace the input video ("bwdif" stands for "Bob Weaver @@ -26356,6 +26357,7 @@ Apply dilation filter with threshold0 set to 30, threshold1 set 40, threshold2 s @end example @end itemize +@anchor{nlmeans_opencl} @section nlmeans_opencl Non-local Means denoise filter through OpenCL, this filter accepts same options as @ref{nlmeans}. @@ -27184,6 +27186,350 @@ See @ref{xstack}. @c man end VAAPI VIDEO FILTERS +@chapter Vulkan Video Filters +@c man begin VULKAN VIDEO FILTERS + +Below is a description of the currently available Vulkan video filters. + +To enable compilation of these filters you need to configure FFmpeg with +@code{--enable-vulkan} and either @code{--enable-libglslang} or @code{--enable-libshaderc}. + +Running Vulkan filters requires you to initialize a hardware device and to pass that device to all filters in any filter graph. +@table @option + +@item -init_hw_device vulkan[=@var{name}][:@var{device}[,@var{key=value}...]] +Initialise a new hardware device of type @var{vulkan} called @var{name}, using the +given device parameters and options in @var{key=value}. The following options +are supported: + +@table @option +@item debug +Switches validation layers on if set to 1. + +@item linear_images +Allocates linear images. Does not apply to decoding. + +@item disable_multiplane +Disables multiplane images. Does not apply to decoding. +@end table + +@item -filter_hw_device @var{name} +Pass the hardware device called @var{name} to all filters in any filter graph. + +@end table + +For more detailed information see @url{https://www.ffmpeg.org/ffmpeg.html#Advanced-Video-options} + +@itemize +@item +Example of choosing the first device and running nlmeans_vulkan filter with default parameters on it. +@example +-init_hw_device vulkan=vk:0 -filter_hw_device vk -i INPUT -vf "hwupload,nlmeans_vulkan,hwdownload" OUTPUT +@end example +@end itemize + +As Vulkan filters are not able to access frame data in normal memory, all frame data needs to be uploaded (@ref{hwupload}) to hardware surfaces connected to the appropriate device before being used and then downloaded (@ref{hwdownload}) back to normal memory. Note that @ref{hwupload} will upload to a frame with the same layout as the software frame, so it may be necessary to add a @ref{format} filter immediately before to get the input into the right format and @ref{hwdownload} does not support all formats on the output - it is usually necessary to insert an additional @ref{format} filter immediately following in the graph to get the output in a supported format. + +@section avgblur_vulkan + +Apply an average blur filter, implemented on the GPU using Vulkan. + +The filter accepts the following options: + +@table @option +@item sizeX +Set horizontal radius size. +Range is @code{[1, 32]} and default value is @code{3}. + +@item sizeY +Set vertical radius size. Range is @code{[1, 32]} and default value is @code{3}. + +@item planes +Set which planes to filter. Default value is @code{0xf}, by which all planes are processed. +@end table + +@section blend_vulkan + +Blend two Vulkan frames into each other. + +The @code{blend} filter takes two input streams and outputs one +stream, the first input is the "top" layer and second input is +"bottom" layer. By default, the output terminates when the longest input terminates. + +A description of the accepted options follows. + +@table @option +@item c0_mode +@item c1_mode +@item c2_mode +@item c3_mode +@item all_mode +Set blend mode for specific pixel component or all pixel components in case +of @var{all_mode}. Default value is @code{normal}. + +Available values for component modes are: +@table @samp +@item normal +@item multiply +@end table + +@end table + +@section bwdif_vulkan + +Deinterlacer using @ref{bwdif}, the "Bob Weaver Deinterlacing Filter" algorithm, implemented +on the GPU using Vulkan. + +It accepts the following parameters: + +@table @option +@item mode +The interlacing mode to adopt. It accepts one of the following values: + +@table @option +@item 0, send_frame +Output one frame for each frame. +@item 1, send_field +Output one frame for each field. +@end table + +The default value is @code{send_field}. + +@item parity +The picture field parity assumed for the input interlaced video. It accepts one +of the following values: + +@table @option +@item 0, tff +Assume the top field is first. +@item 1, bff +Assume the bottom field is first. +@item -1, auto +Enable automatic detection of field parity. +@end table + +The default value is @code{auto}. +If the interlacing is unknown or the decoder does not export this information, +top field first will be assumed. + +@item deint +Specify which frames to deinterlace. Accepts one of the following +values: + +@table @option +@item 0, all +Deinterlace all frames. +@item 1, interlaced +Only deinterlace frames marked as interlaced. +@end table + +The default value is @code{all}. +@end table + +@section chromaber_vulkan + +Apply an effect that emulates chromatic aberration. Works best with RGB inputs, +but provides a similar effect with YCbCr inputs too. + +@table @option +@item dist_x +Horizontal displacement multiplier. Each chroma pixel's position will be multiplied +by this amount, starting from the center of the image. Default is @code{0}. + +@item dist_y +Similarly, this sets the vertical displacement multiplier. Default is @code{0}. + +@end table + +@section color_vulkan + +Video source that creates a Vulkan frame of a solid color. +Useful for benchmarking, or overlaying. + +It accepts the following parameters: + +@table @option +@item color +The color to use. Either a name, or a hexadecimal value. +The default value is @code{black}. + +@item size +The size of the output frame. Default value is @code{1920x1080}. + +@item rate +The framerate to output at. Default value is @code{60} frames per second. + +@item duration +The video duration. Default value is @code{-0.000001}. + +@item sar +The video signal aspect ratio. Default value is @code{1/1}. + +@item format +The pixel format of the output Vulkan frames. Default value is @code{yuv444p}. + +@item out_range +Set the output YCbCr sample range. + +This allows the autodetected value to be overridden as well as allows forcing +a specific value used for the output and encoder. If not specified, the +range depends on the pixel format. Possible values: + +@table @samp +@item auto/unknown +Choose automatically. + +@item jpeg/full/pc +Set full range (0-255 in case of 8-bit luma). + +@item mpeg/limited/tv +Set "MPEG" range (16-235 in case of 8-bit luma). +@end table + +@end table + +@section vflip_vulkan + +Flips an image vertically. + +@section hflip_vulkan + +Flips an image horizontally. + +@section flip_vulkan + +Flips an image along both the vertical and horizontal axis. + +@section gblur_vulkan + +Apply Gaussian blur filter on Vulkan frames. + +The filter accepts the following options: + +@table @option +@item sigma +Set horizontal sigma, standard deviation of Gaussian blur. Default is @code{0.5}. + +@item sigmaV +Set vertical sigma, if negative it will be same as @code{sigma}. +Default is @code{-1}. + +@item planes +Set which planes to filter. By default all planes are filtered. + +@item size +Set the kernel size along the horizontal axis. Default is @code{19}. + +@item sizeV +Set the kernel size along the vertical axis. Default is @code{0}, +which sets to use the same value as @var{size}. + +@end table + +@section nlmeans_vulkan + +Denoise frames using Non-Local Means algorithm, implemented on the GPU using +Vulkan. +Supports more pixel formats than @ref{nlmeans} or @ref{nlmeans_opencl}, including +alpha channel support. + +The filter accepts the following options. + +@table @option +@item s +Set denoising strength for all components. Default is 1.0. Must be in range [1.0, 100.0]. + +@item p +Set patch size for all planes. Default is 7. Must be odd number in range [0, 99]. + +@item r +Set research size. Default is 15. Must be odd number in range [0, 99]. + +@item t +Set parallelism. Default is 36. Must be a number in the range [1, 168]. +Larger values may speed up processing, at the cost of more VRAM. +Lower values will slow it down, reducing VRAM usage. +Only supported on GPUs with atomic float operations (RDNA3+, Ampere+). + +@item s0 +@item s1 +@item s2 +@item s3 +Set denoising strength for a specific component. Default is @var{1}, equal to @option{s}. +Must be odd number in range [1, 100]. + +@item p0 +@item p1 +@item p2 +@item p3 +Set patch size for a specific component. Default is @var{7}, equal to @option{p}. +Must be odd number in range [0, 99]. + +@end table + +@section overlay_vulkan + +Overlay one video on top of another. + +It takes two inputs and has one output. The first input is the "main" video on which the second input is overlaid. +This filter requires all inputs to use the same pixel format. So, format conversion may be needed. + +The filter accepts the following options: + +@table @option +@item x +Set the x coordinate of the overlaid video on the main video. +Default value is @code{0}. + +@item y +Set the y coordinate of the overlaid video on the main video. +Default value is @code{0}. + +@end table + +@section transpose_vulkan + +Transpose rows with columns in the input video and optionally flip it. +For more in depth examples see the @ref{transpose} video filter, which shares mostly the same options. + +It accepts the following parameters: + +@table @option + +@item dir +Specify the transposition direction. + +Can assume the following values: +@table @samp +@item cclock_flip +Rotate by 90 degrees counterclockwise and vertically flip. (default) + +@item clock +Rotate by 90 degrees clockwise. + +@item cclock +Rotate by 90 degrees counterclockwise. + +@item clock_flip +Rotate by 90 degrees clockwise and vertically flip. +@end table + +@item passthrough +Do not apply the transposition if the input geometry matches the one +specified by the specified value. It accepts the following values: +@table @samp +@item none +Always apply transposition. (default) +@item portrait +Preserve portrait geometry (when @var{height} >= @var{width}). +@item landscape +Preserve landscape geometry (when @var{width} >= @var{height}). +@end table + +@end table + +@c man end VULKAN VIDEO FILTERS + @chapter QSV Video Filters @c man begin QSV VIDEO FILTERS From 0c78b0dd3b59384a1bebc6bcb89cbca48667cb55 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Thu, 25 May 2023 22:22:55 +0200 Subject: [PATCH 1310/2172] avformat/mov: creation time should be non negative Fixes: signed integer overflow: -9223372036854775808 - 2082844800 cannot be represented in type 'long' Fixes: 58384/clusterfuzz-testcase-minimized-ffmpeg_dem_MOV_fuzzer-6428383700713472 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 9fdeef057ec..192e460038e 100644 --- a/libavformat/mov.c +++ b/libavformat/mov.c @@ -1521,6 +1521,10 @@ static void mov_metadata_creation_time(MOVContext *c, AVIOContext *pb, AVDiction if (version == 1) { time = avio_rb64(pb); avio_rb64(pb); + if (time < 0) { + av_log(c->fc, AV_LOG_DEBUG, "creation_time is negative\n"); + return; + } } else { time = avio_rb32(pb); avio_rb32(pb); /* modification time */ From 75918016ab16cd69973e818759f027e78022dee4 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Mon, 22 May 2023 23:34:37 +0200 Subject: [PATCH 1311/2172] Move bessel_i0() from swresample/resample to avutil/mathematics 0th order modified bessel function of the first kind are used in multiple places, lets avoid having 3+ different implementations I picked this one as its accurate and quite fast, it can be replaced if a better one is found Signed-off-by: Michael Niedermayer --- doc/APIchanges | 3 ++ libavutil/mathematics.c | 104 ++++++++++++++++++++++++++++++++++++++ libavutil/mathematics.h | 4 ++ libavutil/version.h | 2 +- libswresample/resample.c | 106 +-------------------------------------- 5 files changed, 113 insertions(+), 106 deletions(-) diff --git a/doc/APIchanges b/doc/APIchanges index 2706afcf9d8..0232d05b108 100644 --- a/doc/APIchanges +++ b/doc/APIchanges @@ -2,6 +2,9 @@ The last version increases of all libraries were on 2023-02-09 API changes, most recent first: +2023-05-29 - xxxxxxxxxx - lavu 58.12.100 - mathematics.h + Add av_bessel_i0() + 2023-05-xx - xxxxxxxxxx - lavc 60.15.100 - avcodec.h Add AVHWAccel.update_thread_context, AVHWAccel.free_frame_priv, AVHWAccel.flush. diff --git a/libavutil/mathematics.c b/libavutil/mathematics.c index b878317d632..61aeb7c0292 100644 --- a/libavutil/mathematics.c +++ b/libavutil/mathematics.c @@ -213,3 +213,107 @@ int64_t av_add_stable(AVRational ts_tb, int64_t ts, AVRational inc_tb, int64_t i return av_sat_add64(av_rescale_q(old + 1, inc_tb, ts_tb), ts - old_ts); } } + +static inline double eval_poly(const double *coeff, int size, double x) { + double sum = coeff[size-1]; + int i; + for (i = size-2; i >= 0; --i) { + sum *= x; + sum += coeff[i]; + } + return sum; +} + +/** + * 0th order modified bessel function of the first kind. + * Algorithm taken from the Boost project, source: + * https://searchcode.com/codesearch/view/14918379/ + * Use, modification and distribution are subject to the + * Boost Software License, Version 1.0 (see notice below). + * Boost Software License - Version 1.0 - August 17th, 2003 +Permission is hereby granted, free of charge, to any person or organization +obtaining a copy of the software and accompanying documentation covered by +this license (the "Software") to use, reproduce, display, distribute, +execute, and transmit the Software, and to prepare derivative works of the +Software, and to permit third-parties to whom the Software is furnished to +do so, all subject to the following: + +The copyright notices in the Software and this entire statement, including +the above license grant, this restriction and the following disclaimer, +must be included in all copies of the Software, in whole or in part, and +all derivative works of the Software, unless such copies or derivative +works are solely in the form of machine-executable object code generated by +a source language processor. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. + */ + +double av_bessel_i0(double x) { +// Modified Bessel function of the first kind of order zero +// minimax rational approximations on intervals, see +// Blair and Edwards, Chalk River Report AECL-4928, 1974 + static const double p1[] = { + -2.2335582639474375249e+15, + -5.5050369673018427753e+14, + -3.2940087627407749166e+13, + -8.4925101247114157499e+11, + -1.1912746104985237192e+10, + -1.0313066708737980747e+08, + -5.9545626019847898221e+05, + -2.4125195876041896775e+03, + -7.0935347449210549190e+00, + -1.5453977791786851041e-02, + -2.5172644670688975051e-05, + -3.0517226450451067446e-08, + -2.6843448573468483278e-11, + -1.5982226675653184646e-14, + -5.2487866627945699800e-18, + }; + static const double q1[] = { + -2.2335582639474375245e+15, + 7.8858692566751002988e+12, + -1.2207067397808979846e+10, + 1.0377081058062166144e+07, + -4.8527560179962773045e+03, + 1.0, + }; + static const double p2[] = { + -2.2210262233306573296e-04, + 1.3067392038106924055e-02, + -4.4700805721174453923e-01, + 5.5674518371240761397e+00, + -2.3517945679239481621e+01, + 3.1611322818701131207e+01, + -9.6090021968656180000e+00, + }; + static const double q2[] = { + -5.5194330231005480228e-04, + 3.2547697594819615062e-02, + -1.1151759188741312645e+00, + 1.3982595353892851542e+01, + -6.0228002066743340583e+01, + 8.5539563258012929600e+01, + -3.1446690275135491500e+01, + 1.0, + }; + double y, r, factor; + if (x == 0) + return 1.0; + x = fabs(x); + if (x <= 15) { + y = x * x; + return eval_poly(p1, FF_ARRAY_ELEMS(p1), y) / eval_poly(q1, FF_ARRAY_ELEMS(q1), y); + } + else { + y = 1 / x - 1.0 / 15; + r = eval_poly(p2, FF_ARRAY_ELEMS(p2), y) / eval_poly(q2, FF_ARRAY_ELEMS(q2), y); + factor = exp(x) / sqrt(x); + return factor * r; + } +} diff --git a/libavutil/mathematics.h b/libavutil/mathematics.h index 3e7b52eed6a..e213bab68c9 100644 --- a/libavutil/mathematics.h +++ b/libavutil/mathematics.h @@ -288,6 +288,10 @@ int64_t av_rescale_delta(AVRational in_tb, int64_t in_ts, AVRational fs_tb, int */ int64_t av_add_stable(AVRational ts_tb, int64_t ts, AVRational inc_tb, int64_t inc); +/** + * 0th order modified bessel function of the first kind. + */ +double av_bessel_i0(double x); /** * @} diff --git a/libavutil/version.h b/libavutil/version.h index 032d0c294d0..0d8434493f1 100644 --- a/libavutil/version.h +++ b/libavutil/version.h @@ -79,7 +79,7 @@ */ #define LIBAVUTIL_VERSION_MAJOR 58 -#define LIBAVUTIL_VERSION_MINOR 11 +#define LIBAVUTIL_VERSION_MINOR 12 #define LIBAVUTIL_VERSION_MICRO 100 #define LIBAVUTIL_VERSION_INT AV_VERSION_INT(LIBAVUTIL_VERSION_MAJOR, \ diff --git a/libswresample/resample.c b/libswresample/resample.c index 8f9efc3f219..bd54a7002fb 100644 --- a/libswresample/resample.c +++ b/libswresample/resample.c @@ -30,110 +30,6 @@ #include "libavutil/cpu.h" #include "resample.h" -static inline double eval_poly(const double *coeff, int size, double x) { - double sum = coeff[size-1]; - int i; - for (i = size-2; i >= 0; --i) { - sum *= x; - sum += coeff[i]; - } - return sum; -} - -/** - * 0th order modified bessel function of the first kind. - * Algorithm taken from the Boost project, source: - * https://searchcode.com/codesearch/view/14918379/ - * Use, modification and distribution are subject to the - * Boost Software License, Version 1.0 (see notice below). - * Boost Software License - Version 1.0 - August 17th, 2003 -Permission is hereby granted, free of charge, to any person or organization -obtaining a copy of the software and accompanying documentation covered by -this license (the "Software") to use, reproduce, display, distribute, -execute, and transmit the Software, and to prepare derivative works of the -Software, and to permit third-parties to whom the Software is furnished to -do so, all subject to the following: - -The copyright notices in the Software and this entire statement, including -the above license grant, this restriction and the following disclaimer, -must be included in all copies of the Software, in whole or in part, and -all derivative works of the Software, unless such copies or derivative -works are solely in the form of machine-executable object code generated by -a source language processor. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT -SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE -FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, -ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -DEALINGS IN THE SOFTWARE. - */ - -static double bessel(double x) { -// Modified Bessel function of the first kind of order zero -// minimax rational approximations on intervals, see -// Blair and Edwards, Chalk River Report AECL-4928, 1974 - static const double p1[] = { - -2.2335582639474375249e+15, - -5.5050369673018427753e+14, - -3.2940087627407749166e+13, - -8.4925101247114157499e+11, - -1.1912746104985237192e+10, - -1.0313066708737980747e+08, - -5.9545626019847898221e+05, - -2.4125195876041896775e+03, - -7.0935347449210549190e+00, - -1.5453977791786851041e-02, - -2.5172644670688975051e-05, - -3.0517226450451067446e-08, - -2.6843448573468483278e-11, - -1.5982226675653184646e-14, - -5.2487866627945699800e-18, - }; - static const double q1[] = { - -2.2335582639474375245e+15, - 7.8858692566751002988e+12, - -1.2207067397808979846e+10, - 1.0377081058062166144e+07, - -4.8527560179962773045e+03, - 1.0, - }; - static const double p2[] = { - -2.2210262233306573296e-04, - 1.3067392038106924055e-02, - -4.4700805721174453923e-01, - 5.5674518371240761397e+00, - -2.3517945679239481621e+01, - 3.1611322818701131207e+01, - -9.6090021968656180000e+00, - }; - static const double q2[] = { - -5.5194330231005480228e-04, - 3.2547697594819615062e-02, - -1.1151759188741312645e+00, - 1.3982595353892851542e+01, - -6.0228002066743340583e+01, - 8.5539563258012929600e+01, - -3.1446690275135491500e+01, - 1.0, - }; - double y, r, factor; - if (x == 0) - return 1.0; - x = fabs(x); - if (x <= 15) { - y = x * x; - return eval_poly(p1, FF_ARRAY_ELEMS(p1), y) / eval_poly(q1, FF_ARRAY_ELEMS(q1), y); - } - else { - y = 1 / x - 1.0 / 15; - r = eval_poly(p2, FF_ARRAY_ELEMS(p2), y) / eval_poly(q2, FF_ARRAY_ELEMS(q2), y); - factor = exp(x) / sqrt(x); - return factor * r; - } -} - /** * builds a polyphase filterbank. * @param factor resampling factor @@ -189,7 +85,7 @@ static int build_filter(ResampleContext *c, void *filter, double factor, int tap break; case SWR_FILTER_TYPE_KAISER: w = 2.0*x / (factor*tap_count*M_PI); - y *= bessel(kaiser_beta*sqrt(FFMAX(1-w*w, 0))); + y *= av_bessel_i0(kaiser_beta*sqrt(FFMAX(1-w*w, 0))); break; default: av_assert0(0); From 1e9c337e0f1f179b6fded7cbe62395ed5053ef5f Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Mon, 22 May 2023 23:39:25 +0200 Subject: [PATCH 1312/2172] avfilter/asrc_sinc: Use av_bessel_i0() The new function is much more precise For default beta it is slightly slower, but its speed is already at the worst case in that comparison while the replaced function becomes much slower for larger beta Signed-off-by: Michael Niedermayer --- libavfilter/asrc_sinc.c | 19 ++----------------- 1 file changed, 2 insertions(+), 17 deletions(-) diff --git a/libavfilter/asrc_sinc.c b/libavfilter/asrc_sinc.c index 258f7a139e8..175f030f468 100644 --- a/libavfilter/asrc_sinc.c +++ b/libavfilter/asrc_sinc.c @@ -91,27 +91,12 @@ static int query_formats(AVFilterContext *ctx) return ff_set_common_samplerates_from_list(ctx, sample_rates); } -static float bessel_I_0(float x) -{ - float term = 1, sum = 1, last_sum, x2 = x / 2; - int i = 1; - - do { - float y = x2 / i++; - - last_sum = sum; - sum += term *= y * y; - } while (sum != last_sum); - - return sum; -} - static float *make_lpf(int num_taps, float Fc, float beta, float rho, float scale, int dc_norm) { int i, m = num_taps - 1; float *h = av_calloc(num_taps, sizeof(*h)), sum = 0; - float mult = scale / bessel_I_0(beta), mult1 = 1.f / (.5f * m + rho); + float mult = scale / av_bessel_i0(beta), mult1 = 1.f / (.5f * m + rho); if (!h) return NULL; @@ -121,7 +106,7 @@ static float *make_lpf(int num_taps, float Fc, float beta, float rho, for (i = 0; i <= m / 2; i++) { float z = i - .5f * m, x = z * M_PI, y = z * mult1; h[i] = x ? sinf(Fc * x) / x : Fc; - sum += h[i] *= bessel_I_0(beta * sqrtf(1.f - y * y)) * mult; + sum += h[i] *= av_bessel_i0(beta * sqrtf(1.f - y * y)) * mult; if (m - i != i) { h[m - i] = h[i]; sum += h[i]; From 0c7a0514e3d2b30ba081968d2829ca751a835967 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Tue, 23 May 2023 00:03:31 +0200 Subject: [PATCH 1313/2172] avfilter/window_func: Use av_bessel_i0() Old code needed about 6 times as long as new with defaults in afftfilt Signed-off-by: Michael Niedermayer --- libavfilter/window_func.h | 19 ++++--------------- 1 file changed, 4 insertions(+), 15 deletions(-) diff --git a/libavfilter/window_func.h b/libavfilter/window_func.h index 02b5def9dd1..d0de63b5a81 100644 --- a/libavfilter/window_func.h +++ b/libavfilter/window_func.h @@ -59,19 +59,6 @@ enum WindowFunc { WFUNC_RECT, WFUNC_HANNING, WFUNC_HAMMING, WFUNC_BLACKMAN, { "bohman", "Bohman", 0, AV_OPT_TYPE_CONST, {.i64=WFUNC_BOHMAN}, 0, 0, flag, "win_func" }, \ { "kaiser", "Kaiser", 0, AV_OPT_TYPE_CONST, {.i64=WFUNC_KAISER}, 0, 0, flag, "win_func" } -static inline double get_i0(double x) -{ - double y = 1.0, prev = 1.0, i = 1.0; - - while (fabs(prev) > 1e-20) { - double summand = prev * x * x / (4 * i * i); - y += summand; - prev = summand; - i++; - } - - return y; -} static inline void generate_window_func(float *lut, int N, int win_func, float *overlap) @@ -232,13 +219,15 @@ static inline void generate_window_func(float *lut, int N, int win_func, *overlap = 0.75; break; case WFUNC_KAISER: + { + double scale = 1.0 / av_bessel_i0(12.); for (n = 0; n < N; n++) { double x = 2.0 / (double)(N - 1); - - lut[n] = get_i0(12. * sqrt(1. - SQR(n * x - 1.))) / get_i0(12.); + lut[n] = av_bessel_i0(12. * sqrt(1. - SQR(n * x - 1.))) * scale; } *overlap = 0.75; break; + } default: av_assert0(0); } From 4ea87c0f73d4178fd5dd60cf8ec19e5e71508c9c Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Tue, 23 May 2023 00:17:58 +0200 Subject: [PATCH 1314/2172] avcodec/kbdwin: Use av_bessel_i0() Old code used about 7 times as many cpu cycles as new Signed-off-by: Michael Niedermayer --- libavcodec/kbdwin.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/libavcodec/kbdwin.c b/libavcodec/kbdwin.c index bf32aeb3176..5dff3342506 100644 --- a/libavcodec/kbdwin.c +++ b/libavcodec/kbdwin.c @@ -21,8 +21,6 @@ #include "libavutil/attributes.h" #include "kbdwin.h" -#define BESSEL_I0_ITER 50 // default: 50 iterations of Bessel I0 approximation - av_cold void ff_kbd_window_init(float *window, float alpha, int n) { int i, j; @@ -34,9 +32,7 @@ av_cold void ff_kbd_window_init(float *window, float alpha, int n) for (i = 0; i < n; i++) { tmp = i * (n - i) * alpha2; - bessel = 1.0; - for (j = BESSEL_I0_ITER; j > 0; j--) - bessel = bessel * tmp / (j * j) + 1; + bessel = av_bessel_i0(sqrt(tmp) * 2); sum += bessel; local_window[i] = sum; } From 17ecb224e94a3c111017843afbc255303ed01474 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Tue, 23 May 2023 00:55:17 +0200 Subject: [PATCH 1315/2172] avcodec/kbdwin: Avoid computing bessel values twice Also reduce neeeded temporary storage by half Signed-off-by: Michael Niedermayer --- libavcodec/kbdwin.c | 28 +++++++++++++++++----------- 1 file changed, 17 insertions(+), 11 deletions(-) diff --git a/libavcodec/kbdwin.c b/libavcodec/kbdwin.c index 5dff3342506..e2f64911248 100644 --- a/libavcodec/kbdwin.c +++ b/libavcodec/kbdwin.c @@ -23,23 +23,29 @@ av_cold void ff_kbd_window_init(float *window, float alpha, int n) { - int i, j; - double sum = 0.0, bessel, tmp; - double local_window[FF_KBD_WINDOW_MAX]; - double alpha2 = (alpha * M_PI / n) * (alpha * M_PI / n); + int i; + double sum = 0.0, tmp; + double scale = 0.0; + double temp[FF_KBD_WINDOW_MAX / 2 + 1]; + double alpha2 = 4 * (alpha * M_PI / n) * (alpha * M_PI / n); av_assert0(n <= FF_KBD_WINDOW_MAX); - for (i = 0; i < n; i++) { + for (i = 0; i <= n / 2; i++) { tmp = i * (n - i) * alpha2; - bessel = av_bessel_i0(sqrt(tmp) * 2); - sum += bessel; - local_window[i] = sum; + temp[i] = av_bessel_i0(sqrt(tmp)); + scale += temp[i] * (1 + (i && i Date: Tue, 23 May 2023 01:19:32 +0200 Subject: [PATCH 1316/2172] avcodec/kbdwin: Remove low precision intermediate in ff_kbd_window_init_fixed() Previously floats where scaled up to 32bit int, but floats do not have 32bits in their mantisse so a quarter of the bits where nonsense. It seems no fate test is affected by this change, which is interresting Signed-off-by: Michael Niedermayer --- libavcodec/kbdwin.c | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/libavcodec/kbdwin.c b/libavcodec/kbdwin.c index e2f64911248..163f9d5251f 100644 --- a/libavcodec/kbdwin.c +++ b/libavcodec/kbdwin.c @@ -21,7 +21,7 @@ #include "libavutil/attributes.h" #include "kbdwin.h" -av_cold void ff_kbd_window_init(float *window, float alpha, int n) +av_cold static void kbd_window_init(float *float_window, int *int_window, float alpha, int n) { int i; double sum = 0.0, tmp; @@ -40,20 +40,22 @@ av_cold void ff_kbd_window_init(float *window, float alpha, int n) for (i = 0; i <= n / 2; i++) { sum += temp[i]; - window[i] = sqrt(sum * scale); + if (float_window) float_window[i] = sqrt(sum * scale); + else int_window[i] = lrint(2147483647 * sqrt(sum * scale)); } for (; i < n; i++) { sum += temp[n - i]; - window[i] = sqrt(sum * scale); + if (float_window) float_window[i] = sqrt(sum * scale); + else int_window[i] = lrint(2147483647 * sqrt(sum * scale)); } } -av_cold void ff_kbd_window_init_fixed(int32_t *window, float alpha, int n) +av_cold void ff_kbd_window_init(float *window, float alpha, int n) { - int i; - float local_window[FF_KBD_WINDOW_MAX]; + kbd_window_init(window, NULL, alpha, n); +} - ff_kbd_window_init(local_window, alpha, n); - for (i = 0; i < n; i++) - window[i] = (int)floor(2147483647.0 * local_window[i] + 0.5); +av_cold void ff_kbd_window_init_fixed(int32_t *window, float alpha, int n) +{ + kbd_window_init(NULL, window, alpha, n); } From 58f82fc26a67c32586e635b67efc523ab9755b18 Mon Sep 17 00:00:00 2001 From: Lynne Date: Mon, 29 May 2023 01:10:02 +0200 Subject: [PATCH 1317/2172] vulkan: replace usage of %lu with %"SIZE_SPECIFIER" --- libavcodec/vulkan_av1.c | 2 +- libavcodec/vulkan_h264.c | 2 +- libavcodec/vulkan_hevc.c | 2 +- libavcodec/vulkan_video.c | 2 +- libavutil/vulkan.c | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/libavcodec/vulkan_av1.c b/libavcodec/vulkan_av1.c index 5dc3e8919cc..54473986120 100644 --- a/libavcodec/vulkan_av1.c +++ b/libavcodec/vulkan_av1.c @@ -542,7 +542,7 @@ static int vk_av1_end_frame(AVCodecContext *avctx) rav[i] = ap->ref_src[i]->f; } - av_log(avctx, AV_LOG_VERBOSE, "Decoding frame, %lu bytes, %i tiles\n", + av_log(avctx, AV_LOG_VERBOSE, "Decoding frame, %"SIZE_SPECIFIER" bytes, %i tiles\n", vp->slices_size, ap->tile_list.nb_tiles); return ff_vk_decode_frame(avctx, pic->f, vp, rav, rvp); diff --git a/libavcodec/vulkan_h264.c b/libavcodec/vulkan_h264.c index 7df2e99617a..05482329713 100644 --- a/libavcodec/vulkan_h264.c +++ b/libavcodec/vulkan_h264.c @@ -524,7 +524,7 @@ static int vk_h264_end_frame(AVCodecContext *avctx) rav[i] = hp->ref_src[i]->f; } - av_log(avctx, AV_LOG_VERBOSE, "Decoding frame, %lu bytes, %i slices\n", + av_log(avctx, AV_LOG_VERBOSE, "Decoding frame, %"SIZE_SPECIFIER" bytes, %i slices\n", vp->slices_size, hp->h264_pic_info.sliceCount); return ff_vk_decode_frame(avctx, pic->f, vp, rav, rvp); diff --git a/libavcodec/vulkan_hevc.c b/libavcodec/vulkan_hevc.c index 592b2526e86..c242370f33d 100644 --- a/libavcodec/vulkan_hevc.c +++ b/libavcodec/vulkan_hevc.c @@ -909,7 +909,7 @@ static int vk_hevc_end_frame(AVCodecContext *avctx) rvp[i] = &rfhp->vp; } - av_log(avctx, AV_LOG_VERBOSE, "Decoding frame, %lu bytes, %i slices\n", + av_log(avctx, AV_LOG_VERBOSE, "Decoding frame, %"SIZE_SPECIFIER" bytes, %i slices\n", vp->slices_size, hp->h265_pic_info.sliceSegmentCount); return ff_vk_decode_frame(avctx, pic->frame, vp, rav, rvp); diff --git a/libavcodec/vulkan_video.c b/libavcodec/vulkan_video.c index 24ef73ddf90..9a363aab024 100644 --- a/libavcodec/vulkan_video.c +++ b/libavcodec/vulkan_video.c @@ -339,7 +339,7 @@ av_cold int ff_vk_video_common_init(void *log, FFVulkanContext *s, .memorySize = mem[i].memoryRequirements.size, }; - av_log(log, AV_LOG_VERBOSE, "Allocating %lu bytes in bind index %i for video session\n", + av_log(log, AV_LOG_VERBOSE, "Allocating %"SIZE_SPECIFIER" bytes in bind index %i for video session\n", bind_mem[i].memorySize, bind_mem[i].memoryBindIndex); } diff --git a/libavutil/vulkan.c b/libavutil/vulkan.c index 31e0df494b0..bc4466e6c9a 100644 --- a/libavutil/vulkan.c +++ b/libavutil/vulkan.c @@ -1079,7 +1079,7 @@ int ff_vk_get_pooled_buffer(FFVulkanContext *ctx, AVBufferPool **buf_pool, ff_vk_free_buf(ctx, data); memset(data, 0, sizeof(*data)); - av_log(ctx, AV_LOG_DEBUG, "Allocating buffer of %lu bytes for pool %p\n", + av_log(ctx, AV_LOG_DEBUG, "Allocating buffer of %"SIZE_SPECIFIER" bytes for pool %p\n", size, *buf_pool); err = ff_vk_create_buf(ctx, data, size, From bae92361ed130aef1bada7c59eb67393510e0f1a Mon Sep 17 00:00:00 2001 From: Lynne Date: Mon, 29 May 2023 02:04:59 +0200 Subject: [PATCH 1318/2172] vulkan_decode: check if yuv_sampler exists before freeing it This prevents multiple NULL accesses - if yuv_sampler exists, then everything required for it to be destroyed also exists. --- libavcodec/vulkan_decode.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/libavcodec/vulkan_decode.c b/libavcodec/vulkan_decode.c index 1d1fb9ad974..6138106fefd 100644 --- a/libavcodec/vulkan_decode.c +++ b/libavcodec/vulkan_decode.c @@ -581,8 +581,9 @@ static void free_common(void *opaque, uint8_t *data) ff_vk_video_common_uninit(s, &ctx->common); - vk->DestroySamplerYcbcrConversion(s->hwctx->act_dev, ctx->yuv_sampler, - s->hwctx->alloc); + if (ctx->yuv_sampler) + vk->DestroySamplerYcbcrConversion(s->hwctx->act_dev, ctx->yuv_sampler, + s->hwctx->alloc); ff_vk_uninit(s); } From fe103ee61faa91a5d623f0f5024d56b55933df52 Mon Sep 17 00:00:00 2001 From: James Almer Date: Sun, 28 May 2023 23:18:40 -0300 Subject: [PATCH 1319/2172] avcodec/vulkan_dec: use PRId64 specifier for an int64_t Fixes warnings on x86-32 and Windows. Signed-off-by: James Almer --- libavcodec/vulkan_decode.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavcodec/vulkan_decode.c b/libavcodec/vulkan_decode.c index 6138106fefd..4ec6f166129 100644 --- a/libavcodec/vulkan_decode.c +++ b/libavcodec/vulkan_decode.c @@ -342,7 +342,7 @@ int ff_vk_decode_frame(AVCodecContext *avctx, if (ret == VK_SUCCESS) av_log(avctx, prev_sub_res < 0 ? AV_LOG_ERROR : AV_LOG_DEBUG, - "Result of previous frame decoding: %li\n", prev_sub_res); + "Result of previous frame decoding: %"PRId64"\n", prev_sub_res); } sd_buf = (FFVkVideoBuffer *)vp->slices_buf->data; From 246bec23a9225ffe9e6ad247ba26073a201a1be8 Mon Sep 17 00:00:00 2001 From: James Almer Date: Sun, 28 May 2023 23:24:51 -0300 Subject: [PATCH 1320/2172] avcodec/hevc_ps: remove a unused variable Signed-off-by: James Almer --- libavcodec/hevc_ps.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavcodec/hevc_ps.c b/libavcodec/hevc_ps.c index 01b11ed42aa..d7930d3ac3e 100644 --- a/libavcodec/hevc_ps.c +++ b/libavcodec/hevc_ps.c @@ -856,7 +856,7 @@ int ff_hevc_parse_sps(HEVCSPS *sps, GetBitContext *gb, unsigned int *sps_id, HEVCWindow *ow; int ret = 0; int bit_depth_chroma, start, num_comps; - int i, j; + int i; // Coded parameters From e71cd1804920b846757adcd45da22b3958f58f83 Mon Sep 17 00:00:00 2001 From: Lynne Date: Mon, 29 May 2023 03:50:25 +0200 Subject: [PATCH 1321/2172] vulkan_decode: do not align the image dimensions According to Dave Airlie: > but I think ignoring it should be fine, I can't see any > other way to get the imaeg extents correct for other usage > what width/height should be used for the images? > the final presentable dimensions, or the coded dimensions? > if you don't want noise I think the presentable dims > the driver should round up the allocations internally, > but if you are going to sample from the images then w/h have to be > the bounds of the image you want > since otherwise there's no way to stop the sampler from > going outside the edges Apparently, the alignment values are informative, rather than mandatory, but the spec's wording makes it sound as if they're mandatory. --- libavcodec/vulkan_decode.c | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-) diff --git a/libavcodec/vulkan_decode.c b/libavcodec/vulkan_decode.c index 4ec6f166129..f79ca7f229d 100644 --- a/libavcodec/vulkan_decode.c +++ b/libavcodec/vulkan_decode.c @@ -702,7 +702,6 @@ static VkResult vulkan_setup_profile(AVCodecContext *avctx, } static int vulkan_decode_get_profile(AVCodecContext *avctx, AVBufferRef *frames_ref, - int *width_align, int *height_align, enum AVPixelFormat *pix_fmt, VkFormat *vk_fmt, int *dpb_dedicate) { @@ -841,10 +840,10 @@ static int vulkan_decode_get_profile(AVCodecContext *avctx, AVBufferRef *frames_ " separate_references" : ""); /* Check if decoding is possible with the given parameters */ - if (avctx->coded_width < caps->minCodedExtent.width || - avctx->coded_height < caps->minCodedExtent.height || - avctx->coded_width > caps->maxCodedExtent.width || - avctx->coded_height > caps->maxCodedExtent.height) + if (avctx->width < caps->minCodedExtent.width || + avctx->height < caps->minCodedExtent.height || + avctx->width > caps->maxCodedExtent.width || + avctx->height > caps->maxCodedExtent.height) return AVERROR(EINVAL); if (!(avctx->hwaccel_flags & AV_HWACCEL_FLAG_IGNORE_LEVEL) && @@ -956,8 +955,6 @@ static int vulkan_decode_get_profile(AVCodecContext *avctx, AVBufferRef *frames_ *pix_fmt = best_format; *vk_fmt = best_vkfmt; - *width_align = caps->pictureAccessGranularity.width; - *height_align = caps->pictureAccessGranularity.height; *dpb_dedicate = dec->dedicated_dpb; return 0; @@ -966,7 +963,7 @@ static int vulkan_decode_get_profile(AVCodecContext *avctx, AVBufferRef *frames_ int ff_vk_frame_params(AVCodecContext *avctx, AVBufferRef *hw_frames_ctx) { VkFormat vkfmt; - int err, width_align, height_align, dedicated_dpb; + int err, dedicated_dpb; AVHWFramesContext *frames_ctx = (AVHWFramesContext*)hw_frames_ctx->data; AVVulkanFramesContext *hwfc = frames_ctx->hwctx; FFVulkanDecodeContext *dec = avctx->internal->hwaccel_priv_data; @@ -983,14 +980,13 @@ int ff_vk_frame_params(AVCodecContext *avctx, AVBufferRef *hw_frames_ctx) prof = &ctx->profile_data; err = vulkan_decode_get_profile(avctx, hw_frames_ctx, - &width_align, &height_align, &frames_ctx->sw_format, &vkfmt, &dedicated_dpb); if (err < 0) return err; - frames_ctx->width = FFALIGN(avctx->coded_width, width_align); - frames_ctx->height = FFALIGN(avctx->coded_height, height_align); + frames_ctx->width = avctx->width; + frames_ctx->height = avctx->height; frames_ctx->format = AV_PIX_FMT_VULKAN; hwfc->format[0] = vkfmt; From 364c03d9fe1b7ca1b54644f5477eb75563e11bda Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Sun, 28 May 2023 14:24:07 +0200 Subject: [PATCH 1322/2172] avfilter/silenceremove_template: improve ptp detector --- libavfilter/silenceremove_template.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libavfilter/silenceremove_template.c b/libavfilter/silenceremove_template.c index c1335adb95f..aaaba04f693 100644 --- a/libavfilter/silenceremove_template.c +++ b/libavfilter/silenceremove_template.c @@ -286,8 +286,8 @@ static ftype fn(compute_ptp)(ftype *peak, ftype sample, ftype wsample, peak[back] = sample; max = peak[front]; - min = (back == front) ? -sample : sample; - r = FABS(max - min); + min = sample; + r = FABS(min) + FABS(max - min); *ffront = front; *bback = back; From aa4acc111e6ea1117dfec230435fdb26ec7631d9 Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Sun, 28 May 2023 14:35:46 +0200 Subject: [PATCH 1323/2172] avfilter/af_silenceremove: use separate variable for size of cache --- libavfilter/af_silenceremove.c | 17 +++++++++++++++-- libavfilter/silenceremove_template.c | 8 +++++--- 2 files changed, 20 insertions(+), 5 deletions(-) diff --git a/libavfilter/af_silenceremove.c b/libavfilter/af_silenceremove.c index 6f152146ded..c7975a93654 100644 --- a/libavfilter/af_silenceremove.c +++ b/libavfilter/af_silenceremove.c @@ -94,6 +94,7 @@ typedef struct SilenceRemoveContext { int *stop_back; int64_t window_duration; + int cache_size; int start_window_pos; int start_window_size; @@ -224,10 +225,22 @@ static int config_output(AVFilterLink *outlink) AVFilterContext *ctx = outlink->src; SilenceRemoveContext *s = ctx->priv; + switch (s->detection) { + case D_AVG: + case D_RMS: + s->cache_size = 1; + break; + case D_MEDIAN: + case D_PEAK: + case D_PTP: + s->cache_size = s->window_duration; + break; + } + s->start_window = ff_get_audio_buffer(outlink, s->window_duration); s->stop_window = ff_get_audio_buffer(outlink, s->window_duration); - s->start_cache = av_calloc(outlink->ch_layout.nb_channels, s->window_duration * sizeof(*s->start_cache)); - s->stop_cache = av_calloc(outlink->ch_layout.nb_channels, s->window_duration * sizeof(*s->stop_cache)); + s->start_cache = av_calloc(outlink->ch_layout.nb_channels, s->cache_size * sizeof(*s->start_cache)); + s->stop_cache = av_calloc(outlink->ch_layout.nb_channels, s->cache_size * sizeof(*s->stop_cache)); if (!s->start_window || !s->stop_window || !s->start_cache || !s->stop_cache) return AVERROR(ENOMEM); diff --git a/libavfilter/silenceremove_template.c b/libavfilter/silenceremove_template.c index aaaba04f693..8536d5e723f 100644 --- a/libavfilter/silenceremove_template.c +++ b/libavfilter/silenceremove_template.c @@ -328,6 +328,7 @@ static void fn(filter_start)(AVFilterContext *ctx, ftype *start_cache = (ftype *)s->start_cache; const int start_silence = s->start_silence; int window_size = start_window_nb_samples; + const int cache_size = s->cache_size; int *front = s->start_front; int *back = s->start_back; @@ -352,7 +353,7 @@ static void fn(filter_start)(AVFilterContext *ctx, ftype start_ow = startw[start_wpos + ch]; ftype tstart; - tstart = fn(s->compute)(start_cache + ch * start_window_nb_samples, + tstart = fn(s->compute)(start_cache + ch * cache_size, start_sample, start_ow, window_size, @@ -423,8 +424,9 @@ static void fn(filter_stop)(AVFilterContext *ctx, const int stop_duration = s->stop_duration; ftype *stop_cache = (ftype *)s->stop_cache; const int stop_silence = s->stop_silence; - const int restart = s->restart; int window_size = stop_window_nb_samples; + const int cache_size = s->cache_size; + const int restart = s->restart; int *front = s->stop_front; int *back = s->stop_back; @@ -446,7 +448,7 @@ static void fn(filter_stop)(AVFilterContext *ctx, ftype stop_ow = stopw[stop_wpos + ch]; ftype tstop; - tstop = fn(s->compute)(stop_cache + ch * stop_window_nb_samples, + tstop = fn(s->compute)(stop_cache + ch * cache_size, stop_sample, stop_ow, window_size, From f02964aee1ed06ac4a67103904d5fae2862fa45e Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Sun, 28 May 2023 17:37:55 +0200 Subject: [PATCH 1324/2172] avfilter/af_silenceremove: add standard deviation detector Useful in cases audio samples DC offset is not ~0.0, where other detectors will fail to detect silence. --- doc/filters.texi | 2 ++ libavfilter/af_silenceremove.c | 9 +++++++++ libavfilter/silenceremove_template.c | 17 +++++++++++++++++ 3 files changed, 28 insertions(+) diff --git a/doc/filters.texi b/doc/filters.texi index 2333cfaf7a6..c47e88e5d47 100644 --- a/doc/filters.texi +++ b/doc/filters.texi @@ -6474,6 +6474,8 @@ Maximum of absolute values of samples in moving window. Median of absolute values of samples in moving window. @item ptp Absolute of max peak to min peak difference of samples in moving window. +@item dev +Standard deviation of values of samples in moving window. @end table Default value is @code{rms}. diff --git a/libavfilter/af_silenceremove.c b/libavfilter/af_silenceremove.c index c7975a93654..4cb662080bc 100644 --- a/libavfilter/af_silenceremove.c +++ b/libavfilter/af_silenceremove.c @@ -38,6 +38,7 @@ enum SilenceDetect { D_PEAK, D_MEDIAN, D_PTP, + D_DEV, D_NB }; @@ -146,6 +147,7 @@ static const AVOption silenceremove_options[] = { { "peak", "use max absolute values of samples", 0, AV_OPT_TYPE_CONST, {.i64=D_PEAK},0, 0, AF, "detection" }, { "median", "use median of absolute values of samples", 0, AV_OPT_TYPE_CONST, {.i64=D_MEDIAN},0, 0, AF, "detection" }, { "ptp", "use absolute of max peak to min peak difference", 0, AV_OPT_TYPE_CONST, {.i64=D_PTP}, 0, 0, AF, "detection" }, + { "dev", "use standard deviation from values of samples", 0, AV_OPT_TYPE_CONST, {.i64=D_DEV}, 0, 0, AF, "detection" }, { "window", "set duration of window for silence detection", OFFSET(window_duration_opt), AV_OPT_TYPE_DURATION, {.i64=20000}, 0, 100000000, AF }, { "timestamp", "set how every output frame timestamp is processed", OFFSET(timestamp_mode), AV_OPT_TYPE_INT, {.i64=TS_WRITE}, 0, TS_NB-1, AF, "timestamp" }, { "write", "full timestamps rewrite, keep only the start time", 0, AV_OPT_TYPE_CONST, {.i64=TS_WRITE}, 0, 0, AF, "timestamp" }, @@ -230,6 +232,9 @@ static int config_output(AVFilterLink *outlink) case D_RMS: s->cache_size = 1; break; + case D_DEV: + s->cache_size = 2; + break; case D_MEDIAN: case D_PEAK: case D_PTP: @@ -263,6 +268,10 @@ static int config_output(AVFilterLink *outlink) s->compute_flt = compute_avg_flt; s->compute_dbl = compute_avg_dbl; break; + case D_DEV: + s->compute_flt = compute_dev_flt; + s->compute_dbl = compute_dev_dbl; + break; case D_PTP: s->compute_flt = compute_ptp_flt; s->compute_dbl = compute_ptp_dbl; diff --git a/libavfilter/silenceremove_template.c b/libavfilter/silenceremove_template.c index 8536d5e723f..009ed52f89c 100644 --- a/libavfilter/silenceremove_template.c +++ b/libavfilter/silenceremove_template.c @@ -307,6 +307,23 @@ static ftype fn(compute_rms)(ftype *cache, ftype sample, ftype wsample, return SQRT(r / window_size); } +static ftype fn(compute_dev)(ftype *ss, ftype x, ftype px, + int n, int *unused, int *unused2) +{ + ftype r; + + ss[0] += x; + ss[0] -= px; + + ss[1] += x * x; + ss[1] -= px * px; + ss[1] = FMAX(ss[1], ZERO); + + r = FMAX(ss[1] - ss[0] * ss[0] / n, ZERO) / n; + + return SQRT(r); +} + static void fn(filter_start)(AVFilterContext *ctx, const ftype *src, ftype *dst, int *nb_out_samples, From 45fa85a77797630e361e8f8254560c4f56e0a5cb Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Mon, 29 May 2023 09:18:15 +0200 Subject: [PATCH 1325/2172] avfilter/silenceremove_template: refactor detectors using common peaks code --- libavfilter/silenceremove_template.c | 217 +++++++++------------------ 1 file changed, 72 insertions(+), 145 deletions(-) diff --git a/libavfilter/silenceremove_template.c b/libavfilter/silenceremove_template.c index 009ed52f89c..2f34fb5958b 100644 --- a/libavfilter/silenceremove_template.c +++ b/libavfilter/silenceremove_template.c @@ -105,73 +105,76 @@ static void fn(queue_sample)(AVFilterContext *ctx, *window_pos = 0; } -static ftype fn(compute_avg)(ftype *cache, ftype sample, ftype wsample, +static ftype fn(compute_avg)(ftype *cache, ftype x, ftype px, int window_size, int *unused, int *unused2) { ftype r; - cache[0] += FABS(sample); - cache[0] -= FABS(wsample); + cache[0] += FABS(x); + cache[0] -= FABS(px); cache[0] = r = FMAX(cache[0], ZERO); return r / window_size; } -static ftype fn(compute_median)(ftype *peak, ftype sample, ftype wsample, - int size, int *ffront, int *bback) +#define PEAKS(empty_value,op,sample, psample)\ + if (!empty && psample == ss[front]) { \ + ss[front] = empty_value; \ + if (back != front) { \ + front--; \ + if (front < 0) \ + front = n - 1; \ + } \ + empty = front == back; \ + } \ + \ + if (!empty && sample op ss[front]) { \ + while (1) { \ + ss[front] = empty_value; \ + if (back == front) { \ + empty = 1; \ + break; \ + } \ + front--; \ + if (front < 0) \ + front = n - 1; \ + } \ + } \ + \ + while (!empty && sample op ss[back]) { \ + ss[back] = empty_value; \ + if (back == front) { \ + empty = 1; \ + break; \ + } \ + back++; \ + if (back >= n) \ + back = 0; \ + } \ + \ + if (!empty) { \ + back--; \ + if (back < 0) \ + back = n - 1; \ + } + +static ftype fn(compute_median)(ftype *ss, ftype x, ftype px, + int n, int *ffront, int *bback) { - ftype r, abs_sample = FABS(sample); + ftype r, ax = FABS(x); int front = *ffront; int back = *bback; - int empty = front == back && peak[front] == -ONE; + int empty = front == back && ss[front] == -ONE; int idx; - if (!empty && FABS(wsample) == peak[front]) { - peak[front] = -ONE; - if (back != front) { - front--; - if (front < 0) - front = size - 1; - } - empty = front == back; - } - - if (!empty && abs_sample > peak[front]) { - while (1) { - peak[front] = -ONE; - if (back == front) { - empty = 1; - break; - } - front--; - if (front < 0) - front = size - 1; - } - } - - while (!empty && abs_sample > peak[back]) { - peak[back] = -ONE; - if (back == front) { - empty = 1; - break; - } - back++; - if (back >= size) - back = 0; - } - - if (!empty) { - back--; - if (back < 0) - back = size - 1; - } + PEAKS(-ONE, >, ax, FABS(px)) - peak[back] = abs_sample; - idx = (back <= front) ? back + (front - back + 1) / 2 : back + (size + front - back + 1) / 2; - if (idx >= size) - idx -= size; - av_assert2(idx >= 0 && idx < size); - r = peak[idx]; + ss[back] = ax; + idx = (back <= front) ? back + (front - back + 1) / 2 : back + (n + front - back + 1) / 2; + if (idx >= n) + idx -= n; + av_assert2(idx >= 0 && idx < n); + r = ss[idx]; *ffront = front; *bback = back; @@ -179,56 +182,18 @@ static ftype fn(compute_median)(ftype *peak, ftype sample, ftype wsample, return r; } -static ftype fn(compute_peak)(ftype *peak, ftype sample, ftype wsample, - int size, int *ffront, int *bback) +static ftype fn(compute_peak)(ftype *ss, ftype x, ftype px, + int n, int *ffront, int *bback) { - ftype r, abs_sample = FABS(sample); + ftype r, ax = FABS(x); int front = *ffront; int back = *bback; - int empty = front == back && peak[front] == ZERO; - - if (!empty && FABS(wsample) == peak[front]) { - peak[front] = ZERO; - if (back != front) { - front--; - if (front < 0) - front = size - 1; - } - empty = front == back; - } + int empty = front == back && ss[front] == ZERO; - if (!empty && abs_sample >= peak[front]) { - while (1) { - peak[front] = ZERO; - if (back == front) { - empty = 1; - break; - } - front--; - if (front < 0) - front = size - 1; - } - } + PEAKS(ZERO, >=, ax, FABS(px)) - while (!empty && abs_sample >= peak[back]) { - peak[back] = ZERO; - if (back == front) { - empty = 1; - break; - } - back++; - if (back >= size) - back = 0; - } - - if (!empty) { - back--; - if (back < 0) - back = size - 1; - } - - peak[back] = abs_sample; - r = peak[front]; + ss[back] = ax; + r = ss[front]; *ffront = front; *bback = back; @@ -236,57 +201,19 @@ static ftype fn(compute_peak)(ftype *peak, ftype sample, ftype wsample, return r; } -static ftype fn(compute_ptp)(ftype *peak, ftype sample, ftype wsample, - int size, int *ffront, int *bback) +static ftype fn(compute_ptp)(ftype *ss, ftype x, ftype px, + int n, int *ffront, int *bback) { int front = *ffront; int back = *bback; - int empty = front == back && peak[front] == TMIN; + int empty = front == back && ss[front] == TMIN; ftype r, max, min; - if (!empty && wsample == peak[front]) { - peak[front] = TMIN; - if (back != front) { - front--; - if (front < 0) - front = size - 1; - } - empty = front == back; - } - - if (!empty && sample >= peak[front]) { - while (1) { - peak[front] = TMIN; - if (back == front) { - empty = 1; - break; - } - front--; - if (front < 0) - front = size - 1; - } - } - - while (!empty && sample >= peak[back]) { - peak[back] = TMIN; - if (back == front) { - empty = 1; - break; - } - back++; - if (back >= size) - back = 0; - } - - if (!empty) { - back--; - if (back < 0) - back = size - 1; - } + PEAKS(TMIN, >=, x, px) - peak[back] = sample; - max = peak[front]; - min = sample; + ss[back] = x; + max = ss[front]; + min = x; r = FABS(min) + FABS(max - min); *ffront = front; @@ -295,13 +222,13 @@ static ftype fn(compute_ptp)(ftype *peak, ftype sample, ftype wsample, return r; } -static ftype fn(compute_rms)(ftype *cache, ftype sample, ftype wsample, +static ftype fn(compute_rms)(ftype *cache, ftype x, ftype px, int window_size, int *unused, int *unused2) { ftype r; - cache[0] += sample * sample; - cache[0] -= wsample * wsample; + cache[0] += x * x; + cache[0] -= px * px; cache[0] = r = FMAX(cache[0], ZERO); return SQRT(r / window_size); From 637afea88ed42498be4f60eff4eb8e2f00eeb89f Mon Sep 17 00:00:00 2001 From: Dawid Kozinski Date: Fri, 26 May 2023 12:30:33 +0200 Subject: [PATCH 1326/2172] avcodec: MPEG-5 EVC codec registration Added prerequisites that must be met before providing support for the MPEG-5 EVC codec - Added new entry to codec IDs list - Added new entry to the codec descriptor list - Bumped libavcodec minor version - Added profiles for EVC codec Signed-off-by: Dawid Kozinski Signed-off-by: James Almer --- doc/APIchanges | 3 +++ libavcodec/avcodec.h | 3 +++ libavcodec/codec_desc.c | 8 ++++++++ libavcodec/codec_id.h | 1 + libavcodec/profiles.c | 6 ++++++ libavcodec/profiles.h | 1 + libavcodec/version.h | 2 +- 7 files changed, 23 insertions(+), 1 deletion(-) diff --git a/doc/APIchanges b/doc/APIchanges index 0232d05b108..f040211f7d4 100644 --- a/doc/APIchanges +++ b/doc/APIchanges @@ -2,6 +2,9 @@ The last version increases of all libraries were on 2023-02-09 API changes, most recent first: +2023-05-29 - xxxxxxxxxx - lavc 60.16.100 - avcodec.h codec_id.h + Add AV_CODEC_ID_EVC, FF_PROFILE_EVC_BASELINE, and FF_PROFILE_EVC_MAIN. + 2023-05-29 - xxxxxxxxxx - lavu 58.12.100 - mathematics.h Add av_bessel_i0() diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h index 84e29a02dbc..d17bdc360dd 100644 --- a/libavcodec/avcodec.h +++ b/libavcodec/avcodec.h @@ -1715,6 +1715,9 @@ typedef struct AVCodecContext { #define FF_PROFILE_KLVA_SYNC 0 #define FF_PROFILE_KLVA_ASYNC 1 +#define FF_PROFILE_EVC_BASELINE 0 +#define FF_PROFILE_EVC_MAIN 1 + /** * level * - encoding: Set by user. diff --git a/libavcodec/codec_desc.c b/libavcodec/codec_desc.c index 49dddd1a496..310ed664158 100644 --- a/libavcodec/codec_desc.c +++ b/libavcodec/codec_desc.c @@ -1938,6 +1938,14 @@ static const AVCodecDescriptor codec_descriptors[] = { .long_name = NULL_IF_CONFIG_SMALL("PDV (PlayDate Video)"), .props = AV_CODEC_PROP_LOSSY, }, + { + .id = AV_CODEC_ID_EVC, + .type = AVMEDIA_TYPE_VIDEO, + .name = "evc", + .long_name = NULL_IF_CONFIG_SMALL("MPEG-5 EVC (Essential Video Coding)"), + .props = AV_CODEC_PROP_LOSSY | AV_CODEC_PROP_REORDER, + .profiles = NULL_IF_CONFIG_SMALL(ff_evc_profiles), + }, /* various PCM "codecs" */ { diff --git a/libavcodec/codec_id.h b/libavcodec/codec_id.h index 70800ec20b1..9f621afff01 100644 --- a/libavcodec/codec_id.h +++ b/libavcodec/codec_id.h @@ -321,6 +321,7 @@ enum AVCodecID { AV_CODEC_ID_MEDIA100, AV_CODEC_ID_VQC, AV_CODEC_ID_PDV, + AV_CODEC_ID_EVC, /* various PCM "codecs" */ AV_CODEC_ID_FIRST_AUDIO = 0x10000, ///< A dummy id pointing at the start of audio codecs diff --git a/libavcodec/profiles.c b/libavcodec/profiles.c index 545626337cb..c646a3f54df 100644 --- a/libavcodec/profiles.c +++ b/libavcodec/profiles.c @@ -194,4 +194,10 @@ const AVProfile ff_arib_caption_profiles[] = { { FF_PROFILE_UNKNOWN } }; +const AVProfile ff_evc_profiles[] = { + { FF_PROFILE_EVC_BASELINE, "Baseline" }, + { FF_PROFILE_EVC_MAIN, "Main" }, + { FF_PROFILE_UNKNOWN }, +}; + #endif /* !CONFIG_SMALL */ diff --git a/libavcodec/profiles.h b/libavcodec/profiles.h index 1d523992fc2..c0eacae5c16 100644 --- a/libavcodec/profiles.h +++ b/libavcodec/profiles.h @@ -74,5 +74,6 @@ extern const AVProfile ff_sbc_profiles[]; extern const AVProfile ff_prores_profiles[]; extern const AVProfile ff_mjpeg_profiles[]; extern const AVProfile ff_arib_caption_profiles[]; +extern const AVProfile ff_evc_profiles[]; #endif /* AVCODEC_PROFILES_H */ diff --git a/libavcodec/version.h b/libavcodec/version.h index 9b8c2675291..82a86fe9d98 100644 --- a/libavcodec/version.h +++ b/libavcodec/version.h @@ -29,7 +29,7 @@ #include "version_major.h" -#define LIBAVCODEC_VERSION_MINOR 15 +#define LIBAVCODEC_VERSION_MINOR 16 #define LIBAVCODEC_VERSION_MICRO 100 #define LIBAVCODEC_VERSION_INT AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \ From 098b3383696d2762ba465f6e2f632df37b130579 Mon Sep 17 00:00:00 2001 From: Niklas Haas Date: Mon, 29 May 2023 12:56:04 +0200 Subject: [PATCH 1327/2172] lavfi/vf_libplacebo: require v5.278 for importing Importing Vulkan device on older versions no longer works due to the lavu vulkan API changes (specifically, the switch to planar textures by default). Additionally, importing on versions that don't suppirt lock/unlock_queue is unsafe with the advent of the threaded vulkan hwaccel. As a plus, saves us some annoying #ifdef boilerplate. I will raise the minimum vf_libplacebo version globally on the next stable release of libplacebo, and remove all of these checks. --- libavfilter/vf_libplacebo.c | 20 +++++++++----------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/libavfilter/vf_libplacebo.c b/libavfilter/vf_libplacebo.c index 2b8dac09b06..0a849f86762 100644 --- a/libavfilter/vf_libplacebo.c +++ b/libavfilter/vf_libplacebo.c @@ -544,23 +544,15 @@ static int libplacebo_init(AVFilterContext *avctx) return err; } -#if PL_API_VER >= 201 -# if PL_API_VER >= 278 +#if PL_API_VER >= 278 static void lock_queue(void *priv, uint32_t qf, uint32_t qidx) -# else -static void lock_queue(void *priv, int qf, int qidx) -# endif { AVHWDeviceContext *avhwctx = priv; const AVVulkanDeviceContext *hwctx = avhwctx->hwctx; hwctx->lock_queue(avhwctx, qf, qidx); } -# if PL_API_VER >= 278 static void unlock_queue(void *priv, uint32_t qf, uint32_t qidx) -# else -static void unlock_queue(void *priv, int qf, int qidx) -# endif { AVHWDeviceContext *avhwctx = priv; const AVVulkanDeviceContext *hwctx = avhwctx->hwctx; @@ -576,6 +568,7 @@ static int init_vulkan(AVFilterContext *avctx, const AVVulkanDeviceContext *hwct size_t buf_len; if (hwctx) { +#if PL_API_VER >= 278 /* Import libavfilter vulkan context into libplacebo */ s->vulkan = pl_vulkan_import(s->log, pl_vulkan_import_params( .instance = hwctx->inst, @@ -585,11 +578,9 @@ static int init_vulkan(AVFilterContext *avctx, const AVVulkanDeviceContext *hwct .extensions = hwctx->enabled_dev_extensions, .num_extensions = hwctx->nb_enabled_dev_extensions, .features = &hwctx->device_features, -#if PL_API_VER >= 201 .lock_queue = lock_queue, .unlock_queue = unlock_queue, .queue_ctx = avctx->hw_device_ctx->data, -#endif .queue_graphics = { .index = hwctx->queue_family_index, .count = hwctx->nb_graphics_queues, @@ -605,6 +596,13 @@ static int init_vulkan(AVFilterContext *avctx, const AVVulkanDeviceContext *hwct /* This is the highest version created by hwcontext_vulkan.c */ .max_api_version = VK_API_VERSION_1_3, )); +#else + av_log(s, AV_LOG_ERROR, "libplacebo version %s too old to import " + "Vulkan device, remove it or upgrade libplacebo to >= 5.278\n", + PL_VERSION); + err = AVERROR_EXTERNAL; + goto fail; +#endif } else { s->vulkan = pl_vulkan_create(s->log, pl_vulkan_params( .queue_count = 0, /* enable all queues for parallelization */ From c4cdd794355eaf7c4e63f288fef5bac0216f0f2c Mon Sep 17 00:00:00 2001 From: Niklas Haas Date: Wed, 24 May 2023 15:47:44 +0200 Subject: [PATCH 1328/2172] lavfi/vf_libplacebo: add corner_rounding option For what use it may be. --- doc/filters.texi | 6 ++++++ libavfilter/vf_libplacebo.c | 5 +++++ 2 files changed, 11 insertions(+) diff --git a/doc/filters.texi b/doc/filters.texi index c47e88e5d47..a46357bfd82 100644 --- a/doc/filters.texi +++ b/doc/filters.texi @@ -16164,6 +16164,12 @@ example as a result of @option{normalize_sar}. For the general syntax of this option, check the @ref{color syntax,,"Color" section in the ffmpeg-utils manual,ffmpeg-utils}. Defaults to @code{black}. +@item corner_rounding +Render frames with rounded corners. The value, given as a float ranging from +@code{0.0} to @code{1.0}, indicates the relative degree of rounding, from fully +square to fully circular. In other words, it gives the radius divided by half +the smaller side length. Defaults to @code{0.0}. + @item colorspace @item color_primaries @item color_trc diff --git a/libavfilter/vf_libplacebo.c b/libavfilter/vf_libplacebo.c index 0a849f86762..b546f02dc61 100644 --- a/libavfilter/vf_libplacebo.c +++ b/libavfilter/vf_libplacebo.c @@ -148,6 +148,7 @@ typedef struct LibplaceboContext { AVExpr *pos_x_pexpr, *pos_y_pexpr, *pos_w_pexpr, *pos_h_pexpr; AVRational target_sar; float pad_crop_ratio; + float corner_rounding; int force_original_aspect_ratio; int force_divisible_by; int normalize_sar; @@ -440,6 +441,9 @@ static int update_settings(AVFilterContext *ctx) (float) color_rgba[1] / UINT8_MAX, (float) color_rgba[2] / UINT8_MAX, }, +#if PL_API_VER >= 277 + .corner_rounding = s->corner_rounding, +#endif .deband_params = s->deband ? &s->deband_params : NULL, .sigmoid_params = s->sigmoid ? &pl_sigmoid_default_params : NULL, @@ -1154,6 +1158,7 @@ static const AVOption libplacebo_options[] = { { "normalize_sar", "force SAR normalization to 1:1 by adjusting pos_x/y/w/h", OFFSET(normalize_sar), AV_OPT_TYPE_BOOL, {.i64 = 0}, 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 }, { "fillcolor", "Background fill color", OFFSET(fillcolor), AV_OPT_TYPE_STRING, {.str = "black"}, .flags = DYNAMIC }, + { "corner_rounding", "Corner rounding radius", OFFSET(corner_rounding), AV_OPT_TYPE_FLOAT, {.dbl = 0.0}, 0.0, 1.0, .flags = 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"}, From ee664f41dbd94d896c5b45fa0d916a0b82f22b34 Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Mon, 29 May 2023 14:39:33 +0200 Subject: [PATCH 1329/2172] avfilter/avf_showwaves: force output to fixed framerate if rate is set --- libavfilter/avf_showwaves.c | 161 ++++++++++++++++++++++-------------- 1 file changed, 100 insertions(+), 61 deletions(-) diff --git a/libavfilter/avf_showwaves.c b/libavfilter/avf_showwaves.c index 3db192a835b..c0b9c8c88e4 100644 --- a/libavfilter/avf_showwaves.c +++ b/libavfilter/avf_showwaves.c @@ -77,10 +77,12 @@ typedef struct ShowWavesContext { char *colors; int buf_idx; int16_t *buf_idy; /* y coordinate of previous sample for each channel */ + int16_t *history; + int history_nb_samples; + int history_index; AVFrame *outpicref; - int n; + AVRational n, q, c; int pixstep; - int sample_count_mod; int mode; ///< ShowWavesMode int scale; ///< ShowWavesScale int draw_mode; ///< ShowWavesDrawMode @@ -111,7 +113,7 @@ static const AVOption showwaves_options[] = { { "line", "draw a line for each sample", 0, AV_OPT_TYPE_CONST, {.i64=MODE_LINE}, .flags=FLAGS, .unit="mode"}, { "p2p", "draw a line between samples", 0, AV_OPT_TYPE_CONST, {.i64=MODE_P2P}, .flags=FLAGS, .unit="mode"}, { "cline", "draw a centered line for each sample", 0, AV_OPT_TYPE_CONST, {.i64=MODE_CENTERED_LINE}, .flags=FLAGS, .unit="mode"}, - { "n", "set how many samples to show in the same point", OFFSET(n), AV_OPT_TYPE_INT, {.i64 = 0}, 0, INT_MAX, FLAGS }, + { "n", "set how many samples to show in the same point", OFFSET(n), AV_OPT_TYPE_RATIONAL, {.i64 = 0}, 0, INT_MAX, FLAGS }, { "rate", "set video rate", OFFSET(rate), AV_OPT_TYPE_VIDEO_RATE, {.str = "25"}, 0, INT_MAX, FLAGS }, { "r", "set video rate", OFFSET(rate), AV_OPT_TYPE_VIDEO_RATE, {.str = "25"}, 0, INT_MAX, FLAGS }, { "split_channels", "draw channels separately", OFFSET(split_channels), AV_OPT_TYPE_BOOL, {.i64 = 0}, 0, 1, FLAGS }, @@ -135,6 +137,7 @@ static av_cold void uninit(AVFilterContext *ctx) av_frame_free(&showwaves->outpicref); av_freep(&showwaves->buf_idy); + av_freep(&showwaves->history); av_freep(&showwaves->fg); if (showwaves->single_pic) { @@ -422,29 +425,42 @@ static int config_output(AVFilterLink *outlink) uint8_t x; int ch; - if (showwaves->single_pic) - showwaves->n = 1; + showwaves->q = av_make_q(0, 1); + showwaves->c = av_make_q(0, 1); - if (!showwaves->n) - showwaves->n = FFMAX(1, av_rescale_q(inlink->sample_rate, av_make_q(1, showwaves->w), showwaves->rate)); + if (showwaves->single_pic) { + showwaves->n = av_make_q(1, 1); + outlink->frame_rate = av_make_q(1, 1); + } else { + if (!showwaves->n.num || !showwaves->n.den) { + showwaves->n = av_mul_q(av_make_q(inlink->sample_rate, + showwaves->w), av_inv_q(showwaves->rate)); + outlink->frame_rate = showwaves->rate; + } else { + outlink->frame_rate = av_div_q(av_make_q(inlink->sample_rate, showwaves->w), showwaves->n); + } + } showwaves->buf_idx = 0; if (!FF_ALLOCZ_TYPED_ARRAY(showwaves->buf_idy, nb_channels)) { av_log(ctx, AV_LOG_ERROR, "Could not allocate showwaves buffer\n"); return AVERROR(ENOMEM); } + + showwaves->history_nb_samples = av_rescale(showwaves->w * nb_channels * 2, + showwaves->n.num, showwaves->n.den); + showwaves->history = av_calloc(showwaves->history_nb_samples, + sizeof(*showwaves->history)); + if (!showwaves->history) + return AVERROR(ENOMEM); + + outlink->time_base = av_inv_q(outlink->frame_rate); outlink->w = showwaves->w; outlink->h = showwaves->h; outlink->sample_aspect_ratio = (AVRational){1,1}; - if (showwaves->single_pic) - outlink->frame_rate = av_make_q(1, 1); - else - outlink->frame_rate = av_div_q((AVRational){inlink->sample_rate,showwaves->n}, - (AVRational){showwaves->w,1}); - - av_log(ctx, AV_LOG_VERBOSE, "s:%dx%d r:%f n:%d\n", - showwaves->w, showwaves->h, av_q2d(outlink->frame_rate), showwaves->n); + av_log(ctx, AV_LOG_VERBOSE, "s:%dx%d r:%f n:%f\n", + showwaves->w, showwaves->h, av_q2d(outlink->frame_rate), av_q2d(showwaves->n)); switch (outlink->format) { case AV_PIX_FMT_GRAY8: @@ -524,7 +540,7 @@ static int config_output(AVFilterLink *outlink) if (showwaves->draw_mode == DRAW_SCALE) { /* multiplication factor, pre-computed to avoid in-loop divisions */ - x = 255 / ((showwaves->split_channels ? 1 : nb_channels) * showwaves->n); + x = (showwaves->n.den * 255) / ((showwaves->split_channels ? 1 : nb_channels) * showwaves->n.num); } else { x = 255; } @@ -551,18 +567,23 @@ static int config_output(AVFilterLink *outlink) return 0; } -inline static int push_frame(AVFilterLink *outlink) +inline static int push_frame(AVFilterLink *outlink, int i, int64_t pts) { AVFilterContext *ctx = outlink->src; AVFilterLink *inlink = ctx->inputs[0]; ShowWavesContext *showwaves = outlink->src->priv; int nb_channels = inlink->ch_layout.nb_channels; - int ret, i; + int ret; + + showwaves->outpicref->duration = 1; + showwaves->outpicref->pts = av_rescale_q(pts + i, + inlink->time_base, + outlink->time_base); ret = ff_filter_frame(outlink, showwaves->outpicref); showwaves->outpicref = NULL; showwaves->buf_idx = 0; - for (i = 0; i < nb_channels; i++) + for (int i = 0; i < nb_channels; i++) showwaves->buf_idy[i] = 0; return ret; } @@ -633,7 +654,7 @@ static int push_single_pic(AVFilterLink *outlink) } } - return push_frame(outlink); + return push_frame(outlink, 0, 0); } @@ -645,31 +666,23 @@ static int request_frame(AVFilterLink *outlink) ret = ff_request_frame(inlink); if (ret == AVERROR_EOF && showwaves->outpicref) { - if (showwaves->single_pic) - push_single_pic(outlink); - else - push_frame(outlink); + push_single_pic(outlink); } return ret; } -static int alloc_out_frame(ShowWavesContext *showwaves, const int16_t *p, - const AVFilterLink *inlink, AVFilterLink *outlink, - const AVFrame *in) +static int alloc_out_frame(ShowWavesContext *showwaves, + AVFilterLink *outlink) { if (!showwaves->outpicref) { - int j; AVFrame *out = showwaves->outpicref = ff_get_video_buffer(outlink, outlink->w, outlink->h); if (!out) return AVERROR(ENOMEM); out->width = outlink->w; out->height = outlink->h; - out->pts = in->pts + av_rescale_q((p - (int16_t *)in->data[0]) / inlink->ch_layout.nb_channels, - av_make_q(1, inlink->sample_rate), - outlink->time_base); - for (j = 0; j < outlink->h; j++) + for (int j = 0; j < outlink->h; j++) memset(out->data[0] + j*out->linesize[0], 0, outlink->w * showwaves->pixstep); } return 0; @@ -696,45 +709,67 @@ static int showwaves_filter_frame(AVFilterLink *inlink, AVFrame *insamples) ShowWavesContext *showwaves = ctx->priv; const int nb_samples = insamples->nb_samples; AVFrame *outpicref = showwaves->outpicref; - int16_t *p = (int16_t *)insamples->data[0]; - int nb_channels = inlink->ch_layout.nb_channels; - int i, j, ret = 0; + const int16_t *p = (const int16_t *)insamples->data[0]; + int16_t *history = showwaves->history; + const int nb_channels = inlink->ch_layout.nb_channels; + int i, j, ret = 0, linesize; const int pixstep = showwaves->pixstep; - const int n = showwaves->n; const int ch_height = showwaves->split_channels ? outlink->h / nb_channels : outlink->h; + const int history_nb_samples = showwaves->history_nb_samples; + const int split_channels = showwaves->split_channels; + const AVRational i_n = av_inv_q(showwaves->n); + const AVRational u_q = av_make_q(1, 1); + const AVRational z_q = av_make_q(0, 1); + int16_t *buf_idy = showwaves->buf_idy; + int idx = showwaves->history_index; + int buf_idx = showwaves->buf_idx; + const uint8_t *fg = showwaves->fg; + const int w = showwaves->w; + uint8_t *dst; + + for (int n = 0; n < nb_samples * nb_channels; n++) { + history[idx++] = p[n]; + if (idx >= history_nb_samples) + idx = 0; + } + showwaves->history_index = idx; - /* draw data in the buffer */ - for (i = 0; i < nb_samples; i++) { - - ret = alloc_out_frame(showwaves, p, inlink, outlink, insamples); - if (ret < 0) - goto end; - outpicref = showwaves->outpicref; + ret = alloc_out_frame(showwaves, outlink); + if (ret < 0) + goto end; + outpicref = showwaves->outpicref; + linesize = outpicref->linesize[0]; + /* draw data in the buffer */ + dst = outpicref->data[0]; + for (i = 0; i < history_nb_samples; i++) { for (j = 0; j < nb_channels; j++) { - uint8_t *buf = outpicref->data[0] + showwaves->buf_idx * pixstep; - const int linesize = outpicref->linesize[0]; + uint8_t *buf = dst + buf_idx * pixstep; int h; - if (showwaves->split_channels) + if (split_channels) buf += j*ch_height*linesize; - h = showwaves->get_h(*p++, ch_height); + h = showwaves->get_h(history[idx++], ch_height); + if (idx >= history_nb_samples) + idx = 0; showwaves->draw_sample(buf, ch_height, linesize, - &showwaves->buf_idy[j], &showwaves->fg[j * 4], h); + &buf_idy[j], &fg[j * 4], h); } - showwaves->sample_count_mod++; - if (showwaves->sample_count_mod == n) { - showwaves->sample_count_mod = 0; - showwaves->buf_idx++; + showwaves->c = av_add_q(showwaves->c, i_n); + if (av_cmp_q(showwaves->c, u_q) >= 0) { + showwaves->c = z_q; + buf_idx++; } - if (showwaves->buf_idx == showwaves->w || - (ff_outlink_get_status(inlink) && i == nb_samples - 1)) - if ((ret = push_frame(outlink)) < 0) - break; - outpicref = showwaves->outpicref; + if (buf_idx == w) + break; } + showwaves->buf_idx = buf_idx; + + if ((ret = push_frame(outlink, history_nb_samples - i - 1, insamples->pts)) < 0) + goto end; + outpicref = showwaves->outpicref; end: av_frame_free(&insamples); return ret; @@ -745,17 +780,22 @@ static int activate(AVFilterContext *ctx) AVFilterLink *inlink = ctx->inputs[0]; AVFilterLink *outlink = ctx->outputs[0]; ShowWavesContext *showwaves = ctx->priv; + AVRational q; AVFrame *in; - const int nb_samples = showwaves->n * outlink->w; + int nb_samples; int ret; FF_FILTER_FORWARD_STATUS_BACK(outlink, inlink); + q = av_add_q(showwaves->q, av_mul_q(av_make_q(outlink->w, 1), showwaves->n)); + nb_samples = (q.num + (q.den / 2)) / q.den; ret = ff_inlink_consume_samples(inlink, nb_samples, nb_samples, &in); if (ret < 0) return ret; - if (ret > 0) + if (ret > 0) { + showwaves->q = av_sub_q(q, av_make_q(nb_samples, 1)); return showwaves_filter_frame(inlink, in); + } FF_FILTER_FORWARD_STATUS(inlink, outlink); FF_FILTER_FORWARD_WANTED(outlink, inlink); @@ -838,13 +878,12 @@ static int showwavespic_filter_frame(AVFilterLink *inlink, AVFrame *insamples) AVFilterContext *ctx = inlink->dst; AVFilterLink *outlink = ctx->outputs[0]; ShowWavesContext *showwaves = ctx->priv; - int16_t *p = (int16_t *)insamples->data[0]; int ret = 0; if (showwaves->single_pic) { struct frame_node *f; - ret = alloc_out_frame(showwaves, p, inlink, outlink, insamples); + ret = alloc_out_frame(showwaves, outlink); if (ret < 0) goto end; From 9f9534f5b643f7349396eb33599c4895d1faefa8 Mon Sep 17 00:00:00 2001 From: Lynne Date: Mon, 29 May 2023 23:16:33 +0200 Subject: [PATCH 1330/2172] vulkan_decode: fix typo when setting AV1 capabilities All pNext chained structs in Vulkan are defined as void *, so it doesn't help catch this. --- libavcodec/vulkan_decode.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavcodec/vulkan_decode.c b/libavcodec/vulkan_decode.c index f79ca7f229d..889c67a15fa 100644 --- a/libavcodec/vulkan_decode.c +++ b/libavcodec/vulkan_decode.c @@ -671,7 +671,7 @@ static VkResult vulkan_setup_profile(AVCodecContext *avctx, h265_profile->sType = VK_STRUCTURE_TYPE_VIDEO_DECODE_H265_PROFILE_INFO_KHR; h265_profile->stdProfileIdc = cur_profile; } else if (avctx->codec_id == AV_CODEC_ID_AV1) { - dec_caps->pNext = &av1_caps; + dec_caps->pNext = av1_caps; usage->pNext = av1_profile; av1_profile->sType = VK_STRUCTURE_TYPE_VIDEO_DECODE_AV1_PROFILE_INFO_MESA; av1_profile->stdProfileIdc = cur_profile; From 51a1124a684ae8b9c9f56a2b958ae09847964525 Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Mon, 29 May 2023 23:30:56 +0200 Subject: [PATCH 1331/2172] avfilter/avf_showspectrum: do not use ff_outlink_get_status() on inlink --- libavfilter/avf_showspectrum.c | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/libavfilter/avf_showspectrum.c b/libavfilter/avf_showspectrum.c index 6c3d0e8c2ba..23269dbb4cc 100644 --- a/libavfilter/avf_showspectrum.c +++ b/libavfilter/avf_showspectrum.c @@ -109,6 +109,7 @@ typedef struct ShowSpectrumContext { float dmin, dmax; uint64_t samples; int (*plot_channel)(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs); + int eof; float opacity_factor; @@ -1543,8 +1544,7 @@ static int plot_spectrum_column(AVFilterLink *inlink, AVFrame *insamples) if (!s->single_pic && (s->sliding != FULLFRAME || s->xpos == 0)) { if (s->old_pts < outpicref->pts || s->sliding == FULLFRAME || - (ff_outlink_get_status(inlink) == AVERROR_EOF && - ff_inlink_queued_samples(inlink) <= s->hop_size)) { + (s->eof && ff_inlink_queued_samples(inlink) <= s->hop_size)) { AVFrame *clone; if (s->legend) { @@ -1600,7 +1600,7 @@ static int activate(AVFilterContext *ctx) FF_FILTER_FORWARD_STATUS_BACK(outlink, inlink); - if (s->outpicref) { + if (s->outpicref && ff_inlink_queued_samples(inlink) > 0) { AVFrame *fin; ret = ff_inlink_consume_samples(inlink, s->hop_size, s->hop_size, &fin); @@ -1627,8 +1627,7 @@ static int activate(AVFilterContext *ctx) } } - if (ff_outlink_get_status(inlink) == AVERROR_EOF && - s->sliding == FULLFRAME && + if (s->eof && s->sliding == FULLFRAME && s->xpos > 0 && s->outpicref) { if (s->orientation == VERTICAL) { @@ -1656,11 +1655,15 @@ static int activate(AVFilterContext *ctx) return 0; } - if (ff_inlink_acknowledge_status(inlink, &status, &pts)) { - if (status == AVERROR_EOF) { - ff_outlink_set_status(outlink, status, s->pts); - return 0; - } + if (!s->eof && ff_inlink_acknowledge_status(inlink, &status, &pts)) { + s->eof = status == AVERROR_EOF; + ff_filter_set_ready(ctx, 100); + return 0; + } + + if (s->eof) { + ff_outlink_set_status(outlink, AVERROR_EOF, s->pts); + return 0; } if (ff_inlink_queued_samples(inlink) >= s->hop_size) { From ac6a6d1abf4e7d7f4b36eceaa47a37eb933bd38f Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Tue, 30 May 2023 00:43:08 +0200 Subject: [PATCH 1332/2172] avfilter/af_join: do not use ff_outlink_get_status() on inlink --- libavfilter/af_join.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/libavfilter/af_join.c b/libavfilter/af_join.c index af924b7ec1f..5dbf9d8d22f 100644 --- a/libavfilter/af_join.c +++ b/libavfilter/af_join.c @@ -52,6 +52,7 @@ typedef struct JoinContext { AVChannelLayout ch_layout; int64_t eof_pts; + int eof; ChannelMap *channels; @@ -556,10 +557,11 @@ FF_ENABLE_DEPRECATION_WARNINGS return ret; eof: for (i = 0; i < ctx->nb_inputs; i++) { - if (ff_outlink_get_status(ctx->inputs[i]) && + if (s->eof && ff_inlink_queued_samples(ctx->inputs[i]) <= 0 && !s->input_frames[i]) { ff_outlink_set_status(outlink, AVERROR_EOF, s->eof_pts); + break; } } @@ -580,11 +582,10 @@ static int activate(AVFilterContext *ctx) if (ret < 0) { return ret; } else if (ret == 0 && ff_inlink_acknowledge_status(ctx->inputs[0], &status, &pts)) { - ff_outlink_set_status(ctx->outputs[0], status, s->eof_pts); - return 0; + s->eof |= status == AVERROR_EOF; } - if (!s->input_frames[0] && ff_outlink_frame_wanted(ctx->outputs[0])) { + if (!s->eof && !s->input_frames[0] && ff_outlink_frame_wanted(ctx->outputs[0])) { ff_inlink_request_frame(ctx->inputs[0]); return 0; } @@ -600,11 +601,10 @@ static int activate(AVFilterContext *ctx) if (ret < 0) { return ret; } else if (ff_inlink_acknowledge_status(ctx->inputs[i], &status, &pts)) { - ff_outlink_set_status(ctx->outputs[0], status, pts); - return 0; + s->eof |= status == AVERROR_EOF; } - if (!s->input_frames[i]) { + if (!s->eof && !s->input_frames[i]) { ff_inlink_request_frame(ctx->inputs[i]); return 0; } From 12acbcb7a28fc96760b3387c3360fc867434b76c Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Tue, 30 May 2023 00:52:36 +0200 Subject: [PATCH 1333/2172] avfilter/f_graphmonitor: always output last frame on EOF --- libavfilter/f_graphmonitor.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavfilter/f_graphmonitor.c b/libavfilter/f_graphmonitor.c index a1e467bc8bd..3a2760ed8c0 100644 --- a/libavfilter/f_graphmonitor.c +++ b/libavfilter/f_graphmonitor.c @@ -516,7 +516,7 @@ static int activate(AVFilterContext *ctx) return 0; } - if (s->pts < s->next_pts && ff_outlink_frame_wanted(outlink)) + if (s->eof || (s->pts < s->next_pts && ff_outlink_frame_wanted(outlink))) return create_frame(ctx, s->pts); if (!s->eof && ff_inlink_acknowledge_status(inlink, &status, &pts)) { From 492f64de0820238b9978827283fa4abbad31f297 Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Tue, 30 May 2023 01:14:24 +0200 Subject: [PATCH 1334/2172] avfilter/vf_framepack: remove not needed calls and add newline to log --- libavfilter/vf_framepack.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/libavfilter/vf_framepack.c b/libavfilter/vf_framepack.c index 6ea88df8b28..6fb7688c0b5 100644 --- a/libavfilter/vf_framepack.c +++ b/libavfilter/vf_framepack.c @@ -142,7 +142,7 @@ static int config_output(AVFilterLink *outlink) height *= 2; break; default: - av_log(ctx, AV_LOG_ERROR, "Unknown packing mode."); + av_log(ctx, AV_LOG_ERROR, "Unknown packing mode.\n"); return AVERROR_INVALIDDATA; } @@ -405,14 +405,12 @@ static int activate(AVFilterContext *ctx) FF_FILTER_FORWARD_STATUS(ctx->inputs[1], outlink); if (ff_outlink_frame_wanted(ctx->outputs[0]) && - !ff_outlink_get_status(ctx->inputs[0]) && !s->input_views[0]) { ff_inlink_request_frame(ctx->inputs[0]); return 0; } if (ff_outlink_frame_wanted(ctx->outputs[0]) && - !ff_outlink_get_status(ctx->inputs[1]) && !s->input_views[1]) { ff_inlink_request_frame(ctx->inputs[1]); return 0; From 4ab1184fae88bd47b9d195ac8224853c6f4e94cf Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Tue, 30 May 2023 02:11:05 +0200 Subject: [PATCH 1335/2172] avfilter/af_headphone: do not call ff_outlink_get_status() on inlink --- libavfilter/af_headphone.c | 31 ++++++++++++++++++++----------- 1 file changed, 20 insertions(+), 11 deletions(-) diff --git a/libavfilter/af_headphone.c b/libavfilter/af_headphone.c index 005e151e2c2..03938c16ad3 100644 --- a/libavfilter/af_headphone.c +++ b/libavfilter/af_headphone.c @@ -319,6 +319,16 @@ static int check_ir(AVFilterLink *inlink, int input_number) s->hrir_in[input_number].ir_len = ir_len; s->ir_len = FFMAX(ir_len, s->ir_len); + if (ff_inlink_check_available_samples(inlink, ir_len + 1) == 1) { + s->hrir_in[input_number].eof = 1; + return 1; + } + + if (!s->hrir_in[input_number].eof) { + ff_inlink_request_frame(inlink); + return 0; + } + return 0; } @@ -534,7 +544,7 @@ static int activate(AVFilterContext *ctx) AVFrame *in = NULL; int i, ret; - FF_FILTER_FORWARD_STATUS_BACK_ALL(ctx->outputs[0], ctx); + FF_FILTER_FORWARD_STATUS_BACK_ALL(outlink, ctx); if (!s->eof_hrirs) { int eof = 1; for (i = 0; i < s->nb_hrir_inputs; i++) { @@ -543,24 +553,23 @@ static int activate(AVFilterContext *ctx) if (s->hrir_in[i].eof) continue; - if ((ret = check_ir(input, i)) < 0) + if ((ret = check_ir(input, i)) <= 0) return ret; - if (ff_outlink_get_status(input) == AVERROR_EOF) { + if (s->hrir_in[i].eof) { if (!ff_inlink_queued_samples(input)) { av_log(ctx, AV_LOG_ERROR, "No samples provided for " "HRIR stream %d.\n", i); return AVERROR_INVALIDDATA; } - s->hrir_in[i].eof = 1; } else { - if (ff_outlink_frame_wanted(ctx->outputs[0])) - ff_inlink_request_frame(input); eof = 0; } } - if (!eof) + if (!eof) { + ff_filter_set_ready(ctx, 100); return 0; + } s->eof_hrirs = 1; ret = convert_coeffs(ctx, inlink); @@ -569,7 +578,7 @@ static int activate(AVFilterContext *ctx) } else if (!s->have_hrirs) return AVERROR_EOF; - if ((ret = ff_inlink_consume_samples(ctx->inputs[0], s->size, s->size, &in)) > 0) { + if ((ret = ff_inlink_consume_samples(inlink, s->size, s->size, &in)) > 0) { ret = headphone_frame(s, in, outlink); if (ret < 0) return ret; @@ -578,9 +587,9 @@ static int activate(AVFilterContext *ctx) if (ret < 0) return ret; - FF_FILTER_FORWARD_STATUS(ctx->inputs[0], ctx->outputs[0]); - if (ff_outlink_frame_wanted(ctx->outputs[0])) - ff_inlink_request_frame(ctx->inputs[0]); + FF_FILTER_FORWARD_STATUS(inlink, outlink); + if (ff_outlink_frame_wanted(outlink)) + ff_inlink_request_frame(inlink); return 0; } From 447bdddeacf5111e1e47c91c9fdf9ebef29c1b70 Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Tue, 30 May 2023 14:06:40 +0200 Subject: [PATCH 1336/2172] avfilter/af_afir: do not use ff_outlink_get_status() on inlinks --- libavfilter/af_afir.c | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/libavfilter/af_afir.c b/libavfilter/af_afir.c index e2cb14aba5e..502e544687b 100644 --- a/libavfilter/af_afir.c +++ b/libavfilter/af_afir.c @@ -445,7 +445,7 @@ static int convert_coeffs(AVFilterContext *ctx, int selir) return 0; } -static int check_ir(AVFilterLink *link) +static int check_ir(AVFilterLink *link, int selir) { AVFilterContext *ctx = link->dst; AudioFIRContext *s = ctx->priv; @@ -458,6 +458,9 @@ static int check_ir(AVFilterLink *link) return AVERROR(EINVAL); } + if (ff_inlink_check_available_samples(link, nb_taps + 1) == 1) + s->eof_coeffs[selir] = 1; + return 0; } @@ -480,13 +483,10 @@ static int activate(AVFilterContext *ctx) continue; if (!s->eof_coeffs[selir]) { - ret = check_ir(ctx->inputs[1 + selir]); + ret = check_ir(ctx->inputs[1 + selir], selir); if (ret < 0) return ret; - if (ff_outlink_get_status(ctx->inputs[1 + selir]) == AVERROR_EOF) - s->eof_coeffs[selir] = 1; - if (!s->eof_coeffs[selir]) { if (ff_outlink_frame_wanted(ctx->outputs[0])) ff_inlink_request_frame(ctx->inputs[1 + selir]); @@ -543,15 +543,13 @@ static int activate(AVFilterContext *ctx) } } - if (ff_outlink_frame_wanted(ctx->outputs[0]) && - !ff_outlink_get_status(ctx->inputs[0])) { + if (ff_outlink_frame_wanted(ctx->outputs[0])) { ff_inlink_request_frame(ctx->inputs[0]); return 0; } if (s->response && - ff_outlink_frame_wanted(ctx->outputs[1]) && - !ff_outlink_get_status(ctx->inputs[0])) { + ff_outlink_frame_wanted(ctx->outputs[1])) { ff_inlink_request_frame(ctx->inputs[0]); return 0; } From 81f658b99d7bf3979cb0e89e2017ebbde887c960 Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Tue, 30 May 2023 10:44:02 +0200 Subject: [PATCH 1337/2172] avfilter/f_ebur128: set output frame duration Also produce output video timestamps that are consistent with 10 frames per second. --- libavfilter/f_ebur128.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/libavfilter/f_ebur128.c b/libavfilter/f_ebur128.c index dfa62f0a36c..49f68c0e848 100644 --- a/libavfilter/f_ebur128.c +++ b/libavfilter/f_ebur128.c @@ -295,7 +295,6 @@ static int config_video_output(AVFilterLink *outlink) int i, x, y; uint8_t *p; AVFilterContext *ctx = outlink->src; - AVFilterLink *inlink = ctx->inputs[0]; EBUR128Context *ebur128 = ctx->priv; AVFrame *outpicref; @@ -308,8 +307,8 @@ static int config_video_output(AVFilterLink *outlink) outlink->w = ebur128->w; outlink->h = ebur128->h; outlink->sample_aspect_ratio = (AVRational){1,1}; - outlink->time_base = inlink->time_base; outlink->frame_rate = av_make_q(10, 1); + outlink->time_base = av_inv_q(outlink->frame_rate); #define PAD 8 @@ -430,7 +429,7 @@ static int config_audio_input(AVFilterLink *inlink) * can be more complex to integrate in the one-sample loop of * filter_frame()). */ if (ebur128->metadata || (ebur128->peak_mode & PEAK_MODE_TRUE_PEAKS)) - ebur128->nb_samples = inlink->sample_rate / 10; + ebur128->nb_samples = FFMAX(inlink->sample_rate / 10, 1); return 0; } @@ -735,7 +734,7 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *insamples) AVFilterLink *outlink = ctx->outputs[0]; const int64_t pts = insamples->pts + av_rescale_q(idx_insample, (AVRational){ 1, inlink->sample_rate }, - outlink->time_base); + ctx->outputs[ebur128->do_video]->time_base); ebur128->sample_count = 0; @@ -887,7 +886,8 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *insamples) } /* set pts and push frame */ - pic->pts = pts; + pic->pts = av_rescale_q(pts, inlink->time_base, outlink->time_base); + pic->duration = 1; clone = av_frame_clone(pic); if (!clone) return AVERROR(ENOMEM); From 06e8eedeba3882480b80a9797f6d0d86d72aca12 Mon Sep 17 00:00:00 2001 From: Sami Boukortt Date: Tue, 30 May 2023 12:29:06 +0200 Subject: [PATCH 1338/2172] avfilter/vf_colorspace: fix message for missing/incorrect colorspace Signed-off-by: Ronald S. Bultje --- libavfilter/vf_colorspace.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/libavfilter/vf_colorspace.c b/libavfilter/vf_colorspace.c index 21916b7b7af..852dc11c6c7 100644 --- a/libavfilter/vf_colorspace.c +++ b/libavfilter/vf_colorspace.c @@ -572,15 +572,15 @@ static int create_filtergraph(AVFilterContext *ctx, if (s->out_csp == AVCOL_SPC_UNSPECIFIED) { if (s->user_all == CS_UNSPECIFIED) { av_log(ctx, AV_LOG_ERROR, - "Please specify output transfer characteristics\n"); + "Please specify output colorspace\n"); } else { av_log(ctx, AV_LOG_ERROR, "Unsupported output color property %d\n", s->user_all); } } else { av_log(ctx, AV_LOG_ERROR, - "Unsupported output transfer characteristics %d (%s)\n", - s->out_csp, av_color_space_name(s->out_csp)); + "Unsupported output colorspace %d (%s)\n", s->out_csp, + av_color_space_name(s->out_csp)); } return AVERROR(EINVAL); } From b01cfdb4ab1900f4908c2659f8c3f107fcd31605 Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Tue, 30 May 2023 16:55:02 +0200 Subject: [PATCH 1339/2172] avfilter/avf_showwaves: cleanup and simplify some draw calls --- libavfilter/avf_showwaves.c | 91 +++++++++++++++++-------------------- 1 file changed, 41 insertions(+), 50 deletions(-) diff --git a/libavfilter/avf_showwaves.c b/libavfilter/avf_showwaves.c index c0b9c8c88e4..7597ee27233 100644 --- a/libavfilter/avf_showwaves.c +++ b/libavfilter/avf_showwaves.c @@ -28,6 +28,7 @@ #include "libavutil/avassert.h" #include "libavutil/avstring.h" #include "libavutil/channel_layout.h" +#include "libavutil/intreadwrite.h" #include "libavutil/opt.h" #include "libavutil/parseutils.h" #include "avfilter.h" @@ -241,28 +242,26 @@ static void draw_sample_point_rgba_full(uint8_t *buf, int height, int linesize, int16_t *prev_y, const uint8_t color[4], int h) { - if (h >= 0 && h < height) { - buf[h * linesize + 0] = color[0]; - buf[h * linesize + 1] = color[1]; - buf[h * linesize + 2] = color[2]; - buf[h * linesize + 3] = color[3]; - } + uint32_t clr = AV_RN32(color); + if (h >= 0 && h < height) + AV_WN32(buf + h * linesize, clr); } static void draw_sample_line_rgba_scale(uint8_t *buf, int height, int linesize, int16_t *prev_y, const uint8_t color[4], int h) { - int k; int start = height/2; int end = av_clip(h, 0, height-1); + uint8_t *bufk; if (start > end) FFSWAP(int16_t, start, end); - for (k = start; k < end; k++) { - buf[k * linesize + 0] += color[0]; - buf[k * linesize + 1] += color[1]; - buf[k * linesize + 2] += color[2]; - buf[k * linesize + 3] += color[3]; + bufk = buf + start * linesize; + for (int k = start; k < end; k++, bufk += linesize) { + bufk[0] += color[0]; + bufk[1] += color[1]; + bufk[2] += color[2]; + bufk[3] += color[3]; } } @@ -270,24 +269,21 @@ static void draw_sample_line_rgba_full(uint8_t *buf, int height, int linesize, int16_t *prev_y, const uint8_t color[4], int h) { - int k; int start = height/2; int end = av_clip(h, 0, height-1); + uint32_t clr = AV_RN32(color); + uint8_t *bufk; if (start > end) FFSWAP(int16_t, start, end); - for (k = start; k < end; k++) { - buf[k * linesize + 0] = color[0]; - buf[k * linesize + 1] = color[1]; - buf[k * linesize + 2] = color[2]; - buf[k * linesize + 3] = color[3]; - } + bufk = buf + start * linesize; + for (int k = start; k < end; k++, bufk += linesize) + AV_WN32(bufk, clr); } static void draw_sample_p2p_rgba_scale(uint8_t *buf, int height, int linesize, int16_t *prev_y, const uint8_t color[4], int h) { - int k; if (h >= 0 && h < height) { buf[h * linesize + 0] += color[0]; buf[h * linesize + 1] += color[1]; @@ -295,14 +291,16 @@ static void draw_sample_p2p_rgba_scale(uint8_t *buf, int height, int linesize, buf[h * linesize + 3] += color[3]; if (*prev_y && h != *prev_y) { int start = *prev_y; + uint8_t *bufk; int end = av_clip(h, 0, height-1); if (start > end) FFSWAP(int16_t, start, end); - for (k = start + 1; k < end; k++) { - buf[k * linesize + 0] += color[0]; - buf[k * linesize + 1] += color[1]; - buf[k * linesize + 2] += color[2]; - buf[k * linesize + 3] += color[3]; + bufk = buf + (start + 1) * linesize; + for (int k = start + 1; k < end; k++, bufk += linesize) { + bufk[0] += color[0]; + bufk[1] += color[1]; + bufk[2] += color[2]; + bufk[3] += color[3]; } } } @@ -313,23 +311,18 @@ static void draw_sample_p2p_rgba_full(uint8_t *buf, int height, int linesize, int16_t *prev_y, const uint8_t color[4], int h) { - int k; + uint32_t clr = AV_RN32(color); if (h >= 0 && h < height) { - buf[h * linesize + 0] = color[0]; - buf[h * linesize + 1] = color[1]; - buf[h * linesize + 2] = color[2]; - buf[h * linesize + 3] = color[3]; + AV_WN32(buf + h * linesize, clr); if (*prev_y && h != *prev_y) { int start = *prev_y; + uint8_t *bufk; int end = av_clip(h, 0, height-1); if (start > end) FFSWAP(int16_t, start, end); - for (k = start + 1; k < end; k++) { - buf[k * linesize + 0] = color[0]; - buf[k * linesize + 1] = color[1]; - buf[k * linesize + 2] = color[2]; - buf[k * linesize + 3] = color[3]; - } + bufk = buf + (start + 1) * linesize; + for (int k = start + 1; k < end; k++, bufk += linesize) + AV_WN32(bufk, clr); } } *prev_y = h; @@ -339,29 +332,27 @@ static void draw_sample_cline_rgba_scale(uint8_t *buf, int height, int linesize, int16_t *prev_y, const uint8_t color[4], int h) { - int k; const int start = (height - h) / 2; const int end = start + h; - for (k = start; k < end; k++) { - buf[k * linesize + 0] += color[0]; - buf[k * linesize + 1] += color[1]; - buf[k * linesize + 2] += color[2]; - buf[k * linesize + 3] += color[3]; + uint8_t *bufk = buf + start * linesize; + for (int k = start; k < end; k++, bufk += linesize) { + bufk[0] += color[0]; + bufk[1] += color[1]; + bufk[2] += color[2]; + bufk[3] += color[3]; } } - static void draw_sample_cline_rgba_full(uint8_t *buf, int height, int linesize, + +static void draw_sample_cline_rgba_full(uint8_t *buf, int height, int linesize, int16_t *prev_y, const uint8_t color[4], int h) { - int k; + uint32_t clr = AV_RN32(color); const int start = (height - h) / 2; const int end = start + h; - for (k = start; k < end; k++) { - buf[k * linesize + 0] = color[0]; - buf[k * linesize + 1] = color[1]; - buf[k * linesize + 2] = color[2]; - buf[k * linesize + 3] = color[3]; - } + uint8_t *bufk = buf + start * linesize; + for (int k = start; k < end; k++, bufk += linesize) + AV_WN32(bufk, clr); } static void draw_sample_point_gray(uint8_t *buf, int height, int linesize, From c5508f60c255f7c3c17ac84d0d9c0033094d8a96 Mon Sep 17 00:00:00 2001 From: Arnie Chang Date: Thu, 25 May 2023 20:33:27 +0800 Subject: [PATCH 1340/2172] lavc/h264chroma: RISC-V V add motion compensation for 8x8 chroma blocks Optimize the put and avg filtering for 8x8 chroma blocks Signed-off-by: Arnie Chang --- libavcodec/h264chroma.c | 2 + libavcodec/h264chroma.h | 1 + libavcodec/riscv/Makefile | 2 + libavcodec/riscv/h264_chroma_init_riscv.c | 41 +++ libavcodec/riscv/h264_mc_chroma.S | 307 ++++++++++++++++++++++ 5 files changed, 353 insertions(+) create mode 100644 libavcodec/riscv/h264_chroma_init_riscv.c create mode 100644 libavcodec/riscv/h264_mc_chroma.S diff --git a/libavcodec/h264chroma.c b/libavcodec/h264chroma.c index 60b86b6fba0..1eeab7bc40c 100644 --- a/libavcodec/h264chroma.c +++ b/libavcodec/h264chroma.c @@ -58,5 +58,7 @@ av_cold void ff_h264chroma_init(H264ChromaContext *c, int bit_depth) ff_h264chroma_init_mips(c, bit_depth); #elif ARCH_LOONGARCH64 ff_h264chroma_init_loongarch(c, bit_depth); +#elif ARCH_RISCV + ff_h264chroma_init_riscv(c, bit_depth); #endif } diff --git a/libavcodec/h264chroma.h b/libavcodec/h264chroma.h index b8f9c8f4fcc..9c81c18a76f 100644 --- a/libavcodec/h264chroma.h +++ b/libavcodec/h264chroma.h @@ -37,5 +37,6 @@ 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); +void ff_h264chroma_init_riscv(H264ChromaContext *c, int bit_depth); #endif /* AVCODEC_H264CHROMA_H */ diff --git a/libavcodec/riscv/Makefile b/libavcodec/riscv/Makefile index 965942f4df8..ee17a521fd4 100644 --- a/libavcodec/riscv/Makefile +++ b/libavcodec/riscv/Makefile @@ -10,6 +10,8 @@ OBJS-$(CONFIG_BSWAPDSP) += riscv/bswapdsp_init.o \ RVV-OBJS-$(CONFIG_BSWAPDSP) += riscv/bswapdsp_rvv.o OBJS-$(CONFIG_FMTCONVERT) += riscv/fmtconvert_init.o RVV-OBJS-$(CONFIG_FMTCONVERT) += riscv/fmtconvert_rvv.o +OBJS-$(CONFIG_H264CHROMA) += riscv/h264_chroma_init_riscv.o +RVV-OBJS-$(CONFIG_H264CHROMA) += riscv/h264_mc_chroma.o OBJS-$(CONFIG_IDCTDSP) += riscv/idctdsp_init.o RVV-OBJS-$(CONFIG_IDCTDSP) += riscv/idctdsp_rvv.o OBJS-$(CONFIG_OPUS_DECODER) += riscv/opusdsp_init.o diff --git a/libavcodec/riscv/h264_chroma_init_riscv.c b/libavcodec/riscv/h264_chroma_init_riscv.c new file mode 100644 index 00000000000..7c905edfcd8 --- /dev/null +++ b/libavcodec/riscv/h264_chroma_init_riscv.c @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2023 SiFive, Inc. All rights reserved. + * + * 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/attributes.h" +#include "libavutil/riscv/cpu.h" +#include "libavcodec/h264chroma.h" +#include "config.h" + +void h264_put_chroma_mc8_rvv(uint8_t *p_dst, const uint8_t *p_src, ptrdiff_t stride, int h, int x, int y); +void h264_avg_chroma_mc8_rvv(uint8_t *p_dst, const uint8_t *p_src, ptrdiff_t stride, int h, int x, int y); + +av_cold void ff_h264chroma_init_riscv(H264ChromaContext *c, int bit_depth) +{ +#if HAVE_RVV + int flags = av_get_cpu_flags(); + + if (bit_depth == 8 && (flags & AV_CPU_FLAG_RVV_I32) && ff_get_rv_vlenb() >= 16) { + c->put_h264_chroma_pixels_tab[0] = h264_put_chroma_mc8_rvv; + c->avg_h264_chroma_pixels_tab[0] = h264_avg_chroma_mc8_rvv; + } +#endif +} diff --git a/libavcodec/riscv/h264_mc_chroma.S b/libavcodec/riscv/h264_mc_chroma.S new file mode 100644 index 00000000000..364bc3156e2 --- /dev/null +++ b/libavcodec/riscv/h264_mc_chroma.S @@ -0,0 +1,307 @@ +/* + * Copyright (c) 2023 SiFive, Inc. All rights reserved. + * + * 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/riscv/asm.S" + +.macro h264_chroma_mc8 type +func h264_\type\()_chroma_mc8_rvv, zve32x + csrw vxrm, zero + slli t2, a5, 3 + mul t1, a5, a4 + sh3add a5, a4, t2 + slli a4, a4, 3 + sub a5, t1, a5 + sub a7, a4, t1 + addi a6, a5, 64 + sub t0, t2, t1 + vsetivli t3, 8, e8, m1, ta, mu + beqz t1, 2f + blez a3, 8f + li t4, 0 + li t2, 0 + li t5, 1 + addi a5, t3, 1 + slli t3, a2, 2 +1: # if (xy != 0) + add a4, a1, t4 + vsetvli zero, a5, e8, m1, ta, ma + addi t2, t2, 4 + vle8.v v10, (a4) + add a4, a4, a2 + vslide1down.vx v11, v10, t5 + vsetivli zero, 8, e8, m1, ta, ma + vwmulu.vx v8, v10, a6 + vwmaccu.vx v8, a7, v11 + vsetvli zero, a5, e8, m1, ta, ma + vle8.v v12, (a4) + vsetivli zero, 8, e8, m1, ta, ma + add a4, a4, a2 + vwmaccu.vx v8, t0, v12 + vsetvli zero, a5, e8, m1, ta, ma + vslide1down.vx v13, v12, t5 + vsetivli zero, 8, e8, m1, ta, ma + vwmulu.vx v10, v12, a6 + vwmaccu.vx v8, t1, v13 + vwmaccu.vx v10, a7, v13 + vsetvli zero, a5, e8, m1, ta, ma + vle8.v v14, (a4) + vsetivli zero, 8, e8, m1, ta, ma + add a4, a4, a2 + vwmaccu.vx v10, t0, v14 + vsetvli zero, a5, e8, m1, ta, ma + vslide1down.vx v15, v14, t5 + vsetivli zero, 8, e8, m1, ta, ma + vwmulu.vx v12, v14, a6 + vwmaccu.vx v10, t1, v15 + vwmaccu.vx v12, a7, v15 + vsetvli zero, a5, e8, m1, ta, ma + vle8.v v14, (a4) + vsetivli zero, 8, e8, m1, ta, ma + add a4, a4, a2 + vwmaccu.vx v12, t0, v14 + vsetvli zero, a5, e8, m1, ta, ma + vslide1down.vx v15, v14, t5 + vsetivli zero, 8, e8, m1, ta, ma + vwmulu.vx v16, v14, a6 + vwmaccu.vx v12, t1, v15 + vwmaccu.vx v16, a7, v15 + vsetvli zero, a5, e8, m1, ta, ma + vle8.v v14, (a4) + vsetivli zero, 8, e8, m1, ta, ma + add a4, a0, t4 + add t4, t4, t3 + vwmaccu.vx v16, t0, v14 + vsetvli zero, a5, e8, m1, ta, ma + vslide1down.vx v14, v14, t5 + vsetivli zero, 8, e8, m1, ta, ma + vnclipu.wi v15, v8, 6 + vwmaccu.vx v16, t1, v14 + .ifc \type,avg + vle8.v v9, (a4) + vaaddu.vv v15, v15, v9 + .endif + vse8.v v15, (a4) + add a4, a4, a2 + vnclipu.wi v8, v10, 6 + .ifc \type,avg + vle8.v v9, (a4) + vaaddu.vv v8, v8, v9 + .endif + vse8.v v8, (a4) + add a4, a4, a2 + vnclipu.wi v8, v12, 6 + .ifc \type,avg + vle8.v v9, (a4) + vaaddu.vv v8, v8, v9 + .endif + vse8.v v8, (a4) + add a4, a4, a2 + vnclipu.wi v8, v16, 6 + .ifc \type,avg + vle8.v v9, (a4) + vaaddu.vv v8, v8, v9 + .endif + vse8.v v8, (a4) + blt t2, a3, 1b + j 8f +2: + bnez a4, 4f + beqz t2, 4f + blez a3, 8f + li a4, 0 + li t1, 0 + slli a7, a2, 2 +3: # if ((x8 - xy) == 0 && (y8 -xy) != 0) + add a5, a1, a4 + vsetvli zero, zero, e8, m1, ta, ma + addi t1, t1, 4 + vle8.v v8, (a5) + add a5, a5, a2 + add t2, a5, a2 + vwmulu.vx v10, v8, a6 + vle8.v v8, (a5) + vwmulu.vx v12, v8, a6 + vle8.v v9, (t2) + add t2, t2, a2 + add a5, t2, a2 + vwmaccu.vx v10, t0, v8 + vle8.v v8, (t2) + vle8.v v14, (a5) + add a5, a0, a4 + add a4, a4, a7 + vwmaccu.vx v12, t0, v9 + vnclipu.wi v15, v10, 6 + vwmulu.vx v10, v9, a6 + .ifc \type,avg + vle8.v v16, (a5) + vaaddu.vv v15, v15, v16 + .endif + vse8.v v15, (a5) + add a5, a5, a2 + vnclipu.wi v9, v12, 6 + vwmaccu.vx v10, t0, v8 + vwmulu.vx v12, v8, a6 + .ifc \type,avg + vle8.v v16, (a5) + vaaddu.vv v9, v9, v16 + .endif + vse8.v v9, (a5) + add a5, a5, a2 + vnclipu.wi v8, v10, 6 + vwmaccu.vx v12, t0, v14 + .ifc \type,avg + vle8.v v16, (a5) + vaaddu.vv v8, v8, v16 + .endif + vse8.v v8, (a5) + add a5, a5, a2 + vnclipu.wi v8, v12, 6 + .ifc \type,avg + vle8.v v16, (a5) + vaaddu.vv v8, v8, v16 + .endif + vse8.v v8, (a5) + blt t1, a3, 3b + j 8f +4: + beqz a4, 6f + bnez t2, 6f + blez a3, 8f + li a4, 0 + li t2, 0 + addi t0, t3, 1 + slli t1, a2, 2 +5: # if ((x8 - xy) != 0 && (y8 -xy) == 0) + add a5, a1, a4 + vsetvli zero, t0, e8, m1, ta, ma + addi t2, t2, 4 + vle8.v v8, (a5) + add a5, a5, a2 + vslide1down.vx v9, v8, t5 + vsetivli zero, 8, e8, m1, ta, ma + vwmulu.vx v10, v8, a6 + vwmaccu.vx v10, a7, v9 + vsetvli zero, t0, e8, m1, ta, ma + vle8.v v8, (a5) + add a5, a5, a2 + vslide1down.vx v9, v8, t5 + vsetivli zero, 8, e8, m1, ta, ma + vwmulu.vx v12, v8, a6 + vwmaccu.vx v12, a7, v9 + vsetvli zero, t0, e8, m1, ta, ma + vle8.v v8, (a5) + add a5, a5, a2 + vslide1down.vx v9, v8, t5 + vsetivli zero, 8, e8, m1, ta, ma + vwmulu.vx v14, v8, a6 + vwmaccu.vx v14, a7, v9 + vsetvli zero, t0, e8, m1, ta, ma + vle8.v v8, (a5) + add a5, a0, a4 + add a4, a4, t1 + vslide1down.vx v9, v8, t5 + vsetivli zero, 8, e8, m1, ta, ma + vnclipu.wi v16, v10, 6 + .ifc \type,avg + vle8.v v18, (a5) + vaaddu.vv v16, v16, v18 + .endif + vse8.v v16, (a5) + add a5, a5, a2 + vnclipu.wi v10, v12, 6 + vwmulu.vx v12, v8, a6 + .ifc \type,avg + vle8.v v18, (a5) + vaaddu.vv v10, v10, v18 + .endif + vse8.v v10, (a5) + add a5, a5, a2 + vnclipu.wi v8, v14, 6 + vwmaccu.vx v12, a7, v9 + .ifc \type,avg + vle8.v v18, (a5) + vaaddu.vv v8, v8, v18 + .endif + vse8.v v8, (a5) + add a5, a5, a2 + vnclipu.wi v8, v12, 6 + .ifc \type,avg + vle8.v v18, (a5) + vaaddu.vv v8, v8, v18 + .endif + vse8.v v8, (a5) + blt t2, a3, 5b + j 8f +6: + blez a3, 8f + li a4, 0 + li t2, 0 + slli a7, a2, 2 +7: # the final else, none of the above conditions are met + add t0, a1, a4 + vsetvli zero, zero, e8, m1, ta, ma + add a5, a0, a4 + add a4, a4, a7 + addi t2, t2, 4 + vle8.v v8, (t0) + add t0, t0, a2 + add t1, t0, a2 + vwmulu.vx v10, v8, a6 + vle8.v v8, (t0) + add t0, t1, a2 + vle8.v v9, (t1) + vle8.v v12, (t0) + vnclipu.wi v13, v10, 6 + vwmulu.vx v10, v8, a6 + .ifc \type,avg + vle8.v v18, (a5) + vaaddu.vv v13, v13, v18 + .endif + vse8.v v13, (a5) + add a5, a5, a2 + vnclipu.wi v8, v10, 6 + vwmulu.vx v10, v9, a6 + .ifc \type,avg + vle8.v v18, (a5) + vaaddu.vv v8, v8, v18 + .endif + vse8.v v8, (a5) + add a5, a5, a2 + vnclipu.wi v8, v10, 6 + vwmulu.vx v10, v12, a6 + .ifc \type,avg + vle8.v v18, (a5) + vaaddu.vv v8, v8, v18 + .endif + vse8.v v8, (a5) + add a5, a5, a2 + vnclipu.wi v8, v10, 6 + .ifc \type,avg + vle8.v v18, (a5) + vaaddu.vv v8, v8, v18 + .endif + vse8.v v8, (a5) + blt t2, a3, 7b +8: + ret +endfunc +.endm + +h264_chroma_mc8 put +h264_chroma_mc8 avg From 1636fb415aac8747222bb35efb75555f8bc8772d Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Tue, 30 May 2023 18:14:27 +0200 Subject: [PATCH 1341/2172] avfilter/avf_ahistogram: refactor frame fill data code --- libavfilter/avf_ahistogram.c | 52 +++++++++++++++++++++++++----------- 1 file changed, 36 insertions(+), 16 deletions(-) diff --git a/libavfilter/avf_ahistogram.c b/libavfilter/avf_ahistogram.c index 06490192a57..6df6e18e3d2 100644 --- a/libavfilter/avf_ahistogram.c +++ b/libavfilter/avf_ahistogram.c @@ -207,6 +207,7 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in) AVFilterContext *ctx = inlink->dst; AVFilterLink *outlink = ctx->outputs[0]; AudioHistogramContext *s = ctx->priv; + const int nb_samples = in->nb_samples; const int H = s->histogram_h; const int w = s->w; int c, y, n, p, bin, ret; @@ -260,7 +261,7 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in) const float *src = (const float *)in->extended_data[c]; uint64_t *achistogram = &s->achistogram[(s->dmode == SINGLE ? 0: c) * w]; - for (n = 0; n < in->nb_samples; n++) { + for (n = 0; n < nb_samples; n++) { bin = s->get_bin(src[n], w); achistogram[bin]++; @@ -270,7 +271,7 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in) uint64_t *shistogram = &s->shistogram[(s->dmode == SINGLE ? 0: c) * w]; const float *src2 = (const float *)s->in[s->first]->extended_data[c]; - for (n = 0; n < in->nb_samples; n++) { + for (n = 0; n < nb_samples; n++) { bin = s->get_bin(src2[n], w); shistogram[bin]++; @@ -283,7 +284,7 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in) const float *src = (const float *)in->extended_data[c]; uint64_t *achistogram = &s->achistogram[(s->dmode == SINGLE ? 0: c) * w]; - for (n = 0; n < in->nb_samples; n++) { + for (n = 0; n < nb_samples; n++) { bin = s->get_bin(src[n], w); achistogram[bin]++; @@ -293,7 +294,7 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in) uint64_t *shistogram = &s->shistogram[(s->dmode == SINGLE ? 0: c) * w]; const float *src2 = (const float *)s->in[s->first]->extended_data[c]; - for (n = 0; n < in->nb_samples; n++) { + for (n = 0; n < nb_samples; n++) { bin = s->get_bin(src2[n], w); shistogram[bin]++; @@ -357,10 +358,15 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in) h = aa * (H - 1); if (s->dmode == SINGLE) { - - for (y = H - h; y < H; y++) { - s->out->data[0][y * s->out->linesize[0] + n] = 255; - s->out->data[3][y * s->out->linesize[0] + n] = 255; + int start = H - h, end = H; + const int linesizey = s->out->linesize[0]; + const int linesizea = s->out->linesize[3]; + uint8_t *dsty = s->out->data[0] + start * linesizey; + uint8_t *dsta = s->out->data[3] + start * linesizea; + + for (y = start; y < end; y++, dsty += linesizey, dsta += linesizea) { + dsty[n] = 255; + dsta[n] = 255; } if (s->h - H > 0) { @@ -372,18 +378,32 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in) s->out->data[3][s->ypos * s->out->linesize[3] + n] = 255; } } else if (s->dmode == SEPARATE) { + int start = H - h, end = H; float *out = &s->combine_buffer[3 * n]; + const int linesizey = s->out->linesize[0]; + const int linesizeu = s->out->linesize[1]; + const int linesizev = s->out->linesize[2]; + const int linesizea = s->out->linesize[3]; + uint8_t *dsty = s->out->data[0] + start * linesizey; + uint8_t *dstu = s->out->data[1] + start * linesizeu; + uint8_t *dstv = s->out->data[2] + start * linesizev; + uint8_t *dsta = s->out->data[3] + start * linesizea; int old; - old = s->out->data[0][(H - h) * s->out->linesize[0] + n]; - for (y = H - h; y < H; y++) { - if (s->out->data[0][y * s->out->linesize[0] + n] != old) + old = dsty[n]; + for (y = start; y < end; y++) { + if (dsty[n] != old) break; - old = s->out->data[0][y * s->out->linesize[0] + n]; - s->out->data[0][y * s->out->linesize[0] + n] = av_clip_uint8(yf); - s->out->data[1][y * s->out->linesize[1] + n] = av_clip_uint8(128.f+uf); - s->out->data[2][y * s->out->linesize[2] + n] = av_clip_uint8(128.f+vf); - s->out->data[3][y * s->out->linesize[3] + n] = 255; + old = dsty[n]; + dsty[n] = av_clip_uint8(yf); + dstu[n] = av_clip_uint8(128.f+uf); + dstv[n] = av_clip_uint8(128.f+vf); + dsta[n] = 255; + + dsty += linesizey; + dstu += linesizeu; + dstv += linesizev; + dsta += linesizea; } out[0] += aa * yf; From 862ebbf2edb515b7685952cce8b8b6c8bacc9470 Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Tue, 30 May 2023 19:08:02 +0200 Subject: [PATCH 1342/2172] avfilter/avf_abitscope: refactor bit counting for histogram This helps compiler figure out it can unroll loop and give 4x speedup. --- libavfilter/avf_abitscope.c | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/libavfilter/avf_abitscope.c b/libavfilter/avf_abitscope.c index 782d57e03a5..c74970981e4 100644 --- a/libavfilter/avf_abitscope.c +++ b/libavfilter/avf_abitscope.c @@ -148,25 +148,29 @@ static int config_output(AVFilterLink *outlink) return 0; } +#define BITCOUNTER(type, depth, one) \ + memset(counter, 0, sizeof(s->counter)); \ + for (int i = 0; i < nb_samples; i++) { \ + const type x = in[i]; \ + for (int j = 0; j < depth && x; j++) \ + counter[j] += !!(x & (one << j)); \ + } + #define BARS(type, depth, one) \ for (int ch = 0; ch < inlink->ch_layout.nb_channels; ch++) { \ + const int nb_samples = insamples->nb_samples; \ const type *in = (const type *)insamples->extended_data[ch]; \ const int w = outpicref->width / inlink->ch_layout.nb_channels; \ const int h = outpicref->height / depth; \ const uint32_t color = AV_RN32(&s->fg[4 * ch]); \ + uint64_t *counter = s->counter; \ \ - memset(s->counter, 0, sizeof(s->counter)); \ - for (int i = 0; i < insamples->nb_samples; i++) { \ - for (int j = 0; j < depth; j++) { \ - if (in[i] & (one << j)) \ - s->counter[j]++; \ - } \ - } \ + BITCOUNTER(type, depth, one) \ \ for (int b = 0; b < depth; b++) { \ for (int j = 1; j < h - 1; j++) { \ uint8_t *dst = outpicref->data[0] + (b * h + j) * outpicref->linesize[0] + w * ch * 4; \ - const int ww = (s->counter[depth - b - 1] / (float)insamples->nb_samples) * (w - 1); \ + const int ww = (counter[depth - b - 1] / (float)nb_samples) * (w - 1); \ \ for (int i = 0; i < ww; i++) { \ AV_WN32(&dst[i * 4], color); \ @@ -177,25 +181,21 @@ static int config_output(AVFilterLink *outlink) #define DO_TRACE(type, depth, one) \ for (int ch = 0; ch < inlink->ch_layout.nb_channels; ch++) { \ + const int nb_samples = insamples->nb_samples; \ const int w = outpicref->width / inlink->ch_layout.nb_channels; \ const type *in = (const type *)insamples->extended_data[ch]; \ + uint64_t *counter = s->counter; \ const int wb = w / depth; \ int wv; \ \ - memset(s->counter, 0, sizeof(s->counter)); \ - for (int i = 0; i < insamples->nb_samples; i++) { \ - for (int j = 0; j < depth; j++) { \ - if (in[i] & (one << j)) \ - s->counter[j]++; \ - } \ - } \ + BITCOUNTER(type, depth, one) \ \ for (int b = 0; b < depth; b++) { \ uint8_t colors[4]; \ uint32_t color; \ uint8_t *dst = outpicref->data[0] + w * ch * 4 + wb * b * 4 + \ s->current_vpos * outpicref->linesize[0]; \ - wv = (s->counter[depth - b - 1] * 255) / insamples->nb_samples; \ + wv = (counter[depth - b - 1] * 255) / nb_samples; \ colors[0] = (wv * s->fg[ch * 4 + 0] + 127) / 255; \ colors[1] = (wv * s->fg[ch * 4 + 1] + 127) / 255; \ colors[2] = (wv * s->fg[ch * 4 + 2] + 127) / 255; \ From 3ea3a4ba167cacc94ca34ad1fde7bc16d5c00f99 Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Tue, 30 May 2023 19:28:56 +0200 Subject: [PATCH 1343/2172] avfilter/avf_aphasemeter: avoid using double --- libavfilter/avf_aphasemeter.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libavfilter/avf_aphasemeter.c b/libavfilter/avf_aphasemeter.c index bf9f922639b..2271e7ce737 100644 --- a/libavfilter/avf_aphasemeter.c +++ b/libavfilter/avf_aphasemeter.c @@ -161,7 +161,7 @@ static int config_video_output(AVFilterLink *outlink) static inline int get_x(float phase, int w) { - return (phase + 1.) / 2. * (w - 1); + return (phase + 1.f) / 2.f * (w - 1.f); } static inline void add_metadata(AVFrame *insamples, const char *key, char *value) @@ -251,7 +251,7 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in) int mono_measurement; int out_phase_measurement; float tolerance = 1.0f - s->tolerance; - float angle = cosf(s->angle/180.0f*M_PI); + float angle = cosf(s->angle/180.0f*M_PIf); if (s->do_video && (!s->out || s->out->width != outlink->w || s->out->height != outlink->h)) { From 4d9afbeef522726beb1ef50689009dd88f195d3a Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Tue, 30 May 2023 20:05:23 +0200 Subject: [PATCH 1344/2172] avfilter/avf_aphasemeter: switch to activate --- libavfilter/avf_aphasemeter.c | 81 ++++++++++++++++++++++++++--------- 1 file changed, 61 insertions(+), 20 deletions(-) diff --git a/libavfilter/avf_aphasemeter.c b/libavfilter/avf_aphasemeter.c index 2271e7ce737..fac8d7c048f 100644 --- a/libavfilter/avf_aphasemeter.c +++ b/libavfilter/avf_aphasemeter.c @@ -38,7 +38,8 @@ typedef struct AudioPhaseMeterContext { const AVClass *class; - AVFrame *out; + AVFrame *out, *in; + int64_t last_pts; int do_video; int do_phasing_detection; int w, h; @@ -51,6 +52,7 @@ typedef struct AudioPhaseMeterContext { int is_out_phase; int start_mono_presence; int start_out_phase_presence; + int nb_samples; float tolerance; float angle; float phase; @@ -127,14 +129,10 @@ static int config_input(AVFilterLink *inlink) { AVFilterContext *ctx = inlink->dst; AudioPhaseMeterContext *s = ctx->priv; - int nb_samples; s->duration = av_rescale(s->duration, inlink->sample_rate, AV_TIME_BASE); - if (s->do_video) { - nb_samples = FFMAX(1, av_rescale(inlink->sample_rate, s->frame_rate.den, s->frame_rate.num)); - inlink->min_samples = - inlink->max_samples = nb_samples; - } + if (s->do_video) + s->nb_samples = FFMAX(1, av_rescale(inlink->sample_rate, s->frame_rate.den, s->frame_rate.num)); return 0; } @@ -144,10 +142,13 @@ static int config_video_output(AVFilterLink *outlink) AVFilterContext *ctx = outlink->src; AudioPhaseMeterContext *s = ctx->priv; + s->last_pts = AV_NOPTS_VALUE; + outlink->w = s->w; outlink->h = s->h; outlink->sample_aspect_ratio = (AVRational){1,1}; outlink->frame_rate = s->frame_rate; + outlink->time_base = av_inv_q(outlink->frame_rate); if (!strcmp(s->mpc_str, "none")) s->draw_median_phase = 0; @@ -252,14 +253,15 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in) int out_phase_measurement; float tolerance = 1.0f - s->tolerance; float angle = cosf(s->angle/180.0f*M_PIf); + int64_t new_pts; if (s->do_video && (!s->out || s->out->width != outlink->w || s->out->height != outlink->h)) { av_frame_free(&s->out); s->out = ff_get_video_buffer(outlink, outlink->w, outlink->h); if (!s->out) { - av_frame_free(&in); - return AVERROR(ENOMEM); + ret = AVERROR(ENOMEM); + goto fail; } out = s->out; @@ -267,10 +269,8 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in) memset(out->data[0] + i * out->linesize[0], 0, outlink->w * 4); } else if (s->do_video) { ret = ff_inlink_make_frame_writable(outlink, &s->out); - if (ret < 0) { - av_frame_free(&in); - return ret; - } + if (ret < 0) + goto fail; out = s->out; for (i = outlink->h - 1; i >= 10; i--) memmove(out->data[0] + (i ) * out->linesize[0], @@ -328,18 +328,59 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in) update_out_phase_detection(s, in, out_phase_measurement); } - if (s->do_video) { + if (s->do_video) + new_pts = av_rescale_q(in->pts, inlink->time_base, outlink->time_base); + if (s->do_video && new_pts != s->last_pts) { AVFrame *clone; - s->out->pts = in->pts; - s->out->duration = av_rescale_q(1, av_inv_q(outlink->frame_rate), outlink->time_base); + s->out->pts = s->last_pts = new_pts; + s->out->duration = 1; clone = av_frame_clone(s->out); - if (!clone) - return AVERROR(ENOMEM); - ff_filter_frame(outlink, clone); + if (!clone) { + ret = AVERROR(ENOMEM); + goto fail; + } + ret = ff_filter_frame(outlink, clone); + if (ret < 0) + goto fail; } + s->in = NULL; return ff_filter_frame(aoutlink, in); +fail: + av_frame_free(&in); + s->in = NULL; + return ret; +} + +static int activate(AVFilterContext *ctx) +{ + AVFilterLink *inlink = ctx->inputs[0]; + AVFilterLink *outlink = ctx->outputs[0]; + AudioPhaseMeterContext *s = ctx->priv; + int ret; + + FF_FILTER_FORWARD_STATUS_BACK(outlink, inlink); + if (s->do_video) + FF_FILTER_FORWARD_STATUS_BACK(ctx->outputs[1], inlink); + + if (!s->in) { + if (s->nb_samples > 0) + ret = ff_inlink_consume_samples(inlink, s->nb_samples, s->nb_samples, &s->in); + else + ret = ff_inlink_consume_frame(inlink, &s->in); + if (ret < 0) + return ret; + if (ret > 0) + return filter_frame(inlink, s->in); + } + + FF_FILTER_FORWARD_STATUS_ALL(inlink, ctx); + FF_FILTER_FORWARD_WANTED(outlink, inlink); + if (s->do_video) + FF_FILTER_FORWARD_WANTED(ctx->outputs[1], inlink); + + return FFERROR_NOT_READY; } static av_cold void uninit(AVFilterContext *ctx) @@ -386,7 +427,6 @@ static const AVFilterPad inputs[] = { .name = "default", .type = AVMEDIA_TYPE_AUDIO, .config_props = config_input, - .filter_frame = filter_frame, }, }; @@ -397,6 +437,7 @@ const AVFilter ff_avf_aphasemeter = { .uninit = uninit, .priv_size = sizeof(AudioPhaseMeterContext), FILTER_INPUTS(inputs), + .activate = activate, .outputs = NULL, FILTER_QUERY_FUNC(query_formats), .priv_class = &aphasemeter_class, From a9042db1d30483639b3ca610b74a7d43f29ea1a9 Mon Sep 17 00:00:00 2001 From: Paul Arzelier Date: Tue, 30 May 2023 23:21:36 +0200 Subject: [PATCH 1345/2172] avformat/oggparseflac: check init_get_bits' result Check init_get_bits' result for NULL, to avoid dereferencing a NULL pointer later (CWE-476). Without this, a segfault happens when trying to decode a handcrafted ogg-flac file with an absurdly long (e.g. 268435455 bytes) ogg header. Co-authored-by: James Almer Signed-off-by: Paul Arzelier --- libavformat/oggparseflac.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/libavformat/oggparseflac.c b/libavformat/oggparseflac.c index eef6e099277..557440d94b9 100644 --- a/libavformat/oggparseflac.c +++ b/libavformat/oggparseflac.c @@ -40,7 +40,10 @@ flac_header (AVFormatContext * s, int idx) if (os->buf[os->pstart] == 0xff) return 0; - init_get_bits(&gb, os->buf + os->pstart, os->psize*8); + ret = init_get_bits8(&gb, os->buf + os->pstart, os->psize); + if (ret < 0) + return ret; + skip_bits1(&gb); /* metadata_last */ mdt = get_bits(&gb, 7); From 859c34706d341f6b30f8e4993027657bf987765d Mon Sep 17 00:00:00 2001 From: Devin Heitmueller Date: Fri, 12 May 2023 12:04:57 -0400 Subject: [PATCH 1346/2172] avdevice/decklink_common: Convert to using avpriv_packet_list functions The existing DecklinkQueue implementation was using the PacketList structure but wasn't using the standard avpriv_packet_list_get and avpriv_packet_list_put functions. Convert to using them so we eliminate the duplicate logic, per Marton Balint's suggestion. Updated to reflect feedback from Marton Balint provided on 05/11/23. Signed-off-by: Devin Heitmueller Signed-off-by: Marton Balint --- libavdevice/decklink_common.cpp | 50 ++++++++++----------------------- 1 file changed, 15 insertions(+), 35 deletions(-) diff --git a/libavdevice/decklink_common.cpp b/libavdevice/decklink_common.cpp index 74e26e986d6..b6cc8d71f16 100644 --- a/libavdevice/decklink_common.cpp +++ b/libavdevice/decklink_common.cpp @@ -402,16 +402,12 @@ void ff_decklink_packet_queue_init(AVFormatContext *avctx, DecklinkPacketQueue * void ff_decklink_packet_queue_flush(DecklinkPacketQueue *q) { - PacketListEntry *pkt, *pkt1; + AVPacket pkt; pthread_mutex_lock(&q->mutex); - for (pkt = q->pkt_list.head; pkt != NULL; pkt = pkt1) { - pkt1 = pkt->next; - av_packet_unref(&pkt->pkt); - av_freep(&pkt); + while (avpriv_packet_list_get(&q->pkt_list, &pkt) == 0) { + av_packet_unref(&pkt); } - q->pkt_list.head = NULL; - q->pkt_list.tail = NULL; q->nb_packets = 0; q->size = 0; pthread_mutex_unlock(&q->mutex); @@ -435,7 +431,8 @@ unsigned long long ff_decklink_packet_queue_size(DecklinkPacketQueue *q) int ff_decklink_packet_queue_put(DecklinkPacketQueue *q, AVPacket *pkt) { - PacketListEntry *pkt1; + int pkt_size = pkt->size; + int ret; // Drop Packet if queue size is > maximum queue size if (ff_decklink_packet_queue_size(q) > (uint64_t)q->max_q_size) { @@ -449,30 +446,19 @@ int ff_decklink_packet_queue_put(DecklinkPacketQueue *q, AVPacket *pkt) return -1; } - pkt1 = (PacketListEntry *)av_malloc(sizeof(*pkt1)); - if (!pkt1) { - av_packet_unref(pkt); - return -1; - } - av_packet_move_ref(&pkt1->pkt, pkt); - pkt1->next = NULL; - pthread_mutex_lock(&q->mutex); - if (!q->pkt_list.tail) { - q->pkt_list.head = pkt1; + ret = avpriv_packet_list_put(&q->pkt_list, pkt, NULL, 0); + if (ret == 0) { + q->nb_packets++; + q->size += pkt_size + sizeof(AVPacket); + pthread_cond_signal(&q->cond); } else { - q->pkt_list.tail->next = pkt1; + av_packet_unref(pkt); } - q->pkt_list.tail = pkt1; - q->nb_packets++; - q->size += pkt1->pkt.size + sizeof(*pkt1); - - pthread_cond_signal(&q->cond); - pthread_mutex_unlock(&q->mutex); - return 0; + return ret; } int ff_decklink_packet_queue_get(DecklinkPacketQueue *q, AVPacket *pkt, int block) @@ -482,16 +468,10 @@ int ff_decklink_packet_queue_get(DecklinkPacketQueue *q, AVPacket *pkt, int bloc pthread_mutex_lock(&q->mutex); for (;; ) { - PacketListEntry *pkt1 = q->pkt_list.head; - if (pkt1) { - q->pkt_list.head = pkt1->next; - if (!q->pkt_list.head) { - q->pkt_list.tail = NULL; - } + ret = avpriv_packet_list_get(&q->pkt_list, pkt); + if (ret == 0) { q->nb_packets--; - q->size -= pkt1->pkt.size + sizeof(*pkt1); - *pkt = pkt1->pkt; - av_free(pkt1); + q->size -= pkt->size + sizeof(AVPacket); ret = 1; break; } else if (!block) { From eeb7d92ac77dfc18a46614c4b38c0c72d770dc4e Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Sat, 20 May 2023 19:12:08 +0200 Subject: [PATCH 1347/2172] fftools/ffmpeg_mux_init: merge ost_add_from_filter() to ost_add() This way ost_add() knows about the complex filtergraph it is fed from, which will become useful in future commits. --- fftools/ffmpeg_mux_init.c | 71 ++++++++++++++++++--------------------- 1 file changed, 32 insertions(+), 39 deletions(-) diff --git a/fftools/ffmpeg_mux_init.c b/fftools/ffmpeg_mux_init.c index 7878789bb4b..de39b360afc 100644 --- a/fftools/ffmpeg_mux_init.c +++ b/fftools/ffmpeg_mux_init.c @@ -985,7 +985,8 @@ static int streamcopy_init(const Muxer *mux, OutputStream *ost) } static OutputStream *ost_add(Muxer *mux, const OptionsContext *o, - enum AVMediaType type, InputStream *ist) + enum AVMediaType type, InputStream *ist, + OutputFilter *ofilter) { AVFormatContext *oc = mux->fc; MuxStream *ms; @@ -1040,6 +1041,14 @@ static OutputStream *ost_add(Muxer *mux, const OptionsContext *o, av_strlcat(ms->log_name, "/", sizeof(ms->log_name)); av_strlcat(ms->log_name, enc->name, sizeof(ms->log_name)); } else { + if (ofilter) { + av_log(ost, AV_LOG_ERROR, + "Streamcopy requested for output stream fed " + "from a complex filtergraph. Filtering and streamcopy " + "cannot be used together.\n"); + exit_program(1); + } + av_strlcat(ms->log_name, "/copy", sizeof(ms->log_name)); } @@ -1233,22 +1242,26 @@ static OutputStream *ost_add(Muxer *mux, const OptionsContext *o, exit_program(1); } - if (ost->ist) { - if (ost->enc && - (type == AVMEDIA_TYPE_VIDEO || type == AVMEDIA_TYPE_AUDIO)) { + if (ost->enc && + (type == AVMEDIA_TYPE_VIDEO || type == AVMEDIA_TYPE_AUDIO)) { + if (ofilter) { + ost->filter = ofilter; + ofilter->ost = ost; + avfilter_inout_free(&ofilter->out_tmp); + } else { ret = init_simple_filtergraph(ost->ist, ost); if (ret < 0) { av_log(ost, AV_LOG_ERROR, "Error initializing a simple filtergraph\n"); exit_program(1); } - } else { - ret = ist_output_add(ost->ist, ost); - if (ret < 0) { - av_log(ost, AV_LOG_ERROR, - "Error binding an input stream\n"); - exit_program(1); - } + } + } else if (ost->ist) { + ret = ist_output_add(ost->ist, ost); + if (ret < 0) { + av_log(ost, AV_LOG_ERROR, + "Error binding an input stream\n"); + exit_program(1); } } @@ -1261,26 +1274,6 @@ static OutputStream *ost_add(Muxer *mux, const OptionsContext *o, return ost; } -// add a new output stream fed by the provided filtergraph output -static void ost_add_from_filter(OutputFilter *ofilter, const OptionsContext *o, - Muxer *mux) -{ - OutputStream *ost = ost_add(mux, o, ofilter->type, NULL); - - ost->filter = ofilter; - - ofilter->ost = ost; - - if (!ost->enc_ctx) { - av_log(ost, AV_LOG_ERROR, "Streamcopy requested for output stream fed " - "from a complex filtergraph. Filtering and streamcopy " - "cannot be used together.\n"); - exit_program(1); - } - - avfilter_inout_free(&ofilter->out_tmp); -} - static void map_auto_video(Muxer *mux, const OptionsContext *o) { AVFormatContext *oc = mux->fc; @@ -1329,7 +1322,7 @@ static void map_auto_video(Muxer *mux, const OptionsContext *o) } } if (best_ist) - ost_add(mux, o, AVMEDIA_TYPE_VIDEO, best_ist); + ost_add(mux, o, AVMEDIA_TYPE_VIDEO, best_ist, NULL); } static void map_auto_audio(Muxer *mux, const OptionsContext *o) @@ -1371,7 +1364,7 @@ static void map_auto_audio(Muxer *mux, const OptionsContext *o) } } if (best_ist) - ost_add(mux, o, AVMEDIA_TYPE_AUDIO, best_ist); + ost_add(mux, o, AVMEDIA_TYPE_AUDIO, best_ist, NULL); } static void map_auto_subtitle(Muxer *mux, const OptionsContext *o) @@ -1406,7 +1399,7 @@ static void map_auto_subtitle(Muxer *mux, const OptionsContext *o) input_descriptor && output_descriptor && (!input_descriptor->props || !output_descriptor->props)) { - ost_add(mux, o, AVMEDIA_TYPE_SUBTITLE, ist); + ost_add(mux, o, AVMEDIA_TYPE_SUBTITLE, ist, NULL); break; } } @@ -1426,7 +1419,7 @@ static void map_auto_data(Muxer *mux, const OptionsContext *o) continue; if (ist->st->codecpar->codec_type == AVMEDIA_TYPE_DATA && ist->st->codecpar->codec_id == codec_id ) - ost_add(mux, o, AVMEDIA_TYPE_DATA, ist); + ost_add(mux, o, AVMEDIA_TYPE_DATA, ist, NULL); } } @@ -1458,7 +1451,7 @@ static void map_manual(Muxer *mux, const OptionsContext *o, const StreamMap *map "in any defined filter graph, or was already used elsewhere.\n", map->linklabel); exit_program(1); } - ost_add_from_filter(ofilter, o, mux); + ost_add(mux, o, ofilter->type, NULL, ofilter); } else { ist = input_files[map->file_index]->streams[map->stream_index]; if (ist->user_set_discard == AVDISCARD_ALL) { @@ -1490,7 +1483,7 @@ static void map_manual(Muxer *mux, const OptionsContext *o, const StreamMap *map return; } - ost_add(mux, o, ist->st->codecpar->codec_type, ist); + ost_add(mux, o, ist->st->codecpar->codec_type, ist, NULL); } } @@ -1524,7 +1517,7 @@ static void of_add_attachments(Muxer *mux, const OptionsContext *o) avio_read(pb, attachment, len); memset(attachment + len, 0, AV_INPUT_BUFFER_PADDING_SIZE); - ost = ost_add(mux, o, AVMEDIA_TYPE_ATTACHMENT, NULL); + ost = ost_add(mux, o, AVMEDIA_TYPE_ATTACHMENT, NULL, NULL); ost->attachment_filename = o->attachments[i]; ost->par_in->extradata = attachment; ost->par_in->extradata_size = len; @@ -1557,7 +1550,7 @@ static void create_streams(Muxer *mux, const OptionsContext *o) case AVMEDIA_TYPE_AUDIO: auto_disable_a = 1; break; case AVMEDIA_TYPE_SUBTITLE: auto_disable_s = 1; break; } - ost_add_from_filter(ofilter, o, mux); + ost_add(mux, o, ofilter->type, NULL, ofilter); } } From b56db2956b830cdfa887b93ff4ff8c4354891926 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Thu, 18 May 2023 13:38:09 +0200 Subject: [PATCH 1348/2172] fftools/ffmpeg: add logging for creating output streams --- fftools/ffmpeg_mux_init.c | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/fftools/ffmpeg_mux_init.c b/fftools/ffmpeg_mux_init.c index de39b360afc..033e55d76e9 100644 --- a/fftools/ffmpeg_mux_init.c +++ b/fftools/ffmpeg_mux_init.c @@ -1052,6 +1052,19 @@ static OutputStream *ost_add(Muxer *mux, const OptionsContext *o, av_strlcat(ms->log_name, "/copy", sizeof(ms->log_name)); } + av_log(ost, AV_LOG_VERBOSE, "Created %s stream from ", + av_get_media_type_string(type)); + if (ist) + av_log(ost, AV_LOG_VERBOSE, "input stream %d:%d", + ist->file_index, ist->index); + else if (ofilter) + av_log(ost, AV_LOG_VERBOSE, "complex filtergraph %d:[%s]\n", + ofilter->graph->index, ofilter->name); + else if (type == AVMEDIA_TYPE_ATTACHMENT) + av_log(ost, AV_LOG_VERBOSE, "attached file"); + else av_assert0(0); + av_log(ost, AV_LOG_VERBOSE, "\n"); + ost->pkt = av_packet_alloc(); if (!ost->pkt) report_and_exit(AVERROR(ENOMEM)); @@ -1451,6 +1464,10 @@ static void map_manual(Muxer *mux, const OptionsContext *o, const StreamMap *map "in any defined filter graph, or was already used elsewhere.\n", map->linklabel); exit_program(1); } + + av_log(mux, AV_LOG_VERBOSE, "Creating output stream from an explicitly " + "mapped complex filtergraph %d, output [%s]\n", fg->index, map->linklabel); + ost_add(mux, o, ofilter->type, NULL, ofilter); } else { ist = input_files[map->file_index]->streams[map->stream_index]; @@ -1517,6 +1534,9 @@ static void of_add_attachments(Muxer *mux, const OptionsContext *o) avio_read(pb, attachment, len); memset(attachment + len, 0, AV_INPUT_BUFFER_PADDING_SIZE); + av_log(mux, AV_LOG_VERBOSE, "Creating attachment stream from file %s\n", + o->attachments[i]); + ost = ost_add(mux, o, AVMEDIA_TYPE_ATTACHMENT, NULL, NULL); ost->attachment_filename = o->attachments[i]; ost->par_in->extradata = attachment; @@ -1550,11 +1570,21 @@ static void create_streams(Muxer *mux, const OptionsContext *o) case AVMEDIA_TYPE_AUDIO: auto_disable_a = 1; break; case AVMEDIA_TYPE_SUBTITLE: auto_disable_s = 1; break; } + + av_log(mux, AV_LOG_VERBOSE, "Creating output stream from unlabeled " + "output of complex filtergraph %d.", fg->index); + if (!o->nb_stream_maps) + av_log(mux, AV_LOG_VERBOSE, " This overrides automatic %s mapping.", + av_get_media_type_string(ofilter->type)); + av_log(mux, AV_LOG_VERBOSE, "\n"); + ost_add(mux, o, ofilter->type, NULL, ofilter); } } if (!o->nb_stream_maps) { + av_log(mux, AV_LOG_VERBOSE, "No explicit maps, mapping streams automatically...\n"); + /* pick the "best" stream of each type */ if (!auto_disable_v) map_auto_video(mux, o); @@ -1565,6 +1595,8 @@ static void create_streams(Muxer *mux, const OptionsContext *o) if (!auto_disable_d) map_auto_data(mux, o); } else { + av_log(mux, AV_LOG_VERBOSE, "Adding streams from explicit maps...\n"); + for (int i = 0; i < o->nb_stream_maps; i++) map_manual(mux, o, &o->stream_maps[i]); } From badf959ed6264ad4fce6e8e815e5dd9a5743c848 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Sun, 21 May 2023 19:09:01 +0200 Subject: [PATCH 1349/2172] fftools/ffmpeg_filter: use a dedicated variable for marking simple filtergraphs Do not use an unrelated graph property, which will change in future commits. --- fftools/ffmpeg_filter.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/fftools/ffmpeg_filter.c b/fftools/ffmpeg_filter.c index f37b867b316..e11ae2e9bf8 100644 --- a/fftools/ffmpeg_filter.c +++ b/fftools/ffmpeg_filter.c @@ -41,6 +41,8 @@ typedef struct FilterGraphPriv { FilterGraph fg; + int is_simple; + const char *graph_desc; // frame for temporarily holding output from the filtergraph @@ -353,6 +355,7 @@ FilterGraph *fg_create(char *graph_desc) int init_simple_filtergraph(InputStream *ist, OutputStream *ost) { FilterGraph *fg; + FilterGraphPriv *fgp; OutputFilter *ofilter; InputFilter *ifilter; int ret; @@ -360,6 +363,9 @@ int init_simple_filtergraph(InputStream *ist, OutputStream *ost) fg = fg_create(NULL); if (!fg) report_and_exit(AVERROR(ENOMEM)); + fgp = fgp_from_fg(fg); + + fgp->is_simple = 1; ofilter = ofilter_alloc(fg); ofilter->ost = ost; @@ -1474,7 +1480,7 @@ int ifilter_has_all_input_formats(FilterGraph *fg) int filtergraph_is_simple(FilterGraph *fg) { FilterGraphPriv *fgp = fgp_from_fg(fg); - return !fgp->graph_desc; + return fgp->is_simple; } int reap_filters(int flush) From da7ae627e1a6e0af46790b0ff1c58214ae178093 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Sun, 21 May 2023 19:16:39 +0200 Subject: [PATCH 1350/2172] fftools/ffmpeg_filter: always pass graph description to fg_create() Currently NULL would be passed for simple filtergraphs, which would make the filter code extract the graph description from the output stream when needed. This is unnecessarily convoluted. --- fftools/ffmpeg.h | 4 ++-- fftools/ffmpeg_filter.c | 8 ++++---- fftools/ffmpeg_mux.c | 1 - fftools/ffmpeg_mux_init.c | 16 ++++++++-------- 4 files changed, 14 insertions(+), 15 deletions(-) diff --git a/fftools/ffmpeg.h b/fftools/ffmpeg.h index 95334825ef2..1bb9125bf25 100644 --- a/fftools/ffmpeg.h +++ b/fftools/ffmpeg.h @@ -590,7 +590,6 @@ typedef struct OutputStream { FILE *logfile; OutputFilter *filter; - char *avfilter; AVDictionary *encoder_opts; AVDictionary *sws_dict; @@ -737,7 +736,8 @@ int parse_and_set_vsync(const char *arg, int *vsync_var, int file_idx, int st_id int configure_filtergraph(FilterGraph *fg); void check_filter_outputs(void); int filtergraph_is_simple(FilterGraph *fg); -int init_simple_filtergraph(InputStream *ist, OutputStream *ost); +int init_simple_filtergraph(InputStream *ist, OutputStream *ost, + char *graph_desc); int init_complex_filtergraph(FilterGraph *fg); void sub2video_update(InputStream *ist, int64_t heartbeat_pts, AVSubtitle *sub); diff --git a/fftools/ffmpeg_filter.c b/fftools/ffmpeg_filter.c index e11ae2e9bf8..75317139baa 100644 --- a/fftools/ffmpeg_filter.c +++ b/fftools/ffmpeg_filter.c @@ -352,7 +352,8 @@ FilterGraph *fg_create(char *graph_desc) return fg; } -int init_simple_filtergraph(InputStream *ist, OutputStream *ost) +int init_simple_filtergraph(InputStream *ist, OutputStream *ost, + char *graph_desc) { FilterGraph *fg; FilterGraphPriv *fgp; @@ -360,7 +361,7 @@ int init_simple_filtergraph(InputStream *ist, OutputStream *ost) InputFilter *ifilter; int ret; - fg = fg_create(NULL); + fg = fg_create(graph_desc); if (!fg) report_and_exit(AVERROR(ENOMEM)); fgp = fgp_from_fg(fg); @@ -1263,8 +1264,7 @@ int configure_filtergraph(FilterGraph *fg) AVBufferRef *hw_device; AVFilterInOut *inputs, *outputs, *cur; int ret, i, simple = filtergraph_is_simple(fg); - const char *graph_desc = simple ? fg->outputs[0]->ost->avfilter : - fgp->graph_desc; + const char *graph_desc = fgp->graph_desc; cleanup_filtergraph(fg); if (!(fg->graph = avfilter_graph_alloc())) diff --git a/fftools/ffmpeg_mux.c b/fftools/ffmpeg_mux.c index 36ed4820720..3da3c04d7f7 100644 --- a/fftools/ffmpeg_mux.c +++ b/fftools/ffmpeg_mux.c @@ -853,7 +853,6 @@ static void ost_free(OutputStream **post) av_freep(&ost->kf.pts); av_expr_free(ost->kf.pexpr); - av_freep(&ost->avfilter); av_freep(&ost->logfile_prefix); av_freep(&ost->apad); diff --git a/fftools/ffmpeg_mux_init.c b/fftools/ffmpeg_mux_init.c index 033e55d76e9..1c97804ec81 100644 --- a/fftools/ffmpeg_mux_init.c +++ b/fftools/ffmpeg_mux_init.c @@ -432,7 +432,7 @@ static MuxStream *mux_stream_alloc(Muxer *mux, enum AVMediaType type) } static int ost_get_filters(const OptionsContext *o, AVFormatContext *oc, - OutputStream *ost) + OutputStream *ost, char **dst) { const char *filters = NULL, *filters_script = NULL; @@ -470,12 +470,12 @@ static int ost_get_filters(const OptionsContext *o, AVFormatContext *oc, } if (filters_script) - ost->avfilter = file_read(filters_script); + *dst = file_read(filters_script); else if (filters) - ost->avfilter = av_strdup(filters); + *dst = av_strdup(filters); else - ost->avfilter = av_strdup(ost->type == AVMEDIA_TYPE_VIDEO ? "null" : "anull"); - return ost->avfilter ? 0 : AVERROR(ENOMEM); + *dst = av_strdup(ost->type == AVMEDIA_TYPE_VIDEO ? "null" : "anull"); + return *dst ? 0 : AVERROR(ENOMEM); } static void parse_matrix_coeffs(void *logctx, uint16_t *dest, const char *str) @@ -995,7 +995,7 @@ static OutputStream *ost_add(Muxer *mux, const OptionsContext *o, AVStream *st = avformat_new_stream(oc, NULL); int ret = 0; const char *bsfs = NULL, *time_base = NULL; - char *next, *codec_tag = NULL; + char *filters = NULL, *next, *codec_tag = NULL; double qscale = -1; int i; @@ -1250,7 +1250,7 @@ static OutputStream *ost_add(Muxer *mux, const OptionsContext *o, } if (type == AVMEDIA_TYPE_VIDEO || type == AVMEDIA_TYPE_AUDIO) { - ret = ost_get_filters(o, oc, ost); + ret = ost_get_filters(o, oc, ost, &filters); if (ret < 0) exit_program(1); } @@ -1262,7 +1262,7 @@ static OutputStream *ost_add(Muxer *mux, const OptionsContext *o, ofilter->ost = ost; avfilter_inout_free(&ofilter->out_tmp); } else { - ret = init_simple_filtergraph(ost->ist, ost); + ret = init_simple_filtergraph(ost->ist, ost, filters); if (ret < 0) { av_log(ost, AV_LOG_ERROR, "Error initializing a simple filtergraph\n"); From 7ea10bfef3ac103854d975553bc1d43a5e3979d3 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Sun, 21 May 2023 20:17:19 +0200 Subject: [PATCH 1351/2172] fftools/ffmpeg_filter: store just the link label in OutputFilter Not the entire AVFilterInOut. This is simpler. --- fftools/ffmpeg.h | 6 ++++-- fftools/ffmpeg_filter.c | 8 +++++--- fftools/ffmpeg_mux_init.c | 8 ++++---- 3 files changed, 13 insertions(+), 9 deletions(-) diff --git a/fftools/ffmpeg.h b/fftools/ffmpeg.h index 1bb9125bf25..3aa19c7f5fa 100644 --- a/fftools/ffmpeg.h +++ b/fftools/ffmpeg.h @@ -289,8 +289,10 @@ typedef struct OutputFilter { struct FilterGraph *graph; uint8_t *name; - /* temporary storage until stream maps are processed */ - AVFilterInOut *out_tmp; + /* for filters that are not yet bound to an output stream, + * this stores the output linklabel, if any */ + uint8_t *linklabel; + enum AVMediaType type; /* desired output stream properties */ diff --git a/fftools/ffmpeg_filter.c b/fftools/ffmpeg_filter.c index 75317139baa..323e63b8299 100644 --- a/fftools/ffmpeg_filter.c +++ b/fftools/ffmpeg_filter.c @@ -324,7 +324,7 @@ void fg_free(FilterGraph **pfg) for (int j = 0; j < fg->nb_outputs; j++) { OutputFilter *ofilter = fg->outputs[j]; - avfilter_inout_free(&ofilter->out_tmp); + av_freep(&ofilter->linklabel); av_freep(&ofilter->name); av_channel_layout_uninit(&ofilter->ch_layout); av_freep(&fg->outputs[j]); @@ -661,16 +661,18 @@ int init_complex_filtergraph(FilterGraph *fg) for (cur = outputs; cur;) { OutputFilter *const ofilter = ofilter_alloc(fg); - ofilter->out_tmp = cur; + ofilter->linklabel = cur->name; + cur->name = NULL; + ofilter->type = avfilter_pad_get_type(cur->filter_ctx->output_pads, cur->pad_idx); ofilter->name = describe_filter_link(fg, cur, 0); cur = cur->next; - ofilter->out_tmp->next = NULL; } fail: avfilter_inout_free(&inputs); + avfilter_inout_free(&outputs); avfilter_graph_free(&graph); return ret; } diff --git a/fftools/ffmpeg_mux_init.c b/fftools/ffmpeg_mux_init.c index 1c97804ec81..f7a24feec7d 100644 --- a/fftools/ffmpeg_mux_init.c +++ b/fftools/ffmpeg_mux_init.c @@ -1260,7 +1260,7 @@ static OutputStream *ost_add(Muxer *mux, const OptionsContext *o, if (ofilter) { ost->filter = ofilter; ofilter->ost = ost; - avfilter_inout_free(&ofilter->out_tmp); + av_freep(&ofilter->linklabel); } else { ret = init_simple_filtergraph(ost->ist, ost, filters); if (ret < 0) { @@ -1451,8 +1451,8 @@ static void map_manual(Muxer *mux, const OptionsContext *o, const StreamMap *map for (j = 0; j < nb_filtergraphs; j++) { fg = filtergraphs[j]; for (k = 0; k < fg->nb_outputs; k++) { - AVFilterInOut *out = fg->outputs[k]->out_tmp; - if (out && !strcmp(out->name, map->linklabel)) { + const char *linklabel = fg->outputs[k]->linklabel; + if (linklabel && !strcmp(linklabel, map->linklabel)) { ofilter = fg->outputs[k]; goto loop_end; } @@ -1562,7 +1562,7 @@ static void create_streams(Muxer *mux, const OptionsContext *o) for (int j = 0; j < fg->nb_outputs; j++) { OutputFilter *ofilter = fg->outputs[j]; - if (!ofilter->out_tmp || ofilter->out_tmp->name) + if (ofilter->linklabel || ofilter->ost) continue; switch (ofilter->type) { From 00183880aa065e97a3ec37524c802b562f83876d Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Sun, 21 May 2023 21:11:09 +0200 Subject: [PATCH 1352/2172] fftools/ffmpeg_filter: decouple allocating InputFilter and binding it to InputStream Will be useful in future commits. --- fftools/ffmpeg_filter.c | 31 ++++++++++++++++++++++--------- 1 file changed, 22 insertions(+), 9 deletions(-) diff --git a/fftools/ffmpeg_filter.c b/fftools/ffmpeg_filter.c index 323e63b8299..a8c4ef321fd 100644 --- a/fftools/ffmpeg_filter.c +++ b/fftools/ffmpeg_filter.c @@ -258,7 +258,24 @@ static OutputFilter *ofilter_alloc(FilterGraph *fg) return ofilter; } -static InputFilter *ifilter_alloc(FilterGraph *fg, InputStream *ist) +static int ifilter_bind_ist(InputFilter *ifilter, InputStream *ist) +{ + InputFilterPriv *ifp = ifp_from_ifilter(ifilter); + int ret; + + ret = ist_filter_add(ist, ifilter, filtergraph_is_simple(ifilter->graph)); + if (ret < 0) + return ret; + + ifp->ist = ist; + ifp->type_src = ist->st->codecpar->codec_type; + ifp->type = ifp->type_src == AVMEDIA_TYPE_SUBTITLE ? + AVMEDIA_TYPE_VIDEO : ifp->type_src; + + return 0; +} + +static InputFilter *ifilter_alloc(FilterGraph *fg) { InputFilterPriv *ifp = allocate_array_elem(&fg->inputs, sizeof(*ifp), &fg->nb_inputs); @@ -272,10 +289,6 @@ static InputFilter *ifilter_alloc(FilterGraph *fg, InputStream *ist) ifp->format = -1; ifp->fallback.format = -1; - ifp->ist = ist; - ifp->type_src = ist->st->codecpar->codec_type; - ifp->type = ifp->type_src == AVMEDIA_TYPE_SUBTITLE ? - AVMEDIA_TYPE_VIDEO : ifp->type_src; ifp->frame_queue = av_fifo_alloc2(8, sizeof(AVFrame*), AV_FIFO_FLAG_AUTO_GROW); if (!ifp->frame_queue) @@ -373,9 +386,9 @@ int init_simple_filtergraph(InputStream *ist, OutputStream *ost, ost->filter = ofilter; - ifilter = ifilter_alloc(fg, ist); + ifilter = ifilter_alloc(fg); - ret = ist_filter_add(ist, ifilter, 1); + ret = ifilter_bind_ist(ifilter, ist); if (ret < 0) return ret; @@ -455,10 +468,10 @@ static void init_input_filter(FilterGraph *fg, AVFilterInOut *in) } av_assert0(ist); - ifilter = ifilter_alloc(fg, ist); + ifilter = ifilter_alloc(fg); ifilter->name = describe_filter_link(fg, in, 1); - ret = ist_filter_add(ist, ifilter, 0); + ret = ifilter_bind_ist(ifilter, ist); if (ret < 0) { av_log(NULL, AV_LOG_ERROR, "Error binding an input stream to complex filtergraph input %s.\n", From a1061d4bdcbfb866011c18e787ec334ae48f2820 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Sun, 21 May 2023 20:29:59 +0200 Subject: [PATCH 1353/2172] fftools/ffmpeg_filter: move some functions higher up Needed by the following commit. --- fftools/ffmpeg_filter.c | 374 ++++++++++++++++++++-------------------- 1 file changed, 187 insertions(+), 187 deletions(-) diff --git a/fftools/ffmpeg_filter.c b/fftools/ffmpeg_filter.c index a8c4ef321fd..5169a3ca822 100644 --- a/fftools/ffmpeg_filter.c +++ b/fftools/ffmpeg_filter.c @@ -246,6 +246,193 @@ static void choose_channel_layouts(OutputFilter *ofilter, AVBPrint *bprint) av_bprint_chars(bprint, ':', 1); } +static int read_binary(const char *path, uint8_t **data, int *len) +{ + AVIOContext *io = NULL; + int64_t fsize; + int ret; + + *data = NULL; + *len = 0; + + ret = avio_open2(&io, path, AVIO_FLAG_READ, &int_cb, NULL); + if (ret < 0) { + av_log(NULL, AV_LOG_ERROR, "Cannot open file '%s': %s\n", + path, av_err2str(ret)); + return ret; + } + + fsize = avio_size(io); + if (fsize < 0 || fsize > INT_MAX) { + av_log(NULL, AV_LOG_ERROR, "Cannot obtain size of file %s\n", path); + ret = AVERROR(EIO); + goto fail; + } + + *data = av_malloc(fsize); + if (!*data) { + ret = AVERROR(ENOMEM); + goto fail; + } + + ret = avio_read(io, *data, fsize); + if (ret != fsize) { + av_log(NULL, AV_LOG_ERROR, "Error reading file %s\n", path); + ret = ret < 0 ? ret : AVERROR(EIO); + goto fail; + } + + *len = fsize; + + ret = 0; +fail: + avio_close(io); + if (ret < 0) { + av_freep(data); + *len = 0; + } + return ret; +} + +static int filter_opt_apply(AVFilterContext *f, const char *key, const char *val) +{ + const AVOption *o = NULL; + int ret; + + ret = av_opt_set(f, key, val, AV_OPT_SEARCH_CHILDREN); + if (ret >= 0) + return 0; + + if (ret == AVERROR_OPTION_NOT_FOUND && key[0] == '/') + o = av_opt_find(f, key + 1, NULL, 0, AV_OPT_SEARCH_CHILDREN); + if (!o) + goto err_apply; + + // key is a valid option name prefixed with '/' + // interpret value as a path from which to load the actual option value + key++; + + if (o->type == AV_OPT_TYPE_BINARY) { + uint8_t *data; + int len; + + ret = read_binary(val, &data, &len); + if (ret < 0) + goto err_load; + + ret = av_opt_set_bin(f, key, data, len, AV_OPT_SEARCH_CHILDREN); + av_freep(&data); + } else { + char *data = file_read(val); + if (!data) { + ret = AVERROR(EIO); + goto err_load; + } + + ret = av_opt_set(f, key, data, AV_OPT_SEARCH_CHILDREN); + av_freep(&data); + } + if (ret < 0) + goto err_apply; + + return 0; + +err_apply: + av_log(NULL, AV_LOG_ERROR, + "Error applying option '%s' to filter '%s': %s\n", + key, f->filter->name, av_err2str(ret)); + return ret; +err_load: + av_log(NULL, AV_LOG_ERROR, + "Error loading value for option '%s' from file '%s'\n", + key, val); + return ret; +} + +static int graph_opts_apply(AVFilterGraphSegment *seg) +{ + for (size_t i = 0; i < seg->nb_chains; i++) { + AVFilterChain *ch = seg->chains[i]; + + for (size_t j = 0; j < ch->nb_filters; j++) { + AVFilterParams *p = ch->filters[j]; + const AVDictionaryEntry *e = NULL; + + av_assert0(p->filter); + + while ((e = av_dict_iterate(p->opts, e))) { + int ret = filter_opt_apply(p->filter, e->key, e->value); + if (ret < 0) + return ret; + } + + av_dict_free(&p->opts); + } + } + + return 0; +} + +static int graph_parse(AVFilterGraph *graph, const char *desc, + AVFilterInOut **inputs, AVFilterInOut **outputs, + AVBufferRef *hw_device) +{ + AVFilterGraphSegment *seg; + int ret; + + *inputs = NULL; + *outputs = NULL; + + ret = avfilter_graph_segment_parse(graph, desc, 0, &seg); + if (ret < 0) + return ret; + + ret = avfilter_graph_segment_create_filters(seg, 0); + if (ret < 0) + goto fail; + + if (hw_device) { + for (int i = 0; i < graph->nb_filters; i++) { + AVFilterContext *f = graph->filters[i]; + + if (!(f->filter->flags & AVFILTER_FLAG_HWDEVICE)) + continue; + f->hw_device_ctx = av_buffer_ref(hw_device); + if (!f->hw_device_ctx) { + ret = AVERROR(ENOMEM); + goto fail; + } + } + } + + ret = graph_opts_apply(seg); + if (ret < 0) + goto fail; + + ret = avfilter_graph_segment_apply(seg, 0, inputs, outputs); + +fail: + avfilter_graph_segment_free(&seg); + return ret; +} + +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; + char *res; + + if (nb_pads > 1) + 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) + report_and_exit(AVERROR(ENOMEM)); + return res; +} + static OutputFilter *ofilter_alloc(FilterGraph *fg) { OutputFilter *ofilter; @@ -395,23 +582,6 @@ int init_simple_filtergraph(InputStream *ist, OutputStream *ost, return 0; } -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; - char *res; - - if (nb_pads > 1) - 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) - report_and_exit(AVERROR(ENOMEM)); - return res; -} - static void init_input_filter(FilterGraph *fg, AVFilterInOut *in) { FilterGraphPriv *fgp = fgp_from_fg(fg); @@ -480,176 +650,6 @@ static void init_input_filter(FilterGraph *fg, AVFilterInOut *in) } } -static int read_binary(const char *path, uint8_t **data, int *len) -{ - AVIOContext *io = NULL; - int64_t fsize; - int ret; - - *data = NULL; - *len = 0; - - ret = avio_open2(&io, path, AVIO_FLAG_READ, &int_cb, NULL); - if (ret < 0) { - av_log(NULL, AV_LOG_ERROR, "Cannot open file '%s': %s\n", - path, av_err2str(ret)); - return ret; - } - - fsize = avio_size(io); - if (fsize < 0 || fsize > INT_MAX) { - av_log(NULL, AV_LOG_ERROR, "Cannot obtain size of file %s\n", path); - ret = AVERROR(EIO); - goto fail; - } - - *data = av_malloc(fsize); - if (!*data) { - ret = AVERROR(ENOMEM); - goto fail; - } - - ret = avio_read(io, *data, fsize); - if (ret != fsize) { - av_log(NULL, AV_LOG_ERROR, "Error reading file %s\n", path); - ret = ret < 0 ? ret : AVERROR(EIO); - goto fail; - } - - *len = fsize; - - ret = 0; -fail: - avio_close(io); - if (ret < 0) { - av_freep(data); - *len = 0; - } - return ret; -} - -static int filter_opt_apply(AVFilterContext *f, const char *key, const char *val) -{ - const AVOption *o = NULL; - int ret; - - ret = av_opt_set(f, key, val, AV_OPT_SEARCH_CHILDREN); - if (ret >= 0) - return 0; - - if (ret == AVERROR_OPTION_NOT_FOUND && key[0] == '/') - o = av_opt_find(f, key + 1, NULL, 0, AV_OPT_SEARCH_CHILDREN); - if (!o) - goto err_apply; - - // key is a valid option name prefixed with '/' - // interpret value as a path from which to load the actual option value - key++; - - if (o->type == AV_OPT_TYPE_BINARY) { - uint8_t *data; - int len; - - ret = read_binary(val, &data, &len); - if (ret < 0) - goto err_load; - - ret = av_opt_set_bin(f, key, data, len, AV_OPT_SEARCH_CHILDREN); - av_freep(&data); - } else { - char *data = file_read(val); - if (!data) { - ret = AVERROR(EIO); - goto err_load; - } - - ret = av_opt_set(f, key, data, AV_OPT_SEARCH_CHILDREN); - av_freep(&data); - } - if (ret < 0) - goto err_apply; - - return 0; - -err_apply: - av_log(NULL, AV_LOG_ERROR, - "Error applying option '%s' to filter '%s': %s\n", - key, f->filter->name, av_err2str(ret)); - return ret; -err_load: - av_log(NULL, AV_LOG_ERROR, - "Error loading value for option '%s' from file '%s'\n", - key, val); - return ret; -} - -static int graph_opts_apply(AVFilterGraphSegment *seg) -{ - for (size_t i = 0; i < seg->nb_chains; i++) { - AVFilterChain *ch = seg->chains[i]; - - for (size_t j = 0; j < ch->nb_filters; j++) { - AVFilterParams *p = ch->filters[j]; - const AVDictionaryEntry *e = NULL; - - av_assert0(p->filter); - - while ((e = av_dict_iterate(p->opts, e))) { - int ret = filter_opt_apply(p->filter, e->key, e->value); - if (ret < 0) - return ret; - } - - av_dict_free(&p->opts); - } - } - - return 0; -} - -static int graph_parse(AVFilterGraph *graph, const char *desc, - AVFilterInOut **inputs, AVFilterInOut **outputs, - AVBufferRef *hw_device) -{ - AVFilterGraphSegment *seg; - int ret; - - *inputs = NULL; - *outputs = NULL; - - ret = avfilter_graph_segment_parse(graph, desc, 0, &seg); - if (ret < 0) - return ret; - - ret = avfilter_graph_segment_create_filters(seg, 0); - if (ret < 0) - goto fail; - - if (hw_device) { - for (int i = 0; i < graph->nb_filters; i++) { - AVFilterContext *f = graph->filters[i]; - - if (!(f->filter->flags & AVFILTER_FLAG_HWDEVICE)) - continue; - f->hw_device_ctx = av_buffer_ref(hw_device); - if (!f->hw_device_ctx) { - ret = AVERROR(ENOMEM); - goto fail; - } - } - } - - ret = graph_opts_apply(seg); - if (ret < 0) - goto fail; - - ret = avfilter_graph_segment_apply(seg, 0, inputs, outputs); - -fail: - avfilter_graph_segment_free(&seg); - return ret; -} - int init_complex_filtergraph(FilterGraph *fg) { FilterGraphPriv *fgp = fgp_from_fg(fg); From dc5864a00c7a7ebab3cc478e6abcadc231a68433 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Sun, 21 May 2023 22:18:57 +0200 Subject: [PATCH 1354/2172] fftools/ffmpeg_filter: create Input/OutputFilters together with FilterGraph This way the list of filtergraph inputs/outputs is always known after FilterGraph creation. This will allow treating simple and complex filtergraphs in a more uniform manner. --- fftools/ffmpeg_filter.c | 157 +++++++++++++++++++--------------------- 1 file changed, 74 insertions(+), 83 deletions(-) diff --git a/fftools/ffmpeg_filter.c b/fftools/ffmpeg_filter.c index 5169a3ca822..d74eeef52a5 100644 --- a/fftools/ffmpeg_filter.c +++ b/fftools/ffmpeg_filter.c @@ -62,6 +62,10 @@ typedef struct InputFilterPriv { // used to hold submitted input AVFrame *frame; + /* for filters that are not yet bound to an input stream, + * this stores the input linklabel, if any */ + uint8_t *linklabel; + // filter data type enum AVMediaType type; // source data type: AVMEDIA_TYPE_SUBTITLE for sub2video, @@ -456,8 +460,6 @@ static int ifilter_bind_ist(InputFilter *ifilter, InputStream *ist) ifp->ist = ist; ifp->type_src = ist->st->codecpar->codec_type; - ifp->type = ifp->type_src == AVMEDIA_TYPE_SUBTITLE ? - AVMEDIA_TYPE_VIDEO : ifp->type_src; return 0; } @@ -505,7 +507,7 @@ void fg_free(FilterGraph **pfg) av_frame_free(&frame); av_fifo_freep2(&ifp->frame_queue); } - if (ist->sub2video.sub_queue) { + if (ist && ist->sub2video.sub_queue) { AVSubtitle sub; while (av_fifo_read(ist->sub2video.sub_queue, &sub, 1) >= 0) avsubtitle_free(&sub); @@ -517,6 +519,7 @@ void fg_free(FilterGraph **pfg) av_frame_free(&ifp->frame); av_buffer_unref(&ifp->hw_frames_ctx); + av_freep(&ifp->linklabel); av_freep(&ifilter->name); av_freep(&fg->inputs[j]); } @@ -542,6 +545,10 @@ FilterGraph *fg_create(char *graph_desc) FilterGraphPriv *fgp = allocate_array_elem(&filtergraphs, sizeof(*fgp), &nb_filtergraphs); FilterGraph *fg = &fgp->fg; + AVFilterInOut *inputs, *outputs; + AVFilterGraph *graph; + int ret = 0; + fg->index = nb_filtergraphs - 1; fgp->graph_desc = graph_desc; @@ -549,6 +556,48 @@ FilterGraph *fg_create(char *graph_desc) if (!fgp->frame) report_and_exit(AVERROR(ENOMEM)); + /* this graph is only used for determining the kinds of inputs + * and outputs we have, and is discarded on exit from this function */ + graph = avfilter_graph_alloc(); + if (!graph) + report_and_exit(AVERROR(ENOMEM)); + graph->nb_threads = 1; + + ret = graph_parse(graph, fgp->graph_desc, &inputs, &outputs, NULL); + if (ret < 0) + goto fail; + + for (AVFilterInOut *cur = inputs; cur; cur = cur->next) { + InputFilter *const ifilter = ifilter_alloc(fg); + InputFilterPriv *ifp = ifp_from_ifilter(ifilter); + + ifp->linklabel = cur->name; + cur->name = NULL; + + ifp->type = avfilter_pad_get_type(cur->filter_ctx->input_pads, + cur->pad_idx); + ifilter->name = describe_filter_link(fg, cur, 1); + } + + for (AVFilterInOut *cur = outputs; cur; cur = cur->next) { + OutputFilter *const ofilter = ofilter_alloc(fg); + + ofilter->linklabel = cur->name; + cur->name = NULL; + + ofilter->type = avfilter_pad_get_type(cur->filter_ctx->output_pads, + cur->pad_idx); + ofilter->name = describe_filter_link(fg, cur, 0); + } + +fail: + avfilter_inout_free(&inputs); + avfilter_inout_free(&outputs); + avfilter_graph_free(&graph); + + if (ret < 0) + report_and_exit(ret); + return fg; } @@ -557,8 +606,6 @@ int init_simple_filtergraph(InputStream *ist, OutputStream *ost, { FilterGraph *fg; FilterGraphPriv *fgp; - OutputFilter *ofilter; - InputFilter *ifilter; int ret; fg = fg_create(graph_desc); @@ -568,26 +615,32 @@ int init_simple_filtergraph(InputStream *ist, OutputStream *ost, fgp->is_simple = 1; - ofilter = ofilter_alloc(fg); - ofilter->ost = ost; + if (fg->nb_inputs != 1 || fg->nb_outputs != 1) { + av_log(NULL, AV_LOG_ERROR, "Simple filtergraph '%s' was expected " + "to have exactly 1 input and 1 output. " + "However, it had %d input(s) and %d output(s). Please adjust, " + "or use a complex filtergraph (-filter_complex) instead.\n", + graph_desc, fg->nb_inputs, fg->nb_outputs); + return AVERROR(EINVAL); + } - ost->filter = ofilter; + fg->outputs[0]->ost = ost; - ifilter = ifilter_alloc(fg); + ost->filter = fg->outputs[0]; - ret = ifilter_bind_ist(ifilter, ist); + ret = ifilter_bind_ist(fg->inputs[0], ist); if (ret < 0) return ret; return 0; } -static void init_input_filter(FilterGraph *fg, AVFilterInOut *in) +static void init_input_filter(FilterGraph *fg, InputFilter *ifilter) { FilterGraphPriv *fgp = fgp_from_fg(fg); + InputFilterPriv *ifp = ifp_from_ifilter(ifilter); InputStream *ist = NULL; - enum AVMediaType type = avfilter_pad_get_type(in->filter_ctx->input_pads, in->pad_idx); - InputFilter *ifilter; + enum AVMediaType type = ifp->type; int i, ret; // TODO: support other filter types @@ -597,11 +650,11 @@ static void init_input_filter(FilterGraph *fg, AVFilterInOut *in) exit_program(1); } - if (in->name) { + if (ifp->linklabel) { AVFormatContext *s; AVStream *st = NULL; char *p; - int file_idx = strtol(in->name, &p, 0); + int file_idx = strtol(ifp->linklabel, &p, 0); if (file_idx < 0 || file_idx >= nb_input_files) { av_log(NULL, AV_LOG_FATAL, "Invalid file index %d in filtergraph description %s.\n", @@ -631,63 +684,27 @@ static void init_input_filter(FilterGraph *fg, AVFilterInOut *in) ist = ist_find_unused(type); if (!ist) { av_log(NULL, AV_LOG_FATAL, "Cannot find a matching stream for " - "unlabeled input pad %d on filter %s\n", in->pad_idx, - in->filter_ctx->name); + "unlabeled input pad %s\n", ifilter->name); exit_program(1); } } av_assert0(ist); - ifilter = ifilter_alloc(fg); - ifilter->name = describe_filter_link(fg, in, 1); - ret = ifilter_bind_ist(ifilter, ist); if (ret < 0) { av_log(NULL, AV_LOG_ERROR, "Error binding an input stream to complex filtergraph input %s.\n", - in->name ? in->name : ""); + ifilter->name); exit_program(1); } } int init_complex_filtergraph(FilterGraph *fg) { - FilterGraphPriv *fgp = fgp_from_fg(fg); - AVFilterInOut *inputs, *outputs, *cur; - AVFilterGraph *graph; - int ret = 0; - - /* this graph is only used for determining the kinds of inputs - * and outputs we have, and is discarded on exit from this function */ - graph = avfilter_graph_alloc(); - if (!graph) - return AVERROR(ENOMEM); - graph->nb_threads = 1; - - ret = graph_parse(graph, fgp->graph_desc, &inputs, &outputs, NULL); - if (ret < 0) - goto fail; - - for (cur = inputs; cur; cur = cur->next) - init_input_filter(fg, cur); - - for (cur = outputs; cur;) { - OutputFilter *const ofilter = ofilter_alloc(fg); - - ofilter->linklabel = cur->name; - cur->name = NULL; - - ofilter->type = avfilter_pad_get_type(cur->filter_ctx->output_pads, - cur->pad_idx); - ofilter->name = describe_filter_link(fg, cur, 0); - cur = cur->next; - } - -fail: - avfilter_inout_free(&inputs); - avfilter_inout_free(&outputs); - avfilter_graph_free(&graph); - return ret; + // bind filtergraph inputs to input streams + for (int i = 0; i < fg->nb_inputs; i++) + init_input_filter(fg, fg->inputs[i]); + return 0; } static int insert_trim(int64_t start_time, int64_t duration, @@ -1324,32 +1341,6 @@ int configure_filtergraph(FilterGraph *fg) if ((ret = graph_parse(fg->graph, graph_desc, &inputs, &outputs, hw_device)) < 0) goto fail; - if (simple && (!inputs || inputs->next || !outputs || outputs->next)) { - const char *num_inputs; - const char *num_outputs; - if (!outputs) { - num_outputs = "0"; - } else if (outputs->next) { - num_outputs = ">1"; - } else { - num_outputs = "1"; - } - if (!inputs) { - num_inputs = "0"; - } else if (inputs->next) { - num_inputs = ">1"; - } else { - num_inputs = "1"; - } - av_log(NULL, AV_LOG_ERROR, "Simple filtergraph '%s' was expected " - "to have exactly 1 input and 1 output." - " However, it had %s input(s) and %s output(s)." - " Please adjust, or use a complex filtergraph (-filter_complex) instead.\n", - graph_desc, num_inputs, num_outputs); - ret = AVERROR(EINVAL); - goto fail; - } - for (cur = inputs, i = 0; cur; cur = cur->next, i++) if ((ret = configure_input_filter(fg, fg->inputs[i], cur)) < 0) { avfilter_inout_free(&inputs); From 87b576135e4b647ed5e434dd0d6acd09538f915e Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Sun, 21 May 2023 22:33:13 +0200 Subject: [PATCH 1355/2172] fftools/ffmpeg_filter: factor out binding an output stream to OutputFilter While the new function is trivial for now, it will become more useful in future commits. --- fftools/ffmpeg.h | 2 ++ fftools/ffmpeg_filter.c | 10 ++++++++-- fftools/ffmpeg_mux_init.c | 3 +-- 3 files changed, 11 insertions(+), 4 deletions(-) diff --git a/fftools/ffmpeg.h b/fftools/ffmpeg.h index 3aa19c7f5fa..8c149f1f959 100644 --- a/fftools/ffmpeg.h +++ b/fftools/ffmpeg.h @@ -756,6 +756,8 @@ int ifilter_parameters_from_dec(InputFilter *ifilter, const AVCodecContext *dec) int ifilter_has_all_input_formats(FilterGraph *fg); +void ofilter_bind_ost(OutputFilter *ofilter, OutputStream *ost); + /** * Create a new filtergraph in the global filtergraph list. * diff --git a/fftools/ffmpeg_filter.c b/fftools/ffmpeg_filter.c index d74eeef52a5..5f77f1e00f2 100644 --- a/fftools/ffmpeg_filter.c +++ b/fftools/ffmpeg_filter.c @@ -464,6 +464,12 @@ static int ifilter_bind_ist(InputFilter *ifilter, InputStream *ist) return 0; } +void ofilter_bind_ost(OutputFilter *ofilter, OutputStream *ost) +{ + ofilter->ost = ost; + av_freep(&ofilter->linklabel); +} + static InputFilter *ifilter_alloc(FilterGraph *fg) { InputFilterPriv *ifp = allocate_array_elem(&fg->inputs, sizeof(*ifp), @@ -624,14 +630,14 @@ int init_simple_filtergraph(InputStream *ist, OutputStream *ost, return AVERROR(EINVAL); } - fg->outputs[0]->ost = ost; - ost->filter = fg->outputs[0]; ret = ifilter_bind_ist(fg->inputs[0], ist); if (ret < 0) return ret; + ofilter_bind_ost(fg->outputs[0], ost); + return 0; } diff --git a/fftools/ffmpeg_mux_init.c b/fftools/ffmpeg_mux_init.c index f7a24feec7d..99708b96213 100644 --- a/fftools/ffmpeg_mux_init.c +++ b/fftools/ffmpeg_mux_init.c @@ -1259,8 +1259,7 @@ static OutputStream *ost_add(Muxer *mux, const OptionsContext *o, (type == AVMEDIA_TYPE_VIDEO || type == AVMEDIA_TYPE_AUDIO)) { if (ofilter) { ost->filter = ofilter; - ofilter->ost = ost; - av_freep(&ofilter->linklabel); + ofilter_bind_ost(ofilter, ost); } else { ret = init_simple_filtergraph(ost->ist, ost, filters); if (ret < 0) { From 7520cd9f07293259759783ba003d3aa1a87b17c2 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Sun, 21 May 2023 22:46:59 +0200 Subject: [PATCH 1356/2172] fftools/ffmpeg_mux_init: move OutputFilter setup code to ffmpeg_filter That is a more appropriate place for it. --- fftools/ffmpeg_filter.c | 70 +++++++++++++++++++++++++++++++++++ fftools/ffmpeg_mux_init.c | 77 --------------------------------------- 2 files changed, 70 insertions(+), 77 deletions(-) diff --git a/fftools/ffmpeg_filter.c b/fftools/ffmpeg_filter.c index 5f77f1e00f2..3f6b906468a 100644 --- a/fftools/ffmpeg_filter.c +++ b/fftools/ffmpeg_filter.c @@ -464,10 +464,80 @@ static int ifilter_bind_ist(InputFilter *ifilter, InputStream *ist) return 0; } +static void set_channel_layout(OutputFilter *f, OutputStream *ost) +{ + const AVCodec *c = ost->enc_ctx->codec; + int i, err; + + if (ost->enc_ctx->ch_layout.order != AV_CHANNEL_ORDER_UNSPEC) { + /* Pass the layout through for all orders but UNSPEC */ + err = av_channel_layout_copy(&f->ch_layout, &ost->enc_ctx->ch_layout); + if (err < 0) + report_and_exit(AVERROR(ENOMEM)); + return; + } + + /* Requested layout is of order UNSPEC */ + if (!c->ch_layouts) { + /* Use the default native layout for the requested amount of channels when the + encoder doesn't have a list of supported layouts */ + av_channel_layout_default(&f->ch_layout, ost->enc_ctx->ch_layout.nb_channels); + return; + } + /* Encoder has a list of supported layouts. Pick the first layout in it with the + same amount of channels as the requested layout */ + for (i = 0; c->ch_layouts[i].nb_channels; i++) { + if (c->ch_layouts[i].nb_channels == ost->enc_ctx->ch_layout.nb_channels) + break; + } + if (c->ch_layouts[i].nb_channels) { + /* Use it if one is found */ + err = av_channel_layout_copy(&f->ch_layout, &c->ch_layouts[i]); + if (err < 0) + report_and_exit(AVERROR(ENOMEM)); + return; + } + /* If no layout for the amount of channels requested was found, use the default + native layout for it. */ + av_channel_layout_default(&f->ch_layout, ost->enc_ctx->ch_layout.nb_channels); +} + void ofilter_bind_ost(OutputFilter *ofilter, OutputStream *ost) { + const AVCodec *c = ost->enc_ctx->codec; + ofilter->ost = ost; av_freep(&ofilter->linklabel); + + switch (ost->enc_ctx->codec_type) { + case AVMEDIA_TYPE_VIDEO: + ofilter->frame_rate = ost->frame_rate; + ofilter->width = ost->enc_ctx->width; + ofilter->height = ost->enc_ctx->height; + if (ost->enc_ctx->pix_fmt != AV_PIX_FMT_NONE) { + ofilter->format = ost->enc_ctx->pix_fmt; + } else { + ofilter->formats = c->pix_fmts; + } + break; + case AVMEDIA_TYPE_AUDIO: + if (ost->enc_ctx->sample_fmt != AV_SAMPLE_FMT_NONE) { + ofilter->format = ost->enc_ctx->sample_fmt; + } else { + ofilter->formats = c->sample_fmts; + } + if (ost->enc_ctx->sample_rate) { + ofilter->sample_rate = ost->enc_ctx->sample_rate; + } else { + ofilter->sample_rates = c->supported_samplerates; + } + if (ost->enc_ctx->ch_layout.nb_channels) { + set_channel_layout(ofilter, ost); + } else if (c->ch_layouts) { + ofilter->ch_layouts = c->ch_layouts; + } + break; + } } static InputFilter *ifilter_alloc(FilterGraph *fg) diff --git a/fftools/ffmpeg_mux_init.c b/fftools/ffmpeg_mux_init.c index 99708b96213..4fc6f0fb46a 100644 --- a/fftools/ffmpeg_mux_init.c +++ b/fftools/ffmpeg_mux_init.c @@ -1886,44 +1886,6 @@ static void of_add_metadata(OutputFile *of, AVFormatContext *oc, } } -static void set_channel_layout(OutputFilter *f, OutputStream *ost) -{ - const AVCodec *c = ost->enc_ctx->codec; - int i, err; - - if (ost->enc_ctx->ch_layout.order != AV_CHANNEL_ORDER_UNSPEC) { - /* Pass the layout through for all orders but UNSPEC */ - err = av_channel_layout_copy(&f->ch_layout, &ost->enc_ctx->ch_layout); - if (err < 0) - report_and_exit(AVERROR(ENOMEM)); - return; - } - - /* Requested layout is of order UNSPEC */ - if (!c->ch_layouts) { - /* Use the default native layout for the requested amount of channels when the - encoder doesn't have a list of supported layouts */ - av_channel_layout_default(&f->ch_layout, ost->enc_ctx->ch_layout.nb_channels); - return; - } - /* Encoder has a list of supported layouts. Pick the first layout in it with the - same amount of channels as the requested layout */ - for (i = 0; c->ch_layouts[i].nb_channels; i++) { - if (c->ch_layouts[i].nb_channels == ost->enc_ctx->ch_layout.nb_channels) - break; - } - if (c->ch_layouts[i].nb_channels) { - /* Use it if one is found */ - err = av_channel_layout_copy(&f->ch_layout, &c->ch_layouts[i]); - if (err < 0) - report_and_exit(AVERROR(ENOMEM)); - return; - } - /* If no layout for the amount of channels requested was found, use the default - native layout for it. */ - av_channel_layout_default(&f->ch_layout, ost->enc_ctx->ch_layout.nb_channels); -} - static int copy_chapters(InputFile *ifile, OutputFile *ofile, AVFormatContext *os, int copy_metadata) { @@ -2458,45 +2420,6 @@ int of_open(const OptionsContext *o, const char *filename) /* check if all codec options have been used */ validate_enc_avopt(mux, o->g->codec_opts); - for (int i = 0; i < of->nb_streams; i++) { - OutputStream *ost = of->streams[i]; - - /* set the filter output constraints */ - if (ost->filter) { - const AVCodec *c = ost->enc_ctx->codec; - OutputFilter *f = ost->filter; - switch (ost->enc_ctx->codec_type) { - case AVMEDIA_TYPE_VIDEO: - f->frame_rate = ost->frame_rate; - f->width = ost->enc_ctx->width; - f->height = ost->enc_ctx->height; - if (ost->enc_ctx->pix_fmt != AV_PIX_FMT_NONE) { - f->format = ost->enc_ctx->pix_fmt; - } else { - f->formats = c->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 { - f->formats = c->sample_fmts; - } - if (ost->enc_ctx->sample_rate) { - f->sample_rate = ost->enc_ctx->sample_rate; - } else { - f->sample_rates = c->supported_samplerates; - } - if (ost->enc_ctx->ch_layout.nb_channels) { - set_channel_layout(f, ost); - } else if (c->ch_layouts) { - f->ch_layouts = c->ch_layouts; - } - break; - } - } - } - /* check filename in case of an image number is expected */ if (oc->oformat->flags & AVFMT_NEEDNUMBER && !av_filename_number_test(oc->url)) { av_log(mux, AV_LOG_FATAL, From ad4efb91586dc4918121d96030d247be6af630c1 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Sun, 21 May 2023 23:18:29 +0200 Subject: [PATCH 1357/2172] fftools/ffmpeg_filter: try to configure filtergraphs earlier When the filtergraph has no inputs, it can be configured immediately when all its outputs are bound to output streams. This will simplify treating some corner cases. --- fftools/ffmpeg_filter.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/fftools/ffmpeg_filter.c b/fftools/ffmpeg_filter.c index 3f6b906468a..3bf1862ab6e 100644 --- a/fftools/ffmpeg_filter.c +++ b/fftools/ffmpeg_filter.c @@ -504,6 +504,7 @@ static void set_channel_layout(OutputFilter *f, OutputStream *ost) void ofilter_bind_ost(OutputFilter *ofilter, OutputStream *ost) { + FilterGraph *fg = ofilter->graph; const AVCodec *c = ost->enc_ctx->codec; ofilter->ost = ost; @@ -538,6 +539,23 @@ void ofilter_bind_ost(OutputFilter *ofilter, OutputStream *ost) } break; } + + // if we have all input parameters and all outputs are bound, + // the graph can now be configured + if (ifilter_has_all_input_formats(fg)) { + int ret; + + for (int i = 0; i < fg->nb_outputs; i++) + if (!fg->outputs[i]->ost) + return; + + ret = configure_filtergraph(fg); + if (ret < 0) { + av_log(NULL, AV_LOG_ERROR, "Error configuring filter graph: %s\n", + av_err2str(ret)); + exit_program(1); + } + } } static InputFilter *ifilter_alloc(FilterGraph *fg) From 3d35b73b2a40b9e99724401d6390750e2bc65318 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Tue, 23 May 2023 12:50:19 +0200 Subject: [PATCH 1358/2172] fftools/ffmpeg: constify AVSubtitle parameters as appropriate --- fftools/ffmpeg.c | 5 +++-- fftools/ffmpeg.h | 3 ++- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/fftools/ffmpeg.c b/fftools/ffmpeg.c index 0539a458564..9c68add0a4e 100644 --- a/fftools/ffmpeg.c +++ b/fftools/ffmpeg.c @@ -211,7 +211,8 @@ static void sub2video_push_ref(InputStream *ist, int64_t pts) } } -void sub2video_update(InputStream *ist, int64_t heartbeat_pts, AVSubtitle *sub) +void sub2video_update(InputStream *ist, int64_t heartbeat_pts, + const AVSubtitle *sub) { AVFrame *frame = ist->sub2video.frame; int8_t *dst; @@ -754,7 +755,7 @@ static void print_report(int is_last_report, int64_t timer_start, int64_t cur_ti first_report = 0; } -static int copy_av_subtitle(AVSubtitle *dst, AVSubtitle *src) +static int copy_av_subtitle(AVSubtitle *dst, const AVSubtitle *src) { int ret = AVERROR_BUG; AVSubtitle tmp = { diff --git a/fftools/ffmpeg.h b/fftools/ffmpeg.h index 8c149f1f959..451d18db6f3 100644 --- a/fftools/ffmpeg.h +++ b/fftools/ffmpeg.h @@ -742,7 +742,8 @@ int init_simple_filtergraph(InputStream *ist, OutputStream *ost, char *graph_desc); int init_complex_filtergraph(FilterGraph *fg); -void sub2video_update(InputStream *ist, int64_t heartbeat_pts, AVSubtitle *sub); +void sub2video_update(InputStream *ist, int64_t heartbeat_pts, + const AVSubtitle *sub); int ifilter_send_frame(InputFilter *ifilter, AVFrame *frame, int keep_reference); int ifilter_send_eof(InputFilter *ifilter, int64_t pts, AVRational tb); From 5d530e3a7286df72026f77f7b02f4cf7f083f57c Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Tue, 23 May 2023 13:00:12 +0200 Subject: [PATCH 1359/2172] fftools/ffmpeg_dec: move sub2video submission to ffmpeg_filter This code is a sub2video analogue of ifilter_send_frame(), so it properly belongs to the filtering code. Note that using sub2video with more than one target for a given input subtitle stream is currently broken and this commit does not change that. It will be addressed in following commits. --- fftools/ffmpeg.c | 2 +- fftools/ffmpeg.h | 2 ++ fftools/ffmpeg_dec.c | 23 ++++++++--------------- fftools/ffmpeg_filter.c | 30 ++++++++++++++++++++++++++++++ 4 files changed, 41 insertions(+), 16 deletions(-) diff --git a/fftools/ffmpeg.c b/fftools/ffmpeg.c index 9c68add0a4e..9ee16ee8e0e 100644 --- a/fftools/ffmpeg.c +++ b/fftools/ffmpeg.c @@ -755,7 +755,7 @@ static void print_report(int is_last_report, int64_t timer_start, int64_t cur_ti first_report = 0; } -static int copy_av_subtitle(AVSubtitle *dst, const AVSubtitle *src) +int copy_av_subtitle(AVSubtitle *dst, const AVSubtitle *src) { int ret = AVERROR_BUG; AVSubtitle tmp = { diff --git a/fftools/ffmpeg.h b/fftools/ffmpeg.h index 451d18db6f3..fa5824ee7b5 100644 --- a/fftools/ffmpeg.h +++ b/fftools/ffmpeg.h @@ -744,9 +744,11 @@ int init_complex_filtergraph(FilterGraph *fg); void sub2video_update(InputStream *ist, int64_t heartbeat_pts, const AVSubtitle *sub); +int copy_av_subtitle(AVSubtitle *dst, const AVSubtitle *src); int ifilter_send_frame(InputFilter *ifilter, AVFrame *frame, int keep_reference); int ifilter_send_eof(InputFilter *ifilter, int64_t pts, AVRational tb); +int ifilter_sub2video(InputFilter *ifilter, const AVSubtitle *sub); /** * Set up fallback filtering parameters from a decoder context. They will only diff --git a/fftools/ffmpeg_dec.c b/fftools/ffmpeg_dec.c index c89630512a1..a7acaf67c2d 100644 --- a/fftools/ffmpeg_dec.c +++ b/fftools/ffmpeg_dec.c @@ -336,7 +336,6 @@ static void sub2video_flush(InputStream *ist) int process_subtitle(InputStream *ist, AVSubtitle *subtitle, int *got_output) { int ret = 0; - int free_sub = 1; if (ist->fix_sub_duration) { int end = 1; @@ -361,18 +360,13 @@ int process_subtitle(InputStream *ist, AVSubtitle *subtitle, int *got_output) if (!*got_output) return ret; - if (ist->sub2video.frame) { - sub2video_update(ist, INT64_MIN, subtitle); - } else if (ist->nb_filters) { - if (!ist->sub2video.sub_queue) - ist->sub2video.sub_queue = av_fifo_alloc2(8, sizeof(AVSubtitle), AV_FIFO_FLAG_AUTO_GROW); - if (!ist->sub2video.sub_queue) - report_and_exit(AVERROR(ENOMEM)); - - ret = av_fifo_write(ist->sub2video.sub_queue, subtitle, 1); - if (ret < 0) - exit_program(1); - free_sub = 0; + for (int i = 0; i < ist->nb_filters; i++) { + ret = ifilter_sub2video(ist->filters[i], subtitle); + if (ret < 0) { + av_log(ist, AV_LOG_ERROR, "Error sending a subtitle for filtering: %s\n", + av_err2str(ret)); + goto out; + } } if (!subtitle->num_rects) @@ -387,8 +381,7 @@ int process_subtitle(InputStream *ist, AVSubtitle *subtitle, int *got_output) } out: - if (free_sub) - avsubtitle_free(subtitle); + avsubtitle_free(subtitle); return ret; } diff --git a/fftools/ffmpeg_filter.c b/fftools/ffmpeg_filter.c index 3bf1862ab6e..acfd83244be 100644 --- a/fftools/ffmpeg_filter.c +++ b/fftools/ffmpeg_filter.c @@ -1638,6 +1638,36 @@ int reap_filters(int flush) return 0; } +int ifilter_sub2video(InputFilter *ifilter, const AVSubtitle *subtitle) +{ + InputFilterPriv *ifp = ifp_from_ifilter(ifilter); + InputStream *ist = ifp->ist; + int ret; + + if (ist->sub2video.frame) { + sub2video_update(ist, INT64_MIN, subtitle); + } else { + AVSubtitle sub; + + if (!ist->sub2video.sub_queue) + ist->sub2video.sub_queue = av_fifo_alloc2(8, sizeof(AVSubtitle), AV_FIFO_FLAG_AUTO_GROW); + if (!ist->sub2video.sub_queue) + return AVERROR(ENOMEM); + + ret = copy_av_subtitle(&sub, subtitle); + if (ret < 0) + return ret; + + ret = av_fifo_write(ist->sub2video.sub_queue, &sub, 1); + if (ret < 0) { + avsubtitle_free(&sub); + return ret; + } + } + + return 0; +} + int ifilter_send_eof(InputFilter *ifilter, int64_t pts, AVRational tb) { InputFilterPriv *ifp = ifp_from_ifilter(ifilter); From a6d67b11f5b83b72d1df37a88c864dc854374488 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Tue, 23 May 2023 13:07:57 +0200 Subject: [PATCH 1360/2172] fftools/ffmpeg_filter: move sub2video subtitle queue to InputFilterPriv This queue should be associated with a specific filtergraph input - if a subtitle stream is sent to multiple filters then each should have its own queue. --- fftools/ffmpeg.h | 1 - fftools/ffmpeg_filter.c | 26 +++++++++++++++----------- 2 files changed, 15 insertions(+), 12 deletions(-) diff --git a/fftools/ffmpeg.h b/fftools/ffmpeg.h index fa5824ee7b5..d4aff5cc7c5 100644 --- a/fftools/ffmpeg.h +++ b/fftools/ffmpeg.h @@ -374,7 +374,6 @@ typedef struct InputStream { struct sub2video { int64_t last_pts; int64_t end_pts; - AVFifo *sub_queue; ///< queue of AVSubtitle* before filter init AVFrame *frame; int w, h; unsigned int initialize; ///< marks if sub2video_update should force an initialization diff --git a/fftools/ffmpeg_filter.c b/fftools/ffmpeg_filter.c index acfd83244be..2a73e3a3e32 100644 --- a/fftools/ffmpeg_filter.c +++ b/fftools/ffmpeg_filter.c @@ -104,6 +104,10 @@ typedef struct InputFilterPriv { AVChannelLayout ch_layout; } fallback; + struct { + ///< queue of AVSubtitle* before filter init + AVFifo *queue; + } sub2video; } InputFilterPriv; static InputFilterPriv *ifp_from_ifilter(InputFilter *ifilter) @@ -593,7 +597,6 @@ void fg_free(FilterGraph **pfg) for (int j = 0; j < fg->nb_inputs; j++) { InputFilter *ifilter = fg->inputs[j]; InputFilterPriv *ifp = ifp_from_ifilter(ifilter); - InputStream *ist = ifp->ist; if (ifp->frame_queue) { AVFrame *frame; @@ -601,11 +604,11 @@ void fg_free(FilterGraph **pfg) av_frame_free(&frame); av_fifo_freep2(&ifp->frame_queue); } - if (ist && ist->sub2video.sub_queue) { + if (ifp->sub2video.queue) { AVSubtitle sub; - while (av_fifo_read(ist->sub2video.sub_queue, &sub, 1) >= 0) + while (av_fifo_read(ifp->sub2video.queue, &sub, 1) >= 0) avsubtitle_free(&sub); - av_fifo_freep2(&ist->sub2video.sub_queue); + av_fifo_freep2(&ifp->sub2video.queue); } av_channel_layout_uninit(&ifp->fallback.ch_layout); @@ -1495,10 +1498,11 @@ int configure_filtergraph(FilterGraph *fg) /* process queued up subtitle packets */ for (i = 0; i < fg->nb_inputs; i++) { - InputStream *ist = ifp_from_ifilter(fg->inputs[i])->ist; - if (ist->sub2video.sub_queue && ist->sub2video.frame) { + InputFilterPriv *ifp = ifp_from_ifilter(fg->inputs[i]); + InputStream *ist = ifp->ist; + if (ifp->sub2video.queue && ist->sub2video.frame) { AVSubtitle tmp; - while (av_fifo_read(ist->sub2video.sub_queue, &tmp, 1) >= 0) { + while (av_fifo_read(ifp->sub2video.queue, &tmp, 1) >= 0) { sub2video_update(ist, INT64_MIN, &tmp); avsubtitle_free(&tmp); } @@ -1649,16 +1653,16 @@ int ifilter_sub2video(InputFilter *ifilter, const AVSubtitle *subtitle) } else { AVSubtitle sub; - if (!ist->sub2video.sub_queue) - ist->sub2video.sub_queue = av_fifo_alloc2(8, sizeof(AVSubtitle), AV_FIFO_FLAG_AUTO_GROW); - if (!ist->sub2video.sub_queue) + if (!ifp->sub2video.queue) + ifp->sub2video.queue = av_fifo_alloc2(8, sizeof(AVSubtitle), AV_FIFO_FLAG_AUTO_GROW); + if (!ifp->sub2video.queue) return AVERROR(ENOMEM); ret = copy_av_subtitle(&sub, subtitle); if (ret < 0) return ret; - ret = av_fifo_write(ist->sub2video.sub_queue, &sub, 1); + ret = av_fifo_write(ifp->sub2video.queue, &sub, 1); if (ret < 0) { avsubtitle_free(&sub); return ret; From ea5c39cef624c7bb636145052ea42ef789dae7ed Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Tue, 23 May 2023 20:55:01 +0200 Subject: [PATCH 1361/2172] fftools/ffmpeg: tweak sub2video_heartbeat() arguments This function should not take an InputStream, as it only uses it to get the InputFile and the timebase. Pass those directly instead and avoid confusion over dealing with multiple InputStreams. --- fftools/ffmpeg.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/fftools/ffmpeg.c b/fftools/ffmpeg.c index 9ee16ee8e0e..4624960c171 100644 --- a/fftools/ffmpeg.c +++ b/fftools/ffmpeg.c @@ -252,9 +252,8 @@ void sub2video_update(InputStream *ist, int64_t heartbeat_pts, ist->sub2video.initialize = 0; } -static void sub2video_heartbeat(InputStream *ist, int64_t pts) +static void sub2video_heartbeat(InputFile *infile, int64_t pts, AVRational tb) { - InputFile *infile = input_files[ist->file_index]; int i, j, nb_reqs; int64_t pts2; @@ -268,7 +267,7 @@ static void sub2video_heartbeat(InputStream *ist, int64_t pts) continue; /* subtitles seem to be usually muxed ahead of other streams; if not, subtracting a larger time here is necessary */ - pts2 = av_rescale_q(pts, ist->st->time_base, ist2->st->time_base) - 1; + pts2 = av_rescale_q(pts, tb, ist2->st->time_base) - 1; /* do not send the heartbeat frame if the subtitle is already ahead */ if (pts2 <= ist2->sub2video.last_pts) continue; @@ -1231,7 +1230,7 @@ static int process_input(int file_index) ist = ifile->streams[pkt->stream_index]; - sub2video_heartbeat(ist, pkt->pts); + sub2video_heartbeat(ifile, pkt->pts, pkt->time_base); process_input_packet(ist, pkt, 0); From 20cacfe4936a8d5b643421b5ca93bb098f6b76dd Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Tue, 23 May 2023 22:54:23 +0200 Subject: [PATCH 1362/2172] fftools/ffmpeg: rework setting sub2video parameters Set them in ifilter_parameters_from_dec(), similarly to audio/video streams. This reduces the extent to which sub2video filters need to be treated specially. --- fftools/ffmpeg.c | 6 ++--- fftools/ffmpeg_demux.c | 21 +++++++++++++++ fftools/ffmpeg_filter.c | 58 ++++++++++++----------------------------- 3 files changed, 41 insertions(+), 44 deletions(-) diff --git a/fftools/ffmpeg.c b/fftools/ffmpeg.c index 4624960c171..e9e60407d29 100644 --- a/fftools/ffmpeg.c +++ b/fftools/ffmpeg.c @@ -153,9 +153,9 @@ static int sub2video_get_blank_frame(InputStream *ist) AVFrame *frame = ist->sub2video.frame; av_frame_unref(frame); - ist->sub2video.frame->width = ist->dec_ctx->width ? ist->dec_ctx->width : ist->sub2video.w; - ist->sub2video.frame->height = ist->dec_ctx->height ? ist->dec_ctx->height : ist->sub2video.h; - ist->sub2video.frame->format = AV_PIX_FMT_RGB32; + frame->width = ist->sub2video.w; + frame->height = ist->sub2video.h; + frame->format = AV_PIX_FMT_RGB32; if ((ret = av_frame_get_buffer(frame, 0)) < 0) return ret; memset(frame->data[0], 0, frame->height * frame->linesize[0]); diff --git a/fftools/ffmpeg_demux.c b/fftools/ffmpeg_demux.c index 561b4b00021..817ccbbedc0 100644 --- a/fftools/ffmpeg_demux.c +++ b/fftools/ffmpeg_demux.c @@ -1228,6 +1228,27 @@ static void add_input_streams(const OptionsContext *o, Demuxer *d) av_log(ist, AV_LOG_FATAL, "Invalid canvas size: %s.\n", canvas_size); exit_program(1); } + + /* Compute the size of the canvas for the subtitles stream. + If the subtitles codecpar has set a size, use it. Otherwise use the + maximum dimensions of the video streams in the same file. */ + ist->sub2video.w = ist->dec_ctx->width; + ist->sub2video.h = ist->dec_ctx->height; + if (!(ist->sub2video.w && ist->sub2video.h)) { + for (int j = 0; j < ic->nb_streams; j++) { + AVCodecParameters *par1 = ic->streams[j]->codecpar; + if (par1->codec_type == AVMEDIA_TYPE_VIDEO) { + ist->sub2video.w = FFMAX(ist->sub2video.w, par1->width); + ist->sub2video.h = FFMAX(ist->sub2video.h, par1->height); + } + } + } + + if (!(ist->sub2video.w && ist->sub2video.h)) { + ist->sub2video.w = FFMAX(ist->sub2video.w, 720); + ist->sub2video.h = FFMAX(ist->sub2video.h, 576); + } + break; } case AVMEDIA_TYPE_ATTACHMENT: diff --git a/fftools/ffmpeg_filter.c b/fftools/ffmpeg_filter.c index 2a73e3a3e32..4b5ccf50bd1 100644 --- a/fftools/ffmpeg_filter.c +++ b/fftools/ffmpeg_filter.c @@ -458,13 +458,13 @@ static int ifilter_bind_ist(InputFilter *ifilter, InputStream *ist) InputFilterPriv *ifp = ifp_from_ifilter(ifilter); int ret; + ifp->ist = ist; + ifp->type_src = ist->st->codecpar->codec_type; + ret = ist_filter_add(ist, ifilter, filtergraph_is_simple(ifilter->graph)); if (ret < 0) return ret; - ifp->ist = ist; - ifp->type_src = ist->st->codecpar->codec_type; - return 0; } @@ -1110,38 +1110,6 @@ void check_filter_outputs(void) static int sub2video_prepare(InputStream *ist, InputFilter *ifilter) { - InputFilterPriv *ifp = ifp_from_ifilter(ifilter); - AVFormatContext *avf = input_files[ist->file_index]->ctx; - int i, w, h; - - /* Compute the size of the canvas for the subtitles stream. - If the subtitles codecpar has set a size, use it. Otherwise use the - maximum dimensions of the video streams in the same file. */ - w = ifp->width; - h = ifp->height; - if (!(w && h)) { - for (i = 0; i < avf->nb_streams; i++) { - if (avf->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) { - w = FFMAX(w, avf->streams[i]->codecpar->width); - h = FFMAX(h, avf->streams[i]->codecpar->height); - } - } - if (!(w && h)) { - w = FFMAX(w, 720); - h = FFMAX(h, 576); - } - av_log(avf, AV_LOG_INFO, "sub2video: using %dx%d canvas\n", w, h); - } - ist->sub2video.w = ifp->width = w; - ist->sub2video.h = ifp->height = h; - - ifp->width = ist->dec_ctx->width ? ist->dec_ctx->width : ist->sub2video.w; - ifp->height = ist->dec_ctx->height ? ist->dec_ctx->height : ist->sub2video.h; - - /* rectangles are AV_PIX_FMT_PAL8, but we have no guarantee that the - palettes for all rectangles are identical or compatible */ - ifp->format = AV_PIX_FMT_RGB32; - ist->sub2video.frame = av_frame_alloc(); if (!ist->sub2video.frame) return AVERROR(ENOMEM); @@ -1525,7 +1493,7 @@ int ifilter_parameters_from_dec(InputFilter *ifilter, const AVCodecContext *dec) ifp->fallback.width = dec->width; ifp->fallback.height = dec->height; ifp->fallback.sample_aspect_ratio = dec->sample_aspect_ratio; - } else { + } else if (dec->codec_type == AVMEDIA_TYPE_AUDIO) { int ret; ifp->fallback.format = dec->sample_fmt; @@ -1534,6 +1502,17 @@ int ifilter_parameters_from_dec(InputFilter *ifilter, const AVCodecContext *dec) ret = av_channel_layout_copy(&ifp->fallback.ch_layout, &dec->ch_layout); if (ret < 0) return ret; + } else { + // for subtitles (i.e. sub2video) we set the actual parameters, + // rather than just fallback + ifp->width = ifp->ist->sub2video.w; + ifp->height = ifp->ist->sub2video.h; + + /* rectangles are AV_PIX_FMT_PAL8, but we have no guarantee that the + palettes for all rectangles are identical or compatible */ + ifp->format = AV_PIX_FMT_RGB32; + + av_log(NULL, AV_LOG_VERBOSE, "sub2video: using %dx%d canvas\n", ifp->width, ifp->height); } return 0; @@ -1574,8 +1553,7 @@ int ifilter_has_all_input_formats(FilterGraph *fg) int i; for (i = 0; i < fg->nb_inputs; i++) { InputFilterPriv *ifp = ifp_from_ifilter(fg->inputs[i]); - if (ifp->format < 0 && (ifp->type_src == AVMEDIA_TYPE_AUDIO || - ifp->type_src == AVMEDIA_TYPE_VIDEO)) + if (ifp->format < 0) return 0; } return 1; @@ -1709,9 +1687,7 @@ int ifilter_send_eof(InputFilter *ifilter, int64_t pts, AVRational tb) } } - if (ifp->format < 0 && - (ifp->type_src == AVMEDIA_TYPE_AUDIO || - ifp->type_src == AVMEDIA_TYPE_VIDEO)) { + if (ifp->format < 0) { av_log(NULL, AV_LOG_ERROR, "Cannot determine format of input stream %d:%d after EOF\n", ifp->ist->file_index, ifp->ist->index); From f8abab673c5494d0fc120e2d27f0e5d49ae3d285 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Wed, 24 May 2023 10:08:33 +0200 Subject: [PATCH 1363/2172] fftools/ffmpeg: move sub2video handling to ffmpeg_filter Make all relevant state per-filtergraph input, rather than per-input stream. Refactor the code to make it work and avoid leaking memory when a single subtitle stream is sent to multiple filters. --- fftools/ffmpeg.c | 133 ++-------------------------- fftools/ffmpeg.h | 7 +- fftools/ffmpeg_dec.c | 9 +- fftools/ffmpeg_demux.c | 1 - fftools/ffmpeg_filter.c | 189 +++++++++++++++++++++++++++++++++++----- 5 files changed, 177 insertions(+), 162 deletions(-) diff --git a/fftools/ffmpeg.c b/fftools/ffmpeg.c index e9e60407d29..36b4becaf2b 100644 --- a/fftools/ffmpeg.c +++ b/fftools/ffmpeg.c @@ -147,139 +147,20 @@ static int restore_tty; This is a temporary solution until libavfilter gets real subtitles support. */ -static int sub2video_get_blank_frame(InputStream *ist) -{ - int ret; - AVFrame *frame = ist->sub2video.frame; - - av_frame_unref(frame); - frame->width = ist->sub2video.w; - frame->height = ist->sub2video.h; - frame->format = AV_PIX_FMT_RGB32; - if ((ret = av_frame_get_buffer(frame, 0)) < 0) - return ret; - memset(frame->data[0], 0, frame->height * frame->linesize[0]); - return 0; -} - -static void sub2video_copy_rect(uint8_t *dst, int dst_linesize, int w, int h, - AVSubtitleRect *r) -{ - uint32_t *pal, *dst2; - uint8_t *src, *src2; - int x, y; - - if (r->type != SUBTITLE_BITMAP) { - av_log(NULL, AV_LOG_WARNING, "sub2video: non-bitmap subtitle\n"); - return; - } - if (r->x < 0 || r->x + r->w > w || r->y < 0 || r->y + r->h > h) { - av_log(NULL, AV_LOG_WARNING, "sub2video: rectangle (%d %d %d %d) overflowing %d %d\n", - r->x, r->y, r->w, r->h, w, h - ); - return; - } - - dst += r->y * dst_linesize + r->x * 4; - src = r->data[0]; - pal = (uint32_t *)r->data[1]; - for (y = 0; y < r->h; y++) { - dst2 = (uint32_t *)dst; - src2 = src; - for (x = 0; x < r->w; x++) - *(dst2++) = pal[*(src2++)]; - dst += dst_linesize; - src += r->linesize[0]; - } -} - -static void sub2video_push_ref(InputStream *ist, int64_t pts) -{ - AVFrame *frame = ist->sub2video.frame; - int i; - int ret; - - av_assert1(frame->data[0]); - ist->sub2video.last_pts = frame->pts = pts; - for (i = 0; i < ist->nb_filters; i++) { - ret = av_buffersrc_add_frame_flags(ist->filters[i]->filter, frame, - AV_BUFFERSRC_FLAG_KEEP_REF | - AV_BUFFERSRC_FLAG_PUSH); - if (ret != AVERROR_EOF && ret < 0) - av_log(NULL, AV_LOG_WARNING, "Error while add the frame to buffer source(%s).\n", - av_err2str(ret)); - } -} - -void sub2video_update(InputStream *ist, int64_t heartbeat_pts, - const AVSubtitle *sub) -{ - AVFrame *frame = ist->sub2video.frame; - int8_t *dst; - int dst_linesize; - int num_rects, i; - int64_t pts, end_pts; - - if (!frame) - return; - if (sub) { - pts = av_rescale_q(sub->pts + sub->start_display_time * 1000LL, - AV_TIME_BASE_Q, ist->st->time_base); - end_pts = av_rescale_q(sub->pts + sub->end_display_time * 1000LL, - AV_TIME_BASE_Q, ist->st->time_base); - num_rects = sub->num_rects; - } else { - /* If we are initializing the system, utilize current heartbeat - PTS as the start time, and show until the following subpicture - is received. Otherwise, utilize the previous subpicture's end time - as the fall-back value. */ - pts = ist->sub2video.initialize ? - heartbeat_pts : ist->sub2video.end_pts; - end_pts = INT64_MAX; - num_rects = 0; - } - if (sub2video_get_blank_frame(ist) < 0) { - av_log(NULL, AV_LOG_ERROR, - "Impossible to get a blank canvas.\n"); - return; - } - dst = frame->data [0]; - dst_linesize = frame->linesize[0]; - for (i = 0; i < num_rects; i++) - sub2video_copy_rect(dst, dst_linesize, frame->width, frame->height, sub->rects[i]); - sub2video_push_ref(ist, pts); - ist->sub2video.end_pts = end_pts; - ist->sub2video.initialize = 0; -} - static void sub2video_heartbeat(InputFile *infile, int64_t pts, AVRational tb) { - int i, j, nb_reqs; - int64_t pts2; - /* When a frame is read from a file, examine all sub2video streams in the same file and send the sub2video frame again. Otherwise, decoded video frames could be accumulating in the filter graph while a filter (possibly overlay) is desperately waiting for a subtitle frame. */ - for (i = 0; i < infile->nb_streams; i++) { - InputStream *ist2 = infile->streams[i]; - if (!ist2->sub2video.frame) - continue; - /* subtitles seem to be usually muxed ahead of other streams; - if not, subtracting a larger time here is necessary */ - pts2 = av_rescale_q(pts, tb, ist2->st->time_base) - 1; - /* do not send the heartbeat frame if the subtitle is already ahead */ - if (pts2 <= ist2->sub2video.last_pts) + for (int i = 0; i < infile->nb_streams; i++) { + InputStream *ist = infile->streams[i]; + + if (ist->dec_ctx->codec_type != AVMEDIA_TYPE_SUBTITLE) continue; - if (pts2 >= ist2->sub2video.end_pts || ist2->sub2video.initialize) - /* if we have hit the end of the current displayed subpicture, - or if we need to initialize the system, update the - overlayed subpicture and its start/end times */ - sub2video_update(ist2, pts2 + 1, NULL); - for (j = 0, nb_reqs = 0; j < ist2->nb_filters; j++) - nb_reqs += av_buffersrc_get_nb_failed_requests(ist2->filters[j]->filter); - if (nb_reqs) - sub2video_push_ref(ist2, pts2); + + for (int j = 0; j < ist->nb_filters; j++) + ifilter_sub2video_heartbeat(ist->filters[j], pts, tb); } } diff --git a/fftools/ffmpeg.h b/fftools/ffmpeg.h index d4aff5cc7c5..75695d3fb56 100644 --- a/fftools/ffmpeg.h +++ b/fftools/ffmpeg.h @@ -372,11 +372,7 @@ typedef struct InputStream { } prev_sub; struct sub2video { - int64_t last_pts; - int64_t end_pts; - AVFrame *frame; int w, h; - unsigned int initialize; ///< marks if sub2video_update should force an initialization } sub2video; /* decoded data from this stream goes into all those filters @@ -741,13 +737,12 @@ int init_simple_filtergraph(InputStream *ist, OutputStream *ost, char *graph_desc); int init_complex_filtergraph(FilterGraph *fg); -void sub2video_update(InputStream *ist, int64_t heartbeat_pts, - const AVSubtitle *sub); int copy_av_subtitle(AVSubtitle *dst, const AVSubtitle *src); int ifilter_send_frame(InputFilter *ifilter, AVFrame *frame, int keep_reference); int ifilter_send_eof(InputFilter *ifilter, int64_t pts, AVRational tb); int ifilter_sub2video(InputFilter *ifilter, const AVSubtitle *sub); +void ifilter_sub2video_heartbeat(InputFilter *ifilter, int64_t pts, AVRational tb); /** * Set up fallback filtering parameters from a decoder context. They will only diff --git a/fftools/ffmpeg_dec.c b/fftools/ffmpeg_dec.c index a7acaf67c2d..30959c64b7b 100644 --- a/fftools/ffmpeg_dec.c +++ b/fftools/ffmpeg_dec.c @@ -321,13 +321,8 @@ static int video_frame_process(InputStream *ist, AVFrame *frame) static void sub2video_flush(InputStream *ist) { - int i; - int ret; - - if (ist->sub2video.end_pts < INT64_MAX) - sub2video_update(ist, INT64_MAX, NULL); - for (i = 0; i < ist->nb_filters; i++) { - ret = av_buffersrc_add_frame(ist->filters[i]->filter, NULL); + for (int i = 0; i < ist->nb_filters; i++) { + int ret = ifilter_sub2video(ist->filters[i], NULL); if (ret != AVERROR_EOF && ret < 0) av_log(NULL, AV_LOG_WARNING, "Flush the frame error.\n"); } diff --git a/fftools/ffmpeg_demux.c b/fftools/ffmpeg_demux.c index 817ccbbedc0..5c15b8bad3d 100644 --- a/fftools/ffmpeg_demux.c +++ b/fftools/ffmpeg_demux.c @@ -817,7 +817,6 @@ static void ist_free(InputStream **pist) av_dict_free(&ist->decoder_opts); avsubtitle_free(&ist->prev_sub.subtitle); - av_frame_free(&ist->sub2video.frame); av_freep(&ist->filters); av_freep(&ist->outputs); av_freep(&ist->hwaccel_device); diff --git a/fftools/ffmpeg_filter.c b/fftools/ffmpeg_filter.c index 4b5ccf50bd1..8f839cc273f 100644 --- a/fftools/ffmpeg_filter.c +++ b/fftools/ffmpeg_filter.c @@ -107,6 +107,14 @@ typedef struct InputFilterPriv { struct { ///< queue of AVSubtitle* before filter init AVFifo *queue; + + AVFrame *frame; + + int64_t last_pts; + int64_t end_pts; + + ///< marks if sub2video_update should force an initialization + unsigned int initialize; } sub2video; } InputFilterPriv; @@ -115,6 +123,111 @@ static InputFilterPriv *ifp_from_ifilter(InputFilter *ifilter) return (InputFilterPriv*)ifilter; } +static int sub2video_get_blank_frame(InputFilterPriv *ifp) +{ + AVFrame *frame = ifp->sub2video.frame; + int ret; + + av_frame_unref(frame); + + frame->width = ifp->width; + frame->height = ifp->height; + frame->format = ifp->format; + + ret = av_frame_get_buffer(frame, 0); + if (ret < 0) + return ret; + + memset(frame->data[0], 0, frame->height * frame->linesize[0]); + + return 0; +} + +static void sub2video_copy_rect(uint8_t *dst, int dst_linesize, int w, int h, + AVSubtitleRect *r) +{ + uint32_t *pal, *dst2; + uint8_t *src, *src2; + int x, y; + + if (r->type != SUBTITLE_BITMAP) { + av_log(NULL, AV_LOG_WARNING, "sub2video: non-bitmap subtitle\n"); + return; + } + if (r->x < 0 || r->x + r->w > w || r->y < 0 || r->y + r->h > h) { + av_log(NULL, AV_LOG_WARNING, "sub2video: rectangle (%d %d %d %d) overflowing %d %d\n", + r->x, r->y, r->w, r->h, w, h + ); + return; + } + + dst += r->y * dst_linesize + r->x * 4; + src = r->data[0]; + pal = (uint32_t *)r->data[1]; + for (y = 0; y < r->h; y++) { + dst2 = (uint32_t *)dst; + src2 = src; + for (x = 0; x < r->w; x++) + *(dst2++) = pal[*(src2++)]; + dst += dst_linesize; + src += r->linesize[0]; + } +} + +static void sub2video_push_ref(InputFilterPriv *ifp, int64_t pts) +{ + AVFrame *frame = ifp->sub2video.frame; + int ret; + + av_assert1(frame->data[0]); + ifp->sub2video.last_pts = frame->pts = pts; + ret = av_buffersrc_add_frame_flags(ifp->ifilter.filter, frame, + AV_BUFFERSRC_FLAG_KEEP_REF | + AV_BUFFERSRC_FLAG_PUSH); + if (ret != AVERROR_EOF && ret < 0) + av_log(NULL, AV_LOG_WARNING, "Error while add the frame to buffer source(%s).\n", + av_err2str(ret)); +} + +static void sub2video_update(InputFilterPriv *ifp, int64_t heartbeat_pts, + const AVSubtitle *sub) +{ + AVFrame *frame = ifp->sub2video.frame; + int8_t *dst; + int dst_linesize; + int num_rects, i; + int64_t pts, end_pts; + + if (sub) { + pts = av_rescale_q(sub->pts + sub->start_display_time * 1000LL, + AV_TIME_BASE_Q, ifp->time_base); + end_pts = av_rescale_q(sub->pts + sub->end_display_time * 1000LL, + AV_TIME_BASE_Q, ifp->time_base); + num_rects = sub->num_rects; + } else { + /* If we are initializing the system, utilize current heartbeat + PTS as the start time, and show until the following subpicture + is received. Otherwise, utilize the previous subpicture's end time + as the fall-back value. */ + pts = ifp->sub2video.initialize ? + heartbeat_pts : ifp->sub2video.end_pts; + end_pts = INT64_MAX; + num_rects = 0; + } + if (sub2video_get_blank_frame(ifp) < 0) { + av_log(NULL, AV_LOG_ERROR, + "Impossible to get a blank canvas.\n"); + return; + } + dst = frame->data [0]; + dst_linesize = frame->linesize[0]; + for (i = 0; i < num_rects; i++) + sub2video_copy_rect(dst, dst_linesize, frame->width, frame->height, sub->rects[i]); + sub2video_push_ref(ifp, pts); + ifp->sub2video.end_pts = end_pts; + ifp->sub2video.initialize = 0; +} + // FIXME: YUV420P etc. are actually supported with full color range, // yet the latter information isn't available here. static const enum AVPixelFormat *get_compliance_normal_pix_fmts(const AVCodec *codec, const enum AVPixelFormat default_formats[]) @@ -465,6 +578,12 @@ static int ifilter_bind_ist(InputFilter *ifilter, InputStream *ist) if (ret < 0) return ret; + if (ifp->type_src == AVMEDIA_TYPE_SUBTITLE) { + ifp->sub2video.frame = av_frame_alloc(); + if (!ifp->sub2video.frame) + return AVERROR(ENOMEM); + } + return 0; } @@ -610,6 +729,7 @@ void fg_free(FilterGraph **pfg) avsubtitle_free(&sub); av_fifo_freep2(&ifp->sub2video.queue); } + av_frame_free(&ifp->sub2video.frame); av_channel_layout_uninit(&ifp->fallback.ch_layout); @@ -1108,20 +1228,15 @@ void check_filter_outputs(void) } } -static int sub2video_prepare(InputStream *ist, InputFilter *ifilter) +static void sub2video_prepare(InputFilterPriv *ifp) { - ist->sub2video.frame = av_frame_alloc(); - if (!ist->sub2video.frame) - return AVERROR(ENOMEM); - ist->sub2video.last_pts = INT64_MIN; - ist->sub2video.end_pts = INT64_MIN; + ifp->sub2video.last_pts = INT64_MIN; + ifp->sub2video.end_pts = INT64_MIN; /* sub2video structure has been (re-)initialized. Mark it as such so that the system will be initialized with the first received heartbeat. */ - ist->sub2video.initialize = 1; - - return 0; + ifp->sub2video.initialize = 1; } static int configure_input_video_filter(FilterGraph *fg, InputFilter *ifilter, @@ -1156,11 +1271,8 @@ static int configure_input_video_filter(FilterGraph *fg, InputFilter *ifilter, if (!fr.num) fr = ist->framerate_guessed; - if (ist->dec_ctx->codec_type == AVMEDIA_TYPE_SUBTITLE) { - ret = sub2video_prepare(ist, ifilter); - if (ret < 0) - goto fail; - } + if (ifp->type_src == AVMEDIA_TYPE_SUBTITLE) + sub2video_prepare(ifp); ifp->time_base = ist->framerate.num ? av_inv_q(ist->framerate) : ist->st->time_base; @@ -1466,12 +1578,13 @@ int configure_filtergraph(FilterGraph *fg) /* process queued up subtitle packets */ for (i = 0; i < fg->nb_inputs; i++) { - InputFilterPriv *ifp = ifp_from_ifilter(fg->inputs[i]); - InputStream *ist = ifp->ist; - if (ifp->sub2video.queue && ist->sub2video.frame) { + InputFilter *ifilter = fg->inputs[i]; + InputFilterPriv *ifp = ifp_from_ifilter(ifilter); + + if (ifp->type_src == AVMEDIA_TYPE_SUBTITLE && ifp->sub2video.queue) { AVSubtitle tmp; while (av_fifo_read(ifp->sub2video.queue, &tmp, 1) >= 0) { - sub2video_update(ist, INT64_MIN, &tmp); + sub2video_update(ifp, INT64_MIN, &tmp); avsubtitle_free(&tmp); } } @@ -1620,15 +1733,47 @@ int reap_filters(int flush) return 0; } +void ifilter_sub2video_heartbeat(InputFilter *ifilter, int64_t pts, AVRational tb) +{ + InputFilterPriv *ifp = ifp_from_ifilter(ifilter); + int64_t pts2; + + if (!ifilter->graph->graph) + return; + + /* subtitles seem to be usually muxed ahead of other streams; + if not, subtracting a larger time here is necessary */ + pts2 = av_rescale_q(pts, tb, ifp->time_base) - 1; + + /* do not send the heartbeat frame if the subtitle is already ahead */ + if (pts2 <= ifp->sub2video.last_pts) + return; + + if (pts2 >= ifp->sub2video.end_pts || ifp->sub2video.initialize) + /* if we have hit the end of the current displayed subpicture, + or if we need to initialize the system, update the + overlayed subpicture and its start/end times */ + sub2video_update(ifp, pts2 + 1, NULL); + + if (av_buffersrc_get_nb_failed_requests(ifilter->filter)) + sub2video_push_ref(ifp, pts2); +} + int ifilter_sub2video(InputFilter *ifilter, const AVSubtitle *subtitle) { InputFilterPriv *ifp = ifp_from_ifilter(ifilter); - InputStream *ist = ifp->ist; int ret; - if (ist->sub2video.frame) { - sub2video_update(ist, INT64_MIN, subtitle); - } else { + if (ifilter->graph->graph) { + if (!subtitle) { + if (ifp->sub2video.end_pts < INT64_MAX) + sub2video_update(ifp, INT64_MAX, NULL); + + return av_buffersrc_add_frame(ifilter->filter, NULL); + } + + sub2video_update(ifp, INT64_MIN, subtitle); + } else if (subtitle) { AVSubtitle sub; if (!ifp->sub2video.queue) From f3e0a83e8e379ee9b095ccba1a2729e615d17883 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Sat, 20 May 2023 18:39:21 +0200 Subject: [PATCH 1364/2172] fftools/ffmpeg_enc: stop configuring filters from encoder flush There is no way for a filtergraph to have all input parameters, yet not be configured, so this code should not be reachable. --- fftools/ffmpeg_enc.c | 14 ++------------ 1 file changed, 2 insertions(+), 12 deletions(-) diff --git a/fftools/ffmpeg_enc.c b/fftools/ffmpeg_enc.c index f023657a077..6c9cce252f7 100644 --- a/fftools/ffmpeg_enc.c +++ b/fftools/ffmpeg_enc.c @@ -1172,18 +1172,8 @@ void enc_flush(void) av_log(ost, AV_LOG_WARNING, "Finishing stream without any data written to it.\n"); - if (ost->filter && !fg->graph) { - if (!ifilter_has_all_input_formats(fg)) - continue; - - ret = configure_filtergraph(fg); - if (ret < 0) { - av_log(ost, AV_LOG_ERROR, "Error configuring filter graph\n"); - exit_program(1); - } - - of_output_packet(of, ost->pkt, ost, 1); - } + if (!fg->graph) + continue; ret = enc_open(ost, NULL); if (ret < 0) From 2262df5e8a5a4ae2c3ac44e0bf970f683270362f Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Mon, 22 May 2023 09:56:47 +0200 Subject: [PATCH 1365/2172] fftools/ffmpeg_filter: drop unreachable code Filtergraphs with no inputs are initialized as soon as all their outputs are bound, so this code should not be reachable. --- fftools/ffmpeg_filter.c | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/fftools/ffmpeg_filter.c b/fftools/ffmpeg_filter.c index 8f839cc273f..340696c9891 100644 --- a/fftools/ffmpeg_filter.c +++ b/fftools/ffmpeg_filter.c @@ -1946,17 +1946,6 @@ int fg_transcode_step(FilterGraph *graph, InputStream **best_ist) int nb_requests, nb_requests_max = 0; InputStream *ist; - if (!graph->graph && ifilter_has_all_input_formats(graph)) { - // graph has not been configured yet, but everything is ready; - // this can happen for graphs with no inputs, or when some input - // EOF'ed with zero frames and fallback parameters were used - ret = configure_filtergraph(graph); - if (ret < 0) { - av_log(NULL, AV_LOG_ERROR, "Error reinitializing filters!\n"); - return ret; - } - } - if (!graph->graph) { for (int i = 0; i < graph->nb_inputs; i++) { InputFilter *ifilter = graph->inputs[i]; From 5924b700752574a3c99c4b407ce4b217c34e9c06 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Mon, 22 May 2023 09:58:31 +0200 Subject: [PATCH 1366/2172] fftools/ffmpeg_filter: make ifilter_has_all_input_formats() static It is no longer used outside ffmpeg_filter. --- fftools/ffmpeg.h | 2 -- fftools/ffmpeg_filter.c | 24 ++++++++++++------------ 2 files changed, 12 insertions(+), 14 deletions(-) diff --git a/fftools/ffmpeg.h b/fftools/ffmpeg.h index 75695d3fb56..398bcc58e1f 100644 --- a/fftools/ffmpeg.h +++ b/fftools/ffmpeg.h @@ -751,8 +751,6 @@ void ifilter_sub2video_heartbeat(InputFilter *ifilter, int64_t pts, AVRational t */ int ifilter_parameters_from_dec(InputFilter *ifilter, const AVCodecContext *dec); -int ifilter_has_all_input_formats(FilterGraph *fg); - void ofilter_bind_ost(OutputFilter *ofilter, OutputStream *ost); /** diff --git a/fftools/ffmpeg_filter.c b/fftools/ffmpeg_filter.c index 340696c9891..8910acaac6f 100644 --- a/fftools/ffmpeg_filter.c +++ b/fftools/ffmpeg_filter.c @@ -537,6 +537,18 @@ static int graph_parse(AVFilterGraph *graph, const char *desc, return ret; } +// Filters can be configured only if the formats of all inputs are known. +static int ifilter_has_all_input_formats(FilterGraph *fg) +{ + int i; + for (i = 0; i < fg->nb_inputs; i++) { + InputFilterPriv *ifp = ifp_from_ifilter(fg->inputs[i]); + if (ifp->format < 0) + return 0; + } + return 1; +} + static char *describe_filter_link(FilterGraph *fg, AVFilterInOut *inout, int in) { AVFilterContext *ctx = inout->filter_ctx; @@ -1660,18 +1672,6 @@ static int ifilter_parameters_from_frame(InputFilter *ifilter, const AVFrame *fr return 0; } -// Filters can be configured only if the formats of all inputs are known. -int ifilter_has_all_input_formats(FilterGraph *fg) -{ - int i; - for (i = 0; i < fg->nb_inputs; i++) { - InputFilterPriv *ifp = ifp_from_ifilter(fg->inputs[i]); - if (ifp->format < 0) - return 0; - } - return 1; -} - int filtergraph_is_simple(FilterGraph *fg) { FilterGraphPriv *fgp = fgp_from_fg(fg); From 3bfc2c589ad1470995a0d470466735b841306f7d Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Wed, 24 May 2023 12:35:50 +0200 Subject: [PATCH 1367/2172] fftools/ffmpeg_filter: make InputStream.filter private It is no longer accessed outside of ffmpeg_filter. --- fftools/ffmpeg.h | 1 - fftools/ffmpeg_filter.c | 32 +++++++++++++++++--------------- 2 files changed, 17 insertions(+), 16 deletions(-) diff --git a/fftools/ffmpeg.h b/fftools/ffmpeg.h index 398bcc58e1f..655b5c7ec5b 100644 --- a/fftools/ffmpeg.h +++ b/fftools/ffmpeg.h @@ -278,7 +278,6 @@ typedef struct OptionsContext { } OptionsContext; typedef struct InputFilter { - AVFilterContext *filter; struct FilterGraph *graph; uint8_t *name; } InputFilter; diff --git a/fftools/ffmpeg_filter.c b/fftools/ffmpeg_filter.c index 8910acaac6f..42bb4c73489 100644 --- a/fftools/ffmpeg_filter.c +++ b/fftools/ffmpeg_filter.c @@ -57,6 +57,8 @@ static FilterGraphPriv *fgp_from_fg(FilterGraph *fg) typedef struct InputFilterPriv { InputFilter ifilter; + AVFilterContext *filter; + InputStream *ist; // used to hold submitted input @@ -181,7 +183,7 @@ static void sub2video_push_ref(InputFilterPriv *ifp, int64_t pts) av_assert1(frame->data[0]); ifp->sub2video.last_pts = frame->pts = pts; - ret = av_buffersrc_add_frame_flags(ifp->ifilter.filter, frame, + ret = av_buffersrc_add_frame_flags(ifp->filter, frame, AV_BUFFERSRC_FLAG_KEEP_REF | AV_BUFFERSRC_FLAG_PUSH); if (ret != AVERROR_EOF && ret < 0) @@ -1304,15 +1306,15 @@ static int configure_input_video_filter(FilterGraph *fg, InputFilter *ifilter, ist->file_index, ist->index); - if ((ret = avfilter_graph_create_filter(&ifilter->filter, buffer_filt, name, + if ((ret = avfilter_graph_create_filter(&ifp->filter, buffer_filt, name, args.str, NULL, fg->graph)) < 0) goto fail; par->hw_frames_ctx = ifp->hw_frames_ctx; - ret = av_buffersrc_parameters_set(ifilter->filter, par); + ret = av_buffersrc_parameters_set(ifp->filter, par); if (ret < 0) goto fail; av_freep(&par); - last_filter = ifilter->filter; + last_filter = ifp->filter; desc = av_pix_fmt_desc_get(ifp->format); av_assert0(desc); @@ -1410,11 +1412,11 @@ static int configure_input_audio_filter(FilterGraph *fg, InputFilter *ifilter, snprintf(name, sizeof(name), "graph_%d_in_%d_%d", fg->index, ist->file_index, ist->index); - if ((ret = avfilter_graph_create_filter(&ifilter->filter, abuffer_filt, + if ((ret = avfilter_graph_create_filter(&ifp->filter, abuffer_filt, name, args.str, NULL, fg->graph)) < 0) return ret; - last_filter = ifilter->filter; + last_filter = ifp->filter; snprintf(name, sizeof(name), "trim for input stream %d:%d", ist->file_index, ist->index); @@ -1451,7 +1453,7 @@ static void cleanup_filtergraph(FilterGraph *fg) for (i = 0; i < fg->nb_outputs; i++) fg->outputs[i]->filter = (AVFilterContext *)NULL; for (i = 0; i < fg->nb_inputs; i++) - fg->inputs[i]->filter = (AVFilterContext *)NULL; + ifp_from_ifilter(fg->inputs[i])->filter = NULL; avfilter_graph_free(&fg->graph); } @@ -1571,7 +1573,7 @@ int configure_filtergraph(FilterGraph *fg) InputFilterPriv *ifp = ifp_from_ifilter(fg->inputs[i]); AVFrame *tmp; while (av_fifo_read(ifp->frame_queue, &tmp, 1) >= 0) { - ret = av_buffersrc_add_frame(fg->inputs[i]->filter, tmp); + ret = av_buffersrc_add_frame(ifp->filter, tmp); av_frame_free(&tmp); if (ret < 0) goto fail; @@ -1582,7 +1584,7 @@ int configure_filtergraph(FilterGraph *fg) for (i = 0; i < fg->nb_inputs; i++) { InputFilterPriv *ifp = ifp_from_ifilter(fg->inputs[i]); if (ifp->eof) { - ret = av_buffersrc_add_frame(fg->inputs[i]->filter, NULL); + ret = av_buffersrc_add_frame(ifp->filter, NULL); if (ret < 0) goto fail; } @@ -1755,7 +1757,7 @@ void ifilter_sub2video_heartbeat(InputFilter *ifilter, int64_t pts, AVRational t overlayed subpicture and its start/end times */ sub2video_update(ifp, pts2 + 1, NULL); - if (av_buffersrc_get_nb_failed_requests(ifilter->filter)) + if (av_buffersrc_get_nb_failed_requests(ifp->filter)) sub2video_push_ref(ifp, pts2); } @@ -1769,7 +1771,7 @@ int ifilter_sub2video(InputFilter *ifilter, const AVSubtitle *subtitle) if (ifp->sub2video.end_pts < INT64_MAX) sub2video_update(ifp, INT64_MAX, NULL); - return av_buffersrc_add_frame(ifilter->filter, NULL); + return av_buffersrc_add_frame(ifp->filter, NULL); } sub2video_update(ifp, INT64_MIN, subtitle); @@ -1802,11 +1804,11 @@ int ifilter_send_eof(InputFilter *ifilter, int64_t pts, AVRational tb) ifp->eof = 1; - if (ifilter->filter) { + if (ifp->filter) { pts = av_rescale_q_rnd(pts, tb, ifp->time_base, AV_ROUND_NEAR_INF | AV_ROUND_PASS_MINMAX); - ret = av_buffersrc_close(ifilter->filter, pts, AV_BUFFERSRC_FLAG_PUSH); + ret = av_buffersrc_close(ifp->filter, pts, AV_BUFFERSRC_FLAG_PUSH); if (ret < 0) return ret; } else { @@ -1928,7 +1930,7 @@ int ifilter_send_frame(InputFilter *ifilter, AVFrame *frame, int keep_reference) ) #endif - ret = av_buffersrc_add_frame_flags(ifilter->filter, frame, + ret = av_buffersrc_add_frame_flags(ifp->filter, frame, AV_BUFFERSRC_FLAG_PUSH); if (ret < 0) { av_frame_unref(frame); @@ -1984,7 +1986,7 @@ int fg_transcode_step(FilterGraph *graph, InputStream **best_ist) ist = ifp->ist; if (input_files[ist->file_index]->eagain || ifp->eof) continue; - nb_requests = av_buffersrc_get_nb_failed_requests(ifilter->filter); + nb_requests = av_buffersrc_get_nb_failed_requests(ifp->filter); if (nb_requests > nb_requests_max) { nb_requests_max = nb_requests; *best_ist = ist; From 2674532eeed14f0b82fa027da7b2b3389bc8faaf Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Wed, 24 May 2023 12:39:47 +0200 Subject: [PATCH 1368/2172] fftools/ffmpeg_filter: constify the argument of filtergraph_is_simple() --- fftools/ffmpeg.h | 2 +- fftools/ffmpeg_filter.c | 9 +++++++-- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/fftools/ffmpeg.h b/fftools/ffmpeg.h index 655b5c7ec5b..966397270d1 100644 --- a/fftools/ffmpeg.h +++ b/fftools/ffmpeg.h @@ -731,7 +731,7 @@ int parse_and_set_vsync(const char *arg, int *vsync_var, int file_idx, int st_id int configure_filtergraph(FilterGraph *fg); void check_filter_outputs(void); -int filtergraph_is_simple(FilterGraph *fg); +int filtergraph_is_simple(const FilterGraph *fg); int init_simple_filtergraph(InputStream *ist, OutputStream *ost, char *graph_desc); int init_complex_filtergraph(FilterGraph *fg); diff --git a/fftools/ffmpeg_filter.c b/fftools/ffmpeg_filter.c index 42bb4c73489..2cf3c891ce1 100644 --- a/fftools/ffmpeg_filter.c +++ b/fftools/ffmpeg_filter.c @@ -54,6 +54,11 @@ static FilterGraphPriv *fgp_from_fg(FilterGraph *fg) return (FilterGraphPriv*)fg; } +static const FilterGraphPriv *cfgp_from_cfg(const FilterGraph *fg) +{ + return (const FilterGraphPriv*)fg; +} + typedef struct InputFilterPriv { InputFilter ifilter; @@ -1674,9 +1679,9 @@ static int ifilter_parameters_from_frame(InputFilter *ifilter, const AVFrame *fr return 0; } -int filtergraph_is_simple(FilterGraph *fg) +int filtergraph_is_simple(const FilterGraph *fg) { - FilterGraphPriv *fgp = fgp_from_fg(fg); + const FilterGraphPriv *fgp = cfgp_from_cfg(fg); return fgp->is_simple; } From 106167374c7e14c6e2afb0049897f1a59a25c839 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Thu, 25 May 2023 08:50:19 +0200 Subject: [PATCH 1369/2172] fftools/ffmpeg_mux: flush bsfs immediately on exceeding recoding time Current code marks the output stream as finished and waits for a flush packet, but that is both unnecessary and suspect, as in theory nothing should be sent to a finished stream - not even flush packets. --- fftools/ffmpeg_mux.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/fftools/ffmpeg_mux.c b/fftools/ffmpeg_mux.c index 3da3c04d7f7..feb014ca311 100644 --- a/fftools/ffmpeg_mux.c +++ b/fftools/ffmpeg_mux.c @@ -386,6 +386,11 @@ void of_streamcopy(OutputStream *ost, const AVPacket *pkt, int64_t dts) AVPacket *opkt = ost->pkt; av_packet_unref(opkt); + + if (of->recording_time != INT64_MAX && + dts >= of->recording_time + start_time) + pkt = NULL; + // EOF: flush output bitstream filters. if (!pkt) { of_output_packet(of, opkt, ost, 1); @@ -407,12 +412,6 @@ void of_streamcopy(OutputStream *ost, const AVPacket *pkt, int64_t dts) return; } - if (of->recording_time != INT64_MAX && - dts >= of->recording_time + start_time) { - close_output_stream(ost); - return; - } - if (av_packet_ref(opkt, pkt) < 0) exit_program(1); From ba2c791627334ac70e5a5df480b80ee3ce61519d Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Thu, 25 May 2023 15:38:56 +0200 Subject: [PATCH 1370/2172] fftools/ffmpeg_filter: do not flush encoders on parameter change It makes no sense to do so. --- fftools/ffmpeg_filter.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fftools/ffmpeg_filter.c b/fftools/ffmpeg_filter.c index 2cf3c891ce1..c3075ef8544 100644 --- a/fftools/ffmpeg_filter.c +++ b/fftools/ffmpeg_filter.c @@ -1905,7 +1905,7 @@ int ifilter_send_frame(InputFilter *ifilter, AVFrame *frame, int keep_reference) return ret; } - ret = reap_filters(1); + ret = reap_filters(0); if (ret < 0 && ret != AVERROR_EOF) { av_log(NULL, AV_LOG_ERROR, "Error while filtering: %s\n", av_err2str(ret)); return ret; From 0f2f0dd5b415884792a29f7db15d364c730067cf Mon Sep 17 00:00:00 2001 From: Pierre-Anthony Lemieux Date: Mon, 29 May 2023 09:59:04 -0700 Subject: [PATCH 1371/2172] avformat/imf: clean-up logging * remove logging to NULL * remove extraneous logging --- libavformat/imf.h | 6 +- libavformat/imf_cpl.c | 179 +++++++++++++++++++--------------------- libavformat/imfdec.c | 2 +- libavformat/tests/imf.c | 4 +- 4 files changed, 91 insertions(+), 100 deletions(-) diff --git a/libavformat/imf.h b/libavformat/imf.h index 70ed007312c..ef124bf4124 100644 --- a/libavformat/imf.h +++ b/libavformat/imf.h @@ -140,6 +140,7 @@ typedef struct FFIMFCPL { /** * Parse an IMF CompositionPlaylist element into the FFIMFCPL data structure. + * @param[in] log_ctx Logging context (points to an instance of AVClass). May be NULL. * @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 @@ -147,10 +148,11 @@ typedef struct FFIMFCPL { * 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); +int ff_imf_parse_cpl_from_xml_dom(void *log_ctx, xmlDocPtr doc, FFIMFCPL **cpl); /** * Parse an IMF Composition Playlist document into the FFIMFCPL data structure. + * @param[in] log_ctx Logging context (points to an instance of AVClass). May be NULL. * @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 @@ -158,7 +160,7 @@ int ff_imf_parse_cpl_from_xml_dom(xmlDocPtr doc, FFIMFCPL **cpl); * 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); +int ff_imf_parse_cpl(void *log_ctx, AVIOContext *in, FFIMFCPL **cpl); /** * Allocates and initializes an FFIMFCPL data structure. diff --git a/libavformat/imf_cpl.c b/libavformat/imf_cpl.c index a7cf5fa3600..fe975c2f0c0 100644 --- a/libavformat/imf_cpl.c +++ b/libavformat/imf_cpl.c @@ -76,10 +76,8 @@ int ff_imf_xml_read_uuid(xmlNodePtr element, AVUUID uuid) xmlChar *element_text = xmlNodeListGetString(element->doc, element->xmlChildrenNode, 1); ret = av_uuid_urn_parse(element_text, uuid); - if (ret) { - av_log(NULL, AV_LOG_ERROR, "Invalid UUID\n"); + if (ret) ret = AVERROR_INVALIDDATA; - } xmlFree(element_text); return ret; @@ -90,10 +88,8 @@ int ff_imf_xml_read_rational(xmlNodePtr element, AVRational *rational) int ret = 0; xmlChar *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"); + if (sscanf(element_text, "%i %i", &rational->num, &rational->den) != 2) ret = AVERROR_INVALIDDATA; - } xmlFree(element_text); return ret; @@ -104,10 +100,8 @@ int ff_imf_xml_read_uint32(xmlNodePtr element, uint32_t *number) int ret = 0; xmlChar *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"); + if (sscanf(element_text, "%" PRIu32, number) != 1) ret = AVERROR_INVALIDDATA; - } xmlFree(element_text); return ret; @@ -181,10 +175,8 @@ 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"); + if (!(element = ff_imf_xml_get_child_element_by_name(cpl_element, "ContentTitle"))) return AVERROR_INVALIDDATA; - } cpl->content_title_utf8 = xmlNodeListGetString(cpl_element->doc, element->xmlChildrenNode, 1); @@ -242,22 +234,15 @@ static int fill_timecode(xmlNodePtr cpl_element, FFIMFCPL *cpl) return 0; element = ff_imf_xml_get_child_element_by_name(tc_element, "TimecodeDropFrame"); - if (!element) { - av_log(NULL, AV_LOG_ERROR, "CompositionTimecode element is missing\ - a TimecodeDropFrame child element\n"); + if (!element) return AVERROR_INVALIDDATA; - } - if (ff_imf_xml_read_boolean(element, &df)) { - av_log(NULL, AV_LOG_ERROR, "TimecodeDropFrame element is invalid\n"); + if (ff_imf_xml_read_boolean(element, &df)) return AVERROR_INVALIDDATA; - } + element = ff_imf_xml_get_child_element_by_name(tc_element, "TimecodeStartAddress"); - if (!element) { - av_log(NULL, AV_LOG_ERROR, "CompositionTimecode element is missing\ - a TimecodeStartAddress child element\n"); + if (!element) return AVERROR_INVALIDDATA; - } tc_str = xmlNodeListGetString(element->doc, element->xmlChildrenNode, 1); ret = parse_cpl_tc_type(tc_str, comps); @@ -280,10 +265,8 @@ 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"); + if (!(element = ff_imf_xml_get_child_element_by_name(cpl_element, "EditRate"))) return AVERROR_INVALIDDATA; - } return ff_imf_xml_read_rational(element, &cpl->edit_rate); } @@ -292,10 +275,8 @@ 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"); + if (!(element = ff_imf_xml_get_child_element_by_name(cpl_element, "Id"))) return AVERROR_INVALIDDATA; - } return ff_imf_xml_read_uuid(element, cpl->id_uuid); } @@ -306,22 +287,19 @@ static int fill_marker(xmlNodePtr marker_elem, FFIMFMarker *marker) 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"); + if (!(element = ff_imf_xml_get_child_element_by_name(marker_elem, "Offset"))) 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"); + if (!(element = ff_imf_xml_get_child_element_by_name(marker_elem, "Label"))) 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"); + + if (!(marker->label_utf8 = xmlNodeListGetString(element->doc, element->xmlChildrenNode, 1))) 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"); @@ -334,7 +312,8 @@ static int fill_marker(xmlNodePtr marker_elem, FFIMFMarker *marker) return ret; } -static int fill_base_resource(xmlNodePtr resource_elem, FFIMFBaseResource *resource, FFIMFCPL *cpl) +static int fill_base_resource(void *log_ctx, xmlNodePtr resource_elem, + FFIMFBaseResource *resource, FFIMFCPL *cpl) { xmlNodePtr element = NULL; int ret = 0; @@ -343,14 +322,14 @@ static int fill_base_resource(xmlNodePtr resource_elem, FFIMFBaseResource *resou 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"); + av_log(log_ctx, 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"); + av_log(log_ctx, AV_LOG_ERROR, "Invalid EntryPoint element found in a Resource\n"); return ret; } } else { @@ -359,11 +338,11 @@ static int fill_base_resource(xmlNodePtr resource_elem, FFIMFBaseResource *resou /* 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"); + av_log(log_ctx, 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"); + av_log(log_ctx, AV_LOG_ERROR, "Invalid IntrinsicDuration element found in a Resource\n"); return ret; } resource->duration -= resource->entry_point; @@ -371,7 +350,7 @@ static int fill_base_resource(xmlNodePtr resource_elem, FFIMFBaseResource *resou /* 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"); + av_log(log_ctx, AV_LOG_ERROR, "SourceDuration element missing from Resource\n"); return ret; } } @@ -383,38 +362,38 @@ static int fill_base_resource(xmlNodePtr resource_elem, FFIMFBaseResource *resou return ret; } -static int fill_trackfile_resource(xmlNodePtr tf_resource_elem, +static int fill_trackfile_resource(void *log_ctx, 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))) + if ((ret = fill_base_resource(log_ctx, 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"); + av_log(log_ctx, 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"); + av_log(log_ctx, AV_LOG_ERROR, "TrackFileId element missing from Resource\n"); return AVERROR_INVALIDDATA; } return ret; } -static int fill_marker_resource(xmlNodePtr marker_resource_elem, +static int fill_marker_resource(void *log_ctx, 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))) + if ((ret = fill_base_resource(log_ctx, marker_resource_elem, (FFIMFBaseResource *)marker_resource, cpl))) return ret; /* read markers */ @@ -436,8 +415,10 @@ static int fill_marker_resource(xmlNodePtr marker_resource_elem, ret = fill_marker(element, &marker_resource->markers[marker_resource->marker_count]); marker_resource->marker_count++; - if (ret) + if (ret) { + av_log(log_ctx, AV_LOG_ERROR, "Invalid Marker element\n"); return ret; + } } element = xmlNextElementSibling(element); @@ -446,7 +427,7 @@ static int fill_marker_resource(xmlNodePtr marker_resource_elem, return ret; } -static int push_marker_sequence(xmlNodePtr marker_sequence_elem, FFIMFCPL *cpl) +static int push_marker_sequence(void *log_ctx, xmlNodePtr marker_sequence_elem, FFIMFCPL *cpl) { int ret = 0; AVUUID uuid; @@ -458,14 +439,14 @@ static int push_marker_sequence(xmlNodePtr marker_sequence_elem, FFIMFCPL *cpl) /* 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"); + av_log(log_ctx, 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"); + av_log(log_ctx, AV_LOG_ERROR, "Invalid TrackId element found in Sequence\n"); return AVERROR_INVALIDDATA; } - av_log(NULL, + av_log(log_ctx, AV_LOG_DEBUG, "Processing IMF CPL Marker Sequence for Virtual Track " AV_PRI_UUID "\n", AV_UUID_ARG(uuid)); @@ -479,7 +460,7 @@ static int push_marker_sequence(xmlNodePtr marker_sequence_elem, FFIMFCPL *cpl) av_uuid_copy(cpl->main_markers_track->base.id_uuid, uuid); } else if (!av_uuid_equal(cpl->main_markers_track->base.id_uuid, uuid)) { - av_log(NULL, AV_LOG_ERROR, "Multiple marker virtual tracks were found\n"); + av_log(log_ctx, AV_LOG_ERROR, "Multiple marker virtual tracks were found\n"); return AVERROR_INVALIDDATA; } @@ -496,7 +477,7 @@ static int push_marker_sequence(xmlNodePtr marker_sequence_elem, FFIMFCPL *cpl) cpl->main_markers_track->resource_count + resource_elem_count, sizeof(FFIMFMarkerResource)); if (!tmp) { - av_log(NULL, AV_LOG_ERROR, "Cannot allocate Marker Resources\n"); + av_log(log_ctx, AV_LOG_ERROR, "Cannot allocate Marker Resources\n"); return AVERROR(ENOMEM); } cpl->main_markers_track->resources = tmp; @@ -504,7 +485,7 @@ static int push_marker_sequence(xmlNodePtr marker_sequence_elem, FFIMFCPL *cpl) 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, + ret = fill_marker_resource(log_ctx, resource_elem, &cpl->main_markers_track->resources[cpl->main_markers_track->resource_count], cpl); cpl->main_markers_track->resource_count++; @@ -533,7 +514,7 @@ static int has_stereo_resources(xmlNodePtr element) return 0; } -static int push_main_audio_sequence(xmlNodePtr audio_sequence_elem, FFIMFCPL *cpl) +static int push_main_audio_sequence(void *log_ctx, xmlNodePtr audio_sequence_elem, FFIMFCPL *cpl) { int ret = 0; AVUUID uuid; @@ -546,14 +527,14 @@ static int push_main_audio_sequence(xmlNodePtr audio_sequence_elem, FFIMFCPL *cp /* 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"); + av_log(log_ctx, 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"); + av_log(log_ctx, AV_LOG_ERROR, "Invalid TrackId element found in audio sequence\n"); return ret; } - av_log(NULL, + av_log(log_ctx, AV_LOG_DEBUG, "Processing IMF CPL Audio Sequence for Virtual Track " AV_PRI_UUID "\n", AV_UUID_ARG(uuid)); @@ -597,7 +578,7 @@ static int push_main_audio_sequence(xmlNodePtr audio_sequence_elem, FFIMFCPL *cp (vt->resource_count + resource_elem_count) * sizeof(FFIMFTrackFileResource)); if (!tmp) { - av_log(NULL, AV_LOG_ERROR, "Cannot allocate Main Audio Resources\n"); + av_log(log_ctx, AV_LOG_ERROR, "Cannot allocate Main Audio Resources\n"); return AVERROR(ENOMEM); } vt->resources = tmp; @@ -605,11 +586,11 @@ static int push_main_audio_sequence(xmlNodePtr audio_sequence_elem, FFIMFCPL *cp resource_elem = xmlFirstElementChild(resource_list_elem); while (resource_elem) { imf_trackfile_resource_init(&vt->resources[vt->resource_count]); - ret = fill_trackfile_resource(resource_elem, + ret = fill_trackfile_resource(log_ctx, resource_elem, &vt->resources[vt->resource_count], cpl); if (ret) - av_log(NULL, AV_LOG_ERROR, "Invalid Resource\n"); + av_log(log_ctx, AV_LOG_ERROR, "Invalid Resource\n"); else vt->resource_count++; @@ -619,7 +600,7 @@ static int push_main_audio_sequence(xmlNodePtr audio_sequence_elem, FFIMFCPL *cp return ret; } -static int push_main_image_2d_sequence(xmlNodePtr image_sequence_elem, FFIMFCPL *cpl) +static int push_main_image_2d_sequence(void *log_ctx, xmlNodePtr image_sequence_elem, FFIMFCPL *cpl) { int ret = 0; AVUUID uuid; @@ -631,17 +612,17 @@ static int push_main_image_2d_sequence(xmlNodePtr image_sequence_elem, FFIMFCPL /* skip stereoscopic resources */ if (has_stereo_resources(image_sequence_elem)) { - av_log(NULL, AV_LOG_ERROR, "Stereoscopic 3D image virtual tracks not supported\n"); + av_log(log_ctx, 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"); + av_log(log_ctx, 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"); + av_log(log_ctx, AV_LOG_ERROR, "Invalid TrackId element found in audio sequence\n"); return ret; } @@ -654,10 +635,10 @@ static int push_main_image_2d_sequence(xmlNodePtr image_sequence_elem, FFIMFCPL av_uuid_copy(cpl->main_image_2d_track->base.id_uuid, uuid); } else if (!av_uuid_equal(cpl->main_image_2d_track->base.id_uuid, uuid)) { - av_log(NULL, AV_LOG_ERROR, "Multiple MainImage virtual tracks found\n"); + av_log(log_ctx, AV_LOG_ERROR, "Multiple MainImage virtual tracks found\n"); return AVERROR_INVALIDDATA; } - av_log(NULL, + av_log(log_ctx, AV_LOG_DEBUG, "Processing IMF CPL Main Image Sequence for Virtual Track " AV_PRI_UUID "\n", AV_UUID_ARG(uuid)); @@ -678,7 +659,7 @@ static int push_main_image_2d_sequence(xmlNodePtr image_sequence_elem, FFIMFCPL (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"); + av_log(log_ctx, AV_LOG_ERROR, "Cannot allocate Main Image Resources\n"); return AVERROR(ENOMEM); } cpl->main_image_2d_track->resources = tmp; @@ -687,11 +668,11 @@ static int push_main_image_2d_sequence(xmlNodePtr image_sequence_elem, FFIMFCPL 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, + ret = fill_trackfile_resource(log_ctx, resource_elem, &cpl->main_image_2d_track->resources[cpl->main_image_2d_track->resource_count], cpl); if (ret) - av_log(NULL, AV_LOG_ERROR, "Invalid Resource\n"); + av_log(log_ctx, AV_LOG_ERROR, "Invalid Resource\n"); else cpl->main_image_2d_track->resource_count++; @@ -701,7 +682,7 @@ static int push_main_image_2d_sequence(xmlNodePtr image_sequence_elem, FFIMFCPL return 0; } -static int fill_virtual_tracks(xmlNodePtr cpl_element, FFIMFCPL *cpl) +static int fill_virtual_tracks(void *log_ctx, xmlNodePtr cpl_element, FFIMFCPL *cpl) { int ret = 0; xmlNodePtr segment_list_elem = NULL; @@ -710,14 +691,14 @@ static int fill_virtual_tracks(xmlNodePtr cpl_element, FFIMFCPL *cpl) 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"); + av_log(log_ctx, 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"); + av_log(log_ctx, AV_LOG_DEBUG, "Processing IMF CPL Segment\n"); sequence_list_elem = ff_imf_xml_get_child_element_by_name(segment_elem, "SequenceList"); if (!sequence_list_elem) @@ -726,16 +707,16 @@ static int fill_virtual_tracks(xmlNodePtr cpl_element, FFIMFCPL *cpl) sequence_elem = xmlFirstElementChild(sequence_list_elem); while (sequence_elem) { if (xmlStrcmp(sequence_elem->name, "MarkerSequence") == 0) - ret = push_marker_sequence(sequence_elem, cpl); + ret = push_marker_sequence(log_ctx, sequence_elem, cpl); else if (xmlStrcmp(sequence_elem->name, "MainImageSequence") == 0) - ret = push_main_image_2d_sequence(sequence_elem, cpl); + ret = push_main_image_2d_sequence(log_ctx, sequence_elem, cpl); else if (xmlStrcmp(sequence_elem->name, "MainAudioSequence") == 0) - ret = push_main_audio_sequence(sequence_elem, cpl); + ret = push_main_audio_sequence(log_ctx, sequence_elem, cpl); else - av_log(NULL, + av_log(log_ctx, AV_LOG_INFO, "The following Sequence is not supported and is ignored: %s\n", sequence_elem->name); @@ -753,7 +734,7 @@ static int fill_virtual_tracks(xmlNodePtr cpl_element, FFIMFCPL *cpl) return ret; } -int ff_imf_parse_cpl_from_xml_dom(xmlDocPtr doc, FFIMFCPL **cpl) +int ff_imf_parse_cpl_from_xml_dom(void *log_ctx, xmlDocPtr doc, FFIMFCPL **cpl) { int ret = 0; xmlNodePtr cpl_element = NULL; @@ -766,20 +747,28 @@ int ff_imf_parse_cpl_from_xml_dom(xmlDocPtr doc, FFIMFCPL **cpl) cpl_element = xmlDocGetRootElement(doc); if (!cpl_element || xmlStrcmp(cpl_element->name, "CompositionPlaylist")) { - av_log(NULL, AV_LOG_ERROR, "The root element of the CPL is not CompositionPlaylist\n"); + av_log(log_ctx, 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))) + if ((ret = fill_content_title(cpl_element, *cpl))) { + av_log(log_ctx, AV_LOG_ERROR, "Cannot read the ContentTitle element from the IMF CPL\n"); goto cleanup; - if ((ret = fill_id(cpl_element, *cpl))) + } + if ((ret = fill_id(cpl_element, *cpl))) { + av_log(log_ctx, AV_LOG_ERROR, "Id element not found in the IMF CPL\n"); goto cleanup; - if ((ret = fill_edit_rate(cpl_element, *cpl))) + } + if ((ret = fill_edit_rate(cpl_element, *cpl))) { + av_log(log_ctx, AV_LOG_ERROR, "EditRate element not found in the IMF CPL\n"); goto cleanup; - if ((ret = fill_timecode(cpl_element, *cpl))) + } + if ((ret = fill_timecode(cpl_element, *cpl))) { + av_log(log_ctx, AV_LOG_ERROR, "Invalid CompositionTimecode element found in the IMF CPL\n"); goto cleanup; - if ((ret = fill_virtual_tracks(cpl_element, *cpl))) + } + if ((ret = fill_virtual_tracks(log_ctx, cpl_element, *cpl))) goto cleanup; cleanup: @@ -875,7 +864,7 @@ void ff_imf_cpl_free(FFIMFCPL *cpl) av_freep(&cpl); } -int ff_imf_parse_cpl(AVIOContext *in, FFIMFCPL **cpl) +int ff_imf_parse_cpl(void *log_ctx, AVIOContext *in, FFIMFCPL **cpl) { AVBPrint buf; xmlDoc *doc = NULL; @@ -885,7 +874,7 @@ int ff_imf_parse_cpl(AVIOContext *in, FFIMFCPL **cpl) ret = avio_read_to_bprint(in, &buf, SIZE_MAX); if (ret < 0 || !avio_feof(in)) { - av_log(NULL, AV_LOG_ERROR, "Cannot read IMF CPL\n"); + av_log(log_ctx, AV_LOG_ERROR, "Cannot read IMF CPL\n"); if (ret == 0) ret = AVERROR_INVALIDDATA; goto clean_up; @@ -895,21 +884,21 @@ int ff_imf_parse_cpl(AVIOContext *in, FFIMFCPL **cpl) doc = xmlReadMemory(buf.str, buf.len, NULL, NULL, 0); if (!doc) { - av_log(NULL, + av_log(log_ctx, 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"); + if ((ret = ff_imf_parse_cpl_from_xml_dom(log_ctx, doc, cpl))) { + av_log(log_ctx, AV_LOG_ERROR, "Cannot parse IMF CPL\n"); } else { - av_log(NULL, + av_log(log_ctx, AV_LOG_INFO, "IMF CPL ContentTitle: %s\n", (*cpl)->content_title_utf8); - av_log(NULL, + av_log(log_ctx, AV_LOG_INFO, "IMF CPL Id: " AV_PRI_UUID "\n", AV_UUID_ARG((*cpl)->id_uuid)); diff --git a/libavformat/imfdec.c b/libavformat/imfdec.c index 7d04d0d8535..818b5e590bb 100644 --- a/libavformat/imfdec.c +++ b/libavformat/imfdec.c @@ -649,7 +649,7 @@ static int imf_read_header(AVFormatContext *s) 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) + if ((ret = ff_imf_parse_cpl(s, s->pb, &c->cpl)) < 0) return ret; tcr = av_dict_get(s->metadata, "timecode", NULL, 0); diff --git a/libavformat/tests/imf.c b/libavformat/tests/imf.c index 068ee6c58ab..92d1052a1d1 100644 --- a/libavformat/tests/imf.c +++ b/libavformat/tests/imf.c @@ -341,7 +341,7 @@ static int test_cpl_parsing(void) return 1; } - ret = ff_imf_parse_cpl_from_xml_dom(doc, &cpl); + ret = ff_imf_parse_cpl_from_xml_dom(NULL, doc, &cpl); xmlFreeDoc(doc); if (ret) { printf("CPL parsing failed.\n"); @@ -394,7 +394,7 @@ static int test_cpl_from_doc(FFIMFCPL **cpl, const char* cpl_doc, int should_pas return should_pass; } - ret = ff_imf_parse_cpl_from_xml_dom(doc, cpl); + ret = ff_imf_parse_cpl_from_xml_dom(NULL, doc, cpl); xmlFreeDoc(doc); if (ret) { printf("CPL parsing failed.\n"); From baa9fccf8d72be259024d7e0eb919c909714c6a7 Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Wed, 31 May 2023 15:23:27 +0200 Subject: [PATCH 1372/2172] avfilter/vf_mergeplanes: remove hack for linesize calculation --- libavfilter/vf_mergeplanes.c | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/libavfilter/vf_mergeplanes.c b/libavfilter/vf_mergeplanes.c index 23b9f3d62f1..ae55d819b8c 100644 --- a/libavfilter/vf_mergeplanes.c +++ b/libavfilter/vf_mergeplanes.c @@ -48,6 +48,7 @@ typedef struct MergePlanesContext { int planewidth[4]; int planeheight[4]; Mapping map[4]; + const AVPixFmtDescriptor *indesc[4]; const AVPixFmtDescriptor *outdesc; FFFrameSync fs; @@ -171,7 +172,8 @@ static int process_frame(FFFrameSync *fs) av_image_copy_plane(out->data[i], out->linesize[i], in[input]->data[plane], in[input]->linesize[plane], - s->planewidth[i], s->planeheight[i]); + s->planewidth[i] * ((s->indesc[input]->comp[plane].depth + 7) / 8), + s->planeheight[i]); } return ff_filter_frame(outlink, out); @@ -199,9 +201,9 @@ static int config_output(AVFilterLink *outlink) outlink->sample_aspect_ratio = ctx->inputs[0]->sample_aspect_ratio; s->planewidth[1] = - s->planewidth[2] = AV_CEIL_RSHIFT(((s->outdesc->comp[1].depth > 8) + 1) * outlink->w, s->outdesc->log2_chroma_w); + s->planewidth[2] = AV_CEIL_RSHIFT(outlink->w, s->outdesc->log2_chroma_w); s->planewidth[0] = - s->planewidth[3] = ((s->outdesc->comp[0].depth > 8) + 1) * outlink->w; + s->planewidth[3] = outlink->w; s->planeheight[1] = s->planeheight[2] = AV_CEIL_RSHIFT(outlink->h, s->outdesc->log2_chroma_h); s->planeheight[0] = @@ -210,8 +212,7 @@ static int config_output(AVFilterLink *outlink) for (i = 0; i < s->nb_inputs; i++) { InputParam *inputp = &inputsp[i]; AVFilterLink *inlink = ctx->inputs[i]; - const AVPixFmtDescriptor *indesc = av_pix_fmt_desc_get(inlink->format); - int j; + s->indesc[i] = av_pix_fmt_desc_get(inlink->format); if (outlink->sample_aspect_ratio.num != inlink->sample_aspect_ratio.num || outlink->sample_aspect_ratio.den != inlink->sample_aspect_ratio.den) { @@ -227,17 +228,17 @@ static int config_output(AVFilterLink *outlink) } inputp->planewidth[1] = - inputp->planewidth[2] = AV_CEIL_RSHIFT(((indesc->comp[1].depth > 8) + 1) * inlink->w, indesc->log2_chroma_w); + inputp->planewidth[2] = AV_CEIL_RSHIFT(inlink->w, s->indesc[i]->log2_chroma_w); inputp->planewidth[0] = - inputp->planewidth[3] = ((indesc->comp[0].depth > 8) + 1) * inlink->w; + inputp->planewidth[3] = inlink->w; inputp->planeheight[1] = - inputp->planeheight[2] = AV_CEIL_RSHIFT(inlink->h, indesc->log2_chroma_h); + inputp->planeheight[2] = AV_CEIL_RSHIFT(inlink->h, s->indesc[i]->log2_chroma_h); inputp->planeheight[0] = inputp->planeheight[3] = inlink->h; inputp->nb_planes = av_pix_fmt_count_planes(inlink->format); - for (j = 0; j < inputp->nb_planes; j++) - inputp->depth[j] = indesc->comp[j].depth; + for (int j = 0; j < inputp->nb_planes; j++) + inputp->depth[j] = s->indesc[i]->comp[j].depth; in[i].time_base = inlink->time_base; in[i].sync = 1; From 3cfd85ec20460c34199d191c2caff9a2e0650829 Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Thu, 1 Jun 2023 20:07:13 +0200 Subject: [PATCH 1373/2172] avfilter/avf_showcqt: switch to activate And make output frame durations always same. --- libavfilter/avf_showcqt.c | 84 +++++++++++++++++++++++---------------- 1 file changed, 50 insertions(+), 34 deletions(-) diff --git a/libavfilter/avf_showcqt.c b/libavfilter/avf_showcqt.c index 76086477e93..fa3cdaf22b0 100644 --- a/libavfilter/avf_showcqt.c +++ b/libavfilter/avf_showcqt.c @@ -27,6 +27,7 @@ #include "libavutil/pixdesc.h" #include "libavutil/time.h" #include "avfilter.h" +#include "filters.h" #include "internal.h" #include "lavfutils.h" #include "lswsutils.h" @@ -51,8 +52,6 @@ "st(1, if(between(ld(0),0,1), 0.5-0.5*cos(2*PI*ld(0)), 0));" \ "r(1-ld(1)) + b(ld(1))" #define CSCHEME "1|0.5|0|0|0.5|1" -#define PTS_STEP 10 -#define PTS_TOLERANCE 1 #define OFFSET(x) offsetof(ShowCQTContext, x) #define FLAGS (AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_VIDEO_PARAM) @@ -344,7 +343,7 @@ static int init_cqt(ShowCQTContext *s) } av_expr_free(expr); - av_log(s->ctx, AV_LOG_INFO, "nb_cqt_coeffs = %d.\n", nb_cqt_coeffs); + av_log(s->ctx, AV_LOG_VERBOSE, "nb_cqt_coeffs = %d.\n", nb_cqt_coeffs); return 0; error: @@ -1186,9 +1185,6 @@ static int plot_cqt(AVFilterContext *ctx, AVFrame **frameout) s->draw_sono(out, s->sono_frame, s->bar_h + s->axis_h, s->sono_idx); UPDATE_TIME(s->sono_time); } - out->pts = s->next_pts; - out->duration = PTS_STEP; - s->next_pts += PTS_STEP; } s->sono_count = (s->sono_count + 1) % s->count; if (s->sono_h) @@ -1366,8 +1362,8 @@ static int config_output(AVFilterLink *outlink) s->format = outlink->format; outlink->sample_aspect_ratio = av_make_q(1, 1); outlink->frame_rate = s->rate; - outlink->time_base = av_mul_q(av_inv_q(s->rate), av_make_q(1, PTS_STEP)); - av_log(ctx, AV_LOG_INFO, "video: %dx%d %s %d/%d fps, bar_h = %d, axis_h = %d, sono_h = %d.\n", + outlink->time_base = av_inv_q(s->rate); + av_log(ctx, AV_LOG_VERBOSE, "video: %dx%d %s %d/%d fps, bar_h = %d, axis_h = %d, sono_h = %d.\n", s->width, s->height, av_get_pix_fmt_name(s->format), s->rate.num, s->rate.den, s->bar_h, s->axis_h, s->sono_h); @@ -1380,7 +1376,7 @@ static int config_output(AVFilterLink *outlink) s->fft_bits = FFMAX(ceil(log2(inlink->sample_rate * s->timeclamp)), 4); s->fft_len = 1 << s->fft_bits; - av_log(ctx, AV_LOG_INFO, "fft_len = %d, cqt_len = %d.\n", s->fft_len, s->cqt_len); + av_log(ctx, AV_LOG_VERBOSE, "fft_len = %d, cqt_len = %d.\n", s->fft_len, s->cqt_len); ret = av_tx_init(&s->fft_ctx, &s->tx_fn, AV_TX_FLOAT_FFT, 0, s->fft_len, &scale, 0); s->fft_data = av_calloc(s->fft_len, sizeof(*s->fft_data)); @@ -1470,11 +1466,10 @@ static int config_output(AVFilterLink *outlink) s->step = (int)(s->step_frac.num / s->step_frac.den); s->step_frac.num %= s->step_frac.den; if (s->step_frac.num) { - av_log(ctx, AV_LOG_INFO, "audio: %d Hz, step = %d + %d/%d.\n", + av_log(ctx, AV_LOG_VERBOSE, "audio: %d Hz, step = %d + %d/%d.\n", inlink->sample_rate, s->step, s->step_frac.num, s->step_frac.den); - av_log(ctx, AV_LOG_WARNING, "fractional step.\n"); } else { - av_log(ctx, AV_LOG_INFO, "audio: %d Hz, step = %d.\n", + av_log(ctx, AV_LOG_VERBOSE, "audio: %d Hz, step = %d.\n", inlink->sample_rate, s->step); } @@ -1487,7 +1482,7 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *insamples) AVFilterContext *ctx = inlink->dst; AVFilterLink *outlink = ctx->outputs[0]; ShowCQTContext *s = ctx->priv; - int remaining, step, ret, x, i, j, m; + int remaining, step, ret, x, i, j, m, got_frame = 0; float *audio_data; AVFrame *out = NULL; @@ -1503,11 +1498,15 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *insamples) for (x = 0; x < (s->fft_len/2 + s->remaining_fill_max - step); x++) s->fft_data[x] = s->fft_data[x+step]; s->remaining_fill += step; + s->next_pts++; - if (out) + if (out) { + out->pts = s->next_pts; + out->duration = 1; return ff_filter_frame(outlink, out); + } } - return AVERROR_EOF; + return 0; } remaining = insamples->nb_samples; @@ -1528,16 +1527,11 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *insamples) } remaining -= s->remaining_fill; if (out) { - int64_t pts = av_rescale_q(insamples->pts, inlink->time_base, av_make_q(1, inlink->sample_rate)); - pts += insamples->nb_samples - remaining - s->remaining_fill_max; - pts = av_rescale_q(pts, av_make_q(1, inlink->sample_rate), outlink->time_base); - if (FFABS(pts - out->pts) > PTS_TOLERANCE) { - av_log(ctx, AV_LOG_DEBUG, "changing pts from %"PRId64" (%.3f) to %"PRId64" (%.3f).\n", - out->pts, out->pts * av_q2d(outlink->time_base), - pts, pts * av_q2d(outlink->time_base)); - out->pts = pts; - s->next_pts = pts + PTS_STEP; - } + int64_t pts = av_rescale_q(insamples->nb_samples - remaining - s->remaining_fill_max, + av_make_q(1, inlink->sample_rate), inlink->time_base); + out->pts = av_rescale_q(insamples->pts + pts, inlink->time_base, outlink->time_base); + out->duration = 1; + got_frame = 1; ret = ff_filter_frame(outlink, out); if (ret < 0) { av_frame_free(&insamples); @@ -1559,26 +1553,48 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *insamples) remaining = 0; } } + if (!got_frame) + ff_filter_set_ready(ctx, 100); av_frame_free(&insamples); return 0; } -static int request_frame(AVFilterLink *outlink) +static int activate(AVFilterContext *ctx) { - AVFilterLink *inlink = outlink->src->inputs[0]; - int ret; + AVFilterLink *inlink = ctx->inputs[0]; + AVFilterLink *outlink = ctx->outputs[0]; + ShowCQTContext *s = ctx->priv; + int nb_samples, ret, status; + int64_t pts; + AVFrame *in; - ret = ff_request_frame(inlink); - if (ret == AVERROR_EOF) - ret = filter_frame(inlink, NULL); - return ret; + FF_FILTER_FORWARD_STATUS_BACK(outlink, inlink); + + nb_samples = s->step + (s->step_frac.num + s->remaining_frac) / s->step_frac.den; + ret = ff_inlink_consume_samples(inlink, nb_samples, nb_samples, &in); + if (ret < 0) + return ret; + if (ret > 0) + return filter_frame(inlink, in); + + if (ff_inlink_acknowledge_status(inlink, &status, &pts)) { + if (status == AVERROR_EOF) { + s->next_pts = av_rescale_q(pts, inlink->time_base, outlink->time_base); + ret = filter_frame(inlink, NULL); + ff_outlink_set_status(outlink, AVERROR_EOF, s->next_pts); + return ret; + } + } + + FF_FILTER_FORWARD_WANTED(outlink, inlink); + + return FFERROR_NOT_READY; } static const AVFilterPad showcqt_inputs[] = { { .name = "default", .type = AVMEDIA_TYPE_AUDIO, - .filter_frame = filter_frame, }, }; @@ -1587,7 +1603,6 @@ static const AVFilterPad showcqt_outputs[] = { .name = "default", .type = AVMEDIA_TYPE_VIDEO, .config_props = config_output, - .request_frame = request_frame, }, }; @@ -1595,6 +1610,7 @@ const AVFilter ff_avf_showcqt = { .name = "showcqt", .description = NULL_IF_CONFIG_SMALL("Convert input audio to a CQT (Constant/Clamped Q Transform) spectrum video output."), .init = init, + .activate = activate, .uninit = uninit, .priv_size = sizeof(ShowCQTContext), FILTER_INPUTS(showcqt_inputs), From 03823ac0c6a38bd6ba972539e3203a592579792f Mon Sep 17 00:00:00 2001 From: Timo Rothenpieler Date: Thu, 1 Jun 2023 23:24:43 +0200 Subject: [PATCH 1374/2172] configure: use non-deprecated nvenc GUID for conftest --- configure | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure b/configure index 495493aa0e8..ae56540f4eb 100755 --- a/configure +++ b/configure @@ -7079,7 +7079,7 @@ enabled nvenc && test_cc -I$source_path < NV_ENCODE_API_FUNCTION_LIST flist; -void f(void) { struct { const GUID guid; } s[] = { { NV_ENC_PRESET_HQ_GUID } }; } +void f(void) { struct { const GUID guid; } s[] = { { NV_ENC_CODEC_H264_GUID } }; } int main(void) { return 0; } EOF From d2b46c1ef768bc31ba9180f6d469d5b8be677500 Mon Sep 17 00:00:00 2001 From: Timo Rothenpieler Date: Thu, 1 Jun 2023 23:46:46 +0200 Subject: [PATCH 1375/2172] avcodec/nvenc: stop using deprecated rc modes with SDK 12.1 --- libavcodec/nvenc.c | 11 +++++++++++ libavcodec/nvenc.h | 5 +++++ libavcodec/nvenc_h264.c | 12 ++++++++++++ libavcodec/nvenc_hevc.c | 12 ++++++++++++ 4 files changed, 40 insertions(+) diff --git a/libavcodec/nvenc.c b/libavcodec/nvenc.c index c1798ce564b..50371d63366 100644 --- a/libavcodec/nvenc.c +++ b/libavcodec/nvenc.c @@ -44,9 +44,14 @@ #define CHECK_CU(x) FF_CUDA_CHECK_DL(avctx, dl_fn->cuda_dl, x) #define NVENC_CAP 0x30 + +#ifndef NVENC_NO_DEPRECATED_RC #define IS_CBR(rc) (rc == NV_ENC_PARAMS_RC_CBR || \ rc == NV_ENC_PARAMS_RC_CBR_LOWDELAY_HQ || \ rc == NV_ENC_PARAMS_RC_CBR_HQ) +#else +#define IS_CBR(rc) (rc == NV_ENC_PARAMS_RC_CBR) +#endif const enum AVPixelFormat ff_nvenc_pix_fmts[] = { AV_PIX_FMT_YUV420P, @@ -926,6 +931,7 @@ static void nvenc_override_rate_control(AVCodecContext *avctx) case NV_ENC_PARAMS_RC_CONSTQP: set_constqp(avctx); return; +#ifndef NVENC_NO_DEPRECATED_RC case NV_ENC_PARAMS_RC_VBR_MINQP: if (avctx->qmin < 0) { av_log(avctx, AV_LOG_WARNING, @@ -936,12 +942,15 @@ static void nvenc_override_rate_control(AVCodecContext *avctx) } /* fall through */ case NV_ENC_PARAMS_RC_VBR_HQ: +#endif case NV_ENC_PARAMS_RC_VBR: set_vbr(avctx); break; case NV_ENC_PARAMS_RC_CBR: +#ifndef NVENC_NO_DEPRECATED_RC case NV_ENC_PARAMS_RC_CBR_HQ: case NV_ENC_PARAMS_RC_CBR_LOWDELAY_HQ: +#endif break; } @@ -1211,12 +1220,14 @@ static av_cold int nvenc_setup_h264_config(AVCodecContext *avctx) h264->outputPictureTimingSEI = 1; +#ifndef NVENC_NO_DEPRECATED_RC if (cc->rcParams.rateControlMode == NV_ENC_PARAMS_RC_CBR_LOWDELAY_HQ || cc->rcParams.rateControlMode == NV_ENC_PARAMS_RC_CBR_HQ || cc->rcParams.rateControlMode == NV_ENC_PARAMS_RC_VBR_HQ) { h264->adaptiveTransformMode = NV_ENC_H264_ADAPTIVE_TRANSFORM_ENABLE; h264->fmoMode = NV_ENC_H264_FMO_DISABLE; } +#endif if (ctx->flags & NVENC_LOSSLESS) { h264->qpPrimeYZeroTransformBypassFlag = 1; diff --git a/libavcodec/nvenc.h b/libavcodec/nvenc.h index 411c83aa943..97aad80cd06 100644 --- a/libavcodec/nvenc.h +++ b/libavcodec/nvenc.h @@ -77,6 +77,11 @@ typedef void ID3D11Device; #define NVENC_HAVE_SINGLE_SLICE_INTRA_REFRESH #endif +// SDK 12.1 compile time feature checks +#if NVENCAPI_CHECK_VERSION(12, 1) +#define NVENC_NO_DEPRECATED_RC +#endif + typedef struct NvencSurface { NV_ENC_INPUT_PTR input_surface; diff --git a/libavcodec/nvenc_h264.c b/libavcodec/nvenc_h264.c index 5dc2961c3bc..698615855bf 100644 --- a/libavcodec/nvenc_h264.c +++ b/libavcodec/nvenc_h264.c @@ -100,6 +100,7 @@ static const AVOption options[] = { { "constqp", "Constant QP mode", 0, AV_OPT_TYPE_CONST, { .i64 = NV_ENC_PARAMS_RC_CONSTQP }, 0, 0, VE, "rc" }, { "vbr", "Variable bitrate mode", 0, AV_OPT_TYPE_CONST, { .i64 = NV_ENC_PARAMS_RC_VBR }, 0, 0, VE, "rc" }, { "cbr", "Constant bitrate mode", 0, AV_OPT_TYPE_CONST, { .i64 = NV_ENC_PARAMS_RC_CBR }, 0, 0, VE, "rc" }, +#ifndef NVENC_NO_DEPRECATED_RC { "vbr_minqp", "Variable bitrate mode with MinQP (deprecated)", 0, AV_OPT_TYPE_CONST, { .i64 = RCD(NV_ENC_PARAMS_RC_VBR_MINQP) }, 0, 0, VE, "rc" }, { "ll_2pass_quality", "Multi-pass optimized for image quality (deprecated)", 0, AV_OPT_TYPE_CONST, { .i64 = RCD(NV_ENC_PARAMS_RC_2_PASS_QUALITY) }, 0, 0, VE, "rc" }, @@ -109,6 +110,17 @@ static const AVOption options[] = { { "cbr_ld_hq", "Constant bitrate low delay high quality mode", 0, AV_OPT_TYPE_CONST, { .i64 = RCD(NV_ENC_PARAMS_RC_CBR_LOWDELAY_HQ) }, 0, 0, VE, "rc" }, { "cbr_hq", "Constant bitrate high quality mode", 0, AV_OPT_TYPE_CONST, { .i64 = RCD(NV_ENC_PARAMS_RC_CBR_HQ) }, 0, 0, VE, "rc" }, { "vbr_hq", "Variable bitrate high quality mode", 0, AV_OPT_TYPE_CONST, { .i64 = RCD(NV_ENC_PARAMS_RC_VBR_HQ) }, 0, 0, VE, "rc" }, +#else + { "vbr_minqp", "Variable bitrate mode with MinQP (deprecated)", 0, AV_OPT_TYPE_CONST, { .i64 = RCD(NV_ENC_PARAMS_RC_VBR) }, 0, 0, VE, "rc" }, + { "ll_2pass_quality", "Multi-pass optimized for image quality (deprecated)", + 0, AV_OPT_TYPE_CONST, { .i64 = RCD(NV_ENC_PARAMS_RC_VBR) }, 0, 0, VE, "rc" }, + { "ll_2pass_size", "Multi-pass optimized for constant frame size (deprecated)", + 0, AV_OPT_TYPE_CONST, { .i64 = RCD(NV_ENC_PARAMS_RC_CBR) }, 0, 0, VE, "rc" }, + { "vbr_2pass", "Multi-pass variable bitrate mode (deprecated)", 0, AV_OPT_TYPE_CONST, { .i64 = RCD(NV_ENC_PARAMS_RC_VBR) }, 0, 0, VE, "rc" }, + { "cbr_ld_hq", "Constant bitrate low delay high quality mode", 0, AV_OPT_TYPE_CONST, { .i64 = RCD(NV_ENC_PARAMS_RC_CBR) }, 0, 0, VE, "rc" }, + { "cbr_hq", "Constant bitrate high quality mode", 0, AV_OPT_TYPE_CONST, { .i64 = RCD(NV_ENC_PARAMS_RC_CBR) }, 0, 0, VE, "rc" }, + { "vbr_hq", "Variable bitrate high quality mode", 0, AV_OPT_TYPE_CONST, { .i64 = RCD(NV_ENC_PARAMS_RC_VBR) }, 0, 0, VE, "rc" }, +#endif { "rc-lookahead", "Number of frames to look ahead for rate-control", OFFSET(rc_lookahead), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, INT_MAX, VE }, { "surfaces", "Number of concurrent surfaces", OFFSET(nb_surfaces), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, MAX_REGISTERED_FRAMES, VE }, diff --git a/libavcodec/nvenc_hevc.c b/libavcodec/nvenc_hevc.c index 1362a927c8e..d99077f1705 100644 --- a/libavcodec/nvenc_hevc.c +++ b/libavcodec/nvenc_hevc.c @@ -89,6 +89,7 @@ static const AVOption options[] = { { "constqp", "Constant QP mode", 0, AV_OPT_TYPE_CONST, { .i64 = NV_ENC_PARAMS_RC_CONSTQP }, 0, 0, VE, "rc" }, { "vbr", "Variable bitrate mode", 0, AV_OPT_TYPE_CONST, { .i64 = NV_ENC_PARAMS_RC_VBR }, 0, 0, VE, "rc" }, { "cbr", "Constant bitrate mode", 0, AV_OPT_TYPE_CONST, { .i64 = NV_ENC_PARAMS_RC_CBR }, 0, 0, VE, "rc" }, +#ifndef NVENC_NO_DEPRECATED_RC { "vbr_minqp", "Variable bitrate mode with MinQP (deprecated)", 0, AV_OPT_TYPE_CONST, { .i64 = RCD(NV_ENC_PARAMS_RC_VBR_MINQP) }, 0, 0, VE, "rc" }, { "ll_2pass_quality", "Multi-pass optimized for image quality (deprecated)", 0, AV_OPT_TYPE_CONST, { .i64 = RCD(NV_ENC_PARAMS_RC_2_PASS_QUALITY) }, 0, 0, VE, "rc" }, @@ -98,6 +99,17 @@ static const AVOption options[] = { { "cbr_ld_hq", "Constant bitrate low delay high quality mode", 0, AV_OPT_TYPE_CONST, { .i64 = RCD(NV_ENC_PARAMS_RC_CBR_LOWDELAY_HQ) }, 0, 0, VE, "rc" }, { "cbr_hq", "Constant bitrate high quality mode", 0, AV_OPT_TYPE_CONST, { .i64 = RCD(NV_ENC_PARAMS_RC_CBR_HQ) }, 0, 0, VE, "rc" }, { "vbr_hq", "Variable bitrate high quality mode", 0, AV_OPT_TYPE_CONST, { .i64 = RCD(NV_ENC_PARAMS_RC_VBR_HQ) }, 0, 0, VE, "rc" }, +#else + { "vbr_minqp", "Variable bitrate mode with MinQP (deprecated)", 0, AV_OPT_TYPE_CONST, { .i64 = RCD(NV_ENC_PARAMS_RC_VBR) }, 0, 0, VE, "rc" }, + { "ll_2pass_quality", "Multi-pass optimized for image quality (deprecated)", + 0, AV_OPT_TYPE_CONST, { .i64 = RCD(NV_ENC_PARAMS_RC_VBR) }, 0, 0, VE, "rc" }, + { "ll_2pass_size", "Multi-pass optimized for constant frame size (deprecated)", + 0, AV_OPT_TYPE_CONST, { .i64 = RCD(NV_ENC_PARAMS_RC_CBR) }, 0, 0, VE, "rc" }, + { "vbr_2pass", "Multi-pass variable bitrate mode (deprecated)", 0, AV_OPT_TYPE_CONST, { .i64 = RCD(NV_ENC_PARAMS_RC_VBR) }, 0, 0, VE, "rc" }, + { "cbr_ld_hq", "Constant bitrate low delay high quality mode", 0, AV_OPT_TYPE_CONST, { .i64 = RCD(NV_ENC_PARAMS_RC_CBR) }, 0, 0, VE, "rc" }, + { "cbr_hq", "Constant bitrate high quality mode", 0, AV_OPT_TYPE_CONST, { .i64 = RCD(NV_ENC_PARAMS_RC_CBR) }, 0, 0, VE, "rc" }, + { "vbr_hq", "Variable bitrate high quality mode", 0, AV_OPT_TYPE_CONST, { .i64 = RCD(NV_ENC_PARAMS_RC_VBR) }, 0, 0, VE, "rc" }, +#endif { "rc-lookahead", "Number of frames to look ahead for rate-control", OFFSET(rc_lookahead), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, INT_MAX, VE }, { "surfaces", "Number of concurrent surfaces", OFFSET(nb_surfaces), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, MAX_REGISTERED_FRAMES, VE }, From da23151eaf9be9212c4ad31ae5cbe85793a16244 Mon Sep 17 00:00:00 2001 From: James Almer Date: Tue, 30 May 2023 18:36:17 -0300 Subject: [PATCH 1376/2172] avformat/oggparseflac: use the GetByteContext API All but one read are byte aligned, so there's no point in using the GetBitContext API. Signed-off-by: James Almer --- libavformat/oggparseflac.c | 27 ++++++++++++--------------- 1 file changed, 12 insertions(+), 15 deletions(-) diff --git a/libavformat/oggparseflac.c b/libavformat/oggparseflac.c index 557440d94b9..f25ed9cc155 100644 --- a/libavformat/oggparseflac.c +++ b/libavformat/oggparseflac.c @@ -20,7 +20,7 @@ #include #include "libavcodec/avcodec.h" -#include "libavcodec/get_bits.h" +#include "libavcodec/bytestream.h" #include "libavcodec/flac.h" #include "avformat.h" #include "internal.h" @@ -34,31 +34,28 @@ flac_header (AVFormatContext * s, int idx) struct ogg *ogg = s->priv_data; struct ogg_stream *os = ogg->streams + idx; AVStream *st = s->streams[idx]; - GetBitContext gb; + GetByteContext gb; int mdt, ret; if (os->buf[os->pstart] == 0xff) return 0; - ret = init_get_bits8(&gb, os->buf + os->pstart, os->psize); - if (ret < 0) - return ret; - - skip_bits1(&gb); /* metadata_last */ - mdt = get_bits(&gb, 7); + bytestream2_init(&gb, os->buf + os->pstart, os->psize); + mdt = bytestream2_get_byte(&gb) & 0x7F; if (mdt == OGG_FLAC_METADATA_TYPE_STREAMINFO) { - uint8_t *streaminfo_start = os->buf + os->pstart + 5 + 4 + 4 + 4; uint32_t samplerate; - skip_bits_long(&gb, 4*8); /* "FLAC" */ - if(get_bits(&gb, 8) != 1) /* unsupported major version */ + if (bytestream2_get_bytes_left(&gb) < 4 + 4 + 4 + 4 + FLAC_STREAMINFO_SIZE) + return AVERROR_INVALIDDATA; + bytestream2_skipu(&gb, 4); /* "FLAC" */ + if (bytestream2_get_byteu(&gb) != 1) /* unsupported major version */ return -1; - skip_bits(&gb, 8 + 16); /* minor version + header count */ - skip_bits_long(&gb, 4*8); /* "fLaC" */ + bytestream2_skipu(&gb, 1 + 2); /* minor version + header count */ + bytestream2_skipu(&gb, 4); /* "fLaC" */ /* METADATA_BLOCK_HEADER */ - if (get_bits_long(&gb, 32) != FLAC_STREAMINFO_SIZE) + if (bytestream2_get_be32u(&gb) != FLAC_STREAMINFO_SIZE) return -1; st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO; @@ -67,7 +64,7 @@ flac_header (AVFormatContext * s, int idx) if ((ret = ff_alloc_extradata(st->codecpar, FLAC_STREAMINFO_SIZE)) < 0) return ret; - memcpy(st->codecpar->extradata, streaminfo_start, st->codecpar->extradata_size); + bytestream2_get_bufferu(&gb, st->codecpar->extradata, FLAC_STREAMINFO_SIZE); samplerate = AV_RB24(st->codecpar->extradata + 10) >> 4; if (!samplerate) From 9a9b56c8706957267c57a0c97db890b170b2bb9b Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Fri, 2 Jun 2023 01:08:56 +0200 Subject: [PATCH 1377/2172] avfilter/vf_mix: add fast filtering in case all tmix weights are same --- libavfilter/vf_mix.c | 75 ++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 73 insertions(+), 2 deletions(-) diff --git a/libavfilter/vf_mix.c b/libavfilter/vf_mix.c index 70fe90ea306..446df2c3263 100644 --- a/libavfilter/vf_mix.c +++ b/libavfilter/vf_mix.c @@ -43,8 +43,10 @@ typedef struct MixContext { float scale; float wfactor; + int fast; int tmix; int nb_frames; + int nb_unique_frames; int depth; int max; @@ -53,6 +55,8 @@ typedef struct MixContext { int linesizes[4]; int height[4]; + uint8_t *sum[4]; + uint8_t **data; int *linesize; @@ -81,6 +85,7 @@ static int parse_weights(AVFilterContext *ctx) char *p, *arg, *saveptr = NULL; int i, last = 0; + s->fast = 1; s->wfactor = 0.f; p = s->weights_str; for (i = 0; i < s->nb_inputs; i++) { @@ -93,6 +98,8 @@ static int parse_weights(AVFilterContext *ctx) return AVERROR(EINVAL); } s->wfactor += s->weights[i]; + if (i > 0) + s->fast &= s->weights[i] == s->weights[0]; last = i; } @@ -103,6 +110,8 @@ static int parse_weights(AVFilterContext *ctx) if (s->scale == 0) { s->wfactor = 1 / s->wfactor; } else { + if (s->scale != 1.f / s->wfactor) + s->fast = 0; s->wfactor = s->scale; } @@ -145,13 +154,52 @@ typedef struct ThreadData { AVFrame **in, *out; } ThreadData; +#define FAST_TMIX_SLICE(type, stype, round) \ + for (int p = 0; p < s->nb_planes; p++) { \ + const int slice_start = (s->height[p] * jobnr) / nb_jobs; \ + const int slice_end = (s->height[p] * (jobnr+1)) / nb_jobs; \ + const int width = s->linesizes[p] / sizeof(type); \ + stype *sum = (stype *)(s->sum[p] + slice_start * s->linesizes[p] * 2); \ + type *dst = (type *)(out->data[p] + slice_start * out->linesize[p]); \ + const ptrdiff_t sum_linesize = (s->linesizes[p] * 2) / sizeof(stype); \ + const ptrdiff_t dst_linesize = out->linesize[p] / sizeof(type); \ + const int idx = FFMAX(0, nb_inputs - nb_unique); \ + const ptrdiff_t src_linesize[2] = { in[idx]->linesize[p], \ + in[nb_inputs-1]->linesize[p] }; \ + const type *src[2]; \ + \ + if (!((1 << p) & s->planes)) { \ + av_image_copy_plane((uint8_t *)dst, out->linesize[p], \ + in[0]->data[p] + slice_start * in[0]->linesize[p], \ + in[0]->linesize[p], \ + s->linesizes[p], slice_end - slice_start); \ + continue; \ + } \ + \ + src[0] = (const type *)(in[idx]->data[p] + slice_start*src_linesize[0]); \ + src[1] = (const type *)(in[nb_inputs-1]->data[p] + slice_start * src_linesize[1]); \ + \ + for (int y = slice_start; y < slice_end; y++) { \ + for (int x = 0; x < width; x++) { \ + sum[x] += src[1][x] * (1 + (nb_inputs - 1) * (idx == (nb_inputs - 1))); \ + dst[x] = (sum[x] + (round)) / nb_inputs; \ + sum[x] -= src[0][x]; \ + } \ + \ + dst += dst_linesize; \ + sum += sum_linesize; \ + src[0] += src_linesize[0] / sizeof(type); \ + src[1] += src_linesize[1] / sizeof(type); \ + } \ + } + #define MIX_SLICE(type, fun, clip) \ for (int p = 0; p < s->nb_planes; p++) { \ const int slice_start = (s->height[p] * jobnr) / nb_jobs; \ const int slice_end = (s->height[p] * (jobnr+1)) / nb_jobs; \ const int width = s->linesizes[p] / sizeof(type); \ type *dst = (type *)(out->data[p] + slice_start * out->linesize[p]); \ - ptrdiff_t dst_linesize = out->linesize[p] / sizeof(type); \ + const ptrdiff_t dst_linesize = out->linesize[p] / sizeof(type); \ \ if (!((1 << p) & s->planes)) { \ av_image_copy_plane((uint8_t *)dst, out->linesize[p], \ @@ -200,10 +248,23 @@ static int mix_frames(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) const float *weights = s->weights; uint8_t **srcf = s->data + jobnr * s->nb_inputs; int *linesize = s->linesize + jobnr * s->nb_inputs; + const int nb_unique = s->nb_unique_frames; const int nb_inputs = s->nb_inputs; const float wfactor = s->wfactor; const int max = s->max; + if (s->tmix && s->fast) { + if (s->depth <= 8) { + FAST_TMIX_SLICE(uint8_t, uint16_t, nb_inputs >> 1) + } else if (s->depth <= 16) { + FAST_TMIX_SLICE(uint16_t, uint32_t, nb_inputs >> 1) + } else { + FAST_TMIX_SLICE(float, float, 0.f) + } + + return 0; + } + if (s->depth <= 8) { MIX_SLICE(uint8_t, lrintf, CLIP8) } else if (s->depth <= 16) { @@ -294,8 +355,14 @@ static int config_output(AVFilterLink *outlink) if (!s->linesize) return AVERROR(ENOMEM); - if (s->tmix) + if (s->tmix) { + for (int p = 0; p < s->nb_planes; p++) { + s->sum[p] = av_calloc(s->linesizes[p], s->height[p] * sizeof(*s->sum) * 2); + if (!s->sum[p]) + return AVERROR(ENOMEM); + } return 0; + } outlink->w = width; outlink->h = height; @@ -335,6 +402,8 @@ static av_cold void uninit(AVFilterContext *ctx) av_freep(&s->linesize); if (s->tmix) { + for (i = 0; i < 4; i++) + av_freep(&s->sum[i]); for (i = 0; i < s->nb_frames && s->frames; i++) av_frame_free(&s->frames[i]); } @@ -418,6 +487,7 @@ static int tmix_filter_frame(AVFilterLink *inlink, AVFrame *in) if (s->nb_frames < s->nb_inputs) { s->frames[s->nb_frames] = in; s->nb_frames++; + s->nb_unique_frames++; while (s->nb_frames < s->nb_inputs) { s->frames[s->nb_frames] = av_frame_clone(s->frames[s->nb_frames - 1]); if (!s->frames[s->nb_frames]) @@ -425,6 +495,7 @@ static int tmix_filter_frame(AVFilterLink *inlink, AVFrame *in) s->nb_frames++; } } else { + s->nb_unique_frames = FFMIN(s->nb_unique_frames + 1, s->nb_inputs); av_frame_free(&s->frames[0]); memmove(&s->frames[0], &s->frames[1], sizeof(*s->frames) * (s->nb_inputs - 1)); s->frames[s->nb_inputs - 1] = in; From 8c6b931f4ca08abdaff4896cb2707c38d8483d80 Mon Sep 17 00:00:00 2001 From: James Almer Date: Fri, 2 Jun 2023 13:59:35 -0300 Subject: [PATCH 1378/2172] avcodec/av1dec: reset the fragment on reading failure Fixes: NULL pointer dereference Fixes: 59359/clusterfuzz-testcase-minimized-ffmpeg_AV_CODEC_ID_AV1_fuzzer-6726080594313216 Found-by: continuous fuzzing process https://github.com/google/oss-fuzz/tree/master/projects/ffmpeg Signed-off-by: James Almer --- libavcodec/av1dec.c | 1 + 1 file changed, 1 insertion(+) diff --git a/libavcodec/av1dec.c b/libavcodec/av1dec.c index 5cc5d87c648..d63e7921131 100644 --- a/libavcodec/av1dec.c +++ b/libavcodec/av1dec.c @@ -1460,6 +1460,7 @@ static int av1_receive_frame(AVCodecContext *avctx, AVFrame *frame) ret = ff_cbs_read_packet(s->cbc, &s->current_obu, s->pkt); if (ret < 0) { + ff_cbs_fragment_reset(&s->current_obu); av_packet_unref(s->pkt); av_log(avctx, AV_LOG_ERROR, "Failed to read packet.\n"); return ret; From 4da14c302fe43c5692316f1a0540323b185dec56 Mon Sep 17 00:00:00 2001 From: James Almer Date: Fri, 2 Jun 2023 14:07:20 -0300 Subject: [PATCH 1379/2172] avcodec/av1dec: reset the fragment on extradata reading failure Signed-off-by: James Almer --- libavcodec/av1dec.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavcodec/av1dec.c b/libavcodec/av1dec.c index d63e7921131..e7f98a6c810 100644 --- a/libavcodec/av1dec.c +++ b/libavcodec/av1dec.c @@ -850,7 +850,7 @@ static av_cold int av1_decode_init(AVCodecContext *avctx) avctx); if (ret < 0) { av_log(avctx, AV_LOG_WARNING, "Failed to read extradata.\n"); - return ret; + goto end; } seq = ((CodedBitstreamAV1Context *)(s->cbc->priv_data))->sequence_header; From 6b8d53f72801dd17eb5804aa3ba1134884475309 Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Fri, 2 Jun 2023 21:51:54 +0200 Subject: [PATCH 1380/2172] avcodec/magicyuvenc: add slice encoding support --- libavcodec/magicyuvenc.c | 212 ++++++++++++++++++++++----------------- 1 file changed, 119 insertions(+), 93 deletions(-) diff --git a/libavcodec/magicyuvenc.c b/libavcodec/magicyuvenc.c index 9e41c1b0fe7..a12ef5a33d4 100644 --- a/libavcodec/magicyuvenc.c +++ b/libavcodec/magicyuvenc.c @@ -22,6 +22,7 @@ #include #include +#include "libavutil/cpu.h" #include "libavutil/opt.h" #include "libavutil/pixdesc.h" #include "libavutil/qsort.h" @@ -63,8 +64,8 @@ typedef struct MagicYUVContext { int correlate; int hshift[4]; int vshift[4]; - uint8_t *slices[4]; - unsigned slice_pos[4]; + uint8_t **slices; + unsigned *slice_pos; unsigned tables_size; uint8_t *decorrelate_buf[2]; HuffEntry he[4][256]; @@ -150,7 +151,6 @@ static av_cold int magy_encode_init(AVCodecContext *avctx) { MagicYUVContext *s = avctx->priv_data; PutByteContext pb; - int i; switch (avctx->pix_fmt) { case AV_PIX_FMT_GBRP: @@ -201,14 +201,23 @@ static av_cold int magy_encode_init(AVCodecContext *avctx) s->planes = av_pix_fmt_count_planes(avctx->pix_fmt); - s->nb_slices = 1; + s->nb_slices = (avctx->slices <= 0) ? av_cpu_count() : avctx->slices; + s->nb_slices = FFMIN(s->nb_slices, avctx->height >> s->vshift[1]); + s->nb_slices = FFMAX(1, s->nb_slices); + s->slice_height = FFALIGN((avctx->height + s->nb_slices - 1) / s->nb_slices, 1 << s->vshift[1]); + s->slice_pos = av_calloc(s->nb_slices * s->planes, sizeof(*s->slice_pos)); + s->slices = av_calloc(s->nb_slices * s->planes, sizeof(*s->slices)); + if (!s->slices || !s->slice_pos) + return AVERROR(ENOMEM); - for (i = 0; i < s->planes; i++) { - s->slices[i] = av_malloc(avctx->width * (avctx->height + 2) + - AV_INPUT_BUFFER_PADDING_SIZE); - if (!s->slices[i]) { - av_log(avctx, AV_LOG_ERROR, "Cannot allocate temporary buffer.\n"); - return AVERROR(ENOMEM); + for (int n = 0; n < s->nb_slices; n++) { + for (int i = 0; i < s->planes; i++) { + s->slices[n * s->planes + i] = av_malloc(avctx->width * (s->slice_height + 2) + + AV_INPUT_BUFFER_PADDING_SIZE); + if (!s->slices[n * s->planes + i]) { + av_log(avctx, AV_LOG_ERROR, "Cannot allocate temporary buffer.\n"); + return AVERROR(ENOMEM); + } } } @@ -263,15 +272,12 @@ static void calculate_codes(HuffEntry *he, uint16_t codes_count[33]) } } -static void count_usage(uint8_t *src, int width, +static void count_usage(const uint8_t *src, int width, int height, PTable *counts) { - int i, j; - - for (j = 0; j < height; j++) { - for (i = 0; i < width; i++) { + for (int j = 0; j < height; j++) { + for (int i = 0; i < width; i++) counts[src[i]].prob++; - } src += width; } } @@ -352,26 +358,30 @@ static void magy_huffman_compute_bits(PTable *prob_table, HuffEntry *distincts, } } -static int encode_table(AVCodecContext *avctx, uint8_t *dst, - int width, int height, - PutBitContext *pb, HuffEntry *he) +static int encode_table(AVCodecContext *avctx, + PutBitContext *pb, HuffEntry *he, int plane) { + MagicYUVContext *s = avctx->priv_data; PTable counts[256] = { {0} }; uint16_t codes_counts[33] = { 0 }; - int i; - count_usage(dst, width, height, counts); + for (int n = 0; n < s->nb_slices; n++) { + const uint8_t *dst = s->slices[n * s->planes + plane]; - for (i = 0; i < 256; i++) { - counts[i].prob++; - counts[i].value = i; + count_usage(dst, AV_CEIL_RSHIFT(avctx->width, s->hshift[plane]), + AV_CEIL_RSHIFT(s->slice_height, s->vshift[plane]), counts); + + for (int i = 0; i < 256; i++) { + counts[i].prob++; + counts[i].value = i; + } } magy_huffman_compute_bits(counts, he, codes_counts, 256, 12); calculate_codes(he, codes_counts); - for (i = 0; i < 256; i++) { + for (int i = 0; i < 256; i++) { put_bits(pb, 1, 0); put_bits(pb, 7, he[i].len); } @@ -410,13 +420,66 @@ static int encode_slice(uint8_t *src, uint8_t *dst, int dst_size, return put_bytes_output(&pb); } +static int predict_slice(AVCodecContext *avctx, void *tdata, + int n, int threadnr) +{ + const int aligned_width = FFALIGN(avctx->width, 16); + MagicYUVContext *s = avctx->priv_data; + const int slice_height = s->slice_height; + const int last_height = FFMIN(slice_height, avctx->height - n * slice_height); + const int height = (n < (s->nb_slices - 1)) ? slice_height : last_height; + const int width = avctx->width; + AVFrame *frame = tdata; + + if (s->correlate) { + uint8_t *decorrelated[2] = { s->decorrelate_buf[0] + n * slice_height * aligned_width, + s->decorrelate_buf[1] + n * slice_height * aligned_width }; + const int decorrelate_linesize = aligned_width; + const uint8_t *const data[4] = { decorrelated[0], frame->data[0] + n * slice_height * frame->linesize[0], + decorrelated[1], frame->data[3] + n * slice_height * frame->linesize[3] }; + const uint8_t *r, *g, *b; + const int linesize[4] = { decorrelate_linesize, frame->linesize[0], + decorrelate_linesize, frame->linesize[3] }; + + g = frame->data[0] + n * slice_height * frame->linesize[0]; + b = frame->data[1] + n * slice_height * frame->linesize[1]; + r = frame->data[2] + n * slice_height * frame->linesize[2]; + + for (int i = 0; i < slice_height; i++) { + s->llvidencdsp.diff_bytes(decorrelated[0], b, g, width); + s->llvidencdsp.diff_bytes(decorrelated[1], r, g, width); + g += frame->linesize[0]; + b += frame->linesize[1]; + r += frame->linesize[2]; + decorrelated[0] += decorrelate_linesize; + decorrelated[1] += decorrelate_linesize; + } + + for (int i = 0; i < s->planes; i++) { + s->predict(s, data[i], s->slices[n * s->planes + i], linesize[i], + frame->width, height); + } + } else { + for (int i = 0; i < s->planes; i++) { + s->predict(s, frame->data[i] + n * (slice_height >> s->vshift[i]) * frame->linesize[i], + s->slices[n * s->planes + i], + frame->linesize[i], + AV_CEIL_RSHIFT(frame->width, s->hshift[i]), + AV_CEIL_RSHIFT(height, s->vshift[i])); + } + } + + return 0; +} + static int magy_encode_frame(AVCodecContext *avctx, AVPacket *pkt, const AVFrame *frame, int *got_packet) { MagicYUVContext *s = avctx->priv_data; PutByteContext pb; const int width = avctx->width, height = avctx->height; - int pos, slice, i, j, ret = 0; + const int slice_height = s->slice_height; + int pos, ret = 0; ret = ff_alloc_packet(avctx, pkt, (256 + 4 * s->nb_slices + width * height) * s->planes + 256); @@ -439,92 +502,53 @@ static int magy_encode_frame(AVCodecContext *avctx, AVPacket *pkt, bytestream2_put_le32(&pb, avctx->width); bytestream2_put_le32(&pb, avctx->height); bytestream2_put_le32(&pb, avctx->width); - bytestream2_put_le32(&pb, avctx->height); + bytestream2_put_le32(&pb, slice_height); bytestream2_put_le32(&pb, 0); - for (i = 0; i < s->planes; i++) { + for (int i = 0; i < s->planes; i++) { bytestream2_put_le32(&pb, 0); - for (j = 1; j < s->nb_slices; j++) { + for (int j = 1; j < s->nb_slices; j++) bytestream2_put_le32(&pb, 0); - } } bytestream2_put_byte(&pb, s->planes); - for (i = 0; i < s->planes; i++) { - for (slice = 0; slice < s->nb_slices; slice++) { - bytestream2_put_byte(&pb, i); - } + for (int i = 0; i < s->planes; i++) { + for (int n = 0; n < s->nb_slices; n++) + bytestream2_put_byte(&pb, n * s->planes + i); } - if (s->correlate) { - uint8_t *decorrelated[2] = { s->decorrelate_buf[0], - s->decorrelate_buf[1] }; - const int decorrelate_linesize = FFALIGN(width, 16); - const uint8_t *const data[4] = { decorrelated[0], frame->data[0], - decorrelated[1], frame->data[3] }; - const uint8_t *r, *g, *b; - const int linesize[4] = { decorrelate_linesize, frame->linesize[0], - decorrelate_linesize, frame->linesize[3] }; - - g = frame->data[0]; - b = frame->data[1]; - r = frame->data[2]; - - for (i = 0; i < height; i++) { - s->llvidencdsp.diff_bytes(decorrelated[0], b, g, width); - s->llvidencdsp.diff_bytes(decorrelated[1], r, g, width); - g += frame->linesize[0]; - b += frame->linesize[1]; - r += frame->linesize[2]; - decorrelated[0] += decorrelate_linesize; - decorrelated[1] += decorrelate_linesize; - } - - for (i = 0; i < s->planes; i++) { - for (slice = 0; slice < s->nb_slices; slice++) { - s->predict(s, data[i], s->slices[i], linesize[i], - frame->width, frame->height); - } - } - } else { - for (i = 0; i < s->planes; i++) { - for (slice = 0; slice < s->nb_slices; slice++) { - s->predict(s, frame->data[i], s->slices[i], frame->linesize[i], - AV_CEIL_RSHIFT(frame->width, s->hshift[i]), - AV_CEIL_RSHIFT(frame->height, s->vshift[i])); - } - } - } + avctx->execute2(avctx, predict_slice, (void *)frame, NULL, s->nb_slices); init_put_bits(&s->pb, pkt->data + bytestream2_tell_p(&pb), bytestream2_get_bytes_left_p(&pb)); - for (i = 0; i < s->planes; i++) { - encode_table(avctx, s->slices[i], - AV_CEIL_RSHIFT(frame->width, s->hshift[i]), - AV_CEIL_RSHIFT(frame->height, s->vshift[i]), - &s->pb, s->he[i]); - } + for (int i = 0; i < s->planes; i++) + encode_table(avctx, &s->pb, s->he[i], i); + s->tables_size = put_bytes_count(&s->pb, 1); bytestream2_skip_p(&pb, s->tables_size); - for (i = 0; i < s->planes; i++) { - unsigned slice_size; - - s->slice_pos[i] = bytestream2_tell_p(&pb); - slice_size = encode_slice(s->slices[i], pkt->data + bytestream2_tell_p(&pb), - bytestream2_get_bytes_left_p(&pb), - AV_CEIL_RSHIFT(frame->width, s->hshift[i]), - AV_CEIL_RSHIFT(frame->height, s->vshift[i]), - s->he[i], s->frame_pred); - bytestream2_skip_p(&pb, slice_size); + for (int n = 0; n < s->nb_slices; n++) { + for (int i = 0; i < s->planes; i++) { + unsigned slice_size; + + s->slice_pos[n * s->planes + i] = bytestream2_tell_p(&pb); + slice_size = encode_slice(s->slices[n * s->planes + i], + pkt->data + bytestream2_tell_p(&pb), + bytestream2_get_bytes_left_p(&pb), + AV_CEIL_RSHIFT(frame->width, s->hshift[i]), + AV_CEIL_RSHIFT(slice_height, s->vshift[i]), + s->he[i], s->frame_pred); + bytestream2_skip_p(&pb, slice_size); + } } pos = bytestream2_tell_p(&pb); bytestream2_seek_p(&pb, 32, SEEK_SET); bytestream2_put_le32(&pb, s->slice_pos[0] - 32); - for (i = 0; i < s->planes; i++) { - bytestream2_put_le32(&pb, s->slice_pos[i] - 32); + for (int i = 0; i < s->planes; i++) { + for (int n = 0; n < s->nb_slices; n++) + bytestream2_put_le32(&pb, s->slice_pos[n * s->planes + i] - 32); } bytestream2_seek_p(&pb, pos, SEEK_SET); @@ -538,10 +562,11 @@ static int magy_encode_frame(AVCodecContext *avctx, AVPacket *pkt, static av_cold int magy_encode_close(AVCodecContext *avctx) { MagicYUVContext *s = avctx->priv_data; - int i; - for (i = 0; i < s->planes; i++) + av_freep(&s->slice_pos); + for (int i = 0; i < s->planes && s->slices; i++) av_freep(&s->slices[i]); + av_freep(&s->slices); av_freep(&s->decorrelate_buf); return 0; @@ -570,6 +595,7 @@ const FFCodec ff_magicyuv_encoder = { .p.type = AVMEDIA_TYPE_VIDEO, .p.id = AV_CODEC_ID_MAGICYUV, .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_FRAME_THREADS | + AV_CODEC_CAP_SLICE_THREADS | AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE, .priv_data_size = sizeof(MagicYUVContext), .p.priv_class = &magicyuv_class, From 828d3b4432dbd9f47526e13544e820c9212efc2f Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Wed, 31 May 2023 16:58:50 +0200 Subject: [PATCH 1381/2172] doc/examples/transcode: set packet timebase for decoding It is recommended for callers to set it, though not required. --- doc/examples/transcode.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/doc/examples/transcode.c b/doc/examples/transcode.c index 805a028ed73..84dd9fc8bca 100644 --- a/doc/examples/transcode.c +++ b/doc/examples/transcode.c @@ -97,6 +97,11 @@ static int open_input_file(const char *filename) "for stream #%u\n", i); return ret; } + + /* Inform the decoder about the timebase for the packet timestamps. + * This is highly recommended, but not mandatory. */ + codec_ctx->pkt_timebase = stream->time_base; + /* Reencode video & audio and remux subtitles etc. */ if (codec_ctx->codec_type == AVMEDIA_TYPE_VIDEO || codec_ctx->codec_type == AVMEDIA_TYPE_AUDIO) { From 811b0e02be44277211c3aea49f601330e2e52dcc Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Wed, 31 May 2023 16:58:50 +0200 Subject: [PATCH 1382/2172] doc/examples/transcode: stop using decoder's AVCodecContext.time_base The contents of this field are not defined for decoding. Use pkt_timebase, which is the timebase of demuxed packets. Drop a tautological av_packet_rescale_ts() call, as the stream and decoder timebases are the same. --- doc/examples/transcode.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/doc/examples/transcode.c b/doc/examples/transcode.c index 84dd9fc8bca..a486edc4722 100644 --- a/doc/examples/transcode.c +++ b/doc/examples/transcode.c @@ -271,7 +271,7 @@ static int init_filter(FilteringContext* fctx, AVCodecContext *dec_ctx, snprintf(args, sizeof(args), "video_size=%dx%d:pix_fmt=%d:time_base=%d/%d:pixel_aspect=%d/%d", dec_ctx->width, dec_ctx->height, dec_ctx->pix_fmt, - dec_ctx->time_base.num, dec_ctx->time_base.den, + dec_ctx->pkt_timebase.num, dec_ctx->pkt_timebase.den, dec_ctx->sample_aspect_ratio.num, dec_ctx->sample_aspect_ratio.den); @@ -311,7 +311,7 @@ static int init_filter(FilteringContext* fctx, AVCodecContext *dec_ctx, av_channel_layout_describe(&dec_ctx->ch_layout, buf, sizeof(buf)); snprintf(args, sizeof(args), "time_base=%d/%d:sample_rate=%d:sample_fmt=%s:channel_layout=%s", - dec_ctx->time_base.num, dec_ctx->time_base.den, dec_ctx->sample_rate, + dec_ctx->pkt_timebase.num, dec_ctx->pkt_timebase.den, dec_ctx->sample_rate, av_get_sample_fmt_name(dec_ctx->sample_fmt), buf); ret = avfilter_graph_create_filter(&buffersrc_ctx, buffersrc, "in", @@ -549,9 +549,6 @@ int main(int argc, char **argv) av_log(NULL, AV_LOG_DEBUG, "Going to reencode&filter the frame\n"); - av_packet_rescale_ts(packet, - ifmt_ctx->streams[stream_index]->time_base, - stream->dec_ctx->time_base); ret = avcodec_send_packet(stream->dec_ctx, packet); if (ret < 0) { av_log(NULL, AV_LOG_ERROR, "Decoding failed\n"); From ba32f284983037bcf65c8eb372703cd15bc35078 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Wed, 31 May 2023 16:58:50 +0200 Subject: [PATCH 1383/2172] doc/examples/transcode: convert timestamps between filtering and encoding The timebases do not have to match. --- doc/examples/transcode.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/doc/examples/transcode.c b/doc/examples/transcode.c index a486edc4722..305181663c7 100644 --- a/doc/examples/transcode.c +++ b/doc/examples/transcode.c @@ -441,6 +441,10 @@ static int encode_write_frame(unsigned int stream_index, int flush) /* encode filtered frame */ av_packet_unref(enc_pkt); + if (filt_frame && filt_frame->pts != AV_NOPTS_VALUE) + filt_frame->pts = av_rescale_q(filt_frame->pts, filt_frame->time_base, + stream->enc_ctx->time_base); + ret = avcodec_send_frame(stream->enc_ctx, filt_frame); if (ret < 0) @@ -495,6 +499,7 @@ static int filter_encode_write_frame(AVFrame *frame, unsigned int stream_index) break; } + filter->filtered_frame->time_base = av_buffersink_get_time_base(filter->buffersink_ctx);; filter->filtered_frame->pict_type = AV_PICTURE_TYPE_NONE; ret = encode_write_frame(stream_index, 0); av_frame_unref(filter->filtered_frame); From 2342c05e43573d3045e1648c586c613b95766080 Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Sat, 3 Jun 2023 10:49:08 +0200 Subject: [PATCH 1384/2172] avcodec/magicyuvenc: put some slice work under parallel execution Speeds up slice threaded encoding. --- libavcodec/magicyuvenc.c | 96 +++++++++++++++++++++++++++++++--------- 1 file changed, 74 insertions(+), 22 deletions(-) diff --git a/libavcodec/magicyuvenc.c b/libavcodec/magicyuvenc.c index a12ef5a33d4..082e2846c79 100644 --- a/libavcodec/magicyuvenc.c +++ b/libavcodec/magicyuvenc.c @@ -65,8 +65,12 @@ typedef struct MagicYUVContext { int hshift[4]; int vshift[4]; uint8_t **slices; + uint8_t **bitslices; + unsigned bitslice_size; unsigned *slice_pos; + unsigned *slice_size; unsigned tables_size; + PTable *counts; uint8_t *decorrelate_buf[2]; HuffEntry he[4][256]; LLVidEncDSPContext llvidencdsp; @@ -206,15 +210,20 @@ static av_cold int magy_encode_init(AVCodecContext *avctx) s->nb_slices = FFMAX(1, s->nb_slices); s->slice_height = FFALIGN((avctx->height + s->nb_slices - 1) / s->nb_slices, 1 << s->vshift[1]); s->slice_pos = av_calloc(s->nb_slices * s->planes, sizeof(*s->slice_pos)); + s->slice_size = av_calloc(s->nb_slices * s->planes, sizeof(*s->slice_size)); s->slices = av_calloc(s->nb_slices * s->planes, sizeof(*s->slices)); - if (!s->slices || !s->slice_pos) + s->bitslices = av_calloc(s->nb_slices * s->planes, sizeof(*s->bitslices)); + s->counts = av_calloc(s->nb_slices * s->planes * 256, sizeof(*s->counts)); + if (!s->slices || !s->slice_pos || !s->counts || !s->slice_size) return AVERROR(ENOMEM); + s->bitslice_size = avctx->width * (s->slice_height + 2) + AV_INPUT_BUFFER_PADDING_SIZE; for (int n = 0; n < s->nb_slices; n++) { for (int i = 0; i < s->planes; i++) { + s->bitslices[n * s->planes + i] = av_malloc(s->bitslice_size); s->slices[n * s->planes + i] = av_malloc(avctx->width * (s->slice_height + 2) + - AV_INPUT_BUFFER_PADDING_SIZE); - if (!s->slices[n * s->planes + i]) { + AV_INPUT_BUFFER_PADDING_SIZE); + if (!s->slices[n * s->planes + i] || !s->bitslices[n * s->planes + i]) { av_log(avctx, AV_LOG_ERROR, "Cannot allocate temporary buffer.\n"); return AVERROR(ENOMEM); } @@ -358,6 +367,20 @@ static void magy_huffman_compute_bits(PTable *prob_table, HuffEntry *distincts, } } +static int count_plane_slice(AVCodecContext *avctx, int n, int plane) +{ + MagicYUVContext *s = avctx->priv_data; + const uint8_t *dst = s->slices[n * s->planes + plane]; + PTable *counts = s->counts + 256 * (n * s->planes + plane); + + memset(counts, 0, sizeof(*counts) * 256); + + count_usage(dst, AV_CEIL_RSHIFT(avctx->width, s->hshift[plane]), + AV_CEIL_RSHIFT(s->slice_height, s->vshift[plane]), counts); + + return 0; +} + static int encode_table(AVCodecContext *avctx, PutBitContext *pb, HuffEntry *he, int plane) { @@ -366,15 +389,15 @@ static int encode_table(AVCodecContext *avctx, uint16_t codes_counts[33] = { 0 }; for (int n = 0; n < s->nb_slices; n++) { - const uint8_t *dst = s->slices[n * s->planes + plane]; + PTable *slice_counts = s->counts + 256 * (n * s->planes + plane); - count_usage(dst, AV_CEIL_RSHIFT(avctx->width, s->hshift[plane]), - AV_CEIL_RSHIFT(s->slice_height, s->vshift[plane]), counts); + for (int i = 0; i < 256; i++) + counts[i].prob = slice_counts[i].prob; + } - for (int i = 0; i < 256; i++) { - counts[i].prob++; - counts[i].value = i; - } + for (int i = 0; i < 256; i++) { + counts[i].prob++; + counts[i].value = i; } magy_huffman_compute_bits(counts, he, codes_counts, 256, 12); @@ -389,8 +412,8 @@ static int encode_table(AVCodecContext *avctx, return 0; } -static int encode_slice(uint8_t *src, uint8_t *dst, int dst_size, - int width, int height, HuffEntry *he, int prediction) +static int encode_plane_slice(uint8_t *src, uint8_t *dst, int dst_size, + int width, int height, HuffEntry *he, int prediction) { PutBitContext pb; int i, j; @@ -420,6 +443,31 @@ static int encode_slice(uint8_t *src, uint8_t *dst, int dst_size, return put_bytes_output(&pb); } +static int encode_slice(AVCodecContext *avctx, void *tdata, + int n, int threadnr) +{ + MagicYUVContext *s = avctx->priv_data; + const int slice_height = s->slice_height; + const int last_height = FFMIN(slice_height, avctx->height - n * slice_height); + const int height = (n < (s->nb_slices - 1)) ? slice_height : last_height; + PutByteContext pb; + + for (int i = 0; i < s->planes; i++) { + bytestream2_init_writer(&pb, s->bitslices[n + s->planes + i], + s->bitslice_size); + + s->slice_size[n * s->planes + i] = + encode_plane_slice(s->slices[n * s->planes + i], + s->bitslices[n * s->planes + i], + bytestream2_get_bytes_left_p(&pb), + AV_CEIL_RSHIFT(avctx->width, s->hshift[i]), + AV_CEIL_RSHIFT(height, s->vshift[i]), + s->he[i], s->frame_pred); + } + + return 0; +} + static int predict_slice(AVCodecContext *avctx, void *tdata, int n, int threadnr) { @@ -469,6 +517,9 @@ static int predict_slice(AVCodecContext *avctx, void *tdata, } } + for (int p = 0; p < s->planes; p++) + count_plane_slice(avctx, n, p); + return 0; } @@ -528,18 +579,14 @@ static int magy_encode_frame(AVCodecContext *avctx, AVPacket *pkt, s->tables_size = put_bytes_count(&s->pb, 1); bytestream2_skip_p(&pb, s->tables_size); + avctx->execute2(avctx, encode_slice, NULL, NULL, s->nb_slices); + for (int n = 0; n < s->nb_slices; n++) { for (int i = 0; i < s->planes; i++) { - unsigned slice_size; - s->slice_pos[n * s->planes + i] = bytestream2_tell_p(&pb); - slice_size = encode_slice(s->slices[n * s->planes + i], - pkt->data + bytestream2_tell_p(&pb), - bytestream2_get_bytes_left_p(&pb), - AV_CEIL_RSHIFT(frame->width, s->hshift[i]), - AV_CEIL_RSHIFT(slice_height, s->vshift[i]), - s->he[i], s->frame_pred); - bytestream2_skip_p(&pb, slice_size); + + bytestream2_put_buffer(&pb, s->bitslices[n * s->planes + i], + s->slice_size[n * s->planes + i]); } } @@ -564,9 +611,14 @@ static av_cold int magy_encode_close(AVCodecContext *avctx) MagicYUVContext *s = avctx->priv_data; av_freep(&s->slice_pos); - for (int i = 0; i < s->planes && s->slices; i++) + av_freep(&s->slice_size); + for (int i = 0; i < s->planes * s->nb_slices && s->slices; i++) av_freep(&s->slices[i]); + for (int i = 0; i < s->planes * s->nb_slices && s->bitslices; i++) + av_freep(&s->bitslices[i]); + av_freep(&s->counts); av_freep(&s->slices); + av_freep(&s->bitslices); av_freep(&s->decorrelate_buf); return 0; From cab6d7bd718f9987eb2d73af363f268e94b7582b Mon Sep 17 00:00:00 2001 From: Rick Kern Date: Sat, 3 Jun 2023 15:50:51 -0400 Subject: [PATCH 1385/2172] lavc/videotoolboxenc: use ffmpeg profile constants Signed-off-by: Rick Kern --- libavcodec/videotoolboxenc.c | 57 ++++++++++++++---------------------- 1 file changed, 22 insertions(+), 35 deletions(-) diff --git a/libavcodec/videotoolboxenc.c b/libavcodec/videotoolboxenc.c index b017c90c363..55a40195752 100644 --- a/libavcodec/videotoolboxenc.c +++ b/libavcodec/videotoolboxenc.c @@ -190,14 +190,7 @@ static void loadVTEncSymbols(void){ "EnableLowLatencyRateControl"); } -typedef enum VT_H264Profile { - H264_PROF_AUTO, - H264_PROF_BASELINE, - H264_PROF_MAIN, - H264_PROF_HIGH, - H264_PROF_EXTENDED, - H264_PROF_COUNT -} VT_H264Profile; +#define AUTO_PROFILE 0 typedef enum VTH264Entropy{ VT_ENTROPY_NOT_SET, @@ -205,13 +198,6 @@ typedef enum VTH264Entropy{ VT_CABAC } VTH264Entropy; -typedef enum VT_HEVCProfile { - HEVC_PROF_AUTO, - HEVC_PROF_MAIN, - HEVC_PROF_MAIN10, - HEVC_PROF_COUNT -} VT_HEVCProfile; - static const uint8_t start_code[] = { 0, 0, 0, 1 }; typedef struct ExtraSEI { @@ -730,18 +716,18 @@ static bool get_vt_h264_profile_level(AVCodecContext *avctx, VTEncContext *vtctx = avctx->priv_data; int64_t profile = vtctx->profile; - if (profile == H264_PROF_AUTO && vtctx->level) { + if (profile == AUTO_PROFILE && vtctx->level) { //Need to pick a profile if level is not auto-selected. - profile = vtctx->has_b_frames ? H264_PROF_MAIN : H264_PROF_BASELINE; + profile = vtctx->has_b_frames ? FF_PROFILE_H264_MAIN : FF_PROFILE_H264_BASELINE; } *profile_level_val = NULL; switch (profile) { - case H264_PROF_AUTO: + case AUTO_PROFILE: return true; - case H264_PROF_BASELINE: + case FF_PROFILE_H264_BASELINE: switch (vtctx->level) { case 0: *profile_level_val = compat_keys.kVTProfileLevel_H264_Baseline_AutoLevel; break; @@ -763,7 +749,7 @@ static bool get_vt_h264_profile_level(AVCodecContext *avctx, } break; - case H264_PROF_MAIN: + case FF_PROFILE_H264_MAIN: switch (vtctx->level) { case 0: *profile_level_val = compat_keys.kVTProfileLevel_H264_Main_AutoLevel; break; @@ -782,7 +768,7 @@ static bool get_vt_h264_profile_level(AVCodecContext *avctx, } break; - case H264_PROF_HIGH: + case FF_PROFILE_H264_HIGH: switch (vtctx->level) { case 0: *profile_level_val = compat_keys.kVTProfileLevel_H264_High_AutoLevel; break; @@ -805,7 +791,7 @@ static bool get_vt_h264_profile_level(AVCodecContext *avctx, compat_keys.kVTProfileLevel_H264_High_5_2; break; } break; - case H264_PROF_EXTENDED: + case FF_PROFILE_H264_EXTENDED: switch (vtctx->level) { case 0: *profile_level_val = compat_keys.kVTProfileLevel_H264_Extended_AutoLevel; break; @@ -838,13 +824,13 @@ static bool get_vt_hevc_profile_level(AVCodecContext *avctx, *profile_level_val = NULL; switch (profile) { - case HEVC_PROF_AUTO: + case AUTO_PROFILE: return true; - case HEVC_PROF_MAIN: + case FF_PROFILE_HEVC_MAIN: *profile_level_val = compat_keys.kVTProfileLevel_HEVC_Main_AutoLevel; break; - case HEVC_PROF_MAIN10: + case FF_PROFILE_HEVC_MAIN_10: *profile_level_val = compat_keys.kVTProfileLevel_HEVC_Main10_AutoLevel; break; @@ -1515,12 +1501,12 @@ static int vtenc_configure_encoder(AVCodecContext *avctx) vtctx->get_param_set_func = CMVideoFormatDescriptionGetH264ParameterSetAtIndex; vtctx->has_b_frames = avctx->max_b_frames > 0; - if(vtctx->has_b_frames && vtctx->profile == H264_PROF_BASELINE){ + if(vtctx->has_b_frames && (0xFF & vtctx->profile) == FF_PROFILE_H264_BASELINE){ av_log(avctx, AV_LOG_WARNING, "Cannot use B-frames with baseline profile. Output will not contain B-frames.\n"); vtctx->has_b_frames = 0; } - if (vtctx->entropy == VT_CABAC && vtctx->profile == H264_PROF_BASELINE) { + if (vtctx->entropy == VT_CABAC && (0xFF & vtctx->profile) == FF_PROFILE_H264_BASELINE) { av_log(avctx, AV_LOG_WARNING, "CABAC entropy requires 'main' or 'high' profile, but baseline was requested. Encode will not use CABAC entropy.\n"); vtctx->entropy = VT_ENTROPY_NOT_SET; } @@ -2756,11 +2742,12 @@ static const enum AVPixelFormat prores_pix_fmts[] = { #define OFFSET(x) offsetof(VTEncContext, x) static const AVOption h264_options[] = { - { "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" }, - { "extended", "Extend Profile", 0, AV_OPT_TYPE_CONST, { .i64 = H264_PROF_EXTENDED }, INT_MIN, INT_MAX, VE, "profile" }, + { "profile", "Profile", OFFSET(profile), AV_OPT_TYPE_INT64, { .i64 = AUTO_PROFILE }, 0, INT_MAX, VE, "profile" }, + { "constrained_baseline", "Constrained Baseline Profile", 0, AV_OPT_TYPE_CONST, { .i64 = FF_PROFILE_H264_CONSTRAINED_BASELINE }, INT_MIN, INT_MAX, VE, "profile" }, + { "baseline", "Baseline Profile", 0, AV_OPT_TYPE_CONST, { .i64 = FF_PROFILE_H264_BASELINE }, INT_MIN, INT_MAX, VE, "profile" }, + { "main", "Main Profile", 0, AV_OPT_TYPE_CONST, { .i64 = FF_PROFILE_H264_MAIN }, INT_MIN, INT_MAX, VE, "profile" }, + { "high", "High Profile", 0, AV_OPT_TYPE_CONST, { .i64 = FF_PROFILE_H264_HIGH }, INT_MIN, INT_MAX, VE, "profile" }, + { "extended", "Extend Profile", 0, AV_OPT_TYPE_CONST, { .i64 = FF_PROFILE_H264_EXTENDED }, INT_MIN, INT_MAX, VE, "profile" }, { "level", "Level", OFFSET(level), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 52, VE, "level" }, { "1.3", "Level 1.3, only available with Baseline Profile", 0, AV_OPT_TYPE_CONST, { .i64 = 13 }, INT_MIN, INT_MAX, VE, "level" }, @@ -2811,9 +2798,9 @@ const FFCodec ff_h264_videotoolbox_encoder = { }; static const AVOption hevc_options[] = { - { "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" }, + { "profile", "Profile", OFFSET(profile), AV_OPT_TYPE_INT64, { .i64 = AUTO_PROFILE }, 0, INT_MAX, VE, "profile" }, + { "main", "Main Profile", 0, AV_OPT_TYPE_CONST, { .i64 = FF_PROFILE_HEVC_MAIN }, INT_MIN, INT_MAX, VE, "profile" }, + { "main10", "Main10 Profile", 0, AV_OPT_TYPE_CONST, { .i64 = FF_PROFILE_HEVC_MAIN_10 }, INT_MIN, INT_MAX, VE, "profile" }, { "alpha_quality", "Compression quality for the alpha channel", OFFSET(alpha_quality), AV_OPT_TYPE_DOUBLE, { .dbl = 0.0 }, 0.0, 1.0, VE }, From decc776f887058f6ae6993521f0ca21b4bc3a2c7 Mon Sep 17 00:00:00 2001 From: xufuji456 <839789740@qq.com> Date: Sat, 3 Jun 2023 16:46:11 -0400 Subject: [PATCH 1386/2172] avcodec/videotoolboxenc: add CBP/CHP profile The CBP/CHP profile has available with H264 in iOS 15.0. Official Doc: https://developer.apple.com/documentation/videotoolbox/kvtprofilelevel_h264_constrainedbaseline_autolevel Signed-off-by: Rick Kern --- libavcodec/videotoolboxenc.c | 38 ++++++++++++++++++++++++++++++++---- 1 file changed, 34 insertions(+), 4 deletions(-) diff --git a/libavcodec/videotoolboxenc.c b/libavcodec/videotoolboxenc.c index 55a40195752..d1f73e0579f 100644 --- a/libavcodec/videotoolboxenc.c +++ b/libavcodec/videotoolboxenc.c @@ -108,6 +108,8 @@ static struct{ CFStringRef kVTProfileLevel_H264_High_AutoLevel; CFStringRef kVTProfileLevel_H264_Extended_5_0; CFStringRef kVTProfileLevel_H264_Extended_AutoLevel; + CFStringRef kVTProfileLevel_H264_ConstrainedBaseline_AutoLevel; + CFStringRef kVTProfileLevel_H264_ConstrainedHigh_AutoLevel; CFStringRef kVTProfileLevel_HEVC_Main_AutoLevel; CFStringRef kVTProfileLevel_HEVC_Main10_AutoLevel; @@ -171,6 +173,8 @@ static void loadVTEncSymbols(void){ GET_SYM(kVTProfileLevel_H264_High_AutoLevel, "H264_High_AutoLevel"); GET_SYM(kVTProfileLevel_H264_Extended_5_0, "H264_Extended_5_0"); GET_SYM(kVTProfileLevel_H264_Extended_AutoLevel, "H264_Extended_AutoLevel"); + GET_SYM(kVTProfileLevel_H264_ConstrainedBaseline_AutoLevel, "H264_ConstrainedBaseline_AutoLevel"); + GET_SYM(kVTProfileLevel_H264_ConstrainedHigh_AutoLevel, "H264_ConstrainedHigh_AutoLevel"); GET_SYM(kVTProfileLevel_HEVC_Main_AutoLevel, "HEVC_Main_AutoLevel"); GET_SYM(kVTProfileLevel_HEVC_Main10_AutoLevel, "HEVC_Main10_AutoLevel"); @@ -191,6 +195,7 @@ static void loadVTEncSymbols(void){ } #define AUTO_PROFILE 0 +#define H264_PROFILE_CONSTRAINED_HIGH (FF_PROFILE_H264_HIGH | FF_PROFILE_H264_CONSTRAINED) typedef enum VTH264Entropy{ VT_ENTROPY_NOT_SET, @@ -749,6 +754,18 @@ static bool get_vt_h264_profile_level(AVCodecContext *avctx, } break; + case FF_PROFILE_H264_CONSTRAINED_BASELINE: + *profile_level_val = compat_keys.kVTProfileLevel_H264_ConstrainedBaseline_AutoLevel; + + if (vtctx->level != 0) { + av_log(avctx, + AV_LOG_WARNING, + "Level is auto-selected when constrained-baseline " + "profile is used. The output may be encoded with a " + "different level.\n"); + } + break; + case FF_PROFILE_H264_MAIN: switch (vtctx->level) { case 0: *profile_level_val = @@ -768,6 +785,18 @@ static bool get_vt_h264_profile_level(AVCodecContext *avctx, } break; + case H264_PROFILE_CONSTRAINED_HIGH: + *profile_level_val = compat_keys.kVTProfileLevel_H264_ConstrainedHigh_AutoLevel; + + if (vtctx->level != 0) { + av_log(avctx, + AV_LOG_WARNING, + "Level is auto-selected when constrained-high profile " + "is used. The output may be encoded with a different " + "level.\n"); + } + break; + case FF_PROFILE_H264_HIGH: switch (vtctx->level) { case 0: *profile_level_val = @@ -2743,11 +2772,12 @@ static const enum AVPixelFormat prores_pix_fmts[] = { #define OFFSET(x) offsetof(VTEncContext, x) static const AVOption h264_options[] = { { "profile", "Profile", OFFSET(profile), AV_OPT_TYPE_INT64, { .i64 = AUTO_PROFILE }, 0, INT_MAX, VE, "profile" }, + { "baseline", "Baseline Profile", 0, AV_OPT_TYPE_CONST, { .i64 = FF_PROFILE_H264_BASELINE }, INT_MIN, INT_MAX, VE, "profile" }, { "constrained_baseline", "Constrained Baseline Profile", 0, AV_OPT_TYPE_CONST, { .i64 = FF_PROFILE_H264_CONSTRAINED_BASELINE }, INT_MIN, INT_MAX, VE, "profile" }, - { "baseline", "Baseline Profile", 0, AV_OPT_TYPE_CONST, { .i64 = FF_PROFILE_H264_BASELINE }, INT_MIN, INT_MAX, VE, "profile" }, - { "main", "Main Profile", 0, AV_OPT_TYPE_CONST, { .i64 = FF_PROFILE_H264_MAIN }, INT_MIN, INT_MAX, VE, "profile" }, - { "high", "High Profile", 0, AV_OPT_TYPE_CONST, { .i64 = FF_PROFILE_H264_HIGH }, INT_MIN, INT_MAX, VE, "profile" }, - { "extended", "Extend Profile", 0, AV_OPT_TYPE_CONST, { .i64 = FF_PROFILE_H264_EXTENDED }, INT_MIN, INT_MAX, VE, "profile" }, + { "main", "Main Profile", 0, AV_OPT_TYPE_CONST, { .i64 = FF_PROFILE_H264_MAIN }, INT_MIN, INT_MAX, VE, "profile" }, + { "high", "High Profile", 0, AV_OPT_TYPE_CONST, { .i64 = FF_PROFILE_H264_HIGH }, INT_MIN, INT_MAX, VE, "profile" }, + { "constrained_high", "Constrained High Profile", 0, AV_OPT_TYPE_CONST, { .i64 = H264_PROFILE_CONSTRAINED_HIGH }, INT_MIN, INT_MAX, VE, "profile" }, + { "extended", "Extend Profile", 0, AV_OPT_TYPE_CONST, { .i64 = FF_PROFILE_H264_EXTENDED }, INT_MIN, INT_MAX, VE, "profile" }, { "level", "Level", OFFSET(level), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 52, VE, "level" }, { "1.3", "Level 1.3, only available with Baseline Profile", 0, AV_OPT_TYPE_CONST, { .i64 = 13 }, INT_MIN, INT_MAX, VE, "level" }, From 4ef5e7d47227fda15976bd70d17f325631730ff2 Mon Sep 17 00:00:00 2001 From: Rick Kern Date: Sat, 20 May 2023 18:14:05 -0400 Subject: [PATCH 1387/2172] lavc/videotoolboxenc: support additional options Added support for more VideoToolbox encoder options: - qmin and qmax options are now used - max_slice_bytes: Max number of bytes per H.264 slice - max_ref_frames: Limit the number of reference frames - Disable open GOP when the cgop flag is set - power_efficient: Enable power-efficient mode Signed-off-by: Rick Kern --- libavcodec/videotoolboxenc.c | 122 ++++++++++++++++++++++++++++++++++- 1 file changed, 121 insertions(+), 1 deletion(-) diff --git a/libavcodec/videotoolboxenc.c b/libavcodec/videotoolboxenc.c index d1f73e0579f..9719e0bf544 100644 --- a/libavcodec/videotoolboxenc.c +++ b/libavcodec/videotoolboxenc.c @@ -122,6 +122,11 @@ static struct{ CFStringRef kVTVideoEncoderSpecification_EnableHardwareAcceleratedVideoEncoder; CFStringRef kVTVideoEncoderSpecification_RequireHardwareAcceleratedVideoEncoder; CFStringRef kVTVideoEncoderSpecification_EnableLowLatencyRateControl; + CFStringRef kVTCompressionPropertyKey_AllowOpenGOP; + CFStringRef kVTCompressionPropertyKey_MaximizePowerEfficiency; + CFStringRef kVTCompressionPropertyKey_ReferenceBufferCount; + CFStringRef kVTCompressionPropertyKey_MaxAllowedFrameQP; + CFStringRef kVTCompressionPropertyKey_MinAllowedFrameQP; getParameterSetAtIndex CMVideoFormatDescriptionGetHEVCParameterSetAtIndex; } compat_keys; @@ -192,6 +197,13 @@ static void loadVTEncSymbols(void){ "RequireHardwareAcceleratedVideoEncoder"); GET_SYM(kVTVideoEncoderSpecification_EnableLowLatencyRateControl, "EnableLowLatencyRateControl"); + GET_SYM(kVTCompressionPropertyKey_AllowOpenGOP, "AllowOpenGOP"); + GET_SYM(kVTCompressionPropertyKey_MaximizePowerEfficiency, + "MaximizePowerEfficiency"); + GET_SYM(kVTCompressionPropertyKey_ReferenceBufferCount, + "ReferenceBufferCount"); + GET_SYM(kVTCompressionPropertyKey_MaxAllowedFrameQP, "MaxAllowedFrameQP"); + GET_SYM(kVTCompressionPropertyKey_MinAllowedFrameQP, "MinAllowedFrameQP"); } #define AUTO_PROFILE 0 @@ -259,6 +271,10 @@ typedef struct VTEncContext { /* can't be bool type since AVOption will access it as int */ int a53_cc; + + int max_slice_bytes; + int power_efficient; + int max_ref_frames; } VTEncContext; static int vtenc_populate_extradata(AVCodecContext *avctx, @@ -1121,6 +1137,47 @@ static bool vtenc_qscale_enabled(void) return !TARGET_OS_IPHONE && TARGET_CPU_ARM64; } +static void set_encoder_property_or_log(AVCodecContext *avctx, + CFStringRef key, + const char *print_option_name, + CFTypeRef value) { + int status; + VTEncContext *vtctx = avctx->priv_data; + + status = VTSessionSetProperty(vtctx->session, key, value); + if (status == kVTPropertyNotSupportedErr) { + av_log(avctx, + AV_LOG_INFO, + "This device does not support the %s option. Value ignored.\n", + print_option_name); + } else if (status != 0) { + av_log(avctx, + AV_LOG_ERROR, + "Error setting %s: Error %d\n", + print_option_name, + status); + } +} + +static int set_encoder_int_property_or_log(AVCodecContext* avctx, + CFStringRef key, + const char* print_option_name, + int value) { + CFNumberRef value_cfnum = CFNumberCreate(kCFAllocatorDefault, + kCFNumberIntType, + &value); + + if (value_cfnum == NULL) { + return AVERROR(ENOMEM); + } + + set_encoder_property_or_log(avctx, key, print_option_name, value_cfnum); + + CFRelease(value_cfnum); + + return 0; +} + static int vtenc_create_encoder(AVCodecContext *avctx, CMVideoCodecType codec_type, CFStringRef profile_level, @@ -1491,6 +1548,64 @@ static int vtenc_create_encoder(AVCodecContext *avctx, } } + if ((avctx->flags & AV_CODEC_FLAG_CLOSED_GOP) != 0) { + set_encoder_property_or_log(avctx, + compat_keys.kVTCompressionPropertyKey_AllowOpenGOP, + "AllowOpenGop", + kCFBooleanFalse); + } + + if (avctx->qmin >= 0) { + status = set_encoder_int_property_or_log(avctx, + compat_keys.kVTCompressionPropertyKey_MinAllowedFrameQP, + "qmin", + avctx->qmin); + + if (status != 0) { + return status; + } + } + + if (avctx->qmax >= 0) { + status = set_encoder_int_property_or_log(avctx, + compat_keys.kVTCompressionPropertyKey_MaxAllowedFrameQP, + "qmax", + avctx->qmax); + + if (status != 0) { + return status; + } + } + + if (vtctx->max_slice_bytes >= 0 && avctx->codec_id == AV_CODEC_ID_H264) { + status = set_encoder_int_property_or_log(avctx, + kVTCompressionPropertyKey_MaxH264SliceBytes, + "max_slice_bytes", + vtctx->max_slice_bytes); + + if (status != 0) { + return status; + } + } + + if (vtctx->power_efficient >= 0) { + set_encoder_property_or_log(avctx, + compat_keys.kVTCompressionPropertyKey_MaximizePowerEfficiency, + "power_efficient", + vtctx->power_efficient ? kCFBooleanTrue : kCFBooleanFalse); + } + + if (vtctx->max_ref_frames > 0) { + status = set_encoder_int_property_or_log(avctx, + compat_keys.kVTCompressionPropertyKey_ReferenceBufferCount, + "max_ref_frames", + vtctx->max_ref_frames); + + if (status != 0) { + return status; + } + } + status = VTCompressionSessionPrepareToEncodeFrames(vtctx->session); if (status) { av_log(avctx, AV_LOG_ERROR, "Error: cannot prepare encoder: %d\n", status); @@ -2768,6 +2883,11 @@ static const enum AVPixelFormat prores_pix_fmts[] = { OFFSET(frames_after), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, VE }, \ { "prio_speed", "prioritize encoding speed", OFFSET(prio_speed), AV_OPT_TYPE_BOOL, \ { .i64 = -1 }, -1, 1, VE }, \ + { "power_efficient", "Set to 1 to enable more power-efficient encoding if supported.", \ + OFFSET(power_efficient), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, 1, VE }, \ + { "max_ref_frames", \ + "Sets the maximum number of reference frames. This only has an effect when the value is less than the maximum allowed by the profile/level.", \ + OFFSET(max_ref_frames), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, INT_MAX, VE }, #define OFFSET(x) offsetof(VTEncContext, x) static const AVOption h264_options[] = { @@ -2800,7 +2920,7 @@ static const AVOption h264_options[] = { { "a53cc", "Use A53 Closed Captions (if available)", OFFSET(a53_cc), AV_OPT_TYPE_BOOL, {.i64 = 1}, 0, 1, VE }, { "constant_bit_rate", "Require constant bit rate (macOS 13 or newer)", OFFSET(constant_bit_rate), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, VE }, - + { "max_slice_bytes", "Set the maximum number of bytes in an H.264 slice.", OFFSET(max_slice_bytes), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, INT_MAX, VE }, COMMON_OPTIONS { NULL }, }; From 378fb4028294bcf27df09d145a1f6ab1d014924e Mon Sep 17 00:00:00 2001 From: Philip Langdale Date: Fri, 2 Jun 2023 16:24:46 -0700 Subject: [PATCH 1388/2172] avutil/hwcontext_vulkan: disable multiplane when deriving from cuda Today, cuda is not able to import multiplane images, and cuda requires images to be imported whether you trying to import to cuda or export from cuda (in the later case, the image is imported and then copied into on the cuda side). So any interop between cuda and vulkan requires that multiplane be disabled. The existing option for this is not sufficient, because when deriving devices it is not possible to specify any options. And, it is necessary to derive the Vulkan device, because any pipeline that involves uploading from cuda to vulkan and then back to cuda must use the same cuda context on both sides, and the only way to propagate the cuda context all the way through is to derive the device at each stage. ie: -vf hwupload=derive_device=vulkan,,hwupload=derive_device=cuda --- libavutil/hwcontext_vulkan.c | 25 ++++++++++++++++++------- 1 file changed, 18 insertions(+), 7 deletions(-) diff --git a/libavutil/hwcontext_vulkan.c b/libavutil/hwcontext_vulkan.c index e8241638d91..ec084d94d78 100644 --- a/libavutil/hwcontext_vulkan.c +++ b/libavutil/hwcontext_vulkan.c @@ -1180,6 +1180,7 @@ static void vulkan_device_free(AVHWDeviceContext *ctx) static int vulkan_device_create_internal(AVHWDeviceContext *ctx, VulkanDeviceSelection *dev_select, + int disable_multiplane, AVDictionary *opts, int flags) { int err = 0; @@ -1335,9 +1336,15 @@ 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, "disable_multiplane", NULL, 0); - if (opt_d) - p->disable_multiplane = strtol(opt_d->value, NULL, 10); + /* + * The disable_multiplane argument takes precedent over the option. + */ + p->disable_multiplane = disable_multiplane; + if (!p->disable_multiplane) { + opt_d = av_dict_get(opts, "disable_multiplane", NULL, 0); + if (opt_d) + p->disable_multiplane = strtol(opt_d->value, NULL, 10); + } hwctx->enabled_dev_extensions = dev_info.ppEnabledExtensionNames; hwctx->nb_enabled_dev_extensions = dev_info.enabledExtensionCount; @@ -1511,7 +1518,7 @@ static int vulkan_device_create(AVHWDeviceContext *ctx, const char *device, } } - return vulkan_device_create_internal(ctx, &dev_select, opts, flags); + return vulkan_device_create_internal(ctx, &dev_select, 0, opts, flags); } static int vulkan_device_derive(AVHWDeviceContext *ctx, @@ -1537,7 +1544,7 @@ static int vulkan_device_derive(AVHWDeviceContext *ctx, if (strstr(vendor, "AMD")) dev_select.vendor_id = 0x1002; - return vulkan_device_create_internal(ctx, &dev_select, opts, flags); + return vulkan_device_create_internal(ctx, &dev_select, 0, opts, flags); } #endif #if CONFIG_LIBDRM @@ -1570,7 +1577,7 @@ static int vulkan_device_derive(AVHWDeviceContext *ctx, drmFreeDevice(&drm_dev_info); - return vulkan_device_create_internal(ctx, &dev_select, opts, flags); + return vulkan_device_create_internal(ctx, &dev_select, 0, opts, flags); } #endif #if CONFIG_CUDA @@ -1589,7 +1596,11 @@ static int vulkan_device_derive(AVHWDeviceContext *ctx, dev_select.has_uuid = 1; - return vulkan_device_create_internal(ctx, &dev_select, opts, flags); + /* + * CUDA is not able to import multiplane images, so always derive a + * Vulkan device with multiplane disabled. + */ + return vulkan_device_create_internal(ctx, &dev_select, 1, opts, flags); } #endif default: From b92af7b64e7acd015aea3ae1da2228c5a7e677bf Mon Sep 17 00:00:00 2001 From: Jeremy Wu Date: Tue, 25 Apr 2023 06:09:52 +0000 Subject: [PATCH 1389/2172] avcodec/aacenc: add strict bit rate control option In certain use cases, controlling the maximum frame size is critical. An example is when transmitting AAC packets over Bluetooth A2DP. While the spec allows the packets to be fragmented (but UNRECOMMENDED), in practice most headsets do not recognize nor reassemble such packets. In this patch, we allow setting `bit_rate_tolerance` to 0 to indicate that the specified bit rate should be treated as an upper bound up to frame level. Signed-off-by: Jeremy Wu --- libavcodec/aacenc.c | 12 ++++++++++++ libavcodec/options_table.h | 2 +- 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/libavcodec/aacenc.c b/libavcodec/aacenc.c index ed036209e92..f48f0570221 100644 --- a/libavcodec/aacenc.c +++ b/libavcodec/aacenc.c @@ -1106,6 +1106,18 @@ static int aac_encode_frame(AVCodecContext *avctx, AVPacket *avpkt, too_many_bits = FFMIN(too_many_bits, 6144 * s->channels - 3); too_few_bits = FFMIN(FFMAX(rate_bits - rate_bits/4, target_bits), too_many_bits); + /* When strict bit-rate control is demanded */ + if (avctx->bit_rate_tolerance == 0) { + if (rate_bits < frame_bits) { + float ratio = ((float)rate_bits) / frame_bits; + s->lambda *= FFMIN(0.9f, ratio); + continue; + } + /* reset lambda when solution is found */ + s->lambda = avctx->global_quality > 0 ? avctx->global_quality : 120; + break; + } + /* When using ABR, be strict (but only for increasing) */ too_few_bits = too_few_bits - too_few_bits/8; too_many_bits = too_many_bits + too_many_bits/2; diff --git a/libavcodec/options_table.h b/libavcodec/options_table.h index 03059cc39c9..f1a9729c0d0 100644 --- a/libavcodec/options_table.h +++ b/libavcodec/options_table.h @@ -50,7 +50,7 @@ static const AVOption avcodec_options[] = { {"bt", "Set video bitrate tolerance (in bits/s). In 1-pass mode, bitrate tolerance specifies how far " "ratecontrol is willing to deviate from the target average bitrate value. This is not related " "to minimum/maximum bitrate. Lowering tolerance too much has an adverse effect on quality.", - OFFSET(bit_rate_tolerance), AV_OPT_TYPE_INT, {.i64 = AV_CODEC_DEFAULT_BITRATE*20 }, 1, INT_MAX, V|E}, + OFFSET(bit_rate_tolerance), AV_OPT_TYPE_INT, {.i64 = AV_CODEC_DEFAULT_BITRATE*20 }, 0, INT_MAX, A|V|E}, {"flags", NULL, OFFSET(flags), AV_OPT_TYPE_FLAGS, {.i64 = DEFAULT }, 0, UINT_MAX, V|A|S|E|D, "flags"}, {"unaligned", "allow decoders to produce unaligned output", 0, AV_OPT_TYPE_CONST, { .i64 = AV_CODEC_FLAG_UNALIGNED }, INT_MIN, INT_MAX, V | D, "flags" }, {"mv4", "use four motion vectors per macroblock (MPEG-4)", 0, AV_OPT_TYPE_CONST, {.i64 = AV_CODEC_FLAG_4MV }, INT_MIN, INT_MAX, V|E, "flags"}, From cbe5e480aa1679c1dfc20d433e310acd7449af07 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Sat, 4 Mar 2023 23:58:08 +0100 Subject: [PATCH 1390/2172] avcodec/rka: use 64bit for srate_pad computation Fixes: left shift of 538976288 by 13 places cannot be represented in type 'int' Fixes: 56148/clusterfuzz-testcase-minimized-ffmpeg_AV_CODEC_ID_RKA_fuzzer-6257370708967424 Found-by: continuous fuzzing process https://github.com/google/oss-fuzz/tree/master/projects/ffmpeg Signed-off-by: Michael Niedermayer --- libavcodec/rka.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavcodec/rka.c b/libavcodec/rka.c index 3e86d83819c..ce39a902afb 100644 --- a/libavcodec/rka.c +++ b/libavcodec/rka.c @@ -207,7 +207,7 @@ static int chctx_init(RKAContext *s, ChContext *c, c->bprob[0] = s->bprob[0]; c->bprob[1] = s->bprob[1]; - c->srate_pad = (sample_rate << 13) / 44100 & 0xFFFFFFFCU; + c->srate_pad = ((int64_t)sample_rate << 13) / 44100 & 0xFFFFFFFCU; c->pos_idx = 1; for (int i = 0; i < FF_ARRAY_ELEMS(s->bprob[0]); i++) From b168aeb734069b09ab174666169f9c5dd631fb1b Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Tue, 2 May 2023 01:09:58 +0200 Subject: [PATCH 1391/2172] avcodec/rka: avoid undefined multiply in cmode==0 Fixes: signed integer overflow: -182838 * 32768 cannot be represented in type 'int' Fixes: 58179/clusterfuzz-testcase-minimized-ffmpeg_AV_CODEC_ID_RKA_fuzzer-5333265899978752 Found-by: continuous fuzzing process https://github.com/google/oss-fuzz/tree/master/projects/ffmpeg Signed-off-by: Michael Niedermayer --- libavcodec/rka.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavcodec/rka.c b/libavcodec/rka.c index ce39a902afb..e0ed8c16e44 100644 --- a/libavcodec/rka.c +++ b/libavcodec/rka.c @@ -732,7 +732,7 @@ static int decode_filter(RKAContext *s, ChContext *ctx, ACoder *ac, int off, uns if (bits == 0) { ctx->buf1[off] = sum + val; } else { - ctx->buf1[off] = (val + (sum >> bits)) * (1 << bits) + + ctx->buf1[off] = (val + (sum >> bits)) * (1U << bits) + (((1U << bits) - 1U) & ctx->buf1[off + -1]); } ctx->buf0[off] = ctx->buf1[off] + ctx->buf0[off + -1]; From b1c3d81e71f78e4b3b2c2901ac4649cb74aec272 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Tue, 2 May 2023 01:46:31 +0200 Subject: [PATCH 1392/2172] avformat/oggparsetheora: clip duration within 64bit Fixes: signed integer overflow: 9079256848778919936 - -288230376151711746 cannot be represented in type 'long' Fixes: 58248/clusterfuzz-testcase-minimized-ffmpeg_dem_OGG_fuzzer-6326851353313280 Found-by: continuous fuzzing process https://github.com/google/oss-fuzz/tree/master/projects/ffmpeg Signed-off-by: Michael Niedermayer --- libavformat/oggparsetheora.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavformat/oggparsetheora.c b/libavformat/oggparsetheora.c index b9184eff7b1..85119352c3b 100644 --- a/libavformat/oggparsetheora.c +++ b/libavformat/oggparsetheora.c @@ -196,7 +196,7 @@ static int theora_packet(AVFormatContext *s, int idx) if(s->streams[idx]->start_time == AV_NOPTS_VALUE && os->lastpts != AV_NOPTS_VALUE) { s->streams[idx]->start_time = os->lastpts; if (s->streams[idx]->duration > 0) - s->streams[idx]->duration -= s->streams[idx]->start_time; + s->streams[idx]->duration = av_sat_sub64(s->streams[idx]->duration, s->streams[idx]->start_time); } } From 09af34dc919236916d71b9f0f1997f9aff4e4048 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Sat, 3 Jun 2023 18:53:54 +0200 Subject: [PATCH 1393/2172] tests/fate/ffmpeg: add tests for -max_error_rate --- tests/fate/ffmpeg.mak | 6 ++++++ tests/ref/fate/ffmpeg-error-rate-fail | 0 tests/ref/fate/ffmpeg-error-rate-pass | 0 3 files changed, 6 insertions(+) create mode 100644 tests/ref/fate/ffmpeg-error-rate-fail create mode 100644 tests/ref/fate/ffmpeg-error-rate-pass diff --git a/tests/fate/ffmpeg.mak b/tests/fate/ffmpeg.mak index 800f3a03d2b..223bc97f8e4 100644 --- a/tests/fate/ffmpeg.mak +++ b/tests/fate/ffmpeg.mak @@ -227,3 +227,9 @@ FATE_SAMPLES_FFMPEG-yes += $(FATE_TIME_BASE-yes) # test -r used as an input option fate-ffmpeg-input-r: CMD = framecrc -r 27 -idct simple -i $(TARGET_SAMPLES)/mpeg2/sony-ct3.bs FATE_SAMPLES_FFMPEG-$(call FRAMECRC, MPEGVIDEO, MPEG2VIDEO) += fate-ffmpeg-input-r + +# file with completely undecodable TTA audio stream +# by default should exit with error code 69 +fate-ffmpeg-error-rate-fail: CMD = ffmpeg -i $(TARGET_SAMPLES)/mkv/h264_tta_undecodable.mkv -c:v copy -f null -; test $$? -eq 69 +fate-ffmpeg-error-rate-pass: CMD = ffmpeg -i $(TARGET_SAMPLES)/mkv/h264_tta_undecodable.mkv -c:v copy -f null - -max_error_rate 1 +FATE_SAMPLES_FFMPEG-$(call ENCDEC, PCM_S16LE TTA, NULL MATROSKA) += fate-ffmpeg-error-rate-fail fate-ffmpeg-error-rate-pass diff --git a/tests/ref/fate/ffmpeg-error-rate-fail b/tests/ref/fate/ffmpeg-error-rate-fail new file mode 100644 index 00000000000..e69de29bb2d diff --git a/tests/ref/fate/ffmpeg-error-rate-pass b/tests/ref/fate/ffmpeg-error-rate-pass new file mode 100644 index 00000000000..e69de29bb2d From ba1141d8a9a50f66b7cdc62bec59a536f6ece568 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Sun, 28 May 2023 16:51:57 +0200 Subject: [PATCH 1394/2172] fftools/ffmpeg_enc: move nb_frames{dup,drop} globals into OutputStream --- fftools/ffmpeg.c | 6 ++++-- fftools/ffmpeg.h | 6 +++--- fftools/ffmpeg_enc.c | 8 ++++---- 3 files changed, 11 insertions(+), 9 deletions(-) diff --git a/fftools/ffmpeg.c b/fftools/ffmpeg.c index 36b4becaf2b..bcda7570e9e 100644 --- a/fftools/ffmpeg.c +++ b/fftools/ffmpeg.c @@ -119,8 +119,6 @@ typedef struct BenchmarkTimeStamps { static BenchmarkTimeStamps get_benchmark_time_stamps(void); static int64_t getmaxrss(void); -int64_t nb_frames_dup = 0; -int64_t nb_frames_drop = 0; unsigned nb_output_dumped = 0; static BenchmarkTimeStamps current_time; @@ -491,6 +489,7 @@ static void print_report(int is_last_report, int64_t timer_start, int64_t cur_ti int64_t pts = INT64_MIN + 1; static int64_t last_time = -1; static int first_report = 1; + uint64_t nb_frames_dup = 0, nb_frames_drop = 0; int hours, mins, secs, us; const char *hours_sign; int ret; @@ -536,6 +535,9 @@ static void print_report(int is_last_report, int64_t timer_start, int64_t cur_ti if (is_last_report) av_bprintf(&buf, "L"); + nb_frames_dup = ost->nb_frames_dup; + nb_frames_drop = ost->nb_frames_drop; + vid = 1; } /* compute min output value */ diff --git a/fftools/ffmpeg.h b/fftools/ffmpeg.h index 966397270d1..cef4b5d000a 100644 --- a/fftools/ffmpeg.h +++ b/fftools/ffmpeg.h @@ -553,6 +553,9 @@ typedef struct OutputStream { Encoder *enc; AVCodecContext *enc_ctx; AVPacket *pkt; + + uint64_t nb_frames_dup; + uint64_t nb_frames_drop; int64_t last_dropped; /* video only */ @@ -707,9 +710,6 @@ extern int recast_media; extern FILE *vstats_file; -extern int64_t nb_frames_dup; -extern int64_t nb_frames_drop; - #if FFMPEG_OPT_PSNR extern int do_psnr; #endif diff --git a/fftools/ffmpeg_enc.c b/fftools/ffmpeg_enc.c index 6c9cce252f7..f3e291a9e49 100644 --- a/fftools/ffmpeg_enc.c +++ b/fftools/ffmpeg_enc.c @@ -1078,7 +1078,7 @@ static void do_video_out(OutputFile *of, OutputStream *ost, AVFrame *frame) &nb_frames, &nb_frames_prev); if (nb_frames_prev == 0 && ost->last_dropped) { - nb_frames_drop++; + ost->nb_frames_drop++; av_log(ost, AV_LOG_VERBOSE, "*** dropping frame %"PRId64" at ts %"PRId64"\n", e->vsync_frame_number, e->last_frame->pts); @@ -1086,12 +1086,12 @@ static void do_video_out(OutputFile *of, OutputStream *ost, AVFrame *frame) if (nb_frames > (nb_frames_prev && ost->last_dropped) + (nb_frames > nb_frames_prev)) { if (nb_frames > dts_error_threshold * 30) { av_log(ost, AV_LOG_ERROR, "%"PRId64" frame duplication too large, skipping\n", nb_frames - 1); - nb_frames_drop++; + ost->nb_frames_drop++; return; } - nb_frames_dup += nb_frames - (nb_frames_prev && ost->last_dropped) - (nb_frames > nb_frames_prev); + ost->nb_frames_dup += nb_frames - (nb_frames_prev && ost->last_dropped) - (nb_frames > nb_frames_prev); av_log(ost, AV_LOG_VERBOSE, "*** %"PRId64" dup!\n", nb_frames - 1); - if (nb_frames_dup > dup_warning) { + if (ost->nb_frames_dup > dup_warning) { av_log(ost, AV_LOG_WARNING, "More than %"PRIu64" frames duplicated\n", dup_warning); dup_warning *= 10; } From 57021a68d94b3f48cda7f567d645ae9425d45101 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Sun, 28 May 2023 10:43:36 +0200 Subject: [PATCH 1395/2172] fftools/ffmpeg_mux: set stream duration after the timebase is certainly known Stop assuming the encoder knows the muxing timebase, which does not always have to hold (e.g. due to bitstream filters). --- fftools/ffmpeg_enc.c | 4 ---- fftools/ffmpeg_mux.c | 5 +++++ fftools/ffmpeg_mux.h | 3 +++ fftools/ffmpeg_mux_init.c | 10 ++++++---- 4 files changed, 14 insertions(+), 8 deletions(-) diff --git a/fftools/ffmpeg_enc.c b/fftools/ffmpeg_enc.c index f3e291a9e49..fab71ca0c06 100644 --- a/fftools/ffmpeg_enc.c +++ b/fftools/ffmpeg_enc.c @@ -445,10 +445,6 @@ int enc_open(OutputStream *ost, AVFrame *frame) if (ost->st->time_base.num <= 0 || ost->st->time_base.den <= 0) ost->st->time_base = av_add_q(ost->enc_ctx->time_base, (AVRational){0, 1}); - // copy estimated duration as a hint to the muxer - if (ost->st->duration <= 0 && ist && ist->st->duration > 0) - ost->st->duration = av_rescale_q(ist->st->duration, ist->st->time_base, ost->st->time_base); - ost->mux_timebase = enc_ctx->time_base; ret = of_stream_init(of, ost); diff --git a/fftools/ffmpeg_mux.c b/fftools/ffmpeg_mux.c index feb014ca311..121796a55ad 100644 --- a/fftools/ffmpeg_mux.c +++ b/fftools/ffmpeg_mux.c @@ -666,6 +666,11 @@ int of_stream_init(OutputFile *of, OutputStream *ost) if (ret < 0) return ret; + if (ms->stream_duration) { + ost->st->duration = av_rescale_q(ms->stream_duration, ms->stream_duration_tb, + ost->st->time_base); + } + ost->initialized = 1; return mux_check_init(mux); diff --git a/fftools/ffmpeg_mux.h b/fftools/ffmpeg_mux.h index 7e0454dfba2..bee7addd6a1 100644 --- a/fftools/ffmpeg_mux.h +++ b/fftools/ffmpeg_mux.h @@ -69,6 +69,9 @@ typedef struct MuxStream { * used for making up missing dts values */ int64_t last_mux_dts; + int64_t stream_duration; + AVRational stream_duration_tb; + // audio streamcopy - state for av_rescale_delta() int64_t ts_rescale_delta_last; diff --git a/fftools/ffmpeg_mux_init.c b/fftools/ffmpeg_mux_init.c index 4fc6f0fb46a..33c93e40f2e 100644 --- a/fftools/ffmpeg_mux_init.c +++ b/fftools/ffmpeg_mux_init.c @@ -914,10 +914,6 @@ static int streamcopy_init(const Muxer *mux, OutputStream *ost) ost->st->time_base = av_add_q(av_stream_get_codec_timebase(ost->st), (AVRational){0, 1}); } - // copy estimated duration as a hint to the muxer - 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); - if (!ms->copy_prior_start) { ms->ts_copy_start = (mux->of.start_time == AV_NOPTS_VALUE) ? 0 : mux->of.start_time; @@ -1283,6 +1279,12 @@ static OutputStream *ost_add(Muxer *mux, const OptionsContext *o, exit_program(1); } + // copy estimated duration as a hint to the muxer + if (ost->ist && ost->ist->st->duration > 0) { + ms->stream_duration = ist->st->duration; + ms->stream_duration_tb = ist->st->time_base; + } + return ost; } From ad14bdbcfd0fbc349c7f747d0427956ec504b81f Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Sun, 28 May 2023 12:00:19 +0200 Subject: [PATCH 1396/2172] fftools/ffmpeg_filter: drop a write-only variable --- fftools/ffmpeg.h | 1 - fftools/ffmpeg_filter.c | 1 - 2 files changed, 2 deletions(-) diff --git a/fftools/ffmpeg.h b/fftools/ffmpeg.h index cef4b5d000a..0e9ad5f9f75 100644 --- a/fftools/ffmpeg.h +++ b/fftools/ffmpeg.h @@ -296,7 +296,6 @@ typedef struct OutputFilter { /* desired output stream properties */ int width, height; - AVRational frame_rate; int format; int sample_rate; AVChannelLayout ch_layout; diff --git a/fftools/ffmpeg_filter.c b/fftools/ffmpeg_filter.c index c3075ef8544..287b1e6f9d0 100644 --- a/fftools/ffmpeg_filter.c +++ b/fftools/ffmpeg_filter.c @@ -654,7 +654,6 @@ void ofilter_bind_ost(OutputFilter *ofilter, OutputStream *ost) switch (ost->enc_ctx->codec_type) { case AVMEDIA_TYPE_VIDEO: - ofilter->frame_rate = ost->frame_rate; ofilter->width = ost->enc_ctx->width; ofilter->height = ost->enc_ctx->height; if (ost->enc_ctx->pix_fmt != AV_PIX_FMT_NONE) { From d8c61ba723331750e116a83185d54d577760a5e7 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Sun, 28 May 2023 12:02:45 +0200 Subject: [PATCH 1397/2172] fftools/ffmpeg_filter: drop a block disabled since 2012 --- fftools/ffmpeg_filter.c | 20 -------------------- 1 file changed, 20 deletions(-) diff --git a/fftools/ffmpeg_filter.c b/fftools/ffmpeg_filter.c index 287b1e6f9d0..1150f6fc65f 100644 --- a/fftools/ffmpeg_filter.c +++ b/fftools/ffmpeg_filter.c @@ -1075,26 +1075,6 @@ static int configure_output_video_filter(FilterGraph *fg, OutputFilter *ofilter, pad_idx = 0; } - if (ost->frame_rate.num && 0) { - AVFilterContext *fps; - char args[255]; - - snprintf(args, sizeof(args), "fps=%d/%d", ost->frame_rate.num, - ost->frame_rate.den); - snprintf(name, sizeof(name), "fps_out_%d_%d", - ost->file_index, ost->index); - ret = avfilter_graph_create_filter(&fps, avfilter_get_by_name("fps"), - name, args, NULL, fg->graph); - if (ret < 0) - return ret; - - ret = avfilter_link(last_filter, pad_idx, fps, 0); - if (ret < 0) - return ret; - last_filter = fps; - pad_idx = 0; - } - snprintf(name, sizeof(name), "trim_out_%d_%d", ost->file_index, ost->index); ret = insert_trim(of->start_time, of->recording_time, From c7a05ac117bc4152b27aa6127d67cb5bc0f09271 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Sun, 28 May 2023 12:16:28 +0200 Subject: [PATCH 1398/2172] fftools/ffmpeg_demux: do not set AVCodecContext.framerate For decoding, this field is used by the decoder to export information to the caller; it does not make sense for the caller to set it. --- fftools/ffmpeg_demux.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/fftools/ffmpeg_demux.c b/fftools/ffmpeg_demux.c index 5c15b8bad3d..5e5f106368e 100644 --- a/fftools/ffmpeg_demux.c +++ b/fftools/ffmpeg_demux.c @@ -1194,9 +1194,6 @@ static void add_input_streams(const OptionsContext *o, Demuxer *d) switch (par->codec_type) { case AVMEDIA_TYPE_VIDEO: - // avformat_find_stream_info() doesn't set this for us anymore. - ist->dec_ctx->framerate = st->avg_frame_rate; - MATCH_PER_STREAM_OPT(frame_rates, str, framerate, ic, st); if (framerate && av_parse_video_rate(&ist->framerate, framerate) < 0) { From ccf219e361957eef8fab45ce8b02cdf4d42e5e28 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Sun, 28 May 2023 16:22:58 +0200 Subject: [PATCH 1399/2172] fftools/ffmpeg_enc: avoid breaking exactly integer timestamps in vsync code The code will currently add a small offset to avoid exact midpoints, but this can cause inexact results when a float timestamp is exactly representable as an integer. Fixes off-by-one in the first frame duration in multiple FATE tests. --- fftools/ffmpeg_enc.c | 6 ++++-- tests/ref/fate/apng-osample | 2 +- tests/ref/fate/film-cvid | 2 +- tests/ref/fate/filter-concat-vfr | 2 +- tests/ref/fate/gif-gray | 2 +- 5 files changed, 8 insertions(+), 6 deletions(-) diff --git a/fftools/ffmpeg_enc.c b/fftools/ffmpeg_enc.c index fab71ca0c06..d390e384ed4 100644 --- a/fftools/ffmpeg_enc.c +++ b/fftools/ffmpeg_enc.c @@ -888,9 +888,11 @@ static double adjust_frame_pts_to_encoder_tb(OutputFile *of, OutputStream *ost, float_pts = av_rescale_q(frame->pts, filter_tb, tb) - av_rescale_q(start_time, AV_TIME_BASE_Q, tb); float_pts /= 1 << extra_bits; - // avoid exact midoints to reduce the chance of rounding differences, this + // when float_pts is not exactly an integer, + // avoid exact midpoints to reduce the chance of rounding differences, this // can be removed in case the fps code is changed to work with integers - float_pts += FFSIGN(float_pts) * 1.0 / (1<<17); + if (float_pts != llrint(float_pts)) + float_pts += FFSIGN(float_pts) * 1.0 / (1<<17); frame->pts = av_rescale_q(frame->pts, filter_tb, enc->time_base) - av_rescale_q(start_time, AV_TIME_BASE_Q, enc->time_base); diff --git a/tests/ref/fate/apng-osample b/tests/ref/fate/apng-osample index c91dd5284d4..6cf74a99ee0 100644 --- a/tests/ref/fate/apng-osample +++ b/tests/ref/fate/apng-osample @@ -3,7 +3,7 @@ #codec_id 0: rawvideo #dimensions 0: 116x135 #sar 0: 0/1 -0, 0, 0, 2, 62640, 0x31eb581d +0, 0, 0, 3, 62640, 0x31eb581d 0, 3, 3, 3, 62640, 0x29e11b82 0, 6, 6, 3, 62640, 0x207ed588 0, 9, 9, 3, 62640, 0x3845c906 diff --git a/tests/ref/fate/film-cvid b/tests/ref/fate/film-cvid index 60bbc192d8e..428cb6e9f09 100644 --- a/tests/ref/fate/film-cvid +++ b/tests/ref/fate/film-cvid @@ -3,7 +3,7 @@ #codec_id 0: rawvideo #dimensions 0: 320x224 #sar 0: 0/1 -0, 0, 0, 1, 215040, 0x067c5362 +0, 0, 0, 2, 215040, 0x067c5362 0, 2, 2, 2, 215040, 0xd9eacb98 0, 4, 4, 2, 215040, 0x3c8a4cbd 0, 6, 6, 2, 215040, 0xbdf996e1 diff --git a/tests/ref/fate/filter-concat-vfr b/tests/ref/fate/filter-concat-vfr index 66e9007da81..3d984a49688 100644 --- a/tests/ref/fate/filter-concat-vfr +++ b/tests/ref/fate/filter-concat-vfr @@ -8,7 +8,7 @@ #codec_id 1: pcm_s16le #sample_rate 1: 44100 #channel_layout_name 1: mono -0, 0, 0, 199999, 230400, 0x88c4d19a +0, 0, 0, 200000, 230400, 0x88c4d19a 1, 0, 0, 1024, 2048, 0xb3f10192 1, 1024, 1024, 1024, 2048, 0xb340fe4e 1, 2048, 2048, 1024, 2048, 0x0a5f0111 diff --git a/tests/ref/fate/gif-gray b/tests/ref/fate/gif-gray index aa3969212d7..c246d8a6704 100644 --- a/tests/ref/fate/gif-gray +++ b/tests/ref/fate/gif-gray @@ -3,7 +3,7 @@ #codec_id 0: rawvideo #dimensions 0: 480x360 #sar 0: 0/1 -0, 0, 0, 4, 691200, 0xef6c0f3d +0, 0, 0, 5, 691200, 0xef6c0f3d 0, 5, 5, 2, 691200, 0xc18b32de 0, 7, 7, 2, 691200, 0x2395a3d7 0, 9, 9, 2, 691200, 0x81dc3cf2 From c8a85d1b2fcf4a34ef55570d374bda1719bf2569 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Sun, 28 May 2023 12:23:29 +0200 Subject: [PATCH 1400/2172] fftools/ffmpeg_mux_init: do not overwrite OutputStream.frame_rate for streamcopy The values currently written into it are not used after streamcopy_init(), so it is better to confine them to that function. --- fftools/ffmpeg_mux_init.c | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/fftools/ffmpeg_mux_init.c b/fftools/ffmpeg_mux_init.c index 33c93e40f2e..b5295ad4455 100644 --- a/fftools/ffmpeg_mux_init.c +++ b/fftools/ffmpeg_mux_init.c @@ -861,6 +861,9 @@ static int streamcopy_init(const Muxer *mux, OutputStream *ost) AVCodecContext *codec_ctx = NULL; AVDictionary *codec_opts = NULL; + + AVRational fr = ost->frame_rate; + int ret = 0; codec_ctx = avcodec_alloc_context3(NULL); @@ -893,11 +896,11 @@ static int streamcopy_init(const Muxer *mux, OutputStream *ost) par->codec_tag = codec_tag; - if (!ost->frame_rate.num) - ost->frame_rate = ist->framerate; + if (!fr.num) + fr = ist->framerate; - if (ost->frame_rate.num) - ost->st->avg_frame_rate = ost->frame_rate; + if (fr.num) + ost->st->avg_frame_rate = fr; else ost->st->avg_frame_rate = ist->st->avg_frame_rate; @@ -908,8 +911,8 @@ static int streamcopy_init(const Muxer *mux, OutputStream *ost) // copy timebase while removing common factors if (ost->st->time_base.num <= 0 || ost->st->time_base.den <= 0) { - if (ost->frame_rate.num) - ost->st->time_base = av_inv_q(ost->frame_rate); + if (fr.num) + ost->st->time_base = av_inv_q(fr); else ost->st->time_base = av_add_q(av_stream_get_codec_timebase(ost->st), (AVRational){0, 1}); } From 2baae6434b997294b4a122a0ee2a37d3996f1e48 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Sun, 28 May 2023 17:11:58 +0200 Subject: [PATCH 1401/2172] fftools/ffmpeg_enc: merge two adjacent video-specific blocks There is no meaningful reason for them to be separated. --- fftools/ffmpeg_enc.c | 38 ++++++++++++++++++-------------------- 1 file changed, 18 insertions(+), 20 deletions(-) diff --git a/fftools/ffmpeg_enc.c b/fftools/ffmpeg_enc.c index d390e384ed4..07928b35579 100644 --- a/fftools/ffmpeg_enc.c +++ b/fftools/ffmpeg_enc.c @@ -219,7 +219,24 @@ int enc_open(OutputStream *ost, AVFrame *frame) dec_ctx = ist->dec_ctx; } - if (enc_ctx->codec_type == AVMEDIA_TYPE_VIDEO) { + switch (enc_ctx->codec_type) { + case AVMEDIA_TYPE_AUDIO: + enc_ctx->sample_fmt = av_buffersink_get_format(ost->filter->filter); + enc_ctx->sample_rate = av_buffersink_get_sample_rate(ost->filter->filter); + ret = av_buffersink_get_ch_layout(ost->filter->filter, &enc_ctx->ch_layout); + if (ret < 0) + return ret; + + 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_get_bytes_per_sample(enc_ctx->sample_fmt) << 3); + + init_encoder_time_base(ost, av_make_q(1, enc_ctx->sample_rate)); + break; + + case AVMEDIA_TYPE_VIDEO: if (!ost->frame_rate.num) ost->frame_rate = av_buffersink_get_frame_rate(ost->filter->filter); if (!ost->frame_rate.num && !ost->max_frame_rate.num) { @@ -245,26 +262,7 @@ int enc_open(OutputStream *ost, AVFrame *frame) av_reduce(&ost->frame_rate.num, &ost->frame_rate.den, ost->frame_rate.num, ost->frame_rate.den, 65535); } - } - switch (enc_ctx->codec_type) { - case AVMEDIA_TYPE_AUDIO: - enc_ctx->sample_fmt = av_buffersink_get_format(ost->filter->filter); - enc_ctx->sample_rate = av_buffersink_get_sample_rate(ost->filter->filter); - ret = av_buffersink_get_ch_layout(ost->filter->filter, &enc_ctx->ch_layout); - if (ret < 0) - return ret; - - 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_get_bytes_per_sample(enc_ctx->sample_fmt) << 3); - - init_encoder_time_base(ost, av_make_q(1, enc_ctx->sample_rate)); - break; - - case AVMEDIA_TYPE_VIDEO: init_encoder_time_base(ost, av_inv_q(ost->frame_rate)); if (!(enc_ctx->time_base.num && enc_ctx->time_base.den)) From 58a64e3d544dcedbfeebaabae19bcafce4f8b919 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Sun, 28 May 2023 17:41:43 +0200 Subject: [PATCH 1402/2172] fftools/ffmpeg_mux_init: only process -enc_time_base if the stream is encoded It has no effect otherwise. --- fftools/ffmpeg_mux_init.c | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/fftools/ffmpeg_mux_init.c b/fftools/ffmpeg_mux_init.c index b5295ad4455..d0b89cd1888 100644 --- a/fftools/ffmpeg_mux_init.c +++ b/fftools/ffmpeg_mux_init.c @@ -1073,6 +1073,7 @@ static OutputStream *ost_add(Muxer *mux, const OptionsContext *o, AVIOContext *s = NULL; char *buf = NULL, *arg = NULL, *preset = NULL; const char *enc_stats_pre = NULL, *enc_stats_post = NULL, *mux_stats = NULL; + const char *enc_time_base = NULL; ost->encoder_opts = filter_codec_opts(o->g->codec_opts, enc->codec_id, oc, st, enc->codec); @@ -1139,6 +1140,17 @@ static OutputStream *ost_add(Muxer *mux, const OptionsContext *o, if (ret < 0) exit_program(1); } + + MATCH_PER_STREAM_OPT(enc_time_bases, str, enc_time_base, oc, st); + if (enc_time_base) { + AVRational q; + if (av_parse_ratio(&q, enc_time_base, INT_MAX, 0, NULL) < 0 || + q.den <= 0) { + av_log(ost, AV_LOG_FATAL, "Invalid time base: %s\n", enc_time_base); + exit_program(1); + } + ost->enc_timebase = q; + } } else { ost->encoder_opts = filter_codec_opts(o->g->codec_opts, AV_CODEC_ID_NONE, oc, st, NULL); } @@ -1162,17 +1174,6 @@ static OutputStream *ost_add(Muxer *mux, const OptionsContext *o, st->time_base = q; } - MATCH_PER_STREAM_OPT(enc_time_bases, str, time_base, oc, st); - if (time_base) { - AVRational q; - if (av_parse_ratio(&q, time_base, INT_MAX, 0, NULL) < 0 || - q.den <= 0) { - av_log(ost, AV_LOG_FATAL, "Invalid time base: %s\n", time_base); - exit_program(1); - } - ost->enc_timebase = q; - } - ms->max_frames = INT64_MAX; MATCH_PER_STREAM_OPT(max_frames, i64, ms->max_frames, oc, st); for (i = 0; inb_max_frames; i++) { From 93e26a4db7784ca1372022ce7fea4a103eaf9a47 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Sun, 28 May 2023 17:45:46 +0200 Subject: [PATCH 1403/2172] fftools/ffmpeg: handle -enc_time_base -1 during stream creation There is no reason to postpone it until opening the encoder. Also, abort when the input stream is unknown, rather than disregard an explicit request from the user. --- fftools/ffmpeg_enc.c | 11 ----------- fftools/ffmpeg_mux_init.c | 9 +++++++++ 2 files changed, 9 insertions(+), 11 deletions(-) diff --git a/fftools/ffmpeg_enc.c b/fftools/ffmpeg_enc.c index 07928b35579..04d2c3c2011 100644 --- a/fftools/ffmpeg_enc.c +++ b/fftools/ffmpeg_enc.c @@ -179,7 +179,6 @@ static void set_encoder_id(OutputFile *of, OutputStream *ost) static void init_encoder_time_base(OutputStream *ost, AVRational default_time_base) { - InputStream *ist = ost->ist; AVCodecContext *enc_ctx = ost->enc_ctx; if (ost->enc_timebase.num > 0) { @@ -187,16 +186,6 @@ static void init_encoder_time_base(OutputStream *ost, AVRational default_time_ba return; } - if (ost->enc_timebase.num < 0) { - if (ist) { - enc_ctx->time_base = ist->st->time_base; - return; - } - - av_log(ost, AV_LOG_WARNING, - "Input stream data not available, using default time base\n"); - } - enc_ctx->time_base = default_time_base; } diff --git a/fftools/ffmpeg_mux_init.c b/fftools/ffmpeg_mux_init.c index d0b89cd1888..c49f906dc7f 100644 --- a/fftools/ffmpeg_mux_init.c +++ b/fftools/ffmpeg_mux_init.c @@ -1149,6 +1149,15 @@ static OutputStream *ost_add(Muxer *mux, const OptionsContext *o, av_log(ost, AV_LOG_FATAL, "Invalid time base: %s\n", enc_time_base); exit_program(1); } + if (q.num < 0) { + if (!ost->ist) { + av_log(ost, AV_LOG_FATAL, + "Cannot use input stream timebase for encoding - " + "no input stream available\n"); + exit_program(1); + } + q = ost->ist->st->time_base; + } ost->enc_timebase = q; } } else { From 2f92650c5d8b23f5935285d18567d1ddf3150a96 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Sun, 28 May 2023 18:16:53 +0200 Subject: [PATCH 1404/2172] fftools/ffmpeg_enc: inline init_encoder_time_base() into its callers The function now reduces to a ternary operator, so it is shorter and clearer to eliminate it. --- fftools/ffmpeg_enc.c | 18 ++++-------------- 1 file changed, 4 insertions(+), 14 deletions(-) diff --git a/fftools/ffmpeg_enc.c b/fftools/ffmpeg_enc.c index 04d2c3c2011..4a5ae3aa1bd 100644 --- a/fftools/ffmpeg_enc.c +++ b/fftools/ffmpeg_enc.c @@ -177,18 +177,6 @@ static void set_encoder_id(OutputFile *of, OutputStream *ost) AV_DICT_DONT_STRDUP_VAL | AV_DICT_DONT_OVERWRITE); } -static void init_encoder_time_base(OutputStream *ost, AVRational default_time_base) -{ - AVCodecContext *enc_ctx = ost->enc_ctx; - - if (ost->enc_timebase.num > 0) { - enc_ctx->time_base = ost->enc_timebase; - return; - } - - enc_ctx->time_base = default_time_base; -} - int enc_open(OutputStream *ost, AVFrame *frame) { InputStream *ist = ost->ist; @@ -222,7 +210,8 @@ int enc_open(OutputStream *ost, AVFrame *frame) 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)); + enc_ctx->time_base = ost->enc_timebase.num > 0 ? ost->enc_timebase : + av_make_q(1, enc_ctx->sample_rate); break; case AVMEDIA_TYPE_VIDEO: @@ -252,7 +241,8 @@ int enc_open(OutputStream *ost, AVFrame *frame) ost->frame_rate.num, ost->frame_rate.den, 65535); } - init_encoder_time_base(ost, av_inv_q(ost->frame_rate)); + enc_ctx->time_base = ost->enc_timebase.num > 0 ? ost->enc_timebase : + av_inv_q(ost->frame_rate); if (!(enc_ctx->time_base.num && enc_ctx->time_base.den)) enc_ctx->time_base = av_buffersink_get_time_base(ost->filter->filter); From 5bea8daa787c99b0d7172d41a0749377fee934ed Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Sun, 28 May 2023 22:27:43 +0200 Subject: [PATCH 1405/2172] fftools/ffmpeg_enc: do not guess frame durations from output framerate There is no reason to expect input frame durations to match output framerate. --- fftools/ffmpeg_enc.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/fftools/ffmpeg_enc.c b/fftools/ffmpeg_enc.c index 4a5ae3aa1bd..5be6e9332ad 100644 --- a/fftools/ffmpeg_enc.c +++ b/fftools/ffmpeg_enc.c @@ -1042,9 +1042,6 @@ static void do_video_out(OutputFile *of, OutputStream *ost, AVFrame *frame) if (frame) duration = lrintf(frame->duration * av_q2d(frame->time_base) / av_q2d(enc->time_base)); - if (duration <= 0 && ost->frame_rate.num) - duration = FFMIN(duration, 1/(av_q2d(ost->frame_rate) * av_q2d(enc->time_base))); - frame_rate = av_buffersink_get_frame_rate(filter); if (duration <= 0 && frame_rate.num > 0 && frame_rate.den > 0) duration = 1/(av_q2d(frame_rate) * av_q2d(enc->time_base)); From cf121592c5086ef205f627827ddc67beffff840c Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Sun, 28 May 2023 23:14:31 +0200 Subject: [PATCH 1406/2172] fftools/ffmpeg_mux_init: do not overwrite OutputStream.frame_rate for encoding The values currently written into it are not used after enc_open(), so it is better to confine them to that function. --- fftools/ffmpeg_enc.c | 33 ++++++++++++++++++--------------- 1 file changed, 18 insertions(+), 15 deletions(-) diff --git a/fftools/ffmpeg_enc.c b/fftools/ffmpeg_enc.c index 5be6e9332ad..1b0410ae74d 100644 --- a/fftools/ffmpeg_enc.c +++ b/fftools/ffmpeg_enc.c @@ -214,11 +214,13 @@ int enc_open(OutputStream *ost, AVFrame *frame) av_make_q(1, enc_ctx->sample_rate); break; - case AVMEDIA_TYPE_VIDEO: - if (!ost->frame_rate.num) - ost->frame_rate = av_buffersink_get_frame_rate(ost->filter->filter); - if (!ost->frame_rate.num && !ost->max_frame_rate.num) { - ost->frame_rate = (AVRational){25, 1}; + case AVMEDIA_TYPE_VIDEO: { + AVRational fr = ost->frame_rate; + + if (!fr.num) + fr = av_buffersink_get_frame_rate(ost->filter->filter); + if (!fr.num && !ost->max_frame_rate.num) { + fr = (AVRational){25, 1}; av_log(ost, AV_LOG_WARNING, "No information " "about the input framerate is available. Falling " @@ -227,22 +229,22 @@ int enc_open(OutputStream *ost, AVFrame *frame) } if (ost->max_frame_rate.num && - (av_q2d(ost->frame_rate) > av_q2d(ost->max_frame_rate) || - !ost->frame_rate.den)) - ost->frame_rate = ost->max_frame_rate; + (av_q2d(fr) > av_q2d(ost->max_frame_rate) || + !fr.den)) + fr = ost->max_frame_rate; if (enc->supported_framerates && !ost->force_fps) { - int idx = av_find_nearest_q_idx(ost->frame_rate, enc->supported_framerates); - ost->frame_rate = enc->supported_framerates[idx]; + int idx = av_find_nearest_q_idx(fr, enc->supported_framerates); + fr = enc->supported_framerates[idx]; } // reduce frame rate for mpeg4 to be within the spec limits if (enc_ctx->codec_id == AV_CODEC_ID_MPEG4) { - av_reduce(&ost->frame_rate.num, &ost->frame_rate.den, - ost->frame_rate.num, ost->frame_rate.den, 65535); + av_reduce(&fr.num, &fr.den, + fr.num, fr.den, 65535); } enc_ctx->time_base = ost->enc_timebase.num > 0 ? ost->enc_timebase : - av_inv_q(ost->frame_rate); + av_inv_q(fr); if (!(enc_ctx->time_base.num && enc_ctx->time_base.den)) enc_ctx->time_base = av_buffersink_get_time_base(ost->filter->filter); @@ -277,9 +279,9 @@ int enc_open(OutputStream *ost, AVFrame *frame) enc_ctx->chroma_sample_location = frame->chroma_location; } - enc_ctx->framerate = ost->frame_rate; + enc_ctx->framerate = fr; - ost->st->avg_frame_rate = ost->frame_rate; + ost->st->avg_frame_rate = fr; // Field order: autodetection if (frame) { @@ -307,6 +309,7 @@ int enc_open(OutputStream *ost, AVFrame *frame) } break; + } case AVMEDIA_TYPE_SUBTITLE: enc_ctx->time_base = AV_TIME_BASE_Q; if (!enc_ctx->width) { From d7781cfb95b1a4732456e82deca7e59b9ac18714 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Sun, 28 May 2023 10:25:45 +0200 Subject: [PATCH 1407/2172] fftools/ffmpeg: convert timestamps inside the muxer Packets submitted to the muxer now have their timebase attached to them, so the muxer can do conversion to muxing timebase and avoid exposing it to callers. --- fftools/ffmpeg_enc.c | 17 ++--------------- fftools/ffmpeg_mux.c | 6 ++++++ 2 files changed, 8 insertions(+), 15 deletions(-) diff --git a/fftools/ffmpeg_enc.c b/fftools/ffmpeg_enc.c index 1b0410ae74d..f6431b29d11 100644 --- a/fftools/ffmpeg_enc.c +++ b/fftools/ffmpeg_enc.c @@ -512,8 +512,8 @@ void enc_subtitle(OutputFile *of, OutputStream *ost, AVSubtitle *sub) } av_shrink_packet(pkt, subtitle_out_size); - pkt->time_base = ost->mux_timebase; - pkt->pts = av_rescale_q(sub->pts, AV_TIME_BASE_Q, pkt->time_base); + pkt->time_base = AV_TIME_BASE_Q; + pkt->pts = sub->pts; pkt->duration = av_rescale_q(sub->end_display_time, (AVRational){ 1, 1000 }, pkt->time_base); if (enc->codec_id == AV_CODEC_ID_DVB_SUBTITLE) { /* XXX: the pts correction is handled here. Maybe handling @@ -735,19 +735,6 @@ static int encode_frame(OutputFile *of, OutputStream *ost, AVFrame *frame) av_ts2str(pkt->duration), av_ts2timestr(pkt->duration, &enc->time_base)); } - av_packet_rescale_ts(pkt, pkt->time_base, ost->mux_timebase); - pkt->time_base = ost->mux_timebase; - - if (debug_ts) { - av_log(ost, AV_LOG_INFO, "encoder -> type:%s " - "pkt_pts:%s pkt_pts_time:%s pkt_dts:%s pkt_dts_time:%s " - "duration:%s duration_time:%s\n", - type_desc, - av_ts2str(pkt->pts), av_ts2timestr(pkt->pts, &enc->time_base), - av_ts2str(pkt->dts), av_ts2timestr(pkt->dts, &enc->time_base), - av_ts2str(pkt->duration), av_ts2timestr(pkt->duration, &enc->time_base)); - } - if ((ret = trigger_fix_sub_duration_heartbeat(ost, pkt)) < 0) { av_log(NULL, AV_LOG_ERROR, "Subtitle heartbeat logic failed in %s! (%s)\n", diff --git a/fftools/ffmpeg_mux.c b/fftools/ffmpeg_mux.c index 121796a55ad..dc2d189ff0e 100644 --- a/fftools/ffmpeg_mux.c +++ b/fftools/ffmpeg_mux.c @@ -334,6 +334,12 @@ void of_output_packet(OutputFile *of, AVPacket *pkt, OutputStream *ost, int eof) if (!eof && pkt->dts != AV_NOPTS_VALUE) ost->last_mux_dts = av_rescale_q(pkt->dts, pkt->time_base, AV_TIME_BASE_Q); + /* rescale timestamps to the muxing timebase */ + if (!eof) { + av_packet_rescale_ts(pkt, pkt->time_base, ost->mux_timebase); + pkt->time_base = ost->mux_timebase; + } + /* apply the output bitstream filters */ if (ms->bsf_ctx) { int bsf_eof = 0; From 963034107356cc83a75115644e1516e92c6fa3db Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Sat, 27 May 2023 12:25:51 +0200 Subject: [PATCH 1408/2172] fftools/ffmpeg: factor out attaching FrameData to a frame Will be useful in following commits. --- fftools/ffmpeg.c | 11 +++++++++++ fftools/ffmpeg.h | 6 ++++++ fftools/ffmpeg_dec.c | 5 ++--- 3 files changed, 19 insertions(+), 3 deletions(-) diff --git a/fftools/ffmpeg.c b/fftools/ffmpeg.c index bcda7570e9e..99978815722 100644 --- a/fftools/ffmpeg.c +++ b/fftools/ffmpeg.c @@ -431,6 +431,17 @@ InputStream *ist_iter(InputStream *prev) return NULL; } +FrameData *frame_data(AVFrame *frame) +{ + if (!frame->opaque_ref) { + frame->opaque_ref = av_buffer_allocz(sizeof(FrameData)); + if (!frame->opaque_ref) + return NULL; + } + + return (FrameData*)frame->opaque_ref->data; +} + void remove_avoptions(AVDictionary **a, AVDictionary *b) { const AVDictionaryEntry *t = NULL; diff --git a/fftools/ffmpeg.h b/fftools/ffmpeg.h index 0e9ad5f9f75..6f71e856588 100644 --- a/fftools/ffmpeg.h +++ b/fftools/ffmpeg.h @@ -737,6 +737,12 @@ int init_complex_filtergraph(FilterGraph *fg); int copy_av_subtitle(AVSubtitle *dst, const AVSubtitle *src); +/** + * Get our axiliary frame data attached to the frame, allocating it + * if needed. + */ +FrameData *frame_data(AVFrame *frame); + int ifilter_send_frame(InputFilter *ifilter, AVFrame *frame, int keep_reference); int ifilter_send_eof(InputFilter *ifilter, int64_t pts, AVRational tb); int ifilter_sub2video(InputFilter *ifilter, const AVSubtitle *sub); diff --git a/fftools/ffmpeg_dec.c b/fftools/ffmpeg_dec.c index 30959c64b7b..799be632157 100644 --- a/fftools/ffmpeg_dec.c +++ b/fftools/ffmpeg_dec.c @@ -499,12 +499,11 @@ int dec_packet(InputStream *ist, const AVPacket *pkt, int no_eof) FrameData *fd; av_assert0(!frame->opaque_ref); - frame->opaque_ref = av_buffer_allocz(sizeof(*fd)); - if (!frame->opaque_ref) { + fd = frame_data(frame); + if (!fd) { av_frame_unref(frame); report_and_exit(AVERROR(ENOMEM)); } - fd = (FrameData*)frame->opaque_ref->data; fd->pts = frame->pts; fd->tb = dec->pkt_timebase; fd->idx = dec->frame_num - 1; From 568d414074ddb02976d1bf5a491dba3571eafeba Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Sat, 27 May 2023 12:32:38 +0200 Subject: [PATCH 1409/2172] fftools/ffmpeg: attach filter framerate to frames This way the encoder does not need to reach backward into the filter. --- fftools/ffmpeg.h | 2 ++ fftools/ffmpeg_enc.c | 19 +++++++++++-------- fftools/ffmpeg_filter.c | 10 ++++++++++ 3 files changed, 23 insertions(+), 8 deletions(-) diff --git a/fftools/ffmpeg.h b/fftools/ffmpeg.h index 6f71e856588..49c07ede957 100644 --- a/fftools/ffmpeg.h +++ b/fftools/ffmpeg.h @@ -655,6 +655,8 @@ typedef struct FrameData { uint64_t idx; int64_t pts; AVRational tb; + + AVRational frame_rate_filter; } FrameData; extern InputFile **input_files; diff --git a/fftools/ffmpeg_enc.c b/fftools/ffmpeg_enc.c index f6431b29d11..cd2faccf4e5 100644 --- a/fftools/ffmpeg_enc.c +++ b/fftools/ffmpeg_enc.c @@ -217,8 +217,10 @@ int enc_open(OutputStream *ost, AVFrame *frame) case AVMEDIA_TYPE_VIDEO: { AVRational fr = ost->frame_rate; - if (!fr.num) - fr = av_buffersink_get_frame_rate(ost->filter->filter); + if (!fr.num && frame) { + FrameData *fd = frame_data(frame); + fr = fd->frame_rate_filter; + } if (!fr.num && !ost->max_frame_rate.num) { fr = (AVRational){25, 1}; av_log(ost, AV_LOG_WARNING, @@ -1024,17 +1026,18 @@ static void do_video_out(OutputFile *of, OutputStream *ost, AVFrame *frame) int ret; Encoder *e = ost->enc; AVCodecContext *enc = ost->enc_ctx; - AVRational frame_rate; int64_t nb_frames, nb_frames_prev, i; double duration = 0; - AVFilterContext *filter = ost->filter->filter; - if (frame) + if (frame) { + FrameData *fd = frame_data(frame); + duration = lrintf(frame->duration * av_q2d(frame->time_base) / av_q2d(enc->time_base)); - frame_rate = av_buffersink_get_frame_rate(filter); - if (duration <= 0 && frame_rate.num > 0 && frame_rate.den > 0) - duration = 1/(av_q2d(frame_rate) * av_q2d(enc->time_base)); + if (duration <= 0 && + fd->frame_rate_filter.num > 0 && fd->frame_rate_filter.den > 0) + duration = 1 / (av_q2d(fd->frame_rate_filter) * av_q2d(enc->time_base)); + } video_sync_process(of, ost, frame, duration, &nb_frames, &nb_frames_prev); diff --git a/fftools/ffmpeg_filter.c b/fftools/ffmpeg_filter.c index 1150f6fc65f..a2b45a14b85 100644 --- a/fftools/ffmpeg_filter.c +++ b/fftools/ffmpeg_filter.c @@ -1711,6 +1711,16 @@ int reap_filters(int flush) tb.num, tb.den); } + if (ost->type == AVMEDIA_TYPE_VIDEO) { + FrameData *fd = frame_data(filtered_frame); + if (!fd) { + av_frame_unref(filtered_frame); + report_and_exit(AVERROR(ENOMEM)); + } + + fd->frame_rate_filter = av_buffersink_get_frame_rate(filter); + } + enc_frame(ost, filtered_frame); av_frame_unref(filtered_frame); } From c803b36b8f5c8fa73ab2e77490d284d906d4c44b Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Sat, 27 May 2023 23:26:12 +0200 Subject: [PATCH 1410/2172] fftools/ffmpeg_enc: stop using OutputStream.initialized It is set by the muxing code, which will not be synchronized with encoding code after upcoming threading changes. Use an encoder-private variable instead. --- fftools/ffmpeg_enc.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/fftools/ffmpeg_enc.c b/fftools/ffmpeg_enc.c index cd2faccf4e5..1515ca971f9 100644 --- a/fftools/ffmpeg_enc.c +++ b/fftools/ffmpeg_enc.c @@ -62,6 +62,8 @@ struct Encoder { // number of packets received from the encoder uint64_t packets_encoded; + + int opened; }; static uint64_t dup_warning = 1000; @@ -187,7 +189,7 @@ int enc_open(OutputStream *ost, AVFrame *frame) OutputFile *of = output_files[ost->file_index]; int ret; - if (ost->initialized) + if (e->opened) return 0; set_encoder_id(output_files[ost->file_index], ost); @@ -362,6 +364,8 @@ int enc_open(OutputStream *ost, AVFrame *frame) return ret; } + e->opened = 1; + if (ost->sq_idx_encode >= 0) { e->sq_frame = av_frame_alloc(); if (!e->sq_frame) @@ -1123,6 +1127,7 @@ void enc_flush(void) } for (OutputStream *ost = ost_iter(NULL); ost; ost = ost_iter(ost)) { + Encoder *e = ost->enc; AVCodecContext *enc = ost->enc_ctx; OutputFile *of = output_files[ost->file_index]; @@ -1131,7 +1136,7 @@ void enc_flush(void) // Try to enable encoding with no input frames. // Maybe we should just let encoding fail instead. - if (!ost->initialized) { + if (!e->opened) { FilterGraph *fg = ost->filter->graph; av_log(ost, AV_LOG_WARNING, From 96e1325d9152323cb6418df017da7aca99d59f78 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Wed, 31 May 2023 11:45:13 +0200 Subject: [PATCH 1411/2172] fftools/ffmpeg_mux: use a dedicated packet for BSF output Currently of_output_packet() reuses the input packet, which requires its callers to submit blank packets even on EOF, which makes the code more complex. --- fftools/ffmpeg_mux.c | 9 +++++++-- fftools/ffmpeg_mux.h | 1 + 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/fftools/ffmpeg_mux.c b/fftools/ffmpeg_mux.c index dc2d189ff0e..485f4999710 100644 --- a/fftools/ffmpeg_mux.c +++ b/fftools/ffmpeg_mux.c @@ -351,7 +351,7 @@ void of_output_packet(OutputFile *of, AVPacket *pkt, OutputStream *ost, int eof) } while (!bsf_eof) { - ret = av_bsf_receive_packet(ms->bsf_ctx, pkt); + ret = av_bsf_receive_packet(ms->bsf_ctx, ms->bsf_pkt); if (ret == AVERROR(EAGAIN)) return; else if (ret == AVERROR_EOF) @@ -361,7 +361,7 @@ void of_output_packet(OutputFile *of, AVPacket *pkt, OutputStream *ost, int eof) goto fail; } - ret = submit_packet(mux, bsf_eof ? NULL : pkt, ost); + ret = submit_packet(mux, bsf_eof ? NULL : ms->bsf_pkt, ost); if (ret < 0) goto mux_fail; } @@ -656,6 +656,10 @@ static int bsf_init(MuxStream *ms) return ret; ost->st->time_base = ctx->time_base_out; + ms->bsf_pkt = av_packet_alloc(); + if (!ms->bsf_pkt) + return AVERROR(ENOMEM); + return 0; } @@ -856,6 +860,7 @@ static void ost_free(OutputStream **post) avcodec_parameters_free(&ost->par_in); av_bsf_free(&ms->bsf_ctx); + av_packet_free(&ms->bsf_pkt); av_packet_free(&ost->pkt); av_dict_free(&ost->encoder_opts); diff --git a/fftools/ffmpeg_mux.h b/fftools/ffmpeg_mux.h index bee7addd6a1..ad7b1df8a76 100644 --- a/fftools/ffmpeg_mux.h +++ b/fftools/ffmpeg_mux.h @@ -44,6 +44,7 @@ typedef struct MuxStream { AVFifo *muxing_queue; AVBSFContext *bsf_ctx; + AVPacket *bsf_pkt; EncStats stats; From f94957e8f4416e09e9530ef071929edb598a7d78 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Wed, 31 May 2023 11:52:45 +0200 Subject: [PATCH 1412/2172] fftools/ffmpeg_mux: simplify calling of_output_packet() Use NULL packets to signal EOF instead of a separate variable. This is made possible by the previous commit. --- fftools/ffmpeg.c | 2 +- fftools/ffmpeg.h | 13 +------------ fftools/ffmpeg_enc.c | 6 +++--- fftools/ffmpeg_mux.c | 14 +++++++------- 4 files changed, 12 insertions(+), 23 deletions(-) diff --git a/fftools/ffmpeg.c b/fftools/ffmpeg.c index 99978815722..d62ccc56c97 100644 --- a/fftools/ffmpeg.c +++ b/fftools/ffmpeg.c @@ -1112,7 +1112,7 @@ static int process_input(int file_index) OutputStream *ost = ist->outputs[oidx]; OutputFile *of = output_files[ost->file_index]; close_output_stream(ost); - of_output_packet(of, ost->pkt, ost, 1); + of_output_packet(of, ost, NULL); } } diff --git a/fftools/ffmpeg.h b/fftools/ffmpeg.h index 49c07ede957..890081edb4f 100644 --- a/fftools/ffmpeg.h +++ b/fftools/ffmpeg.h @@ -844,18 +844,7 @@ void of_close(OutputFile **pof); void of_enc_stats_close(void); -/* - * Send a single packet to the output, applying any bitstream filters - * associated with the output stream. This may result in any number - * of packets actually being written, depending on what bitstream - * filters are applied. The supplied packet is consumed and will be - * blank (as if newly-allocated) when this function returns. - * - * If eof is set, instead indicate EOF to all bitstream filters and - * therefore flush any delayed packets to the output. A blank packet - * must be supplied in this case. - */ -void of_output_packet(OutputFile *of, AVPacket *pkt, OutputStream *ost, int eof); +void of_output_packet(OutputFile *of, OutputStream *ost, AVPacket *pkt); /** * @param dts predicted packet dts in AV_TIME_BASE_Q diff --git a/fftools/ffmpeg_enc.c b/fftools/ffmpeg_enc.c index 1515ca971f9..8dd8104ceae 100644 --- a/fftools/ffmpeg_enc.c +++ b/fftools/ffmpeg_enc.c @@ -531,7 +531,7 @@ void enc_subtitle(OutputFile *of, OutputStream *ost, AVSubtitle *sub) } pkt->dts = pkt->pts; - of_output_packet(of, pkt, ost, 0); + of_output_packet(of, ost, pkt); } } @@ -718,7 +718,7 @@ static int encode_frame(OutputFile *of, OutputStream *ost, AVFrame *frame) av_assert0(frame); // should never happen during flushing return 0; } else if (ret == AVERROR_EOF) { - of_output_packet(of, pkt, ost, 1); + of_output_packet(of, ost, NULL); return ret; } else if (ret < 0) { av_log(ost, AV_LOG_ERROR, "%s encoding failed\n", type_desc); @@ -752,7 +752,7 @@ static int encode_frame(OutputFile *of, OutputStream *ost, AVFrame *frame) e->packets_encoded++; - of_output_packet(of, pkt, ost, 0); + of_output_packet(of, ost, pkt); } av_assert0(0); diff --git a/fftools/ffmpeg_mux.c b/fftools/ffmpeg_mux.c index 485f4999710..879a291ba9a 100644 --- a/fftools/ffmpeg_mux.c +++ b/fftools/ffmpeg_mux.c @@ -324,18 +324,18 @@ static int submit_packet(Muxer *mux, AVPacket *pkt, OutputStream *ost) return 0; } -void of_output_packet(OutputFile *of, AVPacket *pkt, OutputStream *ost, int eof) +void of_output_packet(OutputFile *of, OutputStream *ost, AVPacket *pkt) { Muxer *mux = mux_from_of(of); MuxStream *ms = ms_from_ost(ost); const char *err_msg; int ret = 0; - if (!eof && pkt->dts != AV_NOPTS_VALUE) + if (pkt && pkt->dts != AV_NOPTS_VALUE) ost->last_mux_dts = av_rescale_q(pkt->dts, pkt->time_base, AV_TIME_BASE_Q); /* rescale timestamps to the muxing timebase */ - if (!eof) { + if (pkt) { av_packet_rescale_ts(pkt, pkt->time_base, ost->mux_timebase); pkt->time_base = ost->mux_timebase; } @@ -344,7 +344,7 @@ void of_output_packet(OutputFile *of, AVPacket *pkt, OutputStream *ost, int eof) if (ms->bsf_ctx) { int bsf_eof = 0; - ret = av_bsf_send_packet(ms->bsf_ctx, eof ? NULL : pkt); + ret = av_bsf_send_packet(ms->bsf_ctx, pkt); if (ret < 0) { err_msg = "submitting a packet for bitstream filtering"; goto fail; @@ -366,7 +366,7 @@ void of_output_packet(OutputFile *of, AVPacket *pkt, OutputStream *ost, int eof) goto mux_fail; } } else { - ret = submit_packet(mux, eof ? NULL : pkt, ost); + ret = submit_packet(mux, pkt, ost); if (ret < 0) goto mux_fail; } @@ -399,7 +399,7 @@ void of_streamcopy(OutputStream *ost, const AVPacket *pkt, int64_t dts) // EOF: flush output bitstream filters. if (!pkt) { - of_output_packet(of, opkt, ost, 1); + of_output_packet(of, ost, NULL); return; } @@ -453,7 +453,7 @@ void of_streamcopy(OutputStream *ost, const AVPacket *pkt, int64_t dts) } } - of_output_packet(of, opkt, ost, 0); + of_output_packet(of, ost, opkt); ms->streamcopy_started = 1; } From 730a2221afa6384d753fb4f22b7734efc0bef07f Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Wed, 31 May 2023 12:08:49 +0200 Subject: [PATCH 1413/2172] fftools/ffmpeg_enc: use a private AVPacket instance for encoding The code currently uses OutputStream.pkt, which complicates its ownership semantics. --- fftools/ffmpeg_enc.c | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/fftools/ffmpeg_enc.c b/fftools/ffmpeg_enc.c index 8dd8104ceae..2bf4782a9fe 100644 --- a/fftools/ffmpeg_enc.c +++ b/fftools/ffmpeg_enc.c @@ -57,6 +57,9 @@ struct Encoder { AVFrame *sq_frame; + // packet for receiving encoded output + AVPacket *pkt; + // combined size of all the packets received from the encoder uint64_t data_size; @@ -78,6 +81,8 @@ void enc_free(Encoder **penc) av_frame_free(&enc->last_frame); av_frame_free(&enc->sq_frame); + av_packet_free(&enc->pkt); + av_freep(penc); } @@ -97,6 +102,10 @@ int enc_alloc(Encoder **penc, const AVCodec *codec) goto fail; } + enc->pkt = av_packet_alloc(); + if (!enc->pkt) + goto fail; + *penc = enc; return 0; @@ -454,10 +463,11 @@ static int check_recording_time(OutputStream *ost, int64_t ts, AVRational tb) void enc_subtitle(OutputFile *of, OutputStream *ost, AVSubtitle *sub) { + Encoder *e = ost->enc; int subtitle_out_max_size = 1024 * 1024; int subtitle_out_size, nb, i, ret; AVCodecContext *enc; - AVPacket *pkt = ost->pkt; + AVPacket *pkt = e->pkt; int64_t pts; if (sub->pts == AV_NOPTS_VALUE) { @@ -669,7 +679,7 @@ static int encode_frame(OutputFile *of, OutputStream *ost, AVFrame *frame) { Encoder *e = ost->enc; AVCodecContext *enc = ost->enc_ctx; - AVPacket *pkt = ost->pkt; + AVPacket *pkt = e->pkt; const char *type_desc = av_get_media_type_string(enc->codec_type); const char *action = frame ? "encode" : "flush"; int ret; From 141d11cb3ca1b4b8236d23323dca7c89859e487b Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Wed, 31 May 2023 12:14:05 +0200 Subject: [PATCH 1414/2172] fftools/ffmpeg_mux: make OutputStream.pkt private It is no longer used outside of muxing code. --- fftools/ffmpeg.h | 1 - fftools/ffmpeg_mux.c | 4 ++-- fftools/ffmpeg_mux.h | 2 ++ fftools/ffmpeg_mux_init.c | 4 ++-- 4 files changed, 6 insertions(+), 5 deletions(-) diff --git a/fftools/ffmpeg.h b/fftools/ffmpeg.h index 890081edb4f..88e35162435 100644 --- a/fftools/ffmpeg.h +++ b/fftools/ffmpeg.h @@ -551,7 +551,6 @@ typedef struct OutputStream { Encoder *enc; AVCodecContext *enc_ctx; - AVPacket *pkt; uint64_t nb_frames_dup; uint64_t nb_frames_drop; diff --git a/fftools/ffmpeg_mux.c b/fftools/ffmpeg_mux.c index 879a291ba9a..66b2324bb30 100644 --- a/fftools/ffmpeg_mux.c +++ b/fftools/ffmpeg_mux.c @@ -389,7 +389,7 @@ void of_streamcopy(OutputStream *ost, const AVPacket *pkt, int64_t dts) MuxStream *ms = ms_from_ost(ost); int64_t start_time = (of->start_time == AV_NOPTS_VALUE) ? 0 : of->start_time; int64_t ost_tb_start_time = av_rescale_q(start_time, AV_TIME_BASE_Q, ost->mux_timebase); - AVPacket *opkt = ost->pkt; + AVPacket *opkt = ms->pkt; av_packet_unref(opkt); @@ -862,7 +862,7 @@ static void ost_free(OutputStream **post) av_bsf_free(&ms->bsf_ctx); av_packet_free(&ms->bsf_pkt); - av_packet_free(&ost->pkt); + av_packet_free(&ms->pkt); av_dict_free(&ost->encoder_opts); av_freep(&ost->kf.pts); diff --git a/fftools/ffmpeg_mux.h b/fftools/ffmpeg_mux.h index ad7b1df8a76..7f34b86548c 100644 --- a/fftools/ffmpeg_mux.h +++ b/fftools/ffmpeg_mux.h @@ -46,6 +46,8 @@ typedef struct MuxStream { AVBSFContext *bsf_ctx; AVPacket *bsf_pkt; + AVPacket *pkt; + EncStats stats; int64_t max_frames; diff --git a/fftools/ffmpeg_mux_init.c b/fftools/ffmpeg_mux_init.c index c49f906dc7f..a18320fa9b6 100644 --- a/fftools/ffmpeg_mux_init.c +++ b/fftools/ffmpeg_mux_init.c @@ -1064,8 +1064,8 @@ static OutputStream *ost_add(Muxer *mux, const OptionsContext *o, else av_assert0(0); av_log(ost, AV_LOG_VERBOSE, "\n"); - ost->pkt = av_packet_alloc(); - if (!ost->pkt) + ms->pkt = av_packet_alloc(); + if (!ms->pkt) report_and_exit(AVERROR(ENOMEM)); if (ost->enc_ctx) { From 99da411322e1e8603149033138d6e87b58fe41a3 Mon Sep 17 00:00:00 2001 From: Leo Izen Date: Fri, 3 Mar 2023 15:31:45 -0500 Subject: [PATCH 1415/2172] avcodec/libjxldec: add animated decode support Migrate the libjxl decoder wrapper from the decode_frame method to the receive_frame method, which allows sending more than one frame from a single packet. This allows the libjxl decoder to decode JPEG XL files that are animated, and emit every frame of the animation. Now, clients that feed the libjxl decoder with an animated JPEG XL file will be able to receieve the full animation. Signed-off-by: Leo Izen --- libavcodec/libjxldec.c | 107 ++++++++++++++++++++++++++++++----------- libavcodec/version.h | 2 +- 2 files changed, 80 insertions(+), 29 deletions(-) diff --git a/libavcodec/libjxldec.c b/libavcodec/libjxldec.c index 65966b7b579..50417bcb025 100644 --- a/libavcodec/libjxldec.c +++ b/libavcodec/libjxldec.c @@ -37,6 +37,7 @@ #include "avcodec.h" #include "codec_internal.h" #include "decode.h" +#include "internal.h" #include #include @@ -52,13 +53,19 @@ typedef struct LibJxlDecodeContext { #endif JxlDecoderStatus events; AVBufferRef *iccp; + AVPacket *avpkt; + int64_t pts; + int64_t frame_duration; + int prev_is_last; + AVRational timebase; } LibJxlDecodeContext; static int libjxl_init_jxl_decoder(AVCodecContext *avctx) { LibJxlDecodeContext *ctx = avctx->priv_data; - ctx->events = JXL_DEC_BASIC_INFO | JXL_DEC_FULL_IMAGE | JXL_DEC_COLOR_ENCODING; + ctx->events = JXL_DEC_BASIC_INFO | JXL_DEC_FULL_IMAGE + | JXL_DEC_COLOR_ENCODING | JXL_DEC_FRAME; if (JxlDecoderSubscribeEvents(ctx->decoder, ctx->events) != JXL_DEC_SUCCESS) { av_log(avctx, AV_LOG_ERROR, "Error subscribing to JXL events\n"); return AVERROR_EXTERNAL; @@ -71,6 +78,8 @@ static int libjxl_init_jxl_decoder(AVCodecContext *avctx) memset(&ctx->basic_info, 0, sizeof(JxlBasicInfo)); memset(&ctx->jxl_pixfmt, 0, sizeof(JxlPixelFormat)); + ctx->prev_is_last = 1; + ctx->frame_duration = 1; return 0; } @@ -93,6 +102,9 @@ static av_cold int libjxl_decode_init(AVCodecContext *avctx) return AVERROR_EXTERNAL; } + ctx->avpkt = avctx->internal->in_pkt; + ctx->pts = 0; + return libjxl_init_jxl_decoder(avctx); } @@ -328,19 +340,33 @@ static int libjxl_color_encoding_event(AVCodecContext *avctx, AVFrame *frame) return 0; } -static int libjxl_decode_frame(AVCodecContext *avctx, AVFrame *frame, int *got_frame, AVPacket *avpkt) +static int libjxl_receive_frame(AVCodecContext *avctx, AVFrame *frame) { LibJxlDecodeContext *ctx = avctx->priv_data; - const uint8_t *buf = avpkt->data; - size_t remaining = avpkt->size; - JxlDecoderStatus jret; + JxlDecoderStatus jret = JXL_DEC_SUCCESS; int ret; - *got_frame = 0; + AVPacket *pkt = ctx->avpkt; while (1) { + size_t remaining; - jret = JxlDecoderSetInput(ctx->decoder, buf, remaining); + if (!pkt->size) { + av_packet_unref(pkt); + ret = ff_decode_get_packet(avctx, pkt); + if (ret < 0 && ret != AVERROR_EOF) + return ret; + if (!pkt->size) { + /* jret set by the last iteration of the loop */ + if (jret == JXL_DEC_NEED_MORE_INPUT) { + av_log(avctx, AV_LOG_ERROR, "Unexpected end of JXL codestream\n"); + return AVERROR_INVALIDDATA; + } else { + return AVERROR_EOF; + } + } + } + jret = JxlDecoderSetInput(ctx->decoder, pkt->data, pkt->size); if (jret == JXL_DEC_ERROR) { /* this should never happen here unless there's a bug in libjxl */ av_log(avctx, AV_LOG_ERROR, "Unknown libjxl decode error\n"); @@ -354,18 +380,19 @@ static int libjxl_decode_frame(AVCodecContext *avctx, AVFrame *frame, int *got_f * the number of bytes that it did read */ remaining = JxlDecoderReleaseInput(ctx->decoder); - buf = avpkt->data + avpkt->size - remaining; + pkt->data += pkt->size - remaining; + pkt->size = remaining; switch(jret) { case JXL_DEC_ERROR: av_log(avctx, AV_LOG_ERROR, "Unknown libjxl decode error\n"); return AVERROR_INVALIDDATA; case JXL_DEC_NEED_MORE_INPUT: - if (remaining == 0) { - av_log(avctx, AV_LOG_ERROR, "Unexpected end of JXL codestream\n"); - return AVERROR_INVALIDDATA; - } av_log(avctx, AV_LOG_DEBUG, "NEED_MORE_INPUT event emitted\n"); + if (!pkt->size) { + av_packet_unref(pkt); + return AVERROR(EAGAIN); + } continue; case JXL_DEC_BASIC_INFO: av_log(avctx, AV_LOG_DEBUG, "BASIC_INFO event emitted\n"); @@ -384,6 +411,13 @@ static int libjxl_decode_frame(AVCodecContext *avctx, AVFrame *frame, int *got_f } if ((ret = ff_set_dimensions(avctx, ctx->basic_info.xsize, ctx->basic_info.ysize)) < 0) return ret; + if (ctx->basic_info.have_animation) + ctx->timebase = av_make_q(ctx->basic_info.animation.tps_denominator, + ctx->basic_info.animation.tps_numerator); + else if (avctx->pkt_timebase.num) + ctx->timebase = avctx->pkt_timebase; + else + ctx->timebase = AV_TIME_BASE_Q; continue; case JXL_DEC_COLOR_ENCODING: av_log(avctx, AV_LOG_DEBUG, "COLOR_ENCODING event emitted\n"); @@ -407,11 +441,28 @@ static int libjxl_decode_frame(AVCodecContext *avctx, AVFrame *frame, int *got_f } #endif continue; + case JXL_DEC_FRAME: + av_log(avctx, AV_LOG_DEBUG, "FRAME event emitted\n"); + if (!ctx->basic_info.have_animation || ctx->prev_is_last) { + frame->pict_type = AV_PICTURE_TYPE_I; + frame->flags |= AV_FRAME_FLAG_KEY; + } + if (ctx->basic_info.have_animation) { + JxlFrameHeader header; + if (JxlDecoderGetFrameHeader(ctx->decoder, &header) != JXL_DEC_SUCCESS) { + av_log(avctx, AV_LOG_ERROR, "Bad libjxl dec frame event\n"); + return AVERROR_EXTERNAL; + } + ctx->prev_is_last = header.is_last; + ctx->frame_duration = header.duration; + } else { + ctx->prev_is_last = 1; + ctx->frame_duration = 1; + } + continue; case JXL_DEC_FULL_IMAGE: /* full image is one frame, even if animated */ av_log(avctx, AV_LOG_DEBUG, "FULL_IMAGE event emitted\n"); - frame->pict_type = AV_PICTURE_TYPE_I; - frame->flags |= AV_FRAME_FLAG_KEY; if (ctx->iccp) { AVFrameSideData *sd = av_frame_new_side_data_from_buf(frame, AV_FRAME_DATA_ICC_PROFILE, ctx->iccp); if (!sd) @@ -419,25 +470,25 @@ static int libjxl_decode_frame(AVCodecContext *avctx, AVFrame *frame, int *got_f /* ownership is transfered, and it is not ref-ed */ ctx->iccp = NULL; } - *got_frame = 1; - return avpkt->size - remaining; + if (avctx->pkt_timebase.num) { + frame->pts = av_rescale_q(ctx->pts, ctx->timebase, avctx->pkt_timebase); + frame->duration = av_rescale_q(ctx->frame_duration, ctx->timebase, avctx->pkt_timebase); + } else { + frame->pts = ctx->pts; + frame->duration = ctx->frame_duration; + } + ctx->pts += ctx->frame_duration; + return 0; case JXL_DEC_SUCCESS: av_log(avctx, AV_LOG_DEBUG, "SUCCESS event emitted\n"); /* - * The SUCCESS event isn't fired until after JXL_DEC_FULL_IMAGE. If this - * stream only contains one JXL image then JXL_DEC_SUCCESS will never fire. - * If the image2 sequence being decoded contains several JXL files, then - * libjxl will fire this event after the next AVPacket has been passed, - * which means the current packet is actually the next image in the sequence. - * This is why we reset the decoder and populate the packet data now, since - * this is the next packet and it has not been decoded yet. The decoder does - * have to be reset to allow us to use it for the next image, or libjxl - * will become very confused if the header information is not identical. + * this event will be fired when the zero-length EOF + * packet is sent to the decoder by the client, + * but it will also be fired when the next image of + * an image2pipe sequence is loaded up */ JxlDecoderReset(ctx->decoder); libjxl_init_jxl_decoder(avctx); - buf = avpkt->data; - remaining = avpkt->size; continue; default: av_log(avctx, AV_LOG_ERROR, "Bad libjxl event: %d\n", jret); @@ -468,7 +519,7 @@ const FFCodec ff_libjxl_decoder = { .p.id = AV_CODEC_ID_JPEGXL, .priv_data_size = sizeof(LibJxlDecodeContext), .init = libjxl_decode_init, - FF_CODEC_DECODE_CB(libjxl_decode_frame), + FF_CODEC_RECEIVE_FRAME_CB(libjxl_receive_frame), .close = libjxl_decode_close, .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_OTHER_THREADS, .caps_internal = FF_CODEC_CAP_NOT_INIT_THREADSAFE | diff --git a/libavcodec/version.h b/libavcodec/version.h index 82a86fe9d98..9d0485b068c 100644 --- a/libavcodec/version.h +++ b/libavcodec/version.h @@ -30,7 +30,7 @@ #include "version_major.h" #define LIBAVCODEC_VERSION_MINOR 16 -#define LIBAVCODEC_VERSION_MICRO 100 +#define LIBAVCODEC_VERSION_MICRO 101 #define LIBAVCODEC_VERSION_INT AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \ LIBAVCODEC_VERSION_MINOR, \ From fa11c4c7fa3961b0101daaa0032bb26a7a1a9c0f Mon Sep 17 00:00:00 2001 From: Leo Izen Date: Fri, 3 Mar 2023 15:31:46 -0500 Subject: [PATCH 1416/2172] avformat/jpegxl_anim_dec: add animated JPEG XL demuxer Animated JPEG XL files requires a separate demuxer than image2, because the timebase information is set by the demuxer. Should the timebase of an animated JPEG XL file be incompatible with the timebase set by the image2pipe demuxer (usually 1/25 unless set otherwise), rescaling will fail. Adding a separate demuxer for animated JPEG XL files allows the timebase to be set correctly. Signed-off-by: Leo Izen --- MAINTAINERS | 1 + libavformat/Makefile | 1 + libavformat/allformats.c | 1 + libavformat/img2dec.c | 2 +- libavformat/jpegxl_anim_dec.c | 266 ++++++++++++++++++++++++++++++++++ libavformat/jpegxl_probe.c | 19 +-- libavformat/jpegxl_probe.h | 7 +- libavformat/version.h | 2 +- 8 files changed, 287 insertions(+), 12 deletions(-) create mode 100644 libavformat/jpegxl_anim_dec.c diff --git a/MAINTAINERS b/MAINTAINERS index f95be01dc68..07852486e44 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -432,6 +432,7 @@ Muxers/Demuxers: ipmovie.c Mike Melanson ircam* Paul B Mahol iss.c Stefan Gehrer + jpegxl_anim_dec.c Leo Izen jpegxl_probe.* Leo Izen jvdec.c Peter Ross kvag.c Zane van Iperen diff --git a/libavformat/Makefile b/libavformat/Makefile index f8ad7c6a116..05434a0f82d 100644 --- a/libavformat/Makefile +++ b/libavformat/Makefile @@ -316,6 +316,7 @@ OBJS-$(CONFIG_IVF_MUXER) += ivfenc.o OBJS-$(CONFIG_IVR_DEMUXER) += rmdec.o rm.o rmsipr.o OBJS-$(CONFIG_JACOSUB_DEMUXER) += jacosubdec.o subtitles.o OBJS-$(CONFIG_JACOSUB_MUXER) += jacosubenc.o rawenc.o +OBJS-$(CONFIG_JPEGXL_ANIM_DEMUXER) += jpegxl_anim_dec.o jpegxl_probe.o OBJS-$(CONFIG_JV_DEMUXER) += jvdec.o OBJS-$(CONFIG_KUX_DEMUXER) += flvdec.o OBJS-$(CONFIG_KVAG_DEMUXER) += kvag.o diff --git a/libavformat/allformats.c b/libavformat/allformats.c index efdb34e29d9..96443a72721 100644 --- a/libavformat/allformats.c +++ b/libavformat/allformats.c @@ -238,6 +238,7 @@ extern const AVInputFormat ff_ivr_demuxer; extern const AVInputFormat ff_jacosub_demuxer; extern const FFOutputFormat ff_jacosub_muxer; extern const AVInputFormat ff_jv_demuxer; +extern const AVInputFormat ff_jpegxl_anim_demuxer; extern const AVInputFormat ff_kux_demuxer; extern const AVInputFormat ff_kvag_demuxer; extern const FFOutputFormat ff_kvag_muxer; diff --git a/libavformat/img2dec.c b/libavformat/img2dec.c index c037b6aa882..b986d3a502d 100644 --- a/libavformat/img2dec.c +++ b/libavformat/img2dec.c @@ -850,7 +850,7 @@ static int jpegxl_probe(const AVProbeData *p) if (AV_RL16(b) != FF_JPEGXL_CODESTREAM_SIGNATURE_LE) return 0; #if CONFIG_IMAGE_JPEGXL_PIPE_DEMUXER - if (ff_jpegxl_verify_codestream_header(p->buf, p->buf_size) >= 0) + if (ff_jpegxl_verify_codestream_header(p->buf, p->buf_size, 1) >= 0) return AVPROBE_SCORE_MAX - 2; #endif return 0; diff --git a/libavformat/jpegxl_anim_dec.c b/libavformat/jpegxl_anim_dec.c new file mode 100644 index 00000000000..6ea6c46d8f4 --- /dev/null +++ b/libavformat/jpegxl_anim_dec.c @@ -0,0 +1,266 @@ +/* + * Animated JPEG XL Demuxer + * Copyright (c) 2023 Leo Izen (thebombzen) + * + * 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 + * Animated JPEG XL Demuxer + * @see ISO/IEC 18181-1 and 18181-2 + */ + +#include +#include + +#define BITSTREAM_READER_LE +#include "libavcodec/get_bits.h" + +#include "libavutil/intreadwrite.h" +#include "libavutil/opt.h" + +#include "avformat.h" +#include "internal.h" +#include "jpegxl_probe.h" + +typedef struct JXLAnimDemuxContext { + AVBufferRef *initial; +} JXLAnimDemuxContext; + +/* + * copies as much of the codestream into the buffer as possible + * pass a shorter buflen to request less + * returns the number of bytes consumed from input, may be greater than input_len + * if the input doesn't end on an ISOBMFF-box boundary + */ +static int jpegxl_collect_codestream_header(const uint8_t *input_buffer, int input_len, uint8_t *buffer, int buflen, int *copied) { + const uint8_t *b = input_buffer; + *copied = 0; + + while (1) { + uint64_t size; + uint32_t tag; + int head_size = 8; + + if (b - input_buffer >= input_len - 16) + break; + + size = AV_RB32(b); + b += 4; + if (size == 1) { + size = AV_RB64(b); + b += 8; + head_size = 16; + } + /* invalid ISOBMFF size */ + if (size > 0 && size <= head_size) + return AVERROR_INVALIDDATA; + if (size > 0) + size -= head_size; + + tag = AV_RL32(b); + b += 4; + if (tag == MKTAG('j', 'x', 'l', 'p')) { + b += 4; + size -= 4; + } + + if (tag == MKTAG('j', 'x', 'l', 'c') || tag == MKTAG('j', 'x', 'l', 'p')) { + /* + * size = 0 means "until EOF". this is legal but uncommon + * here we just set it to the remaining size of the probe buffer + * which at this point should always be nonnegative + */ + if (size == 0 || size > input_len - (b - input_buffer)) + size = input_len - (b - input_buffer); + + if (size > buflen - *copied) + size = buflen - *copied; + /* + * arbitrary chunking of the payload makes this memcpy hard to avoid + * in practice this will only be performed one or two times at most + */ + memcpy(buffer + *copied, b, size); + *copied += size; + } + b += size; + if (b >= input_buffer + input_len || *copied >= buflen) + break; + } + + return b - input_buffer; +} + +static int jpegxl_anim_probe(const AVProbeData *p) +{ + uint8_t buffer[4096]; + int copied; + + /* this is a raw codestream */ + if (AV_RL16(p->buf) == FF_JPEGXL_CODESTREAM_SIGNATURE_LE) { + if (ff_jpegxl_verify_codestream_header(p->buf, p->buf_size, 1) >= 1) + return AVPROBE_SCORE_MAX; + + return 0; + } + + /* not a JPEG XL file at all */ + if (AV_RL64(p->buf) != FF_JPEGXL_CONTAINER_SIGNATURE_LE) + return 0; + + if (jpegxl_collect_codestream_header(p->buf, p->buf_size, buffer, sizeof(buffer), &copied) <= 0 || copied <= 0) + return 0; + + if (ff_jpegxl_verify_codestream_header(buffer, copied, 0) >= 1) + return AVPROBE_SCORE_MAX; + + return 0; +} + +static int jpegxl_anim_read_header(AVFormatContext *s) +{ + JXLAnimDemuxContext *ctx = s->priv_data; + AVIOContext *pb = s->pb; + AVStream *st; + int offset = 0; + uint8_t head[256]; + int headsize = 0; + int ctrl; + AVRational tb; + GetBitContext gbi, *gb = &gbi; + + uint64_t sig16 = avio_rl16(pb); + if (sig16 == FF_JPEGXL_CODESTREAM_SIGNATURE_LE) { + AV_WL16(head, sig16); + headsize = avio_read(s->pb, head + 2, sizeof(head) - 2); + if (headsize < 0) + return headsize; + headsize += 2; + ctx->initial = av_buffer_alloc(headsize); + if (!ctx->initial) + return AVERROR(ENOMEM); + memcpy(ctx->initial->data, head, headsize); + } else { + uint64_t sig64 = avio_rl64(pb); + sig64 = (sig64 << 16) | sig16; + if (sig64 != FF_JPEGXL_CONTAINER_SIGNATURE_LE) + return AVERROR_INVALIDDATA; + avio_skip(pb, 2); // first box always 12 bytes + while (1) { + int copied; + uint8_t buf[4096]; + int read = avio_read(pb, buf, sizeof(buf)); + if (read < 0) + return read; + if (!ctx->initial) { + ctx->initial = av_buffer_alloc(read + 12); + if (!ctx->initial) + return AVERROR(ENOMEM); + AV_WL64(ctx->initial->data, FF_JPEGXL_CONTAINER_SIGNATURE_LE); + AV_WL32(ctx->initial->data + 8, 0x0a870a0d); + } else { + /* this only should be happening zero or one times in practice */ + if (av_buffer_realloc(&ctx->initial, ctx->initial->size + read) < 0) + return AVERROR(ENOMEM); + } + jpegxl_collect_codestream_header(buf, read, head + headsize, sizeof(head) - headsize, &copied); + memcpy(ctx->initial->data + (ctx->initial->size - read), buf, read); + headsize += copied; + if (headsize >= sizeof(head) || read < sizeof(buf)) + break; + } + } + /* offset in bits of the animation header */ + offset = ff_jpegxl_verify_codestream_header(head, headsize, 0); + if (offset <= 0) + return AVERROR_INVALIDDATA; + if (init_get_bits8(gb, head, headsize) < 0) + return AVERROR_INVALIDDATA; + skip_bits_long(gb, offset); + + st = avformat_new_stream(s, NULL); + if (!st) + return AVERROR(ENOMEM); + + st->codecpar->codec_type = AVMEDIA_TYPE_VIDEO; + st->codecpar->codec_id = AV_CODEC_ID_JPEGXL; + ctrl = get_bits(gb, 2); + tb.den = (const uint32_t[]){100, 1000, 1, 1}[ctrl] + get_bits_long(gb, (const uint32_t[]){0, 0, 10, 30}[ctrl]); + ctrl = get_bits(gb, 2); + tb.num = (const uint32_t[]){1, 1001, 1, 1}[ctrl] + get_bits_long(gb, (const uint32_t[]){0, 0, 8, 10}[ctrl]); + avpriv_set_pts_info(st, 1, tb.num, tb.den); + + return 0; +} + +/* the decoder requires the full input file as a single packet */ +static int jpegxl_anim_read_packet(AVFormatContext *s, AVPacket *pkt) +{ + JXLAnimDemuxContext *ctx = s->priv_data; + AVIOContext *pb = s->pb; + int ret; + int64_t size; + size_t offset = 0; + + if ((size = avio_size(pb)) < 0) + return size; + + /* animated JXL this big should not exist */ + if (size > INT_MAX) + return AVERROR_INVALIDDATA; + + if (ctx->initial && size < ctx->initial->size) + size = ctx->initial->size; + + if ((ret = av_new_packet(pkt, size) < 0)) + return ret; + + if (ctx->initial) { + offset = ctx->initial->size; + memcpy(pkt->data, ctx->initial->data, offset); + av_buffer_unref(&ctx->initial); + } + + if ((ret = avio_read(pb, pkt->data + offset, size - offset)) < 0) + return ret; + + return 0; +} + +static int jpegxl_anim_close(AVFormatContext *s) +{ + JXLAnimDemuxContext *ctx = s->priv_data; + if (ctx->initial) + av_buffer_unref(&ctx->initial); + + return 0; +} + +const AVInputFormat ff_jpegxl_anim_demuxer = { + .name = "jpegxl_anim", + .long_name = NULL_IF_CONFIG_SMALL("Animated JPEG XL"), + .priv_data_size = sizeof(JXLAnimDemuxContext), + .read_probe = jpegxl_anim_probe, + .read_header = jpegxl_anim_read_header, + .read_packet = jpegxl_anim_read_packet, + .read_close = jpegxl_anim_close, + .flags_internal = FF_FMT_INIT_CLEANUP, + .flags = AVFMT_GENERIC_INDEX, + .mime_type = "image/jxl", + .extensions = "jxl", +}; diff --git a/libavformat/jpegxl_probe.c b/libavformat/jpegxl_probe.c index 3de002f0045..a3845b037db 100644 --- a/libavformat/jpegxl_probe.c +++ b/libavformat/jpegxl_probe.c @@ -208,7 +208,7 @@ static void jpegxl_skip_bit_depth(GetBitContext *gb) * validate a Jpeg XL Extra Channel Info bundle * @return >= 0 upon valid, < 0 upon invalid */ -static int jpegxl_read_extra_channel_info(GetBitContext *gb) +static int jpegxl_read_extra_channel_info(GetBitContext *gb, int validate_level) { int all_default = jxl_bits(1); uint32_t type, name_len = 0; @@ -217,7 +217,7 @@ static int jpegxl_read_extra_channel_info(GetBitContext *gb) type = jxl_enum(); if (type > 63) return -1; /* enum types cannot be 64+ */ - if (type == FF_JPEGXL_CT_BLACK) + if (type == FF_JPEGXL_CT_BLACK && validate_level) return -1; jpegxl_skip_bit_depth(gb); jxl_u32(0, 3, 4, 1, 0, 0, 0, 3); /* dim-shift */ @@ -242,12 +242,12 @@ static int jpegxl_read_extra_channel_info(GetBitContext *gb) return 0; } -/* verify that a codestream header is valid */ -int ff_jpegxl_verify_codestream_header(const uint8_t *buf, int buflen) +int ff_jpegxl_verify_codestream_header(const uint8_t *buf, int buflen, int validate_level) { GetBitContext gbi, *gb = &gbi; int all_default, extra_fields = 0; int xyb_encoded = 1, have_icc_profile = 0; + int animation_offset = 0; uint32_t num_extra_channels; uint64_t extensions; int ret; @@ -259,7 +259,7 @@ int ff_jpegxl_verify_codestream_header(const uint8_t *buf, int buflen) if (jxl_bits(16) != FF_JPEGXL_CODESTREAM_SIGNATURE_LE) return -1; - if (jpegxl_read_size_header(gb) < 0) + if (jpegxl_read_size_header(gb) < 0 && validate_level) return -1; all_default = jxl_bits(1); @@ -285,6 +285,7 @@ int ff_jpegxl_verify_codestream_header(const uint8_t *buf, int buflen) /* animation header */ if (jxl_bits(1)) { + animation_offset = get_bits_count(gb); jxl_u32(100, 1000, 1, 1, 0, 0, 10, 30); jxl_u32(1, 1001, 1, 1, 0, 0, 8, 10); jxl_u32(0, 0, 0, 0, 0, 3, 16, 32); @@ -296,14 +297,14 @@ int ff_jpegxl_verify_codestream_header(const uint8_t *buf, int buflen) jpegxl_skip_bit_depth(gb); /* modular_16bit_buffers must equal 1 */ - if (!jxl_bits(1)) + if (!jxl_bits(1) && validate_level) return -1; num_extra_channels = jxl_u32(0, 1, 2, 1, 0, 0, 4, 12); - if (num_extra_channels > 4) + if (num_extra_channels > 4 && validate_level) return -1; for (uint32_t i = 0; i < num_extra_channels; i++) { - if (jpegxl_read_extra_channel_info(gb) < 0) + if (jpegxl_read_extra_channel_info(gb, validate_level) < 0) return -1; } @@ -392,5 +393,5 @@ int ff_jpegxl_verify_codestream_header(const uint8_t *buf, int buflen) if (get_bits_left(gb) < 0) return -1; - return 0; + return animation_offset; } diff --git a/libavformat/jpegxl_probe.h b/libavformat/jpegxl_probe.h index 2960e81e11c..496445fbce2 100644 --- a/libavformat/jpegxl_probe.h +++ b/libavformat/jpegxl_probe.h @@ -27,6 +27,11 @@ #define FF_JPEGXL_CODESTREAM_SIGNATURE_LE 0x0aff #define FF_JPEGXL_CONTAINER_SIGNATURE_LE 0x204c584a0c000000 -int ff_jpegxl_verify_codestream_header(const uint8_t *buf, int buflen); +/** + * @brief verify that a codestream header is valid + * @return Negative upon error, 0 upon verifying that the codestream is not animated, + * and 1 upon verifying that it is animated + */ +int ff_jpegxl_verify_codestream_header(const uint8_t *buf, int buflen, int validate_level); #endif /* AVFORMAT_JPEGXL_PROBE_H */ diff --git a/libavformat/version.h b/libavformat/version.h index e2634b85ae1..4bde82abb44 100644 --- a/libavformat/version.h +++ b/libavformat/version.h @@ -31,7 +31,7 @@ #include "version_major.h" -#define LIBAVFORMAT_VERSION_MINOR 5 +#define LIBAVFORMAT_VERSION_MINOR 6 #define LIBAVFORMAT_VERSION_MICRO 100 #define LIBAVFORMAT_VERSION_INT AV_VERSION_INT(LIBAVFORMAT_VERSION_MAJOR, \ From fb1b88af77cd39034cef4b6d08af79496cd75ed8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Storsj=C3=B6?= Date: Thu, 25 May 2023 14:57:37 +0300 Subject: [PATCH 1417/2172] configure: aarch64: Support assembling the dotprod and i8mm arch extensions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit These are available since ARMv8.4-a and ARMv8.6-a respectively, but can also be available optionally since ARMv8.2-a. Check if ".arch armv8.2-a" and ".arch_extension {dotprod,i8mm}" are supported, and check if the instructions can be assembled. Current clang versions fail to support the dotprod and i8mm features in the .arch_extension directive, but do support them if enabled with -march=armv8.4-a on the command line. (Curiously, lowering the arch level with ".arch armv8.2-a" doesn't make the extensions unavailable if they were enabled with -march; if that changes, Clang should also learn to support these extensions via .arch_extension for them to remain usable here.) Signed-off-by: Martin Storsjö --- configure | 81 ++++++++++++++++++++++++++++++++++++++++- libavutil/aarch64/asm.S | 11 ++++++ 2 files changed, 91 insertions(+), 1 deletion(-) diff --git a/configure b/configure index ae56540f4eb..c791679794c 100755 --- a/configure +++ b/configure @@ -454,6 +454,8 @@ Optimization options (experts only): --disable-armv6t2 disable armv6t2 optimizations --disable-vfp disable VFP optimizations --disable-neon disable NEON optimizations + --disable-dotprod disable DOTPROD optimizations + --disable-i8mm disable I8MM optimizations --disable-inline-asm disable use of inline assembly --disable-x86asm disable use of standalone x86 assembly --disable-mipsdsp disable MIPS DSP ASE R1 optimizations @@ -1154,6 +1156,43 @@ check_insn(){ check_as ${1}_external "$2" } +check_arch_level(){ + log check_arch_level "$@" + level="$1" + check_as tested_arch_level ".arch $level" + enabled tested_arch_level && as_arch_level="$level" +} + +check_archext_insn(){ + log check_archext_insn "$@" + feature="$1" + instr="$2" + # Check if the assembly is accepted in inline assembly. + check_inline_asm ${feature}_inline "\"$instr\"" + # We don't check if the instruction is supported out of the box by the + # external assembler (we don't try to set ${feature}_external) as we don't + # need to use these instructions in non-runtime detected codepaths. + + disable $feature + + enabled as_arch_directive && arch_directive=".arch $as_arch_level" || arch_directive="" + + # Test if the assembler supports the .arch_extension $feature directive. + arch_extension_directive=".arch_extension $feature" + test_as <>$TMPH +enabled aarch64 && + echo "#define AS_ARCH_LEVEL $as_arch_level" >>$TMPH + if enabled x86asm; then append config_files $TMPASM cat > $TMPASM < Date: Thu, 25 May 2023 15:29:02 +0300 Subject: [PATCH 1418/2172] aarch64: Add cpu flags for the dotprod and i8mm extensions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Set these available if they are available unconditionally for the compiler. Signed-off-by: Martin Storsjö --- libavutil/aarch64/cpu.c | 15 ++++++++++++--- libavutil/aarch64/cpu.h | 2 ++ libavutil/cpu.c | 2 ++ libavutil/cpu.h | 2 ++ libavutil/tests/cpu.c | 2 ++ tests/checkasm/checkasm.c | 2 ++ 6 files changed, 22 insertions(+), 3 deletions(-) diff --git a/libavutil/aarch64/cpu.c b/libavutil/aarch64/cpu.c index cc641da576a..0c76f5ad15f 100644 --- a/libavutil/aarch64/cpu.c +++ b/libavutil/aarch64/cpu.c @@ -22,9 +22,18 @@ int ff_get_cpu_flags_aarch64(void) { - return AV_CPU_FLAG_ARMV8 * HAVE_ARMV8 | - AV_CPU_FLAG_NEON * HAVE_NEON | - AV_CPU_FLAG_VFP * HAVE_VFP; + int flags = AV_CPU_FLAG_ARMV8 * HAVE_ARMV8 | + AV_CPU_FLAG_NEON * HAVE_NEON | + AV_CPU_FLAG_VFP * HAVE_VFP; + +#ifdef __ARM_FEATURE_DOTPROD + flags |= AV_CPU_FLAG_DOTPROD; +#endif +#ifdef __ARM_FEATURE_MATMUL_INT8 + flags |= AV_CPU_FLAG_I8MM; +#endif + + return flags; } size_t ff_get_cpu_max_align_aarch64(void) diff --git a/libavutil/aarch64/cpu.h b/libavutil/aarch64/cpu.h index 2ee3f9323af..64d703be377 100644 --- a/libavutil/aarch64/cpu.h +++ b/libavutil/aarch64/cpu.h @@ -25,5 +25,7 @@ #define have_armv8(flags) CPUEXT(flags, ARMV8) #define have_neon(flags) CPUEXT(flags, NEON) #define have_vfp(flags) CPUEXT(flags, VFP) +#define have_dotprod(flags) CPUEXT(flags, DOTPROD) +#define have_i8mm(flags) CPUEXT(flags, I8MM) #endif /* AVUTIL_AARCH64_CPU_H */ diff --git a/libavutil/cpu.c b/libavutil/cpu.c index 2c5f7f4958d..2ffc3986aa4 100644 --- a/libavutil/cpu.c +++ b/libavutil/cpu.c @@ -174,6 +174,8 @@ int av_parse_cpu_caps(unsigned *flags, const char *s) { "armv8", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = AV_CPU_FLAG_ARMV8 }, .unit = "flags" }, { "neon", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = AV_CPU_FLAG_NEON }, .unit = "flags" }, { "vfp", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = AV_CPU_FLAG_VFP }, .unit = "flags" }, + { "dotprod", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = AV_CPU_FLAG_DOTPROD }, .unit = "flags" }, + { "i8mm", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = AV_CPU_FLAG_I8MM }, .unit = "flags" }, #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" }, diff --git a/libavutil/cpu.h b/libavutil/cpu.h index 8fa5ea91995..da486f9c7ab 100644 --- a/libavutil/cpu.h +++ b/libavutil/cpu.h @@ -69,6 +69,8 @@ #define AV_CPU_FLAG_NEON (1 << 5) #define AV_CPU_FLAG_ARMV8 (1 << 6) #define AV_CPU_FLAG_VFP_VM (1 << 7) ///< VFPv2 vector mode, deprecated in ARMv7-A and unavailable in various CPUs implementations +#define AV_CPU_FLAG_DOTPROD (1 << 8) +#define AV_CPU_FLAG_I8MM (1 << 9) #define AV_CPU_FLAG_SETEND (1 <<16) #define AV_CPU_FLAG_MMI (1 << 0) diff --git a/libavutil/tests/cpu.c b/libavutil/tests/cpu.c index dadadb31dc7..a52637339d9 100644 --- a/libavutil/tests/cpu.c +++ b/libavutil/tests/cpu.c @@ -38,6 +38,8 @@ static const struct { { AV_CPU_FLAG_ARMV8, "armv8" }, { AV_CPU_FLAG_NEON, "neon" }, { AV_CPU_FLAG_VFP, "vfp" }, + { AV_CPU_FLAG_DOTPROD, "dotprod" }, + { AV_CPU_FLAG_I8MM, "i8mm" }, #elif ARCH_ARM { AV_CPU_FLAG_ARMV5TE, "armv5te" }, { AV_CPU_FLAG_ARMV6, "armv6" }, diff --git a/tests/checkasm/checkasm.c b/tests/checkasm/checkasm.c index 7389ebaee9f..4311a8ffcb0 100644 --- a/tests/checkasm/checkasm.c +++ b/tests/checkasm/checkasm.c @@ -230,6 +230,8 @@ static const struct { #if ARCH_AARCH64 { "ARMV8", "armv8", AV_CPU_FLAG_ARMV8 }, { "NEON", "neon", AV_CPU_FLAG_NEON }, + { "DOTPROD", "dotprod", AV_CPU_FLAG_DOTPROD }, + { "I8MM", "i8mm", AV_CPU_FLAG_I8MM }, #elif ARCH_ARM { "ARMV5TE", "armv5te", AV_CPU_FLAG_ARMV5TE }, { "ARMV6", "armv6", AV_CPU_FLAG_ARMV6 }, From 493fcde50a84cb23854335bcb0e55c6f383d55db Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Storsj=C3=B6?= Date: Thu, 25 May 2023 15:47:15 +0300 Subject: [PATCH 1419/2172] aarch64: Add Linux runtime cpu feature detection using HWCAP_CPUID MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Based partially on code by Janne Grunau. Signed-off-by: Martin Storsjö --- configure | 2 ++ libavutil/aarch64/cpu.c | 52 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 54 insertions(+) diff --git a/configure b/configure index c791679794c..5127fa0d8c5 100755 --- a/configure +++ b/configure @@ -2209,6 +2209,7 @@ HAVE_LIST_PUB=" HEADERS_LIST=" arpa_inet_h + asm_hwcap_h asm_types_h cdio_paranoia_h cdio_paranoia_paranoia_h @@ -6432,6 +6433,7 @@ check_headers io.h enabled libdrm && check_headers linux/dma-buf.h +check_headers asm/hwcap.h check_headers linux/perf_event.h check_headers libcrystalhd/libcrystalhd_if.h check_headers malloc.h diff --git a/libavutil/aarch64/cpu.c b/libavutil/aarch64/cpu.c index 0c76f5ad15f..025bf308287 100644 --- a/libavutil/aarch64/cpu.c +++ b/libavutil/aarch64/cpu.c @@ -20,6 +20,56 @@ #include "libavutil/cpu_internal.h" #include "config.h" +#if (defined(__linux__) || defined(__ANDROID__)) && HAVE_GETAUXVAL && HAVE_ASM_HWCAP_H +#include +#include +#include + +#define get_cpu_feature_reg(reg, val) \ + __asm__("mrs %0, " #reg : "=r" (val)) + +static int detect_flags(void) +{ + int flags = 0; + unsigned long hwcap; + + hwcap = getauxval(AT_HWCAP); + +#if defined(HWCAP_CPUID) + // We can check for DOTPROD and I8MM using HWCAP_ASIMDDP and + // HWCAP2_I8MM too, avoiding to read the CPUID registers (which triggers + // a trap, handled by the kernel). However the HWCAP_* defines for these + // extensions are added much later than HWCAP_CPUID, so the userland + // headers might lack support for them even if the binary later is run + // on hardware that does support it (and where the kernel might support + // HWCAP_CPUID). + // See https://www.kernel.org/doc/html/latest/arm64/cpu-feature-registers.html + if (hwcap & HWCAP_CPUID) { + uint64_t tmp; + + get_cpu_feature_reg(ID_AA64ISAR0_EL1, tmp); + if (((tmp >> 44) & 0xf) == 0x1) + flags |= AV_CPU_FLAG_DOTPROD; + get_cpu_feature_reg(ID_AA64ISAR1_EL1, tmp); + if (((tmp >> 52) & 0xf) == 0x1) + flags |= AV_CPU_FLAG_I8MM; + } +#else + (void)hwcap; +#endif + + return flags; +} + +#else + +static int detect_flags(void) +{ + return 0; +} + +#endif + int ff_get_cpu_flags_aarch64(void) { int flags = AV_CPU_FLAG_ARMV8 * HAVE_ARMV8 | @@ -33,6 +83,8 @@ int ff_get_cpu_flags_aarch64(void) flags |= AV_CPU_FLAG_I8MM; #endif + flags |= detect_flags(); + return flags; } From 9b0052200aa959d5ac939620bc14f0403621ab05 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Storsj=C3=B6?= Date: Fri, 26 May 2023 10:20:21 +0300 Subject: [PATCH 1420/2172] aarch64: Add Apple runtime detection of dotprod and i8mm using sysctl MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit For now, there's not much value in this since Clang don't support enabling the dotprod or i8mm features with either .arch_extension or .arch (it has to be enabled by the base arch flags passed to the compiler). But it may be supported in the future. Signed-off-by: Martin Storsjö --- configure | 2 ++ libavutil/aarch64/cpu.c | 22 ++++++++++++++++++++++ 2 files changed, 24 insertions(+) diff --git a/configure b/configure index 5127fa0d8c5..2992dae283e 100755 --- a/configure +++ b/configure @@ -2348,6 +2348,7 @@ SYSTEM_FUNCS=" strerror_r sysconf sysctl + sysctlbyname usleep UTGetOSTypeFromString VirtualAlloc @@ -6394,6 +6395,7 @@ check_func_headers mach/mach_time.h mach_absolute_time check_func_headers stdlib.h getenv check_func_headers sys/stat.h lstat check_func_headers sys/auxv.h getauxval +check_func_headers sys/sysctl.h sysctlbyname check_func_headers windows.h GetModuleHandle check_func_headers windows.h GetProcessAffinityMask diff --git a/libavutil/aarch64/cpu.c b/libavutil/aarch64/cpu.c index 025bf308287..b808a7650e5 100644 --- a/libavutil/aarch64/cpu.c +++ b/libavutil/aarch64/cpu.c @@ -61,6 +61,28 @@ static int detect_flags(void) return flags; } +#elif defined(__APPLE__) && HAVE_SYSCTLBYNAME +#include + +static int detect_flags(void) +{ + uint32_t value = 0; + size_t size; + int flags = 0; + + size = sizeof(value); + if (!sysctlbyname("hw.optional.arm.FEAT_DotProd", &value, &size, NULL, 0)) { + if (value) + flags |= AV_CPU_FLAG_DOTPROD; + } + size = sizeof(value); + if (!sysctlbyname("hw.optional.arm.FEAT_I8MM", &value, &size, NULL, 0)) { + if (value) + flags |= AV_CPU_FLAG_I8MM; + } + return flags; +} + #else static int detect_flags(void) From c76643021efdbd24b674298f802ff2c8d9316fe5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Storsj=C3=B6?= Date: Fri, 26 May 2023 14:05:30 +0300 Subject: [PATCH 1421/2172] aarch64: Add Windows runtime detection of the dotprod instructions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit For Windows, there's no publicly defined constant for checking for the i8mm extension yet. Signed-off-by: Martin Storsjö --- libavutil/aarch64/cpu.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/libavutil/aarch64/cpu.c b/libavutil/aarch64/cpu.c index b808a7650e5..a8cb301dd75 100644 --- a/libavutil/aarch64/cpu.c +++ b/libavutil/aarch64/cpu.c @@ -83,6 +83,18 @@ static int detect_flags(void) return flags; } +#elif defined(_WIN32) +#include + +static int detect_flags(void) +{ + int flags = 0; +#ifdef PF_ARM_V82_DP_INSTRUCTIONS_AVAILABLE + if (IsProcessorFeaturePresent(PF_ARM_V82_DP_INSTRUCTIONS_AVAILABLE)) + flags |= AV_CPU_FLAG_DOTPROD; +#endif + return flags; +} #else static int detect_flags(void) From 0b7356c1b493dc50663364b443ad1dad04fdba14 Mon Sep 17 00:00:00 2001 From: Logan Lyu Date: Wed, 3 May 2023 09:53:07 +0800 Subject: [PATCH 1422/2172] lavc/aarch64: new optimization for 8-bit hevc_pel_uni_w_pixels and qpel_uni_w_v MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Martin Storsjö --- libavcodec/aarch64/hevcdsp_init_aarch64.c | 51 ++ libavcodec/aarch64/hevcdsp_qpel_neon.S | 710 ++++++++++++++++++++++ 2 files changed, 761 insertions(+) diff --git a/libavcodec/aarch64/hevcdsp_init_aarch64.c b/libavcodec/aarch64/hevcdsp_init_aarch64.c index be1049a2ec7..6b5341dd459 100644 --- a/libavcodec/aarch64/hevcdsp_init_aarch64.c +++ b/libavcodec/aarch64/hevcdsp_init_aarch64.c @@ -128,6 +128,52 @@ void ff_hevc_put_hevc_qpel_bi_h16_8_neon(uint8_t *_dst, ptrdiff_t _dststride, co ptrdiff_t _srcstride, const int16_t *src2, int height, intptr_t mx, intptr_t my, int width); +#define NEON8_FNPROTO(fn, args, ext) \ + void ff_hevc_put_hevc_##fn##4_8_neon##ext args; \ + void ff_hevc_put_hevc_##fn##6_8_neon##ext args; \ + void ff_hevc_put_hevc_##fn##8_8_neon##ext args; \ + void ff_hevc_put_hevc_##fn##12_8_neon##ext args; \ + void ff_hevc_put_hevc_##fn##16_8_neon##ext args; \ + void ff_hevc_put_hevc_##fn##24_8_neon##ext args; \ + void ff_hevc_put_hevc_##fn##32_8_neon##ext args; \ + void ff_hevc_put_hevc_##fn##48_8_neon##ext args; \ + void ff_hevc_put_hevc_##fn##64_8_neon##ext args; \ + +#define NEON8_FNPROTO_PARTIAL_4(fn, args, ext) \ + void ff_hevc_put_hevc_##fn##4_8_neon##ext args; \ + void ff_hevc_put_hevc_##fn##8_8_neon##ext args; \ + void ff_hevc_put_hevc_##fn##16_8_neon##ext args; \ + void ff_hevc_put_hevc_##fn##64_8_neon##ext args; \ + +NEON8_FNPROTO(pel_uni_w_pixels, (uint8_t *_dst, ptrdiff_t _dststride, + const uint8_t *_src, ptrdiff_t _srcstride, + int height, int denom, int wx, int ox, + intptr_t mx, intptr_t my, int width),); + +NEON8_FNPROTO_PARTIAL_4(qpel_uni_w_v, (uint8_t *_dst, ptrdiff_t _dststride, + const uint8_t *_src, ptrdiff_t _srcstride, + int height, int denom, int wx, int ox, + intptr_t mx, intptr_t my, int width),); + +#define NEON8_FNASSIGN(member, v, h, fn, ext) \ + member[1][v][h] = ff_hevc_put_hevc_##fn##4_8_neon##ext; \ + member[2][v][h] = ff_hevc_put_hevc_##fn##6_8_neon##ext; \ + member[3][v][h] = ff_hevc_put_hevc_##fn##8_8_neon##ext; \ + member[4][v][h] = ff_hevc_put_hevc_##fn##12_8_neon##ext; \ + member[5][v][h] = ff_hevc_put_hevc_##fn##16_8_neon##ext; \ + member[6][v][h] = ff_hevc_put_hevc_##fn##24_8_neon##ext; \ + member[7][v][h] = ff_hevc_put_hevc_##fn##32_8_neon##ext; \ + member[8][v][h] = ff_hevc_put_hevc_##fn##48_8_neon##ext; \ + member[9][v][h] = ff_hevc_put_hevc_##fn##64_8_neon##ext; + +#define NEON8_FNASSIGN_PARTIAL_4(member, v, h, fn, ext) \ + member[1][v][h] = ff_hevc_put_hevc_##fn##4_8_neon##ext; \ + member[3][v][h] = ff_hevc_put_hevc_##fn##8_8_neon##ext; \ + member[5][v][h] = ff_hevc_put_hevc_##fn##16_8_neon##ext; \ + member[7][v][h] = ff_hevc_put_hevc_##fn##64_8_neon##ext; \ + member[8][v][h] = ff_hevc_put_hevc_##fn##64_8_neon##ext; \ + member[9][v][h] = ff_hevc_put_hevc_##fn##64_8_neon##ext; + av_cold void ff_hevc_dsp_init_aarch64(HEVCDSPContext *c, const int bit_depth) { if (!have_neon(av_get_cpu_flags())) return; @@ -185,6 +231,11 @@ av_cold void ff_hevc_dsp_init_aarch64(HEVCDSPContext *c, const int bit_depth) c->put_hevc_qpel_bi[7][0][1] = c->put_hevc_qpel_bi[8][0][1] = c->put_hevc_qpel_bi[9][0][1] = ff_hevc_put_hevc_qpel_bi_h16_8_neon; + + NEON8_FNASSIGN(c->put_hevc_epel_uni_w, 0, 0, pel_uni_w_pixels,); + NEON8_FNASSIGN(c->put_hevc_qpel_uni_w, 0, 0, pel_uni_w_pixels,); + NEON8_FNASSIGN_PARTIAL_4(c->put_hevc_qpel_uni_w, 1, 0, qpel_uni_w_v,); + } if (bit_depth == 10) { c->hevc_h_loop_filter_chroma = ff_hevc_h_loop_filter_chroma_10_neon; diff --git a/libavcodec/aarch64/hevcdsp_qpel_neon.S b/libavcodec/aarch64/hevcdsp_qpel_neon.S index 0e7b912678d..51df52e1eae 100644 --- a/libavcodec/aarch64/hevcdsp_qpel_neon.S +++ b/libavcodec/aarch64/hevcdsp_qpel_neon.S @@ -30,6 +30,13 @@ const qpel_filters, align=4 .byte 0, 1, -5, 17, 58,-10, 4, -1 endconst +const qpel_filters_abs, align=4 + .byte 0, 0, 0, 0, 0, 0, 0, 0 + .byte 1, 4, 10, 58, 17, 5, 1, 0 + .byte 1, 4, 11, 40, 40, 11, 4, 1 + .byte 0, 1, 5, 17, 58, 10, 4, 1 +endconst + .macro load_filter m movrel x15, qpel_filters add x15, x15, \m, lsl #3 @@ -482,3 +489,706 @@ endfunc put_hevc qpel put_hevc qpel_uni put_hevc qpel_bi + + +function ff_hevc_put_hevc_pel_uni_w_pixels4_8_neon, export=1 + mov w10, #-6 + sub w10, w10, w5 + dup v30.8h, w6 + dup v31.4s, w10 + dup v29.4s, w7 +1: + ldr s0, [x2] + ldr s1, [x2, x3] + add x2, x2, x3, lsl #1 + ushll v0.8h, v0.8b, #6 + ushll v1.8h, v1.8b, #6 + smull v0.4s, v0.4h, v30.4h + smull v1.4s, v1.4h, v30.4h + sqrshl v0.4s, v0.4s, v31.4s + sqrshl v1.4s, v1.4s, v31.4s + sqadd v0.4s, v0.4s, v29.4s + sqadd v1.4s, v1.4s, v29.4s + sqxtn v0.4h, v0.4s + sqxtn v1.4h, v1.4s + sqxtun v0.8b, v0.8h + sqxtun v1.8b, v1.8h + str s0, [x0] + str s1, [x0, x1] + add x0, x0, x1, lsl #1 + subs w4, w4, #2 + b.ne 1b + ret +endfunc + +function ff_hevc_put_hevc_pel_uni_w_pixels6_8_neon, export=1 + mov w10, #-6 + sub w10, w10, w5 + dup v30.8h, w6 + dup v31.4s, w10 + dup v29.4s, w7 + sub x1, x1, #4 +1: + ldr d0, [x2] + ldr d1, [x2, x3] + add x2, x2, x3, lsl #1 + ushll v0.8h, v0.8b, #6 + ushll v1.8h, v1.8b, #6 + smull v4.4s, v0.4h, v30.4h + smull2 v5.4s, v0.8h, v30.8h + smull v6.4s, v1.4h, v30.4h + smull2 v7.4s, v1.8h, v30.8h + sqrshl v4.4s, v4.4s, v31.4s + sqrshl v5.4s, v5.4s, v31.4s + sqrshl v6.4s, v6.4s, v31.4s + sqrshl v7.4s, v7.4s, v31.4s + sqadd v4.4s, v4.4s, v29.4s + sqadd v5.4s, v5.4s, v29.4s + sqadd v6.4s, v6.4s, v29.4s + sqadd v7.4s, v7.4s, v29.4s + sqxtn v0.4h, v4.4s + sqxtn2 v0.8h, v5.4s + sqxtn v1.4h, v6.4s + sqxtn2 v1.8h, v7.4s + sqxtun v0.8b, v0.8h + sqxtun v1.8b, v1.8h + str s0, [x0], #4 + st1 {v0.h}[2], [x0], x1 + str s1, [x0], #4 + st1 {v1.h}[2], [x0], x1 + subs w4, w4, #2 + b.ne 1b + ret +endfunc + +function ff_hevc_put_hevc_pel_uni_w_pixels8_8_neon, export=1 + mov w10, #-6 + sub w10, w10, w5 + dup v30.8h, w6 + dup v31.4s, w10 + dup v29.4s, w7 +1: + ldr d0, [x2] + ldr d1, [x2, x3] + add x2, x2, x3, lsl #1 + ushll v0.8h, v0.8b, #6 + ushll v1.8h, v1.8b, #6 + smull v4.4s, v0.4h, v30.4h + smull2 v5.4s, v0.8h, v30.8h + smull v6.4s, v1.4h, v30.4h + smull2 v7.4s, v1.8h, v30.8h + sqrshl v4.4s, v4.4s, v31.4s + sqrshl v5.4s, v5.4s, v31.4s + sqrshl v6.4s, v6.4s, v31.4s + sqrshl v7.4s, v7.4s, v31.4s + sqadd v4.4s, v4.4s, v29.4s + sqadd v5.4s, v5.4s, v29.4s + sqadd v6.4s, v6.4s, v29.4s + sqadd v7.4s, v7.4s, v29.4s + sqxtn v0.4h, v4.4s + sqxtn2 v0.8h, v5.4s + sqxtn v1.4h, v6.4s + sqxtn2 v1.8h, v7.4s + sqxtun v0.8b, v0.8h + sqxtun v1.8b, v1.8h + str d0, [x0] + str d1, [x0, x1] + add x0, x0, x1, lsl #1 + subs w4, w4, #2 + b.ne 1b + ret +endfunc + +function ff_hevc_put_hevc_pel_uni_w_pixels12_8_neon, export=1 + mov w10, #-6 + sub w10, w10, w5 + dup v30.8h, w6 + dup v31.4s, w10 + dup v29.4s, w7 + sub x1, x1, #8 +1: + ldr q0, [x2] + ldr q1, [x2, x3] + add x2, x2, x3, lsl #1 + ushll v4.8h, v0.8b, #6 + ushll2 v5.8h, v0.16b, #6 + ushll v6.8h, v1.8b, #6 + ushll2 v7.8h, v1.16b, #6 + smull v16.4s, v4.4h, v30.4h + smull2 v17.4s, v4.8h, v30.8h + smull v18.4s, v5.4h, v30.4h + smull2 v19.4s, v5.8h, v30.8h + smull v20.4s, v6.4h, v30.4h + smull2 v21.4s, v6.8h, v30.8h + smull v22.4s, v7.4h, v30.4h + smull2 v23.4s, v7.8h, v30.8h + + sqrshl v16.4s, v16.4s, v31.4s + sqrshl v17.4s, v17.4s, v31.4s + sqrshl v18.4s, v18.4s, v31.4s + sqrshl v19.4s, v19.4s, v31.4s + sqrshl v20.4s, v20.4s, v31.4s + sqrshl v21.4s, v21.4s, v31.4s + sqrshl v22.4s, v22.4s, v31.4s + sqrshl v23.4s, v23.4s, v31.4s + sqadd v16.4s, v16.4s, v29.4s + sqadd v17.4s, v17.4s, v29.4s + sqadd v18.4s, v18.4s, v29.4s + sqadd v19.4s, v19.4s, v29.4s + sqadd v20.4s, v20.4s, v29.4s + sqadd v21.4s, v21.4s, v29.4s + sqadd v22.4s, v22.4s, v29.4s + sqadd v23.4s, v23.4s, v29.4s + sqxtn v0.4h, v16.4s + sqxtn2 v0.8h, v17.4s + sqxtn v1.4h, v18.4s + sqxtn2 v1.8h, v19.4s + sqxtn v2.4h, v20.4s + sqxtn2 v2.8h, v21.4s + sqxtn v3.4h, v22.4s + sqxtn2 v3.8h, v23.4s + sqxtun v0.8b, v0.8h + sqxtun2 v0.16b, v1.8h + sqxtun v2.8b, v2.8h + sqxtun2 v2.16b, v3.8h + str d0, [x0], #8 + st1 {v0.s}[2], [x0], x1 + str d2, [x0], #8 + st1 {v2.s}[2], [x0], x1 + subs w4, w4, #2 + b.ne 1b + ret +endfunc + +.macro PEL_UNI_W_PIXEL_CALC s0, t0, t1, d0, d1, d2, d3 + ushll \t0\().8h, \s0\().8b, #6 + ushll2 \t1\().8h, \s0\().16b, #6 + smull \d0\().4s, \t0\().4h, v30.4h + smull2 \d1\().4s, \t0\().8h, v30.8h + smull \d2\().4s, \t1\().4h, v30.4h + smull2 \d3\().4s, \t1\().8h, v30.8h + sqrshl \d0\().4s, \d0\().4s, v31.4s + sqrshl \d1\().4s, \d1\().4s, v31.4s + sqrshl \d2\().4s, \d2\().4s, v31.4s + sqrshl \d3\().4s, \d3\().4s, v31.4s + sqadd \d0\().4s, \d0\().4s, v29.4s + sqadd \d1\().4s, \d1\().4s, v29.4s + sqadd \d2\().4s, \d2\().4s, v29.4s + sqadd \d3\().4s, \d3\().4s, v29.4s + sqxtn \t0\().4h, \d0\().4s + sqxtn2 \t0\().8h, \d1\().4s + sqxtn \t1\().4h, \d2\().4s + sqxtn2 \t1\().8h, \d3\().4s + sqxtun \s0\().8b, \t0\().8h + sqxtun2 \s0\().16b, \t1\().8h +.endm + + +function ff_hevc_put_hevc_pel_uni_w_pixels16_8_neon, export=1 + mov w10, #-6 + sub w10, w10, w5 + dup v30.8h, w6 + dup v31.4s, w10 + dup v29.4s, w7 +1: + ldr q0, [x2] + ldr q1, [x2, x3] + add x2, x2, x3, lsl #1 + PEL_UNI_W_PIXEL_CALC v0, v4, v5, v16, v17, v18, v19 + PEL_UNI_W_PIXEL_CALC v1, v6, v7, v20, v21, v22, v23 + str q0, [x0] + str q1, [x0, x1] + add x0, x0, x1, lsl #1 + subs w4, w4, #2 + b.ne 1b + ret +endfunc + + + +function ff_hevc_put_hevc_pel_uni_w_pixels24_8_neon, export=1 + mov w10, #-6 + sub w10, w10, w5 + dup v30.8h, w6 + dup v31.4s, w10 + dup v29.4s, w7 +1: + ld1 {v0.16b, v1.16b}, [x2], x3 + ushll v4.8h, v0.8b, #6 + ushll2 v5.8h, v0.16b, #6 + ushll v6.8h, v1.8b, #6 + smull v16.4s, v4.4h, v30.4h + smull2 v17.4s, v4.8h, v30.8h + smull v18.4s, v5.4h, v30.4h + smull2 v19.4s, v5.8h, v30.8h + smull v20.4s, v6.4h, v30.4h + smull2 v21.4s, v6.8h, v30.8h + sqrshl v16.4s, v16.4s, v31.4s + sqrshl v17.4s, v17.4s, v31.4s + sqrshl v18.4s, v18.4s, v31.4s + sqrshl v19.4s, v19.4s, v31.4s + sqrshl v20.4s, v20.4s, v31.4s + sqrshl v21.4s, v21.4s, v31.4s + sqadd v16.4s, v16.4s, v29.4s + sqadd v17.4s, v17.4s, v29.4s + sqadd v18.4s, v18.4s, v29.4s + sqadd v19.4s, v19.4s, v29.4s + sqadd v20.4s, v20.4s, v29.4s + sqadd v21.4s, v21.4s, v29.4s + sqxtn v0.4h, v16.4s + sqxtn2 v0.8h, v17.4s + sqxtn v1.4h, v18.4s + sqxtn2 v1.8h, v19.4s + sqxtn v2.4h, v20.4s + sqxtn2 v2.8h, v21.4s + sqxtun v0.8b, v0.8h + sqxtun v1.8b, v1.8h + sqxtun v2.8b, v2.8h + st1 {v0.8b, v1.8b, v2.8b}, [x0], x1 + subs w4, w4, #1 + b.ne 1b + ret +endfunc + +function ff_hevc_put_hevc_pel_uni_w_pixels32_8_neon, export=1 + mov w10, #-6 + sub w10, w10, w5 + dup v30.8h, w6 + dup v31.4s, w10 + dup v29.4s, w7 +1: + ld1 {v0.16b, v1.16b}, [x2], x3 + PEL_UNI_W_PIXEL_CALC v0, v4, v5, v16, v17, v18, v19 + PEL_UNI_W_PIXEL_CALC v1, v6, v7, v20, v21, v22, v23 + st1 {v0.16b, v1.16b}, [x0], x1 + subs w4, w4, #1 + b.ne 1b + ret +endfunc + + +function ff_hevc_put_hevc_pel_uni_w_pixels48_8_neon, export=1 + mov w10, #-6 + sub w10, w10, w5 + dup v30.8h, w6 + dup v31.4s, w10 + dup v29.4s, w7 +1: + ld1 {v0.16b, v1.16b, v2.16b}, [x2], x3 + PEL_UNI_W_PIXEL_CALC v0, v4, v5, v16, v17, v18, v19 + PEL_UNI_W_PIXEL_CALC v1, v6, v7, v20, v21, v22, v23 + PEL_UNI_W_PIXEL_CALC v2, v4, v5, v16, v17, v18, v19 + st1 {v0.16b, v1.16b, v2.16b}, [x0], x1 + subs w4, w4, #1 + b.ne 1b + ret +endfunc + +function ff_hevc_put_hevc_pel_uni_w_pixels64_8_neon, export=1 + mov w10, #-6 + sub w10, w10, w5 + dup v30.8h, w6 + dup v31.4s, w10 + dup v29.4s, w7 +1: + ld1 {v0.16b, v1.16b, v2.16b, v3.16b}, [x2], x3 + PEL_UNI_W_PIXEL_CALC v0, v4, v5, v16, v17, v18, v19 + PEL_UNI_W_PIXEL_CALC v1, v6, v7, v20, v21, v22, v23 + PEL_UNI_W_PIXEL_CALC v2, v4, v5, v16, v17, v18, v19 + PEL_UNI_W_PIXEL_CALC v3, v6, v7, v20, v21, v22, v23 + st1 {v0.16b, v1.16b, v2.16b, v3.16b}, [x0], x1 + subs w4, w4, #1 + b.ne 1b + ret +endfunc + +.macro QPEL_UNI_W_V_HEADER + ldur x12, [sp, #8] // my + sub x2, x2, x3, lsl #1 + sub x2, x2, x3 + movrel x9, qpel_filters_abs + add x9, x9, x12, lsl #3 + ldr d28, [x9] + dup v0.16b, v28.b[0] + dup v1.16b, v28.b[1] + dup v2.16b, v28.b[2] + dup v3.16b, v28.b[3] + dup v4.16b, v28.b[4] + dup v5.16b, v28.b[5] + dup v6.16b, v28.b[6] + dup v7.16b, v28.b[7] + + mov w10, #-6 + sub w10, w10, w5 + dup v30.8h, w6 // wx + dup v31.4s, w10 // shift + dup v29.4s, w7 // ox +.endm + +.macro QPEL_FILTER_B dst, src0, src1, src2, src3, src4, src5, src6, src7 + umull \dst\().8h, \src1\().8b, v1.8b + umlsl \dst\().8h, \src0\().8b, v0.8b + umlsl \dst\().8h, \src2\().8b, v2.8b + umlal \dst\().8h, \src3\().8b, v3.8b + umlal \dst\().8h, \src4\().8b, v4.8b + umlsl \dst\().8h, \src5\().8b, v5.8b + umlal \dst\().8h, \src6\().8b, v6.8b + umlsl \dst\().8h, \src7\().8b, v7.8b +.endm + +.macro QPEL_FILTER_B2 dst, src0, src1, src2, src3, src4, src5, src6, src7 + umull2 \dst\().8h, \src1\().16b, v1.16b + umlsl2 \dst\().8h, \src0\().16b, v0.16b + umlsl2 \dst\().8h, \src2\().16b, v2.16b + umlal2 \dst\().8h, \src3\().16b, v3.16b + umlal2 \dst\().8h, \src4\().16b, v4.16b + umlsl2 \dst\().8h, \src5\().16b, v5.16b + umlal2 \dst\().8h, \src6\().16b, v6.16b + umlsl2 \dst\().8h, \src7\().16b, v7.16b +.endm + +.macro QPEL_UNI_W_V_4 + smull v24.4s, v24.4h, v30.4h + sqrshl v24.4s, v24.4s, v31.4s + sqadd v24.4s, v24.4s, v29.4s + sqxtn v24.4h, v24.4s + sqxtun v24.8b, v24.8h + st1 {v24.s}[0], [x0], x1 +.endm + +function ff_hevc_put_hevc_qpel_uni_w_v4_8_neon, export=1 + QPEL_UNI_W_V_HEADER + ldr s16, [x2] + ldr s17, [x2, x3] + add x2, x2, x3, lsl #1 + ldr s18, [x2] + ldr s19, [x2, x3] + add x2, x2, x3, lsl #1 + ldr s20, [x2] + ldr s21, [x2, x3] + add x2, x2, x3, lsl #1 + ldr s22, [x2] + +1: ldr s23, [x2, x3] + add x2, x2, x3, lsl #1 + QPEL_FILTER_B v24, v16, v17, v18, v19, v20, v21, v22, v23 + QPEL_UNI_W_V_4 + subs w4, w4, #1 + b.eq 2f + + ldr s16, [x2] + QPEL_FILTER_B v24, v17, v18, v19, v20, v21, v22, v23, v16 + QPEL_UNI_W_V_4 + subs w4, w4, #1 + b.eq 2f + + ldr s17, [x2, x3] + add x2, x2, x3, lsl #1 + QPEL_FILTER_B v24, v18, v19, v20, v21, v22, v23, v16, v17 + QPEL_UNI_W_V_4 + subs w4, w4, #1 + b.eq 2f + + ldr s18, [x2] + QPEL_FILTER_B v24, v19, v20, v21, v22, v23, v16, v17, v18 + QPEL_UNI_W_V_4 + subs w4, w4, #1 + b.eq 2f + + ldr s19, [x2, x3] + add x2, x2, x3, lsl #1 + QPEL_FILTER_B v24, v20, v21, v22, v23, v16, v17, v18, v19 + QPEL_UNI_W_V_4 + subs w4, w4, #1 + b.eq 2f + + ldr s20, [x2] + QPEL_FILTER_B v24, v21, v22, v23, v16, v17, v18, v19, v20 + QPEL_UNI_W_V_4 + subs w4, w4, #1 + b.eq 2f + + ldr s21, [x2, x3] + add x2, x2, x3, lsl #1 + QPEL_FILTER_B v24, v22, v23, v16, v17, v18, v19, v20, v21 + QPEL_UNI_W_V_4 + subs w4, w4, #1 + b.eq 2f + + ldr s22, [x2] + QPEL_FILTER_B v24, v23, v16, v17, v18, v19, v20, v21, v22 + QPEL_UNI_W_V_4 + subs w4, w4, #1 + b.ne 1b +2: + ret +endfunc + +.macro QPEL_UNI_W_V_8 + smull v24.4s, v26.4h, v30.4h + smull2 v25.4s, v26.8h, v30.8h + sqrshl v24.4s, v24.4s, v31.4s + sqrshl v25.4s, v25.4s, v31.4s + sqadd v24.4s, v24.4s, v29.4s + sqadd v25.4s, v25.4s, v29.4s + sqxtn v24.4h, v24.4s + sqxtn2 v24.8h, v25.4s + sqxtun v24.8b, v24.8h + st1 {v24.d}[0], [x0], x1 +.endm + +function ff_hevc_put_hevc_qpel_uni_w_v8_8_neon, export=1 + QPEL_UNI_W_V_HEADER + ldr d16, [x2] + ldr d17, [x2, x3] + add x2, x2, x3, lsl #1 + ldr d18, [x2] + ldr d19, [x2, x3] + add x2, x2, x3, lsl #1 + ldr d20, [x2] + ldr d21, [x2, x3] + add x2, x2, x3, lsl #1 + ldr d22, [x2] + +1: ldr d23, [x2, x3] + add x2, x2, x3, lsl #1 + QPEL_FILTER_B v26, v16, v17, v18, v19, v20, v21, v22, v23 + QPEL_UNI_W_V_8 + subs w4, w4, #1 + b.eq 2f + + ldr d16, [x2] + QPEL_FILTER_B v26, v17, v18, v19, v20, v21, v22, v23, v16 + QPEL_UNI_W_V_8 + subs w4, w4, #1 + b.eq 2f + + ldr d17, [x2, x3] + add x2, x2, x3, lsl #1 + QPEL_FILTER_B v26, v18, v19, v20, v21, v22, v23, v16, v17 + QPEL_UNI_W_V_8 + subs w4, w4, #1 + b.eq 2f + + ldr d18, [x2] + QPEL_FILTER_B v26, v19, v20, v21, v22, v23, v16, v17, v18 + QPEL_UNI_W_V_8 + subs w4, w4, #1 + b.eq 2f + + ldr d19, [x2, x3] + add x2, x2, x3, lsl #1 + QPEL_FILTER_B v26, v20, v21, v22, v23, v16, v17, v18, v19 + QPEL_UNI_W_V_8 + subs w4, w4, #1 + b.eq 2f + + ldr d20, [x2] + QPEL_FILTER_B v26, v21, v22, v23, v16, v17, v18, v19, v20 + QPEL_UNI_W_V_8 + subs w4, w4, #1 + b.eq 2f + + ldr d21, [x2, x3] + add x2, x2, x3, lsl #1 + QPEL_FILTER_B v26, v22, v23, v16, v17, v18, v19, v20, v21 + QPEL_UNI_W_V_8 + subs w4, w4, #1 + b.eq 2f + + ldr d22, [x2] + QPEL_FILTER_B v26, v23, v16, v17, v18, v19, v20, v21, v22 + QPEL_UNI_W_V_8 + subs w4, w4, #1 + b.ne 1b +2: + ret +endfunc + +.macro QPEL_UNI_W_V_16 + smull v24.4s, v26.4h, v30.4h + smull2 v25.4s, v26.8h, v30.8h + smull v26.4s, v27.4h, v30.4h + smull2 v27.4s, v27.8h, v30.8h + sqrshl v24.4s, v24.4s, v31.4s + sqrshl v25.4s, v25.4s, v31.4s + sqrshl v26.4s, v26.4s, v31.4s + sqrshl v27.4s, v27.4s, v31.4s + sqadd v24.4s, v24.4s, v29.4s + sqadd v25.4s, v25.4s, v29.4s + sqadd v26.4s, v26.4s, v29.4s + sqadd v27.4s, v27.4s, v29.4s + sqxtn v24.4h, v24.4s + sqxtn2 v24.8h, v25.4s + sqxtn v26.4h, v26.4s + sqxtn2 v26.8h, v27.4s + sqxtun v24.8b, v24.8h + sqxtun2 v24.16b, v26.8h + st1 {v24.16b}, [x0], x1 +.endm + +function ff_hevc_put_hevc_qpel_uni_w_v16_8_neon, export=1 + QPEL_UNI_W_V_HEADER + ldr q16, [x2] + ldr q17, [x2, x3] + add x2, x2, x3, lsl #1 + ldr q18, [x2] + ldr q19, [x2, x3] + add x2, x2, x3, lsl #1 + ldr q20, [x2] + ldr q21, [x2, x3] + add x2, x2, x3, lsl #1 + ldr q22, [x2] + +1: ldr q23, [x2, x3] + add x2, x2, x3, lsl #1 + QPEL_FILTER_B v26, v16, v17, v18, v19, v20, v21, v22, v23 + QPEL_FILTER_B2 v27, v16, v17, v18, v19, v20, v21, v22, v23 + QPEL_UNI_W_V_16 + subs w4, w4, #1 + b.eq 2f + + ldr q16, [x2] + QPEL_FILTER_B v26, v17, v18, v19, v20, v21, v22, v23, v16 + QPEL_FILTER_B2 v27, v17, v18, v19, v20, v21, v22, v23, v16 + QPEL_UNI_W_V_16 + subs w4, w4, #1 + b.eq 2f + + ldr q17, [x2, x3] + add x2, x2, x3, lsl #1 + QPEL_FILTER_B v26, v18, v19, v20, v21, v22, v23, v16, v17 + QPEL_FILTER_B2 v27, v18, v19, v20, v21, v22, v23, v16, v17 + QPEL_UNI_W_V_16 + subs w4, w4, #1 + b.eq 2f + + ldr q18, [x2] + QPEL_FILTER_B v26, v19, v20, v21, v22, v23, v16, v17, v18 + QPEL_FILTER_B2 v27, v19, v20, v21, v22, v23, v16, v17, v18 + QPEL_UNI_W_V_16 + subs w4, w4, #1 + b.eq 2f + + ldr q19, [x2, x3] + add x2, x2, x3, lsl #1 + QPEL_FILTER_B v26, v20, v21, v22, v23, v16, v17, v18, v19 + QPEL_FILTER_B2 v27, v20, v21, v22, v23, v16, v17, v18, v19 + QPEL_UNI_W_V_16 + subs w4, w4, #1 + b.eq 2f + + ldr q20, [x2] + QPEL_FILTER_B v26, v21, v22, v23, v16, v17, v18, v19, v20 + QPEL_FILTER_B2 v27, v21, v22, v23, v16, v17, v18, v19, v20 + QPEL_UNI_W_V_16 + subs w4, w4, #1 + b.eq 2f + + ldr q21, [x2, x3] + add x2, x2, x3, lsl #1 + QPEL_FILTER_B v26, v22, v23, v16, v17, v18, v19, v20, v21 + QPEL_FILTER_B2 v27, v22, v23, v16, v17, v18, v19, v20, v21 + QPEL_UNI_W_V_16 + subs w4, w4, #1 + b.eq 2f + + ldr q22, [x2] + QPEL_FILTER_B v26, v23, v16, v17, v18, v19, v20, v21, v22 + QPEL_FILTER_B2 v27, v23, v16, v17, v18, v19, v20, v21, v22 + QPEL_UNI_W_V_16 + subs w4, w4, #1 + b.ne 1b +2: + ret +endfunc + +function ff_hevc_put_hevc_qpel_uni_w_v64_8_neon, export=1 + QPEL_UNI_W_V_HEADER + ldur w13, [sp, #16] + mov x14, x0 + mov x15, x2 + mov w11, w4 + +3: + ldr q16, [x2] + ldr q17, [x2, x3] + add x2, x2, x3, lsl #1 + ldr q18, [x2] + ldr q19, [x2, x3] + add x2, x2, x3, lsl #1 + ldr q20, [x2] + ldr q21, [x2, x3] + add x2, x2, x3, lsl #1 + ldr q22, [x2] + + +1: ldr q23, [x2, x3] + add x2, x2, x3, lsl #1 + QPEL_FILTER_B v26, v16, v17, v18, v19, v20, v21, v22, v23 + QPEL_FILTER_B2 v27, v16, v17, v18, v19, v20, v21, v22, v23 + QPEL_UNI_W_V_16 + subs w4, w4, #1 + b.eq 2f + + ldr q16, [x2] + QPEL_FILTER_B v26, v17, v18, v19, v20, v21, v22, v23, v16 + QPEL_FILTER_B2 v27, v17, v18, v19, v20, v21, v22, v23, v16 + QPEL_UNI_W_V_16 + subs w4, w4, #1 + b.eq 2f + + ldr q17, [x2, x3] + add x2, x2, x3, lsl #1 + QPEL_FILTER_B v26, v18, v19, v20, v21, v22, v23, v16, v17 + QPEL_FILTER_B2 v27, v18, v19, v20, v21, v22, v23, v16, v17 + QPEL_UNI_W_V_16 + subs w4, w4, #1 + b.eq 2f + + ldr q18, [x2] + QPEL_FILTER_B v26, v19, v20, v21, v22, v23, v16, v17, v18 + QPEL_FILTER_B2 v27, v19, v20, v21, v22, v23, v16, v17, v18 + QPEL_UNI_W_V_16 + subs w4, w4, #1 + b.eq 2f + + ldr q19, [x2, x3] + add x2, x2, x3, lsl #1 + QPEL_FILTER_B v26, v20, v21, v22, v23, v16, v17, v18, v19 + QPEL_FILTER_B2 v27, v20, v21, v22, v23, v16, v17, v18, v19 + QPEL_UNI_W_V_16 + subs w4, w4, #1 + b.eq 2f + + ldr q20, [x2] + QPEL_FILTER_B v26, v21, v22, v23, v16, v17, v18, v19, v20 + QPEL_FILTER_B2 v27, v21, v22, v23, v16, v17, v18, v19, v20 + QPEL_UNI_W_V_16 + subs w4, w4, #1 + b.eq 2f + + ldr q21, [x2, x3] + add x2, x2, x3, lsl #1 + QPEL_FILTER_B v26, v22, v23, v16, v17, v18, v19, v20, v21 + QPEL_FILTER_B2 v27, v22, v23, v16, v17, v18, v19, v20, v21 + QPEL_UNI_W_V_16 + subs w4, w4, #1 + b.eq 2f + + ldr q22, [x2] + QPEL_FILTER_B v26, v23, v16, v17, v18, v19, v20, v21, v22 + QPEL_FILTER_B2 v27, v23, v16, v17, v18, v19, v20, v21, v22 + QPEL_UNI_W_V_16 + subs w4, w4, #1 + b.ne 1b +2: + subs w13, w13, #16 + add x14, x14, #16 + add x15, x15, #16 + mov x0, x14 + mov x2, x15 + mov w4, w11 + b.hi 3b + ret +endfunc From 15972cce8c0a813b3df6b9c31488bceb6fa1a7d4 Mon Sep 17 00:00:00 2001 From: Logan Lyu Date: Fri, 5 May 2023 22:06:22 +0800 Subject: [PATCH 1423/2172] lavc/aarch64: new optimization for 8-bit hevc_qpel_uni_w_h MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Martin Storsjö --- libavcodec/aarch64/hevcdsp_init_aarch64.c | 15 +- libavcodec/aarch64/hevcdsp_qpel_neon.S | 434 ++++++++++++++++++++++ 2 files changed, 448 insertions(+), 1 deletion(-) diff --git a/libavcodec/aarch64/hevcdsp_init_aarch64.c b/libavcodec/aarch64/hevcdsp_init_aarch64.c index 6b5341dd459..a7e62c7d155 100644 --- a/libavcodec/aarch64/hevcdsp_init_aarch64.c +++ b/libavcodec/aarch64/hevcdsp_init_aarch64.c @@ -145,6 +145,7 @@ void ff_hevc_put_hevc_qpel_bi_h16_8_neon(uint8_t *_dst, ptrdiff_t _dststride, co void ff_hevc_put_hevc_##fn##16_8_neon##ext args; \ void ff_hevc_put_hevc_##fn##64_8_neon##ext args; \ + NEON8_FNPROTO(pel_uni_w_pixels, (uint8_t *_dst, ptrdiff_t _dststride, const uint8_t *_src, ptrdiff_t _srcstride, int height, int denom, int wx, int ox, @@ -155,6 +156,12 @@ NEON8_FNPROTO_PARTIAL_4(qpel_uni_w_v, (uint8_t *_dst, ptrdiff_t _dststride, int height, int denom, int wx, int ox, intptr_t mx, intptr_t my, int width),); +NEON8_FNPROTO(qpel_uni_w_h, (uint8_t *_dst, ptrdiff_t _dststride, + const uint8_t *_src, ptrdiff_t _srcstride, + int height, int denom, int wx, int ox, + intptr_t mx, intptr_t my, int width), _i8mm); + + #define NEON8_FNASSIGN(member, v, h, fn, ext) \ member[1][v][h] = ff_hevc_put_hevc_##fn##4_8_neon##ext; \ member[2][v][h] = ff_hevc_put_hevc_##fn##6_8_neon##ext; \ @@ -174,9 +181,11 @@ NEON8_FNPROTO_PARTIAL_4(qpel_uni_w_v, (uint8_t *_dst, ptrdiff_t _dststride, member[8][v][h] = ff_hevc_put_hevc_##fn##64_8_neon##ext; \ member[9][v][h] = ff_hevc_put_hevc_##fn##64_8_neon##ext; + av_cold void ff_hevc_dsp_init_aarch64(HEVCDSPContext *c, const int bit_depth) { - if (!have_neon(av_get_cpu_flags())) return; + int cpu_flags = av_get_cpu_flags(); + if (!have_neon(cpu_flags)) return; if (bit_depth == 8) { c->hevc_h_loop_filter_chroma = ff_hevc_h_loop_filter_chroma_8_neon; @@ -236,6 +245,10 @@ av_cold void ff_hevc_dsp_init_aarch64(HEVCDSPContext *c, const int bit_depth) NEON8_FNASSIGN(c->put_hevc_qpel_uni_w, 0, 0, pel_uni_w_pixels,); NEON8_FNASSIGN_PARTIAL_4(c->put_hevc_qpel_uni_w, 1, 0, qpel_uni_w_v,); + if (have_i8mm(cpu_flags)) { + NEON8_FNASSIGN(c->put_hevc_qpel_uni_w, 0, 1, qpel_uni_w_h, _i8mm); + } + } if (bit_depth == 10) { c->hevc_h_loop_filter_chroma = ff_hevc_h_loop_filter_chroma_10_neon; diff --git a/libavcodec/aarch64/hevcdsp_qpel_neon.S b/libavcodec/aarch64/hevcdsp_qpel_neon.S index 51df52e1eae..8e8b88c9ea3 100644 --- a/libavcodec/aarch64/hevcdsp_qpel_neon.S +++ b/libavcodec/aarch64/hevcdsp_qpel_neon.S @@ -1192,3 +1192,437 @@ function ff_hevc_put_hevc_qpel_uni_w_v64_8_neon, export=1 b.hi 3b ret endfunc + +#if HAVE_I8MM +.macro QPEL_UNI_W_H_HEADER + ldr x12, [sp] + sub x2, x2, #3 + movrel x9, qpel_filters + add x9, x9, x12, lsl #3 + ldr x11, [x9] + dup v28.2d, x11 + mov w10, #-6 + sub w10, w10, w5 + dup v30.4s, w6 // wx + dup v31.4s, w10 // shift + dup v29.4s, w7 // ox +.endm + +function ff_hevc_put_hevc_qpel_uni_w_h4_8_neon_i8mm, export=1 + QPEL_UNI_W_H_HEADER +1: + ld1 {v0.16b}, [x2], x3 + ext v1.16b, v0.16b, v0.16b, #1 + ext v2.16b, v0.16b, v0.16b, #2 + ext v3.16b, v0.16b, v0.16b, #3 + zip1 v0.2d, v0.2d, v1.2d + zip1 v2.2d, v2.2d, v3.2d + movi v16.2d, #0 + movi v17.2d, #0 + usdot v16.4s, v0.16b, v28.16b + usdot v17.4s, v2.16b, v28.16b + addp v16.4s, v16.4s, v17.4s + mul v16.4s, v16.4s, v30.4s + sqrshl v16.4s, v16.4s, v31.4s + sqadd v16.4s, v16.4s, v29.4s + sqxtn v16.4h, v16.4s + sqxtun v16.8b, v16.8h + str s16, [x0] + add x0, x0, x1 + subs w4, w4, #1 + b.hi 1b + ret +endfunc + +function ff_hevc_put_hevc_qpel_uni_w_h6_8_neon_i8mm, export=1 + QPEL_UNI_W_H_HEADER + sub x1, x1, #4 +1: + ld1 {v0.16b}, [x2], x3 + ext v1.16b, v0.16b, v0.16b, #1 + ext v2.16b, v0.16b, v0.16b, #2 + ext v3.16b, v0.16b, v0.16b, #3 + ext v4.16b, v0.16b, v0.16b, #4 + ext v5.16b, v0.16b, v0.16b, #5 + zip1 v0.2d, v0.2d, v1.2d + zip1 v2.2d, v2.2d, v3.2d + zip1 v4.2d, v4.2d, v5.2d + movi v16.2d, #0 + movi v17.2d, #0 + movi v18.2d, #0 + usdot v16.4s, v0.16b, v28.16b + usdot v17.4s, v2.16b, v28.16b + usdot v18.4s, v4.16b, v28.16b + addp v16.4s, v16.4s, v17.4s + addp v18.4s, v18.4s, v18.4s + mul v16.4s, v16.4s, v30.4s + mul v18.2s, v18.2s, v30.2s + sqrshl v16.4s, v16.4s, v31.4s + sqrshl v18.2s, v18.2s, v31.2s + sqadd v16.4s, v16.4s, v29.4s + sqadd v18.2s, v18.2s, v29.2s + sqxtn v16.4h, v16.4s + sqxtn2 v16.8h, v18.4s + sqxtun v16.8b, v16.8h + str s16, [x0], #4 + st1 {v16.h}[2], [x0], x1 + subs w4, w4, #1 + b.hi 1b + ret +endfunc + + +.macro QPEL_UNI_W_H_CALC s0, s1, s2, s3, d0, d1, d2, d3 + movi \d0\().2d, #0 + movi \d1\().2d, #0 + movi \d2\().2d, #0 + movi \d3\().2d, #0 + usdot \d0\().4s, \s0\().16b, v28.16b + usdot \d1\().4s, \s1\().16b, v28.16b + usdot \d2\().4s, \s2\().16b, v28.16b + usdot \d3\().4s, \s3\().16b, v28.16b + addp \d0\().4s, \d0\().4s, \d1\().4s + addp \d2\().4s, \d2\().4s, \d3\().4s + mul \d0\().4s, \d0\().4s, v30.4s + mul \d2\().4s, \d2\().4s, v30.4s + sqrshl \d0\().4s, \d0\().4s, v31.4s + sqrshl \d2\().4s, \d2\().4s, v31.4s + sqadd \d0\().4s, \d0\().4s, v29.4s + sqadd \d2\().4s, \d2\().4s, v29.4s +.endm + +.macro QPEL_UNI_W_H_CALC_HALF s0, s1, d0, d1 + movi \d0\().2d, #0 + movi \d1\().2d, #0 + usdot \d0\().4s, \s0\().16b, v28.16b + usdot \d1\().4s, \s1\().16b, v28.16b + addp \d0\().4s, \d0\().4s, \d1\().4s + mul \d0\().4s, \d0\().4s, v30.4s + sqrshl \d0\().4s, \d0\().4s, v31.4s + sqadd \d0\().4s, \d0\().4s, v29.4s +.endm + + +function ff_hevc_put_hevc_qpel_uni_w_h8_8_neon_i8mm, export=1 + QPEL_UNI_W_H_HEADER +1: + ld1 {v16.16b, v17.16b}, [x2], x3 + ext v1.16b, v16.16b, v17.16b, #1 + ext v2.16b, v16.16b, v17.16b, #2 + ext v3.16b, v16.16b, v17.16b, #3 + ext v4.16b, v16.16b, v17.16b, #4 + ext v5.16b, v16.16b, v17.16b, #5 + ext v6.16b, v16.16b, v17.16b, #6 + ext v7.16b, v16.16b, v17.16b, #7 + zip1 v0.2d, v16.2d, v1.2d + zip1 v2.2d, v2.2d, v3.2d + zip1 v4.2d, v4.2d, v5.2d + zip1 v6.2d, v6.2d, v7.2d + QPEL_UNI_W_H_CALC v0, v2, v4, v6, v18, v19, v20, v21 + sqxtn v18.4h, v18.4s + sqxtn2 v18.8h, v20.4s + sqxtun v18.8b, v18.8h + str d18, [x0] + add x0, x0, x1 + subs w4, w4, #1 + b.hi 1b + ret +endfunc + +function ff_hevc_put_hevc_qpel_uni_w_h12_8_neon_i8mm, export=1 + QPEL_UNI_W_H_HEADER + add x13, x0, #8 +1: + ld1 {v16.16b, v17.16b}, [x2], x3 + ext v1.16b, v16.16b, v17.16b, #1 + ext v2.16b, v16.16b, v17.16b, #2 + ext v3.16b, v16.16b, v17.16b, #3 + ext v4.16b, v16.16b, v17.16b, #4 + ext v5.16b, v16.16b, v17.16b, #5 + ext v6.16b, v16.16b, v17.16b, #6 + ext v7.16b, v16.16b, v17.16b, #7 + zip1 v18.2d, v16.2d, v1.2d + zip1 v19.2d, v2.2d, v3.2d + zip1 v20.2d, v4.2d, v5.2d + zip1 v21.2d, v6.2d, v7.2d + zip2 v22.2d, v16.2d, v1.2d + zip2 v23.2d, v2.2d, v3.2d + QPEL_UNI_W_H_CALC v18, v19, v20, v21, v0, v2, v4, v6 + QPEL_UNI_W_H_CALC_HALF v22, v23, v24, v25 + sqxtn v0.4h, v0.4s + sqxtn2 v0.8h, v4.4s + sqxtn v1.4h, v24.4s + sqxtun v0.8b, v0.8h + sqxtun v1.8b, v1.8h + + str d0, [x0] + str s1, [x13] + add x0, x0, x1 + add x13, x13, x1 + subs w4, w4, #1 + b.hi 1b + ret +endfunc + +function ff_hevc_put_hevc_qpel_uni_w_h16_8_neon_i8mm, export=1 + QPEL_UNI_W_H_HEADER +1: + ld1 {v16.16b, v17.16b}, [x2], x3 + ext v1.16b, v16.16b, v17.16b, #1 + ext v2.16b, v16.16b, v17.16b, #2 + ext v3.16b, v16.16b, v17.16b, #3 + ext v4.16b, v16.16b, v17.16b, #4 + ext v5.16b, v16.16b, v17.16b, #5 + ext v6.16b, v16.16b, v17.16b, #6 + ext v7.16b, v16.16b, v17.16b, #7 + QPEL_UNI_W_H_CALC v16, v2, v1, v3, v18, v19, v20, v21 // v18: 0, 8, 2, 10 v20: 1, 9, 3, 11 + QPEL_UNI_W_H_CALC v4, v6, v5, v7, v22, v23, v24, v25 // v22: 4, 12, 6, 14 v24: 5, 13, 7, 15 + sqxtn v0.4h, v18.4s + sqxtn2 v0.8h, v22.4s + sqxtn v1.4h, v20.4s + sqxtn2 v1.8h, v24.4s + trn1 v2.8h, v0.8h, v1.8h + trn2 v3.8h, v0.8h, v1.8h + sqxtun v0.8b, v2.8h + sqxtun2 v0.16b, v3.8h + st1 {v0.16b}, [x0], x1 + subs w4, w4, #1 + b.hi 1b + ret +endfunc + +function ff_hevc_put_hevc_qpel_uni_w_h24_8_neon_i8mm, export=1 + QPEL_UNI_W_H_HEADER + sub x1, x1, #16 +1: + ld1 {v16.16b, v17.16b}, [x2], x3 + ext v1.16b, v16.16b, v17.16b, #1 + ext v2.16b, v16.16b, v17.16b, #2 + ext v3.16b, v16.16b, v17.16b, #3 + ext v4.16b, v16.16b, v17.16b, #4 + ext v5.16b, v16.16b, v17.16b, #5 + ext v6.16b, v16.16b, v17.16b, #6 + ext v7.16b, v16.16b, v17.16b, #7 + QPEL_UNI_W_H_CALC v16, v2, v1, v3, v18, v19, v20, v21 + QPEL_UNI_W_H_CALC v4, v6, v5, v7, v22, v23, v24, v25 + sqxtn v18.4h, v18.4s + sqxtn2 v18.8h, v22.4s + sqxtn v19.4h, v20.4s + sqxtn2 v19.8h, v24.4s + trn1 v20.8h, v18.8h, v19.8h + trn2 v21.8h, v18.8h, v19.8h + sqxtun v26.8b, v20.8h + sqxtun2 v26.16b, v21.8h // 0-15 + ext v1.16b, v17.16b, v17.16b, #1 + ext v2.16b, v17.16b, v17.16b, #2 + ext v3.16b, v17.16b, v17.16b, #3 + ext v4.16b, v17.16b, v17.16b, #4 + ext v5.16b, v17.16b, v17.16b, #5 + ext v6.16b, v17.16b, v17.16b, #6 + ext v7.16b, v17.16b, v17.16b, #7 + zip1 v0.2d, v17.2d, v1.2d + zip1 v2.2d, v2.2d, v3.2d + zip1 v4.2d, v4.2d, v5.2d + zip1 v6.2d, v6.2d, v7.2d + QPEL_UNI_W_H_CALC v0, v2, v4, v6, v18, v19, v20, v21 + sqxtn v18.4h, v18.4s + sqxtn2 v18.8h, v20.4s + sqxtun v27.8b, v18.8h + + st1 {v26.16b}, [x0], #16 + st1 {v27.8b}, [x0], x1 + subs w4, w4, #1 + b.hi 1b + ret +endfunc + + +function ff_hevc_put_hevc_qpel_uni_w_h32_8_neon_i8mm, export=1 + QPEL_UNI_W_H_HEADER +1: + ld1 {v16.16b, v17.16b, v18.16b}, [x2], x3 + ext v1.16b, v16.16b, v17.16b, #1 + ext v2.16b, v16.16b, v17.16b, #2 + ext v3.16b, v16.16b, v17.16b, #3 + ext v4.16b, v16.16b, v17.16b, #4 + ext v5.16b, v16.16b, v17.16b, #5 + ext v6.16b, v16.16b, v17.16b, #6 + ext v7.16b, v16.16b, v17.16b, #7 + QPEL_UNI_W_H_CALC v16, v2, v1, v3, v0, v19, v20, v21 + QPEL_UNI_W_H_CALC v4, v6, v5, v7, v22, v23, v24, v25 + sqxtn v0.4h, v0.4s + sqxtn2 v0.8h, v22.4s + sqxtn v19.4h, v20.4s + sqxtn2 v19.8h, v24.4s + trn1 v20.8h, v0.8h, v19.8h + trn2 v21.8h, v0.8h, v19.8h + sqxtun v26.8b, v20.8h + sqxtun2 v26.16b, v21.8h // 0-15 + ext v1.16b, v17.16b, v18.16b, #1 + ext v2.16b, v17.16b, v18.16b, #2 + ext v3.16b, v17.16b, v18.16b, #3 + ext v4.16b, v17.16b, v18.16b, #4 + ext v5.16b, v17.16b, v18.16b, #5 + ext v6.16b, v17.16b, v18.16b, #6 + ext v7.16b, v17.16b, v18.16b, #7 + QPEL_UNI_W_H_CALC v17, v2, v1, v3, v0, v19, v20, v21 + QPEL_UNI_W_H_CALC v4, v6, v5, v7, v22, v23, v24, v25 + sqxtn v0.4h, v0.4s + sqxtn2 v0.8h, v22.4s + sqxtn v19.4h, v20.4s + sqxtn2 v19.8h, v24.4s + trn1 v20.8h, v0.8h, v19.8h + trn2 v21.8h, v0.8h, v19.8h + sqxtun v27.8b, v20.8h + sqxtun2 v27.16b, v21.8h // 16-31 + st1 {v26.16b, v27.16b}, [x0], x1 + subs w4, w4, #1 + b.hi 1b + ret +endfunc + +function ff_hevc_put_hevc_qpel_uni_w_h48_8_neon_i8mm, export=1 + QPEL_UNI_W_H_HEADER +1: + ld1 {v16.16b, v17.16b, v18.16b, v19.16b}, [x2], x3 + ext v1.16b, v16.16b, v17.16b, #1 + ext v2.16b, v16.16b, v17.16b, #2 + ext v3.16b, v16.16b, v17.16b, #3 + ext v4.16b, v16.16b, v17.16b, #4 + ext v5.16b, v16.16b, v17.16b, #5 + ext v6.16b, v16.16b, v17.16b, #6 + ext v7.16b, v16.16b, v17.16b, #7 + QPEL_UNI_W_H_CALC v16, v2, v1, v3, v20, v24, v21, v0 + QPEL_UNI_W_H_CALC v4, v6, v5, v7, v22, v24, v23, v0 + sqxtn v20.4h, v20.4s + sqxtn2 v20.8h, v22.4s + sqxtn v21.4h, v21.4s + sqxtn2 v21.8h, v23.4s + trn1 v22.8h, v20.8h, v21.8h + trn2 v23.8h, v20.8h, v21.8h + sqxtun v25.8b, v22.8h + sqxtun2 v25.16b, v23.8h // 0-15 + ext v1.16b, v17.16b, v18.16b, #1 + ext v2.16b, v17.16b, v18.16b, #2 + ext v3.16b, v17.16b, v18.16b, #3 + ext v4.16b, v17.16b, v18.16b, #4 + ext v5.16b, v17.16b, v18.16b, #5 + ext v6.16b, v17.16b, v18.16b, #6 + ext v7.16b, v17.16b, v18.16b, #7 + QPEL_UNI_W_H_CALC v17, v2, v1, v3, v20, v24, v21, v0 + QPEL_UNI_W_H_CALC v4, v6, v5, v7, v22, v24, v23, v0 + sqxtn v20.4h, v20.4s + sqxtn2 v20.8h, v22.4s + sqxtn v21.4h, v21.4s + sqxtn2 v21.8h, v23.4s + trn1 v22.8h, v20.8h, v21.8h + trn2 v23.8h, v20.8h, v21.8h + sqxtun v26.8b, v22.8h + sqxtun2 v26.16b, v23.8h // 16-31 + ext v1.16b, v18.16b, v19.16b, #1 + ext v2.16b, v18.16b, v19.16b, #2 + ext v3.16b, v18.16b, v19.16b, #3 + ext v4.16b, v18.16b, v19.16b, #4 + ext v5.16b, v18.16b, v19.16b, #5 + ext v6.16b, v18.16b, v19.16b, #6 + ext v7.16b, v18.16b, v19.16b, #7 + QPEL_UNI_W_H_CALC v18, v2, v1, v3, v20, v24, v21, v0 + QPEL_UNI_W_H_CALC v4, v6, v5, v7, v22, v24, v23, v0 + sqxtn v20.4h, v20.4s + sqxtn2 v20.8h, v22.4s + sqxtn v21.4h, v21.4s + sqxtn2 v21.8h, v23.4s + trn1 v22.8h, v20.8h, v21.8h + trn2 v23.8h, v20.8h, v21.8h + sqxtun v27.8b, v22.8h + sqxtun2 v27.16b, v23.8h // 32-47 + st1 {v25.16b, v26.16b, v27.16b}, [x0], x1 + subs w4, w4, #1 + b.hi 1b + ret +endfunc + + + +function ff_hevc_put_hevc_qpel_uni_w_h64_8_neon_i8mm, export=1 + QPEL_UNI_W_H_HEADER + sub x3, x3, #64 +1: + ld1 {v16.16b, v17.16b, v18.16b, v19.16b}, [x2], #64 + ext v1.16b, v16.16b, v17.16b, #1 + ext v2.16b, v16.16b, v17.16b, #2 + ext v3.16b, v16.16b, v17.16b, #3 + ext v4.16b, v16.16b, v17.16b, #4 + ext v5.16b, v16.16b, v17.16b, #5 + ext v6.16b, v16.16b, v17.16b, #6 + ext v7.16b, v16.16b, v17.16b, #7 + QPEL_UNI_W_H_CALC v16, v2, v1, v3, v20, v24, v21, v0 + QPEL_UNI_W_H_CALC v4, v6, v5, v7, v22, v24, v23, v0 + sqxtn v20.4h, v20.4s + sqxtn2 v20.8h, v22.4s + sqxtn v21.4h, v21.4s + sqxtn2 v21.8h, v23.4s + trn1 v22.8h, v20.8h, v21.8h + trn2 v23.8h, v20.8h, v21.8h + sqxtun v16.8b, v22.8h + sqxtun2 v16.16b, v23.8h // 0-15 + ext v1.16b, v17.16b, v18.16b, #1 + ext v2.16b, v17.16b, v18.16b, #2 + ext v3.16b, v17.16b, v18.16b, #3 + ext v4.16b, v17.16b, v18.16b, #4 + ext v5.16b, v17.16b, v18.16b, #5 + ext v6.16b, v17.16b, v18.16b, #6 + ext v7.16b, v17.16b, v18.16b, #7 + QPEL_UNI_W_H_CALC v17, v2, v1, v3, v20, v24, v21, v0 + QPEL_UNI_W_H_CALC v4, v6, v5, v7, v22, v24, v23, v0 + sqxtn v20.4h, v20.4s + sqxtn2 v20.8h, v22.4s + sqxtn v21.4h, v21.4s + sqxtn2 v21.8h, v23.4s + trn1 v22.8h, v20.8h, v21.8h + trn2 v23.8h, v20.8h, v21.8h + sqxtun v17.8b, v22.8h + sqxtun2 v17.16b, v23.8h // 16-31 + ext v1.16b, v18.16b, v19.16b, #1 + ext v2.16b, v18.16b, v19.16b, #2 + ext v3.16b, v18.16b, v19.16b, #3 + ext v4.16b, v18.16b, v19.16b, #4 + ext v5.16b, v18.16b, v19.16b, #5 + ext v6.16b, v18.16b, v19.16b, #6 + ext v7.16b, v18.16b, v19.16b, #7 + QPEL_UNI_W_H_CALC v18, v2, v1, v3, v20, v24, v21, v0 + QPEL_UNI_W_H_CALC v4, v6, v5, v7, v22, v24, v23, v0 + ld1 {v0.16b}, [x2], x3 + sqxtn v20.4h, v20.4s + sqxtn2 v20.8h, v22.4s + sqxtn v21.4h, v21.4s + sqxtn2 v21.8h, v23.4s + trn1 v22.8h, v20.8h, v21.8h + trn2 v23.8h, v20.8h, v21.8h + sqxtun v18.8b, v22.8h + sqxtun2 v18.16b, v23.8h // 32-47 + ext v1.16b, v19.16b, v0.16b, #1 + ext v2.16b, v19.16b, v0.16b, #2 + ext v3.16b, v19.16b, v0.16b, #3 + ext v4.16b, v19.16b, v0.16b, #4 + ext v5.16b, v19.16b, v0.16b, #5 + ext v6.16b, v19.16b, v0.16b, #6 + ext v7.16b, v19.16b, v0.16b, #7 + QPEL_UNI_W_H_CALC v19, v2, v1, v3, v20, v24, v21, v0 + QPEL_UNI_W_H_CALC v4, v6, v5, v7, v22, v24, v23, v0 + sqxtn v20.4h, v20.4s + sqxtn2 v20.8h, v22.4s + sqxtn v21.4h, v21.4s + sqxtn2 v21.8h, v23.4s + trn1 v22.8h, v20.8h, v21.8h + trn2 v23.8h, v20.8h, v21.8h + sqxtun v19.8b, v22.8h + sqxtun2 v19.16b, v23.8h // 48-63 + + st1 {v16.16b, v17.16b, v18.16b, v19.16b}, [x0], x1 + subs w4, w4, #1 + b.hi 1b + ret +endfunc + +#endif // HAVE_I8MM From e79686be96e281e981045e93902558fcc2ed844f Mon Sep 17 00:00:00 2001 From: Logan Lyu Date: Sun, 28 May 2023 09:56:51 +0800 Subject: [PATCH 1424/2172] lavc/aarch64: new optimization for 8-bit hevc_qpel_h hevc_qpel_uni_w_hv MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Martin Storsjö --- libavcodec/aarch64/hevcdsp_init_aarch64.c | 24 + libavcodec/aarch64/hevcdsp_qpel_neon.S | 1078 +++++++++++++++++++++ 2 files changed, 1102 insertions(+) diff --git a/libavcodec/aarch64/hevcdsp_init_aarch64.c b/libavcodec/aarch64/hevcdsp_init_aarch64.c index a7e62c7d155..483a9d52535 100644 --- a/libavcodec/aarch64/hevcdsp_init_aarch64.c +++ b/libavcodec/aarch64/hevcdsp_init_aarch64.c @@ -145,6 +145,13 @@ void ff_hevc_put_hevc_qpel_bi_h16_8_neon(uint8_t *_dst, ptrdiff_t _dststride, co void ff_hevc_put_hevc_##fn##16_8_neon##ext args; \ void ff_hevc_put_hevc_##fn##64_8_neon##ext args; \ +#define NEON8_FNPROTO_PARTIAL_5(fn, args, ext) \ + void ff_hevc_put_hevc_##fn##4_8_neon##ext args; \ + void ff_hevc_put_hevc_##fn##8_8_neon##ext args; \ + void ff_hevc_put_hevc_##fn##16_8_neon##ext args; \ + void ff_hevc_put_hevc_##fn##32_8_neon##ext args; \ + void ff_hevc_put_hevc_##fn##64_8_neon##ext args; \ + NEON8_FNPROTO(pel_uni_w_pixels, (uint8_t *_dst, ptrdiff_t _dststride, const uint8_t *_src, ptrdiff_t _srcstride, @@ -156,11 +163,20 @@ NEON8_FNPROTO_PARTIAL_4(qpel_uni_w_v, (uint8_t *_dst, ptrdiff_t _dststride, int height, int denom, int wx, int ox, intptr_t mx, intptr_t my, int width),); + +NEON8_FNPROTO(qpel_h, (int16_t *dst, + const uint8_t *_src, ptrdiff_t _srcstride, + int height, intptr_t mx, intptr_t my, int width), _i8mm); + NEON8_FNPROTO(qpel_uni_w_h, (uint8_t *_dst, ptrdiff_t _dststride, const uint8_t *_src, ptrdiff_t _srcstride, int height, int denom, int wx, int ox, intptr_t mx, intptr_t my, int width), _i8mm); +NEON8_FNPROTO_PARTIAL_5(qpel_uni_w_hv, (uint8_t *_dst, ptrdiff_t _dststride, + const uint8_t *_src, ptrdiff_t _srcstride, + int height, int denom, int wx, int ox, + intptr_t mx, intptr_t my, int width), _i8mm); #define NEON8_FNASSIGN(member, v, h, fn, ext) \ member[1][v][h] = ff_hevc_put_hevc_##fn##4_8_neon##ext; \ @@ -181,6 +197,12 @@ NEON8_FNPROTO(qpel_uni_w_h, (uint8_t *_dst, ptrdiff_t _dststride, member[8][v][h] = ff_hevc_put_hevc_##fn##64_8_neon##ext; \ member[9][v][h] = ff_hevc_put_hevc_##fn##64_8_neon##ext; +#define NEON8_FNASSIGN_PARTIAL_5(member, v, h, fn, ext) \ + member[1][v][h] = ff_hevc_put_hevc_##fn##4_8_neon##ext; \ + member[3][v][h] = ff_hevc_put_hevc_##fn##8_8_neon##ext; \ + member[5][v][h] = ff_hevc_put_hevc_##fn##16_8_neon##ext; \ + member[7][v][h] = ff_hevc_put_hevc_##fn##32_8_neon##ext; \ + member[9][v][h] = ff_hevc_put_hevc_##fn##64_8_neon##ext; av_cold void ff_hevc_dsp_init_aarch64(HEVCDSPContext *c, const int bit_depth) { @@ -247,6 +269,8 @@ av_cold void ff_hevc_dsp_init_aarch64(HEVCDSPContext *c, const int bit_depth) if (have_i8mm(cpu_flags)) { NEON8_FNASSIGN(c->put_hevc_qpel_uni_w, 0, 1, qpel_uni_w_h, _i8mm); + NEON8_FNASSIGN(c->put_hevc_qpel, 0, 1, qpel_h, _i8mm); + NEON8_FNASSIGN_PARTIAL_5(c->put_hevc_qpel_uni_w, 1, 1, qpel_uni_w_hv, _i8mm); } } diff --git a/libavcodec/aarch64/hevcdsp_qpel_neon.S b/libavcodec/aarch64/hevcdsp_qpel_neon.S index 8e8b88c9ea3..46c6d4c27ec 100644 --- a/libavcodec/aarch64/hevcdsp_qpel_neon.S +++ b/libavcodec/aarch64/hevcdsp_qpel_neon.S @@ -1625,4 +1625,1082 @@ function ff_hevc_put_hevc_qpel_uni_w_h64_8_neon_i8mm, export=1 ret endfunc +.macro QPEL_H_HEADER + movrel x9, qpel_filters + add x9, x9, x4, lsl #3 + ldr x11, [x9] + dup v31.2d, x11 + sub x1, x1, #3 +.endm + +function ff_hevc_put_hevc_qpel_h4_8_neon_i8mm, export=1 + QPEL_H_HEADER + mov x10, #MAX_PB_SIZE * 2 +1: + ld1 {v0.16b}, [x1], x2 + ext v1.16b, v0.16b, v0.16b, #1 + ext v2.16b, v0.16b, v0.16b, #2 + ext v3.16b, v0.16b, v0.16b, #3 + zip1 v0.2d, v0.2d, v1.2d + zip1 v2.2d, v2.2d, v3.2d + movi v16.2d, #0 + movi v17.2d, #0 + usdot v16.4s, v0.16b, v31.16b + usdot v17.4s, v2.16b, v31.16b + addp v16.4s, v16.4s, v17.4s + sqxtn v16.4h, v16.4s + str d16, [x0] + add x0, x0, x10 + subs w3, w3, #1 + b.ne 1b + ret +endfunc + +function ff_hevc_put_hevc_qpel_h6_8_neon_i8mm, export=1 + QPEL_H_HEADER + mov x10, #MAX_PB_SIZE * 2 + add x15, x0, #8 +1: + ld1 {v0.16b}, [x1], x2 + ext v1.16b, v0.16b, v0.16b, #1 + ext v2.16b, v0.16b, v0.16b, #2 + ext v3.16b, v0.16b, v0.16b, #3 + ext v4.16b, v0.16b, v0.16b, #4 + ext v5.16b, v0.16b, v0.16b, #5 + zip1 v0.2d, v0.2d, v1.2d + zip1 v2.2d, v2.2d, v3.2d + zip1 v4.2d, v4.2d, v5.2d + movi v16.2d, #0 + movi v17.2d, #0 + movi v18.2d, #0 + usdot v16.4s, v0.16b, v31.16b + usdot v17.4s, v2.16b, v31.16b + usdot v18.4s, v4.16b, v31.16b + addp v16.4s, v16.4s, v17.4s + addp v18.4s, v18.4s, v18.4s + sqxtn v16.4h, v16.4s + sqxtn v18.4h, v18.4s + str d16, [x0] + str s18, [x15] + add x0, x0, x10 + add x15, x15, x10 + subs w3, w3, #1 + b.ne 1b + ret +endfunc + +function ff_hevc_put_hevc_qpel_h8_8_neon_i8mm, export=1 + QPEL_H_HEADER + mov x10, #MAX_PB_SIZE * 2 +1: + ld1 {v0.16b}, [x1], x2 + ext v1.16b, v0.16b, v0.16b, #1 + ext v2.16b, v0.16b, v0.16b, #2 + ext v3.16b, v0.16b, v0.16b, #3 + ext v4.16b, v0.16b, v0.16b, #4 + ext v5.16b, v0.16b, v0.16b, #5 + ext v6.16b, v0.16b, v0.16b, #6 + ext v7.16b, v0.16b, v0.16b, #7 + zip1 v0.2d, v0.2d, v1.2d + zip1 v2.2d, v2.2d, v3.2d + zip1 v4.2d, v4.2d, v5.2d + zip1 v6.2d, v6.2d, v7.2d + movi v16.2d, #0 + movi v17.2d, #0 + movi v18.2d, #0 + movi v19.2d, #0 + usdot v16.4s, v0.16b, v31.16b + usdot v17.4s, v2.16b, v31.16b + usdot v18.4s, v4.16b, v31.16b + usdot v19.4s, v6.16b, v31.16b + addp v16.4s, v16.4s, v17.4s + addp v18.4s, v18.4s, v19.4s + sqxtn v16.4h, v16.4s + sqxtn2 v16.8h, v18.4s + str q16, [x0] + add x0, x0, x10 + subs w3, w3, #1 + b.ne 1b + ret +endfunc + +.macro QPEL_H_CALC s0, s1, s2, s3, d0, d1, d2, d3 + movi \d0\().2d, #0 + movi \d1\().2d, #0 + movi \d2\().2d, #0 + movi \d3\().2d, #0 + usdot \d0\().4s, \s0\().16b, v31.16b + usdot \d1\().4s, \s1\().16b, v31.16b + usdot \d2\().4s, \s2\().16b, v31.16b + usdot \d3\().4s, \s3\().16b, v31.16b +.endm + +function ff_hevc_put_hevc_qpel_h12_8_neon_i8mm, export=1 + QPEL_H_HEADER + mov x10, #MAX_PB_SIZE * 2 + add x15, x0, #16 +1: + ld1 {v16.16b, v17.16b}, [x1], x2 + ext v1.16b, v16.16b, v17.16b, #1 + ext v2.16b, v16.16b, v17.16b, #2 + ext v3.16b, v16.16b, v17.16b, #3 + ext v4.16b, v16.16b, v17.16b, #4 + ext v5.16b, v16.16b, v17.16b, #5 + ext v6.16b, v16.16b, v17.16b, #6 + ext v7.16b, v16.16b, v17.16b, #7 + zip1 v18.2d, v4.2d, v5.2d + zip1 v19.2d, v6.2d, v7.2d + QPEL_H_CALC v16, v1, v2, v3, v20, v21, v22, v23 + addp v20.4s, v20.4s, v22.4s + addp v21.4s, v21.4s, v23.4s + movi v24.2d, #0 + movi v25.2d, #0 + usdot v24.4s, v18.16b, v31.16b + usdot v25.4s, v19.16b, v31.16b + addp v24.4s, v24.4s, v25.4s + trn1 v26.4s, v20.4s, v21.4s + trn2 v27.4s, v20.4s, v21.4s + sqxtn v26.4h, v26.4s + sqxtn v27.4h, v27.4s + sqxtn2 v26.8h, v24.4s + + str q26, [x0] + str d27, [x15] + add x0, x0, x10 + add x15, x15, x10 + subs w3, w3, #1 + b.ne 1b + ret +endfunc + +function ff_hevc_put_hevc_qpel_h16_8_neon_i8mm, export=1 + QPEL_H_HEADER + mov x10, #MAX_PB_SIZE * 2 +1: + ld1 {v16.16b, v17.16b}, [x1], x2 + ext v1.16b, v16.16b, v17.16b, #1 + ext v2.16b, v16.16b, v17.16b, #2 + ext v3.16b, v16.16b, v17.16b, #3 + ext v4.16b, v16.16b, v17.16b, #4 + ext v5.16b, v16.16b, v17.16b, #5 + ext v6.16b, v16.16b, v17.16b, #6 + ext v7.16b, v16.16b, v17.16b, #7 + + QPEL_H_CALC v16, v1, v2, v3, v20, v21, v22, v23 + QPEL_H_CALC v4, v5, v6, v7, v24, v25, v26, v27 + + addp v20.4s, v20.4s, v22.4s + addp v21.4s, v21.4s, v23.4s + addp v24.4s, v24.4s, v26.4s + addp v25.4s, v25.4s, v27.4s + + trn1 v22.4s, v20.4s, v21.4s + trn2 v23.4s, v20.4s, v21.4s + trn1 v26.4s, v24.4s, v25.4s + trn2 v27.4s, v24.4s, v25.4s + + sqxtn v18.4h, v22.4s + sqxtn2 v18.8h, v26.4s + sqxtn v19.4h, v23.4s + sqxtn2 v19.8h, v27.4s + + stp q18, q19, [x0] + add x0, x0, x10 + subs w3, w3, #1 + b.ne 1b + ret +endfunc + +function ff_hevc_put_hevc_qpel_h24_8_neon_i8mm, export=1 + QPEL_H_HEADER + mov x10, #MAX_PB_SIZE * 2 + add x15, x0, #32 +1: + ld1 {v16.16b, v17.16b}, [x1], x2 + ext v1.16b, v16.16b, v17.16b, #1 + ext v2.16b, v16.16b, v17.16b, #2 + ext v3.16b, v16.16b, v17.16b, #3 + ext v4.16b, v16.16b, v17.16b, #4 + ext v5.16b, v16.16b, v17.16b, #5 + ext v6.16b, v16.16b, v17.16b, #6 + ext v7.16b, v16.16b, v17.16b, #7 + QPEL_H_CALC v16, v1, v2, v3, v20, v21, v22, v23 + QPEL_H_CALC v4, v5, v6, v7, v24, v25, v26, v27 + addp v20.4s, v20.4s, v22.4s + addp v21.4s, v21.4s, v23.4s + addp v24.4s, v24.4s, v26.4s + addp v25.4s, v25.4s, v27.4s + trn1 v22.4s, v20.4s, v21.4s + trn2 v23.4s, v20.4s, v21.4s + trn1 v26.4s, v24.4s, v25.4s + trn2 v27.4s, v24.4s, v25.4s + sqxtn v18.4h, v22.4s + sqxtn2 v18.8h, v26.4s + sqxtn v19.4h, v23.4s + sqxtn2 v19.8h, v27.4s + stp q18, q19, [x0] + add x0, x0, x10 + ext v1.16b, v17.16b, v17.16b, #1 + ext v2.16b, v17.16b, v17.16b, #2 + ext v3.16b, v17.16b, v17.16b, #3 + ext v4.16b, v17.16b, v17.16b, #4 + ext v5.16b, v17.16b, v17.16b, #5 + ext v6.16b, v17.16b, v17.16b, #6 + ext v7.16b, v17.16b, v17.16b, #7 + zip1 v0.2d, v17.2d, v1.2d + zip1 v2.2d, v2.2d, v3.2d + zip1 v4.2d, v4.2d, v5.2d + zip1 v6.2d, v6.2d, v7.2d + QPEL_H_CALC v0, v2, v4, v6, v20, v21, v22, v23 + addp v20.4s, v20.4s, v21.4s + addp v22.4s, v22.4s, v23.4s + sqxtn v20.4h, v20.4s + sqxtn2 v20.8h, v22.4s + str q20, [x15] + add x15, x15, x10 + subs w3, w3, #1 + b.ne 1b + ret +endfunc + +function ff_hevc_put_hevc_qpel_h32_8_neon_i8mm, export=1 + QPEL_H_HEADER + mov x10, #MAX_PB_SIZE * 2 + add x15, x0, #32 +1: + ld1 {v16.16b, v17.16b, v18.16b}, [x1], x2 + ext v1.16b, v16.16b, v17.16b, #1 + ext v2.16b, v16.16b, v17.16b, #2 + ext v3.16b, v16.16b, v17.16b, #3 + ext v4.16b, v16.16b, v17.16b, #4 + ext v5.16b, v16.16b, v17.16b, #5 + ext v6.16b, v16.16b, v17.16b, #6 + ext v7.16b, v16.16b, v17.16b, #7 + QPEL_H_CALC v16, v1, v2, v3, v20, v21, v22, v23 + QPEL_H_CALC v4, v5, v6, v7, v24, v25, v26, v27 + addp v20.4s, v20.4s, v22.4s + addp v21.4s, v21.4s, v23.4s + addp v24.4s, v24.4s, v26.4s + addp v25.4s, v25.4s, v27.4s + trn1 v22.4s, v20.4s, v21.4s + trn2 v23.4s, v20.4s, v21.4s + trn1 v26.4s, v24.4s, v25.4s + trn2 v27.4s, v24.4s, v25.4s + sqxtn v20.4h, v22.4s + sqxtn2 v20.8h, v26.4s + sqxtn v21.4h, v23.4s + sqxtn2 v21.8h, v27.4s + stp q20, q21, [x0] + add x0, x0, x10 + ext v1.16b, v17.16b, v18.16b, #1 + ext v2.16b, v17.16b, v18.16b, #2 + ext v3.16b, v17.16b, v18.16b, #3 + ext v4.16b, v17.16b, v18.16b, #4 + ext v5.16b, v17.16b, v18.16b, #5 + ext v6.16b, v17.16b, v18.16b, #6 + ext v7.16b, v17.16b, v18.16b, #7 + QPEL_H_CALC v17, v1, v2, v3, v20, v21, v22, v23 + QPEL_H_CALC v4, v5, v6, v7, v24, v25, v26, v27 + addp v20.4s, v20.4s, v22.4s + addp v21.4s, v21.4s, v23.4s + addp v24.4s, v24.4s, v26.4s + addp v25.4s, v25.4s, v27.4s + trn1 v22.4s, v20.4s, v21.4s + trn2 v23.4s, v20.4s, v21.4s + trn1 v26.4s, v24.4s, v25.4s + trn2 v27.4s, v24.4s, v25.4s + sqxtn v20.4h, v22.4s + sqxtn2 v20.8h, v26.4s + sqxtn v21.4h, v23.4s + sqxtn2 v21.8h, v27.4s + stp q20, q21, [x15] + add x15, x15, x10 + subs w3, w3, #1 + b.ne 1b + ret +endfunc + +function ff_hevc_put_hevc_qpel_h48_8_neon_i8mm, export=1 + QPEL_H_HEADER + mov x10, #MAX_PB_SIZE * 2 - 64 +1: + ld1 {v16.16b, v17.16b, v18.16b, v19.16b}, [x1], x2 + ext v1.16b, v16.16b, v17.16b, #1 + ext v2.16b, v16.16b, v17.16b, #2 + ext v3.16b, v16.16b, v17.16b, #3 + ext v4.16b, v16.16b, v17.16b, #4 + ext v5.16b, v16.16b, v17.16b, #5 + ext v6.16b, v16.16b, v17.16b, #6 + ext v7.16b, v16.16b, v17.16b, #7 + QPEL_H_CALC v16, v1, v2, v3, v20, v21, v22, v23 + QPEL_H_CALC v4, v5, v6, v7, v24, v25, v26, v27 + addp v20.4s, v20.4s, v22.4s + addp v21.4s, v21.4s, v23.4s + addp v24.4s, v24.4s, v26.4s + addp v25.4s, v25.4s, v27.4s + trn1 v22.4s, v20.4s, v21.4s + trn2 v23.4s, v20.4s, v21.4s + trn1 v26.4s, v24.4s, v25.4s + trn2 v27.4s, v24.4s, v25.4s + sqxtn v20.4h, v22.4s + sqxtn2 v20.8h, v26.4s + sqxtn v21.4h, v23.4s + sqxtn2 v21.8h, v27.4s + stp q20, q21, [x0], #32 + + ext v1.16b, v17.16b, v18.16b, #1 + ext v2.16b, v17.16b, v18.16b, #2 + ext v3.16b, v17.16b, v18.16b, #3 + ext v4.16b, v17.16b, v18.16b, #4 + ext v5.16b, v17.16b, v18.16b, #5 + ext v6.16b, v17.16b, v18.16b, #6 + ext v7.16b, v17.16b, v18.16b, #7 + QPEL_H_CALC v17, v1, v2, v3, v20, v21, v22, v23 + QPEL_H_CALC v4, v5, v6, v7, v24, v25, v26, v27 + addp v20.4s, v20.4s, v22.4s + addp v21.4s, v21.4s, v23.4s + addp v24.4s, v24.4s, v26.4s + addp v25.4s, v25.4s, v27.4s + trn1 v22.4s, v20.4s, v21.4s + trn2 v23.4s, v20.4s, v21.4s + trn1 v26.4s, v24.4s, v25.4s + trn2 v27.4s, v24.4s, v25.4s + sqxtn v20.4h, v22.4s + sqxtn2 v20.8h, v26.4s + sqxtn v21.4h, v23.4s + sqxtn2 v21.8h, v27.4s + stp q20, q21, [x0], #32 + ext v1.16b, v18.16b, v19.16b, #1 + ext v2.16b, v18.16b, v19.16b, #2 + ext v3.16b, v18.16b, v19.16b, #3 + ext v4.16b, v18.16b, v19.16b, #4 + ext v5.16b, v18.16b, v19.16b, #5 + ext v6.16b, v18.16b, v19.16b, #6 + ext v7.16b, v18.16b, v19.16b, #7 + QPEL_H_CALC v18, v1, v2, v3, v20, v21, v22, v23 + QPEL_H_CALC v4, v5, v6, v7, v24, v25, v26, v27 + addp v20.4s, v20.4s, v22.4s + addp v21.4s, v21.4s, v23.4s + addp v24.4s, v24.4s, v26.4s + addp v25.4s, v25.4s, v27.4s + trn1 v22.4s, v20.4s, v21.4s + trn2 v23.4s, v20.4s, v21.4s + trn1 v26.4s, v24.4s, v25.4s + trn2 v27.4s, v24.4s, v25.4s + sqxtn v20.4h, v22.4s + sqxtn2 v20.8h, v26.4s + sqxtn v21.4h, v23.4s + sqxtn2 v21.8h, v27.4s + stp q20, q21, [x0] + add x0, x0, x10 + subs w3, w3, #1 + b.ne 1b + ret +endfunc + +function ff_hevc_put_hevc_qpel_h64_8_neon_i8mm, export=1 + QPEL_H_HEADER + sub x2, x2, #64 +1: + ld1 {v16.16b, v17.16b, v18.16b, v19.16b}, [x1], #64 + ext v1.16b, v16.16b, v17.16b, #1 + ext v2.16b, v16.16b, v17.16b, #2 + ext v3.16b, v16.16b, v17.16b, #3 + ext v4.16b, v16.16b, v17.16b, #4 + ext v5.16b, v16.16b, v17.16b, #5 + ext v6.16b, v16.16b, v17.16b, #6 + ext v7.16b, v16.16b, v17.16b, #7 + QPEL_H_CALC v16, v1, v2, v3, v20, v21, v22, v23 + QPEL_H_CALC v4, v5, v6, v7, v24, v25, v26, v27 + addp v20.4s, v20.4s, v22.4s + addp v21.4s, v21.4s, v23.4s + addp v24.4s, v24.4s, v26.4s + addp v25.4s, v25.4s, v27.4s + trn1 v22.4s, v20.4s, v21.4s + trn2 v23.4s, v20.4s, v21.4s + trn1 v26.4s, v24.4s, v25.4s + trn2 v27.4s, v24.4s, v25.4s + sqxtn v20.4h, v22.4s + sqxtn2 v20.8h, v26.4s + sqxtn v21.4h, v23.4s + sqxtn2 v21.8h, v27.4s + stp q20, q21, [x0], #32 + + ext v1.16b, v17.16b, v18.16b, #1 + ext v2.16b, v17.16b, v18.16b, #2 + ext v3.16b, v17.16b, v18.16b, #3 + ext v4.16b, v17.16b, v18.16b, #4 + ext v5.16b, v17.16b, v18.16b, #5 + ext v6.16b, v17.16b, v18.16b, #6 + ext v7.16b, v17.16b, v18.16b, #7 + QPEL_H_CALC v17, v1, v2, v3, v20, v21, v22, v23 + QPEL_H_CALC v4, v5, v6, v7, v24, v25, v26, v27 + addp v20.4s, v20.4s, v22.4s + addp v21.4s, v21.4s, v23.4s + addp v24.4s, v24.4s, v26.4s + addp v25.4s, v25.4s, v27.4s + trn1 v22.4s, v20.4s, v21.4s + trn2 v23.4s, v20.4s, v21.4s + trn1 v26.4s, v24.4s, v25.4s + trn2 v27.4s, v24.4s, v25.4s + sqxtn v20.4h, v22.4s + sqxtn2 v20.8h, v26.4s + sqxtn v21.4h, v23.4s + sqxtn2 v21.8h, v27.4s + stp q20, q21, [x0], #32 + ext v1.16b, v18.16b, v19.16b, #1 + ext v2.16b, v18.16b, v19.16b, #2 + ext v3.16b, v18.16b, v19.16b, #3 + ext v4.16b, v18.16b, v19.16b, #4 + ext v5.16b, v18.16b, v19.16b, #5 + ext v6.16b, v18.16b, v19.16b, #6 + ext v7.16b, v18.16b, v19.16b, #7 + QPEL_H_CALC v18, v1, v2, v3, v20, v21, v22, v23 + QPEL_H_CALC v4, v5, v6, v7, v24, v25, v26, v27 + addp v20.4s, v20.4s, v22.4s + addp v21.4s, v21.4s, v23.4s + addp v24.4s, v24.4s, v26.4s + addp v25.4s, v25.4s, v27.4s + trn1 v22.4s, v20.4s, v21.4s + trn2 v23.4s, v20.4s, v21.4s + trn1 v26.4s, v24.4s, v25.4s + trn2 v27.4s, v24.4s, v25.4s + sqxtn v20.4h, v22.4s + sqxtn2 v20.8h, v26.4s + sqxtn v21.4h, v23.4s + sqxtn2 v21.8h, v27.4s + stp q20, q21, [x0], #32 + ld1 {v28.8b}, [x1], x2 + ext v1.16b, v19.16b, v28.16b, #1 + ext v2.16b, v19.16b, v28.16b, #2 + ext v3.16b, v19.16b, v28.16b, #3 + ext v4.16b, v19.16b, v28.16b, #4 + ext v5.16b, v19.16b, v28.16b, #5 + ext v6.16b, v19.16b, v28.16b, #6 + ext v7.16b, v19.16b, v28.16b, #7 + QPEL_H_CALC v19, v1, v2, v3, v20, v21, v22, v23 + QPEL_H_CALC v4, v5, v6, v7, v24, v25, v26, v27 + addp v20.4s, v20.4s, v22.4s + addp v21.4s, v21.4s, v23.4s + addp v24.4s, v24.4s, v26.4s + addp v25.4s, v25.4s, v27.4s + trn1 v22.4s, v20.4s, v21.4s + trn2 v23.4s, v20.4s, v21.4s + trn1 v26.4s, v24.4s, v25.4s + trn2 v27.4s, v24.4s, v25.4s + sqxtn v20.4h, v22.4s + sqxtn2 v20.8h, v26.4s + sqxtn v21.4h, v23.4s + sqxtn2 v21.8h, v27.4s + stp q20, q21, [x0], #32 + subs w3, w3, #1 + b.ne 1b + ret +endfunc + +.macro QPEL_UNI_W_HV_HEADER width + ldp x14, x15, [sp] // mx, my + ldr w13, [sp, #16] // width + stp x19, x30, [sp, #-80]! + stp x20, x21, [sp, #16] + stp x22, x23, [sp, #32] + stp x24, x25, [sp, #48] + stp x26, x27, [sp, #64] + mov x19, sp + mov x11, #9088 + sub sp, sp, x11 + mov x20, x0 + mov x21, x1 + mov x0, sp + sub x1, x2, x3, lsl #1 + sub x1, x1, x3 + mov x2, x3 + add w3, w4, #7 + mov w22, w4 // height + mov x4, x14 // mx + mov x23, x15 // my + mov w24, w6 // wx + mov w25, w7 // ox + mov w26, #-6 + sub w26, w26, w5 // -shift + mov w27, w13 // width + bl X(ff_hevc_put_hevc_qpel_h\width\()_8_neon_i8mm) + movrel x9, qpel_filters + add x9, x9, x23, lsl #3 + ld1 {v0.8b}, [x9] + sxtl v0.8h, v0.8b + mov x10, #(MAX_PB_SIZE * 2) + dup v28.4s, w24 + dup v29.4s, w25 + dup v30.4s, w26 +.endm + +.macro QPEL_UNI_W_HV_END + mov sp, x19 + ldp x20, x21, [sp, #16] + ldp x22, x23, [sp, #32] + ldp x24, x25, [sp, #48] + ldp x26, x27, [sp, #64] + ldp x19, x30, [sp], #80 +.endm + +.macro QPEL_UNI_W_HV_4 + sshr v26.4s, v26.4s, #6 + mul v24.4s, v26.4s, v28.4s + sqrshl v24.4s, v24.4s, v30.4s + sqadd v24.4s, v24.4s, v29.4s + sqxtn v24.4h, v24.4s + sqxtun v24.8b, v24.8h + st1 {v24.s}[0], [x20], x21 +.endm + +.macro QPEL_FILTER_H dst, src0, src1, src2, src3, src4, src5, src6, src7 + smull \dst\().4s, \src0\().4h, v0.h[0] + smlal \dst\().4s, \src1\().4h, v0.h[1] + smlal \dst\().4s, \src2\().4h, v0.h[2] + smlal \dst\().4s, \src3\().4h, v0.h[3] + smlal \dst\().4s, \src4\().4h, v0.h[4] + smlal \dst\().4s, \src5\().4h, v0.h[5] + smlal \dst\().4s, \src6\().4h, v0.h[6] + smlal \dst\().4s, \src7\().4h, v0.h[7] +.endm + +.macro QPEL_FILTER_H2 dst, src0, src1, src2, src3, src4, src5, src6, src7 + smull2 \dst\().4s, \src0\().8h, v0.h[0] + smlal2 \dst\().4s, \src1\().8h, v0.h[1] + smlal2 \dst\().4s, \src2\().8h, v0.h[2] + smlal2 \dst\().4s, \src3\().8h, v0.h[3] + smlal2 \dst\().4s, \src4\().8h, v0.h[4] + smlal2 \dst\().4s, \src5\().8h, v0.h[5] + smlal2 \dst\().4s, \src6\().8h, v0.h[6] + smlal2 \dst\().4s, \src7\().8h, v0.h[7] +.endm + +function ff_hevc_put_hevc_qpel_uni_w_hv4_8_neon_i8mm, export=1 + QPEL_UNI_W_HV_HEADER 4 + ldr d16, [sp] + ldr d17, [sp, x10] + add sp, sp, x10, lsl #1 + ldr d18, [sp] + ldr d19, [sp, x10] + add sp, sp, x10, lsl #1 + ldr d20, [sp] + ldr d21, [sp, x10] + add sp, sp, x10, lsl #1 + ldr d22, [sp] + add sp, sp, x10 +1: + ldr d23, [sp] + add sp, sp, x10 + QPEL_FILTER_H v26, v16, v17, v18, v19, v20, v21, v22, v23 + QPEL_UNI_W_HV_4 + subs w22, w22, #1 + b.eq 2f + + ldr d16, [sp] + add sp, sp, x10 + QPEL_FILTER_H v26, v17, v18, v19, v20, v21, v22, v23, v16 + QPEL_UNI_W_HV_4 + subs w22, w22, #1 + b.eq 2f + + ldr d17, [sp] + add sp, sp, x10 + QPEL_FILTER_H v26, v18, v19, v20, v21, v22, v23, v16, v17 + QPEL_UNI_W_HV_4 + subs w22, w22, #1 + b.eq 2f + + ldr d18, [sp] + add sp, sp, x10 + QPEL_FILTER_H v26, v19, v20, v21, v22, v23, v16, v17, v18 + QPEL_UNI_W_HV_4 + subs w22, w22, #1 + b.eq 2f + + ldr d19, [sp] + add sp, sp, x10 + QPEL_FILTER_H v26, v20, v21, v22, v23, v16, v17, v18, v19 + QPEL_UNI_W_HV_4 + subs w22, w22, #1 + b.eq 2f + + ldr d20, [sp] + add sp, sp, x10 + QPEL_FILTER_H v26, v21, v22, v23, v16, v17, v18, v19, v20 + QPEL_UNI_W_HV_4 + subs w22, w22, #1 + b.eq 2f + + ldr d21, [sp] + add sp, sp, x10 + QPEL_FILTER_H v26, v22, v23, v16, v17, v18, v19, v20, v21 + QPEL_UNI_W_HV_4 + subs w22, w22, #1 + b.eq 2f + + ldr d22, [sp] + add sp, sp, x10 + QPEL_FILTER_H v26, v23, v16, v17, v18, v19, v20, v21, v22 + QPEL_UNI_W_HV_4 + subs w22, w22, #1 + b.hi 1b + +2: + QPEL_UNI_W_HV_END + ret +endfunc + +.macro QPEL_UNI_W_HV_8 + sshr v26.4s, v26.4s, #6 + sshr v27.4s, v27.4s, #6 + mul v24.4s, v26.4s, v28.4s + mul v25.4s, v27.4s, v28.4s + sqrshl v24.4s, v24.4s, v30.4s + sqrshl v25.4s, v25.4s, v30.4s + sqadd v24.4s, v24.4s, v29.4s + sqadd v25.4s, v25.4s, v29.4s + sqxtn v24.4h, v24.4s + sqxtn2 v24.8h, v25.4s + sqxtun v24.8b, v24.8h + st1 {v24.d}[0], [x20], x21 +.endm + +function ff_hevc_put_hevc_qpel_uni_w_hv8_8_neon_i8mm, export=1 + QPEL_UNI_W_HV_HEADER 8 + ldr q16, [sp] + ldr q17, [sp, x10] + add sp, sp, x10, lsl #1 + ldr q18, [sp] + ldr q19, [sp, x10] + add sp, sp, x10, lsl #1 + ldr q20, [sp] + ldr q21, [sp, x10] + add sp, sp, x10, lsl #1 + ldr q22, [sp] + add sp, sp, x10 +1: + ldr q23, [sp] + add sp, sp, x10 + QPEL_FILTER_H v26, v16, v17, v18, v19, v20, v21, v22, v23 + QPEL_FILTER_H2 v27, v16, v17, v18, v19, v20, v21, v22, v23 + QPEL_UNI_W_HV_8 + subs w22, w22, #1 + b.eq 2f + + ldr q16, [sp] + add sp, sp, x10 + QPEL_FILTER_H v26, v17, v18, v19, v20, v21, v22, v23, v16 + QPEL_FILTER_H2 v27, v17, v18, v19, v20, v21, v22, v23, v16 + QPEL_UNI_W_HV_8 + subs w22, w22, #1 + b.eq 2f + + ldr q17, [sp] + add sp, sp, x10 + QPEL_FILTER_H v26, v18, v19, v20, v21, v22, v23, v16, v17 + QPEL_FILTER_H2 v27, v18, v19, v20, v21, v22, v23, v16, v17 + QPEL_UNI_W_HV_8 + subs w22, w22, #1 + b.eq 2f + + ldr q18, [sp] + add sp, sp, x10 + QPEL_FILTER_H v26, v19, v20, v21, v22, v23, v16, v17, v18 + QPEL_FILTER_H2 v27, v19, v20, v21, v22, v23, v16, v17, v18 + QPEL_UNI_W_HV_8 + subs w22, w22, #1 + b.eq 2f + + ldr q19, [sp] + add sp, sp, x10 + QPEL_FILTER_H v26, v20, v21, v22, v23, v16, v17, v18, v19 + QPEL_FILTER_H2 v27, v20, v21, v22, v23, v16, v17, v18, v19 + QPEL_UNI_W_HV_8 + subs w22, w22, #1 + b.eq 2f + + ldr q20, [sp] + add sp, sp, x10 + QPEL_FILTER_H v26, v21, v22, v23, v16, v17, v18, v19, v20 + QPEL_FILTER_H2 v27, v21, v22, v23, v16, v17, v18, v19, v20 + QPEL_UNI_W_HV_8 + subs w22, w22, #1 + b.eq 2f + + ldr q21, [sp] + add sp, sp, x10 + QPEL_FILTER_H v26, v22, v23, v16, v17, v18, v19, v20, v21 + QPEL_FILTER_H2 v27, v22, v23, v16, v17, v18, v19, v20, v21 + QPEL_UNI_W_HV_8 + subs w22, w22, #1 + b.eq 2f + + ldr q22, [sp] + add sp, sp, x10 + QPEL_FILTER_H v26, v23, v16, v17, v18, v19, v20, v21, v22 + QPEL_FILTER_H2 v27, v23, v16, v17, v18, v19, v20, v21, v22 + QPEL_UNI_W_HV_8 + subs w22, w22, #1 + b.hi 1b + +2: + QPEL_UNI_W_HV_END + ret +endfunc + +.macro QPEL_UNI_W_HV_16 + sshr v24.4s, v24.4s, #6 + sshr v25.4s, v25.4s, #6 + sshr v26.4s, v26.4s, #6 + sshr v27.4s, v27.4s, #6 + mul v24.4s, v24.4s, v28.4s + mul v25.4s, v25.4s, v28.4s + mul v26.4s, v26.4s, v28.4s + mul v27.4s, v27.4s, v28.4s + sqrshl v24.4s, v24.4s, v30.4s + sqrshl v25.4s, v25.4s, v30.4s + sqrshl v26.4s, v26.4s, v30.4s + sqrshl v27.4s, v27.4s, v30.4s + sqadd v24.4s, v24.4s, v29.4s + sqadd v25.4s, v25.4s, v29.4s + sqadd v26.4s, v26.4s, v29.4s + sqadd v27.4s, v27.4s, v29.4s + sqxtn v24.4h, v24.4s + sqxtn2 v24.8h, v25.4s + sqxtn v26.4h, v26.4s + sqxtn2 v26.8h, v27.4s + sqxtun v24.8b, v24.8h + sqxtun2 v24.16b, v26.8h + + st1 {v24.16b}, [x20], x21 +.endm + +function ff_hevc_put_hevc_qpel_uni_w_hv16_8_neon_i8mm, export=1 + QPEL_UNI_W_HV_HEADER 16 + ldp q16, q1, [sp] + add sp, sp, x10 + ldp q17, q2, [sp] + add sp, sp, x10 + ldp q18, q3, [sp] + add sp, sp, x10 + ldp q19, q4, [sp] + add sp, sp, x10 + ldp q20, q5, [sp] + add sp, sp, x10 + ldp q21, q6, [sp] + add sp, sp, x10 + ldp q22, q7, [sp] + add sp, sp, x10 +1: + ldp q23, q31, [sp] + add sp, sp, x10 + QPEL_FILTER_H v24, v16, v17, v18, v19, v20, v21, v22, v23 + QPEL_FILTER_H2 v25, v16, v17, v18, v19, v20, v21, v22, v23 + QPEL_FILTER_H v26, v1, v2, v3, v4, v5, v6, v7, v31 + QPEL_FILTER_H2 v27, v1, v2, v3, v4, v5, v6, v7, v31 + QPEL_UNI_W_HV_16 + subs w22, w22, #1 + b.eq 2f + + ldp q16, q1, [sp] + add sp, sp, x10 + QPEL_FILTER_H v24, v17, v18, v19, v20, v21, v22, v23, v16 + QPEL_FILTER_H2 v25, v17, v18, v19, v20, v21, v22, v23, v16 + QPEL_FILTER_H v26, v2, v3, v4, v5, v6, v7, v31, v1 + QPEL_FILTER_H2 v27, v2, v3, v4, v5, v6, v7, v31, v1 + QPEL_UNI_W_HV_16 + subs w22, w22, #1 + b.eq 2f + + ldp q17, q2, [sp] + add sp, sp, x10 + QPEL_FILTER_H v24, v18, v19, v20, v21, v22, v23, v16, v17 + QPEL_FILTER_H2 v25, v18, v19, v20, v21, v22, v23, v16, v17 + QPEL_FILTER_H v26, v3, v4, v5, v6, v7, v31, v1, v2 + QPEL_FILTER_H2 v27, v3, v4, v5, v6, v7, v31, v1, v2 + QPEL_UNI_W_HV_16 + subs w22, w22, #1 + b.eq 2f + + ldp q18, q3, [sp] + add sp, sp, x10 + QPEL_FILTER_H v24, v19, v20, v21, v22, v23, v16, v17, v18 + QPEL_FILTER_H2 v25, v19, v20, v21, v22, v23, v16, v17, v18 + QPEL_FILTER_H v26, v4, v5, v6, v7, v31, v1, v2, v3 + QPEL_FILTER_H2 v27, v4, v5, v6, v7, v31, v1, v2, v3 + QPEL_UNI_W_HV_16 + subs w22, w22, #1 + b.eq 2f + + ldp q19, q4, [sp] + add sp, sp, x10 + QPEL_FILTER_H v24, v20, v21, v22, v23, v16, v17, v18, v19 + QPEL_FILTER_H2 v25, v20, v21, v22, v23, v16, v17, v18, v19 + QPEL_FILTER_H v26, v5, v6, v7, v31, v1, v2, v3, v4 + QPEL_FILTER_H2 v27, v5, v6, v7, v31, v1, v2, v3, v4 + QPEL_UNI_W_HV_16 + subs w22, w22, #1 + b.eq 2f + + ldp q20, q5, [sp] + add sp, sp, x10 + QPEL_FILTER_H v24, v21, v22, v23, v16, v17, v18, v19, v20 + QPEL_FILTER_H2 v25, v21, v22, v23, v16, v17, v18, v19, v20 + QPEL_FILTER_H v26, v6, v7, v31, v1, v2, v3, v4, v5 + QPEL_FILTER_H2 v27, v6, v7, v31, v1, v2, v3, v4, v5 + QPEL_UNI_W_HV_16 + subs w22, w22, #1 + b.eq 2f + + ldp q21, q6, [sp] + add sp, sp, x10 + QPEL_FILTER_H v24, v22, v23, v16, v17, v18, v19, v20, v21 + QPEL_FILTER_H2 v25, v22, v23, v16, v17, v18, v19, v20, v21 + QPEL_FILTER_H v26, v7, v31, v1, v2, v3, v4, v5, v6 + QPEL_FILTER_H2 v27, v7, v31, v1, v2, v3, v4, v5, v6 + QPEL_UNI_W_HV_16 + subs w22, w22, #1 + b.eq 2f + + ldp q22, q7, [sp] + add sp, sp, x10 + QPEL_FILTER_H v24, v23, v16, v17, v18, v19, v20, v21, v22 + QPEL_FILTER_H2 v25, v23, v16, v17, v18, v19, v20, v21, v22 + QPEL_FILTER_H v26, v31, v1, v2, v3, v4, v5, v6, v7 + QPEL_FILTER_H2 v27, v31, v1, v2, v3, v4, v5, v6, v7 + QPEL_UNI_W_HV_16 + subs w22, w22, #1 + b.hi 1b + +2: + QPEL_UNI_W_HV_END + ret +endfunc + + +function ff_hevc_put_hevc_qpel_uni_w_hv32_8_neon_i8mm, export=1 + QPEL_UNI_W_HV_HEADER 32 + mov x11, sp + mov w12, w22 + mov x13, x20 +3: + ldp q16, q1, [sp] + add sp, sp, x10 + ldp q17, q2, [sp] + add sp, sp, x10 + ldp q18, q3, [sp] + add sp, sp, x10 + ldp q19, q4, [sp] + add sp, sp, x10 + ldp q20, q5, [sp] + add sp, sp, x10 + ldp q21, q6, [sp] + add sp, sp, x10 + ldp q22, q7, [sp] + add sp, sp, x10 +1: + ldp q23, q31, [sp] + add sp, sp, x10 + QPEL_FILTER_H v24, v16, v17, v18, v19, v20, v21, v22, v23 + QPEL_FILTER_H2 v25, v16, v17, v18, v19, v20, v21, v22, v23 + QPEL_FILTER_H v26, v1, v2, v3, v4, v5, v6, v7, v31 + QPEL_FILTER_H2 v27, v1, v2, v3, v4, v5, v6, v7, v31 + QPEL_UNI_W_HV_16 + subs w22, w22, #1 + b.eq 2f + + ldp q16, q1, [sp] + add sp, sp, x10 + QPEL_FILTER_H v24, v17, v18, v19, v20, v21, v22, v23, v16 + QPEL_FILTER_H2 v25, v17, v18, v19, v20, v21, v22, v23, v16 + QPEL_FILTER_H v26, v2, v3, v4, v5, v6, v7, v31, v1 + QPEL_FILTER_H2 v27, v2, v3, v4, v5, v6, v7, v31, v1 + QPEL_UNI_W_HV_16 + subs w22, w22, #1 + b.eq 2f + + ldp q17, q2, [sp] + add sp, sp, x10 + QPEL_FILTER_H v24, v18, v19, v20, v21, v22, v23, v16, v17 + QPEL_FILTER_H2 v25, v18, v19, v20, v21, v22, v23, v16, v17 + QPEL_FILTER_H v26, v3, v4, v5, v6, v7, v31, v1, v2 + QPEL_FILTER_H2 v27, v3, v4, v5, v6, v7, v31, v1, v2 + QPEL_UNI_W_HV_16 + subs w22, w22, #1 + b.eq 2f + + ldp q18, q3, [sp] + add sp, sp, x10 + QPEL_FILTER_H v24, v19, v20, v21, v22, v23, v16, v17, v18 + QPEL_FILTER_H2 v25, v19, v20, v21, v22, v23, v16, v17, v18 + QPEL_FILTER_H v26, v4, v5, v6, v7, v31, v1, v2, v3 + QPEL_FILTER_H2 v27, v4, v5, v6, v7, v31, v1, v2, v3 + QPEL_UNI_W_HV_16 + subs w22, w22, #1 + b.eq 2f + + ldp q19, q4, [sp] + add sp, sp, x10 + QPEL_FILTER_H v24, v20, v21, v22, v23, v16, v17, v18, v19 + QPEL_FILTER_H2 v25, v20, v21, v22, v23, v16, v17, v18, v19 + QPEL_FILTER_H v26, v5, v6, v7, v31, v1, v2, v3, v4 + QPEL_FILTER_H2 v27, v5, v6, v7, v31, v1, v2, v3, v4 + QPEL_UNI_W_HV_16 + subs w22, w22, #1 + b.eq 2f + + ldp q20, q5, [sp] + add sp, sp, x10 + QPEL_FILTER_H v24, v21, v22, v23, v16, v17, v18, v19, v20 + QPEL_FILTER_H2 v25, v21, v22, v23, v16, v17, v18, v19, v20 + QPEL_FILTER_H v26, v6, v7, v31, v1, v2, v3, v4, v5 + QPEL_FILTER_H2 v27, v6, v7, v31, v1, v2, v3, v4, v5 + QPEL_UNI_W_HV_16 + subs w22, w22, #1 + b.eq 2f + + ldp q21, q6, [sp] + add sp, sp, x10 + QPEL_FILTER_H v24, v22, v23, v16, v17, v18, v19, v20, v21 + QPEL_FILTER_H2 v25, v22, v23, v16, v17, v18, v19, v20, v21 + QPEL_FILTER_H v26, v7, v31, v1, v2, v3, v4, v5, v6 + QPEL_FILTER_H2 v27, v7, v31, v1, v2, v3, v4, v5, v6 + QPEL_UNI_W_HV_16 + subs w22, w22, #1 + b.eq 2f + + ldp q22, q7, [sp] + add sp, sp, x10 + QPEL_FILTER_H v24, v23, v16, v17, v18, v19, v20, v21, v22 + QPEL_FILTER_H2 v25, v23, v16, v17, v18, v19, v20, v21, v22 + QPEL_FILTER_H v26, v31, v1, v2, v3, v4, v5, v6, v7 + QPEL_FILTER_H2 v27, v31, v1, v2, v3, v4, v5, v6, v7 + QPEL_UNI_W_HV_16 + subs w22, w22, #1 + b.hi 1b +2: + subs w27, w27, #16 + add sp, x11, #32 + add x20, x13, #16 + mov w22, w12 + mov x11, sp + mov x13, x20 + b.hi 3b + QPEL_UNI_W_HV_END + ret +endfunc + +function ff_hevc_put_hevc_qpel_uni_w_hv64_8_neon_i8mm, export=1 + QPEL_UNI_W_HV_HEADER 64 + mov x11, sp + mov w12, w22 + mov x13, x20 +3: + ldp q16, q1, [sp] + add sp, sp, x10 + ldp q17, q2, [sp] + add sp, sp, x10 + ldp q18, q3, [sp] + add sp, sp, x10 + ldp q19, q4, [sp] + add sp, sp, x10 + ldp q20, q5, [sp] + add sp, sp, x10 + ldp q21, q6, [sp] + add sp, sp, x10 + ldp q22, q7, [sp] + add sp, sp, x10 +1: + ldp q23, q31, [sp] + add sp, sp, x10 + QPEL_FILTER_H v24, v16, v17, v18, v19, v20, v21, v22, v23 + QPEL_FILTER_H2 v25, v16, v17, v18, v19, v20, v21, v22, v23 + QPEL_FILTER_H v26, v1, v2, v3, v4, v5, v6, v7, v31 + QPEL_FILTER_H2 v27, v1, v2, v3, v4, v5, v6, v7, v31 + QPEL_UNI_W_HV_16 + subs w22, w22, #1 + b.eq 2f + + ldp q16, q1, [sp] + add sp, sp, x10 + QPEL_FILTER_H v24, v17, v18, v19, v20, v21, v22, v23, v16 + QPEL_FILTER_H2 v25, v17, v18, v19, v20, v21, v22, v23, v16 + QPEL_FILTER_H v26, v2, v3, v4, v5, v6, v7, v31, v1 + QPEL_FILTER_H2 v27, v2, v3, v4, v5, v6, v7, v31, v1 + QPEL_UNI_W_HV_16 + subs w22, w22, #1 + b.eq 2f + + ldp q17, q2, [sp] + add sp, sp, x10 + QPEL_FILTER_H v24, v18, v19, v20, v21, v22, v23, v16, v17 + QPEL_FILTER_H2 v25, v18, v19, v20, v21, v22, v23, v16, v17 + QPEL_FILTER_H v26, v3, v4, v5, v6, v7, v31, v1, v2 + QPEL_FILTER_H2 v27, v3, v4, v5, v6, v7, v31, v1, v2 + QPEL_UNI_W_HV_16 + subs w22, w22, #1 + b.eq 2f + + ldp q18, q3, [sp] + add sp, sp, x10 + QPEL_FILTER_H v24, v19, v20, v21, v22, v23, v16, v17, v18 + QPEL_FILTER_H2 v25, v19, v20, v21, v22, v23, v16, v17, v18 + QPEL_FILTER_H v26, v4, v5, v6, v7, v31, v1, v2, v3 + QPEL_FILTER_H2 v27, v4, v5, v6, v7, v31, v1, v2, v3 + QPEL_UNI_W_HV_16 + subs w22, w22, #1 + b.eq 2f + + ldp q19, q4, [sp] + add sp, sp, x10 + QPEL_FILTER_H v24, v20, v21, v22, v23, v16, v17, v18, v19 + QPEL_FILTER_H2 v25, v20, v21, v22, v23, v16, v17, v18, v19 + QPEL_FILTER_H v26, v5, v6, v7, v31, v1, v2, v3, v4 + QPEL_FILTER_H2 v27, v5, v6, v7, v31, v1, v2, v3, v4 + QPEL_UNI_W_HV_16 + subs w22, w22, #1 + b.eq 2f + + ldp q20, q5, [sp] + add sp, sp, x10 + QPEL_FILTER_H v24, v21, v22, v23, v16, v17, v18, v19, v20 + QPEL_FILTER_H2 v25, v21, v22, v23, v16, v17, v18, v19, v20 + QPEL_FILTER_H v26, v6, v7, v31, v1, v2, v3, v4, v5 + QPEL_FILTER_H2 v27, v6, v7, v31, v1, v2, v3, v4, v5 + QPEL_UNI_W_HV_16 + subs w22, w22, #1 + b.eq 2f + + ldp q21, q6, [sp] + add sp, sp, x10 + QPEL_FILTER_H v24, v22, v23, v16, v17, v18, v19, v20, v21 + QPEL_FILTER_H2 v25, v22, v23, v16, v17, v18, v19, v20, v21 + QPEL_FILTER_H v26, v7, v31, v1, v2, v3, v4, v5, v6 + QPEL_FILTER_H2 v27, v7, v31, v1, v2, v3, v4, v5, v6 + QPEL_UNI_W_HV_16 + subs w22, w22, #1 + b.eq 2f + + ldp q22, q7, [sp] + add sp, sp, x10 + QPEL_FILTER_H v24, v23, v16, v17, v18, v19, v20, v21, v22 + QPEL_FILTER_H2 v25, v23, v16, v17, v18, v19, v20, v21, v22 + QPEL_FILTER_H v26, v31, v1, v2, v3, v4, v5, v6, v7 + QPEL_FILTER_H2 v27, v31, v1, v2, v3, v4, v5, v6, v7 + QPEL_UNI_W_HV_16 + subs w22, w22, #1 + b.hi 1b +2: + subs w27, w27, #16 + add sp, x11, #32 + add x20, x13, #16 + mov w22, w12 + mov x11, sp + mov x13, x20 + b.hi 3b + QPEL_UNI_W_HV_END + ret +endfunc + #endif // HAVE_I8MM From 65a1e8ee2c4a9c2f325e1921daab915689d9c9fd Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Tue, 6 Jun 2023 17:23:32 +1000 Subject: [PATCH 1425/2172] vulkan/hevc: fix scaling lists sizes. --- libavcodec/vulkan_hevc.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/libavcodec/vulkan_hevc.c b/libavcodec/vulkan_hevc.c index c242370f33d..c9b6888410b 100644 --- a/libavcodec/vulkan_hevc.c +++ b/libavcodec/vulkan_hevc.c @@ -228,17 +228,17 @@ static void set_sps(const HEVCSPS *sps, int sps_idx, for (int i = 0; i < STD_VIDEO_H265_SCALING_LIST_16X16_NUM_LISTS; i++) memcpy(vksps_scaling->ScalingList16x16[i], sps->scaling_list.sl[2][i], - STD_VIDEO_H265_SCALING_LIST_4X4_NUM_ELEMENTS * sizeof(**vksps_scaling->ScalingList16x16)); + STD_VIDEO_H265_SCALING_LIST_16X16_NUM_ELEMENTS * sizeof(**vksps_scaling->ScalingList16x16)); for (int i = 0; i < STD_VIDEO_H265_SCALING_LIST_32X32_NUM_LISTS; i++) memcpy(vksps_scaling->ScalingList32x32[i], sps->scaling_list.sl[3][i], STD_VIDEO_H265_SCALING_LIST_32X32_NUM_ELEMENTS * sizeof(**vksps_scaling->ScalingList32x32)); memcpy(vksps_scaling->ScalingListDCCoef16x16, sps->scaling_list.sl_dc[0], - STD_VIDEO_H265_SCALING_LIST_4X4_NUM_ELEMENTS * sizeof(*vksps_scaling->ScalingListDCCoef16x16)); + STD_VIDEO_H265_SCALING_LIST_16X16_NUM_LISTS * sizeof(*vksps_scaling->ScalingListDCCoef16x16)); memcpy(vksps_scaling->ScalingListDCCoef32x32, sps->scaling_list.sl_dc[1], - STD_VIDEO_H265_SCALING_LIST_32X32_NUM_ELEMENTS * sizeof(*vksps_scaling->ScalingListDCCoef32x32)); + STD_VIDEO_H265_SCALING_LIST_32X32_NUM_LISTS * sizeof(*vksps_scaling->ScalingListDCCoef32x32)); *vksps_vui_header = (StdVideoH265HrdParameters) { .flags = (StdVideoH265HrdFlags) { @@ -474,17 +474,17 @@ static void set_pps(const HEVCPPS *pps, const HEVCSPS *sps, for (int i = 0; i < STD_VIDEO_H265_SCALING_LIST_16X16_NUM_LISTS; i++) memcpy(vkpps_scaling->ScalingList16x16[i], pps->scaling_list.sl[2][i], - STD_VIDEO_H265_SCALING_LIST_4X4_NUM_ELEMENTS * sizeof(**vkpps_scaling->ScalingList16x16)); + STD_VIDEO_H265_SCALING_LIST_16X16_NUM_ELEMENTS * sizeof(**vkpps_scaling->ScalingList16x16)); for (int i = 0; i < STD_VIDEO_H265_SCALING_LIST_32X32_NUM_LISTS; i++) memcpy(vkpps_scaling->ScalingList32x32[i], pps->scaling_list.sl[3][i], STD_VIDEO_H265_SCALING_LIST_32X32_NUM_ELEMENTS * sizeof(**vkpps_scaling->ScalingList32x32)); memcpy(vkpps_scaling->ScalingListDCCoef16x16, pps->scaling_list.sl_dc[0], - STD_VIDEO_H265_SCALING_LIST_4X4_NUM_ELEMENTS * sizeof(*vkpps_scaling->ScalingListDCCoef16x16)); + STD_VIDEO_H265_SCALING_LIST_16X16_NUM_LISTS * sizeof(*vkpps_scaling->ScalingListDCCoef16x16)); memcpy(vkpps_scaling->ScalingListDCCoef32x32, pps->scaling_list.sl_dc[1], - STD_VIDEO_H265_SCALING_LIST_32X32_NUM_ELEMENTS * sizeof(*vkpps_scaling->ScalingListDCCoef32x32)); + STD_VIDEO_H265_SCALING_LIST_32X32_NUM_LISTS * sizeof(*vkpps_scaling->ScalingListDCCoef32x32)); *vkpps = (StdVideoH265PictureParameterSet) { .flags = (StdVideoH265PpsFlags) { From da61ed80fd94c29f9caf16a0e64b86fe34ab72e7 Mon Sep 17 00:00:00 2001 From: James Almer Date: Fri, 2 Jun 2023 20:22:10 -0300 Subject: [PATCH 1426/2172] avformat/av1dec: fix EOF check in Annex-B demuxer And return any packet buffered by the bsf. Signed-off-by: James Almer --- libavformat/av1dec.c | 33 ++++++++++++++++++++------------- 1 file changed, 20 insertions(+), 13 deletions(-) diff --git a/libavformat/av1dec.c b/libavformat/av1dec.c index 216d4e22983..79ad8a94114 100644 --- a/libavformat/av1dec.c +++ b/libavformat/av1dec.c @@ -124,13 +124,17 @@ static const AVClass av1_demuxer_class = { #if CONFIG_AV1_DEMUXER -static int leb(AVIOContext *pb, uint32_t *len) { +static int leb(AVIOContext *pb, uint32_t *len, int eof) { int more, i = 0; uint8_t byte; *len = 0; do { unsigned bits; byte = avio_r8(pb); + if (pb->error) + return pb->error; + if (pb->eof_reached) + return (eof && !i) ? AVERROR_EOF : AVERROR(EIO); more = byte & 0x80; bits = byte & 0x7f; if (i <= 3 || (i == 4 && bits < (1 << 4))) @@ -139,8 +143,6 @@ static int leb(AVIOContext *pb, uint32_t *len) { return AVERROR_INVALIDDATA; if (++i == 8 && more) return AVERROR_INVALIDDATA; - if (pb->eof_reached || pb->error) - return pb->error ? pb->error : AVERROR(EIO); } while (more); return i; } @@ -170,15 +172,15 @@ static int annexb_probe(const AVProbeData *p) ffio_init_context(&ctx, p->buf, p->buf_size, 0, NULL, NULL, NULL, NULL); - ret = leb(pb, &temporal_unit_size); + ret = leb(pb, &temporal_unit_size, 1); if (ret < 0) return 0; cnt += ret; - ret = leb(pb, &frame_unit_size); + ret = leb(pb, &frame_unit_size, 0); if (ret < 0 || ((int64_t)frame_unit_size + ret) > temporal_unit_size) return 0; cnt += ret; - ret = leb(pb, &obu_unit_size); + ret = leb(pb, &obu_unit_size, 0); if (ret < 0 || ((int64_t)obu_unit_size + ret) >= frame_unit_size) return 0; cnt += ret; @@ -196,7 +198,7 @@ static int annexb_probe(const AVProbeData *p) cnt += obu_unit_size; do { - ret = leb(pb, &obu_unit_size); + ret = leb(pb, &obu_unit_size, 0); if (ret < 0 || ((int64_t)obu_unit_size + ret) > frame_unit_size) return 0; cnt += ret; @@ -234,19 +236,24 @@ static int annexb_read_packet(AVFormatContext *s, AVPacket *pkt) } if (!c->temporal_unit_size) { - len = leb(s->pb, &c->temporal_unit_size); - if (len < 0) return AVERROR_INVALIDDATA; + len = leb(s->pb, &c->temporal_unit_size, 1); + if (len == AVERROR_EOF) goto end; + else if (len < 0) return len; } if (!c->frame_unit_size) { - len = leb(s->pb, &c->frame_unit_size); - if (len < 0 || ((int64_t)c->frame_unit_size + len) > c->temporal_unit_size) + len = leb(s->pb, &c->frame_unit_size, 0); + if (len < 0) + return len; + if (((int64_t)c->frame_unit_size + len) > c->temporal_unit_size) return AVERROR_INVALIDDATA; c->temporal_unit_size -= len; } - len = leb(s->pb, &obu_unit_size); - if (len < 0 || ((int64_t)obu_unit_size + len) > c->frame_unit_size) + len = leb(s->pb, &obu_unit_size, 0); + if (len < 0) + return len; + if (((int64_t)obu_unit_size + len) > c->frame_unit_size) return AVERROR_INVALIDDATA; ret = av_get_packet(s->pb, pkt, obu_unit_size); From a5e45988ac6970ef43240b85b5d775f3e25d3156 Mon Sep 17 00:00:00 2001 From: James Almer Date: Sat, 3 Jun 2023 10:20:59 -0300 Subject: [PATCH 1427/2172] avformat/av1dec: don't return EIO when the input file is truncated There was no problem reading the file, so EIO is not correct. Signed-off-by: James Almer --- libavformat/av1dec.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/libavformat/av1dec.c b/libavformat/av1dec.c index 79ad8a94114..501b0cc93f7 100644 --- a/libavformat/av1dec.c +++ b/libavformat/av1dec.c @@ -134,7 +134,7 @@ static int leb(AVIOContext *pb, uint32_t *len, int eof) { if (pb->error) return pb->error; if (pb->eof_reached) - return (eof && !i) ? AVERROR_EOF : AVERROR(EIO); + return (eof && !i) ? AVERROR_EOF : AVERROR_INVALIDDATA; more = byte & 0x80; bits = byte & 0x7f; if (i <= 3 || (i == 4 && bits < (1 << 4))) @@ -231,7 +231,7 @@ static int annexb_read_packet(AVFormatContext *s, AVPacket *pkt) retry: if (avio_feof(s->pb)) { if (c->temporal_unit_size || c->frame_unit_size) - return AVERROR(EIO); + return AVERROR_INVALIDDATA; goto end; } @@ -260,7 +260,7 @@ static int annexb_read_packet(AVFormatContext *s, AVPacket *pkt) if (ret < 0) return ret; if (ret != obu_unit_size) - return AVERROR(EIO); + return AVERROR_INVALIDDATA; c->temporal_unit_size -= obu_unit_size + len; c->frame_unit_size -= obu_unit_size + len; From 20584cdd89063dca4cddc9eac998aaf9291a9d80 Mon Sep 17 00:00:00 2001 From: James Almer Date: Sat, 3 Jun 2023 11:23:31 -0300 Subject: [PATCH 1428/2172] avformat/av1: reduce the scope of a variable Signed-off-by: James Almer --- libavformat/av1dec.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/libavformat/av1dec.c b/libavformat/av1dec.c index 501b0cc93f7..d0d53f41f74 100644 --- a/libavformat/av1dec.c +++ b/libavformat/av1dec.c @@ -126,11 +126,10 @@ static const AVClass av1_demuxer_class = { static int leb(AVIOContext *pb, uint32_t *len, int eof) { int more, i = 0; - uint8_t byte; *len = 0; do { unsigned bits; - byte = avio_r8(pb); + int byte = avio_r8(pb); if (pb->error) return pb->error; if (pb->eof_reached) From 402d98c9d467dff6931d906ebb732b9a00334e0b Mon Sep 17 00:00:00 2001 From: Roman Arzumanyan Date: Thu, 1 Jun 2023 11:17:39 +0300 Subject: [PATCH 1429/2172] libavcodec/cuviddec: determine amount of decoded surfaces from within cuvid parser Signed-off-by: Timo Rothenpieler --- libavcodec/cuviddec.c | 34 ++++++++++++++++++++++++++++++++-- 1 file changed, 32 insertions(+), 2 deletions(-) diff --git a/libavcodec/cuviddec.c b/libavcodec/cuviddec.c index 3d43bbd466b..814bc53f70f 100644 --- a/libavcodec/cuviddec.c +++ b/libavcodec/cuviddec.c @@ -115,6 +115,12 @@ typedef struct CuvidParsedFrame #define CHECK_CU(x) FF_CUDA_CHECK_DL(avctx, ctx->cudl, x) +// NV recommends [2;4] range +#define CUVID_MAX_DISPLAY_DELAY (4) + +// Actual pool size will be determined by parser. +#define CUVID_DEFAULT_NUM_SURFACES (CUVID_MAX_DISPLAY_DELAY + 1) + static int CUDAAPI cuvid_handle_video_sequence(void *opaque, CUVIDEOFORMAT* format) { AVCodecContext *avctx = opaque; @@ -124,6 +130,7 @@ static int CUDAAPI cuvid_handle_video_sequence(void *opaque, CUVIDEOFORMAT* form CUVIDDECODECREATEINFO cuinfo; int surface_fmt; int chroma_444; + int fifo_size_inc; int old_width = avctx->width; int old_height = avctx->height; @@ -309,6 +316,25 @@ static int CUDAAPI cuvid_handle_video_sequence(void *opaque, CUVIDEOFORMAT* form return 0; } + fifo_size_inc = ctx->nb_surfaces; + ctx->nb_surfaces = FFMAX(ctx->nb_surfaces, format->min_num_decode_surfaces + 3); + + if (avctx->extra_hw_frames > 0) + ctx->nb_surfaces += avctx->extra_hw_frames; + + fifo_size_inc = ctx->nb_surfaces - fifo_size_inc; + if (fifo_size_inc > 0 && av_fifo_grow2(ctx->frame_queue, fifo_size_inc) < 0) { + av_log(avctx, AV_LOG_ERROR, "Failed to grow frame queue on video sequence callback\n"); + ctx->internal_error = AVERROR(ENOMEM); + return 0; + } + + if (fifo_size_inc > 0 && av_reallocp_array(&ctx->key_frame, ctx->nb_surfaces, sizeof(int)) < 0) { + av_log(avctx, AV_LOG_ERROR, "Failed to grow key frame array on video sequence callback\n"); + ctx->internal_error = AVERROR(ENOMEM); + return 0; + } + cuinfo.ulNumDecodeSurfaces = ctx->nb_surfaces; cuinfo.ulNumOutputSurfaces = 1; cuinfo.ulCreationFlags = cudaVideoCreate_PreferCUVID; @@ -846,6 +872,10 @@ static av_cold int cuvid_decode_init(AVCodecContext *avctx) goto error; } + // respect the deprecated "surfaces" option if non-default value is given by user; + if(ctx->nb_surfaces < 0) + ctx->nb_surfaces = CUVID_DEFAULT_NUM_SURFACES; + ctx->frame_queue = av_fifo_alloc2(ctx->nb_surfaces, sizeof(CuvidParsedFrame), 0); if (!ctx->frame_queue) { ret = AVERROR(ENOMEM); @@ -993,7 +1023,7 @@ static av_cold int cuvid_decode_init(AVCodecContext *avctx) } ctx->cuparseinfo.ulMaxNumDecodeSurfaces = ctx->nb_surfaces; - ctx->cuparseinfo.ulMaxDisplayDelay = (avctx->flags & AV_CODEC_FLAG_LOW_DELAY) ? 0 : 4; + ctx->cuparseinfo.ulMaxDisplayDelay = (avctx->flags & AV_CODEC_FLAG_LOW_DELAY) ? 0 : CUVID_MAX_DISPLAY_DELAY; ctx->cuparseinfo.pUserData = avctx; ctx->cuparseinfo.pfnSequenceCallback = cuvid_handle_video_sequence; ctx->cuparseinfo.pfnDecodePicture = cuvid_handle_picture_decode; @@ -1097,7 +1127,7 @@ static const AVOption options[] = { { "bob", "Bob deinterlacing", 0, AV_OPT_TYPE_CONST, { .i64 = cudaVideoDeinterlaceMode_Bob }, 0, 0, VD, "deint" }, { "adaptive", "Adaptive deinterlacing", 0, AV_OPT_TYPE_CONST, { .i64 = cudaVideoDeinterlaceMode_Adaptive }, 0, 0, VD, "deint" }, { "gpu", "GPU to be used for decoding", OFFSET(cu_gpu), AV_OPT_TYPE_STRING, { .str = NULL }, 0, 0, VD }, - { "surfaces", "Maximum surfaces to be used for decoding", OFFSET(nb_surfaces), AV_OPT_TYPE_INT, { .i64 = 25 }, 0, INT_MAX, VD }, + { "surfaces", "Maximum surfaces to be used for decoding", OFFSET(nb_surfaces), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, INT_MAX, VD | AV_OPT_FLAG_DEPRECATED }, { "drop_second_field", "Drop second field when deinterlacing", OFFSET(drop_second_field), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, VD }, { "crop", "Crop (top)x(bottom)x(left)x(right)", OFFSET(crop_expr), AV_OPT_TYPE_STRING, { .str = NULL }, 0, 0, VD }, { "resize", "Resize (width)x(height)", OFFSET(resize_expr), AV_OPT_TYPE_STRING, { .str = NULL }, 0, 0, VD }, From 8d5de4e12f1554575d7cddf7438e36aff352e197 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Sun, 8 Jan 2023 13:52:19 +0100 Subject: [PATCH 1430/2172] tools/target_dec_fuzzer: Test lowres Signed-off-by: Michael Niedermayer --- tools/target_dec_fuzzer.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/tools/target_dec_fuzzer.c b/tools/target_dec_fuzzer.c index d8e93f3a211..42de479829b 100644 --- a/tools/target_dec_fuzzer.c +++ b/tools/target_dec_fuzzer.c @@ -428,6 +428,10 @@ int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { ctx->workaround_bugs = bytestream2_get_le32(&gbc); + if (c->p.max_lowres) { + ctx->lowres = bytestream2_get_byte(&gbc) % (c->p.max_lowres+1); + } + if (extradata_size < size) { ctx->extradata = av_mallocz(extradata_size + AV_INPUT_BUFFER_PADDING_SIZE); if (ctx->extradata) { From 0889ebc577749ee6abc620bc9030d2002487935f Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Sun, 4 Jun 2023 19:59:40 +0200 Subject: [PATCH 1431/2172] avcodec/noise_bsf: Check for wrapped frames Wrapped frames contain pointers so they need specific code to noise them, the generic code would lead to segfaults Signed-off-by: Michael Niedermayer --- libavcodec/noise_bsf.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/libavcodec/noise_bsf.c b/libavcodec/noise_bsf.c index 168f3aa3735..7bdaa3c1db6 100644 --- a/libavcodec/noise_bsf.c +++ b/libavcodec/noise_bsf.c @@ -86,6 +86,12 @@ static int noise_init(AVBSFContext *ctx) return AVERROR(ENOMEM); } + if (ctx->par_in->codec_id == AV_CODEC_ID_WRAPPED_AVFRAME && + strcmp(s->amount_str, "0")) { + av_log(ctx, AV_LOG_ERROR, "Wrapped AVFrame noising is unsupported\n"); + return AVERROR_PATCHWELCOME; + } + ret = av_expr_parse(&s->amount_pexpr, s->amount_str, var_names, NULL, NULL, NULL, NULL, 0, ctx); if (ret < 0) { From e62824835d6871de5f1658afa840eb58425e34d4 Mon Sep 17 00:00:00 2001 From: Marvin Scholz Date: Fri, 2 Jun 2023 22:12:26 +0200 Subject: [PATCH 1432/2172] lavfi/vf_xfade: rewrite activate inputs handling The old code was not properly handling a bunch of edge-cases with streams terminating earlier and also did not properly report back EOF to the first input. This fixes at least one case where the filter could stop doing anything: ffmpeg -f lavfi -i "color=blue:d=10" -f lavfi -i "color=aqua:d=0" -filter_complex "[0][1]xfade=duration=2:offset=0:transition=wiperight" -f null - --- libavfilter/vf_xfade.c | 212 ++++++++++++++++++++++++----------------- 1 file changed, 124 insertions(+), 88 deletions(-) diff --git a/libavfilter/vf_xfade.c b/libavfilter/vf_xfade.c index a13a7db627e..92f5139ec53 100644 --- a/libavfilter/vf_xfade.c +++ b/libavfilter/vf_xfade.c @@ -95,14 +95,23 @@ typedef struct XFadeContext { int depth; int is_rgb; + // PTS when the fade should start (in first inputs timebase) + int64_t start_pts; + + // PTS offset between first and second input + int64_t inputs_offset_pts; + + // Duration of the transition int64_t duration_pts; - int64_t offset_pts; - int64_t first_pts; - int64_t last_pts; + + // Current PTS of the first input int64_t pts; - int xfade_is_over; - int need_second; - int eof[2]; + + // If frames are currently just passed through unmodified, + // like before and after the actual transition. + int passthrough; + + int status[2]; AVFrame *xf[2]; int max_value; uint16_t black[4]; @@ -1935,12 +1944,10 @@ static int config_output(AVFilterLink *outlink) s->white[0] = s->white[3] = s->max_value; s->white[1] = s->white[2] = s->is_rgb ? s->max_value : s->max_value / 2; - s->first_pts = s->last_pts = s->pts = AV_NOPTS_VALUE; + s->start_pts = s->inputs_offset_pts = AV_NOPTS_VALUE; if (s->duration) s->duration_pts = av_rescale_q(s->duration, AV_TIME_BASE_Q, outlink->time_base); - if (s->offset) - s->offset_pts = av_rescale_q(s->offset, AV_TIME_BASE_Q, outlink->time_base); switch (s->transition) { case CUSTOM: s->transitionf = s->depth <= 8 ? custom8_transition : custom16_transition; break; @@ -2037,7 +2044,7 @@ static int xfade_frame(AVFilterContext *ctx, AVFrame *a, AVFrame *b) { XFadeContext *s = ctx->priv; AVFilterLink *outlink = ctx->outputs[0]; - float progress = av_clipf(1.f - ((float)(s->pts - s->first_pts - s->offset_pts) / s->duration_pts), 0.f, 1.f); + float progress = av_clipf(1.f - ((float)(s->pts - s->start_pts) / s->duration_pts), 0.f, 1.f); ThreadData td; AVFrame *out; @@ -2055,99 +2062,128 @@ static int xfade_frame(AVFilterContext *ctx, AVFrame *a, AVFrame *b) return ff_filter_frame(outlink, out); } -static int xfade_activate(AVFilterContext *ctx) +static int forward_frame(XFadeContext *s, + AVFilterLink *inlink, AVFilterLink *outlink) { - XFadeContext *s = ctx->priv; - AVFilterLink *outlink = ctx->outputs[0]; - AVFrame *in = NULL; + int64_t status_pts; int ret = 0, status; - int64_t pts; + AVFrame *frame = NULL; - FF_FILTER_FORWARD_STATUS_BACK_ALL(outlink, ctx); + ret = ff_inlink_consume_frame(inlink, &frame); + if (ret < 0) + return ret; - if (s->xfade_is_over) { - if (!s->eof[0]) { - if (ff_inlink_queued_frames(ctx->inputs[0]) > 0) { - ret = ff_inlink_consume_frame(ctx->inputs[0], &in); - if (ret > 0) - av_frame_free(&in); - } - ff_inlink_set_status(ctx->inputs[0], AVERROR_EOF); - s->eof[0] = 1; - } - ret = ff_inlink_consume_frame(ctx->inputs[1], &in); - if (ret < 0) { - return ret; - } else if (ret > 0) { - in->pts = (in->pts - s->last_pts) + s->pts; - return ff_filter_frame(outlink, in); - } else if (ff_inlink_acknowledge_status(ctx->inputs[1], &status, &pts)) { - ff_outlink_set_status(outlink, status, s->pts); - return 0; - } else if (!ret) { - if (ff_outlink_frame_wanted(outlink)) - ff_inlink_request_frame(ctx->inputs[1]); - return 0; - } + if (ret > 0) { + // If we do not have an offset yet, it's because we + // never got a first input. Just offset to 0 + if (s->inputs_offset_pts == AV_NOPTS_VALUE) + s->inputs_offset_pts = -frame->pts; + + // We got a frame, nothing to do other than adjusting the timestamp + frame->pts += s->inputs_offset_pts; + return ff_filter_frame(outlink, frame); } - if (ff_inlink_queued_frames(ctx->inputs[0]) > 0) { - s->xf[0] = ff_inlink_peek_frame(ctx->inputs[0], 0); - if (s->xf[0]) { - if (s->first_pts == AV_NOPTS_VALUE) { - s->first_pts = s->xf[0]->pts; - } - s->pts = s->xf[0]->pts; - if (s->first_pts + s->offset_pts > s->xf[0]->pts) { - s->xf[0] = NULL; - s->need_second = 0; - ff_inlink_consume_frame(ctx->inputs[0], &in); - return ff_filter_frame(outlink, in); + // Forward status with our timestamp + if (ff_inlink_acknowledge_status(inlink, &status, &status_pts)) { + if (s->inputs_offset_pts == AV_NOPTS_VALUE) + s->inputs_offset_pts = -status_pts; + + ff_outlink_set_status(outlink, status, status_pts + s->inputs_offset_pts); + return 0; + } + + // No frame available, request one if needed + if (ff_outlink_frame_wanted(outlink)) + ff_inlink_request_frame(inlink); + + return 0; +} + +static int xfade_activate(AVFilterContext *avctx) +{ + XFadeContext *s = avctx->priv; + AVFilterLink *in_a = avctx->inputs[0]; + AVFilterLink *in_b = avctx->inputs[1]; + AVFilterLink *outlink = avctx->outputs[0]; + int64_t status_pts; + + FF_FILTER_FORWARD_STATUS_BACK_ALL(outlink, avctx); + + // Check if we already transitioned or first input ended prematurely, + // in which case just forward the frames from second input with adjusted + // timestamps until EOF. + if (s->status[0] && !s->status[1]) + return forward_frame(s, in_b, outlink); + + // We did not finish transitioning yet and the first stream + // did not end either, so check if there are more frames to consume. + if (ff_inlink_check_available_frame(in_a)) { + AVFrame *peeked_frame = ff_inlink_peek_frame(in_a, 0); + s->pts = peeked_frame->pts; + + if (s->start_pts == AV_NOPTS_VALUE) + s->start_pts = + s->pts + av_rescale_q(s->offset, AV_TIME_BASE_Q, in_a->time_base); + + // Check if we are not yet transitioning, in which case + // just request and forward the input frame. + if (s->start_pts > s->pts) { + s->passthrough = 1; + ff_inlink_consume_frame(in_a, &s->xf[0]); + return ff_filter_frame(outlink, s->xf[0]); + } + s->passthrough = 0; + + // We are transitioning, so we need a frame from second input + if (ff_inlink_check_available_frame(in_b)) { + int ret; + ff_inlink_consume_frame(avctx->inputs[0], &s->xf[0]); + ff_inlink_consume_frame(avctx->inputs[1], &s->xf[1]); + + // Calculate PTS offset to first input + if (s->inputs_offset_pts == AV_NOPTS_VALUE) + s->inputs_offset_pts = s->pts - s->xf[1]->pts; + + // Check if we finished transitioning, in which case we + // report back EOF to first input as it is no longer needed. + if (s->pts - s->start_pts > s->duration_pts) { + s->status[0] = AVERROR_EOF; + ff_inlink_set_status(in_a, AVERROR_EOF); + s->passthrough = 1; } + ret = xfade_frame(avctx, s->xf[0], s->xf[1]); + av_frame_free(&s->xf[0]); + av_frame_free(&s->xf[1]); + return ret; + } - s->need_second = 1; + // We did not get a frame from second input, check its status. + if (ff_inlink_acknowledge_status(in_b, &s->status[1], &status_pts)) { + // We should transition, but second input is EOF so just report EOF output now. + ff_outlink_set_status(outlink, s->status[1], s->pts); + return 0; } - } - if (s->xf[0] && ff_inlink_queued_frames(ctx->inputs[1]) > 0) { - ff_inlink_consume_frame(ctx->inputs[0], &s->xf[0]); - ff_inlink_consume_frame(ctx->inputs[1], &s->xf[1]); - - s->last_pts = s->xf[1]->pts; - s->pts = s->xf[0]->pts; - if (s->xf[0]->pts - (s->first_pts + s->offset_pts) > s->duration_pts) - s->xfade_is_over = 1; - ret = xfade_frame(ctx, s->xf[0], s->xf[1]); - av_frame_free(&s->xf[0]); - av_frame_free(&s->xf[1]); - return ret; + // We did not get a frame for second input but no EOF either, so just request more. + if (ff_outlink_frame_wanted(outlink)) { + ff_inlink_request_frame(in_b); + return 0; + } } - if (ff_inlink_queued_frames(ctx->inputs[0]) > 0 && - ff_inlink_queued_frames(ctx->inputs[1]) > 0) { - ff_filter_set_ready(ctx, 100); + // We did not get a frame from first input, check its status. + if (ff_inlink_acknowledge_status(in_a, &s->status[0], &status_pts)) { + // No more frames from first input, do not report EOF though, we will just + // forward the second input frames in the next activate calls. + s->passthrough = 1; + ff_filter_set_ready(avctx, 100); return 0; } + // We have no frames yet from first input and no EOF, so request some. if (ff_outlink_frame_wanted(outlink)) { - if (!s->eof[0] && ff_outlink_get_status(ctx->inputs[0])) { - s->eof[0] = 1; - s->xfade_is_over = 1; - } - if (!s->eof[1] && ff_outlink_get_status(ctx->inputs[1])) { - s->eof[1] = 1; - } - if (!s->eof[0] && !s->xf[0] && ff_inlink_queued_frames(ctx->inputs[0]) == 0) - ff_inlink_request_frame(ctx->inputs[0]); - if (!s->eof[1] && (s->need_second || s->eof[0]) && ff_inlink_queued_frames(ctx->inputs[1]) == 0) - ff_inlink_request_frame(ctx->inputs[1]); - if (s->eof[0] && s->eof[1] && ( - ff_inlink_queued_frames(ctx->inputs[0]) <= 0 && - ff_inlink_queued_frames(ctx->inputs[1]) <= 0)) { - ff_outlink_set_status(outlink, AVERROR_EOF, AV_NOPTS_VALUE); - } else if (s->xfade_is_over) { - ff_filter_set_ready(ctx, 100); - } + ff_inlink_request_frame(in_a); return 0; } @@ -2158,7 +2194,7 @@ static AVFrame *get_video_buffer(AVFilterLink *inlink, int w, int h) { XFadeContext *s = inlink->dst->priv; - return s->xfade_is_over || !s->need_second ? + return s->passthrough ? ff_null_get_video_buffer (inlink, w, h) : ff_default_get_video_buffer(inlink, w, h); } From f11515c77f0a2915b831d91f061fb11c4359601f Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Sat, 3 Jun 2023 12:29:25 +0200 Subject: [PATCH 1433/2172] avcodec: add RTV1 decoder --- Changelog | 1 + configure | 1 + libavcodec/Makefile | 1 + libavcodec/allcodecs.c | 1 + libavcodec/codec_desc.c | 7 ++ libavcodec/codec_id.h | 1 + libavcodec/rtv1.c | 148 ++++++++++++++++++++++++++++++++++++++++ libavcodec/version.h | 4 +- libavformat/riff.c | 1 + 9 files changed, 163 insertions(+), 2 deletions(-) create mode 100644 libavcodec/rtv1.c diff --git a/Changelog b/Changelog index 3d197f2b944..c7e71ecfd85 100644 --- a/Changelog +++ b/Changelog @@ -14,6 +14,7 @@ version : - color_vulkan filter - bwdif_vulkan filter - nlmeans_vulkan filter +- RivaTuner video decoder version 6.0: - Radiance HDR image support diff --git a/configure b/configure index 2992dae283e..7e68d56ab0c 100755 --- a/configure +++ b/configure @@ -2962,6 +2962,7 @@ ralf_decoder_select="golomb" rasc_decoder_select="inflate_wrapper" rawvideo_decoder_select="bswapdsp" rscc_decoder_deps="zlib" +rtv1_decoder_select="texturedsp" rv10_decoder_select="h263_decoder" rv10_encoder_select="h263_encoder" rv20_decoder_select="h263_decoder" diff --git a/libavcodec/Makefile b/libavcodec/Makefile index 9aacc1d4774..87a8b900374 100644 --- a/libavcodec/Makefile +++ b/libavcodec/Makefile @@ -643,6 +643,7 @@ OBJS-$(CONFIG_ROQ_DPCM_ENCODER) += roqaudioenc.o OBJS-$(CONFIG_RPZA_DECODER) += rpza.o OBJS-$(CONFIG_RPZA_ENCODER) += rpzaenc.o OBJS-$(CONFIG_RSCC_DECODER) += rscc.o +OBJS-$(CONFIG_RTV1_DECODER) += rtv1.o OBJS-$(CONFIG_RV10_DECODER) += rv10.o OBJS-$(CONFIG_RV10_ENCODER) += rv10enc.o OBJS-$(CONFIG_RV20_DECODER) += rv10.o diff --git a/libavcodec/allcodecs.c b/libavcodec/allcodecs.c index 184bb8521f0..a98c300da48 100644 --- a/libavcodec/allcodecs.c +++ b/libavcodec/allcodecs.c @@ -295,6 +295,7 @@ extern const FFCodec ff_roq_decoder; extern const FFCodec ff_rpza_encoder; extern const FFCodec ff_rpza_decoder; extern const FFCodec ff_rscc_decoder; +extern const FFCodec ff_rtv1_decoder; extern const FFCodec ff_rv10_encoder; extern const FFCodec ff_rv10_decoder; extern const FFCodec ff_rv20_encoder; diff --git a/libavcodec/codec_desc.c b/libavcodec/codec_desc.c index 310ed664158..41293a78dce 100644 --- a/libavcodec/codec_desc.c +++ b/libavcodec/codec_desc.c @@ -1946,6 +1946,13 @@ static const AVCodecDescriptor codec_descriptors[] = { .props = AV_CODEC_PROP_LOSSY | AV_CODEC_PROP_REORDER, .profiles = NULL_IF_CONFIG_SMALL(ff_evc_profiles), }, + { + .id = AV_CODEC_ID_RTV1, + .type = AVMEDIA_TYPE_VIDEO, + .name = "rtv1", + .long_name = NULL_IF_CONFIG_SMALL("RTV1 (RivaTuner Video)"), + .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSY, + }, /* various PCM "codecs" */ { diff --git a/libavcodec/codec_id.h b/libavcodec/codec_id.h index 9f621afff01..9a78cfabe2f 100644 --- a/libavcodec/codec_id.h +++ b/libavcodec/codec_id.h @@ -322,6 +322,7 @@ enum AVCodecID { AV_CODEC_ID_VQC, AV_CODEC_ID_PDV, AV_CODEC_ID_EVC, + AV_CODEC_ID_RTV1, /* various PCM "codecs" */ AV_CODEC_ID_FIRST_AUDIO = 0x10000, ///< A dummy id pointing at the start of audio codecs diff --git a/libavcodec/rtv1.c b/libavcodec/rtv1.c new file mode 100644 index 00000000000..4b202e6a214 --- /dev/null +++ b/libavcodec/rtv1.c @@ -0,0 +1,148 @@ +/* + * RTV1 decoder + * Copyright (c) 2023 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 "avcodec.h" +#include "bytestream.h" +#include "codec_internal.h" +#include "decode.h" +#include "texturedsp.h" +#include "thread.h" + +static av_cold int decode_init(AVCodecContext *avctx) +{ + TextureDSPContext *dsp = avctx->priv_data; + avctx->pix_fmt = AV_PIX_FMT_BGR0; + ff_texturedsp_init(dsp); + return 0; +} + +static int decode_rtv1(GetByteContext *gb, uint8_t *dst, ptrdiff_t linesize, + int width, int height, int flag, + int (*dxt1_block)(uint8_t *dst, ptrdiff_t stride, const uint8_t *block)) +{ + uint8_t block[8] = { 0 }; + int run = 0; + + for (int y = 0; y < height; y += 4) { + for (int x = 0; x < width * 4; x += 16) { + int mode = 0; + + if (run && --run > 0) { + dxt1_block(dst + x, linesize, block); + } else { + int a, b; + + if (bytestream2_get_bytes_left(gb) < 4) + break; + + a = bytestream2_get_le16u(gb); + b = bytestream2_get_le16u(gb); + if (a == b && flag) { + AV_WL32(block + 4, 0); + } else if (a == 1 && b == 0xffff) { + mode = 1; + } else if (b && a == 0) { + run = b; + } else { + AV_WL16(block, a); + AV_WL16(block + 2, b); + AV_WL32(block + 4, bytestream2_get_le32(gb)); + } + if (run && !mode) { + dxt1_block(dst + x, linesize, block); + } else if (!mode) { + AV_WL16(block, a); + AV_WL16(block + 2, b); + dxt1_block(dst + x, linesize, block); + } else { + if (bytestream2_get_bytes_left(gb) < 12 * 4) + break; + + for (int by = 0; by < 4; by++) { + for (int bx = 0; bx < 4; bx++) + AV_WL32(dst + x + bx * 4 + by * linesize, bytestream2_get_le24u(gb)); + } + } + } + } + + dst += linesize * 4; + } + + return 0; +} + +static int decode_frame(AVCodecContext *avctx, AVFrame *p, + int *got_frame, AVPacket *avpkt) +{ + int ret, width, height, flags; + TextureDSPContext *dsp = avctx->priv_data; + GetByteContext gb; + ptrdiff_t linesize; + uint8_t *dst; + + if (avpkt->size < 22) + return AVERROR_INVALIDDATA; + + bytestream2_init(&gb, avpkt->data, avpkt->size); + + if (bytestream2_get_le32(&gb) != MKTAG('D','X','T','1')) + return AVERROR_INVALIDDATA; + flags = bytestream2_get_le32(&gb); + + width = bytestream2_get_le32(&gb); + height = bytestream2_get_le32(&gb); + ret = ff_set_dimensions(avctx, FFALIGN(width, 4), FFALIGN(height, 4)); + if (ret < 0) + return ret; + + avctx->width = width; + avctx->height = height; + + if ((ret = ff_thread_get_buffer(avctx, p, 0)) < 0) + return ret; + + dst = p->data[0] + p->linesize[0] * (avctx->coded_height - 1); + linesize = -p->linesize[0]; + + decode_rtv1(&gb, dst, linesize, width, height, flags, dsp->dxt1_block); + + p->pict_type = AV_PICTURE_TYPE_I; + p->flags |= AV_FRAME_FLAG_KEY; + + *got_frame = 1; + + return avpkt->size; +} + +const FFCodec ff_rtv1_decoder = { + .p.name = "rtv1", + CODEC_LONG_NAME("RTV1 (RivaTuner Video)"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_RTV1, + .priv_data_size = sizeof(TextureDSPContext), + .init = decode_init, + FF_CODEC_DECODE_CB(decode_frame), + .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_FRAME_THREADS, +}; diff --git a/libavcodec/version.h b/libavcodec/version.h index 9d0485b068c..2618016a835 100644 --- a/libavcodec/version.h +++ b/libavcodec/version.h @@ -29,8 +29,8 @@ #include "version_major.h" -#define LIBAVCODEC_VERSION_MINOR 16 -#define LIBAVCODEC_VERSION_MICRO 101 +#define LIBAVCODEC_VERSION_MINOR 17 +#define LIBAVCODEC_VERSION_MICRO 100 #define LIBAVCODEC_VERSION_INT AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \ LIBAVCODEC_VERSION_MINOR, \ diff --git a/libavformat/riff.c b/libavformat/riff.c index 7319406b395..42790711599 100644 --- a/libavformat/riff.c +++ b/libavformat/riff.c @@ -501,6 +501,7 @@ const AVCodecTag ff_codec_bmp_tags[] = { { AV_CODEC_ID_NOTCHLC, MKTAG('n', 'l', 'c', '1') }, { AV_CODEC_ID_VQC, MKTAG('V', 'Q', 'C', '1') }, { AV_CODEC_ID_VQC, MKTAG('V', 'Q', 'C', '2') }, + { AV_CODEC_ID_RTV1, MKTAG('R', 'T', 'V', '1') }, { AV_CODEC_ID_NONE, 0 } }; From dae393fe724ab3c18f9d048013a1457cb06d4264 Mon Sep 17 00:00:00 2001 From: Marvin Scholz Date: Wed, 7 Jun 2023 00:22:59 +0200 Subject: [PATCH 1434/2172] libavfilter: add vf_xfade_vulkan This is an initial version of vf_xfade_vulkan based on vf_xfade_opencl, for now only a subset of transitions are supported. --- Changelog | 1 + configure | 1 + libavfilter/Makefile | 1 + libavfilter/allfilters.c | 1 + libavfilter/vf_xfade_vulkan.c | 584 ++++++++++++++++++++++++++++++++++ 5 files changed, 588 insertions(+) create mode 100644 libavfilter/vf_xfade_vulkan.c diff --git a/Changelog b/Changelog index c7e71ecfd85..d51e03b8ebb 100644 --- a/Changelog +++ b/Changelog @@ -15,6 +15,7 @@ version : - bwdif_vulkan filter - nlmeans_vulkan filter - RivaTuner video decoder +- xfade_vulkan filter version 6.0: - Radiance HDR image support diff --git a/configure b/configure index 7e68d56ab0c..0a7efb242b7 100755 --- a/configure +++ b/configure @@ -3825,6 +3825,7 @@ scale_vulkan_filter_deps="vulkan spirv_compiler" vpp_qsv_filter_deps="libmfx" vpp_qsv_filter_select="qsvvpp" xfade_opencl_filter_deps="opencl" +xfade_vulkan_filter_deps="vulkan spirv_compiler" yadif_cuda_filter_deps="ffnvcodec" yadif_cuda_filter_deps_any="cuda_nvcc cuda_llvm" yadif_videotoolbox_filter_deps="metal corevideo videotoolbox" diff --git a/libavfilter/Makefile b/libavfilter/Makefile index 18935b16169..ff149a3733a 100644 --- a/libavfilter/Makefile +++ b/libavfilter/Makefile @@ -552,6 +552,7 @@ OBJS-$(CONFIG_XBR_FILTER) += vf_xbr.o OBJS-$(CONFIG_XCORRELATE_FILTER) += vf_convolve.o framesync.o OBJS-$(CONFIG_XFADE_FILTER) += vf_xfade.o OBJS-$(CONFIG_XFADE_OPENCL_FILTER) += vf_xfade_opencl.o opencl.o opencl/xfade.o +OBJS-$(CONFIG_XFADE_VULKAN_FILTER) += vf_xfade_vulkan.o vulkan.o vulkan_filter.o OBJS-$(CONFIG_XMEDIAN_FILTER) += vf_xmedian.o framesync.o OBJS-$(CONFIG_XSTACK_FILTER) += vf_stack.o framesync.o OBJS-$(CONFIG_YADIF_FILTER) += vf_yadif.o yadif_common.o diff --git a/libavfilter/allfilters.c b/libavfilter/allfilters.c index f1f781101be..6593e4eb839 100644 --- a/libavfilter/allfilters.c +++ b/libavfilter/allfilters.c @@ -519,6 +519,7 @@ extern const AVFilter ff_vf_xbr; extern const AVFilter ff_vf_xcorrelate; extern const AVFilter ff_vf_xfade; extern const AVFilter ff_vf_xfade_opencl; +extern const AVFilter ff_vf_xfade_vulkan; extern const AVFilter ff_vf_xmedian; extern const AVFilter ff_vf_xstack; extern const AVFilter ff_vf_yadif; diff --git a/libavfilter/vf_xfade_vulkan.c b/libavfilter/vf_xfade_vulkan.c new file mode 100644 index 00000000000..8825717890f --- /dev/null +++ b/libavfilter/vf_xfade_vulkan.c @@ -0,0 +1,584 @@ +/* + * 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/avassert.h" +#include "libavutil/random_seed.h" +#include "libavutil/opt.h" +#include "vulkan_filter.h" +#include "vulkan_spirv.h" +#include "filters.h" +#include "internal.h" + +#define IN_A 0 +#define IN_B 1 +#define IN_NB 2 + +typedef struct XFadeParameters { + float progress; +} XFadeParameters; + +typedef struct XFadeVulkanContext { + FFVulkanContext vkctx; + + int transition; + int64_t duration; + int64_t offset; + + int initialized; + FFVulkanPipeline pl; + FFVkExecPool e; + FFVkQueueFamilyCtx qf; + FFVkSPIRVShader shd; + VkSampler sampler; + + // PTS when the fade should start (in IN_A timebase) + int64_t start_pts; + + // PTS offset between IN_A and IN_B + int64_t inputs_offset_pts; + + // Duration of the transition + int64_t duration_pts; + + // Current PTS of the first input (IN_A) + int64_t pts; + + // If frames are currently just passed through + // unmodified, like before and after the actual + // transition. + int passthrough; + + int status[IN_NB]; +} XFadeVulkanContext; + +enum XFadeTransitions { + FADE, + WIPELEFT, + WIPERIGHT, + WIPEUP, + WIPEDOWN, + SLIDEDOWN, + SLIDEUP, + SLIDELEFT, + SLIDERIGHT, + NB_TRANSITIONS, +}; + +static const char transition_fade[] = { + C(0, void transition(int idx, ivec2 pos, float progress) ) + C(0, { ) + C(1, vec4 a = texture(a_images[idx], pos); ) + C(1, vec4 b = texture(b_images[idx], pos); ) + C(1, imageStore(output_images[idx], pos, mix(a, b, progress)); ) + C(0, } ) +}; + +static const char transition_wipeleft[] = { + C(0, void transition(int idx, ivec2 pos, float progress) ) + C(0, { ) + C(1, ivec2 size = imageSize(output_images[idx]); ) + C(1, int s = int(size.x * (1.0 - progress)); ) + C(1, vec4 a = texture(a_images[idx], pos); ) + C(1, vec4 b = texture(b_images[idx], pos); ) + C(1, imageStore(output_images[idx], pos, pos.x > s ? b : a); ) + C(0, } ) +}; + +static const char transition_wiperight[] = { + C(0, void transition(int idx, ivec2 pos, float progress) ) + C(0, { ) + C(1, ivec2 size = imageSize(output_images[idx]); ) + C(1, int s = int(size.x * progress); ) + C(1, vec4 a = texture(a_images[idx], pos); ) + C(1, vec4 b = texture(b_images[idx], pos); ) + C(1, imageStore(output_images[idx], pos, pos.x > s ? a : b); ) + C(0, } ) +}; + +static const char transition_wipeup[] = { + C(0, void transition(int idx, ivec2 pos, float progress) ) + C(0, { ) + C(1, ivec2 size = imageSize(output_images[idx]); ) + C(1, int s = int(size.y * (1.0 - progress)); ) + C(1, vec4 a = texture(a_images[idx], pos); ) + C(1, vec4 b = texture(b_images[idx], pos); ) + C(1, imageStore(output_images[idx], pos, pos.y > s ? b : a); ) + C(0, } ) +}; + +static const char transition_wipedown[] = { + C(0, void transition(int idx, ivec2 pos, float progress) ) + C(0, { ) + C(1, ivec2 size = imageSize(output_images[idx]); ) + C(1, int s = int(size.y * progress); ) + C(1, vec4 a = texture(a_images[idx], pos); ) + C(1, vec4 b = texture(b_images[idx], pos); ) + C(1, imageStore(output_images[idx], pos, pos.y > s ? a : b); ) + C(0, } ) +}; + +#define SHADER_SLIDE_COMMON \ + C(0, void slide(int idx, ivec2 pos, float progress, ivec2 direction) ) \ + C(0, { ) \ + C(1, ivec2 size = imageSize(output_images[idx]); ) \ + C(1, ivec2 pi = ivec2(progress * size); ) \ + C(1, ivec2 p = pos + pi * direction; ) \ + C(1, ivec2 f = p % size; ) \ + C(1, f = f + size * ivec2(f.x < 0, f.y < 0); ) \ + C(1, vec4 a = texture(a_images[idx], f); ) \ + C(1, vec4 b = texture(b_images[idx], f); ) \ + C(1, vec4 r = (p.y >= 0 && p.x >= 0 && size.y > p.y && size.x > p.x) ? a : b; ) \ + C(1, imageStore(output_images[idx], pos, r); ) \ + C(0, } ) + +static const char transition_slidedown[] = { + SHADER_SLIDE_COMMON + C(0, void transition(int idx, ivec2 pos, float progress) ) + C(0, { ) + C(1, slide(idx, pos, progress, ivec2(0, -1)); ) + C(0, } ) +}; + +static const char transition_slideup[] = { + SHADER_SLIDE_COMMON + C(0, void transition(int idx, ivec2 pos, float progress) ) + C(0, { ) + C(1, slide(idx, pos, progress, ivec2(0, +1)); ) + C(0, } ) +}; + +static const char transition_slideleft[] = { + SHADER_SLIDE_COMMON + C(0, void transition(int idx, ivec2 pos, float progress) ) + C(0, { ) + C(1, slide(idx, pos, progress, ivec2(+1, 0)); ) + C(0, } ) +}; + +static const char transition_slideright[] = { + SHADER_SLIDE_COMMON + C(0, void transition(int idx, ivec2 pos, float progress) ) + C(0, { ) + C(1, slide(idx, pos, progress, ivec2(-1, 0)); ) + C(0, } ) +}; + +static const char* transitions_map[NB_TRANSITIONS] = { + [FADE] = transition_fade, + [WIPELEFT] = transition_wipeleft, + [WIPERIGHT] = transition_wiperight, + [WIPEUP] = transition_wipeup, + [WIPEDOWN] = transition_wipedown, + [SLIDEDOWN] = transition_slidedown, + [SLIDEUP] = transition_slideup, + [SLIDELEFT] = transition_slideleft, + [SLIDERIGHT]= transition_slideright, +}; + +static av_cold int init_vulkan(AVFilterContext *avctx) +{ + int err = 0; + uint8_t *spv_data; + size_t spv_len; + void *spv_opaque = NULL; + XFadeVulkanContext *s = avctx->priv; + FFVulkanContext *vkctx = &s->vkctx; + const int planes = av_pix_fmt_count_planes(s->vkctx.output_format); + FFVkSPIRVShader *shd = &s->shd; + FFVkSPIRVCompiler *spv; + FFVulkanDescriptorSetBinding *desc; + + spv = ff_vk_spirv_init(); + if (!spv) { + av_log(avctx, AV_LOG_ERROR, "Unable to initialize SPIR-V compiler!\n"); + return AVERROR_EXTERNAL; + } + + ff_vk_qf_init(vkctx, &s->qf, VK_QUEUE_COMPUTE_BIT); + RET(ff_vk_exec_pool_init(vkctx, &s->qf, &s->e, s->qf.nb_queues*4, 0, 0, 0, NULL)); + RET(ff_vk_init_sampler(vkctx, &s->sampler, 1, VK_FILTER_NEAREST)); + RET(ff_vk_shader_init(&s->pl, &s->shd, "xfade_compute", + VK_SHADER_STAGE_COMPUTE_BIT, 0)); + + ff_vk_shader_set_compute_sizes(&s->shd, 32, 32, 1); + + desc = (FFVulkanDescriptorSetBinding []) { + { + .name = "a_images", + .type = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, + .dimensions = 2, + .elems = planes, + .stages = VK_SHADER_STAGE_COMPUTE_BIT, + .samplers = DUP_SAMPLER(s->sampler), + }, + { + .name = "b_images", + .type = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, + .dimensions = 2, + .elems = planes, + .stages = VK_SHADER_STAGE_COMPUTE_BIT, + .samplers = DUP_SAMPLER(s->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, + }, + }; + + RET(ff_vk_pipeline_descriptor_set_add(vkctx, &s->pl, shd, desc, 3, 0, 0)); + + GLSLC(0, layout(push_constant, std430) uniform pushConstants { ); + GLSLC(1, float progress; ); + GLSLC(0, }; ); + + ff_vk_add_push_constant(&s->pl, 0, sizeof(XFadeParameters), + VK_SHADER_STAGE_COMPUTE_BIT); + + // Add the right transition type function to the shader + GLSLD(transitions_map[s->transition]); + + GLSLC(0, void main() ); + GLSLC(0, { ); + GLSLC(1, ivec2 pos = ivec2(gl_GlobalInvocationID.xy); ); + GLSLF(1, int planes = %i; ,planes); + GLSLC(1, for (int i = 0; i < planes; i++) { ); + GLSLC(2, transition(i, pos, progress); ); + GLSLC(1, } ); + GLSLC(0, } ); + + RET(spv->compile_shader(spv, avctx, shd, &spv_data, &spv_len, "main", + &spv_opaque)); + RET(ff_vk_shader_create(vkctx, shd, spv_data, spv_len, "main")); + + RET(ff_vk_init_compute_pipeline(vkctx, &s->pl, shd)); + RET(ff_vk_exec_pipeline_register(vkctx, &s->e, &s->pl)); + + s->initialized = 1; + +fail: + if (spv_opaque) + spv->free_shader(spv, &spv_opaque); + if (spv) + spv->uninit(&spv); + + return err; +} + +static int xfade_frame(AVFilterContext *avctx, AVFrame *frame_a, AVFrame *frame_b) +{ + int err; + AVFilterLink *outlink = avctx->outputs[0]; + XFadeVulkanContext *s = avctx->priv; + float progress; + + AVFrame *output = ff_get_video_buffer(outlink, outlink->w, outlink->h); + if (!output) { + err = AVERROR(ENOMEM); + goto fail; + } + + if (!s->initialized) { + AVHWFramesContext *a_fc = (AVHWFramesContext*)frame_a->hw_frames_ctx->data; + AVHWFramesContext *b_fc = (AVHWFramesContext*)frame_b->hw_frames_ctx->data; + if (a_fc->sw_format != b_fc->sw_format) { + av_log(avctx, AV_LOG_ERROR, + "Currently the sw format of the first input needs to match the second!\n"); + return AVERROR(EINVAL); + } + RET(init_vulkan(avctx)); + } + + RET(av_frame_copy_props(output, frame_a)); + output->pts = s->pts; + + progress = av_clipf((float)(s->pts - s->start_pts) / s->duration_pts, + 0.f, 1.f); + + RET(ff_vk_filter_process_Nin(&s->vkctx, &s->e, &s->pl, output, + (AVFrame *[]){ frame_a, frame_b }, 2, s->sampler, + &(XFadeParameters){ progress }, sizeof(XFadeParameters))); + + return ff_filter_frame(outlink, output); + +fail: + av_frame_free(&output); + return err; +} + +static int config_props_output(AVFilterLink *outlink) +{ + int err; + AVFilterContext *avctx = outlink->src; + XFadeVulkanContext *s = avctx->priv; + AVFilterLink *inlink_a = avctx->inputs[IN_A]; + AVFilterLink *inlink_b = avctx->inputs[IN_B]; + + if (inlink_a->w != inlink_b->w || inlink_a->h != inlink_b->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_A].name, inlink_a->w, inlink_a->h, + avctx->input_pads[IN_B].name, inlink_b->w, inlink_b->h); + return AVERROR(EINVAL); + } + + if (inlink_a->time_base.num != inlink_b->time_base.num || + inlink_a->time_base.den != inlink_b->time_base.den) { + av_log(avctx, AV_LOG_ERROR, "First input link %s timebase " + "(%d/%d) does not match the corresponding " + "second input link %s timebase (%d/%d)\n", + avctx->input_pads[IN_A].name, inlink_a->time_base.num, inlink_a->time_base.den, + avctx->input_pads[IN_B].name, inlink_b->time_base.num, inlink_b->time_base.den); + return AVERROR(EINVAL); + } + + s->start_pts = s->inputs_offset_pts = AV_NOPTS_VALUE; + + outlink->time_base = inlink_a->time_base; + outlink->frame_rate = inlink_a->frame_rate; + outlink->sample_aspect_ratio = inlink_a->sample_aspect_ratio; + + if (s->duration) + s->duration_pts = av_rescale_q(s->duration, AV_TIME_BASE_Q, inlink_a->time_base); + RET(ff_vk_filter_config_output(outlink)); + +fail: + return err; +} + +static int forward_frame(XFadeVulkanContext *s, + AVFilterLink *inlink, AVFilterLink *outlink) +{ + int64_t status_pts; + int ret = 0, status; + AVFrame *frame = NULL; + + ret = ff_inlink_consume_frame(inlink, &frame); + if (ret < 0) + return ret; + + if (ret > 0) { + // If we do not have an offset yet, it's because we + // never got a first input. Just offset to 0 + if (s->inputs_offset_pts == AV_NOPTS_VALUE) + s->inputs_offset_pts = -frame->pts; + + // We got a frame, nothing to do other than adjusting the timestamp + frame->pts += s->inputs_offset_pts; + return ff_filter_frame(outlink, frame); + } + + // Forward status with our timestamp + if (ff_inlink_acknowledge_status(inlink, &status, &status_pts)) { + if (s->inputs_offset_pts == AV_NOPTS_VALUE) + s->inputs_offset_pts = -status_pts; + + ff_outlink_set_status(outlink, status, status_pts + s->inputs_offset_pts); + return 0; + } + + // No frame available, request one if needed + if (ff_outlink_frame_wanted(outlink)) + ff_inlink_request_frame(inlink); + + return 0; +} + +static int activate(AVFilterContext *avctx) +{ + XFadeVulkanContext *s = avctx->priv; + AVFilterLink *in_a = avctx->inputs[IN_A]; + AVFilterLink *in_b = avctx->inputs[IN_B]; + AVFilterLink *outlink = avctx->outputs[0]; + int64_t status_pts; + + FF_FILTER_FORWARD_STATUS_BACK_ALL(outlink, avctx); + + // Check if we already transitioned or IN_A ended prematurely, + // in which case just forward the frames from IN_B with adjusted + // timestamps until EOF. + if (s->status[IN_A] && !s->status[IN_B]) + return forward_frame(s, in_b, outlink); + + // We did not finish transitioning yet and the first stream + // did not end either, so check if there are more frames to consume. + if (ff_inlink_check_available_frame(in_a)) { + AVFrame *peeked_frame = ff_inlink_peek_frame(in_a, 0); + s->pts = peeked_frame->pts; + + if (s->start_pts == AV_NOPTS_VALUE) + s->start_pts = + s->pts + av_rescale_q(s->offset, AV_TIME_BASE_Q, in_a->time_base); + + // Check if we are not yet transitioning, in which case + // just request and forward the input frame. + if (s->start_pts > s->pts) { + AVFrame *frame_a = NULL; + s->passthrough = 1; + ff_inlink_consume_frame(in_a, &frame_a); + return ff_filter_frame(outlink, frame_a); + } + s->passthrough = 0; + + // We are transitioning, so we need a frame from IN_B + if (ff_inlink_check_available_frame(in_b)) { + int ret; + AVFrame *frame_a = NULL, *frame_b = NULL; + ff_inlink_consume_frame(avctx->inputs[IN_A], &frame_a); + ff_inlink_consume_frame(avctx->inputs[IN_B], &frame_b); + + // Calculate PTS offset to first input + if (s->inputs_offset_pts == AV_NOPTS_VALUE) + s->inputs_offset_pts = s->pts - frame_b->pts; + + // Check if we finished transitioning, in which case we + // report back EOF to IN_A as it is no longer needed. + if (s->pts - s->start_pts > s->duration_pts) { + s->status[IN_A] = AVERROR_EOF; + ff_inlink_set_status(in_a, AVERROR_EOF); + s->passthrough = 1; + } + ret = xfade_frame(avctx, frame_a, frame_b); + av_frame_free(&frame_a); + av_frame_free(&frame_b); + return ret; + } + + // We did not get a frame from IN_B, check its status. + if (ff_inlink_acknowledge_status(in_b, &s->status[IN_B], &status_pts)) { + // We should transition, but IN_B is EOF so just report EOF output now. + ff_outlink_set_status(outlink, s->status[IN_B], s->pts); + return 0; + } + + // We did not get a frame for IN_B but no EOF either, so just request more. + if (ff_outlink_frame_wanted(outlink)) { + ff_inlink_request_frame(in_b); + return 0; + } + } + + // We did not get a frame from IN_A, check its status. + if (ff_inlink_acknowledge_status(in_a, &s->status[IN_A], &status_pts)) { + // No more frames from IN_A, do not report EOF though, we will just + // forward the IN_B frames in the next activate calls. + s->passthrough = 1; + ff_filter_set_ready(avctx, 100); + return 0; + } + + // We have no frames yet from IN_A and no EOF, so request some. + if (ff_outlink_frame_wanted(outlink)) { + ff_inlink_request_frame(in_a); + return 0; + } + + return FFERROR_NOT_READY; +} + +static av_cold void uninit(AVFilterContext *avctx) +{ + XFadeVulkanContext *s = avctx->priv; + FFVulkanContext *vkctx = &s->vkctx; + FFVulkanFunctions *vk = &vkctx->vkfn; + + ff_vk_exec_pool_free(vkctx, &s->e); + ff_vk_pipeline_free(vkctx, &s->pl); + ff_vk_shader_free(vkctx, &s->shd); + + if (s->sampler) + vk->DestroySampler(vkctx->hwctx->act_dev, s->sampler, + vkctx->hwctx->alloc); + + ff_vk_uninit(&s->vkctx); + + s->initialized = 0; +} + +static AVFrame *get_video_buffer(AVFilterLink *inlink, int w, int h) +{ + XFadeVulkanContext *s = inlink->dst->priv; + + return s->passthrough ? + ff_null_get_video_buffer (inlink, w, h) : + ff_default_get_video_buffer(inlink, w, h); +} + +#define OFFSET(x) offsetof(XFadeVulkanContext, x) +#define FLAGS (AV_OPT_FLAG_FILTERING_PARAM | AV_OPT_FLAG_VIDEO_PARAM) + +static const AVOption xfade_vulkan_options[] = { + { "transition", "set cross fade transition", OFFSET(transition), AV_OPT_TYPE_INT, {.i64=FADE}, 0, NB_TRANSITIONS-1, FLAGS, "transition" }, + { "fade", "fade transition", 0, AV_OPT_TYPE_CONST, {.i64=FADE}, 0, 0, FLAGS, "transition" }, + { "wipeleft", "wipe left transition", 0, AV_OPT_TYPE_CONST, {.i64=WIPELEFT}, 0, 0, FLAGS, "transition" }, + { "wiperight", "wipe right transition", 0, AV_OPT_TYPE_CONST, {.i64=WIPERIGHT}, 0, 0, FLAGS, "transition" }, + { "wipeup", "wipe up transition", 0, AV_OPT_TYPE_CONST, {.i64=WIPEUP}, 0, 0, FLAGS, "transition" }, + { "wipedown", "wipe down transition", 0, AV_OPT_TYPE_CONST, {.i64=WIPEDOWN}, 0, 0, FLAGS, "transition" }, + { "slidedown", "slide down transition", 0, AV_OPT_TYPE_CONST, {.i64=SLIDEDOWN}, 0, 0, FLAGS, "transition" }, + { "slideup", "slide up transition", 0, AV_OPT_TYPE_CONST, {.i64=SLIDEUP}, 0, 0, FLAGS, "transition" }, + { "slideleft", "slide left transition", 0, AV_OPT_TYPE_CONST, {.i64=SLIDELEFT}, 0, 0, FLAGS, "transition" }, + { "slideright","slide right transition", 0, AV_OPT_TYPE_CONST, {.i64=SLIDERIGHT}, 0, 0, FLAGS, "transition" }, + { "duration", "set cross fade duration", OFFSET(duration), AV_OPT_TYPE_DURATION, {.i64=1000000}, 0, 60000000, FLAGS }, + { "offset", "set cross fade start relative to first input stream", OFFSET(offset), AV_OPT_TYPE_DURATION, {.i64=0}, INT64_MIN, INT64_MAX, FLAGS }, + { NULL } +}; + +AVFILTER_DEFINE_CLASS(xfade_vulkan); + +static const AVFilterPad xfade_vulkan_inputs[] = { + { + .name = "main", + .type = AVMEDIA_TYPE_VIDEO, + .get_buffer.video = &get_video_buffer, + .config_props = &ff_vk_filter_config_input, + }, + { + .name = "xfade", + .type = AVMEDIA_TYPE_VIDEO, + .get_buffer.video = &get_video_buffer, + .config_props = &ff_vk_filter_config_input, + }, +}; + +static const AVFilterPad xfade_vulkan_outputs[] = { + { + .name = "default", + .type = AVMEDIA_TYPE_VIDEO, + .config_props = &config_props_output, + }, +}; + +const AVFilter ff_vf_xfade_vulkan = { + .name = "xfade_vulkan", + .description = NULL_IF_CONFIG_SMALL("Cross fade one video with another video."), + .priv_size = sizeof(XFadeVulkanContext), + .init = &ff_vk_filter_init, + .uninit = &uninit, + .activate = &activate, + FILTER_INPUTS(xfade_vulkan_inputs), + FILTER_OUTPUTS(xfade_vulkan_outputs), + FILTER_SINGLE_PIXFMT(AV_PIX_FMT_VULKAN), + .priv_class = &xfade_vulkan_class, + .flags_internal = FF_FILTER_FLAG_HWFRAME_AWARE, + .flags = AVFILTER_FLAG_HWDEVICE, +}; From d8c7fea8ef04e9861ed701bb032f1651cc501ae2 Mon Sep 17 00:00:00 2001 From: Marvin Scholz Date: Fri, 2 Jun 2023 11:42:46 +0200 Subject: [PATCH 1435/2172] lavfi/vf_blend_vulkan: fix leak on error --- libavfilter/vf_blend_vulkan.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libavfilter/vf_blend_vulkan.c b/libavfilter/vf_blend_vulkan.c index 530f4981c24..717efcee418 100644 --- a/libavfilter/vf_blend_vulkan.c +++ b/libavfilter/vf_blend_vulkan.c @@ -249,7 +249,8 @@ static int blend_frame(FFFrameSync *fs) 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); + err = AVERROR(EINVAL); + goto fail; } RET(init_filter(avctx)); } From 697382168dbb4ba80201352eaf239511cb82074f Mon Sep 17 00:00:00 2001 From: Lynne Date: Tue, 6 Jun 2023 12:48:11 +0200 Subject: [PATCH 1436/2172] hevcdec: remove redundant bits_used_for_short_term_rps field It was introduced for Vulkan, but it is equivalent to short_term_ref_pic_set_size when !short_term_ref_pic_set_sps_flag, and when !!short_term_ref_pic_set_sps_flag, Vulkan hardcodes a zero anyway. --- libavcodec/hevcdec.c | 1 - libavcodec/hevcdec.h | 1 - libavcodec/vulkan_hevc.c | 2 +- 3 files changed, 1 insertion(+), 3 deletions(-) diff --git a/libavcodec/hevcdec.c b/libavcodec/hevcdec.c index eee77ec4dbb..a4284921cbc 100644 --- a/libavcodec/hevcdec.c +++ b/libavcodec/hevcdec.c @@ -723,7 +723,6 @@ static int hls_slice_header(HEVCContext *s) if (ret < 0) return ret; - sh->bits_used_for_short_term_rps = pos - get_bits_left(gb); sh->short_term_rps = &sh->slice_rps; } else { int numbits, rps_idx; diff --git a/libavcodec/hevcdec.h b/libavcodec/hevcdec.h index 04ec25d540b..94609e46993 100644 --- a/libavcodec/hevcdec.h +++ b/libavcodec/hevcdec.h @@ -268,7 +268,6 @@ typedef struct SliceHeader { ///< RPS coded in the slice header itself is stored here int short_term_ref_pic_set_sps_flag; - int bits_used_for_short_term_rps; int short_term_ref_pic_set_size; ShortTermRPS slice_rps; const ShortTermRPS *short_term_rps; diff --git a/libavcodec/vulkan_hevc.c b/libavcodec/vulkan_hevc.c index c9b6888410b..dcf7e75bc57 100644 --- a/libavcodec/vulkan_hevc.c +++ b/libavcodec/vulkan_hevc.c @@ -788,7 +788,7 @@ static int vk_hevc_start_frame(AVCodecContext *avctx, .NumDeltaPocsOfRefRpsIdx = h->sh.short_term_rps ? h->sh.short_term_rps->rps_idx_num_delta_pocs : 0, .PicOrderCntVal = h->poc, .NumBitsForSTRefPicSetInSlice = !h->sh.short_term_ref_pic_set_sps_flag ? - h->sh.bits_used_for_short_term_rps : 0, + h->sh.short_term_ref_pic_set_size : 0, }; /* Fill in references */ From 975cd48bb3a45aefe314be3b9f8f3b8f0e4f614c Mon Sep 17 00:00:00 2001 From: Lynne Date: Wed, 7 Jun 2023 00:24:43 +0200 Subject: [PATCH 1437/2172] vulkan: synchronize access to execution pool fences vkResetFences is specified as being user-synchronized (yet vkWaitFences, is not). --- libavutil/vulkan.c | 16 +++++++++++++--- libavutil/vulkan.h | 2 ++ 2 files changed, 15 insertions(+), 3 deletions(-) diff --git a/libavutil/vulkan.c b/libavutil/vulkan.c index bc4466e6c9a..b1c585292e5 100644 --- a/libavutil/vulkan.c +++ b/libavutil/vulkan.c @@ -241,6 +241,7 @@ void ff_vk_exec_pool_free(FFVulkanContext *s, FFVkExecPool *pool) vk->WaitForFences(s->hwctx->act_dev, 1, &e->fence, VK_TRUE, UINT64_MAX); vk->DestroyFence(s->hwctx->act_dev, e->fence, s->hwctx->alloc); } + pthread_mutex_destroy(&e->lock); ff_vk_exec_discard_deps(s, e); @@ -379,12 +380,17 @@ int ff_vk_exec_pool_init(FFVulkanContext *s, FFVkQueueFamilyCtx *qf, /* Init contexts */ for (int i = 0; i < pool->pool_size; i++) { FFVkExecContext *e = &pool->contexts[i]; - - /* Fence */ VkFenceCreateInfo fence_create = { .sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO, .flags = VK_FENCE_CREATE_SIGNALED_BIT, }; + + /* Mutex */ + err = pthread_mutex_init(&e->lock, NULL); + if (err != 0) + return AVERROR(err); + + /* Fence */ ret = vk->CreateFence(s->hwctx->act_dev, &fence_create, s->hwctx->alloc, &e->fence); if (ret != VK_SUCCESS) { @@ -488,9 +494,13 @@ int ff_vk_exec_start(FFVulkanContext *s, FFVkExecContext *e) .flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT, }; - /* Create the fence and don't wait for it initially */ + /* Wait for the fence to be signalled */ vk->WaitForFences(s->hwctx->act_dev, 1, &e->fence, VK_TRUE, UINT64_MAX); + + /* vkResetFences is defined as being host-synchronized */ + pthread_mutex_lock(&e->lock); vk->ResetFences(s->hwctx->act_dev, 1, &e->fence); + pthread_mutex_unlock(&e->lock); /* Discard queue dependencies */ ff_vk_exec_discard_deps(s, e); diff --git a/libavutil/vulkan.h b/libavutil/vulkan.h index 58da720a1cf..bbbc9374aee 100644 --- a/libavutil/vulkan.h +++ b/libavutil/vulkan.h @@ -23,6 +23,7 @@ #include +#include "thread.h" #include "pixdesc.h" #include "bprint.h" #include "hwcontext.h" @@ -152,6 +153,7 @@ typedef struct FFVulkanPipeline { typedef struct FFVkExecContext { int idx; const struct FFVkExecPool *parent; + pthread_mutex_t lock; /* Queue for the execution context */ VkQueue queue; From 5f1be341c2bdc12f77c3209370144b15661a4958 Mon Sep 17 00:00:00 2001 From: Lynne Date: Wed, 7 Jun 2023 01:16:29 +0200 Subject: [PATCH 1438/2172] vulkan: discard dependencies when explicitly waiting for execution This reduces memory needed dramatically, as unneeded resources can be immediately returned to the pool. Although waitforfences is threadsafe, we add a mutex wait around it, as the mutex fence in combination with waitforfences assures us that no other thread will reset the fence in the meanwhile whilst the mutex is locked. This allows is to call ff_vk_exec_discard_deps. --- libavutil/vulkan.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/libavutil/vulkan.c b/libavutil/vulkan.c index b1c585292e5..26b9b6f1fb2 100644 --- a/libavutil/vulkan.c +++ b/libavutil/vulkan.c @@ -480,7 +480,10 @@ FFVkExecContext *ff_vk_exec_get(FFVkExecPool *pool) void ff_vk_exec_wait(FFVulkanContext *s, FFVkExecContext *e) { FFVulkanFunctions *vk = &s->vkfn; + pthread_mutex_lock(&e->lock); vk->WaitForFences(s->hwctx->act_dev, 1, &e->fence, VK_TRUE, UINT64_MAX); + ff_vk_exec_discard_deps(s, e); + pthread_mutex_unlock(&e->lock); } int ff_vk_exec_start(FFVulkanContext *s, FFVkExecContext *e) From 24c4307b80785244d3def38a3787d6e76375f7b5 Mon Sep 17 00:00:00 2001 From: Lynne Date: Wed, 7 Jun 2023 02:59:55 +0200 Subject: [PATCH 1439/2172] vulkan_decode: halve execution pool size Determined experimentally, on various videos and hardware. On Intel, using less resources in-flight is around 15% faster, with similar results on Nvidia hardware. --- libavcodec/vulkan_decode.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/libavcodec/vulkan_decode.c b/libavcodec/vulkan_decode.c index 889c67a15fa..35e265a5b1d 100644 --- a/libavcodec/vulkan_decode.c +++ b/libavcodec/vulkan_decode.c @@ -1105,8 +1105,9 @@ int ff_vk_decode_init(AVCodecContext *avctx) session_create.pVideoProfile = &prof->profile_list.pProfiles[0]; /* Create decode exec context. - * 4 async contexts per thread seems like a good number. */ - err = ff_vk_exec_pool_init(s, &qf_dec, &ctx->exec_pool, 4*avctx->thread_count, + * 2 async contexts per thread was experimentally determined to be optimal + * for a majority of streams. */ + err = ff_vk_exec_pool_init(s, &qf_dec, &ctx->exec_pool, 2*avctx->thread_count, nb_q, VK_QUERY_TYPE_RESULT_STATUS_ONLY_KHR, 0, session_create.pVideoProfile); if (err < 0) From eff565dc19c9c54763cf6f882d14b8ee1a94b190 Mon Sep 17 00:00:00 2001 From: Lynne Date: Wed, 7 Jun 2023 04:01:44 +0200 Subject: [PATCH 1440/2172] hwcontext_vulkan: tune execution pools Having less in-flight resources is better in this case. --- libavutil/hwcontext_vulkan.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/libavutil/hwcontext_vulkan.c b/libavutil/hwcontext_vulkan.c index ec084d94d78..1132a61390e 100644 --- a/libavutil/hwcontext_vulkan.c +++ b/libavutil/hwcontext_vulkan.c @@ -2315,17 +2315,17 @@ static int vulkan_frames_init(AVHWFramesContext *hwfc) hwctx->unlock_frame = unlock_frame; err = ff_vk_exec_pool_init(&p->vkctx, &p->compute_qf, &fp->compute_exec, - p->compute_qf.nb_queues*4, 0, 0, 0, NULL); + p->compute_qf.nb_queues, 0, 0, 0, NULL); if (err) return err; err = ff_vk_exec_pool_init(&p->vkctx, &p->transfer_qf, &fp->upload_exec, - p->transfer_qf.nb_queues*4, 0, 0, 0, NULL); + p->transfer_qf.nb_queues*2, 0, 0, 0, NULL); if (err) return err; err = ff_vk_exec_pool_init(&p->vkctx, &p->transfer_qf, &fp->download_exec, - p->transfer_qf.nb_queues*4, 0, 0, 0, NULL); + p->transfer_qf.nb_queues, 0, 0, 0, NULL); if (err) return err; From 1d7a6eaee66ff7481a0c9a4f4e539227a9d55839 Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Wed, 7 Jun 2023 13:49:49 +0200 Subject: [PATCH 1441/2172] avcodec/proresenc_kostya: set avctx->profile from ctx Otherwise muxers may not be able to guess it. Option is still set by user, but via private codec option. --- libavcodec/proresenc_kostya.c | 1 + 1 file changed, 1 insertion(+) diff --git a/libavcodec/proresenc_kostya.c b/libavcodec/proresenc_kostya.c index 77ab524046b..52fe5639b19 100644 --- a/libavcodec/proresenc_kostya.c +++ b/libavcodec/proresenc_kostya.c @@ -1355,6 +1355,7 @@ static av_cold int encode_init(AVCodecContext *avctx) } avctx->codec_tag = ctx->profile_info->tag; + avctx->profile = ctx->profile; av_log(avctx, AV_LOG_DEBUG, "profile %d, %d slices, interlacing: %s, %d bits per MB\n", From bfd50906287d335598c92c34d0a963ce436efd1b Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Thu, 8 Jun 2023 02:29:16 +0200 Subject: [PATCH 1442/2172] avfilter/af_rubberband: rewrite EOF handling Also pass correct EOF timestamp. --- libavfilter/af_rubberband.c | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/libavfilter/af_rubberband.c b/libavfilter/af_rubberband.c index c56bf5d82fc..9f543051b9b 100644 --- a/libavfilter/af_rubberband.c +++ b/libavfilter/af_rubberband.c @@ -38,7 +38,9 @@ typedef struct RubberBandContext { int64_t nb_samples_out; int64_t nb_samples_in; int64_t first_pts; + int64_t last_pts; int nb_samples; + int eof; } RubberBandContext; #define OFFSET(x) offsetof(RubberBandContext, x) @@ -100,7 +102,7 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in) if (s->first_pts == AV_NOPTS_VALUE) s->first_pts = in->pts; - rubberband_process(s->rbs, (const float *const *)in->extended_data, in->nb_samples, ff_outlink_get_status(inlink)); + rubberband_process(s->rbs, (const float *const *)in->extended_data, in->nb_samples, s->eof); s->nb_samples_in += in->nb_samples; nb_samples = rubberband_available(s->rbs); @@ -113,6 +115,7 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in) out->pts = s->first_pts + av_rescale_q(s->nb_samples_out, (AVRational){ 1, outlink->sample_rate }, outlink->time_base); + s->last_pts = out->pts; nb_samples = rubberband_retrieve(s->rbs, (float *const *)out->extended_data, nb_samples); out->nb_samples = nb_samples; ret = ff_filter_frame(outlink, out); @@ -151,11 +154,16 @@ static int activate(AVFilterContext *ctx) AVFilterLink *outlink = ctx->outputs[0]; RubberBandContext *s = ctx->priv; AVFrame *in = NULL; - int ret; + int64_t pts; + int status, ret; FF_FILTER_FORWARD_STATUS_BACK(outlink, inlink); ret = ff_inlink_consume_samples(inlink, s->nb_samples, s->nb_samples, &in); + + if (ff_inlink_acknowledge_status(inlink, &status, &pts)) + s->eof |= status == AVERROR_EOF; + if (ret < 0) return ret; if (ret > 0) { @@ -164,7 +172,11 @@ static int activate(AVFilterContext *ctx) return ret; } - FF_FILTER_FORWARD_STATUS(inlink, outlink); + if (s->eof) { + ff_outlink_set_status(outlink, AVERROR_EOF, s->last_pts); + return 0; + } + FF_FILTER_FORWARD_WANTED(outlink, inlink); return FFERROR_NOT_READY; From 2c4b6976d5b57dec938dba481fe5d3b93eb24f1e Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Thu, 8 Jun 2023 10:33:15 +1000 Subject: [PATCH 1443/2172] vulkan/hevc: fix 32x32 scaling list indexing This fixes another problem in the hevc scaling lists and aligns the code with what other hwaccels do. --- libavcodec/vulkan_hevc.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/libavcodec/vulkan_hevc.c b/libavcodec/vulkan_hevc.c index dcf7e75bc57..5ddfd0daf3c 100644 --- a/libavcodec/vulkan_hevc.c +++ b/libavcodec/vulkan_hevc.c @@ -231,14 +231,14 @@ static void set_sps(const HEVCSPS *sps, int sps_idx, STD_VIDEO_H265_SCALING_LIST_16X16_NUM_ELEMENTS * sizeof(**vksps_scaling->ScalingList16x16)); for (int i = 0; i < STD_VIDEO_H265_SCALING_LIST_32X32_NUM_LISTS; i++) - memcpy(vksps_scaling->ScalingList32x32[i], sps->scaling_list.sl[3][i], + memcpy(vksps_scaling->ScalingList32x32[i], sps->scaling_list.sl[3][i * 3], STD_VIDEO_H265_SCALING_LIST_32X32_NUM_ELEMENTS * sizeof(**vksps_scaling->ScalingList32x32)); memcpy(vksps_scaling->ScalingListDCCoef16x16, sps->scaling_list.sl_dc[0], STD_VIDEO_H265_SCALING_LIST_16X16_NUM_LISTS * sizeof(*vksps_scaling->ScalingListDCCoef16x16)); - memcpy(vksps_scaling->ScalingListDCCoef32x32, sps->scaling_list.sl_dc[1], - STD_VIDEO_H265_SCALING_LIST_32X32_NUM_LISTS * sizeof(*vksps_scaling->ScalingListDCCoef32x32)); + for (int i = 0; i < STD_VIDEO_H265_SCALING_LIST_32X32_NUM_LISTS; i++) + vksps_scaling->ScalingListDCCoef32x32[i] = sps->scaling_list.sl_dc[1][i * 3]; *vksps_vui_header = (StdVideoH265HrdParameters) { .flags = (StdVideoH265HrdFlags) { @@ -477,14 +477,14 @@ static void set_pps(const HEVCPPS *pps, const HEVCSPS *sps, STD_VIDEO_H265_SCALING_LIST_16X16_NUM_ELEMENTS * sizeof(**vkpps_scaling->ScalingList16x16)); for (int i = 0; i < STD_VIDEO_H265_SCALING_LIST_32X32_NUM_LISTS; i++) - memcpy(vkpps_scaling->ScalingList32x32[i], pps->scaling_list.sl[3][i], + memcpy(vkpps_scaling->ScalingList32x32[i], pps->scaling_list.sl[3][i * 3], STD_VIDEO_H265_SCALING_LIST_32X32_NUM_ELEMENTS * sizeof(**vkpps_scaling->ScalingList32x32)); memcpy(vkpps_scaling->ScalingListDCCoef16x16, pps->scaling_list.sl_dc[0], STD_VIDEO_H265_SCALING_LIST_16X16_NUM_LISTS * sizeof(*vkpps_scaling->ScalingListDCCoef16x16)); - memcpy(vkpps_scaling->ScalingListDCCoef32x32, pps->scaling_list.sl_dc[1], - STD_VIDEO_H265_SCALING_LIST_32X32_NUM_LISTS * sizeof(*vkpps_scaling->ScalingListDCCoef32x32)); + for (int i = 0; i < STD_VIDEO_H265_SCALING_LIST_32X32_NUM_LISTS; i++) + vkpps_scaling->ScalingListDCCoef32x32[i] = sps->scaling_list.sl_dc[1][i * 3]; *vkpps = (StdVideoH265PictureParameterSet) { .flags = (StdVideoH265PpsFlags) { From 3f52b7eedc9f131c10cfc2cdf2d493f04db05fd0 Mon Sep 17 00:00:00 2001 From: Zhao Zhili Date: Sun, 30 Apr 2023 23:38:53 +0800 Subject: [PATCH 1444/2172] avfilter/dnn: define each backend as a DNNModule To avoid export multiple functions for each backend implementation. Signed-off-by: Zhao Zhili --- libavfilter/dnn/dnn_backend_openvino.c | 98 +++++++++++++----------- libavfilter/dnn/dnn_backend_openvino.h | 40 ---------- libavfilter/dnn/dnn_backend_tf.c | 101 +++++++++++++------------ libavfilter/dnn/dnn_backend_tf.h | 40 ---------- libavfilter/dnn/dnn_interface.c | 17 ++--- 5 files changed, 112 insertions(+), 184 deletions(-) delete mode 100644 libavfilter/dnn/dnn_backend_openvino.h delete mode 100644 libavfilter/dnn/dnn_backend_tf.h diff --git a/libavfilter/dnn/dnn_backend_openvino.c b/libavfilter/dnn/dnn_backend_openvino.c index b67f2883364..7db2e7a10fd 100644 --- a/libavfilter/dnn/dnn_backend_openvino.c +++ b/libavfilter/dnn/dnn_backend_openvino.c @@ -23,7 +23,6 @@ * DNN OpenVINO backend implementation. */ -#include "dnn_backend_openvino.h" #include "dnn_io_proc.h" #include "libavformat/avio.h" #include "libavutil/avassert.h" @@ -293,6 +292,46 @@ static void infer_completion_callback(void *args) } } +static void dnn_free_model_ov(DNNModel **model) +{ + if (*model){ + OVModel *ov_model = (*model)->model; + while (ff_safe_queue_size(ov_model->request_queue) != 0) { + OVRequestItem *item = ff_safe_queue_pop_front(ov_model->request_queue); + if (item && item->infer_request) { + ie_infer_request_free(&item->infer_request); + } + av_freep(&item->lltasks); + av_freep(&item); + } + ff_safe_queue_destroy(ov_model->request_queue); + + while (ff_queue_size(ov_model->lltask_queue) != 0) { + LastLevelTaskItem *item = ff_queue_pop_front(ov_model->lltask_queue); + av_freep(&item); + } + ff_queue_destroy(ov_model->lltask_queue); + + while (ff_queue_size(ov_model->task_queue) != 0) { + TaskItem *item = ff_queue_pop_front(ov_model->task_queue); + av_frame_free(&item->in_frame); + av_frame_free(&item->out_frame); + av_freep(&item); + } + ff_queue_destroy(ov_model->task_queue); + + if (ov_model->exe_network) + ie_exec_network_free(&ov_model->exe_network); + if (ov_model->network) + ie_network_free(&ov_model->network); + if (ov_model->core) + ie_core_free(&ov_model->core); + av_freep(&ov_model); + av_freep(model); + } +} + + static int init_model_ov(OVModel *ov_model, const char *input_name, const char *output_name) { int ret = 0; @@ -438,7 +477,7 @@ static int init_model_ov(OVModel *ov_model, const char *input_name, const char * return 0; err: - ff_dnn_free_model_ov(&ov_model->model); + dnn_free_model_ov(&ov_model->model); return ret; } @@ -721,7 +760,7 @@ static int get_output_ov(void *model, const char *input_name, int input_width, i return ret; } -DNNModel *ff_dnn_load_model_ov(const char *model_filename, DNNFunctionType func_type, const char *options, AVFilterContext *filter_ctx) +static DNNModel *dnn_load_model_ov(const char *model_filename, DNNFunctionType func_type, const char *options, AVFilterContext *filter_ctx) { DNNModel *model = NULL; OVModel *ov_model = NULL; @@ -806,11 +845,11 @@ DNNModel *ff_dnn_load_model_ov(const char *model_filename, DNNFunctionType func_ return model; err: - ff_dnn_free_model_ov(&model); + dnn_free_model_ov(&model); return NULL; } -int ff_dnn_execute_model_ov(const DNNModel *model, DNNExecBaseParams *exec_params) +static int dnn_execute_model_ov(const DNNModel *model, DNNExecBaseParams *exec_params) { OVModel *ov_model = model->model; OVContext *ctx = &ov_model->ctx; @@ -893,13 +932,13 @@ int ff_dnn_execute_model_ov(const DNNModel *model, DNNExecBaseParams *exec_param } } -DNNAsyncStatusType ff_dnn_get_result_ov(const DNNModel *model, AVFrame **in, AVFrame **out) +static DNNAsyncStatusType dnn_get_result_ov(const DNNModel *model, AVFrame **in, AVFrame **out) { OVModel *ov_model = model->model; return ff_dnn_get_result_common(ov_model->task_queue, in, out); } -int ff_dnn_flush_ov(const DNNModel *model) +static int dnn_flush_ov(const DNNModel *model) { OVModel *ov_model = model->model; OVContext *ctx = &ov_model->ctx; @@ -937,41 +976,10 @@ int ff_dnn_flush_ov(const DNNModel *model) return 0; } -void ff_dnn_free_model_ov(DNNModel **model) -{ - if (*model){ - OVModel *ov_model = (*model)->model; - while (ff_safe_queue_size(ov_model->request_queue) != 0) { - OVRequestItem *item = ff_safe_queue_pop_front(ov_model->request_queue); - if (item && item->infer_request) { - ie_infer_request_free(&item->infer_request); - } - av_freep(&item->lltasks); - av_freep(&item); - } - ff_safe_queue_destroy(ov_model->request_queue); - - while (ff_queue_size(ov_model->lltask_queue) != 0) { - LastLevelTaskItem *item = ff_queue_pop_front(ov_model->lltask_queue); - av_freep(&item); - } - ff_queue_destroy(ov_model->lltask_queue); - - while (ff_queue_size(ov_model->task_queue) != 0) { - TaskItem *item = ff_queue_pop_front(ov_model->task_queue); - av_frame_free(&item->in_frame); - av_frame_free(&item->out_frame); - av_freep(&item); - } - ff_queue_destroy(ov_model->task_queue); - - if (ov_model->exe_network) - ie_exec_network_free(&ov_model->exe_network); - if (ov_model->network) - ie_network_free(&ov_model->network); - if (ov_model->core) - ie_core_free(&ov_model->core); - av_freep(&ov_model); - av_freep(model); - } -} +const DNNModule ff_dnn_backend_openvino = { + .load_model = dnn_load_model_ov, + .execute_model = dnn_execute_model_ov, + .get_result = dnn_get_result_ov, + .flush = dnn_flush_ov, + .free_model = dnn_free_model_ov, +}; diff --git a/libavfilter/dnn/dnn_backend_openvino.h b/libavfilter/dnn/dnn_backend_openvino.h deleted file mode 100644 index 304bc96b998..00000000000 --- a/libavfilter/dnn/dnn_backend_openvino.h +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright (c) 2020 - * - * 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 - * DNN inference functions interface for OpenVINO backend. - */ - - -#ifndef AVFILTER_DNN_DNN_BACKEND_OPENVINO_H -#define AVFILTER_DNN_DNN_BACKEND_OPENVINO_H - -#include "../dnn_interface.h" - -DNNModel *ff_dnn_load_model_ov(const char *model_filename, DNNFunctionType func_type, const char *options, AVFilterContext *filter_ctx); - -int ff_dnn_execute_model_ov(const DNNModel *model, DNNExecBaseParams *exec_params); -DNNAsyncStatusType ff_dnn_get_result_ov(const DNNModel *model, AVFrame **in, AVFrame **out); -int ff_dnn_flush_ov(const DNNModel *model); - -void ff_dnn_free_model_ov(DNNModel **model); - -#endif diff --git a/libavfilter/dnn/dnn_backend_tf.c b/libavfilter/dnn/dnn_backend_tf.c index 486d2405b86..e6ebd175953 100644 --- a/libavfilter/dnn/dnn_backend_tf.c +++ b/libavfilter/dnn/dnn_backend_tf.c @@ -23,7 +23,6 @@ * DNN tensorflow backend implementation. */ -#include "dnn_backend_tf.h" #include "libavformat/avio.h" #include "libavutil/avassert.h" #include "libavutil/avstring.h" @@ -477,7 +476,48 @@ static int load_tf_model(TFModel *tf_model, const char *model_filename) #define NAME_BUFFER_SIZE 256 -DNNModel *ff_dnn_load_model_tf(const char *model_filename, DNNFunctionType func_type, const char *options, AVFilterContext *filter_ctx) +static void dnn_free_model_tf(DNNModel **model) +{ + TFModel *tf_model; + + if (*model){ + tf_model = (*model)->model; + while (ff_safe_queue_size(tf_model->request_queue) != 0) { + TFRequestItem *item = ff_safe_queue_pop_front(tf_model->request_queue); + destroy_request_item(&item); + } + ff_safe_queue_destroy(tf_model->request_queue); + + while (ff_queue_size(tf_model->lltask_queue) != 0) { + LastLevelTaskItem *item = ff_queue_pop_front(tf_model->lltask_queue); + av_freep(&item); + } + ff_queue_destroy(tf_model->lltask_queue); + + while (ff_queue_size(tf_model->task_queue) != 0) { + TaskItem *item = ff_queue_pop_front(tf_model->task_queue); + av_frame_free(&item->in_frame); + av_frame_free(&item->out_frame); + av_freep(&item); + } + ff_queue_destroy(tf_model->task_queue); + + if (tf_model->graph){ + TF_DeleteGraph(tf_model->graph); + } + if (tf_model->session){ + TF_CloseSession(tf_model->session, tf_model->status); + TF_DeleteSession(tf_model->session, tf_model->status); + } + if (tf_model->status){ + TF_DeleteStatus(tf_model->status); + } + av_freep(&tf_model); + av_freep(model); + } +} + +static DNNModel *dnn_load_model_tf(const char *model_filename, DNNFunctionType func_type, const char *options, AVFilterContext *filter_ctx) { DNNModel *model = NULL; TFModel *tf_model = NULL; @@ -567,7 +607,7 @@ DNNModel *ff_dnn_load_model_tf(const char *model_filename, DNNFunctionType func_ return model; err: - ff_dnn_free_model_tf(&model); + dnn_free_model_tf(&model); return NULL; } @@ -765,11 +805,11 @@ static int execute_model_tf(TFRequestItem *request, Queue *lltask_queue) if (ff_safe_queue_push_back(tf_model->request_queue, request) < 0) { destroy_request_item(&request); } - ff_dnn_free_model_tf(&tf_model->model); + dnn_free_model_tf(&tf_model->model); return ret; } -int ff_dnn_execute_model_tf(const DNNModel *model, DNNExecBaseParams *exec_params) +static int dnn_execute_model_tf(const DNNModel *model, DNNExecBaseParams *exec_params) { TFModel *tf_model = model->model; TFContext *ctx = &tf_model->ctx; @@ -817,13 +857,13 @@ int ff_dnn_execute_model_tf(const DNNModel *model, DNNExecBaseParams *exec_param return execute_model_tf(request, tf_model->lltask_queue); } -DNNAsyncStatusType ff_dnn_get_result_tf(const DNNModel *model, AVFrame **in, AVFrame **out) +static DNNAsyncStatusType dnn_get_result_tf(const DNNModel *model, AVFrame **in, AVFrame **out) { TFModel *tf_model = model->model; return ff_dnn_get_result_common(tf_model->task_queue, in, out); } -int ff_dnn_flush_tf(const DNNModel *model) +static int dnn_flush_tf(const DNNModel *model) { TFModel *tf_model = model->model; TFContext *ctx = &tf_model->ctx; @@ -853,43 +893,10 @@ int ff_dnn_flush_tf(const DNNModel *model) return ff_dnn_start_inference_async(ctx, &request->exec_module); } -void ff_dnn_free_model_tf(DNNModel **model) -{ - TFModel *tf_model; - - if (*model){ - tf_model = (*model)->model; - while (ff_safe_queue_size(tf_model->request_queue) != 0) { - TFRequestItem *item = ff_safe_queue_pop_front(tf_model->request_queue); - destroy_request_item(&item); - } - ff_safe_queue_destroy(tf_model->request_queue); - - while (ff_queue_size(tf_model->lltask_queue) != 0) { - LastLevelTaskItem *item = ff_queue_pop_front(tf_model->lltask_queue); - av_freep(&item); - } - ff_queue_destroy(tf_model->lltask_queue); - - while (ff_queue_size(tf_model->task_queue) != 0) { - TaskItem *item = ff_queue_pop_front(tf_model->task_queue); - av_frame_free(&item->in_frame); - av_frame_free(&item->out_frame); - av_freep(&item); - } - ff_queue_destroy(tf_model->task_queue); - - if (tf_model->graph){ - TF_DeleteGraph(tf_model->graph); - } - if (tf_model->session){ - TF_CloseSession(tf_model->session, tf_model->status); - TF_DeleteSession(tf_model->session, tf_model->status); - } - if (tf_model->status){ - TF_DeleteStatus(tf_model->status); - } - av_freep(&tf_model); - av_freep(model); - } -} +const DNNModule ff_dnn_backend_tf = { + .load_model = dnn_load_model_tf, + .execute_model = dnn_execute_model_tf, + .get_result = dnn_get_result_tf, + .flush = dnn_flush_tf, + .free_model = dnn_free_model_tf, +}; diff --git a/libavfilter/dnn/dnn_backend_tf.h b/libavfilter/dnn/dnn_backend_tf.h deleted file mode 100644 index 0b63a4b6d22..00000000000 --- a/libavfilter/dnn/dnn_backend_tf.h +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright (c) 2018 Sergey Lavrushkin - * - * 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 - * DNN inference functions interface for TensorFlow backend. - */ - - -#ifndef AVFILTER_DNN_DNN_BACKEND_TF_H -#define AVFILTER_DNN_DNN_BACKEND_TF_H - -#include "../dnn_interface.h" - -DNNModel *ff_dnn_load_model_tf(const char *model_filename, DNNFunctionType func_type, const char *options, AVFilterContext *filter_ctx); - -int ff_dnn_execute_model_tf(const DNNModel *model, DNNExecBaseParams *exec_params); -DNNAsyncStatusType ff_dnn_get_result_tf(const DNNModel *model, AVFrame **in, AVFrame **out); -int ff_dnn_flush_tf(const DNNModel *model); - -void ff_dnn_free_model_tf(DNNModel **model); - -#endif diff --git a/libavfilter/dnn/dnn_interface.c b/libavfilter/dnn/dnn_interface.c index 5b1695a1dd2..4f78f354749 100644 --- a/libavfilter/dnn/dnn_interface.c +++ b/libavfilter/dnn/dnn_interface.c @@ -24,10 +24,11 @@ */ #include "../dnn_interface.h" -#include "dnn_backend_tf.h" -#include "dnn_backend_openvino.h" #include "libavutil/mem.h" +extern const DNNModule ff_dnn_backend_openvino; +extern const DNNModule ff_dnn_backend_tf; + DNNModule *ff_get_dnn_module(DNNBackendType backend_type) { DNNModule *dnn_module; @@ -40,11 +41,7 @@ DNNModule *ff_get_dnn_module(DNNBackendType backend_type) switch(backend_type){ case DNN_TF: #if (CONFIG_LIBTENSORFLOW == 1) - dnn_module->load_model = &ff_dnn_load_model_tf; - dnn_module->execute_model = &ff_dnn_execute_model_tf; - dnn_module->get_result = &ff_dnn_get_result_tf; - dnn_module->flush = &ff_dnn_flush_tf; - dnn_module->free_model = &ff_dnn_free_model_tf; + *dnn_module = ff_dnn_backend_tf; #else av_freep(&dnn_module); return NULL; @@ -52,11 +49,7 @@ DNNModule *ff_get_dnn_module(DNNBackendType backend_type) break; case DNN_OV: #if (CONFIG_LIBOPENVINO == 1) - dnn_module->load_model = &ff_dnn_load_model_ov; - dnn_module->execute_model = &ff_dnn_execute_model_ov; - dnn_module->get_result = &ff_dnn_get_result_ov; - dnn_module->flush = &ff_dnn_flush_ov; - dnn_module->free_model = &ff_dnn_free_model_ov; + *dnn_module = ff_dnn_backend_openvino; #else av_freep(&dnn_module); return NULL; From 505c43bb652093625c71b312ce1a5f1b9f9679e2 Mon Sep 17 00:00:00 2001 From: Zhao Zhili Date: Sun, 30 Apr 2023 23:38:54 +0800 Subject: [PATCH 1445/2172] avfilter/dnn: refactor ff_get_dnn_module to remove allocation Signed-off-by: Zhao Zhili --- libavfilter/dnn/dnn_interface.c | 28 +++++----------------------- libavfilter/dnn_filter_common.c | 1 - libavfilter/dnn_filter_common.h | 2 +- libavfilter/dnn_interface.h | 2 +- 4 files changed, 7 insertions(+), 26 deletions(-) diff --git a/libavfilter/dnn/dnn_interface.c b/libavfilter/dnn/dnn_interface.c index 4f78f354749..a60dcb091bb 100644 --- a/libavfilter/dnn/dnn_interface.c +++ b/libavfilter/dnn/dnn_interface.c @@ -29,37 +29,19 @@ extern const DNNModule ff_dnn_backend_openvino; extern const DNNModule ff_dnn_backend_tf; -DNNModule *ff_get_dnn_module(DNNBackendType backend_type) +const DNNModule *ff_get_dnn_module(DNNBackendType backend_type) { - DNNModule *dnn_module; - - dnn_module = av_mallocz(sizeof(DNNModule)); - if(!dnn_module){ - return NULL; - } - switch(backend_type){ - case DNN_TF: #if (CONFIG_LIBTENSORFLOW == 1) - *dnn_module = ff_dnn_backend_tf; - #else - av_freep(&dnn_module); - return NULL; + case DNN_TF: + return &ff_dnn_backend_tf; #endif - break; - case DNN_OV: #if (CONFIG_LIBOPENVINO == 1) - *dnn_module = ff_dnn_backend_openvino; - #else - av_freep(&dnn_module); - return NULL; + case DNN_OV: + return &ff_dnn_backend_openvino; #endif - break; default: av_log(NULL, AV_LOG_ERROR, "Module backend_type is not supported or enabled.\n"); - av_freep(&dnn_module); return NULL; } - - return dnn_module; } diff --git a/libavfilter/dnn_filter_common.c b/libavfilter/dnn_filter_common.c index 5083e3de198..7b34fd0c0a4 100644 --- a/libavfilter/dnn_filter_common.c +++ b/libavfilter/dnn_filter_common.c @@ -158,6 +158,5 @@ void ff_dnn_uninit(DnnContext *ctx) { if (ctx->dnn_module) { (ctx->dnn_module->free_model)(&ctx->model); - av_freep(&ctx->dnn_module); } } diff --git a/libavfilter/dnn_filter_common.h b/libavfilter/dnn_filter_common.h index bcdf37c8155..30871ee3819 100644 --- a/libavfilter/dnn_filter_common.h +++ b/libavfilter/dnn_filter_common.h @@ -36,7 +36,7 @@ typedef struct DnnContext { char **model_outputnames; uint32_t nb_outputs; - DNNModule *dnn_module; + const DNNModule *dnn_module; DNNModel *model; } DnnContext; diff --git a/libavfilter/dnn_interface.h b/libavfilter/dnn_interface.h index 6b64a2b55a3..b2bfdd38e7c 100644 --- a/libavfilter/dnn_interface.h +++ b/libavfilter/dnn_interface.h @@ -123,6 +123,6 @@ typedef struct DNNModule{ } DNNModule; // Initializes DNNModule depending on chosen backend. -DNNModule *ff_get_dnn_module(DNNBackendType backend_type); +const DNNModule *ff_get_dnn_module(DNNBackendType backend_type); #endif From 016f2f61c3b66311ac03e3898772d194321300f2 Mon Sep 17 00:00:00 2001 From: Zhao Zhili Date: Sun, 30 Apr 2023 23:38:55 +0800 Subject: [PATCH 1446/2172] avfilter/dnn: add log context to ff_get_dnn_module Print backend type when failed. Signed-off-by: Zhao Zhili --- libavfilter/dnn/dnn_interface.c | 6 ++++-- libavfilter/dnn_filter_common.c | 2 +- libavfilter/dnn_interface.h | 2 +- 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/libavfilter/dnn/dnn_interface.c b/libavfilter/dnn/dnn_interface.c index a60dcb091bb..e843826aa6d 100644 --- a/libavfilter/dnn/dnn_interface.c +++ b/libavfilter/dnn/dnn_interface.c @@ -29,7 +29,7 @@ extern const DNNModule ff_dnn_backend_openvino; extern const DNNModule ff_dnn_backend_tf; -const DNNModule *ff_get_dnn_module(DNNBackendType backend_type) +const DNNModule *ff_get_dnn_module(DNNBackendType backend_type, void *log_ctx) { switch(backend_type){ #if (CONFIG_LIBTENSORFLOW == 1) @@ -41,7 +41,9 @@ const DNNModule *ff_get_dnn_module(DNNBackendType backend_type) return &ff_dnn_backend_openvino; #endif default: - av_log(NULL, AV_LOG_ERROR, "Module backend_type is not supported or enabled.\n"); + av_log(log_ctx, AV_LOG_ERROR, + "Module backend_type %d is not supported or enabled.\n", + backend_type); return NULL; } } diff --git a/libavfilter/dnn_filter_common.c b/libavfilter/dnn_filter_common.c index 7b34fd0c0a4..d175c919141 100644 --- a/libavfilter/dnn_filter_common.c +++ b/libavfilter/dnn_filter_common.c @@ -68,7 +68,7 @@ int ff_dnn_init(DnnContext *ctx, DNNFunctionType func_type, AVFilterContext *fil return AVERROR(EINVAL); } - ctx->dnn_module = ff_get_dnn_module(ctx->backend_type); + ctx->dnn_module = ff_get_dnn_module(ctx->backend_type, filter_ctx); if (!ctx->dnn_module) { av_log(filter_ctx, AV_LOG_ERROR, "could not create DNN module for requested backend\n"); return AVERROR(ENOMEM); diff --git a/libavfilter/dnn_interface.h b/libavfilter/dnn_interface.h index b2bfdd38e7c..20c6a0a8963 100644 --- a/libavfilter/dnn_interface.h +++ b/libavfilter/dnn_interface.h @@ -123,6 +123,6 @@ typedef struct DNNModule{ } DNNModule; // Initializes DNNModule depending on chosen backend. -const DNNModule *ff_get_dnn_module(DNNBackendType backend_type); +const DNNModule *ff_get_dnn_module(DNNBackendType backend_type, void *log_ctx); #endif From a887bc4ff117620031c043159ef421e1f3c66f21 Mon Sep 17 00:00:00 2001 From: Zhao Zhili Date: Sun, 30 Apr 2023 23:38:56 +0800 Subject: [PATCH 1447/2172] avfilter/vf_dnn_classify: replace magic number by enum value Signed-off-by: Zhao Zhili --- libavfilter/vf_dnn_classify.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libavfilter/vf_dnn_classify.c b/libavfilter/vf_dnn_classify.c index d242aebcfbb..c3f2762cf96 100644 --- a/libavfilter/vf_dnn_classify.c +++ b/libavfilter/vf_dnn_classify.c @@ -44,9 +44,9 @@ typedef struct DnnClassifyContext { #define OFFSET2(x) offsetof(DnnClassifyContext, x) #define FLAGS AV_OPT_FLAG_FILTERING_PARAM | AV_OPT_FLAG_VIDEO_PARAM static const AVOption dnn_classify_options[] = { - { "dnn_backend", "DNN backend", OFFSET(backend_type), AV_OPT_TYPE_INT, { .i64 = 2 }, INT_MIN, INT_MAX, FLAGS, "backend" }, + { "dnn_backend", "DNN backend", OFFSET(backend_type), AV_OPT_TYPE_INT, { .i64 = DNN_OV }, INT_MIN, INT_MAX, FLAGS, "backend" }, #if (CONFIG_LIBOPENVINO == 1) - { "openvino", "openvino backend flag", 0, AV_OPT_TYPE_CONST, { .i64 = 2 }, 0, 0, FLAGS, "backend" }, + { "openvino", "openvino backend flag", 0, AV_OPT_TYPE_CONST, { .i64 = DNN_OV }, 0, 0, FLAGS, "backend" }, #endif DNN_COMMON_OPTIONS { "confidence", "threshold of confidence", OFFSET2(confidence), AV_OPT_TYPE_FLOAT, { .dbl = 0.5 }, 0, 1, FLAGS}, From e7e80e20835b4209c1608377f75a44d4dd58ee10 Mon Sep 17 00:00:00 2001 From: Zhao Zhili Date: Sun, 30 Apr 2023 23:38:57 +0800 Subject: [PATCH 1448/2172] avfilter/vf_dnn_detect: replace magic number by enum value Signed-off-by: Zhao Zhili --- libavfilter/vf_dnn_detect.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/libavfilter/vf_dnn_detect.c b/libavfilter/vf_dnn_detect.c index 7e133f6af55..06efce02a63 100644 --- a/libavfilter/vf_dnn_detect.c +++ b/libavfilter/vf_dnn_detect.c @@ -43,12 +43,12 @@ typedef struct DnnDetectContext { #define OFFSET2(x) offsetof(DnnDetectContext, x) #define FLAGS AV_OPT_FLAG_FILTERING_PARAM | AV_OPT_FLAG_VIDEO_PARAM static const AVOption dnn_detect_options[] = { - { "dnn_backend", "DNN backend", OFFSET(backend_type), AV_OPT_TYPE_INT, { .i64 = 2 }, INT_MIN, INT_MAX, FLAGS, "backend" }, + { "dnn_backend", "DNN backend", OFFSET(backend_type), AV_OPT_TYPE_INT, { .i64 = DNN_OV }, INT_MIN, INT_MAX, FLAGS, "backend" }, #if (CONFIG_LIBTENSORFLOW == 1) - { "tensorflow", "tensorflow backend flag", 0, AV_OPT_TYPE_CONST, { .i64 = 1 }, 0, 0, FLAGS, "backend" }, + { "tensorflow", "tensorflow backend flag", 0, AV_OPT_TYPE_CONST, { .i64 = DNN_TF }, 0, 0, FLAGS, "backend" }, #endif #if (CONFIG_LIBOPENVINO == 1) - { "openvino", "openvino backend flag", 0, AV_OPT_TYPE_CONST, { .i64 = 2 }, 0, 0, FLAGS, "backend" }, + { "openvino", "openvino backend flag", 0, AV_OPT_TYPE_CONST, { .i64 = DNN_OV }, 0, 0, FLAGS, "backend" }, #endif DNN_COMMON_OPTIONS { "confidence", "threshold of confidence", OFFSET2(confidence), AV_OPT_TYPE_FLOAT, { .dbl = 0.5 }, 0, 1, FLAGS}, From e67af9e7f71fdb5a50941f51e4fdeab93691b908 Mon Sep 17 00:00:00 2001 From: Zhao Zhili Date: Sun, 30 Apr 2023 23:38:58 +0800 Subject: [PATCH 1449/2172] avfilter/vf_dnn_processing: replace magic number by enum value Signed-off-by: Zhao Zhili --- libavfilter/vf_dnn_processing.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/libavfilter/vf_dnn_processing.c b/libavfilter/vf_dnn_processing.c index 18ecf111fe4..95c3e0b99b8 100644 --- a/libavfilter/vf_dnn_processing.c +++ b/libavfilter/vf_dnn_processing.c @@ -45,12 +45,12 @@ typedef struct DnnProcessingContext { #define OFFSET(x) offsetof(DnnProcessingContext, dnnctx.x) #define FLAGS AV_OPT_FLAG_FILTERING_PARAM | AV_OPT_FLAG_VIDEO_PARAM static const AVOption dnn_processing_options[] = { - { "dnn_backend", "DNN backend", OFFSET(backend_type), AV_OPT_TYPE_INT, { .i64 = 1 }, INT_MIN, INT_MAX, FLAGS, "backend" }, + { "dnn_backend", "DNN backend", OFFSET(backend_type), AV_OPT_TYPE_INT, { .i64 = DNN_TF }, INT_MIN, INT_MAX, FLAGS, "backend" }, #if (CONFIG_LIBTENSORFLOW == 1) - { "tensorflow", "tensorflow backend flag", 0, AV_OPT_TYPE_CONST, { .i64 = 1 }, 0, 0, FLAGS, "backend" }, + { "tensorflow", "tensorflow backend flag", 0, AV_OPT_TYPE_CONST, { .i64 = DNN_TF }, 0, 0, FLAGS, "backend" }, #endif #if (CONFIG_LIBOPENVINO == 1) - { "openvino", "openvino backend flag", 0, AV_OPT_TYPE_CONST, { .i64 = 2 }, 0, 0, FLAGS, "backend" }, + { "openvino", "openvino backend flag", 0, AV_OPT_TYPE_CONST, { .i64 = DNN_OV }, 0, 0, FLAGS, "backend" }, #endif DNN_COMMON_OPTIONS { NULL } From f3495ef4f88a01e2bf4481244b31a650830c65c0 Mon Sep 17 00:00:00 2001 From: Zhao Zhili Date: Sun, 30 Apr 2023 23:38:59 +0800 Subject: [PATCH 1450/2172] avfilter/dnn_backend_tf: remove unused define Signed-off-by: Zhao Zhili --- libavfilter/dnn/dnn_backend_tf.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/libavfilter/dnn/dnn_backend_tf.c b/libavfilter/dnn/dnn_backend_tf.c index e6ebd175953..74fe06d6fb6 100644 --- a/libavfilter/dnn/dnn_backend_tf.c +++ b/libavfilter/dnn/dnn_backend_tf.c @@ -474,8 +474,6 @@ static int load_tf_model(TFModel *tf_model, const char *model_filename) return 0; } -#define NAME_BUFFER_SIZE 256 - static void dnn_free_model_tf(DNNModel **model) { TFModel *tf_model; From d9f41a343ef9f77fa0d0485f1ea134837b101085 Mon Sep 17 00:00:00 2001 From: Zhao Zhili Date: Sun, 30 Apr 2023 23:39:00 +0800 Subject: [PATCH 1451/2172] avfilter/dnn_backend_tf: check TF_OperationOutputType return value This also fixed a warning: implicit conversion from enumeration type 'TF_DataType' (aka 'enum TF_DataType') to different enumeration type 'DNNDataType'. Signed-off-by: Zhao Zhili --- libavfilter/dnn/dnn_backend_tf.c | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/libavfilter/dnn/dnn_backend_tf.c b/libavfilter/dnn/dnn_backend_tf.c index 74fe06d6fb6..552a9f2fa1d 100644 --- a/libavfilter/dnn/dnn_backend_tf.c +++ b/libavfilter/dnn/dnn_backend_tf.c @@ -274,6 +274,7 @@ static int get_input_tf(void *model, DNNData *input, const char *input_name) TFModel *tf_model = model; TFContext *ctx = &tf_model->ctx; TF_Status *status; + TF_DataType dt; int64_t dims[4]; TF_Output tf_output; @@ -284,7 +285,18 @@ static int get_input_tf(void *model, DNNData *input, const char *input_name) } tf_output.index = 0; - input->dt = TF_OperationOutputType(tf_output); + dt = TF_OperationOutputType(tf_output); + switch (dt) { + case TF_FLOAT: + input->dt = DNN_FLOAT; + break; + case TF_UINT8: + input->dt = DNN_UINT8; + break; + default: + av_log(ctx, AV_LOG_ERROR, "Unsupported output type %d in model\n", dt); + return AVERROR(EINVAL); + } input->order = DCO_RGB; status = TF_NewStatus(); From b0c0fedcda87d3699d65576dbea55c2e4ba76253 Mon Sep 17 00:00:00 2001 From: Zhao Zhili Date: Sun, 30 Apr 2023 23:39:01 +0800 Subject: [PATCH 1452/2172] avfilter/dnn_backend_tf: fix use of uninitialized value Signed-off-by: Zhao Zhili --- libavfilter/dnn/dnn_backend_tf.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavfilter/dnn/dnn_backend_tf.c b/libavfilter/dnn/dnn_backend_tf.c index 552a9f2fa1d..c15f1a7d3b7 100644 --- a/libavfilter/dnn/dnn_backend_tf.c +++ b/libavfilter/dnn/dnn_backend_tf.c @@ -625,7 +625,7 @@ static int fill_model_input_tf(TFModel *tf_model, TFRequestItem *request) { DNNData input; LastLevelTaskItem *lltask; TaskItem *task; - TFInferRequest *infer_request; + TFInferRequest *infer_request = NULL; TFContext *ctx = &tf_model->ctx; int ret = 0; From 3a5d95e3fad53ef05de78edeaf7e655d1b7495c2 Mon Sep 17 00:00:00 2001 From: Zhao Zhili Date: Sun, 30 Apr 2023 23:39:02 +0800 Subject: [PATCH 1453/2172] avfilter/dnn_backend_tf: silence implicit cast warning Signed-off-by: Zhao Zhili --- libavfilter/dnn/dnn_backend_tf.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavfilter/dnn/dnn_backend_tf.c b/libavfilter/dnn/dnn_backend_tf.c index c15f1a7d3b7..b521de7fbe8 100644 --- a/libavfilter/dnn/dnn_backend_tf.c +++ b/libavfilter/dnn/dnn_backend_tf.c @@ -735,7 +735,7 @@ static void infer_completion_callback(void *args) { outputs[i].width = TF_Dim(infer_request->output_tensors[i], 2); outputs[i].channels = TF_Dim(infer_request->output_tensors[i], 3); outputs[i].data = TF_TensorData(infer_request->output_tensors[i]); - outputs[i].dt = TF_TensorType(infer_request->output_tensors[i]); + outputs[i].dt = (DNNDataType)TF_TensorType(infer_request->output_tensors[i]); } switch (tf_model->model->func_type) { case DFT_PROCESS_FRAME: From 6220252f421cf0d7e96c68ea6c3e29986538d57a Mon Sep 17 00:00:00 2001 From: Zhao Zhili Date: Thu, 4 May 2023 11:59:59 +0800 Subject: [PATCH 1454/2172] configure: add pkg-config check for libopenvino Signed-off-by: Zhao Zhili --- configure | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/configure b/configure index 0a7efb242b7..2fbe03921a1 100755 --- a/configure +++ b/configure @@ -6752,7 +6752,8 @@ enabled libopenh264 && require_pkg_config libopenh264 openh264 wels/codec_ enabled libopenjpeg && { check_pkg_config libopenjpeg "libopenjp2 >= 2.1.0" openjpeg.h opj_version || { require_pkg_config libopenjpeg "libopenjp2 >= 2.1.0" openjpeg.h opj_version -DOPJ_STATIC && add_cppflags -DOPJ_STATIC; } } enabled libopenmpt && require_pkg_config libopenmpt "libopenmpt >= 0.2.6557" libopenmpt/libopenmpt.h openmpt_module_create -lstdc++ && append libopenmpt_extralibs "-lstdc++" -enabled libopenvino && require libopenvino c_api/ie_c_api.h ie_c_api_version -linference_engine_c_api +enabled libopenvino && { check_pkg_config libopenvino openvino c_api/ie_c_api.h ie_c_api_version || + require libopenvino c_api/ie_c_api.h ie_c_api_version -linference_engine_c_api; } enabled libopus && { enabled libopus_decoder && { require_pkg_config libopus opus opus_multistream.h opus_multistream_decoder_create From 32a749c7a6890145202266bb269eeea362919751 Mon Sep 17 00:00:00 2001 From: Zhao Zhili Date: Thu, 4 May 2023 21:06:03 +0800 Subject: [PATCH 1455/2172] avfilter/dnn_backend_openvino: fix log message Signed-off-by: Zhao Zhili --- libavfilter/dnn/dnn_backend_openvino.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavfilter/dnn/dnn_backend_openvino.c b/libavfilter/dnn/dnn_backend_openvino.c index 7db2e7a10fd..46cbe8270ed 100644 --- a/libavfilter/dnn/dnn_backend_openvino.c +++ b/libavfilter/dnn/dnn_backend_openvino.c @@ -380,7 +380,7 @@ static int init_model_ov(OVModel *ov_model, const char *input_name, const char * if (status != OK) { if (status == NOT_FOUND) { av_log(ctx, AV_LOG_ERROR, "Could not find \"%s\" in model, failed to set output layout as NHWC, "\ - "all output(s) are: \"%s\"\n", input_name, ov_model->all_output_names); + "all output(s) are: \"%s\"\n", output_name, ov_model->all_output_names); } else{ av_log(ctx, AV_LOG_ERROR, "Failed to set layout as NHWC for output %s\n", output_name); } From b7e79ba395ef3a0b3bca968eee8cbe1243ad19bb Mon Sep 17 00:00:00 2001 From: Zhao Zhili Date: Mon, 22 May 2023 22:07:49 +0800 Subject: [PATCH 1456/2172] avformat/mov: decrease probe score for a random tag The tag comes from samples/ffmpeg/mov/unrecognized/bartjones.mov really looks like some random data. Now the random tag matched another file, which isn't a mov. Signed-off-by: Zhao Zhili --- libavformat/mov.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/libavformat/mov.c b/libavformat/mov.c index 192e460038e..a8d004e02ba 100644 --- a/libavformat/mov.c +++ b/libavformat/mov.c @@ -8111,6 +8111,8 @@ static int mov_probe(const AVProbeData *p) score = FFMAX(score, AVPROBE_SCORE_MAX - 5); break; case MKTAG(0x82,0x82,0x7f,0x7d): + score = FFMAX(score, AVPROBE_SCORE_EXTENSION - 5); + break; case MKTAG('s','k','i','p'): case MKTAG('u','u','i','d'): case MKTAG('p','r','f','l'): From 024c30aa3b3cdb7d32fa5d79b0973ab8f3065ead Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Thu, 8 Jun 2023 12:05:47 +0200 Subject: [PATCH 1457/2172] avcodec/exr: remove wrong scaling for 32bit DWA compression --- libavcodec/exr.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/libavcodec/exr.c b/libavcodec/exr.c index 8cc6b056b29..fae1d08ab03 100644 --- a/libavcodec/exr.c +++ b/libavcodec/exr.c @@ -1119,7 +1119,6 @@ static int dwa_uncompress(const EXRContext *s, const uint8_t *src, int compresse } { - const float scale = s->pixel_type == EXR_FLOAT ? 2.f : 1.f; const int o = s->nb_channels == 4; float *bo = ((float *)td->uncompressed_data) + y * td->xsize * s->nb_channels + td->xsize * (o + 0) + x; @@ -1137,9 +1136,9 @@ static int dwa_uncompress(const EXRContext *s, const uint8_t *src, int compresse convert(yb[idx], ub[idx], vb[idx], &bo[xx], &go[xx], &ro[xx]); - bo[xx] = to_linear(bo[xx], scale); - go[xx] = to_linear(go[xx], scale); - ro[xx] = to_linear(ro[xx], scale); + bo[xx] = to_linear(bo[xx], 1.f); + go[xx] = to_linear(go[xx], 1.f); + ro[xx] = to_linear(ro[xx], 1.f); } bo += td->xsize * s->nb_channels; From 18b2ecc24778140c2bc798ed64842dc8feb6dc3a Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Sun, 12 Feb 2023 20:19:14 +0100 Subject: [PATCH 1458/2172] avcodec/wavarc: add 5elp mode support --- libavcodec/wavarc.c | 349 +++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 348 insertions(+), 1 deletion(-) diff --git a/libavcodec/wavarc.c b/libavcodec/wavarc.c index 7bfc276df4a..6daad6a5a11 100644 --- a/libavcodec/wavarc.c +++ b/libavcodec/wavarc.c @@ -30,6 +30,8 @@ #include "unary.h" typedef struct WavArcContext { + AVClass *av_class; + GetBitContext gb; int shift; @@ -47,6 +49,16 @@ typedef struct WavArcContext { int pred[2][70]; int filter[2][70]; int samples[2][640]; + uint8_t model[256]; + uint16_t freqs[257]; + uint16_t ac_value; + uint16_t ac_low; + uint16_t ac_high; + uint16_t range_high; + uint16_t range_low; + uint16_t freq_range; + int ac_pred[70]; + int ac_out[570]; } WavArcContext; static av_cold int wavarc_init(AVCodecContext *avctx) @@ -90,6 +102,7 @@ static av_cold int wavarc_init(AVCodecContext *avctx) case MKTAG('2','S','L','P'): case MKTAG('3','N','L','P'): case MKTAG('4','A','L','P'): + case MKTAG('5','E','L','P'): s->nb_samples = 570; s->offset = 70; break; @@ -343,7 +356,7 @@ static int decode_2slp(AVCodecContext *avctx, break; case 0: order = get_urice(gb, 2); - if ((unsigned)order >= FF_ARRAY_ELEMS(s->filter[ch])) + if ((unsigned)order > FF_ARRAY_ELEMS(s->filter[ch])) return AVERROR_INVALIDDATA; for (int o = 0; o < order; o++) s->filter[ch][o] = get_srice(gb, 2); @@ -378,6 +391,337 @@ static int decode_2slp(AVCodecContext *avctx, return 0; } +static int ac_init(AVCodecContext *avctx, + WavArcContext *s, GetBitContext *gb) +{ + s->ac_low = 0; + s->ac_high = 0xffffu; + s->ac_value = get_bits(gb, 16); + + s->freq_range = s->freqs[256]; + if (!s->freq_range) + return AVERROR_INVALIDDATA; + return 0; +} + +static unsigned ac_get_prob(WavArcContext *s) +{ + return ((s->freq_range - 1) + ((unsigned)s->ac_value - (unsigned)s->ac_low) * + (unsigned)s->freq_range) / (((unsigned)s->ac_high - (unsigned)s->ac_low) + 1) & 0xffffu; +} + +static unsigned ac_map_symbol(WavArcContext *s, unsigned prob) +{ + int idx = 255; + + while (prob < s->freqs[idx]) + idx--; + + s->range_high = s->freqs[idx + 1]; + s->range_low = s->freqs[idx]; + + return idx; +} + +static int ac_normalize(AVCodecContext *avctx, WavArcContext *s, GetBitContext *gb) +{ + int range; + + range = (unsigned)s->ac_high - (unsigned)s->ac_low + 1; + s->ac_high = (int16_t)((range * (unsigned)s->range_high) / (unsigned)s->freq_range) + -1 + s->ac_low; + s->ac_low += (int16_t)((range * (unsigned)s->range_low) / (unsigned)s->freq_range); + + for (;;) { + if ((s->ac_high & 0x8000) != (s->ac_low & 0x8000)) { + if ((s->ac_low & 0x4000) == 0 || (s->ac_high & 0x4000) != 0) + return 0; + s->ac_value ^= 0x4000; + s->ac_low &= 0x3fff; + s->ac_high |= 0x4000; + } + + s->ac_low = s->ac_low << 1; + s->ac_high = s->ac_high * 2 + 1; + if (s->ac_high < s->ac_low) { + av_log(avctx, AV_LOG_ERROR, "invalid state\n"); + return AVERROR_INVALIDDATA; + } + + if (get_bits_left(gb) <= 0) { + av_log(avctx, AV_LOG_ERROR, "overread in arithmetic coder\n"); + return AVERROR_INVALIDDATA; + } + + s->ac_value = s->ac_value * 2 + get_bits1(gb); + } +} + +static void ac_init_model(WavArcContext *s) +{ + memset(s->freqs, 0, sizeof(s->freqs)); + + for (int n = 0; n < 256; n++) + s->freqs[n+1] = s->model[n] + s->freqs[n]; +} + +static int ac_read_model(AVCodecContext *avctx, + WavArcContext *s, + GetBitContext *gb) +{ + unsigned start, end; + + memset(s->model, 0, sizeof(s->model)); + + start = get_bits(gb, 8); + end = get_bits(gb, 8); + + for (;;) { + while (start <= end) + s->model[start++] = get_bits(gb, 8); + + if (get_bits_left(gb) < 8) + return AVERROR_INVALIDDATA; + + if (get_bits_left(gb) < 8) + return AVERROR_INVALIDDATA; + + start = get_bits(gb, 8); + if (!start) + break; + + end = get_bits(gb, 8); + } + + ac_init_model(s); + + return 0; +} + +static int decode_5elp(AVCodecContext *avctx, + WavArcContext *s, GetBitContext *gb) +{ + int ch, finished, fill, correlated, order = 0; + + ch = 0; + finished = 0; + while (!finished) { + int *samples = s->samples[ch]; + int *ac_pred = s->ac_pred; + int *ac_out = s->ac_out; + int k, block_type; + + if (get_bits_left(gb) <= 0) + return AVERROR_INVALIDDATA; + + memset(s->ac_out, 0, sizeof(s->ac_out)); + + block_type = get_urice(gb, 1); + av_log(avctx, AV_LOG_DEBUG, "block_type : %d\n", block_type); + + if (block_type >= 0 && block_type <= 7) { + k = 1 + (avctx->sample_fmt == AV_SAMPLE_FMT_S16P); + k = get_urice(gb, k) + 1; + } + + if (block_type <= 2 || block_type == 6 || block_type == 13 || + block_type == 14 || block_type == 15 || block_type == 19) { + order = get_urice(gb, 2); + if ((unsigned)order > FF_ARRAY_ELEMS(s->filter[ch])) + return AVERROR_INVALIDDATA; + for (int o = 0; o < order; o++) + s->filter[ch][o] = get_srice(gb, 2); + } + + if (block_type >= 0 && block_type <= 7) { + for (int n = 0; n < s->nb_samples; n++) + samples[n + 70] = get_srice(gb, k); + } else { + for (int n = 0; n < s->nb_samples; n++) + samples[n + 70] = 0; + } + + if (block_type >= 13 && block_type <= 20) { + const int ac_size = get_bits(gb, 12); + const int ac_pos = get_bits_count(gb); + GetBitContext ac_gb = *gb; + int ret; + + skip_bits_long(gb, ac_size); + ret = ac_read_model(avctx, s, &ac_gb); + if (ret < 0) { + av_log(avctx, AV_LOG_ERROR, "bad arithmetic model\n"); + return ret; + } + + ret = ac_init(avctx, s, &ac_gb); + if (ret < 0) { + av_log(avctx, AV_LOG_ERROR, "cannot init arithmetic decoder\n"); + return ret; + } + + for (int n = 0; n < s->nb_samples; n++) { + unsigned prob = ac_get_prob(s); + prob = ac_map_symbol(s, prob); + ac_out[n] = prob - 0x80; + if ((ret = ac_normalize(avctx, s, &ac_gb)) < 0) + return ret; + } + + if (get_bits_count(&ac_gb) != ac_pos + ac_size) { + av_log(avctx, AV_LOG_DEBUG, "over/under-read in arithmetic coder: %d\n", + ac_pos + ac_size - get_bits_count(&ac_gb)); + } + } + + switch (block_type) { + case 12: + s->eof = 1; + return AVERROR_EOF; + case 11: + s->nb_samples = get_urice(gb, 8); + if (s->nb_samples > 570) { + s->nb_samples = 570; + return AVERROR_INVALIDDATA; + } + continue; + case 10: + s->shift = get_urice(gb, 2); + continue; + case 9: + if (avctx->sample_fmt == AV_SAMPLE_FMT_U8P) { + fill = (int8_t)get_bits(gb, 8); + fill -= 0x80; + } else { + fill = (int16_t)get_bits(gb, 16); + fill -= 0x8000; + } + + for (int n = 0; n < s->nb_samples; n++) + samples[n + 70] = fill; + finished = 1; + break; + case 8: + for (int n = 0; n < s->nb_samples; n++) + samples[n + 70] = 0; + finished = 1; + break; + case 20: + case 7: + for (int n = 0; n < s->nb_samples; n++) + samples[n + 70] = ac_out[n] + samples[n + 69] * 3 - samples[n + 68] * 3 + samples[n + 67]; + finished = 1; + break; + case 19: + case 6: + for (int n = 0; n < s->nb_samples; n++) { + int sum = 15; + + for (int o = 0; o < order; o++) + sum += s->filter[ch][o] * (unsigned)samples[n + 70 - o - 1]; + + samples[n + 70] += ac_out[n] + (sum >> 4); + } + finished = 1; + break; + case 18: + case 5: + for (int n = 0; n < s->nb_samples; n++) + samples[n + 70] = ac_out[n] + samples[n + 69] * 2 - samples[n + 68]; + finished = 1; + break; + case 17: + case 4: + for (int n = 0; n < s->nb_samples; n++) + samples[n + 70] = ac_out[n]; + finished = 1; + break; + case 16: + case 3: + for (int n = 0; n < s->nb_samples; n++) + samples[n + 70] = ac_out[n] + samples[n + 69]; + finished = 1; + break; + case 15: + case 2: + for (int n = 0; n < 70; n++) { + ac_pred[n] = samples[n]; + samples[n] = 0; + } + + for (int n = 0; n < s->nb_samples; n++) { + int sum = 15; + + for (int o = 0; o < order; o++) + sum += s->filter[ch][o] * (unsigned)samples[n + 70 - o - 1]; + + samples[n + 70] += ac_out[n] + (sum >> 4); + } + + for (int n = 0; n < 70; n++) + samples[n] = ac_pred[n]; + + for (int n = 0; n < s->nb_samples; n++) + samples[n + 70] += samples[n + 69] * 2 - samples[n + 68]; + + finished = 1; + break; + case 14: + case 1: + for (int n = 0; n < 70; n++) { + ac_pred[n] = samples[n]; + samples[n] = 0; + } + + for (int n = 0; n < s->nb_samples; n++) { + int sum = 15; + + for (int o = 0; o < order; o++) + sum += s->filter[ch][o] * (unsigned)samples[n + 70 - o - 1]; + + samples[n + 70] += ac_out[n] + (sum >> 4); + } + + for (int n = 0; n < 70; n++) + samples[n] = ac_pred[n]; + + for (int n = 0; n < s->nb_samples; n++) + samples[n + 70] += samples[n + 69]; + + finished = 1; + break; + case 13: + case 0: + for (int n = 0; n < s->nb_samples; n++) { + int sum = 15; + + for (int o = 0; o < order; o++) + sum += s->filter[ch][o] * (unsigned)samples[n + 70 - o - 1]; + + samples[n + 70] += ac_out[n] + (sum >> 4); + } + finished = 1; + break; + default: + return AVERROR_INVALIDDATA; + } + + if (finished == 1 && avctx->ch_layout.nb_channels == 2) { + if (ch == 0) + correlated = get_bits1(gb); + finished = ch != 0; + do_stereo(s, ch, correlated, 70); + ch = 1; + } + } + + if (avctx->ch_layout.nb_channels == 1) { + for (int n = 0; n < 70; n++) + s->samples[0][n] = s->samples[0][s->nb_samples + n]; + } + + return 0; +} + static int wavarc_decode(AVCodecContext *avctx, AVFrame *frame, int *got_frame_ptr, AVPacket *pkt) { @@ -424,6 +768,9 @@ static int wavarc_decode(AVCodecContext *avctx, AVFrame *frame, case MKTAG('4','A','L','P'): ret = decode_2slp(avctx, s, gb); break; + case MKTAG('5','E','L','P'): + ret = decode_5elp(avctx, s, gb); + break; default: ret = AVERROR_INVALIDDATA; } From d78bffbf3df1f040c30af7b74113ef74cf10d5e9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Storsj=C3=B6?= Date: Wed, 7 Jun 2023 21:56:56 +0300 Subject: [PATCH 1459/2172] libavutil: Add version bump for new aarch64 cpu flags MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This was missed in 397cb623c85a515663f410821ba2dded3404112f. Signed-off-by: Martin Storsjö --- libavutil/version.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavutil/version.h b/libavutil/version.h index 0d8434493f1..dbdf0bd64ad 100644 --- a/libavutil/version.h +++ b/libavutil/version.h @@ -79,7 +79,7 @@ */ #define LIBAVUTIL_VERSION_MAJOR 58 -#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 25c937c0e03895866d9f5bcc659ad6afc53e20f9 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Thu, 8 Jun 2023 10:26:33 -0400 Subject: [PATCH 1460/2172] avformat/jpegxl_probe: Remove intermediate macro obfuscation around get_bits*() Signed-off-by: Michael Niedermayer --- libavformat/jpegxl_probe.c | 169 +++++++++++++++++++------------------ 1 file changed, 85 insertions(+), 84 deletions(-) diff --git a/libavformat/jpegxl_probe.c b/libavformat/jpegxl_probe.c index a3845b037db..1d9c014f197 100644 --- a/libavformat/jpegxl_probe.c +++ b/libavformat/jpegxl_probe.c @@ -57,49 +57,50 @@ enum JpegXLPrimaries { FF_JPEGXL_PR_P3 = 11, }; -#define jxl_bits(n) get_bits_long(gb, (n)) -#define jxl_bits_skip(n) skip_bits_long(gb, (n)) -#define jxl_u32(c0, c1, c2, c3, u0, u1, u2, u3) jpegxl_u32(gb, \ - (const uint32_t[]){c0, c1, c2, c3}, (const uint32_t[]){u0, u1, u2, u3}) -#define jxl_u64() jpegxl_u64(gb) -#define jxl_enum() jxl_u32(0, 1, 2, 18, 0, 0, 4, 6) - /* read a U32(c_i + u(u_i)) */ -static uint32_t jpegxl_u32(GetBitContext *gb, - const uint32_t constants[4], const uint32_t ubits[4]) +static av_always_inline uint32_t jxl_u32(GetBitContext *gb, + uint32_t c0, uint32_t c1, uint32_t c2, uint32_t c3, + uint32_t u0, uint32_t u1, uint32_t u2, uint32_t u3) { - uint32_t ret, choice = jxl_bits(2); + const uint32_t constants[4] = {c0, c1, c2, c3}; + const uint32_t ubits [4] = {u0, u1, u2, u3}; + uint32_t ret, choice = get_bits(gb, 2); ret = constants[choice]; if (ubits[choice]) - ret += jxl_bits(ubits[choice]); + ret += get_bits_long(gb, ubits[choice]); return ret; } +static av_always_inline uint32_t jxl_enum(GetBitContext *gb) +{ + return jxl_u32(gb, 0, 1, 2, 18, 0, 0, 4, 6); +} + /* read a U64() */ static uint64_t jpegxl_u64(GetBitContext *gb) { uint64_t shift = 12, ret; - switch (jxl_bits(2)) { + switch (get_bits(gb, 2)) { case 0: ret = 0; break; case 1: - ret = 1 + jxl_bits(4); + ret = 1 + get_bits(gb, 4); break; case 2: - ret = 17 + jxl_bits(8); + ret = 17 + get_bits(gb, 8); break; case 3: - ret = jxl_bits(12); - while (jxl_bits(1)) { + ret = get_bits(gb, 12); + while (get_bits1(gb)) { if (shift < 60) { - ret |= (uint64_t)jxl_bits(8) << shift; + ret |= (uint64_t)get_bits(gb, 8) << shift; shift += 8; } else { - ret |= (uint64_t)jxl_bits(4) << shift; + ret |= (uint64_t)get_bits(gb, 4) << shift; break; } } @@ -142,18 +143,18 @@ static int jpegxl_read_size_header(GetBitContext *gb) { uint32_t width, height; - if (jxl_bits(1)) { + if (get_bits1(gb)) { /* small size header */ - height = (jxl_bits(5) + 1) << 3; - width = jpegxl_width_from_ratio(height, jxl_bits(3)); + height = (get_bits(gb, 5) + 1) << 3; + width = jpegxl_width_from_ratio(height, get_bits(gb, 3)); if (!width) - width = (jxl_bits(5) + 1) << 3; + width = (get_bits(gb, 5) + 1) << 3; } else { /* large size header */ - height = 1 + jxl_u32(0, 0, 0, 0, 9, 13, 18, 30); - width = jpegxl_width_from_ratio(height, jxl_bits(3)); + height = 1 + jxl_u32(gb, 0, 0, 0, 0, 9, 13, 18, 30); + width = jpegxl_width_from_ratio(height, get_bits(gb, 3)); if (!width) - width = 1 + jxl_u32(0, 0, 0, 0, 9, 13, 18, 30); + width = 1 + jxl_u32(gb, 0, 0, 0, 0, 9, 13, 18, 30); } if (width > (1 << 18) || height > (1 << 18) || (width >> 4) * (height >> 4) > (1 << 20)) @@ -170,18 +171,18 @@ static int jpegxl_read_preview_header(GetBitContext *gb) { uint32_t width, height; - if (jxl_bits(1)) { + if (get_bits1(gb)) { /* coded height and width divided by eight */ - height = jxl_u32(16, 32, 1, 33, 0, 0, 5, 9) << 3; - width = jpegxl_width_from_ratio(height, jxl_bits(3)); + height = jxl_u32(gb, 16, 32, 1, 33, 0, 0, 5, 9) << 3; + width = jpegxl_width_from_ratio(height, get_bits(gb, 3)); if (!width) - width = jxl_u32(16, 32, 1, 33, 0, 0, 5, 9) << 3; + width = jxl_u32(gb, 16, 32, 1, 33, 0, 0, 5, 9) << 3; } else { /* full height and width coded */ - height = jxl_u32(1, 65, 321, 1345, 6, 8, 10, 12); - width = jpegxl_width_from_ratio(height, jxl_bits(3)); + height = jxl_u32(gb, 1, 65, 321, 1345, 6, 8, 10, 12); + width = jpegxl_width_from_ratio(height, get_bits(gb, 3)); if (!width) - width = jxl_u32(1, 65, 321, 1345, 6, 8, 10, 12); + width = jxl_u32(gb, 1, 65, 321, 1345, 6, 8, 10, 12); } if (width > 4096 || height > 4096) return -1; @@ -194,13 +195,13 @@ static int jpegxl_read_preview_header(GetBitContext *gb) */ static void jpegxl_skip_bit_depth(GetBitContext *gb) { - if (jxl_bits(1)) { + if (get_bits1(gb)) { /* float samples */ - jxl_u32(32, 16, 24, 1, 0, 0, 0, 6); /* mantissa */ - jxl_bits_skip(4); /* exponent */ + jxl_u32(gb, 32, 16, 24, 1, 0, 0, 0, 6); /* mantissa */ + skip_bits_long(gb, 4); /* exponent */ } else { /* integer samples */ - jxl_u32(8, 10, 12, 1, 0, 0, 0, 6); + jxl_u32(gb, 8, 10, 12, 1, 0, 0, 0, 6); } } @@ -210,34 +211,34 @@ static void jpegxl_skip_bit_depth(GetBitContext *gb) */ static int jpegxl_read_extra_channel_info(GetBitContext *gb, int validate_level) { - int all_default = jxl_bits(1); + int all_default = get_bits1(gb); uint32_t type, name_len = 0; if (!all_default) { - type = jxl_enum(); + type = jxl_enum(gb); if (type > 63) return -1; /* enum types cannot be 64+ */ if (type == FF_JPEGXL_CT_BLACK && validate_level) return -1; jpegxl_skip_bit_depth(gb); - jxl_u32(0, 3, 4, 1, 0, 0, 0, 3); /* dim-shift */ + jxl_u32(gb, 0, 3, 4, 1, 0, 0, 0, 3); /* dim-shift */ /* max of name_len is 1071 = 48 + 2^10 - 1 */ - name_len = jxl_u32(0, 0, 16, 48, 0, 4, 5, 10); + name_len = jxl_u32(gb, 0, 0, 16, 48, 0, 4, 5, 10); } else { type = FF_JPEGXL_CT_ALPHA; } /* skip over the name */ - jxl_bits_skip(8 * name_len); + skip_bits_long(gb, 8 * name_len); if (!all_default && type == FF_JPEGXL_CT_ALPHA) - jxl_bits_skip(1); + skip_bits1(gb); if (type == FF_JPEGXL_CT_SPOT_COLOR) - jxl_bits_skip(16 * 4); + skip_bits_long(gb, 16 * 4); if (type == FF_JPEGXL_CT_CFA) - jxl_u32(1, 0, 3, 19, 0, 2, 4, 8); + jxl_u32(gb, 1, 0, 3, 19, 0, 2, 4, 8); return 0; } @@ -256,40 +257,40 @@ int ff_jpegxl_verify_codestream_header(const uint8_t *buf, int buflen, int valid if (ret < 0) return ret; - if (jxl_bits(16) != FF_JPEGXL_CODESTREAM_SIGNATURE_LE) + if (get_bits_long(gb, 16) != FF_JPEGXL_CODESTREAM_SIGNATURE_LE) return -1; if (jpegxl_read_size_header(gb) < 0 && validate_level) return -1; - all_default = jxl_bits(1); + all_default = get_bits1(gb); if (!all_default) - extra_fields = jxl_bits(1); + extra_fields = get_bits1(gb); if (extra_fields) { - jxl_bits_skip(3); /* orientation */ + skip_bits_long(gb, 3); /* orientation */ /* * intrinstic size * any size header here is valid, but as it * is variable length we have to read it */ - if (jxl_bits(1)) + if (get_bits1(gb)) jpegxl_read_size_header(gb); /* preview header */ - if (jxl_bits(1)) { + if (get_bits1(gb)) { if (jpegxl_read_preview_header(gb) < 0) return -1; } /* animation header */ - if (jxl_bits(1)) { + if (get_bits1(gb)) { animation_offset = get_bits_count(gb); - jxl_u32(100, 1000, 1, 1, 0, 0, 10, 30); - jxl_u32(1, 1001, 1, 1, 0, 0, 8, 10); - jxl_u32(0, 0, 0, 0, 0, 3, 16, 32); - jxl_bits_skip(1); + jxl_u32(gb, 100, 1000, 1, 1, 0, 0, 10, 30); + jxl_u32(gb, 1, 1001, 1, 1, 0, 0, 8, 10); + jxl_u32(gb, 0, 0, 0, 0, 0, 3, 16, 32); + skip_bits_long(gb, 1); } } @@ -297,10 +298,10 @@ int ff_jpegxl_verify_codestream_header(const uint8_t *buf, int buflen, int valid jpegxl_skip_bit_depth(gb); /* modular_16bit_buffers must equal 1 */ - if (!jxl_bits(1) && validate_level) + if (!get_bits1(gb) && validate_level) return -1; - num_extra_channels = jxl_u32(0, 1, 2, 1, 0, 0, 4, 12); + num_extra_channels = jxl_u32(gb, 0, 1, 2, 1, 0, 0, 4, 12); if (num_extra_channels > 4 && validate_level) return -1; for (uint32_t i = 0; i < num_extra_channels; i++) { @@ -308,85 +309,85 @@ int ff_jpegxl_verify_codestream_header(const uint8_t *buf, int buflen, int valid return -1; } - xyb_encoded = jxl_bits(1); + xyb_encoded = get_bits1(gb); /* color encoding bundle */ - if (!jxl_bits(1)) { + if (!get_bits1(gb)) { uint32_t color_space; - have_icc_profile = jxl_bits(1); - color_space = jxl_enum(); + have_icc_profile = get_bits1(gb); + color_space = jxl_enum(gb); if (color_space > 63) return -1; if (!have_icc_profile) { if (color_space != FF_JPEGXL_CS_XYB) { - uint32_t white_point = jxl_enum(); + uint32_t white_point = jxl_enum(gb); if (white_point > 63) return -1; if (white_point == FF_JPEGXL_WP_CUSTOM) { /* ux and uy values */ - jxl_u32(0, 524288, 1048576, 2097152, 19, 19, 20, 21); - jxl_u32(0, 524288, 1048576, 2097152, 19, 19, 20, 21); + jxl_u32(gb, 0, 524288, 1048576, 2097152, 19, 19, 20, 21); + jxl_u32(gb, 0, 524288, 1048576, 2097152, 19, 19, 20, 21); } if (color_space != FF_JPEGXL_CS_GRAY) { /* primaries */ - uint32_t primaries = jxl_enum(); + uint32_t primaries = jxl_enum(gb); if (primaries > 63) return -1; if (primaries == FF_JPEGXL_PR_CUSTOM) { /* ux/uy values for r,g,b */ for (int i = 0; i < 6; i++) - jxl_u32(0, 524288, 1048576, 2097152, 19, 19, 20, 21); + jxl_u32(gb, 0, 524288, 1048576, 2097152, 19, 19, 20, 21); } } } /* transfer characteristics */ - if (jxl_bits(1)) { + if (get_bits1(gb)) { /* gamma */ - jxl_bits_skip(24); + skip_bits_long(gb, 24); } else { /* transfer function */ - if (jxl_enum() > 63) + if (jxl_enum(gb) > 63) return -1; } /* rendering intent */ - if (jxl_enum() > 63) + if (jxl_enum(gb) > 63) return -1; } } /* tone mapping bundle */ - if (extra_fields && !jxl_bits(1)) - jxl_bits_skip(16 + 16 + 1 + 16); + if (extra_fields && !get_bits1(gb)) + skip_bits_long(gb, 16 + 16 + 1 + 16); - extensions = jxl_u64(); + extensions = jpegxl_u64(gb); if (extensions) { for (int i = 0; i < 64; i++) { if (extensions & (UINT64_C(1) << i)) - jxl_u64(); + jpegxl_u64(gb); } } } /* default transform */ - if (!jxl_bits(1)) { + if (!get_bits1(gb)) { /* opsin inverse matrix */ - if (xyb_encoded && !jxl_bits(1)) - jxl_bits_skip(16 * 16); + if (xyb_encoded && !get_bits1(gb)) + skip_bits_long(gb, 16 * 16); /* cw_mask and default weights */ - if (jxl_bits(1)) - jxl_bits_skip(16 * 15); - if (jxl_bits(1)) - jxl_bits_skip(16 * 55); - if (jxl_bits(1)) - jxl_bits_skip(16 * 210); + if (get_bits1(gb)) + skip_bits_long(gb, 16 * 15); + if (get_bits1(gb)) + skip_bits_long(gb, 16 * 55); + if (get_bits1(gb)) + skip_bits_long(gb, 16 * 210); } if (!have_icc_profile) { int bits_remaining = 7 - (get_bits_count(gb) - 1) % 8; - if (bits_remaining && jxl_bits(bits_remaining)) + if (bits_remaining && get_bits(gb, bits_remaining)) return -1; } From 1ec4553e355039ce69abf8e49389fa43f1f55fc5 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Thu, 8 Jun 2023 10:26:34 -0400 Subject: [PATCH 1461/2172] avformat/jpegxl_probe: check length instead of blindly reading Enable the checked bitreader to avoid overread. Also add a few checks in loops and between blocks so we exit instead of continued execution. Alternatively we could add manual checks so that no overread can happen. This would be slightly faster but a bit more work and a bit more fragile Fixes: Out of array accesses Fixes: 59640/clusterfuzz-testcase-minimized-ffmpeg_dem_JPEGXL_ANIM_fuzzer-6584117345779712 Found-by: continuous fuzzing process https://github.com/google/oss-fuzz/tree/master/projects/ffmpeg Signed-off-by: Michael Niedermayer --- libavformat/jpegxl_probe.c | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/libavformat/jpegxl_probe.c b/libavformat/jpegxl_probe.c index 1d9c014f197..e15e9eee492 100644 --- a/libavformat/jpegxl_probe.c +++ b/libavformat/jpegxl_probe.c @@ -21,6 +21,7 @@ #include "jpegxl_probe.h" +#define UNCHECKED_BITSTREAM_READER 0 #define BITSTREAM_READER_LE #include "libavcodec/get_bits.h" @@ -293,6 +294,8 @@ int ff_jpegxl_verify_codestream_header(const uint8_t *buf, int buflen, int valid skip_bits_long(gb, 1); } } + if (get_bits_left(gb) < 1) + return AVERROR_INVALIDDATA; if (!all_default) { jpegxl_skip_bit_depth(gb); @@ -307,6 +310,8 @@ int ff_jpegxl_verify_codestream_header(const uint8_t *buf, int buflen, int valid for (uint32_t i = 0; i < num_extra_channels; i++) { if (jpegxl_read_extra_channel_info(gb, validate_level) < 0) return -1; + if (get_bits_left(gb) < 1) + return AVERROR_INVALIDDATA; } xyb_encoded = get_bits1(gb); @@ -336,8 +341,11 @@ int ff_jpegxl_verify_codestream_header(const uint8_t *buf, int buflen, int valid return -1; if (primaries == FF_JPEGXL_PR_CUSTOM) { /* ux/uy values for r,g,b */ - for (int i = 0; i < 6; i++) + for (int i = 0; i < 6; i++) { jxl_u32(gb, 0, 524288, 1048576, 2097152, 19, 19, 20, 21); + if (get_bits_left(gb) < 1) + return AVERROR_INVALIDDATA; + } } } } @@ -363,10 +371,14 @@ int ff_jpegxl_verify_codestream_header(const uint8_t *buf, int buflen, int valid skip_bits_long(gb, 16 + 16 + 1 + 16); extensions = jpegxl_u64(gb); + if (get_bits_left(gb) < 1) + return AVERROR_INVALIDDATA; if (extensions) { for (int i = 0; i < 64; i++) { if (extensions & (UINT64_C(1) << i)) jpegxl_u64(gb); + if (get_bits_left(gb) < 1) + return AVERROR_INVALIDDATA; } } } From 09621fd7d93a12974e9664b2aebb8237e5c46f03 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Thu, 8 Jun 2023 10:26:35 -0400 Subject: [PATCH 1462/2172] avformat/jpegxl_probe: Forward error codes Signed-off-by: Michael Niedermayer --- libavformat/jpegxl_probe.c | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/libavformat/jpegxl_probe.c b/libavformat/jpegxl_probe.c index e15e9eee492..88492cb772d 100644 --- a/libavformat/jpegxl_probe.c +++ b/libavformat/jpegxl_probe.c @@ -261,8 +261,8 @@ int ff_jpegxl_verify_codestream_header(const uint8_t *buf, int buflen, int valid if (get_bits_long(gb, 16) != FF_JPEGXL_CODESTREAM_SIGNATURE_LE) return -1; - if (jpegxl_read_size_header(gb) < 0 && validate_level) - return -1; + if ((ret = jpegxl_read_size_header(gb)) < 0 && validate_level) + return ret; all_default = get_bits1(gb); if (!all_default) @@ -281,8 +281,9 @@ int ff_jpegxl_verify_codestream_header(const uint8_t *buf, int buflen, int valid /* preview header */ if (get_bits1(gb)) { - if (jpegxl_read_preview_header(gb) < 0) - return -1; + ret = jpegxl_read_preview_header(gb); + if (ret < 0) + return ret; } /* animation header */ @@ -308,8 +309,9 @@ int ff_jpegxl_verify_codestream_header(const uint8_t *buf, int buflen, int valid if (num_extra_channels > 4 && validate_level) return -1; for (uint32_t i = 0; i < num_extra_channels; i++) { - if (jpegxl_read_extra_channel_info(gb, validate_level) < 0) - return -1; + ret = jpegxl_read_extra_channel_info(gb, validate_level); + if (ret < 0) + return ret; if (get_bits_left(gb) < 1) return AVERROR_INVALIDDATA; } From 1460acc2ac4c5687742b0fdfc9af89f9f0d28029 Mon Sep 17 00:00:00 2001 From: Zhao Zhili Date: Thu, 8 Jun 2023 10:45:56 +0800 Subject: [PATCH 1463/2172] avformat/hlsenc: fix CODECS attribute of H.264 1. Add avcc extradata support. 2. Add non-standard annexb support with 0 0 1 as prefix for SPS. Reviewed-by: Limin Wang Signed-off-by: Zhao Zhili --- libavformat/hlsenc.c | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/libavformat/hlsenc.c b/libavformat/hlsenc.c index 871afb571be..1e0848ce3db 100644 --- a/libavformat/hlsenc.c +++ b/libavformat/hlsenc.c @@ -355,9 +355,19 @@ static void write_codec_attr(AVStream *st, VariantStream *vs) if (st->codecpar->codec_id == AV_CODEC_ID_H264) { uint8_t *data = st->codecpar->extradata; - if (data && (data[0] | data[1] | data[2]) == 0 && data[3] == 1 && (data[4] & 0x1F) == 7) { + if (data) { + const uint8_t *p; + + if (AV_RB32(data) == 0x01 && (data[4] & 0x1F) == 7) + p = &data[5]; + else if (AV_RB24(data) == 0x01 && (data[3] & 0x1F) == 7) + p = &data[4]; + else if (data[0] == 0x01) /* avcC */ + p = &data[1]; + else + goto fail; snprintf(attr, sizeof(attr), - "avc1.%02x%02x%02x", data[5], data[6], data[7]); + "avc1.%02x%02x%02x", p[0], p[1], p[2]); } else { goto fail; } From 3b0ed2365c089f9eb9a462805796636edc53ff44 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Mon, 12 Jun 2023 14:38:44 +1000 Subject: [PATCH 1464/2172] vulkan/h264: set non-existing flag for invalid gaps This flag is used to indicate to the hw frames in the gaps, vaapi constructs it from a bunch of implicit API information around surface ids. vulkan should just send it explicitly. Reviewed-by: Lynne --- libavcodec/vulkan_h264.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/libavcodec/vulkan_h264.c b/libavcodec/vulkan_h264.c index 05482329713..4cfd83fc191 100644 --- a/libavcodec/vulkan_h264.c +++ b/libavcodec/vulkan_h264.c @@ -68,7 +68,14 @@ static int vk_h264_fill_pict(AVCodecContext *avctx, H264Picture **ref_src, .top_field_flag = is_field ? !!(picture_structure & PICT_TOP_FIELD) : 0, .bottom_field_flag = is_field ? !!(picture_structure & PICT_BOTTOM_FIELD) : 0, .used_for_long_term_reference = pic->reference && pic->long_ref, - .is_non_existing = 0, + /* + * flags.is_non_existing is used to indicate whether the picture is marked as + * “non-existing” as defined in section 8.2.5.2 of the ITU-T H.264 Specification; + * 8.2.5.2 Decoding process for gaps in frame_num + * corresponds to the code in h264_slice.c:h264_field_start, + * which sets the invalid_gap flag when decoding. + */ + .is_non_existing = pic->invalid_gap, }, }; From 2d59ca0a668a0bdf9c83b35fe3ad357f87f8a15d Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Sun, 4 Jun 2023 20:30:59 +0200 Subject: [PATCH 1465/2172] avcodec: add VMX1 decoder --- Changelog | 1 + configure | 1 + libavcodec/Makefile | 1 + libavcodec/allcodecs.c | 1 + libavcodec/codec_desc.c | 7 + libavcodec/codec_id.h | 1 + libavcodec/version.h | 2 +- libavcodec/vmixdec.c | 288 ++++++++++++++++++++++++++++++++++++++++ libavformat/riff.c | 1 + 9 files changed, 302 insertions(+), 1 deletion(-) create mode 100644 libavcodec/vmixdec.c diff --git a/Changelog b/Changelog index d51e03b8ebb..cd872d9bf28 100644 --- a/Changelog +++ b/Changelog @@ -16,6 +16,7 @@ version : - nlmeans_vulkan filter - RivaTuner video decoder - xfade_vulkan filter +- vMix video decoder version 6.0: - Radiance HDR image support diff --git a/configure b/configure index 2fbe03921a1..4ac7cc6c0bf 100755 --- a/configure +++ b/configure @@ -3006,6 +3006,7 @@ utvideo_encoder_select="bswapdsp huffman llvidencdsp" vble_decoder_select="llviddsp" vbn_decoder_select="texturedsp" vbn_encoder_select="texturedspenc" +vmix_decoder_select="idctdsp" vc1_decoder_select="blockdsp h264qpel intrax8 mpegvideodec qpeldsp vc1dsp" vc1image_decoder_select="vc1_decoder" vorbis_encoder_select="audio_frame_queue" diff --git a/libavcodec/Makefile b/libavcodec/Makefile index 87a8b900374..2efab60d7d3 100644 --- a/libavcodec/Makefile +++ b/libavcodec/Makefile @@ -753,6 +753,7 @@ OBJS-$(CONFIG_VC2_ENCODER) += vc2enc.o vc2enc_dwt.o diractab.o OBJS-$(CONFIG_VCR1_DECODER) += vcr1.o OBJS-$(CONFIG_VMDAUDIO_DECODER) += vmdaudio.o OBJS-$(CONFIG_VMDVIDEO_DECODER) += vmdvideo.o +OBJS-$(CONFIG_VMIX_DECODER) += vmixdec.o OBJS-$(CONFIG_VMNC_DECODER) += vmnc.o OBJS-$(CONFIG_VNULL_DECODER) += null.o OBJS-$(CONFIG_VNULL_ENCODER) += null.o diff --git a/libavcodec/allcodecs.c b/libavcodec/allcodecs.c index a98c300da48..11c136ef595 100644 --- a/libavcodec/allcodecs.c +++ b/libavcodec/allcodecs.c @@ -370,6 +370,7 @@ extern const FFCodec ff_vc1_v4l2m2m_decoder; extern const FFCodec ff_vc2_encoder; extern const FFCodec ff_vcr1_decoder; extern const FFCodec ff_vmdvideo_decoder; +extern const FFCodec ff_vmix_decoder; extern const FFCodec ff_vmnc_decoder; extern const FFCodec ff_vp3_decoder; extern const FFCodec ff_vp4_decoder; diff --git a/libavcodec/codec_desc.c b/libavcodec/codec_desc.c index 41293a78dce..3e31a1eed61 100644 --- a/libavcodec/codec_desc.c +++ b/libavcodec/codec_desc.c @@ -1953,6 +1953,13 @@ static const AVCodecDescriptor codec_descriptors[] = { .long_name = NULL_IF_CONFIG_SMALL("RTV1 (RivaTuner Video)"), .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSY, }, + { + .id = AV_CODEC_ID_VMIX, + .type = AVMEDIA_TYPE_VIDEO, + .name = "vmix", + .long_name = NULL_IF_CONFIG_SMALL("vMix Video"), + .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSY, + }, /* various PCM "codecs" */ { diff --git a/libavcodec/codec_id.h b/libavcodec/codec_id.h index 9a78cfabe2f..d23549d7e0c 100644 --- a/libavcodec/codec_id.h +++ b/libavcodec/codec_id.h @@ -323,6 +323,7 @@ enum AVCodecID { AV_CODEC_ID_PDV, AV_CODEC_ID_EVC, AV_CODEC_ID_RTV1, + AV_CODEC_ID_VMIX, /* various PCM "codecs" */ AV_CODEC_ID_FIRST_AUDIO = 0x10000, ///< A dummy id pointing at the start of audio codecs diff --git a/libavcodec/version.h b/libavcodec/version.h index 2618016a835..65bc52fb24b 100644 --- a/libavcodec/version.h +++ b/libavcodec/version.h @@ -29,7 +29,7 @@ #include "version_major.h" -#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/libavcodec/vmixdec.c b/libavcodec/vmixdec.c new file mode 100644 index 00000000000..d0f2219a679 --- /dev/null +++ b/libavcodec/vmixdec.c @@ -0,0 +1,288 @@ +/* + * vMix decoder + * Copyright (c) 2023 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 + +#include "libavutil/avassert.h" +#include "libavutil/intreadwrite.h" +#include "libavutil/mem_internal.h" + +#include "avcodec.h" +#include "codec_internal.h" +#include "decode.h" +#define CACHED_BITSTREAM_READER !ARCH_X86_32 +#include "golomb.h" +#include "get_bits.h" +#include "idctdsp.h" +#include "thread.h" + +typedef struct SliceContext { + const uint8_t *dc_ptr; + const uint8_t *ac_ptr; + unsigned dc_size; + unsigned ac_size; +} SliceContext; + +typedef struct VMIXContext { + int nb_slices; + + int16_t factors[64]; + uint8_t scan[64]; + + SliceContext slices[255]; + + IDCTDSPContext idsp; +} VMIXContext; + +static const uint8_t quality[25] = { + 1, 2, 3, 4, 5, 6, 7, 8, 10, 12, 14, 16, + 18, 20, 22, 24, 28, 32, 36, 40, 44, 48, 52, 56, 64, +}; + +static const uint8_t quant[64] = { + 16, 16, 19, 22, 22, 26, 26, 27, + 16, 16, 22, 22, 26, 27, 27, 29, + 19, 22, 26, 26, 27, 29, 29, 35, + 22, 24, 27, 27, 29, 32, 34, 38, + 26, 27, 29, 29, 32, 35, 38, 46, + 27, 29, 34, 34, 35, 40, 46, 56, + 29, 34, 34, 37, 40, 48, 56, 69, + 34, 37, 38, 40, 48, 58, 69, 83, +}; + +static av_cold int decode_init(AVCodecContext *avctx) +{ + VMIXContext *s = avctx->priv_data; + + avctx->bits_per_raw_sample = 8; + avctx->pix_fmt = AV_PIX_FMT_YUV422P; + + avctx->coded_width = FFALIGN(avctx->width, 16); + avctx->coded_height = FFALIGN(avctx->height, 16); + + ff_idctdsp_init(&s->idsp, avctx); + ff_permute_scantable(s->scan, ff_zigzag_direct, + s->idsp.idct_permutation); + return 0; +} + +static inline int get_se_golomb_vmix(GetBitContext *gb) +{ + unsigned int buf = get_ue_golomb_long(gb); + int sign = (buf & 1) - 1; + return ((buf >> 1) ^ (~sign)); +} + +static int decode_dcac(AVCodecContext *avctx, + GetBitContext *dc_gb, GetBitContext *ac_gb, + unsigned *dcrun, unsigned *acrun, + AVFrame *frame, int width, int by, int plane) +{ + const ptrdiff_t linesize = frame->linesize[plane]; + uint8_t *dst = frame->data[plane] + by * linesize; + unsigned dc_run = *dcrun, ac_run = *acrun; + LOCAL_ALIGNED_32(int16_t, block, [64]); + VMIXContext *s = avctx->priv_data; + const int16_t *factors = s->factors; + const uint8_t *scan = s->scan; + const int add = plane ? 0 : 1024; + int i, dc_v = 0, ac_v = 0, dc = 0; + + for (int y = 0; y < 2; y++) { + for (int x = 0; x < width; x += 8) { + memset(block, 0, sizeof(*block)*64); + + if (dc_run > 0) { + dc_run--; + } else { + dc_v = get_se_golomb_vmix(dc_gb); + dc += dc_v; + if (!dc_v) + dc_run = get_ue_golomb_long(dc_gb); + } + + for (int n = 0; n < 64; n++) { + if (ac_run > 0) { + ac_run--; + continue; + } + + ac_v = get_se_golomb_vmix(ac_gb); + i = scan[n]; + block[i] = (ac_v * factors[i]) >> 4; + if (!ac_v) + ac_run = get_ue_golomb_long(ac_gb); + } + + block[0] = ((dc + add) * 16) >> 4; + s->idsp.idct_put(dst + x, linesize, block); + } + + dst += 8 * linesize; + } + + *dcrun = dc_run; + *acrun = ac_run; + + return 0; +} + +static int decode_slice(AVCodecContext *avctx, AVFrame *frame, + const uint8_t *dc_src, unsigned dc_slice_size, + const uint8_t *ac_src, unsigned ac_slice_size, + int by) +{ + unsigned dc_run = 0, ac_run = 0; + GetBitContext dc_gb, ac_gb; + int ret; + + ret = init_get_bits8(&dc_gb, dc_src, dc_slice_size); + if (ret < 0) + return ret; + + ret = init_get_bits8(&ac_gb, ac_src, ac_slice_size); + if (ret < 0) + return ret; + + for (int p = 0; p < 3; p++) { + const int rshift = !!p; + ret = decode_dcac(avctx, &dc_gb, &ac_gb, + &dc_run, &ac_run, frame, + frame->width >> rshift, by, p); + if (ret < 0) + return ret; + + if (get_bits_left(&dc_gb) < 0) + return AVERROR_INVALIDDATA; + if (get_bits_left(&ac_gb) < 0) + return AVERROR_INVALIDDATA; + + align_get_bits(&dc_gb); + align_get_bits(&ac_gb); + } + + if (get_bits_left(&dc_gb) > 0) + return AVERROR_INVALIDDATA; + if (get_bits_left(&ac_gb) > 0) + return AVERROR_INVALIDDATA; + + return 0; +} + +static int decode_slices(AVCodecContext *avctx, void *arg, + int n, int thread_nb) +{ + VMIXContext *s = avctx->priv_data; + const uint8_t *dc_slice_ptr = s->slices[n].dc_ptr; + const uint8_t *ac_slice_ptr = s->slices[n].ac_ptr; + unsigned dc_slice_size = s->slices[n].dc_size; + unsigned ac_slice_size = s->slices[n].ac_size; + AVFrame *frame = arg; + + return decode_slice(avctx, frame, dc_slice_ptr, dc_slice_size, + ac_slice_ptr, ac_slice_size, n * 16); +} + +static int decode_frame(AVCodecContext *avctx, + AVFrame *frame, int *got_frame, + AVPacket *avpkt) +{ + VMIXContext *s = avctx->priv_data; + unsigned offset = 3, q; + int ret; + + if (avpkt->size <= 7) + return AVERROR_INVALIDDATA; + + if (avpkt->data[0] != 0x01) + return AVERROR_INVALIDDATA; + + q = av_clip(99 - av_clip(avpkt->data[1], 0, 99), 0, FF_ARRAY_ELEMS(quality) - 1); + for (int n = 0; n < 64; n++) + s->factors[n] = quant[n] * quality[q]; + + s->nb_slices = avpkt->data[2]; + if (!s->nb_slices || s->nb_slices > (avctx->height + 15) / 16) + return AVERROR_INVALIDDATA; + + for (int n = 0; n < s->nb_slices; n++) { + unsigned slice_size; + + if (offset + 4 > avpkt->size) + return AVERROR_INVALIDDATA; + + slice_size = AV_RL32(avpkt->data + offset); + if (slice_size > avpkt->size) + return AVERROR_INVALIDDATA; + + if (avpkt->size - slice_size - 4LL < offset) + return AVERROR_INVALIDDATA; + + s->slices[n].dc_size = slice_size; + s->slices[n].dc_ptr = avpkt->data + offset + 4; + offset += slice_size + 4; + } + + for (int n = 0; n < s->nb_slices; n++) { + unsigned slice_size; + + if (offset + 4 > avpkt->size) + return AVERROR_INVALIDDATA; + + slice_size = AV_RL32(avpkt->data + offset); + if (slice_size > avpkt->size) + return AVERROR_INVALIDDATA; + + if (avpkt->size - slice_size - 4LL < offset) + return AVERROR_INVALIDDATA; + + s->slices[n].ac_size = slice_size; + s->slices[n].ac_ptr = avpkt->data + offset + 4; + offset += slice_size + 4; + } + + ret = ff_thread_get_buffer(avctx, frame, 0); + if (ret < 0) + return ret; + + avctx->execute2(avctx, decode_slices, frame, NULL, s->nb_slices); + + frame->pict_type = AV_PICTURE_TYPE_I; + frame->flags |= AV_FRAME_FLAG_KEY; + + *got_frame = 1; + + return avpkt->size; +} + +const FFCodec ff_vmix_decoder = { + .p.name = "vmix", + CODEC_LONG_NAME("vMix Video"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_VMIX, + .priv_data_size = sizeof(VMIXContext), + .init = decode_init, + FF_CODEC_DECODE_CB(decode_frame), + .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_FRAME_THREADS | + AV_CODEC_CAP_SLICE_THREADS, +}; diff --git a/libavformat/riff.c b/libavformat/riff.c index 42790711599..97708df6e37 100644 --- a/libavformat/riff.c +++ b/libavformat/riff.c @@ -502,6 +502,7 @@ const AVCodecTag ff_codec_bmp_tags[] = { { AV_CODEC_ID_VQC, MKTAG('V', 'Q', 'C', '1') }, { AV_CODEC_ID_VQC, MKTAG('V', 'Q', 'C', '2') }, { AV_CODEC_ID_RTV1, MKTAG('R', 'T', 'V', '1') }, + { AV_CODEC_ID_VMIX, MKTAG('V', 'M', 'X', '1') }, { AV_CODEC_ID_NONE, 0 } }; From d26ea03f60ac78476766bfcc115c0ec050c68198 Mon Sep 17 00:00:00 2001 From: Niklas Haas Date: Tue, 13 Jun 2023 15:26:52 +0200 Subject: [PATCH 1466/2172] lavfi/vf_libplacebo: fix typo in assert Not caught because av_assert1 was compiled out on my end. --- libavfilter/vf_libplacebo.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavfilter/vf_libplacebo.c b/libavfilter/vf_libplacebo.c index b546f02dc61..242c8a13f5a 100644 --- a/libavfilter/vf_libplacebo.c +++ b/libavfilter/vf_libplacebo.c @@ -898,7 +898,7 @@ static int libplacebo_activate(AVFilterContext *ctx) if (!s->fps.num) { /* Internally queue an output frame for the same PTS */ - av_assert1(!av_cmp_q(link->time_base, outlink->time_base)); + av_assert1(!av_cmp_q(inlink->time_base, outlink->time_base)); av_fifo_write(s->out_pts, &in->pts, 1); } } From cfcd6e2108a7c43394840ca857ba1b6e8f6351c2 Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Wed, 14 Jun 2023 11:59:58 +0200 Subject: [PATCH 1467/2172] avcodec/proresdec2: remove duplicated function --- libavcodec/proresdec2.c | 15 ++++----------- 1 file changed, 4 insertions(+), 11 deletions(-) diff --git a/libavcodec/proresdec2.c b/libavcodec/proresdec2.c index 6445d948d99..b86614adc08 100644 --- a/libavcodec/proresdec2.c +++ b/libavcodec/proresdec2.c @@ -44,13 +44,6 @@ #include "proresdata.h" #include "thread.h" -static void permute(uint8_t *dst, const uint8_t *src, const uint8_t permutation[64]) -{ - int i; - for (i = 0; i < 64; i++) - dst[i] = permutation[src[i]]; -} - #define ALPHA_SHIFT_16_TO_10(alpha_val) (alpha_val >> 6) #define ALPHA_SHIFT_8_TO_10(alpha_val) ((alpha_val << 2) | (alpha_val >> 6)) #define ALPHA_SHIFT_16_TO_12(alpha_val) (alpha_val >> 4) @@ -187,8 +180,8 @@ static av_cold int decode_init(AVCodecContext *avctx) ff_init_scantable_permutation(idct_permutation, ctx->prodsp.idct_permutation_type); - permute(ctx->progressive_scan, ff_prores_progressive_scan, idct_permutation); - permute(ctx->interlaced_scan, ff_prores_interlaced_scan, idct_permutation); + ff_permute_scantable(ctx->progressive_scan, ff_prores_progressive_scan, idct_permutation); + ff_permute_scantable(ctx->interlaced_scan, ff_prores_interlaced_scan, idct_permutation); ctx->pix_fmt = AV_PIX_FMT_NONE; @@ -304,7 +297,7 @@ static int decode_frame_header(ProresContext *ctx, const uint8_t *buf, av_log(avctx, AV_LOG_ERROR, "Header truncated\n"); return AVERROR_INVALIDDATA; } - permute(ctx->qmat_luma, ctx->prodsp.idct_permutation, ptr); + ff_permute_scantable(ctx->qmat_luma, ctx->prodsp.idct_permutation, ptr); ptr += 64; } else { memset(ctx->qmat_luma, 4, 64); @@ -315,7 +308,7 @@ static int decode_frame_header(ProresContext *ctx, const uint8_t *buf, av_log(avctx, AV_LOG_ERROR, "Header truncated\n"); return AVERROR_INVALIDDATA; } - permute(ctx->qmat_chroma, ctx->prodsp.idct_permutation, ptr); + ff_permute_scantable(ctx->qmat_chroma, ctx->prodsp.idct_permutation, ptr); } else { memcpy(ctx->qmat_chroma, ctx->qmat_luma, 64); } From ac7c265b33b52f914ebe05e581bbe9343eca1186 Mon Sep 17 00:00:00 2001 From: Timo Rothenpieler Date: Thu, 15 Jun 2023 00:45:44 +0200 Subject: [PATCH 1468/2172] Revert "avcodec/nvenc: fix b-frame DTS behavior with fractional framerates" This reverts commit 9a245bdf5d7860b8bc5e5c21a105a075925b719a. This commit basically broke all samples with fractional framerates, rather than fixing them. I at this point do not understand the original issue anymore, and I'm not sure how this slipped my initial testing. All my test samples must have happened to have a simple timebase. The actual dts values pretty much always are just a simple chain of 1,2,3,4,5,... Or maybe slightly bigger steps. Each increase by one means an advance in time by one unit of the timebase. So a fractional framerate/timebase is already not an issue. So with this patch applied, the calculation might end up substracting huge values (1001 is a common one) from the dts, which would be an offset of that many frames, not of that many fractions of a second. This broke at least muxing into mp4, if the sample happened to have a fractional framerate. I do not thing the original issue this patch tried to fix existed in the first place, so it can be reverted without further consequences. --- libavcodec/nvenc.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/libavcodec/nvenc.c b/libavcodec/nvenc.c index 50371d63366..7874cb887b7 100644 --- a/libavcodec/nvenc.c +++ b/libavcodec/nvenc.c @@ -2285,11 +2285,10 @@ static int nvenc_set_timestamp(AVCodecContext *avctx, if (avctx->codec_descriptor->props & AV_CODEC_PROP_REORDER) { FF_DISABLE_DEPRECATION_WARNINGS pkt->dts = dts - - FFMAX(ctx->encode_config.frameIntervalP - 1, 0) #if FF_API_TICKS_PER_FRAME - * FFMAX(avctx->ticks_per_frame, 1) + FFMAX(avctx->ticks_per_frame, 1) * #endif - * FFMAX(avctx->time_base.num, 1); + FFMAX(ctx->encode_config.frameIntervalP - 1, 0); FF_ENABLE_DEPRECATION_WARNINGS } else { pkt->dts = pkt->pts; From 41229ef7058702600cc6a6d09e933251d41e8f3b Mon Sep 17 00:00:00 2001 From: Gyan Doshi Date: Thu, 15 Jun 2023 15:07:05 +0530 Subject: [PATCH 1469/2172] doc/muxers: harmonize option presentation in hls No surrounding option has the '-' prefix. --- doc/muxers.texi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/muxers.texi b/doc/muxers.texi index 31fca17dd62..91d30c5b3be 100644 --- a/doc/muxers.texi +++ b/doc/muxers.texi @@ -1325,7 +1325,7 @@ Use persistent HTTP connections. Applicable only for HTTP output. @item timeout Set timeout for socket I/O operations. Applicable only for HTTP output. -@item -ignore_io_errors +@item ignore_io_errors Ignore IO errors during open, write and delete. Useful for long-duration runs with network output. @item headers From 34e4f18360c4ecb8e5979cab8f389478d8cd7819 Mon Sep 17 00:00:00 2001 From: Dawid Kozinski Date: Thu, 15 Jun 2023 13:46:43 +0200 Subject: [PATCH 1470/2172] avcodec/evc_parser: Added parser implementation for EVC format - Added constants definitions for EVC parser - Provided NAL units parsing following ISO_IEC_23094-1 - EVC parser registration Signed-off-by: Dawid Kozinski --- configure | 2 + libavcodec/Makefile | 2 + libavcodec/evc.h | 155 ++++++++ libavcodec/evc_parse.c | 767 ++++++++++++++++++++++++++++++++++++++++ libavcodec/evc_parse.h | 357 +++++++++++++++++++ libavcodec/evc_parser.c | 235 ++++++++++++ libavcodec/parsers.c | 1 + 7 files changed, 1519 insertions(+) create mode 100644 libavcodec/evc.h create mode 100644 libavcodec/evc_parse.c create mode 100644 libavcodec/evc_parse.h create mode 100644 libavcodec/evc_parser.c diff --git a/configure b/configure index 4ac7cc6c0bf..c9a86e9f8e1 100755 --- a/configure +++ b/configure @@ -2483,6 +2483,7 @@ CONFIG_EXTRA=" dnn dovi_rpu dvprofile + evcparse exif faandct faanidct @@ -3321,6 +3322,7 @@ av1_amf_encoder_deps="amf" # parsers aac_parser_select="adts_header mpeg4audio" av1_parser_select="cbs_av1" +evc_parser_select="golomb evcparse" h264_parser_select="golomb h264dsp h264parse h264_sei" hevc_parser_select="hevcparse hevc_sei" mpegaudio_parser_select="mpegaudioheader" diff --git a/libavcodec/Makefile b/libavcodec/Makefile index 2efab60d7d3..a28919992ad 100644 --- a/libavcodec/Makefile +++ b/libavcodec/Makefile @@ -84,6 +84,7 @@ OBJS-$(CONFIG_DCT) += dct.o dct32_fixed.o dct32_float.o OBJS-$(CONFIG_DEFLATE_WRAPPER) += zlib_wrapper.o OBJS-$(CONFIG_DOVI_RPU) += dovi_rpu.o OBJS-$(CONFIG_ERROR_RESILIENCE) += error_resilience.o +OBJS-$(CONFIG_EVCPARSE) += evc_parse.o OBJS-$(CONFIG_EXIF) += exif.o tiff_common.o OBJS-$(CONFIG_FAANDCT) += faandct.o OBJS-$(CONFIG_FAANIDCT) += faanidct.o @@ -1168,6 +1169,7 @@ OBJS-$(CONFIG_DVAUDIO_PARSER) += dvaudio_parser.o OBJS-$(CONFIG_DVBSUB_PARSER) += dvbsub_parser.o OBJS-$(CONFIG_DVD_NAV_PARSER) += dvd_nav_parser.o OBJS-$(CONFIG_DVDSUB_PARSER) += dvdsub_parser.o +OBJS-$(CONFIG_EVC_PARSER) += evc_parser.o OBJS-$(CONFIG_FLAC_PARSER) += flac_parser.o flacdata.o flac.o OBJS-$(CONFIG_FTR_PARSER) += ftr_parser.o OBJS-$(CONFIG_G723_1_PARSER) += g723_1_parser.o diff --git a/libavcodec/evc.h b/libavcodec/evc.h new file mode 100644 index 00000000000..d1fdb4fac60 --- /dev/null +++ b/libavcodec/evc.h @@ -0,0 +1,155 @@ +/* + * EVC definitions and enums + * Copyright (c) 2022 Dawid Kozinski + * + * 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_EVC_H +#define AVCODEC_EVC_H + +// The length field that indicates the length in bytes of the following NAL unit is configured to be of 4 bytes +#define EVC_NALU_LENGTH_PREFIX_SIZE (4) /* byte */ +#define EVC_NALU_HEADER_SIZE (2) /* byte */ + +/** + * @see ISO_IEC_23094-1_2020, 7.4.2.2 NAL unit header semantic + * Table 4 - NAL unit type codes and NAL unit type classes + */ +enum EVCNALUnitType { + EVC_NOIDR_NUT = 0, /* Coded slice of a non-IDR picture */ + EVC_IDR_NUT = 1, /* Coded slice of an IDR picture */ + EVC_RSV_VCL_NUT02 = 2, + EVC_RSV_VCL_NUT03 = 3, + EVC_RSV_VCL_NUT04 = 4, + EVC_RSV_VCL_NUT05 = 5, + EVC_RSV_VCL_NUT06 = 6, + EVC_RSV_VCL_NUT07 = 7, + EVC_RSV_VCL_NUT08 = 8, + EVC_RSV_VCL_NUT09 = 9, + EVC_RSV_VCL_NUT10 = 10, + EVC_RSV_VCL_NUT11 = 11, + EVC_RSV_VCL_NUT12 = 12, + EVC_RSV_VCL_NUT13 = 13, + EVC_RSV_VCL_NUT14 = 14, + EVC_RSV_VCL_NUT15 = 15, + EVC_RSV_VCL_NUT16 = 16, + EVC_RSV_VCL_NUT17 = 17, + EVC_RSV_VCL_NUT18 = 18, + EVC_RSV_VCL_NUT19 = 19, + EVC_RSV_VCL_NUT20 = 20, + EVC_RSV_VCL_NUT21 = 21, + EVC_RSV_VCL_NUT22 = 22, + EVC_RSV_VCL_NUT23 = 23, + EVC_SPS_NUT = 24, /* Sequence parameter set */ + EVC_PPS_NUT = 25, /* Picture paremeter set */ + EVC_APS_NUT = 26, /* Adaptation parameter set */ + EVC_FD_NUT = 27, /* Filler data */ + EVC_SEI_NUT = 28, /* Supplemental enhancement information */ + EVC_RSV_NONVCL29 = 29, + EVC_RSV_NONVCL30 = 30, + EVC_RSV_NONVCL31 = 31, + EVC_RSV_NONVCL32 = 32, + EVC_RSV_NONVCL33 = 33, + EVC_RSV_NONVCL34 = 34, + EVC_RSV_NONVCL35 = 35, + EVC_RSV_NONVCL36 = 36, + EVC_RSV_NONVCL37 = 37, + EVC_RSV_NONVCL38 = 38, + EVC_RSV_NONVCL39 = 39, + EVC_RSV_NONVCL40 = 40, + EVC_RSV_NONVCL41 = 41, + EVC_RSV_NONVCL42 = 42, + EVC_RSV_NONVCL43 = 43, + EVC_RSV_NONVCL44 = 44, + EVC_RSV_NONVCL45 = 45, + EVC_RSV_NONVCL46 = 46, + EVC_RSV_NONVCL47 = 47, + EVC_RSV_NONVCL48 = 48, + EVC_RSV_NONVCL49 = 49, + EVC_RSV_NONVCL50 = 50, + EVC_RSV_NONVCL51 = 51, + EVC_RSV_NONVCL52 = 52, + EVC_RSV_NONVCL53 = 53, + EVC_RSV_NONVCL54 = 54, + EVC_RSV_NONVCL55 = 55, + EVC_UNSPEC_NUT56 = 56, + EVC_UNSPEC_NUT57 = 57, + EVC_UNSPEC_NUT58 = 58, + EVC_UNSPEC_NUT59 = 59, + EVC_UNSPEC_NUT60 = 60, + EVC_UNSPEC_NUT61 = 61, + EVC_UNSPEC_NUT62 = 62 +}; + +// slice type +// @see ISO_IEC_23094-1_2020 7.4.5 Slice header semantics +// +enum EVCSliceType { + EVC_SLICE_TYPE_B = 0, + EVC_SLICE_TYPE_P = 1, + EVC_SLICE_TYPE_I = 2 +}; + +enum { + // 7.4.3.2: aps_video_parameter_set_id is u(4). + EVC_MAX_APS_COUNT = 32, + + // 7.4.3.1: sps_seq_parameter_set_id is in [0, 15]. + EVC_MAX_SPS_COUNT = 16, + + // 7.4.3.2: pps_pic_parameter_set_id is in [0, 63]. + EVC_MAX_PPS_COUNT = 64, + + // 7.4.5: slice header slice_pic_parameter_set_id in [0, 63] + EVC_MAX_SH_COUNT = 64, + + // E.3.2: cpb_cnt_minus1[i] is in [0, 31]. + EVC_MAX_CPB_CNT = 32, + + // A.4.1: in table A.1 the highest level allows a MaxLumaPs of 35 651 584. + EVC_MAX_LUMA_PS = 35651584, + + EVC_MAX_NUM_REF_PICS = 21, + + EVC_MAX_NUM_RPLS = 32, + + // A.4.1: pic_width_in_luma_samples and pic_height_in_luma_samples are + // constrained to be not greater than sqrt(MaxLumaPs * 8). Hence height/ + // width are bounded above by sqrt(8 * 35651584) = 16888.2 samples. + EVC_MAX_WIDTH = 16888, + EVC_MAX_HEIGHT = 16888, + + // A.4.1: table A.1 allows at most 22 tile rows for any level. + EVC_MAX_TILE_ROWS = 22, + // A.4.1: table A.1 allows at most 20 tile columns for any level. + EVC_MAX_TILE_COLUMNS = 20, + + // A.4.1: table A.1 allows at most 600 slice segments for any level. + EVC_MAX_SLICE_SEGMENTS = 600, + + // 7.4.7.1: in the worst case (tiles_enabled_flag and + // entropy_coding_sync_enabled_flag are both set), entry points can be + // placed at the beginning of every Ctb row in every tile, giving an + // upper bound of (num_tile_columns_minus1 + 1) * PicHeightInCtbsY - 1. + // Only a stream with very high resolution and perverse parameters could + // get near that, though, so set a lower limit here with the maximum + // possible value for 4K video (at most 135 16x16 Ctb rows). + HEVC_MAX_ENTRY_POINT_OFFSETS = EVC_MAX_TILE_COLUMNS * 135, +}; + +#endif // AVCODEC_EVC_H diff --git a/libavcodec/evc_parse.c b/libavcodec/evc_parse.c new file mode 100644 index 00000000000..f69d7ffb6b4 --- /dev/null +++ b/libavcodec/evc_parse.c @@ -0,0 +1,767 @@ +/* + * 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 "golomb.h" +#include "parser.h" +#include "evc.h" +#include "evc_parse.h" + +#define EXTENDED_SAR 255 + +#define NUM_CHROMA_FORMATS 4 // @see ISO_IEC_23094-1 section 6.2 table 2 + +static const enum AVPixelFormat pix_fmts_8bit[NUM_CHROMA_FORMATS] = { + AV_PIX_FMT_GRAY8, AV_PIX_FMT_YUV420P, AV_PIX_FMT_YUV422P, AV_PIX_FMT_YUV444P +}; + +static const enum AVPixelFormat pix_fmts_9bit[NUM_CHROMA_FORMATS] = { + AV_PIX_FMT_GRAY9, AV_PIX_FMT_YUV420P9, AV_PIX_FMT_YUV422P9, AV_PIX_FMT_YUV444P9 +}; + +static const enum AVPixelFormat pix_fmts_10bit[NUM_CHROMA_FORMATS] = { + AV_PIX_FMT_GRAY10, AV_PIX_FMT_YUV420P10, AV_PIX_FMT_YUV422P10, AV_PIX_FMT_YUV444P10 +}; + +static const enum AVPixelFormat pix_fmts_12bit[NUM_CHROMA_FORMATS] = { + AV_PIX_FMT_GRAY12, AV_PIX_FMT_YUV420P12, AV_PIX_FMT_YUV422P12, AV_PIX_FMT_YUV444P12 +}; + +static const enum AVPixelFormat pix_fmts_14bit[NUM_CHROMA_FORMATS] = { + AV_PIX_FMT_GRAY14, AV_PIX_FMT_YUV420P14, AV_PIX_FMT_YUV422P14, AV_PIX_FMT_YUV444P14 +}; + +static const enum AVPixelFormat pix_fmts_16bit[NUM_CHROMA_FORMATS] = { + AV_PIX_FMT_GRAY16, AV_PIX_FMT_YUV420P16, AV_PIX_FMT_YUV422P16, AV_PIX_FMT_YUV444P16 +}; + +// nuh_temporal_id specifies a temporal identifier for the NAL unit +int ff_evc_get_temporal_id(const uint8_t *bits, int bits_size, void *logctx) +{ + int temporal_id = 0; + uint16_t t = 0; + + if (bits_size < EVC_NALU_HEADER_SIZE) { + av_log(logctx, AV_LOG_ERROR, "Can't read NAL unit header\n"); + return 0; + } + + // forbidden_zero_bit + if ((bits[0] & 0x80) != 0) + return -1; + + t = AV_RB16(bits); + + temporal_id = (t >> 6) & 0x0007; + + return temporal_id; +} + +// @see ISO_IEC_23094-1 (7.3.7 Reference picture list structure syntax) +static int ref_pic_list_struct(GetBitContext *gb, RefPicListStruct *rpl) +{ + uint32_t delta_poc_st, strp_entry_sign_flag = 0; + rpl->ref_pic_num = get_ue_golomb(gb); + if (rpl->ref_pic_num > 0) { + delta_poc_st = get_ue_golomb(gb); + + rpl->ref_pics[0] = delta_poc_st; + if (rpl->ref_pics[0] != 0) { + strp_entry_sign_flag = get_bits(gb, 1); + + rpl->ref_pics[0] *= 1 - (strp_entry_sign_flag << 1); + } + } + + for (int i = 1; i < rpl->ref_pic_num; ++i) { + delta_poc_st = get_ue_golomb(gb); + if (delta_poc_st != 0) + strp_entry_sign_flag = get_bits(gb, 1); + rpl->ref_pics[i] = rpl->ref_pics[i - 1] + delta_poc_st * (1 - (strp_entry_sign_flag << 1)); + } + + return 0; +} + +// @see ISO_IEC_23094-1 (E.2.2 HRD parameters syntax) +static int hrd_parameters(GetBitContext *gb, HRDParameters *hrd) +{ + hrd->cpb_cnt_minus1 = get_ue_golomb(gb); + hrd->bit_rate_scale = get_bits(gb, 4); + hrd->cpb_size_scale = get_bits(gb, 4); + for (int SchedSelIdx = 0; SchedSelIdx <= hrd->cpb_cnt_minus1; SchedSelIdx++) { + hrd->bit_rate_value_minus1[SchedSelIdx] = get_ue_golomb(gb); + hrd->cpb_size_value_minus1[SchedSelIdx] = get_ue_golomb(gb); + hrd->cbr_flag[SchedSelIdx] = get_bits(gb, 1); + } + hrd->initial_cpb_removal_delay_length_minus1 = get_bits(gb, 5); + hrd->cpb_removal_delay_length_minus1 = get_bits(gb, 5); + hrd->cpb_removal_delay_length_minus1 = get_bits(gb, 5); + hrd->time_offset_length = get_bits(gb, 5); + + return 0; +} + +// @see ISO_IEC_23094-1 (E.2.1 VUI parameters syntax) +static int vui_parameters(GetBitContext *gb, VUIParameters *vui) +{ + vui->aspect_ratio_info_present_flag = get_bits(gb, 1); + if (vui->aspect_ratio_info_present_flag) { + vui->aspect_ratio_idc = get_bits(gb, 8); + if (vui->aspect_ratio_idc == EXTENDED_SAR) { + vui->sar_width = get_bits(gb, 16); + vui->sar_height = get_bits(gb, 16); + } + } + vui->overscan_info_present_flag = get_bits(gb, 1); + if (vui->overscan_info_present_flag) + vui->overscan_appropriate_flag = get_bits(gb, 1); + vui->video_signal_type_present_flag = get_bits(gb, 1); + if (vui->video_signal_type_present_flag) { + vui->video_format = get_bits(gb, 3); + vui->video_full_range_flag = get_bits(gb, 1); + vui->colour_description_present_flag = get_bits(gb, 1); + if (vui->colour_description_present_flag) { + vui->colour_primaries = get_bits(gb, 8); + vui->transfer_characteristics = get_bits(gb, 8); + vui->matrix_coefficients = get_bits(gb, 8); + } + } + vui->chroma_loc_info_present_flag = get_bits(gb, 1); + if (vui->chroma_loc_info_present_flag) { + vui->chroma_sample_loc_type_top_field = get_ue_golomb(gb); + vui->chroma_sample_loc_type_bottom_field = get_ue_golomb(gb); + } + vui->neutral_chroma_indication_flag = get_bits(gb, 1); + + vui->field_seq_flag = get_bits(gb, 1); + + vui->timing_info_present_flag = get_bits(gb, 1); + if (vui->timing_info_present_flag) { + vui->num_units_in_tick = get_bits(gb, 32); + vui->time_scale = get_bits(gb, 32); + vui->fixed_pic_rate_flag = get_bits(gb, 1); + } + vui->nal_hrd_parameters_present_flag = get_bits(gb, 1); + if (vui->nal_hrd_parameters_present_flag) + hrd_parameters(gb, &vui->hrd_parameters); + vui->vcl_hrd_parameters_present_flag = get_bits(gb, 1); + if (vui->vcl_hrd_parameters_present_flag) + hrd_parameters(gb, &vui->hrd_parameters); + if (vui->nal_hrd_parameters_present_flag || vui->vcl_hrd_parameters_present_flag) + vui->low_delay_hrd_flag = get_bits(gb, 1); + vui->pic_struct_present_flag = get_bits(gb, 1); + vui->bitstream_restriction_flag = get_bits(gb, 1); + if (vui->bitstream_restriction_flag) { + vui->motion_vectors_over_pic_boundaries_flag = get_bits(gb, 1); + vui->max_bytes_per_pic_denom = get_ue_golomb(gb); + vui->max_bits_per_mb_denom = get_ue_golomb(gb); + vui->log2_max_mv_length_horizontal = get_ue_golomb(gb); + vui->log2_max_mv_length_vertical = get_ue_golomb(gb); + vui->num_reorder_pics = get_ue_golomb(gb); + vui->max_dec_pic_buffering = get_ue_golomb(gb); + } + + return 0; +} + +// @see ISO_IEC_23094-1 (7.3.2.1 SPS RBSP syntax) +EVCParserSPS *ff_evc_parse_sps(EVCParserContext *ctx, const uint8_t *bs, int bs_size) +{ + GetBitContext gb; + EVCParserSPS *sps; + int sps_seq_parameter_set_id; + + if (init_get_bits8(&gb, bs, bs_size) < 0) + return NULL; + + sps_seq_parameter_set_id = get_ue_golomb(&gb); + + if (sps_seq_parameter_set_id >= EVC_MAX_SPS_COUNT) + return NULL; + + if(!ctx->sps[sps_seq_parameter_set_id]) { + if((ctx->sps[sps_seq_parameter_set_id] = av_malloc(sizeof(EVCParserSPS))) == NULL) + return NULL; + } + + sps = ctx->sps[sps_seq_parameter_set_id]; + sps->sps_seq_parameter_set_id = sps_seq_parameter_set_id; + + // the Baseline profile is indicated by profile_idc eqal to 0 + // the Main profile is indicated by profile_idc eqal to 1 + sps->profile_idc = get_bits(&gb, 8); + + sps->level_idc = get_bits(&gb, 8); + + skip_bits_long(&gb, 32); /* skip toolset_idc_h */ + skip_bits_long(&gb, 32); /* skip toolset_idc_l */ + + // 0 - monochrome + // 1 - 4:2:0 + // 2 - 4:2:2 + // 3 - 4:4:4 + sps->chroma_format_idc = get_ue_golomb(&gb); + + sps->pic_width_in_luma_samples = get_ue_golomb(&gb); + sps->pic_height_in_luma_samples = get_ue_golomb(&gb); + + sps->bit_depth_luma_minus8 = get_ue_golomb(&gb); + sps->bit_depth_chroma_minus8 = get_ue_golomb(&gb); + + sps->sps_btt_flag = get_bits(&gb, 1); + if (sps->sps_btt_flag) { + sps->log2_ctu_size_minus5 = get_ue_golomb(&gb); + sps->log2_min_cb_size_minus2 = get_ue_golomb(&gb); + sps->log2_diff_ctu_max_14_cb_size = get_ue_golomb(&gb); + sps->log2_diff_ctu_max_tt_cb_size = get_ue_golomb(&gb); + sps->log2_diff_min_cb_min_tt_cb_size_minus2 = get_ue_golomb(&gb); + } + + sps->sps_suco_flag = get_bits(&gb, 1); + if (sps->sps_suco_flag) { + sps->log2_diff_ctu_size_max_suco_cb_size = get_ue_golomb(&gb); + sps->log2_diff_max_suco_min_suco_cb_size = get_ue_golomb(&gb); + } + + sps->sps_admvp_flag = get_bits(&gb, 1); + if (sps->sps_admvp_flag) { + sps->sps_affine_flag = get_bits(&gb, 1); + sps->sps_amvr_flag = get_bits(&gb, 1); + sps->sps_dmvr_flag = get_bits(&gb, 1); + sps->sps_mmvd_flag = get_bits(&gb, 1); + sps->sps_hmvp_flag = get_bits(&gb, 1); + } + + sps->sps_eipd_flag = get_bits(&gb, 1); + if (sps->sps_eipd_flag) { + sps->sps_ibc_flag = get_bits(&gb, 1); + if (sps->sps_ibc_flag) + sps->log2_max_ibc_cand_size_minus2 = get_ue_golomb(&gb); + } + + sps->sps_cm_init_flag = get_bits(&gb, 1); + if (sps->sps_cm_init_flag) + sps->sps_adcc_flag = get_bits(&gb, 1); + + sps->sps_iqt_flag = get_bits(&gb, 1); + if (sps->sps_iqt_flag) + sps->sps_ats_flag = get_bits(&gb, 1); + + sps->sps_addb_flag = get_bits(&gb, 1); + sps->sps_alf_flag = get_bits(&gb, 1); + sps->sps_htdf_flag = get_bits(&gb, 1); + sps->sps_rpl_flag = get_bits(&gb, 1); + sps->sps_pocs_flag = get_bits(&gb, 1); + sps->sps_dquant_flag = get_bits(&gb, 1); + sps->sps_dra_flag = get_bits(&gb, 1); + + if (sps->sps_pocs_flag) + sps->log2_max_pic_order_cnt_lsb_minus4 = get_ue_golomb(&gb); + + if (!sps->sps_pocs_flag || !sps->sps_rpl_flag) { + sps->log2_sub_gop_length = get_ue_golomb(&gb); + if (sps->log2_sub_gop_length == 0) + sps->log2_ref_pic_gap_length = get_ue_golomb(&gb); + } + + if (!sps->sps_rpl_flag) + sps->max_num_tid0_ref_pics = get_ue_golomb(&gb); + else { + sps->sps_max_dec_pic_buffering_minus1 = get_ue_golomb(&gb); + sps->long_term_ref_pic_flag = get_bits(&gb, 1); + sps->rpl1_same_as_rpl0_flag = get_bits(&gb, 1); + sps->num_ref_pic_list_in_sps[0] = get_ue_golomb(&gb); + + for (int i = 0; i < sps->num_ref_pic_list_in_sps[0]; ++i) + ref_pic_list_struct(&gb, &sps->rpls[0][i]); + + if (!sps->rpl1_same_as_rpl0_flag) { + sps->num_ref_pic_list_in_sps[1] = get_ue_golomb(&gb); + for (int i = 0; i < sps->num_ref_pic_list_in_sps[1]; ++i) + ref_pic_list_struct(&gb, &sps->rpls[1][i]); + } + } + + sps->picture_cropping_flag = get_bits(&gb, 1); + + if (sps->picture_cropping_flag) { + sps->picture_crop_left_offset = get_ue_golomb(&gb); + sps->picture_crop_right_offset = get_ue_golomb(&gb); + sps->picture_crop_top_offset = get_ue_golomb(&gb); + sps->picture_crop_bottom_offset = get_ue_golomb(&gb); + } + + if (sps->chroma_format_idc != 0) { + sps->chroma_qp_table_struct.chroma_qp_table_present_flag = get_bits(&gb, 1); + + if (sps->chroma_qp_table_struct.chroma_qp_table_present_flag) { + sps->chroma_qp_table_struct.same_qp_table_for_chroma = get_bits(&gb, 1); + sps->chroma_qp_table_struct.global_offset_flag = get_bits(&gb, 1); + for (int i = 0; i < (sps->chroma_qp_table_struct.same_qp_table_for_chroma ? 1 : 2); i++) { + sps->chroma_qp_table_struct.num_points_in_qp_table_minus1[i] = get_ue_golomb(&gb);; + for (int j = 0; j <= sps->chroma_qp_table_struct.num_points_in_qp_table_minus1[i]; j++) { + sps->chroma_qp_table_struct.delta_qp_in_val_minus1[i][j] = get_bits(&gb, 6); + sps->chroma_qp_table_struct.delta_qp_out_val[i][j] = get_se_golomb(&gb); + } + } + } + } + + sps->vui_parameters_present_flag = get_bits(&gb, 1); + if (sps->vui_parameters_present_flag) + vui_parameters(&gb, &(sps->vui_parameters)); + + // @note + // If necessary, add the missing fields to the EVCParserSPS structure + // and then extend parser implementation + + return sps; +} + +// @see ISO_IEC_23094-1 (7.3.2.2 SPS RBSP syntax) +// +// @note +// The current implementation of parse_sps function doesn't handle VUI parameters parsing. +// If it will be needed, parse_sps function could be extended to handle VUI parameters parsing +// to initialize fields of the AVCodecContex i.e. color_primaries, color_trc,color_range +// +EVCParserPPS *ff_evc_parse_pps(EVCParserContext *ctx, const uint8_t *bs, int bs_size) +{ + GetBitContext gb; + EVCParserPPS *pps; + + int pps_pic_parameter_set_id; + + if (init_get_bits8(&gb, bs, bs_size) < 0) + return NULL; + + pps_pic_parameter_set_id = get_ue_golomb(&gb); + if (pps_pic_parameter_set_id > EVC_MAX_PPS_COUNT) + return NULL; + + if(!ctx->pps[pps_pic_parameter_set_id]) { + if((ctx->pps[pps_pic_parameter_set_id] = av_malloc(sizeof(EVCParserSPS))) == NULL) + return NULL; + } + + pps = ctx->pps[pps_pic_parameter_set_id]; + + pps->pps_pic_parameter_set_id = pps_pic_parameter_set_id; + + pps->pps_seq_parameter_set_id = get_ue_golomb(&gb); + if (pps->pps_seq_parameter_set_id >= EVC_MAX_SPS_COUNT) + return NULL; + + pps->num_ref_idx_default_active_minus1[0] = get_ue_golomb(&gb); + pps->num_ref_idx_default_active_minus1[1] = get_ue_golomb(&gb); + pps->additional_lt_poc_lsb_len = get_ue_golomb(&gb); + pps->rpl1_idx_present_flag = get_bits(&gb, 1); + pps->single_tile_in_pic_flag = get_bits(&gb, 1); + + if (!pps->single_tile_in_pic_flag) { + pps->num_tile_columns_minus1 = get_ue_golomb(&gb); + pps->num_tile_rows_minus1 = get_ue_golomb(&gb); + pps->uniform_tile_spacing_flag = get_bits(&gb, 1); + + if (!pps->uniform_tile_spacing_flag) { + for (int i = 0; i < pps->num_tile_columns_minus1; i++) + pps->tile_column_width_minus1[i] = get_ue_golomb(&gb); + + for (int i = 0; i < pps->num_tile_rows_minus1; i++) + pps->tile_row_height_minus1[i] = get_ue_golomb(&gb); + } + pps->loop_filter_across_tiles_enabled_flag = get_bits(&gb, 1); + pps->tile_offset_len_minus1 = get_ue_golomb(&gb); + } + + pps->tile_id_len_minus1 = get_ue_golomb(&gb); + pps->explicit_tile_id_flag = get_bits(&gb, 1); + + if (pps->explicit_tile_id_flag) { + for (int i = 0; i <= pps->num_tile_rows_minus1; i++) { + for (int j = 0; j <= pps->num_tile_columns_minus1; j++) + pps->tile_id_val[i][j] = get_bits(&gb, pps->tile_id_len_minus1 + 1); + } + } + + pps->pic_dra_enabled_flag = 0; + pps->pic_dra_enabled_flag = get_bits(&gb, 1); + + if (pps->pic_dra_enabled_flag) + pps->pic_dra_aps_id = get_bits(&gb, 5); + + pps->arbitrary_slice_present_flag = get_bits(&gb, 1); + pps->constrained_intra_pred_flag = get_bits(&gb, 1); + pps->cu_qp_delta_enabled_flag = get_bits(&gb, 1); + + if (pps->cu_qp_delta_enabled_flag) + pps->log2_cu_qp_delta_area_minus6 = get_ue_golomb(&gb); + + return pps; +} + +// @see ISO_IEC_23094-1 (7.3.2.6 Slice layer RBSP syntax) +EVCParserSliceHeader *ff_evc_parse_slice_header(EVCParserContext *ctx, const uint8_t *bs, int bs_size) +{ + GetBitContext gb; + EVCParserSliceHeader *sh; + EVCParserPPS *pps; + EVCParserSPS *sps; + + int num_tiles_in_slice = 0; + int slice_pic_parameter_set_id; + + if (init_get_bits8(&gb, bs, bs_size) < 0) + return NULL; + + slice_pic_parameter_set_id = get_ue_golomb(&gb); + + if (slice_pic_parameter_set_id < 0 || slice_pic_parameter_set_id >= EVC_MAX_PPS_COUNT) + return NULL; + + if(!ctx->slice_header[slice_pic_parameter_set_id]) { + if((ctx->slice_header[slice_pic_parameter_set_id] = av_malloc(sizeof(EVCParserSliceHeader))) == NULL) + return NULL; + } + + sh = ctx->slice_header[slice_pic_parameter_set_id]; + + pps = ctx->pps[slice_pic_parameter_set_id]; + if(!pps) + return NULL; + + sps = ctx->sps[slice_pic_parameter_set_id]; + if(!sps) + return NULL; + + sh->slice_pic_parameter_set_id = slice_pic_parameter_set_id; + + if (!pps->single_tile_in_pic_flag) { + sh->single_tile_in_slice_flag = get_bits(&gb, 1); + sh->first_tile_id = get_bits(&gb, pps->tile_id_len_minus1 + 1); + } else + sh->single_tile_in_slice_flag = 1; + + if (!sh->single_tile_in_slice_flag) { + if (pps->arbitrary_slice_present_flag) + sh->arbitrary_slice_flag = get_bits(&gb, 1); + + if (!sh->arbitrary_slice_flag) + sh->last_tile_id = get_bits(&gb, pps->tile_id_len_minus1 + 1); + else { + sh->num_remaining_tiles_in_slice_minus1 = get_ue_golomb(&gb); + num_tiles_in_slice = sh->num_remaining_tiles_in_slice_minus1 + 2; + for (int i = 0; i < num_tiles_in_slice - 1; ++i) + sh->delta_tile_id_minus1[i] = get_ue_golomb(&gb); + } + } + + sh->slice_type = get_ue_golomb(&gb); + + if (ctx->nalu_type == EVC_IDR_NUT) + sh->no_output_of_prior_pics_flag = get_bits(&gb, 1); + + if (sps->sps_mmvd_flag && ((sh->slice_type == EVC_SLICE_TYPE_B) || (sh->slice_type == EVC_SLICE_TYPE_P))) + sh->mmvd_group_enable_flag = get_bits(&gb, 1); + else + sh->mmvd_group_enable_flag = 0; + + if (sps->sps_alf_flag) { + int ChromaArrayType = sps->chroma_format_idc; + + sh->slice_alf_enabled_flag = get_bits(&gb, 1); + + if (sh->slice_alf_enabled_flag) { + sh->slice_alf_luma_aps_id = get_bits(&gb, 5); + sh->slice_alf_map_flag = get_bits(&gb, 1); + sh->slice_alf_chroma_idc = get_bits(&gb, 2); + + if ((ChromaArrayType == 1 || ChromaArrayType == 2) && sh->slice_alf_chroma_idc > 0) + sh->slice_alf_chroma_aps_id = get_bits(&gb, 5); + } + if (ChromaArrayType == 3) { + int sliceChromaAlfEnabledFlag = 0; + int sliceChroma2AlfEnabledFlag = 0; + + if (sh->slice_alf_chroma_idc == 1) { // @see ISO_IEC_23094-1 (7.4.5) + sliceChromaAlfEnabledFlag = 1; + sliceChroma2AlfEnabledFlag = 0; + } else if (sh->slice_alf_chroma_idc == 2) { + sliceChromaAlfEnabledFlag = 0; + sliceChroma2AlfEnabledFlag = 1; + } else if (sh->slice_alf_chroma_idc == 3) { + sliceChromaAlfEnabledFlag = 1; + sliceChroma2AlfEnabledFlag = 1; + } else { + sliceChromaAlfEnabledFlag = 0; + sliceChroma2AlfEnabledFlag = 0; + } + + if (!sh->slice_alf_enabled_flag) + sh->slice_alf_chroma_idc = get_bits(&gb, 2); + + if (sliceChromaAlfEnabledFlag) { + sh->slice_alf_chroma_aps_id = get_bits(&gb, 5); + sh->slice_alf_chroma_map_flag = get_bits(&gb, 1); + } + + if (sliceChroma2AlfEnabledFlag) { + sh->slice_alf_chroma2_aps_id = get_bits(&gb, 5); + sh->slice_alf_chroma2_map_flag = get_bits(&gb, 1); + } + } + } + + if (ctx->nalu_type != EVC_IDR_NUT) { + if (sps->sps_pocs_flag) + sh->slice_pic_order_cnt_lsb = get_bits(&gb, sps->log2_max_pic_order_cnt_lsb_minus4 + 4); + } + + // @note + // If necessary, add the missing fields to the EVCParserSliceHeader structure + // and then extend parser implementation + + return sh; +} + +int ff_evc_parse_nal_unit(EVCParserContext *ctx, const uint8_t *buf, int buf_size, void *logctx) +{ + int nalu_type, nalu_size; + int tid; + const uint8_t *data = buf; + int data_size = buf_size; + + // ctx->picture_structure = AV_PICTURE_STRUCTURE_FRAME; + ctx->key_frame = -1; + + nalu_size = buf_size; + if (nalu_size <= 0) { + av_log(logctx, AV_LOG_ERROR, "Invalid NAL unit size: (%d)\n", nalu_size); + return AVERROR_INVALIDDATA; + } + + // @see ISO_IEC_23094-1_2020, 7.4.2.2 NAL unit header semantic (Table 4 - NAL unit type codes and NAL unit type classes) + // @see enum EVCNALUnitType in evc.h + nalu_type = evc_get_nalu_type(data, data_size, logctx); + if (nalu_type < EVC_NOIDR_NUT || nalu_type > EVC_UNSPEC_NUT62) { + av_log(logctx, AV_LOG_ERROR, "Invalid NAL unit type: (%d)\n", nalu_type); + return AVERROR_INVALIDDATA; + } + ctx->nalu_type = nalu_type; + + tid = ff_evc_get_temporal_id(data, data_size, logctx); + if (tid < 0) { + av_log(logctx, AV_LOG_ERROR, "Invalid temporial id: (%d)\n", tid); + return AVERROR_INVALIDDATA; + } + ctx->nuh_temporal_id = tid; + + data += EVC_NALU_HEADER_SIZE; + data_size -= EVC_NALU_HEADER_SIZE; + + switch(nalu_type) { + case EVC_SPS_NUT: { + EVCParserSPS *sps; + int SubGopLength; + int bit_depth; + + sps = ff_evc_parse_sps(ctx, data, nalu_size); + if (!sps) { + av_log(logctx, AV_LOG_ERROR, "SPS parsing error\n"); + return AVERROR_INVALIDDATA; + } + + ctx->coded_width = sps->pic_width_in_luma_samples; + ctx->coded_height = sps->pic_height_in_luma_samples; + + if(sps->picture_cropping_flag) { + ctx->width = sps->pic_width_in_luma_samples - sps->picture_crop_left_offset - sps->picture_crop_right_offset; + ctx->height = sps->pic_height_in_luma_samples - sps->picture_crop_top_offset - sps->picture_crop_bottom_offset; + } else { + ctx->width = sps->pic_width_in_luma_samples; + ctx->height = sps->pic_height_in_luma_samples; + } + + SubGopLength = (int)pow(2.0, sps->log2_sub_gop_length); + ctx->gop_size = SubGopLength; + + ctx->delay = (sps->sps_max_dec_pic_buffering_minus1) ? sps->sps_max_dec_pic_buffering_minus1 - 1 : SubGopLength + sps->max_num_tid0_ref_pics - 1; + + if (sps->profile_idc == 1) ctx->profile = FF_PROFILE_EVC_MAIN; + else ctx->profile = FF_PROFILE_EVC_BASELINE; + + if (sps->vui_parameters_present_flag) { + if (sps->vui_parameters.timing_info_present_flag) { + int64_t num = sps->vui_parameters.num_units_in_tick; + int64_t den = sps->vui_parameters.time_scale; + if (num != 0 && den != 0) + av_reduce(&ctx->framerate.den, &ctx->framerate.num, num, den, 1 << 30); + } + } + + bit_depth = sps->bit_depth_chroma_minus8 + 8; + ctx->format = AV_PIX_FMT_NONE; + + switch (bit_depth) { + case 8: + ctx->format = pix_fmts_8bit[sps->chroma_format_idc]; + break; + case 9: + ctx->format = pix_fmts_9bit[sps->chroma_format_idc]; + break; + case 10: + ctx->format = pix_fmts_10bit[sps->chroma_format_idc]; + break; + case 12: + ctx->format = pix_fmts_12bit[sps->chroma_format_idc]; + break; + case 14: + ctx->format = pix_fmts_14bit[sps->chroma_format_idc]; + break; + case 16: + ctx->format = pix_fmts_16bit[sps->chroma_format_idc]; + break; + } + av_assert0(ctx->format != AV_PIX_FMT_NONE); + + break; + } + case EVC_PPS_NUT: { + EVCParserPPS *pps; + + pps = ff_evc_parse_pps(ctx, data, nalu_size); + if (!pps) { + av_log(logctx, AV_LOG_ERROR, "PPS parsing error\n"); + return AVERROR_INVALIDDATA; + } + break; + } + case EVC_SEI_NUT: // Supplemental Enhancement Information + case EVC_APS_NUT: // Adaptation parameter set + case EVC_FD_NUT: // Filler data + break; + case EVC_IDR_NUT: // Coded slice of a IDR or non-IDR picture + case EVC_NOIDR_NUT: { + EVCParserSliceHeader *sh; + EVCParserSPS *sps; + int slice_pic_parameter_set_id; + + sh = ff_evc_parse_slice_header(ctx, data, nalu_size); + if (!sh) { + av_log(logctx, AV_LOG_ERROR, "Slice header parsing error\n"); + return AVERROR_INVALIDDATA; + } + + switch (sh->slice_type) { + case EVC_SLICE_TYPE_B: { + ctx->pict_type = AV_PICTURE_TYPE_B; + break; + } + case EVC_SLICE_TYPE_P: { + ctx->pict_type = AV_PICTURE_TYPE_P; + break; + } + case EVC_SLICE_TYPE_I: { + ctx->pict_type = AV_PICTURE_TYPE_I; + break; + } + default: { + ctx->pict_type = AV_PICTURE_TYPE_NONE; + } + } + + ctx->key_frame = (nalu_type == EVC_IDR_NUT) ? 1 : 0; + + // POC (picture order count of the current picture) derivation + // @see ISO/IEC 23094-1:2020(E) 8.3.1 Decoding process for picture order count + slice_pic_parameter_set_id = sh->slice_pic_parameter_set_id; + sps = ctx->sps[slice_pic_parameter_set_id]; + + if (sps && sps->sps_pocs_flag) { + + int PicOrderCntMsb = 0; + ctx->poc.prevPicOrderCntVal = ctx->poc.PicOrderCntVal; + + if (nalu_type == EVC_IDR_NUT) + PicOrderCntMsb = 0; + else { + int MaxPicOrderCntLsb = 1 << (sps->log2_max_pic_order_cnt_lsb_minus4 + 4); + + int prevPicOrderCntLsb = ctx->poc.PicOrderCntVal & (MaxPicOrderCntLsb - 1); + int prevPicOrderCntMsb = ctx->poc.PicOrderCntVal - prevPicOrderCntLsb; + + + if ((sh->slice_pic_order_cnt_lsb < prevPicOrderCntLsb) && + ((prevPicOrderCntLsb - sh->slice_pic_order_cnt_lsb) >= (MaxPicOrderCntLsb / 2))) + + PicOrderCntMsb = prevPicOrderCntMsb + MaxPicOrderCntLsb; + + else if ((sh->slice_pic_order_cnt_lsb > prevPicOrderCntLsb) && + ((sh->slice_pic_order_cnt_lsb - prevPicOrderCntLsb) > (MaxPicOrderCntLsb / 2))) + + PicOrderCntMsb = prevPicOrderCntMsb - MaxPicOrderCntLsb; + + else + PicOrderCntMsb = prevPicOrderCntMsb; + } + ctx->poc.PicOrderCntVal = PicOrderCntMsb + sh->slice_pic_order_cnt_lsb; + + } else { + if (nalu_type == EVC_IDR_NUT) { + ctx->poc.PicOrderCntVal = 0; + ctx->poc.DocOffset = -1; + } else { + int SubGopLength = (int)pow(2.0, sps->log2_sub_gop_length); + if (tid == 0) { + ctx->poc.PicOrderCntVal = ctx->poc.prevPicOrderCntVal + SubGopLength; + ctx->poc.DocOffset = 0; + ctx->poc.prevPicOrderCntVal = ctx->poc.PicOrderCntVal; + } else { + int ExpectedTemporalId; + int PocOffset; + int prevDocOffset = ctx->poc.DocOffset; + + ctx->poc.DocOffset = (prevDocOffset + 1) % SubGopLength; + if (ctx->poc.DocOffset == 0) { + ctx->poc.prevPicOrderCntVal += SubGopLength; + ExpectedTemporalId = 0; + } else + ExpectedTemporalId = 1 + (int)log2(ctx->poc.DocOffset); + while (tid != ExpectedTemporalId) { + ctx->poc.DocOffset = (ctx->poc.DocOffset + 1) % SubGopLength; + if (ctx->poc.DocOffset == 0) + ExpectedTemporalId = 0; + else + ExpectedTemporalId = 1 + (int)log2(ctx->poc.DocOffset); + } + PocOffset = (int)(SubGopLength * ((2.0 * ctx->poc.DocOffset + 1) / (int)pow(2.0, tid) - 2)); + ctx->poc.PicOrderCntVal = ctx->poc.prevPicOrderCntVal + PocOffset; + } + } + } + + ctx->output_picture_number = ctx->poc.PicOrderCntVal; + ctx->key_frame = (nalu_type == EVC_IDR_NUT) ? 1 : 0; + + break; + } + } + + return 0; +} + diff --git a/libavcodec/evc_parse.h b/libavcodec/evc_parse.h new file mode 100644 index 00000000000..d74a3b51599 --- /dev/null +++ b/libavcodec/evc_parse.h @@ -0,0 +1,357 @@ +/* + * 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 + * EVC decoder/parser shared code + */ + +#ifndef AVCODEC_EVC_PARSE_H +#define AVCODEC_EVC_PARSE_H + +#define EVC_MAX_QP_TABLE_SIZE 58 +#define NUM_CPB 32 + +// rpl structure +typedef struct RefPicListStruct { + int poc; + int tid; + int ref_pic_num; + int ref_pic_active_num; + int ref_pics[EVC_MAX_NUM_REF_PICS]; + char pic_type; + +} RefPicListStruct; + +// chromaQP table structure to be signalled in SPS +typedef struct ChromaQpTable { + int chroma_qp_table_present_flag; // u(1) + int same_qp_table_for_chroma; // u(1) + int global_offset_flag; // u(1) + int num_points_in_qp_table_minus1[2]; // ue(v) + int delta_qp_in_val_minus1[2][EVC_MAX_QP_TABLE_SIZE]; // u(6) + int delta_qp_out_val[2][EVC_MAX_QP_TABLE_SIZE]; // se(v) +} ChromaQpTable; + +// Hypothetical Reference Decoder (HRD) parameters, part of VUI +typedef struct HRDParameters { + int cpb_cnt_minus1; // ue(v) + int bit_rate_scale; // u(4) + int cpb_size_scale; // u(4) + int bit_rate_value_minus1[NUM_CPB]; // ue(v) + int cpb_size_value_minus1[NUM_CPB]; // ue(v) + int cbr_flag[NUM_CPB]; // u(1) + int initial_cpb_removal_delay_length_minus1; // u(5) + int cpb_removal_delay_length_minus1; // u(5) + int dpb_output_delay_length_minus1; // u(5) + int time_offset_length; // u(5) +} HRDParameters; + +// video usability information (VUI) part of SPS +typedef struct VUIParameters { + int aspect_ratio_info_present_flag; // u(1) + int aspect_ratio_idc; // u(8) + int sar_width; // u(16) + int sar_height; // u(16) + int overscan_info_present_flag; // u(1) + int overscan_appropriate_flag; // u(1) + int video_signal_type_present_flag; // u(1) + int video_format; // u(3) + int video_full_range_flag; // u(1) + int colour_description_present_flag; // u(1) + int colour_primaries; // u(8) + int transfer_characteristics; // u(8) + int matrix_coefficients; // u(8) + int chroma_loc_info_present_flag; // u(1) + int chroma_sample_loc_type_top_field; // ue(v) + int chroma_sample_loc_type_bottom_field; // ue(v) + int neutral_chroma_indication_flag; // u(1) + int field_seq_flag; // u(1) + int timing_info_present_flag; // u(1) + int num_units_in_tick; // u(32) + int time_scale; // u(32) + int fixed_pic_rate_flag; // u(1) + int nal_hrd_parameters_present_flag; // u(1) + int vcl_hrd_parameters_present_flag; // u(1) + int low_delay_hrd_flag; // u(1) + int pic_struct_present_flag; // u(1) + int bitstream_restriction_flag; // u(1) + int motion_vectors_over_pic_boundaries_flag; // u(1) + int max_bytes_per_pic_denom; // ue(v) + int max_bits_per_mb_denom; // ue(v) + int log2_max_mv_length_horizontal; // ue(v) + int log2_max_mv_length_vertical; // ue(v) + int num_reorder_pics; // ue(v) + int max_dec_pic_buffering; // ue(v) + + HRDParameters hrd_parameters; +} VUIParameters; + +// The sturcture reflects SPS RBSP(raw byte sequence payload) layout +// @see ISO_IEC_23094-1 section 7.3.2.1 +// +// The following descriptors specify the parsing process of each element +// u(n) - unsigned integer using n bits +// ue(v) - unsigned integer 0-th order Exp_Golomb-coded syntax element with the left bit first +typedef struct EVCParserSPS { + int sps_seq_parameter_set_id; // ue(v) + int profile_idc; // u(8) + int level_idc; // u(8) + int toolset_idc_h; // u(32) + int toolset_idc_l; // u(32) + int chroma_format_idc; // ue(v) + int pic_width_in_luma_samples; // ue(v) + int pic_height_in_luma_samples; // ue(v) + int bit_depth_luma_minus8; // ue(v) + int bit_depth_chroma_minus8; // ue(v) + + int sps_btt_flag; // u(1) + int log2_ctu_size_minus5; // ue(v) + int log2_min_cb_size_minus2; // ue(v) + int log2_diff_ctu_max_14_cb_size; // ue(v) + int log2_diff_ctu_max_tt_cb_size; // ue(v) + int log2_diff_min_cb_min_tt_cb_size_minus2; // ue(v) + + int sps_suco_flag; // u(1) + int log2_diff_ctu_size_max_suco_cb_size; // ue(v) + int log2_diff_max_suco_min_suco_cb_size; // ue(v) + + int sps_admvp_flag; // u(1) + int sps_affine_flag; // u(1) + int sps_amvr_flag; // u(1) + int sps_dmvr_flag; // u(1) + int sps_mmvd_flag; // u(1) + int sps_hmvp_flag; // u(1) + + int sps_eipd_flag; // u(1) + int sps_ibc_flag; // u(1) + int log2_max_ibc_cand_size_minus2; // ue(v) + + int sps_cm_init_flag; // u(1) + int sps_adcc_flag; // u(1) + + int sps_iqt_flag; // u(1) + int sps_ats_flag; // u(1) + + int sps_addb_flag; // u(1) + int sps_alf_flag; // u(1) + int sps_htdf_flag; // u(1) + int sps_rpl_flag; // u(1) + int sps_pocs_flag; // u(1) + int sps_dquant_flag; // u(1) + int sps_dra_flag; // u(1) + + int log2_max_pic_order_cnt_lsb_minus4; // ue(v) + int log2_sub_gop_length; // ue(v) + int log2_ref_pic_gap_length; // ue(v) + + int max_num_tid0_ref_pics; // ue(v) + + int sps_max_dec_pic_buffering_minus1; // ue(v) + int long_term_ref_pic_flag; // u(1) + int rpl1_same_as_rpl0_flag; // u(1) + int num_ref_pic_list_in_sps[2]; // ue(v) + struct RefPicListStruct rpls[2][EVC_MAX_NUM_RPLS]; + + int picture_cropping_flag; // u(1) + int picture_crop_left_offset; // ue(v) + int picture_crop_right_offset; // ue(v) + int picture_crop_top_offset; // ue(v) + int picture_crop_bottom_offset; // ue(v) + + struct ChromaQpTable chroma_qp_table_struct; + + int vui_parameters_present_flag; // u(1) + + struct VUIParameters vui_parameters; + +} EVCParserSPS; + +typedef struct EVCParserPPS { + int pps_pic_parameter_set_id; // ue(v) + int pps_seq_parameter_set_id; // ue(v) + int num_ref_idx_default_active_minus1[2]; // ue(v) + int additional_lt_poc_lsb_len; // ue(v) + int rpl1_idx_present_flag; // u(1) + int single_tile_in_pic_flag; // u(1) + int num_tile_columns_minus1; // ue(v) + int num_tile_rows_minus1; // ue(v) + int uniform_tile_spacing_flag; // u(1) + int tile_column_width_minus1[EVC_MAX_TILE_ROWS]; // ue(v) + int tile_row_height_minus1[EVC_MAX_TILE_COLUMNS]; // ue(v) + int loop_filter_across_tiles_enabled_flag; // u(1) + int tile_offset_len_minus1; // ue(v) + int tile_id_len_minus1; // ue(v) + int explicit_tile_id_flag; // u(1) + int tile_id_val[EVC_MAX_TILE_ROWS][EVC_MAX_TILE_COLUMNS]; // u(v) + int pic_dra_enabled_flag; // u(1) + int pic_dra_aps_id; // u(5) + int arbitrary_slice_present_flag; // u(1) + int constrained_intra_pred_flag; // u(1) + int cu_qp_delta_enabled_flag; // u(1) + int log2_cu_qp_delta_area_minus6; // ue(v) + +} EVCParserPPS; + +// The sturcture reflects Slice Header RBSP(raw byte sequence payload) layout +// @see ISO_IEC_23094-1 section 7.3.2.6 +// +// The following descriptors specify the parsing process of each element +// u(n) - unsigned integer using n bits +// ue(v) - unsigned integer 0-th order Exp_Golomb-coded syntax element with the left bit first +// u(n) - unsigned integer using n bits. +// When n is "v" in the syntax table, the number of bits varies in a manner dependent on the value of other syntax elements. +typedef struct EVCParserSliceHeader { + int slice_pic_parameter_set_id; // ue(v) + int single_tile_in_slice_flag; // u(1) + int first_tile_id; // u(v) + int arbitrary_slice_flag; // u(1) + int last_tile_id; // u(v) + int num_remaining_tiles_in_slice_minus1; // ue(v) + int delta_tile_id_minus1[EVC_MAX_TILE_ROWS * EVC_MAX_TILE_COLUMNS]; // ue(v) + + int slice_type; // ue(v) + int no_output_of_prior_pics_flag; // u(1) + int mmvd_group_enable_flag; // u(1) + int slice_alf_enabled_flag; // u(1) + + int slice_alf_luma_aps_id; // u(5) + int slice_alf_map_flag; // u(1) + int slice_alf_chroma_idc; // u(2) + int slice_alf_chroma_aps_id; // u(5) + int slice_alf_chroma_map_flag; // u(1) + int slice_alf_chroma2_aps_id; // u(5) + int slice_alf_chroma2_map_flag; // u(1) + int slice_pic_order_cnt_lsb; // u(v) + + // @note + // Currently the structure does not reflect the entire Slice Header RBSP layout. + // It contains only the fields that are necessary to read from the NAL unit all the values + // necessary for the correct initialization of the AVCodecContext structure. + + // @note + // If necessary, add the missing fields to the structure to reflect + // the contents of the entire NAL unit of the SPS type + +} EVCParserSliceHeader; + +// picture order count of the current picture +typedef struct EVCParserPoc { + int PicOrderCntVal; // current picture order count value + int prevPicOrderCntVal; // the picture order count of the previous Tid0 picture + int DocOffset; // the decoding order count of the previous picture +} EVCParserPoc; + +typedef struct EVCParserContext { + //ParseContext pc; + EVCParserSPS *sps[EVC_MAX_SPS_COUNT]; + EVCParserPPS *pps[EVC_MAX_PPS_COUNT]; + EVCParserSliceHeader *slice_header[EVC_MAX_PPS_COUNT]; + + EVCParserPoc poc; + + int nuh_temporal_id; // the value of TemporalId (shall be the same for all VCL NAL units of an Access Unit) + int nalu_type; // the current NALU type + + // Dimensions of the decoded video intended for presentation. + int width; + int height; + + // Dimensions of the coded video. + int coded_width; + int coded_height; + + // The format of the coded data, corresponds to enum AVPixelFormat + int format; + + // AV_PICTURE_TYPE_I, EVC_SLICE_TYPE_P, AV_PICTURE_TYPE_B + int pict_type; + + // Set by parser to 1 for key frames and 0 for non-key frames + int key_frame; + + // Picture number incremented in presentation or output order. + // This corresponds to EVCEVCParserPoc::PicOrderCntVal + int output_picture_number; + + // profile + // 0: FF_PROFILE_EVC_BASELINE + // 1: FF_PROFILE_EVC_MAIN + int profile; + + // Framerate value in the compressed bitstream + AVRational framerate; + + // Number of pictures in a group of pictures + int gop_size; + + // Number of frames the decoded output will be delayed relative to the encoded input + int delay; + + int parsed_extradata; + +} EVCParserContext; + +static inline int evc_get_nalu_type(const uint8_t *bits, int bits_size, void *logctx) +{ + int unit_type_plus1 = 0; + + if (bits_size >= EVC_NALU_HEADER_SIZE) { + unsigned char *p = (unsigned char *)bits; + // forbidden_zero_bit + if ((p[0] & 0x80) != 0) { + av_log(logctx, AV_LOG_ERROR, "Invalid NAL unit header\n"); + return -1; + } + + // nal_unit_type + unit_type_plus1 = (p[0] >> 1) & 0x3F; + } + + return unit_type_plus1 - 1; +} + +static inline uint32_t evc_read_nal_unit_length(const uint8_t *bits, int bits_size, void *logctx) +{ + uint32_t nalu_len = 0; + + if (bits_size < EVC_NALU_LENGTH_PREFIX_SIZE) { + av_log(logctx, AV_LOG_ERROR, "Can't read NAL unit length\n"); + return 0; + } + + nalu_len = AV_RB32(bits); + + return nalu_len; +} + +// nuh_temporal_id specifies a temporal identifier for the NAL unit +int ff_evc_get_temporal_id(const uint8_t *bits, int bits_size, void *logctx); + +// @see ISO_IEC_23094-1 (7.3.2.1 SPS RBSP syntax) +EVCParserSPS *ff_evc_parse_sps(EVCParserContext *ctx, const uint8_t *bs, int bs_size); + +// @see ISO_IEC_23094-1 (7.3.2.2 SPS RBSP syntax) +EVCParserPPS *ff_evc_parse_pps(EVCParserContext *ctx, const uint8_t *bs, int bs_size); + +// @see ISO_IEC_23094-1 (7.3.2.6 Slice layer RBSP syntax) +EVCParserSliceHeader *ff_evc_parse_slice_header(EVCParserContext *ctx, const uint8_t *bs, int bs_size); + +int ff_evc_parse_nal_unit(EVCParserContext *ctx, const uint8_t *buf, int buf_size, void *logctx); + +#endif /* AVCODEC_EVC_PARSE_H */ diff --git a/libavcodec/evc_parser.c b/libavcodec/evc_parser.c new file mode 100644 index 00000000000..7528fb13db7 --- /dev/null +++ b/libavcodec/evc_parser.c @@ -0,0 +1,235 @@ +/* + * EVC format parser + * + * Copyright (C) 2021 Dawid Kozinski + * + * 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 "parser.h" +#include "bytestream.h" +#include "evc.h" +#include "evc_parse.h" + +/** + * Parse NAL units of found picture and decode some basic information. + * + * @param s codec parser context + * @param avctx codec context + * @param buf buffer with field/frame data + * @param buf_size size of the buffer + */ +static int parse_nal_units(AVCodecParserContext *s, AVCodecContext *avctx, const uint8_t *buf, int buf_size) +{ + EVCParserContext *ctx = s->priv_data; + const uint8_t *data = buf; + int data_size = buf_size; + int bytes_read = 0; + int nalu_size = 0; + + while (data_size > 0) { + + // Buffer size is not enough for buffer to store NAL unit 4-bytes prefix (length) + if (data_size < EVC_NALU_LENGTH_PREFIX_SIZE) + return AVERROR_INVALIDDATA; + + nalu_size = evc_read_nal_unit_length(data, data_size, avctx); + + bytes_read += EVC_NALU_LENGTH_PREFIX_SIZE; + + data += EVC_NALU_LENGTH_PREFIX_SIZE; + data_size -= EVC_NALU_LENGTH_PREFIX_SIZE; + + if (data_size < nalu_size) + return AVERROR_INVALIDDATA; + + if (ff_evc_parse_nal_unit(ctx, data, nalu_size, avctx) != 0) { + av_log(avctx, AV_LOG_ERROR, "Parsing of NAL unit failed\n"); + return AVERROR_INVALIDDATA; + } + + if(ctx->nalu_type == EVC_SPS_NUT) { + + s->coded_width = ctx->coded_width; + s->coded_height = ctx->coded_height; + s->width = ctx->width; + s->height = ctx->height; + + s->format = ctx->format; + + avctx->gop_size = ctx->gop_size; + avctx->delay = ctx->delay; + avctx->profile = ctx->profile; + + } else if(ctx->nalu_type == EVC_NOIDR_NUT || ctx->nalu_type == EVC_IDR_NUT) { + + s->pict_type = ctx->pict_type; + s->key_frame = ctx->key_frame; + s->output_picture_number = ctx->output_picture_number; + + } + + data += nalu_size; + data_size -= nalu_size; + } + return 0; +} + +// Decoding nal units from evcC (EVCDecoderConfigurationRecord) +// @see @see ISO/IEC 14496-15:2021 Coding of audio-visual objects - Part 15: section 12.3.3.2 +static int decode_extradata(EVCParserContext *ctx, const uint8_t *data, int size, void *logctx) +{ + int ret = 0; + GetByteContext gb; + + bytestream2_init(&gb, data, size); + + if (!data || size <= 0) + return -1; + + // extradata is encoded as evcC format. + if (data[0] == 1) { + int num_of_arrays; // indicates the number of arrays of NAL units of the indicated type(s) + + int nalu_length_field_size; // indicates the length in bytes of the NALUnitLenght field in EVC video stream sample in the stream + // The value of this field shall be one of 0, 1, or 3 corresponding to a length encoded with 1, 2, or 4 bytes, respectively. + + if (bytestream2_get_bytes_left(&gb) < 18) { + av_log(logctx, AV_LOG_ERROR, "evcC %d too short\n", size); + return AVERROR_INVALIDDATA; + } + + bytestream2_skip(&gb, 16); + + // @see ISO/IEC 14496-15:2021 Coding of audio-visual objects - Part 15: section 12.3.3.3 + // LengthSizeMinusOne plus 1 indicates the length in bytes of the NALUnitLength field in a EVC video stream sample in the stream to which this configuration record applies. For example, a size of one byte is indicated with a value of 0. + // The value of this field shall be one of 0, 1, or 3 corresponding to a length encoded with 1, 2, or 4 bytes, respectively. + nalu_length_field_size = (bytestream2_get_byte(&gb) & 3) + 1; + if( nalu_length_field_size != 1 && + nalu_length_field_size != 2 && + nalu_length_field_size != 4 ) { + av_log(logctx, AV_LOG_ERROR, "The length in bytes of the NALUnitLenght field in a EVC video stream has unsupported value of %d\n", nalu_length_field_size); + return AVERROR_INVALIDDATA; + } + + num_of_arrays = bytestream2_get_byte(&gb); + + /* Decode nal units from evcC. */ + for (int i = 0; i < num_of_arrays; i++) { + + // @see ISO/IEC 14496-15:2021 Coding of audio-visual objects - Part 15: section 12.3.3.3 + // NAL_unit_type indicates the type of the NAL units in the following array (which shall be all of that type); + // - it takes a value as defined in ISO/IEC 23094-1; + // - it is restricted to take one of the values indicating a SPS, PPS, APS, or SEI NAL unit. + int nal_unit_type = bytestream2_get_byte(&gb) & 0x3f; + int num_nalus = bytestream2_get_be16(&gb); + + for (int j = 0; j < num_nalus; j++) { + + int nal_unit_length = bytestream2_get_be16(&gb); + + if (bytestream2_get_bytes_left(&gb) < nal_unit_length) { + av_log(logctx, AV_LOG_ERROR, "Invalid NAL unit size in extradata.\n"); + return AVERROR_INVALIDDATA; + } + + if( nal_unit_type == EVC_SPS_NUT || + nal_unit_type == EVC_PPS_NUT || + nal_unit_type == EVC_APS_NUT || + nal_unit_type == EVC_SEI_NUT ) { + if (ff_evc_parse_nal_unit(ctx, gb.buffer, nal_unit_length, logctx) != 0) { + av_log(logctx, AV_LOG_ERROR, "Parsing of NAL unit failed\n"); + return AVERROR_INVALIDDATA; + } + } + + bytestream2_skip(&gb, nal_unit_length); + } + } + } else + return -1; + + return ret; +} + +static int evc_parse(AVCodecParserContext *s, AVCodecContext *avctx, + const uint8_t **poutbuf, int *poutbuf_size, + const uint8_t *buf, int buf_size) +{ + int next; + int ret; + EVCParserContext *ctx = s->priv_data; + + if (avctx->extradata && !ctx->parsed_extradata) { + decode_extradata(ctx, avctx->extradata, avctx->extradata_size, avctx); + ctx->parsed_extradata = 1; + } + + next = buf_size; + + ret = parse_nal_units(s, avctx, buf, buf_size); + if(ret < 0) { + *poutbuf = NULL; + *poutbuf_size = 0; + return buf_size; + } + + s->picture_structure = AV_PICTURE_STRUCTURE_FRAME; + + // poutbuf contains just one Access Unit + *poutbuf = buf; + *poutbuf_size = buf_size; + + return next; +} + +static int evc_parser_init(AVCodecParserContext *s) +{ + EVCParserContext *ctx = s->priv_data; + + memset(ctx->sps, 0, sizeof(EVCParserSPS *)*EVC_MAX_SPS_COUNT); + memset(ctx->pps, 0, sizeof(EVCParserPPS *)*EVC_MAX_PPS_COUNT); + memset(ctx->slice_header, 0, sizeof(EVCParserSliceHeader *)*EVC_MAX_PPS_COUNT); + + return 0; +} + +static void evc_parser_close(AVCodecParserContext *s) +{ + EVCParserContext *ctx = s->priv_data; + + for(int i = 0; i < EVC_MAX_SPS_COUNT; i++) { + EVCParserSPS *sps = ctx->sps[i]; + av_freep(&sps); + } + + for(int i = 0; i < EVC_MAX_PPS_COUNT; i++) { + EVCParserPPS *pps = ctx->pps[i]; + EVCParserSliceHeader *sh = ctx->slice_header[i]; + + av_freep(&pps); + av_freep(&sh); + } +} + +const AVCodecParser ff_evc_parser = { + .codec_ids = { AV_CODEC_ID_EVC }, + .priv_data_size = sizeof(EVCParserContext), + .parser_init = evc_parser_init, + .parser_parse = evc_parse, + .parser_close = evc_parser_close, +}; diff --git a/libavcodec/parsers.c b/libavcodec/parsers.c index d3558080181..2c077ec3ae0 100644 --- a/libavcodec/parsers.c +++ b/libavcodec/parsers.c @@ -41,6 +41,7 @@ extern const AVCodecParser ff_dvaudio_parser; extern const AVCodecParser ff_dvbsub_parser; extern const AVCodecParser ff_dvdsub_parser; extern const AVCodecParser ff_dvd_nav_parser; +extern const AVCodecParser ff_evc_parser; extern const AVCodecParser ff_flac_parser; extern const AVCodecParser ff_ftr_parser; extern const AVCodecParser ff_g723_1_parser; From 3069a8fe3cc7159dceec29130deb101edf99b456 Mon Sep 17 00:00:00 2001 From: Dawid Kozinski Date: Thu, 15 Jun 2023 13:47:03 +0200 Subject: [PATCH 1471/2172] avformat/evc_muxer: Added muxer to handle writing EVC encoded data into file or output bytestream - Provided AVOutputFormat structure describing EVC output format (ff_evc_muxer) - Added documentation for EVC muxer Signed-off-by: Dawid Kozinski --- doc/muxers.texi | 6 ++++++ libavformat/Makefile | 1 + libavformat/allformats.c | 1 + libavformat/rawenc.c | 13 +++++++++++++ 4 files changed, 21 insertions(+) diff --git a/doc/muxers.texi b/doc/muxers.texi index 91d30c5b3be..f6071484ff6 100644 --- a/doc/muxers.texi +++ b/doc/muxers.texi @@ -2122,6 +2122,12 @@ DTS Coherent Acoustics (DCA) audio. Dolby Digital Plus, also known as Enhanced AC-3, audio. +@subsection evc + +MPEG-5 Essential Video Coding (EVC) / EVC / MPEG-5 Part 1 EVC video. + +Extensions: evc + @subsection g722 ITU-T G.722 audio. diff --git a/libavformat/Makefile b/libavformat/Makefile index 05434a0f82d..f31135d806b 100644 --- a/libavformat/Makefile +++ b/libavformat/Makefile @@ -251,6 +251,7 @@ OBJS-$(CONFIG_HCOM_DEMUXER) += hcom.o pcm.o OBJS-$(CONFIG_HDS_MUXER) += hdsenc.o OBJS-$(CONFIG_HEVC_DEMUXER) += hevcdec.o rawdec.o OBJS-$(CONFIG_HEVC_MUXER) += rawenc.o +OBJS-$(CONFIG_EVC_MUXER) += rawenc.o OBJS-$(CONFIG_HLS_DEMUXER) += hls.o hls_sample_encryption.o OBJS-$(CONFIG_HLS_MUXER) += hlsenc.o hlsplaylist.o avc.o OBJS-$(CONFIG_HNM_DEMUXER) += hnm.o diff --git a/libavformat/allformats.c b/libavformat/allformats.c index 96443a72721..d3871de2681 100644 --- a/libavformat/allformats.c +++ b/libavformat/allformats.c @@ -154,6 +154,7 @@ extern const AVInputFormat ff_ea_cdata_demuxer; extern const AVInputFormat ff_eac3_demuxer; extern const FFOutputFormat ff_eac3_muxer; extern const AVInputFormat ff_epaf_demuxer; +extern const FFOutputFormat ff_evc_muxer; extern const FFOutputFormat ff_f4v_muxer; extern const AVInputFormat ff_ffmetadata_demuxer; extern const FFOutputFormat ff_ffmetadata_muxer; diff --git a/libavformat/rawenc.c b/libavformat/rawenc.c index 78fadda9679..70d6322c537 100644 --- a/libavformat/rawenc.c +++ b/libavformat/rawenc.c @@ -401,6 +401,19 @@ const FFOutputFormat ff_hevc_muxer = { }; #endif +#if CONFIG_EVC_MUXER +const FFOutputFormat ff_evc_muxer = { + .p.name = "evc", + .p.long_name = NULL_IF_CONFIG_SMALL("raw EVC video"), + .p.extensions = "evc", + .p.audio_codec = AV_CODEC_ID_NONE, + .p.video_codec = AV_CODEC_ID_EVC, + .init = force_one_stream, + .write_packet = ff_raw_write_packet, + .p.flags = AVFMT_NOTIMESTAMPS, +}; +#endif + #if CONFIG_M4V_MUXER const FFOutputFormat ff_m4v_muxer = { .p.name = "m4v", From ab2671c5f2396864fa8da2ebae0b2a5aa942167f Mon Sep 17 00:00:00 2001 From: Dawid Kozinski Date: Thu, 15 Jun 2023 13:47:26 +0200 Subject: [PATCH 1472/2172] avformat/evc_demuxer: Added demuxer to handle reading EVC video files - Provided AVInputFormat struct describing EVC input format (ff_evc_demuxer) Signed-off-by: Dawid Kozinski --- libavcodec/Makefile | 1 + libavcodec/bitstream_filters.c | 5 +- libavcodec/evc_frame_merge_bsf.c | 170 +++++++++++++++++++ libavformat/Makefile | 1 + libavformat/allformats.c | 1 + libavformat/evcdec.c | 276 +++++++++++++++++++++++++++++++ 6 files changed, 452 insertions(+), 2 deletions(-) create mode 100644 libavcodec/evc_frame_merge_bsf.c create mode 100644 libavformat/evcdec.c diff --git a/libavcodec/Makefile b/libavcodec/Makefile index a28919992ad..0ce8fe5b9ca 100644 --- a/libavcodec/Makefile +++ b/libavcodec/Makefile @@ -1258,6 +1258,7 @@ OBJS-$(CONFIG_VP9_METADATA_BSF) += vp9_metadata_bsf.o OBJS-$(CONFIG_VP9_RAW_REORDER_BSF) += vp9_raw_reorder_bsf.o OBJS-$(CONFIG_VP9_SUPERFRAME_BSF) += vp9_superframe_bsf.o OBJS-$(CONFIG_VP9_SUPERFRAME_SPLIT_BSF) += vp9_superframe_split_bsf.o +OBJS-$(CONFIG_EVC_FRAME_MERGE_BSF) += evc_frame_merge_bsf.o # thread libraries OBJS-$(HAVE_LIBC_MSVCRT) += file_open.o diff --git a/libavcodec/bitstream_filters.c b/libavcodec/bitstream_filters.c index e8216819cae..7512fccc782 100644 --- a/libavcodec/bitstream_filters.c +++ b/libavcodec/bitstream_filters.c @@ -65,16 +65,17 @@ extern const FFBitStreamFilter ff_vp9_metadata_bsf; extern const FFBitStreamFilter ff_vp9_raw_reorder_bsf; extern const FFBitStreamFilter ff_vp9_superframe_bsf; extern const FFBitStreamFilter ff_vp9_superframe_split_bsf; +extern const FFBitStreamFilter ff_evc_frame_merge_bsf; #include "libavcodec/bsf_list.c" const AVBitStreamFilter *av_bsf_iterate(void **opaque) { - uintptr_t i = (uintptr_t)*opaque; + uintptr_t i = (uintptr_t) * opaque; const FFBitStreamFilter *f = bitstream_filters[i]; if (f) { - *opaque = (void*)(i + 1); + *opaque = (void *)(i + 1); return &f->p; } return NULL; diff --git a/libavcodec/evc_frame_merge_bsf.c b/libavcodec/evc_frame_merge_bsf.c new file mode 100644 index 00000000000..d2746a1ef6a --- /dev/null +++ b/libavcodec/evc_frame_merge_bsf.c @@ -0,0 +1,170 @@ +/* + * Copyright (c) 2019 James Almer + * + * 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 "get_bits.h" +#include "golomb.h" +#include "bsf.h" +#include "bsf_internal.h" +#include "avcodec.h" + +#include "evc.h" +#include "evc_parse.h" + +#define INIT_AU_BUF_CAPACITY 1024 + +// Access unit data +typedef struct AccessUnitBuffer { + uint8_t *data; // the data buffer + size_t data_size; // size of data in bytes + size_t capacity; // buffer capacity +} AccessUnitBuffer; + +typedef struct EVCFMergeContext { + AVPacket *in; + EVCParserContext parser_ctx; + AccessUnitBuffer au_buffer; +} EVCFMergeContext; + +static int end_of_access_unit_found(EVCParserContext *parser_ctx) +{ + if (parser_ctx->profile == 0) { // BASELINE profile + if (parser_ctx->nalu_type == EVC_NOIDR_NUT || parser_ctx->nalu_type == EVC_IDR_NUT) + return 1; + } else { // MAIN profile + if (parser_ctx->nalu_type == EVC_NOIDR_NUT) { + if (parser_ctx->poc.PicOrderCntVal != parser_ctx->poc.prevPicOrderCntVal) + return 1; + } else if (parser_ctx->nalu_type == EVC_IDR_NUT) + return 1; + } + return 0; +} + +static void evc_frame_merge_flush(AVBSFContext *bsf) +{ + EVCFMergeContext *ctx = bsf->priv_data; + + av_packet_unref(ctx->in); +} + +static int evc_frame_merge_filter(AVBSFContext *bsf, AVPacket *out) +{ + EVCFMergeContext *ctx = bsf->priv_data; + EVCParserContext *parser_ctx = &ctx->parser_ctx; + + AVPacket *in = ctx->in; + + int free_space = 0; + size_t nalu_size = 0; + uint8_t *nalu = NULL; + int au_end_found = 0; + int err; + + err = ff_bsf_get_packet_ref(bsf, in); + if (err < 0) + return err; + + nalu_size = evc_read_nal_unit_length(in->data, EVC_NALU_LENGTH_PREFIX_SIZE, bsf); + if (nalu_size <= 0) { + av_packet_unref(in); + return AVERROR_INVALIDDATA; + } + + nalu = in->data + EVC_NALU_LENGTH_PREFIX_SIZE; + nalu_size = in->size - EVC_NALU_LENGTH_PREFIX_SIZE; + + // NAL unit parsing needed to determine if end of AU was found + err = ff_evc_parse_nal_unit(parser_ctx, nalu, nalu_size, bsf); + if (err < 0) { + av_log(bsf, AV_LOG_ERROR, "NAL Unit parsing error\n"); + av_packet_unref(in); + + return err; + } + + au_end_found = end_of_access_unit_found(parser_ctx); + + free_space = ctx->au_buffer.capacity - ctx->au_buffer.data_size; + while (free_space < in->size) { + ctx->au_buffer.capacity *= 2; + free_space = ctx->au_buffer.capacity - ctx->au_buffer.data_size; + + if (free_space >= in->size) + ctx->au_buffer.data = av_realloc(ctx->au_buffer.data, ctx->au_buffer.capacity); + } + + memcpy(ctx->au_buffer.data + ctx->au_buffer.data_size, in->data, in->size); + + ctx->au_buffer.data_size += in->size; + + av_packet_unref(in); + + if (au_end_found) { + uint8_t *data = av_memdup(ctx->au_buffer.data, ctx->au_buffer.data_size); + err = av_packet_from_data(out, data, ctx->au_buffer.data_size); + + ctx->au_buffer.data_size = 0; + } else + err = AVERROR(EAGAIN); + + if (err < 0 && err != AVERROR(EAGAIN)) + evc_frame_merge_flush(bsf); + + return err; +} + +static int evc_frame_merge_init(AVBSFContext *bsf) +{ + EVCFMergeContext *ctx = bsf->priv_data; + + ctx->in = av_packet_alloc(); + if (!ctx->in) + return AVERROR(ENOMEM); + + ctx->au_buffer.capacity = INIT_AU_BUF_CAPACITY; + ctx->au_buffer.data = av_malloc(INIT_AU_BUF_CAPACITY); + ctx->au_buffer.data_size = 0; + + return 0; +} + +static void evc_frame_merge_close(AVBSFContext *bsf) +{ + EVCFMergeContext *ctx = bsf->priv_data; + + av_packet_free(&ctx->in); + + ctx->au_buffer.capacity = 0; + av_freep(&ctx->au_buffer.data); + ctx->au_buffer.data_size = 0; +} + +static const enum AVCodecID evc_frame_merge_codec_ids[] = { + AV_CODEC_ID_EVC, AV_CODEC_ID_NONE, +}; + +const FFBitStreamFilter ff_evc_frame_merge_bsf = { + .p.name = "evc_frame_merge", + .p.codec_ids = evc_frame_merge_codec_ids, + .priv_data_size = sizeof(EVCFMergeContext), + .init = evc_frame_merge_init, + .flush = evc_frame_merge_flush, + .close = evc_frame_merge_close, + .filter = evc_frame_merge_filter, +}; diff --git a/libavformat/Makefile b/libavformat/Makefile index f31135d806b..6e4231fda28 100644 --- a/libavformat/Makefile +++ b/libavformat/Makefile @@ -251,6 +251,7 @@ OBJS-$(CONFIG_HCOM_DEMUXER) += hcom.o pcm.o OBJS-$(CONFIG_HDS_MUXER) += hdsenc.o OBJS-$(CONFIG_HEVC_DEMUXER) += hevcdec.o rawdec.o OBJS-$(CONFIG_HEVC_MUXER) += rawenc.o +OBJS-$(CONFIG_EVC_DEMUXER) += evcdec.o rawdec.o OBJS-$(CONFIG_EVC_MUXER) += rawenc.o OBJS-$(CONFIG_HLS_DEMUXER) += hls.o hls_sample_encryption.o OBJS-$(CONFIG_HLS_MUXER) += hlsenc.o hlsplaylist.o avc.o diff --git a/libavformat/allformats.c b/libavformat/allformats.c index d3871de2681..ae604236aef 100644 --- a/libavformat/allformats.c +++ b/libavformat/allformats.c @@ -154,6 +154,7 @@ extern const AVInputFormat ff_ea_cdata_demuxer; extern const AVInputFormat ff_eac3_demuxer; extern const FFOutputFormat ff_eac3_muxer; extern const AVInputFormat ff_epaf_demuxer; +extern const AVInputFormat ff_evc_demuxer; extern const FFOutputFormat ff_evc_muxer; extern const FFOutputFormat ff_f4v_muxer; extern const AVInputFormat ff_ffmetadata_demuxer; diff --git a/libavformat/evcdec.c b/libavformat/evcdec.c new file mode 100644 index 00000000000..89eda0f53e8 --- /dev/null +++ b/libavformat/evcdec.c @@ -0,0 +1,276 @@ +/* + * RAW EVC video demuxer + * + * Copyright (c) 2021 Dawid Kozinski + * + * 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/get_bits.h" +#include "libavcodec/golomb.h" +#include "libavcodec/internal.h" +#include "libavcodec/evc.h" +#include "libavcodec/bsf.h" + +#include "libavutil/opt.h" + +#include "rawdec.h" +#include "avformat.h" +#include "internal.h" + + +#define RAW_PACKET_SIZE 1024 + +typedef struct EVCParserContext { + int got_sps; + int got_pps; + int got_idr; + int got_nonidr; + +} EVCParserContext; + +typedef struct EVCDemuxContext { + const AVClass *class; + AVRational framerate; + + AVBSFContext *bsf; + +} EVCDemuxContext; + +#define DEC AV_OPT_FLAG_DECODING_PARAM +#define OFFSET(x) offsetof(EVCDemuxContext, x) +static const AVOption evc_options[] = { + { "framerate", "", OFFSET(framerate), AV_OPT_TYPE_VIDEO_RATE, {.str = "25"}, 0, INT_MAX, DEC}, + { NULL }, +}; +#undef OFFSET + +static const AVClass evc_demuxer_class = { + .class_name = "EVC Annex B demuxer", + .item_name = av_default_item_name, + .option = evc_options, + .version = LIBAVUTIL_VERSION_INT, +}; + +static int get_nalu_type(const uint8_t *bits, int bits_size) +{ + int unit_type_plus1 = 0; + + if (bits_size >= EVC_NALU_HEADER_SIZE) { + unsigned char *p = (unsigned char *)bits; + // forbidden_zero_bit + if ((p[0] & 0x80) != 0) // Cannot get bitstream information. Malformed bitstream. + return -1; + + // nal_unit_type + unit_type_plus1 = (p[0] >> 1) & 0x3F; + } + + return unit_type_plus1 - 1; +} + +static uint32_t read_nal_unit_length(const uint8_t *bits, int bits_size) +{ + uint32_t nalu_len = 0; + + if (bits_size >= EVC_NALU_LENGTH_PREFIX_SIZE) { + + int t = 0; + unsigned char *p = (unsigned char *)bits; + + for (int i = 0; i < EVC_NALU_LENGTH_PREFIX_SIZE; i++) + t = (t << 8) | p[i]; + + nalu_len = t; + if (nalu_len == 0) // Invalid bitstream size + return 0; + } + + return nalu_len; +} + +static int parse_nal_units(const AVProbeData *p, EVCParserContext *ev) +{ + int nalu_type; + size_t nalu_size; + unsigned char *bits = (unsigned char *)p->buf; + int bytes_to_read = p->buf_size; + + while (bytes_to_read > EVC_NALU_LENGTH_PREFIX_SIZE) { + + nalu_size = read_nal_unit_length(bits, EVC_NALU_LENGTH_PREFIX_SIZE); + if (nalu_size == 0) break; + + bits += EVC_NALU_LENGTH_PREFIX_SIZE; + bytes_to_read -= EVC_NALU_LENGTH_PREFIX_SIZE; + + if(bytes_to_read < nalu_size) break; + + nalu_type = get_nalu_type(bits, bytes_to_read); + + if (nalu_type == EVC_SPS_NUT) + ev->got_sps++; + else if (nalu_type == EVC_PPS_NUT) + ev->got_pps++; + else if (nalu_type == EVC_IDR_NUT ) + ev->got_idr++; + else if (nalu_type == EVC_NOIDR_NUT) + ev->got_nonidr++; + + bits += nalu_size; + bytes_to_read -= nalu_size; + } + + return 0; +} + +static int annexb_probe(const AVProbeData *p) +{ + EVCParserContext ev = {0}; + int ret = parse_nal_units(p, &ev); + + if (ret == 0 && ev.got_sps && ev.got_pps && (ev.got_idr || ev.got_nonidr > 3)) + return AVPROBE_SCORE_EXTENSION + 1; // 1 more than .mpg + + return 0; +} + +static int evc_read_header(AVFormatContext *s) +{ + AVStream *st; + FFStream *sti; + const AVBitStreamFilter *filter = av_bsf_get_by_name("evc_frame_merge"); + EVCDemuxContext *c = s->priv_data; + int ret = 0; + + st = avformat_new_stream(s, NULL); + if (!st) { + ret = AVERROR(ENOMEM); + goto fail; + } + sti = ffstream(st); + + st->codecpar->codec_type = AVMEDIA_TYPE_VIDEO; + st->codecpar->codec_id = AV_CODEC_ID_EVC; + + // This causes sending to the parser full frames, not chunks of data + // The flag PARSER_FLAG_COMPLETE_FRAMES will be set in demux.c (demux.c: 1316) + sti->need_parsing = AVSTREAM_PARSE_HEADERS; + + st->avg_frame_rate = c->framerate; + st->codecpar->framerate = c->framerate; + + // taken from rawvideo demuxers + avpriv_set_pts_info(st, 64, 1, 1200000); + + ret = av_bsf_alloc(filter, &c->bsf); + if (ret < 0) + return ret; + + ret = avcodec_parameters_copy(c->bsf->par_in, st->codecpar); + if (ret < 0) + return ret; + + ret = av_bsf_init(c->bsf); + if (ret < 0) + return ret; + +fail: + return ret; +} + +static int evc_read_packet(AVFormatContext *s, AVPacket *pkt) +{ + int ret; + int32_t nalu_size; + int au_end_found; + + EVCDemuxContext *const c = s->priv_data; + + int eof = avio_feof (s->pb); + if(eof) { + av_packet_unref(pkt); + return AVERROR_EOF; + } + + au_end_found = 0; + + while(!au_end_found) { + + uint8_t buf[EVC_NALU_LENGTH_PREFIX_SIZE]; + ret = avio_read(s->pb, (unsigned char *)&buf, EVC_NALU_LENGTH_PREFIX_SIZE); + if (ret < 0) { + av_packet_unref(pkt); + return ret; + } + + nalu_size = read_nal_unit_length((const uint8_t *)&buf, EVC_NALU_LENGTH_PREFIX_SIZE); + if(nalu_size <= 0) { + av_packet_unref(pkt); + return -1; + } + + avio_seek(s->pb, -EVC_NALU_LENGTH_PREFIX_SIZE, SEEK_CUR); + + ret = av_get_packet(s->pb, pkt, nalu_size + EVC_NALU_LENGTH_PREFIX_SIZE); + if (ret < 0) + return ret; + if (ret != (nalu_size + EVC_NALU_LENGTH_PREFIX_SIZE)) + return AVERROR(EIO); + + ret = av_bsf_send_packet(c->bsf, pkt); + if (ret < 0) { + av_log(s, AV_LOG_ERROR, "Failed to send packet to " + "evc_frame_merge filter\n"); + return ret; + } + + ret = av_bsf_receive_packet(c->bsf, pkt); + if (ret < 0 && ret != AVERROR(EAGAIN) && ret != AVERROR_EOF) + av_log(s, AV_LOG_ERROR, "evc_frame_merge filter failed to " + "send output packet\n"); + + au_end_found = 1; + if (ret == AVERROR(EAGAIN)) + au_end_found = 0; + } + + return ret; +} + +static int evc_read_close(AVFormatContext *s) +{ + EVCDemuxContext *const c = s->priv_data; + + av_bsf_free(&c->bsf); + return 0; +} + +const AVInputFormat ff_evc_demuxer = { + .name = "evc", + .long_name = NULL_IF_CONFIG_SMALL("EVC Annex B"), + .read_probe = annexb_probe, + .read_header = evc_read_header, // annexb_read_header + .read_packet = evc_read_packet, // annexb_read_packet + .read_close = evc_read_close, + .extensions = "evc", + .flags = AVFMT_GENERIC_INDEX, + .flags_internal = FF_FMT_INIT_CLEANUP, + .raw_codec_id = AV_CODEC_ID_EVC, + .priv_data_size = sizeof(EVCDemuxContext), + .priv_class = &evc_demuxer_class, +}; From a04ca05f4c62b219f643cb769d839a6737cd5c84 Mon Sep 17 00:00:00 2001 From: Dawid Kozinski Date: Thu, 15 Jun 2023 13:48:34 +0200 Subject: [PATCH 1473/2172] avformat/mov_muxer: Extended MOV muxer to handle EVC video content - Changes in mov_write_video_tag function to handle EVC elementary stream - Provided structure EVCDecoderConfigurationRecord that specifies the decoder configuration information for ISO/IEC 23094-1 video content Signed-off-by: Dawid Kozinski --- libavformat/Makefile | 2 +- libavformat/evc.c | 422 ++++++++++++++++++++++++++++++++++++++++ libavformat/evc.h | 44 +++++ libavformat/isom_tags.c | 2 + libavformat/movenc.c | 33 ++++ 5 files changed, 502 insertions(+), 1 deletion(-) create mode 100644 libavformat/evc.c create mode 100644 libavformat/evc.h diff --git a/libavformat/Makefile b/libavformat/Makefile index 6e4231fda28..d3503196e33 100644 --- a/libavformat/Makefile +++ b/libavformat/Makefile @@ -364,7 +364,7 @@ OBJS-$(CONFIG_MOV_DEMUXER) += mov.o mov_chan.o mov_esds.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 \ - dovi_isom.o + dovi_isom.o evc.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/evc.c b/libavformat/evc.c new file mode 100644 index 00000000000..dc75ccb56da --- /dev/null +++ b/libavformat/evc.c @@ -0,0 +1,422 @@ +/* + * EVC helper functions for muxers + * Copyright (c) 2022 Dawid Kozinski + * + * 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/intreadwrite.h" +#include "libavcodec/get_bits.h" +#include "libavcodec/golomb.h" +#include "libavcodec/evc.h" +#include "libavcodec/evc_parse.h" +#include "avformat.h" +#include "avio.h" +#include "evc.h" +#include "avio_internal.h" + +// The length field that indicates the length in bytes of the following NAL unit is configured to be of 4 bytes +#define EVC_NALU_LENGTH_PREFIX_SIZE (4) /* byte */ +#define EVC_NALU_HEADER_SIZE (2) /* byte */ + +// @see ISO/IEC 14496-15:2021 Coding of audio-visual objects - Part 15: section 12.3.3.1 +enum { + SPS_INDEX, + PPS_INDEX, + APS_INDEX, + SEI_INDEX, + NB_ARRAYS +}; + +// The sturcture reflects SPS RBSP(raw byte sequence payload) layout +// @see ISO_IEC_23094-1 section 7.3.2.1 +// +// The following descriptors specify the parsing process of each element +// u(n) - unsigned integer using n bits +// ue(v) - unsigned integer 0-th order Exp_Golomb-coded syntax element with the left bit first +typedef struct EVCSPS { + int sps_seq_parameter_set_id; // ue(v) + int profile_idc; // u(8) + int level_idc; // u(8) + int toolset_idc_h; // u(32) + int toolset_idc_l; // u(32) + int chroma_format_idc; // ue(v) + int pic_width_in_luma_samples; // ue(v) + int pic_height_in_luma_samples; // ue(v) + int bit_depth_luma_minus8; // ue(v) + int bit_depth_chroma_minus8; // ue(v) + + // @note + // Currently the structure does not reflect the entire SPS RBSP layout. + // It contains only the fields that are necessary to read from the NAL unit all the values + // necessary for the correct initialization of EVCDecoderConfigurationRecord + + // @note + // If necessary, add the missing fields to the structure to reflect + // the contents of the entire NAL unit of the SPS type + +} EVCSPS; + +// @see ISO/IEC 14496-15:2021 Coding of audio-visual objects - Part 15: section 12.3.3.3 +typedef struct EVCNALUnitArray { + uint8_t array_completeness; // when equal to 1 indicates that all NAL units of the given type are in the following array + uint8_t NAL_unit_type; // indicates the type of the NAL units in the following array + uint16_t numNalus; // indicates the number of NAL units of the indicated type + uint16_t *nalUnitLength; // indicates the length in bytes of the NAL unit + uint8_t **nalUnit; // contains an SPS, PPS, APS or a SEI NAL unit, as specified in ISO/IEC 23094-1 +} EVCNALUnitArray; + +/** + * @brief Specifies the decoder configuration information for ISO/IEC 23094-1 video content. + * @see ISO/IEC 14496-15:2021 Coding of audio-visual objects - Part 15: section 12.3.3.2 + * Carriage of network abstraction layer (NAL) unit structured video in the ISO base media file format + */ +typedef struct EVCDecoderConfigurationRecord { + uint8_t configurationVersion; // 8 bits + uint8_t profile_idc; // 8 bits + uint8_t level_idc; // 8 bits + uint32_t toolset_idc_h; // 32 bits + uint32_t toolset_idc_l; // 32 bits + uint8_t chroma_format_idc; // 2 bits + uint8_t bit_depth_luma_minus8; // 3 bits + uint8_t bit_depth_chroma_minus8; // 3 bits + uint16_t pic_width_in_luma_samples; // 16 bits + uint16_t pic_height_in_luma_samples; // 16 bits + uint8_t reserved; // 6 bits '000000'b + uint8_t lengthSizeMinusOne; // 2 bits + uint8_t num_of_arrays; // 8 bits + EVCNALUnitArray arrays[NB_ARRAYS]; +} EVCDecoderConfigurationRecord; + +typedef struct NALU { + int offset; + uint32_t size; +} NALU; + +typedef struct NALUList { + NALU *nalus; + unsigned nalus_array_size; + unsigned nb_nalus; ///< valid entries in nalus +} NALUList; + +// @see ISO_IEC_23094-1 (7.3.2.1 SPS RBSP syntax) +static int evcc_parse_sps(const uint8_t *bs, int bs_size, EVCDecoderConfigurationRecord *evcc) +{ + GetBitContext gb; + int sps_seq_parameter_set_id; + EVCSPS sps; + + if (init_get_bits8(&gb, bs, bs_size) < 0) + return 0; + + sps.sps_seq_parameter_set_id = get_ue_golomb(&gb); + + if (sps_seq_parameter_set_id >= EVC_MAX_SPS_COUNT) + return 0; + + // the Baseline profile is indicated by profile_idc eqal to 0 + // the Main profile is indicated by profile_idc eqal to 1 + sps.profile_idc = get_bits(&gb, 8); + + sps.level_idc = get_bits(&gb, 8); + + sps.toolset_idc_h = get_bits(&gb, 32); + sps.toolset_idc_l = get_bits(&gb, 32); + + // 0 - monochrome + // 1 - 4:2:0 + // 2 - 4:2:2 + // 3 - 4:4:4 + sps.chroma_format_idc = get_ue_golomb(&gb); + + sps.pic_width_in_luma_samples = get_ue_golomb(&gb); + sps.pic_height_in_luma_samples = get_ue_golomb(&gb); + + sps.bit_depth_luma_minus8 = get_ue_golomb(&gb); + sps.bit_depth_chroma_minus8 = get_ue_golomb(&gb); + + evcc->profile_idc = sps.profile_idc; + evcc->level_idc = sps.level_idc; + evcc->toolset_idc_h = sps.toolset_idc_h; + evcc->toolset_idc_l = sps.toolset_idc_l; + evcc->chroma_format_idc = sps.chroma_format_idc; + evcc->bit_depth_luma_minus8 = sps.bit_depth_luma_minus8; + evcc->bit_depth_chroma_minus8 = sps.bit_depth_chroma_minus8; + evcc->pic_width_in_luma_samples = sps.pic_width_in_luma_samples; + evcc->pic_height_in_luma_samples = sps.pic_height_in_luma_samples; + + return 0; +} + +// @see ISO/IEC 14496-15:2021 Coding of audio-visual objects - Part 15: section 12.3.3.3 +static int evcc_array_add_nal_unit(const uint8_t *nal_buf, uint32_t nal_size, + uint8_t nal_type, int ps_array_completeness, + EVCNALUnitArray *array) +{ + int ret; + uint16_t numNalus = array->numNalus; + + ret = av_reallocp_array(&array->nalUnit, numNalus + 1, sizeof(uint8_t *)); + if (ret < 0) + return ret; + + ret = av_reallocp_array(&array->nalUnitLength, numNalus + 1, sizeof(uint16_t)); + if (ret < 0) + return ret; + + array->nalUnit [numNalus] = (uint8_t *)nal_buf; + array->nalUnitLength[numNalus] = nal_size; + array->NAL_unit_type = nal_type; + array->numNalus++; + + /* + * When the sample entry name is 'evc1', the default and mandatory value of + * array_completeness is 1 for arrays of all types of parameter sets, and 0 + * for all other arrays. + */ + if (nal_type == EVC_SPS_NUT || nal_type == EVC_PPS_NUT || nal_type == EVC_APS_NUT) + array->array_completeness = ps_array_completeness; + + return 0; +} + +static void evcc_init(EVCDecoderConfigurationRecord *evcc) +{ + memset(evcc, 0, sizeof(EVCDecoderConfigurationRecord)); + evcc->configurationVersion = 1; + evcc->lengthSizeMinusOne = 3; // 4 bytes +} + +static void evcc_close(EVCDecoderConfigurationRecord *evcc) +{ + for (unsigned i = 0; i < FF_ARRAY_ELEMS(evcc->arrays); i++) { + EVCNALUnitArray *const array = &evcc->arrays[i]; + array->numNalus = 0; + av_freep(&array->nalUnit); + av_freep(&array->nalUnitLength); + } +} + +static int evcc_write(AVIOContext *pb, EVCDecoderConfigurationRecord *evcc) +{ + uint16_t sps_count; + + av_log(NULL, AV_LOG_TRACE, "configurationVersion: %"PRIu8"\n", + evcc->configurationVersion); + av_log(NULL, AV_LOG_TRACE, "profile_idc: %"PRIu8"\n", + evcc->profile_idc); + av_log(NULL, AV_LOG_TRACE, "level_idc: %"PRIu8"\n", + evcc->level_idc); + av_log(NULL, AV_LOG_TRACE, "toolset_idc_h: %"PRIu32"\n", + evcc->toolset_idc_h); + av_log(NULL, AV_LOG_TRACE, "toolset_idc_l: %"PRIu32"\n", + evcc->toolset_idc_l); + av_log(NULL, AV_LOG_TRACE, "chroma_format_idc: %"PRIu8"\n", + evcc->chroma_format_idc); + av_log(NULL, AV_LOG_TRACE, "bit_depth_luma_minus8: %"PRIu8"\n", + evcc->bit_depth_luma_minus8); + av_log(NULL, AV_LOG_TRACE, "bit_depth_chroma_minus8: %"PRIu8"\n", + evcc->bit_depth_chroma_minus8); + av_log(NULL, AV_LOG_TRACE, "pic_width_in_luma_samples: %"PRIu16"\n", + evcc->pic_width_in_luma_samples); + av_log(NULL, AV_LOG_TRACE, "pic_height_in_luma_samples: %"PRIu16"\n", + evcc->pic_height_in_luma_samples); + av_log(NULL, AV_LOG_TRACE, "lengthSizeMinusOne: %"PRIu8"\n", + evcc->lengthSizeMinusOne); + av_log(NULL, AV_LOG_TRACE, "num_of_arrays: %"PRIu8"\n", + evcc->num_of_arrays); + for (unsigned i = 0; i < FF_ARRAY_ELEMS(evcc->arrays); i++) { + const EVCNALUnitArray *const array = &evcc->arrays[i]; + + if(array->numNalus == 0) + continue; + + av_log(NULL, AV_LOG_TRACE, "array_completeness[%"PRIu8"]: %"PRIu8"\n", + i, array->array_completeness); + av_log(NULL, AV_LOG_TRACE, "NAL_unit_type[%"PRIu8"]: %"PRIu8"\n", + i, array->NAL_unit_type); + av_log(NULL, AV_LOG_TRACE, "numNalus[%"PRIu8"]: %"PRIu16"\n", + i, array->numNalus); + for ( unsigned j = 0; j < array->numNalus; j++) + av_log(NULL, AV_LOG_TRACE, + "nalUnitLength[%"PRIu8"][%"PRIu16"]: %"PRIu16"\n", + i, j, array->nalUnitLength[j]); + } + + /* + * We need at least one SPS. + */ + sps_count = evcc->arrays[SPS_INDEX].numNalus; + if (!sps_count || sps_count > EVC_MAX_SPS_COUNT) + return AVERROR_INVALIDDATA; + + if (!sps_count || sps_count > EVC_MAX_SPS_COUNT) + return AVERROR_INVALIDDATA; + + /* unsigned int(8) configurationVersion = 1; */ + avio_w8(pb, evcc->configurationVersion); + + /* unsigned int(8) profile_idc */ + avio_w8(pb, evcc->profile_idc); + + /* unsigned int(8) profile_idc */ + avio_w8(pb, evcc->level_idc); + + /* unsigned int(32) toolset_idc_h */ + avio_wb32(pb, evcc->toolset_idc_h); + + /* unsigned int(32) toolset_idc_l */ + avio_wb32(pb, evcc->toolset_idc_l); + + /* + * unsigned int(2) chroma_format_idc; + * unsigned int(3) bit_depth_luma_minus8; + * unsigned int(3) bit_depth_chroma_minus8; + */ + avio_w8(pb, evcc->chroma_format_idc << 6 | + evcc->bit_depth_luma_minus8 << 3 | + evcc->bit_depth_chroma_minus8); + + /* unsigned int(16) pic_width_in_luma_samples; */ + avio_wb16(pb, evcc->pic_width_in_luma_samples); + + /* unsigned int(16) pic_width_in_luma_samples; */ + avio_wb16(pb, evcc->pic_height_in_luma_samples); + + /* + * bit(6) reserved = '111111'b; + * unsigned int(2) chromaFormat; + */ + avio_w8(pb, evcc->lengthSizeMinusOne | 0xfc); + + /* unsigned int(8) numOfArrays; */ + avio_w8(pb, evcc->num_of_arrays); + + for (unsigned i = 0; i < FF_ARRAY_ELEMS(evcc->arrays); i++) { + const EVCNALUnitArray *const array = &evcc->arrays[i]; + + if (!array->numNalus) + continue; + + /* + * bit(1) array_completeness; + * unsigned int(1) reserved = 0; + * unsigned int(6) NAL_unit_type; + */ + avio_w8(pb, array->array_completeness << 7 | + array->NAL_unit_type & 0x3f); + + /* unsigned int(16) numNalus; */ + avio_wb16(pb, array->numNalus); + + for (unsigned j = 0; j < array->numNalus; j++) { + /* unsigned int(16) nalUnitLength; */ + avio_wb16(pb, array->nalUnitLength[j]); + + /* bit(8*nalUnitLength) nalUnit; */ + avio_write(pb, array->nalUnit[j], + array->nalUnitLength[j]); + } + } + + return 0; +} + +int ff_isom_write_evcc(AVIOContext *pb, const uint8_t *data, + int size, int ps_array_completeness) +{ + EVCDecoderConfigurationRecord evcc; + int nalu_type; + size_t nalu_size; + int bytes_to_read = size; + unsigned array_index; + + int ret = 0; + + if (size < 8) { + /* We can't write a valid evcC from the provided data */ + return AVERROR_INVALIDDATA; + } else if (*data == 1) { + /* Data is already evcC-formatted */ + avio_write(pb, data, size); + return 0; + } + + evcc_init(&evcc); + + while (bytes_to_read > EVC_NALU_LENGTH_PREFIX_SIZE) { + nalu_size = evc_read_nal_unit_length(data, EVC_NALU_LENGTH_PREFIX_SIZE, pb); + if (nalu_size == 0) break; + + data += EVC_NALU_LENGTH_PREFIX_SIZE; + bytes_to_read -= EVC_NALU_LENGTH_PREFIX_SIZE; + + if (bytes_to_read < nalu_size) break; + + nalu_type = evc_get_nalu_type(data, bytes_to_read, pb); + + // @see ISO/IEC 14496-15:2021 Coding of audio-visual objects - Part 15: section 12.3.3.3 + // NAL_unit_type indicates the type of the NAL units in the following array (which shall be all of that type); + // - it takes a value as defined in ISO/IEC 23094-1; + // - it is restricted to take one of the values indicating a SPS, PPS, APS, or SEI NAL unit. + switch (nalu_type) { + case EVC_SPS_NUT: + array_index = SPS_INDEX; + break; + case EVC_PPS_NUT: + array_index = PPS_INDEX; + break; + case EVC_APS_NUT: + array_index = APS_INDEX; + break; + case EVC_SEI_NUT: + array_index = SEI_INDEX; + break; + default: + array_index = -1; + break; + } + + if( (array_index == SPS_INDEX) || + (array_index == PPS_INDEX) || + (array_index == APS_INDEX) || + (array_index == SEI_INDEX) ) { + + ret = evcc_array_add_nal_unit(data, nalu_size, nalu_type, ps_array_completeness, &(evcc.arrays[array_index])); + + if (ret < 0) + goto end; + if (evcc.arrays[array_index].numNalus == 1) + evcc.num_of_arrays++; + + if(nalu_type == EVC_SPS_NUT) { + ret = evcc_parse_sps(data, nalu_size, &evcc); + if (ret < 0) + goto end; + } + } + + data += nalu_size; + bytes_to_read -= nalu_size; + } + + ret = evcc_write(pb, &evcc); + +end: + evcc_close(&evcc); + return ret; +} diff --git a/libavformat/evc.h b/libavformat/evc.h new file mode 100644 index 00000000000..db56275fd85 --- /dev/null +++ b/libavformat/evc.h @@ -0,0 +1,44 @@ +/* + * EVC helper functions for muxers + * Copyright (c) 2022 Dawid Kozinski + * + * 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_EVC_H +#define AVFORMAT_EVC_H + +#include +#include "libavutil/rational.h" +#include "avio.h" + + + +/** + * Writes EVC sample metadata to the provided AVIOContext. + * + * @param pb pointer to the AVIOContext where the evc sample metadata shall be written + * @param buf input data buffer + * @param size size in bytes of the input data buffer + * @param ps_array_completeness @see ISO/IEC 14496-15:2021 Coding of audio-visual objects - Part 15: section 12.3.3.3 + * + * @return 0 in case of success, a negative error code in case of failure + */ +int ff_isom_write_evcc(AVIOContext *pb, const uint8_t *data, + int size, int ps_array_completeness); + +#endif // AVFORMAT_EVC_H diff --git a/libavformat/isom_tags.c b/libavformat/isom_tags.c index 86c72725256..2a29823b2ee 100644 --- a/libavformat/isom_tags.c +++ b/libavformat/isom_tags.c @@ -147,6 +147,8 @@ const AVCodecTag ff_codec_movvideo_tags[] = { { AV_CODEC_ID_H264, MKTAG('d', 'v', 'a', '1') }, /* AVC-based Dolby Vision derived from avc1 */ { AV_CODEC_ID_H264, MKTAG('d', 'v', 'a', 'v') }, /* AVC-based Dolby Vision derived from avc3 */ + { AV_CODEC_ID_EVC, MKTAG('e', 'v', 'c', '1') }, /* EVC/MPEG-5 */ + { AV_CODEC_ID_VP8, MKTAG('v', 'p', '0', '8') }, /* VP8 */ { AV_CODEC_ID_VP9, MKTAG('v', 'p', '0', '9') }, /* VP9 */ { AV_CODEC_ID_AV1, MKTAG('a', 'v', '0', '1') }, /* AV1 */ diff --git a/libavformat/movenc.c b/libavformat/movenc.c index a9c8e104f0d..f1cc80b1b3c 100644 --- a/libavformat/movenc.c +++ b/libavformat/movenc.c @@ -35,6 +35,7 @@ #include "isom.h" #include "av1.h" #include "avc.h" +#include "evc.h" #include "libavcodec/ac3_parser_internal.h" #include "libavcodec/dnxhddata.h" #include "libavcodec/flac.h" @@ -1455,6 +1456,21 @@ static int mov_write_hvcc_tag(AVIOContext *pb, MOVTrack *track) return update_size(pb, pos); } +static int mov_write_evcc_tag(AVIOContext *pb, MOVTrack *track) +{ + int64_t pos = avio_tell(pb); + + avio_wb32(pb, 0); + ffio_wfourcc(pb, "evcC"); + + if (track->tag == MKTAG('e','v','c','1')) + ff_isom_write_evcc(pb, track->vos_data, track->vos_len, 1); + else + ff_isom_write_evcc(pb, track->vos_data, track->vos_len, 0); + + return update_size(pb, pos); +} + /* also used by all avid codecs (dv, imx, meridien) and their variants */ static int mov_write_avid_tag(AVIOContext *pb, MOVTrack *track) { @@ -1704,6 +1720,16 @@ static int mov_get_h264_codec_tag(AVFormatContext *s, MOVTrack *track) return tag; } +static int mov_get_evc_codec_tag(AVFormatContext *s, MOVTrack *track) +{ + int tag = track->par->codec_tag; + + if (!tag) + tag = MKTAG('e', 'v', 'c', '1'); + + return tag; +} + static const struct { enum AVPixelFormat pix_fmt; uint32_t tag; @@ -1785,6 +1811,8 @@ static unsigned int mov_get_codec_tag(AVFormatContext *s, MOVTrack *track) tag = mov_get_mpeg2_xdcam_codec_tag(s, track); else if (track->par->codec_id == AV_CODEC_ID_H264) tag = mov_get_h264_codec_tag(s, track); + else if (track->par->codec_id == AV_CODEC_ID_EVC) + tag = mov_get_evc_codec_tag(s, track); else if (track->par->codec_id == AV_CODEC_ID_DNXHD) tag = mov_get_dnxhd_codec_tag(s, track); else if (track->par->codec_type == AVMEDIA_TYPE_VIDEO) { @@ -2352,6 +2380,9 @@ static int mov_write_video_tag(AVFormatContext *s, AVIOContext *pb, MOVMuxContex mov_write_avcc_tag(pb, track); if (track->mode == MODE_IPOD) mov_write_uuid_tag_ipod(pb); + } + else if (track->par->codec_id ==AV_CODEC_ID_EVC) { + mov_write_evcc_tag(pb, track); } else if (track->par->codec_id == AV_CODEC_ID_VP9) { mov_write_vpcc_tag(mov->fc, pb, track); } else if (track->par->codec_id == AV_CODEC_ID_AV1) { @@ -6126,6 +6157,7 @@ int ff_mov_write_packet(AVFormatContext *s, AVPacket *pkt) par->codec_id == AV_CODEC_ID_H264 || par->codec_id == AV_CODEC_ID_HEVC || par->codec_id == AV_CODEC_ID_VP9 || + par->codec_id == AV_CODEC_ID_EVC || par->codec_id == AV_CODEC_ID_TRUEHD) && !trk->vos_len && !TAG_IS_AVCI(trk->tag)) { /* copy frame to create needed atoms */ @@ -7785,6 +7817,7 @@ static const AVCodecTag codec_mp4_tags[] = { { AV_CODEC_ID_H264, MKTAG('a', 'v', 'c', '3') }, { AV_CODEC_ID_HEVC, MKTAG('h', 'e', 'v', '1') }, { AV_CODEC_ID_HEVC, MKTAG('h', 'v', 'c', '1') }, + { AV_CODEC_ID_EVC, MKTAG('e', 'v', 'c', '1') }, { AV_CODEC_ID_MPEG2VIDEO, MKTAG('m', 'p', '4', 'v') }, { AV_CODEC_ID_MPEG1VIDEO, MKTAG('m', 'p', '4', 'v') }, { AV_CODEC_ID_MJPEG, MKTAG('m', 'p', '4', 'v') }, From 091705cd55afe08f0c85d673dc924856fef9ae6e Mon Sep 17 00:00:00 2001 From: Dawid Kozinski Date: Thu, 15 Jun 2023 13:48:59 +0200 Subject: [PATCH 1474/2172] avformat/mov_demuxer: Extended MOV demuxer to handle EVC video content - Added evc extension to the list of extensions for ff_mov_demuxer Signed-off-by: Dawid Kozinski --- libavformat/demux.c | 1 + libavformat/mov.c | 2 ++ 2 files changed, 3 insertions(+) diff --git a/libavformat/demux.c b/libavformat/demux.c index b3f563ccc77..1b21b8440c5 100644 --- a/libavformat/demux.c +++ b/libavformat/demux.c @@ -120,6 +120,7 @@ static int set_codec_from_probe_data(AVFormatContext *s, AVStream *st, { "mp3", AV_CODEC_ID_MP3, AVMEDIA_TYPE_AUDIO }, { "mpegvideo", AV_CODEC_ID_MPEG2VIDEO, AVMEDIA_TYPE_VIDEO }, { "truehd", AV_CODEC_ID_TRUEHD, AVMEDIA_TYPE_AUDIO }, + { "evc", AV_CODEC_ID_EVC, AVMEDIA_TYPE_VIDEO }, { 0 } }; int score; diff --git a/libavformat/mov.c b/libavformat/mov.c index a8d004e02ba..278dec67652 100644 --- a/libavformat/mov.c +++ b/libavformat/mov.c @@ -2646,6 +2646,7 @@ static int mov_finalize_stsd_codec(MOVContext *c, AVIOContext *pb, case AV_CODEC_ID_VP9: sti->need_parsing = AVSTREAM_PARSE_FULL; break; + case AV_CODEC_ID_EVC: case AV_CODEC_ID_AV1: /* field_order detection of H264 requires parsing */ case AV_CODEC_ID_H264: @@ -7932,6 +7933,7 @@ static const MOVParseTableEntry mov_default_parse_table[] = { { MKTAG('i','l','o','c'), mov_read_iloc }, { MKTAG('p','c','m','C'), mov_read_pcmc }, /* PCM configuration box */ { MKTAG('p','i','t','m'), mov_read_pitm }, +{ MKTAG('e','v','c','C'), mov_read_glbl }, { 0, NULL } }; From 7b15f1780f6e4b70bdb774af721ba0ad7a5cf6c3 Mon Sep 17 00:00:00 2001 From: Dawid Kozinski Date: Thu, 15 Jun 2023 13:49:17 +0200 Subject: [PATCH 1475/2172] avcodec/evc: Changes in Changelog file - Changelog update Signed-off-by: Dawid Kozinski --- Changelog | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Changelog b/Changelog index cd872d9bf28..ac3247982be 100644 --- a/Changelog +++ b/Changelog @@ -17,6 +17,8 @@ version : - RivaTuner video decoder - xfade_vulkan filter - vMix video decoder +- Essential Video Coding parser, muxer and demuxer +- Essential Video Coding frame merge bsf version 6.0: - Radiance HDR image support From 29976915587f0fc93625c5743dbe9a31d50af5bb Mon Sep 17 00:00:00 2001 From: Dawid Kozinski Date: Thu, 15 Jun 2023 13:49:34 +0200 Subject: [PATCH 1476/2172] avcodec/evc: Changes in MAINTAINERS file - MAINTAINERS update Signed-off-by: Dawid Kozinski --- MAINTAINERS | 1 + 1 file changed, 1 insertion(+) diff --git a/MAINTAINERS b/MAINTAINERS index 07852486e44..f6a0f9bcb5b 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -417,6 +417,7 @@ Muxers/Demuxers: dv.c Roman Shaposhnik electronicarts.c Peter Ross epafdec.c Paul B Mahol + evc* Samsung (Dawid Kozinski) ffm* Baptiste Coudurier flic.c Mike Melanson flvdec.c Michael Niedermayer From 77c5c743753b064d236a8924b309547a3b7babc2 Mon Sep 17 00:00:00 2001 From: James Almer Date: Thu, 15 Jun 2023 11:44:04 -0300 Subject: [PATCH 1477/2172] avcodec/version: bump minor after evc parser and frame_merge bsf additions Signed-off-by: James Almer --- libavcodec/version.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavcodec/version.h b/libavcodec/version.h index 65bc52fb24b..4b7ec515fe8 100644 --- a/libavcodec/version.h +++ b/libavcodec/version.h @@ -29,7 +29,7 @@ #include "version_major.h" -#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, \ From 81b4e4abb01b8e6ef27af35f7d66e0535fb7746d Mon Sep 17 00:00:00 2001 From: James Almer Date: Thu, 15 Jun 2023 11:44:37 -0300 Subject: [PATCH 1478/2172] avformt/version: bump minor after evc muxer and demuxer additions Signed-off-by: James Almer --- libavformat/version.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavformat/version.h b/libavformat/version.h index 4bde82abb44..70c554c19c4 100644 --- a/libavformat/version.h +++ b/libavformat/version.h @@ -31,7 +31,7 @@ #include "version_major.h" -#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, \ From 21f6496ccebf3c441affc9ed3f711e9964e81359 Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Thu, 15 Jun 2023 18:01:32 +0200 Subject: [PATCH 1479/2172] avcodec/bink: make two tables use uint8_t type --- libavcodec/bink.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libavcodec/bink.c b/libavcodec/bink.c index 15fc9d29ed8..e3822d689c0 100644 --- a/libavcodec/bink.c +++ b/libavcodec/bink.c @@ -59,11 +59,11 @@ enum OldSources { BINKB_NB_SRC }; -static const int binkb_bundle_sizes[BINKB_NB_SRC] = { +static const uint8_t binkb_bundle_sizes[BINKB_NB_SRC] = { 4, 8, 8, 5, 5, 11, 11, 4, 4, 7 }; -static const int binkb_bundle_signed[BINKB_NB_SRC] = { +static const uint8_t binkb_bundle_signed[BINKB_NB_SRC] = { 0, 0, 0, 1, 1, 0, 1, 0, 0, 0 }; From ecc3f158e130481a1e98d99e023d304c5796b2a7 Mon Sep 17 00:00:00 2001 From: Philip Langdale Date: Wed, 14 Jun 2023 19:59:09 -0700 Subject: [PATCH 1480/2172] avfilter/vf_yadif_cuda: remove unnecessary private struct fields I'm not sure why I originally did this, but there's no good reason to put pointers to the cuda context and stream in the priv struct. They are directly available in the device context that is already being stored there. --- libavfilter/vf_yadif_cuda.c | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/libavfilter/vf_yadif_cuda.c b/libavfilter/vf_yadif_cuda.c index b5ff84e11a8..d777757e656 100644 --- a/libavfilter/vf_yadif_cuda.c +++ b/libavfilter/vf_yadif_cuda.c @@ -38,8 +38,6 @@ typedef struct DeintCUDAContext { AVBufferRef *input_frames_ref; AVHWFramesContext *input_frames; - CUcontext cu_ctx; - CUstream stream; CUmodule cu_module; CUfunction cu_func_uchar; CUfunction cu_func_uchar2; @@ -109,7 +107,7 @@ static CUresult call_kernel(AVFilterContext *ctx, CUfunction func, ret = CHECK_CU(cu->cuLaunchKernel(func, DIV_UP(dst_width, BLOCKX), DIV_UP(dst_height, BLOCKY), 1, BLOCKX, BLOCKY, 1, - 0, s->stream, args, NULL)); + 0, s->hwctx->stream, args, NULL)); exit: if (tex_prev) @@ -131,7 +129,7 @@ static void filter(AVFilterContext *ctx, AVFrame *dst, CUcontext dummy; int i, ret; - ret = CHECK_CU(cu->cuCtxPushCurrent(s->cu_ctx)); + ret = CHECK_CU(cu->cuCtxPushCurrent(s->hwctx->cuda_ctx)); if (ret < 0) return; @@ -197,7 +195,7 @@ static av_cold void deint_cuda_uninit(AVFilterContext *ctx) if (s->hwctx && s->cu_module) { CudaFunctions *cu = s->hwctx->internal->cuda_dl; - CHECK_CU(cu->cuCtxPushCurrent(s->cu_ctx)); + CHECK_CU(cu->cuCtxPushCurrent(s->hwctx->cuda_ctx)); CHECK_CU(cu->cuModuleUnload(s->cu_module)); CHECK_CU(cu->cuCtxPopCurrent(&dummy)); } @@ -253,8 +251,6 @@ static int config_output(AVFilterLink *link) return AVERROR(ENOMEM); } s->hwctx = ((AVHWDeviceContext*)s->device_ref->data)->hwctx; - s->cu_ctx = s->hwctx->cuda_ctx; - s->stream = s->hwctx->stream; cu = s->hwctx->internal->cuda_dl; link->hw_frames_ctx = av_hwframe_ctx_alloc(s->device_ref); @@ -310,7 +306,7 @@ static int config_output(AVFilterLink *link) y->csp = av_pix_fmt_desc_get(output_frames->sw_format); y->filter = filter; - ret = CHECK_CU(cu->cuCtxPushCurrent(s->cu_ctx)); + ret = CHECK_CU(cu->cuCtxPushCurrent(s->hwctx->cuda_ctx)); if (ret < 0) goto exit; From 41be6a5593ab498f8069f0dd11e7d7cebb1f6811 Mon Sep 17 00:00:00 2001 From: Philip Langdale Date: Wed, 28 Sep 2022 19:25:18 -0700 Subject: [PATCH 1481/2172] lavu/hwcontext_cuda: declare support for rgb32/bgr32 nvenc declares support for these formats, but if hwcontext_cuda doesn't do that as well, then it's not possible to hwupload them for use in a possible cuda pipeline before encoding. --- libavutil/hwcontext_cuda.c | 2 ++ libavutil/version.h | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/libavutil/hwcontext_cuda.c b/libavutil/hwcontext_cuda.c index 5ae7711c942..4b298fa93ea 100644 --- a/libavutil/hwcontext_cuda.c +++ b/libavutil/hwcontext_cuda.c @@ -45,6 +45,8 @@ static const enum AVPixelFormat supported_formats[] = { AV_PIX_FMT_YUV444P16, AV_PIX_FMT_0RGB32, AV_PIX_FMT_0BGR32, + AV_PIX_FMT_RGB32, + AV_PIX_FMT_BGR32, #if CONFIG_VULKAN AV_PIX_FMT_VULKAN, #endif diff --git a/libavutil/version.h b/libavutil/version.h index dbdf0bd64ad..17a6d296a61 100644 --- a/libavutil/version.h +++ b/libavutil/version.h @@ -80,7 +80,7 @@ #define LIBAVUTIL_VERSION_MAJOR 58 #define LIBAVUTIL_VERSION_MINOR 13 -#define LIBAVUTIL_VERSION_MICRO 100 +#define LIBAVUTIL_VERSION_MICRO 101 #define LIBAVUTIL_VERSION_INT AV_VERSION_INT(LIBAVUTIL_VERSION_MAJOR, \ LIBAVUTIL_VERSION_MINOR, \ From f30b979ca20fa9589872328dbae05cb1dc7c64fd Mon Sep 17 00:00:00 2001 From: Lynne Date: Tue, 13 Jun 2023 04:04:28 +0200 Subject: [PATCH 1482/2172] pthread_frame: uninit the hwaccel of each frame thread The issue is that with a threadsafe hwaccel and multiple enabled frame threads, hwaccel->uninit() is never called. Previously, the function was guaranteed to never have any threads with hwaccel contexts, so it never bothered to uninit any. --- libavcodec/pthread_frame.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/libavcodec/pthread_frame.c b/libavcodec/pthread_frame.c index 28335231fd7..008f3da43b2 100644 --- a/libavcodec/pthread_frame.c +++ b/libavcodec/pthread_frame.c @@ -751,6 +751,10 @@ void ff_frame_thread_free(AVCodecContext *avctx, int thread_count) if (codec->close && p->thread_init != UNINITIALIZED) codec->close(ctx); + /* When using a threadsafe hwaccel, this is where + * each thread's context is uninit'd and freed. */ + ff_hwaccel_uninit(ctx); + if (ctx->priv_data) { if (codec->p.priv_class) av_opt_free(ctx->priv_data); From b4d5baa8b05974a406615925f379b56fa1c850a6 Mon Sep 17 00:00:00 2001 From: Lynne Date: Tue, 13 Jun 2023 04:35:29 +0200 Subject: [PATCH 1483/2172] hwcontext_vulkan: call ff_vk_uninit() on device uninit This fixes three memory leaks from ff_vk_load_props(). --- libavutil/hwcontext_vulkan.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/libavutil/hwcontext_vulkan.c b/libavutil/hwcontext_vulkan.c index 1132a61390e..c86229ba658 100644 --- a/libavutil/hwcontext_vulkan.c +++ b/libavutil/hwcontext_vulkan.c @@ -1176,6 +1176,8 @@ static void vulkan_device_free(AVHWDeviceContext *ctx) RELEASE_PROPS(hwctx->enabled_inst_extensions, hwctx->nb_enabled_inst_extensions); RELEASE_PROPS(hwctx->enabled_dev_extensions, hwctx->nb_enabled_dev_extensions); + + ff_vk_uninit(&p->vkctx); } static int vulkan_device_create_internal(AVHWDeviceContext *ctx, From d0f1d937fea514abb6e62ff9949eb0b304f99231 Mon Sep 17 00:00:00 2001 From: Lynne Date: Tue, 13 Jun 2023 04:36:54 +0200 Subject: [PATCH 1484/2172] hwcontext_vulkan: free temporary array once unneeded Fixes a small memory leak. This also prevents leaks on malloc/mutex init errors. --- 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 c86229ba658..ca802cc86ef 100644 --- a/libavutil/hwcontext_vulkan.c +++ b/libavutil/hwcontext_vulkan.c @@ -1427,24 +1427,31 @@ static int vulkan_device_init(AVHWDeviceContext *ctx) vk->GetPhysicalDeviceQueueFamilyProperties(hwctx->phys_dev, &qf_num, qf); p->qf_mutex = av_calloc(qf_num, sizeof(*p->qf_mutex)); - if (!p->qf_mutex) + if (!p->qf_mutex) { + av_free(qf); return AVERROR(ENOMEM); + } p->nb_tot_qfs = qf_num; for (uint32_t i = 0; i < qf_num; i++) { p->qf_mutex[i] = av_calloc(qf[i].queueCount, sizeof(**p->qf_mutex)); - if (!p->qf_mutex[i]) + if (!p->qf_mutex[i]) { + av_free(qf); return AVERROR(ENOMEM); + } for (uint32_t j = 0; j < qf[i].queueCount; j++) { err = pthread_mutex_init(&p->qf_mutex[i][j], NULL); if (err != 0) { av_log(ctx, AV_LOG_ERROR, "pthread_mutex_init failed : %s\n", av_err2str(err)); + av_free(qf); return AVERROR(err); } } } + av_free(qf); + graph_index = hwctx->queue_family_index; comp_index = hwctx->queue_family_comp_index; tx_index = hwctx->queue_family_tx_index; From 6964a97f91f723eb114e6015dc65035226c2661d Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Wed, 14 Jun 2023 14:50:08 +1000 Subject: [PATCH 1485/2172] vulkan/av1: fix filling out global motion params. --- libavcodec/vulkan_av1.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/libavcodec/vulkan_av1.c b/libavcodec/vulkan_av1.c index 54473986120..91e44ba8038 100644 --- a/libavcodec/vulkan_av1.c +++ b/libavcodec/vulkan_av1.c @@ -448,9 +448,9 @@ static int vk_av1_start_frame(AVCodecContext *avctx, }, .gm_type = s->cur_frame.gm_type[i], .gm_params = { - frame_header->gm_params[i][0], frame_header->gm_params[i][1], - frame_header->gm_params[i][2], frame_header->gm_params[i][3], - frame_header->gm_params[i][4], frame_header->gm_params[i][5], + s->cur_frame.gm_params[i][0], s->cur_frame.gm_params[i][1], + s->cur_frame.gm_params[i][2], s->cur_frame.gm_params[i][3], + s->cur_frame.gm_params[i][4], s->cur_frame.gm_params[i][5], }, }; } From ca818ab51c437063b2559038aa5ab73dcffb4ff5 Mon Sep 17 00:00:00 2001 From: Lynne Date: Wed, 14 Jun 2023 05:28:03 +0200 Subject: [PATCH 1486/2172] vulkan_h264: filter out constrained/inter flags from the profile index As the comment says, Vulkan signals all the constrant_set flags, and does not want them OR'd onto the profile IDC. So just unset them. --- libavcodec/vulkan_decode.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/libavcodec/vulkan_decode.c b/libavcodec/vulkan_decode.c index 35e265a5b1d..6ba939da46f 100644 --- a/libavcodec/vulkan_decode.c +++ b/libavcodec/vulkan_decode.c @@ -660,7 +660,12 @@ static VkResult vulkan_setup_profile(AVCodecContext *avctx, dec_caps->pNext = h264_caps; usage->pNext = h264_profile; h264_profile->sType = VK_STRUCTURE_TYPE_VIDEO_DECODE_H264_PROFILE_INFO_KHR; - h264_profile->stdProfileIdc = cur_profile; + + /* Vulkan transmits all the constrant_set flags, rather than wanting them + * merged in the profile IDC */ + h264_profile->stdProfileIdc = cur_profile & ~(FF_PROFILE_H264_CONSTRAINED | + FF_PROFILE_H264_INTRA); + h264_profile->pictureLayout = avctx->field_order == AV_FIELD_UNKNOWN || avctx->field_order == AV_FIELD_PROGRESSIVE ? VK_VIDEO_DECODE_H264_PICTURE_LAYOUT_PROGRESSIVE_KHR : From 4abf42ab96a8176b08d03791e3b155c7612f8145 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Sat, 3 Jun 2023 11:55:06 +0200 Subject: [PATCH 1487/2172] lavfi/graphparser: be more verbose when filtergraph parsing fails When an option could not be found, print its name and value. Note that this is not done while applying the options in avfilter_graph_segment_apply_opts() to give the caller the option of handling the missing options in some other way. --- libavfilter/graphparser.c | 36 +++++++++++++++++++++++++++++++++++- 1 file changed, 35 insertions(+), 1 deletion(-) diff --git a/libavfilter/graphparser.c b/libavfilter/graphparser.c index 9f8acea2ac5..96ef6b15bf1 100644 --- a/libavfilter/graphparser.c +++ b/libavfilter/graphparser.c @@ -851,6 +851,32 @@ int avfilter_graph_segment_link(AVFilterGraphSegment *seg, int flags, return ret; } +// print an error message if some options were not found +static void log_unknown_opt(const AVFilterGraphSegment *seg) +{ + for (size_t i = 0; i < seg->nb_chains; i++) { + const AVFilterChain *ch = seg->chains[i]; + + for (size_t j = 0; j < ch->nb_filters; j++) { + const AVFilterParams *p = ch->filters[j]; + const AVDictionaryEntry *e; + + if (!p->filter) + continue; + + e = av_dict_iterate(p->opts, NULL); + + if (e) { + av_log(p->filter, AV_LOG_ERROR, + "Could not set non-existent option '%s' to value '%s'\n", + e->key, e->value); + return; + } + } + } + +} + int avfilter_graph_segment_apply(AVFilterGraphSegment *seg, int flags, AVFilterInOut **inputs, AVFilterInOut **outputs) @@ -868,6 +894,8 @@ int avfilter_graph_segment_apply(AVFilterGraphSegment *seg, int flags, ret = avfilter_graph_segment_apply_opts(seg, 0); if (ret < 0) { + if (ret == AVERROR_OPTION_NOT_FOUND) + log_unknown_opt(seg); av_log(seg->graph, AV_LOG_ERROR, "Error applying filter options\n"); return ret; } @@ -909,8 +937,11 @@ int avfilter_graph_parse_ptr(AVFilterGraph *graph, const char *filters, goto end; ret = avfilter_graph_segment_apply_opts(seg, 0); - if (ret < 0) + if (ret < 0) { + if (ret == AVERROR_OPTION_NOT_FOUND) + log_unknown_opt(seg); goto end; + } ret = avfilter_graph_segment_init(seg, 0); if (ret < 0) @@ -988,6 +1019,9 @@ int avfilter_graph_parse_ptr(AVFilterGraph *graph, const char *filters, avfilter_graph_segment_free(&seg); if (ret < 0) { + av_log(graph, AV_LOG_ERROR, "Error processing filtergraph: %s\n", + av_err2str(ret)); + while (graph->nb_filters) avfilter_free(graph->filters[0]); av_freep(&graph->filters); From 12a073f72cf146d16c7987cf8782519b69be5f56 Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Thu, 15 Jun 2023 17:15:44 +0200 Subject: [PATCH 1488/2172] avfilter/buffersrc: stop passing AV_NOPTS_VALUE on EOF --- libavfilter/buffersrc.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/libavfilter/buffersrc.c b/libavfilter/buffersrc.c index 612541b8039..ea507137011 100644 --- a/libavfilter/buffersrc.c +++ b/libavfilter/buffersrc.c @@ -61,6 +61,7 @@ typedef struct BufferSourceContext { AVChannelLayout ch_layout; int eof; + int64_t last_pts; } BufferSourceContext; #define CHECK_VIDEO_PARAM_CHANGE(s, c, width, height, format, pts)\ @@ -191,10 +192,12 @@ FF_ENABLE_DEPRECATION_WARNINGS s->nb_failed_requests = 0; if (!frame) - return av_buffersrc_close(ctx, AV_NOPTS_VALUE, flags); + return av_buffersrc_close(ctx, s->last_pts, flags); if (s->eof) return AVERROR(EINVAL); + s->last_pts = frame->pts + frame->duration; + refcounted = !!frame->buf[0]; if (!(flags & AV_BUFFERSRC_FLAG_NO_CHECK_FORMAT)) { From a734fa92c8bc39f0792c8da8aecaa145599808bd Mon Sep 17 00:00:00 2001 From: James Almer Date: Thu, 15 Jun 2023 10:53:12 -0300 Subject: [PATCH 1489/2172] avformat/evcdec: set the demuxer as AVFMT_NOTIMESTAMPS Signed-off-by: James Almer --- libavformat/evcdec.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavformat/evcdec.c b/libavformat/evcdec.c index 89eda0f53e8..807406885ae 100644 --- a/libavformat/evcdec.c +++ b/libavformat/evcdec.c @@ -268,7 +268,7 @@ const AVInputFormat ff_evc_demuxer = { .read_packet = evc_read_packet, // annexb_read_packet .read_close = evc_read_close, .extensions = "evc", - .flags = AVFMT_GENERIC_INDEX, + .flags = AVFMT_GENERIC_INDEX | AVFMT_NOTIMESTAMPS, .flags_internal = FF_FMT_INIT_CLEANUP, .raw_codec_id = AV_CODEC_ID_EVC, .priv_data_size = sizeof(EVCDemuxContext), From d00f0eebbdebdf03698e8e134c3765f3ccb2f8c7 Mon Sep 17 00:00:00 2001 From: James Almer Date: Thu, 15 Jun 2023 10:02:43 -0300 Subject: [PATCH 1490/2172] avcodec/evc_parser: remove superfluous memset calls The entire EVCParserContext will be zeroed during allocation. Signed-off-by: James Almer --- libavcodec/evc_parser.c | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/libavcodec/evc_parser.c b/libavcodec/evc_parser.c index 7528fb13db7..639dcbd1353 100644 --- a/libavcodec/evc_parser.c +++ b/libavcodec/evc_parser.c @@ -197,17 +197,6 @@ static int evc_parse(AVCodecParserContext *s, AVCodecContext *avctx, return next; } -static int evc_parser_init(AVCodecParserContext *s) -{ - EVCParserContext *ctx = s->priv_data; - - memset(ctx->sps, 0, sizeof(EVCParserSPS *)*EVC_MAX_SPS_COUNT); - memset(ctx->pps, 0, sizeof(EVCParserPPS *)*EVC_MAX_PPS_COUNT); - memset(ctx->slice_header, 0, sizeof(EVCParserSliceHeader *)*EVC_MAX_PPS_COUNT); - - return 0; -} - static void evc_parser_close(AVCodecParserContext *s) { EVCParserContext *ctx = s->priv_data; @@ -229,7 +218,6 @@ static void evc_parser_close(AVCodecParserContext *s) const AVCodecParser ff_evc_parser = { .codec_ids = { AV_CODEC_ID_EVC }, .priv_data_size = sizeof(EVCParserContext), - .parser_init = evc_parser_init, .parser_parse = evc_parse, .parser_close = evc_parser_close, }; From f42df8384aedeb435b6d427e1b704fda2bd87d5b Mon Sep 17 00:00:00 2001 From: James Almer Date: Thu, 15 Jun 2023 10:35:23 -0300 Subject: [PATCH 1491/2172] avcodec/evc_parse: use the correct struct size when allocating pps Signed-off-by: James Almer --- libavcodec/evc_parse.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavcodec/evc_parse.c b/libavcodec/evc_parse.c index f69d7ffb6b4..cb6c6dc3119 100644 --- a/libavcodec/evc_parse.c +++ b/libavcodec/evc_parse.c @@ -355,7 +355,7 @@ EVCParserPPS *ff_evc_parse_pps(EVCParserContext *ctx, const uint8_t *bs, int bs_ return NULL; if(!ctx->pps[pps_pic_parameter_set_id]) { - if((ctx->pps[pps_pic_parameter_set_id] = av_malloc(sizeof(EVCParserSPS))) == NULL) + if ((ctx->pps[pps_pic_parameter_set_id] = av_malloc(sizeof(EVCParserPPS))) == NULL) return NULL; } From 3c07c2489d94ea0da0b575a4b2bb59f13de0bf6f Mon Sep 17 00:00:00 2001 From: Philip Langdale Date: Thu, 15 Jun 2023 22:10:37 -0700 Subject: [PATCH 1492/2172] avfilter/scale_cuda: add support for rgb32/bgr32 conversions As we are introducing two new formats and supporting conversions between them, and also with the existing 0rgb32/0bgr32 formats, we get a combinatorial explosion of kernels. I introduced a few new macros to keep the things mostly managable. The conversions are all simple, following existing patterns, with four specific exceptions. When converting from 0rgb32/0bgr32 to rgb32/bgr32, we need to ensure the alpha value is set to 1. In all other cases, it can just be passed through, either to be used or ignored. --- libavfilter/version.h | 2 +- libavfilter/vf_scale_cuda.c | 2 + libavfilter/vf_scale_cuda.cu | 151 ++++++++++++++++++++++++++++------- 3 files changed, 123 insertions(+), 32 deletions(-) diff --git a/libavfilter/version.h b/libavfilter/version.h index 08779130f56..c001693e3c9 100644 --- a/libavfilter/version.h +++ b/libavfilter/version.h @@ -32,7 +32,7 @@ #include "version_major.h" #define LIBAVFILTER_VERSION_MINOR 8 -#define LIBAVFILTER_VERSION_MICRO 101 +#define LIBAVFILTER_VERSION_MICRO 102 #define LIBAVFILTER_VERSION_INT AV_VERSION_INT(LIBAVFILTER_VERSION_MAJOR, \ diff --git a/libavfilter/vf_scale_cuda.c b/libavfilter/vf_scale_cuda.c index 1c99befec8e..370cb1d9cde 100644 --- a/libavfilter/vf_scale_cuda.c +++ b/libavfilter/vf_scale_cuda.c @@ -51,6 +51,8 @@ static const enum AVPixelFormat supported_formats[] = { AV_PIX_FMT_YUV444P16, AV_PIX_FMT_0RGB32, AV_PIX_FMT_0BGR32, + AV_PIX_FMT_RGB32, + AV_PIX_FMT_BGR32, }; #define DIV_UP(a, b) ( ((a) + (b) - 1) / (b) ) diff --git a/libavfilter/vf_scale_cuda.cu b/libavfilter/vf_scale_cuda.cu index c9c6cafdb6e..de06ba94331 100644 --- a/libavfilter/vf_scale_cuda.cu +++ b/libavfilter/vf_scale_cuda.cu @@ -853,9 +853,67 @@ struct Convert_yuv444p16le_yuv444p16le } }; -// bgr0->X - -struct Convert_bgr0_bgr0 +#define DEF_CONVERT_IDENTITY(fmt1, fmt2)\ + \ +struct Convert_##fmt1##_##fmt2 \ +{ \ + static const int in_bit_depth = 8; \ + typedef uchar4 in_T; \ + typedef uchar in_T_uv; \ + typedef uchar4 out_T; \ + typedef uchar out_T_uv; \ + \ + DEF_F(Convert, out_T) \ + { \ + DEFAULT_DST(0) = SUB_F(y, 0); \ + } \ + \ + DEF_F(Convert_uv, out_T_uv) \ + { \ + } \ +}; \ + +#define DEF_CONVERT_REORDER(fmt1, fmt2) \ + \ +struct Convert_##fmt1##_##fmt2 \ +{ \ + static const int in_bit_depth = 8; \ + typedef uchar4 in_T; \ + typedef uchar in_T_uv; \ + typedef uchar4 out_T; \ + typedef uchar out_T_uv; \ + \ + DEF_F(Convert, out_T) \ + { \ + uchar4 res = SUB_F(y, 0); \ + DEFAULT_DST(0) = make_uchar4( \ + res.z, \ + res.y, \ + res.x, \ + res.w \ + ); \ + } \ + \ + DEF_F(Convert_uv, out_T_uv) \ + { \ + } \ +}; \ + +#define DEF_CONVERT_RGB(fmt1, fmt2) \ + \ +DEF_CONVERT_IDENTITY(fmt1, fmt1) \ +DEF_CONVERT_REORDER (fmt1, fmt2) \ +DEF_CONVERT_REORDER (fmt2, fmt1) \ +DEF_CONVERT_IDENTITY(fmt2, fmt2) + +DEF_CONVERT_RGB(rgb0, bgr0) +DEF_CONVERT_RGB(rgba, bgra) +DEF_CONVERT_IDENTITY(rgba, rgb0) +DEF_CONVERT_IDENTITY(bgra, bgr0) +DEF_CONVERT_REORDER(rgba, bgr0) +DEF_CONVERT_REORDER(bgra, rgb0) + +struct Convert_bgr0_bgra { static const int in_bit_depth = 8; typedef uchar4 in_T; @@ -865,7 +923,13 @@ struct Convert_bgr0_bgr0 DEF_F(Convert, out_T) { - DEFAULT_DST(0) = SUB_F(y, 0); + uchar4 res = SUB_F(y, 0); + DEFAULT_DST(0) = make_uchar4( + res.x, + res.y, + res.z, + 1 + ); } DEF_F(Convert_uv, out_T_uv) @@ -873,7 +937,7 @@ struct Convert_bgr0_bgr0 } }; -struct Convert_bgr0_rgb0 +struct Convert_bgr0_rgba { static const int in_bit_depth = 8; typedef uchar4 in_T; @@ -888,7 +952,7 @@ struct Convert_bgr0_rgb0 res.z, res.y, res.x, - res.w + 1 ); } @@ -897,9 +961,7 @@ struct Convert_bgr0_rgb0 } }; -// rgb0->X - -struct Convert_rgb0_bgr0 +struct Convert_rgb0_bgra { static const int in_bit_depth = 8; typedef uchar4 in_T; @@ -914,7 +976,7 @@ struct Convert_rgb0_bgr0 res.z, res.y, res.x, - res.w + 1 ); } @@ -923,7 +985,7 @@ struct Convert_rgb0_bgr0 } }; -struct Convert_rgb0_rgb0 +struct Convert_rgb0_rgba { static const int in_bit_depth = 8; typedef uchar4 in_T; @@ -933,7 +995,13 @@ struct Convert_rgb0_rgb0 DEF_F(Convert, out_T) { - DEFAULT_DST(0) = SUB_F(y, 0); + uchar4 res = SUB_F(y, 0); + DEFAULT_DST(0) = make_uchar4( + res.x, + res.y, + res.z, + 1 + ); } DEF_F(Convert_uv, out_T_uv) @@ -1117,6 +1185,12 @@ extern "C" { NEAREST_KERNEL_RAW(p016le_ ## C) \ NEAREST_KERNEL_RAW(yuv444p16le_ ## C) +#define NEAREST_KERNELS_RGB(C) \ + NEAREST_KERNEL_RAW(rgb0_ ## C) \ + NEAREST_KERNEL_RAW(bgr0_ ## C) \ + NEAREST_KERNEL_RAW(rgba_ ## C) \ + NEAREST_KERNEL_RAW(bgra_ ## C) \ + NEAREST_KERNELS(yuv420p) NEAREST_KERNELS(nv12) NEAREST_KERNELS(yuv444p) @@ -1124,11 +1198,10 @@ NEAREST_KERNELS(p010le) NEAREST_KERNELS(p016le) NEAREST_KERNELS(yuv444p16le) -NEAREST_KERNEL_RAW(bgr0_bgr0) -NEAREST_KERNEL_RAW(rgb0_rgb0) -NEAREST_KERNEL_RAW(bgr0_rgb0) -NEAREST_KERNEL_RAW(rgb0_bgr0) - +NEAREST_KERNELS_RGB(rgb0) +NEAREST_KERNELS_RGB(bgr0) +NEAREST_KERNELS_RGB(rgba) +NEAREST_KERNELS_RGB(bgra) #define BILINEAR_KERNEL(C, S) \ __global__ void Subsample_Bilinear_##C##S( \ @@ -1152,6 +1225,12 @@ NEAREST_KERNEL_RAW(rgb0_bgr0) BILINEAR_KERNEL_RAW(p016le_ ## C) \ BILINEAR_KERNEL_RAW(yuv444p16le_ ## C) +#define BILINEAR_KERNELS_RGB(C) \ + BILINEAR_KERNEL_RAW(rgb0_ ## C) \ + BILINEAR_KERNEL_RAW(bgr0_ ## C) \ + BILINEAR_KERNEL_RAW(rgba_ ## C) \ + BILINEAR_KERNEL_RAW(bgra_ ## C) + BILINEAR_KERNELS(yuv420p) BILINEAR_KERNELS(nv12) BILINEAR_KERNELS(yuv444p) @@ -1159,10 +1238,10 @@ BILINEAR_KERNELS(p010le) BILINEAR_KERNELS(p016le) BILINEAR_KERNELS(yuv444p16le) -BILINEAR_KERNEL_RAW(bgr0_bgr0) -BILINEAR_KERNEL_RAW(rgb0_rgb0) -BILINEAR_KERNEL_RAW(bgr0_rgb0) -BILINEAR_KERNEL_RAW(rgb0_bgr0) +BILINEAR_KERNELS_RGB(rgb0) +BILINEAR_KERNELS_RGB(bgr0) +BILINEAR_KERNELS_RGB(rgba) +BILINEAR_KERNELS_RGB(bgra) #define BICUBIC_KERNEL(C, S) \ __global__ void Subsample_Bicubic_##C##S( \ @@ -1186,6 +1265,12 @@ BILINEAR_KERNEL_RAW(rgb0_bgr0) BICUBIC_KERNEL_RAW(p016le_ ## C) \ BICUBIC_KERNEL_RAW(yuv444p16le_ ## C) +#define BICUBIC_KERNELS_RGB(C) \ + BICUBIC_KERNEL_RAW(rgb0_ ## C) \ + BICUBIC_KERNEL_RAW(bgr0_ ## C) \ + BICUBIC_KERNEL_RAW(rgba_ ## C) \ + BICUBIC_KERNEL_RAW(bgra_ ## C) + BICUBIC_KERNELS(yuv420p) BICUBIC_KERNELS(nv12) BICUBIC_KERNELS(yuv444p) @@ -1193,11 +1278,10 @@ BICUBIC_KERNELS(p010le) BICUBIC_KERNELS(p016le) BICUBIC_KERNELS(yuv444p16le) -BICUBIC_KERNEL_RAW(bgr0_bgr0) -BICUBIC_KERNEL_RAW(rgb0_rgb0) -BICUBIC_KERNEL_RAW(bgr0_rgb0) -BICUBIC_KERNEL_RAW(rgb0_bgr0) - +BICUBIC_KERNELS_RGB(rgb0) +BICUBIC_KERNELS_RGB(bgr0) +BICUBIC_KERNELS_RGB(rgba) +BICUBIC_KERNELS_RGB(bgra) #define LANCZOS_KERNEL(C, S) \ __global__ void Subsample_Lanczos_##C##S( \ @@ -1221,6 +1305,12 @@ BICUBIC_KERNEL_RAW(rgb0_bgr0) LANCZOS_KERNEL_RAW(p016le_ ## C) \ LANCZOS_KERNEL_RAW(yuv444p16le_ ## C) +#define LANCZOS_KERNELS_RGB(C) \ + LANCZOS_KERNEL_RAW(rgb0_ ## C) \ + LANCZOS_KERNEL_RAW(bgr0_ ## C) \ + LANCZOS_KERNEL_RAW(rgba_ ## C) \ + LANCZOS_KERNEL_RAW(bgra_ ## C) + LANCZOS_KERNELS(yuv420p) LANCZOS_KERNELS(nv12) LANCZOS_KERNELS(yuv444p) @@ -1228,9 +1318,8 @@ LANCZOS_KERNELS(p010le) LANCZOS_KERNELS(p016le) LANCZOS_KERNELS(yuv444p16le) -LANCZOS_KERNEL_RAW(bgr0_bgr0) -LANCZOS_KERNEL_RAW(rgb0_rgb0) -LANCZOS_KERNEL_RAW(bgr0_rgb0) -LANCZOS_KERNEL_RAW(rgb0_bgr0) - +LANCZOS_KERNELS_RGB(rgb0) +LANCZOS_KERNELS_RGB(bgr0) +LANCZOS_KERNELS_RGB(rgba) +LANCZOS_KERNELS_RGB(bgra) } From 73a2252f1d9062fa877ef153532bc35351dafab6 Mon Sep 17 00:00:00 2001 From: Philip Langdale Date: Thu, 29 Aug 2019 21:43:29 -0700 Subject: [PATCH 1493/2172] avfilter/vf_bwdif_cuda: CUDA accelerated bwdif deinterlacer I've been sitting on this for 3 1/2 years now(!), and I finally got around to fixing the loose ends and convincing myself that it was correct. It follows the same basic structure as yadif_cuda, including leaving out the edge handling, to avoid expensive branching. --- Changelog | 1 + configure | 2 + doc/filters.texi | 52 +++++ libavcodec/version.h | 2 +- libavfilter/Makefile | 2 + libavfilter/allfilters.c | 1 + libavfilter/vf_bwdif_cuda.c | 375 +++++++++++++++++++++++++++++++++++ libavfilter/vf_bwdif_cuda.cu | 309 +++++++++++++++++++++++++++++ 8 files changed, 743 insertions(+), 1 deletion(-) create mode 100644 libavfilter/vf_bwdif_cuda.c create mode 100644 libavfilter/vf_bwdif_cuda.cu diff --git a/Changelog b/Changelog index ac3247982be..fb47d2652bd 100644 --- a/Changelog +++ b/Changelog @@ -19,6 +19,7 @@ version : - vMix video decoder - Essential Video Coding parser, muxer and demuxer - Essential Video Coding frame merge bsf +- bwdif_cuda filter version 6.0: - Radiance HDR image support diff --git a/configure b/configure index c9a86e9f8e1..0c77d8e1fe7 100755 --- a/configure +++ b/configure @@ -3697,6 +3697,8 @@ blend_vulkan_filter_deps="vulkan spirv_compiler" boxblur_filter_deps="gpl" boxblur_opencl_filter_deps="opencl gpl" bs2b_filter_deps="libbs2b" +bwdif_cuda_filter_deps="ffnvcodec" +bwdif_cuda_filter_deps_any="cuda_nvcc cuda_llvm" bwdif_vulkan_filter_deps="vulkan spirv_compiler" chromaber_vulkan_filter_deps="vulkan spirv_compiler" color_vulkan_filter_deps="vulkan spirv_compiler" diff --git a/doc/filters.texi b/doc/filters.texi index a46357bfd82..a8217b07554 100644 --- a/doc/filters.texi +++ b/doc/filters.texi @@ -9145,6 +9145,58 @@ Only deinterlace frames marked as interlaced. The default value is @code{all}. @end table +@section bwdif_cuda + +Deinterlace the input video using the @ref{bwdif} algorithm, but implemented +in CUDA so that it can work as part of a GPU accelerated pipeline with nvdec +and/or nvenc. + +It accepts the following parameters: + +@table @option +@item mode +The interlacing mode to adopt. It accepts one of the following values: + +@table @option +@item 0, send_frame +Output one frame for each frame. +@item 1, send_field +Output one frame for each field. +@end table + +The default value is @code{send_field}. + +@item parity +The picture field parity assumed for the input interlaced video. It accepts one +of the following values: + +@table @option +@item 0, tff +Assume the top field is first. +@item 1, bff +Assume the bottom field is first. +@item -1, auto +Enable automatic detection of field parity. +@end table + +The default value is @code{auto}. +If the interlacing is unknown or the decoder does not export this information, +top field first will be assumed. + +@item deint +Specify which frames to deinterlace. Accepts one of the following +values: + +@table @option +@item 0, all +Deinterlace all frames. +@item 1, interlaced +Only deinterlace frames marked as interlaced. +@end table + +The default value is @code{all}. +@end table + @section ccrepack Repack CEA-708 closed captioning side data diff --git a/libavcodec/version.h b/libavcodec/version.h index 4b7ec515fe8..d0980e28de8 100644 --- a/libavcodec/version.h +++ b/libavcodec/version.h @@ -29,7 +29,7 @@ #include "version_major.h" -#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, \ diff --git a/libavfilter/Makefile b/libavfilter/Makefile index ff149a3733a..9b7813575a0 100644 --- a/libavfilter/Makefile +++ b/libavfilter/Makefile @@ -213,6 +213,8 @@ OBJS-$(CONFIG_BOXBLUR_FILTER) += vf_boxblur.o boxblur.o 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_BWDIF_CUDA_FILTER) += vf_bwdif_cuda.o vf_bwdif_cuda.ptx.o \ + yadif_common.o OBJS-$(CONFIG_BWDIF_VULKAN_FILTER) += vf_bwdif_vulkan.o yadif_common.o vulkan.o vulkan_filter.o OBJS-$(CONFIG_CAS_FILTER) += vf_cas.o OBJS-$(CONFIG_CCREPACK_FILTER) += vf_ccrepack.o diff --git a/libavfilter/allfilters.c b/libavfilter/allfilters.c index 6593e4eb839..9a7fadc58d6 100644 --- a/libavfilter/allfilters.c +++ b/libavfilter/allfilters.c @@ -197,6 +197,7 @@ extern const AVFilter ff_vf_bm3d; extern const AVFilter ff_vf_boxblur; extern const AVFilter ff_vf_boxblur_opencl; extern const AVFilter ff_vf_bwdif; +extern const AVFilter ff_vf_bwdif_cuda; extern const AVFilter ff_vf_bwdif_vulkan; extern const AVFilter ff_vf_cas; extern const AVFilter ff_vf_ccrepack; diff --git a/libavfilter/vf_bwdif_cuda.c b/libavfilter/vf_bwdif_cuda.c new file mode 100644 index 00000000000..a5ecfbadb64 --- /dev/null +++ b/libavfilter/vf_bwdif_cuda.c @@ -0,0 +1,375 @@ +/* + * Copyright (C) 2019 Philip Langdale + * + * 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/avassert.h" +#include "libavutil/hwcontext.h" +#include "libavutil/hwcontext_cuda_internal.h" +#include "libavutil/cuda_check.h" +#include "internal.h" +#include "yadif.h" + +#include "cuda/load_helper.h" + +extern const unsigned char ff_vf_bwdif_cuda_ptx_data[]; +extern const unsigned int ff_vf_bwdif_cuda_ptx_len; + +typedef struct DeintCUDAContext { + YADIFContext yadif; + + AVCUDADeviceContext *hwctx; + AVBufferRef *device_ref; + AVBufferRef *input_frames_ref; + AVHWFramesContext *input_frames; + + CUmodule cu_module; + CUfunction cu_func_uchar; + CUfunction cu_func_uchar2; + CUfunction cu_func_ushort; + CUfunction cu_func_ushort2; +} DeintCUDAContext; + +#define DIV_UP(a, b) ( ((a) + (b) - 1) / (b) ) +#define ALIGN_UP(a, b) (((a) + (b) - 1) & ~((b) - 1)) +#define BLOCKX 32 +#define BLOCKY 16 + +#define CHECK_CU(x) FF_CUDA_CHECK_DL(ctx, s->hwctx->internal->cuda_dl, x) + +static CUresult call_kernel(AVFilterContext *ctx, CUfunction func, + CUdeviceptr prev, CUdeviceptr cur, CUdeviceptr next, + CUarray_format format, int channels, + int src_width, // Width is pixels per channel + int src_height, // Height is pixels per channel + int src_pitch, // Pitch is bytes + CUdeviceptr dst, + int dst_width, // Width is pixels per channel + int dst_height, // Height is pixels per channel + int dst_pitch, // Pitch is pixels per channel + int parity, int tff, int clip_max) +{ + DeintCUDAContext *s = ctx->priv; + YADIFContext *y = &s->yadif; + CudaFunctions *cu = s->hwctx->internal->cuda_dl; + CUtexObject tex_prev = 0, tex_cur = 0, tex_next = 0; + int is_field_end = y->current_field == YADIF_FIELD_END; + int ret; + + void *args[] = { &dst, &tex_prev, &tex_cur, &tex_next, + &dst_width, &dst_height, &dst_pitch, + &src_width, &src_height, &parity, &tff, + &is_field_end, &clip_max }; + + CUDA_TEXTURE_DESC tex_desc = { + .filterMode = CU_TR_FILTER_MODE_POINT, + .flags = CU_TRSF_READ_AS_INTEGER, + }; + + CUDA_RESOURCE_DESC res_desc = { + .resType = CU_RESOURCE_TYPE_PITCH2D, + .res.pitch2D.format = format, + .res.pitch2D.numChannels = channels, + .res.pitch2D.width = src_width, + .res.pitch2D.height = src_height, + .res.pitch2D.pitchInBytes = src_pitch, + }; + + res_desc.res.pitch2D.devPtr = (CUdeviceptr)prev; + ret = CHECK_CU(cu->cuTexObjectCreate(&tex_prev, &res_desc, &tex_desc, NULL)); + if (ret < 0) + goto exit; + + res_desc.res.pitch2D.devPtr = (CUdeviceptr)cur; + ret = CHECK_CU(cu->cuTexObjectCreate(&tex_cur, &res_desc, &tex_desc, NULL)); + if (ret < 0) + goto exit; + + res_desc.res.pitch2D.devPtr = (CUdeviceptr)next; + ret = CHECK_CU(cu->cuTexObjectCreate(&tex_next, &res_desc, &tex_desc, NULL)); + if (ret < 0) + goto exit; + + ret = CHECK_CU(cu->cuLaunchKernel(func, + DIV_UP(dst_width, BLOCKX), DIV_UP(dst_height, BLOCKY), 1, + BLOCKX, BLOCKY, 1, + 0, s->hwctx->stream, args, NULL)); + +exit: + if (tex_prev) + CHECK_CU(cu->cuTexObjectDestroy(tex_prev)); + if (tex_cur) + CHECK_CU(cu->cuTexObjectDestroy(tex_cur)); + if (tex_next) + CHECK_CU(cu->cuTexObjectDestroy(tex_next)); + + return ret; +} + +static void filter(AVFilterContext *ctx, AVFrame *dst, + int parity, int tff) +{ + DeintCUDAContext *s = ctx->priv; + YADIFContext *y = &s->yadif; + CudaFunctions *cu = s->hwctx->internal->cuda_dl; + CUcontext dummy; + int i, ret; + + ret = CHECK_CU(cu->cuCtxPushCurrent(s->hwctx->cuda_ctx)); + if (ret < 0) + return; + + for (i = 0; i < y->csp->nb_components; i++) { + CUfunction func; + CUarray_format format; + int pixel_size, channels, clip_max; + const AVComponentDescriptor *comp = &y->csp->comp[i]; + + 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: + func = channels == 1 ? s->cu_func_uchar : s->cu_func_uchar2; + format = CU_AD_FORMAT_UNSIGNED_INT8; + break; + case 2: + func = channels == 1 ? s->cu_func_ushort : s->cu_func_ushort2; + format = CU_AD_FORMAT_UNSIGNED_INT16; + break; + default: + av_log(ctx, AV_LOG_ERROR, "Unsupported pixel format: %s\n", y->csp->name); + goto exit; + } + + clip_max = (1 << (comp->depth + comp->shift)) - 1; + + av_log(ctx, AV_LOG_TRACE, + "Deinterlacing plane %d: pixel_size: %d channels: %d\n", + comp->plane, pixel_size, channels); + call_kernel(ctx, func, + (CUdeviceptr)y->prev->data[i], + (CUdeviceptr)y->cur->data[i], + (CUdeviceptr)y->next->data[i], + format, channels, + AV_CEIL_RSHIFT(y->cur->width, i ? y->csp->log2_chroma_w : 0), + AV_CEIL_RSHIFT(y->cur->height, i ? y->csp->log2_chroma_h : 0), + y->cur->linesize[i], + (CUdeviceptr)dst->data[i], + AV_CEIL_RSHIFT(dst->width, i ? y->csp->log2_chroma_w : 0), + AV_CEIL_RSHIFT(dst->height, i ? y->csp->log2_chroma_h : 0), + dst->linesize[i] / comp->step, + parity, tff, clip_max); + } + + if (y->current_field == YADIF_FIELD_END) { + y->current_field = YADIF_FIELD_NORMAL; + } + +exit: + CHECK_CU(cu->cuCtxPopCurrent(&dummy)); + return; +} + +static av_cold void deint_cuda_uninit(AVFilterContext *ctx) +{ + CUcontext dummy; + DeintCUDAContext *s = ctx->priv; + YADIFContext *y = &s->yadif; + + if (s->hwctx && s->cu_module) { + CudaFunctions *cu = s->hwctx->internal->cuda_dl; + CHECK_CU(cu->cuCtxPushCurrent(s->hwctx->cuda_ctx)); + CHECK_CU(cu->cuModuleUnload(s->cu_module)); + CHECK_CU(cu->cuCtxPopCurrent(&dummy)); + } + + av_frame_free(&y->prev); + av_frame_free(&y->cur); + av_frame_free(&y->next); + + av_buffer_unref(&s->device_ref); + s->hwctx = NULL; + av_buffer_unref(&s->input_frames_ref); + s->input_frames = NULL; +} + +static int config_input(AVFilterLink *inlink) +{ + AVFilterContext *ctx = inlink->dst; + DeintCUDAContext *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; + DeintCUDAContext *s = ctx->priv; + YADIFContext *y = &s->yadif; + CudaFunctions *cu; + int ret = 0; + CUcontext dummy; + + 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); + } + s->hwctx = ((AVHWDeviceContext*)s->device_ref->data)->hwctx; + cu = s->hwctx->internal->cuda_dl; + + 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_CUDA; + output_frames->sw_format = s->input_frames->sw_format; + output_frames->width = ctx->inputs[0]->w; + output_frames->height = ctx->inputs[0]->h; + + output_frames->initial_pool_size = 4; + + 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 CUDA frame " + "context for output: %d\n", ret); + goto exit; + } + + link->time_base = av_mul_q(ctx->inputs[0]->time_base, (AVRational){1, 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; + + ret = CHECK_CU(cu->cuCtxPushCurrent(s->hwctx->cuda_ctx)); + if (ret < 0) + goto exit; + + ret = ff_cuda_load_module(ctx, s->hwctx, &s->cu_module, ff_vf_bwdif_cuda_ptx_data, ff_vf_bwdif_cuda_ptx_len); + if (ret < 0) + goto exit; + + ret = CHECK_CU(cu->cuModuleGetFunction(&s->cu_func_uchar, s->cu_module, "bwdif_uchar")); + if (ret < 0) + goto exit; + + ret = CHECK_CU(cu->cuModuleGetFunction(&s->cu_func_uchar2, s->cu_module, "bwdif_uchar2")); + if (ret < 0) + goto exit; + + ret = CHECK_CU(cu->cuModuleGetFunction(&s->cu_func_ushort, s->cu_module, "bwdif_ushort")); + if (ret < 0) + goto exit; + + ret = CHECK_CU(cu->cuModuleGetFunction(&s->cu_func_ushort2, s->cu_module, "bwdif_ushort2")); + if (ret < 0) + goto exit; + +exit: + CHECK_CU(cu->cuCtxPopCurrent(&dummy)); + + return ret; +} + +static const AVClass bwdif_cuda_class = { + .class_name = "bwdif_cuda", + .item_name = av_default_item_name, + .option = ff_yadif_options, + .version = LIBAVUTIL_VERSION_INT, + .category = AV_CLASS_CATEGORY_FILTER, +}; + +static const AVFilterPad deint_cuda_inputs[] = { + { + .name = "default", + .type = AVMEDIA_TYPE_VIDEO, + .filter_frame = ff_yadif_filter_frame, + .config_props = config_input, + }, +}; + +static const AVFilterPad deint_cuda_outputs[] = { + { + .name = "default", + .type = AVMEDIA_TYPE_VIDEO, + .request_frame = ff_yadif_request_frame, + .config_props = config_output, + }, +}; + +const AVFilter ff_vf_bwdif_cuda = { + .name = "bwdif_cuda", + .description = NULL_IF_CONFIG_SMALL("Deinterlace CUDA frames"), + .priv_size = sizeof(DeintCUDAContext), + .priv_class = &bwdif_cuda_class, + .uninit = deint_cuda_uninit, + FILTER_SINGLE_PIXFMT(AV_PIX_FMT_CUDA), + FILTER_INPUTS(deint_cuda_inputs), + FILTER_OUTPUTS(deint_cuda_outputs), + .flags = AVFILTER_FLAG_SUPPORT_TIMELINE_INTERNAL, + .flags_internal = FF_FILTER_FLAG_HWFRAME_AWARE, +}; diff --git a/libavfilter/vf_bwdif_cuda.cu b/libavfilter/vf_bwdif_cuda.cu new file mode 100644 index 00000000000..3d4c29d8c39 --- /dev/null +++ b/libavfilter/vf_bwdif_cuda.cu @@ -0,0 +1,309 @@ +/* + * Copyright (C) 2019 Philip Langdale + * + * 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 + */ + +__device__ static const int coef_lf[2] = { 4309, 213 }; +__device__ static const int coef_hf[3] = { 5570, 3801, 1016 }; +__device__ static const int coef_sp[2] = { 5077, 981 }; + +template +__inline__ __device__ T max3(T a, T b, T c) +{ + T x = max(a, b); + return max(x, c); +} + +template +__inline__ __device__ T min3(T a, T b, T c) +{ + T x = min(a, b); + return min(x, c); +} + +template +__inline__ __device__ T clip(T a, T min, T max) +{ + if (a < min) { + return min; + } else if (a > max) { + return max; + } else { + return a; + } +} + +template +__inline__ __device__ T filter_intra(T cur_prefs3, T cur_prefs, + T cur_mrefs, T cur_mrefs3, + int clip_max) +{ + int final = (coef_sp[0] * (cur_mrefs + cur_prefs) - + coef_sp[1] * (cur_mrefs3 + cur_prefs3)) >> 13; + return clip(final, 0, clip_max); +} + +template +__inline__ __device__ T filter(T cur_prefs3, T cur_prefs, T cur_mrefs, T cur_mrefs3, + T prev2_prefs4, T prev2_prefs2, T prev2_0, T prev2_mrefs2, T prev2_mrefs4, + T prev_prefs, T prev_mrefs, T next_prefs, T next_mrefs, + T next2_prefs4, T next2_prefs2, T next2_0, T next2_mrefs2, T next2_mrefs4, + int clip_max) +{ + T final; + + int c = cur_mrefs; + int d = (prev2_0 + next2_0) >> 1; + int e = cur_prefs; + + int temporal_diff0 = abs(prev2_0 - next2_0); + int temporal_diff1 = (abs(prev_mrefs - c) + abs(prev_prefs - e)) >> 1; + int temporal_diff2 = (abs(next_mrefs - c) + abs(next_prefs - e)) >> 1; + int diff = max3(temporal_diff0 >> 1, temporal_diff1, temporal_diff2); + + if (!diff) { + final = d; + } else { + int b = ((prev2_mrefs2 + next2_mrefs2) >> 1) - c; + int f = ((prev2_prefs2 + next2_prefs2) >> 1) - e; + int dc = d - c; + int de = d - e; + int mmax = max3(de, dc, min(b, f)); + int mmin = min3(de, dc, max(b, f)); + diff = max3(diff, mmin, -mmax); + + int interpol; + if (abs(c - e) > temporal_diff0) { + interpol = (((coef_hf[0] * (prev2_0 + next2_0) + - coef_hf[1] * (prev2_mrefs2 + next2_mrefs2 + prev2_prefs2 + next2_prefs2) + + coef_hf[2] * (prev2_mrefs4 + next2_mrefs4 + prev2_prefs4 + next2_mrefs4)) >> 2) + + coef_lf[0] * (c + e) - coef_lf[1] * (cur_mrefs3 + cur_prefs3)) >> 13; + } else { + interpol = (coef_sp[0] * (c + e) - coef_sp[1] * (cur_mrefs3 + cur_prefs3)) >> 13; + } + + if (interpol > d + diff) { + interpol = d + diff; + } else if (interpol < d - diff) { + interpol = d - diff; + } + final = clip(interpol, 0, clip_max); + } + + return final; +} + +template +__inline__ __device__ void bwdif_single(T *dst, + cudaTextureObject_t prev, + cudaTextureObject_t cur, + cudaTextureObject_t next, + int dst_width, int dst_height, int dst_pitch, + int src_width, int src_height, + int parity, int tff, + int is_field_end, int clip_max) +{ + // Identify location + int xo = blockIdx.x * blockDim.x + threadIdx.x; + int yo = blockIdx.y * blockDim.y + threadIdx.y; + + if (xo >= dst_width || yo >= dst_height) { + return; + } + + // Don't modify the primary field + if (yo % 2 == parity) { + dst[yo*dst_pitch+xo] = tex2D(cur, xo, yo); + return; + } + + T cur_prefs3 = tex2D(cur, xo, yo + 3); + T cur_prefs = tex2D(cur, xo, yo + 1); + T cur_mrefs = tex2D(cur, xo, yo - 1); + T cur_mrefs3 = tex2D(cur, xo, yo - 3); + + if (is_field_end) { + dst[yo*dst_pitch+xo] = + filter_intra(cur_prefs3, cur_prefs, cur_mrefs, cur_mrefs3, clip_max); + return; + } + + // Calculate temporal prediction + int is_second_field = !(parity ^ tff); + + cudaTextureObject_t prev2 = prev; + cudaTextureObject_t prev1 = is_second_field ? cur : prev; + cudaTextureObject_t next1 = is_second_field ? next : cur; + cudaTextureObject_t next2 = next; + + T prev2_prefs4 = tex2D(prev2, xo, yo + 4); + T prev2_prefs2 = tex2D(prev2, xo, yo + 2); + T prev2_0 = tex2D(prev2, xo, yo + 0); + T prev2_mrefs2 = tex2D(prev2, xo, yo - 2); + T prev2_mrefs4 = tex2D(prev2, xo, yo - 4); + T prev_prefs = tex2D(prev1, xo, yo + 1); + T prev_mrefs = tex2D(prev1, xo, yo - 1); + T next_prefs = tex2D(next1, xo, yo + 1); + T next_mrefs = tex2D(next1, xo, yo - 1); + T next2_prefs4 = tex2D(next2, xo, yo + 4); + T next2_prefs2 = tex2D(next2, xo, yo + 2); + T next2_0 = tex2D(next2, xo, yo + 0); + T next2_mrefs2 = tex2D(next2, xo, yo - 2); + T next2_mrefs4 = tex2D(next2, xo, yo - 4); + + dst[yo*dst_pitch+xo] = filter(cur_prefs3, cur_prefs, cur_mrefs, cur_mrefs3, + prev2_prefs4, prev2_prefs2, prev2_0, prev2_mrefs2, prev2_mrefs4, + prev_prefs, prev_mrefs, next_prefs, next_mrefs, + next2_prefs4, next2_prefs2, next2_0, next2_mrefs2, next2_mrefs4, + clip_max); +} + +template +__inline__ __device__ void bwdif_double(T *dst, + cudaTextureObject_t prev, + cudaTextureObject_t cur, + cudaTextureObject_t next, + int dst_width, int dst_height, int dst_pitch, + int src_width, int src_height, + int parity, int tff, + int is_field_end, int clip_max) +{ + int xo = blockIdx.x * blockDim.x + threadIdx.x; + int yo = blockIdx.y * blockDim.y + threadIdx.y; + + if (xo >= dst_width || yo >= dst_height) { + return; + } + + if (yo % 2 == parity) { + // Don't modify the primary field + dst[yo*dst_pitch+xo] = tex2D(cur, xo, yo); + return; + } + + T cur_prefs3 = tex2D(cur, xo, yo + 3); + T cur_prefs = tex2D(cur, xo, yo + 1); + T cur_mrefs = tex2D(cur, xo, yo - 1); + T cur_mrefs3 = tex2D(cur, xo, yo - 3); + + if (is_field_end) { + T final; + final.x = filter_intra(cur_prefs3.x, cur_prefs.x, cur_mrefs.x, cur_mrefs3.x, + clip_max); + final.y = filter_intra(cur_prefs3.y, cur_prefs.y, cur_mrefs.y, cur_mrefs3.y, + clip_max); + dst[yo*dst_pitch+xo] = final; + return; + } + + int is_second_field = !(parity ^ tff); + + cudaTextureObject_t prev2 = prev; + cudaTextureObject_t prev1 = is_second_field ? cur : prev; + cudaTextureObject_t next1 = is_second_field ? next : cur; + cudaTextureObject_t next2 = next; + + T prev2_prefs4 = tex2D(prev2, xo, yo + 4); + T prev2_prefs2 = tex2D(prev2, xo, yo + 2); + T prev2_0 = tex2D(prev2, xo, yo + 0); + T prev2_mrefs2 = tex2D(prev2, xo, yo - 2); + T prev2_mrefs4 = tex2D(prev2, xo, yo - 4); + T prev_prefs = tex2D(prev1, xo, yo + 1); + T prev_mrefs = tex2D(prev1, xo, yo - 1); + T next_prefs = tex2D(next1, xo, yo + 1); + T next_mrefs = tex2D(next1, xo, yo - 1); + T next2_prefs4 = tex2D(next2, xo, yo + 4); + T next2_prefs2 = tex2D(next2, xo, yo + 2); + T next2_0 = tex2D(next2, xo, yo + 0); + T next2_mrefs2 = tex2D(next2, xo, yo - 2); + T next2_mrefs4 = tex2D(next2, xo, yo - 4); + + T final; + final.x = filter(cur_prefs3.x, cur_prefs.x, cur_mrefs.x, cur_mrefs3.x, + prev2_prefs4.x, prev2_prefs2.x, prev2_0.x, prev2_mrefs2.x, prev2_mrefs4.x, + prev_prefs.x, prev_mrefs.x, next_prefs.x, next_mrefs.x, + next2_prefs4.x, next2_prefs2.x, next2_0.x, next2_mrefs2.x, next2_mrefs4.x, + clip_max); + final.y = filter(cur_prefs3.y, cur_prefs.y, cur_mrefs.y, cur_mrefs3.y, + prev2_prefs4.y, prev2_prefs2.y, prev2_0.y, prev2_mrefs2.y, prev2_mrefs4.y, + prev_prefs.y, prev_mrefs.y, next_prefs.y, next_mrefs.y, + next2_prefs4.y, next2_prefs2.y, next2_0.y, next2_mrefs2.y, next2_mrefs4.y, + clip_max); + + dst[yo*dst_pitch+xo] = final; +} + +extern "C" { + +__global__ void bwdif_uchar(unsigned char *dst, + cudaTextureObject_t prev, + cudaTextureObject_t cur, + cudaTextureObject_t next, + int dst_width, int dst_height, int dst_pitch, + int src_width, int src_height, + int parity, int tff, int is_field_end, int clip_max) +{ + bwdif_single(dst, prev, cur, next, + dst_width, dst_height, dst_pitch, + src_width, src_height, + parity, tff, is_field_end, clip_max); +} + +__global__ void bwdif_ushort(unsigned short *dst, + cudaTextureObject_t prev, + cudaTextureObject_t cur, + cudaTextureObject_t next, + int dst_width, int dst_height, int dst_pitch, + int src_width, int src_height, + int parity, int tff, int is_field_end, int clip_max) +{ + bwdif_single(dst, prev, cur, next, + dst_width, dst_height, dst_pitch, + src_width, src_height, + parity, tff, is_field_end, clip_max); +} + +__global__ void bwdif_uchar2(uchar2 *dst, + cudaTextureObject_t prev, + cudaTextureObject_t cur, + cudaTextureObject_t next, + int dst_width, int dst_height, int dst_pitch, + int src_width, int src_height, + int parity, int tff, int is_field_end, int clip_max) +{ + bwdif_double(dst, prev, cur, next, + dst_width, dst_height, dst_pitch, + src_width, src_height, + parity, tff, is_field_end, clip_max); +} + +__global__ void bwdif_ushort2(ushort2 *dst, + cudaTextureObject_t prev, + cudaTextureObject_t cur, + cudaTextureObject_t next, + int dst_width, int dst_height, int dst_pitch, + int src_width, int src_height, + int parity, int tff, int is_field_end, int clip_max) +{ + bwdif_double(dst, prev, cur, next, + dst_width, dst_height, dst_pitch, + src_width, src_height, + parity, tff, is_field_end, clip_max); +} + +} /* extern "C" */ From 6c418ae25ede55fa1f896a7449ebaffd18886002 Mon Sep 17 00:00:00 2001 From: Timo Rothenpieler Date: Fri, 16 Jun 2023 20:23:26 +0200 Subject: [PATCH 1494/2172] Revert "lavc/nvenc: handle frame durations and AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE" The implementation is flawed in that the frame opaque data is not in fact correctly reordered along with the packets, but is being output in packet input order, just like the dts are. This reverts commit 35538097038fd1e36577306d3165f38c8fa02466. --- libavcodec/nvenc.c | 116 +++++++--------------------------------- libavcodec/nvenc.h | 2 +- libavcodec/nvenc_av1.c | 3 +- libavcodec/nvenc_h264.c | 3 +- libavcodec/nvenc_hevc.c | 3 +- 5 files changed, 23 insertions(+), 104 deletions(-) diff --git a/libavcodec/nvenc.c b/libavcodec/nvenc.c index 7874cb887b7..177e23d7e42 100644 --- a/libavcodec/nvenc.c +++ b/libavcodec/nvenc.c @@ -28,7 +28,6 @@ #include "av1.h" #endif -#include "libavutil/buffer.h" #include "libavutil/hwcontext_cuda.h" #include "libavutil/hwcontext.h" #include "libavutil/cuda_check.h" @@ -168,27 +167,6 @@ static int nvenc_print_error(AVCodecContext *avctx, NVENCSTATUS err, return ret; } -typedef struct FrameData { - int64_t pts; - int64_t duration; -#if FF_API_REORDERED_OPAQUE - int64_t reordered_opaque; -#endif - - void *frame_opaque; - AVBufferRef *frame_opaque_ref; -} FrameData; - -static void reorder_queue_flush(AVFifo *queue) -{ - FrameData fd; - - av_assert0(queue); - - while (av_fifo_read(queue, &fd, 1) >= 0) - av_buffer_unref(&fd.frame_opaque_ref); -} - typedef struct GUIDTuple { const GUID guid; int flags; @@ -1789,8 +1767,8 @@ static av_cold int nvenc_setup_surfaces(AVCodecContext *avctx) if (!ctx->surfaces) return AVERROR(ENOMEM); - ctx->reorder_queue = av_fifo_alloc2(ctx->nb_surfaces, sizeof(FrameData), 0); - if (!ctx->reorder_queue) + ctx->timestamp_list = av_fifo_alloc2(ctx->nb_surfaces, sizeof(int64_t), 0); + if (!ctx->timestamp_list) return AVERROR(ENOMEM); ctx->unused_surface_queue = av_fifo_alloc2(ctx->nb_surfaces, sizeof(NvencSurface*), 0); @@ -1874,11 +1852,7 @@ av_cold int ff_nvenc_encode_close(AVCodecContext *avctx) p_nvenc->nvEncEncodePicture(ctx->nvencoder, ¶ms); } - if (ctx->reorder_queue) { - reorder_queue_flush(ctx->reorder_queue); - av_fifo_freep2(&ctx->reorder_queue); - } - + av_fifo_freep2(&ctx->timestamp_list); av_fifo_freep2(&ctx->output_surface_ready_queue); av_fifo_freep2(&ctx->output_surface_queue); av_fifo_freep2(&ctx->unused_surface_queue); @@ -2222,53 +2196,18 @@ static void nvenc_codec_specific_pic_params(AVCodecContext *avctx, } } -static void reorder_queue_enqueue(AVFifo *queue, const AVCodecContext *avctx, - const AVFrame *frame, AVBufferRef **opaque_ref) +static inline void timestamp_queue_enqueue(AVFifo *queue, int64_t timestamp) { - FrameData fd; - - fd.pts = frame->pts; - fd.duration = frame->duration; -#if FF_API_REORDERED_OPAQUE -FF_DISABLE_DEPRECATION_WARNINGS - fd.reordered_opaque = frame->reordered_opaque; -FF_ENABLE_DEPRECATION_WARNINGS -#endif - fd.frame_opaque = frame->opaque; - fd.frame_opaque_ref = *opaque_ref; - - *opaque_ref = NULL; - - av_fifo_write(queue, &fd, 1); + av_fifo_write(queue, ×tamp, 1); } -static int64_t reorder_queue_dequeue(AVFifo *queue, AVCodecContext *avctx, - AVPacket *pkt) +static inline int64_t timestamp_queue_dequeue(AVFifo *queue) { - FrameData fd; - + int64_t timestamp = AV_NOPTS_VALUE; // The following call might fail if the queue is empty. - if (av_fifo_read(queue, &fd, 1) < 0) - return AV_NOPTS_VALUE; - - if (pkt) { -#if FF_API_REORDERED_OPAQUE -FF_DISABLE_DEPRECATION_WARNINGS - avctx->reordered_opaque = fd.reordered_opaque; -FF_ENABLE_DEPRECATION_WARNINGS -#endif - pkt->duration = fd.duration; + av_fifo_read(queue, ×tamp, 1); - if (avctx->flags & AV_CODEC_FLAG_COPY_OPAQUE) { - pkt->opaque = fd.frame_opaque; - pkt->opaque_ref = fd.frame_opaque_ref; - fd.frame_opaque_ref = NULL; - } - } - - av_buffer_unref(&fd.frame_opaque_ref); - - return fd.pts; + return timestamp; } static int nvenc_set_timestamp(AVCodecContext *avctx, @@ -2276,15 +2215,12 @@ static int nvenc_set_timestamp(AVCodecContext *avctx, AVPacket *pkt) { NvencContext *ctx = avctx->priv_data; - int64_t dts; pkt->pts = params->outputTimeStamp; - dts = reorder_queue_dequeue(ctx->reorder_queue, avctx, pkt); - if (avctx->codec_descriptor->props & AV_CODEC_PROP_REORDER) { FF_DISABLE_DEPRECATION_WARNINGS - pkt->dts = dts - + pkt->dts = timestamp_queue_dequeue(ctx->timestamp_list) - #if FF_API_TICKS_PER_FRAME FFMAX(avctx->ticks_per_frame, 1) * #endif @@ -2386,7 +2322,7 @@ static int process_output_surface(AVCodecContext *avctx, AVPacket *pkt, NvencSur return 0; error: - reorder_queue_dequeue(ctx->reorder_queue, avctx, NULL); + timestamp_queue_dequeue(ctx->timestamp_list); error2: return res; @@ -2616,8 +2552,6 @@ static int nvenc_send_frame(AVCodecContext *avctx, const AVFrame *frame) int sei_count = 0; int i; - AVBufferRef *opaque_ref = NULL; - NvencContext *ctx = avctx->priv_data; NvencDynLoadFunctions *dl_fn = &ctx->nvenc_dload_funcs; NV_ENCODE_API_FUNCTION_LIST *p_nvenc = &dl_fn->nvenc_funcs; @@ -2685,17 +2619,9 @@ static int nvenc_send_frame(AVCodecContext *avctx, const AVFrame *frame) pic_params.encodePicFlags = NV_ENC_PIC_FLAG_EOS; } - // make a reference for enqueing in the reorder queue here, - // so that reorder_queue_enqueue() cannot fail - if (frame && frame->opaque_ref && avctx->flags & AV_CODEC_FLAG_COPY_OPAQUE) { - opaque_ref = av_buffer_ref(frame->opaque_ref); - if (!opaque_ref) - return AVERROR(ENOMEM); - } - res = nvenc_push_context(avctx); if (res < 0) - goto opaque_ref_fail; + return res; nv_status = p_nvenc->nvEncEncodePicture(ctx->nvencoder, &pic_params); @@ -2704,17 +2630,17 @@ static int nvenc_send_frame(AVCodecContext *avctx, const AVFrame *frame) res = nvenc_pop_context(avctx); if (res < 0) - goto opaque_ref_fail; + return res; if (nv_status != NV_ENC_SUCCESS && - nv_status != NV_ENC_ERR_NEED_MORE_INPUT) { - res = nvenc_print_error(avctx, nv_status, "EncodePicture failed!"); - goto opaque_ref_fail; - } + nv_status != NV_ENC_ERR_NEED_MORE_INPUT) + return nvenc_print_error(avctx, nv_status, "EncodePicture failed!"); if (frame && frame->buf[0]) { av_fifo_write(ctx->output_surface_queue, &in_surf, 1); - reorder_queue_enqueue(ctx->reorder_queue, avctx, frame, &opaque_ref); + + if (avctx->codec_descriptor->props & AV_CODEC_PROP_REORDER) + timestamp_queue_enqueue(ctx->timestamp_list, frame->pts); } /* all the pending buffers are now ready for output */ @@ -2724,10 +2650,6 @@ static int nvenc_send_frame(AVCodecContext *avctx, const AVFrame *frame) } return 0; - -opaque_ref_fail: - av_buffer_unref(&opaque_ref); - return res; } int ff_nvenc_receive_packet(AVCodecContext *avctx, AVPacket *pkt) @@ -2786,5 +2708,5 @@ av_cold void ff_nvenc_encode_flush(AVCodecContext *avctx) NvencContext *ctx = avctx->priv_data; nvenc_send_frame(avctx, NULL); - reorder_queue_flush(ctx->reorder_queue); + av_fifo_reset2(ctx->timestamp_list); } diff --git a/libavcodec/nvenc.h b/libavcodec/nvenc.h index 97aad80cd06..55ec1992115 100644 --- a/libavcodec/nvenc.h +++ b/libavcodec/nvenc.h @@ -176,7 +176,7 @@ typedef struct NvencContext AVFifo *unused_surface_queue; AVFifo *output_surface_queue; AVFifo *output_surface_ready_queue; - AVFifo *reorder_queue; + AVFifo *timestamp_list; NV_ENC_SEI_PAYLOAD *sei_data; int sei_data_size; diff --git a/libavcodec/nvenc_av1.c b/libavcodec/nvenc_av1.c index 2b349c7b61f..2ed99d948b6 100644 --- a/libavcodec/nvenc_av1.c +++ b/libavcodec/nvenc_av1.c @@ -181,8 +181,7 @@ const FFCodec ff_av1_nvenc_encoder = { .defaults = defaults, .p.pix_fmts = ff_nvenc_pix_fmts, .p.capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_HARDWARE | - AV_CODEC_CAP_ENCODER_FLUSH | AV_CODEC_CAP_DR1 | - AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE, + AV_CODEC_CAP_ENCODER_FLUSH | AV_CODEC_CAP_DR1, .caps_internal = FF_CODEC_CAP_NOT_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP, .p.wrapper_name = "nvenc", diff --git a/libavcodec/nvenc_h264.c b/libavcodec/nvenc_h264.c index 698615855bf..dfa8cce72e8 100644 --- a/libavcodec/nvenc_h264.c +++ b/libavcodec/nvenc_h264.c @@ -244,8 +244,7 @@ const FFCodec ff_h264_nvenc_encoder = { .p.priv_class = &h264_nvenc_class, .defaults = defaults, .p.capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_HARDWARE | - AV_CODEC_CAP_ENCODER_FLUSH | AV_CODEC_CAP_DR1 | - AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE, + AV_CODEC_CAP_ENCODER_FLUSH | AV_CODEC_CAP_DR1, .caps_internal = FF_CODEC_CAP_NOT_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP, .p.pix_fmts = ff_nvenc_pix_fmts, diff --git a/libavcodec/nvenc_hevc.c b/libavcodec/nvenc_hevc.c index d99077f1705..ca58a84f223 100644 --- a/libavcodec/nvenc_hevc.c +++ b/libavcodec/nvenc_hevc.c @@ -226,8 +226,7 @@ const FFCodec ff_hevc_nvenc_encoder = { .defaults = defaults, .p.pix_fmts = ff_nvenc_pix_fmts, .p.capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_HARDWARE | - AV_CODEC_CAP_ENCODER_FLUSH | AV_CODEC_CAP_DR1 | - AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE, + AV_CODEC_CAP_ENCODER_FLUSH | AV_CODEC_CAP_DR1, .caps_internal = FF_CODEC_CAP_NOT_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP, .p.wrapper_name = "nvenc", From 16fdb48e0dead244bddf3a0ae9d459d02b4443b1 Mon Sep 17 00:00:00 2001 From: Timo Rothenpieler Date: Fri, 16 Jun 2023 21:35:45 +0200 Subject: [PATCH 1495/2172] avcodec/nvenc: handle frame durations and AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE --- libavcodec/nvenc.c | 81 +++++++++++++++++++++++++++++++++++++++++ libavcodec/nvenc.h | 17 +++++++++ libavcodec/nvenc_av1.c | 3 +- libavcodec/nvenc_h264.c | 3 +- libavcodec/nvenc_hevc.c | 3 +- 5 files changed, 104 insertions(+), 3 deletions(-) diff --git a/libavcodec/nvenc.c b/libavcodec/nvenc.c index 177e23d7e42..d56ebc68e27 100644 --- a/libavcodec/nvenc.c +++ b/libavcodec/nvenc.c @@ -971,6 +971,10 @@ static av_cold int nvenc_recalc_surfaces(AVCodecContext *avctx) ctx->nb_surfaces = FFMAX(1, FFMIN(MAX_REGISTERED_FRAMES, ctx->nb_surfaces)); ctx->async_depth = FFMIN(ctx->async_depth, ctx->nb_surfaces - 1); + // Output in the worst case will only start when the surface buffer is completely full. + // Hence we need to keep at least the max amount of surfaces plus the max reorder delay around. + ctx->frame_data_array_nb = ctx->nb_surfaces + ctx->encode_config.frameIntervalP - 1; + return 0; } @@ -1767,6 +1771,10 @@ static av_cold int nvenc_setup_surfaces(AVCodecContext *avctx) if (!ctx->surfaces) return AVERROR(ENOMEM); + ctx->frame_data_array = av_calloc(ctx->frame_data_array_nb, sizeof(*ctx->frame_data_array)); + if (!ctx->frame_data_array) + return AVERROR(ENOMEM); + ctx->timestamp_list = av_fifo_alloc2(ctx->nb_surfaces, sizeof(int64_t), 0); if (!ctx->timestamp_list) return AVERROR(ENOMEM); @@ -1857,6 +1865,12 @@ av_cold int ff_nvenc_encode_close(AVCodecContext *avctx) av_fifo_freep2(&ctx->output_surface_queue); av_fifo_freep2(&ctx->unused_surface_queue); + if (ctx->frame_data_array) { + for (i = 0; i < ctx->nb_surfaces; i++) + av_buffer_unref(&ctx->frame_data_array[i].frame_opaque_ref); + av_freep(&ctx->frame_data_array); + } + if (ctx->surfaces && (avctx->pix_fmt == AV_PIX_FMT_CUDA || avctx->pix_fmt == AV_PIX_FMT_D3D11)) { for (i = 0; i < ctx->nb_registered_frames; i++) { if (ctx->registered_frames[i].mapped) @@ -2233,6 +2247,65 @@ FF_ENABLE_DEPRECATION_WARNINGS return 0; } +static int nvenc_store_frame_data(AVCodecContext *avctx, NV_ENC_PIC_PARAMS *pic_params, const AVFrame *frame) +{ + NvencContext *ctx = avctx->priv_data; + int res = 0; + + int idx = ctx->frame_data_array_pos; + NvencFrameData *frame_data = &ctx->frame_data_array[idx]; + + // in case the encoder got reconfigured, there might be leftovers + av_buffer_unref(&frame_data->frame_opaque_ref); + + if (frame && frame->opaque_ref && avctx->flags & AV_CODEC_FLAG_COPY_OPAQUE) { + frame_data->frame_opaque_ref = av_buffer_ref(frame->opaque_ref); + if (!frame_data->frame_opaque_ref) + return AVERROR(ENOMEM); + } + + frame_data->duration = frame->duration; + frame_data->frame_opaque = frame->opaque; + +#if FF_API_REORDERED_OPAQUE +FF_DISABLE_DEPRECATION_WARNINGS + frame_data->reordered_opaque = frame->reordered_opaque; +FF_ENABLE_DEPRECATION_WARNINGS +#endif + + ctx->frame_data_array_pos = (ctx->frame_data_array_pos + 1) % ctx->frame_data_array_nb; + pic_params->inputDuration = idx; + + return res; +} + +static int nvenc_retrieve_frame_data(AVCodecContext *avctx, NV_ENC_LOCK_BITSTREAM *lock_params, AVPacket *pkt) +{ + NvencContext *ctx = avctx->priv_data; + int res = 0; + + int idx = lock_params->outputDuration; + NvencFrameData *frame_data = &ctx->frame_data_array[idx]; + + pkt->duration = frame_data->duration; + +#if FF_API_REORDERED_OPAQUE +FF_DISABLE_DEPRECATION_WARNINGS + avctx->reordered_opaque = frame_data->reordered_opaque; +FF_ENABLE_DEPRECATION_WARNINGS +#endif + + if (avctx->flags & AV_CODEC_FLAG_COPY_OPAQUE) { + pkt->opaque = frame_data->frame_opaque; + pkt->opaque_ref = frame_data->frame_opaque_ref; + frame_data->frame_opaque_ref = NULL; + } + + av_buffer_unref(&frame_data->frame_opaque_ref); + + return res; +} + static int process_output_surface(AVCodecContext *avctx, AVPacket *pkt, NvencSurface *tmpoutsurf) { NvencContext *ctx = avctx->priv_data; @@ -2319,6 +2392,10 @@ static int process_output_surface(AVCodecContext *avctx, AVPacket *pkt, NvencSur if (res < 0) goto error2; + res = nvenc_retrieve_frame_data(avctx, &lock_params, pkt); + if (res < 0) + goto error2; + return 0; error: @@ -2614,6 +2691,10 @@ static int nvenc_send_frame(AVCodecContext *avctx, const AVFrame *frame) sei_count = res; } + res = nvenc_store_frame_data(avctx, &pic_params, frame); + if (res < 0) + return res; + nvenc_codec_specific_pic_params(avctx, &pic_params, ctx->sei_data, sei_count); } else { pic_params.encodePicFlags = NV_ENC_PIC_FLAG_EOS; diff --git a/libavcodec/nvenc.h b/libavcodec/nvenc.h index 55ec1992115..3a4b456a41d 100644 --- a/libavcodec/nvenc.h +++ b/libavcodec/nvenc.h @@ -31,6 +31,7 @@ typedef void ID3D11Device; #include #include "compat/cuda/dynlink_loader.h" +#include "libavutil/buffer.h" #include "libavutil/fifo.h" #include "libavutil/opt.h" #include "hwconfig.h" @@ -95,6 +96,18 @@ typedef struct NvencSurface NV_ENC_BUFFER_FORMAT format; } NvencSurface; +typedef struct NvencFrameData +{ + int64_t duration; + +#if FF_API_REORDERED_OPAQUE + int64_t reordered_opaque; +#endif + + void *frame_opaque; + AVBufferRef *frame_opaque_ref; +} NvencFrameData; + typedef struct NvencDynLoadFunctions { CudaFunctions *cuda_dl; @@ -173,6 +186,10 @@ typedef struct NvencContext int nb_surfaces; NvencSurface *surfaces; + NvencFrameData *frame_data_array; + int frame_data_array_nb; + int frame_data_array_pos; + AVFifo *unused_surface_queue; AVFifo *output_surface_queue; AVFifo *output_surface_ready_queue; diff --git a/libavcodec/nvenc_av1.c b/libavcodec/nvenc_av1.c index 2ed99d948b6..2b349c7b61f 100644 --- a/libavcodec/nvenc_av1.c +++ b/libavcodec/nvenc_av1.c @@ -181,7 +181,8 @@ const FFCodec ff_av1_nvenc_encoder = { .defaults = defaults, .p.pix_fmts = ff_nvenc_pix_fmts, .p.capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_HARDWARE | - AV_CODEC_CAP_ENCODER_FLUSH | AV_CODEC_CAP_DR1, + AV_CODEC_CAP_ENCODER_FLUSH | AV_CODEC_CAP_DR1 | + AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE, .caps_internal = FF_CODEC_CAP_NOT_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP, .p.wrapper_name = "nvenc", diff --git a/libavcodec/nvenc_h264.c b/libavcodec/nvenc_h264.c index dfa8cce72e8..698615855bf 100644 --- a/libavcodec/nvenc_h264.c +++ b/libavcodec/nvenc_h264.c @@ -244,7 +244,8 @@ const FFCodec ff_h264_nvenc_encoder = { .p.priv_class = &h264_nvenc_class, .defaults = defaults, .p.capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_HARDWARE | - AV_CODEC_CAP_ENCODER_FLUSH | AV_CODEC_CAP_DR1, + AV_CODEC_CAP_ENCODER_FLUSH | AV_CODEC_CAP_DR1 | + AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE, .caps_internal = FF_CODEC_CAP_NOT_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP, .p.pix_fmts = ff_nvenc_pix_fmts, diff --git a/libavcodec/nvenc_hevc.c b/libavcodec/nvenc_hevc.c index ca58a84f223..d99077f1705 100644 --- a/libavcodec/nvenc_hevc.c +++ b/libavcodec/nvenc_hevc.c @@ -226,7 +226,8 @@ const FFCodec ff_hevc_nvenc_encoder = { .defaults = defaults, .p.pix_fmts = ff_nvenc_pix_fmts, .p.capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_HARDWARE | - AV_CODEC_CAP_ENCODER_FLUSH | AV_CODEC_CAP_DR1, + AV_CODEC_CAP_ENCODER_FLUSH | AV_CODEC_CAP_DR1 | + AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE, .caps_internal = FF_CODEC_CAP_NOT_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP, .p.wrapper_name = "nvenc", From da2af70ffad672b9268551437571d0b63543d7a2 Mon Sep 17 00:00:00 2001 From: James Almer Date: Thu, 15 Jun 2023 10:10:14 -0300 Subject: [PATCH 1496/2172] avcodec/evc_parser: export framerate to the AVCodecContext Signed-off-by: James Almer --- libavcodec/evc_parse.c | 15 +++++++-------- libavcodec/evc_parser.c | 1 + 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/libavcodec/evc_parse.c b/libavcodec/evc_parse.c index cb6c6dc3119..c8d3c921c8a 100644 --- a/libavcodec/evc_parse.c +++ b/libavcodec/evc_parse.c @@ -605,14 +605,13 @@ int ff_evc_parse_nal_unit(EVCParserContext *ctx, const uint8_t *buf, int buf_siz if (sps->profile_idc == 1) ctx->profile = FF_PROFILE_EVC_MAIN; else ctx->profile = FF_PROFILE_EVC_BASELINE; - if (sps->vui_parameters_present_flag) { - if (sps->vui_parameters.timing_info_present_flag) { - int64_t num = sps->vui_parameters.num_units_in_tick; - int64_t den = sps->vui_parameters.time_scale; - if (num != 0 && den != 0) - av_reduce(&ctx->framerate.den, &ctx->framerate.num, num, den, 1 << 30); - } - } + if (sps->vui_parameters_present_flag && sps->vui_parameters.timing_info_present_flag) { + int64_t num = sps->vui_parameters.num_units_in_tick; + int64_t den = sps->vui_parameters.time_scale; + if (num != 0 && den != 0) + av_reduce(&ctx->framerate.den, &ctx->framerate.num, num, den, 1 << 30); + } else + ctx->framerate = (AVRational) { 0, 1 }; bit_depth = sps->bit_depth_chroma_minus8 + 8; ctx->format = AV_PIX_FMT_NONE; diff --git a/libavcodec/evc_parser.c b/libavcodec/evc_parser.c index 639dcbd1353..5feb673b044 100644 --- a/libavcodec/evc_parser.c +++ b/libavcodec/evc_parser.c @@ -71,6 +71,7 @@ static int parse_nal_units(AVCodecParserContext *s, AVCodecContext *avctx, const s->format = ctx->format; + avctx->framerate = ctx->framerate; avctx->gop_size = ctx->gop_size; avctx->delay = ctx->delay; avctx->profile = ctx->profile; From 57879b23bc77013ac6832d19b62203975718f557 Mon Sep 17 00:00:00 2001 From: James Almer Date: Thu, 15 Jun 2023 10:33:25 -0300 Subject: [PATCH 1497/2172] avcodec/evc_parse: zero sps, pps and sh structs Otherwise stale values may remain in place. Signed-off-by: James Almer --- libavcodec/evc_parse.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/libavcodec/evc_parse.c b/libavcodec/evc_parse.c index c8d3c921c8a..6ecfbccfde0 100644 --- a/libavcodec/evc_parse.c +++ b/libavcodec/evc_parse.c @@ -200,6 +200,8 @@ EVCParserSPS *ff_evc_parse_sps(EVCParserContext *ctx, const uint8_t *bs, int bs_ } sps = ctx->sps[sps_seq_parameter_set_id]; + memset(sps, 0, sizeof(*sps)); + sps->sps_seq_parameter_set_id = sps_seq_parameter_set_id; // the Baseline profile is indicated by profile_idc eqal to 0 @@ -360,6 +362,7 @@ EVCParserPPS *ff_evc_parse_pps(EVCParserContext *ctx, const uint8_t *bs, int bs_ } pps = ctx->pps[pps_pic_parameter_set_id]; + memset(pps, 0, sizeof(*pps)); pps->pps_pic_parameter_set_id = pps_pic_parameter_set_id; @@ -440,6 +443,7 @@ EVCParserSliceHeader *ff_evc_parse_slice_header(EVCParserContext *ctx, const uin } sh = ctx->slice_header[slice_pic_parameter_set_id]; + memset(sh, 0, sizeof(*sh)); pps = ctx->pps[slice_pic_parameter_set_id]; if(!pps) From 44f26315c82b03988b4867b05cbfdba01627ca58 Mon Sep 17 00:00:00 2001 From: James Almer Date: Thu, 15 Jun 2023 11:03:51 -0300 Subject: [PATCH 1498/2172] avcodec/evc_parse: use a local EVCParserSliceHeader when parsing slices There's no need to store EVC_MAX_PPS_COUNT amount of slice headers in EVCParserContext. Signed-off-by: James Almer --- libavcodec/evc_parse.c | 50 +++++++++++++++++------------------------ libavcodec/evc_parse.h | 4 ---- libavcodec/evc_parser.c | 2 -- 3 files changed, 21 insertions(+), 35 deletions(-) diff --git a/libavcodec/evc_parse.c b/libavcodec/evc_parse.c index 6ecfbccfde0..d45f703e1cf 100644 --- a/libavcodec/evc_parse.c +++ b/libavcodec/evc_parse.c @@ -419,40 +419,33 @@ EVCParserPPS *ff_evc_parse_pps(EVCParserContext *ctx, const uint8_t *bs, int bs_ } // @see ISO_IEC_23094-1 (7.3.2.6 Slice layer RBSP syntax) -EVCParserSliceHeader *ff_evc_parse_slice_header(EVCParserContext *ctx, const uint8_t *bs, int bs_size) +static int evc_parse_slice_header(EVCParserContext *ctx, EVCParserSliceHeader *sh, const uint8_t *bs, int bs_size) { GetBitContext gb; - EVCParserSliceHeader *sh; EVCParserPPS *pps; EVCParserSPS *sps; int num_tiles_in_slice = 0; int slice_pic_parameter_set_id; + int ret; - if (init_get_bits8(&gb, bs, bs_size) < 0) - return NULL; + if ((ret = init_get_bits8(&gb, bs, bs_size)) < 0) + return ret; slice_pic_parameter_set_id = get_ue_golomb(&gb); if (slice_pic_parameter_set_id < 0 || slice_pic_parameter_set_id >= EVC_MAX_PPS_COUNT) - return NULL; - - if(!ctx->slice_header[slice_pic_parameter_set_id]) { - if((ctx->slice_header[slice_pic_parameter_set_id] = av_malloc(sizeof(EVCParserSliceHeader))) == NULL) - return NULL; - } - - sh = ctx->slice_header[slice_pic_parameter_set_id]; - memset(sh, 0, sizeof(*sh)); + return AVERROR_INVALIDDATA; pps = ctx->pps[slice_pic_parameter_set_id]; if(!pps) - return NULL; + return AVERROR_INVALIDDATA; sps = ctx->sps[slice_pic_parameter_set_id]; if(!sps) - return NULL; + return AVERROR_INVALIDDATA; + memset(sh, 0, sizeof(*sh)); sh->slice_pic_parameter_set_id = slice_pic_parameter_set_id; if (!pps->single_tile_in_pic_flag) { @@ -540,7 +533,7 @@ EVCParserSliceHeader *ff_evc_parse_slice_header(EVCParserContext *ctx, const uin // If necessary, add the missing fields to the EVCParserSliceHeader structure // and then extend parser implementation - return sh; + return 0; } int ff_evc_parse_nal_unit(EVCParserContext *ctx, const uint8_t *buf, int buf_size, void *logctx) @@ -660,17 +653,17 @@ int ff_evc_parse_nal_unit(EVCParserContext *ctx, const uint8_t *buf, int buf_siz break; case EVC_IDR_NUT: // Coded slice of a IDR or non-IDR picture case EVC_NOIDR_NUT: { - EVCParserSliceHeader *sh; + EVCParserSliceHeader sh; EVCParserSPS *sps; - int slice_pic_parameter_set_id; + int ret; - sh = ff_evc_parse_slice_header(ctx, data, nalu_size); - if (!sh) { + ret = evc_parse_slice_header(ctx, &sh, data, nalu_size); + if (ret < 0) { av_log(logctx, AV_LOG_ERROR, "Slice header parsing error\n"); - return AVERROR_INVALIDDATA; + return ret; } - switch (sh->slice_type) { + switch (sh.slice_type) { case EVC_SLICE_TYPE_B: { ctx->pict_type = AV_PICTURE_TYPE_B; break; @@ -692,8 +685,7 @@ int ff_evc_parse_nal_unit(EVCParserContext *ctx, const uint8_t *buf, int buf_siz // POC (picture order count of the current picture) derivation // @see ISO/IEC 23094-1:2020(E) 8.3.1 Decoding process for picture order count - slice_pic_parameter_set_id = sh->slice_pic_parameter_set_id; - sps = ctx->sps[slice_pic_parameter_set_id]; + sps = ctx->sps[sh.slice_pic_parameter_set_id]; if (sps && sps->sps_pocs_flag) { @@ -709,20 +701,20 @@ int ff_evc_parse_nal_unit(EVCParserContext *ctx, const uint8_t *buf, int buf_siz int prevPicOrderCntMsb = ctx->poc.PicOrderCntVal - prevPicOrderCntLsb; - if ((sh->slice_pic_order_cnt_lsb < prevPicOrderCntLsb) && - ((prevPicOrderCntLsb - sh->slice_pic_order_cnt_lsb) >= (MaxPicOrderCntLsb / 2))) + if ((sh.slice_pic_order_cnt_lsb < prevPicOrderCntLsb) && + ((prevPicOrderCntLsb - sh.slice_pic_order_cnt_lsb) >= (MaxPicOrderCntLsb / 2))) PicOrderCntMsb = prevPicOrderCntMsb + MaxPicOrderCntLsb; - else if ((sh->slice_pic_order_cnt_lsb > prevPicOrderCntLsb) && - ((sh->slice_pic_order_cnt_lsb - prevPicOrderCntLsb) > (MaxPicOrderCntLsb / 2))) + else if ((sh.slice_pic_order_cnt_lsb > prevPicOrderCntLsb) && + ((sh.slice_pic_order_cnt_lsb - prevPicOrderCntLsb) > (MaxPicOrderCntLsb / 2))) PicOrderCntMsb = prevPicOrderCntMsb - MaxPicOrderCntLsb; else PicOrderCntMsb = prevPicOrderCntMsb; } - ctx->poc.PicOrderCntVal = PicOrderCntMsb + sh->slice_pic_order_cnt_lsb; + ctx->poc.PicOrderCntVal = PicOrderCntMsb + sh.slice_pic_order_cnt_lsb; } else { if (nalu_type == EVC_IDR_NUT) { diff --git a/libavcodec/evc_parse.h b/libavcodec/evc_parse.h index d74a3b51599..1c1b8ec0934 100644 --- a/libavcodec/evc_parse.h +++ b/libavcodec/evc_parse.h @@ -261,7 +261,6 @@ typedef struct EVCParserContext { //ParseContext pc; EVCParserSPS *sps[EVC_MAX_SPS_COUNT]; EVCParserPPS *pps[EVC_MAX_PPS_COUNT]; - EVCParserSliceHeader *slice_header[EVC_MAX_PPS_COUNT]; EVCParserPoc poc; @@ -349,9 +348,6 @@ EVCParserSPS *ff_evc_parse_sps(EVCParserContext *ctx, const uint8_t *bs, int bs_ // @see ISO_IEC_23094-1 (7.3.2.2 SPS RBSP syntax) EVCParserPPS *ff_evc_parse_pps(EVCParserContext *ctx, const uint8_t *bs, int bs_size); -// @see ISO_IEC_23094-1 (7.3.2.6 Slice layer RBSP syntax) -EVCParserSliceHeader *ff_evc_parse_slice_header(EVCParserContext *ctx, const uint8_t *bs, int bs_size); - int ff_evc_parse_nal_unit(EVCParserContext *ctx, const uint8_t *buf, int buf_size, void *logctx); #endif /* AVCODEC_EVC_PARSE_H */ diff --git a/libavcodec/evc_parser.c b/libavcodec/evc_parser.c index 5feb673b044..072fe41bf12 100644 --- a/libavcodec/evc_parser.c +++ b/libavcodec/evc_parser.c @@ -209,10 +209,8 @@ static void evc_parser_close(AVCodecParserContext *s) for(int i = 0; i < EVC_MAX_PPS_COUNT; i++) { EVCParserPPS *pps = ctx->pps[i]; - EVCParserSliceHeader *sh = ctx->slice_header[i]; av_freep(&pps); - av_freep(&sh); } } From 811460f5c2d32203aef1a6b7f15b3a5f831b107e Mon Sep 17 00:00:00 2001 From: James Almer Date: Thu, 15 Jun 2023 11:06:14 -0300 Subject: [PATCH 1499/2172] avcodec/evc_parse: use the correct sps when parsing slice headers Signed-off-by: James Almer --- libavcodec/evc_parse.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/libavcodec/evc_parse.c b/libavcodec/evc_parse.c index d45f703e1cf..095598e940e 100644 --- a/libavcodec/evc_parse.c +++ b/libavcodec/evc_parse.c @@ -441,7 +441,7 @@ static int evc_parse_slice_header(EVCParserContext *ctx, EVCParserSliceHeader *s if(!pps) return AVERROR_INVALIDDATA; - sps = ctx->sps[slice_pic_parameter_set_id]; + sps = ctx->sps[pps->pps_seq_parameter_set_id]; if(!sps) return AVERROR_INVALIDDATA; @@ -654,7 +654,8 @@ int ff_evc_parse_nal_unit(EVCParserContext *ctx, const uint8_t *buf, int buf_siz case EVC_IDR_NUT: // Coded slice of a IDR or non-IDR picture case EVC_NOIDR_NUT: { EVCParserSliceHeader sh; - EVCParserSPS *sps; + const EVCParserSPS *sps; + const EVCParserPPS *pps; int ret; ret = evc_parse_slice_header(ctx, &sh, data, nalu_size); @@ -685,9 +686,11 @@ int ff_evc_parse_nal_unit(EVCParserContext *ctx, const uint8_t *buf, int buf_siz // POC (picture order count of the current picture) derivation // @see ISO/IEC 23094-1:2020(E) 8.3.1 Decoding process for picture order count - sps = ctx->sps[sh.slice_pic_parameter_set_id]; + pps = ctx->pps[sh.slice_pic_parameter_set_id]; + sps = ctx->sps[pps->pps_seq_parameter_set_id]; + av_assert0(sps && pps); - if (sps && sps->sps_pocs_flag) { + if (sps->sps_pocs_flag) { int PicOrderCntMsb = 0; ctx->poc.prevPicOrderCntVal = ctx->poc.PicOrderCntVal; From 46a9be01b8c200636fb3ebbe43f209ae27b26dbc Mon Sep 17 00:00:00 2001 From: James Almer Date: Thu, 15 Jun 2023 10:39:44 -0300 Subject: [PATCH 1500/2172] avcodec/evc_parse: free pps struct on parsing failure Prevents future checks for their presence from succeeding. Signed-off-by: James Almer --- libavcodec/evc_parse.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/libavcodec/evc_parse.c b/libavcodec/evc_parse.c index 095598e940e..1d8757b231e 100644 --- a/libavcodec/evc_parse.c +++ b/libavcodec/evc_parse.c @@ -367,8 +367,10 @@ EVCParserPPS *ff_evc_parse_pps(EVCParserContext *ctx, const uint8_t *bs, int bs_ pps->pps_pic_parameter_set_id = pps_pic_parameter_set_id; pps->pps_seq_parameter_set_id = get_ue_golomb(&gb); - if (pps->pps_seq_parameter_set_id >= EVC_MAX_SPS_COUNT) + if (pps->pps_seq_parameter_set_id >= EVC_MAX_SPS_COUNT) { + av_freep(&ctx->pps[pps_pic_parameter_set_id]); return NULL; + } pps->num_ref_idx_default_active_minus1[0] = get_ue_golomb(&gb); pps->num_ref_idx_default_active_minus1[1] = get_ue_golomb(&gb); From 9fc1d9adc8d05056ea53522c34ae4953ccdb7c59 Mon Sep 17 00:00:00 2001 From: James Almer Date: Thu, 15 Jun 2023 11:13:48 -0300 Subject: [PATCH 1501/2172] avcodec/evc_parse: make freeing EVCParserContext buffers a shared function Signed-off-by: James Almer --- libavcodec/evc_parse.c | 7 +++++++ libavcodec/evc_parse.h | 2 ++ libavcodec/evc_parser.c | 11 +---------- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/libavcodec/evc_parse.c b/libavcodec/evc_parse.c index 1d8757b231e..44be5c52919 100644 --- a/libavcodec/evc_parse.c +++ b/libavcodec/evc_parse.c @@ -765,3 +765,10 @@ int ff_evc_parse_nal_unit(EVCParserContext *ctx, const uint8_t *buf, int buf_siz return 0; } +void ff_evc_parse_free(EVCParserContext *ctx) { + for (int i = 0; i < EVC_MAX_SPS_COUNT; i++) + av_freep(&ctx->sps[i]); + + for (int i = 0; i < EVC_MAX_PPS_COUNT; i++) + av_freep(&ctx->pps[i]); +} diff --git a/libavcodec/evc_parse.h b/libavcodec/evc_parse.h index 1c1b8ec0934..9eabc2f7a4b 100644 --- a/libavcodec/evc_parse.h +++ b/libavcodec/evc_parse.h @@ -350,4 +350,6 @@ EVCParserPPS *ff_evc_parse_pps(EVCParserContext *ctx, const uint8_t *bs, int bs_ int ff_evc_parse_nal_unit(EVCParserContext *ctx, const uint8_t *buf, int buf_size, void *logctx); +void ff_evc_parse_free(EVCParserContext *ctx); + #endif /* AVCODEC_EVC_PARSE_H */ diff --git a/libavcodec/evc_parser.c b/libavcodec/evc_parser.c index 072fe41bf12..c85b8f89e71 100644 --- a/libavcodec/evc_parser.c +++ b/libavcodec/evc_parser.c @@ -202,16 +202,7 @@ static void evc_parser_close(AVCodecParserContext *s) { EVCParserContext *ctx = s->priv_data; - for(int i = 0; i < EVC_MAX_SPS_COUNT; i++) { - EVCParserSPS *sps = ctx->sps[i]; - av_freep(&sps); - } - - for(int i = 0; i < EVC_MAX_PPS_COUNT; i++) { - EVCParserPPS *pps = ctx->pps[i]; - - av_freep(&pps); - } + ff_evc_parse_free(ctx); } const AVCodecParser ff_evc_parser = { From b1d0b59d81bc36e333572d36f878fc6735be63ad Mon Sep 17 00:00:00 2001 From: James Almer Date: Thu, 15 Jun 2023 11:35:22 -0300 Subject: [PATCH 1502/2172] avcodec/evc_frame_merge_bsf: check for av_memdup() failure Signed-off-by: James Almer --- libavcodec/evc_frame_merge_bsf.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/libavcodec/evc_frame_merge_bsf.c b/libavcodec/evc_frame_merge_bsf.c index d2746a1ef6a..fbb344490a8 100644 --- a/libavcodec/evc_frame_merge_bsf.c +++ b/libavcodec/evc_frame_merge_bsf.c @@ -61,6 +61,7 @@ static void evc_frame_merge_flush(AVBSFContext *bsf) EVCFMergeContext *ctx = bsf->priv_data; av_packet_unref(ctx->in); + ctx->au_buffer.data_size = 0; } static int evc_frame_merge_filter(AVBSFContext *bsf, AVPacket *out) @@ -117,9 +118,13 @@ static int evc_frame_merge_filter(AVBSFContext *bsf, AVPacket *out) if (au_end_found) { uint8_t *data = av_memdup(ctx->au_buffer.data, ctx->au_buffer.data_size); - err = av_packet_from_data(out, data, ctx->au_buffer.data_size); + size_t data_size = ctx->au_buffer.data_size; ctx->au_buffer.data_size = 0; + if (!data) + return AVERROR(ENOMEM); + + err = av_packet_from_data(out, data, data_size); } else err = AVERROR(EAGAIN); From f24064e6276bef326d708bef595f53bc747cb998 Mon Sep 17 00:00:00 2001 From: James Almer Date: Thu, 15 Jun 2023 11:14:07 -0300 Subject: [PATCH 1503/2172] avcodec/evc_frame_merge_bsf: free EVCFMergeContext on flush and close Signed-off-by: James Almer --- libavcodec/evc_frame_merge_bsf.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/libavcodec/evc_frame_merge_bsf.c b/libavcodec/evc_frame_merge_bsf.c index fbb344490a8..7cc701f5c55 100644 --- a/libavcodec/evc_frame_merge_bsf.c +++ b/libavcodec/evc_frame_merge_bsf.c @@ -60,6 +60,7 @@ static void evc_frame_merge_flush(AVBSFContext *bsf) { EVCFMergeContext *ctx = bsf->priv_data; + ff_evc_parse_free(&ctx->parser_ctx); av_packet_unref(ctx->in); ctx->au_buffer.data_size = 0; } @@ -129,7 +130,7 @@ static int evc_frame_merge_filter(AVBSFContext *bsf, AVPacket *out) err = AVERROR(EAGAIN); if (err < 0 && err != AVERROR(EAGAIN)) - evc_frame_merge_flush(bsf); + ctx->au_buffer.data_size = 0; return err; } @@ -154,6 +155,7 @@ static void evc_frame_merge_close(AVBSFContext *bsf) EVCFMergeContext *ctx = bsf->priv_data; av_packet_free(&ctx->in); + ff_evc_parse_free(&ctx->parser_ctx); ctx->au_buffer.capacity = 0; av_freep(&ctx->au_buffer.data); From be91c5c80d8c66a5a39d52c21f9094c9c455ec84 Mon Sep 17 00:00:00 2001 From: James Almer Date: Sat, 17 Jun 2023 10:16:45 -0300 Subject: [PATCH 1504/2172] configure: fix evc related dependencies Signed-off-by: James Almer --- configure | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/configure b/configure index 0c77d8e1fe7..1eb8047cd68 100755 --- a/configure +++ b/configure @@ -2769,6 +2769,7 @@ dovi_rpu_select="golomb" dnn_suggest="libtensorflow libopenvino" dnn_deps="avformat swscale" error_resilience_select="me_cmp" +evcparse_select="golomb" faandct_deps="faan" faandct_select="fdctdsp" faanidct_deps="faan" @@ -3322,7 +3323,7 @@ av1_amf_encoder_deps="amf" # parsers aac_parser_select="adts_header mpeg4audio" av1_parser_select="cbs_av1" -evc_parser_select="golomb evcparse" +evc_parser_select="evcparse" h264_parser_select="golomb h264dsp h264parse h264_sei" hevc_parser_select="hevcparse hevc_sei" mpegaudio_parser_select="mpegaudioheader" @@ -3336,6 +3337,7 @@ av1_frame_split_bsf_select="cbs_av1" av1_metadata_bsf_select="cbs_av1" dts2pts_bsf_select="cbs_h264 h264parse" eac3_core_bsf_select="ac3_parser" +evc_frame_merge_bsf_select="evcparse" filter_units_bsf_select="cbs" h264_metadata_bsf_deps="const_nan" h264_metadata_bsf_select="cbs_h264" @@ -3490,6 +3492,7 @@ dv_demuxer_select="dvprofile" dv_muxer_select="dvprofile" dxa_demuxer_select="riffdec" eac3_demuxer_select="ac3_parser" +evc_demuxer_select="evc_frame_merge_bsf evc_parser" f4v_muxer_select="mov_muxer" fifo_muxer_deps="threads" flac_demuxer_select="flac_parser" From dbc4c228902bc7845fdd0079a88972baaafdef8f Mon Sep 17 00:00:00 2001 From: James Almer Date: Sat, 17 Jun 2023 12:43:15 -0300 Subject: [PATCH 1505/2172] avcodec/evc_parse: add missing includes Fixes make checkheaders. Signed-off-by: James Almer --- libavcodec/evc_parse.h | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/libavcodec/evc_parse.h b/libavcodec/evc_parse.h index 9eabc2f7a4b..ee4b6c57088 100644 --- a/libavcodec/evc_parse.h +++ b/libavcodec/evc_parse.h @@ -24,6 +24,13 @@ #ifndef AVCODEC_EVC_PARSE_H #define AVCODEC_EVC_PARSE_H +#include + +#include "libavutil/intreadwrite.h" +#include "libavutil/log.h" +#include "libavutil/rational.h" +#include "evc.h" + #define EVC_MAX_QP_TABLE_SIZE 58 #define NUM_CPB 32 From f2349e7e628311bfbf217e821e4953052728863e Mon Sep 17 00:00:00 2001 From: Armin Hasitzka Date: Tue, 23 May 2023 11:16:59 +0100 Subject: [PATCH 1506/2172] avformat/hls: Forward stream metadata from subdemuxer Signed-off-by: Anton Khirnov --- libavformat/hls.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/libavformat/hls.c b/libavformat/hls.c index 4fff4405e8f..2a2fe28a540 100644 --- a/libavformat/hls.c +++ b/libavformat/hls.c @@ -1849,6 +1849,8 @@ static int set_stream_info_from_input_stream(AVStream *st, struct playlist *pls, // copy disposition st->disposition = ist->disposition; + av_dict_copy(&st->metadata, ist->metadata, 0); + // copy side data for (int i = 0; i < ist->nb_side_data; i++) { const AVPacketSideData *sd_src = &ist->side_data[i]; From 593e8c2c6ac0571df036c09bf103b7e58445d75d Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Sat, 17 Jun 2023 04:51:25 +0200 Subject: [PATCH 1507/2172] lavc/binkaudio: reset input packet on errors Make sure we don't repeatedly try to decode the same packet, making no progress and possibly causing an infinite loop. --- libavcodec/binkaudio.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/libavcodec/binkaudio.c b/libavcodec/binkaudio.c index f28ecba7603..265f93a8222 100644 --- a/libavcodec/binkaudio.c +++ b/libavcodec/binkaudio.c @@ -325,7 +325,7 @@ static int binkaudio_receive_frame(AVCodecContext *avctx, AVFrame *frame) if (s->ch_offset == 0) { frame->nb_samples = s->frame_len; if ((ret = ff_get_buffer(avctx, frame, 0)) < 0) - return ret; + goto fail; if (!new_pkt) frame->pts = AV_NOPTS_VALUE; } @@ -334,8 +334,8 @@ static int binkaudio_receive_frame(AVCodecContext *avctx, AVFrame *frame) avctx->codec->id == AV_CODEC_ID_BINKAUDIO_DCT, FFMIN(MAX_CHANNELS, s->channels - s->ch_offset), s->ch_offset)) { av_log(avctx, AV_LOG_ERROR, "Incomplete packet\n"); - s->ch_offset = 0; - return AVERROR_INVALIDDATA; + ret = AVERROR_INVALIDDATA; + goto fail; } s->ch_offset += MAX_CHANNELS; get_bits_align32(gb); From 8fe25b120366ebce41ccc2109974dbe07aa2f656 Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Sat, 17 Jun 2023 19:24:09 +0200 Subject: [PATCH 1508/2172] avfilter/vf_xfade: add cover transitions --- doc/filters.texi | 4 +++ libavfilter/vf_xfade.c | 80 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 84 insertions(+) diff --git a/doc/filters.texi b/doc/filters.texi index a8217b07554..693855d28c6 100644 --- a/doc/filters.texi +++ b/doc/filters.texi @@ -25259,6 +25259,10 @@ Set one of available transition effects: @item hrwind @item vuwind @item vdwind +@item coverleft +@item coverright +@item coverup +@item coverdown @end table Default transition effect is fade. diff --git a/libavfilter/vf_xfade.c b/libavfilter/vf_xfade.c index 92f5139ec53..925e860c103 100644 --- a/libavfilter/vf_xfade.c +++ b/libavfilter/vf_xfade.c @@ -80,6 +80,10 @@ enum XFadeTransitions { HRWIND, VUWIND, VDWIND, + COVERLEFT, + COVERRIGHT, + COVERUP, + COVERDOWN, NB_TRANSITIONS, }; @@ -214,6 +218,10 @@ static const AVOption xfade_options[] = { { "hrwind", "hr wind transition", 0, AV_OPT_TYPE_CONST, {.i64=HRWIND}, 0, 0, FLAGS, "transition" }, { "vuwind", "vu wind transition", 0, AV_OPT_TYPE_CONST, {.i64=VUWIND}, 0, 0, FLAGS, "transition" }, { "vdwind", "vd wind transition", 0, AV_OPT_TYPE_CONST, {.i64=VDWIND}, 0, 0, FLAGS, "transition" }, + { "coverleft", "cover left transition", 0, AV_OPT_TYPE_CONST, {.i64=COVERLEFT}, 0, 0, FLAGS, "transition" }, + { "coverright", "cover right transition", 0, AV_OPT_TYPE_CONST, {.i64=COVERRIGHT}, 0, 0, FLAGS, "transition" }, + { "coverup", "cover up transition", 0, AV_OPT_TYPE_CONST, {.i64=COVERUP}, 0, 0, FLAGS, "transition" }, + { "coverdown", "cover down transition", 0, AV_OPT_TYPE_CONST, {.i64=COVERDOWN}, 0, 0, FLAGS, "transition" }, { "duration", "set cross fade duration", OFFSET(duration), AV_OPT_TYPE_DURATION, {.i64=1000000}, 0, 60000000, FLAGS }, { "offset", "set cross fade start relative to first input stream", OFFSET(offset), AV_OPT_TYPE_DURATION, {.i64=0}, INT64_MIN, INT64_MAX, FLAGS }, { "expr", "set expression for custom transition", OFFSET(custom_str), AV_OPT_TYPE_STRING, {.str=NULL}, 0, 0, FLAGS }, @@ -1851,6 +1859,74 @@ VWIND_TRANSITION(16, u, uint16_t, 2, 1.f - ) VWIND_TRANSITION(8, d, uint8_t, 1, ) VWIND_TRANSITION(16, d, uint16_t, 2, ) +#define COVERH_TRANSITION(dir, name, type, div, expr) \ +static void cover##dir##name##_transition(AVFilterContext *ctx, \ + const AVFrame *a, const AVFrame *b, AVFrame *out, \ + float progress, \ + int slice_start, int slice_end, int jobnr) \ +{ \ + XFadeContext *s = ctx->priv; \ + const int height = slice_end - slice_start; \ + const int width = out->width; \ + const int z = (expr progress) * width; \ + \ + for (int p = 0; p < s->nb_planes; p++) { \ + const type *xf0 = (const type *)(a->data[p] + slice_start * a->linesize[p]); \ + const type *xf1 = (const type *)(b->data[p] + slice_start * b->linesize[p]); \ + type *dst = (type *)(out->data[p] + slice_start * out->linesize[p]); \ + \ + for (int y = 0; y < height; y++) { \ + for (int x = 0; x < width; x++) { \ + const int zx = z + x; \ + const int zz = zx % width + width * (zx < 0); \ + dst[x] = (zx >= 0) && (zx < width) ? xf1[zz] : xf0[x]; \ + } \ + \ + dst += out->linesize[p] / div; \ + xf0 += a->linesize[p] / div; \ + xf1 += b->linesize[p] / div; \ + } \ + } \ +} + +COVERH_TRANSITION(left, 8, uint8_t, 1, -) +COVERH_TRANSITION(left, 16, uint16_t, 2, -) +COVERH_TRANSITION(right, 8, uint8_t, 1, ) +COVERH_TRANSITION(right, 16, uint16_t, 2, ) + +#define COVERV_TRANSITION(dir, name, type, div, expr) \ +static void cover##dir##name##_transition(AVFilterContext *ctx, \ + const AVFrame *a, const AVFrame *b, AVFrame *out, \ + float progress, \ + int slice_start, int slice_end, int jobnr) \ +{ \ + XFadeContext *s = ctx->priv; \ + const int height = out->height; \ + const int width = out->width; \ + const int z = (expr progress) * height; \ + \ + for (int p = 0; p < s->nb_planes; p++) { \ + type *dst = (type *)(out->data[p] + slice_start * out->linesize[p]); \ + \ + for (int y = slice_start; y < slice_end; y++) { \ + const int zy = z + y; \ + const int zz = zy % height + height * (zy < 0); \ + const type *xf0 = (const type *)(a->data[p] + y * a->linesize[p]); \ + const type *xf1 = (const type *)(b->data[p] + zz * b->linesize[p]); \ + \ + for (int x = 0; x < width; x++) \ + dst[x] = (zy >= 0) && (zy < height) ? xf1[x] : xf0[x]; \ + \ + dst += out->linesize[p] / div; \ + } \ + } \ +} + +COVERV_TRANSITION(up, 8, uint8_t, 1, -) +COVERV_TRANSITION(up, 16, uint16_t, 2, -) +COVERV_TRANSITION(down, 8, uint8_t, 1, ) +COVERV_TRANSITION(down, 16, uint16_t, 2, ) + static inline double getpix(void *priv, double x, double y, int plane, int nb) { XFadeContext *s = priv; @@ -2001,6 +2077,10 @@ static int config_output(AVFilterLink *outlink) case HRWIND: s->transitionf = s->depth <= 8 ? hrwind8_transition : hrwind16_transition; break; case VUWIND: s->transitionf = s->depth <= 8 ? vuwind8_transition : vuwind16_transition; break; case VDWIND: s->transitionf = s->depth <= 8 ? vdwind8_transition : vdwind16_transition; break; + case COVERLEFT: s->transitionf = s->depth <= 8 ? coverleft8_transition : coverleft16_transition; break; + case COVERRIGHT: s->transitionf = s->depth <= 8 ? coverright8_transition : coverright16_transition; break; + case COVERUP: s->transitionf = s->depth <= 8 ? coverup8_transition : coverup16_transition; break; + case COVERDOWN: s->transitionf = s->depth <= 8 ? coverdown8_transition : coverdown16_transition; break; default: return AVERROR_BUG; } From 4583a24c653ea96932eac13d38e2d71d6ef4e81c Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Sat, 17 Jun 2023 19:34:23 +0200 Subject: [PATCH 1509/2172] avfilter/vf_xfade: add reveal transitions --- doc/filters.texi | 4 +++ libavfilter/vf_xfade.c | 80 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 84 insertions(+) diff --git a/doc/filters.texi b/doc/filters.texi index 693855d28c6..5e25cf293e5 100644 --- a/doc/filters.texi +++ b/doc/filters.texi @@ -25263,6 +25263,10 @@ Set one of available transition effects: @item coverright @item coverup @item coverdown +@item revealleft +@item revealright +@item revealup +@item revealdown @end table Default transition effect is fade. diff --git a/libavfilter/vf_xfade.c b/libavfilter/vf_xfade.c index 925e860c103..625b4075afd 100644 --- a/libavfilter/vf_xfade.c +++ b/libavfilter/vf_xfade.c @@ -84,6 +84,10 @@ enum XFadeTransitions { COVERRIGHT, COVERUP, COVERDOWN, + REVEALLEFT, + REVEALRIGHT, + REVEALUP, + REVEALDOWN, NB_TRANSITIONS, }; @@ -222,6 +226,10 @@ static const AVOption xfade_options[] = { { "coverright", "cover right transition", 0, AV_OPT_TYPE_CONST, {.i64=COVERRIGHT}, 0, 0, FLAGS, "transition" }, { "coverup", "cover up transition", 0, AV_OPT_TYPE_CONST, {.i64=COVERUP}, 0, 0, FLAGS, "transition" }, { "coverdown", "cover down transition", 0, AV_OPT_TYPE_CONST, {.i64=COVERDOWN}, 0, 0, FLAGS, "transition" }, + { "revealleft", "reveal left transition", 0, AV_OPT_TYPE_CONST, {.i64=REVEALLEFT}, 0, 0, FLAGS, "transition" }, + { "revealright","reveal right transition",0, AV_OPT_TYPE_CONST, {.i64=REVEALRIGHT},0, 0, FLAGS, "transition" }, + { "revealup", "reveal up transition", 0, AV_OPT_TYPE_CONST, {.i64=REVEALUP}, 0, 0, FLAGS, "transition" }, + { "revealdown", "reveal down transition", 0, AV_OPT_TYPE_CONST, {.i64=REVEALDOWN}, 0, 0, FLAGS, "transition" }, { "duration", "set cross fade duration", OFFSET(duration), AV_OPT_TYPE_DURATION, {.i64=1000000}, 0, 60000000, FLAGS }, { "offset", "set cross fade start relative to first input stream", OFFSET(offset), AV_OPT_TYPE_DURATION, {.i64=0}, INT64_MIN, INT64_MAX, FLAGS }, { "expr", "set expression for custom transition", OFFSET(custom_str), AV_OPT_TYPE_STRING, {.str=NULL}, 0, 0, FLAGS }, @@ -1927,6 +1935,74 @@ COVERV_TRANSITION(up, 16, uint16_t, 2, -) COVERV_TRANSITION(down, 8, uint8_t, 1, ) COVERV_TRANSITION(down, 16, uint16_t, 2, ) +#define REVEALH_TRANSITION(dir, name, type, div, expr) \ +static void reveal##dir##name##_transition(AVFilterContext *ctx, \ + const AVFrame *a, const AVFrame *b, AVFrame *out, \ + float progress, \ + int slice_start, int slice_end, int jobnr) \ +{ \ + XFadeContext *s = ctx->priv; \ + const int height = slice_end - slice_start; \ + const int width = out->width; \ + const int z = (expr progress) * width; \ + \ + for (int p = 0; p < s->nb_planes; p++) { \ + const type *xf0 = (const type *)(a->data[p] + slice_start * a->linesize[p]); \ + const type *xf1 = (const type *)(b->data[p] + slice_start * b->linesize[p]); \ + type *dst = (type *)(out->data[p] + slice_start * out->linesize[p]); \ + \ + for (int y = 0; y < height; y++) { \ + for (int x = 0; x < width; x++) { \ + const int zx = z + x; \ + const int zz = zx % width + width * (zx < 0); \ + dst[x] = (zx >= 0) && (zx < width) ? xf1[x] : xf0[zz]; \ + } \ + \ + dst += out->linesize[p] / div; \ + xf0 += a->linesize[p] / div; \ + xf1 += b->linesize[p] / div; \ + } \ + } \ +} + +REVEALH_TRANSITION(left, 8, uint8_t, 1, -) +REVEALH_TRANSITION(left, 16, uint16_t, 2, -) +REVEALH_TRANSITION(right, 8, uint8_t, 1, ) +REVEALH_TRANSITION(right, 16, uint16_t, 2, ) + +#define REVEALV_TRANSITION(dir, name, type, div, expr) \ +static void reveal##dir##name##_transition(AVFilterContext *ctx, \ + const AVFrame *a, const AVFrame *b, AVFrame *out, \ + float progress, \ + int slice_start, int slice_end, int jobnr) \ +{ \ + XFadeContext *s = ctx->priv; \ + const int height = out->height; \ + const int width = out->width; \ + const int z = (expr progress) * height; \ + \ + for (int p = 0; p < s->nb_planes; p++) { \ + type *dst = (type *)(out->data[p] + slice_start * out->linesize[p]); \ + \ + for (int y = slice_start; y < slice_end; y++) { \ + const int zy = z + y; \ + const int zz = zy % height + height * (zy < 0); \ + const type *xf0 = (const type *)(a->data[p] + zz * a->linesize[p]); \ + const type *xf1 = (const type *)(b->data[p] + y * b->linesize[p]); \ + \ + for (int x = 0; x < width; x++) \ + dst[x] = (zy >= 0) && (zy < height) ? xf1[x] : xf0[x]; \ + \ + dst += out->linesize[p] / div; \ + } \ + } \ +} + +REVEALV_TRANSITION(up, 8, uint8_t, 1, -) +REVEALV_TRANSITION(up, 16, uint16_t, 2, -) +REVEALV_TRANSITION(down, 8, uint8_t, 1, ) +REVEALV_TRANSITION(down, 16, uint16_t, 2, ) + static inline double getpix(void *priv, double x, double y, int plane, int nb) { XFadeContext *s = priv; @@ -2081,6 +2157,10 @@ static int config_output(AVFilterLink *outlink) case COVERRIGHT: s->transitionf = s->depth <= 8 ? coverright8_transition : coverright16_transition; break; case COVERUP: s->transitionf = s->depth <= 8 ? coverup8_transition : coverup16_transition; break; case COVERDOWN: s->transitionf = s->depth <= 8 ? coverdown8_transition : coverdown16_transition; break; + case REVEALLEFT: s->transitionf = s->depth <= 8 ? revealleft8_transition : revealleft16_transition; break; + case REVEALRIGHT:s->transitionf = s->depth <= 8 ? revealright8_transition: revealright16_transition;break; + case REVEALUP: s->transitionf = s->depth <= 8 ? revealup8_transition : revealup16_transition; break; + case REVEALDOWN: s->transitionf = s->depth <= 8 ? revealdown8_transition : revealdown16_transition; break; default: return AVERROR_BUG; } From a756ae41ed745af3ae93a71f3a38f277abba33ef Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Wed, 17 May 2023 09:14:56 +0200 Subject: [PATCH 1510/2172] avfilter/af_apad: switch to activate Fixes EOF PTS reporting. Also allowing previous/next filters in graph to release no longer needed resources. --- libavfilter/af_apad.c | 105 ++++++++++++++++++++++++++++-------------- 1 file changed, 71 insertions(+), 34 deletions(-) diff --git a/libavfilter/af_apad.c b/libavfilter/af_apad.c index df17c9a5315..45693a2bd5d 100644 --- a/libavfilter/af_apad.c +++ b/libavfilter/af_apad.c @@ -32,12 +32,14 @@ #include "libavutil/avassert.h" #include "avfilter.h" #include "audio.h" +#include "filters.h" #include "internal.h" typedef struct APadContext { const AVClass *class; int64_t next_pts; + int eof; int packet_size; int64_t pad_len, pad_len_left; int64_t whole_len, whole_len_left; @@ -87,50 +89,86 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *frame) return ff_filter_frame(ctx->outputs[0], frame); } -static int request_frame(AVFilterLink *outlink) +static int push_frame(AVFilterLink *outlink) { AVFilterContext *ctx = outlink->src; APadContext *s = ctx->priv; - int ret; + AVFrame *outsamplesref; + int n_out; - ret = ff_request_frame(ctx->inputs[0]); + if (ctx->is_disabled) + return 0; + n_out = s->packet_size; - if (ret == AVERROR_EOF && !ctx->is_disabled) { - int n_out = s->packet_size; - AVFrame *outsamplesref; + if (s->whole_len >= 0 && s->pad_len < 0) { + s->pad_len = s->pad_len_left = s->whole_len_left; + } + if (s->pad_len >=0 || s->whole_len >= 0) { + n_out = FFMIN(n_out, s->pad_len_left); + s->pad_len_left -= n_out; + av_log(ctx, AV_LOG_DEBUG, + "padding n_out:%d pad_len_left:%"PRId64"\n", n_out, s->pad_len_left); + } - if (s->whole_len >= 0 && s->pad_len < 0) { - s->pad_len = s->pad_len_left = s->whole_len_left; - } - if (s->pad_len >=0 || s->whole_len >= 0) { - n_out = FFMIN(n_out, s->pad_len_left); - s->pad_len_left -= n_out; - av_log(ctx, AV_LOG_DEBUG, - "padding n_out:%d pad_len_left:%"PRId64"\n", n_out, s->pad_len_left); - } + if (!n_out) + return AVERROR_EOF; + + outsamplesref = ff_get_audio_buffer(outlink, n_out); + if (!outsamplesref) + return AVERROR(ENOMEM); + + av_assert0(outsamplesref->sample_rate == outlink->sample_rate); + av_assert0(outsamplesref->nb_samples == n_out); + + av_samples_set_silence(outsamplesref->extended_data, 0, + n_out, + outsamplesref->ch_layout.nb_channels, + outsamplesref->format); + + outsamplesref->pts = s->next_pts; + if (s->next_pts != AV_NOPTS_VALUE) + s->next_pts += av_rescale_q(n_out, (AVRational){1, outlink->sample_rate}, outlink->time_base); + + return ff_filter_frame(outlink, outsamplesref); +} - if (!n_out) - return AVERROR_EOF; +static int activate(AVFilterContext *ctx) +{ + AVFilterLink *inlink = ctx->inputs[0]; + AVFilterLink *outlink = ctx->outputs[0]; + APadContext *s = ctx->priv; + int64_t pts; + int status; - outsamplesref = ff_get_audio_buffer(outlink, n_out); - if (!outsamplesref) - return AVERROR(ENOMEM); + FF_FILTER_FORWARD_STATUS_BACK(outlink, inlink); - av_assert0(outsamplesref->sample_rate == outlink->sample_rate); - av_assert0(outsamplesref->nb_samples == n_out); + if (!s->eof && ff_inlink_queued_frames(inlink)) { + AVFrame *frame = NULL; + int ret; + + ret = ff_inlink_consume_frame(inlink, &frame); + if (ret < 0) + return ret; + if (ret > 0) + return filter_frame(inlink, frame); + } - av_samples_set_silence(outsamplesref->extended_data, 0, - n_out, - outsamplesref->ch_layout.nb_channels, - outsamplesref->format); + if (!s->eof && ff_inlink_acknowledge_status(inlink, &status, &pts)) + s->eof = status == AVERROR_EOF; - outsamplesref->pts = s->next_pts; - if (s->next_pts != AV_NOPTS_VALUE) - s->next_pts += av_rescale_q(n_out, (AVRational){1, outlink->sample_rate}, outlink->time_base); + if (s->eof) { + int ret = push_frame(outlink); - return ff_filter_frame(outlink, outsamplesref); + if (ret == AVERROR_EOF) { + ff_outlink_set_status(outlink, AVERROR_EOF, s->next_pts); + return 0; + } + return ret; } - return ret; + + FF_FILTER_FORWARD_WANTED(outlink, inlink); + + return FFERROR_NOT_READY; } static int config_output(AVFilterLink *outlink) @@ -153,16 +191,14 @@ static const AVFilterPad apad_inputs[] = { { .name = "default", .type = AVMEDIA_TYPE_AUDIO, - .filter_frame = filter_frame, }, }; static const AVFilterPad apad_outputs[] = { { .name = "default", - .request_frame = request_frame, - .config_props = config_output, .type = AVMEDIA_TYPE_AUDIO, + .config_props = config_output, }, }; @@ -170,6 +206,7 @@ const AVFilter ff_af_apad = { .name = "apad", .description = NULL_IF_CONFIG_SMALL("Pad audio with silence."), .init = init, + .activate = activate, .priv_size = sizeof(APadContext), FILTER_INPUTS(apad_inputs), FILTER_OUTPUTS(apad_outputs), From c44fe101603dbe1e788079f4a798eeca13dbedcd Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Sat, 17 Jun 2023 22:32:11 +0200 Subject: [PATCH 1511/2172] avfilter/af_afade: stop using ff_outlink_get_status on inputs --- libavfilter/af_afade.c | 42 +++++++++++++++++++++++++----------------- 1 file changed, 25 insertions(+), 17 deletions(-) diff --git a/libavfilter/af_afade.c b/libavfilter/af_afade.c index 2f45b129048..226b63c2756 100644 --- a/libavfilter/af_afade.c +++ b/libavfilter/af_afade.c @@ -42,8 +42,8 @@ typedef struct AudioFadeContext { double silence; double unity; int overlap; - int cf0_eof; - int crossfade_is_over; + int status[2]; + int passthrough; int64_t pts; void (*fade_samples)(uint8_t **dst, uint8_t * const *src, @@ -521,6 +521,13 @@ CROSSFADE(flt, float) CROSSFADE(s16, int16_t) CROSSFADE(s32, int32_t) +static int check_input(AVFilterLink *inlink) +{ + const int queued_samples = ff_inlink_queued_samples(inlink); + + return ff_inlink_check_available_samples(inlink, queued_samples + 1) == 1; +} + static int activate(AVFilterContext *ctx) { AudioFadeContext *s = ctx->priv; @@ -531,7 +538,7 @@ static int activate(AVFilterContext *ctx) FF_FILTER_FORWARD_STATUS_BACK_ALL(outlink, ctx); - if (s->crossfade_is_over) { + if (s->passthrough && s->status[0]) { ret = ff_inlink_consume_frame(ctx->inputs[1], &in); if (ret > 0) { in->pts = s->pts; @@ -541,10 +548,10 @@ static int activate(AVFilterContext *ctx) } else if (ret < 0) { return ret; } else if (ff_inlink_acknowledge_status(ctx->inputs[1], &status, &pts)) { - ff_outlink_set_status(ctx->outputs[0], status, pts); + ff_outlink_set_status(outlink, status, pts); return 0; } else if (!ret) { - if (ff_outlink_frame_wanted(ctx->outputs[0])) { + if (ff_outlink_frame_wanted(outlink)) { ff_inlink_request_frame(ctx->inputs[1]); return 0; } @@ -554,6 +561,7 @@ static int activate(AVFilterContext *ctx) nb_samples = ff_inlink_queued_samples(ctx->inputs[0]); if (nb_samples > s->nb_samples) { nb_samples -= s->nb_samples; + s->passthrough = 1; ret = ff_inlink_consume_samples(ctx->inputs[0], nb_samples, nb_samples, &in); if (ret < 0) return ret; @@ -561,7 +569,7 @@ static int activate(AVFilterContext *ctx) s->pts += av_rescale_q(in->nb_samples, (AVRational){ 1, outlink->sample_rate }, outlink->time_base); return ff_filter_frame(outlink, in); - } else if (s->cf0_eof && nb_samples >= s->nb_samples && + } else if (s->status[0] && nb_samples >= s->nb_samples && ff_inlink_queued_samples(ctx->inputs[1]) >= s->nb_samples) { if (s->overlap) { out = ff_get_audio_buffer(outlink, s->nb_samples); @@ -587,7 +595,7 @@ static int activate(AVFilterContext *ctx) out->pts = s->pts; s->pts += av_rescale_q(s->nb_samples, (AVRational){ 1, outlink->sample_rate }, outlink->time_base); - s->crossfade_is_over = 1; + s->passthrough = 1; av_frame_free(&cf[0]); av_frame_free(&cf[1]); return ff_filter_frame(outlink, out); @@ -627,19 +635,20 @@ static int activate(AVFilterContext *ctx) out->pts = s->pts; s->pts += av_rescale_q(s->nb_samples, (AVRational){ 1, outlink->sample_rate }, outlink->time_base); - s->crossfade_is_over = 1; + s->passthrough = 1; av_frame_free(&cf[1]); return ff_filter_frame(outlink, out); } - } else if (ff_outlink_frame_wanted(ctx->outputs[0])) { - if (!s->cf0_eof && ff_outlink_get_status(ctx->inputs[0])) { - s->cf0_eof = 1; - } - if (ff_outlink_get_status(ctx->inputs[1])) { - ff_outlink_set_status(ctx->outputs[0], AVERROR_EOF, AV_NOPTS_VALUE); + } else if (ff_outlink_frame_wanted(outlink)) { + if (!s->status[0] && check_input(ctx->inputs[0])) + s->status[0] = AVERROR_EOF; + s->passthrough = !s->status[0]; + if (check_input(ctx->inputs[1])) { + s->status[1] = AVERROR_EOF; + ff_outlink_set_status(outlink, AVERROR_EOF, AV_NOPTS_VALUE); return 0; } - if (!s->cf0_eof) + if (!s->status[0]) ff_inlink_request_frame(ctx->inputs[0]); else ff_inlink_request_frame(ctx->inputs[1]); @@ -677,8 +686,7 @@ static AVFrame *get_audio_buffer(AVFilterLink *inlink, int nb_samples) AVFilterContext *ctx = inlink->dst; AudioFadeContext *s = ctx->priv; - return (s->crossfade_is_over || - (ff_inlink_queued_samples(inlink) > s->nb_samples)) ? + return s->passthrough ? ff_null_get_audio_buffer (inlink, nb_samples) : ff_default_get_audio_buffer(inlink, nb_samples); } From 238ec0c31bea6da9a9124edb1d7beb68d54f9d9b Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Sun, 18 Jun 2023 02:03:26 +0200 Subject: [PATCH 1512/2172] avfilter/af_drmeter: fix error in picking 2nd peak --- libavfilter/af_drmeter.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavfilter/af_drmeter.c b/libavfilter/af_drmeter.c index 3e80691339c..67eafc23f76 100644 --- a/libavfilter/af_drmeter.c +++ b/libavfilter/af_drmeter.c @@ -148,7 +148,7 @@ static void print_stats(AVFilterContext *ctx) for (i = 0; i <= BINS; i++) { if (p->peaks[BINS - i]) { - if (first) + if (first || p->peaks[BINS - i] > 1) break; first = 1; } From 494ebfdbfaff87ca422f07b9dcda94b7fc05774b Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Sun, 18 Jun 2023 02:10:11 +0200 Subject: [PATCH 1513/2172] avfilter/af_drmeter: misc cleanups --- libavfilter/af_drmeter.c | 54 ++++++++++++++++++++-------------------- 1 file changed, 27 insertions(+), 27 deletions(-) diff --git a/libavfilter/af_drmeter.c b/libavfilter/af_drmeter.c index 67eafc23f76..5eea865575e 100644 --- a/libavfilter/af_drmeter.c +++ b/libavfilter/af_drmeter.c @@ -41,7 +41,7 @@ typedef struct DRMeterContext { const AVClass *class; ChannelStats *chstats; int nb_channels; - uint64_t tc_samples; + int64_t tc_samples; double time_constant; } DRMeterContext; @@ -59,11 +59,11 @@ static int config_output(AVFilterLink *outlink) { DRMeterContext *s = outlink->src->priv; - s->chstats = av_calloc(sizeof(*s->chstats), outlink->ch_layout.nb_channels); + s->chstats = av_calloc(outlink->ch_layout.nb_channels, sizeof(*s->chstats)); if (!s->chstats) return AVERROR(ENOMEM); s->nb_channels = outlink->ch_layout.nb_channels; - s->tc_samples = s->time_constant * outlink->sample_rate + .5; + s->tc_samples = lrint(s->time_constant * outlink->sample_rate); return 0; } @@ -73,7 +73,7 @@ static void finish_block(ChannelStats *p) int peak_bin, rms_bin; float peak, rms; - rms = sqrt(2 * p->sum / p->nb_samples); + rms = sqrtf(2.f * p->sum / p->nb_samples); peak = p->peak; rms_bin = av_clip(lrintf(rms * BINS), 0, BINS); peak_bin = av_clip(lrintf(peak * BINS), 0, BINS); @@ -88,36 +88,33 @@ static void finish_block(ChannelStats *p) static void update_stat(DRMeterContext *s, ChannelStats *p, float sample) { - if (p->nb_samples >= s->tc_samples) { - finish_block(p); - } - - p->peak = FFMAX(FFABS(sample), p->peak); + p->peak = fmaxf(fabsf(sample), p->peak); p->sum += sample * sample; p->nb_samples++; + if (p->nb_samples >= s->tc_samples) + finish_block(p); } static int filter_frame(AVFilterLink *inlink, AVFrame *buf) { DRMeterContext *s = inlink->dst->priv; const int channels = s->nb_channels; - int i, c; switch (inlink->format) { case AV_SAMPLE_FMT_FLTP: - for (c = 0; c < channels; c++) { + for (int c = 0; c < channels; c++) { ChannelStats *p = &s->chstats[c]; const float *src = (const float *)buf->extended_data[c]; - for (i = 0; i < buf->nb_samples; i++, src++) + for (int i = 0; i < buf->nb_samples; i++, src++) update_stat(s, p, *src); } break; case AV_SAMPLE_FMT_FLT: { const float *src = (const float *)buf->extended_data[0]; - for (i = 0; i < buf->nb_samples; i++) { - for (c = 0; c < channels; c++, src++) + for (int i = 0; i < buf->nb_samples; i++) { + for (int c = 0; c < channels; c++, src++) update_stat(s, &s->chstats[c], *src); }} break; @@ -131,39 +128,42 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *buf) static void print_stats(AVFilterContext *ctx) { DRMeterContext *s = ctx->priv; - float dr = 0; - int ch; + float dr = 0.f; - for (ch = 0; ch < s->nb_channels; ch++) { + for (int ch = 0; ch < s->nb_channels; ch++) { ChannelStats *p = &s->chstats[ch]; - float chdr, secondpeak, rmssum = 0; - int i, j, first = 0; + float chdr, secondpeak, rmssum = 0.f; + int first = 0, last = lrintf(0.2f * p->blknum); + int peak_bin = BINS; if (!p->nb_samples) { av_log(ctx, AV_LOG_INFO, "No data, dynamic range not meassurable\n"); return; } - finish_block(p); + if (p->nb_samples) + finish_block(p); - for (i = 0; i <= BINS; i++) { - if (p->peaks[BINS - i]) { - if (first || p->peaks[BINS - i] > 1) + for (int i = BINS; i >= 0; i--) { + if (p->peaks[i]) { + if (first || p->peaks[i] > 1) { + peak_bin = i; break; + } first = 1; } } - secondpeak = (BINS - i) / (double)BINS; + secondpeak = peak_bin / (float)BINS; - for (i = BINS, j = 0; i >= 0 && j < 0.2 * p->blknum; i--) { + for (int64_t i = BINS, j = 0; i >= 0 && j < last; i--) { if (p->rms[i]) { - rmssum += SQR(i / (double)BINS); + rmssum += SQR(i / (float)BINS) * p->rms[i]; j += p->rms[i]; } } - chdr = 20 * log10(secondpeak / sqrt(rmssum / (0.2 * p->blknum))); + chdr = 20.f * log10f(secondpeak / sqrtf(rmssum / (float)last)); dr += chdr; av_log(ctx, AV_LOG_INFO, "Channel %d: DR: %g\n", ch + 1, chdr); } From 54dc06e09e1d06f9184ffb4327d8e75b5651d431 Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Sun, 18 Jun 2023 11:01:56 +0200 Subject: [PATCH 1514/2172] avfilter/vf_displace: add slice threading support --- libavfilter/vf_displace.c | 109 +++++++++++++++++++++++--------------- 1 file changed, 66 insertions(+), 43 deletions(-) diff --git a/libavfilter/vf_displace.c b/libavfilter/vf_displace.c index 11909949b16..4df98d4cc1e 100644 --- a/libavfilter/vf_displace.c +++ b/libavfilter/vf_displace.c @@ -45,8 +45,7 @@ typedef struct DisplaceContext { uint8_t blank[4]; FFFrameSync fs; - void (*displace)(struct DisplaceContext *s, const AVFrame *in, - const AVFrame *xpic, const AVFrame *ypic, AVFrame *out); + int (*displace_slice)(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs); } DisplaceContext; #define OFFSET(x) offsetof(DisplaceContext, x) @@ -76,29 +75,38 @@ static const enum AVPixelFormat pix_fmts[] = { AV_PIX_FMT_GRAY8, AV_PIX_FMT_NONE }; -static void displace_planar(DisplaceContext *s, const AVFrame *in, - const AVFrame *xpic, const AVFrame *ypic, - AVFrame *out) +typedef struct ThreadData { + AVFrame *in, *xin, *yin, *out; +} ThreadData; + +static int displace_planar(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) { - int plane, x, y; + DisplaceContext *s = ctx->priv; + const ThreadData *td = arg; + const AVFrame *in = td->in; + const AVFrame *xin = td->xin; + const AVFrame *yin = td->yin; + const AVFrame *out = td->out; - for (plane = 0; plane < s->nb_planes; plane++) { + for (int plane = 0; plane < s->nb_planes; plane++) { const int h = s->height[plane]; const int w = s->width[plane]; + const int slice_start = (h * jobnr ) / nb_jobs; + const int slice_end = (h * (jobnr+1)) / nb_jobs; const int dlinesize = out->linesize[plane]; const int slinesize = in->linesize[plane]; - const int xlinesize = xpic->linesize[plane]; - const int ylinesize = ypic->linesize[plane]; + const int xlinesize = xin->linesize[plane]; + const int ylinesize = yin->linesize[plane]; const uint8_t *src = in->data[plane]; - const uint8_t *ysrc = ypic->data[plane]; - const uint8_t *xsrc = xpic->data[plane]; - uint8_t *dst = out->data[plane]; + const uint8_t *ysrc = yin->data[plane] + slice_start * ylinesize; + const uint8_t *xsrc = xin->data[plane] + slice_start * xlinesize; + uint8_t *dst = out->data[plane] + slice_start * dlinesize; const uint8_t blank = s->blank[plane]; - for (y = 0; y < h; y++) { + for (int y = slice_start; y < slice_end; y++) { switch (s->edge) { case EDGE_BLANK: - for (x = 0; x < w; x++) { + for (int x = 0; x < w; x++) { int Y = y + ysrc[x] - 128; int X = x + xsrc[x] - 128; @@ -109,14 +117,14 @@ static void displace_planar(DisplaceContext *s, const AVFrame *in, } break; case EDGE_SMEAR: - for (x = 0; x < w; x++) { + for (int x = 0; x < w; x++) { int Y = av_clip(y + ysrc[x] - 128, 0, h - 1); int X = av_clip(x + xsrc[x] - 128, 0, w - 1); dst[x] = src[Y * slinesize + X]; } break; case EDGE_WRAP: - for (x = 0; x < w; x++) { + for (int x = 0; x < w; x++) { int Y = (y + ysrc[x] - 128) % h; int X = (x + xsrc[x] - 128) % w; @@ -128,7 +136,7 @@ static void displace_planar(DisplaceContext *s, const AVFrame *in, } break; case EDGE_MIRROR: - for (x = 0; x < w; x++) { + for (int x = 0; x < w; x++) { int Y = y + ysrc[x] - 128; int X = x + xsrc[x] - 128; @@ -150,31 +158,37 @@ static void displace_planar(DisplaceContext *s, const AVFrame *in, dst += dlinesize; } } + return 0; } -static void displace_packed(DisplaceContext *s, const AVFrame *in, - const AVFrame *xpic, const AVFrame *ypic, - AVFrame *out) +static int displace_packed(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) { + DisplaceContext *s = ctx->priv; + const ThreadData *td = arg; + const AVFrame *in = td->in; + const AVFrame *xin = td->xin; + const AVFrame *yin = td->yin; + const AVFrame *out = td->out; const int step = s->step; const int h = s->height[0]; const int w = s->width[0]; + const int slice_start = (h * jobnr ) / nb_jobs; + const int slice_end = (h * (jobnr+1)) / nb_jobs; const int dlinesize = out->linesize[0]; const int slinesize = in->linesize[0]; - const int xlinesize = xpic->linesize[0]; - const int ylinesize = ypic->linesize[0]; + const int xlinesize = xin->linesize[0]; + const int ylinesize = yin->linesize[0]; const uint8_t *src = in->data[0]; - const uint8_t *ysrc = ypic->data[0]; - const uint8_t *xsrc = xpic->data[0]; + const uint8_t *ysrc = yin->data[0] + slice_start * ylinesize; + const uint8_t *xsrc = xin->data[0] + slice_start * xlinesize; + uint8_t *dst = out->data[0] + slice_start * dlinesize; const uint8_t *blank = s->blank; - uint8_t *dst = out->data[0]; - int c, x, y; - for (y = 0; y < h; y++) { + for (int y = slice_start; y < slice_end; y++) { switch (s->edge) { case EDGE_BLANK: - for (x = 0; x < w; x++) { - for (c = 0; c < s->nb_components; c++) { + for (int x = 0; x < w; x++) { + for (int c = 0; c < s->nb_components; c++) { int Y = y + (ysrc[x * step + c] - 128); int X = x + (xsrc[x * step + c] - 128); @@ -186,8 +200,8 @@ static void displace_packed(DisplaceContext *s, const AVFrame *in, } break; case EDGE_SMEAR: - for (x = 0; x < w; x++) { - for (c = 0; c < s->nb_components; c++) { + for (int x = 0; x < w; x++) { + for (int c = 0; c < s->nb_components; c++) { int Y = av_clip(y + (ysrc[x * step + c] - 128), 0, h - 1); int X = av_clip(x + (xsrc[x * step + c] - 128), 0, w - 1); @@ -196,8 +210,8 @@ static void displace_packed(DisplaceContext *s, const AVFrame *in, } break; case EDGE_WRAP: - for (x = 0; x < w; x++) { - for (c = 0; c < s->nb_components; c++) { + for (int x = 0; x < w; x++) { + for (int c = 0; c < s->nb_components; c++) { int Y = (y + (ysrc[x * step + c] - 128)) % h; int X = (x + (xsrc[x * step + c] - 128)) % w; @@ -210,8 +224,8 @@ static void displace_packed(DisplaceContext *s, const AVFrame *in, } break; case EDGE_MIRROR: - for (x = 0; x < w; x++) { - for (c = 0; c < s->nb_components; c++) { + for (int x = 0; x < w; x++) { + for (int c = 0; c < s->nb_components; c++) { int Y = y + ysrc[x * step + c] - 128; int X = x + xsrc[x * step + c] - 128; @@ -233,6 +247,7 @@ static void displace_packed(DisplaceContext *s, const AVFrame *in, xsrc += xlinesize; dst += dlinesize; } + return 0; } static int process_frame(FFFrameSync *fs) @@ -240,12 +255,12 @@ static int process_frame(FFFrameSync *fs) AVFilterContext *ctx = fs->parent; DisplaceContext *s = fs->opaque; AVFilterLink *outlink = ctx->outputs[0]; - AVFrame *out, *in, *xpic, *ypic; + AVFrame *out, *in, *xin, *yin; int ret; - if ((ret = ff_framesync_get_frame(&s->fs, 0, &in, 0)) < 0 || - (ret = ff_framesync_get_frame(&s->fs, 1, &xpic, 0)) < 0 || - (ret = ff_framesync_get_frame(&s->fs, 2, &ypic, 0)) < 0) + if ((ret = ff_framesync_get_frame(&s->fs, 0, &in, 0)) < 0 || + (ret = ff_framesync_get_frame(&s->fs, 1, &xin, 0)) < 0 || + (ret = ff_framesync_get_frame(&s->fs, 2, &yin, 0)) < 0) return ret; if (ctx->is_disabled) { @@ -253,12 +268,19 @@ static int process_frame(FFFrameSync *fs) if (!out) return AVERROR(ENOMEM); } else { + ThreadData td; + out = ff_get_video_buffer(outlink, outlink->w, outlink->h); if (!out) return AVERROR(ENOMEM); av_frame_copy_props(out, in); - s->displace(s, in, xpic, ypic, out); + td.in = in; + td.xin = xin; + td.yin = yin; + td.out = out; + ff_filter_execute(ctx, s->displace_slice, &td, NULL, + FFMIN(outlink->h, ff_filter_get_nb_threads(ctx))); } out->pts = av_rescale_q(s->fs.pts, s->fs.time_base, outlink->time_base); @@ -276,9 +298,9 @@ static int config_input(AVFilterLink *inlink) s->nb_components = desc->nb_components; if (s->nb_planes > 1 || s->nb_components == 1) - s->displace = displace_planar; + s->displace_slice = displace_planar; else - s->displace = displace_packed; + s->displace_slice = displace_packed; if (!(desc->flags & AV_PIX_FMT_FLAG_RGB)) { s->blank[1] = s->blank[2] = 128; @@ -398,5 +420,6 @@ const AVFilter ff_vf_displace = { FILTER_OUTPUTS(displace_outputs), FILTER_PIXFMTS_ARRAY(pix_fmts), .priv_class = &displace_class, - .flags = AVFILTER_FLAG_SUPPORT_TIMELINE_INTERNAL, + .flags = AVFILTER_FLAG_SUPPORT_TIMELINE_INTERNAL | + AVFILTER_FLAG_SLICE_THREADS, }; From 8e21f32fe792680c5302df83ef95c738c29742a7 Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Sun, 18 Jun 2023 11:05:38 +0200 Subject: [PATCH 1515/2172] avfilter/vf_displace: add support for commands --- libavfilter/vf_displace.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libavfilter/vf_displace.c b/libavfilter/vf_displace.c index 4df98d4cc1e..ee56f32856c 100644 --- a/libavfilter/vf_displace.c +++ b/libavfilter/vf_displace.c @@ -49,7 +49,7 @@ typedef struct DisplaceContext { } DisplaceContext; #define OFFSET(x) offsetof(DisplaceContext, x) -#define FLAGS AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_VIDEO_PARAM +#define FLAGS AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_VIDEO_PARAM|AV_OPT_FLAG_RUNTIME_PARAM static const AVOption displace_options[] = { { "edge", "set edge mode", OFFSET(edge), AV_OPT_TYPE_INT, {.i64=EDGE_SMEAR}, 0, EDGE_NB-1, FLAGS, "edge" }, @@ -422,4 +422,5 @@ const AVFilter ff_vf_displace = { .priv_class = &displace_class, .flags = AVFILTER_FLAG_SUPPORT_TIMELINE_INTERNAL | AVFILTER_FLAG_SLICE_THREADS, + .process_command = ff_filter_process_command, }; From fead656a7bf523d448fe8bd39c1f2ea36be98fb9 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Sat, 3 Jun 2023 21:44:37 +0200 Subject: [PATCH 1516/2172] avcodec: Ignoring errors is only possible before the input end Fixes: out of array read Fixes: Ticket 10308 Signed-off-by: Michael Niedermayer --- libavcodec/h263dec.c | 2 +- libavcodec/mpeg4videodec.c | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/libavcodec/h263dec.c b/libavcodec/h263dec.c index f4e7048a5f2..68a618a7ed1 100644 --- a/libavcodec/h263dec.c +++ b/libavcodec/h263dec.c @@ -281,7 +281,7 @@ static int decode_slice(MpegEncContext *s) ff_er_add_slice(&s->er, s->resync_mb_x, s->resync_mb_y, s->mb_x, s->mb_y, ER_MB_ERROR & part_mask); - if (s->avctx->err_recognition & AV_EF_IGNORE_ERR) + if ((s->avctx->err_recognition & AV_EF_IGNORE_ERR) && get_bits_left(&s->gb) > 0) continue; return AVERROR_INVALIDDATA; } diff --git a/libavcodec/mpeg4videodec.c b/libavcodec/mpeg4videodec.c index d456e5dd113..30aec5e5293 100644 --- a/libavcodec/mpeg4videodec.c +++ b/libavcodec/mpeg4videodec.c @@ -1437,7 +1437,7 @@ static inline int mpeg4_decode_block(Mpeg4DecContext *ctx, int16_t *block, if (SHOW_UBITS(re, &s->gb, 1) == 0) { av_log(s->avctx, AV_LOG_ERROR, "1. marker bit missing in 3. esc\n"); - if (!(s->avctx->err_recognition & AV_EF_IGNORE_ERR)) + if (!(s->avctx->err_recognition & AV_EF_IGNORE_ERR) || get_bits_left(&s->gb) <= 0) return AVERROR_INVALIDDATA; } SKIP_CACHE(re, &s->gb, 1); @@ -1448,7 +1448,7 @@ static inline int mpeg4_decode_block(Mpeg4DecContext *ctx, int16_t *block, if (SHOW_UBITS(re, &s->gb, 1) == 0) { av_log(s->avctx, AV_LOG_ERROR, "2. marker bit missing in 3. esc\n"); - if (!(s->avctx->err_recognition & AV_EF_IGNORE_ERR)) + if (!(s->avctx->err_recognition & AV_EF_IGNORE_ERR) || get_bits_left(&s->gb) <= 0) return AVERROR_INVALIDDATA; } From 1ee303f1e1677fd997da05ae1cc6aca064f96bdb Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Thu, 25 May 2023 22:58:53 +0200 Subject: [PATCH 1517/2172] avcodec/rka: Avoid undefined left shift Fixes: left shift of 34136248 by 6 places cannot be represented in type 'int' Fixes: 58429/clusterfuzz-testcase-minimized-ffmpeg_AV_CODEC_ID_RKA_fuzzer-5692211592560640 Found-by: continuous fuzzing process https://github.com/google/oss-fuzz/tree/master/projects/ffmpeg Signed-off-by: Michael Niedermayer --- libavcodec/rka.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavcodec/rka.c b/libavcodec/rka.c index e0ed8c16e44..76dca52602b 100644 --- a/libavcodec/rka.c +++ b/libavcodec/rka.c @@ -750,7 +750,7 @@ static int decode_filter(RKAContext *s, ChContext *ctx, ACoder *ac, int off, uns } if (ctx->cmode2 != 0) { int sum = 0; - for (int i = (m << 6) / split; i > 0; i = i >> 1) + for (int i = (signed)((unsigned)m << 6) / split; i > 0; i = i >> 1) sum++; sum = sum - (ctx->cmode2 + 7); ctx->cmode = FFMAX(sum, tab[ctx->cmode2]); From e736238b35a1e0f69fe8e5a9a7359ba24883c488 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Thu, 8 Jun 2023 15:05:50 +0200 Subject: [PATCH 1518/2172] avcodec/rka: use unsigned for buf0 additions Fixes: signed integer overflow: -38912000 + -2109276160 cannot be represented in type 'int' Fixes: 59670/clusterfuzz-testcase-minimized-ffmpeg_AV_CODEC_ID_RKA_fuzzer-4987563245699072 Found-by: continuous fuzzing process https://github.com/google/oss-fuzz/tree/master/projects/ffmpeg Signed-off-by: Michael Niedermayer --- libavcodec/rka.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libavcodec/rka.c b/libavcodec/rka.c index 76dca52602b..d56f4faee4b 100644 --- a/libavcodec/rka.c +++ b/libavcodec/rka.c @@ -735,10 +735,10 @@ static int decode_filter(RKAContext *s, ChContext *ctx, ACoder *ac, int off, uns ctx->buf1[off] = (val + (sum >> bits)) * (1U << bits) + (((1U << bits) - 1U) & ctx->buf1[off + -1]); } - ctx->buf0[off] = ctx->buf1[off] + ctx->buf0[off + -1]; + ctx->buf0[off] = ctx->buf1[off] + (unsigned)ctx->buf0[off + -1]; } else { val *= 1U << ctx->cmode; - sum += ctx->buf0[off + -1] + val; + sum += ctx->buf0[off + -1] + (unsigned)val; switch (s->bps) { case 16: sum = av_clip_int16(sum); break; case 8: sum = av_clip_int8(sum); break; From d7d3f1af2ab23cae1b2fc36afafc9872bc633808 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Thu, 8 Jun 2023 15:47:37 +0200 Subject: [PATCH 1519/2172] avcodec/mpegvideo_dec: consider interlaced lowres 4:2:0 chroma in edge emulation check better Fixes: out of array read Fixes: 59673/clusterfuzz-testcase-minimized-ffmpeg_AV_CODEC_ID_MPEG1VIDEO_fuzzer-5194311374077952 Found-by: continuous fuzzing process https://github.com/google/oss-fuzz/tree/master/projects/ffmpeg Signed-off-by: Michael Niedermayer --- libavcodec/mpegvideo_dec.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libavcodec/mpegvideo_dec.c b/libavcodec/mpegvideo_dec.c index 765ccd0ba4a..c87ca77ae63 100644 --- a/libavcodec/mpegvideo_dec.c +++ b/libavcodec/mpegvideo_dec.c @@ -640,6 +640,7 @@ static av_always_inline void mpeg_motion_lowres(MpegEncContext *s, const int s_mask = (2 << lowres) - 1; const int h_edge_pos = s->h_edge_pos >> lowres; const int v_edge_pos = s->v_edge_pos >> lowres; + int hc = s->chroma_y_shift ? (h+1-bottom_field)>>1 : h; linesize = s->current_picture.f->linesize[0] << field_based; uvlinesize = s->current_picture.f->linesize[1] << field_based; @@ -702,7 +703,7 @@ static av_always_inline void mpeg_motion_lowres(MpegEncContext *s, ptr_cr = ref_picture[2] + uvsrc_y * uvlinesize + uvsrc_x; if ((unsigned) src_x > FFMAX( h_edge_pos - (!!sx) - 2 * block_s, 0) || uvsrc_y<0 || - (unsigned) src_y > FFMAX((v_edge_pos >> field_based) - (!!sy) - h, 0)) { + (unsigned) src_y > FFMAX((v_edge_pos >> field_based) - (!!sy) - FFMAX(h, hc<chroma_y_shift), 0)) { s->vdsp.emulated_edge_mc(s->sc.edge_emu_buffer, ptr_y, linesize >> field_based, linesize >> field_based, 17, 17 + field_based, @@ -747,7 +748,6 @@ static av_always_inline void mpeg_motion_lowres(MpegEncContext *s, pix_op[lowres - 1](dest_y, ptr_y, linesize, h, sx, sy); if (!CONFIG_GRAY || !(s->avctx->flags & AV_CODEC_FLAG_GRAY)) { - int hc = s->chroma_y_shift ? (h+1-bottom_field)>>1 : h; uvsx = (uvsx << 2) >> lowres; uvsy = (uvsy << 2) >> lowres; if (hc) { From adfe003f518dac098ba9cdabcd6158fa55383710 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Thu, 8 Jun 2023 18:17:46 +0200 Subject: [PATCH 1520/2172] avcodec/mpegvideo_dec: Add NULL pointer checks to MPV_motion_lowres() This makes the null pointer checks match mpv_motion_internal() Fixes: NULL pointer dereference Fixes: 59671/clusterfuzz-testcase-minimized-ffmpeg_AV_CODEC_ID_MPEG1VIDEO_fuzzer-4993004566609920 Fixes: 59678/clusterfuzz-testcase-minimized-ffmpeg_AV_CODEC_ID_MPEGVIDEO_fuzzer-4893168991338496 Found-by: continuous fuzzing process https://github.com/google/oss-fuzz/tree/master/projects/ffmpeg Signed-off-by: Michael Niedermayer --- libavcodec/mpegvideo_dec.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/libavcodec/mpegvideo_dec.c b/libavcodec/mpegvideo_dec.c index c87ca77ae63..fcca147cd65 100644 --- a/libavcodec/mpegvideo_dec.c +++ b/libavcodec/mpegvideo_dec.c @@ -885,10 +885,9 @@ static inline void MPV_motion_lowres(MpegEncContext *s, s->mv[dir][1][0], s->mv[dir][1][1], block_s, mb_y); } else { - if (s->picture_structure != s->field_select[dir][0] + 1 && - s->pict_type != AV_PICTURE_TYPE_B && !s->first_field) { + if ( s->picture_structure != s->field_select[dir][0] + 1 && s->pict_type != AV_PICTURE_TYPE_B && !s->first_field + || !ref_picture[0]) { ref_picture = s->current_picture_ptr->f->data; - } mpeg_motion_lowres(s, dest_y, dest_cb, dest_cr, 0, 0, s->field_select[dir][0], @@ -901,8 +900,9 @@ static inline void MPV_motion_lowres(MpegEncContext *s, for (int i = 0; i < 2; i++) { uint8_t *const *ref2picture; - if (s->picture_structure == s->field_select[dir][i] + 1 || - s->pict_type == AV_PICTURE_TYPE_B || s->first_field) { + if ((s->picture_structure == s->field_select[dir][i] + 1 || + s->pict_type == AV_PICTURE_TYPE_B || s->first_field) && + ref_picture[0]) { ref2picture = ref_picture; } else { ref2picture = s->current_picture_ptr->f->data; @@ -933,6 +933,9 @@ static inline void MPV_motion_lowres(MpegEncContext *s, pix_op = s->h264chroma.avg_h264_chroma_pixels_tab; } } else { + if (!ref_picture[0]) { + ref_picture = s->current_picture_ptr->f->data; + } for (int i = 0; i < 2; i++) { mpeg_motion_lowres(s, dest_y, dest_cb, dest_cr, 0, 0, s->picture_structure != i + 1, From ff8a496d41422b694f66684ada97dcf49e167782 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Thu, 25 May 2023 23:40:16 +0200 Subject: [PATCH 1521/2172] avcodec/takdsp: Fix integer overflows Fixes: avcodec/takdsp.c:44:23: runtime error: signed integer overflow: -2097158 - 2147012608 cannot be represented in type 'int' Fixes: 58417/clusterfuzz-testcase-minimized-ffmpeg_AV_CODEC_ID_TAK_fuzzer-5268919664640000 Found-by: continuous fuzzing process https://github.com/google/oss-fuzz/tree/master/projects/ffmpeg Signed-off-by: Michael Niedermayer --- libavcodec/takdsp.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/libavcodec/takdsp.c b/libavcodec/takdsp.c index 881d7be5f27..b646a063db7 100644 --- a/libavcodec/takdsp.c +++ b/libavcodec/takdsp.c @@ -28,8 +28,8 @@ static void decorrelate_ls(int32_t *p1, int32_t *p2, int length) int i; for (i = 0; i < length; i++) { - int32_t a = p1[i]; - int32_t b = p2[i]; + uint32_t a = p1[i]; + uint32_t b = p2[i]; p2[i] = a + b; } } @@ -39,8 +39,8 @@ static void decorrelate_sr(int32_t *p1, int32_t *p2, int length) int i; for (i = 0; i < length; i++) { - int32_t a = p1[i]; - int32_t b = p2[i]; + uint32_t a = p1[i]; + uint32_t b = p2[i]; p1[i] = b - a; } } @@ -50,7 +50,7 @@ static void decorrelate_sm(int32_t *p1, int32_t *p2, int length) int i; for (i = 0; i < length; i++) { - int32_t a = p1[i]; + uint32_t a = p1[i]; int32_t b = p2[i]; a -= b >> 1; p1[i] = a; @@ -63,7 +63,7 @@ static void decorrelate_sf(int32_t *p1, int32_t *p2, int length, int dshift, int int i; for (i = 0; i < length; i++) { - int32_t a = p1[i]; + uint32_t a = p1[i]; int32_t b = p2[i]; b = (unsigned)((int)(dfactor * (unsigned)(b >> dshift) + 128) >> 8) << dshift; p1[i] = b - a; From a0f4d4e65093a4cb627f05d09b19c922e88cfac1 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Thu, 25 May 2023 23:40:18 +0200 Subject: [PATCH 1522/2172] avcodec/hevcdec: Avoid null pointer dereferences in MC Fixes: runtime error: pointer index expression with base 0x000000000000 overflowed to 0xfffffffffffffff8 Fixes: 58440/clusterfuzz-testcase-minimized-ffmpeg_AV_CODEC_ID_HEVC_fuzzer-5956015530311680 Found-by: continuous fuzzing process https://github.com/google/oss-fuzz/tree/master/projects/ffmpeg Signed-off-by: Michael Niedermayer --- libavcodec/hevcdec.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libavcodec/hevcdec.c b/libavcodec/hevcdec.c index a4284921cbc..fcf19b4eb6d 100644 --- a/libavcodec/hevcdec.c +++ b/libavcodec/hevcdec.c @@ -1960,13 +1960,13 @@ static void hls_prediction_unit(HEVCLocalContext *lc, int x0, int y0, if (current_mv.pred_flag & PF_L0) { ref0 = refPicList[0].ref[current_mv.ref_idx[0]]; - if (!ref0) + if (!ref0 || !ref0->frame->data[0]) return; hevc_await_progress(s, ref0, ¤t_mv.mv[0], y0, nPbH); } if (current_mv.pred_flag & PF_L1) { ref1 = refPicList[1].ref[current_mv.ref_idx[1]]; - if (!ref1) + if (!ref1 || !ref1->frame->data[0]) return; hevc_await_progress(s, ref1, ¤t_mv.mv[1], y0, nPbH); } From 6f2cf88771bd8c3986b0c8b6404eabc5b37d8a6e Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Thu, 25 May 2023 23:40:19 +0200 Subject: [PATCH 1523/2172] avcodec/hevc_refs: Check that nb_refs stays <= HEVC_MAX_REFS Fixes: 58528/clusterfuzz-testcase-minimized-ffmpeg_AV_CODEC_ID_HEVC_fuzzer-5834725318328320 Fixes: index 16 out of bounds for type 'int [16]' Found-by: continuous fuzzing process https://github.com/google/oss-fuzz/tree/master/projects/ffmpeg Signed-off-by: Michael Niedermayer --- libavcodec/hevc_refs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavcodec/hevc_refs.c b/libavcodec/hevc_refs.c index a4af6ca6568..3aa8e199504 100644 --- a/libavcodec/hevc_refs.c +++ b/libavcodec/hevc_refs.c @@ -354,7 +354,7 @@ int ff_hevc_slice_rpl(HEVCContext *s) } } // Construct RefPicList0, RefPicList1 (8-8, 8-10) - if (s->ps.pps->pps_curr_pic_ref_enabled_flag) { + if (s->ps.pps->pps_curr_pic_ref_enabled_flag && rpl_tmp.nb_refs < HEVC_MAX_REFS) { rpl_tmp.list[rpl_tmp.nb_refs] = s->ref->poc; rpl_tmp.ref[rpl_tmp.nb_refs] = s->ref; rpl_tmp.isLongTerm[rpl_tmp.nb_refs] = 1; From 61047f0f82c76620cc42888958dd9834bcaa18fb Mon Sep 17 00:00:00 2001 From: Leo Izen Date: Mon, 12 Jun 2023 09:22:56 -0400 Subject: [PATCH 1524/2172] avformat/jpegxl_anim_dec: avoid overrun with jxlp boxes in container This switches the jpegxl_collect_codestream_header function to use avcodec/bytestream2, which better enforces barriers, and should avoid overrunning buffers with jxlp boxes if the size is zero or if the size is so small the box is invalid. Signed-off-by: Leo Izen --- libavformat/jpegxl_anim_dec.c | 56 +++++++++++++++++++---------------- 1 file changed, 30 insertions(+), 26 deletions(-) diff --git a/libavformat/jpegxl_anim_dec.c b/libavformat/jpegxl_anim_dec.c index 6ea6c46d8f4..ec400c955c7 100644 --- a/libavformat/jpegxl_anim_dec.c +++ b/libavformat/jpegxl_anim_dec.c @@ -28,6 +28,7 @@ #include #include +#include "libavcodec/bytestream.h" #define BITSTREAM_READER_LE #include "libavcodec/get_bits.h" @@ -48,62 +49,65 @@ typedef struct JXLAnimDemuxContext { * returns the number of bytes consumed from input, may be greater than input_len * if the input doesn't end on an ISOBMFF-box boundary */ -static int jpegxl_collect_codestream_header(const uint8_t *input_buffer, int input_len, uint8_t *buffer, int buflen, int *copied) { - const uint8_t *b = input_buffer; +static int jpegxl_collect_codestream_header(const uint8_t *input_buffer, int input_len, + uint8_t *buffer, int buflen, int *copied) { + GetByteContext gb; *copied = 0; + bytestream2_init(&gb, input_buffer, input_len); while (1) { uint64_t size; uint32_t tag; int head_size = 8; - if (b - input_buffer >= input_len - 16) + if (bytestream2_get_bytes_left(&gb) < 16) break; - size = AV_RB32(b); - b += 4; + size = bytestream2_get_be32(&gb); if (size == 1) { - size = AV_RB64(b); - b += 8; + size = bytestream2_get_be64(&gb); head_size = 16; } /* invalid ISOBMFF size */ - if (size > 0 && size <= head_size) + if (size && size <= head_size) return AVERROR_INVALIDDATA; - if (size > 0) + if (size) size -= head_size; - tag = AV_RL32(b); - b += 4; + tag = bytestream2_get_le32(&gb); if (tag == MKTAG('j', 'x', 'l', 'p')) { - b += 4; - size -= 4; + if (bytestream2_get_bytes_left(&gb) < 4) + break; + bytestream2_skip(&gb, 4); + if (size) { + if (size <= 4) + return AVERROR_INVALIDDATA; + size -= 4; + } } + /* + * size = 0 means "until EOF". this is legal but uncommon + * here we just set it to the remaining size of the probe buffer + */ + if (!size) + size = bytestream2_get_bytes_left(&gb); if (tag == MKTAG('j', 'x', 'l', 'c') || tag == MKTAG('j', 'x', 'l', 'p')) { - /* - * size = 0 means "until EOF". this is legal but uncommon - * here we just set it to the remaining size of the probe buffer - * which at this point should always be nonnegative - */ - if (size == 0 || size > input_len - (b - input_buffer)) - size = input_len - (b - input_buffer); - if (size > buflen - *copied) size = buflen - *copied; /* * arbitrary chunking of the payload makes this memcpy hard to avoid * in practice this will only be performed one or two times at most */ - memcpy(buffer + *copied, b, size); - *copied += size; + *copied += bytestream2_get_buffer(&gb, buffer + *copied, size); + } else { + bytestream2_skip(&gb, size); } - b += size; - if (b >= input_buffer + input_len || *copied >= buflen) + if (bytestream2_get_bytes_left(&gb) <= 0 || *copied >= buflen) break; } - return b - input_buffer; + return bytestream2_tell(&gb); } static int jpegxl_anim_probe(const AVProbeData *p) From 9fc141f32d52099a6bfeba6e4e7ee2ce7fadc833 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Sun, 18 Jun 2023 23:50:16 +0200 Subject: [PATCH 1525/2172] avformat/jpegxl_anim_dec: Perform operations in a different order Fixes: OOM Fixes: 59802/clusterfuzz-testcase-minimized-ffmpeg_dem_JPEGXL_ANIM_fuzzer-5681765466112000 Found-by: continuous fuzzing process https://github.com/google/oss-fuzz/tree/master/projects/ffmpeg Signed-off-by: Michael Niedermayer --- libavformat/jpegxl_anim_dec.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavformat/jpegxl_anim_dec.c b/libavformat/jpegxl_anim_dec.c index ec400c955c7..8d6ea5005c7 100644 --- a/libavformat/jpegxl_anim_dec.c +++ b/libavformat/jpegxl_anim_dec.c @@ -231,7 +231,7 @@ static int jpegxl_anim_read_packet(AVFormatContext *s, AVPacket *pkt) if (ctx->initial && size < ctx->initial->size) size = ctx->initial->size; - if ((ret = av_new_packet(pkt, size) < 0)) + if ((ret = av_new_packet(pkt, size)) < 0) return ret; if (ctx->initial) { From 5e9986fd2d95a294ba6d2256ecff977ad8911112 Mon Sep 17 00:00:00 2001 From: James Almer Date: Sun, 18 Jun 2023 23:40:46 -0300 Subject: [PATCH 1526/2172] avformat/evc: use get_ue_golomb_long() Fixes compilation of shared libraries, as well as correctly parses width and height values. Signed-off-by: James Almer --- libavformat/evc.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/libavformat/evc.c b/libavformat/evc.c index dc75ccb56da..ba949ebf6e5 100644 --- a/libavformat/evc.c +++ b/libavformat/evc.c @@ -123,7 +123,7 @@ static int evcc_parse_sps(const uint8_t *bs, int bs_size, EVCDecoderConfiguratio if (init_get_bits8(&gb, bs, bs_size) < 0) return 0; - sps.sps_seq_parameter_set_id = get_ue_golomb(&gb); + sps.sps_seq_parameter_set_id = get_ue_golomb_long(&gb); if (sps_seq_parameter_set_id >= EVC_MAX_SPS_COUNT) return 0; @@ -141,13 +141,13 @@ static int evcc_parse_sps(const uint8_t *bs, int bs_size, EVCDecoderConfiguratio // 1 - 4:2:0 // 2 - 4:2:2 // 3 - 4:4:4 - sps.chroma_format_idc = get_ue_golomb(&gb); + sps.chroma_format_idc = get_ue_golomb_long(&gb); - sps.pic_width_in_luma_samples = get_ue_golomb(&gb); - sps.pic_height_in_luma_samples = get_ue_golomb(&gb); + sps.pic_width_in_luma_samples = get_ue_golomb_long(&gb); + sps.pic_height_in_luma_samples = get_ue_golomb_long(&gb); - sps.bit_depth_luma_minus8 = get_ue_golomb(&gb); - sps.bit_depth_chroma_minus8 = get_ue_golomb(&gb); + sps.bit_depth_luma_minus8 = get_ue_golomb_long(&gb); + sps.bit_depth_chroma_minus8 = get_ue_golomb_long(&gb); evcc->profile_idc = sps.profile_idc; evcc->level_idc = sps.level_idc; From a8aeab107e274e8e3764a9004ac5209c8084127e Mon Sep 17 00:00:00 2001 From: Zhao Zhili Date: Thu, 18 May 2023 05:23:38 +0800 Subject: [PATCH 1527/2172] avcodec/cbs: add API to discard units by AVDiscard --- libavcodec/cbs.c | 21 +++++++++++++++++++++ libavcodec/cbs.h | 17 +++++++++++++++++ libavcodec/cbs_internal.h | 6 ++++++ 3 files changed, 44 insertions(+) diff --git a/libavcodec/cbs.c b/libavcodec/cbs.c index 504197e06d4..cf5211249bb 100644 --- a/libavcodec/cbs.c +++ b/libavcodec/cbs.c @@ -1026,3 +1026,24 @@ int ff_cbs_make_unit_writable(CodedBitstreamContext *ctx, av_buffer_unref(&ref); return 0; } + +void ff_cbs_discard_units(CodedBitstreamContext *ctx, + CodedBitstreamFragment *frag, + enum AVDiscard skip, + int flags) +{ + if (!ctx->codec->discarded_unit) + return; + + for (int i = frag->nb_units - 1; i >= 0; i--) { + if (ctx->codec->discarded_unit(ctx, &frag->units[i], skip)) { + // discard all units + if (!(flags & DISCARD_FLAG_KEEP_NON_VCL)) { + ff_cbs_fragment_free(frag); + return; + } + + ff_cbs_delete_unit(frag, i); + } + } +} diff --git a/libavcodec/cbs.h b/libavcodec/cbs.h index ee21623dacb..b4131db5fe2 100644 --- a/libavcodec/cbs.h +++ b/libavcodec/cbs.h @@ -26,6 +26,7 @@ #include "codec_id.h" #include "codec_par.h" +#include "defs.h" #include "packet.h" @@ -432,5 +433,21 @@ int ff_cbs_make_unit_refcounted(CodedBitstreamContext *ctx, int ff_cbs_make_unit_writable(CodedBitstreamContext *ctx, CodedBitstreamUnit *unit); +enum CbsDiscardFlags { + DISCARD_FLAG_NONE = 0, + + /** + * keep non-vcl units even if the picture has been dropped. + */ + DISCARD_FLAG_KEEP_NON_VCL = 0x01, +}; + +/** + * Discard units accroding to 'skip'. + */ +void ff_cbs_discard_units(CodedBitstreamContext *ctx, + CodedBitstreamFragment *frag, + enum AVDiscard skip, + int flags); #endif /* AVCODEC_CBS_H */ diff --git a/libavcodec/cbs_internal.h b/libavcodec/cbs_internal.h index e585c779341..077954eee59 100644 --- a/libavcodec/cbs_internal.h +++ b/libavcodec/cbs_internal.h @@ -133,6 +133,12 @@ typedef struct CodedBitstreamType { CodedBitstreamUnit *unit, PutBitContext *pbc); + // Return 1 when the unit should be dropped according to 'skip', + // 0 otherwise. + int (*discarded_unit)(CodedBitstreamContext *ctx, + const CodedBitstreamUnit *unit, + enum AVDiscard skip); + // Read the data from all of frag->units and assemble it into // a bitstream for the whole fragment. int (*assemble_fragment)(CodedBitstreamContext *ctx, From e7cde0cbd5ce5a6bcb0a80a0ace0596bffd906f2 Mon Sep 17 00:00:00 2001 From: Zhao Zhili Date: Thu, 18 May 2023 05:23:39 +0800 Subject: [PATCH 1528/2172] avcodec/cbs_h2645: add discarded_unit implementation for H.264 --- libavcodec/cbs_h2645.c | 53 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 53 insertions(+) diff --git a/libavcodec/cbs_h2645.c b/libavcodec/cbs_h2645.c index 80e48829af9..c616ac22021 100644 --- a/libavcodec/cbs_h2645.c +++ b/libavcodec/cbs_h2645.c @@ -1213,6 +1213,58 @@ static int cbs_h265_write_nal_unit(CodedBitstreamContext *ctx, return 0; } +static int cbs_h264_discarded_nal_unit(CodedBitstreamContext *ctx, + const CodedBitstreamUnit *unit, + enum AVDiscard skip) +{ + H264RawNALUnitHeader *header; + H264RawSliceHeader *slice; + int slice_type_i, slice_type_b, slice_type_si; + + if (skip <= AVDISCARD_DEFAULT) + return 0; + + // keep non-VCL + if (unit->type != H264_NAL_SLICE && + unit->type != H264_NAL_IDR_SLICE && + unit->type != H264_NAL_AUXILIARY_SLICE) + return 0; + + if (skip >= AVDISCARD_ALL) + return 1; + + if (skip >= AVDISCARD_NONKEY && unit->type != H264_NAL_IDR_SLICE) + return 1; + + header = (H264RawNALUnitHeader *)unit->content; + if (!header) { + av_log(ctx->log_ctx, AV_LOG_WARNING, + "h264 nal unit header is null, missing decompose?\n"); + return 0; + } + + if (skip >= AVDISCARD_NONREF && !header->nal_ref_idc) + return 1; + + slice = (H264RawSliceHeader *)unit->content; + if (!slice) { + av_log(ctx->log_ctx, AV_LOG_WARNING, + "h264 slice header is null, missing decompose?\n"); + return 0; + } + + slice_type_i = slice->slice_type % 5 == 2; + slice_type_b = slice->slice_type % 5 == 1; + slice_type_si = slice->slice_type % 5 == 4; + + if (skip >= AVDISCARD_BIDIR && slice_type_b) + return 1; + if (skip >= AVDISCARD_NONINTRA && !slice_type_i && !slice_type_si) + return 1; + + return 0; +} + static int cbs_h2645_unit_requires_zero_byte(enum AVCodecID codec_id, CodedBitstreamUnitType type, int nal_unit_index) @@ -1441,6 +1493,7 @@ const CodedBitstreamType ff_cbs_type_h264 = { .split_fragment = &cbs_h2645_split_fragment, .read_unit = &cbs_h264_read_nal_unit, .write_unit = &cbs_h264_write_nal_unit, + .discarded_unit = &cbs_h264_discarded_nal_unit, .assemble_fragment = &cbs_h2645_assemble_fragment, .flush = &cbs_h264_flush, From 41445840107d1b0e952ba0b49b4468a5a911ead1 Mon Sep 17 00:00:00 2001 From: Zhao Zhili Date: Thu, 18 May 2023 05:23:40 +0800 Subject: [PATCH 1529/2172] avcodec/cbs_h2645: add discard_unit implementation for H.265 --- libavcodec/cbs_h2645.c | 74 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 74 insertions(+) diff --git a/libavcodec/cbs_h2645.c b/libavcodec/cbs_h2645.c index c616ac22021..f2e59f1ac77 100644 --- a/libavcodec/cbs_h2645.c +++ b/libavcodec/cbs_h2645.c @@ -1265,6 +1265,79 @@ static int cbs_h264_discarded_nal_unit(CodedBitstreamContext *ctx, return 0; } +static int cbs_h265_discarded_nal_unit(CodedBitstreamContext *ctx, + const CodedBitstreamUnit *unit, + enum AVDiscard skip) +{ + H265RawSliceHeader *slice; + + if (skip <= AVDISCARD_DEFAULT) + return 0; + + switch (unit->type) { + case HEVC_NAL_BLA_W_LP: + case HEVC_NAL_BLA_W_RADL: + case HEVC_NAL_BLA_N_LP: + case HEVC_NAL_IDR_W_RADL: + case HEVC_NAL_IDR_N_LP: + case HEVC_NAL_CRA_NUT: + // IRAP slice + if (skip < AVDISCARD_ALL) + return 0; + break; + + case HEVC_NAL_TRAIL_R: + case HEVC_NAL_TRAIL_N: + case HEVC_NAL_TSA_N: + case HEVC_NAL_TSA_R: + case HEVC_NAL_STSA_N: + case HEVC_NAL_STSA_R: + case HEVC_NAL_RADL_N: + case HEVC_NAL_RADL_R: + case HEVC_NAL_RASL_N: + case HEVC_NAL_RASL_R: + // Slice + break; + default: + // Don't discard non-slice nal. + return 0; + } + + if (skip >= AVDISCARD_NONKEY) + return 1; + + slice = (H265RawSliceHeader *)unit->content; + if (!slice) { + av_log(ctx->log_ctx, AV_LOG_WARNING, + "h265 slice header is null, missing decompose?\n"); + return 0; + } + + if (skip >= AVDISCARD_NONINTRA && slice->slice_type != HEVC_SLICE_I) + return 1; + if (skip >= AVDISCARD_BIDIR && slice->slice_type == HEVC_SLICE_B) + return 1; + + if (skip >= AVDISCARD_NONREF) { + switch (unit->type) { + case HEVC_NAL_TRAIL_N: + case HEVC_NAL_TSA_N: + case HEVC_NAL_STSA_N: + case HEVC_NAL_RADL_N: + case HEVC_NAL_RASL_N: + case HEVC_NAL_VCL_N10: + case HEVC_NAL_VCL_N12: + case HEVC_NAL_VCL_N14: + // non-ref + return 1; + default: + break; + } + } + + return 0; +} + static int cbs_h2645_unit_requires_zero_byte(enum AVCodecID codec_id, CodedBitstreamUnitType type, int nal_unit_index) @@ -1510,6 +1583,7 @@ const CodedBitstreamType ff_cbs_type_h265 = { .split_fragment = &cbs_h2645_split_fragment, .read_unit = &cbs_h265_read_nal_unit, .write_unit = &cbs_h265_write_nal_unit, + .discarded_unit = &cbs_h265_discarded_nal_unit, .assemble_fragment = &cbs_h2645_assemble_fragment, .flush = &cbs_h265_flush, From dfa0e24e98576016cdeb9740303f3a056af52281 Mon Sep 17 00:00:00 2001 From: Zhao Zhili Date: Thu, 18 May 2023 05:23:41 +0800 Subject: [PATCH 1530/2172] avcodec/filter_units_bsf: add skip frame support --- libavcodec/filter_units_bsf.c | 42 +++++++++++++++++++++++++++++++++-- libavcodec/version.h | 2 +- 2 files changed, 41 insertions(+), 3 deletions(-) diff --git a/libavcodec/filter_units_bsf.c b/libavcodec/filter_units_bsf.c index 38756baf420..e4c2cadbd51 100644 --- a/libavcodec/filter_units_bsf.c +++ b/libavcodec/filter_units_bsf.c @@ -34,6 +34,8 @@ typedef struct FilterUnitsContext { const char *pass_types; const char *remove_types; + enum AVDiscard discard; + int discard_flags; enum { NOOP, @@ -109,7 +111,7 @@ static int filter_units_filter(AVBSFContext *bsf, AVPacket *pkt) if (err < 0) return err; - if (ctx->mode == NOOP) + if (ctx->mode == NOOP && ctx->discard <= AVDISCARD_DEFAULT) return 0; err = ff_cbs_read_packet(ctx->cbc, frag, pkt); @@ -118,6 +120,8 @@ static int filter_units_filter(AVBSFContext *bsf, AVPacket *pkt) goto fail; } + ff_cbs_discard_units(ctx->cbc, frag, ctx->discard, ctx->discard_flags); + if (ctx->mode != NOOP) { for (i = frag->nb_units - 1; i >= 0; i--) { for (j = 0; j < ctx->nb_types; j++) { if (frag->units[i].type == ctx->type_list[j]) @@ -127,6 +131,7 @@ static int filter_units_filter(AVBSFContext *bsf, AVPacket *pkt) : j >= ctx->nb_types) ff_cbs_delete_unit(frag, i); } + } if (frag->nb_units == 0) { // Don't return packets with nothing in them. @@ -175,7 +180,7 @@ static int filter_units_init(AVBSFContext *bsf) av_log(bsf, AV_LOG_ERROR, "Failed to parse remove_types.\n"); return err; } - } else { + } else if (ctx->discard == AVDISCARD_NONE) { return 0; } @@ -183,9 +188,11 @@ static int filter_units_init(AVBSFContext *bsf) if (err < 0) return err; + if (ctx->discard == AVDISCARD_NONE) { // Don't actually decompose anything, we only want the unit data. ctx->cbc->decompose_unit_types = ctx->type_list; ctx->cbc->nb_decompose_unit_types = 0; + } if (bsf->par_in->extradata) { CodedBitstreamFragment *frag = &ctx->fragment; @@ -225,6 +232,37 @@ static const AVOption filter_units_options[] = { OFFSET(remove_types), AV_OPT_TYPE_STRING, { .str = NULL }, .flags = FLAGS }, + { "discard", "Remove the selected frames", + OFFSET(discard), AV_OPT_TYPE_INT, + { .i64 = AVDISCARD_NONE }, INT_MIN, INT_MAX, FLAGS, "discard"}, + { "none" , "discard none", + 0, AV_OPT_TYPE_CONST, + { .i64 = AVDISCARD_NONE }, INT_MIN, INT_MAX, FLAGS, "discard"}, + { "default" , "discard none, but can be changed after dynamically", + 0, AV_OPT_TYPE_CONST, + { .i64 = AVDISCARD_DEFAULT }, INT_MIN, INT_MAX, FLAGS, "discard"}, + { "nonref", "discard all non-reference frames", + 0, AV_OPT_TYPE_CONST, + { .i64 = AVDISCARD_NONREF }, INT_MIN, INT_MAX, FLAGS, "discard"}, + { "bidir", "discard all bidirectional frames", + 0, AV_OPT_TYPE_CONST, + { .i64 = AVDISCARD_BIDIR }, INT_MIN, INT_MAX, FLAGS, "discard"}, + { "nonintra", "discard all frames except I frames", + 0, AV_OPT_TYPE_CONST, + { .i64 = AVDISCARD_NONINTRA }, INT_MIN, INT_MAX, FLAGS, "discard"}, + { "nonkey", "discard all frames except keyframes", + 0, AV_OPT_TYPE_CONST, + { .i64 = AVDISCARD_NONKEY }, INT_MIN, INT_MAX, FLAGS, "discard"}, + { "all", "discard all frames", + 0, AV_OPT_TYPE_CONST, + { .i64 = AVDISCARD_ALL }, INT_MIN, INT_MAX, FLAGS, "discard"}, + + { "discard_flags", "flags to control the discard frame behavior", + OFFSET(discard_flags), AV_OPT_TYPE_FLAGS, + { .i64 = DISCARD_FLAG_NONE }, INT_MIN, INT_MAX, FLAGS, "discard_flags"}, + { "keep_non_vcl", "non-vcl units even if the picture has been dropped", + 0, AV_OPT_TYPE_CONST, + { .i64 = DISCARD_FLAG_KEEP_NON_VCL }, INT_MIN, INT_MAX, FLAGS, "discard_flags"}, { NULL } }; diff --git a/libavcodec/version.h b/libavcodec/version.h index d0980e28de8..ef9018e70b9 100644 --- a/libavcodec/version.h +++ b/libavcodec/version.h @@ -30,7 +30,7 @@ #include "version_major.h" #define LIBAVCODEC_VERSION_MINOR 20 -#define LIBAVCODEC_VERSION_MICRO 100 +#define LIBAVCODEC_VERSION_MICRO 101 #define LIBAVCODEC_VERSION_INT AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \ LIBAVCODEC_VERSION_MINOR, \ From 4a00cd4fe32a4b9314b3b45354caf37387f5f42a Mon Sep 17 00:00:00 2001 From: Zhao Zhili Date: Thu, 18 May 2023 05:23:42 +0800 Subject: [PATCH 1531/2172] avcodec/filter_units_bsf: reindent after previous commit --- libavcodec/filter_units_bsf.c | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/libavcodec/filter_units_bsf.c b/libavcodec/filter_units_bsf.c index e4c2cadbd51..93367531486 100644 --- a/libavcodec/filter_units_bsf.c +++ b/libavcodec/filter_units_bsf.c @@ -122,15 +122,15 @@ static int filter_units_filter(AVBSFContext *bsf, AVPacket *pkt) ff_cbs_discard_units(ctx->cbc, frag, ctx->discard, ctx->discard_flags); if (ctx->mode != NOOP) { - for (i = frag->nb_units - 1; i >= 0; i--) { - for (j = 0; j < ctx->nb_types; j++) { - if (frag->units[i].type == ctx->type_list[j]) - break; + for (i = frag->nb_units - 1; i >= 0; i--) { + for (j = 0; j < ctx->nb_types; j++) { + if (frag->units[i].type == ctx->type_list[j]) + break; + } + if (ctx->mode == REMOVE ? j < ctx->nb_types + : j >= ctx->nb_types) + ff_cbs_delete_unit(frag, i); } - if (ctx->mode == REMOVE ? j < ctx->nb_types - : j >= ctx->nb_types) - ff_cbs_delete_unit(frag, i); - } } if (frag->nb_units == 0) { @@ -189,9 +189,9 @@ static int filter_units_init(AVBSFContext *bsf) return err; if (ctx->discard == AVDISCARD_NONE) { - // Don't actually decompose anything, we only want the unit data. - ctx->cbc->decompose_unit_types = ctx->type_list; - ctx->cbc->nb_decompose_unit_types = 0; + // Don't actually decompose anything, we only want the unit data. + ctx->cbc->decompose_unit_types = ctx->type_list; + ctx->cbc->nb_decompose_unit_types = 0; } if (bsf->par_in->extradata) { From e349b45fa0065a9d609d1411177cfc4964131371 Mon Sep 17 00:00:00 2001 From: Zhao Zhili Date: Thu, 18 May 2023 01:49:24 +0800 Subject: [PATCH 1532/2172] fate/cbs: add tests for discard_units Signed-off-by: Zhao Zhili --- tests/fate/cbs.mak | 27 ++++++++++ tests/ref/fate/cbs-h264-discard-bidir | 37 +++++++++++++ tests/ref/fate/cbs-h264-discard-nonintra | 8 +++ tests/ref/fate/cbs-h264-discard-nonkey | 3 ++ tests/ref/fate/cbs-h264-discard-nonref | 67 ++++++++++++++++++++++++ tests/ref/fate/cbs-hevc-discard-bidir | 3 ++ tests/ref/fate/cbs-hevc-discard-nonintra | 3 ++ tests/ref/fate/cbs-hevc-discard-nonkey | 3 ++ tests/ref/fate/cbs-hevc-discard-nonref | 26 +++++++++ 9 files changed, 177 insertions(+) create mode 100644 tests/ref/fate/cbs-h264-discard-bidir create mode 100644 tests/ref/fate/cbs-h264-discard-nonintra create mode 100644 tests/ref/fate/cbs-h264-discard-nonkey create mode 100644 tests/ref/fate/cbs-h264-discard-nonref create mode 100644 tests/ref/fate/cbs-hevc-discard-bidir create mode 100644 tests/ref/fate/cbs-hevc-discard-nonintra create mode 100644 tests/ref/fate/cbs-hevc-discard-nonkey create mode 100644 tests/ref/fate/cbs-hevc-discard-nonref diff --git a/tests/fate/cbs.mak b/tests/fate/cbs.mak index a93e58ea9fe..1d6cdf93356 100644 --- a/tests/fate/cbs.mak +++ b/tests/fate/cbs.mak @@ -12,6 +12,18 @@ FATE_CBS_$(1) += fate-cbs-$(1)-$(2) fate-cbs-$(1)-$(2): CMD = md5 -c:v $(3) -i $(TARGET_SAMPLES)/$(4) -c:v copy -y -bsf:v $(1)_metadata -f $(5) endef +define FATE_CBS_DISCARD_TEST +# (codec, discard_type, sample_file, output_format, dep) +FATE_CBS_$(1)_DISCARD += fate-cbs-$(1)-discard-$(2) +tests/data/fate/cbs-$(1)-discard-$2.$(4): TAG = GEN +tests/data/fate/cbs-$(1)-discard-$2.$(4): ffmpeg$(PROGSSUF)$(EXESUF) $(5) | tests/data + $(M)$(TARGET_EXEC) $(TARGET_PATH)/ffmpeg$(PROGSSUF)$(EXESUF) -nostdin \ + -i $(3) -c:v copy -fflags +bitexact -an -bsf:v filter_units=discard=$(2) \ + -f $(4) $(TARGET_PATH)/tests/data/fate/cbs-$(1)-discard-$(2).$(4) -y 2>/dev/null +fate-cbs-$(1)-discard-$2: ffprobe tests/data/fate/cbs-$(1)-discard-$(2).$(4) +fate-cbs-$(1)-discard-$2: CMD = ffprobe_demux $(TARGET_PATH)/tests/data/fate/cbs-$(1)-discard-$(2).$(4) +endef + # AV1 read/write FATE_CBS_AV1_CONFORMANCE_SAMPLES = \ @@ -67,6 +79,13 @@ $(foreach N,$(FATE_CBS_H264_SAMPLES),$(eval $(call FATE_CBS_TEST,h264,$(basename FATE_CBS_H264-$(call FATE_CBS_DEPS, H264, H264, H264, H264, H264) = $(FATE_CBS_h264) +$(eval $(call FATE_CBS_DISCARD_TEST,h264,nonref,$(TARGET_SAMPLES)/h264/interlaced_crop.mp4,mp4)) +$(eval $(call FATE_CBS_DISCARD_TEST,h264,bidir,$(TARGET_SAMPLES)/h264/interlaced_crop.mp4,mp4)) +$(eval $(call FATE_CBS_DISCARD_TEST,h264,nonintra,$(TARGET_SAMPLES)/h264/interlaced_crop.mp4,mp4)) +$(eval $(call FATE_CBS_DISCARD_TEST,h264,nonkey,$(TARGET_SAMPLES)/h264/interlaced_crop.mp4,mp4)) + +FATE_CBS_H264-$(call ALLYES, MP4_MUXER, H264_PARSER, FILTER_UNITS_BSF, H264_MUXER) += $(FATE_CBS_h264_DISCARD) + FATE_H264_REDUNDANT_PPS-$(call REMUX, H264, MOV_DEMUXER H264_REDUNDANT_PPS_BSF \ H264_DECODER H264_PARSER RAWVIDEO_ENCODER) \ @@ -133,6 +152,14 @@ FATE_CBS_HEVC_SAMPLES = \ $(foreach N,$(FATE_CBS_HEVC_SAMPLES),$(eval $(call FATE_CBS_TEST,hevc,$(basename $(N)),hevc,hevc-conformance/$(N),hevc))) FATE_CBS_HEVC-$(call FATE_CBS_DEPS, HEVC, HEVC, HEVC, HEVC, HEVC) = $(FATE_CBS_hevc) + +$(eval $(call FATE_CBS_DISCARD_TEST,hevc,nonref,$(TARGET_PATH)/tests/data/hevc-mp4.mov,mp4,tests/data/hevc-mp4.mov)) +$(eval $(call FATE_CBS_DISCARD_TEST,hevc,bidir,$(TARGET_PATH)/tests/data/hevc-mp4.mov,mp4,tests/data/hevc-mp4.mov)) +$(eval $(call FATE_CBS_DISCARD_TEST,hevc,nonintra,$(TARGET_PATH)/tests/data/hevc-mp4.mov,mp4,tests/data/hevc-mp4.mov)) +$(eval $(call FATE_CBS_DISCARD_TEST,hevc,nonkey,$(TARGET_PATH)/tests/data/hevc-mp4.mov,mp4,tests/data/hevc-mp4.mov)) + +FATE_CBS_HEVC-$(call ALLYES, MP4_MUXER, HEVC_PARSER, FILTER_UNITS_BSF, HEVC_MUXER) += $(FATE_CBS_hevc_DISCARD) + FATE_SAMPLES_AVCONV += $(FATE_CBS_HEVC-yes) fate-cbs-hevc: $(FATE_CBS_HEVC-yes) diff --git a/tests/ref/fate/cbs-h264-discard-bidir b/tests/ref/fate/cbs-h264-discard-bidir new file mode 100644 index 00000000000..0a3f0b22c1c --- /dev/null +++ b/tests/ref/fate/cbs-h264-discard-bidir @@ -0,0 +1,37 @@ +packet|codec_type=video|stream_index=0|pts=0|pts_time=0.000000|dts=-1024|dts_time=-0.080000|duration=512|duration_time=0.040000|size=22583|pos=48|flags=K__|data_hash=CRC32:69e4d65d +packet|codec_type=video|stream_index=0|pts=2048|pts_time=0.160000|dts=-512|dts_time=-0.040000|duration=512|duration_time=0.040000|size=4023|pos=22631|flags=___|data_hash=CRC32:0013cf12 +packet|codec_type=video|stream_index=0|pts=4096|pts_time=0.320000|dts=1536|dts_time=0.120000|duration=512|duration_time=0.040000|size=4214|pos=26654|flags=___|data_hash=CRC32:3d1a75de +packet|codec_type=video|stream_index=0|pts=6144|pts_time=0.480000|dts=3584|dts_time=0.280000|duration=512|duration_time=0.040000|size=4067|pos=30868|flags=___|data_hash=CRC32:0ae6ba93 +packet|codec_type=video|stream_index=0|pts=8192|pts_time=0.640000|dts=5632|dts_time=0.440000|duration=512|duration_time=0.040000|size=4223|pos=34935|flags=___|data_hash=CRC32:653ad50a +packet|codec_type=video|stream_index=0|pts=10240|pts_time=0.800000|dts=7680|dts_time=0.600000|duration=512|duration_time=0.040000|size=4757|pos=39158|flags=___|data_hash=CRC32:9c63fc60 +packet|codec_type=video|stream_index=0|pts=12288|pts_time=0.960000|dts=9728|dts_time=0.760000|duration=512|duration_time=0.040000|size=26559|pos=43915|flags=K__|data_hash=CRC32:3d91ff30 +packet|codec_type=video|stream_index=0|pts=14336|pts_time=1.120000|dts=11776|dts_time=0.920000|duration=512|duration_time=0.040000|size=3419|pos=70474|flags=___|data_hash=CRC32:a16c6e06 +packet|codec_type=video|stream_index=0|pts=16384|pts_time=1.280000|dts=13824|dts_time=1.080000|duration=512|duration_time=0.040000|size=4270|pos=73893|flags=___|data_hash=CRC32:75f5fba0 +packet|codec_type=video|stream_index=0|pts=18432|pts_time=1.440000|dts=15872|dts_time=1.240000|duration=512|duration_time=0.040000|size=6351|pos=78163|flags=___|data_hash=CRC32:b71a5f72 +packet|codec_type=video|stream_index=0|pts=20480|pts_time=1.600000|dts=17920|dts_time=1.400000|duration=512|duration_time=0.040000|size=5504|pos=84514|flags=___|data_hash=CRC32:f4513593 +packet|codec_type=video|stream_index=0|pts=22528|pts_time=1.760000|dts=19968|dts_time=1.560000|duration=512|duration_time=0.040000|size=5330|pos=90018|flags=___|data_hash=CRC32:e0e58cfc +packet|codec_type=video|stream_index=0|pts=24576|pts_time=1.920000|dts=22016|dts_time=1.720000|duration=512|duration_time=0.040000|size=25829|pos=95348|flags=K__|data_hash=CRC32:0ffa1941 +packet|codec_type=video|stream_index=0|pts=26624|pts_time=2.080000|dts=24064|dts_time=1.880000|duration=512|duration_time=0.040000|size=3788|pos=121177|flags=___|data_hash=CRC32:b7d88c97 +packet|codec_type=video|stream_index=0|pts=28672|pts_time=2.240000|dts=26112|dts_time=2.040000|duration=512|duration_time=0.040000|size=5277|pos=124965|flags=___|data_hash=CRC32:836281be +packet|codec_type=video|stream_index=0|pts=30720|pts_time=2.400000|dts=28160|dts_time=2.200000|duration=512|duration_time=0.040000|size=4423|pos=130242|flags=___|data_hash=CRC32:16ce42d5 +packet|codec_type=video|stream_index=0|pts=32768|pts_time=2.560000|dts=30208|dts_time=2.360000|duration=512|duration_time=0.040000|size=4789|pos=134665|flags=___|data_hash=CRC32:c3253157 +packet|codec_type=video|stream_index=0|pts=34816|pts_time=2.720000|dts=32256|dts_time=2.520000|duration=512|duration_time=0.040000|size=4543|pos=139454|flags=___|data_hash=CRC32:2b284455 +packet|codec_type=video|stream_index=0|pts=36864|pts_time=2.880000|dts=34304|dts_time=2.680000|duration=512|duration_time=0.040000|size=24224|pos=143997|flags=K__|data_hash=CRC32:f4545b97 +packet|codec_type=video|stream_index=0|pts=38912|pts_time=3.040000|dts=36352|dts_time=2.840000|duration=512|duration_time=0.040000|size=3804|pos=168221|flags=___|data_hash=CRC32:9e182c9d +packet|codec_type=video|stream_index=0|pts=40960|pts_time=3.200000|dts=38400|dts_time=3.000000|duration=512|duration_time=0.040000|size=4832|pos=172025|flags=___|data_hash=CRC32:9177a3b3 +packet|codec_type=video|stream_index=0|pts=43008|pts_time=3.360000|dts=40448|dts_time=3.160000|duration=512|duration_time=0.040000|size=5169|pos=176857|flags=___|data_hash=CRC32:4b98426d +packet|codec_type=video|stream_index=0|pts=45056|pts_time=3.520000|dts=42496|dts_time=3.320000|duration=512|duration_time=0.040000|size=5428|pos=182026|flags=___|data_hash=CRC32:1b44d316 +packet|codec_type=video|stream_index=0|pts=47104|pts_time=3.680000|dts=44544|dts_time=3.480000|duration=512|duration_time=0.040000|size=5354|pos=187454|flags=___|data_hash=CRC32:e9e88511 +packet|codec_type=video|stream_index=0|pts=49152|pts_time=3.840000|dts=46592|dts_time=3.640000|duration=512|duration_time=0.040000|size=24046|pos=192808|flags=K__|data_hash=CRC32:ce41a6fe +packet|codec_type=video|stream_index=0|pts=51200|pts_time=4.000000|dts=48640|dts_time=3.800000|duration=512|duration_time=0.040000|size=4427|pos=216854|flags=___|data_hash=CRC32:69f58de5 +packet|codec_type=video|stream_index=0|pts=53248|pts_time=4.160000|dts=50688|dts_time=3.960000|duration=512|duration_time=0.040000|size=5196|pos=221281|flags=___|data_hash=CRC32:82877b2a +packet|codec_type=video|stream_index=0|pts=55296|pts_time=4.320000|dts=52736|dts_time=4.120000|duration=512|duration_time=0.040000|size=6958|pos=226477|flags=___|data_hash=CRC32:14b54257 +packet|codec_type=video|stream_index=0|pts=57344|pts_time=4.480000|dts=54784|dts_time=4.280000|duration=512|duration_time=0.040000|size=5007|pos=233435|flags=___|data_hash=CRC32:7b5d6eff +packet|codec_type=video|stream_index=0|pts=59392|pts_time=4.640000|dts=56832|dts_time=4.440000|duration=512|duration_time=0.040000|size=1864|pos=238442|flags=___|data_hash=CRC32:32f9a8b3 +packet|codec_type=video|stream_index=0|pts=61440|pts_time=4.800000|dts=58880|dts_time=4.600000|duration=512|duration_time=0.040000|size=22592|pos=240306|flags=K__|data_hash=CRC32:413e519a +packet|codec_type=video|stream_index=0|pts=61952|pts_time=4.840000|dts=60928|dts_time=4.760000|duration=512|duration_time=0.040000|size=158|pos=262898|flags=___|data_hash=CRC32:aedfe6be +packet|codec_type=video|stream_index=0|pts=62464|pts_time=4.880000|dts=61440|dts_time=4.800000|duration=512|duration_time=0.040000|size=332|pos=263056|flags=___|data_hash=CRC32:4d2e6f42 +packet|codec_type=video|stream_index=0|pts=63488|pts_time=4.960000|dts=61952|dts_time=4.840000|duration=512|duration_time=0.040000|size=326|pos=263388|flags=___|data_hash=CRC32:c9e610e6 +packet|codec_type=video|stream_index=0|pts=64000|pts_time=5.000000|dts=62976|dts_time=4.920000|duration=512|duration_time=0.040000|size=235|pos=263714|flags=___|data_hash=CRC32:5b757bc6 +stream|index=0|codec_name=h264|profile=77|codec_type=video|codec_tag_string=avc1|codec_tag=0x31637661|width=640|height=360|coded_width=640|coded_height=360|closed_captions=0|film_grain=0|has_b_frames=2|sample_aspect_ratio=1:1|display_aspect_ratio=16:9|pix_fmt=yuv420p|level=41|color_range=unknown|color_space=unknown|color_transfer=unknown|color_primaries=unknown|chroma_location=left|field_order=tt|refs=1|is_avc=true|nal_length_size=4|id=0x1|r_frame_rate=25/1|avg_frame_rate=125/18|time_base=1/12800|start_pts=0|start_time=0.000000|duration_ts=64512|duration=5.040000|bit_rate=418890|max_bit_rate=N/A|bits_per_raw_sample=8|nb_frames=35|nb_read_frames=N/A|nb_read_packets=35|extradata_size=54|extradata_hash=CRC32:148701ce|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:language=und|tag:handler_name=GPAC ISO Video Handler|tag:vendor_id=[0][0][0][0] +format|filename=cbs-h264-discard-bidir.mp4|nb_streams=1|nb_programs=0|format_name=mov,mp4,m4a,3gp,3g2,mj2|start_time=0.000000|duration=5.040000|size=264989|bit_rate=420617|probe_score=100|tag:major_brand=isom|tag:minor_version=512|tag:compatible_brands=isomiso2avc1mp41 diff --git a/tests/ref/fate/cbs-h264-discard-nonintra b/tests/ref/fate/cbs-h264-discard-nonintra new file mode 100644 index 00000000000..a482b4c8e24 --- /dev/null +++ b/tests/ref/fate/cbs-h264-discard-nonintra @@ -0,0 +1,8 @@ +packet|codec_type=video|stream_index=0|pts=0|pts_time=0.000000|dts=-1024|dts_time=-0.080000|duration=512|duration_time=0.040000|size=22583|pos=48|flags=K__|data_hash=CRC32:69e4d65d +packet|codec_type=video|stream_index=0|pts=12288|pts_time=0.960000|dts=9728|dts_time=0.760000|duration=512|duration_time=0.040000|size=26559|pos=22631|flags=K__|data_hash=CRC32:3d91ff30 +packet|codec_type=video|stream_index=0|pts=24576|pts_time=1.920000|dts=22016|dts_time=1.720000|duration=512|duration_time=0.040000|size=25829|pos=49190|flags=K__|data_hash=CRC32:0ffa1941 +packet|codec_type=video|stream_index=0|pts=36864|pts_time=2.880000|dts=34304|dts_time=2.680000|duration=512|duration_time=0.040000|size=24224|pos=75019|flags=K__|data_hash=CRC32:f4545b97 +packet|codec_type=video|stream_index=0|pts=49152|pts_time=3.840000|dts=46592|dts_time=3.640000|duration=512|duration_time=0.040000|size=24046|pos=99243|flags=K__|data_hash=CRC32:ce41a6fe +packet|codec_type=video|stream_index=0|pts=61440|pts_time=4.800000|dts=58880|dts_time=4.600000|duration=512|duration_time=0.040000|size=22592|pos=123289|flags=K__|data_hash=CRC32:413e519a +stream|index=0|codec_name=h264|profile=77|codec_type=video|codec_tag_string=avc1|codec_tag=0x31637661|width=640|height=360|coded_width=640|coded_height=360|closed_captions=0|film_grain=0|has_b_frames=2|sample_aspect_ratio=1:1|display_aspect_ratio=16:9|pix_fmt=yuv420p|level=41|color_range=unknown|color_space=unknown|color_transfer=unknown|color_primaries=unknown|chroma_location=left|field_order=tt|refs=1|is_avc=true|nal_length_size=4|id=0x1|r_frame_rate=25/12|avg_frame_rate=75/59|time_base=1/12800|start_pts=0|start_time=0.000000|duration_ts=60416|duration=4.720000|bit_rate=247174|max_bit_rate=N/A|bits_per_raw_sample=8|nb_frames=6|nb_read_frames=N/A|nb_read_packets=6|extradata_size=54|extradata_hash=CRC32:148701ce|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:language=und|tag:handler_name=GPAC ISO Video Handler|tag:vendor_id=[0][0][0][0] +format|filename=cbs-h264-discard-nonintra.mp4|nb_streams=1|nb_programs=0|format_name=mov,mp4,m4a,3gp,3g2,mj2|start_time=0.000000|duration=4.720000|size=146725|bit_rate=248686|probe_score=100|tag:major_brand=isom|tag:minor_version=512|tag:compatible_brands=isomiso2avc1mp41 diff --git a/tests/ref/fate/cbs-h264-discard-nonkey b/tests/ref/fate/cbs-h264-discard-nonkey new file mode 100644 index 00000000000..85417124fc0 --- /dev/null +++ b/tests/ref/fate/cbs-h264-discard-nonkey @@ -0,0 +1,3 @@ +packet|codec_type=video|stream_index=0|pts=0|pts_time=0.000000|dts=-1024|dts_time=-0.080000|duration=512|duration_time=0.040000|size=22583|pos=48|flags=K__|data_hash=CRC32:69e4d65d +stream|index=0|codec_name=h264|profile=77|codec_type=video|codec_tag_string=avc1|codec_tag=0x31637661|width=640|height=360|coded_width=640|coded_height=360|closed_captions=0|film_grain=0|has_b_frames=2|sample_aspect_ratio=1:1|display_aspect_ratio=16:9|pix_fmt=yuv420p|level=41|color_range=unknown|color_space=unknown|color_transfer=unknown|color_primaries=unknown|chroma_location=left|field_order=tt|refs=1|is_avc=true|nal_length_size=4|id=0x1|r_frame_rate=25/1|avg_frame_rate=25/1|time_base=1/12800|start_pts=0|start_time=0.000000|duration_ts=512|duration=0.040000|bit_rate=4516600|max_bit_rate=N/A|bits_per_raw_sample=8|nb_frames=1|nb_read_frames=N/A|nb_read_packets=1|extradata_size=54|extradata_hash=CRC32:148701ce|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:language=und|tag:handler_name=GPAC ISO Video Handler|tag:vendor_id=[0][0][0][0] +format|filename=cbs-h264-discard-nonkey.mp4|nb_streams=1|nb_programs=0|format_name=mov,mp4,m4a,3gp,3g2,mj2|start_time=0.000000|duration=0.040000|size=23427|bit_rate=4685400|probe_score=100|tag:major_brand=isom|tag:minor_version=512|tag:compatible_brands=isomiso2avc1mp41 diff --git a/tests/ref/fate/cbs-h264-discard-nonref b/tests/ref/fate/cbs-h264-discard-nonref new file mode 100644 index 00000000000..5272466a675 --- /dev/null +++ b/tests/ref/fate/cbs-h264-discard-nonref @@ -0,0 +1,67 @@ +packet|codec_type=video|stream_index=0|pts=0|pts_time=0.000000|dts=-1024|dts_time=-0.080000|duration=512|duration_time=0.040000|size=22583|pos=48|flags=K__|data_hash=CRC32:69e4d65d +packet|codec_type=video|stream_index=0|pts=2048|pts_time=0.160000|dts=-512|dts_time=-0.040000|duration=512|duration_time=0.040000|size=4023|pos=22631|flags=___|data_hash=CRC32:0013cf12 +packet|codec_type=video|stream_index=0|pts=1024|pts_time=0.080000|dts=0|dts_time=0.000000|duration=512|duration_time=0.040000|size=1098|pos=26654|flags=___|data_hash=CRC32:0fa0e9cb +packet|codec_type=video|stream_index=0|pts=4096|pts_time=0.320000|dts=1536|dts_time=0.120000|duration=512|duration_time=0.040000|size=4214|pos=27752|flags=___|data_hash=CRC32:3d1a75de +packet|codec_type=video|stream_index=0|pts=3072|pts_time=0.240000|dts=2048|dts_time=0.160000|duration=512|duration_time=0.040000|size=1119|pos=31966|flags=___|data_hash=CRC32:2f0223aa +packet|codec_type=video|stream_index=0|pts=6144|pts_time=0.480000|dts=3584|dts_time=0.280000|duration=512|duration_time=0.040000|size=4067|pos=33085|flags=___|data_hash=CRC32:0ae6ba93 +packet|codec_type=video|stream_index=0|pts=5120|pts_time=0.400000|dts=4096|dts_time=0.320000|duration=512|duration_time=0.040000|size=964|pos=37152|flags=___|data_hash=CRC32:c8ce52dc +packet|codec_type=video|stream_index=0|pts=8192|pts_time=0.640000|dts=5632|dts_time=0.440000|duration=512|duration_time=0.040000|size=4223|pos=38116|flags=___|data_hash=CRC32:653ad50a +packet|codec_type=video|stream_index=0|pts=7168|pts_time=0.560000|dts=6144|dts_time=0.480000|duration=512|duration_time=0.040000|size=1042|pos=42339|flags=___|data_hash=CRC32:9979a4e9 +packet|codec_type=video|stream_index=0|pts=10240|pts_time=0.800000|dts=7680|dts_time=0.600000|duration=512|duration_time=0.040000|size=4757|pos=43381|flags=___|data_hash=CRC32:9c63fc60 +packet|codec_type=video|stream_index=0|pts=9216|pts_time=0.720000|dts=8192|dts_time=0.640000|duration=512|duration_time=0.040000|size=1184|pos=48138|flags=___|data_hash=CRC32:b8909a00 +packet|codec_type=video|stream_index=0|pts=12288|pts_time=0.960000|dts=9728|dts_time=0.760000|duration=512|duration_time=0.040000|size=26559|pos=49322|flags=K__|data_hash=CRC32:3d91ff30 +packet|codec_type=video|stream_index=0|pts=11264|pts_time=0.880000|dts=10240|dts_time=0.800000|duration=512|duration_time=0.040000|size=1143|pos=75881|flags=___|data_hash=CRC32:cae51d5c +packet|codec_type=video|stream_index=0|pts=14336|pts_time=1.120000|dts=11776|dts_time=0.920000|duration=512|duration_time=0.040000|size=3419|pos=77024|flags=___|data_hash=CRC32:a16c6e06 +packet|codec_type=video|stream_index=0|pts=13312|pts_time=1.040000|dts=12288|dts_time=0.960000|duration=512|duration_time=0.040000|size=1130|pos=80443|flags=___|data_hash=CRC32:53fdc474 +packet|codec_type=video|stream_index=0|pts=16384|pts_time=1.280000|dts=13824|dts_time=1.080000|duration=512|duration_time=0.040000|size=4270|pos=81573|flags=___|data_hash=CRC32:75f5fba0 +packet|codec_type=video|stream_index=0|pts=15360|pts_time=1.200000|dts=14336|dts_time=1.120000|duration=512|duration_time=0.040000|size=1121|pos=85843|flags=___|data_hash=CRC32:bcef6ae6 +packet|codec_type=video|stream_index=0|pts=18432|pts_time=1.440000|dts=15872|dts_time=1.240000|duration=512|duration_time=0.040000|size=6351|pos=86964|flags=___|data_hash=CRC32:b71a5f72 +packet|codec_type=video|stream_index=0|pts=17408|pts_time=1.360000|dts=16384|dts_time=1.280000|duration=512|duration_time=0.040000|size=1190|pos=93315|flags=___|data_hash=CRC32:bb46179d +packet|codec_type=video|stream_index=0|pts=20480|pts_time=1.600000|dts=17920|dts_time=1.400000|duration=512|duration_time=0.040000|size=5504|pos=94505|flags=___|data_hash=CRC32:f4513593 +packet|codec_type=video|stream_index=0|pts=19456|pts_time=1.520000|dts=18432|dts_time=1.440000|duration=512|duration_time=0.040000|size=1242|pos=100009|flags=___|data_hash=CRC32:14765239 +packet|codec_type=video|stream_index=0|pts=22528|pts_time=1.760000|dts=19968|dts_time=1.560000|duration=512|duration_time=0.040000|size=5330|pos=101251|flags=___|data_hash=CRC32:e0e58cfc +packet|codec_type=video|stream_index=0|pts=21504|pts_time=1.680000|dts=20480|dts_time=1.600000|duration=512|duration_time=0.040000|size=1273|pos=106581|flags=___|data_hash=CRC32:47e84071 +packet|codec_type=video|stream_index=0|pts=24576|pts_time=1.920000|dts=22016|dts_time=1.720000|duration=512|duration_time=0.040000|size=25829|pos=107854|flags=K__|data_hash=CRC32:0ffa1941 +packet|codec_type=video|stream_index=0|pts=23552|pts_time=1.840000|dts=22528|dts_time=1.760000|duration=512|duration_time=0.040000|size=1208|pos=133683|flags=___|data_hash=CRC32:c36f1ddc +packet|codec_type=video|stream_index=0|pts=26624|pts_time=2.080000|dts=24064|dts_time=1.880000|duration=512|duration_time=0.040000|size=3788|pos=134891|flags=___|data_hash=CRC32:b7d88c97 +packet|codec_type=video|stream_index=0|pts=25600|pts_time=2.000000|dts=24576|dts_time=1.920000|duration=512|duration_time=0.040000|size=1189|pos=138679|flags=___|data_hash=CRC32:f1000036 +packet|codec_type=video|stream_index=0|pts=28672|pts_time=2.240000|dts=26112|dts_time=2.040000|duration=512|duration_time=0.040000|size=5277|pos=139868|flags=___|data_hash=CRC32:836281be +packet|codec_type=video|stream_index=0|pts=27648|pts_time=2.160000|dts=26624|dts_time=2.080000|duration=512|duration_time=0.040000|size=1354|pos=145145|flags=___|data_hash=CRC32:60d42d85 +packet|codec_type=video|stream_index=0|pts=30720|pts_time=2.400000|dts=28160|dts_time=2.200000|duration=512|duration_time=0.040000|size=4423|pos=146499|flags=___|data_hash=CRC32:16ce42d5 +packet|codec_type=video|stream_index=0|pts=29696|pts_time=2.320000|dts=28672|dts_time=2.240000|duration=512|duration_time=0.040000|size=1466|pos=150922|flags=___|data_hash=CRC32:bb24a5a6 +packet|codec_type=video|stream_index=0|pts=32768|pts_time=2.560000|dts=30208|dts_time=2.360000|duration=512|duration_time=0.040000|size=4789|pos=152388|flags=___|data_hash=CRC32:c3253157 +packet|codec_type=video|stream_index=0|pts=31744|pts_time=2.480000|dts=30720|dts_time=2.400000|duration=512|duration_time=0.040000|size=1437|pos=157177|flags=___|data_hash=CRC32:25effcab +packet|codec_type=video|stream_index=0|pts=34816|pts_time=2.720000|dts=32256|dts_time=2.520000|duration=512|duration_time=0.040000|size=4543|pos=158614|flags=___|data_hash=CRC32:2b284455 +packet|codec_type=video|stream_index=0|pts=33792|pts_time=2.640000|dts=32768|dts_time=2.560000|duration=512|duration_time=0.040000|size=1547|pos=163157|flags=___|data_hash=CRC32:fec8c6fd +packet|codec_type=video|stream_index=0|pts=36864|pts_time=2.880000|dts=34304|dts_time=2.680000|duration=512|duration_time=0.040000|size=24224|pos=164704|flags=K__|data_hash=CRC32:f4545b97 +packet|codec_type=video|stream_index=0|pts=35840|pts_time=2.800000|dts=34816|dts_time=2.720000|duration=512|duration_time=0.040000|size=1424|pos=188928|flags=___|data_hash=CRC32:9fea2803 +packet|codec_type=video|stream_index=0|pts=38912|pts_time=3.040000|dts=36352|dts_time=2.840000|duration=512|duration_time=0.040000|size=3804|pos=190352|flags=___|data_hash=CRC32:9e182c9d +packet|codec_type=video|stream_index=0|pts=37888|pts_time=2.960000|dts=36864|dts_time=2.880000|duration=512|duration_time=0.040000|size=1286|pos=194156|flags=___|data_hash=CRC32:80fc98bb +packet|codec_type=video|stream_index=0|pts=40960|pts_time=3.200000|dts=38400|dts_time=3.000000|duration=512|duration_time=0.040000|size=4832|pos=195442|flags=___|data_hash=CRC32:9177a3b3 +packet|codec_type=video|stream_index=0|pts=39936|pts_time=3.120000|dts=38912|dts_time=3.040000|duration=512|duration_time=0.040000|size=1448|pos=200274|flags=___|data_hash=CRC32:ddfa0b77 +packet|codec_type=video|stream_index=0|pts=43008|pts_time=3.360000|dts=40448|dts_time=3.160000|duration=512|duration_time=0.040000|size=5169|pos=201722|flags=___|data_hash=CRC32:4b98426d +packet|codec_type=video|stream_index=0|pts=41984|pts_time=3.280000|dts=40960|dts_time=3.200000|duration=512|duration_time=0.040000|size=1451|pos=206891|flags=___|data_hash=CRC32:aea0b422 +packet|codec_type=video|stream_index=0|pts=45056|pts_time=3.520000|dts=42496|dts_time=3.320000|duration=512|duration_time=0.040000|size=5428|pos=208342|flags=___|data_hash=CRC32:1b44d316 +packet|codec_type=video|stream_index=0|pts=44032|pts_time=3.440000|dts=43008|dts_time=3.360000|duration=512|duration_time=0.040000|size=1576|pos=213770|flags=___|data_hash=CRC32:cbb3eee1 +packet|codec_type=video|stream_index=0|pts=47104|pts_time=3.680000|dts=44544|dts_time=3.480000|duration=512|duration_time=0.040000|size=5354|pos=215346|flags=___|data_hash=CRC32:e9e88511 +packet|codec_type=video|stream_index=0|pts=46080|pts_time=3.600000|dts=45056|dts_time=3.520000|duration=512|duration_time=0.040000|size=1503|pos=220700|flags=___|data_hash=CRC32:b9ee459e +packet|codec_type=video|stream_index=0|pts=49152|pts_time=3.840000|dts=46592|dts_time=3.640000|duration=512|duration_time=0.040000|size=24046|pos=222203|flags=K__|data_hash=CRC32:ce41a6fe +packet|codec_type=video|stream_index=0|pts=48128|pts_time=3.760000|dts=47104|dts_time=3.680000|duration=512|duration_time=0.040000|size=1584|pos=246249|flags=___|data_hash=CRC32:4438c672 +packet|codec_type=video|stream_index=0|pts=51200|pts_time=4.000000|dts=48640|dts_time=3.800000|duration=512|duration_time=0.040000|size=4427|pos=247833|flags=___|data_hash=CRC32:69f58de5 +packet|codec_type=video|stream_index=0|pts=50176|pts_time=3.920000|dts=49152|dts_time=3.840000|duration=512|duration_time=0.040000|size=1494|pos=252260|flags=___|data_hash=CRC32:b78c9e7d +packet|codec_type=video|stream_index=0|pts=53248|pts_time=4.160000|dts=50688|dts_time=3.960000|duration=512|duration_time=0.040000|size=5196|pos=253754|flags=___|data_hash=CRC32:82877b2a +packet|codec_type=video|stream_index=0|pts=52224|pts_time=4.080000|dts=51200|dts_time=4.000000|duration=512|duration_time=0.040000|size=1485|pos=258950|flags=___|data_hash=CRC32:84553d2d +packet|codec_type=video|stream_index=0|pts=55296|pts_time=4.320000|dts=52736|dts_time=4.120000|duration=512|duration_time=0.040000|size=6958|pos=260435|flags=___|data_hash=CRC32:14b54257 +packet|codec_type=video|stream_index=0|pts=54272|pts_time=4.240000|dts=53248|dts_time=4.160000|duration=512|duration_time=0.040000|size=1189|pos=267393|flags=___|data_hash=CRC32:845381ae +packet|codec_type=video|stream_index=0|pts=57344|pts_time=4.480000|dts=54784|dts_time=4.280000|duration=512|duration_time=0.040000|size=5007|pos=268582|flags=___|data_hash=CRC32:7b5d6eff +packet|codec_type=video|stream_index=0|pts=56320|pts_time=4.400000|dts=55296|dts_time=4.320000|duration=512|duration_time=0.040000|size=454|pos=273589|flags=___|data_hash=CRC32:eccc8273 +packet|codec_type=video|stream_index=0|pts=59392|pts_time=4.640000|dts=56832|dts_time=4.440000|duration=512|duration_time=0.040000|size=1864|pos=274043|flags=___|data_hash=CRC32:32f9a8b3 +packet|codec_type=video|stream_index=0|pts=58368|pts_time=4.560000|dts=57344|dts_time=4.480000|duration=512|duration_time=0.040000|size=361|pos=275907|flags=___|data_hash=CRC32:fe582a76 +packet|codec_type=video|stream_index=0|pts=61440|pts_time=4.800000|dts=58880|dts_time=4.600000|duration=512|duration_time=0.040000|size=22592|pos=276268|flags=K__|data_hash=CRC32:413e519a +packet|codec_type=video|stream_index=0|pts=60416|pts_time=4.720000|dts=59392|dts_time=4.640000|duration=512|duration_time=0.040000|size=385|pos=298860|flags=___|data_hash=CRC32:aee406fc +packet|codec_type=video|stream_index=0|pts=61952|pts_time=4.840000|dts=60928|dts_time=4.760000|duration=512|duration_time=0.040000|size=158|pos=299245|flags=___|data_hash=CRC32:aedfe6be +packet|codec_type=video|stream_index=0|pts=62464|pts_time=4.880000|dts=61440|dts_time=4.800000|duration=512|duration_time=0.040000|size=332|pos=299403|flags=___|data_hash=CRC32:4d2e6f42 +packet|codec_type=video|stream_index=0|pts=63488|pts_time=4.960000|dts=61952|dts_time=4.840000|duration=512|duration_time=0.040000|size=326|pos=299735|flags=___|data_hash=CRC32:c9e610e6 +packet|codec_type=video|stream_index=0|pts=64000|pts_time=5.000000|dts=62976|dts_time=4.920000|duration=512|duration_time=0.040000|size=235|pos=300061|flags=___|data_hash=CRC32:5b757bc6 +stream|index=0|codec_name=h264|profile=77|codec_type=video|codec_tag_string=avc1|codec_tag=0x31637661|width=640|height=360|coded_width=640|coded_height=360|closed_captions=0|film_grain=0|has_b_frames=2|sample_aspect_ratio=1:1|display_aspect_ratio=16:9|pix_fmt=yuv420p|level=41|color_range=unknown|color_space=unknown|color_transfer=unknown|color_primaries=unknown|chroma_location=left|field_order=tt|refs=1|is_avc=true|nal_length_size=4|id=0x1|r_frame_rate=25/1|avg_frame_rate=1625/126|time_base=1/12800|start_pts=0|start_time=0.000000|duration_ts=64512|duration=5.040000|bit_rate=476584|max_bit_rate=N/A|bits_per_raw_sample=8|nb_frames=65|nb_read_frames=N/A|nb_read_packets=65|extradata_size=54|extradata_hash=CRC32:148701ce|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:language=und|tag:handler_name=GPAC ISO Video Handler|tag:vendor_id=[0][0][0][0] +format|filename=cbs-h264-discard-nonref.mp4|nb_streams=1|nb_programs=0|format_name=mov,mp4,m4a,3gp,3g2,mj2|start_time=0.000000|duration=5.040000|size=302384|bit_rate=479974|probe_score=100|tag:major_brand=isom|tag:minor_version=512|tag:compatible_brands=isomiso2avc1mp41 diff --git a/tests/ref/fate/cbs-hevc-discard-bidir b/tests/ref/fate/cbs-hevc-discard-bidir new file mode 100644 index 00000000000..399e9520768 --- /dev/null +++ b/tests/ref/fate/cbs-hevc-discard-bidir @@ -0,0 +1,3 @@ +packet|codec_type=video|stream_index=0|pts=0|pts_time=0.000000|dts=0|dts_time=0.000000|duration=48000|duration_time=0.040000|size=7454|pos=44|flags=KD_|data_hash=CRC32:4c4c3bab +stream|index=0|codec_name=hevc|profile=2|codec_type=video|codec_tag_string=hev1|codec_tag=0x31766568|width=416|height=240|coded_width=416|coded_height=240|closed_captions=0|film_grain=0|has_b_frames=3|sample_aspect_ratio=N/A|display_aspect_ratio=N/A|pix_fmt=yuv420p10le|level=60|color_range=tv|color_space=unknown|color_transfer=unknown|color_primaries=unknown|chroma_location=left|field_order=unknown|refs=1|id=0x1|r_frame_rate=25/1|avg_frame_rate=25/1|time_base=1/1200000|start_pts=0|start_time=0.000000|duration_ts=48000|duration=0.040000|bit_rate=1490800|max_bit_rate=N/A|bits_per_raw_sample=N/A|nb_frames=1|nb_read_frames=N/A|nb_read_packets=1|extradata_size=121|extradata_hash=CRC32:bd471302|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:language=und|tag:handler_name=VideoHandler|tag:vendor_id=[0][0][0][0] +format|filename=cbs-hevc-discard-bidir.mp4|nb_streams=1|nb_programs=0|format_name=mov,mp4,m4a,3gp,3g2,mj2|start_time=0.000000|duration=0.040000|size=8311|bit_rate=1662200|probe_score=100|tag:major_brand=isom|tag:minor_version=512|tag:compatible_brands=isomiso2mp41 diff --git a/tests/ref/fate/cbs-hevc-discard-nonintra b/tests/ref/fate/cbs-hevc-discard-nonintra new file mode 100644 index 00000000000..2932641bbd1 --- /dev/null +++ b/tests/ref/fate/cbs-hevc-discard-nonintra @@ -0,0 +1,3 @@ +packet|codec_type=video|stream_index=0|pts=0|pts_time=0.000000|dts=0|dts_time=0.000000|duration=48000|duration_time=0.040000|size=7454|pos=44|flags=KD_|data_hash=CRC32:4c4c3bab +stream|index=0|codec_name=hevc|profile=2|codec_type=video|codec_tag_string=hev1|codec_tag=0x31766568|width=416|height=240|coded_width=416|coded_height=240|closed_captions=0|film_grain=0|has_b_frames=3|sample_aspect_ratio=N/A|display_aspect_ratio=N/A|pix_fmt=yuv420p10le|level=60|color_range=tv|color_space=unknown|color_transfer=unknown|color_primaries=unknown|chroma_location=left|field_order=unknown|refs=1|id=0x1|r_frame_rate=25/1|avg_frame_rate=25/1|time_base=1/1200000|start_pts=0|start_time=0.000000|duration_ts=48000|duration=0.040000|bit_rate=1490800|max_bit_rate=N/A|bits_per_raw_sample=N/A|nb_frames=1|nb_read_frames=N/A|nb_read_packets=1|extradata_size=121|extradata_hash=CRC32:bd471302|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:language=und|tag:handler_name=VideoHandler|tag:vendor_id=[0][0][0][0] +format|filename=cbs-hevc-discard-nonintra.mp4|nb_streams=1|nb_programs=0|format_name=mov,mp4,m4a,3gp,3g2,mj2|start_time=0.000000|duration=0.040000|size=8311|bit_rate=1662200|probe_score=100|tag:major_brand=isom|tag:minor_version=512|tag:compatible_brands=isomiso2mp41 diff --git a/tests/ref/fate/cbs-hevc-discard-nonkey b/tests/ref/fate/cbs-hevc-discard-nonkey new file mode 100644 index 00000000000..47e916c4164 --- /dev/null +++ b/tests/ref/fate/cbs-hevc-discard-nonkey @@ -0,0 +1,3 @@ +packet|codec_type=video|stream_index=0|pts=0|pts_time=0.000000|dts=0|dts_time=0.000000|duration=48000|duration_time=0.040000|size=7454|pos=44|flags=KD_|data_hash=CRC32:4c4c3bab +stream|index=0|codec_name=hevc|profile=2|codec_type=video|codec_tag_string=hev1|codec_tag=0x31766568|width=416|height=240|coded_width=416|coded_height=240|closed_captions=0|film_grain=0|has_b_frames=3|sample_aspect_ratio=N/A|display_aspect_ratio=N/A|pix_fmt=yuv420p10le|level=60|color_range=tv|color_space=unknown|color_transfer=unknown|color_primaries=unknown|chroma_location=left|field_order=unknown|refs=1|id=0x1|r_frame_rate=25/1|avg_frame_rate=25/1|time_base=1/1200000|start_pts=0|start_time=0.000000|duration_ts=48000|duration=0.040000|bit_rate=1490800|max_bit_rate=N/A|bits_per_raw_sample=N/A|nb_frames=1|nb_read_frames=N/A|nb_read_packets=1|extradata_size=121|extradata_hash=CRC32:bd471302|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:language=und|tag:handler_name=VideoHandler|tag:vendor_id=[0][0][0][0] +format|filename=cbs-hevc-discard-nonkey.mp4|nb_streams=1|nb_programs=0|format_name=mov,mp4,m4a,3gp,3g2,mj2|start_time=0.000000|duration=0.040000|size=8311|bit_rate=1662200|probe_score=100|tag:major_brand=isom|tag:minor_version=512|tag:compatible_brands=isomiso2mp41 diff --git a/tests/ref/fate/cbs-hevc-discard-nonref b/tests/ref/fate/cbs-hevc-discard-nonref new file mode 100644 index 00000000000..5090ef32e1f --- /dev/null +++ b/tests/ref/fate/cbs-hevc-discard-nonref @@ -0,0 +1,26 @@ +packet|codec_type=video|stream_index=0|pts=-144000|pts_time=-0.120000|dts=-144000|dts_time=-0.120000|duration=48000|duration_time=0.040000|size=7454|pos=44|flags=KD_|data_hash=CRC32:4c4c3bab +packet|codec_type=video|stream_index=0|pts=-96000|pts_time=-0.080000|dts=-96000|dts_time=-0.080000|duration=48000|duration_time=0.040000|size=2622|pos=7498|flags=_D_|data_hash=CRC32:a49f2745 +packet|codec_type=video|stream_index=0|pts=-48000|pts_time=-0.040000|dts=-48000|dts_time=-0.040000|duration=48000|duration_time=0.040000|size=4672|pos=10120|flags=_D_|data_hash=CRC32:37967f67 +packet|codec_type=video|stream_index=0|pts=0|pts_time=0.000000|dts=0|dts_time=0.000000|duration=144000|duration_time=0.120000|size=4624|pos=14792|flags=___|data_hash=CRC32:f2b7eb13 +packet|codec_type=video|stream_index=0|pts=144000|pts_time=0.120000|dts=144000|dts_time=0.120000|duration=144000|duration_time=0.120000|size=4192|pos=19416|flags=___|data_hash=CRC32:6538ec17 +packet|codec_type=video|stream_index=0|pts=288000|pts_time=0.240000|dts=288000|dts_time=0.240000|duration=48000|duration_time=0.040000|size=2521|pos=23608|flags=___|data_hash=CRC32:eb27f045 +packet|codec_type=video|stream_index=0|pts=336000|pts_time=0.280000|dts=336000|dts_time=0.280000|duration=48000|duration_time=0.040000|size=1343|pos=26129|flags=___|data_hash=CRC32:a719dc68 +packet|codec_type=video|stream_index=0|pts=384000|pts_time=0.320000|dts=384000|dts_time=0.320000|duration=144000|duration_time=0.120000|size=952|pos=27472|flags=___|data_hash=CRC32:afeae5db +packet|codec_type=video|stream_index=0|pts=528000|pts_time=0.440000|dts=528000|dts_time=0.440000|duration=144000|duration_time=0.120000|size=760|pos=28424|flags=___|data_hash=CRC32:1eacc92c +packet|codec_type=video|stream_index=0|pts=672000|pts_time=0.560000|dts=672000|dts_time=0.560000|duration=48000|duration_time=0.040000|size=2591|pos=29184|flags=___|data_hash=CRC32:17372325 +packet|codec_type=video|stream_index=0|pts=720000|pts_time=0.600000|dts=720000|dts_time=0.600000|duration=48000|duration_time=0.040000|size=1188|pos=31775|flags=___|data_hash=CRC32:e9ce977b +packet|codec_type=video|stream_index=0|pts=768000|pts_time=0.640000|dts=768000|dts_time=0.640000|duration=144000|duration_time=0.120000|size=794|pos=32963|flags=___|data_hash=CRC32:8d140f74 +packet|codec_type=video|stream_index=0|pts=912000|pts_time=0.760000|dts=912000|dts_time=0.760000|duration=144000|duration_time=0.120000|size=746|pos=33757|flags=___|data_hash=CRC32:3b811942 +packet|codec_type=video|stream_index=0|pts=1056000|pts_time=0.880000|dts=1056000|dts_time=0.880000|duration=48000|duration_time=0.040000|size=2603|pos=34503|flags=___|data_hash=CRC32:a486f249 +packet|codec_type=video|stream_index=0|pts=1104000|pts_time=0.920000|dts=1104000|dts_time=0.920000|duration=48000|duration_time=0.040000|size=1005|pos=37106|flags=___|data_hash=CRC32:27839d4c +packet|codec_type=video|stream_index=0|pts=1152000|pts_time=0.960000|dts=1152000|dts_time=0.960000|duration=144000|duration_time=0.120000|size=459|pos=38111|flags=___|data_hash=CRC32:eb775bfc +packet|codec_type=video|stream_index=0|pts=1296000|pts_time=1.080000|dts=1296000|dts_time=1.080000|duration=144000|duration_time=0.120000|size=502|pos=38570|flags=___|data_hash=CRC32:ea021457 +packet|codec_type=video|stream_index=0|pts=1440000|pts_time=1.200000|dts=1440000|dts_time=1.200000|duration=48000|duration_time=0.040000|size=2734|pos=39072|flags=___|data_hash=CRC32:6999b39c +packet|codec_type=video|stream_index=0|pts=1488000|pts_time=1.240000|dts=1488000|dts_time=1.240000|duration=48000|duration_time=0.040000|size=1246|pos=41806|flags=___|data_hash=CRC32:0f9f3622 +packet|codec_type=video|stream_index=0|pts=1536000|pts_time=1.280000|dts=1536000|dts_time=1.280000|duration=144000|duration_time=0.120000|size=572|pos=43052|flags=___|data_hash=CRC32:7d6d8758 +packet|codec_type=video|stream_index=0|pts=1680000|pts_time=1.400000|dts=1680000|dts_time=1.400000|duration=144000|duration_time=0.120000|size=749|pos=43624|flags=___|data_hash=CRC32:69746ad8 +packet|codec_type=video|stream_index=0|pts=1824000|pts_time=1.520000|dts=1824000|dts_time=1.520000|duration=48000|duration_time=0.040000|size=1483|pos=44373|flags=___|data_hash=CRC32:3e9468fc +packet|codec_type=video|stream_index=0|pts=1872000|pts_time=1.560000|dts=1872000|dts_time=1.560000|duration=144000|duration_time=0.120000|size=638|pos=45856|flags=___|data_hash=CRC32:dc0f1d30 +packet|codec_type=video|stream_index=0|pts=2016000|pts_time=1.680000|dts=2016000|dts_time=1.680000|duration=48000|duration_time=0.040000|size=1070|pos=46494|flags=___|data_hash=CRC32:49a62247 +stream|index=0|codec_name=hevc|profile=2|codec_type=video|codec_tag_string=hev1|codec_tag=0x31766568|width=416|height=240|coded_width=416|coded_height=240|closed_captions=0|film_grain=0|has_b_frames=3|sample_aspect_ratio=N/A|display_aspect_ratio=N/A|pix_fmt=yuv420p10le|level=60|color_range=tv|color_space=unknown|color_transfer=unknown|color_primaries=unknown|chroma_location=left|field_order=unknown|refs=1|id=0x1|r_frame_rate=25/1|avg_frame_rate=300/23|time_base=1/1200000|start_pts=0|start_time=0.000000|duration_ts=2064000|duration=1.720000|bit_rate=206608|max_bit_rate=N/A|bits_per_raw_sample=N/A|nb_frames=24|nb_read_frames=N/A|nb_read_packets=24|extradata_size=121|extradata_hash=CRC32:bd471302|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:language=und|tag:handler_name=VideoHandler|tag:vendor_id=[0][0][0][0] +format|filename=cbs-hevc-discard-nonref.mp4|nb_streams=1|nb_programs=0|format_name=mov,mp4,m4a,3gp,3g2,mj2|start_time=0.000000|duration=1.720000|size=48589|bit_rate=225995|probe_score=100|tag:major_brand=isom|tag:minor_version=512|tag:compatible_brands=isomiso2mp41 From fb85aa959aad113a2565e5ce97ed42a47583e698 Mon Sep 17 00:00:00 2001 From: Zhao Zhili Date: Fri, 9 Jun 2023 19:14:24 +0800 Subject: [PATCH 1533/2172] avcodec/mediacodecenc: add profile names to options H.264 high10/high422/high44 are unlikely supported by devices. It's there for developers to do the experiment. H.265 main10 works on my device with AV_PIX_FMT_MEDIACODEC. OMX_COLOR_FormatYUV420Planar16 doesn't work. Signed-off-by: Zhao Zhili --- libavcodec/mediacodecenc.c | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/libavcodec/mediacodecenc.c b/libavcodec/mediacodecenc.c index d23745c1c19..1da705d1132 100644 --- a/libavcodec/mediacodecenc.c +++ b/libavcodec/mediacodecenc.c @@ -36,6 +36,7 @@ #include "mediacodec.h" #include "mediacodec_wrapper.h" #include "mediacodecdec_common.h" +#include "profiles.h" #define INPUT_DEQUEUE_TIMEOUT_US 8000 #define OUTPUT_DEQUEUE_TIMEOUT_US 8000 @@ -658,6 +659,16 @@ enum MediaCodecAvcLevel { static const AVOption h264_options[] = { COMMON_OPTION + + FF_AVCTX_PROFILE_OPTION("baseline", NULL, VIDEO, FF_PROFILE_H264_BASELINE) + FF_AVCTX_PROFILE_OPTION("constrained_baseline", NULL, VIDEO, FF_PROFILE_H264_CONSTRAINED_BASELINE) + FF_AVCTX_PROFILE_OPTION("main", NULL, VIDEO, FF_PROFILE_H264_MAIN) + FF_AVCTX_PROFILE_OPTION("extended", NULL, VIDEO, FF_PROFILE_H264_EXTENDED) + FF_AVCTX_PROFILE_OPTION("high", NULL, VIDEO, FF_PROFILE_H264_HIGH) + FF_AVCTX_PROFILE_OPTION("high10", NULL, VIDEO, FF_PROFILE_H264_HIGH_10) + FF_AVCTX_PROFILE_OPTION("high422", NULL, VIDEO, FF_PROFILE_H264_HIGH_422) + FF_AVCTX_PROFILE_OPTION("high444", NULL, VIDEO, FF_PROFILE_H264_HIGH_444) + { "level", "Specify level", OFFSET(level), AV_OPT_TYPE_INT, {.i64 = 0}, 0, INT_MAX, VE, "level" }, { "1", "", 0, AV_OPT_TYPE_CONST, { .i64 = AVCLevel1 }, 0, 0, VE, "level" }, @@ -720,6 +731,10 @@ enum MediaCodecHevcLevel { static const AVOption hevc_options[] = { COMMON_OPTION + + FF_AVCTX_PROFILE_OPTION("main", NULL, VIDEO, FF_PROFILE_HEVC_MAIN) + FF_AVCTX_PROFILE_OPTION("main10", NULL, VIDEO, FF_PROFILE_HEVC_MAIN_10) + { "level", "Specify tier and level", OFFSET(level), AV_OPT_TYPE_INT, {.i64 = 0}, 0, INT_MAX, VE, "level" }, { "m1", "Main tier level 1", @@ -830,6 +845,12 @@ enum MediaCodecVP9Level { static const AVOption vp9_options[] = { COMMON_OPTION + + FF_AVCTX_PROFILE_OPTION("profile0", NULL, VIDEO, FF_PROFILE_VP9_0) + FF_AVCTX_PROFILE_OPTION("profile1", NULL, VIDEO, FF_PROFILE_VP9_1) + FF_AVCTX_PROFILE_OPTION("profile2", NULL, VIDEO, FF_PROFILE_VP9_2) + FF_AVCTX_PROFILE_OPTION("profile3", NULL, VIDEO, FF_PROFILE_VP9_3) + { "level", "Specify tier and level", OFFSET(level), AV_OPT_TYPE_INT, {.i64 = 0}, 0, INT_MAX, VE, "level" }, { "1", "Level 1", @@ -884,6 +905,9 @@ enum MediaCodecMpeg4Level { static const AVOption mpeg4_options[] = { COMMON_OPTION + + FF_MPEG4_PROFILE_OPTS + { "level", "Specify tier and level", OFFSET(level), AV_OPT_TYPE_INT, {.i64 = 0}, 0, INT_MAX, VE, "level" }, { "0", "Level 0", @@ -944,6 +968,9 @@ enum MediaCodecAV1Level { static const AVOption av1_options[] = { COMMON_OPTION + + FF_AV1_PROFILE_OPTS + { "level", "Specify tier and level", OFFSET(level), AV_OPT_TYPE_INT, {.i64 = 0}, 0, INT_MAX, VE, "level" }, { "2", "Level 2", From 315c66af0fd536b952f5d163754e679eb6b5c209 Mon Sep 17 00:00:00 2001 From: Zhao Zhili Date: Fri, 9 Jun 2023 19:14:53 +0800 Subject: [PATCH 1534/2172] avcodec/videotoolboxenc: use int as the type of profile Other than save a few bytes, it also has the benefit to show the AV_OPT_TYPE_CONST value in help, e.g., -profile E..V....... Profile (from 0 to INT_MAX) (default 0) baseline 66 E..V....... Baseline Profile ... Signed-off-by: Zhao Zhili --- libavcodec/videotoolboxenc.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/libavcodec/videotoolboxenc.c b/libavcodec/videotoolboxenc.c index 9719e0bf544..26485a3dea5 100644 --- a/libavcodec/videotoolboxenc.c +++ b/libavcodec/videotoolboxenc.c @@ -252,7 +252,7 @@ typedef struct VTEncContext { int64_t first_pts; int64_t dts_delta; - int64_t profile; + int profile; int level; int entropy; int realtime; @@ -443,7 +443,7 @@ static int count_nalus(size_t length_code_size, } static CMVideoCodecType get_cm_codec_type(AVCodecContext *avctx, - int64_t profile, + int 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); @@ -470,7 +470,7 @@ static CMVideoCodecType get_cm_codec_type(AVCodecContext *avctx, return MKBETAG('a','p','4','x'); // kCMVideoCodecType_AppleProRes4444XQ default: - av_log(avctx, AV_LOG_ERROR, "Unknown profile ID: %"PRId64", using auto\n", profile); + av_log(avctx, AV_LOG_ERROR, "Unknown profile ID: %d, using auto\n", profile); case FF_PROFILE_UNKNOWN: if (desc && ((desc->flags & AV_PIX_FMT_FLAG_ALPHA) || @@ -735,7 +735,7 @@ static bool get_vt_h264_profile_level(AVCodecContext *avctx, CFStringRef *profile_level_val) { VTEncContext *vtctx = avctx->priv_data; - int64_t profile = vtctx->profile; + int profile = vtctx->profile; if (profile == AUTO_PROFILE && vtctx->level) { //Need to pick a profile if level is not auto-selected. @@ -864,7 +864,7 @@ static bool get_vt_hevc_profile_level(AVCodecContext *avctx, CFStringRef *profile_level_val) { VTEncContext *vtctx = avctx->priv_data; - int64_t profile = vtctx->profile; + int profile = vtctx->profile; *profile_level_val = NULL; @@ -2891,7 +2891,7 @@ static const enum AVPixelFormat prores_pix_fmts[] = { #define OFFSET(x) offsetof(VTEncContext, x) static const AVOption h264_options[] = { - { "profile", "Profile", OFFSET(profile), AV_OPT_TYPE_INT64, { .i64 = AUTO_PROFILE }, 0, INT_MAX, VE, "profile" }, + { "profile", "Profile", OFFSET(profile), AV_OPT_TYPE_INT, { .i64 = AUTO_PROFILE }, 0, INT_MAX, VE, "profile" }, { "baseline", "Baseline Profile", 0, AV_OPT_TYPE_CONST, { .i64 = FF_PROFILE_H264_BASELINE }, INT_MIN, INT_MAX, VE, "profile" }, { "constrained_baseline", "Constrained Baseline Profile", 0, AV_OPT_TYPE_CONST, { .i64 = FF_PROFILE_H264_CONSTRAINED_BASELINE }, INT_MIN, INT_MAX, VE, "profile" }, { "main", "Main Profile", 0, AV_OPT_TYPE_CONST, { .i64 = FF_PROFILE_H264_MAIN }, INT_MIN, INT_MAX, VE, "profile" }, @@ -2948,7 +2948,7 @@ const FFCodec ff_h264_videotoolbox_encoder = { }; static const AVOption hevc_options[] = { - { "profile", "Profile", OFFSET(profile), AV_OPT_TYPE_INT64, { .i64 = AUTO_PROFILE }, 0, INT_MAX, VE, "profile" }, + { "profile", "Profile", OFFSET(profile), AV_OPT_TYPE_INT, { .i64 = AUTO_PROFILE }, 0, INT_MAX, VE, "profile" }, { "main", "Main Profile", 0, AV_OPT_TYPE_CONST, { .i64 = FF_PROFILE_HEVC_MAIN }, INT_MIN, INT_MAX, VE, "profile" }, { "main10", "Main10 Profile", 0, AV_OPT_TYPE_CONST, { .i64 = FF_PROFILE_HEVC_MAIN_10 }, INT_MIN, INT_MAX, VE, "profile" }, @@ -2985,7 +2985,7 @@ const FFCodec ff_hevc_videotoolbox_encoder = { }; 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" }, + { "profile", "Profile", OFFSET(profile), AV_OPT_TYPE_INT, { .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" }, From 3fafc842f191454313f9e0b92f62148b2e328c97 Mon Sep 17 00:00:00 2001 From: Zhao Zhili Date: Fri, 9 Jun 2023 19:14:54 +0800 Subject: [PATCH 1535/2172] avcodec/videotoolboxenc: remove AUTO_PROFILE define Use FF_PROFILE_UNKNOWN as auto mode. Signed-off-by: Zhao Zhili --- libavcodec/videotoolboxenc.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/libavcodec/videotoolboxenc.c b/libavcodec/videotoolboxenc.c index 26485a3dea5..9f65519700b 100644 --- a/libavcodec/videotoolboxenc.c +++ b/libavcodec/videotoolboxenc.c @@ -206,7 +206,6 @@ static void loadVTEncSymbols(void){ GET_SYM(kVTCompressionPropertyKey_MinAllowedFrameQP, "MinAllowedFrameQP"); } -#define AUTO_PROFILE 0 #define H264_PROFILE_CONSTRAINED_HIGH (FF_PROFILE_H264_HIGH | FF_PROFILE_H264_CONSTRAINED) typedef enum VTH264Entropy{ @@ -737,7 +736,7 @@ static bool get_vt_h264_profile_level(AVCodecContext *avctx, VTEncContext *vtctx = avctx->priv_data; int profile = vtctx->profile; - if (profile == AUTO_PROFILE && vtctx->level) { + if (profile == FF_PROFILE_UNKNOWN && vtctx->level) { //Need to pick a profile if level is not auto-selected. profile = vtctx->has_b_frames ? FF_PROFILE_H264_MAIN : FF_PROFILE_H264_BASELINE; } @@ -745,7 +744,7 @@ static bool get_vt_h264_profile_level(AVCodecContext *avctx, *profile_level_val = NULL; switch (profile) { - case AUTO_PROFILE: + case FF_PROFILE_UNKNOWN: return true; case FF_PROFILE_H264_BASELINE: @@ -869,7 +868,7 @@ static bool get_vt_hevc_profile_level(AVCodecContext *avctx, *profile_level_val = NULL; switch (profile) { - case AUTO_PROFILE: + case FF_PROFILE_UNKNOWN: return true; case FF_PROFILE_HEVC_MAIN: *profile_level_val = @@ -2891,7 +2890,7 @@ static const enum AVPixelFormat prores_pix_fmts[] = { #define OFFSET(x) offsetof(VTEncContext, x) static const AVOption h264_options[] = { - { "profile", "Profile", OFFSET(profile), AV_OPT_TYPE_INT, { .i64 = AUTO_PROFILE }, 0, INT_MAX, VE, "profile" }, + { "profile", "Profile", OFFSET(profile), AV_OPT_TYPE_INT, { .i64 = FF_PROFILE_UNKNOWN }, FF_PROFILE_UNKNOWN, INT_MAX, VE, "profile" }, { "baseline", "Baseline Profile", 0, AV_OPT_TYPE_CONST, { .i64 = FF_PROFILE_H264_BASELINE }, INT_MIN, INT_MAX, VE, "profile" }, { "constrained_baseline", "Constrained Baseline Profile", 0, AV_OPT_TYPE_CONST, { .i64 = FF_PROFILE_H264_CONSTRAINED_BASELINE }, INT_MIN, INT_MAX, VE, "profile" }, { "main", "Main Profile", 0, AV_OPT_TYPE_CONST, { .i64 = FF_PROFILE_H264_MAIN }, INT_MIN, INT_MAX, VE, "profile" }, @@ -2948,7 +2947,7 @@ const FFCodec ff_h264_videotoolbox_encoder = { }; static const AVOption hevc_options[] = { - { "profile", "Profile", OFFSET(profile), AV_OPT_TYPE_INT, { .i64 = AUTO_PROFILE }, 0, INT_MAX, VE, "profile" }, + { "profile", "Profile", OFFSET(profile), AV_OPT_TYPE_INT, { .i64 = FF_PROFILE_UNKNOWN }, FF_PROFILE_UNKNOWN, INT_MAX, VE, "profile" }, { "main", "Main Profile", 0, AV_OPT_TYPE_CONST, { .i64 = FF_PROFILE_HEVC_MAIN }, INT_MIN, INT_MAX, VE, "profile" }, { "main10", "Main10 Profile", 0, AV_OPT_TYPE_CONST, { .i64 = FF_PROFILE_HEVC_MAIN_10 }, INT_MIN, INT_MAX, VE, "profile" }, From f66e1862e3140a6d6ba9d35243827832e26b61a1 Mon Sep 17 00:00:00 2001 From: Zhao Zhili Date: Fri, 9 Jun 2023 19:14:55 +0800 Subject: [PATCH 1536/2172] avcodec/videotoolboxenc: inherit profile from AVCodecContext This can happen when user set the avctx->profile field directly instead of specify profile via option. Signed-off-by: Zhao Zhili --- libavcodec/videotoolboxenc.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/libavcodec/videotoolboxenc.c b/libavcodec/videotoolboxenc.c index 9f65519700b..a313087876a 100644 --- a/libavcodec/videotoolboxenc.c +++ b/libavcodec/videotoolboxenc.c @@ -1746,6 +1746,9 @@ static av_cold int vtenc_init(AVCodecContext *avctx) pthread_mutex_init(&vtctx->lock, NULL); pthread_cond_init(&vtctx->cv_sample_sent, NULL); + // It can happen when user set avctx->profile directly. + if (vtctx->profile == FF_PROFILE_UNKNOWN) + vtctx->profile = avctx->profile; vtctx->session = NULL; status = vtenc_configure_encoder(avctx); if (status) return status; From a33191ff7aeb61248d89d5fc418a36c9750177b5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Storsj=C3=B6?= Date: Mon, 19 Jun 2023 09:25:01 +0300 Subject: [PATCH 1537/2172] fate/cbs: Fix the ffprobe dependency for Windows targets MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Martin Storsjö --- tests/fate/cbs.mak | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/fate/cbs.mak b/tests/fate/cbs.mak index 1d6cdf93356..0084c3d25c3 100644 --- a/tests/fate/cbs.mak +++ b/tests/fate/cbs.mak @@ -20,7 +20,7 @@ tests/data/fate/cbs-$(1)-discard-$2.$(4): ffmpeg$(PROGSSUF)$(EXESUF) $(5) | test $(M)$(TARGET_EXEC) $(TARGET_PATH)/ffmpeg$(PROGSSUF)$(EXESUF) -nostdin \ -i $(3) -c:v copy -fflags +bitexact -an -bsf:v filter_units=discard=$(2) \ -f $(4) $(TARGET_PATH)/tests/data/fate/cbs-$(1)-discard-$(2).$(4) -y 2>/dev/null -fate-cbs-$(1)-discard-$2: ffprobe tests/data/fate/cbs-$(1)-discard-$(2).$(4) +fate-cbs-$(1)-discard-$2: ffprobe$(PROGSSUF)$(EXESUF) tests/data/fate/cbs-$(1)-discard-$(2).$(4) fate-cbs-$(1)-discard-$2: CMD = ffprobe_demux $(TARGET_PATH)/tests/data/fate/cbs-$(1)-discard-$(2).$(4) endef From 52d7ea663531ba9b6896dbb2e8f34dfd1eee3e8a Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Sat, 17 Jun 2023 10:05:25 +0200 Subject: [PATCH 1538/2172] doc/ffmpeg: improve -stats_*_fmt documentation --- doc/ffmpeg.texi | 34 +++++++++++++++++++++------------- 1 file changed, 21 insertions(+), 13 deletions(-) diff --git a/doc/ffmpeg.texi b/doc/ffmpeg.texi index c0fa90f3817..6769f8d3051 100644 --- a/doc/ffmpeg.texi +++ b/doc/ffmpeg.texi @@ -2145,8 +2145,8 @@ Input frame number. Index of the input frame (i.e. output by a decoder) that corresponds to this output frame or packet. -1 if unavailable. @item tb -Encoder timebase, as a rational number @var{num/den}. Note that this may be -different from the timebase used by the muxer. +Timebase in which this frame/packet's timestamps are expressed, as a rational +number @var{num/den}. Note that encoder and muxer may use different timebases. @item tbi Timebase for @var{ptsi}, as a rational number @var{num/den}. Available when @@ -2169,31 +2169,39 @@ Presentation time of the frame or packet, as a decimal number. Equal to Presentation time of the input frame (see @var{ni}), as a decimal number. Equal to @var{ptsi} multiplied by @var{tbi}. Printed as inf when not available. -@item dts +@item dts (@emph{packet}) Decoding timestamp of the packet, as an integer. Should be multiplied by the -timebase to compute presentation time. Post-encoding only. +timebase to compute presentation time. -@item dt +@item dt (@emph{packet}) Decoding time of the frame or packet, as a decimal number. Equal to @var{dts} multiplied by @var{tb}. -@item sn -Number of audio samples sent to the encoder so far. Audio and pre-encoding only. +@item sn (@emph{frame,audio}) +Number of audio samples sent to the encoder so far. -@item samp -Number of audio samples in the frame. Audio and pre-encoding only. +@item samp (@emph{frame,audio}) +Number of audio samples in the frame. -@item size -Size of the encoded packet in bytes. Post-encoding only. +@item size (@emph{packet}) +Size of the encoded packet in bytes. -@item br +@item br (@emph{packet}) Current bitrate in bits per second. Post-encoding only. -@item abr +@item abr (@emph{packet}) Average bitrate for the whole stream so far, in bits per second, -1 if it cannot be determined at this point. Post-encoding only. @end table +Directives tagged with @emph{packet} may only be used with +@option{-stats_enc_post_fmt} and @option{-stats_mux_pre_fmt}. + +Directives tagged with @emph{frame} may only be used with +@option{-stats_enc_pre_fmt}. + +Directives tagged with @emph{audio} may only be used with audio streams. + The default format strings are: @table @option @item pre-encoding From e9eb44ed8869c340f1c4b415e91741e756e48b11 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Fri, 2 Jun 2023 16:32:55 +0200 Subject: [PATCH 1539/2172] fftools/ffmpeg_dec: drop always-0 InputStream.prev_sub.ret --- fftools/ffmpeg.h | 1 - fftools/ffmpeg_dec.c | 3 +-- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/fftools/ffmpeg.h b/fftools/ffmpeg.h index 88e35162435..7b38812f749 100644 --- a/fftools/ffmpeg.h +++ b/fftools/ffmpeg.h @@ -365,7 +365,6 @@ typedef struct InputStream { int fix_sub_duration; struct { /* previous decoded subtitle and related variables */ int got_output; - int ret; AVSubtitle subtitle; } prev_sub; diff --git a/fftools/ffmpeg_dec.c b/fftools/ffmpeg_dec.c index 799be632157..c0c242147f3 100644 --- a/fftools/ffmpeg_dec.c +++ b/fftools/ffmpeg_dec.c @@ -346,14 +346,13 @@ int process_subtitle(InputStream *ist, AVSubtitle *subtitle, int *got_output) } } FFSWAP(int, *got_output, ist->prev_sub.got_output); - FFSWAP(int, ret, ist->prev_sub.ret); FFSWAP(AVSubtitle, *subtitle, ist->prev_sub.subtitle); if (end <= 0) goto out; } if (!*got_output) - return ret; + return 0; for (int i = 0; i < ist->nb_filters; i++) { ret = ifilter_sub2video(ist->filters[i], subtitle); From df81fb46eefa6b23aa3ed1fae81b29dd5e3d7094 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Fri, 2 Jun 2023 16:41:51 +0200 Subject: [PATCH 1540/2172] fftools/ffmpeg_dec: simplify process_subtitle() Its got_output argument always points to 1. --- fftools/ffmpeg.c | 3 +-- fftools/ffmpeg.h | 2 +- fftools/ffmpeg_dec.c | 9 +++++---- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/fftools/ffmpeg.c b/fftools/ffmpeg.c index d62ccc56c97..45e71ed626c 100644 --- a/fftools/ffmpeg.c +++ b/fftools/ffmpeg.c @@ -731,7 +731,6 @@ int copy_av_subtitle(AVSubtitle *dst, const AVSubtitle *src) static int fix_sub_duration_heartbeat(InputStream *ist, int64_t signal_pts) { int ret = AVERROR_BUG; - int got_output = 1; AVSubtitle *prev_subtitle = &ist->prev_sub.subtitle; AVSubtitle subtitle; @@ -744,7 +743,7 @@ static int fix_sub_duration_heartbeat(InputStream *ist, int64_t signal_pts) subtitle.pts = signal_pts; - return process_subtitle(ist, &subtitle, &got_output); + return process_subtitle(ist, &subtitle); } int trigger_fix_sub_duration_heartbeat(OutputStream *ost, const AVPacket *pkt) diff --git a/fftools/ffmpeg.h b/fftools/ffmpeg.h index 7b38812f749..7189629ad48 100644 --- a/fftools/ffmpeg.h +++ b/fftools/ffmpeg.h @@ -884,7 +884,7 @@ OutputStream *ost_iter(OutputStream *prev); void close_output_stream(OutputStream *ost); int trigger_fix_sub_duration_heartbeat(OutputStream *ost, const AVPacket *pkt); -int process_subtitle(InputStream *ist, AVSubtitle *subtitle, int *got_output); +int process_subtitle(InputStream *ist, AVSubtitle *subtitle); void update_benchmark(const char *fmt, ...); /** diff --git a/fftools/ffmpeg_dec.c b/fftools/ffmpeg_dec.c index c0c242147f3..6582917a39d 100644 --- a/fftools/ffmpeg_dec.c +++ b/fftools/ffmpeg_dec.c @@ -328,8 +328,9 @@ static void sub2video_flush(InputStream *ist) } } -int process_subtitle(InputStream *ist, AVSubtitle *subtitle, int *got_output) +int process_subtitle(InputStream *ist, AVSubtitle *subtitle) { + int got_output = 1; int ret = 0; if (ist->fix_sub_duration) { @@ -345,13 +346,13 @@ int process_subtitle(InputStream *ist, AVSubtitle *subtitle, int *got_output) ist->prev_sub.subtitle.end_display_time = end; } } - FFSWAP(int, *got_output, ist->prev_sub.got_output); + FFSWAP(int, got_output, ist->prev_sub.got_output); FFSWAP(AVSubtitle, *subtitle, ist->prev_sub.subtitle); if (end <= 0) goto out; } - if (!*got_output) + if (!got_output) return 0; for (int i = 0; i < ist->nb_filters; i++) { @@ -402,7 +403,7 @@ static int transcode_subtitles(InputStream *ist, const AVPacket *pkt) ist->frames_decoded++; - return process_subtitle(ist, &subtitle, &got_output); + return process_subtitle(ist, &subtitle); } static int send_filter_eof(InputStream *ist) From 90a26e75a440d9346ded82f0aa9115d078e9cf80 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Fri, 2 Jun 2023 21:01:58 +0200 Subject: [PATCH 1541/2172] tests/fate: rename ffmpeg-streamloop to ffmpeg-streamloop-copy Makes it clear that this tests -streamloop with streamcopy, to distinguish it from further -streamloop tests added in future commits. --- tests/fate/ffmpeg.mak | 4 ++-- tests/ref/fate/{ffmpeg-streamloop => ffmpeg-streamloop-copy} | 0 2 files changed, 2 insertions(+), 2 deletions(-) rename tests/ref/fate/{ffmpeg-streamloop => ffmpeg-streamloop-copy} (100%) diff --git a/tests/fate/ffmpeg.mak b/tests/fate/ffmpeg.mak index 223bc97f8e4..c26c748934f 100644 --- a/tests/fate/ffmpeg.mak +++ b/tests/fate/ffmpeg.mak @@ -167,8 +167,8 @@ FATE_STREAMCOPY-$(call REMUX, PSP MOV, H264_PARSER H264_DECODER) += fate-copy-ps fate-copy-psp: CMD = transcode "mov" $(TARGET_SAMPLES)/h264/wwwq_cut.mp4\ psp "-c copy" "-codec copy" -FATE_STREAMCOPY-$(call FRAMEMD5, FLV, H264) += fate-ffmpeg-streamloop -fate-ffmpeg-streamloop: CMD = framemd5 -stream_loop 2 -i $(TARGET_SAMPLES)/flv/streamloop.flv -c copy +FATE_STREAMCOPY-$(call FRAMEMD5, FLV, H264) += fate-ffmpeg-streamloop-copy +fate-ffmpeg-streamloop-copy: CMD = framemd5 -stream_loop 2 -i $(TARGET_SAMPLES)/flv/streamloop.flv -c copy tests/data/audio_shorter_than_video.nut: TAG = GEN tests/data/audio_shorter_than_video.nut: tests/data/vsynth_lena.yuv diff --git a/tests/ref/fate/ffmpeg-streamloop b/tests/ref/fate/ffmpeg-streamloop-copy similarity index 100% rename from tests/ref/fate/ffmpeg-streamloop rename to tests/ref/fate/ffmpeg-streamloop-copy From 47a14b542e8431a97828d863ca1529ddb16a5d75 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Fri, 2 Jun 2023 21:26:52 +0200 Subject: [PATCH 1542/2172] tests/fate: add a test for -streamloop with transcoding video+audio --- tests/fate/ffmpeg.mak | 4 + tests/ref/fate/ffmpeg-streamloop-transcode-av | 151 ++++++++++++++++++ 2 files changed, 155 insertions(+) create mode 100644 tests/ref/fate/ffmpeg-streamloop-transcode-av diff --git a/tests/fate/ffmpeg.mak b/tests/fate/ffmpeg.mak index c26c748934f..87cd0b46d06 100644 --- a/tests/fate/ffmpeg.mak +++ b/tests/fate/ffmpeg.mak @@ -132,6 +132,10 @@ fate-ffmpeg-fix_sub_duration_heartbeat: CMD = fmtstdout srt -fix_sub_duration \ -c:s srt \ -f null - +FATE_SAMPLES_FFMPEG-$(call FRAMECRC, MATROSKA, H264 AAC_FIXED, PCM_S32LE_ENCODER) += fate-ffmpeg-streamloop-transcode-av +fate-ffmpeg-streamloop-transcode-av: CMD = \ + framecrc -auto_conversion_filters -stream_loop 3 -i $(TARGET_SAMPLES)/mkv/1242-small.mkv -c:a pcm_s32le + FATE_STREAMCOPY-$(call REMUX, MP4 MOV, EAC3_DEMUXER) += fate-copy-trac3074 fate-copy-trac3074: CMD = transcode eac3 $(TARGET_SAMPLES)/eac3/csi_miami_stereo_128_spx.eac3\ mp4 "-codec copy -map 0" "-codec copy" diff --git a/tests/ref/fate/ffmpeg-streamloop-transcode-av b/tests/ref/fate/ffmpeg-streamloop-transcode-av new file mode 100644 index 00000000000..50a626b281b --- /dev/null +++ b/tests/ref/fate/ffmpeg-streamloop-transcode-av @@ -0,0 +1,151 @@ +#tb 0: 125/2997 +#media_type 0: video +#codec_id 0: rawvideo +#dimensions 0: 1280x718 +#sar 0: 1/1 +#tb 1: 1/48000 +#media_type 1: audio +#codec_id 1: pcm_s32le +#sample_rate 1: 48000 +#channel_layout_name 1: stereo +0, 0, 0, 1, 1378560, 0xbaf121ba +1, 0, 0, 1024, 8192, 0x00000000 +1, 1024, 1024, 1024, 8192, 0x00000000 +0, 1, 1, 1, 1378560, 0xbaf121ba +1, 2040, 2040, 1024, 8192, 0x00000000 +1, 3048, 3048, 1024, 8192, 0x00000000 +0, 2, 2, 1, 1378560, 0x6579d31a +1, 4072, 4072, 1024, 8192, 0x00000000 +1, 5096, 5096, 1024, 8192, 0x00000000 +0, 3, 3, 1, 1378560, 0xca1deba8 +1, 6120, 6120, 1024, 8192, 0x687330d2 +1, 7128, 7128, 1024, 8192, 0x9131462c +0, 4, 4, 1, 1378560, 0xd4eed467 +1, 8208, 8208, 1024, 8192, 0x48c01c32 +1, 9232, 9232, 1024, 8192, 0x0ccd8d5f +0, 5, 5, 1, 1378560, 0xd6e1d5b7 +1, 10248, 10248, 1024, 8192, 0xd50cbe9f +1, 11256, 11256, 1024, 8192, 0xbe069303 +0, 6, 6, 1, 1378560, 0x0b574d39 +1, 12280, 12280, 1024, 8192, 0x85fccf5b +1, 13304, 13304, 1024, 8192, 0x4180de71 +0, 7, 7, 1, 1378560, 0x1bdd4d61 +1, 14328, 14328, 1024, 8192, 0x0e9b6ac3 +1, 15336, 15336, 1024, 8192, 0x5c33f724 +0, 8, 8, 1, 1378560, 0x3b28f549 +1, 16360, 16360, 1024, 8192, 0x668aaaec +1, 17384, 17384, 1024, 8192, 0xd137d412 +0, 9, 9, 1, 1378560, 0x45b2f57b +1, 18408, 18408, 1024, 8192, 0x08e1fbf6 +1, 19416, 19416, 1024, 8192, 0xbf3fb4f6 +0, 10, 10, 1, 1378560, 0x8955570e +1, 20440, 20440, 1024, 8192, 0x69cd08a4 +1, 21464, 21464, 1024, 8192, 0xe0fe6297 +1, 22488, 22488, 1024, 8192, 0x172867ad +1, 23496, 23496, 1024, 8192, 0xcbcc1461 +0, 12, 12, 1, 1378560, 0x9c598000 +1, 25488, 25488, 1024, 8192, 0x00000000 +0, 13, 13, 1, 1378560, 0xbaf121ba +1, 26512, 26512, 1024, 8192, 0x00000000 +1, 27528, 27528, 1024, 8192, 0x00000000 +0, 14, 14, 1, 1378560, 0xbaf121ba +1, 28552, 28552, 1024, 8192, 0x00000000 +1, 29576, 29576, 1024, 8192, 0x00000000 +0, 15, 15, 1, 1378560, 0x6579d31a +1, 30600, 30600, 1024, 8192, 0x687330d2 +1, 31608, 31608, 1024, 8192, 0x9131462c +0, 16, 16, 1, 1378560, 0xca1deba8 +1, 32688, 32688, 1024, 8192, 0x48c01c32 +1, 33712, 33712, 1024, 8192, 0x0ccd8d5f +0, 17, 17, 1, 1378560, 0xd4eed467 +1, 34728, 34728, 1024, 8192, 0xd50cbe9f +1, 35736, 35736, 1024, 8192, 0xbe069303 +0, 18, 18, 1, 1378560, 0xd6e1d5b7 +1, 36760, 36760, 1024, 8192, 0x85fccf5b +1, 37784, 37784, 1024, 8192, 0x4180de71 +0, 19, 19, 1, 1378560, 0x0b574d39 +1, 38808, 38808, 1024, 8192, 0x0e9b6ac3 +1, 39816, 39816, 1024, 8192, 0x5c33f724 +0, 20, 20, 1, 1378560, 0x1bdd4d61 +1, 40840, 40840, 1024, 8192, 0x668aaaec +1, 41864, 41864, 1024, 8192, 0xd137d412 +0, 21, 21, 1, 1378560, 0x3b28f549 +1, 42888, 42888, 1024, 8192, 0x08e1fbf6 +1, 43896, 43896, 1024, 8192, 0xbf3fb4f6 +0, 22, 22, 1, 1378560, 0x45b2f57b +1, 44920, 44920, 1024, 8192, 0x69cd08a4 +1, 45944, 45944, 1024, 8192, 0xe0fe6297 +0, 23, 23, 1, 1378560, 0x8955570e +1, 46968, 46968, 1024, 8192, 0x172867ad +1, 47976, 47976, 1024, 8192, 0xcbcc1461 +0, 24, 24, 1, 1378560, 0x9c598000 +1, 49968, 49968, 1024, 8192, 0x00000000 +0, 25, 25, 1, 1378560, 0xbaf121ba +1, 50992, 50992, 1024, 8192, 0x00000000 +1, 52008, 52008, 1024, 8192, 0x00000000 +0, 26, 26, 1, 1378560, 0xbaf121ba +1, 53032, 53032, 1024, 8192, 0x00000000 +0, 27, 27, 1, 1378560, 0x6579d31a +1, 54056, 54056, 1024, 8192, 0x00000000 +1, 55080, 55080, 1024, 8192, 0x687330d2 +0, 28, 28, 1, 1378560, 0xca1deba8 +1, 56088, 56088, 1024, 8192, 0x9131462c +1, 57168, 57168, 1024, 8192, 0x48c01c32 +0, 29, 29, 1, 1378560, 0xd4eed467 +1, 58192, 58192, 1024, 8192, 0x0ccd8d5f +1, 59208, 59208, 1024, 8192, 0xd50cbe9f +0, 30, 30, 1, 1378560, 0xd6e1d5b7 +1, 60216, 60216, 1024, 8192, 0xbe069303 +1, 61240, 61240, 1024, 8192, 0x85fccf5b +0, 31, 31, 1, 1378560, 0x0b574d39 +1, 62264, 62264, 1024, 8192, 0x4180de71 +1, 63288, 63288, 1024, 8192, 0x0e9b6ac3 +0, 32, 32, 1, 1378560, 0x1bdd4d61 +1, 64296, 64296, 1024, 8192, 0x5c33f724 +1, 65320, 65320, 1024, 8192, 0x668aaaec +0, 33, 33, 1, 1378560, 0x3b28f549 +1, 66344, 66344, 1024, 8192, 0xd137d412 +1, 67368, 67368, 1024, 8192, 0x08e1fbf6 +0, 34, 34, 1, 1378560, 0x45b2f57b +1, 68376, 68376, 1024, 8192, 0xbf3fb4f6 +1, 69400, 69400, 1024, 8192, 0x69cd08a4 +0, 35, 35, 1, 1378560, 0x8955570e +1, 70424, 70424, 1024, 8192, 0xe0fe6297 +1, 71448, 71448, 1024, 8192, 0x172867ad +0, 36, 36, 1, 1378560, 0x9c598000 +1, 72456, 72456, 1024, 8192, 0xcbcc1461 +0, 37, 37, 1, 1378560, 0xbaf121ba +1, 74448, 74448, 1024, 8192, 0x00000000 +1, 75472, 75472, 1024, 8192, 0x00000000 +0, 38, 38, 1, 1378560, 0xbaf121ba +1, 76488, 76488, 1024, 8192, 0x00000000 +1, 77512, 77512, 1024, 8192, 0x00000000 +0, 39, 39, 1, 1378560, 0x6579d31a +1, 78536, 78536, 1024, 8192, 0x00000000 +1, 79560, 79560, 1024, 8192, 0x687330d2 +0, 40, 40, 1, 1378560, 0xca1deba8 +1, 80568, 80568, 1024, 8192, 0x9131462c +1, 81648, 81648, 1024, 8192, 0x48c01c32 +0, 41, 41, 1, 1378560, 0xd4eed467 +1, 82672, 82672, 1024, 8192, 0x0ccd8d5f +1, 83688, 83688, 1024, 8192, 0xd50cbe9f +0, 42, 42, 1, 1378560, 0xd6e1d5b7 +1, 84696, 84696, 1024, 8192, 0xbe069303 +1, 85720, 85720, 1024, 8192, 0x85fccf5b +0, 43, 43, 1, 1378560, 0x0b574d39 +1, 86744, 86744, 1024, 8192, 0x4180de71 +1, 87768, 87768, 1024, 8192, 0x0e9b6ac3 +0, 44, 44, 1, 1378560, 0x1bdd4d61 +1, 88776, 88776, 1024, 8192, 0x5c33f724 +1, 89800, 89800, 1024, 8192, 0x668aaaec +0, 45, 45, 1, 1378560, 0x3b28f549 +1, 90824, 90824, 1024, 8192, 0xd137d412 +1, 91848, 91848, 1024, 8192, 0x08e1fbf6 +0, 46, 46, 1, 1378560, 0x45b2f57b +1, 92856, 92856, 1024, 8192, 0xbf3fb4f6 +1, 93880, 93880, 1024, 8192, 0x69cd08a4 +0, 47, 47, 1, 1378560, 0x8955570e +1, 94904, 94904, 1024, 8192, 0xe0fe6297 +1, 95928, 95928, 1024, 8192, 0x172867ad +1, 96936, 96936, 1024, 8192, 0xcbcc1461 +0, 49, 49, 1, 1378560, 0x9c598000 From 98766dbbd77d5c14f3a889376be4d25972eca484 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Tue, 6 Jun 2023 12:31:28 +0200 Subject: [PATCH 1543/2172] fftools/ffmpeg_demux: move the loop out of add_input_streams() Make the function process just one input stream at a time and save an indentation level. Also rename it to ist_add() to be consistent with an analogous function in ffmpeg_mux_init. --- fftools/ffmpeg_demux.c | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) diff --git a/fftools/ffmpeg_demux.c b/fftools/ffmpeg_demux.c index 5e5f106368e..ea407d1f28d 100644 --- a/fftools/ffmpeg_demux.c +++ b/fftools/ffmpeg_demux.c @@ -1032,15 +1032,9 @@ static DemuxStream *demux_stream_alloc(Demuxer *d, AVStream *st) return ds; } -/* Add all the streams from the given input file to the demuxer */ -static void add_input_streams(const OptionsContext *o, Demuxer *d) +static void ist_add(const OptionsContext *o, Demuxer *d, AVStream *st) { - InputFile *f = &d->f; - AVFormatContext *ic = f->ctx; - int i, ret; - - for (i = 0; i < ic->nb_streams; i++) { - AVStream *st = ic->streams[i]; + AVFormatContext *ic = d->f.ctx; AVCodecParameters *par = st->codecpar; DemuxStream *ds; InputStream *ist; @@ -1053,6 +1047,7 @@ static void add_input_streams(const OptionsContext *o, Demuxer *d) const AVClass *cc = avcodec_get_class(); const AVOption *discard_opt = av_opt_find(&cc, "skip_frame", NULL, 0, AV_OPT_SEARCH_FAKE_OBJ); + int ret; ds = demux_stream_alloc(d, st); ist = &ds->ist; @@ -1265,7 +1260,6 @@ static void add_input_streams(const OptionsContext *o, Demuxer *d) } ist->codec_desc = avcodec_descriptor_get(ist->par->codec_id); - } } static void dump_attachment(InputStream *ist, const char *filename) @@ -1580,7 +1574,9 @@ int ifile_open(const OptionsContext *o, const char *filename) d->thread_queue_size = o->thread_queue_size; - add_input_streams(o, d); + /* Add all the streams from the given input file to the demuxer */ + for (int i = 0; i < ic->nb_streams; i++) + ist_add(o, d, ic->streams[i]); /* dump the file content */ av_dump_format(ic, f->index, filename, 0); From 6c9cbf7507a7c083bc37ffa130b77b42307dc142 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Tue, 6 Jun 2023 12:33:03 +0200 Subject: [PATCH 1544/2172] fftools/ffmpeg_demux: reindent after previous commit --- fftools/ffmpeg_demux.c | 386 ++++++++++++++++++++--------------------- 1 file changed, 193 insertions(+), 193 deletions(-) diff --git a/fftools/ffmpeg_demux.c b/fftools/ffmpeg_demux.c index ea407d1f28d..84c286dd658 100644 --- a/fftools/ffmpeg_demux.c +++ b/fftools/ffmpeg_demux.c @@ -1035,231 +1035,231 @@ static DemuxStream *demux_stream_alloc(Demuxer *d, AVStream *st) static void ist_add(const OptionsContext *o, Demuxer *d, AVStream *st) { AVFormatContext *ic = d->f.ctx; - AVCodecParameters *par = st->codecpar; - DemuxStream *ds; - InputStream *ist; - char *framerate = NULL, *hwaccel_device = NULL; - const char *hwaccel = NULL; - char *hwaccel_output_format = NULL; - char *codec_tag = NULL; - char *next; - char *discard_str = NULL; - const AVClass *cc = avcodec_get_class(); - const AVOption *discard_opt = av_opt_find(&cc, "skip_frame", NULL, - 0, AV_OPT_SEARCH_FAKE_OBJ); - int ret; - - ds = demux_stream_alloc(d, st); - ist = &ds->ist; - - ist->discard = 1; - st->discard = AVDISCARD_ALL; - ist->nb_samples = 0; - ds->first_dts = AV_NOPTS_VALUE; - ds->next_dts = AV_NOPTS_VALUE; - - ds->min_pts = INT64_MAX; - ds->max_pts = INT64_MIN; - - ds->ts_scale = 1.0; - MATCH_PER_STREAM_OPT(ts_scale, dbl, ds->ts_scale, ic, st); - - ist->autorotate = 1; - MATCH_PER_STREAM_OPT(autorotate, i, ist->autorotate, ic, st); - - MATCH_PER_STREAM_OPT(codec_tags, str, codec_tag, ic, st); - if (codec_tag) { - uint32_t tag = strtol(codec_tag, &next, 0); - if (*next) { - uint8_t buf[4] = { 0 }; - memcpy(buf, codec_tag, FFMIN(sizeof(buf), strlen(codec_tag))); - tag = AV_RL32(buf); - } + AVCodecParameters *par = st->codecpar; + DemuxStream *ds; + InputStream *ist; + char *framerate = NULL, *hwaccel_device = NULL; + const char *hwaccel = NULL; + char *hwaccel_output_format = NULL; + char *codec_tag = NULL; + char *next; + char *discard_str = NULL; + const AVClass *cc = avcodec_get_class(); + const AVOption *discard_opt = av_opt_find(&cc, "skip_frame", NULL, + 0, AV_OPT_SEARCH_FAKE_OBJ); + int ret; - st->codecpar->codec_tag = tag; - } + ds = demux_stream_alloc(d, st); + ist = &ds->ist; - if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) { - add_display_matrix_to_stream(o, ic, ist); + ist->discard = 1; + st->discard = AVDISCARD_ALL; + ist->nb_samples = 0; + ds->first_dts = AV_NOPTS_VALUE; + ds->next_dts = AV_NOPTS_VALUE; - MATCH_PER_STREAM_OPT(hwaccels, str, hwaccel, ic, st); - MATCH_PER_STREAM_OPT(hwaccel_output_formats, str, - hwaccel_output_format, ic, st); + ds->min_pts = INT64_MAX; + ds->max_pts = INT64_MIN; - if (!hwaccel_output_format && hwaccel && !strcmp(hwaccel, "cuvid")) { - av_log(ist, AV_LOG_WARNING, - "WARNING: defaulting hwaccel_output_format to cuda for compatibility " - "with old commandlines. This behaviour is DEPRECATED and will be removed " - "in the future. Please explicitly set \"-hwaccel_output_format cuda\".\n"); - ist->hwaccel_output_format = AV_PIX_FMT_CUDA; - } else if (!hwaccel_output_format && hwaccel && !strcmp(hwaccel, "qsv")) { - av_log(ist, AV_LOG_WARNING, - "WARNING: defaulting hwaccel_output_format to qsv for compatibility " - "with old commandlines. This behaviour is DEPRECATED and will be removed " - "in the future. Please explicitly set \"-hwaccel_output_format qsv\".\n"); - ist->hwaccel_output_format = AV_PIX_FMT_QSV; - } else if (!hwaccel_output_format && hwaccel && !strcmp(hwaccel, "mediacodec")) { - // There is no real AVHWFrameContext implementation. Set - // hwaccel_output_format to avoid av_hwframe_transfer_data error. - ist->hwaccel_output_format = AV_PIX_FMT_MEDIACODEC; - } else if (hwaccel_output_format) { - ist->hwaccel_output_format = av_get_pix_fmt(hwaccel_output_format); - if (ist->hwaccel_output_format == AV_PIX_FMT_NONE) { - av_log(ist, AV_LOG_FATAL, "Unrecognised hwaccel output " - "format: %s", hwaccel_output_format); - } - } else { - ist->hwaccel_output_format = AV_PIX_FMT_NONE; - } + ds->ts_scale = 1.0; + MATCH_PER_STREAM_OPT(ts_scale, dbl, ds->ts_scale, ic, st); - if (hwaccel) { - // The NVDEC hwaccels use a CUDA device, so remap the name here. - if (!strcmp(hwaccel, "nvdec") || !strcmp(hwaccel, "cuvid")) - hwaccel = "cuda"; - - if (!strcmp(hwaccel, "none")) - ist->hwaccel_id = HWACCEL_NONE; - else if (!strcmp(hwaccel, "auto")) - ist->hwaccel_id = HWACCEL_AUTO; - else { - 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; - } + ist->autorotate = 1; + MATCH_PER_STREAM_OPT(autorotate, i, ist->autorotate, ic, st); - if (!ist->hwaccel_id) { - av_log(ist, AV_LOG_FATAL, "Unrecognized hwaccel: %s.\n", - hwaccel); - av_log(ist, AV_LOG_FATAL, "Supported hwaccels: "); - type = AV_HWDEVICE_TYPE_NONE; - while ((type = av_hwdevice_iterate_types(type)) != - AV_HWDEVICE_TYPE_NONE) - av_log(ist, AV_LOG_FATAL, "%s ", - av_hwdevice_get_type_name(type)); - av_log(ist, AV_LOG_FATAL, "\n"); - exit_program(1); - } - } + MATCH_PER_STREAM_OPT(codec_tags, str, codec_tag, ic, st); + if (codec_tag) { + uint32_t tag = strtol(codec_tag, &next, 0); + if (*next) { + uint8_t buf[4] = { 0 }; + memcpy(buf, codec_tag, FFMIN(sizeof(buf), strlen(codec_tag))); + tag = AV_RL32(buf); + } + + st->codecpar->codec_tag = tag; + } + + if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) { + add_display_matrix_to_stream(o, ic, ist); + + MATCH_PER_STREAM_OPT(hwaccels, str, hwaccel, ic, st); + MATCH_PER_STREAM_OPT(hwaccel_output_formats, str, + hwaccel_output_format, ic, st); + + if (!hwaccel_output_format && hwaccel && !strcmp(hwaccel, "cuvid")) { + av_log(ist, AV_LOG_WARNING, + "WARNING: defaulting hwaccel_output_format to cuda for compatibility " + "with old commandlines. This behaviour is DEPRECATED and will be removed " + "in the future. Please explicitly set \"-hwaccel_output_format cuda\".\n"); + ist->hwaccel_output_format = AV_PIX_FMT_CUDA; + } else if (!hwaccel_output_format && hwaccel && !strcmp(hwaccel, "qsv")) { + av_log(ist, AV_LOG_WARNING, + "WARNING: defaulting hwaccel_output_format to qsv for compatibility " + "with old commandlines. This behaviour is DEPRECATED and will be removed " + "in the future. Please explicitly set \"-hwaccel_output_format qsv\".\n"); + ist->hwaccel_output_format = AV_PIX_FMT_QSV; + } else if (!hwaccel_output_format && hwaccel && !strcmp(hwaccel, "mediacodec")) { + // There is no real AVHWFrameContext implementation. Set + // hwaccel_output_format to avoid av_hwframe_transfer_data error. + ist->hwaccel_output_format = AV_PIX_FMT_MEDIACODEC; + } else if (hwaccel_output_format) { + ist->hwaccel_output_format = av_get_pix_fmt(hwaccel_output_format); + if (ist->hwaccel_output_format == AV_PIX_FMT_NONE) { + av_log(ist, AV_LOG_FATAL, "Unrecognised hwaccel output " + "format: %s", hwaccel_output_format); } + } else { + ist->hwaccel_output_format = AV_PIX_FMT_NONE; + } - MATCH_PER_STREAM_OPT(hwaccel_devices, str, hwaccel_device, ic, st); - if (hwaccel_device) { - ist->hwaccel_device = av_strdup(hwaccel_device); - if (!ist->hwaccel_device) - report_and_exit(AVERROR(ENOMEM)); + if (hwaccel) { + // The NVDEC hwaccels use a CUDA device, so remap the name here. + if (!strcmp(hwaccel, "nvdec") || !strcmp(hwaccel, "cuvid")) + hwaccel = "cuda"; + + if (!strcmp(hwaccel, "none")) + ist->hwaccel_id = HWACCEL_NONE; + else if (!strcmp(hwaccel, "auto")) + ist->hwaccel_id = HWACCEL_AUTO; + else { + 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) { + av_log(ist, AV_LOG_FATAL, "Unrecognized hwaccel: %s.\n", + hwaccel); + av_log(ist, AV_LOG_FATAL, "Supported hwaccels: "); + type = AV_HWDEVICE_TYPE_NONE; + while ((type = av_hwdevice_iterate_types(type)) != + AV_HWDEVICE_TYPE_NONE) + av_log(ist, AV_LOG_FATAL, "%s ", + av_hwdevice_get_type_name(type)); + av_log(ist, AV_LOG_FATAL, "\n"); + exit_program(1); + } } + } - ist->hwaccel_pix_fmt = AV_PIX_FMT_NONE; + MATCH_PER_STREAM_OPT(hwaccel_devices, str, hwaccel_device, ic, st); + if (hwaccel_device) { + ist->hwaccel_device = av_strdup(hwaccel_device); + if (!ist->hwaccel_device) + report_and_exit(AVERROR(ENOMEM)); } - ist->dec = choose_decoder(o, ic, st, ist->hwaccel_id, ist->hwaccel_device_type); - ist->decoder_opts = filter_codec_opts(o->g->codec_opts, ist->st->codecpar->codec_id, ic, st, ist->dec); + ist->hwaccel_pix_fmt = AV_PIX_FMT_NONE; + } - ist->reinit_filters = -1; - MATCH_PER_STREAM_OPT(reinit_filters, i, ist->reinit_filters, ic, st); + ist->dec = choose_decoder(o, ic, st, ist->hwaccel_id, ist->hwaccel_device_type); + ist->decoder_opts = filter_codec_opts(o->g->codec_opts, ist->st->codecpar->codec_id, ic, st, ist->dec); - MATCH_PER_STREAM_OPT(discard, str, discard_str, ic, st); - ist->user_set_discard = AVDISCARD_NONE; + ist->reinit_filters = -1; + MATCH_PER_STREAM_OPT(reinit_filters, i, ist->reinit_filters, ic, st); - if ((o->video_disable && ist->st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) || - (o->audio_disable && ist->st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) || - (o->subtitle_disable && ist->st->codecpar->codec_type == AVMEDIA_TYPE_SUBTITLE) || - (o->data_disable && ist->st->codecpar->codec_type == AVMEDIA_TYPE_DATA)) - ist->user_set_discard = AVDISCARD_ALL; + MATCH_PER_STREAM_OPT(discard, str, discard_str, ic, st); + ist->user_set_discard = AVDISCARD_NONE; - if (discard_str && av_opt_eval_int(&cc, discard_opt, discard_str, &ist->user_set_discard) < 0) { - av_log(ist, AV_LOG_ERROR, "Error parsing discard %s.\n", - discard_str); - exit_program(1); - } + if ((o->video_disable && ist->st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) || + (o->audio_disable && ist->st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) || + (o->subtitle_disable && ist->st->codecpar->codec_type == AVMEDIA_TYPE_SUBTITLE) || + (o->data_disable && ist->st->codecpar->codec_type == AVMEDIA_TYPE_DATA)) + ist->user_set_discard = AVDISCARD_ALL; - ist->dec_ctx = avcodec_alloc_context3(ist->dec); - if (!ist->dec_ctx) - report_and_exit(AVERROR(ENOMEM)); + if (discard_str && av_opt_eval_int(&cc, discard_opt, discard_str, &ist->user_set_discard) < 0) { + av_log(ist, AV_LOG_ERROR, "Error parsing discard %s.\n", + discard_str); + exit_program(1); + } - ret = avcodec_parameters_to_context(ist->dec_ctx, par); - if (ret < 0) { - av_log(ist, AV_LOG_ERROR, "Error initializing the decoder context.\n"); - exit_program(1); - } + ist->dec_ctx = avcodec_alloc_context3(ist->dec); + if (!ist->dec_ctx) + report_and_exit(AVERROR(ENOMEM)); - if (o->bitexact) - ist->dec_ctx->flags |= AV_CODEC_FLAG_BITEXACT; + ret = avcodec_parameters_to_context(ist->dec_ctx, par); + if (ret < 0) { + av_log(ist, AV_LOG_ERROR, "Error initializing the decoder context.\n"); + exit_program(1); + } - switch (par->codec_type) { - case AVMEDIA_TYPE_VIDEO: - MATCH_PER_STREAM_OPT(frame_rates, str, framerate, ic, st); - if (framerate && av_parse_video_rate(&ist->framerate, - framerate) < 0) { - av_log(ist, AV_LOG_ERROR, "Error parsing framerate %s.\n", - framerate); - exit_program(1); - } + if (o->bitexact) + ist->dec_ctx->flags |= AV_CODEC_FLAG_BITEXACT; - ist->top_field_first = -1; - MATCH_PER_STREAM_OPT(top_field_first, i, ist->top_field_first, ic, st); + switch (par->codec_type) { + case AVMEDIA_TYPE_VIDEO: + MATCH_PER_STREAM_OPT(frame_rates, str, framerate, ic, st); + if (framerate && av_parse_video_rate(&ist->framerate, + framerate) < 0) { + av_log(ist, AV_LOG_ERROR, "Error parsing framerate %s.\n", + framerate); + exit_program(1); + } - ist->framerate_guessed = av_guess_frame_rate(ic, st, NULL); + ist->top_field_first = -1; + MATCH_PER_STREAM_OPT(top_field_first, i, ist->top_field_first, ic, st); - break; - case AVMEDIA_TYPE_AUDIO: { - int guess_layout_max = INT_MAX; - MATCH_PER_STREAM_OPT(guess_layout_max, i, guess_layout_max, ic, st); - guess_input_channel_layout(ist, guess_layout_max); - break; + ist->framerate_guessed = av_guess_frame_rate(ic, st, NULL); + + break; + case AVMEDIA_TYPE_AUDIO: { + int guess_layout_max = INT_MAX; + MATCH_PER_STREAM_OPT(guess_layout_max, i, guess_layout_max, ic, st); + guess_input_channel_layout(ist, guess_layout_max); + break; + } + case AVMEDIA_TYPE_DATA: + case AVMEDIA_TYPE_SUBTITLE: { + char *canvas_size = NULL; + MATCH_PER_STREAM_OPT(fix_sub_duration, i, ist->fix_sub_duration, ic, st); + MATCH_PER_STREAM_OPT(canvas_sizes, str, canvas_size, ic, st); + if (canvas_size && + av_parse_video_size(&ist->dec_ctx->width, &ist->dec_ctx->height, canvas_size) < 0) { + av_log(ist, AV_LOG_FATAL, "Invalid canvas size: %s.\n", canvas_size); + exit_program(1); } - case AVMEDIA_TYPE_DATA: - case AVMEDIA_TYPE_SUBTITLE: { - char *canvas_size = NULL; - MATCH_PER_STREAM_OPT(fix_sub_duration, i, ist->fix_sub_duration, ic, st); - MATCH_PER_STREAM_OPT(canvas_sizes, str, canvas_size, ic, st); - if (canvas_size && - av_parse_video_size(&ist->dec_ctx->width, &ist->dec_ctx->height, canvas_size) < 0) { - av_log(ist, AV_LOG_FATAL, "Invalid canvas size: %s.\n", canvas_size); - exit_program(1); - } - /* Compute the size of the canvas for the subtitles stream. - If the subtitles codecpar has set a size, use it. Otherwise use the - maximum dimensions of the video streams in the same file. */ - ist->sub2video.w = ist->dec_ctx->width; - ist->sub2video.h = ist->dec_ctx->height; - if (!(ist->sub2video.w && ist->sub2video.h)) { - for (int j = 0; j < ic->nb_streams; j++) { - AVCodecParameters *par1 = ic->streams[j]->codecpar; - if (par1->codec_type == AVMEDIA_TYPE_VIDEO) { - ist->sub2video.w = FFMAX(ist->sub2video.w, par1->width); - ist->sub2video.h = FFMAX(ist->sub2video.h, par1->height); - } + /* Compute the size of the canvas for the subtitles stream. + If the subtitles codecpar has set a size, use it. Otherwise use the + maximum dimensions of the video streams in the same file. */ + ist->sub2video.w = ist->dec_ctx->width; + ist->sub2video.h = ist->dec_ctx->height; + if (!(ist->sub2video.w && ist->sub2video.h)) { + for (int j = 0; j < ic->nb_streams; j++) { + AVCodecParameters *par1 = ic->streams[j]->codecpar; + if (par1->codec_type == AVMEDIA_TYPE_VIDEO) { + ist->sub2video.w = FFMAX(ist->sub2video.w, par1->width); + ist->sub2video.h = FFMAX(ist->sub2video.h, par1->height); } } - - if (!(ist->sub2video.w && ist->sub2video.h)) { - ist->sub2video.w = FFMAX(ist->sub2video.w, 720); - ist->sub2video.h = FFMAX(ist->sub2video.h, 576); - } - - break; } - case AVMEDIA_TYPE_ATTACHMENT: - case AVMEDIA_TYPE_UNKNOWN: - break; - default: - abort(); + + if (!(ist->sub2video.w && ist->sub2video.h)) { + ist->sub2video.w = FFMAX(ist->sub2video.w, 720); + ist->sub2video.h = FFMAX(ist->sub2video.h, 576); } - ist->par = avcodec_parameters_alloc(); - if (!ist->par) - report_and_exit(AVERROR(ENOMEM)); + break; + } + case AVMEDIA_TYPE_ATTACHMENT: + case AVMEDIA_TYPE_UNKNOWN: + break; + default: + abort(); + } + + ist->par = avcodec_parameters_alloc(); + if (!ist->par) + report_and_exit(AVERROR(ENOMEM)); - ret = avcodec_parameters_from_context(ist->par, ist->dec_ctx); - if (ret < 0) { - av_log(ist, AV_LOG_ERROR, "Error initializing the decoder context.\n"); - exit_program(1); - } + ret = avcodec_parameters_from_context(ist->par, ist->dec_ctx); + if (ret < 0) { + av_log(ist, AV_LOG_ERROR, "Error initializing the decoder context.\n"); + exit_program(1); + } - ist->codec_desc = avcodec_descriptor_get(ist->par->codec_id); + ist->codec_desc = avcodec_descriptor_get(ist->par->codec_id); } static void dump_attachment(InputStream *ist, const char *filename) From 25d96ab6c03ce979a14c05ed7a737d345d8d36a1 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Tue, 6 Jun 2023 12:54:25 +0200 Subject: [PATCH 1545/2172] fftools/ffmpeg_hw: inline hwaccel_decode_init() into its caller The function is now trivial and cannot fail, so all error handling in its caller can be removed. --- fftools/ffmpeg.h | 2 +- fftools/ffmpeg_dec.c | 15 +-------------- fftools/ffmpeg_hw.c | 11 +---------- 3 files changed, 3 insertions(+), 25 deletions(-) diff --git a/fftools/ffmpeg.h b/fftools/ffmpeg.h index 7189629ad48..aeecf92fe69 100644 --- a/fftools/ffmpeg.h +++ b/fftools/ffmpeg.h @@ -805,7 +805,7 @@ void hw_device_free_all(void); */ AVBufferRef *hw_device_for_filter(void); -int hwaccel_decode_init(AVCodecContext *avctx); +int hwaccel_retrieve_data(AVCodecContext *avctx, AVFrame *input); int dec_open(InputStream *ist); void dec_free(Decoder **pdec); diff --git a/fftools/ffmpeg_dec.c b/fftools/ffmpeg_dec.c index 6582917a39d..ca9fbb9bd8c 100644 --- a/fftools/ffmpeg_dec.c +++ b/fftools/ffmpeg_dec.c @@ -538,7 +538,6 @@ static enum AVPixelFormat get_format(AVCodecContext *s, const enum AVPixelFormat { InputStream *ist = s->opaque; const enum AVPixelFormat *p; - int ret; for (p = pix_fmts; *p != AV_PIX_FMT_NONE; p++) { const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(*p); @@ -562,19 +561,7 @@ static enum AVPixelFormat get_format(AVCodecContext *s, const enum AVPixelFormat } } if (config && config->device_type == ist->hwaccel_device_type) { - ret = hwaccel_decode_init(s); - if (ret < 0) { - if (ist->hwaccel_id == HWACCEL_GENERIC) { - av_log(NULL, AV_LOG_FATAL, - "%s hwaccel requested for input stream #%d:%d, " - "but cannot be initialized.\n", - av_hwdevice_get_type_name(config->device_type), - ist->file_index, ist->index); - return AV_PIX_FMT_NONE; - } - continue; - } - + ist->hwaccel_retrieve_data = hwaccel_retrieve_data; ist->hwaccel_pix_fmt = *p; break; } diff --git a/fftools/ffmpeg_hw.c b/fftools/ffmpeg_hw.c index 4a0b346fe1a..46bc7e39c22 100644 --- a/fftools/ffmpeg_hw.c +++ b/fftools/ffmpeg_hw.c @@ -297,7 +297,7 @@ void hw_device_free_all(void) nb_hw_devices = 0; } -static int hwaccel_retrieve_data(AVCodecContext *avctx, AVFrame *input) +int hwaccel_retrieve_data(AVCodecContext *avctx, AVFrame *input) { InputStream *ist = avctx->opaque; AVFrame *output = NULL; @@ -339,15 +339,6 @@ static int hwaccel_retrieve_data(AVCodecContext *avctx, AVFrame *input) return err; } -int hwaccel_decode_init(AVCodecContext *avctx) -{ - InputStream *ist = avctx->opaque; - - ist->hwaccel_retrieve_data = &hwaccel_retrieve_data; - - return 0; -} - AVBufferRef *hw_device_for_filter(void) { // Pick the last hardware device if the user doesn't pick the device for From 174cb3accf75d107c2c1b1b2f1138c1e2b3af85b Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Tue, 6 Jun 2023 12:55:53 +0200 Subject: [PATCH 1546/2172] fftools/ffmpeg_dec: remove pointless InputStream.hwaccel_retrieve_data It is always set to hwaccel_retrieve_data() from ffmpeg_hw.c, so that function can just be called directly instead. --- fftools/ffmpeg.h | 1 - fftools/ffmpeg_dec.c | 5 ++--- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/fftools/ffmpeg.h b/fftools/ffmpeg.h index aeecf92fe69..2559225dd6b 100644 --- a/fftools/ffmpeg.h +++ b/fftools/ffmpeg.h @@ -393,7 +393,6 @@ typedef struct InputStream { char *hwaccel_device; enum AVPixelFormat hwaccel_output_format; - int (*hwaccel_retrieve_data)(AVCodecContext *s, AVFrame *frame); enum AVPixelFormat hwaccel_pix_fmt; /* stats */ diff --git a/fftools/ffmpeg_dec.c b/fftools/ffmpeg_dec.c index ca9fbb9bd8c..85132050d8f 100644 --- a/fftools/ffmpeg_dec.c +++ b/fftools/ffmpeg_dec.c @@ -272,8 +272,8 @@ static int video_frame_process(InputStream *ist, AVFrame *frame) if(ist->top_field_first>=0) frame->flags |= AV_FRAME_FLAG_TOP_FIELD_FIRST; - if (ist->hwaccel_retrieve_data && frame->format == ist->hwaccel_pix_fmt) { - int err = ist->hwaccel_retrieve_data(ist->dec_ctx, frame); + if (frame->format == ist->hwaccel_pix_fmt) { + int err = hwaccel_retrieve_data(ist->dec_ctx, frame); if (err < 0) return err; } @@ -561,7 +561,6 @@ static enum AVPixelFormat get_format(AVCodecContext *s, const enum AVPixelFormat } } if (config && config->device_type == ist->hwaccel_device_type) { - ist->hwaccel_retrieve_data = hwaccel_retrieve_data; ist->hwaccel_pix_fmt = *p; break; } From 1adad44fc783615cd13c83c7d08218bf3d9f2419 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Tue, 6 Jun 2023 13:00:01 +0200 Subject: [PATCH 1547/2172] fftools/ffmpeg_dec: move InputStream.hwaccel_pix_fmt to Decoder It is purely decoder-internal state. --- fftools/ffmpeg.h | 2 -- fftools/ffmpeg_dec.c | 8 ++++++-- fftools/ffmpeg_demux.c | 2 -- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/fftools/ffmpeg.h b/fftools/ffmpeg.h index 2559225dd6b..3c7e819507d 100644 --- a/fftools/ffmpeg.h +++ b/fftools/ffmpeg.h @@ -393,8 +393,6 @@ typedef struct InputStream { char *hwaccel_device; enum AVPixelFormat hwaccel_output_format; - enum AVPixelFormat hwaccel_pix_fmt; - /* stats */ // number of frames/samples retrieved from the decoder uint64_t frames_decoded; diff --git a/fftools/ffmpeg_dec.c b/fftools/ffmpeg_dec.c index 85132050d8f..586be83dc1e 100644 --- a/fftools/ffmpeg_dec.c +++ b/fftools/ffmpeg_dec.c @@ -35,6 +35,8 @@ struct Decoder { AVFrame *frame; AVPacket *pkt; + enum AVPixelFormat hwaccel_pix_fmt; + // pts/estimated duration of the last decoded frame // * in decoder timebase for video, // * in last_frame_tb (may change during decoding) for audio @@ -79,6 +81,7 @@ static int dec_alloc(Decoder **pdec) dec->last_filter_in_rescale_delta = AV_NOPTS_VALUE; dec->last_frame_pts = AV_NOPTS_VALUE; dec->last_frame_tb = (AVRational){ 1, 1 }; + dec->hwaccel_pix_fmt = AV_PIX_FMT_NONE; *pdec = dec; @@ -272,7 +275,7 @@ static int video_frame_process(InputStream *ist, AVFrame *frame) if(ist->top_field_first>=0) frame->flags |= AV_FRAME_FLAG_TOP_FIELD_FIRST; - if (frame->format == ist->hwaccel_pix_fmt) { + if (frame->format == d->hwaccel_pix_fmt) { int err = hwaccel_retrieve_data(ist->dec_ctx, frame); if (err < 0) return err; @@ -537,6 +540,7 @@ int dec_packet(InputStream *ist, const AVPacket *pkt, int no_eof) static enum AVPixelFormat get_format(AVCodecContext *s, const enum AVPixelFormat *pix_fmts) { InputStream *ist = s->opaque; + Decoder *d = ist->decoder; const enum AVPixelFormat *p; for (p = pix_fmts; *p != AV_PIX_FMT_NONE; p++) { @@ -561,7 +565,7 @@ static enum AVPixelFormat get_format(AVCodecContext *s, const enum AVPixelFormat } } if (config && config->device_type == ist->hwaccel_device_type) { - ist->hwaccel_pix_fmt = *p; + d->hwaccel_pix_fmt = *p; break; } } diff --git a/fftools/ffmpeg_demux.c b/fftools/ffmpeg_demux.c index 84c286dd658..1c6a5aab7bd 100644 --- a/fftools/ffmpeg_demux.c +++ b/fftools/ffmpeg_demux.c @@ -1149,8 +1149,6 @@ static void ist_add(const OptionsContext *o, Demuxer *d, AVStream *st) if (!ist->hwaccel_device) report_and_exit(AVERROR(ENOMEM)); } - - ist->hwaccel_pix_fmt = AV_PIX_FMT_NONE; } ist->dec = choose_decoder(o, ic, st, ist->hwaccel_id, ist->hwaccel_device_type); From a934392db048c51b1f3d0f93319ebe351c872ed3 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Sat, 3 Jun 2023 10:08:44 +0200 Subject: [PATCH 1548/2172] fftools/ffmpeg_enc: move dup_warning global variable to Encoder --- fftools/ffmpeg_enc.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/fftools/ffmpeg_enc.c b/fftools/ffmpeg_enc.c index 2bf4782a9fe..0fdf7e7c4d6 100644 --- a/fftools/ffmpeg_enc.c +++ b/fftools/ffmpeg_enc.c @@ -66,11 +66,11 @@ struct Encoder { // number of packets received from the encoder uint64_t packets_encoded; + uint64_t dup_warning; + int opened; }; -static uint64_t dup_warning = 1000; - void enc_free(Encoder **penc) { Encoder *enc = *penc; @@ -106,6 +106,8 @@ int enc_alloc(Encoder **penc, const AVCodec *codec) if (!enc->pkt) goto fail; + enc->dup_warning = 1000; + *penc = enc; return 0; @@ -1070,9 +1072,9 @@ static void do_video_out(OutputFile *of, OutputStream *ost, AVFrame *frame) } ost->nb_frames_dup += nb_frames - (nb_frames_prev && ost->last_dropped) - (nb_frames > nb_frames_prev); av_log(ost, AV_LOG_VERBOSE, "*** %"PRId64" dup!\n", nb_frames - 1); - if (ost->nb_frames_dup > dup_warning) { - av_log(ost, AV_LOG_WARNING, "More than %"PRIu64" frames duplicated\n", dup_warning); - dup_warning *= 10; + if (ost->nb_frames_dup > e->dup_warning) { + av_log(ost, AV_LOG_WARNING, "More than %"PRIu64" frames duplicated\n", e->dup_warning); + e->dup_warning *= 10; } } ost->last_dropped = nb_frames == nb_frames_prev && frame; From a7aa05c599fc013e967cc54f1ce0dbe16316235e Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Thu, 8 Jun 2023 20:58:16 +0200 Subject: [PATCH 1549/2172] fftools/ffmpeg_filter: add an AVClass to FilterGraph Use it for logging. --- fftools/ffmpeg.h | 1 + fftools/ffmpeg_filter.c | 59 +++++++++++++++++++++++++++++------------ 2 files changed, 43 insertions(+), 17 deletions(-) diff --git a/fftools/ffmpeg.h b/fftools/ffmpeg.h index 3c7e819507d..8de8e94e311 100644 --- a/fftools/ffmpeg.h +++ b/fftools/ffmpeg.h @@ -311,6 +311,7 @@ typedef struct OutputFilter { } OutputFilter; typedef struct FilterGraph { + const AVClass *class; int index; AVFilterGraph *graph; diff --git a/fftools/ffmpeg_filter.c b/fftools/ffmpeg_filter.c index a2b45a14b85..4f7565e44e0 100644 --- a/fftools/ffmpeg_filter.c +++ b/fftools/ffmpeg_filter.c @@ -41,6 +41,9 @@ typedef struct FilterGraphPriv { FilterGraph fg; + // name used for logging + char log_name[32]; + int is_simple; const char *graph_desc; @@ -692,7 +695,7 @@ void ofilter_bind_ost(OutputFilter *ofilter, OutputStream *ost) ret = configure_filtergraph(fg); if (ret < 0) { - av_log(NULL, AV_LOG_ERROR, "Error configuring filter graph: %s\n", + av_log(fg, AV_LOG_ERROR, "Error configuring filter graph: %s\n", av_err2str(ret)); exit_program(1); } @@ -775,6 +778,20 @@ void fg_free(FilterGraph **pfg) av_freep(pfg); } +static const char *fg_item_name(void *obj) +{ + const FilterGraphPriv *fgp = obj; + + return fgp->log_name; +} + +static const AVClass fg_class = { + .class_name = "FilterGraph", + .version = LIBAVUTIL_VERSION_INT, + .item_name = fg_item_name, + .category = AV_CLASS_CATEGORY_FILTER, +}; + FilterGraph *fg_create(char *graph_desc) { FilterGraphPriv *fgp = allocate_array_elem(&filtergraphs, sizeof(*fgp), &nb_filtergraphs); @@ -784,9 +801,12 @@ FilterGraph *fg_create(char *graph_desc) AVFilterGraph *graph; int ret = 0; + fg->class = &fg_class; fg->index = nb_filtergraphs - 1; fgp->graph_desc = graph_desc; + snprintf(fgp->log_name, sizeof(fgp->log_name), "fc#%d", fg->index); + fgp->frame = av_frame_alloc(); if (!fgp->frame) report_and_exit(AVERROR(ENOMEM)); @@ -850,8 +870,12 @@ int init_simple_filtergraph(InputStream *ist, OutputStream *ost, fgp->is_simple = 1; + snprintf(fgp->log_name, sizeof(fgp->log_name), "%cf#%d:%d", + av_get_media_type_string(ost->type)[0], + ost->file_index, ost->index); + if (fg->nb_inputs != 1 || fg->nb_outputs != 1) { - av_log(NULL, AV_LOG_ERROR, "Simple filtergraph '%s' was expected " + av_log(fg, AV_LOG_ERROR, "Simple filtergraph '%s' was expected " "to have exactly 1 input and 1 output. " "However, it had %d input(s) and %d output(s). Please adjust, " "or use a complex filtergraph (-filter_complex) instead.\n", @@ -880,7 +904,7 @@ static void init_input_filter(FilterGraph *fg, InputFilter *ifilter) // TODO: support other filter types if (type != AVMEDIA_TYPE_VIDEO && type != AVMEDIA_TYPE_AUDIO) { - av_log(NULL, AV_LOG_FATAL, "Only video and audio filters supported " + av_log(fg, AV_LOG_FATAL, "Only video and audio filters supported " "currently.\n"); exit_program(1); } @@ -892,7 +916,7 @@ static void init_input_filter(FilterGraph *fg, InputFilter *ifilter) int file_idx = strtol(ifp->linklabel, &p, 0); if (file_idx < 0 || file_idx >= nb_input_files) { - av_log(NULL, AV_LOG_FATAL, "Invalid file index %d in filtergraph description %s.\n", + av_log(fg, AV_LOG_FATAL, "Invalid file index %d in filtergraph description %s.\n", file_idx, fgp->graph_desc); exit_program(1); } @@ -910,7 +934,7 @@ static void init_input_filter(FilterGraph *fg, InputFilter *ifilter) } } if (!st) { - av_log(NULL, AV_LOG_FATAL, "Stream specifier '%s' in filtergraph description %s " + av_log(fg, AV_LOG_FATAL, "Stream specifier '%s' in filtergraph description %s " "matches no streams.\n", p, fgp->graph_desc); exit_program(1); } @@ -918,7 +942,7 @@ static void init_input_filter(FilterGraph *fg, InputFilter *ifilter) } else { ist = ist_find_unused(type); if (!ist) { - av_log(NULL, AV_LOG_FATAL, "Cannot find a matching stream for " + av_log(fg, AV_LOG_FATAL, "Cannot find a matching stream for " "unlabeled input pad %s\n", ifilter->name); exit_program(1); } @@ -927,7 +951,7 @@ static void init_input_filter(FilterGraph *fg, InputFilter *ifilter) ret = ifilter_bind_ist(ifilter, ist); if (ret < 0) { - av_log(NULL, AV_LOG_ERROR, + av_log(fg, AV_LOG_ERROR, "Error binding an input stream to complex filtergraph input %s.\n", ifilter->name); exit_program(1); @@ -1111,7 +1135,7 @@ static int configure_output_audio_filter(FilterGraph *fg, OutputFilter *ofilter, #define AUTO_INSERT_FILTER(opt_name, filter_name, arg) do { \ AVFilterContext *filt_ctx; \ \ - av_log(NULL, AV_LOG_INFO, opt_name " is forwarded to lavfi " \ + av_log(fg, AV_LOG_INFO, opt_name " is forwarded to lavfi " \ "similarly to -af " filter_name "=%s.\n", arg); \ \ ret = avfilter_graph_create_filter(&filt_ctx, \ @@ -1200,7 +1224,7 @@ static int configure_output_filter(FilterGraph *fg, OutputFilter *ofilter, AVFilterInOut *out) { if (!ofilter->ost) { - av_log(NULL, AV_LOG_FATAL, "Filter %s has an unconnected output\n", ofilter->name); + av_log(fg, AV_LOG_FATAL, "Filter %s has an unconnected output\n", ofilter->name); exit_program(1); } @@ -1219,7 +1243,8 @@ void check_filter_outputs(void) for (n = 0; n < filtergraphs[i]->nb_outputs; n++) { OutputFilter *output = filtergraphs[i]->outputs[n]; if (!output->ost) { - av_log(NULL, AV_LOG_FATAL, "Filter %s has an unconnected output\n", output->name); + av_log(filtergraphs[i], AV_LOG_FATAL, + "Filter %s has an unconnected output\n", output->name); exit_program(1); } } @@ -1261,7 +1286,7 @@ static int configure_input_video_filter(FilterGraph *fg, InputFilter *ifilter, par->format = AV_PIX_FMT_NONE; if (ist->dec_ctx->codec_type == AVMEDIA_TYPE_AUDIO) { - av_log(NULL, AV_LOG_ERROR, "Cannot connect video filter to audio input\n"); + av_log(fg, AV_LOG_ERROR, "Cannot connect video filter to audio input\n"); ret = AVERROR(EINVAL); goto fail; } @@ -1376,7 +1401,7 @@ static int configure_input_audio_filter(FilterGraph *fg, InputFilter *ifilter, int64_t tsoffset = 0; if (ist->dec_ctx->codec_type != AVMEDIA_TYPE_AUDIO) { - av_log(NULL, AV_LOG_ERROR, "Cannot connect audio filter to non audio input\n"); + av_log(fg, AV_LOG_ERROR, "Cannot connect audio filter to non audio input\n"); return AVERROR(EINVAL); } @@ -1685,7 +1710,7 @@ int reap_filters(int flush) AV_BUFFERSINK_FLAG_NO_REQUEST); if (ret < 0) { if (ret != AVERROR(EAGAIN) && ret != AVERROR_EOF) { - av_log(NULL, AV_LOG_WARNING, + av_log(fgp, AV_LOG_WARNING, "Error in av_buffersink_get_frame_flags(): %s\n", av_err2str(ret)); } else if (flush && ret == AVERROR_EOF) { if (av_buffersink_get_type(filter) == AVMEDIA_TYPE_VIDEO) @@ -1705,7 +1730,7 @@ int reap_filters(int flush) filtered_frame->time_base = tb; if (debug_ts) - av_log(NULL, AV_LOG_INFO, "filter_raw -> pts:%s pts_time:%s time_base:%d/%d\n", + av_log(fgp, AV_LOG_INFO, "filter_raw -> pts:%s pts_time:%s time_base:%d/%d\n", av_ts2str(filtered_frame->pts), av_ts2timestr(filtered_frame->pts, &tb), tb.num, tb.den); @@ -1896,13 +1921,13 @@ int ifilter_send_frame(InputFilter *ifilter, AVFrame *frame, int keep_reference) ret = reap_filters(0); if (ret < 0 && ret != AVERROR_EOF) { - av_log(NULL, AV_LOG_ERROR, "Error while filtering: %s\n", av_err2str(ret)); + av_log(fg, AV_LOG_ERROR, "Error while filtering: %s\n", av_err2str(ret)); return ret; } ret = configure_filtergraph(fg); if (ret < 0) { - av_log(NULL, AV_LOG_ERROR, "Error reinitializing filters!\n"); + av_log(fg, AV_LOG_ERROR, "Error reinitializing filters!\n"); return ret; } } @@ -1929,7 +1954,7 @@ int ifilter_send_frame(InputFilter *ifilter, AVFrame *frame, int keep_reference) if (ret < 0) { av_frame_unref(frame); if (ret != AVERROR_EOF) - av_log(NULL, AV_LOG_ERROR, "Error while filtering: %s\n", av_err2str(ret)); + av_log(fg, AV_LOG_ERROR, "Error while filtering: %s\n", av_err2str(ret)); return ret; } From b1a213ab5d84085ae2b98452daa8feda01881cbf Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Thu, 8 Jun 2023 21:33:44 +0200 Subject: [PATCH 1550/2172] fftools/ffmpeg_filter: reject filtergraphs with zero outputs Nothing useful can be done with them currently. --- fftools/ffmpeg_filter.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/fftools/ffmpeg_filter.c b/fftools/ffmpeg_filter.c index 4f7565e44e0..54c7ed1f5cc 100644 --- a/fftools/ffmpeg_filter.c +++ b/fftools/ffmpeg_filter.c @@ -845,6 +845,12 @@ FilterGraph *fg_create(char *graph_desc) ofilter->name = describe_filter_link(fg, cur, 0); } + if (!fg->nb_outputs) { + av_log(fg, AV_LOG_FATAL, "A filtergraph has zero outputs, this is not supported\n"); + ret = AVERROR(ENOSYS); + goto fail; + } + fail: avfilter_inout_free(&inputs); avfilter_inout_free(&outputs); From 1bdd53e2f95522eefddc34217c74afe8aa8d9a03 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Fri, 9 Jun 2023 19:16:29 +0200 Subject: [PATCH 1551/2172] fftools/ffmpeg_filter: make configure_filtergraph() static It is no longer used outside of ffmpeg_filter. --- fftools/ffmpeg.h | 1 - fftools/ffmpeg_filter.c | 4 +++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/fftools/ffmpeg.h b/fftools/ffmpeg.h index 8de8e94e311..80d9ab52bce 100644 --- a/fftools/ffmpeg.h +++ b/fftools/ffmpeg.h @@ -726,7 +726,6 @@ const AVCodec *find_codec_or_die(void *logctx, const char *name, enum AVMediaType type, int encoder); int parse_and_set_vsync(const char *arg, int *vsync_var, int file_idx, int st_idx, int is_global); -int configure_filtergraph(FilterGraph *fg); void check_filter_outputs(void); int filtergraph_is_simple(const FilterGraph *fg); int init_simple_filtergraph(InputStream *ist, OutputStream *ost, diff --git a/fftools/ffmpeg_filter.c b/fftools/ffmpeg_filter.c index 54c7ed1f5cc..ccde5b26ec8 100644 --- a/fftools/ffmpeg_filter.c +++ b/fftools/ffmpeg_filter.c @@ -133,6 +133,8 @@ static InputFilterPriv *ifp_from_ifilter(InputFilter *ifilter) return (InputFilterPriv*)ifilter; } +static int configure_filtergraph(FilterGraph *fg); + static int sub2video_get_blank_frame(InputFilterPriv *ifp) { AVFrame *frame = ifp->sub2video.frame; @@ -1496,7 +1498,7 @@ static int graph_is_meta(AVFilterGraph *graph) return 1; } -int configure_filtergraph(FilterGraph *fg) +static int configure_filtergraph(FilterGraph *fg) { FilterGraphPriv *fgp = fgp_from_fg(fg); AVBufferRef *hw_device; From 7d4e00ccf0b77dab1bf74320b26af968ba670394 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Fri, 2 Jun 2023 15:12:58 +0200 Subject: [PATCH 1552/2172] fftools/ffmpeg_dec: stop using Decoder.pkt It is only used for flushing the subtitle decoder, so allocate a dedicated packet for that. Keep Decoder.pkt unused for now, it will be repurposed in future commits. --- fftools/ffmpeg_dec.c | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/fftools/ffmpeg_dec.c b/fftools/ffmpeg_dec.c index 586be83dc1e..f9053c424bb 100644 --- a/fftools/ffmpeg_dec.c +++ b/fftools/ffmpeg_dec.c @@ -385,10 +385,20 @@ int process_subtitle(InputStream *ist, AVSubtitle *subtitle) static int transcode_subtitles(InputStream *ist, const AVPacket *pkt) { + AVPacket *flush_pkt = NULL; AVSubtitle subtitle; int got_output; - int ret = avcodec_decode_subtitle2(ist->dec_ctx, - &subtitle, &got_output, pkt); + int ret; + + if (!pkt) { + flush_pkt = av_packet_alloc(); + if (!flush_pkt) + return AVERROR(ENOMEM); + } + + ret = avcodec_decode_subtitle2(ist->dec_ctx, &subtitle, &got_output, + pkt ? pkt : flush_pkt); + av_packet_free(&flush_pkt); if (ret < 0) { av_log(ist, AV_LOG_ERROR, "Error decoding subtitles: %s\n", @@ -399,7 +409,7 @@ static int transcode_subtitles(InputStream *ist, const AVPacket *pkt) } if (ret < 0 || !got_output) { - if (!pkt->size) + if (!pkt) sub2video_flush(ist); return ret < 0 ? ret : AVERROR_EOF; } @@ -432,7 +442,7 @@ int dec_packet(InputStream *ist, const AVPacket *pkt, int no_eof) int ret; if (dec->codec_type == AVMEDIA_TYPE_SUBTITLE) - return transcode_subtitles(ist, pkt ? pkt : d->pkt); + return transcode_subtitles(ist, pkt); // With fate-indeo3-2, we're getting 0-sized packets before EOF for some // reason. This seems like a semi-critical bug. Don't trigger EOF, and From 5293adb1a72347a2c13de1f3b0b37d51625f6985 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Sat, 27 May 2023 17:38:36 +0200 Subject: [PATCH 1553/2172] fftools/ffmpeg: attach bits_per_raw_sample information to frames This way avoids encoders reaching into filters or decoders for this information. --- fftools/ffmpeg.h | 7 ++----- fftools/ffmpeg_dec.c | 21 ++++++++++----------- fftools/ffmpeg_enc.c | 13 ++++++------- fftools/ffmpeg_filter.c | 25 +++++++++++++++++-------- fftools/ffmpeg_mux_init.c | 14 +++++--------- 5 files changed, 40 insertions(+), 40 deletions(-) diff --git a/fftools/ffmpeg.h b/fftools/ffmpeg.h index 80d9ab52bce..abc1a21d731 100644 --- a/fftools/ffmpeg.h +++ b/fftools/ffmpeg.h @@ -315,9 +315,6 @@ typedef struct FilterGraph { int index; AVFilterGraph *graph; - // true when the filtergraph contains only meta filters - // that do not modify the frame data - int is_meta; InputFilter **inputs; int nb_inputs; @@ -339,8 +336,6 @@ typedef struct InputStream { int decoding_needed; /* non zero if the packets must be decoded in 'raw_fifo', see DECODING_FOR_* */ #define DECODING_FOR_OST 1 #define DECODING_FOR_FILTER 2 - // should attach FrameData as opaque_ref after decoding - int want_frame_data; /** * Codec parameters - to be used by the decoding/streamcopy code. @@ -653,6 +648,8 @@ typedef struct FrameData { AVRational tb; AVRational frame_rate_filter; + + int bits_per_raw_sample; } FrameData; extern InputFile **input_files; diff --git a/fftools/ffmpeg_dec.c b/fftools/ffmpeg_dec.c index f9053c424bb..e6c6e22b046 100644 --- a/fftools/ffmpeg_dec.c +++ b/fftools/ffmpeg_dec.c @@ -472,6 +472,7 @@ int dec_packet(InputStream *ist, const AVPacket *pkt, int no_eof) while (1) { AVFrame *frame = d->frame; + FrameData *fd; update_benchmark(NULL); ret = avcodec_receive_frame(dec, frame); @@ -508,19 +509,17 @@ int dec_packet(InputStream *ist, const AVPacket *pkt, int no_eof) exit_program(1); } - if (ist->want_frame_data) { - FrameData *fd; - av_assert0(!frame->opaque_ref); - fd = frame_data(frame); - if (!fd) { - av_frame_unref(frame); - report_and_exit(AVERROR(ENOMEM)); - } - fd->pts = frame->pts; - fd->tb = dec->pkt_timebase; - fd->idx = dec->frame_num - 1; + av_assert0(!frame->opaque_ref); + fd = frame_data(frame); + if (!fd) { + av_frame_unref(frame); + report_and_exit(AVERROR(ENOMEM)); } + fd->pts = frame->pts; + fd->tb = dec->pkt_timebase; + fd->idx = dec->frame_num - 1; + fd->bits_per_raw_sample = dec->bits_per_raw_sample; frame->time_base = dec->pkt_timebase; diff --git a/fftools/ffmpeg_enc.c b/fftools/ffmpeg_enc.c index 0fdf7e7c4d6..f42f4055d67 100644 --- a/fftools/ffmpeg_enc.c +++ b/fftools/ffmpeg_enc.c @@ -198,6 +198,7 @@ int enc_open(OutputStream *ost, AVFrame *frame) AVCodecContext *dec_ctx = NULL; const AVCodec *enc = enc_ctx->codec; OutputFile *of = output_files[ost->file_index]; + FrameData *fd = frame ? frame_data(frame) : NULL; int ret; if (e->opened) @@ -219,8 +220,8 @@ int enc_open(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 && ost->filter->graph->is_meta) - enc_ctx->bits_per_raw_sample = FFMIN(dec_ctx->bits_per_raw_sample, + else if (fd) + enc_ctx->bits_per_raw_sample = FFMIN(fd->bits_per_raw_sample, av_get_bytes_per_sample(enc_ctx->sample_fmt) << 3); enc_ctx->time_base = ost->enc_timebase.num > 0 ? ost->enc_timebase : @@ -230,10 +231,8 @@ int enc_open(OutputStream *ost, AVFrame *frame) case AVMEDIA_TYPE_VIDEO: { AVRational fr = ost->frame_rate; - if (!fr.num && frame) { - FrameData *fd = frame_data(frame); + if (!fr.num && fd) fr = fd->frame_rate_filter; - } if (!fr.num && !ost->max_frame_rate.num) { fr = (AVRational){25, 1}; av_log(ost, AV_LOG_WARNING, @@ -282,8 +281,8 @@ int enc_open(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 && ost->filter->graph->is_meta) - enc_ctx->bits_per_raw_sample = FFMIN(dec_ctx->bits_per_raw_sample, + else if (fd) + enc_ctx->bits_per_raw_sample = FFMIN(fd->bits_per_raw_sample, av_pix_fmt_desc_get(enc_ctx->pix_fmt)->comp[0].depth); if (frame) { diff --git a/fftools/ffmpeg_filter.c b/fftools/ffmpeg_filter.c index ccde5b26ec8..9e6883ccdd9 100644 --- a/fftools/ffmpeg_filter.c +++ b/fftools/ffmpeg_filter.c @@ -45,6 +45,9 @@ typedef struct FilterGraphPriv { char log_name[32]; int is_simple; + // true when the filtergraph contains only meta filters + // that do not modify the frame data + int is_meta; const char *graph_desc; @@ -1566,7 +1569,7 @@ static int configure_filtergraph(FilterGraph *fg) if ((ret = avfilter_graph_config(fg->graph, NULL)) < 0) goto fail; - fg->is_meta = graph_is_meta(fg->graph); + fgp->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 */ @@ -1714,6 +1717,8 @@ int reap_filters(int flush) filtered_frame = fgp->frame; while (1) { + FrameData *fd; + ret = av_buffersink_get_frame_flags(filter, filtered_frame, AV_BUFFERSINK_FLAG_NO_REQUEST); if (ret < 0) { @@ -1744,15 +1749,19 @@ int reap_filters(int flush) tb.num, tb.den); } - if (ost->type == AVMEDIA_TYPE_VIDEO) { - FrameData *fd = frame_data(filtered_frame); - if (!fd) { - av_frame_unref(filtered_frame); - report_and_exit(AVERROR(ENOMEM)); - } + fd = frame_data(filtered_frame); + if (!fd) { + av_frame_unref(filtered_frame); + report_and_exit(AVERROR(ENOMEM)); + } + + // only use bits_per_raw_sample passed through from the decoder + // if the filtergraph did not touch the frame data + if (!fgp->is_meta) + fd->bits_per_raw_sample = 0; + if (ost->type == AVMEDIA_TYPE_VIDEO) fd->frame_rate_filter = av_buffersink_get_frame_rate(filter); - } enc_frame(ost, filtered_frame); av_frame_unref(filtered_frame); diff --git a/fftools/ffmpeg_mux_init.c b/fftools/ffmpeg_mux_init.c index a18320fa9b6..6ab541d7c5a 100644 --- a/fftools/ffmpeg_mux_init.c +++ b/fftools/ffmpeg_mux_init.c @@ -365,15 +365,11 @@ static int enc_stats_init(OutputStream *ost, EncStats *es, int pre, c->type = fmt_specs[i].type; - if (fmt_specs[i].need_input_data) { - if (ost->ist) - ost->ist->want_frame_data = 1; - else { - av_log(ost, AV_LOG_WARNING, - "Format directive '%s' is unavailable, because " - "this output stream has no associated input stream\n", - val); - } + if (fmt_specs[i].need_input_data && !ost->ist) { + av_log(ost, AV_LOG_WARNING, + "Format directive '%s' is unavailable, because " + "this output stream has no associated input stream\n", + val); } break; From 01897c1788b887e42a69072fc6516a73521bdcd6 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Fri, 2 Jun 2023 09:59:31 +0200 Subject: [PATCH 1554/2172] fftools/ffmpeg_dec: move decoding to a separate thread This is only a preparatory step to a fully threaded architecture and does not yet make decoding truly parallel - the main thread will currently submit a packet and wait until it has been fully processed by the decoding thread before moving on. Decoder behavior as observed by the rest of the program should remain unchanged. That will change in future commits after encoders and filters are moved to threads and a thread-aware scheduler is added. --- fftools/ffmpeg.c | 63 +++++--- fftools/ffmpeg.h | 11 ++ fftools/ffmpeg_dec.c | 363 ++++++++++++++++++++++++++++++++++++++----- fftools/ffmpeg_mux.c | 5 - 4 files changed, 381 insertions(+), 61 deletions(-) diff --git a/fftools/ffmpeg.c b/fftools/ffmpeg.c index 45e71ed626c..4e6205e3cbc 100644 --- a/fftools/ffmpeg.c +++ b/fftools/ffmpeg.c @@ -728,6 +728,46 @@ int copy_av_subtitle(AVSubtitle *dst, const AVSubtitle *src) return ret; } +static void subtitle_free(void *opaque, uint8_t *data) +{ + AVSubtitle *sub = (AVSubtitle*)data; + avsubtitle_free(sub); + av_free(sub); +} + +int subtitle_wrap_frame(AVFrame *frame, AVSubtitle *subtitle, int copy) +{ + AVBufferRef *buf; + AVSubtitle *sub; + int ret; + + if (copy) { + sub = av_mallocz(sizeof(*sub)); + ret = sub ? copy_av_subtitle(sub, subtitle) : AVERROR(ENOMEM); + if (ret < 0) { + av_freep(&sub); + return ret; + } + } else { + sub = av_memdup(subtitle, sizeof(*subtitle)); + if (!sub) + return AVERROR(ENOMEM); + memset(subtitle, 0, sizeof(*subtitle)); + } + + buf = av_buffer_create((uint8_t*)sub, sizeof(*sub), + subtitle_free, NULL, 0); + if (!buf) { + avsubtitle_free(sub); + av_freep(&sub); + return AVERROR(ENOMEM); + } + + frame->buf[0] = buf; + + return 0; +} + static int fix_sub_duration_heartbeat(InputStream *ist, int64_t signal_pts) { int ret = AVERROR_BUG; @@ -1038,30 +1078,11 @@ static void decode_flush(InputFile *ifile) { for (int i = 0; i < ifile->nb_streams; i++) { InputStream *ist = ifile->streams[i]; - int ret; - if (ist->discard) + if (ist->discard || !ist->decoding_needed) continue; - do { - ret = process_input_packet(ist, NULL, 1); - } while (ret > 0); - - if (ist->decoding_needed) { - /* report last frame duration to the demuxer thread */ - if (ist->par->codec_type == AVMEDIA_TYPE_AUDIO) { - LastFrameDuration dur; - - dur.stream_idx = i; - dur.duration = av_rescale_q(ist->nb_samples, - (AVRational){ 1, ist->dec_ctx->sample_rate}, - ist->st->time_base); - - av_thread_message_queue_send(ifile->audio_duration_queue, &dur, 0); - } - - avcodec_flush_buffers(ist->dec_ctx); - } + dec_packet(ist, NULL, 1); } } diff --git a/fftools/ffmpeg.h b/fftools/ffmpeg.h index abc1a21d731..5d60da085b4 100644 --- a/fftools/ffmpeg.h +++ b/fftools/ffmpeg.h @@ -730,6 +730,7 @@ int init_simple_filtergraph(InputStream *ist, OutputStream *ost, int init_complex_filtergraph(FilterGraph *fg); int copy_av_subtitle(AVSubtitle *dst, const AVSubtitle *src); +int subtitle_wrap_frame(AVFrame *frame, AVSubtitle *subtitle, int copy); /** * Get our axiliary frame data attached to the frame, allocating it @@ -941,4 +942,14 @@ extern const char * const opt_name_codec_tags[]; extern const char * const opt_name_frame_rates[]; extern const char * const opt_name_top_field_first[]; +static inline void pkt_move(void *dst, void *src) +{ + av_packet_move_ref(dst, src); +} + +static inline void frame_move(void *dst, void *src) +{ + av_frame_move_ref(dst, src); +} + #endif /* FFTOOLS_FFMPEG_H */ diff --git a/fftools/ffmpeg_dec.c b/fftools/ffmpeg_dec.c index e6c6e22b046..d2505345b5e 100644 --- a/fftools/ffmpeg_dec.c +++ b/fftools/ffmpeg_dec.c @@ -30,6 +30,7 @@ #include "libavfilter/buffersrc.h" #include "ffmpeg.h" +#include "thread_queue.h" struct Decoder { AVFrame *frame; @@ -45,8 +46,50 @@ struct Decoder { AVRational last_frame_tb; int64_t last_filter_in_rescale_delta; int last_frame_sample_rate; + + pthread_t thread; + /** + * Queue for sending coded packets from the main thread to + * the decoder thread. + * + * An empty packet is sent to flush the decoder without terminating + * decoding. + */ + ThreadQueue *queue_in; + /** + * Queue for sending decoded frames from the decoder thread + * to the main thread. + * + * An empty frame is sent to signal that a single packet has been fully + * processed. + */ + ThreadQueue *queue_out; }; +// data that is local to the decoder thread and not visible outside of it +typedef struct DecThreadContext { + AVFrame *frame; + AVPacket *pkt; +} DecThreadContext; + +static int dec_thread_stop(Decoder *d) +{ + void *ret; + + if (!d->queue_in) + return 0; + + tq_send_finish(d->queue_in, 0); + tq_receive_finish(d->queue_out, 0); + + pthread_join(d->thread, &ret); + + tq_free(&d->queue_in); + tq_free(&d->queue_out); + + return (intptr_t)ret; +} + void dec_free(Decoder **pdec) { Decoder *dec = *pdec; @@ -54,6 +97,8 @@ void dec_free(Decoder **pdec) if (!dec) return; + dec_thread_stop(dec); + av_frame_free(&dec->frame); av_packet_free(&dec->pkt); @@ -383,8 +428,10 @@ int process_subtitle(InputStream *ist, AVSubtitle *subtitle) return ret; } -static int transcode_subtitles(InputStream *ist, const AVPacket *pkt) +static int transcode_subtitles(InputStream *ist, const AVPacket *pkt, + AVFrame *frame) { + Decoder *d = ist->decoder; AVPacket *flush_pkt = NULL; AVSubtitle subtitle; int got_output; @@ -403,20 +450,30 @@ static int transcode_subtitles(InputStream *ist, const AVPacket *pkt) if (ret < 0) { av_log(ist, AV_LOG_ERROR, "Error decoding subtitles: %s\n", av_err2str(ret)); - if (exit_on_error) - exit_program(1); ist->decode_errors++; + return exit_on_error ? ret : 0; } - if (ret < 0 || !got_output) { - if (!pkt) - sub2video_flush(ist); - return ret < 0 ? ret : AVERROR_EOF; - } + if (!got_output) + return pkt ? 0 : AVERROR_EOF; ist->frames_decoded++; - return process_subtitle(ist, &subtitle); + // XXX the queue for transferring data back to the main thread runs + // on AVFrames, so we wrap AVSubtitle in an AVBufferRef and put that + // inside the frame + // eventually, subtitles should be switched to use AVFrames natively + ret = subtitle_wrap_frame(frame, &subtitle, 0); + if (ret < 0) { + avsubtitle_free(&subtitle); + return ret; + } + + ret = tq_send(d->queue_out, 0, frame); + if (ret < 0) + av_frame_unref(frame); + + return ret; } static int send_filter_eof(InputStream *ist) @@ -434,7 +491,7 @@ static int send_filter_eof(InputStream *ist) return 0; } -int dec_packet(InputStream *ist, const AVPacket *pkt, int no_eof) +static int packet_decode(InputStream *ist, const AVPacket *pkt, AVFrame *frame) { Decoder *d = ist->decoder; AVCodecContext *dec = ist->dec_ctx; @@ -442,7 +499,7 @@ int dec_packet(InputStream *ist, const AVPacket *pkt, int no_eof) int ret; if (dec->codec_type == AVMEDIA_TYPE_SUBTITLE) - return transcode_subtitles(ist, pkt); + return transcode_subtitles(ist, pkt, frame); // With fate-indeo3-2, we're getting 0-sized packets before EOF for some // reason. This seems like a semi-critical bug. Don't trigger EOF, and @@ -457,23 +514,25 @@ int dec_packet(InputStream *ist, const AVPacket *pkt, int no_eof) if (ret == AVERROR(EAGAIN)) { av_log(ist, AV_LOG_FATAL, "A decoder returned an unexpected error code. " "This is a bug, please report it.\n"); - exit_program(1); + return AVERROR_BUG; } av_log(ist, AV_LOG_ERROR, "Error submitting %s to decoder: %s\n", pkt ? "packet" : "EOF", av_err2str(ret)); - if (exit_on_error) - exit_program(1); - if (ret != AVERROR_EOF) + if (ret != AVERROR_EOF) { ist->decode_errors++; + if (!exit_on_error) + ret = 0; + } return ret; } while (1) { - AVFrame *frame = d->frame; FrameData *fd; + av_frame_unref(frame); + update_benchmark(NULL); ret = avcodec_receive_frame(dec, frame); update_benchmark("decode_%s %d.%d", type_desc, @@ -483,30 +542,22 @@ int dec_packet(InputStream *ist, const AVPacket *pkt, int no_eof) av_assert0(pkt); // should never happen during flushing return 0; } else if (ret == AVERROR_EOF) { - /* after flushing, send an EOF on all the filter inputs attached to the stream */ - /* except when looping we need to flush but not to send an EOF */ - if (!no_eof) { - ret = send_filter_eof(ist); - if (ret < 0) { - av_log(NULL, AV_LOG_FATAL, "Error marking filters as finished\n"); - exit_program(1); - } - } - - return AVERROR_EOF; + return ret; } else if (ret < 0) { av_log(ist, AV_LOG_ERROR, "Decoding error: %s\n", av_err2str(ret)); - if (exit_on_error) - exit_program(1); ist->decode_errors++; - return ret; + + if (exit_on_error) + return ret; + + continue; } if (frame->decode_error_flags || (frame->flags & AV_FRAME_FLAG_CORRUPT)) { av_log(ist, exit_on_error ? AV_LOG_FATAL : AV_LOG_WARNING, "corrupt decoded frame\n"); if (exit_on_error) - exit_program(1); + return AVERROR_INVALIDDATA; } @@ -514,7 +565,7 @@ int dec_packet(InputStream *ist, const AVPacket *pkt, int no_eof) fd = frame_data(frame); if (!fd) { av_frame_unref(frame); - report_and_exit(AVERROR(ENOMEM)); + return AVERROR(ENOMEM); } fd->pts = frame->pts; fd->tb = dec->pkt_timebase; @@ -533,17 +584,252 @@ int dec_packet(InputStream *ist, const AVPacket *pkt, int no_eof) if (ret < 0) { av_log(NULL, AV_LOG_FATAL, "Error while processing the decoded " "data for stream #%d:%d\n", ist->file_index, ist->index); - exit_program(1); + return ret; } } ist->frames_decoded++; - ret = send_frame_to_filters(ist, frame); - av_frame_unref(frame); + ret = tq_send(d->queue_out, 0, frame); if (ret < 0) + return ret; + } +} + +static void dec_thread_set_name(const InputStream *ist) +{ + char name[16]; + snprintf(name, sizeof(name), "dec%d:%d:%s", ist->file_index, ist->index, + ist->dec_ctx->codec->name); + ff_thread_setname(name); +} + +static void dec_thread_uninit(DecThreadContext *dt) +{ + av_packet_free(&dt->pkt); + av_frame_free(&dt->frame); + + memset(dt, 0, sizeof(*dt)); +} + +static int dec_thread_init(DecThreadContext *dt) +{ + memset(dt, 0, sizeof(*dt)); + + dt->frame = av_frame_alloc(); + if (!dt->frame) + goto fail; + + dt->pkt = av_packet_alloc(); + if (!dt->pkt) + goto fail; + + return 0; + +fail: + dec_thread_uninit(dt); + return AVERROR(ENOMEM); +} + +static void *decoder_thread(void *arg) +{ + InputStream *ist = arg; + InputFile *ifile = input_files[ist->file_index]; + Decoder *d = ist->decoder; + DecThreadContext dt; + int ret = 0, input_status = 0; + + ret = dec_thread_init(&dt); + if (ret < 0) + goto finish; + + dec_thread_set_name(ist); + + while (!input_status) { + int dummy, flush_buffers; + + input_status = tq_receive(d->queue_in, &dummy, dt.pkt); + flush_buffers = input_status >= 0 && !dt.pkt->buf; + if (!dt.pkt->buf) + av_log(ist, AV_LOG_VERBOSE, "Decoder thread received %s packet\n", + flush_buffers ? "flush" : "EOF"); + + ret = packet_decode(ist, dt.pkt->buf ? dt.pkt : NULL, dt.frame); + + av_packet_unref(dt.pkt); + av_frame_unref(dt.frame); + + if (ret == AVERROR_EOF) { + av_log(ist, AV_LOG_VERBOSE, "Decoder returned EOF, %s\n", + flush_buffers ? "resetting" : "finishing"); + + if (!flush_buffers) + break; + + /* report last frame duration to the demuxer thread */ + if (ist->dec->type == AVMEDIA_TYPE_AUDIO) { + LastFrameDuration dur; + + dur.stream_idx = ist->index; + dur.duration = av_rescale_q(ist->nb_samples, + (AVRational){ 1, ist->dec_ctx->sample_rate}, + ist->st->time_base); + + av_thread_message_queue_send(ifile->audio_duration_queue, &dur, 0); + } + + avcodec_flush_buffers(ist->dec_ctx); + } else if (ret < 0) { + av_log(ist, AV_LOG_ERROR, "Error processing packet in decoder: %s\n", + av_err2str(ret)); + break; + } + + // signal to the consumer thread that the entire packet was processed + ret = tq_send(d->queue_out, 0, dt.frame); + if (ret < 0) { + if (ret != AVERROR_EOF) + av_log(ist, AV_LOG_ERROR, "Error communicating with the main thread\n"); + break; + } + } + + // EOF is normal thread termination + if (ret == AVERROR_EOF) + ret = 0; + +finish: + tq_receive_finish(d->queue_in, 0); + tq_send_finish (d->queue_out, 0); + + // make sure the demuxer does not get stuck waiting for audio durations + // that will never arrive + if (ifile->audio_duration_queue && ist->dec->type == AVMEDIA_TYPE_AUDIO) + av_thread_message_queue_set_err_recv(ifile->audio_duration_queue, AVERROR_EOF); + + dec_thread_uninit(&dt); + + av_log(ist, AV_LOG_VERBOSE, "Terminating decoder thread\n"); + + return (void*)(intptr_t)ret; +} + +int dec_packet(InputStream *ist, const AVPacket *pkt, int no_eof) +{ + Decoder *d = ist->decoder; + int ret = 0, thread_ret; + + // thread already joined + if (!d->queue_in) + return AVERROR_EOF; + + // send the packet/flush request/EOF to the decoder thread + if (pkt || no_eof) { + av_packet_unref(d->pkt); + + if (pkt) { + ret = av_packet_ref(d->pkt, pkt); + if (ret < 0) + goto finish; + } + + ret = tq_send(d->queue_in, 0, d->pkt); + if (ret < 0) + goto finish; + } else + tq_send_finish(d->queue_in, 0); + + // retrieve all decoded data for the packet + while (1) { + int dummy; + + ret = tq_receive(d->queue_out, &dummy, d->frame); + if (ret < 0) + goto finish; + + // packet fully processed + if (!d->frame->buf[0]) + return 0; + + // process the decoded frame + if (ist->dec->type == AVMEDIA_TYPE_SUBTITLE) { + AVSubtitle *sub = (AVSubtitle*)d->frame->buf[0]->data; + ret = process_subtitle(ist, sub); + } else { + ret = send_frame_to_filters(ist, d->frame); + } + av_frame_unref(d->frame); + if (ret < 0) + goto finish; + } + +finish: + thread_ret = dec_thread_stop(d); + if (thread_ret < 0) { + av_log(ist, AV_LOG_ERROR, "Decoder thread returned error: %s\n", + av_err2str(thread_ret)); + ret = err_merge(ret, thread_ret); + } + // non-EOF errors here are all fatal + if (ret < 0 && ret != AVERROR_EOF) + report_and_exit(ret); + + // signal EOF to our downstreams + if (ist->dec->type == AVMEDIA_TYPE_SUBTITLE) + sub2video_flush(ist); + else { + ret = send_filter_eof(ist); + if (ret < 0) { + av_log(NULL, AV_LOG_FATAL, "Error marking filters as finished\n"); exit_program(1); + } } + + return AVERROR_EOF; +} + +static int dec_thread_start(InputStream *ist) +{ + Decoder *d = ist->decoder; + ObjPool *op; + int ret = 0; + + op = objpool_alloc_packets(); + if (!op) + return AVERROR(ENOMEM); + + d->queue_in = tq_alloc(1, 1, op, pkt_move); + if (!d->queue_in) { + objpool_free(&op); + return AVERROR(ENOMEM); + } + + op = objpool_alloc_frames(); + if (!op) + goto fail; + + d->queue_out = tq_alloc(1, 4, op, frame_move); + if (!d->queue_out) { + objpool_free(&op); + goto fail; + } + + ret = pthread_create(&d->thread, NULL, decoder_thread, ist); + if (ret) { + ret = AVERROR(ret); + av_log(ist, AV_LOG_ERROR, "pthread_create() failed: %s\n", + av_err2str(ret)); + goto fail; + } + + return 0; +fail: + if (ret >= 0) + ret = AVERROR(ENOMEM); + + tq_free(&d->queue_in); + tq_free(&d->queue_out); + return ret; } static enum AVPixelFormat get_format(AVCodecContext *s, const enum AVPixelFormat *pix_fmts) @@ -781,5 +1067,12 @@ int dec_open(InputStream *ist) } assert_avoptions(ist->decoder_opts); + ret = dec_thread_start(ist); + if (ret < 0) { + av_log(ist, AV_LOG_ERROR, "Error starting decoder thread: %s\n", + av_err2str(ret)); + return ret; + } + return 0; } diff --git a/fftools/ffmpeg_mux.c b/fftools/ffmpeg_mux.c index 66b2324bb30..026796f7e61 100644 --- a/fftools/ffmpeg_mux.c +++ b/fftools/ffmpeg_mux.c @@ -475,11 +475,6 @@ static int thread_stop(Muxer *mux) return (int)(intptr_t)ret; } -static void pkt_move(void *dst, void *src) -{ - av_packet_move_ref(dst, src); -} - static int thread_start(Muxer *mux) { AVFormatContext *fc = mux->fc; From a45b9d35b9852fd2c5ecdc5b43f48c82e6afddc7 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Wed, 14 Jun 2023 16:09:25 +0200 Subject: [PATCH 1555/2172] fftools/ffmpeg: move fix_sub_duration_heartbeat() to ffmpeg_dec This way ffmpeg.c does not need to access InputStream.prev_sub and it can be made private. --- fftools/ffmpeg.c | 18 ------------------ fftools/ffmpeg.h | 2 +- fftools/ffmpeg_dec.c | 20 +++++++++++++++++++- 3 files changed, 20 insertions(+), 20 deletions(-) diff --git a/fftools/ffmpeg.c b/fftools/ffmpeg.c index 4e6205e3cbc..435e12a37bf 100644 --- a/fftools/ffmpeg.c +++ b/fftools/ffmpeg.c @@ -768,24 +768,6 @@ int subtitle_wrap_frame(AVFrame *frame, AVSubtitle *subtitle, int copy) return 0; } -static int fix_sub_duration_heartbeat(InputStream *ist, int64_t signal_pts) -{ - int ret = AVERROR_BUG; - AVSubtitle *prev_subtitle = &ist->prev_sub.subtitle; - AVSubtitle subtitle; - - if (!ist->fix_sub_duration || !prev_subtitle->num_rects || - signal_pts <= prev_subtitle->pts) - return 0; - - if ((ret = copy_av_subtitle(&subtitle, prev_subtitle)) < 0) - return ret; - - subtitle.pts = signal_pts; - - return process_subtitle(ist, &subtitle); -} - int trigger_fix_sub_duration_heartbeat(OutputStream *ost, const AVPacket *pkt) { OutputFile *of = output_files[ost->file_index]; diff --git a/fftools/ffmpeg.h b/fftools/ffmpeg.h index 5d60da085b4..b4b55f5a73e 100644 --- a/fftools/ffmpeg.h +++ b/fftools/ffmpeg.h @@ -879,7 +879,7 @@ OutputStream *ost_iter(OutputStream *prev); void close_output_stream(OutputStream *ost); int trigger_fix_sub_duration_heartbeat(OutputStream *ost, const AVPacket *pkt); -int process_subtitle(InputStream *ist, AVSubtitle *subtitle); +int fix_sub_duration_heartbeat(InputStream *ist, int64_t signal_pts); void update_benchmark(const char *fmt, ...); /** diff --git a/fftools/ffmpeg_dec.c b/fftools/ffmpeg_dec.c index d2505345b5e..a425b701d48 100644 --- a/fftools/ffmpeg_dec.c +++ b/fftools/ffmpeg_dec.c @@ -376,7 +376,7 @@ static void sub2video_flush(InputStream *ist) } } -int process_subtitle(InputStream *ist, AVSubtitle *subtitle) +static int process_subtitle(InputStream *ist, AVSubtitle *subtitle) { int got_output = 1; int ret = 0; @@ -428,6 +428,24 @@ int process_subtitle(InputStream *ist, AVSubtitle *subtitle) return ret; } +int fix_sub_duration_heartbeat(InputStream *ist, int64_t signal_pts) +{ + int ret = AVERROR_BUG; + AVSubtitle *prev_subtitle = &ist->prev_sub.subtitle; + AVSubtitle subtitle; + + if (!ist->fix_sub_duration || !prev_subtitle->num_rects || + signal_pts <= prev_subtitle->pts) + return 0; + + if ((ret = copy_av_subtitle(&subtitle, prev_subtitle)) < 0) + return ret; + + subtitle.pts = signal_pts; + + return process_subtitle(ist, &subtitle); +} + static int transcode_subtitles(InputStream *ist, const AVPacket *pkt, AVFrame *frame) { From e89a6d1089d5afdb15f4eb118f24a0a98ac9ae93 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Wed, 14 Jun 2023 16:16:50 +0200 Subject: [PATCH 1556/2172] fftools/ffmpeg_dec: move InputStream.prev_sub to Decoder It does not need to be visible outside of decoding code. --- fftools/ffmpeg.h | 4 ---- fftools/ffmpeg_dec.c | 26 ++++++++++++++++++-------- fftools/ffmpeg_demux.c | 1 - 3 files changed, 18 insertions(+), 13 deletions(-) diff --git a/fftools/ffmpeg.h b/fftools/ffmpeg.h index b4b55f5a73e..63ca5423377 100644 --- a/fftools/ffmpeg.h +++ b/fftools/ffmpeg.h @@ -359,10 +359,6 @@ typedef struct InputStream { int autorotate; int fix_sub_duration; - struct { /* previous decoded subtitle and related variables */ - int got_output; - AVSubtitle subtitle; - } prev_sub; struct sub2video { int w, h; diff --git a/fftools/ffmpeg_dec.c b/fftools/ffmpeg_dec.c index a425b701d48..36f418eec82 100644 --- a/fftools/ffmpeg_dec.c +++ b/fftools/ffmpeg_dec.c @@ -47,6 +47,12 @@ struct Decoder { int64_t last_filter_in_rescale_delta; int last_frame_sample_rate; + /* previous decoded subtitle and related variables */ + struct { + int got_output; + AVSubtitle subtitle; + } prev_sub; + pthread_t thread; /** * Queue for sending coded packets from the main thread to @@ -102,6 +108,8 @@ void dec_free(Decoder **pdec) av_frame_free(&dec->frame); av_packet_free(&dec->pkt); + avsubtitle_free(&dec->prev_sub.subtitle); + av_freep(pdec); } @@ -378,24 +386,25 @@ static void sub2video_flush(InputStream *ist) static int process_subtitle(InputStream *ist, AVSubtitle *subtitle) { + Decoder *d = ist->decoder; int got_output = 1; int ret = 0; if (ist->fix_sub_duration) { int end = 1; - if (ist->prev_sub.got_output) { - end = av_rescale(subtitle->pts - ist->prev_sub.subtitle.pts, + if (d->prev_sub.got_output) { + end = av_rescale(subtitle->pts - d->prev_sub.subtitle.pts, 1000, AV_TIME_BASE); - if (end < ist->prev_sub.subtitle.end_display_time) { + if (end < d->prev_sub.subtitle.end_display_time) { av_log(NULL, AV_LOG_DEBUG, "Subtitle duration reduced from %"PRId32" to %d%s\n", - ist->prev_sub.subtitle.end_display_time, end, + d->prev_sub.subtitle.end_display_time, end, end <= 0 ? ", dropping it" : ""); - ist->prev_sub.subtitle.end_display_time = end; + d->prev_sub.subtitle.end_display_time = end; } } - FFSWAP(int, got_output, ist->prev_sub.got_output); - FFSWAP(AVSubtitle, *subtitle, ist->prev_sub.subtitle); + FFSWAP(int, got_output, d->prev_sub.got_output); + FFSWAP(AVSubtitle, *subtitle, d->prev_sub.subtitle); if (end <= 0) goto out; } @@ -430,8 +439,9 @@ static int process_subtitle(InputStream *ist, AVSubtitle *subtitle) int fix_sub_duration_heartbeat(InputStream *ist, int64_t signal_pts) { + Decoder *d = ist->decoder; int ret = AVERROR_BUG; - AVSubtitle *prev_subtitle = &ist->prev_sub.subtitle; + AVSubtitle *prev_subtitle = &d->prev_sub.subtitle; AVSubtitle subtitle; if (!ist->fix_sub_duration || !prev_subtitle->num_rects || diff --git a/fftools/ffmpeg_demux.c b/fftools/ffmpeg_demux.c index 1c6a5aab7bd..5d3e043793d 100644 --- a/fftools/ffmpeg_demux.c +++ b/fftools/ffmpeg_demux.c @@ -816,7 +816,6 @@ static void ist_free(InputStream **pist) dec_free(&ist->decoder); av_dict_free(&ist->decoder_opts); - avsubtitle_free(&ist->prev_sub.subtitle); av_freep(&ist->filters); av_freep(&ist->outputs); av_freep(&ist->hwaccel_device); From fa717baaa599b07eb647cf70a527b98b18c8236e Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Wed, 14 Jun 2023 16:35:46 +0200 Subject: [PATCH 1557/2172] fftools/ffmpeg_enc: constify the subtitle passed to enc_subtitle() --- fftools/ffmpeg.h | 2 +- fftools/ffmpeg_enc.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/fftools/ffmpeg.h b/fftools/ffmpeg.h index 63ca5423377..3da5bc4f7c3 100644 --- a/fftools/ffmpeg.h +++ b/fftools/ffmpeg.h @@ -816,7 +816,7 @@ int enc_alloc(Encoder **penc, const AVCodec *codec); void enc_free(Encoder **penc); int enc_open(OutputStream *ost, AVFrame *frame); -void enc_subtitle(OutputFile *of, OutputStream *ost, AVSubtitle *sub); +void enc_subtitle(OutputFile *of, OutputStream *ost, const AVSubtitle *sub); void enc_frame(OutputStream *ost, AVFrame *frame); void enc_flush(void); diff --git a/fftools/ffmpeg_enc.c b/fftools/ffmpeg_enc.c index f42f4055d67..40295013130 100644 --- a/fftools/ffmpeg_enc.c +++ b/fftools/ffmpeg_enc.c @@ -462,7 +462,7 @@ static int check_recording_time(OutputStream *ost, int64_t ts, AVRational tb) return 1; } -void enc_subtitle(OutputFile *of, OutputStream *ost, AVSubtitle *sub) +void enc_subtitle(OutputFile *of, OutputStream *ost, const AVSubtitle *sub) { Encoder *e = ost->enc; int subtitle_out_max_size = 1024 * 1024; From 88f80977eb571044e2bc157fe1b60ac63061eba0 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Wed, 14 Jun 2023 18:08:10 +0200 Subject: [PATCH 1558/2172] fftools/ffmpeg: use AVFrame to pass subtitles from decoders to filters Allows to use the same buffering code for all media types. Will also be important for the following commit. --- fftools/ffmpeg.h | 2 +- fftools/ffmpeg_dec.c | 88 ++++++++++++++++++++++++++--------------- fftools/ffmpeg_filter.c | 51 ++++++------------------ 3 files changed, 70 insertions(+), 71 deletions(-) diff --git a/fftools/ffmpeg.h b/fftools/ffmpeg.h index 3da5bc4f7c3..316cd2b7a67 100644 --- a/fftools/ffmpeg.h +++ b/fftools/ffmpeg.h @@ -736,7 +736,7 @@ FrameData *frame_data(AVFrame *frame); int ifilter_send_frame(InputFilter *ifilter, AVFrame *frame, int keep_reference); int ifilter_send_eof(InputFilter *ifilter, int64_t pts, AVRational tb); -int ifilter_sub2video(InputFilter *ifilter, const AVSubtitle *sub); +int ifilter_sub2video(InputFilter *ifilter, const AVFrame *frame); void ifilter_sub2video_heartbeat(InputFilter *ifilter, int64_t pts, AVRational tb); /** diff --git a/fftools/ffmpeg_dec.c b/fftools/ffmpeg_dec.c index 36f418eec82..3722a87bc58 100644 --- a/fftools/ffmpeg_dec.c +++ b/fftools/ffmpeg_dec.c @@ -47,11 +47,9 @@ struct Decoder { int64_t last_filter_in_rescale_delta; int last_frame_sample_rate; - /* previous decoded subtitle and related variables */ - struct { - int got_output; - AVSubtitle subtitle; - } prev_sub; + /* previous decoded subtitles */ + AVFrame *sub_prev[2]; + AVFrame *sub_heartbeat; pthread_t thread; /** @@ -108,7 +106,9 @@ void dec_free(Decoder **pdec) av_frame_free(&dec->frame); av_packet_free(&dec->pkt); - avsubtitle_free(&dec->prev_sub.subtitle); + for (int i = 0; i < FF_ARRAY_ELEMS(dec->sub_prev); i++) + av_frame_free(&dec->sub_prev[i]); + av_frame_free(&dec->sub_heartbeat); av_freep(pdec); } @@ -384,45 +384,55 @@ static void sub2video_flush(InputStream *ist) } } -static int process_subtitle(InputStream *ist, AVSubtitle *subtitle) +static int process_subtitle(InputStream *ist, AVFrame *frame) { Decoder *d = ist->decoder; - int got_output = 1; + const AVSubtitle *subtitle = (AVSubtitle*)frame->buf[0]->data; int ret = 0; if (ist->fix_sub_duration) { + AVSubtitle *sub_prev = d->sub_prev[0]->buf[0] ? + (AVSubtitle*)d->sub_prev[0]->buf[0]->data : NULL; int end = 1; - if (d->prev_sub.got_output) { - end = av_rescale(subtitle->pts - d->prev_sub.subtitle.pts, + if (sub_prev) { + end = av_rescale(subtitle->pts - sub_prev->pts, 1000, AV_TIME_BASE); - if (end < d->prev_sub.subtitle.end_display_time) { + if (end < sub_prev->end_display_time) { av_log(NULL, AV_LOG_DEBUG, "Subtitle duration reduced from %"PRId32" to %d%s\n", - d->prev_sub.subtitle.end_display_time, end, + sub_prev->end_display_time, end, end <= 0 ? ", dropping it" : ""); - d->prev_sub.subtitle.end_display_time = end; + sub_prev->end_display_time = end; } } - FFSWAP(int, got_output, d->prev_sub.got_output); - FFSWAP(AVSubtitle, *subtitle, d->prev_sub.subtitle); + + av_frame_unref(d->sub_prev[1]); + av_frame_move_ref(d->sub_prev[1], frame); + + frame = d->sub_prev[0]; + subtitle = frame->buf[0] ? (AVSubtitle*)frame->buf[0]->data : NULL; + + FFSWAP(AVFrame*, d->sub_prev[0], d->sub_prev[1]); + if (end <= 0) - goto out; + return 0; } - if (!got_output) + if (!subtitle) return 0; for (int i = 0; i < ist->nb_filters; i++) { - ret = ifilter_sub2video(ist->filters[i], subtitle); + ret = ifilter_sub2video(ist->filters[i], frame); if (ret < 0) { av_log(ist, AV_LOG_ERROR, "Error sending a subtitle for filtering: %s\n", av_err2str(ret)); - goto out; + return ret; } } + subtitle = (AVSubtitle*)frame->buf[0]->data; if (!subtitle->num_rects) - goto out; + return 0; for (int oidx = 0; oidx < ist->nb_outputs; oidx++) { OutputStream *ost = ist->outputs[oidx]; @@ -432,28 +442,30 @@ static int process_subtitle(InputStream *ist, AVSubtitle *subtitle) enc_subtitle(output_files[ost->file_index], ost, subtitle); } -out: - avsubtitle_free(subtitle); - return ret; + return 0; } int fix_sub_duration_heartbeat(InputStream *ist, int64_t signal_pts) { Decoder *d = ist->decoder; int ret = AVERROR_BUG; - AVSubtitle *prev_subtitle = &d->prev_sub.subtitle; - AVSubtitle subtitle; + AVSubtitle *prev_subtitle = d->sub_prev[0]->buf[0] ? + (AVSubtitle*)d->sub_prev[0]->buf[0]->data : NULL; + AVSubtitle *subtitle; - if (!ist->fix_sub_duration || !prev_subtitle->num_rects || - signal_pts <= prev_subtitle->pts) + if (!ist->fix_sub_duration || !prev_subtitle || + !prev_subtitle->num_rects || signal_pts <= prev_subtitle->pts) return 0; - if ((ret = copy_av_subtitle(&subtitle, prev_subtitle)) < 0) + av_frame_unref(d->sub_heartbeat); + ret = subtitle_wrap_frame(d->sub_heartbeat, prev_subtitle, 1); + if (ret < 0) return ret; - subtitle.pts = signal_pts; + subtitle = (AVSubtitle*)d->sub_heartbeat->buf[0]->data; + subtitle->pts = signal_pts; - return process_subtitle(ist, &subtitle); + return process_subtitle(ist, d->sub_heartbeat); } static int transcode_subtitles(InputStream *ist, const AVPacket *pkt, @@ -781,8 +793,7 @@ int dec_packet(InputStream *ist, const AVPacket *pkt, int no_eof) // process the decoded frame if (ist->dec->type == AVMEDIA_TYPE_SUBTITLE) { - AVSubtitle *sub = (AVSubtitle*)d->frame->buf[0]->data; - ret = process_subtitle(ist, sub); + ret = process_subtitle(ist, d->frame); } else { ret = send_frame_to_filters(ist, d->frame); } @@ -1043,6 +1054,7 @@ static int hw_device_setup_for_decode(InputStream *ist) int dec_open(InputStream *ist) { + Decoder *d; const AVCodec *codec = ist->dec; int ret; @@ -1056,6 +1068,18 @@ int dec_open(InputStream *ist) ret = dec_alloc(&ist->decoder); if (ret < 0) return ret; + d = ist->decoder; + + if (codec->type == AVMEDIA_TYPE_SUBTITLE && ist->fix_sub_duration) { + for (int i = 0; i < FF_ARRAY_ELEMS(d->sub_prev); i++) { + d->sub_prev[i] = av_frame_alloc(); + if (!d->sub_prev[i]) + return AVERROR(ENOMEM); + } + d->sub_heartbeat = av_frame_alloc(); + if (!d->sub_heartbeat) + return AVERROR(ENOMEM); + } ist->dec_ctx->opaque = ist; ist->dec_ctx->get_format = get_format; diff --git a/fftools/ffmpeg_filter.c b/fftools/ffmpeg_filter.c index 9e6883ccdd9..acc8596836c 100644 --- a/fftools/ffmpeg_filter.c +++ b/fftools/ffmpeg_filter.c @@ -118,9 +118,6 @@ typedef struct InputFilterPriv { } fallback; struct { - ///< queue of AVSubtitle* before filter init - AVFifo *queue; - AVFrame *frame; int64_t last_pts; @@ -749,12 +746,6 @@ void fg_free(FilterGraph **pfg) av_frame_free(&frame); av_fifo_freep2(&ifp->frame_queue); } - if (ifp->sub2video.queue) { - AVSubtitle sub; - while (av_fifo_read(ifp->sub2video.queue, &sub, 1) >= 0) - avsubtitle_free(&sub); - av_fifo_freep2(&ifp->sub2video.queue); - } av_frame_free(&ifp->sub2video.frame); av_channel_layout_uninit(&ifp->fallback.ch_layout); @@ -1593,7 +1584,11 @@ static int configure_filtergraph(FilterGraph *fg) InputFilterPriv *ifp = ifp_from_ifilter(fg->inputs[i]); AVFrame *tmp; while (av_fifo_read(ifp->frame_queue, &tmp, 1) >= 0) { - ret = av_buffersrc_add_frame(ifp->filter, tmp); + if (ifp->type_src == AVMEDIA_TYPE_SUBTITLE) { + sub2video_update(ifp, INT64_MIN, (const AVSubtitle*)tmp->buf[0]->data); + } else { + ret = av_buffersrc_add_frame(ifp->filter, tmp); + } av_frame_free(&tmp); if (ret < 0) goto fail; @@ -1610,20 +1605,6 @@ static int configure_filtergraph(FilterGraph *fg) } } - /* process queued up subtitle packets */ - for (i = 0; i < fg->nb_inputs; i++) { - InputFilter *ifilter = fg->inputs[i]; - InputFilterPriv *ifp = ifp_from_ifilter(ifilter); - - if (ifp->type_src == AVMEDIA_TYPE_SUBTITLE && ifp->sub2video.queue) { - AVSubtitle tmp; - while (av_fifo_read(ifp->sub2video.queue, &tmp, 1) >= 0) { - sub2video_update(ifp, INT64_MIN, &tmp); - avsubtitle_free(&tmp); - } - } - } - return 0; fail: @@ -1797,35 +1778,29 @@ void ifilter_sub2video_heartbeat(InputFilter *ifilter, int64_t pts, AVRational t sub2video_push_ref(ifp, pts2); } -int ifilter_sub2video(InputFilter *ifilter, const AVSubtitle *subtitle) +int ifilter_sub2video(InputFilter *ifilter, const AVFrame *frame) { InputFilterPriv *ifp = ifp_from_ifilter(ifilter); int ret; if (ifilter->graph->graph) { - if (!subtitle) { + if (!frame) { if (ifp->sub2video.end_pts < INT64_MAX) sub2video_update(ifp, INT64_MAX, NULL); return av_buffersrc_add_frame(ifp->filter, NULL); } - sub2video_update(ifp, INT64_MIN, subtitle); - } else if (subtitle) { - AVSubtitle sub; + sub2video_update(ifp, INT64_MIN, (const AVSubtitle*)frame->buf[0]->data); + } else if (frame) { + AVFrame *tmp = av_frame_clone(frame); - if (!ifp->sub2video.queue) - ifp->sub2video.queue = av_fifo_alloc2(8, sizeof(AVSubtitle), AV_FIFO_FLAG_AUTO_GROW); - if (!ifp->sub2video.queue) + if (!tmp) return AVERROR(ENOMEM); - ret = copy_av_subtitle(&sub, subtitle); - if (ret < 0) - return ret; - - ret = av_fifo_write(ifp->sub2video.queue, &sub, 1); + ret = av_fifo_write(ifp->frame_queue, &tmp, 1); if (ret < 0) { - avsubtitle_free(&sub); + av_frame_free(&tmp); return ret; } } From 1617d1a752d5e97d5e74f6c384609c027c884553 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Wed, 14 Jun 2023 18:34:57 +0200 Subject: [PATCH 1559/2172] fftools/ffmpeg: pass subtitle decoder dimensions to sub2video Restores behavior from before 20cacfe4936a8d5b643421b5ca93bb098f6b76dd. Eventually this should be handled similarly to audio/video - with a filtergraph reset or a manual scaler. --- fftools/ffmpeg_dec.c | 3 +++ fftools/ffmpeg_filter.c | 3 +++ 2 files changed, 6 insertions(+) diff --git a/fftools/ffmpeg_dec.c b/fftools/ffmpeg_dec.c index 3722a87bc58..85bf8dc5367 100644 --- a/fftools/ffmpeg_dec.c +++ b/fftools/ffmpeg_dec.c @@ -509,6 +509,9 @@ static int transcode_subtitles(InputStream *ist, const AVPacket *pkt, return ret; } + frame->width = ist->dec_ctx->width; + frame->height = ist->dec_ctx->height; + ret = tq_send(d->queue_out, 0, frame); if (ret < 0) av_frame_unref(frame); diff --git a/fftools/ffmpeg_filter.c b/fftools/ffmpeg_filter.c index acc8596836c..60e09866afb 100644 --- a/fftools/ffmpeg_filter.c +++ b/fftools/ffmpeg_filter.c @@ -1791,6 +1791,9 @@ int ifilter_sub2video(InputFilter *ifilter, const AVFrame *frame) return av_buffersrc_add_frame(ifp->filter, NULL); } + ifp->width = frame->width ? frame->width : ifp->width; + ifp->height = frame->height ? frame->height : ifp->height; + sub2video_update(ifp, INT64_MIN, (const AVSubtitle*)frame->buf[0]->data); } else if (frame) { AVFrame *tmp = av_frame_clone(frame); From 96fc1927330b03a7674f9376f19565609678f48a Mon Sep 17 00:00:00 2001 From: James Almer Date: Thu, 15 Jun 2023 21:54:21 -0300 Subject: [PATCH 1560/2172] avcodec/evc_frame_merge: use av_fast_realloc() Signed-off-by: James Almer --- libavcodec/evc_frame_merge_bsf.c | 24 ++++++++---------------- 1 file changed, 8 insertions(+), 16 deletions(-) diff --git a/libavcodec/evc_frame_merge_bsf.c b/libavcodec/evc_frame_merge_bsf.c index 7cc701f5c55..827f114f0bd 100644 --- a/libavcodec/evc_frame_merge_bsf.c +++ b/libavcodec/evc_frame_merge_bsf.c @@ -26,13 +26,11 @@ #include "evc.h" #include "evc_parse.h" -#define INIT_AU_BUF_CAPACITY 1024 - // Access unit data typedef struct AccessUnitBuffer { uint8_t *data; // the data buffer size_t data_size; // size of data in bytes - size_t capacity; // buffer capacity + unsigned capacity; // buffer capacity } AccessUnitBuffer; typedef struct EVCFMergeContext { @@ -72,9 +70,8 @@ static int evc_frame_merge_filter(AVBSFContext *bsf, AVPacket *out) AVPacket *in = ctx->in; - int free_space = 0; size_t nalu_size = 0; - uint8_t *nalu = NULL; + uint8_t *buffer, *nalu = NULL; int au_end_found = 0; int err; @@ -102,15 +99,14 @@ static int evc_frame_merge_filter(AVBSFContext *bsf, AVPacket *out) au_end_found = end_of_access_unit_found(parser_ctx); - free_space = ctx->au_buffer.capacity - ctx->au_buffer.data_size; - while (free_space < in->size) { - ctx->au_buffer.capacity *= 2; - free_space = ctx->au_buffer.capacity - ctx->au_buffer.data_size; - - if (free_space >= in->size) - ctx->au_buffer.data = av_realloc(ctx->au_buffer.data, ctx->au_buffer.capacity); + buffer = av_fast_realloc(ctx->au_buffer.data, &ctx->au_buffer.capacity, + ctx->au_buffer.data_size + in->size); + if (!buffer) { + av_freep(&ctx->au_buffer.data); + return AVERROR(ENOMEM); } + ctx->au_buffer.data = buffer; memcpy(ctx->au_buffer.data + ctx->au_buffer.data_size, in->data, in->size); ctx->au_buffer.data_size += in->size; @@ -143,10 +139,6 @@ static int evc_frame_merge_init(AVBSFContext *bsf) if (!ctx->in) return AVERROR(ENOMEM); - ctx->au_buffer.capacity = INIT_AU_BUF_CAPACITY; - ctx->au_buffer.data = av_malloc(INIT_AU_BUF_CAPACITY); - ctx->au_buffer.data_size = 0; - return 0; } From 8ab706677c8198fcd3e49cb4aa311d1e47709e02 Mon Sep 17 00:00:00 2001 From: James Almer Date: Fri, 16 Jun 2023 09:57:25 -0300 Subject: [PATCH 1561/2172] avcodec/evc_frame_merge_bsf: use av_new_packet() This ensures the buffer is padded as required by the AVPacket API. Signed-off-by: James Almer --- libavcodec/evc_frame_merge_bsf.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/libavcodec/evc_frame_merge_bsf.c b/libavcodec/evc_frame_merge_bsf.c index 827f114f0bd..540bb636315 100644 --- a/libavcodec/evc_frame_merge_bsf.c +++ b/libavcodec/evc_frame_merge_bsf.c @@ -114,14 +114,14 @@ static int evc_frame_merge_filter(AVBSFContext *bsf, AVPacket *out) av_packet_unref(in); if (au_end_found) { - uint8_t *data = av_memdup(ctx->au_buffer.data, ctx->au_buffer.data_size); size_t data_size = ctx->au_buffer.data_size; ctx->au_buffer.data_size = 0; - if (!data) - return AVERROR(ENOMEM); + err = av_new_packet(out, data_size); + if (err < 0) + return err; - err = av_packet_from_data(out, data, data_size); + memcpy(out->data, ctx->au_buffer.data, data_size); } else err = AVERROR(EAGAIN); From 4afee83d359b47949f037ef63183847041ad5e3c Mon Sep 17 00:00:00 2001 From: James Almer Date: Sat, 17 Jun 2023 10:22:49 -0300 Subject: [PATCH 1562/2172] fate/lavf-container: add a test to remux raw evc into mp4 Signed-off-by: James Almer --- tests/fate/lavf-container.mak | 2 ++ tests/ref/lavf-fate/evc.mp4 | 3 +++ 2 files changed, 5 insertions(+) create mode 100644 tests/ref/lavf-fate/evc.mp4 diff --git a/tests/fate/lavf-container.mak b/tests/fate/lavf-container.mak index 93740475b49..0d4a2246014 100644 --- a/tests/fate/lavf-container.mak +++ b/tests/fate/lavf-container.mak @@ -71,6 +71,7 @@ FATE_AVCONV += $(FATE_LAVF_CONTAINER) fate-lavf-container fate-lavf: $(FATE_LAVF_CONTAINER) FATE_LAVF_CONTAINER_FATE-$(call ALLYES, IVF_DEMUXER AV1_PARSER MOV_MUXER) += av1.mp4 +FATE_LAVF_CONTAINER_FATE-$(call ALLYES, EVC_DEMUXER EVC_PARSER MOV_MUXER) += evc.mp4 FATE_LAVF_CONTAINER_FATE-$(call ALLYES, IVF_DEMUXER AV1_PARSER MATROSKA_MUXER) += av1.mkv FATE_LAVF_CONTAINER_FATE-$(call ALLYES, H264_DEMUXER H264_PARSER MOV_MUXER) += h264.mp4 FATE_LAVF_CONTAINER_FATE-$(call ALLYES, MATROSKA_DEMUXER OGG_MUXER) += vp3.ogg @@ -87,6 +88,7 @@ $(FATE_LAVF_CONTAINER_FATE): $(AREF) $(VREF) fate-lavf-fate-av1.mp4: CMD = lavf_container_fate "av1-test-vectors/av1-1-b8-05-mv.ivf" "" "-c:v copy" fate-lavf-fate-av1.mkv: CMD = lavf_container_fate "av1-test-vectors/av1-1-b8-05-mv.ivf" "" "-c:v copy" +fate-lavf-fate-evc.mp4: CMD = lavf_container_fate "evc/akiyo_cif.evc" "" "-c:v copy" fate-lavf-fate-h264.mp4: CMD = lavf_container_fate "h264/intra_refresh.h264" "" "-c:v copy" fate-lavf-fate-vp3.ogg: CMD = lavf_container_fate "vp3/coeff_level64.mkv" "-idct auto" fate-lavf-fate-vp8.ogg: CMD = lavf_container_fate "vp8/RRSF49-short.webm" "" "-acodec copy" diff --git a/tests/ref/lavf-fate/evc.mp4 b/tests/ref/lavf-fate/evc.mp4 new file mode 100644 index 00000000000..b0afa350aca --- /dev/null +++ b/tests/ref/lavf-fate/evc.mp4 @@ -0,0 +1,3 @@ +55294f868fa3b31d34a48344c4f72630 *tests/data/lavf-fate/lavf.evc.mp4 +37386 tests/data/lavf-fate/lavf.evc.mp4 +tests/data/lavf-fate/lavf.evc.mp4 CRC=0x48063f85 From 1e189fed7aba09e7b2198fd5460331ea9501d248 Mon Sep 17 00:00:00 2001 From: James Almer Date: Sat, 17 Jun 2023 12:37:15 -0300 Subject: [PATCH 1563/2172] avcodec/evc_parse: split off Parameter Set parsing into its own file Signed-off-by: James Almer --- libavcodec/Makefile | 2 +- libavcodec/evc_frame_merge_bsf.c | 4 +- libavcodec/evc_parse.c | 371 +----------------------------- libavcodec/evc_parse.h | 198 +--------------- libavcodec/evc_parser.c | 2 +- libavcodec/evc_ps.c | 381 +++++++++++++++++++++++++++++++ libavcodec/evc_ps.h | 228 ++++++++++++++++++ 7 files changed, 621 insertions(+), 565 deletions(-) create mode 100644 libavcodec/evc_ps.c create mode 100644 libavcodec/evc_ps.h diff --git a/libavcodec/Makefile b/libavcodec/Makefile index 0ce8fe5b9ca..723bfa25c78 100644 --- a/libavcodec/Makefile +++ b/libavcodec/Makefile @@ -84,7 +84,7 @@ OBJS-$(CONFIG_DCT) += dct.o dct32_fixed.o dct32_float.o OBJS-$(CONFIG_DEFLATE_WRAPPER) += zlib_wrapper.o OBJS-$(CONFIG_DOVI_RPU) += dovi_rpu.o OBJS-$(CONFIG_ERROR_RESILIENCE) += error_resilience.o -OBJS-$(CONFIG_EVCPARSE) += evc_parse.o +OBJS-$(CONFIG_EVCPARSE) += evc_parse.o evc_ps.o OBJS-$(CONFIG_EXIF) += exif.o tiff_common.o OBJS-$(CONFIG_FAANDCT) += faandct.o OBJS-$(CONFIG_FAANIDCT) += faanidct.o diff --git a/libavcodec/evc_frame_merge_bsf.c b/libavcodec/evc_frame_merge_bsf.c index 540bb636315..f497780afbe 100644 --- a/libavcodec/evc_frame_merge_bsf.c +++ b/libavcodec/evc_frame_merge_bsf.c @@ -58,7 +58,7 @@ static void evc_frame_merge_flush(AVBSFContext *bsf) { EVCFMergeContext *ctx = bsf->priv_data; - ff_evc_parse_free(&ctx->parser_ctx); + ff_evc_ps_free(&ctx->parser_ctx.ps); av_packet_unref(ctx->in); ctx->au_buffer.data_size = 0; } @@ -147,7 +147,7 @@ static void evc_frame_merge_close(AVBSFContext *bsf) EVCFMergeContext *ctx = bsf->priv_data; av_packet_free(&ctx->in); - ff_evc_parse_free(&ctx->parser_ctx); + ff_evc_ps_free(&ctx->parser_ctx.ps); ctx->au_buffer.capacity = 0; av_freep(&ctx->au_buffer.data); diff --git a/libavcodec/evc_parse.c b/libavcodec/evc_parse.c index 44be5c52919..a8e6356b96c 100644 --- a/libavcodec/evc_parse.c +++ b/libavcodec/evc_parse.c @@ -21,8 +21,6 @@ #include "evc.h" #include "evc_parse.h" -#define EXTENDED_SAR 255 - #define NUM_CHROMA_FORMATS 4 // @see ISO_IEC_23094-1 section 6.2 table 2 static const enum AVPixelFormat pix_fmts_8bit[NUM_CHROMA_FORMATS] = { @@ -71,355 +69,6 @@ int ff_evc_get_temporal_id(const uint8_t *bits, int bits_size, void *logctx) return temporal_id; } -// @see ISO_IEC_23094-1 (7.3.7 Reference picture list structure syntax) -static int ref_pic_list_struct(GetBitContext *gb, RefPicListStruct *rpl) -{ - uint32_t delta_poc_st, strp_entry_sign_flag = 0; - rpl->ref_pic_num = get_ue_golomb(gb); - if (rpl->ref_pic_num > 0) { - delta_poc_st = get_ue_golomb(gb); - - rpl->ref_pics[0] = delta_poc_st; - if (rpl->ref_pics[0] != 0) { - strp_entry_sign_flag = get_bits(gb, 1); - - rpl->ref_pics[0] *= 1 - (strp_entry_sign_flag << 1); - } - } - - for (int i = 1; i < rpl->ref_pic_num; ++i) { - delta_poc_st = get_ue_golomb(gb); - if (delta_poc_st != 0) - strp_entry_sign_flag = get_bits(gb, 1); - rpl->ref_pics[i] = rpl->ref_pics[i - 1] + delta_poc_st * (1 - (strp_entry_sign_flag << 1)); - } - - return 0; -} - -// @see ISO_IEC_23094-1 (E.2.2 HRD parameters syntax) -static int hrd_parameters(GetBitContext *gb, HRDParameters *hrd) -{ - hrd->cpb_cnt_minus1 = get_ue_golomb(gb); - hrd->bit_rate_scale = get_bits(gb, 4); - hrd->cpb_size_scale = get_bits(gb, 4); - for (int SchedSelIdx = 0; SchedSelIdx <= hrd->cpb_cnt_minus1; SchedSelIdx++) { - hrd->bit_rate_value_minus1[SchedSelIdx] = get_ue_golomb(gb); - hrd->cpb_size_value_minus1[SchedSelIdx] = get_ue_golomb(gb); - hrd->cbr_flag[SchedSelIdx] = get_bits(gb, 1); - } - hrd->initial_cpb_removal_delay_length_minus1 = get_bits(gb, 5); - hrd->cpb_removal_delay_length_minus1 = get_bits(gb, 5); - hrd->cpb_removal_delay_length_minus1 = get_bits(gb, 5); - hrd->time_offset_length = get_bits(gb, 5); - - return 0; -} - -// @see ISO_IEC_23094-1 (E.2.1 VUI parameters syntax) -static int vui_parameters(GetBitContext *gb, VUIParameters *vui) -{ - vui->aspect_ratio_info_present_flag = get_bits(gb, 1); - if (vui->aspect_ratio_info_present_flag) { - vui->aspect_ratio_idc = get_bits(gb, 8); - if (vui->aspect_ratio_idc == EXTENDED_SAR) { - vui->sar_width = get_bits(gb, 16); - vui->sar_height = get_bits(gb, 16); - } - } - vui->overscan_info_present_flag = get_bits(gb, 1); - if (vui->overscan_info_present_flag) - vui->overscan_appropriate_flag = get_bits(gb, 1); - vui->video_signal_type_present_flag = get_bits(gb, 1); - if (vui->video_signal_type_present_flag) { - vui->video_format = get_bits(gb, 3); - vui->video_full_range_flag = get_bits(gb, 1); - vui->colour_description_present_flag = get_bits(gb, 1); - if (vui->colour_description_present_flag) { - vui->colour_primaries = get_bits(gb, 8); - vui->transfer_characteristics = get_bits(gb, 8); - vui->matrix_coefficients = get_bits(gb, 8); - } - } - vui->chroma_loc_info_present_flag = get_bits(gb, 1); - if (vui->chroma_loc_info_present_flag) { - vui->chroma_sample_loc_type_top_field = get_ue_golomb(gb); - vui->chroma_sample_loc_type_bottom_field = get_ue_golomb(gb); - } - vui->neutral_chroma_indication_flag = get_bits(gb, 1); - - vui->field_seq_flag = get_bits(gb, 1); - - vui->timing_info_present_flag = get_bits(gb, 1); - if (vui->timing_info_present_flag) { - vui->num_units_in_tick = get_bits(gb, 32); - vui->time_scale = get_bits(gb, 32); - vui->fixed_pic_rate_flag = get_bits(gb, 1); - } - vui->nal_hrd_parameters_present_flag = get_bits(gb, 1); - if (vui->nal_hrd_parameters_present_flag) - hrd_parameters(gb, &vui->hrd_parameters); - vui->vcl_hrd_parameters_present_flag = get_bits(gb, 1); - if (vui->vcl_hrd_parameters_present_flag) - hrd_parameters(gb, &vui->hrd_parameters); - if (vui->nal_hrd_parameters_present_flag || vui->vcl_hrd_parameters_present_flag) - vui->low_delay_hrd_flag = get_bits(gb, 1); - vui->pic_struct_present_flag = get_bits(gb, 1); - vui->bitstream_restriction_flag = get_bits(gb, 1); - if (vui->bitstream_restriction_flag) { - vui->motion_vectors_over_pic_boundaries_flag = get_bits(gb, 1); - vui->max_bytes_per_pic_denom = get_ue_golomb(gb); - vui->max_bits_per_mb_denom = get_ue_golomb(gb); - vui->log2_max_mv_length_horizontal = get_ue_golomb(gb); - vui->log2_max_mv_length_vertical = get_ue_golomb(gb); - vui->num_reorder_pics = get_ue_golomb(gb); - vui->max_dec_pic_buffering = get_ue_golomb(gb); - } - - return 0; -} - -// @see ISO_IEC_23094-1 (7.3.2.1 SPS RBSP syntax) -EVCParserSPS *ff_evc_parse_sps(EVCParserContext *ctx, const uint8_t *bs, int bs_size) -{ - GetBitContext gb; - EVCParserSPS *sps; - int sps_seq_parameter_set_id; - - if (init_get_bits8(&gb, bs, bs_size) < 0) - return NULL; - - sps_seq_parameter_set_id = get_ue_golomb(&gb); - - if (sps_seq_parameter_set_id >= EVC_MAX_SPS_COUNT) - return NULL; - - if(!ctx->sps[sps_seq_parameter_set_id]) { - if((ctx->sps[sps_seq_parameter_set_id] = av_malloc(sizeof(EVCParserSPS))) == NULL) - return NULL; - } - - sps = ctx->sps[sps_seq_parameter_set_id]; - memset(sps, 0, sizeof(*sps)); - - sps->sps_seq_parameter_set_id = sps_seq_parameter_set_id; - - // the Baseline profile is indicated by profile_idc eqal to 0 - // the Main profile is indicated by profile_idc eqal to 1 - sps->profile_idc = get_bits(&gb, 8); - - sps->level_idc = get_bits(&gb, 8); - - skip_bits_long(&gb, 32); /* skip toolset_idc_h */ - skip_bits_long(&gb, 32); /* skip toolset_idc_l */ - - // 0 - monochrome - // 1 - 4:2:0 - // 2 - 4:2:2 - // 3 - 4:4:4 - sps->chroma_format_idc = get_ue_golomb(&gb); - - sps->pic_width_in_luma_samples = get_ue_golomb(&gb); - sps->pic_height_in_luma_samples = get_ue_golomb(&gb); - - sps->bit_depth_luma_minus8 = get_ue_golomb(&gb); - sps->bit_depth_chroma_minus8 = get_ue_golomb(&gb); - - sps->sps_btt_flag = get_bits(&gb, 1); - if (sps->sps_btt_flag) { - sps->log2_ctu_size_minus5 = get_ue_golomb(&gb); - sps->log2_min_cb_size_minus2 = get_ue_golomb(&gb); - sps->log2_diff_ctu_max_14_cb_size = get_ue_golomb(&gb); - sps->log2_diff_ctu_max_tt_cb_size = get_ue_golomb(&gb); - sps->log2_diff_min_cb_min_tt_cb_size_minus2 = get_ue_golomb(&gb); - } - - sps->sps_suco_flag = get_bits(&gb, 1); - if (sps->sps_suco_flag) { - sps->log2_diff_ctu_size_max_suco_cb_size = get_ue_golomb(&gb); - sps->log2_diff_max_suco_min_suco_cb_size = get_ue_golomb(&gb); - } - - sps->sps_admvp_flag = get_bits(&gb, 1); - if (sps->sps_admvp_flag) { - sps->sps_affine_flag = get_bits(&gb, 1); - sps->sps_amvr_flag = get_bits(&gb, 1); - sps->sps_dmvr_flag = get_bits(&gb, 1); - sps->sps_mmvd_flag = get_bits(&gb, 1); - sps->sps_hmvp_flag = get_bits(&gb, 1); - } - - sps->sps_eipd_flag = get_bits(&gb, 1); - if (sps->sps_eipd_flag) { - sps->sps_ibc_flag = get_bits(&gb, 1); - if (sps->sps_ibc_flag) - sps->log2_max_ibc_cand_size_minus2 = get_ue_golomb(&gb); - } - - sps->sps_cm_init_flag = get_bits(&gb, 1); - if (sps->sps_cm_init_flag) - sps->sps_adcc_flag = get_bits(&gb, 1); - - sps->sps_iqt_flag = get_bits(&gb, 1); - if (sps->sps_iqt_flag) - sps->sps_ats_flag = get_bits(&gb, 1); - - sps->sps_addb_flag = get_bits(&gb, 1); - sps->sps_alf_flag = get_bits(&gb, 1); - sps->sps_htdf_flag = get_bits(&gb, 1); - sps->sps_rpl_flag = get_bits(&gb, 1); - sps->sps_pocs_flag = get_bits(&gb, 1); - sps->sps_dquant_flag = get_bits(&gb, 1); - sps->sps_dra_flag = get_bits(&gb, 1); - - if (sps->sps_pocs_flag) - sps->log2_max_pic_order_cnt_lsb_minus4 = get_ue_golomb(&gb); - - if (!sps->sps_pocs_flag || !sps->sps_rpl_flag) { - sps->log2_sub_gop_length = get_ue_golomb(&gb); - if (sps->log2_sub_gop_length == 0) - sps->log2_ref_pic_gap_length = get_ue_golomb(&gb); - } - - if (!sps->sps_rpl_flag) - sps->max_num_tid0_ref_pics = get_ue_golomb(&gb); - else { - sps->sps_max_dec_pic_buffering_minus1 = get_ue_golomb(&gb); - sps->long_term_ref_pic_flag = get_bits(&gb, 1); - sps->rpl1_same_as_rpl0_flag = get_bits(&gb, 1); - sps->num_ref_pic_list_in_sps[0] = get_ue_golomb(&gb); - - for (int i = 0; i < sps->num_ref_pic_list_in_sps[0]; ++i) - ref_pic_list_struct(&gb, &sps->rpls[0][i]); - - if (!sps->rpl1_same_as_rpl0_flag) { - sps->num_ref_pic_list_in_sps[1] = get_ue_golomb(&gb); - for (int i = 0; i < sps->num_ref_pic_list_in_sps[1]; ++i) - ref_pic_list_struct(&gb, &sps->rpls[1][i]); - } - } - - sps->picture_cropping_flag = get_bits(&gb, 1); - - if (sps->picture_cropping_flag) { - sps->picture_crop_left_offset = get_ue_golomb(&gb); - sps->picture_crop_right_offset = get_ue_golomb(&gb); - sps->picture_crop_top_offset = get_ue_golomb(&gb); - sps->picture_crop_bottom_offset = get_ue_golomb(&gb); - } - - if (sps->chroma_format_idc != 0) { - sps->chroma_qp_table_struct.chroma_qp_table_present_flag = get_bits(&gb, 1); - - if (sps->chroma_qp_table_struct.chroma_qp_table_present_flag) { - sps->chroma_qp_table_struct.same_qp_table_for_chroma = get_bits(&gb, 1); - sps->chroma_qp_table_struct.global_offset_flag = get_bits(&gb, 1); - for (int i = 0; i < (sps->chroma_qp_table_struct.same_qp_table_for_chroma ? 1 : 2); i++) { - sps->chroma_qp_table_struct.num_points_in_qp_table_minus1[i] = get_ue_golomb(&gb);; - for (int j = 0; j <= sps->chroma_qp_table_struct.num_points_in_qp_table_minus1[i]; j++) { - sps->chroma_qp_table_struct.delta_qp_in_val_minus1[i][j] = get_bits(&gb, 6); - sps->chroma_qp_table_struct.delta_qp_out_val[i][j] = get_se_golomb(&gb); - } - } - } - } - - sps->vui_parameters_present_flag = get_bits(&gb, 1); - if (sps->vui_parameters_present_flag) - vui_parameters(&gb, &(sps->vui_parameters)); - - // @note - // If necessary, add the missing fields to the EVCParserSPS structure - // and then extend parser implementation - - return sps; -} - -// @see ISO_IEC_23094-1 (7.3.2.2 SPS RBSP syntax) -// -// @note -// The current implementation of parse_sps function doesn't handle VUI parameters parsing. -// If it will be needed, parse_sps function could be extended to handle VUI parameters parsing -// to initialize fields of the AVCodecContex i.e. color_primaries, color_trc,color_range -// -EVCParserPPS *ff_evc_parse_pps(EVCParserContext *ctx, const uint8_t *bs, int bs_size) -{ - GetBitContext gb; - EVCParserPPS *pps; - - int pps_pic_parameter_set_id; - - if (init_get_bits8(&gb, bs, bs_size) < 0) - return NULL; - - pps_pic_parameter_set_id = get_ue_golomb(&gb); - if (pps_pic_parameter_set_id > EVC_MAX_PPS_COUNT) - return NULL; - - if(!ctx->pps[pps_pic_parameter_set_id]) { - if ((ctx->pps[pps_pic_parameter_set_id] = av_malloc(sizeof(EVCParserPPS))) == NULL) - return NULL; - } - - pps = ctx->pps[pps_pic_parameter_set_id]; - memset(pps, 0, sizeof(*pps)); - - pps->pps_pic_parameter_set_id = pps_pic_parameter_set_id; - - pps->pps_seq_parameter_set_id = get_ue_golomb(&gb); - if (pps->pps_seq_parameter_set_id >= EVC_MAX_SPS_COUNT) { - av_freep(&ctx->pps[pps_pic_parameter_set_id]); - return NULL; - } - - pps->num_ref_idx_default_active_minus1[0] = get_ue_golomb(&gb); - pps->num_ref_idx_default_active_minus1[1] = get_ue_golomb(&gb); - pps->additional_lt_poc_lsb_len = get_ue_golomb(&gb); - pps->rpl1_idx_present_flag = get_bits(&gb, 1); - pps->single_tile_in_pic_flag = get_bits(&gb, 1); - - if (!pps->single_tile_in_pic_flag) { - pps->num_tile_columns_minus1 = get_ue_golomb(&gb); - pps->num_tile_rows_minus1 = get_ue_golomb(&gb); - pps->uniform_tile_spacing_flag = get_bits(&gb, 1); - - if (!pps->uniform_tile_spacing_flag) { - for (int i = 0; i < pps->num_tile_columns_minus1; i++) - pps->tile_column_width_minus1[i] = get_ue_golomb(&gb); - - for (int i = 0; i < pps->num_tile_rows_minus1; i++) - pps->tile_row_height_minus1[i] = get_ue_golomb(&gb); - } - pps->loop_filter_across_tiles_enabled_flag = get_bits(&gb, 1); - pps->tile_offset_len_minus1 = get_ue_golomb(&gb); - } - - pps->tile_id_len_minus1 = get_ue_golomb(&gb); - pps->explicit_tile_id_flag = get_bits(&gb, 1); - - if (pps->explicit_tile_id_flag) { - for (int i = 0; i <= pps->num_tile_rows_minus1; i++) { - for (int j = 0; j <= pps->num_tile_columns_minus1; j++) - pps->tile_id_val[i][j] = get_bits(&gb, pps->tile_id_len_minus1 + 1); - } - } - - pps->pic_dra_enabled_flag = 0; - pps->pic_dra_enabled_flag = get_bits(&gb, 1); - - if (pps->pic_dra_enabled_flag) - pps->pic_dra_aps_id = get_bits(&gb, 5); - - pps->arbitrary_slice_present_flag = get_bits(&gb, 1); - pps->constrained_intra_pred_flag = get_bits(&gb, 1); - pps->cu_qp_delta_enabled_flag = get_bits(&gb, 1); - - if (pps->cu_qp_delta_enabled_flag) - pps->log2_cu_qp_delta_area_minus6 = get_ue_golomb(&gb); - - return pps; -} - // @see ISO_IEC_23094-1 (7.3.2.6 Slice layer RBSP syntax) static int evc_parse_slice_header(EVCParserContext *ctx, EVCParserSliceHeader *sh, const uint8_t *bs, int bs_size) { @@ -439,11 +88,11 @@ static int evc_parse_slice_header(EVCParserContext *ctx, EVCParserSliceHeader *s if (slice_pic_parameter_set_id < 0 || slice_pic_parameter_set_id >= EVC_MAX_PPS_COUNT) return AVERROR_INVALIDDATA; - pps = ctx->pps[slice_pic_parameter_set_id]; + pps = ctx->ps.pps[slice_pic_parameter_set_id]; if(!pps) return AVERROR_INVALIDDATA; - sps = ctx->sps[pps->pps_seq_parameter_set_id]; + sps = ctx->ps.sps[pps->pps_seq_parameter_set_id]; if(!sps) return AVERROR_INVALIDDATA; @@ -579,7 +228,7 @@ int ff_evc_parse_nal_unit(EVCParserContext *ctx, const uint8_t *buf, int buf_siz int SubGopLength; int bit_depth; - sps = ff_evc_parse_sps(ctx, data, nalu_size); + sps = ff_evc_parse_sps(&ctx->ps, data, nalu_size); if (!sps) { av_log(logctx, AV_LOG_ERROR, "SPS parsing error\n"); return AVERROR_INVALIDDATA; @@ -642,7 +291,7 @@ int ff_evc_parse_nal_unit(EVCParserContext *ctx, const uint8_t *buf, int buf_siz case EVC_PPS_NUT: { EVCParserPPS *pps; - pps = ff_evc_parse_pps(ctx, data, nalu_size); + pps = ff_evc_parse_pps(&ctx->ps, data, nalu_size); if (!pps) { av_log(logctx, AV_LOG_ERROR, "PPS parsing error\n"); return AVERROR_INVALIDDATA; @@ -688,8 +337,8 @@ int ff_evc_parse_nal_unit(EVCParserContext *ctx, const uint8_t *buf, int buf_siz // POC (picture order count of the current picture) derivation // @see ISO/IEC 23094-1:2020(E) 8.3.1 Decoding process for picture order count - pps = ctx->pps[sh.slice_pic_parameter_set_id]; - sps = ctx->sps[pps->pps_seq_parameter_set_id]; + pps = ctx->ps.pps[sh.slice_pic_parameter_set_id]; + sps = ctx->ps.sps[pps->pps_seq_parameter_set_id]; av_assert0(sps && pps); if (sps->sps_pocs_flag) { @@ -764,11 +413,3 @@ int ff_evc_parse_nal_unit(EVCParserContext *ctx, const uint8_t *buf, int buf_siz return 0; } - -void ff_evc_parse_free(EVCParserContext *ctx) { - for (int i = 0; i < EVC_MAX_SPS_COUNT; i++) - av_freep(&ctx->sps[i]); - - for (int i = 0; i < EVC_MAX_PPS_COUNT; i++) - av_freep(&ctx->pps[i]); -} diff --git a/libavcodec/evc_parse.h b/libavcodec/evc_parse.h index ee4b6c57088..b5462f57112 100644 --- a/libavcodec/evc_parse.h +++ b/libavcodec/evc_parse.h @@ -30,190 +30,7 @@ #include "libavutil/log.h" #include "libavutil/rational.h" #include "evc.h" - -#define EVC_MAX_QP_TABLE_SIZE 58 -#define NUM_CPB 32 - -// rpl structure -typedef struct RefPicListStruct { - int poc; - int tid; - int ref_pic_num; - int ref_pic_active_num; - int ref_pics[EVC_MAX_NUM_REF_PICS]; - char pic_type; - -} RefPicListStruct; - -// chromaQP table structure to be signalled in SPS -typedef struct ChromaQpTable { - int chroma_qp_table_present_flag; // u(1) - int same_qp_table_for_chroma; // u(1) - int global_offset_flag; // u(1) - int num_points_in_qp_table_minus1[2]; // ue(v) - int delta_qp_in_val_minus1[2][EVC_MAX_QP_TABLE_SIZE]; // u(6) - int delta_qp_out_val[2][EVC_MAX_QP_TABLE_SIZE]; // se(v) -} ChromaQpTable; - -// Hypothetical Reference Decoder (HRD) parameters, part of VUI -typedef struct HRDParameters { - int cpb_cnt_minus1; // ue(v) - int bit_rate_scale; // u(4) - int cpb_size_scale; // u(4) - int bit_rate_value_minus1[NUM_CPB]; // ue(v) - int cpb_size_value_minus1[NUM_CPB]; // ue(v) - int cbr_flag[NUM_CPB]; // u(1) - int initial_cpb_removal_delay_length_minus1; // u(5) - int cpb_removal_delay_length_minus1; // u(5) - int dpb_output_delay_length_minus1; // u(5) - int time_offset_length; // u(5) -} HRDParameters; - -// video usability information (VUI) part of SPS -typedef struct VUIParameters { - int aspect_ratio_info_present_flag; // u(1) - int aspect_ratio_idc; // u(8) - int sar_width; // u(16) - int sar_height; // u(16) - int overscan_info_present_flag; // u(1) - int overscan_appropriate_flag; // u(1) - int video_signal_type_present_flag; // u(1) - int video_format; // u(3) - int video_full_range_flag; // u(1) - int colour_description_present_flag; // u(1) - int colour_primaries; // u(8) - int transfer_characteristics; // u(8) - int matrix_coefficients; // u(8) - int chroma_loc_info_present_flag; // u(1) - int chroma_sample_loc_type_top_field; // ue(v) - int chroma_sample_loc_type_bottom_field; // ue(v) - int neutral_chroma_indication_flag; // u(1) - int field_seq_flag; // u(1) - int timing_info_present_flag; // u(1) - int num_units_in_tick; // u(32) - int time_scale; // u(32) - int fixed_pic_rate_flag; // u(1) - int nal_hrd_parameters_present_flag; // u(1) - int vcl_hrd_parameters_present_flag; // u(1) - int low_delay_hrd_flag; // u(1) - int pic_struct_present_flag; // u(1) - int bitstream_restriction_flag; // u(1) - int motion_vectors_over_pic_boundaries_flag; // u(1) - int max_bytes_per_pic_denom; // ue(v) - int max_bits_per_mb_denom; // ue(v) - int log2_max_mv_length_horizontal; // ue(v) - int log2_max_mv_length_vertical; // ue(v) - int num_reorder_pics; // ue(v) - int max_dec_pic_buffering; // ue(v) - - HRDParameters hrd_parameters; -} VUIParameters; - -// The sturcture reflects SPS RBSP(raw byte sequence payload) layout -// @see ISO_IEC_23094-1 section 7.3.2.1 -// -// The following descriptors specify the parsing process of each element -// u(n) - unsigned integer using n bits -// ue(v) - unsigned integer 0-th order Exp_Golomb-coded syntax element with the left bit first -typedef struct EVCParserSPS { - int sps_seq_parameter_set_id; // ue(v) - int profile_idc; // u(8) - int level_idc; // u(8) - int toolset_idc_h; // u(32) - int toolset_idc_l; // u(32) - int chroma_format_idc; // ue(v) - int pic_width_in_luma_samples; // ue(v) - int pic_height_in_luma_samples; // ue(v) - int bit_depth_luma_minus8; // ue(v) - int bit_depth_chroma_minus8; // ue(v) - - int sps_btt_flag; // u(1) - int log2_ctu_size_minus5; // ue(v) - int log2_min_cb_size_minus2; // ue(v) - int log2_diff_ctu_max_14_cb_size; // ue(v) - int log2_diff_ctu_max_tt_cb_size; // ue(v) - int log2_diff_min_cb_min_tt_cb_size_minus2; // ue(v) - - int sps_suco_flag; // u(1) - int log2_diff_ctu_size_max_suco_cb_size; // ue(v) - int log2_diff_max_suco_min_suco_cb_size; // ue(v) - - int sps_admvp_flag; // u(1) - int sps_affine_flag; // u(1) - int sps_amvr_flag; // u(1) - int sps_dmvr_flag; // u(1) - int sps_mmvd_flag; // u(1) - int sps_hmvp_flag; // u(1) - - int sps_eipd_flag; // u(1) - int sps_ibc_flag; // u(1) - int log2_max_ibc_cand_size_minus2; // ue(v) - - int sps_cm_init_flag; // u(1) - int sps_adcc_flag; // u(1) - - int sps_iqt_flag; // u(1) - int sps_ats_flag; // u(1) - - int sps_addb_flag; // u(1) - int sps_alf_flag; // u(1) - int sps_htdf_flag; // u(1) - int sps_rpl_flag; // u(1) - int sps_pocs_flag; // u(1) - int sps_dquant_flag; // u(1) - int sps_dra_flag; // u(1) - - int log2_max_pic_order_cnt_lsb_minus4; // ue(v) - int log2_sub_gop_length; // ue(v) - int log2_ref_pic_gap_length; // ue(v) - - int max_num_tid0_ref_pics; // ue(v) - - int sps_max_dec_pic_buffering_minus1; // ue(v) - int long_term_ref_pic_flag; // u(1) - int rpl1_same_as_rpl0_flag; // u(1) - int num_ref_pic_list_in_sps[2]; // ue(v) - struct RefPicListStruct rpls[2][EVC_MAX_NUM_RPLS]; - - int picture_cropping_flag; // u(1) - int picture_crop_left_offset; // ue(v) - int picture_crop_right_offset; // ue(v) - int picture_crop_top_offset; // ue(v) - int picture_crop_bottom_offset; // ue(v) - - struct ChromaQpTable chroma_qp_table_struct; - - int vui_parameters_present_flag; // u(1) - - struct VUIParameters vui_parameters; - -} EVCParserSPS; - -typedef struct EVCParserPPS { - int pps_pic_parameter_set_id; // ue(v) - int pps_seq_parameter_set_id; // ue(v) - int num_ref_idx_default_active_minus1[2]; // ue(v) - int additional_lt_poc_lsb_len; // ue(v) - int rpl1_idx_present_flag; // u(1) - int single_tile_in_pic_flag; // u(1) - int num_tile_columns_minus1; // ue(v) - int num_tile_rows_minus1; // ue(v) - int uniform_tile_spacing_flag; // u(1) - int tile_column_width_minus1[EVC_MAX_TILE_ROWS]; // ue(v) - int tile_row_height_minus1[EVC_MAX_TILE_COLUMNS]; // ue(v) - int loop_filter_across_tiles_enabled_flag; // u(1) - int tile_offset_len_minus1; // ue(v) - int tile_id_len_minus1; // ue(v) - int explicit_tile_id_flag; // u(1) - int tile_id_val[EVC_MAX_TILE_ROWS][EVC_MAX_TILE_COLUMNS]; // u(v) - int pic_dra_enabled_flag; // u(1) - int pic_dra_aps_id; // u(5) - int arbitrary_slice_present_flag; // u(1) - int constrained_intra_pred_flag; // u(1) - int cu_qp_delta_enabled_flag; // u(1) - int log2_cu_qp_delta_area_minus6; // ue(v) - -} EVCParserPPS; +#include "evc_ps.h" // The sturcture reflects Slice Header RBSP(raw byte sequence payload) layout // @see ISO_IEC_23094-1 section 7.3.2.6 @@ -265,10 +82,7 @@ typedef struct EVCParserPoc { } EVCParserPoc; typedef struct EVCParserContext { - //ParseContext pc; - EVCParserSPS *sps[EVC_MAX_SPS_COUNT]; - EVCParserPPS *pps[EVC_MAX_PPS_COUNT]; - + EVCParamSets ps; EVCParserPoc poc; int nuh_temporal_id; // the value of TemporalId (shall be the same for all VCL NAL units of an Access Unit) @@ -349,14 +163,6 @@ static inline uint32_t evc_read_nal_unit_length(const uint8_t *bits, int bits_si // nuh_temporal_id specifies a temporal identifier for the NAL unit int ff_evc_get_temporal_id(const uint8_t *bits, int bits_size, void *logctx); -// @see ISO_IEC_23094-1 (7.3.2.1 SPS RBSP syntax) -EVCParserSPS *ff_evc_parse_sps(EVCParserContext *ctx, const uint8_t *bs, int bs_size); - -// @see ISO_IEC_23094-1 (7.3.2.2 SPS RBSP syntax) -EVCParserPPS *ff_evc_parse_pps(EVCParserContext *ctx, const uint8_t *bs, int bs_size); - int ff_evc_parse_nal_unit(EVCParserContext *ctx, const uint8_t *buf, int buf_size, void *logctx); -void ff_evc_parse_free(EVCParserContext *ctx); - #endif /* AVCODEC_EVC_PARSE_H */ diff --git a/libavcodec/evc_parser.c b/libavcodec/evc_parser.c index c85b8f89e71..1fd8aac1dce 100644 --- a/libavcodec/evc_parser.c +++ b/libavcodec/evc_parser.c @@ -202,7 +202,7 @@ static void evc_parser_close(AVCodecParserContext *s) { EVCParserContext *ctx = s->priv_data; - ff_evc_parse_free(ctx); + ff_evc_ps_free(&ctx->ps); } const AVCodecParser ff_evc_parser = { diff --git a/libavcodec/evc_ps.c b/libavcodec/evc_ps.c new file mode 100644 index 00000000000..af74ba46b0f --- /dev/null +++ b/libavcodec/evc_ps.c @@ -0,0 +1,381 @@ +/* + * 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 "golomb.h" +#include "parser.h" +#include "evc.h" +#include "evc_ps.h" + +#define EXTENDED_SAR 255 + +// @see ISO_IEC_23094-1 (7.3.7 Reference picture list structure syntax) +static int ref_pic_list_struct(GetBitContext *gb, RefPicListStruct *rpl) +{ + uint32_t delta_poc_st, strp_entry_sign_flag = 0; + rpl->ref_pic_num = get_ue_golomb(gb); + if (rpl->ref_pic_num > 0) { + delta_poc_st = get_ue_golomb(gb); + + rpl->ref_pics[0] = delta_poc_st; + if (rpl->ref_pics[0] != 0) { + strp_entry_sign_flag = get_bits(gb, 1); + + rpl->ref_pics[0] *= 1 - (strp_entry_sign_flag << 1); + } + } + + for (int i = 1; i < rpl->ref_pic_num; ++i) { + delta_poc_st = get_ue_golomb(gb); + if (delta_poc_st != 0) + strp_entry_sign_flag = get_bits(gb, 1); + rpl->ref_pics[i] = rpl->ref_pics[i - 1] + delta_poc_st * (1 - (strp_entry_sign_flag << 1)); + } + + return 0; +} + +// @see ISO_IEC_23094-1 (E.2.2 HRD parameters syntax) +static int hrd_parameters(GetBitContext *gb, HRDParameters *hrd) +{ + hrd->cpb_cnt_minus1 = get_ue_golomb(gb); + hrd->bit_rate_scale = get_bits(gb, 4); + hrd->cpb_size_scale = get_bits(gb, 4); + for (int SchedSelIdx = 0; SchedSelIdx <= hrd->cpb_cnt_minus1; SchedSelIdx++) { + hrd->bit_rate_value_minus1[SchedSelIdx] = get_ue_golomb(gb); + hrd->cpb_size_value_minus1[SchedSelIdx] = get_ue_golomb(gb); + hrd->cbr_flag[SchedSelIdx] = get_bits(gb, 1); + } + hrd->initial_cpb_removal_delay_length_minus1 = get_bits(gb, 5); + hrd->cpb_removal_delay_length_minus1 = get_bits(gb, 5); + hrd->cpb_removal_delay_length_minus1 = get_bits(gb, 5); + hrd->time_offset_length = get_bits(gb, 5); + + return 0; +} + +// @see ISO_IEC_23094-1 (E.2.1 VUI parameters syntax) +static int vui_parameters(GetBitContext *gb, VUIParameters *vui) +{ + vui->aspect_ratio_info_present_flag = get_bits(gb, 1); + if (vui->aspect_ratio_info_present_flag) { + vui->aspect_ratio_idc = get_bits(gb, 8); + if (vui->aspect_ratio_idc == EXTENDED_SAR) { + vui->sar_width = get_bits(gb, 16); + vui->sar_height = get_bits(gb, 16); + } + } + vui->overscan_info_present_flag = get_bits(gb, 1); + if (vui->overscan_info_present_flag) + vui->overscan_appropriate_flag = get_bits(gb, 1); + vui->video_signal_type_present_flag = get_bits(gb, 1); + if (vui->video_signal_type_present_flag) { + vui->video_format = get_bits(gb, 3); + vui->video_full_range_flag = get_bits(gb, 1); + vui->colour_description_present_flag = get_bits(gb, 1); + if (vui->colour_description_present_flag) { + vui->colour_primaries = get_bits(gb, 8); + vui->transfer_characteristics = get_bits(gb, 8); + vui->matrix_coefficients = get_bits(gb, 8); + } + } + vui->chroma_loc_info_present_flag = get_bits(gb, 1); + if (vui->chroma_loc_info_present_flag) { + vui->chroma_sample_loc_type_top_field = get_ue_golomb(gb); + vui->chroma_sample_loc_type_bottom_field = get_ue_golomb(gb); + } + vui->neutral_chroma_indication_flag = get_bits(gb, 1); + + vui->field_seq_flag = get_bits(gb, 1); + + vui->timing_info_present_flag = get_bits(gb, 1); + if (vui->timing_info_present_flag) { + vui->num_units_in_tick = get_bits(gb, 32); + vui->time_scale = get_bits(gb, 32); + vui->fixed_pic_rate_flag = get_bits(gb, 1); + } + vui->nal_hrd_parameters_present_flag = get_bits(gb, 1); + if (vui->nal_hrd_parameters_present_flag) + hrd_parameters(gb, &vui->hrd_parameters); + vui->vcl_hrd_parameters_present_flag = get_bits(gb, 1); + if (vui->vcl_hrd_parameters_present_flag) + hrd_parameters(gb, &vui->hrd_parameters); + if (vui->nal_hrd_parameters_present_flag || vui->vcl_hrd_parameters_present_flag) + vui->low_delay_hrd_flag = get_bits(gb, 1); + vui->pic_struct_present_flag = get_bits(gb, 1); + vui->bitstream_restriction_flag = get_bits(gb, 1); + if (vui->bitstream_restriction_flag) { + vui->motion_vectors_over_pic_boundaries_flag = get_bits(gb, 1); + vui->max_bytes_per_pic_denom = get_ue_golomb(gb); + vui->max_bits_per_mb_denom = get_ue_golomb(gb); + vui->log2_max_mv_length_horizontal = get_ue_golomb(gb); + vui->log2_max_mv_length_vertical = get_ue_golomb(gb); + vui->num_reorder_pics = get_ue_golomb(gb); + vui->max_dec_pic_buffering = get_ue_golomb(gb); + } + + return 0; +} + +// @see ISO_IEC_23094-1 (7.3.2.1 SPS RBSP syntax) +EVCParserSPS *ff_evc_parse_sps(EVCParamSets *ps, const uint8_t *bs, int bs_size) +{ + GetBitContext gb; + EVCParserSPS *sps; + int sps_seq_parameter_set_id; + + if (init_get_bits8(&gb, bs, bs_size) < 0) + return NULL; + + sps_seq_parameter_set_id = get_ue_golomb(&gb); + + if (sps_seq_parameter_set_id >= EVC_MAX_SPS_COUNT) + return NULL; + + if(!ps->sps[sps_seq_parameter_set_id]) { + if((ps->sps[sps_seq_parameter_set_id] = av_malloc(sizeof(EVCParserSPS))) == NULL) + return NULL; + } + + sps = ps->sps[sps_seq_parameter_set_id]; + memset(sps, 0, sizeof(*sps)); + + sps->sps_seq_parameter_set_id = sps_seq_parameter_set_id; + + // the Baseline profile is indicated by profile_idc eqal to 0 + // the Main profile is indicated by profile_idc eqal to 1 + sps->profile_idc = get_bits(&gb, 8); + + sps->level_idc = get_bits(&gb, 8); + + skip_bits_long(&gb, 32); /* skip toolset_idc_h */ + skip_bits_long(&gb, 32); /* skip toolset_idc_l */ + + // 0 - monochrome + // 1 - 4:2:0 + // 2 - 4:2:2 + // 3 - 4:4:4 + sps->chroma_format_idc = get_ue_golomb(&gb); + + sps->pic_width_in_luma_samples = get_ue_golomb(&gb); + sps->pic_height_in_luma_samples = get_ue_golomb(&gb); + + sps->bit_depth_luma_minus8 = get_ue_golomb(&gb); + sps->bit_depth_chroma_minus8 = get_ue_golomb(&gb); + + sps->sps_btt_flag = get_bits(&gb, 1); + if (sps->sps_btt_flag) { + sps->log2_ctu_size_minus5 = get_ue_golomb(&gb); + sps->log2_min_cb_size_minus2 = get_ue_golomb(&gb); + sps->log2_diff_ctu_max_14_cb_size = get_ue_golomb(&gb); + sps->log2_diff_ctu_max_tt_cb_size = get_ue_golomb(&gb); + sps->log2_diff_min_cb_min_tt_cb_size_minus2 = get_ue_golomb(&gb); + } + + sps->sps_suco_flag = get_bits(&gb, 1); + if (sps->sps_suco_flag) { + sps->log2_diff_ctu_size_max_suco_cb_size = get_ue_golomb(&gb); + sps->log2_diff_max_suco_min_suco_cb_size = get_ue_golomb(&gb); + } + + sps->sps_admvp_flag = get_bits(&gb, 1); + if (sps->sps_admvp_flag) { + sps->sps_affine_flag = get_bits(&gb, 1); + sps->sps_amvr_flag = get_bits(&gb, 1); + sps->sps_dmvr_flag = get_bits(&gb, 1); + sps->sps_mmvd_flag = get_bits(&gb, 1); + sps->sps_hmvp_flag = get_bits(&gb, 1); + } + + sps->sps_eipd_flag = get_bits(&gb, 1); + if (sps->sps_eipd_flag) { + sps->sps_ibc_flag = get_bits(&gb, 1); + if (sps->sps_ibc_flag) + sps->log2_max_ibc_cand_size_minus2 = get_ue_golomb(&gb); + } + + sps->sps_cm_init_flag = get_bits(&gb, 1); + if (sps->sps_cm_init_flag) + sps->sps_adcc_flag = get_bits(&gb, 1); + + sps->sps_iqt_flag = get_bits(&gb, 1); + if (sps->sps_iqt_flag) + sps->sps_ats_flag = get_bits(&gb, 1); + + sps->sps_addb_flag = get_bits(&gb, 1); + sps->sps_alf_flag = get_bits(&gb, 1); + sps->sps_htdf_flag = get_bits(&gb, 1); + sps->sps_rpl_flag = get_bits(&gb, 1); + sps->sps_pocs_flag = get_bits(&gb, 1); + sps->sps_dquant_flag = get_bits(&gb, 1); + sps->sps_dra_flag = get_bits(&gb, 1); + + if (sps->sps_pocs_flag) + sps->log2_max_pic_order_cnt_lsb_minus4 = get_ue_golomb(&gb); + + if (!sps->sps_pocs_flag || !sps->sps_rpl_flag) { + sps->log2_sub_gop_length = get_ue_golomb(&gb); + if (sps->log2_sub_gop_length == 0) + sps->log2_ref_pic_gap_length = get_ue_golomb(&gb); + } + + if (!sps->sps_rpl_flag) + sps->max_num_tid0_ref_pics = get_ue_golomb(&gb); + else { + sps->sps_max_dec_pic_buffering_minus1 = get_ue_golomb(&gb); + sps->long_term_ref_pic_flag = get_bits(&gb, 1); + sps->rpl1_same_as_rpl0_flag = get_bits(&gb, 1); + sps->num_ref_pic_list_in_sps[0] = get_ue_golomb(&gb); + + for (int i = 0; i < sps->num_ref_pic_list_in_sps[0]; ++i) + ref_pic_list_struct(&gb, &sps->rpls[0][i]); + + if (!sps->rpl1_same_as_rpl0_flag) { + sps->num_ref_pic_list_in_sps[1] = get_ue_golomb(&gb); + for (int i = 0; i < sps->num_ref_pic_list_in_sps[1]; ++i) + ref_pic_list_struct(&gb, &sps->rpls[1][i]); + } + } + + sps->picture_cropping_flag = get_bits(&gb, 1); + + if (sps->picture_cropping_flag) { + sps->picture_crop_left_offset = get_ue_golomb(&gb); + sps->picture_crop_right_offset = get_ue_golomb(&gb); + sps->picture_crop_top_offset = get_ue_golomb(&gb); + sps->picture_crop_bottom_offset = get_ue_golomb(&gb); + } + + if (sps->chroma_format_idc != 0) { + sps->chroma_qp_table_struct.chroma_qp_table_present_flag = get_bits(&gb, 1); + + if (sps->chroma_qp_table_struct.chroma_qp_table_present_flag) { + sps->chroma_qp_table_struct.same_qp_table_for_chroma = get_bits(&gb, 1); + sps->chroma_qp_table_struct.global_offset_flag = get_bits(&gb, 1); + for (int i = 0; i < (sps->chroma_qp_table_struct.same_qp_table_for_chroma ? 1 : 2); i++) { + sps->chroma_qp_table_struct.num_points_in_qp_table_minus1[i] = get_ue_golomb(&gb);; + for (int j = 0; j <= sps->chroma_qp_table_struct.num_points_in_qp_table_minus1[i]; j++) { + sps->chroma_qp_table_struct.delta_qp_in_val_minus1[i][j] = get_bits(&gb, 6); + sps->chroma_qp_table_struct.delta_qp_out_val[i][j] = get_se_golomb(&gb); + } + } + } + } + + sps->vui_parameters_present_flag = get_bits(&gb, 1); + if (sps->vui_parameters_present_flag) + vui_parameters(&gb, &(sps->vui_parameters)); + + // @note + // If necessary, add the missing fields to the EVCParserSPS structure + // and then extend parser implementation + + return sps; +} + +// @see ISO_IEC_23094-1 (7.3.2.2 SPS RBSP syntax) +// +// @note +// The current implementation of parse_sps function doesn't handle VUI parameters parsing. +// If it will be needed, parse_sps function could be extended to handle VUI parameters parsing +// to initialize fields of the AVCodecContex i.e. color_primaries, color_trc,color_range +// +EVCParserPPS *ff_evc_parse_pps(EVCParamSets *ps, const uint8_t *bs, int bs_size) +{ + GetBitContext gb; + EVCParserPPS *pps; + + int pps_pic_parameter_set_id; + + if (init_get_bits8(&gb, bs, bs_size) < 0) + return NULL; + + pps_pic_parameter_set_id = get_ue_golomb(&gb); + if (pps_pic_parameter_set_id > EVC_MAX_PPS_COUNT) + return NULL; + + if(!ps->pps[pps_pic_parameter_set_id]) { + if ((ps->pps[pps_pic_parameter_set_id] = av_malloc(sizeof(EVCParserPPS))) == NULL) + return NULL; + } + + pps = ps->pps[pps_pic_parameter_set_id]; + memset(pps, 0, sizeof(*pps)); + + pps->pps_pic_parameter_set_id = pps_pic_parameter_set_id; + + pps->pps_seq_parameter_set_id = get_ue_golomb(&gb); + if (pps->pps_seq_parameter_set_id >= EVC_MAX_SPS_COUNT) { + av_freep(&ps->pps[pps_pic_parameter_set_id]); + return NULL; + } + + pps->num_ref_idx_default_active_minus1[0] = get_ue_golomb(&gb); + pps->num_ref_idx_default_active_minus1[1] = get_ue_golomb(&gb); + pps->additional_lt_poc_lsb_len = get_ue_golomb(&gb); + pps->rpl1_idx_present_flag = get_bits(&gb, 1); + pps->single_tile_in_pic_flag = get_bits(&gb, 1); + + if (!pps->single_tile_in_pic_flag) { + pps->num_tile_columns_minus1 = get_ue_golomb(&gb); + pps->num_tile_rows_minus1 = get_ue_golomb(&gb); + pps->uniform_tile_spacing_flag = get_bits(&gb, 1); + + if (!pps->uniform_tile_spacing_flag) { + for (int i = 0; i < pps->num_tile_columns_minus1; i++) + pps->tile_column_width_minus1[i] = get_ue_golomb(&gb); + + for (int i = 0; i < pps->num_tile_rows_minus1; i++) + pps->tile_row_height_minus1[i] = get_ue_golomb(&gb); + } + pps->loop_filter_across_tiles_enabled_flag = get_bits(&gb, 1); + pps->tile_offset_len_minus1 = get_ue_golomb(&gb); + } + + pps->tile_id_len_minus1 = get_ue_golomb(&gb); + pps->explicit_tile_id_flag = get_bits(&gb, 1); + + if (pps->explicit_tile_id_flag) { + for (int i = 0; i <= pps->num_tile_rows_minus1; i++) { + for (int j = 0; j <= pps->num_tile_columns_minus1; j++) + pps->tile_id_val[i][j] = get_bits(&gb, pps->tile_id_len_minus1 + 1); + } + } + + pps->pic_dra_enabled_flag = 0; + pps->pic_dra_enabled_flag = get_bits(&gb, 1); + + if (pps->pic_dra_enabled_flag) + pps->pic_dra_aps_id = get_bits(&gb, 5); + + pps->arbitrary_slice_present_flag = get_bits(&gb, 1); + pps->constrained_intra_pred_flag = get_bits(&gb, 1); + pps->cu_qp_delta_enabled_flag = get_bits(&gb, 1); + + if (pps->cu_qp_delta_enabled_flag) + pps->log2_cu_qp_delta_area_minus6 = get_ue_golomb(&gb); + + return pps; +} + +void ff_evc_ps_free(EVCParamSets *ps) { + for (int i = 0; i < EVC_MAX_SPS_COUNT; i++) + av_freep(&ps->sps[i]); + + for (int i = 0; i < EVC_MAX_PPS_COUNT; i++) + av_freep(&ps->pps[i]); +} diff --git a/libavcodec/evc_ps.h b/libavcodec/evc_ps.h new file mode 100644 index 00000000000..989336079fa --- /dev/null +++ b/libavcodec/evc_ps.h @@ -0,0 +1,228 @@ +/* + * 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 + * EVC decoder/parser shared code + */ + +#ifndef AVCODEC_EVC_PS_H +#define AVCODEC_EVC_PS_H + +#include + +#include "evc.h" + +#define EVC_MAX_QP_TABLE_SIZE 58 +#define NUM_CPB 32 + +// rpl structure +typedef struct RefPicListStruct { + int poc; + int tid; + int ref_pic_num; + int ref_pic_active_num; + int ref_pics[EVC_MAX_NUM_REF_PICS]; + char pic_type; + +} RefPicListStruct; + +// chromaQP table structure to be signalled in SPS +typedef struct ChromaQpTable { + int chroma_qp_table_present_flag; // u(1) + int same_qp_table_for_chroma; // u(1) + int global_offset_flag; // u(1) + int num_points_in_qp_table_minus1[2]; // ue(v) + int delta_qp_in_val_minus1[2][EVC_MAX_QP_TABLE_SIZE]; // u(6) + int delta_qp_out_val[2][EVC_MAX_QP_TABLE_SIZE]; // se(v) +} ChromaQpTable; + +// Hypothetical Reference Decoder (HRD) parameters, part of VUI +typedef struct HRDParameters { + int cpb_cnt_minus1; // ue(v) + int bit_rate_scale; // u(4) + int cpb_size_scale; // u(4) + int bit_rate_value_minus1[NUM_CPB]; // ue(v) + int cpb_size_value_minus1[NUM_CPB]; // ue(v) + int cbr_flag[NUM_CPB]; // u(1) + int initial_cpb_removal_delay_length_minus1; // u(5) + int cpb_removal_delay_length_minus1; // u(5) + int dpb_output_delay_length_minus1; // u(5) + int time_offset_length; // u(5) +} HRDParameters; + +// video usability information (VUI) part of SPS +typedef struct VUIParameters { + int aspect_ratio_info_present_flag; // u(1) + int aspect_ratio_idc; // u(8) + int sar_width; // u(16) + int sar_height; // u(16) + int overscan_info_present_flag; // u(1) + int overscan_appropriate_flag; // u(1) + int video_signal_type_present_flag; // u(1) + int video_format; // u(3) + int video_full_range_flag; // u(1) + int colour_description_present_flag; // u(1) + int colour_primaries; // u(8) + int transfer_characteristics; // u(8) + int matrix_coefficients; // u(8) + int chroma_loc_info_present_flag; // u(1) + int chroma_sample_loc_type_top_field; // ue(v) + int chroma_sample_loc_type_bottom_field; // ue(v) + int neutral_chroma_indication_flag; // u(1) + int field_seq_flag; // u(1) + int timing_info_present_flag; // u(1) + int num_units_in_tick; // u(32) + int time_scale; // u(32) + int fixed_pic_rate_flag; // u(1) + int nal_hrd_parameters_present_flag; // u(1) + int vcl_hrd_parameters_present_flag; // u(1) + int low_delay_hrd_flag; // u(1) + int pic_struct_present_flag; // u(1) + int bitstream_restriction_flag; // u(1) + int motion_vectors_over_pic_boundaries_flag; // u(1) + int max_bytes_per_pic_denom; // ue(v) + int max_bits_per_mb_denom; // ue(v) + int log2_max_mv_length_horizontal; // ue(v) + int log2_max_mv_length_vertical; // ue(v) + int num_reorder_pics; // ue(v) + int max_dec_pic_buffering; // ue(v) + + HRDParameters hrd_parameters; +} VUIParameters; + +// The sturcture reflects SPS RBSP(raw byte sequence payload) layout +// @see ISO_IEC_23094-1 section 7.3.2.1 +// +// The following descriptors specify the parsing process of each element +// u(n) - unsigned integer using n bits +// ue(v) - unsigned integer 0-th order Exp_Golomb-coded syntax element with the left bit first +typedef struct EVCParserSPS { + int sps_seq_parameter_set_id; // ue(v) + int profile_idc; // u(8) + int level_idc; // u(8) + int toolset_idc_h; // u(32) + int toolset_idc_l; // u(32) + int chroma_format_idc; // ue(v) + int pic_width_in_luma_samples; // ue(v) + int pic_height_in_luma_samples; // ue(v) + int bit_depth_luma_minus8; // ue(v) + int bit_depth_chroma_minus8; // ue(v) + + int sps_btt_flag; // u(1) + int log2_ctu_size_minus5; // ue(v) + int log2_min_cb_size_minus2; // ue(v) + int log2_diff_ctu_max_14_cb_size; // ue(v) + int log2_diff_ctu_max_tt_cb_size; // ue(v) + int log2_diff_min_cb_min_tt_cb_size_minus2; // ue(v) + + int sps_suco_flag; // u(1) + int log2_diff_ctu_size_max_suco_cb_size; // ue(v) + int log2_diff_max_suco_min_suco_cb_size; // ue(v) + + int sps_admvp_flag; // u(1) + int sps_affine_flag; // u(1) + int sps_amvr_flag; // u(1) + int sps_dmvr_flag; // u(1) + int sps_mmvd_flag; // u(1) + int sps_hmvp_flag; // u(1) + + int sps_eipd_flag; // u(1) + int sps_ibc_flag; // u(1) + int log2_max_ibc_cand_size_minus2; // ue(v) + + int sps_cm_init_flag; // u(1) + int sps_adcc_flag; // u(1) + + int sps_iqt_flag; // u(1) + int sps_ats_flag; // u(1) + + int sps_addb_flag; // u(1) + int sps_alf_flag; // u(1) + int sps_htdf_flag; // u(1) + int sps_rpl_flag; // u(1) + int sps_pocs_flag; // u(1) + int sps_dquant_flag; // u(1) + int sps_dra_flag; // u(1) + + int log2_max_pic_order_cnt_lsb_minus4; // ue(v) + int log2_sub_gop_length; // ue(v) + int log2_ref_pic_gap_length; // ue(v) + + int max_num_tid0_ref_pics; // ue(v) + + int sps_max_dec_pic_buffering_minus1; // ue(v) + int long_term_ref_pic_flag; // u(1) + int rpl1_same_as_rpl0_flag; // u(1) + int num_ref_pic_list_in_sps[2]; // ue(v) + struct RefPicListStruct rpls[2][EVC_MAX_NUM_RPLS]; + + int picture_cropping_flag; // u(1) + int picture_crop_left_offset; // ue(v) + int picture_crop_right_offset; // ue(v) + int picture_crop_top_offset; // ue(v) + int picture_crop_bottom_offset; // ue(v) + + struct ChromaQpTable chroma_qp_table_struct; + + int vui_parameters_present_flag; // u(1) + + struct VUIParameters vui_parameters; + +} EVCParserSPS; + +typedef struct EVCParserPPS { + int pps_pic_parameter_set_id; // ue(v) + int pps_seq_parameter_set_id; // ue(v) + int num_ref_idx_default_active_minus1[2]; // ue(v) + int additional_lt_poc_lsb_len; // ue(v) + int rpl1_idx_present_flag; // u(1) + int single_tile_in_pic_flag; // u(1) + int num_tile_columns_minus1; // ue(v) + int num_tile_rows_minus1; // ue(v) + int uniform_tile_spacing_flag; // u(1) + int tile_column_width_minus1[EVC_MAX_TILE_ROWS]; // ue(v) + int tile_row_height_minus1[EVC_MAX_TILE_COLUMNS]; // ue(v) + int loop_filter_across_tiles_enabled_flag; // u(1) + int tile_offset_len_minus1; // ue(v) + int tile_id_len_minus1; // ue(v) + int explicit_tile_id_flag; // u(1) + int tile_id_val[EVC_MAX_TILE_ROWS][EVC_MAX_TILE_COLUMNS]; // u(v) + int pic_dra_enabled_flag; // u(1) + int pic_dra_aps_id; // u(5) + int arbitrary_slice_present_flag; // u(1) + int constrained_intra_pred_flag; // u(1) + int cu_qp_delta_enabled_flag; // u(1) + int log2_cu_qp_delta_area_minus6; // ue(v) + +} EVCParserPPS; + +typedef struct EVCParamSets { + EVCParserSPS *sps[EVC_MAX_SPS_COUNT]; + EVCParserPPS *pps[EVC_MAX_PPS_COUNT]; +} EVCParamSets; + +// @see ISO_IEC_23094-1 (7.3.2.1 SPS RBSP syntax) +EVCParserSPS *ff_evc_parse_sps(EVCParamSets *ps, const uint8_t *bs, int bs_size); + +// @see ISO_IEC_23094-1 (7.3.2.2 SPS RBSP syntax) +EVCParserPPS *ff_evc_parse_pps(EVCParamSets *ps, const uint8_t *bs, int bs_size); + +void ff_evc_ps_free(EVCParamSets *ps); + +#endif /* AVCODEC_EVC_PS_H */ From f7e0af5edc9e7c1315da35a98f017cb497f65ad4 Mon Sep 17 00:00:00 2001 From: James Almer Date: Sat, 17 Jun 2023 13:06:49 -0300 Subject: [PATCH 1564/2172] avcodec/evc_parser: stop exporting delay and gop_size The former is a property a decoder may export, and the latter is only used in encoding scenarios. Signed-off-by: James Almer --- libavcodec/evc_parse.c | 6 ------ libavcodec/evc_parse.h | 6 ------ libavcodec/evc_parser.c | 2 -- 3 files changed, 14 deletions(-) diff --git a/libavcodec/evc_parse.c b/libavcodec/evc_parse.c index a8e6356b96c..1fe58c80508 100644 --- a/libavcodec/evc_parse.c +++ b/libavcodec/evc_parse.c @@ -225,7 +225,6 @@ int ff_evc_parse_nal_unit(EVCParserContext *ctx, const uint8_t *buf, int buf_siz switch(nalu_type) { case EVC_SPS_NUT: { EVCParserSPS *sps; - int SubGopLength; int bit_depth; sps = ff_evc_parse_sps(&ctx->ps, data, nalu_size); @@ -245,11 +244,6 @@ int ff_evc_parse_nal_unit(EVCParserContext *ctx, const uint8_t *buf, int buf_siz ctx->height = sps->pic_height_in_luma_samples; } - SubGopLength = (int)pow(2.0, sps->log2_sub_gop_length); - ctx->gop_size = SubGopLength; - - ctx->delay = (sps->sps_max_dec_pic_buffering_minus1) ? sps->sps_max_dec_pic_buffering_minus1 - 1 : SubGopLength + sps->max_num_tid0_ref_pics - 1; - if (sps->profile_idc == 1) ctx->profile = FF_PROFILE_EVC_MAIN; else ctx->profile = FF_PROFILE_EVC_BASELINE; diff --git a/libavcodec/evc_parse.h b/libavcodec/evc_parse.h index b5462f57112..2748f8dfbfc 100644 --- a/libavcodec/evc_parse.h +++ b/libavcodec/evc_parse.h @@ -117,12 +117,6 @@ typedef struct EVCParserContext { // Framerate value in the compressed bitstream AVRational framerate; - // Number of pictures in a group of pictures - int gop_size; - - // Number of frames the decoded output will be delayed relative to the encoded input - int delay; - int parsed_extradata; } EVCParserContext; diff --git a/libavcodec/evc_parser.c b/libavcodec/evc_parser.c index 1fd8aac1dce..4fd8c49fd4e 100644 --- a/libavcodec/evc_parser.c +++ b/libavcodec/evc_parser.c @@ -72,8 +72,6 @@ static int parse_nal_units(AVCodecParserContext *s, AVCodecContext *avctx, const s->format = ctx->format; avctx->framerate = ctx->framerate; - avctx->gop_size = ctx->gop_size; - avctx->delay = ctx->delay; avctx->profile = ctx->profile; } else if(ctx->nalu_type == EVC_NOIDR_NUT || ctx->nalu_type == EVC_IDR_NUT) { From ff7a4cdf04fcd0bc8deab540fe83f789fcf99301 Mon Sep 17 00:00:00 2001 From: James Almer Date: Sat, 17 Jun 2023 17:18:04 -0300 Subject: [PATCH 1565/2172] avcodec/evc_parse: split off deriving PoC Signed-off-by: James Almer --- libavcodec/evc_parse.c | 142 +++++++++++++++++++++-------------------- libavcodec/evc_parse.h | 5 ++ 2 files changed, 79 insertions(+), 68 deletions(-) diff --git a/libavcodec/evc_parse.c b/libavcodec/evc_parse.c index 1fe58c80508..262ef5aa390 100644 --- a/libavcodec/evc_parse.c +++ b/libavcodec/evc_parse.c @@ -187,6 +187,77 @@ static int evc_parse_slice_header(EVCParserContext *ctx, EVCParserSliceHeader *s return 0; } +int ff_evc_derive_poc(const EVCParamSets *ps, const EVCParserSliceHeader *sh, + EVCParserPoc *poc, enum EVCNALUnitType nalu_type, int tid) +{ + const EVCParserPPS *pps = ps->pps[sh->slice_pic_parameter_set_id]; + const EVCParserSPS *sps; + + if (!pps) + return AVERROR_INVALIDDATA; + + sps = ps->sps[pps->pps_seq_parameter_set_id]; + if (!sps) + return AVERROR_INVALIDDATA; + + if (sps->sps_pocs_flag) { + int PicOrderCntMsb = 0; + poc->prevPicOrderCntVal = poc->PicOrderCntVal; + + if (nalu_type == EVC_IDR_NUT) + PicOrderCntMsb = 0; + else { + int MaxPicOrderCntLsb = 1 << (sps->log2_max_pic_order_cnt_lsb_minus4 + 4); + int prevPicOrderCntLsb = poc->PicOrderCntVal & (MaxPicOrderCntLsb - 1); + int prevPicOrderCntMsb = poc->PicOrderCntVal - prevPicOrderCntLsb; + + if ((sh->slice_pic_order_cnt_lsb < prevPicOrderCntLsb) && + ((prevPicOrderCntLsb - sh->slice_pic_order_cnt_lsb) >= (MaxPicOrderCntLsb / 2))) + PicOrderCntMsb = prevPicOrderCntMsb + MaxPicOrderCntLsb; + else if ((sh->slice_pic_order_cnt_lsb > prevPicOrderCntLsb) && + ((sh->slice_pic_order_cnt_lsb - prevPicOrderCntLsb) > (MaxPicOrderCntLsb / 2))) + PicOrderCntMsb = prevPicOrderCntMsb - MaxPicOrderCntLsb; + else + PicOrderCntMsb = prevPicOrderCntMsb; + } + poc->PicOrderCntVal = PicOrderCntMsb + sh->slice_pic_order_cnt_lsb; + } else { + if (nalu_type == EVC_IDR_NUT) { + poc->PicOrderCntVal = 0; + poc->DocOffset = -1; + } else { + int SubGopLength = (int)pow(2.0, sps->log2_sub_gop_length); + if (tid == 0) { + poc->PicOrderCntVal = poc->prevPicOrderCntVal + SubGopLength; + poc->DocOffset = 0; + poc->prevPicOrderCntVal = poc->PicOrderCntVal; + } else { + int ExpectedTemporalId; + int PocOffset; + int prevDocOffset = poc->DocOffset; + + poc->DocOffset = (prevDocOffset + 1) % SubGopLength; + if (poc->DocOffset == 0) { + poc->prevPicOrderCntVal += SubGopLength; + ExpectedTemporalId = 0; + } else + ExpectedTemporalId = 1 + (int)log2(poc->DocOffset); + while (tid != ExpectedTemporalId) { + poc->DocOffset = (poc->DocOffset + 1) % SubGopLength; + if (poc->DocOffset == 0) + ExpectedTemporalId = 0; + else + ExpectedTemporalId = 1 + (int)log2(poc->DocOffset); + } + PocOffset = (int)(SubGopLength * ((2.0 * poc->DocOffset + 1) / (int)pow(2.0, tid) - 2)); + poc->PicOrderCntVal = poc->prevPicOrderCntVal + PocOffset; + } + } + } + + return 0; +} + int ff_evc_parse_nal_unit(EVCParserContext *ctx, const uint8_t *buf, int buf_size, void *logctx) { int nalu_type, nalu_size; @@ -299,8 +370,6 @@ int ff_evc_parse_nal_unit(EVCParserContext *ctx, const uint8_t *buf, int buf_siz case EVC_IDR_NUT: // Coded slice of a IDR or non-IDR picture case EVC_NOIDR_NUT: { EVCParserSliceHeader sh; - const EVCParserSPS *sps; - const EVCParserPPS *pps; int ret; ret = evc_parse_slice_header(ctx, &sh, data, nalu_size); @@ -331,72 +400,9 @@ int ff_evc_parse_nal_unit(EVCParserContext *ctx, const uint8_t *buf, int buf_siz // POC (picture order count of the current picture) derivation // @see ISO/IEC 23094-1:2020(E) 8.3.1 Decoding process for picture order count - pps = ctx->ps.pps[sh.slice_pic_parameter_set_id]; - sps = ctx->ps.sps[pps->pps_seq_parameter_set_id]; - av_assert0(sps && pps); - - if (sps->sps_pocs_flag) { - - int PicOrderCntMsb = 0; - ctx->poc.prevPicOrderCntVal = ctx->poc.PicOrderCntVal; - - if (nalu_type == EVC_IDR_NUT) - PicOrderCntMsb = 0; - else { - int MaxPicOrderCntLsb = 1 << (sps->log2_max_pic_order_cnt_lsb_minus4 + 4); - - int prevPicOrderCntLsb = ctx->poc.PicOrderCntVal & (MaxPicOrderCntLsb - 1); - int prevPicOrderCntMsb = ctx->poc.PicOrderCntVal - prevPicOrderCntLsb; - - - if ((sh.slice_pic_order_cnt_lsb < prevPicOrderCntLsb) && - ((prevPicOrderCntLsb - sh.slice_pic_order_cnt_lsb) >= (MaxPicOrderCntLsb / 2))) - - PicOrderCntMsb = prevPicOrderCntMsb + MaxPicOrderCntLsb; - - else if ((sh.slice_pic_order_cnt_lsb > prevPicOrderCntLsb) && - ((sh.slice_pic_order_cnt_lsb - prevPicOrderCntLsb) > (MaxPicOrderCntLsb / 2))) - - PicOrderCntMsb = prevPicOrderCntMsb - MaxPicOrderCntLsb; - - else - PicOrderCntMsb = prevPicOrderCntMsb; - } - ctx->poc.PicOrderCntVal = PicOrderCntMsb + sh.slice_pic_order_cnt_lsb; - - } else { - if (nalu_type == EVC_IDR_NUT) { - ctx->poc.PicOrderCntVal = 0; - ctx->poc.DocOffset = -1; - } else { - int SubGopLength = (int)pow(2.0, sps->log2_sub_gop_length); - if (tid == 0) { - ctx->poc.PicOrderCntVal = ctx->poc.prevPicOrderCntVal + SubGopLength; - ctx->poc.DocOffset = 0; - ctx->poc.prevPicOrderCntVal = ctx->poc.PicOrderCntVal; - } else { - int ExpectedTemporalId; - int PocOffset; - int prevDocOffset = ctx->poc.DocOffset; - - ctx->poc.DocOffset = (prevDocOffset + 1) % SubGopLength; - if (ctx->poc.DocOffset == 0) { - ctx->poc.prevPicOrderCntVal += SubGopLength; - ExpectedTemporalId = 0; - } else - ExpectedTemporalId = 1 + (int)log2(ctx->poc.DocOffset); - while (tid != ExpectedTemporalId) { - ctx->poc.DocOffset = (ctx->poc.DocOffset + 1) % SubGopLength; - if (ctx->poc.DocOffset == 0) - ExpectedTemporalId = 0; - else - ExpectedTemporalId = 1 + (int)log2(ctx->poc.DocOffset); - } - PocOffset = (int)(SubGopLength * ((2.0 * ctx->poc.DocOffset + 1) / (int)pow(2.0, tid) - 2)); - ctx->poc.PicOrderCntVal = ctx->poc.prevPicOrderCntVal + PocOffset; - } - } - } + ret = ff_evc_derive_poc(&ctx->ps, &sh, &ctx->poc, nalu_type, tid); + if (ret < 0) + return ret; ctx->output_picture_number = ctx->poc.PicOrderCntVal; ctx->key_frame = (nalu_type == EVC_IDR_NUT) ? 1 : 0; diff --git a/libavcodec/evc_parse.h b/libavcodec/evc_parse.h index 2748f8dfbfc..97825efcd59 100644 --- a/libavcodec/evc_parse.h +++ b/libavcodec/evc_parse.h @@ -159,4 +159,9 @@ int ff_evc_get_temporal_id(const uint8_t *bits, int bits_size, void *logctx); int ff_evc_parse_nal_unit(EVCParserContext *ctx, const uint8_t *buf, int buf_size, void *logctx); +// POC (picture order count of the current picture) derivation +// @see ISO/IEC 23094-1:2020(E) 8.3.1 Decoding process for picture order count +int ff_evc_derive_poc(const EVCParamSets *ps, const EVCParserSliceHeader *sh, + EVCParserPoc *poc, enum EVCNALUnitType nalu_type, int tid); + #endif /* AVCODEC_EVC_PARSE_H */ From a5663f2d9a3aa322fcba31da5d0e62cd58628477 Mon Sep 17 00:00:00 2001 From: James Almer Date: Sat, 17 Jun 2023 18:02:26 -0300 Subject: [PATCH 1566/2172] avcodec/evc_parser: make ff_evc_parse_nal_unit() local to the parser This is in preparation for the following commits. Signed-off-by: James Almer --- libavcodec/evc_parse.c | 17 +-- libavcodec/evc_parse.h | 3 + libavcodec/evc_parser.c | 222 ++++++++++++++++++++++++++++++++++------ 3 files changed, 202 insertions(+), 40 deletions(-) diff --git a/libavcodec/evc_parse.c b/libavcodec/evc_parse.c index 262ef5aa390..0ad0d821379 100644 --- a/libavcodec/evc_parse.c +++ b/libavcodec/evc_parse.c @@ -70,11 +70,12 @@ int ff_evc_get_temporal_id(const uint8_t *bits, int bits_size, void *logctx) } // @see ISO_IEC_23094-1 (7.3.2.6 Slice layer RBSP syntax) -static int evc_parse_slice_header(EVCParserContext *ctx, EVCParserSliceHeader *sh, const uint8_t *bs, int bs_size) +int ff_evc_parse_slice_header(EVCParserSliceHeader *sh, const EVCParamSets *ps, + enum EVCNALUnitType nalu_type, const uint8_t *bs, int bs_size) { GetBitContext gb; - EVCParserPPS *pps; - EVCParserSPS *sps; + const EVCParserPPS *pps; + const EVCParserSPS *sps; int num_tiles_in_slice = 0; int slice_pic_parameter_set_id; @@ -88,11 +89,11 @@ static int evc_parse_slice_header(EVCParserContext *ctx, EVCParserSliceHeader *s if (slice_pic_parameter_set_id < 0 || slice_pic_parameter_set_id >= EVC_MAX_PPS_COUNT) return AVERROR_INVALIDDATA; - pps = ctx->ps.pps[slice_pic_parameter_set_id]; + pps = ps->pps[slice_pic_parameter_set_id]; if(!pps) return AVERROR_INVALIDDATA; - sps = ctx->ps.sps[pps->pps_seq_parameter_set_id]; + sps = ps->sps[pps->pps_seq_parameter_set_id]; if(!sps) return AVERROR_INVALIDDATA; @@ -121,7 +122,7 @@ static int evc_parse_slice_header(EVCParserContext *ctx, EVCParserSliceHeader *s sh->slice_type = get_ue_golomb(&gb); - if (ctx->nalu_type == EVC_IDR_NUT) + if (nalu_type == EVC_IDR_NUT) sh->no_output_of_prior_pics_flag = get_bits(&gb, 1); if (sps->sps_mmvd_flag && ((sh->slice_type == EVC_SLICE_TYPE_B) || (sh->slice_type == EVC_SLICE_TYPE_P))) @@ -175,7 +176,7 @@ static int evc_parse_slice_header(EVCParserContext *ctx, EVCParserSliceHeader *s } } - if (ctx->nalu_type != EVC_IDR_NUT) { + if (nalu_type != EVC_IDR_NUT) { if (sps->sps_pocs_flag) sh->slice_pic_order_cnt_lsb = get_bits(&gb, sps->log2_max_pic_order_cnt_lsb_minus4 + 4); } @@ -372,7 +373,7 @@ int ff_evc_parse_nal_unit(EVCParserContext *ctx, const uint8_t *buf, int buf_siz EVCParserSliceHeader sh; int ret; - ret = evc_parse_slice_header(ctx, &sh, data, nalu_size); + ret = ff_evc_parse_slice_header(&sh, &ctx->ps, nalu_type, data, nalu_size); if (ret < 0) { av_log(logctx, AV_LOG_ERROR, "Slice header parsing error\n"); return ret; diff --git a/libavcodec/evc_parse.h b/libavcodec/evc_parse.h index 97825efcd59..f31075ff9c9 100644 --- a/libavcodec/evc_parse.h +++ b/libavcodec/evc_parse.h @@ -159,6 +159,9 @@ int ff_evc_get_temporal_id(const uint8_t *bits, int bits_size, void *logctx); int ff_evc_parse_nal_unit(EVCParserContext *ctx, const uint8_t *buf, int buf_size, void *logctx); +int ff_evc_parse_slice_header(EVCParserSliceHeader *sh, const EVCParamSets *ps, + enum EVCNALUnitType nalu_type, const uint8_t *buf, int buf_size); + // POC (picture order count of the current picture) derivation // @see ISO/IEC 23094-1:2020(E) 8.3.1 Decoding process for picture order count int ff_evc_derive_poc(const EVCParamSets *ps, const EVCParserSliceHeader *sh, diff --git a/libavcodec/evc_parser.c b/libavcodec/evc_parser.c index 4fd8c49fd4e..d22922d1c9b 100644 --- a/libavcodec/evc_parser.c +++ b/libavcodec/evc_parser.c @@ -25,6 +25,180 @@ #include "evc.h" #include "evc_parse.h" +#define NUM_CHROMA_FORMATS 4 // @see ISO_IEC_23094-1 section 6.2 table 2 + +static const enum AVPixelFormat pix_fmts_8bit[NUM_CHROMA_FORMATS] = { + AV_PIX_FMT_GRAY8, AV_PIX_FMT_YUV420P, AV_PIX_FMT_YUV422P, AV_PIX_FMT_YUV444P +}; + +static const enum AVPixelFormat pix_fmts_9bit[NUM_CHROMA_FORMATS] = { + AV_PIX_FMT_GRAY9, AV_PIX_FMT_YUV420P9, AV_PIX_FMT_YUV422P9, AV_PIX_FMT_YUV444P9 +}; + +static const enum AVPixelFormat pix_fmts_10bit[NUM_CHROMA_FORMATS] = { + AV_PIX_FMT_GRAY10, AV_PIX_FMT_YUV420P10, AV_PIX_FMT_YUV422P10, AV_PIX_FMT_YUV444P10 +}; + +static const enum AVPixelFormat pix_fmts_12bit[NUM_CHROMA_FORMATS] = { + AV_PIX_FMT_GRAY12, AV_PIX_FMT_YUV420P12, AV_PIX_FMT_YUV422P12, AV_PIX_FMT_YUV444P12 +}; + +static const enum AVPixelFormat pix_fmts_14bit[NUM_CHROMA_FORMATS] = { + AV_PIX_FMT_GRAY14, AV_PIX_FMT_YUV420P14, AV_PIX_FMT_YUV422P14, AV_PIX_FMT_YUV444P14 +}; + +static const enum AVPixelFormat pix_fmts_16bit[NUM_CHROMA_FORMATS] = { + AV_PIX_FMT_GRAY16, AV_PIX_FMT_YUV420P16, AV_PIX_FMT_YUV422P16, AV_PIX_FMT_YUV444P16 +}; + +static int parse_nal_unit(AVCodecParserContext *s, AVCodecContext *avctx, + const uint8_t *buf, int buf_size) +{ + EVCParserContext *ctx = s->priv_data; + int nalu_type, tid; + + if (buf_size <= 0) { + av_log(avctx, AV_LOG_ERROR, "Invalid NAL unit size: (%d)\n", buf_size); + return AVERROR_INVALIDDATA; + } + + // @see ISO_IEC_23094-1_2020, 7.4.2.2 NAL unit header semantic (Table 4 - NAL unit type codes and NAL unit type classes) + // @see enum EVCNALUnitType in evc.h + nalu_type = evc_get_nalu_type(buf, buf_size, avctx); + if (nalu_type < EVC_NOIDR_NUT || nalu_type > EVC_UNSPEC_NUT62) { + av_log(avctx, AV_LOG_ERROR, "Invalid NAL unit type: (%d)\n", nalu_type); + return AVERROR_INVALIDDATA; + } + + tid = ff_evc_get_temporal_id(buf, buf_size, avctx); + if (tid < 0) { + av_log(avctx, AV_LOG_ERROR, "Invalid temporial id: (%d)\n", tid); + return AVERROR_INVALIDDATA; + } + + buf += EVC_NALU_HEADER_SIZE; + buf_size -= EVC_NALU_HEADER_SIZE; + + switch (nalu_type) { + case EVC_SPS_NUT: { + EVCParserSPS *sps = ff_evc_parse_sps(&ctx->ps, buf, buf_size); + if (!sps) { + av_log(avctx, AV_LOG_ERROR, "SPS parsing error\n"); + return AVERROR_INVALIDDATA; + } + break; + } + case EVC_PPS_NUT: { + EVCParserPPS *pps = ff_evc_parse_pps(&ctx->ps, buf, buf_size); + if (!pps) { + av_log(avctx, AV_LOG_ERROR, "PPS parsing error\n"); + return AVERROR_INVALIDDATA; + } + break; + } + case EVC_IDR_NUT: // Coded slice of a IDR or non-IDR picture + case EVC_NOIDR_NUT: { + const EVCParserPPS *pps; + const EVCParserSPS *sps; + EVCParserSliceHeader sh; + int bit_depth; + int ret; + + ret = ff_evc_parse_slice_header(&sh, &ctx->ps, nalu_type, buf, buf_size); + if (ret < 0) { + av_log(avctx, AV_LOG_ERROR, "Slice header parsing error\n"); + return ret; + } + + pps = ctx->ps.pps[sh.slice_pic_parameter_set_id]; + sps = ctx->ps.sps[pps->pps_seq_parameter_set_id]; + av_assert0(sps && pps); + + s->coded_width = sps->pic_width_in_luma_samples; + s->coded_height = sps->pic_height_in_luma_samples; + + if (sps->picture_cropping_flag) { + s->width = sps->pic_width_in_luma_samples - sps->picture_crop_left_offset - sps->picture_crop_right_offset; + s->height = sps->pic_height_in_luma_samples - sps->picture_crop_top_offset - sps->picture_crop_bottom_offset; + } else { + s->width = sps->pic_width_in_luma_samples; + s->height = sps->pic_height_in_luma_samples; + } + + switch (sh.slice_type) { + case EVC_SLICE_TYPE_B: { + s->pict_type = AV_PICTURE_TYPE_B; + break; + } + case EVC_SLICE_TYPE_P: { + s->pict_type = AV_PICTURE_TYPE_P; + break; + } + case EVC_SLICE_TYPE_I: { + s->pict_type = AV_PICTURE_TYPE_I; + break; + } + default: { + s->pict_type = AV_PICTURE_TYPE_NONE; + } + } + + avctx->profile = sps->profile_idc; + + if (sps->vui_parameters_present_flag && sps->vui_parameters.timing_info_present_flag) { + int64_t num = sps->vui_parameters.num_units_in_tick; + int64_t den = sps->vui_parameters.time_scale; + if (num != 0 && den != 0) + av_reduce(&avctx->framerate.den, &avctx->framerate.num, num, den, 1 << 30); + } else + avctx->framerate = (AVRational) { 0, 1 }; + + bit_depth = sps->bit_depth_chroma_minus8 + 8; + s->format = AV_PIX_FMT_NONE; + + switch (bit_depth) { + case 8: + s->format = pix_fmts_8bit[sps->chroma_format_idc]; + break; + case 9: + s->format = pix_fmts_9bit[sps->chroma_format_idc]; + break; + case 10: + s->format = pix_fmts_10bit[sps->chroma_format_idc]; + break; + case 12: + s->format = pix_fmts_12bit[sps->chroma_format_idc]; + break; + case 14: + s->format = pix_fmts_14bit[sps->chroma_format_idc]; + break; + case 16: + s->format = pix_fmts_16bit[sps->chroma_format_idc]; + break; + } + + s->key_frame = (nalu_type == EVC_IDR_NUT) ? 1 : 0; + + // POC (picture order count of the current picture) derivation + // @see ISO/IEC 23094-1:2020(E) 8.3.1 Decoding process for picture order count + ret = ff_evc_derive_poc(&ctx->ps, &sh, &ctx->poc, nalu_type, tid); + if (ret < 0) + return ret; + + s->output_picture_number = ctx->poc.PicOrderCntVal; + + break; + } + case EVC_SEI_NUT: // Supplemental Enhancement Information + case EVC_APS_NUT: // Adaptation parameter set + case EVC_FD_NUT: // Filler data + default: + break; + } + + return 0; +} + /** * Parse NAL units of found picture and decode some basic information. * @@ -35,13 +209,13 @@ */ static int parse_nal_units(AVCodecParserContext *s, AVCodecContext *avctx, const uint8_t *buf, int buf_size) { - EVCParserContext *ctx = s->priv_data; const uint8_t *data = buf; int data_size = buf_size; int bytes_read = 0; - int nalu_size = 0; while (data_size > 0) { + int nalu_size = 0; + int ret; // Buffer size is not enough for buffer to store NAL unit 4-bytes prefix (length) if (data_size < EVC_NALU_LENGTH_PREFIX_SIZE) @@ -57,31 +231,12 @@ static int parse_nal_units(AVCodecParserContext *s, AVCodecContext *avctx, const if (data_size < nalu_size) return AVERROR_INVALIDDATA; - if (ff_evc_parse_nal_unit(ctx, data, nalu_size, avctx) != 0) { + ret = parse_nal_unit(s, avctx, data, nalu_size); + if (ret < 0) { av_log(avctx, AV_LOG_ERROR, "Parsing of NAL unit failed\n"); return AVERROR_INVALIDDATA; } - if(ctx->nalu_type == EVC_SPS_NUT) { - - s->coded_width = ctx->coded_width; - s->coded_height = ctx->coded_height; - s->width = ctx->width; - s->height = ctx->height; - - s->format = ctx->format; - - avctx->framerate = ctx->framerate; - avctx->profile = ctx->profile; - - } else if(ctx->nalu_type == EVC_NOIDR_NUT || ctx->nalu_type == EVC_IDR_NUT) { - - s->pict_type = ctx->pict_type; - s->key_frame = ctx->key_frame; - s->output_picture_number = ctx->output_picture_number; - - } - data += nalu_size; data_size -= nalu_size; } @@ -90,8 +245,10 @@ static int parse_nal_units(AVCodecParserContext *s, AVCodecContext *avctx, const // Decoding nal units from evcC (EVCDecoderConfigurationRecord) // @see @see ISO/IEC 14496-15:2021 Coding of audio-visual objects - Part 15: section 12.3.3.2 -static int decode_extradata(EVCParserContext *ctx, const uint8_t *data, int size, void *logctx) +static int decode_extradata(AVCodecParserContext *s, AVCodecContext *avctx) { + const uint8_t *data = avctx->extradata; + int size = avctx->extradata_size; int ret = 0; GetByteContext gb; @@ -108,7 +265,7 @@ static int decode_extradata(EVCParserContext *ctx, const uint8_t *data, int size // The value of this field shall be one of 0, 1, or 3 corresponding to a length encoded with 1, 2, or 4 bytes, respectively. if (bytestream2_get_bytes_left(&gb) < 18) { - av_log(logctx, AV_LOG_ERROR, "evcC %d too short\n", size); + av_log(avctx, AV_LOG_ERROR, "evcC %d too short\n", size); return AVERROR_INVALIDDATA; } @@ -121,7 +278,7 @@ static int decode_extradata(EVCParserContext *ctx, const uint8_t *data, int size if( nalu_length_field_size != 1 && nalu_length_field_size != 2 && nalu_length_field_size != 4 ) { - av_log(logctx, AV_LOG_ERROR, "The length in bytes of the NALUnitLenght field in a EVC video stream has unsupported value of %d\n", nalu_length_field_size); + av_log(avctx, AV_LOG_ERROR, "The length in bytes of the NALUnitLenght field in a EVC video stream has unsupported value of %d\n", nalu_length_field_size); return AVERROR_INVALIDDATA; } @@ -142,7 +299,7 @@ static int decode_extradata(EVCParserContext *ctx, const uint8_t *data, int size int nal_unit_length = bytestream2_get_be16(&gb); if (bytestream2_get_bytes_left(&gb) < nal_unit_length) { - av_log(logctx, AV_LOG_ERROR, "Invalid NAL unit size in extradata.\n"); + av_log(avctx, AV_LOG_ERROR, "Invalid NAL unit size in extradata.\n"); return AVERROR_INVALIDDATA; } @@ -150,8 +307,8 @@ static int decode_extradata(EVCParserContext *ctx, const uint8_t *data, int size nal_unit_type == EVC_PPS_NUT || nal_unit_type == EVC_APS_NUT || nal_unit_type == EVC_SEI_NUT ) { - if (ff_evc_parse_nal_unit(ctx, gb.buffer, nal_unit_length, logctx) != 0) { - av_log(logctx, AV_LOG_ERROR, "Parsing of NAL unit failed\n"); + if (parse_nal_unit(s, avctx, gb.buffer, nal_unit_length) != 0) { + av_log(avctx, AV_LOG_ERROR, "Parsing of NAL unit failed\n"); return AVERROR_INVALIDDATA; } } @@ -173,8 +330,11 @@ static int evc_parse(AVCodecParserContext *s, AVCodecContext *avctx, int ret; EVCParserContext *ctx = s->priv_data; + s->picture_structure = AV_PICTURE_STRUCTURE_FRAME; + s->key_frame = 0; + if (avctx->extradata && !ctx->parsed_extradata) { - decode_extradata(ctx, avctx->extradata, avctx->extradata_size, avctx); + decode_extradata(s, avctx); ctx->parsed_extradata = 1; } @@ -187,8 +347,6 @@ static int evc_parse(AVCodecParserContext *s, AVCodecContext *avctx, return buf_size; } - s->picture_structure = AV_PICTURE_STRUCTURE_FRAME; - // poutbuf contains just one Access Unit *poutbuf = buf; *poutbuf_size = buf_size; From fdd8daf899c1bdaefea01e3f868e25a3cab63419 Mon Sep 17 00:00:00 2001 From: James Almer Date: Sat, 17 Jun 2023 18:50:33 -0300 Subject: [PATCH 1567/2172] avcodec/evc_parser: remove write only variable Signed-off-by: James Almer --- libavcodec/evc_parser.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/libavcodec/evc_parser.c b/libavcodec/evc_parser.c index d22922d1c9b..c30da6846e1 100644 --- a/libavcodec/evc_parser.c +++ b/libavcodec/evc_parser.c @@ -211,7 +211,6 @@ static int parse_nal_units(AVCodecParserContext *s, AVCodecContext *avctx, const { const uint8_t *data = buf; int data_size = buf_size; - int bytes_read = 0; while (data_size > 0) { int nalu_size = 0; @@ -223,7 +222,6 @@ static int parse_nal_units(AVCodecParserContext *s, AVCodecContext *avctx, const nalu_size = evc_read_nal_unit_length(data, data_size, avctx); - bytes_read += EVC_NALU_LENGTH_PREFIX_SIZE; data += EVC_NALU_LENGTH_PREFIX_SIZE; data_size -= EVC_NALU_LENGTH_PREFIX_SIZE; From 56e52e870d3c71a1bde753f2f535316f80a9bbec Mon Sep 17 00:00:00 2001 From: James Almer Date: Sat, 17 Jun 2023 18:43:37 -0300 Subject: [PATCH 1568/2172] avcodec/evc_frame_merge_bsf: make ff_evc_parse_nal_unit() local to the filter Signed-off-by: James Almer --- libavcodec/evc_frame_merge_bsf.c | 114 +++++++++++++++++++++++++------ 1 file changed, 92 insertions(+), 22 deletions(-) diff --git a/libavcodec/evc_frame_merge_bsf.c b/libavcodec/evc_frame_merge_bsf.c index f497780afbe..817136a551c 100644 --- a/libavcodec/evc_frame_merge_bsf.c +++ b/libavcodec/evc_frame_merge_bsf.c @@ -35,20 +35,27 @@ typedef struct AccessUnitBuffer { typedef struct EVCFMergeContext { AVPacket *in; - EVCParserContext parser_ctx; + EVCParamSets ps; + EVCParserPoc poc; AccessUnitBuffer au_buffer; } EVCFMergeContext; -static int end_of_access_unit_found(EVCParserContext *parser_ctx) +static int end_of_access_unit_found(const EVCParamSets *ps, const EVCParserSliceHeader *sh, + const EVCParserPoc *poc, enum EVCNALUnitType nalu_type) { - if (parser_ctx->profile == 0) { // BASELINE profile - if (parser_ctx->nalu_type == EVC_NOIDR_NUT || parser_ctx->nalu_type == EVC_IDR_NUT) + EVCParserPPS *pps = ps->pps[sh->slice_pic_parameter_set_id]; + EVCParserSPS *sps = ps->sps[pps->pps_seq_parameter_set_id]; + + av_assert0(sps && pps); + + if (sps->profile_idc == 0) { // BASELINE profile + if (nalu_type == EVC_NOIDR_NUT || nalu_type == EVC_IDR_NUT) return 1; } else { // MAIN profile - if (parser_ctx->nalu_type == EVC_NOIDR_NUT) { - if (parser_ctx->poc.PicOrderCntVal != parser_ctx->poc.prevPicOrderCntVal) + if (nalu_type == EVC_NOIDR_NUT) { + if (poc->PicOrderCntVal != poc->prevPicOrderCntVal) return 1; - } else if (parser_ctx->nalu_type == EVC_IDR_NUT) + } else if (nalu_type == EVC_IDR_NUT) return 1; } return 0; @@ -58,7 +65,7 @@ static void evc_frame_merge_flush(AVBSFContext *bsf) { EVCFMergeContext *ctx = bsf->priv_data; - ff_evc_ps_free(&ctx->parser_ctx.ps); + ff_evc_ps_free(&ctx->ps); av_packet_unref(ctx->in); ctx->au_buffer.data_size = 0; } @@ -66,12 +73,10 @@ static void evc_frame_merge_flush(AVBSFContext *bsf) static int evc_frame_merge_filter(AVBSFContext *bsf, AVPacket *out) { EVCFMergeContext *ctx = bsf->priv_data; - EVCParserContext *parser_ctx = &ctx->parser_ctx; - AVPacket *in = ctx->in; - - size_t nalu_size = 0; uint8_t *buffer, *nalu = NULL; + enum EVCNALUnitType nalu_type; + int tid, nalu_size = 0; int au_end_found = 0; int err; @@ -81,29 +86,91 @@ static int evc_frame_merge_filter(AVBSFContext *bsf, AVPacket *out) nalu_size = evc_read_nal_unit_length(in->data, EVC_NALU_LENGTH_PREFIX_SIZE, bsf); if (nalu_size <= 0) { - av_packet_unref(in); - return AVERROR_INVALIDDATA; + err = AVERROR_INVALIDDATA; + goto end; } nalu = in->data + EVC_NALU_LENGTH_PREFIX_SIZE; nalu_size = in->size - EVC_NALU_LENGTH_PREFIX_SIZE; // NAL unit parsing needed to determine if end of AU was found - err = ff_evc_parse_nal_unit(parser_ctx, nalu, nalu_size, bsf); - if (err < 0) { - av_log(bsf, AV_LOG_ERROR, "NAL Unit parsing error\n"); - av_packet_unref(in); + if (nalu_size <= 0) { + av_log(bsf, AV_LOG_ERROR, "Invalid NAL unit size: (%d)\n", nalu_size); + err = AVERROR_INVALIDDATA; + goto end; + } - return err; + // @see ISO_IEC_23094-1_2020, 7.4.2.2 NAL unit header semantic (Table 4 - NAL unit type codes and NAL unit type classes) + // @see enum EVCNALUnitType in evc.h + nalu_type = evc_get_nalu_type(nalu, nalu_size, bsf); + if (nalu_type < EVC_NOIDR_NUT || nalu_type > EVC_UNSPEC_NUT62) { + av_log(bsf, AV_LOG_ERROR, "Invalid NAL unit type: (%d)\n", nalu_type); + err = AVERROR_INVALIDDATA; + goto end; } - au_end_found = end_of_access_unit_found(parser_ctx); + tid = ff_evc_get_temporal_id(nalu, nalu_size, bsf); + if (tid < 0) { + av_log(bsf, AV_LOG_ERROR, "Invalid temporial id: (%d)\n", tid); + err = AVERROR_INVALIDDATA; + goto end; + } + + nalu += EVC_NALU_HEADER_SIZE; + nalu_size -= EVC_NALU_HEADER_SIZE; + + switch (nalu_type) { + case EVC_SPS_NUT: { + EVCParserSPS *sps = ff_evc_parse_sps(&ctx->ps, nalu, nalu_size); + if (!sps) { + av_log(bsf, AV_LOG_ERROR, "SPS parsing error\n"); + err = AVERROR_INVALIDDATA; + goto end; + } + break; + } + case EVC_PPS_NUT: { + EVCParserPPS *pps = ff_evc_parse_pps(&ctx->ps, nalu, nalu_size); + if (!pps) { + av_log(bsf, AV_LOG_ERROR, "PPS parsing error\n"); + err = AVERROR_INVALIDDATA; + goto end; + } + break; + } + case EVC_IDR_NUT: // Coded slice of a IDR or non-IDR picture + case EVC_NOIDR_NUT: { + EVCParserSliceHeader sh; + + err = ff_evc_parse_slice_header(&sh, &ctx->ps, nalu_type, nalu, nalu_size); + if (err < 0) { + av_log(bsf, AV_LOG_ERROR, "Slice header parsing error\n"); + goto end; + } + + // POC (picture order count of the current picture) derivation + // @see ISO/IEC 23094-1:2020(E) 8.3.1 Decoding process for picture order count + err = ff_evc_derive_poc(&ctx->ps, &sh, &ctx->poc, nalu_type, tid); + if (err < 0) + goto end; + + au_end_found = end_of_access_unit_found(&ctx->ps, &sh, &ctx->poc, nalu_type); + + break; + } + case EVC_SEI_NUT: // Supplemental Enhancement Information + case EVC_APS_NUT: // Adaptation parameter set + case EVC_FD_NUT: // Filler data + default: + break; + } buffer = av_fast_realloc(ctx->au_buffer.data, &ctx->au_buffer.capacity, ctx->au_buffer.data_size + in->size); if (!buffer) { av_freep(&ctx->au_buffer.data); - return AVERROR(ENOMEM); + err = AVERROR_INVALIDDATA; + goto end; } ctx->au_buffer.data = buffer; @@ -128,6 +195,9 @@ static int evc_frame_merge_filter(AVBSFContext *bsf, AVPacket *out) if (err < 0 && err != AVERROR(EAGAIN)) ctx->au_buffer.data_size = 0; +end: + if (err < 0) + av_packet_unref(in); return err; } @@ -147,7 +217,7 @@ static void evc_frame_merge_close(AVBSFContext *bsf) EVCFMergeContext *ctx = bsf->priv_data; av_packet_free(&ctx->in); - ff_evc_ps_free(&ctx->parser_ctx.ps); + ff_evc_ps_free(&ctx->ps); ctx->au_buffer.capacity = 0; av_freep(&ctx->au_buffer.data); From 5cb9ef93000048afe29ce1c67f151ad3fffcd83a Mon Sep 17 00:00:00 2001 From: James Almer Date: Sat, 17 Jun 2023 18:44:12 -0300 Subject: [PATCH 1569/2172] avcodec/evc_parse: remove ff_evc_parse_nal_unit() Signed-off-by: James Almer --- libavcodec/evc_parse.c | 182 ---------------------------------------- libavcodec/evc_parse.h | 42 ---------- libavcodec/evc_parser.c | 7 ++ 3 files changed, 7 insertions(+), 224 deletions(-) diff --git a/libavcodec/evc_parse.c b/libavcodec/evc_parse.c index 0ad0d821379..18827ffa635 100644 --- a/libavcodec/evc_parse.c +++ b/libavcodec/evc_parse.c @@ -21,32 +21,6 @@ #include "evc.h" #include "evc_parse.h" -#define NUM_CHROMA_FORMATS 4 // @see ISO_IEC_23094-1 section 6.2 table 2 - -static const enum AVPixelFormat pix_fmts_8bit[NUM_CHROMA_FORMATS] = { - AV_PIX_FMT_GRAY8, AV_PIX_FMT_YUV420P, AV_PIX_FMT_YUV422P, AV_PIX_FMT_YUV444P -}; - -static const enum AVPixelFormat pix_fmts_9bit[NUM_CHROMA_FORMATS] = { - AV_PIX_FMT_GRAY9, AV_PIX_FMT_YUV420P9, AV_PIX_FMT_YUV422P9, AV_PIX_FMT_YUV444P9 -}; - -static const enum AVPixelFormat pix_fmts_10bit[NUM_CHROMA_FORMATS] = { - AV_PIX_FMT_GRAY10, AV_PIX_FMT_YUV420P10, AV_PIX_FMT_YUV422P10, AV_PIX_FMT_YUV444P10 -}; - -static const enum AVPixelFormat pix_fmts_12bit[NUM_CHROMA_FORMATS] = { - AV_PIX_FMT_GRAY12, AV_PIX_FMT_YUV420P12, AV_PIX_FMT_YUV422P12, AV_PIX_FMT_YUV444P12 -}; - -static const enum AVPixelFormat pix_fmts_14bit[NUM_CHROMA_FORMATS] = { - AV_PIX_FMT_GRAY14, AV_PIX_FMT_YUV420P14, AV_PIX_FMT_YUV422P14, AV_PIX_FMT_YUV444P14 -}; - -static const enum AVPixelFormat pix_fmts_16bit[NUM_CHROMA_FORMATS] = { - AV_PIX_FMT_GRAY16, AV_PIX_FMT_YUV420P16, AV_PIX_FMT_YUV422P16, AV_PIX_FMT_YUV444P16 -}; - // nuh_temporal_id specifies a temporal identifier for the NAL unit int ff_evc_get_temporal_id(const uint8_t *bits, int bits_size, void *logctx) { @@ -258,159 +232,3 @@ int ff_evc_derive_poc(const EVCParamSets *ps, const EVCParserSliceHeader *sh, return 0; } - -int ff_evc_parse_nal_unit(EVCParserContext *ctx, const uint8_t *buf, int buf_size, void *logctx) -{ - int nalu_type, nalu_size; - int tid; - const uint8_t *data = buf; - int data_size = buf_size; - - // ctx->picture_structure = AV_PICTURE_STRUCTURE_FRAME; - ctx->key_frame = -1; - - nalu_size = buf_size; - if (nalu_size <= 0) { - av_log(logctx, AV_LOG_ERROR, "Invalid NAL unit size: (%d)\n", nalu_size); - return AVERROR_INVALIDDATA; - } - - // @see ISO_IEC_23094-1_2020, 7.4.2.2 NAL unit header semantic (Table 4 - NAL unit type codes and NAL unit type classes) - // @see enum EVCNALUnitType in evc.h - nalu_type = evc_get_nalu_type(data, data_size, logctx); - if (nalu_type < EVC_NOIDR_NUT || nalu_type > EVC_UNSPEC_NUT62) { - av_log(logctx, AV_LOG_ERROR, "Invalid NAL unit type: (%d)\n", nalu_type); - return AVERROR_INVALIDDATA; - } - ctx->nalu_type = nalu_type; - - tid = ff_evc_get_temporal_id(data, data_size, logctx); - if (tid < 0) { - av_log(logctx, AV_LOG_ERROR, "Invalid temporial id: (%d)\n", tid); - return AVERROR_INVALIDDATA; - } - ctx->nuh_temporal_id = tid; - - data += EVC_NALU_HEADER_SIZE; - data_size -= EVC_NALU_HEADER_SIZE; - - switch(nalu_type) { - case EVC_SPS_NUT: { - EVCParserSPS *sps; - int bit_depth; - - sps = ff_evc_parse_sps(&ctx->ps, data, nalu_size); - if (!sps) { - av_log(logctx, AV_LOG_ERROR, "SPS parsing error\n"); - return AVERROR_INVALIDDATA; - } - - ctx->coded_width = sps->pic_width_in_luma_samples; - ctx->coded_height = sps->pic_height_in_luma_samples; - - if(sps->picture_cropping_flag) { - ctx->width = sps->pic_width_in_luma_samples - sps->picture_crop_left_offset - sps->picture_crop_right_offset; - ctx->height = sps->pic_height_in_luma_samples - sps->picture_crop_top_offset - sps->picture_crop_bottom_offset; - } else { - ctx->width = sps->pic_width_in_luma_samples; - ctx->height = sps->pic_height_in_luma_samples; - } - - if (sps->profile_idc == 1) ctx->profile = FF_PROFILE_EVC_MAIN; - else ctx->profile = FF_PROFILE_EVC_BASELINE; - - if (sps->vui_parameters_present_flag && sps->vui_parameters.timing_info_present_flag) { - int64_t num = sps->vui_parameters.num_units_in_tick; - int64_t den = sps->vui_parameters.time_scale; - if (num != 0 && den != 0) - av_reduce(&ctx->framerate.den, &ctx->framerate.num, num, den, 1 << 30); - } else - ctx->framerate = (AVRational) { 0, 1 }; - - bit_depth = sps->bit_depth_chroma_minus8 + 8; - ctx->format = AV_PIX_FMT_NONE; - - switch (bit_depth) { - case 8: - ctx->format = pix_fmts_8bit[sps->chroma_format_idc]; - break; - case 9: - ctx->format = pix_fmts_9bit[sps->chroma_format_idc]; - break; - case 10: - ctx->format = pix_fmts_10bit[sps->chroma_format_idc]; - break; - case 12: - ctx->format = pix_fmts_12bit[sps->chroma_format_idc]; - break; - case 14: - ctx->format = pix_fmts_14bit[sps->chroma_format_idc]; - break; - case 16: - ctx->format = pix_fmts_16bit[sps->chroma_format_idc]; - break; - } - av_assert0(ctx->format != AV_PIX_FMT_NONE); - - break; - } - case EVC_PPS_NUT: { - EVCParserPPS *pps; - - pps = ff_evc_parse_pps(&ctx->ps, data, nalu_size); - if (!pps) { - av_log(logctx, AV_LOG_ERROR, "PPS parsing error\n"); - return AVERROR_INVALIDDATA; - } - break; - } - case EVC_SEI_NUT: // Supplemental Enhancement Information - case EVC_APS_NUT: // Adaptation parameter set - case EVC_FD_NUT: // Filler data - break; - case EVC_IDR_NUT: // Coded slice of a IDR or non-IDR picture - case EVC_NOIDR_NUT: { - EVCParserSliceHeader sh; - int ret; - - ret = ff_evc_parse_slice_header(&sh, &ctx->ps, nalu_type, data, nalu_size); - if (ret < 0) { - av_log(logctx, AV_LOG_ERROR, "Slice header parsing error\n"); - return ret; - } - - switch (sh.slice_type) { - case EVC_SLICE_TYPE_B: { - ctx->pict_type = AV_PICTURE_TYPE_B; - break; - } - case EVC_SLICE_TYPE_P: { - ctx->pict_type = AV_PICTURE_TYPE_P; - break; - } - case EVC_SLICE_TYPE_I: { - ctx->pict_type = AV_PICTURE_TYPE_I; - break; - } - default: { - ctx->pict_type = AV_PICTURE_TYPE_NONE; - } - } - - ctx->key_frame = (nalu_type == EVC_IDR_NUT) ? 1 : 0; - - // POC (picture order count of the current picture) derivation - // @see ISO/IEC 23094-1:2020(E) 8.3.1 Decoding process for picture order count - ret = ff_evc_derive_poc(&ctx->ps, &sh, &ctx->poc, nalu_type, tid); - if (ret < 0) - return ret; - - ctx->output_picture_number = ctx->poc.PicOrderCntVal; - ctx->key_frame = (nalu_type == EVC_IDR_NUT) ? 1 : 0; - - break; - } - } - - return 0; -} diff --git a/libavcodec/evc_parse.h b/libavcodec/evc_parse.h index f31075ff9c9..a1fbbc643dc 100644 --- a/libavcodec/evc_parse.h +++ b/libavcodec/evc_parse.h @@ -81,46 +81,6 @@ typedef struct EVCParserPoc { int DocOffset; // the decoding order count of the previous picture } EVCParserPoc; -typedef struct EVCParserContext { - EVCParamSets ps; - EVCParserPoc poc; - - int nuh_temporal_id; // the value of TemporalId (shall be the same for all VCL NAL units of an Access Unit) - int nalu_type; // the current NALU type - - // Dimensions of the decoded video intended for presentation. - int width; - int height; - - // Dimensions of the coded video. - int coded_width; - int coded_height; - - // The format of the coded data, corresponds to enum AVPixelFormat - int format; - - // AV_PICTURE_TYPE_I, EVC_SLICE_TYPE_P, AV_PICTURE_TYPE_B - int pict_type; - - // Set by parser to 1 for key frames and 0 for non-key frames - int key_frame; - - // Picture number incremented in presentation or output order. - // This corresponds to EVCEVCParserPoc::PicOrderCntVal - int output_picture_number; - - // profile - // 0: FF_PROFILE_EVC_BASELINE - // 1: FF_PROFILE_EVC_MAIN - int profile; - - // Framerate value in the compressed bitstream - AVRational framerate; - - int parsed_extradata; - -} EVCParserContext; - static inline int evc_get_nalu_type(const uint8_t *bits, int bits_size, void *logctx) { int unit_type_plus1 = 0; @@ -157,8 +117,6 @@ static inline uint32_t evc_read_nal_unit_length(const uint8_t *bits, int bits_si // nuh_temporal_id specifies a temporal identifier for the NAL unit int ff_evc_get_temporal_id(const uint8_t *bits, int bits_size, void *logctx); -int ff_evc_parse_nal_unit(EVCParserContext *ctx, const uint8_t *buf, int buf_size, void *logctx); - int ff_evc_parse_slice_header(EVCParserSliceHeader *sh, const EVCParamSets *ps, enum EVCNALUnitType nalu_type, const uint8_t *buf, int buf_size); diff --git a/libavcodec/evc_parser.c b/libavcodec/evc_parser.c index c30da6846e1..710fabccb2e 100644 --- a/libavcodec/evc_parser.c +++ b/libavcodec/evc_parser.c @@ -25,6 +25,13 @@ #include "evc.h" #include "evc_parse.h" +typedef struct EVCParserContext { + EVCParamSets ps; + EVCParserPoc poc; + + int parsed_extradata; +} EVCParserContext; + #define NUM_CHROMA_FORMATS 4 // @see ISO_IEC_23094-1 section 6.2 table 2 static const enum AVPixelFormat pix_fmts_8bit[NUM_CHROMA_FORMATS] = { From 921596e677e7b3617f70a21d7188f8bc0f314328 Mon Sep 17 00:00:00 2001 From: James Almer Date: Sun, 18 Jun 2023 20:29:16 -0300 Subject: [PATCH 1570/2172] avcodec/evc_ps: make ff_evc_parse_{sps,pps} return an error code Signed-off-by: James Almer --- libavcodec/evc_frame_merge_bsf.c | 16 ++++------ libavcodec/evc_parser.c | 20 ++++++------ libavcodec/evc_ps.c | 54 ++++++++++++++++++-------------- libavcodec/evc_ps.h | 4 +-- 4 files changed, 48 insertions(+), 46 deletions(-) diff --git a/libavcodec/evc_frame_merge_bsf.c b/libavcodec/evc_frame_merge_bsf.c index 817136a551c..8e7ce9a2ab9 100644 --- a/libavcodec/evc_frame_merge_bsf.c +++ b/libavcodec/evc_frame_merge_bsf.c @@ -120,24 +120,20 @@ static int evc_frame_merge_filter(AVBSFContext *bsf, AVPacket *out) nalu_size -= EVC_NALU_HEADER_SIZE; switch (nalu_type) { - case EVC_SPS_NUT: { - EVCParserSPS *sps = ff_evc_parse_sps(&ctx->ps, nalu, nalu_size); - if (!sps) { + case EVC_SPS_NUT: + err = ff_evc_parse_sps(&ctx->ps, nalu, nalu_size); + if (err < 0) { av_log(bsf, AV_LOG_ERROR, "SPS parsing error\n"); - err = AVERROR_INVALIDDATA; goto end; } break; - } - case EVC_PPS_NUT: { - EVCParserPPS *pps = ff_evc_parse_pps(&ctx->ps, nalu, nalu_size); - if (!pps) { + case EVC_PPS_NUT: + err = ff_evc_parse_pps(&ctx->ps, nalu, nalu_size); + if (err < 0) { av_log(bsf, AV_LOG_ERROR, "PPS parsing error\n"); - err = AVERROR_INVALIDDATA; goto end; } break; - } case EVC_IDR_NUT: // Coded slice of a IDR or non-IDR picture case EVC_NOIDR_NUT: { EVCParserSliceHeader sh; diff --git a/libavcodec/evc_parser.c b/libavcodec/evc_parser.c index 710fabccb2e..5c8fcc5970f 100644 --- a/libavcodec/evc_parser.c +++ b/libavcodec/evc_parser.c @@ -63,6 +63,7 @@ static int parse_nal_unit(AVCodecParserContext *s, AVCodecContext *avctx, { EVCParserContext *ctx = s->priv_data; int nalu_type, tid; + int ret; if (buf_size <= 0) { av_log(avctx, AV_LOG_ERROR, "Invalid NAL unit size: (%d)\n", buf_size); @@ -87,29 +88,26 @@ static int parse_nal_unit(AVCodecParserContext *s, AVCodecContext *avctx, buf_size -= EVC_NALU_HEADER_SIZE; switch (nalu_type) { - case EVC_SPS_NUT: { - EVCParserSPS *sps = ff_evc_parse_sps(&ctx->ps, buf, buf_size); - if (!sps) { + case EVC_SPS_NUT: + ret = ff_evc_parse_sps(&ctx->ps, buf, buf_size); + if (ret < 0) { av_log(avctx, AV_LOG_ERROR, "SPS parsing error\n"); - return AVERROR_INVALIDDATA; + return ret; } break; - } - case EVC_PPS_NUT: { - EVCParserPPS *pps = ff_evc_parse_pps(&ctx->ps, buf, buf_size); - if (!pps) { + case EVC_PPS_NUT: + ret = ff_evc_parse_pps(&ctx->ps, buf, buf_size); + if (ret < 0) { av_log(avctx, AV_LOG_ERROR, "PPS parsing error\n"); - return AVERROR_INVALIDDATA; + return ret; } break; - } case EVC_IDR_NUT: // Coded slice of a IDR or non-IDR picture case EVC_NOIDR_NUT: { const EVCParserPPS *pps; const EVCParserSPS *sps; EVCParserSliceHeader sh; int bit_depth; - int ret; ret = ff_evc_parse_slice_header(&sh, &ctx->ps, nalu_type, buf, buf_size); if (ret < 0) { diff --git a/libavcodec/evc_ps.c b/libavcodec/evc_ps.c index af74ba46b0f..b8d7329b945 100644 --- a/libavcodec/evc_ps.c +++ b/libavcodec/evc_ps.c @@ -132,26 +132,26 @@ static int vui_parameters(GetBitContext *gb, VUIParameters *vui) } // @see ISO_IEC_23094-1 (7.3.2.1 SPS RBSP syntax) -EVCParserSPS *ff_evc_parse_sps(EVCParamSets *ps, const uint8_t *bs, int bs_size) +int ff_evc_parse_sps(EVCParamSets *ps, const uint8_t *bs, int bs_size) { GetBitContext gb; EVCParserSPS *sps; int sps_seq_parameter_set_id; + int ret; - if (init_get_bits8(&gb, bs, bs_size) < 0) - return NULL; + ret = init_get_bits8(&gb, bs, bs_size); + if (ret < 0) + return ret; sps_seq_parameter_set_id = get_ue_golomb(&gb); if (sps_seq_parameter_set_id >= EVC_MAX_SPS_COUNT) - return NULL; + return AVERROR_INVALIDDATA; - if(!ps->sps[sps_seq_parameter_set_id]) { - if((ps->sps[sps_seq_parameter_set_id] = av_malloc(sizeof(EVCParserSPS))) == NULL) - return NULL; - } + sps = av_malloc(sizeof(*sps)); + if (!sps) + return AVERROR(ENOMEM); - sps = ps->sps[sps_seq_parameter_set_id]; memset(sps, 0, sizeof(*sps)); sps->sps_seq_parameter_set_id = sps_seq_parameter_set_id; @@ -284,7 +284,10 @@ EVCParserSPS *ff_evc_parse_sps(EVCParamSets *ps, const uint8_t *bs, int bs_size) // If necessary, add the missing fields to the EVCParserSPS structure // and then extend parser implementation - return sps; + av_freep(&ps->sps[sps_seq_parameter_set_id]); + ps->sps[sps_seq_parameter_set_id] = sps; + + return 0; } // @see ISO_IEC_23094-1 (7.3.2.2 SPS RBSP syntax) @@ -294,34 +297,33 @@ EVCParserSPS *ff_evc_parse_sps(EVCParamSets *ps, const uint8_t *bs, int bs_size) // If it will be needed, parse_sps function could be extended to handle VUI parameters parsing // to initialize fields of the AVCodecContex i.e. color_primaries, color_trc,color_range // -EVCParserPPS *ff_evc_parse_pps(EVCParamSets *ps, const uint8_t *bs, int bs_size) +int ff_evc_parse_pps(EVCParamSets *ps, const uint8_t *bs, int bs_size) { GetBitContext gb; EVCParserPPS *pps; - int pps_pic_parameter_set_id; + int ret; - if (init_get_bits8(&gb, bs, bs_size) < 0) - return NULL; + ret = init_get_bits8(&gb, bs, bs_size); + if (ret < 0) + return ret; pps_pic_parameter_set_id = get_ue_golomb(&gb); if (pps_pic_parameter_set_id > EVC_MAX_PPS_COUNT) - return NULL; + return AVERROR_INVALIDDATA; - if(!ps->pps[pps_pic_parameter_set_id]) { - if ((ps->pps[pps_pic_parameter_set_id] = av_malloc(sizeof(EVCParserPPS))) == NULL) - return NULL; - } + pps = av_malloc(sizeof(*pps)); + if (!pps) + return AVERROR(ENOMEM); - pps = ps->pps[pps_pic_parameter_set_id]; memset(pps, 0, sizeof(*pps)); pps->pps_pic_parameter_set_id = pps_pic_parameter_set_id; pps->pps_seq_parameter_set_id = get_ue_golomb(&gb); if (pps->pps_seq_parameter_set_id >= EVC_MAX_SPS_COUNT) { - av_freep(&ps->pps[pps_pic_parameter_set_id]); - return NULL; + ret = AVERROR_INVALIDDATA; + goto fail; } pps->num_ref_idx_default_active_minus1[0] = get_ue_golomb(&gb); @@ -369,7 +371,13 @@ EVCParserPPS *ff_evc_parse_pps(EVCParamSets *ps, const uint8_t *bs, int bs_size) if (pps->cu_qp_delta_enabled_flag) pps->log2_cu_qp_delta_area_minus6 = get_ue_golomb(&gb); - return pps; + av_freep(&ps->pps[pps_pic_parameter_set_id]); + ps->pps[pps_pic_parameter_set_id] = pps; + + return 0; +fail: + av_free(pps); + return ret; } void ff_evc_ps_free(EVCParamSets *ps) { diff --git a/libavcodec/evc_ps.h b/libavcodec/evc_ps.h index 989336079fa..c7ed2af37b3 100644 --- a/libavcodec/evc_ps.h +++ b/libavcodec/evc_ps.h @@ -218,10 +218,10 @@ typedef struct EVCParamSets { } EVCParamSets; // @see ISO_IEC_23094-1 (7.3.2.1 SPS RBSP syntax) -EVCParserSPS *ff_evc_parse_sps(EVCParamSets *ps, const uint8_t *bs, int bs_size); +int ff_evc_parse_sps(EVCParamSets *ps, const uint8_t *bs, int bs_size); // @see ISO_IEC_23094-1 (7.3.2.2 SPS RBSP syntax) -EVCParserPPS *ff_evc_parse_pps(EVCParamSets *ps, const uint8_t *bs, int bs_size); +int ff_evc_parse_pps(EVCParamSets *ps, const uint8_t *bs, int bs_size); void ff_evc_ps_free(EVCParamSets *ps); From 89f98acbf8dd84cfcd357cc67e8e8b8c25f98a38 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Sun, 18 Jun 2023 23:50:19 +0200 Subject: [PATCH 1571/2172] avcodec/evc_ps: Check log2_sub_gop_length Fixes: 1.70141e+38 is outside the range of representable values of type 'int' Fixes: 59883/clusterfuzz-testcase-minimized-ffmpeg_BSF_EVC_FRAME_MERGE_fuzzer-5557887217565696 Found-by: continuous fuzzing process https://github.com/google/oss-fuzz/tree/master/projects/ffmpeg Signed-off-by: Michael Niedermayer Signed-off-by: James Almer --- libavcodec/evc_ps.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/libavcodec/evc_ps.c b/libavcodec/evc_ps.c index b8d7329b945..0b8cc81d492 100644 --- a/libavcodec/evc_ps.c +++ b/libavcodec/evc_ps.c @@ -229,6 +229,10 @@ int ff_evc_parse_sps(EVCParamSets *ps, const uint8_t *bs, int bs_size) if (!sps->sps_pocs_flag || !sps->sps_rpl_flag) { sps->log2_sub_gop_length = get_ue_golomb(&gb); + if (sps->log2_sub_gop_length > 5U) { + ret = AVERROR_INVALIDDATA; + goto fail; + } if (sps->log2_sub_gop_length == 0) sps->log2_ref_pic_gap_length = get_ue_golomb(&gb); } @@ -288,6 +292,9 @@ int ff_evc_parse_sps(EVCParamSets *ps, const uint8_t *bs, int bs_size) ps->sps[sps_seq_parameter_set_id] = sps; return 0; +fail: + av_free(sps); + return ret; } // @see ISO_IEC_23094-1 (7.3.2.2 SPS RBSP syntax) From 199fc04d09c0ba44418aefe7787ec5f9ef2fa810 Mon Sep 17 00:00:00 2001 From: James Almer Date: Mon, 19 Jun 2023 16:25:13 -0300 Subject: [PATCH 1572/2172] avcodec/evc_ps: use get_bits_long() where needed Signed-off-by: James Almer --- libavcodec/evc_ps.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libavcodec/evc_ps.c b/libavcodec/evc_ps.c index 0b8cc81d492..8d895d228bc 100644 --- a/libavcodec/evc_ps.c +++ b/libavcodec/evc_ps.c @@ -104,8 +104,8 @@ static int vui_parameters(GetBitContext *gb, VUIParameters *vui) vui->timing_info_present_flag = get_bits(gb, 1); if (vui->timing_info_present_flag) { - vui->num_units_in_tick = get_bits(gb, 32); - vui->time_scale = get_bits(gb, 32); + vui->num_units_in_tick = get_bits_long(gb, 32); + vui->time_scale = get_bits_long(gb, 32); vui->fixed_pic_rate_flag = get_bits(gb, 1); } vui->nal_hrd_parameters_present_flag = get_bits(gb, 1); From 377da83b995ade45c31af7278a6502ee39ca1a10 Mon Sep 17 00:00:00 2001 From: James Almer Date: Mon, 19 Jun 2023 16:33:08 -0300 Subject: [PATCH 1573/2172] avcodec/evc_ps: check valid range for a few more elements Should prevent overreads on non spec comformant input. Signed-off-by: James Almer --- libavcodec/evc_ps.c | 22 ++++++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) diff --git a/libavcodec/evc_ps.c b/libavcodec/evc_ps.c index 8d895d228bc..075e705d3db 100644 --- a/libavcodec/evc_ps.c +++ b/libavcodec/evc_ps.c @@ -224,8 +224,13 @@ int ff_evc_parse_sps(EVCParamSets *ps, const uint8_t *bs, int bs_size) sps->sps_dquant_flag = get_bits(&gb, 1); sps->sps_dra_flag = get_bits(&gb, 1); - if (sps->sps_pocs_flag) + if (sps->sps_pocs_flag) { sps->log2_max_pic_order_cnt_lsb_minus4 = get_ue_golomb(&gb); + if (sps->log2_max_pic_order_cnt_lsb_minus4 > 12U) { + ret = AVERROR_INVALIDDATA; + goto fail; + } + } if (!sps->sps_pocs_flag || !sps->sps_rpl_flag) { sps->log2_sub_gop_length = get_ue_golomb(&gb); @@ -271,7 +276,11 @@ int ff_evc_parse_sps(EVCParamSets *ps, const uint8_t *bs, int bs_size) sps->chroma_qp_table_struct.same_qp_table_for_chroma = get_bits(&gb, 1); sps->chroma_qp_table_struct.global_offset_flag = get_bits(&gb, 1); for (int i = 0; i < (sps->chroma_qp_table_struct.same_qp_table_for_chroma ? 1 : 2); i++) { - sps->chroma_qp_table_struct.num_points_in_qp_table_minus1[i] = get_ue_golomb(&gb);; + sps->chroma_qp_table_struct.num_points_in_qp_table_minus1[i] = get_ue_golomb(&gb); + if (sps->chroma_qp_table_struct.num_points_in_qp_table_minus1[i] >= EVC_MAX_QP_TABLE_SIZE) { + ret = AVERROR_INVALIDDATA; + goto fail; + } for (int j = 0; j <= sps->chroma_qp_table_struct.num_points_in_qp_table_minus1[i]; j++) { sps->chroma_qp_table_struct.delta_qp_in_val_minus1[i][j] = get_bits(&gb, 6); sps->chroma_qp_table_struct.delta_qp_out_val[i][j] = get_se_golomb(&gb); @@ -342,6 +351,11 @@ int ff_evc_parse_pps(EVCParamSets *ps, const uint8_t *bs, int bs_size) if (!pps->single_tile_in_pic_flag) { pps->num_tile_columns_minus1 = get_ue_golomb(&gb); pps->num_tile_rows_minus1 = get_ue_golomb(&gb); + if (pps->num_tile_columns_minus1 >= EVC_MAX_TILE_COLUMNS || + pps->num_tile_rows_minus1 >= EVC_MAX_TILE_ROWS) { + ret = AVERROR_INVALIDDATA; + goto fail; + } pps->uniform_tile_spacing_flag = get_bits(&gb, 1); if (!pps->uniform_tile_spacing_flag) { @@ -356,6 +370,10 @@ int ff_evc_parse_pps(EVCParamSets *ps, const uint8_t *bs, int bs_size) } pps->tile_id_len_minus1 = get_ue_golomb(&gb); + if (pps->tile_id_len_minus1 > 15U) { + ret = AVERROR_INVALIDDATA; + goto fail; + } pps->explicit_tile_id_flag = get_bits(&gb, 1); if (pps->explicit_tile_id_flag) { From 048b8bdd5eb4add7ba839b98ed717fe85b890c50 Mon Sep 17 00:00:00 2001 From: James Almer Date: Mon, 19 Jun 2023 16:36:25 -0300 Subject: [PATCH 1574/2172] avformat/evc: use get_bits_long() where needed Signed-off-by: James Almer --- libavformat/evc.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libavformat/evc.c b/libavformat/evc.c index ba949ebf6e5..a194da1c39e 100644 --- a/libavformat/evc.c +++ b/libavformat/evc.c @@ -134,8 +134,8 @@ static int evcc_parse_sps(const uint8_t *bs, int bs_size, EVCDecoderConfiguratio sps.level_idc = get_bits(&gb, 8); - sps.toolset_idc_h = get_bits(&gb, 32); - sps.toolset_idc_l = get_bits(&gb, 32); + sps.toolset_idc_h = get_bits_long(&gb, 32); + sps.toolset_idc_l = get_bits_long(&gb, 32); // 0 - monochrome // 1 - 4:2:0 From e81eafcb974f9d7999889dd6c96cf77b07fde08b Mon Sep 17 00:00:00 2001 From: James Almer Date: Mon, 19 Jun 2023 17:01:41 -0300 Subject: [PATCH 1575/2172] avformat/evc: skip nalu header size bytes before parsing sps Signed-off-by: James Almer --- libavformat/evc.c | 7 +++++++ tests/ref/lavf-fate/evc.mp4 | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/libavformat/evc.c b/libavformat/evc.c index a194da1c39e..79463ba018c 100644 --- a/libavformat/evc.c +++ b/libavformat/evc.c @@ -120,6 +120,9 @@ static int evcc_parse_sps(const uint8_t *bs, int bs_size, EVCDecoderConfiguratio int sps_seq_parameter_set_id; EVCSPS sps; + bs += EVC_NALU_HEADER_SIZE; + bs_size -= EVC_NALU_HEADER_SIZE; + if (init_get_bits8(&gb, bs, bs_size) < 0) return 0; @@ -368,6 +371,10 @@ int ff_isom_write_evcc(AVIOContext *pb, const uint8_t *data, if (bytes_to_read < nalu_size) break; nalu_type = evc_get_nalu_type(data, bytes_to_read, pb); + if (nalu_type < EVC_NOIDR_NUT || nalu_type > EVC_UNSPEC_NUT62) { + ret = AVERROR_INVALIDDATA; + goto end; + } // @see ISO/IEC 14496-15:2021 Coding of audio-visual objects - Part 15: section 12.3.3.3 // NAL_unit_type indicates the type of the NAL units in the following array (which shall be all of that type); diff --git a/tests/ref/lavf-fate/evc.mp4 b/tests/ref/lavf-fate/evc.mp4 index b0afa350aca..4b410b84f32 100644 --- a/tests/ref/lavf-fate/evc.mp4 +++ b/tests/ref/lavf-fate/evc.mp4 @@ -1,3 +1,3 @@ -55294f868fa3b31d34a48344c4f72630 *tests/data/lavf-fate/lavf.evc.mp4 +885fb330b20632b88ef9d7fb03dfa2e9 *tests/data/lavf-fate/lavf.evc.mp4 37386 tests/data/lavf-fate/lavf.evc.mp4 tests/data/lavf-fate/lavf.evc.mp4 CRC=0x48063f85 From 17499f43b15f9130ba44aa257410db9c6db2864b Mon Sep 17 00:00:00 2001 From: James Almer Date: Mon, 19 Jun 2023 17:34:15 -0300 Subject: [PATCH 1576/2172] avformat/evc: remove unused variable And check the correct one. Should fix use of uninitialized value warnings. Signed-off-by: James Almer --- libavformat/evc.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/libavformat/evc.c b/libavformat/evc.c index 79463ba018c..421ff84cb7c 100644 --- a/libavformat/evc.c +++ b/libavformat/evc.c @@ -117,7 +117,6 @@ typedef struct NALUList { static int evcc_parse_sps(const uint8_t *bs, int bs_size, EVCDecoderConfigurationRecord *evcc) { GetBitContext gb; - int sps_seq_parameter_set_id; EVCSPS sps; bs += EVC_NALU_HEADER_SIZE; @@ -128,7 +127,7 @@ static int evcc_parse_sps(const uint8_t *bs, int bs_size, EVCDecoderConfiguratio sps.sps_seq_parameter_set_id = get_ue_golomb_long(&gb); - if (sps_seq_parameter_set_id >= EVC_MAX_SPS_COUNT) + if (sps.sps_seq_parameter_set_id >= EVC_MAX_SPS_COUNT) return 0; // the Baseline profile is indicated by profile_idc eqal to 0 From ba00ed33e56eb737670e10fa3a08e939ece10ee0 Mon Sep 17 00:00:00 2001 From: yethie Date: Mon, 15 May 2023 17:00:30 +0200 Subject: [PATCH 1577/2172] avfilter/vf_drawtext: cosmetics --- libavfilter/vf_drawtext.c | 89 +++++++++++++++++++-------------------- 1 file changed, 44 insertions(+), 45 deletions(-) diff --git a/libavfilter/vf_drawtext.c b/libavfilter/vf_drawtext.c index 71ab851462b..0c4db3ec53b 100644 --- a/libavfilter/vf_drawtext.c +++ b/libavfilter/vf_drawtext.c @@ -78,8 +78,8 @@ static const char *const var_names[] = { "line_h", "lh", ///< line height, same as max_glyph_h "main_h", "h", "H", ///< height of the input video "main_w", "w", "W", ///< width of the input video - "max_glyph_a", "ascent", ///< max glyph ascent - "max_glyph_d", "descent", ///< min glyph descent + "max_glyph_a", "ascent", ///< max glyph ascender + "max_glyph_d", "descent", ///< min glyph descender "max_glyph_h", ///< max glyph height "max_glyph_w", ///< max glyph width "n", ///< number of frame @@ -161,7 +161,7 @@ typedef struct DrawTextContext { int exp_mode; ///< expansion mode to use for the text int reinit; ///< tells if the filter is being reinited #if CONFIG_LIBFONTCONFIG - uint8_t *font; ///< font to be used + uint8_t *font; ///< font to be used #endif uint8_t *fontfile; ///< font to be used uint8_t *text; ///< text to be drawn @@ -227,25 +227,25 @@ typedef struct DrawTextContext { #define FLAGS AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_VIDEO_PARAM static const AVOption drawtext_options[]= { - {"fontfile", "set font file", OFFSET(fontfile), AV_OPT_TYPE_STRING, {.str=NULL}, 0, 0, FLAGS}, - {"text", "set text", OFFSET(text), AV_OPT_TYPE_STRING, {.str=NULL}, 0, 0, FLAGS}, - {"textfile", "set text file", OFFSET(textfile), AV_OPT_TYPE_STRING, {.str=NULL}, 0, 0, FLAGS}, - {"fontcolor", "set foreground color", OFFSET(fontcolor.rgba), AV_OPT_TYPE_COLOR, {.str="black"}, 0, 0, FLAGS}, + {"fontfile", "set font file", OFFSET(fontfile), AV_OPT_TYPE_STRING, {.str=NULL}, 0, 0, FLAGS}, + {"text", "set text", OFFSET(text), AV_OPT_TYPE_STRING, {.str=NULL}, 0, 0, FLAGS}, + {"textfile", "set text file", OFFSET(textfile), AV_OPT_TYPE_STRING, {.str=NULL}, 0, 0, FLAGS}, + {"fontcolor", "set foreground color", OFFSET(fontcolor.rgba), AV_OPT_TYPE_COLOR, {.str="black"}, 0, 0, FLAGS}, {"fontcolor_expr", "set foreground color expression", OFFSET(fontcolor_expr), AV_OPT_TYPE_STRING, {.str=""}, 0, 0, FLAGS}, - {"boxcolor", "set box color", OFFSET(boxcolor.rgba), AV_OPT_TYPE_COLOR, {.str="white"}, 0, 0, FLAGS}, - {"bordercolor", "set border color", OFFSET(bordercolor.rgba), AV_OPT_TYPE_COLOR, {.str="black"}, 0, 0, FLAGS}, - {"shadowcolor", "set shadow color", OFFSET(shadowcolor.rgba), AV_OPT_TYPE_COLOR, {.str="black"}, 0, 0, FLAGS}, - {"box", "set box", OFFSET(draw_box), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1 , FLAGS}, - {"boxborderw", "set box border width", OFFSET(boxborderw), AV_OPT_TYPE_INT, {.i64=0}, INT_MIN, INT_MAX , FLAGS}, - {"line_spacing", "set line spacing in pixels", OFFSET(line_spacing), AV_OPT_TYPE_INT, {.i64=0}, INT_MIN, INT_MAX,FLAGS}, - {"fontsize", "set font size", OFFSET(fontsize_expr), AV_OPT_TYPE_STRING, {.str=NULL}, 0, 0 , FLAGS}, - {"x", "set x expression", OFFSET(x_expr), AV_OPT_TYPE_STRING, {.str="0"}, 0, 0, FLAGS}, - {"y", "set y expression", OFFSET(y_expr), AV_OPT_TYPE_STRING, {.str="0"}, 0, 0, FLAGS}, - {"shadowx", "set shadow x offset", OFFSET(shadowx), AV_OPT_TYPE_INT, {.i64=0}, INT_MIN, INT_MAX , FLAGS}, - {"shadowy", "set shadow y offset", OFFSET(shadowy), AV_OPT_TYPE_INT, {.i64=0}, INT_MIN, INT_MAX , FLAGS}, - {"borderw", "set border width", OFFSET(borderw), AV_OPT_TYPE_INT, {.i64=0}, INT_MIN, INT_MAX , FLAGS}, - {"tabsize", "set tab size", OFFSET(tabsize), AV_OPT_TYPE_INT, {.i64=4}, 0, INT_MAX , FLAGS}, - {"basetime", "set base time", OFFSET(basetime), AV_OPT_TYPE_INT64, {.i64=AV_NOPTS_VALUE}, INT64_MIN, INT64_MAX , FLAGS}, + {"boxcolor", "set box color", OFFSET(boxcolor.rgba), AV_OPT_TYPE_COLOR, {.str="white"}, 0, 0, FLAGS}, + {"bordercolor", "set border color", OFFSET(bordercolor.rgba), AV_OPT_TYPE_COLOR, {.str="black"}, 0, 0, FLAGS}, + {"shadowcolor", "set shadow color", OFFSET(shadowcolor.rgba), AV_OPT_TYPE_COLOR, {.str="black"}, 0, 0, FLAGS}, + {"box", "set box", OFFSET(draw_box), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1, FLAGS}, + {"boxborderw", "set box borders width", OFFSET(boxborderw), AV_OPT_TYPE_INT, {.i64=0}, INT_MIN, INT_MAX, FLAGS}, + {"line_spacing", "set line spacing in pixels", OFFSET(line_spacing), AV_OPT_TYPE_INT, {.i64=0}, INT_MIN, INT_MAX, FLAGS}, + {"fontsize", "set font size", OFFSET(fontsize_expr), AV_OPT_TYPE_STRING, {.str=NULL}, 0, 0, FLAGS}, + {"x", "set x expression", OFFSET(x_expr), AV_OPT_TYPE_STRING, {.str="0"}, 0, 0, FLAGS}, + {"y", "set y expression", OFFSET(y_expr), AV_OPT_TYPE_STRING, {.str="0"}, 0, 0, FLAGS}, + {"shadowx", "set shadow x offset", OFFSET(shadowx), AV_OPT_TYPE_INT, {.i64=0}, INT_MIN, INT_MAX, FLAGS}, + {"shadowy", "set shadow y offset", OFFSET(shadowy), AV_OPT_TYPE_INT, {.i64=0}, INT_MIN, INT_MAX, FLAGS}, + {"borderw", "set border width", OFFSET(borderw), AV_OPT_TYPE_INT, {.i64=0}, INT_MIN, INT_MAX, FLAGS}, + {"tabsize", "set tab size", OFFSET(tabsize), AV_OPT_TYPE_INT, {.i64=4}, 0, INT_MAX, FLAGS}, + {"basetime", "set base time", OFFSET(basetime), AV_OPT_TYPE_INT64, {.i64=AV_NOPTS_VALUE}, INT64_MIN, INT64_MAX, FLAGS}, #if CONFIG_LIBFONTCONFIG { "font", "Font name", OFFSET(font), AV_OPT_TYPE_STRING, { .str = "Sans" }, .flags = FLAGS }, #endif @@ -256,15 +256,15 @@ static const AVOption drawtext_options[]= { {"strftime", "set strftime expansion (deprecated)", OFFSET(exp_mode), AV_OPT_TYPE_CONST, {.i64=EXP_STRFTIME}, 0, 0, FLAGS, "expansion"}, {"timecode", "set initial timecode", OFFSET(tc_opt_string), AV_OPT_TYPE_STRING, {.str=NULL}, 0, 0, FLAGS}, - {"tc24hmax", "set 24 hours max (timecode only)", OFFSET(tc24hmax), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1, FLAGS}, - {"timecode_rate", "set rate (timecode only)", OFFSET(tc_rate), AV_OPT_TYPE_RATIONAL, {.dbl=0}, 0, INT_MAX, FLAGS}, - {"r", "set rate (timecode only)", OFFSET(tc_rate), AV_OPT_TYPE_RATIONAL, {.dbl=0}, 0, INT_MAX, FLAGS}, - {"rate", "set rate (timecode only)", OFFSET(tc_rate), AV_OPT_TYPE_RATIONAL, {.dbl=0}, 0, INT_MAX, FLAGS}, - {"reload", "reload text file at specified frame interval", OFFSET(reload), AV_OPT_TYPE_INT, {.i64=0}, 0, INT_MAX, FLAGS}, - { "alpha", "apply alpha while rendering", OFFSET(a_expr), AV_OPT_TYPE_STRING, { .str = "1" }, .flags = FLAGS }, - {"fix_bounds", "check and fix text coords to avoid clipping", OFFSET(fix_bounds), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1, FLAGS}, - {"start_number", "start frame number for n/frame_num variable", OFFSET(start_number), AV_OPT_TYPE_INT, {.i64=0}, 0, INT_MAX, FLAGS}, - {"text_source", "the source of text", OFFSET(text_source_string), AV_OPT_TYPE_STRING, {.str=NULL}, 0, 1, FLAGS }, + {"tc24hmax", "set 24 hours max (timecode only)", OFFSET(tc24hmax), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1, FLAGS}, + {"timecode_rate", "set rate (timecode only)", OFFSET(tc_rate), AV_OPT_TYPE_RATIONAL, {.dbl=0}, 0, INT_MAX, FLAGS}, + {"r", "set rate (timecode only)", OFFSET(tc_rate), AV_OPT_TYPE_RATIONAL, {.dbl=0}, 0, INT_MAX, FLAGS}, + {"rate", "set rate (timecode only)", OFFSET(tc_rate), AV_OPT_TYPE_RATIONAL, {.dbl=0}, 0, INT_MAX, FLAGS}, + {"reload", "reload text file at specified frame interval", OFFSET(reload), AV_OPT_TYPE_INT, {.i64=0}, 0, INT_MAX, FLAGS}, + {"alpha", "apply alpha while rendering", OFFSET(a_expr), AV_OPT_TYPE_STRING, {.str = "1"}, .flags = FLAGS}, + {"fix_bounds", "check and fix text coords to avoid clipping", OFFSET(fix_bounds), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1, FLAGS}, + {"start_number", "start frame number for n/frame_num variable", OFFSET(start_number), AV_OPT_TYPE_INT, {.i64=0}, 0, INT_MAX, FLAGS}, + {"text_source", "the source of text", OFFSET(text_source_string), AV_OPT_TYPE_STRING, {.str=NULL}, 0, 1, FLAGS }, #if CONFIG_LIBFRIBIDI {"text_shaping", "attempt to shape text before drawing", OFFSET(text_shaping), AV_OPT_TYPE_BOOL, {.i64=1}, 0, 1, FLAGS}, @@ -324,9 +324,9 @@ static int glyph_cmp(const void *key, const void *b) int64_t diff = (int64_t)a->code - (int64_t)bb->code; if (diff != 0) - return diff > 0 ? 1 : -1; + return diff > 0 ? 1 : -1; else - return FFDIFFSIGN((int64_t)a->fontsize, (int64_t)bb->fontsize); + return FFDIFFSIGN((int64_t)a->fontsize, (int64_t)bb->fontsize); } /** @@ -447,7 +447,6 @@ static av_cold int update_fontsize(AVFilterContext *ctx) return err; size = av_expr_eval(s->fontsize_pexpr, s->var_values, &s->prng); - if (!isnan(size)) { roundedsize = round(size); // test for overflow before cast @@ -455,7 +454,6 @@ static av_cold int update_fontsize(AVFilterContext *ctx) av_log(ctx, AV_LOG_ERROR, "fontsize overflow\n"); return AVERROR(EINVAL); } - fontsize = roundedsize; } } @@ -556,7 +554,7 @@ static int load_font_fontconfig(AVFilterContext *ctx) goto fail; } - av_log(ctx, AV_LOG_INFO, "Using \"%s\"\n", filename); + av_log(ctx, AV_LOG_VERBOSE, "Using \"%s\"\n", filename); if (parse_err) s->default_fontsize = size + 0.5; @@ -698,6 +696,7 @@ static int shape_text(AVFilterContext *ctx) s->text = tmp; len = fribidi_unicode_to_charset(FRIBIDI_CHAR_SET_UTF8, unicodestr, len, s->text); + ret = 0; out: @@ -888,15 +887,15 @@ static int config_input(AVFilterLink *inlink) ff_draw_color(&s->dc, &s->bordercolor, s->bordercolor.rgba); ff_draw_color(&s->dc, &s->boxcolor, s->boxcolor.rgba); - s->var_values[VAR_w] = s->var_values[VAR_W] = s->var_values[VAR_MAIN_W] = inlink->w; - s->var_values[VAR_h] = s->var_values[VAR_H] = s->var_values[VAR_MAIN_H] = inlink->h; - s->var_values[VAR_SAR] = inlink->sample_aspect_ratio.num ? av_q2d(inlink->sample_aspect_ratio) : 1; - s->var_values[VAR_DAR] = (double)inlink->w / inlink->h * s->var_values[VAR_SAR]; - s->var_values[VAR_HSUB] = 1 << s->dc.hsub_max; - s->var_values[VAR_VSUB] = 1 << s->dc.vsub_max; - s->var_values[VAR_X] = NAN; - s->var_values[VAR_Y] = NAN; - s->var_values[VAR_T] = NAN; + s->var_values[VAR_w] = s->var_values[VAR_W] = s->var_values[VAR_MAIN_W] = inlink->w; + s->var_values[VAR_h] = s->var_values[VAR_H] = s->var_values[VAR_MAIN_H] = inlink->h; + s->var_values[VAR_SAR] = inlink->sample_aspect_ratio.num ? av_q2d(inlink->sample_aspect_ratio) : 1; + s->var_values[VAR_DAR] = (double)inlink->w / inlink->h * s->var_values[VAR_SAR]; + s->var_values[VAR_HSUB] = 1 << s->dc.hsub_max; + s->var_values[VAR_VSUB] = 1 << s->dc.vsub_max; + s->var_values[VAR_X] = NAN; + s->var_values[VAR_Y] = NAN; + s->var_values[VAR_T] = NAN; av_lfg_init(&s->prng, av_get_random_seed()); @@ -1423,7 +1422,7 @@ static int draw_text(AVFilterContext *ctx, AVFrame *frame, av_bprint_clear(bp); - if(s->basetime != AV_NOPTS_VALUE) + if (s->basetime != AV_NOPTS_VALUE) now= frame->pts*av_q2d(ctx->inputs[0]->time_base) + s->basetime/1000000; switch (s->exp_mode) { From 1eeb59a2099479eeead8cdc0d4586443fb301a8a Mon Sep 17 00:00:00 2001 From: yethie Date: Fri, 26 May 2023 12:11:41 +0200 Subject: [PATCH 1578/2172] avfilter/vf_drawtext: improve glyph shaping and positioning - text is now shaped using libharfbuz - glyphs position is now accurate to 1/4 pixel in both directions - the default line height is now the one defined in the font Adds libharfbuzz dependency. --- configure | 5 +- doc/filters.texi | 8 +- libavfilter/vf_drawtext.c | 859 ++++++++++++++++++++++++++------------ 3 files changed, 592 insertions(+), 280 deletions(-) diff --git a/configure b/configure index 1eb8047cd68..ed9efad9856 100755 --- a/configure +++ b/configure @@ -236,6 +236,7 @@ External library support: --enable-libfontconfig enable libfontconfig, useful for drawtext filter [no] --enable-libfreetype enable libfreetype, needed for drawtext filter [no] --enable-libfribidi enable libfribidi, improves drawtext filter [no] + --enable-libharfbuzz enable libharfbuzz, needed for drawtext filter [no] --enable-libglslang enable GLSL->SPIRV compilation via libglslang [no] --enable-libgme enable Game Music Emu via libgme [no] --enable-libgsm enable GSM de/encoding via libgsm [no] @@ -1859,6 +1860,7 @@ EXTERNAL_LIBRARY_LIST=" libfontconfig libfreetype libfribidi + libharfbuzz libglslang libgme libgsm @@ -3726,7 +3728,7 @@ dilation_opencl_filter_deps="opencl" dnn_classify_filter_select="dnn" dnn_detect_filter_select="dnn" dnn_processing_filter_select="dnn" -drawtext_filter_deps="libfreetype" +drawtext_filter_deps="libfreetype libharfbuzz" drawtext_filter_suggest="libfontconfig libfribidi" elbg_filter_deps="avcodec" eq_filter_deps="gpl" @@ -6693,6 +6695,7 @@ 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 libharfbuzz && require_pkg_config libharfbuzz harfbuzz hb.h hb_buffer_create 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 || diff --git a/doc/filters.texi b/doc/filters.texi index 5e25cf293e5..6d002eaae56 100644 --- a/doc/filters.texi +++ b/doc/filters.texi @@ -12344,7 +12344,7 @@ Draw a text string or text from a specified file on top of a video, using the libfreetype library. To enable compilation of this filter, you need to configure FFmpeg with -@code{--enable-libfreetype}. +@code{--enable-libfreetype} and @code{--enable-libharfbuzz}. To enable default font fallback and the @var{font} option you need to configure FFmpeg with @code{--enable-libfontconfig}. To enable the @var{text_shaping} option, you need to configure FFmpeg with @@ -12372,8 +12372,7 @@ option, check the @ref{color syntax,,"Color" section in the ffmpeg-utils manual, The default value of @var{boxcolor} is "white". @item line_spacing -Set the line spacing in pixels of the border to be drawn around the box using @var{box}. -The default value of @var{line_spacing} is 0. +Set the line spacing in pixels. The default value of @var{line_spacing} is 0. @item borderw Set the width of the border to be drawn around the text using @var{bordercolor}. @@ -12873,6 +12872,9 @@ For more information about fontconfig, check: For more information about libfribidi, check: @url{http://fribidi.org/}. +For more information about libharfbuzz, check: +@url{https://github.com/harfbuzz/harfbuzz}. + @section edgedetect Detect and draw edges. The filter uses the Canny Edge Detection algorithm. diff --git a/libavfilter/vf_drawtext.c b/libavfilter/vf_drawtext.c index 0c4db3ec53b..bdab591efdf 100644 --- a/libavfilter/vf_drawtext.c +++ b/libavfilter/vf_drawtext.c @@ -1,4 +1,5 @@ /* + * Copyright (c) 2023 Francesco Carusi * Copyright (c) 2011 Stefano Sabatini * Copyright (c) 2010 S.N. Hemanth Meenakshisundaram * Copyright (c) 2003 Gustavo Sverzut Barbieri @@ -72,10 +73,16 @@ #include FT_GLYPH_H #include FT_STROKER_H +#include +#include + +// Ceiling operation for positive integers division +#define POS_CEIL(x, y) ((x)/(y) + ((x)%(y) != 0)) + static const char *const var_names[] = { "dar", "hsub", "vsub", - "line_h", "lh", ///< line height, same as max_glyph_h + "line_h", "lh", ///< line height "main_h", "h", "H", ///< height of the input video "main_w", "w", "W", ///< width of the input video "max_glyph_a", "ascent", ///< max glyph ascender @@ -156,6 +163,72 @@ enum expansion_mode { EXP_STRFTIME, }; +typedef struct HarfbuzzData { + hb_buffer_t* buf; + hb_font_t* font; + unsigned int glyph_count; + hb_glyph_info_t* glyph_info; + hb_glyph_position_t* glyph_pos; +} HarfbuzzData; + +/** Information about a single glyph in a text line */ +typedef struct GlyphInfo { + uint32_t code; ///< the glyph code point + int x; ///< the x position of the glyph + int y; ///< the y position of the glyph + int shift_x64; ///< the horizontal shift of the glyph in 26.6 units + int shift_y64; ///< the vertical shift of the glyph in 26.6 units +} GlyphInfo; + +/** Information about a single line of text */ +typedef struct TextLine { + int offset_left64; ///< offset between the origin and + /// the leftmost pixel of the first glyph + int offset_right64; ///< maximum offset between the origin and + /// the rightmost pixel of the last glyph + int width64; ///< width of the line + HarfbuzzData hb_data; ///< libharfbuzz data of this text line + GlyphInfo* glyphs; ///< array of glyphs in this text line + int cluster_offset; ///< the offset at which this line begins +} TextLine; + +/** A glyph as loaded and rendered using libfreetype */ +typedef struct Glyph { + FT_Glyph glyph; + FT_Glyph border_glyph; + uint32_t code; + unsigned int fontsize; + /** Glyph bitmaps with 1/4 pixel precision in both directions */ + FT_BitmapGlyph bglyph[16]; + /** Outlined glyph bitmaps with 1/4 pixel precision in both directions */ + FT_BitmapGlyph border_bglyph[16]; + FT_BBox bbox; +} Glyph; + +/** Global text metrics */ +typedef struct TextMetrics { + int offset_top64; ///< ascender amount of the first line (in 26.6 units) + int offset_bottom64; ///< descender amount of the last line (in 26.6 units) + int offset_left64; ///< maximum offset between the origin and + /// the leftmost pixel of the first glyph + /// of each line (in 26.6 units) + int offset_right64; ///< maximum offset between the origin and + /// the rightmost pixel of the last glyph + /// of each line (in 26.6 units) + int line_height64; ///< the font-defined line height + int width; ///< width of the longest line - ceil(width64/64) + int height; ///< total height of the text - ceil(height64/64) + + int min_y64; ///< minimum value of bbox.yMin among glyphs (in 26.6 units) + int max_y64; ///< maximum value of bbox.yMax among glyphs (in 26.6 units) + int min_x64; ///< minimum value of bbox.xMin among glyphs (in 26.6 units) + int max_x64; ///< maximum value of bbox.xMax among glyphs (in 26.6 units) + + // Position of the background box (without borders) + int rect_x; ///< x position of the box + int rect_y; ///< y position of the box +} TextMetrics; + typedef struct DrawTextContext { const AVClass *class; int exp_mode; ///< expansion mode to use for the text @@ -169,11 +242,9 @@ typedef struct DrawTextContext { uint8_t *fontcolor_expr; ///< fontcolor expression to evaluate AVBPrint expanded_fontcolor; ///< used to contain the expanded fontcolor spec int ft_load_flags; ///< flags used for loading fonts, see FT_LOAD_* - FT_Vector *positions; ///< positions for each element in the text - size_t nb_positions; ///< number of elements of positions array char *textfile; ///< file with text to be drawn - int x; ///< x position to start drawing text - int y; ///< y position to start drawing text + double x; ///< x position to start drawing text + double y; ///< y position to start drawing text int max_glyph_w; ///< max glyph width int max_glyph_h; ///< max glyph height int shadowx, shadowy; @@ -186,7 +257,10 @@ typedef struct DrawTextContext { int line_spacing; ///< lines spacing in pixels short int draw_box; ///< draw box around text - true or false int boxborderw; ///< box border width - int use_kerning; ///< font kerning is used - true/false + int bb_top; ///< the size of the top box border + int bb_right; ///< the size of the right box border + int bb_bottom; ///< the size of the bottom box border + int bb_left; ///< the size of the left box border int tabsize; ///< tab size int fix_bounds; ///< do we let it go out of frame bounds - t/f @@ -221,6 +295,12 @@ typedef struct DrawTextContext { int text_shaping; ///< 1 to shape the text before drawing it #endif AVDictionary *metadata; + + TextLine *lines; ///< computed information about text lines + int line_count; ///< the number of text lines + uint32_t *tab_clusters; ///< the position of tab characters in the text + int tab_count; ///< the number of tab characters + int blank_advance64; ///< the size of the space character } DrawTextContext; #define OFFSET(x) offsetof(DrawTextContext, x) @@ -236,7 +316,7 @@ static const AVOption drawtext_options[]= { {"bordercolor", "set border color", OFFSET(bordercolor.rgba), AV_OPT_TYPE_COLOR, {.str="black"}, 0, 0, FLAGS}, {"shadowcolor", "set shadow color", OFFSET(shadowcolor.rgba), AV_OPT_TYPE_COLOR, {.str="black"}, 0, 0, FLAGS}, {"box", "set box", OFFSET(draw_box), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1, FLAGS}, - {"boxborderw", "set box borders width", OFFSET(boxborderw), AV_OPT_TYPE_INT, {.i64=0}, INT_MIN, INT_MAX, FLAGS}, + {"boxborderw", "set box borders width", OFFSET(boxborderw), AV_OPT_TYPE_INT, {.i64=0}, 0, INT_MAX, FLAGS}, {"line_spacing", "set line spacing in pixels", OFFSET(line_spacing), AV_OPT_TYPE_INT, {.i64=0}, INT_MIN, INT_MAX, FLAGS}, {"fontsize", "set font size", OFFSET(fontsize_expr), AV_OPT_TYPE_STRING, {.str=NULL}, 0, 0, FLAGS}, {"x", "set x expression", OFFSET(x_expr), AV_OPT_TYPE_STRING, {.str="0"}, 0, 0, FLAGS}, @@ -305,19 +385,6 @@ static const struct ft_error { #define FT_ERRMSG(e) ft_errors[e].err_msg -typedef struct Glyph { - FT_Glyph glyph; - FT_Glyph border_glyph; - uint32_t code; - unsigned int fontsize; - FT_Bitmap bitmap; ///< array holding bitmaps of font - FT_Bitmap border_bitmap; ///< array holding bitmaps of font border - FT_BBox bbox; - int advance; - int bitmap_left; - int bitmap_top; -} Glyph; - static int glyph_cmp(const void *key, const void *b) { const Glyph *a = key, *bb = b; @@ -329,77 +396,6 @@ static int glyph_cmp(const void *key, const void *b) return FFDIFFSIGN((int64_t)a->fontsize, (int64_t)bb->fontsize); } -/** - * Load glyphs corresponding to the UTF-32 codepoint code. - */ -static int load_glyph(AVFilterContext *ctx, Glyph **glyph_ptr, uint32_t code) -{ - DrawTextContext *s = ctx->priv; - FT_BitmapGlyph bitmapglyph; - Glyph *glyph; - struct AVTreeNode *node = NULL; - int ret; - - /* load glyph into s->face->glyph */ - if (FT_Load_Char(s->face, code, s->ft_load_flags)) - return AVERROR(EINVAL); - - glyph = av_mallocz(sizeof(*glyph)); - if (!glyph) { - ret = AVERROR(ENOMEM); - goto error; - } - glyph->code = code; - glyph->fontsize = s->fontsize; - - if (FT_Get_Glyph(s->face->glyph, &glyph->glyph)) { - ret = AVERROR(EINVAL); - goto error; - } - if (s->borderw) { - glyph->border_glyph = glyph->glyph; - if (FT_Glyph_StrokeBorder(&glyph->border_glyph, s->stroker, 0, 0) || - FT_Glyph_To_Bitmap(&glyph->border_glyph, FT_RENDER_MODE_NORMAL, 0, 1)) { - ret = AVERROR_EXTERNAL; - goto error; - } - bitmapglyph = (FT_BitmapGlyph) glyph->border_glyph; - glyph->border_bitmap = bitmapglyph->bitmap; - } - if (FT_Glyph_To_Bitmap(&glyph->glyph, FT_RENDER_MODE_NORMAL, 0, 1)) { - ret = AVERROR_EXTERNAL; - goto error; - } - bitmapglyph = (FT_BitmapGlyph) glyph->glyph; - - glyph->bitmap = bitmapglyph->bitmap; - glyph->bitmap_left = bitmapglyph->left; - glyph->bitmap_top = bitmapglyph->top; - glyph->advance = s->face->glyph->advance.x >> 6; - - /* measure text height to calculate text_height (or the maximum text height) */ - FT_Glyph_Get_CBox(glyph->glyph, ft_glyph_bbox_pixels, &glyph->bbox); - - /* cache the newly created glyph */ - if (!(node = av_tree_node_alloc())) { - ret = AVERROR(ENOMEM); - goto error; - } - av_tree_insert(&s->glyphs, glyph, glyph_cmp, &node); - - if (glyph_ptr) - *glyph_ptr = glyph; - return 0; - -error: - if (glyph) - av_freep(&glyph->glyph); - - av_freep(&glyph); - av_freep(&node); - return ret; -} - static av_cold int set_fontsize(AVFilterContext *ctx, unsigned int fontsize) { int err; @@ -718,11 +714,114 @@ static enum AVFrameSideDataType text_source_string_parse(const char *text_source } } +static inline int get_subpixel_idx(int shift_x64, int shift_y64) +{ + int idx = (shift_x64 >> 2) + (shift_y64 >> 4); + return idx; +} + +// Loads and (optionally) renders a glyph +static int load_glyph(AVFilterContext *ctx, Glyph **glyph_ptr, uint32_t code, int8_t shift_x64, int8_t shift_y64) +{ + DrawTextContext *s = ctx->priv; + Glyph dummy = { 0 }; + Glyph *glyph; + FT_Vector shift; + struct AVTreeNode *node = NULL; + int ret = 0; + + /* get glyph */ + dummy.code = code; + dummy.fontsize = s->fontsize; + glyph = av_tree_find(s->glyphs, &dummy, glyph_cmp, NULL); + if (!glyph) { + if (FT_Load_Glyph(s->face, code, s->ft_load_flags)) { + return AVERROR(EINVAL); + } + glyph = av_mallocz(sizeof(*glyph)); + if (!glyph) { + ret = AVERROR(ENOMEM); + goto error; + } + glyph->code = code; + glyph->fontsize = s->fontsize; + if (FT_Get_Glyph(s->face->glyph, &glyph->glyph)) { + ret = AVERROR(EINVAL); + goto error; + } + if (s->borderw) { + glyph->border_glyph = glyph->glyph; + if (FT_Glyph_StrokeBorder(&glyph->border_glyph, s->stroker, 0, 0)) { + ret = AVERROR_EXTERNAL; + goto error; + } + } + /* measure text height to calculate text_height (or the maximum text height) */ + FT_Glyph_Get_CBox(glyph->glyph, FT_GLYPH_BBOX_SUBPIXELS, &glyph->bbox); + + /* cache the newly created glyph */ + if (!(node = av_tree_node_alloc())) { + ret = AVERROR(ENOMEM); + goto error; + } + av_tree_insert(&s->glyphs, glyph, glyph_cmp, &node); + } else { + if (s->borderw && !glyph->border_glyph) { + glyph->border_glyph = glyph->glyph; + if (FT_Glyph_StrokeBorder(&glyph->border_glyph, s->stroker, 0, 0)) { + ret = AVERROR_EXTERNAL; + goto error; + } + } + } + + // Check if a bitmap is needed + if (shift_x64 >= 0 && shift_y64 >= 0) { + // Get the bitmap subpixel index (0 -> 15) + int idx = get_subpixel_idx(shift_x64, shift_y64); + shift.x = shift_x64; + shift.y = shift_y64; + + if (!glyph->bglyph[idx]) { + FT_Glyph tmp_glyph = glyph->glyph; + if (FT_Glyph_To_Bitmap(&tmp_glyph, FT_RENDER_MODE_NORMAL, &shift, 0)) { + ret = AVERROR_EXTERNAL; + goto error; + } + glyph->bglyph[idx] = (FT_BitmapGlyph)tmp_glyph; + if (glyph->bglyph[idx]->bitmap.pixel_mode == FT_PIXEL_MODE_MONO) { + av_log(ctx, AV_LOG_ERROR, "Monocromatic (1bpp) fonts are not supported.\n"); + ret = AVERROR(EINVAL); + goto error; + } + } + if (s->borderw && !glyph->border_bglyph[idx]) { + FT_Glyph tmp_glyph = glyph->border_glyph; + if (FT_Glyph_To_Bitmap(&tmp_glyph, FT_RENDER_MODE_NORMAL, &shift, 0)) { + ret = AVERROR_EXTERNAL; + goto error; + } + glyph->border_bglyph[idx] = (FT_BitmapGlyph)tmp_glyph; + } + } + if (glyph_ptr) { + *glyph_ptr = glyph; + } + return 0; + +error: + if (glyph && glyph->glyph) + FT_Done_Glyph(glyph->glyph); + + av_freep(&glyph); + av_freep(&node); + return ret; +} + static av_cold int init(AVFilterContext *ctx) { int err; DrawTextContext *s = ctx->priv; - Glyph *glyph; av_expr_free(s->fontsize_pexpr); s->fontsize_pexpr = NULL; @@ -811,17 +910,8 @@ static av_cold int init(AVFilterContext *ctx) FT_STROKER_LINEJOIN_ROUND, 0); } - s->use_kerning = FT_HAS_KERNING(s->face); - /* load the fallback glyph with code 0 */ - load_glyph(ctx, NULL, 0); - - /* set the tabsize in pixels */ - if ((err = load_glyph(ctx, &glyph, ' ')) < 0) { - av_log(ctx, AV_LOG_ERROR, "Could not set tabsize.\n"); - return err; - } - s->tabsize *= glyph->advance; + load_glyph(ctx, NULL, 0, 0, 0); if (s->exp_mode == EXP_STRFTIME && (strchr(s->text, '%') || strchr(s->text, '\\'))) @@ -844,6 +934,14 @@ static int glyph_enu_free(void *opaque, void *elem) FT_Done_Glyph(glyph->glyph); FT_Done_Glyph(glyph->border_glyph); + for (int t = 0; t < 16; ++t) { + if (glyph->bglyph[t] != NULL) { + FT_Done_Glyph((FT_Glyph)glyph->bglyph[t]); + } + if (glyph->border_bglyph[t] != NULL) { + FT_Done_Glyph((FT_Glyph)glyph->border_bglyph[t]); + } + } av_free(elem); return 0; } @@ -859,9 +957,6 @@ static av_cold void uninit(AVFilterContext *ctx) s->x_pexpr = s->y_pexpr = s->a_pexpr = s->fontsize_pexpr = NULL; - av_freep(&s->positions); - s->nb_positions = 0; - av_tree_enumerate(s->glyphs, NULL, NULL, glyph_enu_free); av_tree_destroy(s->glyphs); s->glyphs = NULL; @@ -1325,91 +1420,283 @@ static int expand_text(AVFilterContext *ctx, char *text, AVBPrint *bp) return 0; } +static void update_color_with_alpha(DrawTextContext *s, FFDrawColor *color, const FFDrawColor incolor) +{ + *color = incolor; + color->rgba[3] = (color->rgba[3] * s->alpha) / 255; + ff_draw_color(&s->dc, color, color->rgba); +} + +static void update_alpha(DrawTextContext *s) +{ + double alpha = av_expr_eval(s->a_pexpr, s->var_values, &s->prng); + + if (isnan(alpha)) + return; + + if (alpha >= 1.0) + s->alpha = 255; + else if (alpha <= 0) + s->alpha = 0; + else + s->alpha = 256 * alpha; +} + static int draw_glyphs(DrawTextContext *s, AVFrame *frame, - int width, int height, FFDrawColor *color, + TextMetrics *metrics, int x, int y, int borderw) { - char *text = s->expanded_text.str; - uint32_t code = 0; - int i, x1, y1; - uint8_t *p; - Glyph *glyph = NULL; - - for (i = 0, p = text; *p; i++) { - FT_Bitmap bitmap; - Glyph dummy = { 0 }; - GET_UTF8(code, *p ? *p++ : 0, code = 0xfffd; goto continue_on_invalid;); -continue_on_invalid: + int g, l, x1, y1, w1, h1, idx; + int dx = 0, dy = 0, pdx = 0; + GlyphInfo *info; + Glyph dummy = { 0 }, *glyph; + FT_Bitmap bitmap; + FT_BitmapGlyph b_glyph; + int clip_x = 0, clip_y = 0; + + clip_x = FFMIN(metrics->rect_x + metrics->width + s->bb_right, frame->width); + clip_y = FFMIN(metrics->rect_y + metrics->height + s->bb_bottom, frame->height); + + for (l = 0; l < s->line_count; ++l) { + TextLine *line = &s->lines[l]; + for (g = 0; g < line->hb_data.glyph_count; ++g) { + info = &line->glyphs[g]; + dummy.fontsize = s->fontsize; + dummy.code = info->code; + glyph = av_tree_find(s->glyphs, &dummy, glyph_cmp, NULL); + if (!glyph) { + return AVERROR(EINVAL); + } - /* skip new line chars, just go to new line */ - if (code == '\n' || code == '\r' || code == '\t') - continue; + idx = get_subpixel_idx(info->shift_x64, info->shift_y64); + b_glyph = borderw ? glyph->border_bglyph[idx] : glyph->bglyph[idx]; + bitmap = b_glyph->bitmap; + x1 = x + info->x + b_glyph->left; + y1 = y + info->y - b_glyph->top; + w1 = bitmap.width; + h1 = bitmap.rows; + + // Offset of the glyph's bitmap in the visible region + dx = dy = 0; + if (x1 < metrics->rect_x - s->bb_left) { + dx = metrics->rect_x - s->bb_left - x1; + x1 = metrics->rect_x - s->bb_left; + } + if (y1 < metrics->rect_y - s->bb_top) { + dy = metrics->rect_y - s->bb_top - y1; + y1 = metrics->rect_y - s->bb_top; + } - dummy.code = code; - dummy.fontsize = s->fontsize; - glyph = av_tree_find(s->glyphs, &dummy, glyph_cmp, NULL); + // check if the glyph is empty or out of the clipping region + if (dx >= w1 || dy >= h1 || x1 >= clip_x || y1 >= clip_y) { + continue; + } - bitmap = borderw ? glyph->border_bitmap : glyph->bitmap; + pdx = dx + dy * bitmap.pitch; + w1 = FFMIN(clip_x - x1, w1 - dx); + h1 = FFMIN(clip_y - y1, h1 - dy); - if (glyph->bitmap.pixel_mode != FT_PIXEL_MODE_MONO && - glyph->bitmap.pixel_mode != FT_PIXEL_MODE_GRAY) - return AVERROR(EINVAL); + ff_blend_mask(&s->dc, color, frame->data, frame->linesize, clip_x, clip_y, + bitmap.buffer + pdx, bitmap.pitch, w1, h1, 3, 0, x1, y1); + } + } - x1 = s->positions[i].x+s->x+x - borderw; - y1 = s->positions[i].y+s->y+y - borderw; + return 0; +} - ff_blend_mask(&s->dc, color, - frame->data, frame->linesize, width, height, - bitmap.buffer, bitmap.pitch, - bitmap.width, bitmap.rows, - bitmap.pixel_mode == FT_PIXEL_MODE_MONO ? 0 : 3, - 0, x1, y1); +// Shapes a line of text using libharfbuzz +static int shape_text_hb(DrawTextContext *s, HarfbuzzData* hb, const char* text, int textLen) +{ + hb->buf = hb_buffer_create(); + if(!hb_buffer_allocation_successful(hb->buf)) { + return AVERROR(ENOMEM); } + hb_buffer_set_direction(hb->buf, HB_DIRECTION_LTR); + hb_buffer_set_script(hb->buf, HB_SCRIPT_LATIN); + hb_buffer_set_language(hb->buf, hb_language_from_string("en", -1)); + hb_buffer_guess_segment_properties(hb->buf); + hb->font = hb_ft_font_create(s->face, NULL); + if(hb->font == NULL) { + return AVERROR(ENOMEM); + } + hb_ft_font_set_funcs(hb->font); + hb_buffer_add_utf8(hb->buf, text, textLen, 0, -1); + hb_shape(hb->font, hb->buf, NULL, 0); + hb->glyph_info = hb_buffer_get_glyph_infos(hb->buf, &hb->glyph_count); + hb->glyph_pos = hb_buffer_get_glyph_positions(hb->buf, &hb->glyph_count); return 0; } - -static void update_color_with_alpha(DrawTextContext *s, FFDrawColor *color, const FFDrawColor incolor) +static void hb_destroy(HarfbuzzData *hb) { - *color = incolor; - color->rgba[3] = (color->rgba[3] * s->alpha) / 255; - ff_draw_color(&s->dc, color, color->rgba); + hb_buffer_destroy(hb->buf); + hb_font_destroy(hb->font); + hb->buf = NULL; + hb->font = NULL; + hb->glyph_info = NULL; + hb->glyph_pos = NULL; } -static void update_alpha(DrawTextContext *s) +static int measure_text(AVFilterContext *ctx, TextMetrics *metrics) { - double alpha = av_expr_eval(s->a_pexpr, s->var_values, &s->prng); + DrawTextContext *s = ctx->priv; + char *text = s->expanded_text.str; + char *textdup = NULL, *start = NULL; + int num_chars = 0; + int width64 = 0, w64 = 0; + int cur_min_y64 = 0, first_max_y64 = -32000; + int first_min_x64 = 32000, last_max_x64 = -32000; + int min_y64 = 32000, max_y64 = -32000, min_x64 = 32000, max_x64 = -32000; + int line_count = 0; + uint32_t code = 0; + Glyph *glyph = NULL; + int height64; + + int i, tab_idx = 0, last_tab_idx = 0, line_offset = 0; + char* p; + int ret = 0; + + // Count the lines and the tab characters + s->tab_count = 0; + for (i = 0, p = text; 1; i++) { + GET_UTF8(code, *p ? *p++ : 0, code = 0xfffd; goto continue_on_failed;); +continue_on_failed: + if (is_newline(code) || code == 0) { + ++line_count; + if (code == 0) { + break; + } + } else if (code == '\t') { + ++s->tab_count; + } + } - if (isnan(alpha)) - return; + // Evaluate the width of the space character if needed to replace tabs + if (s->tab_count > 0 && !s->blank_advance64) { + HarfbuzzData hb_data; + ret = shape_text_hb(s, &hb_data, " ", 1); + if(ret != 0) { + goto done; + } + s->blank_advance64 = hb_data.glyph_pos[0].x_advance; + hb_destroy(&hb_data); + } - if (alpha >= 1.0) - s->alpha = 255; - else if (alpha <= 0) - s->alpha = 0; - else - s->alpha = 256 * alpha; + s->line_count = line_count; + s->lines = av_mallocz(line_count * sizeof(TextLine)); + s->tab_clusters = av_mallocz(s->tab_count * sizeof(uint32_t)); + for (i = 0; i < s->tab_count; ++i) { + s->tab_clusters[i] = -1; + } + + start = textdup = av_strdup(text); + if (textdup == NULL) { + ret = AVERROR(ENOMEM); + goto done; + } + line_count = 0; + for (i = 0, p = textdup; 1; i++) { + if (*p == '\t') { + s->tab_clusters[tab_idx++] = i; + *p = ' '; + } + GET_UTF8(code, *p ? *p++ : 0, code = 0xfffd; goto continue_on_failed2;); +continue_on_failed2: + if (is_newline(code) || code == 0) { + TextLine *cur_line = &s->lines[line_count]; + HarfbuzzData *hb = &cur_line->hb_data; + cur_line->cluster_offset = line_offset; + ret = shape_text_hb(s, hb, start, num_chars); + if (ret != 0) { + goto done; + } + w64 = 0; + cur_min_y64 = 32000; + for (int t = 0; t < hb->glyph_count; ++t) { + uint8_t is_tab = last_tab_idx < s->tab_count && + hb->glyph_info[t].cluster == s->tab_clusters[last_tab_idx] - line_offset; + if (is_tab) { + ++last_tab_idx; + } + ret = load_glyph(ctx, &glyph, hb->glyph_info[t].codepoint, -1, -1); + if (ret != 0) { + goto done; + } + if (line_count == 0) { + first_max_y64 = FFMAX(glyph->bbox.yMax, first_max_y64); + } + if (t == 0) { + cur_line->offset_left64 = glyph->bbox.xMin; + first_min_x64 = FFMIN(glyph->bbox.xMin, first_min_x64); + } + if (t == hb->glyph_count - 1) { + w64 += glyph->bbox.xMax; + last_max_x64 = FFMAX(glyph->bbox.xMax, last_max_x64); + cur_line->offset_right64 = glyph->bbox.xMax; + } else { + if (is_tab) { + int size = s->blank_advance64 * s->tabsize; + w64 = (w64 / size + 1) * size; + } else { + w64 += hb->glyph_pos[t].x_advance; + } + } + cur_min_y64 = FFMIN(glyph->bbox.yMin, cur_min_y64); + min_y64 = FFMIN(glyph->bbox.yMin, min_y64); + max_y64 = FFMAX(glyph->bbox.yMax, max_y64); + min_x64 = FFMIN(glyph->bbox.xMin, min_x64); + max_x64 = FFMAX(glyph->bbox.xMax, max_x64); + } + + cur_line->width64 = w64; + + av_log(s, AV_LOG_DEBUG, " Line: %d -- glyphs count: %d - width64: %d - offset_left64: %d - offset_right64: %d)\n", + line_count, hb->glyph_count, cur_line->width64, cur_line->offset_left64, cur_line->offset_right64); + + if (w64 > width64) { + width64 = w64; + } + num_chars = -1; + start = p; + ++line_count; + line_offset = i + 1; + } + + if (code == 0) break; + ++num_chars; + } + + metrics->line_height64 = s->face->size->metrics.height; + + metrics->width = POS_CEIL(width64, 64); + height64 = (metrics->line_height64 + s->line_spacing * 64) * + (FFMAX(0, line_count - 1)) + first_max_y64 - cur_min_y64; + metrics->height = POS_CEIL(height64, 64); + + metrics->offset_top64 = first_max_y64; + metrics->offset_right64 = last_max_x64; + metrics->offset_bottom64 = cur_min_y64; + metrics->offset_left64 = first_min_x64; + metrics->min_x64 = min_x64; + metrics->min_y64 = min_y64; + metrics->max_x64 = max_x64; + metrics->max_y64 = max_y64; + +done: + av_free(textdup); + return ret; } -static int draw_text(AVFilterContext *ctx, AVFrame *frame, - int width, int height) +static int draw_text(AVFilterContext *ctx, AVFrame *frame) { DrawTextContext *s = ctx->priv; AVFilterLink *inlink = ctx->inputs[0]; - - uint32_t code = 0, prev_code = 0; - int x = 0, y = 0, i = 0, ret; - int max_text_line_w = 0, len; - int box_w, box_h; - char *text; - uint8_t *p; - int y_min = 32000, y_max = -32000; - int x_min = 32000, x_max = -32000; - FT_Vector delta; - Glyph *glyph = NULL, *prev_glyph = NULL; - Glyph dummy = { 0 }; + int x = 0, y = 0, ret; + int shift_x64, shift_y64; + int x64, y64; + Glyph *glyph = NULL; time_t now = time(0); struct tm ltime; @@ -1420,6 +1707,14 @@ static int draw_text(AVFilterContext *ctx, AVFrame *frame, FFDrawColor bordercolor; FFDrawColor boxcolor; + int width = frame->width; + int height = frame->height; + int rec_x = 0, rec_y = 0, rec_width = 0, rec_height = 0; + int is_outside = 0; + int last_tab_idx = 0; + + TextMetrics metrics; + av_bprint_clear(bp); if (s->basetime != AV_NOPTS_VALUE) @@ -1448,13 +1743,6 @@ static int draw_text(AVFilterContext *ctx, AVFrame *frame, if (!av_bprint_is_complete(bp)) return AVERROR(ENOMEM); - text = s->expanded_text.str; - if ((len = s->expanded_text.len) > s->nb_positions) { - if (!(s->positions = - av_realloc(s->positions, len*sizeof(*s->positions)))) - return AVERROR(ENOMEM); - s->nb_positions = len; - } if (s->fontcolor_expr[0]) { /* If expression is set, evaluate and replace the static value */ @@ -1470,85 +1758,26 @@ static int draw_text(AVFilterContext *ctx, AVFrame *frame, ff_draw_color(&s->dc, &s->fontcolor, s->fontcolor.rgba); } - x = 0; - y = 0; - - if ((ret = update_fontsize(ctx)) < 0) + if ((ret = update_fontsize(ctx)) < 0) { return ret; - - /* load and cache glyphs */ - for (i = 0, p = text; *p; i++) { - GET_UTF8(code, *p ? *p++ : 0, code = 0xfffd; goto continue_on_invalid;); -continue_on_invalid: - - /* get glyph */ - dummy.code = code; - dummy.fontsize = s->fontsize; - glyph = av_tree_find(s->glyphs, &dummy, glyph_cmp, NULL); - if (!glyph) { - ret = load_glyph(ctx, &glyph, code); - if (ret < 0) - return ret; - } - - y_min = FFMIN(glyph->bbox.yMin, y_min); - y_max = FFMAX(glyph->bbox.yMax, y_max); - x_min = FFMIN(glyph->bbox.xMin, x_min); - x_max = FFMAX(glyph->bbox.xMax, x_max); } - s->max_glyph_h = y_max - y_min; - s->max_glyph_w = x_max - x_min; - - /* compute and save position for each glyph */ - glyph = NULL; - for (i = 0, p = text; *p; i++) { - GET_UTF8(code, *p ? *p++ : 0, code = 0xfffd; goto continue_on_invalid2;); -continue_on_invalid2: - - /* skip the \n in the sequence \r\n */ - if (prev_code == '\r' && code == '\n') - continue; - - prev_code = code; - if (is_newline(code)) { - - max_text_line_w = FFMAX(max_text_line_w, x); - y += s->max_glyph_h + s->line_spacing; - x = 0; - continue; - } - - /* get glyph */ - prev_glyph = glyph; - dummy.code = code; - dummy.fontsize = s->fontsize; - glyph = av_tree_find(s->glyphs, &dummy, glyph_cmp, NULL); - - /* kerning */ - if (s->use_kerning && prev_glyph && glyph->code) { - FT_Get_Kerning(s->face, prev_glyph->code, glyph->code, - ft_kerning_default, &delta); - x += delta.x >> 6; - } - /* save position */ - s->positions[i].x = x + glyph->bitmap_left; - s->positions[i].y = y - glyph->bitmap_top + y_max; - if (code == '\t') x = (x / s->tabsize + 1)*s->tabsize; - else x += glyph->advance; + if ((ret = measure_text(ctx, &metrics)) < 0) { + return ret; } - max_text_line_w = FFMAX(x, max_text_line_w); + s->max_glyph_h = POS_CEIL(metrics.max_y64 - metrics.min_y64, 64); + s->max_glyph_w = POS_CEIL(metrics.max_x64 - metrics.min_x64, 64); - s->var_values[VAR_TW] = s->var_values[VAR_TEXT_W] = max_text_line_w; - s->var_values[VAR_TH] = s->var_values[VAR_TEXT_H] = y + s->max_glyph_h; + s->var_values[VAR_TW] = s->var_values[VAR_TEXT_W] = metrics.width; + s->var_values[VAR_TH] = s->var_values[VAR_TEXT_H] = metrics.height; s->var_values[VAR_MAX_GLYPH_W] = s->max_glyph_w; s->var_values[VAR_MAX_GLYPH_H] = s->max_glyph_h; - s->var_values[VAR_MAX_GLYPH_A] = s->var_values[VAR_ASCENT ] = y_max; - s->var_values[VAR_MAX_GLYPH_D] = s->var_values[VAR_DESCENT] = y_min; + s->var_values[VAR_MAX_GLYPH_A] = s->var_values[VAR_ASCENT] = POS_CEIL(metrics.max_y64, 64); + s->var_values[VAR_MAX_GLYPH_D] = s->var_values[VAR_DESCENT] = POS_CEIL(metrics.min_y64, 64); - s->var_values[VAR_LINE_H] = s->var_values[VAR_LH] = s->max_glyph_h; + s->var_values[VAR_LINE_H] = s->var_values[VAR_LH] = metrics.line_height64 / 64.; if (s->text_source == AV_FRAME_DATA_DETECTION_BBOXES) { s->var_values[VAR_X] = s->x; @@ -1566,56 +1795,139 @@ static int draw_text(AVFilterContext *ctx, AVFrame *frame, update_color_with_alpha(s, &bordercolor, s->bordercolor); update_color_with_alpha(s, &boxcolor , s->boxcolor ); - box_w = max_text_line_w; - box_h = y + s->max_glyph_h; + if (s->draw_box && s->boxborderw) { + s->bb_top = s->bb_right = s->bb_bottom = s->bb_left = s->boxborderw; + } else { + s->bb_top = s->bb_right = s->bb_bottom = s->bb_left = 0; + } if (s->fix_bounds) { - /* calculate footprint of text effects */ - int boxoffset = s->draw_box ? FFMAX(s->boxborderw, 0) : 0; int borderoffset = s->borderw ? FFMAX(s->borderw, 0) : 0; - int offsetleft = FFMAX3(boxoffset, borderoffset, + int offsetleft = FFMAX3(FFMAX(s->bb_left, 0), borderoffset, (s->shadowx < 0 ? FFABS(s->shadowx) : 0)); - int offsettop = FFMAX3(boxoffset, borderoffset, + int offsettop = FFMAX3(FFMAX(s->bb_top, 0), borderoffset, (s->shadowy < 0 ? FFABS(s->shadowy) : 0)); - - int offsetright = FFMAX3(boxoffset, borderoffset, + int offsetright = FFMAX3(FFMAX(s->bb_right, 0), borderoffset, (s->shadowx > 0 ? s->shadowx : 0)); - int offsetbottom = FFMAX3(boxoffset, borderoffset, + int offsetbottom = FFMAX3(FFMAX(s->bb_bottom, 0), borderoffset, (s->shadowy > 0 ? s->shadowy : 0)); - if (s->x - offsetleft < 0) s->x = offsetleft; if (s->y - offsettop < 0) s->y = offsettop; - if (s->x + box_w + offsetright > width) - s->x = FFMAX(width - box_w - offsetright, 0); - if (s->y + box_h + offsetbottom > height) - s->y = FFMAX(height - box_h - offsetbottom, 0); + if (s->x + metrics.width + offsetright > width) + s->x = FFMAX(width - metrics.width - offsetright, 0); + if (s->y + metrics.height + offsetbottom > height) + s->y = FFMAX(height - metrics.height - offsetbottom, 0); } - /* draw box */ - if (s->draw_box) - ff_blend_rectangle(&s->dc, &boxcolor, - frame->data, frame->linesize, width, height, - s->x - s->boxborderw, s->y - s->boxborderw, - box_w + s->boxborderw * 2, box_h + s->boxborderw * 2); + x = 0; + y = 0; + x64 = (int)(s->x * 64.); + y64 = (int)(s->y * 64. + metrics.offset_top64); + + for (int l = 0; l < s->line_count; ++l) { + TextLine *line = &s->lines[l]; + HarfbuzzData *hb = &line->hb_data; + line->glyphs = av_mallocz(hb->glyph_count * sizeof(GlyphInfo)); + + for (int t = 0; t < hb->glyph_count; ++t) { + GlyphInfo *g_info = &line->glyphs[t]; + uint8_t is_tab = last_tab_idx < s->tab_count && + hb->glyph_info[t].cluster == s->tab_clusters[last_tab_idx] - line->cluster_offset; + int true_x, true_y; + if (is_tab) { + ++last_tab_idx; + } + true_x = x + hb->glyph_pos[t].x_offset; + true_y = y + hb->glyph_pos[t].y_offset; + shift_x64 = (((x64 + true_x) >> 4) & 0b0011) << 4; + shift_y64 = ((4 - (((y64 + true_y) >> 4) & 0b0011)) & 0b0011) << 4; + + ret = load_glyph(ctx, &glyph, hb->glyph_info[t].codepoint, shift_x64, shift_y64); + if (ret != 0) { + return ret; + } + g_info->code = hb->glyph_info[t].codepoint; + g_info->x = (x64 + true_x) >> 6; + g_info->y = ((y64 + true_y) >> 6) + (shift_y64 > 0 ? 1 : 0); + g_info->shift_x64 = shift_x64; + g_info->shift_y64 = shift_y64; + + if (!is_tab) { + x += hb->glyph_pos[t].x_advance; + } else { + int size = s->blank_advance64 * s->tabsize; + x = (x / size + 1) * size; + } + y += hb->glyph_pos[t].y_advance; + } - if (s->shadowx || s->shadowy) { - if ((ret = draw_glyphs(s, frame, width, height, - &shadowcolor, s->shadowx, s->shadowy, 0)) < 0) - return ret; + y += metrics.line_height64 + s->line_spacing * 64; + x = 0; } - if (s->borderw) { - if ((ret = draw_glyphs(s, frame, width, height, - &bordercolor, 0, 0, s->borderw)) < 0) + metrics.rect_x = s->x; + metrics.rect_y = s->y; + + if (!s->draw_box) { + // Create a border for the clipping region to take into account subpixel + // errors in text measurement and effects. + int borderoffset = s->borderw ? FFMAX(s->borderw, 0) : 0; + s->bb_left = borderoffset + (s->shadowx < 0 ? FFABS(s->shadowx) : 0) + 1; + s->bb_top = borderoffset + (s->shadowy < 0 ? FFABS(s->shadowy) : 0) + 1; + s->bb_right = borderoffset + (s->shadowx > 0 ? s->shadowx : 0) + 1; + s->bb_bottom = borderoffset + (s->shadowy > 0 ? s->shadowy : 0) + 1; + } + + /* Check if the whole box is out of the frame */ + is_outside = metrics.rect_x - s->bb_left >= width || + metrics.rect_y - s->bb_top >= height || + metrics.rect_x + metrics.width + s->bb_right <= 0 || + metrics.rect_y + metrics.height + s->bb_bottom <= 0; + + if (!is_outside) { + /* draw box */ + if (s->draw_box) { + rec_x = metrics.rect_x - s->bb_left; + rec_y = metrics.rect_y - s->bb_top; + rec_width = metrics.width + s->bb_right + s->bb_left; + rec_height = metrics.height + s->bb_bottom + s->bb_top; + ff_blend_rectangle(&s->dc, &boxcolor, + frame->data, frame->linesize, width, height, + rec_x, rec_y, rec_width, rec_height); + } + + if (s->shadowx || s->shadowy) { + if ((ret = draw_glyphs(s, frame, &shadowcolor, &metrics, + s->shadowx, s->shadowy, s->borderw)) < 0) { + return ret; + } + } + + if (s->borderw) { + if ((ret = draw_glyphs(s, frame, &bordercolor, &metrics, + 0, 0, s->borderw)) < 0) { + return ret; + } + } + + if ((ret = draw_glyphs(s, frame, &fontcolor, &metrics, 0, + 0, 0)) < 0) { return ret; + } } - if ((ret = draw_glyphs(s, frame, width, height, - &fontcolor, 0, 0, 0)) < 0) - return ret; + + // FREE data structures + for (int l = 0; l < s->line_count; ++l) { + TextLine *line = &s->lines[l]; + av_freep(&line->glyphs); + hb_destroy(&line->hb_data); + } + av_freep(&s->lines); + av_freep(&s->tab_clusters); return 0; } @@ -1691,14 +2003,9 @@ FF_ENABLE_DEPRECATION_WARNINGS s->x = bbox->x; s->y = bbox->y - s->fontsize; } - draw_text(ctx, frame, frame->width, frame->height); + draw_text(ctx, frame); } - av_log(ctx, AV_LOG_DEBUG, "n:%d t:%f text_w:%d text_h:%d x:%d y:%d\n", - (int)s->var_values[VAR_N], s->var_values[VAR_T], - (int)s->var_values[VAR_TEXT_W], (int)s->var_values[VAR_TEXT_H], - s->x, s->y); - return ff_filter_frame(outlink, frame); } From 79e39978d8beb7548f81f6c75733e4c0f4678ccc Mon Sep 17 00:00:00 2001 From: yethie Date: Fri, 26 May 2023 12:21:31 +0200 Subject: [PATCH 1579/2172] avfilter/vf_drawtext: extend boxborderw option Adds support for different border size in each direction. --- doc/filters.texi | 12 +++++++++++- libavfilter/vf_drawtext.c | 41 ++++++++++++++++++++++++++++++++++++--- 2 files changed, 49 insertions(+), 4 deletions(-) diff --git a/doc/filters.texi b/doc/filters.texi index 6d002eaae56..dd4ede03668 100644 --- a/doc/filters.texi +++ b/doc/filters.texi @@ -12363,7 +12363,17 @@ The default value of @var{box} is 0. @item boxborderw Set the width of the border to be drawn around the box using @var{boxcolor}. -The default value of @var{boxborderw} is 0. +The value must be specified using one of the following formats: +@itemize @bullet +@item @code{boxborderw=10} set the width of all the borders to 10 +@item @code{boxborderw=10|20} set the width of the top and bottom borders to 10 + and the width of the left and right borders to 20 +@item @code{boxborderw=10|20|30} set the width of the top border to 10, the width + of the bottom border to 30 and the width of the left and right borders to 20 +@item @code{boxborderw=10|20|30|40} set the borders width to 10 (top), 20 (right), + 30 (bottom), 40 (left) +@end itemize +The default value of @var{boxborderw} is "0". @item boxcolor The color to be used for drawing box around text. For the syntax of this diff --git a/libavfilter/vf_drawtext.c b/libavfilter/vf_drawtext.c index bdab591efdf..07a775f933b 100644 --- a/libavfilter/vf_drawtext.c +++ b/libavfilter/vf_drawtext.c @@ -256,7 +256,8 @@ typedef struct DrawTextContext { int line_spacing; ///< lines spacing in pixels short int draw_box; ///< draw box around text - true or false - int boxborderw; ///< box border width + char *boxborderw; ///< box border width (padding) + /// allowed formats: "all", "vert|oriz", "top|right|bottom|left" int bb_top; ///< the size of the top box border int bb_right; ///< the size of the right box border int bb_bottom; ///< the size of the bottom box border @@ -316,7 +317,7 @@ static const AVOption drawtext_options[]= { {"bordercolor", "set border color", OFFSET(bordercolor.rgba), AV_OPT_TYPE_COLOR, {.str="black"}, 0, 0, FLAGS}, {"shadowcolor", "set shadow color", OFFSET(shadowcolor.rgba), AV_OPT_TYPE_COLOR, {.str="black"}, 0, 0, FLAGS}, {"box", "set box", OFFSET(draw_box), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1, FLAGS}, - {"boxborderw", "set box borders width", OFFSET(boxborderw), AV_OPT_TYPE_INT, {.i64=0}, 0, INT_MAX, FLAGS}, + {"boxborderw", "set box borders width", OFFSET(boxborderw), AV_OPT_TYPE_STRING, {.str="0"}, 0, 0, FLAGS}, {"line_spacing", "set line spacing in pixels", OFFSET(line_spacing), AV_OPT_TYPE_INT, {.i64=0}, INT_MIN, INT_MAX, FLAGS}, {"fontsize", "set font size", OFFSET(fontsize_expr), AV_OPT_TYPE_STRING, {.str=NULL}, 0, 0, FLAGS}, {"x", "set x expression", OFFSET(x_expr), AV_OPT_TYPE_STRING, {.str="0"}, 0, 0, FLAGS}, @@ -818,6 +819,23 @@ static int load_glyph(AVFilterContext *ctx, Glyph **glyph_ptr, uint32_t code, in return ret; } +// Convert a string formatted as "n1|n2|...|nN" into an integer array +static int string_to_array(const char *source, int *result, int result_size) +{ + int counter = 0, size = strlen(source) + 1; + char *saveptr, *curval, *dup = av_malloc(size); + if (!dup) + return 0; + av_strlcpy(dup, source, size); + if (result_size > 0 && (curval = av_strtok(dup, "|", &saveptr))) { + do { + result[counter++] = atoi(curval); + } while ((curval = av_strtok(NULL, "|", &saveptr)) && counter < result_size); + } + av_free(dup); + return counter; +} + static av_cold int init(AVFilterContext *ctx) { int err; @@ -1796,7 +1814,24 @@ static int draw_text(AVFilterContext *ctx, AVFrame *frame) update_color_with_alpha(s, &boxcolor , s->boxcolor ); if (s->draw_box && s->boxborderw) { - s->bb_top = s->bb_right = s->bb_bottom = s->bb_left = s->boxborderw; + int bbsize[4]; + int count; + count = string_to_array(s->boxborderw, bbsize, 4); + if (count == 1) { + s->bb_top = s->bb_right = s->bb_bottom = s->bb_left = bbsize[0]; + } else if (count == 2) { + s->bb_top = s->bb_bottom = bbsize[0]; + s->bb_right = s->bb_left = bbsize[1]; + } else if (count == 3) { + s->bb_top = bbsize[0]; + s->bb_right = s->bb_left = bbsize[1]; + s->bb_bottom = bbsize[2]; + } else if (count == 4) { + s->bb_top = bbsize[0]; + s->bb_right = bbsize[1]; + s->bb_bottom = bbsize[2]; + s->bb_left = bbsize[3]; + } } else { s->bb_top = s->bb_right = s->bb_bottom = s->bb_left = 0; } From fac7bb06d86ab8a82adfa50c4b1f2348427af55b Mon Sep 17 00:00:00 2001 From: yethie Date: Wed, 14 Jun 2023 18:35:45 +0200 Subject: [PATCH 1580/2172] avfilter/vf_drawtext: add options for size of the background box --- doc/filters.texi | 8 ++++++++ libavfilter/vf_drawtext.c | 22 ++++++++++++++++------ 2 files changed, 24 insertions(+), 6 deletions(-) diff --git a/doc/filters.texi b/doc/filters.texi index dd4ede03668..97fec936a48 100644 --- a/doc/filters.texi +++ b/doc/filters.texi @@ -12478,6 +12478,14 @@ ffmpeg-utils manual,ffmpeg-utils}. The default value of @var{shadowcolor} is "black". +@item boxw +Set the width of the box to be drawn around text. +The default value of @var{boxw} is computed automatically to match the text width + +@item boxh +Set the height of the box to be drawn around text. +The default value of @var{boxh} is computed automatically to match the text height + @item shadowx @item shadowy The x and y offsets for the text shadow position with respect to the diff --git a/libavfilter/vf_drawtext.c b/libavfilter/vf_drawtext.c index 07a775f933b..b971eebdf42 100644 --- a/libavfilter/vf_drawtext.c +++ b/libavfilter/vf_drawtext.c @@ -262,6 +262,8 @@ typedef struct DrawTextContext { int bb_right; ///< the size of the right box border int bb_bottom; ///< the size of the bottom box border int bb_left; ///< the size of the left box border + int box_width; ///< the width of box + int box_height; ///< the height of box int tabsize; ///< tab size int fix_bounds; ///< do we let it go out of frame bounds - t/f @@ -297,6 +299,9 @@ typedef struct DrawTextContext { #endif AVDictionary *metadata; + int boxw; ///< the value of the boxw parameter + int boxh; ///< the value of the boxh parameter + TextLine *lines; ///< computed information about text lines int line_count; ///< the number of text lines uint32_t *tab_clusters; ///< the position of tab characters in the text @@ -322,6 +327,8 @@ static const AVOption drawtext_options[]= { {"fontsize", "set font size", OFFSET(fontsize_expr), AV_OPT_TYPE_STRING, {.str=NULL}, 0, 0, FLAGS}, {"x", "set x expression", OFFSET(x_expr), AV_OPT_TYPE_STRING, {.str="0"}, 0, 0, FLAGS}, {"y", "set y expression", OFFSET(y_expr), AV_OPT_TYPE_STRING, {.str="0"}, 0, 0, FLAGS}, + {"boxw", "set box width", OFFSET(boxw), AV_OPT_TYPE_INT, {.i64=0}, 0, INT_MAX, FLAGS}, + {"boxh", "set box height", OFFSET(boxh), AV_OPT_TYPE_INT, {.i64=0}, 0, INT_MAX, FLAGS}, {"shadowx", "set shadow x offset", OFFSET(shadowx), AV_OPT_TYPE_INT, {.i64=0}, INT_MIN, INT_MAX, FLAGS}, {"shadowy", "set shadow y offset", OFFSET(shadowy), AV_OPT_TYPE_INT, {.i64=0}, INT_MIN, INT_MAX, FLAGS}, {"borderw", "set border width", OFFSET(borderw), AV_OPT_TYPE_INT, {.i64=0}, INT_MIN, INT_MAX, FLAGS}, @@ -1473,8 +1480,8 @@ static int draw_glyphs(DrawTextContext *s, AVFrame *frame, FT_BitmapGlyph b_glyph; int clip_x = 0, clip_y = 0; - clip_x = FFMIN(metrics->rect_x + metrics->width + s->bb_right, frame->width); - clip_y = FFMIN(metrics->rect_y + metrics->height + s->bb_bottom, frame->height); + clip_x = FFMIN(metrics->rect_x + s->box_width + s->bb_right, frame->width); + clip_y = FFMIN(metrics->rect_y + s->box_height + s->bb_bottom, frame->height); for (l = 0; l < s->line_count; ++l) { TextLine *line = &s->lines[l]; @@ -1907,6 +1914,9 @@ static int draw_text(AVFilterContext *ctx, AVFrame *frame) metrics.rect_x = s->x; metrics.rect_y = s->y; + s->box_width = s->boxw == 0 ? metrics.width : s->boxw; + s->box_height = s->boxh == 0 ? metrics.height : s->boxh; + if (!s->draw_box) { // Create a border for the clipping region to take into account subpixel // errors in text measurement and effects. @@ -1920,16 +1930,16 @@ static int draw_text(AVFilterContext *ctx, AVFrame *frame) /* Check if the whole box is out of the frame */ is_outside = metrics.rect_x - s->bb_left >= width || metrics.rect_y - s->bb_top >= height || - metrics.rect_x + metrics.width + s->bb_right <= 0 || - metrics.rect_y + metrics.height + s->bb_bottom <= 0; + metrics.rect_x + s->box_width + s->bb_right <= 0 || + metrics.rect_y + s->box_height + s->bb_bottom <= 0; if (!is_outside) { /* draw box */ if (s->draw_box) { rec_x = metrics.rect_x - s->bb_left; rec_y = metrics.rect_y - s->bb_top; - rec_width = metrics.width + s->bb_right + s->bb_left; - rec_height = metrics.height + s->bb_bottom + s->bb_top; + rec_width = s->box_width + s->bb_right + s->bb_left; + rec_height = s->box_height + s->bb_bottom + s->bb_top; ff_blend_rectangle(&s->dc, &boxcolor, frame->data, frame->linesize, width, height, rec_x, rec_y, rec_width, rec_height); From 01d843f6d09b94f6f424d4d408ca2fc92dcaefd7 Mon Sep 17 00:00:00 2001 From: yethie Date: Fri, 26 May 2023 12:46:10 +0200 Subject: [PATCH 1581/2172] avfilter/vf_drawtext: add expression variables to control font ascent/descent The following new variables can be used in the x and y expressions: font_a, font_d, top_a, bottom_d. --- doc/filters.texi | 12 ++++++++++++ libavfilter/vf_drawtext.c | 12 ++++++++++++ 2 files changed, 24 insertions(+) diff --git a/doc/filters.texi b/doc/filters.texi index 97fec936a48..da355eca643 100644 --- a/doc/filters.texi +++ b/doc/filters.texi @@ -12597,6 +12597,18 @@ contained in the rendered text, it is equivalent to @var{ascent} - maximum glyph width, that is the maximum width for all the glyphs contained in the rendered text +@item font_a +the ascent size defined in the font metrics + +@item font_d +the descent size defined in the font metrics + +@item top_a +the maximum ascender of the glyphs of the first text line + +@item bottom_d +the maximum descender of the glyphs of the last text line + @item n the number of input frame, starting from 0 diff --git a/libavfilter/vf_drawtext.c b/libavfilter/vf_drawtext.c index b971eebdf42..417733596d5 100644 --- a/libavfilter/vf_drawtext.c +++ b/libavfilter/vf_drawtext.c @@ -89,6 +89,10 @@ static const char *const var_names[] = { "max_glyph_d", "descent", ///< min glyph descender "max_glyph_h", ///< max glyph height "max_glyph_w", ///< max glyph width + "font_a", ///< font-defined ascent + "font_d", ///< font-defined descent + "top_a", ///< max glyph ascender of the top line + "bottom_d", ///< max glyph descender of the bottom line "n", ///< number of frame "sar", "t", ///< timestamp expressed in seconds @@ -136,6 +140,10 @@ enum var_name { VAR_MAX_GLYPH_D, VAR_DESCENT, VAR_MAX_GLYPH_H, VAR_MAX_GLYPH_W, + VAR_FONT_A, + VAR_FONT_D, + VAR_TOP_A, + VAR_BOTTOM_D, VAR_N, VAR_SAR, VAR_T, @@ -1800,8 +1808,12 @@ static int draw_text(AVFilterContext *ctx, AVFrame *frame) s->var_values[VAR_MAX_GLYPH_W] = s->max_glyph_w; s->var_values[VAR_MAX_GLYPH_H] = s->max_glyph_h; s->var_values[VAR_MAX_GLYPH_A] = s->var_values[VAR_ASCENT] = POS_CEIL(metrics.max_y64, 64); + s->var_values[VAR_FONT_A] = s->face->size->metrics.ascender / 64; s->var_values[VAR_MAX_GLYPH_D] = s->var_values[VAR_DESCENT] = POS_CEIL(metrics.min_y64, 64); + s->var_values[VAR_FONT_D] = -s->face->size->metrics.descender / 64; + s->var_values[VAR_TOP_A] = POS_CEIL(metrics.offset_top64, 64); + s->var_values[VAR_BOTTOM_D] = -POS_CEIL(metrics.offset_bottom64, 64); s->var_values[VAR_LINE_H] = s->var_values[VAR_LH] = metrics.line_height64 / 64.; if (s->text_source == AV_FRAME_DATA_DETECTION_BBOXES) { From 5f2d907de2ddefd024d161b66d63f8da6208d4d0 Mon Sep 17 00:00:00 2001 From: yethie Date: Fri, 26 May 2023 12:51:05 +0200 Subject: [PATCH 1582/2172] avfilter/vf_drawtext: implement text alignment Text can now be aligned vertically (top, middle, bottom) and horizontally (left, center, right) relative to the background box. --- doc/filters.texi | 6 +++++ libavfilter/vf_drawtext.c | 51 ++++++++++++++++++++++++++++++++++++++- 2 files changed, 56 insertions(+), 1 deletion(-) diff --git a/doc/filters.texi b/doc/filters.texi index da355eca643..891c0510293 100644 --- a/doc/filters.texi +++ b/doc/filters.texi @@ -12384,6 +12384,12 @@ The default value of @var{boxcolor} is "white". @item line_spacing Set the line spacing in pixels. The default value of @var{line_spacing} is 0. +@item text_align +Set the vertical and horizontal alignment of the text with respect to the box boundaries. +The value must contain exactly two letters, one for the vertical alignment (T=top, +M=middle, B=bottom) and one for the horizontal alignment (L=left, C=center, R=right). +Please note that tab characters are only supported with the left horizontal alignment. + @item borderw Set the width of the border to be drawn around the text using @var{bordercolor}. The default value of @var{borderw} is 0. diff --git a/libavfilter/vf_drawtext.c b/libavfilter/vf_drawtext.c index 417733596d5..e147196844f 100644 --- a/libavfilter/vf_drawtext.c +++ b/libavfilter/vf_drawtext.c @@ -309,12 +309,14 @@ typedef struct DrawTextContext { int boxw; ///< the value of the boxw parameter int boxh; ///< the value of the boxh parameter + uint8_t *text_align; ///< the horizontal and vertical text alignment TextLine *lines; ///< computed information about text lines int line_count; ///< the number of text lines uint32_t *tab_clusters; ///< the position of tab characters in the text int tab_count; ///< the number of tab characters int blank_advance64; ///< the size of the space character + int tab_warning_printed; ///< ensure the tab warning to be printed only once } DrawTextContext; #define OFFSET(x) offsetof(DrawTextContext, x) @@ -333,6 +335,7 @@ static const AVOption drawtext_options[]= { {"boxborderw", "set box borders width", OFFSET(boxborderw), AV_OPT_TYPE_STRING, {.str="0"}, 0, 0, FLAGS}, {"line_spacing", "set line spacing in pixels", OFFSET(line_spacing), AV_OPT_TYPE_INT, {.i64=0}, INT_MIN, INT_MAX, FLAGS}, {"fontsize", "set font size", OFFSET(fontsize_expr), AV_OPT_TYPE_STRING, {.str=NULL}, 0, 0, FLAGS}, + {"text_align", "set text alignment", OFFSET(text_align), AV_OPT_TYPE_STRING, {.str="TL"}, 0, 0, FLAGS}, {"x", "set x expression", OFFSET(x_expr), AV_OPT_TYPE_STRING, {.str="0"}, 0, 0, FLAGS}, {"y", "set y expression", OFFSET(y_expr), AV_OPT_TYPE_STRING, {.str="0"}, 0, 0, FLAGS}, {"boxw", "set box width", OFFSET(boxw), AV_OPT_TYPE_INT, {.i64=0}, 0, INT_MAX, FLAGS}, @@ -851,6 +854,19 @@ static int string_to_array(const char *source, int *result, int result_size) return counter; } +static int validate_text_align(char* text_align) +{ + int err = 0; + if (strlen(text_align) != 2 + || strchr("LCRTMB", text_align[0]) == NULL || strchr("LCRTMB", text_align[1]) == NULL + || (strchr("TMB", text_align[0]) != NULL && strchr("LCR", text_align[1]) == NULL) + || (strchr("LCR", text_align[0]) != NULL && strchr("TMB", text_align[1]) == NULL)) { + err = AVERROR(EINVAL); + } + + return err; +} + static av_cold int init(AVFilterContext *ctx) { int err; @@ -916,6 +932,14 @@ static av_cold int init(AVFilterContext *ctx) return AVERROR(EINVAL); } + if ((err = validate_text_align(s->text_align))) { + av_log(ctx, AV_LOG_ERROR, + "The value provided for parameter 'text_align' is not valid,\n"); + av_log(ctx, AV_LOG_ERROR, + "please specify a two characters string containing only one letter for horizontal alignment ('LCR') and one for vertical alignment ('TMB')\n"); + return err; + } + #if CONFIG_LIBFRIBIDI if (s->text_shaping) if ((err = shape_text(ctx)) < 0) @@ -1486,13 +1510,32 @@ static int draw_glyphs(DrawTextContext *s, AVFrame *frame, Glyph dummy = { 0 }, *glyph; FT_Bitmap bitmap; FT_BitmapGlyph b_glyph; + uint8_t j_center = 0, j_right = 0, j_middle = 0, j_bottom = 0; + int line_w, offset_y = 0; int clip_x = 0, clip_y = 0; + j_center = strstr(s->text_align, "C") > 0; + j_right = strstr(s->text_align, "R") > 0; + j_middle = strstr(s->text_align, "M") > 0; + j_bottom = strstr(s->text_align, "B") > 0; + + if (j_middle) { + offset_y = (s->box_height - metrics->height) / 2; + } else if (j_bottom) { + offset_y = s->box_height - metrics->height; + } + + if ((j_right || j_center) && !s->tab_warning_printed && s->tab_count > 0) { + s->tab_warning_printed = 1; + av_log(s, AV_LOG_WARNING, "Tab characters are only supported with left horizontal alignment\n"); + } + clip_x = FFMIN(metrics->rect_x + s->box_width + s->bb_right, frame->width); clip_y = FFMIN(metrics->rect_y + s->box_height + s->bb_bottom, frame->height); for (l = 0; l < s->line_count; ++l) { TextLine *line = &s->lines[l]; + line_w = POS_CEIL(line->width64, 64); for (g = 0; g < line->hb_data.glyph_count; ++g) { info = &line->glyphs[g]; dummy.fontsize = s->fontsize; @@ -1506,10 +1549,16 @@ static int draw_glyphs(DrawTextContext *s, AVFrame *frame, b_glyph = borderw ? glyph->border_bglyph[idx] : glyph->bglyph[idx]; bitmap = b_glyph->bitmap; x1 = x + info->x + b_glyph->left; - y1 = y + info->y - b_glyph->top; + y1 = y + info->y - b_glyph->top + offset_y; w1 = bitmap.width; h1 = bitmap.rows; + if (j_center) { + x1 += (s->box_width - line_w) / 2; + } else if (j_right) { + x1 += s->box_width - line_w; + } + // Offset of the glyph's bitmap in the visible region dx = dy = 0; if (x1 < metrics->rect_x - s->bb_left) { From 692d37d2e9ac641fa477c7a039f4d1e3beb3bd47 Mon Sep 17 00:00:00 2001 From: yethie Date: Wed, 14 Jun 2023 18:58:32 +0200 Subject: [PATCH 1583/2172] avfilter/vf_drawtext: add y_align option The new y_align option specifies if the user provided y value is referred to the top of the text, to the font baseline or to the top of the font --- doc/filters.texi | 10 +++++++++ libavfilter/vf_drawtext.c | 47 ++++++++++++++++++++++++++++++--------- 2 files changed, 46 insertions(+), 11 deletions(-) diff --git a/doc/filters.texi b/doc/filters.texi index 891c0510293..9730444337b 100644 --- a/doc/filters.texi +++ b/doc/filters.texi @@ -12390,6 +12390,16 @@ The value must contain exactly two letters, one for the vertical alignment (T=to M=middle, B=bottom) and one for the horizontal alignment (L=left, C=center, R=right). Please note that tab characters are only supported with the left horizontal alignment. +@item y_align +Specify what the @var{y} value is referred to. Possible values are: +@itemize @bullet +@item @code{text} the top of the highest glyph of the first text line is placed at @var{y} +@item @code{baseline} the baseline of the first text line is placed at @var{y} +@item @code{font} the baseline of the first text line is placed at @var{y} plus the + ascent (in pixels) defined in the font metrics +@end itemize +The default value of @var{y_align} is "text" for backward compatibility. + @item borderw Set the width of the border to be drawn around the text using @var{bordercolor}. The default value of @var{borderw} is 0. diff --git a/libavfilter/vf_drawtext.c b/libavfilter/vf_drawtext.c index e147196844f..59ba3e40c08 100644 --- a/libavfilter/vf_drawtext.c +++ b/libavfilter/vf_drawtext.c @@ -171,6 +171,12 @@ enum expansion_mode { EXP_STRFTIME, }; +enum y_alignment { + YA_TEXT, + YA_BASELINE, + YA_FONT, +}; + typedef struct HarfbuzzData { hb_buffer_t* buf; hb_font_t* font; @@ -310,6 +316,7 @@ typedef struct DrawTextContext { int boxw; ///< the value of the boxw parameter int boxh; ///< the value of the boxh parameter uint8_t *text_align; ///< the horizontal and vertical text alignment + int y_align; ///< the value of the y_align parameter TextLine *lines; ///< computed information about text lines int line_count; ///< the number of text lines @@ -353,6 +360,10 @@ static const AVOption drawtext_options[]= { {"none", "set no expansion", OFFSET(exp_mode), AV_OPT_TYPE_CONST, {.i64=EXP_NONE}, 0, 0, FLAGS, "expansion"}, {"normal", "set normal expansion", OFFSET(exp_mode), AV_OPT_TYPE_CONST, {.i64=EXP_NORMAL}, 0, 0, FLAGS, "expansion"}, {"strftime", "set strftime expansion (deprecated)", OFFSET(exp_mode), AV_OPT_TYPE_CONST, {.i64=EXP_STRFTIME}, 0, 0, FLAGS, "expansion"}, + {"y_align", "set the y alignment", OFFSET(y_align), AV_OPT_TYPE_INT, {.i64=YA_TEXT}, 0, 2, FLAGS, "y_align"}, + {"text", "y is referred to the top of the first text line", OFFSET(y_align), AV_OPT_TYPE_CONST, {.i64=YA_TEXT}, 0, 0, FLAGS, "y_align"}, + {"baseline", "y is referred to the baseline of the first line", OFFSET(y_align), AV_OPT_TYPE_CONST, {.i64=YA_BASELINE}, 0, 0, FLAGS, "y_align"}, + {"font", "y is referred to the font defined line metrics", OFFSET(y_align), AV_OPT_TYPE_CONST, {.i64=YA_FONT}, 0, 0, FLAGS, "y_align"}, {"timecode", "set initial timecode", OFFSET(tc_opt_string), AV_OPT_TYPE_STRING, {.str=NULL}, 0, 0, FLAGS}, {"tc24hmax", "set 24 hours max (timecode only)", OFFSET(tc24hmax), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1, FLAGS}, @@ -958,11 +969,13 @@ static av_cold int init(AVFilterContext *ctx) if ((err = update_fontsize(ctx)) < 0) return err; + // Always init the stroker, may be needed if borderw is set via command + if (FT_Stroker_New(s->library, &s->stroker)) { + av_log(ctx, AV_LOG_ERROR, "Could not init FT stroker\n"); + return AVERROR_EXTERNAL; + } + if (s->borderw) { - if (FT_Stroker_New(s->library, &s->stroker)) { - av_log(ctx, AV_LOG_ERROR, "Coult not init FT stroker\n"); - return AVERROR_EXTERNAL; - } FT_Stroker_Set(s->stroker, s->borderw << 6, FT_STROKER_LINECAP_ROUND, FT_STROKER_LINEJOIN_ROUND, 0); } @@ -1634,7 +1647,6 @@ static int measure_text(AVFilterContext *ctx, TextMetrics *metrics) int line_count = 0; uint32_t code = 0; Glyph *glyph = NULL; - int height64; int i, tab_idx = 0, last_tab_idx = 0, line_offset = 0; char* p; @@ -1753,10 +1765,13 @@ static int measure_text(AVFilterContext *ctx, TextMetrics *metrics) metrics->line_height64 = s->face->size->metrics.height; metrics->width = POS_CEIL(width64, 64); - height64 = (metrics->line_height64 + s->line_spacing * 64) * - (FFMAX(0, line_count - 1)) + first_max_y64 - cur_min_y64; - metrics->height = POS_CEIL(height64, 64); - + if (s->y_align == YA_FONT) { + metrics->height = POS_CEIL(metrics->line_height64 * line_count, 64); + } else { + int height64 = (metrics->line_height64 + s->line_spacing * 64) * + (FFMAX(0, line_count - 1)) + first_max_y64 - cur_min_y64; + metrics->height = POS_CEIL(height64, 64); + } metrics->offset_top64 = first_max_y64; metrics->offset_right64 = last_max_x64; metrics->offset_bottom64 = cur_min_y64; @@ -1929,7 +1944,13 @@ static int draw_text(AVFilterContext *ctx, AVFrame *frame) x = 0; y = 0; x64 = (int)(s->x * 64.); - y64 = (int)(s->y * 64. + metrics.offset_top64); + if (s->y_align == YA_FONT) { + y64 = (int)(s->y * 64. + s->face->size->metrics.ascender); + } else if (s->y_align == YA_BASELINE) { + y64 = (int)(s->y * 64.); + } else { + y64 = (int)(s->y * 64. + metrics.offset_top64); + } for (int l = 0; l < s->line_count; ++l) { TextLine *line = &s->lines[l]; @@ -1973,7 +1994,11 @@ static int draw_text(AVFilterContext *ctx, AVFrame *frame) } metrics.rect_x = s->x; - metrics.rect_y = s->y; + if (s->y_align == YA_BASELINE) { + metrics.rect_y = s->y - metrics.offset_top64 / 64; + } else { + metrics.rect_y = s->y; + } s->box_width = s->boxw == 0 ? metrics.width : s->boxw; s->box_height = s->boxh == 0 ? metrics.height : s->boxh; From 01420316d281f3daadf1079159bf5430553c8818 Mon Sep 17 00:00:00 2001 From: yethie Date: Fri, 26 May 2023 13:06:47 +0200 Subject: [PATCH 1584/2172] avfilter/vf_drawtext: add support for commands --- doc/filters.texi | 25 +++++++++++- libavfilter/vf_drawtext.c | 82 ++++++++++++++++++++++++++++----------- 2 files changed, 84 insertions(+), 23 deletions(-) diff --git a/doc/filters.texi b/doc/filters.texi index 9730444337b..3afcc23b6a3 100644 --- a/doc/filters.texi +++ b/doc/filters.texi @@ -12791,11 +12791,34 @@ Full filter invocation with sendcmd would look like this: @example sendcmd=c='56.0 drawtext reinit fontsize=56\:fontcolor=green\:text=Hello\\ World' @end example -@end table If the entire argument can't be parsed or applied as valid values then the filter will continue with its existing parameters. +@end table + +The following options are also supported as @ref{commands}: + +@itemize @bullet +@item x +@item y +@item alpha +@item fontsize +@item fontcolor +@item boxcolor +@item bordercolor +@item shadowcolor +@item box +@item boxw +@item boxh +@item boxborderw +@item line_spacing +@item text_align +@item shadowx +@item shadowy +@item borderw +@end itemize + @subsection Examples @itemize diff --git a/libavfilter/vf_drawtext.c b/libavfilter/vf_drawtext.c index 59ba3e40c08..4c5c5d8bd65 100644 --- a/libavfilter/vf_drawtext.c +++ b/libavfilter/vf_drawtext.c @@ -328,29 +328,30 @@ typedef struct DrawTextContext { #define OFFSET(x) offsetof(DrawTextContext, x) #define FLAGS AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_VIDEO_PARAM +#define TFLAGS AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_VIDEO_PARAM|AV_OPT_FLAG_RUNTIME_PARAM static const AVOption drawtext_options[]= { {"fontfile", "set font file", OFFSET(fontfile), AV_OPT_TYPE_STRING, {.str=NULL}, 0, 0, FLAGS}, - {"text", "set text", OFFSET(text), AV_OPT_TYPE_STRING, {.str=NULL}, 0, 0, FLAGS}, + {"text", "set text", OFFSET(text), AV_OPT_TYPE_STRING, {.str=NULL}, 0, 0, TFLAGS}, {"textfile", "set text file", OFFSET(textfile), AV_OPT_TYPE_STRING, {.str=NULL}, 0, 0, FLAGS}, - {"fontcolor", "set foreground color", OFFSET(fontcolor.rgba), AV_OPT_TYPE_COLOR, {.str="black"}, 0, 0, FLAGS}, + {"fontcolor", "set foreground color", OFFSET(fontcolor.rgba), AV_OPT_TYPE_COLOR, {.str="black"}, 0, 0, TFLAGS}, {"fontcolor_expr", "set foreground color expression", OFFSET(fontcolor_expr), AV_OPT_TYPE_STRING, {.str=""}, 0, 0, FLAGS}, - {"boxcolor", "set box color", OFFSET(boxcolor.rgba), AV_OPT_TYPE_COLOR, {.str="white"}, 0, 0, FLAGS}, - {"bordercolor", "set border color", OFFSET(bordercolor.rgba), AV_OPT_TYPE_COLOR, {.str="black"}, 0, 0, FLAGS}, - {"shadowcolor", "set shadow color", OFFSET(shadowcolor.rgba), AV_OPT_TYPE_COLOR, {.str="black"}, 0, 0, FLAGS}, - {"box", "set box", OFFSET(draw_box), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1, FLAGS}, - {"boxborderw", "set box borders width", OFFSET(boxborderw), AV_OPT_TYPE_STRING, {.str="0"}, 0, 0, FLAGS}, - {"line_spacing", "set line spacing in pixels", OFFSET(line_spacing), AV_OPT_TYPE_INT, {.i64=0}, INT_MIN, INT_MAX, FLAGS}, - {"fontsize", "set font size", OFFSET(fontsize_expr), AV_OPT_TYPE_STRING, {.str=NULL}, 0, 0, FLAGS}, - {"text_align", "set text alignment", OFFSET(text_align), AV_OPT_TYPE_STRING, {.str="TL"}, 0, 0, FLAGS}, - {"x", "set x expression", OFFSET(x_expr), AV_OPT_TYPE_STRING, {.str="0"}, 0, 0, FLAGS}, - {"y", "set y expression", OFFSET(y_expr), AV_OPT_TYPE_STRING, {.str="0"}, 0, 0, FLAGS}, - {"boxw", "set box width", OFFSET(boxw), AV_OPT_TYPE_INT, {.i64=0}, 0, INT_MAX, FLAGS}, - {"boxh", "set box height", OFFSET(boxh), AV_OPT_TYPE_INT, {.i64=0}, 0, INT_MAX, FLAGS}, - {"shadowx", "set shadow x offset", OFFSET(shadowx), AV_OPT_TYPE_INT, {.i64=0}, INT_MIN, INT_MAX, FLAGS}, - {"shadowy", "set shadow y offset", OFFSET(shadowy), AV_OPT_TYPE_INT, {.i64=0}, INT_MIN, INT_MAX, FLAGS}, - {"borderw", "set border width", OFFSET(borderw), AV_OPT_TYPE_INT, {.i64=0}, INT_MIN, INT_MAX, FLAGS}, - {"tabsize", "set tab size", OFFSET(tabsize), AV_OPT_TYPE_INT, {.i64=4}, 0, INT_MAX, FLAGS}, + {"boxcolor", "set box color", OFFSET(boxcolor.rgba), AV_OPT_TYPE_COLOR, {.str="white"}, 0, 0, TFLAGS}, + {"bordercolor", "set border color", OFFSET(bordercolor.rgba), AV_OPT_TYPE_COLOR, {.str="black"}, 0, 0, TFLAGS}, + {"shadowcolor", "set shadow color", OFFSET(shadowcolor.rgba), AV_OPT_TYPE_COLOR, {.str="black"}, 0, 0, TFLAGS}, + {"box", "set box", OFFSET(draw_box), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1, TFLAGS}, + {"boxborderw", "set box borders width", OFFSET(boxborderw), AV_OPT_TYPE_STRING, {.str="0"}, 0, 0, TFLAGS}, + {"line_spacing", "set line spacing in pixels", OFFSET(line_spacing), AV_OPT_TYPE_INT, {.i64=0}, INT_MIN, INT_MAX, TFLAGS}, + {"fontsize", "set font size", OFFSET(fontsize_expr), AV_OPT_TYPE_STRING, {.str=NULL}, 0, 0, TFLAGS}, + {"text_align", "set text alignment", OFFSET(text_align), AV_OPT_TYPE_STRING, {.str="TL"}, 0, 0, TFLAGS}, + {"x", "set x expression", OFFSET(x_expr), AV_OPT_TYPE_STRING, {.str="0"}, 0, 0, TFLAGS}, + {"y", "set y expression", OFFSET(y_expr), AV_OPT_TYPE_STRING, {.str="0"}, 0, 0, TFLAGS}, + {"boxw", "set box width", OFFSET(boxw), AV_OPT_TYPE_INT, {.i64=0}, 0, INT_MAX, TFLAGS}, + {"boxh", "set box height", OFFSET(boxh), AV_OPT_TYPE_INT, {.i64=0}, 0, INT_MAX, TFLAGS}, + {"shadowx", "set shadow x offset", OFFSET(shadowx), AV_OPT_TYPE_INT, {.i64=0}, INT_MIN, INT_MAX, TFLAGS}, + {"shadowy", "set shadow y offset", OFFSET(shadowy), AV_OPT_TYPE_INT, {.i64=0}, INT_MIN, INT_MAX, TFLAGS}, + {"borderw", "set border width", OFFSET(borderw), AV_OPT_TYPE_INT, {.i64=0}, INT_MIN, INT_MAX, TFLAGS}, + {"tabsize", "set tab size", OFFSET(tabsize), AV_OPT_TYPE_INT, {.i64=4}, 0, INT_MAX, TFLAGS}, {"basetime", "set base time", OFFSET(basetime), AV_OPT_TYPE_INT64, {.i64=AV_NOPTS_VALUE}, INT64_MIN, INT64_MAX, FLAGS}, #if CONFIG_LIBFONTCONFIG { "font", "Font name", OFFSET(font), AV_OPT_TYPE_STRING, { .str = "Sans" }, .flags = FLAGS }, @@ -360,7 +361,7 @@ static const AVOption drawtext_options[]= { {"none", "set no expansion", OFFSET(exp_mode), AV_OPT_TYPE_CONST, {.i64=EXP_NONE}, 0, 0, FLAGS, "expansion"}, {"normal", "set normal expansion", OFFSET(exp_mode), AV_OPT_TYPE_CONST, {.i64=EXP_NORMAL}, 0, 0, FLAGS, "expansion"}, {"strftime", "set strftime expansion (deprecated)", OFFSET(exp_mode), AV_OPT_TYPE_CONST, {.i64=EXP_STRFTIME}, 0, 0, FLAGS, "expansion"}, - {"y_align", "set the y alignment", OFFSET(y_align), AV_OPT_TYPE_INT, {.i64=YA_TEXT}, 0, 2, FLAGS, "y_align"}, + {"y_align", "set the y alignment", OFFSET(y_align), AV_OPT_TYPE_INT, {.i64=YA_TEXT}, 0, 2, TFLAGS, "y_align"}, {"text", "y is referred to the top of the first text line", OFFSET(y_align), AV_OPT_TYPE_CONST, {.i64=YA_TEXT}, 0, 0, FLAGS, "y_align"}, {"baseline", "y is referred to the baseline of the first line", OFFSET(y_align), AV_OPT_TYPE_CONST, {.i64=YA_BASELINE}, 0, 0, FLAGS, "y_align"}, {"font", "y is referred to the font defined line metrics", OFFSET(y_align), AV_OPT_TYPE_CONST, {.i64=YA_FONT}, 0, 0, FLAGS, "y_align"}, @@ -371,7 +372,7 @@ static const AVOption drawtext_options[]= { {"r", "set rate (timecode only)", OFFSET(tc_rate), AV_OPT_TYPE_RATIONAL, {.dbl=0}, 0, INT_MAX, FLAGS}, {"rate", "set rate (timecode only)", OFFSET(tc_rate), AV_OPT_TYPE_RATIONAL, {.dbl=0}, 0, INT_MAX, FLAGS}, {"reload", "reload text file at specified frame interval", OFFSET(reload), AV_OPT_TYPE_INT, {.i64=0}, 0, INT_MAX, FLAGS}, - {"alpha", "apply alpha while rendering", OFFSET(a_expr), AV_OPT_TYPE_STRING, {.str = "1"}, .flags = FLAGS}, + {"alpha", "apply alpha while rendering", OFFSET(a_expr), AV_OPT_TYPE_STRING, {.str = "1"}, .flags = TFLAGS}, {"fix_bounds", "check and fix text coords to avoid clipping", OFFSET(fix_bounds), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1, FLAGS}, {"start_number", "start frame number for n/frame_num variable", OFFSET(start_number), AV_OPT_TYPE_INT, {.i64=0}, 0, INT_MAX, FLAGS}, {"text_source", "the source of text", OFFSET(text_source_string), AV_OPT_TYPE_STRING, {.str=NULL}, 0, 1, FLAGS }, @@ -998,6 +999,23 @@ static int query_formats(AVFilterContext *ctx) return ff_set_common_formats(ctx, ff_draw_supported_pixel_formats(0)); } +static int glyph_enu_border_free(void *opaque, void *elem) +{ + Glyph *glyph = elem; + + if (glyph->border_glyph != NULL) { + for (int t = 0; t < 16; ++t) { + if (glyph->border_bglyph[t] != NULL) { + FT_Done_Glyph((FT_Glyph)glyph->border_bglyph[t]); + glyph->border_bglyph[t] = NULL; + } + } + FT_Done_Glyph(glyph->border_glyph); + glyph->border_glyph = NULL; + } + return 0; +} + static int glyph_enu_free(void *opaque, void *elem) { Glyph *glyph = elem; @@ -1120,8 +1138,28 @@ static int command(AVFilterContext *ctx, const char *cmd, const char *arg, char ctx->priv = new; return config_input(ctx->inputs[0]); - } else - return AVERROR(ENOSYS); + } else { + int old_borderw = old->borderw; + if ((ret = ff_filter_process_command(ctx, cmd, arg, res, res_len, flags)) < 0) { + return ret; + } + if (old->borderw != old_borderw) { + FT_Stroker_Set(old->stroker, old->borderw << 6, FT_STROKER_LINECAP_ROUND, + FT_STROKER_LINEJOIN_ROUND, 0); + // Dispose the old border glyphs + av_tree_enumerate(old->glyphs, NULL, NULL, glyph_enu_border_free); + } else if (strcmp(cmd, "text_align") == 0) { + if (validate_text_align(old->text_align) != 0) { + av_log(ctx, AV_LOG_ERROR, + "Invalid command value '%s' for 'text_align'\n", old->text_align); + } + } else if (strcmp(cmd, "fontsize") == 0) { + av_expr_free(old->fontsize_pexpr); + old->fontsize_pexpr = NULL; + old->blank_advance64 = 0; + } + return config_input(ctx->inputs[0]); + } fail: av_log(ctx, AV_LOG_ERROR, "Failed to process command. Continuing with existing parameters.\n"); From ea190b8a2385ae527c2539ab63e668d02ca56b00 Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Mon, 19 Jun 2023 21:50:26 +0200 Subject: [PATCH 1585/2172] avfilter/vf_drawtext: use flags type of option for text_align --- doc/filters.texi | 2 +- libavfilter/vf_drawtext.c | 65 +++++++++++++++++---------------------- 2 files changed, 30 insertions(+), 37 deletions(-) diff --git a/doc/filters.texi b/doc/filters.texi index 3afcc23b6a3..59721457631 100644 --- a/doc/filters.texi +++ b/doc/filters.texi @@ -12386,7 +12386,7 @@ Set the line spacing in pixels. The default value of @var{line_spacing} is 0. @item text_align Set the vertical and horizontal alignment of the text with respect to the box boundaries. -The value must contain exactly two letters, one for the vertical alignment (T=top, +The value is combination of flags, one for the vertical alignment (T=top, M=middle, B=bottom) and one for the horizontal alignment (L=left, C=center, R=right). Please note that tab characters are only supported with the left horizontal alignment. diff --git a/libavfilter/vf_drawtext.c b/libavfilter/vf_drawtext.c index 4c5c5d8bd65..7854362eab5 100644 --- a/libavfilter/vf_drawtext.c +++ b/libavfilter/vf_drawtext.c @@ -177,6 +177,13 @@ enum y_alignment { YA_FONT, }; +enum text_alignment { + TA_LEFT = (1 << 0), + TA_RIGHT = (1 << 1), + TA_TOP = (1 << 2), + TA_BOTTOM = (1 << 3), +}; + typedef struct HarfbuzzData { hb_buffer_t* buf; hb_font_t* font; @@ -315,7 +322,7 @@ typedef struct DrawTextContext { int boxw; ///< the value of the boxw parameter int boxh; ///< the value of the boxh parameter - uint8_t *text_align; ///< the horizontal and vertical text alignment + int text_align; ///< the horizontal and vertical text alignment int y_align; ///< the value of the y_align parameter TextLine *lines; ///< computed information about text lines @@ -343,7 +350,19 @@ static const AVOption drawtext_options[]= { {"boxborderw", "set box borders width", OFFSET(boxborderw), AV_OPT_TYPE_STRING, {.str="0"}, 0, 0, TFLAGS}, {"line_spacing", "set line spacing in pixels", OFFSET(line_spacing), AV_OPT_TYPE_INT, {.i64=0}, INT_MIN, INT_MAX, TFLAGS}, {"fontsize", "set font size", OFFSET(fontsize_expr), AV_OPT_TYPE_STRING, {.str=NULL}, 0, 0, TFLAGS}, - {"text_align", "set text alignment", OFFSET(text_align), AV_OPT_TYPE_STRING, {.str="TL"}, 0, 0, TFLAGS}, + {"text_align", "set text alignment", OFFSET(text_align), AV_OPT_TYPE_FLAGS, {.i64=0}, 0, (TA_LEFT|TA_RIGHT|TA_TOP|TA_BOTTOM), TFLAGS, "text_align"}, + { "left", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = TA_LEFT }, .flags = TFLAGS, .unit = "text_align" }, + { "L", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = TA_LEFT }, .flags = TFLAGS, .unit = "text_align" }, + { "right", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = TA_RIGHT }, .flags = TFLAGS, .unit = "text_align" }, + { "R", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = TA_RIGHT }, .flags = TFLAGS, .unit = "text_align" }, + { "center", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = (TA_LEFT|TA_RIGHT) }, .flags = TFLAGS, .unit = "text_align" }, + { "C", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = (TA_LEFT|TA_RIGHT) }, .flags = TFLAGS, .unit = "text_align" }, + { "top", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = TA_TOP }, .flags = TFLAGS, .unit = "text_align" }, + { "T", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = TA_TOP }, .flags = TFLAGS, .unit = "text_align" }, + { "bottom", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = TA_BOTTOM }, .flags = TFLAGS, .unit = "text_align" }, + { "B", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = TA_BOTTOM }, .flags = TFLAGS, .unit = "text_align" }, + { "middle", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = (TA_TOP|TA_BOTTOM) }, .flags = TFLAGS, .unit = "text_align" }, + { "M", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = (TA_TOP|TA_BOTTOM) }, .flags = TFLAGS, .unit = "text_align" }, {"x", "set x expression", OFFSET(x_expr), AV_OPT_TYPE_STRING, {.str="0"}, 0, 0, TFLAGS}, {"y", "set y expression", OFFSET(y_expr), AV_OPT_TYPE_STRING, {.str="0"}, 0, 0, TFLAGS}, {"boxw", "set box width", OFFSET(boxw), AV_OPT_TYPE_INT, {.i64=0}, 0, INT_MAX, TFLAGS}, @@ -866,19 +885,6 @@ static int string_to_array(const char *source, int *result, int result_size) return counter; } -static int validate_text_align(char* text_align) -{ - int err = 0; - if (strlen(text_align) != 2 - || strchr("LCRTMB", text_align[0]) == NULL || strchr("LCRTMB", text_align[1]) == NULL - || (strchr("TMB", text_align[0]) != NULL && strchr("LCR", text_align[1]) == NULL) - || (strchr("LCR", text_align[0]) != NULL && strchr("TMB", text_align[1]) == NULL)) { - err = AVERROR(EINVAL); - } - - return err; -} - static av_cold int init(AVFilterContext *ctx) { int err; @@ -944,14 +950,6 @@ static av_cold int init(AVFilterContext *ctx) return AVERROR(EINVAL); } - if ((err = validate_text_align(s->text_align))) { - av_log(ctx, AV_LOG_ERROR, - "The value provided for parameter 'text_align' is not valid,\n"); - av_log(ctx, AV_LOG_ERROR, - "please specify a two characters string containing only one letter for horizontal alignment ('LCR') and one for vertical alignment ('TMB')\n"); - return err; - } - #if CONFIG_LIBFRIBIDI if (s->text_shaping) if ((err = shape_text(ctx)) < 0) @@ -1148,11 +1146,6 @@ static int command(AVFilterContext *ctx, const char *cmd, const char *arg, char FT_STROKER_LINEJOIN_ROUND, 0); // Dispose the old border glyphs av_tree_enumerate(old->glyphs, NULL, NULL, glyph_enu_border_free); - } else if (strcmp(cmd, "text_align") == 0) { - if (validate_text_align(old->text_align) != 0) { - av_log(ctx, AV_LOG_ERROR, - "Invalid command value '%s' for 'text_align'\n", old->text_align); - } } else if (strcmp(cmd, "fontsize") == 0) { av_expr_free(old->fontsize_pexpr); old->fontsize_pexpr = NULL; @@ -1561,22 +1554,22 @@ static int draw_glyphs(DrawTextContext *s, AVFrame *frame, Glyph dummy = { 0 }, *glyph; FT_Bitmap bitmap; FT_BitmapGlyph b_glyph; - uint8_t j_center = 0, j_right = 0, j_middle = 0, j_bottom = 0; + uint8_t j_left = 0, j_right = 0, j_top = 0, j_bottom = 0; int line_w, offset_y = 0; int clip_x = 0, clip_y = 0; - j_center = strstr(s->text_align, "C") > 0; - j_right = strstr(s->text_align, "R") > 0; - j_middle = strstr(s->text_align, "M") > 0; - j_bottom = strstr(s->text_align, "B") > 0; + j_left = !!(s->text_align & TA_LEFT); + j_right = !!(s->text_align & TA_RIGHT); + j_top = !!(s->text_align & TA_TOP); + j_bottom = !!(s->text_align & TA_BOTTOM); - if (j_middle) { + if (j_top && j_bottom) { offset_y = (s->box_height - metrics->height) / 2; } else if (j_bottom) { offset_y = s->box_height - metrics->height; } - if ((j_right || j_center) && !s->tab_warning_printed && s->tab_count > 0) { + if ((!j_left || j_right) && !s->tab_warning_printed && s->tab_count > 0) { s->tab_warning_printed = 1; av_log(s, AV_LOG_WARNING, "Tab characters are only supported with left horizontal alignment\n"); } @@ -1604,7 +1597,7 @@ static int draw_glyphs(DrawTextContext *s, AVFrame *frame, w1 = bitmap.width; h1 = bitmap.rows; - if (j_center) { + if (j_left && j_right) { x1 += (s->box_width - line_w) / 2; } else if (j_right) { x1 += s->box_width - line_w; From 5b372c7ff2804f864af4cb127cf25760eff150ed Mon Sep 17 00:00:00 2001 From: James Almer Date: Mon, 19 Jun 2023 19:43:12 -0300 Subject: [PATCH 1586/2172] avcodec/evc_ps: use get_bits1() where useful Signed-off-by: James Almer --- libavcodec/evc_ps.c | 74 ++++++++++++++++++++++----------------------- 1 file changed, 37 insertions(+), 37 deletions(-) diff --git a/libavcodec/evc_ps.c b/libavcodec/evc_ps.c index 075e705d3db..ed39af104e8 100644 --- a/libavcodec/evc_ps.c +++ b/libavcodec/evc_ps.c @@ -177,7 +177,7 @@ int ff_evc_parse_sps(EVCParamSets *ps, const uint8_t *bs, int bs_size) sps->bit_depth_luma_minus8 = get_ue_golomb(&gb); sps->bit_depth_chroma_minus8 = get_ue_golomb(&gb); - sps->sps_btt_flag = get_bits(&gb, 1); + sps->sps_btt_flag = get_bits1(&gb); if (sps->sps_btt_flag) { sps->log2_ctu_size_minus5 = get_ue_golomb(&gb); sps->log2_min_cb_size_minus2 = get_ue_golomb(&gb); @@ -186,43 +186,43 @@ int ff_evc_parse_sps(EVCParamSets *ps, const uint8_t *bs, int bs_size) sps->log2_diff_min_cb_min_tt_cb_size_minus2 = get_ue_golomb(&gb); } - sps->sps_suco_flag = get_bits(&gb, 1); + sps->sps_suco_flag = get_bits1(&gb); if (sps->sps_suco_flag) { sps->log2_diff_ctu_size_max_suco_cb_size = get_ue_golomb(&gb); sps->log2_diff_max_suco_min_suco_cb_size = get_ue_golomb(&gb); } - sps->sps_admvp_flag = get_bits(&gb, 1); + sps->sps_admvp_flag = get_bits1(&gb); if (sps->sps_admvp_flag) { - sps->sps_affine_flag = get_bits(&gb, 1); - sps->sps_amvr_flag = get_bits(&gb, 1); - sps->sps_dmvr_flag = get_bits(&gb, 1); - sps->sps_mmvd_flag = get_bits(&gb, 1); - sps->sps_hmvp_flag = get_bits(&gb, 1); + sps->sps_affine_flag = get_bits1(&gb); + sps->sps_amvr_flag = get_bits1(&gb); + sps->sps_dmvr_flag = get_bits1(&gb); + sps->sps_mmvd_flag = get_bits1(&gb); + sps->sps_hmvp_flag = get_bits1(&gb); } - sps->sps_eipd_flag = get_bits(&gb, 1); + sps->sps_eipd_flag = get_bits1(&gb); if (sps->sps_eipd_flag) { - sps->sps_ibc_flag = get_bits(&gb, 1); + sps->sps_ibc_flag = get_bits1(&gb); if (sps->sps_ibc_flag) sps->log2_max_ibc_cand_size_minus2 = get_ue_golomb(&gb); } - sps->sps_cm_init_flag = get_bits(&gb, 1); + sps->sps_cm_init_flag = get_bits1(&gb); if (sps->sps_cm_init_flag) - sps->sps_adcc_flag = get_bits(&gb, 1); + sps->sps_adcc_flag = get_bits1(&gb); - sps->sps_iqt_flag = get_bits(&gb, 1); + sps->sps_iqt_flag = get_bits1(&gb); if (sps->sps_iqt_flag) - sps->sps_ats_flag = get_bits(&gb, 1); + sps->sps_ats_flag = get_bits1(&gb); - sps->sps_addb_flag = get_bits(&gb, 1); - sps->sps_alf_flag = get_bits(&gb, 1); - sps->sps_htdf_flag = get_bits(&gb, 1); - sps->sps_rpl_flag = get_bits(&gb, 1); - sps->sps_pocs_flag = get_bits(&gb, 1); - sps->sps_dquant_flag = get_bits(&gb, 1); - sps->sps_dra_flag = get_bits(&gb, 1); + sps->sps_addb_flag = get_bits1(&gb); + sps->sps_alf_flag = get_bits1(&gb); + sps->sps_htdf_flag = get_bits1(&gb); + sps->sps_rpl_flag = get_bits1(&gb); + sps->sps_pocs_flag = get_bits1(&gb); + sps->sps_dquant_flag = get_bits1(&gb); + sps->sps_dra_flag = get_bits1(&gb); if (sps->sps_pocs_flag) { sps->log2_max_pic_order_cnt_lsb_minus4 = get_ue_golomb(&gb); @@ -246,8 +246,8 @@ int ff_evc_parse_sps(EVCParamSets *ps, const uint8_t *bs, int bs_size) sps->max_num_tid0_ref_pics = get_ue_golomb(&gb); else { sps->sps_max_dec_pic_buffering_minus1 = get_ue_golomb(&gb); - sps->long_term_ref_pic_flag = get_bits(&gb, 1); - sps->rpl1_same_as_rpl0_flag = get_bits(&gb, 1); + sps->long_term_ref_pic_flag = get_bits1(&gb); + sps->rpl1_same_as_rpl0_flag = get_bits1(&gb); sps->num_ref_pic_list_in_sps[0] = get_ue_golomb(&gb); for (int i = 0; i < sps->num_ref_pic_list_in_sps[0]; ++i) @@ -260,7 +260,7 @@ int ff_evc_parse_sps(EVCParamSets *ps, const uint8_t *bs, int bs_size) } } - sps->picture_cropping_flag = get_bits(&gb, 1); + sps->picture_cropping_flag = get_bits1(&gb); if (sps->picture_cropping_flag) { sps->picture_crop_left_offset = get_ue_golomb(&gb); @@ -270,11 +270,11 @@ int ff_evc_parse_sps(EVCParamSets *ps, const uint8_t *bs, int bs_size) } if (sps->chroma_format_idc != 0) { - sps->chroma_qp_table_struct.chroma_qp_table_present_flag = get_bits(&gb, 1); + sps->chroma_qp_table_struct.chroma_qp_table_present_flag = get_bits1(&gb); if (sps->chroma_qp_table_struct.chroma_qp_table_present_flag) { - sps->chroma_qp_table_struct.same_qp_table_for_chroma = get_bits(&gb, 1); - sps->chroma_qp_table_struct.global_offset_flag = get_bits(&gb, 1); + sps->chroma_qp_table_struct.same_qp_table_for_chroma = get_bits1(&gb); + sps->chroma_qp_table_struct.global_offset_flag = get_bits1(&gb); for (int i = 0; i < (sps->chroma_qp_table_struct.same_qp_table_for_chroma ? 1 : 2); i++) { sps->chroma_qp_table_struct.num_points_in_qp_table_minus1[i] = get_ue_golomb(&gb); if (sps->chroma_qp_table_struct.num_points_in_qp_table_minus1[i] >= EVC_MAX_QP_TABLE_SIZE) { @@ -289,7 +289,7 @@ int ff_evc_parse_sps(EVCParamSets *ps, const uint8_t *bs, int bs_size) } } - sps->vui_parameters_present_flag = get_bits(&gb, 1); + sps->vui_parameters_present_flag = get_bits1(&gb); if (sps->vui_parameters_present_flag) vui_parameters(&gb, &(sps->vui_parameters)); @@ -345,8 +345,8 @@ int ff_evc_parse_pps(EVCParamSets *ps, const uint8_t *bs, int bs_size) pps->num_ref_idx_default_active_minus1[0] = get_ue_golomb(&gb); pps->num_ref_idx_default_active_minus1[1] = get_ue_golomb(&gb); pps->additional_lt_poc_lsb_len = get_ue_golomb(&gb); - pps->rpl1_idx_present_flag = get_bits(&gb, 1); - pps->single_tile_in_pic_flag = get_bits(&gb, 1); + pps->rpl1_idx_present_flag = get_bits1(&gb); + pps->single_tile_in_pic_flag = get_bits1(&gb); if (!pps->single_tile_in_pic_flag) { pps->num_tile_columns_minus1 = get_ue_golomb(&gb); @@ -356,7 +356,7 @@ int ff_evc_parse_pps(EVCParamSets *ps, const uint8_t *bs, int bs_size) ret = AVERROR_INVALIDDATA; goto fail; } - pps->uniform_tile_spacing_flag = get_bits(&gb, 1); + pps->uniform_tile_spacing_flag = get_bits1(&gb); if (!pps->uniform_tile_spacing_flag) { for (int i = 0; i < pps->num_tile_columns_minus1; i++) @@ -365,7 +365,7 @@ int ff_evc_parse_pps(EVCParamSets *ps, const uint8_t *bs, int bs_size) for (int i = 0; i < pps->num_tile_rows_minus1; i++) pps->tile_row_height_minus1[i] = get_ue_golomb(&gb); } - pps->loop_filter_across_tiles_enabled_flag = get_bits(&gb, 1); + pps->loop_filter_across_tiles_enabled_flag = get_bits1(&gb); pps->tile_offset_len_minus1 = get_ue_golomb(&gb); } @@ -374,7 +374,7 @@ int ff_evc_parse_pps(EVCParamSets *ps, const uint8_t *bs, int bs_size) ret = AVERROR_INVALIDDATA; goto fail; } - pps->explicit_tile_id_flag = get_bits(&gb, 1); + pps->explicit_tile_id_flag = get_bits1(&gb); if (pps->explicit_tile_id_flag) { for (int i = 0; i <= pps->num_tile_rows_minus1; i++) { @@ -384,14 +384,14 @@ int ff_evc_parse_pps(EVCParamSets *ps, const uint8_t *bs, int bs_size) } pps->pic_dra_enabled_flag = 0; - pps->pic_dra_enabled_flag = get_bits(&gb, 1); + pps->pic_dra_enabled_flag = get_bits1(&gb); if (pps->pic_dra_enabled_flag) pps->pic_dra_aps_id = get_bits(&gb, 5); - pps->arbitrary_slice_present_flag = get_bits(&gb, 1); - pps->constrained_intra_pred_flag = get_bits(&gb, 1); - pps->cu_qp_delta_enabled_flag = get_bits(&gb, 1); + pps->arbitrary_slice_present_flag = get_bits1(&gb); + pps->constrained_intra_pred_flag = get_bits1(&gb); + pps->cu_qp_delta_enabled_flag = get_bits1(&gb); if (pps->cu_qp_delta_enabled_flag) pps->log2_cu_qp_delta_area_minus6 = get_ue_golomb(&gb); From 7ff3dce29a7cadbe4790d3b6df080fc82fc0e04b Mon Sep 17 00:00:00 2001 From: James Almer Date: Mon, 19 Jun 2023 19:43:17 -0300 Subject: [PATCH 1587/2172] avcodec/evc_parse: use get_bits1() where useful Signed-off-by: James Almer --- libavcodec/evc_parse.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/libavcodec/evc_parse.c b/libavcodec/evc_parse.c index 18827ffa635..0c35e40b476 100644 --- a/libavcodec/evc_parse.c +++ b/libavcodec/evc_parse.c @@ -75,14 +75,14 @@ int ff_evc_parse_slice_header(EVCParserSliceHeader *sh, const EVCParamSets *ps, sh->slice_pic_parameter_set_id = slice_pic_parameter_set_id; if (!pps->single_tile_in_pic_flag) { - sh->single_tile_in_slice_flag = get_bits(&gb, 1); + sh->single_tile_in_slice_flag = get_bits1(&gb); sh->first_tile_id = get_bits(&gb, pps->tile_id_len_minus1 + 1); } else sh->single_tile_in_slice_flag = 1; if (!sh->single_tile_in_slice_flag) { if (pps->arbitrary_slice_present_flag) - sh->arbitrary_slice_flag = get_bits(&gb, 1); + sh->arbitrary_slice_flag = get_bits1(&gb); if (!sh->arbitrary_slice_flag) sh->last_tile_id = get_bits(&gb, pps->tile_id_len_minus1 + 1); @@ -97,21 +97,21 @@ int ff_evc_parse_slice_header(EVCParserSliceHeader *sh, const EVCParamSets *ps, sh->slice_type = get_ue_golomb(&gb); if (nalu_type == EVC_IDR_NUT) - sh->no_output_of_prior_pics_flag = get_bits(&gb, 1); + sh->no_output_of_prior_pics_flag = get_bits1(&gb); if (sps->sps_mmvd_flag && ((sh->slice_type == EVC_SLICE_TYPE_B) || (sh->slice_type == EVC_SLICE_TYPE_P))) - sh->mmvd_group_enable_flag = get_bits(&gb, 1); + sh->mmvd_group_enable_flag = get_bits1(&gb); else sh->mmvd_group_enable_flag = 0; if (sps->sps_alf_flag) { int ChromaArrayType = sps->chroma_format_idc; - sh->slice_alf_enabled_flag = get_bits(&gb, 1); + sh->slice_alf_enabled_flag = get_bits1(&gb); if (sh->slice_alf_enabled_flag) { sh->slice_alf_luma_aps_id = get_bits(&gb, 5); - sh->slice_alf_map_flag = get_bits(&gb, 1); + sh->slice_alf_map_flag = get_bits1(&gb); sh->slice_alf_chroma_idc = get_bits(&gb, 2); if ((ChromaArrayType == 1 || ChromaArrayType == 2) && sh->slice_alf_chroma_idc > 0) @@ -140,12 +140,12 @@ int ff_evc_parse_slice_header(EVCParserSliceHeader *sh, const EVCParamSets *ps, if (sliceChromaAlfEnabledFlag) { sh->slice_alf_chroma_aps_id = get_bits(&gb, 5); - sh->slice_alf_chroma_map_flag = get_bits(&gb, 1); + sh->slice_alf_chroma_map_flag = get_bits1(&gb); } if (sliceChroma2AlfEnabledFlag) { sh->slice_alf_chroma2_aps_id = get_bits(&gb, 5); - sh->slice_alf_chroma2_map_flag = get_bits(&gb, 1); + sh->slice_alf_chroma2_map_flag = get_bits1(&gb); } } } From 2bc65003e2861eeeeae4db828890df33d2fc037c Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Tue, 20 Jun 2023 01:01:58 +0200 Subject: [PATCH 1588/2172] avcodec: AC-4 codec registration --- libavcodec/codec_desc.c | 7 +++++++ libavcodec/codec_id.h | 1 + libavcodec/version.h | 4 ++-- 3 files changed, 10 insertions(+), 2 deletions(-) diff --git a/libavcodec/codec_desc.c b/libavcodec/codec_desc.c index 3e31a1eed61..4406dd8318f 100644 --- a/libavcodec/codec_desc.c +++ b/libavcodec/codec_desc.c @@ -3406,6 +3406,13 @@ static const AVCodecDescriptor codec_descriptors[] = { .long_name = NULL_IF_CONFIG_SMALL("RKA (RK Audio)"), .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSY | AV_CODEC_PROP_LOSSLESS, }, + { + .id = AV_CODEC_ID_AC4, + .type = AVMEDIA_TYPE_AUDIO, + .name = "ac4", + .long_name = NULL_IF_CONFIG_SMALL("AC-4"), + .props = AV_CODEC_PROP_LOSSY, + }, /* subtitle codecs */ { diff --git a/libavcodec/codec_id.h b/libavcodec/codec_id.h index d23549d7e0c..a5a0cb85255 100644 --- a/libavcodec/codec_id.h +++ b/libavcodec/codec_id.h @@ -542,6 +542,7 @@ enum AVCodecID { AV_CODEC_ID_FTR, AV_CODEC_ID_WAVARC, AV_CODEC_ID_RKA, + AV_CODEC_ID_AC4, /* subtitle codecs */ AV_CODEC_ID_FIRST_SUBTITLE = 0x17000, ///< A dummy ID pointing at the start of subtitle codecs. diff --git a/libavcodec/version.h b/libavcodec/version.h index ef9018e70b9..da6f3a84ac1 100644 --- a/libavcodec/version.h +++ b/libavcodec/version.h @@ -29,8 +29,8 @@ #include "version_major.h" -#define LIBAVCODEC_VERSION_MINOR 20 -#define LIBAVCODEC_VERSION_MICRO 101 +#define LIBAVCODEC_VERSION_MINOR 21 +#define LIBAVCODEC_VERSION_MICRO 100 #define LIBAVCODEC_VERSION_INT AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \ LIBAVCODEC_VERSION_MINOR, \ From 9c6538d4c2d045cc55674adde7a758fd24e7b79e Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Tue, 19 Feb 2019 20:30:55 +0100 Subject: [PATCH 1589/2172] avformat: add raw AC-4 demuxer --- libavformat/Makefile | 1 + libavformat/ac4dec.c | 104 +++++++++++++++++++++++++++++++++++++++ libavformat/allformats.c | 1 + libavformat/version.h | 2 +- 4 files changed, 107 insertions(+), 1 deletion(-) create mode 100644 libavformat/ac4dec.c diff --git a/libavformat/Makefile b/libavformat/Makefile index d3503196e33..2c037c0b24c 100644 --- a/libavformat/Makefile +++ b/libavformat/Makefile @@ -77,6 +77,7 @@ OBJS-$(CONFIG_AAC_DEMUXER) += aacdec.o apetag.o img2.o rawdec.o OBJS-$(CONFIG_AAX_DEMUXER) += aaxdec.o OBJS-$(CONFIG_AC3_DEMUXER) += ac3dec.o rawdec.o OBJS-$(CONFIG_AC3_MUXER) += rawenc.o +OBJS-$(CONFIG_AC4_DEMUXER) += ac4dec.o OBJS-$(CONFIG_ACE_DEMUXER) += acedec.o OBJS-$(CONFIG_ACM_DEMUXER) += acm.o rawdec.o OBJS-$(CONFIG_ACT_DEMUXER) += act.o diff --git a/libavformat/ac4dec.c b/libavformat/ac4dec.c new file mode 100644 index 00000000000..eb7bbaa655c --- /dev/null +++ b/libavformat/ac4dec.c @@ -0,0 +1,104 @@ +/* + * RAW AC-4 demuxer + * Copyright (c) 2019 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 "libavutil/avassert.h" +#include "libavutil/crc.h" +#include "avformat.h" +#include "rawdec.h" + +static int ac4_probe(const AVProbeData *p) +{ + const uint8_t *buf = p->buf; + int left = p->buf_size; + int max_frames = 0; + + while (left > 7) { + int size; + + if (buf[0] == 0xAC && + (buf[1] == 0x40 || + buf[1] == 0x41)) { + size = (buf[2] << 8) | buf[3]; + if (size == 0xFFFF) + size = 3 + ((buf[4] << 16) | (buf[5] << 8) | buf[6]); + size += 4; + if (buf[1] == 0x41) + size += 2; + max_frames++; + left -= size; + buf += size; + } else { + break; + } + } + + return FFMIN(AVPROBE_SCORE_MAX, max_frames * 7); +} + +static int ac4_read_header(AVFormatContext *s) +{ + AVStream *st; + + st = avformat_new_stream(s, NULL); + if (!st) + return AVERROR(ENOMEM); + + st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO; + st->codecpar->codec_id = AV_CODEC_ID_AC4; + + return 0; +} + +static int ac4_read_packet(AVFormatContext *s, AVPacket *pkt) +{ + AVIOContext *pb = s->pb; + int64_t pos; + uint16_t sync; + int ret, size; + + if (avio_feof(s->pb)) + return AVERROR_EOF; + + pos = avio_tell(s->pb); + sync = avio_rb16(pb); + size = avio_rb16(pb); + if (size == 0xffff) + size = avio_rb24(pb); + + ret = av_get_packet(pb, pkt, size); + pkt->pos = pos; + pkt->stream_index = 0; + + if (sync == 0xAC41) + avio_skip(pb, 2); + + return ret; +} + +AVInputFormat ff_ac4_demuxer = { + .name = "ac4", + .long_name = NULL_IF_CONFIG_SMALL("raw AC-4"), + .read_probe = ac4_probe, + .read_header = ac4_read_header, + .read_packet = ac4_read_packet, + .flags = AVFMT_GENERIC_INDEX, + .extensions = "ac4", +}; diff --git a/libavformat/allformats.c b/libavformat/allformats.c index ae604236aef..70fa7f14608 100644 --- a/libavformat/allformats.c +++ b/libavformat/allformats.c @@ -34,6 +34,7 @@ extern const AVInputFormat ff_aac_demuxer; extern const AVInputFormat ff_aax_demuxer; extern const AVInputFormat ff_ac3_demuxer; extern const FFOutputFormat ff_ac3_muxer; +extern const AVInputFormat ff_ac4_demuxer; extern const AVInputFormat ff_ace_demuxer; extern const AVInputFormat ff_acm_demuxer; extern const AVInputFormat ff_act_demuxer; diff --git a/libavformat/version.h b/libavformat/version.h index 70c554c19c4..35d796d318c 100644 --- a/libavformat/version.h +++ b/libavformat/version.h @@ -31,7 +31,7 @@ #include "version_major.h" -#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 293e353460856f5f0f8c122a1d2b406fa39876be Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Mon, 5 Sep 2022 23:47:11 +0200 Subject: [PATCH 1590/2172] avformat/isom_tags: add AC-4 --- libavformat/isom_tags.c | 1 + 1 file changed, 1 insertion(+) diff --git a/libavformat/isom_tags.c b/libavformat/isom_tags.c index 2a29823b2ee..4738171a9ca 100644 --- a/libavformat/isom_tags.c +++ b/libavformat/isom_tags.c @@ -290,6 +290,7 @@ const AVCodecTag ff_codec_movaudio_tags[] = { { AV_CODEC_ID_AAC, MKTAG('m', 'p', '4', 'a') }, { AV_CODEC_ID_AC3, MKTAG('a', 'c', '-', '3') }, /* ETSI TS 102 366 Annex F */ { AV_CODEC_ID_AC3, MKTAG('s', 'a', 'c', '3') }, /* Nero Recode */ + { AV_CODEC_ID_AC4, MKTAG('a', 'c', '-', '4') }, { AV_CODEC_ID_ADPCM_IMA_QT, MKTAG('i', 'm', 'a', '4') }, { AV_CODEC_ID_ALAC, MKTAG('a', 'l', 'a', 'c') }, { AV_CODEC_ID_AMR_NB, MKTAG('s', 'a', 'm', 'r') }, /* AMR-NB 3gp */ From 961b17eace0eb36f201df97fe9067f3f57648332 Mon Sep 17 00:00:00 2001 From: Aman Karmani Date: Sun, 18 Jun 2023 13:39:42 +0200 Subject: [PATCH 1591/2172] avformat/mpegts: add AC-4 --- libavformat/mpegts.c | 1 + 1 file changed, 1 insertion(+) diff --git a/libavformat/mpegts.c b/libavformat/mpegts.c index 385d78b98bb..fb8b0bf8fd0 100644 --- a/libavformat/mpegts.c +++ b/libavformat/mpegts.c @@ -859,6 +859,7 @@ static const StreamType HLS_SAMPLE_ENC_types[] = { static const StreamType REGD_types[] = { { MKTAG('d', 'r', 'a', 'c'), AVMEDIA_TYPE_VIDEO, AV_CODEC_ID_DIRAC }, { MKTAG('A', 'C', '-', '3'), AVMEDIA_TYPE_AUDIO, AV_CODEC_ID_AC3 }, + { MKTAG('A', 'C', '-', '4'), AVMEDIA_TYPE_AUDIO, AV_CODEC_ID_AC4 }, { MKTAG('B', 'S', 'S', 'D'), AVMEDIA_TYPE_AUDIO, AV_CODEC_ID_S302M }, { MKTAG('D', 'T', 'S', '1'), AVMEDIA_TYPE_AUDIO, AV_CODEC_ID_DTS }, { MKTAG('D', 'T', 'S', '2'), AVMEDIA_TYPE_AUDIO, AV_CODEC_ID_DTS }, From da4b2549c65dcab733b50ba0a58ae846d705d2c8 Mon Sep 17 00:00:00 2001 From: "Yeoh, Hoong Tee" Date: Wed, 11 Jan 2023 01:35:47 +0000 Subject: [PATCH 1592/2172] lavf/rtpenc_jpeg: Retrieve sampling factor from SOF0 In ff_rtp_send_jpeg, the type is defined based on PIX_FMT and color-range parsed in. There is limitation on current design where need to include support newly introduced PIX_FMT such as AV_PIX_FMT_QSV and there might be more and more in future. Hence, retrive the sampling factor from SOF0 in JPEG compressed header directly. This introduces flexibility to handle different type of new codec introduced in future. Signed-off-by: Yeoh, Hoong Tee --- libavformat/rtpenc_jpeg.c | 41 +++++++++++++++++++++++++-------------- 1 file changed, 26 insertions(+), 15 deletions(-) diff --git a/libavformat/rtpenc_jpeg.c b/libavformat/rtpenc_jpeg.c index 91116832dad..e4e95931f45 100644 --- a/libavformat/rtpenc_jpeg.c +++ b/libavformat/rtpenc_jpeg.c @@ -30,7 +30,7 @@ void ff_rtp_send_jpeg(AVFormatContext *s1, const uint8_t *buf, int size) RTPMuxContext *s = s1->priv_data; const uint8_t *qtables[4] = { NULL }; int nb_qtables = 0; - uint8_t type; + uint8_t type = 2; /* initialized non-0/1 value for RTP/JPEG type check*/ uint8_t w, h; uint8_t *p; int off = 0; /* fragment offset of the current JPEG frame */ @@ -45,20 +45,6 @@ void ff_rtp_send_jpeg(AVFormatContext *s1, const uint8_t *buf, int size) w = AV_CEIL_RSHIFT(s1->streams[0]->codecpar->width, 3); h = AV_CEIL_RSHIFT(s1->streams[0]->codecpar->height, 3); - /* get the pixel format type or fail */ - if (s1->streams[0]->codecpar->format == AV_PIX_FMT_YUVJ422P || - (s1->streams[0]->codecpar->color_range == AVCOL_RANGE_JPEG && - s1->streams[0]->codecpar->format == AV_PIX_FMT_YUV422P)) { - type = 0; - } else if (s1->streams[0]->codecpar->format == AV_PIX_FMT_YUVJ420P || - (s1->streams[0]->codecpar->color_range == AVCOL_RANGE_JPEG && - s1->streams[0]->codecpar->format == AV_PIX_FMT_YUV420P)) { - type = 1; - } else { - av_log(s1, AV_LOG_ERROR, "Unsupported pixel format\n"); - return; - } - /* preparse the header for getting some info */ for (i = 0; i < size; i++) { if (buf[i] != 0xff) @@ -90,6 +76,23 @@ void ff_rtp_send_jpeg(AVFormatContext *s1, const uint8_t *buf, int size) "Only 1x1 chroma blocks are supported. Aborted!\n"); return; } + + /* + * Find out the sampling factor in SOF0. + * In SOF0, hsample/vsample is inserted in form of (2<<4) | (type ? 2 : 1). + * First 4-bit is hsample while Last 4-bit is vsample. + */ + + /* Luma channel sampling factor in 4:2:2 chroma subsampling are 2x1 */ + if (buf[i + 11] == 33) { + type = 0; + /* Luma channel sampling factor in 4:2:0 chroma subsampling are 2x2 */ + } else if (buf[i + 11] == 34) { + type = 1; + } else { + av_log(s1, AV_LOG_ERROR, "Unsupported pixel format\n"); + return; + } } else if (buf[i + 1] == DHT) { int dht_size = AV_RB16(&buf[i + 2]); default_huffman_tables |= 1 << 4; @@ -163,6 +166,14 @@ void ff_rtp_send_jpeg(AVFormatContext *s1, const uint8_t *buf, int size) break; } } + + /* Check validity of RTP/JPEG type */ + if (type != 0 && type != 1) { + av_log(s1, AV_LOG_ERROR, + "Invalid RTP/JPEG type\n"); + return; + } + if (default_huffman_tables && default_huffman_tables != 31) { av_log(s1, AV_LOG_ERROR, "RFC 2435 requires standard Huffman tables for jpeg\n"); From 07139b6deb83a760ef7ddec45797f32478118687 Mon Sep 17 00:00:00 2001 From: Haihao Xiang Date: Mon, 12 Jun 2023 16:14:43 +0800 Subject: [PATCH 1593/2172] lavfi/qsvvpp: track the runtime version in vpp context We may check whether a feature is supported via the runtime version in future. Signed-off-by: Haihao Xiang --- libavfilter/qsvvpp.c | 6 ++++++ libavfilter/qsvvpp.h | 2 ++ 2 files changed, 8 insertions(+) diff --git a/libavfilter/qsvvpp.c b/libavfilter/qsvvpp.c index b233b812435..779afce66dc 100644 --- a/libavfilter/qsvvpp.c +++ b/libavfilter/qsvvpp.c @@ -655,6 +655,12 @@ static int init_vpp_session(AVFilterContext *avctx, QSVVPPContext *s) if (ret) return ret; + ret = MFXQueryVersion(s->session, &s->ver); + if (ret != MFX_ERR_NONE) { + av_log(avctx, AV_LOG_ERROR, "Error querying the runtime version\n"); + return AVERROR_UNKNOWN; + } + if (handle) { ret = MFXVideoCORE_SetHandle(s->session, handle_type, handle); if (ret != MFX_ERR_NONE) diff --git a/libavfilter/qsvvpp.h b/libavfilter/qsvvpp.h index 3b321937440..8851185ff38 100644 --- a/libavfilter/qsvvpp.h +++ b/libavfilter/qsvvpp.h @@ -83,6 +83,8 @@ typedef struct QSVVPPContext { int eof; /** order with frame_out, sync */ AVFifo *async_fifo; + + mfxVersion ver; } QSVVPPContext; typedef struct QSVVPPCrop { From 5189b51939f4b1c21d0fb23b2303b07893c7f6a5 Mon Sep 17 00:00:00 2001 From: Haihao Xiang Date: Mon, 12 Jun 2023 16:14:44 +0800 Subject: [PATCH 1594/2172] lavfi/qsvvpp: copy metadata fields from src to dst Signed-off-by: Haihao Xiang --- libavfilter/qsvvpp.c | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/libavfilter/qsvvpp.c b/libavfilter/qsvvpp.c index 779afce66dc..61402c8e0ac 100644 --- a/libavfilter/qsvvpp.c +++ b/libavfilter/qsvvpp.c @@ -474,7 +474,7 @@ static QSVFrame *submit_frame(QSVVPPContext *s, AVFilterLink *inlink, AVFrame *p } /* get the output surface */ -static QSVFrame *query_frame(QSVVPPContext *s, AVFilterLink *outlink) +static QSVFrame *query_frame(QSVVPPContext *s, AVFilterLink *outlink, const AVFrame *in) { AVFilterContext *ctx = outlink->src; QSVFrame *out_frame; @@ -493,6 +493,12 @@ static QSVFrame *query_frame(QSVVPPContext *s, AVFilterLink *outlink) if (!out_frame->frame) return NULL; + ret = av_frame_copy_props(out_frame->frame, in); + if (ret < 0) { + av_log(ctx, AV_LOG_ERROR, "Failed to copy metadata fields from src to dst.\n"); + return NULL; + } + ret = av_hwframe_get_buffer(outlink->hw_frames_ctx, out_frame->frame, 0); if (ret < 0) { av_log(ctx, AV_LOG_ERROR, "Can't allocate a surface.\n"); @@ -509,6 +515,12 @@ static QSVFrame *query_frame(QSVVPPContext *s, AVFilterLink *outlink) if (!out_frame->frame) return NULL; + ret = av_frame_copy_props(out_frame->frame, in); + if (ret < 0) { + av_log(ctx, AV_LOG_ERROR, "Failed to copy metadata fields from src to dst.\n"); + return NULL; + } + ret = map_frame_to_surface(out_frame->frame, &out_frame->surface); if (ret < 0) @@ -884,7 +896,7 @@ int ff_qsvvpp_filter_frame(QSVVPPContext *s, AVFilterLink *inlink, AVFrame *picr } do { - out_frame = query_frame(s, outlink); + out_frame = query_frame(s, outlink, in_frame->frame); if (!out_frame) { av_log(ctx, AV_LOG_ERROR, "Failed to query an output frame.\n"); return AVERROR(ENOMEM); From 579711c2ccbaf5dc0e521980869be5bde54c437c Mon Sep 17 00:00:00 2001 From: Haihao Xiang Date: Mon, 12 Jun 2023 16:14:45 +0800 Subject: [PATCH 1595/2172] lavfi/qsvvpp: check the parameters before initializing vpp session According to the description about MFXVideoVPP_Query [1], we may call MFXVideoVPP_Query to check the validity of the parameters for vpp session, use the corrected values to initialize the session. [1] https://spec.oneapi.io/versions/latest/elements/oneVPL/source/API_ref/VPL_func_vid_vpp.html#mfxvideovpp-query Signed-off-by: Haihao Xiang --- libavfilter/qsvvpp.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/libavfilter/qsvvpp.c b/libavfilter/qsvvpp.c index 61402c8e0ac..8683a4f217b 100644 --- a/libavfilter/qsvvpp.c +++ b/libavfilter/qsvvpp.c @@ -823,6 +823,14 @@ int ff_qsvvpp_init(AVFilterContext *avctx, QSVVPPParam *param) ff_qsvvpp_print_iopattern(avctx, s->vpp_param.IOPattern & 0x0F, "VPP"); /* Print output memory mode */ ff_qsvvpp_print_iopattern(avctx, s->vpp_param.IOPattern & 0xF0, "VPP"); + + ret = MFXVideoVPP_Query(s->session, &s->vpp_param, &s->vpp_param); + if (ret < 0) { + ret = ff_qsvvpp_print_error(avctx, ret, "Error querying VPP params"); + goto failed; + } else if (ret > 0) + ff_qsvvpp_print_warning(avctx, ret, "Warning When querying VPP params"); + ret = MFXVideoVPP_Init(s->session, &s->vpp_param); if (ret < 0) { ret = ff_qsvvpp_print_error(avctx, ret, "Failed to create a qsvvpp"); From cf21ca9efbcafeb0a885ef1979258c9e4f10c63f Mon Sep 17 00:00:00 2001 From: Haihao Xiang Date: Mon, 12 Jun 2023 16:14:46 +0800 Subject: [PATCH 1596/2172] lavfi/qsvvpp: store a copy of the sequence parameters We will postpone the vpp session initialization to when input and output frames are ready, this copy of the sequence parameters will be used to initialize vpp session. Signed-off-by: Haihao Xiang --- libavfilter/qsvvpp.c | 42 ++++++++++++++++++++++++++---------------- libavfilter/qsvvpp.h | 7 ++++++- 2 files changed, 32 insertions(+), 17 deletions(-) diff --git a/libavfilter/qsvvpp.c b/libavfilter/qsvvpp.c index 8683a4f217b..d168ab5d1df 100644 --- a/libavfilter/qsvvpp.c +++ b/libavfilter/qsvvpp.c @@ -767,28 +767,39 @@ int ff_qsvvpp_init(AVFilterContext *avctx, QSVVPPParam *param) goto failed; } + s->nb_seq_buffers = param->num_ext_buf; #if QSV_HAVE_OPAQUE - if (IS_OPAQUE_MEMORY(s->in_mem_mode) || IS_OPAQUE_MEMORY(s->out_mem_mode)) { - s->nb_ext_buffers = param->num_ext_buf + 1; + if (IS_OPAQUE_MEMORY(s->in_mem_mode) || IS_OPAQUE_MEMORY(s->out_mem_mode)) + s->nb_seq_buffers++; +#endif + + if (s->nb_seq_buffers) { + s->seq_buffers = av_calloc(s->nb_seq_buffers, sizeof(*s->seq_buffers)); + if (!s->seq_buffers) { + ret = AVERROR(ENOMEM); + goto failed; + } + + for (i = 0; i < param->num_ext_buf; i++) + s->seq_buffers[i] = param->ext_buf[i]; + +#if QSV_HAVE_OPAQUE + if (IS_OPAQUE_MEMORY(s->in_mem_mode) || IS_OPAQUE_MEMORY(s->out_mem_mode)) + s->seq_buffers[i] = (mfxExtBuffer *)&s->opaque_alloc; +#endif + + s->nb_ext_buffers = s->nb_seq_buffers; s->ext_buffers = av_calloc(s->nb_ext_buffers, sizeof(*s->ext_buffers)); if (!s->ext_buffers) { ret = AVERROR(ENOMEM); goto failed; } - s->ext_buffers[0] = (mfxExtBuffer *)&s->opaque_alloc; - for (i = 1; i < param->num_ext_buf; i++) - s->ext_buffers[i] = param->ext_buf[i - 1]; - s->vpp_param.ExtParam = s->ext_buffers; - s->vpp_param.NumExtParam = s->nb_ext_buffers; - } else { - s->vpp_param.NumExtParam = param->num_ext_buf; - s->vpp_param.ExtParam = param->ext_buf; + memcpy(s->ext_buffers, s->seq_buffers, s->nb_seq_buffers * sizeof(*s->seq_buffers)); } -#else - s->vpp_param.NumExtParam = param->num_ext_buf; - s->vpp_param.ExtParam = param->ext_buf; -#endif + + s->vpp_param.ExtParam = s->ext_buffers; + s->vpp_param.NumExtParam = s->nb_ext_buffers; s->got_frame = 0; @@ -861,9 +872,8 @@ int ff_qsvvpp_close(AVFilterContext *avctx) clear_frame_list(&s->out_frame_list); av_freep(&s->surface_ptrs_in); av_freep(&s->surface_ptrs_out); -#if QSV_HAVE_OPAQUE + av_freep(&s->seq_buffers); av_freep(&s->ext_buffers); -#endif av_freep(&s->frame_infos); av_fifo_freep2(&s->async_fifo); diff --git a/libavfilter/qsvvpp.h b/libavfilter/qsvvpp.h index 8851185ff38..073c89fe701 100644 --- a/libavfilter/qsvvpp.h +++ b/libavfilter/qsvvpp.h @@ -74,9 +74,14 @@ typedef struct QSVVPPContext { #if QSV_HAVE_OPAQUE /** MFXVPP extern parameters */ mfxExtOpaqueSurfaceAlloc opaque_alloc; +#endif + /** store sequence parameters */ + mfxExtBuffer **seq_buffers; + int nb_seq_buffers; + + /** store all parameters for vpp execution, including parameters per frame */ mfxExtBuffer **ext_buffers; int nb_ext_buffers; -#endif int got_frame; int async_depth; From bcdea21675dac424daa4f4b356f1c0d5ac525fdb Mon Sep 17 00:00:00 2001 From: Haihao Xiang Date: Mon, 12 Jun 2023 16:14:47 +0800 Subject: [PATCH 1597/2172] lavfi/qsvvpp: postpone vpp session initialization So there is a chance to update vpp parameters per frame Signed-off-by: Haihao Xiang --- libavfilter/qsvvpp.c | 38 +++++++++++++++++++++++++++++++------- libavfilter/qsvvpp.h | 1 + 2 files changed, 32 insertions(+), 7 deletions(-) diff --git a/libavfilter/qsvvpp.c b/libavfilter/qsvvpp.c index d168ab5d1df..f2e8e5fd733 100644 --- a/libavfilter/qsvvpp.c +++ b/libavfilter/qsvvpp.c @@ -835,6 +835,7 @@ int ff_qsvvpp_init(AVFilterContext *avctx, QSVVPPParam *param) /* Print output memory mode */ ff_qsvvpp_print_iopattern(avctx, s->vpp_param.IOPattern & 0xF0, "VPP"); + /* Validate VPP params, but don't initial VPP session here */ ret = MFXVideoVPP_Query(s->session, &s->vpp_param, &s->vpp_param); if (ret < 0) { ret = ff_qsvvpp_print_error(avctx, ret, "Error querying VPP params"); @@ -842,13 +843,6 @@ int ff_qsvvpp_init(AVFilterContext *avctx, QSVVPPParam *param) } else if (ret > 0) ff_qsvvpp_print_warning(avctx, ret, "Warning When querying VPP params"); - ret = MFXVideoVPP_Init(s->session, &s->vpp_param); - if (ret < 0) { - ret = ff_qsvvpp_print_error(avctx, ret, "Failed to create a qsvvpp"); - goto failed; - } else if (ret > 0) - ff_qsvvpp_print_warning(avctx, ret, "Warning When creating qsvvpp"); - return 0; failed: @@ -857,6 +851,31 @@ int ff_qsvvpp_init(AVFilterContext *avctx, QSVVPPParam *param) return ret; } +static int qsvvpp_init_vpp_session(AVFilterContext *avctx, QSVVPPContext *s) +{ + int ret; + + if (s->vpp_initted) + return 0; + + /* Query VPP params again, including params for frame */ + ret = MFXVideoVPP_Query(s->session, &s->vpp_param, &s->vpp_param); + if (ret < 0) + return ff_qsvvpp_print_error(avctx, ret, "Error querying VPP params"); + else if (ret > 0) + ff_qsvvpp_print_warning(avctx, ret, "Warning When querying VPP params"); + + ret = MFXVideoVPP_Init(s->session, &s->vpp_param); + if (ret < 0) + return ff_qsvvpp_print_error(avctx, ret, "Failed to create a qsvvpp"); + else if (ret > 0) + ff_qsvvpp_print_warning(avctx, ret, "Warning When creating qsvvpp"); + + s->vpp_initted = 1; + + return 0; +} + int ff_qsvvpp_close(AVFilterContext *avctx) { QSVVPPContext *s = avctx->priv; @@ -865,6 +884,7 @@ int ff_qsvvpp_close(AVFilterContext *avctx) MFXVideoVPP_Close(s->session); MFXClose(s->session); s->session = NULL; + s->vpp_initted = 0; } /* release all the resources */ @@ -920,6 +940,10 @@ int ff_qsvvpp_filter_frame(QSVVPPContext *s, AVFilterLink *inlink, AVFrame *picr return AVERROR(ENOMEM); } + ret = qsvvpp_init_vpp_session(ctx, s); + if (ret) + return ret; + do { ret = MFXVideoVPP_RunFrameVPPAsync(s->session, &in_frame->surface, &out_frame->surface, NULL, &sync); diff --git a/libavfilter/qsvvpp.h b/libavfilter/qsvvpp.h index 073c89fe701..fba5f037d40 100644 --- a/libavfilter/qsvvpp.h +++ b/libavfilter/qsvvpp.h @@ -90,6 +90,7 @@ typedef struct QSVVPPContext { AVFifo *async_fifo; mfxVersion ver; + int vpp_initted; } QSVVPPContext; typedef struct QSVVPPCrop { From 88b3841149b9f41d6c5ec7930dcd5c6caf28b198 Mon Sep 17 00:00:00 2001 From: Haihao Xiang Date: Mon, 12 Jun 2023 16:14:48 +0800 Subject: [PATCH 1598/2172] lavfi/qsvvpp: use the right picture struct for vpp initilaization Signed-off-by: Haihao Xiang --- libavfilter/qsvvpp.c | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/libavfilter/qsvvpp.c b/libavfilter/qsvvpp.c index f2e8e5fd733..a03de05d9ce 100644 --- a/libavfilter/qsvvpp.c +++ b/libavfilter/qsvvpp.c @@ -536,6 +536,20 @@ static QSVFrame *query_frame(QSVVPPContext *s, AVFilterLink *outlink, const AVFr out_frame->frame->height = outlink->h; out_frame->surface.Info = s->vpp_param.vpp.Out; + for (int i = 0; i < s->vpp_param.NumExtParam; i++) { + mfxExtBuffer *extbuf = s->vpp_param.ExtParam[i]; + + if (extbuf->BufferId == MFX_EXTBUFF_VPP_DEINTERLACING) { + out_frame->frame->interlaced_frame = 0; + break; + } + } + + out_frame->surface.Info.PicStruct = + !out_frame->frame->interlaced_frame ? MFX_PICSTRUCT_PROGRESSIVE : + (out_frame->frame->top_field_first ? MFX_PICSTRUCT_FIELD_TFF : + MFX_PICSTRUCT_FIELD_BFF); + return out_frame; } @@ -851,13 +865,16 @@ int ff_qsvvpp_init(AVFilterContext *avctx, QSVVPPParam *param) return ret; } -static int qsvvpp_init_vpp_session(AVFilterContext *avctx, QSVVPPContext *s) +static int qsvvpp_init_vpp_session(AVFilterContext *avctx, QSVVPPContext *s, const QSVFrame *in, QSVFrame *out) { int ret; if (s->vpp_initted) return 0; + s->vpp_param.vpp.In.PicStruct = in->surface.Info.PicStruct; + s->vpp_param.vpp.Out.PicStruct = out->surface.Info.PicStruct; + /* Query VPP params again, including params for frame */ ret = MFXVideoVPP_Query(s->session, &s->vpp_param, &s->vpp_param); if (ret < 0) @@ -940,7 +957,7 @@ int ff_qsvvpp_filter_frame(QSVVPPContext *s, AVFilterLink *inlink, AVFrame *picr return AVERROR(ENOMEM); } - ret = qsvvpp_init_vpp_session(ctx, s); + ret = qsvvpp_init_vpp_session(ctx, s, in_frame, out_frame); if (ret) return ret; From 2cac3fd744ea7f1a8bd0f507718c3323e75442c6 Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Tue, 11 Jan 2022 11:28:30 -0800 Subject: [PATCH 1599/2172] avformat: add raw AC-4 muxer --- libavformat/Makefile | 1 + libavformat/ac4enc.c | 102 +++++++++++++++++++++++++++++++++++++++ libavformat/allformats.c | 1 + libavformat/version.h | 2 +- 4 files changed, 105 insertions(+), 1 deletion(-) create mode 100644 libavformat/ac4enc.c diff --git a/libavformat/Makefile b/libavformat/Makefile index 2c037c0b24c..2b90b788c0e 100644 --- a/libavformat/Makefile +++ b/libavformat/Makefile @@ -78,6 +78,7 @@ OBJS-$(CONFIG_AAX_DEMUXER) += aaxdec.o OBJS-$(CONFIG_AC3_DEMUXER) += ac3dec.o rawdec.o OBJS-$(CONFIG_AC3_MUXER) += rawenc.o OBJS-$(CONFIG_AC4_DEMUXER) += ac4dec.o +OBJS-$(CONFIG_AC4_MUXER) += ac4enc.o OBJS-$(CONFIG_ACE_DEMUXER) += acedec.o OBJS-$(CONFIG_ACM_DEMUXER) += acm.o rawdec.o OBJS-$(CONFIG_ACT_DEMUXER) += act.o diff --git a/libavformat/ac4enc.c b/libavformat/ac4enc.c new file mode 100644 index 00000000000..aefbfc26845 --- /dev/null +++ b/libavformat/ac4enc.c @@ -0,0 +1,102 @@ +/* + * Raw AC-4 muxer + * + * 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/codec_id.h" +#include "libavcodec/codec_par.h" +#include "libavcodec/packet.h" +#include "libavutil/crc.h" +#include "libavutil/opt.h" +#include "avformat.h" +#include "mux.h" + +typedef struct AC4Context { + AVClass *class; + int write_crc; +} AC4Context; + +static int ac4_init(AVFormatContext *s) +{ + AVCodecParameters *par = s->streams[0]->codecpar; + + if (s->nb_streams != 1 || par->codec_id != AV_CODEC_ID_AC4) { + av_log(s, AV_LOG_ERROR, "Only one AC-4 stream can be muxed by the AC-4 muxer\n"); + return AVERROR(EINVAL); + } + + return 0; +} + +static int ac4_write_packet(AVFormatContext *s, AVPacket *pkt) +{ + AC4Context *ac4 = s->priv_data; + AVIOContext *pb = s->pb; + + if (!pkt->size) + return 0; + + if (ac4->write_crc) + avio_wb16(pb, 0xAC41); + else + avio_wb16(pb, 0xAC40); + + if (pkt->size >= 0xffff) { + avio_wb16(pb, 0xffff); + avio_wb24(pb, pkt->size); + } else { + avio_wb16(pb, pkt->size); + } + + avio_write(pb, pkt->data, pkt->size); + + if (ac4->write_crc) { + uint16_t crc = av_crc(av_crc_get_table(AV_CRC_16_ANSI), 0, pkt->data, pkt->size); + avio_wl16(pb, crc); + } + + return 0; +} + +#define ENC AV_OPT_FLAG_ENCODING_PARAM +#define OFFSET(obj) offsetof(AC4Context, obj) +static const AVOption ac4_options[] = { + { "write_crc", "enable checksum", OFFSET(write_crc), AV_OPT_TYPE_BOOL, {.i64 = 0}, 0, 1, ENC}, + { NULL }, +}; + +static const AVClass ac4_muxer_class = { + .class_name = "AC4 muxer", + .item_name = av_default_item_name, + .option = ac4_options, + .version = LIBAVUTIL_VERSION_INT, +}; + +const FFOutputFormat ff_ac4_muxer = { + .p.name = "ac4", + .p.long_name = NULL_IF_CONFIG_SMALL("raw AC-4"), + .p.mime_type = "audio/ac4", + .p.extensions = "ac4", + .priv_data_size = sizeof(AC4Context), + .p.audio_codec = AV_CODEC_ID_AC4, + .p.video_codec = AV_CODEC_ID_NONE, + .init = ac4_init, + .write_packet = ac4_write_packet, + .p.priv_class = &ac4_muxer_class, + .p.flags = AVFMT_NOTIMESTAMPS, +}; diff --git a/libavformat/allformats.c b/libavformat/allformats.c index 70fa7f14608..f64b0870aac 100644 --- a/libavformat/allformats.c +++ b/libavformat/allformats.c @@ -35,6 +35,7 @@ extern const AVInputFormat ff_aax_demuxer; extern const AVInputFormat ff_ac3_demuxer; extern const FFOutputFormat ff_ac3_muxer; extern const AVInputFormat ff_ac4_demuxer; +extern const FFOutputFormat ff_ac4_muxer; extern const AVInputFormat ff_ace_demuxer; extern const AVInputFormat ff_acm_demuxer; extern const AVInputFormat ff_act_demuxer; diff --git a/libavformat/version.h b/libavformat/version.h index 35d796d318c..1b079ebce8c 100644 --- a/libavformat/version.h +++ b/libavformat/version.h @@ -31,7 +31,7 @@ #include "version_major.h" -#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, \ From 4cc40c050ac671d470deeff6c47671a5dd143221 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomas=20H=C3=A4rdin?= Date: Thu, 8 Jun 2023 11:55:28 +0200 Subject: [PATCH 1600/2172] lavc/riffenc: Fix msrle support on Windows 95 --- libavformat/riffenc.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/libavformat/riffenc.c b/libavformat/riffenc.c index 179b0f12cb0..3325419b945 100644 --- a/libavformat/riffenc.c +++ b/libavformat/riffenc.c @@ -239,14 +239,16 @@ void ff_put_bmp_header(AVIOContext *pb, AVCodecParameters *par, /* depth */ avio_wl16(pb, par->bits_per_coded_sample ? par->bits_per_coded_sample : 24); /* compression type */ - avio_wl32(pb, par->codec_tag); + // MSRLE compatibility with Media Player 3.1 and Windows 95 + avio_wl32(pb, par->codec_id == AV_CODEC_ID_MSRLE ? 1 : par->codec_tag); avio_wl32(pb, (par->width * par->height * (par->bits_per_coded_sample ? par->bits_per_coded_sample : 24)+7) / 8); avio_wl32(pb, 0); avio_wl32(pb, 0); /* Number of color indices in the color table that are used. * A value of 0 means 2^biBitCount indices, but this doesn't work * with Windows Media Player and files containing xxpc chunks. */ - avio_wl32(pb, pal_avi ? 1 << par->bits_per_coded_sample : 0); + // MSRLE on Windows 95 requires a zero here + avio_wl32(pb, pal_avi && par->codec_id != AV_CODEC_ID_MSRLE ? 1 << par->bits_per_coded_sample : 0); avio_wl32(pb, 0); if (!ignore_extradata) { From 8e53233f68a441cb4f1177bc3c237768830ac58e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomas=20H=C3=A4rdin?= Date: Thu, 8 Jun 2023 11:57:53 +0200 Subject: [PATCH 1601/2172] lavc/msrleenc: Add msrle encoder Keyframes are marked automagically --- Changelog | 1 + MAINTAINERS | 1 + doc/encoders.texi | 14 ++ libavcodec/Makefile | 1 + libavcodec/allcodecs.c | 1 + libavcodec/msrleenc.c | 303 +++++++++++++++++++++++++++++ tests/fate/vcodec.mak | 3 + tests/ref/vsynth/vsynth1-msrle | 4 + tests/ref/vsynth/vsynth2-msrle | 4 + tests/ref/vsynth/vsynth3-msrle | 4 + tests/ref/vsynth/vsynth_lena-msrle | 4 + 11 files changed, 340 insertions(+) create mode 100644 libavcodec/msrleenc.c create mode 100644 tests/ref/vsynth/vsynth1-msrle create mode 100644 tests/ref/vsynth/vsynth2-msrle create mode 100644 tests/ref/vsynth/vsynth3-msrle create mode 100644 tests/ref/vsynth/vsynth_lena-msrle diff --git a/Changelog b/Changelog index fb47d2652bd..9cf3df8d6fc 100644 --- a/Changelog +++ b/Changelog @@ -20,6 +20,7 @@ version : - Essential Video Coding parser, muxer and demuxer - Essential Video Coding frame merge bsf - bwdif_cuda filter +- Microsoft RLE video encoder version 6.0: - Radiance HDR image support diff --git a/MAINTAINERS b/MAINTAINERS index f6a0f9bcb5b..fe60eca88da 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -210,6 +210,7 @@ Codecs: mqc* Nicolas Bertrand msmpeg4.c, msmpeg4data.h Michael Niedermayer msrle.c Mike Melanson + msrleenc.c Tomas Härdin msvideo1.c Mike Melanson nuv.c Reimar Doeffinger nvdec*, nvenc* Timo Rothenpieler diff --git a/doc/encoders.texi b/doc/encoders.texi index 20cb8a14217..25d6b7f09ed 100644 --- a/doc/encoders.texi +++ b/doc/encoders.texi @@ -3061,6 +3061,20 @@ Video encoders can take input in either of nv12 or yuv420p form (some encoders support both, some support only either - in practice, nv12 is the safer choice, especially among HW encoders). +@section Microsoft RLE + +Microsoft RLE aka MSRLE encoder. +Only 8-bit palette mode supported. +Compatible with Windows 3.1 and Windows 95. + +@subsection Options + +@table @option +@item g @var{integer} +Keyframe interval. +A keyframe is inserted at least every @code{-g} frames, sometimes sooner. +@end table + @section mpeg2 MPEG-2 video encoder. diff --git a/libavcodec/Makefile b/libavcodec/Makefile index 723bfa25c78..0e4d27f37b4 100644 --- a/libavcodec/Makefile +++ b/libavcodec/Makefile @@ -553,6 +553,7 @@ OBJS-$(CONFIG_MSA1_DECODER) += mss3.o OBJS-$(CONFIG_MSCC_DECODER) += mscc.o OBJS-$(CONFIG_MSNSIREN_DECODER) += siren.o OBJS-$(CONFIG_MSP2_DECODER) += msp2dec.o +OBJS-$(CONFIG_MSRLE_ENCODER) += msrleenc.o OBJS-$(CONFIG_MSRLE_DECODER) += msrle.o msrledec.o OBJS-$(CONFIG_MSS1_DECODER) += mss1.o mss12.o OBJS-$(CONFIG_MSS2_DECODER) += mss2.o mss12.o mss2dsp.o wmv2data.o diff --git a/libavcodec/allcodecs.c b/libavcodec/allcodecs.c index 11c136ef595..8775d15a4fe 100644 --- a/libavcodec/allcodecs.c +++ b/libavcodec/allcodecs.c @@ -228,6 +228,7 @@ extern const FFCodec ff_msmpeg4v3_encoder; extern const FFCodec ff_msmpeg4v3_decoder; extern const FFCodec ff_msmpeg4_crystalhd_decoder; extern const FFCodec ff_msp2_decoder; +extern const FFCodec ff_msrle_encoder; extern const FFCodec ff_msrle_decoder; extern const FFCodec ff_mss1_decoder; extern const FFCodec ff_mss2_decoder; diff --git a/libavcodec/msrleenc.c b/libavcodec/msrleenc.c new file mode 100644 index 00000000000..b73aa5e384b --- /dev/null +++ b/libavcodec/msrleenc.c @@ -0,0 +1,303 @@ +/* + * Copyright (c) 2023 Tomas Härdin + * + * 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 + * MSRLE encoder + * @see https://wiki.multimedia.cx/index.php?title=Microsoft_RLE + */ + +// TODO: pal4 mode? + +#include "bytestream.h" +#include "codec_internal.h" +#include "encode.h" + +typedef struct MSRLEContext { + const AVClass *class; + int curframe; + AVFrame *last_frame; +} MSRLEContext; + +static av_cold int msrle_encode_init(AVCodecContext *avctx) +{ + avctx->bits_per_coded_sample = 8; + return 0; +} + +static void write_run(AVCodecContext *avctx, uint8_t **data, int len, int value) +{ + // we're allowed to write odd runs + while (len >= 255) { + bytestream_put_byte(data, 255); + bytestream_put_byte(data, value); + len -= 255; + } + if (len >= 1) { + // this is wasteful when len == 1 and sometimes when len == 2 + // but sometimes we have no choice. also write_absolute() + // relies on this + bytestream_put_byte(data, len); + bytestream_put_byte(data, value); + } +} + +static void write_absolute(AVCodecContext *avctx, uint8_t **data, uint8_t *line, int len) +{ + // writing 255 would be wasteful here due to the padding requirement + while (len >= 254) { + bytestream_put_byte(data, 0); + bytestream_put_byte(data, 254); + bytestream_put_buffer(data, line, 254); + line += 254; + len -= 254; + } + if (len == 1) { + // it's less wasteful to write single pixels as runs + // not to mention that absolute mode requires >= 3 pixels + write_run(avctx, data, 1, line[0]); + } else if (len == 2) { + write_run(avctx, data, 1, line[0]); + write_run(avctx, data, 1, line[1]); + } else if (len > 0) { + bytestream_put_byte(data, 0); + bytestream_put_byte(data, len); + bytestream_put_buffer(data, line, len); + if (len & 1) + bytestream_put_byte(data, 0); + } +} + +static void write_delta(AVCodecContext *avctx, uint8_t **data, int delta) +{ + // we let the yskip logic handle the case where we want to delta + // to following lines. it's not perfect but it's easier than finding + // the optimal combination of end-of-lines and deltas to reach any + // following position including places where dx < 0 + while (delta >= 255) { + bytestream_put_byte(data, 0); + bytestream_put_byte(data, 2); + bytestream_put_byte(data, 255); + bytestream_put_byte(data, 0); + delta -= 255; + } + if (delta > 0) { + bytestream_put_byte(data, 0); + bytestream_put_byte(data, 2); + bytestream_put_byte(data, delta); + bytestream_put_byte(data, 0); + } +} + +static void write_yskip(AVCodecContext *avctx, uint8_t **data, int yskip) +{ + if (yskip < 4) + return; + // we have yskip*2 nul bytess + *data -= 2*yskip; + // the end-of-line counts as one skip + yskip--; + while (yskip >= 255) { + bytestream_put_byte(data, 0); + bytestream_put_byte(data, 2); + bytestream_put_byte(data, 0); + bytestream_put_byte(data, 255); + yskip -= 255; + } + if (yskip > 0) { + bytestream_put_byte(data, 0); + bytestream_put_byte(data, 2); + bytestream_put_byte(data, 0); + bytestream_put_byte(data, yskip); + } + bytestream_put_be16(data, 0x0000); +} + +// used both to encode lines in keyframes and to encode lines between deltas +static void encode_line(AVCodecContext *avctx, uint8_t **data, uint8_t *line, int length) +{ + int run = 0, last = -1, absstart = 0; + if (length == 0) + return; + for (int x = 0; x < length; x++) { + if (last == line[x]) { + run++; + if (run == 3) + write_absolute(avctx, data, &line[absstart], x - absstart - 2); + } else { + if (run >= 3) { + write_run(avctx, data, run, last); + absstart = x; + } + run = 1; + } + last = line[x]; + } + if (run >= 3) + write_run(avctx, data, run, last); + else + write_absolute(avctx, data, &line[absstart], length - absstart); +} + +static int encode(AVCodecContext *avctx, AVPacket *pkt, + const AVFrame *pict, int keyframe, int *got_keyframe) +{ + MSRLEContext *s = avctx->priv_data; + uint8_t *data = pkt->data; + + /* Compare the current frame to the last frame, or code the entire frame + if keyframe != 0. We're continually outputting pairs of bytes: + + 00 00 end of line + 00 01 end of bitmap + 00 02 dx dy delta. move pointer to x+dx, y+dy + 00 ll dd dd .. absolute (verbatim) mode. ll >= 3 + rr dd run. rr >= 1 + + For keyframes we only have absolute mode and runs at our disposal, and + we are not allowed to end a line early. If this happens when keyframe == 0 + then *got_keyframe is set to 1 and s->curframe is reset. + */ + *got_keyframe = 1; // set to zero whenever we use a feature that makes this a not-keyframe + + if (keyframe) { + for (int y = avctx->height-1; y >= 0; y--) { + uint8_t *line = &pict->data[0][y*pict->linesize[0]]; + encode_line(avctx, &data, line, avctx->width); + bytestream_put_be16(&data, 0x0000); // end of line + } + } else { + // compare to previous frame + int yskip = 0; // we can encode large skips using deltas + for (int y = avctx->height-1; y >= 0; y--) { + uint8_t *line = &pict->data[0][y*pict->linesize[0]]; + uint8_t *prev = &s->last_frame->data[0][y*s->last_frame->linesize[0]]; + // we need at least 5 pixels in a row for a delta to be worthwhile + int delta = 0, linestart = 0, encoded = 0; + for (int x = 0; x < avctx->width; x++) { + if (line[x] == prev[x]) { + delta++; + if (delta == 5) { + int len = x - linestart - 4; + if (len > 0) { + write_yskip(avctx, &data, yskip); + yskip = 0; + encode_line(avctx, &data, &line[linestart], len); + encoded = 1; + } + linestart = -1; + } + } else { + if (delta >= 5) { + write_yskip(avctx, &data, yskip); + yskip = 0; + write_delta(avctx, &data, delta); + *got_keyframe = 0; + encoded = 1; + } + delta = 0; + if (linestart == -1) + linestart = x; + } + } + if (delta < 5) { + write_yskip(avctx, &data, yskip); + yskip = 0; + encode_line(avctx, &data, &line[linestart], avctx->width - linestart); + encoded = 1; + } else + *got_keyframe = 0; + bytestream_put_be16(&data, 0x0000); // end of line + if (!encoded) + yskip++; + else + yskip = 0; + } + write_yskip(avctx, &data, yskip); + } + bytestream_put_be16(&data, 0x0001); // end of bitmap + pkt->size = data - pkt->data; + return 0; } + +static int msrle_encode_frame(AVCodecContext *avctx, AVPacket *pkt, + const AVFrame *pict, int *got_packet) +{ + MSRLEContext *s = avctx->priv_data; + int ret, got_keyframe; + + if ((ret = ff_alloc_packet(avctx, pkt, ( + avctx->width*2 /* worst case = rle every pixel */ + 2 /*end of line */ + ) * avctx->height + 2 /* end of bitmap */ + AV_INPUT_BUFFER_MIN_SIZE))) + return ret; + + if (pict->data[1]) { + uint8_t *side_data = av_packet_new_side_data(pkt, AV_PKT_DATA_PALETTE, AVPALETTE_SIZE); + memcpy(side_data, pict->data[1], AVPALETTE_SIZE); + } + + if ((ret = encode(avctx, pkt, pict, s->curframe == 0, &got_keyframe))) + return ret; + + if (got_keyframe) { + pkt->flags |= AV_PKT_FLAG_KEY; + s->curframe = 0; + } + if (++s->curframe >= avctx->gop_size) + s->curframe = 0; + *got_packet = 1; + + if (!s->last_frame) + s->last_frame = av_frame_alloc(); + else + av_frame_unref(s->last_frame); + + av_frame_ref(s->last_frame, pict); + return 0; +} + +static int msrle_encode_close(AVCodecContext *avctx) +{ + MSRLEContext *s = avctx->priv_data; + av_frame_free(&s->last_frame); + return 0; +} + +static const AVClass msrle_class = { + .class_name = "Microsoft RLE encoder", + .item_name = av_default_item_name, + .version = LIBAVUTIL_VERSION_INT, +}; + +const FFCodec ff_msrle_encoder = { + .p.name = "msrle", + CODEC_LONG_NAME("Microsoft RLE"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_MSRLE, + .p.capabilities = AV_CODEC_CAP_DR1, + .priv_data_size = sizeof(MSRLEContext), + .init = msrle_encode_init, + FF_CODEC_ENCODE_CB(msrle_encode_frame), + .close = msrle_encode_close, + .p.pix_fmts = (const enum AVPixelFormat[]){ + AV_PIX_FMT_PAL8, AV_PIX_FMT_NONE + }, + .p.priv_class = &msrle_class, + .caps_internal = FF_CODEC_CAP_INIT_CLEANUP, +}; diff --git a/tests/fate/vcodec.mak b/tests/fate/vcodec.mak index fbee264a9d7..ef8904613aa 100644 --- a/tests/fate/vcodec.mak +++ b/tests/fate/vcodec.mak @@ -338,6 +338,9 @@ fate-vsynth%-msmpeg4: ENCOPTS = -qscale 10 FATE_VCODEC-$(call ENCDEC, MSMPEG4V2, AVI) += msmpeg4v2 fate-vsynth%-msmpeg4v2: ENCOPTS = -qscale 10 +FATE_VCODEC_SCALE-$(call ENCDEC, MSRLE, AVI) += msrle +fate-vsynth%-msrle: CODEC = msrle + FATE_VCODEC_SCALE-$(call ENCDEC, PNG, AVI) += mpng fate-vsynth%-mpng: CODEC = png diff --git a/tests/ref/vsynth/vsynth1-msrle b/tests/ref/vsynth/vsynth1-msrle new file mode 100644 index 00000000000..6174ff57f81 --- /dev/null +++ b/tests/ref/vsynth/vsynth1-msrle @@ -0,0 +1,4 @@ +b19bc15e2c5866f3c7942aad47ce0261 *tests/data/fate/vsynth1-msrle.avi +5216296 tests/data/fate/vsynth1-msrle.avi +f142ee03bf9f37bb2e1902fe32366bbf *tests/data/fate/vsynth1-msrle.out.rawvideo +stddev: 8.69 PSNR: 29.34 MAXDIFF: 64 bytes: 7603200/ 7603200 diff --git a/tests/ref/vsynth/vsynth2-msrle b/tests/ref/vsynth/vsynth2-msrle new file mode 100644 index 00000000000..dd579b6ee91 --- /dev/null +++ b/tests/ref/vsynth/vsynth2-msrle @@ -0,0 +1,4 @@ +850744d6d38ab09adb2fbd685d5df740 *tests/data/fate/vsynth2-msrle.avi +4556642 tests/data/fate/vsynth2-msrle.avi +df26a524cad8ebf0cf5ba4376c5f115f *tests/data/fate/vsynth2-msrle.out.rawvideo +stddev: 7.57 PSNR: 30.54 MAXDIFF: 35 bytes: 7603200/ 7603200 diff --git a/tests/ref/vsynth/vsynth3-msrle b/tests/ref/vsynth/vsynth3-msrle new file mode 100644 index 00000000000..9cc92be0367 --- /dev/null +++ b/tests/ref/vsynth/vsynth3-msrle @@ -0,0 +1,4 @@ +ee8f4d86f117d69919be69fbc976981a *tests/data/fate/vsynth3-msrle.avi +72866 tests/data/fate/vsynth3-msrle.avi +fa6042492a3116c1ae9a32b487caa677 *tests/data/fate/vsynth3-msrle.out.rawvideo +stddev: 8.88 PSNR: 29.16 MAXDIFF: 51 bytes: 86700/ 86700 diff --git a/tests/ref/vsynth/vsynth_lena-msrle b/tests/ref/vsynth/vsynth_lena-msrle new file mode 100644 index 00000000000..67226f05a2d --- /dev/null +++ b/tests/ref/vsynth/vsynth_lena-msrle @@ -0,0 +1,4 @@ +9654924690cbaf6348ea798e442e819c *tests/data/fate/vsynth_lena-msrle.avi +4671320 tests/data/fate/vsynth_lena-msrle.avi +db453693ceae6f65c173dd716ee2662e *tests/data/fate/vsynth_lena-msrle.out.rawvideo +stddev: 8.07 PSNR: 29.99 MAXDIFF: 32 bytes: 7603200/ 7603200 From 43991dbd0557cd4142e90d0d9698c7678cee60b6 Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt Date: Tue, 14 Mar 2023 04:03:19 +0100 Subject: [PATCH 1602/2172] avformat/assenc: Fix potential NULL + 1 Incrementing a NULL pointer is undefined behaviour, yet this is what would happen in case trailer were NULL before the check. Signed-off-by: Andreas Rheinhardt --- libavformat/assenc.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libavformat/assenc.c b/libavformat/assenc.c index 6ecfb045173..62ea0745a42 100644 --- a/libavformat/assenc.c +++ b/libavformat/assenc.c @@ -63,8 +63,8 @@ static int write_header(AVFormatContext *s) if (trailer) trailer = strstr(trailer, "\n"); - if (trailer++) { - header_size = (trailer - par->extradata); + if (trailer) { + header_size = (++trailer - par->extradata); ass->trailer_size = par->extradata_size - header_size; if (ass->trailer_size) ass->trailer = trailer; From ca8a66017683752a84ea49357f8029d7fb00c1f0 Mon Sep 17 00:00:00 2001 From: James Almer Date: Sat, 17 Jun 2023 22:02:44 -0300 Subject: [PATCH 1603/2172] avformat/evcdec: simplify probe function Signed-off-by: James Almer --- libavformat/evcdec.c | 29 +++++++---------------------- 1 file changed, 7 insertions(+), 22 deletions(-) diff --git a/libavformat/evcdec.c b/libavformat/evcdec.c index 807406885ae..0c30f3b4fe5 100644 --- a/libavformat/evcdec.c +++ b/libavformat/evcdec.c @@ -35,14 +35,6 @@ #define RAW_PACKET_SIZE 1024 -typedef struct EVCParserContext { - int got_sps; - int got_pps; - int got_idr; - int got_nonidr; - -} EVCParserContext; - typedef struct EVCDemuxContext { const AVClass *class; AVRational framerate; @@ -103,10 +95,11 @@ static uint32_t read_nal_unit_length(const uint8_t *bits, int bits_size) return nalu_len; } -static int parse_nal_units(const AVProbeData *p, EVCParserContext *ev) +static int annexb_probe(const AVProbeData *p) { int nalu_type; size_t nalu_size; + int got_sps = 0, got_pps = 0, got_idr = 0, got_nonidr = 0; unsigned char *bits = (unsigned char *)p->buf; int bytes_to_read = p->buf_size; @@ -123,27 +116,19 @@ static int parse_nal_units(const AVProbeData *p, EVCParserContext *ev) nalu_type = get_nalu_type(bits, bytes_to_read); if (nalu_type == EVC_SPS_NUT) - ev->got_sps++; + got_sps++; else if (nalu_type == EVC_PPS_NUT) - ev->got_pps++; + got_pps++; else if (nalu_type == EVC_IDR_NUT ) - ev->got_idr++; + got_idr++; else if (nalu_type == EVC_NOIDR_NUT) - ev->got_nonidr++; + got_nonidr++; bits += nalu_size; bytes_to_read -= nalu_size; } - return 0; -} - -static int annexb_probe(const AVProbeData *p) -{ - EVCParserContext ev = {0}; - int ret = parse_nal_units(p, &ev); - - if (ret == 0 && ev.got_sps && ev.got_pps && (ev.got_idr || ev.got_nonidr > 3)) + if (got_sps && got_pps && (got_idr || got_nonidr > 3)) return AVPROBE_SCORE_EXTENSION + 1; // 1 more than .mpg return 0; From 5a2ff4338444b87248e838061214f3d72f1e8447 Mon Sep 17 00:00:00 2001 From: James Almer Date: Sat, 17 Jun 2023 22:18:14 -0300 Subject: [PATCH 1604/2172] avformat/evcdec: simplify au_end_found check Signed-off-by: James Almer --- libavformat/evcdec.c | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/libavformat/evcdec.c b/libavformat/evcdec.c index 0c30f3b4fe5..41b0bceb0c5 100644 --- a/libavformat/evcdec.c +++ b/libavformat/evcdec.c @@ -182,7 +182,7 @@ static int evc_read_packet(AVFormatContext *s, AVPacket *pkt) { int ret; int32_t nalu_size; - int au_end_found; + int au_end_found = 0; EVCDemuxContext *const c = s->priv_data; @@ -192,8 +192,6 @@ static int evc_read_packet(AVFormatContext *s, AVPacket *pkt) return AVERROR_EOF; } - au_end_found = 0; - while(!au_end_found) { uint8_t buf[EVC_NALU_LENGTH_PREFIX_SIZE]; @@ -229,9 +227,8 @@ static int evc_read_packet(AVFormatContext *s, AVPacket *pkt) av_log(s, AV_LOG_ERROR, "evc_frame_merge filter failed to " "send output packet\n"); - au_end_found = 1; - if (ret == AVERROR(EAGAIN)) - au_end_found = 0; + if (ret != AVERROR(EAGAIN)) + au_end_found = 1; } return ret; From 3f48815501942d3cd65eab2d61dbe99c4328fd9b Mon Sep 17 00:00:00 2001 From: James Almer Date: Sat, 17 Jun 2023 22:19:16 -0300 Subject: [PATCH 1605/2172] avformat/evcdec: don't set AVCodecParameters.framerate It's not necessary. Setting AVStream.avg_frame_rate is enough. Signed-off-by: James Almer --- libavformat/evcdec.c | 1 - 1 file changed, 1 deletion(-) diff --git a/libavformat/evcdec.c b/libavformat/evcdec.c index 41b0bceb0c5..890babd3cb0 100644 --- a/libavformat/evcdec.c +++ b/libavformat/evcdec.c @@ -157,7 +157,6 @@ static int evc_read_header(AVFormatContext *s) sti->need_parsing = AVSTREAM_PARSE_HEADERS; st->avg_frame_rate = c->framerate; - st->codecpar->framerate = c->framerate; // taken from rawvideo demuxers avpriv_set_pts_info(st, 64, 1, 1200000); From 7be4434c88209193c7d50f2cc26ed92f95167595 Mon Sep 17 00:00:00 2001 From: Niklas Haas Date: Thu, 15 Jun 2023 16:14:12 +0200 Subject: [PATCH 1606/2172] lavfi/vf_libplacebo: drop redundant case If the input queue is EOF, then the s->status check should already have covered it, and prevented the code from getting this far. If we still hit this case for some reason, it's probably a bug. Better to hit the AVERROR_BUG branch. --- libavfilter/vf_libplacebo.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/libavfilter/vf_libplacebo.c b/libavfilter/vf_libplacebo.c index 242c8a13f5a..a048424cecc 100644 --- a/libavfilter/vf_libplacebo.c +++ b/libavfilter/vf_libplacebo.c @@ -949,9 +949,6 @@ static int libplacebo_activate(AVFilterContext *ctx) if (!s->fps.num) av_fifo_drain2(s->out_pts, 1); return output_frame_mix(ctx, &mix, pts); - case PL_QUEUE_EOF: - ff_outlink_set_status(outlink, AVERROR_EOF, pts); - return 0; case PL_QUEUE_ERR: return AVERROR_EXTERNAL; } From c3b17ccc6251ec26ac3a06ed2571b45489ce7f46 Mon Sep 17 00:00:00 2001 From: Niklas Haas Date: Tue, 13 Jun 2023 15:44:13 +0200 Subject: [PATCH 1607/2172] lavfi/vf_libplacebo: move input-specific state to struct In anticipation of a refactor which will enable multiple input support. Note: the renderer is also input-specific because it maintains a frame cache, HDR peak detection state and mixing cache, all of which are tied to a specific input stream. --- libavfilter/vf_libplacebo.c | 80 ++++++++++++++++++++++++------------- 1 file changed, 52 insertions(+), 28 deletions(-) diff --git a/libavfilter/vf_libplacebo.c b/libavfilter/vf_libplacebo.c index a048424cecc..10fd4327458 100644 --- a/libavfilter/vf_libplacebo.c +++ b/libavfilter/vf_libplacebo.c @@ -113,6 +113,16 @@ enum var_name { VAR_VARS_NB }; +/* per-input dynamic filter state */ +typedef struct LibplaceboInput { + pl_renderer renderer; + pl_queue queue; + AVFilterLink *link; + AVFifo *out_pts; ///< timestamps of wanted output frames + int64_t status_pts; + int status; +} LibplaceboInput; + typedef struct LibplaceboContext { /* lavfi vulkan*/ FFVulkanContext vkctx; @@ -121,14 +131,10 @@ typedef struct LibplaceboContext { pl_log log; pl_vulkan vulkan; pl_gpu gpu; - pl_renderer renderer; - pl_queue queue; pl_tex tex[4]; - /* filter state */ - AVFifo *out_pts; ///< timestamps of wanted output frames - int64_t status_pts; - int status; + /* input state */ + LibplaceboInput input; /* settings */ char *out_format_string; @@ -536,8 +542,6 @@ static int libplacebo_init(AVFilterContext *avctx) RET(av_expr_parse(&s->pos_h_pexpr, s->pos_h_expr, var_names, NULL, NULL, NULL, NULL, 0, s)); - /* Initialize dynamic filter state */ - s->out_pts = av_fifo_alloc2(1, sizeof(int64_t), AV_FIFO_FLAG_AUTO_GROW); if (strcmp(s->fps_string, "none") != 0) RET(av_parse_video_rate(&s->fps, s->fps_string)); @@ -564,6 +568,28 @@ static void unlock_queue(void *priv, uint32_t qf, uint32_t qidx) } #endif +static int input_init(AVFilterContext *avctx, AVFilterLink *link, + LibplaceboInput *input) +{ + LibplaceboContext *s = avctx->priv; + + input->out_pts = av_fifo_alloc2(1, sizeof(int64_t), AV_FIFO_FLAG_AUTO_GROW); + if (!input->out_pts) + return AVERROR(ENOMEM); + input->queue = pl_queue_create(s->gpu); + input->renderer = pl_renderer_create(s->log, s->gpu); + input->link = link; + + return 0; +} + +static void input_uninit(LibplaceboInput *input) +{ + pl_renderer_destroy(&input->renderer); + pl_queue_destroy(&input->queue); + av_fifo_freep2(&input->out_pts); +} + static int init_vulkan(AVFilterContext *avctx, const AVVulkanDeviceContext *hwctx) { int err = 0; @@ -620,10 +646,7 @@ static int init_vulkan(AVFilterContext *avctx, const AVVulkanDeviceContext *hwct goto fail; } - /* Create the renderer */ s->gpu = s->vulkan->gpu; - s->renderer = pl_renderer_create(s->log, s->gpu); - s->queue = pl_queue_create(s->gpu); /* Parse the user shaders, if requested */ if (s->shader_bin_len) @@ -634,6 +657,9 @@ static int init_vulkan(AVFilterContext *avctx, const AVVulkanDeviceContext *hwct RET(parse_shader(avctx, buf, buf_len)); } + /* Initialize inputs */ + RET(input_init(avctx, avctx->inputs[0], &s->input)); + /* fall through */ fail: if (buf) @@ -649,8 +675,7 @@ static void libplacebo_uninit(AVFilterContext *avctx) pl_tex_destroy(s->gpu, &s->tex[i]); for (int i = 0; i < s->num_hooks; i++) pl_mpv_user_shader_destroy(&s->hooks[i]); - pl_renderer_destroy(&s->renderer); - pl_queue_destroy(&s->queue); + input_uninit(&s->input); pl_vulkan_destroy(&s->vulkan); pl_log_destroy(&s->log); ff_vk_uninit(&s->vkctx); @@ -664,7 +689,6 @@ static void libplacebo_uninit(AVFilterContext *avctx) av_expr_free(s->pos_y_pexpr); av_expr_free(s->pos_w_pexpr); av_expr_free(s->pos_h_pexpr); - av_fifo_freep2(&s->out_pts); } static int libplacebo_process_command(AVFilterContext *ctx, const char *cmd, @@ -826,7 +850,7 @@ static int output_frame_mix(AVFilterContext *ctx, } update_crops(ctx, mix, &target, ref_sig, out->pts * av_q2d(outlink->time_base)); - pl_render_image_mix(s->renderer, mix, &target, &s->params); + pl_render_image_mix(s->input.renderer, mix, &target, &s->params); if (outdesc->flags & AV_PIX_FMT_FLAG_HWACCEL) { pl_unmap_avframe(s->gpu, &target); @@ -886,7 +910,7 @@ static int libplacebo_activate(AVFilterContext *ctx) while ((ret = ff_inlink_consume_frame(inlink, &in)) > 0) { in->opaque = s; - pl_queue_push(s->queue, &(struct pl_source_frame) { + pl_queue_push(s->input.queue, &(struct pl_source_frame) { .pts = in->pts * av_q2d(inlink->time_base), .duration = in->duration * av_q2d(inlink->time_base), .first_field = pl_field_from_avframe(in), @@ -899,19 +923,19 @@ static int libplacebo_activate(AVFilterContext *ctx) if (!s->fps.num) { /* Internally queue an output frame for the same PTS */ av_assert1(!av_cmp_q(inlink->time_base, outlink->time_base)); - av_fifo_write(s->out_pts, &in->pts, 1); + av_fifo_write(s->input.out_pts, &in->pts, 1); } } if (ret < 0) return ret; - if (!s->status && ff_inlink_acknowledge_status(inlink, &status, &pts)) { + if (!s->input.status && ff_inlink_acknowledge_status(inlink, &status, &pts)) { pts = av_rescale_q_rnd(pts, inlink->time_base, outlink->time_base, AV_ROUND_UP); - pl_queue_push(s->queue, NULL); /* Signal EOF to pl_queue */ - s->status = status; - s->status_pts = pts; + pl_queue_push(s->input.queue, NULL); /* Signal EOF to pl_queue */ + s->input.status = status; + s->input.status_pts = pts; } if (ff_outlink_frame_wanted(outlink)) { @@ -920,22 +944,22 @@ static int libplacebo_activate(AVFilterContext *ctx) if (s->fps.num) { pts = outlink->frame_count_out; - } else if (av_fifo_peek(s->out_pts, &pts, 1, 0) < 0) { + } else if (av_fifo_peek(s->input.out_pts, &pts, 1, 0) < 0) { /* No frames queued */ - if (s->status) { - pts = s->status_pts; + if (s->input.status) { + pts = s->input.status_pts; } else { ff_inlink_request_frame(inlink); return 0; } } - if (s->status && pts >= s->status_pts) { - ff_outlink_set_status(outlink, s->status, s->status_pts); + if (s->input.status && pts >= s->input.status_pts) { + ff_outlink_set_status(outlink, s->input.status, s->input.status_pts); return 0; } - ret = pl_queue_update(s->queue, &mix, pl_queue_params( + ret = pl_queue_update(s->input.queue, &mix, pl_queue_params( .pts = pts * av_q2d(outlink->time_base), .radius = pl_frame_mix_radius(&s->params), .vsync_duration = av_q2d(av_inv_q(outlink->frame_rate)), @@ -947,7 +971,7 @@ static int libplacebo_activate(AVFilterContext *ctx) return 0; case PL_QUEUE_OK: if (!s->fps.num) - av_fifo_drain2(s->out_pts, 1); + av_fifo_drain2(s->input.out_pts, 1); return output_frame_mix(ctx, &mix, pts); case PL_QUEUE_ERR: return AVERROR_EXTERNAL; From b5d48111ad9f7de82bdc8077dd1a5d8eea18282d Mon Sep 17 00:00:00 2001 From: Niklas Haas Date: Thu, 15 Jun 2023 15:28:04 +0200 Subject: [PATCH 1608/2172] lavfi/vf_libplacebo: move input handling to separate function To be re-used once we support more than one input. --- libavfilter/vf_libplacebo.c | 45 ++++++++++++++++++++++++------------- 1 file changed, 29 insertions(+), 16 deletions(-) diff --git a/libavfilter/vf_libplacebo.c b/libavfilter/vf_libplacebo.c index 10fd4327458..879a3a05086 100644 --- a/libavfilter/vf_libplacebo.c +++ b/libavfilter/vf_libplacebo.c @@ -896,23 +896,19 @@ static void discard_frame(const struct pl_source_frame *src) av_frame_free(&avframe); } -static int libplacebo_activate(AVFilterContext *ctx) +static int handle_input(AVFilterContext *ctx, LibplaceboInput *input) { int ret, status; LibplaceboContext *s = ctx->priv; - AVFilterLink *inlink = ctx->inputs[0]; AVFilterLink *outlink = ctx->outputs[0]; AVFrame *in; int64_t pts; - FF_FILTER_FORWARD_STATUS_BACK(outlink, inlink); - pl_log_level_update(s->log, get_log_level()); - - while ((ret = ff_inlink_consume_frame(inlink, &in)) > 0) { + while ((ret = ff_inlink_consume_frame(input->link, &in)) > 0) { in->opaque = s; - pl_queue_push(s->input.queue, &(struct pl_source_frame) { - .pts = in->pts * av_q2d(inlink->time_base), - .duration = in->duration * av_q2d(inlink->time_base), + pl_queue_push(input->queue, &(struct pl_source_frame) { + .pts = in->pts * av_q2d(input->link->time_base), + .duration = in->duration * av_q2d(input->link->time_base), .first_field = pl_field_from_avframe(in), .frame_data = in, .map = map_frame, @@ -922,22 +918,39 @@ static int libplacebo_activate(AVFilterContext *ctx) if (!s->fps.num) { /* Internally queue an output frame for the same PTS */ - av_assert1(!av_cmp_q(inlink->time_base, outlink->time_base)); - av_fifo_write(s->input.out_pts, &in->pts, 1); + pts = av_rescale_q(in->pts, input->link->time_base, outlink->time_base); + av_fifo_write(input->out_pts, &pts, 1); } } if (ret < 0) return ret; - if (!s->input.status && ff_inlink_acknowledge_status(inlink, &status, &pts)) { - pts = av_rescale_q_rnd(pts, inlink->time_base, outlink->time_base, + if (!input->status && ff_inlink_acknowledge_status(input->link, &status, &pts)) { + pts = av_rescale_q_rnd(pts, input->link->time_base, outlink->time_base, AV_ROUND_UP); - pl_queue_push(s->input.queue, NULL); /* Signal EOF to pl_queue */ - s->input.status = status; - s->input.status_pts = pts; + pl_queue_push(input->queue, NULL); /* Signal EOF to pl_queue */ + input->status = status; + input->status_pts = pts; } + return 0; +} + +static int libplacebo_activate(AVFilterContext *ctx) +{ + int ret; + LibplaceboContext *s = ctx->priv; + AVFilterLink *inlink = ctx->inputs[0]; + AVFilterLink *outlink = ctx->outputs[0]; + int64_t pts; + + FF_FILTER_FORWARD_STATUS_BACK(outlink, inlink); + pl_log_level_update(s->log, get_log_level()); + + if ((ret = handle_input(ctx, &s->input)) < 0) + return ret; + if (ff_outlink_frame_wanted(outlink)) { struct pl_frame_mix mix; enum pl_queue_status ret; From a4197196a072eed38b4331745b7eb1e2bbef74b0 Mon Sep 17 00:00:00 2001 From: Niklas Haas Date: Thu, 15 Jun 2023 15:28:39 +0200 Subject: [PATCH 1609/2172] lavfi/vf_libplacebo: cosmetic Assign local variable 'in' for 's->input' and replace 'inlink' by 'in->link' to avoid hard-coding ID 0 in more than one place. --- libavfilter/vf_libplacebo.c | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/libavfilter/vf_libplacebo.c b/libavfilter/vf_libplacebo.c index 879a3a05086..beddd2f796d 100644 --- a/libavfilter/vf_libplacebo.c +++ b/libavfilter/vf_libplacebo.c @@ -941,14 +941,14 @@ static int libplacebo_activate(AVFilterContext *ctx) { int ret; LibplaceboContext *s = ctx->priv; - AVFilterLink *inlink = ctx->inputs[0]; + LibplaceboInput *in = &s->input; AVFilterLink *outlink = ctx->outputs[0]; int64_t pts; - FF_FILTER_FORWARD_STATUS_BACK(outlink, inlink); + FF_FILTER_FORWARD_STATUS_BACK(outlink, in->link); pl_log_level_update(s->log, get_log_level()); - if ((ret = handle_input(ctx, &s->input)) < 0) + if ((ret = handle_input(ctx, in)) < 0) return ret; if (ff_outlink_frame_wanted(outlink)) { @@ -957,22 +957,22 @@ static int libplacebo_activate(AVFilterContext *ctx) if (s->fps.num) { pts = outlink->frame_count_out; - } else if (av_fifo_peek(s->input.out_pts, &pts, 1, 0) < 0) { + } else if (av_fifo_peek(in->out_pts, &pts, 1, 0) < 0) { /* No frames queued */ - if (s->input.status) { - pts = s->input.status_pts; + if (in->status) { + pts = in->status_pts; } else { - ff_inlink_request_frame(inlink); + ff_inlink_request_frame(in->link); return 0; } } - if (s->input.status && pts >= s->input.status_pts) { - ff_outlink_set_status(outlink, s->input.status, s->input.status_pts); + if (in->status && pts >= in->status_pts) { + ff_outlink_set_status(outlink, in->status, in->status_pts); return 0; } - ret = pl_queue_update(s->input.queue, &mix, pl_queue_params( + ret = pl_queue_update(in->queue, &mix, pl_queue_params( .pts = pts * av_q2d(outlink->time_base), .radius = pl_frame_mix_radius(&s->params), .vsync_duration = av_q2d(av_inv_q(outlink->frame_rate)), @@ -980,11 +980,11 @@ static int libplacebo_activate(AVFilterContext *ctx) switch (ret) { case PL_QUEUE_MORE: - ff_inlink_request_frame(inlink); + ff_inlink_request_frame(in->link); return 0; case PL_QUEUE_OK: if (!s->fps.num) - av_fifo_drain2(s->input.out_pts, 1); + av_fifo_drain2(in->out_pts, 1); return output_frame_mix(ctx, &mix, pts); case PL_QUEUE_ERR: return AVERROR_EXTERNAL; From ad445a7030fa62d4ef750b78f7756db219702ead Mon Sep 17 00:00:00 2001 From: Niklas Haas Date: Thu, 15 Jun 2023 15:32:39 +0200 Subject: [PATCH 1610/2172] lavfi/vf_libplacebo: move temporary vars into per-input struct Including the queue status, because these will need to be re-queried inside output_frame_mix when that function is refactored to handle multiple inputs. --- libavfilter/vf_libplacebo.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/libavfilter/vf_libplacebo.c b/libavfilter/vf_libplacebo.c index beddd2f796d..4baa766bacf 100644 --- a/libavfilter/vf_libplacebo.c +++ b/libavfilter/vf_libplacebo.c @@ -117,6 +117,8 @@ enum var_name { typedef struct LibplaceboInput { pl_renderer renderer; pl_queue queue; + enum pl_queue_status qstatus; + struct pl_frame_mix mix; ///< temporary storage AVFilterLink *link; AVFifo *out_pts; ///< timestamps of wanted output frames int64_t status_pts; @@ -952,9 +954,6 @@ static int libplacebo_activate(AVFilterContext *ctx) return ret; if (ff_outlink_frame_wanted(outlink)) { - struct pl_frame_mix mix; - enum pl_queue_status ret; - if (s->fps.num) { pts = outlink->frame_count_out; } else if (av_fifo_peek(in->out_pts, &pts, 1, 0) < 0) { @@ -972,20 +971,20 @@ static int libplacebo_activate(AVFilterContext *ctx) return 0; } - ret = pl_queue_update(in->queue, &mix, pl_queue_params( + in->qstatus = pl_queue_update(in->queue, &in->mix, pl_queue_params( .pts = pts * av_q2d(outlink->time_base), .radius = pl_frame_mix_radius(&s->params), .vsync_duration = av_q2d(av_inv_q(outlink->frame_rate)), )); - switch (ret) { + switch (in->qstatus) { case PL_QUEUE_MORE: ff_inlink_request_frame(in->link); return 0; case PL_QUEUE_OK: if (!s->fps.num) av_fifo_drain2(in->out_pts, 1); - return output_frame_mix(ctx, &mix, pts); + return output_frame_mix(ctx, &in->mix, pts); case PL_QUEUE_ERR: return AVERROR_EXTERNAL; } From 666c8aa4d7d302c15bed862b9c183f057b133e3a Mon Sep 17 00:00:00 2001 From: Niklas Haas Date: Thu, 15 Jun 2023 15:37:10 +0200 Subject: [PATCH 1611/2172] lavif/vf_libplacebo: remove pl_frame_mix from output_frame_mix Instead, rename this function to `output_frame` and make it pull the `pl_frame_mix` from the input structure. Step towards handling multiple inputs. --- libavfilter/vf_libplacebo.c | 23 +++++++++++------------ 1 file changed, 11 insertions(+), 12 deletions(-) diff --git a/libavfilter/vf_libplacebo.c b/libavfilter/vf_libplacebo.c index 4baa766bacf..0289187b46b 100644 --- a/libavfilter/vf_libplacebo.c +++ b/libavfilter/vf_libplacebo.c @@ -760,20 +760,19 @@ static void update_crops(AVFilterContext *ctx, } } -/* Construct and emit an output frame for a given frame mix */ -static int output_frame_mix(AVFilterContext *ctx, - struct pl_frame_mix *mix, - int64_t pts) +/* Construct and emit an output frame for a given timestamp */ +static int output_frame(AVFilterContext *ctx, int64_t pts) { int err = 0, ok, changed_csp; LibplaceboContext *s = ctx->priv; + LibplaceboInput *in = &s->input; AVFilterLink *outlink = ctx->outputs[0]; const AVPixFmtDescriptor *outdesc = av_pix_fmt_desc_get(outlink->format); struct pl_frame target; const AVFrame *ref; AVFrame *out; uint64_t ref_sig; - if (!mix->num_frames) + if (!in->mix.num_frames) return 0; out = ff_get_video_buffer(outlink, outlink->w, outlink->h); @@ -781,11 +780,11 @@ static int output_frame_mix(AVFilterContext *ctx, return AVERROR(ENOMEM); /* Use the last frame before current PTS value as reference */ - for (int i = 0; i < mix->num_frames; i++) { - if (i && mix->timestamps[i] > 0.0f) + for (int i = 0; i < in->mix.num_frames; i++) { + if (i && in->mix.timestamps[i] > 0.0f) break; - ref = pl_get_mapped_avframe(mix->frames[i]); - ref_sig = mix->signatures[i]; + ref = pl_get_mapped_avframe(in->mix.frames[i]); + ref_sig = in->mix.signatures[i]; } RET(av_frame_copy_props(out, ref)); @@ -851,8 +850,8 @@ static int output_frame_mix(AVFilterContext *ctx, goto fail; } - update_crops(ctx, mix, &target, ref_sig, out->pts * av_q2d(outlink->time_base)); - pl_render_image_mix(s->input.renderer, mix, &target, &s->params); + update_crops(ctx, &in->mix, &target, ref_sig, out->pts * av_q2d(outlink->time_base)); + pl_render_image_mix(in->renderer, &in->mix, &target, &s->params); if (outdesc->flags & AV_PIX_FMT_FLAG_HWACCEL) { pl_unmap_avframe(s->gpu, &target); @@ -984,7 +983,7 @@ static int libplacebo_activate(AVFilterContext *ctx) case PL_QUEUE_OK: if (!s->fps.num) av_fifo_drain2(in->out_pts, 1); - return output_frame_mix(ctx, &in->mix, pts); + return output_frame(ctx, pts); case PL_QUEUE_ERR: return AVERROR_EXTERNAL; } From 93c7e8c0ae2948ba68d1b9ef7d939f96d06cbc50 Mon Sep 17 00:00:00 2001 From: Niklas Haas Date: Thu, 15 Jun 2023 15:41:57 +0200 Subject: [PATCH 1612/2172] lavfi/vf_libplacebo: factor out ref frame logic Instead of finding the ref frame in output_frame() and then passing its signature to update_crops(), pull out the logic and invoke it a second time inside update_crops(). This may seem wasteful at present, but will actually become required in the future, since update_crops() runs on *every* input, and needs values specific to that input (which the signature isn't), while output_frame() is only interested in a single input. It's much easier to just split the logic cleanly. --- libavfilter/vf_libplacebo.c | 29 +++++++++++++++-------------- 1 file changed, 15 insertions(+), 14 deletions(-) diff --git a/libavfilter/vf_libplacebo.c b/libavfilter/vf_libplacebo.c index 0289187b46b..b83df24a84b 100644 --- a/libavfilter/vf_libplacebo.c +++ b/libavfilter/vf_libplacebo.c @@ -706,11 +706,21 @@ static int libplacebo_process_command(AVFilterContext *ctx, const char *cmd, return err; } +static const AVFrame *ref_frame(const struct pl_frame_mix *mix) +{ + for (int i = 0; i < mix->num_frames; i++) { + if (i+1 == mix->num_frames || mix->timestamps[i+1] > 0) + return pl_get_mapped_avframe(mix->frames[i]); + } + return NULL; +} + static void update_crops(AVFilterContext *ctx, struct pl_frame_mix *mix, struct pl_frame *target, - uint64_t ref_sig, double target_pts) + double target_pts) { LibplaceboContext *s = ctx->priv; + const AVFrame *ref = ref_frame(mix); for (int i = 0; i < mix->num_frames; i++) { // Mutate the `pl_frame.crop` fields in-place. This is fine because we @@ -745,7 +755,7 @@ static void update_crops(AVFilterContext *ctx, image->crop.x1 = image->crop.x0 + s->var_values[VAR_CROP_W]; image->crop.y1 = image->crop.y0 + s->var_values[VAR_CROP_H]; - if (mix->signatures[i] == ref_sig) { + if (src == ref) { /* Only update the target crop once, for the 'reference' frame */ target->crop.x0 = av_expr_eval(s->pos_x_pexpr, s->var_values, NULL); target->crop.y0 = av_expr_eval(s->pos_y_pexpr, s->var_values, NULL); @@ -768,25 +778,16 @@ static int output_frame(AVFilterContext *ctx, int64_t pts) LibplaceboInput *in = &s->input; AVFilterLink *outlink = ctx->outputs[0]; const AVPixFmtDescriptor *outdesc = av_pix_fmt_desc_get(outlink->format); + const AVFrame *ref = ref_frame(&in->mix); struct pl_frame target; - const AVFrame *ref; AVFrame *out; - uint64_t ref_sig; - if (!in->mix.num_frames) + if (!ref) return 0; out = ff_get_video_buffer(outlink, outlink->w, outlink->h); if (!out) return AVERROR(ENOMEM); - /* Use the last frame before current PTS value as reference */ - for (int i = 0; i < in->mix.num_frames; i++) { - if (i && in->mix.timestamps[i] > 0.0f) - break; - ref = pl_get_mapped_avframe(in->mix.frames[i]); - ref_sig = in->mix.signatures[i]; - } - RET(av_frame_copy_props(out, ref)); out->pts = pts; out->width = outlink->w; @@ -850,7 +851,7 @@ static int output_frame(AVFilterContext *ctx, int64_t pts) goto fail; } - update_crops(ctx, &in->mix, &target, ref_sig, out->pts * av_q2d(outlink->time_base)); + update_crops(ctx, &in->mix, &target, out->pts * av_q2d(outlink->time_base)); pl_render_image_mix(in->renderer, &in->mix, &target, &s->params); if (outdesc->flags & AV_PIX_FMT_FLAG_HWACCEL) { From a7775bd32c461ccb0ef314f33bf879aea1f0d2a0 Mon Sep 17 00:00:00 2001 From: Niklas Haas Date: Thu, 15 Jun 2023 15:47:55 +0200 Subject: [PATCH 1613/2172] lavfi/vf_libplacebo: use correct link in update_crops() Instead of hard-coding input 0, pass the per-input structure and use the link contained inside it. --- libavfilter/vf_libplacebo.c | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/libavfilter/vf_libplacebo.c b/libavfilter/vf_libplacebo.c index b83df24a84b..408fb3918aa 100644 --- a/libavfilter/vf_libplacebo.c +++ b/libavfilter/vf_libplacebo.c @@ -715,19 +715,18 @@ static const AVFrame *ref_frame(const struct pl_frame_mix *mix) return NULL; } -static void update_crops(AVFilterContext *ctx, - struct pl_frame_mix *mix, struct pl_frame *target, - double target_pts) +static void update_crops(AVFilterContext *ctx, LibplaceboInput *in, + struct pl_frame *target, double target_pts) { LibplaceboContext *s = ctx->priv; - const AVFrame *ref = ref_frame(mix); + const AVFrame *ref = ref_frame(&in->mix); - for (int i = 0; i < mix->num_frames; i++) { + for (int i = 0; i < in->mix.num_frames; i++) { // Mutate the `pl_frame.crop` fields in-place. This is fine because we // own the entire pl_queue, and hence, the pointed-at frames. - struct pl_frame *image = (struct pl_frame *) mix->frames[i]; + struct pl_frame *image = (struct pl_frame *) in->mix.frames[i]; const AVFrame *src = pl_get_mapped_avframe(image); - double image_pts = src->pts * av_q2d(ctx->inputs[0]->time_base); + double image_pts = src->pts * av_q2d(in->link->time_base); /* Update dynamic variables */ s->var_values[VAR_IN_T] = s->var_values[VAR_T] = image_pts; @@ -851,7 +850,7 @@ static int output_frame(AVFilterContext *ctx, int64_t pts) goto fail; } - update_crops(ctx, &in->mix, &target, out->pts * av_q2d(outlink->time_base)); + update_crops(ctx, in, &target, out->pts * av_q2d(outlink->time_base)); pl_render_image_mix(in->renderer, &in->mix, &target, &s->params); if (outdesc->flags & AV_PIX_FMT_FLAG_HWACCEL) { From 4e4a66b8c49371e5eb53796eae902ebe2843b815 Mon Sep 17 00:00:00 2001 From: Niklas Haas Date: Thu, 15 Jun 2023 15:52:32 +0200 Subject: [PATCH 1614/2172] lavfi/vf_libplacebo: replace s->input by dynamic array For now, hard-coded to 1 element. --- libavfilter/vf_libplacebo.c | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/libavfilter/vf_libplacebo.c b/libavfilter/vf_libplacebo.c index 408fb3918aa..ee8780036cf 100644 --- a/libavfilter/vf_libplacebo.c +++ b/libavfilter/vf_libplacebo.c @@ -136,7 +136,8 @@ typedef struct LibplaceboContext { pl_tex tex[4]; /* input state */ - LibplaceboInput input; + LibplaceboInput *inputs; + int nb_inputs; /* settings */ char *out_format_string; @@ -660,7 +661,12 @@ static int init_vulkan(AVFilterContext *avctx, const AVVulkanDeviceContext *hwct } /* Initialize inputs */ - RET(input_init(avctx, avctx->inputs[0], &s->input)); + s->nb_inputs = 1; + s->inputs = av_calloc(s->nb_inputs, sizeof(*s->inputs)); + if (!s->inputs) + return AVERROR(ENOMEM); + for (int i = 0; i < s->nb_inputs; i++) + RET(input_init(avctx, avctx->inputs[i], &s->inputs[i])); /* fall through */ fail: @@ -677,7 +683,11 @@ static void libplacebo_uninit(AVFilterContext *avctx) pl_tex_destroy(s->gpu, &s->tex[i]); for (int i = 0; i < s->num_hooks; i++) pl_mpv_user_shader_destroy(&s->hooks[i]); - input_uninit(&s->input); + if (s->inputs) { + for (int i = 0; i < s->nb_inputs; i++) + input_uninit(&s->inputs[i]); + av_freep(&s->inputs); + } pl_vulkan_destroy(&s->vulkan); pl_log_destroy(&s->log); ff_vk_uninit(&s->vkctx); @@ -774,7 +784,7 @@ static int output_frame(AVFilterContext *ctx, int64_t pts) { int err = 0, ok, changed_csp; LibplaceboContext *s = ctx->priv; - LibplaceboInput *in = &s->input; + LibplaceboInput *in = &s->inputs[0]; AVFilterLink *outlink = ctx->outputs[0]; const AVPixFmtDescriptor *outdesc = av_pix_fmt_desc_get(outlink->format); const AVFrame *ref = ref_frame(&in->mix); @@ -942,7 +952,7 @@ static int libplacebo_activate(AVFilterContext *ctx) { int ret; LibplaceboContext *s = ctx->priv; - LibplaceboInput *in = &s->input; + LibplaceboInput *in = &s->inputs[0]; AVFilterLink *outlink = ctx->outputs[0]; int64_t pts; From 0c66d912ba2248a3650fb1ed8563adf28bff2987 Mon Sep 17 00:00:00 2001 From: Niklas Haas Date: Thu, 15 Jun 2023 15:54:31 +0200 Subject: [PATCH 1615/2172] lavfi/vf_libplacebo: keep track of latest status globally This field will effectively hold the most recent status set by any input. Currently functionally equivalent to input->status, but will change soon. --- libavfilter/vf_libplacebo.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/libavfilter/vf_libplacebo.c b/libavfilter/vf_libplacebo.c index ee8780036cf..5b45d4f8fb5 100644 --- a/libavfilter/vf_libplacebo.c +++ b/libavfilter/vf_libplacebo.c @@ -138,6 +138,8 @@ typedef struct LibplaceboContext { /* input state */ LibplaceboInput *inputs; int nb_inputs; + int64_t status_pts; ///< tracks status of most recently used input + int status; /* settings */ char *out_format_string; @@ -943,6 +945,11 @@ static int handle_input(AVFilterContext *ctx, LibplaceboInput *input) pl_queue_push(input->queue, NULL); /* Signal EOF to pl_queue */ input->status = status; input->status_pts = pts; + if (!s->status || pts >= s->status_pts) { + /* Also propagate to output unless overwritten by later status change */ + s->status = status; + s->status_pts = pts; + } } return 0; @@ -975,8 +982,8 @@ static int libplacebo_activate(AVFilterContext *ctx) } } - if (in->status && pts >= in->status_pts) { - ff_outlink_set_status(outlink, in->status, in->status_pts); + if (s->status && pts >= s->status_pts) { + ff_outlink_set_status(outlink, s->status, s->status_pts); return 0; } From 56e550b2645963ad38f0211c6f01720d5bf0d6f3 Mon Sep 17 00:00:00 2001 From: Niklas Haas Date: Thu, 15 Jun 2023 15:56:33 +0200 Subject: [PATCH 1616/2172] lavfi/vf_libplacebo: support blending multiple inputs Subsequent inputs require frame blending to be enabled, in order to not overwrite the existing frame contents. For output metadata, we implicitly copy the metadata of the *first* available stream (falling back to the second stream if the first has already reached EOF, and so on). This is done to resolve any conflicts between inputs with differing metadata. So when e.g. input 1 is HDR and output 2 is SDR, the output will be HDR, and vice versa. This logic could probablly be improved by dynamically determining some "superior" set of metadata, but I don't want to handle that complexity in this series. --- libavfilter/vf_libplacebo.c | 24 ++++++++++++++++++++---- 1 file changed, 20 insertions(+), 4 deletions(-) diff --git a/libavfilter/vf_libplacebo.c b/libavfilter/vf_libplacebo.c index 5b45d4f8fb5..5ea6fcd7920 100644 --- a/libavfilter/vf_libplacebo.c +++ b/libavfilter/vf_libplacebo.c @@ -786,12 +786,18 @@ static int output_frame(AVFilterContext *ctx, int64_t pts) { int err = 0, ok, changed_csp; LibplaceboContext *s = ctx->priv; - LibplaceboInput *in = &s->inputs[0]; AVFilterLink *outlink = ctx->outputs[0]; const AVPixFmtDescriptor *outdesc = av_pix_fmt_desc_get(outlink->format); - const AVFrame *ref = ref_frame(&in->mix); struct pl_frame target; + const AVFrame *ref = NULL; AVFrame *out; + + /* Use the first active input as metadata reference */ + for (int i = 0; i < s->nb_inputs; i++) { + const LibplaceboInput *in = &s->inputs[i]; + if (in->qstatus == PL_QUEUE_OK && (ref = ref_frame(&in->mix))) + break; + } if (!ref) return 0; @@ -862,8 +868,18 @@ static int output_frame(AVFilterContext *ctx, int64_t pts) goto fail; } - update_crops(ctx, in, &target, out->pts * av_q2d(outlink->time_base)); - pl_render_image_mix(in->renderer, &in->mix, &target, &s->params); + /* Draw first frame opaque, others with blending */ + s->params.skip_target_clearing = false; + s->params.blend_params = NULL; + for (int i = 0; i < s->nb_inputs; i++) { + LibplaceboInput *in = &s->inputs[i]; + if (in->qstatus != PL_QUEUE_OK) + continue; + update_crops(ctx, in, &target, out->pts * av_q2d(outlink->time_base)); + pl_render_image_mix(in->renderer, &in->mix, &target, &s->params); + s->params.skip_target_clearing = true; + s->params.blend_params = &pl_alpha_overlay; + } if (outdesc->flags & AV_PIX_FMT_FLAG_HWACCEL) { pl_unmap_avframe(s->gpu, &target); From 0eb37c2419ad8728fbc5df8dc85791fc8fdf26e2 Mon Sep 17 00:00:00 2001 From: Niklas Haas Date: Thu, 15 Jun 2023 15:58:33 +0200 Subject: [PATCH 1617/2172] lavfi/vf_libplacebo: handle multiple inputs This commit still relies on a single input for PTS determination, to be changed in the next commit. --- libavfilter/vf_libplacebo.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/libavfilter/vf_libplacebo.c b/libavfilter/vf_libplacebo.c index 5ea6fcd7920..a56ebbf54e7 100644 --- a/libavfilter/vf_libplacebo.c +++ b/libavfilter/vf_libplacebo.c @@ -979,11 +979,13 @@ static int libplacebo_activate(AVFilterContext *ctx) AVFilterLink *outlink = ctx->outputs[0]; int64_t pts; - FF_FILTER_FORWARD_STATUS_BACK(outlink, in->link); + FF_FILTER_FORWARD_STATUS_BACK_ALL(outlink, ctx); pl_log_level_update(s->log, get_log_level()); - if ((ret = handle_input(ctx, in)) < 0) - return ret; + for (int i = 0; i < s->nb_inputs; i++) { + if ((ret = handle_input(ctx, &s->inputs[i])) < 0) + return ret; + } if (ff_outlink_frame_wanted(outlink)) { if (s->fps.num) { From 502b699a506b7854d382a58e4910f5f13f4846e4 Mon Sep 17 00:00:00 2001 From: Niklas Haas Date: Thu, 15 Jun 2023 16:01:55 +0200 Subject: [PATCH 1618/2172] lavfi/vf_libplacebo: determine PTS of next frame from any input When combining multiple inputs with different PTS and durations, in input-timed mode, we emit one output frame for every input frame PTS, from *any* input. So when combining a low FPS stream with a high FPS stream, the output framerate would match the higher FPS, independent of which order they are specified in. --- libavfilter/vf_libplacebo.c | 33 ++++++++++++++++++++------------- 1 file changed, 20 insertions(+), 13 deletions(-) diff --git a/libavfilter/vf_libplacebo.c b/libavfilter/vf_libplacebo.c index a56ebbf54e7..47f019fa192 100644 --- a/libavfilter/vf_libplacebo.c +++ b/libavfilter/vf_libplacebo.c @@ -973,11 +973,11 @@ static int handle_input(AVFilterContext *ctx, LibplaceboInput *input) static int libplacebo_activate(AVFilterContext *ctx) { - int ret; + int ret, retry = 0; LibplaceboContext *s = ctx->priv; LibplaceboInput *in = &s->inputs[0]; AVFilterLink *outlink = ctx->outputs[0]; - int64_t pts; + int64_t pts, out_pts; FF_FILTER_FORWARD_STATUS_BACK_ALL(outlink, ctx); pl_log_level_update(s->log, get_log_level()); @@ -989,24 +989,31 @@ static int libplacebo_activate(AVFilterContext *ctx) if (ff_outlink_frame_wanted(outlink)) { if (s->fps.num) { - pts = outlink->frame_count_out; - } else if (av_fifo_peek(in->out_pts, &pts, 1, 0) < 0) { - /* No frames queued */ - if (in->status) { - pts = in->status_pts; - } else { - ff_inlink_request_frame(in->link); - return 0; + out_pts = outlink->frame_count_out; + } else { + /* Determine the PTS of the next frame from any active input */ + out_pts = INT64_MAX; + for (int i = 0; i < s->nb_inputs; i++) { + LibplaceboInput *in = &s->inputs[i]; + if (av_fifo_peek(in->out_pts, &pts, 1, 0) >= 0) { + out_pts = FFMIN(out_pts, pts); + } else if (!in->status) { + ff_inlink_request_frame(in->link); + retry = true; + } } + + if (retry) /* some inputs are incomplete */ + return 0; } - if (s->status && pts >= s->status_pts) { + if (s->status && out_pts >= s->status_pts) { ff_outlink_set_status(outlink, s->status, s->status_pts); return 0; } in->qstatus = pl_queue_update(in->queue, &in->mix, pl_queue_params( - .pts = pts * av_q2d(outlink->time_base), + .pts = out_pts * av_q2d(outlink->time_base), .radius = pl_frame_mix_radius(&s->params), .vsync_duration = av_q2d(av_inv_q(outlink->frame_rate)), )); @@ -1018,7 +1025,7 @@ static int libplacebo_activate(AVFilterContext *ctx) case PL_QUEUE_OK: if (!s->fps.num) av_fifo_drain2(in->out_pts, 1); - return output_frame(ctx, pts); + return output_frame(ctx, out_pts); case PL_QUEUE_ERR: return AVERROR_EXTERNAL; } From 6c41c3f92815b9b62d19f871cbb261afbd58d5a0 Mon Sep 17 00:00:00 2001 From: Niklas Haas Date: Thu, 15 Jun 2023 16:03:32 +0200 Subject: [PATCH 1619/2172] lavfi/vf_libplacebo: only drain actually used PTS When combining multiple inputs, the output PTS may be less than the PTS of the input. In this case, the current's code assumption of always draining one value from the FIFO is incorrect. Replace by a smarter function which drains only those PTS values that were actually consumed. --- libavfilter/vf_libplacebo.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/libavfilter/vf_libplacebo.c b/libavfilter/vf_libplacebo.c index 47f019fa192..753d6f3cc79 100644 --- a/libavfilter/vf_libplacebo.c +++ b/libavfilter/vf_libplacebo.c @@ -971,6 +971,13 @@ static int handle_input(AVFilterContext *ctx, LibplaceboInput *input) return 0; } +static void drain_input_pts(LibplaceboInput *in, int64_t until) +{ + int64_t pts; + while (av_fifo_peek(in->out_pts, &pts, 1, 0) >= 0 && pts <= until) + av_fifo_drain2(in->out_pts, 1); +} + static int libplacebo_activate(AVFilterContext *ctx) { int ret, retry = 0; @@ -1023,8 +1030,7 @@ static int libplacebo_activate(AVFilterContext *ctx) ff_inlink_request_frame(in->link); return 0; case PL_QUEUE_OK: - if (!s->fps.num) - av_fifo_drain2(in->out_pts, 1); + drain_input_pts(in, out_pts); return output_frame(ctx, out_pts); case PL_QUEUE_ERR: return AVERROR_EXTERNAL; From d625010acde36fcf3ac4931ee25184aec06643c3 Mon Sep 17 00:00:00 2001 From: Niklas Haas Date: Thu, 15 Jun 2023 16:07:51 +0200 Subject: [PATCH 1620/2172] lavfi/vf_libplacebo: generalize frame update to multiple inputs In the event that some frame mixes are OK while others are not, the priority goes: 1. Errors in updating any frame -> return error 2. Any input incomplete -> request frames and return 3. Any inputs OK -> ignore EOF streams and render remaining inputs 4. No inputs OK -> set output to most recent status This logic ensures that we can continue rendering the remaining streams, no matter which streams reach their end of life, until we have no streams left at which point we forward the last EOF. --- libavfilter/vf_libplacebo.c | 52 ++++++++++++++++++++++++------------- 1 file changed, 34 insertions(+), 18 deletions(-) diff --git a/libavfilter/vf_libplacebo.c b/libavfilter/vf_libplacebo.c index 753d6f3cc79..6399aae0c67 100644 --- a/libavfilter/vf_libplacebo.c +++ b/libavfilter/vf_libplacebo.c @@ -980,9 +980,8 @@ static void drain_input_pts(LibplaceboInput *in, int64_t until) static int libplacebo_activate(AVFilterContext *ctx) { - int ret, retry = 0; + int ret, ok = 0, retry = 0; LibplaceboContext *s = ctx->priv; - LibplaceboInput *in = &s->inputs[0]; AVFilterLink *outlink = ctx->outputs[0]; int64_t pts, out_pts; @@ -1014,26 +1013,43 @@ static int libplacebo_activate(AVFilterContext *ctx) return 0; } - if (s->status && out_pts >= s->status_pts) { - ff_outlink_set_status(outlink, s->status, s->status_pts); - return 0; - } + /* Update all input queues to the chosen out_pts */ + for (int i = 0; i < s->nb_inputs; i++) { + LibplaceboInput *in = &s->inputs[i]; + if (in->status && out_pts >= in->status_pts) { + in->qstatus = PL_QUEUE_EOF; + continue; + } - in->qstatus = pl_queue_update(in->queue, &in->mix, pl_queue_params( - .pts = out_pts * av_q2d(outlink->time_base), - .radius = pl_frame_mix_radius(&s->params), - .vsync_duration = av_q2d(av_inv_q(outlink->frame_rate)), - )); + in->qstatus = pl_queue_update(in->queue, &in->mix, pl_queue_params( + .pts = out_pts * av_q2d(outlink->time_base), + .radius = pl_frame_mix_radius(&s->params), + .vsync_duration = av_q2d(av_inv_q(outlink->frame_rate)), + )); + + switch (in->qstatus) { + case PL_QUEUE_MORE: + ff_inlink_request_frame(in->link); + retry = true; + break; + case PL_QUEUE_OK: + ok = true; + break; + case PL_QUEUE_ERR: + return AVERROR_EXTERNAL; + } + } - switch (in->qstatus) { - case PL_QUEUE_MORE: - ff_inlink_request_frame(in->link); + if (retry) { return 0; - case PL_QUEUE_OK: - drain_input_pts(in, out_pts); + } else if (ok) { + /* Got any valid frame mixes, drain PTS queue and render output */ + for (int i = 0; i < s->nb_inputs; i++) + drain_input_pts(&s->inputs[i], out_pts); return output_frame(ctx, out_pts); - case PL_QUEUE_ERR: - return AVERROR_EXTERNAL; + } else if (s->status) { + ff_outlink_set_status(outlink, s->status, s->status_pts); + return 0; } return AVERROR_BUG; From 7645c8df666a0fb4520dd11f1c799660c2a33327 Mon Sep 17 00:00:00 2001 From: Niklas Haas Date: Thu, 15 Jun 2023 16:23:26 +0200 Subject: [PATCH 1621/2172] lavfi/vf_libplacebo: make input-dependent vars dynamic Because these can differ based on the input, for multiple inputs. --- libavfilter/vf_libplacebo.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/libavfilter/vf_libplacebo.c b/libavfilter/vf_libplacebo.c index 6399aae0c67..a3a034766e2 100644 --- a/libavfilter/vf_libplacebo.c +++ b/libavfilter/vf_libplacebo.c @@ -741,6 +741,11 @@ static void update_crops(AVFilterContext *ctx, LibplaceboInput *in, double image_pts = src->pts * av_q2d(in->link->time_base); /* Update dynamic variables */ + s->var_values[VAR_IN_W] = s->var_values[VAR_IW] = in->link->w; + s->var_values[VAR_IN_H] = s->var_values[VAR_IH] = in->link->h; + s->var_values[VAR_A] = (double) in->link->w / in->link->h; + s->var_values[VAR_SAR] = in->link->sample_aspect_ratio.num ? + av_q2d(in->link->sample_aspect_ratio) : 1.0; s->var_values[VAR_IN_T] = s->var_values[VAR_T] = image_pts; s->var_values[VAR_OUT_T] = s->var_values[VAR_OT] = target_pts; s->var_values[VAR_N] = ctx->outputs[0]->frame_count_out; @@ -1193,13 +1198,8 @@ static int libplacebo_config_output(AVFilterLink *outlink) } /* Static variables */ - s->var_values[VAR_IN_W] = s->var_values[VAR_IW] = inlink->w; - s->var_values[VAR_IN_H] = s->var_values[VAR_IH] = inlink->h; s->var_values[VAR_OUT_W] = s->var_values[VAR_OW] = outlink->w; s->var_values[VAR_OUT_H] = s->var_values[VAR_OH] = outlink->h; - s->var_values[VAR_A] = (double) inlink->w / inlink->h; - s->var_values[VAR_SAR] = inlink->sample_aspect_ratio.num ? - av_q2d(inlink->sample_aspect_ratio) : 1.0; s->var_values[VAR_DAR] = outlink->sample_aspect_ratio.num ? av_q2d(outlink->sample_aspect_ratio) : 1.0; s->var_values[VAR_HSUB] = 1 << desc->log2_chroma_w; From 5989719e87ba12d21196e6dea73ad5a631fddee1 Mon Sep 17 00:00:00 2001 From: Niklas Haas Date: Thu, 15 Jun 2023 16:24:20 +0200 Subject: [PATCH 1622/2172] lavfi/vf_libplacebo: add in_idx variable To allow placing an input dynamically, as a function of the input index. --- doc/filters.texi | 2 ++ libavfilter/vf_libplacebo.c | 9 +++++++-- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/doc/filters.texi b/doc/filters.texi index 59721457631..366dc53b792 100644 --- a/doc/filters.texi +++ b/doc/filters.texi @@ -16320,6 +16320,8 @@ the @option{crop_w}, @option{crop_h}, @option{crop_x}, @option{crop_y}, also contain the following constants: @table @option +@item in_idx, idx +The (0-based) numeric index of the currently active input stream. @item crop_w, cw @item crop_h, ch The computed values of @option{crop_w} and @option{crop_h}. diff --git a/libavfilter/vf_libplacebo.c b/libavfilter/vf_libplacebo.c index a3a034766e2..fcd3ad07e2c 100644 --- a/libavfilter/vf_libplacebo.c +++ b/libavfilter/vf_libplacebo.c @@ -70,6 +70,7 @@ enum { }; static const char *const var_names[] = { + "in_idx", "idx",///< index of input "in_w", "iw", ///< width of the input video frame "in_h", "ih", ///< height of the input video frame "out_w", "ow", ///< width of the output video frame @@ -92,6 +93,7 @@ static const char *const var_names[] = { }; enum var_name { + VAR_IN_IDX, VAR_IDX, VAR_IN_W, VAR_IW, VAR_IN_H, VAR_IH, VAR_OUT_W, VAR_OW, @@ -115,6 +117,7 @@ enum var_name { /* per-input dynamic filter state */ typedef struct LibplaceboInput { + int idx; pl_renderer renderer; pl_queue queue; enum pl_queue_status qstatus; @@ -574,7 +577,7 @@ static void unlock_queue(void *priv, uint32_t qf, uint32_t qidx) #endif static int input_init(AVFilterContext *avctx, AVFilterLink *link, - LibplaceboInput *input) + LibplaceboInput *input, int idx) { LibplaceboContext *s = avctx->priv; @@ -584,6 +587,7 @@ static int input_init(AVFilterContext *avctx, AVFilterLink *link, input->queue = pl_queue_create(s->gpu); input->renderer = pl_renderer_create(s->log, s->gpu); input->link = link; + input->idx = idx; return 0; } @@ -668,7 +672,7 @@ static int init_vulkan(AVFilterContext *avctx, const AVVulkanDeviceContext *hwct if (!s->inputs) return AVERROR(ENOMEM); for (int i = 0; i < s->nb_inputs; i++) - RET(input_init(avctx, avctx->inputs[i], &s->inputs[i])); + RET(input_init(avctx, avctx->inputs[i], &s->inputs[i], i)); /* fall through */ fail: @@ -741,6 +745,7 @@ static void update_crops(AVFilterContext *ctx, LibplaceboInput *in, double image_pts = src->pts * av_q2d(in->link->time_base); /* Update dynamic variables */ + s->var_values[VAR_IN_IDX] = s->var_values[VAR_IDX] = in->idx; s->var_values[VAR_IN_W] = s->var_values[VAR_IW] = in->link->w; s->var_values[VAR_IN_H] = s->var_values[VAR_IH] = in->link->h; s->var_values[VAR_A] = (double) in->link->w / in->link->h; From 015c3b659ee38505f704bebe8a8fad612b9c5f48 Mon Sep 17 00:00:00 2001 From: Niklas Haas Date: Thu, 15 Jun 2023 16:51:19 +0200 Subject: [PATCH 1623/2172] lavfi/vf_libplacebo: set format list for all inputs --- libavfilter/vf_libplacebo.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libavfilter/vf_libplacebo.c b/libavfilter/vf_libplacebo.c index fcd3ad07e2c..627223256c6 100644 --- a/libavfilter/vf_libplacebo.c +++ b/libavfilter/vf_libplacebo.c @@ -1131,7 +1131,8 @@ static int libplacebo_query_format(AVFilterContext *ctx) goto fail; } - RET(ff_formats_ref(infmts, &ctx->inputs[0]->outcfg.formats)); + for (int i = 0; i < s->nb_inputs; i++) + RET(ff_formats_ref(infmts, &ctx->inputs[i]->outcfg.formats)); RET(ff_formats_ref(outfmts, &ctx->outputs[0]->incfg.formats)); return 0; From 618b72d4b407b916c47aa621ad90f21b7fa6adc2 Mon Sep 17 00:00:00 2001 From: Niklas Haas Date: Thu, 15 Jun 2023 17:00:42 +0200 Subject: [PATCH 1624/2172] lavfi/vf_libplacebo: skip cache selectively per-input It may be the case that we want to skip the single frame cache for some inputs but not others. --- libavfilter/vf_libplacebo.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/libavfilter/vf_libplacebo.c b/libavfilter/vf_libplacebo.c index 627223256c6..f7b9bdba742 100644 --- a/libavfilter/vf_libplacebo.c +++ b/libavfilter/vf_libplacebo.c @@ -182,7 +182,6 @@ typedef struct LibplaceboContext { float antiringing; int sigmoid; int skip_aa; - int skip_cache; float polar_cutoff; int disable_linear; int disable_builtin; @@ -471,7 +470,6 @@ static int update_settings(AVFilterContext *ctx) .num_hooks = s->num_hooks, .skip_anti_aliasing = s->skip_aa, - .skip_caching_single_frame = s->skip_cache, .polar_cutoff = s->polar_cutoff, .disable_linear_scaling = s->disable_linear, .disable_builtin_scalers = s->disable_builtin, @@ -883,8 +881,10 @@ static int output_frame(AVFilterContext *ctx, int64_t pts) s->params.blend_params = NULL; for (int i = 0; i < s->nb_inputs; i++) { LibplaceboInput *in = &s->inputs[i]; + int high_fps = av_cmp_q(in->link->frame_rate, outlink->frame_rate) > 0; if (in->qstatus != PL_QUEUE_OK) continue; + s->params.skip_caching_single_frame = high_fps; update_crops(ctx, in, &target, out->pts * av_q2d(outlink->time_base)); pl_render_image_mix(in->renderer, &in->mix, &target, &s->params); s->params.skip_target_clearing = true; @@ -1198,9 +1198,6 @@ static int libplacebo_config_output(AVFilterLink *outlink) if (s->fps.num) { outlink->frame_rate = s->fps; outlink->time_base = av_inv_q(s->fps); - s->skip_cache = av_cmp_q(inlink->frame_rate, s->fps) > 0; - } else { - s->skip_cache = true; } /* Static variables */ From 1b2c6c9a0367e49842ae6464c7d077f35ad22052 Mon Sep 17 00:00:00 2001 From: Niklas Haas Date: Thu, 15 Jun 2023 17:01:07 +0200 Subject: [PATCH 1625/2172] lavfi/vf_libplacebo: also skip cache if in FPS == out FPS Fixes an oversight in the previous code which should have been >=, not >. --- libavfilter/vf_libplacebo.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavfilter/vf_libplacebo.c b/libavfilter/vf_libplacebo.c index f7b9bdba742..1085b6fdd0a 100644 --- a/libavfilter/vf_libplacebo.c +++ b/libavfilter/vf_libplacebo.c @@ -881,7 +881,7 @@ static int output_frame(AVFilterContext *ctx, int64_t pts) s->params.blend_params = NULL; for (int i = 0; i < s->nb_inputs; i++) { LibplaceboInput *in = &s->inputs[i]; - int high_fps = av_cmp_q(in->link->frame_rate, outlink->frame_rate) > 0; + int high_fps = av_cmp_q(in->link->frame_rate, outlink->frame_rate) >= 0; if (in->qstatus != PL_QUEUE_OK) continue; s->params.skip_caching_single_frame = high_fps; From 9049ea676363f113eaaef4dbf21aee7df69a3988 Mon Sep 17 00:00:00 2001 From: Niklas Haas Date: Thu, 15 Jun 2023 17:02:48 +0200 Subject: [PATCH 1626/2172] lavfi/vf_libplacebo: set time_base/frame_rate dynamically Use the gcd of all input timebases to ensure PTS accuracy. For the framerate, just pick the highest of all the inputs, under the assumption that we will render frames with approximately this frequency. Of course, this is not 100% accurate, in particular if the input frames are badly misaligned. But this field is informational to begin with. Importantly, it covers the "common" case of combining high FPS and low FPS streams with aligned frames. --- libavfilter/vf_libplacebo.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/libavfilter/vf_libplacebo.c b/libavfilter/vf_libplacebo.c index 1085b6fdd0a..09a24e7c291 100644 --- a/libavfilter/vf_libplacebo.c +++ b/libavfilter/vf_libplacebo.c @@ -1158,6 +1158,11 @@ static int libplacebo_config_input(AVFilterLink *inlink) return 0; } +static inline AVRational max_q(AVRational a, AVRational b) +{ + return av_cmp_q(a, b) < 0 ? b : a; +} + static int libplacebo_config_output(AVFilterLink *outlink) { int err; @@ -1198,6 +1203,16 @@ static int libplacebo_config_output(AVFilterLink *outlink) if (s->fps.num) { outlink->frame_rate = s->fps; outlink->time_base = av_inv_q(s->fps); + } else { + outlink->frame_rate = avctx->inputs[0]->frame_rate; + outlink->time_base = avctx->inputs[0]->time_base; + for (int i = 1; i < s->nb_inputs; i++) { + outlink->frame_rate = max_q(outlink->frame_rate, + avctx->inputs[i]->frame_rate); + outlink->time_base = av_gcd_q(outlink->time_base, + avctx->inputs[i]->time_base, + AV_TIME_BASE / 2, AV_TIME_BASE_Q); + } } /* Static variables */ From f998a618bac1f61586a3625620e0794c1abba04c Mon Sep 17 00:00:00 2001 From: Niklas Haas Date: Thu, 15 Jun 2023 13:36:20 +0200 Subject: [PATCH 1627/2172] lavfi/vf_libplacebo: add nb_inputs option To control the number of inputs. --- doc/filters.texi | 5 +++++ libavfilter/vf_libplacebo.c | 25 ++++++++++++++----------- 2 files changed, 19 insertions(+), 11 deletions(-) diff --git a/doc/filters.texi b/doc/filters.texi index 366dc53b792..f596773af65 100644 --- a/doc/filters.texi +++ b/doc/filters.texi @@ -16224,6 +16224,11 @@ to preserve the source colorimetry and size as best as it can, but it will apply any embedded film grain, dolby vision metadata or anamorphic SAR present in source frames. @table @option +@item inputs +Set the number of inputs. This can be used, alongside the @code{idx} variable, +to allow placing/blending multiple inputs inside the output frame. This +effectively enables functionality similar to @ref{hstack}, @ref{overlay}, etc. + @item w @item h Set the output video dimension expression. Default values are @code{iw} and diff --git a/libavfilter/vf_libplacebo.c b/libavfilter/vf_libplacebo.c index 09a24e7c291..056041d2131 100644 --- a/libavfilter/vf_libplacebo.c +++ b/libavfilter/vf_libplacebo.c @@ -502,6 +502,7 @@ static int parse_shader(AVFilterContext *avctx, const void *shader, size_t len) } static void libplacebo_uninit(AVFilterContext *avctx); +static int libplacebo_config_input(AVFilterLink *inlink); static int libplacebo_init(AVFilterContext *avctx) { @@ -530,6 +531,17 @@ static int libplacebo_init(AVFilterContext *avctx) s->out_format = AV_PIX_FMT_NONE; } + for (int i = 0; i < s->nb_inputs; i++) { + AVFilterPad pad = { + .name = av_asprintf("input%d", i), + .type = AVMEDIA_TYPE_VIDEO, + .config_props = &libplacebo_config_input, + }; + if (!pad.name) + return AVERROR(ENOMEM); + RET(ff_append_inpad_free_name(avctx, &pad)); + } + RET(update_settings(avctx)); RET(av_expr_parse(&s->crop_x_pexpr, s->crop_x_expr, var_names, NULL, NULL, NULL, NULL, 0, s)); @@ -665,7 +677,6 @@ static int init_vulkan(AVFilterContext *avctx, const AVVulkanDeviceContext *hwct } /* Initialize inputs */ - s->nb_inputs = 1; s->inputs = av_calloc(s->nb_inputs, sizeof(*s->inputs)); if (!s->inputs) return AVERROR(ENOMEM); @@ -1252,6 +1263,7 @@ static int libplacebo_config_output(AVFilterLink *outlink) #define DYNAMIC (STATIC | AV_OPT_FLAG_RUNTIME_PARAM) static const AVOption libplacebo_options[] = { + { "inputs", "Number of inputs", OFFSET(nb_inputs), AV_OPT_TYPE_INT, {.i64 = 1}, 1, INT_MAX, .flags = STATIC }, { "w", "Output video frame width", OFFSET(w_expr), AV_OPT_TYPE_STRING, {.str = "iw"}, .flags = STATIC }, { "h", "Output video frame height", OFFSET(h_expr), AV_OPT_TYPE_STRING, {.str = "ih"}, .flags = STATIC }, { "fps", "Output video frame rate", OFFSET(fps_string), AV_OPT_TYPE_STRING, {.str = "none"}, .flags = STATIC }, @@ -1443,14 +1455,6 @@ static const AVOption libplacebo_options[] = { AVFILTER_DEFINE_CLASS(libplacebo); -static const AVFilterPad libplacebo_inputs[] = { - { - .name = "default", - .type = AVMEDIA_TYPE_VIDEO, - .config_props = &libplacebo_config_input, - }, -}; - static const AVFilterPad libplacebo_outputs[] = { { .name = "default", @@ -1467,10 +1471,9 @@ const AVFilter ff_vf_libplacebo = { .uninit = &libplacebo_uninit, .activate = &libplacebo_activate, .process_command = &libplacebo_process_command, - FILTER_INPUTS(libplacebo_inputs), FILTER_OUTPUTS(libplacebo_outputs), FILTER_QUERY_FUNC(libplacebo_query_format), .priv_class = &libplacebo_class, .flags_internal = FF_FILTER_FLAG_HWFRAME_AWARE, - .flags = AVFILTER_FLAG_HWDEVICE, + .flags = AVFILTER_FLAG_HWDEVICE | AVFILTER_FLAG_DYNAMIC_INPUTS, }; From e998d0a4f7cce78d36a7d4ebdc11aa4e39f5b440 Mon Sep 17 00:00:00 2001 From: Niklas Haas Date: Tue, 20 Jun 2023 16:36:08 +0200 Subject: [PATCH 1628/2172] lavfi/vf_libplacebo: allow pos_w to depend on pos_h Ditto for crop_w/crop_h. Requires simply repeating the evaluation of the first variable to be evaluated. --- libavfilter/vf_libplacebo.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/libavfilter/vf_libplacebo.c b/libavfilter/vf_libplacebo.c index 056041d2131..0f7c6481925 100644 --- a/libavfilter/vf_libplacebo.c +++ b/libavfilter/vf_libplacebo.c @@ -775,10 +775,14 @@ static void update_crops(AVFilterContext *ctx, LibplaceboInput *in, av_expr_eval(s->crop_w_pexpr, s->var_values, NULL); s->var_values[VAR_CROP_H] = s->var_values[VAR_CH] = av_expr_eval(s->crop_h_pexpr, s->var_values, NULL); + s->var_values[VAR_CROP_W] = s->var_values[VAR_CW] = + av_expr_eval(s->crop_w_pexpr, s->var_values, NULL); s->var_values[VAR_POS_W] = s->var_values[VAR_PW] = av_expr_eval(s->pos_w_pexpr, s->var_values, NULL); s->var_values[VAR_POS_H] = s->var_values[VAR_PH] = av_expr_eval(s->pos_h_pexpr, s->var_values, NULL); + s->var_values[VAR_POS_W] = s->var_values[VAR_PW] = + av_expr_eval(s->pos_w_pexpr, s->var_values, NULL); image->crop.x0 = av_expr_eval(s->crop_x_pexpr, s->var_values, NULL); image->crop.y0 = av_expr_eval(s->crop_y_pexpr, s->var_values, NULL); From 33c99728081e1a647eadf8d1ae95d569ed77e611 Mon Sep 17 00:00:00 2001 From: Leo Izen Date: Sun, 18 Jun 2023 10:39:20 -0400 Subject: [PATCH 1629/2172] MAINTAINERS: change Leo Izen IRC nickname I use a different nick on IRC now, Traneptora, instead of what I formerly used, thebombzen. Signed-off-by: --- MAINTAINERS | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MAINTAINERS b/MAINTAINERS index fe60eca88da..b5c116c3d4d 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -618,7 +618,7 @@ 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 -Leo Izen (thebombzen) B6FD 3CFC 7ACF 83FC 9137 6945 5A71 C331 FD2F A19A +Leo Izen (Traneptora) B6FD 3CFC 7ACF 83FC 9137 6945 5A71 C331 FD2F A19A Loren Merritt ABD9 08F4 C920 3F65 D8BE 35D7 1540 DAA7 060F 56DE Lynne FE50 139C 6805 72CA FD52 1F8D A2FE A5F0 3F03 4464 Michael Niedermayer 9FF2 128B 147E F673 0BAD F133 611E C787 040B 0FAB From 6a9d13acc26bf02a33b9b8b836bed26d9d43f303 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Sun, 18 Jun 2023 23:50:18 +0200 Subject: [PATCH 1630/2172] avformat/jpegxl_anim_dec: fix out of array read using buffer padding Fixes: out of array read Fixes: 59828/clusterfuzz-testcase-minimized-ffmpeg_dem_JPEGXL_ANIM_fuzzer-5029813220671488 Found-by: continuous fuzzing process https://github.com/google/oss-fuzz/tree/master/projects/ffmpeg Signed-off-by: Michael Niedermayer --- libavformat/jpegxl_anim_dec.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/libavformat/jpegxl_anim_dec.c b/libavformat/jpegxl_anim_dec.c index 8d6ea5005c7..956b56c1d8e 100644 --- a/libavformat/jpegxl_anim_dec.c +++ b/libavformat/jpegxl_anim_dec.c @@ -112,7 +112,7 @@ static int jpegxl_collect_codestream_header(const uint8_t *input_buffer, int inp static int jpegxl_anim_probe(const AVProbeData *p) { - uint8_t buffer[4096]; + uint8_t buffer[4096 + AV_INPUT_BUFFER_PADDING_SIZE]; int copied; /* this is a raw codestream */ @@ -127,7 +127,7 @@ static int jpegxl_anim_probe(const AVProbeData *p) if (AV_RL64(p->buf) != FF_JPEGXL_CONTAINER_SIGNATURE_LE) return 0; - if (jpegxl_collect_codestream_header(p->buf, p->buf_size, buffer, sizeof(buffer), &copied) <= 0 || copied <= 0) + if (jpegxl_collect_codestream_header(p->buf, p->buf_size, buffer, sizeof(buffer) - AV_INPUT_BUFFER_PADDING_SIZE, &copied) <= 0 || copied <= 0) return 0; if (ff_jpegxl_verify_codestream_header(buffer, copied, 0) >= 1) @@ -142,7 +142,8 @@ static int jpegxl_anim_read_header(AVFormatContext *s) AVIOContext *pb = s->pb; AVStream *st; int offset = 0; - uint8_t head[256]; + uint8_t head[256 + AV_INPUT_BUFFER_PADDING_SIZE]; + const int sizeofhead = sizeof(head) - AV_INPUT_BUFFER_PADDING_SIZE; int headsize = 0; int ctrl; AVRational tb; @@ -151,7 +152,7 @@ static int jpegxl_anim_read_header(AVFormatContext *s) uint64_t sig16 = avio_rl16(pb); if (sig16 == FF_JPEGXL_CODESTREAM_SIGNATURE_LE) { AV_WL16(head, sig16); - headsize = avio_read(s->pb, head + 2, sizeof(head) - 2); + headsize = avio_read(s->pb, head + 2, sizeofhead - 2); if (headsize < 0) return headsize; headsize += 2; @@ -182,10 +183,10 @@ static int jpegxl_anim_read_header(AVFormatContext *s) if (av_buffer_realloc(&ctx->initial, ctx->initial->size + read) < 0) return AVERROR(ENOMEM); } - jpegxl_collect_codestream_header(buf, read, head + headsize, sizeof(head) - headsize, &copied); + jpegxl_collect_codestream_header(buf, read, head + headsize, sizeofhead - headsize, &copied); memcpy(ctx->initial->data + (ctx->initial->size - read), buf, read); headsize += copied; - if (headsize >= sizeof(head) || read < sizeof(buf)) + if (headsize >= sizeofhead || read < sizeof(buf)) break; } } From 98cae37e23ed4c48116d5e7d8ad5131df2e193c3 Mon Sep 17 00:00:00 2001 From: James Almer Date: Tue, 20 Jun 2023 14:54:11 -0300 Subject: [PATCH 1631/2172] Changelog: mention the recent AC-4 additions Signed-off-by: James Almer --- Changelog | 1 + 1 file changed, 1 insertion(+) diff --git a/Changelog b/Changelog index 9cf3df8d6fc..5e4492fb71a 100644 --- a/Changelog +++ b/Changelog @@ -21,6 +21,7 @@ version : - Essential Video Coding frame merge bsf - bwdif_cuda filter - Microsoft RLE video encoder +- Raw AC-4 muxer and demuxer version 6.0: - Radiance HDR image support From 468615f2045da325e0f73e8e668d49cf456ccb37 Mon Sep 17 00:00:00 2001 From: Romain Beauxis Date: Tue, 20 Jun 2023 00:09:33 -0500 Subject: [PATCH 1632/2172] libavformat/mpegts.c: fix hardcoded 5-bytes skip for metadata streams. Before the introduction of AV_CODEC_ID_TIMED_ID3 for timed_id3 metadata streams in mpegts (commit 4a4437c0fbc8f7afe0c533070395a42e56b4ee75), AV_CODEC_ID_SMPTE_KLV was the only existing codec for metadata. It seems that this codec has a 5-bytes metadata header[1] that, for some reason, was always skipped when decoding data packets. However, when working with a AV_CODEC_ID_TIMED_ID3 streams, this results in the 5 first bytes of the payload being cut-off, which includes essential informations such as the ID3 tag version. This patch fixes the issue by keeping the 5-bytes skip only for AV_CODEC_ID_SMPTE_KLV streams. Reviewed-by: Paul B Mahol Signed-off-by: James Almer --- libavformat/mpegts.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavformat/mpegts.c b/libavformat/mpegts.c index fb8b0bf8fd0..0b3edda8179 100644 --- a/libavformat/mpegts.c +++ b/libavformat/mpegts.c @@ -1305,7 +1305,7 @@ static int mpegts_push_data(MpegTSFilter *filter, p += sl_header_bytes; buf_size -= sl_header_bytes; } - if (pes->stream_type == 0x15 && buf_size >= 5) { + if (pes->st->codecpar->codec_id == AV_CODEC_ID_SMPTE_KLV && buf_size >= 5) { /* skip metadata access unit header */ pes->pes_header_size += 5; p += 5; From 83b3ff741be6d7c0c4b10bedaada7a329b96f22b Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Mon, 19 Jun 2023 15:32:27 +0200 Subject: [PATCH 1633/2172] tests/fate/ffmpeg: silence the audio for fate-ffmpeg-streamloop-transcode-av Fixed-point AAC decoder currently does not produce the same output on all platforms. Until that is fixed, silence the audio stream using the volume filter. Also, actually use the aac_fixed decoder as was the original intent. --- tests/fate/ffmpeg.mak | 7 +- tests/ref/fate/ffmpeg-streamloop-transcode-av | 144 +++++++++--------- 2 files changed, 77 insertions(+), 74 deletions(-) diff --git a/tests/fate/ffmpeg.mak b/tests/fate/ffmpeg.mak index 87cd0b46d06..2b3135b6a67 100644 --- a/tests/fate/ffmpeg.mak +++ b/tests/fate/ffmpeg.mak @@ -132,9 +132,12 @@ fate-ffmpeg-fix_sub_duration_heartbeat: CMD = fmtstdout srt -fix_sub_duration \ -c:s srt \ -f null - -FATE_SAMPLES_FFMPEG-$(call FRAMECRC, MATROSKA, H264 AAC_FIXED, PCM_S32LE_ENCODER) += fate-ffmpeg-streamloop-transcode-av +# FIXME: the integer AAC decoder does not produce the same output on all platforms +# so until that is fixed we use the volume filter to silence the data +FATE_SAMPLES_FFMPEG-$(call FRAMECRC, MATROSKA, H264 AAC_FIXED, PCM_S32LE_ENCODER VOLUME_FILTER) += fate-ffmpeg-streamloop-transcode-av fate-ffmpeg-streamloop-transcode-av: CMD = \ - framecrc -auto_conversion_filters -stream_loop 3 -i $(TARGET_SAMPLES)/mkv/1242-small.mkv -c:a pcm_s32le + framecrc -auto_conversion_filters -stream_loop 3 -c:a aac_fixed -i $(TARGET_SAMPLES)/mkv/1242-small.mkv \ + -af volume=0:precision=fixed -c:a pcm_s32le FATE_STREAMCOPY-$(call REMUX, MP4 MOV, EAC3_DEMUXER) += fate-copy-trac3074 fate-copy-trac3074: CMD = transcode eac3 $(TARGET_SAMPLES)/eac3/csi_miami_stereo_128_spx.eac3\ diff --git a/tests/ref/fate/ffmpeg-streamloop-transcode-av b/tests/ref/fate/ffmpeg-streamloop-transcode-av index 50a626b281b..6934e39d41f 100644 --- a/tests/ref/fate/ffmpeg-streamloop-transcode-av +++ b/tests/ref/fate/ffmpeg-streamloop-transcode-av @@ -18,31 +18,31 @@ 1, 4072, 4072, 1024, 8192, 0x00000000 1, 5096, 5096, 1024, 8192, 0x00000000 0, 3, 3, 1, 1378560, 0xca1deba8 -1, 6120, 6120, 1024, 8192, 0x687330d2 -1, 7128, 7128, 1024, 8192, 0x9131462c +1, 6120, 6120, 1024, 8192, 0x00000000 +1, 7128, 7128, 1024, 8192, 0x00000000 0, 4, 4, 1, 1378560, 0xd4eed467 -1, 8208, 8208, 1024, 8192, 0x48c01c32 -1, 9232, 9232, 1024, 8192, 0x0ccd8d5f +1, 8208, 8208, 1024, 8192, 0x00000000 +1, 9232, 9232, 1024, 8192, 0x00000000 0, 5, 5, 1, 1378560, 0xd6e1d5b7 -1, 10248, 10248, 1024, 8192, 0xd50cbe9f -1, 11256, 11256, 1024, 8192, 0xbe069303 +1, 10248, 10248, 1024, 8192, 0x00000000 +1, 11256, 11256, 1024, 8192, 0x00000000 0, 6, 6, 1, 1378560, 0x0b574d39 -1, 12280, 12280, 1024, 8192, 0x85fccf5b -1, 13304, 13304, 1024, 8192, 0x4180de71 +1, 12280, 12280, 1024, 8192, 0x00000000 +1, 13304, 13304, 1024, 8192, 0x00000000 0, 7, 7, 1, 1378560, 0x1bdd4d61 -1, 14328, 14328, 1024, 8192, 0x0e9b6ac3 -1, 15336, 15336, 1024, 8192, 0x5c33f724 +1, 14328, 14328, 1024, 8192, 0x00000000 +1, 15336, 15336, 1024, 8192, 0x00000000 0, 8, 8, 1, 1378560, 0x3b28f549 -1, 16360, 16360, 1024, 8192, 0x668aaaec -1, 17384, 17384, 1024, 8192, 0xd137d412 +1, 16360, 16360, 1024, 8192, 0x00000000 +1, 17384, 17384, 1024, 8192, 0x00000000 0, 9, 9, 1, 1378560, 0x45b2f57b -1, 18408, 18408, 1024, 8192, 0x08e1fbf6 -1, 19416, 19416, 1024, 8192, 0xbf3fb4f6 +1, 18408, 18408, 1024, 8192, 0x00000000 +1, 19416, 19416, 1024, 8192, 0x00000000 0, 10, 10, 1, 1378560, 0x8955570e -1, 20440, 20440, 1024, 8192, 0x69cd08a4 -1, 21464, 21464, 1024, 8192, 0xe0fe6297 -1, 22488, 22488, 1024, 8192, 0x172867ad -1, 23496, 23496, 1024, 8192, 0xcbcc1461 +1, 20440, 20440, 1024, 8192, 0x00000000 +1, 21464, 21464, 1024, 8192, 0x00000000 +1, 22488, 22488, 1024, 8192, 0x00000000 +1, 23496, 23496, 1024, 8192, 0x00000000 0, 12, 12, 1, 1378560, 0x9c598000 1, 25488, 25488, 1024, 8192, 0x00000000 0, 13, 13, 1, 1378560, 0xbaf121ba @@ -52,32 +52,32 @@ 1, 28552, 28552, 1024, 8192, 0x00000000 1, 29576, 29576, 1024, 8192, 0x00000000 0, 15, 15, 1, 1378560, 0x6579d31a -1, 30600, 30600, 1024, 8192, 0x687330d2 -1, 31608, 31608, 1024, 8192, 0x9131462c +1, 30600, 30600, 1024, 8192, 0x00000000 +1, 31608, 31608, 1024, 8192, 0x00000000 0, 16, 16, 1, 1378560, 0xca1deba8 -1, 32688, 32688, 1024, 8192, 0x48c01c32 -1, 33712, 33712, 1024, 8192, 0x0ccd8d5f +1, 32688, 32688, 1024, 8192, 0x00000000 +1, 33712, 33712, 1024, 8192, 0x00000000 0, 17, 17, 1, 1378560, 0xd4eed467 -1, 34728, 34728, 1024, 8192, 0xd50cbe9f -1, 35736, 35736, 1024, 8192, 0xbe069303 +1, 34728, 34728, 1024, 8192, 0x00000000 +1, 35736, 35736, 1024, 8192, 0x00000000 0, 18, 18, 1, 1378560, 0xd6e1d5b7 -1, 36760, 36760, 1024, 8192, 0x85fccf5b -1, 37784, 37784, 1024, 8192, 0x4180de71 +1, 36760, 36760, 1024, 8192, 0x00000000 +1, 37784, 37784, 1024, 8192, 0x00000000 0, 19, 19, 1, 1378560, 0x0b574d39 -1, 38808, 38808, 1024, 8192, 0x0e9b6ac3 -1, 39816, 39816, 1024, 8192, 0x5c33f724 +1, 38808, 38808, 1024, 8192, 0x00000000 +1, 39816, 39816, 1024, 8192, 0x00000000 0, 20, 20, 1, 1378560, 0x1bdd4d61 -1, 40840, 40840, 1024, 8192, 0x668aaaec -1, 41864, 41864, 1024, 8192, 0xd137d412 +1, 40840, 40840, 1024, 8192, 0x00000000 +1, 41864, 41864, 1024, 8192, 0x00000000 0, 21, 21, 1, 1378560, 0x3b28f549 -1, 42888, 42888, 1024, 8192, 0x08e1fbf6 -1, 43896, 43896, 1024, 8192, 0xbf3fb4f6 +1, 42888, 42888, 1024, 8192, 0x00000000 +1, 43896, 43896, 1024, 8192, 0x00000000 0, 22, 22, 1, 1378560, 0x45b2f57b -1, 44920, 44920, 1024, 8192, 0x69cd08a4 -1, 45944, 45944, 1024, 8192, 0xe0fe6297 +1, 44920, 44920, 1024, 8192, 0x00000000 +1, 45944, 45944, 1024, 8192, 0x00000000 0, 23, 23, 1, 1378560, 0x8955570e -1, 46968, 46968, 1024, 8192, 0x172867ad -1, 47976, 47976, 1024, 8192, 0xcbcc1461 +1, 46968, 46968, 1024, 8192, 0x00000000 +1, 47976, 47976, 1024, 8192, 0x00000000 0, 24, 24, 1, 1378560, 0x9c598000 1, 49968, 49968, 1024, 8192, 0x00000000 0, 25, 25, 1, 1378560, 0xbaf121ba @@ -87,33 +87,33 @@ 1, 53032, 53032, 1024, 8192, 0x00000000 0, 27, 27, 1, 1378560, 0x6579d31a 1, 54056, 54056, 1024, 8192, 0x00000000 -1, 55080, 55080, 1024, 8192, 0x687330d2 +1, 55080, 55080, 1024, 8192, 0x00000000 0, 28, 28, 1, 1378560, 0xca1deba8 -1, 56088, 56088, 1024, 8192, 0x9131462c -1, 57168, 57168, 1024, 8192, 0x48c01c32 +1, 56088, 56088, 1024, 8192, 0x00000000 +1, 57168, 57168, 1024, 8192, 0x00000000 0, 29, 29, 1, 1378560, 0xd4eed467 -1, 58192, 58192, 1024, 8192, 0x0ccd8d5f -1, 59208, 59208, 1024, 8192, 0xd50cbe9f +1, 58192, 58192, 1024, 8192, 0x00000000 +1, 59208, 59208, 1024, 8192, 0x00000000 0, 30, 30, 1, 1378560, 0xd6e1d5b7 -1, 60216, 60216, 1024, 8192, 0xbe069303 -1, 61240, 61240, 1024, 8192, 0x85fccf5b +1, 60216, 60216, 1024, 8192, 0x00000000 +1, 61240, 61240, 1024, 8192, 0x00000000 0, 31, 31, 1, 1378560, 0x0b574d39 -1, 62264, 62264, 1024, 8192, 0x4180de71 -1, 63288, 63288, 1024, 8192, 0x0e9b6ac3 +1, 62264, 62264, 1024, 8192, 0x00000000 +1, 63288, 63288, 1024, 8192, 0x00000000 0, 32, 32, 1, 1378560, 0x1bdd4d61 -1, 64296, 64296, 1024, 8192, 0x5c33f724 -1, 65320, 65320, 1024, 8192, 0x668aaaec +1, 64296, 64296, 1024, 8192, 0x00000000 +1, 65320, 65320, 1024, 8192, 0x00000000 0, 33, 33, 1, 1378560, 0x3b28f549 -1, 66344, 66344, 1024, 8192, 0xd137d412 -1, 67368, 67368, 1024, 8192, 0x08e1fbf6 +1, 66344, 66344, 1024, 8192, 0x00000000 +1, 67368, 67368, 1024, 8192, 0x00000000 0, 34, 34, 1, 1378560, 0x45b2f57b -1, 68376, 68376, 1024, 8192, 0xbf3fb4f6 -1, 69400, 69400, 1024, 8192, 0x69cd08a4 +1, 68376, 68376, 1024, 8192, 0x00000000 +1, 69400, 69400, 1024, 8192, 0x00000000 0, 35, 35, 1, 1378560, 0x8955570e -1, 70424, 70424, 1024, 8192, 0xe0fe6297 -1, 71448, 71448, 1024, 8192, 0x172867ad +1, 70424, 70424, 1024, 8192, 0x00000000 +1, 71448, 71448, 1024, 8192, 0x00000000 0, 36, 36, 1, 1378560, 0x9c598000 -1, 72456, 72456, 1024, 8192, 0xcbcc1461 +1, 72456, 72456, 1024, 8192, 0x00000000 0, 37, 37, 1, 1378560, 0xbaf121ba 1, 74448, 74448, 1024, 8192, 0x00000000 1, 75472, 75472, 1024, 8192, 0x00000000 @@ -122,30 +122,30 @@ 1, 77512, 77512, 1024, 8192, 0x00000000 0, 39, 39, 1, 1378560, 0x6579d31a 1, 78536, 78536, 1024, 8192, 0x00000000 -1, 79560, 79560, 1024, 8192, 0x687330d2 +1, 79560, 79560, 1024, 8192, 0x00000000 0, 40, 40, 1, 1378560, 0xca1deba8 -1, 80568, 80568, 1024, 8192, 0x9131462c -1, 81648, 81648, 1024, 8192, 0x48c01c32 +1, 80568, 80568, 1024, 8192, 0x00000000 +1, 81648, 81648, 1024, 8192, 0x00000000 0, 41, 41, 1, 1378560, 0xd4eed467 -1, 82672, 82672, 1024, 8192, 0x0ccd8d5f -1, 83688, 83688, 1024, 8192, 0xd50cbe9f +1, 82672, 82672, 1024, 8192, 0x00000000 +1, 83688, 83688, 1024, 8192, 0x00000000 0, 42, 42, 1, 1378560, 0xd6e1d5b7 -1, 84696, 84696, 1024, 8192, 0xbe069303 -1, 85720, 85720, 1024, 8192, 0x85fccf5b +1, 84696, 84696, 1024, 8192, 0x00000000 +1, 85720, 85720, 1024, 8192, 0x00000000 0, 43, 43, 1, 1378560, 0x0b574d39 -1, 86744, 86744, 1024, 8192, 0x4180de71 -1, 87768, 87768, 1024, 8192, 0x0e9b6ac3 +1, 86744, 86744, 1024, 8192, 0x00000000 +1, 87768, 87768, 1024, 8192, 0x00000000 0, 44, 44, 1, 1378560, 0x1bdd4d61 -1, 88776, 88776, 1024, 8192, 0x5c33f724 -1, 89800, 89800, 1024, 8192, 0x668aaaec +1, 88776, 88776, 1024, 8192, 0x00000000 +1, 89800, 89800, 1024, 8192, 0x00000000 0, 45, 45, 1, 1378560, 0x3b28f549 -1, 90824, 90824, 1024, 8192, 0xd137d412 -1, 91848, 91848, 1024, 8192, 0x08e1fbf6 +1, 90824, 90824, 1024, 8192, 0x00000000 +1, 91848, 91848, 1024, 8192, 0x00000000 0, 46, 46, 1, 1378560, 0x45b2f57b -1, 92856, 92856, 1024, 8192, 0xbf3fb4f6 -1, 93880, 93880, 1024, 8192, 0x69cd08a4 +1, 92856, 92856, 1024, 8192, 0x00000000 +1, 93880, 93880, 1024, 8192, 0x00000000 0, 47, 47, 1, 1378560, 0x8955570e -1, 94904, 94904, 1024, 8192, 0xe0fe6297 -1, 95928, 95928, 1024, 8192, 0x172867ad -1, 96936, 96936, 1024, 8192, 0xcbcc1461 +1, 94904, 94904, 1024, 8192, 0x00000000 +1, 95928, 95928, 1024, 8192, 0x00000000 +1, 96936, 96936, 1024, 8192, 0x00000000 0, 49, 49, 1, 1378560, 0x9c598000 From 2276bcc52acf224da38eadb8068a8535260678e0 Mon Sep 17 00:00:00 2001 From: James Almer Date: Mon, 19 Jun 2023 23:25:43 -0300 Subject: [PATCH 1634/2172] avformat/evcdec: ensure there are enough bytes to seekback Signed-off-by: James Almer --- libavformat/evcdec.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/libavformat/evcdec.c b/libavformat/evcdec.c index 890babd3cb0..9c4969e78fe 100644 --- a/libavformat/evcdec.c +++ b/libavformat/evcdec.c @@ -30,6 +30,7 @@ #include "rawdec.h" #include "avformat.h" +#include "avio_internal.h" #include "internal.h" @@ -192,8 +193,12 @@ static int evc_read_packet(AVFormatContext *s, AVPacket *pkt) } while(!au_end_found) { - uint8_t buf[EVC_NALU_LENGTH_PREFIX_SIZE]; + + ret = ffio_ensure_seekback(s->pb, EVC_NALU_LENGTH_PREFIX_SIZE); + if (ret < 0) + return ret; + ret = avio_read(s->pb, (unsigned char *)&buf, EVC_NALU_LENGTH_PREFIX_SIZE); if (ret < 0) { av_packet_unref(pkt); From 43ace56c7e79aa94aa5437911e4a3424821d7ab6 Mon Sep 17 00:00:00 2001 From: James Almer Date: Mon, 19 Jun 2023 23:35:37 -0300 Subject: [PATCH 1635/2172] avformat/evcdec: remove unnecessary av_packet_unref() calls And return proper error codes. Signed-off-by: James Almer --- libavformat/evcdec.c | 17 +++++------------ 1 file changed, 5 insertions(+), 12 deletions(-) diff --git a/libavformat/evcdec.c b/libavformat/evcdec.c index 9c4969e78fe..68f3a91e532 100644 --- a/libavformat/evcdec.c +++ b/libavformat/evcdec.c @@ -186,11 +186,8 @@ static int evc_read_packet(AVFormatContext *s, AVPacket *pkt) EVCDemuxContext *const c = s->priv_data; - int eof = avio_feof (s->pb); - if(eof) { - av_packet_unref(pkt); + if (avio_feof(s->pb)) return AVERROR_EOF; - } while(!au_end_found) { uint8_t buf[EVC_NALU_LENGTH_PREFIX_SIZE]; @@ -200,16 +197,12 @@ static int evc_read_packet(AVFormatContext *s, AVPacket *pkt) return ret; ret = avio_read(s->pb, (unsigned char *)&buf, EVC_NALU_LENGTH_PREFIX_SIZE); - if (ret < 0) { - av_packet_unref(pkt); + if (ret < 0) return ret; - } nalu_size = read_nal_unit_length((const uint8_t *)&buf, EVC_NALU_LENGTH_PREFIX_SIZE); - if(nalu_size <= 0) { - av_packet_unref(pkt); - return -1; - } + if (nalu_size <= 0) + return AVERROR_INVALIDDATA; avio_seek(s->pb, -EVC_NALU_LENGTH_PREFIX_SIZE, SEEK_CUR); @@ -217,7 +210,7 @@ static int evc_read_packet(AVFormatContext *s, AVPacket *pkt) if (ret < 0) return ret; if (ret != (nalu_size + EVC_NALU_LENGTH_PREFIX_SIZE)) - return AVERROR(EIO); + return AVERROR_INVALIDDATA; ret = av_bsf_send_packet(c->bsf, pkt); if (ret < 0) { From a6a5e5359573aab7a0dd19045ceafe5149dffd87 Mon Sep 17 00:00:00 2001 From: James Almer Date: Mon, 19 Jun 2023 23:42:04 -0300 Subject: [PATCH 1636/2172] avformat/evcdec: flush the bsf on EOF Signed-off-by: James Almer --- libavformat/evcdec.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/libavformat/evcdec.c b/libavformat/evcdec.c index 68f3a91e532..842258d2298 100644 --- a/libavformat/evcdec.c +++ b/libavformat/evcdec.c @@ -183,15 +183,14 @@ static int evc_read_packet(AVFormatContext *s, AVPacket *pkt) int ret; int32_t nalu_size; int au_end_found = 0; - EVCDemuxContext *const c = s->priv_data; - if (avio_feof(s->pb)) - return AVERROR_EOF; - while(!au_end_found) { uint8_t buf[EVC_NALU_LENGTH_PREFIX_SIZE]; + if (avio_feof(s->pb)) + goto end; + ret = ffio_ensure_seekback(s->pb, EVC_NALU_LENGTH_PREFIX_SIZE); if (ret < 0) return ret; @@ -212,6 +211,7 @@ static int evc_read_packet(AVFormatContext *s, AVPacket *pkt) if (ret != (nalu_size + EVC_NALU_LENGTH_PREFIX_SIZE)) return AVERROR_INVALIDDATA; +end: ret = av_bsf_send_packet(c->bsf, pkt); if (ret < 0) { av_log(s, AV_LOG_ERROR, "Failed to send packet to " From d0d20f16ce4de0d814b7dac28fa18c666b7a8a85 Mon Sep 17 00:00:00 2001 From: James Almer Date: Mon, 19 Jun 2023 23:47:07 -0300 Subject: [PATCH 1637/2172] avformat/evcdec: use an unsigned type for nalu_size But ensure the value returned by evc_read_nal_unit_length() fits in an int. Should prevent integer overflows later in the code. Signed-off-by: James Almer --- libavformat/evcdec.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libavformat/evcdec.c b/libavformat/evcdec.c index 842258d2298..ef743028ae1 100644 --- a/libavformat/evcdec.c +++ b/libavformat/evcdec.c @@ -181,7 +181,7 @@ static int evc_read_header(AVFormatContext *s) static int evc_read_packet(AVFormatContext *s, AVPacket *pkt) { int ret; - int32_t nalu_size; + uint32_t nalu_size; int au_end_found = 0; EVCDemuxContext *const c = s->priv_data; @@ -200,7 +200,7 @@ static int evc_read_packet(AVFormatContext *s, AVPacket *pkt) return ret; nalu_size = read_nal_unit_length((const uint8_t *)&buf, EVC_NALU_LENGTH_PREFIX_SIZE); - if (nalu_size <= 0) + if (!nalu_size || nalu_size > INT_MAX) return AVERROR_INVALIDDATA; avio_seek(s->pb, -EVC_NALU_LENGTH_PREFIX_SIZE, SEEK_CUR); From 2212808a72e6a9789836cfc4e9ed89f45291595e Mon Sep 17 00:00:00 2001 From: James Almer Date: Tue, 20 Jun 2023 10:40:58 -0300 Subject: [PATCH 1638/2172] avcodec/evc_ps: pass a GetBitContext to the SPS and PPS parsing functions This is in preparation for the following patch. Signed-off-by: James Almer --- libavcodec/evc_frame_merge_bsf.c | 11 +- libavcodec/evc_parser.c | 11 +- libavcodec/evc_ps.c | 186 +++++++++++++++---------------- libavcodec/evc_ps.h | 5 +- 4 files changed, 109 insertions(+), 104 deletions(-) diff --git a/libavcodec/evc_frame_merge_bsf.c b/libavcodec/evc_frame_merge_bsf.c index 8e7ce9a2ab9..bd30a09b156 100644 --- a/libavcodec/evc_frame_merge_bsf.c +++ b/libavcodec/evc_frame_merge_bsf.c @@ -75,6 +75,7 @@ static int evc_frame_merge_filter(AVBSFContext *bsf, AVPacket *out) EVCFMergeContext *ctx = bsf->priv_data; AVPacket *in = ctx->in; uint8_t *buffer, *nalu = NULL; + GetBitContext gb; enum EVCNALUnitType nalu_type; int tid, nalu_size = 0; int au_end_found = 0; @@ -121,14 +122,20 @@ static int evc_frame_merge_filter(AVBSFContext *bsf, AVPacket *out) switch (nalu_type) { case EVC_SPS_NUT: - err = ff_evc_parse_sps(&ctx->ps, nalu, nalu_size); + err = init_get_bits8(&gb, nalu, nalu_size); + if (err < 0) + return err; + err = ff_evc_parse_sps(&gb, &ctx->ps); if (err < 0) { av_log(bsf, AV_LOG_ERROR, "SPS parsing error\n"); goto end; } break; case EVC_PPS_NUT: - err = ff_evc_parse_pps(&ctx->ps, nalu, nalu_size); + err = init_get_bits8(&gb, nalu, nalu_size); + if (err < 0) + return err; + err = ff_evc_parse_pps(&gb, &ctx->ps); if (err < 0) { av_log(bsf, AV_LOG_ERROR, "PPS parsing error\n"); goto end; diff --git a/libavcodec/evc_parser.c b/libavcodec/evc_parser.c index 5c8fcc5970f..8dd6b5fda72 100644 --- a/libavcodec/evc_parser.c +++ b/libavcodec/evc_parser.c @@ -62,6 +62,7 @@ static int parse_nal_unit(AVCodecParserContext *s, AVCodecContext *avctx, const uint8_t *buf, int buf_size) { EVCParserContext *ctx = s->priv_data; + GetBitContext gb; int nalu_type, tid; int ret; @@ -89,14 +90,20 @@ static int parse_nal_unit(AVCodecParserContext *s, AVCodecContext *avctx, switch (nalu_type) { case EVC_SPS_NUT: - ret = ff_evc_parse_sps(&ctx->ps, buf, buf_size); + ret = init_get_bits8(&gb, buf, buf_size); + if (ret < 0) + return ret; + ret = ff_evc_parse_sps(&gb, &ctx->ps); if (ret < 0) { av_log(avctx, AV_LOG_ERROR, "SPS parsing error\n"); return ret; } break; case EVC_PPS_NUT: - ret = ff_evc_parse_pps(&ctx->ps, buf, buf_size); + ret = init_get_bits8(&gb, buf, buf_size); + if (ret < 0) + return ret; + ret = ff_evc_parse_pps(&gb, &ctx->ps); if (ret < 0) { av_log(avctx, AV_LOG_ERROR, "PPS parsing error\n"); return ret; diff --git a/libavcodec/evc_ps.c b/libavcodec/evc_ps.c index ed39af104e8..156f76554a0 100644 --- a/libavcodec/evc_ps.c +++ b/libavcodec/evc_ps.c @@ -132,18 +132,13 @@ static int vui_parameters(GetBitContext *gb, VUIParameters *vui) } // @see ISO_IEC_23094-1 (7.3.2.1 SPS RBSP syntax) -int ff_evc_parse_sps(EVCParamSets *ps, const uint8_t *bs, int bs_size) +int ff_evc_parse_sps(GetBitContext *gb, EVCParamSets *ps) { - GetBitContext gb; EVCParserSPS *sps; int sps_seq_parameter_set_id; int ret; - ret = init_get_bits8(&gb, bs, bs_size); - if (ret < 0) - return ret; - - sps_seq_parameter_set_id = get_ue_golomb(&gb); + sps_seq_parameter_set_id = get_ue_golomb(gb); if (sps_seq_parameter_set_id >= EVC_MAX_SPS_COUNT) return AVERROR_INVALIDDATA; @@ -158,74 +153,74 @@ int ff_evc_parse_sps(EVCParamSets *ps, const uint8_t *bs, int bs_size) // the Baseline profile is indicated by profile_idc eqal to 0 // the Main profile is indicated by profile_idc eqal to 1 - sps->profile_idc = get_bits(&gb, 8); + sps->profile_idc = get_bits(gb, 8); - sps->level_idc = get_bits(&gb, 8); + sps->level_idc = get_bits(gb, 8); - skip_bits_long(&gb, 32); /* skip toolset_idc_h */ - skip_bits_long(&gb, 32); /* skip toolset_idc_l */ + skip_bits_long(gb, 32); /* skip toolset_idc_h */ + skip_bits_long(gb, 32); /* skip toolset_idc_l */ // 0 - monochrome // 1 - 4:2:0 // 2 - 4:2:2 // 3 - 4:4:4 - sps->chroma_format_idc = get_ue_golomb(&gb); + sps->chroma_format_idc = get_ue_golomb(gb); - sps->pic_width_in_luma_samples = get_ue_golomb(&gb); - sps->pic_height_in_luma_samples = get_ue_golomb(&gb); + sps->pic_width_in_luma_samples = get_ue_golomb(gb); + sps->pic_height_in_luma_samples = get_ue_golomb(gb); - sps->bit_depth_luma_minus8 = get_ue_golomb(&gb); - sps->bit_depth_chroma_minus8 = get_ue_golomb(&gb); + sps->bit_depth_luma_minus8 = get_ue_golomb(gb); + sps->bit_depth_chroma_minus8 = get_ue_golomb(gb); - sps->sps_btt_flag = get_bits1(&gb); + sps->sps_btt_flag = get_bits1(gb); if (sps->sps_btt_flag) { - sps->log2_ctu_size_minus5 = get_ue_golomb(&gb); - sps->log2_min_cb_size_minus2 = get_ue_golomb(&gb); - sps->log2_diff_ctu_max_14_cb_size = get_ue_golomb(&gb); - sps->log2_diff_ctu_max_tt_cb_size = get_ue_golomb(&gb); - sps->log2_diff_min_cb_min_tt_cb_size_minus2 = get_ue_golomb(&gb); + sps->log2_ctu_size_minus5 = get_ue_golomb(gb); + sps->log2_min_cb_size_minus2 = get_ue_golomb(gb); + sps->log2_diff_ctu_max_14_cb_size = get_ue_golomb(gb); + sps->log2_diff_ctu_max_tt_cb_size = get_ue_golomb(gb); + sps->log2_diff_min_cb_min_tt_cb_size_minus2 = get_ue_golomb(gb); } - sps->sps_suco_flag = get_bits1(&gb); + sps->sps_suco_flag = get_bits1(gb); if (sps->sps_suco_flag) { - sps->log2_diff_ctu_size_max_suco_cb_size = get_ue_golomb(&gb); - sps->log2_diff_max_suco_min_suco_cb_size = get_ue_golomb(&gb); + sps->log2_diff_ctu_size_max_suco_cb_size = get_ue_golomb(gb); + sps->log2_diff_max_suco_min_suco_cb_size = get_ue_golomb(gb); } - sps->sps_admvp_flag = get_bits1(&gb); + sps->sps_admvp_flag = get_bits1(gb); if (sps->sps_admvp_flag) { - sps->sps_affine_flag = get_bits1(&gb); - sps->sps_amvr_flag = get_bits1(&gb); - sps->sps_dmvr_flag = get_bits1(&gb); - sps->sps_mmvd_flag = get_bits1(&gb); - sps->sps_hmvp_flag = get_bits1(&gb); + sps->sps_affine_flag = get_bits1(gb); + sps->sps_amvr_flag = get_bits1(gb); + sps->sps_dmvr_flag = get_bits1(gb); + sps->sps_mmvd_flag = get_bits1(gb); + sps->sps_hmvp_flag = get_bits1(gb); } - sps->sps_eipd_flag = get_bits1(&gb); + sps->sps_eipd_flag = get_bits1(gb); if (sps->sps_eipd_flag) { - sps->sps_ibc_flag = get_bits1(&gb); + sps->sps_ibc_flag = get_bits1(gb); if (sps->sps_ibc_flag) - sps->log2_max_ibc_cand_size_minus2 = get_ue_golomb(&gb); + sps->log2_max_ibc_cand_size_minus2 = get_ue_golomb(gb); } - sps->sps_cm_init_flag = get_bits1(&gb); + sps->sps_cm_init_flag = get_bits1(gb); if (sps->sps_cm_init_flag) - sps->sps_adcc_flag = get_bits1(&gb); + sps->sps_adcc_flag = get_bits1(gb); - sps->sps_iqt_flag = get_bits1(&gb); + sps->sps_iqt_flag = get_bits1(gb); if (sps->sps_iqt_flag) - sps->sps_ats_flag = get_bits1(&gb); + sps->sps_ats_flag = get_bits1(gb); - sps->sps_addb_flag = get_bits1(&gb); - sps->sps_alf_flag = get_bits1(&gb); - sps->sps_htdf_flag = get_bits1(&gb); - sps->sps_rpl_flag = get_bits1(&gb); - sps->sps_pocs_flag = get_bits1(&gb); - sps->sps_dquant_flag = get_bits1(&gb); - sps->sps_dra_flag = get_bits1(&gb); + sps->sps_addb_flag = get_bits1(gb); + sps->sps_alf_flag = get_bits1(gb); + sps->sps_htdf_flag = get_bits1(gb); + sps->sps_rpl_flag = get_bits1(gb); + sps->sps_pocs_flag = get_bits1(gb); + sps->sps_dquant_flag = get_bits1(gb); + sps->sps_dra_flag = get_bits1(gb); if (sps->sps_pocs_flag) { - sps->log2_max_pic_order_cnt_lsb_minus4 = get_ue_golomb(&gb); + sps->log2_max_pic_order_cnt_lsb_minus4 = get_ue_golomb(gb); if (sps->log2_max_pic_order_cnt_lsb_minus4 > 12U) { ret = AVERROR_INVALIDDATA; goto fail; @@ -233,65 +228,65 @@ int ff_evc_parse_sps(EVCParamSets *ps, const uint8_t *bs, int bs_size) } if (!sps->sps_pocs_flag || !sps->sps_rpl_flag) { - sps->log2_sub_gop_length = get_ue_golomb(&gb); + sps->log2_sub_gop_length = get_ue_golomb(gb); if (sps->log2_sub_gop_length > 5U) { ret = AVERROR_INVALIDDATA; goto fail; } if (sps->log2_sub_gop_length == 0) - sps->log2_ref_pic_gap_length = get_ue_golomb(&gb); + sps->log2_ref_pic_gap_length = get_ue_golomb(gb); } if (!sps->sps_rpl_flag) - sps->max_num_tid0_ref_pics = get_ue_golomb(&gb); + sps->max_num_tid0_ref_pics = get_ue_golomb(gb); else { - sps->sps_max_dec_pic_buffering_minus1 = get_ue_golomb(&gb); - sps->long_term_ref_pic_flag = get_bits1(&gb); - sps->rpl1_same_as_rpl0_flag = get_bits1(&gb); - sps->num_ref_pic_list_in_sps[0] = get_ue_golomb(&gb); + sps->sps_max_dec_pic_buffering_minus1 = get_ue_golomb(gb); + sps->long_term_ref_pic_flag = get_bits1(gb); + sps->rpl1_same_as_rpl0_flag = get_bits1(gb); + sps->num_ref_pic_list_in_sps[0] = get_ue_golomb(gb); for (int i = 0; i < sps->num_ref_pic_list_in_sps[0]; ++i) - ref_pic_list_struct(&gb, &sps->rpls[0][i]); + ref_pic_list_struct(gb, &sps->rpls[0][i]); if (!sps->rpl1_same_as_rpl0_flag) { - sps->num_ref_pic_list_in_sps[1] = get_ue_golomb(&gb); + sps->num_ref_pic_list_in_sps[1] = get_ue_golomb(gb); for (int i = 0; i < sps->num_ref_pic_list_in_sps[1]; ++i) - ref_pic_list_struct(&gb, &sps->rpls[1][i]); + ref_pic_list_struct(gb, &sps->rpls[1][i]); } } - sps->picture_cropping_flag = get_bits1(&gb); + sps->picture_cropping_flag = get_bits1(gb); if (sps->picture_cropping_flag) { - sps->picture_crop_left_offset = get_ue_golomb(&gb); - sps->picture_crop_right_offset = get_ue_golomb(&gb); - sps->picture_crop_top_offset = get_ue_golomb(&gb); - sps->picture_crop_bottom_offset = get_ue_golomb(&gb); + sps->picture_crop_left_offset = get_ue_golomb(gb); + sps->picture_crop_right_offset = get_ue_golomb(gb); + sps->picture_crop_top_offset = get_ue_golomb(gb); + sps->picture_crop_bottom_offset = get_ue_golomb(gb); } if (sps->chroma_format_idc != 0) { - sps->chroma_qp_table_struct.chroma_qp_table_present_flag = get_bits1(&gb); + sps->chroma_qp_table_struct.chroma_qp_table_present_flag = get_bits1(gb); if (sps->chroma_qp_table_struct.chroma_qp_table_present_flag) { - sps->chroma_qp_table_struct.same_qp_table_for_chroma = get_bits1(&gb); - sps->chroma_qp_table_struct.global_offset_flag = get_bits1(&gb); + sps->chroma_qp_table_struct.same_qp_table_for_chroma = get_bits1(gb); + sps->chroma_qp_table_struct.global_offset_flag = get_bits1(gb); for (int i = 0; i < (sps->chroma_qp_table_struct.same_qp_table_for_chroma ? 1 : 2); i++) { - sps->chroma_qp_table_struct.num_points_in_qp_table_minus1[i] = get_ue_golomb(&gb); + sps->chroma_qp_table_struct.num_points_in_qp_table_minus1[i] = get_ue_golomb(gb); if (sps->chroma_qp_table_struct.num_points_in_qp_table_minus1[i] >= EVC_MAX_QP_TABLE_SIZE) { ret = AVERROR_INVALIDDATA; goto fail; } for (int j = 0; j <= sps->chroma_qp_table_struct.num_points_in_qp_table_minus1[i]; j++) { - sps->chroma_qp_table_struct.delta_qp_in_val_minus1[i][j] = get_bits(&gb, 6); - sps->chroma_qp_table_struct.delta_qp_out_val[i][j] = get_se_golomb(&gb); + sps->chroma_qp_table_struct.delta_qp_in_val_minus1[i][j] = get_bits(gb, 6); + sps->chroma_qp_table_struct.delta_qp_out_val[i][j] = get_se_golomb(gb); } } } } - sps->vui_parameters_present_flag = get_bits1(&gb); + sps->vui_parameters_present_flag = get_bits1(gb); if (sps->vui_parameters_present_flag) - vui_parameters(&gb, &(sps->vui_parameters)); + vui_parameters(gb, &(sps->vui_parameters)); // @note // If necessary, add the missing fields to the EVCParserSPS structure @@ -313,18 +308,13 @@ int ff_evc_parse_sps(EVCParamSets *ps, const uint8_t *bs, int bs_size) // If it will be needed, parse_sps function could be extended to handle VUI parameters parsing // to initialize fields of the AVCodecContex i.e. color_primaries, color_trc,color_range // -int ff_evc_parse_pps(EVCParamSets *ps, const uint8_t *bs, int bs_size) +int ff_evc_parse_pps(GetBitContext *gb, EVCParamSets *ps) { - GetBitContext gb; EVCParserPPS *pps; int pps_pic_parameter_set_id; int ret; - ret = init_get_bits8(&gb, bs, bs_size); - if (ret < 0) - return ret; - - pps_pic_parameter_set_id = get_ue_golomb(&gb); + pps_pic_parameter_set_id = get_ue_golomb(gb); if (pps_pic_parameter_set_id > EVC_MAX_PPS_COUNT) return AVERROR_INVALIDDATA; @@ -336,65 +326,65 @@ int ff_evc_parse_pps(EVCParamSets *ps, const uint8_t *bs, int bs_size) pps->pps_pic_parameter_set_id = pps_pic_parameter_set_id; - pps->pps_seq_parameter_set_id = get_ue_golomb(&gb); + pps->pps_seq_parameter_set_id = get_ue_golomb(gb); if (pps->pps_seq_parameter_set_id >= EVC_MAX_SPS_COUNT) { ret = AVERROR_INVALIDDATA; goto fail; } - pps->num_ref_idx_default_active_minus1[0] = get_ue_golomb(&gb); - pps->num_ref_idx_default_active_minus1[1] = get_ue_golomb(&gb); - pps->additional_lt_poc_lsb_len = get_ue_golomb(&gb); - pps->rpl1_idx_present_flag = get_bits1(&gb); - pps->single_tile_in_pic_flag = get_bits1(&gb); + pps->num_ref_idx_default_active_minus1[0] = get_ue_golomb(gb); + pps->num_ref_idx_default_active_minus1[1] = get_ue_golomb(gb); + pps->additional_lt_poc_lsb_len = get_ue_golomb(gb); + pps->rpl1_idx_present_flag = get_bits1(gb); + pps->single_tile_in_pic_flag = get_bits1(gb); if (!pps->single_tile_in_pic_flag) { - pps->num_tile_columns_minus1 = get_ue_golomb(&gb); - pps->num_tile_rows_minus1 = get_ue_golomb(&gb); + pps->num_tile_columns_minus1 = get_ue_golomb(gb); + pps->num_tile_rows_minus1 = get_ue_golomb(gb); if (pps->num_tile_columns_minus1 >= EVC_MAX_TILE_COLUMNS || pps->num_tile_rows_minus1 >= EVC_MAX_TILE_ROWS) { ret = AVERROR_INVALIDDATA; goto fail; } - pps->uniform_tile_spacing_flag = get_bits1(&gb); + pps->uniform_tile_spacing_flag = get_bits1(gb); if (!pps->uniform_tile_spacing_flag) { for (int i = 0; i < pps->num_tile_columns_minus1; i++) - pps->tile_column_width_minus1[i] = get_ue_golomb(&gb); + pps->tile_column_width_minus1[i] = get_ue_golomb(gb); for (int i = 0; i < pps->num_tile_rows_minus1; i++) - pps->tile_row_height_minus1[i] = get_ue_golomb(&gb); + pps->tile_row_height_minus1[i] = get_ue_golomb(gb); } - pps->loop_filter_across_tiles_enabled_flag = get_bits1(&gb); - pps->tile_offset_len_minus1 = get_ue_golomb(&gb); + pps->loop_filter_across_tiles_enabled_flag = get_bits1(gb); + pps->tile_offset_len_minus1 = get_ue_golomb(gb); } - pps->tile_id_len_minus1 = get_ue_golomb(&gb); + pps->tile_id_len_minus1 = get_ue_golomb(gb); if (pps->tile_id_len_minus1 > 15U) { ret = AVERROR_INVALIDDATA; goto fail; } - pps->explicit_tile_id_flag = get_bits1(&gb); + pps->explicit_tile_id_flag = get_bits1(gb); if (pps->explicit_tile_id_flag) { for (int i = 0; i <= pps->num_tile_rows_minus1; i++) { for (int j = 0; j <= pps->num_tile_columns_minus1; j++) - pps->tile_id_val[i][j] = get_bits(&gb, pps->tile_id_len_minus1 + 1); + pps->tile_id_val[i][j] = get_bits(gb, pps->tile_id_len_minus1 + 1); } } pps->pic_dra_enabled_flag = 0; - pps->pic_dra_enabled_flag = get_bits1(&gb); + pps->pic_dra_enabled_flag = get_bits1(gb); if (pps->pic_dra_enabled_flag) - pps->pic_dra_aps_id = get_bits(&gb, 5); + pps->pic_dra_aps_id = get_bits(gb, 5); - pps->arbitrary_slice_present_flag = get_bits1(&gb); - pps->constrained_intra_pred_flag = get_bits1(&gb); - pps->cu_qp_delta_enabled_flag = get_bits1(&gb); + pps->arbitrary_slice_present_flag = get_bits1(gb); + pps->constrained_intra_pred_flag = get_bits1(gb); + pps->cu_qp_delta_enabled_flag = get_bits1(gb); if (pps->cu_qp_delta_enabled_flag) - pps->log2_cu_qp_delta_area_minus6 = get_ue_golomb(&gb); + pps->log2_cu_qp_delta_area_minus6 = get_ue_golomb(gb); av_freep(&ps->pps[pps_pic_parameter_set_id]); ps->pps[pps_pic_parameter_set_id] = pps; diff --git a/libavcodec/evc_ps.h b/libavcodec/evc_ps.h index c7ed2af37b3..5aaa30de207 100644 --- a/libavcodec/evc_ps.h +++ b/libavcodec/evc_ps.h @@ -27,6 +27,7 @@ #include #include "evc.h" +#include "get_bits.h" #define EVC_MAX_QP_TABLE_SIZE 58 #define NUM_CPB 32 @@ -218,10 +219,10 @@ typedef struct EVCParamSets { } EVCParamSets; // @see ISO_IEC_23094-1 (7.3.2.1 SPS RBSP syntax) -int ff_evc_parse_sps(EVCParamSets *ps, const uint8_t *bs, int bs_size); +int ff_evc_parse_sps(GetBitContext *gb, EVCParamSets *ps); // @see ISO_IEC_23094-1 (7.3.2.2 SPS RBSP syntax) -int ff_evc_parse_pps(EVCParamSets *ps, const uint8_t *bs, int bs_size); +int ff_evc_parse_pps(GetBitContext *gb, EVCParamSets *ps); void ff_evc_ps_free(EVCParamSets *ps); From e5da2ec456d6ef8e6b68da431a190d7edc1b52ff Mon Sep 17 00:00:00 2001 From: James Almer Date: Tue, 20 Jun 2023 11:05:38 -0300 Subject: [PATCH 1639/2172] avcodec/evc_parse: pass a GetBitContext to the slice header parsing function Signed-off-by: James Almer --- libavcodec/evc_frame_merge_bsf.c | 6 +++- libavcodec/evc_parse.c | 52 ++++++++++++++------------------ libavcodec/evc_parse.h | 4 +-- libavcodec/evc_parser.c | 6 +++- 4 files changed, 35 insertions(+), 33 deletions(-) diff --git a/libavcodec/evc_frame_merge_bsf.c b/libavcodec/evc_frame_merge_bsf.c index bd30a09b156..3904170ebd8 100644 --- a/libavcodec/evc_frame_merge_bsf.c +++ b/libavcodec/evc_frame_merge_bsf.c @@ -145,7 +145,11 @@ static int evc_frame_merge_filter(AVBSFContext *bsf, AVPacket *out) case EVC_NOIDR_NUT: { EVCParserSliceHeader sh; - err = ff_evc_parse_slice_header(&sh, &ctx->ps, nalu_type, nalu, nalu_size); + err = init_get_bits8(&gb, nalu, nalu_size); + if (err < 0) + return err; + + err = ff_evc_parse_slice_header(&gb, &sh, &ctx->ps, nalu_type); if (err < 0) { av_log(bsf, AV_LOG_ERROR, "Slice header parsing error\n"); goto end; diff --git a/libavcodec/evc_parse.c b/libavcodec/evc_parse.c index 0c35e40b476..dee48e947bd 100644 --- a/libavcodec/evc_parse.c +++ b/libavcodec/evc_parse.c @@ -44,21 +44,15 @@ int ff_evc_get_temporal_id(const uint8_t *bits, int bits_size, void *logctx) } // @see ISO_IEC_23094-1 (7.3.2.6 Slice layer RBSP syntax) -int ff_evc_parse_slice_header(EVCParserSliceHeader *sh, const EVCParamSets *ps, - enum EVCNALUnitType nalu_type, const uint8_t *bs, int bs_size) +int ff_evc_parse_slice_header(GetBitContext *gb, EVCParserSliceHeader *sh, + const EVCParamSets *ps, enum EVCNALUnitType nalu_type) { - GetBitContext gb; const EVCParserPPS *pps; const EVCParserSPS *sps; - int num_tiles_in_slice = 0; int slice_pic_parameter_set_id; - int ret; - - if ((ret = init_get_bits8(&gb, bs, bs_size)) < 0) - return ret; - slice_pic_parameter_set_id = get_ue_golomb(&gb); + slice_pic_parameter_set_id = get_ue_golomb(gb); if (slice_pic_parameter_set_id < 0 || slice_pic_parameter_set_id >= EVC_MAX_PPS_COUNT) return AVERROR_INVALIDDATA; @@ -75,47 +69,47 @@ int ff_evc_parse_slice_header(EVCParserSliceHeader *sh, const EVCParamSets *ps, sh->slice_pic_parameter_set_id = slice_pic_parameter_set_id; if (!pps->single_tile_in_pic_flag) { - sh->single_tile_in_slice_flag = get_bits1(&gb); - sh->first_tile_id = get_bits(&gb, pps->tile_id_len_minus1 + 1); + sh->single_tile_in_slice_flag = get_bits1(gb); + sh->first_tile_id = get_bits(gb, pps->tile_id_len_minus1 + 1); } else sh->single_tile_in_slice_flag = 1; if (!sh->single_tile_in_slice_flag) { if (pps->arbitrary_slice_present_flag) - sh->arbitrary_slice_flag = get_bits1(&gb); + sh->arbitrary_slice_flag = get_bits1(gb); if (!sh->arbitrary_slice_flag) - sh->last_tile_id = get_bits(&gb, pps->tile_id_len_minus1 + 1); + sh->last_tile_id = get_bits(gb, pps->tile_id_len_minus1 + 1); else { - sh->num_remaining_tiles_in_slice_minus1 = get_ue_golomb(&gb); + sh->num_remaining_tiles_in_slice_minus1 = get_ue_golomb(gb); num_tiles_in_slice = sh->num_remaining_tiles_in_slice_minus1 + 2; for (int i = 0; i < num_tiles_in_slice - 1; ++i) - sh->delta_tile_id_minus1[i] = get_ue_golomb(&gb); + sh->delta_tile_id_minus1[i] = get_ue_golomb(gb); } } - sh->slice_type = get_ue_golomb(&gb); + sh->slice_type = get_ue_golomb(gb); if (nalu_type == EVC_IDR_NUT) - sh->no_output_of_prior_pics_flag = get_bits1(&gb); + sh->no_output_of_prior_pics_flag = get_bits1(gb); if (sps->sps_mmvd_flag && ((sh->slice_type == EVC_SLICE_TYPE_B) || (sh->slice_type == EVC_SLICE_TYPE_P))) - sh->mmvd_group_enable_flag = get_bits1(&gb); + sh->mmvd_group_enable_flag = get_bits1(gb); else sh->mmvd_group_enable_flag = 0; if (sps->sps_alf_flag) { int ChromaArrayType = sps->chroma_format_idc; - sh->slice_alf_enabled_flag = get_bits1(&gb); + sh->slice_alf_enabled_flag = get_bits1(gb); if (sh->slice_alf_enabled_flag) { - sh->slice_alf_luma_aps_id = get_bits(&gb, 5); - sh->slice_alf_map_flag = get_bits1(&gb); - sh->slice_alf_chroma_idc = get_bits(&gb, 2); + sh->slice_alf_luma_aps_id = get_bits(gb, 5); + sh->slice_alf_map_flag = get_bits1(gb); + sh->slice_alf_chroma_idc = get_bits(gb, 2); if ((ChromaArrayType == 1 || ChromaArrayType == 2) && sh->slice_alf_chroma_idc > 0) - sh->slice_alf_chroma_aps_id = get_bits(&gb, 5); + sh->slice_alf_chroma_aps_id = get_bits(gb, 5); } if (ChromaArrayType == 3) { int sliceChromaAlfEnabledFlag = 0; @@ -136,23 +130,23 @@ int ff_evc_parse_slice_header(EVCParserSliceHeader *sh, const EVCParamSets *ps, } if (!sh->slice_alf_enabled_flag) - sh->slice_alf_chroma_idc = get_bits(&gb, 2); + sh->slice_alf_chroma_idc = get_bits(gb, 2); if (sliceChromaAlfEnabledFlag) { - sh->slice_alf_chroma_aps_id = get_bits(&gb, 5); - sh->slice_alf_chroma_map_flag = get_bits1(&gb); + sh->slice_alf_chroma_aps_id = get_bits(gb, 5); + sh->slice_alf_chroma_map_flag = get_bits1(gb); } if (sliceChroma2AlfEnabledFlag) { - sh->slice_alf_chroma2_aps_id = get_bits(&gb, 5); - sh->slice_alf_chroma2_map_flag = get_bits1(&gb); + sh->slice_alf_chroma2_aps_id = get_bits(gb, 5); + sh->slice_alf_chroma2_map_flag = get_bits1(gb); } } } if (nalu_type != EVC_IDR_NUT) { if (sps->sps_pocs_flag) - sh->slice_pic_order_cnt_lsb = get_bits(&gb, sps->log2_max_pic_order_cnt_lsb_minus4 + 4); + sh->slice_pic_order_cnt_lsb = get_bits(gb, sps->log2_max_pic_order_cnt_lsb_minus4 + 4); } // @note diff --git a/libavcodec/evc_parse.h b/libavcodec/evc_parse.h index a1fbbc643dc..322f52c9289 100644 --- a/libavcodec/evc_parse.h +++ b/libavcodec/evc_parse.h @@ -117,8 +117,8 @@ static inline uint32_t evc_read_nal_unit_length(const uint8_t *bits, int bits_si // nuh_temporal_id specifies a temporal identifier for the NAL unit int ff_evc_get_temporal_id(const uint8_t *bits, int bits_size, void *logctx); -int ff_evc_parse_slice_header(EVCParserSliceHeader *sh, const EVCParamSets *ps, - enum EVCNALUnitType nalu_type, const uint8_t *buf, int buf_size); +int ff_evc_parse_slice_header(GetBitContext *gb, EVCParserSliceHeader *sh, + const EVCParamSets *ps, enum EVCNALUnitType nalu_type); // POC (picture order count of the current picture) derivation // @see ISO/IEC 23094-1:2020(E) 8.3.1 Decoding process for picture order count diff --git a/libavcodec/evc_parser.c b/libavcodec/evc_parser.c index 8dd6b5fda72..ae399ef8cca 100644 --- a/libavcodec/evc_parser.c +++ b/libavcodec/evc_parser.c @@ -116,7 +116,11 @@ static int parse_nal_unit(AVCodecParserContext *s, AVCodecContext *avctx, EVCParserSliceHeader sh; int bit_depth; - ret = ff_evc_parse_slice_header(&sh, &ctx->ps, nalu_type, buf, buf_size); + ret = init_get_bits8(&gb, buf, buf_size); + if (ret < 0) + return ret; + + ret = ff_evc_parse_slice_header(&gb, &sh, &ctx->ps, nalu_type); if (ret < 0) { av_log(avctx, AV_LOG_ERROR, "Slice header parsing error\n"); return ret; From c7183a22dbc34d02016d92bd19b06a2e665861df Mon Sep 17 00:00:00 2001 From: James Almer Date: Tue, 20 Jun 2023 10:31:24 -0300 Subject: [PATCH 1640/2172] avformat/evc: move NALU length and type parsing functions to a header Signed-off-by: James Almer --- libavformat/evc.c | 5 ++--- libavformat/evc.h | 30 ++++++++++++++++++++++++++++++ libavformat/evcdec.c | 44 ++++---------------------------------------- 3 files changed, 36 insertions(+), 43 deletions(-) diff --git a/libavformat/evc.c b/libavformat/evc.c index 421ff84cb7c..f6e53aa6cf9 100644 --- a/libavformat/evc.c +++ b/libavformat/evc.c @@ -23,7 +23,6 @@ #include "libavcodec/get_bits.h" #include "libavcodec/golomb.h" #include "libavcodec/evc.h" -#include "libavcodec/evc_parse.h" #include "avformat.h" #include "avio.h" #include "evc.h" @@ -361,7 +360,7 @@ int ff_isom_write_evcc(AVIOContext *pb, const uint8_t *data, evcc_init(&evcc); while (bytes_to_read > EVC_NALU_LENGTH_PREFIX_SIZE) { - nalu_size = evc_read_nal_unit_length(data, EVC_NALU_LENGTH_PREFIX_SIZE, pb); + nalu_size = evc_read_nal_unit_length(data, EVC_NALU_LENGTH_PREFIX_SIZE); if (nalu_size == 0) break; data += EVC_NALU_LENGTH_PREFIX_SIZE; @@ -369,7 +368,7 @@ int ff_isom_write_evcc(AVIOContext *pb, const uint8_t *data, if (bytes_to_read < nalu_size) break; - nalu_type = evc_get_nalu_type(data, bytes_to_read, pb); + nalu_type = evc_get_nalu_type(data, bytes_to_read); if (nalu_type < EVC_NOIDR_NUT || nalu_type > EVC_UNSPEC_NUT62) { ret = AVERROR_INVALIDDATA; goto end; diff --git a/libavformat/evc.h b/libavformat/evc.h index db56275fd85..46b27f7df77 100644 --- a/libavformat/evc.h +++ b/libavformat/evc.h @@ -24,9 +24,39 @@ #include #include "libavutil/rational.h" +#include "libavcodec/evc.h" #include "avio.h" +static inline int evc_get_nalu_type(const uint8_t *bits, int bits_size) +{ + int unit_type_plus1 = 0; + if (bits_size >= EVC_NALU_HEADER_SIZE) { + unsigned char *p = (unsigned char *)bits; + // forbidden_zero_bit + if ((p[0] & 0x80) != 0) // Cannot get bitstream information. Malformed bitstream. + return -1; + + // nal_unit_type + unit_type_plus1 = (p[0] >> 1) & 0x3F; + } + + return unit_type_plus1 - 1; +} + +static inline uint32_t evc_read_nal_unit_length(const uint8_t *bits, int bits_size) +{ + uint32_t nalu_len = 0; + + if (bits_size >= EVC_NALU_LENGTH_PREFIX_SIZE) { + unsigned char *p = (unsigned char *)bits; + + for (int i = 0; i < EVC_NALU_LENGTH_PREFIX_SIZE; i++) + nalu_len = (nalu_len << 8) | p[i]; + } + + return nalu_len; +} /** * Writes EVC sample metadata to the provided AVIOContext. diff --git a/libavformat/evcdec.c b/libavformat/evcdec.c index ef743028ae1..73aab6c52f3 100644 --- a/libavformat/evcdec.c +++ b/libavformat/evcdec.c @@ -31,6 +31,7 @@ #include "rawdec.h" #include "avformat.h" #include "avio_internal.h" +#include "evc.h" #include "internal.h" @@ -59,43 +60,6 @@ static const AVClass evc_demuxer_class = { .version = LIBAVUTIL_VERSION_INT, }; -static int get_nalu_type(const uint8_t *bits, int bits_size) -{ - int unit_type_plus1 = 0; - - if (bits_size >= EVC_NALU_HEADER_SIZE) { - unsigned char *p = (unsigned char *)bits; - // forbidden_zero_bit - if ((p[0] & 0x80) != 0) // Cannot get bitstream information. Malformed bitstream. - return -1; - - // nal_unit_type - unit_type_plus1 = (p[0] >> 1) & 0x3F; - } - - return unit_type_plus1 - 1; -} - -static uint32_t read_nal_unit_length(const uint8_t *bits, int bits_size) -{ - uint32_t nalu_len = 0; - - if (bits_size >= EVC_NALU_LENGTH_PREFIX_SIZE) { - - int t = 0; - unsigned char *p = (unsigned char *)bits; - - for (int i = 0; i < EVC_NALU_LENGTH_PREFIX_SIZE; i++) - t = (t << 8) | p[i]; - - nalu_len = t; - if (nalu_len == 0) // Invalid bitstream size - return 0; - } - - return nalu_len; -} - static int annexb_probe(const AVProbeData *p) { int nalu_type; @@ -106,7 +70,7 @@ static int annexb_probe(const AVProbeData *p) while (bytes_to_read > EVC_NALU_LENGTH_PREFIX_SIZE) { - nalu_size = read_nal_unit_length(bits, EVC_NALU_LENGTH_PREFIX_SIZE); + nalu_size = evc_read_nal_unit_length(bits, EVC_NALU_LENGTH_PREFIX_SIZE); if (nalu_size == 0) break; bits += EVC_NALU_LENGTH_PREFIX_SIZE; @@ -114,7 +78,7 @@ static int annexb_probe(const AVProbeData *p) if(bytes_to_read < nalu_size) break; - nalu_type = get_nalu_type(bits, bytes_to_read); + nalu_type = evc_get_nalu_type(bits, bytes_to_read); if (nalu_type == EVC_SPS_NUT) got_sps++; @@ -199,7 +163,7 @@ static int evc_read_packet(AVFormatContext *s, AVPacket *pkt) if (ret < 0) return ret; - nalu_size = read_nal_unit_length((const uint8_t *)&buf, EVC_NALU_LENGTH_PREFIX_SIZE); + nalu_size = evc_read_nal_unit_length((const uint8_t *)&buf, EVC_NALU_LENGTH_PREFIX_SIZE); if (!nalu_size || nalu_size > INT_MAX) return AVERROR_INVALIDDATA; From 7fc6c7633ed13a34b7865bab2ad4b5f7014e74ae Mon Sep 17 00:00:00 2001 From: James Almer Date: Tue, 20 Jun 2023 11:15:42 -0300 Subject: [PATCH 1641/2172] avcodec/evc_frame_merge: use a GetBitContext to parse entire NALUs Signed-off-by: James Almer --- libavcodec/evc_frame_merge_bsf.c | 48 +++++++++++--------------------- 1 file changed, 17 insertions(+), 31 deletions(-) diff --git a/libavcodec/evc_frame_merge_bsf.c b/libavcodec/evc_frame_merge_bsf.c index 3904170ebd8..a9b44f4d101 100644 --- a/libavcodec/evc_frame_merge_bsf.c +++ b/libavcodec/evc_frame_merge_bsf.c @@ -74,57 +74,50 @@ static int evc_frame_merge_filter(AVBSFContext *bsf, AVPacket *out) { EVCFMergeContext *ctx = bsf->priv_data; AVPacket *in = ctx->in; - uint8_t *buffer, *nalu = NULL; + uint8_t *buffer; GetBitContext gb; enum EVCNALUnitType nalu_type; - int tid, nalu_size = 0; - int au_end_found = 0; + uint32_t nalu_size; + int tid, au_end_found = 0; int err; err = ff_bsf_get_packet_ref(bsf, in); if (err < 0) return err; - nalu_size = evc_read_nal_unit_length(in->data, EVC_NALU_LENGTH_PREFIX_SIZE, bsf); - if (nalu_size <= 0) { - err = AVERROR_INVALIDDATA; - goto end; - } - - nalu = in->data + EVC_NALU_LENGTH_PREFIX_SIZE; - nalu_size = in->size - EVC_NALU_LENGTH_PREFIX_SIZE; - // NAL unit parsing needed to determine if end of AU was found - if (nalu_size <= 0) { + nalu_size = evc_read_nal_unit_length(in->data, EVC_NALU_LENGTH_PREFIX_SIZE, bsf); + if (!nalu_size || nalu_size > INT_MAX) { av_log(bsf, AV_LOG_ERROR, "Invalid NAL unit size: (%d)\n", nalu_size); err = AVERROR_INVALIDDATA; goto end; } + err = init_get_bits8(&gb, in->data + EVC_NALU_LENGTH_PREFIX_SIZE, nalu_size); + if (err < 0) + return err; + // @see ISO_IEC_23094-1_2020, 7.4.2.2 NAL unit header semantic (Table 4 - NAL unit type codes and NAL unit type classes) // @see enum EVCNALUnitType in evc.h - nalu_type = evc_get_nalu_type(nalu, nalu_size, bsf); - if (nalu_type < EVC_NOIDR_NUT || nalu_type > EVC_UNSPEC_NUT62) { - av_log(bsf, AV_LOG_ERROR, "Invalid NAL unit type: (%d)\n", nalu_type); + if (get_bits1(&gb)) {// forbidden_zero_bit + av_log(bsf, AV_LOG_ERROR, "Invalid NAL unit header\n"); err = AVERROR_INVALIDDATA; goto end; } - tid = ff_evc_get_temporal_id(nalu, nalu_size, bsf); - if (tid < 0) { - av_log(bsf, AV_LOG_ERROR, "Invalid temporial id: (%d)\n", tid); + nalu_type = get_bits(&gb, 6) - 1; + if (nalu_type < EVC_NOIDR_NUT || nalu_type > EVC_UNSPEC_NUT62) { + av_log(bsf, AV_LOG_ERROR, "Invalid NAL unit type: (%d)\n", nalu_type); err = AVERROR_INVALIDDATA; goto end; } - nalu += EVC_NALU_HEADER_SIZE; - nalu_size -= EVC_NALU_HEADER_SIZE; + tid = get_bits(&gb, 3); + skip_bits(&gb, 5); // nuh_reserved_zero_5bits + skip_bits1(&gb); // nuh_extension_flag switch (nalu_type) { case EVC_SPS_NUT: - err = init_get_bits8(&gb, nalu, nalu_size); - if (err < 0) - return err; err = ff_evc_parse_sps(&gb, &ctx->ps); if (err < 0) { av_log(bsf, AV_LOG_ERROR, "SPS parsing error\n"); @@ -132,9 +125,6 @@ static int evc_frame_merge_filter(AVBSFContext *bsf, AVPacket *out) } break; case EVC_PPS_NUT: - err = init_get_bits8(&gb, nalu, nalu_size); - if (err < 0) - return err; err = ff_evc_parse_pps(&gb, &ctx->ps); if (err < 0) { av_log(bsf, AV_LOG_ERROR, "PPS parsing error\n"); @@ -145,10 +135,6 @@ static int evc_frame_merge_filter(AVBSFContext *bsf, AVPacket *out) case EVC_NOIDR_NUT: { EVCParserSliceHeader sh; - err = init_get_bits8(&gb, nalu, nalu_size); - if (err < 0) - return err; - err = ff_evc_parse_slice_header(&gb, &sh, &ctx->ps, nalu_type); if (err < 0) { av_log(bsf, AV_LOG_ERROR, "Slice header parsing error\n"); From 1bcb8a73382a253cee8b2b9e704e5a2fa3369593 Mon Sep 17 00:00:00 2001 From: James Almer Date: Tue, 20 Jun 2023 11:15:51 -0300 Subject: [PATCH 1642/2172] avcodec/evc_parser: use a GetBitContext to parse entire NALUs Signed-off-by: James Almer --- libavcodec/evc_parse.c | 22 ---------------------- libavcodec/evc_parse.h | 22 ---------------------- libavcodec/evc_parser.c | 30 ++++++++++++------------------ 3 files changed, 12 insertions(+), 62 deletions(-) diff --git a/libavcodec/evc_parse.c b/libavcodec/evc_parse.c index dee48e947bd..eff4b7bc38c 100644 --- a/libavcodec/evc_parse.c +++ b/libavcodec/evc_parse.c @@ -21,28 +21,6 @@ #include "evc.h" #include "evc_parse.h" -// nuh_temporal_id specifies a temporal identifier for the NAL unit -int ff_evc_get_temporal_id(const uint8_t *bits, int bits_size, void *logctx) -{ - int temporal_id = 0; - uint16_t t = 0; - - if (bits_size < EVC_NALU_HEADER_SIZE) { - av_log(logctx, AV_LOG_ERROR, "Can't read NAL unit header\n"); - return 0; - } - - // forbidden_zero_bit - if ((bits[0] & 0x80) != 0) - return -1; - - t = AV_RB16(bits); - - temporal_id = (t >> 6) & 0x0007; - - return temporal_id; -} - // @see ISO_IEC_23094-1 (7.3.2.6 Slice layer RBSP syntax) int ff_evc_parse_slice_header(GetBitContext *gb, EVCParserSliceHeader *sh, const EVCParamSets *ps, enum EVCNALUnitType nalu_type) diff --git a/libavcodec/evc_parse.h b/libavcodec/evc_parse.h index 322f52c9289..0f142976f53 100644 --- a/libavcodec/evc_parse.h +++ b/libavcodec/evc_parse.h @@ -81,25 +81,6 @@ typedef struct EVCParserPoc { int DocOffset; // the decoding order count of the previous picture } EVCParserPoc; -static inline int evc_get_nalu_type(const uint8_t *bits, int bits_size, void *logctx) -{ - int unit_type_plus1 = 0; - - if (bits_size >= EVC_NALU_HEADER_SIZE) { - unsigned char *p = (unsigned char *)bits; - // forbidden_zero_bit - if ((p[0] & 0x80) != 0) { - av_log(logctx, AV_LOG_ERROR, "Invalid NAL unit header\n"); - return -1; - } - - // nal_unit_type - unit_type_plus1 = (p[0] >> 1) & 0x3F; - } - - return unit_type_plus1 - 1; -} - static inline uint32_t evc_read_nal_unit_length(const uint8_t *bits, int bits_size, void *logctx) { uint32_t nalu_len = 0; @@ -114,9 +95,6 @@ static inline uint32_t evc_read_nal_unit_length(const uint8_t *bits, int bits_si return nalu_len; } -// nuh_temporal_id specifies a temporal identifier for the NAL unit -int ff_evc_get_temporal_id(const uint8_t *bits, int bits_size, void *logctx); - int ff_evc_parse_slice_header(GetBitContext *gb, EVCParserSliceHeader *sh, const EVCParamSets *ps, enum EVCNALUnitType nalu_type); diff --git a/libavcodec/evc_parser.c b/libavcodec/evc_parser.c index ae399ef8cca..76790d81110 100644 --- a/libavcodec/evc_parser.c +++ b/libavcodec/evc_parser.c @@ -71,28 +71,29 @@ static int parse_nal_unit(AVCodecParserContext *s, AVCodecContext *avctx, return AVERROR_INVALIDDATA; } + ret = init_get_bits8(&gb, buf, buf_size); + if (ret < 0) + return ret; + // @see ISO_IEC_23094-1_2020, 7.4.2.2 NAL unit header semantic (Table 4 - NAL unit type codes and NAL unit type classes) // @see enum EVCNALUnitType in evc.h - nalu_type = evc_get_nalu_type(buf, buf_size, avctx); - if (nalu_type < EVC_NOIDR_NUT || nalu_type > EVC_UNSPEC_NUT62) { - av_log(avctx, AV_LOG_ERROR, "Invalid NAL unit type: (%d)\n", nalu_type); + if (get_bits1(&gb)) {// forbidden_zero_bit + av_log(avctx, AV_LOG_ERROR, "Invalid NAL unit header\n"); return AVERROR_INVALIDDATA; } - tid = ff_evc_get_temporal_id(buf, buf_size, avctx); - if (tid < 0) { - av_log(avctx, AV_LOG_ERROR, "Invalid temporial id: (%d)\n", tid); + nalu_type = get_bits(&gb, 6) - 1; + if (nalu_type < EVC_NOIDR_NUT || nalu_type > EVC_UNSPEC_NUT62) { + av_log(avctx, AV_LOG_ERROR, "Invalid NAL unit type: (%d)\n", nalu_type); return AVERROR_INVALIDDATA; } - buf += EVC_NALU_HEADER_SIZE; - buf_size -= EVC_NALU_HEADER_SIZE; + tid = get_bits(&gb, 3); + skip_bits(&gb, 5); // nuh_reserved_zero_5bits + skip_bits1(&gb); // nuh_extension_flag switch (nalu_type) { case EVC_SPS_NUT: - ret = init_get_bits8(&gb, buf, buf_size); - if (ret < 0) - return ret; ret = ff_evc_parse_sps(&gb, &ctx->ps); if (ret < 0) { av_log(avctx, AV_LOG_ERROR, "SPS parsing error\n"); @@ -100,9 +101,6 @@ static int parse_nal_unit(AVCodecParserContext *s, AVCodecContext *avctx, } break; case EVC_PPS_NUT: - ret = init_get_bits8(&gb, buf, buf_size); - if (ret < 0) - return ret; ret = ff_evc_parse_pps(&gb, &ctx->ps); if (ret < 0) { av_log(avctx, AV_LOG_ERROR, "PPS parsing error\n"); @@ -116,10 +114,6 @@ static int parse_nal_unit(AVCodecParserContext *s, AVCodecContext *avctx, EVCParserSliceHeader sh; int bit_depth; - ret = init_get_bits8(&gb, buf, buf_size); - if (ret < 0) - return ret; - ret = ff_evc_parse_slice_header(&gb, &sh, &ctx->ps, nalu_type); if (ret < 0) { av_log(avctx, AV_LOG_ERROR, "Slice header parsing error\n"); From 13ff3aa9e74508c735b57f73767aac6912c429aa Mon Sep 17 00:00:00 2001 From: Lynne Date: Tue, 13 Jun 2023 06:10:20 +0200 Subject: [PATCH 1643/2172] vulkan_decode: use the hwfc->user_opaque field to store the profile --- libavcodec/vulkan_decode.c | 64 ++++++++++++++++++++++++-------------- libavcodec/vulkan_decode.h | 6 ++-- 2 files changed, 44 insertions(+), 26 deletions(-) diff --git a/libavcodec/vulkan_decode.c b/libavcodec/vulkan_decode.c index 6ba939da46f..3c348c533f1 100644 --- a/libavcodec/vulkan_decode.c +++ b/libavcodec/vulkan_decode.c @@ -196,7 +196,6 @@ int ff_vk_decode_add_slice(AVCodecContext *avctx, FFVulkanDecodePicture *vp, { FFVulkanDecodeContext *dec = avctx->internal->hwaccel_priv_data; FFVulkanDecodeShared *ctx = (FFVulkanDecodeShared *)dec->shared_ref->data; - FFVulkanDecodeProfileData *prof = &ctx->profile_data; static const uint8_t startcode_prefix[3] = { 0x0, 0x0, 0x1 }; const size_t startcode_len = add_startcode ? sizeof(startcode_prefix) : 0; @@ -206,8 +205,8 @@ int ff_vk_decode_add_slice(AVCodecContext *avctx, FFVulkanDecodePicture *vp, FFVkVideoBuffer *vkbuf; size_t new_size = vp->slices_size + startcode_len + size + - prof->caps.minBitstreamBufferSizeAlignment; - new_size = FFALIGN(new_size, prof->caps.minBitstreamBufferSizeAlignment); + ctx->caps.minBitstreamBufferSizeAlignment; + new_size = FFALIGN(new_size, ctx->caps.minBitstreamBufferSizeAlignment); slice_off = av_fast_realloc(vp->slice_off, &vp->slice_off_max, (nb + 1)*sizeof(slice_off)); @@ -295,7 +294,6 @@ int ff_vk_decode_frame(AVCodecContext *avctx, FFVulkanDecodeContext *dec = avctx->internal->hwaccel_priv_data; FFVulkanDecodeShared *ctx = (FFVulkanDecodeShared *)dec->shared_ref->data; - FFVulkanDecodeProfileData *prof = &ctx->profile_data; FFVulkanFunctions *vk = &ctx->s.vkfn; /* Output */ @@ -319,7 +317,7 @@ int ff_vk_decode_frame(AVCodecContext *avctx, VkImageMemoryBarrier2 img_bar[37]; int nb_img_bar = 0; size_t data_size = FFALIGN(vp->slices_size, - prof->caps.minBitstreamBufferSizeAlignment); + ctx->caps.minBitstreamBufferSizeAlignment); FFVkExecContext *exec = ff_vk_exec_get(&ctx->exec_pool); @@ -640,10 +638,10 @@ static VkResult vulkan_setup_profile(AVCodecContext *avctx, VkVideoDecodeH264CapabilitiesKHR *h264_caps, VkVideoDecodeH265CapabilitiesKHR *h265_caps, VkVideoDecodeAV1CapabilitiesMESA *av1_caps, + VkVideoCapabilitiesKHR *caps, + VkVideoDecodeCapabilitiesKHR *dec_caps, int cur_profile) { - VkVideoCapabilitiesKHR *caps = &prof->caps; - VkVideoDecodeCapabilitiesKHR *dec_caps = &prof->dec_caps; VkVideoDecodeUsageInfoKHR *usage = &prof->usage; VkVideoProfileInfoKHR *profile = &prof->profile; VkVideoProfileListInfoKHR *profile_list = &prof->profile_list; @@ -708,6 +706,7 @@ static VkResult vulkan_setup_profile(AVCodecContext *avctx, static int vulkan_decode_get_profile(AVCodecContext *avctx, AVBufferRef *frames_ref, enum AVPixelFormat *pix_fmt, VkFormat *vk_fmt, + FFVulkanDecodeProfileData *prof, int *dpb_dedicate) { VkResult ret; @@ -724,9 +723,8 @@ static int vulkan_decode_get_profile(AVCodecContext *avctx, AVBufferRef *frames_ FFVulkanDecodeShared *ctx = (FFVulkanDecodeShared *)dec->shared_ref->data; FFVulkanFunctions *vk = &ctx->s.vkfn; - FFVulkanDecodeProfileData *prof = &ctx->profile_data; - VkVideoCapabilitiesKHR *caps = &prof->caps; - VkVideoDecodeCapabilitiesKHR *dec_caps = &prof->dec_caps; + VkVideoCapabilitiesKHR *caps = &ctx->caps; + VkVideoDecodeCapabilitiesKHR *dec_caps = &ctx->dec_caps; VkVideoDecodeH264CapabilitiesKHR h264_caps = { .sType = VK_STRUCTURE_TYPE_VIDEO_DECODE_H264_CAPABILITIES_KHR, @@ -765,6 +763,8 @@ static int vulkan_decode_get_profile(AVCodecContext *avctx, AVBufferRef *frames_ &h264_caps, &h265_caps, &av1_caps, + caps, + dec_caps, cur_profile); if (ret == VK_ERROR_VIDEO_PROFILE_OPERATION_NOT_SUPPORTED_KHR && avctx->flags & AV_HWACCEL_FLAG_ALLOW_PROFILE_MISMATCH && @@ -779,6 +779,8 @@ static int vulkan_decode_get_profile(AVCodecContext *avctx, AVBufferRef *frames_ &h264_caps, &h265_caps, &av1_caps, + caps, + dec_caps, cur_profile); } @@ -965,6 +967,11 @@ static int vulkan_decode_get_profile(AVCodecContext *avctx, AVBufferRef *frames_ return 0; } +static void free_profile_data(AVHWFramesContext *hwfc) +{ + av_free(hwfc->user_opaque); +} + int ff_vk_frame_params(AVCodecContext *avctx, AVBufferRef *hw_frames_ctx) { VkFormat vkfmt; @@ -972,7 +979,6 @@ int ff_vk_frame_params(AVCodecContext *avctx, AVBufferRef *hw_frames_ctx) AVHWFramesContext *frames_ctx = (AVHWFramesContext*)hw_frames_ctx->data; AVVulkanFramesContext *hwfc = frames_ctx->hwctx; FFVulkanDecodeContext *dec = avctx->internal->hwaccel_priv_data; - FFVulkanDecodeShared *ctx; FFVulkanDecodeProfileData *prof; frames_ctx->sw_format = AV_PIX_FMT_NONE; @@ -981,14 +987,20 @@ int ff_vk_frame_params(AVCodecContext *avctx, AVBufferRef *hw_frames_ctx) if (err < 0) return err; - ctx = (FFVulkanDecodeShared *)dec->shared_ref->data; - prof = &ctx->profile_data; + prof = av_mallocz(sizeof(FFVulkanDecodeProfileData)); + if (!prof) + return AVERROR(ENOMEM); err = vulkan_decode_get_profile(avctx, hw_frames_ctx, &frames_ctx->sw_format, &vkfmt, - &dedicated_dpb); - if (err < 0) + prof, &dedicated_dpb); + if (err < 0) { + av_free(prof); return err; + } + + frames_ctx->user_opaque = prof; + frames_ctx->free = free_profile_data; frames_ctx->width = avctx->width; frames_ctx->height = avctx->height; @@ -1032,10 +1044,10 @@ int ff_vk_decode_init(AVCodecContext *avctx) VkResult ret; FFVulkanDecodeContext *dec = avctx->internal->hwaccel_priv_data; FFVulkanDecodeShared *ctx; - FFVulkanDecodeProfileData *prof; FFVulkanContext *s; FFVulkanFunctions *vk; FFVkQueueFamilyCtx qf_dec; + const VkVideoProfileListInfoKHR *profile_list; VkVideoDecodeH264SessionParametersCreateInfoKHR h264_params = { .sType = VK_STRUCTURE_TYPE_VIDEO_DECODE_H264_SESSION_PARAMETERS_CREATE_INFO_KHR, @@ -1069,7 +1081,6 @@ int ff_vk_decode_init(AVCodecContext *avctx) /* Initialize contexts */ ctx = (FFVulkanDecodeShared *)dec->shared_ref->data; - prof = &ctx->profile_data; s = &ctx->s; vk = &ctx->s.vkfn; @@ -1080,6 +1091,13 @@ int ff_vk_decode_init(AVCodecContext *avctx) s->device = (AVHWDeviceContext *)s->frames->device_ref->data; s->hwctx = s->device->hwctx; + profile_list = ff_vk_find_struct(s->hwfc->create_pnext, + VK_STRUCTURE_TYPE_VIDEO_PROFILE_LIST_INFO_KHR); + if (!profile_list) { + av_log(avctx, AV_LOG_ERROR, "Profile list missing from frames context!"); + return AVERROR(EINVAL); + } + err = ff_vk_load_props(s); if (err < 0) goto fail; @@ -1101,13 +1119,13 @@ int ff_vk_decode_init(AVCodecContext *avctx) session_create.flags = 0x0; session_create.queueFamilyIndex = s->hwctx->queue_family_decode_index; - session_create.maxCodedExtent = prof->caps.maxCodedExtent; - session_create.maxDpbSlots = prof->caps.maxDpbSlots; - session_create.maxActiveReferencePictures = prof->caps.maxActiveReferencePictures; + session_create.maxCodedExtent = ctx->caps.maxCodedExtent; + session_create.maxDpbSlots = ctx->caps.maxDpbSlots; + session_create.maxActiveReferencePictures = ctx->caps.maxActiveReferencePictures; session_create.pictureFormat = s->hwfc->format[0]; session_create.referencePictureFormat = session_create.pictureFormat; session_create.pStdHeaderVersion = dec_ext[avctx->codec_id]; - session_create.pVideoProfile = &prof->profile_list.pProfiles[0]; + session_create.pVideoProfile = &profile_list->pProfiles[0]; /* Create decode exec context. * 2 async contexts per thread was experimentally determined to be optimal @@ -1152,14 +1170,14 @@ int ff_vk_decode_init(AVCodecContext *avctx) dpb_frames->height = s->frames->height; dpb_hwfc = dpb_frames->hwctx; - dpb_hwfc->create_pnext = (void *)&prof->profile_list; + dpb_hwfc->create_pnext = (void *)profile_list; dpb_hwfc->format[0] = s->hwfc->format[0]; dpb_hwfc->tiling = VK_IMAGE_TILING_OPTIMAL; dpb_hwfc->usage = VK_IMAGE_USAGE_VIDEO_DECODE_DPB_BIT_KHR | VK_IMAGE_USAGE_SAMPLED_BIT; /* Shuts validator up. */ if (dec->layered_dpb) - dpb_hwfc->nb_layers = prof->caps.maxDpbSlots; + dpb_hwfc->nb_layers = ctx->caps.maxDpbSlots; err = av_hwframe_ctx_init(ctx->dpb_hwfc_ref); if (err < 0) diff --git a/libavcodec/vulkan_decode.h b/libavcodec/vulkan_decode.h index 681d2476cdb..3ac103f6b45 100644 --- a/libavcodec/vulkan_decode.h +++ b/libavcodec/vulkan_decode.h @@ -26,8 +26,6 @@ #include "vulkan_video.h" typedef struct FFVulkanDecodeProfileData { - VkVideoCapabilitiesKHR caps; - VkVideoDecodeCapabilitiesKHR dec_caps; VkVideoDecodeH264ProfileInfoKHR h264_profile; VkVideoDecodeH264ProfileInfoKHR h265_profile; VkVideoDecodeAV1ProfileInfoMESA av1_profile; @@ -40,7 +38,9 @@ typedef struct FFVulkanDecodeShared { FFVulkanContext s; FFVkVideoCommon common; FFVkExecPool exec_pool; - FFVulkanDecodeProfileData profile_data; + + VkVideoCapabilitiesKHR caps; + VkVideoDecodeCapabilitiesKHR dec_caps; AVBufferRef *dpb_hwfc_ref; /* Only used for dedicated_dpb */ From d9af84426bfea003e06c4f389f4d1666c3515340 Mon Sep 17 00:00:00 2001 From: Lynne Date: Tue, 13 Jun 2023 06:13:10 +0200 Subject: [PATCH 1644/2172] vulkan_decode: fix small memory leak This requires using the new AVHWFramesContext.opaque field, as otherwise, the profile attached to the decoder will be freed before the frames context, rendering the frames context useless. --- libavcodec/vulkan_decode.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/libavcodec/vulkan_decode.c b/libavcodec/vulkan_decode.c index 3c348c533f1..afcdcd80216 100644 --- a/libavcodec/vulkan_decode.c +++ b/libavcodec/vulkan_decode.c @@ -584,6 +584,8 @@ static void free_common(void *opaque, uint8_t *data) s->hwctx->alloc); ff_vk_uninit(s); + + av_free(ctx); } static int vulkan_decode_bootstrap(AVCodecContext *avctx, AVBufferRef *frames_ref) From 237c400727c9bfb7b0c50221bcd17864b2b8ade3 Mon Sep 17 00:00:00 2001 From: Lynne Date: Tue, 20 Jun 2023 03:22:27 +0200 Subject: [PATCH 1645/2172] vulkan_decode: remove unused fields --- libavcodec/vulkan_decode.c | 2 -- libavcodec/vulkan_decode.h | 6 ------ 2 files changed, 8 deletions(-) diff --git a/libavcodec/vulkan_decode.c b/libavcodec/vulkan_decode.c index afcdcd80216..d4395e32e4c 100644 --- a/libavcodec/vulkan_decode.c +++ b/libavcodec/vulkan_decode.c @@ -136,7 +136,6 @@ int ff_vk_decode_prepare_frame(FFVulkanDecodeContext *dec, AVFrame *pic, int err; FFVulkanDecodeShared *ctx = (FFVulkanDecodeShared *)dec->shared_ref->data; - vkpic->nb_slices = 0; vkpic->slices_size = 0; /* If the decoder made a blank frame to make up for a missing ref, or the @@ -247,7 +246,6 @@ int ff_vk_decode_add_slice(AVCodecContext *avctx, FFVulkanDecodePicture *vp, memcpy(slices + vp->slices_size + startcode_len, data, size); *nb_slices = nb + 1; - vp->nb_slices++; vp->slices_size += startcode_len + size; return 0; diff --git a/libavcodec/vulkan_decode.h b/libavcodec/vulkan_decode.h index 3ac103f6b45..bb53100429c 100644 --- a/libavcodec/vulkan_decode.h +++ b/libavcodec/vulkan_decode.h @@ -80,10 +80,6 @@ typedef struct FFVulkanDecodePicture { VkSemaphore sem; uint64_t sem_value; - /* State */ - int update_params; - AVBufferRef *session_params; - /* Current picture */ VkVideoPictureResourceInfoKHR ref; VkVideoReferenceSlotInfoKHR ref_slot; @@ -93,7 +89,6 @@ typedef struct FFVulkanDecodePicture { VkVideoReferenceSlotInfoKHR ref_slots[36]; /* Main decoding struct */ - AVBufferRef *params_buf; VkVideoDecodeInfoKHR decode_info; /* Slice data */ @@ -101,7 +96,6 @@ typedef struct FFVulkanDecodePicture { size_t slices_size; uint32_t *slice_off; unsigned int slice_off_max; - uint32_t nb_slices; } FFVulkanDecodePicture; /** From ba8a80323615cd297e3cfe077aa2dcb5bca0fc44 Mon Sep 17 00:00:00 2001 From: Lynne Date: Tue, 20 Jun 2023 03:37:34 +0200 Subject: [PATCH 1646/2172] vulkan_decode: clean up slice handling Move the slice offsets buffer to the thread decode context. It isn't part of the resources for frame decoding, the driver has to process and finish with it at submission time. That way, it doesn't need to be alloc'd + freed on every frame. --- libavcodec/vulkan_decode.c | 8 +++----- libavcodec/vulkan_decode.h | 5 +++-- libavcodec/vulkan_h264.c | 1 - libavcodec/vulkan_hevc.c | 1 - 4 files changed, 6 insertions(+), 9 deletions(-) diff --git a/libavcodec/vulkan_decode.c b/libavcodec/vulkan_decode.c index d4395e32e4c..685e300e8a0 100644 --- a/libavcodec/vulkan_decode.c +++ b/libavcodec/vulkan_decode.c @@ -207,12 +207,12 @@ int ff_vk_decode_add_slice(AVCodecContext *avctx, FFVulkanDecodePicture *vp, ctx->caps.minBitstreamBufferSizeAlignment; new_size = FFALIGN(new_size, ctx->caps.minBitstreamBufferSizeAlignment); - slice_off = av_fast_realloc(vp->slice_off, &vp->slice_off_max, + slice_off = av_fast_realloc(dec->slice_off, &dec->slice_off_max, (nb + 1)*sizeof(slice_off)); if (!slice_off) return AVERROR(ENOMEM); - *offsets = vp->slice_off = slice_off; + *offsets = dec->slice_off = slice_off; slice_off[nb] = vp->slices_size; vkbuf = vp->slices_buf ? (FFVkVideoBuffer *)vp->slices_buf->data : NULL; @@ -538,9 +538,6 @@ void ff_vk_decode_free_frame(AVHWDeviceContext *dev_ctx, FFVulkanDecodePicture * /* Free slices data */ av_buffer_unref(&vp->slices_buf); - /* TODO: use a pool in the decode context instead to avoid per-frame allocs. */ - av_freep(&vp->slice_off); - /* Destroy image view (out) */ if (vp->img_view_out && vp->img_view_out != vp->img_view_dest) destroy_image_view(hwctx->act_dev, vp->img_view_out, hwctx->alloc); @@ -1035,6 +1032,7 @@ int ff_vk_decode_uninit(AVCodecContext *avctx) av_buffer_pool_uninit(&dec->tmp_pool); av_buffer_unref(&dec->session_params); av_buffer_unref(&dec->shared_ref); + av_freep(&dec->slice_off); return 0; } diff --git a/libavcodec/vulkan_decode.h b/libavcodec/vulkan_decode.h index bb53100429c..776538a3355 100644 --- a/libavcodec/vulkan_decode.h +++ b/libavcodec/vulkan_decode.h @@ -66,6 +66,9 @@ typedef struct FFVulkanDecodeContext { AVBufferPool *tmp_pool; /* Pool for temporary data, if needed (HEVC) */ size_t tmp_pool_ele_size; int params_changed; + + uint32_t *slice_off; + unsigned int slice_off_max; } FFVulkanDecodeContext; typedef struct FFVulkanDecodePicture { @@ -94,8 +97,6 @@ typedef struct FFVulkanDecodePicture { /* Slice data */ AVBufferRef *slices_buf; size_t slices_size; - uint32_t *slice_off; - unsigned int slice_off_max; } FFVulkanDecodePicture; /** diff --git a/libavcodec/vulkan_h264.c b/libavcodec/vulkan_h264.c index 4cfd83fc191..d0b66734d1b 100644 --- a/libavcodec/vulkan_h264.c +++ b/libavcodec/vulkan_h264.c @@ -463,7 +463,6 @@ static int vk_h264_start_frame(AVCodecContext *avctx, hp->h264_pic_info = (VkVideoDecodeH264PictureInfoKHR) { .sType = VK_STRUCTURE_TYPE_VIDEO_DECODE_H264_PICTURE_INFO_KHR, .pStdPictureInfo = &hp->h264pic, - .sliceCount = 0, }; vp->decode_info = (VkVideoDecodeInfoKHR) { diff --git a/libavcodec/vulkan_hevc.c b/libavcodec/vulkan_hevc.c index 5ddfd0daf3c..a1df0766fac 100644 --- a/libavcodec/vulkan_hevc.c +++ b/libavcodec/vulkan_hevc.c @@ -855,7 +855,6 @@ static int vk_hevc_start_frame(AVCodecContext *avctx, .sType = VK_STRUCTURE_TYPE_VIDEO_DECODE_H265_PICTURE_INFO_KHR, .pStdPictureInfo = &hp->h265pic, .sliceSegmentCount = 0, - .pSliceSegmentOffsets = vp->slice_off, }; vp->decode_info = (VkVideoDecodeInfoKHR) { From 343716bd744a44cb15205af73c6e6ad0fdaa0b7b Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Wed, 21 Jun 2023 09:50:52 +1000 Subject: [PATCH 1647/2172] vulkan/av1: fix tile upload offsets. This fixes decoding av1-1-b8-22-svc-L2T1.ivf while not breaking other videos. --- libavcodec/vulkan_av1.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/libavcodec/vulkan_av1.c b/libavcodec/vulkan_av1.c index 91e44ba8038..005998b1bd5 100644 --- a/libavcodec/vulkan_av1.c +++ b/libavcodec/vulkan_av1.c @@ -513,13 +513,15 @@ static int vk_av1_decode_slice(AVCodecContext *avctx, .tg_end = s->tg_end, }; - err = ff_vk_decode_add_slice(avctx, vp, data, size, 0, + err = ff_vk_decode_add_slice(avctx, vp, + data + s->tile_group_info[i].tile_offset, + s->tile_group_info[i].tile_size, 0, &ap->tile_list.nb_tiles, &ap->tile_offsets); if (err < 0) return err; -// ap->tiles[ap->tile_list.nb_tiles - 1].offset = ap->tile_offsets[ap->tile_list.nb_tiles - 1]; + ap->tiles[ap->tile_list.nb_tiles - 1].offset = ap->tile_offsets[ap->tile_list.nb_tiles - 1]; } return 0; From 4ff303a7b827de2179c6e346959e36960e57b5ba Mon Sep 17 00:00:00 2001 From: Lynne Date: Wed, 21 Jun 2023 18:24:55 +0200 Subject: [PATCH 1648/2172] vulkan_decode: simplify and make session parameter generation more robust This commit scraps a bool to signal to recreate the session parameters, but instead destroys them, forcing them to be recreated. As this can happen between start_frame and end_frame, do this at both places. --- libavcodec/vulkan_av1.c | 13 +++++++++---- libavcodec/vulkan_decode.c | 4 ++-- libavcodec/vulkan_decode.h | 5 ++--- libavcodec/vulkan_h264.c | 16 ++++++++++------ libavcodec/vulkan_hevc.c | 20 ++++++++++++++++---- 5 files changed, 39 insertions(+), 19 deletions(-) diff --git a/libavcodec/vulkan_av1.c b/libavcodec/vulkan_av1.c index 005998b1bd5..e953096b89e 100644 --- a/libavcodec/vulkan_av1.c +++ b/libavcodec/vulkan_av1.c @@ -229,12 +229,10 @@ static int vk_av1_start_frame(AVCodecContext *avctx, const int apply_grain = !(avctx->export_side_data & AV_CODEC_EXPORT_DATA_FILM_GRAIN) && film_grain->apply_grain; - if (!dec->session_params || dec->params_changed) { - av_buffer_unref(&dec->session_params); + if (!dec->session_params) { err = vk_av1_create_params(avctx, &dec->session_params); if (err < 0) return err; - dec->params_changed = 0; } if (!ap->frame_id_set) { @@ -530,12 +528,19 @@ static int vk_av1_decode_slice(AVCodecContext *avctx, static int vk_av1_end_frame(AVCodecContext *avctx) { const AV1DecContext *s = avctx->priv_data; + FFVulkanDecodeContext *dec = avctx->internal->hwaccel_priv_data; const AV1Frame *pic = &s->cur_frame; AV1VulkanDecodePicture *ap = pic->hwaccel_picture_private; FFVulkanDecodePicture *vp = &ap->vp; FFVulkanDecodePicture *rvp[AV1_NUM_REF_FRAMES] = { 0 }; AVFrame *rav[AV1_NUM_REF_FRAMES] = { 0 }; + if (!dec->session_params) { + int err = vk_av1_create_params(avctx, &dec->session_params); + if (err < 0) + return err; + } + for (int i = 0; i < vp->decode_info.referenceSlotCount; i++) { const AV1Frame *rp = ap->ref_src[i]; AV1VulkanDecodePicture *rhp = rp->hwaccel_picture_private; @@ -578,7 +583,7 @@ const AVHWAccel ff_av1_vulkan_hwaccel = { .frame_priv_data_size = sizeof(AV1VulkanDecodePicture), .init = &ff_vk_decode_init, .update_thread_context = &ff_vk_update_thread_context, - .decode_params = &ff_vk_params_changed, + .decode_params = &ff_vk_params_invalidate, .flush = &ff_vk_decode_flush, .uninit = &ff_vk_decode_uninit, .frame_params = &ff_vk_frame_params, diff --git a/libavcodec/vulkan_decode.c b/libavcodec/vulkan_decode.c index 685e300e8a0..973c7ca5482 100644 --- a/libavcodec/vulkan_decode.c +++ b/libavcodec/vulkan_decode.c @@ -66,10 +66,10 @@ int ff_vk_update_thread_context(AVCodecContext *dst, const AVCodecContext *src) return 0; } -int ff_vk_params_changed(AVCodecContext *avctx, int t, const uint8_t *b, uint32_t s) +int ff_vk_params_invalidate(AVCodecContext *avctx, int t, const uint8_t *b, uint32_t s) { FFVulkanDecodeContext *dec = avctx->internal->hwaccel_priv_data; - dec->params_changed = 1; + av_buffer_unref(&dec->session_params); return 0; } diff --git a/libavcodec/vulkan_decode.h b/libavcodec/vulkan_decode.h index 776538a3355..4e45cbde715 100644 --- a/libavcodec/vulkan_decode.h +++ b/libavcodec/vulkan_decode.h @@ -65,7 +65,6 @@ typedef struct FFVulkanDecodeContext { /* Thread-local state below */ AVBufferPool *tmp_pool; /* Pool for temporary data, if needed (HEVC) */ size_t tmp_pool_ele_size; - int params_changed; uint32_t *slice_off; unsigned int slice_off_max; @@ -119,9 +118,9 @@ int ff_vk_update_thread_context(AVCodecContext *dst, const AVCodecContext *src); int ff_vk_frame_params(AVCodecContext *avctx, AVBufferRef *hw_frames_ctx); /** - * Sets FFVulkanDecodeContext.params_changed to 1. + * Removes current session parameters to recreate them */ -int ff_vk_params_changed(AVCodecContext *avctx, int t, const uint8_t *b, uint32_t s); +int ff_vk_params_invalidate(AVCodecContext *avctx, int t, const uint8_t *b, uint32_t s); /** * Prepare a frame, creates the image view, and sets up the dpb fields. diff --git a/libavcodec/vulkan_h264.c b/libavcodec/vulkan_h264.c index d0b66734d1b..62e350266a7 100644 --- a/libavcodec/vulkan_h264.c +++ b/libavcodec/vulkan_h264.c @@ -379,12 +379,10 @@ static int vk_h264_start_frame(AVCodecContext *avctx, H264VulkanDecodePicture *hp = pic->hwaccel_picture_private; FFVulkanDecodePicture *vp = &hp->vp; - if (!dec->session_params || dec->params_changed) { - av_buffer_unref(&dec->session_params); + if (!dec->session_params) { err = vk_h264_create_params(avctx, &dec->session_params); if (err < 0) return err; - dec->params_changed = 0; } /* Fill in main slot */ @@ -519,8 +517,14 @@ static int vk_h264_end_frame(AVCodecContext *avctx) FFVulkanDecodePicture *rvp[H264_MAX_PICTURE_COUNT] = { 0 }; AVFrame *rav[H264_MAX_PICTURE_COUNT] = { 0 }; - if (!dec->session_params) - return AVERROR(EINVAL); + if (!dec->session_params) { + int err = vk_h264_create_params(avctx, &dec->session_params); + if (err < 0) + return err; + + hp->h264pic.seq_parameter_set_id = pic->pps->sps_id; + hp->h264pic.pic_parameter_set_id = pic->pps->pps_id; + } for (int i = 0; i < vp->decode_info.referenceSlotCount; i++) { H264Picture *rp = hp->ref_src[i]; @@ -560,7 +564,7 @@ const AVHWAccel ff_h264_vulkan_hwaccel = { .frame_priv_data_size = sizeof(H264VulkanDecodePicture), .init = &ff_vk_decode_init, .update_thread_context = &ff_vk_update_thread_context, - .decode_params = &ff_vk_params_changed, + .decode_params = &ff_vk_params_invalidate, .flush = &ff_vk_decode_flush, .uninit = &ff_vk_decode_uninit, .frame_params = &ff_vk_frame_params, diff --git a/libavcodec/vulkan_hevc.c b/libavcodec/vulkan_hevc.c index a1df0766fac..58940868217 100644 --- a/libavcodec/vulkan_hevc.c +++ b/libavcodec/vulkan_hevc.c @@ -767,12 +767,10 @@ static int vk_hevc_start_frame(AVCodecContext *avctx, const HEVCPPS *pps = h->ps.pps; int nb_refs = 0; - if (!dec->session_params || dec->params_changed) { - av_buffer_unref(&dec->session_params); + if (!dec->session_params) { err = vk_hevc_create_params(avctx, &dec->session_params); if (err < 0) return err; - dec->params_changed = 0; } hp->h265pic = (StdVideoDecodeH265PictureInfo) { @@ -896,12 +894,26 @@ static int vk_hevc_decode_slice(AVCodecContext *avctx, static int vk_hevc_end_frame(AVCodecContext *avctx) { const HEVCContext *h = avctx->priv_data; + FFVulkanDecodeContext *dec = avctx->internal->hwaccel_priv_data; HEVCFrame *pic = h->ref; HEVCVulkanDecodePicture *hp = pic->hwaccel_picture_private; FFVulkanDecodePicture *vp = &hp->vp; FFVulkanDecodePicture *rvp[HEVC_MAX_REFS] = { 0 }; AVFrame *rav[HEVC_MAX_REFS] = { 0 }; + if (!dec->session_params) { + const HEVCSPS *sps = h->ps.sps; + const HEVCPPS *pps = h->ps.pps; + + int err = vk_hevc_create_params(avctx, &dec->session_params); + if (err < 0) + return err; + + hp->h265pic.sps_video_parameter_set_id = sps->vps_id; + hp->h265pic.pps_seq_parameter_set_id = pps->sps_id; + hp->h265pic.pps_pic_parameter_set_id = pps->pps_id; + } + for (int i = 0; i < vp->decode_info.referenceSlotCount; i++) { HEVCVulkanDecodePicture *rfhp = hp->ref_src[i]->hwaccel_picture_private; rav[i] = hp->ref_src[i]->frame; @@ -938,7 +950,7 @@ const AVHWAccel ff_hevc_vulkan_hwaccel = { .frame_priv_data_size = sizeof(HEVCVulkanDecodePicture), .init = &ff_vk_decode_init, .update_thread_context = &ff_vk_update_thread_context, - .decode_params = &ff_vk_params_changed, + .decode_params = &ff_vk_params_invalidate, .flush = &ff_vk_decode_flush, .uninit = &ff_vk_decode_uninit, .frame_params = &ff_vk_frame_params, From 997d8a7e73a9b9f00e4bc32ed3b41b30d2e39cf8 Mon Sep 17 00:00:00 2001 From: Lynne Date: Thu, 22 Jun 2023 04:59:40 +0200 Subject: [PATCH 1649/2172] vulkan_decode: reject decoding of frames with no slices As per the spec: VUID-VkVideoDecodeH264PictureInfoKHR-sliceCount-arraylength sliceCount must be greater than 0 VUID-VkVideoDecodeH265PictureInfoKHR-sliceSegmentCount-arraylength sliceSegmentCount must be greater than 0 This particularly happens with seeking in field-coded H264. --- libavcodec/vulkan_av1.c | 3 +++ libavcodec/vulkan_h264.c | 3 +++ libavcodec/vulkan_hevc.c | 3 +++ 3 files changed, 9 insertions(+) diff --git a/libavcodec/vulkan_av1.c b/libavcodec/vulkan_av1.c index e953096b89e..e06457bbc33 100644 --- a/libavcodec/vulkan_av1.c +++ b/libavcodec/vulkan_av1.c @@ -535,6 +535,9 @@ static int vk_av1_end_frame(AVCodecContext *avctx) FFVulkanDecodePicture *rvp[AV1_NUM_REF_FRAMES] = { 0 }; AVFrame *rav[AV1_NUM_REF_FRAMES] = { 0 }; + if (!ap->tile_list.nb_tiles) + return 0; + if (!dec->session_params) { int err = vk_av1_create_params(avctx, &dec->session_params); if (err < 0) diff --git a/libavcodec/vulkan_h264.c b/libavcodec/vulkan_h264.c index 62e350266a7..089a181bb40 100644 --- a/libavcodec/vulkan_h264.c +++ b/libavcodec/vulkan_h264.c @@ -517,6 +517,9 @@ static int vk_h264_end_frame(AVCodecContext *avctx) FFVulkanDecodePicture *rvp[H264_MAX_PICTURE_COUNT] = { 0 }; AVFrame *rav[H264_MAX_PICTURE_COUNT] = { 0 }; + if (!hp->h264_pic_info.sliceCount) + return 0; + if (!dec->session_params) { int err = vk_h264_create_params(avctx, &dec->session_params); if (err < 0) diff --git a/libavcodec/vulkan_hevc.c b/libavcodec/vulkan_hevc.c index 58940868217..af5da3984bc 100644 --- a/libavcodec/vulkan_hevc.c +++ b/libavcodec/vulkan_hevc.c @@ -901,6 +901,9 @@ static int vk_hevc_end_frame(AVCodecContext *avctx) FFVulkanDecodePicture *rvp[HEVC_MAX_REFS] = { 0 }; AVFrame *rav[HEVC_MAX_REFS] = { 0 }; + if (!hp->h265_pic_info.sliceSegmentCount) + return 0; + if (!dec->session_params) { const HEVCSPS *sps = h->ps.sps; const HEVCPPS *pps = h->ps.pps; From 99dfdb45a89955916651eeaeac77d938e9a4217a Mon Sep 17 00:00:00 2001 From: Ricardo Monteiro Date: Thu, 22 Jun 2023 12:18:19 +0200 Subject: [PATCH 1650/2172] avcodec/nvenc: let preset decide default gop size Default GOP size is now set by preset and tuning info. This GOP size is only overwriten if -g value is provided. Signed-off-by: Timo Rothenpieler --- libavcodec/nvenc.c | 35 ++++++++++++++++++----------------- libavcodec/nvenc_av1.c | 2 +- libavcodec/nvenc_h264.c | 2 +- libavcodec/nvenc_hevc.c | 2 +- 4 files changed, 21 insertions(+), 20 deletions(-) diff --git a/libavcodec/nvenc.c b/libavcodec/nvenc.c index d56ebc68e27..06579a502b6 100644 --- a/libavcodec/nvenc.c +++ b/libavcodec/nvenc.c @@ -1171,8 +1171,8 @@ static av_cold int nvenc_setup_h264_config(AVCodecContext *avctx) if (ctx->intra_refresh) { h264->enableIntraRefresh = 1; - h264->intraRefreshPeriod = avctx->gop_size; - h264->intraRefreshCnt = avctx->gop_size - 1; + h264->intraRefreshPeriod = cc->gopLength; + h264->intraRefreshCnt = cc->gopLength - 1; #ifdef NVENC_HAVE_SINGLE_SLICE_INTRA_REFRESH h264->singleSliceIntraRefresh = ctx->single_slice_intra_refresh; #endif @@ -1192,8 +1192,8 @@ static av_cold int nvenc_setup_h264_config(AVCodecContext *avctx) if (ctx->intra_refresh) { h264->idrPeriod = NVENC_INFINITE_GOPLENGTH; - } else if (avctx->gop_size >= 0) { - h264->idrPeriod = avctx->gop_size; + } else if (cc->gopLength > 0) { + h264->idrPeriod = cc->gopLength; } if (IS_CBR(cc->rcParams.rateControlMode)) { @@ -1295,8 +1295,8 @@ static av_cold int nvenc_setup_hevc_config(AVCodecContext *avctx) if (ctx->intra_refresh) { hevc->enableIntraRefresh = 1; - hevc->intraRefreshPeriod = avctx->gop_size; - hevc->intraRefreshCnt = avctx->gop_size - 1; + hevc->intraRefreshPeriod = cc->gopLength; + hevc->intraRefreshCnt = cc->gopLength - 1; #ifdef NVENC_HAVE_SINGLE_SLICE_INTRA_REFRESH hevc->singleSliceIntraRefresh = ctx->single_slice_intra_refresh; #endif @@ -1318,8 +1318,8 @@ static av_cold int nvenc_setup_hevc_config(AVCodecContext *avctx) if (ctx->intra_refresh) { hevc->idrPeriod = NVENC_INFINITE_GOPLENGTH; - } else if (avctx->gop_size >= 0) { - hevc->idrPeriod = avctx->gop_size; + } else if (cc->gopLength > 0) { + hevc->idrPeriod = cc->gopLength; } if (IS_CBR(cc->rcParams.rateControlMode)) { @@ -1413,12 +1413,12 @@ static av_cold int nvenc_setup_av1_config(AVCodecContext *avctx) if (ctx->intra_refresh) { av1->enableIntraRefresh = 1; - av1->intraRefreshPeriod = avctx->gop_size; - av1->intraRefreshCnt = avctx->gop_size - 1; + av1->intraRefreshPeriod = cc->gopLength; + av1->intraRefreshCnt = cc->gopLength - 1; av1->idrPeriod = NVENC_INFINITE_GOPLENGTH; - } else if (avctx->gop_size >= 0) { - av1->idrPeriod = avctx->gop_size; + } else if (cc->gopLength > 0) { + av1->idrPeriod = cc->gopLength; } if (IS_CBR(cc->rcParams.rateControlMode)) { @@ -1603,17 +1603,18 @@ FF_ENABLE_DEPRECATION_WARNINGS } if (avctx->gop_size > 0) { - if (avctx->max_b_frames >= 0) { - /* 0 is intra-only, 1 is I/P only, 2 is one B-Frame, 3 two B-frames, and so on. */ - ctx->encode_config.frameIntervalP = avctx->max_b_frames + 1; - } - + // only overwrite preset if a GOP size was selected as input ctx->encode_config.gopLength = avctx->gop_size; } else if (avctx->gop_size == 0) { ctx->encode_config.frameIntervalP = 0; ctx->encode_config.gopLength = 1; } + if (avctx->max_b_frames >= 0 && ctx->encode_config.gopLength > 1) { + /* 0 is intra-only, 1 is I/P only, 2 is one B-Frame, 3 two B-frames, and so on. */ + ctx->encode_config.frameIntervalP = avctx->max_b_frames + 1; + } + /* force to enable intra refresh */ if(ctx->single_slice_intra_refresh) ctx->intra_refresh = 1; diff --git a/libavcodec/nvenc_av1.c b/libavcodec/nvenc_av1.c index 2b349c7b61f..43643f7bf1a 100644 --- a/libavcodec/nvenc_av1.c +++ b/libavcodec/nvenc_av1.c @@ -154,7 +154,7 @@ static const FFCodecDefault defaults[] = { { "qdiff", "-1" }, { "qblur", "-1" }, { "qcomp", "-1" }, - { "g", "250" }, + { "g", "-1" }, { "bf", "-1" }, { "refs", "0" }, { NULL }, diff --git a/libavcodec/nvenc_h264.c b/libavcodec/nvenc_h264.c index 698615855bf..a99860998e7 100644 --- a/libavcodec/nvenc_h264.c +++ b/libavcodec/nvenc_h264.c @@ -218,7 +218,7 @@ static const FFCodecDefault defaults[] = { { "qdiff", "-1" }, { "qblur", "-1" }, { "qcomp", "-1" }, - { "g", "250" }, + { "g", "-1" }, { "bf", "-1" }, { "refs", "0" }, { NULL }, diff --git a/libavcodec/nvenc_hevc.c b/libavcodec/nvenc_hevc.c index d99077f1705..a02f277888c 100644 --- a/libavcodec/nvenc_hevc.c +++ b/libavcodec/nvenc_hevc.c @@ -199,7 +199,7 @@ static const FFCodecDefault defaults[] = { { "qdiff", "-1" }, { "qblur", "-1" }, { "qcomp", "-1" }, - { "g", "250" }, + { "g", "-1" }, { "bf", "-1" }, { "refs", "0" }, { NULL }, From e6359b0cc1e04d5586612665a5aa174deaa7bacb Mon Sep 17 00:00:00 2001 From: James Almer Date: Tue, 20 Jun 2023 20:26:48 -0300 Subject: [PATCH 1651/2172] avcodec/evc_frame_merge: properly support packets with more than one NALU Parse through all NALUs in a packet, pull new ones when a complete AU could not be assembled, or keep them around if an AU was assembled while data remained in them. Signed-off-by: James Almer --- libavcodec/evc_frame_merge_bsf.c | 112 ++++++++++++++++++++----------- 1 file changed, 71 insertions(+), 41 deletions(-) diff --git a/libavcodec/evc_frame_merge_bsf.c b/libavcodec/evc_frame_merge_bsf.c index a9b44f4d101..18daa725161 100644 --- a/libavcodec/evc_frame_merge_bsf.c +++ b/libavcodec/evc_frame_merge_bsf.c @@ -70,30 +70,14 @@ static void evc_frame_merge_flush(AVBSFContext *bsf) ctx->au_buffer.data_size = 0; } -static int evc_frame_merge_filter(AVBSFContext *bsf, AVPacket *out) +static int parse_nal_unit(AVBSFContext *bsf, const uint8_t *buf, int buf_size) { EVCFMergeContext *ctx = bsf->priv_data; - AVPacket *in = ctx->in; - uint8_t *buffer; GetBitContext gb; enum EVCNALUnitType nalu_type; - uint32_t nalu_size; - int tid, au_end_found = 0; - int err; + int tid, err; - err = ff_bsf_get_packet_ref(bsf, in); - if (err < 0) - return err; - - // NAL unit parsing needed to determine if end of AU was found - nalu_size = evc_read_nal_unit_length(in->data, EVC_NALU_LENGTH_PREFIX_SIZE, bsf); - if (!nalu_size || nalu_size > INT_MAX) { - av_log(bsf, AV_LOG_ERROR, "Invalid NAL unit size: (%d)\n", nalu_size); - err = AVERROR_INVALIDDATA; - goto end; - } - - err = init_get_bits8(&gb, in->data + EVC_NALU_LENGTH_PREFIX_SIZE, nalu_size); + err = init_get_bits8(&gb, buf, buf_size); if (err < 0) return err; @@ -101,15 +85,13 @@ static int evc_frame_merge_filter(AVBSFContext *bsf, AVPacket *out) // @see enum EVCNALUnitType in evc.h if (get_bits1(&gb)) {// forbidden_zero_bit av_log(bsf, AV_LOG_ERROR, "Invalid NAL unit header\n"); - err = AVERROR_INVALIDDATA; - goto end; + return AVERROR_INVALIDDATA; } nalu_type = get_bits(&gb, 6) - 1; if (nalu_type < EVC_NOIDR_NUT || nalu_type > EVC_UNSPEC_NUT62) { av_log(bsf, AV_LOG_ERROR, "Invalid NAL unit type: (%d)\n", nalu_type); - err = AVERROR_INVALIDDATA; - goto end; + return AVERROR_INVALIDDATA; } tid = get_bits(&gb, 3); @@ -121,14 +103,14 @@ static int evc_frame_merge_filter(AVBSFContext *bsf, AVPacket *out) err = ff_evc_parse_sps(&gb, &ctx->ps); if (err < 0) { av_log(bsf, AV_LOG_ERROR, "SPS parsing error\n"); - goto end; + return err; } break; case EVC_PPS_NUT: err = ff_evc_parse_pps(&gb, &ctx->ps); if (err < 0) { av_log(bsf, AV_LOG_ERROR, "PPS parsing error\n"); - goto end; + return err; } break; case EVC_IDR_NUT: // Coded slice of a IDR or non-IDR picture @@ -138,16 +120,16 @@ static int evc_frame_merge_filter(AVBSFContext *bsf, AVPacket *out) err = ff_evc_parse_slice_header(&gb, &sh, &ctx->ps, nalu_type); if (err < 0) { av_log(bsf, AV_LOG_ERROR, "Slice header parsing error\n"); - goto end; + return err; } // POC (picture order count of the current picture) derivation // @see ISO/IEC 23094-1:2020(E) 8.3.1 Decoding process for picture order count err = ff_evc_derive_poc(&ctx->ps, &sh, &ctx->poc, nalu_type, tid); if (err < 0) - goto end; + return err; - au_end_found = end_of_access_unit_found(&ctx->ps, &sh, &ctx->poc, nalu_type); + return end_of_access_unit_found(&ctx->ps, &sh, &ctx->poc, nalu_type); break; } @@ -158,8 +140,56 @@ static int evc_frame_merge_filter(AVBSFContext *bsf, AVPacket *out) break; } + return 0; +} + +static int evc_frame_merge_filter(AVBSFContext *bsf, AVPacket *out) +{ + EVCFMergeContext *ctx = bsf->priv_data; + AVPacket *in = ctx->in; + size_t data_size; + int au_end_found = 0, err; + + while (!au_end_found) { + uint8_t *buffer; + uint32_t nalu_size; + + if (!in->size) { + av_packet_unref(in); + err = ff_bsf_get_packet_ref(bsf, in); + if (err < 0) { + if (err == AVERROR_EOF && ctx->au_buffer.data_size > 0) + break; + return err; + } + } + + // Buffer size is not enough for buffer to store NAL unit 4-bytes prefix (length) + if (in->size < EVC_NALU_LENGTH_PREFIX_SIZE) + return AVERROR_INVALIDDATA; + + nalu_size = evc_read_nal_unit_length(in->data, EVC_NALU_LENGTH_PREFIX_SIZE, bsf); + if (!nalu_size || nalu_size > INT_MAX) { + av_log(bsf, AV_LOG_ERROR, "Invalid NAL unit size: (%u)\n", nalu_size); + err = AVERROR_INVALIDDATA; + goto end; + } + + if (in->size < nalu_size + EVC_NALU_LENGTH_PREFIX_SIZE) { + err = AVERROR_INVALIDDATA; + goto end; + } + + err = parse_nal_unit(bsf, in->data + EVC_NALU_LENGTH_PREFIX_SIZE, nalu_size); + if (err < 0) { + av_log(bsf, AV_LOG_ERROR, "Parsing of NAL unit failed\n"); + goto end; + } + au_end_found = err; + + nalu_size += EVC_NALU_LENGTH_PREFIX_SIZE; buffer = av_fast_realloc(ctx->au_buffer.data, &ctx->au_buffer.capacity, - ctx->au_buffer.data_size + in->size); + ctx->au_buffer.data_size + nalu_size); if (!buffer) { av_freep(&ctx->au_buffer.data); err = AVERROR_INVALIDDATA; @@ -167,30 +197,30 @@ static int evc_frame_merge_filter(AVBSFContext *bsf, AVPacket *out) } ctx->au_buffer.data = buffer; - memcpy(ctx->au_buffer.data + ctx->au_buffer.data_size, in->data, in->size); + memcpy(ctx->au_buffer.data + ctx->au_buffer.data_size, in->data, nalu_size); - ctx->au_buffer.data_size += in->size; + ctx->au_buffer.data_size += nalu_size; - av_packet_unref(in); + in->data += nalu_size; + in->size -= nalu_size; + } - if (au_end_found) { - size_t data_size = ctx->au_buffer.data_size; + av_packet_unref(in); + data_size = ctx->au_buffer.data_size; ctx->au_buffer.data_size = 0; err = av_new_packet(out, data_size); if (err < 0) - return err; + goto end; memcpy(out->data, ctx->au_buffer.data, data_size); - } else - err = AVERROR(EAGAIN); - - if (err < 0 && err != AVERROR(EAGAIN)) - ctx->au_buffer.data_size = 0; + err = 0; end: - if (err < 0) + if (err < 0) { av_packet_unref(in); + ctx->au_buffer.data_size = 0; + } return err; } From daf61a706a4e6abe802d75957a1708259bd439d6 Mon Sep 17 00:00:00 2001 From: James Almer Date: Tue, 20 Jun 2023 22:13:43 -0300 Subject: [PATCH 1652/2172] avcodec/evc_frame_merge: reindent after previous commit Signed-off-by: James Almer --- libavcodec/evc_frame_merge_bsf.c | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/libavcodec/evc_frame_merge_bsf.c b/libavcodec/evc_frame_merge_bsf.c index 18daa725161..27fe65946d8 100644 --- a/libavcodec/evc_frame_merge_bsf.c +++ b/libavcodec/evc_frame_merge_bsf.c @@ -188,18 +188,18 @@ static int evc_frame_merge_filter(AVBSFContext *bsf, AVPacket *out) au_end_found = err; nalu_size += EVC_NALU_LENGTH_PREFIX_SIZE; - buffer = av_fast_realloc(ctx->au_buffer.data, &ctx->au_buffer.capacity, - ctx->au_buffer.data_size + nalu_size); - if (!buffer) { - av_freep(&ctx->au_buffer.data); - err = AVERROR_INVALIDDATA; - goto end; - } + buffer = av_fast_realloc(ctx->au_buffer.data, &ctx->au_buffer.capacity, + ctx->au_buffer.data_size + nalu_size); + if (!buffer) { + av_freep(&ctx->au_buffer.data); + err = AVERROR_INVALIDDATA; + goto end; + } - ctx->au_buffer.data = buffer; - memcpy(ctx->au_buffer.data + ctx->au_buffer.data_size, in->data, nalu_size); + ctx->au_buffer.data = buffer; + memcpy(ctx->au_buffer.data + ctx->au_buffer.data_size, in->data, nalu_size); - ctx->au_buffer.data_size += nalu_size; + ctx->au_buffer.data_size += nalu_size; in->data += nalu_size; in->size -= nalu_size; @@ -208,12 +208,12 @@ static int evc_frame_merge_filter(AVBSFContext *bsf, AVPacket *out) av_packet_unref(in); data_size = ctx->au_buffer.data_size; - ctx->au_buffer.data_size = 0; - err = av_new_packet(out, data_size); - if (err < 0) - goto end; + ctx->au_buffer.data_size = 0; + err = av_new_packet(out, data_size); + if (err < 0) + goto end; - memcpy(out->data, ctx->au_buffer.data, data_size); + memcpy(out->data, ctx->au_buffer.data, data_size); err = 0; end: From 98346606015c309305587457f0197013df64872c Mon Sep 17 00:00:00 2001 From: James Almer Date: Tue, 20 Jun 2023 20:50:48 -0300 Subject: [PATCH 1653/2172] avcodec/evc_frame_merge: copy input packet props to output Signed-off-by: James Almer --- libavcodec/evc_frame_merge_bsf.c | 24 +++++++++++++++++++++--- 1 file changed, 21 insertions(+), 3 deletions(-) diff --git a/libavcodec/evc_frame_merge_bsf.c b/libavcodec/evc_frame_merge_bsf.c index 27fe65946d8..121f93c0b0d 100644 --- a/libavcodec/evc_frame_merge_bsf.c +++ b/libavcodec/evc_frame_merge_bsf.c @@ -34,7 +34,7 @@ typedef struct AccessUnitBuffer { } AccessUnitBuffer; typedef struct EVCFMergeContext { - AVPacket *in; + AVPacket *in, *buffer_pkt; EVCParamSets ps; EVCParserPoc poc; AccessUnitBuffer au_buffer; @@ -67,6 +67,7 @@ static void evc_frame_merge_flush(AVBSFContext *bsf) ff_evc_ps_free(&ctx->ps); av_packet_unref(ctx->in); + av_packet_unref(ctx->buffer_pkt); ctx->au_buffer.data_size = 0; } @@ -146,7 +147,7 @@ static int parse_nal_unit(AVBSFContext *bsf, const uint8_t *buf, int buf_size) static int evc_frame_merge_filter(AVBSFContext *bsf, AVPacket *out) { EVCFMergeContext *ctx = bsf->priv_data; - AVPacket *in = ctx->in; + AVPacket *in = ctx->in, *buffer_pkt = ctx->buffer_pkt; size_t data_size; int au_end_found = 0, err; @@ -162,6 +163,16 @@ static int evc_frame_merge_filter(AVBSFContext *bsf, AVPacket *out) break; return err; } + /* Buffer packets with timestamps (there should be at most one per AU) + * or any packet if buffer_pkt is empty. The latter is needed to + * passthrough positions in case there are no timestamps like with + * the raw EVC demuxer. */ + if (!buffer_pkt->data || + in->pts != AV_NOPTS_VALUE && buffer_pkt->pts == AV_NOPTS_VALUE) { + err = av_packet_ref(buffer_pkt, in); + if (err < 0) + goto end; + } } // Buffer size is not enough for buffer to store NAL unit 4-bytes prefix (length) @@ -210,15 +221,20 @@ static int evc_frame_merge_filter(AVBSFContext *bsf, AVPacket *out) ctx->au_buffer.data_size = 0; err = av_new_packet(out, data_size); + if (err < 0) + goto end; + err = av_packet_copy_props(out, buffer_pkt); if (err < 0) goto end; + av_packet_unref(buffer_pkt); memcpy(out->data, ctx->au_buffer.data, data_size); err = 0; end: if (err < 0) { av_packet_unref(in); + av_packet_unref(buffer_pkt); ctx->au_buffer.data_size = 0; } return err; @@ -229,7 +245,8 @@ static int evc_frame_merge_init(AVBSFContext *bsf) EVCFMergeContext *ctx = bsf->priv_data; ctx->in = av_packet_alloc(); - if (!ctx->in) + ctx->buffer_pkt = av_packet_alloc(); + if (!ctx->in || !ctx->buffer_pkt) return AVERROR(ENOMEM); return 0; @@ -240,6 +257,7 @@ static void evc_frame_merge_close(AVBSFContext *bsf) EVCFMergeContext *ctx = bsf->priv_data; av_packet_free(&ctx->in); + av_packet_free(&ctx->buffer_pkt); ff_evc_ps_free(&ctx->ps); ctx->au_buffer.capacity = 0; From 25ce1c8333337ca27cd0ca54da2179f122a0dc83 Mon Sep 17 00:00:00 2001 From: James Almer Date: Tue, 20 Jun 2023 17:25:58 -0300 Subject: [PATCH 1654/2172] avformat/id3v2: check the return value of avio_close_dyn_buf() Fixes ticket #10424. Reviewed-by: Michael Niedermayer Signed-off-by: James Almer --- libavformat/id3v2.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/libavformat/id3v2.c b/libavformat/id3v2.c index cb318640455..38c86a8e79e 100644 --- a/libavformat/id3v2.c +++ b/libavformat/id3v2.c @@ -246,7 +246,7 @@ static int decode_str(AVFormatContext *s, AVIOContext *pb, int encoding, int ret; uint8_t tmp; uint32_t ch = 1; - int left = *maxread; + int left = *maxread, dynsize; unsigned int (*get)(AVIOContext*) = avio_rb16; AVIOContext *dynbuf; @@ -308,7 +308,9 @@ static int decode_str(AVFormatContext *s, AVIOContext *pb, int encoding, if (ch) avio_w8(dynbuf, 0); - avio_close_dyn_buf(dynbuf, dst); + dynsize = avio_close_dyn_buf(dynbuf, dst); + if (dynsize <= 0) + return AVERROR(ENOMEM); *maxread = left; return 0; From a4bf559683a999c8faa408fdd8f29bd28a6a47ea Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Sun, 18 Jun 2023 21:00:03 +0200 Subject: [PATCH 1655/2172] avcodec/utils: fix 2 integer overflows in get_audio_frame_duration() Fixes: signed integer overflow: 256 * 668003712 cannot be represented in type 'int' Fixes: 59819/clusterfuzz-testcase-minimized-ffmpeg_dem_MATROSKA_fuzzer-4674636538052608 Found-by: continuous fuzzing process https://github.com/google/oss-fuzz/tree/master/projects/ffmpeg Signed-off-by: Michael Niedermayer --- libavcodec/utils.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libavcodec/utils.c b/libavcodec/utils.c index a8514ba6c17..672eb15d982 100644 --- a/libavcodec/utils.c +++ b/libavcodec/utils.c @@ -641,9 +641,9 @@ static int get_audio_frame_duration(enum AVCodecID id, int sr, int ch, int ba, if (sr > 0) { /* calc from sample rate */ if (id == AV_CODEC_ID_TTA) - return 256 * sr / 245; + return 256ll * sr / 245; else if (id == AV_CODEC_ID_DST) - return 588 * sr / 44100; + return 588ll * sr / 44100; else if (id == AV_CODEC_ID_BINKAUDIO_DCT) { if (sr / 22050 > 22) return 0; From 043a9d09cbcd34c5afdb4c2ff92c06ed8c5d8054 Mon Sep 17 00:00:00 2001 From: caleb Date: Wed, 7 Jun 2023 10:34:34 +0300 Subject: [PATCH 1656/2172] avcodec/jpeg2000htdec: Check for invalid magref length. Fixes: shift exponent -8 is negative Fixes: 58328/clusterfuzz-testcase-minimized-ffmpeg_AV_CODEC_ID_JPEG2000_fuzzer-6007789196804096 Found-by: continuous fuzzing process https://github.com/google/oss-fuzz/tree/master/projects/ffmpeg Signed-off-by: Michael Niedermayer --- libavcodec/jpeg2000htdec.c | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/libavcodec/jpeg2000htdec.c b/libavcodec/jpeg2000htdec.c index 51cd96e0f1c..4c4e54710d5 100644 --- a/libavcodec/jpeg2000htdec.c +++ b/libavcodec/jpeg2000htdec.c @@ -1101,8 +1101,9 @@ static void jpeg2000_decode_sigprop_segment(Jpeg2000Cblk *cblk, uint16_t width, * See procedure decodeSigPropMag at Rec. ITU-T T.814, 7.5. */ static int -jpeg2000_decode_magref_segment(Jpeg2000Cblk *cblk, uint16_t width, uint16_t block_height, uint8_t *magref_segment, - uint32_t magref_length, uint8_t pLSB, int32_t *sample_buf, uint8_t *block_states) +jpeg2000_decode_magref_segment( uint16_t width, uint16_t block_height, + uint8_t *magref_segment,uint32_t magref_length, + uint8_t pLSB, int32_t *sample_buf, uint8_t *block_states) { StateVars mag_ref = { 0 }; @@ -1260,10 +1261,17 @@ ff_jpeg2000_decode_htj2k(const Jpeg2000DecoderContext *s, Jpeg2000CodingStyle *c jpeg2000_decode_sigprop_segment(cblk, width, height, Dref, Lref, pLSB - 1, sample_buf, block_states); - if (cblk->npasses > 2) - if ((ret = jpeg2000_decode_magref_segment(cblk, width, height, Dref, Lref, - pLSB - 1, sample_buf, block_states)) < 0) + if (cblk->npasses > 2) { + + if (Lref < 2){ + av_log(s->avctx,AV_LOG_ERROR,"Invalid magnitude refinement length\n"); + ret = AVERROR_INVALIDDATA; + goto free; + } + if ((ret = jpeg2000_decode_magref_segment(width, height, Dref, Lref, + pLSB - 1, sample_buf, block_states)) < 0) goto free; + } pLSB = 31 - M_b; From fe167bae969cf2deac2f5c480fc5c5ac5f8e6267 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Tue, 20 Jun 2023 00:20:40 +0200 Subject: [PATCH 1657/2172] tools/target_dec_fuzzer: Adjust threshold for speex Fixes: Timeout Fixes: 59731/clusterfuzz-testcase-minimized-ffmpeg_AV_CODEC_ID_SPEEX_fuzzer-4809436670328832 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 42de479829b..165951dc9d5 100644 --- a/tools/target_dec_fuzzer.c +++ b/tools/target_dec_fuzzer.c @@ -278,6 +278,7 @@ int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { case AV_CODEC_ID_SCPR: maxpixels /= 32; break; case AV_CODEC_ID_SCREENPRESSO:maxpixels /= 64; break; case AV_CODEC_ID_SIMBIOSIS_IMX:maxpixels /= 16384; break; + case AV_CODEC_ID_SPEEX: maxsamples /= 128; break; case AV_CODEC_ID_SMACKAUDIO: maxsamples /= 4096; break; case AV_CODEC_ID_SMACKVIDEO: maxpixels /= 64; break; case AV_CODEC_ID_SNOW: maxpixels /= 128; break; From d84677abd8ffb8ca8ad94eced6d9e03928f35d79 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Tue, 20 Jun 2023 00:59:40 +0200 Subject: [PATCH 1658/2172] avutil/softfloat: fix av_sincos_sf() Signed-off-by: Michael Niedermayer --- libavutil/softfloat.h | 2 +- libavutil/tests/softfloat.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/libavutil/softfloat.h b/libavutil/softfloat.h index a651406f749..1520027ddc7 100644 --- a/libavutil/softfloat.h +++ b/libavutil/softfloat.h @@ -281,7 +281,7 @@ static av_unused void av_sincos_sf(int a, int *s, int *c) (int64_t)av_sintbl_4_sf[(idx & 0x1f) + 1] * (a & 0x7ff) + 0x400) >> 11); - *c = (int)(((int64_t)cv * ct + (int64_t)sv * st + 0x20000000) >> 30); + *c = (int)(((int64_t)cv * ct - (int64_t)sv * st + 0x20000000) >> 30); *s = (int)(((int64_t)cv * st + (int64_t)sv * ct + 0x20000000) >> 30); } diff --git a/libavutil/tests/softfloat.c b/libavutil/tests/softfloat.c index c06de449334..a2e628fe81b 100644 --- a/libavutil/tests/softfloat.c +++ b/libavutil/tests/softfloat.c @@ -148,7 +148,7 @@ int main(void){ av_sincos_sf(i*(1ULL<<32)/36/4, &s, &c); errs = (double)s/ (1<<30) - sin(i*M_PI/36); errc = (double)c/ (1<<30) - cos(i*M_PI/36); - if (fabs(errs) > 0.00000002 || fabs(errc) >0.001) { + if (fabs(errs) > 0.000000004 || fabs(errc) >0.000000004) { printf("sincos FAIL %d %f %f %f %f\n", i, (float)s/ (1<<30), (float)c/ (1<<30), sin(i*M_PI/36), cos(i*M_PI/36)); } From 4aa1a42a91438b7107d2d77db1fc5ca95c27740c Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Tue, 20 Jun 2023 01:26:33 +0200 Subject: [PATCH 1659/2172] avutil/softfloat: Basic documentation for av_sincos_sf() Signed-off-by: Michael Niedermayer --- libavutil/softfloat.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/libavutil/softfloat.h b/libavutil/softfloat.h index 1520027ddc7..399ca6d6829 100644 --- a/libavutil/softfloat.h +++ b/libavutil/softfloat.h @@ -236,6 +236,10 @@ static av_always_inline SoftFloat av_sqrt_sf(SoftFloat val) /** * Rounding-to-nearest used. + * + * @param a angle in units of (1ULL<<30)/M_PI radians + * @param s pointer to where sine in units of (1<<30) is returned + * @param c pointer to where cosine in units of (1<<30) is returned */ static av_unused void av_sincos_sf(int a, int *s, int *c) { From b1b45ac9d445752e7cb0e10b2b9ee9aa4023e3a0 Mon Sep 17 00:00:00 2001 From: James Almer Date: Wed, 21 Jun 2023 17:10:47 -0300 Subject: [PATCH 1660/2172] avcodec/evc_frame_merge: ensure the assembled buffer fits in an AVPacket Signed-off-by: James Almer --- libavcodec/evc_frame_merge_bsf.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/libavcodec/evc_frame_merge_bsf.c b/libavcodec/evc_frame_merge_bsf.c index 121f93c0b0d..3e1258c6c9f 100644 --- a/libavcodec/evc_frame_merge_bsf.c +++ b/libavcodec/evc_frame_merge_bsf.c @@ -199,8 +199,16 @@ static int evc_frame_merge_filter(AVBSFContext *bsf, AVPacket *out) au_end_found = err; nalu_size += EVC_NALU_LENGTH_PREFIX_SIZE; + + data_size = ctx->au_buffer.data_size + nalu_size; + if (data_size > INT_MAX - AV_INPUT_BUFFER_PADDING_SIZE) { + av_log(bsf, AV_LOG_ERROR, "Assembled packet is too big\n"); + err = AVERROR(ERANGE); + goto end; + } + buffer = av_fast_realloc(ctx->au_buffer.data, &ctx->au_buffer.capacity, - ctx->au_buffer.data_size + nalu_size); + data_size); if (!buffer) { av_freep(&ctx->au_buffer.data); err = AVERROR_INVALIDDATA; @@ -210,7 +218,7 @@ static int evc_frame_merge_filter(AVBSFContext *bsf, AVPacket *out) ctx->au_buffer.data = buffer; memcpy(ctx->au_buffer.data + ctx->au_buffer.data_size, in->data, nalu_size); - ctx->au_buffer.data_size += nalu_size; + ctx->au_buffer.data_size = data_size; in->data += nalu_size; in->size -= nalu_size; From d0fc1b3507c277977201f3291c8f7c02f23fdfd6 Mon Sep 17 00:00:00 2001 From: James Almer Date: Thu, 22 Jun 2023 10:31:01 -0300 Subject: [PATCH 1661/2172] avformat/evc: remove unnecessary struct And don't use get_ue_golomb_long() for known small values. Signed-off-by: James Almer --- libavformat/evc.c | 67 ++++++++++------------------------------------- 1 file changed, 14 insertions(+), 53 deletions(-) diff --git a/libavformat/evc.c b/libavformat/evc.c index f6e53aa6cf9..1c72b141bd4 100644 --- a/libavformat/evc.c +++ b/libavformat/evc.c @@ -41,35 +41,6 @@ enum { NB_ARRAYS }; -// The sturcture reflects SPS RBSP(raw byte sequence payload) layout -// @see ISO_IEC_23094-1 section 7.3.2.1 -// -// The following descriptors specify the parsing process of each element -// u(n) - unsigned integer using n bits -// ue(v) - unsigned integer 0-th order Exp_Golomb-coded syntax element with the left bit first -typedef struct EVCSPS { - int sps_seq_parameter_set_id; // ue(v) - int profile_idc; // u(8) - int level_idc; // u(8) - int toolset_idc_h; // u(32) - int toolset_idc_l; // u(32) - int chroma_format_idc; // ue(v) - int pic_width_in_luma_samples; // ue(v) - int pic_height_in_luma_samples; // ue(v) - int bit_depth_luma_minus8; // ue(v) - int bit_depth_chroma_minus8; // ue(v) - - // @note - // Currently the structure does not reflect the entire SPS RBSP layout. - // It contains only the fields that are necessary to read from the NAL unit all the values - // necessary for the correct initialization of EVCDecoderConfigurationRecord - - // @note - // If necessary, add the missing fields to the structure to reflect - // the contents of the entire NAL unit of the SPS type - -} EVCSPS; - // @see ISO/IEC 14496-15:2021 Coding of audio-visual objects - Part 15: section 12.3.3.3 typedef struct EVCNALUnitArray { uint8_t array_completeness; // when equal to 1 indicates that all NAL units of the given type are in the following array @@ -116,7 +87,7 @@ typedef struct NALUList { static int evcc_parse_sps(const uint8_t *bs, int bs_size, EVCDecoderConfigurationRecord *evcc) { GetBitContext gb; - EVCSPS sps; + unsigned sps_seq_parameter_set_id; bs += EVC_NALU_HEADER_SIZE; bs_size -= EVC_NALU_HEADER_SIZE; @@ -124,41 +95,31 @@ static int evcc_parse_sps(const uint8_t *bs, int bs_size, EVCDecoderConfiguratio if (init_get_bits8(&gb, bs, bs_size) < 0) return 0; - sps.sps_seq_parameter_set_id = get_ue_golomb_long(&gb); + sps_seq_parameter_set_id = get_ue_golomb_31(&gb); - if (sps.sps_seq_parameter_set_id >= EVC_MAX_SPS_COUNT) + if (sps_seq_parameter_set_id >= EVC_MAX_SPS_COUNT) return 0; // the Baseline profile is indicated by profile_idc eqal to 0 // the Main profile is indicated by profile_idc eqal to 1 - sps.profile_idc = get_bits(&gb, 8); + evcc->profile_idc = get_bits(&gb, 8); - sps.level_idc = get_bits(&gb, 8); + evcc->level_idc = get_bits(&gb, 8); - sps.toolset_idc_h = get_bits_long(&gb, 32); - sps.toolset_idc_l = get_bits_long(&gb, 32); + evcc->toolset_idc_h = get_bits_long(&gb, 32); + evcc->toolset_idc_l = get_bits_long(&gb, 32); // 0 - monochrome // 1 - 4:2:0 // 2 - 4:2:2 // 3 - 4:4:4 - sps.chroma_format_idc = get_ue_golomb_long(&gb); - - sps.pic_width_in_luma_samples = get_ue_golomb_long(&gb); - sps.pic_height_in_luma_samples = get_ue_golomb_long(&gb); - - sps.bit_depth_luma_minus8 = get_ue_golomb_long(&gb); - sps.bit_depth_chroma_minus8 = get_ue_golomb_long(&gb); - - evcc->profile_idc = sps.profile_idc; - evcc->level_idc = sps.level_idc; - evcc->toolset_idc_h = sps.toolset_idc_h; - evcc->toolset_idc_l = sps.toolset_idc_l; - evcc->chroma_format_idc = sps.chroma_format_idc; - evcc->bit_depth_luma_minus8 = sps.bit_depth_luma_minus8; - evcc->bit_depth_chroma_minus8 = sps.bit_depth_chroma_minus8; - evcc->pic_width_in_luma_samples = sps.pic_width_in_luma_samples; - evcc->pic_height_in_luma_samples = sps.pic_height_in_luma_samples; + evcc->chroma_format_idc = get_ue_golomb_31(&gb); + + evcc->pic_width_in_luma_samples = get_ue_golomb_long(&gb); + evcc->pic_height_in_luma_samples = get_ue_golomb_long(&gb); + + evcc->bit_depth_luma_minus8 = get_ue_golomb_31(&gb); + evcc->bit_depth_chroma_minus8 = get_ue_golomb_31(&gb); return 0; } From 552879d6216413539b5de79f319266b544c4f5ca Mon Sep 17 00:00:00 2001 From: James Almer Date: Thu, 22 Jun 2023 10:31:11 -0300 Subject: [PATCH 1662/2172] avformat/evc: remove duplicate check Signed-off-by: James Almer --- libavformat/evc.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/libavformat/evc.c b/libavformat/evc.c index 1c72b141bd4..9d0fe8d84cf 100644 --- a/libavformat/evc.c +++ b/libavformat/evc.c @@ -226,9 +226,6 @@ static int evcc_write(AVIOContext *pb, EVCDecoderConfigurationRecord *evcc) if (!sps_count || sps_count > EVC_MAX_SPS_COUNT) return AVERROR_INVALIDDATA; - if (!sps_count || sps_count > EVC_MAX_SPS_COUNT) - return AVERROR_INVALIDDATA; - /* unsigned int(8) configurationVersion = 1; */ avio_w8(pb, evcc->configurationVersion); From 3d1199dff63dcfe75df15a0250ddd0361cafa150 Mon Sep 17 00:00:00 2001 From: James Almer Date: Thu, 22 Jun 2023 10:44:44 -0300 Subject: [PATCH 1663/2172] avformat/evc: add range checks to evcc_parse_sps and return proper error codes Signed-off-by: James Almer --- libavformat/evc.c | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/libavformat/evc.c b/libavformat/evc.c index 9d0fe8d84cf..287e5f8b28b 100644 --- a/libavformat/evc.c +++ b/libavformat/evc.c @@ -88,17 +88,19 @@ static int evcc_parse_sps(const uint8_t *bs, int bs_size, EVCDecoderConfiguratio { GetBitContext gb; unsigned sps_seq_parameter_set_id; + int ret; bs += EVC_NALU_HEADER_SIZE; bs_size -= EVC_NALU_HEADER_SIZE; - if (init_get_bits8(&gb, bs, bs_size) < 0) - return 0; + ret = init_get_bits8(&gb, bs, bs_size); + if (ret < 0) + return ret; sps_seq_parameter_set_id = get_ue_golomb_31(&gb); if (sps_seq_parameter_set_id >= EVC_MAX_SPS_COUNT) - return 0; + return AVERROR_INVALIDDATA; // the Baseline profile is indicated by profile_idc eqal to 0 // the Main profile is indicated by profile_idc eqal to 1 @@ -114,12 +116,17 @@ static int evcc_parse_sps(const uint8_t *bs, int bs_size, EVCDecoderConfiguratio // 2 - 4:2:2 // 3 - 4:4:4 evcc->chroma_format_idc = get_ue_golomb_31(&gb); + if (evcc->chroma_format_idc > 3) + return AVERROR_INVALIDDATA; evcc->pic_width_in_luma_samples = get_ue_golomb_long(&gb); evcc->pic_height_in_luma_samples = get_ue_golomb_long(&gb); evcc->bit_depth_luma_minus8 = get_ue_golomb_31(&gb); evcc->bit_depth_chroma_minus8 = get_ue_golomb_31(&gb); + // EVCDecoderConfigurationRecord can't store values > 7. Limit it to bit depth 14. + if (evcc->bit_depth_luma_minus8 > 6 || evcc->bit_depth_chroma_minus8 > 6) + return AVERROR_INVALIDDATA; return 0; } From 528dd5637d9a306e74a9f1455acd2e4a0718b3e9 Mon Sep 17 00:00:00 2001 From: James Almer Date: Thu, 22 Jun 2023 11:04:34 -0300 Subject: [PATCH 1664/2172] avformat/evc: remove duplicate defines Signed-off-by: James Almer --- libavformat/evc.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/libavformat/evc.c b/libavformat/evc.c index 287e5f8b28b..a4fa42d9026 100644 --- a/libavformat/evc.c +++ b/libavformat/evc.c @@ -28,10 +28,6 @@ #include "evc.h" #include "avio_internal.h" -// The length field that indicates the length in bytes of the following NAL unit is configured to be of 4 bytes -#define EVC_NALU_LENGTH_PREFIX_SIZE (4) /* byte */ -#define EVC_NALU_HEADER_SIZE (2) /* byte */ - // @see ISO/IEC 14496-15:2021 Coding of audio-visual objects - Part 15: section 12.3.3.1 enum { SPS_INDEX, From 5b966be5b8a4272d51a7486375072e45bdaa8acf Mon Sep 17 00:00:00 2001 From: James Almer Date: Thu, 22 Jun 2023 19:46:22 -0300 Subject: [PATCH 1665/2172] avcodec/evc_parse: use unsigned types in structs where corresponds Signed-off-by: James Almer --- libavcodec/evc_parse.c | 12 ++++++------ libavcodec/evc_parse.h | 42 +++++++++++++++++++++--------------------- 2 files changed, 27 insertions(+), 27 deletions(-) diff --git a/libavcodec/evc_parse.c b/libavcodec/evc_parse.c index eff4b7bc38c..447f6195c23 100644 --- a/libavcodec/evc_parse.c +++ b/libavcodec/evc_parse.c @@ -28,11 +28,11 @@ int ff_evc_parse_slice_header(GetBitContext *gb, EVCParserSliceHeader *sh, const EVCParserPPS *pps; const EVCParserSPS *sps; int num_tiles_in_slice = 0; - int slice_pic_parameter_set_id; + unsigned slice_pic_parameter_set_id; - slice_pic_parameter_set_id = get_ue_golomb(gb); + slice_pic_parameter_set_id = get_ue_golomb_31(gb); - if (slice_pic_parameter_set_id < 0 || slice_pic_parameter_set_id >= EVC_MAX_PPS_COUNT) + if (slice_pic_parameter_set_id >= EVC_MAX_PPS_COUNT) return AVERROR_INVALIDDATA; pps = ps->pps[slice_pic_parameter_set_id]; @@ -59,14 +59,14 @@ int ff_evc_parse_slice_header(GetBitContext *gb, EVCParserSliceHeader *sh, if (!sh->arbitrary_slice_flag) sh->last_tile_id = get_bits(gb, pps->tile_id_len_minus1 + 1); else { - sh->num_remaining_tiles_in_slice_minus1 = get_ue_golomb(gb); + sh->num_remaining_tiles_in_slice_minus1 = get_ue_golomb_long(gb); num_tiles_in_slice = sh->num_remaining_tiles_in_slice_minus1 + 2; for (int i = 0; i < num_tiles_in_slice - 1; ++i) - sh->delta_tile_id_minus1[i] = get_ue_golomb(gb); + sh->delta_tile_id_minus1[i] = get_ue_golomb_long(gb); } } - sh->slice_type = get_ue_golomb(gb); + sh->slice_type = get_ue_golomb_31(gb); if (nalu_type == EVC_IDR_NUT) sh->no_output_of_prior_pics_flag = get_bits1(gb); diff --git a/libavcodec/evc_parse.h b/libavcodec/evc_parse.h index 0f142976f53..55cdd553eae 100644 --- a/libavcodec/evc_parse.h +++ b/libavcodec/evc_parse.h @@ -41,27 +41,27 @@ // u(n) - unsigned integer using n bits. // When n is "v" in the syntax table, the number of bits varies in a manner dependent on the value of other syntax elements. typedef struct EVCParserSliceHeader { - int slice_pic_parameter_set_id; // ue(v) - int single_tile_in_slice_flag; // u(1) - int first_tile_id; // u(v) - int arbitrary_slice_flag; // u(1) - int last_tile_id; // u(v) - int num_remaining_tiles_in_slice_minus1; // ue(v) - int delta_tile_id_minus1[EVC_MAX_TILE_ROWS * EVC_MAX_TILE_COLUMNS]; // ue(v) - - int slice_type; // ue(v) - int no_output_of_prior_pics_flag; // u(1) - int mmvd_group_enable_flag; // u(1) - int slice_alf_enabled_flag; // u(1) - - int slice_alf_luma_aps_id; // u(5) - int slice_alf_map_flag; // u(1) - int slice_alf_chroma_idc; // u(2) - int slice_alf_chroma_aps_id; // u(5) - int slice_alf_chroma_map_flag; // u(1) - int slice_alf_chroma2_aps_id; // u(5) - int slice_alf_chroma2_map_flag; // u(1) - int slice_pic_order_cnt_lsb; // u(v) + uint8_t slice_pic_parameter_set_id; // ue(v) + uint8_t single_tile_in_slice_flag; // u(1) + uint8_t first_tile_id; // u(v) + uint8_t arbitrary_slice_flag; // u(1) + uint8_t last_tile_id; // u(v) + uint32_t num_remaining_tiles_in_slice_minus1; // ue(v) + uint16_t delta_tile_id_minus1[EVC_MAX_TILE_ROWS * EVC_MAX_TILE_COLUMNS]; // ue(v) + + uint8_t slice_type; // ue(v) + uint8_t no_output_of_prior_pics_flag; // u(1) + uint8_t mmvd_group_enable_flag; // u(1) + uint8_t slice_alf_enabled_flag; // u(1) + + uint8_t slice_alf_luma_aps_id; // u(5) + uint8_t slice_alf_map_flag; // u(1) + uint8_t slice_alf_chroma_idc; // u(2) + uint8_t slice_alf_chroma_aps_id; // u(5) + uint8_t slice_alf_chroma_map_flag; // u(1) + uint8_t slice_alf_chroma2_aps_id; // u(5) + uint8_t slice_alf_chroma2_map_flag; // u(1) + uint16_t slice_pic_order_cnt_lsb; // u(v) // @note // Currently the structure does not reflect the entire Slice Header RBSP layout. From 7347b44224d707f44a6f9a90b6a9e714b5d35b0d Mon Sep 17 00:00:00 2001 From: James Almer Date: Thu, 22 Jun 2023 19:46:27 -0300 Subject: [PATCH 1666/2172] avcodec/evc_ps: use unsigned types in structs where corresponds Signed-off-by: James Almer --- libavcodec/evc_ps.c | 70 +++++------ libavcodec/evc_ps.h | 277 ++++++++++++++++++++++---------------------- 2 files changed, 171 insertions(+), 176 deletions(-) diff --git a/libavcodec/evc_ps.c b/libavcodec/evc_ps.c index 156f76554a0..cd699d6ad56 100644 --- a/libavcodec/evc_ps.c +++ b/libavcodec/evc_ps.c @@ -27,9 +27,9 @@ static int ref_pic_list_struct(GetBitContext *gb, RefPicListStruct *rpl) { uint32_t delta_poc_st, strp_entry_sign_flag = 0; - rpl->ref_pic_num = get_ue_golomb(gb); + rpl->ref_pic_num = get_ue_golomb_long(gb); if (rpl->ref_pic_num > 0) { - delta_poc_st = get_ue_golomb(gb); + delta_poc_st = get_ue_golomb_long(gb); rpl->ref_pics[0] = delta_poc_st; if (rpl->ref_pics[0] != 0) { @@ -40,7 +40,7 @@ static int ref_pic_list_struct(GetBitContext *gb, RefPicListStruct *rpl) } for (int i = 1; i < rpl->ref_pic_num; ++i) { - delta_poc_st = get_ue_golomb(gb); + delta_poc_st = get_ue_golomb_long(gb); if (delta_poc_st != 0) strp_entry_sign_flag = get_bits(gb, 1); rpl->ref_pics[i] = rpl->ref_pics[i - 1] + delta_poc_st * (1 - (strp_entry_sign_flag << 1)); @@ -52,12 +52,12 @@ static int ref_pic_list_struct(GetBitContext *gb, RefPicListStruct *rpl) // @see ISO_IEC_23094-1 (E.2.2 HRD parameters syntax) static int hrd_parameters(GetBitContext *gb, HRDParameters *hrd) { - hrd->cpb_cnt_minus1 = get_ue_golomb(gb); + hrd->cpb_cnt_minus1 = get_ue_golomb_31(gb); hrd->bit_rate_scale = get_bits(gb, 4); hrd->cpb_size_scale = get_bits(gb, 4); for (int SchedSelIdx = 0; SchedSelIdx <= hrd->cpb_cnt_minus1; SchedSelIdx++) { - hrd->bit_rate_value_minus1[SchedSelIdx] = get_ue_golomb(gb); - hrd->cpb_size_value_minus1[SchedSelIdx] = get_ue_golomb(gb); + hrd->bit_rate_value_minus1[SchedSelIdx] = get_ue_golomb_long(gb); + hrd->cpb_size_value_minus1[SchedSelIdx] = get_ue_golomb_long(gb); hrd->cbr_flag[SchedSelIdx] = get_bits(gb, 1); } hrd->initial_cpb_removal_delay_length_minus1 = get_bits(gb, 5); @@ -95,8 +95,8 @@ static int vui_parameters(GetBitContext *gb, VUIParameters *vui) } vui->chroma_loc_info_present_flag = get_bits(gb, 1); if (vui->chroma_loc_info_present_flag) { - vui->chroma_sample_loc_type_top_field = get_ue_golomb(gb); - vui->chroma_sample_loc_type_bottom_field = get_ue_golomb(gb); + vui->chroma_sample_loc_type_top_field = get_ue_golomb_31(gb); + vui->chroma_sample_loc_type_bottom_field = get_ue_golomb_31(gb); } vui->neutral_chroma_indication_flag = get_bits(gb, 1); @@ -120,12 +120,12 @@ static int vui_parameters(GetBitContext *gb, VUIParameters *vui) vui->bitstream_restriction_flag = get_bits(gb, 1); if (vui->bitstream_restriction_flag) { vui->motion_vectors_over_pic_boundaries_flag = get_bits(gb, 1); - vui->max_bytes_per_pic_denom = get_ue_golomb(gb); - vui->max_bits_per_mb_denom = get_ue_golomb(gb); - vui->log2_max_mv_length_horizontal = get_ue_golomb(gb); - vui->log2_max_mv_length_vertical = get_ue_golomb(gb); - vui->num_reorder_pics = get_ue_golomb(gb); - vui->max_dec_pic_buffering = get_ue_golomb(gb); + vui->max_bytes_per_pic_denom = get_ue_golomb_31(gb); + vui->max_bits_per_mb_denom = get_ue_golomb_31(gb); + vui->log2_max_mv_length_horizontal = get_ue_golomb_31(gb); + vui->log2_max_mv_length_vertical = get_ue_golomb_31(gb); + vui->num_reorder_pics = get_ue_golomb_long(gb); + vui->max_dec_pic_buffering = get_ue_golomb_long(gb); } return 0; @@ -135,7 +135,7 @@ static int vui_parameters(GetBitContext *gb, VUIParameters *vui) int ff_evc_parse_sps(GetBitContext *gb, EVCParamSets *ps) { EVCParserSPS *sps; - int sps_seq_parameter_set_id; + unsigned sps_seq_parameter_set_id; int ret; sps_seq_parameter_set_id = get_ue_golomb(gb); @@ -164,27 +164,27 @@ int ff_evc_parse_sps(GetBitContext *gb, EVCParamSets *ps) // 1 - 4:2:0 // 2 - 4:2:2 // 3 - 4:4:4 - sps->chroma_format_idc = get_ue_golomb(gb); + sps->chroma_format_idc = get_ue_golomb_31(gb); - sps->pic_width_in_luma_samples = get_ue_golomb(gb); - sps->pic_height_in_luma_samples = get_ue_golomb(gb); + sps->pic_width_in_luma_samples = get_ue_golomb_long(gb); + sps->pic_height_in_luma_samples = get_ue_golomb_long(gb); - sps->bit_depth_luma_minus8 = get_ue_golomb(gb); - sps->bit_depth_chroma_minus8 = get_ue_golomb(gb); + sps->bit_depth_luma_minus8 = get_ue_golomb_31(gb); + sps->bit_depth_chroma_minus8 = get_ue_golomb_31(gb); sps->sps_btt_flag = get_bits1(gb); if (sps->sps_btt_flag) { - sps->log2_ctu_size_minus5 = get_ue_golomb(gb); - sps->log2_min_cb_size_minus2 = get_ue_golomb(gb); - sps->log2_diff_ctu_max_14_cb_size = get_ue_golomb(gb); - sps->log2_diff_ctu_max_tt_cb_size = get_ue_golomb(gb); - sps->log2_diff_min_cb_min_tt_cb_size_minus2 = get_ue_golomb(gb); + sps->log2_ctu_size_minus2 = get_ue_golomb_long(gb); + sps->log2_min_cb_size_minus2 = get_ue_golomb_long(gb); + sps->log2_diff_ctu_max_14_cb_size = get_ue_golomb_long(gb); + sps->log2_diff_ctu_max_tt_cb_size = get_ue_golomb_long(gb); + sps->log2_diff_min_cb_min_tt_cb_size_minus2 = get_ue_golomb_long(gb); } sps->sps_suco_flag = get_bits1(gb); if (sps->sps_suco_flag) { - sps->log2_diff_ctu_size_max_suco_cb_size = get_ue_golomb(gb); - sps->log2_diff_max_suco_min_suco_cb_size = get_ue_golomb(gb); + sps->log2_diff_ctu_size_max_suco_cb_size = get_ue_golomb_long(gb); + sps->log2_diff_max_suco_min_suco_cb_size = get_ue_golomb_long(gb); } sps->sps_admvp_flag = get_bits1(gb); @@ -238,9 +238,9 @@ int ff_evc_parse_sps(GetBitContext *gb, EVCParamSets *ps) } if (!sps->sps_rpl_flag) - sps->max_num_tid0_ref_pics = get_ue_golomb(gb); + sps->max_num_tid0_ref_pics = get_ue_golomb_31(gb); else { - sps->sps_max_dec_pic_buffering_minus1 = get_ue_golomb(gb); + sps->sps_max_dec_pic_buffering_minus1 = get_ue_golomb_long(gb); sps->long_term_ref_pic_flag = get_bits1(gb); sps->rpl1_same_as_rpl0_flag = get_bits1(gb); sps->num_ref_pic_list_in_sps[0] = get_ue_golomb(gb); @@ -258,10 +258,10 @@ int ff_evc_parse_sps(GetBitContext *gb, EVCParamSets *ps) sps->picture_cropping_flag = get_bits1(gb); if (sps->picture_cropping_flag) { - sps->picture_crop_left_offset = get_ue_golomb(gb); - sps->picture_crop_right_offset = get_ue_golomb(gb); - sps->picture_crop_top_offset = get_ue_golomb(gb); - sps->picture_crop_bottom_offset = get_ue_golomb(gb); + sps->picture_crop_left_offset = get_ue_golomb_long(gb); + sps->picture_crop_right_offset = get_ue_golomb_long(gb); + sps->picture_crop_top_offset = get_ue_golomb_long(gb); + sps->picture_crop_bottom_offset = get_ue_golomb_long(gb); } if (sps->chroma_format_idc != 0) { @@ -278,7 +278,7 @@ int ff_evc_parse_sps(GetBitContext *gb, EVCParamSets *ps) } for (int j = 0; j <= sps->chroma_qp_table_struct.num_points_in_qp_table_minus1[i]; j++) { sps->chroma_qp_table_struct.delta_qp_in_val_minus1[i][j] = get_bits(gb, 6); - sps->chroma_qp_table_struct.delta_qp_out_val[i][j] = get_se_golomb(gb); + sps->chroma_qp_table_struct.delta_qp_out_val[i][j] = get_se_golomb_long(gb); } } } @@ -311,7 +311,7 @@ int ff_evc_parse_sps(GetBitContext *gb, EVCParamSets *ps) int ff_evc_parse_pps(GetBitContext *gb, EVCParamSets *ps) { EVCParserPPS *pps; - int pps_pic_parameter_set_id; + unsigned pps_pic_parameter_set_id; int ret; pps_pic_parameter_set_id = get_ue_golomb(gb); diff --git a/libavcodec/evc_ps.h b/libavcodec/evc_ps.h index 5aaa30de207..0bbec1f1384 100644 --- a/libavcodec/evc_ps.h +++ b/libavcodec/evc_ps.h @@ -34,75 +34,70 @@ // rpl structure typedef struct RefPicListStruct { - int poc; - int tid; - int ref_pic_num; - int ref_pic_active_num; - int ref_pics[EVC_MAX_NUM_REF_PICS]; - char pic_type; - + uint32_t ref_pic_num; + uint32_t ref_pics[EVC_MAX_NUM_REF_PICS]; } RefPicListStruct; // chromaQP table structure to be signalled in SPS typedef struct ChromaQpTable { - int chroma_qp_table_present_flag; // u(1) - int same_qp_table_for_chroma; // u(1) - int global_offset_flag; // u(1) - int num_points_in_qp_table_minus1[2]; // ue(v) - int delta_qp_in_val_minus1[2][EVC_MAX_QP_TABLE_SIZE]; // u(6) + uint8_t chroma_qp_table_present_flag; // u(1) + uint8_t same_qp_table_for_chroma; // u(1) + uint8_t global_offset_flag; // u(1) + uint8_t num_points_in_qp_table_minus1[2]; // ue(v) + uint8_t delta_qp_in_val_minus1[2][EVC_MAX_QP_TABLE_SIZE]; // u(6) int delta_qp_out_val[2][EVC_MAX_QP_TABLE_SIZE]; // se(v) } ChromaQpTable; // Hypothetical Reference Decoder (HRD) parameters, part of VUI typedef struct HRDParameters { - int cpb_cnt_minus1; // ue(v) - int bit_rate_scale; // u(4) - int cpb_size_scale; // u(4) - int bit_rate_value_minus1[NUM_CPB]; // ue(v) - int cpb_size_value_minus1[NUM_CPB]; // ue(v) - int cbr_flag[NUM_CPB]; // u(1) - int initial_cpb_removal_delay_length_minus1; // u(5) - int cpb_removal_delay_length_minus1; // u(5) - int dpb_output_delay_length_minus1; // u(5) - int time_offset_length; // u(5) + uint8_t cpb_cnt_minus1; // ue(v) + uint8_t bit_rate_scale; // u(4) + uint8_t cpb_size_scale; // u(4) + uint32_t bit_rate_value_minus1[NUM_CPB]; // ue(v) + uint32_t cpb_size_value_minus1[NUM_CPB]; // ue(v) + uint8_t cbr_flag[NUM_CPB]; // u(1) + uint8_t initial_cpb_removal_delay_length_minus1; // u(5) + uint8_t cpb_removal_delay_length_minus1; // u(5) + uint8_t dpb_output_delay_length_minus1; // u(5) + uint8_t time_offset_length; // u(5) } HRDParameters; // video usability information (VUI) part of SPS typedef struct VUIParameters { - int aspect_ratio_info_present_flag; // u(1) - int aspect_ratio_idc; // u(8) - int sar_width; // u(16) - int sar_height; // u(16) - int overscan_info_present_flag; // u(1) - int overscan_appropriate_flag; // u(1) - int video_signal_type_present_flag; // u(1) - int video_format; // u(3) - int video_full_range_flag; // u(1) - int colour_description_present_flag; // u(1) - int colour_primaries; // u(8) - int transfer_characteristics; // u(8) - int matrix_coefficients; // u(8) - int chroma_loc_info_present_flag; // u(1) - int chroma_sample_loc_type_top_field; // ue(v) - int chroma_sample_loc_type_bottom_field; // ue(v) - int neutral_chroma_indication_flag; // u(1) - int field_seq_flag; // u(1) - int timing_info_present_flag; // u(1) - int num_units_in_tick; // u(32) - int time_scale; // u(32) - int fixed_pic_rate_flag; // u(1) - int nal_hrd_parameters_present_flag; // u(1) - int vcl_hrd_parameters_present_flag; // u(1) - int low_delay_hrd_flag; // u(1) - int pic_struct_present_flag; // u(1) - int bitstream_restriction_flag; // u(1) - int motion_vectors_over_pic_boundaries_flag; // u(1) - int max_bytes_per_pic_denom; // ue(v) - int max_bits_per_mb_denom; // ue(v) - int log2_max_mv_length_horizontal; // ue(v) - int log2_max_mv_length_vertical; // ue(v) - int num_reorder_pics; // ue(v) - int max_dec_pic_buffering; // ue(v) + uint8_t aspect_ratio_info_present_flag; // u(1) + uint8_t aspect_ratio_idc; // u(8) + uint16_t sar_width; // u(16) + uint16_t sar_height; // u(16) + uint8_t overscan_info_present_flag; // u(1) + uint8_t overscan_appropriate_flag; // u(1) + uint8_t video_signal_type_present_flag; // u(1) + uint8_t video_format; // u(3) + uint8_t video_full_range_flag; // u(1) + uint8_t colour_description_present_flag; // u(1) + uint8_t colour_primaries; // u(8) + uint8_t transfer_characteristics; // u(8) + uint8_t matrix_coefficients; // u(8) + uint8_t chroma_loc_info_present_flag; // u(1) + uint8_t chroma_sample_loc_type_top_field; // ue(v) + uint8_t chroma_sample_loc_type_bottom_field; // ue(v) + uint8_t neutral_chroma_indication_flag; // u(1) + uint8_t field_seq_flag; // u(1) + uint8_t timing_info_present_flag; // u(1) + uint32_t num_units_in_tick; // u(32) + uint32_t time_scale; // u(32) + uint8_t fixed_pic_rate_flag; // u(1) + uint8_t nal_hrd_parameters_present_flag; // u(1) + uint8_t vcl_hrd_parameters_present_flag; // u(1) + uint8_t low_delay_hrd_flag; // u(1) + uint8_t pic_struct_present_flag; // u(1) + uint8_t bitstream_restriction_flag; // u(1) + uint8_t motion_vectors_over_pic_boundaries_flag; // u(1) + uint8_t max_bytes_per_pic_denom; // ue(v) + uint8_t max_bits_per_mb_denom; // ue(v) + uint8_t log2_max_mv_length_horizontal; // ue(v) + uint8_t log2_max_mv_length_vertical; // ue(v) + uint32_t num_reorder_pics; // ue(v) + uint32_t max_dec_pic_buffering; // ue(v) HRDParameters hrd_parameters; } VUIParameters; @@ -114,102 +109,102 @@ typedef struct VUIParameters { // u(n) - unsigned integer using n bits // ue(v) - unsigned integer 0-th order Exp_Golomb-coded syntax element with the left bit first typedef struct EVCParserSPS { - int sps_seq_parameter_set_id; // ue(v) - int profile_idc; // u(8) - int level_idc; // u(8) - int toolset_idc_h; // u(32) - int toolset_idc_l; // u(32) - int chroma_format_idc; // ue(v) - int pic_width_in_luma_samples; // ue(v) - int pic_height_in_luma_samples; // ue(v) - int bit_depth_luma_minus8; // ue(v) - int bit_depth_chroma_minus8; // ue(v) - - int sps_btt_flag; // u(1) - int log2_ctu_size_minus5; // ue(v) - int log2_min_cb_size_minus2; // ue(v) - int log2_diff_ctu_max_14_cb_size; // ue(v) - int log2_diff_ctu_max_tt_cb_size; // ue(v) - int log2_diff_min_cb_min_tt_cb_size_minus2; // ue(v) - - int sps_suco_flag; // u(1) - int log2_diff_ctu_size_max_suco_cb_size; // ue(v) - int log2_diff_max_suco_min_suco_cb_size; // ue(v) - - int sps_admvp_flag; // u(1) - int sps_affine_flag; // u(1) - int sps_amvr_flag; // u(1) - int sps_dmvr_flag; // u(1) - int sps_mmvd_flag; // u(1) - int sps_hmvp_flag; // u(1) - - int sps_eipd_flag; // u(1) - int sps_ibc_flag; // u(1) - int log2_max_ibc_cand_size_minus2; // ue(v) - - int sps_cm_init_flag; // u(1) - int sps_adcc_flag; // u(1) - - int sps_iqt_flag; // u(1) - int sps_ats_flag; // u(1) - - int sps_addb_flag; // u(1) - int sps_alf_flag; // u(1) - int sps_htdf_flag; // u(1) - int sps_rpl_flag; // u(1) - int sps_pocs_flag; // u(1) - int sps_dquant_flag; // u(1) - int sps_dra_flag; // u(1) - - int log2_max_pic_order_cnt_lsb_minus4; // ue(v) - int log2_sub_gop_length; // ue(v) - int log2_ref_pic_gap_length; // ue(v) - - int max_num_tid0_ref_pics; // ue(v) - - int sps_max_dec_pic_buffering_minus1; // ue(v) - int long_term_ref_pic_flag; // u(1) - int rpl1_same_as_rpl0_flag; // u(1) - int num_ref_pic_list_in_sps[2]; // ue(v) + uint8_t sps_seq_parameter_set_id; // ue(v) + uint8_t profile_idc; // u(8) + uint8_t level_idc; // u(8) + uint32_t toolset_idc_h; // u(32) + uint32_t toolset_idc_l; // u(32) + uint8_t chroma_format_idc; // ue(v) + uint32_t pic_width_in_luma_samples; // ue(v) + uint32_t pic_height_in_luma_samples; // ue(v) + uint8_t bit_depth_luma_minus8; // ue(v) + uint8_t bit_depth_chroma_minus8; // ue(v) + + uint8_t sps_btt_flag; // u(1) + uint32_t log2_ctu_size_minus2; // ue(v) + uint32_t log2_min_cb_size_minus2; // ue(v) + uint32_t log2_diff_ctu_max_14_cb_size; // ue(v) + uint32_t log2_diff_ctu_max_tt_cb_size; // ue(v) + uint32_t log2_diff_min_cb_min_tt_cb_size_minus2; // ue(v) + + uint8_t sps_suco_flag; // u(1) + uint32_t log2_diff_ctu_size_max_suco_cb_size; // ue(v) + uint32_t log2_diff_max_suco_min_suco_cb_size; // ue(v) + + uint8_t sps_admvp_flag; // u(1) + uint8_t sps_affine_flag; // u(1) + uint8_t sps_amvr_flag; // u(1) + uint8_t sps_dmvr_flag; // u(1) + uint8_t sps_mmvd_flag; // u(1) + uint8_t sps_hmvp_flag; // u(1) + + uint8_t sps_eipd_flag; // u(1) + uint8_t sps_ibc_flag; // u(1) + uint32_t log2_max_ibc_cand_size_minus2; // ue(v) + + uint8_t sps_cm_init_flag; // u(1) + uint8_t sps_adcc_flag; // u(1) + + uint8_t sps_iqt_flag; // u(1) + uint8_t sps_ats_flag; // u(1) + + uint8_t sps_addb_flag; // u(1) + uint8_t sps_alf_flag; // u(1) + uint8_t sps_htdf_flag; // u(1) + uint8_t sps_rpl_flag; // u(1) + uint8_t sps_pocs_flag; // u(1) + uint8_t sps_dquant_flag; // u(1) + uint8_t sps_dra_flag; // u(1) + + uint32_t log2_max_pic_order_cnt_lsb_minus4; // ue(v) + uint32_t log2_sub_gop_length; // ue(v) + uint32_t log2_ref_pic_gap_length; // ue(v) + + uint8_t max_num_tid0_ref_pics; // ue(v) + + uint32_t sps_max_dec_pic_buffering_minus1; // ue(v) + uint8_t long_term_ref_pic_flag; // u(1) + uint8_t rpl1_same_as_rpl0_flag; // u(1) + uint8_t num_ref_pic_list_in_sps[2]; // ue(v) struct RefPicListStruct rpls[2][EVC_MAX_NUM_RPLS]; - int picture_cropping_flag; // u(1) - int picture_crop_left_offset; // ue(v) - int picture_crop_right_offset; // ue(v) - int picture_crop_top_offset; // ue(v) - int picture_crop_bottom_offset; // ue(v) + uint8_t picture_cropping_flag; // u(1) + uint32_t picture_crop_left_offset; // ue(v) + uint32_t picture_crop_right_offset; // ue(v) + uint32_t picture_crop_top_offset; // ue(v) + uint32_t picture_crop_bottom_offset; // ue(v) struct ChromaQpTable chroma_qp_table_struct; - int vui_parameters_present_flag; // u(1) + uint8_t vui_parameters_present_flag; // u(1) struct VUIParameters vui_parameters; } EVCParserSPS; typedef struct EVCParserPPS { - int pps_pic_parameter_set_id; // ue(v) - int pps_seq_parameter_set_id; // ue(v) - int num_ref_idx_default_active_minus1[2]; // ue(v) - int additional_lt_poc_lsb_len; // ue(v) - int rpl1_idx_present_flag; // u(1) - int single_tile_in_pic_flag; // u(1) - int num_tile_columns_minus1; // ue(v) - int num_tile_rows_minus1; // ue(v) - int uniform_tile_spacing_flag; // u(1) - int tile_column_width_minus1[EVC_MAX_TILE_ROWS]; // ue(v) - int tile_row_height_minus1[EVC_MAX_TILE_COLUMNS]; // ue(v) - int loop_filter_across_tiles_enabled_flag; // u(1) - int tile_offset_len_minus1; // ue(v) - int tile_id_len_minus1; // ue(v) - int explicit_tile_id_flag; // u(1) - int tile_id_val[EVC_MAX_TILE_ROWS][EVC_MAX_TILE_COLUMNS]; // u(v) - int pic_dra_enabled_flag; // u(1) - int pic_dra_aps_id; // u(5) - int arbitrary_slice_present_flag; // u(1) - int constrained_intra_pred_flag; // u(1) - int cu_qp_delta_enabled_flag; // u(1) - int log2_cu_qp_delta_area_minus6; // ue(v) + uint8_t pps_pic_parameter_set_id; // ue(v) + uint8_t pps_seq_parameter_set_id; // ue(v) + uint8_t num_ref_idx_default_active_minus1[2]; // ue(v) + uint8_t additional_lt_poc_lsb_len; // ue(v) + uint8_t rpl1_idx_present_flag; // u(1) + uint8_t single_tile_in_pic_flag; // u(1) + uint32_t num_tile_columns_minus1; // ue(v) + uint32_t num_tile_rows_minus1; // ue(v) + uint8_t uniform_tile_spacing_flag; // u(1) + uint32_t tile_column_width_minus1[EVC_MAX_TILE_ROWS]; // ue(v) + uint32_t tile_row_height_minus1[EVC_MAX_TILE_COLUMNS]; // ue(v) + uint8_t loop_filter_across_tiles_enabled_flag; // u(1) + uint32_t tile_offset_len_minus1; // ue(v) + uint8_t tile_id_len_minus1; // ue(v) + uint8_t explicit_tile_id_flag; // u(1) + uint32_t tile_id_val[EVC_MAX_TILE_ROWS][EVC_MAX_TILE_COLUMNS]; // u(v) + uint8_t pic_dra_enabled_flag; // u(1) + uint8_t pic_dra_aps_id; // u(5) + uint8_t arbitrary_slice_present_flag; // u(1) + uint8_t constrained_intra_pred_flag; // u(1) + uint8_t cu_qp_delta_enabled_flag; // u(1) + uint32_t log2_cu_qp_delta_area_minus6; // ue(v) } EVCParserPPS; From ffe4ec5c84f5e7f9cf358eb206f626ec5d437449 Mon Sep 17 00:00:00 2001 From: James Almer Date: Fri, 23 Jun 2023 09:39:14 -0300 Subject: [PATCH 1667/2172] avcodec/evc_ps: fix allowed range for pps_pic_parameter_set_id Signed-off-by: James Almer --- libavcodec/evc_ps.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavcodec/evc_ps.c b/libavcodec/evc_ps.c index cd699d6ad56..ec405345ae2 100644 --- a/libavcodec/evc_ps.c +++ b/libavcodec/evc_ps.c @@ -315,7 +315,7 @@ int ff_evc_parse_pps(GetBitContext *gb, EVCParamSets *ps) int ret; pps_pic_parameter_set_id = get_ue_golomb(gb); - if (pps_pic_parameter_set_id > EVC_MAX_PPS_COUNT) + if (pps_pic_parameter_set_id >= EVC_MAX_PPS_COUNT) return AVERROR_INVALIDDATA; pps = av_malloc(sizeof(*pps)); From 5fdb12d6a06016ee01022b96f271b7223976c3d8 Mon Sep 17 00:00:00 2001 From: Niklas Haas Date: Tue, 20 Jun 2023 16:37:28 +0200 Subject: [PATCH 1668/2172] lavfi/vf_libplacebo: simplify SAR normalization The old logic was trying to be excessively clever in "deducing" that the user wanted to stretch/scale the image when ow/oh differed from iw/ih aspect ratio. But this is almost surely unintended except in pathological cases, and in those cases users should simply disable normalize_sar and do all the stretching/scaling logic themselves. This is especially important in multi-input mode, where the canvas may be vastly different from the input dimensions of any stream. Also, passing through input 0 SAR in multi-input mode is arbitrary and nearly useless, so again force output SAR to 1:1 here. --- libavfilter/vf_libplacebo.c | 19 ++++++------------- 1 file changed, 6 insertions(+), 13 deletions(-) diff --git a/libavfilter/vf_libplacebo.c b/libavfilter/vf_libplacebo.c index 0f7c6481925..e58183a5caa 100644 --- a/libavfilter/vf_libplacebo.c +++ b/libavfilter/vf_libplacebo.c @@ -160,7 +160,6 @@ typedef struct LibplaceboContext { // Parsed expressions for input/output crop AVExpr *crop_x_pexpr, *crop_y_pexpr, *crop_w_pexpr, *crop_h_pexpr; AVExpr *pos_x_pexpr, *pos_y_pexpr, *pos_w_pexpr, *pos_h_pexpr; - AVRational target_sar; float pad_crop_ratio; float corner_rounding; int force_original_aspect_ratio; @@ -795,9 +794,9 @@ static void update_crops(AVFilterContext *ctx, LibplaceboInput *in, target->crop.y0 = av_expr_eval(s->pos_y_pexpr, s->var_values, NULL); target->crop.x1 = target->crop.x0 + s->var_values[VAR_POS_W]; target->crop.y1 = target->crop.y0 + s->var_values[VAR_POS_H]; - - if (s->target_sar.num) { - float aspect = pl_rect2df_aspect(&target->crop) * av_q2d(s->target_sar); + if (s->normalize_sar) { + float aspect = pl_rect2df_aspect(&image->crop); + aspect *= av_q2d(in->link->sample_aspect_ratio); pl_rect2df_aspect_set(&target->crop, aspect, s->pad_crop_ratio); } } @@ -1188,7 +1187,6 @@ static int libplacebo_config_output(AVFilterLink *outlink) const AVPixFmtDescriptor *out_desc = av_pix_fmt_desc_get(outlink->format); AVHWFramesContext *hwfc; AVVulkanFramesContext *vkfc; - AVRational scale_sar; /* Frame dimensions */ RET(ff_scale_eval_dimensions(s, s->w_expr, s->h_expr, inlink, outlink, @@ -1198,20 +1196,15 @@ static int libplacebo_config_output(AVFilterLink *outlink) s->force_original_aspect_ratio, s->force_divisible_by); - scale_sar = (AVRational){outlink->h * inlink->w, outlink->w * inlink->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 */ + if (s->normalize_sar || s->nb_inputs > 1) { + /* SAR is normalized, or we have multiple inputs, set out to 1:1 */ outlink->sample_aspect_ratio = (AVRational){ 1, 1 }; - 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; + outlink->sample_aspect_ratio = inlink->sample_aspect_ratio; } /* Frame rate */ From a9d41ab89016fabe5d2f0dba4d10b2580608d428 Mon Sep 17 00:00:00 2001 From: James Almer Date: Fri, 23 Jun 2023 11:04:46 -0300 Subject: [PATCH 1669/2172] avcodec/evc_frame_merge: remove an av_packet_copy_props() call And only fill out if no failures can happen, fixing potential leaks. Signed-off-by: James Almer --- libavcodec/evc_frame_merge_bsf.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/libavcodec/evc_frame_merge_bsf.c b/libavcodec/evc_frame_merge_bsf.c index 3e1258c6c9f..cfdf24c69e7 100644 --- a/libavcodec/evc_frame_merge_bsf.c +++ b/libavcodec/evc_frame_merge_bsf.c @@ -228,15 +228,17 @@ static int evc_frame_merge_filter(AVBSFContext *bsf, AVPacket *out) data_size = ctx->au_buffer.data_size; ctx->au_buffer.data_size = 0; - err = av_new_packet(out, data_size); - if (err < 0) - goto end; - err = av_packet_copy_props(out, buffer_pkt); + // drop the data in buffer_pkt, if any, but keep the props + av_buffer_unref(&buffer_pkt->buf); + err = av_buffer_realloc(&buffer_pkt->buf, data_size + AV_INPUT_BUFFER_PADDING_SIZE); if (err < 0) goto end; - av_packet_unref(buffer_pkt); + buffer_pkt->data = buffer_pkt->buf->data; + buffer_pkt->size = data_size; + av_packet_move_ref(out, buffer_pkt); memcpy(out->data, ctx->au_buffer.data, data_size); + memset(out->data + data_size, 0, AV_INPUT_BUFFER_PADDING_SIZE); err = 0; end: From 3323b515abc1cda20510e5e5d7ae4f3d7419ec8e Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Sun, 18 Jun 2023 23:44:09 +0200 Subject: [PATCH 1670/2172] doc/developer: Require new modules to include tests Signed-off-by: Michael Niedermayer --- doc/developer.texi | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/doc/developer.texi b/doc/developer.texi index a7da2ce2d5d..0c2f2cd7d1b 100644 --- a/doc/developer.texi +++ b/doc/developer.texi @@ -805,7 +805,10 @@ Lines with similar content should be aligned vertically when doing so improves readability. @item -Consider adding a regression test for your code. +Consider adding a regression test for your code. All new modules +should be covered by tests. That includes demuxers, muxers, decoders, encoders +filters, bitstream filters, parsers. If its not possible to do that, add +an explanation why to your patchset, its ok to not test if theres a reason. @item If you added YASM code please check that things still work with --disable-yasm. From af3f12078563d8119bd59771793994f651842ff2 Mon Sep 17 00:00:00 2001 From: Zhao Zhili Date: Mon, 12 Jun 2023 19:56:28 +0800 Subject: [PATCH 1671/2172] avformat/mov: fix overallocation when reading pssh/saiz mov_try_read_block() allocates 1MB at least, which can be more than enough. It was called when reading saiz box, which can appear periodically inside fmp4. This consumes a lot of memory. We can fix mov_try_read_block() by clamp 'block_size' with 'size'. However, the function is harmful than helpful. It avoids allocating large memory when the real data is small. Even in that case, if allocating large memory directly failed, it's fine to return ENOMEM; if allocating success and reading doesn't match the given size, it's fine to free and return AVERROR_INVALIDDATA. In other cases, it's a waste of CPU and memory. So I decided to remove the function, and replace it by call av_malloc() and avio_read() directly. mov_read_saiz() and mov_read_pssh() need more check, but they don't belong to this patch. Fixes #7641 and #9243. Signed-off-by: Zhao Zhili --- libavformat/mov.c | 63 +++++++++++++++++++---------------------------- 1 file changed, 25 insertions(+), 38 deletions(-) diff --git a/libavformat/mov.c b/libavformat/mov.c index 278dec67652..444aca52351 100644 --- a/libavformat/mov.c +++ b/libavformat/mov.c @@ -6650,38 +6650,6 @@ static int mov_parse_auxiliary_info(MOVContext *c, MOVStreamContext *sc, AVIOCon return ret; } -/** - * Tries to read the given number of bytes from the stream and puts it in a - * newly allocated buffer. This reads in small chunks to avoid allocating large - * memory if the file contains an invalid/malicious size value. - */ -static int mov_try_read_block(AVIOContext *pb, size_t size, uint8_t **data) -{ - const unsigned int block_size = 1024 * 1024; - uint8_t *buffer = NULL; - unsigned int alloc_size = 0, offset = 0; - while (offset < size) { - unsigned int new_size = - alloc_size >= INT_MAX - block_size ? INT_MAX : alloc_size + block_size; - uint8_t *new_buffer = av_fast_realloc(buffer, &alloc_size, new_size); - unsigned int to_read = FFMIN(size, alloc_size) - offset; - if (!new_buffer) { - av_free(buffer); - return AVERROR(ENOMEM); - } - buffer = new_buffer; - - if (avio_read(pb, buffer + offset, to_read) != to_read) { - av_free(buffer); - return AVERROR_INVALIDDATA; - } - offset += to_read; - } - - *data = buffer; - return 0; -} - static int mov_read_saiz(MOVContext *c, AVIOContext *pb, MOVAtom atom) { MOVEncryptionIndex *encryption_index; @@ -6737,15 +6705,24 @@ static int mov_read_saiz(MOVContext *c, AVIOContext *pb, MOVAtom atom) encryption_index->auxiliary_info_default_size = avio_r8(pb); sample_count = avio_rb32(pb); - encryption_index->auxiliary_info_sample_count = sample_count; if (encryption_index->auxiliary_info_default_size == 0) { - ret = mov_try_read_block(pb, sample_count, &encryption_index->auxiliary_info_sizes); - if (ret < 0) { - av_log(c->fc, AV_LOG_ERROR, "Failed to read the auxiliary info\n"); + encryption_index->auxiliary_info_sizes = av_malloc(sample_count); + if (!encryption_index->auxiliary_info_sizes) + return AVERROR(ENOMEM); + + ret = avio_read(pb, encryption_index->auxiliary_info_sizes, sample_count); + if (ret != sample_count) { + av_freep(&encryption_index->auxiliary_info_sizes); + + if (ret >= 0) + ret = AVERROR_INVALIDDATA; + av_log(c->fc, AV_LOG_ERROR, "Failed to read the auxiliary info, %s\n", + av_err2str(ret)); return ret; } } + encryption_index->auxiliary_info_sample_count = sample_count; if (encryption_index->auxiliary_offsets_count) { return mov_parse_auxiliary_info(c, sc, pb, encryption_index); @@ -6914,9 +6891,19 @@ static int mov_read_pssh(MOVContext *c, AVIOContext *pb, MOVAtom atom) } extra_data_size = avio_rb32(pb); - ret = mov_try_read_block(pb, extra_data_size, &extra_data); - if (ret < 0) + extra_data = av_malloc(extra_data_size); + if (!extra_data) { + ret = AVERROR(ENOMEM); goto finish; + } + ret = avio_read(pb, extra_data, extra_data_size); + if (ret != extra_data_size) { + av_free(extra_data); + + if (ret >= 0) + ret = AVERROR_INVALIDDATA; + goto finish; + } av_freep(&info->data); // malloc(0) may still allocate something. info->data = extra_data; From 35af1695a9ad6f950e03efd156b99898b94dd57c Mon Sep 17 00:00:00 2001 From: James Almer Date: Sat, 24 Jun 2023 14:37:10 -0300 Subject: [PATCH 1672/2172] avcodec/aac_ac3_parser: add preprocessor checks for codec specific code Should fix ticket #10421. Signed-off-by: James Almer --- libavcodec/aac_ac3_parser.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/libavcodec/aac_ac3_parser.c b/libavcodec/aac_ac3_parser.c index 9ab979632dc..83d515b5a83 100644 --- a/libavcodec/aac_ac3_parser.c +++ b/libavcodec/aac_ac3_parser.c @@ -95,6 +95,7 @@ int ff_aac_ac3_parse(AVCodecParserContext *s1, duration in seconds is still correct (as is the number of bits in the frame). */ if (avctx->codec_id != AV_CODEC_ID_AAC) { +#if CONFIG_AC3_PARSER AC3HeaderInfo hdr, *phrd = &hdr; int offset = ff_ac3_find_syncword(buf, buf_size); @@ -146,7 +147,9 @@ FF_ENABLE_DEPRECATION_WARNINGS if (hdr.bitstream_mode == 0x7 && hdr.channels > 1) avctx->audio_service_type = AV_AUDIO_SERVICE_TYPE_KARAOKE; bit_rate = hdr.bit_rate; +#endif } else { +#if CONFIG_AAC_PARSER AACADTSHeaderInfo hdr, *phrd = &hdr; int ret = avpriv_adts_header_parse(&phrd, buf, buf_size); @@ -154,6 +157,7 @@ FF_ENABLE_DEPRECATION_WARNINGS return i; bit_rate = hdr.bit_rate; +#endif } /* Calculate the average bit rate */ From 10f1bbfe117e990a6fe56c03085966fa0c0f0f2e Mon Sep 17 00:00:00 2001 From: James Almer Date: Sat, 24 Jun 2023 14:11:57 -0300 Subject: [PATCH 1673/2172] avcodec/j2kenc: use uint64_t type for the lambda value Should fix integer overflows, and improve encoding results. Reviewed-by: Paul B Mahol Signed-off-by: James Almer --- libavcodec/j2kenc.c | 4 ++-- tests/ref/vsynth/vsynth1-jpeg2000-yuva444p16 | 8 ++++---- tests/ref/vsynth/vsynth2-jpeg2000-yuva444p16 | 8 ++++---- tests/ref/vsynth/vsynth3-jpeg2000-yuva444p16 | 8 ++++---- tests/ref/vsynth/vsynth_lena-jpeg2000-yuva444p16 | 8 ++++---- 5 files changed, 18 insertions(+), 18 deletions(-) diff --git a/libavcodec/j2kenc.c b/libavcodec/j2kenc.c index 2b0c58cff43..5f95b772d19 100644 --- a/libavcodec/j2kenc.c +++ b/libavcodec/j2kenc.c @@ -127,7 +127,7 @@ typedef struct { uint8_t *buf_end; int bit_index; - int64_t lambda; + uint64_t lambda; Jpeg2000CodingStyle codsty; Jpeg2000QuantStyle qntsty; @@ -1348,7 +1348,7 @@ static void makelayers(Jpeg2000EncoderContext *s, Jpeg2000Tile *tile) } } -static int getcut(Jpeg2000Cblk *cblk, int64_t lambda, int dwt_norm) +static int getcut(Jpeg2000Cblk *cblk, uint64_t lambda, int dwt_norm) { int passno, res = 0; for (passno = 0; passno < cblk->npasses; passno++){ diff --git a/tests/ref/vsynth/vsynth1-jpeg2000-yuva444p16 b/tests/ref/vsynth/vsynth1-jpeg2000-yuva444p16 index 363ddc4ffaa..f3d3ba8a6cd 100644 --- a/tests/ref/vsynth/vsynth1-jpeg2000-yuva444p16 +++ b/tests/ref/vsynth/vsynth1-jpeg2000-yuva444p16 @@ -1,4 +1,4 @@ -9261706cfd4dfd8db38fc9bdafe6bef7 *tests/data/fate/vsynth1-jpeg2000-yuva444p16.avi -12433462 tests/data/fate/vsynth1-jpeg2000-yuva444p16.avi -6bc7131cd19dbb59339bb13a6d53b94d *tests/data/fate/vsynth1-jpeg2000-yuva444p16.out.rawvideo -stddev: 12.97 PSNR: 25.87 MAXDIFF: 169 bytes: 7603200/ 7603200 +4c051562f5ac7c9871e034917326787c *tests/data/fate/vsynth1-jpeg2000-yuva444p16.avi +12502390 tests/data/fate/vsynth1-jpeg2000-yuva444p16.avi +59d53e883f76d41d17c926236ca9d7d2 *tests/data/fate/vsynth1-jpeg2000-yuva444p16.out.rawvideo +stddev: 2.66 PSNR: 39.62 MAXDIFF: 44 bytes: 7603200/ 7603200 diff --git a/tests/ref/vsynth/vsynth2-jpeg2000-yuva444p16 b/tests/ref/vsynth/vsynth2-jpeg2000-yuva444p16 index bec08da307e..3cbe5f4ad20 100644 --- a/tests/ref/vsynth/vsynth2-jpeg2000-yuva444p16 +++ b/tests/ref/vsynth/vsynth2-jpeg2000-yuva444p16 @@ -1,4 +1,4 @@ -54063ab98e48b2a079b63643fe26e082 *tests/data/fate/vsynth2-jpeg2000-yuva444p16.avi -11489842 tests/data/fate/vsynth2-jpeg2000-yuva444p16.avi -a4232b2959472f88b5310572456fa900 *tests/data/fate/vsynth2-jpeg2000-yuva444p16.out.rawvideo -stddev: 11.69 PSNR: 26.77 MAXDIFF: 188 bytes: 7603200/ 7603200 +37555b5b00bba2773d5a4212f6c7debd *tests/data/fate/vsynth2-jpeg2000-yuva444p16.avi +11501630 tests/data/fate/vsynth2-jpeg2000-yuva444p16.avi +61be7920a21190d946c22cb2c945ab6f *tests/data/fate/vsynth2-jpeg2000-yuva444p16.out.rawvideo +stddev: 0.53 PSNR: 53.49 MAXDIFF: 13 bytes: 7603200/ 7603200 diff --git a/tests/ref/vsynth/vsynth3-jpeg2000-yuva444p16 b/tests/ref/vsynth/vsynth3-jpeg2000-yuva444p16 index dae44f40bd1..ce92bf7e431 100644 --- a/tests/ref/vsynth/vsynth3-jpeg2000-yuva444p16 +++ b/tests/ref/vsynth/vsynth3-jpeg2000-yuva444p16 @@ -1,4 +1,4 @@ -afdff47e9c71d912153e59a56afdf2a9 *tests/data/fate/vsynth3-jpeg2000-yuva444p16.avi -194250 tests/data/fate/vsynth3-jpeg2000-yuva444p16.avi -9e0ef11f8c85206a950a919cb679f129 *tests/data/fate/vsynth3-jpeg2000-yuva444p16.out.rawvideo -stddev: 10.72 PSNR: 27.53 MAXDIFF: 82 bytes: 86700/ 86700 +ae5951cee3db63c7c6f81d23b601c0fb *tests/data/fate/vsynth3-jpeg2000-yuva444p16.avi +194668 tests/data/fate/vsynth3-jpeg2000-yuva444p16.avi +d959793c1f0bb86b0fc509d5747e03c7 *tests/data/fate/vsynth3-jpeg2000-yuva444p16.out.rawvideo +stddev: 3.06 PSNR: 38.39 MAXDIFF: 40 bytes: 86700/ 86700 diff --git a/tests/ref/vsynth/vsynth_lena-jpeg2000-yuva444p16 b/tests/ref/vsynth/vsynth_lena-jpeg2000-yuva444p16 index d9e856735b2..6dc522bb015 100644 --- a/tests/ref/vsynth/vsynth_lena-jpeg2000-yuva444p16 +++ b/tests/ref/vsynth/vsynth_lena-jpeg2000-yuva444p16 @@ -1,4 +1,4 @@ -e9c56e128cf980db7c8e965d2afc0ea6 *tests/data/fate/vsynth_lena-jpeg2000-yuva444p16.avi -11109882 tests/data/fate/vsynth_lena-jpeg2000-yuva444p16.avi -3e1a4f9ca46c2dd3fd997c01a0dfb130 *tests/data/fate/vsynth_lena-jpeg2000-yuva444p16.out.rawvideo -stddev: 11.67 PSNR: 26.79 MAXDIFF: 150 bytes: 7603200/ 7603200 +fcfb2e4738ad6afd7f9d4e9f92084415 *tests/data/fate/vsynth_lena-jpeg2000-yuva444p16.avi +11123818 tests/data/fate/vsynth_lena-jpeg2000-yuva444p16.avi +62ac96a84eb370e5543582512dbe5d7c *tests/data/fate/vsynth_lena-jpeg2000-yuva444p16.out.rawvideo +stddev: 0.45 PSNR: 54.88 MAXDIFF: 7 bytes: 7603200/ 7603200 From c39e861a3d42c2beeae5d87fa8ddf87c36fac9b1 Mon Sep 17 00:00:00 2001 From: Lynne Date: Sun, 25 Jun 2023 02:42:29 +0200 Subject: [PATCH 1674/2172] vulkan_h264: check if slices_buf exists on end_frame The issue is that while decode_slice is guaranteed to never get called without start_frame, end_frame is not. Moreover, it is not guaranteed it won't be called twice. On a badly-broken sample, this is what happens, which leads to a segfault, as vp->slices_buf doesn't exist, as it has been handed off for decoding already and isn't owned by the frame. Return an error as it's indicative that it's a corrupt stream rather than just missing any slices. Prevents a segfault. --- libavcodec/vulkan_h264.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/libavcodec/vulkan_h264.c b/libavcodec/vulkan_h264.c index 089a181bb40..84bcef7933e 100644 --- a/libavcodec/vulkan_h264.c +++ b/libavcodec/vulkan_h264.c @@ -520,6 +520,9 @@ static int vk_h264_end_frame(AVCodecContext *avctx) if (!hp->h264_pic_info.sliceCount) return 0; + if (!vp->slices_buf) + return AVERROR(EINVAL); + if (!dec->session_params) { int err = vk_h264_create_params(avctx, &dec->session_params); if (err < 0) From f565da83463715b5dc0ea6272d51e3dc2c6d076b Mon Sep 17 00:00:00 2001 From: Fei Wang Date: Fri, 16 Jun 2023 08:58:08 +0800 Subject: [PATCH 1675/2172] lavfi/vaapi: Add function to get surface ID from AVFrame Signed-off-by: Fei Wang --- libavfilter/vaapi_vpp.c | 10 ++-------- libavfilter/vaapi_vpp.h | 5 +++++ 2 files changed, 7 insertions(+), 8 deletions(-) diff --git a/libavfilter/vaapi_vpp.c b/libavfilter/vaapi_vpp.c index a323dab8b8a..10d31977c61 100644 --- a/libavfilter/vaapi_vpp.c +++ b/libavfilter/vaapi_vpp.c @@ -518,7 +518,6 @@ int ff_vaapi_vpp_init_params(AVFilterContext *avctx, AVFrame *output_frame) { VAAPIVPPContext *ctx = avctx->priv; - VASurfaceID input_surface; int err; ctx->input_region = (VARectangle) { @@ -534,10 +533,8 @@ int ff_vaapi_vpp_init_params(AVFilterContext *avctx, output_frame->crop_left = 0; output_frame->crop_right = 0; - input_surface = (VASurfaceID)(uintptr_t)input_frame->data[3], - *params = (VAProcPipelineParameterBuffer) { - .surface = input_surface, + .surface = ff_vaapi_vpp_get_surface_id(input_frame), .surface_region = &ctx->input_region, .output_region = NULL, .output_background_color = VAAPI_VPP_BACKGROUND_BLACK, @@ -623,7 +620,6 @@ int ff_vaapi_vpp_render_pictures(AVFilterContext *avctx, AVFrame *output_frame) { VAAPIVPPContext *ctx = avctx->priv; - VASurfaceID output_surface; VABufferID *params_ids; VAStatus vas; int err; @@ -635,10 +631,8 @@ int ff_vaapi_vpp_render_pictures(AVFilterContext *avctx, for (int i = 0; i < cout; i++) params_ids[i] = VA_INVALID_ID; - output_surface = (VASurfaceID)(uintptr_t)output_frame->data[3]; - vas = vaBeginPicture(ctx->hwctx->display, - ctx->va_context, output_surface); + ctx->va_context, ff_vaapi_vpp_get_surface_id(output_frame)); if (vas != VA_STATUS_SUCCESS) { av_log(avctx, AV_LOG_ERROR, "Failed to attach new picture: " "%d (%s).\n", vas, vaErrorStr(vas)); diff --git a/libavfilter/vaapi_vpp.h b/libavfilter/vaapi_vpp.h index ead07036dce..cc845b854cc 100644 --- a/libavfilter/vaapi_vpp.h +++ b/libavfilter/vaapi_vpp.h @@ -27,6 +27,11 @@ #include "avfilter.h" +static inline VASurfaceID ff_vaapi_vpp_get_surface_id(const AVFrame *frame) +{ + return (uintptr_t)frame->data[3]; +} + // ARGB black, for VAProcPipelineParameterBuffer.output_background_color. #define VAAPI_VPP_BACKGROUND_BLACK 0xff000000 From f2d45bc565dc6ea5ee15505f4756accff773f5cd Mon Sep 17 00:00:00 2001 From: Fei Wang Date: Fri, 16 Jun 2023 08:58:09 +0800 Subject: [PATCH 1676/2172] lavfi/vaapi: Add some debug message Signed-off-by: Fei Wang --- libavfilter/vaapi_vpp.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/libavfilter/vaapi_vpp.c b/libavfilter/vaapi_vpp.c index 10d31977c61..4de19564e92 100644 --- a/libavfilter/vaapi_vpp.c +++ b/libavfilter/vaapi_vpp.c @@ -554,6 +554,10 @@ int ff_vaapi_vpp_init_params(AVFilterContext *avctx, if (err < 0) return err; + av_log(avctx, AV_LOG_DEBUG, "Filter frame from surface %#x to %#x.\n", + ff_vaapi_vpp_get_surface_id(input_frame), + ff_vaapi_vpp_get_surface_id(output_frame)); + return 0; } From 13a10fe8925ddc78500107e34799d84dd568a434 Mon Sep 17 00:00:00 2001 From: Fei Wang Date: Fri, 16 Jun 2023 08:58:10 +0800 Subject: [PATCH 1677/2172] lavfi/{denoise, procamp, scale, sharpness}_vaapi: Add passthrough mode Signed-off-by: Fei Wang --- libavfilter/vaapi_vpp.c | 15 ++++++++++++--- libavfilter/vaapi_vpp.h | 2 ++ libavfilter/vf_misc_vaapi.c | 9 +++++++++ libavfilter/vf_procamp_vaapi.c | 10 ++++++++++ libavfilter/vf_scale_vaapi.c | 13 +++++++++++++ 5 files changed, 46 insertions(+), 3 deletions(-) diff --git a/libavfilter/vaapi_vpp.c b/libavfilter/vaapi_vpp.c index 4de19564e92..cf2592e0689 100644 --- a/libavfilter/vaapi_vpp.c +++ b/libavfilter/vaapi_vpp.c @@ -95,6 +95,7 @@ int ff_vaapi_vpp_config_input(AVFilterLink *inlink) int ff_vaapi_vpp_config_output(AVFilterLink *outlink) { AVFilterContext *avctx = outlink->src; + AVFilterLink *inlink = avctx->inputs[0]; VAAPIVPPContext *ctx = avctx->priv; AVVAAPIHWConfig *hwconfig = NULL; AVHWFramesConstraints *constraints = NULL; @@ -111,6 +112,17 @@ int ff_vaapi_vpp_config_output(AVFilterLink *outlink) if (!ctx->output_height) ctx->output_height = avctx->inputs[0]->h; + outlink->w = ctx->output_width; + outlink->h = ctx->output_height; + + if (ctx->passthrough) { + if (inlink->hw_frames_ctx) + outlink->hw_frames_ctx = av_buffer_ref(inlink->hw_frames_ctx); + av_log(ctx, AV_LOG_VERBOSE, "Using VAAPI filter passthrough mode.\n"); + + return 0; + } + av_assert0(ctx->input_frames); ctx->device_ref = av_buffer_ref(ctx->input_frames->device_ref); if (!ctx->device_ref) { @@ -214,9 +226,6 @@ int ff_vaapi_vpp_config_output(AVFilterLink *outlink) return AVERROR(EIO); } - outlink->w = ctx->output_width; - outlink->h = ctx->output_height; - if (ctx->build_filter_params) { err = ctx->build_filter_params(avctx); if (err < 0) diff --git a/libavfilter/vaapi_vpp.h b/libavfilter/vaapi_vpp.h index cc845b854cc..6764ab0c390 100644 --- a/libavfilter/vaapi_vpp.h +++ b/libavfilter/vaapi_vpp.h @@ -56,6 +56,8 @@ typedef struct VAAPIVPPContext { VABufferID filter_buffers[VAProcFilterCount]; int nb_filter_buffers; + int passthrough; + int (*build_filter_params)(AVFilterContext *avctx); void (*pipeline_uninit)(AVFilterContext *avctx); diff --git a/libavfilter/vf_misc_vaapi.c b/libavfilter/vf_misc_vaapi.c index db3e69679af..71bc5e3c34a 100644 --- a/libavfilter/vf_misc_vaapi.c +++ b/libavfilter/vf_misc_vaapi.c @@ -131,6 +131,9 @@ static int misc_vaapi_filter_frame(AVFilterLink *inlink, AVFrame *input_frame) av_get_pix_fmt_name(input_frame->format), input_frame->width, input_frame->height, input_frame->pts); + if (vpp_ctx->passthrough) + return ff_filter_frame(outlink, input_frame); + if (vpp_ctx->va_context == VA_INVALID_ID) return AVERROR(EINVAL); @@ -176,11 +179,14 @@ static int misc_vaapi_filter_frame(AVFilterLink *inlink, AVFrame *input_frame) static av_cold int denoise_vaapi_init(AVFilterContext *avctx) { VAAPIVPPContext *vpp_ctx = avctx->priv; + DenoiseVAAPIContext *ctx = avctx->priv; ff_vaapi_vpp_ctx_init(avctx); vpp_ctx->pipeline_uninit = ff_vaapi_vpp_pipeline_uninit; vpp_ctx->build_filter_params = denoise_vaapi_build_filter_params; vpp_ctx->output_format = AV_PIX_FMT_NONE; + if (ctx->denoise == DENOISE_DEFAULT) + vpp_ctx->passthrough = 1; return 0; } @@ -188,11 +194,14 @@ static av_cold int denoise_vaapi_init(AVFilterContext *avctx) static av_cold int sharpness_vaapi_init(AVFilterContext *avctx) { VAAPIVPPContext *vpp_ctx = avctx->priv; + SharpnessVAAPIContext *ctx = avctx->priv; ff_vaapi_vpp_ctx_init(avctx); vpp_ctx->pipeline_uninit = ff_vaapi_vpp_pipeline_uninit; vpp_ctx->build_filter_params = sharpness_vaapi_build_filter_params; vpp_ctx->output_format = AV_PIX_FMT_NONE; + if (ctx->sharpness == SHARPNESS_DEFAULT) + vpp_ctx->passthrough = 1; return 0; } diff --git a/libavfilter/vf_procamp_vaapi.c b/libavfilter/vf_procamp_vaapi.c index 4a3b9d0766f..acfc72947c7 100644 --- a/libavfilter/vf_procamp_vaapi.c +++ b/libavfilter/vf_procamp_vaapi.c @@ -136,6 +136,9 @@ static int procamp_vaapi_filter_frame(AVFilterLink *inlink, AVFrame *input_frame av_get_pix_fmt_name(input_frame->format), input_frame->width, input_frame->height, input_frame->pts); + if (vpp_ctx->passthrough) + return ff_filter_frame(outlink, input_frame); + if (vpp_ctx->va_context == VA_INVALID_ID) return AVERROR(EINVAL); @@ -179,11 +182,18 @@ static int procamp_vaapi_filter_frame(AVFilterLink *inlink, AVFrame *input_frame static av_cold int procamp_vaapi_init(AVFilterContext *avctx) { VAAPIVPPContext *vpp_ctx = avctx->priv; + ProcampVAAPIContext *ctx = avctx->priv; + float eps = 1.0e-10f; ff_vaapi_vpp_ctx_init(avctx); vpp_ctx->pipeline_uninit = ff_vaapi_vpp_pipeline_uninit; vpp_ctx->build_filter_params = procamp_vaapi_build_filter_params; vpp_ctx->output_format = AV_PIX_FMT_NONE; + if (fabs(ctx->saturation - SATURATION_DEFAULT) < eps && + fabs(ctx->bright - BRIGHTNESS_DEFAULT) < eps && + fabs(ctx->contrast - CONTRAST_DEFAULT) < eps && + fabs(ctx->hue - HUE_DEFAULT) < eps) + vpp_ctx->passthrough = 1; return 0; } diff --git a/libavfilter/vf_scale_vaapi.c b/libavfilter/vf_scale_vaapi.c index a371077ee02..11bd7a9de9c 100644 --- a/libavfilter/vf_scale_vaapi.c +++ b/libavfilter/vf_scale_vaapi.c @@ -85,6 +85,16 @@ static int scale_vaapi_config_output(AVFilterLink *outlink) ff_scale_adjust_dimensions(inlink, &vpp_ctx->output_width, &vpp_ctx->output_height, ctx->force_original_aspect_ratio, ctx->force_divisible_by); + if (inlink->w == vpp_ctx->output_width && inlink->h == vpp_ctx->output_height && + (vpp_ctx->input_frames->sw_format == vpp_ctx->output_format || + vpp_ctx->output_format == AV_PIX_FMT_NONE) && + ctx->colour_primaries == AVCOL_PRI_UNSPECIFIED && + ctx->colour_transfer == AVCOL_TRC_UNSPECIFIED && + ctx->colour_matrix == AVCOL_SPC_UNSPECIFIED && + ctx->colour_range == AVCOL_RANGE_UNSPECIFIED && + ctx->chroma_location == AVCHROMA_LOC_UNSPECIFIED) + vpp_ctx->passthrough = 1; + err = ff_vaapi_vpp_config_output(outlink); if (err < 0) return err; @@ -111,6 +121,9 @@ static int scale_vaapi_filter_frame(AVFilterLink *inlink, AVFrame *input_frame) av_get_pix_fmt_name(input_frame->format), input_frame->width, input_frame->height, input_frame->pts); + if (vpp_ctx->passthrough) + return ff_filter_frame(outlink, input_frame); + if (vpp_ctx->va_context == VA_INVALID_ID) return AVERROR(EINVAL); From 28ed898ac6dcb78dab42913513e85038c069aa33 Mon Sep 17 00:00:00 2001 From: Tong Wu Date: Mon, 19 Jun 2023 14:15:07 +0800 Subject: [PATCH 1678/2172] avutil/hwcontext_qsv: register free function for device_derive When qsv device is created by device_derive, the ctx->free function is not registered, causing potential memory leak because of not properly closing the MFX session. Signed-off-by: Tong Wu Signed-off-by: Wenbin Chen --- libavutil/hwcontext_qsv.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/libavutil/hwcontext_qsv.c b/libavutil/hwcontext_qsv.c index 4ed4242ddfb..b1759a93e19 100644 --- a/libavutil/hwcontext_qsv.c +++ b/libavutil/hwcontext_qsv.c @@ -2094,6 +2094,15 @@ static int qsv_device_derive(AVHWDeviceContext *ctx, AVDictionary *opts, int flags) { mfxIMPL impl; + QSVDevicePriv *priv; + + priv = av_mallocz(sizeof(*priv)); + if (!priv) + return AVERROR(ENOMEM); + + ctx->user_opaque = priv; + ctx->free = qsv_device_free; + impl = choose_implementation("hw_any", child_device_ctx->type); return qsv_device_derive_from_child(ctx, impl, child_device_ctx, flags); From 8ea31f694a2a0634872f38aa214a4a6cd678120c Mon Sep 17 00:00:00 2001 From: Tong Wu Date: Mon, 19 Jun 2023 14:15:08 +0800 Subject: [PATCH 1679/2172] lavu/hwcontext_qsv: fix memory leak for d3d11va impl Signed-off-by: Tong Wu --- libavutil/hwcontext_qsv.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/libavutil/hwcontext_qsv.c b/libavutil/hwcontext_qsv.c index b1759a93e19..bcf07f064c9 100644 --- a/libavutil/hwcontext_qsv.c +++ b/libavutil/hwcontext_qsv.c @@ -665,6 +665,7 @@ static mfxStatus frame_get_hdl(mfxHDL pthis, mfxMemId mid, mfxHDL *hdl) static int qsv_d3d11_update_config(void *ctx, mfxHDL handle, mfxConfig cfg) { + int ret = AVERROR_UNKNOWN; #if CONFIG_D3D11VA mfxStatus sts; IDXGIAdapter *pDXGIAdapter; @@ -679,7 +680,8 @@ static int qsv_d3d11_update_config(void *ctx, mfxHDL handle, mfxConfig cfg) hr = IDXGIDevice_GetAdapter(pDXGIDevice, &pDXGIAdapter); if (FAILED(hr)) { av_log(ctx, AV_LOG_ERROR, "Error IDXGIDevice_GetAdapter %d\n", hr); - goto fail; + IDXGIDevice_Release(pDXGIDevice); + return ret; } hr = IDXGIAdapter_GetDesc(pDXGIAdapter, &adapterDesc); @@ -689,7 +691,7 @@ static int qsv_d3d11_update_config(void *ctx, mfxHDL handle, mfxConfig cfg) } } else { av_log(ctx, AV_LOG_ERROR, "Error ID3D11Device_QueryInterface %d\n", hr); - goto fail; + return ret; } impl_value.Type = MFX_VARIANT_TYPE_U16; @@ -722,11 +724,13 @@ static int qsv_d3d11_update_config(void *ctx, mfxHDL handle, mfxConfig cfg) goto fail; } - return 0; + ret = 0; fail: + IDXGIAdapter_Release(pDXGIAdapter); + IDXGIDevice_Release(pDXGIDevice); #endif - return AVERROR_UNKNOWN; + return ret; } static int qsv_d3d9_update_config(void *ctx, mfxHDL handle, mfxConfig cfg) From d51b0580e423f57d9957a0b4d29800a82389f4d3 Mon Sep 17 00:00:00 2001 From: Tong Wu Date: Mon, 19 Jun 2023 14:15:09 +0800 Subject: [PATCH 1680/2172] lavu/hwcontext_qsv: fix memory leak for d3d9 impl Signed-off-by: Tong Wu --- libavutil/hwcontext_qsv.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/libavutil/hwcontext_qsv.c b/libavutil/hwcontext_qsv.c index bcf07f064c9..d4b564ba2db 100644 --- a/libavutil/hwcontext_qsv.c +++ b/libavutil/hwcontext_qsv.c @@ -756,25 +756,28 @@ static int qsv_d3d9_update_config(void *ctx, mfxHDL handle, mfxConfig cfg) hr = IDirect3DDeviceManager9_LockDevice(devmgr, device_handle, &device, TRUE); if (FAILED(hr)) { av_log(ctx, AV_LOG_ERROR, "Error LockDevice %d\n", hr); + IDirect3DDeviceManager9_CloseDeviceHandle(devmgr, device_handle); goto fail; } hr = IDirect3DDevice9Ex_GetCreationParameters(device, ¶ms); if (FAILED(hr)) { av_log(ctx, AV_LOG_ERROR, "Error IDirect3DDevice9_GetCreationParameters %d\n", hr); + IDirect3DDevice9Ex_Release(device); goto unlock; } hr = IDirect3DDevice9Ex_GetDirect3D(device, &d3d9ex); if (FAILED(hr)) { av_log(ctx, AV_LOG_ERROR, "Error IDirect3DDevice9Ex_GetAdapterLUID %d\n", hr); + IDirect3DDevice9Ex_Release(device); goto unlock; } hr = IDirect3D9Ex_GetAdapterLUID(d3d9ex, params.AdapterOrdinal, &luid); if (FAILED(hr)) { av_log(ctx, AV_LOG_ERROR, "Error IDirect3DDevice9Ex_GetAdapterLUID %d\n", hr); - goto unlock; + goto release; } impl_value.Type = MFX_VARIANT_TYPE_PTR; @@ -784,13 +787,18 @@ static int qsv_d3d9_update_config(void *ctx, mfxHDL handle, mfxConfig cfg) if (sts != MFX_ERR_NONE) { av_log(ctx, AV_LOG_ERROR, "Error adding a MFX configuration" "DeviceLUID property: %d.\n", sts); - goto unlock; + goto release; } ret = 0; +release: + IDirect3D9Ex_Release(d3d9ex); + IDirect3DDevice9Ex_Release(device); + unlock: IDirect3DDeviceManager9_UnlockDevice(devmgr, device_handle, FALSE); + IDirect3DDeviceManager9_CloseDeviceHandle(devmgr, device_handle); fail: #endif return ret; From 285c7f6f6b3740725101e7d5cea94a47e2915298 Mon Sep 17 00:00:00 2001 From: Gyan Doshi Date: Mon, 26 Jun 2023 16:02:42 +0530 Subject: [PATCH 1681/2172] doc/filters: correct luma terminology Partially fixes #10427 See https://poynton.ca/notes/colour_and_gamma/ColorFAQ.html#RTFToC11 for ref. --- doc/filters.texi | 38 +++++++++++++++++++------------------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/doc/filters.texi b/doc/filters.texi index f596773af65..f17488c7c77 100644 --- a/doc/filters.texi +++ b/doc/filters.texi @@ -8482,10 +8482,10 @@ This filter supports the all above options as @ref{commands}. @section bbox Compute the bounding box for the non-black pixels in the input frame -luminance plane. +luma plane. This filter computes the bounding box containing all the pixels with a -luminance value greater than the minimum allowed value. +luma value greater than the minimum allowed value. The parameters describing the bounding box are printed on the filter log. @@ -8493,7 +8493,7 @@ The filter accepts the following option: @table @option @item min_val -Set the minimal luminance value. Default is @code{16}. +Set the minimal luma value. Default is @code{16}. @end table @subsection Commands @@ -8616,14 +8616,14 @@ Default value is 0.98. @item pixel_black_th, pix_th Set the threshold for considering a pixel "black". -The threshold expresses the maximum pixel luminance value for which a +The threshold expresses the maximum pixel luma value for which a pixel is considered "black". The provided value is scaled according to the following equation: @example -@var{absolute_threshold} = @var{luminance_minimum_value} + @var{pixel_black_th} * @var{luminance_range_size} +@var{absolute_threshold} = @var{luma_minimum_value} + @var{pixel_black_th} * @var{luma_range_size} @end example -@var{luminance_range_size} and @var{luminance_minimum_value} depend on +@var{luma_range_size} and @var{luma_minimum_value} depend on the input video format, the range is [0-255] for YUV full-range formats and [16-235] for YUV non full-range formats. @@ -14613,7 +14613,7 @@ The filter accepts the following options: @table @option @item lum_expr, lum -Set the luminance expression. +Set the luma expression. @item cb_expr, cb Set the chrominance blue expression. @item cr_expr, cr @@ -14638,7 +14638,7 @@ colorspace. If one of the chrominance expression is not defined, it falls back on the other one. If no alpha expression is specified it will evaluate to opaque value. If none of chrominance expressions are specified, they will evaluate -to the luminance expression. +to the luma expression. The expressions can use the following variables and functions: @@ -14669,7 +14669,7 @@ Return the value of the pixel at location (@var{x},@var{y}) of the current plane. @item lum(x, y) -Return the value of the pixel at location (@var{x},@var{y}) of the luminance +Return the value of the pixel at location (@var{x},@var{y}) of the luma plane. @item cb(x, y) @@ -17129,7 +17129,7 @@ set blue component expression alpha component expression @item y -set Y/luminance component expression +set Y/luma component expression @item u set U/Cb component expression @item v @@ -17204,7 +17204,7 @@ lutyuv="y=negval:u=negval:v=negval" @end example @item -Negate luminance: +Negate luma: @example lutyuv=y=negval @end example @@ -17234,7 +17234,7 @@ format=rgba,lutrgb=a="maxval-minval/2" @end example @item -Correct luminance gamma by a factor of 0.5: +Correct luma gamma by a factor of 0.5: @example lutyuv=y=gammaval(0.5) @end example @@ -19443,10 +19443,10 @@ Honor the quality commands for this subfilter. Do chrominance filtering, too (default). @item y/nochrom -Do luminance filtering only (no chrominance). +Do luma filtering only (no chrominance). @item n/noluma -Do chrominance filtering only (no luminance). +Do chrominance filtering only (no luma). @end table These options can be appended after the subfilter name, separated by a '|'. @@ -19518,7 +19518,7 @@ larger -> stronger filtering @item al/autolevels[:f/fullyrange], automatic brightness / contrast correction @table @option @item f/fullyrange -Stretch luminance to @code{0-255}. +Stretch luma to @code{0-255}. @end table @item lb/linblenddeint @@ -19586,7 +19586,7 @@ pp=default/tmpnoise|1|2|3 @end example @item -Apply deblocking on luminance only, and switch vertical deblocking on or off +Apply deblocking on luma only, and switch vertical deblocking on or off automatically depending on available CPU time: @example pp=hb|y/vb|a @@ -25032,7 +25032,7 @@ This filter supports same @ref{commands} as options. @section waveform Video waveform monitor. -The waveform monitor plots color component intensity. By default luminance +The waveform monitor plots color component intensity. By default luma only. Each column of the waveform corresponds to a column of pixels in the source video. @@ -25087,7 +25087,7 @@ correction is easy to perform by making level adjustments the three waveforms. Default is @code{stack}. @item components, c -Set which color components to display. Default is 1, which means only luminance +Set which color components to display. Default is 1, which means only luma or red color component if input is in RGB colorspace. If is set for example to 7 it will display all 3 (if) available color components. @@ -28589,7 +28589,7 @@ color=c=red@@0.2:s=qcif:r=10 @item If the input content is to be ignored, @code{nullsrc} can be used. The -following command generates noise in the luminance plane by employing +following command generates noise in the luma plane by employing the @code{geq} filter: @example nullsrc=s=256x256, geq=random(1)*255:128:128 From 6ff95758e6bf47004f69c56d7547a971c4782b21 Mon Sep 17 00:00:00 2001 From: James Almer Date: Tue, 27 Jun 2023 12:52:38 -0300 Subject: [PATCH 1682/2172] avformat/evc: use get_ue_golomb_long() This partially reverts commit d0fc1b3507c, which reintroduced a regression originally fixed in 5e9986fd2d. Signed-off-by: James Almer --- libavformat/evc.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/libavformat/evc.c b/libavformat/evc.c index a4fa42d9026..95f07266b03 100644 --- a/libavformat/evc.c +++ b/libavformat/evc.c @@ -93,7 +93,7 @@ static int evcc_parse_sps(const uint8_t *bs, int bs_size, EVCDecoderConfiguratio if (ret < 0) return ret; - sps_seq_parameter_set_id = get_ue_golomb_31(&gb); + sps_seq_parameter_set_id = get_ue_golomb_long(&gb); if (sps_seq_parameter_set_id >= EVC_MAX_SPS_COUNT) return AVERROR_INVALIDDATA; @@ -111,15 +111,15 @@ static int evcc_parse_sps(const uint8_t *bs, int bs_size, EVCDecoderConfiguratio // 1 - 4:2:0 // 2 - 4:2:2 // 3 - 4:4:4 - evcc->chroma_format_idc = get_ue_golomb_31(&gb); + evcc->chroma_format_idc = get_ue_golomb_long(&gb); if (evcc->chroma_format_idc > 3) return AVERROR_INVALIDDATA; evcc->pic_width_in_luma_samples = get_ue_golomb_long(&gb); evcc->pic_height_in_luma_samples = get_ue_golomb_long(&gb); - evcc->bit_depth_luma_minus8 = get_ue_golomb_31(&gb); - evcc->bit_depth_chroma_minus8 = get_ue_golomb_31(&gb); + evcc->bit_depth_luma_minus8 = get_ue_golomb_long(&gb); + evcc->bit_depth_chroma_minus8 = get_ue_golomb_long(&gb); // EVCDecoderConfigurationRecord can't store values > 7. Limit it to bit depth 14. if (evcc->bit_depth_luma_minus8 > 6 || evcc->bit_depth_chroma_minus8 > 6) return AVERROR_INVALIDDATA; From 9b6d191a66a8d9b3064efecc79a9f44fb14d7875 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Sat, 10 Jun 2023 01:09:52 +0200 Subject: [PATCH 1683/2172] avcodec/jpeg2000dec: Check for reduction factor and image offset MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This combination is not working (it writes out of array) Reviewed-by: Tomas Härdin Signed-off-by: Michael Niedermayer --- libavcodec/jpeg2000dec.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/libavcodec/jpeg2000dec.c b/libavcodec/jpeg2000dec.c index 0e95cca64e0..d6f2a5938e8 100644 --- a/libavcodec/jpeg2000dec.c +++ b/libavcodec/jpeg2000dec.c @@ -238,6 +238,11 @@ static int get_siz(Jpeg2000DecoderContext *s) return AVERROR_INVALIDDATA; } + if (s->reduction_factor && (s->image_offset_x || s->image_offset_y) ){ + av_log(s->avctx, AV_LOG_ERROR, "reduction factor with image offsets is not fully implemented"); + return AVERROR_PATCHWELCOME; + } + s->ncomponents = ncomponents; if (s->tile_width <= 0 || s->tile_height <= 0) { From 9e3f07aa21ea71c394116cd5b180c6d710d897d8 Mon Sep 17 00:00:00 2001 From: Dmitrii Ovchinnikov Date: Wed, 17 May 2023 14:59:39 +0200 Subject: [PATCH 1684/2172] amfenc: Update the min version to 1.4.29.0 for AMF SDK. --- configure | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure b/configure index ed9efad9856..f23252dfec0 100755 --- a/configure +++ b/configure @@ -7185,7 +7185,7 @@ fi enabled amf && check_cpp_condition amf "AMF/core/Version.h" \ - "(AMF_VERSION_MAJOR << 48 | AMF_VERSION_MINOR << 32 | AMF_VERSION_RELEASE << 16 | AMF_VERSION_BUILD_NUM) >= 0x00010004001c0000" + "(AMF_VERSION_MAJOR << 48 | AMF_VERSION_MINOR << 32 | AMF_VERSION_RELEASE << 16 | AMF_VERSION_BUILD_NUM) >= 0x00010004001d0000" # Funny iconv installations are not unusual, so check it after all flags have been set if enabled libc_iconv; then From f593dc98bfe4196ad60510008d43764e526d8cb9 Mon Sep 17 00:00:00 2001 From: Dmitrii Ovchinnikov Date: Wed, 17 May 2023 14:59:40 +0200 Subject: [PATCH 1685/2172] libavcodec/amfenc: add PreAnalysis support Additional information about the work of preanalysis can be found here: https://github.com/GPUOpen-LibrariesAndSDKs/AMF/wiki/PreProcessing%20and%20PreAnalysis --- libavcodec/amfenc.c | 101 +++++++++++---------- libavcodec/amfenc.h | 27 +++++- libavcodec/amfenc_av1.c | 133 ++++++++++++++++++++++++++-- libavcodec/amfenc_h264.c | 187 ++++++++++++++++++++++++++++++++++----- libavcodec/amfenc_hevc.c | 144 +++++++++++++++++++++++++++--- 5 files changed, 503 insertions(+), 89 deletions(-) diff --git a/libavcodec/amfenc.c b/libavcodec/amfenc.c index c487fc48aad..cb48f8c273c 100644 --- a/libavcodec/amfenc.c +++ b/libavcodec/amfenc.c @@ -481,7 +481,7 @@ static int amf_copy_buffer(AVCodecContext *avctx, AVPacket *pkt, AMFBuffer *buff AVERROR_UNKNOWN, "timestamp_list is empty\n"); // calc dts shift if max_b_frames > 0 - if (avctx->max_b_frames > 0 && ctx->dts_delay == 0) { + if ((ctx->max_b_frames > 0 || ((ctx->pa_adaptive_mini_gop == 1) ? true : false)) && ctx->dts_delay == 0) { int64_t timestamp_last = AV_NOPTS_VALUE; size_t can_read = av_fifo_can_read(ctx->timestamp_list); @@ -593,6 +593,8 @@ int ff_amf_receive_packet(AVCodecContext *avctx, AVPacket *avpkt) AMFData *data = NULL; AVFrame *frame = ctx->delayed_frame; int block_and_wait; + int query_output_data_flag = 0; + AMF_RESULT res_resubmit; if (!ctx->encoder) return AVERROR(EINVAL); @@ -715,56 +717,61 @@ int ff_amf_receive_packet(AVCodecContext *avctx, AVPacket *avpkt) do { block_and_wait = 0; // poll data - res_query = ctx->encoder->pVtbl->QueryOutput(ctx->encoder, &data); - if (data) { - // copy data to packet - AMFBuffer* buffer; - AMFGuid guid = IID_AMFBuffer(); - data->pVtbl->QueryInterface(data, &guid, (void**)&buffer); // query for buffer interface - ret = amf_copy_buffer(avctx, avpkt, buffer); - - buffer->pVtbl->Release(buffer); - - if (data->pVtbl->HasProperty(data, L"av_frame_ref")) { - AMFBuffer *frame_ref_storage_buffer; - res = amf_get_property_buffer(data, L"av_frame_ref", &frame_ref_storage_buffer); - AMF_RETURN_IF_FALSE(ctx, res == AMF_OK, AVERROR_UNKNOWN, "GetProperty failed for \"av_frame_ref\" with error %d\n", res); - amf_release_buffer_with_frame_ref(frame_ref_storage_buffer); - ctx->hwsurfaces_in_queue--; - } - - data->pVtbl->Release(data); + if (!avpkt->data && !avpkt->buf) { + res_query = ctx->encoder->pVtbl->QueryOutput(ctx->encoder, &data); + if (data) { + query_output_data_flag = 1; + // copy data to packet + AMFBuffer *buffer; + AMFGuid guid = IID_AMFBuffer(); + data->pVtbl->QueryInterface(data, &guid, (void**)&buffer); // query for buffer interface + ret = amf_copy_buffer(avctx, avpkt, buffer); + + buffer->pVtbl->Release(buffer); + + if (data->pVtbl->HasProperty(data, L"av_frame_ref")) { + AMFBuffer* frame_ref_storage_buffer; + res = amf_get_property_buffer(data, L"av_frame_ref", &frame_ref_storage_buffer); + AMF_RETURN_IF_FALSE(ctx, res == AMF_OK, AVERROR_UNKNOWN, "GetProperty failed for \"av_frame_ref\" with error %d\n", res); + amf_release_buffer_with_frame_ref(frame_ref_storage_buffer); + ctx->hwsurfaces_in_queue--; + } - AMF_RETURN_IF_FALSE(ctx, ret >= 0, ret, "amf_copy_buffer() failed with error %d\n", ret); + data->pVtbl->Release(data); - if (ctx->delayed_surface != NULL) { // try to resubmit frame - res = ctx->encoder->pVtbl->SubmitInput(ctx->encoder, (AMFData*)ctx->delayed_surface); - if (res != AMF_INPUT_FULL) { - int64_t pts = ctx->delayed_surface->pVtbl->GetPts(ctx->delayed_surface); - ctx->delayed_surface->pVtbl->Release(ctx->delayed_surface); - ctx->delayed_surface = NULL; - av_frame_unref(ctx->delayed_frame); - AMF_RETURN_IF_FALSE(ctx, res == AMF_OK, AVERROR_UNKNOWN, "Repeated SubmitInput() failed with error %d\n", res); + AMF_RETURN_IF_FALSE(ctx, ret >= 0, ret, "amf_copy_buffer() failed with error %d\n", ret); + } + } + res_resubmit = AMF_OK; + if (ctx->delayed_surface != NULL) { // try to resubmit frame + res_resubmit = ctx->encoder->pVtbl->SubmitInput(ctx->encoder, (AMFData*)ctx->delayed_surface); + if (res_resubmit != AMF_INPUT_FULL) { + int64_t pts = ctx->delayed_surface->pVtbl->GetPts(ctx->delayed_surface); + ctx->delayed_surface->pVtbl->Release(ctx->delayed_surface); + ctx->delayed_surface = NULL; + av_frame_unref(ctx->delayed_frame); + AMF_RETURN_IF_FALSE(ctx, res_resubmit == AMF_OK, AVERROR_UNKNOWN, "Repeated SubmitInput() failed with error %d\n", res_resubmit); + + ret = av_fifo_write(ctx->timestamp_list, &pts, 1); + if (ret < 0) + return ret; + } + } else if (ctx->delayed_drain) { // try to resubmit drain + res = ctx->encoder->pVtbl->Drain(ctx->encoder); + if (res != AMF_INPUT_FULL) { + ctx->delayed_drain = 0; + ctx->eof = 1; // drain started + AMF_RETURN_IF_FALSE(ctx, res == AMF_OK, AVERROR_UNKNOWN, "Repeated Drain() failed with error %d\n", res); + } else { + av_log(avctx, AV_LOG_WARNING, "Data acquired but delayed drain submission got AMF_INPUT_FULL- should not happen\n"); + } + } - ret = av_fifo_write(ctx->timestamp_list, &pts, 1); - if (ret < 0) - return ret; - } else { - av_log(avctx, AV_LOG_WARNING, "Data acquired but delayed frame submission got AMF_INPUT_FULL- should not happen\n"); - } - } else if (ctx->delayed_drain) { // try to resubmit drain - res = ctx->encoder->pVtbl->Drain(ctx->encoder); - if (res != AMF_INPUT_FULL) { - ctx->delayed_drain = 0; - ctx->eof = 1; // drain started - AMF_RETURN_IF_FALSE(ctx, res == AMF_OK, AVERROR_UNKNOWN, "Repeated Drain() failed with error %d\n", res); - } else { - av_log(avctx, AV_LOG_WARNING, "Data acquired but delayed drain submission got AMF_INPUT_FULL- should not happen\n"); - } + if (query_output_data_flag == 0) { + if (res_resubmit == AMF_INPUT_FULL || ctx->delayed_drain || (ctx->eof && res_query != AMF_EOF) || (ctx->hwsurfaces_in_queue >= ctx->hwsurfaces_in_queue_max)) { + block_and_wait = 1; + av_usleep(1000); } - } else if (ctx->delayed_surface != NULL || ctx->delayed_drain || (ctx->eof && res_query != AMF_EOF) || (ctx->hwsurfaces_in_queue >= ctx->hwsurfaces_in_queue_max)) { - block_and_wait = 1; - av_usleep(1000); // wait and poll again } } while (block_and_wait); diff --git a/libavcodec/amfenc.h b/libavcodec/amfenc.h index 66e06807196..2dbd378ef87 100644 --- a/libavcodec/amfenc.h +++ b/libavcodec/amfenc.h @@ -30,6 +30,7 @@ #include "avcodec.h" #include "hwconfig.h" +#define MAX_LOOKAHEAD_DEPTH 41 /** * AMF trace writer callback class @@ -84,7 +85,7 @@ typedef struct AmfContext { int usage; int profile; int level; - int preanalysis; + int preencode; int quality; int b_frame_delta_qp; int ref_b_frame_delta_qp; @@ -107,6 +108,10 @@ typedef struct AmfContext { int me_half_pel; int me_quarter_pel; int aud; + int max_consecutive_b_frames; + int max_b_frames; + int qvbr_quality_level; + int hw_high_motion_quality_boost; // HEVC - specific options @@ -122,6 +127,26 @@ typedef struct AmfContext { enum AMF_VIDEO_ENCODER_AV1_ALIGNMENT_MODE_ENUM align; + // Preanalysis - specific options + + int preanalysis; + int pa_activity_type; + int pa_scene_change_detection; + int pa_scene_change_detection_sensitivity; + int pa_static_scene_detection; + int pa_static_scene_detection_sensitivity; + int pa_initial_qp; + int pa_max_qp; + int pa_caq_strength; + int pa_frame_sad; + int pa_ltr; + int pa_lookahead_buffer_depth; + int pa_paq_mode; + int pa_taq_mode; + int pa_high_motion_quality_boost_mode; + int pa_adaptive_mini_gop; + + } AmfContext; extern const AVCodecHWConfigInternal *const ff_amfenc_hw_configs[]; diff --git a/libavcodec/amfenc_av1.c b/libavcodec/amfenc_av1.c index ad09b7910a2..30c0a9fad25 100644 --- a/libavcodec/amfenc_av1.c +++ b/libavcodec/amfenc_av1.c @@ -65,21 +65,29 @@ static const AVOption options[] = { { "quality", "", 0, AV_OPT_TYPE_CONST, {.i64 = AMF_VIDEO_ENCODER_AV1_QUALITY_PRESET_QUALITY }, 0, 0, VE, "quality" }, { "high_quality", "", 0, AV_OPT_TYPE_CONST, {.i64 = AMF_VIDEO_ENCODER_AV1_QUALITY_PRESET_HIGH_QUALITY }, 0, 0, VE, "quality" }, - { "rc", "Set the rate control mode", OFFSET(rate_control_mode), AV_OPT_TYPE_INT, {.i64 = AMF_VIDEO_ENCODER_AV1_RATE_CONTROL_METHOD_UNKNOWN }, AMF_VIDEO_ENCODER_AV1_RATE_CONTROL_METHOD_UNKNOWN, AMF_VIDEO_ENCODER_AV1_RATE_CONTROL_METHOD_CBR, VE, "rc" }, + { "rc", "Set the rate control mode", OFFSET(rate_control_mode), AV_OPT_TYPE_INT, {.i64 = AMF_VIDEO_ENCODER_AV1_RATE_CONTROL_METHOD_UNKNOWN }, AMF_VIDEO_ENCODER_AV1_RATE_CONTROL_METHOD_UNKNOWN, AMF_VIDEO_ENCODER_AV1_RATE_CONTROL_METHOD_HIGH_QUALITY_CBR, VE, "rc" }, { "cqp", "Constant Quantization Parameter", 0, AV_OPT_TYPE_CONST, {.i64 = AMF_VIDEO_ENCODER_AV1_RATE_CONTROL_METHOD_CONSTANT_QP }, 0, 0, VE, "rc" }, { "vbr_latency", "Latency Constrained Variable Bitrate", 0, AV_OPT_TYPE_CONST, {.i64 = AMF_VIDEO_ENCODER_AV1_RATE_CONTROL_METHOD_LATENCY_CONSTRAINED_VBR }, 0, 0, VE, "rc" }, { "vbr_peak", "Peak Contrained Variable Bitrate", 0, AV_OPT_TYPE_CONST, {.i64 = AMF_VIDEO_ENCODER_AV1_RATE_CONTROL_METHOD_PEAK_CONSTRAINED_VBR }, 0, 0, VE, "rc" }, { "cbr", "Constant Bitrate", 0, AV_OPT_TYPE_CONST, {.i64 = AMF_VIDEO_ENCODER_AV1_RATE_CONTROL_METHOD_CBR }, 0, 0, VE, "rc" }, + { "qvbr", "Quality Variable Bitrate", 0, AV_OPT_TYPE_CONST, {.i64 = AMF_VIDEO_ENCODER_AV1_RATE_CONTROL_METHOD_QUALITY_VBR }, 0, 0, VE, "rc" }, + { "hqvbr", "High Quality Variable Bitrate", 0, AV_OPT_TYPE_CONST, {.i64 = AMF_VIDEO_ENCODER_AV1_RATE_CONTROL_METHOD_HIGH_QUALITY_VBR }, 0, 0, VE, "rc" }, + { "hqcbr", "High Quality Constant Bitrate", 0, AV_OPT_TYPE_CONST, {.i64 = AMF_VIDEO_ENCODER_AV1_RATE_CONTROL_METHOD_HIGH_QUALITY_CBR }, 0, 0, VE, "rc" }, + + { "qvbr_quality_level", "Sets the QVBR quality level", OFFSET(qvbr_quality_level), AV_OPT_TYPE_INT, {.i64 = -1 }, -1, 51, VE }, + { "header_insertion_mode", "Set header insertion mode", OFFSET(header_insertion_mode), AV_OPT_TYPE_INT,{.i64 = AMF_VIDEO_ENCODER_AV1_HEADER_INSERTION_MODE_NONE }, AMF_VIDEO_ENCODER_AV1_HEADER_INSERTION_MODE_NONE, AMF_VIDEO_ENCODER_AV1_HEADER_INSERTION_MODE_KEY_FRAME_ALIGNED, VE, "hdrmode" }, { "none", "", 0, AV_OPT_TYPE_CONST, {.i64 = AMF_VIDEO_ENCODER_AV1_HEADER_INSERTION_MODE_NONE }, 0, 0, VE, "hdrmode" }, { "gop", "", 0, AV_OPT_TYPE_CONST, {.i64 = AMF_VIDEO_ENCODER_AV1_HEADER_INSERTION_MODE_GOP_ALIGNED }, 0, 0, VE, "hdrmode" }, { "frame", "", 0, AV_OPT_TYPE_CONST, {.i64 = AMF_VIDEO_ENCODER_AV1_HEADER_INSERTION_MODE_KEY_FRAME_ALIGNED }, 0, 0, VE, "hdrmode" }, - { "preanalysis", "Enable preanalysis", OFFSET(preanalysis), AV_OPT_TYPE_BOOL, {.i64 = 0 }, 0, 1, VE}, + { "preencode", "Enable preencode", OFFSET(preencode), AV_OPT_TYPE_BOOL, {.i64 = 0 }, 0, 1, VE}, { "enforce_hrd", "Enforce HRD", OFFSET(enforce_hrd), AV_OPT_TYPE_BOOL, {.i64 = 0 }, 0, 1, VE}, { "filler_data", "Filler Data Enable", OFFSET(filler_data), AV_OPT_TYPE_BOOL, {.i64 = 0 }, 0, 1, VE}, + { "high_motion_quality_boost_enable", "Enable High motion quality boost mode", OFFSET(hw_high_motion_quality_boost), AV_OPT_TYPE_BOOL, {.i64 = -1 }, -1, 1, VE }, + // min_qp_i -> min_qp_intra, min_qp_p -> min_qp_inter { "min_qp_i", "min quantization parameter for I-frame", OFFSET(min_qp_i), AV_OPT_TYPE_INT, {.i64 = -1 }, -1, 255, VE }, { "max_qp_i", "max quantization parameter for I-frame", OFFSET(max_qp_i), AV_OPT_TYPE_INT, {.i64 = -1 }, -1, 255, VE }, @@ -94,6 +102,53 @@ static const AVOption options[] = { { "1080p", "", 0, AV_OPT_TYPE_CONST, {.i64 = AMF_VIDEO_ENCODER_AV1_ALIGNMENT_MODE_64X16_1080P_CODED_1082 }, 0, 0, VE, "align" }, { "none", "", 0, AV_OPT_TYPE_CONST, {.i64 = AMF_VIDEO_ENCODER_AV1_ALIGNMENT_MODE_NO_RESTRICTIONS }, 0, 0, VE, "align" }, + { "log_to_dbg", "Enable AMF logging to debug output", OFFSET(log_to_dbg), AV_OPT_TYPE_BOOL,{.i64 = 0 }, 0, 1, VE }, + + //Pre Analysis options + { "preanalysis", "Enable preanalysis", OFFSET(preanalysis), AV_OPT_TYPE_BOOL, {.i64 = -1 }, -1, 1, VE }, + + { "pa_activity_type", "Set the type of activity analysis", OFFSET(pa_activity_type), AV_OPT_TYPE_INT, {.i64 = -1 }, -1, AMF_PA_ACTIVITY_YUV, VE, "activity_type" }, + { "y", "activity y", 0, AV_OPT_TYPE_CONST, {.i64 = AMF_PA_ACTIVITY_Y }, 0, 0, VE, "activity_type" }, + { "yuv", "activity yuv", 0, AV_OPT_TYPE_CONST, {.i64 = AMF_PA_ACTIVITY_YUV }, 0, 0, VE, "activity_type" }, + + { "pa_scene_change_detection_enable", "Enable scene change detection", OFFSET(pa_scene_change_detection), AV_OPT_TYPE_BOOL, {.i64 = -1 }, -1, 1, VE }, + + { "pa_scene_change_detection_sensitivity", "Set the sensitivity of scene change detection", OFFSET(pa_scene_change_detection_sensitivity), AV_OPT_TYPE_INT, {.i64 = -1 }, -1, AMF_PA_SCENE_CHANGE_DETECTION_SENSITIVITY_HIGH, VE, "scene_change_sensitivity" }, + { "low", "low scene change dectection sensitivity", 0, AV_OPT_TYPE_CONST, {.i64 = AMF_PA_SCENE_CHANGE_DETECTION_SENSITIVITY_LOW }, 0, 0, VE, "scene_change_sensitivity" }, + { "medium", "medium scene change dectection sensitivity", 0, AV_OPT_TYPE_CONST, {.i64 = AMF_PA_SCENE_CHANGE_DETECTION_SENSITIVITY_MEDIUM }, 0, 0, VE, "scene_change_sensitivity" }, + { "high", "high scene change dectection sensitivity", 0, AV_OPT_TYPE_CONST, {.i64 = AMF_PA_SCENE_CHANGE_DETECTION_SENSITIVITY_HIGH }, 0, 0, VE, "scene_change_sensitivity" }, + + { "pa_static_scene_detection_enable", "Enable static scene detection", OFFSET(pa_static_scene_detection), AV_OPT_TYPE_BOOL, {.i64 = -1 }, -1, 1, VE }, + + { "pa_static_scene_detection_sensitivity", "Set the sensitivity of static scene detection", OFFSET(pa_static_scene_detection_sensitivity), AV_OPT_TYPE_INT, {.i64 = -1 }, -1, AMF_PA_STATIC_SCENE_DETECTION_SENSITIVITY_HIGH, VE , "static_scene_sensitivity" }, + { "low", "low static scene dectection sensitivity", 0, AV_OPT_TYPE_CONST, {.i64 = AMF_PA_STATIC_SCENE_DETECTION_SENSITIVITY_LOW }, 0, 0, VE, "static_scene_sensitivity" }, + { "medium", "medium static scene dectection sensitivity", 0, AV_OPT_TYPE_CONST, {.i64 = AMF_PA_STATIC_SCENE_DETECTION_SENSITIVITY_MEDIUM }, 0, 0, VE, "static_scene_sensitivity" }, + { "high", "high static scene dectection sensitivity", 0, AV_OPT_TYPE_CONST, {.i64 = AMF_PA_STATIC_SCENE_DETECTION_SENSITIVITY_HIGH }, 0, 0, VE, "static_scene_sensitivity" }, + + { "pa_initial_qp_after_scene_change", "The QP value that is used immediately after a scene change", OFFSET(pa_initial_qp), AV_OPT_TYPE_INT, {.i64 = -1 }, -1, 51, VE }, + { "pa_max_qp_before_force_skip", "The QP threshold to allow a skip frame", OFFSET(pa_max_qp), AV_OPT_TYPE_INT, {.i64 = -1 }, -1, 51, VE }, + + { "pa_caq_strength", "Content Adaptive Quantization strength", OFFSET(pa_caq_strength), AV_OPT_TYPE_INT, {.i64 = -1 }, -1, AMF_PA_CAQ_STRENGTH_HIGH, VE , "caq_strength" }, + { "low", "low Content Adaptive Quantization strength", 0, AV_OPT_TYPE_CONST, {.i64 = AMF_PA_CAQ_STRENGTH_LOW }, 0, 0, VE, "caq_strength" }, + { "medium", "medium Content Adaptive Quantization strength", 0, AV_OPT_TYPE_CONST, {.i64 = AMF_PA_CAQ_STRENGTH_MEDIUM }, 0, 0, VE, "caq_strength" }, + { "high", "high Content Adaptive Quantization strength", 0, AV_OPT_TYPE_CONST, {.i64 = AMF_PA_CAQ_STRENGTH_HIGH }, 0, 0, VE, "caq_strength" }, + + { "pa_frame_sad_enable", "Enable Frame SAD algorithm", OFFSET(pa_frame_sad), AV_OPT_TYPE_BOOL, {.i64 = -1 }, -1, 1, VE }, + { "pa_ltr_enable", "Enable long term reference frame management", OFFSET(pa_ltr), AV_OPT_TYPE_BOOL, {.i64 = -1 }, -1, 1, VE }, + { "pa_lookahead_buffer_depth", "Sets the PA lookahead buffer size", OFFSET(pa_lookahead_buffer_depth), AV_OPT_TYPE_INT, {.i64 = -1 }, -1, MAX_LOOKAHEAD_DEPTH, VE }, + + { "pa_paq_mode", "Sets the perceptual adaptive quantization mode", OFFSET(pa_paq_mode), AV_OPT_TYPE_INT, {.i64 = -1 }, -1, AMF_PA_PAQ_MODE_CAQ, VE , "paq_mode" }, + { "none", "no perceptual adaptive quantization", 0, AV_OPT_TYPE_CONST, {.i64 = AMF_PA_PAQ_MODE_NONE }, 0, 0, VE, "paq_mode" }, + { "caq", "caq perceptual adaptive quantization", 0, AV_OPT_TYPE_CONST, {.i64 = AMF_PA_PAQ_MODE_CAQ }, 0, 0, VE, "paq_mode" }, + + { "pa_taq_mode", "Sets the temporal adaptive quantization mode", OFFSET(pa_taq_mode), AV_OPT_TYPE_INT, {.i64 = -1 }, -1, AMF_PA_TAQ_MODE_2, VE , "taq_mode" }, + { "none", "no temporal adaptive quantization", 0, AV_OPT_TYPE_CONST, {.i64 = AMF_PA_TAQ_MODE_NONE }, 0, 0, VE, "taq_mode" }, + { "1", "temporal adaptive quantization mode 1", 0, AV_OPT_TYPE_CONST, {.i64 = AMF_PA_TAQ_MODE_1 }, 0, 0, VE, "taq_mode" }, + { "2", "temporal adaptive quantization mode 2", 0, AV_OPT_TYPE_CONST, {.i64 = AMF_PA_TAQ_MODE_2 }, 0, 0, VE, "taq_mode" }, + + { "pa_high_motion_quality_boost_mode", "Sets the PA high motion quality boost mode", OFFSET(pa_high_motion_quality_boost_mode), AV_OPT_TYPE_INT, {.i64 = -1 }, -1, AMF_PA_HIGH_MOTION_QUALITY_BOOST_MODE_AUTO, VE , "high_motion_quality_boost_mode" }, + { "none", "no high motion quality boost", 0, AV_OPT_TYPE_CONST, {.i64 = AMF_PA_HIGH_MOTION_QUALITY_BOOST_MODE_NONE }, 0, 0, VE, "high_motion_quality_boost_mode" }, + { "auto", "auto high motion quality boost", 0, AV_OPT_TYPE_CONST, {.i64 = AMF_PA_HIGH_MOTION_QUALITY_BOOST_MODE_AUTO }, 0, 0, VE, "high_motion_quality_boost_mode" }, { NULL } }; @@ -186,6 +241,26 @@ FF_ENABLE_DEPRECATION_WARNINGS } } + // Pre-Pass, Pre-Analysis, Two-Pass + if (ctx->rate_control_mode == AMF_VIDEO_ENCODER_AV1_RATE_CONTROL_METHOD_CONSTANT_QP) { + AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_AV1_RATE_CONTROL_PREENCODE, 0); + if (ctx->preencode) + av_log(ctx, AV_LOG_WARNING, "Preencode is not supported by cqp Rate Control Method, automatically disabled\n"); + } + else { + AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_AV1_RATE_CONTROL_PREENCODE, ctx->preencode); + } + + if (ctx->rate_control_mode == AMF_VIDEO_ENCODER_AV1_RATE_CONTROL_METHOD_QUALITY_VBR) { + if (ctx->qvbr_quality_level != -1) { + AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_AV1_QVBR_QUALITY_LEVEL, ctx->qvbr_quality_level); + } + } + + if (ctx->hw_high_motion_quality_boost != -1) { + AMF_ASSIGN_PROPERTY_BOOL(res, ctx->encoder, AMF_VIDEO_ENCODER_AV1_HIGH_MOTION_QUALITY_BOOST, ((ctx->hw_high_motion_quality_boost == 0) ? false : true)); + } + AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_AV1_RATE_CONTROL_METHOD, ctx->rate_control_mode); if (avctx->rc_buffer_size) { AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_AV1_VBV_BUFFER_SIZE, avctx->rc_buffer_size); @@ -198,9 +273,6 @@ FF_ENABLE_DEPRECATION_WARNINGS } } - // Pre-Pass, Pre-Analysis, Two-Pass - AMF_ASSIGN_PROPERTY_BOOL(res, ctx->encoder, AMF_VIDEO_ENCODER_AV1_PRE_ANALYSIS_ENABLE, ctx->preanalysis); - // init dynamic rate control params if (ctx->max_au_size) ctx->enforce_hrd = 1; @@ -255,6 +327,56 @@ FF_ENABLE_DEPRECATION_WARNINGS } AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_AV1_ALIGNMENT_MODE, ctx->align); + if (ctx->preanalysis != -1) { + AMF_ASSIGN_PROPERTY_BOOL(res, ctx->encoder, AMF_VIDEO_ENCODER_AV1_PRE_ANALYSIS_ENABLE, !!((ctx->preanalysis == 0) ? false : true)); + } + + res = ctx->encoder->pVtbl->GetProperty(ctx->encoder, AMF_VIDEO_ENCODER_AV1_PRE_ANALYSIS_ENABLE, &var); + if ((int)var.int64Value) + { + if (ctx->pa_activity_type != -1) { + AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_PA_ACTIVITY_TYPE, ctx->pa_activity_type); + } + if (ctx->pa_scene_change_detection != -1) { + AMF_ASSIGN_PROPERTY_BOOL(res, ctx->encoder, AMF_PA_SCENE_CHANGE_DETECTION_ENABLE, ((ctx->pa_scene_change_detection == 0) ? false : true)); + } + if (ctx->pa_scene_change_detection_sensitivity != -1) { + AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_PA_SCENE_CHANGE_DETECTION_SENSITIVITY, ctx->pa_scene_change_detection_sensitivity); + } + if (ctx->pa_static_scene_detection != -1) { + AMF_ASSIGN_PROPERTY_BOOL(res, ctx->encoder, AMF_PA_STATIC_SCENE_DETECTION_ENABLE, ((ctx->pa_static_scene_detection == 0) ? false : true)); + } + if (ctx->pa_static_scene_detection_sensitivity != -1) { + AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_PA_STATIC_SCENE_DETECTION_SENSITIVITY, ctx->pa_static_scene_detection_sensitivity); + } + if (ctx->pa_initial_qp != -1) { + AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_PA_INITIAL_QP_AFTER_SCENE_CHANGE, ctx->pa_initial_qp); + } + if (ctx->pa_max_qp != -1) { + AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_PA_MAX_QP_BEFORE_FORCE_SKIP, ctx->pa_max_qp); + } + if (ctx->pa_caq_strength != -1) { + AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_PA_CAQ_STRENGTH, ctx->pa_caq_strength); + } + if (ctx->pa_frame_sad != -1) { + AMF_ASSIGN_PROPERTY_BOOL(res, ctx->encoder, AMF_PA_FRAME_SAD_ENABLE, ((ctx->pa_frame_sad == 0) ? false : true)); + } + if (ctx->pa_paq_mode != -1) { + AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_PA_PAQ_MODE, ctx->pa_paq_mode); + } + if (ctx->pa_taq_mode != -1) { + AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_PA_TAQ_MODE, ctx->pa_taq_mode); + } + if (ctx->pa_ltr != -1) { + AMF_ASSIGN_PROPERTY_BOOL(res, ctx->encoder, AMF_PA_LTR_ENABLE, ((ctx->pa_ltr == 0) ? false : true)); + } + if (ctx->pa_lookahead_buffer_depth != -1) { + AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_PA_LOOKAHEAD_BUFFER_DEPTH, ctx->pa_lookahead_buffer_depth); + } + if (ctx->pa_high_motion_quality_boost_mode != -1) { + AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_PA_HIGH_MOTION_QUALITY_BOOST_MODE, ctx->pa_high_motion_quality_boost_mode); + } + } // init encoder res = ctx->encoder->pVtbl->Init(ctx->encoder, ctx->format, avctx->width, avctx->height); @@ -298,7 +420,6 @@ FF_ENABLE_DEPRECATION_WARNINGS } AMF_ASSIGN_PROPERTY_BOOL(res, ctx->encoder, AMF_VIDEO_ENCODER_AV1_RATE_CONTROL_SKIP_FRAME, ctx->skip_frame); - // fill extradata res = AMFVariantInit(&var); AMF_RETURN_IF_FALSE(ctx, res == AMF_OK, AVERROR_BUG, "AMFVariantInit() failed with error %d\n", res); diff --git a/libavcodec/amfenc_h264.c b/libavcodec/amfenc_h264.c index d2fc33971b3..2380aa4e906 100644 --- a/libavcodec/amfenc_h264.c +++ b/libavcodec/amfenc_h264.c @@ -22,6 +22,7 @@ #include "amfenc.h" #include "codec_internal.h" #include "internal.h" +#include #define OFFSET(x) offsetof(AmfContext, x) #define VE AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_ENCODING_PARAM @@ -29,11 +30,14 @@ static const AVOption options[] = { // Static /// Usage - { "usage", "Encoder Usage", OFFSET(usage), AV_OPT_TYPE_INT, { .i64 = AMF_VIDEO_ENCODER_USAGE_TRANSCONDING }, AMF_VIDEO_ENCODER_USAGE_TRANSCONDING, AMF_VIDEO_ENCODER_USAGE_WEBCAM, VE, "usage" }, - { "transcoding", "Generic Transcoding", 0, AV_OPT_TYPE_CONST, { .i64 = AMF_VIDEO_ENCODER_USAGE_TRANSCONDING }, 0, 0, VE, "usage" }, - { "ultralowlatency","", 0, AV_OPT_TYPE_CONST, { .i64 = AMF_VIDEO_ENCODER_USAGE_ULTRA_LOW_LATENCY }, 0, 0, VE, "usage" }, - { "lowlatency", "", 0, AV_OPT_TYPE_CONST, { .i64 = AMF_VIDEO_ENCODER_USAGE_LOW_LATENCY }, 0, 0, VE, "usage" }, + { "usage", "Encoder Usage", OFFSET(usage), AV_OPT_TYPE_INT, { .i64 = AMF_VIDEO_ENCODER_USAGE_TRANSCODING }, AMF_VIDEO_ENCODER_USAGE_TRANSCODING, AMF_VIDEO_ENCODER_USAGE_LOW_LATENCY_HIGH_QUALITY, VE, "usage" }, + { "transcoding", "Generic Transcoding", 0, AV_OPT_TYPE_CONST, { .i64 = AMF_VIDEO_ENCODER_USAGE_TRANSCODING }, 0, 0, VE, "usage" }, + { "ultralowlatency","ultra low latency trancoding", 0, AV_OPT_TYPE_CONST, { .i64 = AMF_VIDEO_ENCODER_USAGE_ULTRA_LOW_LATENCY }, 0, 0, VE, "usage" }, + { "lowlatency", "low latency trancoding", 0, AV_OPT_TYPE_CONST, { .i64 = AMF_VIDEO_ENCODER_USAGE_LOW_LATENCY }, 0, 0, VE, "usage" }, { "webcam", "Webcam", 0, AV_OPT_TYPE_CONST, { .i64 = AMF_VIDEO_ENCODER_USAGE_WEBCAM }, 0, 0, VE, "usage" }, + { "high_quality", "high quality trancoding", 0, AV_OPT_TYPE_CONST, { .i64 = AMF_VIDEO_ENCODER_USAGE_HIGH_QUALITY }, 0, 0, VE, "usage" }, + { "lowlatency_high_quality", "low latency yet high quality trancoding", 0, AV_OPT_TYPE_CONST, { .i64 = AMF_VIDEO_ENCODER_USAGE_LOW_LATENCY_HIGH_QUALITY }, 0, 0, VE, "usage" }, + /// Profile, { "profile", "Profile", OFFSET(profile),AV_OPT_TYPE_INT, { .i64 = AMF_VIDEO_ENCODER_PROFILE_MAIN }, AMF_VIDEO_ENCODER_PROFILE_BASELINE, AMF_VIDEO_ENCODER_PROFILE_CONSTRAINED_HIGH, VE, "profile" }, @@ -74,11 +78,16 @@ static const AVOption options[] = { // Dynamic /// Rate Control Method - { "rc", "Rate Control Method", OFFSET(rate_control_mode), AV_OPT_TYPE_INT, { .i64 = AMF_VIDEO_ENCODER_RATE_CONTROL_METHOD_UNKNOWN }, AMF_VIDEO_ENCODER_RATE_CONTROL_METHOD_UNKNOWN, AMF_VIDEO_ENCODER_RATE_CONTROL_METHOD_LATENCY_CONSTRAINED_VBR, VE, "rc" }, + { "rc", "Rate Control Method", OFFSET(rate_control_mode), AV_OPT_TYPE_INT, { .i64 = AMF_VIDEO_ENCODER_RATE_CONTROL_METHOD_UNKNOWN }, AMF_VIDEO_ENCODER_RATE_CONTROL_METHOD_UNKNOWN, AMF_VIDEO_ENCODER_RATE_CONTROL_METHOD_HIGH_QUALITY_CBR, VE, "rc" }, { "cqp", "Constant Quantization Parameter", 0, AV_OPT_TYPE_CONST, { .i64 = AMF_VIDEO_ENCODER_RATE_CONTROL_METHOD_CONSTANT_QP }, 0, 0, VE, "rc" }, { "cbr", "Constant Bitrate", 0, AV_OPT_TYPE_CONST, { .i64 = AMF_VIDEO_ENCODER_RATE_CONTROL_METHOD_CBR }, 0, 0, VE, "rc" }, { "vbr_peak", "Peak Contrained Variable Bitrate", 0, AV_OPT_TYPE_CONST, { .i64 = AMF_VIDEO_ENCODER_RATE_CONTROL_METHOD_PEAK_CONSTRAINED_VBR }, 0, 0, VE, "rc" }, { "vbr_latency", "Latency Constrained Variable Bitrate", 0, AV_OPT_TYPE_CONST, { .i64 = AMF_VIDEO_ENCODER_RATE_CONTROL_METHOD_LATENCY_CONSTRAINED_VBR }, 0, 0, VE, "rc" }, + { "qvbr", "Quality Variable Bitrate", 0, AV_OPT_TYPE_CONST, { .i64 = AMF_VIDEO_ENCODER_RATE_CONTROL_METHOD_QUALITY_VBR }, 0, 0, VE, "rc" }, + { "hqvbr", "High Quality Variable Bitrate", 0, AV_OPT_TYPE_CONST, { .i64 = AMF_VIDEO_ENCODER_RATE_CONTROL_METHOD_HIGH_QUALITY_VBR }, 0, 0, VE, "rc" }, + { "hqcbr", "High Quality Constant Bitrate", 0, AV_OPT_TYPE_CONST, { .i64 = AMF_VIDEO_ENCODER_RATE_CONTROL_METHOD_HIGH_QUALITY_CBR }, 0, 0, VE, "rc" }, + + { "qvbr_quality_level", "Sets the QVBR quality level", OFFSET(qvbr_quality_level),AV_OPT_TYPE_INT, { .i64 = -1 }, -1, 51, VE }, /// Enforce HRD, Filler Data, VBAQ, Frame Skipping { "enforce_hrd", "Enforce HRD", OFFSET(enforce_hrd), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, VE }, @@ -92,7 +101,7 @@ static const AVOption options[] = { { "qp_b", "Quantization Parameter for B-Frame", OFFSET(qp_b), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, 51, VE }, /// Pre-Pass, Pre-Analysis, Two-Pass - { "preanalysis", "Pre-Analysis Mode", OFFSET(preanalysis), AV_OPT_TYPE_BOOL,{ .i64 = 0 }, 0, 1, VE, NULL }, + { "preencode", "Pre-encode assisted rate control", OFFSET(preencode), AV_OPT_TYPE_BOOL,{ .i64 = 0 }, 0, 1, VE, NULL }, /// Maximum Access Unit Size { "max_au_size", "Maximum Access Unit Size for rate control (in bits)", OFFSET(max_au_size), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, INT_MAX, VE }, @@ -106,6 +115,9 @@ static const AVOption options[] = { { "bf_ref", "Enable Reference to B-Frames", OFFSET(b_frame_ref), AV_OPT_TYPE_BOOL, { .i64 = 1 }, 0, 1, VE }, { "bf_ref_delta_qp","Reference B-Picture Delta QP", OFFSET(ref_b_frame_delta_qp), AV_OPT_TYPE_INT, { .i64 = 4 }, -10, 10, VE }, + { "max_b_frames", "Maximum number of consecutive B Pictures", OFFSET(max_consecutive_b_frames), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, 3, VE }, + { "bf", "B Picture Pattern", OFFSET(max_b_frames), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, 3, VE }, + /// Intra-Refresh { "intra_refresh_mb","Intra Refresh MBs Number Per Slot in Macroblocks", OFFSET(intra_refresh_mb), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, INT_MAX, VE }, @@ -115,6 +127,8 @@ static const AVOption options[] = { { "cavlc", "Context Adaptive Variable-Length Coding", 0, AV_OPT_TYPE_CONST, { .i64 = AMF_VIDEO_ENCODER_CALV }, 0, 0, VE, "coder" }, { "cabac", "Context Adaptive Binary Arithmetic Coding", 0, AV_OPT_TYPE_CONST, { .i64 = AMF_VIDEO_ENCODER_CABAC }, 0, 0, VE, "coder" }, + { "high_motion_quality_boost_enable", "Enable High motion quality boost mode", OFFSET(hw_high_motion_quality_boost), AV_OPT_TYPE_BOOL, {.i64 = -1 }, -1, 1, VE }, + { "me_half_pel", "Enable ME Half Pixel", OFFSET(me_half_pel), AV_OPT_TYPE_BOOL, { .i64 = 1 }, 0, 1, VE }, { "me_quarter_pel", "Enable ME Quarter Pixel", OFFSET(me_quarter_pel),AV_OPT_TYPE_BOOL, { .i64 = 1 }, 0, 1, VE }, @@ -122,6 +136,53 @@ static const AVOption options[] = { { "log_to_dbg", "Enable AMF logging to debug output", OFFSET(log_to_dbg) , AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, VE }, + //Pre Analysis options + { "preanalysis", "Enable preanalysis", OFFSET(preanalysis), AV_OPT_TYPE_BOOL, {.i64 = -1 }, -1, 1, VE }, + + { "pa_activity_type", "Set the type of activity analysis", OFFSET(pa_activity_type), AV_OPT_TYPE_INT, {.i64 = -1 }, -1, AMF_PA_ACTIVITY_YUV, VE, "activity_type" }, + { "y", "activity y", 0, AV_OPT_TYPE_CONST, {.i64 = AMF_PA_ACTIVITY_Y }, 0, 0, VE, "activity_type" }, + { "yuv", "activity yuv", 0, AV_OPT_TYPE_CONST, {.i64 = AMF_PA_ACTIVITY_YUV }, 0, 0, VE, "activity_type" }, + + { "pa_scene_change_detection_enable", "Enable scene change detection", OFFSET(pa_scene_change_detection), AV_OPT_TYPE_BOOL, {.i64 = -1 }, -1, 1, VE }, + + { "pa_scene_change_detection_sensitivity", "Set the sensitivity of scene change detection", OFFSET(pa_scene_change_detection_sensitivity), AV_OPT_TYPE_INT, {.i64 = -1 }, -1, AMF_PA_SCENE_CHANGE_DETECTION_SENSITIVITY_HIGH, VE, "scene_change_sensitivity" }, + { "low", "low scene change dectection sensitivity", 0, AV_OPT_TYPE_CONST, {.i64 = AMF_PA_SCENE_CHANGE_DETECTION_SENSITIVITY_LOW }, 0, 0, VE, "scene_change_sensitivity" }, + { "medium", "medium scene change dectection sensitivity", 0, AV_OPT_TYPE_CONST, {.i64 = AMF_PA_SCENE_CHANGE_DETECTION_SENSITIVITY_MEDIUM }, 0, 0, VE, "scene_change_sensitivity" }, + { "high", "high scene change dectection sensitivity", 0, AV_OPT_TYPE_CONST, {.i64 = AMF_PA_SCENE_CHANGE_DETECTION_SENSITIVITY_HIGH }, 0, 0, VE, "scene_change_sensitivity" }, + + { "pa_static_scene_detection_enable", "Enable static scene detection", OFFSET(pa_static_scene_detection), AV_OPT_TYPE_BOOL, {.i64 = -1 }, -1, 1, VE }, + + { "pa_static_scene_detection_sensitivity", "Set the sensitivity of static scene detection", OFFSET(pa_static_scene_detection_sensitivity), AV_OPT_TYPE_INT, {.i64 = -1 }, -1, AMF_PA_STATIC_SCENE_DETECTION_SENSITIVITY_HIGH, VE , "static_scene_sensitivity" }, + { "low", "low static scene dectection sensitivity", 0, AV_OPT_TYPE_CONST, {.i64 = AMF_PA_STATIC_SCENE_DETECTION_SENSITIVITY_LOW }, 0, 0, VE, "static_scene_sensitivity" }, + { "medium", "medium static scene dectection sensitivity", 0, AV_OPT_TYPE_CONST, {.i64 = AMF_PA_STATIC_SCENE_DETECTION_SENSITIVITY_MEDIUM }, 0, 0, VE, "static_scene_sensitivity" }, + { "high", "high static scene dectection sensitivity", 0, AV_OPT_TYPE_CONST, {.i64 = AMF_PA_STATIC_SCENE_DETECTION_SENSITIVITY_HIGH }, 0, 0, VE, "static_scene_sensitivity" }, + + { "pa_initial_qp_after_scene_change", "The QP value that is used immediately after a scene change", OFFSET(pa_initial_qp), AV_OPT_TYPE_INT, {.i64 = -1 }, -1, 51, VE }, + { "pa_max_qp_before_force_skip", "The QP threshold to allow a skip frame", OFFSET(pa_max_qp), AV_OPT_TYPE_INT, {.i64 = -1 }, -1, 51, VE }, + + { "pa_caq_strength", "Content Adaptive Quantization strength", OFFSET(pa_caq_strength), AV_OPT_TYPE_INT, {.i64 = -1 }, -1, AMF_PA_CAQ_STRENGTH_HIGH, VE , "caq_strength" }, + { "low", "low Content Adaptive Quantization strength", 0, AV_OPT_TYPE_CONST, {.i64 = AMF_PA_CAQ_STRENGTH_LOW }, 0, 0, VE, "caq_strength" }, + { "medium", "medium Content Adaptive Quantization strength", 0, AV_OPT_TYPE_CONST, {.i64 = AMF_PA_CAQ_STRENGTH_MEDIUM }, 0, 0, VE, "caq_strength" }, + { "high", "high Content Adaptive Quantization strength", 0, AV_OPT_TYPE_CONST, {.i64 = AMF_PA_CAQ_STRENGTH_HIGH }, 0, 0, VE, "caq_strength" }, + + { "pa_frame_sad_enable", "Enable Frame SAD algorithm", OFFSET(pa_frame_sad), AV_OPT_TYPE_BOOL, {.i64 = -1 }, -1, 1, VE }, + { "pa_ltr_enable", "Enable long term reference frame management", OFFSET(pa_ltr), AV_OPT_TYPE_BOOL, {.i64 = -1 }, -1, 1, VE }, + { "pa_lookahead_buffer_depth", "Sets the PA lookahead buffer size", OFFSET(pa_lookahead_buffer_depth), AV_OPT_TYPE_INT, {.i64 = -1 }, -1, MAX_LOOKAHEAD_DEPTH, VE }, + + { "pa_paq_mode", "Sets the perceptual adaptive quantization mode", OFFSET(pa_paq_mode), AV_OPT_TYPE_INT, {.i64 = -1 }, -1, AMF_PA_PAQ_MODE_CAQ, VE , "paq_mode" }, + { "none", "no perceptual adaptive quantization", 0, AV_OPT_TYPE_CONST, {.i64 = AMF_PA_PAQ_MODE_NONE }, 0, 0, VE, "paq_mode" }, + { "caq", "caq perceptual adaptive quantization", 0, AV_OPT_TYPE_CONST, {.i64 = AMF_PA_PAQ_MODE_CAQ }, 0, 0, VE, "paq_mode" }, + + { "pa_taq_mode", "Sets the temporal adaptive quantization mode", OFFSET(pa_taq_mode), AV_OPT_TYPE_INT, {.i64 = -1 }, -1, AMF_PA_TAQ_MODE_2, VE , "taq_mode" }, + { "none", "no temporal adaptive quantization", 0, AV_OPT_TYPE_CONST, {.i64 = AMF_PA_TAQ_MODE_NONE }, 0, 0, VE, "taq_mode" }, + { "1", "temporal adaptive quantization mode 1", 0, AV_OPT_TYPE_CONST, {.i64 = AMF_PA_TAQ_MODE_1 }, 0, 0, VE, "taq_mode" }, + { "2", "temporal adaptive quantization mode 2", 0, AV_OPT_TYPE_CONST, {.i64 = AMF_PA_TAQ_MODE_2 }, 0, 0, VE, "taq_mode" }, + + { "pa_high_motion_quality_boost_mode", "Sets the PA high motion quality boost mode", OFFSET(pa_high_motion_quality_boost_mode), AV_OPT_TYPE_INT, {.i64 = -1 }, -1, AMF_PA_HIGH_MOTION_QUALITY_BOOST_MODE_AUTO, VE , "high_motion_quality_boost_mode" }, + { "none", "no high motion quality boost", 0, AV_OPT_TYPE_CONST, {.i64 = AMF_PA_HIGH_MOTION_QUALITY_BOOST_MODE_NONE }, 0, 0, VE, "high_motion_quality_boost_mode" }, + { "auto", "auto high motion quality boost", 0, AV_OPT_TYPE_CONST, {.i64 = AMF_PA_HIGH_MOTION_QUALITY_BOOST_MODE_AUTO }, 0, 0, VE, "high_motion_quality_boost_mode" }, + + { "pa_adaptive_mini_gop", "Enable Adaptive MiniGOP", OFFSET(pa_adaptive_mini_gop), AV_OPT_TYPE_BOOL, { .i64 = -1 }, -1, 1, VE }, { NULL } }; @@ -221,11 +282,21 @@ FF_ENABLE_DEPRECATION_WARNINGS } if (ctx->rate_control_mode == AMF_VIDEO_ENCODER_RATE_CONTROL_METHOD_CONSTANT_QP) { - AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_RATE_CONTROL_PREANALYSIS_ENABLE, AMF_VIDEO_ENCODER_PREENCODE_DISABLED); - if (ctx->preanalysis) - av_log(ctx, AV_LOG_WARNING, "Pre-Analysis is not supported by cqp Rate Control Method, automatically disabled\n"); + AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_PREENCODE_ENABLE, AMF_VIDEO_ENCODER_PREENCODE_DISABLED); + if (ctx->preencode) + av_log(ctx, AV_LOG_WARNING, "Preencode is not supported by cqp Rate Control Method, automatically disabled\n"); } else { - AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_RATE_CONTROL_PREANALYSIS_ENABLE, ctx->preanalysis); + AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_PREENCODE_ENABLE, ctx->preencode); + } + + if (ctx->rate_control_mode == AMF_VIDEO_ENCODER_RATE_CONTROL_METHOD_QUALITY_VBR) { + if (ctx->qvbr_quality_level != -1) { + AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_QVBR_QUALITY_LEVEL, ctx->qvbr_quality_level); + } + } + + if (ctx->hw_high_motion_quality_boost != -1) { + AMF_ASSIGN_PROPERTY_BOOL(res, ctx->encoder, AMF_VIDEO_ENCODER_HIGH_MOTION_QUALITY_BOOST_ENABLE, ((ctx->hw_high_motion_quality_boost == 0) ? false : true)); } AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_QUALITY_PRESET, ctx->quality); @@ -282,6 +353,88 @@ FF_ENABLE_DEPRECATION_WARNINGS av_log(ctx, AV_LOG_WARNING, "rate control mode is PEAK_CONSTRAINED_VBR but rc_max_rate is not set\n"); } + if (ctx->preanalysis != -1) { + AMF_ASSIGN_PROPERTY_BOOL(res, ctx->encoder, AMF_VIDEO_ENCODER_PRE_ANALYSIS_ENABLE, !!((ctx->preanalysis == 0) ? false : true)); + } + + res = ctx->encoder->pVtbl->GetProperty(ctx->encoder, AMF_VIDEO_ENCODER_PRE_ANALYSIS_ENABLE, &var); + if ((int)var.int64Value) + { + if (ctx->pa_activity_type != -1) { + AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_PA_ACTIVITY_TYPE, ctx->pa_activity_type); + } + if (ctx->pa_scene_change_detection != -1) { + AMF_ASSIGN_PROPERTY_BOOL(res, ctx->encoder, AMF_PA_SCENE_CHANGE_DETECTION_ENABLE, ((ctx->pa_scene_change_detection == 0) ? false : true)); + } + if (ctx->pa_scene_change_detection_sensitivity != -1) { + AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_PA_SCENE_CHANGE_DETECTION_SENSITIVITY, ctx->pa_scene_change_detection_sensitivity); + } + if (ctx->pa_static_scene_detection != -1) { + AMF_ASSIGN_PROPERTY_BOOL(res, ctx->encoder, AMF_PA_STATIC_SCENE_DETECTION_ENABLE, ((ctx->pa_static_scene_detection == 0) ? false : true)); + } + if (ctx->pa_static_scene_detection_sensitivity != -1) { + AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_PA_STATIC_SCENE_DETECTION_SENSITIVITY, ctx->pa_static_scene_detection_sensitivity); + } + if (ctx->pa_initial_qp != -1) { + AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_PA_INITIAL_QP_AFTER_SCENE_CHANGE, ctx->pa_initial_qp); + } + if (ctx->pa_max_qp != -1) { + AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_PA_MAX_QP_BEFORE_FORCE_SKIP, ctx->pa_max_qp); + } + if (ctx->pa_caq_strength != -1) { + AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_PA_CAQ_STRENGTH, ctx->pa_caq_strength); + } + if (ctx->pa_frame_sad != -1) { + AMF_ASSIGN_PROPERTY_BOOL(res, ctx->encoder, AMF_PA_FRAME_SAD_ENABLE, ((ctx->pa_frame_sad == 0) ? false : true)); + } + if (ctx->pa_paq_mode != -1) { + AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_PA_PAQ_MODE, ctx->pa_paq_mode); + } + if (ctx->pa_taq_mode != -1) { + AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_PA_TAQ_MODE, ctx->pa_taq_mode); + } + if (ctx->pa_adaptive_mini_gop != -1) { + AMF_ASSIGN_PROPERTY_BOOL(res, ctx->encoder, AMF_VIDEO_ENCODER_ADAPTIVE_MINIGOP, ((ctx->pa_adaptive_mini_gop == 0) ? false : true)); + } + if (ctx->pa_ltr != -1) { + AMF_ASSIGN_PROPERTY_BOOL(res, ctx->encoder, AMF_PA_LTR_ENABLE, ((ctx->pa_ltr == 0) ? false : true)); + } + if (ctx->pa_lookahead_buffer_depth != -1) { + AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_PA_LOOKAHEAD_BUFFER_DEPTH, ctx->pa_lookahead_buffer_depth); + } + if (ctx->pa_high_motion_quality_boost_mode != -1) { + AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_PA_HIGH_MOTION_QUALITY_BOOST_MODE, ctx->pa_high_motion_quality_boost_mode); + } + } + + // B-Frames + if (ctx->max_consecutive_b_frames != -1) { + AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_MAX_CONSECUTIVE_BPICTURES, ctx->max_consecutive_b_frames); + if (ctx->max_b_frames != -1) { + AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_B_PIC_PATTERN, ctx->max_b_frames); + if (res != AMF_OK) { + res = ctx->encoder->pVtbl->GetProperty(ctx->encoder, AMF_VIDEO_ENCODER_B_PIC_PATTERN, &var); + av_log(ctx, AV_LOG_WARNING, "B-frames=%d is not supported by this GPU, switched to %d\n", + ctx->max_b_frames, (int)var.int64Value); + ctx->max_b_frames = (int)var.int64Value; + } + if (ctx->max_consecutive_b_frames < ctx->max_b_frames) { + av_log(ctx, AVERROR_BUG, "Maxium B frames needs to be greater than the specified B frame count.\n"); + } + } + } + else { + if (ctx->max_b_frames != -1) { + av_log(ctx, AVERROR_BUG, "Maxium number of B frames needs to be specified.\n"); + } + } + res = ctx->encoder->pVtbl->GetProperty(ctx->encoder, AMF_VIDEO_ENCODER_B_PIC_PATTERN, &var); + if ((int)var.int64Value) { + AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_B_PIC_DELTA_QP, ctx->b_frame_delta_qp); + AMF_ASSIGN_PROPERTY_BOOL(res, ctx->encoder, AMF_VIDEO_ENCODER_B_REFERENCE_ENABLE, !!ctx->b_frame_ref); + AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_REF_B_PIC_DELTA_QP, ctx->ref_b_frame_delta_qp); + } + // Initialize Encoder res = ctx->encoder->pVtbl->Init(ctx->encoder, ctx->format, avctx->width, avctx->height); AMF_RETURN_IF_FALSE(ctx, res == AMF_OK, AVERROR_BUG, "encoder->Init() failed with error %d\n", res); @@ -299,20 +452,6 @@ FF_ENABLE_DEPRECATION_WARNINGS } AMF_ASSIGN_PROPERTY_BOOL(res, ctx->encoder, AMF_VIDEO_ENCODER_DE_BLOCKING_FILTER, !!deblocking_filter); - // B-Frames - AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_B_PIC_PATTERN, avctx->max_b_frames); - if (res != AMF_OK) { - res = ctx->encoder->pVtbl->GetProperty(ctx->encoder, AMF_VIDEO_ENCODER_B_PIC_PATTERN, &var); - av_log(ctx, AV_LOG_WARNING, "B-frames=%d is not supported by this GPU, switched to %d\n", - avctx->max_b_frames, (int)var.int64Value); - avctx->max_b_frames = (int)var.int64Value; - } - if (avctx->max_b_frames) { - AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_B_PIC_DELTA_QP, ctx->b_frame_delta_qp); - AMF_ASSIGN_PROPERTY_BOOL(res, ctx->encoder, AMF_VIDEO_ENCODER_B_REFERENCE_ENABLE, !!ctx->b_frame_ref); - AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_REF_B_PIC_DELTA_QP, ctx->ref_b_frame_delta_qp); - } - // Keyframe Interval AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_IDR_PERIOD, avctx->gop_size); diff --git a/libavcodec/amfenc_hevc.c b/libavcodec/amfenc_hevc.c index 674a4095d6c..dd232cc8ac8 100644 --- a/libavcodec/amfenc_hevc.c +++ b/libavcodec/amfenc_hevc.c @@ -21,15 +21,18 @@ #include "amfenc.h" #include "codec_internal.h" #include "internal.h" +#include #define OFFSET(x) offsetof(AmfContext, x) #define VE AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_ENCODING_PARAM static const AVOption options[] = { - { "usage", "Set the encoding usage", OFFSET(usage), AV_OPT_TYPE_INT, { .i64 = AMF_VIDEO_ENCODER_HEVC_USAGE_TRANSCONDING }, AMF_VIDEO_ENCODER_HEVC_USAGE_TRANSCONDING, AMF_VIDEO_ENCODER_HEVC_USAGE_WEBCAM, VE, "usage" }, - { "transcoding", "", 0, AV_OPT_TYPE_CONST, { .i64 = AMF_VIDEO_ENCODER_HEVC_USAGE_TRANSCONDING }, 0, 0, VE, "usage" }, - { "ultralowlatency","", 0, AV_OPT_TYPE_CONST, { .i64 = AMF_VIDEO_ENCODER_HEVC_USAGE_ULTRA_LOW_LATENCY }, 0, 0, VE, "usage" }, - { "lowlatency", "", 0, AV_OPT_TYPE_CONST, { .i64 = AMF_VIDEO_ENCODER_HEVC_USAGE_LOW_LATENCY }, 0, 0, VE, "usage" }, - { "webcam", "", 0, AV_OPT_TYPE_CONST, { .i64 = AMF_VIDEO_ENCODER_HEVC_USAGE_WEBCAM }, 0, 0, VE, "usage" }, + { "usage", "Set the encoding usage", OFFSET(usage), AV_OPT_TYPE_INT, {.i64 = AMF_VIDEO_ENCODER_HEVC_USAGE_TRANSCODING }, AMF_VIDEO_ENCODER_HEVC_USAGE_TRANSCODING, AMF_VIDEO_ENCODER_HEVC_USAGE_LOW_LATENCY_HIGH_QUALITY, VE, "usage" }, + { "transcoding", "Generic Transcoding", 0, AV_OPT_TYPE_CONST, {.i64 = AMF_VIDEO_ENCODER_HEVC_USAGE_TRANSCODING }, 0, 0, VE, "usage" }, + { "ultralowlatency", "ultra low latency trancoding", 0, AV_OPT_TYPE_CONST, {.i64 = AMF_VIDEO_ENCODER_HEVC_USAGE_ULTRA_LOW_LATENCY }, 0, 0, VE, "usage" }, + { "lowlatency", "low latency trancoding", 0, AV_OPT_TYPE_CONST, {.i64 = AMF_VIDEO_ENCODER_HEVC_USAGE_LOW_LATENCY }, 0, 0, VE, "usage" }, + { "webcam", "Webcam", 0, AV_OPT_TYPE_CONST, {.i64 = AMF_VIDEO_ENCODER_HEVC_USAGE_WEBCAM }, 0, 0, VE, "usage" }, + { "high_quality", "high quality trancoding", 0, AV_OPT_TYPE_CONST, {.i64 = AMF_VIDEO_ENCODER_HEVC_USAGE_HIGH_QUALITY }, 0, 0, VE, "usage" }, + { "lowlatency_high_quality","low latency yet high quality trancoding", 0, AV_OPT_TYPE_CONST, {.i64 = AMF_VIDEO_ENCODER_HEVC_USAGE_LOW_LATENCY_HIGH_QUALITY }, 0, 0, VE, "usage" }, { "profile", "Set the profile (default main)", OFFSET(profile), AV_OPT_TYPE_INT,{ .i64 = AMF_VIDEO_ENCODER_HEVC_PROFILE_MAIN }, AMF_VIDEO_ENCODER_HEVC_PROFILE_MAIN, AMF_VIDEO_ENCODER_HEVC_PROFILE_MAIN, VE, "profile" }, { "main", "", 0, AV_OPT_TYPE_CONST,{ .i64 = AMF_VIDEO_ENCODER_HEVC_PROFILE_MAIN }, 0, 0, VE, "profile" }, @@ -59,19 +62,25 @@ static const AVOption options[] = { { "speed", "", 0, AV_OPT_TYPE_CONST, { .i64 = AMF_VIDEO_ENCODER_HEVC_QUALITY_PRESET_SPEED }, 0, 0, VE, "quality" }, { "quality", "", 0, AV_OPT_TYPE_CONST, { .i64 = AMF_VIDEO_ENCODER_HEVC_QUALITY_PRESET_QUALITY }, 0, 0, VE, "quality" }, - { "rc", "Set the rate control mode", OFFSET(rate_control_mode), AV_OPT_TYPE_INT, { .i64 = AMF_VIDEO_ENCODER_HEVC_RATE_CONTROL_METHOD_UNKNOWN }, AMF_VIDEO_ENCODER_HEVC_RATE_CONTROL_METHOD_UNKNOWN, AMF_VIDEO_ENCODER_HEVC_RATE_CONTROL_METHOD_CBR, VE, "rc" }, + { "rc", "Set the rate control mode", OFFSET(rate_control_mode), AV_OPT_TYPE_INT, { .i64 = AMF_VIDEO_ENCODER_HEVC_RATE_CONTROL_METHOD_UNKNOWN }, AMF_VIDEO_ENCODER_HEVC_RATE_CONTROL_METHOD_UNKNOWN, AMF_VIDEO_ENCODER_HEVC_RATE_CONTROL_METHOD_HIGH_QUALITY_CBR, VE, "rc" }, { "cqp", "Constant Quantization Parameter", 0, AV_OPT_TYPE_CONST, { .i64 = AMF_VIDEO_ENCODER_HEVC_RATE_CONTROL_METHOD_CONSTANT_QP }, 0, 0, VE, "rc" }, { "cbr", "Constant Bitrate", 0, AV_OPT_TYPE_CONST, { .i64 = AMF_VIDEO_ENCODER_HEVC_RATE_CONTROL_METHOD_CBR }, 0, 0, VE, "rc" }, { "vbr_peak", "Peak Contrained Variable Bitrate", 0, AV_OPT_TYPE_CONST, { .i64 = AMF_VIDEO_ENCODER_HEVC_RATE_CONTROL_METHOD_PEAK_CONSTRAINED_VBR }, 0, 0, VE, "rc" }, { "vbr_latency", "Latency Constrained Variable Bitrate", 0, AV_OPT_TYPE_CONST, { .i64 = AMF_VIDEO_ENCODER_HEVC_RATE_CONTROL_METHOD_LATENCY_CONSTRAINED_VBR }, 0, 0, VE, "rc" }, + { "qvbr", "Quality Variable Bitrate", 0, AV_OPT_TYPE_CONST, { .i64 = AMF_VIDEO_ENCODER_HEVC_RATE_CONTROL_METHOD_QUALITY_VBR }, 0, 0, VE, "rc" }, + { "hqvbr", "High Quality Variable Bitrate", 0, AV_OPT_TYPE_CONST, { .i64 = AMF_VIDEO_ENCODER_HEVC_RATE_CONTROL_METHOD_HIGH_QUALITY_VBR }, 0, 0, VE, "rc" }, + { "hqcbr", "High Quality Constant Bitrate", 0, AV_OPT_TYPE_CONST, { .i64 = AMF_VIDEO_ENCODER_HEVC_RATE_CONTROL_METHOD_HIGH_QUALITY_CBR }, 0, 0, VE, "rc" }, + + { "qvbr_quality_level", "Sets the QVBR quality level", OFFSET(qvbr_quality_level), AV_OPT_TYPE_INT, {.i64 = -1 }, -1, 51, VE }, { "header_insertion_mode", "Set header insertion mode", OFFSET(header_insertion_mode), AV_OPT_TYPE_INT,{ .i64 = AMF_VIDEO_ENCODER_HEVC_HEADER_INSERTION_MODE_NONE }, AMF_VIDEO_ENCODER_HEVC_HEADER_INSERTION_MODE_NONE, AMF_VIDEO_ENCODER_HEVC_HEADER_INSERTION_MODE_IDR_ALIGNED, VE, "hdrmode" }, { "none", "", 0, AV_OPT_TYPE_CONST, { .i64 = AMF_VIDEO_ENCODER_HEVC_HEADER_INSERTION_MODE_NONE }, 0, 0, VE, "hdrmode" }, { "gop", "", 0, AV_OPT_TYPE_CONST, { .i64 = AMF_VIDEO_ENCODER_HEVC_HEADER_INSERTION_MODE_GOP_ALIGNED }, 0, 0, VE, "hdrmode" }, { "idr", "", 0, AV_OPT_TYPE_CONST, { .i64 = AMF_VIDEO_ENCODER_HEVC_HEADER_INSERTION_MODE_IDR_ALIGNED }, 0, 0, VE, "hdrmode" }, - { "gops_per_idr", "GOPs per IDR 0-no IDR will be inserted", OFFSET(gops_per_idr), AV_OPT_TYPE_INT, { .i64 = 1 }, 0, INT_MAX, VE }, - { "preanalysis", "Enable preanalysis", OFFSET(preanalysis), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, VE}, + { "high_motion_quality_boost_enable", "Enable High motion quality boost mode", OFFSET(hw_high_motion_quality_boost), AV_OPT_TYPE_BOOL, {.i64 = -1 }, -1, 1, VE }, + { "gops_per_idr", "GOPs per IDR 0-no IDR will be inserted", OFFSET(gops_per_idr), AV_OPT_TYPE_INT, { .i64 = 1 }, 0, INT_MAX, VE }, + { "preencode", "Enable preencode", OFFSET(preencode), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, VE}, { "vbaq", "Enable VBAQ", OFFSET(enable_vbaq), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, VE}, { "enforce_hrd", "Enforce HRD", OFFSET(enforce_hrd), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, VE}, { "filler_data", "Filler Data Enable", OFFSET(filler_data), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, VE}, @@ -89,6 +98,52 @@ static const AVOption options[] = { { "aud", "Inserts AU Delimiter NAL unit", OFFSET(aud) ,AV_OPT_TYPE_BOOL,{ .i64 = 0 }, 0, 1, VE }, { "log_to_dbg", "Enable AMF logging to debug output", OFFSET(log_to_dbg), AV_OPT_TYPE_BOOL,{ .i64 = 0 }, 0, 1, VE }, + + //Pre Analysis options + { "preanalysis", "Enable preanalysis", OFFSET(preanalysis), AV_OPT_TYPE_BOOL, {.i64 = -1 }, -1, 1, VE }, + + { "pa_activity_type", "Set the type of activity analysis", OFFSET(pa_activity_type), AV_OPT_TYPE_INT, {.i64 = -1 }, -1, AMF_PA_ACTIVITY_YUV, VE, "activity_type" }, + { "y", "activity y", 0, AV_OPT_TYPE_CONST, {.i64 = AMF_PA_ACTIVITY_Y }, 0, 0, VE, "activity_type" }, + { "yuv", "activity yuv", 0, AV_OPT_TYPE_CONST, {.i64 = AMF_PA_ACTIVITY_YUV }, 0, 0, VE, "activity_type" }, + + { "pa_scene_change_detection_enable", "Enable scene change detection", OFFSET(pa_scene_change_detection), AV_OPT_TYPE_BOOL, {.i64 = -1 }, -1, 1, VE }, + + { "pa_scene_change_detection_sensitivity", "Set the sensitivity of scene change detection", OFFSET(pa_scene_change_detection_sensitivity), AV_OPT_TYPE_INT, {.i64 = -1 }, -1, AMF_PA_SCENE_CHANGE_DETECTION_SENSITIVITY_HIGH, VE, "scene_change_sensitivity" }, + { "low", "low scene change dectection sensitivity", 0, AV_OPT_TYPE_CONST, {.i64 = AMF_PA_SCENE_CHANGE_DETECTION_SENSITIVITY_LOW }, 0, 0, VE, "scene_change_sensitivity" }, + { "medium", "medium scene change dectection sensitivity", 0, AV_OPT_TYPE_CONST, {.i64 = AMF_PA_SCENE_CHANGE_DETECTION_SENSITIVITY_MEDIUM }, 0, 0, VE, "scene_change_sensitivity" }, + { "high", "high scene change dectection sensitivity", 0, AV_OPT_TYPE_CONST, {.i64 = AMF_PA_SCENE_CHANGE_DETECTION_SENSITIVITY_HIGH }, 0, 0, VE, "scene_change_sensitivity" }, + + { "pa_static_scene_detection_enable", "Enable static scene detection", OFFSET(pa_static_scene_detection), AV_OPT_TYPE_BOOL, {.i64 = -1 }, -1, 1, VE }, + + { "pa_static_scene_detection_sensitivity", "Set the sensitivity of static scene detection", OFFSET(pa_static_scene_detection_sensitivity), AV_OPT_TYPE_INT, {.i64 = -1 }, -1, AMF_PA_STATIC_SCENE_DETECTION_SENSITIVITY_HIGH, VE , "static_scene_sensitivity" }, + { "low", "low static scene dectection sensitivity", 0, AV_OPT_TYPE_CONST, {.i64 = AMF_PA_STATIC_SCENE_DETECTION_SENSITIVITY_LOW }, 0, 0, VE, "static_scene_sensitivity" }, + { "medium", "medium static scene dectection sensitivity", 0, AV_OPT_TYPE_CONST, {.i64 = AMF_PA_STATIC_SCENE_DETECTION_SENSITIVITY_MEDIUM }, 0, 0, VE, "static_scene_sensitivity" }, + { "high", "high static scene dectection sensitivity", 0, AV_OPT_TYPE_CONST, {.i64 = AMF_PA_STATIC_SCENE_DETECTION_SENSITIVITY_HIGH }, 0, 0, VE, "static_scene_sensitivity" }, + + { "pa_initial_qp_after_scene_change", "The QP value that is used immediately after a scene change", OFFSET(pa_initial_qp), AV_OPT_TYPE_INT, {.i64 = -1 }, -1, 51, VE }, + { "pa_max_qp_before_force_skip", "The QP threshold to allow a skip frame", OFFSET(pa_max_qp), AV_OPT_TYPE_INT, {.i64 = -1 }, -1, 51, VE }, + + { "pa_caq_strength", "Content Adaptive Quantization strength", OFFSET(pa_caq_strength), AV_OPT_TYPE_INT, {.i64 = -1 }, -1, AMF_PA_CAQ_STRENGTH_HIGH, VE , "caq_strength" }, + { "low", "low Content Adaptive Quantization strength", 0, AV_OPT_TYPE_CONST, {.i64 = AMF_PA_CAQ_STRENGTH_LOW }, 0, 0, VE, "caq_strength" }, + { "medium", "medium Content Adaptive Quantization strength", 0, AV_OPT_TYPE_CONST, {.i64 = AMF_PA_CAQ_STRENGTH_MEDIUM }, 0, 0, VE, "caq_strength" }, + { "high", "high Content Adaptive Quantization strength", 0, AV_OPT_TYPE_CONST, {.i64 = AMF_PA_CAQ_STRENGTH_HIGH }, 0, 0, VE, "caq_strength" }, + + { "pa_frame_sad_enable", "Enable Frame SAD algorithm", OFFSET(pa_frame_sad), AV_OPT_TYPE_BOOL, {.i64 = -1 }, -1, 1, VE }, + { "pa_ltr_enable", "Enable long term reference frame management", OFFSET(pa_ltr), AV_OPT_TYPE_BOOL, {.i64 = -1 }, -1, 1, VE }, + { "pa_lookahead_buffer_depth", "Sets the PA lookahead buffer size", OFFSET(pa_lookahead_buffer_depth), AV_OPT_TYPE_INT, {.i64 = -1 }, -1, MAX_LOOKAHEAD_DEPTH, VE }, + + { "pa_paq_mode", "Sets the perceptual adaptive quantization mode", OFFSET(pa_paq_mode), AV_OPT_TYPE_INT, {.i64 = -1 }, -1, AMF_PA_PAQ_MODE_CAQ, VE , "paq_mode" }, + { "none", "no perceptual adaptive quantization", 0, AV_OPT_TYPE_CONST, {.i64 = AMF_PA_PAQ_MODE_NONE }, 0, 0, VE, "paq_mode" }, + { "caq", "caq perceptual adaptive quantization", 0, AV_OPT_TYPE_CONST, {.i64 = AMF_PA_PAQ_MODE_CAQ }, 0, 0, VE, "paq_mode" }, + + { "pa_taq_mode", "Sets the temporal adaptive quantization mode", OFFSET(pa_taq_mode), AV_OPT_TYPE_INT, {.i64 = -1 }, -1, AMF_PA_TAQ_MODE_2, VE , "taq_mode" }, + { "none", "no temporal adaptive quantization", 0, AV_OPT_TYPE_CONST, {.i64 = AMF_PA_TAQ_MODE_NONE }, 0, 0, VE, "taq_mode" }, + { "1", "temporal adaptive quantization mode 1", 0, AV_OPT_TYPE_CONST, {.i64 = AMF_PA_TAQ_MODE_1 }, 0, 0, VE, "taq_mode" }, + { "2", "temporal adaptive quantization mode 2", 0, AV_OPT_TYPE_CONST, {.i64 = AMF_PA_TAQ_MODE_2 }, 0, 0, VE, "taq_mode" }, + + { "pa_high_motion_quality_boost_mode", "Sets the PA high motion quality boost mode", OFFSET(pa_high_motion_quality_boost_mode), AV_OPT_TYPE_INT, {.i64 = -1 }, -1, AMF_PA_HIGH_MOTION_QUALITY_BOOST_MODE_AUTO, VE , "high_motion_quality_boost_mode" }, + { "none", "no high motion quality boost", 0, AV_OPT_TYPE_CONST, {.i64 = AMF_PA_HIGH_MOTION_QUALITY_BOOST_MODE_NONE }, 0, 0, VE, "high_motion_quality_boost_mode" }, + { "auto", "auto high motion quality boost", 0, AV_OPT_TYPE_CONST, {.i64 = AMF_PA_HIGH_MOTION_QUALITY_BOOST_MODE_AUTO }, 0, 0, VE, "high_motion_quality_boost_mode" }, { NULL } }; @@ -186,6 +241,25 @@ FF_ENABLE_DEPRECATION_WARNINGS } } + // Pre-Pass, Pre-Analysis, Two-Pass + if (ctx->rate_control_mode == AMF_VIDEO_ENCODER_HEVC_RATE_CONTROL_METHOD_CONSTANT_QP) { + AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_HEVC_PREENCODE_ENABLE, 0); + if (ctx->preencode) + av_log(ctx, AV_LOG_WARNING, "Preencode is not supported by cqp Rate Control Method, automatically disabled\n"); + } + else { + AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_HEVC_PREENCODE_ENABLE, ctx->preencode); + } + + if (ctx->rate_control_mode == AMF_VIDEO_ENCODER_HEVC_RATE_CONTROL_METHOD_QUALITY_VBR) { + if (ctx->qvbr_quality_level != -1) { + AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_HEVC_QVBR_QUALITY_LEVEL, ctx->qvbr_quality_level); + } + } + + if (ctx->hw_high_motion_quality_boost != -1) { + AMF_ASSIGN_PROPERTY_BOOL(res, ctx->encoder, AMF_VIDEO_ENCODER_HEVC_HIGH_MOTION_QUALITY_BOOST_ENABLE, ((ctx->hw_high_motion_quality_boost == 0) ? false : true)); + } AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_HEVC_RATE_CONTROL_METHOD, ctx->rate_control_mode); if (avctx->rc_buffer_size) { @@ -198,8 +272,6 @@ FF_ENABLE_DEPRECATION_WARNINGS AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_HEVC_INITIAL_VBV_BUFFER_FULLNESS, amf_buffer_fullness); } } - // Pre-Pass, Pre-Analysis, Two-Pass - AMF_ASSIGN_PROPERTY_BOOL(res, ctx->encoder, AMF_VIDEO_ENCODER_HEVC_RATE_CONTROL_PREANALYSIS_ENABLE, ctx->preanalysis); if (ctx->rate_control_mode == AMF_VIDEO_ENCODER_HEVC_RATE_CONTROL_METHOD_CONSTANT_QP) { AMF_ASSIGN_PROPERTY_BOOL(res, ctx->encoder, AMF_VIDEO_ENCODER_HEVC_ENABLE_VBAQ, false); @@ -228,6 +300,57 @@ FF_ENABLE_DEPRECATION_WARNINGS av_log(ctx, AV_LOG_WARNING, "rate control mode is PEAK_CONSTRAINED_VBR but rc_max_rate is not set\n"); } + if (ctx->preanalysis != -1) { + AMF_ASSIGN_PROPERTY_BOOL(res, ctx->encoder, AMF_VIDEO_ENCODER_HEVC_PRE_ANALYSIS_ENABLE, !!((ctx->preanalysis == 0) ? false : true)); + } + + res = ctx->encoder->pVtbl->GetProperty(ctx->encoder, AMF_VIDEO_ENCODER_HEVC_PRE_ANALYSIS_ENABLE, &var); + if ((int)var.int64Value) + { + if (ctx->pa_activity_type != -1) { + AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_PA_ACTIVITY_TYPE, ctx->pa_activity_type); + } + if (ctx->pa_scene_change_detection != -1) { + AMF_ASSIGN_PROPERTY_BOOL(res, ctx->encoder, AMF_PA_SCENE_CHANGE_DETECTION_ENABLE, ((ctx->pa_scene_change_detection == 0) ? false : true)); + } + if (ctx->pa_scene_change_detection_sensitivity != -1) { + AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_PA_SCENE_CHANGE_DETECTION_SENSITIVITY, ctx->pa_scene_change_detection_sensitivity); + } + if (ctx->pa_static_scene_detection != -1) { + AMF_ASSIGN_PROPERTY_BOOL(res, ctx->encoder, AMF_PA_STATIC_SCENE_DETECTION_ENABLE, ((ctx->pa_static_scene_detection == 0) ? false : true)); + } + if (ctx->pa_static_scene_detection_sensitivity != -1) { + AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_PA_STATIC_SCENE_DETECTION_SENSITIVITY, ctx->pa_static_scene_detection_sensitivity); + } + if (ctx->pa_initial_qp != -1) { + AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_PA_INITIAL_QP_AFTER_SCENE_CHANGE, ctx->pa_initial_qp); + } + if (ctx->pa_max_qp != -1) { + AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_PA_MAX_QP_BEFORE_FORCE_SKIP, ctx->pa_max_qp); + } + if (ctx->pa_caq_strength != -1) { + AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_PA_CAQ_STRENGTH, ctx->pa_caq_strength); + } + if (ctx->pa_frame_sad != -1) { + AMF_ASSIGN_PROPERTY_BOOL(res, ctx->encoder, AMF_PA_FRAME_SAD_ENABLE, ((ctx->pa_frame_sad == 0) ? false : true)); + } + if (ctx->pa_paq_mode != -1) { + AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_PA_PAQ_MODE, ctx->pa_paq_mode); + } + if (ctx->pa_taq_mode != -1) { + AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_PA_TAQ_MODE, ctx->pa_taq_mode); + } + if (ctx->pa_ltr != -1) { + AMF_ASSIGN_PROPERTY_BOOL(res, ctx->encoder, AMF_PA_LTR_ENABLE, ((ctx->pa_ltr == 0) ? false : true)); + } + if (ctx->pa_lookahead_buffer_depth != -1) { + AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_PA_LOOKAHEAD_BUFFER_DEPTH, ctx->pa_lookahead_buffer_depth); + } + if (ctx->pa_high_motion_quality_boost_mode != -1) { + AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_PA_HIGH_MOTION_QUALITY_BOOST_MODE, ctx->pa_high_motion_quality_boost_mode); + } + } + // init encoder res = ctx->encoder->pVtbl->Init(ctx->encoder, ctx->format, avctx->width, avctx->height); AMF_RETURN_IF_FALSE(ctx, res == AMF_OK, AVERROR_BUG, "encoder->Init() failed with error %d\n", res); @@ -268,7 +391,6 @@ FF_ENABLE_DEPRECATION_WARNINGS } AMF_ASSIGN_PROPERTY_BOOL(res, ctx->encoder, AMF_VIDEO_ENCODER_HEVC_RATE_CONTROL_SKIP_FRAME_ENABLE, ctx->skip_frame); - // fill extradata res = AMFVariantInit(&var); AMF_RETURN_IF_FALSE(ctx, res == AMF_OK, AVERROR_BUG, "AMFVariantInit() failed with error %d\n", res); From bcfcc1982151ee17808d66c39426975714fc7906 Mon Sep 17 00:00:00 2001 From: Romain Beauxis Date: Thu, 22 Jun 2023 09:14:18 -0500 Subject: [PATCH 1686/2172] Add FATE test for timed id3 demux. Signed-off-by: Anton Khirnov --- tests/fate/demux.mak | 3 +++ tests/ref/fate/ts-timed-id3-demux | 6 ++++++ 2 files changed, 9 insertions(+) create mode 100644 tests/ref/fate/ts-timed-id3-demux diff --git a/tests/fate/demux.mak b/tests/fate/demux.mak index d8fc68af886..ace8fa0b523 100644 --- a/tests/fate/demux.mak +++ b/tests/fate/demux.mak @@ -157,6 +157,9 @@ fate-xwma-demux: CMD = crc -i $(TARGET_SAMPLES)/xwma/ergon.xwma -c:a copy FATE_FFPROBE_DEMUX-$(CONFIG_MPEGTS_DEMUXER) += fate-ts-demux fate-ts-demux: CMD = ffprobe_demux $(TARGET_SAMPLES)/ac3/mp3ac325-4864-small.ts +FATE_FFPROBE_DEMUX-$(CONFIG_MPEGTS_DEMUXER) += fate-ts-timed-id3-demux +fate-ts-timed-id3-demux: CMD = ffprobe_demux $(TARGET_SAMPLES)/mpegts/id3.ts + FATE_SAMPLES_DEMUX += $(FATE_SAMPLES_DEMUX-yes) FATE_SAMPLES_FFMPEG += $(FATE_SAMPLES_DEMUX) FATE_FFPROBE_DEMUX += $(FATE_FFPROBE_DEMUX-yes) diff --git a/tests/ref/fate/ts-timed-id3-demux b/tests/ref/fate/ts-timed-id3-demux new file mode 100644 index 00000000000..922ca17d157 --- /dev/null +++ b/tests/ref/fate/ts-timed-id3-demux @@ -0,0 +1,6 @@ +packet|codec_type=data|stream_index=0|pts=126000|pts_time=1.400000|dts=126000|dts_time=1.400000|duration=N/A|duration_time=N/A|size=26|pos=564|flags=K__|data_hash=CRC32:469f474b|side_data|side_data_type=MPEGTS Stream ID|id=189 + +packet|codec_type=data|stream_index=0|pts=577350|pts_time=6.415000|dts=577350|dts_time=6.415000|duration=N/A|duration_time=N/A|size=26|pos=1316|flags=K__|data_hash=CRC32:469f474b|side_data|side_data_type=MPEGTS Stream ID|id=189 + +stream|index=0|codec_name=timed_id3|profile=unknown|codec_type=data|codec_tag_string=ID3 |codec_tag=0x20334449|ts_packetsize=188|id=0x100|r_frame_rate=0/0|avg_frame_rate=0/0|time_base=1/90000|start_pts=126000|start_time=1.400000|duration_ts=451350|duration=5.015000|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=2|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=id3.ts|nb_streams=1|nb_programs=1|format_name=mpegts|start_time=1.400000|duration=5.015000|size=1504|bit_rate=2399|probe_score=2 From 0b8c1f26d33884e1e775f4266c850b5a2da7dd58 Mon Sep 17 00:00:00 2001 From: Nuo Mi Date: Tue, 21 Mar 2023 16:01:14 +0100 Subject: [PATCH 1687/2172] avcodec/h2645_parse: add support for H266/VVC Co-authored-by: Thomas Siedel Signed-off-by: James Almer --- libavcodec/h2645_parse.c | 71 +++++++++++++++++++- libavcodec/vvc.h | 142 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 212 insertions(+), 1 deletion(-) create mode 100644 libavcodec/vvc.h diff --git a/libavcodec/h2645_parse.c b/libavcodec/h2645_parse.c index 90944177c72..28db465059e 100644 --- a/libavcodec/h2645_parse.c +++ b/libavcodec/h2645_parse.c @@ -30,6 +30,7 @@ #include "hevc.h" #include "h264.h" #include "h2645_parse.h" +#include "vvc.h" int ff_h2645_extract_rbsp(const uint8_t *src, int length, H2645RBSP *rbsp, H2645NAL *nal, int small_padding) @@ -145,6 +146,47 @@ int ff_h2645_extract_rbsp(const uint8_t *src, int length, return si; } +static const char *const vvc_nal_type_name[32] = { + "TRAIL_NUT", // VVC_TRAIL_NUT + "STSA_NUT", // VVC_STSA_NUT + "RADL_NUT", // VVC_RADL_NUT + "RASL_NUT", // VVC_RASL_NUT + "RSV_VCL4", // VVC_RSV_VCL_4 + "RSV_VCL5", // VVC_RSV_VCL_5 + "RSV_VCL6", // VVC_RSV_VCL_6 + "IDR_W_RADL", // VVC_IDR_W_RADL + "IDR_N_LP", // VVC_IDR_N_LP + "CRA_NUT", // VVC_CRA_NUT + "GDR_NUT", // VVC_GDR_NUT + "RSV_IRAP_11", // VVC_RSV_IRAP_11 + "OPI_NUT", // VVC_OPI_NUT + "DCI_NUT", // VVC_DCI_NUT + "VPS_NUT", // VVC_VPS_NUT + "SPS_NUT", // VVC_SPS_NUT + "PPS_NUT", // VVC_PPS_NUT + "APS_PREFIX", // VVC_PREFIX_APS_NUT + "APS_SUFFIX", // VVC_SUFFIX_APS_NUT + "PH_NUT", // VVC_PH_NUT + "AUD_NUT", // VVC_AUD_NUT + "EOS_NUT", // VVC_EOS_NUT + "EOB_NUT", // VVC_EOB_NUT + "SEI_PREFIX", // VVC_PREFIX_SEI_NUT + "SEI_SUFFIX", // VVC_SUFFIX_SEI_NUT + "FD_NUT", // VVC_FD_NUT + "RSV_NVCL26", // VVC_RSV_NVCL_26 + "RSV_NVCL27", // VVC_RSV_NVCL_27 + "UNSPEC28", // VVC_UNSPEC_28 + "UNSPEC29", // VVC_UNSPEC_29 + "UNSPEC30", // VVC_UNSPEC_30 + "UNSPEC31", // VVC_UNSPEC_31 +}; + +static const char *vvc_nal_unit_name(int nal_type) +{ + av_assert0(nal_type >= 0 && nal_type < 32); + return vvc_nal_type_name[nal_type]; +} + static const char *const hevc_nal_type_name[64] = { "TRAIL_N", // HEVC_NAL_TRAIL_N "TRAIL_R", // HEVC_NAL_TRAIL_R @@ -293,6 +335,31 @@ static int get_bit_length(H2645NAL *nal, int min_size, int skip_trailing_zeros) * @return AVERROR_INVALIDDATA if the packet is not a valid NAL unit, * 0 otherwise */ +static int vvc_parse_nal_header(H2645NAL *nal, void *logctx) +{ + GetBitContext *gb = &nal->gb; + + if (get_bits1(gb) != 0) //forbidden_zero_bit + return AVERROR_INVALIDDATA; + + skip_bits1(gb); //nuh_reserved_zero_bit + + nal->nuh_layer_id = get_bits(gb, 6); + nal->type = get_bits(gb, 5); + nal->temporal_id = get_bits(gb, 3) - 1; + if (nal->temporal_id < 0) + return AVERROR_INVALIDDATA; + + if ((nal->type >= VVC_IDR_W_RADL && nal->type <= VVC_RSV_IRAP_11) && nal->temporal_id) + return AVERROR_INVALIDDATA; + + av_log(logctx, AV_LOG_DEBUG, + "nal_unit_type: %d(%s), nuh_layer_id: %d, temporal_id: %d\n", + nal->type, vvc_nal_unit_name(nal->type), nal->nuh_layer_id, nal->temporal_id); + + return 0; +} + static int hevc_parse_nal_header(H2645NAL *nal, void *logctx) { GetBitContext *gb = &nal->gb; @@ -509,7 +576,9 @@ int ff_h2645_packet_split(H2645Packet *pkt, const uint8_t *buf, int length, /* Reset type in case it contains a stale value from a previously parsed NAL */ nal->type = 0; - if (codec_id == AV_CODEC_ID_HEVC) + if (codec_id == AV_CODEC_ID_VVC) + ret = vvc_parse_nal_header(nal, logctx); + else if (codec_id == AV_CODEC_ID_HEVC) ret = hevc_parse_nal_header(nal, logctx); else ret = h264_parse_nal_header(nal, logctx); diff --git a/libavcodec/vvc.h b/libavcodec/vvc.h new file mode 100644 index 00000000000..099d2fc2adb --- /dev/null +++ b/libavcodec/vvc.h @@ -0,0 +1,142 @@ +/* + * H.266 / VVC shared code + * + * 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_VVC_H +#define AVCODEC_VVC_H + +/** + * Table 5 – NAL unit type codes and NAL unit type classes + * in T-REC-H.266-202008 + */ +enum VVCNALUnitType { + VVC_TRAIL_NUT = 0, + VVC_STSA_NUT = 1, + VVC_RADL_NUT = 2, + VVC_RASL_NUT = 3, + VVC_RSV_VCL_4 = 4, + VVC_RSV_VCL_5 = 5, + VVC_RSV_VCL_6 = 6, + VVC_IDR_W_RADL = 7, + VVC_IDR_N_LP = 8, + VVC_CRA_NUT = 9, + VVC_GDR_NUT = 10, + VVC_RSV_IRAP_11 = 11, + VVC_OPI_NUT = 12, + VVC_DCI_NUT = 13, + VVC_VPS_NUT = 14, + VVC_SPS_NUT = 15, + VVC_PPS_NUT = 16, + VVC_PREFIX_APS_NUT = 17, + VVC_SUFFIX_APS_NUT = 18, + VVC_PH_NUT = 19, + VVC_AUD_NUT = 20, + VVC_EOS_NUT = 21, + VVC_EOB_NUT = 22, + VVC_PREFIX_SEI_NUT = 23, + VVC_SUFFIX_SEI_NUT = 24, + VVC_FD_NUT = 25, + VVC_RSV_NVCL_26 = 26, + VVC_RSV_NVCL_27 = 27, + VVC_UNSPEC_28 = 28, + VVC_UNSPEC_29 = 29, + VVC_UNSPEC_30 = 30, + VVC_UNSPEC_31 = 31, +}; + +enum VVCSliceType { + VVC_SLICE_TYPE_B = 0, + VVC_SLICE_TYPE_P = 1, + VVC_SLICE_TYPE_I = 2, +}; + +enum { + //6.2 we can have 3 sample arrays + VVC_MAX_SAMPLE_ARRAYS = 3, + + //7.4.3.3 vps_max_layers_minus1 is u(6) + VVC_MAX_LAYERS = 64, + + //7.4.3.3 The value of vps_max_sublayers_minus1 shall be in the range of 0 to 6, inclusive + VVC_MAX_SUBLAYERS = 7, + + //7.4.3.3 vps_num_ptls_minus1 is u(8) + VVC_MAX_PTLS = 256, + + //7.4.3.3 vps_num_output_layer_sets_minus2 is u(8) + VVC_MAX_TOTAL_NUM_OLSS = 257, + + // 7.3.2.3: vps_video_parameter_set_id is u(4). + VVC_MAX_VPS_COUNT = 16, + // 7.3.2.4: sps_seq_parameter_set_id is u(4) + VVC_MAX_SPS_COUNT = 16, + // 7.3.2.5: pps_pic_parameter_set_id is u(6) + VVC_MAX_PPS_COUNT = 64, + + // 7.4.4.1: ptl_num_sub_profiles is u(8) + VVC_MAX_SUB_PROFILES = 256, + + // A.4.2: according to (1577), MaxDpbSize is bounded above by 2 * maxDpbPicBuf(8) + VVC_MAX_DPB_SIZE = 16, + + //7.4.3.4 sps_num_ref_pic_lists in range [0, 64] + VVC_MAX_REF_PIC_LISTS = 64, + + //7.4.11 num_ref_entries in range [0, MaxDpbSize + 13] + VVC_MAX_REF_ENTRIES = VVC_MAX_DPB_SIZE + 13, + + //7.4.3.3 sps_num_points_in_qp_table_minus1[i] in range [0, 36 − sps_qp_table_start_minus26[i]], + //sps_qp_table_start_minus26[i] in range [sps_qp_table_start_minus26[i] −26 − QpBdOffset, 36] + //for 10 bitsQpBdOffset is 12, so sps_num_points_in_qp_table_minus1[i] in range [0, 74] + VVC_MAX_POINTS_IN_QP_TABLE = 75, + + // 7.4.6.1: hrd_cpb_cnt_minus1 is in [0, 31]. + VVC_MAX_CPB_CNT = 32, + + // A.4.1: the highest level allows a MaxLumaPs of 35 651 584. + VVC_MAX_LUMA_PS = 35651584, + + // A.4.1: pic_width_in_luma_samples and pic_height_in_luma_samples are + // constrained to be not greater than sqrt(MaxLumaPs * 8). Hence height/ + // width are bounded above by sqrt(8 * 35651584) = 16888.2 samples. + VVC_MAX_WIDTH = 16888, + VVC_MAX_HEIGHT = 16888, + + // A.4.1: table A.1 allows at most 440 tiles per au for any level. + VVC_MAX_TILES_PER_AU = 440, + // A.4.1: table A.1 did not define max tile rows. + // in worest a case, we can have 1x440 tiles picture. + VVC_MAX_TILE_ROWS = VVC_MAX_TILES_PER_AU, + // A.4.1: table A.1 allows at most 20 tile columns for any level. + VVC_MAX_TILE_COLUMNS = 20, + + // A.4.1 table A.1 allows at most 600 slice for any level. + VVC_MAX_SLICES = 600, + + // 7.4.8: in the worst case (!pps_no_pic_partition_flag and + // sps_entropy_coding_sync_enabled_flag are both true), entry points can be + // placed at the beginning of every Ctb row in every tile, giving an + // upper bound of (num_tile_columns_minus1 + 1) * PicHeightInCtbsY - 1. + // Only a stream with very high resolution and perverse parameters could + // get near that, though, so set a lower limit here with the maximum + // possible value for 8K video (at most 135 32x32 Ctb rows). + VVC_MAX_ENTRY_POINTS = VVC_MAX_TILE_COLUMNS * 135, +}; + +#endif /* AVCODEC_VVC_H */ From 136e96a8a896b04724bcb991c5eb2943d101aa51 Mon Sep 17 00:00:00 2001 From: James Almer Date: Thu, 29 Jun 2023 11:16:57 -0300 Subject: [PATCH 1688/2172] avcodec/extract_extradata: add support for H266/VVC Signed-off-by: James Almer --- libavcodec/extract_extradata_bsf.c | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/libavcodec/extract_extradata_bsf.c b/libavcodec/extract_extradata_bsf.c index 329b1a61744..d5c81a27689 100644 --- a/libavcodec/extract_extradata_bsf.c +++ b/libavcodec/extract_extradata_bsf.c @@ -31,6 +31,7 @@ #include "hevc.h" #include "startcode.h" #include "vc1_common.h" +#include "vvc.h" typedef struct ExtractExtradataContext { const AVClass *class; @@ -134,6 +135,9 @@ static int extract_extradata_av1(AVBSFContext *ctx, AVPacket *pkt, static int extract_extradata_h2645(AVBSFContext *ctx, AVPacket *pkt, uint8_t **data, int *size) { + static const int extradata_nal_types_vvc[] = { + VVC_VPS_NUT, VVC_SPS_NUT, VVC_PPS_NUT, + }; static const int extradata_nal_types_hevc[] = { HEVC_NAL_VPS, HEVC_NAL_SPS, HEVC_NAL_PPS, }; @@ -148,7 +152,10 @@ static int extract_extradata_h2645(AVBSFContext *ctx, AVPacket *pkt, int nb_extradata_nal_types; int i, has_sps = 0, has_vps = 0, ret = 0; - if (ctx->par_in->codec_id == AV_CODEC_ID_HEVC) { + if (ctx->par_in->codec_id == AV_CODEC_ID_VVC) { + extradata_nal_types = extradata_nal_types_vvc; + nb_extradata_nal_types = FF_ARRAY_ELEMS(extradata_nal_types_vvc); + } else if (ctx->par_in->codec_id == AV_CODEC_ID_HEVC) { extradata_nal_types = extradata_nal_types_hevc; nb_extradata_nal_types = FF_ARRAY_ELEMS(extradata_nal_types_hevc); } else { @@ -165,7 +172,10 @@ static int extract_extradata_h2645(AVBSFContext *ctx, AVPacket *pkt, H2645NAL *nal = &s->h2645_pkt.nals[i]; if (val_in_array(extradata_nal_types, nb_extradata_nal_types, nal->type)) { extradata_size += nal->raw_size + 3; - if (ctx->par_in->codec_id == AV_CODEC_ID_HEVC) { + if (ctx->par_in->codec_id == AV_CODEC_ID_VVC) { + if (nal->type == VVC_SPS_NUT) has_sps = 1; + if (nal->type == VVC_VPS_NUT) has_vps = 1; + } else if (ctx->par_in->codec_id == AV_CODEC_ID_HEVC) { if (nal->type == HEVC_NAL_SPS) has_sps = 1; if (nal->type == HEVC_NAL_VPS) has_vps = 1; } else { @@ -177,7 +187,8 @@ static int extract_extradata_h2645(AVBSFContext *ctx, AVPacket *pkt, } if (extradata_size && - ((ctx->par_in->codec_id == AV_CODEC_ID_HEVC && has_sps && has_vps) || + ((ctx->par_in->codec_id == AV_CODEC_ID_VVC && has_sps) || + (ctx->par_in->codec_id == AV_CODEC_ID_HEVC && has_sps && has_vps) || (ctx->par_in->codec_id == AV_CODEC_ID_H264 && has_sps))) { AVBufferRef *filtered_buf = NULL; PutByteContext pb_filtered_data, pb_extradata; @@ -335,6 +346,7 @@ static const struct { { AV_CODEC_ID_MPEG2VIDEO, extract_extradata_mpeg12 }, { AV_CODEC_ID_MPEG4, extract_extradata_mpeg4 }, { AV_CODEC_ID_VC1, extract_extradata_vc1 }, + { AV_CODEC_ID_VVC, extract_extradata_h2645 }, }; static int extract_extradata_init(AVBSFContext *ctx) @@ -404,6 +416,7 @@ static const enum AVCodecID codec_ids[] = { AV_CODEC_ID_MPEG2VIDEO, AV_CODEC_ID_MPEG4, AV_CODEC_ID_VC1, + AV_CODEC_ID_VVC, AV_CODEC_ID_NONE, }; From dfc62fd1c6da6429bbd0eb3cbb6f3804e8fcb8ae Mon Sep 17 00:00:00 2001 From: Nuo Mi Date: Tue, 21 Mar 2023 16:01:15 +0100 Subject: [PATCH 1689/2172] avcodec/cbs: add cbs implementation for H266/VVC Add CodedBitstreamContext to parse VPS,SPS,PPS in VVC nal units. Implement parsing and writing of SPS,PPS,VPS,PH,AUD,SEI and slices. Add ff_cbs_type_h266 to cbs types tables and AV_CODEC_ID_H266 to cbs codec ids. Co-authored-by: Thomas Siedel Signed-off-by: James Almer --- configure | 2 + libavcodec/Makefile | 1 + libavcodec/cbs.c | 6 + libavcodec/cbs_h2645.c | 454 +++- libavcodec/cbs_h266.h | 783 +++++++ libavcodec/cbs_h266_syntax_template.c | 3116 +++++++++++++++++++++++++ libavcodec/cbs_internal.h | 1 + libavcodec/cbs_sei.c | 29 + 8 files changed, 4390 insertions(+), 2 deletions(-) create mode 100644 libavcodec/cbs_h266.h create mode 100644 libavcodec/cbs_h266_syntax_template.c diff --git a/configure b/configure index f23252dfec0..b2665a0fbd5 100755 --- a/configure +++ b/configure @@ -2477,6 +2477,7 @@ CONFIG_EXTRA=" cbs_av1 cbs_h264 cbs_h265 + cbs_h266 cbs_jpeg cbs_mpeg2 cbs_vp9 @@ -2761,6 +2762,7 @@ threads_if_any="$THREADS_LIST" cbs_av1_select="cbs" cbs_h264_select="cbs" cbs_h265_select="cbs" +cbs_h266_select="cbs" cbs_jpeg_select="cbs" cbs_mpeg2_select="cbs" cbs_vp9_select="cbs" diff --git a/libavcodec/Makefile b/libavcodec/Makefile index 0e4d27f37b4..a0ebb15a2c4 100644 --- a/libavcodec/Makefile +++ b/libavcodec/Makefile @@ -76,6 +76,7 @@ OBJS-$(CONFIG_CBS) += cbs.o cbs_bsf.o OBJS-$(CONFIG_CBS_AV1) += cbs_av1.o OBJS-$(CONFIG_CBS_H264) += cbs_h2645.o cbs_sei.o h2645_parse.o OBJS-$(CONFIG_CBS_H265) += cbs_h2645.o cbs_sei.o h2645_parse.o +OBJS-$(CONFIG_CBS_H266) += cbs_h2645.o cbs_sei.o h2645_parse.o OBJS-$(CONFIG_CBS_JPEG) += cbs_jpeg.o OBJS-$(CONFIG_CBS_MPEG2) += cbs_mpeg2.o OBJS-$(CONFIG_CBS_VP9) += cbs_vp9.o diff --git a/libavcodec/cbs.c b/libavcodec/cbs.c index cf5211249bb..13a01bef513 100644 --- a/libavcodec/cbs.c +++ b/libavcodec/cbs.c @@ -40,6 +40,9 @@ static const CodedBitstreamType *const cbs_type_table[] = { #if CONFIG_CBS_H265 &ff_cbs_type_h265, #endif +#if CONFIG_CBS_H266 + &ff_cbs_type_h266, +#endif #if CONFIG_CBS_JPEG &ff_cbs_type_jpeg, #endif @@ -61,6 +64,9 @@ const enum AVCodecID ff_cbs_all_codec_ids[] = { #if CONFIG_CBS_H265 AV_CODEC_ID_H265, #endif +#if CONFIG_CBS_H266 + AV_CODEC_ID_H266, +#endif #if CONFIG_CBS_JPEG AV_CODEC_ID_MJPEG, #endif diff --git a/libavcodec/cbs_h2645.c b/libavcodec/cbs_h2645.c index f2e59f1ac77..cdd79015188 100644 --- a/libavcodec/cbs_h2645.c +++ b/libavcodec/cbs_h2645.c @@ -24,9 +24,11 @@ #include "cbs_internal.h" #include "cbs_h264.h" #include "cbs_h265.h" +#include "cbs_h266.h" #include "h264.h" #include "h2645_parse.h" #include "hevc.h" +#include "vvc.h" static int cbs_read_ue_golomb(CodedBitstreamContext *ctx, GetBitContext *gbc, @@ -255,6 +257,7 @@ static int cbs_h265_payload_extension_present(GetBitContext *gbc, uint32_t paylo #define FUNC_NAME1(rw, codec, name) FUNC_NAME2(rw, codec, name) #define FUNC_H264(name) FUNC_NAME1(READWRITE, h264, name) #define FUNC_H265(name) FUNC_NAME1(READWRITE, h265, name) +#define FUNC_H266(name) FUNC_NAME1(READWRITE, h266, name) #define FUNC_SEI(name) FUNC_NAME1(READWRITE, sei, name) #define SUBSCRIPTS(subs, ...) (subs > 0 ? ((int[subs + 1]){ subs, __VA_ARGS__ }) : NULL) @@ -369,6 +372,10 @@ static int cbs_h2645_read_more_rbsp_data(GetBitContext *gbc) #include "cbs_h265_syntax_template.c" #undef FUNC +#define FUNC(name) FUNC_H266(name) +#include "cbs_h266_syntax_template.c" +#undef FUNC + #undef READ #undef READWRITE #undef RWContext @@ -447,6 +454,10 @@ static int cbs_h2645_read_more_rbsp_data(GetBitContext *gbc) #include "cbs_h265_syntax_template.c" #undef FUNC +#define FUNC(name) FUNC_H266(name) +#include "cbs_h266_syntax_template.c" +#undef FUNC + #undef WRITE #undef READWRITE #undef RWContext @@ -476,8 +487,9 @@ static int cbs_h2645_fragment_add_nals(CodedBitstreamContext *ctx, const H2645NAL *nal = &packet->nals[i]; AVBufferRef *ref; size_t size = nal->size; + enum AVCodecID codec_id = ctx->codec->codec_id; - if (nal->nuh_layer_id > 0) + if (codec_id != AV_CODEC_ID_VVC && nal->nuh_layer_id > 0) continue; // Remove trailing zeroes. @@ -513,6 +525,12 @@ static int cbs_h2645_split_fragment(CodedBitstreamContext *ctx, if (frag->data_size == 0) return 0; + if (codec_id == AV_CODEC_ID_VVC) { + //we deactive picture header here to avoid reuse previous au's ph. + CodedBitstreamH266Context *h266 = ctx->priv_data; + h266->priv.ph = NULL; + } + if (header && frag->data[0] && codec_id == AV_CODEC_ID_H264) { // AVCC header. size_t size, start, end; @@ -640,6 +658,71 @@ static int cbs_h2645_split_fragment(CodedBitstreamContext *ctx, return err; } + } else if(header && frag->data[0] && codec_id == AV_CODEC_ID_VVC) { + // VVCC header. + int ptl_present_flag, num_arrays; + int b, i, j; + + priv->mp4 = 1; + + bytestream2_init(&gbc, frag->data, frag->data_size); + + b = bytestream2_get_byte(&gbc); + priv->nal_length_size = ((b >> 1) & 3) + 1; + ptl_present_flag = b & 1; + + if(ptl_present_flag) { + int num_sublayers, num_bytes_constraint_info, num_sub_profiles; + num_sublayers = (bytestream2_get_be16u(&gbc) >> 4) & 7; + bytestream2_skip(&gbc, 1); + + // begin VvcPTLRecord(num_sublayers); + num_bytes_constraint_info = bytestream2_get_byte(&gbc) & 0x3f; + bytestream2_skip(&gbc, 2 + num_bytes_constraint_info); + if(num_sublayers > 1) { + int count_present_flags = 0; + b = bytestream2_get_byte(&gbc); + for(i = num_sublayers - 2; i >= 0; i--) { + if((b >> (7 - (num_sublayers - 2 - i))) & 0x01) + count_present_flags++; + } + bytestream2_skip(&gbc, count_present_flags); + } + num_sub_profiles = bytestream2_get_byte(&gbc); + bytestream2_skip(&gbc, num_sub_profiles * 4); + // end VvcPTLRecord(num_sublayers); + + bytestream2_skip(&gbc, 3 * 2); + } + + num_arrays = bytestream2_get_byte(&gbc); + for(j = 0; j < num_arrays; j++) { + size_t start, end, size; + int nal_unit_type = bytestream2_get_byte(&gbc) & 0x1f; + unsigned int num_nalus = 1; + if(nal_unit_type != VVC_DCI_NUT && nal_unit_type != VVC_OPI_NUT) + num_nalus = bytestream2_get_be16u(&gbc); + + start = bytestream2_tell(&gbc); + for(i = 0; i < num_nalus; i++) { + size = bytestream2_get_be16(&gbc); + bytestream2_skip(&gbc, size); + } + end = bytestream2_tell(&gbc); + + err = ff_h2645_packet_split(&priv->read_packet, + frag->data + start, end - start, + ctx->log_ctx, 1, 2, AV_CODEC_ID_VVC, 1, 1); + if (err < 0) { + av_log(ctx->log_ctx, AV_LOG_ERROR, "Failed to split " + "VVCC array %d (%d NAL units of type %d).\n", + i, num_nalus, nal_unit_type); + return err; + } + err = cbs_h2645_fragment_add_nals(ctx, frag, &priv->read_packet); + if (err < 0) + return err; + } } else { // Annex B, or later MP4 with already-known parameters. @@ -686,6 +769,46 @@ cbs_h2645_replace_ps(5, VPS, vps, vps_video_parameter_set_id) cbs_h2645_replace_ps(5, SPS, sps, sps_seq_parameter_set_id) cbs_h2645_replace_ps(5, PPS, pps, pps_pic_parameter_set_id) +#define cbs_h266_replace_ps(h26n, ps_name, ps_var, id_element) \ +static int cbs_h26 ## h26n ## _replace_ ## ps_var(CodedBitstreamContext *ctx, \ + CodedBitstreamUnit *unit) \ +{ \ + CodedBitstreamH26 ## h26n ## Context *priv = ctx->priv_data; \ + H26 ## h26n ## Raw ## ps_name *ps_var = unit->content; \ + unsigned int id = ps_var->id_element; \ + int err = ff_cbs_make_unit_refcounted(ctx, unit); \ + if (err < 0) \ + return err; \ + av_buffer_unref(&priv->ps_var ## _ref[id]); \ + av_assert0(unit->content_ref); \ + priv->ps_var ## _ref[id] = av_buffer_ref(unit->content_ref); \ + if (!priv->ps_var ## _ref[id]) \ + return AVERROR(ENOMEM); \ + priv->ps_var[id] = (H26 ## h26n ## Raw ## ps_name *)priv->ps_var ## _ref[id]->data; \ + return 0; \ +} + +cbs_h266_replace_ps(6, VPS, vps, vps_video_parameter_set_id) +cbs_h266_replace_ps(6, SPS, sps, sps_seq_parameter_set_id) +cbs_h266_replace_ps(6, PPS, pps, pps_pic_parameter_set_id) + +static int cbs_h266_replace_ph(CodedBitstreamContext *ctx, + CodedBitstreamUnit *unit) +{ + CodedBitstreamH266Context *h266 = ctx->priv_data; + int err; + + h266->priv.ph = NULL; + err = ff_cbs_make_unit_refcounted(ctx, unit); + if (err < 0) + return err; + err = av_buffer_replace(&h266->priv.ph_ref, unit->content_ref); + if (err < 0) + return err; + h266->priv.ph = (H266RawPH*)h266->priv.ph_ref->data; + return 0; +} + static int cbs_h264_read_nal_unit(CodedBitstreamContext *ctx, CodedBitstreamUnit *unit) { @@ -926,6 +1049,130 @@ static int cbs_h265_read_nal_unit(CodedBitstreamContext *ctx, return 0; } +static int cbs_h266_read_nal_unit(CodedBitstreamContext *ctx, + CodedBitstreamUnit *unit) +{ + GetBitContext gbc; + int err; + + err = init_get_bits8(&gbc, unit->data, unit->data_size); + if (err < 0) + return err; + + err = ff_cbs_alloc_unit_content(ctx, unit); + if (err < 0) + return err; + + switch (unit->type) { + case VVC_VPS_NUT: + { + H266RawVPS *vps = unit->content; + + err = cbs_h266_read_vps(ctx, &gbc, vps); + if (err < 0) + return err; + + err = cbs_h266_replace_vps(ctx, unit); + if (err < 0) + return err; + } + break; + case VVC_SPS_NUT: + { + H266RawSPS *sps = unit->content; + + err = cbs_h266_read_sps(ctx, &gbc, sps); + if (err < 0) + return err; + + err = cbs_h266_replace_sps(ctx, unit); + if (err < 0) + return err; + } + break; + + case VVC_PPS_NUT: + { + H266RawPPS *pps = unit->content; + + err = cbs_h266_read_pps(ctx, &gbc, pps); + if (err < 0) + return err; + + err = cbs_h266_replace_pps(ctx, unit); + if (err < 0) + return err; + } + break; + + case VVC_PH_NUT: + { + H266RawPH *ph = unit->content; + err = cbs_h266_read_ph(ctx, &gbc, ph); + if (err < 0) + return err; + err = cbs_h266_replace_ph(ctx, unit); + if (err < 0) + return err; + } + break; + + case VVC_TRAIL_NUT: + case VVC_STSA_NUT: + case VVC_RADL_NUT: + case VVC_RASL_NUT: + case VVC_IDR_W_RADL: + case VVC_IDR_N_LP: + case VVC_CRA_NUT: + case VVC_GDR_NUT: + { + H266RawSlice *slice = unit->content; + int pos, len; + + err = cbs_h266_read_slice_header(ctx, &gbc, &slice->header); + if (err < 0) + return err; + + if (!cbs_h2645_read_more_rbsp_data(&gbc)) + return AVERROR_INVALIDDATA; + + pos = get_bits_count(&gbc); + len = unit->data_size; + + slice->data_size = len - pos / 8; + slice->data_ref = av_buffer_ref(unit->data_ref); + if (!slice->data_ref) + return AVERROR(ENOMEM); + slice->data = unit->data + pos / 8; + slice->data_bit_start = pos % 8; + } + break; + + case VVC_AUD_NUT: + { + err = cbs_h266_read_aud(ctx, &gbc, unit->content); + if (err < 0) + return err; + } + break; + + case VVC_PREFIX_SEI_NUT: + case VVC_SUFFIX_SEI_NUT: + { + err = cbs_h266_read_sei(ctx, &gbc, unit->content, + unit->type == VVC_PREFIX_SEI_NUT); + + if (err < 0) + return err; + } + break; + + default: + return AVERROR(ENOSYS); + } + return 0; +} + static int cbs_h2645_write_slice_data(CodedBitstreamContext *ctx, PutBitContext *pbc, const uint8_t *data, size_t data_size, int data_bit_start) @@ -1338,11 +1585,127 @@ static int cbs_h265_discarded_nal_unit(CodedBitstreamContext *ctx, return 0; } +static int cbs_h266_write_nal_unit(CodedBitstreamContext *ctx, + CodedBitstreamUnit *unit, + PutBitContext *pbc) +{ + int err; + + switch (unit->type) { + case VVC_VPS_NUT: + { + H266RawVPS *vps = unit->content; + + err = cbs_h266_write_vps(ctx, pbc, vps); + if (err < 0) + return err; + + err = cbs_h266_replace_vps(ctx, unit); + if (err < 0) + return err; + } + break; + case VVC_SPS_NUT: + { + H266RawSPS *sps = unit->content; + + err = cbs_h266_write_sps(ctx, pbc, sps); + if (err < 0) + return err; + + err = cbs_h266_replace_sps(ctx, unit); + if (err < 0) + return err; + } + break; + + case VVC_PPS_NUT: + { + H266RawPPS *pps = unit->content; + + err = cbs_h266_write_pps(ctx, pbc, pps); + if (err < 0) + return err; + + err = cbs_h266_replace_pps(ctx, unit); + if (err < 0) + return err; + } + break; + + case VVC_PH_NUT: + { + H266RawPH *ph = unit->content; + err = cbs_h266_write_ph(ctx, pbc, ph); + if (err < 0) + return err; + + err = cbs_h266_replace_ph(ctx, unit); + if (err < 0) + return err; + } + break; + + case VVC_TRAIL_NUT: + case VVC_STSA_NUT: + case VVC_RADL_NUT: + case VVC_RASL_NUT: + case VVC_IDR_W_RADL: + case VVC_IDR_N_LP: + case VVC_CRA_NUT: + case VVC_GDR_NUT: + { + H266RawSlice *slice = unit->content; + + err = cbs_h266_write_slice_header(ctx, pbc, &slice->header); + if (err < 0) + return err; + + if (slice->data) { + err = cbs_h2645_write_slice_data(ctx, pbc, slice->data, + slice->data_size, + slice->data_bit_start); + if (err < 0) + return err; + } else { + // No slice data - that was just the header. + } + } + break; + + case VVC_AUD_NUT: + { + err = cbs_h266_write_aud(ctx, pbc, unit->content); + if (err < 0) + return err; + } + break; + + case VVC_PREFIX_SEI_NUT: + case VVC_SUFFIX_SEI_NUT: + { + err = cbs_h266_write_sei(ctx, pbc, unit->content, + unit->type == VVC_PREFIX_SEI_NUT); + + if (err < 0) + return err; + } + break; + + default: + av_log(ctx->log_ctx, AV_LOG_ERROR, "Write unimplemented for " + "NAL unit type %"PRIu32".\n", unit->type); + return AVERROR_PATCHWELCOME; + } + + return 0; +} + static int cbs_h2645_unit_requires_zero_byte(enum AVCodecID codec_id, CodedBitstreamUnitType type, int nal_unit_index) { - // Section B.1.2 in H.264, section B.2.2 in H.265. + // Section B.1.2 in H.264, section B.2.2 in H.265, H.266. if (nal_unit_index == 0) { // Assume that this is the first NAL unit in an access unit. return 1; @@ -1351,6 +1714,8 @@ static int cbs_h2645_unit_requires_zero_byte(enum AVCodecID codec_id, return type == H264_NAL_SPS || type == H264_NAL_PPS; if (codec_id == AV_CODEC_ID_HEVC) return type == HEVC_NAL_VPS || type == HEVC_NAL_SPS || type == HEVC_NAL_PPS; + if (codec_id == AV_CODEC_ID_VVC) + return type >= VVC_OPI_NUT && type <= VVC_SUFFIX_APS_NUT; return 0; } @@ -1502,6 +1867,35 @@ static void cbs_h265_close(CodedBitstreamContext *ctx) av_buffer_unref(&h265->pps_ref[i]); } +static void cbs_h266_flush(CodedBitstreamContext *ctx) +{ + CodedBitstreamH266Context *h266 = ctx->priv_data; + + for (int i = 0; i < FF_ARRAY_ELEMS(h266->vps); i++) { + av_buffer_unref(&h266->vps_ref[i]); + h266->vps[i] = NULL; + } + + for (int i = 0; i < FF_ARRAY_ELEMS(h266->sps); i++) { + av_buffer_unref(&h266->sps_ref[i]); + h266->sps[i] = NULL; + } + for (int i = 0; i < FF_ARRAY_ELEMS(h266->pps); i++) { + av_buffer_unref(&h266->pps_ref[i]); + h266->pps[i] = NULL; + } + av_buffer_unref(&h266->priv.ph_ref); + h266->priv.ph = NULL; +} + +static void cbs_h266_close(CodedBitstreamContext *ctx) +{ + CodedBitstreamH266Context *h266 = ctx->priv_data; + + cbs_h266_flush(ctx); + ff_h2645_packet_uninit(&h266->common.read_packet); + } + static void cbs_h264_free_sei(void *opaque, uint8_t *content) { H264RawSEI *sei = (H264RawSEI*)content; @@ -1556,6 +1950,33 @@ static const CodedBitstreamUnitTypeDescriptor cbs_h265_unit_types[] = { CBS_UNIT_TYPE_END_OF_LIST }; +static void cbs_h266_free_sei(void *opaque, uint8_t *content) +{ + H266RawSEI *sei = (H266RawSEI*)content; + ff_cbs_sei_free_message_list(&sei->message_list); + av_free(content); +} + +static const CodedBitstreamUnitTypeDescriptor cbs_h266_unit_types[] = { + CBS_UNIT_TYPE_INTERNAL_REF(VVC_VPS_NUT, H266RawVPS, extension_data.data), + CBS_UNIT_TYPE_INTERNAL_REF(VVC_SPS_NUT, H266RawSPS, extension_data.data), + CBS_UNIT_TYPE_INTERNAL_REF(VVC_PPS_NUT, H266RawPPS, extension_data.data), + + CBS_UNIT_TYPE_POD(VVC_PH_NUT , H266RawPH), + CBS_UNIT_TYPE_POD(VVC_AUD_NUT, H266RawAUD), + + CBS_UNIT_RANGE_INTERNAL_REF(VVC_TRAIL_NUT, VVC_RASL_NUT, + H266RawSlice, data), + + CBS_UNIT_RANGE_INTERNAL_REF(VVC_IDR_W_RADL, VVC_GDR_NUT, + H266RawSlice, data), + + CBS_UNIT_TYPES_COMPLEX((VVC_PREFIX_SEI_NUT, VVC_SUFFIX_SEI_NUT), + H266RawSEI, cbs_h266_free_sei), + + CBS_UNIT_TYPE_END_OF_LIST +}; + const CodedBitstreamType ff_cbs_type_h264 = { .codec_id = AV_CODEC_ID_H264, @@ -1590,6 +2011,22 @@ const CodedBitstreamType ff_cbs_type_h265 = { .close = &cbs_h265_close, }; +const CodedBitstreamType ff_cbs_type_h266 = { + .codec_id = AV_CODEC_ID_VVC, + + .priv_data_size = sizeof(CodedBitstreamH266Context), + + .unit_types = cbs_h266_unit_types, + + .split_fragment = &cbs_h2645_split_fragment, + .read_unit = &cbs_h266_read_nal_unit, + .write_unit = &cbs_h266_write_nal_unit, + .assemble_fragment = &cbs_h2645_assemble_fragment, + + .flush = &cbs_h266_flush, + .close = &cbs_h266_close, +}; + static const SEIMessageTypeDescriptor cbs_sei_common_types[] = { { SEI_TYPE_FILLER_PAYLOAD, @@ -1740,6 +2177,16 @@ static const SEIMessageTypeDescriptor cbs_sei_h265_types[] = { SEI_MESSAGE_TYPE_END }; +static const SEIMessageTypeDescriptor cbs_sei_h266_types[] = { + { + SEI_TYPE_DECODED_PICTURE_HASH, + 0, 1, + sizeof(H266RawSEIDecodedPictureHash), + SEI_MESSAGE_RW(h266, sei_decoded_picture_hash), + }, + SEI_MESSAGE_TYPE_END +}; + const SEIMessageTypeDescriptor *ff_cbs_sei_find_type(CodedBitstreamContext *ctx, int payload_type) { @@ -1758,6 +2205,9 @@ const SEIMessageTypeDescriptor *ff_cbs_sei_find_type(CodedBitstreamContext *ctx, case AV_CODEC_ID_H265: codec_list = cbs_sei_h265_types; break; + case AV_CODEC_ID_H266: + codec_list = cbs_sei_h266_types; + break; default: return NULL; } diff --git a/libavcodec/cbs_h266.h b/libavcodec/cbs_h266.h new file mode 100644 index 00000000000..8548e501c05 --- /dev/null +++ b/libavcodec/cbs_h266.h @@ -0,0 +1,783 @@ +/* + * 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_CBS_H266_H +#define AVCODEC_CBS_H266_H + +#include +#include + +#include "cbs_h2645.h" +#include "cbs_sei.h" +#include "vvc.h" + +typedef struct H266RawNALUnitHeader { + uint8_t nuh_layer_id; + uint8_t nal_unit_type; + uint8_t nuh_temporal_id_plus1; + uint8_t nuh_reserved_zero_bit; +} H266RawNALUnitHeader; + +typedef struct H266GeneralConstraintsInfo { + uint8_t gci_present_flag; + /* general */ + uint8_t gci_intra_only_constraint_flag; + uint8_t gci_all_layers_independent_constraint_flag; + uint8_t gci_one_au_only_constraint_flag; + + /* picture format */ + uint8_t gci_sixteen_minus_max_bitdepth_constraint_idc; + uint8_t gci_three_minus_max_chroma_format_constraint_idc; + + /* NAL unit type related */ + uint8_t gci_no_mixed_nalu_types_in_pic_constraint_flag; + uint8_t gci_no_trail_constraint_flag; + uint8_t gci_no_stsa_constraint_flag; + uint8_t gci_no_rasl_constraint_flag; + uint8_t gci_no_radl_constraint_flag; + uint8_t gci_no_idr_constraint_flag; + uint8_t gci_no_cra_constraint_flag; + uint8_t gci_no_gdr_constraint_flag; + uint8_t gci_no_aps_constraint_flag; + uint8_t gci_no_idr_rpl_constraint_flag; + + /* tile, slice, subpicture partitioning */ + uint8_t gci_one_tile_per_pic_constraint_flag; + uint8_t gci_pic_header_in_slice_header_constraint_flag; + uint8_t gci_one_slice_per_pic_constraint_flag; + uint8_t gci_no_rectangular_slice_constraint_flag; + uint8_t gci_one_slice_per_subpic_constraint_flag; + uint8_t gci_no_subpic_info_constraint_flag; + + /* CTU and block partitioning */ + uint8_t gci_three_minus_max_log2_ctu_size_constraint_idc; + uint8_t gci_no_partition_constraints_override_constraint_flag; + uint8_t gci_no_mtt_constraint_flag; + uint8_t gci_no_qtbtt_dual_tree_intra_constraint_flag; + + /* intra */ + uint8_t gci_no_palette_constraint_flag; + uint8_t gci_no_ibc_constraint_flag; + uint8_t gci_no_isp_constraint_flag; + uint8_t gci_no_mrl_constraint_flag; + uint8_t gci_no_mip_constraint_flag; + uint8_t gci_no_cclm_constraint_flag; + + /* inter */ + uint8_t gci_no_ref_pic_resampling_constraint_flag; + uint8_t gci_no_res_change_in_clvs_constraint_flag;; + uint8_t gci_no_weighted_prediction_constraint_flag; + uint8_t gci_no_ref_wraparound_constraint_flag; + uint8_t gci_no_temporal_mvp_constraint_flag; + uint8_t gci_no_sbtmvp_constraint_flag; + uint8_t gci_no_amvr_constraint_flag; + uint8_t gci_no_bdof_constraint_flag; + uint8_t gci_no_smvd_constraint_flag; + uint8_t gci_no_dmvr_constraint_flag; + uint8_t gci_no_mmvd_constraint_flag; + uint8_t gci_no_affine_motion_constraint_flag; + uint8_t gci_no_prof_constraint_flag; + uint8_t gci_no_bcw_constraint_flag; + uint8_t gci_no_ciip_constraint_flag; + uint8_t gci_no_gpm_constraint_flag; + + /* transform, quantization, residual */ + uint8_t gci_no_luma_transform_size_64_constraint_flag; + uint8_t gci_no_transform_skip_constraint_flag; + uint8_t gci_no_bdpcm_constraint_flag; + uint8_t gci_no_mts_constraint_flag; + uint8_t gci_no_lfnst_constraint_flag; + uint8_t gci_no_joint_cbcr_constraint_flag; + uint8_t gci_no_sbt_constraint_flag; + uint8_t gci_no_act_constraint_flag; + uint8_t gci_no_explicit_scaling_list_constraint_flag; + uint8_t gci_no_dep_quant_constraint_flag; + uint8_t gci_no_sign_data_hiding_constraint_flag; + uint8_t gci_no_cu_qp_delta_constraint_flag; + uint8_t gci_no_chroma_qp_offset_constraint_flag; + + /* loop filter */ + uint8_t gci_no_sao_constraint_flag; + uint8_t gci_no_alf_constraint_flag; + uint8_t gci_no_ccalf_constraint_flag; + uint8_t gci_no_lmcs_constraint_flag; + uint8_t gci_no_ladf_constraint_flag; + uint8_t gci_no_virtual_boundaries_constraint_flag; + uint8_t gci_num_reserved_bits; + uint8_t gci_reserved_zero_bit[255]; +} H266GeneralConstraintsInfo; + +typedef struct H266RawProfileTierLevel { + uint8_t general_profile_idc; + uint8_t general_tier_flag; + uint8_t general_level_idc; + uint8_t ptl_frame_only_constraint_flag; + uint8_t ptl_multilayer_enabled_flag; + H266GeneralConstraintsInfo general_constraints_info; + uint8_t ptl_sublayer_level_present_flag[VVC_MAX_SUBLAYERS - 1]; + uint8_t sublayer_level_idc[VVC_MAX_SUBLAYERS - 1]; + uint8_t ptl_num_sub_profiles; + uint32_t general_sub_profile_idc[VVC_MAX_SUB_PROFILES]; + + uint8_t ptl_reserved_zero_bit; +} H266RawProfileTierLevel; + +typedef struct H266RawExtensionData { + uint8_t *data; + AVBufferRef *data_ref; + size_t bit_length; +} H266RawExtensionData; + +typedef struct H266DpbParameters { + uint8_t dpb_max_dec_pic_buffering_minus1[VVC_MAX_SUBLAYERS]; + uint8_t dpb_max_num_reorder_pics[VVC_MAX_SUBLAYERS]; + uint8_t dpb_max_latency_increase_plus1[VVC_MAX_SUBLAYERS]; +} H266DpbParameters; + +typedef struct H266RefPicListStruct { + uint8_t num_ref_entries; + uint8_t ltrp_in_header_flag; + uint8_t inter_layer_ref_pic_flag[VVC_MAX_REF_ENTRIES]; + uint8_t st_ref_pic_flag[VVC_MAX_REF_ENTRIES]; + uint8_t abs_delta_poc_st[VVC_MAX_REF_ENTRIES]; + uint8_t strp_entry_sign_flag[VVC_MAX_REF_ENTRIES]; + uint8_t rpls_poc_lsb_lt[VVC_MAX_REF_ENTRIES]; + uint8_t ilrp_idx[VVC_MAX_REF_ENTRIES]; +} H266RefPicListStruct; + +typedef struct H266RefPicLists { + uint8_t rpl_sps_flag[2]; + uint8_t rpl_idx[2]; + H266RefPicListStruct rpl_ref_list[2]; + uint16_t poc_lsb_lt[2][VVC_MAX_REF_ENTRIES]; + uint8_t delta_poc_msb_cycle_present_flag[2][VVC_MAX_REF_ENTRIES]; + uint16_t delta_poc_msb_cycle_lt[2][VVC_MAX_REF_ENTRIES]; +} H266RefPicLists; + +typedef struct H266RawGeneralTimingHrdParameters { + uint32_t num_units_in_tick; + uint32_t time_scale; + uint8_t general_nal_hrd_params_present_flag; + uint8_t general_vcl_hrd_params_present_flag; + uint8_t general_same_pic_timing_in_all_ols_flag; + uint8_t general_du_hrd_params_present_flag; + uint8_t tick_divisor_minus2; + uint8_t bit_rate_scale; + uint8_t cpb_size_scale; + uint8_t cpb_size_du_scale; + uint8_t hrd_cpb_cnt_minus1; +} H266RawGeneralTimingHrdParameters; + +typedef struct H266RawSubLayerHRDParameters { + uint32_t bit_rate_value_minus1[VVC_MAX_SUBLAYERS][VVC_MAX_CPB_CNT]; + uint32_t cpb_size_value_minus1[VVC_MAX_SUBLAYERS][VVC_MAX_CPB_CNT]; + uint32_t cpb_size_du_value_minus1[VVC_MAX_SUBLAYERS][VVC_MAX_CPB_CNT]; + uint32_t bit_rate_du_value_minus1[VVC_MAX_SUBLAYERS][VVC_MAX_CPB_CNT]; + uint8_t cbr_flag[VVC_MAX_SUBLAYERS][VVC_MAX_CPB_CNT]; +} H266RawSubLayerHRDParameters; + +typedef struct H266RawOlsTimingHrdParameters { + uint8_t fixed_pic_rate_general_flag[VVC_MAX_SUBLAYERS]; + uint8_t fixed_pic_rate_within_cvs_flag[VVC_MAX_SUBLAYERS]; + uint16_t elemental_duration_in_tc_minus1[VVC_MAX_SUBLAYERS]; + uint8_t low_delay_hrd_flag[VVC_MAX_SUBLAYERS]; + H266RawSubLayerHRDParameters nal_sub_layer_hrd_parameters; + H266RawSubLayerHRDParameters vcl_sub_layer_hrd_parameters; +} H266RawOlsTimingHrdParameters; + +typedef struct H266RawVUI { + uint8_t vui_progressive_source_flag; + uint8_t vui_interlaced_source_flag; + uint8_t vui_non_packed_constraint_flag; + uint8_t vui_non_projected_constraint_flag; + + uint8_t vui_aspect_ratio_info_present_flag; + uint8_t vui_aspect_ratio_constant_flag; + uint8_t vui_aspect_ratio_idc; + + uint16_t vui_sar_width; + uint16_t vui_sar_height;; + + uint8_t vui_overscan_info_present_flag; + uint8_t vui_overscan_appropriate_flag; + + uint8_t vui_colour_description_present_flag; + uint8_t vui_colour_primaries; + + uint8_t vui_transfer_characteristics; + uint8_t vui_matrix_coeffs; + uint8_t vui_full_range_flag; + + uint8_t vui_chroma_loc_info_present_flag; + uint8_t vui_chroma_sample_loc_type_frame; + uint8_t vui_chroma_sample_loc_type_top_field; + uint8_t vui_chroma_sample_loc_type_bottom_field; + H266RawExtensionData extension_data; +} H266RawVUI; + +typedef struct H266RawVPS { + H266RawNALUnitHeader nal_unit_header; + + uint8_t vps_video_parameter_set_id; + uint8_t vps_max_layers_minus1; + uint8_t vps_max_sublayers_minus1; + uint8_t vps_default_ptl_dpb_hrd_max_tid_flag; + uint8_t vps_all_independent_layers_flag; + uint8_t vps_layer_id[VVC_MAX_LAYERS]; + uint8_t vps_independent_layer_flag[VVC_MAX_LAYERS]; + uint8_t vps_max_tid_ref_present_flag[VVC_MAX_LAYERS]; + uint8_t vps_direct_ref_layer_flag[VVC_MAX_LAYERS][VVC_MAX_LAYERS - 1]; + uint8_t vps_max_tid_il_ref_pics_plus1[VVC_MAX_LAYERS][VVC_MAX_LAYERS - 1]; + uint8_t vps_each_layer_is_an_ols_flag; + uint8_t vps_ols_mode_idc; + uint8_t vps_num_output_layer_sets_minus2; + uint8_t vps_ols_output_layer_flag[VVC_MAX_TOTAL_NUM_OLSS][VVC_MAX_LAYERS]; + + uint8_t vps_num_ptls_minus1; + uint8_t vps_pt_present_flag[VVC_MAX_PTLS]; + uint8_t vps_ptl_max_tid[VVC_MAX_PTLS]; + H266RawProfileTierLevel vps_profile_tier_level[VVC_MAX_PTLS]; + uint8_t vps_ols_ptl_idx[VVC_MAX_TOTAL_NUM_OLSS]; + + uint16_t vps_num_dpb_params_minus1; + uint8_t vps_sublayer_dpb_params_present_flag; + uint8_t vps_dpb_max_tid[VVC_MAX_TOTAL_NUM_OLSS]; + H266DpbParameters vps_dpb_params[VVC_MAX_TOTAL_NUM_OLSS]; + uint16_t vps_ols_dpb_pic_width[VVC_MAX_TOTAL_NUM_OLSS]; + uint16_t vps_ols_dpb_pic_height[VVC_MAX_TOTAL_NUM_OLSS]; + uint8_t vps_ols_dpb_chroma_format[VVC_MAX_TOTAL_NUM_OLSS]; + uint8_t vps_ols_dpb_bitdepth_minus8[VVC_MAX_TOTAL_NUM_OLSS]; + uint16_t vps_ols_dpb_params_idx[VVC_MAX_TOTAL_NUM_OLSS]; + + uint8_t vps_timing_hrd_params_present_flag; + H266RawGeneralTimingHrdParameters vps_general_timing_hrd_parameters; + uint8_t vps_sublayer_cpb_params_present_flag; + uint16_t vps_num_ols_timing_hrd_params_minus1; + uint8_t vps_hrd_max_tid[VVC_MAX_TOTAL_NUM_OLSS]; + H266RawOlsTimingHrdParameters vps_ols_timing_hrd_parameters; + uint8_t vps_ols_timing_hrd_idx[VVC_MAX_TOTAL_NUM_OLSS]; + + uint8_t vps_extension_flag; + H266RawExtensionData extension_data; +} H266RawVPS; + +typedef struct H266RawSPS { + H266RawNALUnitHeader nal_unit_header; + + uint8_t sps_seq_parameter_set_id; + uint8_t sps_video_parameter_set_id; + uint8_t sps_max_sublayers_minus1; + uint8_t sps_chroma_format_idc; + uint8_t sps_log2_ctu_size_minus5; + uint8_t sps_ptl_dpb_hrd_params_present_flag; + H266RawProfileTierLevel profile_tier_level; + uint8_t sps_gdr_enabled_flag; + uint8_t sps_ref_pic_resampling_enabled_flag; + uint8_t sps_res_change_in_clvs_allowed_flag; + + uint16_t sps_pic_width_max_in_luma_samples; + uint16_t sps_pic_height_max_in_luma_samples; + + uint8_t sps_conformance_window_flag; + uint16_t sps_conf_win_left_offset; + uint16_t sps_conf_win_right_offset; + uint16_t sps_conf_win_top_offset; + uint16_t sps_conf_win_bottom_offset; + + uint8_t sps_subpic_info_present_flag; + uint16_t sps_num_subpics_minus1; + uint8_t sps_independent_subpics_flag; + uint8_t sps_subpic_same_size_flag; + uint16_t sps_subpic_ctu_top_left_x[VVC_MAX_SLICES]; + uint16_t sps_subpic_ctu_top_left_y[VVC_MAX_SLICES]; + uint16_t sps_subpic_width_minus1[VVC_MAX_SLICES]; + uint16_t sps_subpic_height_minus1[VVC_MAX_SLICES]; + uint8_t sps_subpic_treated_as_pic_flag[VVC_MAX_SLICES]; + uint8_t sps_loop_filter_across_subpic_enabled_flag[VVC_MAX_SLICES]; + uint8_t sps_subpic_id_len_minus1; + uint8_t sps_subpic_id_mapping_explicitly_signalled_flag; + uint8_t sps_subpic_id_mapping_present_flag; + uint32_t sps_subpic_id[VVC_MAX_SLICES]; + + + uint8_t sps_bitdepth_minus8; + uint8_t sps_entropy_coding_sync_enabled_flag; + uint8_t sps_entry_point_offsets_present_flag; + + uint8_t sps_log2_max_pic_order_cnt_lsb_minus4; + uint8_t sps_poc_msb_cycle_flag; + uint8_t sps_poc_msb_cycle_len_minus1; + + uint8_t sps_num_extra_ph_bytes; + uint8_t sps_extra_ph_bit_present_flag[16]; + + uint8_t sps_num_extra_sh_bytes; + uint8_t sps_extra_sh_bit_present_flag[16]; + + uint8_t sps_sublayer_dpb_params_flag; + H266DpbParameters sps_dpb_params; + + uint8_t sps_log2_min_luma_coding_block_size_minus2; + uint8_t sps_partition_constraints_override_enabled_flag; + uint8_t sps_log2_diff_min_qt_min_cb_intra_slice_luma; + uint8_t sps_max_mtt_hierarchy_depth_intra_slice_luma; + uint8_t sps_log2_diff_max_bt_min_qt_intra_slice_luma; + uint8_t sps_log2_diff_max_tt_min_qt_intra_slice_luma; + + uint8_t sps_qtbtt_dual_tree_intra_flag; + uint8_t sps_log2_diff_min_qt_min_cb_intra_slice_chroma; + uint8_t sps_max_mtt_hierarchy_depth_intra_slice_chroma; + uint8_t sps_log2_diff_max_bt_min_qt_intra_slice_chroma; + uint8_t sps_log2_diff_max_tt_min_qt_intra_slice_chroma; + + uint8_t sps_log2_diff_min_qt_min_cb_inter_slice; + uint8_t sps_max_mtt_hierarchy_depth_inter_slice; + uint8_t sps_log2_diff_max_bt_min_qt_inter_slice; + uint8_t sps_log2_diff_max_tt_min_qt_inter_slice; + + uint8_t sps_max_luma_transform_size_64_flag; + + uint8_t sps_transform_skip_enabled_flag; + uint8_t sps_log2_transform_skip_max_size_minus2; + uint8_t sps_bdpcm_enabled_flag; + + uint8_t sps_mts_enabled_flag; + uint8_t sps_explicit_mts_intra_enabled_flag; + uint8_t sps_explicit_mts_inter_enabled_flag; + + uint8_t sps_lfnst_enabled_flag; + + uint8_t sps_joint_cbcr_enabled_flag; + uint8_t sps_same_qp_table_for_chroma_flag; + + int8_t sps_qp_table_start_minus26[VVC_MAX_SAMPLE_ARRAYS]; + uint8_t sps_num_points_in_qp_table_minus1[VVC_MAX_SAMPLE_ARRAYS]; + uint8_t sps_delta_qp_in_val_minus1[VVC_MAX_SAMPLE_ARRAYS][VVC_MAX_POINTS_IN_QP_TABLE]; + uint8_t sps_delta_qp_diff_val[VVC_MAX_SAMPLE_ARRAYS][VVC_MAX_POINTS_IN_QP_TABLE]; + + uint8_t sps_sao_enabled_flag; + uint8_t sps_alf_enabled_flag; + uint8_t sps_ccalf_enabled_flag; + uint8_t sps_lmcs_enabled_flag; + uint8_t sps_weighted_pred_flag; + uint8_t sps_weighted_bipred_flag; + uint8_t sps_long_term_ref_pics_flag; + uint8_t sps_inter_layer_prediction_enabled_flag; + uint8_t sps_idr_rpl_present_flag; + uint8_t sps_rpl1_same_as_rpl0_flag; + + uint8_t sps_num_ref_pic_lists[2]; + H266RefPicListStruct sps_ref_pic_list_struct[2][VVC_MAX_REF_PIC_LISTS]; + + uint8_t sps_ref_wraparound_enabled_flag; + uint8_t sps_temporal_mvp_enabled_flag; + uint8_t sps_sbtmvp_enabled_flag; + uint8_t sps_amvr_enabled_flag; + uint8_t sps_bdof_enabled_flag; + uint8_t sps_bdof_control_present_in_ph_flag; + uint8_t sps_smvd_enabled_flag; + uint8_t sps_dmvr_enabled_flag; + uint8_t sps_dmvr_control_present_in_ph_flag; + uint8_t sps_mmvd_enabled_flag; + uint8_t sps_mmvd_fullpel_only_enabled_flag; + uint8_t sps_six_minus_max_num_merge_cand; + uint8_t sps_sbt_enabled_flag; + uint8_t sps_affine_enabled_flag; + uint8_t sps_five_minus_max_num_subblock_merge_cand; + uint8_t sps_6param_affine_enabled_flag; + uint8_t sps_affine_amvr_enabled_flag; + uint8_t sps_affine_prof_enabled_flag; + uint8_t sps_prof_control_present_in_ph_flag; + uint8_t sps_bcw_enabled_flag; + uint8_t sps_ciip_enabled_flag; + uint8_t sps_gpm_enabled_flag; + uint8_t sps_max_num_merge_cand_minus_max_num_gpm_cand; + uint8_t sps_log2_parallel_merge_level_minus2; + uint8_t sps_isp_enabled_flag; + uint8_t sps_mrl_enabled_flag; + uint8_t sps_mip_enabled_flag; + uint8_t sps_cclm_enabled_flag; + uint8_t sps_chroma_horizontal_collocated_flag; + uint8_t sps_chroma_vertical_collocated_flag; + uint8_t sps_palette_enabled_flag; + uint8_t sps_act_enabled_flag; + uint8_t sps_min_qp_prime_ts; + uint8_t sps_ibc_enabled_flag; + uint8_t sps_six_minus_max_num_ibc_merge_cand; + uint8_t sps_ladf_enabled_flag; + uint8_t sps_num_ladf_intervals_minus2; + int8_t sps_ladf_lowest_interval_qp_offset; + int8_t sps_ladf_qp_offset[4]; + uint16_t sps_ladf_delta_threshold_minus1[4]; + + uint8_t sps_explicit_scaling_list_enabled_flag; + uint8_t sps_scaling_matrix_for_lfnst_disabled_flag; + uint8_t sps_scaling_matrix_for_alternative_colour_space_disabled_flag; + uint8_t sps_scaling_matrix_designated_colour_space_flag; + uint8_t sps_dep_quant_enabled_flag; + uint8_t sps_sign_data_hiding_enabled_flag; + + uint8_t sps_virtual_boundaries_enabled_flag; + uint8_t sps_virtual_boundaries_present_flag; + uint8_t sps_num_ver_virtual_boundaries; + uint16_t sps_virtual_boundary_pos_x_minus1[3]; + uint8_t sps_num_hor_virtual_boundaries; + uint16_t sps_virtual_boundary_pos_y_minus1[3]; + + uint8_t sps_timing_hrd_params_present_flag; + uint8_t sps_sublayer_cpb_params_present_flag; + H266RawGeneralTimingHrdParameters sps_general_timing_hrd_parameters; + H266RawOlsTimingHrdParameters sps_ols_timing_hrd_parameters; + + uint8_t sps_field_seq_flag; + uint8_t sps_vui_parameters_present_flag; + uint16_t sps_vui_payload_size_minus1; + H266RawVUI vui; + + uint8_t sps_extension_flag; + + H266RawExtensionData extension_data; + +} H266RawSPS; + +typedef struct H266RawPPS { + H266RawNALUnitHeader nal_unit_header; + + uint8_t pps_pic_parameter_set_id; + uint8_t pps_seq_parameter_set_id; + uint8_t pps_mixed_nalu_types_in_pic_flag; + uint16_t pps_pic_width_in_luma_samples; + uint16_t pps_pic_height_in_luma_samples; + + uint8_t pps_conformance_window_flag; + uint16_t pps_conf_win_left_offset; + uint16_t pps_conf_win_right_offset; + uint16_t pps_conf_win_top_offset; + uint16_t pps_conf_win_bottom_offset; + + uint8_t pps_scaling_window_explicit_signalling_flag; + int16_t pps_scaling_win_left_offset; + int16_t pps_scaling_win_right_offset; + int16_t pps_scaling_win_top_offset; + int16_t pps_scaling_win_bottom_offset; + + uint8_t pps_output_flag_present_flag; + uint8_t pps_no_pic_partition_flag; + + uint8_t pps_subpic_id_mapping_present_flag; + uint16_t pps_num_subpics_minus1; + uint8_t pps_subpic_id_len_minus1; + uint16_t pps_subpic_id[VVC_MAX_SLICES]; + + uint8_t pps_log2_ctu_size_minus5; + uint8_t pps_num_exp_tile_columns_minus1; + uint8_t pps_num_exp_tile_rows_minus1; + uint16_t pps_tile_column_width_minus1[VVC_MAX_TILE_COLUMNS]; + uint16_t pps_tile_row_height_minus1[VVC_MAX_TILE_ROWS]; + + uint8_t pps_loop_filter_across_tiles_enabled_flag; + uint8_t pps_rect_slice_flag; + uint8_t pps_single_slice_per_subpic_flag; + + uint16_t pps_num_slices_in_pic_minus1; + uint8_t pps_tile_idx_delta_present_flag; + uint16_t pps_slice_width_in_tiles_minus1[VVC_MAX_SLICES]; + uint16_t pps_slice_height_in_tiles_minus1[VVC_MAX_SLICES]; + uint16_t pps_num_exp_slices_in_tile[VVC_MAX_SLICES]; + uint16_t pps_exp_slice_height_in_ctus_minus1[VVC_MAX_SLICES][VVC_MAX_TILE_ROWS]; + int16_t pps_tile_idx_delta_val[VVC_MAX_SLICES]; + + uint8_t pps_loop_filter_across_slices_enabled_flag; + uint8_t pps_cabac_init_present_flag; + uint8_t pps_num_ref_idx_default_active_minus1[2]; + uint8_t pps_rpl1_idx_present_flag; + uint8_t pps_weighted_pred_flag; + uint8_t pps_weighted_bipred_flag; + uint8_t pps_ref_wraparound_enabled_flag; + uint16_t pps_pic_width_minus_wraparound_offset; + int8_t pps_init_qp_minus26; + uint8_t pps_cu_qp_delta_enabled_flag; + uint8_t pps_chroma_tool_offsets_present_flag; + int8_t pps_cb_qp_offset; + int8_t pps_cr_qp_offset; + uint8_t pps_joint_cbcr_qp_offset_present_flag; + int8_t pps_joint_cbcr_qp_offset_value; + uint8_t pps_slice_chroma_qp_offsets_present_flag; + uint8_t pps_cu_chroma_qp_offset_list_enabled_flag; + uint8_t pps_chroma_qp_offset_list_len_minus1; + uint8_t pps_cb_qp_offset_list[6]; + uint8_t pps_cr_qp_offset_list[6]; + uint8_t pps_joint_cbcr_qp_offset_list[6]; + uint8_t pps_deblocking_filter_control_present_flag; + uint8_t pps_deblocking_filter_override_enabled_flag; + uint8_t pps_deblocking_filter_disabled_flag; + uint8_t pps_dbf_info_in_ph_flag; + + int8_t pps_luma_beta_offset_div2; + int8_t pps_luma_tc_offset_div2; + int8_t pps_cb_beta_offset_div2; + int8_t pps_cb_tc_offset_div2; + int8_t pps_cr_beta_offset_div2; + int8_t pps_cr_tc_offset_div2; + + uint8_t pps_rpl_info_in_ph_flag; + uint8_t pps_sao_info_in_ph_flag; + uint8_t pps_alf_info_in_ph_flag; + uint8_t pps_wp_info_in_ph_flag; + uint8_t pps_qp_delta_info_in_ph_flag; + + uint8_t pps_picture_header_extension_present_flag; + uint8_t pps_slice_header_extension_present_flag; + uint8_t pps_extension_flag; + H266RawExtensionData extension_data; + + //calculated value; + uint16_t num_tile_columns; + uint16_t num_tile_rows; + uint16_t num_tiles_in_pic; + uint16_t slice_height_in_ctus[VVC_MAX_SLICES]; + uint16_t num_slices_in_subpic[VVC_MAX_SLICES]; +} H266RawPPS; + +typedef struct H266RawAUD { + H266RawNALUnitHeader nal_unit_header; + uint8_t aud_irap_or_gdr_flag; + uint8_t aud_pic_type; +} H266RawAUD; + +typedef struct H266RawPredWeightTable { + uint8_t luma_log2_weight_denom; + int8_t delta_chroma_log2_weight_denom; + + uint8_t num_l0_weights; + uint8_t luma_weight_l0_flag[15]; + uint8_t chroma_weight_l0_flag[15]; + int8_t delta_luma_weight_l0[15]; + int8_t luma_offset_l0[15]; + int8_t delta_chroma_weight_l0[15][2]; + int16_t delta_chroma_offset_l0[15][2]; + + uint8_t num_l1_weights; + uint8_t luma_weight_l1_flag[15]; + uint8_t chroma_weight_l1_flag[15]; + int8_t delta_luma_weight_l1[15]; + int8_t luma_offset_l1[15]; + int8_t delta_chroma_weight_l1[15][2]; + int16_t delta_chroma_offset_l1[15][2]; +} H266RawPredWeightTable; + +typedef struct H266RawPH { + H266RawNALUnitHeader nal_unit_header; + uint8_t ph_gdr_or_irap_pic_flag; + uint8_t ph_non_ref_pic_flag; + uint8_t ph_gdr_pic_flag; + uint8_t ph_inter_slice_allowed_flag; + uint8_t ph_intra_slice_allowed_flag; + uint8_t ph_pic_parameter_set_id; + uint16_t ph_pic_order_cnt_lsb; + uint8_t ph_recovery_poc_cnt; + uint8_t ph_extra_bit[16]; + uint8_t ph_poc_msb_cycle_present_flag; + uint8_t ph_poc_msb_cycle_val; + + uint8_t ph_alf_enabled_flag; + uint8_t ph_num_alf_aps_ids_luma; + uint8_t ph_alf_aps_id_luma[8]; + uint8_t ph_alf_cb_enabled_flag; + uint8_t ph_alf_cr_enabled_flag; + uint8_t ph_alf_aps_id_chroma; + uint8_t ph_alf_cc_cb_enabled_flag; + uint8_t ph_alf_cc_cb_aps_id; + uint8_t ph_alf_cc_cr_enabled_flag; + uint8_t ph_alf_cc_cr_aps_id; + + uint8_t ph_lmcs_enabled_flag; + uint8_t ph_lmcs_aps_id; + uint8_t ph_chroma_residual_scale_flag; + uint8_t ph_explicit_scaling_list_enabled_flag; + uint8_t ph_scaling_list_aps_id; + + uint8_t ph_virtual_boundaries_present_flag; + uint8_t ph_num_ver_virtual_boundaries; + uint16_t ph_virtual_boundary_pos_x_minus1[3]; + uint8_t ph_num_hor_virtual_boundaries; + uint16_t ph_virtual_boundary_pos_y_minus1[3]; + + uint8_t ph_pic_output_flag; + H266RefPicLists ph_ref_pic_lists; + + uint8_t ph_partition_constraints_override_flag; + + uint8_t ph_log2_diff_min_qt_min_cb_intra_slice_luma; + uint8_t ph_max_mtt_hierarchy_depth_intra_slice_luma; + uint8_t ph_log2_diff_max_bt_min_qt_intra_slice_luma; + uint8_t ph_log2_diff_max_tt_min_qt_intra_slice_luma; + uint8_t ph_log2_diff_min_qt_min_cb_intra_slice_chroma; + + uint8_t ph_max_mtt_hierarchy_depth_intra_slice_chroma; + uint8_t ph_log2_diff_max_bt_min_qt_intra_slice_chroma; + uint8_t ph_log2_diff_max_tt_min_qt_intra_slice_chroma; + + uint8_t ph_cu_qp_delta_subdiv_intra_slice; + uint8_t ph_cu_chroma_qp_offset_subdiv_intra_slice; + + uint8_t ph_log2_diff_min_qt_min_cb_inter_slice; + uint8_t ph_max_mtt_hierarchy_depth_inter_slice; + uint8_t ph_log2_diff_max_bt_min_qt_inter_slice; + uint8_t ph_log2_diff_max_tt_min_qt_inter_slice; + uint8_t ph_cu_qp_delta_subdiv_inter_slice; + uint8_t ph_cu_chroma_qp_offset_subdiv_inter_slice; + + uint8_t ph_temporal_mvp_enabled_flag; + uint8_t ph_collocated_from_l0_flag; + uint8_t ph_collocated_ref_idx; + uint8_t ph_mmvd_fullpel_only_flag; + uint8_t ph_mvd_l1_zero_flag; + uint8_t ph_bdof_disabled_flag; + uint8_t ph_dmvr_disabled_flag; + uint8_t ph_prof_disabled_flag; + + H266RawPredWeightTable ph_pred_weight_table; + + int8_t ph_qp_delta; + uint8_t ph_joint_cbcr_sign_flag; + uint8_t ph_sao_luma_enabled_flag; + uint8_t ph_sao_chroma_enabled_flag; + + uint8_t ph_deblocking_params_present_flag; + uint8_t ph_deblocking_filter_disabled_flag; + int8_t ph_luma_beta_offset_div2; + int8_t ph_luma_tc_offset_div2; + int8_t ph_cb_beta_offset_div2; + int8_t ph_cb_tc_offset_div2; + int8_t ph_cr_beta_offset_div2; + int8_t ph_cr_tc_offset_div2; + + uint8_t ph_extension_length; + uint8_t ph_extension_data_byte[256]; +} H266RawPH; + +typedef struct H266RawSliceHeader { + H266RawNALUnitHeader nal_unit_header; + uint8_t sh_picture_header_in_slice_header_flag; + H266RawPH sh_picture_header; + + uint16_t sh_subpic_id; + uint16_t sh_slice_address; + uint8_t sh_extra_bit[16]; + uint8_t sh_num_tiles_in_slice_minus1; + uint8_t sh_slice_type; + uint8_t sh_no_output_of_prior_pics_flag; + + uint8_t sh_alf_enabled_flag; + uint8_t sh_num_alf_aps_ids_luma; + uint8_t sh_alf_aps_id_luma[8]; + uint8_t sh_alf_cb_enabled_flag; + uint8_t sh_alf_cr_enabled_flag; + uint8_t sh_alf_aps_id_chroma; + uint8_t sh_alf_cc_cb_enabled_flag; + uint8_t sh_alf_cc_cb_aps_id; + uint8_t sh_alf_cc_cr_enabled_flag; + uint8_t sh_alf_cc_cr_aps_id; + + uint8_t sh_lmcs_used_flag; + uint8_t sh_explicit_scaling_list_used_flag; + + H266RefPicLists sh_ref_pic_lists; + + uint8_t sh_num_ref_idx_active_override_flag; + uint8_t sh_num_ref_idx_active_minus1[2]; + uint8_t sh_cabac_init_flag; + uint8_t sh_collocated_from_l0_flag; + uint8_t sh_collocated_ref_idx; + + H266RawPredWeightTable sh_pred_weight_table; + + int8_t sh_qp_delta; + int8_t sh_cb_qp_offset; + int8_t sh_cr_qp_offset; + int8_t sh_joint_cbcr_qp_offset; + uint8_t sh_cu_chroma_qp_offset_enabled_flag; + + uint8_t sh_sao_luma_used_flag; + uint8_t sh_sao_chroma_used_flag; + + uint8_t sh_deblocking_params_present_flag; + uint8_t sh_deblocking_filter_disabled_flag; + int8_t sh_luma_beta_offset_div2; + int8_t sh_luma_tc_offset_div2; + int8_t sh_cb_beta_offset_div2; + int8_t sh_cb_tc_offset_div2; + int8_t sh_cr_beta_offset_div2; + int8_t sh_cr_tc_offset_div2; + uint8_t sh_dep_quant_used_flag; + + uint8_t sh_sign_data_hiding_used_flag; + uint8_t sh_ts_residual_coding_disabled_flag; + uint16_t sh_slice_header_extension_length; + uint8_t sh_slice_header_extension_data_byte[256]; + + uint8_t sh_entry_offset_len_minus1; + uint32_t sh_entry_point_offset_minus1[VVC_MAX_ENTRY_POINTS]; + +} H266RawSliceHeader; + +typedef struct H266RawSlice { + H266RawSliceHeader header; + + uint8_t *data; + AVBufferRef *data_ref; + size_t data_size; + int data_bit_start; +} H266RawSlice; + +typedef struct H266RawSEIDecodedPictureHash { + uint8_t dph_sei_hash_type; + uint8_t dph_sei_single_component_flag; + uint8_t dph_sei_picture_md5[3][16]; + uint16_t dph_sei_picture_crc[3]; + uint32_t dph_sei_picture_checksum[3]; + + uint8_t dph_sei_reserved_zero_7bits; +} H266RawSEIDecodedPictureHash; + +typedef struct H266RawSEI { + H266RawNALUnitHeader nal_unit_header; + SEIRawMessageList message_list; +} H266RawSEI; + +typedef struct CodedBitstreamH266Context { + // Reader/writer context in common with the H.264 implementation. + CodedBitstreamH2645Context common; + + // All currently available parameter sets. These are updated when + // any parameter set NAL unit is read/written with this context. + AVBufferRef *vps_ref[VVC_MAX_VPS_COUNT]; + AVBufferRef *sps_ref[VVC_MAX_SPS_COUNT]; + AVBufferRef *pps_ref[VVC_MAX_PPS_COUNT]; + H266RawVPS *vps[VVC_MAX_SPS_COUNT]; + H266RawSPS *sps[VVC_MAX_SPS_COUNT]; + H266RawPPS *pps[VVC_MAX_PPS_COUNT]; + + struct { + AVBufferRef *ph_ref; + H266RawPH *ph; + } priv; +} CodedBitstreamH266Context; + +#endif /* AVCODEC_CBS_H266_H */ diff --git a/libavcodec/cbs_h266_syntax_template.c b/libavcodec/cbs_h266_syntax_template.c new file mode 100644 index 00000000000..06f9f29e085 --- /dev/null +++ b/libavcodec/cbs_h266_syntax_template.c @@ -0,0 +1,3116 @@ +/* + * 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 + */ + +static int FUNC(rbsp_trailing_bits) (CodedBitstreamContext *ctx, + RWContext *rw) +{ + int err; + + fixed(1, rbsp_stop_one_bit, 1); + while (byte_alignment(rw) != 0) + fixed(1, rbsp_alignment_zero_bit, 0); + return 0; +} + +static int FUNC(nal_unit_header) (CodedBitstreamContext *ctx, RWContext *rw, + H266RawNALUnitHeader *current, + int expected_nal_unit_type) +{ + int err; + + fixed(1, forbidden_zero_bit, 0); + flag(nuh_reserved_zero_bit); + + u(6, nuh_layer_id, 0, 55); + + if (expected_nal_unit_type >= 0) + u(5, nal_unit_type, expected_nal_unit_type, expected_nal_unit_type); + else + ub(5, nal_unit_type); + + u(3, nuh_temporal_id_plus1, 1, 7); + return 0; +} + +static int FUNC(byte_alignment) (CodedBitstreamContext *ctx, RWContext *rw) +{ + int err; + + fixed(1, byte_alignment_bit_equal_to_one, 1); + while (byte_alignment(rw) != 0) + fixed(1, byte_alignment_bit_equal_to_zero, 0); + return 0; +} + +static int FUNC(general_constraints_info) (CodedBitstreamContext *ctx, + RWContext *rw, + H266GeneralConstraintsInfo *current) +{ + int err, i; + + flag(gci_present_flag); + if (current->gci_present_flag) { + /* general */ + flag(gci_intra_only_constraint_flag); + flag(gci_all_layers_independent_constraint_flag); + flag(gci_one_au_only_constraint_flag); + + /* picture format */ + u(4, gci_sixteen_minus_max_bitdepth_constraint_idc, 0, 8); + ub(2, gci_three_minus_max_chroma_format_constraint_idc); + + /* NAL unit type related */ + flag(gci_no_mixed_nalu_types_in_pic_constraint_flag); + flag(gci_no_trail_constraint_flag); + flag(gci_no_stsa_constraint_flag); + flag(gci_no_rasl_constraint_flag); + flag(gci_no_radl_constraint_flag); + flag(gci_no_idr_constraint_flag); + flag(gci_no_cra_constraint_flag); + flag(gci_no_gdr_constraint_flag); + flag(gci_no_aps_constraint_flag); + flag(gci_no_idr_rpl_constraint_flag); + + /* tile, slice, subpicture partitioning */ + flag(gci_one_tile_per_pic_constraint_flag); + flag(gci_pic_header_in_slice_header_constraint_flag); + flag(gci_one_slice_per_pic_constraint_flag); + flag(gci_no_rectangular_slice_constraint_flag); + flag(gci_one_slice_per_subpic_constraint_flag); + flag(gci_no_subpic_info_constraint_flag); + + /* CTU and block partitioning */ + ub(2, gci_three_minus_max_log2_ctu_size_constraint_idc); + flag(gci_no_partition_constraints_override_constraint_flag); + flag(gci_no_mtt_constraint_flag); + flag(gci_no_qtbtt_dual_tree_intra_constraint_flag); + + /* intra */ + flag(gci_no_palette_constraint_flag); + flag(gci_no_ibc_constraint_flag); + flag(gci_no_isp_constraint_flag); + flag(gci_no_mrl_constraint_flag); + flag(gci_no_mip_constraint_flag); + flag(gci_no_cclm_constraint_flag); + + /* inter */ + flag(gci_no_ref_pic_resampling_constraint_flag); + flag(gci_no_res_change_in_clvs_constraint_flag); + flag(gci_no_weighted_prediction_constraint_flag); + flag(gci_no_ref_wraparound_constraint_flag); + flag(gci_no_temporal_mvp_constraint_flag); + flag(gci_no_sbtmvp_constraint_flag); + flag(gci_no_amvr_constraint_flag); + flag(gci_no_bdof_constraint_flag); + flag(gci_no_smvd_constraint_flag); + flag(gci_no_dmvr_constraint_flag); + flag(gci_no_mmvd_constraint_flag); + flag(gci_no_affine_motion_constraint_flag); + flag(gci_no_prof_constraint_flag); + flag(gci_no_bcw_constraint_flag); + flag(gci_no_ciip_constraint_flag); + flag(gci_no_gpm_constraint_flag); + + /* transform, quantization, residual */ + flag(gci_no_luma_transform_size_64_constraint_flag); + flag(gci_no_transform_skip_constraint_flag); + flag(gci_no_bdpcm_constraint_flag); + flag(gci_no_mts_constraint_flag); + flag(gci_no_lfnst_constraint_flag); + flag(gci_no_joint_cbcr_constraint_flag); + flag(gci_no_sbt_constraint_flag); + flag(gci_no_act_constraint_flag); + flag(gci_no_explicit_scaling_list_constraint_flag); + flag(gci_no_dep_quant_constraint_flag); + flag(gci_no_sign_data_hiding_constraint_flag); + flag(gci_no_cu_qp_delta_constraint_flag); + flag(gci_no_chroma_qp_offset_constraint_flag); + + /* loop filter */ + flag(gci_no_sao_constraint_flag); + flag(gci_no_alf_constraint_flag); + flag(gci_no_ccalf_constraint_flag); + flag(gci_no_lmcs_constraint_flag); + flag(gci_no_ladf_constraint_flag); + flag(gci_no_virtual_boundaries_constraint_flag); + ub(8, gci_num_reserved_bits); + for (i = 0; i < current->gci_num_reserved_bits; i++) { + flags(gci_reserved_zero_bit[i], 1, i); + } + } + while (byte_alignment(rw) != 0) + fixed(1, gci_alignment_zero_bit, 0); + return 0; +} + +static int FUNC(profile_tier_level) (CodedBitstreamContext *ctx, + RWContext *rw, + H266RawProfileTierLevel *current, + int profile_tier_present_flag, + int max_num_sub_layers_minus1) +{ + int err, i; + + if (profile_tier_present_flag) { + ub(7, general_profile_idc); + flag(general_tier_flag); + } + ub(8, general_level_idc); + flag(ptl_frame_only_constraint_flag); + flag(ptl_multilayer_enabled_flag); + if (profile_tier_present_flag) { + CHECK(FUNC(general_constraints_info) (ctx, rw, + ¤t-> + general_constraints_info)); + } + for (i = max_num_sub_layers_minus1 - 1; i >= 0; i--) + flags(ptl_sublayer_level_present_flag[i], 1, i); + while (byte_alignment(rw) != 0) + flag(ptl_reserved_zero_bit); + for (i = max_num_sub_layers_minus1 - 1; i >= 0; i--) + if (current->ptl_sublayer_level_present_flag[i]) + ubs(8, sublayer_level_idc[i], 1, i); + if (profile_tier_present_flag) { + ub(8, ptl_num_sub_profiles); + for (i = 0; i < current->ptl_num_sub_profiles; i++) + ubs(32, general_sub_profile_idc[i], 1, i); + } + return 0; +} + +static int FUNC(vui_parameters_default) (CodedBitstreamContext *ctx, + RWContext *rw, H266RawVUI *current) +{ + //defined in D.8 + infer(vui_progressive_source_flag, 0); + infer(vui_interlaced_source_flag, 0); + + infer(vui_non_packed_constraint_flag, 0); + infer(vui_non_projected_constraint_flag, 0); + + infer(vui_aspect_ratio_constant_flag, 0); + infer(vui_aspect_ratio_idc, 0); + + infer(vui_overscan_info_present_flag, 0); + + infer(vui_colour_primaries, 2); + infer(vui_transfer_characteristics, 2); + infer(vui_matrix_coeffs, 2); + infer(vui_full_range_flag, 0); + + infer(vui_chroma_sample_loc_type_frame, 6); + infer(vui_chroma_sample_loc_type_top_field, 6); + infer(vui_chroma_sample_loc_type_bottom_field, 6); + return 0; +} + +static int FUNC(vui_parameters) (CodedBitstreamContext *ctx, RWContext *rw, + H266RawVUI *current, + uint8_t chroma_format_idc) +{ + int err; + + flag(vui_progressive_source_flag); + flag(vui_interlaced_source_flag); + flag(vui_non_packed_constraint_flag); + flag(vui_non_projected_constraint_flag); + flag(vui_aspect_ratio_info_present_flag); + if (current->vui_aspect_ratio_info_present_flag) { + flag(vui_aspect_ratio_constant_flag); + ub(8, vui_aspect_ratio_idc); + if (current->vui_aspect_ratio_idc == 255) { + ub(16, vui_sar_width); + ub(16, vui_sar_height); + } + } else { + infer(vui_aspect_ratio_constant_flag, 0); + infer(vui_aspect_ratio_idc, 0); + } + flag(vui_overscan_info_present_flag); + if (current->vui_overscan_info_present_flag) + flag(vui_overscan_appropriate_flag); + flag(vui_colour_description_present_flag); + if (current->vui_colour_description_present_flag) { + ub(8, vui_colour_primaries); + av_log(ctx->log_ctx, AV_LOG_DEBUG, "vui_colour_primaries == %d \n", + current->vui_colour_primaries); + ub(8, vui_transfer_characteristics); + av_log(ctx->log_ctx, AV_LOG_DEBUG, + "vui_transfer_characteristics == %d \n", + current->vui_transfer_characteristics); + ub(8, vui_matrix_coeffs); + av_log(ctx->log_ctx, AV_LOG_DEBUG, "vui_matrix_coeffs == %d \n", + current->vui_matrix_coeffs); + flag(vui_full_range_flag); + } else { + infer(vui_colour_primaries, 2); + infer(vui_transfer_characteristics, 2); + infer(vui_matrix_coeffs, 2); + infer(vui_full_range_flag, 0); + } + flag(vui_chroma_loc_info_present_flag); + if (chroma_format_idc != 1 && current->vui_chroma_loc_info_present_flag) { + av_log(ctx->log_ctx, AV_LOG_ERROR, "chroma_format_idc == %d," + "vui_chroma_loc_info_present_flag can't not be true", + chroma_format_idc); + return AVERROR_INVALIDDATA; + } + if (current->vui_chroma_loc_info_present_flag) { + if (current->vui_progressive_source_flag && + !current->vui_interlaced_source_flag) { + ue(vui_chroma_sample_loc_type_frame, 0, 6); + } else { + ue(vui_chroma_sample_loc_type_top_field, 0, 6); + ue(vui_chroma_sample_loc_type_bottom_field, 0, 6); + } + } else { + if (chroma_format_idc == 1) { + infer(vui_chroma_sample_loc_type_frame, 6); + infer(vui_chroma_sample_loc_type_top_field, + current->vui_chroma_sample_loc_type_frame); + infer(vui_chroma_sample_loc_type_bottom_field, + current->vui_chroma_sample_loc_type_frame); + } + } + return 0; +} + +static int FUNC(payload_extension) (CodedBitstreamContext *ctx, RWContext *rw, + H266RawExtensionData *current, + uint32_t payload_size, int cur_pos) +{ + int err; + size_t byte_length, k; + +#ifdef READ + GetBitContext tmp; + int bits_left, payload_zero_bits; + + if (!cbs_h265_payload_extension_present(rw, payload_size, cur_pos)) + return 0; + + bits_left = 8 * payload_size - cur_pos; + tmp = *rw; + if (bits_left > 8) + skip_bits_long(&tmp, bits_left - 8); + payload_zero_bits = get_bits(&tmp, FFMIN(bits_left, 8)); + if (!payload_zero_bits) + return AVERROR_INVALIDDATA; + payload_zero_bits = ff_ctz(payload_zero_bits); + current->bit_length = bits_left - payload_zero_bits - 1; + allocate(current->data, (current->bit_length + 7) / 8); +#endif + + byte_length = (current->bit_length + 7) / 8; + for (k = 0; k < byte_length; k++) { + int length = FFMIN(current->bit_length - k * 8, 8); + xu(length, reserved_payload_extension_data, current->data[k], + 0, MAX_UINT_BITS(length), 0); + } + + return 0; +} + +static int FUNC(vui_payload) (CodedBitstreamContext *ctx, RWContext *rw, + H266RawVUI *current, uint16_t vui_payload_size, + uint8_t chroma_format_idc) +{ + int err; + int start_position, current_position; + + start_position = bit_position(rw); + CHECK(FUNC(vui_parameters) (ctx, rw, current, chroma_format_idc)); + current_position = bit_position(rw) - start_position; + + if (current_position < 8 * vui_payload_size) { + CHECK(FUNC(payload_extension) (ctx, rw, ¤t->extension_data, + vui_payload_size, current_position)); + fixed(1, vui_payload_bit_equal_to_one, 1); + while (byte_alignment(rw) != 0) + fixed(1, vui_payload_bit_equal_to_zero, 0); + } + return 0; +} + +static int FUNC(extension_data) (CodedBitstreamContext *ctx, RWContext *rw, + H266RawExtensionData *current) +{ + int err; + size_t k; +#ifdef READ + GetBitContext start; + uint8_t bit; + start = *rw; + for (k = 0; cbs_h2645_read_more_rbsp_data(rw); k++) + skip_bits(rw, 1); + current->bit_length = k; + if (k > 0) { + *rw = start; + allocate(current->data, (current->bit_length + 7) / 8); + for (k = 0; k < current->bit_length; k++) { + xu(1, extension_data, bit, 0, 1, 0); + current->data[k / 8] |= bit << (7 - k % 8); + } + } +#else + for (k = 0; k < current->bit_length; k++) + xu(1, extension_data, current->data[k / 8] >> (7 - k % 8) & 1, 0, 1, 0); +#endif + return 0; +} + +static int FUNC(dpb_parameters) (CodedBitstreamContext *ctx, RWContext *rw, + H266DpbParameters *current, + uint8_t max_sublayers_minus1, + uint8_t sublayer_info_flag) +{ + int err, i; + for (i = (sublayer_info_flag ? 0 : max_sublayers_minus1); + i <= max_sublayers_minus1; i++) { + ues(dpb_max_dec_pic_buffering_minus1[i], 0, VVC_MAX_DPB_SIZE - 1, 1, i); + ues(dpb_max_num_reorder_pics[i], + 0, current->dpb_max_dec_pic_buffering_minus1[i], 1, i); + ues(dpb_max_latency_increase_plus1[i], 0, UINT32_MAX - 1, 1, i); + } + return 0; +} + +static int FUNC(ref_pic_list_struct) (CodedBitstreamContext *ctx, + RWContext *rw, + H266RefPicListStruct *current, + uint8_t list_idx, uint8_t rpls_idx, + const H266RawSPS *sps) +{ + CodedBitstreamH266Context *h266 = ctx->priv_data; + int err, i, j, general_layer_idx = -1, num_direct_ref_layers = 0; + const H266RawVPS *vps = h266->vps[sps->sps_video_parameter_set_id]; + + if (!vps) { + av_log(ctx->log_ctx, AV_LOG_ERROR, + "VPS id %d not available.\n", sps->sps_video_parameter_set_id); + return AVERROR_INVALIDDATA; + } + //7.4.3.3 (29) + for (i = 0; i <= vps->vps_max_layers_minus1; i++) { + if (sps->nal_unit_header.nuh_layer_id == vps->vps_layer_id[i]) { + general_layer_idx = i; + break; + } + } + if (general_layer_idx < 0) { + av_log(ctx->log_ctx, AV_LOG_ERROR, "vps_layer_id %d not available.\n", + sps->nal_unit_header.nuh_layer_id); + return AVERROR_INVALIDDATA; + } + //7.4.3.3 (28) + for (j = 0; j <= vps->vps_max_layers_minus1; j++) { + if (vps->vps_direct_ref_layer_flag[general_layer_idx][j]) + num_direct_ref_layers++; + } + + ue(num_ref_entries, 0, VVC_MAX_REF_ENTRIES); + if (sps->sps_long_term_ref_pics_flag && + rpls_idx < sps->sps_num_ref_pic_lists[list_idx] && + current->num_ref_entries > 0) + flag(ltrp_in_header_flag); + if (sps->sps_long_term_ref_pics_flag && + rpls_idx == sps->sps_num_ref_pic_lists[list_idx]) + infer(ltrp_in_header_flag, 1); + for (i = 0, j = 0; i < current->num_ref_entries; i++) { + if (sps->sps_inter_layer_prediction_enabled_flag) + flags(inter_layer_ref_pic_flag[i], 1, i); + else + infer(inter_layer_ref_pic_flag[i], 0); + + if (!current->inter_layer_ref_pic_flag[i]) { + if (sps->sps_long_term_ref_pics_flag) + flags(st_ref_pic_flag[i], 1, i); + else + infer(st_ref_pic_flag[i], 1); + if (current->st_ref_pic_flag[i]) { + int abs_delta_poc_st; + ues(abs_delta_poc_st[i], 0, MAX_UINT_BITS(15), 1, i); + if ((sps->sps_weighted_pred_flag || + sps->sps_weighted_bipred_flag) && i != 0) + abs_delta_poc_st = current->abs_delta_poc_st[i]; + else + abs_delta_poc_st = current->abs_delta_poc_st[i] + 1; + if (abs_delta_poc_st > 0) + flags(strp_entry_sign_flag[i], 1, i); + } else { + if (!current->ltrp_in_header_flag) { + uint8_t bits = sps->sps_log2_max_pic_order_cnt_lsb_minus4 + 4; + ubs(bits, rpls_poc_lsb_lt[j], 1, j); + j++; + } + } + } else { + if (num_direct_ref_layers == 0) { + av_log(ctx->log_ctx, AV_LOG_ERROR, + "num_direct_ref_layers needs > 0.\n"); + return AVERROR_INVALIDDATA; + } + ues(ilrp_idx[i], 0, num_direct_ref_layers - 1, 1, i); + } + } + return 0; +} + +static int FUNC(ref_pic_lists) (CodedBitstreamContext *ctx, RWContext *rw, + const H266RawSPS *sps, const H266RawPPS *pps, + H266RefPicLists *current) { + const H266RefPicListStruct * ref_list; + int err, i, j, num_ltrp_entries; + for (i = 0; i < 2; i++) { + if (sps->sps_num_ref_pic_lists[i] > 0 && + (i == 0 || (i == 1 && pps->pps_rpl1_idx_present_flag))) { + flags(rpl_sps_flag[i], 1, i); + } else { + if (sps->sps_num_ref_pic_lists[i] == 0) { + infer(rpl_sps_flag[i], 0); + } else { + if (!pps->pps_rpl1_idx_present_flag && i == 1) + infer(rpl_sps_flag[1], current->rpl_sps_flag[0]); + } + } + if (current->rpl_sps_flag[i]) { + if (sps->sps_num_ref_pic_lists[i] > 1 && + (i == 0 || (i == 1 && pps->pps_rpl1_idx_present_flag))) { + uint8_t bits = av_ceil_log2(sps->sps_num_ref_pic_lists[i]); + us(bits, rpl_idx[i], 0, sps->sps_num_ref_pic_lists[i] - 1, 1, i); + } else if (sps->sps_num_ref_pic_lists[i] == 1) { + infer(rpl_idx[i], 0); + } else if (i == 1 && !pps->pps_rpl1_idx_present_flag) { + infer(rpl_idx[1], current->rpl_idx[0]); + } else { + //how to handle this? or never happpend? + av_log(ctx->log_ctx, AV_LOG_ERROR, + "can't infer the rpl_idx[i]\n"); + return AVERROR_PATCHWELCOME; + } + memcpy(¤t->rpl_ref_list[i], + &sps->sps_ref_pic_list_struct[i][current->rpl_idx[i]], + sizeof(current->rpl_ref_list[i])); + } else { + CHECK(FUNC(ref_pic_list_struct) (ctx, rw, ¤t->rpl_ref_list[i], + i, sps->sps_num_ref_pic_lists[i], + sps)); + } + ref_list = ¤t->rpl_ref_list[i]; + + num_ltrp_entries = 0; + for (int i = 0; i < ref_list->num_ref_entries; i++) { + if (!ref_list->inter_layer_ref_pic_flag[i]) { + if (!ref_list->st_ref_pic_flag[i]) { + num_ltrp_entries++; + } + } + } + + for (j = 0; j < num_ltrp_entries; j++) { + if (ref_list->ltrp_in_header_flag) { + ubs(sps->sps_log2_max_pic_order_cnt_lsb_minus4 + 4, + poc_lsb_lt[i][j], 2, i, j); + } + flags(delta_poc_msb_cycle_present_flag[i][j], 2, i, j); + if (current->delta_poc_msb_cycle_present_flag[i][j]) { + uint32_t max = + 1 << (32 - sps->sps_log2_max_pic_order_cnt_lsb_minus4 - 4); + ues(delta_poc_msb_cycle_lt[i][j], 0, max, 2, i, j); + } + } + } + return 0; +} + +static int FUNC(general_timing_hrd_parameters)(CodedBitstreamContext *ctx, + RWContext *rw, + H266RawGeneralTimingHrdParameters *current) +{ + int err; + ub(32, num_units_in_tick); + u(32, time_scale, 1, MAX_UINT_BITS(32)); + flag(general_nal_hrd_params_present_flag); + flag(general_vcl_hrd_params_present_flag); + + if (current->general_nal_hrd_params_present_flag || + current->general_vcl_hrd_params_present_flag) { + flag(general_same_pic_timing_in_all_ols_flag); + flag(general_du_hrd_params_present_flag); + if (current->general_du_hrd_params_present_flag) + ub(8, tick_divisor_minus2); + ub(4, bit_rate_scale); + ub(4, cpb_size_scale); + if (current->general_du_hrd_params_present_flag) + ub(4, cpb_size_du_scale); + ue(hrd_cpb_cnt_minus1, 0, 31); + } else { + //infer general_same_pic_timing_in_all_ols_flag? + infer(general_du_hrd_params_present_flag, 0); + } + return 0; +} + +static int FUNC(sublayer_hrd_parameters) (CodedBitstreamContext *ctx, + RWContext *rw, + H266RawSubLayerHRDParameters *current, + int sublayer_id, + const H266RawGeneralTimingHrdParameters *general) +{ + int err, i; + for (i = 0; i <= general->hrd_cpb_cnt_minus1; i++) { + ues(bit_rate_value_minus1[sublayer_id][i], 0, UINT32_MAX - 1, 2, + sublayer_id, i); + ues(cpb_size_value_minus1[sublayer_id][i], 0, UINT32_MAX - 1, 2, + sublayer_id, i); + if (general->general_du_hrd_params_present_flag) { + ues(cpb_size_du_value_minus1[sublayer_id][i], + 0, UINT32_MAX - 1, 2, sublayer_id, i); + ues(bit_rate_du_value_minus1[sublayer_id][i], + 0, UINT32_MAX - 1, 2, sublayer_id, i); + } + flags(cbr_flag[sublayer_id][i], 2, sublayer_id, i); + } + return 0; +} + +static int FUNC(ols_timing_hrd_parameters) (CodedBitstreamContext *ctx, + RWContext *rw, H266RawOlsTimingHrdParameters *current, + uint8_t first_sublayer, uint8_t max_sublayers_minus1, + const H266RawGeneralTimingHrdParameters *general) +{ + int err, i; + for (i = first_sublayer; i <= max_sublayers_minus1; i++) { + flags(fixed_pic_rate_general_flag[i], 1, i); + if (!current->fixed_pic_rate_general_flag[i]) + flags(fixed_pic_rate_within_cvs_flag[i], 1, i); + else + infer(fixed_pic_rate_within_cvs_flag[i], 1); + if (current->fixed_pic_rate_within_cvs_flag[i]) { + ues(elemental_duration_in_tc_minus1[i], 0, 2047, 1, i); + infer(low_delay_hrd_flag[i], 0); + } else if ((general->general_nal_hrd_params_present_flag || + general->general_vcl_hrd_params_present_flag) && + general->hrd_cpb_cnt_minus1 == 0) { + flags(low_delay_hrd_flag[i], 1, i); + } else { + infer(low_delay_hrd_flag[i], 0); + } + if (general->general_nal_hrd_params_present_flag) + CHECK(FUNC(sublayer_hrd_parameters) (ctx, rw, + ¤t->nal_sub_layer_hrd_parameters, + i, general)); + if (general->general_vcl_hrd_params_present_flag) + CHECK(FUNC(sublayer_hrd_parameters) (ctx, rw, + ¤t->nal_sub_layer_hrd_parameters, + i, general)); + } + return 0; +} + +static int FUNC(vps) (CodedBitstreamContext *ctx, RWContext *rw, + H266RawVPS *current) +{ + int err, i, j, k; + uint16_t total_num_olss = 0; + uint8_t ols_mode_idc = 0; + uint16_t num_multi_layer_olss = 0; + uint8_t layer_included_in_ols_flag[VVC_MAX_TOTAL_NUM_OLSS][VVC_MAX_LAYERS]; + uint8_t num_ref_layers[VVC_MAX_LAYERS]; + uint8_t reference_layer_idx[VVC_MAX_LAYERS][VVC_MAX_LAYERS]; + + HEADER("Video Parameter Set"); + + CHECK(FUNC(nal_unit_header) (ctx, rw, + ¤t->nal_unit_header, VVC_VPS_NUT)); + + ub(4, vps_video_parameter_set_id); + if (current->vps_video_parameter_set_id == 0) { + av_log(ctx->log_ctx, AV_LOG_ERROR, + "vps_video_parameter_set_id should > 0.\n"); + return AVERROR_INVALIDDATA; + } + ub(6, vps_max_layers_minus1); + u(3, vps_max_sublayers_minus1, 0, 6); + if (current->vps_max_layers_minus1 > 0 + && current->vps_max_sublayers_minus1 > 0) + flag(vps_default_ptl_dpb_hrd_max_tid_flag); + else + infer(vps_default_ptl_dpb_hrd_max_tid_flag, 1); + + if (current->vps_max_layers_minus1 > 0) + flag(vps_all_independent_layers_flag); + else + infer(vps_all_independent_layers_flag, 1); + + for (i = 0; i <= current->vps_max_layers_minus1; i++) { + ubs(6, vps_layer_id[i], 1, i); + if (i > 0 && current->vps_layer_id[i] <= current->vps_layer_id[i - 1]) { + av_log(ctx->log_ctx, AV_LOG_ERROR, + "vps_layer_id[%d](%d) should > vps_layer_id[%d](%d).\n", + i, current->vps_layer_id[i], i - 1, + current->vps_layer_id[i - 1]); + return AVERROR_INVALIDDATA; + } + if (i > 0 && !current->vps_all_independent_layers_flag) { + flags(vps_independent_layer_flag[i], 1, i); + if (!current->vps_independent_layer_flag[i]) { + flags(vps_max_tid_ref_present_flag[i], 1, i); + for (j = 0; j < i; j++) { + flags(vps_direct_ref_layer_flag[i][j], 2, i, j); + if (current->vps_max_tid_ref_present_flag[i] && + current->vps_direct_ref_layer_flag[i][j]) { + ubs(3, vps_max_tid_il_ref_pics_plus1[i][j], 2, i, j); + } else { + infer(vps_max_tid_il_ref_pics_plus1[i][j], + current->vps_max_sublayers_minus1 + 1); + } + } + } else { + for (j = 0; j < i; j++) { + infer(vps_direct_ref_layer_flag[i][j], 0); + } + } + } else { + infer(vps_independent_layer_flag[i], 1); + for (j = 0; j < i; j++) { + infer(vps_direct_ref_layer_flag[i][j], 0); + } + } + } + + if (current->vps_max_layers_minus1 > 0) { + if (current->vps_all_independent_layers_flag) + flag(vps_each_layer_is_an_ols_flag); + else + infer(vps_each_layer_is_an_ols_flag, 0); + if (!current->vps_each_layer_is_an_ols_flag) { + if (!current->vps_all_independent_layers_flag) + ub(2, vps_ols_mode_idc); + else + infer(vps_ols_mode_idc, 2); + if (current->vps_ols_mode_idc == 2) { + ub(8, vps_num_output_layer_sets_minus2); + for (i = 1; i <= current->vps_num_output_layer_sets_minus2 + 1; + i++) + for (j = 0; j <= current->vps_max_layers_minus1; j++) + flags(vps_ols_output_layer_flag[i][j], 2, i, j); + } + ols_mode_idc = current->vps_ols_mode_idc; + } else { + ols_mode_idc = 4; + } + if (ols_mode_idc == 4 || ols_mode_idc == 0 || ols_mode_idc == 1) + total_num_olss = current->vps_max_layers_minus1 + 1; + else if (ols_mode_idc = 2) + total_num_olss = current->vps_num_output_layer_sets_minus2 + 2; + else + av_log(ctx->log_ctx, AV_LOG_ERROR, + "ols_mode_idc == 3, patch welcome"); + u(8, vps_num_ptls_minus1, 0, total_num_olss - 1); + } else { + infer(vps_each_layer_is_an_ols_flag, 1); + infer(vps_num_ptls_minus1, 0); + } + { + //calc NumMultiLayerOlss + int m; + uint8_t dependency_flag[VVC_MAX_LAYERS][VVC_MAX_LAYERS]; + uint16_t num_output_layers_in_ols[VVC_MAX_TOTAL_NUM_OLSS]; + uint8_t num_sub_layers_in_layer_in_ols[VVC_MAX_TOTAL_NUM_OLSS][VVC_MAX_TOTAL_NUM_OLSS]; + uint8_t output_layer_idx[VVC_MAX_TOTAL_NUM_OLSS][VVC_MAX_LAYERS]; + + //7.4.3.3 vps_direct_ref_layer_flag section + for (i = 0; i <= current->vps_max_layers_minus1; i++) { + for (j = 0; j <= current->vps_max_layers_minus1; j++) { + dependency_flag[i][j] = current->vps_direct_ref_layer_flag[i][j]; + for (k = 0; k < i; k++) { + if (current->vps_direct_ref_layer_flag[i][k] && + dependency_flag[k][j]) + dependency_flag[i][j] = 1; + } + } + } + for (i = 0; i <= current->vps_max_layers_minus1; i++) { + int r; + for (j = 0, r = 0; j <= current->vps_max_layers_minus1; j++) { + if (dependency_flag[i][j]) + reference_layer_idx[i][r++] = j; + } + num_ref_layers[i] = r; + } + + //7.4.3.3 vps_ols_output_layer_flag section + num_output_layers_in_ols[0] = 1; + num_sub_layers_in_layer_in_ols[0][0] = + current->vps_ptl_max_tid[current->vps_ols_ptl_idx[0]] + 1; + for (i = 1; i < total_num_olss; i++) { + if (ols_mode_idc == 4 || ols_mode_idc == 0) { + num_output_layers_in_ols[i] = 1; + if (current->vps_each_layer_is_an_ols_flag) { + num_sub_layers_in_layer_in_ols[i][0] = + current->vps_ptl_max_tid[current->vps_ols_ptl_idx[i]] + 1; + } else { + num_sub_layers_in_layer_in_ols[i][i] = + current->vps_ptl_max_tid[current->vps_ols_ptl_idx[i]] + 1; + for (k = i - 1; k >= 0; k--) { + num_sub_layers_in_layer_in_ols[i][k] = 0; + for (m = k + 1; m <= i; m++) { + uint8_t max_sublayer_needed = + FFMIN(num_sub_layers_in_layer_in_ols[i][m], + current->vps_max_tid_il_ref_pics_plus1[m][k]); + if (current->vps_direct_ref_layer_flag[m][k] && + num_sub_layers_in_layer_in_ols[i][k] < max_sublayer_needed) + num_sub_layers_in_layer_in_ols[i][k] = max_sublayer_needed; + } + } + } + } else if (current->vps_ols_mode_idc == 1) { + num_output_layers_in_ols[i] = i + 1; + for (j = 0; j < num_output_layers_in_ols[i]; j++) { + num_sub_layers_in_layer_in_ols[i][j] = + current->vps_ptl_max_tid[current->vps_ols_ptl_idx[i]] + 1; + } + } else if (current->vps_ols_mode_idc == 2) { + uint8_t highest_included_layer = 0; + for (j = 0; j <= current->vps_max_layers_minus1; j++) { + layer_included_in_ols_flag[i][j] = 0; + num_sub_layers_in_layer_in_ols[i][j] = 0; + } + for (k = 0, j = 0; k <= current->vps_max_layers_minus1; k++) { + if (current->vps_ols_output_layer_flag[i][k]) { + layer_included_in_ols_flag[i][k] = 1; + highest_included_layer = k; + output_layer_idx[i][j] = k; + num_sub_layers_in_layer_in_ols[i][k] = + current->vps_ptl_max_tid[current-> + vps_ols_ptl_idx[i]] + 1; + j++; + } + } + num_output_layers_in_ols[i] = j; + for (j = 0; j < num_output_layers_in_ols[i]; j++) { + int idx = output_layer_idx[i][j]; + for (k = 0; k < num_ref_layers[idx]; k++) { + if (!layer_included_in_ols_flag[i][reference_layer_idx[idx][k]]) + layer_included_in_ols_flag[i][reference_layer_idx[idx][k]] = 1; + } + } + for (k = highest_included_layer - 1; k >= 0; k--) { + if (layer_included_in_ols_flag[i][k] && + !current->vps_ols_output_layer_flag[i][k]) { + for (m = k + 1; m <= highest_included_layer; m++) { + uint8_t max_sublayer_needed = + FFMIN(num_sub_layers_in_layer_in_ols[i][m], + current->vps_max_tid_il_ref_pics_plus1[m][k]); + if (current->vps_direct_ref_layer_flag[m][k] && + layer_included_in_ols_flag[i][m] && + num_sub_layers_in_layer_in_ols[i][k] < + max_sublayer_needed) + num_sub_layers_in_layer_in_ols[i][k] = + max_sublayer_needed; + } + } + } + } + } + for (i = 1; i < total_num_olss; i++) { + int num_layers_in_ols = 0; + if (current->vps_each_layer_is_an_ols_flag) { + num_layers_in_ols = 1; + } else if (current->vps_ols_mode_idc == 0 || + current->vps_ols_mode_idc == 1) { + num_layers_in_ols = i + 1; + } else if (current->vps_ols_mode_idc == 2) { + for (k = 0, j = 0; k <= current->vps_max_layers_minus1; k++) { + if (layer_included_in_ols_flag[i][k]) + j++; + num_layers_in_ols = j; + } + } + if (num_layers_in_ols > 1) { + num_multi_layer_olss++; + } + } + } + + for (i = 0; i <= current->vps_num_ptls_minus1; i++) { + if (i > 0) + flags(vps_pt_present_flag[i], 1, i); + else + infer(vps_pt_present_flag[i], 1); + + if (!current->vps_default_ptl_dpb_hrd_max_tid_flag) + us(3, vps_ptl_max_tid[i], 0, current->vps_max_sublayers_minus1, 1, i); + else + infer(vps_ptl_max_tid[i], current->vps_max_sublayers_minus1); + } + while (byte_alignment(rw) != 0) + fixed(1, vps_ptl_alignment_zero_bit, 0); + for (i = 0; i <= current->vps_num_ptls_minus1; i++) { + CHECK(FUNC(profile_tier_level) (ctx, rw, + current->vps_profile_tier_level + i, + current->vps_pt_present_flag[i], + current->vps_ptl_max_tid[i])); + } + for (i = 0; i < total_num_olss; i++) { + if (current->vps_num_ptls_minus1 > 0 && + current->vps_num_ptls_minus1 + 1 != total_num_olss) { + us(8, vps_ols_ptl_idx[i], 0, current->vps_num_ptls_minus1, 1, i); + } else if (current->vps_num_ptls_minus1 == 0) { + infer(vps_ols_ptl_idx[i], 0); + } else { + infer(vps_ols_ptl_idx[i], i); + } + } + + if (!current->vps_each_layer_is_an_ols_flag) { + uint16_t vps_num_dpb_params; + ue(vps_num_dpb_params_minus1, 0, num_multi_layer_olss - 1); + if (current->vps_each_layer_is_an_ols_flag) + vps_num_dpb_params = 0; + else + vps_num_dpb_params = current->vps_num_dpb_params_minus1 + 1; + + if (current->vps_max_sublayers_minus1 > 0) + flag(vps_sublayer_dpb_params_present_flag); + else + infer(vps_sublayer_dpb_params_present_flag, 0); + + for (i = 0; i < vps_num_dpb_params; i++) { + if (!current->vps_default_ptl_dpb_hrd_max_tid_flag) + us(3, vps_dpb_max_tid[i], 0, current->vps_max_sublayers_minus1, + 1, i); + else + infer(vps_dpb_max_tid[i], current->vps_max_sublayers_minus1); + CHECK(FUNC(dpb_parameters) (ctx, rw, current->vps_dpb_params + i, + current->vps_dpb_max_tid[i], + current-> + vps_sublayer_dpb_params_present_flag)); + } + for (i = 0; i < num_multi_layer_olss; i++) { + ues(vps_ols_dpb_pic_width[i], 0, UINT16_MAX, 1, i); + ues(vps_ols_dpb_pic_height[i], 0, UINT16_MAX, 1, i); + ubs(2, vps_ols_dpb_chroma_format[i], 1, i); + ues(vps_ols_dpb_bitdepth_minus8[i], 0, 2, 1, i); + if (vps_num_dpb_params > 1 + && vps_num_dpb_params != num_multi_layer_olss) + ues(vps_ols_dpb_params_idx[i], 0, vps_num_dpb_params - 1, 1, i); + else if (vps_num_dpb_params == 1) + infer(vps_ols_dpb_params_idx[i], 0); + else + infer(vps_ols_dpb_params_idx[i], i); + } + flag(vps_timing_hrd_params_present_flag); + if (current->vps_timing_hrd_params_present_flag) { + CHECK(FUNC(general_timing_hrd_parameters) (ctx, rw, + ¤t-> + vps_general_timing_hrd_parameters)); + if (current->vps_max_sublayers_minus1 > 0) + flag(vps_sublayer_cpb_params_present_flag); + else + infer(vps_sublayer_cpb_params_present_flag, 0); + ue(vps_num_ols_timing_hrd_params_minus1, 0, + num_multi_layer_olss - 1); + for (i = 0; i <= current->vps_num_ols_timing_hrd_params_minus1; i++) { + uint8_t first_sublayer; + if (!current->vps_default_ptl_dpb_hrd_max_tid_flag) + us(3, vps_hrd_max_tid[i], 0, + current->vps_max_sublayers_minus1, 1, i); + else + infer(vps_hrd_max_tid[i], + current->vps_max_sublayers_minus1); + first_sublayer = current->vps_sublayer_cpb_params_present_flag ? + 0 : current->vps_hrd_max_tid[i]; + CHECK(FUNC(ols_timing_hrd_parameters) + (ctx, rw, ¤t->vps_ols_timing_hrd_parameters, + first_sublayer, current->vps_max_sublayers_minus1, + ¤t->vps_general_timing_hrd_parameters)); + + } + if (current->vps_num_ols_timing_hrd_params_minus1 > 0 && + current->vps_num_ols_timing_hrd_params_minus1 + 1 != + num_multi_layer_olss) { + for (i = 0; i < num_multi_layer_olss; i++) { + ues(vps_ols_timing_hrd_idx[i], 0, + current->vps_num_ols_timing_hrd_params_minus1, 1, i); + } + } else if (current->vps_num_ols_timing_hrd_params_minus1 == 0) { + for (i = 0; i < num_multi_layer_olss; i++) + infer(vps_ols_timing_hrd_idx[i], 0); + } else { + for (i = 0; i < num_multi_layer_olss; i++) + infer(vps_ols_timing_hrd_idx[i], i); + } + } + } + + flag(vps_extension_flag); + if (current->vps_extension_flag) + CHECK(FUNC(extension_data) (ctx, rw, ¤t->extension_data)); + CHECK(FUNC(rbsp_trailing_bits) (ctx, rw)); + + return 0; +} + + +static int FUNC(sps)(CodedBitstreamContext *ctx, RWContext *rw, + H266RawSPS *current) +{ + CodedBitstreamH266Context *h266 = ctx->priv_data; + int err, i, j; + unsigned int ctb_log2_size_y, min_cb_log2_size_y, + min_qt_log2_size_intra_y, min_qt_log2_size_inter_y, + ctb_size_y, max_num_merge_cand, tmp_width_val, tmp_height_val; + uint8_t qp_bd_offset; + + static const uint8_t h266_sub_width_c[] = { + 1, 2, 2, 1 + }; + static const uint8_t h266_sub_height_c[] = { + 1, 2, 1, 1 + }; + + HEADER("Sequence Parameter Set"); + + CHECK(FUNC(nal_unit_header) (ctx, rw, + ¤t->nal_unit_header, VVC_SPS_NUT)); + + ub(4, sps_seq_parameter_set_id); + ub(4, sps_video_parameter_set_id); + if (current->sps_video_parameter_set_id == 0 && !h266->vps_ref[0]) { + H266RawVPS *vps; + AVBufferRef *ref = av_buffer_allocz(sizeof(H266RawVPS)); + if (!ref) { + return AVERROR(ENOMEM); + } + vps = (H266RawVPS *) ref->data; + vps->vps_max_layers_minus1 = 0; + vps->vps_independent_layer_flag[0] = 1; + vps->vps_layer_id[0] = current->nal_unit_header.nuh_layer_id; + h266->vps_ref[0] = ref; + h266->vps[0] = vps; + } + + u(3, sps_max_sublayers_minus1, 0, VVC_MAX_SUBLAYERS - 1); + u(2, sps_chroma_format_idc, 0, 3); + u(2, sps_log2_ctu_size_minus5, 0, 3); + ctb_log2_size_y = current->sps_log2_ctu_size_minus5 + 5; + ctb_size_y = 1 << ctb_log2_size_y; + + flag(sps_ptl_dpb_hrd_params_present_flag); + if (current->sps_ptl_dpb_hrd_params_present_flag) { + CHECK(FUNC(profile_tier_level) (ctx, rw, ¤t->profile_tier_level, + 1, current->sps_max_sublayers_minus1)); + } + flag(sps_gdr_enabled_flag); + flag(sps_ref_pic_resampling_enabled_flag); + if (current->sps_ref_pic_resampling_enabled_flag) + flag(sps_res_change_in_clvs_allowed_flag); + else + infer(sps_res_change_in_clvs_allowed_flag, 0); + + ue(sps_pic_width_max_in_luma_samples, 1, VVC_MAX_WIDTH); + ue(sps_pic_height_max_in_luma_samples, 1, VVC_MAX_HEIGHT); + + flag(sps_conformance_window_flag); + if (current->sps_conformance_window_flag) { + uint8_t sub_width_c = h266_sub_width_c[current->sps_chroma_format_idc]; + uint8_t sub_height_c = h266_sub_height_c[current->sps_chroma_format_idc]; + uint16_t width = current->sps_pic_width_max_in_luma_samples / sub_width_c; + uint16_t height = current->sps_pic_height_max_in_luma_samples / sub_height_c; + ue(sps_conf_win_left_offset, 0, width); + ue(sps_conf_win_right_offset, 0, width - current->sps_conf_win_left_offset); + ue(sps_conf_win_top_offset, 0, height); + ue(sps_conf_win_bottom_offset, 0, height - current->sps_conf_win_top_offset); + } else { + infer(sps_conf_win_left_offset, 0); + infer(sps_conf_win_right_offset, 0); + infer(sps_conf_win_top_offset, 0); + infer(sps_conf_win_bottom_offset, 0); + } + + tmp_width_val = AV_CEIL_RSHIFT(current->sps_pic_width_max_in_luma_samples, + ctb_log2_size_y); + tmp_height_val = AV_CEIL_RSHIFT(current->sps_pic_height_max_in_luma_samples, + ctb_log2_size_y); + + flag(sps_subpic_info_present_flag); + if (current->sps_subpic_info_present_flag) { + ue(sps_num_subpics_minus1, 1, VVC_MAX_SLICES - 1); + if (current->sps_num_subpics_minus1 > 0) { + flag(sps_independent_subpics_flag); + flag(sps_subpic_same_size_flag); + } + + if (current->sps_num_subpics_minus1 > 0) { + int wlen = av_ceil_log2(tmp_width_val); + int hlen = av_ceil_log2(tmp_height_val); + if (current->sps_pic_width_max_in_luma_samples > ctb_size_y) + ubs(wlen, sps_subpic_width_minus1[0], 1, 0); + else + infer(sps_subpic_width_minus1[i], tmp_width_val - 1); + if (current->sps_pic_height_max_in_luma_samples > ctb_size_y) + ubs(hlen, sps_subpic_height_minus1[0], 1, 0); + else + infer(sps_subpic_height_minus1[0], tmp_height_val); + if (!current->sps_independent_subpics_flag) { + flags(sps_subpic_treated_as_pic_flag[0], 1, 0); + flags(sps_loop_filter_across_subpic_enabled_flag[0], 1, 0); + } else { + infer(sps_subpic_treated_as_pic_flag[0], 1); + infer(sps_loop_filter_across_subpic_enabled_flag[0], 1); + } + for (i = 1; i <= current->sps_num_subpics_minus1; i++) { + if (!current->sps_subpic_same_size_flag) { + if (current->sps_pic_width_max_in_luma_samples > ctb_size_y) + ubs(wlen, sps_subpic_ctu_top_left_x[i], 1, i); + else + infer(sps_subpic_ctu_top_left_x[i], 0); + if (current->sps_pic_height_max_in_luma_samples > + ctb_size_y) + ubs(hlen, sps_subpic_ctu_top_left_y[i], 1, i); + else + infer(sps_subpic_ctu_top_left_y[i], 0); + if (i < current->sps_num_subpics_minus1 && + current->sps_pic_width_max_in_luma_samples > + ctb_size_y) { + ubs(wlen, sps_subpic_width_minus1[i], 1, i); + } else { + infer(sps_subpic_width_minus1[i], + tmp_width_val - + current->sps_subpic_ctu_top_left_x[i] - 1); + } + if (i < current->sps_num_subpics_minus1 && + current->sps_pic_height_max_in_luma_samples > + ctb_size_y) { + ubs(hlen, sps_subpic_height_minus1[i], 1, i); + } else { + infer(sps_subpic_height_minus1[i], + tmp_height_val - + current->sps_subpic_ctu_top_left_y[i] - 1); + } + } else { + int num_subpic_cols = tmp_width_val / + (current->sps_subpic_width_minus1[0] + 1); + infer(sps_subpic_ctu_top_left_x[i], + (i % num_subpic_cols) * + (current->sps_subpic_width_minus1[0] + 1)); + infer(sps_subpic_ctu_top_left_y[i], + (i / num_subpic_cols) * + (current->sps_subpic_height_minus1[0] + 1)); + infer(sps_subpic_width_minus1[i], + current->sps_subpic_width_minus1[0]); + infer(sps_subpic_height_minus1[i], + current->sps_subpic_height_minus1[0]); + } + if (!current->sps_independent_subpics_flag) { + flags(sps_subpic_treated_as_pic_flag[i], 1, i); + flags(sps_loop_filter_across_subpic_enabled_flag[i], 1, i); + } else { + infer(sps_subpic_treated_as_pic_flag[i], 1); + infer(sps_loop_filter_across_subpic_enabled_flag[i], 0); + } + } + ue(sps_subpic_id_len_minus1, 0, 15); + if ((1 << (current->sps_subpic_id_len_minus1 + 1)) < + current->sps_num_subpics_minus1 + 1) { + av_log(ctx->log_ctx, AV_LOG_ERROR, + "sps_subpic_id_len_minus1(%d) is too small\n", + current->sps_subpic_id_len_minus1); + return AVERROR_INVALIDDATA; + } + flag(sps_subpic_id_mapping_explicitly_signalled_flag); + if (current->sps_subpic_id_mapping_explicitly_signalled_flag) { + flag(sps_subpic_id_mapping_present_flag); + if (current->sps_subpic_id_mapping_present_flag) { + for (i = 0; i <= current->sps_num_subpics_minus1; i++) { + ubs(current->sps_subpic_id_len_minus1 + 1, + sps_subpic_id[i], 1, i); + } + } + } + } else { + infer(sps_subpic_ctu_top_left_x[0], 0); + infer(sps_subpic_ctu_top_left_y[0], 0); + infer(sps_subpic_width_minus1[0], tmp_width_val - 1); + infer(sps_subpic_height_minus1[0], tmp_height_val - 1); + } + } else { + infer(sps_num_subpics_minus1, 0); + infer(sps_independent_subpics_flag, 1); + infer(sps_subpic_same_size_flag, 0); + infer(sps_subpic_id_mapping_explicitly_signalled_flag, 0); + infer(sps_subpic_ctu_top_left_x[0], 0); + infer(sps_subpic_ctu_top_left_y[0], 0); + infer(sps_subpic_width_minus1[0], tmp_width_val - 1); + infer(sps_subpic_height_minus1[0], tmp_height_val - 1); + } + + + ue(sps_bitdepth_minus8, 0, 2); + qp_bd_offset = 6 * current->sps_bitdepth_minus8; + + flag(sps_entropy_coding_sync_enabled_flag); + flag(sps_entry_point_offsets_present_flag); + + u(4, sps_log2_max_pic_order_cnt_lsb_minus4, 0, 12); + flag(sps_poc_msb_cycle_flag); + if (current->sps_poc_msb_cycle_flag) + ue(sps_poc_msb_cycle_len_minus1, + 0, 32 - current->sps_log2_max_pic_order_cnt_lsb_minus4 - 5); + + u(2, sps_num_extra_ph_bytes, 0, 2); + for (i = 0; i < (current->sps_num_extra_ph_bytes * 8); i++) { + flags(sps_extra_ph_bit_present_flag[i], 1, i); + } + + u(2, sps_num_extra_sh_bytes, 0, 2); + for (i = 0; i < (current->sps_num_extra_sh_bytes * 8); i++) { + flags(sps_extra_sh_bit_present_flag[i], 1, i); + } + + if (current->sps_ptl_dpb_hrd_params_present_flag) { + if (current->sps_max_sublayers_minus1 > 0) + flag(sps_sublayer_dpb_params_flag); + else + infer(sps_sublayer_dpb_params_flag, 0); + CHECK(FUNC(dpb_parameters) (ctx, rw, ¤t->sps_dpb_params, + current->sps_max_sublayers_minus1, + current->sps_sublayer_dpb_params_flag)); + } + + ue(sps_log2_min_luma_coding_block_size_minus2, + 0, FFMIN(4, current->sps_log2_ctu_size_minus5 + 3)); + min_cb_log2_size_y = + current->sps_log2_min_luma_coding_block_size_minus2 + 2; + + flag(sps_partition_constraints_override_enabled_flag); + + ue(sps_log2_diff_min_qt_min_cb_intra_slice_luma, + 0, FFMIN(6, ctb_log2_size_y) - min_cb_log2_size_y); + min_qt_log2_size_intra_y = + current->sps_log2_diff_min_qt_min_cb_intra_slice_luma + + min_cb_log2_size_y; + + ue(sps_max_mtt_hierarchy_depth_intra_slice_luma, + 0, 2 * (ctb_log2_size_y - min_cb_log2_size_y)); + + if (current->sps_max_mtt_hierarchy_depth_intra_slice_luma != 0) { + ue(sps_log2_diff_max_bt_min_qt_intra_slice_luma, + 0, ctb_log2_size_y - min_qt_log2_size_intra_y); + ue(sps_log2_diff_max_tt_min_qt_intra_slice_luma, + 0, FFMIN(6, ctb_log2_size_y) - min_qt_log2_size_intra_y); + } else { + infer(sps_log2_diff_max_bt_min_qt_intra_slice_luma, 0); + infer(sps_log2_diff_max_tt_min_qt_intra_slice_luma, 0); + } + + if (current->sps_chroma_format_idc != 0) { + flag(sps_qtbtt_dual_tree_intra_flag); + } else { + infer(sps_qtbtt_dual_tree_intra_flag, 0); + } + + if (current->sps_qtbtt_dual_tree_intra_flag) { + ue(sps_log2_diff_min_qt_min_cb_intra_slice_chroma, + 0, FFMIN(6, ctb_log2_size_y) - min_cb_log2_size_y); + ue(sps_max_mtt_hierarchy_depth_intra_slice_chroma, + 0, 2 * (ctb_log2_size_y - min_cb_log2_size_y)); + if (current->sps_max_mtt_hierarchy_depth_intra_slice_chroma != 0) { + unsigned int min_qt_log2_size_intra_c = + current->sps_log2_diff_min_qt_min_cb_intra_slice_chroma + + min_cb_log2_size_y; + ue(sps_log2_diff_max_bt_min_qt_intra_slice_chroma, + 0, FFMIN(6, ctb_log2_size_y) - min_qt_log2_size_intra_c); + ue(sps_log2_diff_max_tt_min_qt_intra_slice_chroma, + 0, FFMIN(6, ctb_log2_size_y) - min_qt_log2_size_intra_c); + } + } else { + infer(sps_log2_diff_min_qt_min_cb_intra_slice_chroma, 0); + infer(sps_max_mtt_hierarchy_depth_intra_slice_chroma, 0); + } + if (current->sps_max_mtt_hierarchy_depth_intra_slice_chroma == 0) { + infer(sps_log2_diff_max_bt_min_qt_intra_slice_chroma, 0); + infer(sps_log2_diff_max_tt_min_qt_intra_slice_chroma, 0); + } + + ue(sps_log2_diff_min_qt_min_cb_inter_slice, + 0, FFMIN(6, ctb_log2_size_y) - min_cb_log2_size_y); + min_qt_log2_size_inter_y = + current->sps_log2_diff_min_qt_min_cb_inter_slice + min_cb_log2_size_y; + + ue(sps_max_mtt_hierarchy_depth_inter_slice, + 0, 2 * (ctb_log2_size_y - min_cb_log2_size_y)); + if (current->sps_max_mtt_hierarchy_depth_inter_slice != 0) { + ue(sps_log2_diff_max_bt_min_qt_inter_slice, + 0, ctb_log2_size_y - min_qt_log2_size_inter_y); + ue(sps_log2_diff_max_tt_min_qt_inter_slice, + 0, FFMIN(6, ctb_log2_size_y) - min_qt_log2_size_inter_y); + } else { + infer(sps_log2_diff_max_bt_min_qt_inter_slice, 0); + infer(sps_log2_diff_max_tt_min_qt_inter_slice, 0); + } + + if (ctb_size_y > 32) + flag(sps_max_luma_transform_size_64_flag); + else + infer(sps_max_luma_transform_size_64_flag, 0); + + flag(sps_transform_skip_enabled_flag); + if (current->sps_transform_skip_enabled_flag) { + ue(sps_log2_transform_skip_max_size_minus2, 0, 3); + flag(sps_bdpcm_enabled_flag); + } + + flag(sps_mts_enabled_flag); + if (current->sps_mts_enabled_flag) { + flag(sps_explicit_mts_intra_enabled_flag); + flag(sps_explicit_mts_inter_enabled_flag); + } else { + infer(sps_explicit_mts_intra_enabled_flag, 0); + infer(sps_explicit_mts_inter_enabled_flag, 0); + } + + flag(sps_lfnst_enabled_flag); + + if (current->sps_chroma_format_idc != 0) { + uint8_t num_qp_tables; + flag(sps_joint_cbcr_enabled_flag); + flag(sps_same_qp_table_for_chroma_flag); + num_qp_tables = current->sps_same_qp_table_for_chroma_flag ? + 1 : (current->sps_joint_cbcr_enabled_flag ? 3 : 2); + for (i = 0; i < num_qp_tables; i++) { + ses(sps_qp_table_start_minus26[i], -26 - qp_bd_offset, 36, 1, i); + ues(sps_num_points_in_qp_table_minus1[i], + 0, 36 - current->sps_qp_table_start_minus26[i], 1, i); + for (j = 0; j <= current->sps_num_points_in_qp_table_minus1[i]; j++) { + uint8_t max = MAX_UINT_BITS(8); + ues(sps_delta_qp_in_val_minus1[i][j], 0, max, 2, i, j); + ues(sps_delta_qp_diff_val[i][j], 0, max, 2, i, j); + } + } + } else { + infer(sps_joint_cbcr_enabled_flag, 0); + infer(sps_same_qp_table_for_chroma_flag, 0); + } + + flag(sps_sao_enabled_flag); + flag(sps_alf_enabled_flag); + if (current->sps_alf_enabled_flag && current->sps_chroma_format_idc) + flag(sps_ccalf_enabled_flag); + else + infer(sps_ccalf_enabled_flag, 0); + flag(sps_lmcs_enabled_flag); + flag(sps_weighted_pred_flag); + flag(sps_weighted_bipred_flag); + flag(sps_long_term_ref_pics_flag); + if (current->sps_video_parameter_set_id > 0) + flag(sps_inter_layer_prediction_enabled_flag); + else + infer(sps_inter_layer_prediction_enabled_flag, 0); + flag(sps_idr_rpl_present_flag); + flag(sps_rpl1_same_as_rpl0_flag); + + for (i = 0; i < (current->sps_rpl1_same_as_rpl0_flag ? 1 : 2); i++) { + ues(sps_num_ref_pic_lists[i], 0, VVC_MAX_REF_PIC_LISTS, 1, i); + for (j = 0; j < current->sps_num_ref_pic_lists[i]; j++) + CHECK(FUNC(ref_pic_list_struct) (ctx, rw, + ¤t-> + sps_ref_pic_list_struct[i][j], i, + j, current)); + } + + if (current->sps_rpl1_same_as_rpl0_flag) { + current->sps_num_ref_pic_lists[1] = current->sps_num_ref_pic_lists[0]; + for (j = 0; j < current->sps_num_ref_pic_lists[0]; j++) + memcpy(¤t->sps_ref_pic_list_struct[1][j], + ¤t->sps_ref_pic_list_struct[0][j], + sizeof(current->sps_ref_pic_list_struct[0][j])); + } + + flag(sps_ref_wraparound_enabled_flag); + + flag(sps_temporal_mvp_enabled_flag); + if (current->sps_temporal_mvp_enabled_flag) + flag(sps_sbtmvp_enabled_flag); + else + infer(sps_sbtmvp_enabled_flag, 0); + + flag(sps_amvr_enabled_flag); + flag(sps_bdof_enabled_flag); + if (current->sps_bdof_enabled_flag) + flag(sps_bdof_control_present_in_ph_flag); + else + infer(sps_bdof_control_present_in_ph_flag, 0); + + flag(sps_smvd_enabled_flag); + flag(sps_dmvr_enabled_flag); + if (current->sps_dmvr_enabled_flag) + flag(sps_dmvr_control_present_in_ph_flag); + else + infer(sps_dmvr_control_present_in_ph_flag, 0); + + flag(sps_mmvd_enabled_flag); + if (current->sps_mmvd_enabled_flag) + flag(sps_mmvd_fullpel_only_enabled_flag); + else + infer(sps_mmvd_fullpel_only_enabled_flag, 0); + + ue(sps_six_minus_max_num_merge_cand, 0, 5); + max_num_merge_cand = 6 - current->sps_six_minus_max_num_merge_cand; + + flag(sps_sbt_enabled_flag); + + flag(sps_affine_enabled_flag); + if (current->sps_affine_enabled_flag) { + ue(sps_five_minus_max_num_subblock_merge_cand, + 0, 5 - current->sps_sbtmvp_enabled_flag); + flag(sps_6param_affine_enabled_flag); + if (current->sps_amvr_enabled_flag) + flag(sps_affine_amvr_enabled_flag); + else + infer(sps_affine_amvr_enabled_flag, 0); + flag(sps_affine_prof_enabled_flag); + if (current->sps_affine_prof_enabled_flag) + flag(sps_prof_control_present_in_ph_flag); + else + infer(sps_prof_control_present_in_ph_flag, 0); + } else { + infer(sps_6param_affine_enabled_flag, 0); + infer(sps_affine_amvr_enabled_flag, 0); + infer(sps_affine_prof_enabled_flag, 0); + infer(sps_prof_control_present_in_ph_flag, 0); + } + + flag(sps_bcw_enabled_flag); + flag(sps_ciip_enabled_flag); + + if (max_num_merge_cand >= 2) { + flag(sps_gpm_enabled_flag); + if (current->sps_gpm_enabled_flag && max_num_merge_cand >= 3) + ue(sps_max_num_merge_cand_minus_max_num_gpm_cand, + 0, max_num_merge_cand - 2); + } else { + infer(sps_gpm_enabled_flag, 0); + } + + ue(sps_log2_parallel_merge_level_minus2, 0, ctb_log2_size_y - 2); + + flag(sps_isp_enabled_flag); + flag(sps_mrl_enabled_flag); + flag(sps_mip_enabled_flag); + + if (current->sps_chroma_format_idc != 0) + flag(sps_cclm_enabled_flag); + else + infer(sps_cclm_enabled_flag, 0); + if (current->sps_chroma_format_idc == 1) { + flag(sps_chroma_horizontal_collocated_flag); + flag(sps_chroma_vertical_collocated_flag); + } else { + infer(sps_chroma_horizontal_collocated_flag, 1); + infer(sps_chroma_vertical_collocated_flag, 1); + } + + flag(sps_palette_enabled_flag); + if (current->sps_chroma_format_idc == 3 && + !current->sps_max_luma_transform_size_64_flag) + flag(sps_act_enabled_flag); + else + infer(sps_act_enabled_flag, 0); + if (current->sps_transform_skip_enabled_flag || + current->sps_palette_enabled_flag) + ue(sps_min_qp_prime_ts, 0, 8); + + flag(sps_ibc_enabled_flag); + if (current->sps_ibc_enabled_flag) + ue(sps_six_minus_max_num_ibc_merge_cand, 0, 5); + + flag(sps_ladf_enabled_flag); + if (current->sps_ladf_enabled_flag) { + ub(2, sps_num_ladf_intervals_minus2); + se(sps_ladf_lowest_interval_qp_offset, -63, 63); + for (i = 0; i < current->sps_num_ladf_intervals_minus2 + 1; i++) { + ses(sps_ladf_qp_offset[i], -63, 63, 1, i); + ues(sps_ladf_delta_threshold_minus1[i], + 0, (2 << (8 + current->sps_bitdepth_minus8)) - 3, 1, i); + } + } + + flag(sps_explicit_scaling_list_enabled_flag); + if (current->sps_lfnst_enabled_flag && + current->sps_explicit_scaling_list_enabled_flag) + flag(sps_scaling_matrix_for_lfnst_disabled_flag); + + if (current->sps_act_enabled_flag && + current->sps_explicit_scaling_list_enabled_flag) + flag(sps_scaling_matrix_for_alternative_colour_space_disabled_flag); + else + infer(sps_scaling_matrix_for_alternative_colour_space_disabled_flag, 0); + if (current->sps_scaling_matrix_for_alternative_colour_space_disabled_flag) + flag(sps_scaling_matrix_designated_colour_space_flag); + + flag(sps_dep_quant_enabled_flag); + flag(sps_sign_data_hiding_enabled_flag); + + flag(sps_virtual_boundaries_enabled_flag); + if (current->sps_virtual_boundaries_enabled_flag) { + flag(sps_virtual_boundaries_present_flag); + if (current->sps_virtual_boundaries_present_flag) { + ue(sps_num_ver_virtual_boundaries, + 0, current->sps_pic_width_max_in_luma_samples <= 8 ? 0 : 3); + for (i = 0; i < current->sps_num_ver_virtual_boundaries; i++) + ues(sps_virtual_boundary_pos_x_minus1[i], + 0, (current->sps_pic_width_max_in_luma_samples + 7) / 8 - 2, + 1, i); + ue(sps_num_hor_virtual_boundaries, + 0, current->sps_pic_height_max_in_luma_samples <= 8 ? 0 : 3); + for (i = 0; i < current->sps_num_hor_virtual_boundaries; i++) + ues(sps_virtual_boundary_pos_y_minus1[i], + 0, (current->sps_pic_height_max_in_luma_samples + 7) / + 8 - 2, 1, i); + } + } else { + infer(sps_virtual_boundaries_present_flag, 0); + infer(sps_num_ver_virtual_boundaries, 0); + infer(sps_num_hor_virtual_boundaries, 0); + } + + if (current->sps_ptl_dpb_hrd_params_present_flag) { + flag(sps_timing_hrd_params_present_flag); + if (current->sps_timing_hrd_params_present_flag) { + uint8_t first_sublayer; + CHECK(FUNC(general_timing_hrd_parameters) (ctx, rw, + ¤t->sps_general_timing_hrd_parameters)); + if (current->sps_max_sublayers_minus1 > 0) + flag(sps_sublayer_cpb_params_present_flag); + else + infer(sps_sublayer_cpb_params_present_flag, 0); + first_sublayer = current->sps_sublayer_cpb_params_present_flag ? + 0 : current->sps_max_sublayers_minus1; + CHECK(FUNC(ols_timing_hrd_parameters) (ctx, rw, + ¤t->sps_ols_timing_hrd_parameters, first_sublayer, + current->sps_max_sublayers_minus1, + ¤t->sps_general_timing_hrd_parameters)); + } + } + + flag(sps_field_seq_flag); + flag(sps_vui_parameters_present_flag); + if (current->sps_vui_parameters_present_flag) { + ue(sps_vui_payload_size_minus1, 0, 1023); + while (byte_alignment(rw) != 0) + fixed(1, sps_vui_alignment_zero_bit, 0); + CHECK(FUNC(vui_payload) (ctx, rw, ¤t->vui, + current->sps_vui_payload_size_minus1 + 1, + current->sps_chroma_format_idc)); + } else { + CHECK(FUNC(vui_parameters_default) (ctx, rw, ¤t->vui)); + } + flag(sps_extension_flag); + if (current->sps_extension_flag) + CHECK(FUNC(extension_data) (ctx, rw, ¤t->extension_data)); + + CHECK(FUNC(rbsp_trailing_bits) (ctx, rw)); + + return 0; +} + +static int FUNC(pps) (CodedBitstreamContext *ctx, RWContext *rw, + H266RawPPS *current) +{ + CodedBitstreamH266Context *h266 = ctx->priv_data; + const H266RawSPS *sps; + int err, i; + unsigned int min_cb_size_y, divisor, ctb_size_y, + pic_width_in_ctbs_y, pic_height_in_ctbs_y; + uint8_t sub_width_c, sub_height_c, qp_bd_offset; + + static const uint8_t h266_sub_width_c[] = { + 1, 2, 2, 1 + }; + static const uint8_t h266_sub_height_c[] = { + 1, 2, 1, 1 + }; + + HEADER("Picture Parameter Set"); + + CHECK(FUNC(nal_unit_header) (ctx, rw, + ¤t->nal_unit_header, VVC_PPS_NUT)); + + ub(6, pps_pic_parameter_set_id); + ub(4, pps_seq_parameter_set_id); + sps = h266->sps[current->pps_seq_parameter_set_id]; + if (!sps) { + av_log(ctx->log_ctx, AV_LOG_ERROR, "SPS id %d not available.\n", + current->pps_seq_parameter_set_id); + return AVERROR_INVALIDDATA; + } + + flag(pps_mixed_nalu_types_in_pic_flag); + ue(pps_pic_width_in_luma_samples, + 1, sps->sps_pic_width_max_in_luma_samples); + ue(pps_pic_height_in_luma_samples, + 1, sps->sps_pic_height_max_in_luma_samples); + + min_cb_size_y = 1 << (sps->sps_log2_min_luma_coding_block_size_minus2 + 2); + divisor = FFMAX(min_cb_size_y, 8); + if (current->pps_pic_width_in_luma_samples % divisor || + current->pps_pic_height_in_luma_samples % divisor) { + av_log(ctx->log_ctx, AV_LOG_ERROR, + "Invalid dimensions: %ux%u not divisible " + "by %u, MinCbSizeY = %u.\n", + current->pps_pic_width_in_luma_samples, + current->pps_pic_height_in_luma_samples, divisor, min_cb_size_y); + return AVERROR_INVALIDDATA; + } + if (!sps->sps_res_change_in_clvs_allowed_flag && + (current->pps_pic_width_in_luma_samples != + sps->sps_pic_width_max_in_luma_samples || + current->pps_pic_height_in_luma_samples != + sps->sps_pic_height_max_in_luma_samples)) { + av_log(ctx->log_ctx, AV_LOG_ERROR, + "Resoltuion change is not allowed, " + "in max resolution (%ux%u) mismatched with pps(%ux%u).\n", + sps->sps_pic_width_max_in_luma_samples, + sps->sps_pic_height_max_in_luma_samples, + current->pps_pic_width_in_luma_samples, + current->pps_pic_height_in_luma_samples); + return AVERROR_INVALIDDATA; + } + + ctb_size_y = 1 << (sps->sps_log2_ctu_size_minus5 + 5); + if (sps->sps_ref_wraparound_enabled_flag) { + if ((ctb_size_y / min_cb_size_y + 1) > + (current->pps_pic_width_in_luma_samples / min_cb_size_y - 1)) { + av_log(ctx->log_ctx, AV_LOG_ERROR, + "Invalid width(%u), ctb_size_y = %u, min_cb_size_y = %u.\n", + current->pps_pic_width_in_luma_samples, + ctb_size_y, min_cb_size_y); + return AVERROR_INVALIDDATA; + } + } + + flag(pps_conformance_window_flag); + if (current->pps_pic_width_in_luma_samples == + sps->sps_pic_width_max_in_luma_samples && + current->pps_pic_height_in_luma_samples == + sps->sps_pic_height_max_in_luma_samples && + current->pps_conformance_window_flag) { + av_log(ctx->log_ctx, AV_LOG_ERROR, + "Conformance window flag should not true.\n"); + return AVERROR_INVALIDDATA; + } + + sub_width_c = h266_sub_width_c[sps->sps_chroma_format_idc]; + sub_height_c = h266_sub_height_c[sps->sps_chroma_format_idc]; + if (current->pps_conformance_window_flag) { + ue(pps_conf_win_left_offset, 0, current->pps_pic_width_in_luma_samples); + ue(pps_conf_win_right_offset, + 0, current->pps_pic_width_in_luma_samples); + ue(pps_conf_win_top_offset, 0, current->pps_pic_height_in_luma_samples); + ue(pps_conf_win_bottom_offset, + 0, current->pps_pic_height_in_luma_samples); + if (sub_width_c * + (current->pps_conf_win_left_offset + + current->pps_conf_win_right_offset) >= + current->pps_pic_width_in_luma_samples || + sub_height_c * + (current->pps_conf_win_top_offset + + current->pps_conf_win_bottom_offset) >= + current->pps_pic_height_in_luma_samples) { + av_log(ctx->log_ctx, AV_LOG_ERROR, + "Invalid pps conformance window: (%u, %u, %u, %u), " + "resolution is %ux%u, sub wxh is %ux%u.\n", + current->pps_conf_win_left_offset, + current->pps_conf_win_right_offset, + current->pps_conf_win_top_offset, + current->pps_conf_win_bottom_offset, + current->pps_pic_width_in_luma_samples, + current->pps_pic_height_in_luma_samples, + sub_width_c, sub_height_c); + return AVERROR_INVALIDDATA; + } + } else { + if (current->pps_pic_width_in_luma_samples == + sps->sps_pic_width_max_in_luma_samples && + current->pps_pic_height_in_luma_samples == + sps->sps_pic_height_max_in_luma_samples) { + infer(pps_conf_win_left_offset, sps->sps_conf_win_left_offset); + infer(pps_conf_win_right_offset, sps->sps_conf_win_right_offset); + infer(pps_conf_win_top_offset, sps->sps_conf_win_top_offset); + infer(pps_conf_win_bottom_offset, sps->sps_conf_win_bottom_offset); + } else { + infer(pps_conf_win_left_offset, 0); + infer(pps_conf_win_right_offset, 0); + infer(pps_conf_win_top_offset, 0); + infer(pps_conf_win_bottom_offset, 0); + } + + } + + flag(pps_scaling_window_explicit_signalling_flag); + if (!sps->sps_ref_pic_resampling_enabled_flag && + current->pps_scaling_window_explicit_signalling_flag) { + av_log(ctx->log_ctx, AV_LOG_ERROR, + "Invalid data: sps_ref_pic_resampling_enabled_flag is false, " + "but pps_scaling_window_explicit_signalling_flag is true.\n"); + return AVERROR_INVALIDDATA; + } + if (current->pps_scaling_window_explicit_signalling_flag) { + se(pps_scaling_win_left_offset, + -current->pps_pic_width_in_luma_samples * 15 / sub_width_c, + current->pps_pic_width_in_luma_samples / sub_width_c); + se(pps_scaling_win_right_offset, + -current->pps_pic_width_in_luma_samples * 15 / sub_width_c, + current->pps_pic_width_in_luma_samples / sub_width_c); + se(pps_scaling_win_top_offset, + -current->pps_pic_height_in_luma_samples * 15 / sub_height_c, + current->pps_pic_height_in_luma_samples / sub_height_c); + se(pps_scaling_win_bottom_offset, + -current->pps_pic_height_in_luma_samples * 15 / sub_height_c, + current->pps_pic_height_in_luma_samples / sub_height_c); + } else { + infer(pps_scaling_win_left_offset, current->pps_conf_win_left_offset); + infer(pps_scaling_win_right_offset, current->pps_conf_win_right_offset); + infer(pps_scaling_win_top_offset, current->pps_conf_win_top_offset); + infer(pps_scaling_win_bottom_offset, current->pps_conf_win_bottom_offset); + } + + flag(pps_output_flag_present_flag); + flag(pps_no_pic_partition_flag); + flag(pps_subpic_id_mapping_present_flag); + + if (current->pps_subpic_id_mapping_present_flag) { + if (!current->pps_no_pic_partition_flag) { + ue(pps_num_subpics_minus1, + sps->sps_num_subpics_minus1, sps->sps_num_subpics_minus1); + } else { + infer(pps_num_subpics_minus1, 0); + } + ue(pps_subpic_id_len_minus1, sps->sps_subpic_id_len_minus1, + sps->sps_subpic_id_len_minus1); + for (i = 0; i <= current->pps_num_subpics_minus1; i++) { + ubs(sps->sps_subpic_id_len_minus1 + 1, pps_subpic_id[i], 1, i); + } + } + + pic_width_in_ctbs_y = AV_CEIL_RSHIFT + (current->pps_pic_width_in_luma_samples, (sps->sps_log2_ctu_size_minus5 + 5)); + pic_height_in_ctbs_y = AV_CEIL_RSHIFT( + current->pps_pic_height_in_luma_samples,(sps->sps_log2_ctu_size_minus5 + 5)); + if (!current->pps_no_pic_partition_flag) { + unsigned int exp_tile_width = 0, exp_tile_height = 0; + unsigned int unified_size, remaining_size; + + u(2, pps_log2_ctu_size_minus5, + sps->sps_log2_ctu_size_minus5, sps->sps_log2_ctu_size_minus5); + ue(pps_num_exp_tile_columns_minus1, + 0, FFMIN(pic_width_in_ctbs_y - 1, VVC_MAX_TILE_COLUMNS - 1)); + ue(pps_num_exp_tile_rows_minus1, + 0, FFMIN(pic_height_in_ctbs_y - 1, VVC_MAX_TILE_ROWS - 1)); + + for (i = 0; i <= current->pps_num_exp_tile_columns_minus1; i++) { + ues(pps_tile_column_width_minus1[i], + 0, pic_width_in_ctbs_y - exp_tile_width - 1, 1, i); + exp_tile_width += current->pps_tile_column_width_minus1[i] + 1; + } + for (i = 0; i <= current->pps_num_exp_tile_rows_minus1; i++) { + ues(pps_tile_row_height_minus1[i], + 0, pic_height_in_ctbs_y - 1, 1, i); + exp_tile_height += current->pps_tile_row_height_minus1[i] + 1; + } + + remaining_size = pic_width_in_ctbs_y; + for (i = 0; i <= current->pps_num_exp_tile_columns_minus1; i++) { + if (current->pps_tile_column_width_minus1[i] >= remaining_size) { + av_log(ctx->log_ctx, AV_LOG_ERROR, + "Tile column width(%d) exceeds picture width\n",i); + return AVERROR_INVALIDDATA; + } + remaining_size -= (current->pps_tile_column_width_minus1[i] + 1); + } + unified_size = (i == 0 ? pic_width_in_ctbs_y : + (current->pps_tile_column_width_minus1[i - 1] + 1)); + while (remaining_size > 0) { + if (current->num_tile_columns > VVC_MAX_TILE_COLUMNS) { + av_log(ctx->log_ctx, AV_LOG_ERROR, + "NumTileColumns(%d) > than VVC_MAX_TILE_COLUMNS(%d)\n", + current->num_tile_columns, VVC_MAX_TILE_COLUMNS); + return AVERROR_INVALIDDATA; + } + unified_size = FFMIN(remaining_size, unified_size); + current->pps_tile_column_width_minus1[i] = unified_size - 1; + remaining_size -= unified_size; + i++; + } + current->num_tile_columns = i; + if (current->num_tile_columns > VVC_MAX_TILE_COLUMNS) { + av_log(ctx->log_ctx, AV_LOG_ERROR, + "NumTileColumns(%d) > than VVC_MAX_TILE_COLUMNS(%d)\n", + current->num_tile_columns, VVC_MAX_TILE_COLUMNS); + return AVERROR_INVALIDDATA; + } + + remaining_size = pic_height_in_ctbs_y; + for (i = 0; i <= current->pps_num_exp_tile_rows_minus1; i++) { + if (current->pps_tile_row_height_minus1[i] >= remaining_size) { + av_log(ctx->log_ctx, AV_LOG_ERROR, + "Tile row height(%d) exceeds picture height\n",i); + return AVERROR_INVALIDDATA; + } + remaining_size -= (current->pps_tile_row_height_minus1[i] + 1); + } + unified_size = (i == 0 ? pic_height_in_ctbs_y : + (current->pps_tile_row_height_minus1[i - 1] + 1)); + + while (remaining_size > 0) { + unified_size = FFMIN(remaining_size, unified_size); + current->pps_tile_row_height_minus1[i] = unified_size - 1; + remaining_size -= unified_size; + i++; + } + current->num_tile_rows=i; + if (current->num_tile_rows > VVC_MAX_TILE_ROWS) { + av_log(ctx->log_ctx, AV_LOG_ERROR, + "NumTileRows(%d) > than VVC_MAX_TILE_ROWS(%d)\n", + current->num_tile_rows, VVC_MAX_TILE_ROWS); + return AVERROR_INVALIDDATA; + } + + current->num_tiles_in_pic = current->num_tile_columns * + current->num_tile_rows; + if (current->num_tiles_in_pic > VVC_MAX_TILES_PER_AU) { + av_log(ctx->log_ctx, AV_LOG_ERROR, + "NumTilesInPic(%d) > than VVC_MAX_TILES_PER_AU(%d)\n", + current->num_tiles_in_pic, VVC_MAX_TILES_PER_AU); + return AVERROR_INVALIDDATA; + } + + if (current->num_tiles_in_pic > 1) { + flag(pps_loop_filter_across_tiles_enabled_flag); + flag(pps_rect_slice_flag); + } else { + infer(pps_loop_filter_across_tiles_enabled_flag, 0); + infer(pps_rect_slice_flag, 1); + } + if (current->pps_rect_slice_flag) + flag(pps_single_slice_per_subpic_flag); + else + infer(pps_single_slice_per_subpic_flag, 1); + if (current->pps_rect_slice_flag && + !current->pps_single_slice_per_subpic_flag) { + int j; + uint16_t tile_idx = 0, tile_x, tile_y, ctu_x, ctu_y; + uint16_t slice_top_left_ctu_x[VVC_MAX_SLICES]; + uint16_t slice_top_left_ctu_y[VVC_MAX_SLICES]; + ue(pps_num_slices_in_pic_minus1, 0, VVC_MAX_SLICES - 1); + if (current->pps_num_slices_in_pic_minus1 > 1) + flag(pps_tile_idx_delta_present_flag); + else + infer(pps_tile_idx_delta_present_flag, 0); + for (i = 0; i < current->pps_num_slices_in_pic_minus1; i++) { + tile_x = tile_idx % current->num_tile_columns; + tile_y = tile_idx / current->num_tile_columns; + if (tile_x != current->num_tile_columns - 1) { + ues(pps_slice_width_in_tiles_minus1[i], + 0, current->num_tile_columns - 1, 1, i); + } else { + infer(pps_slice_width_in_tiles_minus1[i], 0); + } + if (tile_y != current->num_tile_rows - 1 && + (current->pps_tile_idx_delta_present_flag || tile_x == 0)) { + ues(pps_slice_height_in_tiles_minus1[i], + 0, current->num_tile_rows - 1, 1, i); + } else { + if (tile_y == current->num_tile_rows - 1) + infer(pps_slice_height_in_tiles_minus1[i], 0); + else + infer(pps_slice_height_in_tiles_minus1[i], + current->pps_slice_height_in_tiles_minus1[i - 1]); + } + + ctu_x = ctu_y = 0; + for (j = 0; j < tile_x; j++) { + ctu_x += current->pps_tile_column_width_minus1[j] + 1; + } + for (j = 0; j < tile_y; j++) { + ctu_y += current->pps_tile_row_height_minus1[j] + 1; + } + if (current->pps_slice_width_in_tiles_minus1[i] == 0 && + current->pps_slice_height_in_tiles_minus1[i] == 0 && + current->pps_tile_row_height_minus1[tile_y] > 0) { + int num_slices_in_tile, + uniform_slice_height, remaining_height_in_ctbs_y; + remaining_height_in_ctbs_y = + current->pps_tile_row_height_minus1[tile_y] + 1; + ues(pps_num_exp_slices_in_tile[i], + 0, current->pps_tile_row_height_minus1[tile_y], 1, i); + if (current->pps_num_exp_slices_in_tile[i] == 0) { + num_slices_in_tile = 1; + slice_top_left_ctu_x[i] = ctu_x; + slice_top_left_ctu_y[i] = ctu_y; + } else { + uint16_t slice_height_in_ctus; + for (j = 0; j < current->pps_num_exp_slices_in_tile[i]; + j++) { + ues(pps_exp_slice_height_in_ctus_minus1[i][j], 0, + current->pps_tile_row_height_minus1[tile_y], 2, + i, j); + slice_height_in_ctus = + current-> + pps_exp_slice_height_in_ctus_minus1[i][j] + 1; + + current->slice_height_in_ctus[i + j] = + slice_height_in_ctus; + slice_top_left_ctu_x[i + j] = ctu_x; + slice_top_left_ctu_y[i + j] = ctu_y; + ctu_y += slice_height_in_ctus; + + remaining_height_in_ctbs_y -= slice_height_in_ctus; + } + uniform_slice_height = 1 + + (j == 0 ? current->pps_tile_row_height_minus1[tile_y] : + current->pps_exp_slice_height_in_ctus_minus1[i][j-1]); + while (remaining_height_in_ctbs_y > uniform_slice_height) { + current->slice_height_in_ctus[i + j] = + uniform_slice_height; + slice_top_left_ctu_x[i + j] = ctu_x; + slice_top_left_ctu_y[i + j] = ctu_y; + ctu_y += uniform_slice_height; + + remaining_height_in_ctbs_y -= uniform_slice_height; + j++; + } + if (remaining_height_in_ctbs_y > 0) { + current->slice_height_in_ctus[i + j] = + remaining_height_in_ctbs_y; + slice_top_left_ctu_x[i + j] = ctu_x; + slice_top_left_ctu_y[i + j] = ctu_y; + j++; + } + num_slices_in_tile = j; + } + i += num_slices_in_tile - 1; + } else { + uint16_t height = 0; + infer(pps_num_exp_slices_in_tile[i], 0); + for (j = 0; + j <= current->pps_slice_height_in_tiles_minus1[i]; + j++) { + height += + current->pps_tile_row_height_minus1[tile_y + j] + 1; + } + current->slice_height_in_ctus[i] = height; + + slice_top_left_ctu_x[i] = ctu_x; + slice_top_left_ctu_y[i] = ctu_y; + } + if (i < current->pps_num_slices_in_pic_minus1) { + if (current->pps_tile_idx_delta_present_flag) { + ses(pps_tile_idx_delta_val[i], + -current->num_tiles_in_pic + 1, + current->num_tiles_in_pic - 1, 1, i); + if (current->pps_tile_idx_delta_val[i] == 0) { + av_log(ctx->log_ctx, AV_LOG_ERROR, + "pps_tile_idx_delta_val[i] shall not be equal to 0.\n"); + } + tile_idx += current->pps_tile_idx_delta_val[i]; + } else { + infer(pps_tile_idx_delta_val[i], 0); + tile_idx += + current->pps_slice_width_in_tiles_minus1[i] + 1; + if (tile_idx % current->num_tile_columns == 0) { + tile_idx += + current->pps_slice_height_in_tiles_minus1[i] * + current->num_tile_columns; + } + } + } + } + if (i == current->pps_num_slices_in_pic_minus1) { + uint16_t height = 0; + + tile_x = tile_idx % current->num_tile_columns; + tile_y = tile_idx / current->num_tile_columns; + + ctu_x = 0, ctu_y = 0; + for (j = 0; j < tile_x; j++) { + ctu_x += current->pps_tile_column_width_minus1[j] + 1; + } + for (j = 0; j < tile_y; j++) { + ctu_y += current->pps_tile_row_height_minus1[j] + 1; + } + slice_top_left_ctu_x[i] = ctu_x; + slice_top_left_ctu_y[i] = ctu_y; + + current->pps_slice_width_in_tiles_minus1[i] = + current->num_tile_columns - tile_x - 1; + current->pps_slice_height_in_tiles_minus1[i] = + current->num_tile_rows - tile_y - 1; + + for (j = 0; j <= current->pps_slice_height_in_tiles_minus1[i]; + j++) { + height += + current->pps_tile_row_height_minus1[tile_y + j] + 1; + } + current->slice_height_in_ctus[i] = height; + + infer(pps_num_exp_slices_in_tile[i], 0); + } + //now, we got all slice information, let's resolve NumSlicesInSubpic + for (i = 0; i <= sps->sps_num_subpics_minus1; i++) { + current->num_slices_in_subpic[i] = 0; + for (j = 0; j <= current->pps_num_slices_in_pic_minus1; j++) { + uint16_t pos_x = 0, pos_y = 0; + pos_x = slice_top_left_ctu_x[j]; + pos_y = slice_top_left_ctu_y[j]; + if ((pos_x >= sps->sps_subpic_ctu_top_left_x[i]) && + (pos_x < + sps->sps_subpic_ctu_top_left_x[i] + + sps->sps_subpic_width_minus1[i] + 1) && + (pos_y >= sps->sps_subpic_ctu_top_left_y[i]) && + (pos_y < sps->sps_subpic_ctu_top_left_y[i] + + sps->sps_subpic_height_minus1[i] + 1)) { + current->num_slices_in_subpic[i]++; + } + } + } + } else { + if (current->pps_no_pic_partition_flag) + infer(pps_num_slices_in_pic_minus1, 0); + else if (current->pps_single_slice_per_subpic_flag) + infer(pps_num_slices_in_pic_minus1, + sps->sps_num_subpics_minus1); + // else? + } + if (!current->pps_rect_slice_flag || + current->pps_single_slice_per_subpic_flag || + current->pps_num_slices_in_pic_minus1 > 0) + flag(pps_loop_filter_across_slices_enabled_flag); + else + infer(pps_loop_filter_across_slices_enabled_flag, 0); + } else { + infer(pps_num_exp_tile_columns_minus1, 0); + infer(pps_tile_column_width_minus1[0], pic_width_in_ctbs_y - 1); + infer(pps_num_exp_tile_rows_minus1, 0); + infer(pps_tile_row_height_minus1[0], pic_height_in_ctbs_y - 1); + infer(num_tile_columns, 1); + infer(num_tile_rows, 1); + infer(num_tiles_in_pic, 1); + } + + flag(pps_cabac_init_present_flag); + for (i = 0; i < 2; i++) + ues(pps_num_ref_idx_default_active_minus1[i], 0, 14, 1, i); + flag(pps_rpl1_idx_present_flag); + flag(pps_weighted_pred_flag); + flag(pps_weighted_bipred_flag); + flag(pps_ref_wraparound_enabled_flag); + if (current->pps_ref_wraparound_enabled_flag) { + ue(pps_pic_width_minus_wraparound_offset, + 0, (current->pps_pic_width_in_luma_samples / min_cb_size_y) + - (ctb_size_y / min_cb_size_y) - 2); + } + + qp_bd_offset = 6 * sps->sps_bitdepth_minus8; + se(pps_init_qp_minus26, -(26 + qp_bd_offset), 37); + flag(pps_cu_qp_delta_enabled_flag); + flag(pps_chroma_tool_offsets_present_flag); + if (current->pps_chroma_tool_offsets_present_flag) { + se(pps_cb_qp_offset, -12, 12); + se(pps_cr_qp_offset, -12, 12); + flag(pps_joint_cbcr_qp_offset_present_flag); + if (current->pps_joint_cbcr_qp_offset_present_flag) + se(pps_joint_cbcr_qp_offset_value, -12, 12); + else + infer(pps_joint_cbcr_qp_offset_value, 0); + flag(pps_slice_chroma_qp_offsets_present_flag); + flag(pps_cu_chroma_qp_offset_list_enabled_flag); + if (current->pps_cu_chroma_qp_offset_list_enabled_flag) { + ue(pps_chroma_qp_offset_list_len_minus1, 0, 5); + for (i = 0; i <= current->pps_chroma_qp_offset_list_len_minus1; i++) { + ses(pps_cb_qp_offset_list[i], -12, 12, 1, i); + ses(pps_cr_qp_offset_list[i], -12, 12, 1, i); + if (current->pps_joint_cbcr_qp_offset_present_flag) + ses(pps_joint_cbcr_qp_offset_list[i], -12, 12, 1, i); + else + infer(pps_joint_cbcr_qp_offset_list[i], 0); + } + } + } else { + infer(pps_cb_qp_offset, 0); + infer(pps_cr_qp_offset, 0); + infer(pps_joint_cbcr_qp_offset_present_flag, 0); + infer(pps_joint_cbcr_qp_offset_value, 0); + infer(pps_slice_chroma_qp_offsets_present_flag, 0); + infer(pps_cu_chroma_qp_offset_list_enabled_flag, 0); + } + flag(pps_deblocking_filter_control_present_flag); + if (current->pps_deblocking_filter_control_present_flag) { + flag(pps_deblocking_filter_override_enabled_flag); + flag(pps_deblocking_filter_disabled_flag); + if (!current->pps_no_pic_partition_flag && + current->pps_deblocking_filter_override_enabled_flag) + flag(pps_dbf_info_in_ph_flag); + else + infer(pps_dbf_info_in_ph_flag, 0); + if (!current->pps_deblocking_filter_disabled_flag) { + se(pps_luma_beta_offset_div2, -12, 12); + se(pps_luma_tc_offset_div2, -12, 12); + if (current->pps_chroma_tool_offsets_present_flag) { + se(pps_cb_beta_offset_div2, -12, 12); + se(pps_cb_tc_offset_div2, -12, 12); + se(pps_cr_beta_offset_div2, -12, 12); + se(pps_cr_tc_offset_div2, -12, 12); + } else { + infer(pps_cb_beta_offset_div2, + current->pps_luma_beta_offset_div2); + infer(pps_cb_tc_offset_div2, current->pps_luma_tc_offset_div2); + infer(pps_cr_beta_offset_div2, + current->pps_luma_beta_offset_div2); + infer(pps_cr_tc_offset_div2, current->pps_luma_tc_offset_div2); + } + } else { + infer(pps_luma_beta_offset_div2, 0); + infer(pps_luma_tc_offset_div2, 0); + infer(pps_cb_beta_offset_div2, 0); + infer(pps_cb_tc_offset_div2, 0); + infer(pps_cr_beta_offset_div2, 0); + infer(pps_cr_tc_offset_div2, 0); + } + } else { + infer(pps_deblocking_filter_override_enabled_flag, 0); + infer(pps_deblocking_filter_disabled_flag, 0); + infer(pps_dbf_info_in_ph_flag, 0); + infer(pps_luma_beta_offset_div2, 0); + infer(pps_luma_tc_offset_div2, 0); + infer(pps_cb_beta_offset_div2, 0); + infer(pps_cb_tc_offset_div2, 0); + infer(pps_cr_beta_offset_div2, 0); + infer(pps_cr_tc_offset_div2, 0); + } + + if (!current->pps_no_pic_partition_flag) { + flag(pps_rpl_info_in_ph_flag); + flag(pps_sao_info_in_ph_flag); + flag(pps_alf_info_in_ph_flag); + if ((current->pps_weighted_pred_flag || + current->pps_weighted_bipred_flag) && + current->pps_rpl_info_in_ph_flag) + flag(pps_wp_info_in_ph_flag); + flag(pps_qp_delta_info_in_ph_flag); + } + flag(pps_picture_header_extension_present_flag); + flag(pps_slice_header_extension_present_flag); + + flag(pps_extension_flag); + if (current->pps_extension_flag) + CHECK(FUNC(extension_data) (ctx, rw, ¤t->extension_data)); + + CHECK(FUNC(rbsp_trailing_bits) (ctx, rw)); + return 0; +} + +static int FUNC(aud) (CodedBitstreamContext *ctx, RWContext *rw, + H266RawAUD *current) +{ + int err; + + HEADER("Access Unit Delimiter"); + + CHECK(FUNC(nal_unit_header) (ctx, rw, + ¤t->nal_unit_header, VVC_AUD_NUT)); + + flag(aud_irap_or_gdr_flag); + u(3, aud_pic_type, 0, 2); + + CHECK(FUNC(rbsp_trailing_bits) (ctx, rw)); + return 0; +} + +static int FUNC(pred_weight_table) (CodedBitstreamContext *ctx, RWContext *rw, + const H266RawSPS *sps, + const H266RawPPS *pps, + const H266RefPicLists *ref_lists, + uint8_t num_ref_idx_active[2], + H266RawPredWeightTable *current) +{ + int err, i, j; + uint8_t num_weights_l0, num_weights_l1; + ue(luma_log2_weight_denom, 0, 7); + if (sps->sps_chroma_format_idc != 0) { + se(delta_chroma_log2_weight_denom, + -current->luma_log2_weight_denom, + 7 - current->luma_log2_weight_denom); + } else { + infer(delta_chroma_log2_weight_denom, 0); + } + if (pps->pps_wp_info_in_ph_flag) + ue(num_l0_weights, 0, + FFMIN(15, ref_lists->rpl_ref_list[0].num_ref_entries)); + else + infer(num_l0_weights, 0); + num_weights_l0 = pps->pps_wp_info_in_ph_flag ? + current->num_l0_weights : num_ref_idx_active[0]; + for (i = 0; i < num_weights_l0; i++) { + flags(luma_weight_l0_flag[i], 1, i); + } + if (sps->sps_chroma_format_idc != 0) { + for (i = 0; i < num_weights_l0; i++) + flags(chroma_weight_l0_flag[i], 1, i); + } + for (i = 0; i < num_weights_l0; i++) { + if (current->luma_weight_l0_flag[i]) { + ses(delta_luma_weight_l0[i], -128, 127, 1, i); + ses(luma_offset_l0[i], -128, 127, 1, i); + } else { + infer(delta_luma_weight_l0[i], 0); + infer(luma_offset_l0[i], 0); + } + if (current->chroma_weight_l0_flag[i]) { + for (j = 0; j < 2; j++) { + ses(delta_chroma_weight_l0[i][j], -128, 127, 2, i, j); + ses(delta_chroma_offset_l0[i][j], -4 * 128, 4 * 127, 2, i, j); + } + } + } + + if (pps->pps_weighted_bipred_flag && pps->pps_wp_info_in_ph_flag && + ref_lists->rpl_ref_list[1].num_ref_entries > 0) { + ue(num_l1_weights, 0, + FFMIN(15, ref_lists->rpl_ref_list[1].num_ref_entries)); + } + if (!pps->pps_weighted_bipred_flag || + (pps->pps_wp_info_in_ph_flag && + ref_lists->rpl_ref_list[1].num_ref_entries == 0)) { + num_weights_l1 = 0; + } else if (pps->pps_wp_info_in_ph_flag) { + num_weights_l1 = current->num_l1_weights; + } else { + num_weights_l1 = num_ref_idx_active[1]; + } + + for (i = 0; i < num_weights_l1; i++) + flags(luma_weight_l1_flag[i], 1, i); + if (sps->sps_chroma_format_idc != 0) { + for (i = 0; i < num_weights_l1; i++) + flags(chroma_weight_l1_flag[i], 1, i); + } + for (i = 0; i < num_weights_l1; i++) { + if (current->luma_weight_l1_flag[i]) { + ses(delta_luma_weight_l1[i], -128, 127, 1, i); + ses(luma_offset_l1[i], -128, 127, 1, i); + } else { + infer(delta_luma_weight_l1[i], 0); + infer(luma_offset_l1[i], 0); + } + if (current->chroma_weight_l1_flag[i]) { + for (j = 0; j < 2; j++) { + ses(delta_chroma_weight_l1[i][j], -128, 127, 2, i, j); + ses(delta_chroma_offset_l1[i][j], -4 * 128, 4 * 127, 2, i, j); + } + } + } + return 0; +} + +static int FUNC(picture_header) (CodedBitstreamContext *ctx, RWContext *rw, + H266RawPH *current){ + CodedBitstreamH266Context *h266 = ctx->priv_data; + const H266RawVPS *vps; + const H266RawSPS *sps; + const H266RawPPS *pps; + int err, i; + unsigned int ctb_log2_size_y, min_cb_log2_size_y, + min_qt_log2_size_intra_y, min_qt_log2_size_inter_y; + uint8_t qp_bd_offset; + + flag(ph_gdr_or_irap_pic_flag); + flag(ph_non_ref_pic_flag); + if (current->ph_gdr_or_irap_pic_flag) + flag(ph_gdr_pic_flag); + else + infer(ph_gdr_pic_flag, 0); + flag(ph_inter_slice_allowed_flag); + if (current->ph_inter_slice_allowed_flag) + flag(ph_intra_slice_allowed_flag); + else + infer(ph_intra_slice_allowed_flag, 1); + ue(ph_pic_parameter_set_id, 0, VVC_MAX_PPS_COUNT - 1); + pps = h266->pps[current->ph_pic_parameter_set_id]; + if (!pps) { + av_log(ctx->log_ctx, AV_LOG_ERROR, "PPS id %d not available.\n", + current->ph_pic_parameter_set_id); + return AVERROR_INVALIDDATA; + } + sps = h266->sps[pps->pps_seq_parameter_set_id]; + if (!sps) { + av_log(ctx->log_ctx, AV_LOG_ERROR, "SPS id %d not available.\n", + pps->pps_seq_parameter_set_id); + return AVERROR_INVALIDDATA; + } + vps = h266->vps[sps->sps_video_parameter_set_id]; + if (!vps) { + av_log(ctx->log_ctx, AV_LOG_ERROR, "VPS id %d not available.\n", + sps->sps_video_parameter_set_id); + return AVERROR_INVALIDDATA; + } + + ub(sps->sps_log2_max_pic_order_cnt_lsb_minus4 + 4, ph_pic_order_cnt_lsb); + if (current->ph_gdr_pic_flag) + ue(ph_recovery_poc_cnt, 0, + 1 << (sps->sps_log2_max_pic_order_cnt_lsb_minus4 + 4)); + + for (i = 0; i < sps->sps_num_extra_ph_bytes * 8; i++) { + if (sps->sps_extra_ph_bit_present_flag[i]) + flags(ph_extra_bit[i], 1, i); + } + if (sps->sps_poc_msb_cycle_flag) { + flag(ph_poc_msb_cycle_present_flag); + if (current->ph_poc_msb_cycle_present_flag) + ub(sps->sps_poc_msb_cycle_len_minus1 + 1, ph_poc_msb_cycle_val); + } + if (sps->sps_alf_enabled_flag && pps->pps_alf_info_in_ph_flag) { + flag(ph_alf_enabled_flag); + if (current->ph_alf_enabled_flag) { + + ub(3, ph_num_alf_aps_ids_luma); + for (i = 0; i < current->ph_num_alf_aps_ids_luma; i++) + ubs(3, ph_alf_aps_id_luma[i], 1, i); + + if (sps->sps_chroma_format_idc != 0) { + flag(ph_alf_cb_enabled_flag); + flag(ph_alf_cr_enabled_flag); + } else { + infer(ph_alf_cb_enabled_flag, 0); + infer(ph_alf_cr_enabled_flag, 0); + } + + if (current->ph_alf_cb_enabled_flag + || current->ph_alf_cr_enabled_flag) { + ub(3, ph_alf_aps_id_chroma); + } + + if (sps->sps_ccalf_enabled_flag) { + flag(ph_alf_cc_cb_enabled_flag); + if (current->ph_alf_cc_cb_enabled_flag) + ub(3, ph_alf_cc_cb_aps_id); + flag(ph_alf_cc_cr_enabled_flag); + if (current->ph_alf_cc_cr_enabled_flag) + ub(3, ph_alf_cc_cr_aps_id); + } + } + } else { + infer(ph_alf_enabled_flag, 0); + } + if (sps->sps_lmcs_enabled_flag) { + flag(ph_lmcs_enabled_flag); + if (current->ph_lmcs_enabled_flag) { + ub(2, ph_lmcs_aps_id); + if (sps->sps_chroma_format_idc != 0) + flag(ph_chroma_residual_scale_flag); + else + infer(ph_chroma_residual_scale_flag, 0); + } + } else { + infer(ph_lmcs_enabled_flag, 0); + infer(ph_chroma_residual_scale_flag, 0); + } + + if (sps->sps_explicit_scaling_list_enabled_flag) { + flag(ph_explicit_scaling_list_enabled_flag); + if (current->ph_explicit_scaling_list_enabled_flag) { + //todo: check the ph_scaling_list_aps_id range, when aps ready + ub(3, ph_scaling_list_aps_id); + } + } else { + infer(ph_explicit_scaling_list_enabled_flag, 0); + } + if (sps->sps_virtual_boundaries_enabled_flag && + !sps->sps_virtual_boundaries_present_flag) { + flag(ph_virtual_boundaries_present_flag); + if (current->ph_virtual_boundaries_present_flag) { + ue(ph_num_ver_virtual_boundaries, + 0, pps->pps_pic_width_in_luma_samples <= 8 ? 0 : 3); + for (i = 0; i < current->ph_num_ver_virtual_boundaries; i++) { + ues(ph_virtual_boundary_pos_x_minus1[i], + 0, (pps->pps_pic_width_in_luma_samples + 7) / 8 - 2, 1, i); + } + ue(ph_num_hor_virtual_boundaries, + 0, pps->pps_pic_height_in_luma_samples <= 8 ? 0 : 3); + for (i = 0; i < current->ph_num_hor_virtual_boundaries; i++) { + ues(ph_virtual_boundary_pos_y_minus1[i], + 0, (pps->pps_pic_height_in_luma_samples + 7) / 8 - 2, 1, i); + } + } else { + infer(ph_num_ver_virtual_boundaries, 0); + infer(ph_num_hor_virtual_boundaries, 0); + } + } + if (pps->pps_output_flag_present_flag && !current->ph_non_ref_pic_flag) + flag(ph_pic_output_flag); + else + infer(ph_pic_output_flag, 1); + if (pps->pps_rpl_info_in_ph_flag) { + CHECK(FUNC(ref_pic_lists) + (ctx, rw, sps, pps, ¤t->ph_ref_pic_lists)); + } + if (sps->sps_partition_constraints_override_enabled_flag) + flag(ph_partition_constraints_override_flag); + else + infer(ph_partition_constraints_override_flag, 0); + + ctb_log2_size_y = sps->sps_log2_ctu_size_minus5 + 5; + min_cb_log2_size_y = sps->sps_log2_min_luma_coding_block_size_minus2 + 2; + if (current->ph_intra_slice_allowed_flag) { + if (current->ph_partition_constraints_override_flag) { + ue(ph_log2_diff_min_qt_min_cb_intra_slice_luma, + 0, FFMIN(6, ctb_log2_size_y) - min_cb_log2_size_y); + ue(ph_max_mtt_hierarchy_depth_intra_slice_luma, + 0, 2 * (ctb_log2_size_y - min_cb_log2_size_y)); + if (current->ph_max_mtt_hierarchy_depth_intra_slice_luma != 0) { + ue(ph_log2_diff_max_bt_min_qt_intra_slice_luma, + 0, ctb_log2_size_y - min_qt_log2_size_intra_y); + ue(ph_log2_diff_max_tt_min_qt_intra_slice_luma, + 0, FFMIN(6, ctb_log2_size_y) - min_qt_log2_size_intra_y); + } else { + infer(ph_log2_diff_max_bt_min_qt_intra_slice_luma, + sps->sps_log2_diff_max_bt_min_qt_intra_slice_luma); + infer(ph_log2_diff_max_tt_min_qt_intra_slice_luma, + sps->sps_log2_diff_max_tt_min_qt_intra_slice_luma); + } + if (sps->sps_qtbtt_dual_tree_intra_flag) { + ue(ph_log2_diff_min_qt_min_cb_intra_slice_chroma, + 0, FFMIN(6, ctb_log2_size_y) - min_cb_log2_size_y); + ue(ph_max_mtt_hierarchy_depth_intra_slice_chroma, + 0, 2 * (ctb_log2_size_y - min_cb_log2_size_y)); + if (sps->sps_max_mtt_hierarchy_depth_intra_slice_chroma != 0) { + unsigned int min_qt_log2_size_intra_c = + sps->sps_log2_diff_min_qt_min_cb_intra_slice_chroma + + min_cb_log2_size_y; + ue(ph_log2_diff_max_bt_min_qt_intra_slice_chroma, + 0, FFMIN(6, ctb_log2_size_y) - min_qt_log2_size_intra_c); + ue(ph_log2_diff_max_tt_min_qt_intra_slice_chroma, + 0, FFMIN(6, ctb_log2_size_y) - min_qt_log2_size_intra_c); + } else { + infer(ph_log2_diff_max_bt_min_qt_intra_slice_chroma, + sps->sps_log2_diff_max_bt_min_qt_intra_slice_chroma); + infer(ph_log2_diff_max_tt_min_qt_intra_slice_chroma, + sps->sps_log2_diff_max_tt_min_qt_intra_slice_chroma); + } + } + } else { + infer(ph_log2_diff_min_qt_min_cb_intra_slice_luma, + sps->sps_log2_diff_min_qt_min_cb_intra_slice_luma); + infer(ph_max_mtt_hierarchy_depth_intra_slice_luma, + sps->sps_max_mtt_hierarchy_depth_intra_slice_luma); + infer(ph_log2_diff_max_bt_min_qt_intra_slice_luma, + sps->sps_log2_diff_max_bt_min_qt_intra_slice_luma); + infer(ph_log2_diff_max_tt_min_qt_intra_slice_luma, + sps->sps_log2_diff_max_tt_min_qt_intra_slice_luma); + infer(ph_log2_diff_min_qt_min_cb_intra_slice_chroma, + sps->sps_log2_diff_min_qt_min_cb_intra_slice_chroma); + infer(ph_max_mtt_hierarchy_depth_intra_slice_chroma, + sps->sps_max_mtt_hierarchy_depth_intra_slice_chroma); + infer(ph_log2_diff_max_bt_min_qt_intra_slice_chroma, + sps->sps_log2_diff_max_bt_min_qt_intra_slice_chroma); + infer(ph_log2_diff_max_tt_min_qt_intra_slice_chroma, + sps->sps_log2_diff_max_tt_min_qt_intra_slice_chroma); + } + + min_qt_log2_size_intra_y = + current->ph_log2_diff_min_qt_min_cb_intra_slice_luma + + min_cb_log2_size_y; + if (pps->pps_cu_qp_delta_enabled_flag) + ue(ph_cu_qp_delta_subdiv_intra_slice, 0, + 2 * (ctb_log2_size_y - min_qt_log2_size_intra_y + + current->ph_max_mtt_hierarchy_depth_intra_slice_luma)); + else + infer(ph_cu_qp_delta_subdiv_intra_slice, 0); + + if (pps->pps_cu_chroma_qp_offset_list_enabled_flag) + ue(ph_cu_chroma_qp_offset_subdiv_intra_slice, 0, + 2 * (ctb_log2_size_y - min_qt_log2_size_intra_y + + current->ph_max_mtt_hierarchy_depth_intra_slice_luma)); + else + infer(ph_cu_chroma_qp_offset_subdiv_intra_slice, 0); + } + if (current->ph_inter_slice_allowed_flag) { + if (current->ph_partition_constraints_override_flag) { + ue(ph_log2_diff_min_qt_min_cb_inter_slice, + 0, FFMIN(6, ctb_log2_size_y) - min_cb_log2_size_y); + min_qt_log2_size_inter_y = + current->ph_log2_diff_min_qt_min_cb_inter_slice + + min_cb_log2_size_y; + ue(ph_max_mtt_hierarchy_depth_inter_slice, 0, + 2 * (ctb_log2_size_y - min_cb_log2_size_y)); + if (current->ph_max_mtt_hierarchy_depth_inter_slice != 0) { + ue(ph_log2_diff_max_bt_min_qt_inter_slice, + 0, ctb_log2_size_y - min_qt_log2_size_inter_y); + ue(ph_log2_diff_max_tt_min_qt_inter_slice, + 0, FFMIN(6, ctb_log2_size_y) - min_qt_log2_size_inter_y); + } + } else { + infer(ph_log2_diff_min_qt_min_cb_inter_slice, + sps->sps_log2_diff_min_qt_min_cb_inter_slice); + min_qt_log2_size_inter_y = + current->ph_log2_diff_min_qt_min_cb_inter_slice + + min_cb_log2_size_y; + infer(ph_max_mtt_hierarchy_depth_inter_slice, + sps->sps_max_mtt_hierarchy_depth_inter_slice); + infer(ph_log2_diff_max_bt_min_qt_inter_slice, + sps->sps_log2_diff_max_bt_min_qt_inter_slice); + infer(ph_log2_diff_max_tt_min_qt_inter_slice, + sps->sps_log2_diff_max_tt_min_qt_inter_slice); + } + + if (pps->pps_cu_qp_delta_enabled_flag) + ue(ph_cu_qp_delta_subdiv_inter_slice, 0, + 2 * (ctb_log2_size_y - min_qt_log2_size_inter_y + + current->ph_max_mtt_hierarchy_depth_inter_slice)); + else + infer(ph_cu_qp_delta_subdiv_inter_slice, 0); + + if (pps->pps_cu_chroma_qp_offset_list_enabled_flag) + ue(ph_cu_chroma_qp_offset_subdiv_inter_slice, 0, + 2 * (ctb_log2_size_y - min_qt_log2_size_inter_y + + current->ph_max_mtt_hierarchy_depth_inter_slice)); + else + infer(ph_cu_chroma_qp_offset_subdiv_inter_slice, 0); + if (sps->sps_temporal_mvp_enabled_flag) { + flag(ph_temporal_mvp_enabled_flag); + if (current->ph_temporal_mvp_enabled_flag && + pps->pps_rpl_info_in_ph_flag) { + if (current->ph_ref_pic_lists.rpl_ref_list[1].num_ref_entries > 0) + flag(ph_collocated_from_l0_flag); + else + infer(ph_collocated_from_l0_flag, 1); + if ((current->ph_collocated_from_l0_flag && + current->ph_ref_pic_lists.rpl_ref_list[0].num_ref_entries > 1) + || (!current->ph_collocated_from_l0_flag && + current->ph_ref_pic_lists.rpl_ref_list[1].num_ref_entries > 1)) { + unsigned int idx = + current->ph_collocated_from_l0_flag ? 0 : 1; + ue(ph_collocated_ref_idx, 0, + current->ph_ref_pic_lists.rpl_ref_list[idx]. + num_ref_entries - 1); + } else { + infer(ph_collocated_ref_idx, 0); + } + } + } + if (sps->sps_mmvd_fullpel_only_enabled_flag) + flag(ph_mmvd_fullpel_only_flag); + else + infer(ph_mmvd_fullpel_only_flag, 0); + if (!pps->pps_rpl_info_in_ph_flag || + current->ph_ref_pic_lists.rpl_ref_list[1].num_ref_entries > 0) { + flag(ph_mvd_l1_zero_flag); + if (sps->sps_bdof_control_present_in_ph_flag) { + flag(ph_bdof_disabled_flag); + } else { + if (!sps->sps_bdof_control_present_in_ph_flag) + infer(ph_bdof_disabled_flag, + 1 - sps->sps_bdof_enabled_flag); + else + infer(ph_bdof_disabled_flag, 1); + } + if (sps->sps_dmvr_control_present_in_ph_flag) { + flag(ph_dmvr_disabled_flag); + } else { + if (!sps->sps_dmvr_control_present_in_ph_flag) + infer(ph_dmvr_disabled_flag, + 1 - sps->sps_dmvr_enabled_flag); + else + infer(ph_dmvr_disabled_flag, 1); + } + } else { + infer(ph_mvd_l1_zero_flag, 1); + } + if (sps->sps_prof_control_present_in_ph_flag) + flag(ph_prof_disabled_flag); + else + infer(ph_prof_disabled_flag, !sps->sps_affine_prof_enabled_flag); + if ((pps->pps_weighted_pred_flag || + pps->pps_weighted_bipred_flag) && pps->pps_wp_info_in_ph_flag) { + + // if pps->pps_wp_info_in_ph_fla == 1 + // pred_weight_table will not use num_ref_idx_active + uint8_t num_ref_idx_active[2] = { 0, 0 }; + CHECK(FUNC(pred_weight_table) + (ctx, rw, sps, pps, ¤t->ph_ref_pic_lists, + num_ref_idx_active, ¤t->ph_pred_weight_table)); + } + } + + qp_bd_offset = 6 * sps->sps_bitdepth_minus8; + if (pps->pps_qp_delta_info_in_ph_flag) + se(ph_qp_delta, -qp_bd_offset - (26 + pps->pps_init_qp_minus26), + 63 - (26 + pps->pps_init_qp_minus26)); + + if (sps->sps_joint_cbcr_enabled_flag) + flag(ph_joint_cbcr_sign_flag); + else + infer(ph_joint_cbcr_sign_flag, 0); + if (sps->sps_sao_enabled_flag && pps->pps_sao_info_in_ph_flag) { + flag(ph_sao_luma_enabled_flag); + if (sps->sps_chroma_format_idc != 0) + flag(ph_sao_chroma_enabled_flag); + else + infer(ph_sao_chroma_enabled_flag, 0); + } else { + infer(ph_sao_luma_enabled_flag, 0); + infer(ph_sao_chroma_enabled_flag, 0); + } + + if (pps->pps_dbf_info_in_ph_flag) { + flag(ph_deblocking_params_present_flag); + if (current->ph_deblocking_params_present_flag) { + if (!pps->pps_deblocking_filter_disabled_flag) { + flag(ph_deblocking_filter_disabled_flag); + } else { + if (pps->pps_deblocking_filter_disabled_flag && + current->ph_deblocking_params_present_flag) { + infer(ph_deblocking_filter_disabled_flag, 0); + } else { + infer(ph_deblocking_filter_disabled_flag, + pps->pps_deblocking_filter_disabled_flag); + } + } + if (!current->ph_deblocking_filter_disabled_flag) { + se(ph_luma_beta_offset_div2, -12, 12); + se(ph_luma_tc_offset_div2, -12, 12); + if (pps->pps_chroma_tool_offsets_present_flag) { + se(ph_cb_beta_offset_div2, -12, 12); + se(ph_cb_tc_offset_div2, -12, 12); + se(ph_cr_beta_offset_div2, -12, 12); + se(ph_cr_tc_offset_div2, -12, 12); + } else { + infer(ph_cb_beta_offset_div2, + current->ph_luma_beta_offset_div2); + infer(ph_cb_tc_offset_div2, + current->ph_luma_tc_offset_div2); + infer(ph_cr_beta_offset_div2, + current->ph_luma_beta_offset_div2); + infer(ph_cr_tc_offset_div2, + current->ph_luma_tc_offset_div2); + } + } else { + infer(ph_luma_beta_offset_div2, pps->pps_luma_beta_offset_div2); + infer(ph_luma_tc_offset_div2, pps->pps_luma_tc_offset_div2); + if (pps->pps_chroma_tool_offsets_present_flag) { + infer(ph_cb_beta_offset_div2, pps->pps_cb_beta_offset_div2); + infer(ph_cb_tc_offset_div2, pps->pps_cb_tc_offset_div2); + infer(ph_cr_beta_offset_div2, pps->pps_cr_beta_offset_div2); + infer(ph_cr_tc_offset_div2, pps->pps_cr_tc_offset_div2); + } else { + infer(ph_cb_beta_offset_div2, + current->ph_luma_beta_offset_div2); + infer(ph_cb_tc_offset_div2, + current->ph_luma_tc_offset_div2); + infer(ph_cr_beta_offset_div2, + current->ph_luma_beta_offset_div2); + infer(ph_cr_tc_offset_div2, + current->ph_luma_tc_offset_div2); + } + } + } + } + + if (pps->pps_picture_header_extension_present_flag) { + ue(ph_extension_length, 0, 256); + for (i = 0; i < current->ph_extension_length; i++) + us(8, ph_extension_data_byte[i], 0x00, 0xff, 1, i); + } + + return 0; +} + +static int FUNC(ph) (CodedBitstreamContext *ctx, RWContext *rw, + H266RawPH *current) +{ + int err; + + HEADER("Picture Header"); + + CHECK(FUNC(nal_unit_header) (ctx, rw, ¤t->nal_unit_header, VVC_PH_NUT)); + CHECK(FUNC(picture_header) (ctx, rw, current)); + CHECK(FUNC(rbsp_trailing_bits) (ctx, rw)); + return 0; +} + +static int FUNC(slice_header) (CodedBitstreamContext *ctx, RWContext *rw, + H266RawSliceHeader *current) +{ + CodedBitstreamH266Context *h266 = ctx->priv_data; + const H266RawSPS *sps; + const H266RawPPS *pps; + const H266RawPH *ph; + const H266RefPicLists *ref_pic_lists; + int err, i; + uint8_t nal_unit_type, qp_bd_offset; + uint16_t curr_subpic_idx; + uint16_t num_slices_in_subpic; + + HEADER("Slice Header"); + + CHECK(FUNC(nal_unit_header) (ctx, rw, ¤t->nal_unit_header, -1)); + + flag(sh_picture_header_in_slice_header_flag); + if (current->sh_picture_header_in_slice_header_flag) { + CHECK(FUNC(picture_header) (ctx, rw, ¤t->sh_picture_header)); + ph = ¤t->sh_picture_header; + //7.4.8 if sh_picture_header_in_slice_header_flag is true, we do not have PH NAL unit + h266->priv.ph = NULL; + } else { + ph = h266->priv.ph; + if (!ph) { + av_log(ctx->log_ctx, AV_LOG_ERROR, + "Picture header not available.\n"); + return AVERROR_INVALIDDATA; + } + } + + pps = h266->pps[ph->ph_pic_parameter_set_id]; + if (!pps) { + av_log(ctx->log_ctx, AV_LOG_ERROR, "PPS id %d not available.\n", + ph->ph_pic_parameter_set_id); + return AVERROR_INVALIDDATA; + } + sps = h266->sps[pps->pps_seq_parameter_set_id]; + if (!sps) { + av_log(ctx->log_ctx, AV_LOG_ERROR, "SPS id %d not available.\n", + pps->pps_seq_parameter_set_id); + return AVERROR_INVALIDDATA; + } + + if (sps->sps_subpic_info_present_flag) { + ub(sps->sps_subpic_id_len_minus1 + 1, sh_subpic_id); + if (sps->sps_subpic_id_mapping_explicitly_signalled_flag) { + for (i = 0; i <= sps->sps_num_subpics_minus1; i++) { + uint16_t subpic_id_val = + pps->pps_subpic_id_mapping_present_flag ? + pps->pps_subpic_id[i] : sps->sps_subpic_id[i]; + if (subpic_id_val == current->sh_subpic_id) { + curr_subpic_idx = i; + break; + } + } + } else { + curr_subpic_idx = current->sh_subpic_id; + if (curr_subpic_idx > sps->sps_num_subpics_minus1) { + av_log(ctx->log_ctx, AV_LOG_ERROR, + "sh_subpic_id(%d) should in range [0, %d]\n", + curr_subpic_idx, sps->sps_num_subpics_minus1); + return AVERROR_INVALIDDATA; + } + } + } else { + curr_subpic_idx = 0; + } + + num_slices_in_subpic = pps->num_slices_in_subpic[curr_subpic_idx]; + + if ((pps->pps_rect_slice_flag && num_slices_in_subpic > 1) || + (!pps->pps_rect_slice_flag && pps->num_tiles_in_pic > 1)) { + unsigned int bits, max; + if (!pps->pps_rect_slice_flag) { + bits = av_ceil_log2(pps->num_tiles_in_pic); + max = pps->num_tiles_in_pic - 1; + } else { + bits = av_ceil_log2(num_slices_in_subpic); + max = num_slices_in_subpic - 1; + } + u(bits, sh_slice_address, 0, max); + } else { + infer(sh_slice_address, 0); + } + + for (i = 0; i < sps->sps_num_extra_sh_bytes * 8; i++) { + if (sps->sps_extra_sh_bit_present_flag[i]) + flags(sh_extra_bit[i], 1, i); + } + + if (!pps->pps_rect_slice_flag && + pps->num_tiles_in_pic - current->sh_slice_address > 1) + ue(sh_num_tiles_in_slice_minus1, 0, pps->num_tiles_in_pic - 1); + else + infer(sh_num_tiles_in_slice_minus1, 0); + + if (ph->ph_inter_slice_allowed_flag) + ue(sh_slice_type, 0, 2); + else + infer(sh_slice_type, 2); + + nal_unit_type = current->nal_unit_header.nal_unit_type; + if (nal_unit_type == VVC_IDR_W_RADL || nal_unit_type == VVC_IDR_N_LP || + nal_unit_type == VVC_CRA_NUT || nal_unit_type == VVC_GDR_NUT) + flag(sh_no_output_of_prior_pics_flag); + if (sps->sps_alf_enabled_flag && !pps->pps_alf_info_in_ph_flag) { + flag(sh_alf_enabled_flag); + if (current->sh_alf_enabled_flag) { + ub(3, sh_num_alf_aps_ids_luma); + for (i = 0; i < current->sh_num_alf_aps_ids_luma; i++) + ubs(3, sh_alf_aps_id_luma[i], 1, i); + if (sps->sps_chroma_format_idc != 0) { + flag(sh_alf_cb_enabled_flag); + flag(sh_alf_cr_enabled_flag); + } else { + infer(sh_alf_cb_enabled_flag, ph->ph_alf_cb_enabled_flag); + infer(sh_alf_cr_enabled_flag, ph->ph_alf_cr_enabled_flag); + } + if (current->sh_alf_cb_enabled_flag || + current->sh_alf_cr_enabled_flag) + ub(3, sh_alf_aps_id_chroma); + else + infer(sh_alf_aps_id_chroma, ph->ph_alf_aps_id_chroma); + if (sps->sps_ccalf_enabled_flag) { + flag(sh_alf_cc_cb_enabled_flag); + if (current->sh_alf_cc_cb_enabled_flag) + ub(3, sh_alf_cc_cb_aps_id); + else + infer(sh_alf_cc_cb_aps_id, ph->ph_alf_cc_cb_aps_id); + flag(sh_alf_cc_cr_enabled_flag); + if (current->sh_alf_cc_cr_enabled_flag) + ub(3, sh_alf_cc_cr_aps_id); + else + infer(sh_alf_cc_cr_aps_id, ph->ph_alf_cc_cr_aps_id); + } else { + infer(sh_alf_cc_cb_enabled_flag, ph->ph_alf_cc_cb_enabled_flag); + infer(sh_alf_cc_cr_enabled_flag, ph->ph_alf_cc_cr_enabled_flag); + infer(sh_alf_cc_cb_aps_id, ph->ph_alf_cc_cb_aps_id); + infer(sh_alf_cc_cr_aps_id, ph->ph_alf_cc_cr_aps_id); + } + } + } else { + infer(sh_alf_enabled_flag, 0); + } + + if (ph->ph_lmcs_enabled_flag && + !current->sh_picture_header_in_slice_header_flag) + flag(sh_lmcs_used_flag); + else + infer(sh_lmcs_used_flag, 0); + + if (ph->ph_explicit_scaling_list_enabled_flag && + !current->sh_picture_header_in_slice_header_flag) + flag(sh_explicit_scaling_list_used_flag); + else + infer(sh_explicit_scaling_list_used_flag, 0); + + if (!pps->pps_rpl_info_in_ph_flag && + ((nal_unit_type != VVC_IDR_W_RADL && + nal_unit_type != VVC_IDR_N_LP) || sps->sps_idr_rpl_present_flag)) { + CHECK(FUNC(ref_pic_lists) + (ctx, rw, sps, pps, ¤t->sh_ref_pic_lists)); + ref_pic_lists = ¤t->sh_ref_pic_lists; + } else { + ref_pic_lists = &h266->priv.ph->ph_ref_pic_lists; + } + if ((current->sh_slice_type != VVC_SLICE_TYPE_I && + ref_pic_lists->rpl_ref_list[0].num_ref_entries > 1) || + (current->sh_slice_type == VVC_SLICE_TYPE_B && + ref_pic_lists->rpl_ref_list[1].num_ref_entries > 1)) { + flag(sh_num_ref_idx_active_override_flag); + if (current->sh_num_ref_idx_active_override_flag) { + for (i = 0; + i < (current->sh_slice_type == VVC_SLICE_TYPE_B ? 2 : 1); i++) + if (ref_pic_lists->rpl_ref_list[i].num_ref_entries > 1) + ues(sh_num_ref_idx_active_minus1[i], 0, 14, 1, i); + else + infer(sh_num_ref_idx_active_minus1[i], 0); + } + } else { + infer(sh_num_ref_idx_active_override_flag, 1); + } + if (current->sh_slice_type != VVC_SLICE_TYPE_I) { + if (pps->pps_cabac_init_present_flag) + flag(sh_cabac_init_flag); + else + infer(sh_cabac_init_flag, 0); + if (ph->ph_temporal_mvp_enabled_flag && !pps->pps_rpl_info_in_ph_flag) { + uint8_t num_ref_idx_active[2]; + for (i = 0; i < 2; i++) { + if (current->sh_slice_type == VVC_SLICE_TYPE_B || + (current->sh_slice_type == VVC_SLICE_TYPE_P && i == 0)) { + if (current->sh_num_ref_idx_active_override_flag) { + num_ref_idx_active[i] = + current->sh_num_ref_idx_active_minus1[i] + 1; + } else { + num_ref_idx_active[i] = + FFMIN(ref_pic_lists->rpl_ref_list[i].num_ref_entries, + pps->pps_num_ref_idx_default_active_minus1[i] + 1); + } + } else { + num_ref_idx_active[i] = 0; + } + } + + if (current->sh_slice_type == VVC_SLICE_TYPE_B) + flag(sh_collocated_from_l0_flag); + else + infer(sh_collocated_from_l0_flag, 1); + if ((current->sh_collocated_from_l0_flag && + num_ref_idx_active[0] > 1) || + (!current->sh_collocated_from_l0_flag && + num_ref_idx_active[1] > 1)) { + unsigned int idx = current->sh_collocated_from_l0_flag ? 0 : 1; + ue(sh_collocated_ref_idx, 0, num_ref_idx_active[idx] - 1); + } else { + infer(sh_collocated_ref_idx, 0); + } + if (!pps->pps_wp_info_in_ph_flag && + ((pps->pps_weighted_pred_flag && + current->sh_slice_type == VVC_SLICE_TYPE_P) || + (pps->pps_weighted_bipred_flag && + current->sh_slice_type == VVC_SLICE_TYPE_B))) { + CHECK(FUNC(pred_weight_table) (ctx, rw, sps, pps, ref_pic_lists, + num_ref_idx_active, + ¤t->sh_pred_weight_table)); + } + } + + } + qp_bd_offset = 6 * sps->sps_bitdepth_minus8; + if (!pps->pps_qp_delta_info_in_ph_flag) + se(sh_qp_delta, -qp_bd_offset - (26 + pps->pps_init_qp_minus26), + 63 - (26 + pps->pps_init_qp_minus26)); + if (pps->pps_slice_chroma_qp_offsets_present_flag) { + int8_t off; + + se(sh_cb_qp_offset, -12, 12); + off = pps->pps_cb_qp_offset + current->sh_cb_qp_offset; + if (off < -12 || off > 12) { + av_log(ctx->log_ctx, AV_LOG_ERROR, + "pps_cb_qp_offset + sh_cb_qp_offset (%d) not in range [-12, 12].\n", + off); + return AVERROR_INVALIDDATA; + } + + se(sh_cr_qp_offset, -12, 12); + off = pps->pps_cr_qp_offset + current->sh_cr_qp_offset; + if (off < -12 || off > 12) { + av_log(ctx->log_ctx, AV_LOG_ERROR, + "pps_cr_qp_offset + sh_cr_qp_offset (%d) not in range [-12, 12].\n", + off); + return AVERROR_INVALIDDATA; + } + + if (sps->sps_joint_cbcr_enabled_flag) { + se(sh_joint_cbcr_qp_offset, -12, 12); + off = + pps->pps_joint_cbcr_qp_offset_value + + current->sh_joint_cbcr_qp_offset; + if (off < -12 || off > 12) { + av_log(ctx->log_ctx, AV_LOG_ERROR, + "pps_joint_cbcr_qp_offset_value + sh_joint_cbcr_qp_offset (%d)" + "not in range [-12, 12]. \n", off); + return AVERROR_INVALIDDATA; + } + } else { + infer(sh_joint_cbcr_qp_offset, 0); + } + } else { + infer(sh_cb_qp_offset, 0); + infer(sh_cr_qp_offset, 0); + infer(sh_joint_cbcr_qp_offset, 0); + } + if (pps->pps_cu_chroma_qp_offset_list_enabled_flag) + flag(sh_cu_chroma_qp_offset_enabled_flag); + else + infer(sh_cu_chroma_qp_offset_enabled_flag, 0); + if (sps->sps_sao_enabled_flag && !pps->pps_sao_info_in_ph_flag) { + flag(sh_sao_luma_used_flag); + if (sps->sps_chroma_format_idc != 0) + flag(sh_sao_chroma_used_flag); + else + infer(sh_sao_chroma_used_flag, ph->ph_sao_chroma_enabled_flag); + } else { + infer(sh_sao_luma_used_flag, ph->ph_sao_luma_enabled_flag); + infer(sh_sao_chroma_used_flag, ph->ph_sao_chroma_enabled_flag); + } + + if (pps->pps_deblocking_filter_override_enabled_flag && + !pps->pps_dbf_info_in_ph_flag) + flag(sh_deblocking_params_present_flag); + else + infer(sh_deblocking_params_present_flag, 0); + if (current->sh_deblocking_params_present_flag) { + if (!pps->pps_deblocking_filter_disabled_flag) + flag(sh_deblocking_filter_disabled_flag); + else + infer(sh_deblocking_filter_disabled_flag, + !(pps->pps_deblocking_filter_disabled_flag && + current->sh_deblocking_params_present_flag)); + if (!current->sh_deblocking_filter_disabled_flag) { + se(sh_luma_beta_offset_div2, -12, 12); + se(sh_luma_tc_offset_div2, -12, 12); + if (pps->pps_chroma_tool_offsets_present_flag) { + se(sh_cb_beta_offset_div2, -12, 12); + se(sh_cb_tc_offset_div2, -12, 12); + se(sh_cr_beta_offset_div2, -12, 12); + se(sh_cr_tc_offset_div2, -12, 12); + } else { + infer(sh_cb_beta_offset_div2, + current->sh_luma_beta_offset_div2); + infer(sh_cb_tc_offset_div2, current->sh_luma_tc_offset_div2); + infer(sh_cr_beta_offset_div2, + current->sh_luma_beta_offset_div2); + infer(sh_cr_tc_offset_div2, current->sh_luma_tc_offset_div2); + } + } else { + infer(sh_luma_beta_offset_div2, ph->ph_luma_beta_offset_div2); + infer(sh_luma_tc_offset_div2, ph->ph_luma_tc_offset_div2); + if (pps->pps_chroma_tool_offsets_present_flag) { + infer(sh_cb_beta_offset_div2, ph->ph_cb_beta_offset_div2); + infer(sh_cb_tc_offset_div2, ph->ph_cb_tc_offset_div2); + infer(sh_cr_beta_offset_div2, ph->ph_cr_beta_offset_div2); + infer(sh_cr_tc_offset_div2, ph->ph_cr_beta_offset_div2); + } else { + infer(sh_cb_beta_offset_div2, + current->sh_luma_beta_offset_div2); + infer(sh_cb_tc_offset_div2, current->sh_luma_tc_offset_div2); + infer(sh_cr_beta_offset_div2, + current->sh_luma_beta_offset_div2); + infer(sh_cr_tc_offset_div2, current->sh_luma_tc_offset_div2); + } + } + } + + if (sps->sps_dep_quant_enabled_flag) + flag(sh_dep_quant_used_flag); + else + infer(sh_dep_quant_used_flag, 0); + + if (sps->sps_sign_data_hiding_enabled_flag && + !current->sh_dep_quant_used_flag) + flag(sh_sign_data_hiding_used_flag); + else + infer(sh_sign_data_hiding_used_flag, 0); + + if (sps->sps_transform_skip_enabled_flag && + !current->sh_dep_quant_used_flag && + !current->sh_sign_data_hiding_used_flag) + flag(sh_ts_residual_coding_disabled_flag); + else + infer(sh_ts_residual_coding_disabled_flag, 0); + if (pps->pps_slice_header_extension_present_flag) { + ue(sh_slice_header_extension_length, 0, 256); + for (i = 0; i < current->sh_slice_header_extension_length; i++) + us(8, sh_slice_header_extension_data_byte[i], 0x00, 0xff, 1, i); + } + if (sps->sps_entry_point_offsets_present_flag) { + int num_entry_points = 0; + uint8_t entropy_sync = sps->sps_entropy_coding_sync_enabled_flag; + int height; + if (pps->pps_rect_slice_flag) { + int width_in_tiles; + int slice_idx = current->sh_slice_address; + for (i = 0; i < curr_subpic_idx; i++) { + slice_idx += pps->num_slices_in_subpic[i]; + } + width_in_tiles = + pps->pps_slice_width_in_tiles_minus1[slice_idx] + 1; + + if (entropy_sync) + height = pps->slice_height_in_ctus[slice_idx]; + else + height = pps->pps_slice_height_in_tiles_minus1[slice_idx] + 1; + + num_entry_points = width_in_tiles * height; + } else { + int tile_idx; + int tile_y; + for (tile_idx = current->sh_slice_address; + tile_idx <= + current->sh_slice_address + + current->sh_num_tiles_in_slice_minus1; tile_idx++) { + tile_y = tile_idx / pps->num_tile_rows; + height = pps->pps_tile_row_height_minus1[tile_y] + 1; + num_entry_points += (entropy_sync ? height : 1); + } + } + num_entry_points--; + if (num_entry_points > VVC_MAX_ENTRY_POINTS) { + av_log(ctx->log_ctx, AV_LOG_ERROR, "Too many entry points: " + "%" PRIu16 ".\n", num_entry_points); + return AVERROR_PATCHWELCOME; + } + if (num_entry_points > 0) { + ue(sh_entry_offset_len_minus1, 0, 31); + for (i = 0; i < num_entry_points; i++) { + ubs(current->sh_entry_offset_len_minus1 + 1, + sh_entry_point_offset_minus1[i], 1, i); + } + } + } + CHECK(FUNC(byte_alignment) (ctx, rw)); + + return 0; +} + +static int FUNC(sei_decoded_picture_hash) (CodedBitstreamContext *ctx, + RWContext *rw, + H266RawSEIDecodedPictureHash * + current) +{ + int err, c_idx, i; + + HEADER("Decoded Picture Hash"); + + u(8, dph_sei_hash_type, 0, 2); + flag(dph_sei_single_component_flag); + ub(7, dph_sei_reserved_zero_7bits); + + for (c_idx = 0; c_idx < (current->dph_sei_single_component_flag ? 1 : 3); + c_idx++) { + if (current->dph_sei_hash_type == 0) { + for (i = 0; i < 16; i++) + us(8, dph_sei_picture_md5[c_idx][i], 0x00, 0xff, 2, c_idx, i); + } else if (current->dph_sei_hash_type == 1) { + us(16, dph_sei_picture_crc[c_idx], 0x0000, 0xffff, 1, c_idx); + } else if (current->dph_sei_hash_type == 2) { + us(32, dph_sei_picture_checksum[c_idx], 0x00000000, 0xffffffff, 1, + c_idx); + } + } + return 0; +} + +static int FUNC(sei) (CodedBitstreamContext *ctx, RWContext *rw, + H266RawSEI *current, int prefix) +{ + int err; + + if (prefix) + HEADER("Prefix Supplemental Enhancement Information"); + else + HEADER("Suffix Supplemental Enhancement Information"); + + CHECK(FUNC(nal_unit_header) (ctx, rw, ¤t->nal_unit_header, + prefix ? VVC_PREFIX_SEI_NUT + : VVC_SUFFIX_SEI_NUT)); + + CHECK(FUNC_SEI(message_list) (ctx, rw, ¤t->message_list, prefix)); + + CHECK(FUNC(rbsp_trailing_bits) (ctx, rw)); + + return 0; +} diff --git a/libavcodec/cbs_internal.h b/libavcodec/cbs_internal.h index 077954eee59..b752d646845 100644 --- a/libavcodec/cbs_internal.h +++ b/libavcodec/cbs_internal.h @@ -251,6 +251,7 @@ int ff_cbs_write_signed(CodedBitstreamContext *ctx, PutBitContext *pbc, extern const CodedBitstreamType ff_cbs_type_av1; extern const CodedBitstreamType ff_cbs_type_h264; extern const CodedBitstreamType ff_cbs_type_h265; +extern const CodedBitstreamType ff_cbs_type_h266; extern const CodedBitstreamType ff_cbs_type_jpeg; extern const CodedBitstreamType ff_cbs_type_mpeg2; extern const CodedBitstreamType ff_cbs_type_vp9; diff --git a/libavcodec/cbs_sei.c b/libavcodec/cbs_sei.c index 50a513f592a..bd7f6f49382 100644 --- a/libavcodec/cbs_sei.c +++ b/libavcodec/cbs_sei.c @@ -20,6 +20,7 @@ #include "cbs_internal.h" #include "cbs_h264.h" #include "cbs_h265.h" +#include "cbs_h266.h" #include "cbs_sei.h" static void cbs_free_user_data_registered(void *opaque, uint8_t *data) @@ -132,6 +133,13 @@ static int cbs_sei_get_unit(CodedBitstreamContext *ctx, else sei_type = HEVC_NAL_SEI_SUFFIX; break; + case AV_CODEC_ID_H266: + highest_vcl_type = VVC_RSV_IRAP_11; + if (prefix) + sei_type = VVC_PREFIX_SEI_NUT; + else + sei_type = VVC_SUFFIX_SEI_NUT; + break; default: return AVERROR(EINVAL); } @@ -207,6 +215,18 @@ static int cbs_sei_get_unit(CodedBitstreamContext *ctx, memcpy(unit->content, &sei, sizeof(sei)); } break; + case AV_CODEC_ID_H266: + { + H266RawSEI sei = { + .nal_unit_header = { + .nal_unit_type = sei_type, + .nuh_layer_id = 0, + .nuh_temporal_id_plus1 = 1, + }, + }; + memcpy(unit->content, &sei, sizeof(sei)); + } + break; default: av_assert0(0); } @@ -237,6 +257,15 @@ static int cbs_sei_get_message_list(CodedBitstreamContext *ctx, *list = &sei->message_list; } break; + case AV_CODEC_ID_H266: + { + H266RawSEI *sei = unit->content; + if (unit->type != VVC_PREFIX_SEI_NUT && + unit->type != VVC_SUFFIX_SEI_NUT) + return AVERROR(EINVAL); + *list = &sei->message_list; + } + break; default: return AVERROR(EINVAL); } From b5aefb6e70f7a19adbab3dd41633666ba95e1997 Mon Sep 17 00:00:00 2001 From: Nuo Mi Date: Tue, 21 Mar 2023 16:01:16 +0100 Subject: [PATCH 1690/2172] avcodec: add bitstream parser for H266/VVC Add nal parser ff_vvc_parser to parse vvc elementary bitstreams. Co-authored-by: Thomas Siedel Co-authored-by: James Almer Signed-off-by: James Almer --- Changelog | 1 + configure | 1 + libavcodec/Makefile | 1 + libavcodec/parsers.c | 1 + libavcodec/vvc_parser.c | 580 ++++++++++++++++++++++++++++++++++++++++ 5 files changed, 584 insertions(+) create mode 100644 libavcodec/vvc_parser.c diff --git a/Changelog b/Changelog index 5e4492fb71a..e9cbce7e1ce 100644 --- a/Changelog +++ b/Changelog @@ -22,6 +22,7 @@ version : - bwdif_cuda filter - Microsoft RLE video encoder - Raw AC-4 muxer and demuxer +- Raw VVC bitstream parser version 6.0: - Radiance HDR image support diff --git a/configure b/configure index b2665a0fbd5..10d12770d69 100755 --- a/configure +++ b/configure @@ -3333,6 +3333,7 @@ hevc_parser_select="hevcparse hevc_sei" mpegaudio_parser_select="mpegaudioheader" mpeg4video_parser_select="h263dsp mpegvideodec qpeldsp" vc1_parser_select="vc1dsp" +vvc_parser_select="cbs_h266" # bitstream_filters aac_adtstoasc_bsf_select="adts_header mpeg4audio" diff --git a/libavcodec/Makefile b/libavcodec/Makefile index a0ebb15a2c4..b915464b90e 100644 --- a/libavcodec/Makefile +++ b/libavcodec/Makefile @@ -1209,6 +1209,7 @@ OBJS-$(CONFIG_VC1_PARSER) += vc1_parser.o vc1.o vc1data.o \ OBJS-$(CONFIG_VP3_PARSER) += vp3_parser.o OBJS-$(CONFIG_VP8_PARSER) += vp8_parser.o OBJS-$(CONFIG_VP9_PARSER) += vp9_parser.o +OBJS-$(CONFIG_VVC_PARSER) += vvc_parser.o OBJS-$(CONFIG_WEBP_PARSER) += webp_parser.o OBJS-$(CONFIG_XBM_PARSER) += xbm_parser.o OBJS-$(CONFIG_XMA_PARSER) += xma_parser.o diff --git a/libavcodec/parsers.c b/libavcodec/parsers.c index 2c077ec3ae0..285f81a901b 100644 --- a/libavcodec/parsers.c +++ b/libavcodec/parsers.c @@ -75,6 +75,7 @@ extern const AVCodecParser ff_vorbis_parser; extern const AVCodecParser ff_vp3_parser; extern const AVCodecParser ff_vp8_parser; extern const AVCodecParser ff_vp9_parser; +extern const AVCodecParser ff_vvc_parser; extern const AVCodecParser ff_webp_parser; extern const AVCodecParser ff_xbm_parser; extern const AVCodecParser ff_xma_parser; diff --git a/libavcodec/vvc_parser.c b/libavcodec/vvc_parser.c new file mode 100644 index 00000000000..4f7657f7ab7 --- /dev/null +++ b/libavcodec/vvc_parser.c @@ -0,0 +1,580 @@ +/* + * H.266 / VVC parser + * + * Copyright (C) 2021 Nuo Mi + * + * 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 "cbs.h" +#include "cbs_h266.h" +#include "internal.h" +#include "parser.h" +#include "decode.h" + +#define START_CODE 0x000001 ///< start_code_prefix_one_3bytes +#define IS_IDR(nut) (nut == VVC_IDR_W_RADL || nut == VVC_IDR_N_LP) +#define IS_H266_SLICE(nut) (nut <= VVC_RASL_NUT || (nut >= VVC_IDR_W_RADL && nut <= VVC_GDR_NUT)) + +typedef struct PuInfo { + AVBufferRef *sps_ref; + AVBufferRef *pps_ref; + AVBufferRef *slice_ref; + AVBufferRef *ph_ref; + + const H266RawPPS *pps; + const H266RawSPS *sps; + const H266RawPH *ph; + const H266RawSlice *slice; + int pic_type; +} PuInfo; + +typedef struct AuDetector { + uint8_t prev_layer_id; + int prev_tid0_poc; + int prev_poc; +} AuDetector; + +typedef struct VVCParserContext { + ParseContext pc; + CodedBitstreamContext *cbc; + + CodedBitstreamFragment picture_unit; + + PuInfo au_info; + AVPacket au; + AVPacket last_au; + + AuDetector au_detector; + + int parsed_extradata; +} VVCParserContext; + +static const enum AVPixelFormat pix_fmts_8bit[] = { + AV_PIX_FMT_GRAY8, AV_PIX_FMT_YUV420P, + AV_PIX_FMT_YUV422P, AV_PIX_FMT_YUV444P +}; + +static const enum AVPixelFormat pix_fmts_10bit[] = { + AV_PIX_FMT_GRAY10, AV_PIX_FMT_YUV420P10, + AV_PIX_FMT_YUV422P10, AV_PIX_FMT_YUV444P10 +}; + +static int get_format(const H266RawSPS *sps) +{ + switch (sps->sps_bitdepth_minus8) { + case 0: + return pix_fmts_8bit[sps->sps_chroma_format_idc]; + case 2: + return pix_fmts_10bit[sps->sps_chroma_format_idc]; + } + return AV_PIX_FMT_NONE; +} + +/** + * Find the end of the current frame in the bitstream. + * @return the position of the first byte of the next frame, or END_NOT_FOUND + */ +static int find_frame_end(AVCodecParserContext *s, const uint8_t *buf, + int buf_size) +{ + VVCParserContext *ctx = s->priv_data; + ParseContext *pc = &ctx->pc; + int i; + + for (i = 0; i < buf_size; i++) { + int nut, code_len; + + pc->state64 = (pc->state64 << 8) | buf[i]; + + if (((pc->state64 >> 3 * 8) & 0xFFFFFF) != START_CODE) + continue; + + code_len = ((pc->state64 >> 3 * 8) & 0xFFFFFFFF) == 0x01 ? 4 : 3; + + nut = (pc->state64 >> (8 + 3)) & 0x1F; + // 7.4.2.4.3 and 7.4.2.4.4 + if ((nut >= VVC_OPI_NUT && nut <= VVC_PREFIX_APS_NUT && + nut != VVC_PH_NUT) || nut == VVC_AUD_NUT + || (nut == VVC_PREFIX_SEI_NUT && !pc->frame_start_found) + || nut == VVC_RSV_NVCL_26 || nut == VVC_UNSPEC_28 + || nut == VVC_UNSPEC_29) { + if (pc->frame_start_found) { + pc->frame_start_found = 0; + return i - (code_len + 2); + } + } else if (nut == VVC_PH_NUT || IS_H266_SLICE(nut)) { + int sh_picture_header_in_slice_header_flag = buf[i] >> 7; + + if (nut == VVC_PH_NUT || sh_picture_header_in_slice_header_flag) { + if (!pc->frame_start_found) { + pc->frame_start_found = 1; + } else { // First slice of next frame found + pc->frame_start_found = 0; + return i - (code_len + 2); + } + } + } + } + return END_NOT_FOUND; +} + +static int get_pict_type(const CodedBitstreamFragment *pu) +{ + int has_p = 0; + for (int i = 0; i < pu->nb_units; i++) { + CodedBitstreamUnit *unit = &pu->units[i]; + if (IS_H266_SLICE(unit->type)) { + const H266RawSlice *slice = unit->content; + uint8_t type = slice->header.sh_slice_type; + if (type == VVC_SLICE_TYPE_B) { + return AV_PICTURE_TYPE_B; + } + if (type == VVC_SLICE_TYPE_P) { + has_p = 1; + } + } + } + return has_p ? AV_PICTURE_TYPE_P : AV_PICTURE_TYPE_I; +} + +static void pu_info_unref(PuInfo *info) +{ + av_buffer_unref(&info->slice_ref); + av_buffer_unref(&info->ph_ref); + av_buffer_unref(&info->pps_ref); + av_buffer_unref(&info->sps_ref); + info->slice = NULL; + info->ph = NULL; + info->pps = NULL; + info->sps = NULL; + info->pic_type = AV_PICTURE_TYPE_NONE; +} + +static int pu_info_ref(PuInfo *dest, const PuInfo *src) +{ + pu_info_unref(dest); + dest->sps_ref = av_buffer_ref(src->sps_ref); + dest->pps_ref = av_buffer_ref(src->pps_ref); + if (src->ph_ref) + dest->ph_ref = av_buffer_ref(src->ph_ref); + dest->slice_ref = av_buffer_ref(src->slice_ref); + if (!dest->sps_ref || !dest->pps_ref || (src->ph_ref && !dest->ph_ref) + || !dest->slice_ref) { + pu_info_unref(dest); + return AVERROR(ENOMEM); + } + + dest->sps = src->sps; + dest->pps = src->pps; + dest->ph = src->ph; + dest->slice = src->slice; + dest->pic_type = src->pic_type; + return 0; +} + +static void set_parser_ctx(AVCodecParserContext *s, AVCodecContext *avctx, + const PuInfo *pu) +{ + static const uint8_t h266_sub_width_c[] = { + 1, 2, 2, 1 + }; + static const uint8_t h266_sub_height_c[] = { + 1, 2, 1, 1 + }; + const H266RawSPS *sps = pu->sps; + const H266RawPPS *pps = pu->pps; + //const H266RawPH *ph = pu->ph; + const H266RawNALUnitHeader *nal = &pu->slice->header.nal_unit_header; + + s->pict_type = pu->pic_type; + s->format = get_format(sps); + s->picture_structure = AV_PICTURE_STRUCTURE_FRAME; + + s->key_frame = nal->nal_unit_type == VVC_IDR_W_RADL || + nal->nal_unit_type == VVC_IDR_N_LP || + nal->nal_unit_type == VVC_CRA_NUT || + nal->nal_unit_type == VVC_GDR_NUT; + + s->coded_width = pps->pps_pic_width_in_luma_samples; + s->coded_height = pps->pps_pic_height_in_luma_samples; + s->width = pps->pps_pic_width_in_luma_samples - + (pps->pps_conf_win_left_offset + pps->pps_conf_win_right_offset) * + h266_sub_width_c[sps->sps_chroma_format_idc]; + s->height = pps->pps_pic_height_in_luma_samples - + (pps->pps_conf_win_top_offset + pps->pps_conf_win_bottom_offset) * + h266_sub_height_c[sps->sps_chroma_format_idc];; + + avctx->profile = sps->profile_tier_level.general_profile_idc; + avctx->level = sps->profile_tier_level.general_level_idc; + + avctx->colorspace = (enum AVColorSpace) sps->vui.vui_matrix_coeffs; + avctx->color_primaries = (enum AVColorPrimaries) sps->vui.vui_colour_primaries; + avctx->color_trc = (enum AVColorTransferCharacteristic) sps->vui.vui_transfer_characteristics; + avctx->color_range = + sps->vui.vui_full_range_flag ? AVCOL_RANGE_JPEG : AVCOL_RANGE_MPEG; + + avctx->has_b_frames = (sps->sps_max_sublayers_minus1 + 1) > 2 ? 2 : + sps->sps_max_sublayers_minus1; + avctx->max_b_frames = sps->sps_max_sublayers_minus1; + + if (sps->sps_ptl_dpb_hrd_params_present_flag && + sps->sps_timing_hrd_params_present_flag) { + int num = sps->sps_general_timing_hrd_parameters.num_units_in_tick; + int den = sps->sps_general_timing_hrd_parameters.time_scale; + + if (num != 0 && den != 0) + av_reduce(&avctx->framerate.den, &avctx->framerate.num, + num, den, 1 << 30); + } +} + +static int set_ctx(AVCodecParserContext *s, AVCodecContext *avctx, + const PuInfo *next_pu) +{ + VVCParserContext *ctx = s->priv_data; + + int ret = pu_info_ref(&ctx->au_info, next_pu); + if (ret < 0) + return ret; + + set_parser_ctx(s, avctx, &ctx->au_info); + + return 0; +} + +//8.3.1 Decoding process for picture order count. +//VTM did not follow the spec, and it's much simpler than spec. +//We follow the VTM. +static void get_slice_poc(VVCParserContext *s, int *poc, + const H266RawSPS *sps, + const H266RawPH *ph, + const H266RawSliceHeader *slice, void *log_ctx) +{ + int poc_msb, max_poc_lsb, poc_lsb; + AuDetector *d = &s->au_detector; + max_poc_lsb = 1 << (sps->sps_log2_max_pic_order_cnt_lsb_minus4 + 4); + poc_lsb = ph->ph_pic_order_cnt_lsb; + if (IS_IDR(slice->nal_unit_header.nal_unit_type)) { + if (ph->ph_poc_msb_cycle_present_flag) + poc_msb = ph->ph_poc_msb_cycle_val * max_poc_lsb; + else + poc_msb = 0; + } else { + int prev_poc = d->prev_tid0_poc; + int prev_poc_lsb = prev_poc & (max_poc_lsb - 1); + int prev_poc_msb = prev_poc - prev_poc_lsb; + if (ph->ph_poc_msb_cycle_present_flag) { + poc_msb = ph->ph_poc_msb_cycle_val * max_poc_lsb; + } else { + if ((poc_lsb < prev_poc_lsb) && ((prev_poc_lsb - poc_lsb) >= + (max_poc_lsb / 2))) + poc_msb = prev_poc_msb + max_poc_lsb; + else if ((poc_lsb > prev_poc_lsb) && ((poc_lsb - prev_poc_lsb) > + (max_poc_lsb / 2))) + poc_msb = prev_poc_msb - max_poc_lsb; + else + poc_msb = prev_poc_msb; + } + } + + *poc = poc_msb + poc_lsb; +} + +static void au_detector_init(AuDetector *d) +{ + d->prev_layer_id = UINT8_MAX; + d->prev_poc = INT_MAX; + d->prev_tid0_poc = INT_MAX; +} + +static int is_au_start(VVCParserContext *s, const PuInfo *pu, void *log_ctx) +{ + //7.4.2.4.3 + AuDetector *d = &s->au_detector; + const H266RawSPS *sps = pu->sps; + const H266RawNALUnitHeader *nal = &pu->slice->header.nal_unit_header; + const H266RawPH *ph = pu->ph; + const H266RawSlice *slice = pu->slice; + int ret, poc, nut; + + get_slice_poc(s, &poc, sps, ph, &slice->header, log_ctx); + + ret = (nal->nuh_layer_id <= d->prev_layer_id) || (poc != d->prev_poc); + + nut = nal->nal_unit_type; + d->prev_layer_id = nal->nuh_layer_id; + d->prev_poc = poc; + if (nal->nuh_temporal_id_plus1 == 1 && + !ph->ph_non_ref_pic_flag && nut != VVC_RADL_NUT + && nut != VVC_RASL_NUT) { + d->prev_tid0_poc = poc; + } + return ret; +} + +static int get_pu_info(PuInfo *info, const CodedBitstreamH266Context *h266, + const CodedBitstreamFragment *pu, void *logctx) +{ + const H266RawNALUnitHeader *nal; + int ret; + + memset(info, 0, sizeof(*info)); + for (int i = 0; i < pu->nb_units; i++) { + nal = pu->units[i].content; + if (!nal) + continue; + if ( nal->nal_unit_type == VVC_PH_NUT ) { + info->ph = pu->units[i].content; + info->ph_ref = pu->units[i].content_ref; + } else if (IS_H266_SLICE(nal->nal_unit_type)) { + info->slice = pu->units[i].content; + info->slice_ref = pu->units[i].content_ref; + if (info->slice->header.sh_picture_header_in_slice_header_flag) + info->ph = &info->slice->header.sh_picture_header; + if (!info->ph) { + av_log(logctx, AV_LOG_ERROR, + "can't find picture header in picture unit.\n"); + ret = AVERROR_INVALIDDATA; + goto error; + } + break; + } + } + if (!info->slice) { + av_log(logctx, AV_LOG_ERROR, "can't find slice in picture unit.\n"); + ret = AVERROR_INVALIDDATA; + goto error; + } + info->pps = h266->pps[info->ph->ph_pic_parameter_set_id]; + if (!info->pps) { + av_log(logctx, AV_LOG_ERROR, "PPS id %d is not avaliable.\n", + info->ph->ph_pic_parameter_set_id); + ret = AVERROR_INVALIDDATA; + goto error; + } + info->pps_ref = h266->pps_ref[info->ph->ph_pic_parameter_set_id]; + info->sps = h266->sps[info->pps->pps_seq_parameter_set_id]; + if (!info->sps) { + av_log(logctx, AV_LOG_ERROR, "SPS id %d is not avaliable.\n", + info->pps->pps_seq_parameter_set_id); + ret = AVERROR_INVALIDDATA; + goto error; + } + info->sps_ref = h266->sps_ref[info->pps->pps_seq_parameter_set_id]; + info->pic_type = get_pict_type(pu); + return 0; + error: + memset(info, 0, sizeof(*info)); + return ret; +} + +static int append_au(AVPacket *pkt, const uint8_t *buf, int buf_size) +{ + int offset = pkt->size; + int ret; + if ((ret = av_grow_packet(pkt, buf_size)) < 0) + goto end; + memcpy(pkt->data + offset, buf, buf_size); + end: + return ret; +} + +/** + * Parse NAL units of found picture and decode some basic information. + * + * @param s parser context. + * @param avctx codec context. + * @param buf buffer with field/frame data. + * @param buf_size size of the buffer. + * @return < 0 for error, == 0 for a complete au, > 0 is not a completed au. + */ +static int parse_nal_units(AVCodecParserContext *s, const uint8_t *buf, + int buf_size, AVCodecContext *avctx) +{ + VVCParserContext *ctx = s->priv_data; + const CodedBitstreamH266Context *h266 = ctx->cbc->priv_data; + + CodedBitstreamFragment *pu = &ctx->picture_unit; + int ret; + PuInfo info; + + if (!buf_size) { + if (ctx->au.size) { + av_packet_move_ref(&ctx->last_au, &ctx->au); + return 0; + } + return 1; + } + + if ((ret = ff_cbs_read(ctx->cbc, pu, buf, buf_size)) < 0) { + av_log(avctx, AV_LOG_ERROR, "Failed to parse picture unit.\n"); + goto end; + } + if ((ret = get_pu_info(&info, h266, pu, avctx)) < 0) + goto end; + if (append_au(&ctx->au, buf, buf_size) < 0) { + ret = AVERROR(ENOMEM); + goto end; + } + if (is_au_start(ctx, &info, avctx)) { + if ((ret = set_ctx(s, avctx, &info)) < 0) + goto end; + av_packet_move_ref(&ctx->last_au, &ctx->au); + } else { + ret = 1; //not a completed au + } + end: + ff_cbs_fragment_reset(pu); + return ret; +} + +/** + * Combine PU to AU + * + * @param s parser context. + * @param avctx codec context. + * @param buf buffer to a PU. + * @param buf_size size of the buffer. + * @return < 0 for error, == 0 a complete au, > 0 not a completed au. + */ +static int combine_au(AVCodecParserContext *s, AVCodecContext *avctx, + const uint8_t **buf, int *buf_size) +{ + VVCParserContext *ctx = s->priv_data; + int ret; + + ctx->cbc->log_ctx = avctx; + + av_packet_unref(&ctx->last_au); + ret = parse_nal_units(s, *buf, *buf_size, avctx); + if (ret == 0) { + if (ctx->last_au.size) { + *buf = ctx->last_au.data; + *buf_size = ctx->last_au.size; + } else { + ret = 1; //no output + } + } + ctx->cbc->log_ctx = NULL; + return ret; +} + +static int vvc_parser_parse(AVCodecParserContext *s, AVCodecContext *avctx, + const uint8_t **poutbuf, int *poutbuf_size, + const uint8_t *buf, int buf_size) +{ + int next, ret; + VVCParserContext *ctx = s->priv_data; + ParseContext *pc = &ctx->pc; + CodedBitstreamFragment *pu = &ctx->picture_unit; + + int is_dummy_buf = !buf_size; + int flush = !buf_size; + const uint8_t *dummy_buf = buf; + + *poutbuf = NULL; + *poutbuf_size = 0; + + if (avctx->extradata_size && !ctx->parsed_extradata) { + ctx->parsed_extradata = 1; + + ret = ff_cbs_read_extradata_from_codec(ctx->cbc, pu, avctx); + if (ret < 0) + av_log(avctx, AV_LOG_WARNING, "Failed to parse extradata.\n"); + + ff_cbs_fragment_reset(pu); + } + + if (s->flags & PARSER_FLAG_COMPLETE_FRAMES) { + next = buf_size; + } else { + next = find_frame_end(s, buf, buf_size); + if (ff_combine_frame(pc, next, &buf, &buf_size) < 0) + return buf_size; + } + + is_dummy_buf &= (dummy_buf == buf); + + if (!is_dummy_buf) { + ret = combine_au(s, avctx, &buf, &buf_size); + if (ret > 0 && flush) { + buf_size = 0; + ret = combine_au(s, avctx, &buf, &buf_size); + } + if (ret != 0) + return next; + } + + *poutbuf = buf; + *poutbuf_size = buf_size; + + return next; +} + +static const CodedBitstreamUnitType decompose_unit_types[] = { + VVC_TRAIL_NUT, + VVC_STSA_NUT, + VVC_RADL_NUT, + VVC_RASL_NUT, + VVC_IDR_W_RADL, + VVC_IDR_N_LP, + VVC_CRA_NUT, + VVC_GDR_NUT, + VVC_VPS_NUT, + VVC_SPS_NUT, + VVC_PPS_NUT, + VVC_PH_NUT, + VVC_AUD_NUT, +}; + +static av_cold int vvc_parser_init(AVCodecParserContext *s) +{ + VVCParserContext *ctx = s->priv_data; + int ret; + + ret = ff_cbs_init(&ctx->cbc, AV_CODEC_ID_VVC, NULL); + if (ret < 0) + return ret; + au_detector_init(&ctx->au_detector); + + ctx->cbc->decompose_unit_types = decompose_unit_types; + ctx->cbc->nb_decompose_unit_types = FF_ARRAY_ELEMS(decompose_unit_types); + + return ret; +} + +static void vvc_parser_close(AVCodecParserContext *s) +{ + VVCParserContext *ctx = s->priv_data; + + pu_info_unref(&ctx->au_info); + av_packet_unref(&ctx->au); + av_packet_unref(&ctx->last_au); + ff_cbs_fragment_free(&ctx->picture_unit); + + ff_cbs_close(&ctx->cbc); + av_freep(&ctx->pc.buffer); +} + +AVCodecParser ff_vvc_parser = { + .codec_ids = { AV_CODEC_ID_VVC }, + .priv_data_size = sizeof(VVCParserContext), + .parser_init = vvc_parser_init, + .parser_close = vvc_parser_close, + .parser_parse = vvc_parser_parse, +}; From c7864a998720d00c9977bd66fc39c6585f6c2fbf Mon Sep 17 00:00:00 2001 From: Nuo Mi Date: Tue, 21 Mar 2023 16:01:17 +0100 Subject: [PATCH 1691/2172] avcodec: add Metadata bsf for H266/VVC Add H.266/VVC metadata bsf. Signed-off-by: James Almer --- Changelog | 1 + configure | 1 + libavcodec/Makefile | 1 + libavcodec/bitstream_filters.c | 1 + libavcodec/h266_metadata_bsf.c | 149 +++++++++++++++++++++++++++++++++ 5 files changed, 153 insertions(+) create mode 100644 libavcodec/h266_metadata_bsf.c diff --git a/Changelog b/Changelog index e9cbce7e1ce..79744136278 100644 --- a/Changelog +++ b/Changelog @@ -23,6 +23,7 @@ version : - Microsoft RLE video encoder - Raw AC-4 muxer and demuxer - Raw VVC bitstream parser +- Bitstream filter for editing metadata in VVC streams version 6.0: - Radiance HDR image support diff --git a/configure b/configure index 10d12770d69..107d533b3e2 100755 --- a/configure +++ b/configure @@ -3352,6 +3352,7 @@ mjpeg2jpeg_bsf_select="jpegtables" mpeg2_metadata_bsf_select="cbs_mpeg2" trace_headers_bsf_select="cbs" vp9_metadata_bsf_select="cbs_vp9" +vvc_metadata_bsf_select="cbs_h266" # external libraries aac_at_decoder_deps="audiotoolbox" diff --git a/libavcodec/Makefile b/libavcodec/Makefile index b915464b90e..6faa47d1cb9 100644 --- a/libavcodec/Makefile +++ b/libavcodec/Makefile @@ -1261,6 +1261,7 @@ OBJS-$(CONFIG_VP9_METADATA_BSF) += vp9_metadata_bsf.o OBJS-$(CONFIG_VP9_RAW_REORDER_BSF) += vp9_raw_reorder_bsf.o OBJS-$(CONFIG_VP9_SUPERFRAME_BSF) += vp9_superframe_bsf.o OBJS-$(CONFIG_VP9_SUPERFRAME_SPLIT_BSF) += vp9_superframe_split_bsf.o +OBJS-$(CONFIG_VVC_METADATA_BSF) += h266_metadata_bsf.o OBJS-$(CONFIG_EVC_FRAME_MERGE_BSF) += evc_frame_merge_bsf.o # thread libraries diff --git a/libavcodec/bitstream_filters.c b/libavcodec/bitstream_filters.c index 7512fccc782..0d3f52260eb 100644 --- a/libavcodec/bitstream_filters.c +++ b/libavcodec/bitstream_filters.c @@ -65,6 +65,7 @@ extern const FFBitStreamFilter ff_vp9_metadata_bsf; extern const FFBitStreamFilter ff_vp9_raw_reorder_bsf; extern const FFBitStreamFilter ff_vp9_superframe_bsf; extern const FFBitStreamFilter ff_vp9_superframe_split_bsf; +extern const FFBitStreamFilter ff_vvc_metadata_bsf; extern const FFBitStreamFilter ff_evc_frame_merge_bsf; #include "libavcodec/bsf_list.c" diff --git a/libavcodec/h266_metadata_bsf.c b/libavcodec/h266_metadata_bsf.c new file mode 100644 index 00000000000..18fa1a5c9c2 --- /dev/null +++ b/libavcodec/h266_metadata_bsf.c @@ -0,0 +1,149 @@ +/* + * 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/common.h" +#include "libavutil/opt.h" + +#include "bsf.h" +#include "bsf_internal.h" +#include "cbs.h" +#include "cbs_bsf.h" +#include "cbs_h266.h" +#include "vvc.h" + +#define IS_H266_SLICE(nut) (nut <= VVC_RASL_NUT || (nut >= VVC_IDR_W_RADL && nut <= VVC_GDR_NUT)) + +typedef struct H266MetadataContext { + CBSBSFContext common; + + H266RawAUD aud_nal; + + int aud; +} H266MetadataContext; + +static int h266_metadata_update_fragment(AVBSFContext *bsf, AVPacket *pkt, + CodedBitstreamFragment *pu) +{ + H266MetadataContext *ctx = bsf->priv_data; + int err, i; + + // If an AUD is present, it must be the first NAL unit. + if (pu->units[0].type == VVC_AUD_NUT) { + if (ctx->aud == BSF_ELEMENT_REMOVE) + ff_cbs_delete_unit(pu, 0); + } else if ( pkt && ctx->aud == BSF_ELEMENT_INSERT) { + const H266RawSlice *first_slice = NULL; + const H266RawPH *ph = NULL; + H266RawAUD *aud = &ctx->aud_nal; + int pic_type = 0, temporal_id = 8, layer_id = 0; + for (i = 0; i < pu->nb_units; i++) { + const H266RawNALUnitHeader *nal = pu->units[i].content; + if (!nal) + continue; + if (nal->nuh_temporal_id_plus1 < temporal_id + 1) + temporal_id = nal->nuh_temporal_id_plus1 - 1; + if ( nal->nal_unit_type == VVC_PH_NUT ) { + ph = pu->units[i].content; + } else if (IS_H266_SLICE(nal->nal_unit_type)) { + const H266RawSlice *slice = pu->units[i].content; + layer_id = nal->nuh_layer_id; + if (slice->header.sh_slice_type == VVC_SLICE_TYPE_B && + pic_type < 2) + pic_type = 2; + if (slice->header.sh_slice_type == VVC_SLICE_TYPE_P && + pic_type < 1) + pic_type = 1; + if (!first_slice) { + first_slice = slice; + if (first_slice->header. + sh_picture_header_in_slice_header_flag) + ph = &first_slice->header.sh_picture_header; + else if (!ph) + break; + } + } + } + if (!ph) { + av_log(bsf, AV_LOG_ERROR, "no avaliable picture header"); + return AVERROR_INVALIDDATA; + } + + aud->nal_unit_header = (H266RawNALUnitHeader) { + .nal_unit_type = VVC_AUD_NUT, + .nuh_layer_id = layer_id, + .nuh_temporal_id_plus1 = temporal_id + 1, + }; + aud->aud_pic_type = pic_type; + aud->aud_irap_or_gdr_flag = ph->ph_gdr_or_irap_pic_flag; + + err = ff_cbs_insert_unit_content(pu, 0, VVC_AUD_NUT, aud, NULL); + if (err < 0) { + av_log(bsf, AV_LOG_ERROR, "Failed to insert AUD.\n"); + return err; + } + } + + /* TODO: implement more metadata parsing, like VUI, Levels etc. */ + //for (i = 0; i < pu->nb_units; i++) { + // if (pu->units[i].type == VVC_SPS_NUT) { + // } + //} + return 0; +} + +static const CBSBSFType h266_metadata_type = { + .codec_id = AV_CODEC_ID_VVC, + .fragment_name = "access unit", + .unit_name = "NAL unit", + .update_fragment = &h266_metadata_update_fragment, +}; + +static int h266_metadata_init(AVBSFContext *bsf) +{ + return ff_cbs_bsf_generic_init(bsf, &h266_metadata_type); +} + +#define OFFSET(x) offsetof(H266MetadataContext, x) +#define FLAGS (AV_OPT_FLAG_VIDEO_PARAM|AV_OPT_FLAG_BSF_PARAM) +static const AVOption h266_metadata_options[] = { + BSF_ELEMENT_OPTIONS_PIR("aud", "Access Unit Delimiter NAL units", + aud, FLAGS), + + { NULL } +}; + +static const AVClass h266_metadata_class = { + .class_name = "h266_metadata_bsf", + .item_name = av_default_item_name, + .option = h266_metadata_options, + .version = LIBAVUTIL_VERSION_INT, +}; + +static const enum AVCodecID h266_metadata_codec_ids[] = { + AV_CODEC_ID_VVC, AV_CODEC_ID_NONE, +}; + +const FFBitStreamFilter ff_vvc_metadata_bsf = { + .p.name = "vvc_metadata", + .p.codec_ids = h266_metadata_codec_ids, + .p.priv_class = &h266_metadata_class, + .priv_data_size = sizeof(H266MetadataContext), + .init = &h266_metadata_init, + .close = &ff_cbs_bsf_generic_close, + .filter = &ff_cbs_bsf_generic_filter, +}; From 54390f4fa7113db6d5a52515612575fe6ecefc19 Mon Sep 17 00:00:00 2001 From: Thomas Siedel Date: Tue, 21 Mar 2023 16:01:18 +0100 Subject: [PATCH 1692/2172] avcodec: add MP4 to annexb bsf for H266/VVC Add parser for H.266/VVC MP4 to Annex B byte stream format. Signed-off-by: James Almer --- Changelog | 1 + libavcodec/Makefile | 1 + libavcodec/bitstream_filters.c | 1 + libavcodec/vvc_mp4toannexb_bsf.c | 329 +++++++++++++++++++++++++++++++ 4 files changed, 332 insertions(+) create mode 100644 libavcodec/vvc_mp4toannexb_bsf.c diff --git a/Changelog b/Changelog index 79744136278..1e85826c661 100644 --- a/Changelog +++ b/Changelog @@ -24,6 +24,7 @@ version : - Raw AC-4 muxer and demuxer - Raw VVC bitstream parser - Bitstream filter for editing metadata in VVC streams +- Bitstream filter for converting VVC from MP4 to Annex B version 6.0: - Radiance HDR image support diff --git a/libavcodec/Makefile b/libavcodec/Makefile index 6faa47d1cb9..1b0226c089e 100644 --- a/libavcodec/Makefile +++ b/libavcodec/Makefile @@ -1262,6 +1262,7 @@ OBJS-$(CONFIG_VP9_RAW_REORDER_BSF) += vp9_raw_reorder_bsf.o OBJS-$(CONFIG_VP9_SUPERFRAME_BSF) += vp9_superframe_bsf.o OBJS-$(CONFIG_VP9_SUPERFRAME_SPLIT_BSF) += vp9_superframe_split_bsf.o OBJS-$(CONFIG_VVC_METADATA_BSF) += h266_metadata_bsf.o +OBJS-$(CONFIG_VVC_MP4TOANNEXB_BSF) += vvc_mp4toannexb_bsf.o OBJS-$(CONFIG_EVC_FRAME_MERGE_BSF) += evc_frame_merge_bsf.o # thread libraries diff --git a/libavcodec/bitstream_filters.c b/libavcodec/bitstream_filters.c index 0d3f52260eb..1e9a676a3d2 100644 --- a/libavcodec/bitstream_filters.c +++ b/libavcodec/bitstream_filters.c @@ -66,6 +66,7 @@ extern const FFBitStreamFilter ff_vp9_raw_reorder_bsf; extern const FFBitStreamFilter ff_vp9_superframe_bsf; extern const FFBitStreamFilter ff_vp9_superframe_split_bsf; extern const FFBitStreamFilter ff_vvc_metadata_bsf; +extern const FFBitStreamFilter ff_vvc_mp4toannexb_bsf; extern const FFBitStreamFilter ff_evc_frame_merge_bsf; #include "libavcodec/bsf_list.c" diff --git a/libavcodec/vvc_mp4toannexb_bsf.c b/libavcodec/vvc_mp4toannexb_bsf.c new file mode 100644 index 00000000000..9e606cdc274 --- /dev/null +++ b/libavcodec/vvc_mp4toannexb_bsf.c @@ -0,0 +1,329 @@ +/* + * H.266/VVC MP4 to Annex B byte stream format filter + * Copyright (c) 2022, Thomas Siedel + * + * 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/intreadwrite.h" +#include "libavutil/mem.h" + +#include "avcodec.h" +#include "bsf.h" +#include "bsf_internal.h" +#include "bytestream.h" +#include "vvc.h" + +#include "libavcodec/get_bits.h" + +#define MIN_VVCC_LENGTH 23 + +typedef struct VVCBSFContext { + uint8_t length_size; + int extradata_parsed; +} VVCBSFContext; + +static int vvc_extradata_to_annexb(AVBSFContext *ctx) +{ + GetByteContext gb; + int length_size, num_arrays, i, j; + int ret = 0; + int temp = 0; + int ptl_present; + + uint8_t *new_extradata = NULL; + size_t new_extradata_size = 0; + + int max_picture_width = 0; + int max_picture_height = 0; + int avg_frame_rate = 0; + + bytestream2_init(&gb, ctx->par_in->extradata, ctx->par_in->extradata_size); + temp = bytestream2_get_byte(&gb); + length_size = ((temp & 6) >> 1) + 1; + ptl_present = temp & 1; + if (ptl_present) { + int num_bytes_constraint_info; + int general_profile_idc; + int general_tier_flag; + int general_level_idc; + int ptl_frame_only_constraint_flag; + int ptl_multi_layer_enabled_flag; + int ptl_num_sub_profiles; + int temp3, temp4, temp5; + int temp2 = bytestream2_get_be16(&gb); + int ols_idx = (temp2 >> 7) & 0x1ff; + int num_sublayers = (temp2 >> 4) & 0x7; + int constant_frame_rate = (temp2 >> 2) & 0x3; + int chroma_format_idc = temp2 & 0x3; + int bit_depth_minus8 = (bytestream2_get_byte(&gb) >> 5) & 0x7; + av_log(ctx, AV_LOG_DEBUG, + "bit_depth_minus8 %d chroma_format_idc %d\n", bit_depth_minus8, + chroma_format_idc); + av_log(ctx, AV_LOG_DEBUG, "constant_frame_rate %d, ols_idx %d\n", + constant_frame_rate, ols_idx); + // VvcPTLRecord(num_sublayers) native_ptl + temp3 = bytestream2_get_byte(&gb); + num_bytes_constraint_info = (temp3) & 0x3f; + temp4 = bytestream2_get_byte(&gb); + general_profile_idc = (temp4 >> 1) & 0x7f; + general_tier_flag = (temp4) & 1; + general_level_idc = bytestream2_get_byte(&gb); + av_log(ctx, AV_LOG_DEBUG, + "general_profile_idc %d, general_tier_flag %d, general_level_idc %d, num_sublayers %d num_bytes_constraint_info %d\n", + general_profile_idc, general_tier_flag, general_level_idc, + num_sublayers, num_bytes_constraint_info); + + temp5 = bytestream2_get_byte(&gb); + ptl_frame_only_constraint_flag = (temp5 >> 7) & 0x1; + ptl_multi_layer_enabled_flag = (temp5 >> 6) & 0x1; + for (i = 0; i < num_bytes_constraint_info - 1; i++) { + // unsigned int(8*num_bytes_constraint_info - 2) general_constraint_info; + bytestream2_get_byte(&gb); + } + + av_log(ctx, AV_LOG_DEBUG, + "ptl_multi_layer_enabled_flag %d, ptl_frame_only_constraint_flag %d\n", + ptl_multi_layer_enabled_flag, ptl_frame_only_constraint_flag); + + if (num_sublayers > 1) { + int temp6 = bytestream2_get_byte(&gb); + uint8_t ptl_sublayer_level_present_flag[8] = { 0 }; + //uint8_t sublayer_level_idc[8] = {0}; + for (i = num_sublayers - 2; i >= 0; i--) { + ptl_sublayer_level_present_flag[i] = + (temp6 >> (7 - (num_sublayers - 2 - i))) & 0x01; + } + // for (j=num_sublayers; j<=8 && num_sublayers > 1; j++) + // bit(1) ptl_reserved_zero_bit = 0; + for (i = num_sublayers - 2; i >= 0; i--) { + if (ptl_sublayer_level_present_flag[i]) { + //sublayer_level_idc[i] = bytestream2_get_byte(&gb); + } + } + } + + ptl_num_sub_profiles = bytestream2_get_byte(&gb); + for (j = 0; j < ptl_num_sub_profiles; j++) { + // unsigned int(32) general_sub_profile_idc[j]; + bytestream2_get_be16(&gb); + bytestream2_get_be16(&gb); + } + + max_picture_width = bytestream2_get_be16(&gb); // unsigned_int(16) max_picture_width; + max_picture_height = bytestream2_get_be16(&gb); // unsigned_int(16) max_picture_height; + avg_frame_rate = bytestream2_get_be16(&gb); // unsigned int(16) avg_frame_rate; } + av_log(ctx, AV_LOG_DEBUG, + "max_picture_width %d, max_picture_height %d, avg_frame_rate %d\n", + max_picture_width, max_picture_height, avg_frame_rate); + } + + num_arrays = bytestream2_get_byte(&gb); + + for (i = 0; i < num_arrays; i++) { + int cnt; + int type = bytestream2_get_byte(&gb) & 0x1f; + + if (type == VVC_OPI_NUT || type == VVC_DCI_NUT) + cnt = 1; + else + cnt = bytestream2_get_be16(&gb); + + av_log(ctx, AV_LOG_DEBUG, "nalu_type %d cnt %d\n", type, cnt); + + if (!(type == VVC_OPI_NUT || type == VVC_DCI_NUT || + type == VVC_VPS_NUT || type == VVC_SPS_NUT || type == VVC_PPS_NUT + || type == VVC_PREFIX_SEI_NUT || type == VVC_SUFFIX_SEI_NUT)) { + av_log(ctx, AV_LOG_ERROR, + "Invalid NAL unit type in extradata: %d\n", type); + ret = AVERROR_INVALIDDATA; + goto fail; + } + + for (j = 0; j < cnt; j++) { + int nalu_len = bytestream2_get_be16(&gb); + + if (4 + AV_INPUT_BUFFER_PADDING_SIZE + nalu_len > + SIZE_MAX - new_extradata_size) { + ret = AVERROR_INVALIDDATA; + goto fail; + } + ret = av_reallocp(&new_extradata, new_extradata_size + nalu_len + 4 + + AV_INPUT_BUFFER_PADDING_SIZE); + if (ret < 0) + goto fail; + + AV_WB32(new_extradata + new_extradata_size, 1); // add the startcode + bytestream2_get_buffer(&gb, new_extradata + new_extradata_size + 4, + nalu_len); + new_extradata_size += 4 + nalu_len; + memset(new_extradata + new_extradata_size, 0, + AV_INPUT_BUFFER_PADDING_SIZE); + } + } + + av_freep(&ctx->par_out->extradata); + ctx->par_out->extradata = new_extradata; + ctx->par_out->extradata_size = new_extradata_size; + + if (!new_extradata_size) + av_log(ctx, AV_LOG_WARNING, "No parameter sets in the extradata\n"); + + return length_size; + fail: + av_freep(&new_extradata); + return ret; +} + +static int vvc_mp4toannexb_init(AVBSFContext *ctx) +{ + VVCBSFContext *s = ctx->priv_data; + int ret; + + if (ctx->par_in->extradata_size < MIN_VVCC_LENGTH || + AV_RB24(ctx->par_in->extradata) == 1 || + AV_RB32(ctx->par_in->extradata) == 1) { + av_log(ctx, AV_LOG_VERBOSE, + "The input looks like it is Annex B already\n"); + } else { + ret = vvc_extradata_to_annexb(ctx); + if (ret < 0) + return ret; + s->length_size = ret; + s->extradata_parsed = 1; + } + + return 0; +} + +static int vvc_mp4toannexb_filter(AVBSFContext *ctx, AVPacket *out) +{ + VVCBSFContext *s = ctx->priv_data; + AVPacket *in; + GetByteContext gb; + + int is_irap = 0; + int added_extra = 0; + int i, ret = 0; + + ret = ff_bsf_get_packet(ctx, &in); + if (ret < 0) + return ret; + + if (!s->extradata_parsed) { + av_packet_move_ref(out, in); + av_packet_free(&in); + return 0; + } + + bytestream2_init(&gb, in->data, in->size); + + /* check if this packet contains an IRAP. The extradata will need to be added before any potential PH_NUT */ + while (bytestream2_get_bytes_left(&gb)) { + uint32_t nalu_size = 0; + int nalu_type; + + if (bytestream2_get_bytes_left(&gb) < s->length_size) { + ret = AVERROR_INVALIDDATA; + goto fail; + } + + for (i = 0; i < s->length_size; i++) + nalu_size = (nalu_size << 8) | bytestream2_get_byte(&gb); + + if (nalu_size < 2 || nalu_size > bytestream2_get_bytes_left(&gb)) { + ret = AVERROR_INVALIDDATA; + goto fail; + } + + nalu_type = (bytestream2_peek_be16(&gb) >> 3) & 0x1f; + is_irap = nalu_type >= VVC_IDR_W_RADL && nalu_type <= VVC_RSV_IRAP_11; + if (is_irap) { + break; + } + bytestream2_seek(&gb, nalu_size, SEEK_CUR); + } + + bytestream2_seek(&gb, 0, SEEK_SET); + while (bytestream2_get_bytes_left(&gb)) { + uint32_t nalu_size = 0; + int nalu_type; + int add_extradata, extra_size, prev_size; + + if (bytestream2_get_bytes_left(&gb) < s->length_size) { + ret = AVERROR_INVALIDDATA; + goto fail; + } + + for (i = 0; i < s->length_size; i++) + nalu_size = (nalu_size << 8) | bytestream2_get_byte(&gb); + + if (nalu_size < 2 || nalu_size > bytestream2_get_bytes_left(&gb)) { + ret = AVERROR_INVALIDDATA; + goto fail; + } + + nalu_type = (bytestream2_peek_be16(&gb) >> 3) & 0x1f; + + /* prepend extradata to IRAP frames */ + add_extradata = is_irap && nalu_type != VVC_AUD_NUT && !added_extra; + extra_size = add_extradata * ctx->par_out->extradata_size; + added_extra |= add_extradata; + + if (FFMIN(INT_MAX, SIZE_MAX) < 4ULL + nalu_size + extra_size) { + ret = AVERROR_INVALIDDATA; + goto fail; + } + + prev_size = out->size; + + ret = av_grow_packet(out, 4 + nalu_size + extra_size); + if (ret < 0) + goto fail; + + if (extra_size) + memcpy(out->data + prev_size, ctx->par_out->extradata, extra_size); + AV_WB32(out->data + prev_size + extra_size, 1); + bytestream2_get_buffer(&gb, out->data + prev_size + 4 + extra_size, + nalu_size); + } + + ret = av_packet_copy_props(out, in); + if (ret < 0) + goto fail; + + fail: + if (ret < 0) + av_packet_unref(out); + av_packet_free(&in); + + return ret; +} + +static const enum AVCodecID codec_ids[] = { + AV_CODEC_ID_VVC, AV_CODEC_ID_NONE, +}; + +const FFBitStreamFilter ff_vvc_mp4toannexb_bsf = { + .p.name = "vvc_mp4toannexb", + .p.codec_ids = codec_ids, + .priv_data_size = sizeof(VVCBSFContext), + .init = vvc_mp4toannexb_init, + .filter = vvc_mp4toannexb_filter, +}; From 86796f1f0ef7d18395943f4cf5b3afbac87e4d65 Mon Sep 17 00:00:00 2001 From: James Almer Date: Thu, 29 Jun 2023 12:19:24 -0300 Subject: [PATCH 1693/2172] avcodec/version: bump minor after recent additions Signed-off-by: James Almer --- libavcodec/version.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavcodec/version.h b/libavcodec/version.h index da6f3a84ac1..9411511e043 100644 --- a/libavcodec/version.h +++ b/libavcodec/version.h @@ -29,7 +29,7 @@ #include "version_major.h" -#define LIBAVCODEC_VERSION_MINOR 21 +#define LIBAVCODEC_VERSION_MINOR 22 #define LIBAVCODEC_VERSION_MICRO 100 #define LIBAVCODEC_VERSION_INT AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \ From ac2b25f4e5ad0f03cf2a17c82defe2b1ba7a02b1 Mon Sep 17 00:00:00 2001 From: Thomas Siedel Date: Tue, 21 Mar 2023 16:01:19 +0100 Subject: [PATCH 1694/2172] avformat: add demuxer and probe support for H266/VVC Add demuxer to probe raw vvc and parse vvcc byte stream format. Co-authored-by: Nuo Mi Signed-off-by: James Almer --- Changelog | 2 +- libavformat/Makefile | 1 + libavformat/allformats.c | 1 + libavformat/demux.c | 7 +++-- libavformat/vvcdec.c | 61 ++++++++++++++++++++++++++++++++++++++++ 5 files changed, 69 insertions(+), 3 deletions(-) create mode 100644 libavformat/vvcdec.c diff --git a/Changelog b/Changelog index 1e85826c661..9a05ebe0163 100644 --- a/Changelog +++ b/Changelog @@ -22,7 +22,7 @@ version : - bwdif_cuda filter - Microsoft RLE video encoder - Raw AC-4 muxer and demuxer -- Raw VVC bitstream parser +- Raw VVC bitstream parser and demuxer - Bitstream filter for editing metadata in VVC streams - Bitstream filter for converting VVC from MP4 to Annex B diff --git a/libavformat/Makefile b/libavformat/Makefile index 2b90b788c0e..239b779d1ee 100644 --- a/libavformat/Makefile +++ b/libavformat/Makefile @@ -603,6 +603,7 @@ OBJS-$(CONFIG_VOC_MUXER) += vocenc.o voc.o OBJS-$(CONFIG_VPK_DEMUXER) += vpk.o OBJS-$(CONFIG_VPLAYER_DEMUXER) += vplayerdec.o subtitles.o OBJS-$(CONFIG_VQF_DEMUXER) += vqf.o +OBJS-$(CONFIG_VVC_DEMUXER) += vvcdec.o rawdec.o OBJS-$(CONFIG_W64_DEMUXER) += wavdec.o w64.o pcm.o OBJS-$(CONFIG_W64_MUXER) += wavenc.o w64.o OBJS-$(CONFIG_WADY_DEMUXER) += wady.o pcm.o diff --git a/libavformat/allformats.c b/libavformat/allformats.c index f64b0870aac..05c4e47a635 100644 --- a/libavformat/allformats.c +++ b/libavformat/allformats.c @@ -486,6 +486,7 @@ extern const FFOutputFormat ff_voc_muxer; extern const AVInputFormat ff_vpk_demuxer; extern const AVInputFormat ff_vplayer_demuxer; extern const AVInputFormat ff_vqf_demuxer; +extern const AVInputFormat ff_vvc_demuxer; extern const AVInputFormat ff_w64_demuxer; extern const FFOutputFormat ff_w64_muxer; extern const AVInputFormat ff_wady_demuxer; diff --git a/libavformat/demux.c b/libavformat/demux.c index 1b21b8440c5..1ef297d5e70 100644 --- a/libavformat/demux.c +++ b/libavformat/demux.c @@ -121,6 +121,7 @@ static int set_codec_from_probe_data(AVFormatContext *s, AVStream *st, { "mpegvideo", AV_CODEC_ID_MPEG2VIDEO, AVMEDIA_TYPE_VIDEO }, { "truehd", AV_CODEC_ID_TRUEHD, AVMEDIA_TYPE_AUDIO }, { "evc", AV_CODEC_ID_EVC, AVMEDIA_TYPE_VIDEO }, + { "vvc", AV_CODEC_ID_VVC, AVMEDIA_TYPE_VIDEO }, { 0 } }; int score; @@ -753,7 +754,8 @@ static int64_t select_from_pts_buffer(AVStream *st, int64_t *pts_buffer, int64_t { FFStream *const sti = ffstream(st); int onein_oneout = st->codecpar->codec_id != AV_CODEC_ID_H264 && - st->codecpar->codec_id != AV_CODEC_ID_HEVC; + st->codecpar->codec_id != AV_CODEC_ID_HEVC && + st->codecpar->codec_id != AV_CODEC_ID_VVC; if (!onein_oneout) { int delay = sti->avctx->has_b_frames; @@ -943,7 +945,8 @@ static void compute_pkt_fields(AVFormatContext *s, AVStream *st, int64_t offset; AVRational duration; int onein_oneout = st->codecpar->codec_id != AV_CODEC_ID_H264 && - st->codecpar->codec_id != AV_CODEC_ID_HEVC; + st->codecpar->codec_id != AV_CODEC_ID_HEVC && + st->codecpar->codec_id != AV_CODEC_ID_VVC; if (s->flags & AVFMT_FLAG_NOFILLIN) return; diff --git a/libavformat/vvcdec.c b/libavformat/vvcdec.c new file mode 100644 index 00000000000..31c5ae1f148 --- /dev/null +++ b/libavformat/vvcdec.c @@ -0,0 +1,61 @@ +/* + * RAW H.266 / VVC video demuxer + * Copyright (c) 2020 Nuo Mi + * + * 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/vvc.h" + +#include "avformat.h" +#include "rawdec.h" + +static int vvc_probe(const AVProbeData *p) +{ + uint32_t code = -1; + int sps = 0, pps = 0, irap = 0; + int i; + + for (i = 0; i < p->buf_size - 1; i++) { + code = (code << 8) + p->buf[i]; + if ((code & 0xffffff00) == 0x100) { + uint8_t nal2 = p->buf[i + 1]; + int type = (nal2 & 0xF8) >> 3; + + if (code & 0x80) // forbidden_zero_bit + return 0; + + if ((nal2 & 0x7) == 0) // nuh_temporal_id_plus1 + return 0; + + switch (type) { + case VVC_SPS_NUT: sps++; break; + case VVC_PPS_NUT: pps++; break; + case VVC_IDR_N_LP: + case VVC_IDR_W_RADL: + case VVC_CRA_NUT: + case VVC_GDR_NUT: irap++; break; + } + } + } + + if (sps && pps && irap) + return AVPROBE_SCORE_EXTENSION + 1; // 1 more than .mpg + return 0; +} + +FF_DEF_RAWVIDEO_DEMUXER(vvc, "raw H.266/VVC video", vvc_probe, "h266,266,vvc", AV_CODEC_ID_VVC) From 45a8a62df9b9c6c93c003b177ce0190860c1f8e8 Mon Sep 17 00:00:00 2001 From: Thomas Siedel Date: Tue, 21 Mar 2023 16:01:20 +0100 Subject: [PATCH 1695/2172] avformat/rawenc: add H266/VVC muxer Signed-off-by: James Almer --- Changelog | 2 +- libavformat/Makefile | 1 + libavformat/allformats.c | 1 + libavformat/rawenc.c | 23 +++++++++++++++++++++++ 4 files changed, 26 insertions(+), 1 deletion(-) diff --git a/Changelog b/Changelog index 9a05ebe0163..38760828441 100644 --- a/Changelog +++ b/Changelog @@ -22,7 +22,7 @@ version : - bwdif_cuda filter - Microsoft RLE video encoder - Raw AC-4 muxer and demuxer -- Raw VVC bitstream parser and demuxer +- Raw VVC bitstream parser, muxer and demuxer - Bitstream filter for editing metadata in VVC streams - Bitstream filter for converting VVC from MP4 to Annex B diff --git a/libavformat/Makefile b/libavformat/Makefile index 239b779d1ee..4cb00f8700a 100644 --- a/libavformat/Makefile +++ b/libavformat/Makefile @@ -604,6 +604,7 @@ OBJS-$(CONFIG_VPK_DEMUXER) += vpk.o OBJS-$(CONFIG_VPLAYER_DEMUXER) += vplayerdec.o subtitles.o OBJS-$(CONFIG_VQF_DEMUXER) += vqf.o OBJS-$(CONFIG_VVC_DEMUXER) += vvcdec.o rawdec.o +OBJS-$(CONFIG_VVC_MUXER) += rawenc.o OBJS-$(CONFIG_W64_DEMUXER) += wavdec.o w64.o pcm.o OBJS-$(CONFIG_W64_MUXER) += wavenc.o w64.o OBJS-$(CONFIG_WADY_DEMUXER) += wady.o pcm.o diff --git a/libavformat/allformats.c b/libavformat/allformats.c index 05c4e47a635..6324952bd2c 100644 --- a/libavformat/allformats.c +++ b/libavformat/allformats.c @@ -487,6 +487,7 @@ extern const AVInputFormat ff_vpk_demuxer; extern const AVInputFormat ff_vplayer_demuxer; extern const AVInputFormat ff_vqf_demuxer; extern const AVInputFormat ff_vvc_demuxer; +extern const FFOutputFormat ff_vvc_muxer; extern const AVInputFormat ff_w64_demuxer; extern const FFOutputFormat ff_w64_muxer; extern const AVInputFormat ff_wady_demuxer; diff --git a/libavformat/rawenc.c b/libavformat/rawenc.c index 70d6322c537..f916db13a20 100644 --- a/libavformat/rawenc.c +++ b/libavformat/rawenc.c @@ -378,6 +378,29 @@ const FFOutputFormat ff_h264_muxer = { }; #endif +#if CONFIG_VVC_MUXER +static int vvc_check_bitstream(AVFormatContext *s, AVStream *st, + const AVPacket *pkt) +{ + if (pkt->size >= 5 && AV_RB32(pkt->data) != 0x0000001 && + AV_RB24(pkt->data) != 0x000001) + return ff_stream_add_bitstream_filter(st, "vvc_mp4toannexb", NULL); + return 1; +} + +const FFOutputFormat ff_vvc_muxer = { + .p.name = "vvc", + .p.long_name = NULL_IF_CONFIG_SMALL("raw H.266/VVC video"), + .p.extensions = "vvc,h266,266", + .p.audio_codec = AV_CODEC_ID_NONE, + .p.video_codec = AV_CODEC_ID_VVC, + .init = force_one_stream, + .write_packet = ff_raw_write_packet, + .check_bitstream = vvc_check_bitstream, + .p.flags = AVFMT_NOTIMESTAMPS, +}; +#endif + #if CONFIG_HEVC_MUXER static int hevc_check_bitstream(AVFormatContext *s, AVStream *st, const AVPacket *pkt) From 05186be641159c99b9de241cc40bb8cf4c8b81b1 Mon Sep 17 00:00:00 2001 From: James Almer Date: Thu, 29 Jun 2023 12:19:52 -0300 Subject: [PATCH 1696/2172] avformat/version: bump minor after recent additions Signed-off-by: James Almer --- libavformat/version.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavformat/version.h b/libavformat/version.h index 1b079ebce8c..979952183cc 100644 --- a/libavformat/version.h +++ b/libavformat/version.h @@ -31,7 +31,7 @@ #include "version_major.h" -#define LIBAVFORMAT_VERSION_MINOR 9 +#define LIBAVFORMAT_VERSION_MINOR 10 #define LIBAVFORMAT_VERSION_MICRO 100 #define LIBAVFORMAT_VERSION_INT AV_VERSION_INT(LIBAVFORMAT_VERSION_MAJOR, \ From 9367b58e71a618d3125526ef2c5dc94b1e39caca Mon Sep 17 00:00:00 2001 From: James Almer Date: Thu, 29 Jun 2023 09:58:29 -0300 Subject: [PATCH 1697/2172] tools/target_bsf_fuzzer: set aud option on h266_metadata bsf Signed-off-by: James Almer --- tools/target_bsf_fuzzer.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tools/target_bsf_fuzzer.c b/tools/target_bsf_fuzzer.c index 703647b61bf..c8fab003439 100644 --- a/tools/target_bsf_fuzzer.c +++ b/tools/target_bsf_fuzzer.c @@ -94,7 +94,8 @@ int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { if (flags & 0x20) { if (!strcmp(f->name, "av1_metadata")) av_opt_set_int(bsf->priv_data, "td", bytestream2_get_byte(&gbc) % 3, 0); - else if (!strcmp(f->name, "h264_metadata") || !strcmp(f->name, "h265_metadata")) + else if (!strcmp(f->name, "h264_metadata") || !strcmp(f->name, "h265_metadata") || + !strcmp(f->name, "h266_metadata")) av_opt_set_int(bsf->priv_data, "aud", bytestream2_get_byte(&gbc) % 3, 0); else if (!strcmp(f->name, "extract_extradata")) av_opt_set_int(bsf->priv_data, "remove", bytestream2_get_byte(&gbc) & 1, 0); From e132fae1a56eab1327d5bf83f1eca3f2491cbfb3 Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt Date: Thu, 29 Jun 2023 20:10:55 +0200 Subject: [PATCH 1698/2172] avcodec/cbs_h266: Remove double ; Fixes a warning from GCC when in pedantic mode: "extra semicolon in struct or union specified" May also fix compilation with MSVC, see https://fate.ffmpeg.org/report.cgi?time=20230629174305&slot=x86_64-msvc17-windows-native Reviewed-by: James Almer Signed-off-by: Andreas Rheinhardt --- libavcodec/cbs_h266.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libavcodec/cbs_h266.h b/libavcodec/cbs_h266.h index 8548e501c05..03dfd4a9542 100644 --- a/libavcodec/cbs_h266.h +++ b/libavcodec/cbs_h266.h @@ -80,7 +80,7 @@ typedef struct H266GeneralConstraintsInfo { /* inter */ uint8_t gci_no_ref_pic_resampling_constraint_flag; - uint8_t gci_no_res_change_in_clvs_constraint_flag;; + uint8_t gci_no_res_change_in_clvs_constraint_flag; uint8_t gci_no_weighted_prediction_constraint_flag; uint8_t gci_no_ref_wraparound_constraint_flag; uint8_t gci_no_temporal_mvp_constraint_flag; @@ -211,7 +211,7 @@ typedef struct H266RawVUI { uint8_t vui_aspect_ratio_idc; uint16_t vui_sar_width; - uint16_t vui_sar_height;; + uint16_t vui_sar_height; uint8_t vui_overscan_info_present_flag; uint8_t vui_overscan_appropriate_flag; From 22c47b10b28c0c47298d34a7108d378be5d7d08e Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt Date: Thu, 29 Jun 2023 20:12:23 +0200 Subject: [PATCH 1699/2172] avcodec/vvc_parser: Constify parser The discrepancy between the definition and the declaration in parsers.c is actually UB. Reviewed-by: James Almer Signed-off-by: Andreas Rheinhardt --- libavcodec/vvc_parser.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavcodec/vvc_parser.c b/libavcodec/vvc_parser.c index 4f7657f7ab7..f350fe70a92 100644 --- a/libavcodec/vvc_parser.c +++ b/libavcodec/vvc_parser.c @@ -571,7 +571,7 @@ static void vvc_parser_close(AVCodecParserContext *s) av_freep(&ctx->pc.buffer); } -AVCodecParser ff_vvc_parser = { +const AVCodecParser ff_vvc_parser = { .codec_ids = { AV_CODEC_ID_VVC }, .priv_data_size = sizeof(VVCParserContext), .parser_init = vvc_parser_init, From 652add3a6d675a568eb7564d85434712829b03d3 Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt Date: Thu, 29 Jun 2023 20:15:36 +0200 Subject: [PATCH 1700/2172] avfilter/vf_ccrepack: Constify filter The discrepancy between the definition and the declaration in allfilters.c is actually UB. Reviewed-by: James Almer Signed-off-by: Andreas Rheinhardt --- libavfilter/vf_ccrepack.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavfilter/vf_ccrepack.c b/libavfilter/vf_ccrepack.c index 61eb2128ae8..950bb7b528d 100644 --- a/libavfilter/vf_ccrepack.c +++ b/libavfilter/vf_ccrepack.c @@ -92,7 +92,7 @@ static const AVFilterPad avfilter_vf_ccrepack_outputs[] = { }, }; -AVFilter ff_vf_ccrepack = { +const AVFilter ff_vf_ccrepack = { .name = "ccrepack", .description = NULL_IF_CONFIG_SMALL("Repack CEA-708 closed caption metadata"), .uninit = uninit, From f780e07149bc3aec592e74c5eb2ee6acaa719127 Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt Date: Thu, 29 Jun 2023 20:16:14 +0200 Subject: [PATCH 1701/2172] avformat/ac4dec: Constify demuxer The discrepancy between the definition and the declaration in allformats.c is actually UB. Signed-off-by: Andreas Rheinhardt --- libavformat/ac4dec.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavformat/ac4dec.c b/libavformat/ac4dec.c index eb7bbaa655c..71950f52dcd 100644 --- a/libavformat/ac4dec.c +++ b/libavformat/ac4dec.c @@ -93,7 +93,7 @@ static int ac4_read_packet(AVFormatContext *s, AVPacket *pkt) return ret; } -AVInputFormat ff_ac4_demuxer = { +const AVInputFormat ff_ac4_demuxer = { .name = "ac4", .long_name = NULL_IF_CONFIG_SMALL("raw AC-4"), .read_probe = ac4_probe, From 0cd2e7dcfbc835f4519f1b2b7da6bd902dbb0190 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kacper=20Michaj=C5=82ow?= Date: Thu, 1 Jun 2023 21:43:47 +0200 Subject: [PATCH 1702/2172] avformat/http: copy only mime type from Content-Type MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Content-Type can include charset and boundary which is not a part of mime type and shouldn't be copied as such. Fixes HLS playback when the Content-Type includes additional fields. Signed-off-by: Kacper Michajłow --- libavformat/http.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavformat/http.c b/libavformat/http.c index 0817aafb5b2..fd931c2d8e7 100644 --- a/libavformat/http.c +++ b/libavformat/http.c @@ -1205,7 +1205,7 @@ static int process_line(URLContext *h, char *line, int line_count) } } else if (!av_strcasecmp(tag, "Content-Type")) { av_free(s->mime_type); - s->mime_type = av_strdup(p); + s->mime_type = av_get_token((const char **)&p, ";"); } else if (!av_strcasecmp(tag, "Set-Cookie")) { if (parse_cookie(s, p, &s->cookie_dict)) av_log(h, AV_LOG_WARNING, "Unable to parse '%s'\n", p); From 6caf5642c88252c7a80d6bc25c0b5d11646c09c2 Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt Date: Thu, 29 Jun 2023 22:39:56 +0200 Subject: [PATCH 1703/2172] avcodec/vvc_parser: Remove unnecessary headers Reviewed-by: James Almer Signed-off-by: Andreas Rheinhardt --- libavcodec/vvc_parser.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/libavcodec/vvc_parser.c b/libavcodec/vvc_parser.c index f350fe70a92..efea833565e 100644 --- a/libavcodec/vvc_parser.c +++ b/libavcodec/vvc_parser.c @@ -22,9 +22,7 @@ #include "cbs.h" #include "cbs_h266.h" -#include "internal.h" #include "parser.h" -#include "decode.h" #define START_CODE 0x000001 ///< start_code_prefix_one_3bytes #define IS_IDR(nut) (nut == VVC_IDR_W_RADL || nut == VVC_IDR_N_LP) From 0009cbe11d0a57da447ad9234c57f98701e8553b Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt Date: Thu, 29 Jun 2023 23:29:18 +0200 Subject: [PATCH 1704/2172] avcodec/vvc_parser: Don't store state unnecessarily VVCParserContext.au_info is only used once (and in a read-only manner); but this happens immediately after au_info has been completely overwritten. Therefore one can just the src structure used to overwrite au_info directly and remove au_info. This also means that the whole referencing and unreferncing of au_info (which duplicates AVBufferRefs CodedBitstreamH266Context and is therefore of dubious gain) can be removed, as can the AVBufferRef* contained in PuInfo; this also removes a certain uglyness: Sometimes these AVBufferRef* were ownership pointers and sometimes not. Reviewed-by: James Almer Signed-off-by: Andreas Rheinhardt --- libavcodec/vvc_parser.c | 63 +---------------------------------------- 1 file changed, 1 insertion(+), 62 deletions(-) diff --git a/libavcodec/vvc_parser.c b/libavcodec/vvc_parser.c index efea833565e..69696eef572 100644 --- a/libavcodec/vvc_parser.c +++ b/libavcodec/vvc_parser.c @@ -29,11 +29,6 @@ #define IS_H266_SLICE(nut) (nut <= VVC_RASL_NUT || (nut >= VVC_IDR_W_RADL && nut <= VVC_GDR_NUT)) typedef struct PuInfo { - AVBufferRef *sps_ref; - AVBufferRef *pps_ref; - AVBufferRef *slice_ref; - AVBufferRef *ph_ref; - const H266RawPPS *pps; const H266RawSPS *sps; const H266RawPH *ph; @@ -53,7 +48,6 @@ typedef struct VVCParserContext { CodedBitstreamFragment picture_unit; - PuInfo au_info; AVPacket au; AVPacket last_au; @@ -150,41 +144,6 @@ static int get_pict_type(const CodedBitstreamFragment *pu) return has_p ? AV_PICTURE_TYPE_P : AV_PICTURE_TYPE_I; } -static void pu_info_unref(PuInfo *info) -{ - av_buffer_unref(&info->slice_ref); - av_buffer_unref(&info->ph_ref); - av_buffer_unref(&info->pps_ref); - av_buffer_unref(&info->sps_ref); - info->slice = NULL; - info->ph = NULL; - info->pps = NULL; - info->sps = NULL; - info->pic_type = AV_PICTURE_TYPE_NONE; -} - -static int pu_info_ref(PuInfo *dest, const PuInfo *src) -{ - pu_info_unref(dest); - dest->sps_ref = av_buffer_ref(src->sps_ref); - dest->pps_ref = av_buffer_ref(src->pps_ref); - if (src->ph_ref) - dest->ph_ref = av_buffer_ref(src->ph_ref); - dest->slice_ref = av_buffer_ref(src->slice_ref); - if (!dest->sps_ref || !dest->pps_ref || (src->ph_ref && !dest->ph_ref) - || !dest->slice_ref) { - pu_info_unref(dest); - return AVERROR(ENOMEM); - } - - dest->sps = src->sps; - dest->pps = src->pps; - dest->ph = src->ph; - dest->slice = src->slice; - dest->pic_type = src->pic_type; - return 0; -} - static void set_parser_ctx(AVCodecParserContext *s, AVCodecContext *avctx, const PuInfo *pu) { @@ -241,20 +200,6 @@ static void set_parser_ctx(AVCodecParserContext *s, AVCodecContext *avctx, } } -static int set_ctx(AVCodecParserContext *s, AVCodecContext *avctx, - const PuInfo *next_pu) -{ - VVCParserContext *ctx = s->priv_data; - - int ret = pu_info_ref(&ctx->au_info, next_pu); - if (ret < 0) - return ret; - - set_parser_ctx(s, avctx, &ctx->au_info); - - return 0; -} - //8.3.1 Decoding process for picture order count. //VTM did not follow the spec, and it's much simpler than spec. //We follow the VTM. @@ -338,10 +283,8 @@ static int get_pu_info(PuInfo *info, const CodedBitstreamH266Context *h266, continue; if ( nal->nal_unit_type == VVC_PH_NUT ) { info->ph = pu->units[i].content; - info->ph_ref = pu->units[i].content_ref; } else if (IS_H266_SLICE(nal->nal_unit_type)) { info->slice = pu->units[i].content; - info->slice_ref = pu->units[i].content_ref; if (info->slice->header.sh_picture_header_in_slice_header_flag) info->ph = &info->slice->header.sh_picture_header; if (!info->ph) { @@ -365,7 +308,6 @@ static int get_pu_info(PuInfo *info, const CodedBitstreamH266Context *h266, ret = AVERROR_INVALIDDATA; goto error; } - info->pps_ref = h266->pps_ref[info->ph->ph_pic_parameter_set_id]; info->sps = h266->sps[info->pps->pps_seq_parameter_set_id]; if (!info->sps) { av_log(logctx, AV_LOG_ERROR, "SPS id %d is not avaliable.\n", @@ -373,7 +315,6 @@ static int get_pu_info(PuInfo *info, const CodedBitstreamH266Context *h266, ret = AVERROR_INVALIDDATA; goto error; } - info->sps_ref = h266->sps_ref[info->pps->pps_seq_parameter_set_id]; info->pic_type = get_pict_type(pu); return 0; error: @@ -430,8 +371,7 @@ static int parse_nal_units(AVCodecParserContext *s, const uint8_t *buf, goto end; } if (is_au_start(ctx, &info, avctx)) { - if ((ret = set_ctx(s, avctx, &info)) < 0) - goto end; + set_parser_ctx(s, avctx, &info); av_packet_move_ref(&ctx->last_au, &ctx->au); } else { ret = 1; //not a completed au @@ -560,7 +500,6 @@ static void vvc_parser_close(AVCodecParserContext *s) { VVCParserContext *ctx = s->priv_data; - pu_info_unref(&ctx->au_info); av_packet_unref(&ctx->au); av_packet_unref(&ctx->last_au); ff_cbs_fragment_free(&ctx->picture_unit); From b7158377c9449df831f89fe6fd39309efecbf188 Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt Date: Fri, 30 Jun 2023 00:11:34 +0200 Subject: [PATCH 1705/2172] avcodec/vvc_parser: Mark close function as av_cold Reviewed-by: James Almer Signed-off-by: Andreas Rheinhardt --- libavcodec/vvc_parser.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavcodec/vvc_parser.c b/libavcodec/vvc_parser.c index 69696eef572..0a8ef9f1772 100644 --- a/libavcodec/vvc_parser.c +++ b/libavcodec/vvc_parser.c @@ -496,7 +496,7 @@ static av_cold int vvc_parser_init(AVCodecParserContext *s) return ret; } -static void vvc_parser_close(AVCodecParserContext *s) +static av_cold void vvc_parser_close(AVCodecParserContext *s) { VVCParserContext *ctx = s->priv_data; From 915701939ca5d0a801647f7916394f33a2645d83 Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt Date: Fri, 30 Jun 2023 00:24:53 +0200 Subject: [PATCH 1706/2172] avcodec/evc_ps: Replace av_malloc+memset by av_mallocz Reviewed-by: James Almer Signed-off-by: Andreas Rheinhardt --- libavcodec/evc_ps.c | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/libavcodec/evc_ps.c b/libavcodec/evc_ps.c index ec405345ae2..fc2105b352c 100644 --- a/libavcodec/evc_ps.c +++ b/libavcodec/evc_ps.c @@ -143,12 +143,10 @@ int ff_evc_parse_sps(GetBitContext *gb, EVCParamSets *ps) if (sps_seq_parameter_set_id >= EVC_MAX_SPS_COUNT) return AVERROR_INVALIDDATA; - sps = av_malloc(sizeof(*sps)); + sps = av_mallocz(sizeof(*sps)); if (!sps) return AVERROR(ENOMEM); - memset(sps, 0, sizeof(*sps)); - sps->sps_seq_parameter_set_id = sps_seq_parameter_set_id; // the Baseline profile is indicated by profile_idc eqal to 0 @@ -318,12 +316,10 @@ int ff_evc_parse_pps(GetBitContext *gb, EVCParamSets *ps) if (pps_pic_parameter_set_id >= EVC_MAX_PPS_COUNT) return AVERROR_INVALIDDATA; - pps = av_malloc(sizeof(*pps)); + pps = av_mallocz(sizeof(*pps)); if (!pps) return AVERROR(ENOMEM); - memset(pps, 0, sizeof(*pps)); - pps->pps_pic_parameter_set_id = pps_pic_parameter_set_id; pps->pps_seq_parameter_set_id = get_ue_golomb(gb); From f48ddc1ba0fbf42e71aeda4ac6df18a08f469a25 Mon Sep 17 00:00:00 2001 From: James Almer Date: Thu, 29 Jun 2023 22:44:11 -0300 Subject: [PATCH 1707/2172] tools/target_bsf_fuzzer: fix some filter names Signed-off-by: James Almer --- tools/target_bsf_fuzzer.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/target_bsf_fuzzer.c b/tools/target_bsf_fuzzer.c index c8fab003439..76e3b89cf1a 100644 --- a/tools/target_bsf_fuzzer.c +++ b/tools/target_bsf_fuzzer.c @@ -94,8 +94,8 @@ int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { if (flags & 0x20) { if (!strcmp(f->name, "av1_metadata")) av_opt_set_int(bsf->priv_data, "td", bytestream2_get_byte(&gbc) % 3, 0); - else if (!strcmp(f->name, "h264_metadata") || !strcmp(f->name, "h265_metadata") || - !strcmp(f->name, "h266_metadata")) + else if (!strcmp(f->name, "h264_metadata") || !strcmp(f->name, "hevc_metadata") || + !strcmp(f->name, "vvc_metadata")) av_opt_set_int(bsf->priv_data, "aud", bytestream2_get_byte(&gbc) % 3, 0); else if (!strcmp(f->name, "extract_extradata")) av_opt_set_int(bsf->priv_data, "remove", bytestream2_get_byte(&gbc) & 1, 0); From 995976750a18c0d0ab92f8da6c40f02a4faa1798 Mon Sep 17 00:00:00 2001 From: James Almer Date: Thu, 29 Jun 2023 17:21:33 -0300 Subject: [PATCH 1708/2172] avcodec/cbs_h2645: fix parsing and storing Picture Header references in the context Signed-off-by: James Almer --- libavcodec/cbs_h2645.c | 35 ++++++++++++++++----------- libavcodec/cbs_h266.h | 17 +++++++------ libavcodec/cbs_h266_syntax_template.c | 13 +++++----- libavcodec/h266_metadata_bsf.c | 5 ++-- libavcodec/vvc_parser.c | 10 ++++---- 5 files changed, 44 insertions(+), 36 deletions(-) diff --git a/libavcodec/cbs_h2645.c b/libavcodec/cbs_h2645.c index cdd79015188..68ccf6a7eb5 100644 --- a/libavcodec/cbs_h2645.c +++ b/libavcodec/cbs_h2645.c @@ -525,12 +525,6 @@ static int cbs_h2645_split_fragment(CodedBitstreamContext *ctx, if (frag->data_size == 0) return 0; - if (codec_id == AV_CODEC_ID_VVC) { - //we deactive picture header here to avoid reuse previous au's ph. - CodedBitstreamH266Context *h266 = ctx->priv_data; - h266->priv.ph = NULL; - } - if (header && frag->data[0] && codec_id == AV_CODEC_ID_H264) { // AVCC header. size_t size, start, end; @@ -793,19 +787,20 @@ cbs_h266_replace_ps(6, SPS, sps, sps_seq_parameter_set_id) cbs_h266_replace_ps(6, PPS, pps, pps_pic_parameter_set_id) static int cbs_h266_replace_ph(CodedBitstreamContext *ctx, - CodedBitstreamUnit *unit) + CodedBitstreamUnit *unit, + H266RawPictureHeader *ph) { CodedBitstreamH266Context *h266 = ctx->priv_data; int err; - h266->priv.ph = NULL; err = ff_cbs_make_unit_refcounted(ctx, unit); if (err < 0) return err; - err = av_buffer_replace(&h266->priv.ph_ref, unit->content_ref); + av_assert0(unit->content_ref); + err = av_buffer_replace(&h266->ph_ref, unit->content_ref); if (err < 0) return err; - h266->priv.ph = (H266RawPH*)h266->priv.ph_ref->data; + h266->ph = ph; return 0; } @@ -1111,7 +1106,7 @@ static int cbs_h266_read_nal_unit(CodedBitstreamContext *ctx, err = cbs_h266_read_ph(ctx, &gbc, ph); if (err < 0) return err; - err = cbs_h266_replace_ph(ctx, unit); + err = cbs_h266_replace_ph(ctx, unit, &ph->ph_picture_header); if (err < 0) return err; } @@ -1139,6 +1134,12 @@ static int cbs_h266_read_nal_unit(CodedBitstreamContext *ctx, pos = get_bits_count(&gbc); len = unit->data_size; + if (slice->header.sh_picture_header_in_slice_header_flag) { + err = cbs_h266_replace_ph(ctx, unit, &slice->header.sh_picture_header); + if (err < 0) + return err; + } + slice->data_size = len - pos / 8; slice->data_ref = av_buffer_ref(unit->data_ref); if (!slice->data_ref) @@ -1640,7 +1641,7 @@ static int cbs_h266_write_nal_unit(CodedBitstreamContext *ctx, if (err < 0) return err; - err = cbs_h266_replace_ph(ctx, unit); + err = cbs_h266_replace_ph(ctx, unit, &ph->ph_picture_header); if (err < 0) return err; } @@ -1661,6 +1662,12 @@ static int cbs_h266_write_nal_unit(CodedBitstreamContext *ctx, if (err < 0) return err; + if (slice->header.sh_picture_header_in_slice_header_flag) { + err = cbs_h266_replace_ph(ctx, unit, &slice->header.sh_picture_header); + if (err < 0) + return err; + } + if (slice->data) { err = cbs_h2645_write_slice_data(ctx, pbc, slice->data, slice->data_size, @@ -1884,8 +1891,8 @@ static void cbs_h266_flush(CodedBitstreamContext *ctx) av_buffer_unref(&h266->pps_ref[i]); h266->pps[i] = NULL; } - av_buffer_unref(&h266->priv.ph_ref); - h266->priv.ph = NULL; + av_buffer_unref(&h266->ph_ref); + h266->ph = NULL; } static void cbs_h266_close(CodedBitstreamContext *ctx) diff --git a/libavcodec/cbs_h266.h b/libavcodec/cbs_h266.h index 03dfd4a9542..54590748c34 100644 --- a/libavcodec/cbs_h266.h +++ b/libavcodec/cbs_h266.h @@ -581,8 +581,7 @@ typedef struct H266RawPredWeightTable { int16_t delta_chroma_offset_l1[15][2]; } H266RawPredWeightTable; -typedef struct H266RawPH { - H266RawNALUnitHeader nal_unit_header; +typedef struct H266RawPictureHeader { uint8_t ph_gdr_or_irap_pic_flag; uint8_t ph_non_ref_pic_flag; uint8_t ph_gdr_pic_flag; @@ -670,12 +669,17 @@ typedef struct H266RawPH { uint8_t ph_extension_length; uint8_t ph_extension_data_byte[256]; +} H266RawPictureHeader; + +typedef struct H266RawPH { + H266RawNALUnitHeader nal_unit_header; + H266RawPictureHeader ph_picture_header; } H266RawPH; typedef struct H266RawSliceHeader { H266RawNALUnitHeader nal_unit_header; uint8_t sh_picture_header_in_slice_header_flag; - H266RawPH sh_picture_header; + H266RawPictureHeader sh_picture_header; uint16_t sh_subpic_id; uint16_t sh_slice_address; @@ -770,14 +774,11 @@ typedef struct CodedBitstreamH266Context { AVBufferRef *vps_ref[VVC_MAX_VPS_COUNT]; AVBufferRef *sps_ref[VVC_MAX_SPS_COUNT]; AVBufferRef *pps_ref[VVC_MAX_PPS_COUNT]; + AVBufferRef *ph_ref; H266RawVPS *vps[VVC_MAX_SPS_COUNT]; H266RawSPS *sps[VVC_MAX_SPS_COUNT]; H266RawPPS *pps[VVC_MAX_PPS_COUNT]; - - struct { - AVBufferRef *ph_ref; - H266RawPH *ph; - } priv; + H266RawPictureHeader *ph; } CodedBitstreamH266Context; #endif /* AVCODEC_CBS_H266_H */ diff --git a/libavcodec/cbs_h266_syntax_template.c b/libavcodec/cbs_h266_syntax_template.c index 06f9f29e085..b23a80d356c 100644 --- a/libavcodec/cbs_h266_syntax_template.c +++ b/libavcodec/cbs_h266_syntax_template.c @@ -2232,7 +2232,7 @@ static int FUNC(pred_weight_table) (CodedBitstreamContext *ctx, RWContext *rw, } static int FUNC(picture_header) (CodedBitstreamContext *ctx, RWContext *rw, - H266RawPH *current){ + H266RawPictureHeader *current) { CodedBitstreamH266Context *h266 = ctx->priv_data; const H266RawVPS *vps; const H266RawSPS *sps; @@ -2651,7 +2651,7 @@ static int FUNC(ph) (CodedBitstreamContext *ctx, RWContext *rw, HEADER("Picture Header"); CHECK(FUNC(nal_unit_header) (ctx, rw, ¤t->nal_unit_header, VVC_PH_NUT)); - CHECK(FUNC(picture_header) (ctx, rw, current)); + CHECK(FUNC(picture_header) (ctx, rw, ¤t->ph_picture_header)); CHECK(FUNC(rbsp_trailing_bits) (ctx, rw)); return 0; } @@ -2662,7 +2662,7 @@ static int FUNC(slice_header) (CodedBitstreamContext *ctx, RWContext *rw, CodedBitstreamH266Context *h266 = ctx->priv_data; const H266RawSPS *sps; const H266RawPPS *pps; - const H266RawPH *ph; + const H266RawPictureHeader *ph; const H266RefPicLists *ref_pic_lists; int err, i; uint8_t nal_unit_type, qp_bd_offset; @@ -2675,12 +2675,11 @@ static int FUNC(slice_header) (CodedBitstreamContext *ctx, RWContext *rw, flag(sh_picture_header_in_slice_header_flag); if (current->sh_picture_header_in_slice_header_flag) { + // 7.4.8 if sh_picture_header_in_slice_header_flag is true, we do not have a PH NAL unit CHECK(FUNC(picture_header) (ctx, rw, ¤t->sh_picture_header)); ph = ¤t->sh_picture_header; - //7.4.8 if sh_picture_header_in_slice_header_flag is true, we do not have PH NAL unit - h266->priv.ph = NULL; } else { - ph = h266->priv.ph; + ph = h266->ph; if (!ph) { av_log(ctx->log_ctx, AV_LOG_ERROR, "Picture header not available.\n"); @@ -2822,7 +2821,7 @@ static int FUNC(slice_header) (CodedBitstreamContext *ctx, RWContext *rw, (ctx, rw, sps, pps, ¤t->sh_ref_pic_lists)); ref_pic_lists = ¤t->sh_ref_pic_lists; } else { - ref_pic_lists = &h266->priv.ph->ph_ref_pic_lists; + ref_pic_lists = &ph->ph_ref_pic_lists; } if ((current->sh_slice_type != VVC_SLICE_TYPE_I && ref_pic_lists->rpl_ref_list[0].num_ref_entries > 1) || diff --git a/libavcodec/h266_metadata_bsf.c b/libavcodec/h266_metadata_bsf.c index 18fa1a5c9c2..c0dbf8ef965 100644 --- a/libavcodec/h266_metadata_bsf.c +++ b/libavcodec/h266_metadata_bsf.c @@ -48,7 +48,7 @@ static int h266_metadata_update_fragment(AVBSFContext *bsf, AVPacket *pkt, ff_cbs_delete_unit(pu, 0); } else if ( pkt && ctx->aud == BSF_ELEMENT_INSERT) { const H266RawSlice *first_slice = NULL; - const H266RawPH *ph = NULL; + const H266RawPictureHeader *ph = NULL; H266RawAUD *aud = &ctx->aud_nal; int pic_type = 0, temporal_id = 8, layer_id = 0; for (i = 0; i < pu->nb_units; i++) { @@ -58,7 +58,8 @@ static int h266_metadata_update_fragment(AVBSFContext *bsf, AVPacket *pkt, if (nal->nuh_temporal_id_plus1 < temporal_id + 1) temporal_id = nal->nuh_temporal_id_plus1 - 1; if ( nal->nal_unit_type == VVC_PH_NUT ) { - ph = pu->units[i].content; + const H266RawPH *header = pu->units[i].content; + ph = &header->ph_picture_header; } else if (IS_H266_SLICE(nal->nal_unit_type)) { const H266RawSlice *slice = pu->units[i].content; layer_id = nal->nuh_layer_id; diff --git a/libavcodec/vvc_parser.c b/libavcodec/vvc_parser.c index 0a8ef9f1772..3951ebe50af 100644 --- a/libavcodec/vvc_parser.c +++ b/libavcodec/vvc_parser.c @@ -31,7 +31,7 @@ typedef struct PuInfo { const H266RawPPS *pps; const H266RawSPS *sps; - const H266RawPH *ph; + const H266RawPictureHeader *ph; const H266RawSlice *slice; int pic_type; } PuInfo; @@ -155,7 +155,6 @@ static void set_parser_ctx(AVCodecParserContext *s, AVCodecContext *avctx, }; const H266RawSPS *sps = pu->sps; const H266RawPPS *pps = pu->pps; - //const H266RawPH *ph = pu->ph; const H266RawNALUnitHeader *nal = &pu->slice->header.nal_unit_header; s->pict_type = pu->pic_type; @@ -205,7 +204,7 @@ static void set_parser_ctx(AVCodecParserContext *s, AVCodecContext *avctx, //We follow the VTM. static void get_slice_poc(VVCParserContext *s, int *poc, const H266RawSPS *sps, - const H266RawPH *ph, + const H266RawPictureHeader *ph, const H266RawSliceHeader *slice, void *log_ctx) { int poc_msb, max_poc_lsb, poc_lsb; @@ -251,7 +250,7 @@ static int is_au_start(VVCParserContext *s, const PuInfo *pu, void *log_ctx) AuDetector *d = &s->au_detector; const H266RawSPS *sps = pu->sps; const H266RawNALUnitHeader *nal = &pu->slice->header.nal_unit_header; - const H266RawPH *ph = pu->ph; + const H266RawPictureHeader *ph = pu->ph; const H266RawSlice *slice = pu->slice; int ret, poc, nut; @@ -282,7 +281,8 @@ static int get_pu_info(PuInfo *info, const CodedBitstreamH266Context *h266, if (!nal) continue; if ( nal->nal_unit_type == VVC_PH_NUT ) { - info->ph = pu->units[i].content; + const H266RawPH *ph = pu->units[i].content; + info->ph = &ph->ph_picture_header; } else if (IS_H266_SLICE(nal->nal_unit_type)) { info->slice = pu->units[i].content; if (info->slice->header.sh_picture_header_in_slice_header_flag) From 3fd7841ef1ecedf494b69b1bcb17fcf46450f17f Mon Sep 17 00:00:00 2001 From: James Almer Date: Thu, 29 Jun 2023 13:33:26 -0300 Subject: [PATCH 1709/2172] fate/cbs: add VVC tests Signed-off-by: James Almer --- tests/fate/cbs.mak | 40 ++++++++++++++++++++++ tests/ref/fate/cbs-vvc-AUD_A_3 | 1 + tests/ref/fate/cbs-vvc-BOUNDARY_A_3 | 1 + tests/ref/fate/cbs-vvc-BUMP_A_2 | 1 + tests/ref/fate/cbs-vvc-CROP_B_4 | 1 + tests/ref/fate/cbs-vvc-CodingToolsSets_A_2 | 1 + tests/ref/fate/cbs-vvc-HRD_A_3 | 1 + tests/ref/fate/cbs-vvc-PHSH_B_1 | 1 + tests/ref/fate/cbs-vvc-POC_A_1 | 1 + tests/ref/fate/cbs-vvc-PPS_B_1 | 1 + tests/ref/fate/cbs-vvc-RAP_A_1 | 1 + tests/ref/fate/cbs-vvc-SAO_A_3 | 1 + tests/ref/fate/cbs-vvc-SCALING_A_1 | 1 + tests/ref/fate/cbs-vvc-SLICES_A_3 | 1 + tests/ref/fate/cbs-vvc-SPS_B_1 | 1 + tests/ref/fate/cbs-vvc-STILL_B_1 | 1 + tests/ref/fate/cbs-vvc-SUBPIC_A_3 | 1 + tests/ref/fate/cbs-vvc-TILE_A_2 | 1 + tests/ref/fate/cbs-vvc-VPS_A_3 | 1 + tests/ref/fate/cbs-vvc-WPP_A_3 | 1 + tests/ref/fate/cbs-vvc-WP_A_3 | 1 + tests/ref/fate/cbs-vvc-WRAP_A_4 | 1 + 22 files changed, 61 insertions(+) create mode 100644 tests/ref/fate/cbs-vvc-AUD_A_3 create mode 100644 tests/ref/fate/cbs-vvc-BOUNDARY_A_3 create mode 100644 tests/ref/fate/cbs-vvc-BUMP_A_2 create mode 100644 tests/ref/fate/cbs-vvc-CROP_B_4 create mode 100644 tests/ref/fate/cbs-vvc-CodingToolsSets_A_2 create mode 100644 tests/ref/fate/cbs-vvc-HRD_A_3 create mode 100644 tests/ref/fate/cbs-vvc-PHSH_B_1 create mode 100644 tests/ref/fate/cbs-vvc-POC_A_1 create mode 100644 tests/ref/fate/cbs-vvc-PPS_B_1 create mode 100644 tests/ref/fate/cbs-vvc-RAP_A_1 create mode 100644 tests/ref/fate/cbs-vvc-SAO_A_3 create mode 100644 tests/ref/fate/cbs-vvc-SCALING_A_1 create mode 100644 tests/ref/fate/cbs-vvc-SLICES_A_3 create mode 100644 tests/ref/fate/cbs-vvc-SPS_B_1 create mode 100644 tests/ref/fate/cbs-vvc-STILL_B_1 create mode 100644 tests/ref/fate/cbs-vvc-SUBPIC_A_3 create mode 100644 tests/ref/fate/cbs-vvc-TILE_A_2 create mode 100644 tests/ref/fate/cbs-vvc-VPS_A_3 create mode 100644 tests/ref/fate/cbs-vvc-WPP_A_3 create mode 100644 tests/ref/fate/cbs-vvc-WP_A_3 create mode 100644 tests/ref/fate/cbs-vvc-WRAP_A_4 diff --git a/tests/fate/cbs.mak b/tests/fate/cbs.mak index 0084c3d25c3..344515a7fac 100644 --- a/tests/fate/cbs.mak +++ b/tests/fate/cbs.mak @@ -5,6 +5,7 @@ fate-cbs: fate-cbs-av1 fate-cbs-h264 fate-cbs-hevc fate-cbs-mpeg2 fate-cbs-vp9 FATE_CBS_DEPS = $(call ALLYES, $(1)_DEMUXER $(2)_PARSER $(3)_METADATA_BSF $(4)_DECODER $(5)_MUXER) +FATE_CBS_NO_DEC_DEPS = $(call ALLYES, $(1)_DEMUXER $(2)_PARSER $(3)_METADATA_BSF $(4)_MUXER) define FATE_CBS_TEST # (codec, test_name, sample_file, output_format) @@ -12,6 +13,12 @@ FATE_CBS_$(1) += fate-cbs-$(1)-$(2) fate-cbs-$(1)-$(2): CMD = md5 -c:v $(3) -i $(TARGET_SAMPLES)/$(4) -c:v copy -y -bsf:v $(1)_metadata -f $(5) endef +define FATE_CBS_NO_DEC_TEST +# (codec, test_name, sample_file, output_format) +FATE_CBS_$(1) += fate-cbs-$(1)-$(2) +fate-cbs-$(1)-$(2): CMD = md5 -i $(TARGET_SAMPLES)/$(3) -c:v copy -y -bsf:v $(1)_metadata -f $(4) +endef + define FATE_CBS_DISCARD_TEST # (codec, discard_type, sample_file, output_format, dep) FATE_CBS_$(1)_DISCARD += fate-cbs-$(1)-discard-$(2) @@ -163,6 +170,39 @@ FATE_CBS_HEVC-$(call ALLYES, MP4_MUXER, HEVC_PARSER, FILTER_UNITS_BSF, HEVC_MUXE FATE_SAMPLES_AVCONV += $(FATE_CBS_HEVC-yes) fate-cbs-hevc: $(FATE_CBS_HEVC-yes) +# H.266 read/write + +FATE_CBS_VVC_SAMPLES = \ + AUD_A_3.bit \ + BOUNDARY_A_3.bit \ + BUMP_A_2.bit \ + CodingToolsSets_A_2.bit \ + CROP_B_4.bit \ + HRD_A_3.bit \ + PHSH_B_1.bit \ + POC_A_1.bit \ + PPS_B_1.bit \ + RAP_A_1.bit \ + SAO_A_3.bit \ + SCALING_A_1.bit \ + SLICES_A_3.bit \ + SPS_B_1.bit \ + STILL_B_1.bit \ + SUBPIC_A_3.bit \ + TILE_A_2.bit \ + VPS_A_3.bit \ + WP_A_3.bit \ + WPP_A_3.bit \ + WRAP_A_4.bit \ + + +$(foreach N,$(FATE_CBS_VVC_SAMPLES),$(eval $(call FATE_CBS_NO_DEC_TEST,vvc,$(basename $(N)),vvc-conformance/$(N),vvc))) + +FATE_CBS_VVC-$(call FATE_CBS_NO_DEC_DEPS, HEVC, HEVC, HEVC, HEVC) = $(FATE_CBS_vvc) + +FATE_SAMPLES_AVCONV += $(FATE_CBS_VVC-yes) +fate-cbs-vvc: $(FATE_CBS_VVC-yes) + # MPEG-2 read/write FATE_CBS_MPEG2_SAMPLES = \ diff --git a/tests/ref/fate/cbs-vvc-AUD_A_3 b/tests/ref/fate/cbs-vvc-AUD_A_3 new file mode 100644 index 00000000000..91dfc817b78 --- /dev/null +++ b/tests/ref/fate/cbs-vvc-AUD_A_3 @@ -0,0 +1 @@ +5a5bf4ec5e75d38958863ce8aa6c1fad diff --git a/tests/ref/fate/cbs-vvc-BOUNDARY_A_3 b/tests/ref/fate/cbs-vvc-BOUNDARY_A_3 new file mode 100644 index 00000000000..2647e37041f --- /dev/null +++ b/tests/ref/fate/cbs-vvc-BOUNDARY_A_3 @@ -0,0 +1 @@ +3ef48cf6019ee5d7ca4ab8d5cd12bbd5 diff --git a/tests/ref/fate/cbs-vvc-BUMP_A_2 b/tests/ref/fate/cbs-vvc-BUMP_A_2 new file mode 100644 index 00000000000..4f7c69c2b7b --- /dev/null +++ b/tests/ref/fate/cbs-vvc-BUMP_A_2 @@ -0,0 +1 @@ +80cb700aa0c31e693abaad7be56a606b diff --git a/tests/ref/fate/cbs-vvc-CROP_B_4 b/tests/ref/fate/cbs-vvc-CROP_B_4 new file mode 100644 index 00000000000..6b46df0c825 --- /dev/null +++ b/tests/ref/fate/cbs-vvc-CROP_B_4 @@ -0,0 +1 @@ +7d451021118d63bebe613cec1f773cc5 diff --git a/tests/ref/fate/cbs-vvc-CodingToolsSets_A_2 b/tests/ref/fate/cbs-vvc-CodingToolsSets_A_2 new file mode 100644 index 00000000000..a6a787b9dee --- /dev/null +++ b/tests/ref/fate/cbs-vvc-CodingToolsSets_A_2 @@ -0,0 +1 @@ +6f0043acadfc70d7ec8d556194169a6e diff --git a/tests/ref/fate/cbs-vvc-HRD_A_3 b/tests/ref/fate/cbs-vvc-HRD_A_3 new file mode 100644 index 00000000000..39e4b906c65 --- /dev/null +++ b/tests/ref/fate/cbs-vvc-HRD_A_3 @@ -0,0 +1 @@ +c0d308912bcdda2b780f3e0a808ff138 diff --git a/tests/ref/fate/cbs-vvc-PHSH_B_1 b/tests/ref/fate/cbs-vvc-PHSH_B_1 new file mode 100644 index 00000000000..437a9eb64f0 --- /dev/null +++ b/tests/ref/fate/cbs-vvc-PHSH_B_1 @@ -0,0 +1 @@ +724e3af9b9aac47049a58534ada918e6 diff --git a/tests/ref/fate/cbs-vvc-POC_A_1 b/tests/ref/fate/cbs-vvc-POC_A_1 new file mode 100644 index 00000000000..f259307ca6a --- /dev/null +++ b/tests/ref/fate/cbs-vvc-POC_A_1 @@ -0,0 +1 @@ +608f780e20d18f8dde4ca25276a66598 diff --git a/tests/ref/fate/cbs-vvc-PPS_B_1 b/tests/ref/fate/cbs-vvc-PPS_B_1 new file mode 100644 index 00000000000..1981930a04b --- /dev/null +++ b/tests/ref/fate/cbs-vvc-PPS_B_1 @@ -0,0 +1 @@ +de563a85244bf4a7781b98198a5bf409 diff --git a/tests/ref/fate/cbs-vvc-RAP_A_1 b/tests/ref/fate/cbs-vvc-RAP_A_1 new file mode 100644 index 00000000000..22661eed540 --- /dev/null +++ b/tests/ref/fate/cbs-vvc-RAP_A_1 @@ -0,0 +1 @@ +6460f629ca2377bd271bd1fa5787214f diff --git a/tests/ref/fate/cbs-vvc-SAO_A_3 b/tests/ref/fate/cbs-vvc-SAO_A_3 new file mode 100644 index 00000000000..d8b3096dde1 --- /dev/null +++ b/tests/ref/fate/cbs-vvc-SAO_A_3 @@ -0,0 +1 @@ +44f8666cd7fa1f4f52f0570ad29e7a8b diff --git a/tests/ref/fate/cbs-vvc-SCALING_A_1 b/tests/ref/fate/cbs-vvc-SCALING_A_1 new file mode 100644 index 00000000000..e9c5477ccd8 --- /dev/null +++ b/tests/ref/fate/cbs-vvc-SCALING_A_1 @@ -0,0 +1 @@ +50b3221ba3dc373189527428ea8a4b38 diff --git a/tests/ref/fate/cbs-vvc-SLICES_A_3 b/tests/ref/fate/cbs-vvc-SLICES_A_3 new file mode 100644 index 00000000000..d45aa2c3f0a --- /dev/null +++ b/tests/ref/fate/cbs-vvc-SLICES_A_3 @@ -0,0 +1 @@ +77ac8631941cc5fe0d67cefe94e923a2 diff --git a/tests/ref/fate/cbs-vvc-SPS_B_1 b/tests/ref/fate/cbs-vvc-SPS_B_1 new file mode 100644 index 00000000000..a4ca603037b --- /dev/null +++ b/tests/ref/fate/cbs-vvc-SPS_B_1 @@ -0,0 +1 @@ +cf3e0c51035bde7499f80eac34563762 diff --git a/tests/ref/fate/cbs-vvc-STILL_B_1 b/tests/ref/fate/cbs-vvc-STILL_B_1 new file mode 100644 index 00000000000..34b54b736ff --- /dev/null +++ b/tests/ref/fate/cbs-vvc-STILL_B_1 @@ -0,0 +1 @@ +bfa7b1d3ad3b84dac122e8127d579a24 diff --git a/tests/ref/fate/cbs-vvc-SUBPIC_A_3 b/tests/ref/fate/cbs-vvc-SUBPIC_A_3 new file mode 100644 index 00000000000..b3b5123fd8b --- /dev/null +++ b/tests/ref/fate/cbs-vvc-SUBPIC_A_3 @@ -0,0 +1 @@ +70eb8a1074a76e63406036e03dc8734a diff --git a/tests/ref/fate/cbs-vvc-TILE_A_2 b/tests/ref/fate/cbs-vvc-TILE_A_2 new file mode 100644 index 00000000000..c788b028d0d --- /dev/null +++ b/tests/ref/fate/cbs-vvc-TILE_A_2 @@ -0,0 +1 @@ +b9fca953a0b5aed276fb3c0418ada885 diff --git a/tests/ref/fate/cbs-vvc-VPS_A_3 b/tests/ref/fate/cbs-vvc-VPS_A_3 new file mode 100644 index 00000000000..62e95650e2b --- /dev/null +++ b/tests/ref/fate/cbs-vvc-VPS_A_3 @@ -0,0 +1 @@ +40c6750868d27bba165a1553c519cee5 diff --git a/tests/ref/fate/cbs-vvc-WPP_A_3 b/tests/ref/fate/cbs-vvc-WPP_A_3 new file mode 100644 index 00000000000..82631cfdfbe --- /dev/null +++ b/tests/ref/fate/cbs-vvc-WPP_A_3 @@ -0,0 +1 @@ +c5e6ba8eb4ef6e991b8528ca2490d350 diff --git a/tests/ref/fate/cbs-vvc-WP_A_3 b/tests/ref/fate/cbs-vvc-WP_A_3 new file mode 100644 index 00000000000..71789587dc3 --- /dev/null +++ b/tests/ref/fate/cbs-vvc-WP_A_3 @@ -0,0 +1 @@ +05a8ac4844ce65c7a64dfd304f4186a5 diff --git a/tests/ref/fate/cbs-vvc-WRAP_A_4 b/tests/ref/fate/cbs-vvc-WRAP_A_4 new file mode 100644 index 00000000000..708d07e623a --- /dev/null +++ b/tests/ref/fate/cbs-vvc-WRAP_A_4 @@ -0,0 +1 @@ +ba7de3caf1bf4efe77bdb424ba5fc814 From 96d69905171be47369839f8e8d3e6036f91df74f Mon Sep 17 00:00:00 2001 From: James Almer Date: Fri, 30 Jun 2023 08:42:07 -0300 Subject: [PATCH 1710/2172] avcodec/cbs_h266: use VVC_MAX_VPS_COUNT for range checks and array size Signed-off-by: James Almer --- libavcodec/cbs_h266.h | 2 +- libavcodec/cbs_h266_syntax_template.c | 7 +------ 2 files changed, 2 insertions(+), 7 deletions(-) diff --git a/libavcodec/cbs_h266.h b/libavcodec/cbs_h266.h index 54590748c34..be3c7444260 100644 --- a/libavcodec/cbs_h266.h +++ b/libavcodec/cbs_h266.h @@ -775,7 +775,7 @@ typedef struct CodedBitstreamH266Context { AVBufferRef *sps_ref[VVC_MAX_SPS_COUNT]; AVBufferRef *pps_ref[VVC_MAX_PPS_COUNT]; AVBufferRef *ph_ref; - H266RawVPS *vps[VVC_MAX_SPS_COUNT]; + H266RawVPS *vps[VVC_MAX_VPS_COUNT]; H266RawSPS *sps[VVC_MAX_SPS_COUNT]; H266RawPPS *pps[VVC_MAX_PPS_COUNT]; H266RawPictureHeader *ph; diff --git a/libavcodec/cbs_h266_syntax_template.c b/libavcodec/cbs_h266_syntax_template.c index b23a80d356c..863fecdefaf 100644 --- a/libavcodec/cbs_h266_syntax_template.c +++ b/libavcodec/cbs_h266_syntax_template.c @@ -639,12 +639,7 @@ static int FUNC(vps) (CodedBitstreamContext *ctx, RWContext *rw, CHECK(FUNC(nal_unit_header) (ctx, rw, ¤t->nal_unit_header, VVC_VPS_NUT)); - ub(4, vps_video_parameter_set_id); - if (current->vps_video_parameter_set_id == 0) { - av_log(ctx->log_ctx, AV_LOG_ERROR, - "vps_video_parameter_set_id should > 0.\n"); - return AVERROR_INVALIDDATA; - } + u(4, vps_video_parameter_set_id, 1, VVC_MAX_VPS_COUNT - 1); ub(6, vps_max_layers_minus1); u(3, vps_max_sublayers_minus1, 0, 6); if (current->vps_max_layers_minus1 > 0 From 686156f366ebaa9330ef25ea4f269d8a46d958f0 Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt Date: Fri, 30 Jun 2023 01:35:06 +0200 Subject: [PATCH 1711/2172] avcodec/hevc_ps: Constify VPS, SPS pointers when parsing PPS Signed-off-by: Andreas Rheinhardt --- libavcodec/hevc_ps.c | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/libavcodec/hevc_ps.c b/libavcodec/hevc_ps.c index d7930d3ac3e..4c4c1e2c174 100644 --- a/libavcodec/hevc_ps.c +++ b/libavcodec/hevc_ps.c @@ -725,7 +725,8 @@ static void set_default_scaling_list_data(ScalingList *sl) memcpy(sl->sl[3][5], default_scaling_list_inter, 64); } -static int scaling_list_data(GetBitContext *gb, AVCodecContext *avctx, ScalingList *sl, HEVCSPS *sps) +static int scaling_list_data(GetBitContext *gb, AVCodecContext *avctx, + ScalingList *sl, const HEVCSPS *sps) { uint8_t scaling_list_pred_mode_flag; uint8_t scaling_list_dc_coef[2][6]; @@ -1412,7 +1413,7 @@ static int colour_mapping_table(GetBitContext *gb, AVCodecContext *avctx, HEVCPP } static int pps_multilayer_extension(GetBitContext *gb, AVCodecContext *avctx, - HEVCPPS *pps, HEVCSPS *sps, HEVCVPS *vps) + HEVCPPS *pps, const HEVCSPS *sps, const HEVCVPS *vps) { pps->poc_reset_info_present_flag = get_bits1(gb); pps->pps_infer_scaling_list_flag = get_bits1(gb); @@ -1483,7 +1484,7 @@ static void delta_dlt(GetBitContext *gb, HEVCPPS *pps) } static int pps_3d_extension(GetBitContext *gb, AVCodecContext *avctx, - HEVCPPS *pps, HEVCSPS *sps) + HEVCPPS *pps, const HEVCSPS *sps) { unsigned int pps_depth_layers_minus1; @@ -1507,7 +1508,7 @@ static int pps_3d_extension(GetBitContext *gb, AVCodecContext *avctx, } static int pps_range_extensions(GetBitContext *gb, AVCodecContext *avctx, - HEVCPPS *pps, HEVCSPS *sps) + HEVCPPS *pps, const HEVCSPS *sps) { if (pps->transform_skip_enabled_flag) { pps->log2_max_transform_skip_block_size = get_ue_golomb_31(gb) + 2; @@ -1547,7 +1548,7 @@ static int pps_range_extensions(GetBitContext *gb, AVCodecContext *avctx, } static int pps_scc_extension(GetBitContext *gb, AVCodecContext *avctx, - HEVCPPS *pps, HEVCSPS *sps) + HEVCPPS *pps, const HEVCSPS *sps) { int num_comps, ret; @@ -1599,7 +1600,7 @@ static int pps_scc_extension(GetBitContext *gb, AVCodecContext *avctx, } static inline int setup_pps(AVCodecContext *avctx, GetBitContext *gb, - HEVCPPS *pps, HEVCSPS *sps) + HEVCPPS *pps, const HEVCSPS *sps) { int log2_diff; int pic_area_in_ctbs; @@ -1733,8 +1734,8 @@ static inline int setup_pps(AVCodecContext *avctx, GetBitContext *gb, int ff_hevc_decode_nal_pps(GetBitContext *gb, AVCodecContext *avctx, HEVCParamSets *ps) { - HEVCSPS *sps = NULL; - HEVCVPS *vps = NULL; + const HEVCSPS *sps = NULL; + const HEVCVPS *vps = NULL; int i, ret = 0; unsigned int pps_id = 0; ptrdiff_t nal_size; From 46a5b9e2c063f7a6776323afdebe6d9558ba96c1 Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt Date: Fri, 30 Jun 2023 13:25:48 +0200 Subject: [PATCH 1712/2172] avcodec/tests/avcodec: Remove unnecessary internal.h inclusion Forgotten in a688f3c13ce55c2ba51dbbb344564649f1bb52fe. Signed-off-by: Andreas Rheinhardt --- libavcodec/tests/avcodec.c | 1 - 1 file changed, 1 deletion(-) diff --git a/libavcodec/tests/avcodec.c b/libavcodec/tests/avcodec.c index d78447d0fc8..bbf5289af2f 100644 --- a/libavcodec/tests/avcodec.c +++ b/libavcodec/tests/avcodec.c @@ -20,7 +20,6 @@ #include "libavcodec/codec.h" #include "libavcodec/codec_desc.h" #include "libavcodec/codec_internal.h" -#include "libavcodec/internal.h" static const char *get_type_string(enum AVMediaType type) { From e4d4d616ba08f4046f2247f57f8b5a8fb0b05369 Mon Sep 17 00:00:00 2001 From: James Almer Date: Fri, 30 Jun 2023 13:45:34 -0300 Subject: [PATCH 1713/2172] fate/cbs: run the VVC tests within the fate-cbs target Signed-off-by: James Almer --- tests/fate/cbs.mak | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/fate/cbs.mak b/tests/fate/cbs.mak index 344515a7fac..b01a02766fc 100644 --- a/tests/fate/cbs.mak +++ b/tests/fate/cbs.mak @@ -2,7 +2,7 @@ # arguments, it decomposes the stream fully and then recomposes it # without making any changes. -fate-cbs: fate-cbs-av1 fate-cbs-h264 fate-cbs-hevc fate-cbs-mpeg2 fate-cbs-vp9 +fate-cbs: fate-cbs-av1 fate-cbs-h264 fate-cbs-hevc fate-cbs-mpeg2 fate-cbs-vp9 fate-cbs-vvc FATE_CBS_DEPS = $(call ALLYES, $(1)_DEMUXER $(2)_PARSER $(3)_METADATA_BSF $(4)_DECODER $(5)_MUXER) FATE_CBS_NO_DEC_DEPS = $(call ALLYES, $(1)_DEMUXER $(2)_PARSER $(3)_METADATA_BSF $(4)_MUXER) From b40324d417e7952b73ce600b1e9651aeeda8db47 Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Fri, 30 Jun 2023 21:39:45 +0200 Subject: [PATCH 1714/2172] doc/general_contents: update for recent additions --- doc/general_contents.texi | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/doc/general_contents.texi b/doc/general_contents.texi index 2eeebd847da..8ac121dee17 100644 --- a/doc/general_contents.texi +++ b/doc/general_contents.texi @@ -1006,7 +1006,7 @@ following image formats are supported: @tab Also known as Microsoft Screen 3. @item Microsoft Expression Encoder Screen @tab @tab X @tab Also known as Microsoft Titanium Screen 2. -@item Microsoft RLE @tab @tab X +@item Microsoft RLE @tab X @tab X @item Microsoft Screen 1 @tab @tab X @tab Also known as Windows Media Video V7 Screen. @item Microsoft Screen 2 @tab @tab X @@ -1066,6 +1066,8 @@ following image formats are supported: @item RealVideo 4.0 @tab @tab X @item Renderware TXD (TeXture Dictionary) @tab @tab X @tab Texture dictionaries used by the Renderware Engine. +@item RivaTuner Video @tab @tab X + @tab fourcc: 'RTV1' @item RL2 video @tab @tab X @tab used in some games by Entertainment Software Partners @item ScreenPressor @tab @tab X @@ -1102,6 +1104,8 @@ following image formats are supported: @item v408 QuickTime uncompressed 4:4:4:4 @tab X @tab X @item v410 QuickTime uncompressed 4:4:4 10-bit @tab X @tab X @item VBLE Lossless Codec @tab @tab X +@item vMix Video @tab @tab X + @tab fourcc: 'VMX1' @item VMware Screen Codec / VMware Video @tab @tab X @tab Codec used in videos captured by VMware. @item Westwood Studios VQA (Vector Quantized Animation) video @tab @tab X From c732fdfa05949e53afc41d888ae4cd5d525d5aaf Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt Date: Fri, 30 Jun 2023 23:29:53 +0200 Subject: [PATCH 1715/2172] avcodec/cbs_h266_syntax_template: Don't use uninitialized value Just a typo. Fixes a warning from Clang. Reviewed-by: Nuo Mi Signed-off-by: Andreas Rheinhardt --- libavcodec/cbs_h266_syntax_template.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavcodec/cbs_h266_syntax_template.c b/libavcodec/cbs_h266_syntax_template.c index 863fecdefaf..56e1205337b 100644 --- a/libavcodec/cbs_h266_syntax_template.c +++ b/libavcodec/cbs_h266_syntax_template.c @@ -1059,7 +1059,7 @@ static int FUNC(sps)(CodedBitstreamContext *ctx, RWContext *rw, if (current->sps_pic_width_max_in_luma_samples > ctb_size_y) ubs(wlen, sps_subpic_width_minus1[0], 1, 0); else - infer(sps_subpic_width_minus1[i], tmp_width_val - 1); + infer(sps_subpic_width_minus1[0], tmp_width_val - 1); if (current->sps_pic_height_max_in_luma_samples > ctb_size_y) ubs(hlen, sps_subpic_height_minus1[0], 1, 0); else From e7f152a8c2214f5d82dccdc49734f050469f5869 Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt Date: Fri, 30 Jun 2023 23:40:52 +0200 Subject: [PATCH 1716/2172] avcodec/cbs_h266_syntax_template: Avoid shadowing Reviewed-by: Nuo Mi Signed-off-by: Andreas Rheinhardt --- libavcodec/cbs_h266_syntax_template.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/libavcodec/cbs_h266_syntax_template.c b/libavcodec/cbs_h266_syntax_template.c index 56e1205337b..f48b89cac92 100644 --- a/libavcodec/cbs_h266_syntax_template.c +++ b/libavcodec/cbs_h266_syntax_template.c @@ -514,9 +514,9 @@ static int FUNC(ref_pic_lists) (CodedBitstreamContext *ctx, RWContext *rw, ref_list = ¤t->rpl_ref_list[i]; num_ltrp_entries = 0; - for (int i = 0; i < ref_list->num_ref_entries; i++) { - if (!ref_list->inter_layer_ref_pic_flag[i]) { - if (!ref_list->st_ref_pic_flag[i]) { + for (int k = 0; k < ref_list->num_ref_entries; k++) { + if (!ref_list->inter_layer_ref_pic_flag[k]) { + if (!ref_list->st_ref_pic_flag[k]) { num_ltrp_entries++; } } From a77f5019f5731d79eb6f6dee7c3eb2d9d447ef2c Mon Sep 17 00:00:00 2001 From: James Almer Date: Fri, 30 Jun 2023 22:20:28 -0300 Subject: [PATCH 1717/2172] avcodec/cbs_h266: store SubpicIdVal in the context And use it to derive CurrSubpicIdx Signed-off-by: James Almer --- libavcodec/cbs_h266.h | 1 + libavcodec/cbs_h266_syntax_template.c | 34 +++++++++++++-------------- 2 files changed, 18 insertions(+), 17 deletions(-) diff --git a/libavcodec/cbs_h266.h b/libavcodec/cbs_h266.h index be3c7444260..9e823919af2 100644 --- a/libavcodec/cbs_h266.h +++ b/libavcodec/cbs_h266.h @@ -552,6 +552,7 @@ typedef struct H266RawPPS { uint16_t num_tiles_in_pic; uint16_t slice_height_in_ctus[VVC_MAX_SLICES]; uint16_t num_slices_in_subpic[VVC_MAX_SLICES]; + uint16_t sub_pic_id_val[VVC_MAX_SLICES]; } H266RawPPS; typedef struct H266RawAUD { diff --git a/libavcodec/cbs_h266_syntax_template.c b/libavcodec/cbs_h266_syntax_template.c index f48b89cac92..f1cd45f8155 100644 --- a/libavcodec/cbs_h266_syntax_template.c +++ b/libavcodec/cbs_h266_syntax_template.c @@ -1706,6 +1706,15 @@ static int FUNC(pps) (CodedBitstreamContext *ctx, RWContext *rw, } } + for (i = 0; i <= sps->sps_num_subpics_minus1; i++) { + if (sps->sps_subpic_id_mapping_explicitly_signalled_flag) + current->sub_pic_id_val[i] = current->pps_subpic_id_mapping_present_flag + ? current->pps_subpic_id[i] + : sps->sps_subpic_id[i]; + else + current->sub_pic_id_val[i] = i; + } + pic_width_in_ctbs_y = AV_CEIL_RSHIFT (current->pps_pic_width_in_luma_samples, (sps->sps_log2_ctu_size_minus5 + 5)); pic_height_in_ctbs_y = AV_CEIL_RSHIFT( @@ -2697,25 +2706,16 @@ static int FUNC(slice_header) (CodedBitstreamContext *ctx, RWContext *rw, if (sps->sps_subpic_info_present_flag) { ub(sps->sps_subpic_id_len_minus1 + 1, sh_subpic_id); - if (sps->sps_subpic_id_mapping_explicitly_signalled_flag) { - for (i = 0; i <= sps->sps_num_subpics_minus1; i++) { - uint16_t subpic_id_val = - pps->pps_subpic_id_mapping_present_flag ? - pps->pps_subpic_id[i] : sps->sps_subpic_id[i]; - if (subpic_id_val == current->sh_subpic_id) { - curr_subpic_idx = i; - break; - } - } - } else { - curr_subpic_idx = current->sh_subpic_id; - if (curr_subpic_idx > sps->sps_num_subpics_minus1) { - av_log(ctx->log_ctx, AV_LOG_ERROR, - "sh_subpic_id(%d) should in range [0, %d]\n", - curr_subpic_idx, sps->sps_num_subpics_minus1); - return AVERROR_INVALIDDATA; + for (i = 0; i <= sps->sps_num_subpics_minus1; i++) { + if (pps->sub_pic_id_val[i] == current->sh_subpic_id) { + curr_subpic_idx = i; + break; } } + if (i > sps->sps_num_subpics_minus1) { + av_log(ctx->log_ctx, AV_LOG_ERROR, "invalid CurrSubpicIdx %d\n", i); + return AVERROR_INVALIDDATA; + } } else { curr_subpic_idx = 0; } From ab57b445273a49e72b42cd0542c5f4f23ec903c0 Mon Sep 17 00:00:00 2001 From: James Almer Date: Fri, 30 Jun 2023 13:44:34 -0300 Subject: [PATCH 1718/2172] fate/cbs: simplify the filter_unit discard tests No need to generate intermediate files and probe them. We only care to know that the output of the bsf excludes the frames in question, and a simple checksum is enough. Signed-off-by: James Almer --- tests/fate/cbs.mak | 30 +++++------ tests/ref/fate/cbs-h264-discard-bidir | 38 +------------ tests/ref/fate/cbs-h264-discard-nonintra | 9 +--- tests/ref/fate/cbs-h264-discard-nonkey | 4 +- tests/ref/fate/cbs-h264-discard-nonref | 68 +----------------------- tests/ref/fate/cbs-hevc-discard-bidir | 4 +- tests/ref/fate/cbs-hevc-discard-nonintra | 4 +- tests/ref/fate/cbs-hevc-discard-nonkey | 4 +- tests/ref/fate/cbs-hevc-discard-nonref | 27 +--------- 9 files changed, 20 insertions(+), 168 deletions(-) diff --git a/tests/fate/cbs.mak b/tests/fate/cbs.mak index b01a02766fc..6a68fcc5933 100644 --- a/tests/fate/cbs.mak +++ b/tests/fate/cbs.mak @@ -20,15 +20,9 @@ fate-cbs-$(1)-$(2): CMD = md5 -i $(TARGET_SAMPLES)/$(3) -c:v copy -y -bsf:v $(1) endef define FATE_CBS_DISCARD_TEST -# (codec, discard_type, sample_file, output_format, dep) +# (codec, discard_type, sample_file, output_format) FATE_CBS_$(1)_DISCARD += fate-cbs-$(1)-discard-$(2) -tests/data/fate/cbs-$(1)-discard-$2.$(4): TAG = GEN -tests/data/fate/cbs-$(1)-discard-$2.$(4): ffmpeg$(PROGSSUF)$(EXESUF) $(5) | tests/data - $(M)$(TARGET_EXEC) $(TARGET_PATH)/ffmpeg$(PROGSSUF)$(EXESUF) -nostdin \ - -i $(3) -c:v copy -fflags +bitexact -an -bsf:v filter_units=discard=$(2) \ - -f $(4) $(TARGET_PATH)/tests/data/fate/cbs-$(1)-discard-$(2).$(4) -y 2>/dev/null -fate-cbs-$(1)-discard-$2: ffprobe$(PROGSSUF)$(EXESUF) tests/data/fate/cbs-$(1)-discard-$(2).$(4) -fate-cbs-$(1)-discard-$2: CMD = ffprobe_demux $(TARGET_PATH)/tests/data/fate/cbs-$(1)-discard-$(2).$(4) +fate-cbs-$(1)-discard-$(2): CMD = md5 -i $(TARGET_SAMPLES)/$(3) -c:v copy -y -bsf:v filter_units=discard=$(2) -f $(4) endef # AV1 read/write @@ -86,12 +80,15 @@ $(foreach N,$(FATE_CBS_H264_SAMPLES),$(eval $(call FATE_CBS_TEST,h264,$(basename FATE_CBS_H264-$(call FATE_CBS_DEPS, H264, H264, H264, H264, H264) = $(FATE_CBS_h264) -$(eval $(call FATE_CBS_DISCARD_TEST,h264,nonref,$(TARGET_SAMPLES)/h264/interlaced_crop.mp4,mp4)) -$(eval $(call FATE_CBS_DISCARD_TEST,h264,bidir,$(TARGET_SAMPLES)/h264/interlaced_crop.mp4,mp4)) -$(eval $(call FATE_CBS_DISCARD_TEST,h264,nonintra,$(TARGET_SAMPLES)/h264/interlaced_crop.mp4,mp4)) -$(eval $(call FATE_CBS_DISCARD_TEST,h264,nonkey,$(TARGET_SAMPLES)/h264/interlaced_crop.mp4,mp4)) +FATE_CBS_DISCARD_TYPES = \ + nonref \ + bidir \ + nonintra \ + nonkey -FATE_CBS_H264-$(call ALLYES, MP4_MUXER, H264_PARSER, FILTER_UNITS_BSF, H264_MUXER) += $(FATE_CBS_h264_DISCARD) +$(foreach N,$(FATE_CBS_DISCARD_TYPES),$(eval $(call FATE_CBS_DISCARD_TEST,h264,$(N),$(TARGET_SAMPLES)/h264/interlaced_crop.mp4,h264))) + +FATE_CBS_H264-$(call ALLYES, MOV_DEMUXER, H264_MUXER, H264_PARSER, FILTER_UNITS_BSF) += $(FATE_CBS_h264_DISCARD) FATE_H264_REDUNDANT_PPS-$(call REMUX, H264, MOV_DEMUXER H264_REDUNDANT_PPS_BSF \ @@ -160,12 +157,9 @@ $(foreach N,$(FATE_CBS_HEVC_SAMPLES),$(eval $(call FATE_CBS_TEST,hevc,$(basename FATE_CBS_HEVC-$(call FATE_CBS_DEPS, HEVC, HEVC, HEVC, HEVC, HEVC) = $(FATE_CBS_hevc) -$(eval $(call FATE_CBS_DISCARD_TEST,hevc,nonref,$(TARGET_PATH)/tests/data/hevc-mp4.mov,mp4,tests/data/hevc-mp4.mov)) -$(eval $(call FATE_CBS_DISCARD_TEST,hevc,bidir,$(TARGET_PATH)/tests/data/hevc-mp4.mov,mp4,tests/data/hevc-mp4.mov)) -$(eval $(call FATE_CBS_DISCARD_TEST,hevc,nonintra,$(TARGET_PATH)/tests/data/hevc-mp4.mov,mp4,tests/data/hevc-mp4.mov)) -$(eval $(call FATE_CBS_DISCARD_TEST,hevc,nonkey,$(TARGET_PATH)/tests/data/hevc-mp4.mov,mp4,tests/data/hevc-mp4.mov)) +$(foreach N,$(FATE_CBS_DISCARD_TYPES),$(eval $(call FATE_CBS_DISCARD_TEST,hevc,$(N),$(TARGET_SAMPLES)/hevc-conformance/WPP_A_ericsson_MAIN10_2.bit,hevc))) -FATE_CBS_HEVC-$(call ALLYES, MP4_MUXER, HEVC_PARSER, FILTER_UNITS_BSF, HEVC_MUXER) += $(FATE_CBS_hevc_DISCARD) +FATE_CBS_HEVC-$(call ALLYES, HEVC_DEMUXER, HEVC_MUXER, HEVC_PARSER, FILTER_UNITS_BSF) += $(FATE_CBS_hevc_DISCARD) FATE_SAMPLES_AVCONV += $(FATE_CBS_HEVC-yes) fate-cbs-hevc: $(FATE_CBS_HEVC-yes) diff --git a/tests/ref/fate/cbs-h264-discard-bidir b/tests/ref/fate/cbs-h264-discard-bidir index 0a3f0b22c1c..065022edb42 100644 --- a/tests/ref/fate/cbs-h264-discard-bidir +++ b/tests/ref/fate/cbs-h264-discard-bidir @@ -1,37 +1 @@ -packet|codec_type=video|stream_index=0|pts=0|pts_time=0.000000|dts=-1024|dts_time=-0.080000|duration=512|duration_time=0.040000|size=22583|pos=48|flags=K__|data_hash=CRC32:69e4d65d -packet|codec_type=video|stream_index=0|pts=2048|pts_time=0.160000|dts=-512|dts_time=-0.040000|duration=512|duration_time=0.040000|size=4023|pos=22631|flags=___|data_hash=CRC32:0013cf12 -packet|codec_type=video|stream_index=0|pts=4096|pts_time=0.320000|dts=1536|dts_time=0.120000|duration=512|duration_time=0.040000|size=4214|pos=26654|flags=___|data_hash=CRC32:3d1a75de -packet|codec_type=video|stream_index=0|pts=6144|pts_time=0.480000|dts=3584|dts_time=0.280000|duration=512|duration_time=0.040000|size=4067|pos=30868|flags=___|data_hash=CRC32:0ae6ba93 -packet|codec_type=video|stream_index=0|pts=8192|pts_time=0.640000|dts=5632|dts_time=0.440000|duration=512|duration_time=0.040000|size=4223|pos=34935|flags=___|data_hash=CRC32:653ad50a -packet|codec_type=video|stream_index=0|pts=10240|pts_time=0.800000|dts=7680|dts_time=0.600000|duration=512|duration_time=0.040000|size=4757|pos=39158|flags=___|data_hash=CRC32:9c63fc60 -packet|codec_type=video|stream_index=0|pts=12288|pts_time=0.960000|dts=9728|dts_time=0.760000|duration=512|duration_time=0.040000|size=26559|pos=43915|flags=K__|data_hash=CRC32:3d91ff30 -packet|codec_type=video|stream_index=0|pts=14336|pts_time=1.120000|dts=11776|dts_time=0.920000|duration=512|duration_time=0.040000|size=3419|pos=70474|flags=___|data_hash=CRC32:a16c6e06 -packet|codec_type=video|stream_index=0|pts=16384|pts_time=1.280000|dts=13824|dts_time=1.080000|duration=512|duration_time=0.040000|size=4270|pos=73893|flags=___|data_hash=CRC32:75f5fba0 -packet|codec_type=video|stream_index=0|pts=18432|pts_time=1.440000|dts=15872|dts_time=1.240000|duration=512|duration_time=0.040000|size=6351|pos=78163|flags=___|data_hash=CRC32:b71a5f72 -packet|codec_type=video|stream_index=0|pts=20480|pts_time=1.600000|dts=17920|dts_time=1.400000|duration=512|duration_time=0.040000|size=5504|pos=84514|flags=___|data_hash=CRC32:f4513593 -packet|codec_type=video|stream_index=0|pts=22528|pts_time=1.760000|dts=19968|dts_time=1.560000|duration=512|duration_time=0.040000|size=5330|pos=90018|flags=___|data_hash=CRC32:e0e58cfc -packet|codec_type=video|stream_index=0|pts=24576|pts_time=1.920000|dts=22016|dts_time=1.720000|duration=512|duration_time=0.040000|size=25829|pos=95348|flags=K__|data_hash=CRC32:0ffa1941 -packet|codec_type=video|stream_index=0|pts=26624|pts_time=2.080000|dts=24064|dts_time=1.880000|duration=512|duration_time=0.040000|size=3788|pos=121177|flags=___|data_hash=CRC32:b7d88c97 -packet|codec_type=video|stream_index=0|pts=28672|pts_time=2.240000|dts=26112|dts_time=2.040000|duration=512|duration_time=0.040000|size=5277|pos=124965|flags=___|data_hash=CRC32:836281be -packet|codec_type=video|stream_index=0|pts=30720|pts_time=2.400000|dts=28160|dts_time=2.200000|duration=512|duration_time=0.040000|size=4423|pos=130242|flags=___|data_hash=CRC32:16ce42d5 -packet|codec_type=video|stream_index=0|pts=32768|pts_time=2.560000|dts=30208|dts_time=2.360000|duration=512|duration_time=0.040000|size=4789|pos=134665|flags=___|data_hash=CRC32:c3253157 -packet|codec_type=video|stream_index=0|pts=34816|pts_time=2.720000|dts=32256|dts_time=2.520000|duration=512|duration_time=0.040000|size=4543|pos=139454|flags=___|data_hash=CRC32:2b284455 -packet|codec_type=video|stream_index=0|pts=36864|pts_time=2.880000|dts=34304|dts_time=2.680000|duration=512|duration_time=0.040000|size=24224|pos=143997|flags=K__|data_hash=CRC32:f4545b97 -packet|codec_type=video|stream_index=0|pts=38912|pts_time=3.040000|dts=36352|dts_time=2.840000|duration=512|duration_time=0.040000|size=3804|pos=168221|flags=___|data_hash=CRC32:9e182c9d -packet|codec_type=video|stream_index=0|pts=40960|pts_time=3.200000|dts=38400|dts_time=3.000000|duration=512|duration_time=0.040000|size=4832|pos=172025|flags=___|data_hash=CRC32:9177a3b3 -packet|codec_type=video|stream_index=0|pts=43008|pts_time=3.360000|dts=40448|dts_time=3.160000|duration=512|duration_time=0.040000|size=5169|pos=176857|flags=___|data_hash=CRC32:4b98426d -packet|codec_type=video|stream_index=0|pts=45056|pts_time=3.520000|dts=42496|dts_time=3.320000|duration=512|duration_time=0.040000|size=5428|pos=182026|flags=___|data_hash=CRC32:1b44d316 -packet|codec_type=video|stream_index=0|pts=47104|pts_time=3.680000|dts=44544|dts_time=3.480000|duration=512|duration_time=0.040000|size=5354|pos=187454|flags=___|data_hash=CRC32:e9e88511 -packet|codec_type=video|stream_index=0|pts=49152|pts_time=3.840000|dts=46592|dts_time=3.640000|duration=512|duration_time=0.040000|size=24046|pos=192808|flags=K__|data_hash=CRC32:ce41a6fe -packet|codec_type=video|stream_index=0|pts=51200|pts_time=4.000000|dts=48640|dts_time=3.800000|duration=512|duration_time=0.040000|size=4427|pos=216854|flags=___|data_hash=CRC32:69f58de5 -packet|codec_type=video|stream_index=0|pts=53248|pts_time=4.160000|dts=50688|dts_time=3.960000|duration=512|duration_time=0.040000|size=5196|pos=221281|flags=___|data_hash=CRC32:82877b2a -packet|codec_type=video|stream_index=0|pts=55296|pts_time=4.320000|dts=52736|dts_time=4.120000|duration=512|duration_time=0.040000|size=6958|pos=226477|flags=___|data_hash=CRC32:14b54257 -packet|codec_type=video|stream_index=0|pts=57344|pts_time=4.480000|dts=54784|dts_time=4.280000|duration=512|duration_time=0.040000|size=5007|pos=233435|flags=___|data_hash=CRC32:7b5d6eff -packet|codec_type=video|stream_index=0|pts=59392|pts_time=4.640000|dts=56832|dts_time=4.440000|duration=512|duration_time=0.040000|size=1864|pos=238442|flags=___|data_hash=CRC32:32f9a8b3 -packet|codec_type=video|stream_index=0|pts=61440|pts_time=4.800000|dts=58880|dts_time=4.600000|duration=512|duration_time=0.040000|size=22592|pos=240306|flags=K__|data_hash=CRC32:413e519a -packet|codec_type=video|stream_index=0|pts=61952|pts_time=4.840000|dts=60928|dts_time=4.760000|duration=512|duration_time=0.040000|size=158|pos=262898|flags=___|data_hash=CRC32:aedfe6be -packet|codec_type=video|stream_index=0|pts=62464|pts_time=4.880000|dts=61440|dts_time=4.800000|duration=512|duration_time=0.040000|size=332|pos=263056|flags=___|data_hash=CRC32:4d2e6f42 -packet|codec_type=video|stream_index=0|pts=63488|pts_time=4.960000|dts=61952|dts_time=4.840000|duration=512|duration_time=0.040000|size=326|pos=263388|flags=___|data_hash=CRC32:c9e610e6 -packet|codec_type=video|stream_index=0|pts=64000|pts_time=5.000000|dts=62976|dts_time=4.920000|duration=512|duration_time=0.040000|size=235|pos=263714|flags=___|data_hash=CRC32:5b757bc6 -stream|index=0|codec_name=h264|profile=77|codec_type=video|codec_tag_string=avc1|codec_tag=0x31637661|width=640|height=360|coded_width=640|coded_height=360|closed_captions=0|film_grain=0|has_b_frames=2|sample_aspect_ratio=1:1|display_aspect_ratio=16:9|pix_fmt=yuv420p|level=41|color_range=unknown|color_space=unknown|color_transfer=unknown|color_primaries=unknown|chroma_location=left|field_order=tt|refs=1|is_avc=true|nal_length_size=4|id=0x1|r_frame_rate=25/1|avg_frame_rate=125/18|time_base=1/12800|start_pts=0|start_time=0.000000|duration_ts=64512|duration=5.040000|bit_rate=418890|max_bit_rate=N/A|bits_per_raw_sample=8|nb_frames=35|nb_read_frames=N/A|nb_read_packets=35|extradata_size=54|extradata_hash=CRC32:148701ce|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:language=und|tag:handler_name=GPAC ISO Video Handler|tag:vendor_id=[0][0][0][0] -format|filename=cbs-h264-discard-bidir.mp4|nb_streams=1|nb_programs=0|format_name=mov,mp4,m4a,3gp,3g2,mj2|start_time=0.000000|duration=5.040000|size=264989|bit_rate=420617|probe_score=100|tag:major_brand=isom|tag:minor_version=512|tag:compatible_brands=isomiso2avc1mp41 +7940bb467e4b795f123e0ab147ca4bea diff --git a/tests/ref/fate/cbs-h264-discard-nonintra b/tests/ref/fate/cbs-h264-discard-nonintra index a482b4c8e24..bad37dbee40 100644 --- a/tests/ref/fate/cbs-h264-discard-nonintra +++ b/tests/ref/fate/cbs-h264-discard-nonintra @@ -1,8 +1 @@ -packet|codec_type=video|stream_index=0|pts=0|pts_time=0.000000|dts=-1024|dts_time=-0.080000|duration=512|duration_time=0.040000|size=22583|pos=48|flags=K__|data_hash=CRC32:69e4d65d -packet|codec_type=video|stream_index=0|pts=12288|pts_time=0.960000|dts=9728|dts_time=0.760000|duration=512|duration_time=0.040000|size=26559|pos=22631|flags=K__|data_hash=CRC32:3d91ff30 -packet|codec_type=video|stream_index=0|pts=24576|pts_time=1.920000|dts=22016|dts_time=1.720000|duration=512|duration_time=0.040000|size=25829|pos=49190|flags=K__|data_hash=CRC32:0ffa1941 -packet|codec_type=video|stream_index=0|pts=36864|pts_time=2.880000|dts=34304|dts_time=2.680000|duration=512|duration_time=0.040000|size=24224|pos=75019|flags=K__|data_hash=CRC32:f4545b97 -packet|codec_type=video|stream_index=0|pts=49152|pts_time=3.840000|dts=46592|dts_time=3.640000|duration=512|duration_time=0.040000|size=24046|pos=99243|flags=K__|data_hash=CRC32:ce41a6fe -packet|codec_type=video|stream_index=0|pts=61440|pts_time=4.800000|dts=58880|dts_time=4.600000|duration=512|duration_time=0.040000|size=22592|pos=123289|flags=K__|data_hash=CRC32:413e519a -stream|index=0|codec_name=h264|profile=77|codec_type=video|codec_tag_string=avc1|codec_tag=0x31637661|width=640|height=360|coded_width=640|coded_height=360|closed_captions=0|film_grain=0|has_b_frames=2|sample_aspect_ratio=1:1|display_aspect_ratio=16:9|pix_fmt=yuv420p|level=41|color_range=unknown|color_space=unknown|color_transfer=unknown|color_primaries=unknown|chroma_location=left|field_order=tt|refs=1|is_avc=true|nal_length_size=4|id=0x1|r_frame_rate=25/12|avg_frame_rate=75/59|time_base=1/12800|start_pts=0|start_time=0.000000|duration_ts=60416|duration=4.720000|bit_rate=247174|max_bit_rate=N/A|bits_per_raw_sample=8|nb_frames=6|nb_read_frames=N/A|nb_read_packets=6|extradata_size=54|extradata_hash=CRC32:148701ce|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:language=und|tag:handler_name=GPAC ISO Video Handler|tag:vendor_id=[0][0][0][0] -format|filename=cbs-h264-discard-nonintra.mp4|nb_streams=1|nb_programs=0|format_name=mov,mp4,m4a,3gp,3g2,mj2|start_time=0.000000|duration=4.720000|size=146725|bit_rate=248686|probe_score=100|tag:major_brand=isom|tag:minor_version=512|tag:compatible_brands=isomiso2avc1mp41 +e5ec7a91e6213248027eeea3e498c205 diff --git a/tests/ref/fate/cbs-h264-discard-nonkey b/tests/ref/fate/cbs-h264-discard-nonkey index 85417124fc0..75cb7f94b53 100644 --- a/tests/ref/fate/cbs-h264-discard-nonkey +++ b/tests/ref/fate/cbs-h264-discard-nonkey @@ -1,3 +1 @@ -packet|codec_type=video|stream_index=0|pts=0|pts_time=0.000000|dts=-1024|dts_time=-0.080000|duration=512|duration_time=0.040000|size=22583|pos=48|flags=K__|data_hash=CRC32:69e4d65d -stream|index=0|codec_name=h264|profile=77|codec_type=video|codec_tag_string=avc1|codec_tag=0x31637661|width=640|height=360|coded_width=640|coded_height=360|closed_captions=0|film_grain=0|has_b_frames=2|sample_aspect_ratio=1:1|display_aspect_ratio=16:9|pix_fmt=yuv420p|level=41|color_range=unknown|color_space=unknown|color_transfer=unknown|color_primaries=unknown|chroma_location=left|field_order=tt|refs=1|is_avc=true|nal_length_size=4|id=0x1|r_frame_rate=25/1|avg_frame_rate=25/1|time_base=1/12800|start_pts=0|start_time=0.000000|duration_ts=512|duration=0.040000|bit_rate=4516600|max_bit_rate=N/A|bits_per_raw_sample=8|nb_frames=1|nb_read_frames=N/A|nb_read_packets=1|extradata_size=54|extradata_hash=CRC32:148701ce|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:language=und|tag:handler_name=GPAC ISO Video Handler|tag:vendor_id=[0][0][0][0] -format|filename=cbs-h264-discard-nonkey.mp4|nb_streams=1|nb_programs=0|format_name=mov,mp4,m4a,3gp,3g2,mj2|start_time=0.000000|duration=0.040000|size=23427|bit_rate=4685400|probe_score=100|tag:major_brand=isom|tag:minor_version=512|tag:compatible_brands=isomiso2avc1mp41 +2f3a096573bc63190c83886ba8860c37 diff --git a/tests/ref/fate/cbs-h264-discard-nonref b/tests/ref/fate/cbs-h264-discard-nonref index 5272466a675..a82fd7c08d2 100644 --- a/tests/ref/fate/cbs-h264-discard-nonref +++ b/tests/ref/fate/cbs-h264-discard-nonref @@ -1,67 +1 @@ -packet|codec_type=video|stream_index=0|pts=0|pts_time=0.000000|dts=-1024|dts_time=-0.080000|duration=512|duration_time=0.040000|size=22583|pos=48|flags=K__|data_hash=CRC32:69e4d65d -packet|codec_type=video|stream_index=0|pts=2048|pts_time=0.160000|dts=-512|dts_time=-0.040000|duration=512|duration_time=0.040000|size=4023|pos=22631|flags=___|data_hash=CRC32:0013cf12 -packet|codec_type=video|stream_index=0|pts=1024|pts_time=0.080000|dts=0|dts_time=0.000000|duration=512|duration_time=0.040000|size=1098|pos=26654|flags=___|data_hash=CRC32:0fa0e9cb -packet|codec_type=video|stream_index=0|pts=4096|pts_time=0.320000|dts=1536|dts_time=0.120000|duration=512|duration_time=0.040000|size=4214|pos=27752|flags=___|data_hash=CRC32:3d1a75de -packet|codec_type=video|stream_index=0|pts=3072|pts_time=0.240000|dts=2048|dts_time=0.160000|duration=512|duration_time=0.040000|size=1119|pos=31966|flags=___|data_hash=CRC32:2f0223aa -packet|codec_type=video|stream_index=0|pts=6144|pts_time=0.480000|dts=3584|dts_time=0.280000|duration=512|duration_time=0.040000|size=4067|pos=33085|flags=___|data_hash=CRC32:0ae6ba93 -packet|codec_type=video|stream_index=0|pts=5120|pts_time=0.400000|dts=4096|dts_time=0.320000|duration=512|duration_time=0.040000|size=964|pos=37152|flags=___|data_hash=CRC32:c8ce52dc -packet|codec_type=video|stream_index=0|pts=8192|pts_time=0.640000|dts=5632|dts_time=0.440000|duration=512|duration_time=0.040000|size=4223|pos=38116|flags=___|data_hash=CRC32:653ad50a -packet|codec_type=video|stream_index=0|pts=7168|pts_time=0.560000|dts=6144|dts_time=0.480000|duration=512|duration_time=0.040000|size=1042|pos=42339|flags=___|data_hash=CRC32:9979a4e9 -packet|codec_type=video|stream_index=0|pts=10240|pts_time=0.800000|dts=7680|dts_time=0.600000|duration=512|duration_time=0.040000|size=4757|pos=43381|flags=___|data_hash=CRC32:9c63fc60 -packet|codec_type=video|stream_index=0|pts=9216|pts_time=0.720000|dts=8192|dts_time=0.640000|duration=512|duration_time=0.040000|size=1184|pos=48138|flags=___|data_hash=CRC32:b8909a00 -packet|codec_type=video|stream_index=0|pts=12288|pts_time=0.960000|dts=9728|dts_time=0.760000|duration=512|duration_time=0.040000|size=26559|pos=49322|flags=K__|data_hash=CRC32:3d91ff30 -packet|codec_type=video|stream_index=0|pts=11264|pts_time=0.880000|dts=10240|dts_time=0.800000|duration=512|duration_time=0.040000|size=1143|pos=75881|flags=___|data_hash=CRC32:cae51d5c -packet|codec_type=video|stream_index=0|pts=14336|pts_time=1.120000|dts=11776|dts_time=0.920000|duration=512|duration_time=0.040000|size=3419|pos=77024|flags=___|data_hash=CRC32:a16c6e06 -packet|codec_type=video|stream_index=0|pts=13312|pts_time=1.040000|dts=12288|dts_time=0.960000|duration=512|duration_time=0.040000|size=1130|pos=80443|flags=___|data_hash=CRC32:53fdc474 -packet|codec_type=video|stream_index=0|pts=16384|pts_time=1.280000|dts=13824|dts_time=1.080000|duration=512|duration_time=0.040000|size=4270|pos=81573|flags=___|data_hash=CRC32:75f5fba0 -packet|codec_type=video|stream_index=0|pts=15360|pts_time=1.200000|dts=14336|dts_time=1.120000|duration=512|duration_time=0.040000|size=1121|pos=85843|flags=___|data_hash=CRC32:bcef6ae6 -packet|codec_type=video|stream_index=0|pts=18432|pts_time=1.440000|dts=15872|dts_time=1.240000|duration=512|duration_time=0.040000|size=6351|pos=86964|flags=___|data_hash=CRC32:b71a5f72 -packet|codec_type=video|stream_index=0|pts=17408|pts_time=1.360000|dts=16384|dts_time=1.280000|duration=512|duration_time=0.040000|size=1190|pos=93315|flags=___|data_hash=CRC32:bb46179d -packet|codec_type=video|stream_index=0|pts=20480|pts_time=1.600000|dts=17920|dts_time=1.400000|duration=512|duration_time=0.040000|size=5504|pos=94505|flags=___|data_hash=CRC32:f4513593 -packet|codec_type=video|stream_index=0|pts=19456|pts_time=1.520000|dts=18432|dts_time=1.440000|duration=512|duration_time=0.040000|size=1242|pos=100009|flags=___|data_hash=CRC32:14765239 -packet|codec_type=video|stream_index=0|pts=22528|pts_time=1.760000|dts=19968|dts_time=1.560000|duration=512|duration_time=0.040000|size=5330|pos=101251|flags=___|data_hash=CRC32:e0e58cfc -packet|codec_type=video|stream_index=0|pts=21504|pts_time=1.680000|dts=20480|dts_time=1.600000|duration=512|duration_time=0.040000|size=1273|pos=106581|flags=___|data_hash=CRC32:47e84071 -packet|codec_type=video|stream_index=0|pts=24576|pts_time=1.920000|dts=22016|dts_time=1.720000|duration=512|duration_time=0.040000|size=25829|pos=107854|flags=K__|data_hash=CRC32:0ffa1941 -packet|codec_type=video|stream_index=0|pts=23552|pts_time=1.840000|dts=22528|dts_time=1.760000|duration=512|duration_time=0.040000|size=1208|pos=133683|flags=___|data_hash=CRC32:c36f1ddc -packet|codec_type=video|stream_index=0|pts=26624|pts_time=2.080000|dts=24064|dts_time=1.880000|duration=512|duration_time=0.040000|size=3788|pos=134891|flags=___|data_hash=CRC32:b7d88c97 -packet|codec_type=video|stream_index=0|pts=25600|pts_time=2.000000|dts=24576|dts_time=1.920000|duration=512|duration_time=0.040000|size=1189|pos=138679|flags=___|data_hash=CRC32:f1000036 -packet|codec_type=video|stream_index=0|pts=28672|pts_time=2.240000|dts=26112|dts_time=2.040000|duration=512|duration_time=0.040000|size=5277|pos=139868|flags=___|data_hash=CRC32:836281be -packet|codec_type=video|stream_index=0|pts=27648|pts_time=2.160000|dts=26624|dts_time=2.080000|duration=512|duration_time=0.040000|size=1354|pos=145145|flags=___|data_hash=CRC32:60d42d85 -packet|codec_type=video|stream_index=0|pts=30720|pts_time=2.400000|dts=28160|dts_time=2.200000|duration=512|duration_time=0.040000|size=4423|pos=146499|flags=___|data_hash=CRC32:16ce42d5 -packet|codec_type=video|stream_index=0|pts=29696|pts_time=2.320000|dts=28672|dts_time=2.240000|duration=512|duration_time=0.040000|size=1466|pos=150922|flags=___|data_hash=CRC32:bb24a5a6 -packet|codec_type=video|stream_index=0|pts=32768|pts_time=2.560000|dts=30208|dts_time=2.360000|duration=512|duration_time=0.040000|size=4789|pos=152388|flags=___|data_hash=CRC32:c3253157 -packet|codec_type=video|stream_index=0|pts=31744|pts_time=2.480000|dts=30720|dts_time=2.400000|duration=512|duration_time=0.040000|size=1437|pos=157177|flags=___|data_hash=CRC32:25effcab -packet|codec_type=video|stream_index=0|pts=34816|pts_time=2.720000|dts=32256|dts_time=2.520000|duration=512|duration_time=0.040000|size=4543|pos=158614|flags=___|data_hash=CRC32:2b284455 -packet|codec_type=video|stream_index=0|pts=33792|pts_time=2.640000|dts=32768|dts_time=2.560000|duration=512|duration_time=0.040000|size=1547|pos=163157|flags=___|data_hash=CRC32:fec8c6fd -packet|codec_type=video|stream_index=0|pts=36864|pts_time=2.880000|dts=34304|dts_time=2.680000|duration=512|duration_time=0.040000|size=24224|pos=164704|flags=K__|data_hash=CRC32:f4545b97 -packet|codec_type=video|stream_index=0|pts=35840|pts_time=2.800000|dts=34816|dts_time=2.720000|duration=512|duration_time=0.040000|size=1424|pos=188928|flags=___|data_hash=CRC32:9fea2803 -packet|codec_type=video|stream_index=0|pts=38912|pts_time=3.040000|dts=36352|dts_time=2.840000|duration=512|duration_time=0.040000|size=3804|pos=190352|flags=___|data_hash=CRC32:9e182c9d -packet|codec_type=video|stream_index=0|pts=37888|pts_time=2.960000|dts=36864|dts_time=2.880000|duration=512|duration_time=0.040000|size=1286|pos=194156|flags=___|data_hash=CRC32:80fc98bb -packet|codec_type=video|stream_index=0|pts=40960|pts_time=3.200000|dts=38400|dts_time=3.000000|duration=512|duration_time=0.040000|size=4832|pos=195442|flags=___|data_hash=CRC32:9177a3b3 -packet|codec_type=video|stream_index=0|pts=39936|pts_time=3.120000|dts=38912|dts_time=3.040000|duration=512|duration_time=0.040000|size=1448|pos=200274|flags=___|data_hash=CRC32:ddfa0b77 -packet|codec_type=video|stream_index=0|pts=43008|pts_time=3.360000|dts=40448|dts_time=3.160000|duration=512|duration_time=0.040000|size=5169|pos=201722|flags=___|data_hash=CRC32:4b98426d -packet|codec_type=video|stream_index=0|pts=41984|pts_time=3.280000|dts=40960|dts_time=3.200000|duration=512|duration_time=0.040000|size=1451|pos=206891|flags=___|data_hash=CRC32:aea0b422 -packet|codec_type=video|stream_index=0|pts=45056|pts_time=3.520000|dts=42496|dts_time=3.320000|duration=512|duration_time=0.040000|size=5428|pos=208342|flags=___|data_hash=CRC32:1b44d316 -packet|codec_type=video|stream_index=0|pts=44032|pts_time=3.440000|dts=43008|dts_time=3.360000|duration=512|duration_time=0.040000|size=1576|pos=213770|flags=___|data_hash=CRC32:cbb3eee1 -packet|codec_type=video|stream_index=0|pts=47104|pts_time=3.680000|dts=44544|dts_time=3.480000|duration=512|duration_time=0.040000|size=5354|pos=215346|flags=___|data_hash=CRC32:e9e88511 -packet|codec_type=video|stream_index=0|pts=46080|pts_time=3.600000|dts=45056|dts_time=3.520000|duration=512|duration_time=0.040000|size=1503|pos=220700|flags=___|data_hash=CRC32:b9ee459e -packet|codec_type=video|stream_index=0|pts=49152|pts_time=3.840000|dts=46592|dts_time=3.640000|duration=512|duration_time=0.040000|size=24046|pos=222203|flags=K__|data_hash=CRC32:ce41a6fe -packet|codec_type=video|stream_index=0|pts=48128|pts_time=3.760000|dts=47104|dts_time=3.680000|duration=512|duration_time=0.040000|size=1584|pos=246249|flags=___|data_hash=CRC32:4438c672 -packet|codec_type=video|stream_index=0|pts=51200|pts_time=4.000000|dts=48640|dts_time=3.800000|duration=512|duration_time=0.040000|size=4427|pos=247833|flags=___|data_hash=CRC32:69f58de5 -packet|codec_type=video|stream_index=0|pts=50176|pts_time=3.920000|dts=49152|dts_time=3.840000|duration=512|duration_time=0.040000|size=1494|pos=252260|flags=___|data_hash=CRC32:b78c9e7d -packet|codec_type=video|stream_index=0|pts=53248|pts_time=4.160000|dts=50688|dts_time=3.960000|duration=512|duration_time=0.040000|size=5196|pos=253754|flags=___|data_hash=CRC32:82877b2a -packet|codec_type=video|stream_index=0|pts=52224|pts_time=4.080000|dts=51200|dts_time=4.000000|duration=512|duration_time=0.040000|size=1485|pos=258950|flags=___|data_hash=CRC32:84553d2d -packet|codec_type=video|stream_index=0|pts=55296|pts_time=4.320000|dts=52736|dts_time=4.120000|duration=512|duration_time=0.040000|size=6958|pos=260435|flags=___|data_hash=CRC32:14b54257 -packet|codec_type=video|stream_index=0|pts=54272|pts_time=4.240000|dts=53248|dts_time=4.160000|duration=512|duration_time=0.040000|size=1189|pos=267393|flags=___|data_hash=CRC32:845381ae -packet|codec_type=video|stream_index=0|pts=57344|pts_time=4.480000|dts=54784|dts_time=4.280000|duration=512|duration_time=0.040000|size=5007|pos=268582|flags=___|data_hash=CRC32:7b5d6eff -packet|codec_type=video|stream_index=0|pts=56320|pts_time=4.400000|dts=55296|dts_time=4.320000|duration=512|duration_time=0.040000|size=454|pos=273589|flags=___|data_hash=CRC32:eccc8273 -packet|codec_type=video|stream_index=0|pts=59392|pts_time=4.640000|dts=56832|dts_time=4.440000|duration=512|duration_time=0.040000|size=1864|pos=274043|flags=___|data_hash=CRC32:32f9a8b3 -packet|codec_type=video|stream_index=0|pts=58368|pts_time=4.560000|dts=57344|dts_time=4.480000|duration=512|duration_time=0.040000|size=361|pos=275907|flags=___|data_hash=CRC32:fe582a76 -packet|codec_type=video|stream_index=0|pts=61440|pts_time=4.800000|dts=58880|dts_time=4.600000|duration=512|duration_time=0.040000|size=22592|pos=276268|flags=K__|data_hash=CRC32:413e519a -packet|codec_type=video|stream_index=0|pts=60416|pts_time=4.720000|dts=59392|dts_time=4.640000|duration=512|duration_time=0.040000|size=385|pos=298860|flags=___|data_hash=CRC32:aee406fc -packet|codec_type=video|stream_index=0|pts=61952|pts_time=4.840000|dts=60928|dts_time=4.760000|duration=512|duration_time=0.040000|size=158|pos=299245|flags=___|data_hash=CRC32:aedfe6be -packet|codec_type=video|stream_index=0|pts=62464|pts_time=4.880000|dts=61440|dts_time=4.800000|duration=512|duration_time=0.040000|size=332|pos=299403|flags=___|data_hash=CRC32:4d2e6f42 -packet|codec_type=video|stream_index=0|pts=63488|pts_time=4.960000|dts=61952|dts_time=4.840000|duration=512|duration_time=0.040000|size=326|pos=299735|flags=___|data_hash=CRC32:c9e610e6 -packet|codec_type=video|stream_index=0|pts=64000|pts_time=5.000000|dts=62976|dts_time=4.920000|duration=512|duration_time=0.040000|size=235|pos=300061|flags=___|data_hash=CRC32:5b757bc6 -stream|index=0|codec_name=h264|profile=77|codec_type=video|codec_tag_string=avc1|codec_tag=0x31637661|width=640|height=360|coded_width=640|coded_height=360|closed_captions=0|film_grain=0|has_b_frames=2|sample_aspect_ratio=1:1|display_aspect_ratio=16:9|pix_fmt=yuv420p|level=41|color_range=unknown|color_space=unknown|color_transfer=unknown|color_primaries=unknown|chroma_location=left|field_order=tt|refs=1|is_avc=true|nal_length_size=4|id=0x1|r_frame_rate=25/1|avg_frame_rate=1625/126|time_base=1/12800|start_pts=0|start_time=0.000000|duration_ts=64512|duration=5.040000|bit_rate=476584|max_bit_rate=N/A|bits_per_raw_sample=8|nb_frames=65|nb_read_frames=N/A|nb_read_packets=65|extradata_size=54|extradata_hash=CRC32:148701ce|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:language=und|tag:handler_name=GPAC ISO Video Handler|tag:vendor_id=[0][0][0][0] -format|filename=cbs-h264-discard-nonref.mp4|nb_streams=1|nb_programs=0|format_name=mov,mp4,m4a,3gp,3g2,mj2|start_time=0.000000|duration=5.040000|size=302384|bit_rate=479974|probe_score=100|tag:major_brand=isom|tag:minor_version=512|tag:compatible_brands=isomiso2avc1mp41 +6782650c620a5c8aff3107e192af19a7 diff --git a/tests/ref/fate/cbs-hevc-discard-bidir b/tests/ref/fate/cbs-hevc-discard-bidir index 399e9520768..39dd4405f24 100644 --- a/tests/ref/fate/cbs-hevc-discard-bidir +++ b/tests/ref/fate/cbs-hevc-discard-bidir @@ -1,3 +1 @@ -packet|codec_type=video|stream_index=0|pts=0|pts_time=0.000000|dts=0|dts_time=0.000000|duration=48000|duration_time=0.040000|size=7454|pos=44|flags=KD_|data_hash=CRC32:4c4c3bab -stream|index=0|codec_name=hevc|profile=2|codec_type=video|codec_tag_string=hev1|codec_tag=0x31766568|width=416|height=240|coded_width=416|coded_height=240|closed_captions=0|film_grain=0|has_b_frames=3|sample_aspect_ratio=N/A|display_aspect_ratio=N/A|pix_fmt=yuv420p10le|level=60|color_range=tv|color_space=unknown|color_transfer=unknown|color_primaries=unknown|chroma_location=left|field_order=unknown|refs=1|id=0x1|r_frame_rate=25/1|avg_frame_rate=25/1|time_base=1/1200000|start_pts=0|start_time=0.000000|duration_ts=48000|duration=0.040000|bit_rate=1490800|max_bit_rate=N/A|bits_per_raw_sample=N/A|nb_frames=1|nb_read_frames=N/A|nb_read_packets=1|extradata_size=121|extradata_hash=CRC32:bd471302|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:language=und|tag:handler_name=VideoHandler|tag:vendor_id=[0][0][0][0] -format|filename=cbs-hevc-discard-bidir.mp4|nb_streams=1|nb_programs=0|format_name=mov,mp4,m4a,3gp,3g2,mj2|start_time=0.000000|duration=0.040000|size=8311|bit_rate=1662200|probe_score=100|tag:major_brand=isom|tag:minor_version=512|tag:compatible_brands=isomiso2mp41 +1e288139b41d50b5d117ef2610bf4d53 diff --git a/tests/ref/fate/cbs-hevc-discard-nonintra b/tests/ref/fate/cbs-hevc-discard-nonintra index 2932641bbd1..39dd4405f24 100644 --- a/tests/ref/fate/cbs-hevc-discard-nonintra +++ b/tests/ref/fate/cbs-hevc-discard-nonintra @@ -1,3 +1 @@ -packet|codec_type=video|stream_index=0|pts=0|pts_time=0.000000|dts=0|dts_time=0.000000|duration=48000|duration_time=0.040000|size=7454|pos=44|flags=KD_|data_hash=CRC32:4c4c3bab -stream|index=0|codec_name=hevc|profile=2|codec_type=video|codec_tag_string=hev1|codec_tag=0x31766568|width=416|height=240|coded_width=416|coded_height=240|closed_captions=0|film_grain=0|has_b_frames=3|sample_aspect_ratio=N/A|display_aspect_ratio=N/A|pix_fmt=yuv420p10le|level=60|color_range=tv|color_space=unknown|color_transfer=unknown|color_primaries=unknown|chroma_location=left|field_order=unknown|refs=1|id=0x1|r_frame_rate=25/1|avg_frame_rate=25/1|time_base=1/1200000|start_pts=0|start_time=0.000000|duration_ts=48000|duration=0.040000|bit_rate=1490800|max_bit_rate=N/A|bits_per_raw_sample=N/A|nb_frames=1|nb_read_frames=N/A|nb_read_packets=1|extradata_size=121|extradata_hash=CRC32:bd471302|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:language=und|tag:handler_name=VideoHandler|tag:vendor_id=[0][0][0][0] -format|filename=cbs-hevc-discard-nonintra.mp4|nb_streams=1|nb_programs=0|format_name=mov,mp4,m4a,3gp,3g2,mj2|start_time=0.000000|duration=0.040000|size=8311|bit_rate=1662200|probe_score=100|tag:major_brand=isom|tag:minor_version=512|tag:compatible_brands=isomiso2mp41 +1e288139b41d50b5d117ef2610bf4d53 diff --git a/tests/ref/fate/cbs-hevc-discard-nonkey b/tests/ref/fate/cbs-hevc-discard-nonkey index 47e916c4164..39dd4405f24 100644 --- a/tests/ref/fate/cbs-hevc-discard-nonkey +++ b/tests/ref/fate/cbs-hevc-discard-nonkey @@ -1,3 +1 @@ -packet|codec_type=video|stream_index=0|pts=0|pts_time=0.000000|dts=0|dts_time=0.000000|duration=48000|duration_time=0.040000|size=7454|pos=44|flags=KD_|data_hash=CRC32:4c4c3bab -stream|index=0|codec_name=hevc|profile=2|codec_type=video|codec_tag_string=hev1|codec_tag=0x31766568|width=416|height=240|coded_width=416|coded_height=240|closed_captions=0|film_grain=0|has_b_frames=3|sample_aspect_ratio=N/A|display_aspect_ratio=N/A|pix_fmt=yuv420p10le|level=60|color_range=tv|color_space=unknown|color_transfer=unknown|color_primaries=unknown|chroma_location=left|field_order=unknown|refs=1|id=0x1|r_frame_rate=25/1|avg_frame_rate=25/1|time_base=1/1200000|start_pts=0|start_time=0.000000|duration_ts=48000|duration=0.040000|bit_rate=1490800|max_bit_rate=N/A|bits_per_raw_sample=N/A|nb_frames=1|nb_read_frames=N/A|nb_read_packets=1|extradata_size=121|extradata_hash=CRC32:bd471302|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:language=und|tag:handler_name=VideoHandler|tag:vendor_id=[0][0][0][0] -format|filename=cbs-hevc-discard-nonkey.mp4|nb_streams=1|nb_programs=0|format_name=mov,mp4,m4a,3gp,3g2,mj2|start_time=0.000000|duration=0.040000|size=8311|bit_rate=1662200|probe_score=100|tag:major_brand=isom|tag:minor_version=512|tag:compatible_brands=isomiso2mp41 +1e288139b41d50b5d117ef2610bf4d53 diff --git a/tests/ref/fate/cbs-hevc-discard-nonref b/tests/ref/fate/cbs-hevc-discard-nonref index 5090ef32e1f..12624f08498 100644 --- a/tests/ref/fate/cbs-hevc-discard-nonref +++ b/tests/ref/fate/cbs-hevc-discard-nonref @@ -1,26 +1 @@ -packet|codec_type=video|stream_index=0|pts=-144000|pts_time=-0.120000|dts=-144000|dts_time=-0.120000|duration=48000|duration_time=0.040000|size=7454|pos=44|flags=KD_|data_hash=CRC32:4c4c3bab -packet|codec_type=video|stream_index=0|pts=-96000|pts_time=-0.080000|dts=-96000|dts_time=-0.080000|duration=48000|duration_time=0.040000|size=2622|pos=7498|flags=_D_|data_hash=CRC32:a49f2745 -packet|codec_type=video|stream_index=0|pts=-48000|pts_time=-0.040000|dts=-48000|dts_time=-0.040000|duration=48000|duration_time=0.040000|size=4672|pos=10120|flags=_D_|data_hash=CRC32:37967f67 -packet|codec_type=video|stream_index=0|pts=0|pts_time=0.000000|dts=0|dts_time=0.000000|duration=144000|duration_time=0.120000|size=4624|pos=14792|flags=___|data_hash=CRC32:f2b7eb13 -packet|codec_type=video|stream_index=0|pts=144000|pts_time=0.120000|dts=144000|dts_time=0.120000|duration=144000|duration_time=0.120000|size=4192|pos=19416|flags=___|data_hash=CRC32:6538ec17 -packet|codec_type=video|stream_index=0|pts=288000|pts_time=0.240000|dts=288000|dts_time=0.240000|duration=48000|duration_time=0.040000|size=2521|pos=23608|flags=___|data_hash=CRC32:eb27f045 -packet|codec_type=video|stream_index=0|pts=336000|pts_time=0.280000|dts=336000|dts_time=0.280000|duration=48000|duration_time=0.040000|size=1343|pos=26129|flags=___|data_hash=CRC32:a719dc68 -packet|codec_type=video|stream_index=0|pts=384000|pts_time=0.320000|dts=384000|dts_time=0.320000|duration=144000|duration_time=0.120000|size=952|pos=27472|flags=___|data_hash=CRC32:afeae5db -packet|codec_type=video|stream_index=0|pts=528000|pts_time=0.440000|dts=528000|dts_time=0.440000|duration=144000|duration_time=0.120000|size=760|pos=28424|flags=___|data_hash=CRC32:1eacc92c -packet|codec_type=video|stream_index=0|pts=672000|pts_time=0.560000|dts=672000|dts_time=0.560000|duration=48000|duration_time=0.040000|size=2591|pos=29184|flags=___|data_hash=CRC32:17372325 -packet|codec_type=video|stream_index=0|pts=720000|pts_time=0.600000|dts=720000|dts_time=0.600000|duration=48000|duration_time=0.040000|size=1188|pos=31775|flags=___|data_hash=CRC32:e9ce977b -packet|codec_type=video|stream_index=0|pts=768000|pts_time=0.640000|dts=768000|dts_time=0.640000|duration=144000|duration_time=0.120000|size=794|pos=32963|flags=___|data_hash=CRC32:8d140f74 -packet|codec_type=video|stream_index=0|pts=912000|pts_time=0.760000|dts=912000|dts_time=0.760000|duration=144000|duration_time=0.120000|size=746|pos=33757|flags=___|data_hash=CRC32:3b811942 -packet|codec_type=video|stream_index=0|pts=1056000|pts_time=0.880000|dts=1056000|dts_time=0.880000|duration=48000|duration_time=0.040000|size=2603|pos=34503|flags=___|data_hash=CRC32:a486f249 -packet|codec_type=video|stream_index=0|pts=1104000|pts_time=0.920000|dts=1104000|dts_time=0.920000|duration=48000|duration_time=0.040000|size=1005|pos=37106|flags=___|data_hash=CRC32:27839d4c -packet|codec_type=video|stream_index=0|pts=1152000|pts_time=0.960000|dts=1152000|dts_time=0.960000|duration=144000|duration_time=0.120000|size=459|pos=38111|flags=___|data_hash=CRC32:eb775bfc -packet|codec_type=video|stream_index=0|pts=1296000|pts_time=1.080000|dts=1296000|dts_time=1.080000|duration=144000|duration_time=0.120000|size=502|pos=38570|flags=___|data_hash=CRC32:ea021457 -packet|codec_type=video|stream_index=0|pts=1440000|pts_time=1.200000|dts=1440000|dts_time=1.200000|duration=48000|duration_time=0.040000|size=2734|pos=39072|flags=___|data_hash=CRC32:6999b39c -packet|codec_type=video|stream_index=0|pts=1488000|pts_time=1.240000|dts=1488000|dts_time=1.240000|duration=48000|duration_time=0.040000|size=1246|pos=41806|flags=___|data_hash=CRC32:0f9f3622 -packet|codec_type=video|stream_index=0|pts=1536000|pts_time=1.280000|dts=1536000|dts_time=1.280000|duration=144000|duration_time=0.120000|size=572|pos=43052|flags=___|data_hash=CRC32:7d6d8758 -packet|codec_type=video|stream_index=0|pts=1680000|pts_time=1.400000|dts=1680000|dts_time=1.400000|duration=144000|duration_time=0.120000|size=749|pos=43624|flags=___|data_hash=CRC32:69746ad8 -packet|codec_type=video|stream_index=0|pts=1824000|pts_time=1.520000|dts=1824000|dts_time=1.520000|duration=48000|duration_time=0.040000|size=1483|pos=44373|flags=___|data_hash=CRC32:3e9468fc -packet|codec_type=video|stream_index=0|pts=1872000|pts_time=1.560000|dts=1872000|dts_time=1.560000|duration=144000|duration_time=0.120000|size=638|pos=45856|flags=___|data_hash=CRC32:dc0f1d30 -packet|codec_type=video|stream_index=0|pts=2016000|pts_time=1.680000|dts=2016000|dts_time=1.680000|duration=48000|duration_time=0.040000|size=1070|pos=46494|flags=___|data_hash=CRC32:49a62247 -stream|index=0|codec_name=hevc|profile=2|codec_type=video|codec_tag_string=hev1|codec_tag=0x31766568|width=416|height=240|coded_width=416|coded_height=240|closed_captions=0|film_grain=0|has_b_frames=3|sample_aspect_ratio=N/A|display_aspect_ratio=N/A|pix_fmt=yuv420p10le|level=60|color_range=tv|color_space=unknown|color_transfer=unknown|color_primaries=unknown|chroma_location=left|field_order=unknown|refs=1|id=0x1|r_frame_rate=25/1|avg_frame_rate=300/23|time_base=1/1200000|start_pts=0|start_time=0.000000|duration_ts=2064000|duration=1.720000|bit_rate=206608|max_bit_rate=N/A|bits_per_raw_sample=N/A|nb_frames=24|nb_read_frames=N/A|nb_read_packets=24|extradata_size=121|extradata_hash=CRC32:bd471302|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:language=und|tag:handler_name=VideoHandler|tag:vendor_id=[0][0][0][0] -format|filename=cbs-hevc-discard-nonref.mp4|nb_streams=1|nb_programs=0|format_name=mov,mp4,m4a,3gp,3g2,mj2|start_time=0.000000|duration=1.720000|size=48589|bit_rate=225995|probe_score=100|tag:major_brand=isom|tag:minor_version=512|tag:compatible_brands=isomiso2mp41 +2af1c1236ca0034d2a853bc975c20d81 From 8489e317bf293d1fa1f07f39ccdb80987716f819 Mon Sep 17 00:00:00 2001 From: Nuo Mi Date: Sun, 2 Jul 2023 18:15:11 +0800 Subject: [PATCH 1719/2172] cbs_h266: fix sign for pps_xxx_qp_offset_list Signed-off-by: James Almer --- libavcodec/cbs_h266.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/libavcodec/cbs_h266.h b/libavcodec/cbs_h266.h index 9e823919af2..e33d08a0f55 100644 --- a/libavcodec/cbs_h266.h +++ b/libavcodec/cbs_h266.h @@ -520,9 +520,9 @@ typedef struct H266RawPPS { uint8_t pps_slice_chroma_qp_offsets_present_flag; uint8_t pps_cu_chroma_qp_offset_list_enabled_flag; uint8_t pps_chroma_qp_offset_list_len_minus1; - uint8_t pps_cb_qp_offset_list[6]; - uint8_t pps_cr_qp_offset_list[6]; - uint8_t pps_joint_cbcr_qp_offset_list[6]; + int8_t pps_cb_qp_offset_list[6]; + int8_t pps_cr_qp_offset_list[6]; + int8_t pps_joint_cbcr_qp_offset_list[6]; uint8_t pps_deblocking_filter_control_present_flag; uint8_t pps_deblocking_filter_override_enabled_flag; uint8_t pps_deblocking_filter_disabled_flag; From 3720fa5fecc69af5fb22b6341d527788274db091 Mon Sep 17 00:00:00 2001 From: Nuo Mi Date: Sun, 2 Jul 2023 18:15:40 +0800 Subject: [PATCH 1720/2172] cbs_h266: fix typo for ols_mode_idc == 2 Signed-off-by: James Almer --- libavcodec/cbs_h266_syntax_template.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavcodec/cbs_h266_syntax_template.c b/libavcodec/cbs_h266_syntax_template.c index f1cd45f8155..ae44565a54a 100644 --- a/libavcodec/cbs_h266_syntax_template.c +++ b/libavcodec/cbs_h266_syntax_template.c @@ -712,7 +712,7 @@ static int FUNC(vps) (CodedBitstreamContext *ctx, RWContext *rw, } if (ols_mode_idc == 4 || ols_mode_idc == 0 || ols_mode_idc == 1) total_num_olss = current->vps_max_layers_minus1 + 1; - else if (ols_mode_idc = 2) + else if (ols_mode_idc == 2) total_num_olss = current->vps_num_output_layer_sets_minus2 + 2; else av_log(ctx->log_ctx, AV_LOG_ERROR, From 8a6d3482de7994cbdc4ed4ea6160224abd91ee09 Mon Sep 17 00:00:00 2001 From: James Almer Date: Sun, 2 Jul 2023 12:53:23 -0300 Subject: [PATCH 1721/2172] fate/cbs: fix sample path for discard tests Signed-off-by: James Almer --- tests/fate/cbs.mak | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/fate/cbs.mak b/tests/fate/cbs.mak index 6a68fcc5933..4d8742d99cb 100644 --- a/tests/fate/cbs.mak +++ b/tests/fate/cbs.mak @@ -86,7 +86,7 @@ FATE_CBS_DISCARD_TYPES = \ nonintra \ nonkey -$(foreach N,$(FATE_CBS_DISCARD_TYPES),$(eval $(call FATE_CBS_DISCARD_TEST,h264,$(N),$(TARGET_SAMPLES)/h264/interlaced_crop.mp4,h264))) +$(foreach N,$(FATE_CBS_DISCARD_TYPES),$(eval $(call FATE_CBS_DISCARD_TEST,h264,$(N),h264/interlaced_crop.mp4,h264))) FATE_CBS_H264-$(call ALLYES, MOV_DEMUXER, H264_MUXER, H264_PARSER, FILTER_UNITS_BSF) += $(FATE_CBS_h264_DISCARD) @@ -157,7 +157,7 @@ $(foreach N,$(FATE_CBS_HEVC_SAMPLES),$(eval $(call FATE_CBS_TEST,hevc,$(basename FATE_CBS_HEVC-$(call FATE_CBS_DEPS, HEVC, HEVC, HEVC, HEVC, HEVC) = $(FATE_CBS_hevc) -$(foreach N,$(FATE_CBS_DISCARD_TYPES),$(eval $(call FATE_CBS_DISCARD_TEST,hevc,$(N),$(TARGET_SAMPLES)/hevc-conformance/WPP_A_ericsson_MAIN10_2.bit,hevc))) +$(foreach N,$(FATE_CBS_DISCARD_TYPES),$(eval $(call FATE_CBS_DISCARD_TEST,hevc,$(N),hevc-conformance/WPP_A_ericsson_MAIN10_2.bit,hevc))) FATE_CBS_HEVC-$(call ALLYES, HEVC_DEMUXER, HEVC_MUXER, HEVC_PARSER, FILTER_UNITS_BSF) += $(FATE_CBS_hevc_DISCARD) From 5930d397ef1555d8aba2d1e3d1dc694922650101 Mon Sep 17 00:00:00 2001 From: xufuji456 <839789740@qq.com> Date: Wed, 21 Jun 2023 17:38:33 +0800 Subject: [PATCH 1722/2172] lavc/videotoolboxenc: fix enabling low-latency encode Use CFDictionarySetValue to enable low-latency encoding mode. Since the key is a type of "EncoderSpecification", instead of "CompressionProperty". Signed-off-by: xufuji456 <839789740@qq.com> Signed-off-by: Rick Kern --- libavcodec/videotoolboxenc.c | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-) diff --git a/libavcodec/videotoolboxenc.c b/libavcodec/videotoolboxenc.c index a313087876a..61143513926 100644 --- a/libavcodec/videotoolboxenc.c +++ b/libavcodec/videotoolboxenc.c @@ -1536,17 +1536,6 @@ static int vtenc_create_encoder(AVCodecContext *avctx, } } - // low-latency mode: eliminate frame reordering, follow a one-in-one-out encoding mode - if ((avctx->flags & AV_CODEC_FLAG_LOW_DELAY) && avctx->codec_id == AV_CODEC_ID_H264) { - status = VTSessionSetProperty(vtctx->session, - compat_keys.kVTVideoEncoderSpecification_EnableLowLatencyRateControl, - kCFBooleanTrue); - - if (status) { - av_log(avctx, AV_LOG_ERROR, "Error setting low latency property: %d\n", status); - } - } - if ((avctx->flags & AV_CODEC_FLAG_CLOSED_GOP) != 0) { set_encoder_property_or_log(avctx, compat_keys.kVTCompressionPropertyKey_AllowOpenGOP, @@ -1690,6 +1679,13 @@ static int vtenc_configure_encoder(AVCodecContext *avctx) } #endif + // low-latency mode: eliminate frame reordering, follow a one-in-one-out encoding mode + if ((avctx->flags & AV_CODEC_FLAG_LOW_DELAY) && avctx->codec_id == AV_CODEC_ID_H264) { + CFDictionarySetValue(enc_info, + compat_keys.kVTVideoEncoderSpecification_EnableLowLatencyRateControl, + kCFBooleanTrue); + } + if (avctx->pix_fmt != AV_PIX_FMT_VIDEOTOOLBOX) { status = create_cv_pixel_buffer_info(avctx, &pixel_buffer_info); if (status) From e7d800fe89d337a0414d4d3b2de4162d94fe7046 Mon Sep 17 00:00:00 2001 From: Devin Heitmueller Date: Fri, 30 Jun 2023 17:14:38 -0400 Subject: [PATCH 1723/2172] avdevice/decklink: move queue_size to an argument for ff_decklink_packet_queue_init The existing queue initialization function would always sets it's maximum queue size to ctx->queue_size. But because we are introducing more queues we may want the sizes to differ between them. Move the specification of the queue size into an argument, which can be passed from the caller. This patch makes no functional change to the behavior. It is being made to accommodate Marton Balin's request to split out the queue size for the new VANC queue being introduced in a later patch. Signed-off-by: Devin Heitmueller Signed-off-by: Marton Balint --- libavdevice/decklink_common.cpp | 5 ++--- libavdevice/decklink_common.h | 2 +- libavdevice/decklink_dec.cpp | 2 +- 3 files changed, 4 insertions(+), 5 deletions(-) diff --git a/libavdevice/decklink_common.cpp b/libavdevice/decklink_common.cpp index b6cc8d71f16..b3b83f53b88 100644 --- a/libavdevice/decklink_common.cpp +++ b/libavdevice/decklink_common.cpp @@ -390,14 +390,13 @@ int ff_decklink_set_format(AVFormatContext *avctx, decklink_direction_t directio return ff_decklink_set_format(avctx, 0, 0, 0, 0, AV_FIELD_UNKNOWN, direction); } -void ff_decklink_packet_queue_init(AVFormatContext *avctx, DecklinkPacketQueue *q) +void ff_decklink_packet_queue_init(AVFormatContext *avctx, DecklinkPacketQueue *q, int64_t queue_size) { - struct decklink_cctx *ctx = (struct decklink_cctx *)avctx->priv_data; memset(q, 0, sizeof(DecklinkPacketQueue)); pthread_mutex_init(&q->mutex, NULL); pthread_cond_init(&q->cond, NULL); q->avctx = avctx; - q->max_q_size = ctx->queue_size; + q->max_q_size = queue_size; } void ff_decklink_packet_queue_flush(DecklinkPacketQueue *q) diff --git a/libavdevice/decklink_common.h b/libavdevice/decklink_common.h index ebb5b94bed1..53e9983abe0 100644 --- a/libavdevice/decklink_common.h +++ b/libavdevice/decklink_common.h @@ -235,7 +235,7 @@ int ff_decklink_list_formats(AVFormatContext *avctx, decklink_direction_t direct void ff_decklink_cleanup(AVFormatContext *avctx); int ff_decklink_init_device(AVFormatContext *avctx, const char* name); -void ff_decklink_packet_queue_init(AVFormatContext *avctx, DecklinkPacketQueue *q); +void ff_decklink_packet_queue_init(AVFormatContext *avctx, DecklinkPacketQueue *q, int64_t queue_size); void ff_decklink_packet_queue_flush(DecklinkPacketQueue *q); void ff_decklink_packet_queue_end(DecklinkPacketQueue *q); unsigned long long ff_decklink_packet_queue_size(DecklinkPacketQueue *q); diff --git a/libavdevice/decklink_dec.cpp b/libavdevice/decklink_dec.cpp index 66abee12683..11640f72caa 100644 --- a/libavdevice/decklink_dec.cpp +++ b/libavdevice/decklink_dec.cpp @@ -1297,7 +1297,7 @@ av_cold int ff_decklink_read_header(AVFormatContext *avctx) goto error; } - ff_decklink_packet_queue_init(avctx, &ctx->queue); + ff_decklink_packet_queue_init(avctx, &ctx->queue, cctx->queue_size); if (ctx->dli->StartStreams() != S_OK) { av_log(avctx, AV_LOG_ERROR, "Cannot start input stream\n"); From ac4247270c055ecc56e6aca94fbb13a3f8aab3ce Mon Sep 17 00:00:00 2001 From: Devin Heitmueller Date: Fri, 30 Jun 2023 17:14:39 -0400 Subject: [PATCH 1724/2172] avdevice/decklink_enc: add support for SMPTE 2038 VANC packet output Support decoding and embedding VANC packets delivered via SMPTE 2038 into the SDI output. We leverage an intermediate queue because data packets are announced separately from video but we need to embed the data into the video frame when it is output. Note that this patch has some additional abstraction for data streams in general as opposed to just SMPTE 2038 packets. This is because subsequent patches will introduce support for other data codecs. Thanks to Marton Balint for review/feedback. Signed-off-by: Devin Heitmueller Signed-off-by: Marton Balint --- doc/outdevs.texi | 5 ++ libavdevice/decklink_common.cpp | 16 ++++++ libavdevice/decklink_common.h | 4 ++ libavdevice/decklink_common_c.h | 1 + libavdevice/decklink_enc.cpp | 94 ++++++++++++++++++++++++++++++++- libavdevice/decklink_enc_c.c | 1 + libavdevice/version.h | 2 +- 7 files changed, 121 insertions(+), 2 deletions(-) diff --git a/doc/outdevs.texi b/doc/outdevs.texi index 93391dbed75..f0484bbf8fb 100644 --- a/doc/outdevs.texi +++ b/doc/outdevs.texi @@ -235,6 +235,11 @@ Enable SMPTE Level A mode on the used output. Must be @samp{unset}, @samp{true} or @samp{false}. Defaults to @option{unset}. +@item vanc_queue_size +Sets maximum output buffer size in bytes for VANC data. If the buffering reaches this value, +outgoing VANC data will be dropped. +Defaults to @samp{1048576}. + @end table @subsection Examples diff --git a/libavdevice/decklink_common.cpp b/libavdevice/decklink_common.cpp index b3b83f53b88..47de7ef6b0f 100644 --- a/libavdevice/decklink_common.cpp +++ b/libavdevice/decklink_common.cpp @@ -484,6 +484,22 @@ int ff_decklink_packet_queue_get(DecklinkPacketQueue *q, AVPacket *pkt, int bloc return ret; } +int64_t ff_decklink_packet_queue_peekpts(DecklinkPacketQueue *q) +{ + PacketListEntry *pkt1; + int64_t pts = -1; + + pthread_mutex_lock(&q->mutex); + pkt1 = q->pkt_list.head; + if (pkt1) { + pts = pkt1->pkt.pts; + } + pthread_mutex_unlock(&q->mutex); + + return pts; +} + + int ff_decklink_list_devices(AVFormatContext *avctx, struct AVDeviceInfoList *device_list, int show_inputs, int show_outputs) diff --git a/libavdevice/decklink_common.h b/libavdevice/decklink_common.h index 53e9983abe0..34ab1b96700 100644 --- a/libavdevice/decklink_common.h +++ b/libavdevice/decklink_common.h @@ -115,6 +115,9 @@ struct decklink_ctx { CCFifo cc_fifo; ///< closed captions + /* Output VANC queue */ + DecklinkPacketQueue vanc_queue; + /* Streams present */ int audio; int video; @@ -241,5 +244,6 @@ void ff_decklink_packet_queue_end(DecklinkPacketQueue *q); unsigned long long ff_decklink_packet_queue_size(DecklinkPacketQueue *q); int ff_decklink_packet_queue_put(DecklinkPacketQueue *q, AVPacket *pkt); int ff_decklink_packet_queue_get(DecklinkPacketQueue *q, AVPacket *pkt, int block); +int64_t ff_decklink_packet_queue_peekpts(DecklinkPacketQueue *q); #endif /* AVDEVICE_DECKLINK_COMMON_H */ diff --git a/libavdevice/decklink_common_c.h b/libavdevice/decklink_common_c.h index 75896ad32b2..9c55d891494 100644 --- a/libavdevice/decklink_common_c.h +++ b/libavdevice/decklink_common_c.h @@ -63,6 +63,7 @@ struct decklink_cctx { char *format_code; int raw_format; int64_t queue_size; + int64_t vanc_queue_size; int copyts; int64_t timestamp_align; int timing_offset; diff --git a/libavdevice/decklink_enc.cpp b/libavdevice/decklink_enc.cpp index 6906cb0882c..1809f79cacd 100644 --- a/libavdevice/decklink_enc.cpp +++ b/libavdevice/decklink_enc.cpp @@ -345,6 +345,25 @@ static int decklink_setup_subtitle(AVFormatContext *avctx, AVStream *st) return ret; } +static int decklink_setup_data(AVFormatContext *avctx, AVStream *st) +{ + int ret = -1; + + switch(st->codecpar->codec_id) { +#if CONFIG_LIBKLVANC + case AV_CODEC_ID_SMPTE_2038: + /* No specific setup required */ + ret = 0; + break; +#endif + default: + av_log(avctx, AV_LOG_ERROR, "Unsupported data codec specified\n"); + break; + } + + return ret; +} + av_cold int ff_decklink_write_trailer(AVFormatContext *avctx) { struct decklink_cctx *cctx = (struct decklink_cctx *)avctx->priv_data; @@ -370,6 +389,7 @@ av_cold int ff_decklink_write_trailer(AVFormatContext *avctx) #if CONFIG_LIBKLVANC klvanc_context_destroy(ctx->vanc_ctx); #endif + ff_decklink_packet_queue_end(&ctx->vanc_queue); ff_ccfifo_uninit(&ctx->cc_fifo); av_freep(&cctx->ctx); @@ -552,6 +572,58 @@ static int decklink_construct_vanc(AVFormatContext *avctx, struct decklink_ctx * construct_cc(avctx, ctx, pkt, &vanc_lines); construct_afd(avctx, ctx, pkt, &vanc_lines, st); + /* See if there any pending data packets to process */ + while (ff_decklink_packet_queue_size(&ctx->vanc_queue) > 0) { + AVStream *vanc_st; + AVPacket vanc_pkt; + int64_t pts; + + pts = ff_decklink_packet_queue_peekpts(&ctx->vanc_queue); + if (pts > ctx->last_pts) { + /* We haven't gotten to the video frame we are supposed to inject + the oldest VANC packet into yet, so leave it on the queue... */ + break; + } + + ret = ff_decklink_packet_queue_get(&ctx->vanc_queue, &vanc_pkt, 1); + if (vanc_pkt.pts + 1 < ctx->last_pts) { + av_log(avctx, AV_LOG_WARNING, "VANC packet too old, throwing away\n"); + av_packet_unref(&vanc_pkt); + continue; + } + + vanc_st = avctx->streams[vanc_pkt.stream_index]; + if (vanc_st->codecpar->codec_id == AV_CODEC_ID_SMPTE_2038) { + struct klvanc_smpte2038_anc_data_packet_s *pkt_2038 = NULL; + + klvanc_smpte2038_parse_pes_payload(vanc_pkt.data, vanc_pkt.size, &pkt_2038); + if (pkt_2038 == NULL) { + av_log(avctx, AV_LOG_ERROR, "failed to decode SMPTE 2038 PES packet"); + av_packet_unref(&vanc_pkt); + continue; + } + for (int i = 0; i < pkt_2038->lineCount; i++) { + struct klvanc_smpte2038_anc_data_line_s *l = &pkt_2038->lines[i]; + uint16_t *vancWords = NULL; + uint16_t vancWordCount; + + if (klvanc_smpte2038_convert_line_to_words(l, &vancWords, + &vancWordCount) < 0) + break; + + ret = klvanc_line_insert(ctx->vanc_ctx, &vanc_lines, vancWords, + vancWordCount, l->line_number, 0); + free(vancWords); + if (ret != 0) { + av_log(avctx, AV_LOG_ERROR, "VANC line insertion failed\n"); + break; + } + } + klvanc_smpte2038_anc_data_packet_free(pkt_2038); + } + av_packet_unref(&vanc_pkt); + } + IDeckLinkVideoFrameAncillary *vanc; int result = ctx->dlo->CreateAncillaryData(bmdFormat10BitYUV, &vanc); if (result != S_OK) { @@ -750,6 +822,18 @@ static int decklink_write_subtitle_packet(AVFormatContext *avctx, AVPacket *pkt) return 0; } +static int decklink_write_data_packet(AVFormatContext *avctx, AVPacket *pkt) +{ + struct decklink_cctx *cctx = (struct decklink_cctx *)avctx->priv_data; + struct decklink_ctx *ctx = (struct decklink_ctx *)cctx->ctx; + + if (ff_decklink_packet_queue_put(&ctx->vanc_queue, pkt) < 0) { + av_log(avctx, AV_LOG_WARNING, "Failed to queue DATA packet\n"); + } + + return 0; +} + extern "C" { av_cold int ff_decklink_write_header(AVFormatContext *avctx) @@ -814,6 +898,9 @@ av_cold int ff_decklink_write_header(AVFormatContext *avctx) } else if (c->codec_type == AVMEDIA_TYPE_VIDEO) { if (decklink_setup_video(avctx, st)) goto error; + } else if (c->codec_type == AVMEDIA_TYPE_DATA) { + if (decklink_setup_data(avctx, st)) + goto error; } else if (c->codec_type == AVMEDIA_TYPE_SUBTITLE) { if (decklink_setup_subtitle(avctx, st)) goto error; @@ -823,13 +910,16 @@ av_cold int ff_decklink_write_header(AVFormatContext *avctx) } } + /* Reconfigure the data/subtitle stream clocks to match the video */ for (n = 0; n < avctx->nb_streams; n++) { AVStream *st = avctx->streams[n]; AVCodecParameters *c = st->codecpar; - if(c->codec_type == AVMEDIA_TYPE_SUBTITLE) + if(c->codec_type == AVMEDIA_TYPE_DATA || + c->codec_type == AVMEDIA_TYPE_SUBTITLE) avpriv_set_pts_info(st, 64, ctx->bmd_tb_num, ctx->bmd_tb_den); } + ff_decklink_packet_queue_init(avctx, &ctx->vanc_queue, cctx->vanc_queue_size); ret = ff_ccfifo_init(&ctx->cc_fifo, av_make_q(ctx->bmd_tb_den, ctx->bmd_tb_num), avctx); if (ret < 0) { @@ -852,6 +942,8 @@ int ff_decklink_write_packet(AVFormatContext *avctx, AVPacket *pkt) return decklink_write_video_packet(avctx, pkt); else if (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) return decklink_write_audio_packet(avctx, pkt); + else if (st->codecpar->codec_type == AVMEDIA_TYPE_DATA) + return decklink_write_data_packet(avctx, pkt); else if (st->codecpar->codec_type == AVMEDIA_TYPE_SUBTITLE) return decklink_write_subtitle_packet(avctx, pkt); diff --git a/libavdevice/decklink_enc_c.c b/libavdevice/decklink_enc_c.c index 0a3984b9e23..25ffe777840 100644 --- a/libavdevice/decklink_enc_c.c +++ b/libavdevice/decklink_enc_c.c @@ -32,6 +32,7 @@ static const AVOption options[] = { { "list_devices", "use ffmpeg -sinks decklink instead", OFFSET(list_devices), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, ENC | AV_OPT_FLAG_DEPRECATED}, { "list_formats", "list supported formats" , OFFSET(list_formats), AV_OPT_TYPE_INT , { .i64 = 0 }, 0, 1, ENC }, { "preroll" , "video preroll in seconds", OFFSET(preroll ), AV_OPT_TYPE_DOUBLE, { .dbl = 0.5 }, 0, 5, ENC }, + { "vanc_queue_size", "VANC queue buffer size", OFFSET(vanc_queue_size), AV_OPT_TYPE_INT64, { .i64 = (1024 * 1024)}, 0, INT64_MAX, ENC }, #if BLACKMAGIC_DECKLINK_API_VERSION >= 0x0b000000 { "duplex_mode" , "duplex mode" , OFFSET(duplex_mode ), AV_OPT_TYPE_INT , { .i64 = 0 }, 0, 5, ENC, "duplex_mode"}, #else diff --git a/libavdevice/version.h b/libavdevice/version.h index 5cd01a1672c..0796e41221e 100644 --- a/libavdevice/version.h +++ b/libavdevice/version.h @@ -30,7 +30,7 @@ #include "version_major.h" #define LIBAVDEVICE_VERSION_MINOR 2 -#define LIBAVDEVICE_VERSION_MICRO 100 +#define LIBAVDEVICE_VERSION_MICRO 101 #define LIBAVDEVICE_VERSION_INT AV_VERSION_INT(LIBAVDEVICE_VERSION_MAJOR, \ LIBAVDEVICE_VERSION_MINOR, \ From 695789eacc19332d066e2184e340bad3d321a4c8 Mon Sep 17 00:00:00 2001 From: Devin Heitmueller Date: Fri, 30 Jun 2023 17:38:49 -0400 Subject: [PATCH 1725/2172] avcodec/decode: Preserve AFD side data when going from AVPacket to AVFrame This is needed to ensure that AFD data continues to work when capturing V210 video with the Decklink libavdevice input. Signed-off-by: Devin Heitmueller Signed-off-by: Marton Balint --- libavcodec/decode.c | 1 + 1 file changed, 1 insertion(+) diff --git a/libavcodec/decode.c b/libavcodec/decode.c index a7c130207c1..6ee2c85a750 100644 --- a/libavcodec/decode.c +++ b/libavcodec/decode.c @@ -1331,6 +1331,7 @@ int ff_decode_frame_props_from_pkt(const AVCodecContext *avctx, { AV_PKT_DATA_MASTERING_DISPLAY_METADATA, AV_FRAME_DATA_MASTERING_DISPLAY_METADATA }, { AV_PKT_DATA_CONTENT_LIGHT_LEVEL, AV_FRAME_DATA_CONTENT_LIGHT_LEVEL }, { AV_PKT_DATA_A53_CC, AV_FRAME_DATA_A53_CC }, + { AV_PKT_DATA_AFD, AV_FRAME_DATA_AFD }, { AV_PKT_DATA_ICC_PROFILE, AV_FRAME_DATA_ICC_PROFILE }, { AV_PKT_DATA_S12M_TIMECODE, AV_FRAME_DATA_S12M_TIMECODE }, { AV_PKT_DATA_DYNAMIC_HDR10_PLUS, AV_FRAME_DATA_DYNAMIC_HDR_PLUS }, From 25a91824af5d3699a5af49f80a4fce3c053031f7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomas=20H=C3=A4rdin?= Date: Sun, 2 Jul 2023 16:58:11 +0200 Subject: [PATCH 1726/2172] Add SMC vsynth tests --- tests/fate/vcodec.mak | 4 ++++ tests/ref/vsynth/vsynth1-smc | 4 ++++ tests/ref/vsynth/vsynth2-smc | 4 ++++ tests/ref/vsynth/vsynth3-smc | 4 ++++ tests/ref/vsynth/vsynth_lena-smc | 4 ++++ 5 files changed, 20 insertions(+) create mode 100644 tests/ref/vsynth/vsynth1-smc create mode 100644 tests/ref/vsynth/vsynth2-smc create mode 100644 tests/ref/vsynth/vsynth3-smc create mode 100644 tests/ref/vsynth/vsynth_lena-smc diff --git a/tests/fate/vcodec.mak b/tests/fate/vcodec.mak index ef8904613aa..2839e54de84 100644 --- a/tests/fate/vcodec.mak +++ b/tests/fate/vcodec.mak @@ -404,6 +404,10 @@ FATE_VCODEC-$(call ENCDEC, RV20, RM) += rv20 fate-vsynth%-rv20: ENCOPTS = -qscale 10 fate-vsynth%-rv20: FMT = rm +FATE_VCODEC_SCALE-$(call ENCDEC, SMC, MOV) += smc +fate-vsynth%-smc: CODEC = smc +fate-vsynth%-smc: FMT = mov + FATE_VCODEC_SCALE-$(call ENCDEC, SNOW, AVI) += snow snow-hpel fate-vsynth%-snow: ENCOPTS = -qscale 2 -flags +qpel \ -motion_est iter -dia_size 2 \ diff --git a/tests/ref/vsynth/vsynth1-smc b/tests/ref/vsynth/vsynth1-smc new file mode 100644 index 00000000000..09f4bd4ce13 --- /dev/null +++ b/tests/ref/vsynth/vsynth1-smc @@ -0,0 +1,4 @@ +b92226742d745515732a5e7b8a03e7b7 *tests/data/fate/vsynth1-smc.mov +4613320 tests/data/fate/vsynth1-smc.mov +f142ee03bf9f37bb2e1902fe32366bbf *tests/data/fate/vsynth1-smc.out.rawvideo +stddev: 8.69 PSNR: 29.34 MAXDIFF: 64 bytes: 7603200/ 7603200 diff --git a/tests/ref/vsynth/vsynth2-smc b/tests/ref/vsynth/vsynth2-smc new file mode 100644 index 00000000000..3ce6478e564 --- /dev/null +++ b/tests/ref/vsynth/vsynth2-smc @@ -0,0 +1,4 @@ +6e97e428fb20e96a5b8fc8a21f427504 *tests/data/fate/vsynth2-smc.mov +3475261 tests/data/fate/vsynth2-smc.mov +df26a524cad8ebf0cf5ba4376c5f115f *tests/data/fate/vsynth2-smc.out.rawvideo +stddev: 7.57 PSNR: 30.54 MAXDIFF: 35 bytes: 7603200/ 7603200 diff --git a/tests/ref/vsynth/vsynth3-smc b/tests/ref/vsynth/vsynth3-smc new file mode 100644 index 00000000000..ed9efd92e20 --- /dev/null +++ b/tests/ref/vsynth/vsynth3-smc @@ -0,0 +1,4 @@ +e4eb9909095e02577b59004e209ad8ec *tests/data/fate/vsynth3-smc.mov +65521 tests/data/fate/vsynth3-smc.mov +fa6042492a3116c1ae9a32b487caa677 *tests/data/fate/vsynth3-smc.out.rawvideo +stddev: 8.88 PSNR: 29.16 MAXDIFF: 51 bytes: 86700/ 86700 diff --git a/tests/ref/vsynth/vsynth_lena-smc b/tests/ref/vsynth/vsynth_lena-smc new file mode 100644 index 00000000000..2f9f5c1e87d --- /dev/null +++ b/tests/ref/vsynth/vsynth_lena-smc @@ -0,0 +1,4 @@ +037fa90a1ac659ff4dca22fb375dc7e1 *tests/data/fate/vsynth_lena-smc.mov +3502732 tests/data/fate/vsynth_lena-smc.mov +db453693ceae6f65c173dd716ee2662e *tests/data/fate/vsynth_lena-smc.out.rawvideo +stddev: 8.07 PSNR: 29.99 MAXDIFF: 32 bytes: 7603200/ 7603200 From 50f34172e0cca2cabc5836308ec66dbf93f5f2a3 Mon Sep 17 00:00:00 2001 From: James Almer Date: Thu, 29 Jun 2023 18:47:53 -0300 Subject: [PATCH 1727/2172] fftools/ffplay: remove usage of internal AVInputFormat.read_seek field It's an internal field, so it should not be touched. Reviewed-by: Marton Balint Signed-off-by: James Almer --- fftools/ffplay.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fftools/ffplay.c b/fftools/ffplay.c index 15fd6449740..663f61d8b2e 100644 --- a/fftools/ffplay.c +++ b/fftools/ffplay.c @@ -2639,7 +2639,7 @@ static int stream_component_open(VideoState *is, int stream_index) if ((ret = decoder_init(&is->auddec, avctx, &is->audioq, is->continue_read_thread)) < 0) goto fail; - if ((is->ic->iformat->flags & (AVFMT_NOBINSEARCH | AVFMT_NOGENSEARCH | AVFMT_NO_BYTE_SEEK)) && !is->ic->iformat->read_seek) { + if (is->ic->iformat->flags & AVFMT_NOTIMESTAMPS) { is->auddec.start_pts = is->audio_st->start_time; is->auddec.start_pts_tb = is->audio_st->time_base; } From 372f71cdc76c1e265d5be02de1f7e9f131912e9f Mon Sep 17 00:00:00 2001 From: Zhao Zhili Date: Tue, 13 Jun 2023 15:37:15 +0800 Subject: [PATCH 1728/2172] avcodec/hevc_parse: restrict configurationVersion to 0 and 1 The standard only defined configurationVersion 1. configurationVersion 0 is for backward compatibility predates the standard. This patch reduces the chance that some malformated streams being detected as hvcC. Signed-off-by: Zhao Zhili --- libavcodec/hevc_parse.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/libavcodec/hevc_parse.c b/libavcodec/hevc_parse.c index 29dfd479f38..1f3beed183e 100644 --- a/libavcodec/hevc_parse.c +++ b/libavcodec/hevc_parse.c @@ -86,11 +86,11 @@ int ff_hevc_decode_extradata(const uint8_t *data, int size, HEVCParamSets *ps, bytestream2_init(&gb, data, size); - if (size > 3 && (data[0] || data[1] || data[2] > 1)) { - /* It seems the extradata is encoded as hvcC format. - * Temporarily, we support configurationVersion==0 until 14496-15 3rd - * is finalized. When finalized, configurationVersion will be 1 and we - * can recognize hvcC by checking if avctx->extradata[0]==1 or not. */ + /* data[0] == 1 is configurationVersion from 14496-15. + * data[0] == 0 is for backward compatibility predates the standard. + */ + if (size > 3 && ((data[0] == 1) || (data[0] == 0 && (data[1] || data[2] > 1)))) { + /* It seems the extradata is encoded as hvcC format. */ int i, j, num_arrays, nal_len_size; *is_nalff = 1; From bdb4b64f16b75c4d4cd88c0755aa6111cadaa602 Mon Sep 17 00:00:00 2001 From: Zhao Zhili Date: Tue, 13 Jun 2023 15:37:16 +0800 Subject: [PATCH 1729/2172] avcodec/hevc_parse: check the size of hvcC is at least 23 The code after the check skip 21 bytes and then read two bytes. Signed-off-by: Zhao Zhili --- libavcodec/hevc_parse.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/libavcodec/hevc_parse.c b/libavcodec/hevc_parse.c index 1f3beed183e..7bc28fd081c 100644 --- a/libavcodec/hevc_parse.c +++ b/libavcodec/hevc_parse.c @@ -88,8 +88,10 @@ int ff_hevc_decode_extradata(const uint8_t *data, int size, HEVCParamSets *ps, /* data[0] == 1 is configurationVersion from 14496-15. * data[0] == 0 is for backward compatibility predates the standard. + * + * Minimum number of bytes of hvcC with 0 numOfArrays is 23. */ - if (size > 3 && ((data[0] == 1) || (data[0] == 0 && (data[1] || data[2] > 1)))) { + if (size >= 23 && ((data[0] == 1) || (data[0] == 0 && (data[1] || data[2] > 1)))) { /* It seems the extradata is encoded as hvcC format. */ int i, j, num_arrays, nal_len_size; From 3eb7968ed98229e3b44a91b89c7cd5512643b182 Mon Sep 17 00:00:00 2001 From: Zhao Zhili Date: Tue, 13 Jun 2023 15:37:17 +0800 Subject: [PATCH 1730/2172] avformat/asfdec_f: support bmp_tags_unofficial Signed-off-by: Zhao Zhili --- libavformat/asfdec_f.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/libavformat/asfdec_f.c b/libavformat/asfdec_f.c index bdbd4271c8c..1e3eb33fd6c 100644 --- a/libavformat/asfdec_f.c +++ b/libavformat/asfdec_f.c @@ -445,6 +445,8 @@ static int asf_read_stream_properties(AVFormatContext *s, int64_t size) st->codecpar->codec_tag = tag1; st->codecpar->codec_id = ff_codec_get_id(ff_codec_bmp_tags, tag1); + if (!st->codecpar->codec_id) + st->codecpar->codec_id = ff_codec_get_id(ff_codec_bmp_tags_unofficial, tag1); if (tag1 == MKTAG('D', 'V', 'R', ' ')) { sti->need_parsing = AVSTREAM_PARSE_FULL; /* issue658 contains wrong w/h and MS even puts a fake seq header @@ -459,6 +461,8 @@ static int asf_read_stream_properties(AVFormatContext *s, int64_t size) sti->need_parsing = AVSTREAM_PARSE_FULL_ONCE; if (st->codecpar->codec_id == AV_CODEC_ID_MPEG4) sti->need_parsing = AVSTREAM_PARSE_FULL_ONCE; + if (st->codecpar->codec_id == AV_CODEC_ID_HEVC) + sti->need_parsing = AVSTREAM_PARSE_FULL; } pos2 = avio_tell(pb); avio_skip(pb, size - (pos2 - pos1 + 24)); From d4b989c94d7ec2693bd52b286099f02d99e2bc4f Mon Sep 17 00:00:00 2001 From: Zhao Zhili Date: Tue, 13 Jun 2023 15:37:18 +0800 Subject: [PATCH 1731/2172] avformat/asfdec_f: fix need_parsing flag for codec mpeg4 AVSTREAM_PARSE_FULL_ONCE is only implemented for H.264. Signed-off-by: Zhao Zhili --- libavformat/asfdec_f.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavformat/asfdec_f.c b/libavformat/asfdec_f.c index 1e3eb33fd6c..54059564670 100644 --- a/libavformat/asfdec_f.c +++ b/libavformat/asfdec_f.c @@ -460,7 +460,7 @@ static int asf_read_stream_properties(AVFormatContext *s, int64_t size) if (st->codecpar->codec_id == AV_CODEC_ID_H264) sti->need_parsing = AVSTREAM_PARSE_FULL_ONCE; if (st->codecpar->codec_id == AV_CODEC_ID_MPEG4) - sti->need_parsing = AVSTREAM_PARSE_FULL_ONCE; + sti->need_parsing = AVSTREAM_PARSE_FULL; if (st->codecpar->codec_id == AV_CODEC_ID_HEVC) sti->need_parsing = AVSTREAM_PARSE_FULL; } From 9ff834c2a0dbbe5544ec09b56d077a3b21f728c0 Mon Sep 17 00:00:00 2001 From: Lynne Date: Tue, 4 Jul 2023 00:48:09 +0200 Subject: [PATCH 1732/2172] bwdif_vulkan: clamp the temporarily interpolated sample spatially This makes the filter output match that of the C version. It was left intentionally while we figured out if it was better or not, and while it makes certain samples better, it makes static samples jump around slightly. --- libavfilter/vf_bwdif_vulkan.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/libavfilter/vf_bwdif_vulkan.c b/libavfilter/vf_bwdif_vulkan.c index 1fc74d15442..db916b22cd0 100644 --- a/libavfilter/vf_bwdif_vulkan.c +++ b/libavfilter/vf_bwdif_vulkan.c @@ -86,8 +86,7 @@ static const char filter_fn[] = { C(0, ) C(1, bvec4 interpolate_cnd1 = greaterThan(abs(fc - fe), temp_diff[0]); ) C(1, vec4 interpol = mix(interpolate_cur, interpolate_all, interpolate_cnd1); ) - /* Cliping interpol between [fd - diff, fd + diff] is intentionally left out. - * Removing the clipping increases quality. TODO: research and fix the C version to match this. */ + C(1, interpol = clamp(interpol, fd - diff, fd + diff); ) C(1, return mix(interpol, fd, diff_mask); ) C(0, } ) }; From 8622dcb39b6554dfcb54c2c95c8dcca96b46d60b Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Wed, 5 Jul 2023 01:11:22 +0200 Subject: [PATCH 1733/2172] avfilter/adynamicequalizer_template: refactor and improve output --- libavfilter/adynamicequalizer_template.c | 46 ++++++++++-------------- libavfilter/af_adynamicequalizer.c | 12 +------ 2 files changed, 20 insertions(+), 38 deletions(-) diff --git a/libavfilter/adynamicequalizer_template.c b/libavfilter/adynamicequalizer_template.c index a6b35aa93e3..4f7d58c9396 100644 --- a/libavfilter/adynamicequalizer_template.c +++ b/libavfilter/adynamicequalizer_template.c @@ -167,13 +167,16 @@ static int fn(filter_channels)(AVFilterContext *ctx, void *arg, int jobnr, int n ftype *dst = (ftype *)out->extended_data[ch]; ftype *state = (ftype *)s->state->extended_data[ch]; const ftype threshold = detection == 0 ? state[5] : s->threshold; + ftype fa[3], fm[3]; if (detection < 0) state[5] = threshold; + memcpy(fa, state + 8, sizeof(fa)); + memcpy(fm, state + 11, sizeof(fm)); + for (int n = 0; n < out->nb_samples; n++) { ftype detect, gain, v, listen; - ftype fa[3], fm[3]; ftype k, g; detect = listen = fn(get_svf)(src[n], dm, da, state); @@ -182,46 +185,32 @@ static int fn(filter_channels)(AVFilterContext *ctx, void *arg, int jobnr, int n if (detection > 0) state[5] = FMAX(state[5], detect); - if (direction == 0) { - if (detect < threshold) { - if (mode == 0) - detect = ONE / CLIP(ONE + makeup + (threshold - detect) * ratio, ONE, range); - else - detect = CLIP(ONE + makeup + (threshold - detect) * ratio, ONE, range); + if (mode >= 0) { + if (direction == 0 && detect < threshold) { + detect = CLIP(ONE + makeup + (threshold - detect) * ratio, ONE, range); + if (!mode) + detect = ONE / detect; + } else if (direction == 1 && detect > threshold) { + detect = CLIP(ONE + makeup + (detect - threshold) * ratio, ONE, range); + if (!mode) + detect = ONE / detect; } else { detect = ONE; } - } else { - if (detect > threshold) { - if (mode == 0) - detect = ONE / CLIP(ONE + makeup + (detect - threshold) * ratio, ONE, range); - else - detect = CLIP(ONE + makeup + (detect - threshold) * ratio, ONE, range); - } else { - detect = ONE; - } - } - if (direction == 0) { - if (detect > state[4]) { - detect = iattack * detect + attack * state[4]; - } else { - detect = irelease * detect + release * state[4]; - } - } else { - if (detect < state[4]) { + if ((direction == 0 && detect > state[4]) || (direction == 1 && detect < state[4])) { detect = iattack * detect + attack * state[4]; } else { detect = irelease * detect + release * state[4]; } } - if (state[4] != detect || n == 0) { + if (state[4] != detect) { state[4] = gain = detect; switch (tftype) { case 0: - k = ONE / (tqfactor * gain); + k = itqfactor / gain; fa[0] = ONE / (ONE + fg * (fg + k)); fa[1] = fg * fa[0]; @@ -262,6 +251,9 @@ static int fn(filter_channels)(AVFilterContext *ctx, void *arg, int jobnr, int n v = mode == -1 ? listen : v; dst[n] = ctx->is_disabled ? src[n] : v; } + + memcpy(state + 8, fa, sizeof(fa)); + memcpy(state + 11, fm, sizeof(fm)); } return 0; diff --git a/libavfilter/af_adynamicequalizer.c b/libavfilter/af_adynamicequalizer.c index a3aeee91c5a..5a2c8efb2ac 100644 --- a/libavfilter/af_adynamicequalizer.c +++ b/libavfilter/af_adynamicequalizer.c @@ -96,26 +96,16 @@ static int config_input(AVFilterLink *inlink) AudioDynamicEqualizerContext *s = ctx->priv; s->format = inlink->format; - s->state = ff_get_audio_buffer(inlink, 8); + s->state = ff_get_audio_buffer(inlink, 16); if (!s->state) return AVERROR(ENOMEM); switch (s->format) { case AV_SAMPLE_FMT_DBLP: - for (int ch = 0; ch < inlink->ch_layout.nb_channels; ch++) { - double *state = (double *)s->state->extended_data[ch]; - - state[4] = 1.; - } s->filter_prepare = filter_prepare_double; s->filter_channels = filter_channels_double; break; case AV_SAMPLE_FMT_FLTP: - for (int ch = 0; ch < inlink->ch_layout.nb_channels; ch++) { - float *state = (float *)s->state->extended_data[ch]; - - state[4] = 1.; - } s->filter_prepare = filter_prepare_float; s->filter_channels = filter_channels_float; break; From ca939ebb4faf6aac343c22702e2f28e3eeed1ba1 Mon Sep 17 00:00:00 2001 From: Haihao Xiang Date: Fri, 30 Jun 2023 19:51:32 +0800 Subject: [PATCH 1734/2172] lavfi/tonemap_vaapi: remove HDR metadata The HDR metadata should be removed after HDR to SDR conversion, otherwise the output frame still has HDR side data. Signed-off-by: Haihao Xiang --- libavfilter/vf_tonemap_vaapi.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/libavfilter/vf_tonemap_vaapi.c b/libavfilter/vf_tonemap_vaapi.c index cd2f4c21950..52303a8b869 100644 --- a/libavfilter/vf_tonemap_vaapi.c +++ b/libavfilter/vf_tonemap_vaapi.c @@ -309,6 +309,9 @@ static int tonemap_vaapi_filter_frame(AVFilterLink *inlink, AVFrame *input_frame av_get_pix_fmt_name(output_frame->format), output_frame->width, output_frame->height, output_frame->pts); + av_frame_remove_side_data(output_frame, AV_FRAME_DATA_CONTENT_LIGHT_LEVEL); + av_frame_remove_side_data(output_frame, AV_FRAME_DATA_MASTERING_DISPLAY_METADATA); + return ff_filter_frame(outlink, output_frame); fail: From a8178be3b3f6666aa3501dc146661c120cbe7dfe Mon Sep 17 00:00:00 2001 From: Frank Plowman Date: Wed, 5 Jul 2023 19:40:27 +0800 Subject: [PATCH 1735/2172] cbs_h266: expand the bit depth range to 16 bits Signed-off-by: James Almer --- libavcodec/cbs_h266_syntax_template.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libavcodec/cbs_h266_syntax_template.c b/libavcodec/cbs_h266_syntax_template.c index ae44565a54a..485c02f5907 100644 --- a/libavcodec/cbs_h266_syntax_template.c +++ b/libavcodec/cbs_h266_syntax_template.c @@ -902,7 +902,7 @@ static int FUNC(vps) (CodedBitstreamContext *ctx, RWContext *rw, ues(vps_ols_dpb_pic_width[i], 0, UINT16_MAX, 1, i); ues(vps_ols_dpb_pic_height[i], 0, UINT16_MAX, 1, i); ubs(2, vps_ols_dpb_chroma_format[i], 1, i); - ues(vps_ols_dpb_bitdepth_minus8[i], 0, 2, 1, i); + ues(vps_ols_dpb_bitdepth_minus8[i], 0, 8, 1, i); if (vps_num_dpb_params > 1 && vps_num_dpb_params != num_multi_layer_olss) ues(vps_ols_dpb_params_idx[i], 0, vps_num_dpb_params - 1, 1, i); @@ -1158,7 +1158,7 @@ static int FUNC(sps)(CodedBitstreamContext *ctx, RWContext *rw, } - ue(sps_bitdepth_minus8, 0, 2); + ue(sps_bitdepth_minus8, 0, 8); qp_bd_offset = 6 * current->sps_bitdepth_minus8; flag(sps_entropy_coding_sync_enabled_flag); From a357758ec59ad0c211ace22abd372a715ca41bb2 Mon Sep 17 00:00:00 2001 From: Nuo Mi Date: Wed, 5 Jul 2023 19:40:28 +0800 Subject: [PATCH 1736/2172] vvc.h: Enable 16-bit support for VVC_MAX_POINTS_IN_QP_TABLE Signed-off-by: James Almer --- libavcodec/vvc.h | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/libavcodec/vvc.h b/libavcodec/vvc.h index 099d2fc2adb..7cf26d5e8cc 100644 --- a/libavcodec/vvc.h +++ b/libavcodec/vvc.h @@ -102,9 +102,10 @@ enum { VVC_MAX_REF_ENTRIES = VVC_MAX_DPB_SIZE + 13, //7.4.3.3 sps_num_points_in_qp_table_minus1[i] in range [0, 36 − sps_qp_table_start_minus26[i]], - //sps_qp_table_start_minus26[i] in range [sps_qp_table_start_minus26[i] −26 − QpBdOffset, 36] - //for 10 bitsQpBdOffset is 12, so sps_num_points_in_qp_table_minus1[i] in range [0, 74] - VVC_MAX_POINTS_IN_QP_TABLE = 75, + //and sps_qp_table_start_minus26[i] in range [−26 − QpBdOffset, 36]. + //so sps_num_points_in_qp_table_minus1[i] should in range [0, 62 + QpBdOffset] + //since 16 bits QpBdOffset is 48, sps_num_points_in_qp_table_minus1[i] should range [0, 110] + VVC_MAX_POINTS_IN_QP_TABLE = 111, // 7.4.6.1: hrd_cpb_cnt_minus1 is in [0, 31]. VVC_MAX_CPB_CNT = 32, From 7a1128ca07fa38836775168d002ff6bc55134023 Mon Sep 17 00:00:00 2001 From: James Almer Date: Tue, 4 Jul 2023 19:37:04 -0300 Subject: [PATCH 1737/2172] avutil/random_seed: use fread() in read_random() This ensures the requested amount of bytes is read. Also remove /dev/random as it's no longer necessary. Signed-off-by: James Almer --- libavutil/random_seed.c | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/libavutil/random_seed.c b/libavutil/random_seed.c index 66dd504ef00..a51149235b2 100644 --- a/libavutil/random_seed.c +++ b/libavutil/random_seed.c @@ -49,17 +49,20 @@ static int read_random(uint32_t *dst, const char *file) { #if HAVE_UNISTD_H - int fd = avpriv_open(file, O_RDONLY); - int err = -1; + FILE *fp = avpriv_fopen_utf8(file, "r"); + size_t err; - if (fd == -1) - return -1; - err = read(fd, dst, sizeof(*dst)); - close(fd); + if (!fp) + return AVERROR_UNKNOWN; + err = fread(dst, 1, sizeof(*dst), fp); + fclose(fp); - return err; + if (err != sizeof(*dst)) + return AVERROR_UNKNOWN; + + return 0; #else - return -1; + return AVERROR(ENOSYS); #endif } @@ -138,9 +141,7 @@ uint32_t av_get_random_seed(void) return arc4random(); #endif - if (read_random(&seed, "/dev/urandom") == sizeof(seed)) - return seed; - if (read_random(&seed, "/dev/random") == sizeof(seed)) + if (!read_random(&seed, "/dev/urandom")) return seed; return get_generic_seed(); } From d694c25b44c319eadfb8039fc917639314cadb08 Mon Sep 17 00:00:00 2001 From: James Almer Date: Tue, 4 Jul 2023 19:46:32 -0300 Subject: [PATCH 1738/2172] avutil/random_seed: add av_random_bytes() Uses the existing code for av_get_random_seed() to return a buffer with cryptographically secure random data, or an error if none could be generated. Signed-off-by: James Almer --- doc/APIchanges | 3 +++ libavutil/random_seed.c | 33 ++++++++++++++++++++++----------- libavutil/random_seed.h | 13 +++++++++++++ libavutil/version.h | 4 ++-- 4 files changed, 40 insertions(+), 13 deletions(-) diff --git a/doc/APIchanges b/doc/APIchanges index f040211f7d4..27f835cfced 100644 --- a/doc/APIchanges +++ b/doc/APIchanges @@ -2,6 +2,9 @@ The last version increases of all libraries were on 2023-02-09 API changes, most recent first: +2023-07-05 - xxxxxxxxxx - lavu 58.14.100 - random_seed.h + Add av_random_bytes() + 2023-05-29 - xxxxxxxxxx - lavc 60.16.100 - avcodec.h codec_id.h Add AV_CODEC_ID_EVC, FF_PROFILE_EVC_BASELINE, and FF_PROFILE_EVC_MAIN. diff --git a/libavutil/random_seed.c b/libavutil/random_seed.c index a51149235b2..f5c291263e9 100644 --- a/libavutil/random_seed.c +++ b/libavutil/random_seed.c @@ -46,7 +46,7 @@ #define TEST 0 #endif -static int read_random(uint32_t *dst, const char *file) +static int read_random(uint8_t *dst, size_t len, const char *file) { #if HAVE_UNISTD_H FILE *fp = avpriv_fopen_utf8(file, "r"); @@ -54,10 +54,10 @@ static int read_random(uint32_t *dst, const char *file) if (!fp) return AVERROR_UNKNOWN; - err = fread(dst, 1, sizeof(*dst), fp); + err = fread(dst, 1, len, fp); fclose(fp); - if (err != sizeof(*dst)) + if (err != len) return AVERROR_UNKNOWN; return 0; @@ -121,27 +121,38 @@ static uint32_t get_generic_seed(void) return AV_RB32(digest) + AV_RB32(digest + 16); } -uint32_t av_get_random_seed(void) +int av_random_bytes(uint8_t* buf, size_t len) { - uint32_t seed; + int err; #if HAVE_BCRYPT BCRYPT_ALG_HANDLE algo_handle; NTSTATUS ret = BCryptOpenAlgorithmProvider(&algo_handle, BCRYPT_RNG_ALGORITHM, MS_PRIMITIVE_PROVIDER, 0); if (BCRYPT_SUCCESS(ret)) { - NTSTATUS ret = BCryptGenRandom(algo_handle, (UCHAR*)&seed, sizeof(seed), 0); + NTSTATUS ret = BCryptGenRandom(algo_handle, (PUCHAR)buf, len, 0); BCryptCloseAlgorithmProvider(algo_handle, 0); if (BCRYPT_SUCCESS(ret)) - return seed; + return 0; } #endif #if HAVE_ARC4RANDOM - return arc4random(); + arc4random_buf(buf, len); + return 0; #endif - if (!read_random(&seed, "/dev/urandom")) - return seed; - return get_generic_seed(); + err = read_random(buf, len, "/dev/urandom"); + + return err; +} + +uint32_t av_get_random_seed(void) +{ + uint32_t seed; + + if (av_random_bytes((uint8_t *)&seed, sizeof(seed)) < 0) + return get_generic_seed(); + + return seed; } diff --git a/libavutil/random_seed.h b/libavutil/random_seed.h index 0462a048e04..e67e6e38c44 100644 --- a/libavutil/random_seed.h +++ b/libavutil/random_seed.h @@ -36,6 +36,19 @@ */ uint32_t av_get_random_seed(void); +/** + * Generate cryptographically secure random data, i.e. suitable for use as + * encryption keys and similar. + * + * @param buf buffer into which the random data will be written + * @param len size of buf in bytes + * + * @retval 0 success, len bytes of random data was written + * into buf + * @retval "a negative AVERROR code" random data could not be generated + */ +int av_random_bytes(uint8_t *buf, size_t len); + /** * @} */ diff --git a/libavutil/version.h b/libavutil/version.h index 17a6d296a61..24af520e085 100644 --- a/libavutil/version.h +++ b/libavutil/version.h @@ -79,8 +79,8 @@ */ #define LIBAVUTIL_VERSION_MAJOR 58 -#define LIBAVUTIL_VERSION_MINOR 13 -#define LIBAVUTIL_VERSION_MICRO 101 +#define LIBAVUTIL_VERSION_MINOR 14 +#define LIBAVUTIL_VERSION_MICRO 100 #define LIBAVUTIL_VERSION_INT AV_VERSION_INT(LIBAVUTIL_VERSION_MAJOR, \ LIBAVUTIL_VERSION_MINOR, \ From 0e7fa8b3ca28c986503473043331029fa77f6317 Mon Sep 17 00:00:00 2001 From: Philip Langdale Date: Wed, 5 Jul 2023 10:24:45 -0700 Subject: [PATCH 1739/2172] avutil/random_seed: include stddef.h The new function uses size_t, which has to be defined. --- libavutil/random_seed.h | 1 + 1 file changed, 1 insertion(+) diff --git a/libavutil/random_seed.h b/libavutil/random_seed.h index e67e6e38c44..8a47be96796 100644 --- a/libavutil/random_seed.h +++ b/libavutil/random_seed.h @@ -21,6 +21,7 @@ #ifndef AVUTIL_RANDOM_SEED_H #define AVUTIL_RANDOM_SEED_H +#include #include /** * @addtogroup lavu_crypto From a196d02e866909e0e632a3f4edfffa0eee82bc51 Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Wed, 17 May 2023 09:15:51 +0200 Subject: [PATCH 1740/2172] avfilter/af_aresample: switch to activate --- libavfilter/af_aresample.c | 54 ++++++++++++++++++++++++++++++++------ 1 file changed, 46 insertions(+), 8 deletions(-) diff --git a/libavfilter/af_aresample.c b/libavfilter/af_aresample.c index 971c861d0ef..9cc50d4b380 100644 --- a/libavfilter/af_aresample.c +++ b/libavfilter/af_aresample.c @@ -32,6 +32,7 @@ #include "libswresample/swresample.h" #include "avfilter.h" #include "audio.h" +#include "filters.h" #include "internal.h" typedef struct AResampleContext { @@ -41,6 +42,7 @@ typedef struct AResampleContext { struct SwrContext *swr; int64_t next_pts; int more_data; + int eof; } AResampleContext; static av_cold int preinit(AVFilterContext *ctx) @@ -169,7 +171,8 @@ static int config_output(AVFilterLink *outlink) static int filter_frame(AVFilterLink *inlink, AVFrame *insamplesref) { - AResampleContext *aresample = inlink->dst->priv; + AVFilterContext *ctx = inlink->dst; + AResampleContext *aresample = ctx->priv; const int n_in = insamplesref->nb_samples; int64_t delay; int n_out = n_in * aresample->ratio + 32; @@ -214,6 +217,7 @@ FF_ENABLE_DEPRECATION_WARNINGS if (n_out <= 0) { av_frame_free(&outsamplesref); av_frame_free(&insamplesref); + ff_inlink_request_frame(inlink); return 0; } @@ -260,8 +264,10 @@ static int flush_frame(AVFilterLink *outlink, int final, AVFrame **outsamplesref static int request_frame(AVFilterLink *outlink) { AVFilterContext *ctx = outlink->src; + AVFilterLink *inlink = ctx->inputs[0]; AResampleContext *aresample = ctx->priv; - int ret; + int ret = 0, status; + int64_t pts; // First try to get data from the internal buffers if (aresample->more_data) { @@ -273,19 +279,52 @@ static int request_frame(AVFilterLink *outlink) } aresample->more_data = 0; + if (!aresample->eof && ff_inlink_acknowledge_status(inlink, &status, &pts)) + aresample->eof = 1; + // Second request more data from the input - ret = ff_request_frame(ctx->inputs[0]); + if (!aresample->eof) + FF_FILTER_FORWARD_WANTED(outlink, inlink); // Third if we hit the end flush - if (ret == AVERROR_EOF) { + if (aresample->eof) { AVFrame *outsamplesref; - if ((ret = flush_frame(outlink, 1, &outsamplesref)) < 0) + if ((ret = flush_frame(outlink, 1, &outsamplesref)) < 0) { + if (ret == AVERROR_EOF) { + ff_outlink_set_status(outlink, AVERROR_EOF, aresample->next_pts); + return 0; + } return ret; + } return ff_filter_frame(outlink, outsamplesref); } - return ret; + + ff_filter_set_ready(ctx, 100); + return 0; +} + +static int activate(AVFilterContext *ctx) +{ + AResampleContext *aresample = ctx->priv; + AVFilterLink *inlink = ctx->inputs[0]; + AVFilterLink *outlink = ctx->outputs[0]; + + FF_FILTER_FORWARD_STATUS_BACK(outlink, inlink); + + if (!aresample->eof && ff_inlink_queued_frames(inlink)) { + AVFrame *frame = NULL; + int ret; + + ret = ff_inlink_consume_frame(inlink, &frame); + if (ret < 0) + return ret; + if (ret > 0) + return filter_frame(inlink, frame); + } + + return request_frame(outlink); } static const AVClass *resample_child_class_iterate(void **iter) @@ -322,7 +361,6 @@ static const AVFilterPad aresample_inputs[] = { { .name = "default", .type = AVMEDIA_TYPE_AUDIO, - .filter_frame = filter_frame, }, }; @@ -330,7 +368,6 @@ static const AVFilterPad aresample_outputs[] = { { .name = "default", .config_props = config_output, - .request_frame = request_frame, .type = AVMEDIA_TYPE_AUDIO, }, }; @@ -339,6 +376,7 @@ const AVFilter ff_af_aresample = { .name = "aresample", .description = NULL_IF_CONFIG_SMALL("Resample audio data."), .preinit = preinit, + .activate = activate, .uninit = uninit, .priv_size = sizeof(AResampleContext), .priv_class = &aresample_class, From 0cdfe46f4e2d2152632e7588fd544d8d13f6fcc2 Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Wed, 5 Jul 2023 22:56:05 +0200 Subject: [PATCH 1741/2172] avfilter/avf_showcwt: fix output frame pts if inlink timebase does not match sample rate --- libavfilter/avf_showcwt.c | 1 + 1 file changed, 1 insertion(+) diff --git a/libavfilter/avf_showcwt.c b/libavfilter/avf_showcwt.c index ed1bc4c65ae..cc8740fb825 100644 --- a/libavfilter/avf_showcwt.c +++ b/libavfilter/avf_showcwt.c @@ -868,6 +868,7 @@ static int output_frame(AVFilterContext *ctx) if (s->slide != SLIDE_FRAME || s->new_frame == 1) { int64_t pts_offset = s->new_frame ? 0LL : av_rescale(s->ihop_index, s->hop_size, s->ihop_size); + pts_offset = av_rescale_q(pts_offset, av_make_q(1, inlink->sample_rate), inlink->time_base); s->outpicref->pts = av_rescale_q(s->in_pts + pts_offset, inlink->time_base, outlink->time_base); s->outpicref->duration = 1; } From 3bbb1c023b0e00324c133a86ebb0a955dd8dea0f Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Wed, 5 Jul 2023 23:02:08 +0200 Subject: [PATCH 1742/2172] avfilter/avf_showcwt: fix offset to take into initial delay Syncs audio with video. --- libavfilter/avf_showcwt.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavfilter/avf_showcwt.c b/libavfilter/avf_showcwt.c index cc8740fb825..0ee4414ea2f 100644 --- a/libavfilter/avf_showcwt.c +++ b/libavfilter/avf_showcwt.c @@ -868,7 +868,7 @@ static int output_frame(AVFilterContext *ctx) if (s->slide != SLIDE_FRAME || s->new_frame == 1) { int64_t pts_offset = s->new_frame ? 0LL : av_rescale(s->ihop_index, s->hop_size, s->ihop_size); - pts_offset = av_rescale_q(pts_offset, av_make_q(1, inlink->sample_rate), inlink->time_base); + pts_offset = av_rescale_q(pts_offset - 16384LL, av_make_q(1, inlink->sample_rate), inlink->time_base); s->outpicref->pts = av_rescale_q(s->in_pts + pts_offset, inlink->time_base, outlink->time_base); s->outpicref->duration = 1; } From ee09f20796e4ee5234900665ef1748c2a48239da Mon Sep 17 00:00:00 2001 From: James Almer Date: Sun, 2 Jul 2023 10:10:31 -0300 Subject: [PATCH 1743/2172] avcodec/cbs_h266: don't infer derived values The macro is meant for coded values only. Signed-off-by: James Almer --- libavcodec/cbs_h266_syntax_template.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/libavcodec/cbs_h266_syntax_template.c b/libavcodec/cbs_h266_syntax_template.c index 485c02f5907..a6cb2c56c23 100644 --- a/libavcodec/cbs_h266_syntax_template.c +++ b/libavcodec/cbs_h266_syntax_template.c @@ -2015,9 +2015,9 @@ static int FUNC(pps) (CodedBitstreamContext *ctx, RWContext *rw, infer(pps_tile_column_width_minus1[0], pic_width_in_ctbs_y - 1); infer(pps_num_exp_tile_rows_minus1, 0); infer(pps_tile_row_height_minus1[0], pic_height_in_ctbs_y - 1); - infer(num_tile_columns, 1); - infer(num_tile_rows, 1); - infer(num_tiles_in_pic, 1); + current->num_tile_columns = 1; + current->num_tile_rows = 1; + current->num_tiles_in_pic = 1; } flag(pps_cabac_init_present_flag); From 319a6b3ae2dfb4524db89cf82f08632a3ecc6233 Mon Sep 17 00:00:00 2001 From: James Almer Date: Sun, 2 Jul 2023 10:12:58 -0300 Subject: [PATCH 1744/2172] avcodec/cbs_h266: store RowHeightVal and ColWidthVal in the context Stop overwriting values from the bitstream arrays pps_tile_column_width_minus1 and pps_tile_row_height_minus1. Signed-off-by: James Almer --- libavcodec/cbs_h266.h | 2 ++ libavcodec/cbs_h266_syntax_template.c | 38 ++++++++++++++------------- 2 files changed, 22 insertions(+), 18 deletions(-) diff --git a/libavcodec/cbs_h266.h b/libavcodec/cbs_h266.h index e33d08a0f55..9e211b293fa 100644 --- a/libavcodec/cbs_h266.h +++ b/libavcodec/cbs_h266.h @@ -553,6 +553,8 @@ typedef struct H266RawPPS { uint16_t slice_height_in_ctus[VVC_MAX_SLICES]; uint16_t num_slices_in_subpic[VVC_MAX_SLICES]; uint16_t sub_pic_id_val[VVC_MAX_SLICES]; + uint16_t col_width_val[VVC_MAX_TILE_COLUMNS]; + uint16_t row_height_val[VVC_MAX_TILE_ROWS]; } H266RawPPS; typedef struct H266RawAUD { diff --git a/libavcodec/cbs_h266_syntax_template.c b/libavcodec/cbs_h266_syntax_template.c index a6cb2c56c23..7d69593b821 100644 --- a/libavcodec/cbs_h266_syntax_template.c +++ b/libavcodec/cbs_h266_syntax_template.c @@ -1748,10 +1748,10 @@ static int FUNC(pps) (CodedBitstreamContext *ctx, RWContext *rw, "Tile column width(%d) exceeds picture width\n",i); return AVERROR_INVALIDDATA; } + current->col_width_val[i] = current->pps_tile_column_width_minus1[i] + 1; remaining_size -= (current->pps_tile_column_width_minus1[i] + 1); } - unified_size = (i == 0 ? pic_width_in_ctbs_y : - (current->pps_tile_column_width_minus1[i - 1] + 1)); + unified_size = current->pps_tile_column_width_minus1[i - 1] + 1; while (remaining_size > 0) { if (current->num_tile_columns > VVC_MAX_TILE_COLUMNS) { av_log(ctx->log_ctx, AV_LOG_ERROR, @@ -1760,7 +1760,7 @@ static int FUNC(pps) (CodedBitstreamContext *ctx, RWContext *rw, return AVERROR_INVALIDDATA; } unified_size = FFMIN(remaining_size, unified_size); - current->pps_tile_column_width_minus1[i] = unified_size - 1; + current->col_width_val[i] = unified_size; remaining_size -= unified_size; i++; } @@ -1779,14 +1779,14 @@ static int FUNC(pps) (CodedBitstreamContext *ctx, RWContext *rw, "Tile row height(%d) exceeds picture height\n",i); return AVERROR_INVALIDDATA; } + current->row_height_val[i] = current->pps_tile_row_height_minus1[i] + 1; remaining_size -= (current->pps_tile_row_height_minus1[i] + 1); } - unified_size = (i == 0 ? pic_height_in_ctbs_y : - (current->pps_tile_row_height_minus1[i - 1] + 1)); + unified_size = current->pps_tile_row_height_minus1[i - 1] + 1; while (remaining_size > 0) { unified_size = FFMIN(remaining_size, unified_size); - current->pps_tile_row_height_minus1[i] = unified_size - 1; + current->row_height_val[i] = unified_size; remaining_size -= unified_size; i++; } @@ -1852,20 +1852,20 @@ static int FUNC(pps) (CodedBitstreamContext *ctx, RWContext *rw, ctu_x = ctu_y = 0; for (j = 0; j < tile_x; j++) { - ctu_x += current->pps_tile_column_width_minus1[j] + 1; + ctu_x += current->col_width_val[j]; } for (j = 0; j < tile_y; j++) { - ctu_y += current->pps_tile_row_height_minus1[j] + 1; + ctu_y += current->row_height_val[j]; } if (current->pps_slice_width_in_tiles_minus1[i] == 0 && current->pps_slice_height_in_tiles_minus1[i] == 0 && - current->pps_tile_row_height_minus1[tile_y] > 0) { + current->row_height_val[tile_y] > 1) { int num_slices_in_tile, uniform_slice_height, remaining_height_in_ctbs_y; remaining_height_in_ctbs_y = - current->pps_tile_row_height_minus1[tile_y] + 1; + current->row_height_val[tile_y]; ues(pps_num_exp_slices_in_tile[i], - 0, current->pps_tile_row_height_minus1[tile_y], 1, i); + 0, current->row_height_val[tile_y] - 1, 1, i); if (current->pps_num_exp_slices_in_tile[i] == 0) { num_slices_in_tile = 1; slice_top_left_ctu_x[i] = ctu_x; @@ -1875,7 +1875,7 @@ static int FUNC(pps) (CodedBitstreamContext *ctx, RWContext *rw, for (j = 0; j < current->pps_num_exp_slices_in_tile[i]; j++) { ues(pps_exp_slice_height_in_ctus_minus1[i][j], 0, - current->pps_tile_row_height_minus1[tile_y], 2, + current->row_height_val[tile_y] - 1, 2, i, j); slice_height_in_ctus = current-> @@ -1890,7 +1890,7 @@ static int FUNC(pps) (CodedBitstreamContext *ctx, RWContext *rw, remaining_height_in_ctbs_y -= slice_height_in_ctus; } uniform_slice_height = 1 + - (j == 0 ? current->pps_tile_row_height_minus1[tile_y] : + (j == 0 ? current->row_height_val[tile_y] - 1: current->pps_exp_slice_height_in_ctus_minus1[i][j-1]); while (remaining_height_in_ctbs_y > uniform_slice_height) { current->slice_height_in_ctus[i + j] = @@ -1919,7 +1919,7 @@ static int FUNC(pps) (CodedBitstreamContext *ctx, RWContext *rw, j <= current->pps_slice_height_in_tiles_minus1[i]; j++) { height += - current->pps_tile_row_height_minus1[tile_y + j] + 1; + current->row_height_val[tile_y + j]; } current->slice_height_in_ctus[i] = height; @@ -1956,10 +1956,10 @@ static int FUNC(pps) (CodedBitstreamContext *ctx, RWContext *rw, ctu_x = 0, ctu_y = 0; for (j = 0; j < tile_x; j++) { - ctu_x += current->pps_tile_column_width_minus1[j] + 1; + ctu_x += current->col_width_val[j]; } for (j = 0; j < tile_y; j++) { - ctu_y += current->pps_tile_row_height_minus1[j] + 1; + ctu_y += current->row_height_val[j]; } slice_top_left_ctu_x[i] = ctu_x; slice_top_left_ctu_y[i] = ctu_y; @@ -1972,7 +1972,7 @@ static int FUNC(pps) (CodedBitstreamContext *ctx, RWContext *rw, for (j = 0; j <= current->pps_slice_height_in_tiles_minus1[i]; j++) { height += - current->pps_tile_row_height_minus1[tile_y + j] + 1; + current->row_height_val[tile_y + j]; } current->slice_height_in_ctus[i] = height; @@ -2015,6 +2015,8 @@ static int FUNC(pps) (CodedBitstreamContext *ctx, RWContext *rw, infer(pps_tile_column_width_minus1[0], pic_width_in_ctbs_y - 1); infer(pps_num_exp_tile_rows_minus1, 0); infer(pps_tile_row_height_minus1[0], pic_height_in_ctbs_y - 1); + current->col_width_val[0] = pic_width_in_ctbs_y; + current->row_height_val[0] = pic_height_in_ctbs_y; current->num_tile_columns = 1; current->num_tile_rows = 1; current->num_tiles_in_pic = 1; @@ -3037,7 +3039,7 @@ static int FUNC(slice_header) (CodedBitstreamContext *ctx, RWContext *rw, current->sh_slice_address + current->sh_num_tiles_in_slice_minus1; tile_idx++) { tile_y = tile_idx / pps->num_tile_rows; - height = pps->pps_tile_row_height_minus1[tile_y] + 1; + height = pps->row_height_val[tile_y]; num_entry_points += (entropy_sync ? height : 1); } } From 6cb57bb457ebf544d311676bead7f1112ac9f8a9 Mon Sep 17 00:00:00 2001 From: James Almer Date: Sun, 2 Jul 2023 20:26:19 -0300 Subject: [PATCH 1745/2172] avcodec/cbs_h266: add support for Operating point information NALU type Signed-off-by: James Almer --- libavcodec/cbs_h2645.c | 18 ++++++++++++++++++ libavcodec/cbs_h266.h | 11 +++++++++++ libavcodec/cbs_h266_syntax_template.c | 27 +++++++++++++++++++++++++++ 3 files changed, 56 insertions(+) diff --git a/libavcodec/cbs_h2645.c b/libavcodec/cbs_h2645.c index 68ccf6a7eb5..8dc9ae471d5 100644 --- a/libavcodec/cbs_h2645.c +++ b/libavcodec/cbs_h2645.c @@ -1059,6 +1059,14 @@ static int cbs_h266_read_nal_unit(CodedBitstreamContext *ctx, return err; switch (unit->type) { + case VVC_OPI_NUT: + { + err = cbs_h266_read_opi(ctx, &gbc, unit->content); + + if (err < 0) + return err; + } + break; case VVC_VPS_NUT: { H266RawVPS *vps = unit->content; @@ -1593,6 +1601,15 @@ static int cbs_h266_write_nal_unit(CodedBitstreamContext *ctx, int err; switch (unit->type) { + case VVC_OPI_NUT: + { + H266RawOPI *opi = unit->content; + + err = cbs_h266_write_opi(ctx, pbc, opi); + if (err < 0) + return err; + } + break; case VVC_VPS_NUT: { H266RawVPS *vps = unit->content; @@ -1965,6 +1982,7 @@ static void cbs_h266_free_sei(void *opaque, uint8_t *content) } static const CodedBitstreamUnitTypeDescriptor cbs_h266_unit_types[] = { + CBS_UNIT_TYPE_INTERNAL_REF(VVC_OPI_NUT, H266RawOPI, extension_data.data), CBS_UNIT_TYPE_INTERNAL_REF(VVC_VPS_NUT, H266RawVPS, extension_data.data), CBS_UNIT_TYPE_INTERNAL_REF(VVC_SPS_NUT, H266RawSPS, extension_data.data), CBS_UNIT_TYPE_INTERNAL_REF(VVC_PPS_NUT, H266RawPPS, extension_data.data), diff --git a/libavcodec/cbs_h266.h b/libavcodec/cbs_h266.h index 9e211b293fa..19eed3dc8e6 100644 --- a/libavcodec/cbs_h266.h +++ b/libavcodec/cbs_h266.h @@ -230,6 +230,17 @@ typedef struct H266RawVUI { H266RawExtensionData extension_data; } H266RawVUI; +typedef struct H266RawOPI { + H266RawNALUnitHeader nal_unit_header; + + uint8_t opi_ols_info_present_flag; + uint8_t opi_htid_info_present_flag; + uint16_t opi_ols_idx; + uint8_t opi_htid_plus1; + uint8_t opi_extension_flag; + H266RawExtensionData extension_data; +} H266RawOPI; + typedef struct H266RawVPS { H266RawNALUnitHeader nal_unit_header; diff --git a/libavcodec/cbs_h266_syntax_template.c b/libavcodec/cbs_h266_syntax_template.c index 7d69593b821..9537461dddf 100644 --- a/libavcodec/cbs_h266_syntax_template.c +++ b/libavcodec/cbs_h266_syntax_template.c @@ -623,6 +623,33 @@ static int FUNC(ols_timing_hrd_parameters) (CodedBitstreamContext *ctx, return 0; } +static int FUNC(opi)(CodedBitstreamContext *ctx, RWContext *rw, + H266RawOPI *current) +{ + int err; + + HEADER("Operating point information"); + + CHECK(FUNC(nal_unit_header)(ctx, rw, + ¤t->nal_unit_header, VVC_OPI_NUT)); + + flag(opi_ols_info_present_flag); + flag(opi_htid_info_present_flag); + + if(current->opi_ols_info_present_flag) + ue(opi_ols_idx, 0, VVC_MAX_TOTAL_NUM_OLSS - 1); + + if(current->opi_htid_info_present_flag) + ub(3, opi_htid_plus1); + + flag(opi_extension_flag); + if (current->opi_extension_flag) + CHECK(FUNC(extension_data) (ctx, rw, ¤t->extension_data)); + CHECK(FUNC(rbsp_trailing_bits) (ctx, rw)); + + return 0; +} + static int FUNC(vps) (CodedBitstreamContext *ctx, RWContext *rw, H266RawVPS *current) { From 8995e2f77ec0ace4980bb0e2a979897d09129258 Mon Sep 17 00:00:00 2001 From: James Almer Date: Sun, 2 Jul 2023 20:26:20 -0300 Subject: [PATCH 1746/2172] avcodec/cbs_h266: add support for Decoding capability information NALU type Signed-off-by: James Almer --- libavcodec/cbs_h2645.c | 18 ++++++++++++++++++ libavcodec/cbs_h266.h | 10 ++++++++++ libavcodec/cbs_h266_syntax_template.c | 24 ++++++++++++++++++++++++ libavcodec/vvc.h | 3 +++ 4 files changed, 55 insertions(+) diff --git a/libavcodec/cbs_h2645.c b/libavcodec/cbs_h2645.c index 8dc9ae471d5..95da597427d 100644 --- a/libavcodec/cbs_h2645.c +++ b/libavcodec/cbs_h2645.c @@ -1059,6 +1059,14 @@ static int cbs_h266_read_nal_unit(CodedBitstreamContext *ctx, return err; switch (unit->type) { + case VVC_DCI_NUT: + { + err = cbs_h266_read_dci(ctx, &gbc, unit->content); + + if (err < 0) + return err; + } + break; case VVC_OPI_NUT: { err = cbs_h266_read_opi(ctx, &gbc, unit->content); @@ -1601,6 +1609,15 @@ static int cbs_h266_write_nal_unit(CodedBitstreamContext *ctx, int err; switch (unit->type) { + case VVC_DCI_NUT: + { + H266RawDCI *dci = unit->content; + + err = cbs_h266_write_dci(ctx, pbc, dci); + if (err < 0) + return err; + } + break; case VVC_OPI_NUT: { H266RawOPI *opi = unit->content; @@ -1982,6 +1999,7 @@ static void cbs_h266_free_sei(void *opaque, uint8_t *content) } static const CodedBitstreamUnitTypeDescriptor cbs_h266_unit_types[] = { + CBS_UNIT_TYPE_INTERNAL_REF(VVC_DCI_NUT, H266RawDCI, extension_data.data), CBS_UNIT_TYPE_INTERNAL_REF(VVC_OPI_NUT, H266RawOPI, extension_data.data), CBS_UNIT_TYPE_INTERNAL_REF(VVC_VPS_NUT, H266RawVPS, extension_data.data), CBS_UNIT_TYPE_INTERNAL_REF(VVC_SPS_NUT, H266RawSPS, extension_data.data), diff --git a/libavcodec/cbs_h266.h b/libavcodec/cbs_h266.h index 19eed3dc8e6..63af3bacf02 100644 --- a/libavcodec/cbs_h266.h +++ b/libavcodec/cbs_h266.h @@ -241,6 +241,16 @@ typedef struct H266RawOPI { H266RawExtensionData extension_data; } H266RawOPI; +typedef struct H266RawDCI { + H266RawNALUnitHeader nal_unit_header; + + uint8_t dci_reserved_zero_4bits; + uint8_t dci_num_ptls_minus1; + H266RawProfileTierLevel dci_profile_tier_level[VVC_MAX_DCI_PTLS]; + uint8_t dci_extension_flag; + H266RawExtensionData extension_data; +} H266RawDCI; + typedef struct H266RawVPS { H266RawNALUnitHeader nal_unit_header; diff --git a/libavcodec/cbs_h266_syntax_template.c b/libavcodec/cbs_h266_syntax_template.c index 9537461dddf..e2246cfc1b9 100644 --- a/libavcodec/cbs_h266_syntax_template.c +++ b/libavcodec/cbs_h266_syntax_template.c @@ -650,6 +650,30 @@ static int FUNC(opi)(CodedBitstreamContext *ctx, RWContext *rw, return 0; } +static int FUNC(dci)(CodedBitstreamContext *ctx, RWContext *rw, + H266RawDCI *current) +{ + int err, i; + + HEADER("Decoding capability information"); + + CHECK(FUNC(nal_unit_header)(ctx, rw, + ¤t->nal_unit_header, VVC_DCI_NUT)); + + ub(4, dci_reserved_zero_4bits); + ub(4, dci_num_ptls_minus1); + for (i = 0; i <= current->dci_num_ptls_minus1; i++) + CHECK(FUNC(profile_tier_level)(ctx, rw, + current->dci_profile_tier_level + i, 1, 0)); + + flag(dci_extension_flag); + if (current->dci_extension_flag) + CHECK(FUNC(extension_data)(ctx, rw, ¤t->extension_data)); + CHECK(FUNC(rbsp_trailing_bits)(ctx, rw)); + + return 0; +} + static int FUNC(vps) (CodedBitstreamContext *ctx, RWContext *rw, H266RawVPS *current) { diff --git a/libavcodec/vvc.h b/libavcodec/vvc.h index 7cf26d5e8cc..9fbb4a953c5 100644 --- a/libavcodec/vvc.h +++ b/libavcodec/vvc.h @@ -76,6 +76,9 @@ enum { //7.4.3.3 The value of vps_max_sublayers_minus1 shall be in the range of 0 to 6, inclusive VVC_MAX_SUBLAYERS = 7, + //7.3.2.1 dci_num_ptls_minus1 is u(4) + VVC_MAX_DCI_PTLS = 16, + //7.4.3.3 vps_num_ptls_minus1 is u(8) VVC_MAX_PTLS = 256, From 7caa8d6b91e738ad2c1ea61746b6c062c470f7d3 Mon Sep 17 00:00:00 2001 From: John Cox Date: Tue, 4 Jul 2023 14:04:39 +0000 Subject: [PATCH 1747/2172] tests/checkasm: Add test for vf_bwdif filter_intra MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: John Cox Signed-off-by: Martin Storsjö --- tests/checkasm/vf_bwdif.c | 37 +++++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/tests/checkasm/vf_bwdif.c b/tests/checkasm/vf_bwdif.c index 46224bb5757..034bbabb4c5 100644 --- a/tests/checkasm/vf_bwdif.c +++ b/tests/checkasm/vf_bwdif.c @@ -20,6 +20,7 @@ #include "checkasm.h" #include "libavcodec/internal.h" #include "libavfilter/bwdif.h" +#include "libavutil/mem_internal.h" #define WIDTH 256 @@ -81,4 +82,40 @@ void checkasm_check_vf_bwdif(void) BODY(uint16_t, 10); report("bwdif10"); } + + if (check_func(ctx_8.filter_intra, "bwdif8.intra")) { + LOCAL_ALIGNED_16(uint8_t, cur0, [11*WIDTH]); + LOCAL_ALIGNED_16(uint8_t, cur1, [11*WIDTH]); + LOCAL_ALIGNED_16(uint8_t, dst0, [WIDTH*3]); + LOCAL_ALIGNED_16(uint8_t, dst1, [WIDTH*3]); + const int stride = WIDTH; + const int mask = (1<<8)-1; + + declare_func(void, void *dst1, void *cur1, int w, int prefs, int mrefs, + int prefs3, int mrefs3, int parity, int clip_max); + + randomize_buffers( cur0, cur1, mask, 11*WIDTH); + memset(dst0, 0xba, WIDTH * 3); + memset(dst1, 0xba, WIDTH * 3); + + call_ref(dst0 + stride, + cur0 + stride * 4, WIDTH, + stride, -stride, stride * 3, -stride * 3, + 0, mask); + call_new(dst1 + stride, + cur0 + stride * 4, WIDTH, + stride, -stride, stride * 3, -stride * 3, + 0, mask); + + if (memcmp(dst0, dst1, WIDTH*3) + || memcmp( cur0, cur1, WIDTH*11)) + fail(); + + bench_new(dst1 + stride, + cur0 + stride * 4, WIDTH, + stride, -stride, stride * 3, -stride * 3, + 0, mask); + + report("bwdif8.intra"); + } } From 5075cfb4e6a21f6b4da9e62bdb0bad4cb32a4673 Mon Sep 17 00:00:00 2001 From: John Cox Date: Tue, 4 Jul 2023 14:04:40 +0000 Subject: [PATCH 1748/2172] avfilter/vf_bwdif: Add neon for filter_intra MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Adds an outline for aarch neon functions Adds common macros and consts for aarch64 neon Exports C filter_intra needed for tail fixup of neon code Adds neon for filter_intra Signed-off-by: John Cox Signed-off-by: Martin Storsjö --- libavfilter/aarch64/Makefile | 2 + libavfilter/aarch64/vf_bwdif_init_aarch64.c | 56 ++++++++ libavfilter/aarch64/vf_bwdif_neon.S | 136 ++++++++++++++++++++ libavfilter/bwdif.h | 4 + libavfilter/vf_bwdif.c | 8 +- 5 files changed, 203 insertions(+), 3 deletions(-) create mode 100644 libavfilter/aarch64/vf_bwdif_init_aarch64.c create mode 100644 libavfilter/aarch64/vf_bwdif_neon.S diff --git a/libavfilter/aarch64/Makefile b/libavfilter/aarch64/Makefile index b58daa3a3fe..b68209bc94a 100644 --- a/libavfilter/aarch64/Makefile +++ b/libavfilter/aarch64/Makefile @@ -1,3 +1,5 @@ +OBJS-$(CONFIG_BWDIF_FILTER) += aarch64/vf_bwdif_init_aarch64.o OBJS-$(CONFIG_NLMEANS_FILTER) += aarch64/vf_nlmeans_init.o +NEON-OBJS-$(CONFIG_BWDIF_FILTER) += aarch64/vf_bwdif_neon.o NEON-OBJS-$(CONFIG_NLMEANS_FILTER) += aarch64/vf_nlmeans_neon.o diff --git a/libavfilter/aarch64/vf_bwdif_init_aarch64.c b/libavfilter/aarch64/vf_bwdif_init_aarch64.c new file mode 100644 index 00000000000..3ffaa07ab36 --- /dev/null +++ b/libavfilter/aarch64/vf_bwdif_init_aarch64.c @@ -0,0 +1,56 @@ +/* + * bwdif aarch64 NEON optimisations + * + * Copyright (c) 2023 John Cox + * + * 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/common.h" +#include "libavfilter/bwdif.h" +#include "libavutil/aarch64/cpu.h" + +void ff_bwdif_filter_intra_neon(void *dst1, void *cur1, int w, int prefs, int mrefs, + int prefs3, int mrefs3, int parity, int clip_max); + + +static void filter_intra_helper(void *dst1, void *cur1, int w, int prefs, int mrefs, + int prefs3, int mrefs3, int parity, int clip_max) +{ + const int w0 = clip_max != 255 ? 0 : w & ~15; + + ff_bwdif_filter_intra_neon(dst1, cur1, w0, prefs, mrefs, prefs3, mrefs3, parity, clip_max); + + if (w0 < w) + ff_bwdif_filter_intra_c((char *)dst1 + w0, (char *)cur1 + w0, + w - w0, prefs, mrefs, prefs3, mrefs3, parity, clip_max); +} + +void +ff_bwdif_init_aarch64(BWDIFContext *s, int bit_depth) +{ + const int cpu_flags = av_get_cpu_flags(); + + if (bit_depth != 8) + return; + + if (!have_neon(cpu_flags)) + return; + + s->filter_intra = filter_intra_helper; +} + diff --git a/libavfilter/aarch64/vf_bwdif_neon.S b/libavfilter/aarch64/vf_bwdif_neon.S new file mode 100644 index 00000000000..e288efbe6c3 --- /dev/null +++ b/libavfilter/aarch64/vf_bwdif_neon.S @@ -0,0 +1,136 @@ +/* + * bwdif aarch64 NEON optimisations + * + * Copyright (c) 2023 John Cox + * + * 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/aarch64/asm.S" + +// Space taken on the stack by an int (32-bit) +#ifdef __APPLE__ +.set SP_INT, 4 +#else +.set SP_INT, 8 +#endif + +.macro SQSHRUNN b, s0, s1, s2, s3, n + sqshrun \s0\().4h, \s0\().4s, #\n - 8 + sqshrun2 \s0\().8h, \s1\().4s, #\n - 8 + sqshrun \s1\().4h, \s2\().4s, #\n - 8 + sqshrun2 \s1\().8h, \s3\().4s, #\n - 8 + uzp2 \b\().16b, \s0\().16b, \s1\().16b +.endm + +.macro SMULL4K a0, a1, a2, a3, s0, s1, k + smull \a0\().4s, \s0\().4h, \k + smull2 \a1\().4s, \s0\().8h, \k + smull \a2\().4s, \s1\().4h, \k + smull2 \a3\().4s, \s1\().8h, \k +.endm + +.macro UMULL4K a0, a1, a2, a3, s0, s1, k + umull \a0\().4s, \s0\().4h, \k + umull2 \a1\().4s, \s0\().8h, \k + umull \a2\().4s, \s1\().4h, \k + umull2 \a3\().4s, \s1\().8h, \k +.endm + +.macro UMLAL4K a0, a1, a2, a3, s0, s1, k + umlal \a0\().4s, \s0\().4h, \k + umlal2 \a1\().4s, \s0\().8h, \k + umlal \a2\().4s, \s1\().4h, \k + umlal2 \a3\().4s, \s1\().8h, \k +.endm + +.macro UMLSL4K a0, a1, a2, a3, s0, s1, k + umlsl \a0\().4s, \s0\().4h, \k + umlsl2 \a1\().4s, \s0\().8h, \k + umlsl \a2\().4s, \s1\().4h, \k + umlsl2 \a3\().4s, \s1\().8h, \k +.endm + +.macro LDR_COEFFS d, t0 + movrel \t0, coeffs, 0 + ld1 {\d\().8h}, [\t0] +.endm + +// static const uint16_t coef_lf[2] = { 4309, 213 }; +// static const uint16_t coef_hf[3] = { 5570, 3801, 1016 }; +// static const uint16_t coef_sp[2] = { 5077, 981 }; + +const coeffs, align=4 // align 4 means align on 2^4 boundry + .hword 4309 * 4, 213 * 4 // lf[0]*4 = v0.h[0] + .hword 5570, 3801, 1016, -3801 // hf[0] = v0.h[2], -hf[1] = v0.h[5] + .hword 5077, 981 // sp[0] = v0.h[6] +endconst + +// ============================================================================ +// +// void ff_bwdif_filter_intra_neon( +// void *dst1, // x0 +// void *cur1, // x1 +// int w, // w2 +// int prefs, // w3 +// int mrefs, // w4 +// int prefs3, // w5 +// int mrefs3, // w6 +// int parity, // w7 unused +// int clip_max) // [sp, #0] unused + +function ff_bwdif_filter_intra_neon, export=1 + cmp w2, #0 + ble 99f + + LDR_COEFFS v0, x17 + +// for (x = 0; x < w; x++) { +10: + +// interpol = (coef_sp[0] * (cur[mrefs] + cur[prefs]) - coef_sp[1] * (cur[mrefs3] + cur[prefs3])) >> 13; + ldr q31, [x1, w4, sxtw] + ldr q30, [x1, w3, sxtw] + ldr q29, [x1, w6, sxtw] + ldr q28, [x1, w5, sxtw] + + uaddl v20.8h, v31.8b, v30.8b + uaddl2 v21.8h, v31.16b, v30.16b + + UMULL4K v2, v3, v4, v5, v20, v21, v0.h[6] + + uaddl v20.8h, v29.8b, v28.8b + uaddl2 v21.8h, v29.16b, v28.16b + + UMLSL4K v2, v3, v4, v5, v20, v21, v0.h[7] + +// dst[0] = av_clip(interpol, 0, clip_max); + SQSHRUNN v2, v2, v3, v4, v5, 13 + str q2, [x0], #16 + +// dst++; +// cur++; +// } + + subs w2, w2, #16 + add x1, x1, #16 + bgt 10b + +99: + ret +endfunc diff --git a/libavfilter/bwdif.h b/libavfilter/bwdif.h index 5749345f784..ae6f6ce2233 100644 --- a/libavfilter/bwdif.h +++ b/libavfilter/bwdif.h @@ -39,5 +39,9 @@ typedef struct BWDIFContext { void ff_bwdif_init_filter_line(BWDIFContext *bwdif, int bit_depth); void ff_bwdif_init_x86(BWDIFContext *bwdif, int bit_depth); +void ff_bwdif_init_aarch64(BWDIFContext *bwdif, int bit_depth); + +void ff_bwdif_filter_intra_c(void *dst1, void *cur1, int w, int prefs, int mrefs, + int prefs3, int mrefs3, int parity, int clip_max); #endif /* AVFILTER_BWDIF_H */ diff --git a/libavfilter/vf_bwdif.c b/libavfilter/vf_bwdif.c index e278cf12176..035fc58670e 100644 --- a/libavfilter/vf_bwdif.c +++ b/libavfilter/vf_bwdif.c @@ -122,8 +122,8 @@ typedef struct ThreadData { next2++; \ } -static void filter_intra(void *dst1, void *cur1, int w, int prefs, int mrefs, - int prefs3, int mrefs3, int parity, int clip_max) +void ff_bwdif_filter_intra_c(void *dst1, void *cur1, int w, int prefs, int mrefs, + int prefs3, int mrefs3, int parity, int clip_max) { uint8_t *dst = dst1; uint8_t *cur = cur1; @@ -362,13 +362,15 @@ av_cold void ff_bwdif_init_filter_line(BWDIFContext *s, int bit_depth) s->filter_line = filter_line_c_16bit; s->filter_edge = filter_edge_16bit; } else { - s->filter_intra = filter_intra; + s->filter_intra = ff_bwdif_filter_intra_c; s->filter_line = filter_line_c; s->filter_edge = filter_edge; } #if ARCH_X86 ff_bwdif_init_x86(s, bit_depth); +#elif ARCH_AARCH64 + ff_bwdif_init_aarch64(s, bit_depth); #endif } From 7ed7c00f55a50ac88589f9e17c172d4a4fce0581 Mon Sep 17 00:00:00 2001 From: John Cox Date: Tue, 4 Jul 2023 14:04:41 +0000 Subject: [PATCH 1749/2172] tests/checkasm: Add test for vf_bwdif filter_edge MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: John Cox Signed-off-by: Martin Storsjö --- tests/checkasm/vf_bwdif.c | 54 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 54 insertions(+) diff --git a/tests/checkasm/vf_bwdif.c b/tests/checkasm/vf_bwdif.c index 034bbabb4c5..5fdba09fdc7 100644 --- a/tests/checkasm/vf_bwdif.c +++ b/tests/checkasm/vf_bwdif.c @@ -83,6 +83,60 @@ void checkasm_check_vf_bwdif(void) report("bwdif10"); } + { + LOCAL_ALIGNED_16(uint8_t, prev0, [11*WIDTH]); + LOCAL_ALIGNED_16(uint8_t, prev1, [11*WIDTH]); + LOCAL_ALIGNED_16(uint8_t, next0, [11*WIDTH]); + LOCAL_ALIGNED_16(uint8_t, next1, [11*WIDTH]); + LOCAL_ALIGNED_16(uint8_t, cur0, [11*WIDTH]); + LOCAL_ALIGNED_16(uint8_t, cur1, [11*WIDTH]); + LOCAL_ALIGNED_16(uint8_t, dst0, [WIDTH*3]); + LOCAL_ALIGNED_16(uint8_t, dst1, [WIDTH*3]); + const int stride = WIDTH; + const int mask = (1<<8)-1; + int spat; + int parity; + + for (spat = 0; spat != 2; ++spat) { + for (parity = 0; parity != 2; ++parity) { + if (check_func(ctx_8.filter_edge, "bwdif8.edge.s%d.p%d", spat, parity)) { + + declare_func(void, void *dst1, void *prev1, void *cur1, void *next1, + int w, int prefs, int mrefs, int prefs2, int mrefs2, + int parity, int clip_max, int spat); + + randomize_buffers(prev0, prev1, mask, 11*WIDTH); + randomize_buffers(next0, next1, mask, 11*WIDTH); + randomize_buffers( cur0, cur1, mask, 11*WIDTH); + memset(dst0, 0xba, WIDTH * 3); + memset(dst1, 0xba, WIDTH * 3); + + call_ref(dst0 + stride, + prev0 + stride * 4, cur0 + stride * 4, next0 + stride * 4, WIDTH, + stride, -stride, stride * 2, -stride * 2, + parity, mask, spat); + call_new(dst1 + stride, + prev1 + stride * 4, cur1 + stride * 4, next1 + stride * 4, WIDTH, + stride, -stride, stride * 2, -stride * 2, + parity, mask, spat); + + if (memcmp(dst0, dst1, WIDTH*3) + || memcmp(prev0, prev1, WIDTH*11) + || memcmp(next0, next1, WIDTH*11) + || memcmp( cur0, cur1, WIDTH*11)) + fail(); + + bench_new(dst1 + stride, + prev1 + stride * 4, cur1 + stride * 4, next1 + stride * 4, WIDTH, + stride, -stride, stride * 2, -stride * 2, + parity, mask, spat); + } + } + } + + report("bwdif8.edge"); + } + if (check_func(ctx_8.filter_intra, "bwdif8.intra")) { LOCAL_ALIGNED_16(uint8_t, cur0, [11*WIDTH]); LOCAL_ALIGNED_16(uint8_t, cur1, [11*WIDTH]); From 8130df83e0fbd3264fe990fb4e084ecbd452d0b1 Mon Sep 17 00:00:00 2001 From: John Cox Date: Tue, 4 Jul 2023 14:04:42 +0000 Subject: [PATCH 1750/2172] avfilter/vf_bwdif: Add neon for filter_edge MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Adds clip and spatial macros for aarch64 neon Exports C filter_edge needed for tail fixup of neon code Adds neon for filter_edge Signed-off-by: John Cox Signed-off-by: Martin Storsjö --- libavfilter/aarch64/vf_bwdif_init_aarch64.c | 20 +++ libavfilter/aarch64/vf_bwdif_neon.S | 177 ++++++++++++++++++++ libavfilter/bwdif.h | 4 + libavfilter/vf_bwdif.c | 8 +- 4 files changed, 205 insertions(+), 4 deletions(-) diff --git a/libavfilter/aarch64/vf_bwdif_init_aarch64.c b/libavfilter/aarch64/vf_bwdif_init_aarch64.c index 3ffaa07ab36..e75cf2f2045 100644 --- a/libavfilter/aarch64/vf_bwdif_init_aarch64.c +++ b/libavfilter/aarch64/vf_bwdif_init_aarch64.c @@ -24,10 +24,29 @@ #include "libavfilter/bwdif.h" #include "libavutil/aarch64/cpu.h" +void ff_bwdif_filter_edge_neon(void *dst1, void *prev1, void *cur1, void *next1, + int w, int prefs, int mrefs, int prefs2, int mrefs2, + int parity, int clip_max, int spat); + void ff_bwdif_filter_intra_neon(void *dst1, void *cur1, int w, int prefs, int mrefs, int prefs3, int mrefs3, int parity, int clip_max); +static void filter_edge_helper(void *dst1, void *prev1, void *cur1, void *next1, + int w, int prefs, int mrefs, int prefs2, int mrefs2, + int parity, int clip_max, int spat) +{ + const int w0 = clip_max != 255 ? 0 : w & ~15; + + ff_bwdif_filter_edge_neon(dst1, prev1, cur1, next1, w0, prefs, mrefs, prefs2, mrefs2, + parity, clip_max, spat); + + if (w0 < w) + ff_bwdif_filter_edge_c((char *)dst1 + w0, (char *)prev1 + w0, (char *)cur1 + w0, (char *)next1 + w0, + w - w0, prefs, mrefs, prefs2, mrefs2, + parity, clip_max, spat); +} + static void filter_intra_helper(void *dst1, void *cur1, int w, int prefs, int mrefs, int prefs3, int mrefs3, int parity, int clip_max) { @@ -52,5 +71,6 @@ ff_bwdif_init_aarch64(BWDIFContext *s, int bit_depth) return; s->filter_intra = filter_intra_helper; + s->filter_edge = filter_edge_helper; } diff --git a/libavfilter/aarch64/vf_bwdif_neon.S b/libavfilter/aarch64/vf_bwdif_neon.S index e288efbe6c3..389302b813a 100644 --- a/libavfilter/aarch64/vf_bwdif_neon.S +++ b/libavfilter/aarch64/vf_bwdif_neon.S @@ -66,6 +66,79 @@ umlsl2 \a3\().4s, \s1\().8h, \k .endm +// int b = m2s1 - m1; +// int f = p2s1 - p1; +// int dc = c0s1 - m1; +// int de = c0s1 - p1; +// int sp_max = FFMIN(p1 - c0s1, m1 - c0s1); +// sp_max = FFMIN(sp_max, FFMAX(-b,-f)); +// int sp_min = FFMIN(c0s1 - p1, c0s1 - m1); +// sp_min = FFMIN(sp_min, FFMAX(b,f)); +// diff = diff == 0 ? 0 : FFMAX3(diff, sp_min, sp_max); +.macro SPAT_CHECK diff, m2s1, m1, c0s1, p1, p2s1, t0, t1, t2, t3 + uqsub \t0\().16b, \p1\().16b, \c0s1\().16b + uqsub \t2\().16b, \m1\().16b, \c0s1\().16b + umin \t2\().16b, \t0\().16b, \t2\().16b + + uqsub \t1\().16b, \m1\().16b, \m2s1\().16b + uqsub \t3\().16b, \p1\().16b, \p2s1\().16b + umax \t3\().16b, \t3\().16b, \t1\().16b + umin \t3\().16b, \t3\().16b, \t2\().16b + + uqsub \t0\().16b, \c0s1\().16b, \p1\().16b + uqsub \t2\().16b, \c0s1\().16b, \m1\().16b + umin \t2\().16b, \t0\().16b, \t2\().16b + + uqsub \t1\().16b, \m2s1\().16b, \m1\().16b + uqsub \t0\().16b, \p2s1\().16b, \p1\().16b + umax \t0\().16b, \t0\().16b, \t1\().16b + umin \t2\().16b, \t2\().16b, \t0\().16b + + cmeq \t1\().16b, \diff\().16b, #0 + umax \diff\().16b, \diff\().16b, \t3\().16b + umax \diff\().16b, \diff\().16b, \t2\().16b + bic \diff\().16b, \diff\().16b, \t1\().16b +.endm + +// i0 = s0; +// if (i0 > d0 + diff0) +// i0 = d0 + diff0; +// else if (i0 < d0 - diff0) +// i0 = d0 - diff0; +// +// i0 = s0 is safe +.macro DIFF_CLIP i0, s0, d0, diff, t0, t1 + uqadd \t0\().16b, \d0\().16b, \diff\().16b + uqsub \t1\().16b, \d0\().16b, \diff\().16b + umin \i0\().16b, \s0\().16b, \t0\().16b + umax \i0\().16b, \i0\().16b, \t1\().16b +.endm + +// i0 = FFABS(m1 - p1) > td0 ? i1 : i2; +// DIFF_CLIP +// +// i0 = i1 is safe +.macro INTERPOL i0, i1, i2, m1, d0, p1, td0, diff, t0, t1, t2 + uabd \t0\().16b, \m1\().16b, \p1\().16b + cmhi \t0\().16b, \t0\().16b, \td0\().16b + bsl \t0\().16b, \i1\().16b, \i2\().16b + DIFF_CLIP \i0, \t0, \d0, \diff, \t1, \t2 +.endm + +.macro PUSH_VREGS + stp d8, d9, [sp, #-64]! + stp d10, d11, [sp, #16] + stp d12, d13, [sp, #32] + stp d14, d15, [sp, #48] +.endm + +.macro POP_VREGS + ldp d14, d15, [sp, #48] + ldp d12, d13, [sp, #32] + ldp d10, d11, [sp, #16] + ldp d8, d9, [sp], #64 +.endm + .macro LDR_COEFFS d, t0 movrel \t0, coeffs, 0 ld1 {\d\().8h}, [\t0] @@ -81,6 +154,110 @@ const coeffs, align=4 // align 4 means align on 2^4 boundry .hword 5077, 981 // sp[0] = v0.h[6] endconst +// ============================================================================ +// +// void ff_bwdif_filter_edge_neon( +// void *dst1, // x0 +// void *prev1, // x1 +// void *cur1, // x2 +// void *next1, // x3 +// int w, // w4 +// int prefs, // w5 +// int mrefs, // w6 +// int prefs2, // w7 +// int mrefs2, // [sp, #0] +// int parity, // [sp, #SP_INT] +// int clip_max, // [sp, #SP_INT*2] unused +// int spat); // [sp, #SP_INT*3] + +function ff_bwdif_filter_edge_neon, export=1 + // Sanity check w + cmp w4, #0 + ble 99f + +// #define prev2 cur +// const uint8_t * restrict next2 = parity ? prev : next; + + ldr w8, [sp, #0] // mrefs2 + + ldr w17, [sp, #SP_INT] // parity + ldr w16, [sp, #SP_INT*3] // spat + cmp w17, #0 + csel x17, x1, x3, ne + +// for (x = 0; x < w; x++) { + +10: +// int m1 = cur[mrefs]; +// int d = (prev2[0] + next2[0]) >> 1; +// int p1 = cur[prefs]; +// int temporal_diff0 = FFABS(prev2[0] - next2[0]); +// int temporal_diff1 =(FFABS(prev[mrefs] - m1) + FFABS(prev[prefs] - p1)) >> 1; +// int temporal_diff2 =(FFABS(next[mrefs] - m1) + FFABS(next[prefs] - p1)) >> 1; +// int diff = FFMAX3(temporal_diff0 >> 1, temporal_diff1, temporal_diff2); + ldr q31, [x2] + ldr q21, [x17] + uhadd v16.16b, v31.16b, v21.16b // d0 = v16 + uabd v17.16b, v31.16b, v21.16b // td0 = v17 + ldr q24, [x2, w6, sxtw] // m1 = v24 + ldr q22, [x2, w5, sxtw] // p1 = v22 + + ldr q0, [x1, w6, sxtw] // prev[mrefs] + ldr q2, [x1, w5, sxtw] // prev[prefs] + ldr q1, [x3, w6, sxtw] // next[mrefs] + ldr q3, [x3, w5, sxtw] // next[prefs] + + ushr v29.16b, v17.16b, #1 + + uabd v31.16b, v0.16b, v24.16b + uabd v30.16b, v2.16b, v22.16b + uhadd v0.16b, v31.16b, v30.16b // td1 = q0 + + uabd v31.16b, v1.16b, v24.16b + uabd v30.16b, v3.16b, v22.16b + uhadd v1.16b, v31.16b, v30.16b // td2 = q1 + + umax v0.16b, v0.16b, v29.16b + umax v0.16b, v0.16b, v1.16b // diff = v0 + +// if (spat) { +// SPAT_CHECK() +// } +// i0 = (m1 + p1) >> 1; + cbz w16, 1f + + ldr q31, [x2, w8, sxtw] + ldr q18, [x17, w8, sxtw] + ldr q30, [x2, w7, sxtw] + ldr q19, [x17, w7, sxtw] + uhadd v18.16b, v18.16b, v31.16b + uhadd v19.16b, v19.16b, v30.16b + + SPAT_CHECK v0, v18, v24, v16, v22, v19, v31, v30, v29, v28 + +1: + uhadd v2.16b, v22.16b, v24.16b + + // i0 = v2, s0 = v2, d0 = v16, diff = v0, t0 = v31, t1 = v30 + DIFF_CLIP v2, v2, v16, v0, v31, v30 + +// dst[0] = av_clip(interpol, 0, clip_max); + str q2, [x0], #16 + +// dst++; +// cur++; +// } + subs w4, w4, #16 + add x1, x1, #16 + add x2, x2, #16 + add x3, x3, #16 + add x17, x17, #16 + bgt 10b + +99: + ret +endfunc + // ============================================================================ // // void ff_bwdif_filter_intra_neon( diff --git a/libavfilter/bwdif.h b/libavfilter/bwdif.h index ae6f6ce2233..ae1616d366c 100644 --- a/libavfilter/bwdif.h +++ b/libavfilter/bwdif.h @@ -41,6 +41,10 @@ void ff_bwdif_init_filter_line(BWDIFContext *bwdif, int bit_depth); void ff_bwdif_init_x86(BWDIFContext *bwdif, int bit_depth); void ff_bwdif_init_aarch64(BWDIFContext *bwdif, int bit_depth); +void ff_bwdif_filter_edge_c(void *dst1, void *prev1, void *cur1, void *next1, + int w, int prefs, int mrefs, int prefs2, int mrefs2, + int parity, int clip_max, int spat); + void ff_bwdif_filter_intra_c(void *dst1, void *cur1, int w, int prefs, int mrefs, int prefs3, int mrefs3, int parity, int clip_max); diff --git a/libavfilter/vf_bwdif.c b/libavfilter/vf_bwdif.c index 035fc58670e..bec83111b44 100644 --- a/libavfilter/vf_bwdif.c +++ b/libavfilter/vf_bwdif.c @@ -150,9 +150,9 @@ static void filter_line_c(void *dst1, void *prev1, void *cur1, void *next1, FILTER2() } -static void filter_edge(void *dst1, void *prev1, void *cur1, void *next1, - int w, int prefs, int mrefs, int prefs2, int mrefs2, - int parity, int clip_max, int spat) +void ff_bwdif_filter_edge_c(void *dst1, void *prev1, void *cur1, void *next1, + int w, int prefs, int mrefs, int prefs2, int mrefs2, + int parity, int clip_max, int spat) { uint8_t *dst = dst1; uint8_t *prev = prev1; @@ -364,7 +364,7 @@ av_cold void ff_bwdif_init_filter_line(BWDIFContext *s, int bit_depth) } else { s->filter_intra = ff_bwdif_filter_intra_c; s->filter_line = filter_line_c; - s->filter_edge = filter_edge; + s->filter_edge = ff_bwdif_filter_edge_c; } #if ARCH_X86 From 94cb94a2c0910d364a7181fc5cc0e9556b777d0a Mon Sep 17 00:00:00 2001 From: John Cox Date: Tue, 4 Jul 2023 14:04:43 +0000 Subject: [PATCH 1751/2172] avfilter/vf_bwdif: Add neon for filter_line MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Exports C filter_line needed for tail fixup of neon code Adds neon for filter_line Signed-off-by: John Cox Signed-off-by: Martin Storsjö --- libavfilter/aarch64/vf_bwdif_init_aarch64.c | 21 ++ libavfilter/aarch64/vf_bwdif_neon.S | 203 ++++++++++++++++++++ libavfilter/bwdif.h | 5 + libavfilter/vf_bwdif.c | 10 +- 4 files changed, 234 insertions(+), 5 deletions(-) diff --git a/libavfilter/aarch64/vf_bwdif_init_aarch64.c b/libavfilter/aarch64/vf_bwdif_init_aarch64.c index e75cf2f2045..21e67884ab9 100644 --- a/libavfilter/aarch64/vf_bwdif_init_aarch64.c +++ b/libavfilter/aarch64/vf_bwdif_init_aarch64.c @@ -31,6 +31,26 @@ void ff_bwdif_filter_edge_neon(void *dst1, void *prev1, void *cur1, void *next1, void ff_bwdif_filter_intra_neon(void *dst1, void *cur1, int w, int prefs, int mrefs, int prefs3, int mrefs3, int parity, int clip_max); +void ff_bwdif_filter_line_neon(void *dst1, void *prev1, void *cur1, void *next1, + int w, int prefs, int mrefs, int prefs2, int mrefs2, + int prefs3, int mrefs3, int prefs4, int mrefs4, + int parity, int clip_max); + + +static void filter_line_helper(void *dst1, void *prev1, void *cur1, void *next1, + int w, int prefs, int mrefs, int prefs2, int mrefs2, + int prefs3, int mrefs3, int prefs4, int mrefs4, + int parity, int clip_max) +{ + const int w0 = clip_max != 255 ? 0 : w & ~15; + + ff_bwdif_filter_line_neon(dst1, prev1, cur1, next1, + w0, prefs, mrefs, prefs2, mrefs2, prefs3, mrefs3, prefs4, mrefs4, parity, clip_max); + + if (w0 < w) + ff_bwdif_filter_line_c((char *)dst1 + w0, (char *)prev1 + w0, (char *)cur1 + w0, (char *)next1 + w0, + w - w0, prefs, mrefs, prefs2, mrefs2, prefs3, mrefs3, prefs4, mrefs4, parity, clip_max); +} static void filter_edge_helper(void *dst1, void *prev1, void *cur1, void *next1, int w, int prefs, int mrefs, int prefs2, int mrefs2, @@ -71,6 +91,7 @@ ff_bwdif_init_aarch64(BWDIFContext *s, int bit_depth) return; s->filter_intra = filter_intra_helper; + s->filter_line = filter_line_helper; s->filter_edge = filter_edge_helper; } diff --git a/libavfilter/aarch64/vf_bwdif_neon.S b/libavfilter/aarch64/vf_bwdif_neon.S index 389302b813a..f185e94e3c6 100644 --- a/libavfilter/aarch64/vf_bwdif_neon.S +++ b/libavfilter/aarch64/vf_bwdif_neon.S @@ -154,6 +154,209 @@ const coeffs, align=4 // align 4 means align on 2^4 boundry .hword 5077, 981 // sp[0] = v0.h[6] endconst +// =========================================================================== +// +// void filter_line( +// void *dst1, // x0 +// void *prev1, // x1 +// void *cur1, // x2 +// void *next1, // x3 +// int w, // w4 +// int prefs, // w5 +// int mrefs, // w6 +// int prefs2, // w7 +// int mrefs2, // [sp, #0] +// int prefs3, // [sp, #SP_INT] +// int mrefs3, // [sp, #SP_INT*2] +// int prefs4, // [sp, #SP_INT*3] +// int mrefs4, // [sp, #SP_INT*4] +// int parity, // [sp, #SP_INT*5] +// int clip_max) // [sp, #SP_INT*6] + +function ff_bwdif_filter_line_neon, export=1 + // Sanity check w + cmp w4, #0 + ble 99f + + // Rearrange regs to be the same as line3 for ease of debug! + mov w10, w4 // w10 = loop count + mov w9, w6 // w9 = mref + mov w12, w7 // w12 = pref2 + mov w11, w5 // w11 = pref + ldr w8, [sp, #0] // w8 = mref2 + ldr w7, [sp, #SP_INT*2] // w7 = mref3 + ldr w6, [sp, #SP_INT*4] // w6 = mref4 + ldr w13, [sp, #SP_INT] // w13 = pref3 + ldr w14, [sp, #SP_INT*3] // w14 = pref4 + + mov x4, x3 + mov x3, x2 + mov x2, x1 + + LDR_COEFFS v0, x17 + +// #define prev2 cur +// const uint8_t * restrict next2 = parity ? prev : next; + ldr w17, [sp, #SP_INT*5] // parity + cmp w17, #0 + csel x17, x2, x4, ne + + PUSH_VREGS + +// for (x = 0; x < w; x++) { +// int diff0, diff2; +// int d0, d2; +// int temporal_diff0, temporal_diff2; +// +// int i1, i2; +// int j1, j2; +// int p6, p5, p4, p3, p2, p1, c0, m1, m2, m3, m4; + +10: +// c0 = prev2[0] + next2[0]; // c0 = v20, v21 +// d0 = c0 >> 1; // d0 = v10 +// temporal_diff0 = FFABS(prev2[0] - next2[0]); // td0 = v11 + ldr q31, [x3] + ldr q21, [x17] + uhadd v10.16b, v31.16b, v21.16b + uabd v11.16b, v31.16b, v21.16b + uaddl v20.8h, v21.8b, v31.8b + uaddl2 v21.8h, v21.16b, v31.16b + + ldr q31, [x3, w6, sxtw] + ldr q23, [x17, w6, sxtw] + +// i1 = coef_hf[0] * c0; // i1 = v2-v5 + UMULL4K v2, v3, v4, v5, v20, v21, v0.h[2] + + ldr q30, [x3, w14, sxtw] + ldr q25, [x17, w14, sxtw] + +// m4 = prev2[mrefs4] + next2[mrefs4]; // m4 = v22,v23 + uaddl v22.8h, v23.8b, v31.8b + uaddl2 v23.8h, v23.16b, v31.16b + +// p4 = prev2[prefs4] + next2[prefs4]; // p4 = v24,v25, (p4 >> 1) = v12 + uhadd v12.16b, v25.16b, v30.16b + uaddl v24.8h, v25.8b, v30.8b + uaddl2 v25.8h, v25.16b, v30.16b + +// m3 = cur[mrefs3]; // m3 = v20 + ldr q20, [x3, w7, sxtw] + +// p3 = cur[prefs3]; // p3 = v21 + ldr q21, [x3, w13, sxtw] + +// i1 += coef_hf[2] * (m4 + p4); // (-m4:v22,v23) (-p4:v24,v25) + add v22.8h, v22.8h, v24.8h + add v23.8h, v23.8h, v25.8h + UMLAL4K v2, v3, v4, v5, v22, v23, v0.h[4] + + ldr q29, [x3, w8, sxtw] + ldr q23, [x17, w8, sxtw] + +// i1 -= coef_lf[1] * 4 * (m3 + p3); // - + uaddl v30.8h, v20.8b, v21.8b + uaddl2 v31.8h, v20.16b, v21.16b + + UMLSL4K v2, v3, v4, v5, v30, v31, v0.h[1] + + ldr q31, [x3, w12, sxtw] + ldr q27, [x17, w12, sxtw] + +// m2 = prev2[mrefs2] + next2[mrefs2]; // m2 = v22,v23, (m2 >> 1) = v13 + uhadd v13.16b, v23.16b, v29.16b + uaddl v22.8h, v23.8b, v29.8b + uaddl2 v23.8h, v23.16b, v29.16b + +// m1 = cur[mrefs]; // m1 = v24 + ldr q24, [x3, w9, sxtw] + +// p2 = prev2[prefs2] + next2[prefs2]; // p2 = v26, v27 +// temporal_diff2 = FFABS(prev2[prefs2] - next2[prefs2]); // td2 = v14 +// d2 = p2 >> 1; // d2 = v15 + uabd v14.16b, v31.16b, v27.16b + uhadd v15.16b, v31.16b, v27.16b + uaddl v26.8h, v27.8b, v31.8b + uaddl2 v27.8h, v27.16b, v31.16b + +// i1 -= coef_hf[1] * (m2 + p2); // (-m2:v22,v23*) (-p2:v26*,v27*) + add v22.8h, v22.8h, v26.8h + add v23.8h, v23.8h, v27.8h + UMLSL4K v2, v3, v4, v5, v22, v23, v0.h[3] + +// p1 = cur[prefs]; // p1 = v22 + ldr q22, [x3, w11, sxtw] + +// i2 = (coef_sp[0] * (m1 + p1) - coef_sp[1] * (m3 + p3)) >> 13; // (-m3:v20*) i2=v17 + uaddl v18.8h, v22.8b, v24.8b + uaddl2 v19.8h, v22.16b, v24.16b + UMULL4K v28, v29, v30, v31, v18, v19, v0.h[6] + + uaddl v18.8h, v20.8b, v21.8b + uaddl2 v19.8h, v20.16b, v21.16b + UMLSL4K v28, v29, v30, v31, v18, v19, v0.h[7] + + SQSHRUNN v17, v28, v29, v30, v31, 13 + +// i1 += coef_lf[0] * 4 * (m1 + p1); // p1 = v22, m1 = v24 + uaddl v26.8h, v24.8b, v22.8b + uaddl2 v27.8h, v24.16b, v22.16b + UMLAL4K v2, v3, v4, v5, v26, v27, v0.h[0] + + ldr q31, [x2, w9, sxtw] + ldr q29, [x4, w9, sxtw] + + ldr q30, [x2, w11, sxtw] + ldr q28, [x4, w11, sxtw] + +// i1 >>= 15; // i1 = v2, -v3, -v4*, -v5* + SQSHRUNN v2, v2, v3, v4, v5, 15 + +// { +// int t1 =(FFABS(prev[mrefs] - m1) + FFABS(prev[prefs] - p1)) >> 1; +// int t2 =(FFABS(next[mrefs] - m1) + FFABS(next[prefs] - p1)) >> 1; + uabd v30.16b, v22.16b, v30.16b + uabd v31.16b, v24.16b, v31.16b + uabd v28.16b, v22.16b, v28.16b + uabd v29.16b, v24.16b, v29.16b + uhadd v31.16b, v31.16b, v30.16b + uhadd v29.16b, v29.16b, v28.16b + +// diff0 = FFMAX3(temporal_diff0 >> 1, t1, t2); // diff0=v18 + ushr v18.16b, v11.16b, #1 + umax v18.16b, v18.16b, v31.16b + umax v18.16b, v18.16b, v29.16b + + // diff0 = v18, (m2 >> 1) = v13, m1 = v24, d0 = v10, p1 = v22, d2 = v15 + SPAT_CHECK v18, v13, v24, v10, v22, v15, v31, v30, v29, v28 + + // i1 = v2, i2 = v17, m1 = v24, d0 = v10, p1 = v22, td2 = v11, diff2 = v18 + INTERPOL v2, v2, v17, v24, v10, v22, v11, v18, v31, v30, v29 + +// dst[0] = av_clip_uint8(interpol); + str q2, [x0], #16 +// } +// +// dst++; +// cur++; +// prev++; +// prev2++; +// next++; +// } + + subs w10, w10, #16 + add x2, x2, #16 + add x3, x3, #16 + add x4, x4, #16 + add x17, x17, #16 + bgt 10b + + POP_VREGS +99: + ret +endfunc + // ============================================================================ // // void ff_bwdif_filter_edge_neon( diff --git a/libavfilter/bwdif.h b/libavfilter/bwdif.h index ae1616d366c..cce99953f36 100644 --- a/libavfilter/bwdif.h +++ b/libavfilter/bwdif.h @@ -48,4 +48,9 @@ void ff_bwdif_filter_edge_c(void *dst1, void *prev1, void *cur1, void *next1, void ff_bwdif_filter_intra_c(void *dst1, void *cur1, int w, int prefs, int mrefs, int prefs3, int mrefs3, int parity, int clip_max); +void ff_bwdif_filter_line_c(void *dst1, void *prev1, void *cur1, void *next1, + int w, int prefs, int mrefs, int prefs2, int mrefs2, + int prefs3, int mrefs3, int prefs4, int mrefs4, + int parity, int clip_max); + #endif /* AVFILTER_BWDIF_H */ diff --git a/libavfilter/vf_bwdif.c b/libavfilter/vf_bwdif.c index bec83111b44..26349da1fd4 100644 --- a/libavfilter/vf_bwdif.c +++ b/libavfilter/vf_bwdif.c @@ -132,10 +132,10 @@ void ff_bwdif_filter_intra_c(void *dst1, void *cur1, int w, int prefs, int mrefs FILTER_INTRA() } -static void filter_line_c(void *dst1, void *prev1, void *cur1, void *next1, - int w, int prefs, int mrefs, int prefs2, int mrefs2, - int prefs3, int mrefs3, int prefs4, int mrefs4, - int parity, int clip_max) +void ff_bwdif_filter_line_c(void *dst1, void *prev1, void *cur1, void *next1, + int w, int prefs, int mrefs, int prefs2, int mrefs2, + int prefs3, int mrefs3, int prefs4, int mrefs4, + int parity, int clip_max) { uint8_t *dst = dst1; uint8_t *prev = prev1; @@ -363,7 +363,7 @@ av_cold void ff_bwdif_init_filter_line(BWDIFContext *s, int bit_depth) s->filter_edge = filter_edge_16bit; } else { s->filter_intra = ff_bwdif_filter_intra_c; - s->filter_line = filter_line_c; + s->filter_line = ff_bwdif_filter_line_c; s->filter_edge = ff_bwdif_filter_edge_c; } From 697533e76dbea8cc7fd6a0642bc60050cc05ead8 Mon Sep 17 00:00:00 2001 From: John Cox Date: Tue, 4 Jul 2023 14:04:44 +0000 Subject: [PATCH 1752/2172] avfilter/vf_bwdif: Add a filter_line3 method for optimisation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add an optional filter_line3 to the available optimisations. filter_line3 is equivalent to filter_line, memcpy, filter_line filter_line shares quite a number of loads and some calculations in common with its next iteration and testing shows that using aarch64 neon filter_line3s performance is 30% better than two filter_lines and a memcpy. Adds a test for vf_bwdif filter_line3 to checkasm Rounds job start lines down to a multiple of 4. This means that if filter_line3 exists then filter_line will not sometimes be called once at the end of a slice depending on thread count. The final slice may do up to 3 extra lines but filter_edge is faster than filter_line so it is unlikely to create any noticable thread load variation. Signed-off-by: John Cox Signed-off-by: Martin Storsjö --- libavfilter/bwdif.h | 7 ++++ libavfilter/vf_bwdif.c | 44 +++++++++++++++++++-- tests/checkasm/vf_bwdif.c | 81 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 129 insertions(+), 3 deletions(-) diff --git a/libavfilter/bwdif.h b/libavfilter/bwdif.h index cce99953f36..496cec72ef0 100644 --- a/libavfilter/bwdif.h +++ b/libavfilter/bwdif.h @@ -35,6 +35,9 @@ typedef struct BWDIFContext { void (*filter_edge)(void *dst, void *prev, void *cur, void *next, int w, int prefs, int mrefs, int prefs2, int mrefs2, int parity, int clip_max, int spat); + void (*filter_line3)(void *dst, int dstride, + const void *prev, const void *cur, const void *next, int prefs, + int w, int parity, int clip_max); } BWDIFContext; void ff_bwdif_init_filter_line(BWDIFContext *bwdif, int bit_depth); @@ -53,4 +56,8 @@ void ff_bwdif_filter_line_c(void *dst1, void *prev1, void *cur1, void *next1, int prefs3, int mrefs3, int prefs4, int mrefs4, int parity, int clip_max); +void ff_bwdif_filter_line3_c(void * dst1, int d_stride, + const void * prev1, const void * cur1, const void * next1, int s_stride, + int w, int parity, int clip_max); + #endif /* AVFILTER_BWDIF_H */ diff --git a/libavfilter/vf_bwdif.c b/libavfilter/vf_bwdif.c index 26349da1fd4..6701208efe2 100644 --- a/libavfilter/vf_bwdif.c +++ b/libavfilter/vf_bwdif.c @@ -150,6 +150,31 @@ void ff_bwdif_filter_line_c(void *dst1, void *prev1, void *cur1, void *next1, FILTER2() } +#define NEXT_LINE()\ + dst += d_stride; \ + prev += prefs; \ + cur += prefs; \ + next += prefs; + +void ff_bwdif_filter_line3_c(void * dst1, int d_stride, + const void * prev1, const void * cur1, const void * next1, int s_stride, + int w, int parity, int clip_max) +{ + const int prefs = s_stride; + uint8_t * dst = dst1; + const uint8_t * prev = prev1; + const uint8_t * cur = cur1; + const uint8_t * next = next1; + + ff_bwdif_filter_line_c(dst, (void*)prev, (void*)cur, (void*)next, w, + prefs, -prefs, prefs * 2, - prefs * 2, prefs * 3, -prefs * 3, prefs * 4, -prefs * 4, parity, clip_max); + NEXT_LINE(); + memcpy(dst, cur, w); + NEXT_LINE(); + ff_bwdif_filter_line_c(dst, (void*)prev, (void*)cur, (void*)next, w, + prefs, -prefs, prefs * 2, - prefs * 2, prefs * 3, -prefs * 3, prefs * 4, -prefs * 4, parity, clip_max); +} + void ff_bwdif_filter_edge_c(void *dst1, void *prev1, void *cur1, void *next1, int w, int prefs, int mrefs, int prefs2, int mrefs2, int parity, int clip_max, int spat) @@ -212,6 +237,13 @@ static void filter_edge_16bit(void *dst1, void *prev1, void *cur1, void *next1, FILTER2() } +// Round job start line down to multiple of 4 so that if filter_line3 exists +// and the frame is a multiple of 4 high then filter_line will never be called +static inline int job_start(const int jobnr, const int nb_jobs, const int h) +{ + return jobnr >= nb_jobs ? h : ((h * jobnr) / nb_jobs) & ~3; +} + static int filter_slice(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) { BWDIFContext *s = ctx->priv; @@ -221,8 +253,8 @@ static int filter_slice(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) int clip_max = (1 << (yadif->csp->comp[td->plane].depth)) - 1; int df = (yadif->csp->comp[td->plane].depth + 7) / 8; int refs = linesize / df; - int slice_start = (td->h * jobnr ) / nb_jobs; - int slice_end = (td->h * (jobnr+1)) / nb_jobs; + int slice_start = job_start(jobnr, nb_jobs, td->h); + int slice_end = job_start(jobnr + 1, nb_jobs, td->h); int y; for (y = slice_start; y < slice_end; y++) { @@ -244,6 +276,11 @@ static int filter_slice(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) refs << 1, -(refs << 1), td->parity ^ td->tff, clip_max, (y < 2) || ((y + 3) > td->h) ? 0 : 1); + } else if (s->filter_line3 && y + 2 < slice_end && y + 6 < td->h) { + s->filter_line3(dst, td->frame->linesize[td->plane], + prev, cur, next, linesize, td->w, + td->parity ^ td->tff, clip_max); + y += 2; } else { s->filter_line(dst, prev, cur, next, td->w, refs, -refs, refs << 1, -(refs << 1), @@ -280,7 +317,7 @@ static void filter(AVFilterContext *ctx, AVFrame *dstpic, td.plane = i; ff_filter_execute(ctx, filter_slice, &td, NULL, - FFMIN(h, ff_filter_get_nb_threads(ctx))); + FFMIN((h+3)/4, ff_filter_get_nb_threads(ctx))); } if (yadif->current_field == YADIF_FIELD_END) { yadif->current_field = YADIF_FIELD_NORMAL; @@ -357,6 +394,7 @@ static int config_props(AVFilterLink *link) av_cold void ff_bwdif_init_filter_line(BWDIFContext *s, int bit_depth) { + s->filter_line3 = 0; if (bit_depth > 8) { s->filter_intra = filter_intra_16bit; s->filter_line = filter_line_c_16bit; diff --git a/tests/checkasm/vf_bwdif.c b/tests/checkasm/vf_bwdif.c index 5fdba09fdc7..3399cacdf79 100644 --- a/tests/checkasm/vf_bwdif.c +++ b/tests/checkasm/vf_bwdif.c @@ -28,6 +28,10 @@ for (size_t i = 0; i < count; i++) \ buf0[i] = buf1[i] = rnd() & mask +#define randomize_overflow_check(buf0, buf1, mask, count) \ + for (size_t i = 0; i < count; i++) \ + buf0[i] = buf1[i] = (rnd() & 1) != 0 ? mask : 0; + #define BODY(type, depth) \ do { \ type prev0[9*WIDTH], prev1[9*WIDTH]; \ @@ -83,6 +87,83 @@ void checkasm_check_vf_bwdif(void) report("bwdif10"); } + if (!ctx_8.filter_line3) + ctx_8.filter_line3 = ff_bwdif_filter_line3_c; + + { + LOCAL_ALIGNED_16(uint8_t, prev0, [11*WIDTH]); + LOCAL_ALIGNED_16(uint8_t, prev1, [11*WIDTH]); + LOCAL_ALIGNED_16(uint8_t, next0, [11*WIDTH]); + LOCAL_ALIGNED_16(uint8_t, next1, [11*WIDTH]); + LOCAL_ALIGNED_16(uint8_t, cur0, [11*WIDTH]); + LOCAL_ALIGNED_16(uint8_t, cur1, [11*WIDTH]); + LOCAL_ALIGNED_16(uint8_t, dst0, [WIDTH*3]); + LOCAL_ALIGNED_16(uint8_t, dst1, [WIDTH*3]); + const int stride = WIDTH; + const int mask = (1<<8)-1; + int parity; + + for (parity = 0; parity != 2; ++parity) { + if (check_func(ctx_8.filter_line3, "bwdif8.line3.rnd.p%d", parity)) { + + declare_func(void, void * dst1, int d_stride, + const void * prev1, const void * cur1, const void * next1, int prefs, + int w, int parity, int clip_max); + + randomize_buffers(prev0, prev1, mask, 11*WIDTH); + randomize_buffers(next0, next1, mask, 11*WIDTH); + randomize_buffers( cur0, cur1, mask, 11*WIDTH); + + call_ref(dst0, stride, + prev0 + stride * 4, cur0 + stride * 4, next0 + stride * 4, stride, + WIDTH, parity, mask); + call_new(dst1, stride, + prev1 + stride * 4, cur1 + stride * 4, next1 + stride * 4, stride, + WIDTH, parity, mask); + + if (memcmp(dst0, dst1, WIDTH*3) + || memcmp(prev0, prev1, WIDTH*11) + || memcmp(next0, next1, WIDTH*11) + || memcmp( cur0, cur1, WIDTH*11)) + fail(); + + bench_new(dst1, stride, + prev1 + stride * 4, cur1 + stride * 4, next1 + stride * 4, stride, + WIDTH, parity, mask); + } + } + + // Use just 0s and ~0s to try to provoke bad cropping or overflow + // Parity makes no difference to this test so just test 0 + if (check_func(ctx_8.filter_line3, "bwdif8.line3.overflow")) { + + declare_func(void, void * dst1, int d_stride, + const void * prev1, const void * cur1, const void * next1, int prefs, + int w, int parity, int clip_max); + + randomize_overflow_check(prev0, prev1, mask, 11*WIDTH); + randomize_overflow_check(next0, next1, mask, 11*WIDTH); + randomize_overflow_check( cur0, cur1, mask, 11*WIDTH); + + call_ref(dst0, stride, + prev0 + stride * 4, cur0 + stride * 4, next0 + stride * 4, stride, + WIDTH, 0, mask); + call_new(dst1, stride, + prev1 + stride * 4, cur1 + stride * 4, next1 + stride * 4, stride, + WIDTH, 0, mask); + + if (memcmp(dst0, dst1, WIDTH*3) + || memcmp(prev0, prev1, WIDTH*11) + || memcmp(next0, next1, WIDTH*11) + || memcmp( cur0, cur1, WIDTH*11)) + fail(); + + // No point to benching + } + + report("bwdif8.line3"); + } + { LOCAL_ALIGNED_16(uint8_t, prev0, [11*WIDTH]); LOCAL_ALIGNED_16(uint8_t, prev1, [11*WIDTH]); From f00222e81f7d6a59d977fbb280d67989818e0ad2 Mon Sep 17 00:00:00 2001 From: John Cox Date: Tue, 4 Jul 2023 14:04:45 +0000 Subject: [PATCH 1753/2172] avfilter/vf_bwdif: Add neon for filter_line3 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: John Cox Signed-off-by: Martin Storsjö --- libavfilter/aarch64/vf_bwdif_init_aarch64.c | 28 ++ libavfilter/aarch64/vf_bwdif_neon.S | 272 ++++++++++++++++++++ 2 files changed, 300 insertions(+) diff --git a/libavfilter/aarch64/vf_bwdif_init_aarch64.c b/libavfilter/aarch64/vf_bwdif_init_aarch64.c index 21e67884ab9..f52bc4b9b43 100644 --- a/libavfilter/aarch64/vf_bwdif_init_aarch64.c +++ b/libavfilter/aarch64/vf_bwdif_init_aarch64.c @@ -36,6 +36,33 @@ void ff_bwdif_filter_line_neon(void *dst1, void *prev1, void *cur1, void *next1, int prefs3, int mrefs3, int prefs4, int mrefs4, int parity, int clip_max); +void ff_bwdif_filter_line3_neon(void * dst1, int d_stride, + const void * prev1, const void * cur1, const void * next1, int s_stride, + int w, int parity, int clip_max); + + +static void filter_line3_helper(void * dst1, int d_stride, + const void * prev1, const void * cur1, const void * next1, int s_stride, + int w, int parity, int clip_max) +{ + // Asm works on 16 byte chunks + // If w is a multiple of 16 then all is good - if not then if width rounded + // up to nearest 16 will fit in both src & dst strides then allow the asm + // to write over the padding bytes as that is almost certainly faster than + // having to invoke the C version to clean up the tail. + const int w1 = FFALIGN(w, 16); + const int w0 = clip_max != 255 ? 0 : + d_stride <= w1 && s_stride <= w1 ? w : w & ~15; + + ff_bwdif_filter_line3_neon(dst1, d_stride, + prev1, cur1, next1, s_stride, + w0, parity, clip_max); + + if (w0 < w) + ff_bwdif_filter_line3_c((char *)dst1 + w0, d_stride, + (const char *)prev1 + w0, (const char *)cur1 + w0, (const char *)next1 + w0, s_stride, + w - w0, parity, clip_max); +} static void filter_line_helper(void *dst1, void *prev1, void *cur1, void *next1, int w, int prefs, int mrefs, int prefs2, int mrefs2, @@ -93,5 +120,6 @@ ff_bwdif_init_aarch64(BWDIFContext *s, int bit_depth) s->filter_intra = filter_intra_helper; s->filter_line = filter_line_helper; s->filter_edge = filter_edge_helper; + s->filter_line3 = filter_line3_helper; } diff --git a/libavfilter/aarch64/vf_bwdif_neon.S b/libavfilter/aarch64/vf_bwdif_neon.S index f185e94e3c6..ae9aab20cdd 100644 --- a/libavfilter/aarch64/vf_bwdif_neon.S +++ b/libavfilter/aarch64/vf_bwdif_neon.S @@ -154,6 +154,278 @@ const coeffs, align=4 // align 4 means align on 2^4 boundry .hword 5077, 981 // sp[0] = v0.h[6] endconst +// =========================================================================== +// +// void ff_bwdif_filter_line3_neon( +// void * dst1, // x0 +// int d_stride, // w1 +// const void * prev1, // x2 +// const void * cur1, // x3 +// const void * next1, // x4 +// int s_stride, // w5 +// int w, // w6 +// int parity, // w7 +// int clip_max); // [sp, #0] (Ignored) + +function ff_bwdif_filter_line3_neon, export=1 + // Sanity check w + cmp w6, #0 + ble 99f + + LDR_COEFFS v0, x17 + +// #define prev2 cur +// const uint8_t * restrict next2 = parity ? prev : next; + cmp w7, #0 + csel x17, x2, x4, ne + + // We want all the V registers - save all the ones we must + PUSH_VREGS + + // Some rearrangement of initial values for nice layout of refs in regs + mov w10, w6 // w10 = loop count + neg w9, w5 // w9 = mref + lsl w8, w9, #1 // w8 = mref2 + add w7, w9, w9, LSL #1 // w7 = mref3 + lsl w6, w9, #2 // w6 = mref4 + mov w11, w5 // w11 = pref + lsl w12, w5, #1 // w12 = pref2 + add w13, w5, w5, LSL #1 // w13 = pref3 + lsl w14, w5, #2 // w14 = pref4 + add w15, w5, w5, LSL #2 // w15 = pref5 + add w16, w14, w12 // w16 = pref6 + + lsl w5, w1, #1 // w5 = d_stride * 2 + +// for (x = 0; x < w; x++) { +// int diff0, diff2; +// int d0, d2; +// int temporal_diff0, temporal_diff2; +// +// int i1, i2; +// int j1, j2; +// int p6, p5, p4, p3, p2, p1, c0, m1, m2, m3, m4; + +10: +// c0 = prev2[0] + next2[0]; // c0 = v20, v21 +// d0 = c0 >> 1; // d0 = v10 +// temporal_diff0 = FFABS(prev2[0] - next2[0]); // td0 = v11 + ldr q31, [x3] + ldr q21, [x17] + uhadd v10.16b, v31.16b, v21.16b + uabd v11.16b, v31.16b, v21.16b + uaddl v20.8h, v21.8b, v31.8b + uaddl2 v21.8h, v21.16b, v31.16b + + ldr q31, [x3, w6, sxtw] + ldr q23, [x17, w6, sxtw] + +// i1 = coef_hf[0] * c0; // i1 = v2-v5 + UMULL4K v2, v3, v4, v5, v20, v21, v0.h[2] + + ldr q30, [x3, w14, sxtw] + ldr q25, [x17, w14, sxtw] + +// m4 = prev2[mrefs4] + next2[mrefs4]; // m4 = v22,v23 + uaddl v22.8h, v23.8b, v31.8b + uaddl2 v23.8h, v23.16b, v31.16b + +// p4 = prev2[prefs4] + next2[prefs4]; // p4 = v24,v25, (p4 >> 1) = v12 + uhadd v12.16b, v25.16b, v30.16b + uaddl v24.8h, v25.8b, v30.8b + uaddl2 v25.8h, v25.16b, v30.16b + +// j1 = -coef_hf[1] * (c0 + p4); // j1 = v6-v9 (-c0:v20,v21) + add v20.8h, v20.8h, v24.8h + add v21.8h, v21.8h, v25.8h + SMULL4K v6, v7, v8, v9, v20, v21, v0.h[5] + +// m3 = cur[mrefs3]; // m3 = v20 + ldr q20, [x3, w7, sxtw] + +// p3 = cur[prefs3]; // p3 = v21 + ldr q21, [x3, w13, sxtw] + +// i1 += coef_hf[2] * (m4 + p4); // (-m4:v22,v23) (-p4:v24,v25) + add v22.8h, v22.8h, v24.8h + add v23.8h, v23.8h, v25.8h + UMLAL4K v2, v3, v4, v5, v22, v23, v0.h[4] + + ldr q29, [x3, w8, sxtw] + ldr q23, [x17, w8, sxtw] + +// i1 -= coef_lf[1] * 4 * (m3 + p3); // - + uaddl v30.8h, v20.8b, v21.8b + uaddl2 v31.8h, v20.16b, v21.16b + + ldr q28, [x3, w16, sxtw] + ldr q25, [x17, w16, sxtw] + + UMLSL4K v2, v3, v4, v5, v30, v31, v0.h[1] + +// m2 = prev2[mrefs2] + next2[mrefs2]; // m2 = v22,v23, (m2 >> 1) = v13 + uhadd v13.16b, v23.16b, v29.16b + uaddl v22.8h, v23.8b, v29.8b + uaddl2 v23.8h, v23.16b, v29.16b + + ldr q31, [x3, w12, sxtw] + ldr q27, [x17, w12, sxtw] + +// p6 = prev2[prefs6] + next2[prefs6]; // p6 = v24,v25 + uaddl v24.8h, v25.8b, v28.8b + uaddl2 v25.8h, v25.16b, v28.16b + +// j1 += coef_hf[2] * (m2 + p6); // (-p6:v24,v25) + add v24.8h, v24.8h, v22.8h + add v25.8h, v25.8h, v23.8h + UMLAL4K v6, v7, v8, v9, v24, v25, v0.h[4] + +// m1 = cur[mrefs]; // m1 = v24 + ldr q24, [x3, w9, sxtw] + +// p5 = cur[prefs5]; // p5 = v25 + ldr q25, [x3, w15, sxtw] + +// p2 = prev2[prefs2] + next2[prefs2]; // p2 = v26, v27 +// temporal_diff2 = FFABS(prev2[prefs2] - next2[prefs2]); // td2 = v14 +// d2 = p2 >> 1; // d2 = v15 + uabd v14.16b, v31.16b, v27.16b + uhadd v15.16b, v31.16b, v27.16b + uaddl v26.8h, v27.8b, v31.8b + uaddl2 v27.8h, v27.16b, v31.16b + +// j1 += coef_hf[0] * p2; // - + UMLAL4K v6, v7, v8, v9, v26, v27, v0.h[2] + +// i1 -= coef_hf[1] * (m2 + p2); // (-m2:v22,v23*) (-p2:v26*,v27*) + add v22.8h, v22.8h, v26.8h + add v23.8h, v23.8h, v27.8h + UMLSL4K v2, v3, v4, v5, v22, v23, v0.h[3] + +// p1 = cur[prefs]; // p1 = v22 + ldr q22, [x3, w11, sxtw] + +// j1 -= coef_lf[1] * 4 * (m1 + p5); // - + uaddl v26.8h, v24.8b, v25.8b + uaddl2 v27.8h, v24.16b, v25.16b + UMLSL4K v6, v7, v8, v9, v26, v27, v0.h[1] + +// j2 = (coef_sp[0] * (p1 + p3) - coef_sp[1] * (m1 + p5)) >> 13; // (-p5:v25*) j2=v16 + uaddl v18.8h, v22.8b, v21.8b + uaddl2 v19.8h, v22.16b, v21.16b + UMULL4K v28, v29, v30, v31, v18, v19, v0.h[6] + + uaddl v18.8h, v24.8b, v25.8b + uaddl2 v19.8h, v24.16b, v25.16b + UMLSL4K v28, v29, v30, v31, v18, v19, v0.h[7] + + SQSHRUNN v16, v28, v29, v30, v31, 13 + +// i2 = (coef_sp[0] * (m1 + p1) - coef_sp[1] * (m3 + p3)) >> 13; // (-m3:v20*) i2=v17 + uaddl v18.8h, v22.8b, v24.8b + uaddl2 v19.8h, v22.16b, v24.16b + UMULL4K v28, v29, v30, v31, v18, v19, v0.h[6] + + uaddl v18.8h, v20.8b, v21.8b + uaddl2 v19.8h, v20.16b, v21.16b + UMLSL4K v28, v29, v30, v31, v18, v19, v0.h[7] + + SQSHRUNN v17, v28, v29, v30, v31, 13 + +// i1 += coef_lf[0] * 4 * (m1 + p1); // p1 = v22, m1 = v24 + uaddl v26.8h, v24.8b, v22.8b + uaddl2 v27.8h, v24.16b, v22.16b + UMLAL4K v2, v3, v4, v5, v26, v27, v0.h[0] + + ldr q31, [x2, w9, sxtw] + ldr q29, [x4, w9, sxtw] + +// j1 += coef_lf[0] * 4 * (p1 + p3); // p1 = v22, p3 = v21 + uaddl v26.8h, v21.8b, v22.8b + uaddl2 v27.8h, v21.16b, v22.16b + UMLAL4K v6, v7, v8, v9, v26, v27, v0.h[0] + + ldr q30, [x2, w11, sxtw] + ldr q28, [x4, w11, sxtw] + +// i1 >>= 15; // i1 = v2, -v3, -v4*, -v5* + SQSHRUNN v2, v2, v3, v4, v5, 15 + +// j1 >>= 15; // j1 = v3, -v6*, -v7*, -v8*, -v9* + SQSHRUNN v3, v6, v7, v8, v9, 15 + +// { +// int t1 =(FFABS(prev[mrefs] - m1) + FFABS(prev[prefs] - p1)) >> 1; +// int t2 =(FFABS(next[mrefs] - m1) + FFABS(next[prefs] - p1)) >> 1; + uabd v30.16b, v22.16b, v30.16b + uabd v31.16b, v24.16b, v31.16b + uabd v28.16b, v22.16b, v28.16b + uabd v29.16b, v24.16b, v29.16b + uhadd v31.16b, v31.16b, v30.16b + uhadd v29.16b, v29.16b, v28.16b + + ldr q27, [x2, w13, sxtw] + ldr q26, [x4, w13, sxtw] + +// diff0 = FFMAX3(temporal_diff0 >> 1, t1, t2); // diff0=v18 + ushr v18.16b, v11.16b, #1 + umax v18.16b, v18.16b, v31.16b + umax v18.16b, v18.16b, v29.16b +// } // v28, v30 preserved for next block +// { // tdiff2 = v14 +// int t1 =(FFABS(prev[prefs] - p1) + FFABS(prev[prefs3] - p3)) >> 1; +// int t2 =(FFABS(next[prefs] - p1) + FFABS(next[prefs3] - p3)) >> 1; + uabd v31.16b, v21.16b, v27.16b + uabd v29.16b, v21.16b, v26.16b + uhadd v31.16b, v31.16b, v30.16b + uhadd v29.16b, v29.16b, v28.16b + +// diff2 = FFMAX3(temporal_diff2 >> 1, t1, t2); // diff2=v19 + ushr v19.16b, v14.16b, #1 + umax v19.16b, v19.16b, v31.16b + umax v19.16b, v19.16b, v29.16b +// } + + // diff0 = v18, (m2 >> 1) = v13, m1 = v24, d0 = v10, p1 = v22, d2 = v15 + SPAT_CHECK v18, v13, v24, v10, v22, v15, v31, v30, v29, v28 + + // diff2 = v19, d0 = v10, p1 = v22, d2 = v15, p3 = v21, (p4 >> 1) = v12 + SPAT_CHECK v19, v10, v22, v15, v21, v12, v31, v30, v29, v28 + + // j1 = v3, j2 = v16, p1 = v22, d2 = v15, p3 = v21, td2 = v14, diff2 = v19 + INTERPOL v3, v3, v16, v22, v15, v21, v14, v19, v31, v30, v29 + +// dst[d_stride * 2] = av_clip_uint8(interpol); + str q3, [x0, w5, sxtw] + +// dst[d_stride] = p1; + str q22, [x0, w1, sxtw] + + // i1 = v2, i2 = v17, m1 = v24, d0 = v10, p1 = v22, td2 = v11, diff2 = v18 + INTERPOL v2, v2, v17, v24, v10, v22, v11, v18, v31, v30, v29 + +// dst[0] = av_clip_uint8(interpol); + str q2, [x0], #16 +// } +// +// dst++; +// cur++; +// prev++; +// prev2++; +// next++; +// } + subs w10, w10, #16 + add x2, x2, #16 + add x3, x3, #16 + add x4, x4, #16 + add x17, x17, #16 + bgt 10b + + POP_VREGS +99: + ret +endfunc + // =========================================================================== // // void filter_line( From 4b19690ff43221cf95656253f6a83a837470ed47 Mon Sep 17 00:00:00 2001 From: Frank Plowman Date: Wed, 5 Jul 2023 22:01:13 +0800 Subject: [PATCH 1754/2172] cbs_h266: add range extension support example clips: * 12b444vvc1_E_Sony_2 * 12b444Ietsrc_A_Kwai_2 * 10b444P16_D_Sony_2 * 12b444Iepp_A_Sharp_2 * 12b444SPetsrc_B_Kwai_2 Co-authored-by: Nuo Mi Signed-off-by: James Almer --- libavcodec/cbs_h266.h | 23 +++++++- libavcodec/cbs_h266_syntax_template.c | 81 +++++++++++++++++++++++++-- 2 files changed, 96 insertions(+), 8 deletions(-) diff --git a/libavcodec/cbs_h266.h b/libavcodec/cbs_h266.h index 63af3bacf02..a70afd50fbd 100644 --- a/libavcodec/cbs_h266.h +++ b/libavcodec/cbs_h266.h @@ -118,8 +118,16 @@ typedef struct H266GeneralConstraintsInfo { uint8_t gci_no_lmcs_constraint_flag; uint8_t gci_no_ladf_constraint_flag; uint8_t gci_no_virtual_boundaries_constraint_flag; - uint8_t gci_num_reserved_bits; - uint8_t gci_reserved_zero_bit[255]; + + uint8_t gci_num_additional_bits; + uint8_t gci_reserved_bit[255]; + + uint8_t gci_all_rap_pictures_constraint_flag; + uint8_t gci_no_extended_precision_processing_constraint_flag; + uint8_t gci_no_ts_residual_coding_rice_constraint_flag; + uint8_t gci_no_rrc_rice_extension_constraint_flag; + uint8_t gci_no_persistent_rice_adaptation_constraint_flag; + uint8_t gci_no_reverse_last_sig_coeff_constraint_flag; } H266GeneralConstraintsInfo; typedef struct H266RawProfileTierLevel { @@ -472,6 +480,15 @@ typedef struct H266RawSPS { uint8_t sps_extension_flag; + uint8_t sps_range_extension_flag; + uint8_t sps_extension_7bits; + + uint8_t sps_extended_precision_flag; + uint8_t sps_ts_residual_coding_rice_present_in_sh_flag; + uint8_t sps_rrc_rice_extension_flag; + uint8_t sps_persistent_rice_adaptation_enabled_flag; + uint8_t sps_reverse_last_sig_coeff_enabled_flag; + H266RawExtensionData extension_data; } H266RawSPS; @@ -757,6 +774,8 @@ typedef struct H266RawSliceHeader { uint8_t sh_sign_data_hiding_used_flag; uint8_t sh_ts_residual_coding_disabled_flag; + uint8_t sh_ts_residual_coding_rice_idx_minus1; + uint8_t sh_reverse_last_sig_coeff_flag; uint16_t sh_slice_header_extension_length; uint8_t sh_slice_header_extension_data_byte[256]; diff --git a/libavcodec/cbs_h266_syntax_template.c b/libavcodec/cbs_h266_syntax_template.c index e2246cfc1b9..41be73b5b2d 100644 --- a/libavcodec/cbs_h266_syntax_template.c +++ b/libavcodec/cbs_h266_syntax_template.c @@ -61,7 +61,7 @@ static int FUNC(general_constraints_info) (CodedBitstreamContext *ctx, RWContext *rw, H266GeneralConstraintsInfo *current) { - int err, i; + int err, i, num_additional_bits_used; flag(gci_present_flag); if (current->gci_present_flag) { @@ -148,10 +148,27 @@ static int FUNC(general_constraints_info) (CodedBitstreamContext *ctx, flag(gci_no_lmcs_constraint_flag); flag(gci_no_ladf_constraint_flag); flag(gci_no_virtual_boundaries_constraint_flag); - ub(8, gci_num_reserved_bits); - for (i = 0; i < current->gci_num_reserved_bits; i++) { - flags(gci_reserved_zero_bit[i], 1, i); + ub(8, gci_num_additional_bits); + if (current->gci_num_additional_bits > 5) { + flag(gci_all_rap_pictures_constraint_flag); + flag(gci_no_extended_precision_processing_constraint_flag); + flag(gci_no_ts_residual_coding_rice_constraint_flag); + flag(gci_no_rrc_rice_extension_constraint_flag); + flag(gci_no_persistent_rice_adaptation_constraint_flag); + flag(gci_no_reverse_last_sig_coeff_constraint_flag); + num_additional_bits_used = 6; + } else { + infer(gci_all_rap_pictures_constraint_flag, 0); + infer(gci_no_extended_precision_processing_constraint_flag, 0); + infer(gci_no_ts_residual_coding_rice_constraint_flag, 0); + infer(gci_no_rrc_rice_extension_constraint_flag, 0); + infer(gci_no_persistent_rice_adaptation_constraint_flag, 0); + infer(gci_no_reverse_last_sig_coeff_constraint_flag, 0); + num_additional_bits_used = 0; } + + for (i = 0; i < current->gci_num_additional_bits - num_additional_bits_used; i++) + flags(gci_reserved_bit[i], 1, i); } while (byte_alignment(rw) != 0) fixed(1, gci_alignment_zero_bit, 0); @@ -1014,6 +1031,22 @@ static int FUNC(vps) (CodedBitstreamContext *ctx, RWContext *rw, return 0; } +static int FUNC(sps_range_extension)(CodedBitstreamContext *ctx, RWContext *rw, + H266RawSPS *current) +{ + int err; + + flag(sps_extended_precision_flag); + if (current->sps_transform_skip_enabled_flag) + flag(sps_ts_residual_coding_rice_present_in_sh_flag); + else + infer(sps_ts_residual_coding_rice_present_in_sh_flag, 0); + flag(sps_rrc_rice_extension_flag); + flag(sps_persistent_rice_adaptation_enabled_flag); + flag(sps_reverse_last_sig_coeff_enabled_flag); + + return 0; +} static int FUNC(sps)(CodedBitstreamContext *ctx, RWContext *rw, H266RawSPS *current) @@ -1569,9 +1602,33 @@ static int FUNC(sps)(CodedBitstreamContext *ctx, RWContext *rw, } else { CHECK(FUNC(vui_parameters_default) (ctx, rw, ¤t->vui)); } + flag(sps_extension_flag); - if (current->sps_extension_flag) - CHECK(FUNC(extension_data) (ctx, rw, ¤t->extension_data)); + if (current->sps_extension_flag) { + flag(sps_range_extension_flag); + ub(7, sps_extension_7bits); + + if (current->sps_range_extension_flag) { + CHECK(FUNC(sps_range_extension)(ctx, rw, current)); + } else { + infer(sps_extended_precision_flag, 0); + infer(sps_ts_residual_coding_rice_present_in_sh_flag, 0); + infer(sps_rrc_rice_extension_flag, 0); + infer(sps_persistent_rice_adaptation_enabled_flag, 0); + infer(sps_reverse_last_sig_coeff_enabled_flag, 0); + } + } else { + infer(sps_range_extension_flag, 0); + infer(sps_extension_7bits, 0); + infer(sps_extended_precision_flag, 0); + infer(sps_ts_residual_coding_rice_present_in_sh_flag, 0); + infer(sps_rrc_rice_extension_flag, 0); + infer(sps_persistent_rice_adaptation_enabled_flag, 0); + infer(sps_reverse_last_sig_coeff_enabled_flag, 0); + } + + if (current->sps_extension_7bits) + CHECK(FUNC(extension_data)(ctx, rw, ¤t->extension_data)); CHECK(FUNC(rbsp_trailing_bits) (ctx, rw)); @@ -3058,6 +3115,18 @@ static int FUNC(slice_header) (CodedBitstreamContext *ctx, RWContext *rw, flag(sh_ts_residual_coding_disabled_flag); else infer(sh_ts_residual_coding_disabled_flag, 0); + + if (!current->sh_ts_residual_coding_disabled_flag && + sps->sps_ts_residual_coding_rice_present_in_sh_flag) + ub(3, sh_ts_residual_coding_rice_idx_minus1); + else + infer(sh_ts_residual_coding_rice_idx_minus1, 0); + + if (sps->sps_reverse_last_sig_coeff_enabled_flag) + flag(sh_reverse_last_sig_coeff_flag); + else + infer(sh_reverse_last_sig_coeff_flag, 0); + if (pps->pps_slice_header_extension_present_flag) { ue(sh_slice_header_extension_length, 0, 256); for (i = 0; i < current->sh_slice_header_extension_length; i++) From 68e9d2835fa3e5c0f73a32a8455fdcd9a5a01e77 Mon Sep 17 00:00:00 2001 From: James Almer Date: Sun, 2 Jul 2023 20:26:21 -0300 Subject: [PATCH 1755/2172] avcodec/cbs_h266: add support for Adaptation parameter set NALU type Reviewed-by: Nuo Mi Signed-off-by: James Almer --- libavcodec/cbs_h2645.c | 21 +++ libavcodec/cbs_h266.h | 46 +++++ libavcodec/cbs_h266_syntax_template.c | 231 ++++++++++++++++++++++++++ libavcodec/vvc.h | 10 ++ 4 files changed, 308 insertions(+) diff --git a/libavcodec/cbs_h2645.c b/libavcodec/cbs_h2645.c index 95da597427d..34c5d1d372f 100644 --- a/libavcodec/cbs_h2645.c +++ b/libavcodec/cbs_h2645.c @@ -1116,6 +1116,16 @@ static int cbs_h266_read_nal_unit(CodedBitstreamContext *ctx, } break; + case VVC_PREFIX_APS_NUT: + case VVC_SUFFIX_APS_NUT: + { + err = cbs_h266_read_aps(ctx, &gbc, unit->content, + unit->type == VVC_PREFIX_APS_NUT); + + if (err < 0) + return err; + } + break; case VVC_PH_NUT: { H266RawPH *ph = unit->content; @@ -1668,6 +1678,15 @@ static int cbs_h266_write_nal_unit(CodedBitstreamContext *ctx, } break; + case VVC_PREFIX_APS_NUT: + case VVC_SUFFIX_APS_NUT: + { + err = cbs_h266_write_aps(ctx, pbc, unit->content, + unit->type == VVC_PREFIX_APS_NUT); + if (err < 0) + return err; + } + break; case VVC_PH_NUT: { H266RawPH *ph = unit->content; @@ -2004,6 +2023,8 @@ static const CodedBitstreamUnitTypeDescriptor cbs_h266_unit_types[] = { CBS_UNIT_TYPE_INTERNAL_REF(VVC_VPS_NUT, H266RawVPS, extension_data.data), CBS_UNIT_TYPE_INTERNAL_REF(VVC_SPS_NUT, H266RawSPS, extension_data.data), CBS_UNIT_TYPE_INTERNAL_REF(VVC_PPS_NUT, H266RawPPS, extension_data.data), + CBS_UNIT_TYPE_INTERNAL_REF(VVC_PREFIX_APS_NUT, H266RawAPS, extension_data.data), + CBS_UNIT_TYPE_INTERNAL_REF(VVC_SUFFIX_APS_NUT, H266RawAPS, extension_data.data), CBS_UNIT_TYPE_POD(VVC_PH_NUT , H266RawPH), CBS_UNIT_TYPE_POD(VVC_AUD_NUT, H266RawAUD), diff --git a/libavcodec/cbs_h266.h b/libavcodec/cbs_h266.h index a70afd50fbd..0196f46bc08 100644 --- a/libavcodec/cbs_h266.h +++ b/libavcodec/cbs_h266.h @@ -595,6 +595,52 @@ typedef struct H266RawPPS { uint16_t row_height_val[VVC_MAX_TILE_ROWS]; } H266RawPPS; +typedef struct H266RawAPS { + H266RawNALUnitHeader nal_unit_header; + uint8_t aps_params_type; + uint8_t aps_adaptation_parameter_set_id; + uint8_t aps_chroma_present_flag; + + uint8_t alf_luma_filter_signal_flag; + uint8_t alf_chroma_filter_signal_flag; + uint8_t alf_cc_cb_filter_signal_flag; + uint8_t alf_cc_cr_filter_signal_flag; + uint8_t alf_luma_clip_flag; + uint8_t alf_luma_num_filters_signalled_minus1; + uint8_t alf_luma_coeff_delta_idx[VVC_NUM_ALF_FILTERS]; + uint8_t alf_luma_coeff_abs[VVC_NUM_ALF_FILTERS][12]; + uint8_t alf_luma_coeff_sign[VVC_NUM_ALF_FILTERS][12]; + uint8_t alf_luma_clip_idx[VVC_NUM_ALF_FILTERS][12]; + uint8_t alf_chroma_clip_flag; + uint8_t alf_chroma_num_alt_filters_minus1; + uint8_t alf_chroma_coeff_abs[8][6]; + uint8_t alf_chroma_coeff_sign[8][6]; + uint8_t alf_chroma_clip_idx[8][6]; + uint8_t alf_cc_cb_filters_signalled_minus1; + uint8_t alf_cc_cb_mapped_coeff_abs[4][7]; + uint8_t alf_cc_cb_coeff_sign[4][7]; + uint8_t alf_cc_cr_filters_signalled_minus1; + uint8_t alf_cc_cr_mapped_coeff_abs[4][7]; + uint8_t alf_cc_cr_coeff_sign[4][7]; + + uint8_t scaling_list_copy_mode_flag[28]; + uint8_t scaling_list_pred_mode_flag[28]; + uint8_t scaling_list_pred_id_delta[28]; + int8_t scaling_list_dc_coef[14]; + int8_t scaling_list_delta_coef[28][64]; + + uint8_t lmcs_min_bin_idx; + uint8_t lmcs_delta_max_bin_idx; + uint8_t lmcs_delta_cw_prec_minus1; + uint16_t lmcs_delta_abs_cw[16]; + uint8_t lmcs_delta_sign_cw_flag[16]; + uint8_t lmcs_delta_abs_crs; + uint8_t lmcs_delta_sign_crs_flag; + + uint8_t aps_extension_flag; + H266RawExtensionData extension_data; +} H266RawAPS; + typedef struct H266RawAUD { H266RawNALUnitHeader nal_unit_header; uint8_t aud_irap_or_gdr_flag; diff --git a/libavcodec/cbs_h266_syntax_template.c b/libavcodec/cbs_h266_syntax_template.c index 41be73b5b2d..b984a12d8f8 100644 --- a/libavcodec/cbs_h266_syntax_template.c +++ b/libavcodec/cbs_h266_syntax_template.c @@ -2242,6 +2242,237 @@ static int FUNC(pps) (CodedBitstreamContext *ctx, RWContext *rw, return 0; } +static int FUNC(alf_data)(CodedBitstreamContext *ctx, RWContext *rw, + H266RawAPS *current) +{ + int err, j, k; + + flag(alf_luma_filter_signal_flag); + + if (current->aps_chroma_present_flag) { + flag(alf_chroma_filter_signal_flag); + flag(alf_cc_cb_filter_signal_flag); + flag(alf_cc_cr_filter_signal_flag); + } else { + infer(alf_chroma_filter_signal_flag, 0); + infer(alf_cc_cb_filter_signal_flag, 0); + infer(alf_cc_cr_filter_signal_flag, 0); + } + + if (current->alf_luma_filter_signal_flag) { + flag(alf_luma_clip_flag); + ue(alf_luma_num_filters_signalled_minus1, 0, VVC_NUM_ALF_FILTERS - 1); + if (current->alf_luma_num_filters_signalled_minus1 > 0) { + unsigned int bits = av_ceil_log2(current->alf_luma_num_filters_signalled_minus1 + 1); + for (int filt_idx = 0; filt_idx < VVC_NUM_ALF_FILTERS; filt_idx++) + us(bits, alf_luma_coeff_delta_idx[filt_idx], + 0, current->alf_luma_num_filters_signalled_minus1, + 1, filt_idx); + } + for (int sf_idx = 0; sf_idx <= current->alf_luma_num_filters_signalled_minus1; sf_idx++) + for (j = 0; j < 12; j++) { + ues(alf_luma_coeff_abs[sf_idx][j], 0, 128, 2, sf_idx, j); + if (current->alf_luma_coeff_abs[sf_idx][j]) + ubs(1, alf_luma_coeff_sign[sf_idx][j], 2, sf_idx, j); + else + infer(alf_luma_coeff_sign[sf_idx][j], 0); + } + } else { + infer(alf_luma_clip_flag, 0); + infer(alf_luma_num_filters_signalled_minus1, 0); + } + for (int sf_idx = 0; sf_idx <= current->alf_luma_num_filters_signalled_minus1; sf_idx++) { + for (j = 0; j < 12; j++) { + if (current->alf_luma_clip_flag) + ubs(2, alf_luma_clip_idx[sf_idx][j], 2, sf_idx, j); + else + infer(alf_luma_clip_idx[sf_idx][j], 0); + } + } + + if (current->alf_chroma_filter_signal_flag) { + flag(alf_chroma_clip_flag); + ue(alf_chroma_num_alt_filters_minus1, 0, 7); + } else { + infer(alf_chroma_clip_flag, 0); + infer(alf_chroma_num_alt_filters_minus1, 0); + } + for (int alt_idx = 0; alt_idx <= current->alf_chroma_num_alt_filters_minus1; alt_idx++) { + for (j = 0; j < 6; j++) { + if (current->alf_chroma_filter_signal_flag) + ues(alf_chroma_coeff_abs[alt_idx][j], 0, 128, 2, alt_idx, j); + else + infer(alf_chroma_coeff_abs[alt_idx][j], 0); + if (current->alf_chroma_coeff_abs[alt_idx][j] > 0) + ubs(1, alf_chroma_coeff_sign[alt_idx][j], 2, alt_idx, j); + else + infer(alf_chroma_coeff_sign[alt_idx][j], 0); + } + for (j = 0; j < 6; j++) { + if (current->alf_chroma_clip_flag) + ubs(2, alf_chroma_clip_idx[alt_idx][j], 2, alt_idx, j); + else + infer(alf_chroma_clip_idx[alt_idx][j], 0); + } + } + + if (current->alf_cc_cb_filter_signal_flag) + ue(alf_cc_cb_filters_signalled_minus1, 0, 3); + else + infer(alf_cc_cb_filters_signalled_minus1, 0); + for (k = 0; k <= current->alf_cc_cb_filters_signalled_minus1; k++) { + for (j = 0; j < 7; j++) { + if (current->alf_cc_cb_filter_signal_flag) + ubs(3, alf_cc_cb_mapped_coeff_abs[k][j], 2, k, j); + else + infer(alf_cc_cb_mapped_coeff_abs[k][j], 0); + if (current->alf_cc_cb_mapped_coeff_abs[k][j]) + ubs(1, alf_cc_cb_coeff_sign[k][j], 2, k, j); + else + infer(alf_cc_cb_coeff_sign[k][j], 0); + } + } + + if (current->alf_cc_cr_filter_signal_flag) + ue(alf_cc_cr_filters_signalled_minus1, 0, 3); + else + infer(alf_cc_cr_filters_signalled_minus1, 0); + for (k = 0; k < current->alf_cc_cr_filters_signalled_minus1 + 1; k++) { + for (j = 0; j < 7; j++) { + if (current->alf_cc_cr_filter_signal_flag) + ubs(3, alf_cc_cr_mapped_coeff_abs[k][j], 2, k, j); + else + infer(alf_cc_cr_mapped_coeff_abs[k][j], 0); + if (current->alf_cc_cr_mapped_coeff_abs[k][j]) + ubs(1, alf_cc_cr_coeff_sign[k][j], 2, k, j); + else + infer(alf_cc_cr_coeff_sign[k][j], 0); + } + } + + return 0; +} + +static int FUNC(lmcs_data)(CodedBitstreamContext *ctx, RWContext *rw, + H266RawAPS *current) +{ + int err, i, lmcs_max_bin_idx; + + ue(lmcs_min_bin_idx, 0, 15); + ue(lmcs_delta_max_bin_idx, 0, 15); + ue(lmcs_delta_cw_prec_minus1, 0, 14); + + lmcs_max_bin_idx = 15 - current->lmcs_delta_max_bin_idx; + + if (lmcs_max_bin_idx < current->lmcs_min_bin_idx) + return AVERROR_INVALIDDATA; + + for (i = current->lmcs_min_bin_idx; i <= lmcs_max_bin_idx; i++) { + ubs(current->lmcs_delta_cw_prec_minus1 + 1, lmcs_delta_abs_cw[i], 1, i); + if (current->lmcs_delta_abs_cw[i] > 0) + flags(lmcs_delta_sign_cw_flag[i], 1, i); + else + infer(lmcs_delta_sign_cw_flag[i], 0); + } + + if (current->aps_chroma_present_flag) { + ub(3, lmcs_delta_abs_crs); + if (current->lmcs_delta_abs_crs > 0) + flag(lmcs_delta_sign_crs_flag); + else + infer(lmcs_delta_sign_crs_flag, 0); + } else { + infer(lmcs_delta_abs_crs, 0); + infer(lmcs_delta_sign_crs_flag, 0); + } + + return 0; +} + +static int FUNC(scaling_list_data)(CodedBitstreamContext *ctx, RWContext *rw, + H266RawAPS *current) +{ + // 7.4.3.4, deriving DiagScanOrder + static const uint8_t diag_scan_order[64][2] = { + { 0, 0, }, { 0, 1, }, { 1, 0, }, { 0, 2, }, { 1, 1, }, { 2, 0, }, { 0, 3, }, { 1, 2, }, + { 2, 1, }, { 3, 0, }, { 0, 4, }, { 1, 3, }, { 2, 2, }, { 3, 1, }, { 4, 0, }, { 0, 5, }, + { 1, 4, }, { 2, 3, }, { 3, 2, }, { 4, 1, }, { 5, 0, }, { 0, 6, }, { 1, 5, }, { 2, 4, }, + { 3, 3, }, { 4, 2, }, { 5, 1, }, { 6, 0, }, { 0, 7, }, { 1, 6, }, { 2, 5, }, { 3, 4, }, + { 4, 3, }, { 5, 2, }, { 6, 1, }, { 7, 0, }, { 1, 7, }, { 2, 6, }, { 3, 5, }, { 4, 4, }, + { 5, 3, }, { 6, 2, }, { 7, 1, }, { 2, 7, }, { 3, 6, }, { 4, 5, }, { 5, 4, }, { 6, 3, }, + { 7, 2, }, { 3, 7, }, { 4, 6, }, { 5, 5, }, { 6, 4, }, { 7, 3, }, { 4, 7, }, { 5, 6, }, + { 6, 5, }, { 7, 4, }, { 5, 7, }, { 6, 6, }, { 7, 5, }, { 6, 7, }, { 7, 6, }, { 7, 7, }, }; + int err; + + for (int id = 0; id < 28; id ++) { + if (current->aps_chroma_present_flag || id % 3 == 2 || id == 27) { + flags(scaling_list_copy_mode_flag[id], 1, id); + if (!current->scaling_list_copy_mode_flag[id]) + flags(scaling_list_pred_mode_flag[id], 1, id); + else + infer(scaling_list_pred_mode_flag[id], 0); + if ((current->scaling_list_copy_mode_flag[id] || + current->scaling_list_pred_mode_flag[id]) && + id != 0 && id != 2 && id != 8) { + int max_id_delta = (id < 2) ? id : ((id < 8) ? (id - 2) : (id - 8)); + ues(scaling_list_pred_id_delta[id], 0, max_id_delta, 1, id); + } + if (!current->scaling_list_copy_mode_flag[id]) { + int matrix_size = id < 2 ? 2 : (id < 8 ? 4 : 8); + if (id > 13) { + int idx = id - 14; + ses(scaling_list_dc_coef[idx], -128, 127, 1, idx); + } + for (int i = 0; i < matrix_size * matrix_size; i++) { + int x = diag_scan_order[i][0]; + int y = diag_scan_order[i][1]; + if (!(id > 25 && x >= 4 && y >= 4)) + ses(scaling_list_delta_coef[id][i], -128, 127, 2, id, i); + } + } else if (id > 13) { + int idx = id - 14; + infer(scaling_list_dc_coef[idx], 0); + } + } else { + infer(scaling_list_copy_mode_flag[id], 1); + infer(scaling_list_pred_mode_flag[id], 0); + } + } + + return 0; +} + +static int FUNC(aps)(CodedBitstreamContext *ctx, RWContext *rw, + H266RawAPS *current, int prefix) +{ + int err; + + if (prefix) + HEADER("Prefix Adaptation parameter set"); + else + HEADER("Suffix Adaptation parameter set"); + + CHECK(FUNC(nal_unit_header)(ctx, rw, ¤t->nal_unit_header, + prefix ? VVC_PREFIX_APS_NUT + : VVC_SUFFIX_APS_NUT)); + + ub(3, aps_params_type); + ub(5, aps_adaptation_parameter_set_id); + flag(aps_chroma_present_flag); + if (current->aps_params_type == VVC_ASP_TYPE_ALF) + CHECK(FUNC(alf_data)(ctx, rw, current)); + else if(current->aps_params_type == VVC_ASP_TYPE_LMCS) + CHECK(FUNC(lmcs_data)(ctx, rw, current)); + else if (current->aps_params_type == VVC_ASP_TYPE_SCALING) + CHECK(FUNC(scaling_list_data)(ctx, rw, current)); + flag(aps_extension_flag); + if (current->aps_extension_flag) + CHECK(FUNC(extension_data) (ctx, rw, ¤t->extension_data)); + CHECK(FUNC(rbsp_trailing_bits) (ctx, rw)); + + return 0; +} + static int FUNC(aud) (CodedBitstreamContext *ctx, RWContext *rw, H266RawAUD *current) { diff --git a/libavcodec/vvc.h b/libavcodec/vvc.h index 9fbb4a953c5..7d165cdb861 100644 --- a/libavcodec/vvc.h +++ b/libavcodec/vvc.h @@ -66,6 +66,12 @@ enum VVCSliceType { VVC_SLICE_TYPE_I = 2, }; +enum VVCAPSType { + VVC_ASP_TYPE_ALF = 0, + VVC_ASP_TYPE_LMCS = 1, + VVC_ASP_TYPE_SCALING = 2, +}; + enum { //6.2 we can have 3 sample arrays VVC_MAX_SAMPLE_ARRAYS = 3, @@ -95,6 +101,10 @@ enum { // 7.4.4.1: ptl_num_sub_profiles is u(8) VVC_MAX_SUB_PROFILES = 256, + // 7.4.3.18: The variable NumAlfFilters specifying the number of different adaptive loop + // filters is set equal to 25. + VVC_NUM_ALF_FILTERS = 25, + // A.4.2: according to (1577), MaxDpbSize is bounded above by 2 * maxDpbPicBuf(8) VVC_MAX_DPB_SIZE = 16, From b7f4d5fa7e04498fddd60d298bc4a95241a581da Mon Sep 17 00:00:00 2001 From: James Almer Date: Tue, 4 Jul 2023 19:49:23 -0300 Subject: [PATCH 1756/2172] avutil/random_seed: add support for gcrypt and OpenSSL as source of randomness Reviewed-by: Anton Khirnov Signed-off-by: James Almer --- configure | 2 +- libavutil/random_seed.c | 16 ++++++++++++++++ 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/configure b/configure index 107d533b3e2..d6e78297fe5 100755 --- a/configure +++ b/configure @@ -3892,7 +3892,7 @@ avfilter_deps="avutil" avfilter_suggest="libm stdatomic" avformat_deps="avcodec avutil" avformat_suggest="libm network zlib stdatomic" -avutil_suggest="clock_gettime ffnvcodec libm libdrm libmfx opencl user32 vaapi vulkan videotoolbox corefoundation corevideo coremedia bcrypt stdatomic" +avutil_suggest="clock_gettime ffnvcodec gcrypt libm libdrm libmfx opencl openssl user32 vaapi vulkan videotoolbox corefoundation corevideo coremedia bcrypt stdatomic" postproc_deps="avutil gpl" postproc_suggest="libm stdatomic" swresample_deps="avutil" diff --git a/libavutil/random_seed.c b/libavutil/random_seed.c index f5c291263e9..2980e565e08 100644 --- a/libavutil/random_seed.c +++ b/libavutil/random_seed.c @@ -30,6 +30,11 @@ #include #include #endif +#if CONFIG_GCRYPT +#include +#elif CONFIG_OPENSSL +#include +#endif #include #include #include @@ -143,6 +148,17 @@ int av_random_bytes(uint8_t* buf, size_t len) #endif err = read_random(buf, len, "/dev/urandom"); + if (!err) + return err; + +#if CONFIG_GCRYPT + gcry_randomize(buf, len, GCRY_VERY_STRONG_RANDOM); + return 0; +#elif CONFIG_OPENSSL + if (RAND_bytes(buf, len) == 1) + return 0; + err = AVERROR_EXTERNAL; +#endif return err; } From 4e27b485d7924dfa4600c978863b1d84f1fc317b Mon Sep 17 00:00:00 2001 From: Marton Balint Date: Sun, 25 Jun 2023 20:38:32 +0200 Subject: [PATCH 1757/2172] avcodec/mpeg12dec: ignore picture start code in extradata for AVID mpeg2 files AVID IMX MPEG2 files in MOV seems to have extradata like this: 00000000: 0000 0018 4143 4c52 4143 4c52 3030 3031 ....ACLRACLR0001 00000010: 0000 0001 0000 0000 ........ Signed-off-by: Marton Balint --- libavcodec/mpeg12dec.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/libavcodec/mpeg12dec.c b/libavcodec/mpeg12dec.c index 27c862ffb22..27b45c6fc4a 100644 --- a/libavcodec/mpeg12dec.c +++ b/libavcodec/mpeg12dec.c @@ -2522,6 +2522,11 @@ static int decode_chunks(AVCodecContext *avctx, AVFrame *picture, } picture_start_code_seen = 1; + if (buf == avctx->extradata && avctx->codec_tag == AV_RL32("AVmp")) { + av_log(avctx, AV_LOG_WARNING, "ignoring picture start code in AVmp extradata\n"); + break; + } + if (s2->width <= 0 || s2->height <= 0) { av_log(avctx, AV_LOG_ERROR, "Invalid frame dimensions %dx%d.\n", s2->width, s2->height); From 79f41a0760780d997ef02e56cec0db72303bed0a Mon Sep 17 00:00:00 2001 From: QiTong Li Date: Wed, 5 Jul 2023 11:36:14 +0800 Subject: [PATCH 1758/2172] fftools/ffplay: fix typo in frame_queue_destory Not sure if the function naming frame_queue_destory is intended because "destory" is not really a word. Changing it to "destroy" makes more sense. Signed-off-by: QiTong Li Signed-off-by: Marton Balint --- fftools/ffplay.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/fftools/ffplay.c b/fftools/ffplay.c index 663f61d8b2e..51cde0d208b 100644 --- a/fftools/ffplay.c +++ b/fftools/ffplay.c @@ -696,7 +696,7 @@ static int frame_queue_init(FrameQueue *f, PacketQueue *pktq, int max_size, int return 0; } -static void frame_queue_destory(FrameQueue *f) +static void frame_queue_destroy(FrameQueue *f) { int i; for (i = 0; i < f->max_size; i++) { @@ -1252,9 +1252,9 @@ static void stream_close(VideoState *is) packet_queue_destroy(&is->subtitleq); /* free all pictures */ - frame_queue_destory(&is->pictq); - frame_queue_destory(&is->sampq); - frame_queue_destory(&is->subpq); + frame_queue_destroy(&is->pictq); + frame_queue_destroy(&is->sampq); + frame_queue_destroy(&is->subpq); SDL_DestroyCond(is->continue_read_thread); sws_freeContext(is->sub_convert_ctx); av_free(is->filename); From 83c0f7b046d0efbfa4ac08b51e3c1500071a857f Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt Date: Thu, 6 Jul 2023 22:31:33 +0200 Subject: [PATCH 1759/2172] avformat/evcdec: Avoid nonsense casts For uint8_t buf[EVC_NALU_LENGTH_PREFIX_SIZE], &buf still points to the beginning of buf, but it is of type "pointer to array of EVC_NALU_LENGTH_PREFIX_SIZE uint8_t" (i.e. pointer arithmetic would operate on blocks of size EVC_NALU_LENGTH_PREFIX_SIZE). This is of course a different type than uint8_t*, which is why there have been casts in evc_read_packet(). But these are unnecessary if one justs removes the unnecessary address-of operator. Reviewed-by: James Almer Signed-off-by: Andreas Rheinhardt --- libavformat/evcdec.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/libavformat/evcdec.c b/libavformat/evcdec.c index 73aab6c52f3..9e09f8d2647 100644 --- a/libavformat/evcdec.c +++ b/libavformat/evcdec.c @@ -65,7 +65,7 @@ static int annexb_probe(const AVProbeData *p) int nalu_type; size_t nalu_size; int got_sps = 0, got_pps = 0, got_idr = 0, got_nonidr = 0; - unsigned char *bits = (unsigned char *)p->buf; + const unsigned char *bits = p->buf; int bytes_to_read = p->buf_size; while (bytes_to_read > EVC_NALU_LENGTH_PREFIX_SIZE) { @@ -159,11 +159,11 @@ static int evc_read_packet(AVFormatContext *s, AVPacket *pkt) if (ret < 0) return ret; - ret = avio_read(s->pb, (unsigned char *)&buf, EVC_NALU_LENGTH_PREFIX_SIZE); + ret = avio_read(s->pb, buf, EVC_NALU_LENGTH_PREFIX_SIZE); if (ret < 0) return ret; - nalu_size = evc_read_nal_unit_length((const uint8_t *)&buf, EVC_NALU_LENGTH_PREFIX_SIZE); + nalu_size = evc_read_nal_unit_length(buf, EVC_NALU_LENGTH_PREFIX_SIZE); if (!nalu_size || nalu_size > INT_MAX) return AVERROR_INVALIDDATA; From 5e7b5b0090bdf68e0897fe55ee657fdccc0cbca2 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Tue, 20 Jun 2023 12:29:50 +0200 Subject: [PATCH 1760/2172] lavc: add a header for internal generic-layer APIs The goal is to distinguish between APIs provided by the generic layer to individual codecs and APIs internal to the generic layer. Start by moving ff_{decode,encode}_receive_frame() and ff_{decode,encode}_preinit() into this new header, as those functions are called from generic code and should not be visible to individual codecs. --- libavcodec/avcodec.c | 1 + libavcodec/avcodec_internal.h | 53 +++++++++++++++++++++++++++++++++++ libavcodec/decode.c | 1 + libavcodec/decode.h | 11 -------- libavcodec/encode.c | 1 + libavcodec/encode.h | 11 -------- 6 files changed, 56 insertions(+), 22 deletions(-) create mode 100644 libavcodec/avcodec_internal.h diff --git a/libavcodec/avcodec.c b/libavcodec/avcodec.c index db8226f9b3d..638cb55146b 100644 --- a/libavcodec/avcodec.c +++ b/libavcodec/avcodec.c @@ -34,6 +34,7 @@ #include "libavutil/opt.h" #include "libavutil/thread.h" #include "avcodec.h" +#include "avcodec_internal.h" #include "bsf.h" #include "codec_internal.h" #include "decode.h" diff --git a/libavcodec/avcodec_internal.h b/libavcodec/avcodec_internal.h new file mode 100644 index 00000000000..be60a36644f --- /dev/null +++ b/libavcodec/avcodec_internal.h @@ -0,0 +1,53 @@ +/* + * 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 + */ + +/* + * APIs internal to the generic codec layer. + * + * MUST NOT be included by individual encoders or decoders. + */ + +#ifndef AVCODEC_AVCODEC_INTERNAL_H +#define AVCODEC_AVCODEC_INTERNAL_H + +struct AVCodecContext; +struct AVFrame; + +/** + * avcodec_receive_frame() implementation for decoders. + */ +int ff_decode_receive_frame(struct AVCodecContext *avctx, struct AVFrame *frame); + +/** + * avcodec_receive_frame() implementation for encoders. + */ +int ff_encode_receive_frame(struct AVCodecContext *avctx, struct AVFrame *frame); + +/* + * Perform encoder initialization and validation. + * Called when opening the encoder, before the FFCodec.init() call. + */ +int ff_encode_preinit(struct AVCodecContext *avctx); + +/** + * Perform decoder initialization and validation. + * Called when opening the decoder, before the FFCodec.init() call. + */ +int ff_decode_preinit(struct AVCodecContext *avctx); + +#endif // AVCODEC_AVCODEC_INTERNAL_H diff --git a/libavcodec/decode.c b/libavcodec/decode.c index 6ee2c85a750..336635f772c 100644 --- a/libavcodec/decode.c +++ b/libavcodec/decode.c @@ -41,6 +41,7 @@ #include "libavutil/opt.h" #include "avcodec.h" +#include "avcodec_internal.h" #include "bytestream.h" #include "bsf.h" #include "codec_internal.h" diff --git a/libavcodec/decode.h b/libavcodec/decode.h index aaa29bc7f52..2b9fe59907a 100644 --- a/libavcodec/decode.h +++ b/libavcodec/decode.h @@ -53,11 +53,6 @@ typedef struct FrameDecodeData { void (*hwaccel_priv_free)(void *priv); } FrameDecodeData; -/** - * avcodec_receive_frame() implementation for decoders. - */ -int ff_decode_receive_frame(AVCodecContext *avctx, AVFrame *frame); - /** * Called by decoders to get the next packet for decoding. * @@ -99,12 +94,6 @@ int ff_attach_decode_data(AVFrame *frame); */ int ff_copy_palette(void *dst, const AVPacket *src, void *logctx); -/** - * Perform decoder initialization and validation. - * Called when opening the decoder, before the FFCodec.init() call. - */ -int ff_decode_preinit(AVCodecContext *avctx); - /** * Check that the provided frame dimensions are valid and set them on the codec * context. diff --git a/libavcodec/encode.c b/libavcodec/encode.c index ab5f889615e..3a016b14c1a 100644 --- a/libavcodec/encode.c +++ b/libavcodec/encode.c @@ -27,6 +27,7 @@ #include "libavutil/samplefmt.h" #include "avcodec.h" +#include "avcodec_internal.h" #include "codec_internal.h" #include "encode.h" #include "frame_thread_encoder.h" diff --git a/libavcodec/encode.h b/libavcodec/encode.h index 26a3304045b..dfaab7c9760 100644 --- a/libavcodec/encode.h +++ b/libavcodec/encode.h @@ -26,11 +26,6 @@ #include "avcodec.h" #include "packet.h" -/** - * avcodec_receive_frame() implementation for encoders. - */ -int ff_encode_receive_frame(AVCodecContext *avctx, AVFrame *frame); - /** * Called by encoders to get the next frame for encoding. * @@ -75,12 +70,6 @@ int ff_alloc_packet(AVCodecContext *avctx, AVPacket *avpkt, int64_t size); int ff_encode_reordered_opaque(AVCodecContext *avctx, AVPacket *pkt, const AVFrame *frame); -/* - * Perform encoder initialization and validation. - * Called when opening the encoder, before the FFCodec.init() call. - */ -int ff_encode_preinit(AVCodecContext *avctx); - int ff_encode_encode_cb(AVCodecContext *avctx, AVPacket *avpkt, AVFrame *frame, int *got_packet); From 6ff27024b8dc2a0f3ce4277b341401b5137a1990 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Tue, 20 Jun 2023 12:52:49 +0200 Subject: [PATCH 1761/2172] lavc/avcodec: split flushing into decode- and encode-specific functions Will allow making some state private to encoding/decoding in the future. --- libavcodec/avcodec.c | 17 +++-------------- libavcodec/avcodec_internal.h | 3 +++ libavcodec/decode.c | 15 +++++++++++++++ libavcodec/encode.c | 10 ++++++++++ 4 files changed, 31 insertions(+), 14 deletions(-) diff --git a/libavcodec/avcodec.c b/libavcodec/avcodec.c index 638cb55146b..c01dac2049f 100644 --- a/libavcodec/avcodec.c +++ b/libavcodec/avcodec.c @@ -383,23 +383,12 @@ void avcodec_flush_buffers(AVCodecContext *avctx) "that doesn't support it\n"); return; } - if (avci->in_frame) - av_frame_unref(avci->in_frame); - if (avci->recon_frame) - av_frame_unref(avci->recon_frame); - } else { - av_packet_unref(avci->last_pkt_props); - av_packet_unref(avci->in_pkt); - - avctx->pts_correction_last_pts = - avctx->pts_correction_last_dts = INT64_MIN; - - av_bsf_flush(avci->bsf); - } + ff_encode_flush_buffers(avctx); + } else + ff_decode_flush_buffers(avctx); avci->draining = 0; avci->draining_done = 0; - avci->nb_draining_errors = 0; av_frame_unref(avci->buffer_frame); av_packet_unref(avci->buffer_pkt); diff --git a/libavcodec/avcodec_internal.h b/libavcodec/avcodec_internal.h index be60a36644f..6ffe575c3e7 100644 --- a/libavcodec/avcodec_internal.h +++ b/libavcodec/avcodec_internal.h @@ -50,4 +50,7 @@ int ff_encode_preinit(struct AVCodecContext *avctx); */ int ff_decode_preinit(struct AVCodecContext *avctx); +void ff_decode_flush_buffers(struct AVCodecContext *avctx); +void ff_encode_flush_buffers(struct AVCodecContext *avctx); + #endif // AVCODEC_AVCODEC_INTERNAL_H diff --git a/libavcodec/decode.c b/libavcodec/decode.c index 336635f772c..01ac35bf346 100644 --- a/libavcodec/decode.c +++ b/libavcodec/decode.c @@ -1740,3 +1740,18 @@ AVBufferRef *ff_hwaccel_frame_priv_alloc(AVCodecContext *avctx, return ref; } + +void ff_decode_flush_buffers(AVCodecContext *avctx) +{ + AVCodecInternal *avci = avctx->internal; + + av_packet_unref(avci->last_pkt_props); + av_packet_unref(avci->in_pkt); + + avctx->pts_correction_last_pts = + avctx->pts_correction_last_dts = INT64_MIN; + + av_bsf_flush(avci->bsf); + + avci->nb_draining_errors = 0; +} diff --git a/libavcodec/encode.c b/libavcodec/encode.c index 3a016b14c1a..0b1947c7817 100644 --- a/libavcodec/encode.c +++ b/libavcodec/encode.c @@ -785,3 +785,13 @@ int ff_encode_receive_frame(AVCodecContext *avctx, AVFrame *frame) av_frame_move_ref(frame, avci->recon_frame); return 0; } + +void ff_encode_flush_buffers(AVCodecContext *avctx) +{ + AVCodecInternal *avci = avctx->internal; + + if (avci->in_frame) + av_frame_unref(avci->in_frame); + if (avci->recon_frame) + av_frame_unref(avci->recon_frame); +} From 21de4db402cc40734b30685f9435538e7d35ef9a Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Tue, 20 Jun 2023 12:53:48 +0200 Subject: [PATCH 1762/2172] lavc: reindent after previous commit --- libavcodec/decode.c | 10 +++++----- libavcodec/encode.c | 8 ++++---- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/libavcodec/decode.c b/libavcodec/decode.c index 01ac35bf346..3115282923e 100644 --- a/libavcodec/decode.c +++ b/libavcodec/decode.c @@ -1745,13 +1745,13 @@ void ff_decode_flush_buffers(AVCodecContext *avctx) { AVCodecInternal *avci = avctx->internal; - av_packet_unref(avci->last_pkt_props); - av_packet_unref(avci->in_pkt); + av_packet_unref(avci->last_pkt_props); + av_packet_unref(avci->in_pkt); - avctx->pts_correction_last_pts = - avctx->pts_correction_last_dts = INT64_MIN; + avctx->pts_correction_last_pts = + avctx->pts_correction_last_dts = INT64_MIN; - av_bsf_flush(avci->bsf); + av_bsf_flush(avci->bsf); avci->nb_draining_errors = 0; } diff --git a/libavcodec/encode.c b/libavcodec/encode.c index 0b1947c7817..26208104761 100644 --- a/libavcodec/encode.c +++ b/libavcodec/encode.c @@ -790,8 +790,8 @@ void ff_encode_flush_buffers(AVCodecContext *avctx) { AVCodecInternal *avci = avctx->internal; - if (avci->in_frame) - av_frame_unref(avci->in_frame); - if (avci->recon_frame) - av_frame_unref(avci->recon_frame); + if (avci->in_frame) + av_frame_unref(avci->in_frame); + if (avci->recon_frame) + av_frame_unref(avci->recon_frame); } From f2fb882b3f0046493e40306724a6d855b12e2121 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Tue, 20 Jun 2023 13:02:59 +0200 Subject: [PATCH 1763/2172] lavc: add generic-decode-layer private data Move AVCodecInternal.nb_draining_errors to it, should should not be visible outside of decode.c. --- libavcodec/avcodec.c | 4 +++- libavcodec/avcodec_internal.h | 2 ++ libavcodec/decode.c | 21 +++++++++++++++++++-- libavcodec/internal.h | 3 --- libavcodec/pthread_frame.c | 3 ++- 5 files changed, 26 insertions(+), 7 deletions(-) diff --git a/libavcodec/avcodec.c b/libavcodec/avcodec.c index c01dac2049f..aef2edce325 100644 --- a/libavcodec/avcodec.c +++ b/libavcodec/avcodec.c @@ -150,7 +150,9 @@ int attribute_align_arg avcodec_open2(AVCodecContext *avctx, const AVCodec *code if (avctx->extradata_size < 0 || avctx->extradata_size >= FF_MAX_EXTRADATA_SIZE) return AVERROR(EINVAL); - avci = av_mallocz(sizeof(*avci)); + avci = av_codec_is_decoder(codec) ? + ff_decode_internal_alloc() : + av_mallocz(sizeof(AVCodecInternal)); if (!avci) { ret = AVERROR(ENOMEM); goto end; diff --git a/libavcodec/avcodec_internal.h b/libavcodec/avcodec_internal.h index 6ffe575c3e7..f52f91e07c4 100644 --- a/libavcodec/avcodec_internal.h +++ b/libavcodec/avcodec_internal.h @@ -53,4 +53,6 @@ int ff_decode_preinit(struct AVCodecContext *avctx); void ff_decode_flush_buffers(struct AVCodecContext *avctx); void ff_encode_flush_buffers(struct AVCodecContext *avctx); +struct AVCodecInternal *ff_decode_internal_alloc(void); + #endif // AVCODEC_AVCODEC_INTERNAL_H diff --git a/libavcodec/decode.c b/libavcodec/decode.c index 3115282923e..acec9860a58 100644 --- a/libavcodec/decode.c +++ b/libavcodec/decode.c @@ -50,6 +50,18 @@ #include "internal.h" #include "thread.h" +typedef struct DecodeContext { + AVCodecInternal avci; + + /* to prevent infinite loop on errors when draining */ + int nb_draining_errors; +} DecodeContext; + +static DecodeContext *decode_ctx(AVCodecInternal *avci) +{ + return (DecodeContext *)avci; +} + static int apply_param_change(AVCodecContext *avctx, const AVPacket *avpkt) { int ret; @@ -439,7 +451,7 @@ FF_ENABLE_DEPRECATION_WARNINGS int nb_errors_max = 20 + (HAVE_THREADS && avctx->active_thread_type & FF_THREAD_FRAME ? avctx->thread_count : 1); - if (avci->nb_draining_errors++ >= nb_errors_max) { + if (decode_ctx(avci)->nb_draining_errors++ >= nb_errors_max) { av_log(avctx, AV_LOG_ERROR, "Too many errors when draining, this is a bug. " "Stop draining and force EOF.\n"); avci->draining_done = 1; @@ -1753,5 +1765,10 @@ void ff_decode_flush_buffers(AVCodecContext *avctx) av_bsf_flush(avci->bsf); - avci->nb_draining_errors = 0; + decode_ctx(avci)->nb_draining_errors = 0; +} + +AVCodecInternal *ff_decode_internal_alloc(void) +{ + return av_mallocz(sizeof(DecodeContext)); } diff --git a/libavcodec/internal.h b/libavcodec/internal.h index dceae182c0e..0c1f0b82ead 100644 --- a/libavcodec/internal.h +++ b/libavcodec/internal.h @@ -148,9 +148,6 @@ typedef struct AVCodecInternal { AVFrame *buffer_frame; int draining_done; - /* to prevent infinite loop on errors when draining */ - int nb_draining_errors; - /* used when avctx flag AV_CODEC_FLAG_DROPCHANGED is set */ int changed_frames_dropped; int initial_format; diff --git a/libavcodec/pthread_frame.c b/libavcodec/pthread_frame.c index 008f3da43b2..bc305f561f9 100644 --- a/libavcodec/pthread_frame.c +++ b/libavcodec/pthread_frame.c @@ -28,6 +28,7 @@ #include #include "avcodec.h" +#include "avcodec_internal.h" #include "codec_internal.h" #include "decode.h" #include "hwconfig.h" @@ -815,7 +816,7 @@ static av_cold int init_thread(PerThreadContext *p, int *threads_to_free, p->parent = fctx; p->avctx = copy; - copy->internal = av_mallocz(sizeof(*copy->internal)); + copy->internal = ff_decode_internal_alloc(); if (!copy->internal) return AVERROR(ENOMEM); copy->internal->thread_ctx = p; From 232700154cad24f110cd4fb6ac3b2d3c254e4512 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Tue, 20 Jun 2023 13:24:49 +0200 Subject: [PATCH 1764/2172] lavc: add generic-encode-layer private data Move AVCodecInternal.intra_only_flag to it, should should not be visible outside of encode.c. --- libavcodec/avcodec.c | 2 +- libavcodec/avcodec_internal.h | 1 + libavcodec/encode.c | 26 ++++++++++++++++++++++++-- libavcodec/internal.h | 7 ------- 4 files changed, 26 insertions(+), 10 deletions(-) diff --git a/libavcodec/avcodec.c b/libavcodec/avcodec.c index aef2edce325..8ccc6102272 100644 --- a/libavcodec/avcodec.c +++ b/libavcodec/avcodec.c @@ -152,7 +152,7 @@ int attribute_align_arg avcodec_open2(AVCodecContext *avctx, const AVCodec *code avci = av_codec_is_decoder(codec) ? ff_decode_internal_alloc() : - av_mallocz(sizeof(AVCodecInternal)); + ff_encode_internal_alloc(); if (!avci) { ret = AVERROR(ENOMEM); goto end; diff --git a/libavcodec/avcodec_internal.h b/libavcodec/avcodec_internal.h index f52f91e07c4..9b93ff3d819 100644 --- a/libavcodec/avcodec_internal.h +++ b/libavcodec/avcodec_internal.h @@ -54,5 +54,6 @@ void ff_decode_flush_buffers(struct AVCodecContext *avctx); void ff_encode_flush_buffers(struct AVCodecContext *avctx); struct AVCodecInternal *ff_decode_internal_alloc(void); +struct AVCodecInternal *ff_encode_internal_alloc(void); #endif // AVCODEC_AVCODEC_INTERNAL_H diff --git a/libavcodec/encode.c b/libavcodec/encode.c index 26208104761..6da5d86ea0a 100644 --- a/libavcodec/encode.c +++ b/libavcodec/encode.c @@ -33,6 +33,22 @@ #include "frame_thread_encoder.h" #include "internal.h" +typedef struct EncodeContext { + AVCodecInternal avci; + + /** + * This is set to AV_PKT_FLAG_KEY for encoders that encode intra-only + * formats (i.e. whose codec descriptor has AV_CODEC_PROP_INTRA_ONLY set). + * This is used to set said flag generically for said encoders. + */ + int intra_only_flag; +} EncodeContext; + +static EncodeContext *encode_ctx(AVCodecInternal *avci) +{ + return (EncodeContext*)avci; +} + int ff_alloc_packet(AVCodecContext *avctx, AVPacket *avpkt, int64_t size) { if (size < 0 || size > INT_MAX - AV_INPUT_BUFFER_PADDING_SIZE) { @@ -372,7 +388,7 @@ static int encode_receive_packet_internal(AVCodecContext *avctx, AVPacket *avpkt } else ret = encode_simple_receive_packet(avctx, avpkt); if (ret >= 0) - avpkt->flags |= avci->intra_only_flag; + avpkt->flags |= encode_ctx(avci)->intra_only_flag; if (ret == AVERROR_EOF) avci->draining_done = 1; @@ -680,6 +696,7 @@ static int encode_preinit_audio(AVCodecContext *avctx) int ff_encode_preinit(AVCodecContext *avctx) { AVCodecInternal *avci = avctx->internal; + EncodeContext *ec = encode_ctx(avci); int ret = 0; if (avctx->time_base.num <= 0 || avctx->time_base.den <= 0) { @@ -710,7 +727,7 @@ int ff_encode_preinit(AVCodecContext *avctx) avctx->rc_initial_buffer_occupancy = avctx->rc_buffer_size * 3LL / 4; if (avctx->codec_descriptor->props & AV_CODEC_PROP_INTRA_ONLY) - avctx->internal->intra_only_flag = AV_PKT_FLAG_KEY; + ec->intra_only_flag = AV_PKT_FLAG_KEY; if (ffcodec(avctx->codec)->cb_type == FF_CODEC_CB_TYPE_ENCODE) { avci->in_frame = av_frame_alloc(); @@ -795,3 +812,8 @@ void ff_encode_flush_buffers(AVCodecContext *avctx) if (avci->recon_frame) av_frame_unref(avci->recon_frame); } + +AVCodecInternal *ff_encode_internal_alloc(void) +{ + return av_mallocz(sizeof(EncodeContext)); +} diff --git a/libavcodec/internal.h b/libavcodec/internal.h index 0c1f0b82ead..497cd77f230 100644 --- a/libavcodec/internal.h +++ b/libavcodec/internal.h @@ -95,13 +95,6 @@ typedef struct AVCodecInternal { uint8_t *byte_buffer; unsigned int byte_buffer_size; - /** - * This is set to AV_PKT_FLAG_KEY for encoders that encode intra-only - * formats (i.e. whose codec descriptor has AV_CODEC_PROP_INTRA_ONLY set). - * This is used to set said flag generically for said encoders. - */ - int intra_only_flag; - void *frame_thread_encoder; /** From fd915dc1da5f2dc7760dfd5f514c82c22f0597f8 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Tue, 20 Jun 2023 13:26:32 +0200 Subject: [PATCH 1765/2172] lavc: move AVCodecInternal.last_audio_frame to EncodeContext It does not need to be visible outside of encode.c. --- libavcodec/encode.c | 13 ++++++++++--- libavcodec/internal.h | 6 ------ 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/libavcodec/encode.c b/libavcodec/encode.c index 6da5d86ea0a..58eab5b0015 100644 --- a/libavcodec/encode.c +++ b/libavcodec/encode.c @@ -42,6 +42,12 @@ typedef struct EncodeContext { * This is used to set said flag generically for said encoders. */ int intra_only_flag; + + /** + * An audio frame with less than required samples has been submitted (and + * potentially padded with silence). Reject all subsequent frames. + */ + int last_audio_frame; } EncodeContext; static EncodeContext *encode_ctx(AVCodecInternal *avci) @@ -174,7 +180,7 @@ static int pad_last_frame(AVCodecContext *s, AVFrame *frame, const AVFrame *src, fail: av_frame_unref(frame); - s->internal->last_audio_frame = 0; + encode_ctx(s->internal)->last_audio_frame = 0; return ret; } @@ -446,6 +452,7 @@ static int encode_generate_icc_profile(av_unused AVCodecContext *c, av_unused AV static int encode_send_frame_internal(AVCodecContext *avctx, const AVFrame *src) { AVCodecInternal *avci = avctx->internal; + EncodeContext *ec = encode_ctx(avci); AVFrame *dst = avci->buffer_frame; int ret; @@ -458,7 +465,7 @@ static int encode_send_frame_internal(AVCodecContext *avctx, const AVFrame *src) /* check for valid frame size */ if (!(avctx->codec->capabilities & AV_CODEC_CAP_VARIABLE_FRAME_SIZE)) { /* if we already got an undersized frame, that must have been the last */ - if (avctx->internal->last_audio_frame) { + if (ec->last_audio_frame) { av_log(avctx, AV_LOG_ERROR, "frame_size (%d) was not respected for a non-last frame\n", avctx->frame_size); return AVERROR(EINVAL); } @@ -467,7 +474,7 @@ static int encode_send_frame_internal(AVCodecContext *avctx, const AVFrame *src) return AVERROR(EINVAL); } if (src->nb_samples < avctx->frame_size) { - avctx->internal->last_audio_frame = 1; + ec->last_audio_frame = 1; if (!(avctx->codec->capabilities & AV_CODEC_CAP_SMALL_LAST_FRAME)) { int pad_samples = avci->pad_samples ? avci->pad_samples : avctx->frame_size; int out_samples = (src->nb_samples + pad_samples - 1) / pad_samples * pad_samples; diff --git a/libavcodec/internal.h b/libavcodec/internal.h index 497cd77f230..868dd46b489 100644 --- a/libavcodec/internal.h +++ b/libavcodec/internal.h @@ -56,12 +56,6 @@ typedef struct AVCodecInternal { */ int is_copy; - /** - * An audio frame with less than required samples has been submitted (and - * potentially padded with silence). Reject all subsequent frames. - */ - int last_audio_frame; - /** * Audio encoders can set this flag during init to indicate that they * want the small last frame to be padded to a multiple of pad_samples. From c4332dfda934ae7f3fee1b4c09cb197c00519f92 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Tue, 20 Jun 2023 15:40:40 +0200 Subject: [PATCH 1766/2172] lavc/decode: track whether the caller started draining with a separate flag Decoding pipeline has multiple stages, some of which may have their own delay (e.g. bitstream filters). The code currently uses AVCodecInternal.draining to track all of them, but they do not have to all be in sync. --- libavcodec/decode.c | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/libavcodec/decode.c b/libavcodec/decode.c index acec9860a58..47714a93936 100644 --- a/libavcodec/decode.c +++ b/libavcodec/decode.c @@ -55,6 +55,11 @@ typedef struct DecodeContext { /* to prevent infinite loop on errors when draining */ int nb_draining_errors; + + /** + * The caller has submitted a NULL packet on input. + */ + int draining_started; } DecodeContext; static DecodeContext *decode_ctx(AVCodecInternal *avci) @@ -626,12 +631,13 @@ FF_ENABLE_DEPRECATION_WARNINGS int attribute_align_arg avcodec_send_packet(AVCodecContext *avctx, const AVPacket *avpkt) { AVCodecInternal *avci = avctx->internal; + DecodeContext *dc = decode_ctx(avci); int ret; if (!avcodec_is_open(avctx) || !av_codec_is_decoder(avctx->codec)) return AVERROR(EINVAL); - if (avctx->internal->draining) + if (dc->draining_started) return AVERROR_EOF; if (avpkt && !avpkt->size && avpkt->data) @@ -642,7 +648,8 @@ int attribute_align_arg avcodec_send_packet(AVCodecContext *avctx, const AVPacke ret = av_packet_ref(avci->buffer_pkt, avpkt); if (ret < 0) return ret; - } + } else + dc->draining_started = 1; ret = av_bsf_send_packet(avci->bsf, avci->buffer_pkt); if (ret < 0) { @@ -1756,6 +1763,7 @@ AVBufferRef *ff_hwaccel_frame_priv_alloc(AVCodecContext *avctx, void ff_decode_flush_buffers(AVCodecContext *avctx) { AVCodecInternal *avci = avctx->internal; + DecodeContext *dc = decode_ctx(avci); av_packet_unref(avci->last_pkt_props); av_packet_unref(avci->in_pkt); @@ -1765,7 +1773,8 @@ void ff_decode_flush_buffers(AVCodecContext *avctx) av_bsf_flush(avci->bsf); - decode_ctx(avci)->nb_draining_errors = 0; + dc->nb_draining_errors = 0; + dc->draining_started = 0; } AVCodecInternal *ff_decode_internal_alloc(void) From 0f957cfba2dc83c9cfa9dc494052836ebbbdfd78 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Sat, 24 Jun 2023 13:10:08 +0200 Subject: [PATCH 1767/2172] lavc/bsf: move IS_EMPTY() to packet_internal() It will be useful in other places. --- libavcodec/bsf.c | 11 +++++------ libavcodec/packet_internal.h | 2 ++ 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/libavcodec/bsf.c b/libavcodec/bsf.c index 42cc1b5ab0c..1e710f7d4af 100644 --- a/libavcodec/bsf.c +++ b/libavcodec/bsf.c @@ -31,8 +31,7 @@ #include "bsf_internal.h" #include "codec_desc.h" #include "codec_par.h" - -#define IS_EMPTY(pkt) (!(pkt)->data && !(pkt)->side_data_elems) +#include "packet_internal.h" static av_always_inline const FFBitStreamFilter *ff_bsf(const AVBitStreamFilter *bsf) { @@ -205,7 +204,7 @@ int av_bsf_send_packet(AVBSFContext *ctx, AVPacket *pkt) FFBSFContext *const bsfi = ffbsfcontext(ctx); int ret; - if (!pkt || IS_EMPTY(pkt)) { + if (!pkt || AVPACKET_IS_EMPTY(pkt)) { if (pkt) av_packet_unref(pkt); bsfi->eof = 1; @@ -217,7 +216,7 @@ int av_bsf_send_packet(AVBSFContext *ctx, AVPacket *pkt) return AVERROR(EINVAL); } - if (!IS_EMPTY(bsfi->buffer_pkt)) + if (!AVPACKET_IS_EMPTY(bsfi->buffer_pkt)) return AVERROR(EAGAIN); ret = av_packet_make_refcounted(pkt); @@ -241,7 +240,7 @@ int ff_bsf_get_packet(AVBSFContext *ctx, AVPacket **pkt) if (bsfi->eof) return AVERROR_EOF; - if (IS_EMPTY(bsfi->buffer_pkt)) + if (AVPACKET_IS_EMPTY(bsfi->buffer_pkt)) return AVERROR(EAGAIN); tmp_pkt = av_packet_alloc(); @@ -261,7 +260,7 @@ int ff_bsf_get_packet_ref(AVBSFContext *ctx, AVPacket *pkt) if (bsfi->eof) return AVERROR_EOF; - if (IS_EMPTY(bsfi->buffer_pkt)) + if (AVPACKET_IS_EMPTY(bsfi->buffer_pkt)) return AVERROR(EAGAIN); av_packet_move_ref(pkt, bsfi->buffer_pkt); diff --git a/libavcodec/packet_internal.h b/libavcodec/packet_internal.h index 92a0d4e6d53..52fa6d9be90 100644 --- a/libavcodec/packet_internal.h +++ b/libavcodec/packet_internal.h @@ -23,6 +23,8 @@ #include "packet.h" +#define AVPACKET_IS_EMPTY(pkt) (!(pkt)->data && !(pkt)->side_data_elems) + typedef struct PacketListEntry { struct PacketListEntry *next; AVPacket pkt; From 69516ab3e917a6e91d26e38d04183c60fd71cbab Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Tue, 20 Jun 2023 16:02:34 +0200 Subject: [PATCH 1768/2172] lavc/decode: move submitting input packets to bitstream filters Do it from ff_decode_get_packet() rather than from avcodec_send_packet(). This way all nontrivial stages of the decoding pipeline (i.e. other than just placing a packet at its entrance) are pull-based rather than a mix of push an pull. --- libavcodec/decode.c | 37 +++++++++++++++++++++++++++---------- 1 file changed, 27 insertions(+), 10 deletions(-) diff --git a/libavcodec/decode.c b/libavcodec/decode.c index 47714a93936..89c3c2a48dc 100644 --- a/libavcodec/decode.c +++ b/libavcodec/decode.c @@ -48,6 +48,7 @@ #include "decode.h" #include "hwconfig.h" #include "internal.h" +#include "packet_internal.h" #include "thread.h" typedef struct DecodeContext { @@ -200,14 +201,11 @@ static int decode_bsfs_init(AVCodecContext *avctx) return ret; } -int ff_decode_get_packet(AVCodecContext *avctx, AVPacket *pkt) +static int decode_get_packet(AVCodecContext *avctx, AVPacket *pkt) { AVCodecInternal *avci = avctx->internal; int ret; - if (avci->draining) - return AVERROR_EOF; - ret = av_bsf_receive_packet(avci->bsf, pkt); if (ret == AVERROR_EOF) avci->draining = 1; @@ -230,6 +228,31 @@ int ff_decode_get_packet(AVCodecContext *avctx, AVPacket *pkt) return ret; } +int ff_decode_get_packet(AVCodecContext *avctx, AVPacket *pkt) +{ + AVCodecInternal *avci = avctx->internal; + DecodeContext *dc = decode_ctx(avci); + + if (avci->draining) + return AVERROR_EOF; + + while (1) { + int ret = decode_get_packet(avctx, pkt); + if (ret == AVERROR(EAGAIN) && + (!AVPACKET_IS_EMPTY(avci->buffer_pkt) || dc->draining_started)) { + ret = av_bsf_send_packet(avci->bsf, avci->buffer_pkt); + if (ret < 0) { + av_packet_unref(avci->buffer_pkt); + return ret; + } + + continue; + } + + return ret; + } +} + /** * Attempt to guess proper monotonic timestamps for decoded video frames * which might have incorrect times. Input timestamps may wrap around, in @@ -651,12 +674,6 @@ int attribute_align_arg avcodec_send_packet(AVCodecContext *avctx, const AVPacke } else dc->draining_started = 1; - ret = av_bsf_send_packet(avci->bsf, avci->buffer_pkt); - if (ret < 0) { - av_packet_unref(avci->buffer_pkt); - return ret; - } - if (!avci->buffer_frame->buf[0]) { ret = decode_receive_frame_internal(avctx, avci->buffer_frame); if (ret < 0 && ret != AVERROR(EAGAIN) && ret != AVERROR_EOF) From b54603a26a53bfd89fd19b97308e64f4fbeef4b3 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Tue, 20 Jun 2023 16:10:10 +0200 Subject: [PATCH 1769/2172] lavc/decode: do not perform decoding when sending draining packets This way decoding errors will not be returned when the user starts draining the decoder, avoiding confusion over whether draining did or did not start. Fixes failures of fate-h264-attachment-631 for certain numbers of frame threads (e.g. 5). --- libavcodec/decode.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavcodec/decode.c b/libavcodec/decode.c index 89c3c2a48dc..269633ce106 100644 --- a/libavcodec/decode.c +++ b/libavcodec/decode.c @@ -674,7 +674,7 @@ int attribute_align_arg avcodec_send_packet(AVCodecContext *avctx, const AVPacke } else dc->draining_started = 1; - if (!avci->buffer_frame->buf[0]) { + if (!avci->buffer_frame->buf[0] && !dc->draining_started) { ret = decode_receive_frame_internal(avctx, avci->buffer_frame); if (ret < 0 && ret != AVERROR(EAGAIN) && ret != AVERROR_EOF) return ret; From 9b625ab6792f07fb60b3ce9f2cf5933b2fb0fa1c Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Wed, 28 Jun 2023 14:17:18 +0200 Subject: [PATCH 1770/2172] lavc/dvdec: export bitrate Changes the result of fate-mxf-probe-dv25, where the bitrate is now exported. Also changes the result of fate-bsf-dv-error-marker, where the exported bitrate is now different. Note that the codec layer bitrate does not match the container bitrate, because container timing is 25fps, while the DV profile is 50. --- libavcodec/dvdec.c | 3 +++ tests/fate/dvvideo.mak | 2 +- tests/ref/fate/mxf-probe-dv25 | 2 +- 3 files changed, 5 insertions(+), 2 deletions(-) diff --git a/libavcodec/dvdec.c b/libavcodec/dvdec.c index 750e25a4af7..c57578a2089 100644 --- a/libavcodec/dvdec.c +++ b/libavcodec/dvdec.c @@ -650,6 +650,9 @@ static int dvvideo_decode_frame(AVCodecContext *avctx, AVFrame *frame, frame->pict_type = AV_PICTURE_TYPE_I; avctx->pix_fmt = s->sys->pix_fmt; avctx->framerate = av_inv_q(s->sys->time_base); + avctx->bit_rate = av_rescale_q(s->sys->frame_size, + (AVRational) { 8, 1 }, + s->sys->time_base); ret = ff_set_dimensions(avctx, s->sys->width, s->sys->height); if (ret < 0) diff --git a/tests/fate/dvvideo.mak b/tests/fate/dvvideo.mak index 24e50ca357c..33686d7762b 100644 --- a/tests/fate/dvvideo.mak +++ b/tests/fate/dvvideo.mak @@ -1,7 +1,7 @@ fate-bsf-dv-error-marker: CMD = md5 -i $(TARGET_SAMPLES)/dv/dvcprohd_720p50.mov -flags +bitexact -fflags +bitexact -c:v copy -bsf noise=100,dv_error_marker=color=blue -f avi fate-bsf-dv-error-marker: CMP = oneline -fate-bsf-dv-error-marker: REF = 4e884d3e8045299d0d45ec920fa58a44 +fate-bsf-dv-error-marker: REF = 3190a334b1ceef2d9fd050a1590da7c6 FATE_DVVIDEO-$(call ALLYES, MOV_DEMUXER DV_ERROR_MARKER_BSF NOISE_BSF AVI_MUXER) += fate-bsf-dv-error-marker FATE_SAMPLES_FFMPEG += $(FATE_DVVIDEO-yes) diff --git a/tests/ref/fate/mxf-probe-dv25 b/tests/ref/fate/mxf-probe-dv25 index 8b12a17838a..f89357e1913 100644 --- a/tests/ref/fate/mxf-probe-dv25 +++ b/tests/ref/fate/mxf-probe-dv25 @@ -31,7 +31,7 @@ start_pts=0 start_time=0.000000 duration_ts=25 duration=1.000000 -bit_rate=N/A +bit_rate=28800000 max_bit_rate=N/A bits_per_raw_sample=N/A nb_frames=N/A From ac616afa62c3164ddad7ac8d2d6fb94d6effa3f6 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Tue, 4 Jul 2023 18:27:04 +0200 Subject: [PATCH 1771/2172] lavf/dv: stop setting a random video bitrate A real value is determined from the bytestream. --- libavformat/dv.c | 1 - 1 file changed, 1 deletion(-) diff --git a/libavformat/dv.c b/libavformat/dv.c index d01ecedc622..6df93fe4162 100644 --- a/libavformat/dv.c +++ b/libavformat/dv.c @@ -358,7 +358,6 @@ static int dv_init_demux(AVFormatContext *s, DVDemuxContext *c) c->fctx = s; c->vst->codecpar->codec_type = AVMEDIA_TYPE_VIDEO; c->vst->codecpar->codec_id = AV_CODEC_ID_DVVIDEO; - c->vst->codecpar->bit_rate = 25000000; c->vst->start_time = 0; avpriv_set_pts_info(c->vst, 64, 1, DV_TIMESCALE_VIDEO); From 0d0c39832fe0ceb58797548d544621eb7bd0755c Mon Sep 17 00:00:00 2001 From: Zhao Zhili Date: Thu, 6 Jul 2023 20:00:48 +0800 Subject: [PATCH 1772/2172] avcodec/nvenc: fix intraRefreshPeriod setting Regression since 99dfdb45. intraRefreshPeriod access cc->gopLength, which has been overwritten to NVENC_INFINITE_GOPLENGTH before. Fixes #10445. --- libavcodec/nvenc.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/libavcodec/nvenc.c b/libavcodec/nvenc.c index 06579a502b6..13fafcd2467 100644 --- a/libavcodec/nvenc.c +++ b/libavcodec/nvenc.c @@ -1173,6 +1173,7 @@ static av_cold int nvenc_setup_h264_config(AVCodecContext *avctx) h264->enableIntraRefresh = 1; h264->intraRefreshPeriod = cc->gopLength; h264->intraRefreshCnt = cc->gopLength - 1; + cc->gopLength = NVENC_INFINITE_GOPLENGTH; #ifdef NVENC_HAVE_SINGLE_SLICE_INTRA_REFRESH h264->singleSliceIntraRefresh = ctx->single_slice_intra_refresh; #endif @@ -1297,6 +1298,7 @@ static av_cold int nvenc_setup_hevc_config(AVCodecContext *avctx) hevc->enableIntraRefresh = 1; hevc->intraRefreshPeriod = cc->gopLength; hevc->intraRefreshCnt = cc->gopLength - 1; + cc->gopLength = NVENC_INFINITE_GOPLENGTH; #ifdef NVENC_HAVE_SINGLE_SLICE_INTRA_REFRESH hevc->singleSliceIntraRefresh = ctx->single_slice_intra_refresh; #endif @@ -1415,6 +1417,7 @@ static av_cold int nvenc_setup_av1_config(AVCodecContext *avctx) av1->enableIntraRefresh = 1; av1->intraRefreshPeriod = cc->gopLength; av1->intraRefreshCnt = cc->gopLength - 1; + cc->gopLength = NVENC_INFINITE_GOPLENGTH; av1->idrPeriod = NVENC_INFINITE_GOPLENGTH; } else if (cc->gopLength > 0) { @@ -1619,9 +1622,6 @@ FF_ENABLE_DEPRECATION_WARNINGS if(ctx->single_slice_intra_refresh) ctx->intra_refresh = 1; - if (ctx->intra_refresh) - ctx->encode_config.gopLength = NVENC_INFINITE_GOPLENGTH; - nvenc_recalc_surfaces(avctx); nvenc_setup_rate_control(avctx); From 7eeef72c67d1292472c7923f7e0c59dd9780ff5c Mon Sep 17 00:00:00 2001 From: Zhao Zhili Date: Fri, 7 Jul 2023 03:57:38 +0800 Subject: [PATCH 1773/2172] avcodec/nvenc: set idrPeriod to gopLength unconditionally When intra_refresh is enabled, gopLength is equal to NVENC_INFINITE_GOPLENGTH. gopLength should be 1 at least. Signed-off-by: Zhao Zhili --- libavcodec/nvenc.c | 18 ++++-------------- 1 file changed, 4 insertions(+), 14 deletions(-) diff --git a/libavcodec/nvenc.c b/libavcodec/nvenc.c index 13fafcd2467..0b6417674ef 100644 --- a/libavcodec/nvenc.c +++ b/libavcodec/nvenc.c @@ -1191,11 +1191,7 @@ static av_cold int nvenc_setup_h264_config(AVCodecContext *avctx) h264->maxNumRefFrames = ctx->dpb_size; } - if (ctx->intra_refresh) { - h264->idrPeriod = NVENC_INFINITE_GOPLENGTH; - } else if (cc->gopLength > 0) { - h264->idrPeriod = cc->gopLength; - } + h264->idrPeriod = cc->gopLength; if (IS_CBR(cc->rcParams.rateControlMode)) { h264->outputBufferingPeriodSEI = 1; @@ -1318,11 +1314,7 @@ static av_cold int nvenc_setup_hevc_config(AVCodecContext *avctx) hevc->maxNumRefFramesInDPB = ctx->dpb_size; } - if (ctx->intra_refresh) { - hevc->idrPeriod = NVENC_INFINITE_GOPLENGTH; - } else if (cc->gopLength > 0) { - hevc->idrPeriod = cc->gopLength; - } + hevc->idrPeriod = cc->gopLength; if (IS_CBR(cc->rcParams.rateControlMode)) { hevc->outputBufferingPeriodSEI = 1; @@ -1418,12 +1410,10 @@ static av_cold int nvenc_setup_av1_config(AVCodecContext *avctx) av1->intraRefreshPeriod = cc->gopLength; av1->intraRefreshCnt = cc->gopLength - 1; cc->gopLength = NVENC_INFINITE_GOPLENGTH; - - av1->idrPeriod = NVENC_INFINITE_GOPLENGTH; - } else if (cc->gopLength > 0) { - av1->idrPeriod = cc->gopLength; } + av1->idrPeriod = cc->gopLength; + if (IS_CBR(cc->rcParams.rateControlMode)) { av1->enableBitstreamPadding = 1; } From 0f008a0ffa5c1a863e4c78c640135a3693ff1d9c Mon Sep 17 00:00:00 2001 From: James Almer Date: Thu, 6 Jul 2023 12:04:50 -0300 Subject: [PATCH 1774/2172] avcodec/cbs_h266: fix use of uninitialized value And fix the allowed range for ph_log2_diff_max_bt_min_qt_intra_slice_luma while at it. Signed-off-by: James Almer --- libavcodec/cbs_h266_syntax_template.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/libavcodec/cbs_h266_syntax_template.c b/libavcodec/cbs_h266_syntax_template.c index b984a12d8f8..a39efe588e2 100644 --- a/libavcodec/cbs_h266_syntax_template.c +++ b/libavcodec/cbs_h266_syntax_template.c @@ -2731,8 +2731,13 @@ static int FUNC(picture_header) (CodedBitstreamContext *ctx, RWContext *rw, ue(ph_max_mtt_hierarchy_depth_intra_slice_luma, 0, 2 * (ctb_log2_size_y - min_cb_log2_size_y)); if (current->ph_max_mtt_hierarchy_depth_intra_slice_luma != 0) { + min_qt_log2_size_intra_y = + current->ph_log2_diff_min_qt_min_cb_intra_slice_luma + + min_cb_log2_size_y; ue(ph_log2_diff_max_bt_min_qt_intra_slice_luma, - 0, ctb_log2_size_y - min_qt_log2_size_intra_y); + 0, (sps->sps_qtbtt_dual_tree_intra_flag ? + FFMIN(6, ctb_log2_size_y) : + ctb_log2_size_y) - min_qt_log2_size_intra_y); ue(ph_log2_diff_max_tt_min_qt_intra_slice_luma, 0, FFMIN(6, ctb_log2_size_y) - min_qt_log2_size_intra_y); } else { From 3a30abd8ae708e608fe58d3a6ceb80f6aeb37b1d Mon Sep 17 00:00:00 2001 From: James Almer Date: Thu, 6 Jul 2023 12:05:52 -0300 Subject: [PATCH 1775/2172] avcodec/cbs_h266: use exp_tile_height when checking the allowed range for pps_num_exp_tile_rows_minus1 Fixes warnings about variable set but not used. Signed-off-by: James Almer --- libavcodec/cbs_h266_syntax_template.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavcodec/cbs_h266_syntax_template.c b/libavcodec/cbs_h266_syntax_template.c index a39efe588e2..dce0216fbce 100644 --- a/libavcodec/cbs_h266_syntax_template.c +++ b/libavcodec/cbs_h266_syntax_template.c @@ -1845,7 +1845,7 @@ static int FUNC(pps) (CodedBitstreamContext *ctx, RWContext *rw, } for (i = 0; i <= current->pps_num_exp_tile_rows_minus1; i++) { ues(pps_tile_row_height_minus1[i], - 0, pic_height_in_ctbs_y - 1, 1, i); + 0, pic_height_in_ctbs_y - exp_tile_height - 1, 1, i); exp_tile_height += current->pps_tile_row_height_minus1[i] + 1; } From 13ef5025e395831f6a9e45751e984d898f3738eb Mon Sep 17 00:00:00 2001 From: James Almer Date: Sun, 2 Jul 2023 20:26:22 -0300 Subject: [PATCH 1776/2172] fate/cbs: add more VVC tests Signed-off-by: James Almer --- tests/fate/cbs.mak | 5 +++++ tests/ref/fate/cbs-vvc-APSALF_A_2 | 1 + tests/ref/fate/cbs-vvc-APSLMCS_D_1 | 1 + tests/ref/fate/cbs-vvc-APSMULT_A_4 | 1 + tests/ref/fate/cbs-vvc-DCI_A_3 | 1 + tests/ref/fate/cbs-vvc-OPI_B_3 | 1 + 6 files changed, 10 insertions(+) create mode 100644 tests/ref/fate/cbs-vvc-APSALF_A_2 create mode 100644 tests/ref/fate/cbs-vvc-APSLMCS_D_1 create mode 100644 tests/ref/fate/cbs-vvc-APSMULT_A_4 create mode 100644 tests/ref/fate/cbs-vvc-DCI_A_3 create mode 100644 tests/ref/fate/cbs-vvc-OPI_B_3 diff --git a/tests/fate/cbs.mak b/tests/fate/cbs.mak index 4d8742d99cb..802b0351a37 100644 --- a/tests/fate/cbs.mak +++ b/tests/fate/cbs.mak @@ -167,12 +167,17 @@ fate-cbs-hevc: $(FATE_CBS_HEVC-yes) # H.266 read/write FATE_CBS_VVC_SAMPLES = \ + APSALF_A_2.bit \ + APSLMCS_D_1.bit \ + APSMULT_A_4.bit \ AUD_A_3.bit \ BOUNDARY_A_3.bit \ BUMP_A_2.bit \ CodingToolsSets_A_2.bit \ CROP_B_4.bit \ + DCI_A_3.bit \ HRD_A_3.bit \ + OPI_B_3.bit \ PHSH_B_1.bit \ POC_A_1.bit \ PPS_B_1.bit \ diff --git a/tests/ref/fate/cbs-vvc-APSALF_A_2 b/tests/ref/fate/cbs-vvc-APSALF_A_2 new file mode 100644 index 00000000000..eb2fc02a5ea --- /dev/null +++ b/tests/ref/fate/cbs-vvc-APSALF_A_2 @@ -0,0 +1 @@ +c981a00e28e51adde1654850935a889d diff --git a/tests/ref/fate/cbs-vvc-APSLMCS_D_1 b/tests/ref/fate/cbs-vvc-APSLMCS_D_1 new file mode 100644 index 00000000000..430dc934b78 --- /dev/null +++ b/tests/ref/fate/cbs-vvc-APSLMCS_D_1 @@ -0,0 +1 @@ +e2e3407885d84e0dee5ec5d51dd4a3a6 diff --git a/tests/ref/fate/cbs-vvc-APSMULT_A_4 b/tests/ref/fate/cbs-vvc-APSMULT_A_4 new file mode 100644 index 00000000000..79f29373b90 --- /dev/null +++ b/tests/ref/fate/cbs-vvc-APSMULT_A_4 @@ -0,0 +1 @@ +66dc3dba5c25bcaab231007bc059c331 diff --git a/tests/ref/fate/cbs-vvc-DCI_A_3 b/tests/ref/fate/cbs-vvc-DCI_A_3 new file mode 100644 index 00000000000..fec635afa55 --- /dev/null +++ b/tests/ref/fate/cbs-vvc-DCI_A_3 @@ -0,0 +1 @@ +2b0eb33eb66078a3454619c5612e7bc2 diff --git a/tests/ref/fate/cbs-vvc-OPI_B_3 b/tests/ref/fate/cbs-vvc-OPI_B_3 new file mode 100644 index 00000000000..99c85165aa4 --- /dev/null +++ b/tests/ref/fate/cbs-vvc-OPI_B_3 @@ -0,0 +1 @@ +c35066104c7cf9be0e7b9aad5b576256 From 2e83ba001d79e1b543f6c0e408ae17da4ca5251a Mon Sep 17 00:00:00 2001 From: Niklas Haas Date: Sat, 8 Jul 2023 12:41:45 +0200 Subject: [PATCH 1777/2172] lavfi/vf_libplacebo: deprecate hybrid_mix option Deprecated upstream in libplacebo v6.292. --- doc/filters.texi | 6 ------ libavfilter/vf_libplacebo.c | 16 +++++++++------- 2 files changed, 9 insertions(+), 13 deletions(-) diff --git a/doc/filters.texi b/doc/filters.texi index f17488c7c77..95b04cea1ac 100644 --- a/doc/filters.texi +++ b/doc/filters.texi @@ -16664,12 +16664,6 @@ output color volumes. Disabled by default. Size of the tone-mapping LUT, between @code{2} and @code{1024}. Defaults to @code{256}. Note that this figure is squared when combined with @code{peak_detect}. - -@item hybrid_mix -If nonzero, this much of the upper range of the tone-mapped result is smoothly -mixed with a per-channel (LMS) tone-mapped version. Helps avoid unnatural -blown-out highlights when tone-mapping very bright, strongly saturated colors. -Defaults to @code{0.2}. @end table @subsubsection Dithering diff --git a/libavfilter/vf_libplacebo.c b/libavfilter/vf_libplacebo.c index e58183a5caa..10a79ac950d 100644 --- a/libavfilter/vf_libplacebo.c +++ b/libavfilter/vf_libplacebo.c @@ -219,7 +219,6 @@ typedef struct LibplaceboContext { float tonemapping_param; int inverse_tonemapping; int tonemapping_lut_size; - float hybrid_mix; #if FF_API_LIBPLACEBO_OPTS /* for backwards compatibility */ @@ -232,6 +231,7 @@ typedef struct LibplaceboContext { int tonemapping_mode; float crosstalk; float overshoot; + float hybrid_mix; #endif /* pl_dither_params */ @@ -360,12 +360,10 @@ static int update_settings(AVFilterContext *ctx) int err = 0; LibplaceboContext *s = ctx->priv; int gamut_mode = s->gamut_mode; - float hybrid_mix = s->hybrid_mix; uint8_t color_rgba[4]; - RET(av_parse_color(color_rgba, s->fillcolor, -1, s)); - #if FF_API_LIBPLACEBO_OPTS + float hybrid_mix = s->hybrid_mix; /* backwards compatibility with older API */ switch (s->tonemapping_mode) { case 0: /*PL_TONE_MAP_AUTO*/ @@ -390,6 +388,8 @@ static int update_settings(AVFilterContext *ctx) gamut_mode = GAMUT_MAP_DESATURATE; #endif + RET(av_parse_color(color_rgba, s->fillcolor, -1, s)); + s->deband_params = *pl_deband_params( .iterations = s->deband_iterations, .threshold = s->deband_threshold, @@ -419,11 +419,13 @@ static int update_settings(AVFilterContext *ctx) ); s->color_map_params = *pl_color_map_params( -#if PL_API_VER >= 269 +#if FF_API_LIBPLACEBO_OPTS +# if PL_API_VER >= 269 .hybrid_mix = hybrid_mix, -#elif FF_API_LIBPLACEBO_OPTS +# else .tone_mapping_mode = s->tonemapping_mode, .tone_mapping_crosstalk = s->crosstalk, +# endif #endif .tone_mapping_function = get_tonemapping_func(s->tonemapping), .tone_mapping_param = s->tonemapping_param, @@ -1396,7 +1398,6 @@ static const AVOption libplacebo_options[] = { { "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 }, { "inverse_tonemapping", "Inverse tone mapping (range expansion)", OFFSET(inverse_tonemapping), AV_OPT_TYPE_BOOL, {.i64 = 0}, 0, 1, DYNAMIC }, { "tonemapping_lut_size", "Tone-mapping LUT size", OFFSET(tonemapping_lut_size), AV_OPT_TYPE_INT, {.i64 = 256}, 2, 1024, DYNAMIC }, - { "hybrid_mix", "Tone-mapping hybrid LMS mixing coefficient", OFFSET(hybrid_mix), AV_OPT_TYPE_FLOAT, {.dbl = 0.20}, 0.0, 1.00, DYNAMIC }, #if FF_API_LIBPLACEBO_OPTS /* deprecated options for backwards compatibility, defaulting to -1 to not override the new defaults */ @@ -1417,6 +1418,7 @@ static const AVOption libplacebo_options[] = { { "luma", "Luminance", 0, AV_OPT_TYPE_CONST, {.i64 = 4}, 0, 0, STATIC, "tonemap_mode" }, { "tonemapping_crosstalk", "Crosstalk factor for tone-mapping", OFFSET(crosstalk), AV_OPT_TYPE_FLOAT, {.dbl = 0.04}, 0.0, 0.30, DYNAMIC | AV_OPT_FLAG_DEPRECATED }, { "overshoot", "Tone-mapping overshoot margin", OFFSET(overshoot), AV_OPT_TYPE_FLOAT, {.dbl = 0.05}, 0.0, 1.0, DYNAMIC | AV_OPT_FLAG_DEPRECATED }, + { "hybrid_mix", "Tone-mapping hybrid LMS mixing coefficient", OFFSET(hybrid_mix), AV_OPT_TYPE_FLOAT, {.dbl = 0.20}, 0.0, 1.00, DYNAMIC }, #endif { "dithering", "Dither method to use", OFFSET(dithering), AV_OPT_TYPE_INT, {.i64 = PL_DITHER_BLUE_NOISE}, -1, PL_DITHER_METHOD_COUNT - 1, DYNAMIC, "dither" }, From 13e989901468b2e53a7d3a099511aae6987c7b00 Mon Sep 17 00:00:00 2001 From: Niklas Haas Date: Sat, 8 Jul 2023 12:54:49 +0200 Subject: [PATCH 1778/2172] lavfi/vf_libplacebo: add contrast recovery options New upstream option. Enabled by default in the high-quality preset upstream, so enable it by default here. --- doc/filters.texi | 13 +++++++++++++ libavfilter/vf_libplacebo.c | 8 ++++++++ 2 files changed, 21 insertions(+) diff --git a/doc/filters.texi b/doc/filters.texi index 95b04cea1ac..54cc5ba820d 100644 --- a/doc/filters.texi +++ b/doc/filters.texi @@ -16664,6 +16664,19 @@ output color volumes. Disabled by default. Size of the tone-mapping LUT, between @code{2} and @code{1024}. Defaults to @code{256}. Note that this figure is squared when combined with @code{peak_detect}. + +@item contrast_recovery +Contrast recovery strength. If set to a value above @code{0.0}, the source +image will be divided into high-frequency and low-frequency components, and a +portion of the high-frequency image is added back onto the tone-mapped output. +May cause excessive ringing artifacts for some HDR sources, but can improve the +subjective sharpness and detail left over in the image after tone-mapping. +Defaults to @code{0.30}. + +@item contrast_smoothness +Contrast recovery lowpass kernel size. Defaults to @code{3.5}. Increasing or +decreasing this will affect the visual appearance substantially. Has no effect +when @code{contrast_recovery} is disabled. @end table @subsubsection Dithering diff --git a/libavfilter/vf_libplacebo.c b/libavfilter/vf_libplacebo.c index 10a79ac950d..031265b637a 100644 --- a/libavfilter/vf_libplacebo.c +++ b/libavfilter/vf_libplacebo.c @@ -219,6 +219,8 @@ typedef struct LibplaceboContext { float tonemapping_param; int inverse_tonemapping; int tonemapping_lut_size; + float contrast_recovery; + float contrast_smoothness; #if FF_API_LIBPLACEBO_OPTS /* for backwards compatibility */ @@ -431,6 +433,10 @@ static int update_settings(AVFilterContext *ctx) .tone_mapping_param = s->tonemapping_param, .inverse_tone_mapping = s->inverse_tonemapping, .lut_size = s->tonemapping_lut_size, +#if PL_API_VER >= 285 + .contrast_recovery = s->contrast_recovery, + .contrast_smoothness = s->contrast_smoothness, +#endif ); set_gamut_mode(&s->color_map_params, gamut_mode); @@ -1398,6 +1404,8 @@ static const AVOption libplacebo_options[] = { { "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 }, { "inverse_tonemapping", "Inverse tone mapping (range expansion)", OFFSET(inverse_tonemapping), AV_OPT_TYPE_BOOL, {.i64 = 0}, 0, 1, DYNAMIC }, { "tonemapping_lut_size", "Tone-mapping LUT size", OFFSET(tonemapping_lut_size), AV_OPT_TYPE_INT, {.i64 = 256}, 2, 1024, DYNAMIC }, + { "contrast_recovery", "HDR contrast recovery strength", OFFSET(contrast_recovery), AV_OPT_TYPE_FLOAT, {.dbl = 0.30}, 0.0, 3.0, DYNAMIC }, + { "contrast_smoothness", "HDR contrast recovery smoothness", OFFSET(contrast_smoothness), AV_OPT_TYPE_FLOAT, {.dbl = 3.50}, 1.0, 32.0, DYNAMIC }, #if FF_API_LIBPLACEBO_OPTS /* deprecated options for backwards compatibility, defaulting to -1 to not override the new defaults */ From 0056d9f1765dc1ef0dcb81c6919de7e75575a889 Mon Sep 17 00:00:00 2001 From: Pavel Koshevoy Date: Sat, 8 Jul 2023 11:48:13 -0600 Subject: [PATCH 1779/2172] avutil: fix build failure on osx 10.4 libavutil/random_seed.c calls arc4random_buf which is not available on OSX 10.4 Tiger, but the configuration script tests for arc4random which is available. Fix the configuration test to match the actual API used. Co-authored-by: James Almer Signed-off-by: James Almer --- configure | 4 ++-- libavutil/random_seed.c | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/configure b/configure index d6e78297fe5..0ab0761011b 100755 --- a/configure +++ b/configure @@ -2301,7 +2301,7 @@ SYSTEM_FEATURES=" SYSTEM_FUNCS=" access aligned_malloc - arc4random + arc4random_buf clock_gettime closesocket CommandLineToArgvW @@ -6381,7 +6381,7 @@ check_func ${malloc_prefix}memalign && enable memalign check_func ${malloc_prefix}posix_memalign && enable posix_memalign check_func access -check_func_headers stdlib.h arc4random +check_func_headers stdlib.h arc4random_buf check_lib clock_gettime time.h clock_gettime || check_lib clock_gettime time.h clock_gettime -lrt check_func fcntl check_func fork diff --git a/libavutil/random_seed.c b/libavutil/random_seed.c index 2980e565e08..f167b172f28 100644 --- a/libavutil/random_seed.c +++ b/libavutil/random_seed.c @@ -142,7 +142,7 @@ int av_random_bytes(uint8_t* buf, size_t len) } #endif -#if HAVE_ARC4RANDOM +#if HAVE_ARC4RANDOM_BUF arc4random_buf(buf, len); return 0; #endif From e5ab2dab2c73710c753bf8a44171fc747625e9f3 Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt Date: Thu, 6 Jul 2023 22:48:55 +0200 Subject: [PATCH 1780/2172] avformat/evcdec: Check that enough data has been read Fixes potential use of uninitialized values in evc_read_nal_unit_length(). Reviewed-by: James Almer Signed-off-by: Andreas Rheinhardt --- libavformat/evcdec.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/libavformat/evcdec.c b/libavformat/evcdec.c index 9e09f8d2647..6cce174f46a 100644 --- a/libavformat/evcdec.c +++ b/libavformat/evcdec.c @@ -162,6 +162,8 @@ static int evc_read_packet(AVFormatContext *s, AVPacket *pkt) ret = avio_read(s->pb, buf, EVC_NALU_LENGTH_PREFIX_SIZE); if (ret < 0) return ret; + if (ret != EVC_NALU_LENGTH_PREFIX_SIZE) + return AVERROR_INVALIDDATA; nalu_size = evc_read_nal_unit_length(buf, EVC_NALU_LENGTH_PREFIX_SIZE); if (!nalu_size || nalu_size > INT_MAX) From e52676e20b387dae8e338bbf191729ce029fab7e Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt Date: Thu, 6 Jul 2023 23:05:00 +0200 Subject: [PATCH 1781/2172] avformat/evc: Don't cast const away, avoid loop Signed-off-by: Andreas Rheinhardt --- libavformat/evc.h | 17 ++++++----------- 1 file changed, 6 insertions(+), 11 deletions(-) diff --git a/libavformat/evc.h b/libavformat/evc.h index 46b27f7df77..f30831257d1 100644 --- a/libavformat/evc.h +++ b/libavformat/evc.h @@ -23,16 +23,17 @@ #define AVFORMAT_EVC_H #include + +#include "libavutil/intreadwrite.h" #include "libavutil/rational.h" #include "libavcodec/evc.h" #include "avio.h" -static inline int evc_get_nalu_type(const uint8_t *bits, int bits_size) +static inline int evc_get_nalu_type(const uint8_t *p, int bits_size) { int unit_type_plus1 = 0; if (bits_size >= EVC_NALU_HEADER_SIZE) { - unsigned char *p = (unsigned char *)bits; // forbidden_zero_bit if ((p[0] & 0x80) != 0) // Cannot get bitstream information. Malformed bitstream. return -1; @@ -46,16 +47,10 @@ static inline int evc_get_nalu_type(const uint8_t *bits, int bits_size) static inline uint32_t evc_read_nal_unit_length(const uint8_t *bits, int bits_size) { - uint32_t nalu_len = 0; - - if (bits_size >= EVC_NALU_LENGTH_PREFIX_SIZE) { - unsigned char *p = (unsigned char *)bits; - - for (int i = 0; i < EVC_NALU_LENGTH_PREFIX_SIZE; i++) - nalu_len = (nalu_len << 8) | p[i]; - } + if (bits_size >= EVC_NALU_LENGTH_PREFIX_SIZE) + return AV_RB32(bits); - return nalu_len; + return 0; } /** From 889c2529cc6ef65bb4c4f10aa79ca7ca0070a1aa Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Thu, 6 Jul 2023 16:47:02 +0200 Subject: [PATCH 1782/2172] avfilter/af_adynamicequalizer: simplify calculations --- libavfilter/adynamicequalizer_template.c | 16 ++++++++++------ libavfilter/af_adynamicequalizer.c | 2 +- 2 files changed, 11 insertions(+), 7 deletions(-) diff --git a/libavfilter/adynamicequalizer_template.c b/libavfilter/adynamicequalizer_template.c index 4f7d58c9396..ee9f4a1d5f3 100644 --- a/libavfilter/adynamicequalizer_template.c +++ b/libavfilter/adynamicequalizer_template.c @@ -26,6 +26,7 @@ #undef FMIN #undef CLIP #undef SAMPLE_FORMAT +#undef EPSILON #undef FABS #if DEPTH == 32 #define SAMPLE_FORMAT float @@ -39,6 +40,7 @@ #define CLIP av_clipf #define FABS fabsf #define ftype float +#define EPSILON (1.f / (1 << 22)) #else #define SAMPLE_FORMAT double #define SQRT sqrt @@ -51,6 +53,7 @@ #define CLIP av_clipd #define FABS fabs #define ftype double +#define EPSILON (1.0 / (1LL << 51)) #endif #define fn3(a,b) a##_##b @@ -147,9 +150,7 @@ static int fn(filter_channels)(AVFilterContext *ctx, void *arg, int jobnr, int n const ftype range = s->range; const ftype tfrequency = FMIN(s->tfrequency, sample_rate * 0.5); const ftype release = s->release_coef; - const ftype irelease = ONE - release; const ftype attack = s->attack_coef; - const ftype iattack = ONE - attack; const ftype tqfactor = s->tqfactor; const ftype itqfactor = ONE / tqfactor; const ftype fg = TAN(M_PI * tfrequency / sample_rate); @@ -198,10 +199,13 @@ static int fn(filter_channels)(AVFilterContext *ctx, void *arg, int jobnr, int n detect = ONE; } - if ((direction == 0 && detect > state[4]) || (direction == 1 && detect < state[4])) { - detect = iattack * detect + attack * state[4]; - } else { - detect = irelease * detect + release * state[4]; + { + ftype delta = detect - state[4]; + + if (delta > EPSILON) + detect = state[4] + attack * delta; + else if (delta < -EPSILON) + detect = state[4] + release * delta; } } diff --git a/libavfilter/af_adynamicequalizer.c b/libavfilter/af_adynamicequalizer.c index 5a2c8efb2ac..2a76827ada6 100644 --- a/libavfilter/af_adynamicequalizer.c +++ b/libavfilter/af_adynamicequalizer.c @@ -76,7 +76,7 @@ static int query_formats(AVFilterContext *ctx) static double get_coef(double x, double sr) { - return exp(-1000. / (x * sr)); + return 1.0 - exp(-1000. / (x * sr)); } typedef struct ThreadData { From 20b8688092a02b425b94279fbbb55606d3560214 Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Sun, 9 Jul 2023 09:56:03 +0200 Subject: [PATCH 1783/2172] avfilter/adynamicequalizer_template: fix peak filter --- libavfilter/adynamicequalizer_template.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavfilter/adynamicequalizer_template.c b/libavfilter/adynamicequalizer_template.c index ee9f4a1d5f3..94a27ea1cc3 100644 --- a/libavfilter/adynamicequalizer_template.c +++ b/libavfilter/adynamicequalizer_template.c @@ -129,7 +129,7 @@ static int fn(filter_prepare)(AVFilterContext *ctx) da[1] = dg * da[0]; da[2] = dg * da[1]; - dm[0] = ZERO; + dm[0] = ONE; dm[1] = -k; dm[2] = -TWO; break; From f607e8517d4c35f757168733856405693e47ea26 Mon Sep 17 00:00:00 2001 From: Marton Balint Date: Sun, 2 Jul 2023 20:12:52 +0200 Subject: [PATCH 1784/2172] avdevice/decklink_enc: use 64bit format string for BMD timebase instead of long long MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit BMDTimeValue is defined as LONGLONG on Windows, but int64_t on Linux/Mac. Fixes format string warnings: libavdevice/decklink_enc.cpp: In function ‘void construct_cc(AVFormatContext*, decklink_ctx*, AVPacket*, klvanc_line_set_s*)’: libavdevice/decklink_enc.cpp:424:48: warning: format ‘%lld’ expects argument of type ‘long long int’, but argument 4 has type ‘BMDTimeValue {aka long int}’ [-Wformat=] ctx->bmd_tb_num, ctx->bmd_tb_den); ~~~~~~~~~~~~~~~ ^ libavdevice/decklink_enc.cpp:424:48: warning: format ‘%lld’ expects argument of type ‘long long int’, but argument 5 has type ‘BMDTimeValue {aka long int}’ [-Wformat=] Signed-off-by: Marton Balint --- libavdevice/decklink_enc.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavdevice/decklink_enc.cpp b/libavdevice/decklink_enc.cpp index 1809f79cacd..ffd0ad92508 100644 --- a/libavdevice/decklink_enc.cpp +++ b/libavdevice/decklink_enc.cpp @@ -420,7 +420,7 @@ static void construct_cc(AVFormatContext *avctx, struct decklink_ctx *ctx, ret = klvanc_set_framerate_EIA_708B(cdp, ctx->bmd_tb_num, ctx->bmd_tb_den); if (ret) { - av_log(avctx, AV_LOG_ERROR, "Invalid framerate specified: %lld/%lld\n", + av_log(avctx, AV_LOG_ERROR, "Invalid framerate specified: %" PRId64 "/%" PRId64 "\n", ctx->bmd_tb_num, ctx->bmd_tb_den); klvanc_destroy_eia708_cdp(cdp); return; From 7357012bb5205e0d03634aff48fc0167a9248190 Mon Sep 17 00:00:00 2001 From: Marton Balint Date: Mon, 3 Jul 2023 23:17:01 +0200 Subject: [PATCH 1785/2172] fftools/ffmpeg: fix negative timestamps at the beginning of the encoding Also fix a couple of possible overflows while at it. Fixes the negative initial timestamps in ticket #10358. 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 435e12a37bf..71d4067a6c6 100644 --- a/fftools/ffmpeg.c +++ b/fftools/ffmpeg.c @@ -497,11 +497,12 @@ static void print_report(int is_last_report, int64_t timer_start, int64_t cur_ti int vid; double bitrate; double speed; - int64_t pts = INT64_MIN + 1; + int64_t pts = AV_NOPTS_VALUE; static int64_t last_time = -1; static int first_report = 1; uint64_t nb_frames_dup = 0, nb_frames_drop = 0; - int hours, mins, secs, us; + int mins, secs, us; + int64_t hours; const char *hours_sign; int ret; float t; @@ -553,7 +554,8 @@ static void print_report(int is_last_report, int64_t timer_start, int64_t cur_ti } /* compute min output value */ if (ost->last_mux_dts != AV_NOPTS_VALUE) { - pts = FFMAX(pts, ost->last_mux_dts); + if (pts == AV_NOPTS_VALUE || ost->last_mux_dts > pts) + pts = ost->last_mux_dts; if (copy_ts) { if (copy_ts_first_pts == AV_NOPTS_VALUE && pts > 1) copy_ts_first_pts = pts; @@ -566,23 +568,21 @@ static void print_report(int is_last_report, int64_t timer_start, int64_t cur_ti nb_frames_drop += ost->last_dropped; } - secs = FFABS(pts) / AV_TIME_BASE; - us = FFABS(pts) % AV_TIME_BASE; - mins = secs / 60; - secs %= 60; - hours = mins / 60; - mins %= 60; + us = FFABS64U(pts) % AV_TIME_BASE; + secs = FFABS64U(pts) / AV_TIME_BASE % 60; + mins = FFABS64U(pts) / AV_TIME_BASE / 60 % 60; + hours = FFABS64U(pts) / AV_TIME_BASE / 3600; hours_sign = (pts < 0) ? "-" : ""; - bitrate = pts && total_size >= 0 ? total_size * 8 / (pts / 1000.0) : -1; - speed = t != 0.0 ? (double)pts / AV_TIME_BASE / t : -1; + bitrate = pts != AV_NOPTS_VALUE && pts && total_size >= 0 ? total_size * 8 / (pts / 1000.0) : -1; + speed = pts != AV_NOPTS_VALUE && t != 0.0 ? (double)pts / AV_TIME_BASE / t : -1; if (total_size < 0) av_bprintf(&buf, "size=N/A time="); else av_bprintf(&buf, "size=%8.0fkB time=", total_size / 1024.0); if (pts == AV_NOPTS_VALUE) { av_bprintf(&buf, "N/A "); } else { - av_bprintf(&buf, "%s%02d:%02d:%02d.%02d ", + av_bprintf(&buf, "%s%02"PRId64":%02d:%02d.%02d ", hours_sign, hours, mins, secs, (100 * us) / AV_TIME_BASE); } @@ -603,7 +603,7 @@ static void print_report(int is_last_report, int64_t timer_start, int64_t cur_ti } else { av_bprintf(&buf_script, "out_time_us=%"PRId64"\n", pts); av_bprintf(&buf_script, "out_time_ms=%"PRId64"\n", pts); - av_bprintf(&buf_script, "out_time=%s%02d:%02d:%02d.%06d\n", + av_bprintf(&buf_script, "out_time=%s%02"PRId64":%02d:%02d.%06d\n", hours_sign, hours, mins, secs, us); } From 7f23b72dde9db1a6867e9897b786fba064fe685d Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Sun, 9 Jul 2023 19:56:10 +0200 Subject: [PATCH 1786/2172] avfilter/avf_showcwt: add sqrt frequency scale --- doc/filters.texi | 1 + libavfilter/avf_showcwt.c | 10 ++++++++++ 2 files changed, 11 insertions(+) diff --git a/doc/filters.texi b/doc/filters.texi index 54cc5ba820d..ab90f2a8768 100644 --- a/doc/filters.texi +++ b/doc/filters.texi @@ -30709,6 +30709,7 @@ Set the frequency scale used. Allowed values are: @item bark @item mel @item erbs +@item sqrt @end table Default value is @code{linear}. diff --git a/libavfilter/avf_showcwt.c b/libavfilter/avf_showcwt.c index 0ee4414ea2f..f9bbcb8ab37 100644 --- a/libavfilter/avf_showcwt.c +++ b/libavfilter/avf_showcwt.c @@ -40,6 +40,7 @@ enum FrequencyScale { FSCALE_BARK, FSCALE_MEL, FSCALE_ERBS, + FSCALE_SQRT, NB_FSCALE }; @@ -127,6 +128,7 @@ static const AVOption showcwt_options[] = { { "bark", "bark", 0, AV_OPT_TYPE_CONST,{.i64=FSCALE_BARK}, 0, 0, FLAGS, "scale" }, { "mel", "mel", 0, AV_OPT_TYPE_CONST,{.i64=FSCALE_MEL}, 0, 0, FLAGS, "scale" }, { "erbs", "erbs", 0, AV_OPT_TYPE_CONST,{.i64=FSCALE_ERBS}, 0, 0, FLAGS, "scale" }, + { "sqrt", "sqrt", 0, AV_OPT_TYPE_CONST,{.i64=FSCALE_SQRT}, 0, 0, FLAGS, "scale" }, { "min", "set minimum frequency", OFFSET(minimum_frequency), AV_OPT_TYPE_FLOAT, {.dbl = 20.}, 1, 2000, FLAGS }, { "max", "set maximum frequency", OFFSET(maximum_frequency), AV_OPT_TYPE_FLOAT, {.dbl = 20000.}, 0, 192000, FLAGS }, { "logb", "set logarithmic basis", OFFSET(logarithmic_basis), AV_OPT_TYPE_FLOAT, {.dbl = 0.0001}, 0, 1, FLAGS }, @@ -241,6 +243,10 @@ static void frequency_band(float *frequency_band, frequency = 676170.4f / (47.06538f - expf(frequency * 0.08950404f)) - 14678.49f; frequency_derivative *= (frequency * frequency + 14990.4 * frequency + 4577850.f) / 160514.f; break; + case FSCALE_SQRT: + frequency = frequency * frequency; + frequency_derivative *= 2.f * sqrtf(frequency); + break; } frequency_band[y*2 ] = frequency; @@ -680,6 +686,10 @@ static int config_output(AVFilterLink *outlink) minimum_frequency = 11.17268f * log(1.f + (46.06538f * minimum_frequency) / (minimum_frequency + 14678.49f)); maximum_frequency = 11.17268f * log(1.f + (46.06538f * maximum_frequency) / (maximum_frequency + 14678.49f)); break; + case FSCALE_SQRT: + minimum_frequency = sqrtf(minimum_frequency); + maximum_frequency = sqrtf(maximum_frequency); + break; } frequency_band(s->frequency_band, From aee8689ba5700c0335fbc020910eab0f13009086 Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Sun, 9 Jul 2023 20:06:46 +0200 Subject: [PATCH 1787/2172] avfilter/avf_showcwt: add cbrt frequency scale --- doc/filters.texi | 1 + libavfilter/avf_showcwt.c | 10 ++++++++++ 2 files changed, 11 insertions(+) diff --git a/doc/filters.texi b/doc/filters.texi index ab90f2a8768..1a07e03bad8 100644 --- a/doc/filters.texi +++ b/doc/filters.texi @@ -30710,6 +30710,7 @@ Set the frequency scale used. Allowed values are: @item mel @item erbs @item sqrt +@item cbrt @end table Default value is @code{linear}. diff --git a/libavfilter/avf_showcwt.c b/libavfilter/avf_showcwt.c index f9bbcb8ab37..b989beab119 100644 --- a/libavfilter/avf_showcwt.c +++ b/libavfilter/avf_showcwt.c @@ -41,6 +41,7 @@ enum FrequencyScale { FSCALE_MEL, FSCALE_ERBS, FSCALE_SQRT, + FSCALE_CBRT, NB_FSCALE }; @@ -129,6 +130,7 @@ static const AVOption showcwt_options[] = { { "mel", "mel", 0, AV_OPT_TYPE_CONST,{.i64=FSCALE_MEL}, 0, 0, FLAGS, "scale" }, { "erbs", "erbs", 0, AV_OPT_TYPE_CONST,{.i64=FSCALE_ERBS}, 0, 0, FLAGS, "scale" }, { "sqrt", "sqrt", 0, AV_OPT_TYPE_CONST,{.i64=FSCALE_SQRT}, 0, 0, FLAGS, "scale" }, + { "cbrt", "cbrt", 0, AV_OPT_TYPE_CONST,{.i64=FSCALE_CBRT}, 0, 0, FLAGS, "scale" }, { "min", "set minimum frequency", OFFSET(minimum_frequency), AV_OPT_TYPE_FLOAT, {.dbl = 20.}, 1, 2000, FLAGS }, { "max", "set maximum frequency", OFFSET(maximum_frequency), AV_OPT_TYPE_FLOAT, {.dbl = 20000.}, 0, 192000, FLAGS }, { "logb", "set logarithmic basis", OFFSET(logarithmic_basis), AV_OPT_TYPE_FLOAT, {.dbl = 0.0001}, 0, 1, FLAGS }, @@ -247,6 +249,10 @@ static void frequency_band(float *frequency_band, frequency = frequency * frequency; frequency_derivative *= 2.f * sqrtf(frequency); break; + case FSCALE_CBRT: + frequency = frequency * frequency * frequency; + frequency_derivative *= 3.f * powf(frequency, 2.f / 3.f); + break; } frequency_band[y*2 ] = frequency; @@ -690,6 +696,10 @@ static int config_output(AVFilterLink *outlink) minimum_frequency = sqrtf(minimum_frequency); maximum_frequency = sqrtf(maximum_frequency); break; + case FSCALE_CBRT: + minimum_frequency = cbrtf(minimum_frequency); + maximum_frequency = cbrtf(maximum_frequency); + break; } frequency_band(s->frequency_band, From fcbee7efdfb55a25d573669114b5a968a72deb9f Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Sun, 9 Jul 2023 20:50:04 +0200 Subject: [PATCH 1788/2172] avfilter/avf_showcwt: add qdrt frequency scale --- doc/filters.texi | 1 + libavfilter/avf_showcwt.c | 10 ++++++++++ 2 files changed, 11 insertions(+) diff --git a/doc/filters.texi b/doc/filters.texi index 1a07e03bad8..a8e0dbde15f 100644 --- a/doc/filters.texi +++ b/doc/filters.texi @@ -30711,6 +30711,7 @@ Set the frequency scale used. Allowed values are: @item erbs @item sqrt @item cbrt +@item qdrt @end table Default value is @code{linear}. diff --git a/libavfilter/avf_showcwt.c b/libavfilter/avf_showcwt.c index b989beab119..ff2c06fb7a5 100644 --- a/libavfilter/avf_showcwt.c +++ b/libavfilter/avf_showcwt.c @@ -42,6 +42,7 @@ enum FrequencyScale { FSCALE_ERBS, FSCALE_SQRT, FSCALE_CBRT, + FSCALE_QDRT, NB_FSCALE }; @@ -131,6 +132,7 @@ static const AVOption showcwt_options[] = { { "erbs", "erbs", 0, AV_OPT_TYPE_CONST,{.i64=FSCALE_ERBS}, 0, 0, FLAGS, "scale" }, { "sqrt", "sqrt", 0, AV_OPT_TYPE_CONST,{.i64=FSCALE_SQRT}, 0, 0, FLAGS, "scale" }, { "cbrt", "cbrt", 0, AV_OPT_TYPE_CONST,{.i64=FSCALE_CBRT}, 0, 0, FLAGS, "scale" }, + { "qdrt", "qdrt", 0, AV_OPT_TYPE_CONST,{.i64=FSCALE_QDRT}, 0, 0, FLAGS, "scale" }, { "min", "set minimum frequency", OFFSET(minimum_frequency), AV_OPT_TYPE_FLOAT, {.dbl = 20.}, 1, 2000, FLAGS }, { "max", "set maximum frequency", OFFSET(maximum_frequency), AV_OPT_TYPE_FLOAT, {.dbl = 20000.}, 0, 192000, FLAGS }, { "logb", "set logarithmic basis", OFFSET(logarithmic_basis), AV_OPT_TYPE_FLOAT, {.dbl = 0.0001}, 0, 1, FLAGS }, @@ -253,6 +255,10 @@ static void frequency_band(float *frequency_band, frequency = frequency * frequency * frequency; frequency_derivative *= 3.f * powf(frequency, 2.f / 3.f); break; + case FSCALE_QDRT: + frequency = frequency * frequency * frequency * frequency; + frequency_derivative *= 4.f * powf(frequency, 3.f / 4.f); + break; } frequency_band[y*2 ] = frequency; @@ -700,6 +706,10 @@ static int config_output(AVFilterLink *outlink) minimum_frequency = cbrtf(minimum_frequency); maximum_frequency = cbrtf(maximum_frequency); break; + case FSCALE_QDRT: + minimum_frequency = powf(minimum_frequency, 0.25f); + maximum_frequency = powf(maximum_frequency, 0.25f); + break; } frequency_band(s->frequency_band, From 3b358f151ddc7543f1c0fc0cff82b6fe4ddf9cbf Mon Sep 17 00:00:00 2001 From: "Dai, Jianhui J" Date: Mon, 3 Jul 2023 04:25:38 +0000 Subject: [PATCH 1789/2172] avformat/ivfenc: Set the "number of frames" in IVF header Should set "number of frames" to bytes 24-27 of IVF header, not duration. It is described by [1], and confirmed by parsing all IVF files in [2]. This commit also updates the md5sum of refs to pass fate-cbs. [1] Duck IVF - MultimediaWiki https://wiki.multimedia.cx/index.php/Duck_IVF [2] webm/vp8-test-vectors https://chromium.googlesource.com/webm/vp8-test-vectors Signed-off-by: Jianhui Dai Signed-off-by: Ronald S. Bultje --- libavformat/ivfdec.c | 13 ++++++++++--- libavformat/ivfenc.c | 13 +++++-------- tests/ref/fate/cbs-vp9-vp90-2-03-deltaq | 2 +- tests/ref/fate/cbs-vp9-vp90-2-06-bilinear | 2 +- tests/ref/fate/cbs-vp9-vp90-2-09-lf_deltas | 2 +- .../ref/fate/cbs-vp9-vp90-2-10-show-existing-frame | 2 +- .../ref/fate/cbs-vp9-vp90-2-10-show-existing-frame2 | 2 +- tests/ref/fate/cbs-vp9-vp90-2-segmentation-aq-akiyo | 2 +- tests/ref/fate/cbs-vp9-vp90-2-segmentation-sf-akiyo | 2 +- tests/ref/fate/cbs-vp9-vp90-2-tiling-pedestrian | 2 +- tests/ref/fate/cbs-vp9-vp91-2-04-yuv440 | 2 +- tests/ref/fate/cbs-vp9-vp91-2-04-yuv444 | 2 +- tests/ref/fate/cbs-vp9-vp92-2-20-10bit-yuv420 | 2 +- tests/ref/fate/cbs-vp9-vp93-2-20-10bit-yuv422 | 2 +- tests/ref/fate/cbs-vp9-vp93-2-20-12bit-yuv444 | 2 +- 15 files changed, 28 insertions(+), 24 deletions(-) diff --git a/libavformat/ivfdec.c b/libavformat/ivfdec.c index 511f2387ede..141ce4f1be9 100644 --- a/libavformat/ivfdec.c +++ b/libavformat/ivfdec.c @@ -51,11 +51,18 @@ static int read_header(AVFormatContext *s) st->codecpar->codec_id = ff_codec_get_id(ff_codec_bmp_tags, st->codecpar->codec_tag); st->codecpar->width = avio_rl16(s->pb); st->codecpar->height = avio_rl16(s->pb); - time_base.den = avio_rl32(s->pb); - time_base.num = avio_rl32(s->pb); - st->duration = avio_rl32(s->pb); + time_base.den = avio_rl32(s->pb); + time_base.num = avio_rl32(s->pb); + st->nb_frames = avio_rl32(s->pb); avio_skip(s->pb, 4); // unused + // Infer duration from nb_frames, in order to be backward compatible with + // previous IVF demuxer. + // It is popular to configure time_base to 1/frame_rate by IVF muxer, that + // the duration happens to be the same with nb_frames. See + // `https://chromium.googlesource.com/webm/vp8-test-vectors/+/refs/heads/main` + st->duration = st->nb_frames; + ffstream(st)->need_parsing = AVSTREAM_PARSE_HEADERS; if (!time_base.den || !time_base.num) { diff --git a/libavformat/ivfenc.c b/libavformat/ivfenc.c index 47b4efbcd10..88399099d45 100644 --- a/libavformat/ivfenc.c +++ b/libavformat/ivfenc.c @@ -72,7 +72,8 @@ static int ivf_write_header(AVFormatContext *s) avio_wl16(pb, par->height); avio_wl32(pb, s->streams[0]->time_base.den); avio_wl32(pb, s->streams[0]->time_base.num); - avio_wl64(pb, 0xFFFFFFFFFFFFFFFFULL); // length is overwritten at the end of muxing + avio_wl32(pb, 0xFFFFFFFF); // "number of frames" is overwritten at the end of muxing + avio_wl32(pb, 0); // unused return 0; } @@ -99,16 +100,12 @@ static int ivf_write_trailer(AVFormatContext *s) AVIOContext *pb = s->pb; IVFEncContext *ctx = s->priv_data; - if ((pb->seekable & AVIO_SEEKABLE_NORMAL) && - (ctx->frame_cnt > 1 || (ctx->frame_cnt == 1 && ctx->last_pkt_duration))) { + // overwrite the "number of frames" + if ((pb->seekable & AVIO_SEEKABLE_NORMAL)) { int64_t end = avio_tell(pb); avio_seek(pb, 24, SEEK_SET); - // overwrite the "length" field (duration) - avio_wl32(pb, ctx->last_pkt_duration ? - ctx->sum_delta_pts + ctx->last_pkt_duration : - ctx->frame_cnt * ctx->sum_delta_pts / (ctx->frame_cnt - 1)); - avio_wl32(pb, 0); // zero out unused bytes + avio_wl32(pb, ctx->frame_cnt); avio_seek(pb, end, SEEK_SET); } diff --git a/tests/ref/fate/cbs-vp9-vp90-2-03-deltaq b/tests/ref/fate/cbs-vp9-vp90-2-03-deltaq index db09cfd5e02..f621d7a4809 100644 --- a/tests/ref/fate/cbs-vp9-vp90-2-03-deltaq +++ b/tests/ref/fate/cbs-vp9-vp90-2-03-deltaq @@ -1 +1 @@ -bb630ef560f83951fa6547a664fdb636 +fe62460fe28202e0666e628afd8602ca diff --git a/tests/ref/fate/cbs-vp9-vp90-2-06-bilinear b/tests/ref/fate/cbs-vp9-vp90-2-06-bilinear index f5794591792..9359e21e403 100644 --- a/tests/ref/fate/cbs-vp9-vp90-2-06-bilinear +++ b/tests/ref/fate/cbs-vp9-vp90-2-06-bilinear @@ -1 +1 @@ -2ca9d012c7212e38f5e2727ac66ec6c5 +179e228004c396a301c89f34b6c72f68 diff --git a/tests/ref/fate/cbs-vp9-vp90-2-09-lf_deltas b/tests/ref/fate/cbs-vp9-vp90-2-09-lf_deltas index e0b5686d0b7..5b21675c768 100644 --- a/tests/ref/fate/cbs-vp9-vp90-2-09-lf_deltas +++ b/tests/ref/fate/cbs-vp9-vp90-2-09-lf_deltas @@ -1 +1 @@ -78f5e46bfaecbcd62b9126697a0d97b7 +1d1f0768c547461ae2abef57f0aabc24 diff --git a/tests/ref/fate/cbs-vp9-vp90-2-10-show-existing-frame b/tests/ref/fate/cbs-vp9-vp90-2-10-show-existing-frame index 4a4d7524283..19b7a78dd8f 100644 --- a/tests/ref/fate/cbs-vp9-vp90-2-10-show-existing-frame +++ b/tests/ref/fate/cbs-vp9-vp90-2-10-show-existing-frame @@ -1 +1 @@ -eea9d10a696c6ed971e4fae9fb619b10 +13fa042ee1b4079c227a5c5c96e2db38 diff --git a/tests/ref/fate/cbs-vp9-vp90-2-10-show-existing-frame2 b/tests/ref/fate/cbs-vp9-vp90-2-10-show-existing-frame2 index 6da89991142..e7bf2a078d7 100644 --- a/tests/ref/fate/cbs-vp9-vp90-2-10-show-existing-frame2 +++ b/tests/ref/fate/cbs-vp9-vp90-2-10-show-existing-frame2 @@ -1 +1 @@ -abf4c7d4be7d3576d96b6f92166b5894 +2ab7c95e4637fb6a15efd8c0a8d6af98 diff --git a/tests/ref/fate/cbs-vp9-vp90-2-segmentation-aq-akiyo b/tests/ref/fate/cbs-vp9-vp90-2-segmentation-aq-akiyo index 12dfb10d401..f30889dbdcf 100644 --- a/tests/ref/fate/cbs-vp9-vp90-2-segmentation-aq-akiyo +++ b/tests/ref/fate/cbs-vp9-vp90-2-segmentation-aq-akiyo @@ -1 +1 @@ -86cd3750cc9a0672717643c9b9f87fd5 +b5be66a6a8792f7aac090beb9f3b4555 diff --git a/tests/ref/fate/cbs-vp9-vp90-2-segmentation-sf-akiyo b/tests/ref/fate/cbs-vp9-vp90-2-segmentation-sf-akiyo index c2b1b8723a0..dca77f21131 100644 --- a/tests/ref/fate/cbs-vp9-vp90-2-segmentation-sf-akiyo +++ b/tests/ref/fate/cbs-vp9-vp90-2-segmentation-sf-akiyo @@ -1 +1 @@ -5d12fbe6220aae9e62b1d79785a83387 +7bde6532fc682bfa3f5170cf9d607865 diff --git a/tests/ref/fate/cbs-vp9-vp90-2-tiling-pedestrian b/tests/ref/fate/cbs-vp9-vp90-2-tiling-pedestrian index f9cab39bd6c..0aa3cc8ce6f 100644 --- a/tests/ref/fate/cbs-vp9-vp90-2-tiling-pedestrian +++ b/tests/ref/fate/cbs-vp9-vp90-2-tiling-pedestrian @@ -1 +1 @@ -4c51f3c796baa7c2baa4b7ec0d011406 +1e40e8b48e4682e8b8004b9e0e60a5b6 diff --git a/tests/ref/fate/cbs-vp9-vp91-2-04-yuv440 b/tests/ref/fate/cbs-vp9-vp91-2-04-yuv440 index 62899300701..947e1229eb7 100644 --- a/tests/ref/fate/cbs-vp9-vp91-2-04-yuv440 +++ b/tests/ref/fate/cbs-vp9-vp91-2-04-yuv440 @@ -1 +1 @@ -293bdc92851ca1105e27f04737d8c5f3 +9bb416c0304a13c4f66c56aef8431cd4 diff --git a/tests/ref/fate/cbs-vp9-vp91-2-04-yuv444 b/tests/ref/fate/cbs-vp9-vp91-2-04-yuv444 index 628ea9a4d99..bf251138ed3 100644 --- a/tests/ref/fate/cbs-vp9-vp91-2-04-yuv444 +++ b/tests/ref/fate/cbs-vp9-vp91-2-04-yuv444 @@ -1 +1 @@ -911eafd8e442e646c5ce97d781757ca8 +3a7ed001d30f96d4888f5ca16e6263ce diff --git a/tests/ref/fate/cbs-vp9-vp92-2-20-10bit-yuv420 b/tests/ref/fate/cbs-vp9-vp92-2-20-10bit-yuv420 index eeb7580d74d..2cad8b947c8 100644 --- a/tests/ref/fate/cbs-vp9-vp92-2-20-10bit-yuv420 +++ b/tests/ref/fate/cbs-vp9-vp92-2-20-10bit-yuv420 @@ -1 +1 @@ -16198c32c29228e0513004ed1bf6fcee +7315bb7b55693a87c350b48cd2ee9811 diff --git a/tests/ref/fate/cbs-vp9-vp93-2-20-10bit-yuv422 b/tests/ref/fate/cbs-vp9-vp93-2-20-10bit-yuv422 index b25bc1166e9..bb1c0f7ea7b 100644 --- a/tests/ref/fate/cbs-vp9-vp93-2-20-10bit-yuv422 +++ b/tests/ref/fate/cbs-vp9-vp93-2-20-10bit-yuv422 @@ -1 +1 @@ -4bceedef4aa6a663a09761971e43b5a8 +1a7b5bf86bf0bbef10c9a1b2c799b276 diff --git a/tests/ref/fate/cbs-vp9-vp93-2-20-12bit-yuv444 b/tests/ref/fate/cbs-vp9-vp93-2-20-12bit-yuv444 index 8d122d13704..9b7b358d04e 100644 --- a/tests/ref/fate/cbs-vp9-vp93-2-20-12bit-yuv444 +++ b/tests/ref/fate/cbs-vp9-vp93-2-20-12bit-yuv444 @@ -1 +1 @@ -0f413b840633bfcfcc78b4c9fab933bf +9b7a0b7fc081542d9be1074b23054861 From 1c61c24f5f681c573afce2fba804962e88ca262a Mon Sep 17 00:00:00 2001 From: Philip Langdale Date: Mon, 10 Jul 2023 16:35:17 +0800 Subject: [PATCH 1790/2172] vulkan/hevc: handle missing active PPS I don't pretend to understand how we get into this situation, but there are files out there where we can end up with the active PPS not being identified when we call vk_hevc_end_frame. In these situations today, we will segfault. So, before we give up, see if we can get the active PPS id from the slice header, and use that if possible. If that still doesn't work, return an error instead of segfaulting. --- libavcodec/vulkan_hevc.c | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/libavcodec/vulkan_hevc.c b/libavcodec/vulkan_hevc.c index af5da3984bc..ab0f6b96d0f 100644 --- a/libavcodec/vulkan_hevc.c +++ b/libavcodec/vulkan_hevc.c @@ -900,6 +900,7 @@ static int vk_hevc_end_frame(AVCodecContext *avctx) FFVulkanDecodePicture *vp = &hp->vp; FFVulkanDecodePicture *rvp[HEVC_MAX_REFS] = { 0 }; AVFrame *rav[HEVC_MAX_REFS] = { 0 }; + int err; if (!hp->h265_pic_info.sliceSegmentCount) return 0; @@ -908,7 +909,19 @@ static int vk_hevc_end_frame(AVCodecContext *avctx) const HEVCSPS *sps = h->ps.sps; const HEVCPPS *pps = h->ps.pps; - int err = vk_hevc_create_params(avctx, &dec->session_params); + if (!pps) { + unsigned int pps_id = h->sh.pps_id; + if (pps_id < HEVC_MAX_PPS_COUNT && h->ps.pps_list[pps_id] != NULL) + pps = (const HEVCPPS *)h->ps.pps_list[pps_id]->data; + } + + if (!pps) { + av_log(avctx, AV_LOG_ERROR, + "Encountered frame without a valid active PPS reference.\n"); + return AVERROR_INVALIDDATA; + } + + err = vk_hevc_create_params(avctx, &dec->session_params); if (err < 0) return err; From f6dc85ae1610b6aae40fc3c8eb61791d71ea00ab Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt Date: Mon, 10 Jul 2023 02:10:56 +0200 Subject: [PATCH 1791/2172] avcodec/hevc_ps: Improve PPS SCC extension bit depth check From the spec: "It is a requirement of bitstream conformance that the value of luma_bit_depth_entry_minus8 shall be equal to the value of bit_depth_luma_minus8"; similarly for chroma. Also fixes Coverity ticket #1529226 (complaining about the fact that chroma_bit_depth_entry is checked twice). Reviewed-by: James Almer Signed-off-by: Andreas Rheinhardt --- libavcodec/hevc_ps.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/libavcodec/hevc_ps.c b/libavcodec/hevc_ps.c index 4c4c1e2c174..1db2d3a2429 100644 --- a/libavcodec/hevc_ps.c +++ b/libavcodec/hevc_ps.c @@ -1581,11 +1581,13 @@ static int pps_scc_extension(GetBitContext *gb, AVCodecContext *avctx, } pps->monochrome_palette_flag = get_bits1(gb); pps->luma_bit_depth_entry = get_ue_golomb_31(gb) + 8; - if (!pps->monochrome_palette_flag) - pps->chroma_bit_depth_entry = get_ue_golomb_31(gb) + 8; - - if (pps->chroma_bit_depth_entry > 16 || pps->chroma_bit_depth_entry > 16) + if (pps->luma_bit_depth_entry != sps->bit_depth) return AVERROR_INVALIDDATA; + if (!pps->monochrome_palette_flag) { + pps->chroma_bit_depth_entry = get_ue_golomb_31(gb) + 8; + if (pps->chroma_bit_depth_entry != sps->bit_depth_chroma) + return AVERROR_INVALIDDATA; + } num_comps = pps->monochrome_palette_flag ? 1 : 3; for (int comp = 0; comp < num_comps; comp++) { From a92dbeb9ae520d39069381be528c5e8d4756da5f Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt Date: Mon, 10 Jul 2023 01:26:31 +0200 Subject: [PATCH 1792/2172] avcodec/decode: Return EAGAIN instead of discarding unused packet Should fix #10457, a regression caused by 69516ab3e917a6e91d26e38d04183c60fd71cbab. Reviewed-by: Anton Khirnov Signed-off-by: Andreas Rheinhardt --- libavcodec/decode.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/libavcodec/decode.c b/libavcodec/decode.c index 269633ce106..a47abeca060 100644 --- a/libavcodec/decode.c +++ b/libavcodec/decode.c @@ -666,7 +666,9 @@ int attribute_align_arg avcodec_send_packet(AVCodecContext *avctx, const AVPacke if (avpkt && !avpkt->size && avpkt->data) return AVERROR(EINVAL); - av_packet_unref(avci->buffer_pkt); + if (!AVPACKET_IS_EMPTY(avci->buffer_pkt)) + return AVERROR(EAGAIN); + if (avpkt && (avpkt->data || avpkt->side_data_elems)) { ret = av_packet_ref(avci->buffer_pkt, avpkt); if (ret < 0) From 2c4fa968b60d64dc257286c7a808c26848f7bf82 Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Mon, 10 Jul 2023 10:24:52 +0200 Subject: [PATCH 1793/2172] avfilter/avf_showcwt: use av_rescale() --- libavfilter/avf_showcwt.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavfilter/avf_showcwt.c b/libavfilter/avf_showcwt.c index ff2c06fb7a5..505c66e3ab6 100644 --- a/libavfilter/avf_showcwt.c +++ b/libavfilter/avf_showcwt.c @@ -590,7 +590,7 @@ static int config_output(AVFilterLink *outlink) s->input_sample_count = s->nb_consumed_samples; s->hop_size = s->nb_consumed_samples >> 1; s->input_padding_size = 65536; - s->output_padding_size = FFMAX(16, s->input_padding_size * s->pps / inlink->sample_rate); + s->output_padding_size = FFMAX(16, av_rescale(s->input_padding_size, s->pps, inlink->sample_rate)); outlink->w = s->w; outlink->h = s->h; From 587189cdb98b9703e00b2418807508a2015caac9 Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Mon, 10 Jul 2023 11:00:24 +0200 Subject: [PATCH 1794/2172] avfilter/avf_showcwt: simplify cache handling --- libavfilter/avf_showcwt.c | 39 ++++++++++++++------------------------- 1 file changed, 14 insertions(+), 25 deletions(-) diff --git a/libavfilter/avf_showcwt.c b/libavfilter/avf_showcwt.c index 505c66e3ab6..3ef8433b61d 100644 --- a/libavfilter/avf_showcwt.c +++ b/libavfilter/avf_showcwt.c @@ -85,7 +85,7 @@ typedef struct ShowCWTContext { unsigned *index; int *kernel_start; int *kernel_stop; - AVFrame *cache[2]; + AVFrame *cache; AVFrame *outpicref; AVFrame *fft_in; AVFrame *fft_out; @@ -168,8 +168,7 @@ static av_cold void uninit(AVFilterContext *ctx) av_freep(&s->index); av_frame_free(&s->kernel); - av_frame_free(&s->cache[0]); - av_frame_free(&s->cache[1]); + av_frame_free(&s->cache); av_frame_free(&s->outpicref); av_frame_free(&s->fft_in); av_frame_free(&s->fft_out); @@ -280,32 +279,25 @@ static int run_channel_cwt_prepare(AVFilterContext *ctx, void *arg, int jobnr, i ShowCWTContext *s = ctx->priv; const int hop_size = s->hop_size; AVFrame *fin = arg; - float *cache0 = (float *)s->cache[0]->extended_data[ch]; - float *cache = (float *)s->cache[1]->extended_data[ch]; + AVComplexFloat *cache = (AVComplexFloat *)s->cache->extended_data[ch]; AVComplexFloat *src = (AVComplexFloat *)s->fft_in->extended_data[ch]; AVComplexFloat *dst = (AVComplexFloat *)s->fft_out->extended_data[ch]; if (fin) { - const int offset = s->hop_index; const float *input = (const float *)fin->extended_data[ch]; + const int offset = s->input_padding_size - fin->nb_samples; - memcpy(&cache[offset], input, - fin->nb_samples * sizeof(float)); + memmove(cache, cache + fin->nb_samples, sizeof(*cache) * offset); + for (int n = 0; n < fin->nb_samples; n++) { + cache[offset + n].re = input[n]; + cache[offset + n].im = 0.f; + } } - if (fin == NULL) { - memset(&cache[s->hop_index], 0, - (hop_size - s->hop_index) * sizeof(float)); - } else if (s->hop_index + fin->nb_samples < hop_size) { + if (fin && s->hop_index + fin->nb_samples < hop_size) return 0; - } - for (int n = 0; n < hop_size; n++) { - src[n].re = cache0[n]; - src[n].im = 0.f; - src[n + hop_size].re = cache[n]; - src[n + hop_size].im = 0.f; - } + memcpy(src, cache, sizeof(*src) * s->input_padding_size); s->tx_fn(s->fft[jobnr], dst, src, sizeof(*src)); @@ -630,8 +622,7 @@ static int config_output(AVFilterLink *outlink) s->outpicref = ff_get_video_buffer(outlink, outlink->w, outlink->h); s->fft_in = ff_get_audio_buffer(inlink, s->fft_in_size * 2); s->fft_out = ff_get_audio_buffer(inlink, s->fft_out_size * 2); - s->cache[0] = ff_get_audio_buffer(inlink, s->hop_size); - s->cache[1] = ff_get_audio_buffer(inlink, s->hop_size); + s->cache = ff_get_audio_buffer(inlink, s->fft_in_size * 2); s->ch_out = ff_get_audio_buffer(inlink, s->frequency_band_count * 2 * s->ihop_size); s->ifft_in = av_frame_alloc(); s->ifft_out = av_frame_alloc(); @@ -641,7 +632,7 @@ static int config_output(AVFilterLink *outlink) s->kernel_stop = av_calloc(s->frequency_band_count, sizeof(*s->kernel_stop)); if (!s->outpicref || !s->fft_in || !s->fft_out || !s->ifft_in || !s->ifft_out || !s->kernel_start || !s->kernel_stop || - !s->frequency_band || !s->kernel || !s->cache[0] || !s->cache[1] || !s->index) + !s->frequency_band || !s->kernel || !s->cache || !s->index) return AVERROR(ENOMEM); s->ifft_in->format = inlink->format; @@ -983,10 +974,8 @@ static int activate(AVFilterContext *ctx) } if (s->hop_index >= s->hop_size || s->ihop_index > 0) { - if (s->hop_index) { - FFSWAP(AVFrame *, s->cache[0], s->cache[1]); + if (s->hop_index) s->hop_index = 0; - } for (int ch = 0; ch < s->nb_channels && s->ihop_index == 0; ch++) { ff_filter_execute(ctx, run_channel_cwt, (void *)&ch, NULL, From 2f2f76def7dba9930b10a09a72f5045f39be9701 Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Mon, 10 Jul 2023 12:08:13 +0200 Subject: [PATCH 1795/2172] avfilter/avf_showcwt: optimize multiplication with kernel --- libavfilter/avf_showcwt.c | 73 ++++++++++++++++++++++++++++++++------- 1 file changed, 61 insertions(+), 12 deletions(-) diff --git a/libavfilter/avf_showcwt.c b/libavfilter/avf_showcwt.c index 3ef8433b61d..8b881488159 100644 --- a/libavfilter/avf_showcwt.c +++ b/libavfilter/avf_showcwt.c @@ -25,6 +25,7 @@ #include "libavutil/avassert.h" #include "libavutil/avstring.h" #include "libavutil/channel_layout.h" +#include "libavutil/float_dsp.h" #include "libavutil/cpu.h" #include "libavutil/opt.h" #include "libavutil/parseutils.h" @@ -89,6 +90,9 @@ typedef struct ShowCWTContext { AVFrame *outpicref; AVFrame *fft_in; AVFrame *fft_out; + AVFrame *dst_x; + AVFrame *src_x; + AVFrame *kernel_x; AVFrame *ifft_in; AVFrame *ifft_out; AVFrame *ch_out; @@ -114,6 +118,8 @@ typedef struct ShowCWTContext { float minimum_frequency; float maximum_frequency; float deviation; + + AVFloatDSPContext *fdsp; } ShowCWTContext; #define OFFSET(x) offsetof(ShowCWTContext, x) @@ -172,6 +178,9 @@ static av_cold void uninit(AVFilterContext *ctx) av_frame_free(&s->outpicref); av_frame_free(&s->fft_in); av_frame_free(&s->fft_out); + av_frame_free(&s->dst_x); + av_frame_free(&s->src_x); + av_frame_free(&s->kernel_x); av_frame_free(&s->ifft_in); av_frame_free(&s->ifft_out); av_frame_free(&s->ch_out); @@ -187,6 +196,8 @@ static av_cold void uninit(AVFilterContext *ctx) av_tx_uninit(&s->ifft[n]); av_freep(&s->ifft); } + + av_freep(&s->fdsp); } static int query_formats(AVFilterContext *ctx) @@ -483,18 +494,27 @@ static int run_channel_cwt(AVFilterContext *ctx, void *arg, int jobnr, int nb_jo AVComplexFloat *isrc = (AVComplexFloat *)s->ifft_in->extended_data[y]; AVComplexFloat *idst = (AVComplexFloat *)s->ifft_out->extended_data[y]; AVComplexFloat *chout = ((AVComplexFloat *)s->ch_out->extended_data[ch]) + y * ihop_size; - const float *kernel = (const float *)s->kernel->extended_data[y]; + AVComplexFloat *dstx = (AVComplexFloat *)s->dst_x->extended_data[jobnr]; + AVComplexFloat *srcx = (AVComplexFloat *)s->src_x->extended_data[jobnr]; + AVComplexFloat *kernelx = (AVComplexFloat *)s->kernel_x->extended_data[jobnr]; + const AVComplexFloat *kernel = (const AVComplexFloat *)s->kernel->extended_data[y]; const unsigned *index = (const unsigned *)s->index; const int kernel_start = s->kernel_start[y]; const int kernel_stop = s->kernel_stop[y]; + const int kernel_range = kernel_stop - kernel_start; + + memcpy(kernelx, kernel + kernel_start, sizeof(*kernel) * kernel_range); + memcpy(srcx, dst + kernel_start, sizeof(*dst) * kernel_range); + + s->fdsp->vector_fmul((float *)dstx, (const float *)srcx, + (const float *)kernelx, FFALIGN(kernel_range * 2, 16)); memset(isrc, 0, sizeof(*isrc) * output_sample_count); - for (int i = kernel_start; i < kernel_stop; i++) { - const unsigned n = index[i]; - const float ff = kernel[i]; + for (int i = 0; i < kernel_range; i++) { + const unsigned n = index[i + kernel_start]; - isrc[n].re += ff * dst[i].re; - isrc[n].im += ff * dst[i].im; + isrc[n].re += dstx[i].re; + isrc[n].im += dstx[i].im; } s->itx_fn(s->ifft[jobnr], idst, isrc, sizeof(*isrc)); @@ -515,7 +535,7 @@ static void compute_kernel(AVFilterContext *ctx) unsigned *index = s->index; for (int y = 0; y < fsize; y++) { - float *kernel = (float *)s->kernel->extended_data[y]; + AVComplexFloat *kernel = (AVComplexFloat *)s->kernel->extended_data[y]; int *kernel_start = s->kernel_start; int *kernel_stop = s->kernel_stop; float frequency = s->frequency_band[y*2]; @@ -527,18 +547,19 @@ static void compute_kernel(AVFilterContext *ctx) f = size - fabsf(f - size); ff = expf(-f*f*deviation) * scale_factor; - kernel[n] = ff; + kernel[n].re = ff; + kernel[n].im = ff; } for (int n = 0; n < size; n++) { - if (kernel[n] != 0.f) { + if (kernel[n].re != 0.f) { kernel_start[y] = n; break; } } for (int n = 0; n < size; n++) { - if (kernel[size - n - 1] != 0.f) { + if (kernel[size - n - 1].re != 0.f) { kernel_stop[y] = size - n; break; } @@ -561,6 +582,10 @@ static int config_output(AVFilterLink *outlink) uninit(ctx); + s->fdsp = avpriv_float_dsp_alloc(0); + if (!s->fdsp) + return AVERROR(ENOMEM); + switch (s->direction) { case DIRECTION_LR: case DIRECTION_RL: @@ -622,6 +647,9 @@ static int config_output(AVFilterLink *outlink) s->outpicref = ff_get_video_buffer(outlink, outlink->w, outlink->h); s->fft_in = ff_get_audio_buffer(inlink, s->fft_in_size * 2); s->fft_out = ff_get_audio_buffer(inlink, s->fft_out_size * 2); + s->dst_x = av_frame_alloc(); + s->src_x = av_frame_alloc(); + s->kernel_x = av_frame_alloc(); s->cache = ff_get_audio_buffer(inlink, s->fft_in_size * 2); s->ch_out = ff_get_audio_buffer(inlink, s->frequency_band_count * 2 * s->ihop_size); s->ifft_in = av_frame_alloc(); @@ -630,7 +658,7 @@ static int config_output(AVFilterLink *outlink) s->index = av_calloc(s->input_padding_size, sizeof(*s->index)); s->kernel_start = av_calloc(s->frequency_band_count, sizeof(*s->kernel_start)); s->kernel_stop = av_calloc(s->frequency_band_count, sizeof(*s->kernel_stop)); - if (!s->outpicref || !s->fft_in || !s->fft_out || + if (!s->outpicref || !s->fft_in || !s->fft_out || !s->src_x || !s->dst_x || !s->kernel_x || !s->ifft_in || !s->ifft_out || !s->kernel_start || !s->kernel_stop || !s->frequency_band || !s->kernel || !s->cache || !s->index) return AVERROR(ENOMEM); @@ -650,12 +678,33 @@ static int config_output(AVFilterLink *outlink) return ret; s->kernel->format = inlink->format; - s->kernel->nb_samples = s->input_padding_size; + s->kernel->nb_samples = s->input_padding_size * 2; s->kernel->ch_layout.nb_channels = s->frequency_band_count; ret = av_frame_get_buffer(s->kernel, 0); if (ret < 0) return ret; + s->src_x->format = inlink->format; + s->src_x->nb_samples = s->fft_out_size * 2; + s->src_x->ch_layout.nb_channels = s->nb_threads; + ret = av_frame_get_buffer(s->src_x, 0); + if (ret < 0) + return ret; + + s->dst_x->format = inlink->format; + s->dst_x->nb_samples = s->fft_out_size * 2; + s->dst_x->ch_layout.nb_channels = s->nb_threads; + ret = av_frame_get_buffer(s->dst_x, 0); + if (ret < 0) + return ret; + + s->kernel_x->format = inlink->format; + s->kernel_x->nb_samples = s->fft_out_size * 2; + s->kernel_x->ch_layout.nb_channels = s->nb_threads; + ret = av_frame_get_buffer(s->kernel_x, 0); + if (ret < 0) + return ret; + s->outpicref->sample_aspect_ratio = (AVRational){1,1}; for (int y = 0; y < outlink->h; y++) { From 1324698ff306bde4dad392832f96b62b9e4284ed Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Mon, 10 Jul 2023 15:33:29 +0200 Subject: [PATCH 1796/2172] avfilter/avf_showcwt: simplify EOF checking --- libavfilter/avf_showcwt.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/libavfilter/avf_showcwt.c b/libavfilter/avf_showcwt.c index 8b881488159..a3aa7627ec7 100644 --- a/libavfilter/avf_showcwt.c +++ b/libavfilter/avf_showcwt.c @@ -1037,8 +1037,7 @@ static int activate(AVFilterContext *ctx) } } - if (s->eof && s->eof_pts != AV_NOPTS_VALUE && - (s->old_pts + 1 >= s->eof_pts || (s->slide == SLIDE_FRAME))) { + if (s->eof) { if (s->slide == SLIDE_FRAME) ret = output_frame(ctx); ff_outlink_set_status(outlink, AVERROR_EOF, s->eof_pts); From f3896a148ebdfea15de3366066bcb2fa32f7d915 Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Mon, 10 Jul 2023 15:58:47 +0200 Subject: [PATCH 1797/2172] avfilter/avf_showcwt: fix frame slide output --- libavfilter/avf_showcwt.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/libavfilter/avf_showcwt.c b/libavfilter/avf_showcwt.c index a3aa7627ec7..896e470dd10 100644 --- a/libavfilter/avf_showcwt.c +++ b/libavfilter/avf_showcwt.c @@ -597,7 +597,6 @@ static int config_output(AVFilterLink *outlink) break; } - s->new_frame = 1; s->nb_threads = FFMIN(s->frequency_band_count, ff_filter_get_nb_threads(ctx)); s->nb_channels = inlink->ch_layout.nb_channels; s->old_pts = AV_NOPTS_VALUE; @@ -1010,10 +1009,8 @@ static int activate(AVFilterContext *ctx) ff_filter_execute(ctx, run_channels_cwt_prepare, fin, NULL, FFMIN(s->nb_threads, s->nb_channels)); if (fin) { - if ((s->hop_index == 0 && s->slide != SLIDE_FRAME) || s->new_frame) { + if (s->hop_index == 0) s->in_pts = fin->pts; - s->new_frame = 0; - } s->hop_index += fin->nb_samples; av_frame_free(&fin); } else { From 75b1a555a70c178a9166629e43ec2f6250219eb2 Mon Sep 17 00:00:00 2001 From: Leo Izen Date: Sat, 8 Jul 2023 14:43:31 -0400 Subject: [PATCH 1798/2172] avcodec/libjxldec: build against libjxl 0.9 Git master libjxl changed several function signatures, so this commit adds some #ifdefs to handle the new signatures without breaking old releases. Do note that old git master development versions of libjxl will be broken, but no releases will be. Signed-off-by: Leo Izen --- libavcodec/libjxldec.c | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/libavcodec/libjxldec.c b/libavcodec/libjxldec.c index 50417bcb025..e45ac02c078 100644 --- a/libavcodec/libjxldec.c +++ b/libavcodec/libjxldec.c @@ -210,14 +210,22 @@ static int libjxl_get_icc(AVCodecContext *avctx) JxlDecoderStatus jret; /* an ICC profile is present, and we can meaningfully get it, * because the pixel data is not XYB-encoded */ +#if JPEGXL_NUMERIC_VERSION < JPEGXL_COMPUTE_NUMERIC_VERSION(0, 9, 0) jret = JxlDecoderGetICCProfileSize(ctx->decoder, &ctx->jxl_pixfmt, JXL_COLOR_PROFILE_TARGET_DATA, &icc_len); +#else + jret = JxlDecoderGetICCProfileSize(ctx->decoder, JXL_COLOR_PROFILE_TARGET_DATA, &icc_len); +#endif if (jret == JXL_DEC_SUCCESS && icc_len > 0) { av_buffer_unref(&ctx->iccp); ctx->iccp = av_buffer_alloc(icc_len); if (!ctx->iccp) return AVERROR(ENOMEM); +#if JPEGXL_NUMERIC_VERSION < JPEGXL_COMPUTE_NUMERIC_VERSION(0, 9, 0) jret = JxlDecoderGetColorAsICCProfile(ctx->decoder, &ctx->jxl_pixfmt, JXL_COLOR_PROFILE_TARGET_DATA, - ctx->iccp->data, icc_len); + ctx->iccp->data, icc_len); +#else + jret = JxlDecoderGetColorAsICCProfile(ctx->decoder, JXL_COLOR_PROFILE_TARGET_DATA, ctx->iccp->data, icc_len); +#endif if (jret != JXL_DEC_SUCCESS) { av_log(avctx, AV_LOG_WARNING, "Unable to obtain ICC Profile\n"); av_buffer_unref(&ctx->iccp); @@ -253,12 +261,21 @@ static int libjxl_color_encoding_event(AVCodecContext *avctx, AVFrame *frame) /* set this flag if we need to fall back on wide gamut */ int fallback = 0; +#if JPEGXL_NUMERIC_VERSION < JPEGXL_COMPUTE_NUMERIC_VERSION(0, 9, 0) jret = JxlDecoderGetColorAsEncodedProfile(ctx->decoder, NULL, JXL_COLOR_PROFILE_TARGET_ORIGINAL, &jxl_color); +#else + jret = JxlDecoderGetColorAsEncodedProfile(ctx->decoder, JXL_COLOR_PROFILE_TARGET_ORIGINAL, &jxl_color); +#endif if (jret == JXL_DEC_SUCCESS) { /* enum values describe the colors of this image */ jret = JxlDecoderSetPreferredColorProfile(ctx->decoder, &jxl_color); if (jret == JXL_DEC_SUCCESS) - jret = JxlDecoderGetColorAsEncodedProfile(ctx->decoder, &ctx->jxl_pixfmt, JXL_COLOR_PROFILE_TARGET_DATA, &jxl_color); +#if JPEGXL_NUMERIC_VERSION < JPEGXL_COMPUTE_NUMERIC_VERSION(0, 9, 0) + jret = JxlDecoderGetColorAsEncodedProfile(ctx->decoder, &ctx->jxl_pixfmt, + JXL_COLOR_PROFILE_TARGET_DATA, &jxl_color); +#else + jret = JxlDecoderGetColorAsEncodedProfile(ctx->decoder, JXL_COLOR_PROFILE_TARGET_DATA, &jxl_color); +#endif /* if we couldn't successfully request the pixel data space, we fall back on wide gamut */ /* this code path is very unlikely to happen in practice */ if (jret != JXL_DEC_SUCCESS) From bbff143b07613c3055eaa606b011168e94a3a024 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Sun, 9 Jul 2023 11:25:55 +0200 Subject: [PATCH 1799/2172] lavfi/src_movie: stop using AV_CODEC_FLAG_COPY_OPAQUE That feature is overkill for a constant pointer to AVFilterLink which can be stored in AVCodecContext.opaque (indirectly, because the link is not allocated yet at the time the codec is opened). This also avoids leaking non-NULL AVFrame.opaque to callers. --- libavfilter/src_movie.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/libavfilter/src_movie.c b/libavfilter/src_movie.c index f0d295d4bb7..e50ebc99dce 100644 --- a/libavfilter/src_movie.c +++ b/libavfilter/src_movie.c @@ -51,6 +51,7 @@ #include "video.h" typedef struct MovieStream { + AVFilterLink *link; AVStream *st; AVCodecContext *codec_ctx; int64_t discontinuity_threshold; @@ -162,7 +163,8 @@ static AVStream *find_stream(void *log, AVFormatContext *avf, const char *spec) static int get_buffer(AVCodecContext *avctx, AVFrame *frame, int flags) { int linesize_align[AV_NUM_DATA_POINTERS]; - AVFilterLink *outlink = frame->opaque; + MovieStream *st = avctx->opaque; + AVFilterLink *outlink = st->link; int w, h, ow, oh, copy = 0; AVFrame *new; @@ -202,7 +204,6 @@ static int get_buffer(AVCodecContext *avctx, AVFrame *frame, int flags) av_frame_move_ref(frame, new); av_frame_free(&new); - frame->opaque = outlink; frame->width = ow; frame->height = oh; @@ -224,7 +225,7 @@ static int open_stream(AVFilterContext *ctx, MovieStream *st, int dec_threads) if (!st->codec_ctx) return AVERROR(ENOMEM); - st->codec_ctx->flags |= AV_CODEC_FLAG_COPY_OPAQUE; + st->codec_ctx->opaque = st; st->codec_ctx->get_buffer2 = get_buffer; ret = avcodec_parameters_to_context(st->codec_ctx, st->st->codecpar); if (ret < 0) @@ -469,6 +470,8 @@ static int movie_config_output_props(AVFilterLink *outlink) break; } + st->link = outlink; + return 0; } @@ -581,7 +584,6 @@ static int activate(AVFilterContext *ctx) movie->out_index[movie->pkt->stream_index]; if (pkt_out_id >= 0) { - movie->pkt->opaque = ctx->outputs[pkt_out_id]; ret = decode_packet(ctx, pkt_out_id); } av_packet_unref(movie->pkt); From 551a9af5a1a19d2c9f6542328e279f33a2f821f0 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Thu, 22 Jun 2023 18:33:06 +0200 Subject: [PATCH 1800/2172] lavu/tests/cpu: stop processing the thread count Just print it as it is. Needed by the following commit. --- libavutil/tests/cpu.c | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/libavutil/tests/cpu.c b/libavutil/tests/cpu.c index a52637339d9..200f20388a9 100644 --- a/libavutil/tests/cpu.c +++ b/libavutil/tests/cpu.c @@ -106,7 +106,7 @@ int main(int argc, char **argv) int cpu_flags_raw = av_get_cpu_flags(); int cpu_flags_eff; int cpu_count = av_cpu_count(); - char threads[5] = "auto"; + const char *threads = "auto"; int i; for(i = 0; cpu_flag_tab[i].flag; i++) { @@ -136,11 +136,7 @@ int main(int argc, char **argv) } case 't': { - int len = av_strlcpy(threads, optarg, sizeof(threads)); - if (len >= sizeof(threads)) { - fprintf(stderr, "Invalid thread count '%s'\n", optarg); - return 2; - } + threads = optarg; } } } From 1b45405d4419d81a6ec03515129ca4bf278b9eff Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Thu, 22 Jun 2023 18:42:24 +0200 Subject: [PATCH 1801/2172] tests/fate-run: add testing with a random number of threads Useful for discovering bugs that depend on a specific thread count. Use like THREADS=randomX for a random thread count from 1 to X, with X=16 when not specified. Note that the thread count is different for every test. --- doc/fate.texi | 8 ++++++++ tests/fate-run.sh | 10 ++++++++++ 2 files changed, 18 insertions(+) diff --git a/doc/fate.texi b/doc/fate.texi index 84508560157..2fa8c34c2d5 100644 --- a/doc/fate.texi +++ b/doc/fate.texi @@ -223,6 +223,14 @@ meaning only while running the regression tests. Specify how many threads to use while running regression tests, it is quite useful to detect thread-related regressions. +This variable may be set to the string "random", optionally followed by a +number, like "random99", This will cause each test to use a random number of +threads. If a number is specified, it is used as a maximum number of threads, +otherwise 16 is the maximum. + +In case a test fails, the thread count used for it will be written into the +errfile. + @item THREAD_TYPE Specify which threading strategy test, either @samp{slice} or @samp{frame}, by default @samp{slice+frame} diff --git a/tests/fate-run.sh b/tests/fate-run.sh index e12279e4cfe..5a71ac001e2 100755 --- a/tests/fate-run.sh +++ b/tests/fate-run.sh @@ -33,6 +33,15 @@ errfile="${outdir}/${test}.err" cmpfile="${outdir}/${test}.diff" repfile="${outdir}/${test}.rep" +case $threads in + random*) + threads_max=${threads#random} + [ -z "$threads_max" ] && threads_max=16 + threads=$(awk "BEGIN { print 1+int(rand() * $threads_max) }" < /dev/null) + ;; +esac + + target_path(){ test ${1} = ${1#/} && p=${target_path}/ echo ${p}${1} @@ -630,6 +639,7 @@ fi if [ $err -eq 0 ] && test $report_type = "standard" ; then unset cmpo erro else + echo "threads=$threads" >> "$errfile" cmpo="$($base64 <$cmpfile)" erro="$($base64 <$errfile)" fi From 62cb9d97c1f9a655d3d144d7cb2b1145f890ef20 Mon Sep 17 00:00:00 2001 From: James Almer Date: Sun, 9 Jul 2023 16:16:49 -0300 Subject: [PATCH 1802/2172] avcodec/av1dec: remove FF_CODEC_CAP_SETS_PKT_DTS flag It has no effect on receive_frame() decoders. Signed-off-by: James Almer --- libavcodec/av1dec.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/libavcodec/av1dec.c b/libavcodec/av1dec.c index e7f98a6c810..cc178464b95 100644 --- a/libavcodec/av1dec.c +++ b/libavcodec/av1dec.c @@ -1527,8 +1527,7 @@ const FFCodec ff_av1_decoder = { .close = av1_decode_free, FF_CODEC_RECEIVE_FRAME_CB(av1_receive_frame), .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_AVOID_PROBING, - .caps_internal = FF_CODEC_CAP_INIT_CLEANUP | - FF_CODEC_CAP_SETS_PKT_DTS, + .caps_internal = FF_CODEC_CAP_INIT_CLEANUP, .flush = av1_decode_flush, .p.profiles = NULL_IF_CONFIG_SMALL(ff_av1_profiles), .p.priv_class = &av1_class, From 5ad78a26848ec8ab3eba42c546e9742374795749 Mon Sep 17 00:00:00 2001 From: James Almer Date: Sun, 9 Jul 2023 16:17:04 -0300 Subject: [PATCH 1803/2172] avcodec/libdav1d: remove FF_CODEC_CAP_SETS_PKT_DTS flag It has no effect on receive_frame() decoders. Signed-off-by: James Almer --- libavcodec/libdav1d.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavcodec/libdav1d.c b/libavcodec/libdav1d.c index c263157a2a6..11cdbca2748 100644 --- a/libavcodec/libdav1d.c +++ b/libavcodec/libdav1d.c @@ -698,7 +698,7 @@ const FFCodec ff_libdav1d_decoder = { .flush = libdav1d_flush, FF_CODEC_RECEIVE_FRAME_CB(libdav1d_receive_frame), .p.capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_OTHER_THREADS, - .caps_internal = FF_CODEC_CAP_SETS_PKT_DTS | FF_CODEC_CAP_SETS_FRAME_PROPS | + .caps_internal = FF_CODEC_CAP_SETS_FRAME_PROPS | FF_CODEC_CAP_AUTO_THREADS, .p.priv_class = &libdav1d_class, .p.wrapper_name = "libdav1d", From 994dbcdadee642088cd5990ab5f1fd8b926a335b Mon Sep 17 00:00:00 2001 From: James Almer Date: Sun, 9 Jul 2023 16:17:21 -0300 Subject: [PATCH 1804/2172] avcodec/mediacodecdec: remove FF_CODEC_CAP_SETS_PKT_DTS flag It has no effect on receive_frame() decoders. Signed-off-by: James Almer --- libavcodec/mediacodecdec.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/libavcodec/mediacodecdec.c b/libavcodec/mediacodecdec.c index 21464900d18..44f55947be8 100644 --- a/libavcodec/mediacodecdec.c +++ b/libavcodec/mediacodecdec.c @@ -577,8 +577,7 @@ const FFCodec ff_ ## short_name ## _mediacodec_decoder = { .flush = mediacodec_decode_flush, \ .close = mediacodec_decode_close, \ .p.capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_AVOID_PROBING | AV_CODEC_CAP_HARDWARE, \ - .caps_internal = FF_CODEC_CAP_NOT_INIT_THREADSAFE | \ - FF_CODEC_CAP_SETS_PKT_DTS, \ + .caps_internal = FF_CODEC_CAP_NOT_INIT_THREADSAFE, \ .bsfs = bsf, \ .hw_configs = mediacodec_hw_configs, \ .p.wrapper_name = "mediacodec", \ From 823387aa9f7ff9f9c138388bbdfd4152b8511941 Mon Sep 17 00:00:00 2001 From: James Almer Date: Sun, 9 Jul 2023 16:17:38 -0300 Subject: [PATCH 1805/2172] avcodec/mjpegdec: remove FF_CODEC_CAP_SETS_PKT_DTS flag It has no effect on receive_frame() decoders. Signed-off-by: James Almer --- libavcodec/mjpegdec.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavcodec/mjpegdec.c b/libavcodec/mjpegdec.c index ab7fa73819f..b42e75bcdd4 100644 --- a/libavcodec/mjpegdec.c +++ b/libavcodec/mjpegdec.c @@ -3110,6 +3110,6 @@ const FFCodec ff_smvjpeg_decoder = { .flush = decode_flush, .p.capabilities = AV_CODEC_CAP_DR1, .caps_internal = FF_CODEC_CAP_EXPORTS_CROPPING | - FF_CODEC_CAP_SETS_PKT_DTS | FF_CODEC_CAP_INIT_CLEANUP, + FF_CODEC_CAP_INIT_CLEANUP, }; #endif From 132271c54e565b05c0bf60202710e7c3e9d1f29f Mon Sep 17 00:00:00 2001 From: James Almer Date: Sun, 9 Jul 2023 16:18:19 -0300 Subject: [PATCH 1806/2172] avcodec/mmaldec: remove FF_CODEC_CAP_SETS_PKT_DTS flag It has no effect on receive_frame() decoders. Signed-off-by: James Almer --- libavcodec/mmaldec.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/libavcodec/mmaldec.c b/libavcodec/mmaldec.c index 9bfb6778b64..8d67d10cd92 100644 --- a/libavcodec/mmaldec.c +++ b/libavcodec/mmaldec.c @@ -843,8 +843,7 @@ static const AVClass ffmmal_dec_class = { .flush = ffmmal_flush, \ .p.priv_class = &ffmmal_dec_class, \ .p.capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_HARDWARE, \ - .caps_internal = FF_CODEC_CAP_NOT_INIT_THREADSAFE | \ - FF_CODEC_CAP_SETS_PKT_DTS, \ + .caps_internal = FF_CODEC_CAP_NOT_INIT_THREADSAFE \ .p.pix_fmts = (const enum AVPixelFormat[]) { AV_PIX_FMT_MMAL, \ AV_PIX_FMT_YUV420P, \ AV_PIX_FMT_NONE}, \ From 31ae95d988027a61922d47da622bc17357b49af2 Mon Sep 17 00:00:00 2001 From: James Almer Date: Sun, 9 Jul 2023 16:20:44 -0300 Subject: [PATCH 1807/2172] avcodec/v4l2_m2m_dec: remove FF_CODEC_CAP_SETS_PKT_DTS flag It has no effect on receive_frame() decoders. Signed-off-by: James Almer --- libavcodec/v4l2_m2m_dec.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavcodec/v4l2_m2m_dec.c b/libavcodec/v4l2_m2m_dec.c index 4944d085119..aa2d759e1ea 100644 --- a/libavcodec/v4l2_m2m_dec.c +++ b/libavcodec/v4l2_m2m_dec.c @@ -253,7 +253,7 @@ static const AVOption options[] = { .bsfs = bsf_name, \ .p.capabilities = AV_CODEC_CAP_HARDWARE | AV_CODEC_CAP_DELAY | AV_CODEC_CAP_AVOID_PROBING, \ .caps_internal = FF_CODEC_CAP_NOT_INIT_THREADSAFE | \ - FF_CODEC_CAP_SETS_PKT_DTS | FF_CODEC_CAP_INIT_CLEANUP, \ + FF_CODEC_CAP_INIT_CLEANUP, \ .p.wrapper_name = "v4l2m2m", \ } From 2bbb6cf74eb8db58f2e1cbb862434f7ec8f9e95d Mon Sep 17 00:00:00 2001 From: James Almer Date: Sun, 9 Jul 2023 16:19:09 -0300 Subject: [PATCH 1808/2172] avcodec/test/avcodec: check decoders for FF_CODEC_CAP_SETS_PKT_DTS Ensure that only decode() callback ones set it. Signed-off-by: James Almer --- libavcodec/tests/avcodec.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/libavcodec/tests/avcodec.c b/libavcodec/tests/avcodec.c index bbf5289af2f..08ca507bf0e 100644 --- a/libavcodec/tests/avcodec.c +++ b/libavcodec/tests/avcodec.c @@ -175,6 +175,10 @@ int main(void){ !(codec->capabilities & AV_CODEC_CAP_FRAME_THREADS)) ERR("Decoder %s wants allocated progress without supporting" "frame threads\n"); + if (codec2->cb_type != FF_CODEC_CB_TYPE_DECODE && + codec2->caps_internal & FF_CODEC_CAP_SETS_PKT_DTS) + ERR("Decoder %s is marked as setting pkt_dts when it doesn't have" + "any effect\n"); } if (priv_data_size_wrong(codec2)) ERR_EXT("Private context of codec %s is impossibly-sized (size %d).", From 160fefacd3feb6107a42f030fa16b00fc95fae13 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Thu, 6 Jul 2023 17:58:19 +0200 Subject: [PATCH 1809/2172] lavc/encode: print separate messages for unknown and unsupported formats The former is typically a bug in the calling program, while the latter will more often be a user configuration issue. --- libavcodec/encode.c | 25 +++++++++++++++++-------- 1 file changed, 17 insertions(+), 8 deletions(-) diff --git a/libavcodec/encode.c b/libavcodec/encode.c index 58eab5b0015..15f6eb11d06 100644 --- a/libavcodec/encode.c +++ b/libavcodec/encode.c @@ -24,6 +24,7 @@ #include "libavutil/frame.h" #include "libavutil/imgutils.h" #include "libavutil/internal.h" +#include "libavutil/pixdesc.h" #include "libavutil/samplefmt.h" #include "avcodec.h" @@ -576,15 +577,19 @@ static int encode_preinit_video(AVCodecContext *avctx) const AVPixFmtDescriptor *pixdesc = av_pix_fmt_desc_get(avctx->pix_fmt); int i; + if (!av_get_pix_fmt_name(avctx->pix_fmt)) { + av_log(avctx, AV_LOG_ERROR, "Invalid video pixel format: %d\n", + avctx->pix_fmt); + return AVERROR(EINVAL); + } + if (avctx->codec->pix_fmts) { for (i = 0; avctx->codec->pix_fmts[i] != AV_PIX_FMT_NONE; i++) if (avctx->pix_fmt == avctx->codec->pix_fmts[i]) break; if (avctx->codec->pix_fmts[i] == AV_PIX_FMT_NONE) { - char buf[128]; - snprintf(buf, sizeof(buf), "%d", avctx->pix_fmt); - av_log(avctx, AV_LOG_ERROR, "Specified pixel format %s is invalid or not supported\n", - (char *)av_x_if_null(av_get_pix_fmt_name(avctx->pix_fmt), buf)); + av_log(avctx, AV_LOG_ERROR, "Specified pixel format %s is not supported\n", + av_get_pix_fmt_name(avctx->pix_fmt)); return AVERROR(EINVAL); } if (avctx->codec->pix_fmts[i] == AV_PIX_FMT_YUVJ420P || @@ -646,6 +651,12 @@ static int encode_preinit_audio(AVCodecContext *avctx) { int i; + if (!av_get_sample_fmt_name(avctx->sample_fmt)) { + av_log(avctx, AV_LOG_ERROR, "Invalid audio sample format: %d\n", + avctx->sample_fmt); + return AVERROR(EINVAL); + } + if (avctx->codec->sample_fmts) { for (i = 0; avctx->codec->sample_fmts[i] != AV_SAMPLE_FMT_NONE; i++) { if (avctx->sample_fmt == avctx->codec->sample_fmts[i]) @@ -658,10 +669,8 @@ static int encode_preinit_audio(AVCodecContext *avctx) } } if (avctx->codec->sample_fmts[i] == AV_SAMPLE_FMT_NONE) { - char buf[128]; - snprintf(buf, sizeof(buf), "%d", avctx->sample_fmt); - av_log(avctx, AV_LOG_ERROR, "Specified sample format %s is invalid or not supported\n", - (char *)av_x_if_null(av_get_sample_fmt_name(avctx->sample_fmt), buf)); + av_log(avctx, AV_LOG_ERROR, "Specified sample format %s is not supported\n", + av_get_sample_fmt_name(avctx->sample_fmt)); return AVERROR(EINVAL); } } From e026395d22eb217623ae16d3e5592c1e1a2c9336 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Thu, 6 Jul 2023 18:11:24 +0200 Subject: [PATCH 1810/2172] lavc/encode: shorten code by using a local variable --- libavcodec/encode.c | 48 +++++++++++++++++++++++---------------------- 1 file changed, 25 insertions(+), 23 deletions(-) diff --git a/libavcodec/encode.c b/libavcodec/encode.c index 15f6eb11d06..fd182007cc1 100644 --- a/libavcodec/encode.c +++ b/libavcodec/encode.c @@ -574,6 +574,7 @@ int attribute_align_arg avcodec_receive_packet(AVCodecContext *avctx, AVPacket * static int encode_preinit_video(AVCodecContext *avctx) { + const AVCodec *c = avctx->codec; const AVPixFmtDescriptor *pixdesc = av_pix_fmt_desc_get(avctx->pix_fmt); int i; @@ -583,20 +584,20 @@ static int encode_preinit_video(AVCodecContext *avctx) return AVERROR(EINVAL); } - if (avctx->codec->pix_fmts) { - for (i = 0; avctx->codec->pix_fmts[i] != AV_PIX_FMT_NONE; i++) - if (avctx->pix_fmt == avctx->codec->pix_fmts[i]) + if (c->pix_fmts) { + for (i = 0; c->pix_fmts[i] != AV_PIX_FMT_NONE; i++) + if (avctx->pix_fmt == c->pix_fmts[i]) break; - if (avctx->codec->pix_fmts[i] == AV_PIX_FMT_NONE) { + if (c->pix_fmts[i] == AV_PIX_FMT_NONE) { av_log(avctx, AV_LOG_ERROR, "Specified pixel format %s is not supported\n", av_get_pix_fmt_name(avctx->pix_fmt)); return AVERROR(EINVAL); } - if (avctx->codec->pix_fmts[i] == AV_PIX_FMT_YUVJ420P || - avctx->codec->pix_fmts[i] == AV_PIX_FMT_YUVJ411P || - avctx->codec->pix_fmts[i] == AV_PIX_FMT_YUVJ422P || - avctx->codec->pix_fmts[i] == AV_PIX_FMT_YUVJ440P || - avctx->codec->pix_fmts[i] == AV_PIX_FMT_YUVJ444P) + if (c->pix_fmts[i] == AV_PIX_FMT_YUVJ420P || + c->pix_fmts[i] == AV_PIX_FMT_YUVJ411P || + c->pix_fmts[i] == AV_PIX_FMT_YUVJ422P || + c->pix_fmts[i] == AV_PIX_FMT_YUVJ440P || + c->pix_fmts[i] == AV_PIX_FMT_YUVJ444P) avctx->color_range = AVCOL_RANGE_JPEG; } @@ -649,6 +650,7 @@ FF_ENABLE_DEPRECATION_WARNINGS static int encode_preinit_audio(AVCodecContext *avctx) { + const AVCodec *c = avctx->codec; int i; if (!av_get_sample_fmt_name(avctx->sample_fmt)) { @@ -657,28 +659,28 @@ static int encode_preinit_audio(AVCodecContext *avctx) return AVERROR(EINVAL); } - if (avctx->codec->sample_fmts) { - for (i = 0; avctx->codec->sample_fmts[i] != AV_SAMPLE_FMT_NONE; i++) { - if (avctx->sample_fmt == avctx->codec->sample_fmts[i]) + if (c->sample_fmts) { + for (i = 0; c->sample_fmts[i] != AV_SAMPLE_FMT_NONE; i++) { + if (avctx->sample_fmt == c->sample_fmts[i]) break; if (avctx->ch_layout.nb_channels == 1 && av_get_planar_sample_fmt(avctx->sample_fmt) == - av_get_planar_sample_fmt(avctx->codec->sample_fmts[i])) { - avctx->sample_fmt = avctx->codec->sample_fmts[i]; + av_get_planar_sample_fmt(c->sample_fmts[i])) { + avctx->sample_fmt = c->sample_fmts[i]; break; } } - if (avctx->codec->sample_fmts[i] == AV_SAMPLE_FMT_NONE) { + if (c->sample_fmts[i] == AV_SAMPLE_FMT_NONE) { av_log(avctx, AV_LOG_ERROR, "Specified sample format %s is not supported\n", av_get_sample_fmt_name(avctx->sample_fmt)); return AVERROR(EINVAL); } } - if (avctx->codec->supported_samplerates) { - for (i = 0; avctx->codec->supported_samplerates[i] != 0; i++) - if (avctx->sample_rate == avctx->codec->supported_samplerates[i]) + if (c->supported_samplerates) { + for (i = 0; c->supported_samplerates[i] != 0; i++) + if (avctx->sample_rate == c->supported_samplerates[i]) break; - if (avctx->codec->supported_samplerates[i] == 0) { + if (c->supported_samplerates[i] == 0) { av_log(avctx, AV_LOG_ERROR, "Specified sample rate %d is not supported\n", avctx->sample_rate); return AVERROR(EINVAL); @@ -689,12 +691,12 @@ static int encode_preinit_audio(AVCodecContext *avctx) avctx->sample_rate); return AVERROR(EINVAL); } - if (avctx->codec->ch_layouts) { - for (i = 0; avctx->codec->ch_layouts[i].nb_channels; i++) { - if (!av_channel_layout_compare(&avctx->ch_layout, &avctx->codec->ch_layouts[i])) + if (c->ch_layouts) { + for (i = 0; c->ch_layouts[i].nb_channels; i++) { + if (!av_channel_layout_compare(&avctx->ch_layout, &c->ch_layouts[i])) break; } - if (!avctx->codec->ch_layouts[i].nb_channels) { + if (!c->ch_layouts[i].nb_channels) { char buf[512]; int ret = av_channel_layout_describe(&avctx->ch_layout, buf, sizeof(buf)); if (ret > 0) From fc6c746aa17fd4434cf81f045c4644ded02b0912 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Thu, 6 Jul 2023 18:25:40 +0200 Subject: [PATCH 1811/2172] lavc/encoder: always print an error on an unsupported channel layout Even if the layout is indescribable. --- libavcodec/encode.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libavcodec/encode.c b/libavcodec/encode.c index fd182007cc1..f443f07e150 100644 --- a/libavcodec/encode.c +++ b/libavcodec/encode.c @@ -699,8 +699,8 @@ static int encode_preinit_audio(AVCodecContext *avctx) if (!c->ch_layouts[i].nb_channels) { char buf[512]; int ret = av_channel_layout_describe(&avctx->ch_layout, buf, sizeof(buf)); - if (ret > 0) - av_log(avctx, AV_LOG_ERROR, "Specified channel layout '%s' is not supported\n", buf); + av_log(avctx, AV_LOG_ERROR, "Specified channel layout '%s' is not supported\n", + ret > 0 ? buf : "?"); return AVERROR(EINVAL); } } From 39206c5e581f5020fe47adf463a759b0f39186d8 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Thu, 6 Jul 2023 18:16:49 +0200 Subject: [PATCH 1812/2172] lavc/encode: improve input sample rate validation Reject zero sample rates in addition to negative ones and describe them as 'invalid' rather than 'unsupported'. --- libavcodec/encode.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/libavcodec/encode.c b/libavcodec/encode.c index f443f07e150..0d009a26ccd 100644 --- a/libavcodec/encode.c +++ b/libavcodec/encode.c @@ -658,6 +658,11 @@ static int encode_preinit_audio(AVCodecContext *avctx) avctx->sample_fmt); return AVERROR(EINVAL); } + if (avctx->sample_rate <= 0) { + av_log(avctx, AV_LOG_ERROR, "Invalid audio sample rate: %d\n", + avctx->sample_rate); + return AVERROR(EINVAL); + } if (c->sample_fmts) { for (i = 0; c->sample_fmts[i] != AV_SAMPLE_FMT_NONE; i++) { @@ -686,11 +691,6 @@ static int encode_preinit_audio(AVCodecContext *avctx) return AVERROR(EINVAL); } } - if (avctx->sample_rate < 0) { - av_log(avctx, AV_LOG_ERROR, "Specified sample rate %d is not supported\n", - avctx->sample_rate); - return AVERROR(EINVAL); - } if (c->ch_layouts) { for (i = 0; c->ch_layouts[i].nb_channels; i++) { if (!av_channel_layout_compare(&avctx->ch_layout, &c->ch_layouts[i])) From afeb2468b251604aa249cba23f0fac022f54195e Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Thu, 6 Jul 2023 18:13:41 +0200 Subject: [PATCH 1813/2172] lavc/encode: improve unsupported-format error messages Mention encoder name in the message to emphasize that the value in question is not supported by this specific encoder, not necessarily by libavcodec in general. Print a list of values supported by the encoder. --- libavcodec/encode.c | 45 +++++++++++++++++++++++++++++++++++++-------- 1 file changed, 37 insertions(+), 8 deletions(-) diff --git a/libavcodec/encode.c b/libavcodec/encode.c index 0d009a26ccd..32cc903b1f8 100644 --- a/libavcodec/encode.c +++ b/libavcodec/encode.c @@ -589,8 +589,16 @@ static int encode_preinit_video(AVCodecContext *avctx) if (avctx->pix_fmt == c->pix_fmts[i]) break; if (c->pix_fmts[i] == AV_PIX_FMT_NONE) { - av_log(avctx, AV_LOG_ERROR, "Specified pixel format %s is not supported\n", - av_get_pix_fmt_name(avctx->pix_fmt)); + av_log(avctx, AV_LOG_ERROR, + "Specified pixel format %s is not supported by the %s encoder.\n", + av_get_pix_fmt_name(avctx->pix_fmt), c->name); + + av_log(avctx, AV_LOG_ERROR, "Supported pixel formats:\n"); + for (int p = 0; c->pix_fmts[p] != AV_PIX_FMT_NONE; p++) { + av_log(avctx, AV_LOG_ERROR, " %s\n", + av_get_pix_fmt_name(c->pix_fmts[p])); + } + return AVERROR(EINVAL); } if (c->pix_fmts[i] == AV_PIX_FMT_YUVJ420P || @@ -676,8 +684,16 @@ static int encode_preinit_audio(AVCodecContext *avctx) } } if (c->sample_fmts[i] == AV_SAMPLE_FMT_NONE) { - av_log(avctx, AV_LOG_ERROR, "Specified sample format %s is not supported\n", - av_get_sample_fmt_name(avctx->sample_fmt)); + av_log(avctx, AV_LOG_ERROR, + "Specified sample format %s is not supported by the %s encoder\n", + av_get_sample_fmt_name(avctx->sample_fmt), c->name); + + av_log(avctx, AV_LOG_ERROR, "Supported sample formats:\n"); + for (int p = 0; c->sample_fmts[p] != AV_SAMPLE_FMT_NONE; p++) { + av_log(avctx, AV_LOG_ERROR, " %s\n", + av_get_sample_fmt_name(c->sample_fmts[p])); + } + return AVERROR(EINVAL); } } @@ -686,8 +702,14 @@ static int encode_preinit_audio(AVCodecContext *avctx) if (avctx->sample_rate == c->supported_samplerates[i]) break; if (c->supported_samplerates[i] == 0) { - av_log(avctx, AV_LOG_ERROR, "Specified sample rate %d is not supported\n", - avctx->sample_rate); + av_log(avctx, AV_LOG_ERROR, + "Specified sample rate %d is not supported by the %s encoder\n", + avctx->sample_rate, c->name); + + av_log(avctx, AV_LOG_ERROR, "Supported sample rates:\n"); + for (int p = 0; c->supported_samplerates[p]; p++) + av_log(avctx, AV_LOG_ERROR, " %d\n", c->supported_samplerates[p]); + return AVERROR(EINVAL); } } @@ -699,8 +721,15 @@ static int encode_preinit_audio(AVCodecContext *avctx) if (!c->ch_layouts[i].nb_channels) { char buf[512]; int ret = av_channel_layout_describe(&avctx->ch_layout, buf, sizeof(buf)); - av_log(avctx, AV_LOG_ERROR, "Specified channel layout '%s' is not supported\n", - ret > 0 ? buf : "?"); + av_log(avctx, AV_LOG_ERROR, + "Specified channel layout '%s' is not supported by the %s encoder\n", + ret > 0 ? buf : "?", c->name); + + av_log(avctx, AV_LOG_ERROR, "Supported channel layouts:\n"); + for (int p = 0; c->ch_layouts[p].nb_channels; p++) { + ret = av_channel_layout_describe(&c->ch_layouts[p], buf, sizeof(buf)); + av_log(avctx, AV_LOG_ERROR, " %s\n", ret > 0 ? buf : "?"); + } return AVERROR(EINVAL); } } From fcc33ada47e594d6b35b71c4a998af796f56492e Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Thu, 6 Jul 2023 21:46:25 +0200 Subject: [PATCH 1814/2172] lavfi: make sure frame SAR matches the link value --- libavfilter/avfilter.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/libavfilter/avfilter.c b/libavfilter/avfilter.c index 0141b64cbcf..04887b6ee59 100644 --- a/libavfilter/avfilter.c +++ b/libavfilter/avfilter.c @@ -984,6 +984,8 @@ int ff_filter_frame(AVFilterLink *link, AVFrame *frame) av_assert1(frame->width == link->w); av_assert1(frame->height == link->h); } + + frame->sample_aspect_ratio = link->sample_aspect_ratio; } else { if (frame->format != link->format) { av_log(link->dst, AV_LOG_ERROR, "Format change is not supported\n"); From c9a99ffe5120e300638e1d2f6634221e17fa5234 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Thu, 8 Jun 2023 16:19:14 +0200 Subject: [PATCH 1815/2172] fftools/ffmpeg_filter: make sure no input or output is bound twice --- fftools/ffmpeg_filter.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/fftools/ffmpeg_filter.c b/fftools/ffmpeg_filter.c index 60e09866afb..432e2fced93 100644 --- a/fftools/ffmpeg_filter.c +++ b/fftools/ffmpeg_filter.c @@ -595,6 +595,8 @@ static int ifilter_bind_ist(InputFilter *ifilter, InputStream *ist) InputFilterPriv *ifp = ifp_from_ifilter(ifilter); int ret; + av_assert0(!ifp->ist); + ifp->ist = ist; ifp->type_src = ist->st->codecpar->codec_type; @@ -654,6 +656,8 @@ void ofilter_bind_ost(OutputFilter *ofilter, OutputStream *ost) FilterGraph *fg = ofilter->graph; const AVCodec *c = ost->enc_ctx->codec; + av_assert0(!ofilter->ost); + ofilter->ost = ost; av_freep(&ofilter->linklabel); From 42f3f54cf4c99f0910d40e225d538a1814490012 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Thu, 6 Jul 2023 17:09:59 +0200 Subject: [PATCH 1816/2172] fftools/ffmpeg_filter: make OutputFile.format/sample_rate private They are not used outside of the filtering code. --- fftools/ffmpeg.h | 2 -- fftools/ffmpeg_filter.c | 39 +++++++++++++++++++++++++++++---------- 2 files changed, 29 insertions(+), 12 deletions(-) diff --git a/fftools/ffmpeg.h b/fftools/ffmpeg.h index 316cd2b7a67..5b4117eeea0 100644 --- a/fftools/ffmpeg.h +++ b/fftools/ffmpeg.h @@ -296,8 +296,6 @@ typedef struct OutputFilter { /* desired output stream properties */ int width, height; - int format; - int sample_rate; AVChannelLayout ch_layout; // those are only set if no format is specified and the encoder gives us multiple options diff --git a/fftools/ffmpeg_filter.c b/fftools/ffmpeg_filter.c index 432e2fced93..b1fda7b9e8e 100644 --- a/fftools/ffmpeg_filter.c +++ b/fftools/ffmpeg_filter.c @@ -133,6 +133,19 @@ static InputFilterPriv *ifp_from_ifilter(InputFilter *ifilter) return (InputFilterPriv*)ifilter; } +typedef struct OutputFilterPriv { + OutputFilter ofilter; + + /* desired output stream properties */ + int format; + int sample_rate; +} OutputFilterPriv; + +static OutputFilterPriv *ofp_from_ofilter(OutputFilter *ofilter) +{ + return (OutputFilterPriv*)ofilter; +} + static int configure_filtergraph(FilterGraph *fg); static int sub2video_get_blank_frame(InputFilterPriv *ifp) @@ -333,11 +346,12 @@ static const char *choose_pix_fmts(OutputFilter *ofilter, AVBPrint *bprint) #define DEF_CHOOSE_FORMAT(name, type, var, supported_list, none, printf_format, get_name) \ static void choose_ ## name (OutputFilter *ofilter, AVBPrint *bprint) \ { \ - if (ofilter->var == none && !ofilter->supported_list) \ + OutputFilterPriv *ofp = ofp_from_ofilter(ofilter); \ + if (ofp->var == none && !ofilter->supported_list) \ return; \ av_bprintf(bprint, #name "="); \ - if (ofilter->var != none) { \ - av_bprintf(bprint, printf_format, get_name(ofilter->var)); \ + if (ofp->var != none) { \ + av_bprintf(bprint, printf_format, get_name(ofp->var)); \ } else { \ const type *p; \ \ @@ -580,11 +594,14 @@ static char *describe_filter_link(FilterGraph *fg, AVFilterInOut *inout, int in) static OutputFilter *ofilter_alloc(FilterGraph *fg) { + OutputFilterPriv *ofp; OutputFilter *ofilter; - ofilter = ALLOC_ARRAY_ELEM(fg->outputs, fg->nb_outputs); + ofp = allocate_array_elem(&fg->outputs, sizeof(*ofp), + &fg->nb_outputs); + ofilter = &ofp->ofilter; ofilter->graph = fg; - ofilter->format = -1; + ofp->format = -1; ofilter->last_pts = AV_NOPTS_VALUE; return ofilter; @@ -653,6 +670,7 @@ static void set_channel_layout(OutputFilter *f, OutputStream *ost) void ofilter_bind_ost(OutputFilter *ofilter, OutputStream *ost) { + OutputFilterPriv *ofp = ofp_from_ofilter(ofilter); FilterGraph *fg = ofilter->graph; const AVCodec *c = ost->enc_ctx->codec; @@ -666,19 +684,19 @@ void ofilter_bind_ost(OutputFilter *ofilter, OutputStream *ost) ofilter->width = ost->enc_ctx->width; ofilter->height = ost->enc_ctx->height; if (ost->enc_ctx->pix_fmt != AV_PIX_FMT_NONE) { - ofilter->format = ost->enc_ctx->pix_fmt; + ofp->format = ost->enc_ctx->pix_fmt; } else { ofilter->formats = c->pix_fmts; } break; case AVMEDIA_TYPE_AUDIO: if (ost->enc_ctx->sample_fmt != AV_SAMPLE_FMT_NONE) { - ofilter->format = ost->enc_ctx->sample_fmt; + ofp->format = ost->enc_ctx->sample_fmt; } else { ofilter->formats = c->sample_fmts; } if (ost->enc_ctx->sample_rate) { - ofilter->sample_rate = ost->enc_ctx->sample_rate; + ofp->sample_rate = ost->enc_ctx->sample_rate; } else { ofilter->sample_rates = c->supported_samplerates; } @@ -1570,14 +1588,15 @@ static int configure_filtergraph(FilterGraph *fg) * make sure they stay the same if the filtergraph is reconfigured later */ for (i = 0; i < fg->nb_outputs; i++) { OutputFilter *ofilter = fg->outputs[i]; + OutputFilterPriv *ofp = ofp_from_ofilter(ofilter); AVFilterContext *sink = ofilter->filter; - ofilter->format = av_buffersink_get_format(sink); + ofp->format = av_buffersink_get_format(sink); ofilter->width = av_buffersink_get_w(sink); ofilter->height = av_buffersink_get_h(sink); - ofilter->sample_rate = av_buffersink_get_sample_rate(sink); + ofp->sample_rate = av_buffersink_get_sample_rate(sink); av_channel_layout_uninit(&ofilter->ch_layout); ret = av_buffersink_get_ch_layout(sink, &ofilter->ch_layout); if (ret < 0) From c19aa9c28f89e77ae89fbc09bafec57005ac3533 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Thu, 6 Jul 2023 17:09:59 +0200 Subject: [PATCH 1817/2172] fftools/ffmpeg_filter: make OutputFile.ch_layout private It is not used outside of the filtering code. --- fftools/ffmpeg.h | 1 - fftools/ffmpeg_filter.c | 17 ++++++++++------- 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/fftools/ffmpeg.h b/fftools/ffmpeg.h index 5b4117eeea0..b789233a088 100644 --- a/fftools/ffmpeg.h +++ b/fftools/ffmpeg.h @@ -296,7 +296,6 @@ typedef struct OutputFilter { /* desired output stream properties */ int width, height; - AVChannelLayout ch_layout; // those are only set if no format is specified and the encoder gives us multiple options // They point directly to the relevant lists of the encoder. diff --git a/fftools/ffmpeg_filter.c b/fftools/ffmpeg_filter.c index b1fda7b9e8e..0272b0a96b2 100644 --- a/fftools/ffmpeg_filter.c +++ b/fftools/ffmpeg_filter.c @@ -139,6 +139,7 @@ typedef struct OutputFilterPriv { /* desired output stream properties */ int format; int sample_rate; + AVChannelLayout ch_layout; } OutputFilterPriv; static OutputFilterPriv *ofp_from_ofilter(OutputFilter *ofilter) @@ -375,9 +376,10 @@ DEF_CHOOSE_FORMAT(sample_rates, int, sample_rate, sample_rates, 0, static void choose_channel_layouts(OutputFilter *ofilter, AVBPrint *bprint) { - if (av_channel_layout_check(&ofilter->ch_layout)) { + OutputFilterPriv *ofp = ofp_from_ofilter(ofilter); + if (av_channel_layout_check(&ofp->ch_layout)) { av_bprintf(bprint, "channel_layouts="); - av_channel_layout_describe_bprint(&ofilter->ch_layout, bprint); + av_channel_layout_describe_bprint(&ofp->ch_layout, bprint); } else if (ofilter->ch_layouts) { const AVChannelLayout *p; @@ -630,7 +632,7 @@ static int ifilter_bind_ist(InputFilter *ifilter, InputStream *ist) return 0; } -static void set_channel_layout(OutputFilter *f, OutputStream *ost) +static void set_channel_layout(OutputFilterPriv *f, OutputStream *ost) { const AVCodec *c = ost->enc_ctx->codec; int i, err; @@ -701,7 +703,7 @@ void ofilter_bind_ost(OutputFilter *ofilter, OutputStream *ost) ofilter->sample_rates = c->supported_samplerates; } if (ost->enc_ctx->ch_layout.nb_channels) { - set_channel_layout(ofilter, ost); + set_channel_layout(ofp, ost); } else if (c->ch_layouts) { ofilter->ch_layouts = c->ch_layouts; } @@ -782,10 +784,11 @@ void fg_free(FilterGraph **pfg) av_freep(&fg->inputs); for (int j = 0; j < fg->nb_outputs; j++) { OutputFilter *ofilter = fg->outputs[j]; + OutputFilterPriv *ofp = ofp_from_ofilter(ofilter); av_freep(&ofilter->linklabel); av_freep(&ofilter->name); - av_channel_layout_uninit(&ofilter->ch_layout); + av_channel_layout_uninit(&ofp->ch_layout); av_freep(&fg->outputs[j]); } av_freep(&fg->outputs); @@ -1597,8 +1600,8 @@ static int configure_filtergraph(FilterGraph *fg) ofilter->height = av_buffersink_get_h(sink); ofp->sample_rate = av_buffersink_get_sample_rate(sink); - av_channel_layout_uninit(&ofilter->ch_layout); - ret = av_buffersink_get_ch_layout(sink, &ofilter->ch_layout); + av_channel_layout_uninit(&ofp->ch_layout); + ret = av_buffersink_get_ch_layout(sink, &ofp->ch_layout); if (ret < 0) goto fail; } From a3ab5bf80d9edf15465d0c1fea349bb3cc76b013 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Thu, 6 Jul 2023 17:09:59 +0200 Subject: [PATCH 1818/2172] fftools/ffmpeg_filter: make OutputFile.width,height private They are not used outside of the filtering code. --- fftools/ffmpeg.h | 3 --- fftools/ffmpeg_filter.c | 14 ++++++++------ 2 files changed, 8 insertions(+), 9 deletions(-) diff --git a/fftools/ffmpeg.h b/fftools/ffmpeg.h index b789233a088..79f3f35b3ab 100644 --- a/fftools/ffmpeg.h +++ b/fftools/ffmpeg.h @@ -294,9 +294,6 @@ typedef struct OutputFilter { enum AVMediaType type; - /* desired output stream properties */ - int width, height; - // those are only set if no format is specified and the encoder gives us multiple options // They point directly to the relevant lists of the encoder. const int *formats; diff --git a/fftools/ffmpeg_filter.c b/fftools/ffmpeg_filter.c index 0272b0a96b2..0874187f3e6 100644 --- a/fftools/ffmpeg_filter.c +++ b/fftools/ffmpeg_filter.c @@ -138,6 +138,7 @@ typedef struct OutputFilterPriv { /* desired output stream properties */ int format; + int width, height; int sample_rate; AVChannelLayout ch_layout; } OutputFilterPriv; @@ -683,8 +684,8 @@ void ofilter_bind_ost(OutputFilter *ofilter, OutputStream *ost) switch (ost->enc_ctx->codec_type) { case AVMEDIA_TYPE_VIDEO: - ofilter->width = ost->enc_ctx->width; - ofilter->height = ost->enc_ctx->height; + ofp->width = ost->enc_ctx->width; + ofp->height = ost->enc_ctx->height; if (ost->enc_ctx->pix_fmt != AV_PIX_FMT_NONE) { ofp->format = ost->enc_ctx->pix_fmt; } else { @@ -1068,6 +1069,7 @@ static int insert_filter(AVFilterContext **last_filter, int *pad_idx, static int configure_output_video_filter(FilterGraph *fg, OutputFilter *ofilter, AVFilterInOut *out) { + OutputFilterPriv *ofp = ofp_from_ofilter(ofilter); OutputStream *ost = ofilter->ost; OutputFile *of = output_files[ost->file_index]; AVFilterContext *last_filter = out->filter_ctx; @@ -1085,13 +1087,13 @@ static int configure_output_video_filter(FilterGraph *fg, OutputFilter *ofilter, if (ret < 0) return ret; - if ((ofilter->width || ofilter->height) && ofilter->ost->autoscale) { + if ((ofp->width || ofp->height) && ofilter->ost->autoscale) { char args[255]; AVFilterContext *filter; const AVDictionaryEntry *e = NULL; snprintf(args, sizeof(args), "%d:%d", - ofilter->width, ofilter->height); + ofp->width, ofp->height); while ((e = av_dict_iterate(ost->sws_dict, e))) { av_strlcatf(args, sizeof(args), ":%s=%s", e->key, e->value); @@ -1596,8 +1598,8 @@ static int configure_filtergraph(FilterGraph *fg) ofp->format = av_buffersink_get_format(sink); - ofilter->width = av_buffersink_get_w(sink); - ofilter->height = av_buffersink_get_h(sink); + ofp->width = av_buffersink_get_w(sink); + ofp->height = av_buffersink_get_h(sink); ofp->sample_rate = av_buffersink_get_sample_rate(sink); av_channel_layout_uninit(&ofp->ch_layout); From 432399780aa1518f780174805f51bd9471c54bd7 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Thu, 6 Jul 2023 17:09:59 +0200 Subject: [PATCH 1819/2172] fftools/ffmpeg_filter: make OutputFile.{formats,ch_layouts,sample_rates} private They are not used outside of the filtering code. --- fftools/ffmpeg.h | 6 ------ fftools/ffmpeg_filter.c | 35 ++++++++++++++++++++--------------- 2 files changed, 20 insertions(+), 21 deletions(-) diff --git a/fftools/ffmpeg.h b/fftools/ffmpeg.h index 79f3f35b3ab..3201163a4ff 100644 --- a/fftools/ffmpeg.h +++ b/fftools/ffmpeg.h @@ -294,12 +294,6 @@ typedef struct OutputFilter { enum AVMediaType type; - // those are only set if no format is specified and the encoder gives us multiple options - // They point directly to the relevant lists of the encoder. - const int *formats; - const AVChannelLayout *ch_layouts; - const int *sample_rates; - /* pts of the last frame received from this filter, in AV_TIME_BASE_Q */ int64_t last_pts; } OutputFilter; diff --git a/fftools/ffmpeg_filter.c b/fftools/ffmpeg_filter.c index 0874187f3e6..f60d1cd23be 100644 --- a/fftools/ffmpeg_filter.c +++ b/fftools/ffmpeg_filter.c @@ -141,6 +141,12 @@ typedef struct OutputFilterPriv { int width, height; int sample_rate; AVChannelLayout ch_layout; + + // those are only set if no format is specified and the encoder gives us multiple options + // They point directly to the relevant lists of the encoder. + const int *formats; + const AVChannelLayout *ch_layouts; + const int *sample_rates; } OutputFilterPriv; static OutputFilterPriv *ofp_from_ofilter(OutputFilter *ofilter) @@ -346,10 +352,9 @@ static const char *choose_pix_fmts(OutputFilter *ofilter, AVBPrint *bprint) /* Define a function for appending a list of allowed formats * to an AVBPrint. If nonempty, the list will have a header. */ #define DEF_CHOOSE_FORMAT(name, type, var, supported_list, none, printf_format, get_name) \ -static void choose_ ## name (OutputFilter *ofilter, AVBPrint *bprint) \ +static void choose_ ## name (OutputFilterPriv *ofp, AVBPrint *bprint) \ { \ - OutputFilterPriv *ofp = ofp_from_ofilter(ofilter); \ - if (ofp->var == none && !ofilter->supported_list) \ + if (ofp->var == none && !ofp->supported_list) \ return; \ av_bprintf(bprint, #name "="); \ if (ofp->var != none) { \ @@ -357,7 +362,7 @@ static void choose_ ## name (OutputFilter *ofilter, AVBPrint *bprint) \ } else { \ const type *p; \ \ - for (p = ofilter->supported_list; *p != none; p++) { \ + for (p = ofp->supported_list; *p != none; p++) { \ av_bprintf(bprint, printf_format "|", get_name(*p)); \ } \ if (bprint->len > 0) \ @@ -375,17 +380,16 @@ DEF_CHOOSE_FORMAT(sample_fmts, enum AVSampleFormat, format, formats, DEF_CHOOSE_FORMAT(sample_rates, int, sample_rate, sample_rates, 0, "%d", ) -static void choose_channel_layouts(OutputFilter *ofilter, AVBPrint *bprint) +static void choose_channel_layouts(OutputFilterPriv *ofp, AVBPrint *bprint) { - OutputFilterPriv *ofp = ofp_from_ofilter(ofilter); if (av_channel_layout_check(&ofp->ch_layout)) { av_bprintf(bprint, "channel_layouts="); av_channel_layout_describe_bprint(&ofp->ch_layout, bprint); - } else if (ofilter->ch_layouts) { + } else if (ofp->ch_layouts) { const AVChannelLayout *p; av_bprintf(bprint, "channel_layouts="); - for (p = ofilter->ch_layouts; p->nb_channels; p++) { + for (p = ofp->ch_layouts; p->nb_channels; p++) { av_channel_layout_describe_bprint(p, bprint); av_bprintf(bprint, "|"); } @@ -689,24 +693,24 @@ void ofilter_bind_ost(OutputFilter *ofilter, OutputStream *ost) if (ost->enc_ctx->pix_fmt != AV_PIX_FMT_NONE) { ofp->format = ost->enc_ctx->pix_fmt; } else { - ofilter->formats = c->pix_fmts; + ofp->formats = c->pix_fmts; } break; case AVMEDIA_TYPE_AUDIO: if (ost->enc_ctx->sample_fmt != AV_SAMPLE_FMT_NONE) { ofp->format = ost->enc_ctx->sample_fmt; } else { - ofilter->formats = c->sample_fmts; + ofp->formats = c->sample_fmts; } if (ost->enc_ctx->sample_rate) { ofp->sample_rate = ost->enc_ctx->sample_rate; } else { - ofilter->sample_rates = c->supported_samplerates; + ofp->sample_rates = c->supported_samplerates; } if (ost->enc_ctx->ch_layout.nb_channels) { set_channel_layout(ofp, ost); } else if (c->ch_layouts) { - ofilter->ch_layouts = c->ch_layouts; + ofp->ch_layouts = c->ch_layouts; } break; } @@ -1144,6 +1148,7 @@ static int configure_output_video_filter(FilterGraph *fg, OutputFilter *ofilter, static int configure_output_audio_filter(FilterGraph *fg, OutputFilter *ofilter, AVFilterInOut *out) { + OutputFilterPriv *ofp = ofp_from_ofilter(ofilter); OutputStream *ost = ofilter->ost; OutputFile *of = output_files[ost->file_index]; AVFilterContext *last_filter = out->filter_ctx; @@ -1196,9 +1201,9 @@ static int configure_output_audio_filter(FilterGraph *fg, OutputFilter *ofilter, } #endif - choose_sample_fmts(ofilter, &args); - choose_sample_rates(ofilter, &args); - choose_channel_layouts(ofilter, &args); + choose_sample_fmts(ofp, &args); + choose_sample_rates(ofp, &args); + choose_channel_layouts(ofp, &args); if (!av_bprint_is_complete(&args)) { ret = AVERROR(ENOMEM); goto fail; From 57a42a714b5a6cc445fab876143b91e0b5103de7 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Thu, 6 Jul 2023 17:35:19 +0200 Subject: [PATCH 1820/2172] fftools/ffmpeg_filter: consolidate calling avfilter_graph_set_auto_convert() Do not call it from choose_pix_fmts(), as that function is not supposed to modify random filtergraph properties. --- fftools/ffmpeg_filter.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/fftools/ffmpeg_filter.c b/fftools/ffmpeg_filter.c index f60d1cd23be..caf85194c58 100644 --- a/fftools/ffmpeg_filter.c +++ b/fftools/ffmpeg_filter.c @@ -48,6 +48,7 @@ typedef struct FilterGraphPriv { // true when the filtergraph contains only meta filters // that do not modify the frame data int is_meta; + int disable_conversions; const char *graph_desc; @@ -321,8 +322,6 @@ static const char *choose_pix_fmts(OutputFilter *ofilter, AVBPrint *bprint) av_opt_set(ost->enc_ctx, "strict", strict_dict->value, 0); if (ost->keep_pix_fmt) { - avfilter_graph_set_auto_convert(ofilter->graph->graph, - AVFILTER_AUTO_CONVERT_NONE); if (ost->enc_ctx->pix_fmt == AV_PIX_FMT_NONE) return NULL; return av_get_pix_fmt_name(ost->enc_ctx->pix_fmt); @@ -679,6 +678,7 @@ void ofilter_bind_ost(OutputFilter *ofilter, OutputStream *ost) { OutputFilterPriv *ofp = ofp_from_ofilter(ofilter); FilterGraph *fg = ofilter->graph; + FilterGraphPriv *fgp = fgp_from_fg(fg); const AVCodec *c = ost->enc_ctx->codec; av_assert0(!ofilter->ost); @@ -695,6 +695,9 @@ void ofilter_bind_ost(OutputFilter *ofilter, OutputStream *ost) } else { ofp->formats = c->pix_fmts; } + + fgp->disable_conversions |= ost->keep_pix_fmt; + break; case AVMEDIA_TYPE_AUDIO: if (ost->enc_ctx->sample_fmt != AV_SAMPLE_FMT_NONE) { @@ -830,6 +833,7 @@ FilterGraph *fg_create(char *graph_desc) fg->class = &fg_class; fg->index = nb_filtergraphs - 1; fgp->graph_desc = graph_desc; + fgp->disable_conversions = !auto_conversion_filters; snprintf(fgp->log_name, sizeof(fgp->log_name), "fc#%d", fg->index); @@ -1587,7 +1591,7 @@ static int configure_filtergraph(FilterGraph *fg) configure_output_filter(fg, fg->outputs[i], cur); avfilter_inout_free(&outputs); - if (!auto_conversion_filters) + if (fgp->disable_conversions) avfilter_graph_set_auto_convert(fg->graph, AVFILTER_AUTO_CONVERT_NONE); if ((ret = avfilter_graph_config(fg->graph, NULL)) < 0) goto fail; From 6a9d3f46c7fc661b86192e922ab932495d27f953 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Thu, 6 Jul 2023 19:44:54 +0200 Subject: [PATCH 1821/2172] fftools/ffmpeg: drop an obsolete debug log The value it prints has not been cur_dts from lavf for a very long time, so it's misleading. --- fftools/ffmpeg.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/fftools/ffmpeg.c b/fftools/ffmpeg.c index 71d4067a6c6..96638242f3e 100644 --- a/fftools/ffmpeg.c +++ b/fftools/ffmpeg.c @@ -941,10 +941,6 @@ static int choose_output(OutputStream **post) } else { opts = ost->last_mux_dts == AV_NOPTS_VALUE ? INT64_MIN : ost->last_mux_dts; - if (ost->last_mux_dts == AV_NOPTS_VALUE) - av_log(ost, AV_LOG_DEBUG, - "cur_dts is invalid [init:%d i_done:%d finish:%d] (this is harmless if it occurs once at the start per stream)\n", - ost->initialized, ost->inputs_done, ost->finished); } if (!ost->initialized && !ost->inputs_done && !ost->finished) { From 886c1ffb5da83a239df292800d16d399bc5ab0a7 Mon Sep 17 00:00:00 2001 From: Jonas Lindner Date: Mon, 10 Jul 2023 00:06:33 +0200 Subject: [PATCH 1822/2172] libavcodec/ansi: fix ECMA-48 SGR parameter 49 As can be seen in man console_codes this parameter sets the default background color Signed-off-by: Jonas Lindner --- libavcodec/ansi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavcodec/ansi.c b/libavcodec/ansi.c index 49c3770c4c8..d8d32bafbdc 100644 --- a/libavcodec/ansi.c +++ b/libavcodec/ansi.c @@ -330,7 +330,7 @@ FF_ENABLE_DEPRECATION_WARNINGS s->bg = index < 16 ? ansi_to_cga[index] : index; i += 2; } else if (m == 49) { - s->fg = ansi_to_cga[DEFAULT_BG_COLOR]; + s->bg = ansi_to_cga[DEFAULT_BG_COLOR]; } else { avpriv_request_sample(avctx, "Unsupported rendition parameter"); } From 02aeacbb5e77f1c760031dc6426a46671c6d220a Mon Sep 17 00:00:00 2001 From: Nicolas George Date: Wed, 12 Jul 2023 14:57:39 +0200 Subject: [PATCH 1823/2172] lavd/opengl: select the GL context before drawing MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Since “2d924b3a63 fftools/ffmpeg: move each muxer to a separate thread”, opengl_write_packet() is called from a different thread than opengl_write_header() and would nothing for lack of a selected context. --- libavdevice/opengl_enc.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/libavdevice/opengl_enc.c b/libavdevice/opengl_enc.c index 88c413ee633..8d059343fbe 100644 --- a/libavdevice/opengl_enc.c +++ b/libavdevice/opengl_enc.c @@ -1200,6 +1200,10 @@ static int opengl_draw(AVFormatContext *h, void *input, int repaint, int is_pkt) const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(pix_fmt); int ret; + /* At this point, opengl->glcontext implies opengl->glcontext */ + if (opengl->glcontext) + SDL_GL_MakeCurrent(opengl->window, opengl->glcontext); + #if CONFIG_SDL2 if (!opengl->no_window && (ret = opengl_sdl_process_events(h)) < 0) goto fail; From e6954fd087d4b36cae6834e2c6b423db604f569b Mon Sep 17 00:00:00 2001 From: James Almer Date: Tue, 11 Jul 2023 23:04:10 -0300 Subject: [PATCH 1824/2172] avcodec/decode: don't reject flush packets when buffer_pkt is not empty Restores the behavior before commit a92dbeb9ae. Signed-off-by: James Almer --- libavcodec/decode.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/libavcodec/decode.c b/libavcodec/decode.c index a47abeca060..239ad70b411 100644 --- a/libavcodec/decode.c +++ b/libavcodec/decode.c @@ -666,10 +666,9 @@ int attribute_align_arg avcodec_send_packet(AVCodecContext *avctx, const AVPacke if (avpkt && !avpkt->size && avpkt->data) return AVERROR(EINVAL); - if (!AVPACKET_IS_EMPTY(avci->buffer_pkt)) - return AVERROR(EAGAIN); - if (avpkt && (avpkt->data || avpkt->side_data_elems)) { + if (!AVPACKET_IS_EMPTY(avci->buffer_pkt)) + return AVERROR(EAGAIN); ret = av_packet_ref(avci->buffer_pkt, avpkt); if (ret < 0) return ret; From cf7ed01938a4d8b2ccd28f1fadacd79103e54eed Mon Sep 17 00:00:00 2001 From: Nicolas George Date: Wed, 26 Apr 2023 14:28:02 +0200 Subject: [PATCH 1825/2172] lavc/intrax8: fix an assert --- libavcodec/intrax8.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavcodec/intrax8.c b/libavcodec/intrax8.c index e4c8b96c9c0..c5c67272825 100644 --- a/libavcodec/intrax8.c +++ b/libavcodec/intrax8.c @@ -109,7 +109,7 @@ static inline void x8_select_ac_table(IntraX8Context *const w, int mode) table_index = get_bits(w->gb, 3); // 2 modes use same tables w->j_ac_vlc_table[mode] = j_ac_vlc[w->quant < 13][mode >> 1][table_index].table; - av_assert2(w->j_ac_vlc[mode]); + av_assert2(j_ac_vlc[mode]); } static inline int x8_get_orient_vlc(IntraX8Context *w) From ca9ec4e7ed64e222b2045e66b1000c7f88ea696e Mon Sep 17 00:00:00 2001 From: Nicolas George Date: Wed, 26 Apr 2023 14:29:29 +0200 Subject: [PATCH 1826/2172] lavu/avassert: include config.h Fix setting the assert level. --- libavutil/avassert.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/libavutil/avassert.h b/libavutil/avassert.h index 51e462bbae7..1895fb75513 100644 --- a/libavutil/avassert.h +++ b/libavutil/avassert.h @@ -28,6 +28,9 @@ #define AVUTIL_AVASSERT_H #include +#ifdef HAVE_AV_CONFIG_H +# include "config.h" +#endif #include "log.h" #include "macros.h" From 422bfdc4aefc9117a9aa9611269ba666c91b497c Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Mon, 10 Jul 2023 22:52:04 +0200 Subject: [PATCH 1827/2172] avfilter/avf_showcwt: add bar display support --- libavfilter/avf_showcwt.c | 126 +++++++++++++++++++++++++++++++++----- 1 file changed, 111 insertions(+), 15 deletions(-) diff --git a/libavfilter/avf_showcwt.c b/libavfilter/avf_showcwt.c index 896e470dd10..61b04bf8408 100644 --- a/libavfilter/avf_showcwt.c +++ b/libavfilter/avf_showcwt.c @@ -96,6 +96,7 @@ typedef struct ShowCWTContext { AVFrame *ifft_in; AVFrame *ifft_out; AVFrame *ch_out; + AVFrame *bh_out; int nb_threads; int nb_channels; int nb_consumed_samples; @@ -118,6 +119,8 @@ typedef struct ShowCWTContext { float minimum_frequency; float maximum_frequency; float deviation; + float bar_ratio; + int bar_size; AVFloatDSPContext *fdsp; } ShowCWTContext; @@ -159,6 +162,7 @@ static const AVOption showcwt_options[] = { { "rl", "right to left", 0, AV_OPT_TYPE_CONST,{.i64=DIRECTION_RL}, 0, 0, FLAGS, "direction" }, { "ud", "up to down", 0, AV_OPT_TYPE_CONST,{.i64=DIRECTION_UD}, 0, 0, FLAGS, "direction" }, { "du", "down to up", 0, AV_OPT_TYPE_CONST,{.i64=DIRECTION_DU}, 0, 0, FLAGS, "direction" }, + { "bar", "set bar ratio", OFFSET(bar_ratio), AV_OPT_TYPE_FLOAT, {.dbl = 0.}, 0, 1, FLAGS }, { NULL } }; @@ -184,6 +188,7 @@ static av_cold void uninit(AVFilterContext *ctx) av_frame_free(&s->ifft_in); av_frame_free(&s->ifft_out); av_frame_free(&s->ch_out); + av_frame_free(&s->bh_out); if (s->fft) { for (int n = 0; n < s->nb_threads; n++) @@ -315,6 +320,80 @@ static int run_channel_cwt_prepare(AVFilterContext *ctx, void *arg, int jobnr, i return 0; } +#define DRAW_BAR_COLOR(x) \ +do { \ + if (Y <= ht) { \ + dstY[x] = 0; \ + dstU[x] = 128; \ + dstV[x] = 128; \ + } else { \ + float mul = (Y - ht) * bh[0]; \ + dstY[x] = av_clip_uint8(lrintf(Y * mul * 255.f)); \ + dstU[x] = av_clip_uint8(lrintf((U-0.5f) * 128.f + 128)); \ + dstV[x] = av_clip_uint8(lrintf((V-0.5f) * 128.f + 128)); \ + } \ +} while (0) + +static void draw_bar(ShowCWTContext *s, int y, + float Y, float U, float V) +{ + float *bh = ((float *)s->bh_out->extended_data[0]) + y; + const ptrdiff_t ylinesize = s->outpicref->linesize[0]; + const ptrdiff_t ulinesize = s->outpicref->linesize[1]; + const ptrdiff_t vlinesize = s->outpicref->linesize[2]; + const int direction = s->direction; + const int bar_size = s->bar_size; + const float rcp_bar_h = 1.f / bar_size; + uint8_t *dstY, *dstU, *dstV; + const int w_1 = s->w - 1; + + bh[0] = 1.f / (Y + 0.0001f); + switch (direction) { + case DIRECTION_LR: + dstY = s->outpicref->data[0] + y * ylinesize; + dstU = s->outpicref->data[1] + y * ulinesize; + dstV = s->outpicref->data[2] + y * vlinesize; + for (int x = 0; x < bar_size; x++) { + float ht = (bar_size - x) * rcp_bar_h; + DRAW_BAR_COLOR(x); + } + break; + case DIRECTION_RL: + dstY = s->outpicref->data[0] + y * ylinesize; + dstU = s->outpicref->data[1] + y * ulinesize; + dstV = s->outpicref->data[2] + y * vlinesize; + for (int x = 0; x < bar_size; x++) { + float ht = x * rcp_bar_h; + DRAW_BAR_COLOR(w_1 - bar_size + x); + } + break; + case DIRECTION_UD: + dstY = s->outpicref->data[0] + w_1 - y; + dstU = s->outpicref->data[1] + w_1 - y; + dstV = s->outpicref->data[2] + w_1 - y; + for (int x = 0; x < bar_size; x++) { + float ht = (bar_size - x) * rcp_bar_h; + DRAW_BAR_COLOR(0); + dstY += ylinesize; + dstU += ulinesize; + dstV += vlinesize; + } + break; + case DIRECTION_DU: + dstY = s->outpicref->data[0] + w_1 - y + ylinesize * (s->h - 1 - bar_size); + dstU = s->outpicref->data[1] + w_1 - y + ulinesize * (s->h - 1 - bar_size); + dstV = s->outpicref->data[2] + w_1 - y + vlinesize * (s->h - 1 - bar_size); + for (int x = 0; x < bar_size; x++) { + float ht = x * rcp_bar_h; + DRAW_BAR_COLOR(0); + dstY += ylinesize; + dstU += ulinesize; + dstV += vlinesize; + } + break; + } +} + static int draw(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) { ShowCWTContext *s = ctx->priv; @@ -330,6 +409,7 @@ static int draw(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) const int ihop_size = s->ihop_size; const int direction = s->direction; uint8_t *dstY, *dstU, *dstV, *dstA; + const int bar_size = s->bar_size; const int mode = s->mode; const int w_1 = s->w - 1; const int x = s->pos; @@ -414,6 +494,9 @@ static int draw(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) dstV[0] = av_clip_uint8(lrintf(V * 255.f)); if (dstA) dstA[0] = dstY[0]; + + if (bar_size > 0) + draw_bar(s, y, Y, U, V); } break; case 3: @@ -441,6 +524,9 @@ static int draw(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) dstV[0] = av_clip_uint8(lrintf(V * 255.f)); if (dstA) dstA[0] = dstY[0]; + + if (bar_size > 0) + draw_bar(s, y, Y, U, V); } break; case 2: @@ -455,6 +541,8 @@ static int draw(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) dstV[0] = av_clip_uint8(lrintf(V * 255.f)); if (dstA) dstA[0] = dstY[0]; + if (bar_size > 0) + draw_bar(s, y, Y, U, V); break; case 1: Y = atan2f(src[0].im, src[0].re); @@ -463,6 +551,8 @@ static int draw(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) dstY[0] = av_clip_uint8(lrintf(Y * 255.f)); if (dstA) dstA[0] = dstY[0]; + if (bar_size > 0) + draw_bar(s, y, Y, 0.5f, 0.5f); break; case 0: Y = hypotf(src[0].re, src[0].im); @@ -471,6 +561,9 @@ static int draw(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) dstY[0] = av_clip_uint8(lrintf(Y * 255.f)); if (dstA) dstA[0] = dstY[0]; + + if (bar_size > 0) + draw_bar(s, y, Y, 0.5f, 0.5f); break; } } @@ -589,10 +682,12 @@ static int config_output(AVFilterLink *outlink) switch (s->direction) { case DIRECTION_LR: case DIRECTION_RL: + s->bar_size = s->w * s->bar_ratio; s->frequency_band_count = s->h; break; case DIRECTION_UD: case DIRECTION_DU: + s->bar_size = s->h * s->bar_ratio; s->frequency_band_count = s->w; break; } @@ -651,6 +746,7 @@ static int config_output(AVFilterLink *outlink) s->kernel_x = av_frame_alloc(); s->cache = ff_get_audio_buffer(inlink, s->fft_in_size * 2); s->ch_out = ff_get_audio_buffer(inlink, s->frequency_band_count * 2 * s->ihop_size); + s->bh_out = ff_get_audio_buffer(inlink, s->frequency_band_count); s->ifft_in = av_frame_alloc(); s->ifft_out = av_frame_alloc(); s->kernel = av_frame_alloc(); @@ -658,8 +754,8 @@ static int config_output(AVFilterLink *outlink) s->kernel_start = av_calloc(s->frequency_band_count, sizeof(*s->kernel_start)); s->kernel_stop = av_calloc(s->frequency_band_count, sizeof(*s->kernel_stop)); if (!s->outpicref || !s->fft_in || !s->fft_out || !s->src_x || !s->dst_x || !s->kernel_x || - !s->ifft_in || !s->ifft_out || !s->kernel_start || !s->kernel_stop || - !s->frequency_band || !s->kernel || !s->cache || !s->index) + !s->ifft_in || !s->ifft_out || !s->kernel_start || !s->kernel_stop || !s->ch_out || + !s->frequency_band || !s->kernel || !s->cache || !s->index || !s->bh_out) return AVERROR(ENOMEM); s->ifft_in->format = inlink->format; @@ -760,16 +856,16 @@ static int config_output(AVFilterLink *outlink) switch (s->direction) { case DIRECTION_LR: - s->pos = 0; + s->pos = s->bar_size; break; case DIRECTION_RL: - s->pos = s->w - 1; + s->pos = FFMAX(0, s->w - 2 - s->bar_size); break; case DIRECTION_UD: - s->pos = 0; + s->pos = s->bar_size; break; case DIRECTION_DU: - s->pos = s->h - 1; + s->pos = FFMAX(0, s->h - 2 - s->bar_size); break; } @@ -802,7 +898,7 @@ static int output_frame(AVFilterContext *ctx) for (int p = 0; p < nb_planes; p++) { ptrdiff_t linesize = s->outpicref->linesize[p]; - for (int y = s->h - 1; y > 0; y--) { + for (int y = s->h - 1; y > s->bar_size; y--) { uint8_t *dst = s->outpicref->data[p] + y * linesize; memmove(dst, dst - linesize, s->w); @@ -813,7 +909,7 @@ static int output_frame(AVFilterContext *ctx) for (int p = 0; p < nb_planes; p++) { ptrdiff_t linesize = s->outpicref->linesize[p]; - for (int y = 0; y < s->h - 1; y++) { + for (int y = 0; y < s->h - 2 - s->bar_size; y++) { uint8_t *dst = s->outpicref->data[p] + y * linesize; memmove(dst, dst + linesize, s->w); @@ -833,28 +929,28 @@ static int output_frame(AVFilterContext *ctx) case DIRECTION_LR: s->pos++; if (s->pos >= s->w) { - s->pos = 0; + s->pos = s->bar_size; s->new_frame = 1; } break; case DIRECTION_RL: s->pos--; if (s->pos < 0) { - s->pos = s->w - 1; + s->pos = FFMAX(0, s->w - 2 - s->bar_size); s->new_frame = 1; } break; case DIRECTION_UD: s->pos++; if (s->pos >= s->h) { - s->pos = 0; + s->pos = s->bar_size; s->new_frame = 1; } break; case DIRECTION_DU: s->pos--; if (s->pos < 0) { - s->pos = s->h - 1; + s->pos = FFMAX(0, s->h - 2 - s->bar_size); s->new_frame = 1; } break; @@ -864,13 +960,13 @@ static int output_frame(AVFilterContext *ctx) switch (s->direction) { case DIRECTION_UD: case DIRECTION_LR: - s->pos = 0; + s->pos = s->bar_size; break; case DIRECTION_RL: - s->pos = s->w - 1; + s->pos = FFMAX(0, s->w - 2 - s->bar_size); break; case DIRECTION_DU: - s->pos = s->h - 1; + s->pos = FFMAX(0, s->h - 2 - s->bar_size); break; } break; From 7430ee2b8b1ed8fd675787eb8c4abd44ed89601c Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Wed, 12 Jul 2023 22:49:56 +0200 Subject: [PATCH 1828/2172] avfilter/avf_showcwt: add rotation option --- doc/filters.texi | 7 +++++++ libavfilter/avf_showcwt.c | 17 +++++++++++++---- 2 files changed, 20 insertions(+), 4 deletions(-) diff --git a/doc/filters.texi b/doc/filters.texi index a8e0dbde15f..770c5d0272d 100644 --- a/doc/filters.texi +++ b/doc/filters.texi @@ -30784,6 +30784,13 @@ Direction from up to down. @item du Direction from down to up. @end table + +@item bar +Set the ratio of bargraph display to display size. Default is 0. + +@item rotation +Set color rotation, must be in [-1.0, 1.0] range. +Default value is @code{0}. @end table @section showfreqs diff --git a/libavfilter/avf_showcwt.c b/libavfilter/avf_showcwt.c index 61b04bf8408..578312cdd6a 100644 --- a/libavfilter/avf_showcwt.c +++ b/libavfilter/avf_showcwt.c @@ -121,6 +121,7 @@ typedef struct ShowCWTContext { float deviation; float bar_ratio; int bar_size; + float rotation; AVFloatDSPContext *fdsp; } ShowCWTContext; @@ -163,6 +164,7 @@ static const AVOption showcwt_options[] = { { "ud", "up to down", 0, AV_OPT_TYPE_CONST,{.i64=DIRECTION_UD}, 0, 0, FLAGS, "direction" }, { "du", "down to up", 0, AV_OPT_TYPE_CONST,{.i64=DIRECTION_DU}, 0, 0, FLAGS, "direction" }, { "bar", "set bar ratio", OFFSET(bar_ratio), AV_OPT_TYPE_FLOAT, {.dbl = 0.}, 0, 1, FLAGS }, + { "rotation", "set color rotation", OFFSET(rotation), AV_OPT_TYPE_FLOAT, {.dbl = 0}, -1, 1, FLAGS }, { NULL } }; @@ -407,6 +409,7 @@ static int draw(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) const int end = (count * (jobnr+1)) / nb_jobs; const int ihop_index = s->ihop_index; const int ihop_size = s->ihop_size; + const float rotation = s->rotation; const int direction = s->direction; uint8_t *dstY, *dstU, *dstV, *dstA; const int bar_size = s->bar_size; @@ -486,8 +489,14 @@ static int draw(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) v = remap_log(v, log_factor); Y = z; - U = 0.5f + z * sinf((v - u) * M_PI_2); - V = 0.5f + z * sinf((u - v) * M_PI_2); + U = sinf((v - u) * M_PI_2); + V = sinf((u - v) * M_PI_2); + + u = U * cosf(rotation * M_PI) - V * sinf(rotation * M_PI); + v = U * sinf(rotation * M_PI) + V * cosf(rotation * M_PI); + + U = 0.5f + 0.5f * z * u; + V = 0.5f + 0.5f * z * v; dstY[0] = av_clip_uint8(lrintf(Y * 255.f)); dstU[0] = av_clip_uint8(lrintf(U * 255.f)); @@ -515,8 +524,8 @@ static int draw(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) z = remap_log(z, log_factor); Y += z * yf; - U += z * yf * sinf(2.f * M_PI * ch * yf); - V += z * yf * cosf(2.f * M_PI * ch * yf); + U += z * yf * sinf(2.f * M_PI * (ch * yf + rotation)); + V += z * yf * cosf(2.f * M_PI * (ch * yf + rotation)); } dstY[0] = av_clip_uint8(lrintf(Y * 255.f)); From 9a2335444b83b9bfa6553c43c9cbdd352f0f11ef Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Mon, 10 Jul 2023 10:48:38 +0200 Subject: [PATCH 1829/2172] fftools/ffmpeg_mux: forward EOF from the sync queue EOF from sq_receive() means no packets will ever be output by the sync queue. Since the muxing sync queue is always used by all interleaved (i.e. non-attachment) streams, this means no further packets can make it to the muxer and we can terminate muxing now. --- fftools/ffmpeg_mux.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/fftools/ffmpeg_mux.c b/fftools/ffmpeg_mux.c index 026796f7e61..ca32967cd8c 100644 --- a/fftools/ffmpeg_mux.c +++ b/fftools/ffmpeg_mux.c @@ -166,8 +166,14 @@ static int sync_queue_process(Muxer *mux, OutputStream *ost, AVPacket *pkt, int while (1) { ret = sq_receive(mux->sq_mux, -1, SQPKT(mux->sq_pkt)); - if (ret < 0) - return (ret == AVERROR_EOF || ret == AVERROR(EAGAIN)) ? 0 : ret; + if (ret < 0) { + /* n.b.: We forward EOF from the sync queue, terminating muxing. + * This assumes that if a muxing sync queue is present, then all + * the streams use it. That is true currently, but may change in + * the future, then this code needs to be revisited. + */ + return ret == AVERROR(EAGAIN) ? 0 : ret; + } ret = write_packet(mux, of->streams[ret], mux->sq_pkt); From a7b3c0203fc059db13595e0d0935e50979d2f41c Mon Sep 17 00:00:00 2001 From: Khem Raj Date: Sun, 2 Jul 2023 19:44:12 -0700 Subject: [PATCH 1830/2172] libswscale/riscv: fix syntax of vsetvli MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add missing operand which clang complains about but GCC assumes it to be 'm1' if not specified. Works around build failure with Clang: | src/libswscale/riscv/rgb2rgb_rvv.S:88:25: error: operand must be e[8|16|32|64|128|256|512|1024],m[1|2|4|8|f2|f4|f8],[ta|tu],[ma|mu] | vsetvli t4, t3, e8, ta, ma | ^ Signed-off-by: Rémi Denis-Courmont --- libswscale/riscv/rgb2rgb_rvv.S | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libswscale/riscv/rgb2rgb_rvv.S b/libswscale/riscv/rgb2rgb_rvv.S index 5626d906eb9..bbdfdbebbc8 100644 --- a/libswscale/riscv/rgb2rgb_rvv.S +++ b/libswscale/riscv/rgb2rgb_rvv.S @@ -85,7 +85,7 @@ func ff_interleave_bytes_rvv, zve32x mv t3, a3 addi a4, a4, -1 2: - vsetvli t4, t3, e8, ta, ma + vsetvli t4, t3, e8, m1, ta, ma sub t3, t3, t4 vle8.v v8, (t0) add t0, t4, t0 From 7bcc1b4eb8534fce66e53d0fc2d66a899bbad8a2 Mon Sep 17 00:00:00 2001 From: Vignesh Venkatasubramanian Date: Mon, 26 Jun 2023 10:47:09 -0700 Subject: [PATCH 1831/2172] libsvtav1: Add workaround for gop_size == 1 In some versions of libsvtav1, setting intra_period_length to 0 does not produce the intended result (i.e.) all frames produced are not keyframes. Instead handle the gop_size == 1 as a special case by setting the pic_type to EB_AV1_KEY_PICTURE when encoding each frame so that all the output frames are keyframes. SVT-AV1 Bug: https://gitlab.com/AOMediaCodec/SVT-AV1/-/issues/2076 Example command: ffmpeg -f lavfi -i testsrc=duration=1:size=64x64:rate=30 -c:v libsvtav1 -g 1 -y test.webm Before: Only first frame is keyframe, rest are intraonly. After: All frames are keyframes. Signed-off-by: Vignesh Venkatasubramanian Signed-off-by: Ronald S. Bultje --- libavcodec/libsvtav1.c | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/libavcodec/libsvtav1.c b/libavcodec/libsvtav1.c index 718a04d221a..f2b73361d8f 100644 --- a/libavcodec/libsvtav1.c +++ b/libavcodec/libsvtav1.c @@ -242,9 +242,20 @@ static int config_enc_params(EbSvtAv1EncConfiguration *param, if (avctx->level != FF_LEVEL_UNKNOWN) param->level = avctx->level; - if (avctx->gop_size > 0) + // gop_size == 1 case is handled when encoding each frame by setting + // pic_type to EB_AV1_KEY_PICTURE. For gop_size > 1, set the + // intra_period_length. Even though setting intra_period_length to 0 should + // work in this case, it does not. + // See: https://gitlab.com/AOMediaCodec/SVT-AV1/-/issues/2076 + if (avctx->gop_size > 1) param->intra_period_length = avctx->gop_size - 1; + // In order for SVT-AV1 to force keyframes by setting pic_type to + // EB_AV1_KEY_PICTURE on any frame, force_key_frames has to be set. Note + // that this does not force all frames to be keyframes (it only forces a + // keyframe with pic_type is set to EB_AV1_KEY_PICTURE). + param->force_key_frames = 1; + if (avctx->framerate.num > 0 && avctx->framerate.den > 0) { param->frame_rate_numerator = avctx->framerate.num; param->frame_rate_denominator = avctx->framerate.den; @@ -462,6 +473,9 @@ static int eb_send_frame(AVCodecContext *avctx, const AVFrame *frame) break; } + if (avctx->gop_size == 1) + headerPtr->pic_type = EB_AV1_KEY_PICTURE; + svt_av1_enc_send_picture(svt_enc->svt_handle, headerPtr); return 0; From 374184a4dc16421ec6b182191898582d9275808a Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Fri, 14 Jul 2023 00:42:02 +0200 Subject: [PATCH 1832/2172] avfilter/split: fix EOF passing to inlink --- libavfilter/split.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/libavfilter/split.c b/libavfilter/split.c index 98b51f976ec..2a511668e2e 100644 --- a/libavfilter/split.c +++ b/libavfilter/split.c @@ -67,11 +67,15 @@ static int activate(AVFilterContext *ctx) { AVFilterLink *inlink = ctx->inputs[0]; AVFrame *in; - int status, ret; + int status, ret, nb_eofs = 0; int64_t pts; - for (int i = 0; i < ctx->nb_outputs; i++) { - FF_FILTER_FORWARD_STATUS_BACK_ALL(ctx->outputs[i], ctx); + for (int i = 0; i < ctx->nb_outputs; i++) + nb_eofs += ff_outlink_get_status(ctx->outputs[i]) == AVERROR_EOF; + + if (nb_eofs == ctx->nb_outputs) { + ff_inlink_set_status(inlink, AVERROR_EOF); + return 0; } ret = ff_inlink_consume_frame(inlink, &in); From 357a8632999e3a944392d557927bb5e568acbc7d Mon Sep 17 00:00:00 2001 From: David Lemler Date: Fri, 7 Jul 2023 16:31:03 -0500 Subject: [PATCH 1833/2172] lavc/libvpxenc: prevent fifo from filling up Prevent the fifo used in encoding VPx videos from filling up and stopping encode when it reaches 21845 items, which happens when the video has more than that number of frames. Incorporated suggestion from James Zern to prevent calling frame_data_submit() at all when performing the first pass of a 2-pass encode so the fifo is not filled at all; replaces original patch which drained the fifo after filling to prevent it from becoming full. Fixes the regression originally introduced in 5bda4ec6c3cb6f286bb40dee4457c3c26e0f78cb Co-authored-by: James Zern Signed-off-by: David Lemler Signed-off-by: James Zern --- libavcodec/libvpxenc.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/libavcodec/libvpxenc.c b/libavcodec/libvpxenc.c index 8833df2d68c..549ac55aaae 100644 --- a/libavcodec/libvpxenc.c +++ b/libavcodec/libvpxenc.c @@ -1780,9 +1780,11 @@ static int vpx_encode(AVCodecContext *avctx, AVPacket *pkt, } } - res = frame_data_submit(avctx, ctx->fifo, frame); - if (res < 0) - return res; + if (!(avctx->flags & AV_CODEC_FLAG_PASS1)) { + res = frame_data_submit(avctx, ctx->fifo, frame); + if (res < 0) + return res; + } } // this is for encoding with preset temporal layering patterns defined in From 78c52a8ca4e5733a601ac6c37c72e7557b6b0c9a Mon Sep 17 00:00:00 2001 From: James Almer Date: Sat, 8 Jul 2023 14:48:42 -0300 Subject: [PATCH 1834/2172] avcodec/decode: move processing discard samples to its own function Signed-off-by: James Almer --- libavcodec/decode.c | 269 +++++++++++++++++++++++--------------------- 1 file changed, 141 insertions(+), 128 deletions(-) diff --git a/libavcodec/decode.c b/libavcodec/decode.c index 239ad70b411..4478c8c4fe2 100644 --- a/libavcodec/decode.c +++ b/libavcodec/decode.c @@ -289,6 +289,123 @@ static int64_t guess_correct_pts(AVCodecContext *ctx, return pts; } +static int discard_samples(AVCodecContext *avctx, AVFrame *frame, int64_t *discarded_samples) +{ + AVCodecInternal *avci = avctx->internal; + int ret = 0; + uint8_t *side; + size_t side_size; + uint32_t discard_padding = 0; + uint8_t skip_reason = 0; + uint8_t discard_reason = 0; + + side = av_packet_get_side_data(avci->last_pkt_props, AV_PKT_DATA_SKIP_SAMPLES, &side_size); + if (side && side_size >= 10) { + avci->skip_samples = AV_RL32(side); + avci->skip_samples = FFMAX(0, avci->skip_samples); + discard_padding = AV_RL32(side + 4); + av_log(avctx, AV_LOG_DEBUG, "skip %d / discard %d samples due to side data\n", + avci->skip_samples, (int)discard_padding); + skip_reason = AV_RL8(side + 8); + discard_reason = AV_RL8(side + 9); + } + + if (!frame->buf[0]) + return AVERROR(EAGAIN); + + if (frame->format == AV_SAMPLE_FMT_NONE) + frame->format = avctx->sample_fmt; + if (!frame->ch_layout.nb_channels) { + int ret2 = av_channel_layout_copy(&frame->ch_layout, &avctx->ch_layout); + if (ret2 < 0) { + ret = ret2; + } + } +#if FF_API_OLD_CHANNEL_LAYOUT +FF_DISABLE_DEPRECATION_WARNINGS + if (!frame->channel_layout) + frame->channel_layout = avctx->ch_layout.order == AV_CHANNEL_ORDER_NATIVE ? + avctx->ch_layout.u.mask : 0; + if (!frame->channels) + frame->channels = avctx->ch_layout.nb_channels; +FF_ENABLE_DEPRECATION_WARNINGS +#endif + if (!frame->sample_rate) + frame->sample_rate = avctx->sample_rate; + + if ((frame->flags & AV_FRAME_FLAG_DISCARD) && + !(avctx->flags2 & AV_CODEC_FLAG2_SKIP_MANUAL)) { + avci->skip_samples = FFMAX(0, avci->skip_samples - frame->nb_samples); + *discarded_samples += frame->nb_samples; + return AVERROR(EAGAIN); + } + + if (avci->skip_samples > 0 && + !(avctx->flags2 & AV_CODEC_FLAG2_SKIP_MANUAL)) { + if (frame->nb_samples <= avci->skip_samples){ + *discarded_samples += frame->nb_samples; + avci->skip_samples -= frame->nb_samples; + av_log(avctx, AV_LOG_DEBUG, "skip whole frame, skip left: %d\n", + avci->skip_samples); + return AVERROR(EAGAIN); + } else { + av_samples_copy(frame->extended_data, frame->extended_data, 0, avci->skip_samples, + frame->nb_samples - avci->skip_samples, avctx->ch_layout.nb_channels, frame->format); + if (avctx->pkt_timebase.num && avctx->sample_rate) { + int64_t diff_ts = av_rescale_q(avci->skip_samples, + (AVRational){1, avctx->sample_rate}, + avctx->pkt_timebase); + if (frame->pts != AV_NOPTS_VALUE) + frame->pts += diff_ts; + if (frame->pkt_dts != AV_NOPTS_VALUE) + frame->pkt_dts += diff_ts; + if (frame->duration >= diff_ts) + frame->duration -= diff_ts; + } else + av_log(avctx, AV_LOG_WARNING, "Could not update timestamps for skipped samples.\n"); + + av_log(avctx, AV_LOG_DEBUG, "skip %d/%d samples\n", + avci->skip_samples, frame->nb_samples); + *discarded_samples += avci->skip_samples; + frame->nb_samples -= avci->skip_samples; + avci->skip_samples = 0; + } + } + + if (discard_padding > 0 && discard_padding <= frame->nb_samples && + !(avctx->flags2 & AV_CODEC_FLAG2_SKIP_MANUAL)) { + if (discard_padding == frame->nb_samples) { + *discarded_samples += frame->nb_samples; + return AVERROR(EAGAIN); + } else { + if (avctx->pkt_timebase.num && avctx->sample_rate) { + int64_t diff_ts = av_rescale_q(frame->nb_samples - discard_padding, + (AVRational){1, avctx->sample_rate}, + avctx->pkt_timebase); + frame->duration = diff_ts; + } else + av_log(avctx, AV_LOG_WARNING, "Could not update timestamps for discarded samples.\n"); + + av_log(avctx, AV_LOG_DEBUG, "discard %d/%d samples\n", + (int)discard_padding, frame->nb_samples); + frame->nb_samples -= discard_padding; + } + } + + if ((avctx->flags2 & AV_CODEC_FLAG2_SKIP_MANUAL)) { + AVFrameSideData *fside = av_frame_new_side_data(frame, AV_FRAME_DATA_SKIP_SAMPLES, 10); + if (fside) { + AV_WL32(fside->data, avci->skip_samples); + AV_WL32(fside->data + 4, discard_padding); + AV_WL8(fside->data + 8, skip_reason); + AV_WL8(fside->data + 9, discard_reason); + avci->skip_samples = 0; + } + } + + return ret; +} + /* * The core of the receive_frame_wrapper for the decoders implementing * the simple API. Certain decoders might consume partial packets without @@ -300,7 +417,7 @@ static inline int decode_simple_internal(AVCodecContext *avctx, AVFrame *frame, AVCodecInternal *avci = avctx->internal; AVPacket *const pkt = avci->in_pkt; const FFCodec *const codec = ffcodec(avctx->codec); - int got_frame, actual_got_frame; + int got_frame, consumed; int ret; if (!pkt->data && !avci->draining) { @@ -323,9 +440,9 @@ static inline int decode_simple_internal(AVCodecContext *avctx, AVFrame *frame, got_frame = 0; if (HAVE_THREADS && avctx->active_thread_type & FF_THREAD_FRAME) { - ret = ff_thread_decode_frame(avctx, frame, &got_frame, pkt); + consumed = ff_thread_decode_frame(avctx, frame, &got_frame, pkt); } else { - ret = codec->cb.decode(avctx, frame, &got_frame, pkt); + consumed = codec->cb.decode(avctx, frame, &got_frame, pkt); if (!(codec->caps_internal & FF_CODEC_CAP_SETS_PKT_DTS)) frame->pkt_dts = pkt->dts; @@ -347,132 +464,33 @@ FF_ENABLE_DEPRECATION_WARNINGS } } emms_c(); - actual_got_frame = got_frame; + + if (!got_frame) + av_frame_unref(frame); if (avctx->codec->type == AVMEDIA_TYPE_VIDEO) { - if (frame->flags & AV_FRAME_FLAG_DISCARD) - got_frame = 0; + ret = (!got_frame || frame->flags & AV_FRAME_FLAG_DISCARD) + ? AVERROR(EAGAIN) + : 0; } else if (avctx->codec->type == AVMEDIA_TYPE_AUDIO) { - uint8_t *side; - size_t side_size; - uint32_t discard_padding = 0; - uint8_t skip_reason = 0; - uint8_t discard_reason = 0; - - if (ret >= 0 && got_frame) { - if (frame->format == AV_SAMPLE_FMT_NONE) - frame->format = avctx->sample_fmt; - if (!frame->ch_layout.nb_channels) { - int ret2 = av_channel_layout_copy(&frame->ch_layout, &avctx->ch_layout); - if (ret2 < 0) { - ret = ret2; - got_frame = 0; - } - } -#if FF_API_OLD_CHANNEL_LAYOUT -FF_DISABLE_DEPRECATION_WARNINGS - if (!frame->channel_layout) - frame->channel_layout = avctx->ch_layout.order == AV_CHANNEL_ORDER_NATIVE ? - avctx->ch_layout.u.mask : 0; - if (!frame->channels) - frame->channels = avctx->ch_layout.nb_channels; -FF_ENABLE_DEPRECATION_WARNINGS -#endif - if (!frame->sample_rate) - frame->sample_rate = avctx->sample_rate; - } - - side= av_packet_get_side_data(avci->last_pkt_props, AV_PKT_DATA_SKIP_SAMPLES, &side_size); - if(side && side_size>=10) { - avci->skip_samples = AV_RL32(side); - avci->skip_samples = FFMAX(0, avci->skip_samples); - discard_padding = AV_RL32(side + 4); - av_log(avctx, AV_LOG_DEBUG, "skip %d / discard %d samples due to side data\n", - avci->skip_samples, (int)discard_padding); - skip_reason = AV_RL8(side + 8); - discard_reason = AV_RL8(side + 9); - } - - if ((frame->flags & AV_FRAME_FLAG_DISCARD) && got_frame && - !(avctx->flags2 & AV_CODEC_FLAG2_SKIP_MANUAL)) { - avci->skip_samples = FFMAX(0, avci->skip_samples - frame->nb_samples); - got_frame = 0; - *discarded_samples += frame->nb_samples; - } - - if (avci->skip_samples > 0 && got_frame && - !(avctx->flags2 & AV_CODEC_FLAG2_SKIP_MANUAL)) { - if(frame->nb_samples <= avci->skip_samples){ - got_frame = 0; - *discarded_samples += frame->nb_samples; - avci->skip_samples -= frame->nb_samples; - av_log(avctx, AV_LOG_DEBUG, "skip whole frame, skip left: %d\n", - avci->skip_samples); - } else { - av_samples_copy(frame->extended_data, frame->extended_data, 0, avci->skip_samples, - frame->nb_samples - avci->skip_samples, avctx->ch_layout.nb_channels, frame->format); - if(avctx->pkt_timebase.num && avctx->sample_rate) { - int64_t diff_ts = av_rescale_q(avci->skip_samples, - (AVRational){1, avctx->sample_rate}, - avctx->pkt_timebase); - if(frame->pts!=AV_NOPTS_VALUE) - frame->pts += diff_ts; - if(frame->pkt_dts!=AV_NOPTS_VALUE) - frame->pkt_dts += diff_ts; - if (frame->duration >= diff_ts) - frame->duration -= diff_ts; - } else { - av_log(avctx, AV_LOG_WARNING, "Could not update timestamps for skipped samples.\n"); - } - av_log(avctx, AV_LOG_DEBUG, "skip %d/%d samples\n", - avci->skip_samples, frame->nb_samples); - *discarded_samples += avci->skip_samples; - frame->nb_samples -= avci->skip_samples; - avci->skip_samples = 0; - } - } - - if (discard_padding > 0 && discard_padding <= frame->nb_samples && got_frame && - !(avctx->flags2 & AV_CODEC_FLAG2_SKIP_MANUAL)) { - if (discard_padding == frame->nb_samples) { - *discarded_samples += frame->nb_samples; - got_frame = 0; - } else { - if(avctx->pkt_timebase.num && avctx->sample_rate) { - int64_t diff_ts = av_rescale_q(frame->nb_samples - discard_padding, - (AVRational){1, avctx->sample_rate}, - avctx->pkt_timebase); - frame->duration = diff_ts; - } else { - av_log(avctx, AV_LOG_WARNING, "Could not update timestamps for discarded samples.\n"); - } - av_log(avctx, AV_LOG_DEBUG, "discard %d/%d samples\n", - (int)discard_padding, frame->nb_samples); - frame->nb_samples -= discard_padding; - } - } - - if ((avctx->flags2 & AV_CODEC_FLAG2_SKIP_MANUAL) && got_frame) { - AVFrameSideData *fside = av_frame_new_side_data(frame, AV_FRAME_DATA_SKIP_SAMPLES, 10); - if (fside) { - AV_WL32(fside->data, avci->skip_samples); - AV_WL32(fside->data + 4, discard_padding); - AV_WL8(fside->data + 8, skip_reason); - AV_WL8(fside->data + 9, discard_reason); - avci->skip_samples = 0; - } - } + ret = discard_samples(avctx, frame, discarded_samples); } - if (!got_frame) + if (ret == AVERROR(EAGAIN)) av_frame_unref(frame); - if (ret >= 0 && avctx->codec->type == AVMEDIA_TYPE_VIDEO) - ret = pkt->size; + if (consumed < 0) + ret = consumed; + if (consumed >= 0 && avctx->codec->type == AVMEDIA_TYPE_VIDEO) + consumed = pkt->size; + + if (!ret) + av_assert0(frame->buf[0]); + if (ret == AVERROR(EAGAIN)) + ret = 0; - /* do not stop draining when actual_got_frame != 0 or ret < 0 */ - /* got_frame == 0 but actual_got_frame != 0 when frame is discarded */ - if (avci->draining && !actual_got_frame) { + /* do not stop draining when got_frame != 0 or ret < 0 */ + if (avci->draining && !got_frame) { if (ret < 0) { /* prevent infinite loop if a decoder wrongly always return error on draining */ /* reasonable nb_errors_max = maximum b frames + thread count */ @@ -490,11 +508,9 @@ FF_ENABLE_DEPRECATION_WARNINGS } } - if (ret >= pkt->size || ret < 0) { + if (consumed >= pkt->size || ret < 0) { av_packet_unref(pkt); } else { - int consumed = ret; - pkt->data += consumed; pkt->size -= consumed; pkt->pts = AV_NOPTS_VALUE; @@ -509,10 +525,7 @@ FF_ENABLE_DEPRECATION_WARNINGS } } - if (got_frame) - av_assert0(frame->buf[0]); - - return ret < 0 ? ret : 0; + return ret; } #if CONFIG_LCMS2 From 7db4c3eaa656e8ddbde793da45697a1074a033fe Mon Sep 17 00:00:00 2001 From: James Almer Date: Wed, 12 Jul 2023 18:29:09 -0300 Subject: [PATCH 1835/2172] avcodec/decode: simplify applying or exporting skip samples Copy packet side data to the output frame in ff_decode_frame_props_from_pkt() instead of in discard_samples(), having the latter only applying the skip if required. This will be useful for the following commit. Signed-off-by: James Almer --- libavcodec/decode.c | 59 +++++++++++++++++++++------------------------ 1 file changed, 27 insertions(+), 32 deletions(-) diff --git a/libavcodec/decode.c b/libavcodec/decode.c index 4478c8c4fe2..7bf54b95d1e 100644 --- a/libavcodec/decode.c +++ b/libavcodec/decode.c @@ -293,26 +293,22 @@ static int discard_samples(AVCodecContext *avctx, AVFrame *frame, int64_t *disca { AVCodecInternal *avci = avctx->internal; int ret = 0; - uint8_t *side; - size_t side_size; + AVFrameSideData *side; uint32_t discard_padding = 0; uint8_t skip_reason = 0; uint8_t discard_reason = 0; - side = av_packet_get_side_data(avci->last_pkt_props, AV_PKT_DATA_SKIP_SAMPLES, &side_size); - if (side && side_size >= 10) { - avci->skip_samples = AV_RL32(side); + side = av_frame_get_side_data(frame, AV_FRAME_DATA_SKIP_SAMPLES); + if (side && side->size >= 10) { + avci->skip_samples = AV_RL32(side->data); avci->skip_samples = FFMAX(0, avci->skip_samples); - discard_padding = AV_RL32(side + 4); + discard_padding = AV_RL32(side->data + 4); av_log(avctx, AV_LOG_DEBUG, "skip %d / discard %d samples due to side data\n", avci->skip_samples, (int)discard_padding); - skip_reason = AV_RL8(side + 8); - discard_reason = AV_RL8(side + 9); + skip_reason = AV_RL8(side->data + 8); + discard_reason = AV_RL8(side->data + 9); } - if (!frame->buf[0]) - return AVERROR(EAGAIN); - if (frame->format == AV_SAMPLE_FMT_NONE) frame->format = avctx->sample_fmt; if (!frame->ch_layout.nb_channels) { @@ -333,15 +329,27 @@ FF_ENABLE_DEPRECATION_WARNINGS if (!frame->sample_rate) frame->sample_rate = avctx->sample_rate; - if ((frame->flags & AV_FRAME_FLAG_DISCARD) && - !(avctx->flags2 & AV_CODEC_FLAG2_SKIP_MANUAL)) { + if ((avctx->flags2 & AV_CODEC_FLAG2_SKIP_MANUAL)) { + if (!side && (avci->skip_samples || discard_padding)) + side = av_frame_new_side_data(frame, AV_FRAME_DATA_SKIP_SAMPLES, 10); + if (side && (avci->skip_samples || discard_padding)) { + AV_WL32(side->data, avci->skip_samples); + AV_WL32(side->data + 4, discard_padding); + AV_WL8(side->data + 8, skip_reason); + AV_WL8(side->data + 9, discard_reason); + avci->skip_samples = 0; + } + return ret; + } + av_frame_remove_side_data(frame, AV_FRAME_DATA_SKIP_SAMPLES); + + if ((frame->flags & AV_FRAME_FLAG_DISCARD)) { avci->skip_samples = FFMAX(0, avci->skip_samples - frame->nb_samples); *discarded_samples += frame->nb_samples; return AVERROR(EAGAIN); } - if (avci->skip_samples > 0 && - !(avctx->flags2 & AV_CODEC_FLAG2_SKIP_MANUAL)) { + if (avci->skip_samples > 0) { if (frame->nb_samples <= avci->skip_samples){ *discarded_samples += frame->nb_samples; avci->skip_samples -= frame->nb_samples; @@ -372,8 +380,7 @@ FF_ENABLE_DEPRECATION_WARNINGS } } - if (discard_padding > 0 && discard_padding <= frame->nb_samples && - !(avctx->flags2 & AV_CODEC_FLAG2_SKIP_MANUAL)) { + if (discard_padding > 0 && discard_padding <= frame->nb_samples) { if (discard_padding == frame->nb_samples) { *discarded_samples += frame->nb_samples; return AVERROR(EAGAIN); @@ -392,17 +399,6 @@ FF_ENABLE_DEPRECATION_WARNINGS } } - if ((avctx->flags2 & AV_CODEC_FLAG2_SKIP_MANUAL)) { - AVFrameSideData *fside = av_frame_new_side_data(frame, AV_FRAME_DATA_SKIP_SAMPLES, 10); - if (fside) { - AV_WL32(fside->data, avci->skip_samples); - AV_WL32(fside->data + 4, discard_padding); - AV_WL8(fside->data + 8, skip_reason); - AV_WL8(fside->data + 9, discard_reason); - avci->skip_samples = 0; - } - } - return ret; } @@ -465,15 +461,13 @@ FF_ENABLE_DEPRECATION_WARNINGS } emms_c(); - if (!got_frame) - av_frame_unref(frame); - if (avctx->codec->type == AVMEDIA_TYPE_VIDEO) { ret = (!got_frame || frame->flags & AV_FRAME_FLAG_DISCARD) ? AVERROR(EAGAIN) : 0; } else if (avctx->codec->type == AVMEDIA_TYPE_AUDIO) { - ret = discard_samples(avctx, frame, discarded_samples); + ret = !got_frame ? AVERROR(EAGAIN) + : discard_samples(avctx, frame, discarded_samples); } if (ret == AVERROR(EAGAIN)) @@ -1386,6 +1380,7 @@ int ff_decode_frame_props_from_pkt(const AVCodecContext *avctx, { AV_PKT_DATA_ICC_PROFILE, AV_FRAME_DATA_ICC_PROFILE }, { AV_PKT_DATA_S12M_TIMECODE, AV_FRAME_DATA_S12M_TIMECODE }, { AV_PKT_DATA_DYNAMIC_HDR10_PLUS, AV_FRAME_DATA_DYNAMIC_HDR_PLUS }, + { AV_PKT_DATA_SKIP_SAMPLES, AV_FRAME_DATA_SKIP_SAMPLES }, }; frame->pts = pkt->pts; From 94ac6475597ea4b5bf93d2072f518aaf25ef32b7 Mon Sep 17 00:00:00 2001 From: James Almer Date: Sun, 9 Jul 2023 10:39:16 -0300 Subject: [PATCH 1836/2172] avcodec/decode: check the output frame for discard samples with all decoders And not just those with the old decode() API. Signed-off-by: James Almer --- libavcodec/decode.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/libavcodec/decode.c b/libavcodec/decode.c index 7bf54b95d1e..e2aebbbde4e 100644 --- a/libavcodec/decode.c +++ b/libavcodec/decode.c @@ -597,6 +597,14 @@ static int decode_receive_frame_internal(AVCodecContext *avctx, AVFrame *frame) if (codec->cb_type == FF_CODEC_CB_TYPE_RECEIVE_FRAME) { ret = codec->cb.receive_frame(avctx, frame); emms_c(); + if (!ret) { + if (avctx->codec->type == AVMEDIA_TYPE_VIDEO) + ret = (frame->flags & AV_FRAME_FLAG_DISCARD) ? AVERROR(EAGAIN) : 0; + else if (avctx->codec->type == AVMEDIA_TYPE_AUDIO) { + int64_t discarded_samples = 0; + ret = discard_samples(avctx, frame, &discarded_samples); + } + } } else ret = decode_simple_receive_frame(avctx, frame); From dd7bdb40c4d576ea475310c6409eec6adf8cef68 Mon Sep 17 00:00:00 2001 From: James Almer Date: Sat, 8 Jul 2023 15:55:21 -0300 Subject: [PATCH 1837/2172] avcodec/decode: fill missing frame fields for all decoders And not just those with the old decode() API. Signed-off-by: James Almer --- libavcodec/decode.c | 79 +++++++++++++++++++++++++++------------------ 1 file changed, 48 insertions(+), 31 deletions(-) diff --git a/libavcodec/decode.c b/libavcodec/decode.c index e2aebbbde4e..1523fddf70a 100644 --- a/libavcodec/decode.c +++ b/libavcodec/decode.c @@ -292,7 +292,6 @@ static int64_t guess_correct_pts(AVCodecContext *ctx, static int discard_samples(AVCodecContext *avctx, AVFrame *frame, int64_t *discarded_samples) { AVCodecInternal *avci = avctx->internal; - int ret = 0; AVFrameSideData *side; uint32_t discard_padding = 0; uint8_t skip_reason = 0; @@ -309,26 +308,6 @@ static int discard_samples(AVCodecContext *avctx, AVFrame *frame, int64_t *disca discard_reason = AV_RL8(side->data + 9); } - if (frame->format == AV_SAMPLE_FMT_NONE) - frame->format = avctx->sample_fmt; - if (!frame->ch_layout.nb_channels) { - int ret2 = av_channel_layout_copy(&frame->ch_layout, &avctx->ch_layout); - if (ret2 < 0) { - ret = ret2; - } - } -#if FF_API_OLD_CHANNEL_LAYOUT -FF_DISABLE_DEPRECATION_WARNINGS - if (!frame->channel_layout) - frame->channel_layout = avctx->ch_layout.order == AV_CHANNEL_ORDER_NATIVE ? - avctx->ch_layout.u.mask : 0; - if (!frame->channels) - frame->channels = avctx->ch_layout.nb_channels; -FF_ENABLE_DEPRECATION_WARNINGS -#endif - if (!frame->sample_rate) - frame->sample_rate = avctx->sample_rate; - if ((avctx->flags2 & AV_CODEC_FLAG2_SKIP_MANUAL)) { if (!side && (avci->skip_samples || discard_padding)) side = av_frame_new_side_data(frame, AV_FRAME_DATA_SKIP_SAMPLES, 10); @@ -339,7 +318,7 @@ FF_ENABLE_DEPRECATION_WARNINGS AV_WL8(side->data + 9, discard_reason); avci->skip_samples = 0; } - return ret; + return 0; } av_frame_remove_side_data(frame, AV_FRAME_DATA_SKIP_SAMPLES); @@ -399,7 +378,7 @@ FF_ENABLE_DEPRECATION_WARNINGS } } - return ret; + return 0; } /* @@ -449,14 +428,6 @@ FF_DISABLE_DEPRECATION_WARNINGS frame->pkt_pos = pkt->pos; FF_ENABLE_DEPRECATION_WARNINGS #endif - //FIXME these should be under if(!avctx->has_b_frames) - /* get_buffer is supposed to set frame parameters */ - if (!(avctx->codec->capabilities & AV_CODEC_CAP_DR1)) { - if (!frame->sample_aspect_ratio.num) frame->sample_aspect_ratio = avctx->sample_aspect_ratio; - if (!frame->width) frame->width = avctx->width; - if (!frame->height) frame->height = avctx->height; - if (frame->format == AV_PIX_FMT_NONE) frame->format = avctx->pix_fmt; - } } } emms_c(); @@ -570,6 +541,45 @@ static int detect_colorspace(av_unused AVCodecContext *c, av_unused AVFrame *f) } #endif +static int fill_frame_props(AVCodecContext *avctx, AVFrame *frame) +{ + int ret; + + if (avctx->codec_type == AVMEDIA_TYPE_VIDEO) { + //FIXME these should be under if(!avctx->has_b_frames) + /* get_buffer is supposed to set frame parameters */ + if (!(avctx->codec->capabilities & AV_CODEC_CAP_DR1)) { + if (!frame->sample_aspect_ratio.num) frame->sample_aspect_ratio = avctx->sample_aspect_ratio; + if (!frame->width) frame->width = avctx->width; + if (!frame->height) frame->height = avctx->height; + if (frame->format == AV_PIX_FMT_NONE) frame->format = avctx->pix_fmt; + } + } else if (avctx->codec->type == AVMEDIA_TYPE_AUDIO) { + if (frame->format == AV_SAMPLE_FMT_NONE) + frame->format = avctx->sample_fmt; + if (!frame->ch_layout.nb_channels) { + ret = av_channel_layout_copy(&frame->ch_layout, &avctx->ch_layout); + if (ret < 0) { + av_frame_unref(frame); + return ret; + } + } +#if FF_API_OLD_CHANNEL_LAYOUT +FF_DISABLE_DEPRECATION_WARNINGS + if (!frame->channel_layout) + frame->channel_layout = avctx->ch_layout.order == AV_CHANNEL_ORDER_NATIVE ? + avctx->ch_layout.u.mask : 0; + if (!frame->channels) + frame->channels = avctx->ch_layout.nb_channels; +FF_ENABLE_DEPRECATION_WARNINGS +#endif + if (!frame->sample_rate) + frame->sample_rate = avctx->sample_rate; + } + + return 0; +} + static int decode_simple_receive_frame(AVCodecContext *avctx, AVFrame *frame) { int ret; @@ -621,6 +631,13 @@ static int decode_receive_frame_internal(AVCodecContext *avctx, AVFrame *frame) if (!ret) { if (avctx->codec_type != AVMEDIA_TYPE_VIDEO) frame->flags |= AV_FRAME_FLAG_KEY; + + ret = fill_missing_fields(avctx, frame); + if (ret < 0) { + av_frame_unref(frame); + return ret; + } + #if FF_API_FRAME_KEY FF_DISABLE_DEPRECATION_WARNINGS frame->key_frame = !!(frame->flags & AV_FRAME_FLAG_KEY); From 74611cdb5ca02e96d40ace2f34cbf14ac88a0dcc Mon Sep 17 00:00:00 2001 From: James Almer Date: Fri, 14 Jul 2023 13:59:40 -0300 Subject: [PATCH 1838/2172] avcodec/decode: use the correct function name Fixes compilation erros. Signed-off-by: James Almer --- libavcodec/decode.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavcodec/decode.c b/libavcodec/decode.c index 1523fddf70a..68525e47a60 100644 --- a/libavcodec/decode.c +++ b/libavcodec/decode.c @@ -632,7 +632,7 @@ static int decode_receive_frame_internal(AVCodecContext *avctx, AVFrame *frame) if (avctx->codec_type != AVMEDIA_TYPE_VIDEO) frame->flags |= AV_FRAME_FLAG_KEY; - ret = fill_missing_fields(avctx, frame); + ret = fill_frame_props(avctx, frame); if (ret < 0) { av_frame_unref(frame); return ret; From e652e7dcdaefbc5d4adc61b01ba10d223c28ba83 Mon Sep 17 00:00:00 2001 From: Logan Lyu Date: Sun, 7 May 2023 16:58:30 +0800 Subject: [PATCH 1839/2172] lavc/aarch64: new optimization for 8-bit hevc_pel_uni_pixels MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit put_hevc_pel_uni_pixels4_8_c: 35.9 put_hevc_pel_uni_pixels4_8_neon: 7.6 put_hevc_pel_uni_pixels6_8_c: 46.1 put_hevc_pel_uni_pixels6_8_neon: 20.6 put_hevc_pel_uni_pixels8_8_c: 53.4 put_hevc_pel_uni_pixels8_8_neon: 11.6 put_hevc_pel_uni_pixels12_8_c: 89.1 put_hevc_pel_uni_pixels12_8_neon: 25.9 put_hevc_pel_uni_pixels16_8_c: 106.4 put_hevc_pel_uni_pixels16_8_neon: 20.4 put_hevc_pel_uni_pixels24_8_c: 137.6 put_hevc_pel_uni_pixels24_8_neon: 47.1 put_hevc_pel_uni_pixels32_8_c: 173.6 put_hevc_pel_uni_pixels32_8_neon: 54.1 put_hevc_pel_uni_pixels48_8_c: 268.1 put_hevc_pel_uni_pixels48_8_neon: 117.1 put_hevc_pel_uni_pixels64_8_c: 346.1 put_hevc_pel_uni_pixels64_8_neon: 205.9 Signed-off-by: Martin Storsjö --- libavcodec/aarch64/hevcdsp_init_aarch64.c | 5 ++ libavcodec/aarch64/hevcdsp_qpel_neon.S | 104 ++++++++++++++++++++++ 2 files changed, 109 insertions(+) diff --git a/libavcodec/aarch64/hevcdsp_init_aarch64.c b/libavcodec/aarch64/hevcdsp_init_aarch64.c index 483a9d52535..5a1d520eec8 100644 --- a/libavcodec/aarch64/hevcdsp_init_aarch64.c +++ b/libavcodec/aarch64/hevcdsp_init_aarch64.c @@ -152,6 +152,9 @@ void ff_hevc_put_hevc_qpel_bi_h16_8_neon(uint8_t *_dst, ptrdiff_t _dststride, co void ff_hevc_put_hevc_##fn##32_8_neon##ext args; \ void ff_hevc_put_hevc_##fn##64_8_neon##ext args; \ +NEON8_FNPROTO(pel_uni_pixels, (uint8_t *_dst, ptrdiff_t _dststride, + const uint8_t *_src, ptrdiff_t _srcstride, + int height, intptr_t mx, intptr_t my, int width),); NEON8_FNPROTO(pel_uni_w_pixels, (uint8_t *_dst, ptrdiff_t _dststride, const uint8_t *_src, ptrdiff_t _srcstride, @@ -263,6 +266,8 @@ av_cold void ff_hevc_dsp_init_aarch64(HEVCDSPContext *c, const int bit_depth) c->put_hevc_qpel_bi[8][0][1] = c->put_hevc_qpel_bi[9][0][1] = ff_hevc_put_hevc_qpel_bi_h16_8_neon; + NEON8_FNASSIGN(c->put_hevc_epel_uni, 0, 0, pel_uni_pixels,); + NEON8_FNASSIGN(c->put_hevc_qpel_uni, 0, 0, pel_uni_pixels,); NEON8_FNASSIGN(c->put_hevc_epel_uni_w, 0, 0, pel_uni_w_pixels,); NEON8_FNASSIGN(c->put_hevc_qpel_uni_w, 0, 0, pel_uni_w_pixels,); NEON8_FNASSIGN_PARTIAL_4(c->put_hevc_qpel_uni_w, 1, 0, qpel_uni_w_v,); diff --git a/libavcodec/aarch64/hevcdsp_qpel_neon.S b/libavcodec/aarch64/hevcdsp_qpel_neon.S index 46c6d4c27ec..e38dff9645d 100644 --- a/libavcodec/aarch64/hevcdsp_qpel_neon.S +++ b/libavcodec/aarch64/hevcdsp_qpel_neon.S @@ -490,6 +490,110 @@ put_hevc qpel put_hevc qpel_uni put_hevc qpel_bi +function ff_hevc_put_hevc_pel_uni_pixels4_8_neon, export=1 +1: + ldr s0, [x2] + ldr s1, [x2, x3] + subs w4, w4, #2 + add x2, x2, x3, lsl #1 + str s0, [x0] + str s1, [x0, x1] + add x0, x0, x1, lsl #1 + b.hi 1b + ret +endfunc + +function ff_hevc_put_hevc_pel_uni_pixels6_8_neon, export=1 + sub x1, x1, #4 +1: + ldr d0, [x2] + ldr d1, [x2, x3] + subs w4, w4, #2 + add x2, x2, x3, lsl #1 + str s0, [x0], #4 + st1 {v0.h}[2], [x0], x1 + str s1, [x0], #4 + st1 {v1.h}[2], [x0], x1 + b.hi 1b + ret +endfunc + +function ff_hevc_put_hevc_pel_uni_pixels8_8_neon, export=1 +1: + ldr d0, [x2] + ldr d1, [x2, x3] + subs w4, w4, #2 + add x2, x2, x3, lsl #1 + str d0, [x0] + str d1, [x0, x1] + add x0, x0, x1, lsl #1 + b.hi 1b + ret +endfunc + +function ff_hevc_put_hevc_pel_uni_pixels12_8_neon, export=1 + sub x1, x1, #8 +1: + ldr q0, [x2] + ldr q1, [x2, x3] + subs w4, w4, #2 + add x2, x2, x3, lsl #1 + str d0, [x0], #8 + st1 {v0.s}[2], [x0], x1 + str d1, [x0], #8 + st1 {v1.s}[2], [x0], x1 + b.hi 1b + ret +endfunc + +function ff_hevc_put_hevc_pel_uni_pixels16_8_neon, export=1 +1: + ldr q0, [x2] + ldr q1, [x2, x3] + subs w4, w4, #2 + add x2, x2, x3, lsl #1 + str q0, [x0] + str q1, [x0, x1] + add x0, x0, x1, lsl #1 + b.hi 1b + ret +endfunc + +function ff_hevc_put_hevc_pel_uni_pixels24_8_neon, export=1 +1: + ld1 {v0.8b, v1.8b, v2.8b}, [x2], x3 + subs w4, w4, #1 + st1 {v0.8b, v1.8b, v2.8b}, [x0], x1 + b.hi 1b + ret +endfunc + +function ff_hevc_put_hevc_pel_uni_pixels32_8_neon, export=1 +1: + ld1 {v0.16b, v1.16b}, [x2], x3 + subs w4, w4, #1 + st1 {v0.16b, v1.16b}, [x0], x1 + b.hi 1b + ret +endfunc + +function ff_hevc_put_hevc_pel_uni_pixels48_8_neon, export=1 +1: + ld1 {v0.16b, v1.16b, v2.16b}, [x2], x3 + subs w4, w4, #1 + st1 {v0.16b, v1.16b, v2.16b}, [x0], x1 + b.hi 1b + ret +endfunc + +function ff_hevc_put_hevc_pel_uni_pixels64_8_neon, export=1 +1: + ld1 {v0.16b, v1.16b, v2.16b, v3.16b}, [x2], x3 + subs w4, w4, #1 + st1 {v0.16b, v1.16b, v2.16b, v3.16b}, [x0], x1 + b.hi 1b + ret +endfunc function ff_hevc_put_hevc_pel_uni_w_pixels4_8_neon, export=1 mov w10, #-6 From 0c604b19137cc36f101ecca3bd0efc6e93df8896 Mon Sep 17 00:00:00 2001 From: Logan Lyu Date: Sun, 28 May 2023 10:07:28 +0800 Subject: [PATCH 1840/2172] lavc/aarch64: new optimization for 8-bit hevc_epel_uni_w_h MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit put_hevc_epel_uni_w_h4_8_c: 126.1 put_hevc_epel_uni_w_h4_8_i8mm: 41.6 put_hevc_epel_uni_w_h6_8_c: 222.9 put_hevc_epel_uni_w_h6_8_i8mm: 91.4 put_hevc_epel_uni_w_h8_8_c: 374.4 put_hevc_epel_uni_w_h8_8_i8mm: 102.1 put_hevc_epel_uni_w_h12_8_c: 806.1 put_hevc_epel_uni_w_h12_8_i8mm: 225.6 put_hevc_epel_uni_w_h16_8_c: 1414.4 put_hevc_epel_uni_w_h16_8_i8mm: 333.4 put_hevc_epel_uni_w_h24_8_c: 3128.6 put_hevc_epel_uni_w_h24_8_i8mm: 713.1 put_hevc_epel_uni_w_h32_8_c: 5519.1 put_hevc_epel_uni_w_h32_8_i8mm: 1118.1 put_hevc_epel_uni_w_h48_8_c: 12364.4 put_hevc_epel_uni_w_h48_8_i8mm: 2541.1 put_hevc_epel_uni_w_h64_8_c: 21925.9 put_hevc_epel_uni_w_h64_8_i8mm: 4383.6 Signed-off-by: Martin Storsjö --- libavcodec/aarch64/Makefile | 1 + libavcodec/aarch64/hevcdsp_epel_neon.S | 377 ++++++++++++++++++++++ libavcodec/aarch64/hevcdsp_init_aarch64.c | 7 +- 3 files changed, 384 insertions(+), 1 deletion(-) create mode 100644 libavcodec/aarch64/hevcdsp_epel_neon.S diff --git a/libavcodec/aarch64/Makefile b/libavcodec/aarch64/Makefile index 216191640c7..cb428b49e0f 100644 --- a/libavcodec/aarch64/Makefile +++ b/libavcodec/aarch64/Makefile @@ -69,4 +69,5 @@ NEON-OBJS-$(CONFIG_HEVC_DECODER) += aarch64/hevcdsp_deblock_neon.o \ aarch64/hevcdsp_idct_neon.o \ aarch64/hevcdsp_init_aarch64.o \ aarch64/hevcdsp_qpel_neon.o \ + aarch64/hevcdsp_epel_neon.o \ aarch64/hevcdsp_sao_neon.o diff --git a/libavcodec/aarch64/hevcdsp_epel_neon.S b/libavcodec/aarch64/hevcdsp_epel_neon.S new file mode 100644 index 00000000000..0411de9864f --- /dev/null +++ b/libavcodec/aarch64/hevcdsp_epel_neon.S @@ -0,0 +1,377 @@ +/* -*-arm64-*- + * vim: syntax=arm64asm + * + * 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/aarch64/asm.S" +#define MAX_PB_SIZE 64 + +const epel_filters, align=4 + .byte 0, 0, 0, 0 + .byte -2, 58, 10, -2 + .byte -4, 54, 16, -2 + .byte -6, 46, 28, -4 + .byte -4, 36, 36, -4 + .byte -4, 28, 46, -6 + .byte -2, 16, 54, -4 + .byte -2, 10, 58, -2 +endconst + +#if HAVE_I8MM +.macro EPEL_UNI_W_H_HEADER + ldr x12, [sp] + sub x2, x2, #1 + movrel x9, epel_filters + add x9, x9, x12, lsl #2 + ld1r {v28.4s}, [x9] + mov w10, #-6 + sub w10, w10, w5 + dup v30.4s, w6 + dup v31.4s, w10 + dup v29.4s, w7 +.endm + + +function ff_hevc_put_hevc_epel_uni_w_h4_8_neon_i8mm, export=1 + EPEL_UNI_W_H_HEADER +1: + ld1 {v0.8b}, [x2], x3 + subs w4, w4, #1 + ext v1.8b, v0.8b, v0.8b, #1 + ext v2.8b, v0.8b, v0.8b, #2 + ext v3.8b, v0.8b, v0.8b, #3 + trn1 v0.2s, v0.2s, v2.2s + trn1 v1.2s, v1.2s, v3.2s + zip1 v0.4s, v0.4s, v1.4s + movi v16.2d, #0 + usdot v16.4s, v0.16b, v28.16b + mul v16.4s, v16.4s, v30.4s + sqrshl v16.4s, v16.4s, v31.4s + sqadd v16.4s, v16.4s, v29.4s + sqxtn v16.4h, v16.4s + sqxtun v16.8b, v16.8h + str s16, [x0] + add x0, x0, x1 + b.hi 1b + ret +endfunc + + +function ff_hevc_put_hevc_epel_uni_w_h6_8_neon_i8mm, export=1 + EPEL_UNI_W_H_HEADER + sub x1, x1, #4 +1: + ld1 {v0.16b}, [x2], x3 + subs w4, w4, #1 + ext v1.16b, v0.16b, v0.16b, #1 + ext v2.16b, v0.16b, v0.16b, #2 + ext v3.16b, v0.16b, v0.16b, #3 + trn1 v4.2s, v0.2s, v1.2s + trn2 v6.2s, v0.2s, v1.2s + trn1 v5.2s, v2.2s, v3.2s + zip1 v4.2d, v4.2d, v5.2d + movi v16.2d, #0 + movi v17.2d, #0 + usdot v16.4s, v4.16b, v28.16b + usdot v17.2s, v6.8b, v28.8b + mul v16.4s, v16.4s, v30.4s + mul v17.2s, v17.2s, v30.2s + sqrshl v16.4s, v16.4s, v31.4s + sqrshl v17.2s, v17.2s, v31.2s + sqadd v16.4s, v16.4s, v29.4s + sqadd v17.2s, v17.2s, v29.2s + sqxtn v16.4h, v16.4s + sqxtn2 v16.8h, v17.4s + sqxtun v16.8b, v16.8h + str s16, [x0], #4 + st1 {v16.h}[2], [x0], x1 + b.hi 1b + ret +endfunc + +.macro EPEL_UNI_W_H_CALC s0, s1, d0, d1 + movi \d0\().2d, #0 + movi \d1\().2d, #0 + usdot \d0\().4s, \s0\().16b, v28.16b + usdot \d1\().4s, \s1\().16b, v28.16b + mul \d0\().4s, \d0\().4s, v30.4s + mul \d1\().4s, \d1\().4s, v30.4s + sqrshl \d0\().4s, \d0\().4s, v31.4s + sqrshl \d1\().4s, \d1\().4s, v31.4s + sqadd \d0\().4s, \d0\().4s, v29.4s + sqadd \d1\().4s, \d1\().4s, v29.4s +.endm + +function ff_hevc_put_hevc_epel_uni_w_h8_8_neon_i8mm, export=1 + EPEL_UNI_W_H_HEADER +1: + ld1 {v0.16b}, [x2], x3 + subs w4, w4, #1 + ext v1.16b, v0.16b, v0.16b, #1 + ext v2.16b, v0.16b, v0.16b, #2 + ext v3.16b, v0.16b, v0.16b, #3 + zip1 v4.4s, v0.4s, v2.4s + zip1 v5.4s, v1.4s, v3.4s + EPEL_UNI_W_H_CALC v4, v5, v16, v17 + sqxtn v16.4h, v16.4s + sqxtn v17.4h, v17.4s + zip1 v16.8h, v16.8h, v17.8h + sqxtun v16.8b, v16.8h + str d16, [x0] + add x0, x0, x1 + b.hi 1b + ret +endfunc + +function ff_hevc_put_hevc_epel_uni_w_h12_8_neon_i8mm, export=1 + EPEL_UNI_W_H_HEADER +1: + ld1 {v0.16b}, [x2], x3 + subs w4, w4, #1 + ext v1.16b, v0.16b, v0.16b, #1 + ext v2.16b, v0.16b, v0.16b, #2 + ext v3.16b, v0.16b, v0.16b, #3 + zip1 v4.4s, v0.4s, v2.4s + zip1 v5.4s, v1.4s, v3.4s + zip2 v6.4s, v0.4s, v2.4s + zip2 v7.4s, v1.4s, v3.4s + zip1 v6.4s, v6.4s, v7.4s + EPEL_UNI_W_H_CALC v4, v5, v16, v17 + movi v18.2d, #0 + usdot v18.4s, v6.16b, v28.16b + mul v18.4s, v18.4s, v30.4s + sqrshl v18.4s, v18.4s, v31.4s + sqadd v18.4s, v18.4s, v29.4s + sqxtn v16.4h, v16.4s + sqxtn v17.4h, v17.4s + sqxtn v18.4h, v18.4s + zip1 v16.8h, v16.8h, v17.8h + sqxtun v16.8b, v16.8h + sqxtun v18.8b, v18.8h + str d16, [x0] + str s18, [x0, #8] + add x0, x0, x1 + b.hi 1b + ret +endfunc + +function ff_hevc_put_hevc_epel_uni_w_h16_8_neon_i8mm, export=1 + EPEL_UNI_W_H_HEADER +1: + ld1 {v0.16b, v1.16b}, [x2], x3 + subs w4, w4, #1 + ext v4.16b, v0.16b, v1.16b, #1 + ext v5.16b, v0.16b, v1.16b, #2 + ext v6.16b, v0.16b, v1.16b, #3 + zip1 v20.4s, v0.4s, v5.4s + zip1 v21.4s, v4.4s, v6.4s + zip2 v22.4s, v0.4s, v5.4s + zip2 v23.4s, v4.4s, v6.4s + EPEL_UNI_W_H_CALC v20, v21, v16, v17 + EPEL_UNI_W_H_CALC v22, v23, v18, v19 + sqxtn v16.4h, v16.4s + sqxtn v17.4h, v17.4s + sqxtn2 v16.8h, v18.4s + sqxtn2 v17.8h, v19.4s + sqxtun v16.8b, v16.8h + sqxtun v17.8b, v17.8h + st2 {v16.8b, v17.8b}, [x0], x1 + b.hi 1b + ret +endfunc + +function ff_hevc_put_hevc_epel_uni_w_h24_8_neon_i8mm, export=1 + EPEL_UNI_W_H_HEADER +1: + ld1 {v0.16b, v1.16b}, [x2], x3 + subs w4, w4, #1 + ext v2.16b, v0.16b, v1.16b, #1 + ext v3.16b, v0.16b, v1.16b, #2 + ext v4.16b, v0.16b, v1.16b, #3 + ext v5.16b, v1.16b, v1.16b, #1 + ext v6.16b, v1.16b, v1.16b, #2 + ext v7.16b, v1.16b, v1.16b, #3 + zip1 v20.4s, v0.4s, v3.4s + zip1 v21.4s, v2.4s, v4.4s + zip2 v22.4s, v0.4s, v3.4s + zip2 v23.4s, v2.4s, v4.4s + zip1 v24.4s, v1.4s, v6.4s + zip1 v25.4s, v5.4s, v7.4s + EPEL_UNI_W_H_CALC v20, v21, v16, v17 + EPEL_UNI_W_H_CALC v22, v23, v18, v19 + EPEL_UNI_W_H_CALC v24, v25, v26, v27 + sqxtn v16.4h, v16.4s + sqxtn v17.4h, v17.4s + sqxtn v18.4h, v18.4s + sqxtn v19.4h, v19.4s + sqxtn v26.4h, v26.4s + sqxtn v27.4h, v27.4s + zip1 v16.8h, v16.8h, v17.8h + zip1 v18.8h, v18.8h, v19.8h + zip1 v26.8h, v26.8h, v27.8h + sqxtun v16.8b, v16.8h + sqxtun2 v16.16b, v18.8h + sqxtun v26.8b, v26.8h + str q16, [x0] + str d26, [x0, #16] + add x0, x0, x1 + b.hi 1b + ret +endfunc + +function ff_hevc_put_hevc_epel_uni_w_h32_8_neon_i8mm, export=1 + EPEL_UNI_W_H_HEADER +1: + ld1 {v0.16b, v1.16b, v2.16b}, [x2], x3 + subs w4, w4, #1 + ext v3.16b, v0.16b, v1.16b, #1 + ext v4.16b, v0.16b, v1.16b, #2 + ext v5.16b, v0.16b, v1.16b, #3 + ext v16.16b, v1.16b, v2.16b, #1 + ext v17.16b, v1.16b, v2.16b, #2 + ext v18.16b, v1.16b, v2.16b, #3 + EPEL_UNI_W_H_CALC v0, v3, v6, v7 + EPEL_UNI_W_H_CALC v4, v5, v19, v20 + EPEL_UNI_W_H_CALC v1, v16, v21, v22 + EPEL_UNI_W_H_CALC v17, v18, v23, v24 + sqxtn v6.4h, v6.4s + sqxtn2 v6.8h, v21.4s + sqxtn v7.4h, v7.4s + sqxtn2 v7.8h, v22.4s + sqxtn v19.4h, v19.4s + sqxtn2 v19.8h, v23.4s + sqxtn v20.4h, v20.4s + sqxtn2 v20.8h, v24.4s + sqxtun v0.8b, v6.8h + sqxtun v1.8b, v7.8h + sqxtun v2.8b, v19.8h + sqxtun v3.8b, v20.8h + st4 {v0.8b, v1.8b, v2.8b, v3.8b}, [x0], x1 + b.hi 1b + ret +endfunc + + + +function ff_hevc_put_hevc_epel_uni_w_h48_8_neon_i8mm, export=1 + EPEL_UNI_W_H_HEADER + sub x1, x1, #32 +1: + ld1 {v0.16b, v1.16b, v2.16b, v3.16b}, [x2], x3 + subs w4, w4, #1 + ext v4.16b, v0.16b, v1.16b, #1 + ext v5.16b, v0.16b, v1.16b, #2 + ext v6.16b, v0.16b, v1.16b, #3 + ext v16.16b, v1.16b, v2.16b, #1 + ext v17.16b, v1.16b, v2.16b, #2 + ext v18.16b, v1.16b, v2.16b, #3 + EPEL_UNI_W_H_CALC v0, v4, v19, v20 + EPEL_UNI_W_H_CALC v5, v6, v21, v22 + EPEL_UNI_W_H_CALC v1, v16, v23, v24 + EPEL_UNI_W_H_CALC v17, v18, v25, v26 + sqxtn v19.4h, v19.4s + sqxtn2 v19.8h, v23.4s + sqxtn v20.4h, v20.4s + sqxtn2 v20.8h, v24.4s + sqxtn v21.4h, v21.4s + sqxtn2 v21.8h, v25.4s + sqxtn v22.4h, v22.4s + sqxtn2 v22.8h, v26.4s + sqxtun v19.8b, v19.8h + sqxtun v20.8b, v20.8h + sqxtun v21.8b, v21.8h + sqxtun v22.8b, v22.8h + st4 {v19.8b, v20.8b, v21.8b, v22.8b}, [x0], #32 + ext v5.16b, v2.16b, v3.16b, #1 + ext v6.16b, v2.16b, v3.16b, #2 + ext v7.16b, v2.16b, v3.16b, #3 + EPEL_UNI_W_H_CALC v2, v5, v19, v20 + EPEL_UNI_W_H_CALC v6, v7, v21, v22 + sqxtn v19.4h, v19.4s + sqxtn v20.4h, v20.4s + sqxtn v21.4h, v21.4s + sqxtn v22.4h, v22.4s + zip1 v4.8h, v19.8h, v21.8h + zip1 v5.8h, v20.8h, v22.8h + sqxtun v4.8b, v4.8h + sqxtun v5.8b, v5.8h + st2 {v4.8b, v5.8b}, [x0], x1 + b.hi 1b + ret +endfunc + + +function ff_hevc_put_hevc_epel_uni_w_h64_8_neon_i8mm, export=1 + EPEL_UNI_W_H_HEADER + sub x1, x1, #32 + sub x3, x3, #64 +1: + ld1 {v0.16b, v1.16b, v2.16b, v3.16b}, [x2], #64 + subs w4, w4, #1 + ext v4.16b, v0.16b, v1.16b, #1 + ext v5.16b, v0.16b, v1.16b, #2 + ext v6.16b, v0.16b, v1.16b, #3 + ext v16.16b, v1.16b, v2.16b, #1 + ext v17.16b, v1.16b, v2.16b, #2 + ext v18.16b, v1.16b, v2.16b, #3 + EPEL_UNI_W_H_CALC v0, v4, v19, v20 + EPEL_UNI_W_H_CALC v5, v6, v21, v22 + EPEL_UNI_W_H_CALC v1, v16, v23, v24 + EPEL_UNI_W_H_CALC v17, v18, v25, v26 + sqxtn v19.4h, v19.4s + sqxtn2 v19.8h, v23.4s + sqxtn v20.4h, v20.4s + sqxtn2 v20.8h, v24.4s + sqxtn v21.4h, v21.4s + sqxtn2 v21.8h, v25.4s + sqxtn v22.4h, v22.4s + sqxtn2 v22.8h, v26.4s + sqxtun v19.8b, v19.8h + sqxtun v20.8b, v20.8h + sqxtun v21.8b, v21.8h + sqxtun v22.8b, v22.8h + st4 {v19.8b, v20.8b, v21.8b, v22.8b}, [x0], #32 + ld1 {v7.8b}, [x2], x3 + ext v4.16b, v2.16b, v3.16b, #1 + ext v5.16b, v2.16b, v3.16b, #2 + ext v6.16b, v2.16b, v3.16b, #3 + ext v16.16b, v3.16b, v7.16b, #1 + ext v17.16b, v3.16b, v7.16b, #2 + ext v18.16b, v3.16b, v7.16b, #3 + EPEL_UNI_W_H_CALC v2, v4, v19, v20 + EPEL_UNI_W_H_CALC v5, v6, v21, v22 + EPEL_UNI_W_H_CALC v3, v16, v23, v24 + EPEL_UNI_W_H_CALC v17, v18, v25, v26 + sqxtn v19.4h, v19.4s + sqxtn2 v19.8h, v23.4s + sqxtn v20.4h, v20.4s + sqxtn2 v20.8h, v24.4s + sqxtn v21.4h, v21.4s + sqxtn2 v21.8h, v25.4s + sqxtn v22.4h, v22.4s + sqxtn2 v22.8h, v26.4s + sqxtun v19.8b, v19.8h + sqxtun v20.8b, v20.8h + sqxtun v21.8b, v21.8h + sqxtun v22.8b, v22.8h + st4 {v19.8b, v20.8b, v21.8b, v22.8b}, [x0], x1 + b.hi 1b + ret +endfunc + +#endif diff --git a/libavcodec/aarch64/hevcdsp_init_aarch64.c b/libavcodec/aarch64/hevcdsp_init_aarch64.c index 5a1d520eec8..8af0a2b4b92 100644 --- a/libavcodec/aarch64/hevcdsp_init_aarch64.c +++ b/libavcodec/aarch64/hevcdsp_init_aarch64.c @@ -166,6 +166,10 @@ NEON8_FNPROTO_PARTIAL_4(qpel_uni_w_v, (uint8_t *_dst, ptrdiff_t _dststride, int height, int denom, int wx, int ox, intptr_t mx, intptr_t my, int width),); +NEON8_FNPROTO(epel_uni_w_h, (uint8_t *_dst, ptrdiff_t _dststride, + const uint8_t *_src, ptrdiff_t _srcstride, + int height, int denom, int wx, int ox, + intptr_t mx, intptr_t my, int width), _i8mm); NEON8_FNPROTO(qpel_h, (int16_t *dst, const uint8_t *_src, ptrdiff_t _srcstride, @@ -273,8 +277,9 @@ av_cold void ff_hevc_dsp_init_aarch64(HEVCDSPContext *c, const int bit_depth) NEON8_FNASSIGN_PARTIAL_4(c->put_hevc_qpel_uni_w, 1, 0, qpel_uni_w_v,); if (have_i8mm(cpu_flags)) { - NEON8_FNASSIGN(c->put_hevc_qpel_uni_w, 0, 1, qpel_uni_w_h, _i8mm); + NEON8_FNASSIGN(c->put_hevc_epel_uni_w, 0, 1, epel_uni_w_h ,_i8mm); NEON8_FNASSIGN(c->put_hevc_qpel, 0, 1, qpel_h, _i8mm); + NEON8_FNASSIGN(c->put_hevc_qpel_uni_w, 0, 1, qpel_uni_w_h, _i8mm); NEON8_FNASSIGN_PARTIAL_5(c->put_hevc_qpel_uni_w, 1, 1, qpel_uni_w_hv, _i8mm); } From 668eb4c00e4df76ec8921cfea7c0c7574f605d8f Mon Sep 17 00:00:00 2001 From: Logan Lyu Date: Sat, 27 May 2023 09:42:07 +0800 Subject: [PATCH 1841/2172] lavc/aarch64: new optimization for 8-bit hevc_epel_uni_w_v MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit put_hevc_epel_uni_w_v4_8_c: 116.1 put_hevc_epel_uni_w_v4_8_neon: 48.6 put_hevc_epel_uni_w_v6_8_c: 248.9 put_hevc_epel_uni_w_v6_8_neon: 80.6 put_hevc_epel_uni_w_v8_8_c: 383.9 put_hevc_epel_uni_w_v8_8_neon: 91.9 put_hevc_epel_uni_w_v12_8_c: 806.1 put_hevc_epel_uni_w_v12_8_neon: 202.9 put_hevc_epel_uni_w_v16_8_c: 1411.1 put_hevc_epel_uni_w_v16_8_neon: 289.9 put_hevc_epel_uni_w_v24_8_c: 3168.9 put_hevc_epel_uni_w_v24_8_neon: 619.4 put_hevc_epel_uni_w_v32_8_c: 5632.9 put_hevc_epel_uni_w_v32_8_neon: 1161.1 put_hevc_epel_uni_w_v48_8_c: 12406.1 put_hevc_epel_uni_w_v48_8_neon: 2476.4 put_hevc_epel_uni_w_v64_8_c: 22001.4 put_hevc_epel_uni_w_v64_8_neon: 4343.9 Signed-off-by: Martin Storsjö --- libavcodec/aarch64/hevcdsp_epel_neon.S | 503 ++++++++++++++++++++++ libavcodec/aarch64/hevcdsp_init_aarch64.c | 6 + 2 files changed, 509 insertions(+) diff --git a/libavcodec/aarch64/hevcdsp_epel_neon.S b/libavcodec/aarch64/hevcdsp_epel_neon.S index 0411de9864f..a99fac1c50f 100644 --- a/libavcodec/aarch64/hevcdsp_epel_neon.S +++ b/libavcodec/aarch64/hevcdsp_epel_neon.S @@ -375,3 +375,506 @@ function ff_hevc_put_hevc_epel_uni_w_h64_8_neon_i8mm, export=1 endfunc #endif + + +.macro EPEL_UNI_W_V_HEADER + ldr x12, [sp, #8] + movrel x9, epel_filters + add x9, x9, x12, lsl #2 + ld4r {v0.16b, v1.16b, v2.16b, v3.16b}, [x9] // filter + neg v0.16b, v0.16b + neg v3.16b, v3.16b + mov w10, #-6 + sub w10, w10, w5 + dup v30.8h, w6 + dup v31.4s, w10 + dup v29.4s, w7 + sub x2, x2, x3 +.endm + +.macro EPEL_UNI_W_V4_CALC d0, s0, s1, s2, s3 + movi \d0\().2d, #0 + umlsl \d0\().8h, \s0\().8b, v0.8b + umlal \d0\().8h, \s1\().8b, v1.8b + umlal \d0\().8h, \s2\().8b, v2.8b + umlsl \d0\().8h, \s3\().8b, v3.8b + smull \d0\().4s, \d0\().4h, v30.4h + sqrshl \d0\().4s, \d0\().4s, v31.4s + sqadd \d0\().4s, \d0\().4s, v29.4s + sqxtn \d0\().4h, \d0\().4s + sqxtun \d0\().8b, \d0\().8h +.endm + +function ff_hevc_put_hevc_epel_uni_w_v4_8_neon, export=1 + EPEL_UNI_W_V_HEADER + + ldr s4, [x2] + ldr s5, [x2, x3] + add x2, x2, x3, lsl #1 + ldr s6, [x2] +1: + ldr s7, [x2, x3] + subs w4, w4, #1 + add x2, x2, x3, lsl #1 + EPEL_UNI_W_V4_CALC v16, v4, v5, v6, v7 + str s16, [x0] + b.eq 2f + add x0, x0, x1 + ldr s4, [x2] + subs w4, w4, #1 + EPEL_UNI_W_V4_CALC v17, v5, v6, v7, v4 + str s17, [x0] + add x0, x0, x1 + b.eq 2f + ldr s5, [x2, x3] + subs w4, w4, #1 + add x2, x2, x3, lsl #1 + EPEL_UNI_W_V4_CALC v18, v6, v7, v4, v5 + str s18, [x0] + add x0, x0, x1 + b.eq 2f + ldr s6, [x2] + subs w4, w4, #1 + EPEL_UNI_W_V4_CALC v19, v7, v4, v5, v6 + str s19, [x0] + add x0, x0, x1 + b.hi 1b +2: + ret +endfunc + +.macro EPEL_UNI_W_V8_CALC d0, s0, s1, s2, s3, t0, t1 + movi \d0\().2d, #0 + umlsl \d0\().8h, \s0\().8b, v0.8b + umlal \d0\().8h, \s1\().8b, v1.8b + umlal \d0\().8h, \s2\().8b, v2.8b + umlsl \d0\().8h, \s3\().8b, v3.8b + smull \t0\().4s, \d0\().4h, v30.4h + smull2 \t1\().4s, \d0\().8h, v30.8h + sqrshl \t0\().4s, \t0\().4s, v31.4s + sqrshl \t1\().4s, \t1\().4s, v31.4s + sqadd \t0\().4s, \t0\().4s, v29.4s + sqadd \t1\().4s, \t1\().4s, v29.4s + sqxtn \d0\().4h, \t0\().4s + sqxtn2 \d0\().8h, \t1\().4s + sqxtun \d0\().8b, \d0\().8h +.endm + +function ff_hevc_put_hevc_epel_uni_w_v6_8_neon, export=1 + EPEL_UNI_W_V_HEADER + + sub x1, x1, #4 + ldr d4, [x2] + ldr d5, [x2, x3] + add x2, x2, x3, lsl #1 + ldr d6, [x2] +1: + ldr d7, [x2, x3] + subs w4, w4, #1 + add x2, x2, x3, lsl #1 + EPEL_UNI_W_V8_CALC v16, v4, v5, v6, v7, v20, v21 + str s16, [x0], #4 + st1 {v16.h}[2], [x0], x1 + b.eq 2f + ldr d4, [x2] + subs w4, w4, #1 + EPEL_UNI_W_V8_CALC v17, v5, v6, v7, v4, v20, v21 + str s17, [x0], #4 + st1 {v17.h}[2], [x0], x1 + b.eq 2f + ldr d5, [x2, x3] + subs w4, w4, #1 + add x2, x2, x3, lsl #1 + EPEL_UNI_W_V8_CALC v18, v6, v7, v4, v5, v20, v21 + str s18, [x0], #4 + st1 {v18.h}[2], [x0], x1 + b.eq 2f + ldr d6, [x2] + subs w4, w4, #1 + EPEL_UNI_W_V8_CALC v19, v7, v4, v5, v6, v20, v21 + str s19, [x0], #4 + st1 {v19.h}[2], [x0], x1 + b.hi 1b +2: + ret +endfunc + +function ff_hevc_put_hevc_epel_uni_w_v8_8_neon, export=1 + EPEL_UNI_W_V_HEADER + + ldr d4, [x2] + ldr d5, [x2, x3] + add x2, x2, x3, lsl #1 + ldr d6, [x2] +1: + ldr d7, [x2, x3] + subs w4, w4, #1 + add x2, x2, x3, lsl #1 + EPEL_UNI_W_V8_CALC v16, v4, v5, v6, v7, v20, v21 + str d16, [x0] + add x0, x0, x1 + b.eq 2f + ldr d4, [x2] + subs w4, w4, #1 + EPEL_UNI_W_V8_CALC v17, v5, v6, v7, v4, v20, v21 + str d17, [x0] + add x0, x0, x1 + b.eq 2f + ldr d5, [x2, x3] + subs w4, w4, #1 + add x2, x2, x3, lsl #1 + EPEL_UNI_W_V8_CALC v18, v6, v7, v4, v5, v20, v21 + str d18, [x0] + add x0, x0, x1 + b.eq 2f + ldr d6, [x2] + subs w4, w4, #1 + EPEL_UNI_W_V8_CALC v19, v7, v4, v5, v6, v20, v21 + str d19, [x0] + add x0, x0, x1 + b.hi 1b +2: + ret +endfunc + +.macro EPEL_UNI_W_V12_CALC d0, d1, s0, s1, s2, s3, t0, t1, t2, t3 + movi \d0\().2d, #0 + movi \d1\().2d, #0 + umlsl \d0\().8h, \s0\().8b, v0.8b + umlsl2 \d1\().8h, \s0\().16b, v0.16b + umlal \d0\().8h, \s1\().8b, v1.8b + umlal2 \d1\().8h, \s1\().16b, v1.16b + umlal \d0\().8h, \s2\().8b, v2.8b + umlal2 \d1\().8h, \s2\().16b, v2.16b + umlsl \d0\().8h, \s3\().8b, v3.8b + umlsl2 \d1\().8h, \s3\().16b, v3.16b + + smull \t0\().4s, \d0\().4h, v30.4h + smull2 \t1\().4s, \d0\().8h, v30.8h + smull \t2\().4s, \d1\().4h, v30.4h + + sqrshl \t0\().4s, \t0\().4s, v31.4s + sqrshl \t1\().4s, \t1\().4s, v31.4s + sqrshl \t2\().4s, \t2\().4s, v31.4s + sqadd \t0\().4s, \t0\().4s, v29.4s + sqadd \t1\().4s, \t1\().4s, v29.4s + sqadd \t2\().4s, \t2\().4s, v29.4s + + sqxtn \d0\().4h, \t0\().4s + sqxtn2 \d0\().8h, \t1\().4s + sqxtn \d1\().4h, \t2\().4s + sqxtun \d0\().8b, \d0\().8h + sqxtun2 \d0\().16b, \d1\().8h +.endm + +function ff_hevc_put_hevc_epel_uni_w_v12_8_neon, export=1 + EPEL_UNI_W_V_HEADER + + ldr q4, [x2] + ldr q5, [x2, x3] + add x2, x2, x3, lsl #1 + ldr q6, [x2] + sub x1, x1, #8 +1: + ldr q7, [x2, x3] + subs w4, w4, #1 + add x2, x2, x3, lsl #1 + EPEL_UNI_W_V12_CALC v16, v17, v4, v5, v6, v7, v24, v25, v26, v27 + str d16, [x0], #8 + st1 {v16.s}[2], [x0] + add x0, x0, x1 + b.eq 2f + ldr q4, [x2] + subs w4, w4, #1 + EPEL_UNI_W_V12_CALC v18, v19, v5, v6, v7, v4, v24, v25, v26, v27 + str d18, [x0], #8 + st1 {v18.s}[2], [x0] + add x0, x0, x1 + b.eq 2f + ldr q5, [x2, x3] + subs w4, w4, #1 + add x2, x2, x3, lsl #1 + EPEL_UNI_W_V12_CALC v20, v21, v6, v7, v4, v5, v24, v25, v26, v27 + str d20, [x0], #8 + st1 {v20.s}[2], [x0] + add x0, x0, x1 + b.eq 2f + ldr q6, [x2] + subs w4, w4, #1 + EPEL_UNI_W_V12_CALC v22, v23, v7, v4, v5, v6, v24, v25, v26, v27 + str d22, [x0], #8 + st1 {v22.s}[2], [x0] + add x0, x0, x1 + b.hi 1b +2: + ret +endfunc + +.macro EPEL_UNI_W_V16_CALC d0, d1, s0, s1, s2, s3, t0, t1, t2, t3 + movi \d0\().2d, #0 + movi \d1\().2d, #0 + umlsl \d0\().8h, \s0\().8b, v0.8b + umlsl2 \d1\().8h, \s0\().16b, v0.16b + umlal \d0\().8h, \s1\().8b, v1.8b + umlal2 \d1\().8h, \s1\().16b, v1.16b + umlal \d0\().8h, \s2\().8b, v2.8b + umlal2 \d1\().8h, \s2\().16b, v2.16b + umlsl \d0\().8h, \s3\().8b, v3.8b + umlsl2 \d1\().8h, \s3\().16b, v3.16b + + smull \t0\().4s, \d0\().4h, v30.4h + smull2 \t1\().4s, \d0\().8h, v30.8h + smull \t2\().4s, \d1\().4h, v30.4h + smull2 \t3\().4s, \d1\().8h, v30.8h + + sqrshl \t0\().4s, \t0\().4s, v31.4s + sqrshl \t1\().4s, \t1\().4s, v31.4s + sqrshl \t2\().4s, \t2\().4s, v31.4s + sqrshl \t3\().4s, \t3\().4s, v31.4s + sqadd \t0\().4s, \t0\().4s, v29.4s + sqadd \t1\().4s, \t1\().4s, v29.4s + sqadd \t2\().4s, \t2\().4s, v29.4s + sqadd \t3\().4s, \t3\().4s, v29.4s + + sqxtn \d0\().4h, \t0\().4s + sqxtn2 \d0\().8h, \t1\().4s + sqxtn \d1\().4h, \t2\().4s + sqxtn2 \d1\().8h, \t3\().4s + sqxtun \d0\().8b, \d0\().8h + sqxtun2 \d0\().16b, \d1\().8h +.endm + + +function ff_hevc_put_hevc_epel_uni_w_v16_8_neon, export=1 + EPEL_UNI_W_V_HEADER + + ldr q4, [x2] + ldr q5, [x2, x3] + add x2, x2, x3, lsl #1 + ldr q6, [x2] +1: + ldr q7, [x2, x3] + subs w4, w4, #1 + add x2, x2, x3, lsl #1 + EPEL_UNI_W_V16_CALC v16, v17, v4, v5, v6, v7, v24, v25, v26, v27 + str q16, [x0] + add x0, x0, x1 + b.eq 2f + ldr q4, [x2] + subs w4, w4, #1 + EPEL_UNI_W_V16_CALC v18, v19, v5, v6, v7, v4, v24, v25, v26, v27 + str q18, [x0] + add x0, x0, x1 + b.eq 2f + ldr q5, [x2, x3] + subs w4, w4, #1 + add x2, x2, x3, lsl #1 + EPEL_UNI_W_V16_CALC v20, v21, v6, v7, v4, v5, v24, v25, v26, v27 + str q20, [x0] + add x0, x0, x1 + b.eq 2f + ldr q6, [x2] + subs w4, w4, #1 + EPEL_UNI_W_V16_CALC v22, v23, v7, v4, v5, v6, v24, v25, v26, v27 + str q22, [x0] + add x0, x0, x1 + b.hi 1b +2: + ret +endfunc + + + +function ff_hevc_put_hevc_epel_uni_w_v24_8_neon, export=1 + EPEL_UNI_W_V_HEADER + + ldp q16, q17, [x2] + add x2, x2, x3 + ldp q18, q19, [x2] + add x2, x2, x3 + ldp q20, q21, [x2] + add x2, x2, x3 +1: + ldp q22, q23, [x2] + subs w4, w4, #1 + add x2, x2, x3 + EPEL_UNI_W_V16_CALC v4, v5, v16, v18, v20, v22, v24, v25, v26, v27 + EPEL_UNI_W_V8_CALC v6, v17, v19, v21, v23, v24, v25 + str q4, [x0] + str d6, [x0, #16] + add x0, x0, x1 + b.eq 2f + ldp q16, q17, [x2] + subs w4, w4, #1 + add x2, x2, x3 + EPEL_UNI_W_V16_CALC v4, v5, v18, v20, v22, v16, v24, v25, v26, v27 + EPEL_UNI_W_V8_CALC v6, v19, v21, v23, v17, v24, v25 + str q4, [x0] + str d6, [x0, #16] + add x0, x0, x1 + b.eq 2f + ldp q18, q19, [x2] + subs w4, w4, #1 + add x2, x2, x3 + EPEL_UNI_W_V16_CALC v4, v5, v20, v22, v16, v18, v24, v25, v26, v27 + EPEL_UNI_W_V8_CALC v6, v21, v23, v17, v19, v24, v25 + str q4, [x0] + str d6, [x0, #16] + add x0, x0, x1 + b.eq 2f + ldp q20, q21, [x2] + subs w4, w4, #1 + add x2, x2, x3 + EPEL_UNI_W_V16_CALC v4, v5, v22, v16, v18, v20, v24, v25, v26, v27 + EPEL_UNI_W_V8_CALC v6, v23, v17, v19, v21, v24, v25 + str q4, [x0] + str d6, [x0, #16] + add x0, x0, x1 + b.hi 1b +2: + ret +endfunc + +function ff_hevc_put_hevc_epel_uni_w_v32_8_neon, export=1 + EPEL_UNI_W_V_HEADER + + ldp q16, q17, [x2] + add x2, x2, x3 + ldp q18, q19, [x2] + add x2, x2, x3 + ldp q20, q21, [x2] + add x2, x2, x3 +1: + ldp q22, q23, [x2] + subs w4, w4, #1 + add x2, x2, x3 + EPEL_UNI_W_V16_CALC v4, v5, v16, v18, v20, v22, v24, v25, v26, v27 + EPEL_UNI_W_V16_CALC v6, v7, v17, v19, v21, v23, v24, v25, v26, v27 + str q4, [x0] + str q6, [x0, #16] + add x0, x0, x1 + b.eq 2f + ldp q16, q17, [x2] + subs w4, w4, #1 + add x2, x2, x3 + EPEL_UNI_W_V16_CALC v4, v5, v18, v20, v22, v16, v24, v25, v26, v27 + EPEL_UNI_W_V16_CALC v6, v7, v19, v21, v23, v17, v24, v25, v26, v27 + str q4, [x0] + str q6, [x0, #16] + add x0, x0, x1 + b.eq 2f + ldp q18, q19, [x2] + subs w4, w4, #1 + add x2, x2, x3 + EPEL_UNI_W_V16_CALC v4, v5, v20, v22, v16, v18, v24, v25, v26, v27 + EPEL_UNI_W_V16_CALC v6, v7, v21, v23, v17, v19, v24, v25, v26, v27 + str q4, [x0] + str q6, [x0, #16] + add x0, x0, x1 + b.eq 2f + ldp q20, q21, [x2] + subs w4, w4, #1 + add x2, x2, x3 + EPEL_UNI_W_V16_CALC v4, v5, v22, v16, v18, v20, v24, v25, v26, v27 + EPEL_UNI_W_V16_CALC v6, v7, v23, v17, v19, v21, v24, v25, v26, v27 + str q4, [x0] + str q6, [x0, #16] + add x0, x0, x1 + b.hi 1b +2: + ret +endfunc + +function ff_hevc_put_hevc_epel_uni_w_v48_8_neon, export=1 + EPEL_UNI_W_V_HEADER + stp d8, d9, [sp, #-32]! + stp d10, d11, [sp, #16] + + ld1 {v16.16b, v17.16b, v18.16b}, [x2], x3 + ld1 {v19.16b, v20.16b, v21.16b}, [x2], x3 + ld1 {v22.16b, v23.16b, v24.16b}, [x2], x3 +1: + ld1 {v25.16b, v26.16b, v27.16b}, [x2], x3 + subs w4, w4, #1 + EPEL_UNI_W_V16_CALC v4, v6, v16, v19, v22, v25, v8, v9, v10, v11 + EPEL_UNI_W_V16_CALC v5, v7, v17, v20, v23, v26, v8, v9, v10, v11 + EPEL_UNI_W_V16_CALC v6, v7, v18, v21, v24, v27, v8, v9, v10, v11 + st1 {v4.16b, v5.16b, v6.16b}, [x0], x1 + b.eq 2f + ld1 {v16.16b, v17.16b, v18.16b}, [x2], x3 + subs w4, w4, #1 + EPEL_UNI_W_V16_CALC v4, v6, v19, v22, v25, v16, v8, v9, v10, v11 + EPEL_UNI_W_V16_CALC v5, v7, v20, v23, v26, v17, v8, v9, v10, v11 + EPEL_UNI_W_V16_CALC v6, v7, v21, v24, v27, v18, v8, v9, v10, v11 + st1 {v4.16b, v5.16b, v6.16b}, [x0], x1 + b.eq 2f + ld1 {v19.16b, v20.16b, v21.16b}, [x2], x3 + subs w4, w4, #1 + EPEL_UNI_W_V16_CALC v4, v6, v22, v25, v16, v19, v8, v9, v10, v11 + EPEL_UNI_W_V16_CALC v5, v7, v23, v26, v17, v20, v8, v9, v10, v11 + EPEL_UNI_W_V16_CALC v6, v7, v24, v27, v18, v21, v8, v9, v10, v11 + st1 {v4.16b, v5.16b, v6.16b}, [x0], x1 + b.eq 2f + ld1 {v22.16b, v23.16b, v24.16b}, [x2], x3 + subs w4, w4, #1 + EPEL_UNI_W_V16_CALC v4, v6, v25, v16, v19, v22, v8, v9, v10, v11 + EPEL_UNI_W_V16_CALC v5, v7, v26, v17, v20, v23, v8, v9, v10, v11 + EPEL_UNI_W_V16_CALC v6, v7, v27, v18, v21, v24, v8, v9, v10, v11 + st1 {v4.16b, v5.16b, v6.16b}, [x0], x1 + b.hi 1b +2: + ldp d10, d11, [sp, #16] + ldp d8, d9, [sp], #32 + ret +endfunc + +function ff_hevc_put_hevc_epel_uni_w_v64_8_neon, export=1 + EPEL_UNI_W_V_HEADER + stp d8, d9, [sp, #-64]! + stp d10, d11, [sp, #16] + stp d12, d13, [sp, #32] + stp d14, d15, [sp, #48] + + ld1 {v16.16b, v17.16b, v18.16b, v19.16b}, [x2], x3 + ld1 {v20.16b, v21.16b, v22.16b, v23.16b}, [x2], x3 + ld1 {v24.16b, v25.16b, v26.16b, v27.16b}, [x2], x3 +1: + ld1 {v12.16b, v13.16b, v14.16b, v15.16b}, [x2], x3 + subs w4, w4, #1 + EPEL_UNI_W_V16_CALC v4, v6, v16, v20, v24, v12, v8, v9, v10, v11 + EPEL_UNI_W_V16_CALC v5, v7, v17, v21, v25, v13, v8, v9, v10, v11 + EPEL_UNI_W_V16_CALC v6, v7, v18, v22, v26, v14, v8, v9, v10, v11 + EPEL_UNI_W_V16_CALC v7,v28, v19, v23, v27, v15, v8, v9, v10, v11 + st1 {v4.16b, v5.16b, v6.16b, v7.16b}, [x0], x1 + b.eq 2f + ld1 {v16.16b, v17.16b, v18.16b, v19.16b}, [x2], x3 + subs w4, w4, #1 + EPEL_UNI_W_V16_CALC v4, v6, v20, v24, v12, v16, v8, v9, v10, v11 + EPEL_UNI_W_V16_CALC v5, v7, v21, v25, v13, v17, v8, v9, v10, v11 + EPEL_UNI_W_V16_CALC v6, v7, v22, v26, v14, v18, v8, v9, v10, v11 + EPEL_UNI_W_V16_CALC v7,v28, v23, v27, v15, v19, v8, v9, v10, v11 + st1 {v4.16b, v5.16b, v6.16b, v7.16b}, [x0], x1 + b.eq 2f + ld1 {v20.16b, v21.16b, v22.16b, v23.16b}, [x2], x3 + subs w4, w4, #1 + EPEL_UNI_W_V16_CALC v4, v6, v24, v12, v16, v20, v8, v9, v10, v11 + EPEL_UNI_W_V16_CALC v5, v7, v25, v13, v17, v21, v8, v9, v10, v11 + EPEL_UNI_W_V16_CALC v6, v7, v26, v14, v18, v22, v8, v9, v10, v11 + EPEL_UNI_W_V16_CALC v7,v28, v27, v15, v19, v23, v8, v9, v10, v11 + st1 {v4.16b, v5.16b, v6.16b, v7.16b}, [x0], x1 + b.eq 2f + ld1 {v24.16b, v25.16b, v26.16b, v27.16b}, [x2], x3 + subs w4, w4, #1 + EPEL_UNI_W_V16_CALC v4, v6, v12, v16, v20, v24, v8, v9, v10, v11 + EPEL_UNI_W_V16_CALC v5, v7, v13, v17, v21, v25, v8, v9, v10, v11 + EPEL_UNI_W_V16_CALC v6, v7, v14, v18, v22, v26, v8, v9, v10, v11 + EPEL_UNI_W_V16_CALC v7,v28, v15, v19, v23, v27, v8, v9, v10, v11 + st1 {v4.16b, v5.16b, v6.16b, v7.16b}, [x0], x1 + b.hi 1b +2: + ldp d10, d11, [sp, #16] + ldp d12, d13, [sp, #32] + ldp d14, d15, [sp, #48] + ldp d8, d9, [sp], #64 + ret +endfunc diff --git a/libavcodec/aarch64/hevcdsp_init_aarch64.c b/libavcodec/aarch64/hevcdsp_init_aarch64.c index 8af0a2b4b92..4a260e1d9af 100644 --- a/libavcodec/aarch64/hevcdsp_init_aarch64.c +++ b/libavcodec/aarch64/hevcdsp_init_aarch64.c @@ -161,6 +161,11 @@ NEON8_FNPROTO(pel_uni_w_pixels, (uint8_t *_dst, ptrdiff_t _dststride, int height, int denom, int wx, int ox, intptr_t mx, intptr_t my, int width),); +NEON8_FNPROTO(epel_uni_w_v, (uint8_t *_dst, ptrdiff_t _dststride, + const uint8_t *_src, ptrdiff_t _srcstride, + int height, int denom, int wx, int ox, + intptr_t mx, intptr_t my, int width),); + NEON8_FNPROTO_PARTIAL_4(qpel_uni_w_v, (uint8_t *_dst, ptrdiff_t _dststride, const uint8_t *_src, ptrdiff_t _srcstride, int height, int denom, int wx, int ox, @@ -274,6 +279,7 @@ av_cold void ff_hevc_dsp_init_aarch64(HEVCDSPContext *c, const int bit_depth) NEON8_FNASSIGN(c->put_hevc_qpel_uni, 0, 0, pel_uni_pixels,); NEON8_FNASSIGN(c->put_hevc_epel_uni_w, 0, 0, pel_uni_w_pixels,); NEON8_FNASSIGN(c->put_hevc_qpel_uni_w, 0, 0, pel_uni_w_pixels,); + NEON8_FNASSIGN(c->put_hevc_epel_uni_w, 1, 0, epel_uni_w_v,); NEON8_FNASSIGN_PARTIAL_4(c->put_hevc_qpel_uni_w, 1, 0, qpel_uni_w_v,); if (have_i8mm(cpu_flags)) { From d48c89701c0cdad1074a797e8bfc214d8b49123b Mon Sep 17 00:00:00 2001 From: Logan Lyu Date: Sun, 28 May 2023 10:30:28 +0800 Subject: [PATCH 1842/2172] lavc/aarch64: new optimization for 8-bit hevc_epel_h MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit put_hevc_epel_h4_8_c: 67.1 put_hevc_epel_h4_8_i8mm: 21.1 put_hevc_epel_h6_8_c: 147.1 put_hevc_epel_h6_8_i8mm: 45.1 put_hevc_epel_h8_8_c: 237.4 put_hevc_epel_h8_8_i8mm: 72.1 put_hevc_epel_h12_8_c: 527.4 put_hevc_epel_h12_8_i8mm: 115.4 put_hevc_epel_h16_8_c: 943.6 put_hevc_epel_h16_8_i8mm: 153.9 put_hevc_epel_h24_8_c: 2105.4 put_hevc_epel_h24_8_i8mm: 384.4 put_hevc_epel_h32_8_c: 3631.4 put_hevc_epel_h32_8_i8mm: 519.9 put_hevc_epel_h48_8_c: 8082.1 put_hevc_epel_h48_8_i8mm: 1110.4 put_hevc_epel_h64_8_c: 14400.6 put_hevc_epel_h64_8_i8mm: 2057.1 put_hevc_qpel_h4_8_c: 124.9 put_hevc_qpel_h4_8_neon: 43.1 put_hevc_qpel_h4_8_i8mm: 33.1 put_hevc_qpel_h6_8_c: 269.4 put_hevc_qpel_h6_8_neon: 90.6 put_hevc_qpel_h6_8_i8mm: 61.4 put_hevc_qpel_h8_8_c: 477.6 put_hevc_qpel_h8_8_neon: 82.1 put_hevc_qpel_h8_8_i8mm: 99.9 put_hevc_qpel_h12_8_c: 1062.4 put_hevc_qpel_h12_8_neon: 226.9 put_hevc_qpel_h12_8_i8mm: 170.9 put_hevc_qpel_h16_8_c: 1880.6 put_hevc_qpel_h16_8_neon: 302.9 put_hevc_qpel_h16_8_i8mm: 251.4 put_hevc_qpel_h24_8_c: 4221.9 put_hevc_qpel_h24_8_neon: 893.9 put_hevc_qpel_h24_8_i8mm: 626.1 put_hevc_qpel_h32_8_c: 7437.6 put_hevc_qpel_h32_8_neon: 1189.9 put_hevc_qpel_h32_8_i8mm: 959.1 put_hevc_qpel_h48_8_c: 16838.4 put_hevc_qpel_h48_8_neon: 2727.9 put_hevc_qpel_h48_8_i8mm: 2163.9 put_hevc_qpel_h64_8_c: 29982.1 put_hevc_qpel_h64_8_neon: 4777.6 Signed-off-by: Martin Storsjö --- libavcodec/aarch64/hevcdsp_epel_neon.S | 343 ++++++++++++++++++++++ libavcodec/aarch64/hevcdsp_init_aarch64.c | 5 + 2 files changed, 348 insertions(+) diff --git a/libavcodec/aarch64/hevcdsp_epel_neon.S b/libavcodec/aarch64/hevcdsp_epel_neon.S index a99fac1c50f..c695c4d8ab8 100644 --- a/libavcodec/aarch64/hevcdsp_epel_neon.S +++ b/libavcodec/aarch64/hevcdsp_epel_neon.S @@ -33,6 +33,349 @@ const epel_filters, align=4 endconst #if HAVE_I8MM + +.macro EPEL_H_HEADER + movrel x5, epel_filters + add x5, x5, x4, lsl #2 + ld1r {v30.4s}, [x5] + sub x1, x1, #1 + mov x10, #(MAX_PB_SIZE * 2) +.endm + +function ff_hevc_put_hevc_epel_h4_8_neon_i8mm, export=1 + EPEL_H_HEADER +1: ld1 {v4.8b}, [x1], x2 + subs w3, w3, #1 // height + ext v5.8b, v4.8b, v4.8b, #1 + ext v6.8b, v4.8b, v4.8b, #2 + ext v7.8b, v4.8b, v4.8b, #3 + trn1 v4.2s, v4.2s, v5.2s + trn1 v6.2s, v6.2s, v7.2s + trn1 v4.2d, v4.2d, v6.2d + movi v16.2d, #0 + usdot v16.4s, v4.16b, v30.16b + xtn v16.4h, v16.4s + st1 {v16.4h}, [x0], x10 + b.ne 1b + ret +endfunc + + +function ff_hevc_put_hevc_epel_h6_8_neon_i8mm, export=1 + EPEL_H_HEADER +1: ld1 {v4.16b}, [x1], x2 + subs w3, w3, #1 // height + ext v5.16b, v4.16b, v4.16b, #1 + ext v6.8b, v4.8b, v4.8b, #2 + ext v7.8b, v4.8b, v4.8b, #3 + trn1 v16.2s, v4.2s, v5.2s + trn2 v17.2s, v4.2s, v5.2s + trn1 v6.2s, v6.2s, v7.2s + trn1 v16.2d, v16.2d, v6.2d + movi v18.2d, #0 + movi v19.2d, #0 + usdot v18.4s, v16.16b, v30.16b + usdot v19.2s, v17.8b, v30.8b + xtn v18.4h, v18.4s + xtn v19.4h, v19.4s + str d18, [x0] + str s19, [x0, #8] + add x0, x0, x10 + b.ne 1b + ret +endfunc + +function ff_hevc_put_hevc_epel_h8_8_neon_i8mm, export=1 + EPEL_H_HEADER +1: ld1 {v4.16b}, [x1], x2 + subs w3, w3, #1 // height + ext v5.16b, v4.16b, v4.16b, #1 + ext v6.16b, v4.16b, v4.16b, #2 + ext v7.16b, v4.16b, v4.16b, #3 + zip1 v20.4s, v4.4s, v6.4s + zip1 v21.4s, v5.4s, v7.4s + movi v16.2d, #0 + movi v17.2d, #0 + usdot v16.4s, v20.16b, v30.16b + usdot v17.4s, v21.16b, v30.16b + xtn v16.4h, v16.4s + xtn v17.4h, v17.4s + st2 {v16.4h, v17.4h}, [x0], x10 + b.ne 1b + ret +endfunc + +function ff_hevc_put_hevc_epel_h12_8_neon_i8mm, export=1 + EPEL_H_HEADER +1: ld1 {v4.16b}, [x1], x2 + subs w3, w3, #1 // height + ext v5.16b, v4.16b, v4.16b, #1 + ext v6.16b, v4.16b, v4.16b, #2 + ext v7.16b, v4.16b, v4.16b, #3 + trn1 v20.2d, v4.2d, v6.2d + trn2 v22.2d, v4.2d, v6.2d + trn1 v21.2d, v5.2d, v7.2d + trn2 v23.2d, v5.2d, v7.2d + trn1 v4.4s, v20.4s, v21.4s + trn2 v5.4s, v20.4s, v21.4s + trn1 v6.4s, v22.4s, v23.4s + movi v16.2d, #0 + movi v17.2d, #0 + movi v18.2d, #0 + usdot v16.4s, v4.16b, v30.16b + usdot v17.4s, v5.16b, v30.16b + usdot v18.4s, v6.16b, v30.16b + xtn v16.4h, v16.4s + xtn2 v16.8h, v17.4s + xtn v18.4h, v18.4s + str q16, [x0] + str d18, [x0, #16] + add x0, x0, x10 + b.ne 1b + ret +endfunc + +function ff_hevc_put_hevc_epel_h16_8_neon_i8mm, export=1 + EPEL_H_HEADER +1: ld1 {v0.16b, v1.16b}, [x1], x2 + subs w3, w3, #1 // height + ext v5.16b, v0.16b, v1.16b, #1 + ext v6.16b, v0.16b, v1.16b, #2 + ext v7.16b, v0.16b, v1.16b, #3 + zip1 v20.4s, v0.4s, v6.4s + zip2 v22.4s, v0.4s, v6.4s + zip1 v21.4s, v5.4s, v7.4s + zip2 v23.4s, v5.4s, v7.4s + movi v16.2d, #0 + movi v17.2d, #0 + movi v18.2d, #0 + movi v19.2d, #0 + usdot v16.4s, v20.16b, v30.16b + usdot v17.4s, v21.16b, v30.16b + usdot v18.4s, v22.16b, v30.16b + usdot v19.4s, v23.16b, v30.16b + xtn v16.4h, v16.4s + xtn2 v16.8h, v18.4s + xtn v17.4h, v17.4s + xtn2 v17.8h, v19.4s + st2 {v16.8h, v17.8h}, [x0], x10 + b.ne 1b + ret +endfunc + +function ff_hevc_put_hevc_epel_h24_8_neon_i8mm, export=1 + EPEL_H_HEADER +1: ld1 {v0.16b, v1.16b}, [x1], x2 + subs w3, w3, #1 // height + ext v5.16b, v0.16b, v1.16b, #1 + ext v6.16b, v0.16b, v1.16b, #2 + ext v7.16b, v0.16b, v1.16b, #3 + ext v26.16b, v1.16b, v1.16b, #1 + ext v27.16b, v1.16b, v1.16b, #2 + ext v28.16b, v1.16b, v1.16b, #3 + movi v16.2d, #0 + movi v17.2d, #0 + movi v18.2d, #0 + movi v19.2d, #0 + movi v20.2d, #0 + movi v21.2d, #0 + movi v22.2d, #0 + movi v23.2d, #0 + usdot v16.4s, v0.16b, v30.16b + usdot v17.4s, v5.16b, v30.16b + usdot v18.4s, v6.16b, v30.16b + usdot v19.4s, v7.16b, v30.16b + usdot v20.4s, v1.16b, v30.16b + usdot v21.4s, v26.16b, v30.16b + usdot v22.4s, v27.16b, v30.16b + usdot v23.4s, v28.16b, v30.16b + xtn v16.4h, v16.4s + xtn2 v16.8h, v20.4s + xtn v17.4h, v17.4s + xtn2 v17.8h, v21.4s + xtn v18.4h, v18.4s + xtn2 v18.8h, v22.4s + xtn v19.4h, v19.4s + xtn2 v19.8h, v23.4s + zip1 v20.8h, v16.8h, v18.8h + zip1 v21.8h, v17.8h, v19.8h + zip2 v22.8h, v16.8h, v18.8h + zip2 v23.8h, v17.8h, v19.8h + zip1 v22.8h, v22.8h, v23.8h + add x7, x0, #32 + st2 {v20.8h, v21.8h}, [x0], x10 + st1 {v22.8h}, [x7] + b.ne 1b + ret +endfunc + +function ff_hevc_put_hevc_epel_h32_8_neon_i8mm, export=1 + EPEL_H_HEADER +1: ld1 {v0.16b, v1.16b, v2.16b}, [x1], x2 + subs w3, w3, #1 // height + ext v5.16b, v0.16b, v1.16b, #1 + ext v6.16b, v0.16b, v1.16b, #2 + ext v7.16b, v0.16b, v1.16b, #3 + ext v26.16b, v1.16b, v2.16b, #1 + ext v27.16b, v1.16b, v2.16b, #2 + ext v28.16b, v1.16b, v2.16b, #3 + movi v16.2d, #0 + movi v17.2d, #0 + movi v18.2d, #0 + movi v19.2d, #0 + movi v20.2d, #0 + movi v21.2d, #0 + movi v22.2d, #0 + movi v23.2d, #0 + usdot v16.4s, v0.16b, v30.16b + usdot v17.4s, v5.16b, v30.16b + usdot v18.4s, v6.16b, v30.16b + usdot v19.4s, v7.16b, v30.16b + usdot v20.4s, v1.16b, v30.16b + usdot v21.4s, v26.16b, v30.16b + usdot v22.4s, v27.16b, v30.16b + usdot v23.4s, v28.16b, v30.16b + xtn v16.4h, v16.4s + xtn2 v16.8h, v20.4s + xtn v17.4h, v17.4s + xtn2 v17.8h, v21.4s + xtn v18.4h, v18.4s + xtn2 v18.8h, v22.4s + xtn v19.4h, v19.4s + xtn2 v19.8h, v23.4s + st4 {v16.8h, v17.8h, v18.8h, v19.8h}, [x0], x10 + b.ne 1b + ret +endfunc + +function ff_hevc_put_hevc_epel_h48_8_neon_i8mm, export=1 + EPEL_H_HEADER +1: ld1 {v0.16b, v1.16b, v2.16b, v3.16b}, [x1], x2 + subs w3, w3, #1 // height + ext v4.16b, v0.16b, v1.16b, #1 + ext v5.16b, v0.16b, v1.16b, #2 + ext v6.16b, v0.16b, v1.16b, #3 + ext v16.16b, v1.16b, v2.16b, #1 + ext v17.16b, v1.16b, v2.16b, #2 + ext v18.16b, v1.16b, v2.16b, #3 + movi v20.2d, #0 + movi v21.2d, #0 + movi v22.2d, #0 + movi v23.2d, #0 + usdot v20.4s, v0.16b, v30.16b + usdot v21.4s, v4.16b, v30.16b + usdot v22.4s, v5.16b, v30.16b + usdot v23.4s, v6.16b, v30.16b + movi v24.2d, #0 + movi v25.2d, #0 + movi v26.2d, #0 + movi v27.2d, #0 + usdot v24.4s, v1.16b, v30.16b + usdot v25.4s, v16.16b, v30.16b + usdot v26.4s, v17.16b, v30.16b + usdot v27.4s, v18.16b, v30.16b + xtn v20.4h, v20.4s + xtn2 v20.8h, v24.4s + xtn v21.4h, v21.4s + xtn2 v21.8h, v25.4s + xtn v22.4h, v22.4s + xtn2 v22.8h, v26.4s + xtn v23.4h, v23.4s + xtn2 v23.8h, v27.4s + st4 {v20.8h, v21.8h, v22.8h, v23.8h}, [x0], x10 + ext v4.16b, v2.16b, v3.16b, #1 + ext v5.16b, v2.16b, v3.16b, #2 + ext v6.16b, v2.16b, v3.16b, #3 + movi v20.2d, #0 + movi v21.2d, #0 + movi v22.2d, #0 + movi v23.2d, #0 + usdot v20.4s, v2.16b, v30.16b + usdot v21.4s, v4.16b, v30.16b + usdot v22.4s, v5.16b, v30.16b + usdot v23.4s, v6.16b, v30.16b + xtn v20.4h, v20.4s + xtn2 v20.8h, v22.4s + xtn v21.4h, v21.4s + xtn2 v21.8h, v23.4s + add x7, x0, #64 + st2 {v20.8h, v21.8h}, [x7] + b.ne 1b + ret +endfunc + +function ff_hevc_put_hevc_epel_h64_8_neon_i8mm, export=1 + EPEL_H_HEADER + sub x2, x2, #64 +1: ld1 {v0.16b, v1.16b, v2.16b, v3.16b}, [x1], #64 + subs w3, w3, #1 // height + ext v4.16b, v0.16b, v1.16b, #1 + ext v5.16b, v0.16b, v1.16b, #2 + ext v6.16b, v0.16b, v1.16b, #3 + ext v16.16b, v1.16b, v2.16b, #1 + ext v17.16b, v1.16b, v2.16b, #2 + ext v18.16b, v1.16b, v2.16b, #3 + movi v20.2d, #0 + movi v21.2d, #0 + movi v22.2d, #0 + movi v23.2d, #0 + usdot v20.4s, v0.16b, v30.16b + usdot v21.4s, v4.16b, v30.16b + usdot v22.4s, v5.16b, v30.16b + usdot v23.4s, v6.16b, v30.16b + movi v24.2d, #0 + movi v25.2d, #0 + movi v26.2d, #0 + movi v27.2d, #0 + usdot v24.4s, v1.16b, v30.16b + usdot v25.4s, v16.16b, v30.16b + usdot v26.4s, v17.16b, v30.16b + usdot v27.4s, v18.16b, v30.16b + xtn v20.4h, v20.4s + xtn2 v20.8h, v24.4s + xtn v21.4h, v21.4s + xtn2 v21.8h, v25.4s + xtn v22.4h, v22.4s + xtn2 v22.8h, v26.4s + xtn v23.4h, v23.4s + xtn2 v23.8h, v27.4s + st4 {v20.8h, v21.8h, v22.8h, v23.8h}, [x0], #64 + ld1 {v7.8b}, [x1], x2 + ext v4.16b, v2.16b, v3.16b, #1 + ext v5.16b, v2.16b, v3.16b, #2 + ext v6.16b, v2.16b, v3.16b, #3 + ext v16.16b, v3.16b, v7.16b, #1 + ext v17.16b, v3.16b, v7.16b, #2 + ext v18.16b, v3.16b, v7.16b, #3 + movi v20.2d, #0 + movi v21.2d, #0 + movi v22.2d, #0 + movi v23.2d, #0 + usdot v20.4s, v2.16b, v30.16b + usdot v21.4s, v4.16b, v30.16b + usdot v22.4s, v5.16b, v30.16b + usdot v23.4s, v6.16b, v30.16b + movi v24.2d, #0 + movi v25.2d, #0 + movi v26.2d, #0 + movi v27.2d, #0 + usdot v24.4s, v3.16b, v30.16b + usdot v25.4s, v16.16b, v30.16b + usdot v26.4s, v17.16b, v30.16b + usdot v27.4s, v18.16b, v30.16b + xtn v20.4h, v20.4s + xtn2 v20.8h, v24.4s + xtn v21.4h, v21.4s + xtn2 v21.8h, v25.4s + xtn v22.4h, v22.4s + xtn2 v22.8h, v26.4s + xtn v23.4h, v23.4s + xtn2 v23.8h, v27.4s + st4 {v20.8h, v21.8h, v22.8h, v23.8h}, [x0], #64 + b.ne 1b + ret +endfunc + .macro EPEL_UNI_W_H_HEADER ldr x12, [sp] sub x2, x2, #1 diff --git a/libavcodec/aarch64/hevcdsp_init_aarch64.c b/libavcodec/aarch64/hevcdsp_init_aarch64.c index 4a260e1d9af..b448d755b92 100644 --- a/libavcodec/aarch64/hevcdsp_init_aarch64.c +++ b/libavcodec/aarch64/hevcdsp_init_aarch64.c @@ -171,6 +171,10 @@ NEON8_FNPROTO_PARTIAL_4(qpel_uni_w_v, (uint8_t *_dst, ptrdiff_t _dststride, int height, int denom, int wx, int ox, intptr_t mx, intptr_t my, int width),); +NEON8_FNPROTO(epel_h, (int16_t *dst, + const uint8_t *_src, ptrdiff_t _srcstride, + int height, intptr_t mx, intptr_t my, int width), _i8mm); + NEON8_FNPROTO(epel_uni_w_h, (uint8_t *_dst, ptrdiff_t _dststride, const uint8_t *_src, ptrdiff_t _srcstride, int height, int denom, int wx, int ox, @@ -283,6 +287,7 @@ av_cold void ff_hevc_dsp_init_aarch64(HEVCDSPContext *c, const int bit_depth) NEON8_FNASSIGN_PARTIAL_4(c->put_hevc_qpel_uni_w, 1, 0, qpel_uni_w_v,); if (have_i8mm(cpu_flags)) { + NEON8_FNASSIGN(c->put_hevc_epel, 0, 1, epel_h, _i8mm); NEON8_FNASSIGN(c->put_hevc_epel_uni_w, 0, 1, epel_uni_w_h ,_i8mm); NEON8_FNASSIGN(c->put_hevc_qpel, 0, 1, qpel_h, _i8mm); NEON8_FNASSIGN(c->put_hevc_qpel_uni_w, 0, 1, qpel_uni_w_h, _i8mm); From 9557bf26b351fd4c8d213b9bb9895f9cd05ea926 Mon Sep 17 00:00:00 2001 From: Logan Lyu Date: Sun, 28 May 2023 10:35:43 +0800 Subject: [PATCH 1843/2172] lavc/aarch64: new optimization for 8-bit hevc_epel_uni_w_hv MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit put_hevc_epel_uni_w_hv4_8_c: 254.6 put_hevc_epel_uni_w_hv4_8_i8mm: 102.9 put_hevc_epel_uni_w_hv6_8_c: 411.6 put_hevc_epel_uni_w_hv6_8_i8mm: 221.6 put_hevc_epel_uni_w_hv8_8_c: 669.4 put_hevc_epel_uni_w_hv8_8_i8mm: 214.9 put_hevc_epel_uni_w_hv12_8_c: 1412.6 put_hevc_epel_uni_w_hv12_8_i8mm: 481.4 put_hevc_epel_uni_w_hv16_8_c: 2425.4 put_hevc_epel_uni_w_hv16_8_i8mm: 647.4 put_hevc_epel_uni_w_hv24_8_c: 5384.1 put_hevc_epel_uni_w_hv24_8_i8mm: 1450.6 put_hevc_epel_uni_w_hv32_8_c: 9470.9 put_hevc_epel_uni_w_hv32_8_i8mm: 2497.1 put_hevc_epel_uni_w_hv48_8_c: 20930.1 put_hevc_epel_uni_w_hv48_8_i8mm: 5635.9 put_hevc_epel_uni_w_hv64_8_c: 36682.9 put_hevc_epel_uni_w_hv64_8_i8mm: 9712.6 Signed-off-by: Martin Storsjö --- libavcodec/aarch64/hevcdsp_epel_neon.S | 668 ++++++++++++++++++++++ libavcodec/aarch64/hevcdsp_init_aarch64.c | 6 + 2 files changed, 674 insertions(+) diff --git a/libavcodec/aarch64/hevcdsp_epel_neon.S b/libavcodec/aarch64/hevcdsp_epel_neon.S index c695c4d8ab8..a8d694639bd 100644 --- a/libavcodec/aarch64/hevcdsp_epel_neon.S +++ b/libavcodec/aarch64/hevcdsp_epel_neon.S @@ -717,6 +717,674 @@ function ff_hevc_put_hevc_epel_uni_w_h64_8_neon_i8mm, export=1 ret endfunc +.macro epel_uni_w_hv_start + mov x15, x5 //denom + mov x16, x6 //wx + mov x17, x7 //ox + add w15, w15, #6 //shift = denom+6 + + + ldp x5, x6, [sp] + ldr x7, [sp, #16] + + stp d14, d15, [sp, #-64]! + stp d8, d9, [sp, #16] + stp d10, d11, [sp, #32] + stp d12, d13, [sp, #48] + + dup v13.8h, w16 //wx + dup v14.4s, w17 //ox + + mov w17, #1 + lsl w17, w17, w15 + lsr w17, w17, #1 + dup v15.4s, w17 + + neg w15, w15 // -shift + dup v12.4s, w15 //shift +.endm + +.macro epel_uni_w_hv_end + smull v28.4s, v4.4h, v13.4h + smull2 v29.4s, v4.8h, v13.8h + add v28.4s, v28.4s, v15.4s + add v29.4s, v29.4s, v15.4s + sshl v28.4s, v28.4s, v12.4s + sshl v29.4s, v29.4s, v12.4s + add v28.4s, v28.4s, v14.4s + add v29.4s, v29.4s, v14.4s + sqxtn v4.4h, v28.4s + sqxtn2 v4.8h, v29.4s +.endm + +.macro epel_uni_w_hv_end2 + smull v28.4s, v4.4h, v13.4h + smull2 v29.4s, v4.8h, v13.8h + smull v30.4s, v5.4h, v13.4h + smull2 v31.4s, v5.8h, v13.8h + add v28.4s, v28.4s, v15.4s + add v29.4s, v29.4s, v15.4s + add v30.4s, v30.4s, v15.4s + add v31.4s, v31.4s, v15.4s + + sshl v28.4s, v28.4s, v12.4s + sshl v29.4s, v29.4s, v12.4s + sshl v30.4s, v30.4s, v12.4s + sshl v31.4s, v31.4s, v12.4s + + add v28.4s, v28.4s, v14.4s + add v29.4s, v29.4s, v14.4s + add v30.4s, v30.4s, v14.4s + add v31.4s, v31.4s, v14.4s + + sqxtn v4.4h, v28.4s + sqxtn2 v4.8h, v29.4s + sqxtn v5.4h, v30.4s + sqxtn2 v5.8h, v31.4s +.endm + +.macro epel_uni_w_hv_end3 + smull v1.4s, v4.4h, v13.4h + smull2 v2.4s, v4.8h, v13.8h + smull v28.4s, v5.4h, v13.4h + smull2 v29.4s, v5.8h, v13.8h + smull v30.4s, v6.4h, v13.4h + smull2 v31.4s, v6.8h, v13.8h + add v1.4s, v1.4s, v15.4s + add v2.4s, v2.4s, v15.4s + add v28.4s, v28.4s, v15.4s + add v29.4s, v29.4s, v15.4s + add v30.4s, v30.4s, v15.4s + add v31.4s, v31.4s, v15.4s + + sshl v1.4s, v1.4s, v12.4s + sshl v2.4s, v2.4s, v12.4s + sshl v28.4s, v28.4s, v12.4s + sshl v29.4s, v29.4s, v12.4s + sshl v30.4s, v30.4s, v12.4s + sshl v31.4s, v31.4s, v12.4s + add v1.4s, v1.4s, v14.4s + add v2.4s, v2.4s, v14.4s + add v28.4s, v28.4s, v14.4s + add v29.4s, v29.4s, v14.4s + add v30.4s, v30.4s, v14.4s + add v31.4s, v31.4s, v14.4s + + sqxtn v4.4h, v1.4s + sqxtn2 v4.8h, v2.4s + sqxtn v5.4h, v28.4s + sqxtn2 v5.8h, v29.4s + sqxtn v6.4h, v30.4s + sqxtn2 v6.8h, v31.4s +.endm + +.macro calc_epelh dst, src0, src1, src2, src3 + smull \dst\().4s, \src0\().4h, v0.h[0] + smlal \dst\().4s, \src1\().4h, v0.h[1] + smlal \dst\().4s, \src2\().4h, v0.h[2] + smlal \dst\().4s, \src3\().4h, v0.h[3] + sqshrn \dst\().4h, \dst\().4s, #6 +.endm + +.macro calc_epelh2 dst, tmp, src0, src1, src2, src3 + smull2 \tmp\().4s, \src0\().8h, v0.h[0] + smlal2 \tmp\().4s, \src1\().8h, v0.h[1] + smlal2 \tmp\().4s, \src2\().8h, v0.h[2] + smlal2 \tmp\().4s, \src3\().8h, v0.h[3] + sqshrn2 \dst\().8h, \tmp\().4s, #6 +.endm + +.macro load_epel_filterh freg, xreg + movrel \xreg, epel_filters + add \xreg, \xreg, \freg, lsl #2 + ld1 {v0.8b}, [\xreg] + sxtl v0.8h, v0.8b +.endm + +function ff_hevc_put_hevc_epel_uni_w_hv4_8_neon_i8mm, export=1 + epel_uni_w_hv_start + sxtw x4, w4 + + add x10, x4, #3 + lsl x10, x10, #7 + sub sp, sp, x10 // tmp_array + str x30, [sp, #-48]! + stp x4, x6, [sp, #16] + stp x0, x1, [sp, #32] + add x0, sp, #48 + sub x1, x2, x3 + mov x2, x3 + add x3, x4, #3 + mov x4, x5 + bl X(ff_hevc_put_hevc_epel_h4_8_neon_i8mm) + ldp x4, x6, [sp, #16] + ldp x0, x1, [sp, #32] + ldr x30, [sp], #48 + load_epel_filterh x6, x5 + mov x10, #(MAX_PB_SIZE * 2) + ld1 {v16.4h}, [sp], x10 + ld1 {v17.4h}, [sp], x10 + ld1 {v18.4h}, [sp], x10 +1: ld1 {v19.4h}, [sp], x10 + subs x4, x4, #1 + calc_epelh v4, v16, v17, v18, v19 + epel_uni_w_hv_end + sqxtun v4.8b, v4.8h + str s4, [x0] + add x0, x0, x1 + b.eq 2f + + ld1 {v16.4h}, [sp], x10 + subs x4, x4, #1 + calc_epelh v4, v17, v18, v19, v16 + epel_uni_w_hv_end + sqxtun v4.8b, v4.8h + str s4, [x0] + add x0, x0, x1 + b.eq 2f + + ld1 {v17.4h}, [sp], x10 + subs x4, x4, #1 + calc_epelh v4, v18, v19, v16, v17 + epel_uni_w_hv_end + sqxtun v4.8b, v4.8h + str s4, [x0] + add x0, x0, x1 + b.eq 2f + + ld1 {v18.4h}, [sp], x10 + subs x4, x4, #1 + calc_epelh v4, v19, v16, v17, v18 + epel_uni_w_hv_end + sqxtun v4.8b, v4.8h + str s4, [x0] + add x0, x0, x1 + b.ne 1b +2: + ldp d8, d9, [sp, #16] + ldp d10, d11, [sp, #32] + ldp d12, d13, [sp, #48] + ldp d14, d15, [sp], #64 + ret +endfunc + +function ff_hevc_put_hevc_epel_uni_w_hv6_8_neon_i8mm, export=1 + epel_uni_w_hv_start + sxtw x4, w4 + + add x10, x4, #3 + lsl x10, x10, #7 + sub sp, sp, x10 // tmp_array + str x30, [sp, #-48]! + stp x4, x6, [sp, #16] + stp x0, x1, [sp, #32] + add x0, sp, #48 + sub x1, x2, x3 + mov x2, x3 + add x3, x4, #3 + mov x4, x5 + bl X(ff_hevc_put_hevc_epel_h6_8_neon_i8mm) + ldp x4, x6, [sp, #16] + ldp x0, x1, [sp, #32] + ldr x30, [sp], #48 + load_epel_filterh x6, x5 + sub x1, x1, #4 + mov x10, #(MAX_PB_SIZE * 2) + ld1 {v16.8h}, [sp], x10 + ld1 {v17.8h}, [sp], x10 + ld1 {v18.8h}, [sp], x10 +1: ld1 {v19.8h}, [sp], x10 + subs x4, x4, #1 + calc_epelh v4, v16, v17, v18, v19 + calc_epelh2 v4, v5, v16, v17, v18, v19 + epel_uni_w_hv_end + sqxtun v4.8b, v4.8h + st1 {v4.s}[0], [x0], #4 + st1 {v4.h}[2], [x0], x1 + b.eq 2f + + ld1 {v16.8h}, [sp], x10 + subs x4, x4, #1 + calc_epelh v4, v17, v18, v19, v16 + calc_epelh2 v4, v5, v17, v18, v19, v16 + epel_uni_w_hv_end + sqxtun v4.8b, v4.8h + st1 {v4.s}[0], [x0], #4 + st1 {v4.h}[2], [x0], x1 + b.eq 2f + + ld1 {v17.8h}, [sp], x10 + subs x4, x4, #1 + calc_epelh v4, v18, v19, v16, v17 + calc_epelh2 v4, v5, v18, v19, v16, v17 + epel_uni_w_hv_end + sqxtun v4.8b, v4.8h + st1 {v4.s}[0], [x0], #4 + st1 {v4.h}[2], [x0], x1 + b.eq 2f + + ld1 {v18.8h}, [sp], x10 + subs x4, x4, #1 + calc_epelh v4, v19, v16, v17, v18 + calc_epelh2 v4, v5, v19, v16, v17, v18 + epel_uni_w_hv_end + sqxtun v4.8b, v4.8h + st1 {v4.s}[0], [x0], #4 + st1 {v4.h}[2], [x0], x1 + b.ne 1b +2: + ldp d8, d9, [sp, #16] + ldp d10, d11, [sp, #32] + ldp d12, d13, [sp, #48] + ldp d14, d15, [sp], #64 + ret +endfunc + +function ff_hevc_put_hevc_epel_uni_w_hv8_8_neon_i8mm, export=1 + epel_uni_w_hv_start + sxtw x4, w4 + + add x10, x4, #3 + lsl x10, x10, #7 + sub sp, sp, x10 // tmp_array + str x30, [sp, #-48]! + stp x4, x6, [sp, #16] + stp x0, x1, [sp, #32] + add x0, sp, #48 + sub x1, x2, x3 + mov x2, x3 + add x3, x4, #3 + mov x4, x5 + bl X(ff_hevc_put_hevc_epel_h8_8_neon_i8mm) + ldp x4, x6, [sp, #16] + ldp x0, x1, [sp, #32] + ldr x30, [sp], #48 + load_epel_filterh x6, x5 + mov x10, #(MAX_PB_SIZE * 2) + ld1 {v16.8h}, [sp], x10 + ld1 {v17.8h}, [sp], x10 + ld1 {v18.8h}, [sp], x10 +1: ld1 {v19.8h}, [sp], x10 + subs x4, x4, #1 + calc_epelh v4, v16, v17, v18, v19 + calc_epelh2 v4, v5, v16, v17, v18, v19 + epel_uni_w_hv_end + sqxtun v4.8b, v4.8h + st1 {v4.8b}, [x0], x1 + b.eq 2f + + ld1 {v16.8h}, [sp], x10 + subs x4, x4, #1 + calc_epelh v4, v17, v18, v19, v16 + calc_epelh2 v4, v5, v17, v18, v19, v16 + epel_uni_w_hv_end + sqxtun v4.8b, v4.8h + st1 {v4.8b}, [x0], x1 + b.eq 2f + + ld1 {v17.8h}, [sp], x10 + subs x4, x4, #1 + calc_epelh v4, v18, v19, v16, v17 + calc_epelh2 v4, v5, v18, v19, v16, v17 + epel_uni_w_hv_end + sqxtun v4.8b, v4.8h + st1 {v4.8b}, [x0], x1 + b.eq 2f + + ld1 {v18.8h}, [sp], x10 + subs x4, x4, #1 + calc_epelh v4, v19, v16, v17, v18 + calc_epelh2 v4, v5, v19, v16, v17, v18 + epel_uni_w_hv_end + sqxtun v4.8b, v4.8h + st1 {v4.8b}, [x0], x1 + b.ne 1b +2: + ldp d8, d9, [sp, #16] + ldp d10, d11, [sp, #32] + ldp d12, d13, [sp, #48] + ldp d14, d15, [sp], #64 + ret +endfunc + +function ff_hevc_put_hevc_epel_uni_w_hv12_8_neon_i8mm, export=1 + epel_uni_w_hv_start + sxtw x4, w4 + + add x10, x4, #3 + lsl x10, x10, #7 + sub sp, sp, x10 // tmp_array + str x30, [sp, #-48]! + stp x4, x6, [sp, #16] + stp x0, x1, [sp, #32] + add x0, sp, #48 + sub x1, x2, x3 + mov x2, x3 + add x3, x4, #3 + mov x4, x5 + bl X(ff_hevc_put_hevc_epel_h12_8_neon_i8mm) + ldp x4, x6, [sp, #16] + ldp x0, x1, [sp, #32] + ldr x30, [sp], #48 + load_epel_filterh x6, x5 + sub x1, x1, #8 + mov x10, #(MAX_PB_SIZE * 2) + ld1 {v16.8h, v17.8h}, [sp], x10 + ld1 {v18.8h, v19.8h}, [sp], x10 + ld1 {v20.8h, v21.8h}, [sp], x10 +1: ld1 {v22.8h, v23.8h}, [sp], x10 + subs x4, x4, #1 + calc_epelh v4, v16, v18, v20, v22 + calc_epelh2 v4, v5, v16, v18, v20, v22 + calc_epelh v5, v17, v19, v21, v23 + epel_uni_w_hv_end2 + sqxtun v4.8b, v4.8h + sqxtun2 v4.16b, v5.8h + st1 {v4.8b}, [x0], #8 + st1 {v4.s}[2], [x0], x1 + b.eq 2f + + ld1 {v16.8h, v17.8h}, [sp], x10 + subs x4, x4, #1 + calc_epelh v4, v18, v20, v22, v16 + calc_epelh2 v4, v5, v18, v20, v22, v16 + calc_epelh v5, v19, v21, v23, v17 + epel_uni_w_hv_end2 + sqxtun v4.8b, v4.8h + sqxtun2 v4.16b, v5.8h + st1 {v4.8b}, [x0], #8 + st1 {v4.s}[2], [x0], x1 + b.eq 2f + + ld1 {v18.8h, v19.8h}, [sp], x10 + subs x4, x4, #1 + calc_epelh v4, v20, v22, v16, v18 + calc_epelh2 v4, v5, v20, v22, v16, v18 + calc_epelh v5, v21, v23, v17, v19 + epel_uni_w_hv_end2 + sqxtun v4.8b, v4.8h + sqxtun2 v4.16b, v5.8h + st1 {v4.8b}, [x0], #8 + st1 {v4.s}[2], [x0], x1 + b.eq 2f + + ld1 {v20.8h, v21.8h}, [sp], x10 + subs x4, x4, #1 + calc_epelh v4, v22, v16, v18, v20 + calc_epelh2 v4, v5, v22, v16, v18, v20 + calc_epelh v5, v23, v17, v19, v21 + epel_uni_w_hv_end2 + sqxtun v4.8b, v4.8h + sqxtun2 v4.16b, v5.8h + st1 {v4.8b}, [x0], #8 + st1 {v4.s}[2], [x0], x1 + b.ne 1b +2: + ldp d8, d9, [sp, #16] + ldp d10, d11, [sp, #32] + ldp d12, d13, [sp, #48] + ldp d14, d15, [sp], #64 + ret +endfunc + +function ff_hevc_put_hevc_epel_uni_w_hv16_8_neon_i8mm, export=1 + epel_uni_w_hv_start + sxtw x4, w4 + + add x10, x4, #3 + lsl x10, x10, #7 + sub sp, sp, x10 // tmp_array + str x30, [sp, #-48]! + stp x4, x6, [sp, #16] + stp x0, x1, [sp, #32] + add x0, sp, #48 + sub x1, x2, x3 + mov x2, x3 + add x3, x4, #3 + mov x4, x5 + bl X(ff_hevc_put_hevc_epel_h16_8_neon_i8mm) + ldp x4, x6, [sp, #16] + ldp x0, x1, [sp, #32] + ldr x30, [sp], #48 + load_epel_filterh x6, x5 + mov x10, #(MAX_PB_SIZE * 2) + ld1 {v16.8h, v17.8h}, [sp], x10 + ld1 {v18.8h, v19.8h}, [sp], x10 + ld1 {v20.8h, v21.8h}, [sp], x10 +1: ld1 {v22.8h, v23.8h}, [sp], x10 + subs x4, x4, #1 + calc_epelh v4, v16, v18, v20, v22 + calc_epelh2 v4, v5, v16, v18, v20, v22 + calc_epelh v5, v17, v19, v21, v23 + calc_epelh2 v5, v6, v17, v19, v21, v23 + epel_uni_w_hv_end2 + sqxtun v4.8b, v4.8h + sqxtun2 v4.16b, v5.8h + st1 {v4.16b}, [x0], x1 + b.eq 2f + + ld1 {v16.8h, v17.8h}, [sp], x10 + subs x4, x4, #1 + calc_epelh v4, v18, v20, v22, v16 + calc_epelh2 v4, v5, v18, v20, v22, v16 + calc_epelh v5, v19, v21, v23, v17 + calc_epelh2 v5, v6, v19, v21, v23, v17 + epel_uni_w_hv_end2 + sqxtun v4.8b, v4.8h + sqxtun2 v4.16b, v5.8h + st1 {v4.16b}, [x0], x1 + b.eq 2f + + ld1 {v18.8h, v19.8h}, [sp], x10 + subs x4, x4, #1 + calc_epelh v4, v20, v22, v16, v18 + calc_epelh2 v4, v5, v20, v22, v16, v18 + calc_epelh v5, v21, v23, v17, v19 + calc_epelh2 v5, v6, v21, v23, v17, v19 + epel_uni_w_hv_end2 + sqxtun v4.8b, v4.8h + sqxtun2 v4.16b, v5.8h + st1 {v4.16b}, [x0], x1 + b.eq 2f + + ld1 {v20.8h, v21.8h}, [sp], x10 + subs x4, x4, #1 + calc_epelh v4, v22, v16, v18, v20 + calc_epelh2 v4, v5, v22, v16, v18, v20 + calc_epelh v5, v23, v17, v19, v21 + calc_epelh2 v5, v6, v23, v17, v19, v21 + epel_uni_w_hv_end2 + sqxtun v4.8b, v4.8h + sqxtun2 v4.16b, v5.8h + st1 {v4.16b}, [x0], x1 + b.ne 1b +2: + ldp d8, d9, [sp, #16] + ldp d10, d11, [sp, #32] + ldp d12, d13, [sp, #48] + ldp d14, d15, [sp], #64 + ret +endfunc + +function ff_hevc_put_hevc_epel_uni_w_hv24_8_neon_i8mm, export=1 + epel_uni_w_hv_start + sxtw x4, w4 + + add x10, x4, #3 + lsl x10, x10, #7 + sub sp, sp, x10 // tmp_array + str x30, [sp, #-48]! + stp x4, x6, [sp, #16] + stp x0, x1, [sp, #32] + add x0, sp, #48 + sub x1, x2, x3 + mov x2, x3 + add x3, x4, #3 + mov x4, x5 + bl X(ff_hevc_put_hevc_epel_h24_8_neon_i8mm) + ldp x4, x6, [sp, #16] + ldp x0, x1, [sp, #32] + ldr x30, [sp], #48 + load_epel_filterh x6, x5 + mov x10, #(MAX_PB_SIZE * 2) + ld1 {v16.8h, v17.8h, v18.8h}, [sp], x10 + ld1 {v19.8h, v20.8h, v21.8h}, [sp], x10 + ld1 {v22.8h, v23.8h, v24.8h}, [sp], x10 +1: ld1 {v25.8h, v26.8h, v27.8h}, [sp], x10 + subs x4, x4, #1 + calc_epelh v4, v16, v19, v22, v25 + calc_epelh2 v4, v5, v16, v19, v22, v25 + calc_epelh v5, v17, v20, v23, v26 + calc_epelh2 v5, v6, v17, v20, v23, v26 + calc_epelh v6, v18, v21, v24, v27 + calc_epelh2 v6, v7, v18, v21, v24, v27 + + epel_uni_w_hv_end3 + sqxtun v4.8b, v4.8h + sqxtun v5.8b, v5.8h + sqxtun v6.8b, v6.8h + st1 {v4.8b, v5.8b, v6.8b}, [x0], x1 + b.eq 2f + + ld1 {v16.8h, v17.8h, v18.8h}, [sp], x10 + subs x4, x4, #1 + calc_epelh v4, v19, v22, v25, v16 + calc_epelh2 v4, v5, v19, v22, v25, v16 + calc_epelh v5, v20, v23, v26, v17 + calc_epelh2 v5, v6, v20, v23, v26, v17 + calc_epelh v6, v21, v24, v27, v18 + calc_epelh2 v6, v7, v21, v24, v27, v18 + epel_uni_w_hv_end3 + + sqxtun v4.8b, v4.8h + sqxtun v5.8b, v5.8h + sqxtun v6.8b, v6.8h + st1 {v4.8b, v5.8b, v6.8b}, [x0], x1 + b.eq 2f + + ld1 {v19.8h, v20.8h, v21.8h}, [sp], x10 + subs x4, x4, #1 + calc_epelh v4, v22, v25, v16, v19 + calc_epelh2 v4, v5, v22, v25, v16, v19 + calc_epelh v5, v23, v26, v17, v20 + calc_epelh2 v5, v6, v23, v26, v17, v20 + calc_epelh v6, v24, v27, v18, v21 + calc_epelh2 v6, v7, v24, v27, v18, v21 + epel_uni_w_hv_end3 + + sqxtun v4.8b, v4.8h + sqxtun v5.8b, v5.8h + sqxtun v6.8b, v6.8h + st1 {v4.8b, v5.8b, v6.8b}, [x0], x1 + b.eq 2f + + ld1 {v22.8h, v23.8h, v24.8h}, [sp], x10 + subs x4, x4, #1 + calc_epelh v4, v25, v16, v19, v22 + calc_epelh2 v4, v5, v25, v16, v19, v22 + calc_epelh v5, v26, v17, v20, v23 + calc_epelh2 v5, v6, v26, v17, v20, v23 + calc_epelh v6, v27, v18, v21, v24 + calc_epelh2 v6, v7, v27, v18, v21, v24 + epel_uni_w_hv_end3 + + sqxtun v4.8b, v4.8h + sqxtun v5.8b, v5.8h + sqxtun v6.8b, v6.8h + st1 {v4.8b, v5.8b, v6.8b}, [x0], x1 + b.ne 1b +2: + ldp d8, d9, [sp, #16] + ldp d10, d11, [sp, #32] + ldp d12, d13, [sp, #48] + ldp d14, d15, [sp], #64 + ret +endfunc + +function ff_hevc_put_hevc_epel_uni_w_hv32_8_neon_i8mm, export=1 + ldp x15, x16, [sp] + mov x17, #16 + stp x15, x16, [sp, #-96]! + stp x0, x30, [sp, #16] + stp x1, x2, [sp, #32] + stp x3, x4, [sp, #48] + stp x5, x6, [sp, #64] + stp x17, x7, [sp, #80] + + bl X(ff_hevc_put_hevc_epel_uni_w_hv16_8_neon_i8mm) + ldp x0, x30, [sp, #16] + ldp x1, x2, [sp, #32] + ldp x3, x4, [sp, #48] + ldp x5, x6, [sp, #64] + ldp x17, x7, [sp, #80] + ldp x15, x16, [sp], #96 + add x0, x0, #16 + add x2, x2, #16 + mov x17, #16 + stp x15, x16, [sp, #-32]! + stp x17, x30, [sp, #16] + bl X(ff_hevc_put_hevc_epel_uni_w_hv16_8_neon_i8mm) + ldp x17, x30, [sp, #16] + ldp x15, x16, [sp], #32 + ret +endfunc + +function ff_hevc_put_hevc_epel_uni_w_hv48_8_neon_i8mm, export=1 + ldp x15, x16, [sp] + mov x17, #24 + stp x15, x16, [sp, #-96]! + stp x0, x30, [sp, #16] + stp x1, x2, [sp, #32] + stp x3, x4, [sp, #48] + stp x5, x6, [sp, #64] + stp x17, x7, [sp, #80] + bl X(ff_hevc_put_hevc_epel_uni_w_hv24_8_neon_i8mm) + ldp x0, x30, [sp, #16] + ldp x1, x2, [sp, #32] + ldp x3, x4, [sp, #48] + ldp x5, x6, [sp, #64] + ldp x17, x7, [sp, #80] + ldp x15, x16, [sp], #96 + add x0, x0, #24 + add x2, x2, #24 + mov x17, #24 + stp x15, x16, [sp, #-32]! + stp x17, x30, [sp, #16] + bl X(ff_hevc_put_hevc_epel_uni_w_hv24_8_neon_i8mm) + ldp x17, x30, [sp, #16] + ldp x15, x16, [sp], #32 + ret +endfunc + +function ff_hevc_put_hevc_epel_uni_w_hv64_8_neon_i8mm, export=1 + ldp x15, x16, [sp] + mov x17, #32 + stp x15, x16, [sp, #-96]! + stp x0, x30, [sp, #16] + stp x1, x2, [sp, #32] + stp x3, x4, [sp, #48] + stp x5, x6, [sp, #64] + stp x17, x7, [sp, #80] + + bl X(ff_hevc_put_hevc_epel_uni_w_hv32_8_neon_i8mm) + ldp x0, x30, [sp, #16] + ldp x1, x2, [sp, #32] + ldp x3, x4, [sp, #48] + ldp x5, x6, [sp, #64] + ldp x17, x7, [sp, #80] + ldp x15, x16, [sp], #96 + add x0, x0, #32 + add x2, x2, #32 + mov x17, #32 + stp x15, x16, [sp, #-32]! + stp x17, x30, [sp, #16] + bl X(ff_hevc_put_hevc_epel_uni_w_hv32_8_neon_i8mm) + ldp x17, x30, [sp, #16] + ldp x15, x16, [sp], #32 + ret +endfunc + + #endif diff --git a/libavcodec/aarch64/hevcdsp_init_aarch64.c b/libavcodec/aarch64/hevcdsp_init_aarch64.c index b448d755b92..e125b0cfb28 100644 --- a/libavcodec/aarch64/hevcdsp_init_aarch64.c +++ b/libavcodec/aarch64/hevcdsp_init_aarch64.c @@ -189,6 +189,11 @@ NEON8_FNPROTO(qpel_uni_w_h, (uint8_t *_dst, ptrdiff_t _dststride, int height, int denom, int wx, int ox, intptr_t mx, intptr_t my, int width), _i8mm); +NEON8_FNPROTO(epel_uni_w_hv, (uint8_t *_dst, ptrdiff_t _dststride, + const uint8_t *_src, ptrdiff_t _srcstride, + int height, int denom, int wx, int ox, + intptr_t mx, intptr_t my, int width), _i8mm); + NEON8_FNPROTO_PARTIAL_5(qpel_uni_w_hv, (uint8_t *_dst, ptrdiff_t _dststride, const uint8_t *_src, ptrdiff_t _srcstride, int height, int denom, int wx, int ox, @@ -291,6 +296,7 @@ av_cold void ff_hevc_dsp_init_aarch64(HEVCDSPContext *c, const int bit_depth) NEON8_FNASSIGN(c->put_hevc_epel_uni_w, 0, 1, epel_uni_w_h ,_i8mm); NEON8_FNASSIGN(c->put_hevc_qpel, 0, 1, qpel_h, _i8mm); NEON8_FNASSIGN(c->put_hevc_qpel_uni_w, 0, 1, qpel_uni_w_h, _i8mm); + NEON8_FNASSIGN(c->put_hevc_epel_uni_w, 1, 1, epel_uni_w_hv, _i8mm); NEON8_FNASSIGN_PARTIAL_5(c->put_hevc_qpel_uni_w, 1, 1, qpel_uni_w_hv, _i8mm); } From f264204de9d15f21d10a67304ee32347a5adb411 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Sun, 9 Jul 2023 14:53:46 +0200 Subject: [PATCH 1844/2172] lavc: deprecate AV_CODEC_FLAG_DROPCHANGED This decoding flag makes decoders drop all frames after a parameter change, but what exactly constitutes a parameter change is not well defined and will typically depend on the exact use case. This functionality then does not belong in libavcodec, but rather in user code --- doc/APIchanges | 3 +++ libavcodec/avcodec.c | 2 ++ libavcodec/avcodec.h | 7 ++++--- libavcodec/decode.c | 11 +++++++++-- libavcodec/internal.h | 2 ++ libavcodec/options_table.h | 4 +++- libavcodec/version_major.h | 1 + 7 files changed, 24 insertions(+), 6 deletions(-) diff --git a/doc/APIchanges b/doc/APIchanges index 27f835cfced..5afe8bcb75a 100644 --- a/doc/APIchanges +++ b/doc/APIchanges @@ -2,6 +2,9 @@ The last version increases of all libraries were on 2023-02-09 API changes, most recent first: +2023-07-xx - xxxxxxxxxx - lavc 60 - avcodec.h + Deprecate AV_CODEC_FLAG_DROPCHANGED without replacement. + 2023-07-05 - xxxxxxxxxx - lavu 58.14.100 - random_seed.h Add av_random_bytes() diff --git a/libavcodec/avcodec.c b/libavcodec/avcodec.c index 8ccc6102272..340abe830e8 100644 --- a/libavcodec/avcodec.c +++ b/libavcodec/avcodec.c @@ -456,7 +456,9 @@ av_cold int avcodec_close(AVCodecContext *avctx) av_bsf_free(&avci->bsf); +#if FF_API_DROPCHANGED av_channel_layout_uninit(&avci->initial_ch_layout); +#endif #if CONFIG_LCMS2 ff_icc_context_uninit(&avci->icc); diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h index d17bdc360dd..fe41ecc3c9f 100644 --- a/libavcodec/avcodec.h +++ b/libavcodec/avcodec.h @@ -226,11 +226,15 @@ typedef struct RcOverride{ * Use qpel MC. */ #define AV_CODEC_FLAG_QPEL (1 << 4) +#if FF_API_DROPCHANGED /** * Don't output frames whose parameters differ from first * decoded frame in stream. + * + * @deprecated callers should implement this functionality in their own code */ #define AV_CODEC_FLAG_DROPCHANGED (1 << 5) +#endif /** * Request the encoder to output reconstructed frames, i.e.\ frames that would * be produced by decoding the encoded bistream. These frames may be retrieved @@ -2713,9 +2717,6 @@ int avcodec_send_packet(AVCodecContext *avctx, const AVPacket *avpkt); * no more output frames * @retval AVERROR(EINVAL) codec not opened, or it is an encoder without the * @ref AV_CODEC_FLAG_RECON_FRAME flag enabled - * @retval AVERROR_INPUT_CHANGED current decoded frame has changed parameters with - * respect to first decoded frame. Applicable when flag - * AV_CODEC_FLAG_DROPCHANGED is set. * @retval "other negative error code" legitimate decoding errors */ int avcodec_receive_frame(AVCodecContext *avctx, AVFrame *frame); diff --git a/libavcodec/decode.c b/libavcodec/decode.c index 68525e47a60..a19cca1a7ce 100644 --- a/libavcodec/decode.c +++ b/libavcodec/decode.c @@ -773,7 +773,7 @@ static int frame_validate(AVCodecContext *avctx, AVFrame *frame) int ff_decode_receive_frame(AVCodecContext *avctx, AVFrame *frame) { AVCodecInternal *avci = avctx->internal; - int ret, changed; + int ret; if (!avcodec_is_open(avctx) || !av_codec_is_decoder(avctx->codec)) return AVERROR(EINVAL); @@ -803,6 +803,7 @@ FF_DISABLE_DEPRECATION_WARNINGS FF_ENABLE_DEPRECATION_WARNINGS #endif +#if FF_API_DROPCHANGED if (avctx->flags & AV_CODEC_FLAG_DROPCHANGED) { if (avctx->frame_num == 1) { @@ -823,7 +824,7 @@ FF_ENABLE_DEPRECATION_WARNINGS } if (avctx->frame_num > 1) { - changed = avci->initial_format != frame->format; + int changed = avci->initial_format != frame->format; switch(avctx->codec_type) { case AVMEDIA_TYPE_VIDEO: @@ -848,6 +849,7 @@ FF_ENABLE_DEPRECATION_WARNINGS } } } +#endif return 0; fail: av_frame_unref(frame); @@ -1773,6 +1775,11 @@ int ff_decode_preinit(AVCodecContext *avctx) if (ret < 0) return ret; +#if FF_API_DROPCHANGED + if (avctx->flags & AV_CODEC_FLAG_DROPCHANGED) + av_log(avctx, AV_LOG_WARNING, "The dropchanged flag is deprecated.\n"); +#endif + return 0; } diff --git a/libavcodec/internal.h b/libavcodec/internal.h index 868dd46b489..4dce9f6fbb9 100644 --- a/libavcodec/internal.h +++ b/libavcodec/internal.h @@ -135,12 +135,14 @@ typedef struct AVCodecInternal { AVFrame *buffer_frame; int draining_done; +#if FF_API_DROPCHANGED /* used when avctx flag AV_CODEC_FLAG_DROPCHANGED is set */ int changed_frames_dropped; int initial_format; int initial_width, initial_height; int initial_sample_rate; AVChannelLayout initial_ch_layout; +#endif #if CONFIG_LCMS2 FFIccContext icc; /* used to read and write embedded ICC profiles */ diff --git a/libavcodec/options_table.h b/libavcodec/options_table.h index f1a9729c0d0..bb4b894b064 100644 --- a/libavcodec/options_table.h +++ b/libavcodec/options_table.h @@ -72,7 +72,9 @@ static const AVOption avcodec_options[] = { {"ilme", "interlaced motion estimation", 0, AV_OPT_TYPE_CONST, {.i64 = AV_CODEC_FLAG_INTERLACED_ME }, INT_MIN, INT_MAX, V|E, "flags"}, {"cgop", "closed GOP", 0, AV_OPT_TYPE_CONST, {.i64 = AV_CODEC_FLAG_CLOSED_GOP }, INT_MIN, INT_MAX, V|E, "flags"}, {"output_corrupt", "Output even potentially corrupted frames", 0, AV_OPT_TYPE_CONST, {.i64 = AV_CODEC_FLAG_OUTPUT_CORRUPT }, INT_MIN, INT_MAX, V|D, "flags"}, -{"drop_changed", "Drop frames whose parameters differ from first decoded frame", 0, AV_OPT_TYPE_CONST, {.i64 = AV_CODEC_FLAG_DROPCHANGED }, INT_MIN, INT_MAX, A|V|D, "flags"}, +#if FF_API_DROPCHANGED +{"drop_changed", "Drop frames whose parameters differ from first decoded frame", 0, AV_OPT_TYPE_CONST, {.i64 = AV_CODEC_FLAG_DROPCHANGED }, INT_MIN, INT_MAX, A|V|D | AV_OPT_FLAG_DEPRECATED, "flags"}, +#endif {"flags2", NULL, OFFSET(flags2), AV_OPT_TYPE_FLAGS, {.i64 = DEFAULT}, 0, UINT_MAX, V|A|E|D|S, "flags2"}, {"fast", "allow non-spec-compliant speedup tricks", 0, AV_OPT_TYPE_CONST, {.i64 = AV_CODEC_FLAG2_FAST }, INT_MIN, INT_MAX, V|E, "flags2"}, {"noout", "skip bitstream encoding", 0, AV_OPT_TYPE_CONST, {.i64 = AV_CODEC_FLAG2_NO_OUTPUT }, INT_MIN, INT_MAX, V|E, "flags2"}, diff --git a/libavcodec/version_major.h b/libavcodec/version_major.h index 2f5138d0794..95c5aec0c58 100644 --- a/libavcodec/version_major.h +++ b/libavcodec/version_major.h @@ -48,6 +48,7 @@ #define FF_API_SLICE_OFFSET (LIBAVCODEC_VERSION_MAJOR < 61) #define FF_API_SUBFRAMES (LIBAVCODEC_VERSION_MAJOR < 61) #define FF_API_TICKS_PER_FRAME (LIBAVCODEC_VERSION_MAJOR < 61) +#define FF_API_DROPCHANGED (LIBAVCODEC_VERSION_MAJOR < 61) // reminder to remove CrystalHD decoders on next major bump #define FF_CODEC_CRYSTAL_HD (LIBAVCODEC_VERSION_MAJOR < 61) From ef3b5789ece62c26c12697c588bbb34f3efbd437 Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Sat, 15 Jul 2023 10:39:27 +0200 Subject: [PATCH 1845/2172] avfilter/af_atempo: improve RE_MALLOC_OR_FAIL macro Make use of third parameter of av_calloc() call. --- libavfilter/af_atempo.c | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/libavfilter/af_atempo.c b/libavfilter/af_atempo.c index 27f13638b02..4621b67b036 100644 --- a/libavfilter/af_atempo.c +++ b/libavfilter/af_atempo.c @@ -247,10 +247,10 @@ static void yae_release_buffers(ATempoContext *atempo) /* av_realloc is not aligned enough; fortunately, the data does not need to * be preserved */ -#define RE_MALLOC_OR_FAIL(field, field_size) \ +#define RE_MALLOC_OR_FAIL(field, field_size, element_size) \ do { \ av_freep(&field); \ - field = av_calloc(field_size, 1); \ + field = av_calloc(field_size, element_size); \ if (!field) { \ yae_release_buffers(atempo); \ return AVERROR(ENOMEM); \ @@ -290,12 +290,12 @@ static int yae_reset(ATempoContext *atempo, } // initialize audio fragment buffers: - RE_MALLOC_OR_FAIL(atempo->frag[0].data, atempo->window * atempo->stride); - RE_MALLOC_OR_FAIL(atempo->frag[1].data, atempo->window * atempo->stride); - RE_MALLOC_OR_FAIL(atempo->frag[0].xdat_in, (atempo->window + 1) * sizeof(AVComplexFloat)); - RE_MALLOC_OR_FAIL(atempo->frag[1].xdat_in, (atempo->window + 1) * sizeof(AVComplexFloat)); - RE_MALLOC_OR_FAIL(atempo->frag[0].xdat, (atempo->window + 1) * sizeof(AVComplexFloat)); - RE_MALLOC_OR_FAIL(atempo->frag[1].xdat, (atempo->window + 1) * sizeof(AVComplexFloat)); + RE_MALLOC_OR_FAIL(atempo->frag[0].data, atempo->window, atempo->stride); + RE_MALLOC_OR_FAIL(atempo->frag[1].data, atempo->window, atempo->stride); + RE_MALLOC_OR_FAIL(atempo->frag[0].xdat_in, (atempo->window + 1), sizeof(AVComplexFloat)); + RE_MALLOC_OR_FAIL(atempo->frag[1].xdat_in, (atempo->window + 1), sizeof(AVComplexFloat)); + RE_MALLOC_OR_FAIL(atempo->frag[0].xdat, (atempo->window + 1), sizeof(AVComplexFloat)); + RE_MALLOC_OR_FAIL(atempo->frag[1].xdat, (atempo->window + 1), sizeof(AVComplexFloat)); // initialize rDFT contexts: av_tx_uninit(&atempo->real_to_complex); @@ -313,14 +313,14 @@ static int yae_reset(ATempoContext *atempo, return AVERROR(ENOMEM); } - RE_MALLOC_OR_FAIL(atempo->correlation_in, (atempo->window + 1) * sizeof(AVComplexFloat)); - RE_MALLOC_OR_FAIL(atempo->correlation, atempo->window * sizeof(AVComplexFloat)); + RE_MALLOC_OR_FAIL(atempo->correlation_in, (atempo->window + 1), sizeof(AVComplexFloat)); + RE_MALLOC_OR_FAIL(atempo->correlation, atempo->window, sizeof(AVComplexFloat)); atempo->ring = atempo->window * 3; - RE_MALLOC_OR_FAIL(atempo->buffer, atempo->ring * atempo->stride); + RE_MALLOC_OR_FAIL(atempo->buffer, atempo->ring, atempo->stride); // initialize the Hann window function: - RE_MALLOC_OR_FAIL(atempo->hann, atempo->window * sizeof(float)); + RE_MALLOC_OR_FAIL(atempo->hann, atempo->window, sizeof(float)); for (i = 0; i < atempo->window; i++) { double t = (double)i / (double)(atempo->window - 1); From c313cdd70c510d5f2b632fc2c57d6d387c44d6ce Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Wed, 12 Jul 2023 12:45:57 +0200 Subject: [PATCH 1846/2172] fftools/ffmpeg_mux_init: return errors from of_open() instead of aborting --- fftools/ffmpeg_mux_init.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/fftools/ffmpeg_mux_init.c b/fftools/ffmpeg_mux_init.c index 6ab541d7c5a..8a3e7b98cf8 100644 --- a/fftools/ffmpeg_mux_init.c +++ b/fftools/ffmpeg_mux_init.c @@ -2380,7 +2380,7 @@ int of_open(const OptionsContext *o, const char *filename) int64_t start_time = o->start_time == AV_NOPTS_VALUE ? 0 : o->start_time; if (stop_time <= start_time) { av_log(mux, AV_LOG_ERROR, "-to value smaller than -ss; aborting.\n"); - exit_program(1); + return AVERROR(EINVAL); } else { recording_time = stop_time - start_time; } @@ -2401,7 +2401,7 @@ int of_open(const OptionsContext *o, const char *filename) if (!oc) { av_log(mux, AV_LOG_FATAL, "Error initializing the muxer for %s: %s\n", filename, av_err2str(err)); - exit_program(1); + return err; } mux->fc = oc; @@ -2437,7 +2437,7 @@ int of_open(const OptionsContext *o, const char *filename) "Output filename '%s' does not contain a numeric pattern like " "'%%d', which is required by output format '%s'.\n", oc->url, oc->oformat->name); - exit_program(1); + return AVERROR(EINVAL); } if (!(oc->oformat->flags & AVFMT_NOFILE)) { @@ -2450,7 +2450,7 @@ int of_open(const OptionsContext *o, const char *filename) &mux->opts)) < 0) { av_log(mux, AV_LOG_FATAL, "Error opening output %s: %s\n", filename, av_err2str(err)); - exit_program(1); + return err; } } else if (strcmp(oc->oformat->name, "image2")==0 && !av_filename_number_test(filename)) assert_file_overwrite(filename); @@ -2469,7 +2469,7 @@ int of_open(const OptionsContext *o, const char *filename) err = set_dispositions(mux, o); if (err < 0) { av_log(mux, AV_LOG_FATAL, "Error setting output stream dispositions\n"); - exit_program(1); + return err; } // parse forced keyframe specifications; @@ -2477,13 +2477,13 @@ int of_open(const OptionsContext *o, const char *filename) err = process_forced_keyframes(mux, o); if (err < 0) { av_log(mux, AV_LOG_FATAL, "Error processing forced keyframes\n"); - exit_program(1); + return err; } err = setup_sync_queues(mux, oc, o->shortest_buf_duration * AV_TIME_BASE); if (err < 0) { av_log(mux, AV_LOG_FATAL, "Error setting up output sync queues\n"); - exit_program(1); + return err; } of->url = filename; @@ -2500,7 +2500,7 @@ int of_open(const OptionsContext *o, const char *filename) err = init_output_stream_nofilter(ost); if (err < 0) - report_and_exit(err); + return err; } /* write the header for files with no streams */ From ad80857a973da89b5576fc87b928670ad1f1d9f2 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Wed, 12 Jul 2023 12:45:57 +0200 Subject: [PATCH 1847/2172] fftools/ffmpeg_demux: return errors from ifile_open() instead of aborting --- fftools/ffmpeg_demux.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/fftools/ffmpeg_demux.c b/fftools/ffmpeg_demux.c index 5d3e043793d..a6df2a19048 100644 --- a/fftools/ffmpeg_demux.c +++ b/fftools/ffmpeg_demux.c @@ -1349,7 +1349,7 @@ int ifile_open(const OptionsContext *o, const char *filename) int64_t start = start_time == AV_NOPTS_VALUE ? 0 : start_time; if (stop_time <= start) { av_log(d, AV_LOG_ERROR, "-to value smaller than -ss; aborting.\n"); - exit_program(1); + return AVERROR(EINVAL); } else { recording_time = stop_time - start; } @@ -1358,7 +1358,7 @@ int ifile_open(const OptionsContext *o, const char *filename) if (o->format) { if (!(file_iformat = av_find_input_format(o->format))) { av_log(d, AV_LOG_FATAL, "Unknown input format: '%s'\n", o->format); - exit_program(1); + return AVERROR(EINVAL); } } @@ -1372,7 +1372,7 @@ int ifile_open(const OptionsContext *o, const char *filename) /* get default parameters from command line */ ic = avformat_alloc_context(); if (!ic) - report_and_exit(AVERROR(ENOMEM)); + return AVERROR(ENOMEM); if (o->nb_audio_sample_rate) { av_dict_set_int(&o->g->format_opts, "sample_rate", o->audio_sample_rate[o->nb_audio_sample_rate - 1].u.i, 0); } @@ -1446,7 +1446,7 @@ int ifile_open(const OptionsContext *o, const char *filename) "Error opening input: %s\n", av_err2str(err)); if (err == AVERROR_PROTOCOL_NOT_FOUND) av_log(d, AV_LOG_ERROR, "Did you mean file:%s?\n", filename); - exit_program(1); + return err; } av_strlcat(d->log_name, "/", sizeof(d->log_name)); @@ -1477,7 +1477,7 @@ int ifile_open(const OptionsContext *o, const char *filename) av_log(d, AV_LOG_FATAL, "could not find codec parameters\n"); if (ic->nb_streams == 0) { avformat_close_input(&ic); - exit_program(1); + return ret; } } } @@ -1490,7 +1490,7 @@ int ifile_open(const OptionsContext *o, const char *filename) if (start_time_eof != AV_NOPTS_VALUE) { if (start_time_eof >= 0) { av_log(d, AV_LOG_ERROR, "-sseof value must be negative; aborting\n"); - exit_program(1); + return AVERROR(EINVAL); } if (ic->duration > 0) { start_time = start_time_eof + ic->duration; @@ -1547,7 +1547,7 @@ int ifile_open(const OptionsContext *o, const char *filename) f->readrate = o->readrate ? o->readrate : 0.0; if (f->readrate < 0.0f) { av_log(d, AV_LOG_ERROR, "Option -readrate is %0.3f; it must be non-negative.\n", f->readrate); - exit_program(1); + return AVERROR(EINVAL); } if (o->rate_emu) { if (f->readrate) { @@ -1562,7 +1562,7 @@ int ifile_open(const OptionsContext *o, const char *filename) av_log(d, AV_LOG_ERROR, "Option -readrate_initial_burst is %0.3f; it must be non-negative.\n", d->readrate_initial_burst); - exit_program(1); + return AVERROR(EINVAL); } } else if (o->readrate_initial_burst) { av_log(d, AV_LOG_WARNING, "Option -readrate_initial_burst ignored " @@ -1601,7 +1601,7 @@ int ifile_open(const OptionsContext *o, const char *filename) if (!(option->flags & AV_OPT_FLAG_DECODING_PARAM)) { av_log(d, AV_LOG_ERROR, "Codec AVOption %s (%s) is not a decoding " "option.\n", e->key, option->help ? option->help : ""); - exit_program(1); + return AVERROR(EINVAL); } av_log(d, AV_LOG_WARNING, "Codec AVOption %s (%s) has not been used " From ff0160cb372fb46dee5a593d5fe3fdff0fb92414 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Wed, 12 Jul 2023 12:56:28 +0200 Subject: [PATCH 1848/2172] fftools/ffmpeg_demux: drop a redundant avio_flush() It is immediately followed by avio_close(), which is documented to flush the buffers. --- fftools/ffmpeg_demux.c | 1 - 1 file changed, 1 deletion(-) diff --git a/fftools/ffmpeg_demux.c b/fftools/ffmpeg_demux.c index a6df2a19048..40bbfa0c0eb 100644 --- a/fftools/ffmpeg_demux.c +++ b/fftools/ffmpeg_demux.c @@ -1286,7 +1286,6 @@ static void dump_attachment(InputStream *ist, const char *filename) } avio_write(out, st->codecpar->extradata, st->codecpar->extradata_size); - avio_flush(out); avio_close(out); } From 63e4e8e4f498e4be17d1c9d7bc3eed446693c24e Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Wed, 12 Jul 2023 13:00:16 +0200 Subject: [PATCH 1849/2172] fftools/ffmpeg_demux: forward errors from dump_attachment() instead of aborting Also, check the return code of avio_close(). --- fftools/ffmpeg_demux.c | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/fftools/ffmpeg_demux.c b/fftools/ffmpeg_demux.c index 40bbfa0c0eb..498830098d4 100644 --- a/fftools/ffmpeg_demux.c +++ b/fftools/ffmpeg_demux.c @@ -1259,7 +1259,7 @@ static void ist_add(const OptionsContext *o, Demuxer *d, AVStream *st) ist->codec_desc = avcodec_descriptor_get(ist->par->codec_id); } -static void dump_attachment(InputStream *ist, const char *filename) +static int dump_attachment(InputStream *ist, const char *filename) { AVStream *st = ist->st; int ret; @@ -1268,13 +1268,13 @@ static void dump_attachment(InputStream *ist, const char *filename) if (!st->codecpar->extradata_size) { av_log(ist, AV_LOG_WARNING, "No extradata to dump.\n"); - return; + return 0; } if (!*filename && (e = av_dict_get(st->metadata, "filename", NULL, 0))) filename = e->value; if (!*filename) { av_log(ist, AV_LOG_FATAL, "No filename specified and no 'filename' tag"); - exit_program(1); + return AVERROR(EINVAL); } assert_file_overwrite(filename); @@ -1282,11 +1282,13 @@ static void dump_attachment(InputStream *ist, const char *filename) if ((ret = avio_open2(&out, filename, AVIO_FLAG_WRITE, &int_cb, NULL)) < 0) { av_log(ist, AV_LOG_FATAL, "Could not open file %s for writing.\n", filename); - exit_program(1); + return ret; } avio_write(out, st->codecpar->extradata, st->codecpar->extradata_size); - avio_close(out); + ret = avio_close(out); + + return ret; } static const char *input_file_item_name(void *obj) @@ -1617,8 +1619,11 @@ int ifile_open(const OptionsContext *o, const char *filename) for (j = 0; j < f->nb_streams; j++) { InputStream *ist = f->streams[j]; - if (check_stream_specifier(ic, ist->st, o->dump_attachment[i].specifier) == 1) - dump_attachment(ist, o->dump_attachment[i].u.str); + if (check_stream_specifier(ic, ist->st, o->dump_attachment[i].specifier) == 1) { + ret = dump_attachment(ist, o->dump_attachment[i].u.str); + if (ret < 0) + return ret; + } } } From 2d59873fc1b3ebdeaf4bae1e0db1e37bd3d0902f Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Wed, 12 Jul 2023 13:00:16 +0200 Subject: [PATCH 1850/2172] fftools/ffmpeg_demux: add logging for -dump_attachment Makes it more clear what was written where. --- fftools/ffmpeg_demux.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/fftools/ffmpeg_demux.c b/fftools/ffmpeg_demux.c index 498830098d4..ab99daf9f80 100644 --- a/fftools/ffmpeg_demux.c +++ b/fftools/ffmpeg_demux.c @@ -1288,6 +1288,10 @@ static int dump_attachment(InputStream *ist, const char *filename) avio_write(out, st->codecpar->extradata, st->codecpar->extradata_size); ret = avio_close(out); + if (ret >= 0) + av_log(ist, AV_LOG_INFO, "Wrote attachment (%d bytes) to '%s'\n", + st->codecpar->extradata_size, filename); + return ret; } From cce294638b781cb1ba772268e4059dc27e1e5554 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Wed, 12 Jul 2023 13:09:14 +0200 Subject: [PATCH 1851/2172] fftools/ffmpeg: return errors from assert_file_overwrite() instead of aborting --- fftools/ffmpeg.h | 2 +- fftools/ffmpeg_demux.c | 4 +++- fftools/ffmpeg_mux_init.c | 11 ++++++++--- fftools/ffmpeg_opt.c | 12 +++++++----- 4 files changed, 19 insertions(+), 10 deletions(-) diff --git a/fftools/ffmpeg.h b/fftools/ffmpeg.h index 3201163a4ff..30020cd0f84 100644 --- a/fftools/ffmpeg.h +++ b/fftools/ffmpeg.h @@ -700,7 +700,7 @@ void show_usage(void); void remove_avoptions(AVDictionary **a, AVDictionary *b); void assert_avoptions(AVDictionary *m); -void assert_file_overwrite(const char *filename); +int assert_file_overwrite(const char *filename); char *file_read(const char *filename); AVDictionary *strip_specifiers(const AVDictionary *dict); const AVCodec *find_codec_or_die(void *logctx, const char *name, diff --git a/fftools/ffmpeg_demux.c b/fftools/ffmpeg_demux.c index ab99daf9f80..bc915178ec5 100644 --- a/fftools/ffmpeg_demux.c +++ b/fftools/ffmpeg_demux.c @@ -1277,7 +1277,9 @@ static int dump_attachment(InputStream *ist, const char *filename) return AVERROR(EINVAL); } - assert_file_overwrite(filename); + ret = assert_file_overwrite(filename); + if (ret < 0) + return ret; if ((ret = avio_open2(&out, filename, AVIO_FLAG_WRITE, &int_cb, NULL)) < 0) { av_log(ist, AV_LOG_FATAL, "Could not open file %s for writing.\n", diff --git a/fftools/ffmpeg_mux_init.c b/fftools/ffmpeg_mux_init.c index 8a3e7b98cf8..4d40ceda051 100644 --- a/fftools/ffmpeg_mux_init.c +++ b/fftools/ffmpeg_mux_init.c @@ -2442,7 +2442,9 @@ int of_open(const OptionsContext *o, const char *filename) if (!(oc->oformat->flags & AVFMT_NOFILE)) { /* test if it already exists to avoid losing precious files */ - assert_file_overwrite(filename); + err = assert_file_overwrite(filename); + if (err < 0) + return err; /* open the file */ if ((err = avio_open2(&oc->pb, filename, AVIO_FLAG_WRITE, @@ -2452,8 +2454,11 @@ int of_open(const OptionsContext *o, const char *filename) filename, av_err2str(err)); return err; } - } else if (strcmp(oc->oformat->name, "image2")==0 && !av_filename_number_test(filename)) - assert_file_overwrite(filename); + } else if (strcmp(oc->oformat->name, "image2")==0 && !av_filename_number_test(filename)) { + err = assert_file_overwrite(filename); + if (err < 0) + return err; + } if (o->mux_preload) { av_dict_set_int(&mux->opts, "preload", o->mux_preload*AV_TIME_BASE, 0); diff --git a/fftools/ffmpeg_opt.c b/fftools/ffmpeg_opt.c index 7f22b22604b..300f042660a 100644 --- a/fftools/ffmpeg_opt.c +++ b/fftools/ffmpeg_opt.c @@ -652,13 +652,13 @@ const AVCodec *find_codec_or_die(void *logctx, const char *name, return codec; } -void assert_file_overwrite(const char *filename) +int assert_file_overwrite(const char *filename) { const char *proto_name = avio_find_protocol_name(filename); if (file_overwrite && no_file_overwrite) { fprintf(stderr, "Error, both -y and -n supplied. Exiting.\n"); - exit_program(1); + return AVERROR(EINVAL); } if (!file_overwrite) { @@ -670,13 +670,13 @@ void assert_file_overwrite(const char *filename) signal(SIGINT, SIG_DFL); if (!read_yesno()) { av_log(NULL, AV_LOG_FATAL, "Not overwriting - exiting\n"); - exit_program(1); + return AVERROR_EXIT; } term_init(); } else { av_log(NULL, AV_LOG_FATAL, "File '%s' already exists. Exiting.\n", filename); - exit_program(1); + return AVERROR_EXIT; } } } @@ -689,10 +689,12 @@ void assert_file_overwrite(const char *filename) if (!strcmp(filename, file->ctx->url)) { av_log(NULL, AV_LOG_FATAL, "Output %s same as Input #%d - exiting\n", filename, i); av_log(NULL, AV_LOG_WARNING, "FFmpeg cannot edit existing files in-place.\n"); - exit_program(1); + return AVERROR(EINVAL); } } } + + return 0; } /* read file contents into a string */ From c23cff5a8a963fbf8763816f52a19c00cae01de6 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Wed, 12 Jul 2023 13:09:14 +0200 Subject: [PATCH 1852/2172] fftools/ffmpeg_demux: return errors from ist_add() instead of aborting --- fftools/ffmpeg_demux.c | 70 ++++++++++++++++++++++++++---------------- 1 file changed, 43 insertions(+), 27 deletions(-) diff --git a/fftools/ffmpeg_demux.c b/fftools/ffmpeg_demux.c index bc915178ec5..9e7f13a2b4d 100644 --- a/fftools/ffmpeg_demux.c +++ b/fftools/ffmpeg_demux.c @@ -964,8 +964,8 @@ static int guess_input_channel_layout(InputStream *ist, int guess_layout_max) return 1; } -static void add_display_matrix_to_stream(const OptionsContext *o, - AVFormatContext *ctx, InputStream *ist) +static int add_display_matrix_to_stream(const OptionsContext *o, + AVFormatContext *ctx, InputStream *ist) { AVStream *st = ist->st; double rotation = DBL_MAX; @@ -982,12 +982,12 @@ static void add_display_matrix_to_stream(const OptionsContext *o, vflip_set = vflip != -1; if (!rotation_set && !hflip_set && !vflip_set) - return; + return 0; buf = (int32_t *)av_stream_new_side_data(st, AV_PKT_DATA_DISPLAYMATRIX, sizeof(int32_t) * 9); if (!buf) { av_log(ist, AV_LOG_FATAL, "Failed to generate a display matrix!\n"); - exit_program(1); + return AVERROR(ENOMEM); } av_display_rotation_set(buf, @@ -996,6 +996,8 @@ static void add_display_matrix_to_stream(const OptionsContext *o, av_display_matrix_flip(buf, hflip_set ? hflip : 0, vflip_set ? vflip : 0); + + return 0; } static const char *input_stream_item_name(void *obj) @@ -1031,7 +1033,7 @@ static DemuxStream *demux_stream_alloc(Demuxer *d, AVStream *st) return ds; } -static void ist_add(const OptionsContext *o, Demuxer *d, AVStream *st) +static int ist_add(const OptionsContext *o, Demuxer *d, AVStream *st) { AVFormatContext *ic = d->f.ctx; AVCodecParameters *par = st->codecpar; @@ -1079,7 +1081,9 @@ static void ist_add(const OptionsContext *o, Demuxer *d, AVStream *st) } if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) { - add_display_matrix_to_stream(o, ic, ist); + ret = add_display_matrix_to_stream(o, ic, ist); + if (ret < 0) + return ret; MATCH_PER_STREAM_OPT(hwaccels, str, hwaccel, ic, st); MATCH_PER_STREAM_OPT(hwaccel_output_formats, str, @@ -1137,7 +1141,7 @@ static void ist_add(const OptionsContext *o, Demuxer *d, AVStream *st) av_log(ist, AV_LOG_FATAL, "%s ", av_hwdevice_get_type_name(type)); av_log(ist, AV_LOG_FATAL, "\n"); - exit_program(1); + return AVERROR(EINVAL); } } } @@ -1146,7 +1150,7 @@ static void ist_add(const OptionsContext *o, Demuxer *d, AVStream *st) if (hwaccel_device) { ist->hwaccel_device = av_strdup(hwaccel_device); if (!ist->hwaccel_device) - report_and_exit(AVERROR(ENOMEM)); + return AVERROR(ENOMEM); } } @@ -1165,20 +1169,22 @@ static void ist_add(const OptionsContext *o, Demuxer *d, AVStream *st) (o->data_disable && ist->st->codecpar->codec_type == AVMEDIA_TYPE_DATA)) ist->user_set_discard = AVDISCARD_ALL; - if (discard_str && av_opt_eval_int(&cc, discard_opt, discard_str, &ist->user_set_discard) < 0) { - av_log(ist, AV_LOG_ERROR, "Error parsing discard %s.\n", - discard_str); - exit_program(1); + if (discard_str) { + ret = av_opt_eval_int(&cc, discard_opt, discard_str, &ist->user_set_discard); + if (ret < 0) { + av_log(ist, AV_LOG_ERROR, "Error parsing discard %s.\n", discard_str); + return ret; + } } ist->dec_ctx = avcodec_alloc_context3(ist->dec); if (!ist->dec_ctx) - report_and_exit(AVERROR(ENOMEM)); + return AVERROR(ENOMEM); ret = avcodec_parameters_to_context(ist->dec_ctx, par); if (ret < 0) { av_log(ist, AV_LOG_ERROR, "Error initializing the decoder context.\n"); - exit_program(1); + return ret; } if (o->bitexact) @@ -1187,11 +1193,13 @@ static void ist_add(const OptionsContext *o, Demuxer *d, AVStream *st) switch (par->codec_type) { case AVMEDIA_TYPE_VIDEO: MATCH_PER_STREAM_OPT(frame_rates, str, framerate, ic, st); - if (framerate && av_parse_video_rate(&ist->framerate, - framerate) < 0) { - av_log(ist, AV_LOG_ERROR, "Error parsing framerate %s.\n", - framerate); - exit_program(1); + if (framerate) { + ret = av_parse_video_rate(&ist->framerate, framerate); + if (ret < 0) { + av_log(ist, AV_LOG_ERROR, "Error parsing framerate %s.\n", + framerate); + return ret; + } } ist->top_field_first = -1; @@ -1211,10 +1219,13 @@ static void ist_add(const OptionsContext *o, Demuxer *d, AVStream *st) char *canvas_size = NULL; MATCH_PER_STREAM_OPT(fix_sub_duration, i, ist->fix_sub_duration, ic, st); MATCH_PER_STREAM_OPT(canvas_sizes, str, canvas_size, ic, st); - if (canvas_size && - av_parse_video_size(&ist->dec_ctx->width, &ist->dec_ctx->height, canvas_size) < 0) { - av_log(ist, AV_LOG_FATAL, "Invalid canvas size: %s.\n", canvas_size); - exit_program(1); + if (canvas_size) { + ret = av_parse_video_size(&ist->dec_ctx->width, &ist->dec_ctx->height, + canvas_size); + if (ret < 0) { + av_log(ist, AV_LOG_FATAL, "Invalid canvas size: %s.\n", canvas_size); + return ret; + } } /* Compute the size of the canvas for the subtitles stream. @@ -1248,15 +1259,17 @@ static void ist_add(const OptionsContext *o, Demuxer *d, AVStream *st) ist->par = avcodec_parameters_alloc(); if (!ist->par) - report_and_exit(AVERROR(ENOMEM)); + return AVERROR(ENOMEM); ret = avcodec_parameters_from_context(ist->par, ist->dec_ctx); if (ret < 0) { av_log(ist, AV_LOG_ERROR, "Error initializing the decoder context.\n"); - exit_program(1); + return ret; } ist->codec_desc = avcodec_descriptor_get(ist->par->codec_id); + + return 0; } static int dump_attachment(InputStream *ist, const char *filename) @@ -1579,8 +1592,11 @@ int ifile_open(const OptionsContext *o, const char *filename) d->thread_queue_size = o->thread_queue_size; /* Add all the streams from the given input file to the demuxer */ - for (int i = 0; i < ic->nb_streams; i++) - ist_add(o, d, ic->streams[i]); + for (int i = 0; i < ic->nb_streams; i++) { + ret = ist_add(o, d, ic->streams[i]); + if (ret < 0) + return ret; + } /* dump the file content */ av_dump_format(ic, f->index, filename, 0); From b3eedca5e5501f27acaa5e1b0c87804922754e39 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Wed, 12 Jul 2023 13:22:10 +0200 Subject: [PATCH 1853/2172] fftools/ffmpeg_mux_init: return errors from create_streams() instead of aborting --- fftools/ffmpeg_mux_init.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/fftools/ffmpeg_mux_init.c b/fftools/ffmpeg_mux_init.c index 4d40ceda051..dbc58abea87 100644 --- a/fftools/ffmpeg_mux_init.c +++ b/fftools/ffmpeg_mux_init.c @@ -1558,7 +1558,7 @@ static void of_add_attachments(Muxer *mux, const OptionsContext *o) } } -static void create_streams(Muxer *mux, const OptionsContext *o) +static int create_streams(Muxer *mux, const OptionsContext *o) { AVFormatContext *oc = mux->fc; int auto_disable_v = o->video_disable; @@ -1616,8 +1616,10 @@ static void create_streams(Muxer *mux, const OptionsContext *o) if (!oc->nb_streams && !(oc->oformat->flags & AVFMT_NOSTREAMS)) { av_dump_format(oc, nb_output_files - 1, oc->url, 1); av_log(mux, AV_LOG_ERROR, "Output file does not contain any stream\n"); - exit_program(1); + return AVERROR(EINVAL); } + + return 0; } static int setup_sync_queues(Muxer *mux, AVFormatContext *oc, int64_t buf_size_us) @@ -2426,7 +2428,9 @@ int of_open(const OptionsContext *o, const char *filename) } /* create all output streams for this file */ - create_streams(mux, o); + err = create_streams(mux, o); + if (err < 0) + return err; /* check if all codec options have been used */ validate_enc_avopt(mux, o->g->codec_opts); From eee09cdf39136da206366e4ba26af4f62a4e957c Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Wed, 12 Jul 2023 13:22:10 +0200 Subject: [PATCH 1854/2172] fftools/ffmpeg_mux_init: improve error handling in of_add_attachments() * return error codes instead of aborting * avoid leaking the AVIOContext on failure * check the return code of avio_read() --- fftools/ffmpeg_mux_init.c | 44 +++++++++++++++++++++++++++++++-------- 1 file changed, 35 insertions(+), 9 deletions(-) diff --git a/fftools/ffmpeg_mux_init.c b/fftools/ffmpeg_mux_init.c index dbc58abea87..47b6f826b62 100644 --- a/fftools/ffmpeg_mux_init.c +++ b/fftools/ffmpeg_mux_init.c @@ -1514,7 +1514,7 @@ static void map_manual(Muxer *mux, const OptionsContext *o, const StreamMap *map } } -static void of_add_attachments(Muxer *mux, const OptionsContext *o) +static int of_add_attachments(Muxer *mux, const OptionsContext *o) { OutputStream *ost; int err; @@ -1528,20 +1528,42 @@ static void of_add_attachments(Muxer *mux, const OptionsContext *o) if ((err = avio_open2(&pb, o->attachments[i], AVIO_FLAG_READ, &int_cb, NULL)) < 0) { av_log(mux, AV_LOG_FATAL, "Could not open attachment file %s.\n", o->attachments[i]); - exit_program(1); + return err; } if ((len = avio_size(pb)) <= 0) { av_log(mux, AV_LOG_FATAL, "Could not get size of the attachment %s.\n", o->attachments[i]); - exit_program(1); + err = len ? len : AVERROR_INVALIDDATA; + goto read_fail; } - if (len > INT_MAX - AV_INPUT_BUFFER_PADDING_SIZE || - !(attachment = av_malloc(len + AV_INPUT_BUFFER_PADDING_SIZE))) { + if (len > INT_MAX - AV_INPUT_BUFFER_PADDING_SIZE) { av_log(mux, AV_LOG_FATAL, "Attachment %s too large.\n", o->attachments[i]); - exit_program(1); + err = AVERROR(ERANGE); + goto read_fail; + } + + attachment = av_malloc(len + AV_INPUT_BUFFER_PADDING_SIZE); + if (!attachment) { + err = AVERROR(ENOMEM); + goto read_fail; } - avio_read(pb, attachment, len); + + err = avio_read(pb, attachment, len); + if (err < 0) + av_log(mux, AV_LOG_FATAL, "Error reading attachment file %s: %s\n", + o->attachments[i], av_err2str(err)); + else if (err != len) { + av_log(mux, AV_LOG_FATAL, "Could not read all %"PRId64" bytes for " + "attachment file %s\n", len, o->attachments[i]); + err = AVERROR(EIO); + } + +read_fail: + avio_closep(&pb); + if (err < 0) + return err; + memset(attachment + len, 0, AV_INPUT_BUFFER_PADDING_SIZE); av_log(mux, AV_LOG_VERBOSE, "Creating attachment stream from file %s\n", @@ -1554,8 +1576,9 @@ static void of_add_attachments(Muxer *mux, const OptionsContext *o) p = strrchr(o->attachments[i], '/'); av_dict_set(&ost->st->metadata, "filename", (p && *p) ? p + 1 : o->attachments[i], AV_DICT_DONT_OVERWRITE); - avio_closep(&pb); } + + return 0; } static int create_streams(Muxer *mux, const OptionsContext *o) @@ -1565,6 +1588,7 @@ static int create_streams(Muxer *mux, const OptionsContext *o) int auto_disable_a = o->audio_disable; int auto_disable_s = o->subtitle_disable; int auto_disable_d = o->data_disable; + int ret; /* create streams for all unlabeled output pads */ for (int i = 0; i < nb_filtergraphs; i++) { @@ -1611,7 +1635,9 @@ static int create_streams(Muxer *mux, const OptionsContext *o) map_manual(mux, o, &o->stream_maps[i]); } - of_add_attachments(mux, o); + ret = of_add_attachments(mux, o); + if (ret < 0) + return ret; if (!oc->nb_streams && !(oc->oformat->flags & AVFMT_NOSTREAMS)) { av_dump_format(oc, nb_output_files - 1, oc->url, 1); From 4e366100e9326427106ce34fd06c6728ae4201c1 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Wed, 12 Jul 2023 13:22:10 +0200 Subject: [PATCH 1855/2172] fftools/ffmpeg_mux_init: return error codes from map_*() instead of aborting --- fftools/ffmpeg_mux_init.c | 92 +++++++++++++++++++++++---------------- 1 file changed, 55 insertions(+), 37 deletions(-) diff --git a/fftools/ffmpeg_mux_init.c b/fftools/ffmpeg_mux_init.c index 47b6f826b62..8e640610cd8 100644 --- a/fftools/ffmpeg_mux_init.c +++ b/fftools/ffmpeg_mux_init.c @@ -1297,7 +1297,7 @@ static OutputStream *ost_add(Muxer *mux, const OptionsContext *o, return ost; } -static void map_auto_video(Muxer *mux, const OptionsContext *o) +static int map_auto_video(Muxer *mux, const OptionsContext *o) { AVFormatContext *oc = mux->fc; InputStream *best_ist = NULL; @@ -1306,7 +1306,7 @@ static void map_auto_video(Muxer *mux, const OptionsContext *o) /* video: highest resolution */ if (av_guess_codec(oc->oformat, NULL, oc->url, NULL, AVMEDIA_TYPE_VIDEO) == AV_CODEC_ID_NONE) - return; + return 0; qcr = avformat_query_codec(oc->oformat, oc->oformat->video_codec, 0); for (int j = 0; j < nb_input_files; j++) { @@ -1346,9 +1346,11 @@ static void map_auto_video(Muxer *mux, const OptionsContext *o) } if (best_ist) ost_add(mux, o, AVMEDIA_TYPE_VIDEO, best_ist, NULL); + + return 0; } -static void map_auto_audio(Muxer *mux, const OptionsContext *o) +static int map_auto_audio(Muxer *mux, const OptionsContext *o) { AVFormatContext *oc = mux->fc; InputStream *best_ist = NULL; @@ -1356,7 +1358,7 @@ static void map_auto_audio(Muxer *mux, const OptionsContext *o) /* audio: most channels */ if (av_guess_codec(oc->oformat, NULL, oc->url, NULL, AVMEDIA_TYPE_AUDIO) == AV_CODEC_ID_NONE) - return; + return 0; for (int j = 0; j < nb_input_files; j++) { InputFile *ifile = input_files[j]; @@ -1388,9 +1390,11 @@ static void map_auto_audio(Muxer *mux, const OptionsContext *o) } if (best_ist) ost_add(mux, o, AVMEDIA_TYPE_AUDIO, best_ist, NULL); + + return 0; } -static void map_auto_subtitle(Muxer *mux, const OptionsContext *o) +static int map_auto_subtitle(Muxer *mux, const OptionsContext *o) { AVFormatContext *oc = mux->fc; char *subtitle_codec_name = NULL; @@ -1398,7 +1402,7 @@ static void map_auto_subtitle(Muxer *mux, const OptionsContext *o) /* subtitles: pick first */ MATCH_PER_TYPE_OPT(codec_names, str, subtitle_codec_name, oc, "s"); if (!avcodec_find_encoder(oc->oformat->subtitle_codec) && !subtitle_codec_name) - return; + return 0; for (InputStream *ist = ist_iter(NULL); ist; ist = ist_iter(ist)) if (ist->st->codecpar->codec_type == AVMEDIA_TYPE_SUBTITLE) { @@ -1426,16 +1430,18 @@ static void map_auto_subtitle(Muxer *mux, const OptionsContext *o) break; } } + + return 0; } -static void map_auto_data(Muxer *mux, const OptionsContext *o) +static int map_auto_data(Muxer *mux, const OptionsContext *o) { AVFormatContext *oc = mux->fc; /* Data only if codec id match */ enum AVCodecID codec_id = av_guess_codec(oc->oformat, NULL, oc->url, NULL, AVMEDIA_TYPE_DATA); if (codec_id == AV_CODEC_ID_NONE) - return; + return 0; for (InputStream *ist = ist_iter(NULL); ist; ist = ist_iter(ist)) { if (ist->user_set_discard == AVDISCARD_ALL) @@ -1444,14 +1450,16 @@ static void map_auto_data(Muxer *mux, const OptionsContext *o) ist->st->codecpar->codec_id == codec_id ) ost_add(mux, o, AVMEDIA_TYPE_DATA, ist, NULL); } + + return 0; } -static void map_manual(Muxer *mux, const OptionsContext *o, const StreamMap *map) +static int map_manual(Muxer *mux, const OptionsContext *o, const StreamMap *map) { InputStream *ist; if (map->disabled) - return; + return 0; if (map->linklabel) { FilterGraph *fg; @@ -1472,7 +1480,7 @@ static void map_manual(Muxer *mux, const OptionsContext *o, const StreamMap *map if (!ofilter) { av_log(mux, AV_LOG_FATAL, "Output with label '%s' does not exist " "in any defined filter graph, or was already used elsewhere.\n", map->linklabel); - exit_program(1); + return AVERROR(EINVAL); } av_log(mux, AV_LOG_VERBOSE, "Creating output stream from an explicitly " @@ -1484,16 +1492,16 @@ static void map_manual(Muxer *mux, const OptionsContext *o, const StreamMap *map if (ist->user_set_discard == AVDISCARD_ALL) { av_log(mux, AV_LOG_FATAL, "Stream #%d:%d is disabled and cannot be mapped.\n", map->file_index, map->stream_index); - exit_program(1); + return AVERROR(EINVAL); } if(o->subtitle_disable && ist->st->codecpar->codec_type == AVMEDIA_TYPE_SUBTITLE) - return; + return 0; if(o-> audio_disable && ist->st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) - return; + return 0; if(o-> video_disable && ist->st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) - return; + return 0; if(o-> data_disable && ist->st->codecpar->codec_type == AVMEDIA_TYPE_DATA) - return; + return 0; if (ist->st->codecpar->codec_type == AVMEDIA_TYPE_UNKNOWN && !copy_unknown_streams) { @@ -1505,13 +1513,15 @@ static void map_manual(Muxer *mux, const OptionsContext *o, const StreamMap *map "If you want unsupported types ignored instead " "of failing, please use the -ignore_unknown option\n" "If you want them copied, please use -copy_unknown\n"); - exit_program(1); + return AVERROR(EINVAL); } - return; + return 0; } ost_add(mux, o, ist->st->codecpar->codec_type, ist, NULL); } + + return 0; } static int of_add_attachments(Muxer *mux, const OptionsContext *o) @@ -1583,11 +1593,21 @@ static int of_add_attachments(Muxer *mux, const OptionsContext *o) static int create_streams(Muxer *mux, const OptionsContext *o) { + static const int (*map_func[])(Muxer *mux, const OptionsContext *o) = { + [AVMEDIA_TYPE_VIDEO] = map_auto_video, + [AVMEDIA_TYPE_AUDIO] = map_auto_audio, + [AVMEDIA_TYPE_SUBTITLE] = map_auto_subtitle, + [AVMEDIA_TYPE_DATA] = map_auto_data, + }; + AVFormatContext *oc = mux->fc; - int auto_disable_v = o->video_disable; - int auto_disable_a = o->audio_disable; - int auto_disable_s = o->subtitle_disable; - int auto_disable_d = o->data_disable; + + int auto_disable = + o->video_disable * (1 << AVMEDIA_TYPE_VIDEO) | + o->audio_disable * (1 << AVMEDIA_TYPE_AUDIO) | + o->subtitle_disable * (1 << AVMEDIA_TYPE_SUBTITLE) | + o->data_disable * (1 << AVMEDIA_TYPE_DATA); + int ret; /* create streams for all unlabeled output pads */ @@ -1599,11 +1619,7 @@ static int create_streams(Muxer *mux, const OptionsContext *o) if (ofilter->linklabel || ofilter->ost) continue; - switch (ofilter->type) { - case AVMEDIA_TYPE_VIDEO: auto_disable_v = 1; break; - case AVMEDIA_TYPE_AUDIO: auto_disable_a = 1; break; - case AVMEDIA_TYPE_SUBTITLE: auto_disable_s = 1; break; - } + auto_disable |= 1 << ofilter->type; av_log(mux, AV_LOG_VERBOSE, "Creating output stream from unlabeled " "output of complex filtergraph %d.", fg->index); @@ -1620,19 +1636,21 @@ static int create_streams(Muxer *mux, const OptionsContext *o) av_log(mux, AV_LOG_VERBOSE, "No explicit maps, mapping streams automatically...\n"); /* pick the "best" stream of each type */ - if (!auto_disable_v) - map_auto_video(mux, o); - if (!auto_disable_a) - map_auto_audio(mux, o); - if (!auto_disable_s) - map_auto_subtitle(mux, o); - if (!auto_disable_d) - map_auto_data(mux, o); + for (int i = 0; i < FF_ARRAY_ELEMS(map_func); i++) { + if (!map_func[i] || auto_disable & (1 << i)) + continue; + ret = map_func[i](mux, o); + if (ret < 0) + return ret; + } } else { av_log(mux, AV_LOG_VERBOSE, "Adding streams from explicit maps...\n"); - for (int i = 0; i < o->nb_stream_maps; i++) - map_manual(mux, o, &o->stream_maps[i]); + for (int i = 0; i < o->nb_stream_maps; i++) { + ret = map_manual(mux, o, &o->stream_maps[i]); + if (ret < 0) + return ret; + } } ret = of_add_attachments(mux, o); From 38a2fc2c291efd3f0e09941c5c0a43805a9b2cd2 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Wed, 12 Jul 2023 16:22:43 +0200 Subject: [PATCH 1856/2172] fftools/ffmpeg_mux_init: move allocation out of prologue ost_add() has a very large variable declaration prologue, performing "active" actions that can fail in there is confusing. --- fftools/ffmpeg_mux_init.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/fftools/ffmpeg_mux_init.c b/fftools/ffmpeg_mux_init.c index 8e640610cd8..bd4c0a9f976 100644 --- a/fftools/ffmpeg_mux_init.c +++ b/fftools/ffmpeg_mux_init.c @@ -987,13 +987,14 @@ static OutputStream *ost_add(Muxer *mux, const OptionsContext *o, MuxStream *ms; OutputStream *ost; const AVCodec *enc; - AVStream *st = avformat_new_stream(oc, NULL); + AVStream *st; int ret = 0; const char *bsfs = NULL, *time_base = NULL; char *filters = NULL, *next, *codec_tag = NULL; double qscale = -1; int i; + st = avformat_new_stream(oc, NULL); if (!st) report_and_exit(AVERROR(ENOMEM)); From 54cbe6f57d8e32e0481b886d9a1ce7c40f37731f Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Wed, 12 Jul 2023 16:40:19 +0200 Subject: [PATCH 1857/2172] fftools/ffmpeg_mux_init: return error codes from ost_add() instead of aborting --- fftools/ffmpeg_mux_init.c | 88 +++++++++++++++++++++++---------------- 1 file changed, 53 insertions(+), 35 deletions(-) diff --git a/fftools/ffmpeg_mux_init.c b/fftools/ffmpeg_mux_init.c index bd4c0a9f976..8ad799f9514 100644 --- a/fftools/ffmpeg_mux_init.c +++ b/fftools/ffmpeg_mux_init.c @@ -979,9 +979,9 @@ static int streamcopy_init(const Muxer *mux, OutputStream *ost) return ret; } -static OutputStream *ost_add(Muxer *mux, const OptionsContext *o, - enum AVMediaType type, InputStream *ist, - OutputFilter *ofilter) +static int ost_add(Muxer *mux, const OptionsContext *o, enum AVMediaType type, + InputStream *ist, OutputFilter *ofilter, + OutputStream **post) { AVFormatContext *oc = mux->fc; MuxStream *ms; @@ -996,7 +996,7 @@ static OutputStream *ost_add(Muxer *mux, const OptionsContext *o, st = avformat_new_stream(oc, NULL); if (!st) - report_and_exit(AVERROR(ENOMEM)); + return AVERROR(ENOMEM); if (oc->nb_streams - 1 < o->nb_streamid_map) st->id = o->streamid_map[oc->nb_streams - 1]; @@ -1006,11 +1006,11 @@ static OutputStream *ost_add(Muxer *mux, const OptionsContext *o, ost->par_in = avcodec_parameters_alloc(); if (!ost->par_in) - report_and_exit(AVERROR(ENOMEM)); + return AVERROR(ENOMEM); ms->muxing_queue = av_fifo_alloc2(8, sizeof(AVPacket*), 0); if (!ms->muxing_queue) - report_and_exit(AVERROR(ENOMEM)); + return AVERROR(ENOMEM); ms->last_mux_dts = AV_NOPTS_VALUE; ost->st = st; @@ -1022,17 +1022,17 @@ static OutputStream *ost_add(Muxer *mux, const OptionsContext *o, ret = choose_encoder(o, oc, ost, &enc); if (ret < 0) { av_log(ost, AV_LOG_FATAL, "Error selecting an encoder\n"); - exit_program(1); + return ret; } if (enc) { ost->enc_ctx = avcodec_alloc_context3(enc); if (!ost->enc_ctx) - report_and_exit(AVERROR(ENOMEM)); + return AVERROR(ENOMEM); ret = enc_alloc(&ost->enc, enc); if (ret < 0) - report_and_exit(ret); + return ret; av_strlcat(ms->log_name, "/", sizeof(ms->log_name)); av_strlcat(ms->log_name, enc->name, sizeof(ms->log_name)); @@ -1042,7 +1042,7 @@ static OutputStream *ost_add(Muxer *mux, const OptionsContext *o, "Streamcopy requested for output stream fed " "from a complex filtergraph. Filtering and streamcopy " "cannot be used together.\n"); - exit_program(1); + return AVERROR(EINVAL); } av_strlcat(ms->log_name, "/copy", sizeof(ms->log_name)); @@ -1063,7 +1063,7 @@ static OutputStream *ost_add(Muxer *mux, const OptionsContext *o, ms->pkt = av_packet_alloc(); if (!ms->pkt) - report_and_exit(AVERROR(ENOMEM)); + return AVERROR(ENOMEM); if (ost->enc_ctx) { AVCodecContext *enc = ost->enc_ctx; @@ -1088,7 +1088,8 @@ static OutputStream *ost_add(Muxer *mux, const OptionsContext *o, continue; if (!(arg = strchr(buf, '='))) { av_log(ost, AV_LOG_FATAL, "Invalid line found in the preset file.\n"); - exit_program(1); + ret = AVERROR(EINVAL); + break; } *arg++ = 0; av_dict_set(&ost->encoder_opts, buf, arg, AV_DICT_DONT_OVERWRITE); @@ -1099,7 +1100,7 @@ static OutputStream *ost_add(Muxer *mux, const OptionsContext *o, if (ret) { av_log(ost, AV_LOG_FATAL, "Preset %s specified, but could not be opened.\n", preset); - exit_program(1); + return ret; } MATCH_PER_STREAM_OPT(enc_stats_pre, str, enc_stats_pre, oc, st); @@ -1111,7 +1112,7 @@ static OutputStream *ost_add(Muxer *mux, const OptionsContext *o, ret = enc_stats_init(ost, &ost->enc_stats_pre, 1, enc_stats_pre, format); if (ret < 0) - exit_program(1); + return ret; } MATCH_PER_STREAM_OPT(enc_stats_post, str, enc_stats_post, oc, st); @@ -1123,7 +1124,7 @@ static OutputStream *ost_add(Muxer *mux, const OptionsContext *o, ret = enc_stats_init(ost, &ost->enc_stats_post, 0, enc_stats_post, format); if (ret < 0) - exit_program(1); + return ret; } MATCH_PER_STREAM_OPT(mux_stats, str, mux_stats, oc, st); @@ -1135,7 +1136,7 @@ static OutputStream *ost_add(Muxer *mux, const OptionsContext *o, ret = enc_stats_init(ost, &ms->stats, 0, mux_stats, format); if (ret < 0) - exit_program(1); + return ret; } MATCH_PER_STREAM_OPT(enc_time_bases, str, enc_time_base, oc, st); @@ -1144,14 +1145,14 @@ static OutputStream *ost_add(Muxer *mux, const OptionsContext *o, if (av_parse_ratio(&q, enc_time_base, INT_MAX, 0, NULL) < 0 || q.den <= 0) { av_log(ost, AV_LOG_FATAL, "Invalid time base: %s\n", enc_time_base); - exit_program(1); + return AVERROR(EINVAL); } if (q.num < 0) { if (!ost->ist) { av_log(ost, AV_LOG_FATAL, "Cannot use input stream timebase for encoding - " "no input stream available\n"); - exit_program(1); + return AVERROR(EINVAL); } q = ost->ist->st->time_base; } @@ -1175,7 +1176,7 @@ static OutputStream *ost_add(Muxer *mux, const OptionsContext *o, if (av_parse_ratio(&q, time_base, INT_MAX, 0, NULL) < 0 || q.num <= 0 || q.den <= 0) { av_log(ost, AV_LOG_FATAL, "Invalid time base: %s\n", time_base); - exit_program(1); + return AVERROR(EINVAL); } st->time_base = q; } @@ -1198,7 +1199,7 @@ static OutputStream *ost_add(Muxer *mux, const OptionsContext *o, ret = av_bsf_list_parse_str(bsfs, &ms->bsf_ctx); if (ret < 0) { av_log(ost, AV_LOG_ERROR, "Error parsing bitstream filter sequence '%s': %s\n", bsfs, av_err2str(ret)); - exit_program(1); + return ret; } } @@ -1258,7 +1259,7 @@ static OutputStream *ost_add(Muxer *mux, const OptionsContext *o, if (type == AVMEDIA_TYPE_VIDEO || type == AVMEDIA_TYPE_AUDIO) { ret = ost_get_filters(o, oc, ost, &filters); if (ret < 0) - exit_program(1); + return ret; } if (ost->enc && @@ -1271,7 +1272,7 @@ static OutputStream *ost_add(Muxer *mux, const OptionsContext *o, if (ret < 0) { av_log(ost, AV_LOG_ERROR, "Error initializing a simple filtergraph\n"); - exit_program(1); + return ret; } } } else if (ost->ist) { @@ -1279,14 +1280,14 @@ static OutputStream *ost_add(Muxer *mux, const OptionsContext *o, if (ret < 0) { av_log(ost, AV_LOG_ERROR, "Error binding an input stream\n"); - exit_program(1); + return ret; } } if (ost->ist && !ost->enc) { ret = streamcopy_init(mux, ost); if (ret < 0) - exit_program(1); + return ret; } // copy estimated duration as a hint to the muxer @@ -1295,7 +1296,10 @@ static OutputStream *ost_add(Muxer *mux, const OptionsContext *o, ms->stream_duration_tb = ist->st->time_base; } - return ost; + if (post) + *post = ost; + + return 0; } static int map_auto_video(Muxer *mux, const OptionsContext *o) @@ -1346,7 +1350,7 @@ static int map_auto_video(Muxer *mux, const OptionsContext *o) } } if (best_ist) - ost_add(mux, o, AVMEDIA_TYPE_VIDEO, best_ist, NULL); + return ost_add(mux, o, AVMEDIA_TYPE_VIDEO, best_ist, NULL, NULL); return 0; } @@ -1390,7 +1394,7 @@ static int map_auto_audio(Muxer *mux, const OptionsContext *o) } } if (best_ist) - ost_add(mux, o, AVMEDIA_TYPE_AUDIO, best_ist, NULL); + return ost_add(mux, o, AVMEDIA_TYPE_AUDIO, best_ist, NULL, NULL); return 0; } @@ -1427,8 +1431,7 @@ static int map_auto_subtitle(Muxer *mux, const OptionsContext *o) input_descriptor && output_descriptor && (!input_descriptor->props || !output_descriptor->props)) { - ost_add(mux, o, AVMEDIA_TYPE_SUBTITLE, ist, NULL); - break; + return ost_add(mux, o, AVMEDIA_TYPE_SUBTITLE, ist, NULL, NULL); } } @@ -1448,8 +1451,11 @@ static int map_auto_data(Muxer *mux, const OptionsContext *o) if (ist->user_set_discard == AVDISCARD_ALL) continue; if (ist->st->codecpar->codec_type == AVMEDIA_TYPE_DATA && - ist->st->codecpar->codec_id == codec_id ) - ost_add(mux, o, AVMEDIA_TYPE_DATA, ist, NULL); + ist->st->codecpar->codec_id == codec_id) { + int ret = ost_add(mux, o, AVMEDIA_TYPE_DATA, ist, NULL, NULL); + if (ret < 0) + return ret; + } } return 0; @@ -1458,6 +1464,7 @@ static int map_auto_data(Muxer *mux, const OptionsContext *o) static int map_manual(Muxer *mux, const OptionsContext *o, const StreamMap *map) { InputStream *ist; + int ret; if (map->disabled) return 0; @@ -1487,7 +1494,9 @@ static int map_manual(Muxer *mux, const OptionsContext *o, const StreamMap *map) av_log(mux, AV_LOG_VERBOSE, "Creating output stream from an explicitly " "mapped complex filtergraph %d, output [%s]\n", fg->index, map->linklabel); - ost_add(mux, o, ofilter->type, NULL, ofilter); + ret = ost_add(mux, o, ofilter->type, NULL, ofilter, NULL); + if (ret < 0) + return ret; } else { ist = input_files[map->file_index]->streams[map->stream_index]; if (ist->user_set_discard == AVDISCARD_ALL) { @@ -1519,7 +1528,9 @@ static int map_manual(Muxer *mux, const OptionsContext *o, const StreamMap *map) return 0; } - ost_add(mux, o, ist->st->codecpar->codec_type, ist, NULL); + ret = ost_add(mux, o, ist->st->codecpar->codec_type, ist, NULL, NULL); + if (ret < 0) + return ret; } return 0; @@ -1580,7 +1591,12 @@ static int of_add_attachments(Muxer *mux, const OptionsContext *o) av_log(mux, AV_LOG_VERBOSE, "Creating attachment stream from file %s\n", o->attachments[i]); - ost = ost_add(mux, o, AVMEDIA_TYPE_ATTACHMENT, NULL, NULL); + err = ost_add(mux, o, AVMEDIA_TYPE_ATTACHMENT, NULL, NULL, &ost); + if (err < 0) { + av_freep(&attachment); + return err; + } + ost->attachment_filename = o->attachments[i]; ost->par_in->extradata = attachment; ost->par_in->extradata_size = len; @@ -1629,7 +1645,9 @@ static int create_streams(Muxer *mux, const OptionsContext *o) av_get_media_type_string(ofilter->type)); av_log(mux, AV_LOG_VERBOSE, "\n"); - ost_add(mux, o, ofilter->type, NULL, ofilter); + ret = ost_add(mux, o, ofilter->type, NULL, ofilter, NULL); + if (ret < 0) + return ret; } } From 6691d131d8132712942418f26f4da84bfbbf4077 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Wed, 12 Jul 2023 16:40:19 +0200 Subject: [PATCH 1858/2172] fftools/ffmpeg_mux_init: return error codes from copy_meta() instead of aborting --- fftools/ffmpeg_mux_init.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/fftools/ffmpeg_mux_init.c b/fftools/ffmpeg_mux_init.c index 8ad799f9514..f85357d8e47 100644 --- a/fftools/ffmpeg_mux_init.c +++ b/fftools/ffmpeg_mux_init.c @@ -2089,7 +2089,7 @@ static int copy_metadata(Muxer *mux, AVFormatContext *ic, return 0; } -static void copy_meta(Muxer *mux, const OptionsContext *o) +static int copy_meta(Muxer *mux, const OptionsContext *o) { OutputFile *of = &mux->of; AVFormatContext *oc = mux->fc; @@ -2106,7 +2106,7 @@ static void copy_meta(Muxer *mux, const OptionsContext *o) if (in_file_index >= nb_input_files) { av_log(mux, AV_LOG_FATAL, "Invalid input file index %d while " "processing metadata maps\n", in_file_index); - exit_program(1); + return AVERROR(EINVAL); } copy_metadata(mux, in_file_index >= 0 ? input_files[in_file_index]->ctx : NULL, @@ -2128,7 +2128,7 @@ static void copy_meta(Muxer *mux, const OptionsContext *o) } else { av_log(mux, AV_LOG_FATAL, "Invalid input file index %d in chapter mapping.\n", chapters_input_file); - exit_program(1); + return AVERROR(EINVAL); } } if (chapters_input_file >= 0) @@ -2157,6 +2157,8 @@ static void copy_meta(Muxer *mux, const OptionsContext *o) av_dict_set(&ost->st->metadata, "encoder", NULL, 0); } } + + return 0; } static int set_dispositions(Muxer *mux, const OptionsContext *o) @@ -2533,7 +2535,9 @@ int of_open(const OptionsContext *o, const char *filename) oc->max_delay = (int)(o->mux_max_delay * AV_TIME_BASE); /* copy metadata and chapters from input files */ - copy_meta(mux, o); + err = copy_meta(mux, o); + if (err < 0) + return err; of_add_programs(mux, o); of_add_metadata(of, oc, o); From 4e3557aadb07c0bd029894dfed850c9c5b1b17f7 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Wed, 12 Jul 2023 16:40:19 +0200 Subject: [PATCH 1859/2172] fftools/ffmpeg_mux_init: return error codes from parse_forced_key_frames() instead of aborting --- fftools/ffmpeg_mux_init.c | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/fftools/ffmpeg_mux_init.c b/fftools/ffmpeg_mux_init.c index f85357d8e47..7a8c9357953 100644 --- a/fftools/ffmpeg_mux_init.c +++ b/fftools/ffmpeg_mux_init.c @@ -2245,8 +2245,8 @@ static int compare_int64(const void *a, const void *b) return FFDIFFSIGN(*(const int64_t *)a, *(const int64_t *)b); } -static void parse_forced_key_frames(KeyframeForceCtx *kf, const Muxer *mux, - const char *spec) +static int parse_forced_key_frames(KeyframeForceCtx *kf, const Muxer *mux, + const char *spec) { const char *p; int n = 1, i, size, index = 0; @@ -2258,7 +2258,7 @@ static void parse_forced_key_frames(KeyframeForceCtx *kf, const Muxer *mux, size = n; pts = av_malloc_array(size, sizeof(*pts)); if (!pts) - report_and_exit(AVERROR(ENOMEM)); + return AVERROR(ENOMEM); p = spec; for (i = 0; i < n; i++) { @@ -2275,7 +2275,7 @@ static void parse_forced_key_frames(KeyframeForceCtx *kf, const Muxer *mux, if (nb_ch > INT_MAX - size || !(pts = av_realloc_f(pts, size += nb_ch - 1, sizeof(*pts)))) - report_and_exit(AVERROR(ENOMEM)); + return AVERROR(ENOMEM); t = p[8] ? parse_time_or_die("force_key_frames", p + 8, 1) : 0; for (j = 0; j < nb_ch; j++) { @@ -2297,6 +2297,8 @@ static void parse_forced_key_frames(KeyframeForceCtx *kf, const Muxer *mux, qsort(pts, size, sizeof(*pts), compare_int64); kf->nb_pts = size; kf->pts = pts; + + return 0; } static int process_forced_keyframes(Muxer *mux, const OptionsContext *o) @@ -2331,7 +2333,9 @@ static int process_forced_keyframes(Muxer *mux, const OptionsContext *o) } else if (!strcmp(forced_keyframes, "source_no_drop")) { ost->kf.type = KF_FORCE_SOURCE_NO_DROP; } else { - parse_forced_key_frames(&ost->kf, mux, forced_keyframes); + int ret = parse_forced_key_frames(&ost->kf, mux, forced_keyframes); + if (ret < 0) + return ret; } } From fd401971709b57dd946eb7fd1810e3d4b9bad61f Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Wed, 12 Jul 2023 16:40:19 +0200 Subject: [PATCH 1860/2172] fftools/ffmpeg_mux_init: return error codes from validate_enc_avopt() instead of aborting --- fftools/ffmpeg_mux_init.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/fftools/ffmpeg_mux_init.c b/fftools/ffmpeg_mux_init.c index 7a8c9357953..3a327048bb5 100644 --- a/fftools/ffmpeg_mux_init.c +++ b/fftools/ffmpeg_mux_init.c @@ -2342,7 +2342,7 @@ static int process_forced_keyframes(Muxer *mux, const OptionsContext *o) return 0; } -static void validate_enc_avopt(Muxer *mux, const AVDictionary *codec_avopt) +static int validate_enc_avopt(Muxer *mux, const AVDictionary *codec_avopt) { const AVClass *class = avcodec_get_class(); const AVClass *fclass = avformat_get_class(); @@ -2370,7 +2370,7 @@ static void validate_enc_avopt(Muxer *mux, const AVDictionary *codec_avopt) if (!(option->flags & AV_OPT_FLAG_ENCODING_PARAM)) { av_log(mux, AV_LOG_ERROR, "Codec AVOption %s (%s) is not an " "encoding option.\n", e->key, option->help ? option->help : ""); - exit_program(1); + return AVERROR(EINVAL); } // gop_timecode is injected by generic code but not always used @@ -2384,6 +2384,8 @@ static void validate_enc_avopt(Muxer *mux, const AVDictionary *codec_avopt) "any stream.\n", e->key, option->help ? option->help : ""); } av_dict_free(&unused_opts); + + return 0; } static int init_output_stream_nofilter(OutputStream *ost) @@ -2502,7 +2504,9 @@ int of_open(const OptionsContext *o, const char *filename) return err; /* check if all codec options have been used */ - validate_enc_avopt(mux, o->g->codec_opts); + err = validate_enc_avopt(mux, o->g->codec_opts); + if (err < 0) + return err; /* check filename in case of an image number is expected */ if (oc->oformat->flags & AVFMT_NEEDNUMBER && !av_filename_number_test(oc->url)) { From dd44871eb9c696db8d95a89918cfa2a3a556d4db Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Wed, 12 Jul 2023 17:58:53 +0200 Subject: [PATCH 1861/2172] fftools/ffmpeg_mux_init: improve of_add_programs() Replace duplicated(!) and broken* custom string parsing with av_dict_parse_string(). Return error codes instead of aborting. * e.g. it treats NULL returned from av_get_token() as "separator not found", when in fact av_get_token() only returns NULL on memory allocation failure --- fftools/ffmpeg_mux_init.c | 105 ++++++++++++++++++-------------------- 1 file changed, 49 insertions(+), 56 deletions(-) diff --git a/fftools/ffmpeg_mux_init.c b/fftools/ffmpeg_mux_init.c index 3a327048bb5..b0befb89247 100644 --- a/fftools/ffmpeg_mux_init.c +++ b/fftools/ffmpeg_mux_init.c @@ -1782,76 +1782,66 @@ static int setup_sync_queues(Muxer *mux, AVFormatContext *oc, int64_t buf_size_u return 0; } -static void of_add_programs(Muxer *mux, const OptionsContext *o) +static int of_add_programs(Muxer *mux, const OptionsContext *o) { AVFormatContext *oc = mux->fc; /* process manually set programs */ for (int i = 0; i < o->nb_program; i++) { - const char *p = o->program[i].u.str; - int progid = i+1; + AVDictionary *dict = NULL; + const AVDictionaryEntry *e; AVProgram *program; + int ret, progid = i + 1; - while(*p) { - const char *p2 = av_get_token(&p, ":"); - const char *to_dealloc = p2; - char *key; - if (!p2) - break; + ret = av_dict_parse_string(&dict, o->program[i].u.str, "=", ":", + AV_DICT_MULTIKEY); + if (ret < 0) { + av_log(mux, AV_LOG_ERROR, "Error parsing program specification %s\n", + o->program[i].u.str); + return ret; + } - if(*p) p++; + e = av_dict_get(dict, "program_num", NULL, 0); + if (e) { + progid = strtol(e->value, NULL, 0); + av_dict_set(&dict, e->key, NULL, 0); + } - key = av_get_token(&p2, "="); - if (!key || !*p2) { - av_freep(&to_dealloc); - av_freep(&key); - break; - } - p2++; + program = av_new_program(oc, progid); + if (!program) { + ret = AVERROR(ENOMEM); + goto fail; + } - if (!strcmp(key, "program_num")) - progid = strtol(p2, NULL, 0); - av_freep(&to_dealloc); - av_freep(&key); + e = av_dict_get(dict, "title", NULL, 0); + if (e) { + av_dict_set(&program->metadata, e->key, e->value, 0); + av_dict_set(&dict, e->key, NULL, 0); } - program = av_new_program(oc, progid); - if (!program) - report_and_exit(AVERROR(ENOMEM)); + e = NULL; + while (e = av_dict_get(dict, "st", e, 0)) { + int st_num = strtol(e->value, NULL, 0); + av_program_add_stream_index(oc, progid, st_num); + } - p = o->program[i].u.str; - while(*p) { - const char *p2 = av_get_token(&p, ":"); - const char *to_dealloc = p2; - char *key; - if (!p2) - break; - if(*p) p++; + // make sure that nothing but "st" entries are left in the dict + e = NULL; + while (e = av_dict_iterate(dict, e)) { + if (!strcmp(e->key, "st")) + continue; - key = av_get_token(&p2, "="); - if (!key) { - av_log(mux, AV_LOG_FATAL, - "No '=' character in program string %s.\n", - p2); - exit_program(1); - } - if (!*p2) - exit_program(1); - p2++; - - if (!strcmp(key, "title")) { - av_dict_set(&program->metadata, "title", p2, 0); - } else if (!strcmp(key, "program_num")) { - } else if (!strcmp(key, "st")) { - int st_num = strtol(p2, NULL, 0); - av_program_add_stream_index(oc, progid, st_num); - } else { - av_log(mux, AV_LOG_FATAL, "Unknown program key %s.\n", key); - exit_program(1); - } - av_freep(&to_dealloc); - av_freep(&key); + av_log(mux, AV_LOG_FATAL, "Unknown program key %s.\n", e->key); + ret = AVERROR(EINVAL); + goto fail; } + +fail: + av_dict_free(&dict); + if (ret < 0) + return ret; } + + return 0; } /** @@ -2547,7 +2537,10 @@ int of_open(const OptionsContext *o, const char *filename) if (err < 0) return err; - of_add_programs(mux, o); + err = of_add_programs(mux, o); + if (err < 0) + return err; + of_add_metadata(of, oc, o); err = set_dispositions(mux, o); From 45473258ffd3026ee40568a8c64420b9abed959b Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Wed, 12 Jul 2023 18:12:10 +0200 Subject: [PATCH 1862/2172] fftools/ffmpeg_mux_init: return error codes from metadata processing instead of aborting --- fftools/ffmpeg_mux_init.c | 63 ++++++++++++++++++++++++--------------- 1 file changed, 39 insertions(+), 24 deletions(-) diff --git a/fftools/ffmpeg_mux_init.c b/fftools/ffmpeg_mux_init.c index b0befb89247..2bd152039d3 100644 --- a/fftools/ffmpeg_mux_init.c +++ b/fftools/ffmpeg_mux_init.c @@ -1851,8 +1851,8 @@ static int of_add_programs(Muxer *mux, const OptionsContext *o) * @param index for type c/p, chapter/program index is written here * @param stream_spec for type s, the stream specifier is written here */ -static void parse_meta_type(void *logctx, const char *arg, - char *type, int *index, const char **stream_spec) +static int parse_meta_type(void *logctx, const char *arg, + char *type, int *index, const char **stream_spec) { if (*arg) { *type = *arg; @@ -1862,7 +1862,7 @@ static void parse_meta_type(void *logctx, const char *arg, case 's': if (*(++arg) && *arg != ':') { av_log(logctx, AV_LOG_FATAL, "Invalid metadata specifier %s.\n", arg); - exit_program(1); + return AVERROR(EINVAL); } *stream_spec = *arg == ':' ? arg + 1 : ""; break; @@ -1873,14 +1873,16 @@ static void parse_meta_type(void *logctx, const char *arg, break; default: av_log(logctx, AV_LOG_FATAL, "Invalid metadata type %c.\n", *arg); - exit_program(1); + return AVERROR(EINVAL); } } else *type = 'g'; + + return 0; } -static void of_add_metadata(OutputFile *of, AVFormatContext *oc, - const OptionsContext *o) +static int of_add_metadata(OutputFile *of, AVFormatContext *oc, + const OptionsContext *o) { for (int i = 0; i < o->nb_metadata; i++) { AVDictionary **m; @@ -1892,11 +1894,14 @@ static void of_add_metadata(OutputFile *of, AVFormatContext *oc, if (!val) { av_log(of, AV_LOG_FATAL, "No '=' character in metadata string %s.\n", o->metadata[i].u.str); - exit_program(1); + return AVERROR(EINVAL); } *val++ = 0; - parse_meta_type(of, o->metadata[i].specifier, &type, &index, &stream_spec); + ret = parse_meta_type(of, o->metadata[i].specifier, &type, &index, &stream_spec); + if (ret < 0) + return ret; + if (type == 's') { for (int j = 0; j < oc->nb_streams; j++) { OutputStream *ost = of->streams[j]; @@ -1922,7 +1927,7 @@ static void of_add_metadata(OutputFile *of, AVFormatContext *oc, } #endif } else if (ret < 0) - exit_program(1); + return ret; } } else { switch (type) { @@ -1932,24 +1937,26 @@ static void of_add_metadata(OutputFile *of, AVFormatContext *oc, case 'c': if (index < 0 || index >= oc->nb_chapters) { av_log(of, AV_LOG_FATAL, "Invalid chapter index %d in metadata specifier.\n", index); - exit_program(1); + return AVERROR(EINVAL); } m = &oc->chapters[index]->metadata; break; case 'p': if (index < 0 || index >= oc->nb_programs) { av_log(of, AV_LOG_FATAL, "Invalid program index %d in metadata specifier.\n", index); - exit_program(1); + return AVERROR(EINVAL); } m = &oc->programs[index]->metadata; break; default: av_log(of, AV_LOG_FATAL, "Invalid metadata specifier %s.\n", o->metadata[i].specifier); - exit_program(1); + return AVERROR(EINVAL); } av_dict_set(m, o->metadata[i].u.str, *val ? val : NULL, 0); } } + + return 0; } static int copy_chapters(InputFile *ifile, OutputFile *ofile, AVFormatContext *os, @@ -2008,8 +2015,11 @@ static int copy_metadata(Muxer *mux, AVFormatContext *ic, const char *istream_spec = NULL, *ostream_spec = NULL; int idx_in = 0, idx_out = 0; - parse_meta_type(mux, inspec, &type_in, &idx_in, &istream_spec); - parse_meta_type(mux, outspec, &type_out, &idx_out, &ostream_spec); + ret = parse_meta_type(mux, inspec, &type_in, &idx_in, &istream_spec); + if (ret >= 0) + ret = parse_meta_type(mux, outspec, &type_out, &idx_out, &ostream_spec); + if (ret < 0) + return ret; if (type_in == 'g' || type_out == 'g' || !*outspec) *metadata_global_manual = 1; @@ -2026,7 +2036,7 @@ static int copy_metadata(Muxer *mux, AVFormatContext *ic, if ((index) < 0 || (index) >= (nb_elems)) {\ av_log(mux, AV_LOG_FATAL, "Invalid %s index %d while processing metadata maps.\n",\ (desc), (index));\ - exit_program(1);\ + return AVERROR(EINVAL);\ } #define SET_DICT(type, meta, context, index)\ @@ -2057,11 +2067,11 @@ static int copy_metadata(Muxer *mux, AVFormatContext *ic, meta_in = &ic->streams[i]->metadata; break; } else if (ret < 0) - exit_program(1); + return ret; } if (!meta_in) { av_log(mux, AV_LOG_FATAL, "Stream specifier %s does not match any streams.\n", istream_spec); - exit_program(1); + return AVERROR(EINVAL); } } @@ -2071,7 +2081,7 @@ static int copy_metadata(Muxer *mux, AVFormatContext *ic, meta_out = &oc->streams[i]->metadata; av_dict_copy(meta_out, *meta_in, AV_DICT_DONT_OVERWRITE); } else if (ret < 0) - exit_program(1); + return ret; } } else av_dict_copy(meta_out, *meta_in, AV_DICT_DONT_OVERWRITE); @@ -2087,6 +2097,7 @@ static int copy_meta(Muxer *mux, const OptionsContext *o) int metadata_global_manual = 0; int metadata_streams_manual = 0; int metadata_chapters_manual = 0; + int ret; /* copy metadata */ for (int i = 0; i < o->nb_metadata_map; i++) { @@ -2098,11 +2109,13 @@ static int copy_meta(Muxer *mux, const OptionsContext *o) "processing metadata maps\n", in_file_index); return AVERROR(EINVAL); } - copy_metadata(mux, - in_file_index >= 0 ? input_files[in_file_index]->ctx : NULL, - o->metadata_map[i].specifier, *p ? p + 1 : p, - &metadata_global_manual, &metadata_streams_manual, - &metadata_chapters_manual); + ret = copy_metadata(mux, + in_file_index >= 0 ? input_files[in_file_index]->ctx : NULL, + o->metadata_map[i].specifier, *p ? p + 1 : p, + &metadata_global_manual, &metadata_streams_manual, + &metadata_chapters_manual); + if (ret < 0) + return ret; } /* copy chapters */ @@ -2541,7 +2554,9 @@ int of_open(const OptionsContext *o, const char *filename) if (err < 0) return err; - of_add_metadata(of, oc, o); + err = of_add_metadata(of, oc, o); + if (err < 0) + return err; err = set_dispositions(mux, o); if (err < 0) { From 858b635613751ab7023b95c33567bfdc9a822afd Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Wed, 12 Jul 2023 18:24:48 +0200 Subject: [PATCH 1863/2172] fftools/ffmpeg_mux_init: replace all remaining aborts with returning error codes Mainly concerns new_stream_*() and their callees. --- fftools/ffmpeg_mux_init.c | 126 ++++++++++++++++++++++++-------------- 1 file changed, 79 insertions(+), 47 deletions(-) diff --git a/fftools/ffmpeg_mux_init.c b/fftools/ffmpeg_mux_init.c index 2bd152039d3..4b7961b833e 100644 --- a/fftools/ffmpeg_mux_init.c +++ b/fftools/ffmpeg_mux_init.c @@ -154,7 +154,8 @@ static char *get_line(AVIOContext *s, AVBPrint *bprint) av_bprint_chars(bprint, c, 1); if (!av_bprint_is_complete(bprint)) - report_and_exit(AVERROR(ENOMEM)); + return NULL; + return bprint->str; } @@ -462,7 +463,7 @@ static int ost_get_filters(const OptionsContext *o, AVFormatContext *oc, if (filters_script && filters) { av_log(ost, AV_LOG_ERROR, "Both -filter and -filter_script set\n"); - exit_program(1); + return AVERROR(EINVAL); } if (filters_script) @@ -474,7 +475,7 @@ static int ost_get_filters(const OptionsContext *o, AVFormatContext *oc, return *dst ? 0 : AVERROR(ENOMEM); } -static void parse_matrix_coeffs(void *logctx, uint16_t *dest, const char *str) +static int parse_matrix_coeffs(void *logctx, uint16_t *dest, const char *str) { int i; const char *p = str; @@ -486,36 +487,39 @@ static void parse_matrix_coeffs(void *logctx, uint16_t *dest, const char *str) if (!p) { av_log(logctx, AV_LOG_FATAL, "Syntax error in matrix \"%s\" at coeff %d\n", str, i); - exit_program(1); + return AVERROR(EINVAL); } p++; } + + return 0; } -static void new_stream_video(Muxer *mux, const OptionsContext *o, - OutputStream *ost) +static int new_stream_video(Muxer *mux, const OptionsContext *o, + OutputStream *ost) { AVFormatContext *oc = mux->fc; AVStream *st; char *frame_rate = NULL, *max_frame_rate = NULL, *frame_aspect_ratio = NULL; + int ret = 0; st = ost->st; MATCH_PER_STREAM_OPT(frame_rates, str, frame_rate, oc, st); if (frame_rate && av_parse_video_rate(&ost->frame_rate, frame_rate) < 0) { av_log(ost, AV_LOG_FATAL, "Invalid framerate value: %s\n", frame_rate); - exit_program(1); + return AVERROR(EINVAL); } MATCH_PER_STREAM_OPT(max_frame_rates, str, max_frame_rate, oc, st); if (max_frame_rate && av_parse_video_rate(&ost->max_frame_rate, max_frame_rate) < 0) { av_log(ost, AV_LOG_FATAL, "Invalid maximum framerate value: %s\n", max_frame_rate); - exit_program(1); + return AVERROR(EINVAL); } if (frame_rate && max_frame_rate) { av_log(ost, AV_LOG_ERROR, "Only one of -fpsmax and -r can be set for a stream.\n"); - exit_program(1); + return AVERROR(EINVAL); } MATCH_PER_STREAM_OPT(frame_aspect_ratios, str, frame_aspect_ratio, oc, st); @@ -524,7 +528,7 @@ static void new_stream_video(Muxer *mux, const OptionsContext *o, if (av_parse_ratio(&q, frame_aspect_ratio, 255, 0, NULL) < 0 || q.num <= 0 || q.den <= 0) { av_log(ost, AV_LOG_FATAL, "Invalid aspect ratio: %s\n", frame_aspect_ratio); - exit_program(1); + return AVERROR(EINVAL); } ost->frame_aspect_ratio = q; } @@ -540,9 +544,12 @@ static void new_stream_video(Muxer *mux, const OptionsContext *o, int i; MATCH_PER_STREAM_OPT(frame_sizes, str, frame_size, oc, st); - if (frame_size && av_parse_video_size(&video_enc->width, &video_enc->height, frame_size) < 0) { - av_log(ost, AV_LOG_FATAL, "Invalid frame size: %s.\n", frame_size); - exit_program(1); + if (frame_size) { + ret = av_parse_video_size(&video_enc->width, &video_enc->height, frame_size); + if (ret < 0) { + av_log(ost, AV_LOG_FATAL, "Invalid frame size: %s.\n", frame_size); + return AVERROR(EINVAL); + } } MATCH_PER_STREAM_OPT(frame_pix_fmts, str, frame_pix_fmt, oc, st); @@ -553,29 +560,36 @@ static void new_stream_video(Muxer *mux, const OptionsContext *o, } if (frame_pix_fmt && (video_enc->pix_fmt = av_get_pix_fmt(frame_pix_fmt)) == AV_PIX_FMT_NONE) { av_log(ost, AV_LOG_FATAL, "Unknown pixel format requested: %s.\n", frame_pix_fmt); - exit_program(1); + return AVERROR(EINVAL); } st->sample_aspect_ratio = video_enc->sample_aspect_ratio; 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))) - report_and_exit(AVERROR(ENOMEM)); - parse_matrix_coeffs(ost, video_enc->intra_matrix, intra_matrix); + return AVERROR(ENOMEM); + + ret = parse_matrix_coeffs(ost, video_enc->intra_matrix, intra_matrix); + if (ret < 0) + return ret; } MATCH_PER_STREAM_OPT(chroma_intra_matrices, str, chroma_intra_matrix, oc, st); if (chroma_intra_matrix) { uint16_t *p = av_mallocz(sizeof(*video_enc->chroma_intra_matrix) * 64); if (!p) - report_and_exit(AVERROR(ENOMEM)); + return AVERROR(ENOMEM); video_enc->chroma_intra_matrix = p; - parse_matrix_coeffs(ost, p, chroma_intra_matrix); + ret = parse_matrix_coeffs(ost, p, chroma_intra_matrix); + if (ret < 0) + return ret; } MATCH_PER_STREAM_OPT(inter_matrices, str, inter_matrix, oc, st); if (inter_matrix) { if (!(video_enc->inter_matrix = av_mallocz(sizeof(*video_enc->inter_matrix) * 64))) - report_and_exit(AVERROR(ENOMEM)); - parse_matrix_coeffs(ost, video_enc->inter_matrix, inter_matrix); + return AVERROR(ENOMEM); + ret = parse_matrix_coeffs(ost, video_enc->inter_matrix, inter_matrix); + if (ret < 0) + return ret; } MATCH_PER_STREAM_OPT(rc_overrides, str, p, oc, st); @@ -584,14 +598,14 @@ static void new_stream_video(Muxer *mux, const OptionsContext *o, int e = sscanf(p, "%d,%d,%d", &start, &end, &q); if (e != 3) { av_log(ost, AV_LOG_FATAL, "error parsing rc_override\n"); - exit_program(1); + return AVERROR(EINVAL); } video_enc->rc_override = av_realloc_array(video_enc->rc_override, i + 1, sizeof(RcOverride)); if (!video_enc->rc_override) { av_log(ost, AV_LOG_FATAL, "Could not (re)allocate memory for rc_override.\n"); - exit_program(1); + return AVERROR(ENOMEM); } video_enc->rc_override[i].start_frame = start; video_enc->rc_override[i].end_frame = end; @@ -631,7 +645,7 @@ static void new_stream_video(Muxer *mux, const OptionsContext *o, MATCH_PER_STREAM_OPT(passlogfiles, str, ost->logfile_prefix, oc, st); if (ost->logfile_prefix && !(ost->logfile_prefix = av_strdup(ost->logfile_prefix))) - report_and_exit(AVERROR(ENOMEM)); + return AVERROR(ENOMEM); if (do_pass) { int ost_idx = -1; @@ -655,7 +669,7 @@ static void new_stream_video(Muxer *mux, const OptionsContext *o, if (!logbuffer) { av_log(ost, AV_LOG_FATAL, "Error reading log file '%s' for pass-2 encoding\n", logfilename); - exit_program(1); + return AVERROR(EIO); } video_enc->stats_in = logbuffer; } @@ -665,7 +679,7 @@ static void new_stream_video(Muxer *mux, const OptionsContext *o, av_log(ost, AV_LOG_FATAL, "Cannot write log file '%s' for pass-1 encoding: %s\n", logfilename, strerror(errno)); - exit_program(1); + return AVERROR(errno); } ost->logfile = f; } @@ -687,7 +701,7 @@ static void new_stream_video(Muxer *mux, const OptionsContext *o, ost->vsync_method == VSYNC_CFR || ost->vsync_method == VSYNC_VSCFR)) { av_log(ost, AV_LOG_FATAL, "One of -r/-fpsmax was specified " "together a non-CFR -vsync/-fps_mode. This is contradictory.\n"); - exit_program(1); + return AVERROR(EINVAL); } if (ost->vsync_method == VSYNC_AUTO) { @@ -715,13 +729,16 @@ static void new_stream_video(Muxer *mux, const OptionsContext *o, } ost->is_cfr = (ost->vsync_method == VSYNC_CFR || ost->vsync_method == VSYNC_VSCFR); } + + return 0; } -static void new_stream_audio(Muxer *mux, const OptionsContext *o, - OutputStream *ost) +static int new_stream_audio(Muxer *mux, const OptionsContext *o, + OutputStream *ost) { AVFormatContext *oc = mux->fc; AVStream *st; + int ret = 0; st = ost->st; @@ -748,7 +765,7 @@ static void new_stream_audio(Muxer *mux, const OptionsContext *o, if (!mask) { #endif av_log(ost, AV_LOG_FATAL, "Unknown channel layout: %s\n", layout); - exit_program(1); + return AVERROR(EINVAL); #if FF_API_OLD_CHANNEL_LAYOUT } av_log(ost, AV_LOG_WARNING, "Channel layout '%s' uses a deprecated syntax.\n", @@ -762,7 +779,7 @@ static void new_stream_audio(Muxer *mux, const OptionsContext *o, if (sample_fmt && (audio_enc->sample_fmt = av_get_sample_fmt(sample_fmt)) == AV_SAMPLE_FMT_NONE) { av_log(ost, AV_LOG_FATAL, "Invalid sample format '%s'\n", sample_fmt); - exit_program(1); + return AVERROR(EINVAL); } MATCH_PER_STREAM_OPT(audio_sample_rate, i, audio_enc->sample_rate, oc, st); @@ -789,11 +806,11 @@ static void new_stream_audio(Muxer *mux, const OptionsContext *o, } if (!ist || (ist->file_index == map->file_idx && ist->index == map->stream_idx)) { - if (av_reallocp_array(&ost->audio_channels_map, - ost->audio_channels_mapped + 1, - sizeof(*ost->audio_channels_map) - ) < 0 ) - report_and_exit(AVERROR(ENOMEM)); + ret = av_reallocp_array(&ost->audio_channels_map, + ost->audio_channels_mapped + 1, + sizeof(*ost->audio_channels_map)); + if (ret < 0) + return ret; ost->audio_channels_map[ost->audio_channels_mapped++] = map->channel_idx; } @@ -801,16 +818,19 @@ static void new_stream_audio(Muxer *mux, const OptionsContext *o, } #endif } + + return 0; } -static void new_stream_attachment(Muxer *mux, const OptionsContext *o, - OutputStream *ost) +static int new_stream_attachment(Muxer *mux, const OptionsContext *o, + OutputStream *ost) { ost->finished = 1; + return 0; } -static void new_stream_subtitle(Muxer *mux, const OptionsContext *o, - OutputStream *ost) +static int new_stream_subtitle(Muxer *mux, const OptionsContext *o, + OutputStream *ost) { AVStream *st; @@ -828,9 +848,12 @@ static void new_stream_subtitle(Muxer *mux, const OptionsContext *o, char *frame_size = NULL; MATCH_PER_STREAM_OPT(frame_sizes, str, frame_size, mux->fc, st); - if (frame_size && av_parse_video_size(&subtitle_enc->width, &subtitle_enc->height, frame_size) < 0) { - av_log(ost, AV_LOG_FATAL, "Invalid frame size: %s.\n", frame_size); - exit_program(1); + if (frame_size) { + int ret = av_parse_video_size(&subtitle_enc->width, &subtitle_enc->height, frame_size); + if (ret < 0) { + av_log(ost, AV_LOG_FATAL, "Invalid frame size: %s.\n", frame_size); + return ret; + } } if (input_descriptor) input_props = input_descriptor->props & (AV_CODEC_PROP_TEXT_SUB | AV_CODEC_PROP_BITMAP_SUB); @@ -840,9 +863,11 @@ static void new_stream_subtitle(Muxer *mux, const OptionsContext *o, av_log(ost, AV_LOG_ERROR, "Subtitle encoding currently only possible from text to text " "or bitmap to bitmap\n"); - exit_program(1); + return AVERROR(EINVAL); } } + + return 0; } static int streamcopy_init(const Muxer *mux, OutputStream *ost) @@ -1084,6 +1109,11 @@ static int ost_add(Muxer *mux, const OptionsContext *o, enum AVMediaType type, do { av_bprint_clear(&bprint); buf = get_line(s, &bprint); + if (!buf) { + ret = AVERROR(ENOMEM); + break; + } + if (!buf[0] || buf[0] == '#') continue; if (!(arg = strchr(buf, '='))) { @@ -1250,11 +1280,13 @@ static int ost_add(Muxer *mux, const OptionsContext *o, enum AVMediaType type, ms->copy_initial_nonkeyframes, oc, st); switch (type) { - case AVMEDIA_TYPE_VIDEO: new_stream_video (mux, o, ost); break; - case AVMEDIA_TYPE_AUDIO: new_stream_audio (mux, o, ost); break; - case AVMEDIA_TYPE_SUBTITLE: new_stream_subtitle (mux, o, ost); break; - case AVMEDIA_TYPE_ATTACHMENT: new_stream_attachment(mux, o, ost); break; + case AVMEDIA_TYPE_VIDEO: ret = new_stream_video (mux, o, ost); break; + case AVMEDIA_TYPE_AUDIO: ret = new_stream_audio (mux, o, ost); break; + case AVMEDIA_TYPE_SUBTITLE: ret = new_stream_subtitle (mux, o, ost); break; + case AVMEDIA_TYPE_ATTACHMENT: ret = new_stream_attachment(mux, o, ost); break; } + if (ret < 0) + return ret; if (type == AVMEDIA_TYPE_VIDEO || type == AVMEDIA_TYPE_AUDIO) { ret = ost_get_filters(o, oc, ost, &filters); From 5fe3914c391699c05cbd7a09f38f318d0452f1df Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Wed, 12 Jul 2023 19:48:05 +0200 Subject: [PATCH 1864/2172] fftools/ffmpeg: return an error instead of aborting --- fftools/ffmpeg.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fftools/ffmpeg.c b/fftools/ffmpeg.c index 96638242f3e..68924d21e08 100644 --- a/fftools/ffmpeg.c +++ b/fftools/ffmpeg.c @@ -1094,7 +1094,7 @@ static int process_input(int file_index) av_log(ifile, AV_LOG_ERROR, "Error retrieving a packet from demuxer: %s\n", av_err2str(ret)); if (exit_on_error) - exit_program(1); + return ret; } for (i = 0; i < ifile->nb_streams; i++) { From 464a5e8e7681267501cb4a5e96ad040522a67d4e Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Wed, 12 Jul 2023 19:49:43 +0200 Subject: [PATCH 1865/2172] fftools/ffmpeg: handle error codes from process_input_packet() None are returned for now, but that will change in future commits. --- fftools/ffmpeg.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/fftools/ffmpeg.c b/fftools/ffmpeg.c index 68924d21e08..dd7cfcf632f 100644 --- a/fftools/ffmpeg.c +++ b/fftools/ffmpeg.c @@ -1103,6 +1103,8 @@ static int process_input(int file_index) ret = process_input_packet(ist, NULL, 0); if (ret>0) return 0; + else if (ret < 0) + return ret; } /* mark all outputs that don't go through lavfi as finished */ @@ -1124,11 +1126,11 @@ static int process_input(int file_index) sub2video_heartbeat(ifile, pkt->pts, pkt->time_base); - process_input_packet(ist, pkt, 0); + ret = process_input_packet(ist, pkt, 0); av_packet_free(&pkt); - return 0; + return ret < 0 ? ret : 0; } /** @@ -1219,7 +1221,8 @@ static int transcode(int *err_rate_exceeded) float err_rate; if (!input_files[ist->file_index]->eof_reached) { - process_input_packet(ist, NULL, 0); + int err = process_input_packet(ist, NULL, 0); + ret = err_merge(ret, err); } err_rate = (ist->frames_decoded || ist->decode_errors) ? From 2e742a2c3c05e9d2ea86216daaf35cbdd108f3aa Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Wed, 12 Jul 2023 19:52:19 +0200 Subject: [PATCH 1866/2172] fftools/ffmpeg_mux: return errors from of_streamcopy() instead of aborting --- fftools/ffmpeg.c | 4 +++- fftools/ffmpeg.h | 2 +- fftools/ffmpeg_mux.c | 20 ++++++++++++-------- 3 files changed, 16 insertions(+), 10 deletions(-) diff --git a/fftools/ffmpeg.c b/fftools/ffmpeg.c index dd7cfcf632f..3e8d2a4c89a 100644 --- a/fftools/ffmpeg.c +++ b/fftools/ffmpeg.c @@ -839,7 +839,9 @@ static int process_input_packet(InputStream *ist, const AVPacket *pkt, int no_eo continue; } - of_streamcopy(ost, pkt, dts_est); + ret = of_streamcopy(ost, pkt, dts_est); + if (ret < 0) + return ret; } return !eof_reached; diff --git a/fftools/ffmpeg.h b/fftools/ffmpeg.h index 30020cd0f84..fdee20d6b25 100644 --- a/fftools/ffmpeg.h +++ b/fftools/ffmpeg.h @@ -826,7 +826,7 @@ void of_output_packet(OutputFile *of, OutputStream *ost, AVPacket *pkt); /** * @param dts predicted packet dts in AV_TIME_BASE_Q */ -void of_streamcopy(OutputStream *ost, const AVPacket *pkt, int64_t dts); +int of_streamcopy(OutputStream *ost, const AVPacket *pkt, int64_t dts); int64_t of_filesize(OutputFile *of); diff --git a/fftools/ffmpeg_mux.c b/fftools/ffmpeg_mux.c index ca32967cd8c..a6cc8244963 100644 --- a/fftools/ffmpeg_mux.c +++ b/fftools/ffmpeg_mux.c @@ -389,13 +389,14 @@ void of_output_packet(OutputFile *of, OutputStream *ost, AVPacket *pkt) } -void of_streamcopy(OutputStream *ost, const AVPacket *pkt, int64_t dts) +int of_streamcopy(OutputStream *ost, const AVPacket *pkt, int64_t dts) { OutputFile *of = output_files[ost->file_index]; MuxStream *ms = ms_from_ost(ost); int64_t start_time = (of->start_time == AV_NOPTS_VALUE) ? 0 : of->start_time; int64_t ost_tb_start_time = av_rescale_q(start_time, AV_TIME_BASE_Q, ost->mux_timebase); AVPacket *opkt = ms->pkt; + int ret; av_packet_unref(opkt); @@ -406,26 +407,27 @@ void of_streamcopy(OutputStream *ost, const AVPacket *pkt, int64_t dts) // EOF: flush output bitstream filters. if (!pkt) { of_output_packet(of, ost, NULL); - return; + return 0; } if (!ms->streamcopy_started && !(pkt->flags & AV_PKT_FLAG_KEY) && !ms->copy_initial_nonkeyframes) - return; + return 0; if (!ms->streamcopy_started) { if (!ms->copy_prior_start && (pkt->pts == AV_NOPTS_VALUE ? dts < ms->ts_copy_start : pkt->pts < av_rescale_q(ms->ts_copy_start, AV_TIME_BASE_Q, pkt->time_base))) - return; + return 0; if (of->start_time != AV_NOPTS_VALUE && dts < of->start_time) - return; + return 0; } - if (av_packet_ref(opkt, pkt) < 0) - exit_program(1); + ret = av_packet_ref(opkt, pkt); + if (ret < 0) + return ret; opkt->time_base = ost->mux_timebase; @@ -455,13 +457,15 @@ void of_streamcopy(OutputStream *ost, const AVPacket *pkt, int64_t dts) av_log(NULL, AV_LOG_ERROR, "Subtitle heartbeat logic failed in %s! (%s)\n", __func__, av_err2str(ret)); - exit_program(1); + return ret; } } of_output_packet(of, ost, opkt); ms->streamcopy_started = 1; + + return 0; } static int thread_stop(Muxer *mux) From c328bff4daac260336665745d48059903d4bb203 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Wed, 12 Jul 2023 19:59:24 +0200 Subject: [PATCH 1867/2172] fftools/ffmpeg_enc: return errors from enc_subtitle() instead of aborting --- fftools/ffmpeg.h | 2 +- fftools/ffmpeg_dec.c | 4 +++- fftools/ffmpeg_enc.c | 16 ++++++++-------- 3 files changed, 12 insertions(+), 10 deletions(-) diff --git a/fftools/ffmpeg.h b/fftools/ffmpeg.h index fdee20d6b25..bcd9cc584ef 100644 --- a/fftools/ffmpeg.h +++ b/fftools/ffmpeg.h @@ -804,7 +804,7 @@ int enc_alloc(Encoder **penc, const AVCodec *codec); void enc_free(Encoder **penc); int enc_open(OutputStream *ost, AVFrame *frame); -void enc_subtitle(OutputFile *of, OutputStream *ost, const AVSubtitle *sub); +int enc_subtitle(OutputFile *of, OutputStream *ost, const AVSubtitle *sub); void enc_frame(OutputStream *ost, AVFrame *frame); void enc_flush(void); diff --git a/fftools/ffmpeg_dec.c b/fftools/ffmpeg_dec.c index 85bf8dc5367..a1d811f5123 100644 --- a/fftools/ffmpeg_dec.c +++ b/fftools/ffmpeg_dec.c @@ -439,7 +439,9 @@ static int process_subtitle(InputStream *ist, AVFrame *frame) if (!ost->enc || ost->type != AVMEDIA_TYPE_SUBTITLE) continue; - enc_subtitle(output_files[ost->file_index], ost, subtitle); + ret = enc_subtitle(output_files[ost->file_index], ost, subtitle); + if (ret < 0) + return ret; } return 0; diff --git a/fftools/ffmpeg_enc.c b/fftools/ffmpeg_enc.c index 40295013130..b35dbb62901 100644 --- a/fftools/ffmpeg_enc.c +++ b/fftools/ffmpeg_enc.c @@ -462,7 +462,7 @@ static int check_recording_time(OutputStream *ost, int64_t ts, AVRational tb) return 1; } -void enc_subtitle(OutputFile *of, OutputStream *ost, const AVSubtitle *sub) +int enc_subtitle(OutputFile *of, OutputStream *ost, const AVSubtitle *sub) { Encoder *e = ost->enc; int subtitle_out_max_size = 1024 * 1024; @@ -473,13 +473,11 @@ void enc_subtitle(OutputFile *of, OutputStream *ost, const AVSubtitle *sub) if (sub->pts == AV_NOPTS_VALUE) { av_log(ost, AV_LOG_ERROR, "Subtitle packets must have a pts\n"); - if (exit_on_error) - exit_program(1); - return; + return exit_on_error ? AVERROR(EINVAL) : 0; } if (ost->finished || (of->start_time != AV_NOPTS_VALUE && sub->pts < of->start_time)) - return; + return 0; enc = ost->enc_ctx; @@ -501,11 +499,11 @@ void enc_subtitle(OutputFile *of, OutputStream *ost, const AVSubtitle *sub) AVSubtitle local_sub = *sub; if (!check_recording_time(ost, pts, AV_TIME_BASE_Q)) - return; + return 0; ret = av_new_packet(pkt, subtitle_out_max_size); if (ret < 0) - report_and_exit(AVERROR(ENOMEM)); + return AVERROR(ENOMEM); local_sub.pts = pts; // start_display_time is required to be 0 @@ -525,7 +523,7 @@ void enc_subtitle(OutputFile *of, OutputStream *ost, const AVSubtitle *sub) subtitle_out_size = avcodec_encode_subtitle(enc, pkt->data, pkt->size, &local_sub); if (subtitle_out_size < 0) { av_log(ost, AV_LOG_FATAL, "Subtitle encoding failed\n"); - exit_program(1); + return subtitle_out_size; } av_shrink_packet(pkt, subtitle_out_size); @@ -544,6 +542,8 @@ void enc_subtitle(OutputFile *of, OutputStream *ost, const AVSubtitle *sub) of_output_packet(of, ost, pkt); } + + return 0; } void enc_stats_write(OutputStream *ost, EncStats *es, From 20c42213eaf0a9cfd446f5c3ab5afcfe9ec01f26 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Wed, 12 Jul 2023 20:11:18 +0200 Subject: [PATCH 1868/2172] fftools/ffmpeg_mux_init: drop an obsolete assignment This line was added in c30a4489b44 along with AVStream.sample_aspect_ratio. However, configuring SAR for video encoding is now done after this code (specifically in enc_open(), which is called when the first video frame to be encoded is obtained), so this line cannot have any meaningful effect. --- fftools/ffmpeg_mux_init.c | 1 - 1 file changed, 1 deletion(-) diff --git a/fftools/ffmpeg_mux_init.c b/fftools/ffmpeg_mux_init.c index 4b7961b833e..2dba76b82b3 100644 --- a/fftools/ffmpeg_mux_init.c +++ b/fftools/ffmpeg_mux_init.c @@ -562,7 +562,6 @@ static int new_stream_video(Muxer *mux, const OptionsContext *o, av_log(ost, AV_LOG_FATAL, "Unknown pixel format requested: %s.\n", frame_pix_fmt); return AVERROR(EINVAL); } - st->sample_aspect_ratio = video_enc->sample_aspect_ratio; MATCH_PER_STREAM_OPT(intra_matrices, str, intra_matrix, oc, st); if (intra_matrix) { From 0a6751a78ab8a894eceaade6bf7578af6c0cd38b Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Thu, 6 Jul 2023 21:31:49 +0200 Subject: [PATCH 1869/2172] fftools/ffmpeg: rework initializing encoders with no frames When no frames were passed from a filtergraph to an encoder, but the filtergraph is configured (i.e. has output parameters), encoder flush code will use those parameters to initialize the encoder in a last-ditch effort to produce some useful output. Rework this process so that it is triggered by the filtergraph, which now sends a dummy frame with parameters, but no data, to the encoder, rather than the encoder reaching backwards into the filter. This approach is more in line with the natural data flow from filters to encoders and will allow to reduce encoder-filter interactions in following commits. This code is tested by fate-adpcm-ima-cunning-trunc-t2-track1, which (as confirmed by Zane) is supposed to produce empty output. --- fftools/ffmpeg_enc.c | 22 ++--------------- fftools/ffmpeg_filter.c | 54 ++++++++++++++++++++++++++++++++++++++--- 2 files changed, 52 insertions(+), 24 deletions(-) diff --git a/fftools/ffmpeg_enc.c b/fftools/ffmpeg_enc.c index b35dbb62901..390f1b3b571 100644 --- a/fftools/ffmpeg_enc.c +++ b/fftools/ffmpeg_enc.c @@ -1142,26 +1142,8 @@ void enc_flush(void) AVCodecContext *enc = ost->enc_ctx; OutputFile *of = output_files[ost->file_index]; - if (!enc) - continue; - - // Try to enable encoding with no input frames. - // Maybe we should just let encoding fail instead. - if (!e->opened) { - FilterGraph *fg = ost->filter->graph; - - av_log(ost, AV_LOG_WARNING, - "Finishing stream without any data written to it.\n"); - - if (!fg->graph) - continue; - - ret = enc_open(ost, NULL); - if (ret < 0) - exit_program(1); - } - - if (enc->codec_type != AVMEDIA_TYPE_VIDEO && enc->codec_type != AVMEDIA_TYPE_AUDIO) + if (!enc || !e->opened || + (enc->codec_type != AVMEDIA_TYPE_VIDEO && enc->codec_type != AVMEDIA_TYPE_AUDIO)) continue; ret = submit_encode_frame(of, ost, NULL); diff --git a/fftools/ffmpeg_filter.c b/fftools/ffmpeg_filter.c index caf85194c58..1b51ed55bd6 100644 --- a/fftools/ffmpeg_filter.c +++ b/fftools/ffmpeg_filter.c @@ -143,11 +143,17 @@ typedef struct OutputFilterPriv { int sample_rate; AVChannelLayout ch_layout; + AVRational time_base; + AVRational sample_aspect_ratio; + // those are only set if no format is specified and the encoder gives us multiple options // They point directly to the relevant lists of the encoder. const int *formats; const AVChannelLayout *ch_layouts; const int *sample_rates; + + // set to 1 after at least one frame passed through this output + int got_frame; } OutputFilterPriv; static OutputFilterPriv *ofp_from_ofilter(OutputFilter *ofilter) @@ -1610,6 +1616,9 @@ static int configure_filtergraph(FilterGraph *fg) ofp->width = av_buffersink_get_w(sink); ofp->height = av_buffersink_get_h(sink); + ofp->time_base = av_buffersink_get_time_base(sink); + ofp->sample_aspect_ratio = av_buffersink_get_sample_aspect_ratio(sink); + ofp->sample_rate = av_buffersink_get_sample_rate(sink); av_channel_layout_uninit(&ofp->ch_layout); ret = av_buffersink_get_ch_layout(sink, &ofp->ch_layout); @@ -1722,6 +1731,7 @@ int reap_filters(int flush) { /* Reap all buffers present in the buffer sinks */ for (OutputStream *ost = ost_iter(NULL); ost; ost = ost_iter(ost)) { + OutputFilterPriv *ofp; FilterGraphPriv *fgp; AVFrame *filtered_frame; AVFilterContext *filter; @@ -1731,6 +1741,7 @@ int reap_filters(int flush) continue; filter = ost->filter->filter; fgp = fgp_from_fg(ost->filter->graph); + ofp = ofp_from_ofilter(ost->filter); filtered_frame = fgp->frame; @@ -1783,6 +1794,7 @@ int reap_filters(int flush) enc_frame(ost, filtered_frame); av_frame_unref(filtered_frame); + ofp->got_frame = 1; } } @@ -1995,6 +2007,7 @@ int ifilter_send_frame(InputFilter *ifilter, AVFrame *frame, int keep_reference) int fg_transcode_step(FilterGraph *graph, InputStream **best_ist) { + FilterGraphPriv *fgp = fgp_from_fg(graph); int i, ret; int nb_requests, nb_requests_max = 0; InputStream *ist; @@ -2022,10 +2035,43 @@ int fg_transcode_step(FilterGraph *graph, InputStream **best_ist) return reap_filters(0); if (ret == AVERROR_EOF) { - ret = reap_filters(1); - for (i = 0; i < graph->nb_outputs; i++) - close_output_stream(graph->outputs[i]->ost); - return ret; + reap_filters(1); + for (int i = 0; i < graph->nb_outputs; i++) { + OutputFilter *ofilter = graph->outputs[i]; + OutputFilterPriv *ofp = ofp_from_ofilter(ofilter); + + // we are finished and no frames were ever seen at this output, + // at least initialize the encoder with a dummy frame + if (!ofp->got_frame) { + AVFrame *frame = fgp->frame; + + frame->time_base = ofp->time_base; + frame->format = ofp->format; + + frame->width = ofp->width; + frame->height = ofp->height; + frame->sample_aspect_ratio = ofp->sample_aspect_ratio; + + frame->sample_rate = ofp->sample_rate; + if (ofp->ch_layout.nb_channels) { + ret = av_channel_layout_copy(&frame->ch_layout, &ofp->ch_layout); + if (ret < 0) + return ret; + } + + av_assert0(!frame->buf[0]); + + av_log(ofilter->ost, AV_LOG_WARNING, + "No filtered frames for output stream, trying to " + "initialize anyway.\n"); + + enc_open(ofilter->ost, frame); + av_frame_unref(frame); + } + + close_output_stream(ofilter->ost); + } + return 0; } if (ret != AVERROR(EAGAIN)) return ret; From b295ec31f351d8cc2dfad6f7c0cb261c1b19b7d9 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Fri, 7 Jul 2023 09:29:58 +0200 Subject: [PATCH 1870/2172] fftools/ffmpeg_filter: only flush vsync code if encoding actually started Otherwise this has no effect. Will be useful in following commits. --- fftools/ffmpeg_filter.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/fftools/ffmpeg_filter.c b/fftools/ffmpeg_filter.c index 1b51ed55bd6..1ca97283909 100644 --- a/fftools/ffmpeg_filter.c +++ b/fftools/ffmpeg_filter.c @@ -1754,10 +1754,10 @@ int reap_filters(int flush) if (ret != AVERROR(EAGAIN) && ret != AVERROR_EOF) { av_log(fgp, AV_LOG_WARNING, "Error in av_buffersink_get_frame_flags(): %s\n", av_err2str(ret)); - } else if (flush && ret == AVERROR_EOF) { - if (av_buffersink_get_type(filter) == AVMEDIA_TYPE_VIDEO) - enc_frame(ost, NULL); - } + } else if (flush && ret == AVERROR_EOF && ofp->got_frame && + av_buffersink_get_type(filter) == AVMEDIA_TYPE_VIDEO) + enc_frame(ost, NULL); + break; } if (ost->finished) { From 9a97f9cf3a95f4c2f13abc52702bd19e3a748b66 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Fri, 7 Jul 2023 09:37:32 +0200 Subject: [PATCH 1871/2172] fftools/ffmpeg_enc: initialize audio/video encoders from frame parameters This is possible now that enc_open() is always called with a non-NULL frame for audio/video. Previously the code would directly reach into the buffersink, which is a layering violation. --- fftools/ffmpeg_enc.c | 35 +++++++++++++++++++++-------------- 1 file changed, 21 insertions(+), 14 deletions(-) diff --git a/fftools/ffmpeg_enc.c b/fftools/ffmpeg_enc.c index 390f1b3b571..88c62124a99 100644 --- a/fftools/ffmpeg_enc.c +++ b/fftools/ffmpeg_enc.c @@ -34,8 +34,6 @@ #include "libavutil/rational.h" #include "libavutil/timestamp.h" -#include "libavfilter/buffersink.h" - #include "libavcodec/avcodec.h" // FIXME private header, used for mid_pred() @@ -198,12 +196,21 @@ int enc_open(OutputStream *ost, AVFrame *frame) AVCodecContext *dec_ctx = NULL; const AVCodec *enc = enc_ctx->codec; OutputFile *of = output_files[ost->file_index]; - FrameData *fd = frame ? frame_data(frame) : NULL; + FrameData *fd; int ret; if (e->opened) return 0; + // frame is always non-NULL for audio and video + av_assert0(frame || (enc->type != AVMEDIA_TYPE_VIDEO && enc->type != AVMEDIA_TYPE_AUDIO)); + + if (frame) { + fd = frame_data(frame); + if (!fd) + return AVERROR(ENOMEM); + } + set_encoder_id(output_files[ost->file_index], ost); if (ist) { @@ -212,15 +219,15 @@ int enc_open(OutputStream *ost, AVFrame *frame) switch (enc_ctx->codec_type) { case AVMEDIA_TYPE_AUDIO: - enc_ctx->sample_fmt = av_buffersink_get_format(ost->filter->filter); - enc_ctx->sample_rate = av_buffersink_get_sample_rate(ost->filter->filter); - ret = av_buffersink_get_ch_layout(ost->filter->filter, &enc_ctx->ch_layout); + enc_ctx->sample_fmt = frame->format; + enc_ctx->sample_rate = frame->sample_rate; + ret = av_channel_layout_copy(&enc_ctx->ch_layout, &frame->ch_layout); if (ret < 0) return ret; if (ost->bits_per_raw_sample) enc_ctx->bits_per_raw_sample = ost->bits_per_raw_sample; - else if (fd) + else enc_ctx->bits_per_raw_sample = FFMIN(fd->bits_per_raw_sample, av_get_bytes_per_sample(enc_ctx->sample_fmt) << 3); @@ -231,7 +238,7 @@ int enc_open(OutputStream *ost, AVFrame *frame) case AVMEDIA_TYPE_VIDEO: { AVRational fr = ost->frame_rate; - if (!fr.num && fd) + if (!fr.num) fr = fd->frame_rate_filter; if (!fr.num && !ost->max_frame_rate.num) { fr = (AVRational){25, 1}; @@ -261,7 +268,7 @@ int enc_open(OutputStream *ost, AVFrame *frame) av_inv_q(fr); if (!(enc_ctx->time_base.num && enc_ctx->time_base.den)) - enc_ctx->time_base = av_buffersink_get_time_base(ost->filter->filter); + enc_ctx->time_base = frame->time_base; if ( av_q2d(enc_ctx->time_base) < 0.001 && ost->vsync_method != VSYNC_PASSTHROUGH && (ost->vsync_method == VSYNC_CFR || ost->vsync_method == VSYNC_VSCFR || (ost->vsync_method == VSYNC_AUTO && !(of->format->flags & AVFMT_VARIABLE_FPS)))){ @@ -270,18 +277,18 @@ int enc_open(OutputStream *ost, AVFrame *frame) "setting vsync/fps_mode to vfr\n"); } - enc_ctx->width = av_buffersink_get_w(ost->filter->filter); - enc_ctx->height = av_buffersink_get_h(ost->filter->filter); + enc_ctx->width = frame->width; + enc_ctx->height = frame->height; enc_ctx->sample_aspect_ratio = ost->st->sample_aspect_ratio = ost->frame_aspect_ratio.num ? // overridden by the -aspect cli option av_mul_q(ost->frame_aspect_ratio, (AVRational){ enc_ctx->height, enc_ctx->width }) : - av_buffersink_get_sample_aspect_ratio(ost->filter->filter); + frame->sample_aspect_ratio; - enc_ctx->pix_fmt = av_buffersink_get_format(ost->filter->filter); + enc_ctx->pix_fmt = frame->format; if (ost->bits_per_raw_sample) enc_ctx->bits_per_raw_sample = ost->bits_per_raw_sample; - else if (fd) + else enc_ctx->bits_per_raw_sample = FFMIN(fd->bits_per_raw_sample, av_pix_fmt_desc_get(enc_ctx->pix_fmt)->comp[0].depth); From 75d0af388f0bce87e101d16b1daee3081791f690 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Sat, 27 May 2023 17:58:35 +0200 Subject: [PATCH 1872/2172] fftools/ffmpeg_filter: make OutputFilter.filter private It should not be accessed from outside of filtering code. --- fftools/ffmpeg.h | 1 - fftools/ffmpeg_filter.c | 18 ++++++++++-------- 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/fftools/ffmpeg.h b/fftools/ffmpeg.h index bcd9cc584ef..bd6b0ed6d1f 100644 --- a/fftools/ffmpeg.h +++ b/fftools/ffmpeg.h @@ -283,7 +283,6 @@ typedef struct InputFilter { } InputFilter; typedef struct OutputFilter { - AVFilterContext *filter; struct OutputStream *ost; struct FilterGraph *graph; uint8_t *name; diff --git a/fftools/ffmpeg_filter.c b/fftools/ffmpeg_filter.c index 1ca97283909..de75c9970e4 100644 --- a/fftools/ffmpeg_filter.c +++ b/fftools/ffmpeg_filter.c @@ -137,6 +137,8 @@ static InputFilterPriv *ifp_from_ifilter(InputFilter *ifilter) typedef struct OutputFilterPriv { OutputFilter ofilter; + AVFilterContext *filter; + /* desired output stream properties */ int format; int width, height; @@ -1094,7 +1096,7 @@ static int configure_output_video_filter(FilterGraph *fg, OutputFilter *ofilter, char name[255]; snprintf(name, sizeof(name), "out_%d_%d", ost->file_index, ost->index); - ret = avfilter_graph_create_filter(&ofilter->filter, + ret = avfilter_graph_create_filter(&ofp->filter, avfilter_get_by_name("buffersink"), name, NULL, NULL, fg->graph); @@ -1150,7 +1152,7 @@ static int configure_output_video_filter(FilterGraph *fg, OutputFilter *ofilter, return ret; - if ((ret = avfilter_link(last_filter, pad_idx, ofilter->filter, 0)) < 0) + if ((ret = avfilter_link(last_filter, pad_idx, ofp->filter, 0)) < 0) return ret; return 0; @@ -1168,12 +1170,12 @@ static int configure_output_audio_filter(FilterGraph *fg, OutputFilter *ofilter, int ret; snprintf(name, sizeof(name), "out_%d_%d", ost->file_index, ost->index); - ret = avfilter_graph_create_filter(&ofilter->filter, + ret = avfilter_graph_create_filter(&ofp->filter, avfilter_get_by_name("abuffersink"), name, NULL, NULL, fg->graph); if (ret < 0) return ret; - if ((ret = av_opt_set_int(ofilter->filter, "all_channel_counts", 1, AV_OPT_SEARCH_CHILDREN)) < 0) + if ((ret = av_opt_set_int(ofp->filter, "all_channel_counts", 1, AV_OPT_SEARCH_CHILDREN)) < 0) return ret; #define AUTO_INSERT_FILTER(opt_name, filter_name, arg) do { \ @@ -1256,7 +1258,7 @@ static int configure_output_audio_filter(FilterGraph *fg, OutputFilter *ofilter, if (ret < 0) goto fail; - if ((ret = avfilter_link(last_filter, pad_idx, ofilter->filter, 0)) < 0) + if ((ret = avfilter_link(last_filter, pad_idx, ofp->filter, 0)) < 0) goto fail; fail: av_bprint_finalize(&args, NULL); @@ -1504,7 +1506,7 @@ static void cleanup_filtergraph(FilterGraph *fg) { int i; for (i = 0; i < fg->nb_outputs; i++) - fg->outputs[i]->filter = (AVFilterContext *)NULL; + ofp_from_ofilter(fg->outputs[i])->filter = NULL; for (i = 0; i < fg->nb_inputs; i++) ifp_from_ifilter(fg->inputs[i])->filter = NULL; avfilter_graph_free(&fg->graph); @@ -1609,7 +1611,7 @@ static int configure_filtergraph(FilterGraph *fg) for (i = 0; i < fg->nb_outputs; i++) { OutputFilter *ofilter = fg->outputs[i]; OutputFilterPriv *ofp = ofp_from_ofilter(ofilter); - AVFilterContext *sink = ofilter->filter; + AVFilterContext *sink = ofp->filter; ofp->format = av_buffersink_get_format(sink); @@ -1739,9 +1741,9 @@ int reap_filters(int flush) if (!ost->filter || !ost->filter->graph->graph) continue; - filter = ost->filter->filter; fgp = fgp_from_fg(ost->filter->graph); ofp = ofp_from_ofilter(ost->filter); + filter = ofp->filter; filtered_frame = fgp->frame; From 4d06742b93394b6265fb32640ee7bb36f4fe1a06 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Fri, 7 Jul 2023 11:02:15 +0200 Subject: [PATCH 1873/2172] fftools/ffmpeg: add more structure to FrameData It now contains data from multiple sources, so group those items that always come from the decoder. Also, initialize them to invalid values, so that frames that did not originate from a decoder can be distinguished. --- fftools/ffmpeg.c | 8 +++++++- fftools/ffmpeg.h | 10 +++++++--- fftools/ffmpeg_dec.c | 6 +++--- fftools/ffmpeg_enc.c | 6 +++--- 4 files changed, 20 insertions(+), 10 deletions(-) diff --git a/fftools/ffmpeg.c b/fftools/ffmpeg.c index 3e8d2a4c89a..cbeddab125d 100644 --- a/fftools/ffmpeg.c +++ b/fftools/ffmpeg.c @@ -434,9 +434,15 @@ InputStream *ist_iter(InputStream *prev) FrameData *frame_data(AVFrame *frame) { if (!frame->opaque_ref) { - frame->opaque_ref = av_buffer_allocz(sizeof(FrameData)); + FrameData *fd; + + frame->opaque_ref = av_buffer_allocz(sizeof(*fd)); if (!frame->opaque_ref) return NULL; + fd = (FrameData*)frame->opaque_ref->data; + + fd->dec.frame_num = UINT64_MAX; + fd->dec.pts = AV_NOPTS_VALUE; } return (FrameData*)frame->opaque_ref->data; diff --git a/fftools/ffmpeg.h b/fftools/ffmpeg.h index bd6b0ed6d1f..97aa4d716e0 100644 --- a/fftools/ffmpeg.h +++ b/fftools/ffmpeg.h @@ -626,9 +626,13 @@ typedef struct OutputFile { // optionally attached as opaque_ref to decoded AVFrames typedef struct FrameData { - uint64_t idx; - int64_t pts; - AVRational tb; + // properties that come from the decoder + struct { + uint64_t frame_num; + + int64_t pts; + AVRational tb; + } dec; AVRational frame_rate_filter; diff --git a/fftools/ffmpeg_dec.c b/fftools/ffmpeg_dec.c index a1d811f5123..5c1b8888e95 100644 --- a/fftools/ffmpeg_dec.c +++ b/fftools/ffmpeg_dec.c @@ -612,9 +612,9 @@ static int packet_decode(InputStream *ist, const AVPacket *pkt, AVFrame *frame) av_frame_unref(frame); return AVERROR(ENOMEM); } - fd->pts = frame->pts; - fd->tb = dec->pkt_timebase; - fd->idx = dec->frame_num - 1; + fd->dec.pts = frame->pts; + fd->dec.tb = dec->pkt_timebase; + fd->dec.frame_num = dec->frame_num - 1; fd->bits_per_raw_sample = dec->bits_per_raw_sample; frame->time_base = dec->pkt_timebase; diff --git a/fftools/ffmpeg_enc.c b/fftools/ffmpeg_enc.c index 88c62124a99..0e2285c5a24 100644 --- a/fftools/ffmpeg_enc.c +++ b/fftools/ffmpeg_enc.c @@ -569,8 +569,8 @@ void enc_stats_write(OutputStream *ost, EncStats *es, if ((frame && frame->opaque_ref) || (pkt && pkt->opaque_ref)) { fd = (const FrameData*)(frame ? frame->opaque_ref->data : pkt->opaque_ref->data); - tbi = fd->tb; - ptsi = fd->pts; + tbi = fd->dec.tb; + ptsi = fd->dec.pts; } for (size_t i = 0; i < es->nb_components; i++) { @@ -588,7 +588,7 @@ void enc_stats_write(OutputStream *ost, EncStats *es, case ENC_STATS_PTS_TIME_IN: avio_printf(io, "%g", ptsi == INT64_MAX ? INFINITY : ptsi * av_q2d(tbi)); continue; case ENC_STATS_FRAME_NUM: avio_printf(io, "%"PRIu64, frame_num); continue; - case ENC_STATS_FRAME_NUM_IN: avio_printf(io, "%"PRIu64, fd ? fd->idx : -1); continue; + case ENC_STATS_FRAME_NUM_IN: avio_printf(io, "%"PRIu64, fd ? fd->dec.frame_num : -1); continue; } if (frame) { From dff3a283cd8c71802d43fbbbfcf57fb479784a24 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Fri, 7 Jul 2023 11:31:53 +0200 Subject: [PATCH 1874/2172] fftools/ffmpeg: rework -enc_time_base handling Read the timebase from FrameData rather than the input stream. This should fix #10393 and generally be more reliable. Replace the use of '-1' to indicate demuxing timebase with the string 'demux'. Also allow to request filter timebase with '-enc_time_base filter'. --- doc/ffmpeg.texi | 7 ++++--- fftools/ffmpeg.h | 6 ++++++ fftools/ffmpeg_enc.c | 16 ++++++++++++++-- fftools/ffmpeg_mux_init.c | 31 +++++++++++++++++++------------ tests/fate/video.mak | 2 +- 5 files changed, 44 insertions(+), 18 deletions(-) diff --git a/doc/ffmpeg.texi b/doc/ffmpeg.texi index 6769f8d3051..59e9fbfcb25 100644 --- a/doc/ffmpeg.texi +++ b/doc/ffmpeg.texi @@ -1812,10 +1812,11 @@ Assign a default value according to the media type. For video - use 1/framerate, for audio - use 1/samplerate. -@item -1 -Use the input stream timebase when possible. +@item demux +Use the timebase from the demuxer. -If an input stream is not available, the default timebase will be used. +@item filter +Use the timebase from the filtergraph. @item >0 Use the provided number as the timebase. diff --git a/fftools/ffmpeg.h b/fftools/ffmpeg.h index 97aa4d716e0..f45ddf33b2f 100644 --- a/fftools/ffmpeg.h +++ b/fftools/ffmpeg.h @@ -56,6 +56,7 @@ #define FFMPEG_ROTATION_METADATA 1 #define FFMPEG_OPT_QPHIST 1 #define FFMPEG_OPT_ADRIFT_THRESHOLD 1 +#define FFMPEG_OPT_ENC_TIME_BASE_NUM 1 enum VideoSyncMethod { VSYNC_AUTO = -1, @@ -66,6 +67,11 @@ enum VideoSyncMethod { VSYNC_DROP, }; +enum EncTimeBase { + ENC_TIME_BASE_DEMUX = -1, + ENC_TIME_BASE_FILTER = -2, +}; + #define MAX_STREAMS 1024 /* arbitrary sanity check value */ enum HWAccelID { diff --git a/fftools/ffmpeg_enc.c b/fftools/ffmpeg_enc.c index 0e2285c5a24..1489b2f1793 100644 --- a/fftools/ffmpeg_enc.c +++ b/fftools/ffmpeg_enc.c @@ -264,8 +264,20 @@ int enc_open(OutputStream *ost, AVFrame *frame) fr.num, fr.den, 65535); } - enc_ctx->time_base = ost->enc_timebase.num > 0 ? ost->enc_timebase : - av_inv_q(fr); + if (ost->enc_timebase.num == ENC_TIME_BASE_DEMUX) { + if (fd->dec.tb.num <= 0 || fd->dec.tb.den <= 0) { + av_log(ost, AV_LOG_ERROR, + "Demuxing timebase not available - cannot use it for encoding\n"); + return AVERROR(EINVAL); + } + + enc_ctx->time_base = fd->dec.tb; + } else if (ost->enc_timebase.num == ENC_TIME_BASE_FILTER) { + enc_ctx->time_base = frame->time_base; + } else { + enc_ctx->time_base = ost->enc_timebase.num > 0 ? ost->enc_timebase : + av_inv_q(fr); + } if (!(enc_ctx->time_base.num && enc_ctx->time_base.den)) enc_ctx->time_base = frame->time_base; diff --git a/fftools/ffmpeg_mux_init.c b/fftools/ffmpeg_mux_init.c index 2dba76b82b3..6458414b5f4 100644 --- a/fftools/ffmpeg_mux_init.c +++ b/fftools/ffmpeg_mux_init.c @@ -1171,20 +1171,27 @@ static int ost_add(Muxer *mux, const OptionsContext *o, enum AVMediaType type, MATCH_PER_STREAM_OPT(enc_time_bases, str, enc_time_base, oc, st); if (enc_time_base) { AVRational q; - if (av_parse_ratio(&q, enc_time_base, INT_MAX, 0, NULL) < 0 || - q.den <= 0) { - av_log(ost, AV_LOG_FATAL, "Invalid time base: %s\n", enc_time_base); - return AVERROR(EINVAL); - } - if (q.num < 0) { - if (!ost->ist) { - av_log(ost, AV_LOG_FATAL, - "Cannot use input stream timebase for encoding - " - "no input stream available\n"); - return AVERROR(EINVAL); + if (!strcmp(enc_time_base, "demux")) { + q = (AVRational){ ENC_TIME_BASE_DEMUX, 0 }; + } else if (!strcmp(enc_time_base, "filter")) { + q = (AVRational){ ENC_TIME_BASE_FILTER, 0 }; + } else { + ret = av_parse_ratio(&q, enc_time_base, INT_MAX, 0, NULL); + if (ret < 0 || q.den <= 0 +#if !FFMPEG_OPT_ENC_TIME_BASE_NUM + || q.num < 0 +#endif + ) { + av_log(ost, AV_LOG_FATAL, "Invalid time base: %s\n", enc_time_base); + return ret < 0 ? ret : AVERROR(EINVAL); } - q = ost->ist->st->time_base; +#if FFMPEG_OPT_ENC_TIME_BASE_NUM + if (q.num < 0) + av_log(ost, AV_LOG_WARNING, "-enc_time_base -1 is deprecated," + " use -enc_timebase demux\n"); +#endif } + ost->enc_timebase = q; } } else { diff --git a/tests/fate/video.mak b/tests/fate/video.mak index a2011d0dad8..4e7a77537f4 100644 --- a/tests/fate/video.mak +++ b/tests/fate/video.mak @@ -270,7 +270,7 @@ FATE_VIDEO-$(call FRAMECRC, MXG, MXPEG) += fate-mxpeg fate-mxpeg: CMD = framecrc -idct simple -flags +bitexact -i $(TARGET_SAMPLES)/mxpeg/m1.mxg -an FATE_NUV += fate-nuv-rtjpeg -fate-nuv-rtjpeg: CMD = framecrc -idct simple -i $(TARGET_SAMPLES)/nuv/Today.nuv -an -enc_time_base -1 +fate-nuv-rtjpeg: CMD = framecrc -idct simple -i $(TARGET_SAMPLES)/nuv/Today.nuv -an -enc_time_base demux FATE_NUV += fate-nuv-rtjpeg-fh fate-nuv-rtjpeg-fh: CMD = framecrc -idct simple -i $(TARGET_SAMPLES)/nuv/rtjpeg_frameheader.nuv -an From acde0ae6c7fa65dc89b642d9752c9ec32868709a Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Fri, 7 Jul 2023 11:43:17 +0200 Subject: [PATCH 1875/2172] doc/ffmpeg: fix -enc_time_base documentation Stop claiming the argument is always a floating point number, which * confuses floating point and decimal numbers * is not always true even accounting for the above point --- doc/ffmpeg.texi | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/doc/ffmpeg.texi b/doc/ffmpeg.texi index 59e9fbfcb25..2273c39214a 100644 --- a/doc/ffmpeg.texi +++ b/doc/ffmpeg.texi @@ -1803,8 +1803,7 @@ Try to make the choice automatically, in order to generate a sane output. Default value is -1. @item -enc_time_base[:@var{stream_specifier}] @var{timebase} (@emph{output,per-stream}) -Set the encoder timebase. @var{timebase} is a floating point number, -and can assume one of the following values: +Set the encoder timebase. @var{timebase} can assume one of the following values: @table @option @item 0 @@ -1818,11 +1817,11 @@ Use the timebase from the demuxer. @item filter Use the timebase from the filtergraph. -@item >0 +@item a positive number Use the provided number as the timebase. This field can be provided as a ratio of two integers (e.g. 1:24, 1:48000) -or as a floating point number (e.g. 0.04166, 2.0833e-5) +or as a decimal number (e.g. 0.04166, 2.0833e-5) @end table Default value is 0. From 891167dee584b7c7760fe9a54bb65aec9bca0a56 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Tue, 11 Jul 2023 19:12:23 +0200 Subject: [PATCH 1876/2172] lavc/gifdec: unify get_buffer() calls I/P frames Always call ff_reget_buffer(), which ensures that get_buffer2() is called with AV_GET_BUFFER_FLAG_REF. Fixes #10460. --- libavcodec/gifdec.c | 37 ++++++++++++------------------------- 1 file changed, 12 insertions(+), 25 deletions(-) diff --git a/libavcodec/gifdec.c b/libavcodec/gifdec.c index f2ab783ef03..86aaa8881ce 100644 --- a/libavcodec/gifdec.c +++ b/libavcodec/gifdec.c @@ -489,42 +489,29 @@ static int gif_decode_frame(AVCodecContext *avctx, AVFrame *rframe, return ret; av_frame_unref(s->frame); - if ((ret = ff_get_buffer(avctx, s->frame, 0)) < 0) - return ret; - av_fast_malloc(&s->idx_line, &s->idx_line_size, s->screen_width); if (!s->idx_line) return AVERROR(ENOMEM); - - s->frame->pict_type = AV_PICTURE_TYPE_I; - s->frame->flags |= AV_FRAME_FLAG_KEY; - s->keyframe_ok = 1; - } else { - if (!s->keyframe_ok) { - av_log(avctx, AV_LOG_ERROR, "cannot decode frame without keyframe\n"); - return AVERROR_INVALIDDATA; - } - - if ((ret = ff_reget_buffer(avctx, s->frame, 0)) < 0) - return ret; - - s->frame->pict_type = AV_PICTURE_TYPE_P; - s->frame->flags &= ~AV_FRAME_FLAG_KEY; + } else if (!s->keyframe_ok) { + av_log(avctx, AV_LOG_ERROR, "cannot decode frame without keyframe\n"); + return AVERROR_INVALIDDATA; } + ret = ff_reget_buffer(avctx, s->frame, 0); + if (ret < 0) + return ret; + ret = gif_parse_next_image(s, s->frame); if (ret < 0) return ret; if ((ret = av_frame_ref(rframe, s->frame)) < 0) return ret; - if (s->keyframe) { - rframe->pict_type = AV_PICTURE_TYPE_I; - rframe->flags |= AV_FRAME_FLAG_KEY; - } else { - rframe->pict_type = AV_PICTURE_TYPE_P; - rframe->flags &= ~AV_FRAME_FLAG_KEY; - } + + rframe->pict_type = s->keyframe ? AV_PICTURE_TYPE_I : AV_PICTURE_TYPE_P; + rframe->flags = AV_FRAME_FLAG_KEY * s->keyframe; + s->keyframe_ok |= !!s->keyframe; + *got_frame = 1; return bytestream2_tell(&s->gb); From 138d3ac15dfc444c0e2a35daf7388a4ed353d406 Mon Sep 17 00:00:00 2001 From: Niklas Haas Date: Fri, 14 Jul 2023 12:47:53 +0200 Subject: [PATCH 1877/2172] lavfi/vf_libplacebo: test for renderable pixel formats Requires a new upstream function to test not for *import* support on a given output pixel format, but also whether we can render to it. Fixes: https://github.com/haasn/libplacebo/issues/173 --- libavfilter/vf_libplacebo.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/libavfilter/vf_libplacebo.c b/libavfilter/vf_libplacebo.c index 031265b637a..3b92719225d 100644 --- a/libavfilter/vf_libplacebo.c +++ b/libavfilter/vf_libplacebo.c @@ -1141,6 +1141,11 @@ static int libplacebo_query_format(AVFilterContext *ctx) } } +#if PL_API_VER >= 293 + if (!pl_test_pixfmt_caps(s->gpu, pixfmt, PL_FMT_CAP_RENDERABLE)) + continue; +#endif + RET(ff_add_format(&outfmts, pixfmt)); } From da94c6a00c5fdeb84c14333c285bef9809d35676 Mon Sep 17 00:00:00 2001 From: Timo Rothenpieler Date: Fri, 14 Jul 2023 20:29:22 +0200 Subject: [PATCH 1878/2172] avfilter/vsrc_ddagrab: account for mouse-only frames during probing --- libavfilter/vsrc_ddagrab.c | 28 +++++++++++++++++++++------- 1 file changed, 21 insertions(+), 7 deletions(-) diff --git a/libavfilter/vsrc_ddagrab.c b/libavfilter/vsrc_ddagrab.c index 042842104f0..4bf316c15a4 100644 --- a/libavfilter/vsrc_ddagrab.c +++ b/libavfilter/vsrc_ddagrab.c @@ -585,7 +585,7 @@ static int update_mouse_pointer(AVFilterContext *avctx, DXGI_OUTDUPL_FRAME_INFO return 0; } -static int next_frame_internal(AVFilterContext *avctx, ID3D11Texture2D **desktop_texture) +static int next_frame_internal(AVFilterContext *avctx, ID3D11Texture2D **desktop_texture, int need_frame) { DXGI_OUTDUPL_FRAME_INFO frame_info; DdagrabContext *dda = avctx->priv; @@ -608,18 +608,32 @@ static int next_frame_internal(AVFilterContext *avctx, ID3D11Texture2D **desktop if (dda->draw_mouse) { ret = update_mouse_pointer(avctx, &frame_info); if (ret < 0) - return ret; + goto error; + } + + if (need_frame && (!frame_info.LastPresentTime.QuadPart || !frame_info.AccumulatedFrames)) { + ret = AVERROR(EAGAIN); + goto error; } hr = IDXGIResource_QueryInterface(desktop_resource, &IID_ID3D11Texture2D, (void**)desktop_texture); - IDXGIResource_Release(desktop_resource); - desktop_resource = NULL; + release_resource(&desktop_resource); if (FAILED(hr)) { av_log(avctx, AV_LOG_ERROR, "DXGIResource QueryInterface failed\n"); - return AVERROR_EXTERNAL; + ret = AVERROR_EXTERNAL; + goto error; } return 0; + +error: + release_resource(&desktop_resource); + + hr = IDXGIOutputDuplication_ReleaseFrame(dda->dxgi_outdupl); + if (FAILED(hr)) + av_log(avctx, AV_LOG_ERROR, "DDA error ReleaseFrame failed!\n"); + + return ret; } static int probe_output_format(AVFilterContext *avctx) @@ -631,7 +645,7 @@ static int probe_output_format(AVFilterContext *avctx) av_assert1(!dda->probed_texture); do { - ret = next_frame_internal(avctx, &dda->probed_texture); + ret = next_frame_internal(avctx, &dda->probed_texture, 1); } while(ret == AVERROR(EAGAIN)); if (ret < 0) return ret; @@ -918,7 +932,7 @@ static int ddagrab_request_frame(AVFilterLink *outlink) now -= dda->first_pts; if (!dda->probed_texture) { - ret = next_frame_internal(avctx, &cur_texture); + ret = next_frame_internal(avctx, &cur_texture, 0); } else { cur_texture = dda->probed_texture; dda->probed_texture = NULL; From 3c73200be2aef966a36d8c54359fef68e22c58b6 Mon Sep 17 00:00:00 2001 From: Timo Rothenpieler Date: Sat, 15 Jul 2023 18:48:49 +0200 Subject: [PATCH 1879/2172] avfilter/vsrc_ddagrab: calculate pointer position on rotated screens --- libavfilter/vsrc_ddagrab.c | 54 ++++++++++++++++++++++++++++++++++++-- 1 file changed, 52 insertions(+), 2 deletions(-) diff --git a/libavfilter/vsrc_ddagrab.c b/libavfilter/vsrc_ddagrab.c index 4bf316c15a4..525d48110a3 100644 --- a/libavfilter/vsrc_ddagrab.c +++ b/libavfilter/vsrc_ddagrab.c @@ -533,8 +533,23 @@ static int update_mouse_pointer(AVFilterContext *avctx, DXGI_OUTDUPL_FRAME_INFO return 0; if (frame_info->PointerPosition.Visible) { - dda->mouse_x = frame_info->PointerPosition.Position.x; - dda->mouse_y = frame_info->PointerPosition.Position.y; + switch (dda->output_desc.Rotation) { + case DXGI_MODE_ROTATION_ROTATE90: + dda->mouse_x = frame_info->PointerPosition.Position.y; + dda->mouse_y = dda->output_desc.DesktopCoordinates.right - dda->output_desc.DesktopCoordinates.left - frame_info->PointerPosition.Position.x - 1; + break; + case DXGI_MODE_ROTATION_ROTATE180: + dda->mouse_x = dda->output_desc.DesktopCoordinates.right - dda->output_desc.DesktopCoordinates.left - frame_info->PointerPosition.Position.x - 1; + dda->mouse_y = dda->output_desc.DesktopCoordinates.bottom - dda->output_desc.DesktopCoordinates.top - frame_info->PointerPosition.Position.y - 1; + break; + case DXGI_MODE_ROTATION_ROTATE270: + dda->mouse_x = dda->output_desc.DesktopCoordinates.bottom - dda->output_desc.DesktopCoordinates.top - frame_info->PointerPosition.Position.y - 1; + dda->mouse_y = frame_info->PointerPosition.Position.x; + break; + default: + dda->mouse_x = frame_info->PointerPosition.Position.x; + dda->mouse_y = frame_info->PointerPosition.Position.y; + } } else { dda->mouse_x = dda->mouse_y = -1; } @@ -853,6 +868,41 @@ static int draw_mouse_pointer(AVFilterContext *avctx, AVFrame *frame) D3D11_SUBRESOURCE_DATA init_data = { 0 }; D3D11_BUFFER_DESC buf_desc = { 0 }; + switch (dda->output_desc.Rotation) { + case DXGI_MODE_ROTATION_ROTATE90: + vertices[ 0] = x; vertices[ 1] = y; + vertices[ 5] = x; vertices[ 6] = y - tex_desc.Width; + vertices[10] = x + tex_desc.Height; vertices[11] = y; + vertices[15] = x + tex_desc.Height; vertices[16] = y - tex_desc.Width; + vertices[ 3] = 0.0f; vertices[ 4] = 0.0f; + vertices[ 8] = 1.0f; vertices[ 9] = 0.0f; + vertices[13] = 0.0f; vertices[14] = 1.0f; + vertices[18] = 1.0f; vertices[19] = 1.0f; + break; + case DXGI_MODE_ROTATION_ROTATE180: + vertices[ 0] = x - tex_desc.Width; vertices[ 1] = y; + vertices[ 5] = x - tex_desc.Width; vertices[ 6] = y - tex_desc.Height; + vertices[10] = x; vertices[11] = y; + vertices[15] = x; vertices[16] = y - tex_desc.Height; + vertices[ 3] = 1.0f; vertices[ 4] = 0.0f; + vertices[ 8] = 1.0f; vertices[ 9] = 1.0f; + vertices[13] = 0.0f; vertices[14] = 0.0f; + vertices[18] = 0.0f; vertices[19] = 1.0f; + break; + case DXGI_MODE_ROTATION_ROTATE270: + vertices[ 0] = x - tex_desc.Height; vertices[ 1] = y + tex_desc.Width; + vertices[ 5] = x - tex_desc.Height; vertices[ 6] = y; + vertices[10] = x; vertices[11] = y + tex_desc.Width; + vertices[15] = x; vertices[16] = y; + vertices[ 3] = 1.0f; vertices[ 4] = 1.0f; + vertices[ 8] = 0.0f; vertices[ 9] = 1.0f; + vertices[13] = 1.0f; vertices[14] = 0.0f; + vertices[18] = 0.0f; vertices[19] = 0.0f; + break; + default: + break; + } + num_vertices = sizeof(vertices) / (sizeof(FLOAT) * 5); buf_desc.Usage = D3D11_USAGE_DEFAULT; From 82cb4b1c05519523150f589fd020f5df0b66461b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9mi=20Denis-Courmont?= Date: Fri, 14 Jul 2023 19:23:02 +0300 Subject: [PATCH 1880/2172] lavc/aarch64: remove bogus HAVE_VFP guard The IMDCT offset is only relevant for NEON optimisations. There are no VFP optimisations here that would justify the HAVE_VFP flag. In practice, this makes no difference because HAVE_NEON is practically always true for standard Armv8 platforms. --- libavcodec/aarch64/synth_filter_init.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavcodec/aarch64/synth_filter_init.c b/libavcodec/aarch64/synth_filter_init.c index 801b46e2176..6b6da35b54e 100644 --- a/libavcodec/aarch64/synth_filter_init.c +++ b/libavcodec/aarch64/synth_filter_init.c @@ -28,7 +28,7 @@ #include "asm-offsets.h" -#if HAVE_NEON || HAVE_VFP +#if HAVE_NEON AV_CHECK_OFFSET(FFTContext, imdct_half, IMDCT_HALF); #endif From f03223495385f64e11b29b5a51fcef2a93627184 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9mi=20Denis-Courmont?= Date: Fri, 14 Jul 2023 19:29:32 +0300 Subject: [PATCH 1881/2172] aarch64: remove VFP feature check This is not actually used for anything. The configure check causes the CPU feature flag to be set, but nothing consumes it at all. While AArch64 does have VFP, it is only used for the scalar C code. Conversely, it is still possible to disable VFP, by changing the C compiler flags as before (though that only makes sense for an hypothetical non-standard Armv8 platform without VFP). Note that this retains the "vfp" option flag, for backward compatibility and on the very remote but theoretically possible chance that FFmpeg actually makes use of it in the future. AV_CPU_FLAG_VFP is retained as it is actually used by AArch32. --- configure | 4 +--- libavutil/aarch64/cpu.c | 3 +-- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/configure b/configure index 0ab0761011b..dab3fb90363 100755 --- a/configure +++ b/configure @@ -2668,7 +2668,7 @@ armv6t2_deps="arm" armv8_deps="aarch64" neon_deps_any="aarch64 arm" intrinsics_neon_deps="neon" -vfp_deps_any="aarch64 arm" +vfp_deps="arm" vfpv3_deps="vfp" setend_deps="arm" dotprod_deps="aarch64 neon" @@ -6058,7 +6058,6 @@ if enabled aarch64; then enabled armv8 && check_insn armv8 'prfm pldl1strm, [x0]' # internal assembler in clang 3.3 does not support this instruction enabled neon && check_insn neon 'ext v0.8B, v0.8B, v1.8B, #1' - enabled vfp && check_insn vfp 'fmadd d0, d0, d1, d2' archext_list="dotprod i8mm" enabled dotprod && check_archext_insn dotprod 'udot v0.4s, v0.16b, v0.16b' @@ -7705,7 +7704,6 @@ if enabled x86; then fi if enabled aarch64; then echo "NEON enabled ${neon-no}" - echo "VFP enabled ${vfp-no}" echo "DOTPROD enabled ${dotprod-no}" echo "I8MM enabled ${i8mm-no}" fi diff --git a/libavutil/aarch64/cpu.c b/libavutil/aarch64/cpu.c index a8cb301dd75..2803b314436 100644 --- a/libavutil/aarch64/cpu.c +++ b/libavutil/aarch64/cpu.c @@ -107,8 +107,7 @@ static int detect_flags(void) int ff_get_cpu_flags_aarch64(void) { int flags = AV_CPU_FLAG_ARMV8 * HAVE_ARMV8 | - AV_CPU_FLAG_NEON * HAVE_NEON | - AV_CPU_FLAG_VFP * HAVE_VFP; + AV_CPU_FLAG_NEON * HAVE_NEON; #ifdef __ARM_FEATURE_DOTPROD flags |= AV_CPU_FLAG_DOTPROD; From c183f840fa9aee6000ed90466ccbd9671f1ad7eb Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Sat, 15 Jul 2023 23:13:44 +0200 Subject: [PATCH 1882/2172] avfilter/af_axcorrelate: add another algorithm for calculation Rewrite EOF logic while here. --- doc/filters.texi | 4 +- libavfilter/af_axcorrelate.c | 143 +++++++++++++++++++++++++++-------- 2 files changed, 114 insertions(+), 33 deletions(-) diff --git a/doc/filters.texi b/doc/filters.texi index 770c5d0272d..e5325c7410b 100644 --- a/doc/filters.texi +++ b/doc/filters.texi @@ -3762,8 +3762,8 @@ Set size of segment over which cross-correlation is calculated. Default is 256. Allowed range is from 2 to 131072. @item algo -Set algorithm for cross-correlation. Can be @code{slow} or @code{fast}. -Default is @code{slow}. Fast algorithm assumes mean values over any given segment +Set algorithm for cross-correlation. Can be @code{slow} or @code{fast} or @code{best}. +Default is @code{best}. Fast algorithm assumes mean values over any given segment are always zero and thus need much less calculations to make. This is generally not true, but is valid for typical audio streams. @end table diff --git a/libavfilter/af_axcorrelate.c b/libavfilter/af_axcorrelate.c index 9be3f1c9215..a20c79f4209 100644 --- a/libavfilter/af_axcorrelate.c +++ b/libavfilter/af_axcorrelate.c @@ -110,7 +110,7 @@ static int xcorrelate_slow_##suffix(AVFilterContext *ctx, \ AVFrame *out, int available) \ { \ AudioXCorrelateContext *s = ctx->priv; \ - const int size = FFMIN(available, s->size); \ + const int size = s->size; \ int used; \ \ for (int ch = 0; ch < out->ch_layout.nb_channels; ch++) { \ @@ -127,13 +127,13 @@ static int xcorrelate_slow_##suffix(AVFilterContext *ctx, \ used = 1; \ } \ \ - for (int n = 0; n < out->nb_samples; n++) { \ - const int idx = available <= s->size ? out->nb_samples - n - 1 : n + size; \ - \ - dst[n] = xcorrelate_##suffix(x + n, y + n, \ - sumx[0], sumy[0], \ - size); \ - \ + for (int n = 0; n < out->nb_samples; n++) { \ + const int idx = n + size; \ + \ + dst[n] = xcorrelate_##suffix(x + n, y + n, \ + sumx[0], sumy[0],\ + size); \ + \ sumx[0] -= x[n]; \ sumx[0] += x[idx]; \ sumy[0] -= y[n]; \ @@ -147,12 +147,15 @@ static int xcorrelate_slow_##suffix(AVFilterContext *ctx, \ XCORRELATE_SLOW(f, float) XCORRELATE_SLOW(d, double) -#define XCORRELATE_FAST(suffix, type, zero, small, sqrtfun) \ +#define clipf(x) (av_clipf(x, -1.f, 1.f)) +#define clipd(x) (av_clipd(x, -1.0, 1.0)) + +#define XCORRELATE_FAST(suffix, type, zero, small, sqrtfun, CLIP) \ static int xcorrelate_fast_##suffix(AVFilterContext *ctx, AVFrame *out, \ int available) \ { \ AudioXCorrelateContext *s = ctx->priv; \ - const int size = FFMIN(available, s->size); \ + const int size = s->size; \ int used; \ \ for (int ch = 0; ch < out->ch_layout.nb_channels; ch++) { \ @@ -171,14 +174,14 @@ static int xcorrelate_fast_##suffix(AVFilterContext *ctx, AVFrame *out, \ used = 1; \ } \ \ - for (int n = 0; n < out->nb_samples; n++) { \ - const int idx = available <= s->size ? out->nb_samples - n - 1 : n + size; \ - type num, den; \ + for (int n = 0; n < out->nb_samples; n++) { \ + const int idx = n + size; \ + type num, den; \ \ num = num_sum[0] / size; \ den = sqrtfun((den_sumx[0] * den_sumy[0]) / size / size); \ \ - dst[n] = den <= small ? zero : num / den; \ + dst[n] = den <= small ? zero : CLIP(num / den); \ \ num_sum[0] -= x[n] * y[n]; \ num_sum[0] += x[idx] * y[idx]; \ @@ -194,20 +197,82 @@ static int xcorrelate_fast_##suffix(AVFilterContext *ctx, AVFrame *out, \ return used; \ } -XCORRELATE_FAST(f, float, 0.f, 1e-6f, sqrtf) -XCORRELATE_FAST(d, double, 0.0, 1e-9, sqrt) +XCORRELATE_FAST(f, float, 0.f, 1e-6f, sqrtf, clipf) +XCORRELATE_FAST(d, double, 0.0, 1e-9, sqrt, clipd) + +#define XCORRELATE_BEST(suffix, type, zero, small, sqrtfun, FMAX, CLIP) \ +static int xcorrelate_best_##suffix(AVFilterContext *ctx, AVFrame *out, \ + int available) \ +{ \ + AudioXCorrelateContext *s = ctx->priv; \ + const int size = s->size; \ + int used; \ + \ + for (int ch = 0; ch < out->ch_layout.nb_channels; ch++) { \ + const type *x = (const type *)s->cache[0]->extended_data[ch]; \ + const type *y = (const type *)s->cache[1]->extended_data[ch]; \ + type *mean_sumx = (type *)s->mean_sum[0]->extended_data[ch]; \ + type *mean_sumy = (type *)s->mean_sum[1]->extended_data[ch]; \ + type *num_sum = (type *)s->num_sum->extended_data[ch]; \ + type *den_sumx = (type *)s->den_sum[0]->extended_data[ch]; \ + type *den_sumy = (type *)s->den_sum[1]->extended_data[ch]; \ + type *dst = (type *)out->extended_data[ch]; \ + \ + used = s->used; \ + if (!used) { \ + num_sum[0] = square_sum_##suffix(x, y, size); \ + den_sumx[0] = square_sum_##suffix(x, x, size); \ + den_sumy[0] = square_sum_##suffix(y, y, size); \ + mean_sumx[0] = mean_sum_##suffix(x, size); \ + mean_sumy[0] = mean_sum_##suffix(y, size); \ + used = 1; \ + } \ + \ + for (int n = 0; n < out->nb_samples; n++) { \ + const int idx = n + size; \ + type num, den, xm, ym; \ + \ + xm = mean_sumx[0] / size; \ + ym = mean_sumy[0] / size; \ + num = num_sum[0] - size * xm * ym; \ + den = sqrtfun(FMAX(den_sumx[0] - size * xm * xm, zero)) * \ + sqrtfun(FMAX(den_sumy[0] - size * ym * ym, zero)); \ + \ + dst[n] = den <= small ? zero : CLIP(num / den); \ + \ + mean_sumx[0]-= x[n]; \ + mean_sumx[0]+= x[idx]; \ + mean_sumy[0]-= y[n]; \ + mean_sumy[0]+= y[idx]; \ + num_sum[0] -= x[n] * y[n]; \ + num_sum[0] += x[idx] * y[idx]; \ + den_sumx[0] -= x[n] * x[n]; \ + den_sumx[0] += x[idx] * x[idx]; \ + den_sumx[0] = FMAX(den_sumx[0], zero); \ + den_sumy[0] -= y[n] * y[n]; \ + den_sumy[0] += y[idx] * y[idx]; \ + den_sumy[0] = FMAX(den_sumy[0], zero); \ + } \ + } \ + \ + return used; \ +} + +XCORRELATE_BEST(f, float, 0.f, 1e-6f, sqrtf, fmaxf, clipf) +XCORRELATE_BEST(d, double, 0.0, 1e-9, sqrt, fmax, clipd) static int activate(AVFilterContext *ctx) { AudioXCorrelateContext *s = ctx->priv; + AVFilterLink *outlink = ctx->outputs[0]; AVFrame *frame = NULL; int ret, status; int available; int64_t pts; - FF_FILTER_FORWARD_STATUS_BACK_ALL(ctx->outputs[0], ctx); + FF_FILTER_FORWARD_STATUS_BACK_ALL(outlink, ctx); - for (int i = 0; i < 2; i++) { + for (int i = 0; i < 2 && !s->eof; i++) { ret = ff_inlink_consume_frame(ctx->inputs[i], &frame); if (ret > 0) { if (s->pts == AV_NOPTS_VALUE) @@ -221,20 +286,20 @@ static int activate(AVFilterContext *ctx) } available = FFMIN(av_audio_fifo_size(s->fifo[0]), av_audio_fifo_size(s->fifo[1])); - if (available > s->size || (s->eof && available > 0)) { - const int out_samples = s->eof ? available : available - s->size; + if (available > s->size) { + const int out_samples = available - s->size; AVFrame *out; if (!s->cache[0] || s->cache[0]->nb_samples < available) { av_frame_free(&s->cache[0]); - s->cache[0] = ff_get_audio_buffer(ctx->outputs[0], available); + s->cache[0] = ff_get_audio_buffer(outlink, available); if (!s->cache[0]) return AVERROR(ENOMEM); } if (!s->cache[1] || s->cache[1]->nb_samples < available) { av_frame_free(&s->cache[1]); - s->cache[1] = ff_get_audio_buffer(ctx->outputs[0], available); + s->cache[1] = ff_get_audio_buffer(outlink, available); if (!s->cache[1]) return AVERROR(ENOMEM); } @@ -247,7 +312,7 @@ static int activate(AVFilterContext *ctx) if (ret < 0) return ret; - out = ff_get_audio_buffer(ctx->outputs[0], out_samples); + out = ff_get_audio_buffer(outlink, out_samples); if (!out) return AVERROR(ENOMEM); @@ -259,18 +324,31 @@ static int activate(AVFilterContext *ctx) av_audio_fifo_drain(s->fifo[0], out_samples); av_audio_fifo_drain(s->fifo[1], out_samples); - return ff_filter_frame(ctx->outputs[0], out); + return ff_filter_frame(outlink, out); } for (int i = 0; i < 2 && !s->eof; i++) { - if (ff_inlink_acknowledge_status(ctx->inputs[i], &status, &pts)) + if (ff_inlink_acknowledge_status(ctx->inputs[i], &status, &pts)) { + AVFrame *silence = ff_get_audio_buffer(outlink, s->size); + s->eof = 1; + if (!silence) + return AVERROR(ENOMEM); + + av_audio_fifo_write(s->fifo[0], (void **)silence->extended_data, + silence->nb_samples); + + av_audio_fifo_write(s->fifo[1], (void **)silence->extended_data, + silence->nb_samples); + + av_frame_free(&silence); + } } if (s->eof && - (av_audio_fifo_size(s->fifo[0]) <= 0 || - av_audio_fifo_size(s->fifo[1]) <= 0)) { - ff_outlink_set_status(ctx->outputs[0], AVERROR_EOF, s->pts); + (av_audio_fifo_size(s->fifo[0]) <= s->size || + av_audio_fifo_size(s->fifo[1]) <= s->size)) { + ff_outlink_set_status(outlink, AVERROR_EOF, s->pts); return 0; } @@ -280,7 +358,7 @@ static int activate(AVFilterContext *ctx) return 0; } - if (ff_outlink_frame_wanted(ctx->outputs[0]) && !s->eof) { + if (ff_outlink_frame_wanted(outlink) && !s->eof) { for (int i = 0; i < 2; i++) { if (av_audio_fifo_size(s->fifo[i]) > s->size) continue; @@ -316,12 +394,14 @@ static int config_output(AVFilterLink *outlink) switch (s->algo) { case 0: s->xcorrelate = xcorrelate_slow_f; break; case 1: s->xcorrelate = xcorrelate_fast_f; break; + case 2: s->xcorrelate = xcorrelate_best_f; break; } if (outlink->format == AV_SAMPLE_FMT_DBLP) { switch (s->algo) { case 0: s->xcorrelate = xcorrelate_slow_d; break; case 1: s->xcorrelate = xcorrelate_fast_d; break; + case 2: s->xcorrelate = xcorrelate_best_d; break; } } @@ -366,10 +446,11 @@ static const AVFilterPad outputs[] = { #define OFFSET(x) offsetof(AudioXCorrelateContext, x) static const AVOption axcorrelate_options[] = { - { "size", "set segment size", OFFSET(size), AV_OPT_TYPE_INT, {.i64=256}, 2, 131072, AF }, - { "algo", "set algorithm", OFFSET(algo), AV_OPT_TYPE_INT, {.i64=0}, 0, 1, AF, "algo" }, + { "size", "set the segment size", OFFSET(size), AV_OPT_TYPE_INT, {.i64=256}, 2, 131072, AF }, + { "algo", "set the algorithm", OFFSET(algo), AV_OPT_TYPE_INT, {.i64=2}, 0, 2, AF, "algo" }, { "slow", "slow algorithm", 0, AV_OPT_TYPE_CONST, {.i64=0}, 0, 0, AF, "algo" }, { "fast", "fast algorithm", 0, AV_OPT_TYPE_CONST, {.i64=1}, 0, 0, AF, "algo" }, + { "best", "best algorithm", 0, AV_OPT_TYPE_CONST, {.i64=2}, 0, 0, AF, "algo" }, { NULL } }; From e047d9c62bff5920074c516da966952cee20da66 Mon Sep 17 00:00:00 2001 From: James Almer Date: Fri, 14 Jul 2023 09:31:32 -0300 Subject: [PATCH 1883/2172] avcodec/mpegvideo_dec: properly set output frames as keyframes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Should fix ticket #10426. Reviewed-by: Jan Ekström Signed-off-by: James Almer --- libavcodec/mpegvideo_dec.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libavcodec/mpegvideo_dec.c b/libavcodec/mpegvideo_dec.c index fcca147cd65..670b0912e21 100644 --- a/libavcodec/mpegvideo_dec.c +++ b/libavcodec/mpegvideo_dec.c @@ -344,9 +344,9 @@ FF_ENABLE_DEPRECATION_WARNINGS s->current_picture_ptr->f->pict_type = s->pict_type; if (s->pict_type == AV_PICTURE_TYPE_I) - s->current_picture.f->flags |= AV_FRAME_FLAG_KEY; + s->current_picture_ptr->f->flags |= AV_FRAME_FLAG_KEY; else - s->current_picture.f->flags &= ~AV_FRAME_FLAG_KEY; + s->current_picture_ptr->f->flags &= ~AV_FRAME_FLAG_KEY; if ((ret = ff_mpeg_ref_picture(s->avctx, &s->current_picture, s->current_picture_ptr)) < 0) From 35342dc390781f310daa53e6c850285863ab5829 Mon Sep 17 00:00:00 2001 From: Pavel Koshevoy Date: Sat, 15 Jul 2023 13:36:03 -0600 Subject: [PATCH 1884/2172] lavc/audiotoolbox: fix build failure on osx 10.5 (v3) Reviewed-by: Marvin Scholz Signed-off-by: James Almer --- libavcodec/audiotoolboxdec.c | 2 ++ libavcodec/audiotoolboxenc.c | 4 ++++ 2 files changed, 6 insertions(+) diff --git a/libavcodec/audiotoolboxdec.c b/libavcodec/audiotoolboxdec.c index 82babe3d317..5456f916cf4 100644 --- a/libavcodec/audiotoolboxdec.c +++ b/libavcodec/audiotoolboxdec.c @@ -71,10 +71,12 @@ static UInt32 ffat_get_format_id(enum AVCodecID codec, int profile) return kAudioFormatAMR; case AV_CODEC_ID_EAC3: return kAudioFormatEnhancedAC3; +#if MAC_OS_X_VERSION_MIN_REQUIRED >= 1060 case AV_CODEC_ID_GSM_MS: return kAudioFormatMicrosoftGSM; case AV_CODEC_ID_ILBC: return kAudioFormatiLBC; +#endif case AV_CODEC_ID_MP1: return kAudioFormatMPEGLayer1; case AV_CODEC_ID_MP2: diff --git a/libavcodec/audiotoolboxenc.c b/libavcodec/audiotoolboxenc.c index 1ccfda4d207..46aca4c7ff9 100644 --- a/libavcodec/audiotoolboxenc.c +++ b/libavcodec/audiotoolboxenc.c @@ -69,15 +69,19 @@ static UInt32 ffat_get_format_id(enum AVCodecID codec, int profile) return kAudioFormatMPEG4AAC_HE_V2; case FF_PROFILE_AAC_LD: return kAudioFormatMPEG4AAC_LD; +#if MAC_OS_X_VERSION_MIN_REQUIRED >= 1060 case FF_PROFILE_AAC_ELD: return kAudioFormatMPEG4AAC_ELD; +#endif } case AV_CODEC_ID_ADPCM_IMA_QT: return kAudioFormatAppleIMA4; case AV_CODEC_ID_ALAC: return kAudioFormatAppleLossless; +#if MAC_OS_X_VERSION_MIN_REQUIRED >= 1060 case AV_CODEC_ID_ILBC: return kAudioFormatiLBC; +#endif case AV_CODEC_ID_PCM_ALAW: return kAudioFormatALaw; case AV_CODEC_ID_PCM_MULAW: From 153cf85b246a7931fac6344f2189cd268ca9e0aa Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Sun, 16 Jul 2023 10:27:29 +0200 Subject: [PATCH 1885/2172] fftools/ffmpeg_mux_init: fix an array declaration MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit map_func is supposed to be an array of const pointer to function returning int, not an array of pointer to function returning const int. Reported-By: Martin Storsjö --- fftools/ffmpeg_mux_init.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fftools/ffmpeg_mux_init.c b/fftools/ffmpeg_mux_init.c index 6458414b5f4..c2630dd8937 100644 --- a/fftools/ffmpeg_mux_init.c +++ b/fftools/ffmpeg_mux_init.c @@ -1648,7 +1648,7 @@ static int of_add_attachments(Muxer *mux, const OptionsContext *o) static int create_streams(Muxer *mux, const OptionsContext *o) { - static const int (*map_func[])(Muxer *mux, const OptionsContext *o) = { + static int (* const map_func[])(Muxer *mux, const OptionsContext *o) = { [AVMEDIA_TYPE_VIDEO] = map_auto_video, [AVMEDIA_TYPE_AUDIO] = map_auto_audio, [AVMEDIA_TYPE_SUBTITLE] = map_auto_subtitle, From 9a7f060c3264fd6042b54834374cd8e3a0169224 Mon Sep 17 00:00:00 2001 From: Marton Balint Date: Sun, 9 Jul 2023 10:38:21 +0200 Subject: [PATCH 1886/2172] avutil/random_seed: turn off buffering when reading from random Signed-off-by: Marton Balint --- libavutil/random_seed.c | 1 + 1 file changed, 1 insertion(+) diff --git a/libavutil/random_seed.c b/libavutil/random_seed.c index f167b172f28..6d399cee49c 100644 --- a/libavutil/random_seed.c +++ b/libavutil/random_seed.c @@ -59,6 +59,7 @@ static int read_random(uint8_t *dst, size_t len, const char *file) if (!fp) return AVERROR_UNKNOWN; + setvbuf(fp, NULL, _IONBF, 0); err = fread(dst, 1, len, fp); fclose(fp); From 36f4e6f8f4c14b3a571815c55d213d095b54df6f Mon Sep 17 00:00:00 2001 From: Marton Balint Date: Sun, 2 Jul 2023 20:57:47 +0200 Subject: [PATCH 1887/2172] avformat/hlsenc: use av_random_bytes() for generating AES128 key av_random_bytes() can use OS provided strong random functions and does not depend soley on openssl/gcrypt external libraries. Fixes ticket #10441. Signed-off-by: Marton Balint --- configure | 1 - libavformat/hlsenc.c | 23 ++--------------------- 2 files changed, 2 insertions(+), 22 deletions(-) diff --git a/configure b/configure index dab3fb90363..b018abf139a 100755 --- a/configure +++ b/configure @@ -3507,7 +3507,6 @@ gxf_muxer_select="pcm_rechunk_bsf" hds_muxer_select="flv_muxer" hls_demuxer_select="adts_header ac3_parser mov_demuxer mpegts_demuxer" hls_muxer_select="mov_muxer 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" diff --git a/libavformat/hlsenc.c b/libavformat/hlsenc.c index 1e0848ce3db..27d97f5f729 100644 --- a/libavformat/hlsenc.c +++ b/libavformat/hlsenc.c @@ -27,12 +27,6 @@ #include #endif -#if CONFIG_GCRYPT -#include -#elif CONFIG_OPENSSL -#include -#endif - #include "libavutil/avassert.h" #include "libavutil/mathematics.h" #include "libavutil/avstring.h" @@ -40,6 +34,7 @@ #include "libavutil/intreadwrite.h" #include "libavutil/opt.h" #include "libavutil/log.h" +#include "libavutil/random_seed.h" #include "libavutil/time.h" #include "libavutil/time_internal.h" @@ -710,20 +705,6 @@ static int hls_delete_old_segments(AVFormatContext *s, HLSContext *hls, return ret; } -static int randomize(uint8_t *buf, int len) -{ -#if CONFIG_GCRYPT - gcry_randomize(buf, len, GCRY_VERY_STRONG_RANDOM); - return 0; -#elif CONFIG_OPENSSL - if (RAND_bytes(buf, len)) - return 0; -#else - return AVERROR(ENOSYS); -#endif - return AVERROR(EINVAL); -} - static int do_encrypt(AVFormatContext *s, VariantStream *vs) { HLSContext *hls = s->priv_data; @@ -775,7 +756,7 @@ static int do_encrypt(AVFormatContext *s, VariantStream *vs) if (!*hls->key_string) { AVDictionary *options = NULL; if (!hls->key) { - if ((ret = randomize(key, sizeof(key))) < 0) { + if ((ret = av_random_bytes(key, sizeof(key))) < 0) { av_log(s, AV_LOG_ERROR, "Cannot generate a strong random key\n"); return ret; } From b6305a787330af716377f89d1a09afad38c3f05f Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt Date: Sun, 16 Jul 2023 16:01:58 +0200 Subject: [PATCH 1888/2172] avcodec/evc_ps: Fix size of tile_(row|column) arrays Prevents out-of-bound writes when parsing tile row heights. Fixes Coverity issue #1538300. Reviewed-by: James Almer Signed-off-by: Andreas Rheinhardt --- libavcodec/evc_ps.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libavcodec/evc_ps.h b/libavcodec/evc_ps.h index 0bbec1f1384..336953b1769 100644 --- a/libavcodec/evc_ps.h +++ b/libavcodec/evc_ps.h @@ -192,8 +192,8 @@ typedef struct EVCParserPPS { uint32_t num_tile_columns_minus1; // ue(v) uint32_t num_tile_rows_minus1; // ue(v) uint8_t uniform_tile_spacing_flag; // u(1) - uint32_t tile_column_width_minus1[EVC_MAX_TILE_ROWS]; // ue(v) - uint32_t tile_row_height_minus1[EVC_MAX_TILE_COLUMNS]; // ue(v) + uint32_t tile_column_width_minus1[EVC_MAX_TILE_COLUMNS]; // ue(v) + uint32_t tile_row_height_minus1[EVC_MAX_TILE_ROWS]; // ue(v) uint8_t loop_filter_across_tiles_enabled_flag; // u(1) uint32_t tile_offset_len_minus1; // ue(v) uint8_t tile_id_len_minus1; // ue(v) From a28aa0475db99cc66c37c98fd5330e313817709c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9mi=20Denis-Courmont?= Date: Thu, 13 Jul 2023 23:16:03 +0300 Subject: [PATCH 1889/2172] lavc/vorbisdsp: unroll RISC-V V inverse_coupling This increases the group multiplier as per T-Head C910 benchmarks: inverse_coupling_c: 4597.0 inverse_coupling_rvv_i32: 1312.7 (m1) inverse_coupling_rvv_i32: 1116.7 (m2) inverse_coupling_rvv_i32: 732.2 (m4) inverse_coupling_rvv_i32: 898.0 (m8) --- libavcodec/riscv/vorbisdsp_rvv.S | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavcodec/riscv/vorbisdsp_rvv.S b/libavcodec/riscv/vorbisdsp_rvv.S index f45e7dc2f13..81a6c62a657 100644 --- a/libavcodec/riscv/vorbisdsp_rvv.S +++ b/libavcodec/riscv/vorbisdsp_rvv.S @@ -23,7 +23,7 @@ func ff_vorbis_inverse_coupling_rvv, zve32f fmv.w.x ft0, zero 1: - vsetvli t0, a2, e32, m1, ta, ma + vsetvli t0, a2, e32, m4, ta, ma vle32.v v16, (a1) sub a2, a2, t0 vle32.v v24, (a0) From c541ecf0dc38b6da3ba3d290b0db7d147775931f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9mi=20Denis-Courmont?= Date: Thu, 13 Jul 2023 23:16:03 +0300 Subject: [PATCH 1890/2172] lavc/alacdsp: unroll RISC-V V loops This increases the group multiplier as per T-Head C910 benchmarks: alac_append_extra_bits_mono_c: 803.0 alac_append_extra_bits_stereo_c: 1604.2 alac_decorrelate_stereo_c: 1077.5 LMUL=1 alac_append_extra_bits_mono_rvv_i32: 418.2 alac_append_extra_bits_stereo_rvv_i32: 693.2 alac_decorrelate_stereo_rvv_i32: 673.5 LMUL=2 alac_append_extra_bits_mono_rvv_i32: 382.2 alac_append_extra_bits_stereo_rvv_i32: 648.2 alac_decorrelate_stereo_rvv_i32: 542.7 LMUL=4 alac_append_extra_bits_mono_rvv_i32: 241.5 alac_append_extra_bits_stereo_rvv_i32: 512.7 alac_decorrelate_stereo_rvv_i32: 364.2 LMUL=8 alac_append_extra_bits_mono_rvv_i32: 239.7 alac_append_extra_bits_stereo_rvv_i32: 497.2 alac_decorrelate_stereo_rvv_i32: 426.7 --- libavcodec/riscv/alacdsp_rvv.S | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/libavcodec/riscv/alacdsp_rvv.S b/libavcodec/riscv/alacdsp_rvv.S index 8fbe3fbe778..8efb04e0c8d 100644 --- a/libavcodec/riscv/alacdsp_rvv.S +++ b/libavcodec/riscv/alacdsp_rvv.S @@ -25,7 +25,7 @@ func ff_alac_decorrelate_stereo_rvv, zve32x ld a4, 8(a0) ld a0, 0(a0) 1: - vsetvli t0, a1, e32, m1, ta, ma + vsetvli t0, a1, e32, m4, ta, ma vle32.v v24, (a4) sub a1, a1, t0 vle32.v v16, (a0) @@ -47,7 +47,7 @@ func ff_alac_append_extra_bits_mono_rvv, zve32x ld a0, (a0) ld a1, (a1) 1: - vsetvli t0, a4, e32, m1, ta, ma + vsetvli t0, a4, e32, m8, ta, ma vle32.v v16, (a0) sub a4, a4, t0 vle32.v v24, (a1) @@ -67,7 +67,7 @@ func ff_alac_append_extra_bits_stereo_rvv, zve32x ld a7, 8(a1) ld a1, (a1) 1: - vsetvli t0, a4, e32, m1, ta, ma + vsetvli t0, a4, e32, m8, ta, ma vle32.v v16, (a0) sub a4, a4, t0 vle32.v v0, (a6) From 31979127f830b9f93908affe2759afeeb097eb27 Mon Sep 17 00:00:00 2001 From: James Almer Date: Fri, 14 Jul 2023 14:00:57 -0300 Subject: [PATCH 1891/2172] avcodec/decode: factor out filling frame props Signed-off-by: James Almer --- libavcodec/decode.c | 69 ++++++++++++++++----------------------------- 1 file changed, 24 insertions(+), 45 deletions(-) diff --git a/libavcodec/decode.c b/libavcodec/decode.c index a19cca1a7ce..f0e6acc03e8 100644 --- a/libavcodec/decode.c +++ b/libavcodec/decode.c @@ -541,28 +541,31 @@ static int detect_colorspace(av_unused AVCodecContext *c, av_unused AVFrame *f) } #endif -static int fill_frame_props(AVCodecContext *avctx, AVFrame *frame) +static int fill_frame_props(const AVCodecContext *avctx, AVFrame *frame) { int ret; + if (frame->color_primaries == AVCOL_PRI_UNSPECIFIED) + frame->color_primaries = avctx->color_primaries; + if (frame->color_trc == AVCOL_TRC_UNSPECIFIED) + frame->color_trc = avctx->color_trc; + if (frame->colorspace == AVCOL_SPC_UNSPECIFIED) + frame->colorspace = avctx->colorspace; + if (frame->color_range == AVCOL_RANGE_UNSPECIFIED) + frame->color_range = avctx->color_range; + if (frame->chroma_location == AVCHROMA_LOC_UNSPECIFIED) + frame->chroma_location = avctx->chroma_sample_location; + if (avctx->codec_type == AVMEDIA_TYPE_VIDEO) { - //FIXME these should be under if(!avctx->has_b_frames) - /* get_buffer is supposed to set frame parameters */ - if (!(avctx->codec->capabilities & AV_CODEC_CAP_DR1)) { if (!frame->sample_aspect_ratio.num) frame->sample_aspect_ratio = avctx->sample_aspect_ratio; - if (!frame->width) frame->width = avctx->width; - if (!frame->height) frame->height = avctx->height; if (frame->format == AV_PIX_FMT_NONE) frame->format = avctx->pix_fmt; - } } else if (avctx->codec->type == AVMEDIA_TYPE_AUDIO) { if (frame->format == AV_SAMPLE_FMT_NONE) frame->format = avctx->sample_fmt; if (!frame->ch_layout.nb_channels) { ret = av_channel_layout_copy(&frame->ch_layout, &avctx->ch_layout); - if (ret < 0) { - av_frame_unref(frame); + if (ret < 0) return ret; - } } #if FF_API_OLD_CHANNEL_LAYOUT FF_DISABLE_DEPRECATION_WARNINGS @@ -629,7 +632,12 @@ static int decode_receive_frame_internal(AVCodecContext *avctx, AVFrame *frame) } if (!ret) { - if (avctx->codec_type != AVMEDIA_TYPE_VIDEO) + if (avctx->codec_type == AVMEDIA_TYPE_VIDEO) { + if (!frame->width) + frame->width = avctx->width; + if (!frame->height) + frame->height = avctx->height; + } else frame->flags |= AV_FRAME_FLAG_KEY; ret = fill_frame_props(avctx, frame); @@ -1453,9 +1461,10 @@ FF_ENABLE_DEPRECATION_WARNINGS int ff_decode_frame_props(AVCodecContext *avctx, AVFrame *frame) { const AVPacket *pkt = avctx->internal->last_pkt_props; + int ret; if (!(ffcodec(avctx->codec)->caps_internal & FF_CODEC_CAP_SETS_FRAME_PROPS)) { - int ret = ff_decode_frame_props_from_pkt(avctx, frame, pkt); + ret = ff_decode_frame_props_from_pkt(avctx, frame, pkt); if (ret < 0) return ret; #if FF_API_FRAME_PKT @@ -1470,23 +1479,12 @@ FF_DISABLE_DEPRECATION_WARNINGS FF_ENABLE_DEPRECATION_WARNINGS #endif - if (frame->color_primaries == AVCOL_PRI_UNSPECIFIED) - frame->color_primaries = avctx->color_primaries; - if (frame->color_trc == AVCOL_TRC_UNSPECIFIED) - frame->color_trc = avctx->color_trc; - if (frame->colorspace == AVCOL_SPC_UNSPECIFIED) - frame->colorspace = avctx->colorspace; - if (frame->color_range == AVCOL_RANGE_UNSPECIFIED) - frame->color_range = avctx->color_range; - if (frame->chroma_location == AVCHROMA_LOC_UNSPECIFIED) - frame->chroma_location = avctx->chroma_sample_location; + ret = fill_frame_props(avctx, frame); + if (ret < 0) + return ret; switch (avctx->codec->type) { case AVMEDIA_TYPE_VIDEO: - frame->format = avctx->pix_fmt; - if (!frame->sample_aspect_ratio.num) - frame->sample_aspect_ratio = avctx->sample_aspect_ratio; - if (frame->width && frame->height && av_image_check_sar(frame->width, frame->height, frame->sample_aspect_ratio) < 0) { @@ -1495,25 +1493,6 @@ FF_ENABLE_DEPRECATION_WARNINGS frame->sample_aspect_ratio.den); frame->sample_aspect_ratio = (AVRational){ 0, 1 }; } - - break; - case AVMEDIA_TYPE_AUDIO: - if (!frame->sample_rate) - frame->sample_rate = avctx->sample_rate; - if (frame->format < 0) - frame->format = avctx->sample_fmt; - if (!frame->ch_layout.nb_channels) { - int ret = av_channel_layout_copy(&frame->ch_layout, &avctx->ch_layout); - if (ret < 0) - return ret; - } -#if FF_API_OLD_CHANNEL_LAYOUT -FF_DISABLE_DEPRECATION_WARNINGS - frame->channels = frame->ch_layout.nb_channels; - frame->channel_layout = frame->ch_layout.order == AV_CHANNEL_ORDER_NATIVE ? - frame->ch_layout.u.mask : 0; -FF_ENABLE_DEPRECATION_WARNINGS -#endif break; } return 0; From bfe15b81b317bc859223d6804f768ecda7b73db3 Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt Date: Sun, 16 Jul 2023 16:09:57 +0200 Subject: [PATCH 1892/2172] fftools/ffmpeg_enc: Remove always-true checks frame is always != NULL for audio and video here (this is checked by an assert and the frame is already dereferenced before it reaches this code here). Fixes Coverity issue #1538858. Reviewed-by: Anton Khirnov Signed-off-by: Andreas Rheinhardt --- fftools/ffmpeg_enc.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/fftools/ffmpeg_enc.c b/fftools/ffmpeg_enc.c index 1489b2f1793..2c7e29af246 100644 --- a/fftools/ffmpeg_enc.c +++ b/fftools/ffmpeg_enc.c @@ -304,20 +304,17 @@ int enc_open(OutputStream *ost, AVFrame *frame) enc_ctx->bits_per_raw_sample = FFMIN(fd->bits_per_raw_sample, av_pix_fmt_desc_get(enc_ctx->pix_fmt)->comp[0].depth); - if (frame) { enc_ctx->color_range = frame->color_range; enc_ctx->color_primaries = frame->color_primaries; enc_ctx->color_trc = frame->color_trc; enc_ctx->colorspace = frame->colorspace; enc_ctx->chroma_sample_location = frame->chroma_location; - } enc_ctx->framerate = fr; ost->st->avg_frame_rate = fr; // Field order: autodetection - if (frame) { if (enc_ctx->flags & (AV_CODEC_FLAG_INTERLACED_DCT | AV_CODEC_FLAG_INTERLACED_ME) && ost->top_field_first >= 0) if (ost->top_field_first) @@ -332,7 +329,6 @@ int enc_open(OutputStream *ost, AVFrame *frame) enc_ctx->field_order = (frame->flags & AV_FRAME_FLAG_TOP_FIELD_FIRST) ? AV_FIELD_TB:AV_FIELD_BT; } else enc_ctx->field_order = AV_FIELD_PROGRESSIVE; - } // Field order: override if (ost->top_field_first == 0) { From 463a472426cc665e64e1c6f6677bb2142abe85e3 Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt Date: Sun, 16 Jul 2023 16:13:05 +0200 Subject: [PATCH 1893/2172] fftools/ffmpeg_enc: Reindentate after the last commit Reviewed-by: Anton Khirnov Signed-off-by: Andreas Rheinhardt --- fftools/ffmpeg_enc.c | 38 +++++++++++++++++++------------------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/fftools/ffmpeg_enc.c b/fftools/ffmpeg_enc.c index 2c7e29af246..8b750de4e57 100644 --- a/fftools/ffmpeg_enc.c +++ b/fftools/ffmpeg_enc.c @@ -304,31 +304,31 @@ int enc_open(OutputStream *ost, AVFrame *frame) enc_ctx->bits_per_raw_sample = FFMIN(fd->bits_per_raw_sample, av_pix_fmt_desc_get(enc_ctx->pix_fmt)->comp[0].depth); - enc_ctx->color_range = frame->color_range; - enc_ctx->color_primaries = frame->color_primaries; - enc_ctx->color_trc = frame->color_trc; - enc_ctx->colorspace = frame->colorspace; - enc_ctx->chroma_sample_location = frame->chroma_location; + enc_ctx->color_range = frame->color_range; + enc_ctx->color_primaries = frame->color_primaries; + enc_ctx->color_trc = frame->color_trc; + enc_ctx->colorspace = frame->colorspace; + enc_ctx->chroma_sample_location = frame->chroma_location; enc_ctx->framerate = fr; ost->st->avg_frame_rate = fr; // Field order: autodetection - if (enc_ctx->flags & (AV_CODEC_FLAG_INTERLACED_DCT | AV_CODEC_FLAG_INTERLACED_ME) && - ost->top_field_first >= 0) - if (ost->top_field_first) - frame->flags |= AV_FRAME_FLAG_TOP_FIELD_FIRST; - else - frame->flags &= ~AV_FRAME_FLAG_TOP_FIELD_FIRST; - - if (frame->flags & AV_FRAME_FLAG_INTERLACED) { - if (enc->id == AV_CODEC_ID_MJPEG) - enc_ctx->field_order = (frame->flags & AV_FRAME_FLAG_TOP_FIELD_FIRST) ? AV_FIELD_TT:AV_FIELD_BB; - else - enc_ctx->field_order = (frame->flags & AV_FRAME_FLAG_TOP_FIELD_FIRST) ? AV_FIELD_TB:AV_FIELD_BT; - } else - enc_ctx->field_order = AV_FIELD_PROGRESSIVE; + if (enc_ctx->flags & (AV_CODEC_FLAG_INTERLACED_DCT | AV_CODEC_FLAG_INTERLACED_ME) && + ost->top_field_first >= 0) + if (ost->top_field_first) + frame->flags |= AV_FRAME_FLAG_TOP_FIELD_FIRST; + else + frame->flags &= ~AV_FRAME_FLAG_TOP_FIELD_FIRST; + + if (frame->flags & AV_FRAME_FLAG_INTERLACED) { + if (enc->id == AV_CODEC_ID_MJPEG) + enc_ctx->field_order = (frame->flags & AV_FRAME_FLAG_TOP_FIELD_FIRST) ? AV_FIELD_TT:AV_FIELD_BB; + else + enc_ctx->field_order = (frame->flags & AV_FRAME_FLAG_TOP_FIELD_FIRST) ? AV_FIELD_TB:AV_FIELD_BT; + } else + enc_ctx->field_order = AV_FIELD_PROGRESSIVE; // Field order: override if (ost->top_field_first == 0) { From a054ceb4e274b2e2edbf095ed9766d370f782e4d Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt Date: Sun, 16 Jul 2023 16:29:07 +0200 Subject: [PATCH 1894/2172] avcodec/msrleenc: Replace stray \r by \n 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 --- libavcodec/msrleenc.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libavcodec/msrleenc.c b/libavcodec/msrleenc.c index b73aa5e384b..e48d11a0f70 100644 --- a/libavcodec/msrleenc.c +++ b/libavcodec/msrleenc.c @@ -234,7 +234,8 @@ static int encode(AVCodecContext *avctx, AVPacket *pkt, } bytestream_put_be16(&data, 0x0001); // end of bitmap pkt->size = data - pkt->data; - return 0; } + return 0; +} static int msrle_encode_frame(AVCodecContext *avctx, AVPacket *pkt, const AVFrame *pict, int *got_packet) From 3c642af8e03e545371d955f89a200812d869a7b4 Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt Date: Sun, 16 Jul 2023 16:30:08 +0200 Subject: [PATCH 1895/2172] avcodec/msrleenc: Check allocation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fixes Coverity issue #1538297. Reviewed-by: Tomas Härdin Signed-off-by: Andreas Rheinhardt --- libavcodec/msrleenc.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/libavcodec/msrleenc.c b/libavcodec/msrleenc.c index e48d11a0f70..264d57e1782 100644 --- a/libavcodec/msrleenc.c +++ b/libavcodec/msrleenc.c @@ -250,6 +250,8 @@ static int msrle_encode_frame(AVCodecContext *avctx, AVPacket *pkt, if (pict->data[1]) { uint8_t *side_data = av_packet_new_side_data(pkt, AV_PKT_DATA_PALETTE, AVPALETTE_SIZE); + if (!side_data) + return AVERROR(ENOMEM); memcpy(side_data, pict->data[1], AVPALETTE_SIZE); } From 66449f8c6bdf10ac1c5da7ffd5ded00e7dd4e102 Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt Date: Sun, 16 Jul 2023 16:34:18 +0200 Subject: [PATCH 1896/2172] avcodec/msrleenc: Remove useless private class MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit A private class for an encoder without options is useless. Reviewed-by: Tomas Härdin Signed-off-by: Andreas Rheinhardt --- libavcodec/msrleenc.c | 8 -------- 1 file changed, 8 deletions(-) diff --git a/libavcodec/msrleenc.c b/libavcodec/msrleenc.c index 264d57e1782..d5931f42fe4 100644 --- a/libavcodec/msrleenc.c +++ b/libavcodec/msrleenc.c @@ -31,7 +31,6 @@ #include "encode.h" typedef struct MSRLEContext { - const AVClass *class; int curframe; AVFrame *last_frame; } MSRLEContext; @@ -282,12 +281,6 @@ static int msrle_encode_close(AVCodecContext *avctx) return 0; } -static const AVClass msrle_class = { - .class_name = "Microsoft RLE encoder", - .item_name = av_default_item_name, - .version = LIBAVUTIL_VERSION_INT, -}; - const FFCodec ff_msrle_encoder = { .p.name = "msrle", CODEC_LONG_NAME("Microsoft RLE"), @@ -301,6 +294,5 @@ const FFCodec ff_msrle_encoder = { .p.pix_fmts = (const enum AVPixelFormat[]){ AV_PIX_FMT_PAL8, AV_PIX_FMT_NONE }, - .p.priv_class = &msrle_class, .caps_internal = FF_CODEC_CAP_INIT_CLEANUP, }; From 3cb0bd06a8dc154449b0cdff1c57a10ee55f8b30 Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt Date: Sun, 16 Jul 2023 16:41:47 +0200 Subject: [PATCH 1897/2172] avcodec/msrleenc: Check frame allocations/references MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Also allocate the AVFrame during init and use av_frame_replace() to replace it later. Reviewed-by: Tomas Härdin Signed-off-by: Andreas Rheinhardt --- libavcodec/msrleenc.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/libavcodec/msrleenc.c b/libavcodec/msrleenc.c index d5931f42fe4..11f7d2a3198 100644 --- a/libavcodec/msrleenc.c +++ b/libavcodec/msrleenc.c @@ -37,7 +37,13 @@ typedef struct MSRLEContext { static av_cold int msrle_encode_init(AVCodecContext *avctx) { + MSRLEContext *s = avctx->priv_data; + avctx->bits_per_coded_sample = 8; + s->last_frame = av_frame_alloc(); + if (!s->last_frame) + return AVERROR(ENOMEM); + return 0; } @@ -265,13 +271,7 @@ static int msrle_encode_frame(AVCodecContext *avctx, AVPacket *pkt, s->curframe = 0; *got_packet = 1; - if (!s->last_frame) - s->last_frame = av_frame_alloc(); - else - av_frame_unref(s->last_frame); - - av_frame_ref(s->last_frame, pict); - return 0; + return av_frame_replace(s->last_frame, pict); } static int msrle_encode_close(AVCodecContext *avctx) From 9c471c76cb2d00c5794f63d240e07df658ce8db9 Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt Date: Sun, 16 Jul 2023 16:53:52 +0200 Subject: [PATCH 1898/2172] avcodec/msrleenc: Constify pointers for frame->data MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Encoders (usually) have no business modifying frame->data (which need not be writable), so they should use the appropriate pointers. Reviewed-by: Tomas Härdin Signed-off-by: Andreas Rheinhardt --- libavcodec/msrleenc.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/libavcodec/msrleenc.c b/libavcodec/msrleenc.c index 11f7d2a3198..931e7af0538 100644 --- a/libavcodec/msrleenc.c +++ b/libavcodec/msrleenc.c @@ -64,7 +64,8 @@ static void write_run(AVCodecContext *avctx, uint8_t **data, int len, int value) } } -static void write_absolute(AVCodecContext *avctx, uint8_t **data, uint8_t *line, int len) +static void write_absolute(AVCodecContext *avctx, uint8_t **data, + const uint8_t *line, int len) { // writing 255 would be wasteful here due to the padding requirement while (len >= 254) { @@ -136,7 +137,8 @@ static void write_yskip(AVCodecContext *avctx, uint8_t **data, int yskip) } // used both to encode lines in keyframes and to encode lines between deltas -static void encode_line(AVCodecContext *avctx, uint8_t **data, uint8_t *line, int length) +static void encode_line(AVCodecContext *avctx, uint8_t **data, + const uint8_t *line, int length) { int run = 0, last = -1, absstart = 0; if (length == 0) @@ -192,8 +194,8 @@ static int encode(AVCodecContext *avctx, AVPacket *pkt, // compare to previous frame int yskip = 0; // we can encode large skips using deltas for (int y = avctx->height-1; y >= 0; y--) { - uint8_t *line = &pict->data[0][y*pict->linesize[0]]; - uint8_t *prev = &s->last_frame->data[0][y*s->last_frame->linesize[0]]; + const uint8_t *line = &pict->data[0][y*pict->linesize[0]]; + const uint8_t *prev = &s->last_frame->data[0][y*s->last_frame->linesize[0]]; // we need at least 5 pixels in a row for a delta to be worthwhile int delta = 0, linestart = 0, encoded = 0; for (int x = 0; x < avctx->width; x++) { From 51945d5ace5065aaa812486e7d12be1f18344642 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9mi=20Denis-Courmont?= Date: Thu, 22 Sep 2022 19:00:09 +0300 Subject: [PATCH 1899/2172] lavc/aacpsdsp: use restrict qualifier Except for add_squares, telling the compiler that the output vector(s) cannot alias helps quite a bit (cycles on SiFive U74-MC): ps_add_squares_c: 98277.7 ps_add_squares_r: 98320.2 ps_hybrid_analysis_c: 3731.2 ps_hybrid_analysis_r: 2495.7 ps_hybrid_analysis_ileave_c: 20478.0 ps_hybrid_analysis_ileave_r: 16092.2 ps_hybrid_synthesis_deint_c: 19051.5 ps_hybrid_synthesis_deint_r: 15420.0 ps_mul_pair_single_c: 122941.2 ps_mul_pair_single_r: 91035.0 --- libavcodec/aacpsdsp_template.c | 32 +++++++++++++++----------------- 1 file changed, 15 insertions(+), 17 deletions(-) diff --git a/libavcodec/aacpsdsp_template.c b/libavcodec/aacpsdsp_template.c index c063788b897..7b3eb78db1b 100644 --- a/libavcodec/aacpsdsp_template.c +++ b/libavcodec/aacpsdsp_template.c @@ -26,24 +26,25 @@ #include "libavutil/attributes.h" #include "aacpsdsp.h" -static void ps_add_squares_c(INTFLOAT *dst, const INTFLOAT (*src)[2], int n) +static void ps_add_squares_c(INTFLOAT *av_restrict dst, + const INTFLOAT (*src)[2], int n) { - int i; - for (i = 0; i < n; i++) + for (int i = 0; i < n; i++) dst[i] += (UINTFLOAT)AAC_MADD28(src[i][0], src[i][0], src[i][1], src[i][1]); } -static void ps_mul_pair_single_c(INTFLOAT (*dst)[2], INTFLOAT (*src0)[2], INTFLOAT *src1, +static void ps_mul_pair_single_c(INTFLOAT (*av_restrict dst)[2], + INTFLOAT (*src0)[2], INTFLOAT *src1, int n) { - int i; - for (i = 0; i < n; i++) { + for (int i = 0; i < n; i++) { dst[i][0] = AAC_MUL16(src0[i][0], src1[i]); dst[i][1] = AAC_MUL16(src0[i][1], src1[i]); } } -static void ps_hybrid_analysis_c(INTFLOAT (*out)[2], INTFLOAT (*in)[2], +static void ps_hybrid_analysis_c(INTFLOAT (*av_restrict out)[2], + INTFLOAT (*in)[2], const INTFLOAT (*filter)[8][2], ptrdiff_t stride, int n) { @@ -76,13 +77,12 @@ static void ps_hybrid_analysis_c(INTFLOAT (*out)[2], INTFLOAT (*in)[2], } } -static void ps_hybrid_analysis_ileave_c(INTFLOAT (*out)[32][2], INTFLOAT L[2][38][64], - int i, int len) +static void ps_hybrid_analysis_ileave_c(INTFLOAT (*av_restrict out)[32][2], + INTFLOAT L[2][38][64], + int i, int len) { - int j; - for (; i < 64; i++) { - for (j = 0; j < len; j++) { + for (int j = 0; j < len; j++) { out[i][j][0] = L[0][j][i]; out[i][j][1] = L[1][j][i]; } @@ -90,13 +90,11 @@ static void ps_hybrid_analysis_ileave_c(INTFLOAT (*out)[32][2], INTFLOAT L[2][38 } static void ps_hybrid_synthesis_deint_c(INTFLOAT out[2][38][64], - INTFLOAT (*in)[32][2], - int i, int len) + INTFLOAT (*av_restrict in)[32][2], + int i, int len) { - int n; - for (; i < 64; i++) { - for (n = 0; n < len; n++) { + for (int n = 0; n < len; n++) { out[0][n][i] = in[i][n][0]; out[1][n][i] = in[i][n][1]; } From 97c3c9974cc51c6bcf0b4f3ea254cd0be8cfd959 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9mi=20Denis-Courmont?= Date: Tue, 13 Sep 2022 18:56:27 +0300 Subject: [PATCH 1900/2172] lavc/audiodsp: fix aliasing violation Even though they have the same size, and typically the same alignment, uint32_t and float are under no circumstances compatible types in C. The casts from float * to uint32_t * are invalid here. Insofar as the resulting pointers are dereferenced, this is undefined behaviour. This patch uses av_float2int() / av_int2float() instead. --- libavcodec/audiodsp.c | 40 ++++++++++++++++++++-------------------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/libavcodec/audiodsp.c b/libavcodec/audiodsp.c index eba6e809fd6..c5427d3535d 100644 --- a/libavcodec/audiodsp.c +++ b/libavcodec/audiodsp.c @@ -22,36 +22,36 @@ #include "libavutil/common.h" #include "audiodsp.h" -static inline uint32_t clipf_c_one(uint32_t a, uint32_t mini, - uint32_t maxi, uint32_t maxisign) +static inline float clipf_c_one(float a, uint32_t mini, + uint32_t maxi, uint32_t maxisign) { - if (a > mini) - return mini; - else if ((a ^ (1U << 31)) > maxisign) - return maxi; + uint32_t ai = av_float2int(a); + + if (ai > mini) + return av_int2float(mini); + else if ((ai ^ (1U << 31)) > maxisign) + return av_int2float(maxi); else return a; } static void vector_clipf_c_opposite_sign(float *dst, const float *src, - float *min, float *max, int len) + float min, float max, int len) { int i; - uint32_t mini = *(uint32_t *) min; - uint32_t maxi = *(uint32_t *) max; + uint32_t mini = av_float2int(min); + uint32_t maxi = av_float2int(max); uint32_t maxisign = maxi ^ (1U << 31); - uint32_t *dsti = (uint32_t *) dst; - const uint32_t *srci = (const uint32_t *) src; for (i = 0; i < len; i += 8) { - dsti[i + 0] = clipf_c_one(srci[i + 0], mini, maxi, maxisign); - dsti[i + 1] = clipf_c_one(srci[i + 1], mini, maxi, maxisign); - dsti[i + 2] = clipf_c_one(srci[i + 2], mini, maxi, maxisign); - dsti[i + 3] = clipf_c_one(srci[i + 3], mini, maxi, maxisign); - dsti[i + 4] = clipf_c_one(srci[i + 4], mini, maxi, maxisign); - dsti[i + 5] = clipf_c_one(srci[i + 5], mini, maxi, maxisign); - dsti[i + 6] = clipf_c_one(srci[i + 6], mini, maxi, maxisign); - dsti[i + 7] = clipf_c_one(srci[i + 7], mini, maxi, maxisign); + dst[i + 0] = clipf_c_one(src[i + 0], mini, maxi, maxisign); + dst[i + 1] = clipf_c_one(src[i + 1], mini, maxi, maxisign); + dst[i + 2] = clipf_c_one(src[i + 2], mini, maxi, maxisign); + dst[i + 3] = clipf_c_one(src[i + 3], mini, maxi, maxisign); + dst[i + 4] = clipf_c_one(src[i + 4], mini, maxi, maxisign); + dst[i + 5] = clipf_c_one(src[i + 5], mini, maxi, maxisign); + dst[i + 6] = clipf_c_one(src[i + 6], mini, maxi, maxisign); + dst[i + 7] = clipf_c_one(src[i + 7], mini, maxi, maxisign); } } @@ -61,7 +61,7 @@ static void vector_clipf_c(float *dst, const float *src, int len, int i; if (min < 0 && max > 0) { - vector_clipf_c_opposite_sign(dst, src, &min, &max, len); + vector_clipf_c_opposite_sign(dst, src, min, max, len); } else { for (i = 0; i < len; i += 8) { dst[i] = av_clipf(src[i], min, max); From d8ea5f50e238a46728bfacc9793804de21fe0193 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9mi=20Denis-Courmont?= Date: Fri, 14 Jul 2023 21:43:01 +0300 Subject: [PATCH 1901/2172] checkasm: print usage on invalid arguments This checks that arguments are handled. If not, then this prints a short usage notice and returns an error. --- tests/checkasm/checkasm.c | 34 +++++++++++++++++++++++----------- 1 file changed, 23 insertions(+), 11 deletions(-) diff --git a/tests/checkasm/checkasm.c b/tests/checkasm/checkasm.c index 4311a8ffcb0..9976726021e 100644 --- a/tests/checkasm/checkasm.c +++ b/tests/checkasm/checkasm.c @@ -715,6 +715,14 @@ static void bench_uninit(void) #endif } +static int usage(const char *path) +{ + fprintf(stderr, + "Usage: %s [--bench] [--test=] [--verbose] [seed]\n", + path); + return 1; +} + int main(int argc, char *argv[]) { unsigned int seed = av_get_random_seed(); @@ -730,25 +738,29 @@ int main(int argc, char *argv[]) return 0; } - while (argc > 1) { - if (!strncmp(argv[1], "--bench", 7)) { + for (i = 1; i < argc; i++) { + const char *arg = argv[i]; + unsigned long l; + char *end; + + if (!strncmp(arg, "--bench", 7)) { if (bench_init() < 0) return 1; - if (argv[1][7] == '=') { - state.bench_pattern = argv[1] + 8; + if (arg[7] == '=') { + state.bench_pattern = arg + 8; state.bench_pattern_len = strlen(state.bench_pattern); } else state.bench_pattern = ""; - } else if (!strncmp(argv[1], "--test=", 7)) { - state.test_name = argv[1] + 7; - } else if (!strcmp(argv[1], "--verbose") || !strcmp(argv[1], "-v")) { + } else if (!strncmp(arg, "--test=", 7)) { + state.test_name = arg + 7; + } else if (!strcmp(arg, "--verbose") || !strcmp(arg, "-v")) { state.verbose = 1; + } else if ((l = strtoul(arg, &end, 10)) <= UINT_MAX && + *end == '\0') { + seed = l; } else { - seed = strtoul(argv[1], NULL, 10); + return usage(argv[0]); } - - argc--; - argv++; } fprintf(stderr, "checkasm: using random seed %u\n", seed); From 3d79afbe700ade76b77de84245f22010e65ce1bb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9mi=20Denis-Courmont?= Date: Fri, 14 Jul 2023 22:53:35 +0300 Subject: [PATCH 1902/2172] lavu/fixed_dsp: unroll RISC-V V loop Before: butterflies_fixed_c: 804.7 butterflies_fixed_rvv_i32: 348.2 After: butterflies_fixed_rvv_i32: 308.7 --- libavutil/riscv/fixed_dsp_rvv.S | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavutil/riscv/fixed_dsp_rvv.S b/libavutil/riscv/fixed_dsp_rvv.S index a91316e1daf..6e13395294b 100644 --- a/libavutil/riscv/fixed_dsp_rvv.S +++ b/libavutil/riscv/fixed_dsp_rvv.S @@ -23,7 +23,7 @@ // (a0) = (a0) + (a1), (a1) = (a0) - (a1) [0..a2-1] func ff_butterflies_fixed_rvv, zve32x 1: - vsetvli t0, a2, e32, m1, ta, ma + vsetvli t0, a2, e32, m4, ta, ma vle32.v v16, (a0) sub a2, a2, t0 vle32.v v24, (a1) From aa83654d940e7599ee641fc5d0fcd10e7decf277 Mon Sep 17 00:00:00 2001 From: Steven Liu Date: Fri, 26 May 2023 10:33:30 +0800 Subject: [PATCH 1903/2172] avformat/flvenc: support mux hevc in enhanced flv Tested-by: Tristan Matthews Tested-by: Neal Gompa Reviewed-by: Tristan Matthews Reviewed-by: Neal Gompa Signed-off-by: Steven Liu --- libavformat/Makefile | 2 +- libavformat/flv.h | 15 +++++++++++++++ libavformat/flvenc.c | 41 +++++++++++++++++++++++++++++++---------- 3 files changed, 47 insertions(+), 11 deletions(-) diff --git a/libavformat/Makefile b/libavformat/Makefile index 4cb00f8700a..bc5d7605c52 100644 --- a/libavformat/Makefile +++ b/libavformat/Makefile @@ -216,7 +216,7 @@ OBJS-$(CONFIG_FLAC_MUXER) += flacenc.o flacenc_header.o \ OBJS-$(CONFIG_FLIC_DEMUXER) += flic.o OBJS-$(CONFIG_FLV_DEMUXER) += flvdec.o OBJS-$(CONFIG_LIVE_FLV_DEMUXER) += flvdec.o -OBJS-$(CONFIG_FLV_MUXER) += flvenc.o avc.o +OBJS-$(CONFIG_FLV_MUXER) += flvenc.o avc.o hevc.o OBJS-$(CONFIG_FOURXM_DEMUXER) += 4xm.o OBJS-$(CONFIG_FRAMECRC_MUXER) += framecrcenc.o framehash.o OBJS-$(CONFIG_FRAMEHASH_MUXER) += hashenc.o framehash.o diff --git a/libavformat/flv.h b/libavformat/flv.h index 3571b90279c..91e0a4140cb 100644 --- a/libavformat/flv.h +++ b/libavformat/flv.h @@ -35,6 +35,12 @@ #define FLV_VIDEO_FRAMETYPE_OFFSET 4 +/* Extended VideoTagHeader + * defined in reference link: + * https://github.com/veovera/enhanced-rtmp/blob/main/enhanced-rtmp-v1.pdf + * */ +#define FLV_IS_EX_HEADER 0x80 + /* bitmasks to isolate specific values */ #define FLV_AUDIO_CHANNEL_MASK 0x01 #define FLV_AUDIO_SAMPLESIZE_MASK 0x02 @@ -112,6 +118,15 @@ enum { FLV_CODECID_MPEG4 = 9, }; +enum { + PacketTypeSequenceStart = 0, + PacketTypeCodedFrames = 1, + PacketTypeSequenceEnd = 2, + PacketTypeCodedFramesX = 3, + PacketTypeMetadata = 4, + PacketTypeMPEG2TSSequenceStart = 5, +}; + enum { FLV_FRAME_KEY = 1 << FLV_VIDEO_FRAMETYPE_OFFSET, ///< key frame (for AVC, a seekable frame) FLV_FRAME_INTER = 2 << FLV_VIDEO_FRAMETYPE_OFFSET, ///< inter frame (for AVC, a non-seekable frame) diff --git a/libavformat/flvenc.c b/libavformat/flvenc.c index 721f0628114..aed0946a2e0 100644 --- a/libavformat/flvenc.c +++ b/libavformat/flvenc.c @@ -28,6 +28,7 @@ #include "libavcodec/mpeg4audio.h" #include "avio.h" #include "avc.h" +#include "hevc.h" #include "avformat.h" #include "flv.h" #include "internal.h" @@ -46,6 +47,7 @@ static const AVCodecTag flv_video_codec_ids[] = { { AV_CODEC_ID_VP6, FLV_CODECID_VP6 }, { AV_CODEC_ID_VP6A, FLV_CODECID_VP6A }, { AV_CODEC_ID_H264, FLV_CODECID_H264 }, + { AV_CODEC_ID_HEVC, MKBETAG('h', 'v', 'c', '1') }, { AV_CODEC_ID_NONE, 0 } }; @@ -489,7 +491,7 @@ static void flv_write_codec_header(AVFormatContext* s, AVCodecParameters* par, i FLVContext *flv = s->priv_data; if (par->codec_id == AV_CODEC_ID_AAC || par->codec_id == AV_CODEC_ID_H264 - || par->codec_id == AV_CODEC_ID_MPEG4) { + || par->codec_id == AV_CODEC_ID_MPEG4 || par->codec_id == AV_CODEC_ID_HEVC) { int64_t pos; avio_w8(pb, par->codec_type == AVMEDIA_TYPE_VIDEO ? @@ -532,10 +534,19 @@ static void flv_write_codec_header(AVFormatContext* s, AVCodecParameters* par, i } avio_write(pb, par->extradata, par->extradata_size); } else { - avio_w8(pb, par->codec_tag | FLV_FRAME_KEY); // flags - avio_w8(pb, 0); // AVC sequence header - avio_wb24(pb, 0); // composition time - ff_isom_write_avcc(pb, par->extradata, par->extradata_size); + if (par->codec_id == AV_CODEC_ID_HEVC) { + avio_w8(pb, FLV_IS_EX_HEADER | PacketTypeSequenceStart | FLV_FRAME_KEY); // ExVideoTagHeader mode with PacketTypeSequenceStart + avio_write(pb, "hvc1", 4); + } else { + avio_w8(pb, par->codec_tag | FLV_FRAME_KEY); // flags + avio_w8(pb, 0); // AVC sequence header + avio_wb24(pb, 0); // composition time + } + + if (par->codec_id == AV_CODEC_ID_HEVC) + ff_isom_write_hvcc(pb, par->extradata, par->extradata_size, 0); + else + ff_isom_write_avcc(pb, par->extradata, par->extradata_size); } data_size = avio_tell(pb) - pos; avio_seek(pb, -data_size - 10, SEEK_CUR); @@ -821,6 +832,7 @@ static int flv_write_packet(AVFormatContext *s, AVPacket *pkt) unsigned ts; int size = pkt->size; uint8_t *data = NULL; + uint8_t frametype = pkt->flags & AV_PKT_FLAG_KEY ? FLV_FRAME_KEY : FLV_FRAME_INTER; int flags = -1, flags_size, ret = 0; int64_t cur_offset = avio_tell(pb); @@ -832,13 +844,13 @@ static int flv_write_packet(AVFormatContext *s, AVPacket *pkt) if (par->codec_id == AV_CODEC_ID_VP6F || par->codec_id == AV_CODEC_ID_VP6A || par->codec_id == AV_CODEC_ID_VP6 || par->codec_id == AV_CODEC_ID_AAC) flags_size = 2; - else if (par->codec_id == AV_CODEC_ID_H264 || par->codec_id == AV_CODEC_ID_MPEG4) + else if (par->codec_id == AV_CODEC_ID_H264 || par->codec_id == AV_CODEC_ID_MPEG4 || par->codec_id == AV_CODEC_ID_HEVC) flags_size = 5; else flags_size = 1; if (par->codec_id == AV_CODEC_ID_AAC || par->codec_id == AV_CODEC_ID_H264 - || par->codec_id == AV_CODEC_ID_MPEG4) { + || par->codec_id == AV_CODEC_ID_MPEG4 || par->codec_id == AV_CODEC_ID_HEVC) { size_t side_size; uint8_t *side = av_packet_get_side_data(pkt, AV_PKT_DATA_NEW_EXTRADATA, &side_size); if (side && side_size > 0 && (side_size != par->extradata_size || memcmp(side, par->extradata, side_size))) { @@ -858,7 +870,7 @@ static int flv_write_packet(AVFormatContext *s, AVPacket *pkt) "Packets are not in the proper order with respect to DTS\n"); return AVERROR(EINVAL); } - if (par->codec_id == AV_CODEC_ID_H264 || par->codec_id == AV_CODEC_ID_MPEG4) { + if (par->codec_id == AV_CODEC_ID_H264 || par->codec_id == AV_CODEC_ID_MPEG4 || par->codec_id == AV_CODEC_ID_HEVC) { if (pkt->pts == AV_NOPTS_VALUE) { av_log(s, AV_LOG_ERROR, "Packet is missing PTS\n"); return AVERROR(EINVAL); @@ -881,7 +893,7 @@ static int flv_write_packet(AVFormatContext *s, AVPacket *pkt) flags = ff_codec_get_tag(flv_video_codec_ids, par->codec_id); - flags |= pkt->flags & AV_PKT_FLAG_KEY ? FLV_FRAME_KEY : FLV_FRAME_INTER; + flags |= frametype; break; case AVMEDIA_TYPE_AUDIO: flags = get_audio_flags(s, par); @@ -903,6 +915,10 @@ static int flv_write_packet(AVFormatContext *s, AVPacket *pkt) if (par->extradata_size > 0 && *(uint8_t*)par->extradata != 1) if ((ret = ff_avc_parse_nal_units_buf(pkt->data, &data, &size)) < 0) return ret; + } else if (par->codec_id == AV_CODEC_ID_HEVC) { + if (par->extradata_size > 0 && *(uint8_t*)par->extradata != 1) + if ((ret = ff_hevc_annexb2mp4_buf(pkt->data, &data, &size, 0, NULL)) < 0) + return ret; } else if (par->codec_id == AV_CODEC_ID_AAC && pkt->size > 2 && (AV_RB16(pkt->data) & 0xfff0) == 0xfff0) { if (!s->streams[pkt->stream_index]->nb_frames) { @@ -964,7 +980,12 @@ static int flv_write_packet(AVFormatContext *s, AVPacket *pkt) avio_wb32(pb, data_size + 11); } else { av_assert1(flags>=0); - avio_w8(pb,flags); + if (par->codec_id == AV_CODEC_ID_HEVC) { + avio_w8(pb, FLV_IS_EX_HEADER | PacketTypeCodedFramesX | frametype); // ExVideoTagHeader mode with PacketTypeCodedFramesX + avio_write(pb, "hvc1", 4); + } else { + avio_w8(pb, flags); + } if (par->codec_id == AV_CODEC_ID_VP6) avio_w8(pb,0); if (par->codec_id == AV_CODEC_ID_VP6F || par->codec_id == AV_CODEC_ID_VP6A) { From ac5cc66f9e4408c45c303f6bf482ff04d7cb355e Mon Sep 17 00:00:00 2001 From: Steven Liu Date: Thu, 13 Apr 2023 17:12:16 +0800 Subject: [PATCH 1904/2172] avformat/flvdec: support demux hevc in enhanced flv Tested-by: Tristan Matthews Tested-by: Neal Gompa Reviewed-by: Tristan Matthews Reviewed-by: Neal Gompa Signed-off-by: Steven Liu --- libavformat/flvdec.c | 58 ++++++++++++++++++++++++++++++++++++++------ 1 file changed, 50 insertions(+), 8 deletions(-) diff --git a/libavformat/flvdec.c b/libavformat/flvdec.c index d83edff727c..c8e6cadf1c3 100644 --- a/libavformat/flvdec.c +++ b/libavformat/flvdec.c @@ -79,6 +79,8 @@ typedef struct FLVContext { int64_t last_ts; int64_t time_offset; int64_t time_pos; + + uint8_t exheader; } FLVContext; /* AMF date type */ @@ -302,13 +304,25 @@ static void flv_set_audio_codec(AVFormatContext *s, AVStream *astream, } } -static int flv_same_video_codec(AVCodecParameters *vpar, int flags) +static int flv_same_video_codec(AVFormatContext *s, AVCodecParameters *vpar, int flags) { int flv_codecid = flags & FLV_VIDEO_CODECID_MASK; + FLVContext *flv = s->priv_data; if (!vpar->codec_id && !vpar->codec_tag) return 1; + if (flv->exheader) { + uint8_t *codec_id_str = (uint8_t *)s->pb->buf_ptr; + uint32_t codec_id = codec_id_str[3] | codec_id_str[2] << 8 | codec_id_str[1] << 16 | codec_id_str[0] << 24; + switch(codec_id) { + case MKBETAG('h', 'v', 'c', '1'): + return vpar->codec_id == AV_CODEC_ID_HEVC; + default: + break; + } + } + switch (flv_codecid) { case FLV_CODECID_H263: return vpar->codec_id == AV_CODEC_ID_FLV1; @@ -331,9 +345,24 @@ static int flv_set_video_codec(AVFormatContext *s, AVStream *vstream, int flv_codecid, int read) { FFStream *const vstreami = ffstream(vstream); + FLVContext *flv = s->priv_data; int ret = 0; AVCodecParameters *par = vstream->codecpar; enum AVCodecID old_codec_id = vstream->codecpar->codec_id; + flv_codecid &= FLV_VIDEO_CODECID_MASK; + + if (flv->exheader) { + uint32_t codec_id = avio_rb32(s->pb); + + switch(codec_id) { + case MKBETAG('h', 'v', 'c', '1'): + par->codec_id = AV_CODEC_ID_HEVC; + vstreami->need_parsing = AVSTREAM_PARSE_HEADERS; + return 4; + default: + break; + } + } switch (flv_codecid) { case FLV_CODECID_H263: par->codec_id = AV_CODEC_ID_FLV1; @@ -796,6 +825,7 @@ static int flv_read_header(AVFormatContext *s) s->start_time = 0; flv->sum_flv_tag_size = 0; flv->last_keyframe_stream_index = -1; + flv->exheader = 0; return 0; } @@ -1071,6 +1101,11 @@ static int flv_read_packet(AVFormatContext *s, AVPacket *pkt) } else if (type == FLV_TAG_TYPE_VIDEO) { stream_type = FLV_STREAM_TYPE_VIDEO; flags = avio_r8(s->pb); + /* + * Reference Enhancing FLV 2023-03-v1.0.0-B.8 + * https://github.com/veovera/enhanced-rtmp/blob/main/enhanced-rtmp-v1.pdf + * */ + flv->exheader = (flags >> 7) & 1; size--; if ((flags & FLV_VIDEO_FRAMETYPE_MASK) == FLV_FRAME_VIDEO_INFO_CMD) goto skip; @@ -1129,7 +1164,7 @@ static int flv_read_packet(AVFormatContext *s, AVPacket *pkt) break; } else if (stream_type == FLV_STREAM_TYPE_VIDEO) { if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO && - (s->video_codec_id || flv_same_video_codec(st->codecpar, flags))) + (s->video_codec_id || flv_same_video_codec(s, st->codecpar, flags))) break; } else if (stream_type == FLV_STREAM_TYPE_SUBTITLE) { if (st->codecpar->codec_type == AVMEDIA_TYPE_SUBTITLE) @@ -1230,7 +1265,7 @@ static int flv_read_packet(AVFormatContext *s, AVPacket *pkt) avcodec_parameters_free(&par); } } else if (stream_type == FLV_STREAM_TYPE_VIDEO) { - int ret = flv_set_video_codec(s, st, flags & FLV_VIDEO_CODECID_MASK, 1); + int ret = flv_set_video_codec(s, st, flags, 1); if (ret < 0) return ret; size -= ret; @@ -1242,16 +1277,23 @@ static int flv_read_packet(AVFormatContext *s, AVPacket *pkt) if (st->codecpar->codec_id == AV_CODEC_ID_AAC || st->codecpar->codec_id == AV_CODEC_ID_H264 || - st->codecpar->codec_id == AV_CODEC_ID_MPEG4) { - int type = avio_r8(s->pb); - size--; + st->codecpar->codec_id == AV_CODEC_ID_MPEG4 || + st->codecpar->codec_id == AV_CODEC_ID_HEVC) { + int type = 0; + if (flv->exheader && stream_type == FLV_STREAM_TYPE_VIDEO) { + type = flags & 0x0F; + } else { + type = avio_r8(s->pb); + size--; + } if (size < 0) { ret = AVERROR_INVALIDDATA; goto leave; } - if (st->codecpar->codec_id == AV_CODEC_ID_H264 || st->codecpar->codec_id == AV_CODEC_ID_MPEG4) { + if (st->codecpar->codec_id == AV_CODEC_ID_H264 || st->codecpar->codec_id == AV_CODEC_ID_MPEG4 || + (st->codecpar->codec_id == AV_CODEC_ID_HEVC && type == PacketTypeCodedFrames)) { // sign extension int32_t cts = (avio_rb24(s->pb) + 0xff800000) ^ 0xff800000; pts = av_sat_add64(dts, cts); @@ -1267,7 +1309,7 @@ static int flv_read_packet(AVFormatContext *s, AVPacket *pkt) } } if (type == 0 && (!st->codecpar->extradata || st->codecpar->codec_id == AV_CODEC_ID_AAC || - st->codecpar->codec_id == AV_CODEC_ID_H264)) { + st->codecpar->codec_id == AV_CODEC_ID_H264 || st->codecpar->codec_id == AV_CODEC_ID_HEVC)) { AVDictionaryEntry *t; if (st->codecpar->extradata) { From 7a5e9a68b0895e68665e4fb329801a0f5820d856 Mon Sep 17 00:00:00 2001 From: Steven Liu Date: Fri, 12 May 2023 09:56:56 +0800 Subject: [PATCH 1905/2172] avformat/flvenc: support mux av1 in enhanced flv Tested-by: Tristan Matthews Tested-by: Neal Gompa Reviewed-by: Tristan Matthews Reviewed-by: Neal Gompa Signed-off-by: Steven Liu --- libavformat/Makefile | 2 +- libavformat/flvenc.c | 22 ++++++++++++++++++---- 2 files changed, 19 insertions(+), 5 deletions(-) diff --git a/libavformat/Makefile b/libavformat/Makefile index bc5d7605c52..850801ee5c9 100644 --- a/libavformat/Makefile +++ b/libavformat/Makefile @@ -216,7 +216,7 @@ OBJS-$(CONFIG_FLAC_MUXER) += flacenc.o flacenc_header.o \ OBJS-$(CONFIG_FLIC_DEMUXER) += flic.o OBJS-$(CONFIG_FLV_DEMUXER) += flvdec.o OBJS-$(CONFIG_LIVE_FLV_DEMUXER) += flvdec.o -OBJS-$(CONFIG_FLV_MUXER) += flvenc.o avc.o hevc.o +OBJS-$(CONFIG_FLV_MUXER) += flvenc.o avc.o hevc.o av1.o OBJS-$(CONFIG_FOURXM_DEMUXER) += 4xm.o OBJS-$(CONFIG_FRAMECRC_MUXER) += framecrcenc.o framehash.o OBJS-$(CONFIG_FRAMEHASH_MUXER) += hashenc.o framehash.o diff --git a/libavformat/flvenc.c b/libavformat/flvenc.c index aed0946a2e0..99fa1bd7230 100644 --- a/libavformat/flvenc.c +++ b/libavformat/flvenc.c @@ -28,6 +28,7 @@ #include "libavcodec/mpeg4audio.h" #include "avio.h" #include "avc.h" +#include "av1.h" #include "hevc.h" #include "avformat.h" #include "flv.h" @@ -48,6 +49,7 @@ static const AVCodecTag flv_video_codec_ids[] = { { AV_CODEC_ID_VP6A, FLV_CODECID_VP6A }, { AV_CODEC_ID_H264, FLV_CODECID_H264 }, { AV_CODEC_ID_HEVC, MKBETAG('h', 'v', 'c', '1') }, + { AV_CODEC_ID_AV1, MKBETAG('a', 'v', '0', '1') }, { AV_CODEC_ID_NONE, 0 } }; @@ -491,7 +493,8 @@ static void flv_write_codec_header(AVFormatContext* s, AVCodecParameters* par, i FLVContext *flv = s->priv_data; if (par->codec_id == AV_CODEC_ID_AAC || par->codec_id == AV_CODEC_ID_H264 - || par->codec_id == AV_CODEC_ID_MPEG4 || par->codec_id == AV_CODEC_ID_HEVC) { + || par->codec_id == AV_CODEC_ID_MPEG4 || par->codec_id == AV_CODEC_ID_HEVC + || par->codec_id == AV_CODEC_ID_AV1) { int64_t pos; avio_w8(pb, par->codec_type == AVMEDIA_TYPE_VIDEO ? @@ -537,6 +540,9 @@ static void flv_write_codec_header(AVFormatContext* s, AVCodecParameters* par, i if (par->codec_id == AV_CODEC_ID_HEVC) { avio_w8(pb, FLV_IS_EX_HEADER | PacketTypeSequenceStart | FLV_FRAME_KEY); // ExVideoTagHeader mode with PacketTypeSequenceStart avio_write(pb, "hvc1", 4); + } else if (par->codec_id == AV_CODEC_ID_AV1) { + avio_w8(pb, FLV_IS_EX_HEADER | PacketTypeSequenceStart | FLV_FRAME_KEY); + avio_write(pb, "av01", 4); } else { avio_w8(pb, par->codec_tag | FLV_FRAME_KEY); // flags avio_w8(pb, 0); // AVC sequence header @@ -545,6 +551,8 @@ static void flv_write_codec_header(AVFormatContext* s, AVCodecParameters* par, i if (par->codec_id == AV_CODEC_ID_HEVC) ff_isom_write_hvcc(pb, par->extradata, par->extradata_size, 0); + else if (par->codec_id == AV_CODEC_ID_AV1) + ff_isom_write_av1c(pb, par->extradata, par->extradata_size, 1); else ff_isom_write_avcc(pb, par->extradata, par->extradata_size); } @@ -844,13 +852,15 @@ static int flv_write_packet(AVFormatContext *s, AVPacket *pkt) if (par->codec_id == AV_CODEC_ID_VP6F || par->codec_id == AV_CODEC_ID_VP6A || par->codec_id == AV_CODEC_ID_VP6 || par->codec_id == AV_CODEC_ID_AAC) flags_size = 2; - else if (par->codec_id == AV_CODEC_ID_H264 || par->codec_id == AV_CODEC_ID_MPEG4 || par->codec_id == AV_CODEC_ID_HEVC) + else if (par->codec_id == AV_CODEC_ID_H264 || par->codec_id == AV_CODEC_ID_MPEG4 || + par->codec_id == AV_CODEC_ID_HEVC || par->codec_id == AV_CODEC_ID_AV1) flags_size = 5; else flags_size = 1; if (par->codec_id == AV_CODEC_ID_AAC || par->codec_id == AV_CODEC_ID_H264 - || par->codec_id == AV_CODEC_ID_MPEG4 || par->codec_id == AV_CODEC_ID_HEVC) { + || par->codec_id == AV_CODEC_ID_MPEG4 || par->codec_id == AV_CODEC_ID_HEVC + || par->codec_id == AV_CODEC_ID_AV1) { size_t side_size; uint8_t *side = av_packet_get_side_data(pkt, AV_PKT_DATA_NEW_EXTRADATA, &side_size); if (side && side_size > 0 && (side_size != par->extradata_size || memcmp(side, par->extradata, side_size))) { @@ -870,7 +880,8 @@ static int flv_write_packet(AVFormatContext *s, AVPacket *pkt) "Packets are not in the proper order with respect to DTS\n"); return AVERROR(EINVAL); } - if (par->codec_id == AV_CODEC_ID_H264 || par->codec_id == AV_CODEC_ID_MPEG4 || par->codec_id == AV_CODEC_ID_HEVC) { + if (par->codec_id == AV_CODEC_ID_H264 || par->codec_id == AV_CODEC_ID_MPEG4 || + par->codec_id == AV_CODEC_ID_HEVC || par->codec_id == AV_CODEC_ID_AV1) { if (pkt->pts == AV_NOPTS_VALUE) { av_log(s, AV_LOG_ERROR, "Packet is missing PTS\n"); return AVERROR(EINVAL); @@ -983,6 +994,9 @@ static int flv_write_packet(AVFormatContext *s, AVPacket *pkt) if (par->codec_id == AV_CODEC_ID_HEVC) { avio_w8(pb, FLV_IS_EX_HEADER | PacketTypeCodedFramesX | frametype); // ExVideoTagHeader mode with PacketTypeCodedFramesX avio_write(pb, "hvc1", 4); + } else if (par->codec_id == AV_CODEC_ID_AV1) { + avio_w8(pb, FLV_IS_EX_HEADER | PacketTypeCodedFrames | frametype); + avio_write(pb, "av01", 4); } else { avio_w8(pb, flags); } From 23b02557e94af438d2af06b477bfd1e513708dce Mon Sep 17 00:00:00 2001 From: Steven Liu Date: Thu, 13 Apr 2023 14:25:27 +0800 Subject: [PATCH 1906/2172] avformat/flvdec: support demux av1 in enhanced flv Tested-by: Tristan Matthews Tested-by: Neal Gompa Reviewed-by: Tristan Matthews Reviewed-by: Neal Gompa Signed-off-by: Steven Liu --- libavformat/flvdec.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/libavformat/flvdec.c b/libavformat/flvdec.c index c8e6cadf1c3..a0362ff11c5 100644 --- a/libavformat/flvdec.c +++ b/libavformat/flvdec.c @@ -318,6 +318,8 @@ static int flv_same_video_codec(AVFormatContext *s, AVCodecParameters *vpar, int switch(codec_id) { case MKBETAG('h', 'v', 'c', '1'): return vpar->codec_id == AV_CODEC_ID_HEVC; + case MKBETAG('a', 'v', '0', '1'): + return vpar->codec_id == AV_CODEC_ID_AV1; default: break; } @@ -359,6 +361,10 @@ static int flv_set_video_codec(AVFormatContext *s, AVStream *vstream, par->codec_id = AV_CODEC_ID_HEVC; vstreami->need_parsing = AVSTREAM_PARSE_HEADERS; return 4; + case MKBETAG('a', 'v', '0', '1'): + par->codec_id = AV_CODEC_ID_AV1; + vstreami->need_parsing = AVSTREAM_PARSE_HEADERS; + return 4; default: break; } @@ -1278,7 +1284,8 @@ static int flv_read_packet(AVFormatContext *s, AVPacket *pkt) if (st->codecpar->codec_id == AV_CODEC_ID_AAC || st->codecpar->codec_id == AV_CODEC_ID_H264 || st->codecpar->codec_id == AV_CODEC_ID_MPEG4 || - st->codecpar->codec_id == AV_CODEC_ID_HEVC) { + st->codecpar->codec_id == AV_CODEC_ID_HEVC || + st->codecpar->codec_id == AV_CODEC_ID_AV1) { int type = 0; if (flv->exheader && stream_type == FLV_STREAM_TYPE_VIDEO) { type = flags & 0x0F; @@ -1309,7 +1316,8 @@ static int flv_read_packet(AVFormatContext *s, AVPacket *pkt) } } if (type == 0 && (!st->codecpar->extradata || st->codecpar->codec_id == AV_CODEC_ID_AAC || - st->codecpar->codec_id == AV_CODEC_ID_H264 || st->codecpar->codec_id == AV_CODEC_ID_HEVC)) { + st->codecpar->codec_id == AV_CODEC_ID_H264 || st->codecpar->codec_id == AV_CODEC_ID_HEVC || + st->codecpar->codec_id == AV_CODEC_ID_AV1)) { AVDictionaryEntry *t; if (st->codecpar->extradata) { From 0693a2a86ea3c5bcce310c328e9ac03bb8aad80a Mon Sep 17 00:00:00 2001 From: Steven Liu Date: Fri, 12 May 2023 09:57:36 +0800 Subject: [PATCH 1907/2172] avformat/flvenc: support mux vp9 in enhanced flv Tested-by: Tristan Matthews Tested-by: Neal Gompa Reviewed-by: Tristan Matthews Reviewed-by: Neal Gompa Signed-off-by: Steven Liu --- libavformat/Makefile | 2 +- libavformat/flvenc.c | 22 ++++++++++++++-------- 2 files changed, 15 insertions(+), 9 deletions(-) diff --git a/libavformat/Makefile b/libavformat/Makefile index 850801ee5c9..bd78c206b98 100644 --- a/libavformat/Makefile +++ b/libavformat/Makefile @@ -216,7 +216,7 @@ OBJS-$(CONFIG_FLAC_MUXER) += flacenc.o flacenc_header.o \ OBJS-$(CONFIG_FLIC_DEMUXER) += flic.o OBJS-$(CONFIG_FLV_DEMUXER) += flvdec.o OBJS-$(CONFIG_LIVE_FLV_DEMUXER) += flvdec.o -OBJS-$(CONFIG_FLV_MUXER) += flvenc.o avc.o hevc.o av1.o +OBJS-$(CONFIG_FLV_MUXER) += flvenc.o avc.o hevc.o av1.o vpcc.o OBJS-$(CONFIG_FOURXM_DEMUXER) += 4xm.o OBJS-$(CONFIG_FRAMECRC_MUXER) += framecrcenc.o framehash.o OBJS-$(CONFIG_FRAMEHASH_MUXER) += hashenc.o framehash.o diff --git a/libavformat/flvenc.c b/libavformat/flvenc.c index 99fa1bd7230..335d9004156 100644 --- a/libavformat/flvenc.c +++ b/libavformat/flvenc.c @@ -29,6 +29,7 @@ #include "avio.h" #include "avc.h" #include "av1.h" +#include "vpcc.h" #include "hevc.h" #include "avformat.h" #include "flv.h" @@ -50,6 +51,7 @@ static const AVCodecTag flv_video_codec_ids[] = { { AV_CODEC_ID_H264, FLV_CODECID_H264 }, { AV_CODEC_ID_HEVC, MKBETAG('h', 'v', 'c', '1') }, { AV_CODEC_ID_AV1, MKBETAG('a', 'v', '0', '1') }, + { AV_CODEC_ID_VP9, MKBETAG('v', 'p', '0', '9') }, { AV_CODEC_ID_NONE, 0 } }; @@ -494,7 +496,7 @@ static void flv_write_codec_header(AVFormatContext* s, AVCodecParameters* par, i if (par->codec_id == AV_CODEC_ID_AAC || par->codec_id == AV_CODEC_ID_H264 || par->codec_id == AV_CODEC_ID_MPEG4 || par->codec_id == AV_CODEC_ID_HEVC - || par->codec_id == AV_CODEC_ID_AV1) { + || par->codec_id == AV_CODEC_ID_AV1 || par->codec_id == AV_CODEC_ID_VP9) { int64_t pos; avio_w8(pb, par->codec_type == AVMEDIA_TYPE_VIDEO ? @@ -540,9 +542,9 @@ static void flv_write_codec_header(AVFormatContext* s, AVCodecParameters* par, i if (par->codec_id == AV_CODEC_ID_HEVC) { avio_w8(pb, FLV_IS_EX_HEADER | PacketTypeSequenceStart | FLV_FRAME_KEY); // ExVideoTagHeader mode with PacketTypeSequenceStart avio_write(pb, "hvc1", 4); - } else if (par->codec_id == AV_CODEC_ID_AV1) { + } else if (par->codec_id == AV_CODEC_ID_AV1 || par->codec_id == AV_CODEC_ID_VP9) { avio_w8(pb, FLV_IS_EX_HEADER | PacketTypeSequenceStart | FLV_FRAME_KEY); - avio_write(pb, "av01", 4); + avio_write(pb, par->codec_id == AV_CODEC_ID_AV1 ? "av01" : "vp09", 4); } else { avio_w8(pb, par->codec_tag | FLV_FRAME_KEY); // flags avio_w8(pb, 0); // AVC sequence header @@ -553,6 +555,8 @@ static void flv_write_codec_header(AVFormatContext* s, AVCodecParameters* par, i ff_isom_write_hvcc(pb, par->extradata, par->extradata_size, 0); else if (par->codec_id == AV_CODEC_ID_AV1) ff_isom_write_av1c(pb, par->extradata, par->extradata_size, 1); + else if (par->codec_id == AV_CODEC_ID_VP9) + ff_isom_write_vpcc(s, pb, par->extradata, par->extradata_size, par); else ff_isom_write_avcc(pb, par->extradata, par->extradata_size); } @@ -853,14 +857,15 @@ static int flv_write_packet(AVFormatContext *s, AVPacket *pkt) par->codec_id == AV_CODEC_ID_VP6 || par->codec_id == AV_CODEC_ID_AAC) flags_size = 2; else if (par->codec_id == AV_CODEC_ID_H264 || par->codec_id == AV_CODEC_ID_MPEG4 || - par->codec_id == AV_CODEC_ID_HEVC || par->codec_id == AV_CODEC_ID_AV1) + par->codec_id == AV_CODEC_ID_HEVC || par->codec_id == AV_CODEC_ID_AV1 || + par->codec_id == AV_CODEC_ID_VP9) flags_size = 5; else flags_size = 1; if (par->codec_id == AV_CODEC_ID_AAC || par->codec_id == AV_CODEC_ID_H264 || par->codec_id == AV_CODEC_ID_MPEG4 || par->codec_id == AV_CODEC_ID_HEVC - || par->codec_id == AV_CODEC_ID_AV1) { + || par->codec_id == AV_CODEC_ID_AV1 || par->codec_id == AV_CODEC_ID_VP9) { size_t side_size; uint8_t *side = av_packet_get_side_data(pkt, AV_PKT_DATA_NEW_EXTRADATA, &side_size); if (side && side_size > 0 && (side_size != par->extradata_size || memcmp(side, par->extradata, side_size))) { @@ -881,7 +886,8 @@ static int flv_write_packet(AVFormatContext *s, AVPacket *pkt) return AVERROR(EINVAL); } if (par->codec_id == AV_CODEC_ID_H264 || par->codec_id == AV_CODEC_ID_MPEG4 || - par->codec_id == AV_CODEC_ID_HEVC || par->codec_id == AV_CODEC_ID_AV1) { + par->codec_id == AV_CODEC_ID_HEVC || par->codec_id == AV_CODEC_ID_AV1 || + par->codec_id == AV_CODEC_ID_VP9) { if (pkt->pts == AV_NOPTS_VALUE) { av_log(s, AV_LOG_ERROR, "Packet is missing PTS\n"); return AVERROR(EINVAL); @@ -994,9 +1000,9 @@ static int flv_write_packet(AVFormatContext *s, AVPacket *pkt) if (par->codec_id == AV_CODEC_ID_HEVC) { avio_w8(pb, FLV_IS_EX_HEADER | PacketTypeCodedFramesX | frametype); // ExVideoTagHeader mode with PacketTypeCodedFramesX avio_write(pb, "hvc1", 4); - } else if (par->codec_id == AV_CODEC_ID_AV1) { + } else if (par->codec_id == AV_CODEC_ID_AV1 || par->codec_id == AV_CODEC_ID_VP9) { avio_w8(pb, FLV_IS_EX_HEADER | PacketTypeCodedFrames | frametype); - avio_write(pb, "av01", 4); + avio_write(pb, par->codec_id == AV_CODEC_ID_AV1 ? "av01" : "vp09", 4); } else { avio_w8(pb, flags); } From 2cd09fec9f8d3b16d03e762dec6001cc0b792659 Mon Sep 17 00:00:00 2001 From: Steven Liu Date: Thu, 13 Apr 2023 17:08:56 +0800 Subject: [PATCH 1908/2172] avformat/flvdec: support demux vp9 in enhanced flv Tested-by: Tristan Matthews Tested-by: Neal Gompa Reviewed-by: Tristan Matthews Reviewed-by: Neal Gompa Signed-off-by: Steven Liu --- libavformat/flvdec.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/libavformat/flvdec.c b/libavformat/flvdec.c index a0362ff11c5..a6a94a4021d 100644 --- a/libavformat/flvdec.c +++ b/libavformat/flvdec.c @@ -320,6 +320,8 @@ static int flv_same_video_codec(AVFormatContext *s, AVCodecParameters *vpar, int return vpar->codec_id == AV_CODEC_ID_HEVC; case MKBETAG('a', 'v', '0', '1'): return vpar->codec_id == AV_CODEC_ID_AV1; + case MKBETAG('v', 'p', '0', '9'): + return vpar->codec_id == AV_CODEC_ID_VP9; default: break; } @@ -365,6 +367,10 @@ static int flv_set_video_codec(AVFormatContext *s, AVStream *vstream, par->codec_id = AV_CODEC_ID_AV1; vstreami->need_parsing = AVSTREAM_PARSE_HEADERS; return 4; + case MKBETAG('v', 'p', '0', '9'): + par->codec_id = AV_CODEC_ID_VP9; + vstreami->need_parsing = AVSTREAM_PARSE_HEADERS; + return 4; default: break; } @@ -1285,7 +1291,8 @@ static int flv_read_packet(AVFormatContext *s, AVPacket *pkt) st->codecpar->codec_id == AV_CODEC_ID_H264 || st->codecpar->codec_id == AV_CODEC_ID_MPEG4 || st->codecpar->codec_id == AV_CODEC_ID_HEVC || - st->codecpar->codec_id == AV_CODEC_ID_AV1) { + st->codecpar->codec_id == AV_CODEC_ID_AV1 || + st->codecpar->codec_id == AV_CODEC_ID_VP9) { int type = 0; if (flv->exheader && stream_type == FLV_STREAM_TYPE_VIDEO) { type = flags & 0x0F; @@ -1317,7 +1324,7 @@ static int flv_read_packet(AVFormatContext *s, AVPacket *pkt) } if (type == 0 && (!st->codecpar->extradata || st->codecpar->codec_id == AV_CODEC_ID_AAC || st->codecpar->codec_id == AV_CODEC_ID_H264 || st->codecpar->codec_id == AV_CODEC_ID_HEVC || - st->codecpar->codec_id == AV_CODEC_ID_AV1)) { + st->codecpar->codec_id == AV_CODEC_ID_AV1 || st->codecpar->codec_id == AV_CODEC_ID_VP9)) { AVDictionaryEntry *t; if (st->codecpar->extradata) { From 3af0dc6d056ee100d9a483ffbd63d89cda757cd9 Mon Sep 17 00:00:00 2001 From: Zhao Zhili Date: Tue, 4 Jul 2023 23:14:59 +0800 Subject: [PATCH 1909/2172] avutil/bfin: remove dead code The code is unused for a decade since bf6c84d7eb27b. Signed-off-by: Zhao Zhili --- libavutil/bfin/bswap.h | 45 ------------------------------------------ libavutil/bfin/timer.h | 41 -------------------------------------- 2 files changed, 86 deletions(-) delete mode 100644 libavutil/bfin/bswap.h delete mode 100644 libavutil/bfin/timer.h diff --git a/libavutil/bfin/bswap.h b/libavutil/bfin/bswap.h deleted file mode 100644 index 363ed40bc5f..00000000000 --- a/libavutil/bfin/bswap.h +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright (C) 2007 Marc Hoffman - * - * 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 - * byte swapping routines - */ - -#ifndef AVUTIL_BFIN_BSWAP_H -#define AVUTIL_BFIN_BSWAP_H - -#include -#include "config.h" -#include "libavutil/attributes.h" - -#define av_bswap32 av_bswap32 -static av_always_inline av_const uint32_t av_bswap32(uint32_t x) -{ - unsigned tmp; - __asm__("%1 = %0 >> 8 (V); \n\t" - "%0 = %0 << 8 (V); \n\t" - "%0 = %0 | %1; \n\t" - "%0 = PACK(%0.L, %0.H); \n\t" - : "+d"(x), "=&d"(tmp)); - return x; -} - -#endif /* AVUTIL_BFIN_BSWAP_H */ diff --git a/libavutil/bfin/timer.h b/libavutil/bfin/timer.h deleted file mode 100644 index 644573daec9..00000000000 --- a/libavutil/bfin/timer.h +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright (C) 2007 Marc Hoffman - * - * 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_BFIN_TIMER_H -#define AVUTIL_BFIN_TIMER_H - -#include - -#define AV_READ_TIME read_time - -static inline uint64_t read_time(void) -{ - union { - struct { - unsigned lo; - unsigned hi; - } p; - unsigned long long c; - } t; - __asm__ volatile ("%0=cycles; %1=cycles2;" : "=d" (t.p.lo), "=d" (t.p.hi)); - return t.c; -} - -#endif /* AVUTIL_BFIN_TIMER_H */ From be7ac511a6b4dd9883c0a6dd8323b04f651193f4 Mon Sep 17 00:00:00 2001 From: Zhao Zhili Date: Sat, 8 Jul 2023 04:44:17 +0800 Subject: [PATCH 1910/2172] avformat/mov: avss box should be AV_CODEC_ID_CAVS I cannot find the spec, but according to the original commit d4fdba0df71, it's CAVS. e571305a714 changed it to AVS by accident. Ten years on, nothing happened. We still have the sample [1], however, since there is no cavs_mp4tofoobar bsf, the cavs decoder doesn't work. I don't know if there is any use case. [1] https://samples.ffmpeg.org/AVS/AVSFileFormat/AVSFileFormat.mp4 Signed-off-by: Zhao Zhili --- libavformat/mov.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavformat/mov.c b/libavformat/mov.c index 444aca52351..ac19b3157aa 100644 --- a/libavformat/mov.c +++ b/libavformat/mov.c @@ -1911,7 +1911,7 @@ static int mov_read_alac(MOVContext *c, AVIOContext *pb, MOVAtom atom) static int mov_read_avss(MOVContext *c, AVIOContext *pb, MOVAtom atom) { - return mov_read_extradata(c, pb, atom, AV_CODEC_ID_AVS); + return mov_read_extradata(c, pb, atom, AV_CODEC_ID_CAVS); } static int mov_read_jp2h(MOVContext *c, AVIOContext *pb, MOVAtom atom) From 2eb55157aab49076eb581c99227ee81ef5d06b6e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9mi=20Denis-Courmont?= Date: Sat, 15 Jul 2023 23:30:59 +0300 Subject: [PATCH 1911/2172] lavc/aacpsdsp: unroll RISC-V V add_squares This slightly improves performance with the Device Under Test. --- libavcodec/riscv/aacpsdsp_rvv.S | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libavcodec/riscv/aacpsdsp_rvv.S b/libavcodec/riscv/aacpsdsp_rvv.S index 80bd19f6ad2..b581383f775 100644 --- a/libavcodec/riscv/aacpsdsp_rvv.S +++ b/libavcodec/riscv/aacpsdsp_rvv.S @@ -22,13 +22,13 @@ func ff_ps_add_squares_rvv, zve32f 1: - vsetvli t0, a2, e32, m1, ta, ma + vsetvli t0, a2, e32, m4, ta, ma vlseg2e32.v v24, (a1) sub a2, a2, t0 vle32.v v16, (a0) sh3add a1, t0, a1 vfmacc.vv v16, v24, v24 - vfmacc.vv v16, v25, v25 + vfmacc.vv v16, v28, v28 vse32.v v16, (a0) sh2add a0, t0, a0 bnez a2, 1b From 98e4dd39c5d59d62f61f48f6e4a0192f6b46e5aa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9mi=20Denis-Courmont?= Date: Sun, 16 Jul 2023 14:46:00 +0300 Subject: [PATCH 1912/2172] checkasm: test Zbb before V Without this, Zbb functions get shadowed by V functions on devices supporting both extensions, and never tested. --- tests/checkasm/checkasm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/checkasm/checkasm.c b/tests/checkasm/checkasm.c index 9976726021e..bb47f5bd84a 100644 --- a/tests/checkasm/checkasm.c +++ b/tests/checkasm/checkasm.c @@ -248,11 +248,11 @@ static const struct { { "RVI", "rvi", AV_CPU_FLAG_RVI }, { "RVF", "rvf", AV_CPU_FLAG_RVF }, { "RVD", "rvd", AV_CPU_FLAG_RVD }, + { "RVBbasic", "rvb_b", AV_CPU_FLAG_RVB_BASIC }, { "RVVi32", "rvv_i32", AV_CPU_FLAG_RVV_I32 }, { "RVVf32", "rvv_f32", AV_CPU_FLAG_RVV_F32 }, { "RVVi64", "rvv_i64", AV_CPU_FLAG_RVV_I64 }, { "RVVf64", "rvv_f64", AV_CPU_FLAG_RVV_F64 }, - { "RVBbasic", "rvb_b", AV_CPU_FLAG_RVB_BASIC }, #elif ARCH_MIPS { "MMI", "mmi", AV_CPU_FLAG_MMI }, { "MSA", "msa", AV_CPU_FLAG_MSA }, From b6585eb04c0f63f231ed16266c6ad893522dc750 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9mi=20Denis-Courmont?= Date: Sun, 16 Jul 2023 15:08:08 +0300 Subject: [PATCH 1913/2172] lavu: add/use flag for RISC-V Zba extension The code was blindly assuming that Zbb or V implied Zba. While the earlier is practically always true, the later broke some QEMU setups, as V was introduced earlier than Zba. --- libavcodec/riscv/aacpsdsp_init.c | 11 ++++++--- libavcodec/riscv/alacdsp_init.c | 2 +- libavcodec/riscv/audiodsp_init.c | 12 +++++---- libavcodec/riscv/bswapdsp_init.c | 16 ++++++------ libavcodec/riscv/fmtconvert_init.c | 2 +- libavcodec/riscv/h264_chroma_init_riscv.c | 3 ++- libavcodec/riscv/vorbisdsp_init.c | 2 +- libavutil/cpu.c | 1 + libavutil/cpu.h | 1 + libavutil/riscv/cpu.c | 5 +++- libavutil/riscv/fixed_dsp_init.c | 2 +- libavutil/riscv/float_dsp_init.c | 30 ++++++++++++----------- libswscale/riscv/rgb2rgb.c | 2 +- tests/checkasm/checkasm.c | 1 + 14 files changed, 53 insertions(+), 37 deletions(-) diff --git a/libavcodec/riscv/aacpsdsp_init.c b/libavcodec/riscv/aacpsdsp_init.c index f42baf4251a..c5ec7962322 100644 --- a/libavcodec/riscv/aacpsdsp_init.c +++ b/libavcodec/riscv/aacpsdsp_init.c @@ -43,13 +43,16 @@ av_cold void ff_psdsp_init_riscv(PSDSPContext *c) int flags = av_get_cpu_flags(); if (flags & AV_CPU_FLAG_RVV_F32) { - c->add_squares = ff_ps_add_squares_rvv; - c->mul_pair_single = ff_ps_mul_pair_single_rvv; c->hybrid_analysis = ff_ps_hybrid_analysis_rvv; - c->stereo_interpolate[0] = ff_ps_stereo_interpolate_rvv; + + if (flags & AV_CPU_FLAG_RVB_ADDR) { + c->add_squares = ff_ps_add_squares_rvv; + c->mul_pair_single = ff_ps_mul_pair_single_rvv; + c->stereo_interpolate[0] = ff_ps_stereo_interpolate_rvv; + } } - if (flags & AV_CPU_FLAG_RVV_I32) { + if ((flags & AV_CPU_FLAG_RVV_I32) && (flags & AV_CPU_FLAG_RVB_ADDR)) { c->hybrid_analysis_ileave = ff_ps_hybrid_analysis_ileave_rvv; c->hybrid_synthesis_deint = ff_ps_hybrid_synthesis_deint_rvv; } diff --git a/libavcodec/riscv/alacdsp_init.c b/libavcodec/riscv/alacdsp_init.c index fa8a7c81299..cd6dc4f8aea 100644 --- a/libavcodec/riscv/alacdsp_init.c +++ b/libavcodec/riscv/alacdsp_init.c @@ -41,7 +41,7 @@ av_cold void ff_alacdsp_init_riscv(ALACDSPContext *c) #if HAVE_RVV && (__riscv_xlen == 64) int flags = av_get_cpu_flags(); - if (flags & AV_CPU_FLAG_RVV_I32) { + if ((flags & AV_CPU_FLAG_RVV_I32) && (flags & AV_CPU_FLAG_RVB_ADDR)) { c->decorrelate_stereo = ff_alac_decorrelate_stereo_rvv; c->append_extra_bits[0] = ff_alac_append_extra_bits_mono_rvv; c->append_extra_bits[1] = ff_alac_append_extra_bits_stereo_rvv; diff --git a/libavcodec/riscv/audiodsp_init.c b/libavcodec/riscv/audiodsp_init.c index 32c3c6794da..9ab59c011eb 100644 --- a/libavcodec/riscv/audiodsp_init.c +++ b/libavcodec/riscv/audiodsp_init.c @@ -38,11 +38,13 @@ av_cold void ff_audiodsp_init_riscv(AudioDSPContext *c) if (flags & AV_CPU_FLAG_RVF) c->vector_clipf = ff_vector_clipf_rvf; #if HAVE_RVV - if (flags & AV_CPU_FLAG_RVV_I32) { - c->scalarproduct_int16 = ff_scalarproduct_int16_rvv; - c->vector_clip_int32 = ff_vector_clip_int32_rvv; + if (flags & AV_CPU_FLAG_RVB_ADDR) { + if (flags & AV_CPU_FLAG_RVV_I32) { + c->scalarproduct_int16 = ff_scalarproduct_int16_rvv; + c->vector_clip_int32 = ff_vector_clip_int32_rvv; + } + if (flags & AV_CPU_FLAG_RVV_F32) + c->vector_clipf = ff_vector_clipf_rvv; } - if (flags & AV_CPU_FLAG_RVV_F32) - c->vector_clipf = ff_vector_clipf_rvv; #endif } diff --git a/libavcodec/riscv/bswapdsp_init.c b/libavcodec/riscv/bswapdsp_init.c index abe84ec1f7d..6ad63e38058 100644 --- a/libavcodec/riscv/bswapdsp_init.c +++ b/libavcodec/riscv/bswapdsp_init.c @@ -31,16 +31,18 @@ void ff_bswap16_buf_rvv(uint16_t *dst, const uint16_t *src, int len); av_cold void ff_bswapdsp_init_riscv(BswapDSPContext *c) { - int cpu_flags = av_get_cpu_flags(); + int flags = av_get_cpu_flags(); + if (flags & AV_CPU_FLAG_RVB_ADDR) { #if (__riscv_xlen >= 64) - if (cpu_flags & AV_CPU_FLAG_RVB_BASIC) - c->bswap_buf = ff_bswap32_buf_rvb; + if (flags & AV_CPU_FLAG_RVB_BASIC) + c->bswap_buf = ff_bswap32_buf_rvb; #endif #if HAVE_RVV - if (cpu_flags & AV_CPU_FLAG_RVV_I32) { - c->bswap_buf = ff_bswap32_buf_rvv; - c->bswap16_buf = ff_bswap16_buf_rvv; - } + if (flags & AV_CPU_FLAG_RVV_I32) { + c->bswap_buf = ff_bswap32_buf_rvv; + c->bswap16_buf = ff_bswap16_buf_rvv; + } #endif + } } diff --git a/libavcodec/riscv/fmtconvert_init.c b/libavcodec/riscv/fmtconvert_init.c index 2ded9d36153..f5eeafba457 100644 --- a/libavcodec/riscv/fmtconvert_init.c +++ b/libavcodec/riscv/fmtconvert_init.c @@ -36,7 +36,7 @@ av_cold void ff_fmt_convert_init_riscv(FmtConvertContext *c) #if HAVE_RVV int flags = av_get_cpu_flags(); - if (flags & AV_CPU_FLAG_RVV_F32) { + if ((flags & AV_CPU_FLAG_RVV_F32) && (flags & AV_CPU_FLAG_RVB_ADDR)) { c->int32_to_float_fmul_scalar = ff_int32_to_float_fmul_scalar_rvv; c->int32_to_float_fmul_array8 = ff_int32_to_float_fmul_array8_rvv; } diff --git a/libavcodec/riscv/h264_chroma_init_riscv.c b/libavcodec/riscv/h264_chroma_init_riscv.c index 7c905edfcd8..f3e912823b5 100644 --- a/libavcodec/riscv/h264_chroma_init_riscv.c +++ b/libavcodec/riscv/h264_chroma_init_riscv.c @@ -33,7 +33,8 @@ av_cold void ff_h264chroma_init_riscv(H264ChromaContext *c, int bit_depth) #if HAVE_RVV int flags = av_get_cpu_flags(); - if (bit_depth == 8 && (flags & AV_CPU_FLAG_RVV_I32) && ff_get_rv_vlenb() >= 16) { + if (bit_depth == 8 && (flags & AV_CPU_FLAG_RVV_I32) && + (flags & AV_CPU_FLAG_RVB_ADDR) && ff_get_rv_vlenb() >= 16) { c->put_h264_chroma_pixels_tab[0] = h264_put_chroma_mc8_rvv; c->avg_h264_chroma_pixels_tab[0] = h264_avg_chroma_mc8_rvv; } diff --git a/libavcodec/riscv/vorbisdsp_init.c b/libavcodec/riscv/vorbisdsp_init.c index 0c56ffcb9b7..0bbbcb68de6 100644 --- a/libavcodec/riscv/vorbisdsp_init.c +++ b/libavcodec/riscv/vorbisdsp_init.c @@ -31,7 +31,7 @@ av_cold void ff_vorbisdsp_init_riscv(VorbisDSPContext *c) #if HAVE_RVV int flags = av_get_cpu_flags(); - if (flags & AV_CPU_FLAG_RVV_I32) + if ((flags & AV_CPU_FLAG_RVV_I32) && (flags & AV_CPU_FLAG_RVB_ADDR)) c->vorbis_inverse_coupling = ff_vorbis_inverse_coupling_rvv; #endif } diff --git a/libavutil/cpu.c b/libavutil/cpu.c index 2ffc3986aa4..1e0607d581a 100644 --- a/libavutil/cpu.c +++ b/libavutil/cpu.c @@ -190,6 +190,7 @@ int av_parse_cpu_caps(unsigned *flags, const char *s) { "rvv-f32", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = AV_CPU_FLAG_RVV_F32 }, .unit = "flags" }, { "rvv-i64", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = AV_CPU_FLAG_RVV_I64 }, .unit = "flags" }, { "rvv", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = AV_CPU_FLAG_RVV_F64 }, .unit = "flags" }, + { "rvb-addr",NULL, 0, AV_OPT_TYPE_CONST, { .i64 = AV_CPU_FLAG_RVB_ADDR }, .unit = "flags" }, { "rvb-basic",NULL, 0, AV_OPT_TYPE_CONST, { .i64 = AV_CPU_FLAG_RVB_BASIC }, .unit = "flags" }, #endif { NULL }, diff --git a/libavutil/cpu.h b/libavutil/cpu.h index da486f9c7ab..8dff3418864 100644 --- a/libavutil/cpu.h +++ b/libavutil/cpu.h @@ -89,6 +89,7 @@ #define AV_CPU_FLAG_RVV_I64 (1 << 5) ///< Vectors of 64-bit int's */ #define AV_CPU_FLAG_RVV_F64 (1 << 6) ///< Vectors of double's #define AV_CPU_FLAG_RVB_BASIC (1 << 7) ///< Basic bit-manipulations +#define AV_CPU_FLAG_RVB_ADDR (1 << 8) ///< Address bit-manipulations /** * Return the flags which specify extensions supported by the CPU. diff --git a/libavutil/riscv/cpu.c b/libavutil/riscv/cpu.c index a9263dbb786..fa45c0ad83a 100644 --- a/libavutil/riscv/cpu.c +++ b/libavutil/riscv/cpu.c @@ -41,7 +41,7 @@ int ff_get_cpu_flags_riscv(void) if (hwcap & HWCAP_RV('D')) ret |= AV_CPU_FLAG_RVD; if (hwcap & HWCAP_RV('B')) - ret |= AV_CPU_FLAG_RVB_BASIC; + ret |= AV_CPU_FLAG_RVB_ADDR | AV_CPU_FLAG_RVB_BASIC; /* The V extension implies all Zve* functional subsets */ if (hwcap & HWCAP_RV('V')) @@ -59,6 +59,9 @@ int ff_get_cpu_flags_riscv(void) #endif #endif +#ifdef __riscv_zba + ret |= AV_CPU_FLAG_RVB_ADDR; +#endif #ifdef __riscv_zbb ret |= AV_CPU_FLAG_RVB_BASIC; #endif diff --git a/libavutil/riscv/fixed_dsp_init.c b/libavutil/riscv/fixed_dsp_init.c index e2915f1fcd6..d4ca2e2064a 100644 --- a/libavutil/riscv/fixed_dsp_init.c +++ b/libavutil/riscv/fixed_dsp_init.c @@ -32,7 +32,7 @@ av_cold void ff_fixed_dsp_init_riscv(AVFixedDSPContext *fdsp) #if HAVE_RVV int flags = av_get_cpu_flags(); - if (flags & AV_CPU_FLAG_RVV_I32) + if ((flags & AV_CPU_FLAG_RVV_I32) && (flags & AV_CPU_FLAG_RVB_ADDR)) fdsp->butterflies_fixed = ff_butterflies_fixed_rvv; #endif } diff --git a/libavutil/riscv/float_dsp_init.c b/libavutil/riscv/float_dsp_init.c index e61f887862e..585f237225d 100644 --- a/libavutil/riscv/float_dsp_init.c +++ b/libavutil/riscv/float_dsp_init.c @@ -52,21 +52,23 @@ av_cold void ff_float_dsp_init_riscv(AVFloatDSPContext *fdsp) #if HAVE_RVV int flags = av_get_cpu_flags(); - if (flags & AV_CPU_FLAG_RVV_F32) { - fdsp->vector_fmul = ff_vector_fmul_rvv; - fdsp->vector_fmac_scalar = ff_vector_fmac_scalar_rvv; - fdsp->vector_fmul_scalar = ff_vector_fmul_scalar_rvv; - fdsp->vector_fmul_window = ff_vector_fmul_window_rvv; - fdsp->vector_fmul_add = ff_vector_fmul_add_rvv; - fdsp->vector_fmul_reverse = ff_vector_fmul_reverse_rvv; - fdsp->butterflies_float = ff_butterflies_float_rvv; - fdsp->scalarproduct_float = ff_scalarproduct_float_rvv; - } + if (flags & AV_CPU_FLAG_RVB_ADDR) { + if (flags & AV_CPU_FLAG_RVV_F32) { + fdsp->vector_fmul = ff_vector_fmul_rvv; + fdsp->vector_fmac_scalar = ff_vector_fmac_scalar_rvv; + fdsp->vector_fmul_scalar = ff_vector_fmul_scalar_rvv; + fdsp->vector_fmul_window = ff_vector_fmul_window_rvv; + fdsp->vector_fmul_add = ff_vector_fmul_add_rvv; + fdsp->vector_fmul_reverse = ff_vector_fmul_reverse_rvv; + fdsp->butterflies_float = ff_butterflies_float_rvv; + fdsp->scalarproduct_float = ff_scalarproduct_float_rvv; + } - if (flags & AV_CPU_FLAG_RVV_F64) { - fdsp->vector_dmul = ff_vector_dmul_rvv; - fdsp->vector_dmac_scalar = ff_vector_dmac_scalar_rvv; - fdsp->vector_dmul_scalar = ff_vector_dmul_scalar_rvv; + if (flags & AV_CPU_FLAG_RVV_F64) { + fdsp->vector_dmul = ff_vector_dmul_rvv; + fdsp->vector_dmac_scalar = ff_vector_dmac_scalar_rvv; + fdsp->vector_dmul_scalar = ff_vector_dmul_scalar_rvv; + } } #endif } diff --git a/libswscale/riscv/rgb2rgb.c b/libswscale/riscv/rgb2rgb.c index 37a2cd5ea1e..4c2d0f07d23 100644 --- a/libswscale/riscv/rgb2rgb.c +++ b/libswscale/riscv/rgb2rgb.c @@ -45,7 +45,7 @@ av_cold void rgb2rgb_init_riscv(void) #if HAVE_RVV int flags = av_get_cpu_flags(); - if (flags & AV_CPU_FLAG_RVV_I32) { + if ((flags & AV_CPU_FLAG_RVV_I32) && (flags & AV_CPU_FLAG_RVB_ADDR)) { shuffle_bytes_0321 = ff_shuffle_bytes_0321_rvv; shuffle_bytes_2103 = ff_shuffle_bytes_2103_rvv; shuffle_bytes_1230 = ff_shuffle_bytes_1230_rvv; diff --git a/tests/checkasm/checkasm.c b/tests/checkasm/checkasm.c index bb47f5bd84a..30e2dc6fed7 100644 --- a/tests/checkasm/checkasm.c +++ b/tests/checkasm/checkasm.c @@ -248,6 +248,7 @@ static const struct { { "RVI", "rvi", AV_CPU_FLAG_RVI }, { "RVF", "rvf", AV_CPU_FLAG_RVF }, { "RVD", "rvd", AV_CPU_FLAG_RVD }, + { "RVBaddr", "rvb_a", AV_CPU_FLAG_RVB_ADDR }, { "RVBbasic", "rvb_b", AV_CPU_FLAG_RVB_BASIC }, { "RVVi32", "rvv_i32", AV_CPU_FLAG_RVV_I32 }, { "RVVf32", "rvv_f32", AV_CPU_FLAG_RVV_F32 }, From 5de1db53701c470b0d73c521b9385773b97b93f1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9mi=20Denis-Courmont?= Date: Sun, 16 Jul 2023 16:55:30 +0300 Subject: [PATCH 1914/2172] lavc/bswapdsp: rewrite RISC-V V bswap16 This favours bit-wise logic over slow strided stores. --- libavcodec/riscv/bswapdsp_rvv.S | 21 ++++++++++----------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/libavcodec/riscv/bswapdsp_rvv.S b/libavcodec/riscv/bswapdsp_rvv.S index ef2999c1be5..8b585ec5c91 100644 --- a/libavcodec/riscv/bswapdsp_rvv.S +++ b/libavcodec/riscv/bswapdsp_rvv.S @@ -45,18 +45,17 @@ func ff_bswap32_buf_rvv, zve32x endfunc func ff_bswap16_buf_rvv, zve32x - li t2, 2 - addi t1, a0, 1 1: - vsetvli t0, a2, e8, m1, ta, ma - vlseg2e8.v v8, (a1) - sub a2, a2, t0 - sh1add a1, t0, a1 - vsse8.v v8, (t1), t2 - sh1add t1, t0, t1 - vsse8.v v9, (a0), t2 - sh1add a0, t0, a0 - bnez a2, 1b + vsetvli t0, a2, e16, m8, ta, ma + vle16.v v8, (a1) + sub a2, a2, t0 + vsll.vi v16, v8, 8 + sh1add a1, t0, a1 + vsrl.vi v24, v8, 8 + vor.vv v8, v16, v24 + vse16.v v8, (a0) + sh1add a0, t0, a0 + bnez a2, 1b ret endfunc From 61e5ca4ded9c5fe697fdffe69bb041d5852556ba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9mi=20Denis-Courmont?= Date: Sun, 16 Jul 2023 17:27:45 +0300 Subject: [PATCH 1915/2172] lavc/bswapdsp: purge RISC-V V bswap32 This cannot beat the Zbb implementation, and it is unlikely that a real meaningful CPU design would support V and not Zbb. The best loop rewrite that I could come up with (4 shifts, 2 ands, 3 ors) is still ~40% slower than Zbb. A proper faster vector implementation should be feasible with the cryptographic vector extensions, but that is a story for another time. --- libavcodec/riscv/bswapdsp_init.c | 5 +---- libavcodec/riscv/bswapdsp_rvv.S | 23 ----------------------- 2 files changed, 1 insertion(+), 27 deletions(-) diff --git a/libavcodec/riscv/bswapdsp_init.c b/libavcodec/riscv/bswapdsp_init.c index 6ad63e38058..ed666c9b3a3 100644 --- a/libavcodec/riscv/bswapdsp_init.c +++ b/libavcodec/riscv/bswapdsp_init.c @@ -26,7 +26,6 @@ #include "libavcodec/bswapdsp.h" void ff_bswap32_buf_rvb(uint32_t *dst, const uint32_t *src, int len); -void ff_bswap32_buf_rvv(uint32_t *dst, const uint32_t *src, int len); void ff_bswap16_buf_rvv(uint16_t *dst, const uint16_t *src, int len); av_cold void ff_bswapdsp_init_riscv(BswapDSPContext *c) @@ -39,10 +38,8 @@ av_cold void ff_bswapdsp_init_riscv(BswapDSPContext *c) c->bswap_buf = ff_bswap32_buf_rvb; #endif #if HAVE_RVV - if (flags & AV_CPU_FLAG_RVV_I32) { - c->bswap_buf = ff_bswap32_buf_rvv; + if (flags & AV_CPU_FLAG_RVV_I32) c->bswap16_buf = ff_bswap16_buf_rvv; - } #endif } } diff --git a/libavcodec/riscv/bswapdsp_rvv.S b/libavcodec/riscv/bswapdsp_rvv.S index 8b585ec5c91..b37fe262559 100644 --- a/libavcodec/riscv/bswapdsp_rvv.S +++ b/libavcodec/riscv/bswapdsp_rvv.S @@ -21,29 +21,6 @@ #include "config.h" #include "libavutil/riscv/asm.S" -func ff_bswap32_buf_rvv, zve32x - li t4, 4 - addi t1, a0, 1 - addi t2, a0, 2 - addi t3, a0, 3 -1: - vsetvli t0, a2, e8, m1, ta, ma - vlseg4e8.v v8, (a1) - sub a2, a2, t0 - sh2add a1, t0, a1 - vsse8.v v8, (t3), t4 - sh2add t3, t0, t3 - vsse8.v v9, (t2), t4 - sh2add t2, t0, t2 - vsse8.v v10, (t1), t4 - sh2add t1, t0, t1 - vsse8.v v11, (a0), t4 - sh2add a0, t0, a0 - bnez a2, 1b - - ret -endfunc - func ff_bswap16_buf_rvv, zve32x 1: vsetvli t0, a2, e16, m8, ta, ma From 5d8879208cd76e76ae5d093b207787979bea0cb1 Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Wed, 19 Jul 2023 22:48:54 +0200 Subject: [PATCH 1916/2172] avfilter/vf_pseudocolor: add cool preset --- doc/filters.texi | 1 + libavfilter/vf_pseudocolor.c | 58 +++++++++++++++++++++++++++++++++--- 2 files changed, 55 insertions(+), 4 deletions(-) diff --git a/doc/filters.texi b/doc/filters.texi index e5325c7410b..c6d331d12a8 100644 --- a/doc/filters.texi +++ b/doc/filters.texi @@ -19706,6 +19706,7 @@ Available LUTs: @item preferred @item total @item spectral +@item cool @end table @item opacity diff --git a/libavfilter/vf_pseudocolor.c b/libavfilter/vf_pseudocolor.c index 89dc2f0901f..8475d4f4dfc 100644 --- a/libavfilter/vf_pseudocolor.c +++ b/libavfilter/vf_pseudocolor.c @@ -68,6 +68,7 @@ enum Curves { CIVIDIS, SOLAR, SPECTRAL, + COOL, NB_CURVES, }; @@ -87,6 +88,7 @@ enum Presets { PRESET_PREFERRED, PRESET_TOTAL, PRESET_SPECTRAL, + PRESET_COOL, NB_PRESETS, }; @@ -96,6 +98,7 @@ typedef struct Curve { double coef[3][8]; double offset[3]; curve_fun fun[3]; + int yuv; } Curve; typedef struct Fill { @@ -137,6 +140,16 @@ static double solarfun(double x) return 0.5 * sin(x) + 0.5; } +static double coolfunu(double x) +{ + return 0.25 * sin(2.0 * x * M_PI - M_PI) + 0.5; +} + +static double coolfunv(double x) +{ + return 0.25 * sin(2.0 * x * M_PI) + 0.5; +} + static const Curve curves[] = { [MAGMA] = {{ @@ -181,6 +194,14 @@ static const Curve curves[] = { 1.2526e-15, -1.2203e-12, 4.7013e-10, -8.9360e-08, 8.3839e-06, -3.6642e-04, 1.4784e-02, -9.8075e-03 }, { 1.4755e-15, -1.6765e-12, 7.3188e-10, -1.5522e-07, 1.6406e-05, -7.7883e-04, 1.4502e-02, 2.1597e-01 }, }, .fun = { limit, limit, limit }, }, + [COOL] = {{ + { 0, 0, 0, 0, 0, 0, 1./256, 0 }, + { 0, 0, 0, 0, 0, 0, 1./256, 0 }, + { 0, 0, 0, 0, 0, 0, 1./256, 0 }, + }, + .offset = { 0., 0., 0 }, + .yuv = 1, + .fun = { coolfunu, limit, coolfunv }, }, }; static const Preset presets[] = @@ -200,6 +221,7 @@ static const Preset presets[] = [PRESET_HIGHLIGHTS] = { 3, highlights_range, NULL, highlights_fills }, [PRESET_SOLAR] = { 1, &full_range, &curves[SOLAR], NULL }, [PRESET_SPECTRAL]= { 1, &full_range, &curves[SPECTRAL],NULL }, + [PRESET_COOL] = { 1, &full_range, &curves[COOL], NULL }, }; typedef struct PseudoColorContext { @@ -255,6 +277,7 @@ static const AVOption pseudocolor_options[] = { { "preferred", NULL, 0, AV_OPT_TYPE_CONST, {.i64=PRESET_PREFERRED},.flags=FLAGS,"preset" }, { "total", NULL, 0, AV_OPT_TYPE_CONST, {.i64=PRESET_TOTAL}, .flags=FLAGS, "preset" }, { "spectral", NULL, 0, AV_OPT_TYPE_CONST, {.i64=PRESET_SPECTRAL},.flags = FLAGS, "preset" }, + { "cool", NULL, 0, AV_OPT_TYPE_CONST, {.i64=PRESET_COOL}, .flags = FLAGS, "preset" }, { "opacity", "set pseudocolor opacity",OFFSET(opacity), AV_OPT_TYPE_FLOAT, {.dbl=1}, 0, 1, .flags = FLAGS }, { NULL } }; @@ -571,6 +594,19 @@ static void pseudocolor_filter_16_11d(int max, int width, int height, ((0.50000*224.0/255.0) * r1 - (0.45415*224.0/255.0) * g1 - \ (0.04585*224.0/255.0) * b1 + max * 0.5) +#define Wr 0.2126 +#define Wb 0.0722 +#define Wg (1 - Wr - Wb) +#define Umax 0.436 +#define Vmax 0.615 + +#define YUV_BT709_TO_R(y, u, v, max) \ + ((y + v * (1 - Wr) / Vmax) * max) +#define YUV_BT709_TO_G(y, u, v, max) \ + ((y - (u * Wb * (1 - Wb) / (Umax * Wg)) - (v * Wr * (1 - Wr) / (Vmax * Wg))) * max) +#define YUV_BT709_TO_B(y, u, v, max) \ + ((y + u * (1 - Wb) / Umax) * max) + static double poly_eval(const double *const poly, double x, curve_fun fun) { double res = 0.; @@ -696,11 +732,17 @@ static int config_input(AVFilterLink *inlink) const double lf = i / (double)s->max * 256.; double r, g, b; - g = poly_eval(curve.coef[1], lf + curve.offset[1], curve.fun[1]) * s->max; - b = poly_eval(curve.coef[2], lf + curve.offset[2], curve.fun[2]) * s->max; - r = poly_eval(curve.coef[0], lf + curve.offset[0], curve.fun[0]) * s->max; + g = poly_eval(curve.coef[1], lf + curve.offset[1], curve.fun[1]); + b = poly_eval(curve.coef[2], lf + curve.offset[2], curve.fun[2]); + r = poly_eval(curve.coef[0], lf + curve.offset[0], curve.fun[0]); + + if (!curve.yuv || !rgb) { + g *= s->max; + b *= s->max; + r *= s->max; + } - if (!rgb) { + if (!rgb && !curve.yuv) { double y = RGB_TO_Y_BT709(r, g, b); double u = RGB_TO_U_BT709(r, g, b, s->max); double v = RGB_TO_V_BT709(r, g, b, s->max); @@ -708,6 +750,14 @@ static int config_input(AVFilterLink *inlink) r = v; g = y; b = u; + } else if (rgb && curve.yuv) { + double y = g; + double u = b - 0.5; + double v = r - 0.5; + + r = av_clipd(YUV_BT709_TO_R(y, u, v, s->max), 0, s->max); + g = av_clipd(YUV_BT709_TO_G(y, u, v, s->max), 0, s->max); + b = av_clipd(YUV_BT709_TO_B(y, u, v, s->max), 0, s->max); } s->lut[0][i] = g; From 72390c7d809fd636497ba1e3552930c0938c6a44 Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Wed, 19 Jul 2023 23:16:54 +0200 Subject: [PATCH 1917/2172] avfilter/vf_pseudocolor: add heat preset --- doc/filters.texi | 1 + libavfilter/vf_pseudocolor.c | 22 ++++++++++++++++++++++ 2 files changed, 23 insertions(+) diff --git a/doc/filters.texi b/doc/filters.texi index c6d331d12a8..6f3f666c95a 100644 --- a/doc/filters.texi +++ b/doc/filters.texi @@ -19707,6 +19707,7 @@ Available LUTs: @item total @item spectral @item cool +@item heat @end table @item opacity diff --git a/libavfilter/vf_pseudocolor.c b/libavfilter/vf_pseudocolor.c index 8475d4f4dfc..5b6cd5e70ab 100644 --- a/libavfilter/vf_pseudocolor.c +++ b/libavfilter/vf_pseudocolor.c @@ -69,6 +69,7 @@ enum Curves { SOLAR, SPECTRAL, COOL, + HEAT, NB_CURVES, }; @@ -89,6 +90,7 @@ enum Presets { PRESET_TOTAL, PRESET_SPECTRAL, PRESET_COOL, + PRESET_HEAT, NB_PRESETS, }; @@ -150,6 +152,16 @@ static double coolfunv(double x) return 0.25 * sin(2.0 * x * M_PI) + 0.5; } +static double heatfunu(double x) +{ + return 0.25 * cos(2.0 * x * M_PI + M_PI) + 0.75; +} + +static double heatfunv(double x) +{ + return 0.25 * sin(2.0 * x * M_PI) + 0.5; +} + static const Curve curves[] = { [MAGMA] = {{ @@ -202,6 +214,14 @@ static const Curve curves[] = .offset = { 0., 0., 0 }, .yuv = 1, .fun = { coolfunu, limit, coolfunv }, }, + [HEAT] = {{ + { 0, 0, 0, 0, 0, 0, 1./256, 0 }, + { 0, 0, 0, 0, 0, 0, 1./256, 0 }, + { 0, 0, 0, 0, 0, 0, 1./256, 0 }, + }, + .offset = { 0., 0., 0 }, + .yuv = 1, + .fun = { heatfunu, limit, heatfunv }, }, }; static const Preset presets[] = @@ -222,6 +242,7 @@ static const Preset presets[] = [PRESET_SOLAR] = { 1, &full_range, &curves[SOLAR], NULL }, [PRESET_SPECTRAL]= { 1, &full_range, &curves[SPECTRAL],NULL }, [PRESET_COOL] = { 1, &full_range, &curves[COOL], NULL }, + [PRESET_HEAT]= { 1, &full_range, &curves[HEAT],NULL }, }; typedef struct PseudoColorContext { @@ -278,6 +299,7 @@ static const AVOption pseudocolor_options[] = { { "total", NULL, 0, AV_OPT_TYPE_CONST, {.i64=PRESET_TOTAL}, .flags=FLAGS, "preset" }, { "spectral", NULL, 0, AV_OPT_TYPE_CONST, {.i64=PRESET_SPECTRAL},.flags = FLAGS, "preset" }, { "cool", NULL, 0, AV_OPT_TYPE_CONST, {.i64=PRESET_COOL}, .flags = FLAGS, "preset" }, + { "heat", NULL, 0, AV_OPT_TYPE_CONST, {.i64=PRESET_HEAT}, .flags = FLAGS, "preset" }, { "opacity", "set pseudocolor opacity",OFFSET(opacity), AV_OPT_TYPE_FLOAT, {.dbl=1}, 0, 1, .flags = FLAGS }, { NULL } }; From 1e36e1f258a72880e4c74d4af760b4371c9acd43 Mon Sep 17 00:00:00 2001 From: Stephen Hutchinson Date: Sun, 11 Jun 2023 20:21:41 -0400 Subject: [PATCH 1918/2172] avisynth: pass audio channel layout Signed-off-by: Stephen Hutchinson --- libavformat/avisynth.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/libavformat/avisynth.c b/libavformat/avisynth.c index b426ac343e6..027e8c63f68 100644 --- a/libavformat/avisynth.c +++ b/libavformat/avisynth.c @@ -62,6 +62,7 @@ typedef struct AviSynthLibrary { AVSC_DECLARE_FUNC(avs_create_script_environment); AVSC_DECLARE_FUNC(avs_delete_script_environment); AVSC_DECLARE_FUNC(avs_get_audio); + AVSC_DECLARE_FUNC(avs_get_channel_mask); AVSC_DECLARE_FUNC(avs_get_error); AVSC_DECLARE_FUNC(avs_get_frame); AVSC_DECLARE_FUNC(avs_get_version); @@ -157,6 +158,7 @@ static av_cold int avisynth_load_library(void) LOAD_AVS_FUNC(avs_create_script_environment, 0); LOAD_AVS_FUNC(avs_delete_script_environment, 0); LOAD_AVS_FUNC(avs_get_audio, 0); + LOAD_AVS_FUNC(avs_get_channel_mask, 1); LOAD_AVS_FUNC(avs_get_error, 1); // New to AviSynth 2.6 LOAD_AVS_FUNC(avs_get_frame, 0); LOAD_AVS_FUNC(avs_get_version, 0); @@ -793,6 +795,10 @@ static int avisynth_create_stream_audio(AVFormatContext *s, AVStream *st) st->duration = avs->vi->num_audio_samples; avpriv_set_pts_info(st, 64, 1, avs->vi->audio_samples_per_second); + if (avs_library.avs_get_version(avs->clip) >= 10) + av_channel_layout_from_mask(&st->codecpar->ch_layout, + avs_library.avs_get_channel_mask(avs->vi)); + switch (avs->vi->sample_type) { case AVS_SAMPLE_INT8: st->codecpar->codec_id = AV_CODEC_ID_PCM_U8; From efa6cec759d7c692808a8cc43d610fe6b9fadfe1 Mon Sep 17 00:00:00 2001 From: Stephen Hutchinson Date: Sun, 11 Jun 2023 20:26:06 -0400 Subject: [PATCH 1919/2172] configure: bump minimum AviSynth+ header version AVISYNTH_INTERFACE_VERSION 10 fell in-between the releases of 3.7.2 and 3.7.3, and is required to be able to read the channel layout information. Signed-off-by: Stephen Hutchinson --- configure | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/configure b/configure index b018abf139a..d46e868a0cb 100755 --- a/configure +++ b/configure @@ -6656,8 +6656,8 @@ done # these are off by default, so fail if requested and not available enabled avisynth && { require_headers "avisynth/avisynth_c.h avisynth/avs/version.h" && - { test_cpp_condition avisynth/avs/version.h "AVS_MAJOR_VER >= 3 && AVS_MINOR_VER >= 7 && AVS_BUGFIX_VER >= 1 || AVS_MAJOR_VER >= 3 && AVS_MINOR_VER > 7 || AVS_MAJOR_VER > 3" || - die "ERROR: AviSynth+ header version must be >= 3.7.1"; } } + { test_cpp_condition avisynth/avs/version.h "AVS_MAJOR_VER >= 3 && AVS_MINOR_VER >= 7 && AVS_BUGFIX_VER >= 3 || AVS_MAJOR_VER >= 3 && AVS_MINOR_VER > 7 || AVS_MAJOR_VER > 3" || + die "ERROR: AviSynth+ header version must be >= 3.7.3"; } } enabled cuda_nvcc && { check_nvcc cuda_nvcc || die "ERROR: failed checking for nvcc."; } enabled chromaprint && { check_pkg_config chromaprint libchromaprint "chromaprint.h" chromaprint_get_version || require chromaprint chromaprint.h chromaprint_get_version -lchromaprint; } From 6747cda5ca4adda916ec9b5215e65d330b79c456 Mon Sep 17 00:00:00 2001 From: Tobias Rapp Date: Wed, 5 Jul 2023 11:30:33 +0200 Subject: [PATCH 1920/2172] avfilter/vf_overlay: Add support for yuv444p10 pixel format --- doc/filters.texi | 3 +++ libavfilter/vf_overlay.c | 36 +++++++++++++++++++++++++++++++++++- libavfilter/vf_overlay.h | 1 + 3 files changed, 39 insertions(+), 1 deletion(-) diff --git a/doc/filters.texi b/doc/filters.texi index 6f3f666c95a..57d7817dd64 100644 --- a/doc/filters.texi +++ b/doc/filters.texi @@ -18612,6 +18612,9 @@ force YUV422p10 output @item yuv444 force YUV444 output +@item yuv444p10 +force YUV444p10 output + @item rgb force packed RGB output diff --git a/libavfilter/vf_overlay.c b/libavfilter/vf_overlay.c index 36c04ac21ba..fa39abb23a1 100644 --- a/libavfilter/vf_overlay.c +++ b/libavfilter/vf_overlay.c @@ -156,7 +156,7 @@ static int process_command(AVFilterContext *ctx, const char *cmd, const char *ar static const enum AVPixelFormat alpha_pix_fmts[] = { AV_PIX_FMT_YUVA420P, AV_PIX_FMT_YUVA422P, AV_PIX_FMT_YUVA444P, - AV_PIX_FMT_YUVA420P10, AV_PIX_FMT_YUVA422P10, + AV_PIX_FMT_YUVA420P10, AV_PIX_FMT_YUVA422P10, AV_PIX_FMT_YUVA444P10, AV_PIX_FMT_ARGB, AV_PIX_FMT_ABGR, AV_PIX_FMT_RGBA, AV_PIX_FMT_BGRA, AV_PIX_FMT_GBRAP, AV_PIX_FMT_NONE }; @@ -204,6 +204,13 @@ static int query_formats(AVFilterContext *ctx) AV_PIX_FMT_YUVA444P, AV_PIX_FMT_NONE }; + static const enum AVPixelFormat main_pix_fmts_yuv444p10[] = { + AV_PIX_FMT_YUV444P10, AV_PIX_FMT_YUVA444P10, AV_PIX_FMT_NONE + }; + static const enum AVPixelFormat overlay_pix_fmts_yuv444p10[] = { + AV_PIX_FMT_YUVA444P10, AV_PIX_FMT_NONE + }; + static const enum AVPixelFormat main_pix_fmts_gbrp[] = { AV_PIX_FMT_GBRP, AV_PIX_FMT_GBRAP, AV_PIX_FMT_NONE }; @@ -248,6 +255,10 @@ static int query_formats(AVFilterContext *ctx) main_formats = main_pix_fmts_yuv444; overlay_formats = overlay_pix_fmts_yuv444; break; + case OVERLAY_FORMAT_YUV444P10: + main_formats = main_pix_fmts_yuv444p10; + overlay_formats = overlay_pix_fmts_yuv444p10; + break; case OVERLAY_FORMAT_RGB: main_formats = main_pix_fmts_rgb; overlay_formats = overlay_pix_fmts_rgb; @@ -759,6 +770,22 @@ static int blend_slice_yuva444(AVFilterContext *ctx, void *arg, int jobnr, int n return 0; } +static int blend_slice_yuv444p10(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) +{ + OverlayContext *s = ctx->priv; + ThreadData *td = arg; + blend_slice_yuv_16_10bits(ctx, td->dst, td->src, 0, 0, 0, s->x, s->y, 1, jobnr, nb_jobs); + return 0; +} + +static int blend_slice_yuva444p10(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) +{ + OverlayContext *s = ctx->priv; + ThreadData *td = arg; + blend_slice_yuv_16_10bits(ctx, td->dst, td->src, 0, 0, 1, s->x, s->y, 1, jobnr, nb_jobs); + return 0; +} + static int blend_slice_gbrp(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) { OverlayContext *s = ctx->priv; @@ -902,6 +929,9 @@ static int config_input_main(AVFilterLink *inlink) case OVERLAY_FORMAT_YUV444: s->blend_slice = s->main_has_alpha ? blend_slice_yuva444 : blend_slice_yuv444; break; + case OVERLAY_FORMAT_YUV444P10: + s->blend_slice = s->main_has_alpha ? blend_slice_yuva444p10 : blend_slice_yuv444p10; + break; case OVERLAY_FORMAT_RGB: s->blend_slice = s->main_has_alpha ? blend_slice_rgba : blend_slice_rgb; break; @@ -925,6 +955,9 @@ static int config_input_main(AVFilterLink *inlink) case AV_PIX_FMT_YUVA444P: s->blend_slice = blend_slice_yuva444; break; + case AV_PIX_FMT_YUVA444P10: + s->blend_slice = blend_slice_yuva444p10; + break; case AV_PIX_FMT_ARGB: case AV_PIX_FMT_RGBA: case AV_PIX_FMT_BGRA: @@ -1084,6 +1117,7 @@ static const AVOption overlay_options[] = { { "yuv422", "", 0, AV_OPT_TYPE_CONST, {.i64=OVERLAY_FORMAT_YUV422}, .flags = FLAGS, .unit = "format" }, { "yuv422p10", "", 0, AV_OPT_TYPE_CONST, {.i64=OVERLAY_FORMAT_YUV422P10}, .flags = FLAGS, .unit = "format" }, { "yuv444", "", 0, AV_OPT_TYPE_CONST, {.i64=OVERLAY_FORMAT_YUV444}, .flags = FLAGS, .unit = "format" }, + { "yuv444p10", "", 0, AV_OPT_TYPE_CONST, {.i64=OVERLAY_FORMAT_YUV444P10}, .flags = FLAGS, .unit = "format" }, { "rgb", "", 0, AV_OPT_TYPE_CONST, {.i64=OVERLAY_FORMAT_RGB}, .flags = FLAGS, .unit = "format" }, { "gbrp", "", 0, AV_OPT_TYPE_CONST, {.i64=OVERLAY_FORMAT_GBRP}, .flags = FLAGS, .unit = "format" }, { "auto", "", 0, AV_OPT_TYPE_CONST, {.i64=OVERLAY_FORMAT_AUTO}, .flags = FLAGS, .unit = "format" }, diff --git a/libavfilter/vf_overlay.h b/libavfilter/vf_overlay.h index 7e65095a062..59749648c32 100644 --- a/libavfilter/vf_overlay.h +++ b/libavfilter/vf_overlay.h @@ -47,6 +47,7 @@ enum OverlayFormat { OVERLAY_FORMAT_YUV422, OVERLAY_FORMAT_YUV422P10, OVERLAY_FORMAT_YUV444, + OVERLAY_FORMAT_YUV444P10, OVERLAY_FORMAT_RGB, OVERLAY_FORMAT_GBRP, OVERLAY_FORMAT_AUTO, From afaa3458247d0d45f4d07cc0ef53be468c5f3349 Mon Sep 17 00:00:00 2001 From: Tobias Rapp Date: Wed, 5 Jul 2023 12:03:36 +0200 Subject: [PATCH 1921/2172] tests/fate: Add test for overlay filter using yuv444p10 output format --- tests/fate/filter-video.mak | 2 +- tests/filtergraphs/overlay_yuv444p10 | 5 +++++ tests/ref/fate/filter-overlay_yuv444p10 | 8 ++++++++ 3 files changed, 14 insertions(+), 1 deletion(-) create mode 100644 tests/filtergraphs/overlay_yuv444p10 create mode 100644 tests/ref/fate/filter-overlay_yuv444p10 diff --git a/tests/fate/filter-video.mak b/tests/fate/filter-video.mak index e6de7de734d..789ec6414c7 100644 --- a/tests/fate/filter-video.mak +++ b/tests/fate/filter-video.mak @@ -213,7 +213,7 @@ fate-filter-vstack: CMD = framecrc -c:v pgmyuv -i $(SRC) -c:v pgmyuv -i $(SRC) - FATE_FILTER_OVERLAY-$(call FILTERDEMDEC, SCALE OVERLAY, IMAGE2, PGMYUV) += fate-filter-overlay fate-filter-overlay: CMD = framecrc -c:v pgmyuv -i $(SRC) -c:v pgmyuv -i $(SRC) -filter_complex_script $(FILTERGRAPH) -FATE_FILTER_OVERLAY-$(call FILTERDEMDEC, SPLIT SCALE PAD OVERLAY, IMAGE2, PGMYUV) += $(addprefix fate-filter-overlay_, rgb yuv420 yuv420p10 nv12 nv21 yuv422 yuv422p10 yuv444) +FATE_FILTER_OVERLAY-$(call FILTERDEMDEC, SPLIT SCALE PAD OVERLAY, IMAGE2, PGMYUV) += $(addprefix fate-filter-overlay_, rgb yuv420 yuv420p10 nv12 nv21 yuv422 yuv422p10 yuv444 yuv444p10) fate-filter-overlay_%: CMD = framecrc -auto_conversion_filters -c:v pgmyuv -i $(SRC) -filter_complex_script $(FILTERGRAPH) fate-filter-overlay_yuv420: CMD = framecrc -c:v pgmyuv -i $(SRC) -filter_complex_script $(FILTERGRAPH) fate-filter-overlay_%p10: CMD = framecrc -auto_conversion_filters -c:v pgmyuv -i $(SRC) -filter_complex_script $(FILTERGRAPH) -pix_fmt $(@:fate-filter-overlay_%=%)le -frames:v 3 diff --git a/tests/filtergraphs/overlay_yuv444p10 b/tests/filtergraphs/overlay_yuv444p10 new file mode 100644 index 00000000000..b184277c086 --- /dev/null +++ b/tests/filtergraphs/overlay_yuv444p10 @@ -0,0 +1,5 @@ +sws_flags=+accurate_rnd+bitexact; +split [main][over]; +[over] scale=88:72, format=yuv444p10, pad=96:80:4:4 [overf]; +[main] format=yuv444p10 [mainf]; +[mainf][overf] overlay=240:16:format=yuv444p10 diff --git a/tests/ref/fate/filter-overlay_yuv444p10 b/tests/ref/fate/filter-overlay_yuv444p10 new file mode 100644 index 00000000000..b74dbcc37f4 --- /dev/null +++ b/tests/ref/fate/filter-overlay_yuv444p10 @@ -0,0 +1,8 @@ +#tb 0: 1/25 +#media_type 0: video +#codec_id 0: rawvideo +#dimensions 0: 352x288 +#sar 0: 0/1 +0, 0, 0, 1, 608256, 0xc5ba4285 +0, 1, 1, 1, 608256, 0x3066fd50 +0, 2, 2, 1, 608256, 0xdb8e68a8 From 0b075b40924051b70fa5fd86a92edde2015c7970 Mon Sep 17 00:00:00 2001 From: Tobias Rapp Date: Wed, 5 Jul 2023 15:02:55 +0200 Subject: [PATCH 1922/2172] doc/filters: Extend description of overlay filter format option values --- doc/filters.texi | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/doc/filters.texi b/doc/filters.texi index 57d7817dd64..1f1890b97db 100644 --- a/doc/filters.texi +++ b/doc/filters.texi @@ -18598,28 +18598,28 @@ Set the format for the output video. It accepts the following values: @table @samp @item yuv420 -force YUV420 output +force YUV 4:2:0 8-bit planar output @item yuv420p10 -force YUV420p10 output +force YUV 4:2:0 10-bit planar output @item yuv422 -force YUV422 output +force YUV 4:2:2 8-bit planar output @item yuv422p10 -force YUV422p10 output +force YUV 4:2:2 10-bit planar output @item yuv444 -force YUV444 output +force YUV 4:4:4 8-bit planar output @item yuv444p10 -force YUV444p10 output +force YUV 4:4:4 10-bit planar output @item rgb -force packed RGB output +force RGB 8-bit packed output @item gbrp -force planar RGB output +force RGB 8-bit planar output @item auto automatically pick format From 249bca763d85e7c323b71f48eb1816edf6525239 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Thu, 13 Jul 2023 12:20:14 +0200 Subject: [PATCH 1923/2172] fftools/ffmpeg_mux_init: handle pixel format endianness When -pix_fmt designates a BE/LE pixel format, it gets translated into the native one by av_get_pix_fmt(). This may not always be the best choice, as the encoder might only support one endianness. In such a case, explicitly choose the endianness supported by the encoder. While this is currently redundant with choose_pixel_fmt() in ffmpeg_filter.c, the latter code will be deprecated in following commits. --- fftools/ffmpeg_mux_init.c | 55 ++++++++++++++++++++++++++++++++++++--- 1 file changed, 52 insertions(+), 3 deletions(-) diff --git a/fftools/ffmpeg_mux_init.c b/fftools/ffmpeg_mux_init.c index c2630dd8937..eafb8be8bd6 100644 --- a/fftools/ffmpeg_mux_init.c +++ b/fftools/ffmpeg_mux_init.c @@ -495,6 +495,54 @@ static int parse_matrix_coeffs(void *logctx, uint16_t *dest, const char *str) return 0; } +static int fmt_in_list(const int *formats, int format) +{ + for (; *formats != -1; formats++) + if (*formats == format) + return 1; + return 0; +} + +static enum AVPixelFormat pix_fmt_parse(OutputStream *ost, const char *name) +{ + const enum AVPixelFormat *fmts = ost->enc_ctx->codec->pix_fmts; + enum AVPixelFormat fmt; + + fmt = av_get_pix_fmt(name); + if (fmt == AV_PIX_FMT_NONE) { + av_log(ost, AV_LOG_FATAL, "Unknown pixel format requested: %s.\n", name); + return AV_PIX_FMT_NONE; + } + + /* when the user specified-format is an alias for an endianness-specific + * one (e.g. rgb48 -> rgb48be/le), it gets translated into the native + * endianness by av_get_pix_fmt(); + * the following code handles the case when the native endianness is not + * supported by the encoder, but the other one is */ + if (fmts && !fmt_in_list(fmts, fmt)) { + const char *name_canonical = av_get_pix_fmt_name(fmt); + int len = strlen(name_canonical); + + if (strcmp(name, name_canonical) && + (!strcmp(name_canonical + len - 2, "le") || + !strcmp(name_canonical + len - 2, "be"))) { + char name_other[64]; + enum AVPixelFormat fmt_other; + + snprintf(name_other, sizeof(name_other), "%s%ce", + name, name_canonical[len - 2] == 'l' ? 'b' : 'l'); + fmt_other = av_get_pix_fmt(name_other); + if (fmt_other != AV_PIX_FMT_NONE && fmt_in_list(fmts, fmt_other)) { + av_log(ost, AV_LOG_VERBOSE, "Mapping pixel format %s->%s\n", + name, name_other); + fmt = fmt_other; + } + } + } + + return fmt; +} + static int new_stream_video(Muxer *mux, const OptionsContext *o, OutputStream *ost) { @@ -558,9 +606,10 @@ static int new_stream_video(Muxer *mux, const OptionsContext *o, if (!*++frame_pix_fmt) frame_pix_fmt = NULL; } - if (frame_pix_fmt && (video_enc->pix_fmt = av_get_pix_fmt(frame_pix_fmt)) == AV_PIX_FMT_NONE) { - av_log(ost, AV_LOG_FATAL, "Unknown pixel format requested: %s.\n", frame_pix_fmt); - return AVERROR(EINVAL); + if (frame_pix_fmt) { + video_enc->pix_fmt = pix_fmt_parse(ost, frame_pix_fmt); + if (video_enc->pix_fmt == AV_PIX_FMT_NONE) + return AVERROR(EINVAL); } MATCH_PER_STREAM_OPT(intra_matrices, str, intra_matrix, oc, st); From 037d3647977255ddbbc807dca3f0951df816199e Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Sat, 15 Jul 2023 11:56:22 +0200 Subject: [PATCH 1924/2172] fftools/ffmpeg_filter: move "smart" pixfmt selection to ffmpeg_mux_init This code works on encoder information and has no interaction with filtering, so it does not belong in ffmpeg_filter. --- fftools/ffmpeg_filter.c | 36 +----------------------------------- fftools/ffmpeg_mux_init.c | 29 +++++++++++++++++++++++++++++ 2 files changed, 30 insertions(+), 35 deletions(-) diff --git a/fftools/ffmpeg_filter.c b/fftools/ffmpeg_filter.c index de75c9970e4..71595513f3f 100644 --- a/fftools/ffmpeg_filter.c +++ b/fftools/ffmpeg_filter.c @@ -285,38 +285,6 @@ static const enum AVPixelFormat *get_compliance_normal_pix_fmts(const AVCodec *c } } -static enum AVPixelFormat -choose_pixel_fmt(const AVCodec *codec, enum AVPixelFormat target, - int strict_std_compliance) -{ - if (codec && codec->pix_fmts) { - const enum AVPixelFormat *p = codec->pix_fmts; - const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(target); - //FIXME: This should check for AV_PIX_FMT_FLAG_ALPHA after PAL8 pixel format without alpha is implemented - int has_alpha = desc ? desc->nb_components % 2 == 0 : 0; - enum AVPixelFormat best= AV_PIX_FMT_NONE; - - if (strict_std_compliance > FF_COMPLIANCE_UNOFFICIAL) { - p = get_compliance_normal_pix_fmts(codec, p); - } - for (; *p != AV_PIX_FMT_NONE; p++) { - best = av_find_best_pix_fmt_of_2(best, *p, target, has_alpha, NULL); - if (*p == target) - break; - } - if (*p == AV_PIX_FMT_NONE) { - if (target != AV_PIX_FMT_NONE) - av_log(NULL, AV_LOG_WARNING, - "Incompatible pixel format '%s' for codec '%s', auto-selecting format '%s'\n", - av_get_pix_fmt_name(target), - codec->name, - av_get_pix_fmt_name(best)); - return best; - } - } - return target; -} - /* 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. */ @@ -326,7 +294,6 @@ static const char *choose_pix_fmts(OutputFilter *ofilter, AVBPrint *bprint) AVCodecContext *enc = ost->enc_ctx; 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); if (ost->keep_pix_fmt) { @@ -335,8 +302,7 @@ static const char *choose_pix_fmts(OutputFilter *ofilter, AVBPrint *bprint) return av_get_pix_fmt_name(ost->enc_ctx->pix_fmt); } if (ost->enc_ctx->pix_fmt != AV_PIX_FMT_NONE) { - return av_get_pix_fmt_name(choose_pixel_fmt(enc->codec, enc->pix_fmt, - ost->enc_ctx->strict_std_compliance)); + return av_get_pix_fmt_name(enc->pix_fmt); } else if (enc->codec->pix_fmts) { const enum AVPixelFormat *p; diff --git a/fftools/ffmpeg_mux_init.c b/fftools/ffmpeg_mux_init.c index eafb8be8bd6..f7f240c721d 100644 --- a/fftools/ffmpeg_mux_init.c +++ b/fftools/ffmpeg_mux_init.c @@ -503,6 +503,32 @@ static int fmt_in_list(const int *formats, int format) return 0; } +static enum AVPixelFormat +choose_pixel_fmt(const AVCodec *codec, enum AVPixelFormat target) +{ + const enum AVPixelFormat *p = codec->pix_fmts; + const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(target); + //FIXME: This should check for AV_PIX_FMT_FLAG_ALPHA after PAL8 pixel format without alpha is implemented + int has_alpha = desc ? desc->nb_components % 2 == 0 : 0; + enum AVPixelFormat best= AV_PIX_FMT_NONE; + + for (; *p != AV_PIX_FMT_NONE; p++) { + best = av_find_best_pix_fmt_of_2(best, *p, target, has_alpha, NULL); + if (*p == target) + break; + } + if (*p == AV_PIX_FMT_NONE) { + if (target != AV_PIX_FMT_NONE) + av_log(NULL, AV_LOG_WARNING, + "Incompatible pixel format '%s' for codec '%s', auto-selecting format '%s'\n", + av_get_pix_fmt_name(target), + codec->name, + av_get_pix_fmt_name(best)); + return best; + } + return target; +} + static enum AVPixelFormat pix_fmt_parse(OutputStream *ost, const char *name) { const enum AVPixelFormat *fmts = ost->enc_ctx->codec->pix_fmts; @@ -540,6 +566,9 @@ static enum AVPixelFormat pix_fmt_parse(OutputStream *ost, const char *name) } } + if (fmts && !fmt_in_list(fmts, fmt)) + fmt = choose_pixel_fmt(ost->enc_ctx->codec, fmt); + return fmt; } From 45035154be908f969be1e3340225e71ec6ea6942 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Thu, 6 Jul 2023 18:56:40 +0200 Subject: [PATCH 1925/2172] tests/fate: fix mismatches between requested and actually used pixel formats --- tests/fate/fits.mak | 6 +++--- tests/fate/lavf-video.mak | 2 +- tests/fate/vcodec.mak | 4 ++-- tests/ref/fate/{fitsdec-gbrap16le => fitsdec-gbrap16be} | 4 ++-- tests/ref/fate/{fitsdec-gbrp16 => fitsdec-gbrp16be} | 4 ++-- tests/ref/lavf/gif | 2 +- 6 files changed, 11 insertions(+), 11 deletions(-) rename tests/ref/fate/{fitsdec-gbrap16le => fitsdec-gbrap16be} (79%) rename tests/ref/fate/{fitsdec-gbrp16 => fitsdec-gbrp16be} (79%) diff --git a/tests/fate/fits.mak b/tests/fate/fits.mak index b9e99d97ee1..d85946bc1a2 100644 --- a/tests/fate/fits.mak +++ b/tests/fate/fits.mak @@ -8,8 +8,8 @@ tests/data/fits-multi.fits: ffmpeg$(PROGSSUF)$(EXESUF) | tests/data # TODO: Use an actual 64bit input file and fix the gbrp16 test on big-endian fits-png-map-gray := gray8 fits-png-map-gbrp := rgb24 -fits-png-map-gbrp16 := rgb48 -fits-png-map-gbrap16le := rgba64 +fits-png-map-gbrp16be := rgb48 +fits-png-map-gbrap16be := rgba64 FATE_FITS_DEC-$(call FRAMECRC, FITS, FITS, SCALE_FILTER) += fate-fitsdec-ext_data_min_max fate-fitsdec-ext_data_min_max: CMD = framecrc -i $(TARGET_SAMPLES)/fits/x0cj010ct_d0h.fit -pix_fmt gray16le -vf scale @@ -30,7 +30,7 @@ fate-fitsdec-multi: CMD = framecrc -i $(TARGET_PATH)/tests/data/fits-multi.fits fate-fitsdec%: PIXFMT = $(word 3, $(subst -, ,$(@))) fate-fitsdec%: CMD = transcode image2 $(TARGET_SAMPLES)/png1/lena-$(fits-png-map-$(PIXFMT)).png fits "-vf scale -pix_fmt $(PIXFMT)" -FATE_FITS_DEC_PIXFMT = gray gbrp gbrp16 gbrap16le +FATE_FITS_DEC_PIXFMT = gray gbrp gbrp16be gbrap16be FATE_FITS_DEC-$(call TRANSCODE, FITS, FITS, IMAGE2_DEMUXER PNG_DECODER SCALE_FILTER) += $(FATE_FITS_DEC_PIXFMT:%=fate-fitsdec-%) FATE_FITS += $(FATE_FITS_DEC-yes) diff --git a/tests/fate/lavf-video.mak b/tests/fate/lavf-video.mak index e73f8f203b7..da3b114bc8b 100644 --- a/tests/fate/lavf-video.mak +++ b/tests/fate/lavf-video.mak @@ -27,7 +27,7 @@ fate-lavf-gbrp.fits: CMD = lavf_video "-pix_fmt gbrp" fate-lavf-gbrap.fits: CMD = lavf_video "-pix_fmt gbrap" fate-lavf-gbrp16be.fits: CMD = lavf_video "-pix_fmt gbrp16be" fate-lavf-gbrap16be.fits: CMD = lavf_video "-pix_fmt gbrap16be" -fate-lavf-gif: CMD = lavf_video "-pix_fmt rgb24" +fate-lavf-gif: CMD = lavf_video "-pix_fmt rgb8" FATE_AVCONV += $(FATE_LAVF_VIDEO) fate-lavf-video fate-lavf: $(FATE_LAVF_VIDEO) diff --git a/tests/fate/vcodec.mak b/tests/fate/vcodec.mak index 2839e54de84..e32d28c556f 100644 --- a/tests/fate/vcodec.mak +++ b/tests/fate/vcodec.mak @@ -210,9 +210,9 @@ fate-vsynth%-h263p: ENCOPTS = -qscale 2 -flags +aic -umv 1 -aiv 1 - FATE_VCODEC_SCALE-$(call ENCDEC, HUFFYUV, AVI) += huffyuv huffyuvbgr24 huffyuvbgra fate-vsynth%-huffyuv: ENCOPTS = -c:v huffyuv -pix_fmt yuv422p -sws_flags neighbor fate-vsynth%-huffyuv: DECOPTS = -sws_flags neighbor -fate-vsynth%-huffyuvbgr24: ENCOPTS = -c:v huffyuv -pix_fmt bgr24 -sws_flags neighbor +fate-vsynth%-huffyuvbgr24: ENCOPTS = -c:v huffyuv -pix_fmt rgb24 -sws_flags neighbor fate-vsynth%-huffyuvbgr24: DECOPTS = -sws_flags neighbor -fate-vsynth%-huffyuvbgra: ENCOPTS = -c:v huffyuv -pix_fmt bgr32 -sws_flags neighbor +fate-vsynth%-huffyuvbgra: ENCOPTS = -c:v huffyuv -pix_fmt rgb32 -sws_flags neighbor fate-vsynth%-huffyuvbgra: DECOPTS = -sws_flags neighbor FATE_VCODEC_SCALE-$(call ENCDEC, JPEGLS, AVI) += jpegls diff --git a/tests/ref/fate/fitsdec-gbrap16le b/tests/ref/fate/fitsdec-gbrap16be similarity index 79% rename from tests/ref/fate/fitsdec-gbrap16le rename to tests/ref/fate/fitsdec-gbrap16be index 53ef980b133..1174a0f1d82 100644 --- a/tests/ref/fate/fitsdec-gbrap16le +++ b/tests/ref/fate/fitsdec-gbrap16be @@ -1,5 +1,5 @@ -64526d8da12d1fa07ceea5725647076f *tests/data/fate/fitsdec-gbrap16le.fits -135360 tests/data/fate/fitsdec-gbrap16le.fits +64526d8da12d1fa07ceea5725647076f *tests/data/fate/fitsdec-gbrap16be.fits +135360 tests/data/fate/fitsdec-gbrap16be.fits #tb 0: 1/1 #media_type 0: video #codec_id 0: rawvideo diff --git a/tests/ref/fate/fitsdec-gbrp16 b/tests/ref/fate/fitsdec-gbrp16be similarity index 79% rename from tests/ref/fate/fitsdec-gbrp16 rename to tests/ref/fate/fitsdec-gbrp16be index 9250690e9bc..ff4ca9e65c9 100644 --- a/tests/ref/fate/fitsdec-gbrp16 +++ b/tests/ref/fate/fitsdec-gbrp16be @@ -1,5 +1,5 @@ -2078208c93ba417d3fe150ba42bf5a30 *tests/data/fate/fitsdec-gbrp16.fits -103680 tests/data/fate/fitsdec-gbrp16.fits +2078208c93ba417d3fe150ba42bf5a30 *tests/data/fate/fitsdec-gbrp16be.fits +103680 tests/data/fate/fitsdec-gbrp16be.fits #tb 0: 1/1 #media_type 0: video #codec_id 0: rawvideo diff --git a/tests/ref/lavf/gif b/tests/ref/lavf/gif index fc94b9df3dc..7f353df2860 100644 --- a/tests/ref/lavf/gif +++ b/tests/ref/lavf/gif @@ -1,3 +1,3 @@ e35f5ea283bbcb249818e0078ec72664 *tests/data/lavf/lavf.gif 2011766 tests/data/lavf/lavf.gif -tests/data/lavf/lavf.gif CRC=0x2429faff +tests/data/lavf/lavf.gif CRC=0x37f4d323 From 9d44eb8af5392ee208ca22e5997c27ab3aa2afc2 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Thu, 6 Jul 2023 19:19:51 +0200 Subject: [PATCH 1926/2172] fftools/ffmpeg_filter: stop accessing encoder from pixfmt selection ffmpeg CLI pixel format selection for filtering currently special-cases MJPEG encoding, where it will restrict the supported list of pixel formats depending on the value of the -strict option. In order to get that value it will apply it from the options dict into the encoder context, which is a highly invasive action even now, and would become a race once encoding is moved to its own thread. The ugliness of this code can be much reduced by moving the special handling of MJPEG into ofilter_bind_ost(), which is called from encoder init and is thus synchronized with it. There is also no need to write anything to the encoder context, we can evaluate the option into our stack variable. There is also no need to access AVCodec at all during pixel format selection, as the pixel formats array is already stored in OutputFilterPriv. --- fftools/ffmpeg_filter.c | 68 ++++++++++++++++++++--------------------- 1 file changed, 34 insertions(+), 34 deletions(-) diff --git a/fftools/ffmpeg_filter.c b/fftools/ffmpeg_filter.c index 71595513f3f..e14b8f0f3ce 100644 --- a/fftools/ffmpeg_filter.c +++ b/fftools/ffmpeg_filter.c @@ -270,46 +270,22 @@ static void sub2video_update(InputFilterPriv *ifp, int64_t heartbeat_pts, ifp->sub2video.initialize = 0; } -// FIXME: YUV420P etc. are actually supported with full color range, -// yet the latter information isn't available here. -static const enum AVPixelFormat *get_compliance_normal_pix_fmts(const AVCodec *codec, const enum AVPixelFormat default_formats[]) -{ - static const enum AVPixelFormat mjpeg_formats[] = - { AV_PIX_FMT_YUVJ420P, AV_PIX_FMT_YUVJ422P, AV_PIX_FMT_YUVJ444P, - AV_PIX_FMT_NONE }; - - if (!strcmp(codec->name, "mjpeg")) { - return mjpeg_formats; - } else { - return default_formats; - } -} - /* 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) { + OutputFilterPriv *ofp = ofp_from_ofilter(ofilter); OutputStream *ost = ofilter->ost; - AVCodecContext *enc = ost->enc_ctx; - const AVDictionaryEntry *strict_dict = av_dict_get(ost->encoder_opts, "strict", NULL, 0); - if (strict_dict) - av_opt_set(ost->enc_ctx, "strict", strict_dict->value, 0); - - if (ost->keep_pix_fmt) { - if (ost->enc_ctx->pix_fmt == AV_PIX_FMT_NONE) - return NULL; - return av_get_pix_fmt_name(ost->enc_ctx->pix_fmt); - } - if (ost->enc_ctx->pix_fmt != AV_PIX_FMT_NONE) { - return av_get_pix_fmt_name(enc->pix_fmt); - } else if (enc->codec->pix_fmts) { - const enum AVPixelFormat *p; - - p = enc->codec->pix_fmts; - if (ost->enc_ctx->strict_std_compliance > FF_COMPLIANCE_UNOFFICIAL) { - p = get_compliance_normal_pix_fmts(enc->codec, p); - } + + if (ost->keep_pix_fmt) { + return ofp->format == AV_PIX_FMT_NONE ? NULL : + av_get_pix_fmt_name(ofp->format); + } + if (ofp->format != AV_PIX_FMT_NONE) { + return av_get_pix_fmt_name(ofp->format); + } else if (ofp->formats) { + const enum AVPixelFormat *p = ofp->formats; for (; *p != AV_PIX_FMT_NONE; p++) { const char *name = av_get_pix_fmt_name(*p); @@ -668,6 +644,30 @@ void ofilter_bind_ost(OutputFilter *ofilter, OutputStream *ost) ofp->format = ost->enc_ctx->pix_fmt; } else { ofp->formats = c->pix_fmts; + + // MJPEG encoder exports a full list of supported pixel formats, + // but the full-range ones are experimental-only. + // Restrict the auto-conversion list unless -strict experimental + // has been specified. + if (!strcmp(c->name, "mjpeg")) { + // FIXME: YUV420P etc. are actually supported with full color range, + // yet the latter information isn't available here. + static const enum AVPixelFormat mjpeg_formats[] = + { AV_PIX_FMT_YUVJ420P, AV_PIX_FMT_YUVJ422P, AV_PIX_FMT_YUVJ444P, + AV_PIX_FMT_NONE }; + + const AVDictionaryEntry *strict = av_dict_get(ost->encoder_opts, "strict", NULL, 0); + int strict_val = ost->enc_ctx->strict_std_compliance; + + if (strict) { + const AVOption *o = av_opt_find(ost->enc_ctx, strict->key, NULL, 0, 0); + av_assert0(o); + av_opt_eval_int(ost->enc_ctx, o, strict->value, &strict_val); + } + + if (strict_val > FF_COMPLIANCE_UNOFFICIAL) + ofp->formats = mjpeg_formats; + } } fgp->disable_conversions |= ost->keep_pix_fmt; From 3a89e6d35261a261bae10fa856ea512385df6076 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Thu, 8 Jun 2023 13:28:33 +0200 Subject: [PATCH 1927/2172] fftools/ffmpeg_filter: restrict reap_filters() to a single filtergraph This is more natural, as all except one of its callers require processing only one filtergraph. --- fftools/ffmpeg.c | 10 +++++++++- fftools/ffmpeg.h | 4 ++-- fftools/ffmpeg_filter.c | 33 ++++++++++++++++----------------- 3 files changed, 27 insertions(+), 20 deletions(-) diff --git a/fftools/ffmpeg.c b/fftools/ffmpeg.c index cbeddab125d..27c4e7ef26d 100644 --- a/fftools/ffmpeg.c +++ b/fftools/ffmpeg.c @@ -1171,7 +1171,15 @@ static int transcode_step(OutputStream *ost) if (ret < 0) return ret == AVERROR_EOF ? 0 : ret; - return reap_filters(0); + // process_input() above might have caused output to become available + // in multiple filtergraphs, so we process all of them + for (int i = 0; i < nb_filtergraphs; i++) { + ret = reap_filters(filtergraphs[i], 0); + if (ret < 0) + return ret; + } + + return 0; } /* diff --git a/fftools/ffmpeg.h b/fftools/ffmpeg.h index f45ddf33b2f..1b799832add 100644 --- a/fftools/ffmpeg.h +++ b/fftools/ffmpeg.h @@ -765,12 +765,12 @@ void fg_free(FilterGraph **pfg); int fg_transcode_step(FilterGraph *graph, InputStream **best_ist); /** - * Get and encode new output from any of the filtergraphs, without causing + * Get and encode new output from specified filtergraph, without causing * activity. * * @return 0 for success, <0 for severe errors */ -int reap_filters(int flush); +int reap_filters(FilterGraph *fg, int flush); int ffmpeg_parse_options(int argc, char **argv); diff --git a/fftools/ffmpeg_filter.c b/fftools/ffmpeg_filter.c index e14b8f0f3ce..49e0800e6e3 100644 --- a/fftools/ffmpeg_filter.c +++ b/fftools/ffmpeg_filter.c @@ -1695,23 +1695,22 @@ int filtergraph_is_simple(const FilterGraph *fg) return fgp->is_simple; } -int reap_filters(int flush) +int reap_filters(FilterGraph *fg, int flush) { - /* Reap all buffers present in the buffer sinks */ - for (OutputStream *ost = ost_iter(NULL); ost; ost = ost_iter(ost)) { - OutputFilterPriv *ofp; - FilterGraphPriv *fgp; - AVFrame *filtered_frame; - AVFilterContext *filter; - int ret = 0; + FilterGraphPriv *fgp = fgp_from_fg(fg); + AVFrame *filtered_frame = fgp->frame; - if (!ost->filter || !ost->filter->graph->graph) - continue; - fgp = fgp_from_fg(ost->filter->graph); - ofp = ofp_from_ofilter(ost->filter); - filter = ofp->filter; + if (!fg->graph) + return 0; + + /* Reap all buffers present in the buffer sinks */ + for (int i = 0; i < fg->nb_outputs; i++) { + OutputFilter *ofilter = fg->outputs[i]; + OutputStream *ost = ofilter->ost; + OutputFilterPriv *ofp = ofp_from_ofilter(ofilter); + AVFilterContext *filter = ofp->filter; - filtered_frame = fgp->frame; + int ret = 0; while (1) { FrameData *fd; @@ -1931,7 +1930,7 @@ int ifilter_send_frame(InputFilter *ifilter, AVFrame *frame, int keep_reference) return ret; } - ret = reap_filters(0); + ret = reap_filters(fg, 0); if (ret < 0 && ret != AVERROR_EOF) { av_log(fg, AV_LOG_ERROR, "Error while filtering: %s\n", av_err2str(ret)); return ret; @@ -2000,10 +1999,10 @@ int fg_transcode_step(FilterGraph *graph, InputStream **best_ist) *best_ist = NULL; ret = avfilter_graph_request_oldest(graph->graph); if (ret >= 0) - return reap_filters(0); + return reap_filters(graph, 0); if (ret == AVERROR_EOF) { - reap_filters(1); + reap_filters(graph, 1); for (int i = 0; i < graph->nb_outputs; i++) { OutputFilter *ofilter = graph->outputs[i]; OutputFilterPriv *ofp = ofp_from_ofilter(ofilter); From c4b074676a9fff3f072ae4c7e795cf71e010849d Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Fri, 14 Jul 2023 11:42:02 +0200 Subject: [PATCH 1928/2172] fftools/ffmpeg_mux_init: avoid invalid memory access in set_dispositions() This function assumes AVMEDIA_* are always positive, while in fact it can also handle AVMEDIA_TYPE_UNKNOWN, which is -1. --- fftools/ffmpeg_mux_init.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/fftools/ffmpeg_mux_init.c b/fftools/ffmpeg_mux_init.c index f7f240c721d..d6ae154ad93 100644 --- a/fftools/ffmpeg_mux_init.c +++ b/fftools/ffmpeg_mux_init.c @@ -2285,8 +2285,9 @@ static int set_dispositions(Muxer *mux, const OptionsContext *o) OutputFile *of = &mux->of; AVFormatContext *ctx = mux->fc; - int nb_streams[AVMEDIA_TYPE_NB] = { 0 }; - int have_default[AVMEDIA_TYPE_NB] = { 0 }; + // indexed by type+1, because AVMEDIA_TYPE_UNKNOWN=-1 + int nb_streams[AVMEDIA_TYPE_NB + 1] = { 0 }; + int have_default[AVMEDIA_TYPE_NB + 1] = { 0 }; int have_manual = 0; int ret = 0; @@ -2300,7 +2301,7 @@ static int set_dispositions(Muxer *mux, const OptionsContext *o) for (int i = 0; i < ctx->nb_streams; i++) { OutputStream *ost = of->streams[i]; - nb_streams[ost->type]++; + nb_streams[ost->type + 1]++; MATCH_PER_STREAM_OPT(disposition, str, dispositions[i], ctx, ost->st); @@ -2310,7 +2311,7 @@ static int set_dispositions(Muxer *mux, const OptionsContext *o) ost->st->disposition = ost->ist->st->disposition; if (ost->st->disposition & AV_DISPOSITION_DEFAULT) - have_default[ost->type] = 1; + have_default[ost->type + 1] = 1; } } @@ -2335,12 +2336,12 @@ static int set_dispositions(Muxer *mux, const OptionsContext *o) OutputStream *ost = of->streams[i]; enum AVMediaType type = ost->type; - if (nb_streams[type] < 2 || have_default[type] || + if (nb_streams[type + 1] < 2 || have_default[type + 1] || ost->st->disposition & AV_DISPOSITION_ATTACHED_PIC) continue; ost->st->disposition |= AV_DISPOSITION_DEFAULT; - have_default[type] = 1; + have_default[type + 1] = 1; } } From 80a64800eab896b1103094a519a35a9585f25f4b Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Thu, 13 Jul 2023 13:34:32 +0200 Subject: [PATCH 1929/2172] fftools/ffmpeg_enc: return errors from enc_frame() instead of aborting --- fftools/ffmpeg.h | 2 +- fftools/ffmpeg_enc.c | 6 ++++-- fftools/ffmpeg_filter.c | 12 +++++++++--- 3 files changed, 14 insertions(+), 6 deletions(-) diff --git a/fftools/ffmpeg.h b/fftools/ffmpeg.h index 1b799832add..89c87cf1c47 100644 --- a/fftools/ffmpeg.h +++ b/fftools/ffmpeg.h @@ -814,7 +814,7 @@ void enc_free(Encoder **penc); int enc_open(OutputStream *ost, AVFrame *frame); int enc_subtitle(OutputFile *of, OutputStream *ost, const AVSubtitle *sub); -void enc_frame(OutputStream *ost, AVFrame *frame); +int enc_frame(OutputStream *ost, AVFrame *frame); void enc_flush(void); /* diff --git a/fftools/ffmpeg_enc.c b/fftools/ffmpeg_enc.c index 8b750de4e57..5952fc42b7b 100644 --- a/fftools/ffmpeg_enc.c +++ b/fftools/ffmpeg_enc.c @@ -1129,17 +1129,19 @@ static void do_video_out(OutputFile *of, OutputStream *ost, AVFrame *frame) av_frame_move_ref(e->last_frame, frame); } -void enc_frame(OutputStream *ost, AVFrame *frame) +int enc_frame(OutputStream *ost, AVFrame *frame) { OutputFile *of = output_files[ost->file_index]; int ret; ret = enc_open(ost, frame); if (ret < 0) - exit_program(1); + return ret; if (ost->enc_ctx->codec_type == AVMEDIA_TYPE_VIDEO) do_video_out(of, ost, frame); else do_audio_out(of, ost, frame); + + return 0; } void enc_flush(void) diff --git a/fftools/ffmpeg_filter.c b/fftools/ffmpeg_filter.c index 49e0800e6e3..d373d8c0020 100644 --- a/fftools/ffmpeg_filter.c +++ b/fftools/ffmpeg_filter.c @@ -1722,8 +1722,11 @@ int reap_filters(FilterGraph *fg, int flush) av_log(fgp, AV_LOG_WARNING, "Error in av_buffersink_get_frame_flags(): %s\n", av_err2str(ret)); } else if (flush && ret == AVERROR_EOF && ofp->got_frame && - av_buffersink_get_type(filter) == AVMEDIA_TYPE_VIDEO) - enc_frame(ost, NULL); + av_buffersink_get_type(filter) == AVMEDIA_TYPE_VIDEO) { + ret = enc_frame(ost, NULL); + if (ret < 0) + return ret; + } break; } @@ -1759,8 +1762,11 @@ int reap_filters(FilterGraph *fg, int flush) if (ost->type == AVMEDIA_TYPE_VIDEO) fd->frame_rate_filter = av_buffersink_get_frame_rate(filter); - enc_frame(ost, filtered_frame); + ret = enc_frame(ost, filtered_frame); av_frame_unref(filtered_frame); + if (ret < 0) + return ret; + ofp->got_frame = 1; } } From aa1173feee791c35f1306df2bbd69917cb59aae8 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Thu, 13 Jul 2023 13:34:32 +0200 Subject: [PATCH 1930/2172] fftools/ffmpeg_enc: return errors from enc_open() instead of aborting --- fftools/ffmpeg_enc.c | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/fftools/ffmpeg_enc.c b/fftools/ffmpeg_enc.c index 5952fc42b7b..ec1b7fa3ae9 100644 --- a/fftools/ffmpeg_enc.c +++ b/fftools/ffmpeg_enc.c @@ -165,19 +165,19 @@ static int hw_device_setup_for_encode(OutputStream *ost, AVBufferRef *frames_ref return 0; } -static void set_encoder_id(OutputFile *of, OutputStream *ost) +static int set_encoder_id(OutputFile *of, OutputStream *ost) { const char *cname = ost->enc_ctx->codec->name; uint8_t *encoder_string; int encoder_string_len; if (av_dict_get(ost->st->metadata, "encoder", NULL, 0)) - return; + return 0; encoder_string_len = sizeof(LIBAVCODEC_IDENT) + strlen(cname) + 2; encoder_string = av_mallocz(encoder_string_len); if (!encoder_string) - report_and_exit(AVERROR(ENOMEM)); + return AVERROR(ENOMEM); if (!of->bitexact && !ost->bitexact) av_strlcpy(encoder_string, LIBAVCODEC_IDENT " ", encoder_string_len); @@ -186,6 +186,8 @@ static void set_encoder_id(OutputFile *of, OutputStream *ost) av_strlcat(encoder_string, cname, encoder_string_len); av_dict_set(&ost->st->metadata, "encoder", encoder_string, AV_DICT_DONT_STRDUP_VAL | AV_DICT_DONT_OVERWRITE); + + return 0; } int enc_open(OutputStream *ost, AVFrame *frame) @@ -211,7 +213,9 @@ int enc_open(OutputStream *ost, AVFrame *frame) return AVERROR(ENOMEM); } - set_encoder_id(output_files[ost->file_index], ost); + ret = set_encoder_id(output_files[ost->file_index], ost); + if (ret < 0) + return ret; if (ist) { dec_ctx = ist->dec_ctx; @@ -413,7 +417,7 @@ int enc_open(OutputStream *ost, AVFrame *frame) if (ret < 0) { av_log(ost, AV_LOG_FATAL, "Error initializing the output stream codec context.\n"); - exit_program(1); + return ret; } if (ost->enc_ctx->nb_coded_side_data) { From dde3de017088ab5bf7fb7920d3d8d4ba4e5dc290 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Thu, 13 Jul 2023 13:34:32 +0200 Subject: [PATCH 1931/2172] fftools/ffmpeg_enc: return errors from do_*_out() instead of aborting --- fftools/ffmpeg_enc.c | 29 ++++++++++++++--------------- 1 file changed, 14 insertions(+), 15 deletions(-) diff --git a/fftools/ffmpeg_enc.c b/fftools/ffmpeg_enc.c index ec1b7fa3ae9..384c6c0a886 100644 --- a/fftools/ffmpeg_enc.c +++ b/fftools/ffmpeg_enc.c @@ -835,8 +835,8 @@ static int submit_encode_frame(OutputFile *of, OutputStream *ost, } } -static void do_audio_out(OutputFile *of, OutputStream *ost, - AVFrame *frame) +static int do_audio_out(OutputFile *of, OutputStream *ost, + AVFrame *frame) { Encoder *e = ost->enc; AVCodecContext *enc = ost->enc_ctx; @@ -846,7 +846,7 @@ static void do_audio_out(OutputFile *of, OutputStream *ost, enc->ch_layout.nb_channels != frame->ch_layout.nb_channels) { av_log(ost, AV_LOG_ERROR, "Audio channel count changed and encoder does not support parameter changes\n"); - return; + return 0; } if (frame->pts == AV_NOPTS_VALUE) @@ -862,13 +862,12 @@ static void do_audio_out(OutputFile *of, OutputStream *ost, enc->time_base); if (!check_recording_time(ost, frame->pts, frame->time_base)) - return; + return 0; e->next_pts = frame->pts + frame->nb_samples; ret = submit_encode_frame(of, ost, frame); - if (ret < 0 && ret != AVERROR_EOF) - exit_program(1); + return (ret < 0 && ret != AVERROR_EOF) ? ret : 0; } static double adjust_frame_pts_to_encoder_tb(OutputFile *of, OutputStream *ost, @@ -1055,7 +1054,7 @@ static enum AVPictureType forced_kf_apply(void *logctx, KeyframeForceCtx *kf, } /* May modify/reset frame */ -static void do_video_out(OutputFile *of, OutputStream *ost, AVFrame *frame) +static int do_video_out(OutputFile *of, OutputStream *ost, AVFrame *frame) { int ret; Encoder *e = ost->enc; @@ -1086,7 +1085,7 @@ static void do_video_out(OutputFile *of, OutputStream *ost, AVFrame *frame) if (nb_frames > dts_error_threshold * 30) { av_log(ost, AV_LOG_ERROR, "%"PRId64" frame duplication too large, skipping\n", nb_frames - 1); ost->nb_frames_drop++; - return; + return 0; } ost->nb_frames_dup += nb_frames - (nb_frames_prev && ost->last_dropped) - (nb_frames > nb_frames_prev); av_log(ost, AV_LOG_VERBOSE, "*** %"PRId64" dup!\n", nb_frames - 1); @@ -1108,12 +1107,12 @@ static void do_video_out(OutputFile *of, OutputStream *ost, AVFrame *frame) in_picture = frame; if (!in_picture) - return; + return 0; in_picture->pts = e->next_pts; if (!check_recording_time(ost, in_picture->pts, ost->enc_ctx->time_base)) - return; + return 0; in_picture->quality = enc->global_quality; in_picture->pict_type = forced_kf_apply(ost, &ost->kf, enc->time_base, in_picture, i); @@ -1122,7 +1121,7 @@ static void do_video_out(OutputFile *of, OutputStream *ost, AVFrame *frame) if (ret == AVERROR_EOF) break; else if (ret < 0) - exit_program(1); + return ret; e->next_pts++; e->vsync_frame_number++; @@ -1131,6 +1130,8 @@ static void do_video_out(OutputFile *of, OutputStream *ost, AVFrame *frame) av_frame_unref(e->last_frame); if (frame) av_frame_move_ref(e->last_frame, frame); + + return 0; } int enc_frame(OutputStream *ost, AVFrame *frame) @@ -1142,10 +1143,8 @@ int enc_frame(OutputStream *ost, AVFrame *frame) if (ret < 0) return ret; - if (ost->enc_ctx->codec_type == AVMEDIA_TYPE_VIDEO) do_video_out(of, ost, frame); - else do_audio_out(of, ost, frame); - - return 0; + return ost->enc_ctx->codec_type == AVMEDIA_TYPE_VIDEO ? + do_video_out(of, ost, frame) : do_audio_out(of, ost, frame); } void enc_flush(void) From 43bcf631d0e4240c5eb138d97b8685290903c3ed Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Thu, 13 Jul 2023 13:34:32 +0200 Subject: [PATCH 1932/2172] fftools/ffmpeg_enc: return errors from enc_flush() instead of aborting --- fftools/ffmpeg.c | 2 +- fftools/ffmpeg.h | 2 +- fftools/ffmpeg_enc.c | 6 ++++-- 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/fftools/ffmpeg.c b/fftools/ffmpeg.c index 27c4e7ef26d..926fdea23a9 100644 --- a/fftools/ffmpeg.c +++ b/fftools/ffmpeg.c @@ -1250,7 +1250,7 @@ static int transcode(int *err_rate_exceeded) } else if (err_rate) av_log(ist, AV_LOG_VERBOSE, "Decode error rate %g\n", err_rate); } - enc_flush(); + ret = err_merge(ret, enc_flush()); term_exit(); diff --git a/fftools/ffmpeg.h b/fftools/ffmpeg.h index 89c87cf1c47..506deaa0f30 100644 --- a/fftools/ffmpeg.h +++ b/fftools/ffmpeg.h @@ -815,7 +815,7 @@ void enc_free(Encoder **penc); int enc_open(OutputStream *ost, AVFrame *frame); int enc_subtitle(OutputFile *of, OutputStream *ost, const AVSubtitle *sub); int enc_frame(OutputStream *ost, AVFrame *frame); -void enc_flush(void); +int enc_flush(void); /* * Initialize muxing state for the given stream, should be called diff --git a/fftools/ffmpeg_enc.c b/fftools/ffmpeg_enc.c index 384c6c0a886..90ec20ee6b6 100644 --- a/fftools/ffmpeg_enc.c +++ b/fftools/ffmpeg_enc.c @@ -1147,7 +1147,7 @@ int enc_frame(OutputStream *ost, AVFrame *frame) do_video_out(of, ost, frame) : do_audio_out(of, ost, frame); } -void enc_flush(void) +int enc_flush(void) { int ret; @@ -1168,6 +1168,8 @@ void enc_flush(void) ret = submit_encode_frame(of, ost, NULL); if (ret != AVERROR_EOF) - exit_program(1); + return ret; } + + return 0; } From 2b4afe816916192148875fe4d9087fd2c03d05a6 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Thu, 13 Jul 2023 13:34:32 +0200 Subject: [PATCH 1933/2172] fftools/ffmpeg_enc: return errors from encode_frame() instead of aborting --- fftools/ffmpeg_enc.c | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/fftools/ffmpeg_enc.c b/fftools/ffmpeg_enc.c index 90ec20ee6b6..0edbe191362 100644 --- a/fftools/ffmpeg_enc.c +++ b/fftools/ffmpeg_enc.c @@ -637,7 +637,7 @@ static inline double psnr(double d) return -10.0 * log10(d); } -static void update_video_stats(OutputStream *ost, const AVPacket *pkt, int write_vstats) +static int update_video_stats(OutputStream *ost, const AVPacket *pkt, int write_vstats) { Encoder *e = ost->enc; const uint8_t *sd = av_packet_get_side_data(pkt, AV_PKT_DATA_QUALITY_STATS, @@ -659,14 +659,14 @@ static void update_video_stats(OutputStream *ost, const AVPacket *pkt, int write } if (!write_vstats) - return; + return 0; /* this is executed just the first time update_video_stats is called */ if (!vstats_file) { vstats_file = fopen(vstats_filename, "w"); if (!vstats_file) { perror("fopen"); - exit_program(1); + return AVERROR(errno); } } @@ -693,6 +693,8 @@ static void update_video_stats(OutputStream *ost, const AVPacket *pkt, int write fprintf(vstats_file, "s_size= %8.0fkB time= %0.3f br= %7.1fkbits/s avg_br= %7.1fkbits/s ", (double)e->data_size / 1024, ti1, bitrate, avg_bitrate); fprintf(vstats_file, "type= %c\n", av_get_picture_type_char(pict_type)); + + return 0; } static int encode_frame(OutputFile *of, OutputStream *ost, AVFrame *frame) @@ -734,6 +736,8 @@ static int encode_frame(OutputFile *of, OutputStream *ost, AVFrame *frame) } while (1) { + av_packet_unref(pkt); + ret = avcodec_receive_packet(enc, pkt); update_benchmark("%s_%s %d.%d", action, type_desc, ost->file_index, ost->index); @@ -755,8 +759,12 @@ static int encode_frame(OutputFile *of, OutputStream *ost, AVFrame *frame) return ret; } - if (enc->codec_type == AVMEDIA_TYPE_VIDEO) - update_video_stats(ost, pkt, !!vstats_filename); + if (enc->codec_type == AVMEDIA_TYPE_VIDEO) { + ret = update_video_stats(ost, pkt, !!vstats_filename); + if (ret < 0) + return ret; + } + if (ost->enc_stats_post.io) enc_stats_write(ost, &ost->enc_stats_post, NULL, pkt, e->packets_encoded); @@ -775,7 +783,7 @@ static int encode_frame(OutputFile *of, OutputStream *ost, AVFrame *frame) av_log(NULL, AV_LOG_ERROR, "Subtitle heartbeat logic failed in %s! (%s)\n", __func__, av_err2str(ret)); - exit_program(1); + return ret; } e->data_size += pkt->size; From e0f4259689357182e8d555d093e8843f7bf19e5f Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Thu, 13 Jul 2023 13:34:32 +0200 Subject: [PATCH 1934/2172] fftools/ffmpeg_mux: return errors from of_output_packet() instead of aborting --- fftools/ffmpeg.c | 4 +++- fftools/ffmpeg.h | 2 +- fftools/ffmpeg_enc.c | 12 ++++++++---- fftools/ffmpeg_mux.c | 20 +++++++++----------- 4 files changed, 21 insertions(+), 17 deletions(-) diff --git a/fftools/ffmpeg.c b/fftools/ffmpeg.c index 926fdea23a9..ddb011741a1 100644 --- a/fftools/ffmpeg.c +++ b/fftools/ffmpeg.c @@ -1120,7 +1120,9 @@ static int process_input(int file_index) OutputStream *ost = ist->outputs[oidx]; OutputFile *of = output_files[ost->file_index]; close_output_stream(ost); - of_output_packet(of, ost, NULL); + ret = of_output_packet(of, ost, NULL); + if (ret < 0) + return ret; } } diff --git a/fftools/ffmpeg.h b/fftools/ffmpeg.h index 506deaa0f30..36e8867fd5b 100644 --- a/fftools/ffmpeg.h +++ b/fftools/ffmpeg.h @@ -830,7 +830,7 @@ void of_close(OutputFile **pof); void of_enc_stats_close(void); -void of_output_packet(OutputFile *of, OutputStream *ost, AVPacket *pkt); +int of_output_packet(OutputFile *of, OutputStream *ost, AVPacket *pkt); /** * @param dts predicted packet dts in AV_TIME_BASE_Q diff --git a/fftools/ffmpeg_enc.c b/fftools/ffmpeg_enc.c index 0edbe191362..d842bc7df47 100644 --- a/fftools/ffmpeg_enc.c +++ b/fftools/ffmpeg_enc.c @@ -559,7 +559,9 @@ int enc_subtitle(OutputFile *of, OutputStream *ost, const AVSubtitle *sub) } pkt->dts = pkt->pts; - of_output_packet(of, ost, pkt); + ret = of_output_packet(of, ost, pkt); + if (ret < 0) + return ret; } return 0; @@ -752,8 +754,8 @@ static int encode_frame(OutputFile *of, OutputStream *ost, AVFrame *frame) av_assert0(frame); // should never happen during flushing return 0; } else if (ret == AVERROR_EOF) { - of_output_packet(of, ost, NULL); - return ret; + ret = of_output_packet(of, ost, NULL); + return ret < 0 ? ret : AVERROR_EOF; } else if (ret < 0) { av_log(ost, AV_LOG_ERROR, "%s encoding failed\n", type_desc); return ret; @@ -790,7 +792,9 @@ static int encode_frame(OutputFile *of, OutputStream *ost, AVFrame *frame) e->packets_encoded++; - of_output_packet(of, ost, pkt); + ret = of_output_packet(of, ost, pkt); + if (ret < 0) + return ret; } av_assert0(0); diff --git a/fftools/ffmpeg_mux.c b/fftools/ffmpeg_mux.c index a6cc8244963..24cdf00469b 100644 --- a/fftools/ffmpeg_mux.c +++ b/fftools/ffmpeg_mux.c @@ -330,7 +330,7 @@ static int submit_packet(Muxer *mux, AVPacket *pkt, OutputStream *ost) return 0; } -void of_output_packet(OutputFile *of, OutputStream *ost, AVPacket *pkt) +int of_output_packet(OutputFile *of, OutputStream *ost, AVPacket *pkt) { Muxer *mux = mux_from_of(of); MuxStream *ms = ms_from_ost(ost); @@ -359,7 +359,7 @@ void of_output_packet(OutputFile *of, OutputStream *ost, AVPacket *pkt) while (!bsf_eof) { ret = av_bsf_receive_packet(ms->bsf_ctx, ms->bsf_pkt); if (ret == AVERROR(EAGAIN)) - return; + return 0; else if (ret == AVERROR_EOF) bsf_eof = 1; else if (ret < 0) { @@ -377,16 +377,14 @@ void of_output_packet(OutputFile *of, OutputStream *ost, AVPacket *pkt) goto mux_fail; } - return; + return 0; mux_fail: err_msg = "submitting a packet to the muxer"; fail: av_log(ost, AV_LOG_ERROR, "Error %s\n", err_msg); - if (exit_on_error) - exit_program(1); - + return exit_on_error ? ret : 0; } int of_streamcopy(OutputStream *ost, const AVPacket *pkt, int64_t dts) @@ -405,10 +403,8 @@ int of_streamcopy(OutputStream *ost, const AVPacket *pkt, int64_t dts) pkt = NULL; // EOF: flush output bitstream filters. - if (!pkt) { - of_output_packet(of, ost, NULL); - return 0; - } + if (!pkt) + return of_output_packet(of, ost, NULL); if (!ms->streamcopy_started && !(pkt->flags & AV_PKT_FLAG_KEY) && !ms->copy_initial_nonkeyframes) @@ -461,7 +457,9 @@ int of_streamcopy(OutputStream *ost, const AVPacket *pkt, int64_t dts) } } - of_output_packet(of, ost, opkt); + ret = of_output_packet(of, ost, opkt); + if (ret < 0) + return ret; ms->streamcopy_started = 1; From 518b49a735ff0b7df0a5970526a81f8590a7a242 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Thu, 13 Jul 2023 15:11:07 +0200 Subject: [PATCH 1935/2172] fftools/ffmpeg_dec: return error codes from dec_packet() instead of aborting --- fftools/ffmpeg.c | 5 ++++- fftools/ffmpeg_dec.c | 4 ++-- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/fftools/ffmpeg.c b/fftools/ffmpeg.c index ddb011741a1..b4ea52ac1da 100644 --- a/fftools/ffmpeg.c +++ b/fftools/ffmpeg.c @@ -814,8 +814,11 @@ static int process_input_packet(InputStream *ist, const AVPacket *pkt, int no_eo int eof_reached = 0; int duration_exceeded; - if (ist->decoding_needed) + if (ist->decoding_needed) { ret = dec_packet(ist, pkt, no_eof); + if (ret < 0 && ret != AVERROR_EOF) + return ret; + } if (ret == AVERROR_EOF || (!pkt && !ist->decoding_needed)) eof_reached = 1; diff --git a/fftools/ffmpeg_dec.c b/fftools/ffmpeg_dec.c index 5c1b8888e95..f5f764b6fa9 100644 --- a/fftools/ffmpeg_dec.c +++ b/fftools/ffmpeg_dec.c @@ -816,7 +816,7 @@ int dec_packet(InputStream *ist, const AVPacket *pkt, int no_eof) } // non-EOF errors here are all fatal if (ret < 0 && ret != AVERROR_EOF) - report_and_exit(ret); + return ret; // signal EOF to our downstreams if (ist->dec->type == AVMEDIA_TYPE_SUBTITLE) @@ -825,7 +825,7 @@ int dec_packet(InputStream *ist, const AVPacket *pkt, int no_eof) ret = send_filter_eof(ist); if (ret < 0) { av_log(NULL, AV_LOG_FATAL, "Error marking filters as finished\n"); - exit_program(1); + return ret; } } From 6298dd683b8542dd0c6b5eefabdcd8a7c7c54399 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Thu, 13 Jul 2023 15:14:42 +0200 Subject: [PATCH 1936/2172] fftools/ffmpeg_dec: drop redundant handling of AVERROR_EXPERIMENTAL Normal error handling does the job just as well. --- fftools/ffmpeg_dec.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/fftools/ffmpeg_dec.c b/fftools/ffmpeg_dec.c index f5f764b6fa9..62c1baf2874 100644 --- a/fftools/ffmpeg_dec.c +++ b/fftools/ffmpeg_dec.c @@ -1115,9 +1115,6 @@ int dec_open(InputStream *ist) } if ((ret = avcodec_open2(ist->dec_ctx, codec, &ist->decoder_opts)) < 0) { - if (ret == AVERROR_EXPERIMENTAL) - exit_program(1); - av_log(ist, AV_LOG_ERROR, "Error while opening decoder: %s\n", av_err2str(ret)); return ret; From ab16e324eae9f0eded14f8486fe44ad97ef613c8 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Thu, 13 Jul 2023 15:11:07 +0200 Subject: [PATCH 1937/2172] fftools/ffmpeg_filter: return error codes from ofilter_bind_ost() instead of aborting --- fftools/ffmpeg.h | 2 +- fftools/ffmpeg_filter.c | 12 ++++++++---- fftools/ffmpeg_mux_init.c | 4 +++- 3 files changed, 12 insertions(+), 6 deletions(-) diff --git a/fftools/ffmpeg.h b/fftools/ffmpeg.h index 36e8867fd5b..878f8e87d5e 100644 --- a/fftools/ffmpeg.h +++ b/fftools/ffmpeg.h @@ -743,7 +743,7 @@ void ifilter_sub2video_heartbeat(InputFilter *ifilter, int64_t pts, AVRational t */ int ifilter_parameters_from_dec(InputFilter *ifilter, const AVCodecContext *dec); -void ofilter_bind_ost(OutputFilter *ofilter, OutputStream *ost); +int ofilter_bind_ost(OutputFilter *ofilter, OutputStream *ost); /** * Create a new filtergraph in the global filtergraph list. diff --git a/fftools/ffmpeg_filter.c b/fftools/ffmpeg_filter.c index d373d8c0020..cdf56106209 100644 --- a/fftools/ffmpeg_filter.c +++ b/fftools/ffmpeg_filter.c @@ -624,7 +624,7 @@ static void set_channel_layout(OutputFilterPriv *f, OutputStream *ost) av_channel_layout_default(&f->ch_layout, ost->enc_ctx->ch_layout.nb_channels); } -void ofilter_bind_ost(OutputFilter *ofilter, OutputStream *ost) +int ofilter_bind_ost(OutputFilter *ofilter, OutputStream *ost) { OutputFilterPriv *ofp = ofp_from_ofilter(ofilter); FilterGraph *fg = ofilter->graph; @@ -699,15 +699,17 @@ void ofilter_bind_ost(OutputFilter *ofilter, OutputStream *ost) for (int i = 0; i < fg->nb_outputs; i++) if (!fg->outputs[i]->ost) - return; + return 0; ret = configure_filtergraph(fg); if (ret < 0) { av_log(fg, AV_LOG_ERROR, "Error configuring filter graph: %s\n", av_err2str(ret)); - exit_program(1); + return ret; } } + + return 0; } static InputFilter *ifilter_alloc(FilterGraph *fg) @@ -899,7 +901,9 @@ int init_simple_filtergraph(InputStream *ist, OutputStream *ost, if (ret < 0) return ret; - ofilter_bind_ost(fg->outputs[0], ost); + ret = ofilter_bind_ost(fg->outputs[0], ost); + if (ret < 0) + return ret; return 0; } diff --git a/fftools/ffmpeg_mux_init.c b/fftools/ffmpeg_mux_init.c index d6ae154ad93..4580f4af418 100644 --- a/fftools/ffmpeg_mux_init.c +++ b/fftools/ffmpeg_mux_init.c @@ -1382,7 +1382,9 @@ static int ost_add(Muxer *mux, const OptionsContext *o, enum AVMediaType type, (type == AVMEDIA_TYPE_VIDEO || type == AVMEDIA_TYPE_AUDIO)) { if (ofilter) { ost->filter = ofilter; - ofilter_bind_ost(ofilter, ost); + ret = ofilter_bind_ost(ofilter, ost); + if (ret < 0) + return ret; } else { ret = init_simple_filtergraph(ost->ist, ost, filters); if (ret < 0) { From a52ee1aa47b5a4a489ec0c34f7bc752a95dbae04 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Thu, 13 Jul 2023 15:11:07 +0200 Subject: [PATCH 1938/2172] fftools/ffmpeg_filter: return error codes from init_input_filter() instead of aborting --- fftools/ffmpeg_filter.c | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/fftools/ffmpeg_filter.c b/fftools/ffmpeg_filter.c index cdf56106209..79e034d2482 100644 --- a/fftools/ffmpeg_filter.c +++ b/fftools/ffmpeg_filter.c @@ -908,7 +908,7 @@ int init_simple_filtergraph(InputStream *ist, OutputStream *ost, return 0; } -static void init_input_filter(FilterGraph *fg, InputFilter *ifilter) +static int init_input_filter(FilterGraph *fg, InputFilter *ifilter) { FilterGraphPriv *fgp = fgp_from_fg(fg); InputFilterPriv *ifp = ifp_from_ifilter(ifilter); @@ -920,7 +920,7 @@ static void init_input_filter(FilterGraph *fg, InputFilter *ifilter) if (type != AVMEDIA_TYPE_VIDEO && type != AVMEDIA_TYPE_AUDIO) { av_log(fg, AV_LOG_FATAL, "Only video and audio filters supported " "currently.\n"); - exit_program(1); + return AVERROR(ENOSYS); } if (ifp->linklabel) { @@ -932,7 +932,7 @@ static void init_input_filter(FilterGraph *fg, InputFilter *ifilter) if (file_idx < 0 || file_idx >= nb_input_files) { av_log(fg, AV_LOG_FATAL, "Invalid file index %d in filtergraph description %s.\n", file_idx, fgp->graph_desc); - exit_program(1); + return AVERROR(EINVAL); } s = input_files[file_idx]->ctx; @@ -950,7 +950,7 @@ static void init_input_filter(FilterGraph *fg, InputFilter *ifilter) if (!st) { av_log(fg, AV_LOG_FATAL, "Stream specifier '%s' in filtergraph description %s " "matches no streams.\n", p, fgp->graph_desc); - exit_program(1); + return AVERROR(EINVAL); } ist = input_files[file_idx]->streams[st->index]; } else { @@ -958,7 +958,7 @@ static void init_input_filter(FilterGraph *fg, InputFilter *ifilter) if (!ist) { av_log(fg, AV_LOG_FATAL, "Cannot find a matching stream for " "unlabeled input pad %s\n", ifilter->name); - exit_program(1); + return AVERROR(EINVAL); } } av_assert0(ist); @@ -968,15 +968,20 @@ static void init_input_filter(FilterGraph *fg, InputFilter *ifilter) av_log(fg, AV_LOG_ERROR, "Error binding an input stream to complex filtergraph input %s.\n", ifilter->name); - exit_program(1); + return ret; } + + return 0; } int init_complex_filtergraph(FilterGraph *fg) { // bind filtergraph inputs to input streams - for (int i = 0; i < fg->nb_inputs; i++) - init_input_filter(fg, fg->inputs[i]); + for (int i = 0; i < fg->nb_inputs; i++) { + int ret = init_input_filter(fg, fg->inputs[i]); + if (ret < 0) + return ret; + } return 0; } From 8815adfe75739dfc5a1d83d57e824a6dabeb0d9c Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Thu, 13 Jul 2023 15:11:07 +0200 Subject: [PATCH 1939/2172] fftools/ffmpeg_filter: replace remaining exit_program() with error codes --- fftools/ffmpeg.h | 2 +- fftools/ffmpeg_filter.c | 17 ++++++++++++----- fftools/ffmpeg_opt.c | 4 +++- 3 files changed, 16 insertions(+), 7 deletions(-) diff --git a/fftools/ffmpeg.h b/fftools/ffmpeg.h index 878f8e87d5e..4a136c10288 100644 --- a/fftools/ffmpeg.h +++ b/fftools/ffmpeg.h @@ -716,7 +716,7 @@ const AVCodec *find_codec_or_die(void *logctx, const char *name, enum AVMediaType type, int encoder); int parse_and_set_vsync(const char *arg, int *vsync_var, int file_idx, int st_idx, int is_global); -void check_filter_outputs(void); +int check_filter_outputs(void); int filtergraph_is_simple(const FilterGraph *fg); int init_simple_filtergraph(InputStream *ist, OutputStream *ost, char *graph_desc); diff --git a/fftools/ffmpeg_filter.c b/fftools/ffmpeg_filter.c index 79e034d2482..dca9c467fc2 100644 --- a/fftools/ffmpeg_filter.c +++ b/fftools/ffmpeg_filter.c @@ -1246,7 +1246,7 @@ static int configure_output_filter(FilterGraph *fg, OutputFilter *ofilter, { if (!ofilter->ost) { av_log(fg, AV_LOG_FATAL, "Filter %s has an unconnected output\n", ofilter->name); - exit_program(1); + return AVERROR(EINVAL); } switch (avfilter_pad_get_type(out->filter_ctx->output_pads, out->pad_idx)) { @@ -1256,7 +1256,7 @@ static int configure_output_filter(FilterGraph *fg, OutputFilter *ofilter, } } -void check_filter_outputs(void) +int check_filter_outputs(void) { int i; for (i = 0; i < nb_filtergraphs; i++) { @@ -1266,10 +1266,12 @@ void check_filter_outputs(void) if (!output->ost) { av_log(filtergraphs[i], AV_LOG_FATAL, "Filter %s has an unconnected output\n", output->name); - exit_program(1); + return AVERROR(EINVAL); } } } + + return 0; } static void sub2video_prepare(InputFilterPriv *ifp) @@ -1570,8 +1572,13 @@ static int configure_filtergraph(FilterGraph *fg) } avfilter_inout_free(&inputs); - for (cur = outputs, i = 0; cur; cur = cur->next, i++) - configure_output_filter(fg, fg->outputs[i], cur); + for (cur = outputs, i = 0; cur; cur = cur->next, i++) { + ret = configure_output_filter(fg, fg->outputs[i], cur); + if (ret < 0) { + avfilter_inout_free(&outputs); + goto fail; + } + } avfilter_inout_free(&outputs); if (fgp->disable_conversions) diff --git a/fftools/ffmpeg_opt.c b/fftools/ffmpeg_opt.c index 300f042660a..44bf2636219 100644 --- a/fftools/ffmpeg_opt.c +++ b/fftools/ffmpeg_opt.c @@ -1301,7 +1301,9 @@ int ffmpeg_parse_options(int argc, char **argv) apply_sync_offsets(); - check_filter_outputs(); + ret = check_filter_outputs(); + if (ret < 0) + goto fail; fail: uninit_parse_context(&octx); From 8db96808bc034ddd007ad5e861d3ce536d9b9514 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Thu, 13 Jul 2023 15:11:07 +0200 Subject: [PATCH 1940/2172] fftools/ffmpeg_filter: return error codes from choose_pix_fmts() instead of aborting --- fftools/ffmpeg_filter.c | 32 +++++++++++++++++++------------- 1 file changed, 19 insertions(+), 13 deletions(-) diff --git a/fftools/ffmpeg_filter.c b/fftools/ffmpeg_filter.c index dca9c467fc2..c7e2af494f4 100644 --- a/fftools/ffmpeg_filter.c +++ b/fftools/ffmpeg_filter.c @@ -270,20 +270,20 @@ static void sub2video_update(InputFilterPriv *ifp, int64_t heartbeat_pts, ifp->sub2video.initialize = 0; } -/* 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 +/* *dst may return be set to 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) +static int choose_pix_fmts(OutputFilter *ofilter, AVBPrint *bprint, + const char **dst) { OutputFilterPriv *ofp = ofp_from_ofilter(ofilter); OutputStream *ost = ofilter->ost; - if (ost->keep_pix_fmt) { - return ofp->format == AV_PIX_FMT_NONE ? NULL : + *dst = NULL; + + if (ost->keep_pix_fmt || ofp->format != AV_PIX_FMT_NONE) { + *dst = ofp->format == AV_PIX_FMT_NONE ? NULL : av_get_pix_fmt_name(ofp->format); - } - if (ofp->format != AV_PIX_FMT_NONE) { - return av_get_pix_fmt_name(ofp->format); } else if (ofp->formats) { const enum AVPixelFormat *p = ofp->formats; @@ -292,10 +292,12 @@ static const char *choose_pix_fmts(OutputFilter *ofilter, AVBPrint *bprint) av_bprintf(bprint, "%s%c", name, p[1] == AV_PIX_FMT_NONE ? '\0' : '|'); } if (!av_bprint_is_complete(bprint)) - report_and_exit(AVERROR(ENOMEM)); - return bprint->str; - } else - return NULL; + return AVERROR(ENOMEM); + + *dst = bprint->str; + } + + return 0; } /* Define a function for appending a list of allowed formats @@ -1103,7 +1105,11 @@ static int configure_output_video_filter(FilterGraph *fg, OutputFilter *ofilter, } av_bprint_init(&bprint, 0, AV_BPRINT_SIZE_UNLIMITED); - if ((pix_fmts = choose_pix_fmts(ofilter, &bprint))) { + ret = choose_pix_fmts(ofilter, &bprint, &pix_fmts); + if (ret < 0) + return ret; + + if (pix_fmts) { AVFilterContext *filter; ret = avfilter_graph_create_filter(&filter, From 5ba7aa2ce821b39b665fd0ef1e1c236814f3438a Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Thu, 13 Jul 2023 15:11:07 +0200 Subject: [PATCH 1941/2172] fftools/ffmpeg_filter: return error codes from fg_create() instead of aborting --- fftools/ffmpeg.h | 2 +- fftools/ffmpeg_filter.c | 38 ++++++++++++++++++++++---------------- fftools/ffmpeg_opt.c | 8 ++------ 3 files changed, 25 insertions(+), 23 deletions(-) diff --git a/fftools/ffmpeg.h b/fftools/ffmpeg.h index 4a136c10288..fc953be9115 100644 --- a/fftools/ffmpeg.h +++ b/fftools/ffmpeg.h @@ -751,7 +751,7 @@ int ofilter_bind_ost(OutputFilter *ofilter, OutputStream *ost); * @param graph_desc Graph description; an av_malloc()ed string, filtergraph * takes ownership of it. */ -FilterGraph *fg_create(char *graph_desc); +int fg_create(FilterGraph **pfg, char *graph_desc); void fg_free(FilterGraph **pfg); diff --git a/fftools/ffmpeg_filter.c b/fftools/ffmpeg_filter.c index c7e2af494f4..378a6c6871a 100644 --- a/fftools/ffmpeg_filter.c +++ b/fftools/ffmpeg_filter.c @@ -538,16 +538,11 @@ 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; - char *res; if (nb_pads > 1) - 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) - report_and_exit(AVERROR(ENOMEM)); - return res; + return av_strdup(ctx->filter->name); + return av_asprintf("%s:%s", ctx->filter->name, + avfilter_pad_get_name(pads, inout->pad_idx)); } static OutputFilter *ofilter_alloc(FilterGraph *fg) @@ -799,7 +794,7 @@ static const AVClass fg_class = { .category = AV_CLASS_CATEGORY_FILTER, }; -FilterGraph *fg_create(char *graph_desc) +int fg_create(FilterGraph **pfg, char *graph_desc) { FilterGraphPriv *fgp = allocate_array_elem(&filtergraphs, sizeof(*fgp), &nb_filtergraphs); FilterGraph *fg = &fgp->fg; @@ -808,6 +803,9 @@ FilterGraph *fg_create(char *graph_desc) AVFilterGraph *graph; int ret = 0; + if (pfg) + *pfg = fg; + fg->class = &fg_class; fg->index = nb_filtergraphs - 1; fgp->graph_desc = graph_desc; @@ -817,13 +815,13 @@ FilterGraph *fg_create(char *graph_desc) fgp->frame = av_frame_alloc(); if (!fgp->frame) - report_and_exit(AVERROR(ENOMEM)); + return AVERROR(ENOMEM); /* this graph is only used for determining the kinds of inputs * and outputs we have, and is discarded on exit from this function */ graph = avfilter_graph_alloc(); if (!graph) - report_and_exit(AVERROR(ENOMEM)); + return AVERROR(ENOMEM);; graph->nb_threads = 1; ret = graph_parse(graph, fgp->graph_desc, &inputs, &outputs, NULL); @@ -840,6 +838,10 @@ FilterGraph *fg_create(char *graph_desc) ifp->type = avfilter_pad_get_type(cur->filter_ctx->input_pads, cur->pad_idx); ifilter->name = describe_filter_link(fg, cur, 1); + if (!ifilter->name) { + ret = AVERROR(ENOMEM); + goto fail; + } } for (AVFilterInOut *cur = outputs; cur; cur = cur->next) { @@ -851,6 +853,10 @@ FilterGraph *fg_create(char *graph_desc) ofilter->type = avfilter_pad_get_type(cur->filter_ctx->output_pads, cur->pad_idx); ofilter->name = describe_filter_link(fg, cur, 0); + if (!ofilter->name) { + ret = AVERROR(ENOMEM); + goto fail; + } } if (!fg->nb_outputs) { @@ -865,9 +871,9 @@ FilterGraph *fg_create(char *graph_desc) avfilter_graph_free(&graph); if (ret < 0) - report_and_exit(ret); + return ret; - return fg; + return 0; } int init_simple_filtergraph(InputStream *ist, OutputStream *ost, @@ -877,9 +883,9 @@ int init_simple_filtergraph(InputStream *ist, OutputStream *ost, FilterGraphPriv *fgp; int ret; - fg = fg_create(graph_desc); - if (!fg) - report_and_exit(AVERROR(ENOMEM)); + ret = fg_create(&fg, graph_desc); + if (ret < 0) + return ret; fgp = fgp_from_fg(fg); fgp->is_simple = 1; diff --git a/fftools/ffmpeg_opt.c b/fftools/ffmpeg_opt.c index 44bf2636219..25a1083366f 100644 --- a/fftools/ffmpeg_opt.c +++ b/fftools/ffmpeg_opt.c @@ -1112,9 +1112,7 @@ static int opt_filter_complex(void *optctx, const char *opt, const char *arg) if (!graph_desc) return AVERROR(ENOMEM); - fg_create(graph_desc); - - return 0; + return fg_create(NULL, graph_desc); } static int opt_filter_complex_script(void *optctx, const char *opt, const char *arg) @@ -1123,9 +1121,7 @@ static int opt_filter_complex_script(void *optctx, const char *opt, const char * if (!graph_desc) return AVERROR(EINVAL); - fg_create(graph_desc); - - return 0; + return fg_create(NULL, graph_desc); } void show_help_default(const char *opt, const char *arg) From cb8242db8d0191fbb51f06eca6bee2c1a2c0c075 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Thu, 13 Jul 2023 15:11:07 +0200 Subject: [PATCH 1942/2172] fftools/ffmpeg_filter: return error codes from set_channel_layout() instead of aborting --- fftools/ffmpeg_filter.c | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/fftools/ffmpeg_filter.c b/fftools/ffmpeg_filter.c index 378a6c6871a..b7fb66c0479 100644 --- a/fftools/ffmpeg_filter.c +++ b/fftools/ffmpeg_filter.c @@ -583,7 +583,7 @@ static int ifilter_bind_ist(InputFilter *ifilter, InputStream *ist) return 0; } -static void set_channel_layout(OutputFilterPriv *f, OutputStream *ost) +static int set_channel_layout(OutputFilterPriv *f, OutputStream *ost) { const AVCodec *c = ost->enc_ctx->codec; int i, err; @@ -592,8 +592,8 @@ static void set_channel_layout(OutputFilterPriv *f, OutputStream *ost) /* Pass the layout through for all orders but UNSPEC */ err = av_channel_layout_copy(&f->ch_layout, &ost->enc_ctx->ch_layout); if (err < 0) - report_and_exit(AVERROR(ENOMEM)); - return; + return err; + return 0; } /* Requested layout is of order UNSPEC */ @@ -601,7 +601,7 @@ static void set_channel_layout(OutputFilterPriv *f, OutputStream *ost) /* Use the default native layout for the requested amount of channels when the encoder doesn't have a list of supported layouts */ av_channel_layout_default(&f->ch_layout, ost->enc_ctx->ch_layout.nb_channels); - return; + return 0; } /* Encoder has a list of supported layouts. Pick the first layout in it with the same amount of channels as the requested layout */ @@ -613,12 +613,14 @@ static void set_channel_layout(OutputFilterPriv *f, OutputStream *ost) /* Use it if one is found */ err = av_channel_layout_copy(&f->ch_layout, &c->ch_layouts[i]); if (err < 0) - report_and_exit(AVERROR(ENOMEM)); - return; + return err; + return 0; } /* If no layout for the amount of channels requested was found, use the default native layout for it. */ av_channel_layout_default(&f->ch_layout, ost->enc_ctx->ch_layout.nb_channels); + + return 0; } int ofilter_bind_ost(OutputFilter *ofilter, OutputStream *ost) @@ -682,7 +684,9 @@ int ofilter_bind_ost(OutputFilter *ofilter, OutputStream *ost) ofp->sample_rates = c->supported_samplerates; } if (ost->enc_ctx->ch_layout.nb_channels) { - set_channel_layout(ofp, ost); + int ret = set_channel_layout(ofp, ost); + if (ret < 0) + return ret; } else if (c->ch_layouts) { ofp->ch_layouts = c->ch_layouts; } From 13ebc9a0a9b6b67e7bd896a729d9651a24373135 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Thu, 13 Jul 2023 15:11:07 +0200 Subject: [PATCH 1943/2172] fftools/ffmpeg_filter: replace remaining report_and_exit() with error codes --- fftools/ffmpeg_filter.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/fftools/ffmpeg_filter.c b/fftools/ffmpeg_filter.c index b7fb66c0479..538cf6cd435 100644 --- a/fftools/ffmpeg_filter.c +++ b/fftools/ffmpeg_filter.c @@ -723,14 +723,14 @@ static InputFilter *ifilter_alloc(FilterGraph *fg) ifp->frame = av_frame_alloc(); if (!ifp->frame) - report_and_exit(AVERROR(ENOMEM)); + return NULL; ifp->format = -1; ifp->fallback.format = -1; ifp->frame_queue = av_fifo_alloc2(8, sizeof(AVFrame*), AV_FIFO_FLAG_AUTO_GROW); if (!ifp->frame_queue) - report_and_exit(AVERROR(ENOMEM)); + return NULL; return ifilter; } @@ -1783,7 +1783,7 @@ int reap_filters(FilterGraph *fg, int flush) fd = frame_data(filtered_frame); if (!fd) { av_frame_unref(filtered_frame); - report_and_exit(AVERROR(ENOMEM)); + return AVERROR(ENOMEM); } // only use bits_per_raw_sample passed through from the decoder From 37abb3a41913a7f5b83c0f81acb6775f127c86c4 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Thu, 13 Jul 2023 15:11:07 +0200 Subject: [PATCH 1944/2172] fftools/cmdutils: return error codes from setup_find_stream_info_opts() instead of aborting --- fftools/cmdutils.c | 30 +++++++++++++++++++++--------- fftools/cmdutils.h | 8 +++----- fftools/ffmpeg_demux.c | 6 +++++- fftools/ffplay.c | 6 +++++- fftools/ffprobe.c | 6 +++++- 5 files changed, 39 insertions(+), 17 deletions(-) diff --git a/fftools/cmdutils.c b/fftools/cmdutils.c index 9ec00add303..e2fa08c1161 100644 --- a/fftools/cmdutils.c +++ b/fftools/cmdutils.c @@ -645,8 +645,8 @@ static void add_opt(OptionParseContext *octx, const OptionDef *opt, g->opts[g->nb_opts - 1].val = val; } -static void init_parse_context(OptionParseContext *octx, - const OptionGroupDef *groups, int nb_groups) +static int init_parse_context(OptionParseContext *octx, + const OptionGroupDef *groups, int nb_groups) { static const OptionGroupDef global_group = { "global" }; int i; @@ -656,13 +656,15 @@ static void init_parse_context(OptionParseContext *octx, octx->nb_groups = nb_groups; octx->groups = av_calloc(octx->nb_groups, sizeof(*octx->groups)); if (!octx->groups) - report_and_exit(AVERROR(ENOMEM)); + return AVERROR(ENOMEM); for (i = 0; i < octx->nb_groups; i++) octx->groups[i].group_def = &groups[i]; octx->global_opts.group_def = &global_group; octx->global_opts.arg = ""; + + return 0; } void uninit_parse_context(OptionParseContext *octx) @@ -694,13 +696,17 @@ int split_commandline(OptionParseContext *octx, int argc, char *argv[], const OptionDef *options, const OptionGroupDef *groups, int nb_groups) { + int ret; int optindex = 1; int dashdash = -2; /* perform system-dependent conversions for arguments list */ prepare_app_arguments(&argc, &argv); - init_parse_context(octx, groups, nb_groups); + ret = init_parse_context(octx, groups, nb_groups); + if (ret < 0) + return ret; + av_log(NULL, AV_LOG_DEBUG, "Splitting the commandline.\n"); while (optindex < argc) { @@ -950,21 +956,27 @@ AVDictionary *filter_codec_opts(AVDictionary *opts, enum AVCodecID codec_id, return ret; } -AVDictionary **setup_find_stream_info_opts(AVFormatContext *s, - AVDictionary *codec_opts) +int setup_find_stream_info_opts(AVFormatContext *s, + AVDictionary *codec_opts, + AVDictionary ***dst) { int i; AVDictionary **opts; + *dst = NULL; + if (!s->nb_streams) - return NULL; + return 0; + opts = av_calloc(s->nb_streams, sizeof(*opts)); if (!opts) - report_and_exit(AVERROR(ENOMEM)); + return AVERROR(ENOMEM); + for (i = 0; i < s->nb_streams; i++) opts[i] = filter_codec_opts(codec_opts, s->streams[i]->codecpar->codec_id, s, s->streams[i], NULL); - return opts; + *dst = opts; + return 0; } void *grow_array(void *array, int elem_size, int *size, int new_size) diff --git a/fftools/cmdutils.h b/fftools/cmdutils.h index 01159402250..f54f3322efc 100644 --- a/fftools/cmdutils.h +++ b/fftools/cmdutils.h @@ -364,12 +364,10 @@ AVDictionary *filter_codec_opts(AVDictionary *opts, enum AVCodecID codec_id, * contained in s. * 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. - * Calls exit() on failure. */ -AVDictionary **setup_find_stream_info_opts(AVFormatContext *s, - AVDictionary *codec_opts); +int setup_find_stream_info_opts(AVFormatContext *s, + AVDictionary *codec_opts, + AVDictionary ***dst); /** * Print an error message to stderr, indicating filename and a human diff --git a/fftools/ffmpeg_demux.c b/fftools/ffmpeg_demux.c index 9e7f13a2b4d..a43c39b8434 100644 --- a/fftools/ffmpeg_demux.c +++ b/fftools/ffmpeg_demux.c @@ -1482,9 +1482,13 @@ int ifile_open(const OptionsContext *o, const char *filename) choose_decoder(o, ic, ic->streams[i], HWACCEL_NONE, AV_HWDEVICE_TYPE_NONE); if (o->find_stream_info) { - AVDictionary **opts = setup_find_stream_info_opts(ic, o->g->codec_opts); + AVDictionary **opts; int orig_nb_streams = ic->nb_streams; + ret = setup_find_stream_info_opts(ic, o->g->codec_opts, &opts); + if (ret < 0) + return ret; + /* If not enough info to get the stream parameters, we decode the first frames to get it. (used in mpeg case for example) */ ret = avformat_find_stream_info(ic, opts); diff --git a/fftools/ffplay.c b/fftools/ffplay.c index 51cde0d208b..99700dc6f2b 100644 --- a/fftools/ffplay.c +++ b/fftools/ffplay.c @@ -2773,9 +2773,13 @@ static int read_thread(void *arg) av_format_inject_global_side_data(ic); if (find_stream_info) { - AVDictionary **opts = setup_find_stream_info_opts(ic, codec_opts); + AVDictionary **opts; int orig_nb_streams = ic->nb_streams; + err = setup_find_stream_info_opts(ic, codec_opts, &opts); + if (err < 0) + report_and_exit(err); + err = avformat_find_stream_info(ic, opts); for (i = 0; i < orig_nb_streams; i++) diff --git a/fftools/ffprobe.c b/fftools/ffprobe.c index 1ff76ce8094..91a3be660bf 100644 --- a/fftools/ffprobe.c +++ b/fftools/ffprobe.c @@ -3372,9 +3372,13 @@ static int open_input_file(InputFile *ifile, const char *filename, av_log(NULL, AV_LOG_WARNING, "Option %s skipped - not known to demuxer.\n", t->key); if (find_stream_info) { - AVDictionary **opts = setup_find_stream_info_opts(fmt_ctx, codec_opts); + AVDictionary **opts; int orig_nb_streams = fmt_ctx->nb_streams; + err = setup_find_stream_info_opts(fmt_ctx, codec_opts, &opts); + if (err < 0) + report_and_exit(err); + err = avformat_find_stream_info(fmt_ctx, opts); for (i = 0; i < orig_nb_streams; i++) From 26e1e80152beccb12919cc1078f5f42e3a6774c9 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Thu, 13 Jul 2023 17:36:57 +0200 Subject: [PATCH 1945/2172] fftools/ffmpeg_opt: reimplement -streamid using a dictionary This does not require an arbitrary limit on the number of streams. Also, return error codes from opt_streamid() instead of aborting. --- fftools/ffmpeg.h | 7 ++----- fftools/ffmpeg_mux_init.c | 18 +++++++++++++++--- fftools/ffmpeg_opt.c | 12 +++++------- 3 files changed, 22 insertions(+), 15 deletions(-) diff --git a/fftools/ffmpeg.h b/fftools/ffmpeg.h index fc953be9115..0e5e1561f5f 100644 --- a/fftools/ffmpeg.h +++ b/fftools/ffmpeg.h @@ -72,8 +72,6 @@ enum EncTimeBase { ENC_TIME_BASE_FILTER = -2, }; -#define MAX_STREAMS 1024 /* arbitrary sanity check value */ - enum HWAccelID { HWACCEL_NONE = 0, HWACCEL_AUTO, @@ -183,9 +181,8 @@ typedef struct OptionsContext { int subtitle_disable; int data_disable; - /* indexed by output file stream index */ - int *streamid_map; - int nb_streamid_map; + // keys are stream indices + AVDictionary *streamid; SpecifierOpt *metadata; int nb_metadata; diff --git a/fftools/ffmpeg_mux_init.c b/fftools/ffmpeg_mux_init.c index 4580f4af418..8552febce8f 100644 --- a/fftools/ffmpeg_mux_init.c +++ b/fftools/ffmpeg_mux_init.c @@ -1100,12 +1100,24 @@ static int ost_add(Muxer *mux, const OptionsContext *o, enum AVMediaType type, if (!st) return AVERROR(ENOMEM); - if (oc->nb_streams - 1 < o->nb_streamid_map) - st->id = o->streamid_map[oc->nb_streams - 1]; - ms = mux_stream_alloc(mux, type); ost = &ms->ost; + if (o->streamid) { + AVDictionaryEntry *e; + char idx[16], *p; + snprintf(idx, sizeof(idx), "%d", ost->index); + + e = av_dict_get(o->streamid, idx, NULL, 0); + if (e) { + st->id = strtol(e->value, &p, 0); + if (!e->value[0] || *p) { + av_log(ost, AV_LOG_FATAL, "Invalid stream id: %s\n", e->value); + return AVERROR(EINVAL); + } + } + } + ost->par_in = avcodec_parameters_alloc(); if (!ost->par_in) return AVERROR(ENOMEM); diff --git a/fftools/ffmpeg_opt.c b/fftools/ffmpeg_opt.c index 25a1083366f..70029863692 100644 --- a/fftools/ffmpeg_opt.c +++ b/fftools/ffmpeg_opt.c @@ -128,8 +128,9 @@ static void uninit_options(OptionsContext *o) #if FFMPEG_OPT_MAP_CHANNEL av_freep(&o->audio_channel_maps); #endif - av_freep(&o->streamid_map); av_freep(&o->attachments); + + av_dict_free(&o->streamid); } static void init_options(OptionsContext *o) @@ -727,7 +728,6 @@ char *file_read(const char *filename) static int opt_streamid(void *optctx, const char *opt, const char *arg) { OptionsContext *o = optctx; - int idx; char *p; char idx_str[16]; @@ -737,13 +737,11 @@ static int opt_streamid(void *optctx, const char *opt, const char *arg) av_log(NULL, AV_LOG_FATAL, "Invalid value '%s' for option '%s', required syntax is 'index:value'\n", arg, opt); - exit_program(1); + return AVERROR(EINVAL); } *p++ = '\0'; - idx = parse_number_or_die(opt, idx_str, OPT_INT, 0, MAX_STREAMS-1); - o->streamid_map = grow_array(o->streamid_map, sizeof(*o->streamid_map), &o->nb_streamid_map, idx+1); - o->streamid_map[idx] = parse_number_or_die(opt, p, OPT_INT, 0, INT_MAX); - return 0; + + return av_dict_set(&o->streamid, idx_str, p, 0); } static int init_complex_filters(void) From 8eb5adeab87b8f5a367e0f6b39de53c0bf65a9a2 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Thu, 13 Jul 2023 17:40:58 +0200 Subject: [PATCH 1946/2172] fftools/cmdutils: drop unused ALLOC_ARRAY_ELEM() --- fftools/cmdutils.h | 3 --- 1 file changed, 3 deletions(-) diff --git a/fftools/cmdutils.h b/fftools/cmdutils.h index f54f3322efc..decd23040ff 100644 --- a/fftools/cmdutils.h +++ b/fftools/cmdutils.h @@ -443,9 +443,6 @@ void *allocate_array_elem(void *array, size_t elem_size, int *nb_elems); #define GROW_ARRAY(array, nb_elems)\ array = grow_array(array, sizeof(*array), &nb_elems, nb_elems + 1) -#define ALLOC_ARRAY_ELEM(array, 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); From 6be4a2939712136fd83aba2a843c8900829a73c2 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Thu, 13 Jul 2023 17:50:16 +0200 Subject: [PATCH 1947/2172] fftools/cmdutils: add error handling to allocate_array_elem() --- fftools/cmdutils.c | 2 +- fftools/cmdutils.h | 3 +-- fftools/ffmpeg_demux.c | 16 ++++++++++++++-- fftools/ffmpeg_filter.c | 28 +++++++++++++++++++++------- fftools/ffmpeg_mux_init.c | 16 ++++++++++++++-- 5 files changed, 51 insertions(+), 14 deletions(-) diff --git a/fftools/cmdutils.c b/fftools/cmdutils.c index e2fa08c1161..6c627ee815c 100644 --- a/fftools/cmdutils.c +++ b/fftools/cmdutils.c @@ -1002,7 +1002,7 @@ void *allocate_array_elem(void *ptr, size_t elem_size, int *nb_elems) if (!(new_elem = av_mallocz(elem_size)) || av_dynarray_add_nofree(ptr, nb_elems, new_elem) < 0) - report_and_exit(AVERROR(ENOMEM)); + return NULL; return new_elem; } diff --git a/fftools/cmdutils.h b/fftools/cmdutils.h index decd23040ff..6b9d7f80ae8 100644 --- a/fftools/cmdutils.h +++ b/fftools/cmdutils.h @@ -430,13 +430,12 @@ 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 pointer to the newly allocated entry + * @return pointer to the newly allocated entry or NULL on failure */ void *allocate_array_elem(void *array, size_t elem_size, int *nb_elems); diff --git a/fftools/ffmpeg_demux.c b/fftools/ffmpeg_demux.c index a43c39b8434..72b94ea44fc 100644 --- a/fftools/ffmpeg_demux.c +++ b/fftools/ffmpeg_demux.c @@ -1018,8 +1018,11 @@ static DemuxStream *demux_stream_alloc(Demuxer *d, AVStream *st) { const char *type_str = av_get_media_type_string(st->codecpar->codec_type); InputFile *f = &d->f; - DemuxStream *ds = allocate_array_elem(&f->streams, sizeof(*ds), - &f->nb_streams); + DemuxStream *ds; + + ds = allocate_array_elem(&f->streams, sizeof(*ds), &f->nb_streams); + if (!ds) + return NULL; ds->ist.st = st; ds->ist.file_index = f->index; @@ -1051,6 +1054,9 @@ static int ist_add(const OptionsContext *o, Demuxer *d, AVStream *st) int ret; ds = demux_stream_alloc(d, st); + if (!ds) + return AVERROR(ENOMEM); + ist = &ds->ist; ist->discard = 1; @@ -1328,6 +1334,9 @@ static Demuxer *demux_alloc(void) { Demuxer *d = allocate_array_elem(&input_files, sizeof(*d), &nb_input_files); + if (!d) + return NULL; + d->f.class = &input_file_class; d->f.index = nb_input_files - 1; @@ -1358,6 +1367,9 @@ int ifile_open(const OptionsContext *o, const char *filename) int64_t recording_time = o->recording_time; d = demux_alloc(); + if (!d) + return AVERROR(ENOMEM); + f = &d->f; if (stop_time != INT64_MAX && recording_time != INT64_MAX) { diff --git a/fftools/ffmpeg_filter.c b/fftools/ffmpeg_filter.c index 538cf6cd435..925b5116cc8 100644 --- a/fftools/ffmpeg_filter.c +++ b/fftools/ffmpeg_filter.c @@ -550,8 +550,10 @@ static OutputFilter *ofilter_alloc(FilterGraph *fg) OutputFilterPriv *ofp; OutputFilter *ofilter; - ofp = allocate_array_elem(&fg->outputs, sizeof(*ofp), - &fg->nb_outputs); + ofp = allocate_array_elem(&fg->outputs, sizeof(*ofp), &fg->nb_outputs); + if (!ofp) + return NULL; + ofilter = &ofp->ofilter; ofilter->graph = fg; ofp->format = -1; @@ -715,10 +717,14 @@ int ofilter_bind_ost(OutputFilter *ofilter, OutputStream *ost) static InputFilter *ifilter_alloc(FilterGraph *fg) { - InputFilterPriv *ifp = allocate_array_elem(&fg->inputs, sizeof(*ifp), - &fg->nb_inputs); - InputFilter *ifilter = &ifp->ifilter; + InputFilterPriv *ifp; + InputFilter *ifilter; + ifp = allocate_array_elem(&fg->inputs, sizeof(*ifp), &fg->nb_inputs); + if (!ifp) + return NULL; + + ifilter = &ifp->ifilter; ifilter->graph = fg; ifp->frame = av_frame_alloc(); @@ -800,13 +806,18 @@ static const AVClass fg_class = { int fg_create(FilterGraph **pfg, char *graph_desc) { - FilterGraphPriv *fgp = allocate_array_elem(&filtergraphs, sizeof(*fgp), &nb_filtergraphs); - FilterGraph *fg = &fgp->fg; + FilterGraphPriv *fgp; + FilterGraph *fg; AVFilterInOut *inputs, *outputs; AVFilterGraph *graph; int ret = 0; + fgp = allocate_array_elem(&filtergraphs, sizeof(*fgp), &nb_filtergraphs); + if (!fgp) + return AVERROR(ENOMEM); + fg = &fgp->fg; + if (pfg) *pfg = fg; @@ -851,6 +862,9 @@ int fg_create(FilterGraph **pfg, char *graph_desc) for (AVFilterInOut *cur = outputs; cur; cur = cur->next) { OutputFilter *const ofilter = ofilter_alloc(fg); + if (!ofilter) + goto fail; + ofilter->linklabel = cur->name; cur->name = NULL; diff --git a/fftools/ffmpeg_mux_init.c b/fftools/ffmpeg_mux_init.c index 8552febce8f..a45cfa8e61d 100644 --- a/fftools/ffmpeg_mux_init.c +++ b/fftools/ffmpeg_mux_init.c @@ -413,8 +413,11 @@ static const AVClass output_stream_class = { static MuxStream *mux_stream_alloc(Muxer *mux, enum AVMediaType type) { const char *type_str = av_get_media_type_string(type); - MuxStream *ms = allocate_array_elem(&mux->of.streams, sizeof(*ms), - &mux->of.nb_streams); + MuxStream *ms; + + ms = allocate_array_elem(&mux->of.streams, sizeof(*ms), &mux->of.nb_streams); + if (!ms) + return NULL; ms->ost.file_index = mux->of.index; ms->ost.index = mux->of.nb_streams - 1; @@ -1101,6 +1104,9 @@ static int ost_add(Muxer *mux, const OptionsContext *o, enum AVMediaType type, return AVERROR(ENOMEM); ms = mux_stream_alloc(mux, type); + if (!ms) + return AVERROR(ENOMEM); + ost = &ms->ost; if (o->streamid) { @@ -2557,6 +2563,9 @@ static Muxer *mux_alloc(void) { Muxer *mux = allocate_array_elem(&output_files, sizeof(*mux), &nb_output_files); + if (!mux) + return NULL; + mux->of.class = &output_file_class; mux->of.index = nb_output_files - 1; @@ -2576,6 +2585,9 @@ int of_open(const OptionsContext *o, const char *filename) int64_t stop_time = o->stop_time; mux = mux_alloc(); + if (!mux) + return AVERROR(ENOMEM); + of = &mux->of; if (stop_time != INT64_MAX && recording_time != INT64_MAX) { From b23abb7c484b0ada607a73a62ce6c6efe33fc47c Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Fri, 14 Jul 2023 12:28:18 +0200 Subject: [PATCH 1948/2172] fftools/cmdutils: add error handling to grow_array() --- fftools/cmdutils.c | 19 ++++++++++++------- fftools/cmdutils.h | 14 +++++++++----- 2 files changed, 21 insertions(+), 12 deletions(-) diff --git a/fftools/cmdutils.c b/fftools/cmdutils.c index 6c627ee815c..63b29c7a3a3 100644 --- a/fftools/cmdutils.c +++ b/fftools/cmdutils.c @@ -262,6 +262,7 @@ static int write_option(void *optctx, const OptionDef *po, const char *opt, void *dst = po->flags & (OPT_OFFSET | OPT_SPEC) ? (uint8_t *)optctx + po->u.off : po->u.dst_ptr; int *dstcount; + int ret; if (po->flags & OPT_SPEC) { SpecifierOpt **so = dst; @@ -269,7 +270,10 @@ static int write_option(void *optctx, const OptionDef *po, const char *opt, char *str; dstcount = (int *)(so + 1); - *so = grow_array(*so, sizeof(**so), dstcount, *dstcount + 1); + ret = grow_array((void**)so, sizeof(**so), dstcount, *dstcount + 1); + if (ret < 0) + return ret; + str = av_strdup(p ? p + 1 : ""); if (!str) return AVERROR(ENOMEM); @@ -979,21 +983,22 @@ int setup_find_stream_info_opts(AVFormatContext *s, return 0; } -void *grow_array(void *array, int elem_size, int *size, int new_size) +int grow_array(void **array, int elem_size, int *size, int new_size) { if (new_size >= INT_MAX / elem_size) { av_log(NULL, AV_LOG_ERROR, "Array too big.\n"); - exit_program(1); + return AVERROR(ERANGE); } if (*size < new_size) { - uint8_t *tmp = av_realloc_array(array, new_size, elem_size); + uint8_t *tmp = av_realloc_array(*array, new_size, elem_size); if (!tmp) - report_and_exit(AVERROR(ENOMEM)); + return AVERROR(ENOMEM); memset(tmp + *size*elem_size, 0, (new_size-*size) * elem_size); *size = new_size; - return tmp; + *array = tmp; + return 0; } - return array; + return 0; } void *allocate_array_elem(void *ptr, size_t elem_size, int *nb_elems) diff --git a/fftools/cmdutils.h b/fftools/cmdutils.h index 6b9d7f80ae8..0dfe8b313c0 100644 --- a/fftools/cmdutils.h +++ b/fftools/cmdutils.h @@ -416,15 +416,15 @@ FILE *get_preset_file(char *filename, size_t filename_size, /** * Realloc array to hold new_size elements of elem_size. - * Calls exit() on failure. * - * @param array array to reallocate + * @param array pointer to the array to reallocate, will be updated + * with a new pointer on success * @param elem_size size in bytes of each element * @param size new element count will be written here * @param new_size number of elements to place in reallocated array - * @return reallocated array + * @return a non-negative number on success, a negative error code on failure */ -void *grow_array(void *array, int elem_size, int *size, int new_size); +int 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 @@ -440,7 +440,11 @@ void *grow_array(void *array, int elem_size, int *size, int new_size); void *allocate_array_elem(void *array, size_t elem_size, int *nb_elems); #define GROW_ARRAY(array, nb_elems)\ - array = grow_array(array, sizeof(*array), &nb_elems, nb_elems + 1) +do { \ + int _ret = grow_array((void**)&array, sizeof(*array), &nb_elems, nb_elems + 1); \ + if (_ret < 0) \ + report_and_exit(_ret); \ +} while (0) #define GET_PIX_FMT_NAME(pix_fmt)\ const char *name = av_get_pix_fmt_name(pix_fmt); From 2e6afa799ef693b94f993f54ed41a84f6d9f1685 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Fri, 14 Jul 2023 12:28:18 +0200 Subject: [PATCH 1949/2172] fftools/cmdutils: add error handling to GROW_ARRAY() --- fftools/cmdutils.c | 44 ++++++++++++++++++++++++++++++--------- fftools/cmdutils.h | 6 +----- fftools/ffmpeg_demux.c | 10 +++++++-- fftools/ffmpeg_mux_init.c | 15 ++++++++++--- fftools/ffmpeg_opt.c | 24 ++++++++++++++++----- fftools/ffplay.c | 5 ++++- 6 files changed, 78 insertions(+), 26 deletions(-) diff --git a/fftools/cmdutils.c b/fftools/cmdutils.c index 63b29c7a3a3..fb35245f0a0 100644 --- a/fftools/cmdutils.c +++ b/fftools/cmdutils.c @@ -609,13 +609,17 @@ static int match_group_separator(const OptionGroupDef *groups, int nb_groups, * @param group_idx which group definition should this group belong to * @param arg argument of the group delimiting option */ -static void finish_group(OptionParseContext *octx, int group_idx, - const char *arg) +static int finish_group(OptionParseContext *octx, int group_idx, + const char *arg) { OptionGroupList *l = &octx->groups[group_idx]; OptionGroup *g; + int ret; + + ret = GROW_ARRAY(l->groups, l->nb_groups); + if (ret < 0) + return ret; - GROW_ARRAY(l->groups, l->nb_groups); g = &l->groups[l->nb_groups - 1]; *g = octx->cur_group; @@ -632,21 +636,29 @@ static void finish_group(OptionParseContext *octx, int group_idx, swr_opts = NULL; memset(&octx->cur_group, 0, sizeof(octx->cur_group)); + + return ret; } /* * Add an option instance to currently parsed group. */ -static void add_opt(OptionParseContext *octx, const OptionDef *opt, - const char *key, const char *val) +static int add_opt(OptionParseContext *octx, const OptionDef *opt, + const char *key, const char *val) { int global = !(opt->flags & (OPT_PERFILE | OPT_SPEC | OPT_OFFSET)); OptionGroup *g = global ? &octx->global_opts : &octx->cur_group; + int ret; + + ret = GROW_ARRAY(g->opts, g->nb_opts); + if (ret < 0) + return ret; - GROW_ARRAY(g->opts, g->nb_opts); g->opts[g->nb_opts - 1].opt = opt; g->opts[g->nb_opts - 1].key = key; g->opts[g->nb_opts - 1].val = val; + + return 0; } static int init_parse_context(OptionParseContext *octx, @@ -726,7 +738,10 @@ int split_commandline(OptionParseContext *octx, int argc, char *argv[], } /* unnamed group separators, e.g. output filename */ if (opt[0] != '-' || !opt[1] || dashdash+1 == optindex) { - finish_group(octx, 0, opt); + ret = finish_group(octx, 0, opt); + if (ret < 0) + return ret; + av_log(NULL, AV_LOG_DEBUG, " matched as %s.\n", groups[0].name); continue; } @@ -744,7 +759,10 @@ do { \ /* named group separators, e.g. -i */ if ((ret = match_group_separator(groups, nb_groups, opt)) >= 0) { GET_ARG(arg); - finish_group(octx, ret, arg); + ret = finish_group(octx, ret, arg); + if (ret < 0) + return ret; + av_log(NULL, AV_LOG_DEBUG, " matched as %s with argument '%s'.\n", groups[ret].name, arg); continue; @@ -762,7 +780,10 @@ do { \ arg = "1"; } - add_opt(octx, po, opt, arg); + ret = add_opt(octx, po, opt, arg); + if (ret < 0) + return ret; + av_log(NULL, AV_LOG_DEBUG, " matched as option '%s' (%s) with " "argument '%s'.\n", po->name, po->help, arg); continue; @@ -787,7 +808,10 @@ do { \ if (opt[0] == 'n' && opt[1] == 'o' && (po = find_option(options, opt + 2)) && po->name && po->flags & OPT_BOOL) { - add_opt(octx, po, opt, "0"); + ret = add_opt(octx, po, opt, "0"); + if (ret < 0) + return ret; + av_log(NULL, AV_LOG_DEBUG, " matched as option '%s' (%s) with " "argument 0.\n", po->name, po->help); continue; diff --git a/fftools/cmdutils.h b/fftools/cmdutils.h index 0dfe8b313c0..69c21238047 100644 --- a/fftools/cmdutils.h +++ b/fftools/cmdutils.h @@ -440,11 +440,7 @@ int grow_array(void **array, int elem_size, int *size, int new_size); void *allocate_array_elem(void *array, size_t elem_size, int *nb_elems); #define GROW_ARRAY(array, nb_elems)\ -do { \ - int _ret = grow_array((void**)&array, sizeof(*array), &nb_elems, nb_elems + 1); \ - if (_ret < 0) \ - report_and_exit(_ret); \ -} while (0) + grow_array((void**)&array, sizeof(*array), &nb_elems, nb_elems + 1) #define GET_PIX_FMT_NAME(pix_fmt)\ const char *name = av_get_pix_fmt_name(pix_fmt); diff --git a/fftools/ffmpeg_demux.c b/fftools/ffmpeg_demux.c index 72b94ea44fc..5a41db9b21d 100644 --- a/fftools/ffmpeg_demux.c +++ b/fftools/ffmpeg_demux.c @@ -880,7 +880,10 @@ int ist_output_add(InputStream *ist, OutputStream *ost) if (ret < 0) return ret; - GROW_ARRAY(ist->outputs, ist->nb_outputs); + ret = GROW_ARRAY(ist->outputs, ist->nb_outputs); + if (ret < 0) + return ret; + ist->outputs[ist->nb_outputs - 1] = ost; return 0; @@ -894,7 +897,10 @@ int ist_filter_add(InputStream *ist, InputFilter *ifilter, int is_simple) if (ret < 0) return ret; - GROW_ARRAY(ist->filters, ist->nb_filters); + ret = GROW_ARRAY(ist->filters, ist->nb_filters); + if (ret < 0) + return ret; + ist->filters[ist->nb_filters - 1] = ifilter; // initialize fallback parameters for filtering diff --git a/fftools/ffmpeg_mux_init.c b/fftools/ffmpeg_mux_init.c index a45cfa8e61d..eccdae10148 100644 --- a/fftools/ffmpeg_mux_init.c +++ b/fftools/ffmpeg_mux_init.c @@ -208,7 +208,9 @@ static int enc_stats_get_file(AVIOContext **io, const char *path) return 0; } - GROW_ARRAY(enc_stats_files, nb_enc_stats_files); + ret = GROW_ARRAY(enc_stats_files, nb_enc_stats_files); + if (ret < 0) + return ret; esf = &enc_stats_files[nb_enc_stats_files - 1]; @@ -320,7 +322,11 @@ static int enc_stats_init(OutputStream *ost, EncStats *es, int pre, return ret; if (val) { - GROW_ARRAY(es->components, es->nb_components); + ret = GROW_ARRAY(es->components, es->nb_components); + if (ret < 0) { + av_freep(&val); + return ret; + } c = &es->components[es->nb_components - 1]; c->type = ENC_STATS_LITERAL; @@ -351,7 +357,10 @@ static int enc_stats_init(OutputStream *ost, EncStats *es, int pre, } next++; - GROW_ARRAY(es->components, es->nb_components); + ret = GROW_ARRAY(es->components, es->nb_components); + if (ret < 0) + return ret; + c = &es->components[es->nb_components - 1]; for (size_t i = 0; i < FF_ARRAY_ELEMS(fmt_specs); i++) { diff --git a/fftools/ffmpeg_opt.c b/fftools/ffmpeg_opt.c index 70029863692..eef6d5e749f 100644 --- a/fftools/ffmpeg_opt.c +++ b/fftools/ffmpeg_opt.c @@ -361,6 +361,7 @@ static int opt_map(void *optctx, const char *opt, const char *arg) OptionsContext *o = optctx; StreamMap *m = NULL; int i, negative = 0, file_idx, disabled = 0; + int ret; #if FFMPEG_OPT_MAP_SYNC char *sync; #endif @@ -387,7 +388,11 @@ static int opt_map(void *optctx, const char *opt, const char *arg) if (map[0] == '[') { /* this mapping refers to lavfi output */ const char *c = map + 1; - GROW_ARRAY(o->stream_maps, o->nb_stream_maps); + + ret = GROW_ARRAY(o->stream_maps, o->nb_stream_maps); + if (ret < 0) + return ret; + m = &o->stream_maps[o->nb_stream_maps - 1]; m->linklabel = av_get_token(&c, "]"); if (!m->linklabel) { @@ -421,7 +426,10 @@ static int opt_map(void *optctx, const char *opt, const char *arg) disabled = 1; continue; } - GROW_ARRAY(o->stream_maps, o->nb_stream_maps); + ret = GROW_ARRAY(o->stream_maps, o->nb_stream_maps); + if (ret < 0) + return ret; + m = &o->stream_maps[o->nb_stream_maps - 1]; m->file_index = file_idx; @@ -450,7 +458,10 @@ static int opt_map(void *optctx, const char *opt, const char *arg) static int opt_attach(void *optctx, const char *opt, const char *arg) { OptionsContext *o = optctx; - GROW_ARRAY(o->attachments, o->nb_attachments); + int ret = GROW_ARRAY(o->attachments, o->nb_attachments); + if (ret < 0) + return ret; + o->attachments[o->nb_attachments - 1] = arg; return 0; } @@ -459,7 +470,7 @@ static int opt_attach(void *optctx, const char *opt, const char *arg) static int opt_map_channel(void *optctx, const char *opt, const char *arg) { OptionsContext *o = optctx; - int n; + int n, ret; AVStream *st; AudioChannelMap *m; char *allow_unused; @@ -474,7 +485,10 @@ static int opt_map_channel(void *optctx, const char *opt, const char *arg) if (!mapchan) return AVERROR(ENOMEM); - GROW_ARRAY(o->audio_channel_maps, o->nb_audio_channel_maps); + ret = GROW_ARRAY(o->audio_channel_maps, o->nb_audio_channel_maps); + if (ret < 0) + return ret; + m = &o->audio_channel_maps[o->nb_audio_channel_maps - 1]; /* muted channel syntax */ diff --git a/fftools/ffplay.c b/fftools/ffplay.c index 99700dc6f2b..1f9757d6079 100644 --- a/fftools/ffplay.c +++ b/fftools/ffplay.c @@ -388,7 +388,10 @@ static const struct TextureFormatEntry { static int opt_add_vfilter(void *optctx, const char *opt, const char *arg) { - GROW_ARRAY(vfilters_list, nb_vfilters); + int ret = GROW_ARRAY(vfilters_list, nb_vfilters); + if (ret < 0) + return ret; + vfilters_list[nb_vfilters - 1] = arg; return 0; } From 6c6f13baf3649bd4e59bd1054721c2257f8c3159 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Fri, 14 Jul 2023 13:47:23 +0200 Subject: [PATCH 1950/2172] fftools/ffmpeg: return errors from find_codec_or_die() instead of aborting Rename the function to just find_codec(). --- fftools/ffmpeg.h | 4 +-- fftools/ffmpeg_demux.c | 54 +++++++++++++++++++++++++++------------ fftools/ffmpeg_mux_init.c | 4 ++- fftools/ffmpeg_opt.c | 13 ++++++---- 4 files changed, 50 insertions(+), 25 deletions(-) diff --git a/fftools/ffmpeg.h b/fftools/ffmpeg.h index 0e5e1561f5f..67a6bcbc8b9 100644 --- a/fftools/ffmpeg.h +++ b/fftools/ffmpeg.h @@ -709,8 +709,8 @@ void assert_avoptions(AVDictionary *m); int assert_file_overwrite(const char *filename); char *file_read(const char *filename); AVDictionary *strip_specifiers(const AVDictionary *dict); -const AVCodec *find_codec_or_die(void *logctx, const char *name, - enum AVMediaType type, int encoder); +int find_codec(void *logctx, const char *name, + enum AVMediaType type, int encoder, const AVCodec **codec); int parse_and_set_vsync(const char *arg, int *vsync_var, int file_idx, int st_idx, int is_global); int check_filter_outputs(void); diff --git a/fftools/ffmpeg_demux.c b/fftools/ffmpeg_demux.c index 5a41db9b21d..a41b59ceb87 100644 --- a/fftools/ffmpeg_demux.c +++ b/fftools/ffmpeg_demux.c @@ -911,19 +911,22 @@ int ist_filter_add(InputStream *ist, InputFilter *ifilter, int is_simple) return 0; } -static const AVCodec *choose_decoder(const OptionsContext *o, AVFormatContext *s, AVStream *st, - enum HWAccelID hwaccel_id, enum AVHWDeviceType hwaccel_device_type) +static int choose_decoder(const OptionsContext *o, AVFormatContext *s, AVStream *st, + enum HWAccelID hwaccel_id, enum AVHWDeviceType hwaccel_device_type, + const AVCodec **pcodec) { char *codec_name = NULL; MATCH_PER_STREAM_OPT(codec_names, str, codec_name, s, st); if (codec_name) { - const AVCodec *codec = find_codec_or_die(NULL, codec_name, st->codecpar->codec_type, 0); - st->codecpar->codec_id = codec->id; - if (recast_media && st->codecpar->codec_type != codec->type) - st->codecpar->codec_type = codec->type; - return codec; + int ret = find_codec(NULL, codec_name, st->codecpar->codec_type, 0, pcodec); + if (ret < 0) + return ret; + st->codecpar->codec_id = (*pcodec)->id; + if (recast_media && st->codecpar->codec_type != (*pcodec)->type) + st->codecpar->codec_type = (*pcodec)->type; + return 0; } else { if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO && hwaccel_id == HWACCEL_GENERIC && @@ -942,13 +945,15 @@ static const AVCodec *choose_decoder(const OptionsContext *o, AVFormatContext *s if (config->device_type == hwaccel_device_type) { av_log(NULL, AV_LOG_VERBOSE, "Selecting decoder '%s' because of requested hwaccel method %s\n", c->name, av_hwdevice_get_type_name(hwaccel_device_type)); - return c; + *pcodec = c; + return 0; } } } } - return avcodec_find_decoder(st->codecpar->codec_id); + *pcodec = avcodec_find_decoder(st->codecpar->codec_id); + return 0; } } @@ -1166,7 +1171,11 @@ static int ist_add(const OptionsContext *o, Demuxer *d, AVStream *st) } } - ist->dec = choose_decoder(o, ic, st, ist->hwaccel_id, ist->hwaccel_device_type); + ret = choose_decoder(o, ic, st, ist->hwaccel_id, ist->hwaccel_device_type, + &ist->dec); + if (ret < 0) + return ret; + ist->decoder_opts = filter_codec_opts(o->g->codec_opts, ist->st->codecpar->codec_id, ic, st, ist->dec); ist->reinit_filters = -1; @@ -1357,7 +1366,7 @@ int ifile_open(const OptionsContext *o, const char *filename) InputFile *f; AVFormatContext *ic; const AVInputFormat *file_iformat = NULL; - int err, i, ret; + int err, i, ret = 0; int64_t timestamp; AVDictionary *unused_opts = NULL; const AVDictionaryEntry *e = NULL; @@ -1455,13 +1464,19 @@ int ifile_open(const OptionsContext *o, const char *filename) MATCH_PER_TYPE_OPT(codec_names, str, data_codec_name, ic, "d"); if (video_codec_name) - ic->video_codec = find_codec_or_die(NULL, video_codec_name , AVMEDIA_TYPE_VIDEO , 0); + ret = err_merge(ret, find_codec(NULL, video_codec_name , AVMEDIA_TYPE_VIDEO , 0, + &ic->video_codec)); if (audio_codec_name) - ic->audio_codec = find_codec_or_die(NULL, audio_codec_name , AVMEDIA_TYPE_AUDIO , 0); + ret = err_merge(ret, find_codec(NULL, audio_codec_name , AVMEDIA_TYPE_AUDIO , 0, + &ic->audio_codec)); if (subtitle_codec_name) - ic->subtitle_codec = find_codec_or_die(NULL, subtitle_codec_name, AVMEDIA_TYPE_SUBTITLE, 0); + ret = err_merge(ret, find_codec(NULL, subtitle_codec_name, AVMEDIA_TYPE_SUBTITLE, 0, + &ic->subtitle_codec)); if (data_codec_name) - ic->data_codec = find_codec_or_die(NULL, data_codec_name , AVMEDIA_TYPE_DATA , 0); + ret = err_merge(ret, find_codec(NULL, data_codec_name , AVMEDIA_TYPE_DATA, 0, + &ic->data_codec)); + if (ret < 0) + return ret; ic->video_codec_id = video_codec_name ? ic->video_codec->id : AV_CODEC_ID_NONE; ic->audio_codec_id = audio_codec_name ? ic->audio_codec->id : AV_CODEC_ID_NONE; @@ -1496,8 +1511,13 @@ int ifile_open(const OptionsContext *o, const char *filename) assert_avoptions(o->g->format_opts); /* apply forced codec ids */ - for (i = 0; i < ic->nb_streams; i++) - choose_decoder(o, ic, ic->streams[i], HWACCEL_NONE, AV_HWDEVICE_TYPE_NONE); + for (i = 0; i < ic->nb_streams; i++) { + const AVCodec *dummy; + ret = choose_decoder(o, ic, ic->streams[i], HWACCEL_NONE, AV_HWDEVICE_TYPE_NONE, + &dummy); + if (ret < 0) + return ret; + } if (o->find_stream_info) { AVDictionary **opts; diff --git a/fftools/ffmpeg_mux_init.c b/fftools/ffmpeg_mux_init.c index eccdae10148..6a8a1c7b637 100644 --- a/fftools/ffmpeg_mux_init.c +++ b/fftools/ffmpeg_mux_init.c @@ -139,7 +139,9 @@ static int choose_encoder(const OptionsContext *o, AVFormatContext *s, return AVERROR_ENCODER_NOT_FOUND; } } else if (strcmp(codec_name, "copy")) { - *enc = find_codec_or_die(ost, codec_name, ost->type, 1); + int ret = find_codec(ost, codec_name, ost->type, 1, enc); + if (ret < 0) + return ret; ost->par_in->codec_id = (*enc)->id; } diff --git a/fftools/ffmpeg_opt.c b/fftools/ffmpeg_opt.c index eef6d5e749f..5a5a26d0a52 100644 --- a/fftools/ffmpeg_opt.c +++ b/fftools/ffmpeg_opt.c @@ -637,8 +637,8 @@ static int opt_recording_timestamp(void *optctx, const char *opt, const char *ar return 0; } -const AVCodec *find_codec_or_die(void *logctx, const char *name, - enum AVMediaType type, int encoder) +int find_codec(void *logctx, const char *name, + enum AVMediaType type, int encoder, const AVCodec **pcodec) { const AVCodecDescriptor *desc; const char *codec_string = encoder ? "encoder" : "decoder"; @@ -658,13 +658,16 @@ const AVCodec *find_codec_or_die(void *logctx, const char *name, if (!codec) { av_log(logctx, AV_LOG_FATAL, "Unknown %s '%s'\n", codec_string, name); - exit_program(1); + return encoder ? AVERROR_ENCODER_NOT_FOUND : + AVERROR_DECODER_NOT_FOUND; } if (codec->type != type && !recast_media) { av_log(logctx, AV_LOG_FATAL, "Invalid %s type '%s'\n", codec_string, name); - exit_program(1); + return AVERROR(EINVAL); } - return codec; + + *pcodec = codec; + return 0;; } int assert_file_overwrite(const char *filename) From a50f90f1c23e9b10248add652f255618bb1063ee Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Fri, 14 Jul 2023 13:49:49 +0200 Subject: [PATCH 1951/2172] fftools/ffmpeg_opt: replace exit_program() with returning error codes --- fftools/ffmpeg_opt.c | 49 ++++++++++++++++++++++++++------------------ 1 file changed, 29 insertions(+), 20 deletions(-) diff --git a/fftools/ffmpeg_opt.c b/fftools/ffmpeg_opt.c index 5a5a26d0a52..293397a8b79 100644 --- a/fftools/ffmpeg_opt.c +++ b/fftools/ffmpeg_opt.c @@ -190,7 +190,7 @@ int parse_and_set_vsync(const char *arg, int *vsync_var, int file_idx, int st_id else if (!is_global && !av_strcasecmp(arg, "auto")) *vsync_var = VSYNC_AUTO; else if (!is_global) { av_log(NULL, AV_LOG_FATAL, "Invalid value %s specified for fps_mode of #%d:%d.\n", arg, file_idx, st_idx); - exit_program(1); + return AVERROR(EINVAL); } if (is_global && *vsync_var == VSYNC_AUTO) { @@ -250,12 +250,12 @@ static int apply_sync_offsets(void) if (self->input_sync_ref == -1 || self->input_sync_ref == i) continue; if (self->input_sync_ref >= nb_input_files || self->input_sync_ref < -1) { av_log(NULL, AV_LOG_FATAL, "-isync for input %d references non-existent input %d.\n", i, self->input_sync_ref); - exit_program(1); + return AVERROR(EINVAL); } if (copy_ts && !start_at_zero) { av_log(NULL, AV_LOG_FATAL, "Use of -isync requires that start_at_zero be set if copyts is set.\n"); - exit_program(1); + return AVERROR(EINVAL); } ref = input_files[self->input_sync_ref]; @@ -397,7 +397,7 @@ static int opt_map(void *optctx, const char *opt, const char *arg) m->linklabel = av_get_token(&c, "]"); if (!m->linklabel) { av_log(NULL, AV_LOG_ERROR, "Invalid output link label: %s.\n", map); - exit_program(1); + return AVERROR(EINVAL); } } else { if (allow_unused = strchr(map, '?')) @@ -405,7 +405,7 @@ static int opt_map(void *optctx, const char *opt, const char *arg) file_idx = strtol(map, &p, 0); if (file_idx >= nb_input_files || file_idx < 0) { av_log(NULL, AV_LOG_FATAL, "Invalid input file index: %d.\n", file_idx); - exit_program(1); + return AVERROR(EINVAL); } if (negative) /* disable some already defined maps */ @@ -443,11 +443,11 @@ static int opt_map(void *optctx, const char *opt, const char *arg) } else if (disabled) { av_log(NULL, AV_LOG_FATAL, "Stream map '%s' matches disabled streams.\n" "To ignore this, add a trailing '?' to the map.\n", arg); - exit_program(1); + return AVERROR(EINVAL); } else { av_log(NULL, AV_LOG_FATAL, "Stream map '%s' matches no streams.\n" "To ignore this, add a trailing '?' to the map.\n", arg); - exit_program(1); + return AVERROR(EINVAL); } } @@ -509,7 +509,7 @@ static int opt_map_channel(void *optctx, const char *opt, const char *arg) if (n != 3 && n != 5) { av_log(NULL, AV_LOG_FATAL, "Syntax error, mapchan usage: " "[file.stream.channel|-1][:syncfile:syncstream]\n"); - exit_program(1); + goto fail; } if (n != 5) // only file.stream.channel specified @@ -519,19 +519,19 @@ static int opt_map_channel(void *optctx, const char *opt, const char *arg) if (m->file_idx < 0 || m->file_idx >= nb_input_files) { av_log(NULL, AV_LOG_FATAL, "mapchan: invalid input file index: %d\n", m->file_idx); - exit_program(1); + goto fail; } if (m->stream_idx < 0 || m->stream_idx >= input_files[m->file_idx]->nb_streams) { av_log(NULL, AV_LOG_FATAL, "mapchan: invalid input file stream index #%d.%d\n", m->file_idx, m->stream_idx); - exit_program(1); + goto fail; } st = input_files[m->file_idx]->ctx->streams[m->stream_idx]; if (st->codecpar->codec_type != AVMEDIA_TYPE_AUDIO) { av_log(NULL, AV_LOG_FATAL, "mapchan: stream #%d.%d is not an audio stream.\n", m->file_idx, m->stream_idx); - exit_program(1); + goto fail; } /* allow trailing ? to map_channel */ if (allow_unused = strchr(mapchan, '?')) @@ -545,12 +545,15 @@ static int opt_map_channel(void *optctx, const char *opt, const char *arg) av_log(NULL, AV_LOG_FATAL, "mapchan: invalid audio channel #%d.%d.%d\n" "To ignore this, add a trailing '?' to the map_channel.\n", m->file_idx, m->stream_idx, m->channel_idx); - exit_program(1); + goto fail; } } av_free(mapchan); return 0; +fail: + av_free(mapchan); + return AVERROR(EINVAL); } #endif @@ -602,7 +605,7 @@ static int opt_init_hw_device(void *optctx, const char *opt, const char *arg) AV_HWDEVICE_TYPE_NONE) printf("%s\n", av_hwdevice_get_type_name(type)); printf("\n"); - exit_program(0); + return AVERROR_EXIT; } else { return hw_device_init_from_string(arg, NULL); } @@ -819,7 +822,7 @@ static int opt_target(void *optctx, const char *opt, const char *arg) av_log(NULL, AV_LOG_FATAL, "Could not determine norm (PAL/NTSC/NTSC-Film) for target.\n"); av_log(NULL, AV_LOG_FATAL, "Please prefix target with \"pal-\", \"ntsc-\" or \"film-\",\n"); av_log(NULL, AV_LOG_FATAL, "or set a framerate with \"-r xxx\".\n"); - exit_program(1); + return AVERROR(EINVAL); } if (!strcmp(arg, "vcd")) { @@ -931,7 +934,7 @@ static int opt_vstats(void *optctx, const char *opt, const char *arg) if (!today) { // maybe tomorrow av_log(NULL, AV_LOG_FATAL, "Unable to get current time: %s\n", strerror(errno)); - exit_program(1); + return AVERROR(errno); } snprintf(filename, sizeof(filename), "vstats_%02d%02d%02d.log", today->tm_hour, today->tm_min, @@ -983,6 +986,7 @@ static int opt_preset(void *optctx, const char *opt, const char *arg) FILE *f=NULL; char filename[1000], line[1000], tmp_line[1000]; const char *codec_name = NULL; + int ret = 0; tmp_line[0] = *opt; tmp_line[1] = 0; @@ -993,7 +997,7 @@ static int opt_preset(void *optctx, const char *opt, const char *arg) av_log(NULL, AV_LOG_FATAL, "Please use -preset -qp 0\n"); }else av_log(NULL, AV_LOG_FATAL, "File for preset '%s' not found\n", arg); - exit_program(1); + return AVERROR(ENOENT); } while (fgets(line, sizeof(line), f)) { @@ -1005,7 +1009,8 @@ static int opt_preset(void *optctx, const char *opt, const char *arg) if (!av_strtok(key, "=", &value) || !av_strtok(value, "\r\n", &endptr)) { av_log(NULL, AV_LOG_FATAL, "%s: Invalid syntax: '%s'\n", filename, line); - exit_program(1); + ret = AVERROR(EINVAL); + goto fail; } av_log(NULL, AV_LOG_DEBUG, "ffpreset[%s]: set '%s' = '%s'\n", filename, key, value); @@ -1016,13 +1021,15 @@ static int opt_preset(void *optctx, const char *opt, const char *arg) else if (opt_default_new(o, key, value) < 0) { av_log(NULL, AV_LOG_FATAL, "%s: Invalid option or argument: '%s', parsed as '%s' = '%s'\n", filename, line, key, value); - exit_program(1); + ret = AVERROR(EINVAL); + goto fail; } } +fail: fclose(f); - return 0; + return ret; } static int opt_old2new(void *optctx, const char *opt, const char *arg) @@ -1310,7 +1317,9 @@ int ffmpeg_parse_options(int argc, char **argv) correct_input_start_times(); - apply_sync_offsets(); + ret = apply_sync_offsets(); + if (ret < 0) + goto fail; ret = check_filter_outputs(); if (ret < 0) From 4adbe2d219c13d5342d073aace5001a64c57d9c8 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Fri, 14 Jul 2023 13:49:49 +0200 Subject: [PATCH 1952/2172] fftools/opt_common: replace exit_program() with returning error codes --- fftools/opt_common.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/fftools/opt_common.c b/fftools/opt_common.c index f6fe9815e1e..39258bb46c3 100644 --- a/fftools/opt_common.c +++ b/fftools/opt_common.c @@ -1159,7 +1159,9 @@ int init_report(const char *env, FILE **file) report_file_level = strtol(val, &tail, 10); if (*tail) { av_log(NULL, AV_LOG_FATAL, "Invalid report file level\n"); - exit_program(1); + av_free(key); + av_free(val); + return AVERROR(EINVAL); } envlevel = 1; } else { @@ -1219,7 +1221,7 @@ int opt_max_alloc(void *optctx, const char *opt, const char *arg) max = strtol(arg, &tail, 10); if (*tail) { av_log(NULL, AV_LOG_FATAL, "Invalid max_alloc \"%s\".\n", arg); - exit_program(1); + return AVERROR(EINVAL); } av_max_alloc(max); return 0; @@ -1293,7 +1295,7 @@ int opt_loglevel(void *optctx, const char *opt, const char *arg) "Possible levels are numbers or:\n", arg); for (i = 0; i < FF_ARRAY_ELEMS(log_levels); i++) av_log(NULL, AV_LOG_FATAL, "\"%s\"\n", log_levels[i].name); - exit_program(1); + return AVERROR(EINVAL); } end: From 9cb47c78d66c0d8abf5dbedd254d3761d5c5b06a Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Fri, 14 Jul 2023 13:47:23 +0200 Subject: [PATCH 1953/2172] fftools: return errors from parse_number_or_die() instead of aborting Rename the function to just parse_number(). --- fftools/cmdutils.c | 39 +++++++++++++++++++++++++++++---------- fftools/cmdutils.h | 6 ++---- fftools/ffmpeg_mux_init.c | 7 +++++-- fftools/ffmpeg_opt.c | 23 ++++++++++++++++++----- fftools/ffplay.c | 25 +++++++++++++++++++++---- fftools/ffprobe.c | 10 ++++++++-- 6 files changed, 83 insertions(+), 27 deletions(-) diff --git a/fftools/cmdutils.c b/fftools/cmdutils.c index fb35245f0a0..8afa9400cc9 100644 --- a/fftools/cmdutils.c +++ b/fftools/cmdutils.c @@ -104,8 +104,8 @@ void exit_program(int ret) exit(ret); } -double parse_number_or_die(const char *context, const char *numstr, int type, - double min, double max) +int parse_number(const char *context, const char *numstr, int type, + double min, double max, double *dst) { char *tail; const char *error; @@ -118,11 +118,13 @@ double parse_number_or_die(const char *context, const char *numstr, int type, error = "Expected int64 for %s but found %s\n"; else if (type == OPT_INT && (int)d != d) error = "Expected int for %s but found %s\n"; - else - return d; + else { + *dst = d; + return 0; + } + av_log(NULL, AV_LOG_FATAL, error, context, numstr, min, max); - exit_program(1); - return 0; + return AVERROR(EINVAL); } int64_t parse_time_or_die(const char *context, const char *timestr, @@ -262,6 +264,7 @@ static int write_option(void *optctx, const OptionDef *po, const char *opt, void *dst = po->flags & (OPT_OFFSET | OPT_SPEC) ? (uint8_t *)optctx + po->u.off : po->u.dst_ptr; int *dstcount; + double num; int ret; if (po->flags & OPT_SPEC) { @@ -289,15 +292,31 @@ static int write_option(void *optctx, const OptionDef *po, const char *opt, return AVERROR(ENOMEM); *(char **)dst = str; } else if (po->flags & OPT_BOOL || po->flags & OPT_INT) { - *(int *)dst = parse_number_or_die(opt, arg, OPT_INT64, INT_MIN, INT_MAX); + ret = parse_number(opt, arg, OPT_INT64, INT_MIN, INT_MAX, &num); + if (ret < 0) + return ret; + + *(int *)dst = num; } else if (po->flags & OPT_INT64) { - *(int64_t *)dst = parse_number_or_die(opt, arg, OPT_INT64, INT64_MIN, INT64_MAX); + ret = parse_number(opt, arg, OPT_INT64, INT64_MIN, INT64_MAX, &num); + if (ret < 0) + return ret; + + *(int64_t *)dst = num; } else if (po->flags & OPT_TIME) { *(int64_t *)dst = parse_time_or_die(opt, arg, 1); } else if (po->flags & OPT_FLOAT) { - *(float *)dst = parse_number_or_die(opt, arg, OPT_FLOAT, -INFINITY, INFINITY); + ret = parse_number(opt, arg, OPT_FLOAT, -INFINITY, INFINITY, &num); + if (ret < 0) + return ret; + + *(float *)dst = num; } else if (po->flags & OPT_DOUBLE) { - *(double *)dst = parse_number_or_die(opt, arg, OPT_DOUBLE, -INFINITY, INFINITY); + ret = parse_number(opt, arg, OPT_DOUBLE, -INFINITY, INFINITY, &num); + if (ret < 0) + return ret; + + *(double *)dst = num; } else if (po->u.func_arg) { int ret = po->u.func_arg(optctx, opt, arg); if (ret < 0) { diff --git a/fftools/cmdutils.h b/fftools/cmdutils.h index 69c21238047..dedf4de8ddf 100644 --- a/fftools/cmdutils.h +++ b/fftools/cmdutils.h @@ -100,8 +100,6 @@ int opt_timelimit(void *optctx, const char *opt, const char *arg); /** * Parse a string and return its corresponding value as a double. - * Exit from the application if the string cannot be correctly - * parsed or the corresponding value is invalid. * * @param context the context of the value to be set (e.g. the * corresponding command line option name) @@ -111,8 +109,8 @@ int opt_timelimit(void *optctx, const char *opt, const char *arg); * @param min the minimum valid accepted value * @param max the maximum valid accepted value */ -double parse_number_or_die(const char *context, const char *numstr, int type, - double min, double max); +int parse_number(const char *context, const char *numstr, int type, + double min, double max, double *dst); /** * Parse a string specifying a time and return its corresponding diff --git a/fftools/ffmpeg_mux_init.c b/fftools/ffmpeg_mux_init.c index 6a8a1c7b637..f83a3ae2bb2 100644 --- a/fftools/ffmpeg_mux_init.c +++ b/fftools/ffmpeg_mux_init.c @@ -784,8 +784,11 @@ static int new_stream_video(Muxer *mux, const OptionsContext *o, ost->vsync_method = video_sync_method; MATCH_PER_STREAM_OPT(fps_mode, str, fps_mode, oc, st); - if (fps_mode) - parse_and_set_vsync(fps_mode, &ost->vsync_method, ost->file_index, ost->index, 0); + if (fps_mode) { + ret = parse_and_set_vsync(fps_mode, &ost->vsync_method, ost->file_index, ost->index, 0); + if (ret < 0) + return ret; + } if ((ost->frame_rate.num || ost->max_frame_rate.num) && !(ost->vsync_method == VSYNC_AUTO || diff --git a/fftools/ffmpeg_opt.c b/fftools/ffmpeg_opt.c index 293397a8b79..e1696cdd598 100644 --- a/fftools/ffmpeg_opt.c +++ b/fftools/ffmpeg_opt.c @@ -194,7 +194,14 @@ int parse_and_set_vsync(const char *arg, int *vsync_var, int file_idx, int st_id } if (is_global && *vsync_var == VSYNC_AUTO) { - video_sync_method = parse_number_or_die("vsync", arg, OPT_INT, VSYNC_AUTO, VSYNC_VFR); + int ret; + double num; + + ret = parse_number("vsync", arg, OPT_INT, VSYNC_AUTO, VSYNC_VFR, &num); + if (ret < 0) + return ret; + + video_sync_method = num; av_log(NULL, AV_LOG_WARNING, "Passing a number to -vsync is deprecated," " use a string argument as described in the manual.\n"); } @@ -1104,8 +1111,7 @@ static int opt_audio_filters(void *optctx, const char *opt, const char *arg) static int opt_vsync(void *optctx, const char *opt, const char *arg) { av_log(NULL, AV_LOG_WARNING, "-vsync is deprecated. Use -fps_mode\n"); - parse_and_set_vsync(arg, &video_sync_method, -1, -1, 1); - return 0; + return parse_and_set_vsync(arg, &video_sync_method, -1, -1, 1); } static int opt_timecode(void *optctx, const char *opt, const char *arg) @@ -1353,8 +1359,15 @@ static int opt_progress(void *optctx, const char *opt, const char *arg) int opt_timelimit(void *optctx, const char *opt, const char *arg) { #if HAVE_SETRLIMIT - int lim = parse_number_or_die(opt, arg, OPT_INT64, 0, INT_MAX); - struct rlimit rl = { lim, lim + 1 }; + int ret; + double lim; + struct rlimit rl; + + ret = parse_number(opt, arg, OPT_INT64, 0, INT_MAX, &lim); + if (ret < 0) + return ret; + + rl = (struct rlimit){ lim, lim + 1 }; if (setrlimit(RLIMIT_CPU, &rl)) perror("setrlimit"); #else diff --git a/fftools/ffplay.c b/fftools/ffplay.c index 1f9757d6079..6ca1ad98bf2 100644 --- a/fftools/ffplay.c +++ b/fftools/ffplay.c @@ -3440,13 +3440,23 @@ static void event_loop(VideoState *cur_stream) static int opt_width(void *optctx, const char *opt, const char *arg) { - screen_width = parse_number_or_die(opt, arg, OPT_INT64, 1, INT_MAX); + double num; + int ret = parse_number(opt, arg, OPT_INT64, 1, INT_MAX, &num); + if (ret < 0) + return ret; + + screen_width = num; return 0; } static int opt_height(void *optctx, const char *opt, const char *arg) { - screen_height = parse_number_or_die(opt, arg, OPT_INT64, 1, INT_MAX); + double num; + int ret = parse_number(opt, arg, OPT_INT64, 1, INT_MAX, &num); + if (ret < 0) + return ret; + + screen_height = num; return 0; } @@ -3491,8 +3501,15 @@ static int opt_show_mode(void *optctx, const char *opt, const char *arg) { show_mode = !strcmp(arg, "video") ? SHOW_MODE_VIDEO : !strcmp(arg, "waves") ? SHOW_MODE_WAVES : - !strcmp(arg, "rdft" ) ? SHOW_MODE_RDFT : - parse_number_or_die(opt, arg, OPT_INT, 0, SHOW_MODE_NB-1); + !strcmp(arg, "rdft" ) ? SHOW_MODE_RDFT : SHOW_MODE_NONE; + + if (show_mode == SHOW_MODE_NONE) { + double num; + int ret = parse_number(opt, arg, OPT_INT, 0, SHOW_MODE_NB-1, &num); + if (ret < 0) + return ret; + show_mode = num; + } return 0; } diff --git a/fftools/ffprobe.c b/fftools/ffprobe.c index 91a3be660bf..e6fd33492d6 100644 --- a/fftools/ffprobe.c +++ b/fftools/ffprobe.c @@ -3665,8 +3665,14 @@ static int opt_show_optional_fields(void *optctx, const char *opt, const char *a else if (!av_strcasecmp(arg, "never")) show_optional_fields = SHOW_OPTIONAL_FIELDS_NEVER; else if (!av_strcasecmp(arg, "auto")) show_optional_fields = SHOW_OPTIONAL_FIELDS_AUTO; - if (show_optional_fields == SHOW_OPTIONAL_FIELDS_AUTO && av_strcasecmp(arg, "auto")) - show_optional_fields = parse_number_or_die("show_optional_fields", arg, OPT_INT, SHOW_OPTIONAL_FIELDS_AUTO, SHOW_OPTIONAL_FIELDS_ALWAYS); + if (show_optional_fields == SHOW_OPTIONAL_FIELDS_AUTO && av_strcasecmp(arg, "auto")) { + double num; + int ret = parse_number("show_optional_fields", arg, OPT_INT, + SHOW_OPTIONAL_FIELDS_AUTO, SHOW_OPTIONAL_FIELDS_ALWAYS, &num); + if (ret < 0) + return ret; + show_optional_fields = num; + } return 0; } From 49ac7fc48566a5cc33c0cd1a2806251fddb52a03 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Fri, 14 Jul 2023 16:37:19 +0200 Subject: [PATCH 1954/2172] fftools: remove parse_time_or_die() Replace it with calling av_parse_time() directly, which provides graceful error handling and more accurate error messages. --- fftools/cmdutils.c | 19 ++++++------------- fftools/cmdutils.h | 17 ----------------- fftools/ffmpeg_mux_init.c | 30 ++++++++++++++++++++++++------ fftools/ffmpeg_opt.c | 17 ++++++++++++++--- fftools/ffplay.c | 16 ++-------------- 5 files changed, 46 insertions(+), 53 deletions(-) diff --git a/fftools/cmdutils.c b/fftools/cmdutils.c index 8afa9400cc9..038a5d33407 100644 --- a/fftools/cmdutils.c +++ b/fftools/cmdutils.c @@ -127,18 +127,6 @@ int parse_number(const char *context, const char *numstr, int type, return AVERROR(EINVAL); } -int64_t parse_time_or_die(const char *context, const char *timestr, - int is_duration) -{ - int64_t us; - if (av_parse_time(&us, timestr, is_duration) < 0) { - av_log(NULL, AV_LOG_FATAL, "Invalid %s specification for %s: %s\n", - is_duration ? "duration" : "date", context, timestr); - exit_program(1); - } - return us; -} - void show_help_options(const OptionDef *options, const char *msg, int req_flags, int rej_flags, int alt_flags) { @@ -304,7 +292,12 @@ static int write_option(void *optctx, const OptionDef *po, const char *opt, *(int64_t *)dst = num; } else if (po->flags & OPT_TIME) { - *(int64_t *)dst = parse_time_or_die(opt, arg, 1); + ret = av_parse_time(dst, arg, 1); + if (ret < 0) { + av_log(NULL, AV_LOG_ERROR, "Invalid duration for option %s: %s\n", + opt, arg); + return ret; + } } else if (po->flags & OPT_FLOAT) { ret = parse_number(opt, arg, OPT_FLOAT, -INFINITY, INFINITY, &num); if (ret < 0) diff --git a/fftools/cmdutils.h b/fftools/cmdutils.h index dedf4de8ddf..ff1b0f2e844 100644 --- a/fftools/cmdutils.h +++ b/fftools/cmdutils.h @@ -112,23 +112,6 @@ int opt_timelimit(void *optctx, const char *opt, const char *arg); int parse_number(const char *context, const char *numstr, int type, double min, double max, double *dst); -/** - * Parse a string specifying a time and return its corresponding - * value as a number of microseconds. Exit from the application if - * the string cannot be correctly parsed. - * - * @param context the context of the value to be set (e.g. the - * corresponding command line option name) - * @param timestr the string to be parsed - * @param is_duration a flag which tells how to interpret timestr, if - * not zero timestr is interpreted as a duration, otherwise as a - * date - * - * @see av_parse_time() - */ -int64_t parse_time_or_die(const char *context, const char *timestr, - int is_duration); - typedef struct SpecifierOpt { char *specifier; /**< stream/chapter/program/... specifier */ union { diff --git a/fftools/ffmpeg_mux_init.c b/fftools/ffmpeg_mux_init.c index f83a3ae2bb2..da304ee7271 100644 --- a/fftools/ffmpeg_mux_init.c +++ b/fftools/ffmpeg_mux_init.c @@ -2399,11 +2399,11 @@ static int compare_int64(const void *a, const void *b) return FFDIFFSIGN(*(const int64_t *)a, *(const int64_t *)b); } -static int parse_forced_key_frames(KeyframeForceCtx *kf, const Muxer *mux, - const char *spec) +static int parse_forced_key_frames(void *log, KeyframeForceCtx *kf, + const Muxer *mux, const char *spec) { const char *p; - int n = 1, i, size, index = 0; + int n = 1, i, ret, size, index = 0; int64_t t, *pts; for (p = spec; *p; p++) @@ -2430,7 +2430,16 @@ static int parse_forced_key_frames(KeyframeForceCtx *kf, const Muxer *mux, !(pts = av_realloc_f(pts, size += nb_ch - 1, sizeof(*pts)))) return AVERROR(ENOMEM); - t = p[8] ? parse_time_or_die("force_key_frames", p + 8, 1) : 0; + + if (p[8]) { + ret = av_parse_time(&t, p + 8, 1); + if (ret < 0) { + av_log(log, AV_LOG_ERROR, + "Invalid chapter time offset: %s\n", p + 8); + goto fail; + } + } else + t = 0; for (j = 0; j < nb_ch; j++) { const AVChapter *c = ch[j]; @@ -2441,7 +2450,13 @@ static int parse_forced_key_frames(KeyframeForceCtx *kf, const Muxer *mux, } else { av_assert1(index < size); - pts[index++] = parse_time_or_die("force_key_frames", p, 1); + ret = av_parse_time(&t, p, 1); + if (ret < 0) { + av_log(log, AV_LOG_ERROR, "Invalid keyframe time: %s\n", p); + goto fail; + } + + pts[index++] = t; } p = next; @@ -2453,6 +2468,9 @@ static int parse_forced_key_frames(KeyframeForceCtx *kf, const Muxer *mux, kf->pts = pts; return 0; +fail: + av_freep(&pts); + return ret; } static int process_forced_keyframes(Muxer *mux, const OptionsContext *o) @@ -2487,7 +2505,7 @@ static int process_forced_keyframes(Muxer *mux, const OptionsContext *o) } else if (!strcmp(forced_keyframes, "source_no_drop")) { ost->kf.type = KF_FORCE_SOURCE_NO_DROP; } else { - int ret = parse_forced_key_frames(&ost->kf, mux, forced_keyframes); + int ret = parse_forced_key_frames(ost, &ost->kf, mux, forced_keyframes); if (ret < 0) return ret; } diff --git a/fftools/ffmpeg_opt.c b/fftools/ffmpeg_opt.c index e1696cdd598..44a6b49ed7d 100644 --- a/fftools/ffmpeg_opt.c +++ b/fftools/ffmpeg_opt.c @@ -326,7 +326,10 @@ static int opt_abort_on(void *optctx, const char *opt, const char *arg) static int opt_stats_period(void *optctx, const char *opt, const char *arg) { - int64_t user_stats_period = parse_time_or_die(opt, arg, 1); + int64_t user_stats_period; + int ret = av_parse_time(&user_stats_period, arg, 1); + if (ret < 0) + return ret; if (user_stats_period <= 0) { av_log(NULL, AV_LOG_ERROR, "stats_period %s must be positive.\n", arg); @@ -636,8 +639,16 @@ static int opt_recording_timestamp(void *optctx, const char *opt, const char *ar { OptionsContext *o = optctx; char buf[128]; - int64_t recording_timestamp = parse_time_or_die(opt, arg, 0) / 1E6; - struct tm time = *gmtime((time_t*)&recording_timestamp); + int64_t recording_timestamp; + int ret; + struct tm time; + + ret = av_parse_time(&recording_timestamp, arg, 0); + if (ret < 0) + return ret; + + recording_timestamp /= 1e6; + time = *gmtime((time_t*)&recording_timestamp); if (!strftime(buf, sizeof(buf), "creation_time=%Y-%m-%dT%H:%M:%S%z", &time)) return -1; parse_option(o, "metadata", buf, options); diff --git a/fftools/ffplay.c b/fftools/ffplay.c index 6ca1ad98bf2..89cea4d876b 100644 --- a/fftools/ffplay.c +++ b/fftools/ffplay.c @@ -3485,18 +3485,6 @@ static int opt_sync(void *optctx, const char *opt, const char *arg) return 0; } -static int opt_seek(void *optctx, const char *opt, const char *arg) -{ - start_time = parse_time_or_die(opt, arg, 1); - return 0; -} - -static int opt_duration(void *optctx, const char *opt, const char *arg) -{ - duration = parse_time_or_die(opt, arg, 1); - return 0; -} - static int opt_show_mode(void *optctx, const char *opt, const char *arg) { show_mode = !strcmp(arg, "video") ? SHOW_MODE_VIDEO : @@ -3561,8 +3549,8 @@ static const OptionDef options[] = { { "ast", OPT_STRING | HAS_ARG | OPT_EXPERT, { &wanted_stream_spec[AVMEDIA_TYPE_AUDIO] }, "select desired audio stream", "stream_specifier" }, { "vst", OPT_STRING | HAS_ARG | OPT_EXPERT, { &wanted_stream_spec[AVMEDIA_TYPE_VIDEO] }, "select desired video stream", "stream_specifier" }, { "sst", OPT_STRING | HAS_ARG | OPT_EXPERT, { &wanted_stream_spec[AVMEDIA_TYPE_SUBTITLE] }, "select desired subtitle stream", "stream_specifier" }, - { "ss", HAS_ARG, { .func_arg = opt_seek }, "seek to a given position in seconds", "pos" }, - { "t", HAS_ARG, { .func_arg = opt_duration }, "play \"duration\" seconds of audio/video", "duration" }, + { "ss", HAS_ARG | OPT_TIME, { &start_time }, "seek to a given position in seconds", "pos" }, + { "t", HAS_ARG | OPT_TIME, { &duration }, "play \"duration\" seconds of audio/video", "duration" }, { "bytes", OPT_INT | HAS_ARG, { &seek_by_bytes }, "seek by bytes 0=off 1=on -1=auto", "val" }, { "seek_interval", OPT_FLOAT | HAS_ARG, { &seek_interval }, "set seek interval for left/right keys, in seconds", "seconds" }, { "nodisp", OPT_BOOL, { &display_disable }, "disable graphical display" }, From 39d5104332b1e78cb8e2d34dde072d3732d2eca1 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Fri, 14 Jul 2023 16:43:51 +0200 Subject: [PATCH 1955/2172] fftools: handle errors in parse_options() --- fftools/cmdutils.c | 15 ++++++++++----- fftools/cmdutils.h | 4 ++-- fftools/ffplay.c | 12 ++++++++---- fftools/ffprobe.c | 10 +++++++--- 4 files changed, 27 insertions(+), 14 deletions(-) diff --git a/fftools/cmdutils.c b/fftools/cmdutils.c index 038a5d33407..a9809ca0876 100644 --- a/fftools/cmdutils.c +++ b/fftools/cmdutils.c @@ -364,8 +364,8 @@ int parse_option(void *optctx, const char *opt, const char *arg, return !!(po->flags & HAS_ARG); } -void parse_options(void *optctx, int argc, char **argv, const OptionDef *options, - void (*parse_arg_function)(void *, const char*)) +int parse_options(void *optctx, int argc, char **argv, const OptionDef *options, + int (*parse_arg_function)(void *, const char*)) { const char *opt; int optindex, handleoptions = 1, ret; @@ -386,13 +386,18 @@ void parse_options(void *optctx, int argc, char **argv, const OptionDef *options opt++; if ((ret = parse_option(optctx, opt, argv[optindex], options)) < 0) - exit_program(1); + return ret; optindex += ret; } else { - if (parse_arg_function) - parse_arg_function(optctx, opt); + if (parse_arg_function) { + ret = parse_arg_function(optctx, opt); + if (ret < 0) + return ret; + } } } + + return 0; } int parse_optgroup(void *optctx, OptionGroup *g) diff --git a/fftools/cmdutils.h b/fftools/cmdutils.h index ff1b0f2e844..621c5fbe86c 100644 --- a/fftools/cmdutils.h +++ b/fftools/cmdutils.h @@ -194,8 +194,8 @@ void show_help_default(const char *opt, const char *arg); * argument without a leading option name flag. NULL if such arguments do * not have to be processed. */ -void parse_options(void *optctx, int argc, char **argv, const OptionDef *options, - void (* parse_arg_function)(void *optctx, const char*)); +int parse_options(void *optctx, int argc, char **argv, const OptionDef *options, + int (* parse_arg_function)(void *optctx, const char*)); /** * Parse one given option. diff --git a/fftools/ffplay.c b/fftools/ffplay.c index 89cea4d876b..4e26b3309d8 100644 --- a/fftools/ffplay.c +++ b/fftools/ffplay.c @@ -3501,17 +3501,19 @@ static int opt_show_mode(void *optctx, const char *opt, const char *arg) return 0; } -static void opt_input_file(void *optctx, const char *filename) +static int opt_input_file(void *optctx, const char *filename) { if (input_filename) { av_log(NULL, AV_LOG_FATAL, "Argument '%s' provided as input filename, but '%s' was already specified.\n", filename, input_filename); - exit(1); + return AVERROR(EINVAL); } if (!strcmp(filename, "-")) filename = "fd:"; input_filename = filename; + + return 0; } static int opt_codec(void *optctx, const char *opt, const char *arg) @@ -3630,7 +3632,7 @@ void show_help_default(const char *opt, const char *arg) /* Called from the main */ int main(int argc, char **argv) { - int flags; + int flags, ret; VideoState *is; init_dynload(); @@ -3649,7 +3651,9 @@ int main(int argc, char **argv) show_banner(argc, argv, options); - parse_options(NULL, argc, argv, options, opt_input_file); + ret = parse_options(NULL, argc, argv, options, opt_input_file); + if (ret < 0) + exit(1); if (!input_filename) { show_usage(); diff --git a/fftools/ffprobe.c b/fftools/ffprobe.c index e6fd33492d6..ba554377602 100644 --- a/fftools/ffprobe.c +++ b/fftools/ffprobe.c @@ -3770,17 +3770,19 @@ static int opt_show_entries(void *optctx, const char *opt, const char *arg) return ret; } -static void opt_input_file(void *optctx, const char *arg) +static int opt_input_file(void *optctx, const char *arg) { if (input_filename) { av_log(NULL, AV_LOG_ERROR, "Argument '%s' provided as input filename, but '%s' was already specified.\n", arg, input_filename); - exit_program(1); + return AVERROR(EINVAL); } if (!strcmp(arg, "-")) arg = "fd:"; input_filename = arg; + + return 0; } static int opt_input_file_i(void *optctx, const char *opt, const char *arg) @@ -4121,7 +4123,9 @@ int main(int argc, char **argv) #endif show_banner(argc, argv, options); - parse_options(NULL, argc, argv, options, opt_input_file); + ret = parse_options(NULL, argc, argv, options, opt_input_file); + if (ret < 0) + exit_program(1); if (do_show_log) av_log_set_callback(log_callback); From 6b8cf2505ab613fd365c276ed374caccb559f507 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Fri, 14 Jul 2023 17:11:18 +0200 Subject: [PATCH 1956/2172] fftools/cmdutils: constify the first parameter of filter_codec_opts() --- fftools/cmdutils.c | 2 +- fftools/cmdutils.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/fftools/cmdutils.c b/fftools/cmdutils.c index a9809ca0876..fa2797ebba4 100644 --- a/fftools/cmdutils.c +++ b/fftools/cmdutils.c @@ -943,7 +943,7 @@ int check_stream_specifier(AVFormatContext *s, AVStream *st, const char *spec) return ret; } -AVDictionary *filter_codec_opts(AVDictionary *opts, enum AVCodecID codec_id, +AVDictionary *filter_codec_opts(const AVDictionary *opts, enum AVCodecID codec_id, AVFormatContext *s, AVStream *st, const AVCodec *codec) { AVDictionary *ret = NULL; diff --git a/fftools/cmdutils.h b/fftools/cmdutils.h index 621c5fbe86c..8c1bde2a2f6 100644 --- a/fftools/cmdutils.h +++ b/fftools/cmdutils.h @@ -335,7 +335,7 @@ int check_stream_specifier(AVFormatContext *s, AVStream *st, const char *spec); * If null, the default one is looked up according to the codec id. * @return a pointer to the created dictionary */ -AVDictionary *filter_codec_opts(AVDictionary *opts, enum AVCodecID codec_id, +AVDictionary *filter_codec_opts(const AVDictionary *opts, enum AVCodecID codec_id, AVFormatContext *s, AVStream *st, const AVCodec *codec); /** From 87f0333af1810047fcd592f680c8d0a596bca7f6 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Fri, 14 Jul 2023 17:19:28 +0200 Subject: [PATCH 1957/2172] fftools/cmdutils: add error handling to filter_codec_opts() --- fftools/cmdutils.c | 41 ++++++++++++++++++++++++++------------- fftools/cmdutils.h | 8 +++++--- fftools/ffmpeg_demux.c | 5 ++++- fftools/ffmpeg_mux_init.c | 11 ++++++++--- fftools/ffplay.c | 6 +++++- fftools/ffprobe.c | 8 ++++++-- 6 files changed, 56 insertions(+), 23 deletions(-) diff --git a/fftools/cmdutils.c b/fftools/cmdutils.c index fa2797ebba4..c2a783a983f 100644 --- a/fftools/cmdutils.c +++ b/fftools/cmdutils.c @@ -943,8 +943,9 @@ int check_stream_specifier(AVFormatContext *s, AVStream *st, const char *spec) return ret; } -AVDictionary *filter_codec_opts(const AVDictionary *opts, enum AVCodecID codec_id, - AVFormatContext *s, AVStream *st, const AVCodec *codec) +int filter_codec_opts(const AVDictionary *opts, enum AVCodecID codec_id, + AVFormatContext *s, AVStream *st, const AVCodec *codec, + AVDictionary **dst) { AVDictionary *ret = NULL; const AVDictionaryEntry *t = NULL; @@ -977,12 +978,16 @@ AVDictionary *filter_codec_opts(const AVDictionary *opts, enum AVCodecID codec_i char *p = strchr(t->key, ':'); /* check stream specification in opt name */ - if (p) - switch (check_stream_specifier(s, st, p + 1)) { - case 1: *p = 0; break; - case 0: continue; - default: exit_program(1); - } + if (p) { + int err = check_stream_specifier(s, st, p + 1); + if (err < 0) { + av_dict_free(&ret); + return err; + } else if (!err) + continue; + + *p = 0; + } if (av_opt_find(&cc, t->key, NULL, flags, AV_OPT_SEARCH_FAKE_OBJ) || !codec || @@ -998,14 +1003,16 @@ AVDictionary *filter_codec_opts(const AVDictionary *opts, enum AVCodecID codec_i if (p) *p = ':'; } - return ret; + + *dst = ret; + return 0; } int setup_find_stream_info_opts(AVFormatContext *s, AVDictionary *codec_opts, AVDictionary ***dst) { - int i; + int ret; AVDictionary **opts; *dst = NULL; @@ -1017,11 +1024,19 @@ int setup_find_stream_info_opts(AVFormatContext *s, if (!opts) return AVERROR(ENOMEM); - for (i = 0; i < s->nb_streams; i++) - opts[i] = filter_codec_opts(codec_opts, s->streams[i]->codecpar->codec_id, - s, s->streams[i], NULL); + for (int i = 0; i < s->nb_streams; i++) { + ret = filter_codec_opts(codec_opts, s->streams[i]->codecpar->codec_id, + s, s->streams[i], NULL, &opts[i]); + if (ret < 0) + goto fail; + } *dst = opts; return 0; +fail: + for (int i = 0; i < s->nb_streams; i++) + av_dict_free(&opts[i]); + av_freep(&opts); + return ret; } int grow_array(void **array, int elem_size, int *size, int new_size) diff --git a/fftools/cmdutils.h b/fftools/cmdutils.h index 8c1bde2a2f6..56b7f130af2 100644 --- a/fftools/cmdutils.h +++ b/fftools/cmdutils.h @@ -333,10 +333,12 @@ int check_stream_specifier(AVFormatContext *s, AVStream *st, const char *spec); * @param st A stream from s for which the options should be filtered. * @param codec The particular codec for which the options should be filtered. * If null, the default one is looked up according to the codec id. - * @return a pointer to the created dictionary + * @param dst a pointer to the created dictionary + * @return a non-negative number on success, a negative error code on failure */ -AVDictionary *filter_codec_opts(const AVDictionary *opts, enum AVCodecID codec_id, - AVFormatContext *s, AVStream *st, const AVCodec *codec); +int filter_codec_opts(const AVDictionary *opts, enum AVCodecID codec_id, + AVFormatContext *s, AVStream *st, const AVCodec *codec, + AVDictionary **dst); /** * Setup AVCodecContext options for avformat_find_stream_info(). diff --git a/fftools/ffmpeg_demux.c b/fftools/ffmpeg_demux.c index a41b59ceb87..d612c5f434b 100644 --- a/fftools/ffmpeg_demux.c +++ b/fftools/ffmpeg_demux.c @@ -1176,7 +1176,10 @@ static int ist_add(const OptionsContext *o, Demuxer *d, AVStream *st) if (ret < 0) return ret; - ist->decoder_opts = filter_codec_opts(o->g->codec_opts, ist->st->codecpar->codec_id, ic, st, ist->dec); + ret = filter_codec_opts(o->g->codec_opts, ist->st->codecpar->codec_id, + ic, st, ist->dec, &ist->decoder_opts); + if (ret < 0) + return ret; ist->reinit_filters = -1; MATCH_PER_STREAM_OPT(reinit_filters, i, ist->reinit_filters, ic, st); diff --git a/fftools/ffmpeg_mux_init.c b/fftools/ffmpeg_mux_init.c index da304ee7271..86521417ec1 100644 --- a/fftools/ffmpeg_mux_init.c +++ b/fftools/ffmpeg_mux_init.c @@ -1206,8 +1206,10 @@ static int ost_add(Muxer *mux, const OptionsContext *o, enum AVMediaType type, const char *enc_stats_pre = NULL, *enc_stats_post = NULL, *mux_stats = NULL; const char *enc_time_base = NULL; - ost->encoder_opts = filter_codec_opts(o->g->codec_opts, enc->codec_id, - oc, st, enc->codec); + ret = filter_codec_opts(o->g->codec_opts, enc->codec_id, + oc, st, enc->codec, &ost->encoder_opts); + if (ret < 0) + return ret; MATCH_PER_STREAM_OPT(presets, str, preset, oc, st); ost->autoscale = 1; @@ -1305,7 +1307,10 @@ static int ost_add(Muxer *mux, const OptionsContext *o, enum AVMediaType type, ost->enc_timebase = q; } } else { - ost->encoder_opts = filter_codec_opts(o->g->codec_opts, AV_CODEC_ID_NONE, oc, st, NULL); + ret = filter_codec_opts(o->g->codec_opts, AV_CODEC_ID_NONE, oc, st, + NULL, &ost->encoder_opts); + if (ret < 0) + return ret; } diff --git a/fftools/ffplay.c b/fftools/ffplay.c index 4e26b3309d8..df20c6a29db 100644 --- a/fftools/ffplay.c +++ b/fftools/ffplay.c @@ -2584,7 +2584,11 @@ static int stream_component_open(VideoState *is, int stream_index) if (fast) avctx->flags2 |= AV_CODEC_FLAG2_FAST; - opts = filter_codec_opts(codec_opts, avctx->codec_id, ic, ic->streams[stream_index], codec); + ret = filter_codec_opts(codec_opts, avctx->codec_id, ic, + ic->streams[stream_index], codec, &opts); + if (ret < 0) + goto fail; + if (!av_dict_get(opts, "threads", NULL, 0)) av_dict_set(&opts, "threads", "auto", 0); if (stream_lowres) diff --git a/fftools/ffprobe.c b/fftools/ffprobe.c index ba554377602..da8fc898308 100644 --- a/fftools/ffprobe.c +++ b/fftools/ffprobe.c @@ -3421,8 +3421,12 @@ static int open_input_file(InputFile *ifile, const char *filename, continue; } { - AVDictionary *opts = filter_codec_opts(codec_opts, stream->codecpar->codec_id, - fmt_ctx, stream, codec); + AVDictionary *opts; + + err = filter_codec_opts(codec_opts, stream->codecpar->codec_id, + fmt_ctx, stream, codec, &opts); + if (err < 0) + exit(1); ist->dec_ctx = avcodec_alloc_context3(codec); if (!ist->dec_ctx) From c56fabde27dad6aeb12313be854e21a4aca01e5a Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Fri, 14 Jul 2023 18:07:40 +0200 Subject: [PATCH 1958/2172] fftools/ffmpeg_opt: consolidate printing errors in ffmpeg_parse_options() --- fftools/ffmpeg_opt.c | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/fftools/ffmpeg_opt.c b/fftools/ffmpeg_opt.c index 44a6b49ed7d..14b292f202d 100644 --- a/fftools/ffmpeg_opt.c +++ b/fftools/ffmpeg_opt.c @@ -1289,6 +1289,7 @@ static int open_files(OptionGroupList *l, const char *inout, int ffmpeg_parse_options(int argc, char **argv) { OptionParseContext octx; + const char *errmsg = NULL; int ret; memset(&octx, 0, sizeof(octx)); @@ -1297,14 +1298,14 @@ int ffmpeg_parse_options(int argc, char **argv) ret = split_commandline(&octx, argc, argv, options, groups, FF_ARRAY_ELEMS(groups)); if (ret < 0) { - av_log(NULL, AV_LOG_FATAL, "Error splitting the argument list: "); + errmsg = "splitting the argument list"; goto fail; } /* apply global options */ ret = parse_optgroup(NULL, &octx.global_opts); if (ret < 0) { - av_log(NULL, AV_LOG_FATAL, "Error parsing global options: "); + errmsg = "parsing global options"; goto fail; } @@ -1314,21 +1315,21 @@ int ffmpeg_parse_options(int argc, char **argv) /* open input files */ ret = open_files(&octx.groups[GROUP_INFILE], "input", ifile_open); if (ret < 0) { - av_log(NULL, AV_LOG_FATAL, "Error opening input files: "); + errmsg = "opening input files"; goto fail; } /* create the complex filtergraphs */ ret = init_complex_filters(); if (ret < 0) { - av_log(NULL, AV_LOG_FATAL, "Error initializing complex filters.\n"); + errmsg = "initializing complex filters"; goto fail; } /* open output files */ ret = open_files(&octx.groups[GROUP_OUTFILE], "output", of_open); if (ret < 0) { - av_log(NULL, AV_LOG_FATAL, "Error opening output files: "); + errmsg = "opening output files"; goto fail; } @@ -1345,7 +1346,8 @@ int ffmpeg_parse_options(int argc, char **argv) fail: uninit_parse_context(&octx); if (ret < 0) { - av_log(NULL, AV_LOG_FATAL, "%s\n", av_err2str(ret)); + av_log(NULL, AV_LOG_FATAL, "Error %s: %s\n", + errmsg ? errmsg : "", av_err2str(ret)); } return ret; } From 8173623e39cc72866eaaac13538e160f226b0a23 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Fri, 14 Jul 2023 18:10:58 +0200 Subject: [PATCH 1959/2172] fftools/ffmpeg: consolidate exiting from main() on error --- fftools/ffmpeg.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/fftools/ffmpeg.c b/fftools/ffmpeg.c index b4ea52ac1da..0c5e553c724 100644 --- a/fftools/ffmpeg.c +++ b/fftools/ffmpeg.c @@ -1339,17 +1339,19 @@ int main(int argc, char **argv) /* parse options and open all input/output files */ ret = ffmpeg_parse_options(argc, argv); if (ret < 0) - exit_program(1); + goto finish; if (nb_output_files <= 0 && nb_input_files == 0) { show_usage(); av_log(NULL, AV_LOG_WARNING, "Use -h to get full help or, even better, run 'man %s'\n", program_name); - exit_program(1); + ret = 1; + goto finish; } if (nb_output_files <= 0) { av_log(NULL, AV_LOG_FATAL, "At least one output file must be specified\n"); - exit_program(1); + ret = 1; + goto finish; } current_time = ti = get_benchmark_time_stamps(); @@ -1368,6 +1370,7 @@ int main(int argc, char **argv) ret = received_nb_signals ? 255 : err_rate_exceeded ? 69 : ret; +finish: exit_program(ret); return ret; } From eda1fac27afdaaf646d9c84e6f2cea407764fbf2 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Fri, 14 Jul 2023 18:15:27 +0200 Subject: [PATCH 1960/2172] fftools/cmdutils: return AVERROR_EXIT for OPT_EXIT options instead of aborting() --- fftools/cmdutils.c | 2 +- fftools/ffmpeg.c | 3 +++ fftools/ffmpeg_opt.c | 2 +- fftools/ffplay.c | 2 +- fftools/ffprobe.c | 2 +- 5 files changed, 7 insertions(+), 4 deletions(-) diff --git a/fftools/cmdutils.c b/fftools/cmdutils.c index c2a783a983f..45e93ab196e 100644 --- a/fftools/cmdutils.c +++ b/fftools/cmdutils.c @@ -320,7 +320,7 @@ static int write_option(void *optctx, const OptionDef *po, const char *opt, } } if (po->flags & OPT_EXIT) - exit_program(0); + return AVERROR_EXIT; return 0; } diff --git a/fftools/ffmpeg.c b/fftools/ffmpeg.c index 0c5e553c724..50d66584728 100644 --- a/fftools/ffmpeg.c +++ b/fftools/ffmpeg.c @@ -1371,6 +1371,9 @@ int main(int argc, char **argv) err_rate_exceeded ? 69 : ret; finish: + if (ret == AVERROR_EXIT) + ret = 0; + exit_program(ret); return ret; } diff --git a/fftools/ffmpeg_opt.c b/fftools/ffmpeg_opt.c index 14b292f202d..700db706a1f 100644 --- a/fftools/ffmpeg_opt.c +++ b/fftools/ffmpeg_opt.c @@ -1345,7 +1345,7 @@ int ffmpeg_parse_options(int argc, char **argv) fail: uninit_parse_context(&octx); - if (ret < 0) { + if (ret < 0 && ret != AVERROR_EXIT) { av_log(NULL, AV_LOG_FATAL, "Error %s: %s\n", errmsg ? errmsg : "", av_err2str(ret)); } diff --git a/fftools/ffplay.c b/fftools/ffplay.c index df20c6a29db..a491fdd9e31 100644 --- a/fftools/ffplay.c +++ b/fftools/ffplay.c @@ -3657,7 +3657,7 @@ int main(int argc, char **argv) ret = parse_options(NULL, argc, argv, options, opt_input_file); if (ret < 0) - exit(1); + exit(ret == AVERROR_EXIT ? 0 : 1); if (!input_filename) { show_usage(); diff --git a/fftools/ffprobe.c b/fftools/ffprobe.c index da8fc898308..c83d20995e4 100644 --- a/fftools/ffprobe.c +++ b/fftools/ffprobe.c @@ -4129,7 +4129,7 @@ int main(int argc, char **argv) show_banner(argc, argv, options); ret = parse_options(NULL, argc, argv, options, opt_input_file); if (ret < 0) - exit_program(1); + exit_program(ret == AVERROR_EXIT ? 0 : 1); if (do_show_log) av_log_set_callback(log_callback); From 2f155b18a10fec84163b3546efb41a8d64bb7c22 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Fri, 14 Jul 2023 18:18:57 +0200 Subject: [PATCH 1961/2172] fftools/ffmpeg: return an error from assert_avoptions() instead of aborting Rename it to check_avoptions(). --- fftools/ffmpeg.c | 6 ++++-- fftools/ffmpeg.h | 2 +- fftools/ffmpeg_dec.c | 5 ++++- fftools/ffmpeg_demux.c | 5 ++++- fftools/ffmpeg_enc.c | 5 ++++- 5 files changed, 17 insertions(+), 6 deletions(-) diff --git a/fftools/ffmpeg.c b/fftools/ffmpeg.c index 50d66584728..ecb3f89f85c 100644 --- a/fftools/ffmpeg.c +++ b/fftools/ffmpeg.c @@ -457,13 +457,15 @@ void remove_avoptions(AVDictionary **a, AVDictionary *b) } } -void assert_avoptions(AVDictionary *m) +int check_avoptions(AVDictionary *m) { 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); + return AVERROR_OPTION_NOT_FOUND; } + + return 0; } void update_benchmark(const char *fmt, ...) diff --git a/fftools/ffmpeg.h b/fftools/ffmpeg.h index 67a6bcbc8b9..82439dc5e39 100644 --- a/fftools/ffmpeg.h +++ b/fftools/ffmpeg.h @@ -704,7 +704,7 @@ void term_exit(void); void show_usage(void); void remove_avoptions(AVDictionary **a, AVDictionary *b); -void assert_avoptions(AVDictionary *m); +int check_avoptions(AVDictionary *m); int assert_file_overwrite(const char *filename); char *file_read(const char *filename); diff --git a/fftools/ffmpeg_dec.c b/fftools/ffmpeg_dec.c index 62c1baf2874..8a3b52fd7ee 100644 --- a/fftools/ffmpeg_dec.c +++ b/fftools/ffmpeg_dec.c @@ -1119,7 +1119,10 @@ int dec_open(InputStream *ist) av_err2str(ret)); return ret; } - assert_avoptions(ist->decoder_opts); + + ret = check_avoptions(ist->decoder_opts); + if (ret < 0) + return ret; ret = dec_thread_start(ist); if (ret < 0) { diff --git a/fftools/ffmpeg_demux.c b/fftools/ffmpeg_demux.c index d612c5f434b..48edbd7f6b1 100644 --- a/fftools/ffmpeg_demux.c +++ b/fftools/ffmpeg_demux.c @@ -1511,7 +1511,10 @@ int ifile_open(const OptionsContext *o, const char *filename) if (scan_all_pmts_set) av_dict_set(&o->g->format_opts, "scan_all_pmts", NULL, AV_DICT_MATCH_CASE); remove_avoptions(&o->g->format_opts, o->g->codec_opts); - assert_avoptions(o->g->format_opts); + + ret = check_avoptions(o->g->format_opts); + if (ret < 0) + return ret; /* apply forced codec ids */ for (i = 0; i < ic->nb_streams; i++) { diff --git a/fftools/ffmpeg_enc.c b/fftools/ffmpeg_enc.c index d842bc7df47..96424272bf7 100644 --- a/fftools/ffmpeg_enc.c +++ b/fftools/ffmpeg_enc.c @@ -407,7 +407,10 @@ int enc_open(OutputStream *ost, AVFrame *frame) ost->sq_idx_encode, ost->enc_ctx->frame_size); } - assert_avoptions(ost->encoder_opts); + ret = check_avoptions(ost->encoder_opts); + if (ret < 0) + return ret; + if (ost->enc_ctx->bit_rate && ost->enc_ctx->bit_rate < 1000 && ost->enc_ctx->codec_id != AV_CODEC_ID_CODEC2 /* don't complain about 700 bit/s modes */) av_log(ost, AV_LOG_WARNING, "The bitrate parameter is set too low." From 83ace80bfd80fcdba2c65fa1d554923ea931d5bd Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Fri, 14 Jul 2023 18:20:03 +0200 Subject: [PATCH 1962/2172] fftools/ffmpeg: return an error from MATCH_PER_STREAM_OPT() instead of aborting --- fftools/ffmpeg.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fftools/ffmpeg.h b/fftools/ffmpeg.h index 82439dc5e39..d53181e427b 100644 --- a/fftools/ffmpeg.h +++ b/fftools/ffmpeg.h @@ -911,7 +911,7 @@ static inline int err_merge(int err0, int err1) so = &o->name[_i];\ _matches++;\ } else if (_ret < 0)\ - exit_program(1);\ + return _ret;\ }\ if (_matches > 1)\ WARN_MULTIPLE_OPT_USAGE(name, type, so, st);\ From 140cb5a74294f62343f327049057089a3e3abf5b Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Fri, 14 Jul 2023 18:21:39 +0200 Subject: [PATCH 1963/2172] fftools/ffprobe: replace report_and_exit() with returning error codes --- fftools/ffprobe.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/fftools/ffprobe.c b/fftools/ffprobe.c index c83d20995e4..6180a5c952c 100644 --- a/fftools/ffprobe.c +++ b/fftools/ffprobe.c @@ -3350,7 +3350,7 @@ static int open_input_file(InputFile *ifile, const char *filename, fmt_ctx = avformat_alloc_context(); if (!fmt_ctx) - report_and_exit(AVERROR(ENOMEM)); + return AVERROR(ENOMEM); if (!av_dict_get(format_opts, "scan_all_pmts", NULL, AV_DICT_MATCH_CASE)) { av_dict_set(&format_opts, "scan_all_pmts", "1", AV_DICT_DONT_OVERWRITE); @@ -3377,7 +3377,7 @@ static int open_input_file(InputFile *ifile, const char *filename, err = setup_find_stream_info_opts(fmt_ctx, codec_opts, &opts); if (err < 0) - report_and_exit(err); + return err; err = avformat_find_stream_info(fmt_ctx, opts); From 78699923ac8ab8c2de1ba64c464385a9e12258ed Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Fri, 14 Jul 2023 18:26:07 +0200 Subject: [PATCH 1964/2172] fftools/ffplay: replace report_and_exit() with returning an error code --- fftools/ffplay.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/fftools/ffplay.c b/fftools/ffplay.c index a491fdd9e31..5212ad053e8 100644 --- a/fftools/ffplay.c +++ b/fftools/ffplay.c @@ -2784,8 +2784,12 @@ static int read_thread(void *arg) int orig_nb_streams = ic->nb_streams; err = setup_find_stream_info_opts(ic, codec_opts, &opts); - if (err < 0) - report_and_exit(err); + if (err < 0) { + av_log(NULL, AV_LOG_ERROR, + "Error setting up avformat_find_stream_info() options\n"); + ret = err; + goto fail; + } err = avformat_find_stream_info(ic, opts); From 411e1833601e542b28681feab23ef4754644eb47 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Fri, 14 Jul 2023 18:26:43 +0200 Subject: [PATCH 1965/2172] fftools/opt_common: replace report_and_exit() with returning an error code Remove report_and_exit(), as it has no more users. --- fftools/cmdutils.c | 6 ------ fftools/cmdutils.h | 11 ----------- fftools/opt_common.c | 10 +++++++--- 3 files changed, 7 insertions(+), 20 deletions(-) diff --git a/fftools/cmdutils.c b/fftools/cmdutils.c index 45e93ab196e..ed507a8f2e7 100644 --- a/fftools/cmdutils.c +++ b/fftools/cmdutils.c @@ -90,12 +90,6 @@ void register_exit(void (*cb)(int ret)) program_exit = cb; } -void report_and_exit(int ret) -{ - av_log(NULL, AV_LOG_FATAL, "%s\n", av_err2str(ret)); - exit_program(AVUNERROR(ret)); -} - void exit_program(int ret) { if (program_exit) diff --git a/fftools/cmdutils.h b/fftools/cmdutils.h index 56b7f130af2..6d4708f32e4 100644 --- a/fftools/cmdutils.h +++ b/fftools/cmdutils.h @@ -54,17 +54,6 @@ extern int hide_banner; */ void register_exit(void (*cb)(int ret)); -/** - * Reports an error corresponding to the provided - * AVERROR code and calls exit_program() with the - * corresponding POSIX error code. - * @note ret must be an AVERROR-value of a POSIX error code - * (i.e. AVERROR(EFOO) and not AVERROR_FOO). - * library functions can return both, so call this only - * with AVERROR(EFOO) of your own. - */ -void report_and_exit(int ret) av_noreturn; - /** * Wraps exit with a program-specific cleanup routine. */ diff --git a/fftools/opt_common.c b/fftools/opt_common.c index 39258bb46c3..913932c914b 100644 --- a/fftools/opt_common.c +++ b/fftools/opt_common.c @@ -632,7 +632,7 @@ static int compare_codec_desc(const void *a, const void *b) strcmp((*da)->name, (*db)->name); } -static unsigned get_codecs_sorted(const AVCodecDescriptor ***rcodecs) +static int get_codecs_sorted(const AVCodecDescriptor ***rcodecs) { const AVCodecDescriptor *desc = NULL; const AVCodecDescriptor **codecs; @@ -641,7 +641,7 @@ static unsigned get_codecs_sorted(const AVCodecDescriptor ***rcodecs) while ((desc = avcodec_descriptor_next(desc))) nb_codecs++; if (!(codecs = av_calloc(nb_codecs, sizeof(*codecs)))) - report_and_exit(AVERROR(ENOMEM)); + return AVERROR(ENOMEM); desc = NULL; while ((desc = avcodec_descriptor_next(desc))) codecs[i++] = desc; @@ -666,7 +666,11 @@ static char get_media_type_char(enum AVMediaType type) int show_codecs(void *optctx, const char *opt, const char *arg) { const AVCodecDescriptor **codecs; - unsigned i, nb_codecs = get_codecs_sorted(&codecs); + unsigned i; + int nb_codecs = get_codecs_sorted(&codecs); + + if (nb_codecs < 0) + return nb_codecs; printf("Codecs:\n" " D..... = Decoding supported\n" From be49c48282704ada90d2130c8c5193bb97a7cfaa Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Fri, 14 Jul 2023 18:30:23 +0200 Subject: [PATCH 1966/2172] fftools/ffprobe: inline opt_output_file() into its only caller There is no reason to keep them separate. Also, replace exit_program() with returning an error code. --- fftools/ffprobe.c | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/fftools/ffprobe.c b/fftools/ffprobe.c index 6180a5c952c..e234c929048 100644 --- a/fftools/ffprobe.c +++ b/fftools/ffprobe.c @@ -3795,22 +3795,18 @@ static int opt_input_file_i(void *optctx, const char *opt, const char *arg) return 0; } -static void opt_output_file(void *optctx, const char *arg) +static int opt_output_file_o(void *optctx, const char *opt, const char *arg) { if (output_filename) { av_log(NULL, AV_LOG_ERROR, "Argument '%s' provided as output filename, but '%s' was already specified.\n", arg, output_filename); - exit_program(1); + return AVERROR(EINVAL); } if (!strcmp(arg, "-")) arg = "fd:"; output_filename = arg; -} -static int opt_output_file_o(void *optctx, const char *opt, const char *arg) -{ - opt_output_file(optctx, arg); return 0; } From a81d9231b91dac75a8fa1cbb72ec17556b5c6d9f Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Fri, 14 Jul 2023 18:33:12 +0200 Subject: [PATCH 1967/2172] fftools/ffprobe: stop calling exit_program() Inline the relevant part of ffprobe_cleanup() into main() and drop the rest. --- fftools/ffprobe.c | 22 ++++++++-------------- 1 file changed, 8 insertions(+), 14 deletions(-) diff --git a/fftools/ffprobe.c b/fftools/ffprobe.c index e234c929048..a39185f6fed 100644 --- a/fftools/ffprobe.c +++ b/fftools/ffprobe.c @@ -381,17 +381,6 @@ static void log_callback(void *ptr, int level, const char *fmt, va_list vl) #endif } -static void ffprobe_cleanup(int ret) -{ - int i; - for (i = 0; i < FF_ARRAY_ELEMS(sections); i++) - av_dict_free(&(sections[i].entries_to_show)); - -#if HAVE_THREADS - pthread_mutex_destroy(&log_mutex); -#endif -} - struct unit_value { union { double d; long long int i; } val; const char *unit; @@ -4113,7 +4102,6 @@ int main(int argc, char **argv) } #endif av_log_set_flags(AV_LOG_SKIP_REPEATED); - register_exit(ffprobe_cleanup); options = real_options; parse_loglevel(argc, argv, options); @@ -4124,8 +4112,10 @@ int main(int argc, char **argv) show_banner(argc, argv, options); ret = parse_options(NULL, argc, argv, options, opt_input_file); - if (ret < 0) - exit_program(ret == AVERROR_EXIT ? 0 : 1); + if (ret < 0) { + ret = AVERROR_EXIT ? 0 : ret; + goto end; + } if (do_show_log) av_log_set_callback(log_callback); @@ -4249,5 +4239,9 @@ int main(int argc, char **argv) avformat_network_deinit(); +#if HAVE_THREADS + pthread_mutex_destroy(&log_mutex); +#endif + return ret < 0; } From ccc684993276248d64c328a810fb7714af2f4c70 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Fri, 14 Jul 2023 18:36:05 +0200 Subject: [PATCH 1968/2172] fftools/ffmpeg: stop calling exit_program() Remove exit_program() and register_exit(), as they are no longer used. --- fftools/cmdutils.c | 15 --------------- fftools/cmdutils.h | 10 ---------- fftools/ffmpeg.c | 4 +--- 3 files changed, 1 insertion(+), 28 deletions(-) diff --git a/fftools/cmdutils.c b/fftools/cmdutils.c index ed507a8f2e7..156c13801a0 100644 --- a/fftools/cmdutils.c +++ b/fftools/cmdutils.c @@ -83,21 +83,6 @@ void init_dynload(void) #endif } -static void (*program_exit)(int ret); - -void register_exit(void (*cb)(int ret)) -{ - program_exit = cb; -} - -void exit_program(int ret) -{ - if (program_exit) - program_exit(ret); - - exit(ret); -} - int parse_number(const char *context, const char *numstr, int type, double min, double max, double *dst) { diff --git a/fftools/cmdutils.h b/fftools/cmdutils.h index 6d4708f32e4..8b67d827cc7 100644 --- a/fftools/cmdutils.h +++ b/fftools/cmdutils.h @@ -49,16 +49,6 @@ extern AVDictionary *swr_opts; extern AVDictionary *format_opts, *codec_opts; extern int hide_banner; -/** - * Register a program-specific cleanup routine. - */ -void register_exit(void (*cb)(int ret)); - -/** - * Wraps exit with a program-specific cleanup routine. - */ -void exit_program(int ret) av_noreturn; - /** * Initialize dynamic library loading */ diff --git a/fftools/ffmpeg.c b/fftools/ffmpeg.c index ecb3f89f85c..6130fd06fcb 100644 --- a/fftools/ffmpeg.c +++ b/fftools/ffmpeg.c @@ -1324,8 +1324,6 @@ int main(int argc, char **argv) init_dynload(); - register_exit(ffmpeg_cleanup); - setvbuf(stderr,NULL,_IONBF,0); /* win32 runtime needs this */ av_log_set_flags(AV_LOG_SKIP_REPEATED); @@ -1376,6 +1374,6 @@ int main(int argc, char **argv) if (ret == AVERROR_EXIT) ret = 0; - exit_program(ret); + ffmpeg_cleanup(ret); return ret; } From effadce6c756247ea8bae32dc13bb3e6f464f0eb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9mi=20Denis-Courmont?= Date: Sun, 16 Jul 2023 18:18:02 +0300 Subject: [PATCH 1969/2172] avcodec/x86/mathops: clip constants used with shift instructions within inline assembly Fixes assembling with binutil as >= 2.41 Signed-off-by: James Almer --- libavcodec/x86/mathops.h | 26 +++++++++++++++++++++++--- 1 file changed, 23 insertions(+), 3 deletions(-) diff --git a/libavcodec/x86/mathops.h b/libavcodec/x86/mathops.h index 6298f5ed198..ca7e2dffc10 100644 --- a/libavcodec/x86/mathops.h +++ b/libavcodec/x86/mathops.h @@ -35,12 +35,20 @@ static av_always_inline av_const int MULL(int a, int b, unsigned shift) { int rt, dummy; + if (__builtin_constant_p(shift)) __asm__ ( "imull %3 \n\t" "shrdl %4, %%edx, %%eax \n\t" :"=a"(rt), "=d"(dummy) - :"a"(a), "rm"(b), "ci"((uint8_t)shift) + :"a"(a), "rm"(b), "i"(shift & 0x1F) ); + else + __asm__ ( + "imull %3 \n\t" + "shrdl %4, %%edx, %%eax \n\t" + :"=a"(rt), "=d"(dummy) + :"a"(a), "rm"(b), "c"((uint8_t)shift) + ); return rt; } @@ -113,19 +121,31 @@ __asm__ volatile(\ // avoid +32 for shift optimization (gcc should do that ...) #define NEG_SSR32 NEG_SSR32 static inline int32_t NEG_SSR32( int32_t a, int8_t s){ + if (__builtin_constant_p(s)) __asm__ ("sarl %1, %0\n\t" : "+r" (a) - : "ic" ((uint8_t)(-s)) + : "i" (-s & 0x1F) ); + else + __asm__ ("sarl %1, %0\n\t" + : "+r" (a) + : "c" ((uint8_t)(-s)) + ); return a; } #define NEG_USR32 NEG_USR32 static inline uint32_t NEG_USR32(uint32_t a, int8_t s){ + if (__builtin_constant_p(s)) __asm__ ("shrl %1, %0\n\t" : "+r" (a) - : "ic" ((uint8_t)(-s)) + : "i" (-s & 0x1F) ); + else + __asm__ ("shrl %1, %0\n\t" + : "+r" (a) + : "c" ((uint8_t)(-s)) + ); return a; } From b710f881cefde728f869689193885b82af6b90cd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9mi=20Denis-Courmont?= Date: Mon, 17 Jul 2023 19:33:09 +0300 Subject: [PATCH 1970/2172] lavu/float_dsp: unroll RISC-V V loops butterflies_float_c: 1057.0 butterflies_float_rvv_f32: 351.0 (before) butterflies_float_rvv_f32: 329.5 (after) vector_dmac_scalar_c: 819.0 vector_dmac_scalar_rvv_f64: 670.5 (before) vector_dmac_scalar_rvv_f64: 431.0 (after) vector_dmul_c: 800.2 vector_dmul_rvv_f64: 541.5 (before) vector_dmul_rvv_f64: 426.0 (after) vector_dmul_scalar_c: 545.7 vector_dmul_scalar_rvv_f64: 670.7 (before) vector_dmul_scalar_rvv_f64: 324.7 (after) vector_fmac_scalar_c: 804.5 vector_fmac_scalar_rvv_f32: 412.7 (before) vector_fmac_scalar_rvv_f32: 214.5 (after) vector_fmul_c: 811.2 vector_fmul_rvv_f32: 285.7 (before) vector_fmul_rvv_f32: 214.2 (after) vector_fmul_add_c: 1313.0 vector_fmul_add_rvv_f32: 349.0 (before) vector_fmul_add_rvv_f32: 290.2 (after) vector_fmul_reverse_c: 815.7 vector_fmul_reverse_rvv_f32: 529.2 (before) vector_fmul_reverse_rvv_f32: 515.7 (after) vector_fmul_scalar_c: 546.0 vector_fmul_scalar_rvv_f32: 350.2 (before) vector_fmul_scalar_rvv_f32: 169.5 (after) --- libavutil/riscv/float_dsp_rvv.S | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/libavutil/riscv/float_dsp_rvv.S b/libavutil/riscv/float_dsp_rvv.S index 77961b7387e..fa8f9dc2125 100644 --- a/libavutil/riscv/float_dsp_rvv.S +++ b/libavutil/riscv/float_dsp_rvv.S @@ -23,7 +23,7 @@ // (a0) = (a1) * (a2) [0..a3-1] func ff_vector_fmul_rvv, zve32f 1: - vsetvli t0, a3, e32, m1, ta, ma + vsetvli t0, a3, e32, m8, ta, ma vle32.v v16, (a1) sub a3, a3, t0 vle32.v v24, (a2) @@ -42,7 +42,7 @@ func ff_vector_fmac_scalar_rvv, zve32f NOHWF fmv.w.x fa0, a2 NOHWF mv a2, a3 1: - vsetvli t0, a2, e32, m1, ta, ma + vsetvli t0, a2, e32, m8, ta, ma slli t1, t0, 2 vle32.v v24, (a1) sub a2, a2, t0 @@ -61,7 +61,7 @@ func ff_vector_fmul_scalar_rvv, zve32f NOHWF fmv.w.x fa0, a2 NOHWF mv a2, a3 1: - vsetvli t0, a2, e32, m1, ta, ma + vsetvli t0, a2, e32, m8, ta, ma vle32.v v16, (a1) sub a2, a2, t0 vfmul.vf v16, v16, fa0 @@ -82,7 +82,7 @@ func ff_vector_fmul_window_rvv, zve32f sh2add t3, t1, a3 li t1, -4 // byte stride 1: - vsetvli t2, a4, e32, m1, ta, ma + vsetvli t2, a4, e32, m4, ta, ma vle32.v v16, (a1) slli t4, t2, 2 vlse32.v v20, (a2), t1 @@ -109,7 +109,7 @@ endfunc // (a0) = (a1) * (a2) + (a3) [0..a4-1] func ff_vector_fmul_add_rvv, zve32f 1: - vsetvli t0, a4, e32, m1, ta, ma + vsetvli t0, a4, e32, m8, ta, ma vle32.v v8, (a1) sub a4, a4, t0 vle32.v v16, (a2) @@ -131,7 +131,7 @@ func ff_vector_fmul_reverse_rvv, zve32f li t2, -4 // byte stride addi a2, a2, -4 1: - vsetvli t0, a3, e32, m1, ta, ma + vsetvli t0, a3, e32, m8, ta, ma slli t1, t0, 2 vle32.v v16, (a1) sub a3, a3, t0 @@ -149,7 +149,7 @@ endfunc // (a0) = (a0) + (a1), (a1) = (a0) - (a1) [0..a2-1] func ff_butterflies_float_rvv, zve32f 1: - vsetvli t0, a2, e32, m1, ta, ma + vsetvli t0, a2, e32, m8, ta, ma vle32.v v16, (a0) sub a2, a2, t0 vle32.v v24, (a1) @@ -187,7 +187,7 @@ endfunc // (a0) = (a1) * (a2) [0..a3-1] func ff_vector_dmul_rvv, zve64d 1: - vsetvli t0, a3, e64, m1, ta, ma + vsetvli t0, a3, e64, m8, ta, ma vle64.v v16, (a1) sub a3, a3, t0 vle64.v v24, (a2) @@ -206,7 +206,7 @@ func ff_vector_dmac_scalar_rvv, zve64d NOHWD fmv.d.x fa0, a2 NOHWD mv a2, a3 1: - vsetvli t0, a2, e64, m1, ta, ma + vsetvli t0, a2, e64, m8, ta, ma vle64.v v24, (a1) sub a2, a2, t0 vle64.v v16, (a0) @@ -224,7 +224,7 @@ func ff_vector_dmul_scalar_rvv, zve64d NOHWD fmv.d.x fa0, a2 NOHWD mv a2, a3 1: - vsetvli t0, a2, e64, m1, ta, ma + vsetvli t0, a2, e64, m8, ta, ma vle64.v v16, (a1) sub a2, a2, t0 vfmul.vf v16, v16, fa0 From 29b9d616c212f20bc0d3e24928919a14efc047f8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9mi=20Denis-Courmont?= Date: Mon, 17 Jul 2023 20:11:08 +0300 Subject: [PATCH 1971/2172] lavu/float_dsp: rework RISC-V V scalar product 1) Take the reductive sum out of the loop, leaving a regular vector addition in the loop. 2) Merge the addition and the multiplication. 3) Unroll. Before: scalarproduct_float_rvv_f32: 832.5 After: scalarproduct_float_rvv_f32: 275.2 --- libavutil/riscv/float_dsp_rvv.S | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/libavutil/riscv/float_dsp_rvv.S b/libavutil/riscv/float_dsp_rvv.S index fa8f9dc2125..7cfc890bc29 100644 --- a/libavutil/riscv/float_dsp_rvv.S +++ b/libavutil/riscv/float_dsp_rvv.S @@ -166,20 +166,22 @@ endfunc // a0 = (a0).(a1) [0..a2-1] func ff_scalarproduct_float_rvv, zve32f - vsetivli zero, 1, e32, m1, ta, ma - vmv.s.x v8, zero + vsetvli t0, zero, e32, m8, ta, ma + vmv.v.x v8, zero + vmv.s.x v0, zero 1: - vsetvli t0, a2, e32, m1, ta, ma + vsetvli t0, a2, e32, m8, tu, ma vle32.v v16, (a0) sub a2, a2, t0 vle32.v v24, (a1) sh2add a0, t0, a0 - vfmul.vv v16, v16, v24 + vfmacc.vv v8, v16, v24 sh2add a1, t0, a1 - vfredusum.vs v8, v16, v8 bnez a2, 1b - vfmv.f.s fa0, v8 + vsetvli t0, zero, e32, m8, ta, ma + vfredusum.vs v0, v8, v0 + vfmv.f.s fa0, v0 NOHWF fmv.x.w a0, fa0 ret endfunc From 44cac1def0fab47592882afe6695e39c20781839 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9mi=20Denis-Courmont?= Date: Mon, 17 Jul 2023 20:46:06 +0300 Subject: [PATCH 1972/2172] lavc/audiodsp: rework RISC-V V scalar product Take vector reduction out of the loop and unroll. Before: audiodsp.scalarproduct_int16_c: 12321.0 audiodsp.scalarproduct_int16_rvv_i32: 4175.7 After: audiodsp.scalarproduct_int16_c: 12320.5 audiodsp.scalarproduct_int16_rvv_i32: 1230.2 --- libavcodec/riscv/audiodsp_rvv.S | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/libavcodec/riscv/audiodsp_rvv.S b/libavcodec/riscv/audiodsp_rvv.S index af1e07bef9c..f7eba2114f8 100644 --- a/libavcodec/riscv/audiodsp_rvv.S +++ b/libavcodec/riscv/audiodsp_rvv.S @@ -21,21 +21,22 @@ #include "libavutil/riscv/asm.S" func ff_scalarproduct_int16_rvv, zve32x - vsetivli zero, 1, e32, m1, ta, ma - vmv.s.x v8, zero + vsetvli t0, zero, e32, m8, ta, ma + vmv.v.x v8, zero + vmv.s.x v0, zero 1: - vsetvli t0, a2, e16, m1, ta, ma + vsetvli t0, a2, e16, m4, tu, ma vle16.v v16, (a0) sub a2, a2, t0 vle16.v v24, (a1) sh1add a0, t0, a0 - vwmul.vv v0, v16, v24 + vwmacc.vv v8, v16, v24 sh1add a1, t0, a1 - vsetvli zero, t0, e32, m2, ta, ma - vredsum.vs v8, v0, v8 bnez a2, 1b - vmv.x.s a0, v8 + vsetvli t0, zero, e32, m8, ta, ma + vredsum.vs v0, v8, v0 + vmv.x.s a0, v0 ret endfunc From 3dc93acc56258e25ae43176aafb85e2191695105 Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Thu, 20 Jul 2023 09:37:20 +0200 Subject: [PATCH 1973/2172] avfilter/vf_pseudocolor: add four more presets --- doc/filters.texi | 4 +++ libavfilter/vf_pseudocolor.c | 70 +++++++++++++++++++++++++++++++++++- 2 files changed, 73 insertions(+), 1 deletion(-) diff --git a/doc/filters.texi b/doc/filters.texi index 1f1890b97db..9690332092a 100644 --- a/doc/filters.texi +++ b/doc/filters.texi @@ -19711,6 +19711,10 @@ Available LUTs: @item spectral @item cool @item heat +@item fiery +@item blues +@item green +@item helix @end table @item opacity diff --git a/libavfilter/vf_pseudocolor.c b/libavfilter/vf_pseudocolor.c index 5b6cd5e70ab..31532e2824e 100644 --- a/libavfilter/vf_pseudocolor.c +++ b/libavfilter/vf_pseudocolor.c @@ -70,6 +70,10 @@ enum Curves { SPECTRAL, COOL, HEAT, + FIERY, + BLUES, + GREEN, + HELIX, NB_CURVES, }; @@ -91,6 +95,10 @@ enum Presets { PRESET_SPECTRAL, PRESET_COOL, PRESET_HEAT, + PRESET_FIERY, + PRESET_BLUES, + PRESET_GREEN, + PRESET_HELIX, NB_PRESETS, }; @@ -162,6 +170,26 @@ static double heatfunv(double x) return 0.25 * sin(2.0 * x * M_PI) + 0.5; } +static double fieryfunu(double x) +{ + return 0.75 - 0.25 * cos(2.0 * x * M_PI); +} + +static double fieryfunv(double x) +{ + return 0.25 + 0.25 * cos(2.0 * x * M_PI); +} + +static double helixfunu(double x) +{ + return 0.5 + 0.15 * sin(5.0 * x * M_PI + M_PI); +} + +static double helixfunv(double x) +{ + return 0.5 + 0.15 * cos(6.0 * x * M_PI + M_PI_2); +} + static const Curve curves[] = { [MAGMA] = {{ @@ -222,6 +250,38 @@ static const Curve curves[] = .offset = { 0., 0., 0 }, .yuv = 1, .fun = { heatfunu, limit, heatfunv }, }, + [FIERY] = {{ + { 0, 0, 0, 0, 0, 0, 1./256, 0 }, + { 0, 0, 0, 0, 0, 0, 1./256, 0 }, + { 0, 0, 0, 0, 0, 0, 1./256, 0 }, + }, + .offset = { 0., 0., 0 }, + .yuv = 1, + .fun = { fieryfunu, limit, fieryfunv }, }, + [BLUES] = {{ + { 0, 0, 0, 0, 0, 0, 1./256, 0 }, + { 0, 0, 0, 0, 0, 0, 1./256, 0 }, + { 0, 0, 0, 0, 0, 0, 1./256, 0 }, + }, + .offset = { 0., 0., 0 }, + .yuv = 1, + .fun = { fieryfunv, limit, fieryfunu }, }, + [GREEN] = {{ + { 0, 0, 0, 0, 0, 0, 1./256, 0 }, + { 0, 0, 0, 0, 0, 0, 1./256, 0 }, + { 0, 0, 0, 0, 0, 0, 1./256, 0 }, + }, + .offset = { 0., 0., 0 }, + .yuv = 1, + .fun = { fieryfunv, limit, fieryfunv }, }, + [HELIX] = {{ + { 0, 0, 0, 0, 0, 0, 1./256, 0 }, + { 0, 0, 0, 0, 0, 0, 1./256, 0 }, + { 0, 0, 0, 0, 0, 0, 1./256, 0 }, + }, + .offset = { 0., 0., 0 }, + .yuv = 1, + .fun = { helixfunu, limit, helixfunv }, }, }; static const Preset presets[] = @@ -242,7 +302,11 @@ static const Preset presets[] = [PRESET_SOLAR] = { 1, &full_range, &curves[SOLAR], NULL }, [PRESET_SPECTRAL]= { 1, &full_range, &curves[SPECTRAL],NULL }, [PRESET_COOL] = { 1, &full_range, &curves[COOL], NULL }, - [PRESET_HEAT]= { 1, &full_range, &curves[HEAT],NULL }, + [PRESET_HEAT] = { 1, &full_range, &curves[HEAT], NULL }, + [PRESET_FIERY] = { 1, &full_range, &curves[FIERY], NULL }, + [PRESET_BLUES] = { 1, &full_range, &curves[BLUES], NULL }, + [PRESET_GREEN] = { 1, &full_range, &curves[GREEN], NULL }, + [PRESET_HELIX] = { 1, &full_range, &curves[HELIX], NULL }, }; typedef struct PseudoColorContext { @@ -300,6 +364,10 @@ static const AVOption pseudocolor_options[] = { { "spectral", NULL, 0, AV_OPT_TYPE_CONST, {.i64=PRESET_SPECTRAL},.flags = FLAGS, "preset" }, { "cool", NULL, 0, AV_OPT_TYPE_CONST, {.i64=PRESET_COOL}, .flags = FLAGS, "preset" }, { "heat", NULL, 0, AV_OPT_TYPE_CONST, {.i64=PRESET_HEAT}, .flags = FLAGS, "preset" }, + { "fiery", NULL, 0, AV_OPT_TYPE_CONST, {.i64=PRESET_FIERY}, .flags = FLAGS, "preset" }, + { "blues", NULL, 0, AV_OPT_TYPE_CONST, {.i64=PRESET_BLUES}, .flags = FLAGS, "preset" }, + { "green", NULL, 0, AV_OPT_TYPE_CONST, {.i64=PRESET_GREEN}, .flags = FLAGS, "preset" }, + { "helix", NULL, 0, AV_OPT_TYPE_CONST, {.i64=PRESET_HELIX}, .flags = FLAGS, "preset" }, { "opacity", "set pseudocolor opacity",OFFSET(opacity), AV_OPT_TYPE_FLOAT, {.dbl=1}, 0, 1, .flags = FLAGS }, { NULL } }; From 86a1904f417cdbeac48f4def86cd51e9b29d1ed1 Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Thu, 20 Jul 2023 22:30:42 +0200 Subject: [PATCH 1974/2172] avfilter/avf_showcwt: move variables out of loop --- libavfilter/avf_showcwt.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libavfilter/avf_showcwt.c b/libavfilter/avf_showcwt.c index 578312cdd6a..51a45ef636d 100644 --- a/libavfilter/avf_showcwt.c +++ b/libavfilter/avf_showcwt.c @@ -634,12 +634,12 @@ static void compute_kernel(AVFilterContext *ctx) const float scale_factor = 1.f/(float)size; const int output_sample_count = s->output_sample_count; const int fsize = s->frequency_band_count; + int *kernel_start = s->kernel_start; + int *kernel_stop = s->kernel_stop; unsigned *index = s->index; for (int y = 0; y < fsize; y++) { AVComplexFloat *kernel = (AVComplexFloat *)s->kernel->extended_data[y]; - int *kernel_start = s->kernel_start; - int *kernel_stop = s->kernel_stop; float frequency = s->frequency_band[y*2]; float deviation = 1.f / (s->frequency_band[y*2+1] * output_sample_count); From 74474a551b63f778776e94d094c5ea55c3639b9b Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Fri, 21 Jul 2023 00:28:01 +0200 Subject: [PATCH 1975/2172] avfilter/avf_showcwt: fix index storing --- libavfilter/avf_showcwt.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavfilter/avf_showcwt.c b/libavfilter/avf_showcwt.c index 51a45ef636d..ee0d697e1e5 100644 --- a/libavfilter/avf_showcwt.c +++ b/libavfilter/avf_showcwt.c @@ -662,7 +662,7 @@ static void compute_kernel(AVFilterContext *ctx) for (int n = 0; n < size; n++) { if (kernel[size - n - 1].re != 0.f) { - kernel_stop[y] = size - n; + kernel_stop[y] = size - n - 1; break; } } From e6bd8b132372f64a3378c069cb9855d3d91bde09 Mon Sep 17 00:00:00 2001 From: Jan Beich Date: Sat, 15 Jul 2023 04:57:47 +0200 Subject: [PATCH 1976/2172] hwcontext_vulkan: hide Linux-only header after 571756bf2fe2 major/minor are in on BSDs and on Solaris-like. libavutil/hwcontext_vulkan.c:55:10: fatal error: 'sys/sysmacros.h' file not found #include ^~~~~~~~~~~~~~~~~ --- libavutil/hwcontext_vulkan.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/libavutil/hwcontext_vulkan.c b/libavutil/hwcontext_vulkan.c index ca802cc86ef..75314f14072 100644 --- a/libavutil/hwcontext_vulkan.c +++ b/libavutil/hwcontext_vulkan.c @@ -52,7 +52,9 @@ #if CONFIG_VAAPI #include #endif +#ifdef __linux__ #include +#endif #include #include #include From c06ad641ec36ea0e9011be8d6182612c22f6196b Mon Sep 17 00:00:00 2001 From: Lynne Date: Wed, 19 Jul 2023 05:39:07 +0200 Subject: [PATCH 1977/2172] lavc/vulkan_decode: use a single execution pool per thread The spec says command buffer pools must be externally synchronized objects. This still lets us pool some, just not as much. --- libavcodec/vulkan_decode.c | 86 ++++++++++++++++++++++++++++---------- libavcodec/vulkan_decode.h | 3 +- 2 files changed, 66 insertions(+), 23 deletions(-) diff --git a/libavcodec/vulkan_decode.c b/libavcodec/vulkan_decode.c index 973c7ca5482..f20733fb391 100644 --- a/libavcodec/vulkan_decode.c +++ b/libavcodec/vulkan_decode.c @@ -42,12 +42,53 @@ static const VkExtensionProperties *dec_ext[] = { #endif }; +static const VkVideoProfileInfoKHR *get_video_profile(FFVulkanDecodeShared *ctx, enum AVCodecID codec_id) +{ + const VkVideoProfileListInfoKHR *profile_list; + + VkStructureType profile_struct_type = + codec_id == AV_CODEC_ID_H264 ? VK_STRUCTURE_TYPE_VIDEO_DECODE_H264_PROFILE_INFO_KHR : + codec_id == AV_CODEC_ID_HEVC ? VK_STRUCTURE_TYPE_VIDEO_DECODE_H265_PROFILE_INFO_KHR : + codec_id == AV_CODEC_ID_AV1 ? VK_STRUCTURE_TYPE_VIDEO_DECODE_AV1_PROFILE_INFO_MESA : + 0; + + profile_list = ff_vk_find_struct(ctx->s.hwfc->create_pnext, + VK_STRUCTURE_TYPE_VIDEO_PROFILE_LIST_INFO_KHR); + if (!profile_list) + return NULL; + + for (int i = 0; i < profile_list->profileCount; i++) + if (ff_vk_find_struct(profile_list->pProfiles[i].pNext, profile_struct_type)) + return &profile_list->pProfiles[i]; + + return NULL; +} + int ff_vk_update_thread_context(AVCodecContext *dst, const AVCodecContext *src) { int err; FFVulkanDecodeContext *src_ctx = src->internal->hwaccel_priv_data; FFVulkanDecodeContext *dst_ctx = dst->internal->hwaccel_priv_data; + if (!dst_ctx->exec_pool.cmd_bufs) { + FFVulkanDecodeShared *ctx = (FFVulkanDecodeShared *)src_ctx->shared_ref->data; + + const VkVideoProfileInfoKHR *profile = get_video_profile(ctx, dst->codec_id); + if (!profile) { + av_log(dst, AV_LOG_ERROR, "Video profile missing from frames context!"); + return AVERROR(EINVAL); + } + + err = ff_vk_exec_pool_init(&ctx->s, &ctx->qf, + &dst_ctx->exec_pool, + src_ctx->exec_pool.pool_size, + src_ctx->exec_pool.nb_queries, + VK_QUERY_TYPE_RESULT_STATUS_ONLY_KHR, 0, + profile); + if (err < 0) + return err; + } + err = av_buffer_replace(&dst_ctx->shared_ref, src_ctx->shared_ref); if (err < 0) return err; @@ -271,7 +312,7 @@ void ff_vk_decode_flush(AVCodecContext *avctx) }; VkCommandBuffer cmd_buf; - FFVkExecContext *exec = ff_vk_exec_get(&ctx->exec_pool); + FFVkExecContext *exec = ff_vk_exec_get(&dec->exec_pool); ff_vk_exec_start(&ctx->s, exec); cmd_buf = exec->buf; @@ -317,7 +358,7 @@ int ff_vk_decode_frame(AVCodecContext *avctx, size_t data_size = FFALIGN(vp->slices_size, ctx->caps.minBitstreamBufferSizeAlignment); - FFVkExecContext *exec = ff_vk_exec_get(&ctx->exec_pool); + FFVkExecContext *exec = ff_vk_exec_get(&dec->exec_pool); /* The current decoding reference has to be bound as an inactive reference */ VkVideoReferenceSlotInfoKHR *cur_vk_ref; @@ -326,7 +367,7 @@ int ff_vk_decode_frame(AVCodecContext *avctx, cur_vk_ref[0].slotIndex = -1; decode_start.referenceSlotCount++; - if (ctx->exec_pool.nb_queries) { + if (dec->exec_pool.nb_queries) { int64_t prev_sub_res = 0; ff_vk_exec_wait(&ctx->s, exec); ret = ff_vk_exec_get_query(&ctx->s, exec, NULL, &prev_sub_res); @@ -495,14 +536,14 @@ int ff_vk_decode_frame(AVCodecContext *avctx, vk->CmdBeginVideoCodingKHR(cmd_buf, &decode_start); /* Start status query */ - if (ctx->exec_pool.nb_queries) - vk->CmdBeginQuery(cmd_buf, ctx->exec_pool.query_pool, exec->query_idx + 0, 0); + if (dec->exec_pool.nb_queries) + vk->CmdBeginQuery(cmd_buf, dec->exec_pool.query_pool, exec->query_idx + 0, 0); vk->CmdDecodeVideoKHR(cmd_buf, &vp->decode_info); /* End status query */ - if (ctx->exec_pool.nb_queries) - vk->CmdEndQuery(cmd_buf, ctx->exec_pool.query_pool, exec->query_idx + 0); + if (dec->exec_pool.nb_queries) + vk->CmdEndQuery(cmd_buf, dec->exec_pool.query_pool, exec->query_idx + 0); vk->CmdEndVideoCodingKHR(cmd_buf, &decode_end); @@ -555,9 +596,6 @@ static void free_common(void *opaque, uint8_t *data) FFVulkanContext *s = &ctx->s; FFVulkanFunctions *vk = &ctx->s.vkfn; - /* Wait on and free execution pool */ - ff_vk_exec_pool_free(s, &ctx->exec_pool); - /* Destroy layered view */ if (ctx->layered_view) vk->DestroyImageView(s->hwctx->act_dev, ctx->layered_view, s->hwctx->alloc); @@ -1029,6 +1067,11 @@ void ff_vk_decode_free_params(void *opaque, uint8_t *data) int ff_vk_decode_uninit(AVCodecContext *avctx) { FFVulkanDecodeContext *dec = avctx->internal->hwaccel_priv_data; + FFVulkanDecodeShared *ctx = (FFVulkanDecodeShared *)dec->shared_ref->data; + + /* Wait on and free execution pool */ + ff_vk_exec_pool_free(&ctx->s, &dec->exec_pool); + av_buffer_pool_uninit(&dec->tmp_pool); av_buffer_unref(&dec->session_params); av_buffer_unref(&dec->shared_ref); @@ -1044,8 +1087,7 @@ int ff_vk_decode_init(AVCodecContext *avctx) FFVulkanDecodeShared *ctx; FFVulkanContext *s; FFVulkanFunctions *vk; - FFVkQueueFamilyCtx qf_dec; - const VkVideoProfileListInfoKHR *profile_list; + const VkVideoProfileInfoKHR *profile; VkVideoDecodeH264SessionParametersCreateInfoKHR h264_params = { .sType = VK_STRUCTURE_TYPE_VIDEO_DECODE_H264_SESSION_PARAMETERS_CREATE_INFO_KHR, @@ -1089,10 +1131,9 @@ int ff_vk_decode_init(AVCodecContext *avctx) s->device = (AVHWDeviceContext *)s->frames->device_ref->data; s->hwctx = s->device->hwctx; - profile_list = ff_vk_find_struct(s->hwfc->create_pnext, - VK_STRUCTURE_TYPE_VIDEO_PROFILE_LIST_INFO_KHR); - if (!profile_list) { - av_log(avctx, AV_LOG_ERROR, "Profile list missing from frames context!"); + profile = get_video_profile(ctx, avctx->codec_id); + if (!profile) { + av_log(avctx, AV_LOG_ERROR, "Video profile missing from frames context!"); return AVERROR(EINVAL); } @@ -1101,7 +1142,7 @@ int ff_vk_decode_init(AVCodecContext *avctx) goto fail; /* Create queue context */ - qf = ff_vk_qf_init(s, &qf_dec, VK_QUEUE_VIDEO_DECODE_BIT_KHR); + qf = ff_vk_qf_init(s, &ctx->qf, VK_QUEUE_VIDEO_DECODE_BIT_KHR); /* Check for support */ if (!(s->video_props[qf].videoCodecOperations & @@ -1123,14 +1164,14 @@ int ff_vk_decode_init(AVCodecContext *avctx) session_create.pictureFormat = s->hwfc->format[0]; session_create.referencePictureFormat = session_create.pictureFormat; session_create.pStdHeaderVersion = dec_ext[avctx->codec_id]; - session_create.pVideoProfile = &profile_list->pProfiles[0]; + session_create.pVideoProfile = profile; - /* Create decode exec context. + /* Create decode exec context for this specific main thread. * 2 async contexts per thread was experimentally determined to be optimal * for a majority of streams. */ - err = ff_vk_exec_pool_init(s, &qf_dec, &ctx->exec_pool, 2*avctx->thread_count, + err = ff_vk_exec_pool_init(s, &ctx->qf, &dec->exec_pool, 2, nb_q, VK_QUERY_TYPE_RESULT_STATUS_ONLY_KHR, 0, - session_create.pVideoProfile); + profile); if (err < 0) goto fail; @@ -1168,7 +1209,8 @@ int ff_vk_decode_init(AVCodecContext *avctx) dpb_frames->height = s->frames->height; dpb_hwfc = dpb_frames->hwctx; - dpb_hwfc->create_pnext = (void *)profile_list; + dpb_hwfc->create_pnext = (void *)ff_vk_find_struct(ctx->s.hwfc->create_pnext, + VK_STRUCTURE_TYPE_VIDEO_PROFILE_LIST_INFO_KHR); dpb_hwfc->format[0] = s->hwfc->format[0]; dpb_hwfc->tiling = VK_IMAGE_TILING_OPTIMAL; dpb_hwfc->usage = VK_IMAGE_USAGE_VIDEO_DECODE_DPB_BIT_KHR | diff --git a/libavcodec/vulkan_decode.h b/libavcodec/vulkan_decode.h index 4e45cbde715..1b4e1cc712a 100644 --- a/libavcodec/vulkan_decode.h +++ b/libavcodec/vulkan_decode.h @@ -37,7 +37,7 @@ typedef struct FFVulkanDecodeProfileData { typedef struct FFVulkanDecodeShared { FFVulkanContext s; FFVkVideoCommon common; - FFVkExecPool exec_pool; + FFVkQueueFamilyCtx qf; VkVideoCapabilitiesKHR caps; VkVideoDecodeCapabilitiesKHR dec_caps; @@ -56,6 +56,7 @@ typedef struct FFVulkanDecodeShared { typedef struct FFVulkanDecodeContext { AVBufferRef *shared_ref; AVBufferRef *session_params; + FFVkExecPool exec_pool; int dedicated_dpb; /* Oddity #1 - separate DPB images */ int layered_dpb; /* Madness #1 - layered DPB images */ From 97890c2b553aa2447c0ea1a3cea37f25f59a3449 Mon Sep 17 00:00:00 2001 From: Lynne Date: Wed, 19 Jul 2023 04:54:37 +0200 Subject: [PATCH 1978/2172] lavu/vulkan: remove threadsafe buffer index load and fix a signed overflow It's not needed anymore. --- libavutil/vulkan.c | 4 +--- libavutil/vulkan.h | 2 +- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/libavutil/vulkan.c b/libavutil/vulkan.c index 26b9b6f1fb2..48f5f4b5dc4 100644 --- a/libavutil/vulkan.c +++ b/libavutil/vulkan.c @@ -282,8 +282,6 @@ int ff_vk_exec_pool_init(FFVulkanContext *s, FFVkQueueFamilyCtx *qf, VkCommandPoolCreateInfo cqueue_create; VkCommandBufferAllocateInfo cbuf_create; - atomic_init(&pool->idx, 0); - /* Create command pool */ cqueue_create = (VkCommandPoolCreateInfo) { .sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO, @@ -472,7 +470,7 @@ VkResult ff_vk_exec_get_query(FFVulkanContext *s, FFVkExecContext *e, FFVkExecContext *ff_vk_exec_get(FFVkExecPool *pool) { - int idx = atomic_fetch_add_explicit(&pool->idx, 1, memory_order_relaxed); + uint32_t idx = pool->idx++; idx %= pool->pool_size; return &pool->contexts[idx]; } diff --git a/libavutil/vulkan.h b/libavutil/vulkan.h index bbbc9374aee..7171fb3c429 100644 --- a/libavutil/vulkan.h +++ b/libavutil/vulkan.h @@ -151,7 +151,7 @@ typedef struct FFVulkanPipeline { } FFVulkanPipeline; typedef struct FFVkExecContext { - int idx; + uint32_t idx; const struct FFVkExecPool *parent; pthread_mutex_t lock; From 3e3d46309bfb4049c4bcea3d219be7bd299b6ab7 Mon Sep 17 00:00:00 2001 From: Lynne Date: Wed, 19 Jul 2023 05:38:32 +0200 Subject: [PATCH 1979/2172] lavu/vulkan: remove unused field from the execution pool structure --- libavutil/vulkan.h | 1 - 1 file changed, 1 deletion(-) diff --git a/libavutil/vulkan.h b/libavutil/vulkan.h index 7171fb3c429..20b81105dd8 100644 --- a/libavutil/vulkan.h +++ b/libavutil/vulkan.h @@ -208,7 +208,6 @@ typedef struct FFVkExecContext { } FFVkExecContext; typedef struct FFVkExecPool { - FFVkQueueFamilyCtx *qf; FFVkExecContext *contexts; atomic_int_least64_t idx; From e6a12a5214b8d14f1fe88c655548e411c1503ff9 Mon Sep 17 00:00:00 2001 From: Lynne Date: Fri, 21 Jul 2023 19:34:00 +0200 Subject: [PATCH 1980/2172] vulkan_av1: remove an invalid debug print Leftover. --- libavcodec/vulkan_av1.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/libavcodec/vulkan_av1.c b/libavcodec/vulkan_av1.c index e06457bbc33..d0f4019248d 100644 --- a/libavcodec/vulkan_av1.c +++ b/libavcodec/vulkan_av1.c @@ -484,8 +484,6 @@ static int vk_av1_start_frame(AVCodecContext *avctx, ap->av1_frame_header.film_grain.ar_coeffs_cr_plus_128[24] = film_grain->ar_coeffs_cr_plus_128[24]; } - av_log(avctx, AV_LOG_DEBUG, "Created frame parameters"); - /* Workaround for a spec issue. */ ap->dec = dec; From d3948e4db50666da05368d2bc84134fea2e20006 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9mi=20Denis-Courmont?= Date: Tue, 18 Jul 2023 21:11:15 +0300 Subject: [PATCH 1981/2172] swscale: inline ff_shuffle_bytes_3210_rvv No functional changes. --- libswscale/riscv/rgb2rgb_rvv.S | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/libswscale/riscv/rgb2rgb_rvv.S b/libswscale/riscv/rgb2rgb_rvv.S index bbdfdbebbc8..8f30d760cbd 100644 --- a/libswscale/riscv/rgb2rgb_rvv.S +++ b/libswscale/riscv/rgb2rgb_rvv.S @@ -74,7 +74,24 @@ func ff_shuffle_bytes_3210_rvv, zve32x addi t2, a0, 1 addi t3, a0, 0 addi a0, a0, 3 - j 1b + srai a2, a2, 2 + li t4, 4 +1: + vsetvli t0, a2, e8, m1, ta, ma + sub a2, a2, t0 + vlse8.v v8, (a0), t4 + sh2add a0, t0, a0 + vlse8.v v9, (t1), t4 + sh2add t1, t0, t1 + vlse8.v v10, (t2), t4 + sh2add t2, t0, t2 + vlse8.v v11, (t3), t4 + sh2add t3, t0, t3 + vsseg4e8.v v8, (a1) + sh2add a1, t0, a1 + bnez a2, 1b + + ret endfunc func ff_interleave_bytes_rvv, zve32x From 15982554e694e3ccf8d72677e401ded86ca5605b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9mi=20Denis-Courmont?= Date: Tue, 18 Jul 2023 21:39:59 +0300 Subject: [PATCH 1982/2172] swscale/rgb2rgb2: rework RISC-V V shuffle_bytes_{0321,2103} This avoids strided loads. Before: shuffle_bytes_0321_rvv_i32: 307.7 shuffle_bytes_2103_rvv_i32: 308.7 After: shuffle_bytes_0321_rvv_i32: 59.7 shuffle_bytes_2103_rvv_i32: 61.5 --- libswscale/riscv/rgb2rgb_rvv.S | 45 +++++++++++++++------------------- 1 file changed, 20 insertions(+), 25 deletions(-) diff --git a/libswscale/riscv/rgb2rgb_rvv.S b/libswscale/riscv/rgb2rgb_rvv.S index 8f30d760cbd..366f80c1c39 100644 --- a/libswscale/riscv/rgb2rgb_rvv.S +++ b/libswscale/riscv/rgb2rgb_rvv.S @@ -21,38 +21,33 @@ #include "libavutil/riscv/asm.S" func ff_shuffle_bytes_0321_rvv, zve32x - addi t1, a0, 3 - addi t2, a0, 2 - addi t3, a0, 1 + li t1, 0x00ff00ff + j 1f +endfunc + +func ff_shuffle_bytes_2103_rvv, zve32x + li t1, ~0x00ff00ff 1: + not t2, t1 srai a2, a2, 2 - li t4, 4 2: - vsetvli t0, a2, e8, m1, ta, ma - sub a2, a2, t0 - vlse8.v v8, (a0), t4 - sh2add a0, t0, a0 - vlse8.v v9, (t1), t4 - sh2add t1, t0, t1 - vlse8.v v10, (t2), t4 - sh2add t2, t0, t2 - vlse8.v v11, (t3), t4 - sh2add t3, t0, t3 - vsseg4e8.v v8, (a1) - sh2add a1, t0, a1 - bnez a2, 2b + vsetvli t0, a2, e32, m8, ta, ma + vle32.v v8, (a0) + sub a2, a2, t0 + vand.vx v16, v8, t2 + sh2add a0, t0, a0 + vand.vx v8, v8, t1 + vsrl.vi v24, v16, 16 + vsll.vi v16, v16, 16 + vor.vv v8, v8, v24 + vor.vv v8, v16, v8 + vse32.v v8, (a1) + sh2add a1, t0, a1 + bnez a2, 2b ret endfunc -func ff_shuffle_bytes_2103_rvv, zve32x - addi t1, a0, 1 - addi t2, a0, 0 - addi t3, a0, 3 - addi a0, a0, 2 - j 1b -endfunc - func ff_shuffle_bytes_1230_rvv, zve32x addi t1, a0, 2 addi t2, a0, 3 From c2b38619c081658b303d1669155803d2aebf3f6a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9mi=20Denis-Courmont?= Date: Tue, 18 Jul 2023 20:25:13 +0300 Subject: [PATCH 1983/2172] swscale/rgb2rgb2: rework RISC-V V shuffle_bytes_{1230,3012} This avoids strided loads. Before: shuffle_bytes_1230_rvv_i32: 308.7 shuffle_bytes_3012_rvv_i32: 308.7 After: shuffle_bytes_1230_rvv_i32: 46.7 shuffle_bytes_3012_rvv_i32: 46.7 --- libswscale/riscv/rgb2rgb_rvv.S | 30 ++++++++++++++++++++---------- 1 file changed, 20 insertions(+), 10 deletions(-) diff --git a/libswscale/riscv/rgb2rgb_rvv.S b/libswscale/riscv/rgb2rgb_rvv.S index 366f80c1c39..0ac3afff7c7 100644 --- a/libswscale/riscv/rgb2rgb_rvv.S +++ b/libswscale/riscv/rgb2rgb_rvv.S @@ -49,19 +49,29 @@ func ff_shuffle_bytes_2103_rvv, zve32x endfunc func ff_shuffle_bytes_1230_rvv, zve32x - addi t1, a0, 2 - addi t2, a0, 3 - addi t3, a0, 0 - addi a0, a0, 1 - j 1b + li t1, 24 + li t2, 8 + j 3f endfunc func ff_shuffle_bytes_3012_rvv, zve32x - addi t1, a0, 0 - addi t2, a0, 1 - addi t3, a0, 2 - addi a0, a0, 3 - j 1b + li t1, 8 + li t2, 24 +3: + srai a2, a2, 2 +4: + vsetvli t0, a2, e32, m8, ta, ma + vle32.v v8, (a0) + sub a2, a2, t0 + vsll.vx v16, v8, t1 + sh2add a0, t0, a0 + vsrl.vx v8, v8, t2 + vor.vv v16, v16, v8 + vse32.v v16, (a1) + sh2add a1, t0, a1 + bnez a2, 4b + + ret endfunc func ff_shuffle_bytes_3210_rvv, zve32x From a4e616824b785df2a3598a47a306e2242bbe3a25 Mon Sep 17 00:00:00 2001 From: Kieran Kunhya Date: Sat, 17 Dec 2022 21:53:27 +0000 Subject: [PATCH 1984/2172] libavutil: Remove TOMI CPU --- configure | 1 - libavutil/intreadwrite.h | 2 - libavutil/tomi/intreadwrite.h | 150 ---------------------------------- 3 files changed, 153 deletions(-) delete mode 100644 libavutil/tomi/intreadwrite.h diff --git a/configure b/configure index d46e868a0cb..eb2fe392b41 100755 --- a/configure +++ b/configure @@ -2089,7 +2089,6 @@ ARCH_LIST=" sparc64 tilegx tilepro - tomi x86 x86_32 x86_64 diff --git a/libavutil/intreadwrite.h b/libavutil/intreadwrite.h index 4c8413a5368..c4679fdba4c 100644 --- a/libavutil/intreadwrite.h +++ b/libavutil/intreadwrite.h @@ -72,8 +72,6 @@ typedef union { # include "mips/intreadwrite.h" #elif ARCH_PPC # include "ppc/intreadwrite.h" -#elif ARCH_TOMI -# include "tomi/intreadwrite.h" #elif ARCH_X86 # include "x86/intreadwrite.h" #endif diff --git a/libavutil/tomi/intreadwrite.h b/libavutil/tomi/intreadwrite.h deleted file mode 100644 index 7dec4158d3c..00000000000 --- a/libavutil/tomi/intreadwrite.h +++ /dev/null @@ -1,150 +0,0 @@ -/* - * Copyright (c) 2010 Mans Rullgard - * - * 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_TOMI_INTREADWRITE_H -#define AVUTIL_TOMI_INTREADWRITE_H - -#include - -#include "config.h" -#include "libavutil/attributes.h" - -#define AV_RB16 AV_RB16 -static av_always_inline uint16_t AV_RB16(const void *p) -{ - uint16_t v; - __asm__ ("loadacc, (%1+) \n\t" - "rol8 \n\t" - "storeacc, %0 \n\t" - "loadacc, (%1+) \n\t" - "add, %0 \n\t" - : "=r"(v), "+a"(p)); - return v; -} - -#define AV_WB16 AV_WB16 -static av_always_inline void AV_WB16(void *p, uint16_t v) -{ - __asm__ volatile ("loadacc, %1 \n\t" - "lsr8 \n\t" - "storeacc, (%0+) \n\t" - "loadacc, %1 \n\t" - "storeacc, (%0+) \n\t" - : "+&a"(p) : "r"(v)); -} - -#define AV_RL16 AV_RL16 -static av_always_inline uint16_t AV_RL16(const void *p) -{ - uint16_t v; - __asm__ ("loadacc, (%1+) \n\t" - "storeacc, %0 \n\t" - "loadacc, (%1+) \n\t" - "rol8 \n\t" - "add, %0 \n\t" - : "=r"(v), "+a"(p)); - return v; -} - -#define AV_WL16 AV_WL16 -static av_always_inline void AV_WL16(void *p, uint16_t v) -{ - __asm__ volatile ("loadacc, %1 \n\t" - "storeacc, (%0+) \n\t" - "lsr8 \n\t" - "storeacc, (%0+) \n\t" - : "+&a"(p) : "r"(v)); -} - -#define AV_RB32 AV_RB32 -static av_always_inline uint32_t AV_RB32(const void *p) -{ - uint32_t v; - __asm__ ("loadacc, (%1+) \n\t" - "rol8 \n\t" - "rol8 \n\t" - "rol8 \n\t" - "storeacc, %0 \n\t" - "loadacc, (%1+) \n\t" - "rol8 \n\t" - "rol8 \n\t" - "add, %0 \n\t" - "loadacc, (%1+) \n\t" - "rol8 \n\t" - "add, %0 \n\t" - "loadacc, (%1+) \n\t" - "add, %0 \n\t" - : "=r"(v), "+a"(p)); - return v; -} - -#define AV_WB32 AV_WB32 -static av_always_inline void AV_WB32(void *p, uint32_t v) -{ - __asm__ volatile ("loadacc, #4 \n\t" - "add, %0 \n\t" - "loadacc, %1 \n\t" - "storeacc, (-%0) \n\t" - "lsr8 \n\t" - "storeacc, (-%0) \n\t" - "lsr8 \n\t" - "storeacc, (-%0) \n\t" - "lsr8 \n\t" - "storeacc, (-%0) \n\t" - : "+&a"(p) : "r"(v)); -} - -#define AV_RL32 AV_RL32 -static av_always_inline uint32_t AV_RL32(const void *p) -{ - uint32_t v; - __asm__ ("loadacc, (%1+) \n\t" - "storeacc, %0 \n\t" - "loadacc, (%1+) \n\t" - "rol8 \n\t" - "add, %0 \n\t" - "loadacc, (%1+) \n\t" - "rol8 \n\t" - "rol8 \n\t" - "add, %0 \n\t" - "loadacc, (%1+) \n\t" - "rol8 \n\t" - "rol8 \n\t" - "rol8 \n\t" - "add, %0 \n\t" - : "=r"(v), "+a"(p)); - return v; -} - -#define AV_WL32 AV_WL32 -static av_always_inline void AV_WL32(void *p, uint32_t v) -{ - __asm__ volatile ("loadacc, %1 \n\t" - "storeacc, (%0+) \n\t" - "lsr8 \n\t" - "storeacc, (%0+) \n\t" - "lsr8 \n\t" - "storeacc, (%0+) \n\t" - "lsr8 \n\t" - "storeacc, (%0+) \n\t" - : "+&a"(p) : "r"(v)); -} - -#endif /* AVUTIL_TOMI_INTREADWRITE_H */ From 8f48a62151f4a299574959df9a48813303ef4edb Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Tue, 30 May 2023 02:59:11 +0200 Subject: [PATCH 1985/2172] avutil/tx_template: extend to 2M Signed-off-by: Michael Niedermayer --- libavutil/tx_template.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/libavutil/tx_template.c b/libavutil/tx_template.c index 983de75a479..c4ec9502e02 100644 --- a/libavutil/tx_template.c +++ b/libavutil/tx_template.c @@ -43,6 +43,10 @@ SR_TABLE(32768) \ SR_TABLE(65536) \ SR_TABLE(131072) \ + SR_TABLE(262144) \ + SR_TABLE(524288) \ + SR_TABLE(1048576) \ + SR_TABLE(2097152) \ #define SR_TABLE(len) \ TABLE_DEF(len, len/4 + 1); @@ -717,6 +721,10 @@ DECL_SR_CODELET(16384,8192,4096) DECL_SR_CODELET(32768,16384,8192) DECL_SR_CODELET(65536,32768,16384) DECL_SR_CODELET(131072,65536,32768) +DECL_SR_CODELET(262144,131072,65536) +DECL_SR_CODELET(524288,262144,131072) +DECL_SR_CODELET(1048576,524288,262144) +DECL_SR_CODELET(2097152,1048576,524288) static av_cold int TX_NAME(ff_tx_fft_init)(AVTXContext *s, const FFTXCodelet *cd, @@ -1947,6 +1955,10 @@ const FFTXCodelet * const TX_NAME(ff_tx_codelet_list)[] = { &TX_NAME(ff_tx_fft32768_ns_def), &TX_NAME(ff_tx_fft65536_ns_def), &TX_NAME(ff_tx_fft131072_ns_def), + &TX_NAME(ff_tx_fft262144_ns_def), + &TX_NAME(ff_tx_fft524288_ns_def), + &TX_NAME(ff_tx_fft1048576_ns_def), + &TX_NAME(ff_tx_fft2097152_ns_def), /* Prime factor codelets */ &TX_NAME(ff_tx_fft3_ns_def), From 94d44dbe212b3ecb67256c4edfc3d7c3c3ac4472 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Mon, 5 Jun 2023 15:56:58 +0200 Subject: [PATCH 1986/2172] avcodec/pcm: allow Changing parameters SDR needs this for switching between mono and stereo stations Signed-off-by: Michael Niedermayer --- libavcodec/pcm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavcodec/pcm.c b/libavcodec/pcm.c index 23955ba2ddf..467ecb4fe09 100644 --- a/libavcodec/pcm.c +++ b/libavcodec/pcm.c @@ -578,7 +578,7 @@ const FFCodec ff_ ## name_ ## _decoder = { \ .priv_data_size = sizeof(PCMDecode), \ .init = pcm_decode_init, \ FF_CODEC_DECODE_CB(pcm_decode_frame), \ - .p.capabilities = AV_CODEC_CAP_DR1, \ + .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_PARAM_CHANGE, \ .p.sample_fmts = (const enum AVSampleFormat[]){ sample_fmt_, \ AV_SAMPLE_FMT_NONE }, \ } From cf00f60bab1f79213c274a6cd4357b32bd5c0101 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Wed, 14 Jun 2023 17:22:55 +0200 Subject: [PATCH 1987/2172] avcodec/kbdwin: Support arbitrary sized windows Signed-off-by: Michael Niedermayer --- libavcodec/kbdwin.c | 22 ++++++++++++++-------- libavcodec/kbdwin.h | 8 +++++--- 2 files changed, 19 insertions(+), 11 deletions(-) diff --git a/libavcodec/kbdwin.c b/libavcodec/kbdwin.c index 163f9d5251f..82755874d41 100644 --- a/libavcodec/kbdwin.c +++ b/libavcodec/kbdwin.c @@ -19,20 +19,23 @@ #include "libavutil/avassert.h" #include "libavutil/mathematics.h" #include "libavutil/attributes.h" +#include "libavutil/mem.h" #include "kbdwin.h" -av_cold static void kbd_window_init(float *float_window, int *int_window, float alpha, int n) +av_cold static int kbd_window_init(float *float_window, int *int_window, float alpha, int n) { int i; double sum = 0.0, tmp; double scale = 0.0; - double temp[FF_KBD_WINDOW_MAX / 2 + 1]; + double temp_small[FF_KBD_WINDOW_MAX / 2 + 1]; + double *temp= n<=FF_KBD_WINDOW_MAX ? temp_small : av_malloc((n/2+1) * sizeof(*temp)); double alpha2 = 4 * (alpha * M_PI / n) * (alpha * M_PI / n); - av_assert0(n <= FF_KBD_WINDOW_MAX); + if (!temp) + return AVERROR(ENOMEM); for (i = 0; i <= n / 2; i++) { - tmp = i * (n - i) * alpha2; + tmp = alpha2 * i * (n - i); temp[i] = av_bessel_i0(sqrt(tmp)); scale += temp[i] * (1 + (i && i Date: Fri, 16 Jun 2023 19:22:49 +0200 Subject: [PATCH 1988/2172] avcodec: Rename ff_kbd_window_init() as it will be needed from outside libavcodec Signed-off-by: Michael Niedermayer --- libavcodec/aacdec_template.c | 8 ++++---- libavcodec/aactab.c | 4 ++-- libavcodec/ac3dec.c | 2 +- libavcodec/ac3enc_fixed.c | 2 +- libavcodec/ac3enc_float.c | 2 +- libavcodec/dolby_e.c | 4 ++-- libavcodec/kbdwin.c | 4 ++-- libavcodec/kbdwin.h | 6 +++--- 8 files changed, 16 insertions(+), 16 deletions(-) diff --git a/libavcodec/aacdec_template.c b/libavcodec/aacdec_template.c index 444dc4fa9d5..2385ea58b0a 100644 --- a/libavcodec/aacdec_template.c +++ b/libavcodec/aacdec_template.c @@ -1159,8 +1159,8 @@ static av_cold void aac_static_table_init(void) 352); // window initialization - AAC_RENAME(ff_kbd_window_init)(AAC_RENAME(aac_kbd_long_960), 4.0, 960); - AAC_RENAME(ff_kbd_window_init)(AAC_RENAME(aac_kbd_short_120), 6.0, 120); + AAC_RENAME(avpriv_kbd_window_init)(AAC_RENAME(aac_kbd_long_960), 4.0, 960); + AAC_RENAME(avpriv_kbd_window_init)(AAC_RENAME(aac_kbd_short_120), 6.0, 120); #if !USE_FIXED AAC_RENAME(ff_sine_window_init)(AAC_RENAME(sine_960), 960); @@ -1168,8 +1168,8 @@ static av_cold void aac_static_table_init(void) AAC_RENAME(ff_init_ff_sine_windows)(9); ff_aac_float_common_init(); #else - AAC_RENAME(ff_kbd_window_init)(AAC_RENAME2(aac_kbd_long_1024), 4.0, 1024); - AAC_RENAME(ff_kbd_window_init)(AAC_RENAME2(aac_kbd_short_128), 6.0, 128); + AAC_RENAME(avpriv_kbd_window_init)(AAC_RENAME2(aac_kbd_long_1024), 4.0, 1024); + AAC_RENAME(avpriv_kbd_window_init)(AAC_RENAME2(aac_kbd_short_128), 6.0, 128); init_sine_windows_fixed(); #endif diff --git a/libavcodec/aactab.c b/libavcodec/aactab.c index 0f4941d5dff..d0006eac35e 100644 --- a/libavcodec/aactab.c +++ b/libavcodec/aactab.c @@ -48,8 +48,8 @@ DECLARE_ALIGNED(32, float, ff_aac_kbd_short_128)[128]; static av_cold void aac_float_common_init(void) { - ff_kbd_window_init(ff_aac_kbd_long_1024, 4.0, 1024); - ff_kbd_window_init(ff_aac_kbd_short_128, 6.0, 128); + avpriv_kbd_window_init(ff_aac_kbd_long_1024, 4.0, 1024); + avpriv_kbd_window_init(ff_aac_kbd_short_128, 6.0, 128); ff_init_ff_sine_windows(10); ff_init_ff_sine_windows(7); } diff --git a/libavcodec/ac3dec.c b/libavcodec/ac3dec.c index fc0cbeb4938..8c63f015f44 100644 --- a/libavcodec/ac3dec.c +++ b/libavcodec/ac3dec.c @@ -228,7 +228,7 @@ static av_cold int ac3_decode_init(AVCodecContext *avctx) if ((ret = av_tx_init(&s->tx_256, &s->tx_fn_256, IMDCT_TYPE, 1, 256, &scale, 0))) return ret; - AC3_RENAME(ff_kbd_window_init)(s->window, 5.0, 256); + AC3_RENAME(avpriv_kbd_window_init)(s->window, 5.0, 256); ff_bswapdsp_init(&s->bdsp); #if (USE_FIXED) diff --git a/libavcodec/ac3enc_fixed.c b/libavcodec/ac3enc_fixed.c index 88dfd66b91d..079a43dc39a 100644 --- a/libavcodec/ac3enc_fixed.c +++ b/libavcodec/ac3enc_fixed.c @@ -82,7 +82,7 @@ static av_cold int ac3_fixed_mdct_init(AC3EncodeContext *s) if (!iwin) return AVERROR(ENOMEM); - ff_kbd_window_init(fwin, 5.0, AC3_BLOCK_SIZE); + avpriv_kbd_window_init(fwin, 5.0, AC3_BLOCK_SIZE); for (int i = 0; i < AC3_BLOCK_SIZE; i++) iwin[i] = lrintf(fwin[i] * (1 << 22)); diff --git a/libavcodec/ac3enc_float.c b/libavcodec/ac3enc_float.c index ae351a535e9..9664adbf638 100644 --- a/libavcodec/ac3enc_float.c +++ b/libavcodec/ac3enc_float.c @@ -92,7 +92,7 @@ static av_cold int ac3_float_mdct_init(AC3EncodeContext *s) return AVERROR(ENOMEM); } - ff_kbd_window_init(window, 5.0, AC3_BLOCK_SIZE); + avpriv_kbd_window_init(window, 5.0, AC3_BLOCK_SIZE); s->mdct_window = window; return av_tx_init(&s->tx, &s->tx_fn, AV_TX_FLOAT_MDCT, 0, diff --git a/libavcodec/dolby_e.c b/libavcodec/dolby_e.c index 921c33f3ba5..b8dac0fa3f8 100644 --- a/libavcodec/dolby_e.c +++ b/libavcodec/dolby_e.c @@ -1200,7 +1200,7 @@ static av_cold void init_tables(void) gain_tab[i] = exp2f((i - 960) / 64.0f); // short 1 - ff_kbd_window_init(window, 3.0f, 128); + avpriv_kbd_window_init(window, 3.0f, 128); for (i = 0; i < 128; i++) window[128 + i] = window[127 - i]; @@ -1227,7 +1227,7 @@ static av_cold void init_tables(void) window[1088 + i] = 1.0f; // long - ff_kbd_window_init(window + 1408, 3.0f, 256); + avpriv_kbd_window_init(window + 1408, 3.0f, 256); for (i = 0; i < 640; i++) window[1664 + i] = 1.0f; for (i = 0; i < 256; i++) diff --git a/libavcodec/kbdwin.c b/libavcodec/kbdwin.c index 82755874d41..eacdb467742 100644 --- a/libavcodec/kbdwin.c +++ b/libavcodec/kbdwin.c @@ -56,12 +56,12 @@ av_cold static int kbd_window_init(float *float_window, int *int_window, float a return 0; } -av_cold int ff_kbd_window_init(float *window, float alpha, int n) +av_cold int avpriv_kbd_window_init(float *window, float alpha, int n) { return kbd_window_init(window, NULL, alpha, n); } -av_cold int ff_kbd_window_init_fixed(int32_t *window, float alpha, int n) +av_cold int avpriv_kbd_window_init_fixed(int32_t *window, float alpha, int n) { return kbd_window_init(NULL, window, alpha, n); } diff --git a/libavcodec/kbdwin.h b/libavcodec/kbdwin.h index 452fc46596e..0cb2073c5fe 100644 --- a/libavcodec/kbdwin.h +++ b/libavcodec/kbdwin.h @@ -22,7 +22,7 @@ #include /** - * Maximum window size for ff_kbd_window_init. + * Maximum window size for avpriv_kbd_window_init. */ #define FF_KBD_WINDOW_MAX 1024 @@ -34,7 +34,7 @@ * * @return if n is larger than FF_KBD_WINDOW_MAX then AVERROR(ENOMEM) is possible */ -int ff_kbd_window_init(float *window, float alpha, int n); -int ff_kbd_window_init_fixed(int32_t *window, float alpha, int n); +int avpriv_kbd_window_init(float *window, float alpha, int n); +int avpriv_kbd_window_init_fixed(int32_t *window, float alpha, int n); #endif /* AVCODEC_KBDWIN_H */ From 167b4f56f187edafd94fa2e706897ac3bb450511 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Sun, 9 Apr 2023 16:01:35 +0200 Subject: [PATCH 1989/2172] avformat/rka: bps < 8 is invalid Fixes: division by zero Fixes: 57828/clusterfuzz-testcase-minimized-ffmpeg_dem_RKA_fuzzer-6571818338353152 Found-by: continuous fuzzing process https://github.com/google/oss-fuzz/tree/master/projects/ffmpeg Signed-off-by: Michael Niedermayer --- libavformat/rka.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavformat/rka.c b/libavformat/rka.c index 39e5b3bce12..36e25ade017 100644 --- a/libavformat/rka.c +++ b/libavformat/rka.c @@ -72,7 +72,7 @@ static int rka_read_header(AVFormatContext *s) if (channels == 0) return AVERROR_INVALIDDATA; bps = par->extradata[13]; - if (bps == 0) + if (bps < 8) return AVERROR_INVALIDDATA; size_offset = avio_rl32(s->pb); framepos = avio_tell(s->pb); From f9b29451e422e672595e95eefd03879a4398a1f6 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Fri, 30 Jun 2023 01:24:20 +0200 Subject: [PATCH 1990/2172] avcodec/rka: Fix integer overflow in decode_filter() Fixes: signed integer overflow: 2147443649 + 65535 cannot be represented in type 'int' Fixes: 60054/clusterfuzz-testcase-minimized-ffmpeg_AV_CODEC_ID_RKA_fuzzer-5095674572832768 Found-by: continuous fuzzing process https://github.com/google/oss-fuzz/tree/master/projects/ffmpeg Signed-off-by: Michael Niedermayer --- libavcodec/rka.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavcodec/rka.c b/libavcodec/rka.c index d56f4faee4b..7646d776bea 100644 --- a/libavcodec/rka.c +++ b/libavcodec/rka.c @@ -745,7 +745,7 @@ static int decode_filter(RKAContext *s, ChContext *ctx, ACoder *ac, int off, uns } ctx->buf1[off] = sum - ctx->buf0[off + -1]; ctx->buf0[off] = sum; - m += FFABS(ctx->buf1[off]); + m += (unsigned)FFABS(ctx->buf1[off]); } } if (ctx->cmode2 != 0) { From c41ab871c703bc41a4753c784adff1c5fe3795ca Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Fri, 30 Jun 2023 01:57:03 +0200 Subject: [PATCH 1991/2172] avformat/id3v2: Free buffer in decode_str() Fixes: memleak Fixes: 60058/clusterfuzz-testcase-minimized-ffmpeg_dem_IFF_fuzzer-5665259244093440 Found-by: continuous fuzzing process https://github.com/google/oss-fuzz/tree/master/projects/ffmpeg Signed-off-by: Michael Niedermayer --- libavformat/id3v2.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/libavformat/id3v2.c b/libavformat/id3v2.c index 38c86a8e79e..69193933e0b 100644 --- a/libavformat/id3v2.c +++ b/libavformat/id3v2.c @@ -309,8 +309,10 @@ static int decode_str(AVFormatContext *s, AVIOContext *pb, int encoding, avio_w8(dynbuf, 0); dynsize = avio_close_dyn_buf(dynbuf, dst); - if (dynsize <= 0) + if (dynsize <= 0) { + av_freep(dst); return AVERROR(ENOMEM); + } *maxread = left; return 0; From e6168e43a2eec4757cc8d7f981f9d29e1f12dbed Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Fri, 21 Jul 2023 23:11:11 +0200 Subject: [PATCH 1992/2172] avfilter/avf_showcwt: improve analysis Make inverse FFT step always power of 2 in size. --- libavfilter/avf_showcwt.c | 78 +++++++++++++++++++++------------------ 1 file changed, 42 insertions(+), 36 deletions(-) diff --git a/libavfilter/avf_showcwt.c b/libavfilter/avf_showcwt.c index ee0d697e1e5..ef6798e9cf4 100644 --- a/libavfilter/avf_showcwt.c +++ b/libavfilter/avf_showcwt.c @@ -69,14 +69,10 @@ typedef struct ShowCWTContext { char *rate_str; AVRational auto_frame_rate; AVRational frame_rate; - AVTXContext **fft; - AVTXContext **ifft; - av_tx_fn tx_fn; - av_tx_fn itx_fn; - int fft_in_size; - int fft_out_size; - int ifft_in_size; - int ifft_out_size; + AVTXContext **fft, **ifft; + av_tx_fn tx_fn, itx_fn; + int fft_in_size, fft_out_size; + int ifft_in_size, ifft_out_size; int pos; int64_t in_pts; int64_t old_pts; @@ -84,8 +80,7 @@ typedef struct ShowCWTContext { float *frequency_band; AVFrame *kernel; unsigned *index; - int *kernel_start; - int *kernel_stop; + int *kernel_start, *kernel_stop; AVFrame *cache; AVFrame *outpicref; AVFrame *fft_in; @@ -105,19 +100,14 @@ typedef struct ShowCWTContext { int slide; int new_frame; int direction; - int hop_size; - int hop_index; - int ihop_size; - int ihop_index; - int input_padding_size; - int input_sample_count; - int output_padding_size; - int output_sample_count; + int hop_size, ihop_size; + int hop_index, ihop_index; + int input_padding_size, output_padding_size; + int input_sample_count, output_sample_count; int frequency_band_count; float logarithmic_basis; int frequency_scale; - float minimum_frequency; - float maximum_frequency; + float minimum_frequency, maximum_frequency; float deviation; float bar_ratio; int bar_size; @@ -585,9 +575,9 @@ static int run_channel_cwt(AVFilterContext *ctx, void *arg, int jobnr, int nb_jo ShowCWTContext *s = ctx->priv; const int ch = *(int *)arg; AVComplexFloat *dst = (AVComplexFloat *)s->fft_out->extended_data[ch]; - const int output_sample_count = s->output_sample_count; + const int output_padding_size = s->output_padding_size; const int ihop_size = s->ihop_size; - const int ioffset = (s->output_padding_size - ihop_size) >> 1; + const int ioffset = (output_padding_size - ihop_size) >> 1; const int count = s->frequency_band_count; const int start = (count * jobnr) / nb_jobs; const int end = (count * (jobnr+1)) / nb_jobs; @@ -611,7 +601,7 @@ static int run_channel_cwt(AVFilterContext *ctx, void *arg, int jobnr, int nb_jo s->fdsp->vector_fmul((float *)dstx, (const float *)srcx, (const float *)kernelx, FFALIGN(kernel_range * 2, 16)); - memset(isrc, 0, sizeof(*isrc) * output_sample_count); + memset(isrc, 0, sizeof(*isrc) * output_padding_size); for (int i = 0; i < kernel_range; i++) { const unsigned n = index[i + kernel_start]; @@ -627,9 +617,10 @@ static int run_channel_cwt(AVFilterContext *ctx, void *arg, int jobnr, int nb_jo return 0; } -static void compute_kernel(AVFilterContext *ctx) +static int compute_kernel(AVFilterContext *ctx) { ShowCWTContext *s = ctx->priv; + const float correction = s->input_padding_size / (float)s->input_sample_count; const int size = s->input_sample_count; const float scale_factor = 1.f/(float)size; const int output_sample_count = s->output_sample_count; @@ -637,17 +628,18 @@ static void compute_kernel(AVFilterContext *ctx) int *kernel_start = s->kernel_start; int *kernel_stop = s->kernel_stop; unsigned *index = s->index; + int kernel_min = INT_MAX; + int kernel_max = 0; for (int y = 0; y < fsize; y++) { AVComplexFloat *kernel = (AVComplexFloat *)s->kernel->extended_data[y]; - float frequency = s->frequency_band[y*2]; + float frequency = s->frequency_band[y*2] * correction; float deviation = 1.f / (s->frequency_band[y*2+1] * - output_sample_count); + output_sample_count * correction); for (int n = 0; n < size; n++) { float ff, f = fabsf(n-frequency); - f = size - fabsf(f - size); ff = expf(-f*f*deviation) * scale_factor; kernel[n].re = ff; kernel[n].im = ff; @@ -655,21 +647,33 @@ static void compute_kernel(AVFilterContext *ctx) for (int n = 0; n < size; n++) { if (kernel[n].re != 0.f) { + if (kernel[n].re > FLT_MIN) + av_log(ctx, AV_LOG_DEBUG, "out of range kernel\n"); kernel_start[y] = n; + kernel_min = FFMIN(kernel_start[y], kernel_min); break; } } for (int n = 0; n < size; n++) { if (kernel[size - n - 1].re != 0.f) { + if (kernel[size - n - 1].re > FLT_MIN) + av_log(ctx, AV_LOG_DEBUG, "out of range kernel\n"); kernel_stop[y] = size - n - 1; + kernel_max = FFMAX(kernel_stop[y], kernel_max); break; } } } for (int n = 0; n < size; n++) - index[n] = n % output_sample_count; + index[n] = n % s->output_padding_size; + + av_log(ctx, AV_LOG_DEBUG, "kernel_min: %d\n", kernel_min); + av_log(ctx, AV_LOG_DEBUG, "kernel_max: %d\n", kernel_max); + av_log(ctx, AV_LOG_DEBUG, "kernel_range: %d\n", kernel_max - kernel_min); + + return kernel_max - kernel_min; } static int config_output(AVFilterLink *outlink) @@ -708,9 +712,12 @@ static int config_output(AVFilterLink *outlink) s->nb_consumed_samples = 65536; s->input_sample_count = s->nb_consumed_samples; - s->hop_size = s->nb_consumed_samples >> 1; - s->input_padding_size = 65536; - s->output_padding_size = FFMAX(16, av_rescale(s->input_padding_size, s->pps, inlink->sample_rate)); + s->input_padding_size = 1 << (32 - ff_clz(s->input_sample_count)); + s->output_sample_count = FFMAX(1, av_rescale(s->input_sample_count, s->pps, inlink->sample_rate)); + s->output_padding_size = 1 << (32 - ff_clz(s->output_sample_count)); + + s->hop_size = s->input_padding_size >> 1; + s->ihop_size = s->output_padding_size >> 1; outlink->w = s->w; outlink->h = s->h; @@ -719,11 +726,8 @@ static int config_output(AVFilterLink *outlink) s->fft_in_size = FFALIGN(s->input_padding_size, av_cpu_max_align()); s->fft_out_size = FFALIGN(s->input_padding_size, av_cpu_max_align()); - s->output_sample_count = s->output_padding_size; - s->ifft_in_size = FFALIGN(s->output_padding_size, av_cpu_max_align()); s->ifft_out_size = FFALIGN(s->output_padding_size, av_cpu_max_align()); - s->ihop_size = s->output_padding_size >> 1; s->fft = av_calloc(s->nb_threads, sizeof(*s->fft)); if (!s->fft) @@ -821,7 +825,7 @@ static int config_output(AVFilterLink *outlink) s->outpicref->color_range = AVCOL_RANGE_JPEG; - factor = s->nb_consumed_samples / (float)inlink->sample_rate; + factor = s->input_sample_count / (float)inlink->sample_rate; minimum_frequency *= factor; maximum_frequency *= factor; @@ -861,7 +865,9 @@ static int config_output(AVFilterLink *outlink) minimum_frequency, s->frequency_scale, s->deviation); av_log(ctx, AV_LOG_DEBUG, "input_sample_count: %d\n", s->input_sample_count); + av_log(ctx, AV_LOG_DEBUG, "input_padding_size: %d\n", s->input_padding_size); av_log(ctx, AV_LOG_DEBUG, "output_sample_count: %d\n", s->output_sample_count); + av_log(ctx, AV_LOG_DEBUG, "output_padding_size: %d\n", s->output_padding_size); switch (s->direction) { case DIRECTION_LR: @@ -1042,7 +1048,7 @@ static int output_frame(AVFilterContext *ctx) if (s->slide != SLIDE_FRAME || s->new_frame == 1) { int64_t pts_offset = s->new_frame ? 0LL : av_rescale(s->ihop_index, s->hop_size, s->ihop_size); - pts_offset = av_rescale_q(pts_offset - 16384LL, av_make_q(1, inlink->sample_rate), inlink->time_base); + pts_offset = av_rescale_q(pts_offset - s->input_sample_count/2, av_make_q(1, inlink->sample_rate), inlink->time_base); s->outpicref->pts = av_rescale_q(s->in_pts + pts_offset, inlink->time_base, outlink->time_base); s->outpicref->duration = 1; } From c24c7bcc951056c2a47bbb292edb56737fb436da Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Sat, 22 Jul 2023 17:16:33 +0200 Subject: [PATCH 1993/2172] avfilter/avf_showcwt: no need for big forward FFT with small sample rates --- libavfilter/avf_showcwt.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavfilter/avf_showcwt.c b/libavfilter/avf_showcwt.c index ef6798e9cf4..d83aad57f53 100644 --- a/libavfilter/avf_showcwt.c +++ b/libavfilter/avf_showcwt.c @@ -709,7 +709,7 @@ static int config_output(AVFilterLink *outlink) s->nb_channels = inlink->ch_layout.nb_channels; s->old_pts = AV_NOPTS_VALUE; s->eof_pts = AV_NOPTS_VALUE; - s->nb_consumed_samples = 65536; + s->nb_consumed_samples = FFMIN(65536, inlink->sample_rate); s->input_sample_count = s->nb_consumed_samples; s->input_padding_size = 1 << (32 - ff_clz(s->input_sample_count)); From ffa3edbf5137f1180e85b10d958c2e096d955831 Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Sat, 22 Jul 2023 17:25:06 +0200 Subject: [PATCH 1994/2172] avfilter/avf_showcwt: extend min frequency accepted range Also always check that min frequency is lower than max frequency. --- libavfilter/avf_showcwt.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/libavfilter/avf_showcwt.c b/libavfilter/avf_showcwt.c index d83aad57f53..120ce63b620 100644 --- a/libavfilter/avf_showcwt.c +++ b/libavfilter/avf_showcwt.c @@ -133,8 +133,8 @@ static const AVOption showcwt_options[] = { { "sqrt", "sqrt", 0, AV_OPT_TYPE_CONST,{.i64=FSCALE_SQRT}, 0, 0, FLAGS, "scale" }, { "cbrt", "cbrt", 0, AV_OPT_TYPE_CONST,{.i64=FSCALE_CBRT}, 0, 0, FLAGS, "scale" }, { "qdrt", "qdrt", 0, AV_OPT_TYPE_CONST,{.i64=FSCALE_QDRT}, 0, 0, FLAGS, "scale" }, - { "min", "set minimum frequency", OFFSET(minimum_frequency), AV_OPT_TYPE_FLOAT, {.dbl = 20.}, 1, 2000, FLAGS }, - { "max", "set maximum frequency", OFFSET(maximum_frequency), AV_OPT_TYPE_FLOAT, {.dbl = 20000.}, 0, 192000, FLAGS }, + { "min", "set minimum frequency", OFFSET(minimum_frequency), AV_OPT_TYPE_FLOAT, {.dbl = 20.}, 1, 192000, FLAGS }, + { "max", "set maximum frequency", OFFSET(maximum_frequency), AV_OPT_TYPE_FLOAT, {.dbl = 20000.}, 1, 192000, FLAGS }, { "logb", "set logarithmic basis", OFFSET(logarithmic_basis), AV_OPT_TYPE_FLOAT, {.dbl = 0.0001}, 0, 1, FLAGS }, { "deviation", "set frequency deviation", OFFSET(deviation), AV_OPT_TYPE_FLOAT, {.dbl = 1.}, 0, 10, FLAGS }, { "pps", "set pixels per second", OFFSET(pps), AV_OPT_TYPE_INT, {.i64 = 64}, 1, 1024, FLAGS }, @@ -686,6 +686,12 @@ static int config_output(AVFilterLink *outlink) float scale = 1.f, factor; int ret; + if (minimum_frequency >= maximum_frequency) { + av_log(ctx, AV_LOG_ERROR, "min frequency (%f) >= (%f) max frequency\n", + minimum_frequency, maximum_frequency); + return AVERROR(EINVAL); + } + uninit(ctx); s->fdsp = avpriv_float_dsp_alloc(0); From c644aabec8e1144ca5646dc7da2583dd82092119 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9mi=20Denis-Courmont?= Date: Wed, 19 Jul 2023 20:12:11 +0300 Subject: [PATCH 1995/2172] timer: don't leak perf FD if zero --- libavutil/timer.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libavutil/timer.h b/libavutil/timer.h index 861ba7e9d70..2cd299eca37 100644 --- a/libavutil/timer.h +++ b/libavutil/timer.h @@ -105,9 +105,9 @@ #if CONFIG_LINUX_PERF #define START_TIMER \ - static int linux_perf_fd; \ + static int linux_perf_fd = -1; \ uint64_t tperf; \ - if (!linux_perf_fd) { \ + if (linux_perf_fd == -1) { \ struct perf_event_attr attr = { \ .type = PERF_TYPE_HARDWARE, \ .size = sizeof(struct perf_event_attr), \ From 983af7445210271852dc8edaadf927d4bfb4f90c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9mi=20Denis-Courmont?= Date: Wed, 19 Jul 2023 20:23:57 +0300 Subject: [PATCH 1996/2172] macos_kperf: fix incomplete prototype --- libavutil/macos_kperf.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavutil/macos_kperf.c b/libavutil/macos_kperf.c index 9fc04c63491..9fb047eeee8 100644 --- a/libavutil/macos_kperf.c +++ b/libavutil/macos_kperf.c @@ -102,7 +102,7 @@ void ff_kperf_init(void) ff_thread_once(&init_static_once, kperf_init); } -uint64_t ff_kperf_cycles() +uint64_t ff_kperf_cycles(void) { uint64_t counters[COUNTERS_COUNT]; if (kpc_get_thread_counters(0, COUNTERS_COUNT, counters)) { From f25ad0fe022a8daeb654bd67e6b4433f66ee5642 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9mi=20Denis-Courmont?= Date: Fri, 14 Jul 2023 20:08:37 +0300 Subject: [PATCH 1997/2172] checkasm: improve Linux perf error message Report the failing system call name, as is convention, rather than just a rather unhelpful "syscall". --- tests/checkasm/checkasm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/checkasm/checkasm.c b/tests/checkasm/checkasm.c index 30e2dc6fed7..f521d30b7cf 100644 --- a/tests/checkasm/checkasm.c +++ b/tests/checkasm/checkasm.c @@ -667,7 +667,7 @@ static int bench_init_linux(void) state.sysfd = syscall(__NR_perf_event_open, &attr, 0, -1, -1, 0); if (state.sysfd == -1) { - perror("syscall"); + perror("perf_event_open"); return -1; } return 0; From b2ceed406b4648d34e233cb456072ce040dea483 Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Sat, 22 Jul 2023 21:45:48 +0200 Subject: [PATCH 1998/2172] avfilter/avf_showcwt: reduce memory usage --- libavfilter/avf_showcwt.c | 92 ++++++++++++++++++++++----------------- 1 file changed, 52 insertions(+), 40 deletions(-) diff --git a/libavfilter/avf_showcwt.c b/libavfilter/avf_showcwt.c index 120ce63b620..0661afbcdd0 100644 --- a/libavfilter/avf_showcwt.c +++ b/libavfilter/avf_showcwt.c @@ -78,7 +78,7 @@ typedef struct ShowCWTContext { int64_t old_pts; int64_t eof_pts; float *frequency_band; - AVFrame *kernel; + AVComplexFloat **kernel; unsigned *index; int *kernel_start, *kernel_stop; AVFrame *cache; @@ -87,7 +87,6 @@ typedef struct ShowCWTContext { AVFrame *fft_out; AVFrame *dst_x; AVFrame *src_x; - AVFrame *kernel_x; AVFrame *ifft_in; AVFrame *ifft_out; AVFrame *ch_out; @@ -169,14 +168,12 @@ static av_cold void uninit(AVFilterContext *ctx) av_freep(&s->kernel_stop); av_freep(&s->index); - av_frame_free(&s->kernel); av_frame_free(&s->cache); av_frame_free(&s->outpicref); av_frame_free(&s->fft_in); av_frame_free(&s->fft_out); av_frame_free(&s->dst_x); av_frame_free(&s->src_x); - av_frame_free(&s->kernel_x); av_frame_free(&s->ifft_in); av_frame_free(&s->ifft_out); av_frame_free(&s->ch_out); @@ -194,6 +191,12 @@ static av_cold void uninit(AVFilterContext *ctx) av_freep(&s->ifft); } + if (s->kernel) { + for (int n = 0; n < s->frequency_band_count; n++) + av_freep(&s->kernel[n]); + } + av_freep(&s->kernel); + av_freep(&s->fdsp); } @@ -588,18 +591,16 @@ static int run_channel_cwt(AVFilterContext *ctx, void *arg, int jobnr, int nb_jo AVComplexFloat *chout = ((AVComplexFloat *)s->ch_out->extended_data[ch]) + y * ihop_size; AVComplexFloat *dstx = (AVComplexFloat *)s->dst_x->extended_data[jobnr]; AVComplexFloat *srcx = (AVComplexFloat *)s->src_x->extended_data[jobnr]; - AVComplexFloat *kernelx = (AVComplexFloat *)s->kernel_x->extended_data[jobnr]; - const AVComplexFloat *kernel = (const AVComplexFloat *)s->kernel->extended_data[y]; + const AVComplexFloat *kernel = s->kernel[y]; const unsigned *index = (const unsigned *)s->index; const int kernel_start = s->kernel_start[y]; const int kernel_stop = s->kernel_stop[y]; const int kernel_range = kernel_stop - kernel_start; - memcpy(kernelx, kernel + kernel_start, sizeof(*kernel) * kernel_range); memcpy(srcx, dst + kernel_start, sizeof(*dst) * kernel_range); s->fdsp->vector_fmul((float *)dstx, (const float *)srcx, - (const float *)kernelx, FFALIGN(kernel_range * 2, 16)); + (const float *)kernel, FFALIGN(kernel_range * 2, 16)); memset(isrc, 0, sizeof(*isrc) * output_padding_size); for (int i = 0; i < kernel_range; i++) { @@ -629,41 +630,63 @@ static int compute_kernel(AVFilterContext *ctx) int *kernel_stop = s->kernel_stop; unsigned *index = s->index; int kernel_min = INT_MAX; - int kernel_max = 0; + int kernel_max = 0, ret = 0; + float *tkernel; + + tkernel = av_malloc_array(size, sizeof(*tkernel)); + if (!tkernel) + return AVERROR(ENOMEM); for (int y = 0; y < fsize; y++) { - AVComplexFloat *kernel = (AVComplexFloat *)s->kernel->extended_data[y]; + AVComplexFloat *kernel = s->kernel[y]; + int start = 0, stop = 0; float frequency = s->frequency_band[y*2] * correction; float deviation = 1.f / (s->frequency_band[y*2+1] * output_sample_count * correction); + memset(tkernel, 0, size * sizeof(*tkernel)); for (int n = 0; n < size; n++) { float ff, f = fabsf(n-frequency); ff = expf(-f*f*deviation) * scale_factor; - kernel[n].re = ff; - kernel[n].im = ff; + tkernel[n] = ff; } for (int n = 0; n < size; n++) { - if (kernel[n].re != 0.f) { - if (kernel[n].re > FLT_MIN) + if (tkernel[n] != 0.f) { + if (tkernel[n] > FLT_MIN) av_log(ctx, AV_LOG_DEBUG, "out of range kernel\n"); - kernel_start[y] = n; - kernel_min = FFMIN(kernel_start[y], kernel_min); + start = n; + kernel_min = FFMIN(start, kernel_min); break; } } for (int n = 0; n < size; n++) { - if (kernel[size - n - 1].re != 0.f) { - if (kernel[size - n - 1].re > FLT_MIN) + if (tkernel[size - n - 1] != 0.f) { + if (tkernel[size - n - 1] > FLT_MIN) av_log(ctx, AV_LOG_DEBUG, "out of range kernel\n"); - kernel_stop[y] = size - n - 1; - kernel_max = FFMAX(kernel_stop[y], kernel_max); + stop = size - n - 1; + kernel_max = FFMAX(stop, kernel_max); break; } } + + kernel_start[y] = start; + kernel_stop[y] = stop; + + kernel = av_calloc(FFALIGN(stop - start + 1, 16), sizeof(*kernel)); + if (!kernel) { + ret = AVERROR(ENOMEM); + break; + } + + for (int n = start; n <= stop; n++) { + kernel[n - start].re = tkernel[n]; + kernel[n - start].im = tkernel[n]; + } + + s->kernel[y] = kernel; } for (int n = 0; n < size; n++) @@ -673,7 +696,9 @@ static int compute_kernel(AVFilterContext *ctx) av_log(ctx, AV_LOG_DEBUG, "kernel_max: %d\n", kernel_max); av_log(ctx, AV_LOG_DEBUG, "kernel_range: %d\n", kernel_max - kernel_min); - return kernel_max - kernel_min; + av_freep(&tkernel); + + return ret; } static int config_output(AVFilterLink *outlink) @@ -762,19 +787,18 @@ static int config_output(AVFilterLink *outlink) s->fft_out = ff_get_audio_buffer(inlink, s->fft_out_size * 2); s->dst_x = av_frame_alloc(); s->src_x = av_frame_alloc(); - s->kernel_x = av_frame_alloc(); + s->kernel = av_calloc(s->frequency_band_count, sizeof(*s->kernel)); s->cache = ff_get_audio_buffer(inlink, s->fft_in_size * 2); s->ch_out = ff_get_audio_buffer(inlink, s->frequency_band_count * 2 * s->ihop_size); s->bh_out = ff_get_audio_buffer(inlink, s->frequency_band_count); s->ifft_in = av_frame_alloc(); s->ifft_out = av_frame_alloc(); - s->kernel = av_frame_alloc(); s->index = av_calloc(s->input_padding_size, sizeof(*s->index)); s->kernel_start = av_calloc(s->frequency_band_count, sizeof(*s->kernel_start)); s->kernel_stop = av_calloc(s->frequency_band_count, sizeof(*s->kernel_stop)); - if (!s->outpicref || !s->fft_in || !s->fft_out || !s->src_x || !s->dst_x || !s->kernel_x || + if (!s->outpicref || !s->fft_in || !s->fft_out || !s->src_x || !s->dst_x || !s->ifft_in || !s->ifft_out || !s->kernel_start || !s->kernel_stop || !s->ch_out || - !s->frequency_band || !s->kernel || !s->cache || !s->index || !s->bh_out) + !s->frequency_band || !s->cache || !s->index || !s->bh_out || !s->kernel) return AVERROR(ENOMEM); s->ifft_in->format = inlink->format; @@ -791,13 +815,6 @@ static int config_output(AVFilterLink *outlink) if (ret < 0) return ret; - s->kernel->format = inlink->format; - s->kernel->nb_samples = s->input_padding_size * 2; - s->kernel->ch_layout.nb_channels = s->frequency_band_count; - ret = av_frame_get_buffer(s->kernel, 0); - if (ret < 0) - return ret; - s->src_x->format = inlink->format; s->src_x->nb_samples = s->fft_out_size * 2; s->src_x->ch_layout.nb_channels = s->nb_threads; @@ -812,13 +829,6 @@ static int config_output(AVFilterLink *outlink) if (ret < 0) return ret; - s->kernel_x->format = inlink->format; - s->kernel_x->nb_samples = s->fft_out_size * 2; - s->kernel_x->ch_layout.nb_channels = s->nb_threads; - ret = av_frame_get_buffer(s->kernel_x, 0); - if (ret < 0) - return ret; - s->outpicref->sample_aspect_ratio = (AVRational){1,1}; for (int y = 0; y < outlink->h; y++) { @@ -899,7 +909,9 @@ static int config_output(AVFilterLink *outlink) outlink->frame_rate = s->frame_rate; outlink->time_base = av_inv_q(outlink->frame_rate); - compute_kernel(ctx); + ret = compute_kernel(ctx); + if (ret < 0) + return ret; return 0; } From 6c90fcd9e606c1222271f5f867f761abeafbe51e Mon Sep 17 00:00:00 2001 From: Zhao Zhili Date: Sun, 16 Jul 2023 17:13:27 +0800 Subject: [PATCH 1999/2172] avcodec/videotoolboxenc: use color parameters conversion from avutil Signed-off-by: Zhao Zhili --- libavcodec/videotoolboxenc.c | 137 ++++------------------------------- 1 file changed, 13 insertions(+), 124 deletions(-) diff --git a/libavcodec/videotoolboxenc.c b/libavcodec/videotoolboxenc.c index 61143513926..8e493c4f7a7 100644 --- a/libavcodec/videotoolboxenc.c +++ b/libavcodec/videotoolboxenc.c @@ -1001,132 +1001,20 @@ static int create_cv_pixel_buffer_info(AVCodecContext* avctx, return AVERROR(ENOMEM); } -static int get_cv_color_primaries(AVCodecContext *avctx, - CFStringRef *primaries) -{ - enum AVColorPrimaries pri = avctx->color_primaries; - switch (pri) { - case AVCOL_PRI_UNSPECIFIED: - *primaries = NULL; - break; - - case AVCOL_PRI_BT470BG: - *primaries = kCVImageBufferColorPrimaries_EBU_3213; - break; - - case AVCOL_PRI_SMPTE170M: - *primaries = kCVImageBufferColorPrimaries_SMPTE_C; - break; - - case AVCOL_PRI_BT709: - *primaries = kCVImageBufferColorPrimaries_ITU_R_709_2; - break; - - case AVCOL_PRI_BT2020: - *primaries = compat_keys.kCVImageBufferColorPrimaries_ITU_R_2020; - break; - - default: - av_log(avctx, AV_LOG_ERROR, "Color primaries %s is not supported.\n", av_color_primaries_name(pri)); - *primaries = NULL; - return -1; - } - - return 0; -} - -static int get_cv_transfer_function(AVCodecContext *avctx, - CFStringRef *transfer_fnc, - CFNumberRef *gamma_level) +static int get_cv_gamma(AVCodecContext *avctx, + CFNumberRef *gamma_level) { enum AVColorTransferCharacteristic trc = avctx->color_trc; - Float32 gamma; + Float32 gamma = 0; *gamma_level = NULL; - switch (trc) { - case AVCOL_TRC_UNSPECIFIED: - *transfer_fnc = NULL; - break; - - case AVCOL_TRC_BT709: - *transfer_fnc = kCVImageBufferTransferFunction_ITU_R_709_2; - break; - - case AVCOL_TRC_SMPTE240M: - *transfer_fnc = kCVImageBufferTransferFunction_SMPTE_240M_1995; - break; - -#if HAVE_KCVIMAGEBUFFERTRANSFERFUNCTION_SMPTE_ST_2084_PQ - case AVCOL_TRC_SMPTE2084: - *transfer_fnc = kCVImageBufferTransferFunction_SMPTE_ST_2084_PQ; - break; -#endif -#if HAVE_KCVIMAGEBUFFERTRANSFERFUNCTION_LINEAR - case AVCOL_TRC_LINEAR: - *transfer_fnc = kCVImageBufferTransferFunction_Linear; - break; -#endif -#if HAVE_KCVIMAGEBUFFERTRANSFERFUNCTION_ITU_R_2100_HLG - case AVCOL_TRC_ARIB_STD_B67: - *transfer_fnc = kCVImageBufferTransferFunction_ITU_R_2100_HLG; - break; -#endif - - case AVCOL_TRC_GAMMA22: - gamma = 2.2; - *transfer_fnc = kCVImageBufferTransferFunction_UseGamma; - *gamma_level = CFNumberCreate(NULL, kCFNumberFloat32Type, &gamma); - break; - - case AVCOL_TRC_GAMMA28: - gamma = 2.8; - *transfer_fnc = kCVImageBufferTransferFunction_UseGamma; - *gamma_level = CFNumberCreate(NULL, kCFNumberFloat32Type, &gamma); - break; - - case AVCOL_TRC_BT2020_10: - case AVCOL_TRC_BT2020_12: - *transfer_fnc = compat_keys.kCVImageBufferTransferFunction_ITU_R_2020; - break; - - default: - *transfer_fnc = NULL; - av_log(avctx, AV_LOG_ERROR, "Transfer function %s is not supported.\n", av_color_transfer_name(trc)); - return -1; - } - - return 0; -} - -static int get_cv_ycbcr_matrix(AVCodecContext *avctx, CFStringRef *matrix) { - switch(avctx->colorspace) { - case AVCOL_SPC_BT709: - *matrix = kCVImageBufferYCbCrMatrix_ITU_R_709_2; - break; - - case AVCOL_SPC_UNSPECIFIED: - case AVCOL_SPC_RGB: - *matrix = NULL; - break; - - case AVCOL_SPC_BT470BG: - case AVCOL_SPC_SMPTE170M: - *matrix = kCVImageBufferYCbCrMatrix_ITU_R_601_4; - break; - - case AVCOL_SPC_SMPTE240M: - *matrix = kCVImageBufferYCbCrMatrix_SMPTE_240M_1995; - break; - - case AVCOL_SPC_BT2020_NCL: - *matrix = compat_keys.kCVImageBufferYCbCrMatrix_ITU_R_2020; - break; - - default: - av_log(avctx, AV_LOG_ERROR, "Color space %s is not supported.\n", av_color_space_name(avctx->colorspace)); - return -1; - } + if (trc == AVCOL_TRC_GAMMA22) + gamma = 2.2; + else if (trc == AVCOL_TRC_GAMMA28) + gamma = 2.8; + if (gamma != 0) + *gamma_level = CFNumberCreate(NULL, kCFNumberFloat32Type, &gamma); return 0; } @@ -1694,9 +1582,10 @@ static int vtenc_configure_encoder(AVCodecContext *avctx) vtctx->dts_delta = vtctx->has_b_frames ? -1 : 0; - get_cv_transfer_function(avctx, &vtctx->transfer_function, &gamma_level); - get_cv_ycbcr_matrix(avctx, &vtctx->ycbcr_matrix); - get_cv_color_primaries(avctx, &vtctx->color_primaries); + get_cv_gamma(avctx, &gamma_level); + vtctx->transfer_function = av_map_videotoolbox_color_trc_from_av(avctx->color_trc); + vtctx->ycbcr_matrix = av_map_videotoolbox_color_matrix_from_av(avctx->colorspace); + vtctx->color_primaries = av_map_videotoolbox_color_primaries_from_av(avctx->color_primaries); if (avctx->flags & AV_CODEC_FLAG_GLOBAL_HEADER) { From c2c96c4c2419859c4d1b11e6f907e58afb6dfa3c Mon Sep 17 00:00:00 2001 From: Zhao Zhili Date: Sun, 16 Jul 2023 17:13:28 +0800 Subject: [PATCH 2000/2172] avfilter: add scale_vt for videotoolbox pix_fmt For example, ./ffmpeg -hwaccel videotoolbox \ -hwaccel_output_format videotoolbox_vld \ -i ios-265.mov \ -c:v hevc_videotoolbox \ -profile:v main \ -b:v 3M \ -vf scale_vt=w=iw/2:h=ih/2:color_matrix=bt709:color_primaries=bt709:color_transfer=bt709 \ -c:a copy \ -tag:v hvc1 \ /tmp/test.mp4 Input: hevc (Main 10) (hvc1 / 0x31637668), yuv420p10le(tv, bt2020nc/bt2020/arib-std-b67), 3840x2160 Output: hevc (Main) (hvc1 / 0x31637668), yuv420p(tv, bt709, progressive), 1920x1080 Signed-off-by: Zhao Zhili --- Changelog | 1 + configure | 1 + doc/filters.texi | 21 ++++ libavfilter/Makefile | 1 + libavfilter/allfilters.c | 1 + libavfilter/version.h | 4 +- libavfilter/vf_scale_vt.c | 244 ++++++++++++++++++++++++++++++++++++++ 7 files changed, 271 insertions(+), 2 deletions(-) create mode 100644 libavfilter/vf_scale_vt.c diff --git a/Changelog b/Changelog index 38760828441..dadaf15de6a 100644 --- a/Changelog +++ b/Changelog @@ -25,6 +25,7 @@ version : - Raw VVC bitstream parser, muxer and demuxer - Bitstream filter for editing metadata in VVC streams - Bitstream filter for converting VVC from MP4 to Annex B +- scale_vt filter for videotoolbox version 6.0: - Radiance HDR image support diff --git a/configure b/configure index eb2fe392b41..1ceea4c9ca3 100755 --- a/configure +++ b/configure @@ -3833,6 +3833,7 @@ zmq_filter_deps="libzmq" zoompan_filter_deps="swscale" zscale_filter_deps="libzimg const_nan" scale_vaapi_filter_deps="vaapi" +scale_vt_filter_deps="videotoolbox" scale_vulkan_filter_deps="vulkan spirv_compiler" vpp_qsv_filter_deps="libmfx" vpp_qsv_filter_select="qsvvpp" diff --git a/doc/filters.texi b/doc/filters.texi index 9690332092a..b1d9eb3dd2c 100644 --- a/doc/filters.texi +++ b/doc/filters.texi @@ -21184,6 +21184,27 @@ Scale a logo to 1/10th the height of a video, while preserving its display aspec @end example @end itemize +@section scale_vt + +Scale and convert the color parameters using VTPixelTransferSession. + +The filter accepts the following options: +@table @option +@item w +@item h +Set the output video dimension expression. Default value is the input dimension. + +@item color_matrix +Set the output colorspace matrix. + +@item color_primaries +Set the output color primaries. + +@item color_transfer +Set the output transfer characteristics. + +@end table + @section scharr Apply scharr operator to input video stream. diff --git a/libavfilter/Makefile b/libavfilter/Makefile index 9b7813575a0..ef2c87104f5 100644 --- a/libavfilter/Makefile +++ b/libavfilter/Makefile @@ -457,6 +457,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_vpp_qsv.o OBJS-$(CONFIG_SCALE_VAAPI_FILTER) += vf_scale_vaapi.o scale_eval.o vaapi_vpp.o +OBJS-$(CONFIG_SCALE_VT_FILTER) += vf_scale_vt.o scale_eval.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 diff --git a/libavfilter/allfilters.c b/libavfilter/allfilters.c index 9a7fadc58d6..fefaa94d2b8 100644 --- a/libavfilter/allfilters.c +++ b/libavfilter/allfilters.c @@ -427,6 +427,7 @@ extern const AVFilter ff_vf_scale_cuda; extern const AVFilter ff_vf_scale_npp; extern const AVFilter ff_vf_scale_qsv; extern const AVFilter ff_vf_scale_vaapi; +extern const AVFilter ff_vf_scale_vt; extern const AVFilter ff_vf_scale_vulkan; extern const AVFilter ff_vf_scale2ref; extern const AVFilter ff_vf_scale2ref_npp; diff --git a/libavfilter/version.h b/libavfilter/version.h index c001693e3c9..77f38cb9b4f 100644 --- a/libavfilter/version.h +++ b/libavfilter/version.h @@ -31,8 +31,8 @@ #include "version_major.h" -#define LIBAVFILTER_VERSION_MINOR 8 -#define LIBAVFILTER_VERSION_MICRO 102 +#define LIBAVFILTER_VERSION_MINOR 9 +#define LIBAVFILTER_VERSION_MICRO 100 #define LIBAVFILTER_VERSION_INT AV_VERSION_INT(LIBAVFILTER_VERSION_MAJOR, \ diff --git a/libavfilter/vf_scale_vt.c b/libavfilter/vf_scale_vt.c new file mode 100644 index 00000000000..a7f72c8de9f --- /dev/null +++ b/libavfilter/vf_scale_vt.c @@ -0,0 +1,244 @@ +/* + * Copyright (c) 2023 Zhao Zhili + * + * 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/hwcontext.h" +#include "libavutil/hwcontext_videotoolbox.h" +#include "libavutil/opt.h" +#include "libavutil/pixdesc.h" +#include "internal.h" +#include "scale_eval.h" + +typedef struct ScaleVtContext { + AVClass *class; + + VTPixelTransferSessionRef transfer; + int output_width; + int output_height; + char *w_expr; + char *h_expr; + + enum AVColorPrimaries colour_primaries; + enum AVColorTransferCharacteristic colour_transfer; + enum AVColorSpace colour_matrix; + char *colour_primaries_string; + char *colour_transfer_string; + char *colour_matrix_string; +} ScaleVtContext; + +static av_cold int scale_vt_init(AVFilterContext *avctx) +{ + ScaleVtContext *s = avctx->priv; + int ret; + CFStringRef value; + + ret = VTPixelTransferSessionCreate(kCFAllocatorDefault, &s->transfer); + if (ret != noErr) { + av_log(avctx, AV_LOG_ERROR, "transfer session create failed, %d\n", ret); + return AVERROR_EXTERNAL; + } + +#define STRING_OPTION(var_name, func_name, default_value) \ + do { \ + if (s->var_name##_string) { \ + int var = av_##func_name##_from_name(s->var_name##_string); \ + if (var < 0) { \ + av_log(avctx, AV_LOG_ERROR, "Invalid %s.\n", #var_name); \ + return AVERROR(EINVAL); \ + } \ + s->var_name = var; \ + } else { \ + s->var_name = default_value; \ + } \ + } while (0) + + STRING_OPTION(colour_primaries, color_primaries, AVCOL_PRI_UNSPECIFIED); + STRING_OPTION(colour_transfer, color_transfer, AVCOL_TRC_UNSPECIFIED); + STRING_OPTION(colour_matrix, color_space, AVCOL_SPC_UNSPECIFIED); + + if (s->colour_primaries != AVCOL_PRI_UNSPECIFIED) { + value = av_map_videotoolbox_color_primaries_from_av(s->colour_primaries); + if (!value) { + av_log(avctx, AV_LOG_ERROR, + "Doesn't support converting to colour primaries %s\n", + s->colour_primaries_string); + return AVERROR(ENOTSUP); + } + VTSessionSetProperty(s->transfer, kVTPixelTransferPropertyKey_DestinationColorPrimaries, value); + } + + if (s->colour_transfer != AVCOL_TRC_UNSPECIFIED) { + value = av_map_videotoolbox_color_trc_from_av(s->colour_transfer); + if (!value) { + av_log(avctx, AV_LOG_ERROR, + "Doesn't support converting to trc %s\n", + s->colour_transfer_string); + return AVERROR(ENOTSUP); + } + VTSessionSetProperty(s->transfer, kVTPixelTransferPropertyKey_DestinationTransferFunction, value); + } + + if (s->colour_matrix != AVCOL_SPC_UNSPECIFIED) { + value = av_map_videotoolbox_color_matrix_from_av(s->colour_matrix); + if (!value) { + av_log(avctx, AV_LOG_ERROR, + "Doesn't support converting to colorspace %s\n", + s->colour_matrix_string); + return AVERROR(ENOTSUP); + } + VTSessionSetProperty(s->transfer, kVTPixelTransferPropertyKey_DestinationYCbCrMatrix, value); + } + + return 0; +} + +static av_cold void scale_vt_uninit(AVFilterContext *avctx) +{ + ScaleVtContext *s = avctx->priv; + + if (s->transfer) { + VTPixelTransferSessionInvalidate(s->transfer); + CFRelease(s->transfer); + s->transfer = NULL; + } +} + +static int scale_vt_filter_frame(AVFilterLink *link, AVFrame *in) +{ + int ret; + AVFilterContext *ctx = link->dst; + ScaleVtContext *s = ctx->priv; + AVFilterLink *outlink = ctx->outputs[0]; + CVPixelBufferRef src; + CVPixelBufferRef dst; + + AVFrame *out = ff_get_video_buffer(outlink, outlink->w, outlink->h); + if (!out) { + ret = AVERROR(ENOMEM); + goto fail; + } + + ret = av_frame_copy_props(out, in); + if (ret < 0) + goto fail; + + av_reduce(&out->sample_aspect_ratio.num, &out->sample_aspect_ratio.den, + (int64_t)in->sample_aspect_ratio.num * outlink->h * link->w, + (int64_t)in->sample_aspect_ratio.den * outlink->w * link->h, + INT_MAX); + if (s->colour_primaries != AVCOL_PRI_UNSPECIFIED) + out->color_primaries = s->colour_primaries; + if (s->colour_transfer != AVCOL_TRC_UNSPECIFIED) + out->color_trc = s->colour_transfer; + if (s->colour_matrix != AVCOL_SPC_UNSPECIFIED) + out->colorspace = s->colour_matrix; + + src = (CVPixelBufferRef)in->data[3]; + dst = (CVPixelBufferRef)out->data[3]; + ret = VTPixelTransferSessionTransferImage(s->transfer, src, dst); + if (ret != noErr) { + av_log(ctx, AV_LOG_ERROR, "transfer image failed, %d\n", ret); + ret = AVERROR_EXTERNAL; + goto fail; + } + + av_frame_free(&in); + + return ff_filter_frame(outlink, out); + +fail: + av_frame_free(&in); + av_frame_free(&out); + return ret; +} + +static int scale_vt_config_output(AVFilterLink *outlink) +{ + int err; + AVFilterContext *avctx = outlink->src; + ScaleVtContext *s = avctx->priv; + AVFilterLink *inlink = outlink->src->inputs[0]; + + err = ff_scale_eval_dimensions(s, s->w_expr, s->h_expr, inlink, outlink, + &s->output_width, + &s->output_height); + if (err < 0) + return err; + + outlink->w = s->output_width; + outlink->h = s->output_height; + + if (inlink->sample_aspect_ratio.num) { + AVRational r = {outlink->h * inlink->w, outlink->w * inlink->h}; + outlink->sample_aspect_ratio = av_mul_q(r, inlink->sample_aspect_ratio); + } else { + outlink->sample_aspect_ratio = inlink->sample_aspect_ratio; + } + + return 0; +} + +#define OFFSET(x) offsetof(ScaleVtContext, x) +#define FLAGS (AV_OPT_FLAG_FILTERING_PARAM | AV_OPT_FLAG_VIDEO_PARAM) +static const AVOption scale_vt_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 }, + { "color_matrix", "Output colour matrix coefficient set", + OFFSET(colour_matrix_string), AV_OPT_TYPE_STRING, { .str = NULL }, .flags = FLAGS }, + { "color_primaries", "Output colour primaries", + OFFSET(colour_primaries_string), AV_OPT_TYPE_STRING, { .str = NULL }, .flags = FLAGS }, + { "color_transfer", "Output colour transfer characteristics", + OFFSET(colour_transfer_string), AV_OPT_TYPE_STRING, { .str = NULL }, .flags = FLAGS }, + { NULL }, +}; + +AVFILTER_DEFINE_CLASS(scale_vt); + +static const AVFilterPad scale_vt_inputs[] = { + { + .name = "default", + .type = AVMEDIA_TYPE_VIDEO, + .filter_frame = &scale_vt_filter_frame, + }, +}; + +static const AVFilterPad scale_vt_outputs[] = { + { + .name = "default", + .type = AVMEDIA_TYPE_VIDEO, + .config_props = &scale_vt_config_output, + }, +}; + +const AVFilter ff_vf_scale_vt = { + .name = "scale_vt", + .description = NULL_IF_CONFIG_SMALL("Scale Videotoolbox frames"), + .priv_size = sizeof(ScaleVtContext), + .init = scale_vt_init, + .uninit = scale_vt_uninit, + FILTER_INPUTS(scale_vt_inputs), + FILTER_OUTPUTS(scale_vt_outputs), + FILTER_SINGLE_PIXFMT(AV_PIX_FMT_VIDEOTOOLBOX), + .priv_class = &scale_vt_class, + .flags = AVFILTER_FLAG_HWDEVICE, +}; From 89f5124d0a7cea568ab670614b8a67e458cd002e Mon Sep 17 00:00:00 2001 From: Zhao Zhili Date: Sun, 16 Jul 2023 17:13:29 +0800 Subject: [PATCH 2001/2172] avfilter: add transpose_vt for videotoolbox pix_fmt Signed-off-by: Zhao Zhili --- Changelog | 1 + configure | 2 + doc/filters.texi | 48 +++++++ libavfilter/Makefile | 1 + libavfilter/allfilters.c | 1 + libavfilter/version.h | 2 +- libavfilter/vf_transpose_vt.c | 246 ++++++++++++++++++++++++++++++++++ 7 files changed, 300 insertions(+), 1 deletion(-) create mode 100644 libavfilter/vf_transpose_vt.c diff --git a/Changelog b/Changelog index dadaf15de6a..bbda4f4fd4c 100644 --- a/Changelog +++ b/Changelog @@ -26,6 +26,7 @@ version : - Bitstream filter for editing metadata in VVC streams - Bitstream filter for converting VVC from MP4 to Annex B - scale_vt filter for videotoolbox +- transpose_vt filter for videotoolbox version 6.0: - Radiance HDR image support diff --git a/configure b/configure index 1ceea4c9ca3..99388e76648 100755 --- a/configure +++ b/configure @@ -3821,6 +3821,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_vt_filter_deps="videotoolbox VTPixelRotationSessionCreate" transpose_vulkan_filter_deps="vulkan spirv_compiler" unsharp_opencl_filter_deps="opencl" uspp_filter_deps="gpl avcodec" @@ -6465,6 +6466,7 @@ check_headers termios.h check_headers unistd.h check_headers valgrind/valgrind.h check_func_headers VideoToolbox/VTCompressionSession.h VTCompressionSessionPrepareToEncodeFrames -framework VideoToolbox +check_func_headers VideoToolbox/VideoToolbox.h VTPixelRotationSessionCreate -framework VideoToolbox check_headers windows.h check_headers asm/types.h diff --git a/doc/filters.texi b/doc/filters.texi index b1d9eb3dd2c..6f47428aa01 100644 --- a/doc/filters.texi +++ b/doc/filters.texi @@ -27670,6 +27670,54 @@ Default value is @code{0}. @end table +@section transpose_vt + +Transpose rows with columns in the input video and optionally flip it. +For more in depth examples see the @ref{transpose} video filter, which shares mostly the same options. + +It accepts the following parameters: + +@table @option + +@item dir +Specify the transposition direction. + +Can assume the following values: +@table @samp +@item cclock_flip +Rotate by 90 degrees counterclockwise and vertically flip. (default) + +@item clock +Rotate by 90 degrees clockwise. + +@item cclock +Rotate by 90 degrees counterclockwise. + +@item clock_flip +Rotate by 90 degrees clockwise and vertically flip. + +@item hflip +Flip the input video horizontally. + +@item vflip +Flip the input video vertically. + +@end table + +@item passthrough +Do not apply the transposition if the input geometry matches the one +specified by the specified value. It accepts the following values: +@table @samp +@item none +Always apply transposition. (default) +@item portrait +Preserve portrait geometry (when @var{height} >= @var{width}). +@item landscape +Preserve landscape geometry (when @var{width} >= @var{height}). +@end table + +@end table + @section transpose_vulkan Transpose rows with columns in the input video and optionally flip it. diff --git a/libavfilter/Makefile b/libavfilter/Makefile index ef2c87104f5..30a0e22ef81 100644 --- a/libavfilter/Makefile +++ b/libavfilter/Makefile @@ -525,6 +525,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_VT_FILTER) += vf_transpose_vt.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 diff --git a/libavfilter/allfilters.c b/libavfilter/allfilters.c index fefaa94d2b8..089ad3a0ede 100644 --- a/libavfilter/allfilters.c +++ b/libavfilter/allfilters.c @@ -492,6 +492,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_vt; extern const AVFilter ff_vf_transpose_vulkan; extern const AVFilter ff_vf_trim; extern const AVFilter ff_vf_unpremultiply; diff --git a/libavfilter/version.h b/libavfilter/version.h index 77f38cb9b4f..4a69d6be98f 100644 --- a/libavfilter/version.h +++ b/libavfilter/version.h @@ -31,7 +31,7 @@ #include "version_major.h" -#define LIBAVFILTER_VERSION_MINOR 9 +#define LIBAVFILTER_VERSION_MINOR 10 #define LIBAVFILTER_VERSION_MICRO 100 diff --git a/libavfilter/vf_transpose_vt.c b/libavfilter/vf_transpose_vt.c new file mode 100644 index 00000000000..197ea5707c9 --- /dev/null +++ b/libavfilter/vf_transpose_vt.c @@ -0,0 +1,246 @@ +/* + * Copyright (c) 2023 Zhao Zhili + * + * 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/hwcontext.h" +#include "libavutil/hwcontext_videotoolbox.h" +#include "libavutil/opt.h" +#include "libavutil/pixdesc.h" +#include "internal.h" +#include "transpose.h" + +typedef struct TransposeVtContext { + AVClass *class; + + VTPixelRotationSessionRef session; + int dir; + int passthrough; +} TransposeVtContext; + +static av_cold int transpose_vt_init(AVFilterContext *avctx) +{ + TransposeVtContext *s = avctx->priv; + int ret; + + ret = VTPixelRotationSessionCreate(kCFAllocatorDefault, &s->session); + if (ret != noErr) { + av_log(avctx, AV_LOG_ERROR, "Rotation session create failed, %d\n", ret); + return AVERROR_EXTERNAL; + } + + return 0; +} + +static av_cold void transpose_vt_uninit(AVFilterContext *avctx) +{ + TransposeVtContext *s = avctx->priv; + + if (s->session) { + VTPixelRotationSessionInvalidate(s->session); + CFRelease(s->session); + s->session = NULL; + } +} + +static int transpose_vt_filter_frame(AVFilterLink *link, AVFrame *in) +{ + int ret; + AVFilterContext *ctx = link->dst; + TransposeVtContext *s = ctx->priv; + AVFilterLink *outlink = ctx->outputs[0]; + CVPixelBufferRef src; + CVPixelBufferRef dst; + + if (s->passthrough) + return ff_filter_frame(outlink, in); + + AVFrame *out = ff_get_video_buffer(outlink, outlink->w, outlink->h); + if (!out) { + ret = AVERROR(ENOMEM); + goto fail; + } + + ret = av_frame_copy_props(out, in); + if (ret < 0) + goto fail; + + src = (CVPixelBufferRef)in->data[3]; + dst = (CVPixelBufferRef)out->data[3]; + ret = VTPixelRotationSessionRotateImage(s->session, src, dst); + if (ret != noErr) { + av_log(ctx, AV_LOG_ERROR, "transfer image failed, %d\n", ret); + ret = AVERROR_EXTERNAL; + goto fail; + } + + av_frame_free(&in); + + return ff_filter_frame(outlink, out); + +fail: + av_frame_free(&in); + av_frame_free(&out); + return ret; +} + +static int transpose_vt_config_output(AVFilterLink *outlink) +{ + int err; + AVFilterContext *avctx = outlink->src; + TransposeVtContext *s = avctx->priv; + AVFilterLink *inlink = outlink->src->inputs[0]; + CFStringRef rotation = kVTRotation_0; + CFBooleanRef vflip = kCFBooleanFalse; + CFBooleanRef hflip = kCFBooleanFalse; + int swap_w_h = 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); + return 0; + } + + s->passthrough = TRANSPOSE_PT_TYPE_NONE; + + switch (s->dir) { + case TRANSPOSE_CCLOCK_FLIP: + rotation = kVTRotation_CCW90; + vflip = kCFBooleanTrue; + swap_w_h = 1; + break; + case TRANSPOSE_CCLOCK: + rotation = kVTRotation_CCW90; + swap_w_h = 1; + break; + case TRANSPOSE_CLOCK: + rotation = kVTRotation_CW90; + swap_w_h = 1; + break; + case TRANSPOSE_CLOCK_FLIP: + rotation = kVTRotation_CW90; + vflip = kCFBooleanTrue; + swap_w_h = 1; + break; + case TRANSPOSE_REVERSAL: + rotation = kVTRotation_180; + break; + case TRANSPOSE_HFLIP: + hflip = kCFBooleanTrue; + break; + case TRANSPOSE_VFLIP: + vflip = kCFBooleanTrue; + break; + default: + av_log(avctx, AV_LOG_ERROR, "Failed to set direction to %d\n", s->dir); + return AVERROR(EINVAL); + } + + err = VTSessionSetProperty(s->session, kVTPixelRotationPropertyKey_Rotation, + rotation); + if (err != noErr) { + av_log(avctx, AV_LOG_ERROR, "Set rotation property failed, %d\n", err); + return AVERROR_EXTERNAL; + } + err = VTSessionSetProperty(s->session, kVTPixelRotationPropertyKey_FlipVerticalOrientation, + vflip); + if (err != noErr) { + av_log(avctx, AV_LOG_ERROR, "Set vertical flip property failed, %d\n", err); + return AVERROR_EXTERNAL; + } + err = VTSessionSetProperty(s->session, kVTPixelRotationPropertyKey_FlipHorizontalOrientation, + hflip); + if (err != noErr) { + av_log(avctx, AV_LOG_ERROR, "Set horizontal flip property failed, %d\n", err); + return AVERROR_EXTERNAL; + } + + if (swap_w_h) { + outlink->w = inlink->h; + outlink->h = inlink->w; + } + + return 0; +} + +#define OFFSET(x) offsetof(TransposeVtContext, x) +#define FLAGS (AV_OPT_FLAG_FILTERING_PARAM | AV_OPT_FLAG_VIDEO_PARAM) +static const AVOption transpose_vt_options[] = { + { "dir", "set transpose direction", + OFFSET(dir), AV_OPT_TYPE_INT, { .i64 = TRANSPOSE_CCLOCK_FLIP }, 0, 6, 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" }, + { "reversal", "rotate by half-turn", + 0, AV_OPT_TYPE_CONST, { .i64 = TRANSPOSE_REVERSAL }, .flags=FLAGS, .unit = "dir" }, + { "hflip", "flip horizontally", + 0, AV_OPT_TYPE_CONST, { .i64 = TRANSPOSE_HFLIP }, .flags=FLAGS, .unit = "dir" }, + { "vflip", "flip vertically", + 0, AV_OPT_TYPE_CONST, { .i64 = TRANSPOSE_VFLIP }, .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 } +}; + +AVFILTER_DEFINE_CLASS(transpose_vt); + +static const AVFilterPad transpose_vt_inputs[] = { + { + .name = "default", + .type = AVMEDIA_TYPE_VIDEO, + .filter_frame = &transpose_vt_filter_frame, + }, +}; + +static const AVFilterPad transpose_vt_outputs[] = { + { + .name = "default", + .type = AVMEDIA_TYPE_VIDEO, + .config_props = &transpose_vt_config_output, + }, +}; + +const AVFilter ff_vf_transpose_vt = { + .name = "transpose_vt", + .description = NULL_IF_CONFIG_SMALL("Transpose Videotoolbox frames"), + .priv_size = sizeof(TransposeVtContext), + .init = transpose_vt_init, + .uninit = transpose_vt_uninit, + FILTER_INPUTS(transpose_vt_inputs), + FILTER_OUTPUTS(transpose_vt_outputs), + FILTER_SINGLE_PIXFMT(AV_PIX_FMT_VIDEOTOOLBOX), + .priv_class = &transpose_vt_class, + .flags = AVFILTER_FLAG_HWDEVICE, +}; From e9e37ea2f111cefa8654367cb3f920c1997e3760 Mon Sep 17 00:00:00 2001 From: Niklas Haas Date: Sun, 23 Jul 2023 17:49:29 +0200 Subject: [PATCH 2002/2172] avfilter/vf_libplacebo: fix skip_aa option range Max incorrectly specified as 0, should be 1. --- libavfilter/vf_libplacebo.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavfilter/vf_libplacebo.c b/libavfilter/vf_libplacebo.c index 3b92719225d..0733211d0bd 100644 --- a/libavfilter/vf_libplacebo.c +++ b/libavfilter/vf_libplacebo.c @@ -1453,7 +1453,7 @@ static const AVOption libplacebo_options[] = { { "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 }, + { "skip_aa", "Skip anti-aliasing", OFFSET(skip_aa), AV_OPT_TYPE_BOOL, {.i64 = 0}, 0, 1, DYNAMIC }, { "polar_cutoff", "Polar LUT cutoff", OFFSET(polar_cutoff), AV_OPT_TYPE_FLOAT, {.dbl = 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 }, From 2a44c4bc9e2623e623981efe9f2510a45fce84f1 Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt Date: Sat, 22 Jul 2023 20:28:25 +0200 Subject: [PATCH 2003/2172] fftools/ffmpeg_mux_init: Fix leak on error Fixes Coverity issue #1539098. Reviewed-by: Anton Khirnov Signed-off-by: Andreas Rheinhardt --- fftools/ffmpeg_mux_init.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fftools/ffmpeg_mux_init.c b/fftools/ffmpeg_mux_init.c index 86521417ec1..0289cdabad2 100644 --- a/fftools/ffmpeg_mux_init.c +++ b/fftools/ffmpeg_mux_init.c @@ -361,7 +361,7 @@ static int enc_stats_init(OutputStream *ost, EncStats *es, int pre, ret = GROW_ARRAY(es->components, es->nb_components); if (ret < 0) - return ret; + goto fail; c = &es->components[es->nb_components - 1]; From 2654347d7adba61ab8a8cce470d657958f6f00f9 Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt Date: Sat, 22 Jul 2023 20:34:18 +0200 Subject: [PATCH 2004/2172] fftools/ffmpeg_opt: Fix leak on error Fixes Coverity issue #1539097. Reviewed-by: Anton Khirnov Signed-off-by: Andreas Rheinhardt --- fftools/ffmpeg_opt.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/fftools/ffmpeg_opt.c b/fftools/ffmpeg_opt.c index 700db706a1f..f7606ae6f60 100644 --- a/fftools/ffmpeg_opt.c +++ b/fftools/ffmpeg_opt.c @@ -497,7 +497,7 @@ static int opt_map_channel(void *optctx, const char *opt, const char *arg) ret = GROW_ARRAY(o->audio_channel_maps, o->nb_audio_channel_maps); if (ret < 0) - return ret; + goto end; m = &o->audio_channel_maps[o->nb_audio_channel_maps - 1]; @@ -559,11 +559,13 @@ static int opt_map_channel(void *optctx, const char *opt, const char *arg) } } + ret = 0; +end: av_free(mapchan); - return 0; + return ret; fail: - av_free(mapchan); - return AVERROR(EINVAL); + ret = AVERROR(EINVAL); + goto end; } #endif From 0368ded1a9fab23077cfc50f8878a0193dfd0510 Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt Date: Sat, 22 Jul 2023 20:41:04 +0200 Subject: [PATCH 2005/2172] fftools/opt_common: Fix leak on error Fixes Coverity issue #743443. Reviewed-by: Anton Khirnov Signed-off-by: Andreas Rheinhardt --- fftools/opt_common.c | 1 + 1 file changed, 1 insertion(+) diff --git a/fftools/opt_common.c b/fftools/opt_common.c index 913932c914b..7c996f140d2 100644 --- a/fftools/opt_common.c +++ b/fftools/opt_common.c @@ -1165,6 +1165,7 @@ int init_report(const char *env, FILE **file) av_log(NULL, AV_LOG_FATAL, "Invalid report file level\n"); av_free(key); av_free(val); + av_free(filename_template); return AVERROR(EINVAL); } envlevel = 1; From 8bb1bcf47d532c6f67dbc444bb7893f6f94f4c8a Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt Date: Sat, 22 Jul 2023 20:55:10 +0200 Subject: [PATCH 2006/2172] fftools/ffmpeg_opt: Fix leak on error Fixes Coverity id #1539096. Reviewed-by: Anton Khirnov Signed-off-by: Andreas Rheinhardt --- fftools/ffmpeg_opt.c | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/fftools/ffmpeg_opt.c b/fftools/ffmpeg_opt.c index f7606ae6f60..1860e9d329a 100644 --- a/fftools/ffmpeg_opt.c +++ b/fftools/ffmpeg_opt.c @@ -401,13 +401,14 @@ static int opt_map(void *optctx, const char *opt, const char *arg) ret = GROW_ARRAY(o->stream_maps, o->nb_stream_maps); if (ret < 0) - return ret; + goto fail; m = &o->stream_maps[o->nb_stream_maps - 1]; m->linklabel = av_get_token(&c, "]"); if (!m->linklabel) { av_log(NULL, AV_LOG_ERROR, "Invalid output link label: %s.\n", map); - return AVERROR(EINVAL); + ret = AVERROR(EINVAL); + goto fail; } } else { if (allow_unused = strchr(map, '?')) @@ -415,7 +416,8 @@ static int opt_map(void *optctx, const char *opt, const char *arg) file_idx = strtol(map, &p, 0); if (file_idx >= nb_input_files || file_idx < 0) { av_log(NULL, AV_LOG_FATAL, "Invalid input file index: %d.\n", file_idx); - return AVERROR(EINVAL); + ret = AVERROR(EINVAL); + goto fail; } if (negative) /* disable some already defined maps */ @@ -438,7 +440,7 @@ static int opt_map(void *optctx, const char *opt, const char *arg) } ret = GROW_ARRAY(o->stream_maps, o->nb_stream_maps); if (ret < 0) - return ret; + goto fail; m = &o->stream_maps[o->nb_stream_maps - 1]; @@ -453,16 +455,19 @@ static int opt_map(void *optctx, const char *opt, const char *arg) } else if (disabled) { av_log(NULL, AV_LOG_FATAL, "Stream map '%s' matches disabled streams.\n" "To ignore this, add a trailing '?' to the map.\n", arg); - return AVERROR(EINVAL); + ret = AVERROR(EINVAL); + goto fail; } else { av_log(NULL, AV_LOG_FATAL, "Stream map '%s' matches no streams.\n" "To ignore this, add a trailing '?' to the map.\n", arg); - return AVERROR(EINVAL); + ret = AVERROR(EINVAL); + goto fail; } } - + ret = 0; +fail: av_freep(&map); - return 0; + return ret; } static int opt_attach(void *optctx, const char *opt, const char *arg) From 071c625ad71ce328075408d564bbd9d6fbd42c5b Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt Date: Sat, 22 Jul 2023 20:57:12 +0200 Subject: [PATCH 2007/2172] fftools/ffmpeg_opt: Reduce scope of variables for deprecated code Reviewed-by: Anton Khirnov Signed-off-by: Andreas Rheinhardt --- fftools/ffmpeg_opt.c | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/fftools/ffmpeg_opt.c b/fftools/ffmpeg_opt.c index 1860e9d329a..dc6044120a0 100644 --- a/fftools/ffmpeg_opt.c +++ b/fftools/ffmpeg_opt.c @@ -372,9 +372,6 @@ static int opt_map(void *optctx, const char *opt, const char *arg) StreamMap *m = NULL; int i, negative = 0, file_idx, disabled = 0; int ret; -#if FFMPEG_OPT_MAP_SYNC - char *sync; -#endif char *map, *p; char *allow_unused; @@ -387,10 +384,14 @@ static int opt_map(void *optctx, const char *opt, const char *arg) return AVERROR(ENOMEM); #if FFMPEG_OPT_MAP_SYNC - /* parse sync stream first, just pick first matching stream */ - if (sync = strchr(map, ',')) { - *sync = 0; - av_log(NULL, AV_LOG_WARNING, "Specifying a sync stream is deprecated and has no effect\n"); + { + /* parse sync stream first, just pick first matching stream */ + char *sync = strchr(map, ','); + + if (sync) { + *sync = 0; + av_log(NULL, AV_LOG_WARNING, "Specifying a sync stream is deprecated and has no effect\n"); + } } #endif From 40cec0b46570bb27a5a0145ceab932d0318e6e52 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Mon, 24 Apr 2023 18:16:05 +0200 Subject: [PATCH 2008/2172] avcodec/wavarc: Fix k limit The implementation does not support k=32 Fixes: shift exponent 32 is too large for 32-bit type 'unsigned int' Fixes: 57976/clusterfuzz-testcase-minimized-ffmpeg_AV_CODEC_ID_WAVARC_fuzzer-5911925807775744 Found-by: continuous fuzzing process https://github.com/google/oss-fuzz/tree/master/projects/ffmpeg Signed-off-by: Michael Niedermayer --- libavcodec/wavarc.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libavcodec/wavarc.c b/libavcodec/wavarc.c index 6daad6a5a11..8e4c7d17dcd 100644 --- a/libavcodec/wavarc.c +++ b/libavcodec/wavarc.c @@ -205,7 +205,7 @@ static int decode_1dif(AVCodecContext *avctx, if (block_type < 4 && block_type >= 0) { k = 1 + (avctx->sample_fmt == AV_SAMPLE_FMT_S16P); k = get_urice(gb, k) + 1; - if (k > 32) + if (k >= 32) return AVERROR_INVALIDDATA; } @@ -297,7 +297,7 @@ static int decode_2slp(AVCodecContext *avctx, if (block_type < 5 && block_type >= 0) { k = 1 + (avctx->sample_fmt == AV_SAMPLE_FMT_S16P); k = get_urice(gb, k) + 1; - if (k > 32) + if (k >= 32) return AVERROR_INVALIDDATA; } From 87f76d3bee083d33707ed2cb459507186e32fc12 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Mon, 24 Apr 2023 18:21:28 +0200 Subject: [PATCH 2009/2172] avcodec/aacdec_template: Fix undefined signed interger operations Fixed: signed integer overflow: -2 * -1085502286 cannot be represented in type 'int' Fixed: 57986/clusterfuzz-testcase-minimized-ffmpeg_AV_CODEC_ID_AAC_FIXED_fuzzer-5123651145170944 Found-by: continuous fuzzing process https://github.com/google/oss-fuzz/tree/master/projects/ffmpeg Signed-off-by: Michael Niedermayer --- libavcodec/aacdec_template.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libavcodec/aacdec_template.c b/libavcodec/aacdec_template.c index 2385ea58b0a..e8dcd460a07 100644 --- a/libavcodec/aacdec_template.c +++ b/libavcodec/aacdec_template.c @@ -2856,8 +2856,8 @@ static void imdct_and_windowing_eld(AACContext *ac, SingleChannelElement *sce) ac->mdct512_fn(ac->mdct512, buf, in, sizeof(INTFLOAT)); for (i = 0; i < n; i+=2) { - buf[i + 0] = -(USE_FIXED + 1)*buf[i + 0]; - buf[i + 1] = (USE_FIXED + 1)*buf[i + 1]; + buf[i + 0] = -(int)(USE_FIXED + 1U)*buf[i + 0]; + buf[i + 1] = (int)(USE_FIXED + 1U)*buf[i + 1]; } // Like with the regular IMDCT at this point we still have the middle half // of a transform but with even symmetry on the left and odd symmetry on From 13f49a7c62094035ca169201b0313c853365651f Mon Sep 17 00:00:00 2001 From: Wenbin Chen Date: Mon, 17 Jul 2023 13:33:01 +0800 Subject: [PATCH 2010/2172] libavfilter/vf_dnn_detect: bbox index may bigger than bbox number Fix a bug that queried bbox index may bigger than bbox's total number. Signed-off-by: Wenbin Chen --- libavfilter/vf_dnn_detect.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/libavfilter/vf_dnn_detect.c b/libavfilter/vf_dnn_detect.c index 06efce02a63..6ef04e09581 100644 --- a/libavfilter/vf_dnn_detect.c +++ b/libavfilter/vf_dnn_detect.c @@ -106,12 +106,11 @@ static int dnn_detect_post_proc_ov(AVFrame *frame, DNNData *output, AVFilterCont float x1 = detections[i * detect_size + 5]; float y1 = detections[i * detect_size + 6]; - bbox = av_get_detection_bbox(header, i); - if (conf < conf_threshold) { continue; } + bbox = av_get_detection_bbox(header, header->nb_bboxes - nb_bboxes); bbox->x = (int)(x0 * frame->width); bbox->w = (int)(x1 * frame->width) - bbox->x; bbox->y = (int)(y0 * frame->height); From 5b11ee94299fe4e07d3921a3b8f29fff72e1daa1 Mon Sep 17 00:00:00 2001 From: Haihao Xiang Date: Wed, 19 Jul 2023 15:54:04 +0800 Subject: [PATCH 2011/2172] lavd/opengl_enc: fix a compiler error MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit glcontext was added under CONFIG_SDL2 libavdevice/opengl_enc.c: In function ‘opengl_draw’: libavdevice/opengl_enc.c:1204:15: error: ‘OpenGLContext’ has no member named ‘glcontext’ Signed-off-by: Haihao Xiang --- libavdevice/opengl_enc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavdevice/opengl_enc.c b/libavdevice/opengl_enc.c index 8d059343fbe..f9dc846bf11 100644 --- a/libavdevice/opengl_enc.c +++ b/libavdevice/opengl_enc.c @@ -1200,11 +1200,11 @@ static int opengl_draw(AVFormatContext *h, void *input, int repaint, int is_pkt) const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(pix_fmt); int ret; +#if CONFIG_SDL2 /* At this point, opengl->glcontext implies opengl->glcontext */ if (opengl->glcontext) SDL_GL_MakeCurrent(opengl->window, opengl->glcontext); -#if CONFIG_SDL2 if (!opengl->no_window && (ret = opengl_sdl_process_events(h)) < 0) goto fail; #endif From 3fe98db7bbe7132a5d0893597ed5d68923902965 Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt Date: Mon, 17 Jul 2023 02:37:02 +0200 Subject: [PATCH 2012/2172] avcodec/vvc_mp4toannexb_bsf: Improve included headers A BSF should never include avcodec.h at all. Signed-off-by: Andreas Rheinhardt --- libavcodec/vvc_mp4toannexb_bsf.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/libavcodec/vvc_mp4toannexb_bsf.c b/libavcodec/vvc_mp4toannexb_bsf.c index 9e606cdc274..25c37269181 100644 --- a/libavcodec/vvc_mp4toannexb_bsf.c +++ b/libavcodec/vvc_mp4toannexb_bsf.c @@ -24,14 +24,12 @@ #include "libavutil/intreadwrite.h" #include "libavutil/mem.h" -#include "avcodec.h" #include "bsf.h" #include "bsf_internal.h" #include "bytestream.h" +#include "defs.h" #include "vvc.h" -#include "libavcodec/get_bits.h" - #define MIN_VVCC_LENGTH 23 typedef struct VVCBSFContext { From 6e5e74c55bb71e17dcfc7519c6badf3334644f48 Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt Date: Mon, 17 Jul 2023 02:56:57 +0200 Subject: [PATCH 2013/2172] avcodec/evc*: Improve included headers In particular, don't include avcodec.h in evc_frame_merge_bsf.c. Signed-off-by: Andreas Rheinhardt --- libavcodec/evc_frame_merge_bsf.c | 3 +-- libavcodec/evc_parse.c | 1 - libavcodec/evc_parse.h | 1 - libavcodec/evc_parser.c | 2 +- libavcodec/evc_ps.c | 2 +- 5 files changed, 3 insertions(+), 6 deletions(-) diff --git a/libavcodec/evc_frame_merge_bsf.c b/libavcodec/evc_frame_merge_bsf.c index cfdf24c69e7..7b8e6b1c9ee 100644 --- a/libavcodec/evc_frame_merge_bsf.c +++ b/libavcodec/evc_frame_merge_bsf.c @@ -18,13 +18,12 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include "get_bits.h" -#include "golomb.h" #include "bsf.h" #include "bsf_internal.h" -#include "avcodec.h" #include "evc.h" #include "evc_parse.h" +#include "evc_ps.h" // Access unit data typedef struct AccessUnitBuffer { diff --git a/libavcodec/evc_parse.c b/libavcodec/evc_parse.c index 447f6195c23..bd3a4416f2d 100644 --- a/libavcodec/evc_parse.c +++ b/libavcodec/evc_parse.c @@ -17,7 +17,6 @@ */ #include "golomb.h" -#include "parser.h" #include "evc.h" #include "evc_parse.h" diff --git a/libavcodec/evc_parse.h b/libavcodec/evc_parse.h index 55cdd553eae..4712310826b 100644 --- a/libavcodec/evc_parse.h +++ b/libavcodec/evc_parse.h @@ -28,7 +28,6 @@ #include "libavutil/intreadwrite.h" #include "libavutil/log.h" -#include "libavutil/rational.h" #include "evc.h" #include "evc_ps.h" diff --git a/libavcodec/evc_parser.c b/libavcodec/evc_parser.c index 76790d81110..8590ebcdafc 100644 --- a/libavcodec/evc_parser.c +++ b/libavcodec/evc_parser.c @@ -20,7 +20,7 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include "parser.h" +#include "avcodec.h" #include "bytestream.h" #include "evc.h" #include "evc_parse.h" diff --git a/libavcodec/evc_ps.c b/libavcodec/evc_ps.c index fc2105b352c..04ee6a45e6d 100644 --- a/libavcodec/evc_ps.c +++ b/libavcodec/evc_ps.c @@ -16,8 +16,8 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#include "get_bits.h" #include "golomb.h" -#include "parser.h" #include "evc.h" #include "evc_ps.h" From 9fb2efe3b33e9b589f6e93a32b5128b3aef98ab1 Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Sun, 23 Jul 2023 09:04:46 +0200 Subject: [PATCH 2014/2172] avfilter/avf_showcwt: make read only variable const --- libavfilter/avf_showcwt.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libavfilter/avf_showcwt.c b/libavfilter/avf_showcwt.c index 0661afbcdd0..8badfbd34e8 100644 --- a/libavfilter/avf_showcwt.c +++ b/libavfilter/avf_showcwt.c @@ -577,7 +577,7 @@ static int run_channel_cwt(AVFilterContext *ctx, void *arg, int jobnr, int nb_jo { ShowCWTContext *s = ctx->priv; const int ch = *(int *)arg; - AVComplexFloat *dst = (AVComplexFloat *)s->fft_out->extended_data[ch]; + const AVComplexFloat *fft_out = (const AVComplexFloat *)s->fft_out->extended_data[ch]; const int output_padding_size = s->output_padding_size; const int ihop_size = s->ihop_size; const int ioffset = (output_padding_size - ihop_size) >> 1; @@ -597,7 +597,7 @@ static int run_channel_cwt(AVFilterContext *ctx, void *arg, int jobnr, int nb_jo const int kernel_stop = s->kernel_stop[y]; const int kernel_range = kernel_stop - kernel_start; - memcpy(srcx, dst + kernel_start, sizeof(*dst) * kernel_range); + memcpy(srcx, fft_out + kernel_start, sizeof(*fft_out) * kernel_range); s->fdsp->vector_fmul((float *)dstx, (const float *)srcx, (const float *)kernel, FFALIGN(kernel_range * 2, 16)); From 60244d0becd06239edbac06ef3c81fa22310b031 Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Mon, 24 Jul 2023 10:34:17 +0200 Subject: [PATCH 2015/2172] avfilter/af_afir: fix possible array read-overflow --- libavfilter/af_afir.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavfilter/af_afir.c b/libavfilter/af_afir.c index 502e544687b..e00d14d0849 100644 --- a/libavfilter/af_afir.c +++ b/libavfilter/af_afir.c @@ -222,8 +222,8 @@ static int init_segment(AVFilterContext *ctx, AudioFIRSegment *seg, int selir, seg->fft_length = (part_size + 1) * 2; seg->part_size = part_size; - seg->block_size = FFALIGN(seg->fft_length, cpu_align); seg->coeff_size = FFALIGN(seg->part_size + 1, cpu_align); + seg->block_size = FFMAX(seg->coeff_size * 2, FFALIGN(seg->fft_length, cpu_align)); seg->nb_partitions = nb_partitions; seg->input_size = offset + s->min_part_size; seg->input_offset = offset; From f8035bc4260568f9e37b80c23a43f676d7da39c2 Mon Sep 17 00:00:00 2001 From: Timo Rothenpieler Date: Tue, 25 Jul 2023 01:46:31 +0200 Subject: [PATCH 2016/2172] avformat/flvenc: write proper timestamps when muxing hevc --- libavformat/flvenc.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/libavformat/flvenc.c b/libavformat/flvenc.c index 335d9004156..f6d10f331c5 100644 --- a/libavformat/flvenc.c +++ b/libavformat/flvenc.c @@ -863,6 +863,9 @@ static int flv_write_packet(AVFormatContext *s, AVPacket *pkt) else flags_size = 1; + if (par->codec_id == AV_CODEC_ID_HEVC && pkt->pts != pkt->dts) + flags_size += 3; + if (par->codec_id == AV_CODEC_ID_AAC || par->codec_id == AV_CODEC_ID_H264 || par->codec_id == AV_CODEC_ID_MPEG4 || par->codec_id == AV_CODEC_ID_HEVC || par->codec_id == AV_CODEC_ID_AV1 || par->codec_id == AV_CODEC_ID_VP9) { @@ -998,8 +1001,11 @@ static int flv_write_packet(AVFormatContext *s, AVPacket *pkt) } else { av_assert1(flags>=0); if (par->codec_id == AV_CODEC_ID_HEVC) { - avio_w8(pb, FLV_IS_EX_HEADER | PacketTypeCodedFramesX | frametype); // ExVideoTagHeader mode with PacketTypeCodedFramesX + int pkttype = (pkt->pts != pkt->dts) ? PacketTypeCodedFrames : PacketTypeCodedFramesX; + avio_w8(pb, FLV_IS_EX_HEADER | pkttype | frametype); // ExVideoTagHeader mode with PacketTypeCodedFrames(X) avio_write(pb, "hvc1", 4); + if (pkttype == PacketTypeCodedFrames) + avio_wb24(pb, pkt->pts - pkt->dts); } else if (par->codec_id == AV_CODEC_ID_AV1 || par->codec_id == AV_CODEC_ID_VP9) { avio_w8(pb, FLV_IS_EX_HEADER | PacketTypeCodedFrames | frametype); avio_write(pb, par->codec_id == AV_CODEC_ID_AV1 ? "av01" : "vp09", 4); From 6dd5f9509334f53a4217540d430360d49578ecee Mon Sep 17 00:00:00 2001 From: Hendrik Leppkes Date: Tue, 25 Jul 2023 01:41:23 +0200 Subject: [PATCH 2017/2172] avformat/flvdec: fix size desync when reading timestamp offsets The size offset was previously being accounted for in flv_set_video_codec for h264 and mpeg4, instead of being directly accounted for in the spot where its read, which desynced on HEVC streams. For clarity, move the size offset directly to the parsing, similar to how its done for all other header fields. --- libavformat/flvdec.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/libavformat/flvdec.c b/libavformat/flvdec.c index a6a94a4021d..3fe21622f79 100644 --- a/libavformat/flvdec.c +++ b/libavformat/flvdec.c @@ -407,11 +407,9 @@ static int flv_set_video_codec(AVFormatContext *s, AVStream *vstream, case FLV_CODECID_H264: par->codec_id = AV_CODEC_ID_H264; vstreami->need_parsing = AVSTREAM_PARSE_HEADERS; - ret = 3; // not 4, reading packet type will consume one byte break; case FLV_CODECID_MPEG4: par->codec_id = AV_CODEC_ID_MPEG4; - ret = 3; break; default: avpriv_request_sample(s, "Video codec (%x)", flv_codecid); @@ -1321,6 +1319,7 @@ static int flv_read_packet(AVFormatContext *s, AVPacket *pkt) "invalid timestamps %"PRId64" %"PRId64"\n", dts, pts); dts = pts = AV_NOPTS_VALUE; } + size -= 3; } if (type == 0 && (!st->codecpar->extradata || st->codecpar->codec_id == AV_CODEC_ID_AAC || st->codecpar->codec_id == AV_CODEC_ID_H264 || st->codecpar->codec_id == AV_CODEC_ID_HEVC || From 8d1316e51561882a30a3febb77f600a8bb6a5034 Mon Sep 17 00:00:00 2001 From: Arnie Chang Date: Mon, 19 Jun 2023 21:06:09 +0800 Subject: [PATCH 2018/2172] lavc/h264chroma: RISC-V V add motion compensation for 4xH and 2xH chroma blocks MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Optimize the put and avg filtering for 4xH and 2xH blocks Signed-off-by: Rémi Denis-Courmont --- libavcodec/riscv/h264_chroma_init_riscv.c | 8 + libavcodec/riscv/h264_mc_chroma.S | 237 ++++++++++++++-------- 2 files changed, 160 insertions(+), 85 deletions(-) diff --git a/libavcodec/riscv/h264_chroma_init_riscv.c b/libavcodec/riscv/h264_chroma_init_riscv.c index f3e912823b5..e6fe5f6ed63 100644 --- a/libavcodec/riscv/h264_chroma_init_riscv.c +++ b/libavcodec/riscv/h264_chroma_init_riscv.c @@ -27,6 +27,10 @@ void h264_put_chroma_mc8_rvv(uint8_t *p_dst, const uint8_t *p_src, ptrdiff_t stride, int h, int x, int y); void h264_avg_chroma_mc8_rvv(uint8_t *p_dst, const uint8_t *p_src, ptrdiff_t stride, int h, int x, int y); +void h264_put_chroma_mc4_rvv(uint8_t *p_dst, const uint8_t *p_src, ptrdiff_t stride, int h, int x, int y); +void h264_avg_chroma_mc4_rvv(uint8_t *p_dst, const uint8_t *p_src, ptrdiff_t stride, int h, int x, int y); +void h264_put_chroma_mc2_rvv(uint8_t *p_dst, const uint8_t *p_src, ptrdiff_t stride, int h, int x, int y); +void h264_avg_chroma_mc2_rvv(uint8_t *p_dst, const uint8_t *p_src, ptrdiff_t stride, int h, int x, int y); av_cold void ff_h264chroma_init_riscv(H264ChromaContext *c, int bit_depth) { @@ -37,6 +41,10 @@ av_cold void ff_h264chroma_init_riscv(H264ChromaContext *c, int bit_depth) (flags & AV_CPU_FLAG_RVB_ADDR) && ff_get_rv_vlenb() >= 16) { c->put_h264_chroma_pixels_tab[0] = h264_put_chroma_mc8_rvv; c->avg_h264_chroma_pixels_tab[0] = h264_avg_chroma_mc8_rvv; + c->put_h264_chroma_pixels_tab[1] = h264_put_chroma_mc4_rvv; + c->avg_h264_chroma_pixels_tab[1] = h264_avg_chroma_mc4_rvv; + c->put_h264_chroma_pixels_tab[2] = h264_put_chroma_mc2_rvv; + c->avg_h264_chroma_pixels_tab[2] = h264_avg_chroma_mc2_rvv; } #endif } diff --git a/libavcodec/riscv/h264_mc_chroma.S b/libavcodec/riscv/h264_mc_chroma.S index 364bc3156e2..ce99bda44dc 100644 --- a/libavcodec/riscv/h264_mc_chroma.S +++ b/libavcodec/riscv/h264_mc_chroma.S @@ -19,8 +19,7 @@ */ #include "libavutil/riscv/asm.S" -.macro h264_chroma_mc8 type -func h264_\type\()_chroma_mc8_rvv, zve32x +.macro do_chroma_mc type unroll csrw vxrm, zero slli t2, a5, 3 mul t1, a5, a4 @@ -30,94 +29,100 @@ func h264_\type\()_chroma_mc8_rvv, zve32x sub a7, a4, t1 addi a6, a5, 64 sub t0, t2, t1 - vsetivli t3, 8, e8, m1, ta, mu + vsetvli t3, t6, e8, m1, ta, mu beqz t1, 2f blez a3, 8f li t4, 0 li t2, 0 li t5, 1 addi a5, t3, 1 - slli t3, a2, 2 + slli t3, a2, (1 + \unroll) 1: # if (xy != 0) add a4, a1, t4 vsetvli zero, a5, e8, m1, ta, ma + .ifc \unroll,1 addi t2, t2, 4 + .else + addi t2, t2, 2 + .endif vle8.v v10, (a4) add a4, a4, a2 vslide1down.vx v11, v10, t5 - vsetivli zero, 8, e8, m1, ta, ma + vsetvli zero, t6, e8, m1, ta, ma vwmulu.vx v8, v10, a6 vwmaccu.vx v8, a7, v11 vsetvli zero, a5, e8, m1, ta, ma vle8.v v12, (a4) - vsetivli zero, 8, e8, m1, ta, ma + vsetvli zero, t6, e8, m1, ta, ma add a4, a4, a2 vwmaccu.vx v8, t0, v12 vsetvli zero, a5, e8, m1, ta, ma vslide1down.vx v13, v12, t5 - vsetivli zero, 8, e8, m1, ta, ma + vsetvli zero, t6, e8, m1, ta, ma vwmulu.vx v10, v12, a6 vwmaccu.vx v8, t1, v13 vwmaccu.vx v10, a7, v13 vsetvli zero, a5, e8, m1, ta, ma vle8.v v14, (a4) - vsetivli zero, 8, e8, m1, ta, ma + vsetvli zero, t6, e8, m1, ta, ma add a4, a4, a2 vwmaccu.vx v10, t0, v14 vsetvli zero, a5, e8, m1, ta, ma vslide1down.vx v15, v14, t5 - vsetivli zero, 8, e8, m1, ta, ma + vsetvli zero, t6, e8, m1, ta, ma vwmulu.vx v12, v14, a6 vwmaccu.vx v10, t1, v15 vwmaccu.vx v12, a7, v15 + vnclipu.wi v15, v8, 6 + .ifc \type,avg + vle8.v v9, (a0) + vaaddu.vv v15, v15, v9 + .endif + vse8.v v15, (a0) + add a0, a0, a2 + vnclipu.wi v8, v10, 6 + .ifc \type,avg + vle8.v v9, (a0) + vaaddu.vv v8, v8, v9 + .endif + add t4, t4, t3 + vse8.v v8, (a0) + add a0, a0, a2 + .ifc \unroll,1 vsetvli zero, a5, e8, m1, ta, ma vle8.v v14, (a4) - vsetivli zero, 8, e8, m1, ta, ma + vsetvli zero, t6, e8, m1, ta, ma add a4, a4, a2 vwmaccu.vx v12, t0, v14 vsetvli zero, a5, e8, m1, ta, ma vslide1down.vx v15, v14, t5 - vsetivli zero, 8, e8, m1, ta, ma + vsetvli zero, t6, e8, m1, ta, ma vwmulu.vx v16, v14, a6 vwmaccu.vx v12, t1, v15 vwmaccu.vx v16, a7, v15 vsetvli zero, a5, e8, m1, ta, ma vle8.v v14, (a4) - vsetivli zero, 8, e8, m1, ta, ma - add a4, a0, t4 - add t4, t4, t3 + vsetvli zero, t6, e8, m1, ta, ma vwmaccu.vx v16, t0, v14 vsetvli zero, a5, e8, m1, ta, ma vslide1down.vx v14, v14, t5 - vsetivli zero, 8, e8, m1, ta, ma - vnclipu.wi v15, v8, 6 + vsetvli zero, t6, e8, m1, ta, ma vwmaccu.vx v16, t1, v14 - .ifc \type,avg - vle8.v v9, (a4) - vaaddu.vv v15, v15, v9 - .endif - vse8.v v15, (a4) - add a4, a4, a2 - vnclipu.wi v8, v10, 6 - .ifc \type,avg - vle8.v v9, (a4) - vaaddu.vv v8, v8, v9 - .endif - vse8.v v8, (a4) - add a4, a4, a2 vnclipu.wi v8, v12, 6 .ifc \type,avg - vle8.v v9, (a4) + vle8.v v9, (a0) vaaddu.vv v8, v8, v9 .endif - vse8.v v8, (a4) - add a4, a4, a2 + vse8.v v8, (a0) + add a0, a0, a2 vnclipu.wi v8, v16, 6 .ifc \type,avg - vle8.v v9, (a4) + vle8.v v9, (a0) vaaddu.vv v8, v8, v9 .endif - vse8.v v8, (a4) + vse8.v v8, (a0) + add a0, a0, a2 + .endif blt t2, a3, 1b j 8f 2: @@ -126,11 +131,15 @@ func h264_\type\()_chroma_mc8_rvv, zve32x blez a3, 8f li a4, 0 li t1, 0 - slli a7, a2, 2 + slli a7, a2, (1 + \unroll) 3: # if ((x8 - xy) == 0 && (y8 -xy) != 0) add a5, a1, a4 vsetvli zero, zero, e8, m1, ta, ma + .ifc \unroll,1 addi t1, t1, 4 + .else + addi t1, t1, 2 + .endif vle8.v v8, (a5) add a5, a5, a2 add t2, a5, a2 @@ -141,42 +150,44 @@ func h264_\type\()_chroma_mc8_rvv, zve32x add t2, t2, a2 add a5, t2, a2 vwmaccu.vx v10, t0, v8 - vle8.v v8, (t2) - vle8.v v14, (a5) - add a5, a0, a4 add a4, a4, a7 vwmaccu.vx v12, t0, v9 vnclipu.wi v15, v10, 6 vwmulu.vx v10, v9, a6 + vnclipu.wi v9, v12, 6 .ifc \type,avg - vle8.v v16, (a5) + vle8.v v16, (a0) vaaddu.vv v15, v15, v16 .endif - vse8.v v15, (a5) - add a5, a5, a2 - vnclipu.wi v9, v12, 6 - vwmaccu.vx v10, t0, v8 - vwmulu.vx v12, v8, a6 + vse8.v v15, (a0) + add a0, a0, a2 .ifc \type,avg - vle8.v v16, (a5) + vle8.v v16, (a0) vaaddu.vv v9, v9, v16 .endif - vse8.v v9, (a5) - add a5, a5, a2 + vse8.v v9, (a0) + add a0, a0, a2 + .ifc \unroll,1 + vle8.v v8, (t2) + vle8.v v14, (a5) + vwmaccu.vx v10, t0, v8 + vwmulu.vx v12, v8, a6 vnclipu.wi v8, v10, 6 vwmaccu.vx v12, t0, v14 .ifc \type,avg - vle8.v v16, (a5) + vle8.v v16, (a0) vaaddu.vv v8, v8, v16 .endif - vse8.v v8, (a5) - add a5, a5, a2 + vse8.v v8, (a0) + add a0, a0, a2 vnclipu.wi v8, v12, 6 .ifc \type,avg - vle8.v v16, (a5) + vle8.v v16, (a0) vaaddu.vv v8, v8, v16 .endif - vse8.v v8, (a5) + vse8.v v8, (a0) + add a0, a0, a2 + .endif blt t1, a3, 3b j 8f 4: @@ -186,87 +197,95 @@ func h264_\type\()_chroma_mc8_rvv, zve32x li a4, 0 li t2, 0 addi t0, t3, 1 - slli t1, a2, 2 + slli t1, a2, (1 + \unroll) 5: # if ((x8 - xy) != 0 && (y8 -xy) == 0) add a5, a1, a4 vsetvli zero, t0, e8, m1, ta, ma + .ifc \unroll,1 addi t2, t2, 4 + .else + addi t2, t2, 2 + .endif vle8.v v8, (a5) add a5, a5, a2 vslide1down.vx v9, v8, t5 - vsetivli zero, 8, e8, m1, ta, ma + vsetvli zero, t6, e8, m1, ta, ma vwmulu.vx v10, v8, a6 vwmaccu.vx v10, a7, v9 vsetvli zero, t0, e8, m1, ta, ma vle8.v v8, (a5) add a5, a5, a2 vslide1down.vx v9, v8, t5 - vsetivli zero, 8, e8, m1, ta, ma + vsetvli zero, t6, e8, m1, ta, ma vwmulu.vx v12, v8, a6 vwmaccu.vx v12, a7, v9 + vnclipu.wi v16, v10, 6 + .ifc \type,avg + vle8.v v18, (a0) + vaaddu.vv v16, v16, v18 + .endif + vse8.v v16, (a0) + add a0, a0, a2 + vnclipu.wi v10, v12, 6 + .ifc \type,avg + vle8.v v18, (a0) + vaaddu.vv v10, v10, v18 + .endif + add a4, a4, t1 + vse8.v v10, (a0) + add a0, a0, a2 + .ifc \unroll,1 vsetvli zero, t0, e8, m1, ta, ma vle8.v v8, (a5) add a5, a5, a2 vslide1down.vx v9, v8, t5 - vsetivli zero, 8, e8, m1, ta, ma + vsetvli zero, t6, e8, m1, ta, ma vwmulu.vx v14, v8, a6 vwmaccu.vx v14, a7, v9 vsetvli zero, t0, e8, m1, ta, ma vle8.v v8, (a5) - add a5, a0, a4 - add a4, a4, t1 vslide1down.vx v9, v8, t5 - vsetivli zero, 8, e8, m1, ta, ma - vnclipu.wi v16, v10, 6 - .ifc \type,avg - vle8.v v18, (a5) - vaaddu.vv v16, v16, v18 - .endif - vse8.v v16, (a5) - add a5, a5, a2 - vnclipu.wi v10, v12, 6 + vsetvli zero, t6, e8, m1, ta, ma vwmulu.vx v12, v8, a6 - .ifc \type,avg - vle8.v v18, (a5) - vaaddu.vv v10, v10, v18 - .endif - vse8.v v10, (a5) - add a5, a5, a2 vnclipu.wi v8, v14, 6 vwmaccu.vx v12, a7, v9 .ifc \type,avg - vle8.v v18, (a5) + vle8.v v18, (a0) vaaddu.vv v8, v8, v18 .endif - vse8.v v8, (a5) - add a5, a5, a2 + vse8.v v8, (a0) + add a0, a0, a2 vnclipu.wi v8, v12, 6 .ifc \type,avg - vle8.v v18, (a5) + vle8.v v18, (a0) vaaddu.vv v8, v8, v18 .endif - vse8.v v8, (a5) + vse8.v v8, (a0) + add a0, a0, a2 + .endif blt t2, a3, 5b j 8f 6: blez a3, 8f li a4, 0 li t2, 0 - slli a7, a2, 2 + slli a7, a2, (1 + \unroll) 7: # the final else, none of the above conditions are met add t0, a1, a4 vsetvli zero, zero, e8, m1, ta, ma add a5, a0, a4 add a4, a4, a7 + .ifc \unroll,1 addi t2, t2, 4 + .else + addi t2, t2, 2 + .endif vle8.v v8, (t0) add t0, t0, a2 add t1, t0, a2 vwmulu.vx v10, v8, a6 vle8.v v8, (t0) add t0, t1, a2 - vle8.v v9, (t1) - vle8.v v12, (t0) vnclipu.wi v13, v10, 6 vwmulu.vx v10, v8, a6 .ifc \type,avg @@ -276,13 +295,16 @@ func h264_\type\()_chroma_mc8_rvv, zve32x vse8.v v13, (a5) add a5, a5, a2 vnclipu.wi v8, v10, 6 - vwmulu.vx v10, v9, a6 .ifc \type,avg vle8.v v18, (a5) vaaddu.vv v8, v8, v18 .endif vse8.v v8, (a5) add a5, a5, a2 + .ifc \unroll,1 + vle8.v v9, (t1) + vle8.v v12, (t0) + vwmulu.vx v10, v9, a6 vnclipu.wi v8, v10, 6 vwmulu.vx v10, v12, a6 .ifc \type,avg @@ -297,11 +319,56 @@ func h264_\type\()_chroma_mc8_rvv, zve32x vaaddu.vv v8, v8, v18 .endif vse8.v v8, (a5) + .endif blt t2, a3, 7b 8: ret -endfunc .endm -h264_chroma_mc8 put -h264_chroma_mc8 avg +func h264_put_chroma_mc_rvv, zve32x +11: + li a7, 3 + blt a3, a7, 12f + do_chroma_mc put 1 +12: + do_chroma_mc put 0 +endfunc + +func h264_avg_chroma_mc_rvv, zve32x +21: + li a7, 3 + blt a3, a7, 22f + do_chroma_mc avg 1 +22: + do_chroma_mc avg 0 +endfunc + +func h264_put_chroma_mc8_rvv, zve32x + li t6, 8 + j 11b +endfunc + +func h264_put_chroma_mc4_rvv, zve32x + li t6, 4 + j 11b +endfunc + +func h264_put_chroma_mc2_rvv, zve32x + li t6, 2 + j 11b +endfunc + +func h264_avg_chroma_mc8_rvv, zve32x + li t6, 8 + j 21b +endfunc + +func h264_avg_chroma_mc4_rvv, zve32x + li t6, 4 + j 21b +endfunc + +func h264_avg_chroma_mc2_rvv, zve32x + li t6, 2 + j 21b +endfunc From d383ae43c266b160348db04f2fd17ccf30286784 Mon Sep 17 00:00:00 2001 From: James Almer Date: Thu, 20 Jul 2023 19:55:24 -0300 Subject: [PATCH 2019/2172] avcodec/codec_par: always free side data in the destination AVCodecContext Signed-off-by: James Almer --- libavcodec/codec_par.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavcodec/codec_par.c b/libavcodec/codec_par.c index 775c187073f..a38a475dc73 100644 --- a/libavcodec/codec_par.c +++ b/libavcodec/codec_par.c @@ -253,8 +253,8 @@ FF_ENABLE_DEPRECATION_WARNINGS break; } + av_freep(&codec->extradata); if (par->extradata) { - av_freep(&codec->extradata); codec->extradata = av_mallocz(par->extradata_size + AV_INPUT_BUFFER_PADDING_SIZE); if (!codec->extradata) return AVERROR(ENOMEM); From c92948de407d30ab25ae40f0ef7a7c7cafb9b6f9 Mon Sep 17 00:00:00 2001 From: James Almer Date: Sun, 23 Jul 2023 17:14:54 -0300 Subject: [PATCH 2020/2172] avcodec/decode: consistently set channel info when parsing param change side data avctx->ch_layout was being left unchanged. Signed-off-by: James Almer --- libavcodec/decode.c | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/libavcodec/decode.c b/libavcodec/decode.c index f0e6acc03e8..53c90cddb7a 100644 --- a/libavcodec/decode.c +++ b/libavcodec/decode.c @@ -104,15 +104,26 @@ FF_DISABLE_DEPRECATION_WARNINGS ret = AVERROR_INVALIDDATA; goto fail2; } - avctx->channels = val; + av_channel_layout_uninit(&avctx->ch_layout); + avctx->ch_layout.nb_channels = val; + avctx->ch_layout.order = AV_CHANNEL_ORDER_UNSPEC; size -= 4; } if (flags & AV_SIDE_DATA_PARAM_CHANGE_CHANNEL_LAYOUT) { if (size < 8) goto fail; - avctx->channel_layout = bytestream_get_le64(&data); + av_channel_layout_uninit(&avctx->ch_layout); + ret = av_channel_layout_from_mask(&avctx->ch_layout, bytestream_get_le64(&data)); + if (ret < 0) + goto fail2; size -= 8; } + if (flags & (AV_SIDE_DATA_PARAM_CHANGE_CHANNEL_COUNT | + AV_SIDE_DATA_PARAM_CHANGE_CHANNEL_LAYOUT)) { + avctx->channels = avctx->ch_layout.nb_channels; + avctx->channel_layout = (avctx->ch_layout.order == AV_CHANNEL_ORDER_NATIVE) ? + avctx->ch_layout.u.mask : 0; + } FF_ENABLE_DEPRECATION_WARNINGS #endif if (flags & AV_SIDE_DATA_PARAM_CHANGE_SAMPLE_RATE) { From 673862e9474cd343b686cb549ec09af68ec84d6f Mon Sep 17 00:00:00 2001 From: James Almer Date: Tue, 25 Jul 2023 18:06:40 -0300 Subject: [PATCH 2021/2172] avcodec/cbs_h266_syntax_template: add missing checks to subpic dimension values Fixes: division by zero Fixes: 60306/clusterfuzz-testcase-minimized-ffmpeg_BSF_TRACE_HEADERS_fuzzer-5538913553612800 Found-by: continuous fuzzing process https://github.com/google/oss-fuzz/tree/master/projects/ffmpeg Signed-off-by: James Almer --- libavcodec/cbs_h266_syntax_template.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/libavcodec/cbs_h266_syntax_template.c b/libavcodec/cbs_h266_syntax_template.c index dce0216fbce..98a8e033bfc 100644 --- a/libavcodec/cbs_h266_syntax_template.c +++ b/libavcodec/cbs_h266_syntax_template.c @@ -1140,6 +1140,8 @@ static int FUNC(sps)(CodedBitstreamContext *ctx, RWContext *rw, if (current->sps_num_subpics_minus1 > 0) { int wlen = av_ceil_log2(tmp_width_val); int hlen = av_ceil_log2(tmp_height_val); + infer(sps_subpic_ctu_top_left_x[0], 0); + infer(sps_subpic_ctu_top_left_y[0], 0); if (current->sps_pic_width_max_in_luma_samples > ctb_size_y) ubs(wlen, sps_subpic_width_minus1[0], 1, 0); else @@ -1147,7 +1149,7 @@ static int FUNC(sps)(CodedBitstreamContext *ctx, RWContext *rw, if (current->sps_pic_height_max_in_luma_samples > ctb_size_y) ubs(hlen, sps_subpic_height_minus1[0], 1, 0); else - infer(sps_subpic_height_minus1[0], tmp_height_val); + infer(sps_subpic_height_minus1[0], tmp_height_val - 1); if (!current->sps_independent_subpics_flag) { flags(sps_subpic_treated_as_pic_flag[0], 1, 0); flags(sps_loop_filter_across_subpic_enabled_flag[0], 1, 0); @@ -1187,6 +1189,12 @@ static int FUNC(sps)(CodedBitstreamContext *ctx, RWContext *rw, } else { int num_subpic_cols = tmp_width_val / (current->sps_subpic_width_minus1[0] + 1); + if (tmp_width_val % (current->sps_subpic_width_minus1[0] + 1) || + tmp_height_val % (current->sps_subpic_width_minus1[0] + 1) || + current->sps_num_subpics_minus1 != + (num_subpic_cols * tmp_height_val / + (current->sps_subpic_height_minus1[0] + 1) - 1)) + return AVERROR_INVALIDDATA; infer(sps_subpic_ctu_top_left_x[i], (i % num_subpic_cols) * (current->sps_subpic_width_minus1[0] + 1)); From 574f3aaeff6d04762f02044f1ee1e3564bc3ad00 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Sun, 18 Jun 2023 22:41:01 +0200 Subject: [PATCH 2022/2172] avcodec/vmixdec: Fix several integer anomalies Fixes: vmixdec.c:132:34: runtime error: signed integer overflow: -2147483648 * 1856 cannot be represented in type 'int' Fixes: vmixdec.c:119:20: runtime error: signed integer overflow: -1256 + -2147483648 cannot be represented in type 'int' Fixes: vmixdec.c:137:36: runtime error: signed integer overflow: 2147483416 * 16 cannot be represented in type 'int' Fixes: 59843/clusterfuzz-testcase-minimized-ffmpeg_AV_CODEC_ID_VMIX_fuzzer-4857434624360448 Found-by: continuous fuzzing process https://github.com/google/oss-fuzz/tree/master/projects/ffmpeg Signed-off-by: Michael Niedermayer --- libavcodec/vmixdec.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/libavcodec/vmixdec.c b/libavcodec/vmixdec.c index d0f2219a679..b77c90929a1 100644 --- a/libavcodec/vmixdec.c +++ b/libavcodec/vmixdec.c @@ -116,7 +116,7 @@ static int decode_dcac(AVCodecContext *avctx, dc_run--; } else { dc_v = get_se_golomb_vmix(dc_gb); - dc += dc_v; + dc += (unsigned)dc_v; if (!dc_v) dc_run = get_ue_golomb_long(dc_gb); } @@ -129,12 +129,12 @@ static int decode_dcac(AVCodecContext *avctx, ac_v = get_se_golomb_vmix(ac_gb); i = scan[n]; - block[i] = (ac_v * factors[i]) >> 4; + block[i] = ((unsigned)ac_v * factors[i]) >> 4; if (!ac_v) ac_run = get_ue_golomb_long(ac_gb); } - block[0] = ((dc + add) * 16) >> 4; + block[0] = dc + add; s->idsp.idct_put(dst + x, linesize, block); } From c5c719f030a209cc404754f928972a6c1a24dfef Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Sun, 23 Jul 2023 19:52:35 +0200 Subject: [PATCH 2023/2172] avcodec/h266_metadata_bsf: Check if there are CodedBitstreamFragment units Fixes: NULL pointer dereference Fixes: 60269/clusterfuzz-testcase-minimized-ffmpeg_BSF_VVC_METADATA_fuzzer-5215449416335360 Found-by: continuous fuzzing process https://github.com/google/oss-fuzz/tree/master/projects/ffmpeg Reviewed-by: James Almer Signed-off-by: Michael Niedermayer --- libavcodec/h266_metadata_bsf.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavcodec/h266_metadata_bsf.c b/libavcodec/h266_metadata_bsf.c index c0dbf8ef965..1f0f875cfee 100644 --- a/libavcodec/h266_metadata_bsf.c +++ b/libavcodec/h266_metadata_bsf.c @@ -43,7 +43,7 @@ static int h266_metadata_update_fragment(AVBSFContext *bsf, AVPacket *pkt, int err, i; // If an AUD is present, it must be the first NAL unit. - if (pu->units[0].type == VVC_AUD_NUT) { + if (pu->nb_units && pu->units[0].type == VVC_AUD_NUT) { if (ctx->aud == BSF_ELEMENT_REMOVE) ff_cbs_delete_unit(pu, 0); } else if ( pkt && ctx->aud == BSF_ELEMENT_INSERT) { From 509ce40f188734ec74078ebdd8d71f80116d9eaf Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Sun, 23 Jul 2023 20:03:01 +0200 Subject: [PATCH 2024/2172] avformat/imf_cpl: xmlNodeListGetString() can return NULL Fixes: NULL pointer dereference Fixes: 60166/clusterfuzz-testcase-minimized-ffmpeg_DEMUXER_fuzzer-5998301577871360 Found-by: continuous fuzzing process https://github.com/google/oss-fuzz/tree/master/projects/ffmpeg Reviewed-by: Pierre-Anthony Lemieux Signed-off-by: Michael Niedermayer --- libavformat/imf_cpl.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/libavformat/imf_cpl.c b/libavformat/imf_cpl.c index fe975c2f0c0..69155d786dd 100644 --- a/libavformat/imf_cpl.c +++ b/libavformat/imf_cpl.c @@ -75,6 +75,8 @@ int ff_imf_xml_read_uuid(xmlNodePtr element, AVUUID uuid) int ret = 0; xmlChar *element_text = xmlNodeListGetString(element->doc, element->xmlChildrenNode, 1); + if (!element_text) + return AVERROR_INVALIDDATA; ret = av_uuid_urn_parse(element_text, uuid); if (ret) ret = AVERROR_INVALIDDATA; @@ -88,7 +90,7 @@ int ff_imf_xml_read_rational(xmlNodePtr element, AVRational *rational) int ret = 0; xmlChar *element_text = xmlNodeListGetString(element->doc, element->xmlChildrenNode, 1); - if (sscanf(element_text, "%i %i", &rational->num, &rational->den) != 2) + if (element_text == NULL || sscanf(element_text, "%i %i", &rational->num, &rational->den) != 2) ret = AVERROR_INVALIDDATA; xmlFree(element_text); @@ -100,7 +102,7 @@ int ff_imf_xml_read_uint32(xmlNodePtr element, uint32_t *number) int ret = 0; xmlChar *element_text = xmlNodeListGetString(element->doc, element->xmlChildrenNode, 1); - if (sscanf(element_text, "%" PRIu32, number) != 1) + if (element_text == NULL || sscanf(element_text, "%" PRIu32, number) != 1) ret = AVERROR_INVALIDDATA; xmlFree(element_text); @@ -245,6 +247,8 @@ static int fill_timecode(xmlNodePtr cpl_element, FFIMFCPL *cpl) return AVERROR_INVALIDDATA; tc_str = xmlNodeListGetString(element->doc, element->xmlChildrenNode, 1); + if (!tc_str) + return AVERROR_INVALIDDATA; ret = parse_cpl_tc_type(tc_str, comps); xmlFree(tc_str); if (ret) From ac3e6b74bdd6959ce4411e78161b2f06d0926c43 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Sun, 23 Jul 2023 23:30:14 +0200 Subject: [PATCH 2025/2172] avformat/imf_cpl: Replace NULL content_title_utf8 by "" Suggested-by: Pierre-Anthony Lemieux Reviewed-by: Pierre-Anthony Lemieux Signed-off-by: Michael Niedermayer --- libavformat/imf_cpl.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/libavformat/imf_cpl.c b/libavformat/imf_cpl.c index 69155d786dd..5f1a67443f2 100644 --- a/libavformat/imf_cpl.c +++ b/libavformat/imf_cpl.c @@ -182,6 +182,10 @@ static int fill_content_title(xmlNodePtr cpl_element, FFIMFCPL *cpl) cpl->content_title_utf8 = xmlNodeListGetString(cpl_element->doc, element->xmlChildrenNode, 1); + if (!cpl->content_title_utf8) + cpl->content_title_utf8 = xmlStrdup(""); + if (!cpl->content_title_utf8) + return AVERROR(ENOMEM); return 0; } From 0ba719f726632d73592311615087a0d64aa2fb60 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Tue, 25 Jul 2023 02:13:10 +0200 Subject: [PATCH 2026/2172] avcodec/cbs_h2645: Avoid an unchecked bytesteram read The unchecked read caused the 2nd subsequent tell call to move backward resulting in a negative length Fixes: assertion failure Fixes: 60276/clusterfuzz-testcase-minimized-ffmpeg_BSF_TRACE_HEADERS_fuzzer-5434126636023808 Found-by: continuous fuzzing process https://github.com/google/oss-fuzz/tree/master/projects/ffmpeg Reviewed-by: James Almer Signed-off-by: Michael Niedermayer --- libavcodec/cbs_h2645.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavcodec/cbs_h2645.c b/libavcodec/cbs_h2645.c index 34c5d1d372f..21c8bc76d50 100644 --- a/libavcodec/cbs_h2645.c +++ b/libavcodec/cbs_h2645.c @@ -695,7 +695,7 @@ static int cbs_h2645_split_fragment(CodedBitstreamContext *ctx, int nal_unit_type = bytestream2_get_byte(&gbc) & 0x1f; unsigned int num_nalus = 1; if(nal_unit_type != VVC_DCI_NUT && nal_unit_type != VVC_OPI_NUT) - num_nalus = bytestream2_get_be16u(&gbc); + num_nalus = bytestream2_get_be16(&gbc); start = bytestream2_tell(&gbc); for(i = 0; i < num_nalus; i++) { From 33358b862c8b796362218f12555e351aaf35a8f4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Ekstr=C3=B6m?= Date: Tue, 11 Jul 2023 23:40:45 +0300 Subject: [PATCH 2027/2172] avcodec: move mastering display colour volume SEI handling to h2645_sei This allows this common H.274 SEI to be parsed from both H.264 as well as HEVC, as well as probably from VVC in the future. Generally attempts to keep the original code as similar as possible. FATE test refererence changes only change the order of side data export within a single frame. Nothing else seems to have changed. --- libavcodec/h2645_sei.c | 79 +++++++++++++++++++++++++ libavcodec/h2645_sei.h | 9 +++ libavcodec/h264_slice.c | 1 + libavcodec/hevc_sei.c | 31 ---------- libavcodec/hevc_sei.h | 9 --- libavcodec/hevcdec.c | 50 +--------------- tests/ref/fate/hevc-hdr-vivid-metadata | 16 ++--- tests/ref/fate/hevc-hdr10-plus-metadata | 10 ++-- 8 files changed, 105 insertions(+), 100 deletions(-) diff --git a/libavcodec/h2645_sei.c b/libavcodec/h2645_sei.c index 63ab711bc94..b1ec55d35b0 100644 --- a/libavcodec/h2645_sei.c +++ b/libavcodec/h2645_sei.c @@ -29,6 +29,7 @@ #include "libavutil/display.h" #include "libavutil/hdr_dynamic_metadata.h" #include "libavutil/film_grain_params.h" +#include "libavutil/mastering_display_metadata.h" #include "libavutil/pixdesc.h" #include "libavutil/stereo3d.h" @@ -392,6 +393,35 @@ static int decode_film_grain_characteristics(H2645SEIFilmGrainCharacteristics *h return 0; } +static int decode_nal_sei_mastering_display_info(H2645SEIMasteringDisplay *s, + GetByteContext *gb) +{ + int i; + + if (bytestream2_get_bytes_left(gb) < 24) + return AVERROR_INVALIDDATA; + + // Mastering primaries + for (i = 0; i < 3; i++) { + s->display_primaries[i][0] = bytestream2_get_be16u(gb); + s->display_primaries[i][1] = bytestream2_get_be16u(gb); + } + // White point (x, y) + s->white_point[0] = bytestream2_get_be16u(gb); + s->white_point[1] = bytestream2_get_be16u(gb); + + // Max and min luminance of mastering display + s->max_luminance = bytestream2_get_be32u(gb); + s->min_luminance = bytestream2_get_be32u(gb); + + // As this SEI message comes before the first frame that references it, + // initialize the flag to 2 and decrement on IRAP access unit so it + // persists for the coded video sequence (e.g., between two IRAPs) + s->present = 2; + + return 0; +} + int ff_h2645_sei_message_decode(H2645SEI *h, enum SEIType type, enum AVCodecID codec_id, GetBitContext *gb, GetByteContext *gbyte, void *logctx) @@ -412,6 +442,9 @@ int ff_h2645_sei_message_decode(H2645SEI *h, enum SEIType type, case SEI_TYPE_AMBIENT_VIEWING_ENVIRONMENT: return decode_ambient_viewing_environment(&h->ambient_viewing_environment, gbyte); + case SEI_TYPE_MASTERING_DISPLAY_COLOUR_VOLUME: + return decode_nal_sei_mastering_display_info(&h->mastering_display, + gbyte); default: return FF_H2645_SEI_MESSAGE_UNHANDLED; } @@ -652,6 +685,51 @@ int ff_h2645_sei_to_frame(AVFrame *frame, H2645SEI *sei, dst_env->ambient_light_y = av_make_q(env->ambient_light_y, 50000); } + if (sei->mastering_display.present) { + // HEVC uses a g,b,r ordering, which we convert to a more natural r,g,b + const int mapping[3] = {2, 0, 1}; + const int chroma_den = 50000; + const int luma_den = 10000; + int i; + AVMasteringDisplayMetadata *metadata = + av_mastering_display_metadata_create_side_data(frame); + if (!metadata) + return AVERROR(ENOMEM); + + for (i = 0; i < 3; i++) { + const int j = mapping[i]; + metadata->display_primaries[i][0].num = sei->mastering_display.display_primaries[j][0]; + metadata->display_primaries[i][0].den = chroma_den; + metadata->display_primaries[i][1].num = sei->mastering_display.display_primaries[j][1]; + metadata->display_primaries[i][1].den = chroma_den; + } + metadata->white_point[0].num = sei->mastering_display.white_point[0]; + metadata->white_point[0].den = chroma_den; + metadata->white_point[1].num = sei->mastering_display.white_point[1]; + metadata->white_point[1].den = chroma_den; + + metadata->max_luminance.num = sei->mastering_display.max_luminance; + metadata->max_luminance.den = luma_den; + metadata->min_luminance.num = sei->mastering_display.min_luminance; + metadata->min_luminance.den = luma_den; + metadata->has_luminance = 1; + metadata->has_primaries = 1; + + av_log(avctx, AV_LOG_DEBUG, "Mastering Display Metadata:\n"); + av_log(avctx, AV_LOG_DEBUG, + "r(%5.4f,%5.4f) g(%5.4f,%5.4f) b(%5.4f %5.4f) wp(%5.4f, %5.4f)\n", + av_q2d(metadata->display_primaries[0][0]), + av_q2d(metadata->display_primaries[0][1]), + av_q2d(metadata->display_primaries[1][0]), + av_q2d(metadata->display_primaries[1][1]), + av_q2d(metadata->display_primaries[2][0]), + av_q2d(metadata->display_primaries[2][1]), + av_q2d(metadata->white_point[0]), av_q2d(metadata->white_point[1])); + av_log(avctx, AV_LOG_DEBUG, + "min_luminance=%f, max_luminance=%f\n", + av_q2d(metadata->min_luminance), av_q2d(metadata->max_luminance)); + } + return 0; } @@ -667,4 +745,5 @@ void ff_h2645_sei_reset(H2645SEI *s) av_buffer_unref(&s->dynamic_hdr_vivid.info); s->ambient_viewing_environment.present = 0; + s->mastering_display.present = 0; } diff --git a/libavcodec/h2645_sei.h b/libavcodec/h2645_sei.h index e07ae103761..83e1b2ec16f 100644 --- a/libavcodec/h2645_sei.h +++ b/libavcodec/h2645_sei.h @@ -105,6 +105,14 @@ typedef struct H2645SEIFilmGrainCharacteristics { int persistence_flag; //< HEVC only } H2645SEIFilmGrainCharacteristics; +typedef struct H2645SEIMasteringDisplay { + int present; + uint16_t display_primaries[3][2]; + uint16_t white_point[2]; + uint32_t max_luminance; + uint32_t min_luminance; +} H2645SEIMasteringDisplay; + typedef struct H2645SEI { H2645SEIA53Caption a53_caption; H2645SEIAFD afd; @@ -116,6 +124,7 @@ typedef struct H2645SEI { H2645SEIAlternativeTransfer alternative_transfer; H2645SEIFilmGrainCharacteristics film_grain_characteristics; H2645SEIAmbientViewingEnvironment ambient_viewing_environment; + H2645SEIMasteringDisplay mastering_display; } H2645SEI; enum { diff --git a/libavcodec/h264_slice.c b/libavcodec/h264_slice.c index 41bf30eefca..586ce20bba0 100644 --- a/libavcodec/h264_slice.c +++ b/libavcodec/h264_slice.c @@ -439,6 +439,7 @@ int ff_h264_update_thread_context(AVCodecContext *dst, return ret; h->sei.common.unregistered.x264_build = h1->sei.common.unregistered.x264_build; + h->sei.common.mastering_display = h1->sei.common.mastering_display; if (!h->cur_pic_ptr) return 0; diff --git a/libavcodec/hevc_sei.c b/libavcodec/hevc_sei.c index 3c6bde1b62f..b7b77d4d0c2 100644 --- a/libavcodec/hevc_sei.c +++ b/libavcodec/hevc_sei.c @@ -49,35 +49,6 @@ static int decode_nal_sei_decoded_picture_hash(HEVCSEIPictureHash *s, return 0; } -static int decode_nal_sei_mastering_display_info(HEVCSEIMasteringDisplay *s, - GetByteContext *gb) -{ - int i; - - if (bytestream2_get_bytes_left(gb) < 24) - return AVERROR_INVALIDDATA; - - // Mastering primaries - for (i = 0; i < 3; i++) { - s->display_primaries[i][0] = bytestream2_get_be16u(gb); - s->display_primaries[i][1] = bytestream2_get_be16u(gb); - } - // White point (x, y) - s->white_point[0] = bytestream2_get_be16u(gb); - s->white_point[1] = bytestream2_get_be16u(gb); - - // Max and min luminance of mastering display - s->max_luminance = bytestream2_get_be32u(gb); - s->min_luminance = bytestream2_get_be32u(gb); - - // As this SEI message comes before the first frame that references it, - // initialize the flag to 2 and decrement on IRAP access unit so it - // persists for the coded video sequence (e.g., between two IRAPs) - s->present = 2; - - return 0; -} - static int decode_nal_sei_content_light_info(HEVCSEIContentLight *s, GetByteContext *gb) { @@ -206,8 +177,6 @@ static int decode_nal_sei_prefix(GetBitContext *gb, GetByteContext *gbyte, return decode_nal_sei_decoded_picture_hash(&s->picture_hash, gbyte); case SEI_TYPE_PIC_TIMING: return decode_nal_sei_pic_timing(s, gb, ps, logctx); - case SEI_TYPE_MASTERING_DISPLAY_COLOUR_VOLUME: - return decode_nal_sei_mastering_display_info(&s->mastering_display, gbyte); case SEI_TYPE_CONTENT_LIGHT_LEVEL_INFO: return decode_nal_sei_content_light_info(&s->content_light, gbyte); case SEI_TYPE_ACTIVE_PARAMETER_SETS: diff --git a/libavcodec/hevc_sei.h b/libavcodec/hevc_sei.h index 4189f5e6f74..077abdc74a9 100644 --- a/libavcodec/hevc_sei.h +++ b/libavcodec/hevc_sei.h @@ -53,14 +53,6 @@ typedef struct HEVCSEIPictureTiming { int picture_struct; } HEVCSEIPictureTiming; -typedef struct HEVCSEIMasteringDisplay { - int present; - uint16_t display_primaries[3][2]; - uint16_t white_point[2]; - uint32_t max_luminance; - uint32_t min_luminance; -} HEVCSEIMasteringDisplay; - typedef struct HEVCSEIContentLight { int present; uint16_t max_content_light_level; @@ -96,7 +88,6 @@ typedef struct HEVCSEI { H2645SEI common; HEVCSEIPictureHash picture_hash; HEVCSEIPictureTiming picture_timing; - HEVCSEIMasteringDisplay mastering_display; HEVCSEIContentLight content_light; int active_seq_parameter_set_id; HEVCSEITimeCode timecode; diff --git a/libavcodec/hevcdec.c b/libavcodec/hevcdec.c index fcf19b4eb6d..434750965b1 100644 --- a/libavcodec/hevcdec.c +++ b/libavcodec/hevcdec.c @@ -2763,53 +2763,9 @@ static int set_side_data(HEVCContext *s) // Decrement the mastering display flag when IRAP frame has no_rasl_output_flag=1 // so the side data persists for the entire coded video sequence. - if (s->sei.mastering_display.present > 0 && + if (s->sei.common.mastering_display.present > 0 && IS_IRAP(s) && s->no_rasl_output_flag) { - s->sei.mastering_display.present--; - } - if (s->sei.mastering_display.present) { - // HEVC uses a g,b,r ordering, which we convert to a more natural r,g,b - const int mapping[3] = {2, 0, 1}; - const int chroma_den = 50000; - const int luma_den = 10000; - int i; - AVMasteringDisplayMetadata *metadata = - av_mastering_display_metadata_create_side_data(out); - if (!metadata) - return AVERROR(ENOMEM); - - for (i = 0; i < 3; i++) { - const int j = mapping[i]; - metadata->display_primaries[i][0].num = s->sei.mastering_display.display_primaries[j][0]; - metadata->display_primaries[i][0].den = chroma_den; - metadata->display_primaries[i][1].num = s->sei.mastering_display.display_primaries[j][1]; - metadata->display_primaries[i][1].den = chroma_den; - } - metadata->white_point[0].num = s->sei.mastering_display.white_point[0]; - metadata->white_point[0].den = chroma_den; - metadata->white_point[1].num = s->sei.mastering_display.white_point[1]; - metadata->white_point[1].den = chroma_den; - - metadata->max_luminance.num = s->sei.mastering_display.max_luminance; - metadata->max_luminance.den = luma_den; - metadata->min_luminance.num = s->sei.mastering_display.min_luminance; - metadata->min_luminance.den = luma_den; - metadata->has_luminance = 1; - metadata->has_primaries = 1; - - av_log(s->avctx, AV_LOG_DEBUG, "Mastering Display Metadata:\n"); - av_log(s->avctx, AV_LOG_DEBUG, - "r(%5.4f,%5.4f) g(%5.4f,%5.4f) b(%5.4f %5.4f) wp(%5.4f, %5.4f)\n", - av_q2d(metadata->display_primaries[0][0]), - av_q2d(metadata->display_primaries[0][1]), - av_q2d(metadata->display_primaries[1][0]), - av_q2d(metadata->display_primaries[1][1]), - av_q2d(metadata->display_primaries[2][0]), - av_q2d(metadata->display_primaries[2][1]), - av_q2d(metadata->white_point[0]), av_q2d(metadata->white_point[1])); - av_log(s->avctx, AV_LOG_DEBUG, - "min_luminance=%f, max_luminance=%f\n", - av_q2d(metadata->min_luminance), av_q2d(metadata->max_luminance)); + s->sei.common.mastering_display.present--; } // Decrement the mastering display flag when IRAP frame has no_rasl_output_flag=1 // so the side data persists for the entire coded video sequence. @@ -3667,7 +3623,7 @@ static int hevc_update_thread_context(AVCodecContext *dst, s->sei.common.frame_packing = s0->sei.common.frame_packing; s->sei.common.display_orientation = s0->sei.common.display_orientation; s->sei.common.alternative_transfer = s0->sei.common.alternative_transfer; - s->sei.mastering_display = s0->sei.mastering_display; + s->sei.common.mastering_display = s0->sei.common.mastering_display; s->sei.content_light = s0->sei.content_light; ret = export_stream_params_from_sei(s); diff --git a/tests/ref/fate/hevc-hdr-vivid-metadata b/tests/ref/fate/hevc-hdr-vivid-metadata index 5f699730983..cb5db4557f7 100644 --- a/tests/ref/fate/hevc-hdr-vivid-metadata +++ b/tests/ref/fate/hevc-hdr-vivid-metadata @@ -1,5 +1,13 @@ [FRAME] [SIDE_DATA] +side_data_type=Content light level metadata +max_content=0 +max_average=0 +[/SIDE_DATA] +[SIDE_DATA] +side_data_type=H.26[45] User Data Unregistered SEI message +[/SIDE_DATA] +[SIDE_DATA] side_data_type=Mastering display metadata red_x=34000/50000 red_y=16000/50000 @@ -13,14 +21,6 @@ min_luminance=50/10000 max_luminance=40000000/10000 [/SIDE_DATA] [SIDE_DATA] -side_data_type=Content light level metadata -max_content=0 -max_average=0 -[/SIDE_DATA] -[SIDE_DATA] -side_data_type=H.26[45] User Data Unregistered SEI message -[/SIDE_DATA] -[SIDE_DATA] side_data_type=HDR Dynamic Metadata CUVA 005.1 2021 (Vivid) system_start_code=1 num_windows=1 diff --git a/tests/ref/fate/hevc-hdr10-plus-metadata b/tests/ref/fate/hevc-hdr10-plus-metadata index f226cd8c7bb..cdf308b96ab 100644 --- a/tests/ref/fate/hevc-hdr10-plus-metadata +++ b/tests/ref/fate/hevc-hdr10-plus-metadata @@ -1,5 +1,10 @@ [FRAME] [SIDE_DATA] +side_data_type=Content light level metadata +max_content=1000 +max_average=200 +[/SIDE_DATA] +[SIDE_DATA] side_data_type=Mastering display metadata red_x=13250/50000 red_y=34500/50000 @@ -13,11 +18,6 @@ min_luminance=50/10000 max_luminance=10000000/10000 [/SIDE_DATA] [SIDE_DATA] -side_data_type=Content light level metadata -max_content=1000 -max_average=200 -[/SIDE_DATA] -[SIDE_DATA] side_data_type=HDR Dynamic Metadata SMPTE2094-40 (HDR10+) application version=1 num_windows=1 From 43e63ff20a51e0296c446a9deec613df6fd52cb8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Ekstr=C3=B6m?= Date: Wed, 12 Jul 2023 19:57:13 +0300 Subject: [PATCH 2028/2172] avcodec: move content light level SEI handling to h2645_sei This allows this common H.274 SEI to be parsed from both H.264 as well as HEVC, as well as probably from VVC in the future. Generally attempts to keep the original code as similar as possible. FATE test refererence changes only change the order of side data export within a single frame. Nothing else seems to have changed. --- libavcodec/h2645_sei.c | 33 +++++++++++++++++++++++++ libavcodec/h2645_sei.h | 7 ++++++ libavcodec/h264_slice.c | 1 + libavcodec/hevc_sei.c | 19 -------------- libavcodec/hevc_sei.h | 7 ------ libavcodec/hevcdec.c | 19 +++----------- tests/ref/fate/hevc-hdr-vivid-metadata | 10 ++++---- tests/ref/fate/hevc-hdr10-plus-metadata | 10 ++++---- 8 files changed, 54 insertions(+), 52 deletions(-) diff --git a/libavcodec/h2645_sei.c b/libavcodec/h2645_sei.c index b1ec55d35b0..cb6be0594b4 100644 --- a/libavcodec/h2645_sei.c +++ b/libavcodec/h2645_sei.c @@ -422,6 +422,23 @@ static int decode_nal_sei_mastering_display_info(H2645SEIMasteringDisplay *s, return 0; } +static int decode_nal_sei_content_light_info(H2645SEIContentLight *s, + GetByteContext *gb) +{ + if (bytestream2_get_bytes_left(gb) < 4) + return AVERROR_INVALIDDATA; + + // Max and average light levels + s->max_content_light_level = bytestream2_get_be16u(gb); + s->max_pic_average_light_level = bytestream2_get_be16u(gb); + // As this SEI message comes before the first frame that references it, + // initialize the flag to 2 and decrement on IRAP access unit so it + // persists for the coded video sequence (e.g., between two IRAPs) + s->present = 2; + + return 0; +} + int ff_h2645_sei_message_decode(H2645SEI *h, enum SEIType type, enum AVCodecID codec_id, GetBitContext *gb, GetByteContext *gbyte, void *logctx) @@ -445,6 +462,8 @@ int ff_h2645_sei_message_decode(H2645SEI *h, enum SEIType type, case SEI_TYPE_MASTERING_DISPLAY_COLOUR_VOLUME: return decode_nal_sei_mastering_display_info(&h->mastering_display, gbyte); + case SEI_TYPE_CONTENT_LIGHT_LEVEL_INFO: + return decode_nal_sei_content_light_info(&h->content_light, gbyte); default: return FF_H2645_SEI_MESSAGE_UNHANDLED; } @@ -730,6 +749,19 @@ int ff_h2645_sei_to_frame(AVFrame *frame, H2645SEI *sei, av_q2d(metadata->min_luminance), av_q2d(metadata->max_luminance)); } + if (sei->content_light.present) { + AVContentLightMetadata *metadata = + av_content_light_metadata_create_side_data(frame); + if (!metadata) + return AVERROR(ENOMEM); + metadata->MaxCLL = sei->content_light.max_content_light_level; + metadata->MaxFALL = sei->content_light.max_pic_average_light_level; + + av_log(avctx, AV_LOG_DEBUG, "Content Light Level Metadata:\n"); + av_log(avctx, AV_LOG_DEBUG, "MaxCLL=%d, MaxFALL=%d\n", + metadata->MaxCLL, metadata->MaxFALL); + } + return 0; } @@ -746,4 +778,5 @@ void ff_h2645_sei_reset(H2645SEI *s) s->ambient_viewing_environment.present = 0; s->mastering_display.present = 0; + s->content_light.present = 0; } diff --git a/libavcodec/h2645_sei.h b/libavcodec/h2645_sei.h index 83e1b2ec16f..0ebf48011af 100644 --- a/libavcodec/h2645_sei.h +++ b/libavcodec/h2645_sei.h @@ -113,6 +113,12 @@ typedef struct H2645SEIMasteringDisplay { uint32_t min_luminance; } H2645SEIMasteringDisplay; +typedef struct H2645SEIContentLight { + int present; + uint16_t max_content_light_level; + uint16_t max_pic_average_light_level; +} H2645SEIContentLight; + typedef struct H2645SEI { H2645SEIA53Caption a53_caption; H2645SEIAFD afd; @@ -125,6 +131,7 @@ typedef struct H2645SEI { H2645SEIFilmGrainCharacteristics film_grain_characteristics; H2645SEIAmbientViewingEnvironment ambient_viewing_environment; H2645SEIMasteringDisplay mastering_display; + H2645SEIContentLight content_light; } H2645SEI; enum { diff --git a/libavcodec/h264_slice.c b/libavcodec/h264_slice.c index 586ce20bba0..e576bcb0703 100644 --- a/libavcodec/h264_slice.c +++ b/libavcodec/h264_slice.c @@ -440,6 +440,7 @@ int ff_h264_update_thread_context(AVCodecContext *dst, h->sei.common.unregistered.x264_build = h1->sei.common.unregistered.x264_build; h->sei.common.mastering_display = h1->sei.common.mastering_display; + h->sei.common.content_light = h1->sei.common.content_light; if (!h->cur_pic_ptr) return 0; diff --git a/libavcodec/hevc_sei.c b/libavcodec/hevc_sei.c index b7b77d4d0c2..351e699726f 100644 --- a/libavcodec/hevc_sei.c +++ b/libavcodec/hevc_sei.c @@ -49,23 +49,6 @@ static int decode_nal_sei_decoded_picture_hash(HEVCSEIPictureHash *s, return 0; } -static int decode_nal_sei_content_light_info(HEVCSEIContentLight *s, - GetByteContext *gb) -{ - if (bytestream2_get_bytes_left(gb) < 4) - return AVERROR_INVALIDDATA; - - // Max and average light levels - s->max_content_light_level = bytestream2_get_be16u(gb); - s->max_pic_average_light_level = bytestream2_get_be16u(gb); - // As this SEI message comes before the first frame that references it, - // initialize the flag to 2 and decrement on IRAP access unit so it - // persists for the coded video sequence (e.g., between two IRAPs) - s->present = 2; - - return 0; -} - static int decode_nal_sei_pic_timing(HEVCSEI *s, GetBitContext *gb, const HEVCParamSets *ps, void *logctx) { @@ -177,8 +160,6 @@ static int decode_nal_sei_prefix(GetBitContext *gb, GetByteContext *gbyte, return decode_nal_sei_decoded_picture_hash(&s->picture_hash, gbyte); case SEI_TYPE_PIC_TIMING: return decode_nal_sei_pic_timing(s, gb, ps, logctx); - case SEI_TYPE_CONTENT_LIGHT_LEVEL_INFO: - return decode_nal_sei_content_light_info(&s->content_light, gbyte); case SEI_TYPE_ACTIVE_PARAMETER_SETS: return decode_nal_sei_active_parameter_sets(s, gb, logctx); case SEI_TYPE_TIME_CODE: diff --git a/libavcodec/hevc_sei.h b/libavcodec/hevc_sei.h index 077abdc74a9..a23a64ec4f8 100644 --- a/libavcodec/hevc_sei.h +++ b/libavcodec/hevc_sei.h @@ -53,12 +53,6 @@ typedef struct HEVCSEIPictureTiming { int picture_struct; } HEVCSEIPictureTiming; -typedef struct HEVCSEIContentLight { - int present; - uint16_t max_content_light_level; - uint16_t max_pic_average_light_level; -} HEVCSEIContentLight; - typedef struct HEVCSEIAlternativeTransfer { int present; int preferred_transfer_characteristics; @@ -88,7 +82,6 @@ typedef struct HEVCSEI { H2645SEI common; HEVCSEIPictureHash picture_hash; HEVCSEIPictureTiming picture_timing; - HEVCSEIContentLight content_light; int active_seq_parameter_set_id; HEVCSEITimeCode timecode; } HEVCSEI; diff --git a/libavcodec/hevcdec.c b/libavcodec/hevcdec.c index 434750965b1..1fe91238d4a 100644 --- a/libavcodec/hevcdec.c +++ b/libavcodec/hevcdec.c @@ -31,7 +31,6 @@ #include "libavutil/display.h" #include "libavutil/film_grain_params.h" #include "libavutil/internal.h" -#include "libavutil/mastering_display_metadata.h" #include "libavutil/md5.h" #include "libavutil/opt.h" #include "libavutil/pixdesc.h" @@ -2769,21 +2768,9 @@ static int set_side_data(HEVCContext *s) } // Decrement the mastering display flag when IRAP frame has no_rasl_output_flag=1 // so the side data persists for the entire coded video sequence. - if (s->sei.content_light.present > 0 && + if (s->sei.common.content_light.present > 0 && IS_IRAP(s) && s->no_rasl_output_flag) { - s->sei.content_light.present--; - } - if (s->sei.content_light.present) { - AVContentLightMetadata *metadata = - av_content_light_metadata_create_side_data(out); - if (!metadata) - return AVERROR(ENOMEM); - metadata->MaxCLL = s->sei.content_light.max_content_light_level; - metadata->MaxFALL = s->sei.content_light.max_pic_average_light_level; - - av_log(s->avctx, AV_LOG_DEBUG, "Content Light Level Metadata:\n"); - av_log(s->avctx, AV_LOG_DEBUG, "MaxCLL=%d, MaxFALL=%d\n", - metadata->MaxCLL, metadata->MaxFALL); + s->sei.common.content_light.present--; } ret = ff_h2645_sei_to_frame(out, &s->sei.common, AV_CODEC_ID_HEVC, NULL, @@ -3624,7 +3611,7 @@ static int hevc_update_thread_context(AVCodecContext *dst, s->sei.common.display_orientation = s0->sei.common.display_orientation; s->sei.common.alternative_transfer = s0->sei.common.alternative_transfer; s->sei.common.mastering_display = s0->sei.common.mastering_display; - s->sei.content_light = s0->sei.content_light; + s->sei.common.content_light = s0->sei.common.content_light; ret = export_stream_params_from_sei(s); if (ret < 0) diff --git a/tests/ref/fate/hevc-hdr-vivid-metadata b/tests/ref/fate/hevc-hdr-vivid-metadata index cb5db4557f7..f3c777a852d 100644 --- a/tests/ref/fate/hevc-hdr-vivid-metadata +++ b/tests/ref/fate/hevc-hdr-vivid-metadata @@ -1,10 +1,5 @@ [FRAME] [SIDE_DATA] -side_data_type=Content light level metadata -max_content=0 -max_average=0 -[/SIDE_DATA] -[SIDE_DATA] side_data_type=H.26[45] User Data Unregistered SEI message [/SIDE_DATA] [SIDE_DATA] @@ -21,6 +16,11 @@ min_luminance=50/10000 max_luminance=40000000/10000 [/SIDE_DATA] [SIDE_DATA] +side_data_type=Content light level metadata +max_content=0 +max_average=0 +[/SIDE_DATA] +[SIDE_DATA] side_data_type=HDR Dynamic Metadata CUVA 005.1 2021 (Vivid) system_start_code=1 num_windows=1 diff --git a/tests/ref/fate/hevc-hdr10-plus-metadata b/tests/ref/fate/hevc-hdr10-plus-metadata index cdf308b96ab..f226cd8c7bb 100644 --- a/tests/ref/fate/hevc-hdr10-plus-metadata +++ b/tests/ref/fate/hevc-hdr10-plus-metadata @@ -1,10 +1,5 @@ [FRAME] [SIDE_DATA] -side_data_type=Content light level metadata -max_content=1000 -max_average=200 -[/SIDE_DATA] -[SIDE_DATA] side_data_type=Mastering display metadata red_x=13250/50000 red_y=34500/50000 @@ -18,6 +13,11 @@ min_luminance=50/10000 max_luminance=10000000/10000 [/SIDE_DATA] [SIDE_DATA] +side_data_type=Content light level metadata +max_content=1000 +max_average=200 +[/SIDE_DATA] +[SIDE_DATA] side_data_type=HDR Dynamic Metadata SMPTE2094-40 (HDR10+) application version=1 num_windows=1 From 91e1d11d1405f325f6f52e2c8dd5bbbf2462e190 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Ekstr=C3=B6m?= Date: Wed, 12 Jul 2023 21:15:10 +0300 Subject: [PATCH 2029/2172] avcodec/hevcdec: simplify decrementing of MDCV/CLL flags Mostly done to be able to update the comment so that it no longer mentions the same flag twice. --- libavcodec/hevcdec.c | 20 +++++++++----------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/libavcodec/hevcdec.c b/libavcodec/hevcdec.c index 1fe91238d4a..15276edd332 100644 --- a/libavcodec/hevcdec.c +++ b/libavcodec/hevcdec.c @@ -2760,17 +2760,15 @@ static int set_side_data(HEVCContext *s) AVFrame *out = s->ref->frame; int ret; - // Decrement the mastering display flag when IRAP frame has no_rasl_output_flag=1 - // so the side data persists for the entire coded video sequence. - if (s->sei.common.mastering_display.present > 0 && - IS_IRAP(s) && s->no_rasl_output_flag) { - s->sei.common.mastering_display.present--; - } - // Decrement the mastering display flag when IRAP frame has no_rasl_output_flag=1 - // so the side data persists for the entire coded video sequence. - if (s->sei.common.content_light.present > 0 && - IS_IRAP(s) && s->no_rasl_output_flag) { - s->sei.common.content_light.present--; + // Decrement the mastering display and content light level flag when IRAP + // frame has no_rasl_output_flag=1 so the side data persists for the entire + // coded video sequence. + if (IS_IRAP(s) && s->no_rasl_output_flag) { + if (s->sei.common.mastering_display.present > 0) + s->sei.common.mastering_display.present--; + + if (s->sei.common.content_light.present > 0) + s->sei.common.content_light.present--; } ret = ff_h2645_sei_to_frame(out, &s->sei.common, AV_CODEC_ID_HEVC, NULL, From 4fa1d3e7910c3fbe3aacbe5ae5233d0067569c02 Mon Sep 17 00:00:00 2001 From: Richard Acayan Date: Tue, 25 Jul 2023 17:38:39 -0400 Subject: [PATCH 2030/2172] avcodec/v4l2_context: suppress POLLERR and fix crash when buffers are uninitialized A POLLERR occurs when libavcodec attempts to dequeue output buffers before enqueuing capture buffers. This could happen to an application deciding to send the first coded packet. Suppress these POLLERRs when the buffers are uninitialized and avoid crashing because of enumerating uninitialized buffers. See https://trac.ffmpeg.org/ticket/9957 for the original bug report. Signed-off-by: Richard Acayan Signed-off-by: Marton Balint --- libavcodec/v4l2_context.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/libavcodec/v4l2_context.c b/libavcodec/v4l2_context.c index a40be946904..f20f713e1d5 100644 --- a/libavcodec/v4l2_context.c +++ b/libavcodec/v4l2_context.c @@ -325,9 +325,13 @@ static V4L2Buffer* v4l2_dequeue_v4l2buf(V4L2Context *ctx, int timeout) /* 0. handle errors */ if (pfd.revents & POLLERR) { - /* if we are trying to get free buffers but none have been queued yet - no need to raise a warning */ + /* if we are trying to get free buffers but none have been queued yet, + * or if no buffers have been allocated yet, no need to raise a warning + */ if (timeout == 0) { + if (!ctx->buffers) + return NULL; + for (i = 0; i < ctx->num_buffers; i++) { if (ctx->buffers[i].status != V4L2BUF_AVAILABLE) av_log(logger(ctx), AV_LOG_WARNING, "%s POLLERR\n", ctx->name); From f983303af4f53c9837fe8dddd39f20826651db17 Mon Sep 17 00:00:00 2001 From: Marton Balint Date: Sat, 22 Jul 2023 19:24:15 +0200 Subject: [PATCH 2031/2172] avcodec: fix misleading indentation warnings after ticks_per_frame deprecation Signed-off-by: Marton Balint --- libavcodec/libaomenc.c | 3 ++- libavcodec/libvpxenc.c | 3 ++- libavcodec/msmpeg4enc.c | 3 ++- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/libavcodec/libaomenc.c b/libavcodec/libaomenc.c index 16747e7e92f..f29cb0784a8 100644 --- a/libavcodec/libaomenc.c +++ b/libavcodec/libaomenc.c @@ -1299,7 +1299,7 @@ static int aom_encode(AVCodecContext *avctx, AVPacket *pkt, duration = frame->duration; else if (avctx->framerate.num > 0 && avctx->framerate.den > 0) duration = av_rescale_q(1, av_inv_q(avctx->framerate), avctx->time_base); - else + else { FF_DISABLE_DEPRECATION_WARNINGS duration = #if FF_API_TICKS_PER_FRAME @@ -1307,6 +1307,7 @@ FF_DISABLE_DEPRECATION_WARNINGS #endif 1; FF_ENABLE_DEPRECATION_WARNINGS + } switch (frame->color_range) { case AVCOL_RANGE_MPEG: diff --git a/libavcodec/libvpxenc.c b/libavcodec/libvpxenc.c index 549ac55aaae..7a545527a99 100644 --- a/libavcodec/libvpxenc.c +++ b/libavcodec/libvpxenc.c @@ -1830,7 +1830,7 @@ static int vpx_encode(AVCodecContext *avctx, AVPacket *pkt, duration = frame->duration; else if (avctx->framerate.num > 0 && avctx->framerate.den > 0) duration = av_rescale_q(1, av_inv_q(avctx->framerate), avctx->time_base); - else + else { FF_DISABLE_DEPRECATION_WARNINGS duration = #if FF_API_TICKS_PER_FRAME @@ -1838,6 +1838,7 @@ FF_DISABLE_DEPRECATION_WARNINGS #endif 1; FF_ENABLE_DEPRECATION_WARNINGS + } res = vpx_codec_encode(&ctx->encoder, rawimg, timestamp, duration, flags, ctx->deadline); diff --git a/libavcodec/msmpeg4enc.c b/libavcodec/msmpeg4enc.c index 9828901beaf..a8ddb8d8e1e 100644 --- a/libavcodec/msmpeg4enc.c +++ b/libavcodec/msmpeg4enc.c @@ -284,7 +284,7 @@ void ff_msmpeg4_encode_ext_header(MpegEncContext * s) if (s->avctx->framerate.num > 0 && s->avctx->framerate.den > 0) fps = s->avctx->framerate.num / s->avctx->framerate.den; - else + else { FF_DISABLE_DEPRECATION_WARNINGS fps = s->avctx->time_base.den / s->avctx->time_base.num #if FF_API_TICKS_PER_FRAME @@ -292,6 +292,7 @@ FF_DISABLE_DEPRECATION_WARNINGS #endif ; FF_ENABLE_DEPRECATION_WARNINGS + } put_bits(&s->pb, 5, FFMIN(fps, 31)); //yes 29.97 -> 29 From cf9cd35aa9d1db9d7b6b3e9207b47432fdb6fe5e Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Thu, 27 Jul 2023 00:14:15 +0200 Subject: [PATCH 2032/2172] avcodec/evc_ps: Check num_ref_pic_list_in_sps Fixes: out of array write Fixes: 60798/clusterfuzz-testcase-minimized-ffmpeg_BSF_EVC_FRAME_MERGE_fuzzer-4633529766772736 Found-by: continuous fuzzing process https://github.com/google/oss-fuzz/tree/master/projects/ffmpeg Reviewed-by: James Almer Signed-off-by: Michael Niedermayer --- libavcodec/evc.h | 2 +- libavcodec/evc_ps.c | 9 +++++++++ 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/libavcodec/evc.h b/libavcodec/evc.h index d1fdb4fac60..9711c760fef 100644 --- a/libavcodec/evc.h +++ b/libavcodec/evc.h @@ -126,7 +126,7 @@ enum { EVC_MAX_NUM_REF_PICS = 21, - EVC_MAX_NUM_RPLS = 32, + EVC_MAX_NUM_RPLS = 64, // A.4.1: pic_width_in_luma_samples and pic_height_in_luma_samples are // constrained to be not greater than sqrt(MaxLumaPs * 8). Hence height/ diff --git a/libavcodec/evc_ps.c b/libavcodec/evc_ps.c index 04ee6a45e6d..64384a392c2 100644 --- a/libavcodec/evc_ps.c +++ b/libavcodec/evc_ps.c @@ -243,11 +243,20 @@ int ff_evc_parse_sps(GetBitContext *gb, EVCParamSets *ps) sps->rpl1_same_as_rpl0_flag = get_bits1(gb); sps->num_ref_pic_list_in_sps[0] = get_ue_golomb(gb); + if ((unsigned)sps->num_ref_pic_list_in_sps[0] >= EVC_MAX_NUM_RPLS) { + ret = AVERROR_INVALIDDATA; + goto fail; + } + for (int i = 0; i < sps->num_ref_pic_list_in_sps[0]; ++i) ref_pic_list_struct(gb, &sps->rpls[0][i]); if (!sps->rpl1_same_as_rpl0_flag) { sps->num_ref_pic_list_in_sps[1] = get_ue_golomb(gb); + if ((unsigned)sps->num_ref_pic_list_in_sps[1] >= EVC_MAX_NUM_RPLS) { + ret = AVERROR_INVALIDDATA; + goto fail; + } for (int i = 0; i < sps->num_ref_pic_list_in_sps[1]; ++i) ref_pic_list_struct(gb, &sps->rpls[1][i]); } From 27804200ef15a4170167f23b5599541bacaff38e Mon Sep 17 00:00:00 2001 From: Benjamin Cheng Date: Thu, 27 Jul 2023 21:20:49 -0400 Subject: [PATCH 2033/2172] vulkan_hevc: use diagonal scan order for scaling lists The hevc parser parses the diagonal scan order in bitstream into raster scan order. However, the Vulkan spec wants it as specified in H265 spec, which is diagonal scan order. Tested on RADV. v2: fix copy-paste typo with PPS. --- libavcodec/vulkan_hevc.c | 82 ++++++++++++++++++++-------------------- 1 file changed, 40 insertions(+), 42 deletions(-) diff --git a/libavcodec/vulkan_hevc.c b/libavcodec/vulkan_hevc.c index ab0f6b96d0f..d56252399c2 100644 --- a/libavcodec/vulkan_hevc.c +++ b/libavcodec/vulkan_hevc.c @@ -17,6 +17,7 @@ */ #include "hevcdec.h" +#include "hevc_data.h" #include "hevc_ps.h" #include "vulkan_decode.h" @@ -205,6 +206,43 @@ static StdVideoH265LevelIdc convert_to_vk_level_idc(int level_idc) } } +static void copy_scaling_list(const ScalingList *sl, StdVideoH265ScalingLists *vksl) +{ + for (int i = 0; i < STD_VIDEO_H265_SCALING_LIST_4X4_NUM_LISTS; i++) { + for (int j = 0; j < STD_VIDEO_H265_SCALING_LIST_4X4_NUM_ELEMENTS; j++) { + uint8_t pos = 4 * ff_hevc_diag_scan4x4_y[j] + ff_hevc_diag_scan4x4_x[j]; + vksl->ScalingList4x4[i][j] = sl->sl[0][i][pos]; + } + } + + for (int i = 0; i < STD_VIDEO_H265_SCALING_LIST_8X8_NUM_LISTS; i++) { + for (int j = 0; j < STD_VIDEO_H265_SCALING_LIST_8X8_NUM_ELEMENTS; j++) { + uint8_t pos = 8 * ff_hevc_diag_scan8x8_y[j] + ff_hevc_diag_scan8x8_x[j]; + vksl->ScalingList8x8[i][j] = sl->sl[1][i][pos]; + } + } + + for (int i = 0; i < STD_VIDEO_H265_SCALING_LIST_16X16_NUM_LISTS; i++) { + for (int j = 0; j < STD_VIDEO_H265_SCALING_LIST_16X16_NUM_ELEMENTS; j++) { + uint8_t pos = 8 * ff_hevc_diag_scan8x8_y[j] + ff_hevc_diag_scan8x8_x[j]; + vksl->ScalingList16x16[i][j] = sl->sl[2][i][pos]; + } + } + + for (int i = 0; i < STD_VIDEO_H265_SCALING_LIST_32X32_NUM_LISTS; i++) { + for (int j = 0; j < STD_VIDEO_H265_SCALING_LIST_32X32_NUM_ELEMENTS; j++) { + uint8_t pos = 8 * ff_hevc_diag_scan8x8_y[j] + ff_hevc_diag_scan8x8_x[j]; + vksl->ScalingList32x32[i][j] = sl->sl[3][i * 3][pos]; + } + } + + memcpy(vksl->ScalingListDCCoef16x16, sl->sl_dc[0], + STD_VIDEO_H265_SCALING_LIST_16X16_NUM_LISTS * sizeof(*vksl->ScalingListDCCoef16x16)); + + for (int i = 0; i < STD_VIDEO_H265_SCALING_LIST_32X32_NUM_LISTS; i++) + vksl->ScalingListDCCoef32x32[i] = sl->sl_dc[1][i * 3]; +} + static void set_sps(const HEVCSPS *sps, int sps_idx, StdVideoH265ScalingLists *vksps_scaling, StdVideoH265HrdParameters *vksps_vui_header, @@ -218,27 +256,7 @@ static void set_sps(const HEVCSPS *sps, int sps_idx, StdVideoH265ShortTermRefPicSet *str, StdVideoH265LongTermRefPicsSps *ltr) { - for (int i = 0; i < STD_VIDEO_H265_SCALING_LIST_4X4_NUM_LISTS; i++) - memcpy(vksps_scaling->ScalingList4x4[i], sps->scaling_list.sl[0][i], - STD_VIDEO_H265_SCALING_LIST_4X4_NUM_ELEMENTS * sizeof(**vksps_scaling->ScalingList4x4)); - - for (int i = 0; i < STD_VIDEO_H265_SCALING_LIST_8X8_NUM_LISTS; i++) - memcpy(vksps_scaling->ScalingList8x8[i], sps->scaling_list.sl[1][i], - STD_VIDEO_H265_SCALING_LIST_8X8_NUM_ELEMENTS * sizeof(**vksps_scaling->ScalingList8x8)); - - for (int i = 0; i < STD_VIDEO_H265_SCALING_LIST_16X16_NUM_LISTS; i++) - memcpy(vksps_scaling->ScalingList16x16[i], sps->scaling_list.sl[2][i], - STD_VIDEO_H265_SCALING_LIST_16X16_NUM_ELEMENTS * sizeof(**vksps_scaling->ScalingList16x16)); - - for (int i = 0; i < STD_VIDEO_H265_SCALING_LIST_32X32_NUM_LISTS; i++) - memcpy(vksps_scaling->ScalingList32x32[i], sps->scaling_list.sl[3][i * 3], - STD_VIDEO_H265_SCALING_LIST_32X32_NUM_ELEMENTS * sizeof(**vksps_scaling->ScalingList32x32)); - - memcpy(vksps_scaling->ScalingListDCCoef16x16, sps->scaling_list.sl_dc[0], - STD_VIDEO_H265_SCALING_LIST_16X16_NUM_LISTS * sizeof(*vksps_scaling->ScalingListDCCoef16x16)); - - for (int i = 0; i < STD_VIDEO_H265_SCALING_LIST_32X32_NUM_LISTS; i++) - vksps_scaling->ScalingListDCCoef32x32[i] = sps->scaling_list.sl_dc[1][i * 3]; + copy_scaling_list(&sps->scaling_list, vksps_scaling); *vksps_vui_header = (StdVideoH265HrdParameters) { .flags = (StdVideoH265HrdFlags) { @@ -464,27 +482,7 @@ static void set_pps(const HEVCPPS *pps, const HEVCSPS *sps, StdVideoH265PictureParameterSet *vkpps, StdVideoH265PredictorPaletteEntries *pal) { - for (int i = 0; i < STD_VIDEO_H265_SCALING_LIST_4X4_NUM_LISTS; i++) - memcpy(vkpps_scaling->ScalingList4x4[i], pps->scaling_list.sl[0][i], - STD_VIDEO_H265_SCALING_LIST_4X4_NUM_ELEMENTS * sizeof(**vkpps_scaling->ScalingList4x4)); - - for (int i = 0; i < STD_VIDEO_H265_SCALING_LIST_8X8_NUM_LISTS; i++) - memcpy(vkpps_scaling->ScalingList8x8[i], pps->scaling_list.sl[1][i], - STD_VIDEO_H265_SCALING_LIST_8X8_NUM_ELEMENTS * sizeof(**vkpps_scaling->ScalingList8x8)); - - for (int i = 0; i < STD_VIDEO_H265_SCALING_LIST_16X16_NUM_LISTS; i++) - memcpy(vkpps_scaling->ScalingList16x16[i], pps->scaling_list.sl[2][i], - STD_VIDEO_H265_SCALING_LIST_16X16_NUM_ELEMENTS * sizeof(**vkpps_scaling->ScalingList16x16)); - - for (int i = 0; i < STD_VIDEO_H265_SCALING_LIST_32X32_NUM_LISTS; i++) - memcpy(vkpps_scaling->ScalingList32x32[i], pps->scaling_list.sl[3][i * 3], - STD_VIDEO_H265_SCALING_LIST_32X32_NUM_ELEMENTS * sizeof(**vkpps_scaling->ScalingList32x32)); - - memcpy(vkpps_scaling->ScalingListDCCoef16x16, pps->scaling_list.sl_dc[0], - STD_VIDEO_H265_SCALING_LIST_16X16_NUM_LISTS * sizeof(*vkpps_scaling->ScalingListDCCoef16x16)); - - for (int i = 0; i < STD_VIDEO_H265_SCALING_LIST_32X32_NUM_LISTS; i++) - vkpps_scaling->ScalingListDCCoef32x32[i] = sps->scaling_list.sl_dc[1][i * 3]; + copy_scaling_list(&pps->scaling_list, vkpps_scaling); *vkpps = (StdVideoH265PictureParameterSet) { .flags = (StdVideoH265PpsFlags) { From 830e522cdecb644f869b59f8e58aed2e2fd59ff6 Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Thu, 27 Jul 2023 13:03:39 +0200 Subject: [PATCH 2034/2172] avfilter/avf_showcwt: reduce memory usage even more --- libavfilter/avf_showcwt.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/libavfilter/avf_showcwt.c b/libavfilter/avf_showcwt.c index 8badfbd34e8..8278623d4b5 100644 --- a/libavfilter/avf_showcwt.c +++ b/libavfilter/avf_showcwt.c @@ -578,6 +578,8 @@ static int run_channel_cwt(AVFilterContext *ctx, void *arg, int jobnr, int nb_jo ShowCWTContext *s = ctx->priv; const int ch = *(int *)arg; const AVComplexFloat *fft_out = (const AVComplexFloat *)s->fft_out->extended_data[ch]; + AVComplexFloat *isrc = (AVComplexFloat *)s->ifft_in->extended_data[jobnr]; + AVComplexFloat *idst = (AVComplexFloat *)s->ifft_out->extended_data[jobnr]; const int output_padding_size = s->output_padding_size; const int ihop_size = s->ihop_size; const int ioffset = (output_padding_size - ihop_size) >> 1; @@ -586,8 +588,6 @@ static int run_channel_cwt(AVFilterContext *ctx, void *arg, int jobnr, int nb_jo const int end = (count * (jobnr+1)) / nb_jobs; for (int y = start; y < end; y++) { - AVComplexFloat *isrc = (AVComplexFloat *)s->ifft_in->extended_data[y]; - AVComplexFloat *idst = (AVComplexFloat *)s->ifft_out->extended_data[y]; AVComplexFloat *chout = ((AVComplexFloat *)s->ch_out->extended_data[ch]) + y * ihop_size; AVComplexFloat *dstx = (AVComplexFloat *)s->dst_x->extended_data[jobnr]; AVComplexFloat *srcx = (AVComplexFloat *)s->src_x->extended_data[jobnr]; @@ -803,14 +803,14 @@ static int config_output(AVFilterLink *outlink) s->ifft_in->format = inlink->format; s->ifft_in->nb_samples = s->ifft_in_size * 2; - s->ifft_in->ch_layout.nb_channels = s->frequency_band_count; + s->ifft_in->ch_layout.nb_channels = s->nb_threads; ret = av_frame_get_buffer(s->ifft_in, 0); if (ret < 0) return ret; s->ifft_out->format = inlink->format; s->ifft_out->nb_samples = s->ifft_out_size * 2; - s->ifft_out->ch_layout.nb_channels = s->frequency_band_count; + s->ifft_out->ch_layout.nb_channels = s->nb_threads; ret = av_frame_get_buffer(s->ifft_out, 0); if (ret < 0) return ret; From 32a2268b6ead00a9f649ac31abf096067dfd2b9d Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Thu, 27 Jul 2023 14:36:13 +0200 Subject: [PATCH 2035/2172] avfilter/avf_showcwt: switch to overlap-save And do both left and right zero-padding for forward FFT. --- libavfilter/avf_showcwt.c | 55 +++++++++++++++++++++++---------------- 1 file changed, 33 insertions(+), 22 deletions(-) diff --git a/libavfilter/avf_showcwt.c b/libavfilter/avf_showcwt.c index 8278623d4b5..49c02035393 100644 --- a/libavfilter/avf_showcwt.c +++ b/libavfilter/avf_showcwt.c @@ -90,6 +90,7 @@ typedef struct ShowCWTContext { AVFrame *ifft_in; AVFrame *ifft_out; AVFrame *ch_out; + AVFrame *over; AVFrame *bh_out; int nb_threads; int nb_channels; @@ -177,6 +178,7 @@ static av_cold void uninit(AVFilterContext *ctx) av_frame_free(&s->ifft_in); av_frame_free(&s->ifft_out); av_frame_free(&s->ch_out); + av_frame_free(&s->over); av_frame_free(&s->bh_out); if (s->fft) { @@ -290,25 +292,27 @@ static int run_channel_cwt_prepare(AVFilterContext *ctx, void *arg, int jobnr, i ShowCWTContext *s = ctx->priv; const int hop_size = s->hop_size; AVFrame *fin = arg; - AVComplexFloat *cache = (AVComplexFloat *)s->cache->extended_data[ch]; + float *cache = (float *)s->cache->extended_data[ch]; AVComplexFloat *src = (AVComplexFloat *)s->fft_in->extended_data[ch]; AVComplexFloat *dst = (AVComplexFloat *)s->fft_out->extended_data[ch]; + const int offset = (s->input_padding_size - hop_size) >> 1; if (fin) { const float *input = (const float *)fin->extended_data[ch]; - const int offset = s->input_padding_size - fin->nb_samples; + const int offset = s->hop_size - fin->nb_samples; - memmove(cache, cache + fin->nb_samples, sizeof(*cache) * offset); - for (int n = 0; n < fin->nb_samples; n++) { - cache[offset + n].re = input[n]; - cache[offset + n].im = 0.f; - } + memmove(cache, &cache[fin->nb_samples], offset * sizeof(float)); + memcpy(&cache[offset], input, fin->nb_samples * sizeof(float)); } if (fin && s->hop_index + fin->nb_samples < hop_size) return 0; - memcpy(src, cache, sizeof(*src) * s->input_padding_size); + memset(src, 0, sizeof(float) * s->fft_in_size); + for (int n = 0; n < hop_size; n++) { + src[n+offset].re = cache[n]; + src[n+offset].im = 0.f; + } s->tx_fn(s->fft[jobnr], dst, src, sizeof(*src)); @@ -582,20 +586,20 @@ static int run_channel_cwt(AVFilterContext *ctx, void *arg, int jobnr, int nb_jo AVComplexFloat *idst = (AVComplexFloat *)s->ifft_out->extended_data[jobnr]; const int output_padding_size = s->output_padding_size; const int ihop_size = s->ihop_size; - const int ioffset = (output_padding_size - ihop_size) >> 1; const int count = s->frequency_band_count; const int start = (count * jobnr) / nb_jobs; const int end = (count * (jobnr+1)) / nb_jobs; for (int y = start; y < end; y++) { AVComplexFloat *chout = ((AVComplexFloat *)s->ch_out->extended_data[ch]) + y * ihop_size; + AVComplexFloat *over = ((AVComplexFloat *)s->over->extended_data[ch]) + y * ihop_size; AVComplexFloat *dstx = (AVComplexFloat *)s->dst_x->extended_data[jobnr]; AVComplexFloat *srcx = (AVComplexFloat *)s->src_x->extended_data[jobnr]; const AVComplexFloat *kernel = s->kernel[y]; const unsigned *index = (const unsigned *)s->index; const int kernel_start = s->kernel_start[y]; const int kernel_stop = s->kernel_stop[y]; - const int kernel_range = kernel_stop - kernel_start; + const int kernel_range = kernel_stop - kernel_start + 1; memcpy(srcx, fft_out + kernel_start, sizeof(*fft_out) * kernel_range); @@ -612,7 +616,12 @@ static int run_channel_cwt(AVFilterContext *ctx, void *arg, int jobnr, int nb_jo s->itx_fn(s->ifft[jobnr], idst, isrc, sizeof(*isrc)); - memcpy(chout, idst + ioffset, sizeof(*chout) * ihop_size); + memcpy(chout, idst, sizeof(*chout) * ihop_size); + for (int n = 0; n < ihop_size; n++) { + chout[n].re += over[n].re; + chout[n].im += over[n].im; + } + memcpy(over, idst + ihop_size, sizeof(*over) * ihop_size); } return 0; @@ -742,12 +751,12 @@ static int config_output(AVFilterLink *outlink) s->eof_pts = AV_NOPTS_VALUE; s->nb_consumed_samples = FFMIN(65536, inlink->sample_rate); - s->input_sample_count = s->nb_consumed_samples; + s->input_sample_count = 1 << (32 - ff_clz(s->nb_consumed_samples)); s->input_padding_size = 1 << (32 - ff_clz(s->input_sample_count)); s->output_sample_count = FFMAX(1, av_rescale(s->input_sample_count, s->pps, inlink->sample_rate)); s->output_padding_size = 1 << (32 - ff_clz(s->output_sample_count)); - s->hop_size = s->input_padding_size >> 1; + s->hop_size = s->input_sample_count; s->ihop_size = s->output_padding_size >> 1; outlink->w = s->w; @@ -757,7 +766,7 @@ static int config_output(AVFilterLink *outlink) s->fft_in_size = FFALIGN(s->input_padding_size, av_cpu_max_align()); s->fft_out_size = FFALIGN(s->input_padding_size, av_cpu_max_align()); - s->ifft_in_size = FFALIGN(s->output_padding_size, av_cpu_max_align()); + s->ifft_in_size = FFALIGN(s->output_padding_size, av_cpu_max_align()); s->ifft_out_size = FFALIGN(s->output_padding_size, av_cpu_max_align()); s->fft = av_calloc(s->nb_threads, sizeof(*s->fft)); @@ -788,15 +797,16 @@ static int config_output(AVFilterLink *outlink) s->dst_x = av_frame_alloc(); s->src_x = av_frame_alloc(); s->kernel = av_calloc(s->frequency_band_count, sizeof(*s->kernel)); - s->cache = ff_get_audio_buffer(inlink, s->fft_in_size * 2); + s->cache = ff_get_audio_buffer(inlink, s->hop_size); s->ch_out = ff_get_audio_buffer(inlink, s->frequency_band_count * 2 * s->ihop_size); + s->over = ff_get_audio_buffer(inlink, s->frequency_band_count * 2 * s->ihop_size); s->bh_out = ff_get_audio_buffer(inlink, s->frequency_band_count); s->ifft_in = av_frame_alloc(); s->ifft_out = av_frame_alloc(); s->index = av_calloc(s->input_padding_size, sizeof(*s->index)); s->kernel_start = av_calloc(s->frequency_band_count, sizeof(*s->kernel_start)); s->kernel_stop = av_calloc(s->frequency_band_count, sizeof(*s->kernel_stop)); - if (!s->outpicref || !s->fft_in || !s->fft_out || !s->src_x || !s->dst_x || + if (!s->outpicref || !s->fft_in || !s->fft_out || !s->src_x || !s->dst_x || !s->over || !s->ifft_in || !s->ifft_out || !s->kernel_start || !s->kernel_stop || !s->ch_out || !s->frequency_band || !s->cache || !s->index || !s->bh_out || !s->kernel) return AVERROR(ENOMEM); @@ -880,6 +890,9 @@ static int config_output(AVFilterLink *outlink) s->frequency_band_count, maximum_frequency - minimum_frequency, minimum_frequency, s->frequency_scale, s->deviation); + av_log(ctx, AV_LOG_DEBUG, "factor: %f\n", factor); + av_log(ctx, AV_LOG_DEBUG, "hop_size: %d\n", s->hop_size); + av_log(ctx, AV_LOG_DEBUG, "ihop_size: %d\n", s->ihop_size); av_log(ctx, AV_LOG_DEBUG, "input_sample_count: %d\n", s->input_sample_count); av_log(ctx, AV_LOG_DEBUG, "input_padding_size: %d\n", s->input_padding_size); av_log(ctx, AV_LOG_DEBUG, "output_sample_count: %d\n", s->output_sample_count); @@ -1065,15 +1078,16 @@ static int output_frame(AVFilterContext *ctx) if (s->slide != SLIDE_FRAME || s->new_frame == 1) { int64_t pts_offset = s->new_frame ? 0LL : av_rescale(s->ihop_index, s->hop_size, s->ihop_size); + const int offset = (s->input_padding_size - s->hop_size) >> 1; - pts_offset = av_rescale_q(pts_offset - s->input_sample_count/2, av_make_q(1, inlink->sample_rate), inlink->time_base); + pts_offset = av_rescale_q(pts_offset - offset, av_make_q(1, inlink->sample_rate), inlink->time_base); s->outpicref->pts = av_rescale_q(s->in_pts + pts_offset, inlink->time_base, outlink->time_base); s->outpicref->duration = 1; } s->ihop_index++; if (s->ihop_index >= s->ihop_size) - s->ihop_index = 0; + s->ihop_index = s->hop_index = 0; if (s->slide == SLIDE_FRAME && s->new_frame == 0) return 1; @@ -1127,7 +1141,7 @@ static int activate(AVFilterContext *ctx) if (s->outpicref) { AVFrame *fin = NULL; - if (s->ihop_index == 0) { + if (s->hop_index < s->hop_size) { if (!s->eof) { ret = ff_inlink_consume_samples(inlink, 1, s->hop_size - s->hop_index, &fin); if (ret < 0) @@ -1149,9 +1163,6 @@ static int activate(AVFilterContext *ctx) } if (s->hop_index >= s->hop_size || s->ihop_index > 0) { - if (s->hop_index) - s->hop_index = 0; - for (int ch = 0; ch < s->nb_channels && s->ihop_index == 0; ch++) { ff_filter_execute(ctx, run_channel_cwt, (void *)&ch, NULL, s->nb_threads); From a7a46aff463ca88ea719dc51a99a334b1aaae145 Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Fri, 28 Jul 2023 13:15:00 +0200 Subject: [PATCH 2036/2172] avfilter/avf_showcwt: remove excessive operations --- libavfilter/avf_showcwt.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/libavfilter/avf_showcwt.c b/libavfilter/avf_showcwt.c index 49c02035393..1451bfb1e0c 100644 --- a/libavfilter/avf_showcwt.c +++ b/libavfilter/avf_showcwt.c @@ -280,9 +280,7 @@ static void frequency_band(float *frequency_band, static float remap_log(float value, float log_factor) { - float sign = (0 < value) - (value < 0); - - value = logf(value * sign) * log_factor; + value = logf(value) * log_factor; return 1.f - av_clipf(value, 0.f, 1.f); } From e8777221f27401b8540e9a41aea4f6e55263fc65 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Wed, 26 Jul 2023 17:31:38 +0200 Subject: [PATCH 2037/2172] fftools/ffprobe: fix handling parse_options() return value Reviewed-by: James Almer Reviewed-by: Marton Balint Signed-off-by: James Almer --- fftools/ffprobe.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fftools/ffprobe.c b/fftools/ffprobe.c index a39185f6fed..81610c097b9 100644 --- a/fftools/ffprobe.c +++ b/fftools/ffprobe.c @@ -4113,7 +4113,7 @@ int main(int argc, char **argv) show_banner(argc, argv, options); ret = parse_options(NULL, argc, argv, options, opt_input_file); if (ret < 0) { - ret = AVERROR_EXIT ? 0 : ret; + ret = (ret == AVERROR_EXIT) ? 0 : ret; goto end; } From 7de3fcb059376f50268aa1d0e7b9f98a440c1529 Mon Sep 17 00:00:00 2001 From: Sebastian Ramacher Date: Sun, 16 Apr 2023 13:39:27 +0200 Subject: [PATCH 2038/2172] examples: fix build of mux and resample_audio The commits eac4324bfbe452f0292b48b2f1dc37b5052ec0be and cd8211527efbb9cad19db1c0d033da0749836e43 renamed the examples, but the targets were not updated. Hence, the builds are missing -lm. Signed-off-by: Sebastian Ramacher Signed-off-by: James Almer --- doc/examples/Makefile.example | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/examples/Makefile.example b/doc/examples/Makefile.example index 01712f42d94..dee9ebf2f0b 100644 --- a/doc/examples/Makefile.example +++ b/doc/examples/Makefile.example @@ -43,8 +43,8 @@ OBJS=$(addsuffix .o,$(EXAMPLES)) # the following examples make explicit use of the math library avcodec: LDLIBS += -lm encode_audio: LDLIBS += -lm -muxing: LDLIBS += -lm -resampling_audio: LDLIBS += -lm +mux: LDLIBS += -lm +resample_audio: LDLIBS += -lm .phony: all clean-test clean From b300552dfb525990e28eeef14edb67ef5ceacb65 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Ekstr=C3=B6m?= Date: Fri, 21 Apr 2023 16:07:08 +0300 Subject: [PATCH 2039/2172] avformat/mov: enable identifying TTML subtitle streams as such MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The contents are full TTML XML documents. TTML writing tests' results are updated as the streams are now properly identified as TTML ones. Signed-off-by: Jan Ekström --- libavformat/mov.c | 11 +++++++++-- tests/ref/fate/mov-mp4-ttml-dfxp | 9 +++++---- tests/ref/fate/mov-mp4-ttml-stpp | 10 ++++++---- 3 files changed, 20 insertions(+), 10 deletions(-) diff --git a/libavformat/mov.c b/libavformat/mov.c index ac19b3157aa..be9975f297e 100644 --- a/libavformat/mov.c +++ b/libavformat/mov.c @@ -2263,6 +2263,11 @@ static int mov_codec_id(AVStream *st, uint32_t format) (st->codecpar->codec_type == AVMEDIA_TYPE_SUBTITLE && st->codecpar->codec_id == AV_CODEC_ID_NONE)) { id = ff_codec_get_id(ff_codec_movsubtitle_tags, format); + if (id <= 0) { + id = (format == MOV_MP4_TTML_TAG || format == MOV_ISMV_TTML_TAG) ? + AV_CODEC_ID_TTML : id; + } + if (id > 0) st->codecpar->codec_type = AVMEDIA_TYPE_SUBTITLE; else @@ -2457,8 +2462,10 @@ static void mov_parse_stsd_subtitle(MOVContext *c, AVIOContext *pb, // ttxt stsd contains display flags, justification, background // color, fonts, and default styles, so fake an atom to read it MOVAtom fake_atom = { .size = size }; - // mp4s contains a regular esds atom - if (st->codecpar->codec_tag != AV_RL32("mp4s")) + // mp4s contains a regular esds atom, dfxp ISMV TTML has no content + // in extradata unlike stpp MP4 TTML. + if (st->codecpar->codec_tag != AV_RL32("mp4s") && + st->codecpar->codec_tag != MOV_ISMV_TTML_TAG) mov_read_glbl(c, pb, fake_atom); st->codecpar->width = sc->width; st->codecpar->height = sc->height; diff --git a/tests/ref/fate/mov-mp4-ttml-dfxp b/tests/ref/fate/mov-mp4-ttml-dfxp index 15f4f9b69bd..2d60f3d9641 100644 --- a/tests/ref/fate/mov-mp4-ttml-dfxp +++ b/tests/ref/fate/mov-mp4-ttml-dfxp @@ -1,13 +1,13 @@ 2e7e01c821c111466e7a2844826b7f6d *tests/data/fate/mov-mp4-ttml-dfxp.mp4 8519 tests/data/fate/mov-mp4-ttml-dfxp.mp4 #tb 0: 1/1000 -#media_type 0: data -#codec_id 0: none +#media_type 0: subtitle +#codec_id 0: ttml 0, 0, 0, 68500, 7866, 0x456c36b7 { "packets": [ { - "codec_type": "data", + "codec_type": "subtitle", "stream_index": 0, "pts": 0, "pts_time": "0.000000", @@ -26,7 +26,8 @@ "streams": [ { "index": 0, - "codec_type": "data", + "codec_name": "ttml", + "codec_type": "subtitle", "codec_tag_string": "dfxp", "codec_tag": "0x70786664", "time_base": "1/1000", diff --git a/tests/ref/fate/mov-mp4-ttml-stpp b/tests/ref/fate/mov-mp4-ttml-stpp index 7726cd332e2..0a8e423449b 100644 --- a/tests/ref/fate/mov-mp4-ttml-stpp +++ b/tests/ref/fate/mov-mp4-ttml-stpp @@ -1,13 +1,14 @@ cbd2c7ff864a663b0d893deac5a0caec *tests/data/fate/mov-mp4-ttml-stpp.mp4 8547 tests/data/fate/mov-mp4-ttml-stpp.mp4 +#extradata 0: 48, 0x62100c0d #tb 0: 1/1000 -#media_type 0: data -#codec_id 0: none +#media_type 0: subtitle +#codec_id 0: ttml 0, 0, 0, 68500, 7866, 0x456c36b7 { "packets": [ { - "codec_type": "data", + "codec_type": "subtitle", "stream_index": 0, "pts": 0, "pts_time": "0.000000", @@ -26,7 +27,8 @@ cbd2c7ff864a663b0d893deac5a0caec *tests/data/fate/mov-mp4-ttml-stpp.mp4 "streams": [ { "index": 0, - "codec_type": "data", + "codec_name": "ttml", + "codec_type": "subtitle", "codec_tag_string": "stpp", "codec_tag": "0x70707473", "time_base": "1/1000", From dca54600f0672f8f54cb61188a0bd35e7b4a53f2 Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Fri, 28 Jul 2023 21:13:05 +0200 Subject: [PATCH 2040/2172] avfilter/avf_showcwt: keep kernels precision as high as possible --- libavfilter/avf_showcwt.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/libavfilter/avf_showcwt.c b/libavfilter/avf_showcwt.c index 1451bfb1e0c..1bf874c97be 100644 --- a/libavfilter/avf_showcwt.c +++ b/libavfilter/avf_showcwt.c @@ -583,6 +583,7 @@ static int run_channel_cwt(AVFilterContext *ctx, void *arg, int jobnr, int nb_jo AVComplexFloat *isrc = (AVComplexFloat *)s->ifft_in->extended_data[jobnr]; AVComplexFloat *idst = (AVComplexFloat *)s->ifft_out->extended_data[jobnr]; const int output_padding_size = s->output_padding_size; + const float scale = 1.f / s->input_padding_size; const int ihop_size = s->ihop_size; const int count = s->frequency_band_count; const int start = (count * jobnr) / nb_jobs; @@ -601,6 +602,7 @@ static int run_channel_cwt(AVFilterContext *ctx, void *arg, int jobnr, int nb_jo memcpy(srcx, fft_out + kernel_start, sizeof(*fft_out) * kernel_range); + s->fdsp->vector_fmul_scalar((float *)srcx, (const float *)srcx, scale, FFALIGN(kernel_range * 2, 4)); s->fdsp->vector_fmul((float *)dstx, (const float *)srcx, (const float *)kernel, FFALIGN(kernel_range * 2, 16)); @@ -630,7 +632,6 @@ static int compute_kernel(AVFilterContext *ctx) ShowCWTContext *s = ctx->priv; const float correction = s->input_padding_size / (float)s->input_sample_count; const int size = s->input_sample_count; - const float scale_factor = 1.f/(float)size; const int output_sample_count = s->output_sample_count; const int fsize = s->frequency_band_count; int *kernel_start = s->kernel_start; @@ -655,7 +656,7 @@ static int compute_kernel(AVFilterContext *ctx) for (int n = 0; n < size; n++) { float ff, f = fabsf(n-frequency); - ff = expf(-f*f*deviation) * scale_factor; + ff = expf(-f*f*deviation); tkernel[n] = ff; } From 7d6dd90f3aa89601700c443910c7d1fff306e1c3 Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Fri, 28 Jul 2023 22:25:22 +0200 Subject: [PATCH 2041/2172] avfilter/avf_showcwt: unbreak highest frequencies The kernel was truncated too much. --- libavfilter/avf_showcwt.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavfilter/avf_showcwt.c b/libavfilter/avf_showcwt.c index 1bf874c97be..7a8c108906d 100644 --- a/libavfilter/avf_showcwt.c +++ b/libavfilter/avf_showcwt.c @@ -631,7 +631,7 @@ static int compute_kernel(AVFilterContext *ctx) { ShowCWTContext *s = ctx->priv; const float correction = s->input_padding_size / (float)s->input_sample_count; - const int size = s->input_sample_count; + const int size = s->input_padding_size; const int output_sample_count = s->output_sample_count; const int fsize = s->frequency_band_count; int *kernel_start = s->kernel_start; From 8c67e134738037f3d5176c9370ce446b82d3709e Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Fri, 28 Jul 2023 22:26:57 +0200 Subject: [PATCH 2042/2172] avfilter/avf_showcwt: remove not needed fabsf() --- libavfilter/avf_showcwt.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavfilter/avf_showcwt.c b/libavfilter/avf_showcwt.c index 7a8c108906d..4aa008ca2ef 100644 --- a/libavfilter/avf_showcwt.c +++ b/libavfilter/avf_showcwt.c @@ -654,7 +654,7 @@ static int compute_kernel(AVFilterContext *ctx) memset(tkernel, 0, size * sizeof(*tkernel)); for (int n = 0; n < size; n++) { - float ff, f = fabsf(n-frequency); + float ff, f = n-frequency; ff = expf(-f*f*deviation); tkernel[n] = ff; From 096563c1086db8e8ebbb980ef65846b21d1fa010 Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt Date: Mon, 24 Jul 2023 17:33:04 +0200 Subject: [PATCH 2043/2172] avcodec/Makefile: Unconditionally skip vulkan_video_codec_av1std.h libavcodec/vulkan_video_codec_av1std.h currently does not pass checkheaders: It is missing stdint.h and vulkan/vulkan_core.h. The comment "This header is NOT YET generated from the Khronos Vulkan XML API Registry." as well as the fact that it does not use our standard inclusion guards makes the file appear as if it is to be treated like a third-party header and not one of our own. This commit therefore "fixes" the issue by unconditionally skipping said header. Reviewed-by: Lynne Signed-off-by: Andreas Rheinhardt --- libavcodec/Makefile | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libavcodec/Makefile b/libavcodec/Makefile index 1b0226c089e..3c16b514622 100644 --- a/libavcodec/Makefile +++ b/libavcodec/Makefile @@ -1283,6 +1283,7 @@ SKIPHEADERS += %_tablegen.h \ aacenc_quantization.h \ aacenc_quantization_misc.h \ bitstream_template.h \ + vulkan_video_codec_av1std.h \ $(ARCH)/vpx_arith.h \ SKIPHEADERS-$(CONFIG_AMF) += amfenc.h @@ -1304,7 +1305,7 @@ SKIPHEADERS-$(CONFIG_XVMC) += xvmc.h SKIPHEADERS-$(CONFIG_VAAPI) += vaapi_decode.h vaapi_hevc.h vaapi_encode.h SKIPHEADERS-$(CONFIG_VDPAU) += vdpau.h vdpau_internal.h SKIPHEADERS-$(CONFIG_VIDEOTOOLBOX) += videotoolbox.h vt_internal.h -SKIPHEADERS-$(CONFIG_VULKAN) += vulkan.h vulkan_video.h vulkan_decode.h vulkan_video_codec_av1std.h vulkan_video_codec_av1std_decode.h +SKIPHEADERS-$(CONFIG_VULKAN) += vulkan.h vulkan_video.h vulkan_decode.h vulkan_video_codec_av1std_decode.h SKIPHEADERS-$(CONFIG_V4L2_M2M) += v4l2_buffers.h v4l2_context.h v4l2_m2m.h SKIPHEADERS-$(CONFIG_ZLIB) += zlib_wrapper.h From 8387241975c5ac8c2da1cecf9ff2dfae3fabc844 Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt Date: Mon, 24 Jul 2023 14:41:24 +0200 Subject: [PATCH 2044/2172] avcodec/dct: Move fdct function declarations to fdctdsp.h It is the more proper place for them given that this is the only API using them. Also use a forward-declaration of AVCodecContext in fdctdsp.h to avoid including avcodec.h in jfdct(fst|int).c. Signed-off-by: Andreas Rheinhardt --- libavcodec/asvenc.c | 1 - libavcodec/dct.h | 7 ------- libavcodec/fdctdsp.c | 1 - libavcodec/fdctdsp.h | 15 +++++++++++---- libavcodec/jfdctfst.c | 2 +- libavcodec/jfdctint_template.c | 2 +- libavcodec/mpegvideo_enc.c | 1 - libavcodec/ppc/fdctdsp.c | 1 + libavcodec/tests/dct.c | 1 + 9 files changed, 15 insertions(+), 16 deletions(-) diff --git a/libavcodec/asvenc.c b/libavcodec/asvenc.c index 4a14bcf8fa2..50da46738cf 100644 --- a/libavcodec/asvenc.c +++ b/libavcodec/asvenc.c @@ -33,7 +33,6 @@ #include "asv.h" #include "avcodec.h" #include "codec_internal.h" -#include "dct.h" #include "encode.h" #include "fdctdsp.h" #include "mpeg12data.h" diff --git a/libavcodec/dct.h b/libavcodec/dct.h index 0a03e256d13..75f40b9f84c 100644 --- a/libavcodec/dct.h +++ b/libavcodec/dct.h @@ -52,13 +52,6 @@ void ff_dct_end (DCTContext *s); void ff_dct_init_x86(DCTContext *s); -void ff_fdct_ifast(int16_t *data); -void ff_fdct_ifast248(int16_t *data); -void ff_jpeg_fdct_islow_8(int16_t *data); -void ff_jpeg_fdct_islow_10(int16_t *data); -void ff_fdct248_islow_8(int16_t *data); -void ff_fdct248_islow_10(int16_t *data); - void ff_j_rev_dct(int16_t *data); void ff_j_rev_dct4(int16_t *data); void ff_j_rev_dct2(int16_t *data); diff --git a/libavcodec/fdctdsp.c b/libavcodec/fdctdsp.c index 5306c9d047e..f8ba17426c1 100644 --- a/libavcodec/fdctdsp.c +++ b/libavcodec/fdctdsp.c @@ -18,7 +18,6 @@ #include "libavutil/attributes.h" #include "avcodec.h" -#include "dct.h" #include "faandct.h" #include "fdctdsp.h" #include "config.h" diff --git a/libavcodec/fdctdsp.h b/libavcodec/fdctdsp.h index 3e1f683b9ea..be65efa895a 100644 --- a/libavcodec/fdctdsp.h +++ b/libavcodec/fdctdsp.h @@ -21,17 +21,24 @@ #include -#include "avcodec.h" +struct AVCodecContext; typedef struct FDCTDSPContext { void (*fdct)(int16_t *block /* align 16 */); void (*fdct248)(int16_t *block /* align 16 */); } FDCTDSPContext; -void ff_fdctdsp_init(FDCTDSPContext *c, AVCodecContext *avctx); -void ff_fdctdsp_init_ppc(FDCTDSPContext *c, AVCodecContext *avctx, +void ff_fdctdsp_init(FDCTDSPContext *c, struct AVCodecContext *avctx); +void ff_fdctdsp_init_ppc(FDCTDSPContext *c, struct AVCodecContext *avctx, unsigned high_bit_depth); -void ff_fdctdsp_init_x86(FDCTDSPContext *c, AVCodecContext *avctx, +void ff_fdctdsp_init_x86(FDCTDSPContext *c, struct AVCodecContext *avctx, unsigned high_bit_depth); +void ff_fdct_ifast(int16_t *data); +void ff_fdct_ifast248(int16_t *data); +void ff_jpeg_fdct_islow_8(int16_t *data); +void ff_jpeg_fdct_islow_10(int16_t *data); +void ff_fdct248_islow_8(int16_t *data); +void ff_fdct248_islow_10(int16_t *data); + #endif /* AVCODEC_FDCTDSP_H */ diff --git a/libavcodec/jfdctfst.c b/libavcodec/jfdctfst.c index 805e05808c9..946b12f379e 100644 --- a/libavcodec/jfdctfst.c +++ b/libavcodec/jfdctfst.c @@ -68,7 +68,7 @@ #include #include "libavutil/attributes.h" -#include "dct.h" +#include "fdctdsp.h" #define DCTSIZE 8 #define GLOBAL(x) x diff --git a/libavcodec/jfdctint_template.c b/libavcodec/jfdctint_template.c index 67fb77b5e12..ca17300c324 100644 --- a/libavcodec/jfdctint_template.c +++ b/libavcodec/jfdctint_template.c @@ -60,7 +60,7 @@ */ #include "libavutil/common.h" -#include "dct.h" +#include "fdctdsp.h" #include "bit_depth_template.c" diff --git a/libavcodec/mpegvideo_enc.c b/libavcodec/mpegvideo_enc.c index 9bdf5dbe079..64e66ae958c 100644 --- a/libavcodec/mpegvideo_enc.c +++ b/libavcodec/mpegvideo_enc.c @@ -43,7 +43,6 @@ #include "libavutil/opt.h" #include "libavutil/thread.h" #include "avcodec.h" -#include "dct.h" #include "encode.h" #include "idctdsp.h" #include "mpeg12codecs.h" diff --git a/libavcodec/ppc/fdctdsp.c b/libavcodec/ppc/fdctdsp.c index 4ab516c6b35..ae3c1b18ff7 100644 --- a/libavcodec/ppc/fdctdsp.c +++ b/libavcodec/ppc/fdctdsp.c @@ -25,6 +25,7 @@ #include "libavutil/ppc/cpu.h" #include "libavutil/ppc/util_altivec.h" +#include "libavcodec/avcodec.h" #include "libavcodec/fdctdsp.h" #include "fdct.h" diff --git a/libavcodec/tests/dct.c b/libavcodec/tests/dct.c index c847af2f110..e8d0b8dd1db 100644 --- a/libavcodec/tests/dct.c +++ b/libavcodec/tests/dct.c @@ -43,6 +43,7 @@ #include "libavutil/time.h" #include "libavcodec/dct.h" +#include "libavcodec/fdctdsp.h" #include "libavcodec/idctdsp.h" #include "libavcodec/simple_idct.h" #include "libavcodec/xvididct.h" From 27b43643395543783f071731665924d570287ff1 Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt Date: Mon, 24 Jul 2023 15:02:42 +0200 Subject: [PATCH 2045/2172] avcodec/fdctdsp: Mark functions as hidden Pointers to these functions are used in comparisons. Currently the compiler has to presume the worst for these, namely that the functions are from another DSO and therefore loads their addresses from the GOT (which also entails a relocation entry that is processed at runtime, regardless of whether the code using them is run or not). This changes after these functions are declared as hidden. Signed-off-by: Andreas Rheinhardt --- libavcodec/fdctdsp.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/libavcodec/fdctdsp.h b/libavcodec/fdctdsp.h index be65efa895a..7378eab870c 100644 --- a/libavcodec/fdctdsp.h +++ b/libavcodec/fdctdsp.h @@ -21,6 +21,8 @@ #include +#include "libavutil/attributes_internal.h" + struct AVCodecContext; typedef struct FDCTDSPContext { @@ -28,6 +30,7 @@ typedef struct FDCTDSPContext { void (*fdct248)(int16_t *block /* align 16 */); } FDCTDSPContext; +FF_VISIBILITY_PUSH_HIDDEN void ff_fdctdsp_init(FDCTDSPContext *c, struct AVCodecContext *avctx); void ff_fdctdsp_init_ppc(FDCTDSPContext *c, struct AVCodecContext *avctx, unsigned high_bit_depth); @@ -40,5 +43,6 @@ void ff_jpeg_fdct_islow_8(int16_t *data); void ff_jpeg_fdct_islow_10(int16_t *data); void ff_fdct248_islow_8(int16_t *data); void ff_fdct248_islow_10(int16_t *data); +FF_VISIBILITY_POP_HIDDEN #endif /* AVCODEC_FDCTDSP_H */ From 6f6907fd202a08826ceefe0fe2bd6501a696ed15 Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Sat, 29 Jul 2023 00:52:53 +0200 Subject: [PATCH 2046/2172] avfilter/avf_showcwt: fix very low freqs leakage --- libavfilter/avf_showcwt.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/libavfilter/avf_showcwt.c b/libavfilter/avf_showcwt.c index 4aa008ca2ef..85cb19103b7 100644 --- a/libavfilter/avf_showcwt.c +++ b/libavfilter/avf_showcwt.c @@ -636,6 +636,7 @@ static int compute_kernel(AVFilterContext *ctx) const int fsize = s->frequency_band_count; int *kernel_start = s->kernel_start; int *kernel_stop = s->kernel_stop; + const int hsize = size >> 1; unsigned *index = s->index; int kernel_min = INT_MAX; int kernel_max = 0, ret = 0; @@ -656,6 +657,7 @@ static int compute_kernel(AVFilterContext *ctx) for (int n = 0; n < size; n++) { float ff, f = n-frequency; + f = hsize - fabsf(f - hsize); ff = expf(-f*f*deviation); tkernel[n] = ff; } From 44813d66e2c7106a36e8b4537d5b50e54d679fb4 Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Sat, 29 Jul 2023 11:21:28 +0200 Subject: [PATCH 2047/2172] avfilter/avf_showcwt: make kernels symmetrical --- libavfilter/avf_showcwt.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavfilter/avf_showcwt.c b/libavfilter/avf_showcwt.c index 85cb19103b7..96b88413801 100644 --- a/libavfilter/avf_showcwt.c +++ b/libavfilter/avf_showcwt.c @@ -655,7 +655,7 @@ static int compute_kernel(AVFilterContext *ctx) memset(tkernel, 0, size * sizeof(*tkernel)); for (int n = 0; n < size; n++) { - float ff, f = n-frequency; + float ff, f = n+0.5f-frequency; f = hsize - fabsf(f - hsize); ff = expf(-f*f*deviation); From 075dfc271bb78c9c179360d848f746ce76660876 Mon Sep 17 00:00:00 2001 From: James Almer Date: Sat, 29 Jul 2023 00:31:43 -0300 Subject: [PATCH 2048/2172] avfilter/qsvvpp: remove usage of deprecated fields Added by mistake in 88b3841149b9f41d6c5ec7930dcd5c6caf28b198. Reviewed-by: Xiang, Haihao Signed-off-by: James Almer --- libavfilter/qsvvpp.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/libavfilter/qsvvpp.c b/libavfilter/qsvvpp.c index a03de05d9ce..28337038915 100644 --- a/libavfilter/qsvvpp.c +++ b/libavfilter/qsvvpp.c @@ -540,14 +540,19 @@ static QSVFrame *query_frame(QSVVPPContext *s, AVFilterLink *outlink, const AVFr mfxExtBuffer *extbuf = s->vpp_param.ExtParam[i]; if (extbuf->BufferId == MFX_EXTBUFF_VPP_DEINTERLACING) { +#if FF_API_INTERLACED_FRAME +FF_DISABLE_DEPRECATION_WARNINGS out_frame->frame->interlaced_frame = 0; +FF_ENABLE_DEPRECATION_WARNINGS +#endif + out_frame->frame->flags &= ~AV_FRAME_FLAG_INTERLACED; break; } } out_frame->surface.Info.PicStruct = - !out_frame->frame->interlaced_frame ? MFX_PICSTRUCT_PROGRESSIVE : - (out_frame->frame->top_field_first ? MFX_PICSTRUCT_FIELD_TFF : + !(out_frame->frame->flags & AV_FRAME_FLAG_INTERLACED) ? MFX_PICSTRUCT_PROGRESSIVE : + ((out_frame->frame->flags & AV_FRAME_FLAG_TOP_FIELD_FIRST) ? MFX_PICSTRUCT_FIELD_TFF : MFX_PICSTRUCT_FIELD_BFF); return out_frame; From dcff15692dff4c55827d640f1d5d07eb255a5a6a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Reimar=20D=C3=B6ffinger?= Date: Wed, 26 Jul 2023 21:13:44 +0200 Subject: [PATCH 2049/2172] hevcdsp_idct_neon.S: Avoid unnecessary mov. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ret can be given an argument instead. This is also consistent with how other assembler code in FFmpeg does it. Signed-off-by: Reimar Döffinger --- libavcodec/aarch64/hevcdsp_idct_neon.S | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/libavcodec/aarch64/hevcdsp_idct_neon.S b/libavcodec/aarch64/hevcdsp_idct_neon.S index b7f23386a47..f7142c939c7 100644 --- a/libavcodec/aarch64/hevcdsp_idct_neon.S +++ b/libavcodec/aarch64/hevcdsp_idct_neon.S @@ -617,8 +617,7 @@ function ff_hevc_idct_16x16_\bitdepth\()_neon, export=1 add sp, sp, #640 - mov x30, x15 - ret + ret x15 endfunc .endm @@ -814,8 +813,7 @@ function ff_hevc_idct_32x32_\bitdepth\()_neon, export=1 .endr add sp, sp, #2432 - mov x30, x15 - ret + ret x15 endfunc .endm From c0f867bf503e79eba8ee52e1ac53322f88ec2929 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Reimar=20D=C3=B6ffinger?= Date: Wed, 21 Jun 2023 20:06:09 +0200 Subject: [PATCH 2050/2172] libavformat: fix incorrect handling of incomplete AVBPrint. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Change some internal APIs a bit to make it harder to make such mistakes. In particular, have the read chunk functions return an error when the result is incomplete. This might be less flexible, but since there has been no use-case for that so far, avoiding coding mistakes seems better. Add a function to queue a AVBPrint directly (ff_subtitles_queue_insert_bprint). Also fixes a leak in lrcdec when ff_subtitles_queue_insert fails. Signed-off-by: Reimar Döffinger --- libavformat/assdec.c | 4 +++- libavformat/lrcdec.c | 7 ++++++- libavformat/mpsubdec.c | 5 +++-- libavformat/realtextdec.c | 6 +++++- libavformat/samidec.c | 6 +++++- libavformat/srtdec.c | 4 +++- libavformat/subtitles.c | 19 +++++++++++++++---- libavformat/subtitles.h | 14 ++++++++++++-- libavformat/tedcaptionsdec.c | 2 +- libavformat/webvttdec.c | 4 +++- 10 files changed, 56 insertions(+), 15 deletions(-) diff --git a/libavformat/assdec.c b/libavformat/assdec.c index 0915f6fafd7..bf7b8a73a24 100644 --- a/libavformat/assdec.c +++ b/libavformat/assdec.c @@ -73,6 +73,8 @@ static int read_dialogue(ASSContext *ass, AVBPrint *dst, const uint8_t *p, av_bprint_clear(dst); av_bprintf(dst, "%u,%d,%s", ass->readorder++, layer, p + pos); + if (!av_bprint_is_complete(dst)) + return AVERROR(ENOMEM); /* right strip the buffer */ while (dst->len > 0 && @@ -135,7 +137,7 @@ static int ass_read_header(AVFormatContext *s) av_bprintf(&header, "%s", line.str); continue; } - sub = ff_subtitles_queue_insert(&ass->q, rline.str, rline.len, 0); + sub = ff_subtitles_queue_insert_bprint(&ass->q, &rline, 0); if (!sub) { res = AVERROR(ENOMEM); goto end; diff --git a/libavformat/lrcdec.c b/libavformat/lrcdec.c index fff39495f87..83bb4a4b75e 100644 --- a/libavformat/lrcdec.c +++ b/libavformat/lrcdec.c @@ -171,6 +171,8 @@ static int lrc_read_header(AVFormatContext *s) while(!avio_feof(s->pb)) { int64_t pos = read_line(&line, s->pb); + if (!av_bprint_is_complete(&line)) + goto err_nomem_out; int64_t header_offset = find_header(line.str); if(header_offset >= 0) { char *comma_offset = strchr(line.str, ':'); @@ -205,7 +207,7 @@ static int lrc_read_header(AVFormatContext *s) sub = ff_subtitles_queue_insert(&lrc->q, line.str + ts_strlength, line.len - ts_strlength, 0); if (!sub) - return AVERROR(ENOMEM); + goto err_nomem_out; sub->pos = pos; sub->pts = ts_start - lrc->ts_offset; sub->duration = -1; @@ -216,6 +218,9 @@ static int lrc_read_header(AVFormatContext *s) ff_metadata_conv_ctx(s, NULL, ff_lrc_metadata_conv); av_bprint_finalize(&line, NULL); return 0; +err_nomem_out: + av_bprint_finalize(&line, NULL); + return AVERROR(ENOMEM); } const AVInputFormat ff_lrc_demuxer = { diff --git a/libavformat/mpsubdec.c b/libavformat/mpsubdec.c index d290a41fb9c..03745635753 100644 --- a/libavformat/mpsubdec.c +++ b/libavformat/mpsubdec.c @@ -116,9 +116,10 @@ static int mpsub_read_header(AVFormatContext *s) AVPacket *sub; const int64_t pos = avio_tell(s->pb); - ff_subtitles_read_chunk(s->pb, &buf); + res = ff_subtitles_read_chunk(s->pb, &buf); + if (res < 0) goto end; if (buf.len) { - sub = ff_subtitles_queue_insert(&mpsub->q, buf.str, buf.len, 0); + sub = ff_subtitles_queue_insert_bprint(&mpsub->q, &buf, 0); if (!sub) { res = AVERROR(ENOMEM); goto end; diff --git a/libavformat/realtextdec.c b/libavformat/realtextdec.c index c281dec346d..7992a5b7fcd 100644 --- a/libavformat/realtextdec.c +++ b/libavformat/realtextdec.c @@ -80,6 +80,10 @@ static int realtext_read_header(AVFormatContext *s) const int64_t pos = ff_text_pos(&tr) - (c != 0); int n = ff_smil_extract_next_text_chunk(&tr, &buf, &c); + if (n < 0) { + res = n; + goto end; + } if (n == 0) break; @@ -103,7 +107,7 @@ static int realtext_read_header(AVFormatContext *s) /* if we just read a